[media] rename most media/video usb drivers to media/usb
authorMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 14 Aug 2012 03:13:22 +0000 (00:13 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 15 Aug 2012 19:25:07 +0000 (16:25 -0300)
Rename all USB drivers with their own directory under
drivers/media/video into drivers/media/usb and update the
building system.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
571 files changed:
MAINTAINERS
drivers/media/usb/Kconfig
drivers/media/usb/Makefile
drivers/media/usb/au0828/Kconfig [new file with mode: 0644]
drivers/media/usb/au0828/Makefile [new file with mode: 0644]
drivers/media/usb/au0828/au0828-cards.c [new file with mode: 0644]
drivers/media/usb/au0828/au0828-cards.h [new file with mode: 0644]
drivers/media/usb/au0828/au0828-core.c [new file with mode: 0644]
drivers/media/usb/au0828/au0828-dvb.c [new file with mode: 0644]
drivers/media/usb/au0828/au0828-i2c.c [new file with mode: 0644]
drivers/media/usb/au0828/au0828-reg.h [new file with mode: 0644]
drivers/media/usb/au0828/au0828-vbi.c [new file with mode: 0644]
drivers/media/usb/au0828/au0828-video.c [new file with mode: 0644]
drivers/media/usb/au0828/au0828.h [new file with mode: 0644]
drivers/media/usb/cpia2/Kconfig [new file with mode: 0644]
drivers/media/usb/cpia2/Makefile [new file with mode: 0644]
drivers/media/usb/cpia2/cpia2.h [new file with mode: 0644]
drivers/media/usb/cpia2/cpia2_core.c [new file with mode: 0644]
drivers/media/usb/cpia2/cpia2_registers.h [new file with mode: 0644]
drivers/media/usb/cpia2/cpia2_usb.c [new file with mode: 0644]
drivers/media/usb/cpia2/cpia2_v4l.c [new file with mode: 0644]
drivers/media/usb/cx231xx/Kconfig [new file with mode: 0644]
drivers/media/usb/cx231xx/Makefile [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-417.c [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-audio.c [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-avcore.c [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-cards.c [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-conf-reg.h [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-core.c [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-dif.h [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-dvb.c [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-i2c.c [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-input.c [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-reg.h [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-vbi.c [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-vbi.h [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx-video.c [new file with mode: 0644]
drivers/media/usb/cx231xx/cx231xx.h [new file with mode: 0644]
drivers/media/usb/em28xx/Kconfig [new file with mode: 0644]
drivers/media/usb/em28xx/Makefile [new file with mode: 0644]
drivers/media/usb/em28xx/em28xx-audio.c [new file with mode: 0644]
drivers/media/usb/em28xx/em28xx-cards.c [new file with mode: 0644]
drivers/media/usb/em28xx/em28xx-core.c [new file with mode: 0644]
drivers/media/usb/em28xx/em28xx-dvb.c [new file with mode: 0644]
drivers/media/usb/em28xx/em28xx-i2c.c [new file with mode: 0644]
drivers/media/usb/em28xx/em28xx-input.c [new file with mode: 0644]
drivers/media/usb/em28xx/em28xx-reg.h [new file with mode: 0644]
drivers/media/usb/em28xx/em28xx-vbi.c [new file with mode: 0644]
drivers/media/usb/em28xx/em28xx-video.c [new file with mode: 0644]
drivers/media/usb/em28xx/em28xx.h [new file with mode: 0644]
drivers/media/usb/gspca/Kconfig [new file with mode: 0644]
drivers/media/usb/gspca/Makefile [new file with mode: 0644]
drivers/media/usb/gspca/autogain_functions.c [new file with mode: 0644]
drivers/media/usb/gspca/autogain_functions.h [new file with mode: 0644]
drivers/media/usb/gspca/benq.c [new file with mode: 0644]
drivers/media/usb/gspca/conex.c [new file with mode: 0644]
drivers/media/usb/gspca/cpia1.c [new file with mode: 0644]
drivers/media/usb/gspca/etoms.c [new file with mode: 0644]
drivers/media/usb/gspca/finepix.c [new file with mode: 0644]
drivers/media/usb/gspca/gl860/Kconfig [new file with mode: 0644]
drivers/media/usb/gspca/gl860/Makefile [new file with mode: 0644]
drivers/media/usb/gspca/gl860/gl860-mi1320.c [new file with mode: 0644]
drivers/media/usb/gspca/gl860/gl860-mi2020.c [new file with mode: 0644]
drivers/media/usb/gspca/gl860/gl860-ov2640.c [new file with mode: 0644]
drivers/media/usb/gspca/gl860/gl860-ov9655.c [new file with mode: 0644]
drivers/media/usb/gspca/gl860/gl860.c [new file with mode: 0644]
drivers/media/usb/gspca/gl860/gl860.h [new file with mode: 0644]
drivers/media/usb/gspca/gspca.c [new file with mode: 0644]
drivers/media/usb/gspca/gspca.h [new file with mode: 0644]
drivers/media/usb/gspca/jeilinj.c [new file with mode: 0644]
drivers/media/usb/gspca/jl2005bcd.c [new file with mode: 0644]
drivers/media/usb/gspca/jpeg.h [new file with mode: 0644]
drivers/media/usb/gspca/kinect.c [new file with mode: 0644]
drivers/media/usb/gspca/konica.c [new file with mode: 0644]
drivers/media/usb/gspca/m5602/Kconfig [new file with mode: 0644]
drivers/media/usb/gspca/m5602/Makefile [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_bridge.h [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_core.c [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_mt9m111.c [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_mt9m111.h [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_ov7660.c [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_ov7660.h [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_ov9650.c [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_ov9650.h [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_po1030.c [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_po1030.h [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_s5k4aa.c [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_s5k4aa.h [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_s5k83a.c [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_s5k83a.h [new file with mode: 0644]
drivers/media/usb/gspca/m5602/m5602_sensor.h [new file with mode: 0644]
drivers/media/usb/gspca/mars.c [new file with mode: 0644]
drivers/media/usb/gspca/mr97310a.c [new file with mode: 0644]
drivers/media/usb/gspca/nw80x.c [new file with mode: 0644]
drivers/media/usb/gspca/ov519.c [new file with mode: 0644]
drivers/media/usb/gspca/ov534.c [new file with mode: 0644]
drivers/media/usb/gspca/ov534_9.c [new file with mode: 0644]
drivers/media/usb/gspca/pac207.c [new file with mode: 0644]
drivers/media/usb/gspca/pac7302.c [new file with mode: 0644]
drivers/media/usb/gspca/pac7311.c [new file with mode: 0644]
drivers/media/usb/gspca/pac_common.h [new file with mode: 0644]
drivers/media/usb/gspca/se401.c [new file with mode: 0644]
drivers/media/usb/gspca/se401.h [new file with mode: 0644]
drivers/media/usb/gspca/sn9c2028.c [new file with mode: 0644]
drivers/media/usb/gspca/sn9c2028.h [new file with mode: 0644]
drivers/media/usb/gspca/sn9c20x.c [new file with mode: 0644]
drivers/media/usb/gspca/sonixb.c [new file with mode: 0644]
drivers/media/usb/gspca/sonixj.c [new file with mode: 0644]
drivers/media/usb/gspca/spca1528.c [new file with mode: 0644]
drivers/media/usb/gspca/spca500.c [new file with mode: 0644]
drivers/media/usb/gspca/spca501.c [new file with mode: 0644]
drivers/media/usb/gspca/spca505.c [new file with mode: 0644]
drivers/media/usb/gspca/spca506.c [new file with mode: 0644]
drivers/media/usb/gspca/spca508.c [new file with mode: 0644]
drivers/media/usb/gspca/spca561.c [new file with mode: 0644]
drivers/media/usb/gspca/sq905.c [new file with mode: 0644]
drivers/media/usb/gspca/sq905c.c [new file with mode: 0644]
drivers/media/usb/gspca/sq930x.c [new file with mode: 0644]
drivers/media/usb/gspca/stk014.c [new file with mode: 0644]
drivers/media/usb/gspca/stv0680.c [new file with mode: 0644]
drivers/media/usb/gspca/stv06xx/Kconfig [new file with mode: 0644]
drivers/media/usb/gspca/stv06xx/Makefile [new file with mode: 0644]
drivers/media/usb/gspca/stv06xx/stv06xx.c [new file with mode: 0644]
drivers/media/usb/gspca/stv06xx/stv06xx.h [new file with mode: 0644]
drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c [new file with mode: 0644]
drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.h [new file with mode: 0644]
drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c [new file with mode: 0644]
drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.h [new file with mode: 0644]
drivers/media/usb/gspca/stv06xx/stv06xx_sensor.h [new file with mode: 0644]
drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c [new file with mode: 0644]
drivers/media/usb/gspca/stv06xx/stv06xx_st6422.h [new file with mode: 0644]
drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c [new file with mode: 0644]
drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.h [new file with mode: 0644]
drivers/media/usb/gspca/sunplus.c [new file with mode: 0644]
drivers/media/usb/gspca/t613.c [new file with mode: 0644]
drivers/media/usb/gspca/topro.c [new file with mode: 0644]
drivers/media/usb/gspca/tv8532.c [new file with mode: 0644]
drivers/media/usb/gspca/vc032x.c [new file with mode: 0644]
drivers/media/usb/gspca/vicam.c [new file with mode: 0644]
drivers/media/usb/gspca/w996Xcf.c [new file with mode: 0644]
drivers/media/usb/gspca/xirlink_cit.c [new file with mode: 0644]
drivers/media/usb/gspca/zc3xx-reg.h [new file with mode: 0644]
drivers/media/usb/gspca/zc3xx.c [new file with mode: 0644]
drivers/media/usb/hdpvr/Kconfig [new file with mode: 0644]
drivers/media/usb/hdpvr/Makefile [new file with mode: 0644]
drivers/media/usb/hdpvr/hdpvr-control.c [new file with mode: 0644]
drivers/media/usb/hdpvr/hdpvr-core.c [new file with mode: 0644]
drivers/media/usb/hdpvr/hdpvr-i2c.c [new file with mode: 0644]
drivers/media/usb/hdpvr/hdpvr-video.c [new file with mode: 0644]
drivers/media/usb/hdpvr/hdpvr.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/Kconfig [new file with mode: 0644]
drivers/media/usb/pvrusb2/Makefile [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-audio.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-audio.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-context.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-context.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-ctrl.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-ctrl.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-debug.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-debugifc.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-debugifc.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-devattr.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-devattr.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-dvb.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-dvb.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-eeprom.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-eeprom.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-encoder.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-encoder.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-hdw.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-hdw.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-io.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-io.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-ioread.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-ioread.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-main.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-std.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-std.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-sysfs.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-sysfs.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-util.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-v4l2.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-v4l2.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-wm8775.c [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2-wm8775.h [new file with mode: 0644]
drivers/media/usb/pvrusb2/pvrusb2.h [new file with mode: 0644]
drivers/media/usb/pwc/Kconfig [new file with mode: 0644]
drivers/media/usb/pwc/Makefile [new file with mode: 0644]
drivers/media/usb/pwc/philips.txt [new file with mode: 0644]
drivers/media/usb/pwc/pwc-ctrl.c [new file with mode: 0644]
drivers/media/usb/pwc/pwc-dec1.c [new file with mode: 0644]
drivers/media/usb/pwc/pwc-dec1.h [new file with mode: 0644]
drivers/media/usb/pwc/pwc-dec23.c [new file with mode: 0644]
drivers/media/usb/pwc/pwc-dec23.h [new file with mode: 0644]
drivers/media/usb/pwc/pwc-if.c [new file with mode: 0644]
drivers/media/usb/pwc/pwc-kiara.c [new file with mode: 0644]
drivers/media/usb/pwc/pwc-kiara.h [new file with mode: 0644]
drivers/media/usb/pwc/pwc-misc.c [new file with mode: 0644]
drivers/media/usb/pwc/pwc-nala.h [new file with mode: 0644]
drivers/media/usb/pwc/pwc-timon.c [new file with mode: 0644]
drivers/media/usb/pwc/pwc-timon.h [new file with mode: 0644]
drivers/media/usb/pwc/pwc-uncompress.c [new file with mode: 0644]
drivers/media/usb/pwc/pwc-v4l.c [new file with mode: 0644]
drivers/media/usb/pwc/pwc.h [new file with mode: 0644]
drivers/media/usb/sn9c102/Kconfig [new file with mode: 0644]
drivers/media/usb/sn9c102/Makefile [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102.h [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_config.h [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_core.c [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_devtable.h [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_hv7131d.c [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_hv7131r.c [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_mi0343.c [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_mi0360.c [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_mt9v111.c [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_ov7630.c [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_ov7660.c [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_pas106b.c [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_pas202bcb.c [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_sensor.h [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_tas5110c1b.c [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_tas5110d.c [new file with mode: 0644]
drivers/media/usb/sn9c102/sn9c102_tas5130d1b.c [new file with mode: 0644]
drivers/media/usb/stk1160/Kconfig [new file with mode: 0644]
drivers/media/usb/stk1160/Makefile [new file with mode: 0644]
drivers/media/usb/stk1160/stk1160-ac97.c [new file with mode: 0644]
drivers/media/usb/stk1160/stk1160-core.c [new file with mode: 0644]
drivers/media/usb/stk1160/stk1160-i2c.c [new file with mode: 0644]
drivers/media/usb/stk1160/stk1160-reg.h [new file with mode: 0644]
drivers/media/usb/stk1160/stk1160-v4l.c [new file with mode: 0644]
drivers/media/usb/stk1160/stk1160-video.c [new file with mode: 0644]
drivers/media/usb/stk1160/stk1160.h [new file with mode: 0644]
drivers/media/usb/tlg2300/Kconfig [new file with mode: 0644]
drivers/media/usb/tlg2300/Makefile [new file with mode: 0644]
drivers/media/usb/tlg2300/pd-alsa.c [new file with mode: 0644]
drivers/media/usb/tlg2300/pd-common.h [new file with mode: 0644]
drivers/media/usb/tlg2300/pd-dvb.c [new file with mode: 0644]
drivers/media/usb/tlg2300/pd-main.c [new file with mode: 0644]
drivers/media/usb/tlg2300/pd-radio.c [new file with mode: 0644]
drivers/media/usb/tlg2300/pd-video.c [new file with mode: 0644]
drivers/media/usb/tlg2300/vendorcmds.h [new file with mode: 0644]
drivers/media/usb/tm6000/Kconfig [new file with mode: 0644]
drivers/media/usb/tm6000/Makefile [new file with mode: 0644]
drivers/media/usb/tm6000/tm6000-alsa.c [new file with mode: 0644]
drivers/media/usb/tm6000/tm6000-cards.c [new file with mode: 0644]
drivers/media/usb/tm6000/tm6000-core.c [new file with mode: 0644]
drivers/media/usb/tm6000/tm6000-dvb.c [new file with mode: 0644]
drivers/media/usb/tm6000/tm6000-i2c.c [new file with mode: 0644]
drivers/media/usb/tm6000/tm6000-input.c [new file with mode: 0644]
drivers/media/usb/tm6000/tm6000-regs.h [new file with mode: 0644]
drivers/media/usb/tm6000/tm6000-stds.c [new file with mode: 0644]
drivers/media/usb/tm6000/tm6000-usb-isoc.h [new file with mode: 0644]
drivers/media/usb/tm6000/tm6000-video.c [new file with mode: 0644]
drivers/media/usb/tm6000/tm6000.h [new file with mode: 0644]
drivers/media/usb/usbvision/Kconfig [new file with mode: 0644]
drivers/media/usb/usbvision/Makefile [new file with mode: 0644]
drivers/media/usb/usbvision/usbvision-cards.c [new file with mode: 0644]
drivers/media/usb/usbvision/usbvision-cards.h [new file with mode: 0644]
drivers/media/usb/usbvision/usbvision-core.c [new file with mode: 0644]
drivers/media/usb/usbvision/usbvision-i2c.c [new file with mode: 0644]
drivers/media/usb/usbvision/usbvision-video.c [new file with mode: 0644]
drivers/media/usb/usbvision/usbvision.h [new file with mode: 0644]
drivers/media/usb/uvc/Kconfig [new file with mode: 0644]
drivers/media/usb/uvc/Makefile [new file with mode: 0644]
drivers/media/usb/uvc/uvc_ctrl.c [new file with mode: 0644]
drivers/media/usb/uvc/uvc_debugfs.c [new file with mode: 0644]
drivers/media/usb/uvc/uvc_driver.c [new file with mode: 0644]
drivers/media/usb/uvc/uvc_entity.c [new file with mode: 0644]
drivers/media/usb/uvc/uvc_isight.c [new file with mode: 0644]
drivers/media/usb/uvc/uvc_queue.c [new file with mode: 0644]
drivers/media/usb/uvc/uvc_status.c [new file with mode: 0644]
drivers/media/usb/uvc/uvc_v4l2.c [new file with mode: 0644]
drivers/media/usb/uvc/uvc_video.c [new file with mode: 0644]
drivers/media/usb/uvc/uvcvideo.h [new file with mode: 0644]
drivers/media/video/Kconfig
drivers/media/video/Makefile
drivers/media/video/au0828/Kconfig [deleted file]
drivers/media/video/au0828/Makefile [deleted file]
drivers/media/video/au0828/au0828-cards.c [deleted file]
drivers/media/video/au0828/au0828-cards.h [deleted file]
drivers/media/video/au0828/au0828-core.c [deleted file]
drivers/media/video/au0828/au0828-dvb.c [deleted file]
drivers/media/video/au0828/au0828-i2c.c [deleted file]
drivers/media/video/au0828/au0828-reg.h [deleted file]
drivers/media/video/au0828/au0828-vbi.c [deleted file]
drivers/media/video/au0828/au0828-video.c [deleted file]
drivers/media/video/au0828/au0828.h [deleted file]
drivers/media/video/cpia2/Kconfig [deleted file]
drivers/media/video/cpia2/Makefile [deleted file]
drivers/media/video/cpia2/cpia2.h [deleted file]
drivers/media/video/cpia2/cpia2_core.c [deleted file]
drivers/media/video/cpia2/cpia2_registers.h [deleted file]
drivers/media/video/cpia2/cpia2_usb.c [deleted file]
drivers/media/video/cpia2/cpia2_v4l.c [deleted file]
drivers/media/video/cx231xx/Kconfig [deleted file]
drivers/media/video/cx231xx/Makefile [deleted file]
drivers/media/video/cx231xx/cx231xx-417.c [deleted file]
drivers/media/video/cx231xx/cx231xx-audio.c [deleted file]
drivers/media/video/cx231xx/cx231xx-avcore.c [deleted file]
drivers/media/video/cx231xx/cx231xx-cards.c [deleted file]
drivers/media/video/cx231xx/cx231xx-conf-reg.h [deleted file]
drivers/media/video/cx231xx/cx231xx-core.c [deleted file]
drivers/media/video/cx231xx/cx231xx-dif.h [deleted file]
drivers/media/video/cx231xx/cx231xx-dvb.c [deleted file]
drivers/media/video/cx231xx/cx231xx-i2c.c [deleted file]
drivers/media/video/cx231xx/cx231xx-input.c [deleted file]
drivers/media/video/cx231xx/cx231xx-pcb-cfg.c [deleted file]
drivers/media/video/cx231xx/cx231xx-pcb-cfg.h [deleted file]
drivers/media/video/cx231xx/cx231xx-reg.h [deleted file]
drivers/media/video/cx231xx/cx231xx-vbi.c [deleted file]
drivers/media/video/cx231xx/cx231xx-vbi.h [deleted file]
drivers/media/video/cx231xx/cx231xx-video.c [deleted file]
drivers/media/video/cx231xx/cx231xx.h [deleted file]
drivers/media/video/em28xx/Kconfig [deleted file]
drivers/media/video/em28xx/Makefile [deleted file]
drivers/media/video/em28xx/em28xx-audio.c [deleted file]
drivers/media/video/em28xx/em28xx-cards.c [deleted file]
drivers/media/video/em28xx/em28xx-core.c [deleted file]
drivers/media/video/em28xx/em28xx-dvb.c [deleted file]
drivers/media/video/em28xx/em28xx-i2c.c [deleted file]
drivers/media/video/em28xx/em28xx-input.c [deleted file]
drivers/media/video/em28xx/em28xx-reg.h [deleted file]
drivers/media/video/em28xx/em28xx-vbi.c [deleted file]
drivers/media/video/em28xx/em28xx-video.c [deleted file]
drivers/media/video/em28xx/em28xx.h [deleted file]
drivers/media/video/gspca/Kconfig [deleted file]
drivers/media/video/gspca/Makefile [deleted file]
drivers/media/video/gspca/autogain_functions.c [deleted file]
drivers/media/video/gspca/autogain_functions.h [deleted file]
drivers/media/video/gspca/benq.c [deleted file]
drivers/media/video/gspca/conex.c [deleted file]
drivers/media/video/gspca/cpia1.c [deleted file]
drivers/media/video/gspca/etoms.c [deleted file]
drivers/media/video/gspca/finepix.c [deleted file]
drivers/media/video/gspca/gl860/Kconfig [deleted file]
drivers/media/video/gspca/gl860/Makefile [deleted file]
drivers/media/video/gspca/gl860/gl860-mi1320.c [deleted file]
drivers/media/video/gspca/gl860/gl860-mi2020.c [deleted file]
drivers/media/video/gspca/gl860/gl860-ov2640.c [deleted file]
drivers/media/video/gspca/gl860/gl860-ov9655.c [deleted file]
drivers/media/video/gspca/gl860/gl860.c [deleted file]
drivers/media/video/gspca/gl860/gl860.h [deleted file]
drivers/media/video/gspca/gspca.c [deleted file]
drivers/media/video/gspca/gspca.h [deleted file]
drivers/media/video/gspca/jeilinj.c [deleted file]
drivers/media/video/gspca/jl2005bcd.c [deleted file]
drivers/media/video/gspca/jpeg.h [deleted file]
drivers/media/video/gspca/kinect.c [deleted file]
drivers/media/video/gspca/konica.c [deleted file]
drivers/media/video/gspca/m5602/Kconfig [deleted file]
drivers/media/video/gspca/m5602/Makefile [deleted file]
drivers/media/video/gspca/m5602/m5602_bridge.h [deleted file]
drivers/media/video/gspca/m5602/m5602_core.c [deleted file]
drivers/media/video/gspca/m5602/m5602_mt9m111.c [deleted file]
drivers/media/video/gspca/m5602/m5602_mt9m111.h [deleted file]
drivers/media/video/gspca/m5602/m5602_ov7660.c [deleted file]
drivers/media/video/gspca/m5602/m5602_ov7660.h [deleted file]
drivers/media/video/gspca/m5602/m5602_ov9650.c [deleted file]
drivers/media/video/gspca/m5602/m5602_ov9650.h [deleted file]
drivers/media/video/gspca/m5602/m5602_po1030.c [deleted file]
drivers/media/video/gspca/m5602/m5602_po1030.h [deleted file]
drivers/media/video/gspca/m5602/m5602_s5k4aa.c [deleted file]
drivers/media/video/gspca/m5602/m5602_s5k4aa.h [deleted file]
drivers/media/video/gspca/m5602/m5602_s5k83a.c [deleted file]
drivers/media/video/gspca/m5602/m5602_s5k83a.h [deleted file]
drivers/media/video/gspca/m5602/m5602_sensor.h [deleted file]
drivers/media/video/gspca/mars.c [deleted file]
drivers/media/video/gspca/mr97310a.c [deleted file]
drivers/media/video/gspca/nw80x.c [deleted file]
drivers/media/video/gspca/ov519.c [deleted file]
drivers/media/video/gspca/ov534.c [deleted file]
drivers/media/video/gspca/ov534_9.c [deleted file]
drivers/media/video/gspca/pac207.c [deleted file]
drivers/media/video/gspca/pac7302.c [deleted file]
drivers/media/video/gspca/pac7311.c [deleted file]
drivers/media/video/gspca/pac_common.h [deleted file]
drivers/media/video/gspca/se401.c [deleted file]
drivers/media/video/gspca/se401.h [deleted file]
drivers/media/video/gspca/sn9c2028.c [deleted file]
drivers/media/video/gspca/sn9c2028.h [deleted file]
drivers/media/video/gspca/sn9c20x.c [deleted file]
drivers/media/video/gspca/sonixb.c [deleted file]
drivers/media/video/gspca/sonixj.c [deleted file]
drivers/media/video/gspca/spca1528.c [deleted file]
drivers/media/video/gspca/spca500.c [deleted file]
drivers/media/video/gspca/spca501.c [deleted file]
drivers/media/video/gspca/spca505.c [deleted file]
drivers/media/video/gspca/spca506.c [deleted file]
drivers/media/video/gspca/spca508.c [deleted file]
drivers/media/video/gspca/spca561.c [deleted file]
drivers/media/video/gspca/sq905.c [deleted file]
drivers/media/video/gspca/sq905c.c [deleted file]
drivers/media/video/gspca/sq930x.c [deleted file]
drivers/media/video/gspca/stk014.c [deleted file]
drivers/media/video/gspca/stv0680.c [deleted file]
drivers/media/video/gspca/stv06xx/Kconfig [deleted file]
drivers/media/video/gspca/stv06xx/Makefile [deleted file]
drivers/media/video/gspca/stv06xx/stv06xx.c [deleted file]
drivers/media/video/gspca/stv06xx/stv06xx.h [deleted file]
drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c [deleted file]
drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h [deleted file]
drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c [deleted file]
drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h [deleted file]
drivers/media/video/gspca/stv06xx/stv06xx_sensor.h [deleted file]
drivers/media/video/gspca/stv06xx/stv06xx_st6422.c [deleted file]
drivers/media/video/gspca/stv06xx/stv06xx_st6422.h [deleted file]
drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c [deleted file]
drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h [deleted file]
drivers/media/video/gspca/sunplus.c [deleted file]
drivers/media/video/gspca/t613.c [deleted file]
drivers/media/video/gspca/topro.c [deleted file]
drivers/media/video/gspca/tv8532.c [deleted file]
drivers/media/video/gspca/vc032x.c [deleted file]
drivers/media/video/gspca/vicam.c [deleted file]
drivers/media/video/gspca/w996Xcf.c [deleted file]
drivers/media/video/gspca/xirlink_cit.c [deleted file]
drivers/media/video/gspca/zc3xx-reg.h [deleted file]
drivers/media/video/gspca/zc3xx.c [deleted file]
drivers/media/video/hdpvr/Kconfig [deleted file]
drivers/media/video/hdpvr/Makefile [deleted file]
drivers/media/video/hdpvr/hdpvr-control.c [deleted file]
drivers/media/video/hdpvr/hdpvr-core.c [deleted file]
drivers/media/video/hdpvr/hdpvr-i2c.c [deleted file]
drivers/media/video/hdpvr/hdpvr-video.c [deleted file]
drivers/media/video/hdpvr/hdpvr.h [deleted file]
drivers/media/video/pvrusb2/Kconfig [deleted file]
drivers/media/video/pvrusb2/Makefile [deleted file]
drivers/media/video/pvrusb2/pvrusb2-audio.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-audio.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-context.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-context.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-ctrl.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-ctrl.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-debug.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-debugifc.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-debugifc.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-devattr.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-devattr.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-dvb.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-dvb.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-eeprom.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-eeprom.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-encoder.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-encoder.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-hdw.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-hdw.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-i2c-core.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-i2c-core.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-io.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-io.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-ioread.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-ioread.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-main.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-std.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-std.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-sysfs.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-sysfs.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-util.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-v4l2.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-v4l2.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-video-v4l.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-video-v4l.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2-wm8775.c [deleted file]
drivers/media/video/pvrusb2/pvrusb2-wm8775.h [deleted file]
drivers/media/video/pvrusb2/pvrusb2.h [deleted file]
drivers/media/video/pwc/Kconfig [deleted file]
drivers/media/video/pwc/Makefile [deleted file]
drivers/media/video/pwc/philips.txt [deleted file]
drivers/media/video/pwc/pwc-ctrl.c [deleted file]
drivers/media/video/pwc/pwc-dec1.c [deleted file]
drivers/media/video/pwc/pwc-dec1.h [deleted file]
drivers/media/video/pwc/pwc-dec23.c [deleted file]
drivers/media/video/pwc/pwc-dec23.h [deleted file]
drivers/media/video/pwc/pwc-if.c [deleted file]
drivers/media/video/pwc/pwc-kiara.c [deleted file]
drivers/media/video/pwc/pwc-kiara.h [deleted file]
drivers/media/video/pwc/pwc-misc.c [deleted file]
drivers/media/video/pwc/pwc-nala.h [deleted file]
drivers/media/video/pwc/pwc-timon.c [deleted file]
drivers/media/video/pwc/pwc-timon.h [deleted file]
drivers/media/video/pwc/pwc-uncompress.c [deleted file]
drivers/media/video/pwc/pwc-v4l.c [deleted file]
drivers/media/video/pwc/pwc.h [deleted file]
drivers/media/video/sn9c102/Kconfig [deleted file]
drivers/media/video/sn9c102/Makefile [deleted file]
drivers/media/video/sn9c102/sn9c102.h [deleted file]
drivers/media/video/sn9c102/sn9c102_config.h [deleted file]
drivers/media/video/sn9c102/sn9c102_core.c [deleted file]
drivers/media/video/sn9c102/sn9c102_devtable.h [deleted file]
drivers/media/video/sn9c102/sn9c102_hv7131d.c [deleted file]
drivers/media/video/sn9c102/sn9c102_hv7131r.c [deleted file]
drivers/media/video/sn9c102/sn9c102_mi0343.c [deleted file]
drivers/media/video/sn9c102/sn9c102_mi0360.c [deleted file]
drivers/media/video/sn9c102/sn9c102_mt9v111.c [deleted file]
drivers/media/video/sn9c102/sn9c102_ov7630.c [deleted file]
drivers/media/video/sn9c102/sn9c102_ov7660.c [deleted file]
drivers/media/video/sn9c102/sn9c102_pas106b.c [deleted file]
drivers/media/video/sn9c102/sn9c102_pas202bcb.c [deleted file]
drivers/media/video/sn9c102/sn9c102_sensor.h [deleted file]
drivers/media/video/sn9c102/sn9c102_tas5110c1b.c [deleted file]
drivers/media/video/sn9c102/sn9c102_tas5110d.c [deleted file]
drivers/media/video/sn9c102/sn9c102_tas5130d1b.c [deleted file]
drivers/media/video/stk1160/Kconfig [deleted file]
drivers/media/video/stk1160/Makefile [deleted file]
drivers/media/video/stk1160/stk1160-ac97.c [deleted file]
drivers/media/video/stk1160/stk1160-core.c [deleted file]
drivers/media/video/stk1160/stk1160-i2c.c [deleted file]
drivers/media/video/stk1160/stk1160-reg.h [deleted file]
drivers/media/video/stk1160/stk1160-v4l.c [deleted file]
drivers/media/video/stk1160/stk1160-video.c [deleted file]
drivers/media/video/stk1160/stk1160.h [deleted file]
drivers/media/video/tlg2300/Kconfig [deleted file]
drivers/media/video/tlg2300/Makefile [deleted file]
drivers/media/video/tlg2300/pd-alsa.c [deleted file]
drivers/media/video/tlg2300/pd-common.h [deleted file]
drivers/media/video/tlg2300/pd-dvb.c [deleted file]
drivers/media/video/tlg2300/pd-main.c [deleted file]
drivers/media/video/tlg2300/pd-radio.c [deleted file]
drivers/media/video/tlg2300/pd-video.c [deleted file]
drivers/media/video/tlg2300/vendorcmds.h [deleted file]
drivers/media/video/tm6000/Kconfig [deleted file]
drivers/media/video/tm6000/Makefile [deleted file]
drivers/media/video/tm6000/tm6000-alsa.c [deleted file]
drivers/media/video/tm6000/tm6000-cards.c [deleted file]
drivers/media/video/tm6000/tm6000-core.c [deleted file]
drivers/media/video/tm6000/tm6000-dvb.c [deleted file]
drivers/media/video/tm6000/tm6000-i2c.c [deleted file]
drivers/media/video/tm6000/tm6000-input.c [deleted file]
drivers/media/video/tm6000/tm6000-regs.h [deleted file]
drivers/media/video/tm6000/tm6000-stds.c [deleted file]
drivers/media/video/tm6000/tm6000-usb-isoc.h [deleted file]
drivers/media/video/tm6000/tm6000-video.c [deleted file]
drivers/media/video/tm6000/tm6000.h [deleted file]
drivers/media/video/usbvision/Kconfig [deleted file]
drivers/media/video/usbvision/Makefile [deleted file]
drivers/media/video/usbvision/usbvision-cards.c [deleted file]
drivers/media/video/usbvision/usbvision-cards.h [deleted file]
drivers/media/video/usbvision/usbvision-core.c [deleted file]
drivers/media/video/usbvision/usbvision-i2c.c [deleted file]
drivers/media/video/usbvision/usbvision-video.c [deleted file]
drivers/media/video/usbvision/usbvision.h [deleted file]
drivers/media/video/uvc/Kconfig [deleted file]
drivers/media/video/uvc/Makefile [deleted file]
drivers/media/video/uvc/uvc_ctrl.c [deleted file]
drivers/media/video/uvc/uvc_debugfs.c [deleted file]
drivers/media/video/uvc/uvc_driver.c [deleted file]
drivers/media/video/uvc/uvc_entity.c [deleted file]
drivers/media/video/uvc/uvc_isight.c [deleted file]
drivers/media/video/uvc/uvc_queue.c [deleted file]
drivers/media/video/uvc/uvc_status.c [deleted file]
drivers/media/video/uvc/uvc_v4l2.c [deleted file]
drivers/media/video/uvc/uvc_video.c [deleted file]
drivers/media/video/uvc/uvcvideo.h [deleted file]

index ceb5b55b2af83b2d0450da21d4151e5adbb8018b..13fd97f6466a398529f56eb82ac1595d636da44a 100644 (file)
@@ -3119,49 +3119,49 @@ M:      Frank Zago <frank@zago.net>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/gspca/finepix.c
+F:     drivers/media/usb/gspca/finepix.c
 
 GSPCA GL860 SUBDRIVER
 M:     Olivier Lorin <o.lorin@laposte.net>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/gspca/gl860/
+F:     drivers/media/usb/gspca/gl860/
 
 GSPCA M5602 SUBDRIVER
 M:     Erik Andren <erik.andren@gmail.com>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/gspca/m5602/
+F:     drivers/media/usb/gspca/m5602/
 
 GSPCA PAC207 SONIXB SUBDRIVER
 M:     Hans de Goede <hdegoede@redhat.com>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/gspca/pac207.c
+F:     drivers/media/usb/gspca/pac207.c
 
 GSPCA SN9C20X SUBDRIVER
 M:     Brian Johnson <brijohn@gmail.com>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/gspca/sn9c20x.c
+F:     drivers/media/usb/gspca/sn9c20x.c
 
 GSPCA T613 SUBDRIVER
 M:     Leandro Costantino <lcostantino@gmail.com>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/gspca/t613.c
+F:     drivers/media/usb/gspca/t613.c
 
 GSPCA USB WEBCAM DRIVER
 M:     Hans de Goede <hdegoede@redhat.com>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/gspca/
+F:     drivers/media/usb/gspca/
 
 HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
 M:     Frank Seidel <frank@f-seidel.de>
@@ -5525,7 +5525,7 @@ W:        http://www.isely.net/pvrusb2/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
 F:     Documentation/video4linux/README.pvrusb2
-F:     drivers/media/video/pvrusb2/
+F:     drivers/media/usb/pvrusb2/
 
 PWM SUBSYSTEM
 M:     Thierry Reding <thierry.reding@avionic-design.de>
@@ -5956,7 +5956,7 @@ M:        Huang Shijie <shijie8@gmail.com>
 M:     Kang Yong <kangyong@telegent.com>
 M:     Zhang Xiaobing <xbzhang@telegent.com>
 S:     Supported
-F:     drivers/media/video/tlg2300
+F:     drivers/media/usb/tlg2300
 
 SC1200 WDT DRIVER
 M:     Zwane Mwaikambo <zwane@arm.linux.org.uk>
@@ -7297,7 +7297,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 W:     http://www.linux-projects.org
 S:     Maintained
 F:     Documentation/video4linux/sn9c102.txt
-F:     drivers/media/video/sn9c102/
+F:     drivers/media/usb/sn9c102/
 
 USB SUBSYSTEM
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -7332,7 +7332,7 @@ L:        linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 W:     http://www.ideasonboard.org/uvc/
 S:     Maintained
-F:     drivers/media/video/uvc/
+F:     drivers/media/usb/uvc/
 
 USB W996[87]CF DRIVER
 M:     Luca Risolia <luca.risolia@studio.unibo.it>
index 53664b35af1c11e64fae644ffa78600012f261e3..a1e25ee9d67183b36b46513f5c3f2fa7a521071f 100644 (file)
@@ -2,18 +2,49 @@
 # USB media device configuration
 #
 
-menuconfig MEDIA_USB_DRIVERS
-       bool "Supported DVB USB Adapters"
-        depends on USB
-        default y
+menu "Media USB Adapters"
+       visible if USB && MEDIA_SUPPORT
 
-if MEDIA_USB_DRIVERS && DVB_CORE && I2C
+if MEDIA_CAMERA_SUPPORT
+       comment "Webcam devices"
+source "drivers/media/usb/uvc/Kconfig"
+source "drivers/media/usb/gspca/Kconfig"
+source "drivers/media/usb/pwc/Kconfig"
+source "drivers/media/usb/cpia2/Kconfig"
+source "drivers/media/usb/sn9c102/Kconfig"
+endif
+
+if MEDIA_ANALOG_TV_SUPPORT
+       comment "Analog TV USB devices"
+source "drivers/media/usb/au0828/Kconfig"
+source "drivers/media/usb/pvrusb2/Kconfig"
+source "drivers/media/usb/hdpvr/Kconfig"
+source "drivers/media/usb/tlg2300/Kconfig"
+source "drivers/media/usb/usbvision/Kconfig"
+source "drivers/media/usb/stk1160/Kconfig"
 
+endif
+
+if (MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT)
+       comment "Analog/digital TV USB devices"
+source "drivers/media/usb/cx231xx/Kconfig"
+source "drivers/media/usb/tm6000/Kconfig"
+endif
+
+
+if I2C && MEDIA_DIGITAL_TV_SUPPORT
+       comment "Digital TV USB devices"
 source "drivers/media/usb/dvb-usb/Kconfig"
 source "drivers/media/usb/dvb-usb-v2/Kconfig"
 source "drivers/media/usb/ttusb-budget/Kconfig"
 source "drivers/media/usb/ttusb-dec/Kconfig"
 source "drivers/media/usb/siano/Kconfig"
 source "drivers/media/usb/b2c2/Kconfig"
+endif
 
+if (MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT)
+       comment "Webcam, TV (analog/digital) USB devices"
+source "drivers/media/usb/em28xx/Kconfig"
 endif
+
+endmenu
index 6b30ad13c38ebd985f05855bdceff4ac9e1948a7..428827a4d97a24115103380908c91d5fca0e511f 100644 (file)
@@ -4,3 +4,17 @@
 
 # DVB USB-only drivers
 obj-y := ttusb-dec/ ttusb-budget/ dvb-usb/ dvb-usb-v2/ siano/ b2c2/
+obj-$(CONFIG_USB_VIDEO_CLASS)  += uvc/
+obj-$(CONFIG_USB_GSPCA)         += gspca/
+obj-$(CONFIG_USB_PWC)           += pwc/
+obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
+obj-$(CONFIG_USB_SN9C102)       += sn9c102/
+obj-$(CONFIG_VIDEO_AU0828) += au0828/
+obj-$(CONFIG_VIDEO_HDPVR)      += hdpvr/
+obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
+obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/
+obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
+obj-$(CONFIG_VIDEO_STK1160) += stk1160/
+obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
+obj-$(CONFIG_VIDEO_TM6000) += tm6000/
+obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
diff --git a/drivers/media/usb/au0828/Kconfig b/drivers/media/usb/au0828/Kconfig
new file mode 100644 (file)
index 0000000..23f7fd2
--- /dev/null
@@ -0,0 +1,18 @@
+
+config VIDEO_AU0828
+       tristate "Auvitek AU0828 support"
+       depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2
+       depends on DVB_CAPTURE_DRIVERS
+       select I2C_ALGOBIT
+       select VIDEO_TVEEPROM
+       select VIDEOBUF_VMALLOC
+       select DVB_AU8522_DTV if !DVB_FE_CUSTOMISE
+       select DVB_AU8522_V4L if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
+       ---help---
+         This is a video4linux driver for Auvitek's USB device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called au0828
diff --git a/drivers/media/usb/au0828/Makefile b/drivers/media/usb/au0828/Makefile
new file mode 100644 (file)
index 0000000..98cc20c
--- /dev/null
@@ -0,0 +1,9 @@
+au0828-objs    := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-video.o au0828-vbi.o
+
+obj-$(CONFIG_VIDEO_AU0828) += au0828.o
+
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
+
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c
new file mode 100644 (file)
index 0000000..448361c
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
+ *
+ *  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 "au0828.h"
+#include "au0828-cards.h"
+#include "au8522.h"
+#include "media/tuner.h"
+#include "media/v4l2-common.h"
+
+void hvr950q_cs5340_audio(void *priv, int enable)
+{
+       /* Because the HVR-950q shares an i2s bus between the cs5340 and the
+          au8522, we need to hold cs5340 in reset when using the au8522 */
+       struct au0828_dev *dev = priv;
+       if (enable == 1)
+               au0828_set(dev, REG_000, 0x10);
+       else
+               au0828_clear(dev, REG_000, 0x10);
+}
+
+struct au0828_board au0828_boards[] = {
+       [AU0828_BOARD_UNKNOWN] = {
+               .name   = "Unknown board",
+               .tuner_type = UNSET,
+               .tuner_addr = ADDR_UNSET,
+       },
+       [AU0828_BOARD_HAUPPAUGE_HVR850] = {
+               .name   = "Hauppauge HVR850",
+               .tuner_type = TUNER_XC5000,
+               .tuner_addr = 0x61,
+               .i2c_clk_divider = AU0828_I2C_CLK_20KHZ,
+               .input = {
+                       {
+                               .type = AU0828_VMUX_TELEVISION,
+                               .vmux = AU8522_COMPOSITE_CH4_SIF,
+                               .amux = AU8522_AUDIO_SIF,
+                       },
+                       {
+                               .type = AU0828_VMUX_COMPOSITE,
+                               .vmux = AU8522_COMPOSITE_CH1,
+                               .amux = AU8522_AUDIO_NONE,
+                               .audio_setup = hvr950q_cs5340_audio,
+                       },
+                       {
+                               .type = AU0828_VMUX_SVIDEO,
+                               .vmux = AU8522_SVIDEO_CH13,
+                               .amux = AU8522_AUDIO_NONE,
+                               .audio_setup = hvr950q_cs5340_audio,
+                       },
+               },
+       },
+       [AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
+               .name   = "Hauppauge HVR950Q",
+               .tuner_type = TUNER_XC5000,
+               .tuner_addr = 0x61,
+               /* The au0828 hardware i2c implementation does not properly
+                  support the xc5000's i2c clock stretching.  So we need to
+                  lower the clock frequency enough where the 15us clock
+                  stretch fits inside of a normal clock cycle, or else the
+                  au0828 fails to set the STOP bit.  A 30 KHz clock puts the
+                  clock pulse width at 18us */
+               .i2c_clk_divider = AU0828_I2C_CLK_20KHZ,
+               .input = {
+                       {
+                               .type = AU0828_VMUX_TELEVISION,
+                               .vmux = AU8522_COMPOSITE_CH4_SIF,
+                               .amux = AU8522_AUDIO_SIF,
+                       },
+                       {
+                               .type = AU0828_VMUX_COMPOSITE,
+                               .vmux = AU8522_COMPOSITE_CH1,
+                               .amux = AU8522_AUDIO_NONE,
+                               .audio_setup = hvr950q_cs5340_audio,
+                       },
+                       {
+                               .type = AU0828_VMUX_SVIDEO,
+                               .vmux = AU8522_SVIDEO_CH13,
+                               .amux = AU8522_AUDIO_NONE,
+                               .audio_setup = hvr950q_cs5340_audio,
+                       },
+               },
+       },
+       [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = {
+               .name   = "Hauppauge HVR950Q rev xxF8",
+               .tuner_type = UNSET,
+               .tuner_addr = ADDR_UNSET,
+               .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
+       },
+       [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
+               .name   = "DViCO FusionHDTV USB",
+               .tuner_type = UNSET,
+               .tuner_addr = ADDR_UNSET,
+               .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
+       },
+       [AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
+               .name = "Hauppauge Woodbury",
+               .tuner_type = UNSET,
+               .tuner_addr = ADDR_UNSET,
+               .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
+       },
+};
+
+/* Tuner callback function for au0828 boards. Currently only needed
+ * for HVR1500Q, which has an xc5000 tuner.
+ */
+int au0828_tuner_callback(void *priv, int component, int command, int arg)
+{
+       struct au0828_dev *dev = priv;
+
+       dprintk(1, "%s()\n", __func__);
+
+       switch (dev->boardnr) {
+       case AU0828_BOARD_HAUPPAUGE_HVR850:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
+       case AU0828_BOARD_DVICO_FUSIONHDTV7:
+               if (command == 0) {
+                       /* Tuner Reset Command from xc5000 */
+                       /* Drive the tuner into reset and out */
+                       au0828_clear(dev, REG_001, 2);
+                       mdelay(10);
+                       au0828_set(dev, REG_001, 2);
+                       mdelay(10);
+                       return 0;
+               } else {
+                       printk(KERN_ERR
+                               "%s(): Unknown command.\n", __func__);
+                       return -EINVAL;
+               }
+               break;
+       }
+
+       return 0; /* Should never be here */
+}
+
+static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
+{
+       struct tveeprom tv;
+
+       tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
+       dev->board.tuner_type = tv.tuner_type;
+
+       /* Make sure we support the board model */
+       switch (tv.model) {
+       case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */
+       case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
+       case 72101: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
+       case 72201: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
+       case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
+       case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
+       case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
+       case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */
+       case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
+       case 72261: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
+       case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and analog video */
+       case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */
+               break;
+       default:
+               printk(KERN_WARNING "%s: warning: "
+                      "unknown hauppauge model #%d\n", __func__, tv.model);
+               break;
+       }
+
+       printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
+              __func__, tv.model);
+}
+
+void au0828_card_setup(struct au0828_dev *dev)
+{
+       static u8 eeprom[256];
+       struct tuner_setup tun_setup;
+       struct v4l2_subdev *sd;
+       unsigned int mode_mask = T_ANALOG_TV;
+
+       dprintk(1, "%s()\n", __func__);
+
+       memcpy(&dev->board, &au0828_boards[dev->boardnr], sizeof(dev->board));
+
+       if (dev->i2c_rc == 0) {
+               dev->i2c_client.addr = 0xa0 >> 1;
+               tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom));
+       }
+
+       switch (dev->boardnr) {
+       case AU0828_BOARD_HAUPPAUGE_HVR850:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
+       case AU0828_BOARD_HAUPPAUGE_WOODBURY:
+               if (dev->i2c_rc == 0)
+                       hauppauge_eeprom(dev, eeprom+0xa0);
+               break;
+       }
+
+       if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) {
+               /* Load the analog demodulator driver (note this would need to
+                  be abstracted out if we ever need to support a different
+                  demod) */
+               sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+                               "au8522", 0x8e >> 1, NULL);
+               if (sd == NULL)
+                       printk(KERN_ERR "analog subdev registration failed\n");
+       }
+
+       /* Setup tuners */
+       if (dev->board.tuner_type != TUNER_ABSENT) {
+               /* Load the tuner module, which does the attach */
+               sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+                               "tuner", dev->board.tuner_addr, NULL);
+               if (sd == NULL)
+                       printk(KERN_ERR "tuner subdev registration fail\n");
+
+               tun_setup.mode_mask      = mode_mask;
+               tun_setup.type           = dev->board.tuner_type;
+               tun_setup.addr           = dev->board.tuner_addr;
+               tun_setup.tuner_callback = au0828_tuner_callback;
+               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr,
+                                    &tun_setup);
+       }
+}
+
+/*
+ * The bridge has between 8 and 12 gpios.
+ * Regs 1 and 0 deal with output enables.
+ * Regs 3 and 2 deal with direction.
+ */
+void au0828_gpio_setup(struct au0828_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       switch (dev->boardnr) {
+       case AU0828_BOARD_HAUPPAUGE_HVR850:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
+       case AU0828_BOARD_HAUPPAUGE_WOODBURY:
+               /* GPIO's
+                * 4 - CS5340
+                * 5 - AU8522 Demodulator
+                * 6 - eeprom W/P
+                * 7 - power supply
+                * 9 - XC5000 Tuner
+                */
+
+               /* Into reset */
+               au0828_write(dev, REG_003, 0x02);
+               au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10);
+               au0828_write(dev, REG_001, 0x0);
+               au0828_write(dev, REG_000, 0x0);
+               msleep(100);
+
+               /* Out of reset (leave the cs5340 in reset until needed) */
+               au0828_write(dev, REG_003, 0x02);
+               au0828_write(dev, REG_001, 0x02);
+               au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10);
+               au0828_write(dev, REG_000, 0x80 | 0x40 | 0x20);
+
+               msleep(250);
+               break;
+       case AU0828_BOARD_DVICO_FUSIONHDTV7:
+               /* GPIO's
+                * 6 - ?
+                * 8 - AU8522 Demodulator
+                * 9 - XC5000 Tuner
+                */
+
+               /* Into reset */
+               au0828_write(dev, REG_003, 0x02);
+               au0828_write(dev, REG_002, 0xa0);
+               au0828_write(dev, REG_001, 0x0);
+               au0828_write(dev, REG_000, 0x0);
+               msleep(100);
+
+               /* Out of reset */
+               au0828_write(dev, REG_003, 0x02);
+               au0828_write(dev, REG_002, 0xa0);
+               au0828_write(dev, REG_001, 0x02);
+               au0828_write(dev, REG_000, 0xa0);
+               msleep(250);
+               break;
+       }
+}
+
+/* table of devices that work with this driver */
+struct usb_device_id au0828_usb_id_table[] = {
+       { USB_DEVICE(0x2040, 0x7200),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x7240),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 },
+       { USB_DEVICE(0x0fe9, 0xd620),
+               .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 },
+       { USB_DEVICE(0x2040, 0x7210),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x7217),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x721b),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x721e),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x721f),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x7280),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x0fd9, 0x0008),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x7201),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
+       { USB_DEVICE(0x2040, 0x7211),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
+       { USB_DEVICE(0x2040, 0x7281),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
+       { USB_DEVICE(0x05e1, 0x0480),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY },
+       { USB_DEVICE(0x2040, 0x8200),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY },
+       { USB_DEVICE(0x2040, 0x7260),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { USB_DEVICE(0x2040, 0x7213),
+               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
+       { },
+};
+
+MODULE_DEVICE_TABLE(usb, au0828_usb_id_table);
diff --git a/drivers/media/usb/au0828/au0828-cards.h b/drivers/media/usb/au0828/au0828-cards.h
new file mode 100644 (file)
index 0000000..48a1882
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
+ *
+ *  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.
+ */
+
+#define AU0828_BOARD_UNKNOWN           0
+#define AU0828_BOARD_HAUPPAUGE_HVR950Q 1
+#define AU0828_BOARD_HAUPPAUGE_HVR850  2
+#define AU0828_BOARD_DVICO_FUSIONHDTV7 3
+#define AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL     4
+#define AU0828_BOARD_HAUPPAUGE_WOODBURY        5
diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
new file mode 100644 (file)
index 0000000..745a80a
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
+ *
+ *  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/module.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/mutex.h>
+
+#include "au0828.h"
+
+/*
+ * 1 = General debug messages
+ * 2 = USB handling
+ * 4 = I2C related
+ * 8 = Bridge related
+ */
+int au0828_debug;
+module_param_named(debug, au0828_debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+static unsigned int disable_usb_speed_check;
+module_param(disable_usb_speed_check, int, 0444);
+MODULE_PARM_DESC(disable_usb_speed_check,
+                "override min bandwidth requirement of 480M bps");
+
+#define _AU0828_BULKPIPE 0x03
+#define _BULKPIPESIZE 0xffff
+
+static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+                           u16 index);
+static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+       u16 index, unsigned char *cp, u16 size);
+
+/* USB Direction */
+#define CMD_REQUEST_IN         0x00
+#define CMD_REQUEST_OUT                0x01
+
+u32 au0828_readreg(struct au0828_dev *dev, u16 reg)
+{
+       u8 result = 0;
+
+       recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, &result, 1);
+       dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, result);
+
+       return result;
+}
+
+u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
+{
+       dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val);
+       return send_control_msg(dev, CMD_REQUEST_OUT, val, reg);
+}
+
+static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+       u16 index)
+{
+       int status = -ENODEV;
+
+       if (dev->usbdev) {
+
+               /* cp must be memory that has been allocated by kmalloc */
+               status = usb_control_msg(dev->usbdev,
+                               usb_sndctrlpipe(dev->usbdev, 0),
+                               request,
+                               USB_DIR_OUT | USB_TYPE_VENDOR |
+                                       USB_RECIP_DEVICE,
+                               value, index, NULL, 0, 1000);
+
+               status = min(status, 0);
+
+               if (status < 0) {
+                       printk(KERN_ERR "%s() Failed sending control message, error %d.\n",
+                               __func__, status);
+               }
+
+       }
+
+       return status;
+}
+
+static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
+       u16 index, unsigned char *cp, u16 size)
+{
+       int status = -ENODEV;
+       mutex_lock(&dev->mutex);
+       if (dev->usbdev) {
+               status = usb_control_msg(dev->usbdev,
+                               usb_rcvctrlpipe(dev->usbdev, 0),
+                               request,
+                               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               value, index,
+                               dev->ctrlmsg, size, 1000);
+
+               status = min(status, 0);
+
+               if (status < 0) {
+                       printk(KERN_ERR "%s() Failed receiving control message, error %d.\n",
+                               __func__, status);
+               }
+
+               /* the host controller requires heap allocated memory, which
+                  is why we didn't just pass "cp" into usb_control_msg */
+               memcpy(cp, dev->ctrlmsg, size);
+       }
+       mutex_unlock(&dev->mutex);
+       return status;
+}
+
+static void au0828_usb_disconnect(struct usb_interface *interface)
+{
+       struct au0828_dev *dev = usb_get_intfdata(interface);
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* Digital TV */
+       au0828_dvb_unregister(dev);
+
+       if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED)
+               au0828_analog_unregister(dev);
+
+       /* I2C */
+       au0828_i2c_unregister(dev);
+
+       v4l2_device_unregister(&dev->v4l2_dev);
+
+       usb_set_intfdata(interface, NULL);
+
+       mutex_lock(&dev->mutex);
+       dev->usbdev = NULL;
+       mutex_unlock(&dev->mutex);
+
+       kfree(dev);
+
+}
+
+static int au0828_usb_probe(struct usb_interface *interface,
+       const struct usb_device_id *id)
+{
+       int ifnum, retval;
+       struct au0828_dev *dev;
+       struct usb_device *usbdev = interface_to_usbdev(interface);
+
+       ifnum = interface->altsetting->desc.bInterfaceNumber;
+
+       if (ifnum != 0)
+               return -ENODEV;
+
+       dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,
+               le16_to_cpu(usbdev->descriptor.idVendor),
+               le16_to_cpu(usbdev->descriptor.idProduct),
+               ifnum);
+
+       /*
+        * Make sure we have 480 Mbps of bandwidth, otherwise things like
+        * video stream wouldn't likely work, since 12 Mbps is generally
+        * not enough even for most Digital TV streams.
+        */
+       if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {
+               printk(KERN_ERR "au0828: Device initialization failed.\n");
+               printk(KERN_ERR "au0828: Device must be connected to a "
+                      "high-speed USB 2.0 port.\n");
+               return -ENODEV;
+       }
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               printk(KERN_ERR "%s() Unable to allocate memory\n", __func__);
+               return -ENOMEM;
+       }
+
+       mutex_init(&dev->lock);
+       mutex_lock(&dev->lock);
+       mutex_init(&dev->mutex);
+       mutex_init(&dev->dvb.lock);
+       dev->usbdev = usbdev;
+       dev->boardnr = id->driver_info;
+
+       /* Create the v4l2_device */
+       retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
+       if (retval) {
+               printk(KERN_ERR "%s() v4l2_device_register failed\n",
+                      __func__);
+               mutex_unlock(&dev->lock);
+               kfree(dev);
+               return -EIO;
+       }
+
+       /* Power Up the bridge */
+       au0828_write(dev, REG_600, 1 << 4);
+
+       /* Bring up the GPIO's and supporting devices */
+       au0828_gpio_setup(dev);
+
+       /* I2C */
+       au0828_i2c_register(dev);
+
+       /* Setup */
+       au0828_card_setup(dev);
+
+       /* Analog TV */
+       if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED)
+               au0828_analog_register(dev, interface);
+
+       /* Digital TV */
+       au0828_dvb_register(dev);
+
+       /* Store the pointer to the au0828_dev so it can be accessed in
+          au0828_usb_disconnect */
+       usb_set_intfdata(interface, dev);
+
+       printk(KERN_INFO "Registered device AU0828 [%s]\n",
+               dev->board.name == NULL ? "Unset" : dev->board.name);
+
+       mutex_unlock(&dev->lock);
+
+       return 0;
+}
+
+static struct usb_driver au0828_usb_driver = {
+       .name           = DRIVER_NAME,
+       .probe          = au0828_usb_probe,
+       .disconnect     = au0828_usb_disconnect,
+       .id_table       = au0828_usb_id_table,
+};
+
+static int __init au0828_init(void)
+{
+       int ret;
+
+       if (au0828_debug & 1)
+               printk(KERN_INFO "%s() Debugging is enabled\n", __func__);
+
+       if (au0828_debug & 2)
+               printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__);
+
+       if (au0828_debug & 4)
+               printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__);
+
+       if (au0828_debug & 8)
+               printk(KERN_INFO "%s() Bridge Debugging is enabled\n",
+                      __func__);
+
+       printk(KERN_INFO "au0828 driver loaded\n");
+
+       ret = usb_register(&au0828_usb_driver);
+       if (ret)
+               printk(KERN_ERR "usb_register failed, error = %d\n", ret);
+
+       return ret;
+}
+
+static void __exit au0828_exit(void)
+{
+       usb_deregister(&au0828_usb_driver);
+}
+
+module_init(au0828_init);
+module_exit(au0828_exit);
+
+MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
+MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.2");
diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c
new file mode 100644 (file)
index 0000000..b328f65
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
+ *
+ *  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/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+
+#include "au0828.h"
+#include "au8522.h"
+#include "xc5000.h"
+#include "mxl5007t.h"
+#include "tda18271.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define _AU0828_BULKPIPE 0x83
+#define _BULKPIPESIZE 0xe522
+
+static u8 hauppauge_hvr950q_led_states[] = {
+       0x00, /* off */
+       0x02, /* yellow */
+       0x04, /* green */
+};
+
+static struct au8522_led_config hauppauge_hvr950q_led_cfg = {
+       .gpio_output = 0x00e0,
+       .gpio_output_enable  = 0x6006,
+       .gpio_output_disable = 0x0660,
+
+       .gpio_leds = 0x00e2,
+       .led_states  = hauppauge_hvr950q_led_states,
+       .num_led_states = sizeof(hauppauge_hvr950q_led_states),
+
+       .vsb8_strong   = 20 /* dB */ * 10,
+       .qam64_strong  = 25 /* dB */ * 10,
+       .qam256_strong = 32 /* dB */ * 10,
+};
+
+static struct au8522_config hauppauge_hvr950q_config = {
+       .demod_address = 0x8e >> 1,
+       .status_mode   = AU8522_DEMODLOCKING,
+       .qam_if        = AU8522_IF_6MHZ,
+       .vsb_if        = AU8522_IF_6MHZ,
+       .led_cfg       = &hauppauge_hvr950q_led_cfg,
+};
+
+static struct au8522_config fusionhdtv7usb_config = {
+       .demod_address = 0x8e >> 1,
+       .status_mode   = AU8522_DEMODLOCKING,
+       .qam_if        = AU8522_IF_6MHZ,
+       .vsb_if        = AU8522_IF_6MHZ,
+};
+
+static struct au8522_config hauppauge_woodbury_config = {
+       .demod_address = 0x8e >> 1,
+       .status_mode   = AU8522_DEMODLOCKING,
+       .qam_if        = AU8522_IF_4MHZ,
+       .vsb_if        = AU8522_IF_3_25MHZ,
+};
+
+static struct xc5000_config hauppauge_xc5000a_config = {
+       .i2c_address      = 0x61,
+       .if_khz           = 6000,
+       .chip_id          = XC5000A,
+};
+
+static struct xc5000_config hauppauge_xc5000c_config = {
+       .i2c_address      = 0x61,
+       .if_khz           = 6000,
+       .chip_id          = XC5000C,
+};
+
+static struct mxl5007t_config mxl5007t_hvr950q_config = {
+       .xtal_freq_hz = MxL_XTAL_24_MHZ,
+       .if_freq_hz = MxL_IF_6_MHZ,
+};
+
+static struct tda18271_config hauppauge_woodbury_tunerconfig = {
+       .gate    = TDA18271_GATE_DIGITAL,
+};
+
+static void au0828_restart_dvb_streaming(struct work_struct *work);
+
+/*-------------------------------------------------------------------*/
+static void urb_completion(struct urb *purb)
+{
+       struct au0828_dev *dev = purb->context;
+       int ptype = usb_pipetype(purb->pipe);
+       unsigned char *ptr;
+
+       dprintk(2, "%s()\n", __func__);
+
+       if (!dev)
+               return;
+
+       if (dev->urb_streaming == 0)
+               return;
+
+       if (ptype != PIPE_BULK) {
+               printk(KERN_ERR "%s() Unsupported URB type %d\n",
+                      __func__, ptype);
+               return;
+       }
+
+       /* See if the stream is corrupted (to work around a hardware
+          bug where the stream gets misaligned */
+       ptr = purb->transfer_buffer;
+       if (purb->actual_length > 0 && ptr[0] != 0x47) {
+               dprintk(1, "Need to restart streaming %02x len=%d!\n",
+                       ptr[0], purb->actual_length);
+               schedule_work(&dev->restart_streaming);
+               return;
+       }
+
+       /* Feed the transport payload into the kernel demux */
+       dvb_dmx_swfilter_packets(&dev->dvb.demux,
+               purb->transfer_buffer, purb->actual_length / 188);
+
+       /* Clean the buffer before we requeue */
+       memset(purb->transfer_buffer, 0, URB_BUFSIZE);
+
+       /* Requeue URB */
+       usb_submit_urb(purb, GFP_ATOMIC);
+}
+
+static int stop_urb_transfer(struct au0828_dev *dev)
+{
+       int i;
+
+       dprintk(2, "%s()\n", __func__);
+
+       dev->urb_streaming = 0;
+       for (i = 0; i < URB_COUNT; i++) {
+               usb_kill_urb(dev->urbs[i]);
+               kfree(dev->urbs[i]->transfer_buffer);
+               usb_free_urb(dev->urbs[i]);
+       }
+
+       return 0;
+}
+
+static int start_urb_transfer(struct au0828_dev *dev)
+{
+       struct urb *purb;
+       int i, ret = -ENOMEM;
+
+       dprintk(2, "%s()\n", __func__);
+
+       if (dev->urb_streaming) {
+               dprintk(2, "%s: bulk xfer already running!\n", __func__);
+               return 0;
+       }
+
+       for (i = 0; i < URB_COUNT; i++) {
+
+               dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
+               if (!dev->urbs[i])
+                       goto err;
+
+               purb = dev->urbs[i];
+
+               purb->transfer_buffer = kzalloc(URB_BUFSIZE, GFP_KERNEL);
+               if (!purb->transfer_buffer) {
+                       usb_free_urb(purb);
+                       dev->urbs[i] = NULL;
+                       goto err;
+               }
+
+               purb->status = -EINPROGRESS;
+               usb_fill_bulk_urb(purb,
+                                 dev->usbdev,
+                                 usb_rcvbulkpipe(dev->usbdev,
+                                       _AU0828_BULKPIPE),
+                                 purb->transfer_buffer,
+                                 URB_BUFSIZE,
+                                 urb_completion,
+                                 dev);
+
+       }
+
+       for (i = 0; i < URB_COUNT; i++) {
+               ret = usb_submit_urb(dev->urbs[i], GFP_ATOMIC);
+               if (ret != 0) {
+                       stop_urb_transfer(dev);
+                       printk(KERN_ERR "%s: failed urb submission, "
+                              "err = %d\n", __func__, ret);
+                       return ret;
+               }
+       }
+
+       dev->urb_streaming = 1;
+       ret = 0;
+
+err:
+       return ret;
+}
+
+static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
+       struct au0828_dvb *dvb = &dev->dvb;
+       int ret = 0;
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (!demux->dmx.frontend)
+               return -EINVAL;
+
+       if (dvb) {
+               mutex_lock(&dvb->lock);
+               if (dvb->feeding++ == 0) {
+                       /* Start transport */
+                       au0828_write(dev, 0x608, 0x90);
+                       au0828_write(dev, 0x609, 0x72);
+                       au0828_write(dev, 0x60a, 0x71);
+                       au0828_write(dev, 0x60b, 0x01);
+                       ret = start_urb_transfer(dev);
+               }
+               mutex_unlock(&dvb->lock);
+       }
+
+       return ret;
+}
+
+static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
+       struct au0828_dvb *dvb = &dev->dvb;
+       int ret = 0;
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (dvb) {
+               mutex_lock(&dvb->lock);
+               if (--dvb->feeding == 0) {
+                       /* Stop transport */
+                       ret = stop_urb_transfer(dev);
+                       au0828_write(dev, 0x60b, 0x00);
+               }
+               mutex_unlock(&dvb->lock);
+       }
+
+       return ret;
+}
+
+static void au0828_restart_dvb_streaming(struct work_struct *work)
+{
+       struct au0828_dev *dev = container_of(work, struct au0828_dev,
+                                             restart_streaming);
+       struct au0828_dvb *dvb = &dev->dvb;
+       int ret;
+
+       if (dev->urb_streaming == 0)
+               return;
+
+       dprintk(1, "Restarting streaming...!\n");
+
+       mutex_lock(&dvb->lock);
+
+       /* Stop transport */
+       ret = stop_urb_transfer(dev);
+       au0828_write(dev, 0x608, 0x00);
+       au0828_write(dev, 0x609, 0x00);
+       au0828_write(dev, 0x60a, 0x00);
+       au0828_write(dev, 0x60b, 0x00);
+
+       /* Start transport */
+       au0828_write(dev, 0x608, 0x90);
+       au0828_write(dev, 0x609, 0x72);
+       au0828_write(dev, 0x60a, 0x71);
+       au0828_write(dev, 0x60b, 0x01);
+       ret = start_urb_transfer(dev);
+
+       mutex_unlock(&dvb->lock);
+}
+
+static int dvb_register(struct au0828_dev *dev)
+{
+       struct au0828_dvb *dvb = &dev->dvb;
+       int result;
+
+       dprintk(1, "%s()\n", __func__);
+
+       INIT_WORK(&dev->restart_streaming, au0828_restart_dvb_streaming);
+
+       /* register adapter */
+       result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
+                                     &dev->usbdev->dev, adapter_nr);
+       if (result < 0) {
+               printk(KERN_ERR "%s: dvb_register_adapter failed "
+                      "(errno = %d)\n", DRIVER_NAME, result);
+               goto fail_adapter;
+       }
+       dvb->adapter.priv = dev;
+
+       /* register frontend */
+       result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+       if (result < 0) {
+               printk(KERN_ERR "%s: dvb_register_frontend failed "
+                      "(errno = %d)\n", DRIVER_NAME, result);
+               goto fail_frontend;
+       }
+
+       /* register demux stuff */
+       dvb->demux.dmx.capabilities =
+               DMX_TS_FILTERING | DMX_SECTION_FILTERING |
+               DMX_MEMORY_BASED_FILTERING;
+       dvb->demux.priv       = dev;
+       dvb->demux.filternum  = 256;
+       dvb->demux.feednum    = 256;
+       dvb->demux.start_feed = au0828_dvb_start_feed;
+       dvb->demux.stop_feed  = au0828_dvb_stop_feed;
+       result = dvb_dmx_init(&dvb->demux);
+       if (result < 0) {
+               printk(KERN_ERR "%s: dvb_dmx_init failed (errno = %d)\n",
+                      DRIVER_NAME, result);
+               goto fail_dmx;
+       }
+
+       dvb->dmxdev.filternum    = 256;
+       dvb->dmxdev.demux        = &dvb->demux.dmx;
+       dvb->dmxdev.capabilities = 0;
+       result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+       if (result < 0) {
+               printk(KERN_ERR "%s: dvb_dmxdev_init failed (errno = %d)\n",
+                      DRIVER_NAME, result);
+               goto fail_dmxdev;
+       }
+
+       dvb->fe_hw.source = DMX_FRONTEND_0;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_ERR "%s: add_frontend failed "
+                      "(DMX_FRONTEND_0, errno = %d)\n", DRIVER_NAME, result);
+               goto fail_fe_hw;
+       }
+
+       dvb->fe_mem.source = DMX_MEMORY_FE;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       if (result < 0) {
+               printk(KERN_ERR "%s: add_frontend failed "
+                      "(DMX_MEMORY_FE, errno = %d)\n", DRIVER_NAME, result);
+               goto fail_fe_mem;
+       }
+
+       result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_ERR "%s: connect_frontend failed (errno = %d)\n",
+                      DRIVER_NAME, result);
+               goto fail_fe_conn;
+       }
+
+       /* register network adapter */
+       dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
+       return 0;
+
+fail_fe_conn:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+fail_fe_mem:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+fail_fe_hw:
+       dvb_dmxdev_release(&dvb->dmxdev);
+fail_dmxdev:
+       dvb_dmx_release(&dvb->demux);
+fail_dmx:
+       dvb_unregister_frontend(dvb->frontend);
+fail_frontend:
+       dvb_frontend_detach(dvb->frontend);
+       dvb_unregister_adapter(&dvb->adapter);
+fail_adapter:
+       return result;
+}
+
+void au0828_dvb_unregister(struct au0828_dev *dev)
+{
+       struct au0828_dvb *dvb = &dev->dvb;
+
+       dprintk(1, "%s()\n", __func__);
+
+       if (dvb->frontend == NULL)
+               return;
+
+       dvb_net_release(&dvb->net);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       dvb_dmxdev_release(&dvb->dmxdev);
+       dvb_dmx_release(&dvb->demux);
+       dvb_unregister_frontend(dvb->frontend);
+       dvb_frontend_detach(dvb->frontend);
+       dvb_unregister_adapter(&dvb->adapter);
+}
+
+/* All the DVB attach calls go here, this function get's modified
+ * for each new card. No other function in this file needs
+ * to change.
+ */
+int au0828_dvb_register(struct au0828_dev *dev)
+{
+       struct au0828_dvb *dvb = &dev->dvb;
+       int ret;
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* init frontend */
+       switch (dev->boardnr) {
+       case AU0828_BOARD_HAUPPAUGE_HVR850:
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
+               dvb->frontend = dvb_attach(au8522_attach,
+                               &hauppauge_hvr950q_config,
+                               &dev->i2c_adap);
+               if (dvb->frontend != NULL)
+                       switch (dev->board.tuner_type) {
+                       default:
+                       case TUNER_XC5000:
+                               dvb_attach(xc5000_attach, dvb->frontend,
+                                          &dev->i2c_adap,
+                                          &hauppauge_xc5000a_config);
+                               break;
+                       case TUNER_XC5000C:
+                               dvb_attach(xc5000_attach, dvb->frontend,
+                                          &dev->i2c_adap,
+                                          &hauppauge_xc5000c_config);
+                               break;
+                       }
+               break;
+       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
+               dvb->frontend = dvb_attach(au8522_attach,
+                               &hauppauge_hvr950q_config,
+                               &dev->i2c_adap);
+               if (dvb->frontend != NULL)
+                       dvb_attach(mxl5007t_attach, dvb->frontend,
+                                  &dev->i2c_adap, 0x60,
+                                  &mxl5007t_hvr950q_config);
+               break;
+       case AU0828_BOARD_HAUPPAUGE_WOODBURY:
+               dvb->frontend = dvb_attach(au8522_attach,
+                               &hauppauge_woodbury_config,
+                               &dev->i2c_adap);
+               if (dvb->frontend != NULL)
+                       dvb_attach(tda18271_attach, dvb->frontend,
+                                  0x60, &dev->i2c_adap,
+                                  &hauppauge_woodbury_tunerconfig);
+               break;
+       case AU0828_BOARD_DVICO_FUSIONHDTV7:
+               dvb->frontend = dvb_attach(au8522_attach,
+                               &fusionhdtv7usb_config,
+                               &dev->i2c_adap);
+               if (dvb->frontend != NULL) {
+                       dvb_attach(xc5000_attach, dvb->frontend,
+                               &dev->i2c_adap,
+                               &hauppauge_xc5000a_config);
+               }
+               break;
+       default:
+               printk(KERN_WARNING "The frontend of your DVB/ATSC card "
+                      "isn't supported yet\n");
+               break;
+       }
+       if (NULL == dvb->frontend) {
+               printk(KERN_ERR "%s() Frontend initialization failed\n",
+                      __func__);
+               return -1;
+       }
+       /* define general-purpose callback pointer */
+       dvb->frontend->callback = au0828_tuner_callback;
+
+       /* register everything */
+       ret = dvb_register(dev);
+       if (ret < 0) {
+               if (dvb->frontend->ops.release)
+                       dvb->frontend->ops.release(dvb->frontend);
+               return ret;
+       }
+
+       return 0;
+}
diff --git a/drivers/media/usb/au0828/au0828-i2c.c b/drivers/media/usb/au0828/au0828-i2c.c
new file mode 100644 (file)
index 0000000..4ded17f
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ *  Driver for the Auvitek AU0828 USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
+ *
+ *  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/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include "au0828.h"
+#include "media/tuner.h"
+#include <media/v4l2-common.h>
+
+static int i2c_scan;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+#define I2C_WAIT_DELAY 25
+#define I2C_WAIT_RETRY 1000
+
+static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, AU0828_I2C_STATUS_201) &
+               AU0828_I2C_STATUS_NO_WRITE_ACK ? 0 : 1;
+}
+
+static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, AU0828_I2C_STATUS_201) &
+               AU0828_I2C_STATUS_NO_READ_ACK ? 0 : 1;
+}
+
+static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap)
+{
+       int count;
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               if (!i2c_slave_did_read_ack(i2c_adap))
+                       break;
+               udelay(I2C_WAIT_DELAY);
+       }
+
+       if (I2C_WAIT_RETRY == count)
+               return 0;
+
+       return 1;
+}
+
+static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, AU0828_I2C_STATUS_201) &
+               AU0828_I2C_STATUS_READ_DONE ? 0 : 1;
+}
+
+static int i2c_wait_read_done(struct i2c_adapter *i2c_adap)
+{
+       int count;
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               if (!i2c_is_read_busy(i2c_adap))
+                       break;
+               udelay(I2C_WAIT_DELAY);
+       }
+
+       if (I2C_WAIT_RETRY == count)
+               return 0;
+
+       return 1;
+}
+
+static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, AU0828_I2C_STATUS_201) &
+               AU0828_I2C_STATUS_WRITE_DONE ? 1 : 0;
+}
+
+static int i2c_wait_write_done(struct i2c_adapter *i2c_adap)
+{
+       int count;
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               if (i2c_is_write_done(i2c_adap))
+                       break;
+               udelay(I2C_WAIT_DELAY);
+       }
+
+       if (I2C_WAIT_RETRY == count)
+               return 0;
+
+       return 1;
+}
+
+static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       return au0828_read(dev, AU0828_I2C_STATUS_201) &
+               AU0828_I2C_STATUS_BUSY ? 1 : 0;
+}
+
+static int i2c_wait_done(struct i2c_adapter *i2c_adap)
+{
+       int count;
+
+       for (count = 0; count < I2C_WAIT_RETRY; count++) {
+               if (!i2c_is_busy(i2c_adap))
+                       break;
+               udelay(I2C_WAIT_DELAY);
+       }
+
+       if (I2C_WAIT_RETRY == count)
+               return 0;
+
+       return 1;
+}
+
+/* FIXME: Implement join handling correctly */
+static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
+       const struct i2c_msg *msg, int joined_rlen)
+{
+       int i, strobe = 0;
+       struct au0828_dev *dev = i2c_adap->algo_data;
+
+       dprintk(4, "%s()\n", __func__);
+
+       au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
+
+       /* Set the I2C clock */
+       if (((dev->board.tuner_type == TUNER_XC5000) ||
+            (dev->board.tuner_type == TUNER_XC5000C)) &&
+           (dev->board.tuner_addr == msg->addr) &&
+           (msg->len == 64)) {
+               /* Hack to speed up firmware load.  The xc5000 lets us do up
+                  to 400 KHz when in firmware download mode */
+               au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
+                            AU0828_I2C_CLK_250KHZ);
+       } else {
+               /* Use the i2c clock speed in the board configuration */
+               au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
+                            dev->board.i2c_clk_divider);
+       }
+
+       /* Hardware needs 8 bit addresses */
+       au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
+
+       dprintk(4, "SEND: %02x\n", msg->addr);
+
+       /* Deal with i2c_scan */
+       if (msg->len == 0) {
+               /* The analog tuner detection code makes use of the SMBUS_QUICK
+                  message (which involves a zero length i2c write).  To avoid
+                  checking the status register when we didn't strobe out any
+                  actual bytes to the bus, just do a read check.  This is
+                  consistent with how I saw i2c device checking done in the
+                  USB trace of the Windows driver */
+               au0828_write(dev, AU0828_I2C_TRIGGER_200,
+                            AU0828_I2C_TRIGGER_READ);
+
+               if (!i2c_wait_done(i2c_adap))
+                       return -EIO;
+
+               if (i2c_wait_read_ack(i2c_adap))
+                       return -EIO;
+
+               return 0;
+       }
+
+       for (i = 0; i < msg->len;) {
+
+               dprintk(4, " %02x\n", msg->buf[i]);
+
+               au0828_write(dev, AU0828_I2C_WRITE_FIFO_205, msg->buf[i]);
+
+               strobe++;
+               i++;
+
+               if ((strobe >= 4) || (i >= msg->len)) {
+
+                       /* Strobe the byte into the bus */
+                       if (i < msg->len)
+                               au0828_write(dev, AU0828_I2C_TRIGGER_200,
+                                            AU0828_I2C_TRIGGER_WRITE |
+                                            AU0828_I2C_TRIGGER_HOLD);
+                       else
+                               au0828_write(dev, AU0828_I2C_TRIGGER_200,
+                                            AU0828_I2C_TRIGGER_WRITE);
+
+                       /* Reset strobe trigger */
+                       strobe = 0;
+
+                       if (!i2c_wait_write_done(i2c_adap))
+                               return -EIO;
+
+               }
+
+       }
+       if (!i2c_wait_done(i2c_adap))
+               return -EIO;
+
+       dprintk(4, "\n");
+
+       return msg->len;
+}
+
+/* FIXME: Implement join handling correctly */
+static int i2c_readbytes(struct i2c_adapter *i2c_adap,
+       const struct i2c_msg *msg, int joined)
+{
+       struct au0828_dev *dev = i2c_adap->algo_data;
+       int i;
+
+       dprintk(4, "%s()\n", __func__);
+
+       au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
+
+       /* Set the I2C clock */
+       au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
+                    dev->board.i2c_clk_divider);
+
+       /* Hardware needs 8 bit addresses */
+       au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
+
+       dprintk(4, " RECV:\n");
+
+       /* Deal with i2c_scan */
+       if (msg->len == 0) {
+               au0828_write(dev, AU0828_I2C_TRIGGER_200,
+                            AU0828_I2C_TRIGGER_READ);
+
+               if (i2c_wait_read_ack(i2c_adap))
+                       return -EIO;
+               return 0;
+       }
+
+       for (i = 0; i < msg->len;) {
+
+               i++;
+
+               if (i < msg->len)
+                       au0828_write(dev, AU0828_I2C_TRIGGER_200,
+                                    AU0828_I2C_TRIGGER_READ |
+                                    AU0828_I2C_TRIGGER_HOLD);
+               else
+                       au0828_write(dev, AU0828_I2C_TRIGGER_200,
+                                    AU0828_I2C_TRIGGER_READ);
+
+               if (!i2c_wait_read_done(i2c_adap))
+                       return -EIO;
+
+               msg->buf[i-1] = au0828_read(dev, AU0828_I2C_READ_FIFO_209) &
+                       0xff;
+
+               dprintk(4, " %02x\n", msg->buf[i-1]);
+       }
+       if (!i2c_wait_done(i2c_adap))
+               return -EIO;
+
+       dprintk(4, "\n");
+
+       return msg->len;
+}
+
+static int i2c_xfer(struct i2c_adapter *i2c_adap,
+                   struct i2c_msg *msgs, int num)
+{
+       int i, retval = 0;
+
+       dprintk(4, "%s(num = %d)\n", __func__, num);
+
+       for (i = 0; i < num; i++) {
+               dprintk(4, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
+                       __func__, num, msgs[i].addr, msgs[i].len);
+               if (msgs[i].flags & I2C_M_RD) {
+                       /* read */
+                       retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
+               } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
+                          msgs[i].addr == msgs[i + 1].addr) {
+                       /* write then read from same address */
+                       retval = i2c_sendbytes(i2c_adap, &msgs[i],
+                                              msgs[i + 1].len);
+                       if (retval < 0)
+                               goto err;
+                       i++;
+                       retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
+               } else {
+                       /* write */
+                       retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
+               }
+               if (retval < 0)
+                       goto err;
+       }
+       return num;
+
+err:
+       return retval;
+}
+
+static u32 au0828_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm au0828_i2c_algo_template = {
+       .master_xfer    = i2c_xfer,
+       .functionality  = au0828_functionality,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_adapter au0828_i2c_adap_template = {
+       .name              = DRIVER_NAME,
+       .owner             = THIS_MODULE,
+       .algo              = &au0828_i2c_algo_template,
+};
+
+static struct i2c_client au0828_i2c_client_template = {
+       .name   = "au0828 internal",
+};
+
+static char *i2c_devs[128] = {
+       [0x8e >> 1] = "au8522",
+       [0xa0 >> 1] = "eeprom",
+       [0xc2 >> 1] = "tuner/xc5000",
+};
+
+static void do_i2c_scan(char *name, struct i2c_client *c)
+{
+       unsigned char buf;
+       int i, rc;
+
+       for (i = 0; i < 128; i++) {
+               c->addr = i;
+               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] : "???");
+       }
+}
+
+/* init + register i2c adapter */
+int au0828_i2c_register(struct au0828_dev *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       memcpy(&dev->i2c_adap, &au0828_i2c_adap_template,
+              sizeof(dev->i2c_adap));
+       memcpy(&dev->i2c_algo, &au0828_i2c_algo_template,
+              sizeof(dev->i2c_algo));
+       memcpy(&dev->i2c_client, &au0828_i2c_client_template,
+              sizeof(dev->i2c_client));
+
+       dev->i2c_adap.dev.parent = &dev->usbdev->dev;
+
+       strlcpy(dev->i2c_adap.name, DRIVER_NAME,
+               sizeof(dev->i2c_adap.name));
+
+       dev->i2c_adap.algo = &dev->i2c_algo;
+       dev->i2c_adap.algo_data = dev;
+       i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
+       i2c_add_adapter(&dev->i2c_adap);
+
+       dev->i2c_client.adapter = &dev->i2c_adap;
+
+       if (0 == dev->i2c_rc) {
+               printk(KERN_INFO "%s: i2c bus registered\n", DRIVER_NAME);
+               if (i2c_scan)
+                       do_i2c_scan(DRIVER_NAME, &dev->i2c_client);
+       } else
+               printk(KERN_INFO "%s: i2c bus register FAILED\n", DRIVER_NAME);
+
+       return dev->i2c_rc;
+}
+
+int au0828_i2c_unregister(struct au0828_dev *dev)
+{
+       i2c_del_adapter(&dev->i2c_adap);
+       return 0;
+}
+
diff --git a/drivers/media/usb/au0828/au0828-reg.h b/drivers/media/usb/au0828/au0828-reg.h
new file mode 100644 (file)
index 0000000..2140f4c
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *  Driver for the Auvitek USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
+ *
+ *  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.
+ */
+
+/* We'll start to rename these registers once we have a better
+ * understanding of their meaning.
+ */
+#define REG_000 0x000
+#define REG_001 0x001
+#define REG_002 0x002
+#define REG_003 0x003
+
+#define AU0828_SENSORCTRL_100 0x100
+#define AU0828_SENSORCTRL_VBI_103 0x103
+
+/* I2C registers */
+#define AU0828_I2C_TRIGGER_200         0x200
+#define AU0828_I2C_STATUS_201          0x201
+#define AU0828_I2C_CLK_DIVIDER_202     0x202
+#define AU0828_I2C_DEST_ADDR_203       0x203
+#define AU0828_I2C_WRITE_FIFO_205      0x205
+#define AU0828_I2C_READ_FIFO_209       0x209
+#define AU0828_I2C_MULTIBYTE_MODE_2FF  0x2ff
+
+/* Audio registers */
+#define AU0828_AUDIOCTRL_50C 0x50C
+
+#define REG_600 0x600
+
+/*********************************************************************/
+/* Here are constants for values associated with the above registers */
+
+/* I2C Trigger (Reg 0x200) */
+#define AU0828_I2C_TRIGGER_WRITE       0x01
+#define AU0828_I2C_TRIGGER_READ                0x20
+#define AU0828_I2C_TRIGGER_HOLD                0x40
+
+/* I2C Status (Reg 0x201) */
+#define AU0828_I2C_STATUS_READ_DONE    0x01
+#define AU0828_I2C_STATUS_NO_READ_ACK  0x02
+#define AU0828_I2C_STATUS_WRITE_DONE   0x04
+#define AU0828_I2C_STATUS_NO_WRITE_ACK 0x08
+#define AU0828_I2C_STATUS_BUSY         0x10
+
+/* I2C Clock Divider (Reg 0x202) */
+#define AU0828_I2C_CLK_250KHZ 0x07
+#define AU0828_I2C_CLK_100KHZ 0x14
+#define AU0828_I2C_CLK_30KHZ  0x40
+#define AU0828_I2C_CLK_20KHZ  0x60
diff --git a/drivers/media/usb/au0828/au0828-vbi.c b/drivers/media/usb/au0828/au0828-vbi.c
new file mode 100644 (file)
index 0000000..63f5930
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+   au0828-vbi.c - VBI driver for au0828
+
+   Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
+
+   This work was sponsored by GetWellNetwork Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+
+#include "au0828.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)
+{
+       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);
+
+       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 = dev->vbi_width * dev->vbi_height * 2;
+
+       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)
+{
+       struct au0828_fh     *fh  = q->priv_data;
+       struct au0828_dev    *dev = fh->dev;
+       struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
+       int                  rc = 0;
+
+       buf->vb.size = dev->vbi_width * dev->vbi_height * 2;
+
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.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;
+       }
+
+       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)
+{
+       struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
+       free_buffer(q, buf);
+}
+
+struct videobuf_queue_ops au0828_vbi_qops = {
+       .buf_setup    = vbi_setup,
+       .buf_prepare  = vbi_prepare,
+       .buf_queue    = vbi_queue,
+       .buf_release  = vbi_release,
+};
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
new file mode 100644 (file)
index 0000000..fa0fa9a
--- /dev/null
@@ -0,0 +1,2034 @@
+/*
+ * Auvitek AU0828 USB Bridge (Analog video support)
+ *
+ * Copyright (C) 2009 Devin Heitmueller <dheitmueller@linuxtv.org>
+ * Copyright (C) 2005-2008 Auvitek International, 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/* Developer Notes:
+ *
+ * VBI support is not yet working
+ * The hardware scaler supported is unimplemented
+ * AC97 audio support is unimplemented (only i2s audio mode)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/tuner.h>
+#include "au0828.h"
+#include "au0828-reg.h"
+
+static DEFINE_MUTEX(au0828_sysfs_lock);
+
+/* ------------------------------------------------------------------
+       Videobuf operations
+   ------------------------------------------------------------------*/
+
+static unsigned int isoc_debug;
+module_param(isoc_debug, int, 0644);
+MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
+
+#define au0828_isocdbg(fmt, arg...) \
+do {\
+       if (isoc_debug) { \
+               printk(KERN_INFO "au0828 %s :"fmt, \
+                      __func__ , ##arg);          \
+       } \
+  } while (0)
+
+static inline void print_err_status(struct au0828_dev *dev,
+                                   int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+       if (packet < 0) {
+               au0828_isocdbg("URB status %d [%s].\n", status, errmsg);
+       } else {
+               au0828_isocdbg("URB packet %d, status %d [%s].\n",
+                              packet, status, errmsg);
+       }
+}
+
+static int check_dev(struct au0828_dev *dev)
+{
+       if (dev->dev_state & DEV_DISCONNECTED) {
+               printk(KERN_INFO "v4l2 ioctl: device not present\n");
+               return -ENODEV;
+       }
+
+       if (dev->dev_state & DEV_MISCONFIGURED) {
+               printk(KERN_INFO "v4l2 ioctl: device is misconfigured; "
+                      "close and open it again\n");
+               return -EIO;
+       }
+       return 0;
+}
+
+/*
+ * IRQ callback, called by URB callback
+ */
+static void au0828_irq_callback(struct urb *urb)
+{
+       struct au0828_dmaqueue  *dma_q = urb->context;
+       struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
+       unsigned long flags = 0;
+       int i;
+
+       switch (urb->status) {
+       case 0:             /* success */
+       case -ETIMEDOUT:    /* NAK */
+               break;
+       case -ECONNRESET:   /* kill */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               au0828_isocdbg("au0828_irq_callback called: status kill\n");
+               return;
+       default:            /* unknown error */
+               au0828_isocdbg("urb completition error %d.\n", urb->status);
+               break;
+       }
+
+       /* Copy data from URB */
+       spin_lock_irqsave(&dev->slock, flags);
+       dev->isoc_ctl.isoc_copy(dev, urb);
+       spin_unlock_irqrestore(&dev->slock, flags);
+
+       /* Reset urb buffers */
+       for (i = 0; i < urb->number_of_packets; i++) {
+               urb->iso_frame_desc[i].status = 0;
+               urb->iso_frame_desc[i].actual_length = 0;
+       }
+       urb->status = 0;
+
+       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (urb->status) {
+               au0828_isocdbg("urb resubmit failed (error=%i)\n",
+                              urb->status);
+       }
+}
+
+/*
+ * Stop and Deallocate URBs
+ */
+void au0828_uninit_isoc(struct au0828_dev *dev)
+{
+       struct urb *urb;
+       int i;
+
+       au0828_isocdbg("au0828: called au0828_uninit_isoc\n");
+
+       dev->isoc_ctl.nfields = -1;
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               urb = dev->isoc_ctl.urb[i];
+               if (urb) {
+                       if (!irqs_disabled())
+                               usb_kill_urb(urb);
+                       else
+                               usb_unlink_urb(urb);
+
+                       if (dev->isoc_ctl.transfer_buffer[i]) {
+                               usb_free_coherent(dev->usbdev,
+                                       urb->transfer_buffer_length,
+                                       dev->isoc_ctl.transfer_buffer[i],
+                                       urb->transfer_dma);
+                       }
+                       usb_free_urb(urb);
+                       dev->isoc_ctl.urb[i] = NULL;
+               }
+               dev->isoc_ctl.transfer_buffer[i] = NULL;
+       }
+
+       kfree(dev->isoc_ctl.urb);
+       kfree(dev->isoc_ctl.transfer_buffer);
+
+       dev->isoc_ctl.urb = NULL;
+       dev->isoc_ctl.transfer_buffer = NULL;
+       dev->isoc_ctl.num_bufs = 0;
+}
+
+/*
+ * Allocate URBs and start IRQ
+ */
+int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
+                    int num_bufs, int max_pkt_size,
+                    int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb))
+{
+       struct au0828_dmaqueue *dma_q = &dev->vidq;
+       int i;
+       int sb_size, pipe;
+       struct urb *urb;
+       int j, k;
+       int rc;
+
+       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;
+
+       dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs,  GFP_KERNEL);
+       if (!dev->isoc_ctl.urb) {
+               au0828_isocdbg("cannot alloc memory for usb buffers\n");
+               return -ENOMEM;
+       }
+
+       dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
+                                             GFP_KERNEL);
+       if (!dev->isoc_ctl.transfer_buffer) {
+               au0828_isocdbg("cannot allocate memory for usb transfer\n");
+               kfree(dev->isoc_ctl.urb);
+               return -ENOMEM;
+       }
+
+       dev->isoc_ctl.max_pkt_size = max_pkt_size;
+       dev->isoc_ctl.buf = NULL;
+
+       sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
+
+       /* allocate urbs and transfer buffers */
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               urb = usb_alloc_urb(max_packets, GFP_KERNEL);
+               if (!urb) {
+                       au0828_isocdbg("cannot alloc isoc_ctl.urb %i\n", i);
+                       au0828_uninit_isoc(dev);
+                       return -ENOMEM;
+               }
+               dev->isoc_ctl.urb[i] = urb;
+
+               dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->usbdev,
+                       sb_size, GFP_KERNEL, &urb->transfer_dma);
+               if (!dev->isoc_ctl.transfer_buffer[i]) {
+                       printk("unable to allocate %i bytes for transfer"
+                                       " buffer %i%s\n",
+                                       sb_size, i,
+                                       in_interrupt() ? " while in int" : "");
+                       au0828_uninit_isoc(dev);
+                       return -ENOMEM;
+               }
+               memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
+
+               pipe = usb_rcvisocpipe(dev->usbdev,
+                                      dev->isoc_in_endpointaddr),
+
+               usb_fill_int_urb(urb, dev->usbdev, pipe,
+                                dev->isoc_ctl.transfer_buffer[i], sb_size,
+                                au0828_irq_callback, dma_q, 1);
+
+               urb->number_of_packets = max_packets;
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+
+               k = 0;
+               for (j = 0; j < max_packets; j++) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length =
+                                               dev->isoc_ctl.max_pkt_size;
+                       k += dev->isoc_ctl.max_pkt_size;
+               }
+       }
+
+       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);
+               if (rc) {
+                       au0828_isocdbg("submit of urb %i failed (error=%i)\n",
+                                      i, rc);
+                       au0828_uninit_isoc(dev);
+                       return rc;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Announces that a buffer were filled and request the next
+ */
+static inline void buffer_filled(struct au0828_dev *dev,
+                                 struct au0828_dmaqueue *dma_q,
+                                 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++;
+       do_gettimeofday(&buf->vb.ts);
+
+       dev->isoc_ctl.buf = NULL;
+
+       list_del(&buf->vb.queue);
+       wake_up(&buf->vb.done);
+}
+
+static inline void vbi_buffer_filled(struct au0828_dev *dev,
+                                    struct au0828_dmaqueue *dma_q,
+                                    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++;
+       do_gettimeofday(&buf->vb.ts);
+
+       dev->isoc_ctl.vbi_buf = NULL;
+
+       list_del(&buf->vb.queue);
+       wake_up(&buf->vb.done);
+}
+
+/*
+ * Identify the buffer header type and properly handles
+ */
+static void au0828_copy_video(struct au0828_dev *dev,
+                             struct au0828_dmaqueue  *dma_q,
+                             struct au0828_buffer *buf,
+                             unsigned char *p,
+                             unsigned char *outp, unsigned long len)
+{
+       void *fieldstart, *startwrite, *startread;
+       int  linesdone, currlinedone, offset, lencopy, remain;
+       int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */
+
+       if (len == 0)
+               return;
+
+       if (dma_q->pos + len > buf->vb.size)
+               len = buf->vb.size - dma_q->pos;
+
+       startread = p;
+       remain = len;
+
+       /* Interlaces frame */
+       if (buf->top_field)
+               fieldstart = outp;
+       else
+               fieldstart = outp + bytesperline;
+
+       linesdone = dma_q->pos / bytesperline;
+       currlinedone = dma_q->pos % bytesperline;
+       offset = linesdone * bytesperline * 2 + currlinedone;
+       startwrite = fieldstart + offset;
+       lencopy = bytesperline - currlinedone;
+       lencopy = lencopy > remain ? remain : lencopy;
+
+       if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
+               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;
+               lencopy = remain;
+       }
+       if (lencopy <= 0)
+               return;
+       memcpy(startwrite, startread, lencopy);
+
+       remain -= lencopy;
+
+       while (remain > 0) {
+               startwrite += lencopy + bytesperline;
+               startread += lencopy;
+               if (bytesperline > remain)
+                       lencopy = remain;
+               else
+                       lencopy = bytesperline;
+
+               if ((char *)startwrite + lencopy > (char *)outp +
+                   buf->vb.size) {
+                       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 *)startwrite;
+               }
+               if (lencopy <= 0)
+                       break;
+
+               memcpy(startwrite, startread, lencopy);
+
+               remain -= lencopy;
+       }
+
+       if (offset > 1440) {
+               /* We have enough data to check for greenscreen */
+               if (outp[0] < 0x60 && outp[1440] < 0x60)
+                       dev->greenscreen_detected = 1;
+       }
+
+       dma_q->pos += len;
+}
+
+/*
+ * video-buf generic routine to get the next available buffer
+ */
+static inline void get_next_buf(struct au0828_dmaqueue *dma_q,
+                               struct au0828_buffer **buf)
+{
+       struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
+
+       if (list_empty(&dma_q->active)) {
+               au0828_isocdbg("No active queue to serve\n");
+               dev->isoc_ctl.buf = NULL;
+               *buf = NULL;
+               return;
+       }
+
+       /* Get the next buffer */
+       *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
+       dev->isoc_ctl.buf = *buf;
+
+       return;
+}
+
+static void au0828_copy_vbi(struct au0828_dev *dev,
+                             struct au0828_dmaqueue  *dma_q,
+                             struct au0828_buffer *buf,
+                             unsigned char *p,
+                             unsigned char *outp, unsigned long len)
+{
+       unsigned char *startwrite, *startread;
+       int bytesperline;
+       int i, j = 0;
+
+       if (dev == NULL) {
+               au0828_isocdbg("dev is null\n");
+               return;
+       }
+
+       if (dma_q == NULL) {
+               au0828_isocdbg("dma_q is null\n");
+               return;
+       }
+       if (buf == NULL)
+               return;
+       if (p == NULL) {
+               au0828_isocdbg("p is null\n");
+               return;
+       }
+       if (outp == NULL) {
+               au0828_isocdbg("outp is null\n");
+               return;
+       }
+
+       bytesperline = dev->vbi_width;
+
+       if (dma_q->pos + len > buf->vb.size)
+               len = buf->vb.size - dma_q->pos;
+
+       startread = p;
+       startwrite = outp + (dma_q->pos / 2);
+
+       /* Make sure the bottom field populates the second half of the frame */
+       if (buf->top_field == 0)
+               startwrite += bytesperline * dev->vbi_height;
+
+       for (i = 0; i < len; i += 2)
+               startwrite[j++] = startread[i+1];
+
+       dma_q->pos += len;
+}
+
+
+/*
+ * video-buf generic routine to get the next available VBI buffer
+ */
+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");
+               dev->isoc_ctl.vbi_buf = NULL;
+               *buf = NULL;
+               return;
+       }
+
+       /* Get the next buffer */
+       *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
+       /* Cleans up buffer - Useful for testing for frame/URB loss */
+       outp = videobuf_to_vmalloc(&(*buf)->vb);
+       memset(outp, 0x00, (*buf)->vb.size);
+
+       dev->isoc_ctl.vbi_buf = *buf;
+
+       return;
+}
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
+{
+       struct au0828_buffer    *buf;
+       struct au0828_buffer    *vbi_buf;
+       struct au0828_dmaqueue  *dma_q = urb->context;
+       struct au0828_dmaqueue  *vbi_dma_q = &dev->vbiq;
+       unsigned char *outp = NULL;
+       unsigned char *vbioutp = NULL;
+       int i, len = 0, rc = 1;
+       unsigned char *p;
+       unsigned char fbyte;
+       unsigned int vbi_field_size;
+       unsigned int remain, lencopy;
+
+       if (!dev)
+               return 0;
+
+       if ((dev->dev_state & DEV_DISCONNECTED) ||
+           (dev->dev_state & DEV_MISCONFIGURED))
+               return 0;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               if (urb->status == -ENOENT)
+                       return 0;
+       }
+
+       buf = dev->isoc_ctl.buf;
+       if (buf != NULL)
+               outp = videobuf_to_vmalloc(&buf->vb);
+
+       vbi_buf = dev->isoc_ctl.vbi_buf;
+       if (vbi_buf != NULL)
+               vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               int status = urb->iso_frame_desc[i].status;
+
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       if (urb->iso_frame_desc[i].status != -EPROTO)
+                               continue;
+               }
+
+               if (urb->iso_frame_desc[i].actual_length <= 0)
+                       continue;
+
+               if (urb->iso_frame_desc[i].actual_length >
+                                               dev->max_pkt_size) {
+                       au0828_isocdbg("packet bigger than packet size");
+                       continue;
+               }
+
+               p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+               fbyte = p[0];
+               len = urb->iso_frame_desc[i].actual_length - 4;
+               p += 4;
+
+               if (fbyte & 0x80) {
+                       len -= 4;
+                       p += 4;
+                       au0828_isocdbg("Video frame %s\n",
+                                      (fbyte & 0x40) ? "odd" : "even");
+                       if (fbyte & 0x40) {
+                               /* VBI */
+                               if (vbi_buf != NULL)
+                                       vbi_buffer_filled(dev,
+                                                         vbi_dma_q,
+                                                         vbi_buf);
+                               vbi_get_next_buf(vbi_dma_q, &vbi_buf);
+                               if (vbi_buf == NULL)
+                                       vbioutp = NULL;
+                               else
+                                       vbioutp = videobuf_to_vmalloc(
+                                               &vbi_buf->vb);
+
+                               /* Video */
+                               if (buf != NULL)
+                                       buffer_filled(dev, dma_q, buf);
+                               get_next_buf(dma_q, &buf);
+                               if (buf == NULL)
+                                       outp = NULL;
+                               else
+                                       outp = videobuf_to_vmalloc(&buf->vb);
+
+                               /* As long as isoc traffic is arriving, keep
+                                  resetting the timer */
+                               if (dev->vid_timeout_running)
+                                       mod_timer(&dev->vid_timeout,
+                                                 jiffies + (HZ / 10));
+                               if (dev->vbi_timeout_running)
+                                       mod_timer(&dev->vbi_timeout,
+                                                 jiffies + (HZ / 10));
+                       }
+
+                       if (buf != NULL) {
+                               if (fbyte & 0x40)
+                                       buf->top_field = 1;
+                               else
+                                       buf->top_field = 0;
+                       }
+
+                       if (vbi_buf != NULL) {
+                               if (fbyte & 0x40)
+                                       vbi_buf->top_field = 1;
+                               else
+                                       vbi_buf->top_field = 0;
+                       }
+
+                       dev->vbi_read = 0;
+                       vbi_dma_q->pos = 0;
+                       dma_q->pos = 0;
+               }
+
+               vbi_field_size = dev->vbi_width * dev->vbi_height * 2;
+               if (dev->vbi_read < vbi_field_size) {
+                       remain  = vbi_field_size - dev->vbi_read;
+                       if (len < remain)
+                               lencopy = len;
+                       else
+                               lencopy = remain;
+
+                       if (vbi_buf != NULL)
+                               au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
+                                               vbioutp, len);
+
+                       len -= lencopy;
+                       p += lencopy;
+                       dev->vbi_read += lencopy;
+               }
+
+               if (dev->vbi_read >= vbi_field_size && buf != NULL)
+                       au0828_copy_video(dev, dma_q, buf, p, outp, len);
+       }
+       return rc;
+}
+
+static int
+buffer_setup(struct videobuf_queue *vq, unsigned int *count,
+            unsigned int *size)
+{
+       struct au0828_fh *fh = vq->priv_data;
+       *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
+
+       if (0 == *count)
+               *count = AU0828_DEF_BUF;
+
+       if (*count < AU0828_MIN_BUF)
+               *count = AU0828_MIN_BUF;
+       return 0;
+}
+
+/* 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;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+                                               enum v4l2_field field)
+{
+       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;
+
+       buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
+
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+               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) {
+                       printk(KERN_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) {
+                       printk(KERN_INFO "au0828_init_isoc failed\n");
+                       goto fail;
+               }
+       }
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+fail:
+       free_buffer(vq, buf);
+       return rc;
+}
+
+static void
+buffer_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  *vidq    = &dev->vidq;
+
+       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);
+
+       free_buffer(vq, buf);
+}
+
+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 */
+       au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01);
+       return 0;
+}
+
+/*
+ * Auvitek au0828 analog stream enable
+ * Please set interface0 to AS5 before enable the stream
+ */
+int au0828_analog_stream_enable(struct au0828_dev *d)
+{
+       dprintk(1, "au0828_analog_stream_enable called\n");
+       au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
+       au0828_writereg(d, 0x106, 0x00);
+       /* set x position */
+       au0828_writereg(d, 0x110, 0x00);
+       au0828_writereg(d, 0x111, 0x00);
+       au0828_writereg(d, 0x114, 0xa0);
+       au0828_writereg(d, 0x115, 0x05);
+       /* set y position */
+       au0828_writereg(d, 0x112, 0x00);
+       au0828_writereg(d, 0x113, 0x00);
+       au0828_writereg(d, 0x116, 0xf2);
+       au0828_writereg(d, 0x117, 0x00);
+       au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
+
+       return 0;
+}
+
+int au0828_analog_stream_disable(struct au0828_dev *d)
+{
+       dprintk(1, "au0828_analog_stream_disable called\n");
+       au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0);
+       return 0;
+}
+
+void au0828_analog_stream_reset(struct au0828_dev *dev)
+{
+       dprintk(1, "au0828_analog_stream_reset called\n");
+       au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);
+       mdelay(30);
+       au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3);
+}
+
+/*
+ * Some operations needs to stop current streaming
+ */
+static int au0828_stream_interrupt(struct au0828_dev *dev)
+{
+       int ret = 0;
+
+       dev->stream_state = STREAM_INTERRUPT;
+       if (dev->dev_state == DEV_DISCONNECTED)
+               return -ENODEV;
+       else if (ret) {
+               dev->dev_state = DEV_MISCONFIGURED;
+               dprintk(1, "%s device is misconfigured!\n", __func__);
+               return ret;
+       }
+       return 0;
+}
+
+/*
+ * au0828_release_resources
+ * unregister v4l2 devices
+ */
+void au0828_analog_unregister(struct au0828_dev *dev)
+{
+       dprintk(1, "au0828_release_resources 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);
+}
+
+
+/* Usage lock check functions */
+static int res_get(struct au0828_fh *fh, unsigned int bit)
+{
+       struct au0828_dev    *dev = fh->dev;
+
+       if (fh->resources & bit)
+               /* have it already allocated */
+               return 1;
+
+       /* is it free? */
+       if (dev->resources & bit) {
+               /* no, someone else uses it */
+               return 0;
+       }
+       /* it's free, grab it */
+       fh->resources  |= bit;
+       dev->resources |= bit;
+       dprintk(1, "res: get %d\n", bit);
+
+       return 1;
+}
+
+static int res_check(struct au0828_fh *fh, unsigned int bit)
+{
+       return fh->resources & bit;
+}
+
+static int res_locked(struct au0828_dev *dev, unsigned int bit)
+{
+       return dev->resources & bit;
+}
+
+static void res_free(struct au0828_fh *fh, unsigned int bits)
+{
+       struct au0828_dev    *dev = fh->dev;
+
+       BUG_ON((fh->resources & bits) != bits);
+
+       fh->resources  &= ~bits;
+       dev->resources &= ~bits;
+       dprintk(1, "res: put %d\n", bits);
+}
+
+static int get_ressource(struct au0828_fh *fh)
+{
+       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;
+       }
+}
+
+/* This function ensures that video frames continue to be delivered even if
+   the ITU-656 input isn't receiving any data (thereby preventing applications
+   such as tvtime from hanging) */
+void au0828_vid_buffer_timeout(unsigned long data)
+{
+       struct au0828_dev *dev = (struct au0828_dev *) data;
+       struct au0828_dmaqueue *dma_q = &dev->vidq;
+       struct au0828_buffer *buf;
+       unsigned char *vid_data;
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&dev->slock, flags);
+
+       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 */
+               buffer_filled(dev, dma_q, buf);
+       }
+       get_next_buf(dma_q, &buf);
+
+       if (dev->vid_timeout_running == 1)
+               mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
+
+       spin_unlock_irqrestore(&dev->slock, flags);
+}
+
+void au0828_vbi_buffer_timeout(unsigned long data)
+{
+       struct au0828_dev *dev = (struct au0828_dev *) data;
+       struct au0828_dmaqueue *dma_q = &dev->vbiq;
+       struct au0828_buffer *buf;
+       unsigned char *vbi_data;
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&dev->slock, flags);
+
+       buf = dev->isoc_ctl.vbi_buf;
+       if (buf != NULL) {
+               vbi_data = videobuf_to_vmalloc(&buf->vb);
+               memset(vbi_data, 0x00, buf->vb.size);
+               vbi_buffer_filled(dev, dma_q, buf);
+       }
+       vbi_get_next_buf(dma_q, &buf);
+
+       if (dev->vbi_timeout_running == 1)
+               mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
+       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;
+       }
+
+       fh->type = type;
+       fh->dev = dev;
+       filp->private_data = fh;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
+               /* set au0828 interface0 to AS5 here again */
+               ret = usb_set_interface(dev->usbdev, 0, 5);
+               if (ret < 0) {
+                       printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
+                       return -EBUSY;
+               }
+               dev->width = NTSC_STD_W;
+               dev->height = NTSC_STD_H;
+               dev->frame_size = dev->width * dev->height * 2;
+               dev->field_size = dev->width * dev->height;
+               dev->bytesperline = dev->width * 2;
+
+               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++;
+
+       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 */
+       dev->vbi_width = 720;
+       dev->vbi_height = 1;
+       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);
+       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;
+
+       if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
+               /* 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)) {
+               /* 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) {
+               if (dev->dev_state & DEV_DISCONNECTED) {
+                       au0828_analog_unregister(dev);
+                       kfree(dev);
+                       return 0;
+               }
+
+               au0828_analog_stream_disable(dev);
+
+               au0828_uninit_isoc(dev);
+
+               /* Save some power by putting tuner to sleep */
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
+
+               /* When close the device, set the usb intf0 into alt0 to free
+                  USB bandwidth */
+               ret = usb_set_interface(dev->usbdev, 0, 0);
+               if (ret < 0)
+                       printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
+       }
+
+       videobuf_mmap_free(&fh->vb_vidq);
+       videobuf_mmap_free(&fh->vb_vbiq);
+       kfree(fh);
+       dev->users--;
+       wake_up_interruptible_nr(&dev->open, 1);
+       return 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 (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;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               if (!res_get(fh, AU0828_RESOURCE_VIDEO))
+                       return POLLERR;
+               return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
+       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+               if (!res_get(fh, AU0828_RESOURCE_VBI))
+                       return POLLERR;
+               return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
+       } else {
+               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)
+{
+       int ret;
+       int width = format->fmt.pix.width;
+       int height = format->fmt.pix.height;
+
+       if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       /* If they are demanding a format other than the one we support,
+          bail out (tvtime asks for UYVY and then retries with YUYV) */
+       if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
+               return -EINVAL;
+
+       /* format->fmt.pix.width only support 720 and height 480 */
+       if (width != 720)
+               width = 720;
+       if (height != 480)
+               height = 480;
+
+       format->fmt.pix.width = width;
+       format->fmt.pix.height = height;
+       format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
+       format->fmt.pix.bytesperline = width * 2;
+       format->fmt.pix.sizeimage = width * height * 2;
+       format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+       format->fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+       if (cmd == VIDIOC_TRY_FMT)
+               return 0;
+
+       /* maybe set new image format, driver current only support 720*480 */
+       dev->width = width;
+       dev->height = height;
+       dev->frame_size = width * height * 2;
+       dev->field_size = width * height;
+       dev->bytesperline = width * 2;
+
+       if (dev->stream_state == STREAM_ON) {
+               dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");
+               ret = au0828_stream_interrupt(dev);
+               if (ret != 0) {
+                       dprintk(1, "error interrupting video stream!\n");
+                       return ret;
+               }
+       }
+
+       /* set au0828 interface0 to AS5 here again */
+       ret = usb_set_interface(dev->usbdev, 0, 5);
+       if (ret < 0) {
+               printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
+               return -EBUSY;
+       }
+
+       au0828_analog_stream_enable(dev);
+
+       return 0;
+}
+
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+                           struct v4l2_queryctrl *qc)
+{
+       struct au0828_fh *fh = priv;
+       struct au0828_dev *dev = fh->dev;
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
+       if (qc->type)
+               return 0;
+       else
+               return -EINVAL;
+}
+
+static int vidioc_querycap(struct file *file, void  *priv,
+                          struct v4l2_capability *cap)
+{
+       struct au0828_fh *fh  = priv;
+       struct au0828_dev *dev = fh->dev;
+
+       strlcpy(cap->driver, "au0828", sizeof(cap->driver));
+       strlcpy(cap->card, dev->board.name, sizeof(cap->card));
+       strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
+
+       /*set the device capabilities */
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_VBI_CAPTURE |
+               V4L2_CAP_AUDIO |
+               V4L2_CAP_READWRITE |
+               V4L2_CAP_STREAMING |
+               V4L2_CAP_TUNER;
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       if (f->index)
+               return -EINVAL;
+
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       strcpy(f->description, "Packed YUV2");
+
+       f->flags = 0;
+       f->pixelformat = V4L2_PIX_FMT_UYVY;
+
+       return 0;
+}
+
+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;
+
+       f->fmt.pix.width = dev->width;
+       f->fmt.pix.height = dev->height;
+       f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
+       f->fmt.pix.bytesperline = dev->bytesperline;
+       f->fmt.pix.sizeimage = dev->frame_size;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
+       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+       return 0;
+}
+
+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;
+
+       return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
+}
+
+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;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+               printk(KERN_INFO "%s queue busy\n", __func__);
+               rc = -EBUSY;
+               goto out;
+       }
+
+       rc = au0828_set_format(dev, VIDIOC_S_FMT, f);
+out:
+       return rc;
+}
+
+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;
+
+       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
+               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1);
+
+       /* FIXME: when we support something other than NTSC, we are going to
+          have to make the au0828 bridge adjust the size of its capture
+          buffer, which is currently hardcoded at 720x480 */
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);
+       dev->std_set_in_tuner_core = 1;
+
+       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
+               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0);
+
+       return 0;
+}
+
+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;
+       unsigned int tmp;
+
+       static const char *inames[] = {
+               [AU0828_VMUX_UNDEFINED] = "Undefined",
+               [AU0828_VMUX_COMPOSITE] = "Composite",
+               [AU0828_VMUX_SVIDEO] = "S-Video",
+               [AU0828_VMUX_CABLE] = "Cable TV",
+               [AU0828_VMUX_TELEVISION] = "Television",
+               [AU0828_VMUX_DVB] = "DVB",
+               [AU0828_VMUX_DEBUG] = "tv debug"
+       };
+
+       tmp = input->index;
+
+       if (tmp >= AU0828_MAX_INPUT)
+               return -EINVAL;
+       if (AUVI_INPUT(tmp).type == 0)
+               return -EINVAL;
+
+       input->index = tmp;
+       strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
+       if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
+           (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
+               input->type |= V4L2_INPUT_TYPE_TUNER;
+       else
+               input->type |= V4L2_INPUT_TYPE_CAMERA;
+
+       input->std = dev->vdev->tvnorms;
+
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct au0828_fh *fh = priv;
+       struct au0828_dev *dev = fh->dev;
+       *i = dev->ctrl_input;
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
+{
+       struct au0828_fh *fh = priv;
+       struct au0828_dev *dev = fh->dev;
+       int i;
+
+       dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
+               index);
+       if (index >= AU0828_MAX_INPUT)
+               return -EINVAL;
+       if (AUVI_INPUT(index).type == 0)
+               return -EINVAL;
+       dev->ctrl_input = index;
+
+       switch (AUVI_INPUT(index).type) {
+       case AU0828_VMUX_SVIDEO:
+               dev->input_type = AU0828_VMUX_SVIDEO;
+               break;
+       case AU0828_VMUX_COMPOSITE:
+               dev->input_type = AU0828_VMUX_COMPOSITE;
+               break;
+       case AU0828_VMUX_TELEVISION:
+               dev->input_type = AU0828_VMUX_TELEVISION;
+               break;
+       default:
+               dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",
+                       AUVI_INPUT(index).type);
+               break;
+       }
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
+                       AUVI_INPUT(index).vmux, 0, 0);
+
+       for (i = 0; i < AU0828_MAX_INPUT; i++) {
+               int enable = 0;
+               if (AUVI_INPUT(i).audio_setup == NULL)
+                       continue;
+
+               if (i == index)
+                       enable = 1;
+               else
+                       enable = 0;
+               if (enable) {
+                       (AUVI_INPUT(i).audio_setup)(dev, enable);
+               } else {
+                       /* Make sure we leave it turned on if some
+                          other input is routed to this callback */
+                       if ((AUVI_INPUT(i).audio_setup) !=
+                           ((AUVI_INPUT(index).audio_setup))) {
+                               (AUVI_INPUT(i).audio_setup)(dev, enable);
+                       }
+               }
+       }
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
+                       AUVI_INPUT(index).amux, 0, 0);
+       return 0;
+}
+
+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;
+       unsigned int index = a->index;
+
+       if (a->index > 1)
+               return -EINVAL;
+
+       index = dev->ctrl_ainput;
+       if (index == 0)
+               strcpy(a->name, "Television");
+       else
+               strcpy(a->name, "Line in");
+
+       a->capability = V4L2_AUDCAP_STEREO;
+       a->index = index;
+       return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+       struct au0828_fh *fh = priv;
+       struct au0828_dev *dev = fh->dev;
+       if (a->index != dev->ctrl_ainput)
+               return -EINVAL;
+       return 0;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+                        struct v4l2_control *ctrl)
+{
+       struct au0828_fh *fh = priv;
+       struct au0828_dev *dev = fh->dev;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
+       return 0;
+
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctrl)
+{
+       struct au0828_fh *fh = priv;
+       struct au0828_dev *dev = fh->dev;
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
+       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;
+
+       if (t->index != 0)
+               return -EINVAL;
+
+       strcpy(t->name, "Auvitek tuner");
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
+       return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct au0828_fh *fh = priv;
+       struct au0828_dev *dev = fh->dev;
+
+       if (t->index != 0)
+               return -EINVAL;
+
+       t->type = V4L2_TUNER_ANALOG_TV;
+
+       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
+               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1);
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
+
+       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
+               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0);
+
+       dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
+               t->afc);
+
+       return 0;
+
+}
+
+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;
+
+       freq->type = V4L2_TUNER_ANALOG_TV;
+       freq->frequency = dev->ctrl_freq;
+       return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *freq)
+{
+       struct au0828_fh *fh = priv;
+       struct au0828_dev *dev = fh->dev;
+
+       if (freq->tuner != 0)
+               return -EINVAL;
+       if (freq->type != V4L2_TUNER_ANALOG_TV)
+               return -EINVAL;
+
+       dev->ctrl_freq = freq->frequency;
+
+       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
+               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1);
+
+       if (dev->std_set_in_tuner_core == 0) {
+         /* If we've never sent the standard in tuner core, do so now.  We
+            don't do this at device probe because we don't want to incur
+            the cost of a firmware load */
+         v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std,
+                              dev->vdev->tvnorms);
+         dev->std_set_in_tuner_core = 1;
+       }
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
+
+       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
+               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0);
+
+       au0828_analog_stream_reset(dev);
+
+       return 0;
+}
+
+
+/* RAW VBI ioctls */
+
+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;
+
+       format->fmt.vbi.samples_per_line = dev->vbi_width;
+       format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+       format->fmt.vbi.offset = 0;
+       format->fmt.vbi.flags = 0;
+       format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
+
+       format->fmt.vbi.count[0] = dev->vbi_height;
+       format->fmt.vbi.count[1] = dev->vbi_height;
+       format->fmt.vbi.start[0] = 21;
+       format->fmt.vbi.start[1] = 284;
+
+       return 0;
+}
+
+static int vidioc_g_chip_ident(struct file *file, void *priv,
+              struct v4l2_dbg_chip_ident *chip)
+{
+       struct au0828_fh *fh = priv;
+       struct au0828_dev *dev = fh->dev;
+       chip->ident = V4L2_IDENT_NONE;
+       chip->revision = 0;
+
+       if (v4l2_chip_match_host(&chip->match)) {
+               chip->ident = V4L2_IDENT_AU0828;
+               return 0;
+       }
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
+       if (chip->ident == V4L2_IDENT_NONE)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int vidioc_cropcap(struct file *file, void *priv,
+                         struct v4l2_cropcap *cc)
+{
+       struct au0828_fh *fh = priv;
+       struct au0828_dev *dev = fh->dev;
+
+       if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       cc->bounds.left = 0;
+       cc->bounds.top = 0;
+       cc->bounds.width = dev->width;
+       cc->bounds.height = dev->height;
+
+       cc->defrect = cc->bounds;
+
+       cc->pixelaspect.numerator = 54;
+       cc->pixelaspect.denominator = 59;
+
+       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;
+
+       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);
+
+               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;
+
+       switch (reg->match.type) {
+       case V4L2_CHIP_MATCH_I2C_DRIVER:
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
+               return 0;
+       default:
+               if (!v4l2_chip_match_host(&reg->match))
+                       return -EINVAL;
+       }
+
+       reg->val = au0828_read(dev, reg->reg);
+       return 0;
+}
+
+static int vidioc_s_register(struct file *file, void *priv,
+                            struct v4l2_dbg_register *reg)
+{
+       struct au0828_fh *fh = priv;
+       struct au0828_dev *dev = fh->dev;
+
+       switch (reg->match.type) {
+       case V4L2_CHIP_MATCH_I2C_DRIVER:
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
+               return 0;
+       default:
+               if (!v4l2_chip_match_host(&reg->match))
+                       return -EINVAL;
+       }
+       return au0828_writereg(dev, reg->reg, reg->val);
+}
+#endif
+
+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;
+}
+
+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,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+       .vidioc_querycap            = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap    = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap       = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap     = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,
+       .vidioc_g_fmt_vbi_cap       = vidioc_g_fmt_vbi_cap,
+       .vidioc_s_fmt_vbi_cap       = vidioc_g_fmt_vbi_cap,
+       .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_s_std               = vidioc_s_std,
+       .vidioc_enum_input          = vidioc_enum_input,
+       .vidioc_g_input             = vidioc_g_input,
+       .vidioc_s_input             = vidioc_s_input,
+       .vidioc_queryctrl           = vidioc_queryctrl,
+       .vidioc_g_ctrl              = vidioc_g_ctrl,
+       .vidioc_s_ctrl              = vidioc_s_ctrl,
+       .vidioc_streamon            = vidioc_streamon,
+       .vidioc_streamoff           = vidioc_streamoff,
+       .vidioc_g_tuner             = vidioc_g_tuner,
+       .vidioc_s_tuner             = vidioc_s_tuner,
+       .vidioc_g_frequency         = vidioc_g_frequency,
+       .vidioc_s_frequency         = vidioc_s_frequency,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register          = vidioc_g_register,
+       .vidioc_s_register          = vidioc_s_register,
+#endif
+       .vidioc_g_chip_ident        = vidioc_g_chip_ident,
+};
+
+static const struct video_device au0828_video_template = {
+       .fops                       = &au0828_v4l_fops,
+       .release                    = video_device_release,
+       .ioctl_ops                  = &video_ioctl_ops,
+       .tvnorms                    = V4L2_STD_NTSC_M,
+       .current_norm               = V4L2_STD_NTSC_M,
+};
+
+/**************************************************************************/
+
+int au0828_analog_register(struct au0828_dev *dev,
+                          struct usb_interface *interface)
+{
+       int retval = -ENOMEM;
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       int i, ret;
+
+       dprintk(1, "au0828_analog_register called!\n");
+
+       /* set au0828 usb interface0 to as5 */
+       retval = usb_set_interface(dev->usbdev,
+                       interface->cur_altsetting->desc.bInterfaceNumber, 5);
+       if (retval != 0) {
+               printk(KERN_INFO "Failure setting usb interface0 to as5\n");
+               return retval;
+       }
+
+       /* Figure out which endpoint has the isoc interface */
+       iface_desc = interface->cur_altsetting;
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+               endpoint = &iface_desc->endpoint[i].desc;
+               if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+                    == USB_DIR_IN) &&
+                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+                    == USB_ENDPOINT_XFER_ISOC)) {
+
+                       /* we find our isoc in endpoint */
+                       u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
+                       dev->max_pkt_size = (tmp & 0x07ff) *
+                               (((tmp & 0x1800) >> 11) + 1);
+                       dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
+               }
+       }
+       if (!(dev->isoc_in_endpointaddr)) {
+               printk(KERN_INFO "Could not locate isoc endpoint\n");
+               kfree(dev);
+               return -ENODEV;
+       }
+
+       init_waitqueue_head(&dev->open);
+       spin_lock_init(&dev->slock);
+
+       /* 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);
+
+       dev->width = NTSC_STD_W;
+       dev->height = NTSC_STD_H;
+       dev->field_size = dev->width * dev->height;
+       dev->frame_size = dev->field_size << 1;
+       dev->bytesperline = dev->width << 1;
+       dev->ctrl_ainput = 0;
+
+       /* allocate and fill v4l2 video struct */
+       dev->vdev = video_device_alloc();
+       if (NULL == dev->vdev) {
+               dprintk(1, "Can't allocate video_device.\n");
+               return -ENOMEM;
+       }
+
+       /* allocate the VBI struct */
+       dev->vbi_dev = video_device_alloc();
+       if (NULL == dev->vbi_dev) {
+               dprintk(1, "Can't allocate vbi_device.\n");
+               ret = -ENOMEM;
+               goto err_vdev;
+       }
+
+       /* Fill the video capture device struct */
+       *dev->vdev = au0828_video_template;
+       dev->vdev->parent = &dev->usbdev->dev;
+       dev->vdev->lock = &dev->lock;
+       strcpy(dev->vdev->name, "au0828a video");
+
+       /* Setup the VBI device */
+       *dev->vbi_dev = au0828_video_template;
+       dev->vbi_dev->parent = &dev->usbdev->dev;
+       dev->vbi_dev->lock = &dev->lock;
+       strcpy(dev->vbi_dev->name, "au0828a vbi");
+
+       /* Register the v4l2 device */
+       video_set_drvdata(dev->vdev, dev);
+       retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
+       if (retval != 0) {
+               dprintk(1, "unable to register video device (error = %d).\n",
+                       retval);
+               ret = -ENODEV;
+               goto err_vbi_dev;
+       }
+
+       /* Register the vbi device */
+       video_set_drvdata(dev->vbi_dev, dev);
+       retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
+       if (retval != 0) {
+               dprintk(1, "unable to register vbi device (error = %d).\n",
+                       retval);
+               ret = -ENODEV;
+               goto err_vbi_dev;
+       }
+
+       dprintk(1, "%s completed!\n", __func__);
+
+       return 0;
+
+err_vbi_dev:
+       video_device_release(dev->vbi_dev);
+err_vdev:
+       video_device_release(dev->vdev);
+       return ret;
+}
+
diff --git a/drivers/media/usb/au0828/au0828.h b/drivers/media/usb/au0828/au0828.h
new file mode 100644 (file)
index 0000000..66a56ef
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ *  Driver for the Auvitek AU0828 USB bridge
+ *
+ *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
+ *
+ *  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/usb.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <media/tveeprom.h>
+
+/* Analog */
+#include <linux/videodev2.h>
+#include <media/videobuf-vmalloc.h>
+#include <media/v4l2-device.h>
+
+/* DVB */
+#include "demux.h"
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dvb_net.h"
+#include "dvbdev.h"
+
+#include "au0828-reg.h"
+#include "au0828-cards.h"
+
+#define DRIVER_NAME "au0828"
+#define URB_COUNT   16
+#define URB_BUFSIZE (0xe522)
+
+/* Analog constants */
+#define NTSC_STD_W      720
+#define NTSC_STD_H      480
+
+#define AU0828_INTERLACED_DEFAULT       1
+#define V4L2_CID_PRIVATE_SHARPNESS  (V4L2_CID_PRIVATE_BASE + 0)
+
+/* Defination for AU0828 USB transfer */
+#define AU0828_MAX_ISO_BUFS    12  /* maybe resize this value in the future */
+#define AU0828_ISO_PACKETS_PER_URB      128
+
+#define AU0828_MIN_BUF 4
+#define AU0828_DEF_BUF 8
+
+#define AU0828_MAX_INPUT        4
+
+/* au0828 resource types (used for res_get/res_lock etc */
+#define AU0828_RESOURCE_VIDEO 0x01
+#define AU0828_RESOURCE_VBI   0x02
+
+enum au0828_itype {
+       AU0828_VMUX_UNDEFINED = 0,
+       AU0828_VMUX_COMPOSITE,
+       AU0828_VMUX_SVIDEO,
+       AU0828_VMUX_CABLE,
+       AU0828_VMUX_TELEVISION,
+       AU0828_VMUX_DVB,
+       AU0828_VMUX_DEBUG
+};
+
+struct au0828_input {
+       enum au0828_itype type;
+       unsigned int vmux;
+       unsigned int amux;
+       void (*audio_setup) (void *priv, int enable);
+};
+
+struct au0828_board {
+       char *name;
+       unsigned int tuner_type;
+       unsigned char tuner_addr;
+       unsigned char i2c_clk_divider;
+       struct au0828_input input[AU0828_MAX_INPUT];
+
+};
+
+struct au0828_dvb {
+       struct mutex lock;
+       struct dvb_adapter adapter;
+       struct dvb_frontend *frontend;
+       struct dvb_demux demux;
+       struct dmxdev dmxdev;
+       struct dmx_frontend fe_hw;
+       struct dmx_frontend fe_mem;
+       struct dvb_net net;
+       int feeding;
+};
+
+enum au0828_stream_state {
+       STREAM_OFF,
+       STREAM_INTERRUPT,
+       STREAM_ON
+};
+
+#define AUVI_INPUT(nr) (dev->board.input[nr])
+
+/* device state */
+enum au0828_dev_state {
+       DEV_INITIALIZED = 0x01,
+       DEV_DISCONNECTED = 0x02,
+       DEV_MISCONFIGURED = 0x04
+};
+
+struct au0828_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_usb_isoc_ctl {
+               /* max packet size of isoc transaction */
+       int                             max_pkt_size;
+
+               /* number of allocated urbs */
+       int                             num_bufs;
+
+               /* urb for isoc transfers */
+       struct urb                      **urb;
+
+               /* transfer buffers for isoc transfer */
+       char                            **transfer_buffer;
+
+               /* Last buffer command and region */
+       u8                              cmd;
+       int                             pos, size, pktsize;
+
+               /* Last field: ODD or EVEN? */
+       int                             field;
+
+               /* Stores incomplete commands */
+       u32                             tmp_buf;
+       int                             tmp_buf_len;
+
+               /* Stores already requested buffers */
+       struct au0828_buffer            *buf;
+       struct au0828_buffer            *vbi_buf;
+
+               /* Stores the number of received fields */
+       int                             nfields;
+
+               /* isoc urb callback */
+       int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb);
+
+};
+
+/* buffer for one video frame */
+struct au0828_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+
+       struct list_head frame;
+       int top_field;
+       int receiving;
+};
+
+struct au0828_dmaqueue {
+       struct list_head       active;
+       struct list_head       queued;
+
+       wait_queue_head_t          wq;
+
+       /* Counters to control buffer fill */
+       int                        pos;
+};
+
+struct au0828_dev {
+       struct mutex mutex;
+       struct usb_device       *usbdev;
+       int                     boardnr;
+       struct au0828_board     board;
+       u8                      ctrlmsg[64];
+
+       /* I2C */
+       struct i2c_adapter              i2c_adap;
+       struct i2c_algorithm            i2c_algo;
+       struct i2c_client               i2c_client;
+       u32                             i2c_rc;
+
+       /* Digital */
+       struct au0828_dvb               dvb;
+       struct work_struct              restart_streaming;
+
+       /* Analog */
+       struct v4l2_device v4l2_dev;
+       int users;
+       unsigned int resources; /* resources in use */
+       struct video_device *vdev;
+       struct video_device *vbi_dev;
+       struct timer_list vid_timeout;
+       int vid_timeout_running;
+       struct timer_list vbi_timeout;
+       int vbi_timeout_running;
+       int width;
+       int height;
+       int vbi_width;
+       int vbi_height;
+       u32 vbi_read;
+       u32 field_size;
+       u32 frame_size;
+       u32 bytesperline;
+       int type;
+       u8 ctrl_ainput;
+       __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;
+       unsigned int ctrl_input;
+       enum au0828_dev_state dev_state;
+       enum au0828_stream_state stream_state;
+       wait_queue_head_t open;
+
+       struct mutex lock;
+
+       /* Isoc control struct */
+       struct au0828_dmaqueue vidq;
+       struct au0828_dmaqueue vbiq;
+       struct au0828_usb_isoc_ctl isoc_ctl;
+       spinlock_t slock;
+
+       /* usb transfer */
+       int alt;                /* alternate */
+       int max_pkt_size;       /* max packet size of isoc transaction */
+       int num_alt;            /* Number of alternative settings */
+       unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
+       struct urb *urb[AU0828_MAX_ISO_BUFS];   /* urb for isoc transfers */
+       char *transfer_buffer[AU0828_MAX_ISO_BUFS];/* transfer buffers for isoc
+                                                  transfer */
+
+       /* USB / URB Related */
+       int             urb_streaming;
+       struct urb      *urbs[URB_COUNT];
+};
+
+/* ----------------------------------------------------------- */
+#define au0828_read(dev, reg) au0828_readreg(dev, reg)
+#define au0828_write(dev, reg, value) au0828_writereg(dev, reg, value)
+#define au0828_andor(dev, reg, mask, value)                            \
+        au0828_writereg(dev, reg,                                      \
+       (au0828_readreg(dev, reg) & ~(mask)) | ((value) & (mask)))
+
+#define au0828_set(dev, reg, bit) au0828_andor(dev, (reg), (bit), (bit))
+#define au0828_clear(dev, reg, bit) au0828_andor(dev, (reg), (bit), 0)
+
+/* ----------------------------------------------------------- */
+/* au0828-core.c */
+extern u32 au0828_read(struct au0828_dev *dev, u16 reg);
+extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val);
+extern int au0828_debug;
+
+/* ----------------------------------------------------------- */
+/* au0828-cards.c */
+extern struct au0828_board au0828_boards[];
+extern struct usb_device_id au0828_usb_id_table[];
+extern void au0828_gpio_setup(struct au0828_dev *dev);
+extern int au0828_tuner_callback(void *priv, int component,
+                                int command, int arg);
+extern void au0828_card_setup(struct au0828_dev *dev);
+
+/* ----------------------------------------------------------- */
+/* au0828-i2c.c */
+extern int au0828_i2c_register(struct au0828_dev *dev);
+extern int au0828_i2c_unregister(struct au0828_dev *dev);
+
+/* ----------------------------------------------------------- */
+/* au0828-video.c */
+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);
+
+/* ----------------------------------------------------------- */
+/* au0828-dvb.c */
+extern int au0828_dvb_register(struct au0828_dev *dev);
+extern void au0828_dvb_unregister(struct au0828_dev *dev);
+
+/* au0828-vbi.c */
+extern struct videobuf_queue_ops au0828_vbi_qops;
+
+#define dprintk(level, fmt, arg...)\
+       do { if (au0828_debug & level)\
+               printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\
+       } while (0)
diff --git a/drivers/media/usb/cpia2/Kconfig b/drivers/media/usb/cpia2/Kconfig
new file mode 100644 (file)
index 0000000..66e9283
--- /dev/null
@@ -0,0 +1,9 @@
+config VIDEO_CPIA2
+       tristate "CPiA2 Video For Linux"
+       depends on VIDEO_DEV && USB && VIDEO_V4L2
+       ---help---
+         This is the video4linux driver for cameras based on Vision's CPiA2
+         (Colour Processor Interface ASIC), such as the Digital Blue QX5
+         Microscope. If you have one of these cameras, say Y here
+
+         This driver is also available as a module (cpia2).
diff --git a/drivers/media/usb/cpia2/Makefile b/drivers/media/usb/cpia2/Makefile
new file mode 100644 (file)
index 0000000..828cf1b
--- /dev/null
@@ -0,0 +1,3 @@
+cpia2-objs     := cpia2_v4l.o cpia2_usb.o cpia2_core.o
+
+obj-$(CONFIG_VIDEO_CPIA2) += cpia2.o
diff --git a/drivers/media/usb/cpia2/cpia2.h b/drivers/media/usb/cpia2/cpia2.h
new file mode 100644 (file)
index 0000000..cdef677
--- /dev/null
@@ -0,0 +1,487 @@
+/****************************************************************************
+ *
+ *  Filename: cpia2.h
+ *
+ *  Copyright 2001, STMicrolectronics, Inc.
+ *
+ *  Contact:  steve.miller@st.com
+ *
+ *  Description:
+ *     This is a USB driver for CPiA2 based video cameras.
+ *
+ *     This driver is modelled on the cpia usb driver by
+ *     Jochen Scharrlach and Johannes Erdfeldt.
+ *
+ *  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.
+ *
+ ****************************************************************************/
+
+#ifndef __CPIA2_H__
+#define __CPIA2_H__
+
+#include <linux/videodev2.h>
+#include <linux/usb.h>
+#include <linux/poll.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#include "cpia2_registers.h"
+
+/* define for verbose debug output */
+//#define _CPIA2_DEBUG_
+
+/***
+ * Image defines
+ ***/
+
+/*  Misc constants */
+#define ALLOW_CORRUPT 0                /* Causes collater to discard checksum */
+
+/* USB Transfer mode */
+#define XFER_ISOC 0
+#define XFER_BULK 1
+
+/* USB Alternates */
+#define USBIF_CMDONLY 0
+#define USBIF_BULK 1
+#define USBIF_ISO_1 2  /*  128 bytes/ms */
+#define USBIF_ISO_2 3  /*  384 bytes/ms */
+#define USBIF_ISO_3 4  /*  640 bytes/ms */
+#define USBIF_ISO_4 5  /*  768 bytes/ms */
+#define USBIF_ISO_5 6  /*  896 bytes/ms */
+#define USBIF_ISO_6 7  /* 1023 bytes/ms */
+
+/* Flicker Modes */
+#define NEVER_FLICKER   0
+#define FLICKER_60      60
+#define FLICKER_50      50
+
+/* Debug flags */
+#define DEBUG_NONE          0
+#define DEBUG_REG           0x00000001
+#define DEBUG_DUMP_PATCH    0x00000002
+#define DEBUG_DUMP_REGS     0x00000004
+
+/***
+ * Video frame sizes
+ ***/
+enum {
+       VIDEOSIZE_VGA = 0,      /* 640x480 */
+       VIDEOSIZE_CIF,          /* 352x288 */
+       VIDEOSIZE_QVGA,         /* 320x240 */
+       VIDEOSIZE_QCIF,         /* 176x144 */
+       VIDEOSIZE_288_216,
+       VIDEOSIZE_256_192,
+       VIDEOSIZE_224_168,
+       VIDEOSIZE_192_144,
+};
+
+#define STV_IMAGE_CIF_ROWS    288
+#define STV_IMAGE_CIF_COLS    352
+
+#define STV_IMAGE_QCIF_ROWS   144
+#define STV_IMAGE_QCIF_COLS   176
+
+#define STV_IMAGE_VGA_ROWS    480
+#define STV_IMAGE_VGA_COLS    640
+
+#define STV_IMAGE_QVGA_ROWS   240
+#define STV_IMAGE_QVGA_COLS   320
+
+#define JPEG_MARKER_COM (1<<6) /* Comment segment */
+
+/***
+ * Enums
+ ***/
+/* Sensor types available with cpia2 asics */
+enum sensors {
+       CPIA2_SENSOR_410,
+       CPIA2_SENSOR_500
+};
+
+/* Asic types available in the CPiA2 architecture */
+#define  CPIA2_ASIC_672 0x67
+
+/* Device types (stv672, stv676, etc) */
+#define  DEVICE_STV_672   0x0001
+#define  DEVICE_STV_676   0x0002
+
+enum frame_status {
+       FRAME_EMPTY,
+       FRAME_READING,          /* In the process of being grabbed into */
+       FRAME_READY,            /* Ready to be read */
+       FRAME_ERROR,
+};
+
+/***
+ * Register access (for USB request byte)
+ ***/
+enum {
+       CAMERAACCESS_SYSTEM = 0,
+       CAMERAACCESS_VC,
+       CAMERAACCESS_VP,
+       CAMERAACCESS_IDATA
+};
+
+#define CAMERAACCESS_TYPE_BLOCK    0x00
+#define CAMERAACCESS_TYPE_RANDOM   0x04
+#define CAMERAACCESS_TYPE_MASK     0x08
+#define CAMERAACCESS_TYPE_REPEAT   0x0C
+
+#define TRANSFER_READ 0
+#define TRANSFER_WRITE 1
+
+#define DEFAULT_ALT   USBIF_ISO_6
+#define DEFAULT_BRIGHTNESS 0x46
+#define DEFAULT_CONTRAST 0x93
+#define DEFAULT_SATURATION 0x7f
+
+/* Power state */
+#define HI_POWER_MODE CPIA2_SYSTEM_CONTROL_HIGH_POWER
+#define LO_POWER_MODE CPIA2_SYSTEM_CONTROL_LOW_POWER
+
+
+/********
+ * Commands
+ *******/
+enum {
+       CPIA2_CMD_NONE = 0,
+       CPIA2_CMD_GET_VERSION,
+       CPIA2_CMD_GET_PNP_ID,
+       CPIA2_CMD_GET_ASIC_TYPE,
+       CPIA2_CMD_GET_SENSOR,
+       CPIA2_CMD_GET_VP_DEVICE,
+       CPIA2_CMD_GET_VP_BRIGHTNESS,
+       CPIA2_CMD_SET_VP_BRIGHTNESS,
+       CPIA2_CMD_GET_CONTRAST,
+       CPIA2_CMD_SET_CONTRAST,
+       CPIA2_CMD_GET_VP_SATURATION,
+       CPIA2_CMD_SET_VP_SATURATION,
+       CPIA2_CMD_GET_VP_GPIO_DIRECTION,
+       CPIA2_CMD_SET_VP_GPIO_DIRECTION,
+       CPIA2_CMD_GET_VP_GPIO_DATA,
+       CPIA2_CMD_SET_VP_GPIO_DATA,
+       CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION,
+       CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION,
+       CPIA2_CMD_GET_VC_MP_GPIO_DATA,
+       CPIA2_CMD_SET_VC_MP_GPIO_DATA,
+       CPIA2_CMD_ENABLE_PACKET_CTRL,
+       CPIA2_CMD_GET_FLICKER_MODES,
+       CPIA2_CMD_SET_FLICKER_MODES,
+       CPIA2_CMD_RESET_FIFO,   /* clear fifo and enable stream block */
+       CPIA2_CMD_SET_HI_POWER,
+       CPIA2_CMD_SET_LOW_POWER,
+       CPIA2_CMD_CLEAR_V2W_ERR,
+       CPIA2_CMD_SET_USER_MODE,
+       CPIA2_CMD_GET_USER_MODE,
+       CPIA2_CMD_FRAMERATE_REQ,
+       CPIA2_CMD_SET_COMPRESSION_STATE,
+       CPIA2_CMD_GET_WAKEUP,
+       CPIA2_CMD_SET_WAKEUP,
+       CPIA2_CMD_GET_PW_CONTROL,
+       CPIA2_CMD_SET_PW_CONTROL,
+       CPIA2_CMD_GET_SYSTEM_CTRL,
+       CPIA2_CMD_SET_SYSTEM_CTRL,
+       CPIA2_CMD_GET_VP_SYSTEM_STATE,
+       CPIA2_CMD_GET_VP_SYSTEM_CTRL,
+       CPIA2_CMD_SET_VP_SYSTEM_CTRL,
+       CPIA2_CMD_GET_VP_EXP_MODES,
+       CPIA2_CMD_SET_VP_EXP_MODES,
+       CPIA2_CMD_GET_DEVICE_CONFIG,
+       CPIA2_CMD_SET_DEVICE_CONFIG,
+       CPIA2_CMD_SET_SERIAL_ADDR,
+       CPIA2_CMD_SET_SENSOR_CR1,
+       CPIA2_CMD_GET_VC_CONTROL,
+       CPIA2_CMD_SET_VC_CONTROL,
+       CPIA2_CMD_SET_TARGET_KB,
+       CPIA2_CMD_SET_DEF_JPEG_OPT,
+       CPIA2_CMD_REHASH_VP4,
+       CPIA2_CMD_GET_USER_EFFECTS,
+       CPIA2_CMD_SET_USER_EFFECTS
+};
+
+enum user_cmd {
+       COMMAND_NONE = 0x00000001,
+       COMMAND_SET_FPS = 0x00000002,
+       COMMAND_SET_COLOR_PARAMS = 0x00000004,
+       COMMAND_GET_COLOR_PARAMS = 0x00000008,
+       COMMAND_SET_FORMAT = 0x00000010,        /* size, etc */
+       COMMAND_SET_FLICKER = 0x00000020
+};
+
+/***
+ * Some defines specific to the 676 chip
+ ***/
+#define CAMACC_CIF      0x01
+#define CAMACC_VGA      0x02
+#define CAMACC_QCIF     0x04
+#define CAMACC_QVGA     0x08
+
+
+struct cpia2_register {
+       u8 index;
+       u8 value;
+};
+
+struct cpia2_reg_mask {
+       u8 index;
+       u8 and_mask;
+       u8 or_mask;
+       u8 fill;
+};
+
+struct cpia2_command {
+       u32 command;
+       u8 req_mode;            /* (Block or random) | registerBank */
+       u8 reg_count;
+       u8 direction;
+       u8 start;
+       union reg_types {
+               struct cpia2_register registers[32];
+               struct cpia2_reg_mask masks[16];
+               u8 block_data[64];
+               u8 *patch_data; /* points to function defined block */
+       } buffer;
+};
+
+struct camera_params {
+       struct {
+               u8 firmware_revision_hi; /* For system register set (bank 0) */
+               u8 firmware_revision_lo;
+               u8 asic_id;     /* Video Compressor set (bank 1) */
+               u8 asic_rev;
+               u8 vp_device_hi;        /* Video Processor set (bank 2) */
+               u8 vp_device_lo;
+               u8 sensor_flags;
+               u8 sensor_rev;
+       } version;
+
+       struct {
+               u32 device_type;     /* enumerated from vendor/product ids.
+                                     * Currently, either STV_672 or STV_676 */
+               u16 vendor;
+               u16 product;
+               u16 device_revision;
+       } pnp_id;
+
+       struct {
+               u8 brightness;  /* CPIA2_VP_EXPOSURE_TARGET */
+               u8 contrast;    /* Note: this is CPIA2_VP_YRANGE */
+               u8 saturation;  /*  CPIA2_VP_SATURATION */
+       } color_params;
+
+       struct {
+               u8 cam_register;
+               u8 flicker_mode_req;    /* 1 if flicker on, else never flicker */
+       } flicker_control;
+
+       struct {
+               u8 jpeg_options;
+               u8 creep_period;
+               u8 user_squeeze;
+               u8 inhibit_htables;
+       } compression;
+
+       struct {
+               u8 ohsize;      /* output image size */
+               u8 ovsize;
+               u8 hcrop;       /* cropping start_pos/4 */
+               u8 vcrop;
+               u8 hphase;      /* scaling registers */
+               u8 vphase;
+               u8 hispan;
+               u8 vispan;
+               u8 hicrop;
+               u8 vicrop;
+               u8 hifraction;
+               u8 vifraction;
+       } image_size;
+
+       struct {
+               int width;      /* actual window width */
+               int height;     /* actual window height */
+       } roi;
+
+       struct {
+               u8 video_mode;
+               u8 frame_rate;
+               u8 video_size;  /* Not a register, just a convenience for cropped sizes */
+               u8 gpio_direction;
+               u8 gpio_data;
+               u8 system_ctrl;
+               u8 system_state;
+               u8 lowlight_boost;      /* Bool: 0 = off, 1 = on */
+               u8 device_config;
+               u8 exposure_modes;
+               u8 user_effects;
+       } vp_params;
+
+       struct {
+               u8 pw_control;
+               u8 wakeup;
+               u8 vc_control;
+               u8 vc_mp_direction;
+               u8 vc_mp_data;
+               u8 quality;
+       } vc_params;
+
+       struct {
+               u8 power_mode;
+               u8 system_ctrl;
+               u8 stream_mode; /* This is the current alternate for usb drivers */
+               u8 allow_corrupt;
+       } camera_state;
+};
+
+#define NUM_SBUF    2
+
+struct cpia2_sbuf {
+       char *data;
+       struct urb *urb;
+};
+
+struct framebuf {
+       struct timeval timestamp;
+       unsigned long seq;
+       int num;
+       int length;
+       int max_length;
+       volatile enum frame_status status;
+       u8 *data;
+       struct framebuf *next;
+};
+
+struct camera_data {
+       /* locks */
+       struct v4l2_device v4l2_dev;
+       struct mutex v4l2_lock; /* serialize file operations */
+       struct v4l2_ctrl_handler hdl;
+       struct {
+               /* Lights control cluster */
+               struct v4l2_ctrl *top_light;
+               struct v4l2_ctrl *bottom_light;
+       };
+       struct v4l2_ctrl *usb_alt;
+
+       /* camera status */
+       int first_image_seen;
+       enum sensors sensor_type;
+       u8 flush;
+       struct v4l2_fh *stream_fh;
+       u8 mmapped;
+       int streaming;          /* 0 = no, 1 = yes */
+       int xfer_mode;          /* XFER_BULK or XFER_ISOC */
+       struct camera_params params;    /* camera settings */
+
+       /* v4l */
+       int video_size;                 /* VIDEO_SIZE_ */
+       struct video_device vdev;       /* v4l videodev */
+       u32 width;
+       u32 height;                     /* Its size */
+       __u32 pixelformat;       /* Format fourcc      */
+
+       /* USB */
+       struct usb_device *dev;
+       unsigned char iface;
+       unsigned int cur_alt;
+       unsigned int old_alt;
+       struct cpia2_sbuf sbuf[NUM_SBUF];       /* Double buffering */
+
+       wait_queue_head_t wq_stream;
+
+       /* Buffering */
+       u32 frame_size;
+       int num_frames;
+       unsigned long frame_count;
+       u8 *frame_buffer;       /* frame buffer data */
+       struct framebuf *buffers;
+       struct framebuf * volatile curbuff;
+       struct framebuf *workbuff;
+
+       /* MJPEG Extension */
+       int APPn;               /* Number of APP segment to be written, must be 0..15 */
+       int APP_len;            /* Length of data in JPEG APPn segment */
+       char APP_data[60];      /* Data in the JPEG APPn segment. */
+
+       int COM_len;            /* Length of data in JPEG COM segment */
+       char COM_data[60];      /* Data in JPEG COM segment */
+};
+
+/* v4l */
+int cpia2_register_camera(struct camera_data *cam);
+void cpia2_unregister_camera(struct camera_data *cam);
+void cpia2_camera_release(struct v4l2_device *v4l2_dev);
+
+/* core */
+int cpia2_reset_camera(struct camera_data *cam);
+int cpia2_set_low_power(struct camera_data *cam);
+void cpia2_dbg_dump_registers(struct camera_data *cam);
+int cpia2_match_video_size(int width, int height);
+void cpia2_set_camera_state(struct camera_data *cam);
+void cpia2_save_camera_state(struct camera_data *cam);
+void cpia2_set_color_params(struct camera_data *cam);
+void cpia2_set_brightness(struct camera_data *cam, unsigned char value);
+void cpia2_set_contrast(struct camera_data *cam, unsigned char value);
+void cpia2_set_saturation(struct camera_data *cam, unsigned char value);
+int cpia2_set_flicker_mode(struct camera_data *cam, int mode);
+void cpia2_set_format(struct camera_data *cam);
+int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd);
+int cpia2_do_command(struct camera_data *cam,
+                    unsigned int command,
+                    unsigned char direction, unsigned char param);
+struct camera_data *cpia2_init_camera_struct(struct usb_interface *intf);
+int cpia2_init_camera(struct camera_data *cam);
+int cpia2_allocate_buffers(struct camera_data *cam);
+void cpia2_free_buffers(struct camera_data *cam);
+long cpia2_read(struct camera_data *cam,
+               char __user *buf, unsigned long count, int noblock);
+unsigned int cpia2_poll(struct camera_data *cam,
+                       struct file *filp, poll_table *wait);
+int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma);
+void cpia2_set_property_flip(struct camera_data *cam, int prop_val);
+void cpia2_set_property_mirror(struct camera_data *cam, int prop_val);
+int cpia2_set_gpio(struct camera_data *cam, unsigned char setting);
+int cpia2_set_fps(struct camera_data *cam, int framerate);
+
+/* usb */
+int cpia2_usb_init(void);
+void cpia2_usb_cleanup(void);
+int cpia2_usb_transfer_cmd(struct camera_data *cam, void *registers,
+                          u8 request, u8 start, u8 count, u8 direction);
+int cpia2_usb_stream_start(struct camera_data *cam, unsigned int alternate);
+int cpia2_usb_stream_stop(struct camera_data *cam);
+int cpia2_usb_stream_pause(struct camera_data *cam);
+int cpia2_usb_stream_resume(struct camera_data *cam);
+int cpia2_usb_change_streaming_alternate(struct camera_data *cam,
+                                        unsigned int alt);
+
+
+/* ----------------------- debug functions ---------------------- */
+#ifdef _CPIA2_DEBUG_
+#define ALOG(lev, fmt, args...) printk(lev "%s:%d %s(): " fmt, __FILE__, __LINE__, __func__, ## args)
+#define LOG(fmt, args...) ALOG(KERN_INFO, fmt, ## args)
+#define ERR(fmt, args...) ALOG(KERN_ERR, fmt, ## args)
+#define DBG(fmt, args...) ALOG(KERN_DEBUG, fmt, ## args)
+#else
+#define ALOG(fmt,args...) printk(fmt,##args)
+#define LOG(fmt,args...) ALOG(KERN_INFO "cpia2: "fmt,##args)
+#define ERR(fmt,args...) ALOG(KERN_ERR "cpia2: "fmt,##args)
+#define DBG(fmn,args...) do {} while(0)
+#endif
+/* No function or lineno, for shorter lines */
+#define KINFO(fmt, args...) printk(KERN_INFO fmt,##args)
+
+#endif
diff --git a/drivers/media/usb/cpia2/cpia2_core.c b/drivers/media/usb/cpia2/cpia2_core.c
new file mode 100644 (file)
index 0000000..187012c
--- /dev/null
@@ -0,0 +1,2417 @@
+/****************************************************************************
+ *
+ *  Filename: cpia2_core.c
+ *
+ *  Copyright 2001, STMicrolectronics, Inc.
+ *      Contact:  steve.miller@st.com
+ *
+ *  Description:
+ *     This is a USB driver for CPia2 based video cameras.
+ *     The infrastructure of this driver is based on the cpia usb driver by
+ *     Jochen Scharrlach and Johannes Erdfeldt.
+ *
+ *  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.
+ *
+ *  Stripped of 2.4 stuff ready for main kernel submit by
+ *             Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ ****************************************************************************/
+
+#include "cpia2.h"
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+
+#define FIRMWARE "cpia2/stv0672_vp4.bin"
+MODULE_FIRMWARE(FIRMWARE);
+
+/* #define _CPIA2_DEBUG_ */
+
+#ifdef _CPIA2_DEBUG_
+
+static const char *block_name[] = {
+       "System",
+       "VC",
+       "VP",
+       "IDATA"
+};
+#endif
+
+static unsigned int debugs_on; /* default 0 - DEBUG_REG */
+
+
+/******************************************************************************
+ *
+ *  Forward Declarations
+ *
+ *****************************************************************************/
+static int apply_vp_patch(struct camera_data *cam);
+static int set_default_user_mode(struct camera_data *cam);
+static int set_vw_size(struct camera_data *cam, int size);
+static int configure_sensor(struct camera_data *cam,
+                           int reqwidth, int reqheight);
+static int config_sensor_410(struct camera_data *cam,
+                           int reqwidth, int reqheight);
+static int config_sensor_500(struct camera_data *cam,
+                           int reqwidth, int reqheight);
+static int set_all_properties(struct camera_data *cam);
+static void wake_system(struct camera_data *cam);
+static void set_lowlight_boost(struct camera_data *cam);
+static void reset_camera_struct(struct camera_data *cam);
+static int cpia2_set_high_power(struct camera_data *cam);
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the
+ * area and marking the pages as reserved.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr)
+{
+       unsigned long kva, ret;
+
+       kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+       kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+       ret = __pa(kva);
+       return ret;
+}
+
+static void *rvmalloc(unsigned long size)
+{
+       void *mem;
+       unsigned long adr;
+
+       /* Round it off to PAGE_SIZE */
+       size = PAGE_ALIGN(size);
+
+       mem = vmalloc_32(size);
+       if (!mem)
+               return NULL;
+
+       memset(mem, 0, size);   /* Clear the ram out, no junk to the user */
+       adr = (unsigned long) mem;
+
+       while ((long)size > 0) {
+               SetPageReserved(vmalloc_to_page((void *)adr));
+               adr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+       return mem;
+}
+
+static void rvfree(void *mem, unsigned long size)
+{
+       unsigned long adr;
+
+       if (!mem)
+               return;
+
+       size = PAGE_ALIGN(size);
+
+       adr = (unsigned long) mem;
+       while ((long)size > 0) {
+               ClearPageReserved(vmalloc_to_page((void *)adr));
+               adr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+       vfree(mem);
+}
+
+/******************************************************************************
+ *
+ *  cpia2_do_command
+ *
+ *  Send an arbitrary command to the camera.  For commands that read from
+ *  the camera, copy the buffers into the proper param structures.
+ *****************************************************************************/
+int cpia2_do_command(struct camera_data *cam,
+                    u32 command, u8 direction, u8 param)
+{
+       int retval = 0;
+       struct cpia2_command cmd;
+       unsigned int device = cam->params.pnp_id.device_type;
+
+       cmd.command = command;
+       cmd.reg_count = 2;      /* default */
+       cmd.direction = direction;
+
+       /***
+        * Set up the command.
+        ***/
+       switch (command) {
+       case CPIA2_CMD_GET_VERSION:
+               cmd.req_mode =
+                   CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
+               cmd.start = CPIA2_SYSTEM_DEVICE_HI;
+               break;
+       case CPIA2_CMD_GET_PNP_ID:
+               cmd.req_mode =
+                   CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
+               cmd.reg_count = 8;
+               cmd.start = CPIA2_SYSTEM_DESCRIP_VID_HI;
+               break;
+       case CPIA2_CMD_GET_ASIC_TYPE:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
+               cmd.start = CPIA2_VC_ASIC_ID;
+               break;
+       case CPIA2_CMD_GET_SENSOR:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.start = CPIA2_VP_SENSOR_FLAGS;
+               break;
+       case CPIA2_CMD_GET_VP_DEVICE:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.start = CPIA2_VP_DEVICEH;
+               break;
+       case CPIA2_CMD_SET_VP_BRIGHTNESS:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_VP_BRIGHTNESS:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               if (device == DEVICE_STV_672)
+                       cmd.start = CPIA2_VP4_EXPOSURE_TARGET;
+               else
+                       cmd.start = CPIA2_VP5_EXPOSURE_TARGET;
+               break;
+       case CPIA2_CMD_SET_CONTRAST:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_CONTRAST:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VP_YRANGE;
+               break;
+       case CPIA2_CMD_SET_VP_SATURATION:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_VP_SATURATION:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               if (device == DEVICE_STV_672)
+                       cmd.start = CPIA2_VP_SATURATION;
+               else
+                       cmd.start = CPIA2_VP5_MCUVSATURATION;
+               break;
+       case CPIA2_CMD_SET_VP_GPIO_DATA:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_VP_GPIO_DATA:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VP_GPIO_DATA;
+               break;
+       case CPIA2_CMD_SET_VP_GPIO_DIRECTION:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_VP_GPIO_DIRECTION:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VP_GPIO_DIRECTION;
+               break;
+       case CPIA2_CMD_SET_VC_MP_GPIO_DATA:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_VC_MP_GPIO_DATA:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VC_MP_DATA;
+               break;
+       case CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VC_MP_DIR;
+               break;
+       case CPIA2_CMD_ENABLE_PACKET_CTRL:
+               cmd.req_mode =
+                   CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
+               cmd.start = CPIA2_SYSTEM_INT_PACKET_CTRL;
+               cmd.reg_count = 1;
+               cmd.buffer.block_data[0] = param;
+               break;
+       case CPIA2_CMD_SET_FLICKER_MODES:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_FLICKER_MODES:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VP_FLICKER_MODES;
+               break;
+       case CPIA2_CMD_RESET_FIFO:      /* clear fifo and enable stream block */
+               cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC;
+               cmd.reg_count = 2;
+               cmd.start = 0;
+               cmd.buffer.registers[0].index = CPIA2_VC_ST_CTRL;
+               cmd.buffer.registers[0].value = CPIA2_VC_ST_CTRL_SRC_VC |
+                   CPIA2_VC_ST_CTRL_DST_USB | CPIA2_VC_ST_CTRL_EOF_DETECT;
+               cmd.buffer.registers[1].index = CPIA2_VC_ST_CTRL;
+               cmd.buffer.registers[1].value = CPIA2_VC_ST_CTRL_SRC_VC |
+                   CPIA2_VC_ST_CTRL_DST_USB |
+                   CPIA2_VC_ST_CTRL_EOF_DETECT |
+                   CPIA2_VC_ST_CTRL_FIFO_ENABLE;
+               break;
+       case CPIA2_CMD_SET_HI_POWER:
+               cmd.req_mode =
+                   CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_SYSTEM;
+               cmd.reg_count = 2;
+               cmd.buffer.registers[0].index =
+                   CPIA2_SYSTEM_SYSTEM_CONTROL;
+               cmd.buffer.registers[1].index =
+                   CPIA2_SYSTEM_SYSTEM_CONTROL;
+               cmd.buffer.registers[0].value = CPIA2_SYSTEM_CONTROL_CLEAR_ERR;
+               cmd.buffer.registers[1].value =
+                   CPIA2_SYSTEM_CONTROL_HIGH_POWER;
+               break;
+       case CPIA2_CMD_SET_LOW_POWER:
+               cmd.req_mode =
+                   CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_SYSTEM_SYSTEM_CONTROL;
+               cmd.buffer.block_data[0] = 0;
+               break;
+       case CPIA2_CMD_CLEAR_V2W_ERR:
+               cmd.req_mode =
+                   CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_SYSTEM_SYSTEM_CONTROL;
+               cmd.buffer.block_data[0] = CPIA2_SYSTEM_CONTROL_CLEAR_ERR;
+               break;
+       case CPIA2_CMD_SET_USER_MODE:   /* Then fall through */
+               cmd.buffer.block_data[0] = param;
+       case CPIA2_CMD_GET_USER_MODE:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               if (device == DEVICE_STV_672)
+                       cmd.start = CPIA2_VP4_USER_MODE;
+               else
+                       cmd.start = CPIA2_VP5_USER_MODE;
+               break;
+       case CPIA2_CMD_FRAMERATE_REQ:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               if (device == DEVICE_STV_672)
+                       cmd.start = CPIA2_VP4_FRAMERATE_REQUEST;
+               else
+                       cmd.start = CPIA2_VP5_FRAMERATE_REQUEST;
+               cmd.buffer.block_data[0] = param;
+               break;
+       case CPIA2_CMD_SET_WAKEUP:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_WAKEUP:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VC_WAKEUP;
+               break;
+       case CPIA2_CMD_SET_PW_CONTROL:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_PW_CONTROL:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VC_PW_CTRL;
+               break;
+       case CPIA2_CMD_GET_VP_SYSTEM_STATE:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VP_SYSTEMSTATE;
+               break;
+       case CPIA2_CMD_SET_SYSTEM_CTRL:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_SYSTEM_CTRL:
+               cmd.req_mode =
+                   CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_SYSTEM_SYSTEM_CONTROL;
+               break;
+       case CPIA2_CMD_SET_VP_SYSTEM_CTRL:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_VP_SYSTEM_CTRL:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VP_SYSTEMCTRL;
+               break;
+       case CPIA2_CMD_SET_VP_EXP_MODES:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_VP_EXP_MODES:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VP_EXPOSURE_MODES;
+               break;
+       case CPIA2_CMD_SET_DEVICE_CONFIG:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_DEVICE_CONFIG:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VP_DEVICE_CONFIG;
+               break;
+       case CPIA2_CMD_SET_SERIAL_ADDR:
+               cmd.buffer.block_data[0] = param;
+               cmd.req_mode =
+                   CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_SYSTEM_VP_SERIAL_ADDR;
+               break;
+       case CPIA2_CMD_SET_SENSOR_CR1:
+               cmd.buffer.block_data[0] = param;
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_SENSOR_CR1;
+               break;
+       case CPIA2_CMD_SET_VC_CONTROL:
+               cmd.buffer.block_data[0] = param;       /* Then fall through */
+       case CPIA2_CMD_GET_VC_CONTROL:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VC_VC_CTRL;
+               break;
+       case CPIA2_CMD_SET_TARGET_KB:
+               cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC;
+               cmd.reg_count = 1;
+               cmd.buffer.registers[0].index = CPIA2_VC_VC_TARGET_KB;
+               cmd.buffer.registers[0].value = param;
+               break;
+       case CPIA2_CMD_SET_DEF_JPEG_OPT:
+               cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC;
+               cmd.reg_count = 4;
+               cmd.buffer.registers[0].index = CPIA2_VC_VC_JPEG_OPT;
+               cmd.buffer.registers[0].value =
+                   CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE;
+               cmd.buffer.registers[1].index = CPIA2_VC_VC_USER_SQUEEZE;
+               cmd.buffer.registers[1].value = 20;
+               cmd.buffer.registers[2].index = CPIA2_VC_VC_CREEP_PERIOD;
+               cmd.buffer.registers[2].value = 2;
+               cmd.buffer.registers[3].index = CPIA2_VC_VC_JPEG_OPT;
+               cmd.buffer.registers[3].value = CPIA2_VC_VC_JPEG_OPT_DEFAULT;
+               break;
+       case CPIA2_CMD_REHASH_VP4:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VP_REHASH_VALUES;
+               cmd.buffer.block_data[0] = param;
+               break;
+       case CPIA2_CMD_SET_USER_EFFECTS:  /* Note: Be careful with this as
+                                            this register can also affect
+                                            flicker modes */
+               cmd.buffer.block_data[0] = param;      /* Then fall through */
+       case CPIA2_CMD_GET_USER_EFFECTS:
+               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+               cmd.reg_count = 1;
+               if (device == DEVICE_STV_672)
+                       cmd.start = CPIA2_VP4_USER_EFFECTS;
+               else
+                       cmd.start = CPIA2_VP5_USER_EFFECTS;
+               break;
+       default:
+               LOG("DoCommand received invalid command\n");
+               return -EINVAL;
+       }
+
+       retval = cpia2_send_command(cam, &cmd);
+       if (retval) {
+               return retval;
+       }
+
+       /***
+        * Now copy any results from a read into the appropriate param struct.
+        ***/
+       switch (command) {
+       case CPIA2_CMD_GET_VERSION:
+               cam->params.version.firmware_revision_hi =
+                   cmd.buffer.block_data[0];
+               cam->params.version.firmware_revision_lo =
+                   cmd.buffer.block_data[1];
+               break;
+       case CPIA2_CMD_GET_PNP_ID:
+               cam->params.pnp_id.vendor = (cmd.buffer.block_data[0] << 8) |
+                                           cmd.buffer.block_data[1];
+               cam->params.pnp_id.product = (cmd.buffer.block_data[2] << 8) |
+                                            cmd.buffer.block_data[3];
+               cam->params.pnp_id.device_revision =
+                       (cmd.buffer.block_data[4] << 8) |
+                       cmd.buffer.block_data[5];
+               if (cam->params.pnp_id.vendor == 0x553) {
+                       if (cam->params.pnp_id.product == 0x100) {
+                               cam->params.pnp_id.device_type = DEVICE_STV_672;
+                       } else if (cam->params.pnp_id.product == 0x140 ||
+                                  cam->params.pnp_id.product == 0x151) {
+                               cam->params.pnp_id.device_type = DEVICE_STV_676;
+                       }
+               }
+               break;
+       case CPIA2_CMD_GET_ASIC_TYPE:
+               cam->params.version.asic_id = cmd.buffer.block_data[0];
+               cam->params.version.asic_rev = cmd.buffer.block_data[1];
+               break;
+       case CPIA2_CMD_GET_SENSOR:
+               cam->params.version.sensor_flags = cmd.buffer.block_data[0];
+               cam->params.version.sensor_rev = cmd.buffer.block_data[1];
+               break;
+       case CPIA2_CMD_GET_VP_DEVICE:
+               cam->params.version.vp_device_hi = cmd.buffer.block_data[0];
+               cam->params.version.vp_device_lo = cmd.buffer.block_data[1];
+               break;
+       case CPIA2_CMD_GET_VP_GPIO_DATA:
+               cam->params.vp_params.gpio_data = cmd.buffer.block_data[0];
+               break;
+       case CPIA2_CMD_GET_VP_GPIO_DIRECTION:
+               cam->params.vp_params.gpio_direction = cmd.buffer.block_data[0];
+               break;
+       case CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION:
+               cam->params.vc_params.vc_mp_direction =cmd.buffer.block_data[0];
+               break;
+       case CPIA2_CMD_GET_VC_MP_GPIO_DATA:
+               cam->params.vc_params.vc_mp_data = cmd.buffer.block_data[0];
+               break;
+       case CPIA2_CMD_GET_FLICKER_MODES:
+               cam->params.flicker_control.cam_register =
+                       cmd.buffer.block_data[0];
+               break;
+       case CPIA2_CMD_GET_WAKEUP:
+               cam->params.vc_params.wakeup = cmd.buffer.block_data[0];
+               break;
+       case CPIA2_CMD_GET_PW_CONTROL:
+               cam->params.vc_params.pw_control = cmd.buffer.block_data[0];
+               break;
+       case CPIA2_CMD_GET_SYSTEM_CTRL:
+               cam->params.camera_state.system_ctrl = cmd.buffer.block_data[0];
+               break;
+       case CPIA2_CMD_GET_VP_SYSTEM_STATE:
+               cam->params.vp_params.system_state = cmd.buffer.block_data[0];
+               break;
+       case CPIA2_CMD_GET_VP_SYSTEM_CTRL:
+               cam->params.vp_params.system_ctrl = cmd.buffer.block_data[0];
+               break;
+       case CPIA2_CMD_GET_VP_EXP_MODES:
+               cam->params.vp_params.exposure_modes = cmd.buffer.block_data[0];
+               break;
+       case CPIA2_CMD_GET_DEVICE_CONFIG:
+               cam->params.vp_params.device_config = cmd.buffer.block_data[0];
+               break;
+       case CPIA2_CMD_GET_VC_CONTROL:
+               cam->params.vc_params.vc_control = cmd.buffer.block_data[0];
+               break;
+       case CPIA2_CMD_GET_USER_MODE:
+               cam->params.vp_params.video_mode = cmd.buffer.block_data[0];
+               break;
+       case CPIA2_CMD_GET_USER_EFFECTS:
+               cam->params.vp_params.user_effects = cmd.buffer.block_data[0];
+               break;
+       default:
+               break;
+       }
+       return retval;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_send_command
+ *
+ *****************************************************************************/
+
+#define DIR(cmd) ((cmd->direction == TRANSFER_WRITE) ? "Write" : "Read")
+#define BINDEX(cmd) (cmd->req_mode & 0x03)
+
+int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd)
+{
+       u8 count;
+       u8 start;
+       u8 *buffer;
+       int retval;
+
+       switch (cmd->req_mode & 0x0c) {
+       case CAMERAACCESS_TYPE_RANDOM:
+               count = cmd->reg_count * sizeof(struct cpia2_register);
+               start = 0;
+               buffer = (u8 *) & cmd->buffer;
+               if (debugs_on & DEBUG_REG)
+                       DBG("%s Random: Register block %s\n", DIR(cmd),
+                           block_name[BINDEX(cmd)]);
+               break;
+       case CAMERAACCESS_TYPE_BLOCK:
+               count = cmd->reg_count;
+               start = cmd->start;
+               buffer = cmd->buffer.block_data;
+               if (debugs_on & DEBUG_REG)
+                       DBG("%s Block: Register block %s\n", DIR(cmd),
+                           block_name[BINDEX(cmd)]);
+               break;
+       case CAMERAACCESS_TYPE_MASK:
+               count = cmd->reg_count * sizeof(struct cpia2_reg_mask);
+               start = 0;
+               buffer = (u8 *) & cmd->buffer;
+               if (debugs_on & DEBUG_REG)
+                       DBG("%s Mask: Register block %s\n", DIR(cmd),
+                           block_name[BINDEX(cmd)]);
+               break;
+       case CAMERAACCESS_TYPE_REPEAT:  /* For patch blocks only */
+               count = cmd->reg_count;
+               start = cmd->start;
+               buffer = cmd->buffer.block_data;
+               if (debugs_on & DEBUG_REG)
+                       DBG("%s Repeat: Register block %s\n", DIR(cmd),
+                           block_name[BINDEX(cmd)]);
+               break;
+       default:
+               LOG("%s: invalid request mode\n",__func__);
+               return -EINVAL;
+       }
+
+       retval = cpia2_usb_transfer_cmd(cam,
+                                       buffer,
+                                       cmd->req_mode,
+                                       start, count, cmd->direction);
+#ifdef _CPIA2_DEBUG_
+       if (debugs_on & DEBUG_REG) {
+               int i;
+               for (i = 0; i < cmd->reg_count; i++) {
+                       if((cmd->req_mode & 0x0c) == CAMERAACCESS_TYPE_BLOCK)
+                               KINFO("%s Block: [0x%02X] = 0x%02X\n",
+                                   DIR(cmd), start + i, buffer[i]);
+                       if((cmd->req_mode & 0x0c) == CAMERAACCESS_TYPE_RANDOM)
+                               KINFO("%s Random: [0x%02X] = 0x%02X\n",
+                                   DIR(cmd), cmd->buffer.registers[i].index,
+                                   cmd->buffer.registers[i].value);
+               }
+       }
+#endif
+
+       return retval;
+};
+
+/*************
+ * Functions to implement camera functionality
+ *************/
+/******************************************************************************
+ *
+ *  cpia2_get_version_info
+ *
+ *****************************************************************************/
+static void cpia2_get_version_info(struct camera_data *cam)
+{
+       cpia2_do_command(cam, CPIA2_CMD_GET_VERSION, TRANSFER_READ, 0);
+       cpia2_do_command(cam, CPIA2_CMD_GET_PNP_ID, TRANSFER_READ, 0);
+       cpia2_do_command(cam, CPIA2_CMD_GET_ASIC_TYPE, TRANSFER_READ, 0);
+       cpia2_do_command(cam, CPIA2_CMD_GET_SENSOR, TRANSFER_READ, 0);
+       cpia2_do_command(cam, CPIA2_CMD_GET_VP_DEVICE, TRANSFER_READ, 0);
+}
+
+/******************************************************************************
+ *
+ *  cpia2_reset_camera
+ *
+ *  Called at least during the open process, sets up initial params.
+ *****************************************************************************/
+int cpia2_reset_camera(struct camera_data *cam)
+{
+       u8 tmp_reg;
+       int retval = 0;
+       int target_kb;
+       int i;
+       struct cpia2_command cmd;
+
+       /***
+        * VC setup
+        ***/
+       retval = configure_sensor(cam,
+                                 cam->params.roi.width,
+                                 cam->params.roi.height);
+       if (retval < 0) {
+               ERR("Couldn't configure sensor, error=%d\n", retval);
+               return retval;
+       }
+
+       /* Clear FIFO and route/enable stream block */
+       cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC;
+       cmd.direction = TRANSFER_WRITE;
+       cmd.reg_count = 2;
+       cmd.buffer.registers[0].index = CPIA2_VC_ST_CTRL;
+       cmd.buffer.registers[0].value = CPIA2_VC_ST_CTRL_SRC_VC |
+               CPIA2_VC_ST_CTRL_DST_USB | CPIA2_VC_ST_CTRL_EOF_DETECT;
+       cmd.buffer.registers[1].index = CPIA2_VC_ST_CTRL;
+       cmd.buffer.registers[1].value = CPIA2_VC_ST_CTRL_SRC_VC |
+               CPIA2_VC_ST_CTRL_DST_USB |
+               CPIA2_VC_ST_CTRL_EOF_DETECT | CPIA2_VC_ST_CTRL_FIFO_ENABLE;
+
+       cpia2_send_command(cam, &cmd);
+
+       cpia2_set_high_power(cam);
+
+       if (cam->params.pnp_id.device_type == DEVICE_STV_672) {
+               /* Enable button notification */
+               cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_SYSTEM;
+               cmd.buffer.registers[0].index = CPIA2_SYSTEM_INT_PACKET_CTRL;
+               cmd.buffer.registers[0].value =
+                       CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_SW_XX;
+               cmd.reg_count = 1;
+               cpia2_send_command(cam, &cmd);
+       }
+
+       schedule_timeout_interruptible(msecs_to_jiffies(100));
+
+       if (cam->params.pnp_id.device_type == DEVICE_STV_672)
+               retval = apply_vp_patch(cam);
+
+       /* wait for vp to go to sleep */
+       schedule_timeout_interruptible(msecs_to_jiffies(100));
+
+       /***
+        * If this is a 676, apply VP5 fixes before we start streaming
+        ***/
+       if (cam->params.pnp_id.device_type == DEVICE_STV_676) {
+               cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP;
+
+               /* The following writes improve the picture */
+               cmd.buffer.registers[0].index = CPIA2_VP5_MYBLACK_LEVEL;
+               cmd.buffer.registers[0].value = 0; /* reduce from the default
+                                                   * rec 601 pedestal of 16 */
+               cmd.buffer.registers[1].index = CPIA2_VP5_MCYRANGE;
+               cmd.buffer.registers[1].value = 0x92; /* increase from 100% to
+                                                      * (256/256 - 31) to fill
+                                                      * available range */
+               cmd.buffer.registers[2].index = CPIA2_VP5_MYCEILING;
+               cmd.buffer.registers[2].value = 0xFF; /* Increase from the
+                                                      * default rec 601 ceiling
+                                                      * of 240 */
+               cmd.buffer.registers[3].index = CPIA2_VP5_MCUVSATURATION;
+               cmd.buffer.registers[3].value = 0xFF; /* Increase from the rec
+                                                      * 601 100% level (128)
+                                                      * to 145-192 */
+               cmd.buffer.registers[4].index = CPIA2_VP5_ANTIFLKRSETUP;
+               cmd.buffer.registers[4].value = 0x80;  /* Inhibit the
+                                                       * anti-flicker */
+
+               /* The following 4 writes are a fix to allow QVGA to work at 30 fps */
+               cmd.buffer.registers[5].index = CPIA2_VP_RAM_ADDR_H;
+               cmd.buffer.registers[5].value = 0x01;
+               cmd.buffer.registers[6].index = CPIA2_VP_RAM_ADDR_L;
+               cmd.buffer.registers[6].value = 0xE3;
+               cmd.buffer.registers[7].index = CPIA2_VP_RAM_DATA;
+               cmd.buffer.registers[7].value = 0x02;
+               cmd.buffer.registers[8].index = CPIA2_VP_RAM_DATA;
+               cmd.buffer.registers[8].value = 0xFC;
+
+               cmd.direction = TRANSFER_WRITE;
+               cmd.reg_count = 9;
+
+               cpia2_send_command(cam, &cmd);
+       }
+
+       /* Activate all settings and start the data stream */
+       /* Set user mode */
+       set_default_user_mode(cam);
+
+       /* Give VP time to wake up */
+       schedule_timeout_interruptible(msecs_to_jiffies(100));
+
+       set_all_properties(cam);
+
+       cpia2_do_command(cam, CPIA2_CMD_GET_USER_MODE, TRANSFER_READ, 0);
+       DBG("After SetAllProperties(cam), user mode is 0x%0X\n",
+           cam->params.vp_params.video_mode);
+
+       /***
+        * Set audio regulator off.  This and the code to set the compresison
+        * state are too complex to form a CPIA2_CMD_, and seem to be somewhat
+        * intertwined.  This stuff came straight from the windows driver.
+        ***/
+       /* Turn AutoExposure off in VP and enable the serial bridge to the sensor */
+       cpia2_do_command(cam, CPIA2_CMD_GET_VP_SYSTEM_CTRL, TRANSFER_READ, 0);
+       tmp_reg = cam->params.vp_params.system_ctrl;
+       cmd.buffer.registers[0].value = tmp_reg &
+               (tmp_reg & (CPIA2_VP_SYSTEMCTRL_HK_CONTROL ^ 0xFF));
+
+       cpia2_do_command(cam, CPIA2_CMD_GET_DEVICE_CONFIG, TRANSFER_READ, 0);
+       cmd.buffer.registers[1].value = cam->params.vp_params.device_config |
+                                       CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE;
+       cmd.buffer.registers[0].index = CPIA2_VP_SYSTEMCTRL;
+       cmd.buffer.registers[1].index = CPIA2_VP_DEVICE_CONFIG;
+       cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP;
+       cmd.reg_count = 2;
+       cmd.direction = TRANSFER_WRITE;
+       cmd.start = 0;
+       cpia2_send_command(cam, &cmd);
+
+       /* Set the correct I2C address in the CPiA-2 system register */
+       cpia2_do_command(cam,
+                        CPIA2_CMD_SET_SERIAL_ADDR,
+                        TRANSFER_WRITE,
+                        CPIA2_SYSTEM_VP_SERIAL_ADDR_SENSOR);
+
+       /* Now have sensor access - set bit to turn the audio regulator off */
+       cpia2_do_command(cam,
+                        CPIA2_CMD_SET_SENSOR_CR1,
+                        TRANSFER_WRITE, CPIA2_SENSOR_CR1_DOWN_AUDIO_REGULATOR);
+
+       /* Set the correct I2C address in the CPiA-2 system register */
+       if (cam->params.pnp_id.device_type == DEVICE_STV_672)
+               cpia2_do_command(cam,
+                                CPIA2_CMD_SET_SERIAL_ADDR,
+                                TRANSFER_WRITE,
+                                CPIA2_SYSTEM_VP_SERIAL_ADDR_VP); // 0x88
+       else
+               cpia2_do_command(cam,
+                                CPIA2_CMD_SET_SERIAL_ADDR,
+                                TRANSFER_WRITE,
+                                CPIA2_SYSTEM_VP_SERIAL_ADDR_676_VP); // 0x8a
+
+       /* increase signal drive strength */
+       if (cam->params.pnp_id.device_type == DEVICE_STV_676)
+               cpia2_do_command(cam,
+                                CPIA2_CMD_SET_VP_EXP_MODES,
+                                TRANSFER_WRITE,
+                                CPIA2_VP_EXPOSURE_MODES_COMPILE_EXP);
+
+       /* Start autoexposure */
+       cpia2_do_command(cam, CPIA2_CMD_GET_DEVICE_CONFIG, TRANSFER_READ, 0);
+       cmd.buffer.registers[0].value = cam->params.vp_params.device_config &
+                                 (CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE ^ 0xFF);
+
+       cpia2_do_command(cam, CPIA2_CMD_GET_VP_SYSTEM_CTRL, TRANSFER_READ, 0);
+       cmd.buffer.registers[1].value =
+           cam->params.vp_params.system_ctrl | CPIA2_VP_SYSTEMCTRL_HK_CONTROL;
+
+       cmd.buffer.registers[0].index = CPIA2_VP_DEVICE_CONFIG;
+       cmd.buffer.registers[1].index = CPIA2_VP_SYSTEMCTRL;
+       cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP;
+       cmd.reg_count = 2;
+       cmd.direction = TRANSFER_WRITE;
+
+       cpia2_send_command(cam, &cmd);
+
+       /* Set compression state */
+       cpia2_do_command(cam, CPIA2_CMD_GET_VC_CONTROL, TRANSFER_READ, 0);
+       if (cam->params.compression.inhibit_htables) {
+               tmp_reg = cam->params.vc_params.vc_control |
+                         CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES;
+       } else  {
+               tmp_reg = cam->params.vc_params.vc_control &
+                         ~CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES;
+       }
+       cpia2_do_command(cam, CPIA2_CMD_SET_VC_CONTROL, TRANSFER_WRITE,tmp_reg);
+
+       /* Set target size (kb) on vc
+          This is a heuristic based on the quality parameter and the raw
+          framesize in kB divided by 16 (the compression factor when the
+          quality is 100%) */
+       target_kb = (cam->width * cam->height * 2 / 16384) *
+                               cam->params.vc_params.quality / 100;
+       if (target_kb < 1)
+               target_kb = 1;
+       cpia2_do_command(cam, CPIA2_CMD_SET_TARGET_KB,
+                        TRANSFER_WRITE, target_kb);
+
+       /* Wiggle VC Reset */
+       /***
+        * First read and wait a bit.
+        ***/
+       for (i = 0; i < 50; i++) {
+               cpia2_do_command(cam, CPIA2_CMD_GET_PW_CONTROL,
+                                TRANSFER_READ, 0);
+       }
+
+       tmp_reg = cam->params.vc_params.pw_control;
+       tmp_reg &= ~CPIA2_VC_PW_CTRL_VC_RESET_N;
+
+       cpia2_do_command(cam, CPIA2_CMD_SET_PW_CONTROL, TRANSFER_WRITE,tmp_reg);
+
+       tmp_reg |= CPIA2_VC_PW_CTRL_VC_RESET_N;
+       cpia2_do_command(cam, CPIA2_CMD_SET_PW_CONTROL, TRANSFER_WRITE,tmp_reg);
+
+       cpia2_do_command(cam, CPIA2_CMD_SET_DEF_JPEG_OPT, TRANSFER_WRITE, 0);
+
+       cpia2_do_command(cam, CPIA2_CMD_GET_USER_MODE, TRANSFER_READ, 0);
+       DBG("After VC RESET, user mode is 0x%0X\n",
+           cam->params.vp_params.video_mode);
+
+       return retval;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_set_high_power
+ *
+ *****************************************************************************/
+static int cpia2_set_high_power(struct camera_data *cam)
+{
+       int i;
+       for (i = 0; i <= 50; i++) {
+               /* Read system status */
+               cpia2_do_command(cam,CPIA2_CMD_GET_SYSTEM_CTRL,TRANSFER_READ,0);
+
+               /* If there is an error, clear it */
+               if(cam->params.camera_state.system_ctrl &
+                  CPIA2_SYSTEM_CONTROL_V2W_ERR)
+                       cpia2_do_command(cam, CPIA2_CMD_CLEAR_V2W_ERR,
+                                        TRANSFER_WRITE, 0);
+
+               /* Try to set high power mode */
+               cpia2_do_command(cam, CPIA2_CMD_SET_SYSTEM_CTRL,
+                                TRANSFER_WRITE, 1);
+
+               /* Try to read something in VP to check if everything is awake */
+               cpia2_do_command(cam, CPIA2_CMD_GET_VP_SYSTEM_STATE,
+                                TRANSFER_READ, 0);
+               if (cam->params.vp_params.system_state &
+                   CPIA2_VP_SYSTEMSTATE_HK_ALIVE) {
+                       break;
+               } else if (i == 50) {
+                       cam->params.camera_state.power_mode = LO_POWER_MODE;
+                       ERR("Camera did not wake up\n");
+                       return -EIO;
+               }
+       }
+
+       DBG("System now in high power state\n");
+       cam->params.camera_state.power_mode = HI_POWER_MODE;
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_set_low_power
+ *
+ *****************************************************************************/
+int cpia2_set_low_power(struct camera_data *cam)
+{
+       cam->params.camera_state.power_mode = LO_POWER_MODE;
+       cpia2_do_command(cam, CPIA2_CMD_SET_SYSTEM_CTRL, TRANSFER_WRITE, 0);
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  apply_vp_patch
+ *
+ *****************************************************************************/
+static int cpia2_send_onebyte_command(struct camera_data *cam,
+                                     struct cpia2_command *cmd,
+                                     u8 start, u8 datum)
+{
+       cmd->buffer.block_data[0] = datum;
+       cmd->start = start;
+       cmd->reg_count = 1;
+       return cpia2_send_command(cam, cmd);
+}
+
+static int apply_vp_patch(struct camera_data *cam)
+{
+       const struct firmware *fw;
+       const char fw_name[] = FIRMWARE;
+       int i, ret;
+       struct cpia2_command cmd;
+
+       ret = request_firmware(&fw, fw_name, &cam->dev->dev);
+       if (ret) {
+               printk(KERN_ERR "cpia2: failed to load VP patch \"%s\"\n",
+                      fw_name);
+               return ret;
+       }
+
+       cmd.req_mode = CAMERAACCESS_TYPE_REPEAT | CAMERAACCESS_VP;
+       cmd.direction = TRANSFER_WRITE;
+
+       /* First send the start address... */
+       cpia2_send_onebyte_command(cam, &cmd, 0x0A, fw->data[0]); /* hi */
+       cpia2_send_onebyte_command(cam, &cmd, 0x0B, fw->data[1]); /* lo */
+
+       /* ... followed by the data payload */
+       for (i = 2; i < fw->size; i += 64) {
+               cmd.start = 0x0C; /* Data */
+               cmd.reg_count = min_t(int, 64, fw->size - i);
+               memcpy(cmd.buffer.block_data, &fw->data[i], cmd.reg_count);
+               cpia2_send_command(cam, &cmd);
+       }
+
+       /* Next send the start address... */
+       cpia2_send_onebyte_command(cam, &cmd, 0x0A, fw->data[0]); /* hi */
+       cpia2_send_onebyte_command(cam, &cmd, 0x0B, fw->data[1]); /* lo */
+
+       /* ... followed by the 'goto' command */
+       cpia2_send_onebyte_command(cam, &cmd, 0x0D, 1);
+
+       release_firmware(fw);
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  set_default_user_mode
+ *
+ *****************************************************************************/
+static int set_default_user_mode(struct camera_data *cam)
+{
+       unsigned char user_mode;
+       unsigned char frame_rate;
+       int width = cam->params.roi.width;
+       int height = cam->params.roi.height;
+
+       switch (cam->params.version.sensor_flags) {
+       case CPIA2_VP_SENSOR_FLAGS_404:
+       case CPIA2_VP_SENSOR_FLAGS_407:
+       case CPIA2_VP_SENSOR_FLAGS_409:
+       case CPIA2_VP_SENSOR_FLAGS_410:
+               if ((width > STV_IMAGE_QCIF_COLS)
+                   || (height > STV_IMAGE_QCIF_ROWS)) {
+                       user_mode = CPIA2_VP_USER_MODE_CIF;
+               } else {
+                       user_mode = CPIA2_VP_USER_MODE_QCIFDS;
+               }
+               frame_rate = CPIA2_VP_FRAMERATE_30;
+               break;
+       case CPIA2_VP_SENSOR_FLAGS_500:
+               if ((width > STV_IMAGE_CIF_COLS)
+                   || (height > STV_IMAGE_CIF_ROWS)) {
+                       user_mode = CPIA2_VP_USER_MODE_VGA;
+               } else {
+                       user_mode = CPIA2_VP_USER_MODE_QVGADS;
+               }
+               if (cam->params.pnp_id.device_type == DEVICE_STV_672)
+                       frame_rate = CPIA2_VP_FRAMERATE_15;
+               else
+                       frame_rate = CPIA2_VP_FRAMERATE_30;
+               break;
+       default:
+               LOG("%s: Invalid sensor flag value 0x%0X\n",__func__,
+                   cam->params.version.sensor_flags);
+               return -EINVAL;
+       }
+
+       DBG("Sensor flag = 0x%0x, user mode = 0x%0x, frame rate = 0x%X\n",
+           cam->params.version.sensor_flags, user_mode, frame_rate);
+       cpia2_do_command(cam, CPIA2_CMD_SET_USER_MODE, TRANSFER_WRITE,
+                        user_mode);
+       if(cam->params.vp_params.frame_rate > 0 &&
+          frame_rate > cam->params.vp_params.frame_rate)
+               frame_rate = cam->params.vp_params.frame_rate;
+
+       cpia2_set_fps(cam, frame_rate);
+
+//     if (cam->params.pnp_id.device_type == DEVICE_STV_676)
+//             cpia2_do_command(cam,
+//                              CPIA2_CMD_SET_VP_SYSTEM_CTRL,
+//                              TRANSFER_WRITE,
+//                              CPIA2_VP_SYSTEMCTRL_HK_CONTROL |
+//                              CPIA2_VP_SYSTEMCTRL_POWER_CONTROL);
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_match_video_size
+ *
+ *  return the best match, where 'best' is as always
+ *  the largest that is not bigger than what is requested.
+ *****************************************************************************/
+int cpia2_match_video_size(int width, int height)
+{
+       if (width >= STV_IMAGE_VGA_COLS && height >= STV_IMAGE_VGA_ROWS)
+               return VIDEOSIZE_VGA;
+
+       if (width >= STV_IMAGE_CIF_COLS && height >= STV_IMAGE_CIF_ROWS)
+               return VIDEOSIZE_CIF;
+
+       if (width >= STV_IMAGE_QVGA_COLS && height >= STV_IMAGE_QVGA_ROWS)
+               return VIDEOSIZE_QVGA;
+
+       if (width >= 288 && height >= 216)
+               return VIDEOSIZE_288_216;
+
+       if (width >= 256 && height >= 192)
+               return VIDEOSIZE_256_192;
+
+       if (width >= 224 && height >= 168)
+               return VIDEOSIZE_224_168;
+
+       if (width >= 192 && height >= 144)
+               return VIDEOSIZE_192_144;
+
+       if (width >= STV_IMAGE_QCIF_COLS && height >= STV_IMAGE_QCIF_ROWS)
+               return VIDEOSIZE_QCIF;
+
+       return -1;
+}
+
+/******************************************************************************
+ *
+ *  SetVideoSize
+ *
+ *****************************************************************************/
+static int set_vw_size(struct camera_data *cam, int size)
+{
+       int retval = 0;
+
+       cam->params.vp_params.video_size = size;
+
+       switch (size) {
+       case VIDEOSIZE_VGA:
+               DBG("Setting size to VGA\n");
+               cam->params.roi.width = STV_IMAGE_VGA_COLS;
+               cam->params.roi.height = STV_IMAGE_VGA_ROWS;
+               cam->width = STV_IMAGE_VGA_COLS;
+               cam->height = STV_IMAGE_VGA_ROWS;
+               break;
+       case VIDEOSIZE_CIF:
+               DBG("Setting size to CIF\n");
+               cam->params.roi.width = STV_IMAGE_CIF_COLS;
+               cam->params.roi.height = STV_IMAGE_CIF_ROWS;
+               cam->width = STV_IMAGE_CIF_COLS;
+               cam->height = STV_IMAGE_CIF_ROWS;
+               break;
+       case VIDEOSIZE_QVGA:
+               DBG("Setting size to QVGA\n");
+               cam->params.roi.width = STV_IMAGE_QVGA_COLS;
+               cam->params.roi.height = STV_IMAGE_QVGA_ROWS;
+               cam->width = STV_IMAGE_QVGA_COLS;
+               cam->height = STV_IMAGE_QVGA_ROWS;
+               break;
+       case VIDEOSIZE_288_216:
+               cam->params.roi.width = 288;
+               cam->params.roi.height = 216;
+               cam->width = 288;
+               cam->height = 216;
+               break;
+       case VIDEOSIZE_256_192:
+               cam->width = 256;
+               cam->height = 192;
+               cam->params.roi.width = 256;
+               cam->params.roi.height = 192;
+               break;
+       case VIDEOSIZE_224_168:
+               cam->width = 224;
+               cam->height = 168;
+               cam->params.roi.width = 224;
+               cam->params.roi.height = 168;
+               break;
+       case VIDEOSIZE_192_144:
+               cam->width = 192;
+               cam->height = 144;
+               cam->params.roi.width = 192;
+               cam->params.roi.height = 144;
+               break;
+       case VIDEOSIZE_QCIF:
+               DBG("Setting size to QCIF\n");
+               cam->params.roi.width = STV_IMAGE_QCIF_COLS;
+               cam->params.roi.height = STV_IMAGE_QCIF_ROWS;
+               cam->width = STV_IMAGE_QCIF_COLS;
+               cam->height = STV_IMAGE_QCIF_ROWS;
+               break;
+       default:
+               retval = -EINVAL;
+       }
+       return retval;
+}
+
+/******************************************************************************
+ *
+ *  configure_sensor
+ *
+ *****************************************************************************/
+static int configure_sensor(struct camera_data *cam,
+                           int req_width, int req_height)
+{
+       int retval;
+
+       switch (cam->params.version.sensor_flags) {
+       case CPIA2_VP_SENSOR_FLAGS_404:
+       case CPIA2_VP_SENSOR_FLAGS_407:
+       case CPIA2_VP_SENSOR_FLAGS_409:
+       case CPIA2_VP_SENSOR_FLAGS_410:
+               retval = config_sensor_410(cam, req_width, req_height);
+               break;
+       case CPIA2_VP_SENSOR_FLAGS_500:
+               retval = config_sensor_500(cam, req_width, req_height);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return retval;
+}
+
+/******************************************************************************
+ *
+ *  config_sensor_410
+ *
+ *****************************************************************************/
+static int config_sensor_410(struct camera_data *cam,
+                           int req_width, int req_height)
+{
+       struct cpia2_command cmd;
+       int i = 0;
+       int image_size;
+       int image_type;
+       int width = req_width;
+       int height = req_height;
+
+       /***
+        *  Make sure size doesn't exceed CIF.
+        ***/
+       if (width > STV_IMAGE_CIF_COLS)
+               width = STV_IMAGE_CIF_COLS;
+       if (height > STV_IMAGE_CIF_ROWS)
+               height = STV_IMAGE_CIF_ROWS;
+
+       image_size = cpia2_match_video_size(width, height);
+
+       DBG("Config 410: width = %d, height = %d\n", width, height);
+       DBG("Image size returned is %d\n", image_size);
+       if (image_size >= 0) {
+               set_vw_size(cam, image_size);
+               width = cam->params.roi.width;
+               height = cam->params.roi.height;
+
+               DBG("After set_vw_size(), width = %d, height = %d\n",
+                   width, height);
+               if (width <= 176 && height <= 144) {
+                       DBG("image type = VIDEOSIZE_QCIF\n");
+                       image_type = VIDEOSIZE_QCIF;
+               }
+               else if (width <= 320 && height <= 240) {
+                       DBG("image type = VIDEOSIZE_QVGA\n");
+                       image_type = VIDEOSIZE_QVGA;
+               }
+               else {
+                       DBG("image type = VIDEOSIZE_CIF\n");
+                       image_type = VIDEOSIZE_CIF;
+               }
+       } else {
+               ERR("ConfigSensor410 failed\n");
+               return -EINVAL;
+       }
+
+       cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC;
+       cmd.direction = TRANSFER_WRITE;
+
+       /* VC Format */
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_FORMAT;
+       if (image_type == VIDEOSIZE_CIF) {
+               cmd.buffer.registers[i++].value =
+                   (u8) (CPIA2_VC_VC_FORMAT_UFIRST |
+                         CPIA2_VC_VC_FORMAT_SHORTLINE);
+       } else {
+               cmd.buffer.registers[i++].value =
+                   (u8) CPIA2_VC_VC_FORMAT_UFIRST;
+       }
+
+       /* VC Clocks */
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_CLOCKS;
+       if (image_type == VIDEOSIZE_QCIF) {
+               if (cam->params.pnp_id.device_type == DEVICE_STV_672) {
+                       cmd.buffer.registers[i++].value=
+                               (u8)(CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3 |
+                                    CPIA2_VC_VC_672_CLOCKS_SCALING |
+                                    CPIA2_VC_VC_CLOCKS_LOGDIV2);
+                       DBG("VC_Clocks (0xc4) should be B\n");
+               }
+               else {
+                       cmd.buffer.registers[i++].value=
+                               (u8)(CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3 |
+                                    CPIA2_VC_VC_CLOCKS_LOGDIV2);
+               }
+       } else {
+               if (cam->params.pnp_id.device_type == DEVICE_STV_672) {
+                       cmd.buffer.registers[i++].value =
+                          (u8) (CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3 |
+                                CPIA2_VC_VC_CLOCKS_LOGDIV0);
+               }
+               else {
+                       cmd.buffer.registers[i++].value =
+                          (u8) (CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3 |
+                                CPIA2_VC_VC_676_CLOCKS_SCALING |
+                                CPIA2_VC_VC_CLOCKS_LOGDIV0);
+               }
+       }
+       DBG("VC_Clocks (0xc4) = 0x%0X\n", cmd.buffer.registers[i-1].value);
+
+       /* Input reqWidth from VC */
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_IHSIZE_LO;
+       if (image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value =
+                   (u8) (STV_IMAGE_QCIF_COLS / 4);
+       else
+               cmd.buffer.registers[i++].value =
+                   (u8) (STV_IMAGE_CIF_COLS / 4);
+
+       /* Timings */
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_HI;
+       if (image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value = (u8) 0;
+       else
+               cmd.buffer.registers[i++].value = (u8) 1;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_LO;
+       if (image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value = (u8) 208;
+       else
+               cmd.buffer.registers[i++].value = (u8) 160;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_HI;
+       if (image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value = (u8) 0;
+       else
+               cmd.buffer.registers[i++].value = (u8) 1;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_LO;
+       if (image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value = (u8) 160;
+       else
+               cmd.buffer.registers[i++].value = (u8) 64;
+
+       /* Output Image Size */
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_OHSIZE;
+       cmd.buffer.registers[i++].value = cam->params.roi.width / 4;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_OVSIZE;
+       cmd.buffer.registers[i++].value = cam->params.roi.height / 4;
+
+       /* Cropping */
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_HCROP;
+       if (image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value =
+                   (u8) (((STV_IMAGE_QCIF_COLS / 4) - (width / 4)) / 2);
+       else
+               cmd.buffer.registers[i++].value =
+                   (u8) (((STV_IMAGE_CIF_COLS / 4) - (width / 4)) / 2);
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_VCROP;
+       if (image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value =
+                   (u8) (((STV_IMAGE_QCIF_ROWS / 4) - (height / 4)) / 2);
+       else
+               cmd.buffer.registers[i++].value =
+                   (u8) (((STV_IMAGE_CIF_ROWS / 4) - (height / 4)) / 2);
+
+       /* Scaling registers (defaults) */
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_HPHASE;
+       cmd.buffer.registers[i++].value = (u8) 0;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_VPHASE;
+       cmd.buffer.registers[i++].value = (u8) 0;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_HISPAN;
+       cmd.buffer.registers[i++].value = (u8) 31;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_VISPAN;
+       cmd.buffer.registers[i++].value = (u8) 31;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_HICROP;
+       cmd.buffer.registers[i++].value = (u8) 0;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_VICROP;
+       cmd.buffer.registers[i++].value = (u8) 0;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_HFRACT;
+       cmd.buffer.registers[i++].value = (u8) 0x81;    /* = 8/1 = 8 (HIBYTE/LOBYTE) */
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_VFRACT;
+       cmd.buffer.registers[i++].value = (u8) 0x81;    /* = 8/1 = 8 (HIBYTE/LOBYTE) */
+
+       cmd.reg_count = i;
+
+       cpia2_send_command(cam, &cmd);
+
+       return i;
+}
+
+
+/******************************************************************************
+ *
+ *  config_sensor_500(cam)
+ *
+ *****************************************************************************/
+static int config_sensor_500(struct camera_data *cam,
+                            int req_width, int req_height)
+{
+       struct cpia2_command cmd;
+       int i = 0;
+       int image_size = VIDEOSIZE_CIF;
+       int image_type = VIDEOSIZE_VGA;
+       int width = req_width;
+       int height = req_height;
+       unsigned int device = cam->params.pnp_id.device_type;
+
+       image_size = cpia2_match_video_size(width, height);
+
+       if (width > STV_IMAGE_CIF_COLS || height > STV_IMAGE_CIF_ROWS)
+               image_type = VIDEOSIZE_VGA;
+       else if (width > STV_IMAGE_QVGA_COLS || height > STV_IMAGE_QVGA_ROWS)
+               image_type = VIDEOSIZE_CIF;
+       else if (width > STV_IMAGE_QCIF_COLS || height > STV_IMAGE_QCIF_ROWS)
+               image_type = VIDEOSIZE_QVGA;
+       else
+               image_type = VIDEOSIZE_QCIF;
+
+       if (image_size >= 0) {
+               set_vw_size(cam, image_size);
+               width = cam->params.roi.width;
+               height = cam->params.roi.height;
+       } else {
+               ERR("ConfigSensor500 failed\n");
+               return -EINVAL;
+       }
+
+       DBG("image_size = %d, width = %d, height = %d, type = %d\n",
+           image_size, width, height, image_type);
+
+       cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC;
+       cmd.direction = TRANSFER_WRITE;
+       i = 0;
+
+       /* VC Format */
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_FORMAT;
+       cmd.buffer.registers[i].value = (u8) CPIA2_VC_VC_FORMAT_UFIRST;
+       if (image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i].value |= (u8) CPIA2_VC_VC_FORMAT_DECIMATING;
+       i++;
+
+       /* VC Clocks */
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_CLOCKS;
+       if (device == DEVICE_STV_672) {
+               if (image_type == VIDEOSIZE_VGA)
+                       cmd.buffer.registers[i].value =
+                               (u8)CPIA2_VC_VC_CLOCKS_LOGDIV1;
+               else
+                       cmd.buffer.registers[i].value =
+                               (u8)(CPIA2_VC_VC_672_CLOCKS_SCALING |
+                                    CPIA2_VC_VC_CLOCKS_LOGDIV3);
+       } else {
+               if (image_type == VIDEOSIZE_VGA)
+                       cmd.buffer.registers[i].value =
+                               (u8)CPIA2_VC_VC_CLOCKS_LOGDIV0;
+               else
+                       cmd.buffer.registers[i].value =
+                               (u8)(CPIA2_VC_VC_676_CLOCKS_SCALING |
+                                    CPIA2_VC_VC_CLOCKS_LOGDIV2);
+       }
+       i++;
+
+       DBG("VC_CLOCKS = 0x%X\n", cmd.buffer.registers[i-1].value);
+
+       /* Input width from VP */
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_IHSIZE_LO;
+       if (image_type == VIDEOSIZE_VGA)
+               cmd.buffer.registers[i].value =
+                   (u8) (STV_IMAGE_VGA_COLS / 4);
+       else
+               cmd.buffer.registers[i].value =
+                   (u8) (STV_IMAGE_QVGA_COLS / 4);
+       i++;
+       DBG("Input width = %d\n", cmd.buffer.registers[i-1].value);
+
+       /* Timings */
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_HI;
+       if (image_type == VIDEOSIZE_VGA)
+               cmd.buffer.registers[i++].value = (u8) 2;
+       else
+               cmd.buffer.registers[i++].value = (u8) 1;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_LO;
+       if (image_type == VIDEOSIZE_VGA)
+               cmd.buffer.registers[i++].value = (u8) 250;
+       else if (image_type == VIDEOSIZE_QVGA)
+               cmd.buffer.registers[i++].value = (u8) 125;
+       else
+               cmd.buffer.registers[i++].value = (u8) 160;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_HI;
+       if (image_type == VIDEOSIZE_VGA)
+               cmd.buffer.registers[i++].value = (u8) 2;
+       else
+               cmd.buffer.registers[i++].value = (u8) 1;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_LO;
+       if (image_type == VIDEOSIZE_VGA)
+               cmd.buffer.registers[i++].value = (u8) 12;
+       else if (image_type == VIDEOSIZE_QVGA)
+               cmd.buffer.registers[i++].value = (u8) 64;
+       else
+               cmd.buffer.registers[i++].value = (u8) 6;
+
+       /* Output Image Size */
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_OHSIZE;
+       if (image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value = STV_IMAGE_CIF_COLS  / 4;
+       else
+               cmd.buffer.registers[i++].value = width / 4;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_OVSIZE;
+       if (image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value = STV_IMAGE_CIF_ROWS  / 4;
+       else
+               cmd.buffer.registers[i++].value = height / 4;
+
+       /* Cropping */
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_HCROP;
+       if (image_type == VIDEOSIZE_VGA)
+               cmd.buffer.registers[i++].value =
+                   (u8) (((STV_IMAGE_VGA_COLS / 4) - (width / 4)) / 2);
+       else if (image_type == VIDEOSIZE_QVGA)
+               cmd.buffer.registers[i++].value =
+                   (u8) (((STV_IMAGE_QVGA_COLS / 4) - (width / 4)) / 2);
+       else if (image_type == VIDEOSIZE_CIF)
+               cmd.buffer.registers[i++].value =
+                   (u8) (((STV_IMAGE_CIF_COLS / 4) - (width / 4)) / 2);
+       else /*if (image_type == VIDEOSIZE_QCIF)*/
+               cmd.buffer.registers[i++].value =
+                       (u8) (((STV_IMAGE_QCIF_COLS / 4) - (width / 4)) / 2);
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_VCROP;
+       if (image_type == VIDEOSIZE_VGA)
+               cmd.buffer.registers[i++].value =
+                   (u8) (((STV_IMAGE_VGA_ROWS / 4) - (height / 4)) / 2);
+       else if (image_type == VIDEOSIZE_QVGA)
+               cmd.buffer.registers[i++].value =
+                   (u8) (((STV_IMAGE_QVGA_ROWS / 4) - (height / 4)) / 2);
+       else if (image_type == VIDEOSIZE_CIF)
+               cmd.buffer.registers[i++].value =
+                   (u8) (((STV_IMAGE_CIF_ROWS / 4) - (height / 4)) / 2);
+       else /*if (image_type == VIDEOSIZE_QCIF)*/
+               cmd.buffer.registers[i++].value =
+                   (u8) (((STV_IMAGE_QCIF_ROWS / 4) - (height / 4)) / 2);
+
+       /* Scaling registers (defaults) */
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_HPHASE;
+       if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value = (u8) 36;
+       else
+               cmd.buffer.registers[i++].value = (u8) 0;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_VPHASE;
+       if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value = (u8) 32;
+       else
+               cmd.buffer.registers[i++].value = (u8) 0;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_HISPAN;
+       if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value = (u8) 26;
+       else
+               cmd.buffer.registers[i++].value = (u8) 31;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_VISPAN;
+       if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value = (u8) 21;
+       else
+               cmd.buffer.registers[i++].value = (u8) 31;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_HICROP;
+       cmd.buffer.registers[i++].value = (u8) 0;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_VICROP;
+       cmd.buffer.registers[i++].value = (u8) 0;
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_HFRACT;
+       if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value = (u8) 0x2B;    /* 2/11 */
+       else
+               cmd.buffer.registers[i++].value = (u8) 0x81;    /* 8/1 */
+
+       cmd.buffer.registers[i].index = CPIA2_VC_VC_VFRACT;
+       if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF)
+               cmd.buffer.registers[i++].value = (u8) 0x13;    /* 1/3 */
+       else
+               cmd.buffer.registers[i++].value = (u8) 0x81;    /* 8/1 */
+
+       cmd.reg_count = i;
+
+       cpia2_send_command(cam, &cmd);
+
+       return i;
+}
+
+
+/******************************************************************************
+ *
+ *  setallproperties
+ *
+ *  This sets all user changeable properties to the values in cam->params.
+ *****************************************************************************/
+static int set_all_properties(struct camera_data *cam)
+{
+       /**
+        * Don't set target_kb here, it will be set later.
+        * framerate and user_mode were already set (set_default_user_mode).
+        **/
+
+       cpia2_usb_change_streaming_alternate(cam,
+                                         cam->params.camera_state.stream_mode);
+
+       cpia2_do_command(cam,
+                        CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION,
+                        TRANSFER_WRITE, cam->params.vp_params.gpio_direction);
+       cpia2_do_command(cam, CPIA2_CMD_SET_VC_MP_GPIO_DATA, TRANSFER_WRITE,
+                        cam->params.vp_params.gpio_data);
+
+       v4l2_ctrl_handler_setup(&cam->hdl);
+
+       wake_system(cam);
+
+       set_lowlight_boost(cam);
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_save_camera_state
+ *
+ *****************************************************************************/
+void cpia2_save_camera_state(struct camera_data *cam)
+{
+       cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, TRANSFER_READ, 0);
+       cpia2_do_command(cam, CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION, TRANSFER_READ,
+                        0);
+       cpia2_do_command(cam, CPIA2_CMD_GET_VC_MP_GPIO_DATA, TRANSFER_READ, 0);
+       /* Don't get framerate or target_kb. Trust the values we already have */
+}
+
+
+/******************************************************************************
+ *
+ *  cpia2_set_flicker_mode
+ *
+ *****************************************************************************/
+int cpia2_set_flicker_mode(struct camera_data *cam, int mode)
+{
+       unsigned char cam_reg;
+       int err = 0;
+
+       if(cam->params.pnp_id.device_type != DEVICE_STV_672)
+               return -EINVAL;
+
+       /* Set the appropriate bits in FLICKER_MODES, preserving the rest */
+       if((err = cpia2_do_command(cam, CPIA2_CMD_GET_FLICKER_MODES,
+                                  TRANSFER_READ, 0)))
+               return err;
+       cam_reg = cam->params.flicker_control.cam_register;
+
+       switch(mode) {
+       case NEVER_FLICKER:
+               cam_reg |= CPIA2_VP_FLICKER_MODES_NEVER_FLICKER;
+               cam_reg &= ~CPIA2_VP_FLICKER_MODES_50HZ;
+               break;
+       case FLICKER_60:
+               cam_reg &= ~CPIA2_VP_FLICKER_MODES_NEVER_FLICKER;
+               cam_reg &= ~CPIA2_VP_FLICKER_MODES_50HZ;
+               break;
+       case FLICKER_50:
+               cam_reg &= ~CPIA2_VP_FLICKER_MODES_NEVER_FLICKER;
+               cam_reg |= CPIA2_VP_FLICKER_MODES_50HZ;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if((err = cpia2_do_command(cam, CPIA2_CMD_SET_FLICKER_MODES,
+                                  TRANSFER_WRITE, cam_reg)))
+               return err;
+
+       /* Set the appropriate bits in EXP_MODES, preserving the rest */
+       if((err = cpia2_do_command(cam, CPIA2_CMD_GET_VP_EXP_MODES,
+                                  TRANSFER_READ, 0)))
+               return err;
+       cam_reg = cam->params.vp_params.exposure_modes;
+
+       if (mode == NEVER_FLICKER) {
+               cam_reg |= CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER;
+       } else {
+               cam_reg &= ~CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER;
+       }
+
+       if((err = cpia2_do_command(cam, CPIA2_CMD_SET_VP_EXP_MODES,
+                                  TRANSFER_WRITE, cam_reg)))
+               return err;
+
+       if((err = cpia2_do_command(cam, CPIA2_CMD_REHASH_VP4,
+                                  TRANSFER_WRITE, 1)))
+               return err;
+
+       switch(mode) {
+       case NEVER_FLICKER:
+       case FLICKER_60:
+       case FLICKER_50:
+               cam->params.flicker_control.flicker_mode_req = mode;
+               break;
+       default:
+               err = -EINVAL;
+       }
+
+       return err;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_set_property_flip
+ *
+ *****************************************************************************/
+void cpia2_set_property_flip(struct camera_data *cam, int prop_val)
+{
+       unsigned char cam_reg;
+
+       cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, TRANSFER_READ, 0);
+       cam_reg = cam->params.vp_params.user_effects;
+
+       if (prop_val)
+       {
+               cam_reg |= CPIA2_VP_USER_EFFECTS_FLIP;
+       }
+       else
+       {
+               cam_reg &= ~CPIA2_VP_USER_EFFECTS_FLIP;
+       }
+       cam->params.vp_params.user_effects = cam_reg;
+       cpia2_do_command(cam, CPIA2_CMD_SET_USER_EFFECTS, TRANSFER_WRITE,
+                        cam_reg);
+}
+
+/******************************************************************************
+ *
+ *  cpia2_set_property_mirror
+ *
+ *****************************************************************************/
+void cpia2_set_property_mirror(struct camera_data *cam, int prop_val)
+{
+       unsigned char cam_reg;
+
+       cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, TRANSFER_READ, 0);
+       cam_reg = cam->params.vp_params.user_effects;
+
+       if (prop_val)
+       {
+               cam_reg |= CPIA2_VP_USER_EFFECTS_MIRROR;
+       }
+       else
+       {
+               cam_reg &= ~CPIA2_VP_USER_EFFECTS_MIRROR;
+       }
+       cam->params.vp_params.user_effects = cam_reg;
+       cpia2_do_command(cam, CPIA2_CMD_SET_USER_EFFECTS, TRANSFER_WRITE,
+                        cam_reg);
+}
+
+/******************************************************************************
+ *
+ *  cpia2_set_gpio
+ *
+ *****************************************************************************/
+int cpia2_set_gpio(struct camera_data *cam, unsigned char setting)
+{
+       int ret;
+
+       /* Set the microport direction (register 0x90, should be defined
+        * already) to 1 (user output), and set the microport data (0x91) to
+        * the value in the ioctl argument.
+        */
+
+       ret = cpia2_do_command(cam,
+                              CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION,
+                              CPIA2_VC_MP_DIR_OUTPUT,
+                              255);
+       if (ret < 0)
+               return ret;
+       cam->params.vp_params.gpio_direction = 255;
+
+       ret = cpia2_do_command(cam,
+                              CPIA2_CMD_SET_VC_MP_GPIO_DATA,
+                              CPIA2_VC_MP_DIR_OUTPUT,
+                              setting);
+       if (ret < 0)
+               return ret;
+       cam->params.vp_params.gpio_data = setting;
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_set_fps
+ *
+ *****************************************************************************/
+int cpia2_set_fps(struct camera_data *cam, int framerate)
+{
+       int retval;
+
+       switch(framerate) {
+               case CPIA2_VP_FRAMERATE_30:
+               case CPIA2_VP_FRAMERATE_25:
+                       if(cam->params.pnp_id.device_type == DEVICE_STV_672 &&
+                          cam->params.version.sensor_flags ==
+                                                   CPIA2_VP_SENSOR_FLAGS_500) {
+                               return -EINVAL;
+                       }
+                       /* Fall through */
+               case CPIA2_VP_FRAMERATE_15:
+               case CPIA2_VP_FRAMERATE_12_5:
+               case CPIA2_VP_FRAMERATE_7_5:
+               case CPIA2_VP_FRAMERATE_6_25:
+                       break;
+               default:
+                       return -EINVAL;
+       }
+
+       if (cam->params.pnp_id.device_type == DEVICE_STV_672 &&
+           framerate == CPIA2_VP_FRAMERATE_15)
+               framerate = 0; /* Work around bug in VP4 */
+
+       retval = cpia2_do_command(cam,
+                                CPIA2_CMD_FRAMERATE_REQ,
+                                TRANSFER_WRITE,
+                                framerate);
+
+       if(retval == 0)
+               cam->params.vp_params.frame_rate = framerate;
+
+       return retval;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_set_brightness
+ *
+ *****************************************************************************/
+void cpia2_set_brightness(struct camera_data *cam, unsigned char value)
+{
+       /***
+        * Don't let the register be set to zero - bug in VP4 - flash of full
+        * brightness
+        ***/
+       if (cam->params.pnp_id.device_type == DEVICE_STV_672 && value == 0)
+               value++;
+       DBG("Setting brightness to %d (0x%0x)\n", value, value);
+       cpia2_do_command(cam, CPIA2_CMD_SET_VP_BRIGHTNESS, TRANSFER_WRITE, value);
+}
+
+/******************************************************************************
+ *
+ *  cpia2_set_contrast
+ *
+ *****************************************************************************/
+void cpia2_set_contrast(struct camera_data *cam, unsigned char value)
+{
+       DBG("Setting contrast to %d (0x%0x)\n", value, value);
+       cpia2_do_command(cam, CPIA2_CMD_SET_CONTRAST, TRANSFER_WRITE, value);
+}
+
+/******************************************************************************
+ *
+ *  cpia2_set_saturation
+ *
+ *****************************************************************************/
+void cpia2_set_saturation(struct camera_data *cam, unsigned char value)
+{
+       DBG("Setting saturation to %d (0x%0x)\n", value, value);
+       cpia2_do_command(cam,CPIA2_CMD_SET_VP_SATURATION, TRANSFER_WRITE,value);
+}
+
+/******************************************************************************
+ *
+ *  wake_system
+ *
+ *****************************************************************************/
+static void wake_system(struct camera_data *cam)
+{
+       cpia2_do_command(cam, CPIA2_CMD_SET_WAKEUP, TRANSFER_WRITE, 0);
+}
+
+/******************************************************************************
+ *
+ *  set_lowlight_boost
+ *
+ *  Valid for STV500 sensor only
+ *****************************************************************************/
+static void set_lowlight_boost(struct camera_data *cam)
+{
+       struct cpia2_command cmd;
+
+       if (cam->params.pnp_id.device_type != DEVICE_STV_672 ||
+           cam->params.version.sensor_flags != CPIA2_VP_SENSOR_FLAGS_500)
+               return;
+
+       cmd.direction = TRANSFER_WRITE;
+       cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+       cmd.reg_count = 3;
+       cmd.start = CPIA2_VP_RAM_ADDR_H;
+
+       cmd.buffer.block_data[0] = 0;   /* High byte of address to write to */
+       cmd.buffer.block_data[1] = 0x59;        /* Low byte of address to write to */
+       cmd.buffer.block_data[2] = 0;   /* High byte of data to write */
+
+       cpia2_send_command(cam, &cmd);
+
+       if (cam->params.vp_params.lowlight_boost) {
+               cmd.buffer.block_data[0] = 0x02;        /* Low byte data to write */
+       } else {
+               cmd.buffer.block_data[0] = 0x06;
+       }
+       cmd.start = CPIA2_VP_RAM_DATA;
+       cmd.reg_count = 1;
+       cpia2_send_command(cam, &cmd);
+
+       /* Rehash the VP4 values */
+       cpia2_do_command(cam, CPIA2_CMD_REHASH_VP4, TRANSFER_WRITE, 1);
+}
+
+/******************************************************************************
+ *
+ *  cpia2_set_format
+ *
+ *  Assumes that new size is already set in param struct.
+ *****************************************************************************/
+void cpia2_set_format(struct camera_data *cam)
+{
+       cam->flush = true;
+
+       cpia2_usb_stream_pause(cam);
+
+       /* reset camera to new size */
+       cpia2_set_low_power(cam);
+       cpia2_reset_camera(cam);
+       cam->flush = false;
+
+       cpia2_dbg_dump_registers(cam);
+
+       cpia2_usb_stream_resume(cam);
+}
+
+/******************************************************************************
+ *
+ * cpia2_dbg_dump_registers
+ *
+ *****************************************************************************/
+void cpia2_dbg_dump_registers(struct camera_data *cam)
+{
+#ifdef _CPIA2_DEBUG_
+       struct cpia2_command cmd;
+
+       if (!(debugs_on & DEBUG_DUMP_REGS))
+               return;
+
+       cmd.direction = TRANSFER_READ;
+
+       /* Start with bank 0 (SYSTEM) */
+       cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
+       cmd.reg_count = 3;
+       cmd.start = 0;
+       cpia2_send_command(cam, &cmd);
+       printk(KERN_DEBUG "System Device Hi      = 0x%X\n",
+              cmd.buffer.block_data[0]);
+       printk(KERN_DEBUG "System Device Lo      = 0x%X\n",
+              cmd.buffer.block_data[1]);
+       printk(KERN_DEBUG "System_system control = 0x%X\n",
+              cmd.buffer.block_data[2]);
+
+       /* Bank 1 (VC) */
+       cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
+       cmd.reg_count = 4;
+       cmd.start = 0x80;
+       cpia2_send_command(cam, &cmd);
+       printk(KERN_DEBUG "ASIC_ID       = 0x%X\n",
+              cmd.buffer.block_data[0]);
+       printk(KERN_DEBUG "ASIC_REV      = 0x%X\n",
+              cmd.buffer.block_data[1]);
+       printk(KERN_DEBUG "PW_CONTRL     = 0x%X\n",
+              cmd.buffer.block_data[2]);
+       printk(KERN_DEBUG "WAKEUP        = 0x%X\n",
+              cmd.buffer.block_data[3]);
+
+       cmd.start = 0xA0;       /* ST_CTRL */
+       cmd.reg_count = 1;
+       cpia2_send_command(cam, &cmd);
+       printk(KERN_DEBUG "Stream ctrl   = 0x%X\n",
+              cmd.buffer.block_data[0]);
+
+       cmd.start = 0xA4;       /* Stream status */
+       cpia2_send_command(cam, &cmd);
+       printk(KERN_DEBUG "Stream status = 0x%X\n",
+              cmd.buffer.block_data[0]);
+
+       cmd.start = 0xA8;       /* USB status */
+       cmd.reg_count = 3;
+       cpia2_send_command(cam, &cmd);
+       printk(KERN_DEBUG "USB_CTRL      = 0x%X\n",
+              cmd.buffer.block_data[0]);
+       printk(KERN_DEBUG "USB_STRM      = 0x%X\n",
+              cmd.buffer.block_data[1]);
+       printk(KERN_DEBUG "USB_STATUS    = 0x%X\n",
+              cmd.buffer.block_data[2]);
+
+       cmd.start = 0xAF;       /* USB settings */
+       cmd.reg_count = 1;
+       cpia2_send_command(cam, &cmd);
+       printk(KERN_DEBUG "USB settings  = 0x%X\n",
+              cmd.buffer.block_data[0]);
+
+       cmd.start = 0xC0;       /* VC stuff */
+       cmd.reg_count = 26;
+       cpia2_send_command(cam, &cmd);
+       printk(KERN_DEBUG "VC Control    = 0x%0X\n",
+              cmd.buffer.block_data[0]);
+       printk(KERN_DEBUG "VC Format     = 0x%0X\n",
+              cmd.buffer.block_data[3]);
+       printk(KERN_DEBUG "VC Clocks     = 0x%0X\n",
+              cmd.buffer.block_data[4]);
+       printk(KERN_DEBUG "VC IHSize     = 0x%0X\n",
+              cmd.buffer.block_data[5]);
+       printk(KERN_DEBUG "VC Xlim Hi    = 0x%0X\n",
+              cmd.buffer.block_data[6]);
+       printk(KERN_DEBUG "VC XLim Lo    = 0x%0X\n",
+              cmd.buffer.block_data[7]);
+       printk(KERN_DEBUG "VC YLim Hi    = 0x%0X\n",
+              cmd.buffer.block_data[8]);
+       printk(KERN_DEBUG "VC YLim Lo    = 0x%0X\n",
+              cmd.buffer.block_data[9]);
+       printk(KERN_DEBUG "VC OHSize     = 0x%0X\n",
+              cmd.buffer.block_data[10]);
+       printk(KERN_DEBUG "VC OVSize     = 0x%0X\n",
+              cmd.buffer.block_data[11]);
+       printk(KERN_DEBUG "VC HCrop      = 0x%0X\n",
+              cmd.buffer.block_data[12]);
+       printk(KERN_DEBUG "VC VCrop      = 0x%0X\n",
+              cmd.buffer.block_data[13]);
+       printk(KERN_DEBUG "VC HPhase     = 0x%0X\n",
+              cmd.buffer.block_data[14]);
+       printk(KERN_DEBUG "VC VPhase     = 0x%0X\n",
+              cmd.buffer.block_data[15]);
+       printk(KERN_DEBUG "VC HIspan     = 0x%0X\n",
+              cmd.buffer.block_data[16]);
+       printk(KERN_DEBUG "VC VIspan     = 0x%0X\n",
+              cmd.buffer.block_data[17]);
+       printk(KERN_DEBUG "VC HiCrop     = 0x%0X\n",
+              cmd.buffer.block_data[18]);
+       printk(KERN_DEBUG "VC ViCrop     = 0x%0X\n",
+              cmd.buffer.block_data[19]);
+       printk(KERN_DEBUG "VC HiFract    = 0x%0X\n",
+              cmd.buffer.block_data[20]);
+       printk(KERN_DEBUG "VC ViFract    = 0x%0X\n",
+              cmd.buffer.block_data[21]);
+       printk(KERN_DEBUG "VC JPeg Opt   = 0x%0X\n",
+              cmd.buffer.block_data[22]);
+       printk(KERN_DEBUG "VC Creep Per  = 0x%0X\n",
+              cmd.buffer.block_data[23]);
+       printk(KERN_DEBUG "VC User Sq.   = 0x%0X\n",
+              cmd.buffer.block_data[24]);
+       printk(KERN_DEBUG "VC Target KB  = 0x%0X\n",
+              cmd.buffer.block_data[25]);
+
+       /*** VP ***/
+       cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
+       cmd.reg_count = 14;
+       cmd.start = 0;
+       cpia2_send_command(cam, &cmd);
+
+       printk(KERN_DEBUG "VP Dev Hi     = 0x%0X\n",
+              cmd.buffer.block_data[0]);
+       printk(KERN_DEBUG "VP Dev Lo     = 0x%0X\n",
+              cmd.buffer.block_data[1]);
+       printk(KERN_DEBUG "VP Sys State  = 0x%0X\n",
+              cmd.buffer.block_data[2]);
+       printk(KERN_DEBUG "VP Sys Ctrl   = 0x%0X\n",
+              cmd.buffer.block_data[3]);
+       printk(KERN_DEBUG "VP Sensor flg = 0x%0X\n",
+              cmd.buffer.block_data[5]);
+       printk(KERN_DEBUG "VP Sensor Rev = 0x%0X\n",
+              cmd.buffer.block_data[6]);
+       printk(KERN_DEBUG "VP Dev Config = 0x%0X\n",
+              cmd.buffer.block_data[7]);
+       printk(KERN_DEBUG "VP GPIO_DIR   = 0x%0X\n",
+              cmd.buffer.block_data[8]);
+       printk(KERN_DEBUG "VP GPIO_DATA  = 0x%0X\n",
+              cmd.buffer.block_data[9]);
+       printk(KERN_DEBUG "VP Ram ADDR H = 0x%0X\n",
+              cmd.buffer.block_data[10]);
+       printk(KERN_DEBUG "VP Ram ADDR L = 0x%0X\n",
+              cmd.buffer.block_data[11]);
+       printk(KERN_DEBUG "VP RAM Data   = 0x%0X\n",
+              cmd.buffer.block_data[12]);
+       printk(KERN_DEBUG "Do Call       = 0x%0X\n",
+              cmd.buffer.block_data[13]);
+
+       if (cam->params.pnp_id.device_type == DEVICE_STV_672) {
+               cmd.reg_count = 9;
+               cmd.start = 0x0E;
+               cpia2_send_command(cam, &cmd);
+               printk(KERN_DEBUG "VP Clock Ctrl = 0x%0X\n",
+                      cmd.buffer.block_data[0]);
+               printk(KERN_DEBUG "VP Patch Rev  = 0x%0X\n",
+                      cmd.buffer.block_data[1]);
+               printk(KERN_DEBUG "VP Vid Mode   = 0x%0X\n",
+                      cmd.buffer.block_data[2]);
+               printk(KERN_DEBUG "VP Framerate  = 0x%0X\n",
+                      cmd.buffer.block_data[3]);
+               printk(KERN_DEBUG "VP UserEffect = 0x%0X\n",
+                      cmd.buffer.block_data[4]);
+               printk(KERN_DEBUG "VP White Bal  = 0x%0X\n",
+                      cmd.buffer.block_data[5]);
+               printk(KERN_DEBUG "VP WB thresh  = 0x%0X\n",
+                      cmd.buffer.block_data[6]);
+               printk(KERN_DEBUG "VP Exp Modes  = 0x%0X\n",
+                      cmd.buffer.block_data[7]);
+               printk(KERN_DEBUG "VP Exp Target = 0x%0X\n",
+                      cmd.buffer.block_data[8]);
+
+               cmd.reg_count = 1;
+               cmd.start = 0x1B;
+               cpia2_send_command(cam, &cmd);
+               printk(KERN_DEBUG "VP FlickerMds = 0x%0X\n",
+                      cmd.buffer.block_data[0]);
+       } else {
+               cmd.reg_count = 8 ;
+               cmd.start = 0x0E;
+               cpia2_send_command(cam, &cmd);
+               printk(KERN_DEBUG "VP Clock Ctrl = 0x%0X\n",
+                      cmd.buffer.block_data[0]);
+               printk(KERN_DEBUG "VP Patch Rev  = 0x%0X\n",
+                      cmd.buffer.block_data[1]);
+               printk(KERN_DEBUG "VP Vid Mode   = 0x%0X\n",
+                      cmd.buffer.block_data[5]);
+               printk(KERN_DEBUG "VP Framerate  = 0x%0X\n",
+                      cmd.buffer.block_data[6]);
+               printk(KERN_DEBUG "VP UserEffect = 0x%0X\n",
+                      cmd.buffer.block_data[7]);
+
+               cmd.reg_count = 1;
+               cmd.start = CPIA2_VP5_EXPOSURE_TARGET;
+               cpia2_send_command(cam, &cmd);
+               printk(KERN_DEBUG "VP5 Exp Target= 0x%0X\n",
+                      cmd.buffer.block_data[0]);
+
+               cmd.reg_count = 4;
+               cmd.start = 0x3A;
+               cpia2_send_command(cam, &cmd);
+               printk(KERN_DEBUG "VP5 MY Black  = 0x%0X\n",
+                      cmd.buffer.block_data[0]);
+               printk(KERN_DEBUG "VP5 MCY Range = 0x%0X\n",
+                      cmd.buffer.block_data[1]);
+               printk(KERN_DEBUG "VP5 MYCEILING = 0x%0X\n",
+                      cmd.buffer.block_data[2]);
+               printk(KERN_DEBUG "VP5 MCUV Sat  = 0x%0X\n",
+                      cmd.buffer.block_data[3]);
+       }
+#endif
+}
+
+/******************************************************************************
+ *
+ *  reset_camera_struct
+ *
+ *  Sets all values to the defaults
+ *****************************************************************************/
+static void reset_camera_struct(struct camera_data *cam)
+{
+       /***
+        * The following parameter values are the defaults from the register map.
+        ***/
+       cam->params.vp_params.lowlight_boost = 0;
+
+       /* FlickerModes */
+       cam->params.flicker_control.flicker_mode_req = NEVER_FLICKER;
+
+       /* jpeg params */
+       cam->params.compression.jpeg_options = CPIA2_VC_VC_JPEG_OPT_DEFAULT;
+       cam->params.compression.creep_period = 2;
+       cam->params.compression.user_squeeze = 20;
+       cam->params.compression.inhibit_htables = false;
+
+       /* gpio params */
+       cam->params.vp_params.gpio_direction = 0;       /* write, the default safe mode */
+       cam->params.vp_params.gpio_data = 0;
+
+       /* Target kb params */
+       cam->params.vc_params.quality = 100;
+
+       /***
+        * Set Sensor FPS as fast as possible.
+        ***/
+       if(cam->params.pnp_id.device_type == DEVICE_STV_672) {
+               if(cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500)
+                       cam->params.vp_params.frame_rate = CPIA2_VP_FRAMERATE_15;
+               else
+                       cam->params.vp_params.frame_rate = CPIA2_VP_FRAMERATE_30;
+       } else {
+               cam->params.vp_params.frame_rate = CPIA2_VP_FRAMERATE_30;
+       }
+
+       /***
+        * Set default video mode as large as possible :
+        * for vga sensor set to vga, for cif sensor set to CIF.
+        ***/
+       if (cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500) {
+               cam->sensor_type = CPIA2_SENSOR_500;
+               cam->video_size = VIDEOSIZE_VGA;
+               cam->params.roi.width = STV_IMAGE_VGA_COLS;
+               cam->params.roi.height = STV_IMAGE_VGA_ROWS;
+       } else {
+               cam->sensor_type = CPIA2_SENSOR_410;
+               cam->video_size = VIDEOSIZE_CIF;
+               cam->params.roi.width = STV_IMAGE_CIF_COLS;
+               cam->params.roi.height = STV_IMAGE_CIF_ROWS;
+       }
+
+       cam->width = cam->params.roi.width;
+       cam->height = cam->params.roi.height;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_init_camera_struct
+ *
+ *  Initializes camera struct, does not call reset to fill in defaults.
+ *****************************************************************************/
+struct camera_data *cpia2_init_camera_struct(struct usb_interface *intf)
+{
+       struct camera_data *cam;
+
+       cam = kzalloc(sizeof(*cam), GFP_KERNEL);
+
+       if (!cam) {
+               ERR("couldn't kmalloc cpia2 struct\n");
+               return NULL;
+       }
+
+       cam->v4l2_dev.release = cpia2_camera_release;
+       if (v4l2_device_register(&intf->dev, &cam->v4l2_dev) < 0) {
+               v4l2_err(&cam->v4l2_dev, "couldn't register v4l2_device\n");
+               kfree(cam);
+               return NULL;
+       }
+
+       mutex_init(&cam->v4l2_lock);
+       init_waitqueue_head(&cam->wq_stream);
+
+       return cam;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_init_camera
+ *
+ *  Initializes camera.
+ *****************************************************************************/
+int cpia2_init_camera(struct camera_data *cam)
+{
+       DBG("Start\n");
+
+       cam->mmapped = false;
+
+       /* Get sensor and asic types before reset. */
+       cpia2_set_high_power(cam);
+       cpia2_get_version_info(cam);
+       if (cam->params.version.asic_id != CPIA2_ASIC_672) {
+               ERR("Device IO error (asicID has incorrect value of 0x%X\n",
+                   cam->params.version.asic_id);
+               return -ENODEV;
+       }
+
+       /* Set GPIO direction and data to a safe state. */
+       cpia2_do_command(cam, CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION,
+                        TRANSFER_WRITE, 0);
+       cpia2_do_command(cam, CPIA2_CMD_SET_VC_MP_GPIO_DATA,
+                        TRANSFER_WRITE, 0);
+
+       /* resetting struct requires version info for sensor and asic types */
+       reset_camera_struct(cam);
+
+       cpia2_set_low_power(cam);
+
+       DBG("End\n");
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_allocate_buffers
+ *
+ *****************************************************************************/
+int cpia2_allocate_buffers(struct camera_data *cam)
+{
+       int i;
+
+       if(!cam->buffers) {
+               u32 size = cam->num_frames*sizeof(struct framebuf);
+               cam->buffers = kmalloc(size, GFP_KERNEL);
+               if(!cam->buffers) {
+                       ERR("couldn't kmalloc frame buffer structures\n");
+                       return -ENOMEM;
+               }
+       }
+
+       if(!cam->frame_buffer) {
+               cam->frame_buffer = rvmalloc(cam->frame_size*cam->num_frames);
+               if (!cam->frame_buffer) {
+                       ERR("couldn't vmalloc frame buffer data area\n");
+                       kfree(cam->buffers);
+                       cam->buffers = NULL;
+                       return -ENOMEM;
+               }
+       }
+
+       for(i=0; i<cam->num_frames-1; ++i) {
+               cam->buffers[i].next = &cam->buffers[i+1];
+               cam->buffers[i].data = cam->frame_buffer +i*cam->frame_size;
+               cam->buffers[i].status = FRAME_EMPTY;
+               cam->buffers[i].length = 0;
+               cam->buffers[i].max_length = 0;
+               cam->buffers[i].num = i;
+       }
+       cam->buffers[i].next = cam->buffers;
+       cam->buffers[i].data = cam->frame_buffer +i*cam->frame_size;
+       cam->buffers[i].status = FRAME_EMPTY;
+       cam->buffers[i].length = 0;
+       cam->buffers[i].max_length = 0;
+       cam->buffers[i].num = i;
+       cam->curbuff = cam->buffers;
+       cam->workbuff = cam->curbuff->next;
+       DBG("buffers=%p, curbuff=%p, workbuff=%p\n", cam->buffers, cam->curbuff,
+           cam->workbuff);
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_free_buffers
+ *
+ *****************************************************************************/
+void cpia2_free_buffers(struct camera_data *cam)
+{
+       if(cam->buffers) {
+               kfree(cam->buffers);
+               cam->buffers = NULL;
+       }
+       if(cam->frame_buffer) {
+               rvfree(cam->frame_buffer, cam->frame_size*cam->num_frames);
+               cam->frame_buffer = NULL;
+       }
+}
+
+/******************************************************************************
+ *
+ *  cpia2_read
+ *
+ *****************************************************************************/
+long cpia2_read(struct camera_data *cam,
+               char __user *buf, unsigned long count, int noblock)
+{
+       struct framebuf *frame;
+
+       if (!count)
+               return 0;
+
+       if (!buf) {
+               ERR("%s: buffer NULL\n",__func__);
+               return -EINVAL;
+       }
+
+       if (!cam) {
+               ERR("%s: Internal error, camera_data NULL!\n",__func__);
+               return -EINVAL;
+       }
+
+       if (!cam->streaming) {
+               /* Start streaming */
+               cpia2_usb_stream_start(cam,
+                                      cam->params.camera_state.stream_mode);
+       }
+
+       /* Copy cam->curbuff in case it changes while we're processing */
+       frame = cam->curbuff;
+       if (noblock && frame->status != FRAME_READY) {
+               return -EAGAIN;
+       }
+
+       if (frame->status != FRAME_READY) {
+               mutex_unlock(&cam->v4l2_lock);
+               wait_event_interruptible(cam->wq_stream,
+                              !video_is_registered(&cam->vdev) ||
+                              (frame = cam->curbuff)->status == FRAME_READY);
+               mutex_lock(&cam->v4l2_lock);
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+               if (!video_is_registered(&cam->vdev))
+                       return 0;
+       }
+
+       /* copy data to user space */
+       if (frame->length > count)
+               return -EFAULT;
+       if (copy_to_user(buf, frame->data, frame->length))
+               return -EFAULT;
+
+       count = frame->length;
+
+       frame->status = FRAME_EMPTY;
+
+       return count;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_poll
+ *
+ *****************************************************************************/
+unsigned int cpia2_poll(struct camera_data *cam, struct file *filp,
+                       poll_table *wait)
+{
+       unsigned int status = v4l2_ctrl_poll(filp, wait);
+
+       if ((poll_requested_events(wait) & (POLLIN | POLLRDNORM)) &&
+                       !cam->streaming) {
+               /* Start streaming */
+               cpia2_usb_stream_start(cam,
+                                      cam->params.camera_state.stream_mode);
+       }
+
+       poll_wait(filp, &cam->wq_stream, wait);
+
+       if (cam->curbuff->status == FRAME_READY)
+               status |= POLLIN | POLLRDNORM;
+
+       return status;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_remap_buffer
+ *
+ *****************************************************************************/
+int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma)
+{
+       const char *adr = (const char *)vma->vm_start;
+       unsigned long size = vma->vm_end-vma->vm_start;
+       unsigned long start_offset = vma->vm_pgoff << PAGE_SHIFT;
+       unsigned long start = (unsigned long) adr;
+       unsigned long page, pos;
+
+       DBG("mmap offset:%ld size:%ld\n", start_offset, size);
+
+       if (!video_is_registered(&cam->vdev))
+               return -ENODEV;
+
+       if (size > cam->frame_size*cam->num_frames  ||
+           (start_offset % cam->frame_size) != 0 ||
+           (start_offset+size > cam->frame_size*cam->num_frames))
+               return -EINVAL;
+
+       pos = ((unsigned long) (cam->frame_buffer)) + start_offset;
+       while (size > 0) {
+               page = kvirt_to_pa(pos);
+               if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED))
+                       return -EAGAIN;
+               start += PAGE_SIZE;
+               pos += PAGE_SIZE;
+               if (size > PAGE_SIZE)
+                       size -= PAGE_SIZE;
+               else
+                       size = 0;
+       }
+
+       cam->mmapped = true;
+       return 0;
+}
diff --git a/drivers/media/usb/cpia2/cpia2_registers.h b/drivers/media/usb/cpia2/cpia2_registers.h
new file mode 100644 (file)
index 0000000..3bbec51
--- /dev/null
@@ -0,0 +1,476 @@
+/****************************************************************************
+ *
+ *  Filename: cpia2registers.h
+ *
+ *  Copyright 2001, STMicrolectronics, Inc.
+ *
+ *  Description:
+ *     Definitions for the CPia2 register set
+ *
+ *  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.
+ *
+ ****************************************************************************/
+
+#ifndef CPIA2_REGISTER_HEADER
+#define CPIA2_REGISTER_HEADER
+
+/***
+ * System register set (Bank 0)
+ ***/
+#define CPIA2_SYSTEM_DEVICE_HI                     0x00
+#define CPIA2_SYSTEM_DEVICE_LO                     0x01
+
+#define CPIA2_SYSTEM_SYSTEM_CONTROL                0x02
+#define CPIA2_SYSTEM_CONTROL_LOW_POWER       0x00
+#define CPIA2_SYSTEM_CONTROL_HIGH_POWER      0x01
+#define CPIA2_SYSTEM_CONTROL_SUSPEND         0x02
+#define CPIA2_SYSTEM_CONTROL_V2W_ERR         0x10
+#define CPIA2_SYSTEM_CONTROL_RB_ERR          0x10
+#define CPIA2_SYSTEM_CONTROL_CLEAR_ERR       0x80
+
+#define CPIA2_SYSTEM_INT_PACKET_CTRL                0x04
+#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_SW_XX 0x01
+#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_EOF   0x02
+#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_INT1  0x04
+
+#define CPIA2_SYSTEM_CACHE_CTRL                     0x05
+#define CPIA2_SYSTEM_CACHE_CTRL_CACHE_RESET      0x01
+#define CPIA2_SYSTEM_CACHE_CTRL_CACHE_FLUSH      0x02
+
+#define CPIA2_SYSTEM_SERIAL_CTRL                    0x06
+#define CPIA2_SYSTEM_SERIAL_CTRL_NULL_CMD        0x00
+#define CPIA2_SYSTEM_SERIAL_CTRL_START_CMD       0x01
+#define CPIA2_SYSTEM_SERIAL_CTRL_STOP_CMD        0x02
+#define CPIA2_SYSTEM_SERIAL_CTRL_WRITE_CMD       0x03
+#define CPIA2_SYSTEM_SERIAL_CTRL_READ_ACK_CMD    0x04
+#define CPIA2_SYSTEM_SERIAL_CTRL_READ_NACK_CMD   0x05
+
+#define CPIA2_SYSTEM_SERIAL_DATA                     0x07
+
+#define CPIA2_SYSTEM_VP_SERIAL_ADDR                  0x08
+
+/***
+ * I2C addresses for various devices in CPiA2
+ ***/
+#define CPIA2_SYSTEM_VP_SERIAL_ADDR_SENSOR           0x20
+#define CPIA2_SYSTEM_VP_SERIAL_ADDR_VP               0x88
+#define CPIA2_SYSTEM_VP_SERIAL_ADDR_676_VP           0x8A
+
+#define CPIA2_SYSTEM_SPARE_REG1                      0x09
+#define CPIA2_SYSTEM_SPARE_REG2                      0x0A
+#define CPIA2_SYSTEM_SPARE_REG3                      0x0B
+
+#define CPIA2_SYSTEM_MC_PORT_0                       0x0C
+#define CPIA2_SYSTEM_MC_PORT_1                       0x0D
+#define CPIA2_SYSTEM_MC_PORT_2                       0x0E
+#define CPIA2_SYSTEM_MC_PORT_3                       0x0F
+
+#define CPIA2_SYSTEM_STATUS_PKT                      0x20
+#define CPIA2_SYSTEM_STATUS_PKT_END                  0x27
+
+#define CPIA2_SYSTEM_DESCRIP_VID_HI                  0x30
+#define CPIA2_SYSTEM_DESCRIP_VID_LO                  0x31
+#define CPIA2_SYSTEM_DESCRIP_PID_HI                  0x32
+#define CPIA2_SYSTEM_DESCRIP_PID_LO                  0x33
+
+#define CPIA2_SYSTEM_FW_VERSION_HI                   0x34
+#define CPIA2_SYSTEM_FW_VERSION_LO                   0x35
+
+#define CPIA2_SYSTEM_CACHE_START_INDEX               0x80
+#define CPIA2_SYSTEM_CACHE_MAX_WRITES                0x10
+
+/***
+ * VC register set (Bank 1)
+ ***/
+#define CPIA2_VC_ASIC_ID                 0x80
+
+#define CPIA2_VC_ASIC_REV                0x81
+
+#define CPIA2_VC_PW_CTRL                 0x82
+#define CPIA2_VC_PW_CTRL_COLDSTART      0x01
+#define CPIA2_VC_PW_CTRL_CP_CLK_EN      0x02
+#define CPIA2_VC_PW_CTRL_VP_RESET_N     0x04
+#define CPIA2_VC_PW_CTRL_VC_CLK_EN      0x08
+#define CPIA2_VC_PW_CTRL_VC_RESET_N     0x10
+#define CPIA2_VC_PW_CTRL_GOTO_SUSPEND   0x20
+#define CPIA2_VC_PW_CTRL_UDC_SUSPEND    0x40
+#define CPIA2_VC_PW_CTRL_PWR_DOWN       0x80
+
+#define CPIA2_VC_WAKEUP                   0x83
+#define CPIA2_VC_WAKEUP_SW_ENABLE       0x01
+#define CPIA2_VC_WAKEUP_XX_ENABLE       0x02
+#define CPIA2_VC_WAKEUP_SW_ATWAKEUP     0x04
+#define CPIA2_VC_WAKEUP_XX_ATWAKEUP     0x08
+
+#define CPIA2_VC_CLOCK_CTRL               0x84
+#define CPIA2_VC_CLOCK_CTRL_TESTUP72    0x01
+
+#define CPIA2_VC_INT_ENABLE                0x88
+#define CPIA2_VC_INT_ENABLE_XX_IE       0x01
+#define CPIA2_VC_INT_ENABLE_SW_IE       0x02
+#define CPIA2_VC_INT_ENABLE_VC_IE       0x04
+#define CPIA2_VC_INT_ENABLE_USBDATA_IE  0x08
+#define CPIA2_VC_INT_ENABLE_USBSETUP_IE 0x10
+#define CPIA2_VC_INT_ENABLE_USBCFG_IE   0x20
+
+#define CPIA2_VC_INT_FLAG                  0x89
+#define CPIA2_VC_INT_ENABLE_XX_FLAG       0x01
+#define CPIA2_VC_INT_ENABLE_SW_FLAG       0x02
+#define CPIA2_VC_INT_ENABLE_VC_FLAG       0x04
+#define CPIA2_VC_INT_ENABLE_USBDATA_FLAG  0x08
+#define CPIA2_VC_INT_ENABLE_USBSETUP_FLAG 0x10
+#define CPIA2_VC_INT_ENABLE_USBCFG_FLAG   0x20
+#define CPIA2_VC_INT_ENABLE_SET_RESET_BIT 0x80
+
+#define CPIA2_VC_INT_STATE                 0x8A
+#define CPIA2_VC_INT_STATE_XX_STATE     0x01
+#define CPIA2_VC_INT_STATE_SW_STATE     0x02
+
+#define CPIA2_VC_MP_DIR                    0x90
+#define CPIA2_VC_MP_DIR_INPUT           0x00
+#define CPIA2_VC_MP_DIR_OUTPUT          0x01
+
+#define CPIA2_VC_MP_DATA                   0x91
+
+#define CPIA2_VC_DP_CTRL                   0x98
+#define CPIA2_VC_DP_CTRL_MODE_0         0x00
+#define CPIA2_VC_DP_CTRL_MODE_A         0x01
+#define CPIA2_VC_DP_CTRL_MODE_B         0x02
+#define CPIA2_VC_DP_CTRL_MODE_C         0x03
+#define CPIA2_VC_DP_CTRL_FAKE_FST       0x04
+
+#define CPIA2_VC_AD_CTRL                   0x99
+#define CPIA2_VC_AD_CTRL_SRC_0          0x00
+#define CPIA2_VC_AD_CTRL_SRC_DIGI_A     0x01
+#define CPIA2_VC_AD_CTRL_SRC_REG        0x02
+#define CPIA2_VC_AD_CTRL_DST_USB        0x00
+#define CPIA2_VC_AD_CTRL_DST_REG        0x04
+
+#define CPIA2_VC_AD_TEST_IN                0x9B
+
+#define CPIA2_VC_AD_TEST_OUT               0x9C
+
+#define CPIA2_VC_AD_STATUS                 0x9D
+#define CPIA2_VC_AD_STATUS_EMPTY        0x01
+#define CPIA2_VC_AD_STATUS_FULL         0x02
+
+#define CPIA2_VC_DP_DATA                   0x9E
+
+#define CPIA2_VC_ST_CTRL                   0xA0
+#define CPIA2_VC_ST_CTRL_SRC_VC         0x00
+#define CPIA2_VC_ST_CTRL_SRC_DP         0x01
+#define CPIA2_VC_ST_CTRL_SRC_REG        0x02
+
+#define CPIA2_VC_ST_CTRL_RAW_SELECT     0x04
+
+#define CPIA2_VC_ST_CTRL_DST_USB        0x00
+#define CPIA2_VC_ST_CTRL_DST_DP         0x08
+#define CPIA2_VC_ST_CTRL_DST_REG        0x10
+
+#define CPIA2_VC_ST_CTRL_FIFO_ENABLE    0x20
+#define CPIA2_VC_ST_CTRL_EOF_DETECT     0x40
+
+#define CPIA2_VC_ST_TEST                   0xA1
+#define CPIA2_VC_ST_TEST_MODE_MANUAL    0x00
+#define CPIA2_VC_ST_TEST_MODE_INCREMENT 0x02
+
+#define CPIA2_VC_ST_TEST_AUTO_FILL      0x08
+
+#define CPIA2_VC_ST_TEST_REPEAT_FIFO    0x10
+
+#define CPIA2_VC_ST_TEST_IN                0xA2
+
+#define CPIA2_VC_ST_TEST_OUT               0xA3
+
+#define CPIA2_VC_ST_STATUS                 0xA4
+#define CPIA2_VC_ST_STATUS_EMPTY        0x01
+#define CPIA2_VC_ST_STATUS_FULL         0x02
+
+#define CPIA2_VC_ST_FRAME_DETECT_1         0xA5
+
+#define CPIA2_VC_ST_FRAME_DETECT_2         0xA6
+
+#define CPIA2_VC_USB_CTRL                    0xA8
+#define CPIA2_VC_USB_CTRL_CMD_STALLED      0x01
+#define CPIA2_VC_USB_CTRL_CMD_READY        0x02
+#define CPIA2_VC_USB_CTRL_CMD_STATUS       0x04
+#define CPIA2_VC_USB_CTRL_CMD_STATUS_DIR   0x08
+#define CPIA2_VC_USB_CTRL_CMD_NO_CLASH     0x10
+#define CPIA2_VC_USB_CTRL_CMD_MICRO_ACCESS 0x80
+
+#define CPIA2_VC_USB_STRM                  0xA9
+#define CPIA2_VC_USB_STRM_ISO_ENABLE    0x01
+#define CPIA2_VC_USB_STRM_BLK_ENABLE    0x02
+#define CPIA2_VC_USB_STRM_INT_ENABLE    0x04
+#define CPIA2_VC_USB_STRM_AUD_ENABLE    0x08
+
+#define CPIA2_VC_USB_STATUS                   0xAA
+#define CPIA2_VC_USB_STATUS_CMD_IN_PROGRESS  0x01
+#define CPIA2_VC_USB_STATUS_CMD_STATUS_STALL 0x02
+#define CPIA2_VC_USB_STATUS_CMD_HANDSHAKE    0x04
+#define CPIA2_VC_USB_STATUS_CMD_OVERRIDE     0x08
+#define CPIA2_VC_USB_STATUS_CMD_FIFO_BUSY    0x10
+#define CPIA2_VC_USB_STATUS_BULK_REPEAT_TXN  0x20
+#define CPIA2_VC_USB_STATUS_CONFIG_DONE      0x40
+#define CPIA2_VC_USB_STATUS_USB_SUSPEND      0x80
+
+#define CPIA2_VC_USB_CMDW                   0xAB
+
+#define CPIA2_VC_USB_DATARW                 0xAC
+
+#define CPIA2_VC_USB_INFO                   0xAD
+
+#define CPIA2_VC_USB_CONFIG                 0xAE
+
+#define CPIA2_VC_USB_SETTINGS                  0xAF
+#define CPIA2_VC_USB_SETTINGS_CONFIG_MASK    0x03
+#define CPIA2_VC_USB_SETTINGS_INTERFACE_MASK 0x0C
+#define CPIA2_VC_USB_SETTINGS_ALTERNATE_MASK 0x70
+
+#define CPIA2_VC_USB_ISOLIM                  0xB0
+
+#define CPIA2_VC_USB_ISOFAILS                0xB1
+
+#define CPIA2_VC_USB_ISOMAXPKTHI             0xB2
+
+#define CPIA2_VC_USB_ISOMAXPKTLO             0xB3
+
+#define CPIA2_VC_V2W_CTRL                    0xB8
+#define CPIA2_VC_V2W_SELECT               0x01
+
+#define CPIA2_VC_V2W_SCL                     0xB9
+
+#define CPIA2_VC_V2W_SDA                     0xBA
+
+#define CPIA2_VC_VC_CTRL                     0xC0
+#define CPIA2_VC_VC_CTRL_RUN              0x01
+#define CPIA2_VC_VC_CTRL_SINGLESHOT       0x02
+#define CPIA2_VC_VC_CTRL_IDLING           0x04
+#define CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES 0x10
+#define CPIA2_VC_VC_CTRL_INHIBIT_Q_TABLES 0x20
+#define CPIA2_VC_VC_CTRL_INHIBIT_PRIVATE  0x40
+
+#define CPIA2_VC_VC_RESTART_IVAL_HI          0xC1
+
+#define CPIA2_VC_VC_RESTART_IVAL_LO          0xC2
+
+#define CPIA2_VC_VC_FORMAT                   0xC3
+#define CPIA2_VC_VC_FORMAT_UFIRST         0x01
+#define CPIA2_VC_VC_FORMAT_MONO           0x02
+#define CPIA2_VC_VC_FORMAT_DECIMATING     0x04
+#define CPIA2_VC_VC_FORMAT_SHORTLINE      0x08
+#define CPIA2_VC_VC_FORMAT_SELFTEST       0x10
+
+#define CPIA2_VC_VC_CLOCKS                         0xC4
+#define CPIA2_VC_VC_CLOCKS_CLKDIV_MASK        0x03
+#define CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3   0x04
+#define CPIA2_VC_VC_672_CLOCKS_SCALING        0x08
+#define CPIA2_VC_VC_CLOCKS_LOGDIV0        0x00
+#define CPIA2_VC_VC_CLOCKS_LOGDIV1        0x01
+#define CPIA2_VC_VC_CLOCKS_LOGDIV2        0x02
+#define CPIA2_VC_VC_CLOCKS_LOGDIV3        0x03
+#define CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3   0x08
+#define CPIA2_VC_VC_676_CLOCKS_SCALING       0x10
+
+#define CPIA2_VC_VC_IHSIZE_LO                0xC5
+
+#define CPIA2_VC_VC_XLIM_HI                  0xC6
+
+#define CPIA2_VC_VC_XLIM_LO                  0xC7
+
+#define CPIA2_VC_VC_YLIM_HI                  0xC8
+
+#define CPIA2_VC_VC_YLIM_LO                  0xC9
+
+#define CPIA2_VC_VC_OHSIZE                   0xCA
+
+#define CPIA2_VC_VC_OVSIZE                   0xCB
+
+#define CPIA2_VC_VC_HCROP                    0xCC
+
+#define CPIA2_VC_VC_VCROP                    0xCD
+
+#define CPIA2_VC_VC_HPHASE                   0xCE
+
+#define CPIA2_VC_VC_VPHASE                   0xCF
+
+#define CPIA2_VC_VC_HISPAN                   0xD0
+
+#define CPIA2_VC_VC_VISPAN                   0xD1
+
+#define CPIA2_VC_VC_HICROP                   0xD2
+
+#define CPIA2_VC_VC_VICROP                   0xD3
+
+#define CPIA2_VC_VC_HFRACT                   0xD4
+#define CPIA2_VC_VC_HFRACT_DEN_MASK       0x0F
+#define CPIA2_VC_VC_HFRACT_NUM_MASK       0xF0
+
+#define CPIA2_VC_VC_VFRACT                   0xD5
+#define CPIA2_VC_VC_VFRACT_DEN_MASK       0x0F
+#define CPIA2_VC_VC_VFRACT_NUM_MASK       0xF0
+
+#define CPIA2_VC_VC_JPEG_OPT                      0xD6
+#define CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE     0x01
+#define CPIA2_VC_VC_JPEG_OPT_NO_DC_AUTO_SQUEEZE 0x02
+#define CPIA2_VC_VC_JPEG_OPT_AUTO_SQUEEZE       0x04
+#define CPIA2_VC_VC_JPEG_OPT_DEFAULT      (CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE|\
+                                          CPIA2_VC_VC_JPEG_OPT_AUTO_SQUEEZE)
+
+
+#define CPIA2_VC_VC_CREEP_PERIOD             0xD7
+#define CPIA2_VC_VC_USER_SQUEEZE             0xD8
+#define CPIA2_VC_VC_TARGET_KB                0xD9
+
+#define CPIA2_VC_VC_AUTO_SQUEEZE             0xE6
+
+
+/***
+ * VP register set (Bank 2)
+ ***/
+#define CPIA2_VP_DEVICEH                             0
+#define CPIA2_VP_DEVICEL                             1
+
+#define CPIA2_VP_SYSTEMSTATE                         0x02
+#define CPIA2_VP_SYSTEMSTATE_HK_ALIVE             0x01
+
+#define CPIA2_VP_SYSTEMCTRL                          0x03
+#define CPIA2_VP_SYSTEMCTRL_REQ_CLEAR_ERROR       0x80
+#define CPIA2_VP_SYSTEMCTRL_POWER_DOWN_PLL        0x20
+#define CPIA2_VP_SYSTEMCTRL_REQ_SUSPEND_STATE     0x10
+#define CPIA2_VP_SYSTEMCTRL_REQ_SERIAL_WAKEUP     0x08
+#define CPIA2_VP_SYSTEMCTRL_REQ_AUTOLOAD          0x04
+#define CPIA2_VP_SYSTEMCTRL_HK_CONTROL            0x02
+#define CPIA2_VP_SYSTEMCTRL_POWER_CONTROL         0x01
+
+#define CPIA2_VP_SENSOR_FLAGS                        0x05
+#define CPIA2_VP_SENSOR_FLAGS_404                 0x01
+#define CPIA2_VP_SENSOR_FLAGS_407                 0x02
+#define CPIA2_VP_SENSOR_FLAGS_409                 0x04
+#define CPIA2_VP_SENSOR_FLAGS_410                 0x08
+#define CPIA2_VP_SENSOR_FLAGS_500                 0x10
+
+#define CPIA2_VP_SENSOR_REV                          0x06
+
+#define CPIA2_VP_DEVICE_CONFIG                       0x07
+#define CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE      0x01
+
+#define CPIA2_VP_GPIO_DIRECTION                      0x08
+#define CPIA2_VP_GPIO_READ                        0xFF
+#define CPIA2_VP_GPIO_WRITE                       0x00
+
+#define CPIA2_VP_GPIO_DATA                           0x09
+
+#define CPIA2_VP_RAM_ADDR_H                          0x0A
+#define CPIA2_VP_RAM_ADDR_L                          0x0B
+#define CPIA2_VP_RAM_DATA                            0x0C
+
+#define CPIA2_VP_PATCH_REV                           0x0F
+
+#define CPIA2_VP4_USER_MODE                           0x10
+#define CPIA2_VP5_USER_MODE                           0x13
+#define CPIA2_VP_USER_MODE_CIF                    0x01
+#define CPIA2_VP_USER_MODE_QCIFDS                 0x02
+#define CPIA2_VP_USER_MODE_QCIFPTC                0x04
+#define CPIA2_VP_USER_MODE_QVGADS                 0x08
+#define CPIA2_VP_USER_MODE_QVGAPTC                0x10
+#define CPIA2_VP_USER_MODE_VGA                    0x20
+
+#define CPIA2_VP4_FRAMERATE_REQUEST                    0x11
+#define CPIA2_VP5_FRAMERATE_REQUEST                    0x14
+#define CPIA2_VP_FRAMERATE_60                     0x80
+#define CPIA2_VP_FRAMERATE_50                     0x40
+#define CPIA2_VP_FRAMERATE_30                     0x20
+#define CPIA2_VP_FRAMERATE_25                     0x10
+#define CPIA2_VP_FRAMERATE_15                     0x08
+#define CPIA2_VP_FRAMERATE_12_5                   0x04
+#define CPIA2_VP_FRAMERATE_7_5                    0x02
+#define CPIA2_VP_FRAMERATE_6_25                   0x01
+
+#define CPIA2_VP4_USER_EFFECTS                         0x12
+#define CPIA2_VP5_USER_EFFECTS                         0x15
+#define CPIA2_VP_USER_EFFECTS_COLBARS             0x01
+#define CPIA2_VP_USER_EFFECTS_COLBARS_GRAD        0x02
+#define CPIA2_VP_USER_EFFECTS_MIRROR              0x04
+#define CPIA2_VP_USER_EFFECTS_FLIP                0x40  // VP5 only
+
+/* NOTE: CPIA2_VP_EXPOSURE_MODES shares the same register as VP5 User
+ * Effects */
+#define CPIA2_VP_EXPOSURE_MODES                       0x15
+#define CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER   0x20
+#define CPIA2_VP_EXPOSURE_MODES_COMPILE_EXP       0x10
+
+#define CPIA2_VP4_EXPOSURE_TARGET                     0x16    // VP4
+#define CPIA2_VP5_EXPOSURE_TARGET                    0x20    // VP5
+
+#define CPIA2_VP_FLICKER_MODES                        0x1B
+#define CPIA2_VP_FLICKER_MODES_50HZ               0x80
+#define CPIA2_VP_FLICKER_MODES_CUSTOM_FLT_FFREQ   0x40
+#define CPIA2_VP_FLICKER_MODES_NEVER_FLICKER      0x20
+#define CPIA2_VP_FLICKER_MODES_INHIBIT_RUB        0x10
+#define CPIA2_VP_FLICKER_MODES_ADJUST_LINE_FREQ   0x08
+#define CPIA2_VP_FLICKER_MODES_CUSTOM_INT_FFREQ   0x04
+
+#define CPIA2_VP_UMISC                                0x1D
+#define CPIA2_VP_UMISC_FORCE_MONO                 0x80
+#define CPIA2_VP_UMISC_FORCE_ID_MASK              0x40
+#define CPIA2_VP_UMISC_INHIBIT_AUTO_FGS           0x20
+#define CPIA2_VP_UMISC_INHIBIT_AUTO_DIMS          0x08
+#define CPIA2_VP_UMISC_OPT_FOR_SENSOR_DS          0x04
+#define CPIA2_VP_UMISC_INHIBIT_AUTO_MODE_INT      0x02
+
+#define CPIA2_VP5_ANTIFLKRSETUP                       0x22  //34
+
+#define CPIA2_VP_INTERPOLATION                        0x24
+#define CPIA2_VP_INTERPOLATION_EVEN_FIRST         0x40
+#define CPIA2_VP_INTERPOLATION_HJOG               0x20
+#define CPIA2_VP_INTERPOLATION_VJOG               0x10
+
+#define CPIA2_VP_GAMMA                                0x25
+#define CPIA2_VP_DEFAULT_GAMMA                    0x10
+
+#define CPIA2_VP_YRANGE                               0x26
+
+#define CPIA2_VP_SATURATION                           0x27
+
+#define CPIA2_VP5_MYBLACK_LEVEL                       0x3A   //58
+#define CPIA2_VP5_MCYRANGE                            0x3B   //59
+#define CPIA2_VP5_MYCEILING                           0x3C   //60
+#define CPIA2_VP5_MCUVSATURATION                      0x3D   //61
+
+
+#define CPIA2_VP_REHASH_VALUES                        0x60
+
+
+/***
+ * Common sensor registers
+ ***/
+#define CPIA2_SENSOR_DEVICE_H                         0x00
+#define CPIA2_SENSOR_DEVICE_L                         0x01
+
+#define CPIA2_SENSOR_DATA_FORMAT                      0x16
+#define CPIA2_SENSOR_DATA_FORMAT_HMIRROR      0x08
+#define CPIA2_SENSOR_DATA_FORMAT_VMIRROR      0x10
+
+#define CPIA2_SENSOR_CR1                              0x76
+#define CPIA2_SENSOR_CR1_STAND_BY             0x01
+#define CPIA2_SENSOR_CR1_DOWN_RAMP_GEN        0x02
+#define CPIA2_SENSOR_CR1_DOWN_COLUMN_ADC      0x04
+#define CPIA2_SENSOR_CR1_DOWN_CAB_REGULATOR   0x08
+#define CPIA2_SENSOR_CR1_DOWN_AUDIO_REGULATOR 0x10
+#define CPIA2_SENSOR_CR1_DOWN_VRT_AMP         0x20
+#define CPIA2_SENSOR_CR1_DOWN_BAND_GAP        0x40
+
+#endif
diff --git a/drivers/media/usb/cpia2/cpia2_usb.c b/drivers/media/usb/cpia2/cpia2_usb.c
new file mode 100644 (file)
index 0000000..95b5d6e
--- /dev/null
@@ -0,0 +1,955 @@
+/****************************************************************************
+ *
+ *  Filename: cpia2_usb.c
+ *
+ *  Copyright 2001, STMicrolectronics, Inc.
+ *      Contact:  steve.miller@st.com
+ *
+ *  Description:
+ *     This is a USB driver for CPia2 based video cameras.
+ *     The infrastructure of this driver is based on the cpia usb driver by
+ *     Jochen Scharrlach and Johannes Erdfeldt.
+ *
+ *  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.
+ *
+ *  Stripped of 2.4 stuff ready for main kernel submit by
+ *             Alan Cox <alan@lxorguk.ukuu.org.uk>
+ ****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/module.h>
+
+#include "cpia2.h"
+
+static int frame_sizes[] = {
+       0,      // USBIF_CMDONLY
+       0,      // USBIF_BULK
+       128,    // USBIF_ISO_1
+       384,    // USBIF_ISO_2
+       640,    // USBIF_ISO_3
+       768,    // USBIF_ISO_4
+       896,    // USBIF_ISO_5
+       1023,   // USBIF_ISO_6
+};
+
+#define FRAMES_PER_DESC    10
+#define FRAME_SIZE_PER_DESC   frame_sizes[cam->cur_alt]
+
+static void process_frame(struct camera_data *cam);
+static void cpia2_usb_complete(struct urb *urb);
+static int cpia2_usb_probe(struct usb_interface *intf,
+                          const struct usb_device_id *id);
+static void cpia2_usb_disconnect(struct usb_interface *intf);
+static int cpia2_usb_suspend(struct usb_interface *intf, pm_message_t message);
+static int cpia2_usb_resume(struct usb_interface *intf);
+
+static void free_sbufs(struct camera_data *cam);
+static void add_APPn(struct camera_data *cam);
+static void add_COM(struct camera_data *cam);
+static int submit_urbs(struct camera_data *cam);
+static int set_alternate(struct camera_data *cam, unsigned int alt);
+static int configure_transfer_mode(struct camera_data *cam, unsigned int alt);
+
+static struct usb_device_id cpia2_id_table[] = {
+       {USB_DEVICE(0x0553, 0x0100)},
+       {USB_DEVICE(0x0553, 0x0140)},
+       {USB_DEVICE(0x0553, 0x0151)},  /* STV0676 */
+       {}                      /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, cpia2_id_table);
+
+static struct usb_driver cpia2_driver = {
+       .name           = "cpia2",
+       .probe          = cpia2_usb_probe,
+       .disconnect     = cpia2_usb_disconnect,
+       .suspend        = cpia2_usb_suspend,
+       .resume         = cpia2_usb_resume,
+       .reset_resume   = cpia2_usb_resume,
+       .id_table       = cpia2_id_table
+};
+
+
+/******************************************************************************
+ *
+ *  process_frame
+ *
+ *****************************************************************************/
+static void process_frame(struct camera_data *cam)
+{
+       static int frame_count;
+
+       unsigned char *inbuff = cam->workbuff->data;
+
+       DBG("Processing frame #%d, current:%d\n",
+           cam->workbuff->num, cam->curbuff->num);
+
+       if(cam->workbuff->length > cam->workbuff->max_length)
+               cam->workbuff->max_length = cam->workbuff->length;
+
+       if ((inbuff[0] == 0xFF) && (inbuff[1] == 0xD8)) {
+               frame_count++;
+       } else {
+               cam->workbuff->status = FRAME_ERROR;
+               DBG("Start of frame not found\n");
+               return;
+       }
+
+       /***
+        * Now the output buffer should have a JPEG image in it.
+        ***/
+       if(!cam->first_image_seen) {
+               /* Always skip the first image after streaming
+                * starts. It is almost certainly corrupt. */
+               cam->first_image_seen = 1;
+               cam->workbuff->status = FRAME_EMPTY;
+               return;
+       }
+       if (cam->workbuff->length > 3) {
+               if(cam->mmapped &&
+                  cam->workbuff->length < cam->workbuff->max_length) {
+                       /* No junk in the buffers */
+                       memset(cam->workbuff->data+cam->workbuff->length,
+                              0, cam->workbuff->max_length-
+                                 cam->workbuff->length);
+               }
+               cam->workbuff->max_length = cam->workbuff->length;
+               cam->workbuff->status = FRAME_READY;
+
+               if(!cam->mmapped && cam->num_frames > 2) {
+                       /* During normal reading, the most recent
+                        * frame will be read.  If the current frame
+                        * hasn't started reading yet, it will never
+                        * be read, so mark it empty.  If the buffer is
+                        * mmapped, or we have few buffers, we need to
+                        * wait for the user to free the buffer.
+                        *
+                        * NOTE: This is not entirely foolproof with 3
+                        * buffers, but it would take an EXTREMELY
+                        * overloaded system to cause problems (possible
+                        * image data corruption).  Basically, it would
+                        * need to take more time to execute cpia2_read
+                        * than it would for the camera to send
+                        * cam->num_frames-2 frames before problems
+                        * could occur.
+                        */
+                       cam->curbuff->status = FRAME_EMPTY;
+               }
+               cam->curbuff = cam->workbuff;
+               cam->workbuff = cam->workbuff->next;
+               DBG("Changed buffers, work:%d, current:%d\n",
+                   cam->workbuff->num, cam->curbuff->num);
+               return;
+       } else {
+               DBG("Not enough data for an image.\n");
+       }
+
+       cam->workbuff->status = FRAME_ERROR;
+       return;
+}
+
+/******************************************************************************
+ *
+ *  add_APPn
+ *
+ *  Adds a user specified APPn record
+ *****************************************************************************/
+static void add_APPn(struct camera_data *cam)
+{
+       if(cam->APP_len > 0) {
+               cam->workbuff->data[cam->workbuff->length++] = 0xFF;
+               cam->workbuff->data[cam->workbuff->length++] = 0xE0+cam->APPn;
+               cam->workbuff->data[cam->workbuff->length++] = 0;
+               cam->workbuff->data[cam->workbuff->length++] = cam->APP_len+2;
+               memcpy(cam->workbuff->data+cam->workbuff->length,
+                      cam->APP_data, cam->APP_len);
+               cam->workbuff->length += cam->APP_len;
+       }
+}
+
+/******************************************************************************
+ *
+ *  add_COM
+ *
+ *  Adds a user specified COM record
+ *****************************************************************************/
+static void add_COM(struct camera_data *cam)
+{
+       if(cam->COM_len > 0) {
+               cam->workbuff->data[cam->workbuff->length++] = 0xFF;
+               cam->workbuff->data[cam->workbuff->length++] = 0xFE;
+               cam->workbuff->data[cam->workbuff->length++] = 0;
+               cam->workbuff->data[cam->workbuff->length++] = cam->COM_len+2;
+               memcpy(cam->workbuff->data+cam->workbuff->length,
+                      cam->COM_data, cam->COM_len);
+               cam->workbuff->length += cam->COM_len;
+       }
+}
+
+/******************************************************************************
+ *
+ *  cpia2_usb_complete
+ *
+ *  callback when incoming packet is received
+ *****************************************************************************/
+static void cpia2_usb_complete(struct urb *urb)
+{
+       int i;
+       unsigned char *cdata;
+       static int frame_ready = false;
+       struct camera_data *cam = (struct camera_data *) urb->context;
+
+       if (urb->status!=0) {
+               if (!(urb->status == -ENOENT ||
+                     urb->status == -ECONNRESET ||
+                     urb->status == -ESHUTDOWN))
+               {
+                       DBG("urb->status = %d!\n", urb->status);
+               }
+               DBG("Stopping streaming\n");
+               return;
+       }
+
+       if (!cam->streaming || !video_is_registered(&cam->vdev)) {
+               LOG("Will now stop the streaming: streaming = %d, present=%d\n",
+                   cam->streaming, video_is_registered(&cam->vdev));
+               return;
+       }
+
+       /***
+        * Packet collater
+        ***/
+       //DBG("Collating %d packets\n", urb->number_of_packets);
+       for (i = 0; i < urb->number_of_packets; i++) {
+               u16 checksum, iso_checksum;
+               int j;
+               int n = urb->iso_frame_desc[i].actual_length;
+               int st = urb->iso_frame_desc[i].status;
+
+               if(cam->workbuff->status == FRAME_READY) {
+                       struct framebuf *ptr;
+                       /* Try to find an available buffer */
+                       DBG("workbuff full, searching\n");
+                       for (ptr = cam->workbuff->next;
+                            ptr != cam->workbuff;
+                            ptr = ptr->next)
+                       {
+                               if (ptr->status == FRAME_EMPTY) {
+                                       ptr->status = FRAME_READING;
+                                       ptr->length = 0;
+                                       break;
+                               }
+                       }
+                       if (ptr == cam->workbuff)
+                               break; /* No READING or EMPTY buffers left */
+
+                       cam->workbuff = ptr;
+               }
+
+               if (cam->workbuff->status == FRAME_EMPTY ||
+                   cam->workbuff->status == FRAME_ERROR) {
+                       cam->workbuff->status = FRAME_READING;
+                       cam->workbuff->length = 0;
+               }
+
+               //DBG("   Packet %d length = %d, status = %d\n", i, n, st);
+               cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+
+               if (st) {
+                       LOG("cpia2 data error: [%d] len=%d, status = %d\n",
+                           i, n, st);
+                       if(!ALLOW_CORRUPT)
+                               cam->workbuff->status = FRAME_ERROR;
+                       continue;
+               }
+
+               if(n<=2)
+                       continue;
+
+               checksum = 0;
+               for(j=0; j<n-2; ++j)
+                       checksum += cdata[j];
+               iso_checksum = cdata[j] + cdata[j+1]*256;
+               if(checksum != iso_checksum) {
+                       LOG("checksum mismatch: [%d] len=%d, calculated = %x, checksum = %x\n",
+                           i, n, (int)checksum, (int)iso_checksum);
+                       if(!ALLOW_CORRUPT) {
+                               cam->workbuff->status = FRAME_ERROR;
+                               continue;
+                       }
+               }
+               n -= 2;
+
+               if(cam->workbuff->status != FRAME_READING) {
+                       if((0xFF == cdata[0] && 0xD8 == cdata[1]) ||
+                          (0xD8 == cdata[0] && 0xFF == cdata[1] &&
+                           0 != cdata[2])) {
+                               /* frame is skipped, but increment total
+                                * frame count anyway */
+                               cam->frame_count++;
+                       }
+                       DBG("workbuff not reading, status=%d\n",
+                           cam->workbuff->status);
+                       continue;
+               }
+
+               if (cam->frame_size < cam->workbuff->length + n) {
+                       ERR("buffer overflow! length: %d, n: %d\n",
+                           cam->workbuff->length, n);
+                       cam->workbuff->status = FRAME_ERROR;
+                       if(cam->workbuff->length > cam->workbuff->max_length)
+                               cam->workbuff->max_length =
+                                       cam->workbuff->length;
+                       continue;
+               }
+
+               if (cam->workbuff->length == 0) {
+                       int data_offset;
+                       if ((0xD8 == cdata[0]) && (0xFF == cdata[1])) {
+                               data_offset = 1;
+                       } else if((0xFF == cdata[0]) && (0xD8 == cdata[1])
+                                 && (0xFF == cdata[2])) {
+                               data_offset = 2;
+                       } else {
+                               DBG("Ignoring packet, not beginning!\n");
+                               continue;
+                       }
+                       DBG("Start of frame pattern found\n");
+                       do_gettimeofday(&cam->workbuff->timestamp);
+                       cam->workbuff->seq = cam->frame_count++;
+                       cam->workbuff->data[0] = 0xFF;
+                       cam->workbuff->data[1] = 0xD8;
+                       cam->workbuff->length = 2;
+                       add_APPn(cam);
+                       add_COM(cam);
+                       memcpy(cam->workbuff->data+cam->workbuff->length,
+                              cdata+data_offset, n-data_offset);
+                       cam->workbuff->length += n-data_offset;
+               } else if (cam->workbuff->length > 0) {
+                       memcpy(cam->workbuff->data + cam->workbuff->length,
+                              cdata, n);
+                       cam->workbuff->length += n;
+               }
+
+               if ((cam->workbuff->length >= 3) &&
+                   (cam->workbuff->data[cam->workbuff->length - 3] == 0xFF) &&
+                   (cam->workbuff->data[cam->workbuff->length - 2] == 0xD9) &&
+                   (cam->workbuff->data[cam->workbuff->length - 1] == 0xFF)) {
+                       frame_ready = true;
+                       cam->workbuff->data[cam->workbuff->length - 1] = 0;
+                       cam->workbuff->length -= 1;
+               } else if ((cam->workbuff->length >= 2) &&
+                  (cam->workbuff->data[cam->workbuff->length - 2] == 0xFF) &&
+                  (cam->workbuff->data[cam->workbuff->length - 1] == 0xD9)) {
+                       frame_ready = true;
+               }
+
+               if (frame_ready) {
+                       DBG("Workbuff image size = %d\n",cam->workbuff->length);
+                       process_frame(cam);
+
+                       frame_ready = false;
+
+                       if (waitqueue_active(&cam->wq_stream))
+                               wake_up_interruptible(&cam->wq_stream);
+               }
+       }
+
+       if(cam->streaming) {
+               /* resubmit */
+               urb->dev = cam->dev;
+               if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)
+                       ERR("%s: usb_submit_urb ret %d!\n", __func__, i);
+       }
+}
+
+/******************************************************************************
+ *
+ * configure_transfer_mode
+ *
+ *****************************************************************************/
+static int configure_transfer_mode(struct camera_data *cam, unsigned int alt)
+{
+       static unsigned char iso_regs[8][4] = {
+               {0x00, 0x00, 0x00, 0x00},
+               {0x00, 0x00, 0x00, 0x00},
+               {0xB9, 0x00, 0x00, 0x7E},
+               {0xB9, 0x00, 0x01, 0x7E},
+               {0xB9, 0x00, 0x02, 0x7E},
+               {0xB9, 0x00, 0x02, 0xFE},
+               {0xB9, 0x00, 0x03, 0x7E},
+               {0xB9, 0x00, 0x03, 0xFD}
+       };
+       struct cpia2_command cmd;
+       unsigned char reg;
+
+       if (!video_is_registered(&cam->vdev))
+               return -ENODEV;
+
+       /***
+        * Write the isoc registers according to the alternate selected
+        ***/
+       cmd.direction = TRANSFER_WRITE;
+       cmd.buffer.block_data[0] = iso_regs[alt][0];
+       cmd.buffer.block_data[1] = iso_regs[alt][1];
+       cmd.buffer.block_data[2] = iso_regs[alt][2];
+       cmd.buffer.block_data[3] = iso_regs[alt][3];
+       cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
+       cmd.start = CPIA2_VC_USB_ISOLIM;
+       cmd.reg_count = 4;
+       cpia2_send_command(cam, &cmd);
+
+       /***
+        * Enable relevant streams before starting polling.
+        * First read USB Stream Config Register.
+        ***/
+       cmd.direction = TRANSFER_READ;
+       cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
+       cmd.start = CPIA2_VC_USB_STRM;
+       cmd.reg_count = 1;
+       cpia2_send_command(cam, &cmd);
+       reg = cmd.buffer.block_data[0];
+
+       /* Clear iso, bulk, and int */
+       reg &= ~(CPIA2_VC_USB_STRM_BLK_ENABLE |
+                CPIA2_VC_USB_STRM_ISO_ENABLE |
+                CPIA2_VC_USB_STRM_INT_ENABLE);
+
+       if (alt == USBIF_BULK) {
+               DBG("Enabling bulk xfer\n");
+               reg |= CPIA2_VC_USB_STRM_BLK_ENABLE;    /* Enable Bulk */
+               cam->xfer_mode = XFER_BULK;
+       } else if (alt >= USBIF_ISO_1) {
+               DBG("Enabling ISOC xfer\n");
+               reg |= CPIA2_VC_USB_STRM_ISO_ENABLE;
+               cam->xfer_mode = XFER_ISOC;
+       }
+
+       cmd.buffer.block_data[0] = reg;
+       cmd.direction = TRANSFER_WRITE;
+       cmd.start = CPIA2_VC_USB_STRM;
+       cmd.reg_count = 1;
+       cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
+       cpia2_send_command(cam, &cmd);
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ * cpia2_usb_change_streaming_alternate
+ *
+ *****************************************************************************/
+int cpia2_usb_change_streaming_alternate(struct camera_data *cam,
+                                        unsigned int alt)
+{
+       int ret = 0;
+
+       if(alt < USBIF_ISO_1 || alt > USBIF_ISO_6)
+               return -EINVAL;
+
+       if(alt == cam->params.camera_state.stream_mode)
+               return 0;
+
+       cpia2_usb_stream_pause(cam);
+
+       configure_transfer_mode(cam, alt);
+
+       cam->params.camera_state.stream_mode = alt;
+
+       /* Reset the camera to prevent image quality degradation */
+       cpia2_reset_camera(cam);
+
+       cpia2_usb_stream_resume(cam);
+
+       return ret;
+}
+
+/******************************************************************************
+ *
+ * set_alternate
+ *
+ *****************************************************************************/
+static int set_alternate(struct camera_data *cam, unsigned int alt)
+{
+       int ret = 0;
+
+       if(alt == cam->cur_alt)
+               return 0;
+
+       if (cam->cur_alt != USBIF_CMDONLY) {
+               DBG("Changing from alt %d to %d\n", cam->cur_alt, USBIF_CMDONLY);
+               ret = usb_set_interface(cam->dev, cam->iface, USBIF_CMDONLY);
+               if (ret != 0)
+                       return ret;
+       }
+       if (alt != USBIF_CMDONLY) {
+               DBG("Changing from alt %d to %d\n", USBIF_CMDONLY, alt);
+               ret = usb_set_interface(cam->dev, cam->iface, alt);
+               if (ret != 0)
+                       return ret;
+       }
+
+       cam->old_alt = cam->cur_alt;
+       cam->cur_alt = alt;
+
+       return ret;
+}
+
+/******************************************************************************
+ *
+ * free_sbufs
+ *
+ * Free all cam->sbuf[]. All non-NULL .data and .urb members that are non-NULL
+ * are assumed to be allocated. Non-NULL .urb members are also assumed to be
+ * submitted (and must therefore be killed before they are freed).
+ *****************************************************************************/
+static void free_sbufs(struct camera_data *cam)
+{
+       int i;
+
+       for (i = 0; i < NUM_SBUF; i++) {
+               if(cam->sbuf[i].urb) {
+                       usb_kill_urb(cam->sbuf[i].urb);
+                       usb_free_urb(cam->sbuf[i].urb);
+                       cam->sbuf[i].urb = NULL;
+               }
+               if(cam->sbuf[i].data) {
+                       kfree(cam->sbuf[i].data);
+                       cam->sbuf[i].data = NULL;
+               }
+       }
+}
+
+/*******
+* Convenience functions
+*******/
+/****************************************************************************
+ *
+ *  write_packet
+ *
+ ***************************************************************************/
+static int write_packet(struct usb_device *udev,
+                       u8 request, u8 * registers, u16 start, size_t size)
+{
+       if (!registers || size <= 0)
+               return -EINVAL;
+
+       return usb_control_msg(udev,
+                              usb_sndctrlpipe(udev, 0),
+                              request,
+                              USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                              start,   /* value */
+                              0,       /* index */
+                              registers,       /* buffer */
+                              size,
+                              HZ);
+}
+
+/****************************************************************************
+ *
+ *  read_packet
+ *
+ ***************************************************************************/
+static int read_packet(struct usb_device *udev,
+                      u8 request, u8 * registers, u16 start, size_t size)
+{
+       if (!registers || size <= 0)
+               return -EINVAL;
+
+       return usb_control_msg(udev,
+                              usb_rcvctrlpipe(udev, 0),
+                              request,
+                              USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE,
+                              start,   /* value */
+                              0,       /* index */
+                              registers,       /* buffer */
+                              size,
+                              HZ);
+}
+
+/******************************************************************************
+ *
+ *  cpia2_usb_transfer_cmd
+ *
+ *****************************************************************************/
+int cpia2_usb_transfer_cmd(struct camera_data *cam,
+                          void *registers,
+                          u8 request, u8 start, u8 count, u8 direction)
+{
+       int err = 0;
+       struct usb_device *udev = cam->dev;
+
+       if (!udev) {
+               ERR("%s: Internal driver error: udev is NULL\n", __func__);
+               return -EINVAL;
+       }
+
+       if (!registers) {
+               ERR("%s: Internal driver error: register array is NULL\n", __func__);
+               return -EINVAL;
+       }
+
+       if (direction == TRANSFER_READ) {
+               err = read_packet(udev, request, (u8 *)registers, start, count);
+               if (err > 0)
+                       err = 0;
+       } else if (direction == TRANSFER_WRITE) {
+               err =write_packet(udev, request, (u8 *)registers, start, count);
+               if (err < 0) {
+                       LOG("Control message failed, err val = %d\n", err);
+                       LOG("Message: request = 0x%0X, start = 0x%0X\n",
+                           request, start);
+                       LOG("Message: count = %d, register[0] = 0x%0X\n",
+                           count, ((unsigned char *) registers)[0]);
+               } else
+                       err=0;
+       } else {
+               LOG("Unexpected first byte of direction: %d\n",
+                      direction);
+               return -EINVAL;
+       }
+
+       if(err != 0)
+               LOG("Unexpected error: %d\n", err);
+       return err;
+}
+
+
+/******************************************************************************
+ *
+ *  submit_urbs
+ *
+ *****************************************************************************/
+static int submit_urbs(struct camera_data *cam)
+{
+       struct urb *urb;
+       int fx, err, i, j;
+
+       for(i=0; i<NUM_SBUF; ++i) {
+               if (cam->sbuf[i].data)
+                       continue;
+               cam->sbuf[i].data =
+                   kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
+               if (!cam->sbuf[i].data) {
+                       while (--i >= 0) {
+                               kfree(cam->sbuf[i].data);
+                               cam->sbuf[i].data = NULL;
+                       }
+                       return -ENOMEM;
+               }
+       }
+
+       /* We double buffer the Isoc lists, and also know the polling
+        * interval is every frame (1 == (1 << (bInterval -1))).
+        */
+       for(i=0; i<NUM_SBUF; ++i) {
+               if(cam->sbuf[i].urb) {
+                       continue;
+               }
+               urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
+               if (!urb) {
+                       ERR("%s: usb_alloc_urb error!\n", __func__);
+                       for (j = 0; j < i; j++)
+                               usb_free_urb(cam->sbuf[j].urb);
+                       return -ENOMEM;
+               }
+
+               cam->sbuf[i].urb = urb;
+               urb->dev = cam->dev;
+               urb->context = cam;
+               urb->pipe = usb_rcvisocpipe(cam->dev, 1 /*ISOC endpoint*/);
+               urb->transfer_flags = URB_ISO_ASAP;
+               urb->transfer_buffer = cam->sbuf[i].data;
+               urb->complete = cpia2_usb_complete;
+               urb->number_of_packets = FRAMES_PER_DESC;
+               urb->interval = 1;
+               urb->transfer_buffer_length =
+                       FRAME_SIZE_PER_DESC * FRAMES_PER_DESC;
+
+               for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
+                       urb->iso_frame_desc[fx].offset =
+                               FRAME_SIZE_PER_DESC * fx;
+                       urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC;
+               }
+       }
+
+
+       /* Queue the ISO urbs, and resubmit in the completion handler */
+       for(i=0; i<NUM_SBUF; ++i) {
+               err = usb_submit_urb(cam->sbuf[i].urb, GFP_KERNEL);
+               if (err) {
+                       ERR("usb_submit_urb[%d]() = %d\n", i, err);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_usb_stream_start
+ *
+ *****************************************************************************/
+int cpia2_usb_stream_start(struct camera_data *cam, unsigned int alternate)
+{
+       int ret;
+       int old_alt;
+
+       if(cam->streaming)
+               return 0;
+
+       if (cam->flush) {
+               int i;
+               DBG("Flushing buffers\n");
+               for(i=0; i<cam->num_frames; ++i) {
+                       cam->buffers[i].status = FRAME_EMPTY;
+                       cam->buffers[i].length = 0;
+               }
+               cam->curbuff = &cam->buffers[0];
+               cam->workbuff = cam->curbuff->next;
+               cam->flush = false;
+       }
+
+       old_alt = cam->params.camera_state.stream_mode;
+       cam->params.camera_state.stream_mode = 0;
+       ret = cpia2_usb_change_streaming_alternate(cam, alternate);
+       if (ret < 0) {
+               int ret2;
+               ERR("cpia2_usb_change_streaming_alternate() = %d!\n", ret);
+               cam->params.camera_state.stream_mode = old_alt;
+               ret2 = set_alternate(cam, USBIF_CMDONLY);
+               if (ret2 < 0) {
+                       ERR("cpia2_usb_change_streaming_alternate(%d) =%d has already "
+                           "failed. Then tried to call "
+                           "set_alternate(USBIF_CMDONLY) = %d.\n",
+                           alternate, ret, ret2);
+               }
+       } else {
+               cam->frame_count = 0;
+               cam->streaming = 1;
+               ret = cpia2_usb_stream_resume(cam);
+       }
+       return ret;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_usb_stream_pause
+ *
+ *****************************************************************************/
+int cpia2_usb_stream_pause(struct camera_data *cam)
+{
+       int ret = 0;
+       if(cam->streaming) {
+               free_sbufs(cam);
+               ret = set_alternate(cam, USBIF_CMDONLY);
+       }
+       return ret;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_usb_stream_resume
+ *
+ *****************************************************************************/
+int cpia2_usb_stream_resume(struct camera_data *cam)
+{
+       int ret = 0;
+       if(cam->streaming) {
+               cam->first_image_seen = 0;
+               ret = set_alternate(cam, cam->params.camera_state.stream_mode);
+               if(ret == 0) {
+                       /* for some reason the user effects need to be set
+                          again when starting streaming. */
+                       cpia2_do_command(cam, CPIA2_CMD_SET_USER_EFFECTS, TRANSFER_WRITE,
+                                       cam->params.vp_params.user_effects);
+                       ret = submit_urbs(cam);
+               }
+       }
+       return ret;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_usb_stream_stop
+ *
+ *****************************************************************************/
+int cpia2_usb_stream_stop(struct camera_data *cam)
+{
+       int ret;
+
+       ret = cpia2_usb_stream_pause(cam);
+       cam->streaming = 0;
+       configure_transfer_mode(cam, 0);
+       return ret;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_usb_probe
+ *
+ *  Probe and initialize.
+ *****************************************************************************/
+static int cpia2_usb_probe(struct usb_interface *intf,
+                          const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct usb_interface_descriptor *interface;
+       struct camera_data *cam;
+       int ret;
+
+       /* A multi-config CPiA2 camera? */
+       if (udev->descriptor.bNumConfigurations != 1)
+               return -ENODEV;
+       interface = &intf->cur_altsetting->desc;
+
+       /* If we get to this point, we found a CPiA2 camera */
+       LOG("CPiA2 USB camera found\n");
+
+       cam = cpia2_init_camera_struct(intf);
+       if (cam == NULL)
+               return -ENOMEM;
+
+       cam->dev = udev;
+       cam->iface = interface->bInterfaceNumber;
+
+       ret = set_alternate(cam, USBIF_CMDONLY);
+       if (ret < 0) {
+               ERR("%s: usb_set_interface error (ret = %d)\n", __func__, ret);
+               kfree(cam);
+               return ret;
+       }
+
+
+       if((ret = cpia2_init_camera(cam)) < 0) {
+               ERR("%s: failed to initialize cpia2 camera (ret = %d)\n", __func__, ret);
+               kfree(cam);
+               return ret;
+       }
+       LOG("  CPiA Version: %d.%02d (%d.%d)\n",
+              cam->params.version.firmware_revision_hi,
+              cam->params.version.firmware_revision_lo,
+              cam->params.version.asic_id,
+              cam->params.version.asic_rev);
+       LOG("  CPiA PnP-ID: %04x:%04x:%04x\n",
+              cam->params.pnp_id.vendor,
+              cam->params.pnp_id.product,
+              cam->params.pnp_id.device_revision);
+       LOG("  SensorID: %d.(version %d)\n",
+              cam->params.version.sensor_flags,
+              cam->params.version.sensor_rev);
+
+       usb_set_intfdata(intf, cam);
+
+       ret = cpia2_register_camera(cam);
+       if (ret < 0) {
+               ERR("%s: Failed to register cpia2 camera (ret = %d)\n", __func__, ret);
+               kfree(cam);
+               return ret;
+       }
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_disconnect
+ *
+ *****************************************************************************/
+static void cpia2_usb_disconnect(struct usb_interface *intf)
+{
+       struct camera_data *cam = usb_get_intfdata(intf);
+       usb_set_intfdata(intf, NULL);
+
+       DBG("Stopping stream\n");
+       cpia2_usb_stream_stop(cam);
+
+       mutex_lock(&cam->v4l2_lock);
+       DBG("Unregistering camera\n");
+       cpia2_unregister_camera(cam);
+       v4l2_device_disconnect(&cam->v4l2_dev);
+       mutex_unlock(&cam->v4l2_lock);
+       v4l2_device_put(&cam->v4l2_dev);
+
+       if(cam->buffers) {
+               DBG("Wakeup waiting processes\n");
+               cam->curbuff->status = FRAME_READY;
+               cam->curbuff->length = 0;
+               if (waitqueue_active(&cam->wq_stream))
+                       wake_up_interruptible(&cam->wq_stream);
+       }
+
+       DBG("Releasing interface\n");
+       usb_driver_release_interface(&cpia2_driver, intf);
+
+       LOG("CPiA2 camera disconnected.\n");
+}
+
+static int cpia2_usb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct camera_data *cam = usb_get_intfdata(intf);
+
+       mutex_lock(&cam->v4l2_lock);
+       if (cam->streaming) {
+               cpia2_usb_stream_stop(cam);
+               cam->streaming = 1;
+       }
+       mutex_unlock(&cam->v4l2_lock);
+
+       dev_info(&intf->dev, "going into suspend..\n");
+       return 0;
+}
+
+/* Resume device - start device. */
+static int cpia2_usb_resume(struct usb_interface *intf)
+{
+       struct camera_data *cam = usb_get_intfdata(intf);
+
+       mutex_lock(&cam->v4l2_lock);
+       v4l2_ctrl_handler_setup(&cam->hdl);
+       if (cam->streaming) {
+               cam->streaming = 0;
+               cpia2_usb_stream_start(cam,
+                               cam->params.camera_state.stream_mode);
+       }
+       mutex_unlock(&cam->v4l2_lock);
+
+       dev_info(&intf->dev, "coming out of suspend..\n");
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  usb_cpia2_init
+ *
+ *****************************************************************************/
+int cpia2_usb_init(void)
+{
+       return usb_register(&cpia2_driver);
+}
+
+/******************************************************************************
+ *
+ *  usb_cpia_cleanup
+ *
+ *****************************************************************************/
+void cpia2_usb_cleanup(void)
+{
+       schedule_timeout(2 * HZ);
+       usb_deregister(&cpia2_driver);
+}
diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c
new file mode 100644 (file)
index 0000000..5ca6f44
--- /dev/null
@@ -0,0 +1,1267 @@
+/****************************************************************************
+ *
+ *  Filename: cpia2_v4l.c
+ *
+ *  Copyright 2001, STMicrolectronics, Inc.
+ *      Contact:  steve.miller@st.com
+ *  Copyright 2001,2005, Scott J. Bertin <scottbertin@yahoo.com>
+ *
+ *  Description:
+ *     This is a USB driver for CPia2 based video cameras.
+ *     The infrastructure of this driver is based on the cpia usb driver by
+ *     Jochen Scharrlach and Johannes Erdfeldt.
+ *
+ *  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.
+ *
+ *  Stripped of 2.4 stuff ready for main kernel submit by
+ *             Alan Cox <alan@lxorguk.ukuu.org.uk>
+ ****************************************************************************/
+
+#define CPIA_VERSION "3.0.1"
+
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/videodev2.h>
+#include <linux/stringify.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+
+#include "cpia2.h"
+
+static int video_nr = -1;
+module_param(video_nr, int, 0);
+MODULE_PARM_DESC(video_nr, "video device to register (0=/dev/video0, etc)");
+
+static int buffer_size = 68 * 1024;
+module_param(buffer_size, int, 0);
+MODULE_PARM_DESC(buffer_size, "Size for each frame buffer in bytes (default 68k)");
+
+static int num_buffers = 3;
+module_param(num_buffers, int, 0);
+MODULE_PARM_DESC(num_buffers, "Number of frame buffers (1-"
+                __stringify(VIDEO_MAX_FRAME) ", default 3)");
+
+static int alternate = DEFAULT_ALT;
+module_param(alternate, int, 0);
+MODULE_PARM_DESC(alternate, "USB Alternate (" __stringify(USBIF_ISO_1) "-"
+                __stringify(USBIF_ISO_6) ", default "
+                __stringify(DEFAULT_ALT) ")");
+
+static int flicker_mode;
+module_param(flicker_mode, int, 0);
+MODULE_PARM_DESC(flicker_mode, "Flicker frequency (0 (disabled), " __stringify(50) " or "
+                __stringify(60) ", default 0)");
+
+MODULE_AUTHOR("Steve Miller (STMicroelectronics) <steve.miller@st.com>");
+MODULE_DESCRIPTION("V4L-driver for STMicroelectronics CPiA2 based cameras");
+MODULE_SUPPORTED_DEVICE("video");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CPIA_VERSION);
+
+#define ABOUT "V4L-Driver for Vision CPiA2 based cameras"
+#define CPIA2_CID_USB_ALT (V4L2_CID_USER_BASE | 0xf000)
+
+/******************************************************************************
+ *
+ *  cpia2_open
+ *
+ *****************************************************************************/
+static int cpia2_open(struct file *file)
+{
+       struct camera_data *cam = video_drvdata(file);
+       int retval;
+
+       if (mutex_lock_interruptible(&cam->v4l2_lock))
+               return -ERESTARTSYS;
+       retval = v4l2_fh_open(file);
+       if (retval)
+               goto open_unlock;
+
+       if (v4l2_fh_is_singular_file(file)) {
+               if (cpia2_allocate_buffers(cam)) {
+                       v4l2_fh_release(file);
+                       retval = -ENOMEM;
+                       goto open_unlock;
+               }
+
+               /* reset the camera */
+               if (cpia2_reset_camera(cam) < 0) {
+                       v4l2_fh_release(file);
+                       retval = -EIO;
+                       goto open_unlock;
+               }
+
+               cam->APP_len = 0;
+               cam->COM_len = 0;
+       }
+
+       cpia2_dbg_dump_registers(cam);
+open_unlock:
+       mutex_unlock(&cam->v4l2_lock);
+       return retval;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_close
+ *
+ *****************************************************************************/
+static int cpia2_close(struct file *file)
+{
+       struct video_device *dev = video_devdata(file);
+       struct camera_data *cam = video_get_drvdata(dev);
+
+       mutex_lock(&cam->v4l2_lock);
+       if (video_is_registered(&cam->vdev) && v4l2_fh_is_singular_file(file)) {
+               cpia2_usb_stream_stop(cam);
+
+               /* save camera state for later open */
+               cpia2_save_camera_state(cam);
+
+               cpia2_set_low_power(cam);
+               cpia2_free_buffers(cam);
+       }
+
+       if (cam->stream_fh == file->private_data) {
+               cam->stream_fh = NULL;
+               cam->mmapped = 0;
+       }
+       mutex_unlock(&cam->v4l2_lock);
+       return v4l2_fh_release(file);
+}
+
+/******************************************************************************
+ *
+ *  cpia2_v4l_read
+ *
+ *****************************************************************************/
+static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count,
+                             loff_t *off)
+{
+       struct camera_data *cam = video_drvdata(file);
+       int noblock = file->f_flags&O_NONBLOCK;
+       ssize_t ret;
+
+       if(!cam)
+               return -EINVAL;
+
+       if (mutex_lock_interruptible(&cam->v4l2_lock))
+               return -ERESTARTSYS;
+       ret = cpia2_read(cam, buf, count, noblock);
+       mutex_unlock(&cam->v4l2_lock);
+       return ret;
+}
+
+
+/******************************************************************************
+ *
+ *  cpia2_v4l_poll
+ *
+ *****************************************************************************/
+static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait)
+{
+       struct camera_data *cam = video_drvdata(filp);
+       unsigned int res;
+
+       mutex_lock(&cam->v4l2_lock);
+       res = cpia2_poll(cam, filp, wait);
+       mutex_unlock(&cam->v4l2_lock);
+       return res;
+}
+
+
+static int sync(struct camera_data *cam, int frame_nr)
+{
+       struct framebuf *frame = &cam->buffers[frame_nr];
+
+       while (1) {
+               if (frame->status == FRAME_READY)
+                       return 0;
+
+               if (!cam->streaming) {
+                       frame->status = FRAME_READY;
+                       frame->length = 0;
+                       return 0;
+               }
+
+               mutex_unlock(&cam->v4l2_lock);
+               wait_event_interruptible(cam->wq_stream,
+                                        !cam->streaming ||
+                                        frame->status == FRAME_READY);
+               mutex_lock(&cam->v4l2_lock);
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+               if (!video_is_registered(&cam->vdev))
+                       return -ENOTTY;
+       }
+}
+
+/******************************************************************************
+ *
+ *  ioctl_querycap
+ *
+ *  V4L2 device capabilities
+ *
+ *****************************************************************************/
+
+static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *vc)
+{
+       struct camera_data *cam = video_drvdata(file);
+
+       strcpy(vc->driver, "cpia2");
+
+       if (cam->params.pnp_id.product == 0x151)
+               strcpy(vc->card, "QX5 Microscope");
+       else
+               strcpy(vc->card, "CPiA2 Camera");
+       switch (cam->params.pnp_id.device_type) {
+       case DEVICE_STV_672:
+               strcat(vc->card, " (672/");
+               break;
+       case DEVICE_STV_676:
+               strcat(vc->card, " (676/");
+               break;
+       default:
+               strcat(vc->card, " (XXX/");
+               break;
+       }
+       switch (cam->params.version.sensor_flags) {
+       case CPIA2_VP_SENSOR_FLAGS_404:
+               strcat(vc->card, "404)");
+               break;
+       case CPIA2_VP_SENSOR_FLAGS_407:
+               strcat(vc->card, "407)");
+               break;
+       case CPIA2_VP_SENSOR_FLAGS_409:
+               strcat(vc->card, "409)");
+               break;
+       case CPIA2_VP_SENSOR_FLAGS_410:
+               strcat(vc->card, "410)");
+               break;
+       case CPIA2_VP_SENSOR_FLAGS_500:
+               strcat(vc->card, "500)");
+               break;
+       default:
+               strcat(vc->card, "XXX)");
+               break;
+       }
+
+       if (usb_make_path(cam->dev, vc->bus_info, sizeof(vc->bus_info)) <0)
+               memset(vc->bus_info,0, sizeof(vc->bus_info));
+
+       vc->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+                          V4L2_CAP_READWRITE |
+                          V4L2_CAP_STREAMING;
+       vc->capabilities = vc->device_caps |
+                          V4L2_CAP_DEVICE_CAPS;
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  ioctl_input
+ *
+ *  V4L2 input get/set/enumerate
+ *
+ *****************************************************************************/
+
+static int cpia2_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+       if (i->index)
+               return -EINVAL;
+       strcpy(i->name, "Camera");
+       i->type = V4L2_INPUT_TYPE_CAMERA;
+       return 0;
+}
+
+static int cpia2_g_input(struct file *file, void *fh, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int cpia2_s_input(struct file *file, void *fh, unsigned int i)
+{
+       return i ? -EINVAL : 0;
+}
+
+/******************************************************************************
+ *
+ *  ioctl_enum_fmt
+ *
+ *  V4L2 format enumerate
+ *
+ *****************************************************************************/
+
+static int cpia2_enum_fmt_vid_cap(struct file *file, void *fh,
+                                           struct v4l2_fmtdesc *f)
+{
+       int index = f->index;
+
+       if (index < 0 || index > 1)
+              return -EINVAL;
+
+       memset(f, 0, sizeof(*f));
+       f->index = index;
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       f->flags = V4L2_FMT_FLAG_COMPRESSED;
+       switch(index) {
+       case 0:
+               strcpy(f->description, "MJPEG");
+               f->pixelformat = V4L2_PIX_FMT_MJPEG;
+               break;
+       case 1:
+               strcpy(f->description, "JPEG");
+               f->pixelformat = V4L2_PIX_FMT_JPEG;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  ioctl_try_fmt
+ *
+ *  V4L2 format try
+ *
+ *****************************************************************************/
+
+static int cpia2_try_fmt_vid_cap(struct file *file, void *fh,
+                                         struct v4l2_format *f)
+{
+       struct camera_data *cam = video_drvdata(file);
+
+       if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG &&
+           f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG)
+              return -EINVAL;
+
+       f->fmt.pix.field = V4L2_FIELD_NONE;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage = cam->frame_size;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
+       f->fmt.pix.priv = 0;
+
+       switch (cpia2_match_video_size(f->fmt.pix.width, f->fmt.pix.height)) {
+       case VIDEOSIZE_VGA:
+               f->fmt.pix.width = 640;
+               f->fmt.pix.height = 480;
+               break;
+       case VIDEOSIZE_CIF:
+               f->fmt.pix.width = 352;
+               f->fmt.pix.height = 288;
+               break;
+       case VIDEOSIZE_QVGA:
+               f->fmt.pix.width = 320;
+               f->fmt.pix.height = 240;
+               break;
+       case VIDEOSIZE_288_216:
+               f->fmt.pix.width = 288;
+               f->fmt.pix.height = 216;
+               break;
+       case VIDEOSIZE_256_192:
+               f->fmt.pix.width = 256;
+               f->fmt.pix.height = 192;
+               break;
+       case VIDEOSIZE_224_168:
+               f->fmt.pix.width = 224;
+               f->fmt.pix.height = 168;
+               break;
+       case VIDEOSIZE_192_144:
+               f->fmt.pix.width = 192;
+               f->fmt.pix.height = 144;
+               break;
+       case VIDEOSIZE_QCIF:
+       default:
+               f->fmt.pix.width = 176;
+               f->fmt.pix.height = 144;
+               break;
+       }
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  ioctl_set_fmt
+ *
+ *  V4L2 format set
+ *
+ *****************************************************************************/
+
+static int cpia2_s_fmt_vid_cap(struct file *file, void *_fh,
+                                       struct v4l2_format *f)
+{
+       struct camera_data *cam = video_drvdata(file);
+       int err, frame;
+
+       err = cpia2_try_fmt_vid_cap(file, _fh, f);
+       if(err != 0)
+               return err;
+
+       cam->pixelformat = f->fmt.pix.pixelformat;
+
+       /* NOTE: This should be set to 1 for MJPEG, but some apps don't handle
+        * the missing Huffman table properly. */
+       cam->params.compression.inhibit_htables = 0;
+               /*f->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG;*/
+
+       /* we set the video window to something smaller or equal to what
+        * is requested by the user???
+        */
+       DBG("Requested width = %d, height = %d\n",
+           f->fmt.pix.width, f->fmt.pix.height);
+       if (f->fmt.pix.width != cam->width ||
+           f->fmt.pix.height != cam->height) {
+               cam->width = f->fmt.pix.width;
+               cam->height = f->fmt.pix.height;
+               cam->params.roi.width = f->fmt.pix.width;
+               cam->params.roi.height = f->fmt.pix.height;
+               cpia2_set_format(cam);
+       }
+
+       for (frame = 0; frame < cam->num_frames; ++frame) {
+               if (cam->buffers[frame].status == FRAME_READING)
+                       if ((err = sync(cam, frame)) < 0)
+                               return err;
+
+               cam->buffers[frame].status = FRAME_EMPTY;
+       }
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  ioctl_get_fmt
+ *
+ *  V4L2 format get
+ *
+ *****************************************************************************/
+
+static int cpia2_g_fmt_vid_cap(struct file *file, void *fh,
+                                       struct v4l2_format *f)
+{
+       struct camera_data *cam = video_drvdata(file);
+
+       f->fmt.pix.width = cam->width;
+       f->fmt.pix.height = cam->height;
+       f->fmt.pix.pixelformat = cam->pixelformat;
+       f->fmt.pix.field = V4L2_FIELD_NONE;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage = cam->frame_size;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
+       f->fmt.pix.priv = 0;
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  ioctl_cropcap
+ *
+ *  V4L2 query cropping capabilities
+ *  NOTE: cropping is currently disabled
+ *
+ *****************************************************************************/
+
+static int cpia2_cropcap(struct file *file, void *fh, struct v4l2_cropcap *c)
+{
+       struct camera_data *cam = video_drvdata(file);
+
+       if (c->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+              return -EINVAL;
+
+       c->bounds.left = 0;
+       c->bounds.top = 0;
+       c->bounds.width = cam->width;
+       c->bounds.height = cam->height;
+       c->defrect.left = 0;
+       c->defrect.top = 0;
+       c->defrect.width = cam->width;
+       c->defrect.height = cam->height;
+       c->pixelaspect.numerator = 1;
+       c->pixelaspect.denominator = 1;
+
+       return 0;
+}
+
+struct framerate_info {
+       int value;
+       struct v4l2_fract period;
+};
+
+static const struct framerate_info framerate_controls[] = {
+       { CPIA2_VP_FRAMERATE_6_25, { 4, 25 } },
+       { CPIA2_VP_FRAMERATE_7_5,  { 2, 15 } },
+       { CPIA2_VP_FRAMERATE_12_5, { 2, 25 } },
+       { CPIA2_VP_FRAMERATE_15,   { 1, 15 } },
+       { CPIA2_VP_FRAMERATE_25,   { 1, 25 } },
+       { CPIA2_VP_FRAMERATE_30,   { 1, 30 } },
+};
+
+static int cpia2_g_parm(struct file *file, void *fh, struct v4l2_streamparm *p)
+{
+       struct camera_data *cam = video_drvdata(file);
+       struct v4l2_captureparm *cap = &p->parm.capture;
+       int i;
+
+       if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       cap->capability = V4L2_CAP_TIMEPERFRAME;
+       cap->readbuffers = cam->num_frames;
+       for (i = 0; i < ARRAY_SIZE(framerate_controls); i++)
+               if (cam->params.vp_params.frame_rate == framerate_controls[i].value) {
+                       cap->timeperframe = framerate_controls[i].period;
+                       break;
+               }
+       return 0;
+}
+
+static int cpia2_s_parm(struct file *file, void *fh, struct v4l2_streamparm *p)
+{
+       struct camera_data *cam = video_drvdata(file);
+       struct v4l2_captureparm *cap = &p->parm.capture;
+       struct v4l2_fract tpf = cap->timeperframe;
+       int max = ARRAY_SIZE(framerate_controls) - 1;
+       int ret;
+       int i;
+
+       ret = cpia2_g_parm(file, fh, p);
+       if (ret || !tpf.denominator || !tpf.numerator)
+               return ret;
+
+       /* Maximum 15 fps for this model */
+       if (cam->params.pnp_id.device_type == DEVICE_STV_672 &&
+           cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500)
+               max -= 2;
+       for (i = 0; i <= max; i++) {
+               struct v4l2_fract f1 = tpf;
+               struct v4l2_fract f2 = framerate_controls[i].period;
+
+               f1.numerator *= f2.denominator;
+               f2.numerator *= f1.denominator;
+               if (f1.numerator >= f2.numerator)
+                       break;
+       }
+       if (i > max)
+               i = max;
+       cap->timeperframe = framerate_controls[i].period;
+       return cpia2_set_fps(cam, framerate_controls[i].value);
+}
+
+static const struct {
+       u32 width;
+       u32 height;
+} cpia2_framesizes[] = {
+       { 640, 480 },
+       { 352, 288 },
+       { 320, 240 },
+       { 288, 216 },
+       { 256, 192 },
+       { 224, 168 },
+       { 192, 144 },
+       { 176, 144 },
+};
+
+static int cpia2_enum_framesizes(struct file *file, void *fh,
+                                        struct v4l2_frmsizeenum *fsize)
+{
+
+       if (fsize->pixel_format != V4L2_PIX_FMT_MJPEG &&
+           fsize->pixel_format != V4L2_PIX_FMT_JPEG)
+               return -EINVAL;
+       if (fsize->index >= ARRAY_SIZE(cpia2_framesizes))
+               return -EINVAL;
+       fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+       fsize->discrete.width = cpia2_framesizes[fsize->index].width;
+       fsize->discrete.height = cpia2_framesizes[fsize->index].height;
+
+       return 0;
+}
+
+static int cpia2_enum_frameintervals(struct file *file, void *fh,
+                                          struct v4l2_frmivalenum *fival)
+{
+       struct camera_data *cam = video_drvdata(file);
+       int max = ARRAY_SIZE(framerate_controls) - 1;
+       int i;
+
+       if (fival->pixel_format != V4L2_PIX_FMT_MJPEG &&
+           fival->pixel_format != V4L2_PIX_FMT_JPEG)
+               return -EINVAL;
+
+       /* Maximum 15 fps for this model */
+       if (cam->params.pnp_id.device_type == DEVICE_STV_672 &&
+           cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500)
+               max -= 2;
+       if (fival->index > max)
+               return -EINVAL;
+       for (i = 0; i < ARRAY_SIZE(cpia2_framesizes); i++)
+               if (fival->width == cpia2_framesizes[i].width &&
+                   fival->height == cpia2_framesizes[i].height)
+                       break;
+       if (i == ARRAY_SIZE(cpia2_framesizes))
+               return -EINVAL;
+       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+       fival->discrete = framerate_controls[fival->index].period;
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  ioctl_s_ctrl
+ *
+ *  V4L2 set the value of a control variable
+ *
+ *****************************************************************************/
+
+static int cpia2_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct camera_data *cam =
+               container_of(ctrl->handler, struct camera_data, hdl);
+       static const int flicker_table[] = {
+               NEVER_FLICKER,
+               FLICKER_50,
+               FLICKER_60,
+       };
+
+       DBG("Set control id:%d, value:%d\n", ctrl->id, ctrl->val);
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               cpia2_set_brightness(cam, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               cpia2_set_contrast(cam, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               cpia2_set_saturation(cam, ctrl->val);
+               break;
+       case V4L2_CID_HFLIP:
+               cpia2_set_property_mirror(cam, ctrl->val);
+               break;
+       case V4L2_CID_VFLIP:
+               cpia2_set_property_flip(cam, ctrl->val);
+               break;
+       case V4L2_CID_POWER_LINE_FREQUENCY:
+               return cpia2_set_flicker_mode(cam, flicker_table[ctrl->val]);
+       case V4L2_CID_ILLUMINATORS_1:
+               return cpia2_set_gpio(cam, (cam->top_light->val << 6) |
+                                          (cam->bottom_light->val << 7));
+       case V4L2_CID_JPEG_ACTIVE_MARKER:
+               cam->params.compression.inhibit_htables =
+                       !(ctrl->val & V4L2_JPEG_ACTIVE_MARKER_DHT);
+               break;
+       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+               cam->params.vc_params.quality = ctrl->val;
+               break;
+       case CPIA2_CID_USB_ALT:
+               cam->params.camera_state.stream_mode = ctrl->val;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  ioctl_g_jpegcomp
+ *
+ *  V4L2 get the JPEG compression parameters
+ *
+ *****************************************************************************/
+
+static int cpia2_g_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompression *parms)
+{
+       struct camera_data *cam = video_drvdata(file);
+
+       memset(parms, 0, sizeof(*parms));
+
+       parms->quality = 80; // TODO: Can this be made meaningful?
+
+       parms->jpeg_markers = V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI;
+       if(!cam->params.compression.inhibit_htables) {
+               parms->jpeg_markers |= V4L2_JPEG_MARKER_DHT;
+       }
+
+       parms->APPn = cam->APPn;
+       parms->APP_len = cam->APP_len;
+       if(cam->APP_len > 0) {
+               memcpy(parms->APP_data, cam->APP_data, cam->APP_len);
+               parms->jpeg_markers |= V4L2_JPEG_MARKER_APP;
+       }
+
+       parms->COM_len = cam->COM_len;
+       if(cam->COM_len > 0) {
+               memcpy(parms->COM_data, cam->COM_data, cam->COM_len);
+               parms->jpeg_markers |= JPEG_MARKER_COM;
+       }
+
+       DBG("G_JPEGCOMP APP_len:%d COM_len:%d\n",
+           parms->APP_len, parms->COM_len);
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  ioctl_s_jpegcomp
+ *
+ *  V4L2 set the JPEG compression parameters
+ *  NOTE: quality and some jpeg_markers are ignored.
+ *
+ *****************************************************************************/
+
+static int cpia2_s_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompression *parms)
+{
+       struct camera_data *cam = video_drvdata(file);
+
+       DBG("S_JPEGCOMP APP_len:%d COM_len:%d\n",
+           parms->APP_len, parms->COM_len);
+
+       cam->params.compression.inhibit_htables =
+               !(parms->jpeg_markers & V4L2_JPEG_MARKER_DHT);
+       parms->jpeg_markers &= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI |
+                              V4L2_JPEG_MARKER_DHT;
+
+       if(parms->APP_len != 0) {
+               if(parms->APP_len > 0 &&
+                  parms->APP_len <= sizeof(cam->APP_data) &&
+                  parms->APPn >= 0 && parms->APPn <= 15) {
+                       cam->APPn = parms->APPn;
+                       cam->APP_len = parms->APP_len;
+                       memcpy(cam->APP_data, parms->APP_data, parms->APP_len);
+               } else {
+                       LOG("Bad APPn Params n=%d len=%d\n",
+                           parms->APPn, parms->APP_len);
+                       return -EINVAL;
+               }
+       } else {
+               cam->APP_len = 0;
+       }
+
+       if(parms->COM_len != 0) {
+               if(parms->COM_len > 0 &&
+                  parms->COM_len <= sizeof(cam->COM_data)) {
+                       cam->COM_len = parms->COM_len;
+                       memcpy(cam->COM_data, parms->COM_data, parms->COM_len);
+               } else {
+                       LOG("Bad COM_len=%d\n", parms->COM_len);
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  ioctl_reqbufs
+ *
+ *  V4L2 Initiate memory mapping.
+ *  NOTE: The user's request is ignored. For now the buffers are fixed.
+ *
+ *****************************************************************************/
+
+static int cpia2_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *req)
+{
+       struct camera_data *cam = video_drvdata(file);
+
+       if(req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+          req->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
+
+       DBG("REQBUFS requested:%d returning:%d\n", req->count, cam->num_frames);
+       req->count = cam->num_frames;
+       memset(&req->reserved, 0, sizeof(req->reserved));
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  ioctl_querybuf
+ *
+ *  V4L2 Query memory buffer status.
+ *
+ *****************************************************************************/
+
+static int cpia2_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       struct camera_data *cam = video_drvdata(file);
+
+       if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+          buf->index > cam->num_frames)
+               return -EINVAL;
+
+       buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer;
+       buf->length = cam->frame_size;
+
+       buf->memory = V4L2_MEMORY_MMAP;
+
+       if(cam->mmapped)
+               buf->flags = V4L2_BUF_FLAG_MAPPED;
+       else
+               buf->flags = 0;
+
+       switch (cam->buffers[buf->index].status) {
+       case FRAME_EMPTY:
+       case FRAME_ERROR:
+       case FRAME_READING:
+               buf->bytesused = 0;
+               buf->flags = V4L2_BUF_FLAG_QUEUED;
+               break;
+       case FRAME_READY:
+               buf->bytesused = cam->buffers[buf->index].length;
+               buf->timestamp = cam->buffers[buf->index].timestamp;
+               buf->sequence = cam->buffers[buf->index].seq;
+               buf->flags = V4L2_BUF_FLAG_DONE;
+               break;
+       }
+
+       DBG("QUERYBUF index:%d offset:%d flags:%d seq:%d bytesused:%d\n",
+            buf->index, buf->m.offset, buf->flags, buf->sequence,
+            buf->bytesused);
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  ioctl_qbuf
+ *
+ *  V4L2 User is freeing buffer
+ *
+ *****************************************************************************/
+
+static int cpia2_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       struct camera_data *cam = video_drvdata(file);
+
+       if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+          buf->memory != V4L2_MEMORY_MMAP ||
+          buf->index > cam->num_frames)
+               return -EINVAL;
+
+       DBG("QBUF #%d\n", buf->index);
+
+       if(cam->buffers[buf->index].status == FRAME_READY)
+               cam->buffers[buf->index].status = FRAME_EMPTY;
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  find_earliest_filled_buffer
+ *
+ *  Helper for ioctl_dqbuf. Find the next ready buffer.
+ *
+ *****************************************************************************/
+
+static int find_earliest_filled_buffer(struct camera_data *cam)
+{
+       int i;
+       int found = -1;
+       for (i=0; i<cam->num_frames; i++) {
+               if(cam->buffers[i].status == FRAME_READY) {
+                       if(found < 0) {
+                               found = i;
+                       } else {
+                               /* find which buffer is earlier */
+                               struct timeval *tv1, *tv2;
+                               tv1 = &cam->buffers[i].timestamp;
+                               tv2 = &cam->buffers[found].timestamp;
+                               if(tv1->tv_sec < tv2->tv_sec ||
+                                  (tv1->tv_sec == tv2->tv_sec &&
+                                   tv1->tv_usec < tv2->tv_usec))
+                                       found = i;
+                       }
+               }
+       }
+       return found;
+}
+
+/******************************************************************************
+ *
+ *  ioctl_dqbuf
+ *
+ *  V4L2 User is asking for a filled buffer.
+ *
+ *****************************************************************************/
+
+static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+       struct camera_data *cam = video_drvdata(file);
+       int frame;
+
+       if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+          buf->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
+
+       frame = find_earliest_filled_buffer(cam);
+
+       if(frame < 0 && file->f_flags&O_NONBLOCK)
+               return -EAGAIN;
+
+       if(frame < 0) {
+               /* Wait for a frame to become available */
+               struct framebuf *cb=cam->curbuff;
+               mutex_unlock(&cam->v4l2_lock);
+               wait_event_interruptible(cam->wq_stream,
+                                        !video_is_registered(&cam->vdev) ||
+                                        (cb=cam->curbuff)->status == FRAME_READY);
+               mutex_lock(&cam->v4l2_lock);
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+               if (!video_is_registered(&cam->vdev))
+                       return -ENOTTY;
+               frame = cb->num;
+       }
+
+
+       buf->index = frame;
+       buf->bytesused = cam->buffers[buf->index].length;
+       buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
+       buf->field = V4L2_FIELD_NONE;
+       buf->timestamp = cam->buffers[buf->index].timestamp;
+       buf->sequence = cam->buffers[buf->index].seq;
+       buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer;
+       buf->length = cam->frame_size;
+       buf->reserved2 = 0;
+       buf->reserved = 0;
+       memset(&buf->timecode, 0, sizeof(buf->timecode));
+
+       DBG("DQBUF #%d status:%d seq:%d length:%d\n", buf->index,
+           cam->buffers[buf->index].status, buf->sequence, buf->bytesused);
+
+       return 0;
+}
+
+static int cpia2_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
+{
+       struct camera_data *cam = video_drvdata(file);
+       int ret = -EINVAL;
+
+       DBG("VIDIOC_STREAMON, streaming=%d\n", cam->streaming);
+       if (!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (!cam->streaming) {
+               ret = cpia2_usb_stream_start(cam,
+                               cam->params.camera_state.stream_mode);
+               if (!ret)
+                       v4l2_ctrl_grab(cam->usb_alt, true);
+       }
+       return ret;
+}
+
+static int cpia2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
+{
+       struct camera_data *cam = video_drvdata(file);
+       int ret = -EINVAL;
+
+       DBG("VIDIOC_STREAMOFF, streaming=%d\n", cam->streaming);
+       if (!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (cam->streaming) {
+               ret = cpia2_usb_stream_stop(cam);
+               if (!ret)
+                       v4l2_ctrl_grab(cam->usb_alt, false);
+       }
+       return ret;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_mmap
+ *
+ *****************************************************************************/
+static int cpia2_mmap(struct file *file, struct vm_area_struct *area)
+{
+       struct camera_data *cam = video_drvdata(file);
+       int retval;
+
+       if (mutex_lock_interruptible(&cam->v4l2_lock))
+               return -ERESTARTSYS;
+       retval = cpia2_remap_buffer(cam, area);
+
+       if(!retval)
+               cam->stream_fh = file->private_data;
+       mutex_unlock(&cam->v4l2_lock);
+       return retval;
+}
+
+/******************************************************************************
+ *
+ *  reset_camera_struct_v4l
+ *
+ *  Sets all values to the defaults
+ *****************************************************************************/
+static void reset_camera_struct_v4l(struct camera_data *cam)
+{
+       cam->width = cam->params.roi.width;
+       cam->height = cam->params.roi.height;
+
+       cam->frame_size = buffer_size;
+       cam->num_frames = num_buffers;
+
+       /* Flicker modes */
+       cam->params.flicker_control.flicker_mode_req = flicker_mode;
+
+       /* stream modes */
+       cam->params.camera_state.stream_mode = alternate;
+
+       cam->pixelformat = V4L2_PIX_FMT_JPEG;
+}
+
+static const struct v4l2_ioctl_ops cpia2_ioctl_ops = {
+       .vidioc_querycap                    = cpia2_querycap,
+       .vidioc_enum_input                  = cpia2_enum_input,
+       .vidioc_g_input                     = cpia2_g_input,
+       .vidioc_s_input                     = cpia2_s_input,
+       .vidioc_enum_fmt_vid_cap            = cpia2_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap               = cpia2_g_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap               = cpia2_s_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap             = cpia2_try_fmt_vid_cap,
+       .vidioc_g_jpegcomp                  = cpia2_g_jpegcomp,
+       .vidioc_s_jpegcomp                  = cpia2_s_jpegcomp,
+       .vidioc_cropcap                     = cpia2_cropcap,
+       .vidioc_reqbufs                     = cpia2_reqbufs,
+       .vidioc_querybuf                    = cpia2_querybuf,
+       .vidioc_qbuf                        = cpia2_qbuf,
+       .vidioc_dqbuf                       = cpia2_dqbuf,
+       .vidioc_streamon                    = cpia2_streamon,
+       .vidioc_streamoff                   = cpia2_streamoff,
+       .vidioc_s_parm                      = cpia2_s_parm,
+       .vidioc_g_parm                      = cpia2_g_parm,
+       .vidioc_enum_framesizes             = cpia2_enum_framesizes,
+       .vidioc_enum_frameintervals         = cpia2_enum_frameintervals,
+       .vidioc_subscribe_event             = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event           = v4l2_event_unsubscribe,
+};
+
+/***
+ * The v4l video device structure initialized for this device
+ ***/
+static const struct v4l2_file_operations cpia2_fops = {
+       .owner          = THIS_MODULE,
+       .open           = cpia2_open,
+       .release        = cpia2_close,
+       .read           = cpia2_v4l_read,
+       .poll           = cpia2_v4l_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = cpia2_mmap,
+};
+
+static struct video_device cpia2_template = {
+       /* I could not find any place for the old .initialize initializer?? */
+       .name =         "CPiA2 Camera",
+       .fops =         &cpia2_fops,
+       .ioctl_ops =    &cpia2_ioctl_ops,
+       .release =      video_device_release_empty,
+};
+
+void cpia2_camera_release(struct v4l2_device *v4l2_dev)
+{
+       struct camera_data *cam =
+               container_of(v4l2_dev, struct camera_data, v4l2_dev);
+
+       v4l2_ctrl_handler_free(&cam->hdl);
+       v4l2_device_unregister(&cam->v4l2_dev);
+       kfree(cam);
+}
+
+static const struct v4l2_ctrl_ops cpia2_ctrl_ops = {
+       .s_ctrl = cpia2_s_ctrl,
+};
+
+/******************************************************************************
+ *
+ *  cpia2_register_camera
+ *
+ *****************************************************************************/
+int cpia2_register_camera(struct camera_data *cam)
+{
+       struct v4l2_ctrl_handler *hdl = &cam->hdl;
+       struct v4l2_ctrl_config cpia2_usb_alt = {
+               .ops = &cpia2_ctrl_ops,
+               .id = CPIA2_CID_USB_ALT,
+               .name = "USB Alternate",
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .min = USBIF_ISO_1,
+               .max = USBIF_ISO_6,
+               .step = 1,
+       };
+       int ret;
+
+       v4l2_ctrl_handler_init(hdl, 12);
+       v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS,
+                       cam->params.pnp_id.device_type == DEVICE_STV_672 ? 1 : 0,
+                       255, 1, DEFAULT_BRIGHTNESS);
+       v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 255, 1, DEFAULT_CONTRAST);
+       v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 255, 1, DEFAULT_SATURATION);
+       v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
+                       V4L2_CID_JPEG_ACTIVE_MARKER, 0,
+                       V4L2_JPEG_ACTIVE_MARKER_DHT, 0,
+                       V4L2_JPEG_ACTIVE_MARKER_DHT);
+       v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
+                       V4L2_CID_JPEG_COMPRESSION_QUALITY, 1,
+                       100, 1, 100);
+       cpia2_usb_alt.def = alternate;
+       cam->usb_alt = v4l2_ctrl_new_custom(hdl, &cpia2_usb_alt, NULL);
+       /* VP5 Only */
+       if (cam->params.pnp_id.device_type != DEVICE_STV_672)
+               v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       /* Flicker control only valid for 672 */
+       if (cam->params.pnp_id.device_type == DEVICE_STV_672)
+               v4l2_ctrl_new_std_menu(hdl, &cpia2_ctrl_ops,
+                       V4L2_CID_POWER_LINE_FREQUENCY,
+                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
+       /* Light control only valid for the QX5 Microscope */
+       if (cam->params.pnp_id.product == 0x151) {
+               cam->top_light = v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
+                               V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
+               cam->bottom_light = v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
+                               V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0);
+               v4l2_ctrl_cluster(2, &cam->top_light);
+       }
+
+       if (hdl->error) {
+               ret = hdl->error;
+               v4l2_ctrl_handler_free(hdl);
+               return ret;
+       }
+
+       cam->vdev = cpia2_template;
+       video_set_drvdata(&cam->vdev, cam);
+       cam->vdev.lock = &cam->v4l2_lock;
+       cam->vdev.ctrl_handler = hdl;
+       cam->vdev.v4l2_dev = &cam->v4l2_dev;
+       set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
+
+       reset_camera_struct_v4l(cam);
+
+       /* register v4l device */
+       if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
+               ERR("video_register_device failed\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+/******************************************************************************
+ *
+ *  cpia2_unregister_camera
+ *
+ *****************************************************************************/
+void cpia2_unregister_camera(struct camera_data *cam)
+{
+       video_unregister_device(&cam->vdev);
+}
+
+/******************************************************************************
+ *
+ *  check_parameters
+ *
+ *  Make sure that all user-supplied parameters are sensible
+ *****************************************************************************/
+static void __init check_parameters(void)
+{
+       if(buffer_size < PAGE_SIZE) {
+               buffer_size = PAGE_SIZE;
+               LOG("buffer_size too small, setting to %d\n", buffer_size);
+       } else if(buffer_size > 1024*1024) {
+               /* arbitrary upper limiit */
+               buffer_size = 1024*1024;
+               LOG("buffer_size ridiculously large, setting to %d\n",
+                   buffer_size);
+       } else {
+               buffer_size += PAGE_SIZE-1;
+               buffer_size &= ~(PAGE_SIZE-1);
+       }
+
+       if(num_buffers < 1) {
+               num_buffers = 1;
+               LOG("num_buffers too small, setting to %d\n", num_buffers);
+       } else if(num_buffers > VIDEO_MAX_FRAME) {
+               num_buffers = VIDEO_MAX_FRAME;
+               LOG("num_buffers too large, setting to %d\n", num_buffers);
+       }
+
+       if(alternate < USBIF_ISO_1 || alternate > USBIF_ISO_6) {
+               alternate = DEFAULT_ALT;
+               LOG("alternate specified is invalid, using %d\n", alternate);
+       }
+
+       if (flicker_mode != 0 && flicker_mode != FLICKER_50 && flicker_mode != FLICKER_60) {
+               flicker_mode = 0;
+               LOG("Flicker mode specified is invalid, using %d\n",
+                   flicker_mode);
+       }
+
+       DBG("Using %d buffers, each %d bytes, alternate=%d\n",
+           num_buffers, buffer_size, alternate);
+}
+
+/************   Module Stuff ***************/
+
+
+/******************************************************************************
+ *
+ * cpia2_init/module_init
+ *
+ *****************************************************************************/
+static int __init cpia2_init(void)
+{
+       LOG("%s v%s\n",
+           ABOUT, CPIA_VERSION);
+       check_parameters();
+       cpia2_usb_init();
+       return 0;
+}
+
+
+/******************************************************************************
+ *
+ * cpia2_exit/module_exit
+ *
+ *****************************************************************************/
+static void __exit cpia2_exit(void)
+{
+       cpia2_usb_cleanup();
+       schedule_timeout(2 * HZ);
+}
+
+module_init(cpia2_init);
+module_exit(cpia2_exit);
diff --git a/drivers/media/usb/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig
new file mode 100644 (file)
index 0000000..446f692
--- /dev/null
@@ -0,0 +1,51 @@
+config VIDEO_CX231XX
+       tristate "Conexant cx231xx USB video capture support"
+       depends on VIDEO_DEV && I2C
+       select VIDEO_TUNER
+       select VIDEO_TVEEPROM
+       depends on RC_CORE
+       select VIDEOBUF_VMALLOC
+       select VIDEO_CX25840
+       select VIDEO_CX2341X
+
+       ---help---
+         This is a video4linux driver for Conexant 231xx USB based TV cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx231xx
+
+config VIDEO_CX231XX_RC
+       bool "Conexant cx231xx Remote Controller additional support"
+       depends on RC_CORE
+       depends on VIDEO_CX231XX
+       default y
+       ---help---
+         cx231xx hardware has a builtin RX/TX support. However, a few
+         designs opted to not use it, but, instead, some other hardware.
+         This module enables the usage of those other hardware, like the
+         ones used with ISDB-T boards.
+
+         On most cases, all you need for IR is mceusb module.
+
+config VIDEO_CX231XX_ALSA
+       tristate "Conexant Cx231xx ALSA audio module"
+       depends on VIDEO_CX231XX && SND
+       select SND_PCM
+
+       ---help---
+         This is an ALSA driver for Cx231xx USB based TV cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx231xx-alsa
+
+config VIDEO_CX231XX_DVB
+       tristate "DVB/ATSC Support for Cx231xx based TV cards"
+       depends on VIDEO_CX231XX && DVB_CORE && DVB_CAPTURE_DRIVERS
+       select VIDEOBUF_DVB
+       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
+       select DVB_MB86A20S if !DVB_FE_CUSTOMISE
+
+       ---help---
+         This adds support for DVB cards based on the
+         Conexant cx231xx chips.
diff --git a/drivers/media/usb/cx231xx/Makefile b/drivers/media/usb/cx231xx/Makefile
new file mode 100644 (file)
index 0000000..1d40fce
--- /dev/null
@@ -0,0 +1,15 @@
+cx231xx-y += cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o
+cx231xx-y += cx231xx-avcore.o cx231xx-417.o cx231xx-pcb-cfg.o cx231xx-vbi.o
+cx231xx-$(CONFIG_VIDEO_CX231XX_RC) += cx231xx-input.o
+
+cx231xx-alsa-objs := cx231xx-audio.o
+
+obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o
+obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o
+obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o
+
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
+ccflags-y += -Idrivers/media/usb/dvb-usb
diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c
new file mode 100644 (file)
index 0000000..b024e51
--- /dev/null
@@ -0,0 +1,2197 @@
+/*
+ *
+ *  Support for a cx23417 mpeg encoder via cx231xx host port.
+ *
+ *    (c) 2004 Jelle Foks <jelle@foks.us>
+ *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
+ *    (c) 2008 Steven Toth <stoth@linuxtv.org>
+ *      - CX23885/7/8 support
+ *
+ *  Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/vmalloc.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/cx2341x.h>
+#include <linux/usb.h>
+
+#include "cx231xx.h"
+/*#include "cx23885-ioctl.h"*/
+
+#define CX231xx_FIRM_IMAGE_SIZE 376836
+#define CX231xx_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
+
+/* for polaris ITVC */
+#define ITVC_WRITE_DIR          0x03FDFC00
+#define ITVC_READ_DIR            0x0001FC00
+
+#define  MCI_MEMORY_DATA_BYTE0          0x00
+#define  MCI_MEMORY_DATA_BYTE1          0x08
+#define  MCI_MEMORY_DATA_BYTE2          0x10
+#define  MCI_MEMORY_DATA_BYTE3          0x18
+
+#define  MCI_MEMORY_ADDRESS_BYTE2       0x20
+#define  MCI_MEMORY_ADDRESS_BYTE1       0x28
+#define  MCI_MEMORY_ADDRESS_BYTE0       0x30
+
+#define  MCI_REGISTER_DATA_BYTE0        0x40
+#define  MCI_REGISTER_DATA_BYTE1        0x48
+#define  MCI_REGISTER_DATA_BYTE2        0x50
+#define  MCI_REGISTER_DATA_BYTE3        0x58
+
+#define  MCI_REGISTER_ADDRESS_BYTE0     0x60
+#define  MCI_REGISTER_ADDRESS_BYTE1     0x68
+
+#define  MCI_REGISTER_MODE              0x70
+
+/* Read and write modes for polaris ITVC */
+#define  MCI_MODE_REGISTER_READ         0x000
+#define  MCI_MODE_REGISTER_WRITE        0x100
+#define  MCI_MODE_MEMORY_READ           0x000
+#define  MCI_MODE_MEMORY_WRITE          0x4000
+
+static unsigned int mpegbufs = 8;
+module_param(mpegbufs, int, 0644);
+MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");
+static unsigned int mpeglines = 128;
+module_param(mpeglines, int, 0644);
+MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");
+static unsigned int mpeglinesize = 512;
+module_param(mpeglinesize, int, 0644);
+MODULE_PARM_DESC(mpeglinesize,
+       "number of bytes in each line of an MPEG buffer, range 512-1024");
+
+static unsigned int v4l_debug = 1;
+module_param(v4l_debug, int, 0644);
+MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
+struct cx231xx_dmaqueue *dma_qq;
+#define dprintk(level, fmt, arg...)\
+       do { if (v4l_debug >= level) \
+               printk(KERN_INFO "%s: " fmt, \
+               (dev) ? dev->name : "cx231xx[?]", ## arg); \
+       } while (0)
+
+static struct cx231xx_tvnorm cx231xx_tvnorms[] = {
+       {
+               .name      = "NTSC-M",
+               .id        = V4L2_STD_NTSC_M,
+       }, {
+               .name      = "NTSC-JP",
+               .id        = V4L2_STD_NTSC_M_JP,
+       }, {
+               .name      = "PAL-BG",
+               .id        = V4L2_STD_PAL_BG,
+       }, {
+               .name      = "PAL-DK",
+               .id        = V4L2_STD_PAL_DK,
+       }, {
+               .name      = "PAL-I",
+               .id        = V4L2_STD_PAL_I,
+       }, {
+               .name      = "PAL-M",
+               .id        = V4L2_STD_PAL_M,
+       }, {
+               .name      = "PAL-N",
+               .id        = V4L2_STD_PAL_N,
+       }, {
+               .name      = "PAL-Nc",
+               .id        = V4L2_STD_PAL_Nc,
+       }, {
+               .name      = "PAL-60",
+               .id        = V4L2_STD_PAL_60,
+       }, {
+               .name      = "SECAM-L",
+               .id        = V4L2_STD_SECAM_L,
+       }, {
+               .name      = "SECAM-DK",
+               .id        = V4L2_STD_SECAM_DK,
+       }
+};
+
+/* ------------------------------------------------------------------ */
+enum cx231xx_capture_type {
+       CX231xx_MPEG_CAPTURE,
+       CX231xx_RAW_CAPTURE,
+       CX231xx_RAW_PASSTHRU_CAPTURE
+};
+enum cx231xx_capture_bits {
+       CX231xx_RAW_BITS_NONE             = 0x00,
+       CX231xx_RAW_BITS_YUV_CAPTURE      = 0x01,
+       CX231xx_RAW_BITS_PCM_CAPTURE      = 0x02,
+       CX231xx_RAW_BITS_VBI_CAPTURE      = 0x04,
+       CX231xx_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
+       CX231xx_RAW_BITS_TO_HOST_CAPTURE  = 0x10
+};
+enum cx231xx_capture_end {
+       CX231xx_END_AT_GOP, /* stop at the end of gop, generate irq */
+       CX231xx_END_NOW, /* stop immediately, no irq */
+};
+enum cx231xx_framerate {
+       CX231xx_FRAMERATE_NTSC_30, /* NTSC: 30fps */
+       CX231xx_FRAMERATE_PAL_25   /* PAL: 25fps */
+};
+enum cx231xx_stream_port {
+       CX231xx_OUTPUT_PORT_MEMORY,
+       CX231xx_OUTPUT_PORT_STREAMING,
+       CX231xx_OUTPUT_PORT_SERIAL
+};
+enum cx231xx_data_xfer_status {
+       CX231xx_MORE_BUFFERS_FOLLOW,
+       CX231xx_LAST_BUFFER,
+};
+enum cx231xx_picture_mask {
+       CX231xx_PICTURE_MASK_NONE,
+       CX231xx_PICTURE_MASK_I_FRAMES,
+       CX231xx_PICTURE_MASK_I_P_FRAMES = 0x3,
+       CX231xx_PICTURE_MASK_ALL_FRAMES = 0x7,
+};
+enum cx231xx_vbi_mode_bits {
+       CX231xx_VBI_BITS_SLICED,
+       CX231xx_VBI_BITS_RAW,
+};
+enum cx231xx_vbi_insertion_bits {
+       CX231xx_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
+       CX231xx_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
+       CX231xx_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
+       CX231xx_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
+       CX231xx_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
+};
+enum cx231xx_dma_unit {
+       CX231xx_DMA_BYTES,
+       CX231xx_DMA_FRAMES,
+};
+enum cx231xx_dma_transfer_status_bits {
+       CX231xx_DMA_TRANSFER_BITS_DONE = 0x01,
+       CX231xx_DMA_TRANSFER_BITS_ERROR = 0x04,
+       CX231xx_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
+};
+enum cx231xx_pause {
+       CX231xx_PAUSE_ENCODING,
+       CX231xx_RESUME_ENCODING,
+};
+enum cx231xx_copyright {
+       CX231xx_COPYRIGHT_OFF,
+       CX231xx_COPYRIGHT_ON,
+};
+enum cx231xx_notification_type {
+       CX231xx_NOTIFICATION_REFRESH,
+};
+enum cx231xx_notification_status {
+       CX231xx_NOTIFICATION_OFF,
+       CX231xx_NOTIFICATION_ON,
+};
+enum cx231xx_notification_mailbox {
+       CX231xx_NOTIFICATION_NO_MAILBOX = -1,
+};
+enum cx231xx_field1_lines {
+       CX231xx_FIELD1_SAA7114 = 0x00EF, /* 239 */
+       CX231xx_FIELD1_SAA7115 = 0x00F0, /* 240 */
+       CX231xx_FIELD1_MICRONAS = 0x0105, /* 261 */
+};
+enum cx231xx_field2_lines {
+       CX231xx_FIELD2_SAA7114 = 0x00EF, /* 239 */
+       CX231xx_FIELD2_SAA7115 = 0x00F0, /* 240 */
+       CX231xx_FIELD2_MICRONAS = 0x0106, /* 262 */
+};
+enum cx231xx_custom_data_type {
+       CX231xx_CUSTOM_EXTENSION_USR_DATA,
+       CX231xx_CUSTOM_PRIVATE_PACKET,
+};
+enum cx231xx_mute {
+       CX231xx_UNMUTE,
+       CX231xx_MUTE,
+};
+enum cx231xx_mute_video_mask {
+       CX231xx_MUTE_VIDEO_V_MASK = 0x0000FF00,
+       CX231xx_MUTE_VIDEO_U_MASK = 0x00FF0000,
+       CX231xx_MUTE_VIDEO_Y_MASK = 0xFF000000,
+};
+enum cx231xx_mute_video_shift {
+       CX231xx_MUTE_VIDEO_V_SHIFT = 8,
+       CX231xx_MUTE_VIDEO_U_SHIFT = 16,
+       CX231xx_MUTE_VIDEO_Y_SHIFT = 24,
+};
+
+/* defines below are from ivtv-driver.h */
+#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
+
+/* Firmware API commands */
+#define IVTV_API_STD_TIMEOUT 500
+
+/* Registers */
+/* IVTV_REG_OFFSET */
+#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8)
+#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC)
+#define IVTV_REG_SPU (0x9050)
+#define IVTV_REG_HW_BLOCKS (0x9054)
+#define IVTV_REG_VPU (0x9058)
+#define IVTV_REG_APU (0xA064)
+
+/*
+ * Bit definitions for MC417_RWD and MC417_OEN registers
+ *
+ * bits 31-16
+ *+-----------+
+ *| Reserved  |
+ *|+-----------+
+ *|  bit 15  bit 14  bit 13 bit 12  bit 11  bit 10  bit 9   bit 8
+ *|+-------+-------+-------+-------+-------+-------+-------+-------+
+ *|| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0|
+ *|+-------+-------+-------+-------+-------+-------+-------+-------+
+ *| bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
+ *|+-------+-------+-------+-------+-------+-------+-------+-------+
+ *||MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0|
+ *|+-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+#define MC417_MIWR     0x8000
+#define MC417_MIRD     0x4000
+#define MC417_MICS     0x2000
+#define MC417_MIRDY    0x1000
+#define MC417_MIADDR   0x0F00
+#define MC417_MIDATA   0x00FF
+
+
+/* Bit definitions for MC417_CTL register ****
+ *bits 31-6   bits 5-4   bit 3    bits 2-1       Bit 0
+ *+--------+-------------+--------+--------------+------------+
+ *|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN|
+ *+--------+-------------+--------+--------------+------------+
+ */
+#define MC417_SPD_CTL(x)       (((x) << 4) & 0x00000030)
+#define MC417_GPIO_SEL(x)      (((x) << 1) & 0x00000006)
+#define MC417_UART_GPIO_EN     0x00000001
+
+/* Values for speed control */
+#define MC417_SPD_CTL_SLOW     0x1
+#define MC417_SPD_CTL_MEDIUM   0x0
+#define MC417_SPD_CTL_FAST     0x3     /* b'1x, but we use b'11 */
+
+/* Values for GPIO select */
+#define MC417_GPIO_SEL_GPIO3   0x3
+#define MC417_GPIO_SEL_GPIO2   0x2
+#define MC417_GPIO_SEL_GPIO1   0x1
+#define MC417_GPIO_SEL_GPIO0   0x0
+
+
+#define CX23417_GPIO_MASK 0xFC0003FF
+static int setITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 value)
+{
+       int status = 0;
+       u32 _gpio_direction = 0;
+
+       _gpio_direction = _gpio_direction & CX23417_GPIO_MASK;
+       _gpio_direction = _gpio_direction|gpio_direction;
+       status = cx231xx_send_gpio_cmd(dev, _gpio_direction,
+                        (u8 *)&value, 4, 0, 0);
+       return status;
+}
+static int getITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 *pValue)
+{
+       int status = 0;
+       u32 _gpio_direction = 0;
+
+       _gpio_direction = _gpio_direction & CX23417_GPIO_MASK;
+       _gpio_direction = _gpio_direction|gpio_direction;
+
+       status = cx231xx_send_gpio_cmd(dev, _gpio_direction,
+                (u8 *)pValue, 4, 0, 1);
+       return status;
+}
+
+static int waitForMciComplete(struct cx231xx *dev)
+{
+       u32 gpio;
+       u32 gpio_driection = 0;
+       u8 count = 0;
+       getITVCReg(dev, gpio_driection, &gpio);
+
+       while (!(gpio&0x020000)) {
+               msleep(10);
+
+               getITVCReg(dev, gpio_driection, &gpio);
+
+               if (count++ > 100) {
+                       dprintk(3, "ERROR: Timeout - gpio=%x\n", gpio);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+static int mc417_register_write(struct cx231xx *dev, u16 address, u32 value)
+{
+       u32 temp;
+       int status = 0;
+
+       temp = 0x82|MCI_REGISTER_DATA_BYTE0|((value&0x000000FF)<<8);
+       temp = temp<<10;
+       status = setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       if (status < 0)
+               return status;
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*write data byte 1;*/
+       temp = 0x82|MCI_REGISTER_DATA_BYTE1|(value&0x0000FF00);
+       temp = temp<<10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*write data byte 2;*/
+       temp = 0x82|MCI_REGISTER_DATA_BYTE2|((value&0x00FF0000)>>8);
+       temp = temp<<10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*write data byte 3;*/
+       temp = 0x82|MCI_REGISTER_DATA_BYTE3|((value&0xFF000000)>>16);
+       temp = temp<<10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*write address byte 0;*/
+       temp = 0x82|MCI_REGISTER_ADDRESS_BYTE0|((address&0x000000FF)<<8);
+       temp = temp<<10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*write address byte 1;*/
+       temp = 0x82|MCI_REGISTER_ADDRESS_BYTE1|(address&0x0000FF00);
+       temp = temp<<10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*Write that the mode is write.*/
+       temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_WRITE;
+       temp = temp<<10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       return waitForMciComplete(dev);
+}
+
+static int mc417_register_read(struct cx231xx *dev, u16 address, u32 *value)
+{
+       /*write address byte 0;*/
+       u32 temp;
+       u32 return_value = 0;
+       int ret = 0;
+
+       temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE0 | ((address & 0x00FF) << 8);
+       temp = temp << 10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp | ((0x05) << 10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*write address byte 1;*/
+       temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE1 | (address & 0xFF00);
+       temp = temp << 10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp | ((0x05) << 10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*write that the mode is read;*/
+       temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_READ;
+       temp = temp << 10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp | ((0x05) << 10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*wait for the MIRDY line to be asserted ,
+       signalling that the read is done;*/
+       ret = waitForMciComplete(dev);
+
+       /*switch the DATA- GPIO to input mode;*/
+
+       /*Read data byte 0;*/
+       temp = (0x82 | MCI_REGISTER_DATA_BYTE0) << 10;
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       temp = ((0x81 | MCI_REGISTER_DATA_BYTE0) << 10);
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       getITVCReg(dev, ITVC_READ_DIR, &temp);
+       return_value |= ((temp & 0x03FC0000) >> 18);
+       setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));
+
+       /* Read data byte 1;*/
+       temp = (0x82 | MCI_REGISTER_DATA_BYTE1) << 10;
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       temp = ((0x81 | MCI_REGISTER_DATA_BYTE1) << 10);
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       getITVCReg(dev, ITVC_READ_DIR, &temp);
+
+       return_value |= ((temp & 0x03FC0000) >> 10);
+       setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));
+
+       /*Read data byte 2;*/
+       temp = (0x82 | MCI_REGISTER_DATA_BYTE2) << 10;
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       temp = ((0x81 | MCI_REGISTER_DATA_BYTE2) << 10);
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       getITVCReg(dev, ITVC_READ_DIR, &temp);
+       return_value |= ((temp & 0x03FC0000) >> 2);
+       setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));
+
+       /*Read data byte 3;*/
+       temp = (0x82 | MCI_REGISTER_DATA_BYTE3) << 10;
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       temp = ((0x81 | MCI_REGISTER_DATA_BYTE3) << 10);
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       getITVCReg(dev, ITVC_READ_DIR, &temp);
+       return_value |= ((temp & 0x03FC0000) << 6);
+       setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));
+
+       *value  = return_value;
+
+
+       return ret;
+}
+
+static int mc417_memory_write(struct cx231xx *dev, u32 address, u32 value)
+{
+       /*write data byte 0;*/
+
+       u32 temp;
+       int ret = 0;
+
+       temp = 0x82 | MCI_MEMORY_DATA_BYTE0|((value & 0x000000FF) << 8);
+       temp = temp << 10;
+       ret = setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       if (ret < 0)
+               return ret;
+       temp = temp | ((0x05) << 10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*write data byte 1;*/
+       temp = 0x82 | MCI_MEMORY_DATA_BYTE1 | (value & 0x0000FF00);
+       temp = temp << 10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp | ((0x05) << 10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*write data byte 2;*/
+       temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8);
+       temp = temp<<10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*write data byte 3;*/
+       temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16);
+       temp = temp<<10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /* write address byte 2;*/
+       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE |
+               ((address & 0x003F0000)>>8);
+       temp = temp<<10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /* write address byte 1;*/
+       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
+       temp = temp<<10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /* write address byte 0;*/
+       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8);
+       temp = temp<<10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*wait for MIRDY line;*/
+       waitForMciComplete(dev);
+
+       return 0;
+}
+
+static int mc417_memory_read(struct cx231xx *dev, u32 address, u32 *value)
+{
+       u32 temp = 0;
+       u32 return_value = 0;
+       int ret = 0;
+
+       /*write address byte 2;*/
+       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_READ |
+               ((address & 0x003F0000)>>8);
+       temp = temp<<10;
+       ret = setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       if (ret < 0)
+               return ret;
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*write address byte 1*/
+       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
+       temp = temp<<10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*write address byte 0*/
+       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF)<<8);
+       temp = temp<<10;
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+       temp = temp|((0x05)<<10);
+       setITVCReg(dev, ITVC_WRITE_DIR, temp);
+
+       /*Wait for MIRDY line*/
+       ret = waitForMciComplete(dev);
+
+
+       /*Read data byte 3;*/
+       temp = (0x82|MCI_MEMORY_DATA_BYTE3)<<10;
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       temp = ((0x81|MCI_MEMORY_DATA_BYTE3)<<10);
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       getITVCReg(dev, ITVC_READ_DIR, &temp);
+       return_value |= ((temp&0x03FC0000)<<6);
+       setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
+
+       /*Read data byte 2;*/
+       temp = (0x82|MCI_MEMORY_DATA_BYTE2)<<10;
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       temp = ((0x81|MCI_MEMORY_DATA_BYTE2)<<10);
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       getITVCReg(dev, ITVC_READ_DIR, &temp);
+       return_value |= ((temp&0x03FC0000)>>2);
+       setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
+
+       /* Read data byte 1;*/
+       temp = (0x82|MCI_MEMORY_DATA_BYTE1)<<10;
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       temp = ((0x81|MCI_MEMORY_DATA_BYTE1)<<10);
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       getITVCReg(dev, ITVC_READ_DIR, &temp);
+       return_value |= ((temp&0x03FC0000)>>10);
+       setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
+
+       /*Read data byte 0;*/
+       temp = (0x82|MCI_MEMORY_DATA_BYTE0)<<10;
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       temp = ((0x81|MCI_MEMORY_DATA_BYTE0)<<10);
+       setITVCReg(dev, ITVC_READ_DIR, temp);
+       getITVCReg(dev, ITVC_READ_DIR, &temp);
+       return_value |= ((temp&0x03FC0000)>>18);
+       setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
+
+       *value  = return_value;
+       return ret;
+}
+
+/* ------------------------------------------------------------------ */
+
+/* MPEG encoder API */
+static char *cmd_to_str(int cmd)
+{
+       switch (cmd) {
+       case CX2341X_ENC_PING_FW:
+               return  "PING_FW";
+       case CX2341X_ENC_START_CAPTURE:
+               return  "START_CAPTURE";
+       case CX2341X_ENC_STOP_CAPTURE:
+               return  "STOP_CAPTURE";
+       case CX2341X_ENC_SET_AUDIO_ID:
+               return  "SET_AUDIO_ID";
+       case CX2341X_ENC_SET_VIDEO_ID:
+               return  "SET_VIDEO_ID";
+       case CX2341X_ENC_SET_PCR_ID:
+               return  "SET_PCR_PID";
+       case CX2341X_ENC_SET_FRAME_RATE:
+               return  "SET_FRAME_RATE";
+       case CX2341X_ENC_SET_FRAME_SIZE:
+               return  "SET_FRAME_SIZE";
+       case CX2341X_ENC_SET_BIT_RATE:
+               return  "SET_BIT_RATE";
+       case CX2341X_ENC_SET_GOP_PROPERTIES:
+               return  "SET_GOP_PROPERTIES";
+       case CX2341X_ENC_SET_ASPECT_RATIO:
+               return  "SET_ASPECT_RATIO";
+       case CX2341X_ENC_SET_DNR_FILTER_MODE:
+               return  "SET_DNR_FILTER_PROPS";
+       case CX2341X_ENC_SET_DNR_FILTER_PROPS:
+               return  "SET_DNR_FILTER_PROPS";
+       case CX2341X_ENC_SET_CORING_LEVELS:
+               return  "SET_CORING_LEVELS";
+       case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
+               return  "SET_SPATIAL_FILTER_TYPE";
+       case CX2341X_ENC_SET_VBI_LINE:
+               return  "SET_VBI_LINE";
+       case CX2341X_ENC_SET_STREAM_TYPE:
+               return  "SET_STREAM_TYPE";
+       case CX2341X_ENC_SET_OUTPUT_PORT:
+               return  "SET_OUTPUT_PORT";
+       case CX2341X_ENC_SET_AUDIO_PROPERTIES:
+               return  "SET_AUDIO_PROPERTIES";
+       case CX2341X_ENC_HALT_FW:
+               return  "HALT_FW";
+       case CX2341X_ENC_GET_VERSION:
+               return  "GET_VERSION";
+       case CX2341X_ENC_SET_GOP_CLOSURE:
+               return  "SET_GOP_CLOSURE";
+       case CX2341X_ENC_GET_SEQ_END:
+               return  "GET_SEQ_END";
+       case CX2341X_ENC_SET_PGM_INDEX_INFO:
+               return  "SET_PGM_INDEX_INFO";
+       case CX2341X_ENC_SET_VBI_CONFIG:
+               return  "SET_VBI_CONFIG";
+       case CX2341X_ENC_SET_DMA_BLOCK_SIZE:
+               return  "SET_DMA_BLOCK_SIZE";
+       case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10:
+               return  "GET_PREV_DMA_INFO_MB_10";
+       case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9:
+               return  "GET_PREV_DMA_INFO_MB_9";
+       case CX2341X_ENC_SCHED_DMA_TO_HOST:
+               return  "SCHED_DMA_TO_HOST";
+       case CX2341X_ENC_INITIALIZE_INPUT:
+               return  "INITIALIZE_INPUT";
+       case CX2341X_ENC_SET_FRAME_DROP_RATE:
+               return  "SET_FRAME_DROP_RATE";
+       case CX2341X_ENC_PAUSE_ENCODER:
+               return  "PAUSE_ENCODER";
+       case CX2341X_ENC_REFRESH_INPUT:
+               return  "REFRESH_INPUT";
+       case CX2341X_ENC_SET_COPYRIGHT:
+               return  "SET_COPYRIGHT";
+       case CX2341X_ENC_SET_EVENT_NOTIFICATION:
+               return  "SET_EVENT_NOTIFICATION";
+       case CX2341X_ENC_SET_NUM_VSYNC_LINES:
+               return  "SET_NUM_VSYNC_LINES";
+       case CX2341X_ENC_SET_PLACEHOLDER:
+               return  "SET_PLACEHOLDER";
+       case CX2341X_ENC_MUTE_VIDEO:
+               return  "MUTE_VIDEO";
+       case CX2341X_ENC_MUTE_AUDIO:
+               return  "MUTE_AUDIO";
+       case CX2341X_ENC_MISC:
+               return  "MISC";
+       default:
+               return "UNKNOWN";
+       }
+}
+
+static int cx231xx_mbox_func(void *priv,
+                            u32 command,
+                            int in,
+                            int out,
+                            u32 data[CX2341X_MBOX_MAX_DATA])
+{
+       struct cx231xx *dev = priv;
+       unsigned long timeout;
+       u32 value, flag, retval = 0;
+       int i;
+
+       dprintk(3, "%s: command(0x%X) = %s\n", __func__, command,
+               cmd_to_str(command));
+
+       /* this may not be 100% safe if we can't read any memory location
+          without side effects */
+       mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);
+       if (value != 0x12345678) {
+               dprintk(3,
+                       "Firmware and/or mailbox pointer not initialized "
+                       "or corrupted, signature = 0x%x, cmd = %s\n", value,
+                       cmd_to_str(command));
+               return -1;
+       }
+
+       /* This read looks at 32 bits, but flag is only 8 bits.
+        * Seems we also bail if CMD or TIMEOUT bytes are set???
+        */
+       mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
+       if (flag) {
+               dprintk(3, "ERROR: Mailbox appears to be in use "
+                       "(%x), cmd = %s\n", flag, cmd_to_str(command));
+               return -1;
+       }
+
+       flag |= 1; /* tell 'em we're working on it */
+       mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+       /* write command + args + fill remaining with zeros */
+       /* command code */
+       mc417_memory_write(dev, dev->cx23417_mailbox + 1, command);
+       mc417_memory_write(dev, dev->cx23417_mailbox + 3,
+               IVTV_API_STD_TIMEOUT); /* timeout */
+       for (i = 0; i < in; i++) {
+               mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]);
+               dprintk(3, "API Input %d = %d\n", i, data[i]);
+       }
+       for (; i < CX2341X_MBOX_MAX_DATA; i++)
+               mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0);
+
+       flag |= 3; /* tell 'em we're done writing */
+       mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+       /* wait for firmware to handle the API command */
+       timeout = jiffies + msecs_to_jiffies(10);
+       for (;;) {
+               mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
+               if (0 != (flag & 4))
+                       break;
+               if (time_after(jiffies, timeout)) {
+                       dprintk(3, "ERROR: API Mailbox timeout\n");
+                       return -1;
+               }
+               udelay(10);
+       }
+
+       /* read output values */
+       for (i = 0; i < out; i++) {
+               mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i);
+               dprintk(3, "API Output %d = %d\n", i, data[i]);
+       }
+
+       mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval);
+       dprintk(3, "API result = %d\n", retval);
+
+       flag = 0;
+       mc417_memory_write(dev, dev->cx23417_mailbox, flag);
+
+       return retval;
+}
+
+/* We don't need to call the API often, so using just one
+ * mailbox will probably suffice
+ */
+static int cx231xx_api_cmd(struct cx231xx *dev,
+                          u32 command,
+                          u32 inputcnt,
+                          u32 outputcnt,
+                          ...)
+{
+       u32 data[CX2341X_MBOX_MAX_DATA];
+       va_list vargs;
+       int i, err;
+
+       dprintk(3, "%s() cmds = 0x%08x\n", __func__, command);
+
+       va_start(vargs, outputcnt);
+       for (i = 0; i < inputcnt; i++)
+               data[i] = va_arg(vargs, int);
+
+       err = cx231xx_mbox_func(dev, command, inputcnt, outputcnt, data);
+       for (i = 0; i < outputcnt; i++) {
+               int *vptr = va_arg(vargs, int *);
+               *vptr = data[i];
+       }
+       va_end(vargs);
+
+       return err;
+}
+
+static int cx231xx_find_mailbox(struct cx231xx *dev)
+{
+       u32 signature[4] = {
+               0x12345678, 0x34567812, 0x56781234, 0x78123456
+       };
+       int signaturecnt = 0;
+       u32 value;
+       int i;
+       int ret = 0;
+
+       dprintk(2, "%s()\n", __func__);
+
+       for (i = 0; i < 0x100; i++) {/*CX231xx_FIRM_IMAGE_SIZE*/
+               ret = mc417_memory_read(dev, i, &value);
+               if (ret < 0)
+                       return ret;
+               if (value == signature[signaturecnt])
+                       signaturecnt++;
+               else
+                       signaturecnt = 0;
+               if (4 == signaturecnt) {
+                       dprintk(1, "Mailbox signature found at 0x%x\n", i+1);
+                       return i+1;
+               }
+       }
+       dprintk(3, "Mailbox signature values not found!\n");
+       return -1;
+}
+
+static void mciWriteMemoryToGPIO(struct cx231xx *dev, u32 address, u32 value,
+               u32 *p_fw_image)
+{
+
+       u32 temp = 0;
+       int i = 0;
+
+       temp = 0x82|MCI_MEMORY_DATA_BYTE0|((value&0x000000FF)<<8);
+       temp = temp<<10;
+       *p_fw_image = temp;
+       p_fw_image++;
+       temp = temp|((0x05)<<10);
+       *p_fw_image = temp;
+       p_fw_image++;
+
+       /*write data byte 1;*/
+       temp = 0x82|MCI_MEMORY_DATA_BYTE1|(value&0x0000FF00);
+       temp = temp<<10;
+       *p_fw_image = temp;
+       p_fw_image++;
+       temp = temp|((0x05)<<10);
+       *p_fw_image = temp;
+       p_fw_image++;
+
+       /*write data byte 2;*/
+       temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8);
+       temp = temp<<10;
+       *p_fw_image = temp;
+       p_fw_image++;
+       temp = temp|((0x05)<<10);
+       *p_fw_image = temp;
+       p_fw_image++;
+
+       /*write data byte 3;*/
+       temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16);
+       temp = temp<<10;
+       *p_fw_image = temp;
+       p_fw_image++;
+       temp = temp|((0x05)<<10);
+       *p_fw_image = temp;
+       p_fw_image++;
+
+       /* write address byte 2;*/
+       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE |
+               ((address & 0x003F0000)>>8);
+       temp = temp<<10;
+       *p_fw_image = temp;
+       p_fw_image++;
+       temp = temp|((0x05)<<10);
+       *p_fw_image = temp;
+       p_fw_image++;
+
+       /* write address byte 1;*/
+       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
+       temp = temp<<10;
+       *p_fw_image = temp;
+       p_fw_image++;
+       temp = temp|((0x05)<<10);
+       *p_fw_image = temp;
+       p_fw_image++;
+
+       /* write address byte 0;*/
+       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8);
+       temp = temp<<10;
+       *p_fw_image = temp;
+       p_fw_image++;
+       temp = temp|((0x05)<<10);
+       *p_fw_image = temp;
+       p_fw_image++;
+
+       for (i = 0; i < 6; i++) {
+               *p_fw_image = 0xFFFFFFFF;
+               p_fw_image++;
+       }
+}
+
+
+static int cx231xx_load_firmware(struct cx231xx *dev)
+{
+       static const unsigned char magic[8] = {
+               0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
+       };
+       const struct firmware *firmware;
+       int i, retval = 0;
+       u32 value = 0;
+       u32 gpio_output = 0;
+       /*u32 checksum = 0;*/
+       /*u32 *dataptr;*/
+       u32 transfer_size = 0;
+       u32 fw_data = 0;
+       u32 address = 0;
+       /*u32 current_fw[800];*/
+       u32 *p_current_fw, *p_fw;
+       u32 *p_fw_data;
+       int frame = 0;
+       u16 _buffer_size = 4096;
+       u8 *p_buffer;
+
+       p_current_fw = vmalloc(1884180 * 4);
+       p_fw = p_current_fw;
+       if (p_current_fw == NULL) {
+               dprintk(2, "FAIL!!!\n");
+               return -1;
+       }
+
+       p_buffer = vmalloc(4096);
+       if (p_buffer == NULL) {
+               dprintk(2, "FAIL!!!\n");
+               return -1;
+       }
+
+       dprintk(2, "%s()\n", __func__);
+
+       /* Save GPIO settings before reset of APU */
+       retval |= mc417_memory_read(dev, 0x9020, &gpio_output);
+       retval |= mc417_memory_read(dev, 0x900C, &value);
+
+       retval  = mc417_register_write(dev,
+               IVTV_REG_VPU, 0xFFFFFFED);
+       retval |= mc417_register_write(dev,
+               IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
+       retval |= mc417_register_write(dev,
+               IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800);
+       retval |= mc417_register_write(dev,
+               IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
+       retval |= mc417_register_write(dev,
+               IVTV_REG_APU, 0);
+
+       if (retval != 0) {
+               printk(KERN_ERR "%s: Error with mc417_register_write\n",
+                       __func__);
+               return -1;
+       }
+
+       retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME,
+                                 &dev->udev->dev);
+
+       if (retval != 0) {
+               printk(KERN_ERR
+                       "ERROR: Hotplug firmware request failed (%s).\n",
+                       CX231xx_FIRM_IMAGE_NAME);
+               printk(KERN_ERR "Please fix your hotplug setup, the board will "
+                       "not work without firmware loaded!\n");
+               return -1;
+       }
+
+       if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) {
+               printk(KERN_ERR "ERROR: Firmware size mismatch "
+                       "(have %zd, expected %d)\n",
+                       firmware->size, CX231xx_FIRM_IMAGE_SIZE);
+               release_firmware(firmware);
+               return -1;
+       }
+
+       if (0 != memcmp(firmware->data, magic, 8)) {
+               printk(KERN_ERR
+                       "ERROR: Firmware magic mismatch, wrong file?\n");
+               release_firmware(firmware);
+               return -1;
+       }
+
+       initGPIO(dev);
+
+       /* transfer to the chip */
+       dprintk(2, "Loading firmware to GPIO...\n");
+       p_fw_data = (u32 *)firmware->data;
+       dprintk(2, "firmware->size=%zd\n", firmware->size);
+       for (transfer_size = 0; transfer_size < firmware->size;
+                transfer_size += 4) {
+               fw_data = *p_fw_data;
+
+                mciWriteMemoryToGPIO(dev, address, fw_data, p_current_fw);
+               address = address + 1;
+               p_current_fw += 20;
+               p_fw_data += 1;
+       }
+
+       /*download the firmware by ep5-out*/
+
+       for (frame = 0; frame < (int)(CX231xx_FIRM_IMAGE_SIZE*20/_buffer_size);
+            frame++) {
+               for (i = 0; i < _buffer_size; i++) {
+                       *(p_buffer + i) = (u8)(*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x000000FF);
+                       i++;
+                       *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x0000FF00) >> 8);
+                       i++;
+                       *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x00FF0000) >> 16);
+                       i++;
+                       *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0xFF000000) >> 24);
+               }
+               cx231xx_ep5_bulkout(dev, p_buffer, _buffer_size);
+       }
+
+       p_current_fw = p_fw;
+       vfree(p_current_fw);
+       p_current_fw = NULL;
+       uninitGPIO(dev);
+       release_firmware(firmware);
+       dprintk(1, "Firmware upload successful.\n");
+
+       retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,
+               IVTV_CMD_HW_BLOCKS_RST);
+       if (retval < 0) {
+               printk(KERN_ERR "%s: Error with mc417_register_write\n",
+                       __func__);
+               return retval;
+       }
+       /* F/W power up disturbs the GPIOs, restore state */
+       retval |= mc417_register_write(dev, 0x9020, gpio_output);
+       retval |= mc417_register_write(dev, 0x900C, value);
+
+       retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
+       retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
+
+       if (retval < 0) {
+               printk(KERN_ERR "%s: Error with mc417_register_write\n",
+                       __func__);
+               return retval;
+       }
+       return 0;
+}
+
+static void cx231xx_417_check_encoder(struct cx231xx *dev)
+{
+       u32 status, seq;
+
+       status = 0;
+       seq = 0;
+       cx231xx_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq);
+       dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);
+}
+
+static void cx231xx_codec_settings(struct cx231xx *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+
+       /* assign frame size */
+       cx231xx_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
+                               dev->ts1.height, dev->ts1.width);
+
+       dev->mpeg_params.width = dev->ts1.width;
+       dev->mpeg_params.height = dev->ts1.height;
+
+       cx2341x_update(dev, cx231xx_mbox_func, NULL, &dev->mpeg_params);
+
+       cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);
+       cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
+}
+
+static int cx231xx_initialize_codec(struct cx231xx *dev)
+{
+       int version;
+       int retval;
+       u32 i;
+       u32 val = 0;
+
+       dprintk(1, "%s()\n", __func__);
+       cx231xx_disable656(dev);
+       retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
+       if (retval < 0) {
+               dprintk(2, "%s() PING OK\n", __func__);
+               retval = cx231xx_load_firmware(dev);
+               if (retval < 0) {
+                       printk(KERN_ERR "%s() f/w load failed\n", __func__);
+                       return retval;
+               }
+               retval = cx231xx_find_mailbox(dev);
+               if (retval < 0) {
+                       printk(KERN_ERR "%s() mailbox < 0, error\n",
+                               __func__);
+                       return -1;
+               }
+               dev->cx23417_mailbox = retval;
+               retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
+               if (retval < 0) {
+                       printk(KERN_ERR
+                               "ERROR: cx23417 firmware ping failed!\n");
+                       return -1;
+               }
+               retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
+                       &version);
+               if (retval < 0) {
+                       printk(KERN_ERR "ERROR: cx23417 firmware get encoder :"
+                               "version failed!\n");
+                       return -1;
+               }
+               dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
+               msleep(200);
+       }
+
+       for (i = 0; i < 1; i++) {
+               retval = mc417_register_read(dev, 0x20f8, &val);
+               dprintk(3, "***before enable656() VIM Capture Lines =%d ***\n",
+                                val);
+               if (retval < 0)
+                       return retval;
+       }
+
+       cx231xx_enable656(dev);
+                       /* stop mpeg capture */
+                       cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE,
+                                3, 0, 1, 3, 4);
+
+       cx231xx_codec_settings(dev);
+       msleep(60);
+
+/*     cx231xx_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
+               CX231xx_FIELD1_SAA7115, CX231xx_FIELD2_SAA7115);
+       cx231xx_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
+               CX231xx_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0);
+*/
+
+#if 0
+       /* TODO */
+       u32 data[7];
+
+       /* Setup to capture VBI */
+       data[0] = 0x0001BD00;
+       data[1] = 1;          /* frames per interrupt */
+       data[2] = 4;          /* total bufs */
+       data[3] = 0x91559155; /* start codes */
+       data[4] = 0x206080C0; /* stop codes */
+       data[5] = 6;          /* lines */
+       data[6] = 64;         /* BPL */
+
+       cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1],
+               data[2], data[3], data[4], data[5], data[6]);
+
+       for (i = 2; i <= 24; i++) {
+               int valid;
+
+               valid = ((i >= 19) && (i <= 21));
+               cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i,
+                               valid, 0 , 0, 0);
+               cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0,
+                               i | 0x80000000, valid, 0, 0, 0);
+       }
+#endif
+/*     cx231xx_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX231xx_UNMUTE);
+       msleep(60);
+*/
+       /* initialize the video input */
+       retval = cx231xx_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
+       if (retval < 0)
+               return retval;
+       msleep(60);
+
+       /* Enable VIP style pixel invalidation so we work with scaled mode */
+       mc417_memory_write(dev, 2120, 0x00000080);
+
+       /* start capturing to the host interface */
+       retval = cx231xx_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
+               CX231xx_MPEG_CAPTURE, CX231xx_RAW_BITS_NONE);
+       if (retval < 0)
+               return retval;
+       msleep(10);
+
+       for (i = 0; i < 1; i++) {
+               mc417_register_read(dev, 0x20f8, &val);
+       dprintk(3, "***VIM Capture Lines =%d ***\n", val);
+       }
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int bb_buf_setup(struct videobuf_queue *q,
+       unsigned int *count, unsigned int *size)
+{
+       struct cx231xx_fh *fh = q->priv_data;
+
+       fh->dev->ts1.ts_packet_size  = mpeglinesize;
+       fh->dev->ts1.ts_packet_count = mpeglines;
+
+       *size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
+       *count = mpegbufs;
+
+       return 0;
+}
+static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
+{
+       struct cx231xx_fh *fh = vq->priv_data;
+       struct cx231xx *dev = fh->dev;
+       unsigned long flags = 0;
+
+       if (in_interrupt())
+               BUG();
+
+       spin_lock_irqsave(&dev->video_mode.slock, flags);
+       if (dev->USE_ISO) {
+               if (dev->video_mode.isoc_ctl.buf == buf)
+                       dev->video_mode.isoc_ctl.buf = NULL;
+       } else {
+               if (dev->video_mode.bulk_ctl.buf == buf)
+                       dev->video_mode.bulk_ctl.buf = NULL;
+       }
+       spin_unlock_irqrestore(&dev->video_mode.slock, flags);
+       videobuf_waiton(vq, &buf->vb, 0, 0);
+       videobuf_vmalloc_free(&buf->vb);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *urb,
+               struct cx231xx_dmaqueue *dma_q)
+{
+               void *vbuf;
+               struct cx231xx_buffer *buf;
+               u32 tail_data = 0;
+               char *p_data;
+
+               if (dma_q->mpeg_buffer_done == 0) {
+                       if (list_empty(&dma_q->active))
+                               return;
+
+                       buf = list_entry(dma_q->active.next,
+                                       struct cx231xx_buffer, vb.queue);
+                       dev->video_mode.isoc_ctl.buf = buf;
+                       dma_q->mpeg_buffer_done = 1;
+               }
+               /* Fill buffer */
+               buf = dev->video_mode.isoc_ctl.buf;
+               vbuf = videobuf_to_vmalloc(&buf->vb);
+
+               if ((dma_q->mpeg_buffer_completed+len) <
+                  mpeglines*mpeglinesize) {
+                       if (dma_q->add_ps_package_head ==
+                          CX231XX_NEED_ADD_PS_PACKAGE_HEAD) {
+                               memcpy(vbuf+dma_q->mpeg_buffer_completed,
+                                      dma_q->ps_head, 3);
+                               dma_q->mpeg_buffer_completed =
+                                 dma_q->mpeg_buffer_completed + 3;
+                               dma_q->add_ps_package_head =
+                                 CX231XX_NONEED_PS_PACKAGE_HEAD;
+                       }
+                       memcpy(vbuf+dma_q->mpeg_buffer_completed, data, len);
+                       dma_q->mpeg_buffer_completed =
+                         dma_q->mpeg_buffer_completed + len;
+               } else {
+                       dma_q->mpeg_buffer_done = 0;
+
+                       tail_data =
+                         mpeglines*mpeglinesize - dma_q->mpeg_buffer_completed;
+                       memcpy(vbuf+dma_q->mpeg_buffer_completed,
+                              data, tail_data);
+
+                       buf->vb.state = VIDEOBUF_DONE;
+                       buf->vb.field_count++;
+                       do_gettimeofday(&buf->vb.ts);
+                       list_del(&buf->vb.queue);
+                       wake_up(&buf->vb.done);
+                       dma_q->mpeg_buffer_completed = 0;
+
+                       if (len - tail_data > 0) {
+                               p_data = data + tail_data;
+                               dma_q->left_data_count = len - tail_data;
+                               memcpy(dma_q->p_left_data,
+                                      p_data, len - tail_data);
+                       }
+
+               }
+
+           return;
+}
+
+static void buffer_filled(char *data, int len, struct urb *urb,
+               struct cx231xx_dmaqueue *dma_q)
+{
+               void *vbuf;
+               struct cx231xx_buffer *buf;
+
+               if (list_empty(&dma_q->active))
+                       return;
+
+
+               buf = list_entry(dma_q->active.next,
+                                struct cx231xx_buffer, vb.queue);
+
+
+               /* Fill buffer */
+               vbuf = videobuf_to_vmalloc(&buf->vb);
+               memcpy(vbuf, data, len);
+               buf->vb.state = VIDEOBUF_DONE;
+               buf->vb.field_count++;
+               do_gettimeofday(&buf->vb.ts);
+               list_del(&buf->vb.queue);
+               wake_up(&buf->vb.done);
+
+           return;
+}
+static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
+{
+       struct cx231xx_dmaqueue *dma_q = urb->context;
+       unsigned char *p_buffer;
+       u32 buffer_size = 0;
+       u32 i = 0;
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               if (dma_q->left_data_count > 0) {
+                       buffer_copy(dev, dma_q->p_left_data,
+                                   dma_q->left_data_count, urb, dma_q);
+                       dma_q->mpeg_buffer_completed = dma_q->left_data_count;
+                       dma_q->left_data_count = 0;
+               }
+
+               p_buffer = urb->transfer_buffer +
+                               urb->iso_frame_desc[i].offset;
+               buffer_size = urb->iso_frame_desc[i].actual_length;
+
+               if (buffer_size > 0)
+                       buffer_copy(dev, p_buffer, buffer_size, urb, dma_q);
+       }
+
+       return 0;
+}
+static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
+{
+
+       /*char *outp;*/
+       /*struct cx231xx_buffer *buf;*/
+       struct cx231xx_dmaqueue *dma_q = urb->context;
+       unsigned char *p_buffer, *buffer;
+       u32 buffer_size = 0;
+
+       p_buffer = urb->transfer_buffer;
+       buffer_size = urb->actual_length;
+
+       buffer = kmalloc(buffer_size, GFP_ATOMIC);
+
+       memcpy(buffer, dma_q->ps_head, 3);
+       memcpy(buffer+3, p_buffer, buffer_size-3);
+       memcpy(dma_q->ps_head, p_buffer+buffer_size-3, 3);
+
+       p_buffer = buffer;
+       buffer_filled(p_buffer, buffer_size, urb, dma_q);
+
+       kfree(buffer);
+       return 0;
+}
+
+static int bb_buf_prepare(struct videobuf_queue *q,
+       struct videobuf_buffer *vb, enum v4l2_field field)
+{
+       struct cx231xx_fh *fh = q->priv_data;
+       struct cx231xx_buffer *buf =
+           container_of(vb, struct cx231xx_buffer, vb);
+       struct cx231xx *dev = fh->dev;
+       int rc = 0, urb_init = 0;
+       int size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
+
+       dma_qq = &dev->video_mode.vidq;
+
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
+               return -EINVAL;
+       buf->vb.width = fh->dev->ts1.ts_packet_size;
+       buf->vb.height = fh->dev->ts1.ts_packet_count;
+       buf->vb.size = size;
+       buf->vb.field = field;
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               rc = videobuf_iolock(q, &buf->vb, NULL);
+               if (rc < 0)
+                       goto fail;
+       }
+
+       if (dev->USE_ISO) {
+               if (!dev->video_mode.isoc_ctl.num_bufs)
+                       urb_init = 1;
+       } else {
+               if (!dev->video_mode.bulk_ctl.num_bufs)
+                       urb_init = 1;
+       }
+       /*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n",
+               urb_init, dev->video_mode.max_pkt_size);*/
+       dev->mode_tv = 1;
+
+       if (urb_init) {
+               rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
+               rc = cx231xx_unmute_audio(dev);
+               if (dev->USE_ISO) {
+                       cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
+                       rc = cx231xx_init_isoc(dev, mpeglines,
+                                      mpegbufs,
+                                      dev->ts1_mode.max_pkt_size,
+                                      cx231xx_isoc_copy);
+               } else {
+                       cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
+                       rc = cx231xx_init_bulk(dev, mpeglines,
+                                      mpegbufs,
+                                      dev->ts1_mode.max_pkt_size,
+                                      cx231xx_bulk_copy);
+               }
+               if (rc < 0)
+                       goto fail;
+       }
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+fail:
+       free_buffer(q, buf);
+       return rc;
+}
+
+static void bb_buf_queue(struct videobuf_queue *q,
+       struct videobuf_buffer *vb)
+{
+       struct cx231xx_fh *fh = q->priv_data;
+
+       struct cx231xx_buffer *buf =
+           container_of(vb, struct cx231xx_buffer, vb);
+       struct cx231xx *dev = fh->dev;
+       struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
+
+       buf->vb.state = VIDEOBUF_QUEUED;
+       list_add_tail(&buf->vb.queue, &vidq->active);
+
+}
+
+static void bb_buf_release(struct videobuf_queue *q,
+       struct videobuf_buffer *vb)
+{
+       struct cx231xx_buffer *buf =
+           container_of(vb, struct cx231xx_buffer, vb);
+       /*struct cx231xx_fh *fh = q->priv_data;*/
+       /*struct cx231xx *dev = (struct cx231xx *)fh->dev;*/
+
+       free_buffer(q, buf);
+}
+
+static struct videobuf_queue_ops cx231xx_qops = {
+       .buf_setup    = bb_buf_setup,
+       .buf_prepare  = bb_buf_prepare,
+       .buf_queue    = bb_buf_queue,
+       .buf_release  = bb_buf_release,
+};
+
+/* ------------------------------------------------------------------ */
+
+static const u32 *ctrl_classes[] = {
+       cx2341x_mpeg_ctrls,
+       NULL
+};
+
+static int cx231xx_queryctrl(struct cx231xx *dev,
+       struct v4l2_queryctrl *qctrl)
+{
+       qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
+       if (qctrl->id == 0)
+               return -EINVAL;
+
+       /* MPEG V4L2 controls */
+       if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl))
+               qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
+
+       return 0;
+}
+
+static int cx231xx_querymenu(struct cx231xx *dev,
+       struct v4l2_querymenu *qmenu)
+{
+       struct v4l2_queryctrl qctrl;
+
+       qctrl.id = qmenu->id;
+       cx231xx_queryctrl(dev, &qctrl);
+       return v4l2_ctrl_query_menu(qmenu, &qctrl,
+               cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id));
+}
+
+static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm)
+{
+       struct cx231xx_fh  *fh  = file->private_data;
+       struct cx231xx *dev = fh->dev;
+
+       *norm = dev->encodernorm.id;
+       return 0;
+}
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct cx231xx_fh  *fh  = file->private_data;
+       struct cx231xx *dev = fh->dev;
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(cx231xx_tvnorms); i++)
+               if (*id & cx231xx_tvnorms[i].id)
+                       break;
+       if (i == ARRAY_SIZE(cx231xx_tvnorms))
+               return -EINVAL;
+       dev->encodernorm = cx231xx_tvnorms[i];
+
+       if (dev->encodernorm.id & 0xb000) {
+               dprintk(3, "encodernorm set to NTSC\n");
+               dev->norm = V4L2_STD_NTSC;
+               dev->ts1.height = 480;
+               dev->mpeg_params.is_50hz = 0;
+       } else {
+               dprintk(3, "encodernorm set to PAL\n");
+               dev->norm = V4L2_STD_PAL_B;
+               dev->ts1.height = 576;
+               dev->mpeg_params.is_50hz = 1;
+       }
+       call_all(dev, core, s_std, dev->norm);
+       /* do mode control overrides */
+       cx231xx_do_mode_ctrl_overrides(dev);
+
+       dprintk(3, "exit vidioc_s_std() i=0x%x\n", i);
+       return 0;
+}
+static int vidioc_g_audio(struct file *file, void *fh,
+                                       struct v4l2_audio *a)
+{
+               struct v4l2_audio *vin = a;
+
+               int ret = -EINVAL;
+               if (vin->index > 0)
+                       return ret;
+               strncpy(vin->name, "VideoGrabber Audio", 14);
+               vin->capability = V4L2_AUDCAP_STEREO;
+return 0;
+}
+static int vidioc_enumaudio(struct file *file, void *fh,
+                                       struct v4l2_audio *a)
+{
+               struct v4l2_audio *vin = a;
+
+               int ret = -EINVAL;
+
+               if (vin->index > 0)
+                       return ret;
+               strncpy(vin->name, "VideoGrabber Audio", 14);
+               vin->capability = V4L2_AUDCAP_STEREO;
+
+
+return 0;
+}
+static const char *iname[] = {
+       [CX231XX_VMUX_COMPOSITE1] = "Composite1",
+       [CX231XX_VMUX_SVIDEO]     = "S-Video",
+       [CX231XX_VMUX_TELEVISION] = "Television",
+       [CX231XX_VMUX_CABLE]      = "Cable TV",
+       [CX231XX_VMUX_DVB]        = "DVB",
+       [CX231XX_VMUX_DEBUG]      = "for debug only",
+};
+static int vidioc_enum_input(struct file *file, void *priv,
+                               struct v4l2_input *i)
+{
+       struct cx231xx_fh  *fh  = file->private_data;
+       struct cx231xx *dev = fh->dev;
+       struct cx231xx_input *input;
+       int n;
+       dprintk(3, "enter vidioc_enum_input()i->index=%d\n", i->index);
+
+       if (i->index >= 4)
+               return -EINVAL;
+
+
+       input = &cx231xx_boards[dev->model].input[i->index];
+
+       if (input->type == 0)
+               return -EINVAL;
+
+       /* FIXME
+        * strcpy(i->name, input->name); */
+
+       n = i->index;
+       strcpy(i->name, iname[INPUT(n)->type]);
+
+       if (input->type == CX231XX_VMUX_TELEVISION ||
+           input->type == CX231XX_VMUX_CABLE)
+               i->type = V4L2_INPUT_TYPE_TUNER;
+       else
+               i->type  = V4L2_INPUT_TYPE_CAMERA;
+
+
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       *i = 0;
+       return  0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       struct cx231xx_fh  *fh  = file->private_data;
+       struct cx231xx *dev = fh->dev;
+
+       dprintk(3, "enter vidioc_s_input() i=%d\n", i);
+
+       mutex_lock(&dev->lock);
+
+       video_mux(dev, i);
+
+       mutex_unlock(&dev->lock);
+
+       if (i >= 4)
+               return -EINVAL;
+       dev->input = i;
+       dprintk(3, "exit vidioc_s_input()\n");
+       return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+
+
+       return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctl)
+{
+       struct cx231xx_fh  *fh  = file->private_data;
+       struct cx231xx *dev = fh->dev;
+       dprintk(3, "enter vidioc_s_ctrl()\n");
+       /* Update the A/V core */
+       call_all(dev, core, s_ctrl, ctl);
+       dprintk(3, "exit vidioc_s_ctrl()\n");
+       return 0;
+}
+static struct v4l2_capability pvr_capability = {
+       .driver         = "cx231xx",
+       .card           = "VideoGrabber",
+       .bus_info       = "usb",
+       .version        = 1,
+       .capabilities   = (V4L2_CAP_VIDEO_CAPTURE |
+                          V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
+                        V4L2_CAP_STREAMING | V4L2_CAP_READWRITE),
+};
+static int vidioc_querycap(struct file *file, void  *priv,
+                               struct v4l2_capability *cap)
+{
+
+
+
+               memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+
+       if (f->index != 0)
+               return -EINVAL;
+
+       strlcpy(f->description, "MPEG", sizeof(f->description));
+       f->pixelformat = V4L2_PIX_FMT_MPEG;
+
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct cx231xx_fh  *fh  = file->private_data;
+       struct cx231xx *dev = fh->dev;
+       dprintk(3, "enter vidioc_g_fmt_vid_cap()\n");
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage    =
+               dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
+       f->fmt.pix.colorspace   = 0;
+       f->fmt.pix.width        = dev->ts1.width;
+       f->fmt.pix.height       = dev->ts1.height;
+       f->fmt.pix.field        = fh->vidq.field;
+       dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
+               dev->ts1.width, dev->ts1.height, fh->vidq.field);
+       dprintk(3, "exit vidioc_g_fmt_vid_cap()\n");
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct cx231xx_fh  *fh  = file->private_data;
+       struct cx231xx *dev = fh->dev;
+       dprintk(3, "enter vidioc_try_fmt_vid_cap()\n");
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.sizeimage    =
+               dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
+       f->fmt.pix.colorspace   = 0;
+       dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
+               dev->ts1.width, dev->ts1.height, fh->vidq.field);
+       dprintk(3, "exit vidioc_try_fmt_vid_cap()\n");
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+
+       return 0;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                               struct v4l2_requestbuffers *p)
+{
+       struct cx231xx_fh  *fh  = file->private_data;
+
+       return videobuf_reqbufs(&fh->vidq, p);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+                               struct v4l2_buffer *p)
+{
+       struct cx231xx_fh  *fh  = file->private_data;
+
+       return videobuf_querybuf(&fh->vidq, p);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv,
+                               struct v4l2_buffer *p)
+{
+       struct cx231xx_fh  *fh  = file->private_data;
+
+       return videobuf_qbuf(&fh->vidq, p);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct cx231xx_fh  *fh  = priv;
+
+       return videobuf_dqbuf(&fh->vidq, b, file->f_flags & O_NONBLOCK);
+}
+
+
+static int vidioc_streamon(struct file *file, void *priv,
+                               enum v4l2_buf_type i)
+{
+       struct cx231xx_fh  *fh  = file->private_data;
+
+       struct cx231xx *dev = fh->dev;
+       dprintk(3, "enter vidioc_streamon()\n");
+               cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
+               cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
+               if (dev->USE_ISO)
+                       cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
+                                      CX231XX_NUM_BUFS,
+                                      dev->video_mode.max_pkt_size,
+                                      cx231xx_isoc_copy);
+               else {
+                       cx231xx_init_bulk(dev, 320,
+                                      5,
+                                      dev->ts1_mode.max_pkt_size,
+                                      cx231xx_bulk_copy);
+               }
+       dprintk(3, "exit vidioc_streamon()\n");
+       return videobuf_streamon(&fh->vidq);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct cx231xx_fh  *fh  = file->private_data;
+
+       return videobuf_streamoff(&fh->vidq);
+}
+
+static int vidioc_g_ext_ctrls(struct file *file, void *priv,
+                               struct v4l2_ext_controls *f)
+{
+       struct cx231xx_fh  *fh  = priv;
+       struct cx231xx *dev = fh->dev;
+       dprintk(3, "enter vidioc_g_ext_ctrls()\n");
+       if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+       dprintk(3, "exit vidioc_g_ext_ctrls()\n");
+       return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS);
+}
+
+static int vidioc_s_ext_ctrls(struct file *file, void *priv,
+                               struct v4l2_ext_controls *f)
+{
+       struct cx231xx_fh  *fh  = priv;
+       struct cx231xx *dev = fh->dev;
+       struct cx2341x_mpeg_params p;
+       int err;
+       dprintk(3, "enter vidioc_s_ext_ctrls()\n");
+       if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+
+       p = dev->mpeg_params;
+       err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
+       if (err == 0) {
+               err = cx2341x_update(dev, cx231xx_mbox_func,
+                       &dev->mpeg_params, &p);
+               dev->mpeg_params = p;
+       }
+
+       return err;
+
+
+return 0;
+}
+
+static int vidioc_try_ext_ctrls(struct file *file, void *priv,
+                               struct v4l2_ext_controls *f)
+{
+       struct cx231xx_fh  *fh  = priv;
+       struct cx231xx *dev = fh->dev;
+       struct cx2341x_mpeg_params p;
+       int err;
+       dprintk(3, "enter vidioc_try_ext_ctrls()\n");
+       if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+               return -EINVAL;
+
+       p = dev->mpeg_params;
+       err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
+       dprintk(3, "exit vidioc_try_ext_ctrls() err=%d\n", err);
+       return err;
+}
+
+static int vidioc_log_status(struct file *file, void *priv)
+{
+       struct cx231xx_fh  *fh  = priv;
+       struct cx231xx *dev = fh->dev;
+       char name[32 + 2];
+
+       snprintf(name, sizeof(name), "%s/2", dev->name);
+       dprintk(3,
+               "%s/2: ============  START LOG STATUS  ============\n",
+              dev->name);
+       call_all(dev, core, log_status);
+       cx2341x_log_status(&dev->mpeg_params, name);
+       dprintk(3,
+               "%s/2: =============  END LOG STATUS  =============\n",
+              dev->name);
+       return 0;
+}
+
+static int vidioc_querymenu(struct file *file, void *priv,
+                               struct v4l2_querymenu *a)
+{
+       struct cx231xx_fh  *fh  = priv;
+       struct cx231xx *dev = fh->dev;
+       dprintk(3, "enter vidioc_querymenu()\n");
+       dprintk(3, "exit vidioc_querymenu()\n");
+       return cx231xx_querymenu(dev, a);
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+                               struct v4l2_queryctrl *c)
+{
+       struct cx231xx_fh  *fh  = priv;
+       struct cx231xx *dev = fh->dev;
+       dprintk(3, "enter vidioc_queryctrl()\n");
+       dprintk(3, "exit vidioc_queryctrl()\n");
+       return cx231xx_queryctrl(dev, c);
+}
+
+static int mpeg_open(struct file *file)
+{
+       int minor = video_devdata(file)->minor;
+       struct cx231xx *h, *dev = NULL;
+       /*struct list_head *list;*/
+       struct cx231xx_fh *fh;
+       /*u32 value = 0;*/
+
+       dprintk(2, "%s()\n", __func__);
+
+       list_for_each_entry(h, &cx231xx_devlist, devlist) {
+               if (h->v4l_device->minor == minor)
+                       dev = h;
+       }
+
+       if (dev == NULL)
+               return -ENODEV;
+
+       mutex_lock(&dev->lock);
+
+       /* allocate + initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+       if (NULL == fh) {
+               mutex_unlock(&dev->lock);
+               return -ENOMEM;
+       }
+
+       file->private_data = fh;
+       fh->dev      = dev;
+
+
+       videobuf_queue_vmalloc_init(&fh->vidq, &cx231xx_qops,
+                           NULL, &dev->video_mode.slock,
+                           V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED,
+                           sizeof(struct cx231xx_buffer), fh, NULL);
+/*
+       videobuf_queue_sg_init(&fh->vidq, &cx231xx_qops,
+                           &dev->udev->dev, &dev->ts1.slock,
+                           V4L2_BUF_TYPE_VIDEO_CAPTURE,
+                           V4L2_FIELD_INTERLACED,
+                           sizeof(struct cx231xx_buffer),
+                           fh, NULL);
+*/
+
+
+       cx231xx_set_alt_setting(dev, INDEX_VANC, 1);
+       cx231xx_set_gpio_value(dev, 2, 0);
+
+       cx231xx_initialize_codec(dev);
+
+       mutex_unlock(&dev->lock);
+       cx231xx_start_TS1(dev);
+
+       return 0;
+}
+
+static int mpeg_release(struct file *file)
+{
+       struct cx231xx_fh  *fh  = file->private_data;
+       struct cx231xx *dev = fh->dev;
+
+       dprintk(3, "mpeg_release()! dev=0x%p\n", dev);
+
+       if (!dev) {
+               dprintk(3, "abort!!!\n");
+               return 0;
+       }
+
+       mutex_lock(&dev->lock);
+
+       cx231xx_stop_TS1(dev);
+
+               /* do this before setting alternate! */
+               if (dev->USE_ISO)
+                       cx231xx_uninit_isoc(dev);
+               else
+                       cx231xx_uninit_bulk(dev);
+               cx231xx_set_mode(dev, CX231XX_SUSPEND);
+
+               cx231xx_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+                               CX231xx_END_NOW, CX231xx_MPEG_CAPTURE,
+                               CX231xx_RAW_BITS_NONE);
+
+       /* FIXME: Review this crap */
+       /* Shut device down on last close */
+       if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
+               if (atomic_dec_return(&dev->v4l_reader_count) == 0) {
+                       /* stop mpeg capture */
+
+                       msleep(500);
+                       cx231xx_417_check_encoder(dev);
+
+               }
+       }
+
+       if (fh->vidq.streaming)
+               videobuf_streamoff(&fh->vidq);
+       if (fh->vidq.reading)
+               videobuf_read_stop(&fh->vidq);
+
+       videobuf_mmap_free(&fh->vidq);
+       file->private_data = NULL;
+       kfree(fh);
+       mutex_unlock(&dev->lock);
+       return 0;
+}
+
+static ssize_t mpeg_read(struct file *file, char __user *data,
+       size_t count, loff_t *ppos)
+{
+       struct cx231xx_fh *fh = file->private_data;
+       struct cx231xx *dev = fh->dev;
+
+
+       /* Deal w/ A/V decoder * and mpeg encoder sync issues. */
+       /* Start mpeg encoder on first read. */
+       if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
+               if (atomic_inc_return(&dev->v4l_reader_count) == 1) {
+                       if (cx231xx_initialize_codec(dev) < 0)
+                               return -EINVAL;
+               }
+       }
+
+       return videobuf_read_stream(&fh->vidq, data, count, ppos, 0,
+                                   file->f_flags & O_NONBLOCK);
+}
+
+static unsigned int mpeg_poll(struct file *file,
+       struct poll_table_struct *wait)
+{
+       struct cx231xx_fh *fh = file->private_data;
+       /*struct cx231xx *dev = fh->dev;*/
+
+       /*dprintk(2, "%s\n", __func__);*/
+
+       return videobuf_poll_stream(file, &fh->vidq, wait);
+}
+
+static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct cx231xx_fh *fh = file->private_data;
+       struct cx231xx *dev = fh->dev;
+
+       dprintk(2, "%s()\n", __func__);
+
+       return videobuf_mmap_mapper(&fh->vidq, vma);
+}
+
+static struct v4l2_file_operations mpeg_fops = {
+       .owner         = THIS_MODULE,
+       .open          = mpeg_open,
+       .release       = mpeg_release,
+       .read          = mpeg_read,
+       .poll          = mpeg_poll,
+       .mmap          = mpeg_mmap,
+       .ioctl         = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
+       .vidioc_s_std            = vidioc_s_std,
+       .vidioc_g_std            = vidioc_g_std,
+       .vidioc_enum_input       = vidioc_enum_input,
+       .vidioc_enumaudio        = vidioc_enumaudio,
+       .vidioc_g_audio          = vidioc_g_audio,
+       .vidioc_g_input          = vidioc_g_input,
+       .vidioc_s_input          = vidioc_s_input,
+       .vidioc_g_tuner          = vidioc_g_tuner,
+       .vidioc_s_tuner          = vidioc_s_tuner,
+       .vidioc_g_frequency      = vidioc_g_frequency,
+       .vidioc_s_frequency      = vidioc_s_frequency,
+       .vidioc_s_ctrl           = vidioc_s_ctrl,
+       .vidioc_querycap         = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap    = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap  = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap    = vidioc_s_fmt_vid_cap,
+       .vidioc_reqbufs          = vidioc_reqbufs,
+       .vidioc_querybuf         = vidioc_querybuf,
+       .vidioc_qbuf             = vidioc_qbuf,
+       .vidioc_dqbuf            = vidioc_dqbuf,
+       .vidioc_streamon         = vidioc_streamon,
+       .vidioc_streamoff        = vidioc_streamoff,
+       .vidioc_g_ext_ctrls      = vidioc_g_ext_ctrls,
+       .vidioc_s_ext_ctrls      = vidioc_s_ext_ctrls,
+       .vidioc_try_ext_ctrls    = vidioc_try_ext_ctrls,
+       .vidioc_log_status       = vidioc_log_status,
+       .vidioc_querymenu        = vidioc_querymenu,
+       .vidioc_queryctrl        = vidioc_queryctrl,
+/*     .vidioc_g_chip_ident     = cx231xx_g_chip_ident,*/
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+/*     .vidioc_g_register       = cx231xx_g_register,*/
+/*     .vidioc_s_register       = cx231xx_s_register,*/
+#endif
+};
+
+static struct video_device cx231xx_mpeg_template = {
+       .name          = "cx231xx",
+       .fops          = &mpeg_fops,
+       .ioctl_ops     = &mpeg_ioctl_ops,
+       .minor         = -1,
+       .tvnorms       = CX231xx_NORMS,
+       .current_norm  = V4L2_STD_NTSC_M,
+};
+
+void cx231xx_417_unregister(struct cx231xx *dev)
+{
+       dprintk(1, "%s()\n", __func__);
+       dprintk(3, "%s()\n", __func__);
+
+       if (dev->v4l_device) {
+               if (-1 != dev->v4l_device->minor)
+                       video_unregister_device(dev->v4l_device);
+               else
+                       video_device_release(dev->v4l_device);
+               dev->v4l_device = NULL;
+       }
+}
+
+static struct video_device *cx231xx_video_dev_alloc(
+       struct cx231xx *dev,
+       struct usb_device *usbdev,
+       struct video_device *template,
+       char *type)
+{
+       struct video_device *vfd;
+
+       dprintk(1, "%s()\n", __func__);
+       vfd = video_device_alloc();
+       if (NULL == vfd)
+               return NULL;
+       *vfd = *template;
+       vfd->minor = -1;
+       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
+               type, cx231xx_boards[dev->model].name);
+
+       vfd->v4l2_dev = &dev->v4l2_dev;
+       vfd->release = video_device_release;
+
+       return vfd;
+
+}
+
+int cx231xx_417_register(struct cx231xx *dev)
+{
+       /* FIXME: Port1 hardcoded here */
+       int err = -ENODEV;
+       struct cx231xx_tsport *tsport = &dev->ts1;
+
+       dprintk(1, "%s()\n", __func__);
+
+       /* Set default TV standard */
+       dev->encodernorm = cx231xx_tvnorms[0];
+
+       if (dev->encodernorm.id & V4L2_STD_525_60)
+               tsport->height = 480;
+       else
+               tsport->height = 576;
+
+       tsport->width = 720;
+       cx2341x_fill_defaults(&dev->mpeg_params);
+       dev->norm = V4L2_STD_NTSC;
+
+       dev->mpeg_params.port = CX2341X_PORT_SERIAL;
+
+       /* Allocate and initialize V4L video device */
+       dev->v4l_device = cx231xx_video_dev_alloc(dev,
+               dev->udev, &cx231xx_mpeg_template, "mpeg");
+       err = video_register_device(dev->v4l_device,
+               VFL_TYPE_GRABBER, -1);
+       if (err < 0) {
+               dprintk(3, "%s: can't register mpeg device\n", dev->name);
+               return err;
+       }
+
+       dprintk(3, "%s: registered device video%d [mpeg]\n",
+              dev->name, dev->v4l_device->num);
+
+       return 0;
+}
+
+MODULE_FIRMWARE(CX231xx_FIRM_IMAGE_NAME);
diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c
new file mode 100644 (file)
index 0000000..b4c99c7
--- /dev/null
@@ -0,0 +1,780 @@
+/*
+ *  Conexant Cx231xx audio extension
+ *
+ *  Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+ *       Based on em28xx driver
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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/usb.h>
+#include <linux/init.h>
+#include <linux/sound.h>
+#include <linux/spinlock.h>
+#include <linux/soundcard.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
+#include <linux/module.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 "cx231xx.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
+
+#define dprintk(fmt, arg...) do {                                      \
+               if (debug)                                              \
+                       printk(KERN_INFO "cx231xx-audio %s: " fmt,      \
+                               __func__, ##arg);                       \
+       } while (0)
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+
+static int cx231xx_isoc_audio_deinit(struct cx231xx *dev)
+{
+       int i;
+
+       dprintk("Stopping isoc\n");
+
+       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
+               if (dev->adev.urb[i]) {
+                       if (!irqs_disabled())
+                               usb_kill_urb(dev->adev.urb[i]);
+                       else
+                               usb_unlink_urb(dev->adev.urb[i]);
+
+                       usb_free_urb(dev->adev.urb[i]);
+                       dev->adev.urb[i] = NULL;
+
+                       kfree(dev->adev.transfer_buffer[i]);
+                       dev->adev.transfer_buffer[i] = NULL;
+               }
+       }
+
+       return 0;
+}
+
+static int cx231xx_bulk_audio_deinit(struct cx231xx *dev)
+{
+       int i;
+
+       dprintk("Stopping bulk\n");
+
+       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
+               if (dev->adev.urb[i]) {
+                       if (!irqs_disabled())
+                               usb_kill_urb(dev->adev.urb[i]);
+                       else
+                               usb_unlink_urb(dev->adev.urb[i]);
+
+                       usb_free_urb(dev->adev.urb[i]);
+                       dev->adev.urb[i] = NULL;
+
+                       kfree(dev->adev.transfer_buffer[i]);
+                       dev->adev.transfer_buffer[i] = NULL;
+               }
+       }
+
+       return 0;
+}
+
+static void cx231xx_audio_isocirq(struct urb *urb)
+{
+       struct cx231xx *dev = urb->context;
+       int i;
+       unsigned int oldptr;
+       int period_elapsed = 0;
+       int status;
+       unsigned char *cp;
+       unsigned int stride;
+       struct snd_pcm_substream *substream;
+       struct snd_pcm_runtime *runtime;
+
+       if (dev->state & DEV_DISCONNECTED)
+               return;
+
+       switch (urb->status) {
+       case 0:         /* success */
+       case -ETIMEDOUT:        /* NAK */
+               break;
+       case -ECONNRESET:       /* kill */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+       default:                /* error */
+               dprintk("urb completition error %d.\n", urb->status);
+               break;
+       }
+
+       if (atomic_read(&dev->stream_started) == 0)
+               return;
+
+       if (dev->adev.capture_pcm_substream) {
+               substream = dev->adev.capture_pcm_substream;
+               runtime = substream->runtime;
+               stride = runtime->frame_bits >> 3;
+
+               for (i = 0; i < urb->number_of_packets; i++) {
+                       int length = urb->iso_frame_desc[i].actual_length /
+                                    stride;
+                       cp = (unsigned char *)urb->transfer_buffer +
+                                             urb->iso_frame_desc[i].offset;
+
+                       if (!length)
+                               continue;
+
+                       oldptr = dev->adev.hwptr_done_capture;
+                       if (oldptr + length >= runtime->buffer_size) {
+                               unsigned int cnt;
+
+                               cnt = runtime->buffer_size - oldptr;
+                               memcpy(runtime->dma_area + oldptr * stride, cp,
+                                      cnt * stride);
+                               memcpy(runtime->dma_area, cp + cnt * stride,
+                                      length * stride - cnt * stride);
+                       } else {
+                               memcpy(runtime->dma_area + oldptr * stride, cp,
+                                      length * stride);
+                       }
+
+                       snd_pcm_stream_lock(substream);
+
+                       dev->adev.hwptr_done_capture += length;
+                       if (dev->adev.hwptr_done_capture >=
+                                               runtime->buffer_size)
+                               dev->adev.hwptr_done_capture -=
+                                               runtime->buffer_size;
+
+                       dev->adev.capture_transfer_done += length;
+                       if (dev->adev.capture_transfer_done >=
+                               runtime->period_size) {
+                               dev->adev.capture_transfer_done -=
+                                               runtime->period_size;
+                               period_elapsed = 1;
+                       }
+                       snd_pcm_stream_unlock(substream);
+               }
+               if (period_elapsed)
+                       snd_pcm_period_elapsed(substream);
+       }
+       urb->status = 0;
+
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (status < 0) {
+               cx231xx_errdev("resubmit of audio urb failed (error=%i)\n",
+                              status);
+       }
+       return;
+}
+
+static void cx231xx_audio_bulkirq(struct urb *urb)
+{
+       struct cx231xx *dev = urb->context;
+       unsigned int oldptr;
+       int period_elapsed = 0;
+       int status;
+       unsigned char *cp;
+       unsigned int stride;
+       struct snd_pcm_substream *substream;
+       struct snd_pcm_runtime *runtime;
+
+       if (dev->state & DEV_DISCONNECTED)
+               return;
+
+       switch (urb->status) {
+       case 0:         /* success */
+       case -ETIMEDOUT:        /* NAK */
+               break;
+       case -ECONNRESET:       /* kill */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+       default:                /* error */
+               dprintk("urb completition error %d.\n", urb->status);
+               break;
+       }
+
+       if (atomic_read(&dev->stream_started) == 0)
+               return;
+
+       if (dev->adev.capture_pcm_substream) {
+               substream = dev->adev.capture_pcm_substream;
+               runtime = substream->runtime;
+               stride = runtime->frame_bits >> 3;
+
+               if (1) {
+                       int length = urb->actual_length /
+                                    stride;
+                       cp = (unsigned char *)urb->transfer_buffer;
+
+                       oldptr = dev->adev.hwptr_done_capture;
+                       if (oldptr + length >= runtime->buffer_size) {
+                               unsigned int cnt;
+
+                               cnt = runtime->buffer_size - oldptr;
+                               memcpy(runtime->dma_area + oldptr * stride, cp,
+                                      cnt * stride);
+                               memcpy(runtime->dma_area, cp + cnt * stride,
+                                      length * stride - cnt * stride);
+                       } else {
+                               memcpy(runtime->dma_area + oldptr * stride, cp,
+                                      length * stride);
+                       }
+
+                       snd_pcm_stream_lock(substream);
+
+                       dev->adev.hwptr_done_capture += length;
+                       if (dev->adev.hwptr_done_capture >=
+                                               runtime->buffer_size)
+                               dev->adev.hwptr_done_capture -=
+                                               runtime->buffer_size;
+
+                       dev->adev.capture_transfer_done += length;
+                       if (dev->adev.capture_transfer_done >=
+                               runtime->period_size) {
+                               dev->adev.capture_transfer_done -=
+                                               runtime->period_size;
+                               period_elapsed = 1;
+                       }
+                       snd_pcm_stream_unlock(substream);
+               }
+               if (period_elapsed)
+                       snd_pcm_period_elapsed(substream);
+       }
+       urb->status = 0;
+
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (status < 0) {
+               cx231xx_errdev("resubmit of audio urb failed (error=%i)\n",
+                              status);
+       }
+       return;
+}
+
+static int cx231xx_init_audio_isoc(struct cx231xx *dev)
+{
+       int i, errCode;
+       int sb_size;
+
+       cx231xx_info("%s: Starting ISO AUDIO transfers\n", __func__);
+
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
+       sb_size = CX231XX_ISO_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
+
+       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
+               struct urb *urb;
+               int j, k;
+
+               dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
+               if (!dev->adev.transfer_buffer[i])
+                       return -ENOMEM;
+
+               memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
+               urb = usb_alloc_urb(CX231XX_ISO_NUM_AUDIO_PACKETS, GFP_ATOMIC);
+               if (!urb) {
+                       cx231xx_errdev("usb_alloc_urb failed!\n");
+                       for (j = 0; j < i; j++) {
+                               usb_free_urb(dev->adev.urb[j]);
+                               kfree(dev->adev.transfer_buffer[j]);
+                       }
+                       return -ENOMEM;
+               }
+
+               urb->dev = dev->udev;
+               urb->context = dev;
+               urb->pipe = usb_rcvisocpipe(dev->udev,
+                                               dev->adev.end_point_addr);
+               urb->transfer_flags = URB_ISO_ASAP;
+               urb->transfer_buffer = dev->adev.transfer_buffer[i];
+               urb->interval = 1;
+               urb->complete = cx231xx_audio_isocirq;
+               urb->number_of_packets = CX231XX_ISO_NUM_AUDIO_PACKETS;
+               urb->transfer_buffer_length = sb_size;
+
+               for (j = k = 0; j < CX231XX_ISO_NUM_AUDIO_PACKETS;
+                       j++, k += dev->adev.max_pkt_size) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length = dev->adev.max_pkt_size;
+               }
+               dev->adev.urb[i] = urb;
+       }
+
+       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
+               errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
+               if (errCode < 0) {
+                       cx231xx_isoc_audio_deinit(dev);
+                       return errCode;
+               }
+       }
+
+       return errCode;
+}
+
+static int cx231xx_init_audio_bulk(struct cx231xx *dev)
+{
+       int i, errCode;
+       int sb_size;
+
+       cx231xx_info("%s: Starting BULK AUDIO transfers\n", __func__);
+
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
+       sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
+
+       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
+               struct urb *urb;
+               int j;
+
+               dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
+               if (!dev->adev.transfer_buffer[i])
+                       return -ENOMEM;
+
+               memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
+               urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
+               if (!urb) {
+                       cx231xx_errdev("usb_alloc_urb failed!\n");
+                       for (j = 0; j < i; j++) {
+                               usb_free_urb(dev->adev.urb[j]);
+                               kfree(dev->adev.transfer_buffer[j]);
+                       }
+                       return -ENOMEM;
+               }
+
+               urb->dev = dev->udev;
+               urb->context = dev;
+               urb->pipe = usb_rcvbulkpipe(dev->udev,
+                                               dev->adev.end_point_addr);
+               urb->transfer_flags = 0;
+               urb->transfer_buffer = dev->adev.transfer_buffer[i];
+               urb->complete = cx231xx_audio_bulkirq;
+               urb->transfer_buffer_length = sb_size;
+
+               dev->adev.urb[i] = urb;
+
+       }
+
+       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
+               errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
+               if (errCode < 0) {
+                       cx231xx_bulk_audio_deinit(dev);
+                       return errCode;
+               }
+       }
+
+       return errCode;
+}
+
+static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
+                                       size_t size)
+{
+       struct snd_pcm_runtime *runtime = subs->runtime;
+
+       dprintk("Allocating vbuffer\n");
+       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;
+
+       runtime->dma_bytes = size;
+
+       return 0;
+}
+
+static struct snd_pcm_hardware snd_cx231xx_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_CONTINUOUS | SNDRV_PCM_RATE_KNOT,
+
+       .rate_min = 48000,
+       .rate_max = 48000,
+       .channels_min = 2,
+       .channels_max = 2,
+       .buffer_bytes_max = 62720 * 8,  /* just about the value in usbaudio.c */
+       .period_bytes_min = 64,         /* 12544/2, */
+       .period_bytes_max = 12544,
+       .periods_min = 2,
+       .periods_max = 98,              /* 12544, */
+};
+
+static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream)
+{
+       struct cx231xx *dev = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int ret = 0;
+
+       dprintk("opening device and trying to acquire exclusive lock\n");
+
+       if (!dev) {
+               cx231xx_errdev("BUG: cx231xx can't find device struct."
+                              " Can't proceed with open\n");
+               return -ENODEV;
+       }
+
+       if (dev->state & DEV_DISCONNECTED) {
+               cx231xx_errdev("Can't open. the device was removed.\n");
+               return -ENODEV;
+       }
+
+       /* Sets volume, mute, etc */
+       dev->mute = 0;
+
+       /* set alternate setting for audio interface */
+       /* 1 - 48000 samples per sec */
+       mutex_lock(&dev->lock);
+       if (dev->USE_ISO)
+               ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1);
+       else
+               ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
+       mutex_unlock(&dev->lock);
+       if (ret < 0) {
+               cx231xx_errdev("failed to set alternate setting !\n");
+
+               return ret;
+       }
+
+       runtime->hw = snd_cx231xx_hw_capture;
+
+       mutex_lock(&dev->lock);
+       /* inform hardware to start streaming */
+       ret = cx231xx_capture_start(dev, 1, Audio);
+
+       dev->adev.users++;
+       mutex_unlock(&dev->lock);
+
+       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+       dev->adev.capture_pcm_substream = substream;
+       runtime->private_data = dev;
+
+       return 0;
+}
+
+static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream)
+{
+       int ret;
+       struct cx231xx *dev = snd_pcm_substream_chip(substream);
+
+       dprintk("closing device\n");
+
+       /* inform hardware to stop streaming */
+       mutex_lock(&dev->lock);
+       ret = cx231xx_capture_start(dev, 0, Audio);
+
+       /* set alternate setting for audio interface */
+       /* 1 - 48000 samples per sec */
+       ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
+       if (ret < 0) {
+               cx231xx_errdev("failed to set alternate setting !\n");
+
+               mutex_unlock(&dev->lock);
+               return ret;
+       }
+
+       dev->mute = 1;
+       dev->adev.users--;
+       mutex_unlock(&dev->lock);
+
+       if (dev->adev.users == 0 && dev->adev.shutdown == 1) {
+               dprintk("audio users: %d\n", dev->adev.users);
+               dprintk("disabling audio stream!\n");
+               dev->adev.shutdown = 0;
+               dprintk("released lock\n");
+               if (atomic_read(&dev->stream_started) > 0) {
+                       atomic_set(&dev->stream_started, 0);
+                       schedule_work(&dev->wq_trigger);
+               }
+       }
+       return 0;
+}
+
+static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream,
+                                        struct snd_pcm_hw_params *hw_params)
+{
+       int ret;
+
+       dprintk("Setting capture parameters\n");
+
+       ret = snd_pcm_alloc_vmalloc_buffer(substream,
+                                          params_buffer_bytes(hw_params));
+#if 0
+       /* TODO: set up cx231xx audio chip to deliver the correct audio format,
+          current default is 48000hz multiplexed => 96000hz mono
+          which shouldn't matter since analogue TV only supports mono */
+       unsigned int channels, rate, format;
+
+       format = params_format(hw_params);
+       rate = params_rate(hw_params);
+       channels = params_channels(hw_params);
+#endif
+
+       return ret;
+}
+
+static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream)
+{
+       struct cx231xx *dev = snd_pcm_substream_chip(substream);
+
+       dprintk("Stop capture, if needed\n");
+
+       if (atomic_read(&dev->stream_started) > 0) {
+               atomic_set(&dev->stream_started, 0);
+               schedule_work(&dev->wq_trigger);
+       }
+
+       return 0;
+}
+
+static int snd_cx231xx_prepare(struct snd_pcm_substream *substream)
+{
+       struct cx231xx *dev = snd_pcm_substream_chip(substream);
+
+       dev->adev.hwptr_done_capture = 0;
+       dev->adev.capture_transfer_done = 0;
+
+       return 0;
+}
+
+static void audio_trigger(struct work_struct *work)
+{
+       struct cx231xx *dev = container_of(work, struct cx231xx, wq_trigger);
+
+       if (atomic_read(&dev->stream_started)) {
+               dprintk("starting capture");
+               if (is_fw_load(dev) == 0)
+                       cx25840_call(dev, core, load_fw);
+               if (dev->USE_ISO)
+                       cx231xx_init_audio_isoc(dev);
+               else
+                       cx231xx_init_audio_bulk(dev);
+       } else {
+               dprintk("stopping capture");
+               cx231xx_isoc_audio_deinit(dev);
+       }
+}
+
+static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream,
+                                      int cmd)
+{
+       struct cx231xx *dev = snd_pcm_substream_chip(substream);
+       int retval = 0;
+
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
+       spin_lock(&dev->adev.slock);
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_START:
+               atomic_set(&dev->stream_started, 1);
+               break;
+       case SNDRV_PCM_TRIGGER_STOP:
+               atomic_set(&dev->stream_started, 0);
+               break;
+       default:
+               retval = -EINVAL;
+               break;
+       }
+       spin_unlock(&dev->adev.slock);
+
+       schedule_work(&dev->wq_trigger);
+
+       return retval;
+}
+
+static snd_pcm_uframes_t snd_cx231xx_capture_pointer(struct snd_pcm_substream
+                                                    *substream)
+{
+       struct cx231xx *dev;
+       unsigned long flags;
+       snd_pcm_uframes_t hwptr_done;
+
+       dev = snd_pcm_substream_chip(substream);
+
+       spin_lock_irqsave(&dev->adev.slock, flags);
+       hwptr_done = dev->adev.hwptr_done_capture;
+       spin_unlock_irqrestore(&dev->adev.slock, flags);
+
+       return hwptr_done;
+}
+
+static struct page *snd_pcm_get_vmalloc_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 snd_cx231xx_pcm_capture = {
+       .open = snd_cx231xx_capture_open,
+       .close = snd_cx231xx_pcm_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = snd_cx231xx_hw_capture_params,
+       .hw_free = snd_cx231xx_hw_capture_free,
+       .prepare = snd_cx231xx_prepare,
+       .trigger = snd_cx231xx_capture_trigger,
+       .pointer = snd_cx231xx_capture_pointer,
+       .page = snd_pcm_get_vmalloc_page,
+};
+
+static int cx231xx_audio_init(struct cx231xx *dev)
+{
+       struct cx231xx_audio *adev = &dev->adev;
+       struct snd_pcm *pcm;
+       struct snd_card *card;
+       static int devnr;
+       int err;
+       struct usb_interface *uif;
+       int i, isoc_pipe = 0;
+
+       if (dev->has_alsa_audio != 1) {
+               /* This device does not support the extension (in this case
+                  the device is expecting the snd-usb-audio module or
+                  doesn't have analog audio support at all) */
+               return 0;
+       }
+
+       cx231xx_info("cx231xx-audio.c: probing for cx231xx "
+                    "non standard usbaudio\n");
+
+       err = snd_card_create(index[devnr], "Cx231xx Audio", THIS_MODULE,
+                             0, &card);
+       if (err < 0)
+               return err;
+
+       spin_lock_init(&adev->slock);
+       err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+                       &snd_cx231xx_pcm_capture);
+       pcm->info_flags = 0;
+       pcm->private_data = dev;
+       strcpy(pcm->name, "Conexant cx231xx Capture");
+       snd_card_set_dev(card, &dev->udev->dev);
+       strcpy(card->driver, "Cx231xx-Audio");
+       strcpy(card->shortname, "Cx231xx Audio");
+       strcpy(card->longname, "Conexant cx231xx Audio");
+
+       INIT_WORK(&dev->wq_trigger, audio_trigger);
+
+       err = snd_card_register(card);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+       adev->sndcard = card;
+       adev->udev = dev->udev;
+
+       /* compute alternate max packet sizes for Audio */
+       uif =
+           dev->udev->actconfig->interface[dev->current_pcb_config.
+                                           hs_config_info[0].interface_info.
+                                           audio_index + 1];
+
+       adev->end_point_addr =
+           le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.
+                       bEndpointAddress);
+
+       adev->num_alt = uif->num_altsetting;
+       cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+                    adev->end_point_addr, adev->num_alt);
+       adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL);
+
+       if (adev->alt_max_pkt_size == NULL) {
+               cx231xx_errdev("out of memory!\n");
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < adev->num_alt; i++) {
+               u16 tmp =
+                   le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.
+                               wMaxPacketSize);
+               adev->alt_max_pkt_size[i] =
+                   (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+               cx231xx_info("Alternate setting %i, max size= %i\n", i,
+                            adev->alt_max_pkt_size[i]);
+       }
+
+       return 0;
+}
+
+static int cx231xx_audio_fini(struct cx231xx *dev)
+{
+       if (dev == NULL)
+               return 0;
+
+       if (dev->has_alsa_audio != 1) {
+               /* This device does not support the extension (in this case
+                  the device is expecting the snd-usb-audio module or
+                  doesn't have analog audio support at all) */
+               return 0;
+       }
+
+       if (dev->adev.sndcard) {
+               snd_card_free(dev->adev.sndcard);
+               kfree(dev->adev.alt_max_pkt_size);
+               dev->adev.sndcard = NULL;
+       }
+
+       return 0;
+}
+
+static struct cx231xx_ops audio_ops = {
+       .id = CX231XX_AUDIO,
+       .name = "Cx231xx Audio Extension",
+       .init = cx231xx_audio_init,
+       .fini = cx231xx_audio_fini,
+};
+
+static int __init cx231xx_alsa_register(void)
+{
+       return cx231xx_register_extension(&audio_ops);
+}
+
+static void __exit cx231xx_alsa_unregister(void)
+{
+       cx231xx_unregister_extension(&audio_ops);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
+MODULE_DESCRIPTION("Cx231xx Audio driver");
+
+module_init(cx231xx_alsa_register);
+module_exit(cx231xx_alsa_unregister);
diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c
new file mode 100644 (file)
index 0000000..447148e
--- /dev/null
@@ -0,0 +1,3087 @@
+/*
+   cx231xx_avcore.c - driver for Conexant Cx23100/101/102
+                     USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+
+   This program contains the specific code to control the avdecoder chip and
+   other related usb control functions for cx231xx based chipset.
+
+   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/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 <linux/mm.h>
+#include <linux/mutex.h>
+#include <media/tuner.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
+
+#include "cx231xx.h"
+#include "cx231xx-dif.h"
+
+#define TUNER_MODE_FM_RADIO 0
+/******************************************************************************
+                       -: BLOCK ARRANGEMENT :-
+       I2S block ----------------------|
+       [I2S audio]                     |
+                                       |
+       Analog Front End --> Direct IF -|-> Cx25840 --> Audio
+       [video & audio]                 |   [Audio]
+                                       |
+                                       |-> Cx25840 --> Video
+                                           [Video]
+
+*******************************************************************************/
+/******************************************************************************
+ *                    VERVE REGISTER                                          *
+ *                                                                           *
+ ******************************************************************************/
+static int verve_write_byte(struct cx231xx *dev, u8 saddr, u8 data)
+{
+       return cx231xx_write_i2c_data(dev, VERVE_I2C_ADDRESS,
+                                       saddr, 1, data, 1);
+}
+
+static int verve_read_byte(struct cx231xx *dev, u8 saddr, u8 *data)
+{
+       int status;
+       u32 temp = 0;
+
+       status = cx231xx_read_i2c_data(dev, VERVE_I2C_ADDRESS,
+                                       saddr, 1, &temp, 1);
+       *data = (u8) temp;
+       return status;
+}
+void initGPIO(struct cx231xx *dev)
+{
+       u32 _gpio_direction = 0;
+       u32 value = 0;
+       u8 val = 0;
+
+       _gpio_direction = _gpio_direction & 0xFC0003FF;
+       _gpio_direction = _gpio_direction | 0x03FDFC00;
+       cx231xx_send_gpio_cmd(dev, _gpio_direction, (u8 *)&value, 4, 0, 0);
+
+       verve_read_byte(dev, 0x07, &val);
+       cx231xx_info(" verve_read_byte address0x07=0x%x\n", val);
+       verve_write_byte(dev, 0x07, 0xF4);
+       verve_read_byte(dev, 0x07, &val);
+       cx231xx_info(" verve_read_byte address0x07=0x%x\n", val);
+
+       cx231xx_capture_start(dev, 1, Vbi);
+
+       cx231xx_mode_register(dev, EP_MODE_SET, 0x0500FE00);
+       cx231xx_mode_register(dev, GBULK_BIT_EN, 0xFFFDFFFF);
+
+}
+void uninitGPIO(struct cx231xx *dev)
+{
+       u8 value[4] = { 0, 0, 0, 0 };
+
+       cx231xx_capture_start(dev, 0, Vbi);
+       verve_write_byte(dev, 0x07, 0x14);
+       cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                       0x68, value, 4);
+}
+
+/******************************************************************************
+ *                    A F E - B L O C K    C O N T R O L   functions          *
+ *                             [ANALOG FRONT END]                            *
+ ******************************************************************************/
+static int afe_write_byte(struct cx231xx *dev, u16 saddr, u8 data)
+{
+       return cx231xx_write_i2c_data(dev, AFE_DEVICE_ADDRESS,
+                                       saddr, 2, data, 1);
+}
+
+static int afe_read_byte(struct cx231xx *dev, u16 saddr, u8 *data)
+{
+       int status;
+       u32 temp = 0;
+
+       status = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS,
+                                       saddr, 2, &temp, 1);
+       *data = (u8) temp;
+       return status;
+}
+
+int cx231xx_afe_init_super_block(struct cx231xx *dev, u32 ref_count)
+{
+       int status = 0;
+       u8 temp = 0;
+       u8 afe_power_status = 0;
+       int i = 0;
+
+       /* super block initialize */
+       temp = (u8) (ref_count & 0xff);
+       status = afe_write_byte(dev, SUP_BLK_TUNE2, temp);
+       if (status < 0)
+               return status;
+
+       status = afe_read_byte(dev, SUP_BLK_TUNE2, &afe_power_status);
+       if (status < 0)
+               return status;
+
+       temp = (u8) ((ref_count & 0x300) >> 8);
+       temp |= 0x40;
+       status = afe_write_byte(dev, SUP_BLK_TUNE1, temp);
+       if (status < 0)
+               return status;
+
+       status = afe_write_byte(dev, SUP_BLK_PLL2, 0x0f);
+       if (status < 0)
+               return status;
+
+       /* enable pll     */
+       while (afe_power_status != 0x18) {
+               status = afe_write_byte(dev, SUP_BLK_PWRDN, 0x18);
+               if (status < 0) {
+                       cx231xx_info(
+                       ": Init Super Block failed in send cmd\n");
+                       break;
+               }
+
+               status = afe_read_byte(dev, SUP_BLK_PWRDN, &afe_power_status);
+               afe_power_status &= 0xff;
+               if (status < 0) {
+                       cx231xx_info(
+                       ": Init Super Block failed in receive cmd\n");
+                       break;
+               }
+               i++;
+               if (i == 10) {
+                       cx231xx_info(
+                       ": Init Super Block force break in loop !!!!\n");
+                       status = -1;
+                       break;
+               }
+       }
+
+       if (status < 0)
+               return status;
+
+       /* start tuning filter */
+       status = afe_write_byte(dev, SUP_BLK_TUNE3, 0x40);
+       if (status < 0)
+               return status;
+
+       msleep(5);
+
+       /* exit tuning */
+       status = afe_write_byte(dev, SUP_BLK_TUNE3, 0x00);
+
+       return status;
+}
+
+int cx231xx_afe_init_channels(struct cx231xx *dev)
+{
+       int status = 0;
+
+       /* power up all 3 channels, clear pd_buffer */
+       status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, 0x00);
+       status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, 0x00);
+       status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, 0x00);
+
+       /* Enable quantizer calibration */
+       status = afe_write_byte(dev, ADC_COM_QUANT, 0x02);
+
+       /* channel initialize, force modulator (fb) reset */
+       status = afe_write_byte(dev, ADC_FB_FRCRST_CH1, 0x17);
+       status = afe_write_byte(dev, ADC_FB_FRCRST_CH2, 0x17);
+       status = afe_write_byte(dev, ADC_FB_FRCRST_CH3, 0x17);
+
+       /* start quantilizer calibration  */
+       status = afe_write_byte(dev, ADC_CAL_ATEST_CH1, 0x10);
+       status = afe_write_byte(dev, ADC_CAL_ATEST_CH2, 0x10);
+       status = afe_write_byte(dev, ADC_CAL_ATEST_CH3, 0x10);
+       msleep(5);
+
+       /* exit modulator (fb) reset */
+       status = afe_write_byte(dev, ADC_FB_FRCRST_CH1, 0x07);
+       status = afe_write_byte(dev, ADC_FB_FRCRST_CH2, 0x07);
+       status = afe_write_byte(dev, ADC_FB_FRCRST_CH3, 0x07);
+
+       /* enable the pre_clamp in each channel for single-ended input */
+       status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH1, 0xf0);
+       status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH2, 0xf0);
+       status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH3, 0xf0);
+
+       /* use diode instead of resistor, so set term_en to 0, res_en to 0  */
+       status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8,
+                                  ADC_QGAIN_RES_TRM_CH1, 3, 7, 0x00);
+       status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8,
+                                  ADC_QGAIN_RES_TRM_CH2, 3, 7, 0x00);
+       status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8,
+                                  ADC_QGAIN_RES_TRM_CH3, 3, 7, 0x00);
+
+       /* dynamic element matching off */
+       status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH1, 0x03);
+       status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH2, 0x03);
+       status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH3, 0x03);
+
+       return status;
+}
+
+int cx231xx_afe_setup_AFE_for_baseband(struct cx231xx *dev)
+{
+       u8 c_value = 0;
+       int status = 0;
+
+       status = afe_read_byte(dev, ADC_PWRDN_CLAMP_CH2, &c_value);
+       c_value &= (~(0x50));
+       status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, c_value);
+
+       return status;
+}
+
+/*
+       The Analog Front End in Cx231xx has 3 channels. These
+       channels are used to share between different inputs
+       like tuner, s-video and composite inputs.
+
+       channel 1 ----- pin 1  to pin4(in reg is 1-4)
+       channel 2 ----- pin 5  to pin8(in reg is 5-8)
+       channel 3 ----- pin 9 to pin 12(in reg is 9-11)
+*/
+int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux)
+{
+       u8 ch1_setting = (u8) input_mux;
+       u8 ch2_setting = (u8) (input_mux >> 8);
+       u8 ch3_setting = (u8) (input_mux >> 16);
+       int status = 0;
+       u8 value = 0;
+
+       if (ch1_setting != 0) {
+               status = afe_read_byte(dev, ADC_INPUT_CH1, &value);
+               value &= ~INPUT_SEL_MASK;
+               value |= (ch1_setting - 1) << 4;
+               value &= 0xff;
+               status = afe_write_byte(dev, ADC_INPUT_CH1, value);
+       }
+
+       if (ch2_setting != 0) {
+               status = afe_read_byte(dev, ADC_INPUT_CH2, &value);
+               value &= ~INPUT_SEL_MASK;
+               value |= (ch2_setting - 1) << 4;
+               value &= 0xff;
+               status = afe_write_byte(dev, ADC_INPUT_CH2, value);
+       }
+
+       /* For ch3_setting, the value to put in the register is
+          7 less than the input number */
+       if (ch3_setting != 0) {
+               status = afe_read_byte(dev, ADC_INPUT_CH3, &value);
+               value &= ~INPUT_SEL_MASK;
+               value |= (ch3_setting - 1) << 4;
+               value &= 0xff;
+               status = afe_write_byte(dev, ADC_INPUT_CH3, value);
+       }
+
+       return status;
+}
+
+int cx231xx_afe_set_mode(struct cx231xx *dev, enum AFE_MODE mode)
+{
+       int status = 0;
+
+       /*
+       * FIXME: We need to implement the AFE code for LOW IF and for HI IF.
+       * Currently, only baseband works.
+       */
+
+       switch (mode) {
+       case AFE_MODE_LOW_IF:
+               cx231xx_Setup_AFE_for_LowIF(dev);
+               break;
+       case AFE_MODE_BASEBAND:
+               status = cx231xx_afe_setup_AFE_for_baseband(dev);
+               break;
+       case AFE_MODE_EU_HI_IF:
+               /* SetupAFEforEuHiIF(); */
+               break;
+       case AFE_MODE_US_HI_IF:
+               /* SetupAFEforUsHiIF(); */
+               break;
+       case AFE_MODE_JAPAN_HI_IF:
+               /* SetupAFEforJapanHiIF(); */
+               break;
+       }
+
+       if ((mode != dev->afe_mode) &&
+               (dev->video_input == CX231XX_VMUX_TELEVISION))
+               status = cx231xx_afe_adjust_ref_count(dev,
+                                                    CX231XX_VMUX_TELEVISION);
+
+       dev->afe_mode = mode;
+
+       return status;
+}
+
+int cx231xx_afe_update_power_control(struct cx231xx *dev,
+                                       enum AV_MODE avmode)
+{
+       u8 afe_power_status = 0;
+       int status = 0;
+
+       switch (dev->model) {
+       case CX231XX_BOARD_CNXT_CARRAERA:
+       case CX231XX_BOARD_CNXT_RDE_250:
+       case CX231XX_BOARD_CNXT_SHELBY:
+       case CX231XX_BOARD_CNXT_RDU_250:
+       case CX231XX_BOARD_CNXT_RDE_253S:
+       case CX231XX_BOARD_CNXT_RDU_253S:
+       case CX231XX_BOARD_CNXT_VIDEO_GRABBER:
+       case CX231XX_BOARD_HAUPPAUGE_EXETER:
+       case CX231XX_BOARD_HAUPPAUGE_USBLIVE2:
+       case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
+       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
+       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
+               if (avmode == POLARIS_AVMODE_ANALOGT_TV) {
+                       while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
+                                               FLD_PWRDN_ENABLE_PLL)) {
+                               status = afe_write_byte(dev, SUP_BLK_PWRDN,
+                                                       FLD_PWRDN_TUNING_BIAS |
+                                                       FLD_PWRDN_ENABLE_PLL);
+                               status |= afe_read_byte(dev, SUP_BLK_PWRDN,
+                                                       &afe_power_status);
+                               if (status < 0)
+                                       break;
+                       }
+
+                       status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
+                                                       0x00);
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
+                                                       0x00);
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
+                                                       0x00);
+               } else if (avmode == POLARIS_AVMODE_DIGITAL) {
+                       status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
+                                                       0x70);
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
+                                                       0x70);
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
+                                                       0x70);
+
+                       status |= afe_read_byte(dev, SUP_BLK_PWRDN,
+                                                 &afe_power_status);
+                       afe_power_status |= FLD_PWRDN_PD_BANDGAP |
+                                               FLD_PWRDN_PD_BIAS |
+                                               FLD_PWRDN_PD_TUNECK;
+                       status |= afe_write_byte(dev, SUP_BLK_PWRDN,
+                                                  afe_power_status);
+               } else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) {
+                       while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
+                                               FLD_PWRDN_ENABLE_PLL)) {
+                               status = afe_write_byte(dev, SUP_BLK_PWRDN,
+                                                       FLD_PWRDN_TUNING_BIAS |
+                                                       FLD_PWRDN_ENABLE_PLL);
+                               status |= afe_read_byte(dev, SUP_BLK_PWRDN,
+                                                       &afe_power_status);
+                               if (status < 0)
+                                       break;
+                       }
+
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
+                                               0x00);
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
+                                               0x00);
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
+                                               0x00);
+               } else {
+                       cx231xx_info("Invalid AV mode input\n");
+                       status = -1;
+               }
+               break;
+       default:
+               if (avmode == POLARIS_AVMODE_ANALOGT_TV) {
+                       while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
+                                               FLD_PWRDN_ENABLE_PLL)) {
+                               status = afe_write_byte(dev, SUP_BLK_PWRDN,
+                                                       FLD_PWRDN_TUNING_BIAS |
+                                                       FLD_PWRDN_ENABLE_PLL);
+                               status |= afe_read_byte(dev, SUP_BLK_PWRDN,
+                                                       &afe_power_status);
+                               if (status < 0)
+                                       break;
+                       }
+
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
+                                                       0x40);
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
+                                                       0x40);
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
+                                                       0x00);
+               } else if (avmode == POLARIS_AVMODE_DIGITAL) {
+                       status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
+                                                       0x70);
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
+                                                       0x70);
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
+                                                       0x70);
+
+                       status |= afe_read_byte(dev, SUP_BLK_PWRDN,
+                                                      &afe_power_status);
+                       afe_power_status |= FLD_PWRDN_PD_BANDGAP |
+                                               FLD_PWRDN_PD_BIAS |
+                                               FLD_PWRDN_PD_TUNECK;
+                       status |= afe_write_byte(dev, SUP_BLK_PWRDN,
+                                                       afe_power_status);
+               } else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) {
+                       while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
+                                               FLD_PWRDN_ENABLE_PLL)) {
+                               status = afe_write_byte(dev, SUP_BLK_PWRDN,
+                                                       FLD_PWRDN_TUNING_BIAS |
+                                                       FLD_PWRDN_ENABLE_PLL);
+                               status |= afe_read_byte(dev, SUP_BLK_PWRDN,
+                                                       &afe_power_status);
+                               if (status < 0)
+                                       break;
+                       }
+
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
+                                                       0x00);
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
+                                                       0x00);
+                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
+                                                       0x40);
+               } else {
+                       cx231xx_info("Invalid AV mode input\n");
+                       status = -1;
+               }
+       }                       /* switch  */
+
+       return status;
+}
+
+int cx231xx_afe_adjust_ref_count(struct cx231xx *dev, u32 video_input)
+{
+       u8 input_mode = 0;
+       u8 ntf_mode = 0;
+       int status = 0;
+
+       dev->video_input = video_input;
+
+       if (video_input == CX231XX_VMUX_TELEVISION) {
+               status = afe_read_byte(dev, ADC_INPUT_CH3, &input_mode);
+               status = afe_read_byte(dev, ADC_NTF_PRECLMP_EN_CH3,
+                                       &ntf_mode);
+       } else {
+               status = afe_read_byte(dev, ADC_INPUT_CH1, &input_mode);
+               status = afe_read_byte(dev, ADC_NTF_PRECLMP_EN_CH1,
+                                       &ntf_mode);
+       }
+
+       input_mode = (ntf_mode & 0x3) | ((input_mode & 0x6) << 1);
+
+       switch (input_mode) {
+       case SINGLE_ENDED:
+               dev->afe_ref_count = 0x23C;
+               break;
+       case LOW_IF:
+               dev->afe_ref_count = 0x24C;
+               break;
+       case EU_IF:
+               dev->afe_ref_count = 0x258;
+               break;
+       case US_IF:
+               dev->afe_ref_count = 0x260;
+               break;
+       default:
+               break;
+       }
+
+       status = cx231xx_afe_init_super_block(dev, dev->afe_ref_count);
+
+       return status;
+}
+
+/******************************************************************************
+ *     V I D E O / A U D I O    D E C O D E R    C O N T R O L   functions    *
+ ******************************************************************************/
+static int vid_blk_write_byte(struct cx231xx *dev, u16 saddr, u8 data)
+{
+       return cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+                                       saddr, 2, data, 1);
+}
+
+static int vid_blk_read_byte(struct cx231xx *dev, u16 saddr, u8 *data)
+{
+       int status;
+       u32 temp = 0;
+
+       status = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+                                       saddr, 2, &temp, 1);
+       *data = (u8) temp;
+       return status;
+}
+
+static int vid_blk_write_word(struct cx231xx *dev, u16 saddr, u32 data)
+{
+       return cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+                                       saddr, 2, data, 4);
+}
+
+static int vid_blk_read_word(struct cx231xx *dev, u16 saddr, u32 *data)
+{
+       return cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+                                       saddr, 2, data, 4);
+}
+int cx231xx_check_fw(struct cx231xx *dev)
+{
+       u8 temp = 0;
+       int status = 0;
+       status = vid_blk_read_byte(dev, DL_CTL_ADDRESS_LOW, &temp);
+       if (status < 0)
+               return status;
+       else
+               return temp;
+
+}
+
+int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input)
+{
+       int status = 0;
+
+       switch (INPUT(input)->type) {
+       case CX231XX_VMUX_COMPOSITE1:
+       case CX231XX_VMUX_SVIDEO:
+               if ((dev->current_pcb_config.type == USB_BUS_POWER) &&
+                   (dev->power_mode != POLARIS_AVMODE_ENXTERNAL_AV)) {
+                       /* External AV */
+                       status = cx231xx_set_power_mode(dev,
+                                       POLARIS_AVMODE_ENXTERNAL_AV);
+                       if (status < 0) {
+                               cx231xx_errdev("%s: set_power_mode : Failed to"
+                                               " set Power - errCode [%d]!\n",
+                                               __func__, status);
+                               return status;
+                       }
+               }
+               status = cx231xx_set_decoder_video_input(dev,
+                                                        INPUT(input)->type,
+                                                        INPUT(input)->vmux);
+               break;
+       case CX231XX_VMUX_TELEVISION:
+       case CX231XX_VMUX_CABLE:
+               if ((dev->current_pcb_config.type == USB_BUS_POWER) &&
+                   (dev->power_mode != POLARIS_AVMODE_ANALOGT_TV)) {
+                       /* Tuner */
+                       status = cx231xx_set_power_mode(dev,
+                                               POLARIS_AVMODE_ANALOGT_TV);
+                       if (status < 0) {
+                               cx231xx_errdev("%s: set_power_mode:Failed"
+                                       " to set Power - errCode [%d]!\n",
+                                       __func__, status);
+                               return status;
+                       }
+               }
+               if (dev->tuner_type == TUNER_NXP_TDA18271)
+                       status = cx231xx_set_decoder_video_input(dev,
+                                                       CX231XX_VMUX_TELEVISION,
+                                                       INPUT(input)->vmux);
+               else
+                       status = cx231xx_set_decoder_video_input(dev,
+                                                       CX231XX_VMUX_COMPOSITE1,
+                                                       INPUT(input)->vmux);
+
+               break;
+       default:
+               cx231xx_errdev("%s: set_power_mode : Unknown Input %d !\n",
+                    __func__, INPUT(input)->type);
+               break;
+       }
+
+       /* save the selection */
+       dev->video_input = input;
+
+       return status;
+}
+
+int cx231xx_set_decoder_video_input(struct cx231xx *dev,
+                               u8 pin_type, u8 input)
+{
+       int status = 0;
+       u32 value = 0;
+
+       if (pin_type != dev->video_input) {
+               status = cx231xx_afe_adjust_ref_count(dev, pin_type);
+               if (status < 0) {
+                       cx231xx_errdev("%s: adjust_ref_count :Failed to set"
+                               "AFE input mux - errCode [%d]!\n",
+                               __func__, status);
+                       return status;
+               }
+       }
+
+       /* call afe block to set video inputs */
+       status = cx231xx_afe_set_input_mux(dev, input);
+       if (status < 0) {
+               cx231xx_errdev("%s: set_input_mux :Failed to set"
+                               " AFE input mux - errCode [%d]!\n",
+                               __func__, status);
+               return status;
+       }
+
+       switch (pin_type) {
+       case CX231XX_VMUX_COMPOSITE1:
+               status = vid_blk_read_word(dev, AFE_CTRL, &value);
+               value |= (0 << 13) | (1 << 4);
+               value &= ~(1 << 5);
+
+               /* set [24:23] [22:15] to 0  */
+               value &= (~(0x1ff8000));
+               /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0  */
+               value |= 0x1000000;
+               status = vid_blk_write_word(dev, AFE_CTRL, value);
+
+               status = vid_blk_read_word(dev, OUT_CTRL1, &value);
+               value |= (1 << 7);
+               status = vid_blk_write_word(dev, OUT_CTRL1, value);
+
+               /* Set output mode */
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       OUT_CTRL1,
+                                                       FLD_OUT_MODE,
+                                                       dev->board.output_mode);
+
+               /* Tell DIF object to go to baseband mode  */
+               status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
+               if (status < 0) {
+                       cx231xx_errdev("%s: cx231xx_dif set to By pass"
+                                                  " mode- errCode [%d]!\n",
+                               __func__, status);
+                       return status;
+               }
+
+               /* Read the DFE_CTRL1 register */
+               status = vid_blk_read_word(dev, DFE_CTRL1, &value);
+
+               /* enable the VBI_GATE_EN */
+               value |= FLD_VBI_GATE_EN;
+
+               /* Enable the auto-VGA enable */
+               value |= FLD_VGA_AUTO_EN;
+
+               /* Write it back */
+               status = vid_blk_write_word(dev, DFE_CTRL1, value);
+
+               /* Disable auto config of registers */
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                                       VID_BLK_I2C_ADDRESS,
+                                       MODE_CTRL, FLD_ACFG_DIS,
+                                       cx231xx_set_field(FLD_ACFG_DIS, 1));
+
+               /* Set CVBS input mode */
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                       VID_BLK_I2C_ADDRESS,
+                       MODE_CTRL, FLD_INPUT_MODE,
+                       cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0));
+               break;
+       case CX231XX_VMUX_SVIDEO:
+               /* Disable the use of  DIF */
+
+               status = vid_blk_read_word(dev, AFE_CTRL, &value);
+
+               /* set [24:23] [22:15] to 0 */
+               value &= (~(0x1ff8000));
+               /* set FUNC_MODE[24:23] = 2
+               IF_MOD[22:15] = 0 DCR_BYP_CH2[4:4] = 1; */
+               value |= 0x1000010;
+               status = vid_blk_write_word(dev, AFE_CTRL, value);
+
+               /* Tell DIF object to go to baseband mode */
+               status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
+               if (status < 0) {
+                       cx231xx_errdev("%s: cx231xx_dif set to By pass"
+                                                  " mode- errCode [%d]!\n",
+                               __func__, status);
+                       return status;
+               }
+
+               /* Read the DFE_CTRL1 register */
+               status = vid_blk_read_word(dev, DFE_CTRL1, &value);
+
+               /* enable the VBI_GATE_EN */
+               value |= FLD_VBI_GATE_EN;
+
+               /* Enable the auto-VGA enable */
+               value |= FLD_VGA_AUTO_EN;
+
+               /* Write it back */
+               status = vid_blk_write_word(dev, DFE_CTRL1, value);
+
+               /* Disable auto config of registers  */
+               status =  cx231xx_read_modify_write_i2c_dword(dev,
+                                       VID_BLK_I2C_ADDRESS,
+                                       MODE_CTRL, FLD_ACFG_DIS,
+                                       cx231xx_set_field(FLD_ACFG_DIS, 1));
+
+               /* Set YC input mode */
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                       VID_BLK_I2C_ADDRESS,
+                       MODE_CTRL,
+                       FLD_INPUT_MODE,
+                       cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_YC_1));
+
+               /* Chroma to ADC2 */
+               status = vid_blk_read_word(dev, AFE_CTRL, &value);
+               value |= FLD_CHROMA_IN_SEL;     /* set the chroma in select */
+
+               /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8)
+                  This sets them to use video
+                  rather than audio.  Only one of the two will be in use. */
+               value &= ~(FLD_VGA_SEL_CH2 | FLD_VGA_SEL_CH3);
+
+               status = vid_blk_write_word(dev, AFE_CTRL, value);
+
+               status = cx231xx_afe_set_mode(dev, AFE_MODE_BASEBAND);
+               break;
+       case CX231XX_VMUX_TELEVISION:
+       case CX231XX_VMUX_CABLE:
+       default:
+               /* TODO: Test if this is also needed for xc2028/xc3028 */
+               if (dev->board.tuner_type == TUNER_XC5000) {
+                       /* Disable the use of  DIF   */
+
+                       status = vid_blk_read_word(dev, AFE_CTRL, &value);
+                       value |= (0 << 13) | (1 << 4);
+                       value &= ~(1 << 5);
+
+                       /* set [24:23] [22:15] to 0 */
+                       value &= (~(0x1FF8000));
+                       /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */
+                       value |= 0x1000000;
+                       status = vid_blk_write_word(dev, AFE_CTRL, value);
+
+                       status = vid_blk_read_word(dev, OUT_CTRL1, &value);
+                       value |= (1 << 7);
+                       status = vid_blk_write_word(dev, OUT_CTRL1, value);
+
+                       /* Set output mode */
+                       status = cx231xx_read_modify_write_i2c_dword(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       OUT_CTRL1, FLD_OUT_MODE,
+                                                       dev->board.output_mode);
+
+                       /* Tell DIF object to go to baseband mode */
+                       status = cx231xx_dif_set_standard(dev,
+                                                         DIF_USE_BASEBAND);
+                       if (status < 0) {
+                               cx231xx_errdev("%s: cx231xx_dif set to By pass"
+                                               " mode- errCode [%d]!\n",
+                                               __func__, status);
+                               return status;
+                       }
+
+                       /* Read the DFE_CTRL1 register */
+                       status = vid_blk_read_word(dev, DFE_CTRL1, &value);
+
+                       /* enable the VBI_GATE_EN */
+                       value |= FLD_VBI_GATE_EN;
+
+                       /* Enable the auto-VGA enable */
+                       value |= FLD_VGA_AUTO_EN;
+
+                       /* Write it back */
+                       status = vid_blk_write_word(dev, DFE_CTRL1, value);
+
+                       /* Disable auto config of registers */
+                       status = cx231xx_read_modify_write_i2c_dword(dev,
+                                       VID_BLK_I2C_ADDRESS,
+                                       MODE_CTRL, FLD_ACFG_DIS,
+                                       cx231xx_set_field(FLD_ACFG_DIS, 1));
+
+                       /* Set CVBS input mode */
+                       status = cx231xx_read_modify_write_i2c_dword(dev,
+                               VID_BLK_I2C_ADDRESS,
+                               MODE_CTRL, FLD_INPUT_MODE,
+                               cx231xx_set_field(FLD_INPUT_MODE,
+                                               INPUT_MODE_CVBS_0));
+               } else {
+                       /* Enable the DIF for the tuner */
+
+                       /* Reinitialize the DIF */
+                       status = cx231xx_dif_set_standard(dev, dev->norm);
+                       if (status < 0) {
+                               cx231xx_errdev("%s: cx231xx_dif set to By pass"
+                                               " mode- errCode [%d]!\n",
+                                               __func__, status);
+                               return status;
+                       }
+
+                       /* Make sure bypass is cleared */
+                       status = vid_blk_read_word(dev, DIF_MISC_CTRL, &value);
+
+                       /* Clear the bypass bit */
+                       value &= ~FLD_DIF_DIF_BYPASS;
+
+                       /* Enable the use of the DIF block */
+                       status = vid_blk_write_word(dev, DIF_MISC_CTRL, value);
+
+                       /* Read the DFE_CTRL1 register */
+                       status = vid_blk_read_word(dev, DFE_CTRL1, &value);
+
+                       /* Disable the VBI_GATE_EN */
+                       value &= ~FLD_VBI_GATE_EN;
+
+                       /* Enable the auto-VGA enable, AGC, and
+                          set the skip count to 2 */
+                       value |= FLD_VGA_AUTO_EN | FLD_AGC_AUTO_EN | 0x00200000;
+
+                       /* Write it back */
+                       status = vid_blk_write_word(dev, DFE_CTRL1, value);
+
+                       /* Wait until AGC locks up */
+                       msleep(1);
+
+                       /* Disable the auto-VGA enable AGC */
+                       value &= ~(FLD_VGA_AUTO_EN);
+
+                       /* Write it back */
+                       status = vid_blk_write_word(dev, DFE_CTRL1, value);
+
+                       /* Enable Polaris B0 AGC output */
+                       status = vid_blk_read_word(dev, PIN_CTRL, &value);
+                       value |= (FLD_OEF_AGC_RF) |
+                                (FLD_OEF_AGC_IFVGA) |
+                                (FLD_OEF_AGC_IF);
+                       status = vid_blk_write_word(dev, PIN_CTRL, value);
+
+                       /* Set output mode */
+                       status = cx231xx_read_modify_write_i2c_dword(dev,
+                                               VID_BLK_I2C_ADDRESS,
+                                               OUT_CTRL1, FLD_OUT_MODE,
+                                               dev->board.output_mode);
+
+                       /* Disable auto config of registers */
+                       status = cx231xx_read_modify_write_i2c_dword(dev,
+                                       VID_BLK_I2C_ADDRESS,
+                                       MODE_CTRL, FLD_ACFG_DIS,
+                                       cx231xx_set_field(FLD_ACFG_DIS, 1));
+
+                       /* Set CVBS input mode */
+                       status = cx231xx_read_modify_write_i2c_dword(dev,
+                               VID_BLK_I2C_ADDRESS,
+                               MODE_CTRL, FLD_INPUT_MODE,
+                               cx231xx_set_field(FLD_INPUT_MODE,
+                                               INPUT_MODE_CVBS_0));
+
+                       /* Set some bits in AFE_CTRL so that channel 2 or 3
+                        * is ready to receive audio */
+                       /* Clear clamp for channels 2 and 3      (bit 16-17) */
+                       /* Clear droop comp                      (bit 19-20) */
+                       /* Set VGA_SEL (for audio control)       (bit 7-8) */
+                       status = vid_blk_read_word(dev, AFE_CTRL, &value);
+
+                       /*Set Func mode:01-DIF 10-baseband 11-YUV*/
+                       value &= (~(FLD_FUNC_MODE));
+                       value |= 0x800000;
+
+                       value |= FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2;
+
+                       status = vid_blk_write_word(dev, AFE_CTRL, value);
+
+                       if (dev->tuner_type == TUNER_NXP_TDA18271) {
+                               status = vid_blk_read_word(dev, PIN_CTRL,
+                                &value);
+                               status = vid_blk_write_word(dev, PIN_CTRL,
+                                (value & 0xFFFFFFEF));
+                       }
+
+                       break;
+
+               }
+               break;
+       }
+
+       /* Set raw VBI mode */
+       status = cx231xx_read_modify_write_i2c_dword(dev,
+                               VID_BLK_I2C_ADDRESS,
+                               OUT_CTRL1, FLD_VBIHACTRAW_EN,
+                               cx231xx_set_field(FLD_VBIHACTRAW_EN, 1));
+
+       status = vid_blk_read_word(dev, OUT_CTRL1, &value);
+       if (value & 0x02) {
+               value |= (1 << 19);
+               status = vid_blk_write_word(dev, OUT_CTRL1, value);
+       }
+
+       return status;
+}
+
+void cx231xx_enable656(struct cx231xx *dev)
+{
+       u8 temp = 0;
+       /*enable TS1 data[0:7] as output to export 656*/
+
+       vid_blk_write_byte(dev, TS1_PIN_CTL0, 0xFF);
+
+       /*enable TS1 clock as output to export 656*/
+
+       vid_blk_read_byte(dev, TS1_PIN_CTL1, &temp);
+       temp = temp|0x04;
+
+       vid_blk_write_byte(dev, TS1_PIN_CTL1, temp);
+}
+EXPORT_SYMBOL_GPL(cx231xx_enable656);
+
+void cx231xx_disable656(struct cx231xx *dev)
+{
+       u8 temp = 0;
+
+       vid_blk_write_byte(dev, TS1_PIN_CTL0, 0x00);
+
+       vid_blk_read_byte(dev, TS1_PIN_CTL1, &temp);
+       temp = temp&0xFB;
+
+       vid_blk_write_byte(dev, TS1_PIN_CTL1, temp);
+}
+EXPORT_SYMBOL_GPL(cx231xx_disable656);
+
+/*
+ * Handle any video-mode specific overrides that are different
+ * on a per video standards basis after touching the MODE_CTRL
+ * register which resets many values for autodetect
+ */
+int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev)
+{
+       int status = 0;
+
+       cx231xx_info("do_mode_ctrl_overrides : 0x%x\n",
+                    (unsigned int)dev->norm);
+
+       /* Change the DFE_CTRL3 bp_percent to fix flagging */
+       status = vid_blk_write_word(dev, DFE_CTRL3, 0xCD3F0280);
+
+       if (dev->norm & (V4L2_STD_NTSC | V4L2_STD_PAL_M)) {
+               cx231xx_info("do_mode_ctrl_overrides NTSC\n");
+
+               /* Move the close caption lines out of active video,
+                  adjust the active video start point */
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       VERT_TIM_CTRL,
+                                                       FLD_VBLANK_CNT, 0x18);
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       VERT_TIM_CTRL,
+                                                       FLD_VACTIVE_CNT,
+                                                       0x1E7000);
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       VERT_TIM_CTRL,
+                                                       FLD_V656BLANK_CNT,
+                                                       0x1C000000);
+
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       HORIZ_TIM_CTRL,
+                                                       FLD_HBLANK_CNT,
+                                                       cx231xx_set_field
+                                                       (FLD_HBLANK_CNT, 0x79));
+
+       } else if (dev->norm & V4L2_STD_SECAM) {
+               cx231xx_info("do_mode_ctrl_overrides SECAM\n");
+               status =  cx231xx_read_modify_write_i2c_dword(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       VERT_TIM_CTRL,
+                                                       FLD_VBLANK_CNT, 0x20);
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       VERT_TIM_CTRL,
+                                                       FLD_VACTIVE_CNT,
+                                                       cx231xx_set_field
+                                                       (FLD_VACTIVE_CNT,
+                                                        0x244));
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       VERT_TIM_CTRL,
+                                                       FLD_V656BLANK_CNT,
+                                                       cx231xx_set_field
+                                                       (FLD_V656BLANK_CNT,
+                                                       0x24));
+               /* Adjust the active video horizontal start point */
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       HORIZ_TIM_CTRL,
+                                                       FLD_HBLANK_CNT,
+                                                       cx231xx_set_field
+                                                       (FLD_HBLANK_CNT, 0x85));
+       } else {
+               cx231xx_info("do_mode_ctrl_overrides PAL\n");
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       VERT_TIM_CTRL,
+                                                       FLD_VBLANK_CNT, 0x20);
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       VERT_TIM_CTRL,
+                                                       FLD_VACTIVE_CNT,
+                                                       cx231xx_set_field
+                                                       (FLD_VACTIVE_CNT,
+                                                        0x244));
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       VERT_TIM_CTRL,
+                                                       FLD_V656BLANK_CNT,
+                                                       cx231xx_set_field
+                                                       (FLD_V656BLANK_CNT,
+                                                       0x24));
+               /* Adjust the active video horizontal start point */
+               status = cx231xx_read_modify_write_i2c_dword(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       HORIZ_TIM_CTRL,
+                                                       FLD_HBLANK_CNT,
+                                                       cx231xx_set_field
+                                                       (FLD_HBLANK_CNT, 0x85));
+
+       }
+
+       return status;
+}
+
+int cx231xx_unmute_audio(struct cx231xx *dev)
+{
+       return vid_blk_write_byte(dev, PATH1_VOL_CTL, 0x24);
+}
+EXPORT_SYMBOL_GPL(cx231xx_unmute_audio);
+
+int stopAudioFirmware(struct cx231xx *dev)
+{
+       return vid_blk_write_byte(dev, DL_CTL_CONTROL, 0x03);
+}
+
+int restartAudioFirmware(struct cx231xx *dev)
+{
+       return vid_blk_write_byte(dev, DL_CTL_CONTROL, 0x13);
+}
+
+int cx231xx_set_audio_input(struct cx231xx *dev, u8 input)
+{
+       int status = 0;
+       enum AUDIO_INPUT ainput = AUDIO_INPUT_LINE;
+
+       switch (INPUT(input)->amux) {
+       case CX231XX_AMUX_VIDEO:
+               ainput = AUDIO_INPUT_TUNER_TV;
+               break;
+       case CX231XX_AMUX_LINE_IN:
+               status = cx231xx_i2s_blk_set_audio_input(dev, input);
+               ainput = AUDIO_INPUT_LINE;
+               break;
+       default:
+               break;
+       }
+
+       status = cx231xx_set_audio_decoder_input(dev, ainput);
+
+       return status;
+}
+
+int cx231xx_set_audio_decoder_input(struct cx231xx *dev,
+                                   enum AUDIO_INPUT audio_input)
+{
+       u32 dwval;
+       int status;
+       u8 gen_ctrl;
+       u32 value = 0;
+
+       /* Put it in soft reset   */
+       status = vid_blk_read_byte(dev, GENERAL_CTL, &gen_ctrl);
+       gen_ctrl |= 1;
+       status = vid_blk_write_byte(dev, GENERAL_CTL, gen_ctrl);
+
+       switch (audio_input) {
+       case AUDIO_INPUT_LINE:
+               /* setup AUD_IO control from Merlin paralle output */
+               value = cx231xx_set_field(FLD_AUD_CHAN1_SRC,
+                                         AUD_CHAN_SRC_PARALLEL);
+               status = vid_blk_write_word(dev, AUD_IO_CTRL, value);
+
+               /* setup input to Merlin, SRC2 connect to AC97
+                  bypass upsample-by-2, slave mode, sony mode, left justify
+                  adr 091c, dat 01000000 */
+               status = vid_blk_read_word(dev, AC97_CTL, &dwval);
+
+               status = vid_blk_write_word(dev, AC97_CTL,
+                                          (dwval | FLD_AC97_UP2X_BYPASS));
+
+               /* select the parallel1 and SRC3 */
+               status = vid_blk_write_word(dev, BAND_OUT_SEL,
+                               cx231xx_set_field(FLD_SRC3_IN_SEL, 0x0) |
+                               cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x0) |
+                               cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x0));
+
+               /* unmute all, AC97 in, independence mode
+                  adr 08d0, data 0x00063073 */
+               status = vid_blk_write_word(dev, DL_CTL, 0x3000001);
+               status = vid_blk_write_word(dev, PATH1_CTL1, 0x00063073);
+
+               /* set AVC maximum threshold, adr 08d4, dat ffff0024 */
+               status = vid_blk_read_word(dev, PATH1_VOL_CTL, &dwval);
+               status = vid_blk_write_word(dev, PATH1_VOL_CTL,
+                                          (dwval | FLD_PATH1_AVC_THRESHOLD));
+
+               /* set SC maximum threshold, adr 08ec, dat ffffb3a3 */
+               status = vid_blk_read_word(dev, PATH1_SC_CTL, &dwval);
+               status = vid_blk_write_word(dev, PATH1_SC_CTL,
+                                          (dwval | FLD_PATH1_SC_THRESHOLD));
+               break;
+
+       case AUDIO_INPUT_TUNER_TV:
+       default:
+               status = stopAudioFirmware(dev);
+               /* Setup SRC sources and clocks */
+               status = vid_blk_write_word(dev, BAND_OUT_SEL,
+                       cx231xx_set_field(FLD_SRC6_IN_SEL, 0x00)         |
+                       cx231xx_set_field(FLD_SRC6_CLK_SEL, 0x01)        |
+                       cx231xx_set_field(FLD_SRC5_IN_SEL, 0x00)         |
+                       cx231xx_set_field(FLD_SRC5_CLK_SEL, 0x02)        |
+                       cx231xx_set_field(FLD_SRC4_IN_SEL, 0x02)         |
+                       cx231xx_set_field(FLD_SRC4_CLK_SEL, 0x03)        |
+                       cx231xx_set_field(FLD_SRC3_IN_SEL, 0x00)         |
+                       cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x00)        |
+                       cx231xx_set_field(FLD_BASEBAND_BYPASS_CTL, 0x00) |
+                       cx231xx_set_field(FLD_AC97_SRC_SEL, 0x03)        |
+                       cx231xx_set_field(FLD_I2S_SRC_SEL, 0x00)         |
+                       cx231xx_set_field(FLD_PARALLEL2_SRC_SEL, 0x02)   |
+                       cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x01));
+
+               /* Setup the AUD_IO control */
+               status = vid_blk_write_word(dev, AUD_IO_CTRL,
+                       cx231xx_set_field(FLD_I2S_PORT_DIR, 0x00)  |
+                       cx231xx_set_field(FLD_I2S_OUT_SRC, 0x00)   |
+                       cx231xx_set_field(FLD_AUD_CHAN3_SRC, 0x00) |
+                       cx231xx_set_field(FLD_AUD_CHAN2_SRC, 0x00) |
+                       cx231xx_set_field(FLD_AUD_CHAN1_SRC, 0x03));
+
+               status = vid_blk_write_word(dev, PATH1_CTL1, 0x1F063870);
+
+               /* setAudioStandard(_audio_standard); */
+               status = vid_blk_write_word(dev, PATH1_CTL1, 0x00063870);
+
+               status = restartAudioFirmware(dev);
+
+               switch (dev->board.tuner_type) {
+               case TUNER_XC5000:
+                       /* SIF passthrough at 28.6363 MHz sample rate */
+                       status = cx231xx_read_modify_write_i2c_dword(dev,
+                                       VID_BLK_I2C_ADDRESS,
+                                       CHIP_CTRL,
+                                       FLD_SIF_EN,
+                                       cx231xx_set_field(FLD_SIF_EN, 1));
+                       break;
+               case TUNER_NXP_TDA18271:
+                       /* Normal mode: SIF passthrough at 14.32 MHz */
+                       status = cx231xx_read_modify_write_i2c_dword(dev,
+                                       VID_BLK_I2C_ADDRESS,
+                                       CHIP_CTRL,
+                                       FLD_SIF_EN,
+                                       cx231xx_set_field(FLD_SIF_EN, 0));
+                       break;
+               default:
+                       /* This is just a casual suggestion to people adding
+                          new boards in case they use a tuner type we don't
+                          currently know about */
+                       printk(KERN_INFO "Unknown tuner type configuring SIF");
+                       break;
+               }
+               break;
+
+       case AUDIO_INPUT_TUNER_FM:
+               /*  use SIF for FM radio
+                  setupFM();
+                  setAudioStandard(_audio_standard);
+                */
+               break;
+
+       case AUDIO_INPUT_MUTE:
+               status = vid_blk_write_word(dev, PATH1_CTL1, 0x1F011012);
+               break;
+       }
+
+       /* Take it out of soft reset */
+       status = vid_blk_read_byte(dev, GENERAL_CTL, &gen_ctrl);
+       gen_ctrl &= ~1;
+       status = vid_blk_write_byte(dev, GENERAL_CTL, gen_ctrl);
+
+       return status;
+}
+
+/******************************************************************************
+ *                    C H I P Specific  C O N T R O L   functions             *
+ ******************************************************************************/
+int cx231xx_init_ctrl_pin_status(struct cx231xx *dev)
+{
+       u32 value;
+       int status = 0;
+
+       status = vid_blk_read_word(dev, PIN_CTRL, &value);
+       value |= (~dev->board.ctl_pin_status_mask);
+       status = vid_blk_write_word(dev, PIN_CTRL, value);
+
+       return status;
+}
+
+int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev,
+                                             u8 analog_or_digital)
+{
+       int status = 0;
+
+       /* first set the direction to output */
+       status = cx231xx_set_gpio_direction(dev,
+                                           dev->board.
+                                           agc_analog_digital_select_gpio, 1);
+
+       /* 0 - demod ; 1 - Analog mode */
+       status = cx231xx_set_gpio_value(dev,
+                                  dev->board.agc_analog_digital_select_gpio,
+                                  analog_or_digital);
+
+       return status;
+}
+
+int cx231xx_enable_i2c_port_3(struct cx231xx *dev, bool is_port_3)
+{
+       u8 value[4] = { 0, 0, 0, 0 };
+       int status = 0;
+       bool current_is_port_3;
+
+       if (dev->board.dont_use_port_3)
+               is_port_3 = false;
+       status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER,
+                                      PWR_CTL_EN, value, 4);
+       if (status < 0)
+               return status;
+
+       current_is_port_3 = value[0] & I2C_DEMOD_EN ? true : false;
+
+       /* Just return, if already using the right port */
+       if (current_is_port_3 == is_port_3)
+               return 0;
+
+       if (is_port_3)
+               value[0] |= I2C_DEMOD_EN;
+       else
+               value[0] &= ~I2C_DEMOD_EN;
+
+       cx231xx_info("Changing the i2c master port to %d\n",
+                    is_port_3 ?  3 : 1);
+
+       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                       PWR_CTL_EN, value, 4);
+
+       return status;
+
+}
+EXPORT_SYMBOL_GPL(cx231xx_enable_i2c_port_3);
+
+void update_HH_register_after_set_DIF(struct cx231xx *dev)
+{
+/*
+       u8 status = 0;
+       u32 value = 0;
+
+       vid_blk_write_word(dev, PIN_CTRL, 0xA0FFF82F);
+       vid_blk_write_word(dev, DIF_MISC_CTRL, 0x0A203F11);
+       vid_blk_write_word(dev, DIF_SRC_PHASE_INC, 0x1BEFBF06);
+
+       status = vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
+       vid_blk_write_word(dev, AFE_CTRL_C2HH_SRC_CTRL, 0x4485D390);
+       status = vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL,  &value);
+*/
+}
+
+void cx231xx_dump_HH_reg(struct cx231xx *dev)
+{
+       u32 value = 0;
+       u16  i = 0;
+
+       value = 0x45005390;
+       vid_blk_write_word(dev, 0x104, value);
+
+       for (i = 0x100; i < 0x140; i++) {
+               vid_blk_read_word(dev, i, &value);
+               cx231xx_info("reg0x%x=0x%x\n", i, value);
+               i = i+3;
+       }
+
+       for (i = 0x300; i < 0x400; i++) {
+               vid_blk_read_word(dev, i, &value);
+               cx231xx_info("reg0x%x=0x%x\n", i, value);
+               i = i+3;
+       }
+
+       for (i = 0x400; i < 0x440; i++) {
+               vid_blk_read_word(dev, i,  &value);
+               cx231xx_info("reg0x%x=0x%x\n", i, value);
+               i = i+3;
+       }
+
+       vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
+       cx231xx_info("AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
+       vid_blk_write_word(dev, AFE_CTRL_C2HH_SRC_CTRL, 0x4485D390);
+       vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
+       cx231xx_info("AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
+}
+
+void cx231xx_dump_SC_reg(struct cx231xx *dev)
+{
+       u8 value[4] = { 0, 0, 0, 0 };
+       cx231xx_info("cx231xx_dump_SC_reg!\n");
+
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", BOARD_CFG_STAT, value[0],
+                                value[1], value[2], value[3]);
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS_MODE_REG,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS_MODE_REG, value[0],
+                                value[1], value[2], value[3]);
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS1_CFG_REG,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_CFG_REG, value[0],
+                                value[1], value[2], value[3]);
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS1_LENGTH_REG,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_LENGTH_REG, value[0],
+                                value[1], value[2], value[3]);
+
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS2_CFG_REG,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_CFG_REG, value[0],
+                                value[1], value[2], value[3]);
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS2_LENGTH_REG,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_LENGTH_REG, value[0],
+                                value[1], value[2], value[3]);
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", EP_MODE_SET, value[0],
+                                value[1], value[2], value[3]);
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN1,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN1, value[0],
+                                value[1], value[2], value[3]);
+
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN2,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN2, value[0],
+                                value[1], value[2], value[3]);
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN3,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN3, value[0],
+                                value[1], value[2], value[3]);
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK0,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK0, value[0],
+                                value[1], value[2], value[3]);
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK1,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK1, value[0],
+                                value[1], value[2], value[3]);
+
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK2,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK2, value[0],
+                                value[1], value[2], value[3]);
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_GAIN,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_GAIN, value[0],
+                                value[1], value[2], value[3]);
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_CAR_REG,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_CAR_REG, value[0],
+                                value[1], value[2], value[3]);
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_OT_CFG1,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG1, value[0],
+                                value[1], value[2], value[3]);
+
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_OT_CFG2,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG2, value[0],
+                                value[1], value[2], value[3]);
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
+                                value, 4);
+       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN, value[0],
+                                value[1], value[2], value[3]);
+
+
+}
+
+void cx231xx_Setup_AFE_for_LowIF(struct cx231xx *dev)
+
+{
+       u8 value = 0;
+
+       afe_read_byte(dev, ADC_STATUS2_CH3, &value);
+       value = (value & 0xFE)|0x01;
+       afe_write_byte(dev, ADC_STATUS2_CH3, value);
+
+       afe_read_byte(dev, ADC_STATUS2_CH3, &value);
+       value = (value & 0xFE)|0x00;
+       afe_write_byte(dev, ADC_STATUS2_CH3, value);
+
+
+/*
+       config colibri to lo-if mode
+
+       FIXME: ntf_mode = 2'b00 by default. But set 0x1 would reduce
+               the diff IF input by half,
+
+               for low-if agc defect
+*/
+
+       afe_read_byte(dev, ADC_NTF_PRECLMP_EN_CH3, &value);
+       value = (value & 0xFC)|0x00;
+       afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH3, value);
+
+       afe_read_byte(dev, ADC_INPUT_CH3, &value);
+       value = (value & 0xF9)|0x02;
+       afe_write_byte(dev, ADC_INPUT_CH3, value);
+
+       afe_read_byte(dev, ADC_FB_FRCRST_CH3, &value);
+       value = (value & 0xFB)|0x04;
+       afe_write_byte(dev, ADC_FB_FRCRST_CH3, value);
+
+       afe_read_byte(dev, ADC_DCSERVO_DEM_CH3, &value);
+       value = (value & 0xFC)|0x03;
+       afe_write_byte(dev, ADC_DCSERVO_DEM_CH3, value);
+
+       afe_read_byte(dev, ADC_CTRL_DAC1_CH3, &value);
+       value = (value & 0xFB)|0x04;
+       afe_write_byte(dev, ADC_CTRL_DAC1_CH3, value);
+
+       afe_read_byte(dev, ADC_CTRL_DAC23_CH3, &value);
+       value = (value & 0xF8)|0x06;
+       afe_write_byte(dev, ADC_CTRL_DAC23_CH3, value);
+
+       afe_read_byte(dev, ADC_CTRL_DAC23_CH3, &value);
+       value = (value & 0x8F)|0x40;
+       afe_write_byte(dev, ADC_CTRL_DAC23_CH3, value);
+
+       afe_read_byte(dev, ADC_PWRDN_CLAMP_CH3, &value);
+       value = (value & 0xDF)|0x20;
+       afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, value);
+}
+
+void cx231xx_set_Colibri_For_LowIF(struct cx231xx *dev, u32 if_freq,
+                u8 spectral_invert, u32 mode)
+{
+       u32 colibri_carrier_offset = 0;
+       u32 func_mode = 0x01; /* Device has a DIF if this function is called */
+       u32 standard = 0;
+       u8 value[4] = { 0, 0, 0, 0 };
+
+       cx231xx_info("Enter cx231xx_set_Colibri_For_LowIF()\n");
+       value[0] = (u8) 0x6F;
+       value[1] = (u8) 0x6F;
+       value[2] = (u8) 0x6F;
+       value[3] = (u8) 0x6F;
+       cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                       PWR_CTL_EN, value, 4);
+
+       /*Set colibri for low IF*/
+       cx231xx_afe_set_mode(dev, AFE_MODE_LOW_IF);
+
+       /* Set C2HH for low IF operation.*/
+       standard = dev->norm;
+       cx231xx_dif_configure_C2HH_for_low_IF(dev, dev->active_mode,
+                                                      func_mode, standard);
+
+       /* Get colibri offsets.*/
+       colibri_carrier_offset = cx231xx_Get_Colibri_CarrierOffset(mode,
+                                                                  standard);
+
+       cx231xx_info("colibri_carrier_offset=%d, standard=0x%x\n",
+                    colibri_carrier_offset, standard);
+
+       /* Set the band Pass filter for DIF*/
+       cx231xx_set_DIF_bandpass(dev, (if_freq+colibri_carrier_offset),
+                                spectral_invert, mode);
+}
+
+u32 cx231xx_Get_Colibri_CarrierOffset(u32 mode, u32 standerd)
+{
+       u32 colibri_carrier_offset = 0;
+
+       if (mode == TUNER_MODE_FM_RADIO) {
+               colibri_carrier_offset = 1100000;
+       } else if (standerd & (V4L2_STD_MN | V4L2_STD_NTSC_M_JP)) {
+               colibri_carrier_offset = 4832000;  /*4.83MHz    */
+       } else if (standerd & (V4L2_STD_PAL_B | V4L2_STD_PAL_G)) {
+               colibri_carrier_offset = 2700000;  /*2.70MHz       */
+       } else if (standerd & (V4L2_STD_PAL_D | V4L2_STD_PAL_I
+                       | V4L2_STD_SECAM)) {
+               colibri_carrier_offset = 2100000;  /*2.10MHz    */
+       }
+
+       return colibri_carrier_offset;
+}
+
+void cx231xx_set_DIF_bandpass(struct cx231xx *dev, u32 if_freq,
+                u8 spectral_invert, u32 mode)
+{
+       unsigned long pll_freq_word;
+       u32 dif_misc_ctrl_value = 0;
+       u64 pll_freq_u64 = 0;
+       u32 i = 0;
+
+       cx231xx_info("if_freq=%d;spectral_invert=0x%x;mode=0x%x\n",
+                        if_freq, spectral_invert, mode);
+
+
+       if (mode == TUNER_MODE_FM_RADIO) {
+               pll_freq_word = 0x905A1CAC;
+               vid_blk_write_word(dev, DIF_PLL_FREQ_WORD,  pll_freq_word);
+
+       } else /*KSPROPERTY_TUNER_MODE_TV*/{
+               /* Calculate the PLL frequency word based on the adjusted if_freq*/
+               pll_freq_word = if_freq;
+               pll_freq_u64 = (u64)pll_freq_word << 28L;
+               do_div(pll_freq_u64, 50000000);
+               pll_freq_word = (u32)pll_freq_u64;
+               /*pll_freq_word = 0x3463497;*/
+               vid_blk_write_word(dev, DIF_PLL_FREQ_WORD,  pll_freq_word);
+
+       if (spectral_invert) {
+               if_freq -= 400000;
+               /* Enable Spectral Invert*/
+               vid_blk_read_word(dev, DIF_MISC_CTRL,
+                                       &dif_misc_ctrl_value);
+               dif_misc_ctrl_value = dif_misc_ctrl_value | 0x00200000;
+               vid_blk_write_word(dev, DIF_MISC_CTRL,
+                                       dif_misc_ctrl_value);
+       } else {
+               if_freq += 400000;
+               /* Disable Spectral Invert*/
+               vid_blk_read_word(dev, DIF_MISC_CTRL,
+                                       &dif_misc_ctrl_value);
+               dif_misc_ctrl_value = dif_misc_ctrl_value & 0xFFDFFFFF;
+               vid_blk_write_word(dev, DIF_MISC_CTRL,
+                                       dif_misc_ctrl_value);
+       }
+
+       if_freq = (if_freq/100000)*100000;
+
+       if (if_freq < 3000000)
+               if_freq = 3000000;
+
+       if (if_freq > 16000000)
+               if_freq = 16000000;
+       }
+
+       cx231xx_info("Enter IF=%zd\n",
+                       ARRAY_SIZE(Dif_set_array));
+       for (i = 0; i < ARRAY_SIZE(Dif_set_array); i++) {
+               if (Dif_set_array[i].if_freq == if_freq) {
+                       vid_blk_write_word(dev,
+                       Dif_set_array[i].register_address, Dif_set_array[i].value);
+               }
+       }
+}
+
+/******************************************************************************
+ *                 D I F - B L O C K    C O N T R O L   functions             *
+ ******************************************************************************/
+int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode,
+                                         u32 function_mode, u32 standard)
+{
+       int status = 0;
+
+
+       if (mode == V4L2_TUNER_RADIO) {
+               /* C2HH */
+               /* lo if big signal */
+               status = cx231xx_reg_mask_write(dev,
+                               VID_BLK_I2C_ADDRESS, 32,
+                               AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);
+               /* FUNC_MODE = DIF */
+               status = cx231xx_reg_mask_write(dev,
+                               VID_BLK_I2C_ADDRESS, 32,
+                               AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode);
+               /* IF_MODE */
+               status = cx231xx_reg_mask_write(dev,
+                               VID_BLK_I2C_ADDRESS, 32,
+                               AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xFF);
+               /* no inv */
+               status = cx231xx_reg_mask_write(dev,
+                               VID_BLK_I2C_ADDRESS, 32,
+                               AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);
+       } else if (standard != DIF_USE_BASEBAND) {
+               if (standard & V4L2_STD_MN) {
+                       /* lo if big signal */
+                       status = cx231xx_reg_mask_write(dev,
+                                       VID_BLK_I2C_ADDRESS, 32,
+                                       AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);
+                       /* FUNC_MODE = DIF */
+                       status = cx231xx_reg_mask_write(dev,
+                                       VID_BLK_I2C_ADDRESS, 32,
+                                       AFE_CTRL_C2HH_SRC_CTRL, 23, 24,
+                                       function_mode);
+                       /* IF_MODE */
+                       status = cx231xx_reg_mask_write(dev,
+                                       VID_BLK_I2C_ADDRESS, 32,
+                                       AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xb);
+                       /* no inv */
+                       status = cx231xx_reg_mask_write(dev,
+                                       VID_BLK_I2C_ADDRESS, 32,
+                                       AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);
+                       /* 0x124, AUD_CHAN1_SRC = 0x3 */
+                       status = cx231xx_reg_mask_write(dev,
+                                       VID_BLK_I2C_ADDRESS, 32,
+                                       AUD_IO_CTRL, 0, 31, 0x00000003);
+               } else if ((standard == V4L2_STD_PAL_I) |
+                       (standard & V4L2_STD_PAL_D) |
+                       (standard & V4L2_STD_SECAM)) {
+                       /* C2HH setup */
+                       /* lo if big signal */
+                       status = cx231xx_reg_mask_write(dev,
+                                       VID_BLK_I2C_ADDRESS, 32,
+                                       AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);
+                       /* FUNC_MODE = DIF */
+                       status = cx231xx_reg_mask_write(dev,
+                                       VID_BLK_I2C_ADDRESS, 32,
+                                       AFE_CTRL_C2HH_SRC_CTRL, 23, 24,
+                                       function_mode);
+                       /* IF_MODE */
+                       status = cx231xx_reg_mask_write(dev,
+                                       VID_BLK_I2C_ADDRESS, 32,
+                                       AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF);
+                       /* no inv */
+                       status = cx231xx_reg_mask_write(dev,
+                                       VID_BLK_I2C_ADDRESS, 32,
+                                       AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);
+               } else {
+                       /* default PAL BG */
+                       /* C2HH setup */
+                       /* lo if big signal */
+                       status = cx231xx_reg_mask_write(dev,
+                                       VID_BLK_I2C_ADDRESS, 32,
+                                       AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);
+                       /* FUNC_MODE = DIF */
+                       status = cx231xx_reg_mask_write(dev,
+                                       VID_BLK_I2C_ADDRESS, 32,
+                                       AFE_CTRL_C2HH_SRC_CTRL, 23, 24,
+                                       function_mode);
+                       /* IF_MODE */
+                       status = cx231xx_reg_mask_write(dev,
+                                       VID_BLK_I2C_ADDRESS, 32,
+                                       AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE);
+                       /* no inv */
+                       status = cx231xx_reg_mask_write(dev,
+                                       VID_BLK_I2C_ADDRESS, 32,
+                                       AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);
+               }
+       }
+
+       return status;
+}
+
+int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard)
+{
+       int status = 0;
+       u32 dif_misc_ctrl_value = 0;
+       u32 func_mode = 0;
+
+       cx231xx_info("%s: setStandard to %x\n", __func__, standard);
+
+       status = vid_blk_read_word(dev, DIF_MISC_CTRL, &dif_misc_ctrl_value);
+       if (standard != DIF_USE_BASEBAND)
+               dev->norm = standard;
+
+       switch (dev->model) {
+       case CX231XX_BOARD_CNXT_CARRAERA:
+       case CX231XX_BOARD_CNXT_RDE_250:
+       case CX231XX_BOARD_CNXT_SHELBY:
+       case CX231XX_BOARD_CNXT_RDU_250:
+       case CX231XX_BOARD_CNXT_VIDEO_GRABBER:
+       case CX231XX_BOARD_HAUPPAUGE_EXETER:
+               func_mode = 0x03;
+               break;
+       case CX231XX_BOARD_CNXT_RDE_253S:
+       case CX231XX_BOARD_CNXT_RDU_253S:
+       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
+       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
+               func_mode = 0x01;
+               break;
+       default:
+               func_mode = 0x01;
+       }
+
+       status = cx231xx_dif_configure_C2HH_for_low_IF(dev, dev->active_mode,
+                                                 func_mode, standard);
+
+       if (standard == DIF_USE_BASEBAND) {     /* base band */
+               /* There is a different SRC_PHASE_INC value
+                  for baseband vs. DIF */
+               status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC, 0xDF7DF83);
+               status = vid_blk_read_word(dev, DIF_MISC_CTRL,
+                                               &dif_misc_ctrl_value);
+               dif_misc_ctrl_value |= FLD_DIF_DIF_BYPASS;
+               status = vid_blk_write_word(dev, DIF_MISC_CTRL,
+                                               dif_misc_ctrl_value);
+       } else if (standard & V4L2_STD_PAL_D) {
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL3, 0, 31, 0x00008800);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_IF_REF, 0, 31, 0x444C1380);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_IF, 0, 31, 0xDA302600);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_INT, 0, 31, 0xDA261700);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_RF, 0, 31, 0xDA262600);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_IF_INT_CURRENT, 0, 31,
+                                          0x26001700);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_RF_CURRENT, 0, 31,
+                                          0x00002660);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_VIDEO_AGC_CTRL, 0, 31,
+                                          0x72500800);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_VID_AUD_OVERRIDE, 0, 31,
+                                          0x27000100);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AV_SEP_CTRL, 0, 31, 0x3F3934EA);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_COMP_FLT_CTRL, 0, 31,
+                                          0x00000000);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_SRC_PHASE_INC, 0, 31,
+                                          0x1befbf06);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_SRC_GAIN_CONTROL, 0, 31,
+                                          0x000035e8);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_RPT_VARIANCE, 0, 31, 0x00000000);
+               /* Save the Spec Inversion value */
+               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+               dif_misc_ctrl_value |= 0x3a023F11;
+       } else if (standard & V4L2_STD_PAL_I) {
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL3, 0, 31, 0x00008800);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_IF_REF, 0, 31, 0x444C1380);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_IF, 0, 31, 0xDA302600);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_INT, 0, 31, 0xDA261700);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_RF, 0, 31, 0xDA262600);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_IF_INT_CURRENT, 0, 31,
+                                          0x26001700);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_RF_CURRENT, 0, 31,
+                                          0x00002660);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_VIDEO_AGC_CTRL, 0, 31,
+                                          0x72500800);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_VID_AUD_OVERRIDE, 0, 31,
+                                          0x27000100);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AV_SEP_CTRL, 0, 31, 0x5F39A934);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_COMP_FLT_CTRL, 0, 31,
+                                          0x00000000);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_SRC_PHASE_INC, 0, 31,
+                                          0x1befbf06);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_SRC_GAIN_CONTROL, 0, 31,
+                                          0x000035e8);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_RPT_VARIANCE, 0, 31, 0x00000000);
+               /* Save the Spec Inversion value */
+               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+               dif_misc_ctrl_value |= 0x3a033F11;
+       } else if (standard & V4L2_STD_PAL_M) {
+               /* improved Low Frequency Phase Noise */
+               status = vid_blk_write_word(dev, DIF_PLL_CTRL, 0xFF01FF0C);
+               status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xbd038c85);
+               status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1db4640a);
+               status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800);
+               status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C1380);
+               status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT,
+                                               0x26001700);
+               status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT,
+                                               0x00002660);
+               status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL,
+                                               0x72500800);
+               status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE,
+                                               0x27000100);
+               status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL, 0x012c405d);
+               status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL,
+                                               0x009f50c1);
+               status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC,
+                                               0x1befbf06);
+               status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL,
+                                               0x000035e8);
+               status = vid_blk_write_word(dev, DIF_SOFT_RST_CTRL_REVB,
+                                               0x00000000);
+               /* Save the Spec Inversion value */
+               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+               dif_misc_ctrl_value |= 0x3A0A3F10;
+       } else if (standard & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) {
+               /* improved Low Frequency Phase Noise */
+               status = vid_blk_write_word(dev, DIF_PLL_CTRL, 0xFF01FF0C);
+               status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xbd038c85);
+               status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1db4640a);
+               status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800);
+               status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C1380);
+               status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT,
+                                               0x26001700);
+               status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT,
+                                               0x00002660);
+               status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL,
+                                               0x72500800);
+               status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE,
+                                               0x27000100);
+               status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL,
+                                               0x012c405d);
+               status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL,
+                                               0x009f50c1);
+               status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC,
+                                               0x1befbf06);
+               status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL,
+                                               0x000035e8);
+               status = vid_blk_write_word(dev, DIF_SOFT_RST_CTRL_REVB,
+                                               0x00000000);
+               /* Save the Spec Inversion value */
+               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+               dif_misc_ctrl_value = 0x3A093F10;
+       } else if (standard &
+                 (V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G |
+                  V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1)) {
+
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL3, 0, 31, 0x00008800);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_IF_REF, 0, 31, 0x888C0380);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_IF, 0, 31, 0xe0262600);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_INT, 0, 31, 0xc2171700);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_RF, 0, 31, 0xc2262600);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_IF_INT_CURRENT, 0, 31,
+                                          0x26001700);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_RF_CURRENT, 0, 31,
+                                          0x00002660);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_VID_AUD_OVERRIDE, 0, 31,
+                                          0x27000100);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_COMP_FLT_CTRL, 0, 31,
+                                          0x00000000);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_SRC_PHASE_INC, 0, 31,
+                                          0x1befbf06);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_SRC_GAIN_CONTROL, 0, 31,
+                                          0x000035e8);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_RPT_VARIANCE, 0, 31, 0x00000000);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_VIDEO_AGC_CTRL, 0, 31,
+                                          0xf4000000);
+
+               /* Save the Spec Inversion value */
+               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+               dif_misc_ctrl_value |= 0x3a023F11;
+       } else if (standard & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) {
+               /* Is it SECAM_L1? */
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL3, 0, 31, 0x00008800);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_IF_REF, 0, 31, 0x888C0380);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_IF, 0, 31, 0xe0262600);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_INT, 0, 31, 0xc2171700);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_RF, 0, 31, 0xc2262600);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_IF_INT_CURRENT, 0, 31,
+                                          0x26001700);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_RF_CURRENT, 0, 31,
+                                          0x00002660);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_VID_AUD_OVERRIDE, 0, 31,
+                                          0x27000100);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_COMP_FLT_CTRL, 0, 31,
+                                          0x00000000);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_SRC_PHASE_INC, 0, 31,
+                                          0x1befbf06);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_SRC_GAIN_CONTROL, 0, 31,
+                                          0x000035e8);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_RPT_VARIANCE, 0, 31, 0x00000000);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_VIDEO_AGC_CTRL, 0, 31,
+                                          0xf2560000);
+
+               /* Save the Spec Inversion value */
+               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+               dif_misc_ctrl_value |= 0x3a023F11;
+
+       } else if (standard & V4L2_STD_NTSC_M) {
+               /* V4L2_STD_NTSC_M (75 IRE Setup) Or
+                  V4L2_STD_NTSC_M_JP (Japan,  0 IRE Setup) */
+
+               /* For NTSC the centre frequency of video coming out of
+                  sidewinder is around 7.1MHz or 3.6MHz depending on the
+                  spectral inversion. so for a non spectrally inverted channel
+                  the pll freq word is 0x03420c49
+                */
+
+               status = vid_blk_write_word(dev, DIF_PLL_CTRL, 0x6503BC0C);
+               status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xBD038C85);
+               status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1DB4640A);
+               status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800);
+               status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C0380);
+               status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT,
+                                               0x26001700);
+               status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT,
+                                               0x00002660);
+               status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL,
+                                               0x04000800);
+               status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE,
+                                               0x27000100);
+               status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL, 0x01296e1f);
+
+               status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL,
+                                               0x009f50c1);
+               status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC,
+                                               0x1befbf06);
+               status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL,
+                                               0x000035e8);
+
+               status = vid_blk_write_word(dev, DIF_AGC_CTRL_IF, 0xC2262600);
+               status = vid_blk_write_word(dev, DIF_AGC_CTRL_INT,
+                                               0xC2262600);
+               status = vid_blk_write_word(dev, DIF_AGC_CTRL_RF, 0xC2262600);
+
+               /* Save the Spec Inversion value */
+               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+               dif_misc_ctrl_value |= 0x3a003F10;
+       } else {
+               /* default PAL BG */
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_PLL_CTRL3, 0, 31, 0x00008800);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_IF_REF, 0, 31, 0x444C1380);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_IF, 0, 31, 0xDA302600);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_INT, 0, 31, 0xDA261700);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_CTRL_RF, 0, 31, 0xDA262600);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_IF_INT_CURRENT, 0, 31,
+                                          0x26001700);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AGC_RF_CURRENT, 0, 31,
+                                          0x00002660);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_VIDEO_AGC_CTRL, 0, 31,
+                                          0x72500800);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_VID_AUD_OVERRIDE, 0, 31,
+                                          0x27000100);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_AV_SEP_CTRL, 0, 31, 0x3F3530EC);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_COMP_FLT_CTRL, 0, 31,
+                                          0x00A653A8);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_SRC_PHASE_INC, 0, 31,
+                                          0x1befbf06);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_SRC_GAIN_CONTROL, 0, 31,
+                                          0x000035e8);
+               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
+                                          DIF_RPT_VARIANCE, 0, 31, 0x00000000);
+               /* Save the Spec Inversion value */
+               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
+               dif_misc_ctrl_value |= 0x3a013F11;
+       }
+
+       /* The AGC values should be the same for all standards,
+          AUD_SRC_SEL[19] should always be disabled    */
+       dif_misc_ctrl_value &= ~FLD_DIF_AUD_SRC_SEL;
+
+       /* It is still possible to get Set Standard calls even when we
+          are in FM mode.
+          This is done to override the value for FM. */
+       if (dev->active_mode == V4L2_TUNER_RADIO)
+               dif_misc_ctrl_value = 0x7a080000;
+
+       /* Write the calculated value for misc ontrol register      */
+       status = vid_blk_write_word(dev, DIF_MISC_CTRL, dif_misc_ctrl_value);
+
+       return status;
+}
+
+int cx231xx_tuner_pre_channel_change(struct cx231xx *dev)
+{
+       int status = 0;
+       u32 dwval;
+
+       /* Set the RF and IF k_agc values to 3 */
+       status = vid_blk_read_word(dev, DIF_AGC_IF_REF, &dwval);
+       dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF);
+       dwval |= 0x33000000;
+
+       status = vid_blk_write_word(dev, DIF_AGC_IF_REF, dwval);
+
+       return status;
+}
+
+int cx231xx_tuner_post_channel_change(struct cx231xx *dev)
+{
+       int status = 0;
+       u32 dwval;
+       cx231xx_info("cx231xx_tuner_post_channel_change  dev->tuner_type =0%d\n",
+                    dev->tuner_type);
+       /* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for
+        * SECAM L/B/D standards */
+       status = vid_blk_read_word(dev, DIF_AGC_IF_REF, &dwval);
+       dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF);
+
+       if (dev->norm & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_B |
+                        V4L2_STD_SECAM_D)) {
+                       if (dev->tuner_type == TUNER_NXP_TDA18271) {
+                               dwval &= ~FLD_DIF_IF_REF;
+                               dwval |= 0x88000300;
+                       } else
+                               dwval |= 0x88000000;
+               } else {
+                       if (dev->tuner_type == TUNER_NXP_TDA18271) {
+                               dwval &= ~FLD_DIF_IF_REF;
+                               dwval |= 0xCC000300;
+                       } else
+                               dwval |= 0x44000000;
+               }
+
+       status = vid_blk_write_word(dev, DIF_AGC_IF_REF, dwval);
+
+       return status;
+}
+
+/******************************************************************************
+ *                 I 2 S - B L O C K    C O N T R O L   functions            *
+ ******************************************************************************/
+int cx231xx_i2s_blk_initialize(struct cx231xx *dev)
+{
+       int status = 0;
+       u32 value;
+
+       status = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+                                      CH_PWR_CTRL1, 1, &value, 1);
+       /* enables clock to delta-sigma and decimation filter */
+       value |= 0x80;
+       status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+                                       CH_PWR_CTRL1, 1, value, 1);
+       /* power up all channel */
+       status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+                                       CH_PWR_CTRL2, 1, 0x00, 1);
+
+       return status;
+}
+
+int cx231xx_i2s_blk_update_power_control(struct cx231xx *dev,
+                                       enum AV_MODE avmode)
+{
+       int status = 0;
+       u32 value = 0;
+
+       if (avmode != POLARIS_AVMODE_ENXTERNAL_AV) {
+               status = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+                                         CH_PWR_CTRL2, 1, &value, 1);
+               value |= 0xfe;
+               status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+                                               CH_PWR_CTRL2, 1, value, 1);
+       } else {
+               status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+                                               CH_PWR_CTRL2, 1, 0x00, 1);
+       }
+
+       return status;
+}
+
+/* set i2s_blk for audio input types */
+int cx231xx_i2s_blk_set_audio_input(struct cx231xx *dev, u8 audio_input)
+{
+       int status = 0;
+
+       switch (audio_input) {
+       case CX231XX_AMUX_LINE_IN:
+               status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+                                               CH_PWR_CTRL2, 1, 0x00, 1);
+               status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+                                               CH_PWR_CTRL1, 1, 0x80, 1);
+               break;
+       case CX231XX_AMUX_VIDEO:
+       default:
+               break;
+       }
+
+       dev->ctl_ainput = audio_input;
+
+       return status;
+}
+
+/******************************************************************************
+ *                  P O W E R      C O N T R O L   functions                  *
+ ******************************************************************************/
+int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode)
+{
+       u8 value[4] = { 0, 0, 0, 0 };
+       u32 tmp = 0;
+       int status = 0;
+
+       if (dev->power_mode != mode)
+               dev->power_mode = mode;
+       else {
+               cx231xx_info(" setPowerMode::mode = %d, No Change req.\n",
+                            mode);
+               return 0;
+       }
+
+       status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value,
+                                      4);
+       if (status < 0)
+               return status;
+
+       tmp = *((u32 *) value);
+
+       switch (mode) {
+       case POLARIS_AVMODE_ENXTERNAL_AV:
+
+               tmp &= (~PWR_MODE_MASK);
+
+               tmp |= PWR_AV_EN;
+               value[0] = (u8) tmp;
+               value[1] = (u8) (tmp >> 8);
+               value[2] = (u8) (tmp >> 16);
+               value[3] = (u8) (tmp >> 24);
+               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                               PWR_CTL_EN, value, 4);
+               msleep(PWR_SLEEP_INTERVAL);
+
+               tmp |= PWR_ISO_EN;
+               value[0] = (u8) tmp;
+               value[1] = (u8) (tmp >> 8);
+               value[2] = (u8) (tmp >> 16);
+               value[3] = (u8) (tmp >> 24);
+               status =
+                   cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN,
+                                          value, 4);
+               msleep(PWR_SLEEP_INTERVAL);
+
+               tmp |= POLARIS_AVMODE_ENXTERNAL_AV;
+               value[0] = (u8) tmp;
+               value[1] = (u8) (tmp >> 8);
+               value[2] = (u8) (tmp >> 16);
+               value[3] = (u8) (tmp >> 24);
+               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                               PWR_CTL_EN, value, 4);
+
+               /* reset state of xceive tuner */
+               dev->xc_fw_load_done = 0;
+               break;
+
+       case POLARIS_AVMODE_ANALOGT_TV:
+
+               tmp |= PWR_DEMOD_EN;
+               tmp |= (I2C_DEMOD_EN);
+               value[0] = (u8) tmp;
+               value[1] = (u8) (tmp >> 8);
+               value[2] = (u8) (tmp >> 16);
+               value[3] = (u8) (tmp >> 24);
+               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                               PWR_CTL_EN, value, 4);
+               msleep(PWR_SLEEP_INTERVAL);
+
+               if (!(tmp & PWR_TUNER_EN)) {
+                       tmp |= (PWR_TUNER_EN);
+                       value[0] = (u8) tmp;
+                       value[1] = (u8) (tmp >> 8);
+                       value[2] = (u8) (tmp >> 16);
+                       value[3] = (u8) (tmp >> 24);
+                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                                       PWR_CTL_EN, value, 4);
+                       msleep(PWR_SLEEP_INTERVAL);
+               }
+
+               if (!(tmp & PWR_AV_EN)) {
+                       tmp |= PWR_AV_EN;
+                       value[0] = (u8) tmp;
+                       value[1] = (u8) (tmp >> 8);
+                       value[2] = (u8) (tmp >> 16);
+                       value[3] = (u8) (tmp >> 24);
+                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                                       PWR_CTL_EN, value, 4);
+                       msleep(PWR_SLEEP_INTERVAL);
+               }
+               if (!(tmp & PWR_ISO_EN)) {
+                       tmp |= PWR_ISO_EN;
+                       value[0] = (u8) tmp;
+                       value[1] = (u8) (tmp >> 8);
+                       value[2] = (u8) (tmp >> 16);
+                       value[3] = (u8) (tmp >> 24);
+                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                                       PWR_CTL_EN, value, 4);
+                       msleep(PWR_SLEEP_INTERVAL);
+               }
+
+               if (!(tmp & POLARIS_AVMODE_ANALOGT_TV)) {
+                       tmp |= POLARIS_AVMODE_ANALOGT_TV;
+                       value[0] = (u8) tmp;
+                       value[1] = (u8) (tmp >> 8);
+                       value[2] = (u8) (tmp >> 16);
+                       value[3] = (u8) (tmp >> 24);
+                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                                       PWR_CTL_EN, value, 4);
+                       msleep(PWR_SLEEP_INTERVAL);
+               }
+
+               if (dev->board.tuner_type != TUNER_ABSENT) {
+                       /* Enable tuner */
+                       cx231xx_enable_i2c_port_3(dev, true);
+
+                       /* reset the Tuner */
+                       if (dev->board.tuner_gpio)
+                               cx231xx_gpio_set(dev, dev->board.tuner_gpio);
+
+                       if (dev->cx231xx_reset_analog_tuner)
+                               dev->cx231xx_reset_analog_tuner(dev);
+               }
+
+               break;
+
+       case POLARIS_AVMODE_DIGITAL:
+               if (!(tmp & PWR_TUNER_EN)) {
+                       tmp |= (PWR_TUNER_EN);
+                       value[0] = (u8) tmp;
+                       value[1] = (u8) (tmp >> 8);
+                       value[2] = (u8) (tmp >> 16);
+                       value[3] = (u8) (tmp >> 24);
+                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                                       PWR_CTL_EN, value, 4);
+                       msleep(PWR_SLEEP_INTERVAL);
+               }
+               if (!(tmp & PWR_AV_EN)) {
+                       tmp |= PWR_AV_EN;
+                       value[0] = (u8) tmp;
+                       value[1] = (u8) (tmp >> 8);
+                       value[2] = (u8) (tmp >> 16);
+                       value[3] = (u8) (tmp >> 24);
+                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                                       PWR_CTL_EN, value, 4);
+                       msleep(PWR_SLEEP_INTERVAL);
+               }
+               if (!(tmp & PWR_ISO_EN)) {
+                       tmp |= PWR_ISO_EN;
+                       value[0] = (u8) tmp;
+                       value[1] = (u8) (tmp >> 8);
+                       value[2] = (u8) (tmp >> 16);
+                       value[3] = (u8) (tmp >> 24);
+                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                                       PWR_CTL_EN, value, 4);
+                       msleep(PWR_SLEEP_INTERVAL);
+               }
+
+               tmp &= (~PWR_AV_MODE);
+               tmp |= POLARIS_AVMODE_DIGITAL | I2C_DEMOD_EN;
+               value[0] = (u8) tmp;
+               value[1] = (u8) (tmp >> 8);
+               value[2] = (u8) (tmp >> 16);
+               value[3] = (u8) (tmp >> 24);
+               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                               PWR_CTL_EN, value, 4);
+               msleep(PWR_SLEEP_INTERVAL);
+
+               if (!(tmp & PWR_DEMOD_EN)) {
+                       tmp |= PWR_DEMOD_EN;
+                       value[0] = (u8) tmp;
+                       value[1] = (u8) (tmp >> 8);
+                       value[2] = (u8) (tmp >> 16);
+                       value[3] = (u8) (tmp >> 24);
+                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                                       PWR_CTL_EN, value, 4);
+                       msleep(PWR_SLEEP_INTERVAL);
+               }
+
+               if (dev->board.tuner_type != TUNER_ABSENT) {
+                       /*
+                        * Enable tuner
+                        *      Hauppauge Exeter seems to need to do something different!
+                        */
+                       if (dev->model == CX231XX_BOARD_HAUPPAUGE_EXETER)
+                               cx231xx_enable_i2c_port_3(dev, false);
+                       else
+                               cx231xx_enable_i2c_port_3(dev, true);
+
+                       /* reset the Tuner */
+                       if (dev->board.tuner_gpio)
+                               cx231xx_gpio_set(dev, dev->board.tuner_gpio);
+
+                       if (dev->cx231xx_reset_analog_tuner)
+                               dev->cx231xx_reset_analog_tuner(dev);
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       msleep(PWR_SLEEP_INTERVAL);
+
+       /* For power saving, only enable Pwr_resetout_n
+          when digital TV is selected. */
+       if (mode == POLARIS_AVMODE_DIGITAL) {
+               tmp |= PWR_RESETOUT_EN;
+               value[0] = (u8) tmp;
+               value[1] = (u8) (tmp >> 8);
+               value[2] = (u8) (tmp >> 16);
+               value[3] = (u8) (tmp >> 24);
+               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                               PWR_CTL_EN, value, 4);
+               msleep(PWR_SLEEP_INTERVAL);
+       }
+
+       /* update power control for afe */
+       status = cx231xx_afe_update_power_control(dev, mode);
+
+       /* update power control for i2s_blk */
+       status = cx231xx_i2s_blk_update_power_control(dev, mode);
+
+       status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value,
+                                      4);
+
+       return status;
+}
+
+int cx231xx_power_suspend(struct cx231xx *dev)
+{
+       u8 value[4] = { 0, 0, 0, 0 };
+       u32 tmp = 0;
+       int status = 0;
+
+       status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
+                                      value, 4);
+       if (status > 0)
+               return status;
+
+       tmp = *((u32 *) value);
+       tmp &= (~PWR_MODE_MASK);
+
+       value[0] = (u8) tmp;
+       value[1] = (u8) (tmp >> 8);
+       value[2] = (u8) (tmp >> 16);
+       value[3] = (u8) (tmp >> 24);
+       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN,
+                                       value, 4);
+
+       return status;
+}
+
+/******************************************************************************
+ *                  S T R E A M    C O N T R O L   functions                  *
+ ******************************************************************************/
+int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask)
+{
+       u8 value[4] = { 0x0, 0x0, 0x0, 0x0 };
+       u32 tmp = 0;
+       int status = 0;
+
+       cx231xx_info("cx231xx_start_stream():: ep_mask = %x\n", ep_mask);
+       status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET,
+                                      value, 4);
+       if (status < 0)
+               return status;
+
+       tmp = *((u32 *) value);
+       tmp |= ep_mask;
+       value[0] = (u8) tmp;
+       value[1] = (u8) (tmp >> 8);
+       value[2] = (u8) (tmp >> 16);
+       value[3] = (u8) (tmp >> 24);
+
+       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, EP_MODE_SET,
+                                       value, 4);
+
+       return status;
+}
+
+int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask)
+{
+       u8 value[4] = { 0x0, 0x0, 0x0, 0x0 };
+       u32 tmp = 0;
+       int status = 0;
+
+       cx231xx_info("cx231xx_stop_stream():: ep_mask = %x\n", ep_mask);
+       status =
+           cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET, value, 4);
+       if (status < 0)
+               return status;
+
+       tmp = *((u32 *) value);
+       tmp &= (~ep_mask);
+       value[0] = (u8) tmp;
+       value[1] = (u8) (tmp >> 8);
+       value[2] = (u8) (tmp >> 16);
+       value[3] = (u8) (tmp >> 24);
+
+       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, EP_MODE_SET,
+                                       value, 4);
+
+       return status;
+}
+
+int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type)
+{
+       int status = 0;
+       u32 value = 0;
+       u8 val[4] = { 0, 0, 0, 0 };
+
+       if (dev->udev->speed == USB_SPEED_HIGH) {
+               switch (media_type) {
+               case Audio:
+                       cx231xx_info("%s: Audio enter HANC\n", __func__);
+                       status =
+                           cx231xx_mode_register(dev, TS_MODE_REG, 0x9300);
+                       break;
+
+               case Vbi:
+                       cx231xx_info("%s: set vanc registers\n", __func__);
+                       status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300);
+                       break;
+
+               case Sliced_cc:
+                       cx231xx_info("%s: set hanc registers\n", __func__);
+                       status =
+                           cx231xx_mode_register(dev, TS_MODE_REG, 0x1300);
+                       break;
+
+               case Raw_Video:
+                       cx231xx_info("%s: set video registers\n", __func__);
+                       status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
+                       break;
+
+               case TS1_serial_mode:
+                       cx231xx_info("%s: set ts1 registers", __func__);
+
+               if (dev->board.has_417) {
+                       cx231xx_info(" MPEG\n");
+                       value &= 0xFFFFFFFC;
+                       value |= 0x3;
+
+                       status = cx231xx_mode_register(dev, TS_MODE_REG, value);
+
+                       val[0] = 0x04;
+                       val[1] = 0xA3;
+                       val[2] = 0x3B;
+                       val[3] = 0x00;
+                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                TS1_CFG_REG, val, 4);
+
+                       val[0] = 0x00;
+                       val[1] = 0x08;
+                       val[2] = 0x00;
+                       val[3] = 0x08;
+                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                TS1_LENGTH_REG, val, 4);
+
+               } else {
+                       cx231xx_info(" BDA\n");
+                       status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101);
+                       status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x010);
+               }
+                       break;
+
+               case TS1_parallel_mode:
+                       cx231xx_info("%s: set ts1 parallel mode registers\n",
+                                    __func__);
+                       status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
+                       status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400);
+                       break;
+               }
+       } else {
+               status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101);
+       }
+
+       return status;
+}
+
+int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type)
+{
+       int rc = -1;
+       u32 ep_mask = -1;
+       struct pcb_config *pcb_config;
+
+       /* get EP for media type */
+       pcb_config = (struct pcb_config *)&dev->current_pcb_config;
+
+       if (pcb_config->config_num) {
+               switch (media_type) {
+               case Raw_Video:
+                       ep_mask = ENABLE_EP4;   /* ep4  [00:1000] */
+                       break;
+               case Audio:
+                       ep_mask = ENABLE_EP3;   /* ep3  [00:0100] */
+                       break;
+               case Vbi:
+                       ep_mask = ENABLE_EP5;   /* ep5 [01:0000] */
+                       break;
+               case Sliced_cc:
+                       ep_mask = ENABLE_EP6;   /* ep6 [10:0000] */
+                       break;
+               case TS1_serial_mode:
+               case TS1_parallel_mode:
+                       ep_mask = ENABLE_EP1;   /* ep1 [00:0001] */
+                       break;
+               case TS2:
+                       ep_mask = ENABLE_EP2;   /* ep2 [00:0010] */
+                       break;
+               }
+       }
+
+       if (start) {
+               rc = cx231xx_initialize_stream_xfer(dev, media_type);
+
+               if (rc < 0)
+                       return rc;
+
+               /* enable video capture */
+               if (ep_mask > 0)
+                       rc = cx231xx_start_stream(dev, ep_mask);
+       } else {
+               /* disable video capture */
+               if (ep_mask > 0)
+                       rc = cx231xx_stop_stream(dev, ep_mask);
+       }
+
+       if (dev->mode == CX231XX_ANALOG_MODE)
+               ;/* do any in Analog mode */
+       else
+               ;/* do any in digital mode */
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(cx231xx_capture_start);
+
+/*****************************************************************************
+*                   G P I O   B I T control functions                        *
+******************************************************************************/
+int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val)
+{
+       int status = 0;
+
+       status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 0);
+
+       return status;
+}
+
+int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val)
+{
+       int status = 0;
+
+       status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 1);
+
+       return status;
+}
+
+/*
+* cx231xx_set_gpio_direction
+*      Sets the direction of the GPIO pin to input or output
+*
+* Parameters :
+*      pin_number : The GPIO Pin number to program the direction for
+*                   from 0 to 31
+*      pin_value : The Direction of the GPIO Pin under reference.
+*                      0 = Input direction
+*                      1 = Output direction
+*/
+int cx231xx_set_gpio_direction(struct cx231xx *dev,
+                              int pin_number, int pin_value)
+{
+       int status = 0;
+       u32 value = 0;
+
+       /* Check for valid pin_number - if 32 , bail out */
+       if (pin_number >= 32)
+               return -EINVAL;
+
+       /* input */
+       if (pin_value == 0)
+               value = dev->gpio_dir & (~(1 << pin_number));   /* clear */
+       else
+               value = dev->gpio_dir | (1 << pin_number);
+
+       status = cx231xx_set_gpio_bit(dev, value, (u8 *) &dev->gpio_val);
+
+       /* cache the value for future */
+       dev->gpio_dir = value;
+
+       return status;
+}
+
+/*
+* cx231xx_set_gpio_value
+*      Sets the value of the GPIO pin to Logic high or low. The Pin under
+*      reference should ALREADY BE SET IN OUTPUT MODE !!!!!!!!!
+*
+* Parameters :
+*      pin_number : The GPIO Pin number to program the direction for
+*      pin_value : The value of the GPIO Pin under reference.
+*                      0 = set it to 0
+*                      1 = set it to 1
+*/
+int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value)
+{
+       int status = 0;
+       u32 value = 0;
+
+       /* Check for valid pin_number - if 0xFF , bail out */
+       if (pin_number >= 32)
+               return -EINVAL;
+
+       /* first do a sanity check - if the Pin is not output, make it output */
+       if ((dev->gpio_dir & (1 << pin_number)) == 0x00) {
+               /* It was in input mode */
+               value = dev->gpio_dir | (1 << pin_number);
+               dev->gpio_dir = value;
+               status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
+                                             (u8 *) &dev->gpio_val);
+               value = 0;
+       }
+
+       if (pin_value == 0)
+               value = dev->gpio_val & (~(1 << pin_number));
+       else
+               value = dev->gpio_val | (1 << pin_number);
+
+       /* store the value */
+       dev->gpio_val = value;
+
+       /* toggle bit0 of GP_IO */
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+
+       return status;
+}
+
+/*****************************************************************************
+*                      G P I O I2C related functions                         *
+******************************************************************************/
+int cx231xx_gpio_i2c_start(struct cx231xx *dev)
+{
+       int status = 0;
+
+       /* set SCL to output 1 ; set SDA to output 1 */
+       dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio;
+       dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio;
+       dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
+       dev->gpio_val |= 1 << dev->board.tuner_sda_gpio;
+
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+       if (status < 0)
+               return -EINVAL;
+
+       /* set SCL to output 1; set SDA to output 0 */
+       dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
+       dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
+
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+       if (status < 0)
+               return -EINVAL;
+
+       /* set SCL to output 0; set SDA to output 0      */
+       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
+       dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
+
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+       if (status < 0)
+               return -EINVAL;
+
+       return status;
+}
+
+int cx231xx_gpio_i2c_end(struct cx231xx *dev)
+{
+       int status = 0;
+
+       /* set SCL to output 0; set SDA to output 0      */
+       dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio;
+       dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio;
+
+       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
+       dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
+
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+       if (status < 0)
+               return -EINVAL;
+
+       /* set SCL to output 1; set SDA to output 0      */
+       dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
+       dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
+
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+       if (status < 0)
+               return -EINVAL;
+
+       /* set SCL to input ,release SCL cable control
+          set SDA to input ,release SDA cable control */
+       dev->gpio_dir &= ~(1 << dev->board.tuner_scl_gpio);
+       dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio);
+
+       status =
+           cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+       if (status < 0)
+               return -EINVAL;
+
+       return status;
+}
+
+int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data)
+{
+       int status = 0;
+       u8 i;
+
+       /* set SCL to output ; set SDA to output */
+       dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio;
+       dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio;
+
+       for (i = 0; i < 8; i++) {
+               if (((data << i) & 0x80) == 0) {
+                       /* set SCL to output 0; set SDA to output 0     */
+                       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
+                       dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
+                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
+                                                     (u8 *)&dev->gpio_val);
+
+                       /* set SCL to output 1; set SDA to output 0     */
+                       dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
+                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
+                                                     (u8 *)&dev->gpio_val);
+
+                       /* set SCL to output 0; set SDA to output 0     */
+                       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
+                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
+                                                     (u8 *)&dev->gpio_val);
+               } else {
+                       /* set SCL to output 0; set SDA to output 1     */
+                       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
+                       dev->gpio_val |= 1 << dev->board.tuner_sda_gpio;
+                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
+                                                     (u8 *)&dev->gpio_val);
+
+                       /* set SCL to output 1; set SDA to output 1     */
+                       dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
+                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
+                                                     (u8 *)&dev->gpio_val);
+
+                       /* set SCL to output 0; set SDA to output 1     */
+                       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
+                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
+                                                     (u8 *)&dev->gpio_val);
+               }
+       }
+       return status;
+}
+
+int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf)
+{
+       u8 value = 0;
+       int status = 0;
+       u32 gpio_logic_value = 0;
+       u8 i;
+
+       /* read byte */
+       for (i = 0; i < 8; i++) {       /* send write I2c addr */
+
+               /* set SCL to output 0; set SDA to input */
+               dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
+               status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
+                                             (u8 *)&dev->gpio_val);
+
+               /* set SCL to output 1; set SDA to input */
+               dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
+               status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
+                                             (u8 *)&dev->gpio_val);
+
+               /* get SDA data bit */
+               gpio_logic_value = dev->gpio_val;
+               status = cx231xx_get_gpio_bit(dev, dev->gpio_dir,
+                                             (u8 *)&dev->gpio_val);
+               if ((dev->gpio_val & (1 << dev->board.tuner_sda_gpio)) != 0)
+                       value |= (1 << (8 - i - 1));
+
+               dev->gpio_val = gpio_logic_value;
+       }
+
+       /* set SCL to output 0,finish the read latest SCL signal.
+          !!!set SDA to input, never to modify SDA direction at
+          the same times */
+       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+
+       /* store the value */
+       *buf = value & 0xff;
+
+       return status;
+}
+
+int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev)
+{
+       int status = 0;
+       u32 gpio_logic_value = 0;
+       int nCnt = 10;
+       int nInit = nCnt;
+
+       /* clock stretch; set SCL to input; set SDA to input;
+          get SCL value till SCL = 1 */
+       dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio);
+       dev->gpio_dir &= ~(1 << dev->board.tuner_scl_gpio);
+
+       gpio_logic_value = dev->gpio_val;
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+
+       do {
+               msleep(2);
+               status = cx231xx_get_gpio_bit(dev, dev->gpio_dir,
+                                             (u8 *)&dev->gpio_val);
+               nCnt--;
+       } while (((dev->gpio_val &
+                         (1 << dev->board.tuner_scl_gpio)) == 0) &&
+                        (nCnt > 0));
+
+       if (nCnt == 0)
+               cx231xx_info("No ACK after %d msec -GPIO I2C failed!",
+                            nInit * 10);
+
+       /*
+        * readAck
+        * through clock stretch, slave has given a SCL signal,
+        * so the SDA data can be directly read.
+        */
+       status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+
+       if ((dev->gpio_val & 1 << dev->board.tuner_sda_gpio) == 0) {
+               dev->gpio_val = gpio_logic_value;
+               dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
+               status = 0;
+       } else {
+               dev->gpio_val = gpio_logic_value;
+               dev->gpio_val |= (1 << dev->board.tuner_sda_gpio);
+       }
+
+       /* read SDA end, set the SCL to output 0, after this operation,
+          SDA direction can be changed. */
+       dev->gpio_val = gpio_logic_value;
+       dev->gpio_dir |= (1 << dev->board.tuner_scl_gpio);
+       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+
+       return status;
+}
+
+int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev)
+{
+       int status = 0;
+
+       /* set SDA to ouput */
+       dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio;
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+
+       /* set SCL = 0 (output); set SDA = 0 (output) */
+       dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
+       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+
+       /* set SCL = 1 (output); set SDA = 0 (output) */
+       dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+
+       /* set SCL = 0 (output); set SDA = 0 (output) */
+       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+
+       /* set SDA to input,and then the slave will read data from SDA. */
+       dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio);
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+
+       return status;
+}
+
+int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev)
+{
+       int status = 0;
+
+       /* set scl to output ; set sda to input */
+       dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio;
+       dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio);
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+
+       /* set scl to output 0; set sda to input */
+       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+
+       /* set scl to output 1; set sda to input */
+       dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
+       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
+
+       return status;
+}
+
+/*****************************************************************************
+*                      G P I O I2C related functions                         *
+******************************************************************************/
+/* cx231xx_gpio_i2c_read
+ * Function to read data from gpio based I2C interface
+ */
+int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len)
+{
+       int status = 0;
+       int i = 0;
+
+       /* get the lock */
+       mutex_lock(&dev->gpio_i2c_lock);
+
+       /* start */
+       status = cx231xx_gpio_i2c_start(dev);
+
+       /* write dev_addr */
+       status = cx231xx_gpio_i2c_write_byte(dev, (dev_addr << 1) + 1);
+
+       /* readAck */
+       status = cx231xx_gpio_i2c_read_ack(dev);
+
+       /* read data */
+       for (i = 0; i < len; i++) {
+               /* read data */
+               buf[i] = 0;
+               status = cx231xx_gpio_i2c_read_byte(dev, &buf[i]);
+
+               if ((i + 1) != len) {
+                       /* only do write ack if we more length */
+                       status = cx231xx_gpio_i2c_write_ack(dev);
+               }
+       }
+
+       /* write NAK - inform reads are complete */
+       status = cx231xx_gpio_i2c_write_nak(dev);
+
+       /* write end */
+       status = cx231xx_gpio_i2c_end(dev);
+
+       /* release the lock */
+       mutex_unlock(&dev->gpio_i2c_lock);
+
+       return status;
+}
+
+/* cx231xx_gpio_i2c_write
+ * Function to write data to gpio based I2C interface
+ */
+int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len)
+{
+       int i = 0;
+
+       /* get the lock */
+       mutex_lock(&dev->gpio_i2c_lock);
+
+       /* start */
+       cx231xx_gpio_i2c_start(dev);
+
+       /* write dev_addr */
+       cx231xx_gpio_i2c_write_byte(dev, dev_addr << 1);
+
+       /* read Ack */
+       cx231xx_gpio_i2c_read_ack(dev);
+
+       for (i = 0; i < len; i++) {
+               /* Write data */
+               cx231xx_gpio_i2c_write_byte(dev, buf[i]);
+
+               /* read Ack */
+               cx231xx_gpio_i2c_read_ack(dev);
+       }
+
+       /* write End */
+       cx231xx_gpio_i2c_end(dev);
+
+       /* release the lock */
+       mutex_unlock(&dev->gpio_i2c_lock);
+
+       return 0;
+}
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c
new file mode 100644 (file)
index 0000000..02d4d36
--- /dev/null
@@ -0,0 +1,1370 @@
+/*
+   cx231xx-cards.c - driver for Conexant Cx23100/101/102
+                               USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+                               Based on em28xx driver
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   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/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/usb.h>
+#include <media/tuner.h>
+#include <media/tveeprom.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+
+#include <media/cx25840.h>
+#include "dvb-usb-ids.h"
+#include "xc5000.h"
+#include "tda18271.h"
+
+#include "cx231xx.h"
+
+static int tuner = -1;
+module_param(tuner, int, 0444);
+MODULE_PARM_DESC(tuner, "tuner type");
+
+static int transfer_mode = 1;
+module_param(transfer_mode, int, 0444);
+MODULE_PARM_DESC(transfer_mode, "transfer mode (1-ISO or 0-BULK)");
+
+static unsigned int disable_ir;
+module_param(disable_ir, int, 0444);
+MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
+
+/* Bitmask marking allocated devices from 0 to CX231XX_MAXBOARDS */
+static unsigned long cx231xx_devused;
+
+/*
+ *  Reset sequences for analog/digital modes
+ */
+
+static struct cx231xx_reg_seq RDE250_XCV_TUNER[] = {
+       {0x03, 0x01, 10},
+       {0x03, 0x00, 30},
+       {0x03, 0x01, 10},
+       {-1, -1, -1},
+};
+
+/*
+ *  Board definitions
+ */
+struct cx231xx_board cx231xx_boards[] = {
+       [CX231XX_BOARD_UNKNOWN] = {
+               .name = "Unknown CX231xx video grabber",
+               .tuner_type = TUNER_ABSENT,
+               .input = {{
+                               .type = CX231XX_VMUX_TELEVISION,
+                               .vmux = CX231XX_VIN_3_1,
+                               .amux = CX231XX_AMUX_VIDEO,
+                               .gpio = NULL,
+                       }, {
+                               .type = CX231XX_VMUX_COMPOSITE1,
+                               .vmux = CX231XX_VIN_2_1,
+                               .amux = CX231XX_AMUX_LINE_IN,
+                               .gpio = NULL,
+                       }, {
+                               .type = CX231XX_VMUX_SVIDEO,
+                               .vmux = CX231XX_VIN_1_1 |
+                                       (CX231XX_VIN_1_2 << 8) |
+                                       CX25840_SVIDEO_ON,
+                               .amux = CX231XX_AMUX_LINE_IN,
+                               .gpio = NULL,
+                       }
+               },
+       },
+       [CX231XX_BOARD_CNXT_CARRAERA] = {
+               .name = "Conexant Hybrid TV - CARRAERA",
+               .tuner_type = TUNER_XC5000,
+               .tuner_addr = 0x61,
+               .tuner_gpio = RDE250_XCV_TUNER,
+               .tuner_sif_gpio = 0x05,
+               .tuner_scl_gpio = 0x1a,
+               .tuner_sda_gpio = 0x1b,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x0c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 1,
+               .demod_i2c_master = 2,
+               .has_dvb = 1,
+               .demod_addr = 0x02,
+               .norm = V4L2_STD_PAL,
+
+               .input = {{
+                               .type = CX231XX_VMUX_TELEVISION,
+                               .vmux = CX231XX_VIN_3_1,
+                               .amux = CX231XX_AMUX_VIDEO,
+                               .gpio = NULL,
+                       }, {
+                               .type = CX231XX_VMUX_COMPOSITE1,
+                               .vmux = CX231XX_VIN_2_1,
+                               .amux = CX231XX_AMUX_LINE_IN,
+                               .gpio = NULL,
+                       }, {
+                               .type = CX231XX_VMUX_SVIDEO,
+                               .vmux = CX231XX_VIN_1_1 |
+                                       (CX231XX_VIN_1_2 << 8) |
+                                       CX25840_SVIDEO_ON,
+                               .amux = CX231XX_AMUX_LINE_IN,
+                               .gpio = NULL,
+                       }
+               },
+       },
+       [CX231XX_BOARD_CNXT_SHELBY] = {
+               .name = "Conexant Hybrid TV - SHELBY",
+               .tuner_type = TUNER_XC5000,
+               .tuner_addr = 0x61,
+               .tuner_gpio = RDE250_XCV_TUNER,
+               .tuner_sif_gpio = 0x05,
+               .tuner_scl_gpio = 0x1a,
+               .tuner_sda_gpio = 0x1b,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x0c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 1,
+               .demod_i2c_master = 2,
+               .has_dvb = 1,
+               .demod_addr = 0x32,
+               .norm = V4L2_STD_NTSC,
+
+               .input = {{
+                               .type = CX231XX_VMUX_TELEVISION,
+                               .vmux = CX231XX_VIN_3_1,
+                               .amux = CX231XX_AMUX_VIDEO,
+                               .gpio = NULL,
+                       }, {
+                               .type = CX231XX_VMUX_COMPOSITE1,
+                               .vmux = CX231XX_VIN_2_1,
+                               .amux = CX231XX_AMUX_LINE_IN,
+                               .gpio = NULL,
+                       }, {
+                               .type = CX231XX_VMUX_SVIDEO,
+                               .vmux = CX231XX_VIN_1_1 |
+                                       (CX231XX_VIN_1_2 << 8) |
+                                       CX25840_SVIDEO_ON,
+                               .amux = CX231XX_AMUX_LINE_IN,
+                               .gpio = NULL,
+                       }
+               },
+       },
+       [CX231XX_BOARD_CNXT_RDE_253S] = {
+               .name = "Conexant Hybrid TV - RDE253S",
+               .tuner_type = TUNER_NXP_TDA18271,
+               .tuner_addr = 0x60,
+               .tuner_gpio = RDE250_XCV_TUNER,
+               .tuner_sif_gpio = 0x05,
+               .tuner_scl_gpio = 0x1a,
+               .tuner_sda_gpio = 0x1b,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x1c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 1,
+               .demod_i2c_master = 2,
+               .has_dvb = 1,
+               .demod_addr = 0x02,
+               .norm = V4L2_STD_PAL,
+
+               .input = {{
+                               .type = CX231XX_VMUX_TELEVISION,
+                               .vmux = CX231XX_VIN_3_1,
+                               .amux = CX231XX_AMUX_VIDEO,
+                               .gpio = NULL,
+                       }, {
+                               .type = CX231XX_VMUX_COMPOSITE1,
+                               .vmux = CX231XX_VIN_2_1,
+                               .amux = CX231XX_AMUX_LINE_IN,
+                               .gpio = NULL,
+                       }, {
+                               .type = CX231XX_VMUX_SVIDEO,
+                               .vmux = CX231XX_VIN_1_1 |
+                                       (CX231XX_VIN_1_2 << 8) |
+                                       CX25840_SVIDEO_ON,
+                               .amux = CX231XX_AMUX_LINE_IN,
+                               .gpio = NULL,
+                       }
+               },
+       },
+
+       [CX231XX_BOARD_CNXT_RDU_253S] = {
+               .name = "Conexant Hybrid TV - RDU253S",
+               .tuner_type = TUNER_NXP_TDA18271,
+               .tuner_addr = 0x60,
+               .tuner_gpio = RDE250_XCV_TUNER,
+               .tuner_sif_gpio = 0x05,
+               .tuner_scl_gpio = 0x1a,
+               .tuner_sda_gpio = 0x1b,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x1c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 1,
+               .demod_i2c_master = 2,
+               .has_dvb = 1,
+               .demod_addr = 0x02,
+               .norm = V4L2_STD_PAL,
+
+               .input = {{
+                               .type = CX231XX_VMUX_TELEVISION,
+                               .vmux = CX231XX_VIN_3_1,
+                               .amux = CX231XX_AMUX_VIDEO,
+                               .gpio = NULL,
+                       }, {
+                               .type = CX231XX_VMUX_COMPOSITE1,
+                               .vmux = CX231XX_VIN_2_1,
+                               .amux = CX231XX_AMUX_LINE_IN,
+                               .gpio = NULL,
+                       }, {
+                               .type = CX231XX_VMUX_SVIDEO,
+                               .vmux = CX231XX_VIN_1_1 |
+                                       (CX231XX_VIN_1_2 << 8) |
+                                       CX25840_SVIDEO_ON,
+                               .amux = CX231XX_AMUX_LINE_IN,
+                               .gpio = NULL,
+                       }
+               },
+       },
+       [CX231XX_BOARD_CNXT_VIDEO_GRABBER] = {
+               .name = "Conexant VIDEO GRABBER",
+               .tuner_type = TUNER_ABSENT,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x1c,
+               .gpio_pin_status_mask = 0x4001000,
+               .norm = V4L2_STD_PAL,
+               .no_alt_vanc = 1,
+               .external_av = 1,
+               .has_417 = 1,
+
+               .input = {{
+                               .type = CX231XX_VMUX_COMPOSITE1,
+                               .vmux = CX231XX_VIN_2_1,
+                               .amux = CX231XX_AMUX_LINE_IN,
+                               .gpio = NULL,
+                       }, {
+                               .type = CX231XX_VMUX_SVIDEO,
+                               .vmux = CX231XX_VIN_1_1 |
+                                       (CX231XX_VIN_1_2 << 8) |
+                                       CX25840_SVIDEO_ON,
+                               .amux = CX231XX_AMUX_LINE_IN,
+                               .gpio = NULL,
+                       }
+               },
+       },
+       [CX231XX_BOARD_CNXT_RDE_250] = {
+               .name = "Conexant Hybrid TV - rde 250",
+               .tuner_type = TUNER_XC5000,
+               .tuner_addr = 0x61,
+               .tuner_gpio = RDE250_XCV_TUNER,
+               .tuner_sif_gpio = 0x05,
+               .tuner_scl_gpio = 0x1a,
+               .tuner_sda_gpio = 0x1b,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x0c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 1,
+               .demod_i2c_master = 2,
+               .has_dvb = 1,
+               .demod_addr = 0x02,
+               .norm = V4L2_STD_PAL,
+
+               .input = {{
+                               .type = CX231XX_VMUX_TELEVISION,
+                               .vmux = CX231XX_VIN_2_1,
+                               .amux = CX231XX_AMUX_VIDEO,
+                               .gpio = NULL,
+                       }
+               },
+       },
+       [CX231XX_BOARD_CNXT_RDU_250] = {
+               .name = "Conexant Hybrid TV - RDU 250",
+               .tuner_type = TUNER_XC5000,
+               .tuner_addr = 0x61,
+               .tuner_gpio = RDE250_XCV_TUNER,
+               .tuner_sif_gpio = 0x05,
+               .tuner_scl_gpio = 0x1a,
+               .tuner_sda_gpio = 0x1b,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x0c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 1,
+               .demod_i2c_master = 2,
+               .has_dvb = 1,
+               .demod_addr = 0x32,
+               .norm = V4L2_STD_NTSC,
+
+               .input = {{
+                               .type = CX231XX_VMUX_TELEVISION,
+                               .vmux = CX231XX_VIN_2_1,
+                               .amux = CX231XX_AMUX_VIDEO,
+                               .gpio = NULL,
+                       }
+               },
+       },
+       [CX231XX_BOARD_HAUPPAUGE_EXETER] = {
+               .name = "Hauppauge EXETER",
+               .tuner_type = TUNER_NXP_TDA18271,
+               .tuner_addr = 0x60,
+               .tuner_gpio = RDE250_XCV_TUNER,
+               .tuner_sif_gpio = 0x05,
+               .tuner_scl_gpio = 0x1a,
+               .tuner_sda_gpio = 0x1b,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x0c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 1,
+               .demod_i2c_master = 2,
+               .has_dvb = 1,
+               .demod_addr = 0x0e,
+               .norm = V4L2_STD_NTSC,
+
+               .input = {{
+                       .type = CX231XX_VMUX_TELEVISION,
+                       .vmux = CX231XX_VIN_3_1,
+                       .amux = CX231XX_AMUX_VIDEO,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_COMPOSITE1,
+                       .vmux = CX231XX_VIN_2_1,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_SVIDEO,
+                       .vmux = CX231XX_VIN_1_1 |
+                               (CX231XX_VIN_1_2 << 8) |
+                               CX25840_SVIDEO_ON,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               } },
+       },
+       [CX231XX_BOARD_HAUPPAUGE_USBLIVE2] = {
+               .name = "Hauppauge USB Live 2",
+               .tuner_type = TUNER_ABSENT,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x0c,
+               .gpio_pin_status_mask = 0x4001000,
+               .norm = V4L2_STD_NTSC,
+               .no_alt_vanc = 1,
+               .external_av = 1,
+               .dont_use_port_3 = 1,
+               .input = {{
+                       .type = CX231XX_VMUX_COMPOSITE1,
+                       .vmux = CX231XX_VIN_2_1,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_SVIDEO,
+                       .vmux = CX231XX_VIN_1_1 |
+                               (CX231XX_VIN_1_2 << 8) |
+                               CX25840_SVIDEO_ON,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               } },
+       },
+       [CX231XX_BOARD_KWORLD_UB430_USB_HYBRID] = {
+               .name = "Kworld UB430 USB Hybrid",
+               .tuner_type = TUNER_NXP_TDA18271,
+               .tuner_addr = 0x60,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x11, /* According with PV cxPolaris.inf file */
+               .tuner_sif_gpio = -1,
+               .tuner_scl_gpio = -1,
+               .tuner_sda_gpio = -1,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 2,
+               .demod_i2c_master = 1,
+               .ir_i2c_master = 2,
+               .has_dvb = 1,
+               .demod_addr = 0x10,
+               .norm = V4L2_STD_PAL_M,
+               .input = {{
+                       .type = CX231XX_VMUX_TELEVISION,
+                       .vmux = CX231XX_VIN_3_1,
+                       .amux = CX231XX_AMUX_VIDEO,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_COMPOSITE1,
+                       .vmux = CX231XX_VIN_2_1,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_SVIDEO,
+                       .vmux = CX231XX_VIN_1_1 |
+                               (CX231XX_VIN_1_2 << 8) |
+                               CX25840_SVIDEO_ON,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               } },
+       },
+       [CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = {
+               .name = "Pixelview PlayTV USB Hybrid",
+               .tuner_type = TUNER_NXP_TDA18271,
+               .tuner_addr = 0x60,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x00, /* According with PV cxPolaris.inf file */
+               .tuner_sif_gpio = -1,
+               .tuner_scl_gpio = -1,
+               .tuner_sda_gpio = -1,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 2,
+               .demod_i2c_master = 1,
+               .ir_i2c_master = 2,
+               .rc_map_name = RC_MAP_PIXELVIEW_002T,
+               .has_dvb = 1,
+               .demod_addr = 0x10,
+               .norm = V4L2_STD_PAL_M,
+               .input = {{
+                       .type = CX231XX_VMUX_TELEVISION,
+                       .vmux = CX231XX_VIN_3_1,
+                       .amux = CX231XX_AMUX_VIDEO,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_COMPOSITE1,
+                       .vmux = CX231XX_VIN_2_1,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_SVIDEO,
+                       .vmux = CX231XX_VIN_1_1 |
+                               (CX231XX_VIN_1_2 << 8) |
+                               CX25840_SVIDEO_ON,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               } },
+       },
+       [CX231XX_BOARD_PV_XCAPTURE_USB] = {
+               .name = "Pixelview Xcapture USB",
+               .tuner_type = TUNER_ABSENT,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x0c,
+               .gpio_pin_status_mask = 0x4001000,
+               .norm = V4L2_STD_NTSC,
+               .no_alt_vanc = 1,
+               .external_av = 1,
+               .dont_use_port_3 = 1,
+
+               .input = {{
+                               .type = CX231XX_VMUX_COMPOSITE1,
+                               .vmux = CX231XX_VIN_2_1,
+                               .amux = CX231XX_AMUX_LINE_IN,
+                               .gpio = NULL,
+                       }, {
+                               .type = CX231XX_VMUX_SVIDEO,
+                               .vmux = CX231XX_VIN_1_1 |
+                                       (CX231XX_VIN_1_2 << 8) |
+                                       CX25840_SVIDEO_ON,
+                               .amux = CX231XX_AMUX_LINE_IN,
+                               .gpio = NULL,
+                       }
+               },
+       },
+
+       [CX231XX_BOARD_ICONBIT_U100] = {
+               .name = "Iconbit Analog Stick U100 FM",
+               .tuner_type = TUNER_ABSENT,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .demod_xfer_mode = 0,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x1C,
+               .gpio_pin_status_mask = 0x4001000,
+
+               .input = {{
+                       .type = CX231XX_VMUX_COMPOSITE1,
+                       .vmux = CX231XX_VIN_2_1,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_SVIDEO,
+                       .vmux = CX231XX_VIN_1_1 |
+                               (CX231XX_VIN_1_2 << 8) |
+                               CX25840_SVIDEO_ON,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               } },
+       },
+       [CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL] = {
+               .name = "Hauppauge WinTV USB2 FM (PAL)",
+               .tuner_type = TUNER_NXP_TDA18271,
+               .tuner_addr = 0x60,
+               .tuner_gpio = RDE250_XCV_TUNER,
+               .tuner_sif_gpio = 0x05,
+               .tuner_scl_gpio = 0x1a,
+               .tuner_sda_gpio = 0x1b,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x0c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 1,
+               .norm = V4L2_STD_PAL,
+
+               .input = {{
+                       .type = CX231XX_VMUX_TELEVISION,
+                       .vmux = CX231XX_VIN_3_1,
+                       .amux = CX231XX_AMUX_VIDEO,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_COMPOSITE1,
+                       .vmux = CX231XX_VIN_2_1,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_SVIDEO,
+                       .vmux = CX231XX_VIN_1_1 |
+                               (CX231XX_VIN_1_2 << 8) |
+                               CX25840_SVIDEO_ON,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               } },
+       },
+       [CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC] = {
+               .name = "Hauppauge WinTV USB2 FM (NTSC)",
+               .tuner_type = TUNER_NXP_TDA18271,
+               .tuner_addr = 0x60,
+               .tuner_gpio = RDE250_XCV_TUNER,
+               .tuner_sif_gpio = 0x05,
+               .tuner_scl_gpio = 0x1a,
+               .tuner_sda_gpio = 0x1b,
+               .decoder = CX231XX_AVDECODER,
+               .output_mode = OUT_MODE_VIP11,
+               .ctl_pin_status_mask = 0xFFFFFFC4,
+               .agc_analog_digital_select_gpio = 0x0c,
+               .gpio_pin_status_mask = 0x4001000,
+               .tuner_i2c_master = 1,
+               .norm = V4L2_STD_NTSC,
+
+               .input = {{
+                       .type = CX231XX_VMUX_TELEVISION,
+                       .vmux = CX231XX_VIN_3_1,
+                       .amux = CX231XX_AMUX_VIDEO,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_COMPOSITE1,
+                       .vmux = CX231XX_VIN_2_1,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               }, {
+                       .type = CX231XX_VMUX_SVIDEO,
+                       .vmux = CX231XX_VIN_1_1 |
+                               (CX231XX_VIN_1_2 << 8) |
+                               CX25840_SVIDEO_ON,
+                       .amux = CX231XX_AMUX_LINE_IN,
+                       .gpio = NULL,
+               } },
+       },
+};
+const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
+
+/* table of devices that work with this driver */
+struct usb_device_id cx231xx_id_table[] = {
+       {USB_DEVICE(0x0572, 0x5A3C),
+        .driver_info = CX231XX_BOARD_UNKNOWN},
+       {USB_DEVICE(0x0572, 0x58A2),
+        .driver_info = CX231XX_BOARD_CNXT_CARRAERA},
+       {USB_DEVICE(0x0572, 0x58A1),
+        .driver_info = CX231XX_BOARD_CNXT_SHELBY},
+       {USB_DEVICE(0x0572, 0x58A4),
+        .driver_info = CX231XX_BOARD_CNXT_RDE_253S},
+       {USB_DEVICE(0x0572, 0x58A5),
+        .driver_info = CX231XX_BOARD_CNXT_RDU_253S},
+       {USB_DEVICE(0x0572, 0x58A6),
+        .driver_info = CX231XX_BOARD_CNXT_VIDEO_GRABBER},
+       {USB_DEVICE(0x0572, 0x589E),
+        .driver_info = CX231XX_BOARD_CNXT_RDE_250},
+       {USB_DEVICE(0x0572, 0x58A0),
+        .driver_info = CX231XX_BOARD_CNXT_RDU_250},
+       {USB_DEVICE(0x2040, 0xb110),
+        .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL},
+       {USB_DEVICE(0x2040, 0xb111),
+        .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC},
+       {USB_DEVICE(0x2040, 0xb120),
+        .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
+       {USB_DEVICE(0x2040, 0xb140),
+        .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
+       {USB_DEVICE(0x2040, 0xc200),
+        .driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2},
+       {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001),
+        .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID},
+       {USB_DEVICE(USB_VID_PIXELVIEW, 0x5014),
+        .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
+       {USB_DEVICE(0x1b80, 0xe424),
+        .driver_info = CX231XX_BOARD_KWORLD_UB430_USB_HYBRID},
+       {USB_DEVICE(0x1f4d, 0x0237),
+        .driver_info = CX231XX_BOARD_ICONBIT_U100},
+       {},
+};
+
+MODULE_DEVICE_TABLE(usb, cx231xx_id_table);
+
+/* cx231xx_tuner_callback
+ * will be used to reset XC5000 tuner using GPIO pin
+ */
+
+int cx231xx_tuner_callback(void *ptr, int component, int command, int arg)
+{
+       int rc = 0;
+       struct cx231xx *dev = ptr;
+
+       if (dev->tuner_type == TUNER_XC5000) {
+               if (command == XC5000_TUNER_RESET) {
+                       cx231xx_info
+                               ("Tuner CB: RESET: cmd %d : tuner type %d \n",
+                                command, dev->tuner_type);
+                       cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
+                                              1);
+                       msleep(10);
+                       cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
+                                              0);
+                       msleep(330);
+                       cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
+                                              1);
+                       msleep(10);
+               }
+       } else if (dev->tuner_type == TUNER_NXP_TDA18271) {
+               switch (command) {
+               case TDA18271_CALLBACK_CMD_AGC_ENABLE:
+                       if (dev->model == CX231XX_BOARD_PV_PLAYTV_USB_HYBRID)
+                               rc = cx231xx_set_agc_analog_digital_mux_select(dev, arg);
+                       break;
+               default:
+                       rc = -EINVAL;
+                       break;
+               }
+       }
+       return rc;
+}
+EXPORT_SYMBOL_GPL(cx231xx_tuner_callback);
+
+void cx231xx_reset_out(struct cx231xx *dev)
+{
+       cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
+       msleep(200);
+       cx231xx_set_gpio_value(dev, CX23417_RESET, 0);
+       msleep(200);
+       cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
+}
+void cx231xx_enable_OSC(struct cx231xx *dev)
+{
+       cx231xx_set_gpio_value(dev, CX23417_OSC_EN, 1);
+}
+void cx231xx_sleep_s5h1432(struct cx231xx *dev)
+{
+       cx231xx_set_gpio_value(dev, SLEEP_S5H1432, 0);
+}
+
+static inline void cx231xx_set_model(struct cx231xx *dev)
+{
+       memcpy(&dev->board, &cx231xx_boards[dev->model], sizeof(dev->board));
+}
+
+/* Since cx231xx_pre_card_setup() requires a proper dev->model,
+ * this won't work for boards with generic PCI IDs
+ */
+void cx231xx_pre_card_setup(struct cx231xx *dev)
+{
+
+       cx231xx_set_model(dev);
+
+       cx231xx_info("Identified as %s (card=%d)\n",
+                    dev->board.name, dev->model);
+
+       /* set the direction for GPIO pins */
+       if (dev->board.tuner_gpio) {
+               cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1);
+               cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1);
+       }
+       if (dev->board.tuner_sif_gpio >= 0)
+               cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1);
+
+       /* request some modules if any required */
+
+       /* set the mode to Analog mode initially */
+       cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
+
+       /* Unlock device */
+       /* cx231xx_set_mode(dev, CX231XX_SUSPEND); */
+
+}
+
+static void cx231xx_config_tuner(struct cx231xx *dev)
+{
+       struct tuner_setup tun_setup;
+       struct v4l2_frequency f;
+
+       if (dev->tuner_type == TUNER_ABSENT)
+               return;
+
+       tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+       tun_setup.type = dev->tuner_type;
+       tun_setup.addr = dev->tuner_addr;
+       tun_setup.tuner_callback = cx231xx_tuner_callback;
+
+       tuner_call(dev, tuner, s_type_addr, &tun_setup);
+
+#if 0
+       if (tun_setup.type == TUNER_XC5000) {
+               static struct xc2028_ctrl ctrl = {
+                       .fname = XC5000_DEFAULT_FIRMWARE,
+                       .max_len = 64,
+                       .demod = 0;
+               };
+               struct v4l2_priv_tun_config cfg = {
+                       .tuner = dev->tuner_type,
+                       .priv = &ctrl,
+               };
+               tuner_call(dev, tuner, s_config, &cfg);
+       }
+#endif
+       /* configure tuner */
+       f.tuner = 0;
+       f.type = V4L2_TUNER_ANALOG_TV;
+       f.frequency = 9076;     /* just a magic number */
+       dev->ctl_freq = f.frequency;
+       call_all(dev, tuner, s_frequency, &f);
+
+}
+
+void cx231xx_card_setup(struct cx231xx *dev)
+{
+
+       cx231xx_set_model(dev);
+
+       dev->tuner_type = cx231xx_boards[dev->model].tuner_type;
+       if (cx231xx_boards[dev->model].tuner_addr)
+               dev->tuner_addr = cx231xx_boards[dev->model].tuner_addr;
+
+       /* request some modules */
+       if (dev->board.decoder == CX231XX_AVDECODER) {
+               dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
+                                       &dev->i2c_bus[0].i2c_adap,
+                                       "cx25840", 0x88 >> 1, NULL);
+               if (dev->sd_cx25840 == NULL)
+                       cx231xx_info("cx25840 subdev registration failure\n");
+               cx25840_call(dev, core, load_fw);
+
+       }
+
+       /* Initialize the tuner */
+       if (dev->board.tuner_type != TUNER_ABSENT) {
+               dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev,
+                                                   &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
+                                                   "tuner",
+                                                   dev->tuner_addr, NULL);
+               if (dev->sd_tuner == NULL)
+                       cx231xx_info("tuner subdev registration failure\n");
+               else
+                       cx231xx_config_tuner(dev);
+       }
+}
+
+/*
+ * cx231xx_config()
+ * inits registers with sane defaults
+ */
+int cx231xx_config(struct cx231xx *dev)
+{
+       /* TBD need to add cx231xx specific code */
+       dev->mute = 1;          /* maybe not the right place... */
+       dev->volume = 0x1f;
+
+       return 0;
+}
+
+/*
+ * cx231xx_config_i2c()
+ * configure i2c attached devices
+ */
+void cx231xx_config_i2c(struct cx231xx *dev)
+{
+       /* u32 input = INPUT(dev->video_input)->vmux; */
+
+       call_all(dev, video, s_stream, 1);
+}
+
+/*
+ * cx231xx_realease_resources()
+ * unregisters the v4l2,i2c and usb devices
+ * called when the device gets disconected or at module unload
+*/
+void cx231xx_release_resources(struct cx231xx *dev)
+{
+       cx231xx_release_analog_resources(dev);
+
+       cx231xx_remove_from_devlist(dev);
+
+       cx231xx_ir_exit(dev);
+
+       /* Release I2C buses */
+       cx231xx_dev_uninit(dev);
+
+       /* delete v4l2 device */
+       v4l2_device_unregister(&dev->v4l2_dev);
+
+       usb_put_dev(dev->udev);
+
+       /* Mark device as unused */
+       clear_bit(dev->devno, &cx231xx_devused);
+
+       kfree(dev->video_mode.alt_max_pkt_size);
+       kfree(dev->vbi_mode.alt_max_pkt_size);
+       kfree(dev->sliced_cc_mode.alt_max_pkt_size);
+       kfree(dev->ts1_mode.alt_max_pkt_size);
+       kfree(dev);
+}
+
+/*
+ * cx231xx_init_dev()
+ * allocates and inits the device structs, registers i2c bus and v4l device
+ */
+static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev,
+                           int minor)
+{
+       int retval = -ENOMEM;
+       int errCode;
+       unsigned int maxh, maxw;
+
+       dev->udev = udev;
+       mutex_init(&dev->lock);
+       mutex_init(&dev->ctrl_urb_lock);
+       mutex_init(&dev->gpio_i2c_lock);
+       mutex_init(&dev->i2c_lock);
+
+       spin_lock_init(&dev->video_mode.slock);
+       spin_lock_init(&dev->vbi_mode.slock);
+       spin_lock_init(&dev->sliced_cc_mode.slock);
+
+       init_waitqueue_head(&dev->open);
+       init_waitqueue_head(&dev->wait_frame);
+       init_waitqueue_head(&dev->wait_stream);
+
+       dev->cx231xx_read_ctrl_reg = cx231xx_read_ctrl_reg;
+       dev->cx231xx_write_ctrl_reg = cx231xx_write_ctrl_reg;
+       dev->cx231xx_send_usb_command = cx231xx_send_usb_command;
+       dev->cx231xx_gpio_i2c_read = cx231xx_gpio_i2c_read;
+       dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write;
+
+       /* Query cx231xx to find what pcb config it is related to */
+       initialize_cx231xx(dev);
+
+       /*To workaround error number=-71 on EP0 for VideoGrabber,
+                need set alt here.*/
+       if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER ||
+           dev->model == CX231XX_BOARD_HAUPPAUGE_USBLIVE2) {
+               cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3);
+               cx231xx_set_alt_setting(dev, INDEX_VANC, 1);
+       }
+       /* Cx231xx pre card setup */
+       cx231xx_pre_card_setup(dev);
+
+       errCode = cx231xx_config(dev);
+       if (errCode) {
+               cx231xx_errdev("error configuring device\n");
+               return -ENOMEM;
+       }
+
+       /* set default norm */
+       dev->norm = dev->board.norm;
+
+       /* register i2c bus */
+       errCode = cx231xx_dev_init(dev);
+       if (errCode < 0) {
+               cx231xx_dev_uninit(dev);
+               cx231xx_errdev("%s: cx231xx_i2c_register - errCode [%d]!\n",
+                              __func__, errCode);
+               return errCode;
+       }
+
+       /* Do board specific init */
+       cx231xx_card_setup(dev);
+
+       /* configure the device */
+       cx231xx_config_i2c(dev);
+
+       maxw = norm_maxw(dev);
+       maxh = norm_maxh(dev);
+
+       /* set default image size */
+       dev->width = maxw;
+       dev->height = maxh;
+       dev->interlaced = 0;
+       dev->video_input = 0;
+
+       errCode = cx231xx_config(dev);
+       if (errCode < 0) {
+               cx231xx_errdev("%s: cx231xx_config - errCode [%d]!\n",
+                              __func__, errCode);
+               return errCode;
+       }
+
+       /* init video dma queues */
+       INIT_LIST_HEAD(&dev->video_mode.vidq.active);
+       INIT_LIST_HEAD(&dev->video_mode.vidq.queued);
+
+       /* init vbi dma queues */
+       INIT_LIST_HEAD(&dev->vbi_mode.vidq.active);
+       INIT_LIST_HEAD(&dev->vbi_mode.vidq.queued);
+
+       /* Reset other chips required if they are tied up with GPIO pins */
+       cx231xx_add_into_devlist(dev);
+
+       if (dev->board.has_417) {
+               printk(KERN_INFO "attach 417 %d\n", dev->model);
+               if (cx231xx_417_register(dev) < 0) {
+                       printk(KERN_ERR
+                               "%s() Failed to register 417 on VID_B\n",
+                              __func__);
+               }
+       }
+
+       retval = cx231xx_register_analog_devices(dev);
+       if (retval < 0) {
+               cx231xx_release_resources(dev);
+               return retval;
+       }
+
+       cx231xx_ir_init(dev);
+
+       cx231xx_init_extension(dev);
+
+       return 0;
+}
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
+static void request_module_async(struct work_struct *work)
+{
+       struct cx231xx *dev = container_of(work,
+                                          struct cx231xx, request_module_wk);
+
+       if (dev->has_alsa_audio)
+               request_module("cx231xx-alsa");
+
+       if (dev->board.has_dvb)
+               request_module("cx231xx-dvb");
+
+}
+
+static void request_modules(struct cx231xx *dev)
+{
+       INIT_WORK(&dev->request_module_wk, request_module_async);
+       schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_modules(struct cx231xx *dev)
+{
+       flush_work_sync(&dev->request_module_wk);
+}
+#else
+#define request_modules(dev)
+#define flush_request_modules(dev)
+#endif /* CONFIG_MODULES */
+
+/*
+ * cx231xx_usb_probe()
+ * checks for supported devices
+ */
+static int cx231xx_usb_probe(struct usb_interface *interface,
+                            const struct usb_device_id *id)
+{
+       struct usb_device *udev;
+       struct usb_interface *uif;
+       struct cx231xx *dev = NULL;
+       int retval = -ENODEV;
+       int nr = 0, ifnum;
+       int i, isoc_pipe = 0;
+       char *speed;
+       struct usb_interface_assoc_descriptor *assoc_desc;
+
+       udev = usb_get_dev(interface_to_usbdev(interface));
+       ifnum = interface->altsetting[0].desc.bInterfaceNumber;
+
+       /*
+        * Interface number 0 - IR interface (handled by mceusb driver)
+        * Interface number 1 - AV interface (handled by this driver)
+        */
+       if (ifnum != 1)
+               return -ENODEV;
+
+       /* Check to see next free device and mark as used */
+       do {
+               nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
+               if (nr >= CX231XX_MAXBOARDS) {
+                       /* No free device slots */
+                       cx231xx_err(DRIVER_NAME ": Supports only %i devices.\n",
+                                       CX231XX_MAXBOARDS);
+                       return -ENOMEM;
+               }
+       } while (test_and_set_bit(nr, &cx231xx_devused));
+
+       /* allocate memory for our device state and initialize it */
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               cx231xx_err(DRIVER_NAME ": out of memory!\n");
+               clear_bit(nr, &cx231xx_devused);
+               return -ENOMEM;
+       }
+
+       snprintf(dev->name, 29, "cx231xx #%d", nr);
+       dev->devno = nr;
+       dev->model = id->driver_info;
+       dev->video_mode.alt = -1;
+
+       dev->interface_count++;
+       /* reset gpio dir and value */
+       dev->gpio_dir = 0;
+       dev->gpio_val = 0;
+       dev->xc_fw_load_done = 0;
+       dev->has_alsa_audio = 1;
+       dev->power_mode = -1;
+       atomic_set(&dev->devlist_count, 0);
+
+       /* 0 - vbi ; 1 -sliced cc mode */
+       dev->vbi_or_sliced_cc_mode = 0;
+
+       /* get maximum no.of IAD interfaces */
+       assoc_desc = udev->actconfig->intf_assoc[0];
+       dev->max_iad_interface_count = assoc_desc->bInterfaceCount;
+
+       /* init CIR module TBD */
+
+       /*mode_tv: digital=1 or analog=0*/
+       dev->mode_tv = 0;
+
+       dev->USE_ISO = transfer_mode;
+
+       switch (udev->speed) {
+       case USB_SPEED_LOW:
+               speed = "1.5";
+               break;
+       case USB_SPEED_UNKNOWN:
+       case USB_SPEED_FULL:
+               speed = "12";
+               break;
+       case USB_SPEED_HIGH:
+               speed = "480";
+               break;
+       default:
+               speed = "unknown";
+       }
+
+       cx231xx_info("New device %s %s @ %s Mbps "
+            "(%04x:%04x) with %d interfaces\n",
+            udev->manufacturer ? udev->manufacturer : "",
+            udev->product ? udev->product : "",
+            speed,
+            le16_to_cpu(udev->descriptor.idVendor),
+            le16_to_cpu(udev->descriptor.idProduct),
+            dev->max_iad_interface_count);
+
+       /* increment interface count */
+       dev->interface_count++;
+
+       /* get device number */
+       nr = dev->devno;
+
+       assoc_desc = udev->actconfig->intf_assoc[0];
+       if (assoc_desc->bFirstInterface != ifnum) {
+               cx231xx_err(DRIVER_NAME ": Not found "
+                           "matching IAD interface\n");
+               clear_bit(dev->devno, &cx231xx_devused);
+               kfree(dev);
+               dev = NULL;
+               return -ENODEV;
+       }
+
+       cx231xx_info("registering interface %d\n", ifnum);
+
+       /* save our data pointer in this interface device */
+       usb_set_intfdata(interface, dev);
+
+       /*
+        * AV device initialization - only done at the last interface
+        */
+
+       /* Create v4l2 device */
+       retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
+       if (retval) {
+               cx231xx_errdev("v4l2_device_register failed\n");
+               clear_bit(dev->devno, &cx231xx_devused);
+               kfree(dev);
+               dev = NULL;
+               return -EIO;
+       }
+       /* allocate device struct */
+       retval = cx231xx_init_dev(dev, udev, nr);
+       if (retval) {
+               clear_bit(dev->devno, &cx231xx_devused);
+               v4l2_device_unregister(&dev->v4l2_dev);
+               kfree(dev);
+               dev = NULL;
+               usb_set_intfdata(interface, NULL);
+
+               return retval;
+       }
+
+       /* compute alternate max packet sizes for video */
+       uif = udev->actconfig->interface[dev->current_pcb_config.
+                      hs_config_info[0].interface_info.video_index + 1];
+
+       dev->video_mode.end_point_addr = le16_to_cpu(uif->altsetting[0].
+                       endpoint[isoc_pipe].desc.bEndpointAddress);
+
+       dev->video_mode.num_alt = uif->num_altsetting;
+       cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+                    dev->video_mode.end_point_addr,
+                    dev->video_mode.num_alt);
+       dev->video_mode.alt_max_pkt_size =
+               kmalloc(32 * dev->video_mode.num_alt, GFP_KERNEL);
+
+       if (dev->video_mode.alt_max_pkt_size == NULL) {
+               cx231xx_errdev("out of memory!\n");
+               clear_bit(dev->devno, &cx231xx_devused);
+               v4l2_device_unregister(&dev->v4l2_dev);
+               kfree(dev);
+               dev = NULL;
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < dev->video_mode.num_alt; i++) {
+               u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
+                               desc.wMaxPacketSize);
+               dev->video_mode.alt_max_pkt_size[i] =
+                   (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+               cx231xx_info("Alternate setting %i, max size= %i\n", i,
+                            dev->video_mode.alt_max_pkt_size[i]);
+       }
+
+       /* compute alternate max packet sizes for vbi */
+       uif = udev->actconfig->interface[dev->current_pcb_config.
+                                      hs_config_info[0].interface_info.
+                                      vanc_index + 1];
+
+       dev->vbi_mode.end_point_addr =
+           le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.
+                       bEndpointAddress);
+
+       dev->vbi_mode.num_alt = uif->num_altsetting;
+       cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+                    dev->vbi_mode.end_point_addr,
+                    dev->vbi_mode.num_alt);
+       dev->vbi_mode.alt_max_pkt_size =
+           kmalloc(32 * dev->vbi_mode.num_alt, GFP_KERNEL);
+
+       if (dev->vbi_mode.alt_max_pkt_size == NULL) {
+               cx231xx_errdev("out of memory!\n");
+               clear_bit(dev->devno, &cx231xx_devused);
+               v4l2_device_unregister(&dev->v4l2_dev);
+               kfree(dev);
+               dev = NULL;
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < dev->vbi_mode.num_alt; i++) {
+               u16 tmp =
+                   le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
+                               desc.wMaxPacketSize);
+               dev->vbi_mode.alt_max_pkt_size[i] =
+                   (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+               cx231xx_info("Alternate setting %i, max size= %i\n", i,
+                            dev->vbi_mode.alt_max_pkt_size[i]);
+       }
+
+       /* compute alternate max packet sizes for sliced CC */
+       uif = udev->actconfig->interface[dev->current_pcb_config.
+                                      hs_config_info[0].interface_info.
+                                      hanc_index + 1];
+
+       dev->sliced_cc_mode.end_point_addr =
+           le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.
+                       bEndpointAddress);
+
+       dev->sliced_cc_mode.num_alt = uif->num_altsetting;
+       cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+                    dev->sliced_cc_mode.end_point_addr,
+                    dev->sliced_cc_mode.num_alt);
+       dev->sliced_cc_mode.alt_max_pkt_size =
+               kmalloc(32 * dev->sliced_cc_mode.num_alt, GFP_KERNEL);
+
+       if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) {
+               cx231xx_errdev("out of memory!\n");
+               clear_bit(dev->devno, &cx231xx_devused);
+               v4l2_device_unregister(&dev->v4l2_dev);
+               kfree(dev);
+               dev = NULL;
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) {
+               u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
+                               desc.wMaxPacketSize);
+               dev->sliced_cc_mode.alt_max_pkt_size[i] =
+                   (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+               cx231xx_info("Alternate setting %i, max size= %i\n", i,
+                            dev->sliced_cc_mode.alt_max_pkt_size[i]);
+       }
+
+       if (dev->current_pcb_config.ts1_source != 0xff) {
+               /* compute alternate max packet sizes for TS1 */
+               uif = udev->actconfig->interface[dev->current_pcb_config.
+                                              hs_config_info[0].
+                                              interface_info.
+                                              ts1_index + 1];
+
+               dev->ts1_mode.end_point_addr =
+                   le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].
+                               desc.bEndpointAddress);
+
+               dev->ts1_mode.num_alt = uif->num_altsetting;
+               cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+                            dev->ts1_mode.end_point_addr,
+                            dev->ts1_mode.num_alt);
+               dev->ts1_mode.alt_max_pkt_size =
+                       kmalloc(32 * dev->ts1_mode.num_alt, GFP_KERNEL);
+
+               if (dev->ts1_mode.alt_max_pkt_size == NULL) {
+                       cx231xx_errdev("out of memory!\n");
+                       clear_bit(dev->devno, &cx231xx_devused);
+                       v4l2_device_unregister(&dev->v4l2_dev);
+                       kfree(dev);
+                       dev = NULL;
+                       return -ENOMEM;
+               }
+
+               for (i = 0; i < dev->ts1_mode.num_alt; i++) {
+                       u16 tmp = le16_to_cpu(uif->altsetting[i].
+                                               endpoint[isoc_pipe].desc.
+                                               wMaxPacketSize);
+                       dev->ts1_mode.alt_max_pkt_size[i] =
+                           (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+                       cx231xx_info("Alternate setting %i, max size= %i\n", i,
+                                    dev->ts1_mode.alt_max_pkt_size[i]);
+               }
+       }
+
+       if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) {
+               cx231xx_enable_OSC(dev);
+               cx231xx_reset_out(dev);
+               cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3);
+       }
+
+       if (dev->model == CX231XX_BOARD_CNXT_RDE_253S)
+               cx231xx_sleep_s5h1432(dev);
+
+       /* load other modules required */
+       request_modules(dev);
+
+       return 0;
+}
+
+/*
+ * cx231xx_usb_disconnect()
+ * called when the device gets diconencted
+ * video device will be unregistered on v4l2_close in case it is still open
+ */
+static void cx231xx_usb_disconnect(struct usb_interface *interface)
+{
+       struct cx231xx *dev;
+
+       dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+
+       if (!dev)
+               return;
+
+       if (!dev->udev)
+               return;
+
+       dev->state |= DEV_DISCONNECTED;
+
+       flush_request_modules(dev);
+
+       /* wait until all current v4l2 io is finished then deallocate
+          resources */
+       mutex_lock(&dev->lock);
+
+       wake_up_interruptible_all(&dev->open);
+
+       if (dev->users) {
+               cx231xx_warn
+                   ("device %s is open! Deregistration and memory "
+                    "deallocation are deferred on close.\n",
+                    video_device_node_name(dev->vdev));
+
+               /* Even having users, it is safe to remove the RC i2c driver */
+               cx231xx_ir_exit(dev);
+
+               if (dev->USE_ISO)
+                       cx231xx_uninit_isoc(dev);
+               else
+                       cx231xx_uninit_bulk(dev);
+               wake_up_interruptible(&dev->wait_frame);
+               wake_up_interruptible(&dev->wait_stream);
+       } else {
+       }
+
+       cx231xx_close_extension(dev);
+
+       mutex_unlock(&dev->lock);
+
+       if (!dev->users)
+               cx231xx_release_resources(dev);
+}
+
+static struct usb_driver cx231xx_usb_driver = {
+       .name = "cx231xx",
+       .probe = cx231xx_usb_probe,
+       .disconnect = cx231xx_usb_disconnect,
+       .id_table = cx231xx_id_table,
+};
+
+module_usb_driver(cx231xx_usb_driver);
diff --git a/drivers/media/usb/cx231xx/cx231xx-conf-reg.h b/drivers/media/usb/cx231xx/cx231xx-conf-reg.h
new file mode 100644 (file)
index 0000000..25593f2
--- /dev/null
@@ -0,0 +1,495 @@
+/*
+   cx231xx_conf-reg.h - driver for Conexant Cx23100/101/102 USB
+                       video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot 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.
+
+   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.
+ */
+
+#ifndef _POLARIS_REG_H_
+#define _POLARIS_REG_H_
+
+#define BOARD_CFG_STAT          0x0
+#define TS_MODE_REG             0x4
+#define TS1_CFG_REG             0x8
+#define TS1_LENGTH_REG          0xc
+#define TS2_CFG_REG             0x10
+#define TS2_LENGTH_REG          0x14
+#define EP_MODE_SET             0x18
+#define CIR_PWR_PTN1            0x1c
+#define CIR_PWR_PTN2            0x20
+#define CIR_PWR_PTN3            0x24
+#define CIR_PWR_MASK0           0x28
+#define CIR_PWR_MASK1           0x2c
+#define CIR_PWR_MASK2           0x30
+#define CIR_GAIN                0x34
+#define CIR_CAR_REG             0x38
+#define CIR_OT_CFG1             0x40
+#define CIR_OT_CFG2             0x44
+#define GBULK_BIT_EN            0x68
+#define PWR_CTL_EN              0x74
+
+/* Polaris Endpoints capture mask for register EP_MODE_SET */
+#define ENABLE_EP1              0x01   /* Bit[0]=1 */
+#define ENABLE_EP2              0x02   /* Bit[1]=1 */
+#define ENABLE_EP3              0x04   /* Bit[2]=1 */
+#define ENABLE_EP4              0x08   /* Bit[3]=1 */
+#define ENABLE_EP5              0x10   /* Bit[4]=1 */
+#define ENABLE_EP6              0x20   /* Bit[5]=1 */
+
+/* Bit definition for register PWR_CTL_EN */
+#define PWR_MODE_MASK           0x17f
+#define PWR_AV_EN               0x08   /* bit3 */
+#define PWR_ISO_EN              0x40   /* bit6 */
+#define PWR_AV_MODE             0x30   /* bit4,5  */
+#define PWR_TUNER_EN            0x04   /* bit2 */
+#define PWR_DEMOD_EN            0x02   /* bit1 */
+#define I2C_DEMOD_EN            0x01   /* bit0 */
+#define PWR_RESETOUT_EN         0x100  /* bit8 */
+
+enum AV_MODE{
+       POLARIS_AVMODE_DEFAULT = 0,
+       POLARIS_AVMODE_DIGITAL = 0x10,
+       POLARIS_AVMODE_ANALOGT_TV = 0x20,
+       POLARIS_AVMODE_ENXTERNAL_AV = 0x30,
+
+};
+
+/* Colibri Registers */
+
+#define SINGLE_ENDED            0x0
+#define LOW_IF                  0x4
+#define EU_IF                   0x9
+#define US_IF                   0xa
+
+#define SUP_BLK_TUNE1           0x00
+#define SUP_BLK_TUNE2           0x01
+#define SUP_BLK_TUNE3           0x02
+#define SUP_BLK_XTAL            0x03
+#define SUP_BLK_PLL1            0x04
+#define SUP_BLK_PLL2            0x05
+#define SUP_BLK_PLL3            0x06
+#define SUP_BLK_REF             0x07
+#define SUP_BLK_PWRDN           0x08
+#define SUP_BLK_TESTPAD         0x09
+#define ADC_COM_INT5_STAB_REF   0x0a
+#define ADC_COM_QUANT           0x0b
+#define ADC_COM_BIAS1           0x0c
+#define ADC_COM_BIAS2           0x0d
+#define ADC_COM_BIAS3           0x0e
+#define TESTBUS_CTRL            0x12
+
+#define FLD_PWRDN_TUNING_BIAS  0x10
+#define FLD_PWRDN_ENABLE_PLL   0x08
+#define FLD_PWRDN_PD_BANDGAP   0x04
+#define FLD_PWRDN_PD_BIAS      0x02
+#define FLD_PWRDN_PD_TUNECK    0x01
+
+
+#define ADC_STATUS_CH1          0x20
+#define ADC_STATUS_CH2          0x40
+#define ADC_STATUS_CH3          0x60
+
+#define ADC_STATUS2_CH1         0x21
+#define ADC_STATUS2_CH2         0x41
+#define ADC_STATUS2_CH3         0x61
+
+#define ADC_CAL_ATEST_CH1       0x22
+#define ADC_CAL_ATEST_CH2       0x42
+#define ADC_CAL_ATEST_CH3       0x62
+
+#define ADC_PWRDN_CLAMP_CH1     0x23
+#define ADC_PWRDN_CLAMP_CH2     0x43
+#define ADC_PWRDN_CLAMP_CH3     0x63
+
+#define ADC_CTRL_DAC23_CH1      0x24
+#define ADC_CTRL_DAC23_CH2      0x44
+#define ADC_CTRL_DAC23_CH3      0x64
+
+#define ADC_CTRL_DAC1_CH1       0x25
+#define ADC_CTRL_DAC1_CH2       0x45
+#define ADC_CTRL_DAC1_CH3       0x65
+
+#define ADC_DCSERVO_DEM_CH1     0x26
+#define ADC_DCSERVO_DEM_CH2     0x46
+#define ADC_DCSERVO_DEM_CH3     0x66
+
+#define ADC_FB_FRCRST_CH1       0x27
+#define ADC_FB_FRCRST_CH2       0x47
+#define ADC_FB_FRCRST_CH3       0x67
+
+#define ADC_INPUT_CH1           0x28
+#define ADC_INPUT_CH2           0x48
+#define ADC_INPUT_CH3           0x68
+#define INPUT_SEL_MASK          0x30   /* [5:4] in_sel */
+
+#define ADC_NTF_PRECLMP_EN_CH1  0x29
+#define ADC_NTF_PRECLMP_EN_CH2  0x49
+#define ADC_NTF_PRECLMP_EN_CH3  0x69
+
+#define ADC_QGAIN_RES_TRM_CH1   0x2a
+#define ADC_QGAIN_RES_TRM_CH2   0x4a
+#define ADC_QGAIN_RES_TRM_CH3   0x6a
+
+#define ADC_SOC_PRECLMP_TERM_CH1    0x2b
+#define ADC_SOC_PRECLMP_TERM_CH2    0x4b
+#define ADC_SOC_PRECLMP_TERM_CH3    0x6b
+
+#define TESTBUS_CTRL_CH1        0x32
+#define TESTBUS_CTRL_CH2        0x52
+#define TESTBUS_CTRL_CH3        0x72
+
+/******************************************************************************
+                           * DIF registers *
+ ******************************************************************************/
+#define      DIRECT_IF_REVB_BASE  0x00300
+
+/*****************************************************************************/
+#define      DIF_PLL_FREQ_WORD        (DIRECT_IF_REVB_BASE + 0x00000000)
+/*****************************************************************************/
+#define      FLD_DIF_PLL_LOCK                           0x80000000
+/*  Reserved                                [30:29] */
+#define      FLD_DIF_PLL_FREE_RUN                       0x10000000
+#define      FLD_DIF_PLL_FREQ                           0x0fffffff
+
+/*****************************************************************************/
+#define      DIF_PLL_CTRL             (DIRECT_IF_REVB_BASE + 0x00000004)
+/*****************************************************************************/
+#define      FLD_DIF_KD_PD                              0xff000000
+/*  Reserved                             [23:20] */
+#define      FLD_DIF_KDS_PD                             0x000f0000
+#define      FLD_DIF_KI_PD                              0x0000ff00
+/*  Reserved                             [7:4] */
+#define      FLD_DIF_KIS_PD                             0x0000000f
+
+/*****************************************************************************/
+#define      DIF_PLL_CTRL1            (DIRECT_IF_REVB_BASE + 0x00000008)
+/*****************************************************************************/
+#define      FLD_DIF_KD_FD                              0xff000000
+/*  Reserved                             [23:20] */
+#define      FLD_DIF_KDS_FD                             0x000f0000
+#define      FLD_DIF_KI_FD                              0x0000ff00
+#define      FLD_DIF_SIG_PROP_SZ                        0x000000f0
+#define      FLD_DIF_KIS_FD                             0x0000000f
+
+/*****************************************************************************/
+#define      DIF_PLL_CTRL2            (DIRECT_IF_REVB_BASE + 0x0000000c)
+/*****************************************************************************/
+#define      FLD_DIF_PLL_AGC_REF                        0xfff00000
+#define      FLD_DIF_PLL_AGC_KI                         0x000f0000
+/*  Reserved                             [15] */
+#define      FLD_DIF_FREQ_LIMIT                         0x00007000
+#define      FLD_DIF_K_FD                               0x00000f00
+#define      FLD_DIF_DOWNSMPL_FD                        0x000000ff
+
+/*****************************************************************************/
+#define      DIF_PLL_CTRL3            (DIRECT_IF_REVB_BASE + 0x00000010)
+/*****************************************************************************/
+/*  Reserved                             [31:16] */
+#define      FLD_DIF_PLL_AGC_EN                         0x00008000
+/*  Reserved                             [14:12] */
+#define      FLD_DIF_PLL_MAN_GAIN                       0x00000fff
+
+/*****************************************************************************/
+#define      DIF_AGC_IF_REF           (DIRECT_IF_REVB_BASE + 0x00000014)
+/*****************************************************************************/
+#define      FLD_DIF_K_AGC_RF                           0xf0000000
+#define      FLD_DIF_K_AGC_IF                           0x0f000000
+#define      FLD_DIF_K_AGC_INT                          0x00f00000
+/*  Reserved                             [19:12] */
+#define      FLD_DIF_IF_REF                             0x00000fff
+
+/*****************************************************************************/
+#define      DIF_AGC_CTRL_IF          (DIRECT_IF_REVB_BASE + 0x00000018)
+/*****************************************************************************/
+#define      FLD_DIF_IF_MAX                             0xff000000
+#define      FLD_DIF_IF_MIN                             0x00ff0000
+#define      FLD_DIF_IF_AGC                             0x0000ffff
+
+/*****************************************************************************/
+#define      DIF_AGC_CTRL_INT         (DIRECT_IF_REVB_BASE + 0x0000001c)
+/*****************************************************************************/
+#define      FLD_DIF_INT_MAX                            0xff000000
+#define      FLD_DIF_INT_MIN                            0x00ff0000
+#define      FLD_DIF_INT_AGC                            0x0000ffff
+
+/*****************************************************************************/
+#define      DIF_AGC_CTRL_RF          (DIRECT_IF_REVB_BASE + 0x00000020)
+/*****************************************************************************/
+#define      FLD_DIF_RF_MAX                             0xff000000
+#define      FLD_DIF_RF_MIN                             0x00ff0000
+#define      FLD_DIF_RF_AGC                             0x0000ffff
+
+/*****************************************************************************/
+#define      DIF_AGC_IF_INT_CURRENT   (DIRECT_IF_REVB_BASE + 0x00000024)
+/*****************************************************************************/
+#define      FLD_DIF_IF_AGC_IN                          0xffff0000
+#define      FLD_DIF_INT_AGC_IN                         0x0000ffff
+
+/*****************************************************************************/
+#define      DIF_AGC_RF_CURRENT       (DIRECT_IF_REVB_BASE + 0x00000028)
+/*****************************************************************************/
+/*  Reserved                            [31:16] */
+#define      FLD_DIF_RF_AGC_IN                          0x0000ffff
+
+/*****************************************************************************/
+#define      DIF_VIDEO_AGC_CTRL       (DIRECT_IF_REVB_BASE + 0x0000002c)
+/*****************************************************************************/
+#define      FLD_DIF_AFD                                0xc0000000
+#define      FLD_DIF_K_VID_AGC                          0x30000000
+#define      FLD_DIF_LINE_LENGTH                        0x0fff0000
+#define      FLD_DIF_AGC_GAIN                           0x0000ffff
+
+/*****************************************************************************/
+#define      DIF_VID_AUD_OVERRIDE     (DIRECT_IF_REVB_BASE + 0x00000030)
+/*****************************************************************************/
+#define      FLD_DIF_AUDIO_AGC_OVERRIDE                 0x80000000
+/*  Reserved                             [30:30] */
+#define      FLD_DIF_AUDIO_MAN_GAIN                     0x3f000000
+/*  Reserved                             [23:17] */
+#define      FLD_DIF_VID_AGC_OVERRIDE                   0x00010000
+#define      FLD_DIF_VID_MAN_GAIN                       0x0000ffff
+
+/*****************************************************************************/
+#define      DIF_AV_SEP_CTRL          (DIRECT_IF_REVB_BASE + 0x00000034)
+/*****************************************************************************/
+#define      FLD_DIF_LPF_FREQ                           0xc0000000
+#define      FLD_DIF_AV_PHASE_INC                       0x3f000000
+#define      FLD_DIF_AUDIO_FREQ                         0x00ffffff
+
+/*****************************************************************************/
+#define      DIF_COMP_FLT_CTRL        (DIRECT_IF_REVB_BASE + 0x00000038)
+/*****************************************************************************/
+/*  Reserved                            [31:24] */
+#define      FLD_DIF_IIR23_R2                           0x00ff0000
+#define      FLD_DIF_IIR23_R1                           0x0000ff00
+#define      FLD_DIF_IIR1_R1                            0x000000ff
+
+/*****************************************************************************/
+#define      DIF_MISC_CTRL            (DIRECT_IF_REVB_BASE + 0x0000003c)
+/*****************************************************************************/
+#define      FLD_DIF_DIF_BYPASS                         0x80000000
+#define      FLD_DIF_FM_NYQ_GAIN                        0x40000000
+#define      FLD_DIF_RF_AGC_ENA                         0x20000000
+#define      FLD_DIF_INT_AGC_ENA                        0x10000000
+#define      FLD_DIF_IF_AGC_ENA                         0x08000000
+#define      FLD_DIF_FORCE_RF_IF_LOCK                   0x04000000
+#define      FLD_DIF_VIDEO_AGC_ENA                      0x02000000
+#define      FLD_DIF_RF_AGC_INV                         0x01000000
+#define      FLD_DIF_INT_AGC_INV                        0x00800000
+#define      FLD_DIF_IF_AGC_INV                         0x00400000
+#define      FLD_DIF_SPEC_INV                           0x00200000
+#define      FLD_DIF_AUD_FULL_BW                        0x00100000
+#define      FLD_DIF_AUD_SRC_SEL                        0x00080000
+/*  Reserved                             [18] */
+#define      FLD_DIF_IF_FREQ                            0x00030000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_TIP_OFFSET                         0x00003f00
+/*  Reserved                             [7:5] */
+#define      FLD_DIF_DITHER_ENA                         0x00000010
+/*  Reserved                             [3:1] */
+#define      FLD_DIF_RF_IF_LOCK                         0x00000001
+
+/*****************************************************************************/
+#define      DIF_SRC_PHASE_INC        (DIRECT_IF_REVB_BASE + 0x00000040)
+/*****************************************************************************/
+/*  Reserved                             [31:29] */
+#define      FLD_DIF_PHASE_INC                          0x1fffffff
+
+/*****************************************************************************/
+#define      DIF_SRC_GAIN_CONTROL     (DIRECT_IF_REVB_BASE + 0x00000044)
+/*****************************************************************************/
+/*  Reserved                             [31:16] */
+#define      FLD_DIF_SRC_KI                             0x0000ff00
+#define      FLD_DIF_SRC_KD                             0x000000ff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF01          (DIRECT_IF_REVB_BASE + 0x00000048)
+/*****************************************************************************/
+/*  Reserved                             [31:19] */
+#define      FLD_DIF_BPF_COEFF_0                        0x00070000
+/*  Reserved                             [15:4] */
+#define      FLD_DIF_BPF_COEFF_1                        0x0000000f
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF23          (DIRECT_IF_REVB_BASE + 0x0000004c)
+/*****************************************************************************/
+/*  Reserved                             [31:22] */
+#define      FLD_DIF_BPF_COEFF_2                        0x003f0000
+/*  Reserved                             [15:7] */
+#define      FLD_DIF_BPF_COEFF_3                        0x0000007f
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF45          (DIRECT_IF_REVB_BASE + 0x00000050)
+/*****************************************************************************/
+/*  Reserved                             [31:24] */
+#define      FLD_DIF_BPF_COEFF_4                        0x00ff0000
+/*  Reserved                             [15:8] */
+#define      FLD_DIF_BPF_COEFF_5                        0x000000ff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF67          (DIRECT_IF_REVB_BASE + 0x00000054)
+/*****************************************************************************/
+/*  Reserved                             [31:25] */
+#define      FLD_DIF_BPF_COEFF_6                        0x01ff0000
+/*  Reserved                             [15:9] */
+#define      FLD_DIF_BPF_COEFF_7                        0x000001ff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF89          (DIRECT_IF_REVB_BASE + 0x00000058)
+/*****************************************************************************/
+/*  Reserved                             [31:26] */
+#define      FLD_DIF_BPF_COEFF_8                        0x03ff0000
+/*  Reserved                             [15:10] */
+#define      FLD_DIF_BPF_COEFF_9                        0x000003ff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF1011        (DIRECT_IF_REVB_BASE + 0x0000005c)
+/*****************************************************************************/
+/*  Reserved                             [31:27] */
+#define      FLD_DIF_BPF_COEFF_10                       0x07ff0000
+/*  Reserved                             [15:11] */
+#define      FLD_DIF_BPF_COEFF_11                       0x000007ff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF1213        (DIRECT_IF_REVB_BASE + 0x00000060)
+/*****************************************************************************/
+/*  Reserved                             [31:27] */
+#define      FLD_DIF_BPF_COEFF_12                       0x07ff0000
+/*  Reserved                             [15:12] */
+#define      FLD_DIF_BPF_COEFF_13                       0x00000fff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF1415        (DIRECT_IF_REVB_BASE + 0x00000064)
+/*****************************************************************************/
+/*  Reserved                             [31:28] */
+#define      FLD_DIF_BPF_COEFF_14                       0x0fff0000
+/*  Reserved                             [15:12] */
+#define      FLD_DIF_BPF_COEFF_15                       0x00000fff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF1617        (DIRECT_IF_REVB_BASE + 0x00000068)
+/*****************************************************************************/
+/*  Reserved                             [31:29] */
+#define      FLD_DIF_BPF_COEFF_16                       0x1fff0000
+/*  Reserved                             [15:13] */
+#define      FLD_DIF_BPF_COEFF_17                       0x00001fff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF1819        (DIRECT_IF_REVB_BASE + 0x0000006c)
+/*****************************************************************************/
+/*  Reserved                             [31:29] */
+#define      FLD_DIF_BPF_COEFF_18                       0x1fff0000
+/*  Reserved                             [15:13] */
+#define      FLD_DIF_BPF_COEFF_19                       0x00001fff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF2021        (DIRECT_IF_REVB_BASE + 0x00000070)
+/*****************************************************************************/
+/*  Reserved                             [31:29] */
+#define      FLD_DIF_BPF_COEFF_20                       0x1fff0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_21                       0x00003fff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF2223        (DIRECT_IF_REVB_BASE + 0x00000074)
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_22                       0x3fff0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_23                       0x00003fff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF2425        (DIRECT_IF_REVB_BASE + 0x00000078)
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_24                       0x3fff0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_25                       0x00003fff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF2627        (DIRECT_IF_REVB_BASE + 0x0000007c)
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_26                       0x3fff0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_27                       0x00003fff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF2829        (DIRECT_IF_REVB_BASE + 0x00000080)
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_28                       0x3fff0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_29                       0x00003fff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF3031        (DIRECT_IF_REVB_BASE + 0x00000084)
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_30                       0x3fff0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_31                       0x00003fff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF3233        (DIRECT_IF_REVB_BASE + 0x00000088)
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_32                       0x3fff0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_33                       0x00003fff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF3435        (DIRECT_IF_REVB_BASE + 0x0000008c)
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_34                       0x3fff0000
+/*  Reserved                             [15:14] */
+#define      FLD_DIF_BPF_COEFF_35                       0x00003fff
+
+/*****************************************************************************/
+#define      DIF_BPF_COEFF36          (DIRECT_IF_REVB_BASE + 0x00000090)
+/*****************************************************************************/
+/*  Reserved                             [31:30] */
+#define      FLD_DIF_BPF_COEFF_36                       0x3fff0000
+/*  Reserved                             [15:0] */
+
+/*****************************************************************************/
+#define      DIF_RPT_VARIANCE         (DIRECT_IF_REVB_BASE + 0x00000094)
+/*****************************************************************************/
+/*  Reserved                             [31:20] */
+#define      FLD_DIF_RPT_VARIANCE                       0x000fffff
+
+/*****************************************************************************/
+#define      DIF_SOFT_RST_CTRL_REVB       (DIRECT_IF_REVB_BASE + 0x00000098)
+/*****************************************************************************/
+/*  Reserved                             [31:8] */
+#define      FLD_DIF_DIF_SOFT_RST                       0x00000080
+#define      FLD_DIF_DIF_REG_RST_MSK                    0x00000040
+#define      FLD_DIF_AGC_RST_MSK                        0x00000020
+#define      FLD_DIF_CMP_RST_MSK                        0x00000010
+#define      FLD_DIF_AVS_RST_MSK                        0x00000008
+#define      FLD_DIF_NYQ_RST_MSK                        0x00000004
+#define      FLD_DIF_DIF_SRC_RST_MSK                    0x00000002
+#define      FLD_DIF_PLL_RST_MSK                        0x00000001
+
+/*****************************************************************************/
+#define      DIF_PLL_FREQ_ERR         (DIRECT_IF_REVB_BASE + 0x0000009c)
+/*****************************************************************************/
+/*  Reserved                             [31:25] */
+#define      FLD_DIF_CTL_IP                             0x01ffffff
+
+#endif
diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c
new file mode 100644 (file)
index 0000000..05358d4
--- /dev/null
@@ -0,0 +1,1736 @@
+/*
+   cx231xx-core.c - driver for Conexant Cx23100/101/102
+                               USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+                               Based on em28xx driver
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/vmalloc.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+
+#include "cx231xx.h"
+#include "cx231xx-reg.h"
+
+/* #define ENABLE_DEBUG_ISOC_FRAMES */
+
+static unsigned int core_debug;
+module_param(core_debug, int, 0644);
+MODULE_PARM_DESC(core_debug, "enable debug messages [core]");
+
+#define cx231xx_coredbg(fmt, arg...) do {\
+       if (core_debug) \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); } while (0)
+
+static unsigned int reg_debug;
+module_param(reg_debug, int, 0644);
+MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]");
+
+static int alt = CX231XX_PINOUT;
+module_param(alt, int, 0644);
+MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
+
+#define cx231xx_isocdbg(fmt, arg...) do {\
+       if (core_debug) \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); } while (0)
+
+/*****************************************************************
+*             Device control list functions                                     *
+******************************************************************/
+
+LIST_HEAD(cx231xx_devlist);
+static DEFINE_MUTEX(cx231xx_devlist_mutex);
+
+/*
+ * cx231xx_realease_resources()
+ * unregisters the v4l2,i2c and usb devices
+ * called when the device gets disconected or at module unload
+*/
+void cx231xx_remove_from_devlist(struct cx231xx *dev)
+{
+       if (dev == NULL)
+               return;
+       if (dev->udev == NULL)
+               return;
+
+       if (atomic_read(&dev->devlist_count) > 0) {
+               mutex_lock(&cx231xx_devlist_mutex);
+               list_del(&dev->devlist);
+               atomic_dec(&dev->devlist_count);
+               mutex_unlock(&cx231xx_devlist_mutex);
+       }
+};
+
+void cx231xx_add_into_devlist(struct cx231xx *dev)
+{
+       mutex_lock(&cx231xx_devlist_mutex);
+       list_add_tail(&dev->devlist, &cx231xx_devlist);
+       atomic_inc(&dev->devlist_count);
+       mutex_unlock(&cx231xx_devlist_mutex);
+};
+
+static LIST_HEAD(cx231xx_extension_devlist);
+
+int cx231xx_register_extension(struct cx231xx_ops *ops)
+{
+       struct cx231xx *dev = NULL;
+
+       mutex_lock(&cx231xx_devlist_mutex);
+       list_add_tail(&ops->next, &cx231xx_extension_devlist);
+       list_for_each_entry(dev, &cx231xx_devlist, devlist)
+               ops->init(dev);
+
+       printk(KERN_INFO DRIVER_NAME ": %s initialized\n", ops->name);
+       mutex_unlock(&cx231xx_devlist_mutex);
+       return 0;
+}
+EXPORT_SYMBOL(cx231xx_register_extension);
+
+void cx231xx_unregister_extension(struct cx231xx_ops *ops)
+{
+       struct cx231xx *dev = NULL;
+
+       mutex_lock(&cx231xx_devlist_mutex);
+       list_for_each_entry(dev, &cx231xx_devlist, devlist)
+               ops->fini(dev);
+
+
+       printk(KERN_INFO DRIVER_NAME ": %s removed\n", ops->name);
+       list_del(&ops->next);
+       mutex_unlock(&cx231xx_devlist_mutex);
+}
+EXPORT_SYMBOL(cx231xx_unregister_extension);
+
+void cx231xx_init_extension(struct cx231xx *dev)
+{
+       struct cx231xx_ops *ops = NULL;
+
+       mutex_lock(&cx231xx_devlist_mutex);
+       if (!list_empty(&cx231xx_extension_devlist)) {
+               list_for_each_entry(ops, &cx231xx_extension_devlist, next) {
+                       if (ops->init)
+                               ops->init(dev);
+               }
+       }
+       mutex_unlock(&cx231xx_devlist_mutex);
+}
+
+void cx231xx_close_extension(struct cx231xx *dev)
+{
+       struct cx231xx_ops *ops = NULL;
+
+       mutex_lock(&cx231xx_devlist_mutex);
+       if (!list_empty(&cx231xx_extension_devlist)) {
+               list_for_each_entry(ops, &cx231xx_extension_devlist, next) {
+                       if (ops->fini)
+                               ops->fini(dev);
+               }
+       }
+       mutex_unlock(&cx231xx_devlist_mutex);
+}
+
+/****************************************************************
+*               U S B related functions                         *
+*****************************************************************/
+int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus,
+                            struct cx231xx_i2c_xfer_data *req_data)
+{
+       int status = 0;
+       struct cx231xx *dev = i2c_bus->dev;
+       struct VENDOR_REQUEST_IN ven_req;
+
+       u8 saddr_len = 0;
+       u8 _i2c_period = 0;
+       u8 _i2c_nostop = 0;
+       u8 _i2c_reserve = 0;
+
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
+       /* Get the I2C period, nostop and reserve parameters */
+       _i2c_period = i2c_bus->i2c_period;
+       _i2c_nostop = i2c_bus->i2c_nostop;
+       _i2c_reserve = i2c_bus->i2c_reserve;
+
+       saddr_len = req_data->saddr_len;
+
+       /* Set wValue */
+       if (saddr_len == 1)     /* need check saddr_len == 0  */
+               ven_req.wValue =
+                   req_data->
+                   dev_addr << 9 | _i2c_period << 4 | saddr_len << 2 |
+                   _i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6;
+       else
+               ven_req.wValue =
+                   req_data->
+                   dev_addr << 9 | _i2c_period << 4 | saddr_len << 2 |
+                   _i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6;
+
+       /* set channel number */
+       if (req_data->direction & I2C_M_RD) {
+               /* channel number, for read,spec required channel_num +4 */
+               ven_req.bRequest = i2c_bus->nr + 4;
+       } else
+               ven_req.bRequest = i2c_bus->nr; /* channel number,  */
+
+       /* set index value */
+       switch (saddr_len) {
+       case 0:
+               ven_req.wIndex = 0;     /* need check */
+               break;
+       case 1:
+               ven_req.wIndex = (req_data->saddr_dat & 0xff);
+               break;
+       case 2:
+               ven_req.wIndex = req_data->saddr_dat;
+               break;
+       }
+
+       /* set wLength value */
+       ven_req.wLength = req_data->buf_size;
+
+       /* set bData value */
+       ven_req.bData = 0;
+
+       /* set the direction */
+       if (req_data->direction) {
+               ven_req.direction = USB_DIR_IN;
+               memset(req_data->p_buffer, 0x00, ven_req.wLength);
+       } else
+               ven_req.direction = USB_DIR_OUT;
+
+       /* set the buffer for read / write */
+       ven_req.pBuff = req_data->p_buffer;
+
+
+       /* call common vendor command request */
+       status = cx231xx_send_vendor_cmd(dev, &ven_req);
+       if (status < 0) {
+               cx231xx_info
+                   ("UsbInterface::sendCommand, failed with status -%d\n",
+                    status);
+       }
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(cx231xx_send_usb_command);
+
+/*
+ * Sends/Receives URB control messages, assuring to use a kalloced buffer
+ * for all operations (dev->urb_buf), to avoid using stacked buffers, as
+ * they aren't safe for usage with USB, due to DMA restrictions.
+ * Also implements the debug code for control URB's.
+ */
+static int __usb_control_msg(struct cx231xx *dev, unsigned int pipe,
+       __u8 request, __u8 requesttype, __u16 value, __u16 index,
+       void *data, __u16 size, int timeout)
+{
+       int rc, i;
+
+       if (reg_debug) {
+               printk(KERN_DEBUG "%s: (pipe 0x%08x): "
+                               "%s:  %02x %02x %02x %02x %02x %02x %02x %02x ",
+                               dev->name,
+                               pipe,
+                               (requesttype & USB_DIR_IN) ? "IN" : "OUT",
+                               requesttype,
+                               request,
+                               value & 0xff, value >> 8,
+                               index & 0xff, index >> 8,
+                               size & 0xff, size >> 8);
+               if (!(requesttype & USB_DIR_IN)) {
+                       printk(KERN_CONT ">>>");
+                       for (i = 0; i < size; i++)
+                               printk(KERN_CONT " %02x",
+                                      ((unsigned char *)data)[i]);
+               }
+       }
+
+       /* Do the real call to usb_control_msg */
+       mutex_lock(&dev->ctrl_urb_lock);
+       if (!(requesttype & USB_DIR_IN) && size)
+               memcpy(dev->urb_buf, data, size);
+       rc = usb_control_msg(dev->udev, pipe, request, requesttype, value,
+                            index, dev->urb_buf, size, timeout);
+       if ((requesttype & USB_DIR_IN) && size)
+               memcpy(data, dev->urb_buf, size);
+       mutex_unlock(&dev->ctrl_urb_lock);
+
+       if (reg_debug) {
+               if (unlikely(rc < 0)) {
+                       printk(KERN_CONT "FAILED!\n");
+                       return rc;
+               }
+
+               if ((requesttype & USB_DIR_IN)) {
+                       printk(KERN_CONT "<<<");
+                       for (i = 0; i < size; i++)
+                               printk(KERN_CONT " %02x",
+                                      ((unsigned char *)data)[i]);
+               }
+               printk(KERN_CONT "\n");
+       }
+
+       return rc;
+}
+
+
+/*
+ * cx231xx_read_ctrl_reg()
+ * reads data from the usb device specifying bRequest and wValue
+ */
+int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg,
+                         char *buf, int len)
+{
+       u8 val = 0;
+       int ret;
+       int pipe = usb_rcvctrlpipe(dev->udev, 0);
+
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
+       if (len > URB_MAX_CTRL_SIZE)
+               return -EINVAL;
+
+       switch (len) {
+       case 1:
+               val = ENABLE_ONE_BYTE;
+               break;
+       case 2:
+               val = ENABLE_TWE_BYTE;
+               break;
+       case 3:
+               val = ENABLE_THREE_BYTE;
+               break;
+       case 4:
+               val = ENABLE_FOUR_BYTE;
+               break;
+       default:
+               val = 0xFF;     /* invalid option */
+       }
+
+       if (val == 0xFF)
+               return -EINVAL;
+
+       ret = __usb_control_msg(dev, pipe, req,
+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             val, reg, buf, len, HZ);
+       return ret;
+}
+
+int cx231xx_send_vendor_cmd(struct cx231xx *dev,
+                               struct VENDOR_REQUEST_IN *ven_req)
+{
+       int ret;
+       int pipe = 0;
+       int unsend_size = 0;
+       u8 *pdata;
+
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
+       if ((ven_req->wLength > URB_MAX_CTRL_SIZE))
+               return -EINVAL;
+
+       if (ven_req->direction)
+               pipe = usb_rcvctrlpipe(dev->udev, 0);
+       else
+               pipe = usb_sndctrlpipe(dev->udev, 0);
+
+       /*
+        * If the cx23102 read more than 4 bytes with i2c bus,
+        * need chop to 4 byte per request
+        */
+       if ((ven_req->wLength > 4) && ((ven_req->bRequest == 0x4) ||
+                                       (ven_req->bRequest == 0x5) ||
+                                       (ven_req->bRequest == 0x6))) {
+               unsend_size = 0;
+               pdata = ven_req->pBuff;
+
+
+               unsend_size = ven_req->wLength;
+
+               /* the first package */
+               ven_req->wValue = ven_req->wValue & 0xFFFB;
+               ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x2;
+               ret = __usb_control_msg(dev, pipe, ven_req->bRequest,
+                       ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       ven_req->wValue, ven_req->wIndex, pdata,
+                       0x0004, HZ);
+               unsend_size = unsend_size - 4;
+
+               /* the middle package */
+               ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x42;
+               while (unsend_size - 4 > 0) {
+                       pdata = pdata + 4;
+                       ret = __usb_control_msg(dev, pipe,
+                               ven_req->bRequest,
+                               ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               ven_req->wValue, ven_req->wIndex, pdata,
+                               0x0004, HZ);
+                       unsend_size = unsend_size - 4;
+               }
+
+               /* the last package */
+               ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x40;
+               pdata = pdata + 4;
+               ret = __usb_control_msg(dev, pipe, ven_req->bRequest,
+                       ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       ven_req->wValue, ven_req->wIndex, pdata,
+                       unsend_size, HZ);
+       } else {
+               ret = __usb_control_msg(dev, pipe, ven_req->bRequest,
+                               ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               ven_req->wValue, ven_req->wIndex,
+                               ven_req->pBuff, ven_req->wLength, HZ);
+       }
+
+       return ret;
+}
+
+/*
+ * cx231xx_write_ctrl_reg()
+ * sends data to the usb device, specifying bRequest
+ */
+int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf,
+                          int len)
+{
+       u8 val = 0;
+       int ret;
+       int pipe = usb_sndctrlpipe(dev->udev, 0);
+
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
+       if ((len < 1) || (len > URB_MAX_CTRL_SIZE))
+               return -EINVAL;
+
+       switch (len) {
+       case 1:
+               val = ENABLE_ONE_BYTE;
+               break;
+       case 2:
+               val = ENABLE_TWE_BYTE;
+               break;
+       case 3:
+               val = ENABLE_THREE_BYTE;
+               break;
+       case 4:
+               val = ENABLE_FOUR_BYTE;
+               break;
+       default:
+               val = 0xFF;     /* invalid option */
+       }
+
+       if (val == 0xFF)
+               return -EINVAL;
+
+       if (reg_debug) {
+               int byte;
+
+               cx231xx_isocdbg("(pipe 0x%08x): "
+                       "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>",
+                       pipe,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       req, 0, val, reg & 0xff,
+                       reg >> 8, len & 0xff, len >> 8);
+
+               for (byte = 0; byte < len; byte++)
+                       cx231xx_isocdbg(" %02x", (unsigned char)buf[byte]);
+               cx231xx_isocdbg("\n");
+       }
+
+       ret = __usb_control_msg(dev, pipe, req,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             val, reg, buf, len, HZ);
+
+       return ret;
+}
+
+/****************************************************************
+*           USB Alternate Setting functions                     *
+*****************************************************************/
+
+int cx231xx_set_video_alternate(struct cx231xx *dev)
+{
+       int errCode, prev_alt = dev->video_mode.alt;
+       unsigned int min_pkt_size = dev->width * 2 + 4;
+       u32 usb_interface_index = 0;
+
+       /* When image size is bigger than a certain value,
+          the frame size should be increased, otherwise, only
+          green screen will be received.
+        */
+       if (dev->width * 2 * dev->height > 720 * 240 * 2)
+               min_pkt_size *= 2;
+
+       if (dev->width > 360) {
+               /* resolutions: 720,704,640 */
+               dev->video_mode.alt = 3;
+       } else if (dev->width > 180) {
+               /* resolutions: 360,352,320,240 */
+               dev->video_mode.alt = 2;
+       } else if (dev->width > 0) {
+               /* resolutions: 180,176,160,128,88 */
+               dev->video_mode.alt = 1;
+       } else {
+               /* Change to alt0 BULK to release USB bandwidth */
+               dev->video_mode.alt = 0;
+       }
+
+       if (dev->USE_ISO == 0)
+               dev->video_mode.alt = 0;
+
+       cx231xx_coredbg("dev->video_mode.alt= %d\n", dev->video_mode.alt);
+
+       /* Get the correct video interface Index */
+       usb_interface_index =
+           dev->current_pcb_config.hs_config_info[0].interface_info.
+           video_index + 1;
+
+       if (dev->video_mode.alt != prev_alt) {
+               cx231xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
+                               min_pkt_size, dev->video_mode.alt);
+
+               if (dev->video_mode.alt_max_pkt_size != NULL)
+                       dev->video_mode.max_pkt_size =
+                       dev->video_mode.alt_max_pkt_size[dev->video_mode.alt];
+               cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
+                               dev->video_mode.alt,
+                               dev->video_mode.max_pkt_size);
+               errCode =
+                   usb_set_interface(dev->udev, usb_interface_index,
+                                     dev->video_mode.alt);
+               if (errCode < 0) {
+                       cx231xx_errdev
+                           ("cannot change alt number to %d (error=%i)\n",
+                            dev->video_mode.alt, errCode);
+                       return errCode;
+               }
+       }
+       return 0;
+}
+
+int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt)
+{
+       int status = 0;
+       u32 usb_interface_index = 0;
+       u32 max_pkt_size = 0;
+
+       switch (index) {
+       case INDEX_TS1:
+               usb_interface_index =
+                   dev->current_pcb_config.hs_config_info[0].interface_info.
+                   ts1_index + 1;
+               dev->ts1_mode.alt = alt;
+               if (dev->ts1_mode.alt_max_pkt_size != NULL)
+                       max_pkt_size = dev->ts1_mode.max_pkt_size =
+                           dev->ts1_mode.alt_max_pkt_size[dev->ts1_mode.alt];
+               break;
+       case INDEX_TS2:
+               usb_interface_index =
+                   dev->current_pcb_config.hs_config_info[0].interface_info.
+                   ts2_index + 1;
+               break;
+       case INDEX_AUDIO:
+               usb_interface_index =
+                   dev->current_pcb_config.hs_config_info[0].interface_info.
+                   audio_index + 1;
+               dev->adev.alt = alt;
+               if (dev->adev.alt_max_pkt_size != NULL)
+                       max_pkt_size = dev->adev.max_pkt_size =
+                           dev->adev.alt_max_pkt_size[dev->adev.alt];
+               break;
+       case INDEX_VIDEO:
+               usb_interface_index =
+                   dev->current_pcb_config.hs_config_info[0].interface_info.
+                   video_index + 1;
+               dev->video_mode.alt = alt;
+               if (dev->video_mode.alt_max_pkt_size != NULL)
+                       max_pkt_size = dev->video_mode.max_pkt_size =
+                           dev->video_mode.alt_max_pkt_size[dev->video_mode.
+                                                            alt];
+               break;
+       case INDEX_VANC:
+               if (dev->board.no_alt_vanc)
+                       return 0;
+               usb_interface_index =
+                   dev->current_pcb_config.hs_config_info[0].interface_info.
+                   vanc_index + 1;
+               dev->vbi_mode.alt = alt;
+               if (dev->vbi_mode.alt_max_pkt_size != NULL)
+                       max_pkt_size = dev->vbi_mode.max_pkt_size =
+                           dev->vbi_mode.alt_max_pkt_size[dev->vbi_mode.alt];
+               break;
+       case INDEX_HANC:
+               usb_interface_index =
+                   dev->current_pcb_config.hs_config_info[0].interface_info.
+                   hanc_index + 1;
+               dev->sliced_cc_mode.alt = alt;
+               if (dev->sliced_cc_mode.alt_max_pkt_size != NULL)
+                       max_pkt_size = dev->sliced_cc_mode.max_pkt_size =
+                           dev->sliced_cc_mode.alt_max_pkt_size[dev->
+                                                                sliced_cc_mode.
+                                                                alt];
+               break;
+       default:
+               break;
+       }
+
+       if (alt > 0 && max_pkt_size == 0) {
+               cx231xx_errdev
+               ("can't change interface %d alt no. to %d: Max. Pkt size = 0\n",
+               usb_interface_index, alt);
+               /*To workaround error number=-71 on EP0 for videograbber,
+                need add following codes.*/
+               if (dev->board.no_alt_vanc)
+                       return -1;
+       }
+
+       cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u,"
+                       "Interface = %d\n", alt, max_pkt_size,
+                       usb_interface_index);
+
+       if (usb_interface_index > 0) {
+               status = usb_set_interface(dev->udev, usb_interface_index, alt);
+               if (status < 0) {
+                       cx231xx_errdev
+                       ("can't change interface %d alt no. to %d (err=%i)\n",
+                       usb_interface_index, alt, status);
+                       return status;
+               }
+       }
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(cx231xx_set_alt_setting);
+
+int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio)
+{
+       int rc = 0;
+
+       if (!gpio)
+               return rc;
+
+       /* Send GPIO reset sequences specified at board entry */
+       while (gpio->sleep >= 0) {
+               rc = cx231xx_set_gpio_value(dev, gpio->bit, gpio->val);
+               if (rc < 0)
+                       return rc;
+
+               if (gpio->sleep > 0)
+                       msleep(gpio->sleep);
+
+               gpio++;
+       }
+       return rc;
+}
+
+int cx231xx_demod_reset(struct cx231xx *dev)
+{
+
+       u8 status = 0;
+       u8 value[4] = { 0, 0, 0, 0 };
+
+       status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
+                                value, 4);
+
+       cx231xx_coredbg("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN,
+                       value[0], value[1], value[2], value[3]);
+
+       cx231xx_coredbg("Enter cx231xx_demod_reset()\n");
+
+               value[1] = (u8) 0x3;
+               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                               PWR_CTL_EN, value, 4);
+                       msleep(10);
+
+               value[1] = (u8) 0x0;
+               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                               PWR_CTL_EN, value, 4);
+                       msleep(10);
+
+               value[1] = (u8) 0x3;
+               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                                               PWR_CTL_EN, value, 4);
+                       msleep(10);
+
+
+
+       status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
+                                value, 4);
+
+       cx231xx_coredbg("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN,
+                       value[0], value[1], value[2], value[3]);
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(cx231xx_demod_reset);
+int is_fw_load(struct cx231xx *dev)
+{
+       return cx231xx_check_fw(dev);
+}
+EXPORT_SYMBOL_GPL(is_fw_load);
+
+int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode)
+{
+       int errCode = 0;
+
+       if (dev->mode == set_mode)
+               return 0;
+
+       if (set_mode == CX231XX_SUSPEND) {
+               /* Set the chip in power saving mode */
+               dev->mode = set_mode;
+       }
+
+       /* Resource is locked */
+       if (dev->mode != CX231XX_SUSPEND)
+               return -EINVAL;
+
+       dev->mode = set_mode;
+
+       if (dev->mode == CX231XX_DIGITAL_MODE)/* Set Digital power mode */ {
+       /* set AGC mode to Digital */
+               switch (dev->model) {
+               case CX231XX_BOARD_CNXT_CARRAERA:
+               case CX231XX_BOARD_CNXT_RDE_250:
+               case CX231XX_BOARD_CNXT_SHELBY:
+               case CX231XX_BOARD_CNXT_RDU_250:
+               errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
+                       break;
+               case CX231XX_BOARD_CNXT_RDE_253S:
+               case CX231XX_BOARD_CNXT_RDU_253S:
+                       errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);
+                       break;
+               case CX231XX_BOARD_HAUPPAUGE_EXETER:
+                       errCode = cx231xx_set_power_mode(dev,
+                                               POLARIS_AVMODE_DIGITAL);
+                       break;
+               default:
+                       break;
+               }
+       } else/* Set Analog Power mode */ {
+       /* set AGC mode to Analog */
+               switch (dev->model) {
+               case CX231XX_BOARD_CNXT_CARRAERA:
+               case CX231XX_BOARD_CNXT_RDE_250:
+               case CX231XX_BOARD_CNXT_SHELBY:
+               case CX231XX_BOARD_CNXT_RDU_250:
+               errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);
+                       break;
+               case CX231XX_BOARD_CNXT_RDE_253S:
+               case CX231XX_BOARD_CNXT_RDU_253S:
+               case CX231XX_BOARD_HAUPPAUGE_EXETER:
+               case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
+               case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
+               case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
+               errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return errCode ? -EINVAL : 0;
+}
+EXPORT_SYMBOL_GPL(cx231xx_set_mode);
+
+int cx231xx_ep5_bulkout(struct cx231xx *dev, u8 *firmware, u16 size)
+{
+       int errCode = 0;
+       int actlen, ret = -ENOMEM;
+       u32 *buffer;
+
+       buffer = kzalloc(4096, GFP_KERNEL);
+       if (buffer == NULL) {
+               cx231xx_info("out of mem\n");
+               return -ENOMEM;
+       }
+       memcpy(&buffer[0], firmware, 4096);
+
+       ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 5),
+                       buffer, 4096, &actlen, 2000);
+
+       if (ret)
+               cx231xx_info("bulk message failed: %d (%d/%d)", ret,
+                               size, actlen);
+       else {
+               errCode = actlen != size ? -1 : 0;
+       }
+       kfree(buffer);
+       return errCode;
+}
+
+/*****************************************************************
+*                URB Streaming functions                         *
+******************************************************************/
+
+/*
+ * IRQ callback, called by URB callback
+ */
+static void cx231xx_isoc_irq_callback(struct urb *urb)
+{
+       struct cx231xx_dmaqueue *dma_q = urb->context;
+       struct cx231xx_video_mode *vmode =
+           container_of(dma_q, struct cx231xx_video_mode, vidq);
+       struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode);
+       int i;
+
+       switch (urb->status) {
+       case 0:         /* success */
+       case -ETIMEDOUT:        /* NAK */
+               break;
+       case -ECONNRESET:       /* kill */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+       default:                /* error */
+               cx231xx_isocdbg("urb completition error %d.\n", urb->status);
+               break;
+       }
+
+       /* Copy data from URB */
+       spin_lock(&dev->video_mode.slock);
+       dev->video_mode.isoc_ctl.isoc_copy(dev, urb);
+       spin_unlock(&dev->video_mode.slock);
+
+       /* Reset urb buffers */
+       for (i = 0; i < urb->number_of_packets; i++) {
+               urb->iso_frame_desc[i].status = 0;
+               urb->iso_frame_desc[i].actual_length = 0;
+       }
+
+       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (urb->status) {
+               cx231xx_isocdbg("urb resubmit failed (error=%i)\n",
+                               urb->status);
+       }
+}
+/*****************************************************************
+*                URB Streaming functions                         *
+******************************************************************/
+
+/*
+ * IRQ callback, called by URB callback
+ */
+static void cx231xx_bulk_irq_callback(struct urb *urb)
+{
+       struct cx231xx_dmaqueue *dma_q = urb->context;
+       struct cx231xx_video_mode *vmode =
+           container_of(dma_q, struct cx231xx_video_mode, vidq);
+       struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode);
+
+       switch (urb->status) {
+       case 0:         /* success */
+       case -ETIMEDOUT:        /* NAK */
+               break;
+       case -ECONNRESET:       /* kill */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+       default:                /* error */
+               cx231xx_isocdbg("urb completition error %d.\n", urb->status);
+               break;
+       }
+
+       /* Copy data from URB */
+       spin_lock(&dev->video_mode.slock);
+       dev->video_mode.bulk_ctl.bulk_copy(dev, urb);
+       spin_unlock(&dev->video_mode.slock);
+
+       /* Reset urb buffers */
+       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (urb->status) {
+               cx231xx_isocdbg("urb resubmit failed (error=%i)\n",
+                               urb->status);
+       }
+}
+/*
+ * Stop and Deallocate URBs
+ */
+void cx231xx_uninit_isoc(struct cx231xx *dev)
+{
+       struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq;
+       struct urb *urb;
+       int i;
+
+       cx231xx_isocdbg("cx231xx: called cx231xx_uninit_isoc\n");
+
+       dev->video_mode.isoc_ctl.nfields = -1;
+       for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
+               urb = dev->video_mode.isoc_ctl.urb[i];
+               if (urb) {
+                       if (!irqs_disabled())
+                               usb_kill_urb(urb);
+                       else
+                               usb_unlink_urb(urb);
+
+                       if (dev->video_mode.isoc_ctl.transfer_buffer[i]) {
+                               usb_free_coherent(dev->udev,
+                                                 urb->transfer_buffer_length,
+                                                 dev->video_mode.isoc_ctl.
+                                                 transfer_buffer[i],
+                                                 urb->transfer_dma);
+                       }
+                       usb_free_urb(urb);
+                       dev->video_mode.isoc_ctl.urb[i] = NULL;
+               }
+               dev->video_mode.isoc_ctl.transfer_buffer[i] = NULL;
+       }
+
+       kfree(dev->video_mode.isoc_ctl.urb);
+       kfree(dev->video_mode.isoc_ctl.transfer_buffer);
+       kfree(dma_q->p_left_data);
+
+       dev->video_mode.isoc_ctl.urb = NULL;
+       dev->video_mode.isoc_ctl.transfer_buffer = NULL;
+       dev->video_mode.isoc_ctl.num_bufs = 0;
+       dma_q->p_left_data = NULL;
+
+       if (dev->mode_tv == 0)
+               cx231xx_capture_start(dev, 0, Raw_Video);
+       else
+               cx231xx_capture_start(dev, 0, TS1_serial_mode);
+
+
+}
+EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc);
+
+/*
+ * Stop and Deallocate URBs
+ */
+void cx231xx_uninit_bulk(struct cx231xx *dev)
+{
+       struct urb *urb;
+       int i;
+
+       cx231xx_isocdbg("cx231xx: called cx231xx_uninit_bulk\n");
+
+       dev->video_mode.bulk_ctl.nfields = -1;
+       for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) {
+               urb = dev->video_mode.bulk_ctl.urb[i];
+               if (urb) {
+                       if (!irqs_disabled())
+                               usb_kill_urb(urb);
+                       else
+                               usb_unlink_urb(urb);
+
+                       if (dev->video_mode.bulk_ctl.transfer_buffer[i]) {
+                               usb_free_coherent(dev->udev,
+                                               urb->transfer_buffer_length,
+                                               dev->video_mode.isoc_ctl.
+                                               transfer_buffer[i],
+                                               urb->transfer_dma);
+                       }
+                       usb_free_urb(urb);
+                       dev->video_mode.bulk_ctl.urb[i] = NULL;
+               }
+               dev->video_mode.bulk_ctl.transfer_buffer[i] = NULL;
+       }
+
+       kfree(dev->video_mode.bulk_ctl.urb);
+       kfree(dev->video_mode.bulk_ctl.transfer_buffer);
+
+       dev->video_mode.bulk_ctl.urb = NULL;
+       dev->video_mode.bulk_ctl.transfer_buffer = NULL;
+       dev->video_mode.bulk_ctl.num_bufs = 0;
+
+       if (dev->mode_tv == 0)
+               cx231xx_capture_start(dev, 0, Raw_Video);
+       else
+               cx231xx_capture_start(dev, 0, TS1_serial_mode);
+
+
+}
+EXPORT_SYMBOL_GPL(cx231xx_uninit_bulk);
+
+/*
+ * Allocate URBs and start IRQ
+ */
+int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
+                     int num_bufs, int max_pkt_size,
+                     int (*isoc_copy) (struct cx231xx *dev, struct urb *urb))
+{
+       struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq;
+       int i;
+       int sb_size, pipe;
+       struct urb *urb;
+       int j, k;
+       int rc;
+
+       /* De-allocates all pending stuff */
+       cx231xx_uninit_isoc(dev);
+
+       dma_q->p_left_data = kzalloc(4096, GFP_KERNEL);
+       if (dma_q->p_left_data == NULL) {
+               cx231xx_info("out of mem\n");
+               return -ENOMEM;
+       }
+
+
+
+       dev->video_mode.isoc_ctl.isoc_copy = isoc_copy;
+       dev->video_mode.isoc_ctl.num_bufs = num_bufs;
+       dma_q->pos = 0;
+       dma_q->is_partial_line = 0;
+       dma_q->last_sav = 0;
+       dma_q->current_field = -1;
+       dma_q->field1_done = 0;
+       dma_q->lines_per_field = dev->height / 2;
+       dma_q->bytes_left_in_line = dev->width << 1;
+       dma_q->lines_completed = 0;
+       dma_q->mpeg_buffer_done = 0;
+       dma_q->left_data_count = 0;
+       dma_q->mpeg_buffer_completed = 0;
+       dma_q->add_ps_package_head = CX231XX_NEED_ADD_PS_PACKAGE_HEAD;
+       dma_q->ps_head[0] = 0x00;
+       dma_q->ps_head[1] = 0x00;
+       dma_q->ps_head[2] = 0x01;
+       dma_q->ps_head[3] = 0xBA;
+       for (i = 0; i < 8; i++)
+               dma_q->partial_buf[i] = 0;
+
+       dev->video_mode.isoc_ctl.urb =
+           kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
+       if (!dev->video_mode.isoc_ctl.urb) {
+               cx231xx_errdev("cannot alloc memory for usb buffers\n");
+               return -ENOMEM;
+       }
+
+       dev->video_mode.isoc_ctl.transfer_buffer =
+           kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
+       if (!dev->video_mode.isoc_ctl.transfer_buffer) {
+               cx231xx_errdev("cannot allocate memory for usbtransfer\n");
+               kfree(dev->video_mode.isoc_ctl.urb);
+               return -ENOMEM;
+       }
+
+       dev->video_mode.isoc_ctl.max_pkt_size = max_pkt_size;
+       dev->video_mode.isoc_ctl.buf = NULL;
+
+       sb_size = max_packets * dev->video_mode.isoc_ctl.max_pkt_size;
+
+       if (dev->mode_tv == 1)
+               dev->video_mode.end_point_addr = 0x81;
+       else
+               dev->video_mode.end_point_addr = 0x84;
+
+
+       /* allocate urbs and transfer buffers */
+       for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
+               urb = usb_alloc_urb(max_packets, GFP_KERNEL);
+               if (!urb) {
+                       cx231xx_err("cannot alloc isoc_ctl.urb %i\n", i);
+                       cx231xx_uninit_isoc(dev);
+                       return -ENOMEM;
+               }
+               dev->video_mode.isoc_ctl.urb[i] = urb;
+
+               dev->video_mode.isoc_ctl.transfer_buffer[i] =
+                   usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,
+                                      &urb->transfer_dma);
+               if (!dev->video_mode.isoc_ctl.transfer_buffer[i]) {
+                       cx231xx_err("unable to allocate %i bytes for transfer"
+                                   " buffer %i%s\n",
+                                   sb_size, i,
+                                   in_interrupt() ? " while in int" : "");
+                       cx231xx_uninit_isoc(dev);
+                       return -ENOMEM;
+               }
+               memset(dev->video_mode.isoc_ctl.transfer_buffer[i], 0, sb_size);
+
+               pipe =
+                   usb_rcvisocpipe(dev->udev, dev->video_mode.end_point_addr);
+
+               usb_fill_int_urb(urb, dev->udev, pipe,
+                                dev->video_mode.isoc_ctl.transfer_buffer[i],
+                                sb_size, cx231xx_isoc_irq_callback, dma_q, 1);
+
+               urb->number_of_packets = max_packets;
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+
+               k = 0;
+               for (j = 0; j < max_packets; j++) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length =
+                           dev->video_mode.isoc_ctl.max_pkt_size;
+                       k += dev->video_mode.isoc_ctl.max_pkt_size;
+               }
+       }
+
+       init_waitqueue_head(&dma_q->wq);
+
+       /* submit urbs and enables IRQ */
+       for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
+               rc = usb_submit_urb(dev->video_mode.isoc_ctl.urb[i],
+                                   GFP_ATOMIC);
+               if (rc) {
+                       cx231xx_err("submit of urb %i failed (error=%i)\n", i,
+                                   rc);
+                       cx231xx_uninit_isoc(dev);
+                       return rc;
+               }
+       }
+
+       if (dev->mode_tv == 0)
+               cx231xx_capture_start(dev, 1, Raw_Video);
+       else
+               cx231xx_capture_start(dev, 1, TS1_serial_mode);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cx231xx_init_isoc);
+
+/*
+ * Allocate URBs and start IRQ
+ */
+int cx231xx_init_bulk(struct cx231xx *dev, int max_packets,
+                     int num_bufs, int max_pkt_size,
+                     int (*bulk_copy) (struct cx231xx *dev, struct urb *urb))
+{
+       struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq;
+       int i;
+       int sb_size, pipe;
+       struct urb *urb;
+       int rc;
+
+       dev->video_input = dev->video_input > 2 ? 2 : dev->video_input;
+
+       cx231xx_coredbg("Setting Video mux to %d\n", dev->video_input);
+
+       video_mux(dev, dev->video_input);
+
+       /* De-allocates all pending stuff */
+       cx231xx_uninit_bulk(dev);
+
+       dev->video_mode.bulk_ctl.bulk_copy = bulk_copy;
+       dev->video_mode.bulk_ctl.num_bufs = num_bufs;
+       dma_q->pos = 0;
+       dma_q->is_partial_line = 0;
+       dma_q->last_sav = 0;
+       dma_q->current_field = -1;
+       dma_q->field1_done = 0;
+       dma_q->lines_per_field = dev->height / 2;
+       dma_q->bytes_left_in_line = dev->width << 1;
+       dma_q->lines_completed = 0;
+       dma_q->mpeg_buffer_done = 0;
+       dma_q->left_data_count = 0;
+       dma_q->mpeg_buffer_completed = 0;
+       dma_q->ps_head[0] = 0x00;
+       dma_q->ps_head[1] = 0x00;
+       dma_q->ps_head[2] = 0x01;
+       dma_q->ps_head[3] = 0xBA;
+       for (i = 0; i < 8; i++)
+               dma_q->partial_buf[i] = 0;
+
+       dev->video_mode.bulk_ctl.urb =
+           kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
+       if (!dev->video_mode.bulk_ctl.urb) {
+               cx231xx_errdev("cannot alloc memory for usb buffers\n");
+               return -ENOMEM;
+       }
+
+       dev->video_mode.bulk_ctl.transfer_buffer =
+           kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
+       if (!dev->video_mode.bulk_ctl.transfer_buffer) {
+               cx231xx_errdev("cannot allocate memory for usbtransfer\n");
+               kfree(dev->video_mode.bulk_ctl.urb);
+               return -ENOMEM;
+       }
+
+       dev->video_mode.bulk_ctl.max_pkt_size = max_pkt_size;
+       dev->video_mode.bulk_ctl.buf = NULL;
+
+       sb_size = max_packets * dev->video_mode.bulk_ctl.max_pkt_size;
+
+       if (dev->mode_tv == 1)
+               dev->video_mode.end_point_addr = 0x81;
+       else
+               dev->video_mode.end_point_addr = 0x84;
+
+
+       /* allocate urbs and transfer buffers */
+       for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) {
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!urb) {
+                       cx231xx_err("cannot alloc bulk_ctl.urb %i\n", i);
+                       cx231xx_uninit_bulk(dev);
+                       return -ENOMEM;
+               }
+               dev->video_mode.bulk_ctl.urb[i] = urb;
+               urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+
+               dev->video_mode.bulk_ctl.transfer_buffer[i] =
+                   usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,
+                                    &urb->transfer_dma);
+               if (!dev->video_mode.bulk_ctl.transfer_buffer[i]) {
+                       cx231xx_err("unable to allocate %i bytes for transfer"
+                                   " buffer %i%s\n",
+                                   sb_size, i,
+                                   in_interrupt() ? " while in int" : "");
+                       cx231xx_uninit_bulk(dev);
+                       return -ENOMEM;
+               }
+               memset(dev->video_mode.bulk_ctl.transfer_buffer[i], 0, sb_size);
+
+               pipe = usb_rcvbulkpipe(dev->udev,
+                                dev->video_mode.end_point_addr);
+               usb_fill_bulk_urb(urb, dev->udev, pipe,
+                                 dev->video_mode.bulk_ctl.transfer_buffer[i],
+                                 sb_size, cx231xx_bulk_irq_callback, dma_q);
+       }
+
+       init_waitqueue_head(&dma_q->wq);
+
+       /* submit urbs and enables IRQ */
+       for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) {
+               rc = usb_submit_urb(dev->video_mode.bulk_ctl.urb[i],
+                                   GFP_ATOMIC);
+               if (rc) {
+                       cx231xx_err("submit of urb %i failed (error=%i)\n", i,
+                                   rc);
+                       cx231xx_uninit_bulk(dev);
+                       return rc;
+               }
+       }
+
+       if (dev->mode_tv == 0)
+               cx231xx_capture_start(dev, 1, Raw_Video);
+       else
+               cx231xx_capture_start(dev, 1, TS1_serial_mode);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cx231xx_init_bulk);
+void cx231xx_stop_TS1(struct cx231xx *dev)
+{
+       u8 val[4] = { 0, 0, 0, 0 };
+
+       val[0] = 0x00;
+       val[1] = 0x03;
+       val[2] = 0x00;
+       val[3] = 0x00;
+       cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                       TS_MODE_REG, val, 4);
+
+       val[0] = 0x00;
+       val[1] = 0x70;
+       val[2] = 0x04;
+       val[3] = 0x00;
+       cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                       TS1_CFG_REG, val, 4);
+}
+/* EXPORT_SYMBOL_GPL(cx231xx_stop_TS1); */
+void cx231xx_start_TS1(struct cx231xx *dev)
+{
+       u8 val[4] = { 0, 0, 0, 0 };
+
+       val[0] = 0x03;
+       val[1] = 0x03;
+       val[2] = 0x00;
+       val[3] = 0x00;
+       cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                       TS_MODE_REG, val, 4);
+
+       val[0] = 0x04;
+       val[1] = 0xA3;
+       val[2] = 0x3B;
+       val[3] = 0x00;
+       cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+                       TS1_CFG_REG, val, 4);
+}
+/* EXPORT_SYMBOL_GPL(cx231xx_start_TS1); */
+/*****************************************************************
+*             Device Init/UnInit functions                       *
+******************************************************************/
+int cx231xx_dev_init(struct cx231xx *dev)
+{
+       int errCode = 0;
+
+       /* Initialize I2C bus */
+
+       /* External Master 1 Bus */
+       dev->i2c_bus[0].nr = 0;
+       dev->i2c_bus[0].dev = dev;
+       dev->i2c_bus[0].i2c_period = I2C_SPEED_100K;    /* 100 KHz */
+       dev->i2c_bus[0].i2c_nostop = 0;
+       dev->i2c_bus[0].i2c_reserve = 0;
+
+       /* External Master 2 Bus */
+       dev->i2c_bus[1].nr = 1;
+       dev->i2c_bus[1].dev = dev;
+       dev->i2c_bus[1].i2c_period = I2C_SPEED_100K;    /* 100 KHz */
+       dev->i2c_bus[1].i2c_nostop = 0;
+       dev->i2c_bus[1].i2c_reserve = 0;
+
+       /* Internal Master 3 Bus */
+       dev->i2c_bus[2].nr = 2;
+       dev->i2c_bus[2].dev = dev;
+       dev->i2c_bus[2].i2c_period = I2C_SPEED_100K;    /* 100kHz */
+       dev->i2c_bus[2].i2c_nostop = 0;
+       dev->i2c_bus[2].i2c_reserve = 0;
+
+       /* register I2C buses */
+       cx231xx_i2c_register(&dev->i2c_bus[0]);
+       cx231xx_i2c_register(&dev->i2c_bus[1]);
+       cx231xx_i2c_register(&dev->i2c_bus[2]);
+
+       /* init hardware */
+       /* Note : with out calling set power mode function,
+       afe can not be set up correctly */
+       if (dev->board.external_av) {
+               errCode = cx231xx_set_power_mode(dev,
+                                POLARIS_AVMODE_ENXTERNAL_AV);
+               if (errCode < 0) {
+                       cx231xx_errdev
+                       ("%s: Failed to set Power - errCode [%d]!\n",
+                       __func__, errCode);
+                       return errCode;
+               }
+       } else {
+               errCode = cx231xx_set_power_mode(dev,
+                                POLARIS_AVMODE_ANALOGT_TV);
+               if (errCode < 0) {
+                       cx231xx_errdev
+                       ("%s: Failed to set Power - errCode [%d]!\n",
+                       __func__, errCode);
+                       return errCode;
+               }
+       }
+
+       /* reset the Tuner, if it is a Xceive tuner */
+       if ((dev->board.tuner_type == TUNER_XC5000) ||
+           (dev->board.tuner_type == TUNER_XC2028))
+                       cx231xx_gpio_set(dev, dev->board.tuner_gpio);
+
+       /* initialize Colibri block */
+       errCode = cx231xx_afe_init_super_block(dev, 0x23c);
+       if (errCode < 0) {
+               cx231xx_errdev
+                   ("%s: cx231xx_afe init super block - errCode [%d]!\n",
+                    __func__, errCode);
+               return errCode;
+       }
+       errCode = cx231xx_afe_init_channels(dev);
+       if (errCode < 0) {
+               cx231xx_errdev
+                   ("%s: cx231xx_afe init channels - errCode [%d]!\n",
+                    __func__, errCode);
+               return errCode;
+       }
+
+       /* Set DIF in By pass mode */
+       errCode = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
+       if (errCode < 0) {
+               cx231xx_errdev
+                   ("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n",
+                    __func__, errCode);
+               return errCode;
+       }
+
+       /* I2S block related functions */
+       errCode = cx231xx_i2s_blk_initialize(dev);
+       if (errCode < 0) {
+               cx231xx_errdev
+                   ("%s: cx231xx_i2s block initialize - errCode [%d]!\n",
+                    __func__, errCode);
+               return errCode;
+       }
+
+       /* init control pins */
+       errCode = cx231xx_init_ctrl_pin_status(dev);
+       if (errCode < 0) {
+               cx231xx_errdev("%s: cx231xx_init ctrl pins - errCode [%d]!\n",
+                              __func__, errCode);
+               return errCode;
+       }
+
+       /* set AGC mode to Analog */
+       switch (dev->model) {
+       case CX231XX_BOARD_CNXT_CARRAERA:
+       case CX231XX_BOARD_CNXT_RDE_250:
+       case CX231XX_BOARD_CNXT_SHELBY:
+       case CX231XX_BOARD_CNXT_RDU_250:
+       errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);
+               break;
+       case CX231XX_BOARD_CNXT_RDE_253S:
+       case CX231XX_BOARD_CNXT_RDU_253S:
+       case CX231XX_BOARD_HAUPPAUGE_EXETER:
+       case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
+       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
+       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
+       errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
+               break;
+       default:
+               break;
+       }
+       if (errCode < 0) {
+               cx231xx_errdev
+                   ("%s: cx231xx_AGC mode to Analog - errCode [%d]!\n",
+                    __func__, errCode);
+               return errCode;
+       }
+
+       /* set all alternate settings to zero initially */
+       cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);
+       cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
+       cx231xx_set_alt_setting(dev, INDEX_HANC, 0);
+       if (dev->board.has_dvb)
+               cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
+
+       /* set the I2C master port to 3 on channel 1 */
+       errCode = cx231xx_enable_i2c_port_3(dev, true);
+
+       return errCode;
+}
+EXPORT_SYMBOL_GPL(cx231xx_dev_init);
+
+void cx231xx_dev_uninit(struct cx231xx *dev)
+{
+       /* Un Initialize I2C bus */
+       cx231xx_i2c_unregister(&dev->i2c_bus[2]);
+       cx231xx_i2c_unregister(&dev->i2c_bus[1]);
+       cx231xx_i2c_unregister(&dev->i2c_bus[0]);
+}
+EXPORT_SYMBOL_GPL(cx231xx_dev_uninit);
+
+/*****************************************************************
+*              G P I O related functions                         *
+******************************************************************/
+int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val,
+                         u8 len, u8 request, u8 direction)
+{
+       int status = 0;
+       struct VENDOR_REQUEST_IN ven_req;
+
+       /* Set wValue */
+       ven_req.wValue = (u16) (gpio_bit >> 16 & 0xffff);
+
+       /* set request */
+       if (!request) {
+               if (direction)
+                       ven_req.bRequest = VRT_GET_GPIO;        /* 0x8 gpio */
+               else
+                       ven_req.bRequest = VRT_SET_GPIO;        /* 0x9 gpio */
+       } else {
+               if (direction)
+                       ven_req.bRequest = VRT_GET_GPIE;        /* 0xa gpie */
+               else
+                       ven_req.bRequest = VRT_SET_GPIE;        /* 0xb gpie */
+       }
+
+       /* set index value */
+       ven_req.wIndex = (u16) (gpio_bit & 0xffff);
+
+       /* set wLength value */
+       ven_req.wLength = len;
+
+       /* set bData value */
+       ven_req.bData = 0;
+
+       /* set the buffer for read / write */
+       ven_req.pBuff = gpio_val;
+
+       /* set the direction */
+       if (direction) {
+               ven_req.direction = USB_DIR_IN;
+               memset(ven_req.pBuff, 0x00, ven_req.wLength);
+       } else
+               ven_req.direction = USB_DIR_OUT;
+
+
+       /* call common vendor command request */
+       status = cx231xx_send_vendor_cmd(dev, &ven_req);
+       if (status < 0) {
+               cx231xx_info
+                   ("UsbInterface::sendCommand, failed with status -%d\n",
+                    status);
+       }
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(cx231xx_send_gpio_cmd);
+
+/*****************************************************************
+ *    C O N T R O L - Register R E A D / W R I T E functions     *
+ *****************************************************************/
+int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode)
+{
+       u8 value[4] = { 0x0, 0x0, 0x0, 0x0 };
+       u32 tmp = 0;
+       int status = 0;
+
+       status =
+           cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, address, value, 4);
+       if (status < 0)
+               return status;
+
+       tmp = *((u32 *) value);
+       tmp |= mode;
+
+       value[0] = (u8) tmp;
+       value[1] = (u8) (tmp >> 8);
+       value[2] = (u8) (tmp >> 16);
+       value[3] = (u8) (tmp >> 24);
+
+       status =
+           cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, address, value, 4);
+
+       return status;
+}
+
+/*****************************************************************
+ *            I 2 C Internal C O N T R O L   functions           *
+ *****************************************************************/
+int cx231xx_read_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,
+                         u8 saddr_len, u32 *data, u8 data_len, int master)
+{
+       int status = 0;
+       struct cx231xx_i2c_xfer_data req_data;
+       u8 value[64] = "0";
+
+       if (saddr_len == 0)
+               saddr = 0;
+       else if (saddr_len == 1)
+               saddr &= 0xff;
+
+       /* prepare xfer_data struct */
+       req_data.dev_addr = dev_addr >> 1;
+       req_data.direction = I2C_M_RD;
+       req_data.saddr_len = saddr_len;
+       req_data.saddr_dat = saddr;
+       req_data.buf_size = data_len;
+       req_data.p_buffer = (u8 *) value;
+
+       /* usb send command */
+       if (master == 0)
+               status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0],
+                                        &req_data);
+       else if (master == 1)
+               status = dev->cx231xx_send_usb_command(&dev->i2c_bus[1],
+                                        &req_data);
+       else if (master == 2)
+               status = dev->cx231xx_send_usb_command(&dev->i2c_bus[2],
+                                        &req_data);
+
+       if (status >= 0) {
+               /* Copy the data read back to main buffer */
+               if (data_len == 1)
+                       *data = value[0];
+               else if (data_len == 4)
+                       *data =
+                           value[0] | value[1] << 8 | value[2] << 16 | value[3]
+                           << 24;
+               else if (data_len > 4)
+                       *data = value[saddr];
+       }
+
+       return status;
+}
+
+int cx231xx_write_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,
+                          u8 saddr_len, u32 data, u8 data_len, int master)
+{
+       int status = 0;
+       u8 value[4] = { 0, 0, 0, 0 };
+       struct cx231xx_i2c_xfer_data req_data;
+
+       value[0] = (u8) data;
+       value[1] = (u8) (data >> 8);
+       value[2] = (u8) (data >> 16);
+       value[3] = (u8) (data >> 24);
+
+       if (saddr_len == 0)
+               saddr = 0;
+       else if (saddr_len == 1)
+               saddr &= 0xff;
+
+       /* prepare xfer_data struct */
+       req_data.dev_addr = dev_addr >> 1;
+       req_data.direction = 0;
+       req_data.saddr_len = saddr_len;
+       req_data.saddr_dat = saddr;
+       req_data.buf_size = data_len;
+       req_data.p_buffer = value;
+
+       /* usb send command */
+       if (master == 0)
+               status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0],
+                                &req_data);
+       else if (master == 1)
+               status = dev->cx231xx_send_usb_command(&dev->i2c_bus[1],
+                                &req_data);
+       else if (master == 2)
+               status = dev->cx231xx_send_usb_command(&dev->i2c_bus[2],
+                                &req_data);
+
+       return status;
+}
+
+int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr,
+                         u8 saddr_len, u32 *data, u8 data_len)
+{
+       int status = 0;
+       struct cx231xx_i2c_xfer_data req_data;
+       u8 value[4] = { 0, 0, 0, 0 };
+
+       if (saddr_len == 0)
+               saddr = 0;
+       else if (saddr_len == 1)
+               saddr &= 0xff;
+
+       /* prepare xfer_data struct */
+       req_data.dev_addr = dev_addr >> 1;
+       req_data.direction = I2C_M_RD;
+       req_data.saddr_len = saddr_len;
+       req_data.saddr_dat = saddr;
+       req_data.buf_size = data_len;
+       req_data.p_buffer = (u8 *) value;
+
+       /* usb send command */
+       status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data);
+
+       if (status >= 0) {
+               /* Copy the data read back to main buffer */
+               if (data_len == 1)
+                       *data = value[0];
+               else
+                       *data =
+                           value[0] | value[1] << 8 | value[2] << 16 | value[3]
+                           << 24;
+       }
+
+       return status;
+}
+
+int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr,
+                          u8 saddr_len, u32 data, u8 data_len)
+{
+       int status = 0;
+       u8 value[4] = { 0, 0, 0, 0 };
+       struct cx231xx_i2c_xfer_data req_data;
+
+       value[0] = (u8) data;
+       value[1] = (u8) (data >> 8);
+       value[2] = (u8) (data >> 16);
+       value[3] = (u8) (data >> 24);
+
+       if (saddr_len == 0)
+               saddr = 0;
+       else if (saddr_len == 1)
+               saddr &= 0xff;
+
+       /* prepare xfer_data struct */
+       req_data.dev_addr = dev_addr >> 1;
+       req_data.direction = 0;
+       req_data.saddr_len = saddr_len;
+       req_data.saddr_dat = saddr;
+       req_data.buf_size = data_len;
+       req_data.p_buffer = value;
+
+       /* usb send command */
+       status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data);
+
+       return status;
+}
+
+int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size,
+                          u16 register_address, u8 bit_start, u8 bit_end,
+                          u32 value)
+{
+       int status = 0;
+       u32 tmp;
+       u32 mask = 0;
+       int i;
+
+       if (bit_start > (size - 1) || bit_end > (size - 1))
+               return -1;
+
+       if (size == 8) {
+               status =
+                   cx231xx_read_i2c_data(dev, dev_addr, register_address, 2,
+                                         &tmp, 1);
+       } else {
+               status =
+                   cx231xx_read_i2c_data(dev, dev_addr, register_address, 2,
+                                         &tmp, 4);
+       }
+
+       if (status < 0)
+               return status;
+
+       mask = 1 << bit_end;
+       for (i = bit_end; i > bit_start && i > 0; i--)
+               mask = mask + (1 << (i - 1));
+
+       value <<= bit_start;
+
+       if (size == 8) {
+               tmp &= ~mask;
+               tmp |= value;
+               tmp &= 0xff;
+               status =
+                   cx231xx_write_i2c_data(dev, dev_addr, register_address, 2,
+                                          tmp, 1);
+       } else {
+               tmp &= ~mask;
+               tmp |= value;
+               status =
+                   cx231xx_write_i2c_data(dev, dev_addr, register_address, 2,
+                                          tmp, 4);
+       }
+
+       return status;
+}
+
+int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr,
+                                       u16 saddr, u32 mask, u32 value)
+{
+       u32 temp;
+       int status = 0;
+
+       status = cx231xx_read_i2c_data(dev, dev_addr, saddr, 2, &temp, 4);
+
+       if (status < 0)
+               return status;
+
+       temp &= ~mask;
+       temp |= value;
+
+       status = cx231xx_write_i2c_data(dev, dev_addr, saddr, 2, temp, 4);
+
+       return status;
+}
+
+u32 cx231xx_set_field(u32 field_mask, u32 data)
+{
+       u32 temp;
+
+       for (temp = field_mask; (temp & 1) == 0; temp >>= 1)
+               data <<= 1;
+
+       return data;
+}
diff --git a/drivers/media/usb/cx231xx/cx231xx-dif.h b/drivers/media/usb/cx231xx/cx231xx-dif.h
new file mode 100644 (file)
index 0000000..2b63c2f
--- /dev/null
@@ -0,0 +1,3178 @@
+/*
+ *  cx231xx-dif.h - driver for Conexant Cx23100/101/102 USB video capture devices
+ *
+ *  Copyright {C} 2009 <Bill.Liu@conexant.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.
+ *
+ *  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.
+ */
+
+#ifndef _CX231XX_DIF_H
+#define _CX231XX_DIF_H
+
+#include "cx231xx-reg.h"
+
+struct dif_settings{
+       u32 if_freq;
+       u32 register_address;
+       u32 value;
+};
+
+static struct dif_settings Dif_set_array[] = {
+
+/*case 3000000:*/
+/* BEGIN - DIF BPF register values from 30_quant.dat*/
+{3000000, DIF_BPF_COEFF01,    0x00000002},
+{3000000, DIF_BPF_COEFF23,    0x00080012},
+{3000000, DIF_BPF_COEFF45,    0x001e0024},
+{3000000, DIF_BPF_COEFF67,    0x001bfff8},
+{3000000, DIF_BPF_COEFF89,    0xffb4ff50},
+{3000000, DIF_BPF_COEFF1011,  0xfed8fe68},
+{3000000, DIF_BPF_COEFF1213,  0xfe24fe34},
+{3000000, DIF_BPF_COEFF1415,  0xfebaffc7},
+{3000000, DIF_BPF_COEFF1617,  0x014d031f},
+{3000000, DIF_BPF_COEFF1819,  0x04f0065d},
+{3000000, DIF_BPF_COEFF2021,  0x07010688},
+{3000000, DIF_BPF_COEFF2223,  0x04c901d6},
+{3000000, DIF_BPF_COEFF2425,  0xfe00f9d3},
+{3000000, DIF_BPF_COEFF2627,  0xf600f342},
+{3000000, DIF_BPF_COEFF2829,  0xf235f337},
+{3000000, DIF_BPF_COEFF3031,  0xf64efb22},
+{3000000, DIF_BPF_COEFF3233,  0x0105070f},
+{3000000, DIF_BPF_COEFF3435,  0x0c460fce},
+{3000000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 30_quant.dat*/
+
+
+/*case 3100000:*/
+/* BEGIN - DIF BPF register values from 31_quant.dat*/
+{3100000, DIF_BPF_COEFF01,    0x00000001},
+{3100000, DIF_BPF_COEFF23,    0x00070012},
+{3100000, DIF_BPF_COEFF45,    0x00220032},
+{3100000, DIF_BPF_COEFF67,    0x00370026},
+{3100000, DIF_BPF_COEFF89,    0xfff0ff91},
+{3100000, DIF_BPF_COEFF1011,  0xff0efe7c},
+{3100000, DIF_BPF_COEFF1213,  0xfe01fdcc},
+{3100000, DIF_BPF_COEFF1415,  0xfe0afedb},
+{3100000, DIF_BPF_COEFF1617,  0x00440224},
+{3100000, DIF_BPF_COEFF1819,  0x0434060c},
+{3100000, DIF_BPF_COEFF2021,  0x0738074e},
+{3100000, DIF_BPF_COEFF2223,  0x06090361},
+{3100000, DIF_BPF_COEFF2425,  0xff99fb39},
+{3100000, DIF_BPF_COEFF2627,  0xf6fef3b6},
+{3100000, DIF_BPF_COEFF2829,  0xf21af2a5},
+{3100000, DIF_BPF_COEFF3031,  0xf573fa33},
+{3100000, DIF_BPF_COEFF3233,  0x0034067d},
+{3100000, DIF_BPF_COEFF3435,  0x0bfb0fb9},
+{3100000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 31_quant.dat*/
+
+
+/*case 3200000:*/
+/* BEGIN - DIF BPF register values from 32_quant.dat*/
+{3200000, DIF_BPF_COEFF01,    0x00000000},
+{3200000, DIF_BPF_COEFF23,    0x0004000e},
+{3200000, DIF_BPF_COEFF45,    0x00200038},
+{3200000, DIF_BPF_COEFF67,    0x004c004f},
+{3200000, DIF_BPF_COEFF89,    0x002fffdf},
+{3200000, DIF_BPF_COEFF1011,  0xff5cfeb6},
+{3200000, DIF_BPF_COEFF1213,  0xfe0dfd92},
+{3200000, DIF_BPF_COEFF1415,  0xfd7ffe03},
+{3200000, DIF_BPF_COEFF1617,  0xff36010a},
+{3200000, DIF_BPF_COEFF1819,  0x03410575},
+{3200000, DIF_BPF_COEFF2021,  0x072607d2},
+{3200000, DIF_BPF_COEFF2223,  0x071804d5},
+{3200000, DIF_BPF_COEFF2425,  0x0134fcb7},
+{3200000, DIF_BPF_COEFF2627,  0xf81ff451},
+{3200000, DIF_BPF_COEFF2829,  0xf223f22e},
+{3200000, DIF_BPF_COEFF3031,  0xf4a7f94b},
+{3200000, DIF_BPF_COEFF3233,  0xff6405e8},
+{3200000, DIF_BPF_COEFF3435,  0x0bae0fa4},
+{3200000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 32_quant.dat*/
+
+
+/*case 3300000:*/
+/* BEGIN - DIF BPF register values from 33_quant.dat*/
+{3300000, DIF_BPF_COEFF01,    0x0000ffff},
+{3300000, DIF_BPF_COEFF23,    0x00000008},
+{3300000, DIF_BPF_COEFF45,    0x001a0036},
+{3300000, DIF_BPF_COEFF67,    0x0056006d},
+{3300000, DIF_BPF_COEFF89,    0x00670030},
+{3300000, DIF_BPF_COEFF1011,  0xffbdff10},
+{3300000, DIF_BPF_COEFF1213,  0xfe46fd8d},
+{3300000, DIF_BPF_COEFF1415,  0xfd25fd4f},
+{3300000, DIF_BPF_COEFF1617,  0xfe35ffe0},
+{3300000, DIF_BPF_COEFF1819,  0x0224049f},
+{3300000, DIF_BPF_COEFF2021,  0x06c9080e},
+{3300000, DIF_BPF_COEFF2223,  0x07ef0627},
+{3300000, DIF_BPF_COEFF2425,  0x02c9fe45},
+{3300000, DIF_BPF_COEFF2627,  0xf961f513},
+{3300000, DIF_BPF_COEFF2829,  0xf250f1d2},
+{3300000, DIF_BPF_COEFF3031,  0xf3ecf869},
+{3300000, DIF_BPF_COEFF3233,  0xfe930552},
+{3300000, DIF_BPF_COEFF3435,  0x0b5f0f8f},
+{3300000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 33_quant.dat*/
+
+
+/*case 3400000:*/
+/* BEGIN - DIF BPF register values from 34_quant.dat*/
+{3400000, DIF_BPF_COEFF01,    0xfffffffe},
+{3400000, DIF_BPF_COEFF23,    0xfffd0001},
+{3400000, DIF_BPF_COEFF45,    0x000f002c},
+{3400000, DIF_BPF_COEFF67,    0x0054007d},
+{3400000, DIF_BPF_COEFF89,    0x0093007c},
+{3400000, DIF_BPF_COEFF1011,  0x0024ff82},
+{3400000, DIF_BPF_COEFF1213,  0xfea6fdbb},
+{3400000, DIF_BPF_COEFF1415,  0xfd03fcca},
+{3400000, DIF_BPF_COEFF1617,  0xfd51feb9},
+{3400000, DIF_BPF_COEFF1819,  0x00eb0392},
+{3400000, DIF_BPF_COEFF2021,  0x06270802},
+{3400000, DIF_BPF_COEFF2223,  0x08880750},
+{3400000, DIF_BPF_COEFF2425,  0x044dffdb},
+{3400000, DIF_BPF_COEFF2627,  0xfabdf5f8},
+{3400000, DIF_BPF_COEFF2829,  0xf2a0f193},
+{3400000, DIF_BPF_COEFF3031,  0xf342f78f},
+{3400000, DIF_BPF_COEFF3233,  0xfdc404b9},
+{3400000, DIF_BPF_COEFF3435,  0x0b0e0f78},
+{3400000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 34_quant.dat*/
+
+
+/*case 3500000:*/
+/* BEGIN - DIF BPF register values from 35_quant.dat*/
+{3500000, DIF_BPF_COEFF01,    0xfffffffd},
+{3500000, DIF_BPF_COEFF23,    0xfffafff9},
+{3500000, DIF_BPF_COEFF45,    0x0002001b},
+{3500000, DIF_BPF_COEFF67,    0x0046007d},
+{3500000, DIF_BPF_COEFF89,    0x00ad00ba},
+{3500000, DIF_BPF_COEFF1011,  0x00870000},
+{3500000, DIF_BPF_COEFF1213,  0xff26fe1a},
+{3500000, DIF_BPF_COEFF1415,  0xfd1bfc7e},
+{3500000, DIF_BPF_COEFF1617,  0xfc99fda4},
+{3500000, DIF_BPF_COEFF1819,  0xffa5025c},
+{3500000, DIF_BPF_COEFF2021,  0x054507ad},
+{3500000, DIF_BPF_COEFF2223,  0x08dd0847},
+{3500000, DIF_BPF_COEFF2425,  0x05b80172},
+{3500000, DIF_BPF_COEFF2627,  0xfc2ef6ff},
+{3500000, DIF_BPF_COEFF2829,  0xf313f170},
+{3500000, DIF_BPF_COEFF3031,  0xf2abf6bd},
+{3500000, DIF_BPF_COEFF3233,  0xfcf6041f},
+{3500000, DIF_BPF_COEFF3435,  0x0abc0f61},
+{3500000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 35_quant.dat*/
+
+
+/*case 3600000:*/
+/* BEGIN - DIF BPF register values from 36_quant.dat*/
+{3600000, DIF_BPF_COEFF01,    0xfffffffd},
+{3600000, DIF_BPF_COEFF23,    0xfff8fff3},
+{3600000, DIF_BPF_COEFF45,    0xfff50006},
+{3600000, DIF_BPF_COEFF67,    0x002f006c},
+{3600000, DIF_BPF_COEFF89,    0x00b200e3},
+{3600000, DIF_BPF_COEFF1011,  0x00dc007e},
+{3600000, DIF_BPF_COEFF1213,  0xffb9fea0},
+{3600000, DIF_BPF_COEFF1415,  0xfd6bfc71},
+{3600000, DIF_BPF_COEFF1617,  0xfc17fcb1},
+{3600000, DIF_BPF_COEFF1819,  0xfe65010b},
+{3600000, DIF_BPF_COEFF2021,  0x042d0713},
+{3600000, DIF_BPF_COEFF2223,  0x08ec0906},
+{3600000, DIF_BPF_COEFF2425,  0x07020302},
+{3600000, DIF_BPF_COEFF2627,  0xfdaff823},
+{3600000, DIF_BPF_COEFF2829,  0xf3a7f16a},
+{3600000, DIF_BPF_COEFF3031,  0xf228f5f5},
+{3600000, DIF_BPF_COEFF3233,  0xfc2a0384},
+{3600000, DIF_BPF_COEFF3435,  0x0a670f4a},
+{3600000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 36_quant.dat*/
+
+
+/*case 3700000:*/
+/* BEGIN - DIF BPF register values from 37_quant.dat*/
+{3700000, DIF_BPF_COEFF01,    0x0000fffd},
+{3700000, DIF_BPF_COEFF23,    0xfff7ffef},
+{3700000, DIF_BPF_COEFF45,    0xffe9fff1},
+{3700000, DIF_BPF_COEFF67,    0x0010004d},
+{3700000, DIF_BPF_COEFF89,    0x00a100f2},
+{3700000, DIF_BPF_COEFF1011,  0x011a00f0},
+{3700000, DIF_BPF_COEFF1213,  0x0053ff44},
+{3700000, DIF_BPF_COEFF1415,  0xfdedfca2},
+{3700000, DIF_BPF_COEFF1617,  0xfbd3fbef},
+{3700000, DIF_BPF_COEFF1819,  0xfd39ffae},
+{3700000, DIF_BPF_COEFF2021,  0x02ea0638},
+{3700000, DIF_BPF_COEFF2223,  0x08b50987},
+{3700000, DIF_BPF_COEFF2425,  0x08230483},
+{3700000, DIF_BPF_COEFF2627,  0xff39f960},
+{3700000, DIF_BPF_COEFF2829,  0xf45bf180},
+{3700000, DIF_BPF_COEFF3031,  0xf1b8f537},
+{3700000, DIF_BPF_COEFF3233,  0xfb6102e7},
+{3700000, DIF_BPF_COEFF3435,  0x0a110f32},
+{3700000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 37_quant.dat*/
+
+
+/*case 3800000:*/
+/* BEGIN - DIF BPF register values from 38_quant.dat*/
+{3800000, DIF_BPF_COEFF01,    0x0000fffe},
+{3800000, DIF_BPF_COEFF23,    0xfff9ffee},
+{3800000, DIF_BPF_COEFF45,    0xffe1ffdd},
+{3800000, DIF_BPF_COEFF67,    0xfff00024},
+{3800000, DIF_BPF_COEFF89,    0x007c00e5},
+{3800000, DIF_BPF_COEFF1011,  0x013a014a},
+{3800000, DIF_BPF_COEFF1213,  0x00e6fff8},
+{3800000, DIF_BPF_COEFF1415,  0xfe98fd0f},
+{3800000, DIF_BPF_COEFF1617,  0xfbd3fb67},
+{3800000, DIF_BPF_COEFF1819,  0xfc32fe54},
+{3800000, DIF_BPF_COEFF2021,  0x01880525},
+{3800000, DIF_BPF_COEFF2223,  0x083909c7},
+{3800000, DIF_BPF_COEFF2425,  0x091505ee},
+{3800000, DIF_BPF_COEFF2627,  0x00c7fab3},
+{3800000, DIF_BPF_COEFF2829,  0xf52df1b4},
+{3800000, DIF_BPF_COEFF3031,  0xf15df484},
+{3800000, DIF_BPF_COEFF3233,  0xfa9b0249},
+{3800000, DIF_BPF_COEFF3435,  0x09ba0f19},
+{3800000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 38_quant.dat*/
+
+
+/*case 3900000:*/
+/* BEGIN - DIF BPF register values from 39_quant.dat*/
+{3900000, DIF_BPF_COEFF01,    0x00000000},
+{3900000, DIF_BPF_COEFF23,    0xfffbfff0},
+{3900000, DIF_BPF_COEFF45,    0xffdeffcf},
+{3900000, DIF_BPF_COEFF67,    0xffd1fff6},
+{3900000, DIF_BPF_COEFF89,    0x004800be},
+{3900000, DIF_BPF_COEFF1011,  0x01390184},
+{3900000, DIF_BPF_COEFF1213,  0x016300ac},
+{3900000, DIF_BPF_COEFF1415,  0xff5efdb1},
+{3900000, DIF_BPF_COEFF1617,  0xfc17fb23},
+{3900000, DIF_BPF_COEFF1819,  0xfb5cfd0d},
+{3900000, DIF_BPF_COEFF2021,  0x001703e4},
+{3900000, DIF_BPF_COEFF2223,  0x077b09c4},
+{3900000, DIF_BPF_COEFF2425,  0x09d2073c},
+{3900000, DIF_BPF_COEFF2627,  0x0251fc18},
+{3900000, DIF_BPF_COEFF2829,  0xf61cf203},
+{3900000, DIF_BPF_COEFF3031,  0xf118f3dc},
+{3900000, DIF_BPF_COEFF3233,  0xf9d801aa},
+{3900000, DIF_BPF_COEFF3435,  0x09600eff},
+{3900000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 39_quant.dat*/
+
+
+/*case 4000000:*/
+/* BEGIN - DIF BPF register values from 40_quant.dat*/
+{4000000, DIF_BPF_COEFF01,    0x00000001},
+{4000000, DIF_BPF_COEFF23,    0xfffefff4},
+{4000000, DIF_BPF_COEFF45,    0xffe1ffc8},
+{4000000, DIF_BPF_COEFF67,    0xffbaffca},
+{4000000, DIF_BPF_COEFF89,    0x000b0082},
+{4000000, DIF_BPF_COEFF1011,  0x01170198},
+{4000000, DIF_BPF_COEFF1213,  0x01c10152},
+{4000000, DIF_BPF_COEFF1415,  0x0030fe7b},
+{4000000, DIF_BPF_COEFF1617,  0xfc99fb24},
+{4000000, DIF_BPF_COEFF1819,  0xfac3fbe9},
+{4000000, DIF_BPF_COEFF2021,  0xfea5027f},
+{4000000, DIF_BPF_COEFF2223,  0x0683097f},
+{4000000, DIF_BPF_COEFF2425,  0x0a560867},
+{4000000, DIF_BPF_COEFF2627,  0x03d2fd89},
+{4000000, DIF_BPF_COEFF2829,  0xf723f26f},
+{4000000, DIF_BPF_COEFF3031,  0xf0e8f341},
+{4000000, DIF_BPF_COEFF3233,  0xf919010a},
+{4000000, DIF_BPF_COEFF3435,  0x09060ee5},
+{4000000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 40_quant.dat*/
+
+
+/*case 4100000:*/
+/* BEGIN - DIF BPF register values from 41_quant.dat*/
+{4100000, DIF_BPF_COEFF01,    0x00010002},
+{4100000, DIF_BPF_COEFF23,    0x0002fffb},
+{4100000, DIF_BPF_COEFF45,    0xffe8ffca},
+{4100000, DIF_BPF_COEFF67,    0xffacffa4},
+{4100000, DIF_BPF_COEFF89,    0xffcd0036},
+{4100000, DIF_BPF_COEFF1011,  0x00d70184},
+{4100000, DIF_BPF_COEFF1213,  0x01f601dc},
+{4100000, DIF_BPF_COEFF1415,  0x00ffff60},
+{4100000, DIF_BPF_COEFF1617,  0xfd51fb6d},
+{4100000, DIF_BPF_COEFF1819,  0xfa6efaf5},
+{4100000, DIF_BPF_COEFF2021,  0xfd410103},
+{4100000, DIF_BPF_COEFF2223,  0x055708f9},
+{4100000, DIF_BPF_COEFF2425,  0x0a9e0969},
+{4100000, DIF_BPF_COEFF2627,  0x0543ff02},
+{4100000, DIF_BPF_COEFF2829,  0xf842f2f5},
+{4100000, DIF_BPF_COEFF3031,  0xf0cef2b2},
+{4100000, DIF_BPF_COEFF3233,  0xf85e006b},
+{4100000, DIF_BPF_COEFF3435,  0x08aa0ecb},
+{4100000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 41_quant.dat*/
+
+
+/*case 4200000:*/
+/* BEGIN - DIF BPF register values from 42_quant.dat*/
+{4200000, DIF_BPF_COEFF01,    0x00010003},
+{4200000, DIF_BPF_COEFF23,    0x00050003},
+{4200000, DIF_BPF_COEFF45,    0xfff3ffd3},
+{4200000, DIF_BPF_COEFF67,    0xffaaff8b},
+{4200000, DIF_BPF_COEFF89,    0xff95ffe5},
+{4200000, DIF_BPF_COEFF1011,  0x0080014a},
+{4200000, DIF_BPF_COEFF1213,  0x01fe023f},
+{4200000, DIF_BPF_COEFF1415,  0x01ba0050},
+{4200000, DIF_BPF_COEFF1617,  0xfe35fbf8},
+{4200000, DIF_BPF_COEFF1819,  0xfa62fa3b},
+{4200000, DIF_BPF_COEFF2021,  0xfbf9ff7e},
+{4200000, DIF_BPF_COEFF2223,  0x04010836},
+{4200000, DIF_BPF_COEFF2425,  0x0aa90a3d},
+{4200000, DIF_BPF_COEFF2627,  0x069f007f},
+{4200000, DIF_BPF_COEFF2829,  0xf975f395},
+{4200000, DIF_BPF_COEFF3031,  0xf0cbf231},
+{4200000, DIF_BPF_COEFF3233,  0xf7a9ffcb},
+{4200000, DIF_BPF_COEFF3435,  0x084c0eaf},
+{4200000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 42_quant.dat*/
+
+
+/*case 4300000:*/
+/* BEGIN - DIF BPF register values from 43_quant.dat*/
+{4300000, DIF_BPF_COEFF01,    0x00010003},
+{4300000, DIF_BPF_COEFF23,    0x0008000a},
+{4300000, DIF_BPF_COEFF45,    0x0000ffe4},
+{4300000, DIF_BPF_COEFF67,    0xffb4ff81},
+{4300000, DIF_BPF_COEFF89,    0xff6aff96},
+{4300000, DIF_BPF_COEFF1011,  0x001c00f0},
+{4300000, DIF_BPF_COEFF1213,  0x01d70271},
+{4300000, DIF_BPF_COEFF1415,  0x0254013b},
+{4300000, DIF_BPF_COEFF1617,  0xff36fcbd},
+{4300000, DIF_BPF_COEFF1819,  0xfa9ff9c5},
+{4300000, DIF_BPF_COEFF2021,  0xfadbfdfe},
+{4300000, DIF_BPF_COEFF2223,  0x028c073b},
+{4300000, DIF_BPF_COEFF2425,  0x0a750adf},
+{4300000, DIF_BPF_COEFF2627,  0x07e101fa},
+{4300000, DIF_BPF_COEFF2829,  0xfab8f44e},
+{4300000, DIF_BPF_COEFF3031,  0xf0ddf1be},
+{4300000, DIF_BPF_COEFF3233,  0xf6f9ff2b},
+{4300000, DIF_BPF_COEFF3435,  0x07ed0e94},
+{4300000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 43_quant.dat*/
+
+
+/*case 4400000:*/
+/* BEGIN - DIF BPF register values from 44_quant.dat*/
+{4400000, DIF_BPF_COEFF01,    0x00000003},
+{4400000, DIF_BPF_COEFF23,    0x0009000f},
+{4400000, DIF_BPF_COEFF45,    0x000efff8},
+{4400000, DIF_BPF_COEFF67,    0xffc9ff87},
+{4400000, DIF_BPF_COEFF89,    0xff52ff54},
+{4400000, DIF_BPF_COEFF1011,  0xffb5007e},
+{4400000, DIF_BPF_COEFF1213,  0x01860270},
+{4400000, DIF_BPF_COEFF1415,  0x02c00210},
+{4400000, DIF_BPF_COEFF1617,  0x0044fdb2},
+{4400000, DIF_BPF_COEFF1819,  0xfb22f997},
+{4400000, DIF_BPF_COEFF2021,  0xf9f2fc90},
+{4400000, DIF_BPF_COEFF2223,  0x0102060f},
+{4400000, DIF_BPF_COEFF2425,  0x0a050b4c},
+{4400000, DIF_BPF_COEFF2627,  0x0902036e},
+{4400000, DIF_BPF_COEFF2829,  0xfc0af51e},
+{4400000, DIF_BPF_COEFF3031,  0xf106f15a},
+{4400000, DIF_BPF_COEFF3233,  0xf64efe8b},
+{4400000, DIF_BPF_COEFF3435,  0x078d0e77},
+{4400000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 44_quant.dat*/
+
+
+/*case 4500000:*/
+/* BEGIN - DIF BPF register values from 45_quant.dat*/
+{4500000, DIF_BPF_COEFF01,    0x00000002},
+{4500000, DIF_BPF_COEFF23,    0x00080012},
+{4500000, DIF_BPF_COEFF45,    0x0019000e},
+{4500000, DIF_BPF_COEFF67,    0xffe5ff9e},
+{4500000, DIF_BPF_COEFF89,    0xff4fff25},
+{4500000, DIF_BPF_COEFF1011,  0xff560000},
+{4500000, DIF_BPF_COEFF1213,  0x0112023b},
+{4500000, DIF_BPF_COEFF1415,  0x02f702c0},
+{4500000, DIF_BPF_COEFF1617,  0x014dfec8},
+{4500000, DIF_BPF_COEFF1819,  0xfbe5f9b3},
+{4500000, DIF_BPF_COEFF2021,  0xf947fb41},
+{4500000, DIF_BPF_COEFF2223,  0xff7004b9},
+{4500000, DIF_BPF_COEFF2425,  0x095a0b81},
+{4500000, DIF_BPF_COEFF2627,  0x0a0004d8},
+{4500000, DIF_BPF_COEFF2829,  0xfd65f603},
+{4500000, DIF_BPF_COEFF3031,  0xf144f104},
+{4500000, DIF_BPF_COEFF3233,  0xf5aafdec},
+{4500000, DIF_BPF_COEFF3435,  0x072b0e5a},
+{4500000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 45_quant.dat*/
+
+
+/*case 4600000:*/
+/* BEGIN - DIF BPF register values from 46_quant.dat*/
+{4600000, DIF_BPF_COEFF01,    0x00000001},
+{4600000, DIF_BPF_COEFF23,    0x00060012},
+{4600000, DIF_BPF_COEFF45,    0x00200022},
+{4600000, DIF_BPF_COEFF67,    0x0005ffc1},
+{4600000, DIF_BPF_COEFF89,    0xff61ff10},
+{4600000, DIF_BPF_COEFF1011,  0xff09ff82},
+{4600000, DIF_BPF_COEFF1213,  0x008601d7},
+{4600000, DIF_BPF_COEFF1415,  0x02f50340},
+{4600000, DIF_BPF_COEFF1617,  0x0241fff0},
+{4600000, DIF_BPF_COEFF1819,  0xfcddfa19},
+{4600000, DIF_BPF_COEFF2021,  0xf8e2fa1e},
+{4600000, DIF_BPF_COEFF2223,  0xfde30343},
+{4600000, DIF_BPF_COEFF2425,  0x08790b7f},
+{4600000, DIF_BPF_COEFF2627,  0x0ad50631},
+{4600000, DIF_BPF_COEFF2829,  0xfec7f6fc},
+{4600000, DIF_BPF_COEFF3031,  0xf198f0bd},
+{4600000, DIF_BPF_COEFF3233,  0xf50dfd4e},
+{4600000, DIF_BPF_COEFF3435,  0x06c90e3d},
+{4600000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 46_quant.dat*/
+
+
+/*case 4700000:*/
+/* BEGIN - DIF BPF register values from 47_quant.dat*/
+{4700000, DIF_BPF_COEFF01,    0x0000ffff},
+{4700000, DIF_BPF_COEFF23,    0x0003000f},
+{4700000, DIF_BPF_COEFF45,    0x00220030},
+{4700000, DIF_BPF_COEFF67,    0x0025ffed},
+{4700000, DIF_BPF_COEFF89,    0xff87ff15},
+{4700000, DIF_BPF_COEFF1011,  0xfed6ff10},
+{4700000, DIF_BPF_COEFF1213,  0xffed014c},
+{4700000, DIF_BPF_COEFF1415,  0x02b90386},
+{4700000, DIF_BPF_COEFF1617,  0x03110119},
+{4700000, DIF_BPF_COEFF1819,  0xfdfefac4},
+{4700000, DIF_BPF_COEFF2021,  0xf8c6f92f},
+{4700000, DIF_BPF_COEFF2223,  0xfc6701b7},
+{4700000, DIF_BPF_COEFF2425,  0x07670b44},
+{4700000, DIF_BPF_COEFF2627,  0x0b7e0776},
+{4700000, DIF_BPF_COEFF2829,  0x002df807},
+{4700000, DIF_BPF_COEFF3031,  0xf200f086},
+{4700000, DIF_BPF_COEFF3233,  0xf477fcb1},
+{4700000, DIF_BPF_COEFF3435,  0x06650e1e},
+{4700000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 47_quant.dat*/
+
+
+/*case 4800000:*/
+/* BEGIN - DIF BPF register values from 48_quant.dat*/
+{4800000, DIF_BPF_COEFF01,    0xfffffffe},
+{4800000, DIF_BPF_COEFF23,    0xffff0009},
+{4800000, DIF_BPF_COEFF45,    0x001e0038},
+{4800000, DIF_BPF_COEFF67,    0x003f001b},
+{4800000, DIF_BPF_COEFF89,    0xffbcff36},
+{4800000, DIF_BPF_COEFF1011,  0xfec2feb6},
+{4800000, DIF_BPF_COEFF1213,  0xff5600a5},
+{4800000, DIF_BPF_COEFF1415,  0x0248038d},
+{4800000, DIF_BPF_COEFF1617,  0x03b00232},
+{4800000, DIF_BPF_COEFF1819,  0xff39fbab},
+{4800000, DIF_BPF_COEFF2021,  0xf8f4f87f},
+{4800000, DIF_BPF_COEFF2223,  0xfb060020},
+{4800000, DIF_BPF_COEFF2425,  0x062a0ad2},
+{4800000, DIF_BPF_COEFF2627,  0x0bf908a3},
+{4800000, DIF_BPF_COEFF2829,  0x0192f922},
+{4800000, DIF_BPF_COEFF3031,  0xf27df05e},
+{4800000, DIF_BPF_COEFF3233,  0xf3e8fc14},
+{4800000, DIF_BPF_COEFF3435,  0x06000e00},
+{4800000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 48_quant.dat*/
+
+
+/*case 4900000:*/
+/* BEGIN - DIF BPF register values from 49_quant.dat*/
+{4900000, DIF_BPF_COEFF01,    0xfffffffd},
+{4900000, DIF_BPF_COEFF23,    0xfffc0002},
+{4900000, DIF_BPF_COEFF45,    0x00160037},
+{4900000, DIF_BPF_COEFF67,    0x00510046},
+{4900000, DIF_BPF_COEFF89,    0xfff9ff6d},
+{4900000, DIF_BPF_COEFF1011,  0xfed0fe7c},
+{4900000, DIF_BPF_COEFF1213,  0xfecefff0},
+{4900000, DIF_BPF_COEFF1415,  0x01aa0356},
+{4900000, DIF_BPF_COEFF1617,  0x0413032b},
+{4900000, DIF_BPF_COEFF1819,  0x007ffcc5},
+{4900000, DIF_BPF_COEFF2021,  0xf96cf812},
+{4900000, DIF_BPF_COEFF2223,  0xf9cefe87},
+{4900000, DIF_BPF_COEFF2425,  0x04c90a2c},
+{4900000, DIF_BPF_COEFF2627,  0x0c4309b4},
+{4900000, DIF_BPF_COEFF2829,  0x02f3fa4a},
+{4900000, DIF_BPF_COEFF3031,  0xf30ef046},
+{4900000, DIF_BPF_COEFF3233,  0xf361fb7a},
+{4900000, DIF_BPF_COEFF3435,  0x059b0de0},
+{4900000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 49_quant.dat*/
+
+
+/*case 5000000:*/
+/* BEGIN - DIF BPF register values from 50_quant.dat*/
+{5000000, DIF_BPF_COEFF01,    0xfffffffd},
+{5000000, DIF_BPF_COEFF23,    0xfff9fffa},
+{5000000, DIF_BPF_COEFF45,    0x000a002d},
+{5000000, DIF_BPF_COEFF67,    0x00570067},
+{5000000, DIF_BPF_COEFF89,    0x0037ffb5},
+{5000000, DIF_BPF_COEFF1011,  0xfefffe68},
+{5000000, DIF_BPF_COEFF1213,  0xfe62ff3d},
+{5000000, DIF_BPF_COEFF1415,  0x00ec02e3},
+{5000000, DIF_BPF_COEFF1617,  0x043503f6},
+{5000000, DIF_BPF_COEFF1819,  0x01befe05},
+{5000000, DIF_BPF_COEFF2021,  0xfa27f7ee},
+{5000000, DIF_BPF_COEFF2223,  0xf8c6fcf8},
+{5000000, DIF_BPF_COEFF2425,  0x034c0954},
+{5000000, DIF_BPF_COEFF2627,  0x0c5c0aa4},
+{5000000, DIF_BPF_COEFF2829,  0x044cfb7e},
+{5000000, DIF_BPF_COEFF3031,  0xf3b1f03f},
+{5000000, DIF_BPF_COEFF3233,  0xf2e2fae1},
+{5000000, DIF_BPF_COEFF3435,  0x05340dc0},
+{5000000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 50_quant.dat*/
+
+
+/*case 5100000:*/
+/* BEGIN - DIF BPF register values from 51_quant.dat*/
+{5100000, DIF_BPF_COEFF01,    0x0000fffd},
+{5100000, DIF_BPF_COEFF23,    0xfff8fff4},
+{5100000, DIF_BPF_COEFF45,    0xfffd001e},
+{5100000, DIF_BPF_COEFF67,    0x0051007b},
+{5100000, DIF_BPF_COEFF89,    0x006e0006},
+{5100000, DIF_BPF_COEFF1011,  0xff48fe7c},
+{5100000, DIF_BPF_COEFF1213,  0xfe1bfe9a},
+{5100000, DIF_BPF_COEFF1415,  0x001d023e},
+{5100000, DIF_BPF_COEFF1617,  0x04130488},
+{5100000, DIF_BPF_COEFF1819,  0x02e6ff5b},
+{5100000, DIF_BPF_COEFF2021,  0xfb1ef812},
+{5100000, DIF_BPF_COEFF2223,  0xf7f7fb7f},
+{5100000, DIF_BPF_COEFF2425,  0x01bc084e},
+{5100000, DIF_BPF_COEFF2627,  0x0c430b72},
+{5100000, DIF_BPF_COEFF2829,  0x059afcba},
+{5100000, DIF_BPF_COEFF3031,  0xf467f046},
+{5100000, DIF_BPF_COEFF3233,  0xf26cfa4a},
+{5100000, DIF_BPF_COEFF3435,  0x04cd0da0},
+{5100000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 51_quant.dat*/
+
+
+/*case 5200000:*/
+/* BEGIN - DIF BPF register values from 52_quant.dat*/
+{5200000, DIF_BPF_COEFF01,    0x0000fffe},
+{5200000, DIF_BPF_COEFF23,    0xfff8ffef},
+{5200000, DIF_BPF_COEFF45,    0xfff00009},
+{5200000, DIF_BPF_COEFF67,    0x003f007f},
+{5200000, DIF_BPF_COEFF89,    0x00980056},
+{5200000, DIF_BPF_COEFF1011,  0xffa5feb6},
+{5200000, DIF_BPF_COEFF1213,  0xfe00fe15},
+{5200000, DIF_BPF_COEFF1415,  0xff4b0170},
+{5200000, DIF_BPF_COEFF1617,  0x03b004d7},
+{5200000, DIF_BPF_COEFF1819,  0x03e800b9},
+{5200000, DIF_BPF_COEFF2021,  0xfc48f87f},
+{5200000, DIF_BPF_COEFF2223,  0xf768fa23},
+{5200000, DIF_BPF_COEFF2425,  0x0022071f},
+{5200000, DIF_BPF_COEFF2627,  0x0bf90c1b},
+{5200000, DIF_BPF_COEFF2829,  0x06dafdfd},
+{5200000, DIF_BPF_COEFF3031,  0xf52df05e},
+{5200000, DIF_BPF_COEFF3233,  0xf1fef9b5},
+{5200000, DIF_BPF_COEFF3435,  0x04640d7f},
+{5200000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 52_quant.dat*/
+
+
+/*case 5300000:*/
+/* BEGIN - DIF BPF register values from 53_quant.dat*/
+{5300000, DIF_BPF_COEFF01,    0x0000ffff},
+{5300000, DIF_BPF_COEFF23,    0xfff9ffee},
+{5300000, DIF_BPF_COEFF45,    0xffe6fff3},
+{5300000, DIF_BPF_COEFF67,    0x00250072},
+{5300000, DIF_BPF_COEFF89,    0x00af009c},
+{5300000, DIF_BPF_COEFF1011,  0x000cff10},
+{5300000, DIF_BPF_COEFF1213,  0xfe13fdb8},
+{5300000, DIF_BPF_COEFF1415,  0xfe870089},
+{5300000, DIF_BPF_COEFF1617,  0x031104e1},
+{5300000, DIF_BPF_COEFF1819,  0x04b8020f},
+{5300000, DIF_BPF_COEFF2021,  0xfd98f92f},
+{5300000, DIF_BPF_COEFF2223,  0xf71df8f0},
+{5300000, DIF_BPF_COEFF2425,  0xfe8805ce},
+{5300000, DIF_BPF_COEFF2627,  0x0b7e0c9c},
+{5300000, DIF_BPF_COEFF2829,  0x0808ff44},
+{5300000, DIF_BPF_COEFF3031,  0xf603f086},
+{5300000, DIF_BPF_COEFF3233,  0xf19af922},
+{5300000, DIF_BPF_COEFF3435,  0x03fb0d5e},
+{5300000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 53_quant.dat*/
+
+
+/*case 5400000:*/
+/* BEGIN - DIF BPF register values from 54_quant.dat*/
+{5400000, DIF_BPF_COEFF01,    0x00000001},
+{5400000, DIF_BPF_COEFF23,    0xfffcffef},
+{5400000, DIF_BPF_COEFF45,    0xffe0ffe0},
+{5400000, DIF_BPF_COEFF67,    0x00050056},
+{5400000, DIF_BPF_COEFF89,    0x00b000d1},
+{5400000, DIF_BPF_COEFF1011,  0x0071ff82},
+{5400000, DIF_BPF_COEFF1213,  0xfe53fd8c},
+{5400000, DIF_BPF_COEFF1415,  0xfddfff99},
+{5400000, DIF_BPF_COEFF1617,  0x024104a3},
+{5400000, DIF_BPF_COEFF1819,  0x054a034d},
+{5400000, DIF_BPF_COEFF2021,  0xff01fa1e},
+{5400000, DIF_BPF_COEFF2223,  0xf717f7ed},
+{5400000, DIF_BPF_COEFF2425,  0xfcf50461},
+{5400000, DIF_BPF_COEFF2627,  0x0ad50cf4},
+{5400000, DIF_BPF_COEFF2829,  0x0921008d},
+{5400000, DIF_BPF_COEFF3031,  0xf6e7f0bd},
+{5400000, DIF_BPF_COEFF3233,  0xf13ff891},
+{5400000, DIF_BPF_COEFF3435,  0x03920d3b},
+{5400000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 54_quant.dat*/
+
+
+/*case 5500000:*/
+/* BEGIN - DIF BPF register values from 55_quant.dat*/
+{5500000, DIF_BPF_COEFF01,    0x00010002},
+{5500000, DIF_BPF_COEFF23,    0xfffffff3},
+{5500000, DIF_BPF_COEFF45,    0xffdeffd1},
+{5500000, DIF_BPF_COEFF67,    0xffe5002f},
+{5500000, DIF_BPF_COEFF89,    0x009c00ed},
+{5500000, DIF_BPF_COEFF1011,  0x00cb0000},
+{5500000, DIF_BPF_COEFF1213,  0xfebafd94},
+{5500000, DIF_BPF_COEFF1415,  0xfd61feb0},
+{5500000, DIF_BPF_COEFF1617,  0x014d0422},
+{5500000, DIF_BPF_COEFF1819,  0x05970464},
+{5500000, DIF_BPF_COEFF2021,  0x0074fb41},
+{5500000, DIF_BPF_COEFF2223,  0xf759f721},
+{5500000, DIF_BPF_COEFF2425,  0xfb7502de},
+{5500000, DIF_BPF_COEFF2627,  0x0a000d21},
+{5500000, DIF_BPF_COEFF2829,  0x0a2201d4},
+{5500000, DIF_BPF_COEFF3031,  0xf7d9f104},
+{5500000, DIF_BPF_COEFF3233,  0xf0edf804},
+{5500000, DIF_BPF_COEFF3435,  0x03280d19},
+{5500000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 55_quant.dat*/
+
+
+/*case 5600000:*/
+/* BEGIN - DIF BPF register values from 56_quant.dat*/
+{5600000, DIF_BPF_COEFF01,    0x00010003},
+{5600000, DIF_BPF_COEFF23,    0x0003fffa},
+{5600000, DIF_BPF_COEFF45,    0xffe3ffc9},
+{5600000, DIF_BPF_COEFF67,    0xffc90002},
+{5600000, DIF_BPF_COEFF89,    0x007500ef},
+{5600000, DIF_BPF_COEFF1011,  0x010e007e},
+{5600000, DIF_BPF_COEFF1213,  0xff3dfdcf},
+{5600000, DIF_BPF_COEFF1415,  0xfd16fddd},
+{5600000, DIF_BPF_COEFF1617,  0x00440365},
+{5600000, DIF_BPF_COEFF1819,  0x059b0548},
+{5600000, DIF_BPF_COEFF2021,  0x01e3fc90},
+{5600000, DIF_BPF_COEFF2223,  0xf7dff691},
+{5600000, DIF_BPF_COEFF2425,  0xfa0f014d},
+{5600000, DIF_BPF_COEFF2627,  0x09020d23},
+{5600000, DIF_BPF_COEFF2829,  0x0b0a0318},
+{5600000, DIF_BPF_COEFF3031,  0xf8d7f15a},
+{5600000, DIF_BPF_COEFF3233,  0xf0a5f779},
+{5600000, DIF_BPF_COEFF3435,  0x02bd0cf6},
+{5600000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 56_quant.dat*/
+
+
+/*case 5700000:*/
+/* BEGIN - DIF BPF register values from 57_quant.dat*/
+{5700000, DIF_BPF_COEFF01,    0x00010003},
+{5700000, DIF_BPF_COEFF23,    0x00060001},
+{5700000, DIF_BPF_COEFF45,    0xffecffc9},
+{5700000, DIF_BPF_COEFF67,    0xffb4ffd4},
+{5700000, DIF_BPF_COEFF89,    0x004000d5},
+{5700000, DIF_BPF_COEFF1011,  0x013600f0},
+{5700000, DIF_BPF_COEFF1213,  0xffd3fe39},
+{5700000, DIF_BPF_COEFF1415,  0xfd04fd31},
+{5700000, DIF_BPF_COEFF1617,  0xff360277},
+{5700000, DIF_BPF_COEFF1819,  0x055605ef},
+{5700000, DIF_BPF_COEFF2021,  0x033efdfe},
+{5700000, DIF_BPF_COEFF2223,  0xf8a5f642},
+{5700000, DIF_BPF_COEFF2425,  0xf8cbffb6},
+{5700000, DIF_BPF_COEFF2627,  0x07e10cfb},
+{5700000, DIF_BPF_COEFF2829,  0x0bd50456},
+{5700000, DIF_BPF_COEFF3031,  0xf9dff1be},
+{5700000, DIF_BPF_COEFF3233,  0xf067f6f2},
+{5700000, DIF_BPF_COEFF3435,  0x02520cd2},
+{5700000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 57_quant.dat*/
+
+
+/*case 5800000:*/
+/* BEGIN - DIF BPF register values from 58_quant.dat*/
+{5800000, DIF_BPF_COEFF01,    0x00000003},
+{5800000, DIF_BPF_COEFF23,    0x00080009},
+{5800000, DIF_BPF_COEFF45,    0xfff8ffd2},
+{5800000, DIF_BPF_COEFF67,    0xffaaffac},
+{5800000, DIF_BPF_COEFF89,    0x000200a3},
+{5800000, DIF_BPF_COEFF1011,  0x013c014a},
+{5800000, DIF_BPF_COEFF1213,  0x006dfec9},
+{5800000, DIF_BPF_COEFF1415,  0xfd2bfcb7},
+{5800000, DIF_BPF_COEFF1617,  0xfe350165},
+{5800000, DIF_BPF_COEFF1819,  0x04cb0651},
+{5800000, DIF_BPF_COEFF2021,  0x0477ff7e},
+{5800000, DIF_BPF_COEFF2223,  0xf9a5f635},
+{5800000, DIF_BPF_COEFF2425,  0xf7b1fe20},
+{5800000, DIF_BPF_COEFF2627,  0x069f0ca8},
+{5800000, DIF_BPF_COEFF2829,  0x0c81058b},
+{5800000, DIF_BPF_COEFF3031,  0xfaf0f231},
+{5800000, DIF_BPF_COEFF3233,  0xf033f66d},
+{5800000, DIF_BPF_COEFF3435,  0x01e60cae},
+{5800000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 58_quant.dat*/
+
+
+/*case 5900000:*/
+/* BEGIN - DIF BPF register values from 59_quant.dat*/
+{5900000, DIF_BPF_COEFF01,    0x00000002},
+{5900000, DIF_BPF_COEFF23,    0x0009000e},
+{5900000, DIF_BPF_COEFF45,    0x0005ffe1},
+{5900000, DIF_BPF_COEFF67,    0xffacff90},
+{5900000, DIF_BPF_COEFF89,    0xffc5005f},
+{5900000, DIF_BPF_COEFF1011,  0x01210184},
+{5900000, DIF_BPF_COEFF1213,  0x00fcff72},
+{5900000, DIF_BPF_COEFF1415,  0xfd8afc77},
+{5900000, DIF_BPF_COEFF1617,  0xfd51003f},
+{5900000, DIF_BPF_COEFF1819,  0x04020669},
+{5900000, DIF_BPF_COEFF2021,  0x05830103},
+{5900000, DIF_BPF_COEFF2223,  0xfad7f66b},
+{5900000, DIF_BPF_COEFF2425,  0xf6c8fc93},
+{5900000, DIF_BPF_COEFF2627,  0x05430c2b},
+{5900000, DIF_BPF_COEFF2829,  0x0d0d06b5},
+{5900000, DIF_BPF_COEFF3031,  0xfc08f2b2},
+{5900000, DIF_BPF_COEFF3233,  0xf00af5ec},
+{5900000, DIF_BPF_COEFF3435,  0x017b0c89},
+{5900000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 59_quant.dat*/
+
+
+/*case 6000000:*/
+/* BEGIN - DIF BPF register values from 60_quant.dat*/
+{6000000, DIF_BPF_COEFF01,    0x00000001},
+{6000000, DIF_BPF_COEFF23,    0x00070012},
+{6000000, DIF_BPF_COEFF45,    0x0012fff5},
+{6000000, DIF_BPF_COEFF67,    0xffbaff82},
+{6000000, DIF_BPF_COEFF89,    0xff8e000f},
+{6000000, DIF_BPF_COEFF1011,  0x00e80198},
+{6000000, DIF_BPF_COEFF1213,  0x01750028},
+{6000000, DIF_BPF_COEFF1415,  0xfe18fc75},
+{6000000, DIF_BPF_COEFF1617,  0xfc99ff15},
+{6000000, DIF_BPF_COEFF1819,  0x03050636},
+{6000000, DIF_BPF_COEFF2021,  0x0656027f},
+{6000000, DIF_BPF_COEFF2223,  0xfc32f6e2},
+{6000000, DIF_BPF_COEFF2425,  0xf614fb17},
+{6000000, DIF_BPF_COEFF2627,  0x03d20b87},
+{6000000, DIF_BPF_COEFF2829,  0x0d7707d2},
+{6000000, DIF_BPF_COEFF3031,  0xfd26f341},
+{6000000, DIF_BPF_COEFF3233,  0xefeaf56f},
+{6000000, DIF_BPF_COEFF3435,  0x010f0c64},
+{6000000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 60_quant.dat*/
+
+
+/*case 6100000:*/
+/* BEGIN - DIF BPF register values from 61_quant.dat*/
+{6100000, DIF_BPF_COEFF01,    0xffff0000},
+{6100000, DIF_BPF_COEFF23,    0x00050012},
+{6100000, DIF_BPF_COEFF45,    0x001c000b},
+{6100000, DIF_BPF_COEFF67,    0xffd1ff84},
+{6100000, DIF_BPF_COEFF89,    0xff66ffbe},
+{6100000, DIF_BPF_COEFF1011,  0x00960184},
+{6100000, DIF_BPF_COEFF1213,  0x01cd00da},
+{6100000, DIF_BPF_COEFF1415,  0xfeccfcb2},
+{6100000, DIF_BPF_COEFF1617,  0xfc17fdf9},
+{6100000, DIF_BPF_COEFF1819,  0x01e005bc},
+{6100000, DIF_BPF_COEFF2021,  0x06e703e4},
+{6100000, DIF_BPF_COEFF2223,  0xfdabf798},
+{6100000, DIF_BPF_COEFF2425,  0xf599f9b3},
+{6100000, DIF_BPF_COEFF2627,  0x02510abd},
+{6100000, DIF_BPF_COEFF2829,  0x0dbf08df},
+{6100000, DIF_BPF_COEFF3031,  0xfe48f3dc},
+{6100000, DIF_BPF_COEFF3233,  0xefd5f4f6},
+{6100000, DIF_BPF_COEFF3435,  0x00a20c3e},
+{6100000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 61_quant.dat*/
+
+
+/*case 6200000:*/
+/* BEGIN - DIF BPF register values from 62_quant.dat*/
+{6200000, DIF_BPF_COEFF01,    0xfffffffe},
+{6200000, DIF_BPF_COEFF23,    0x0002000f},
+{6200000, DIF_BPF_COEFF45,    0x0021001f},
+{6200000, DIF_BPF_COEFF67,    0xfff0ff97},
+{6200000, DIF_BPF_COEFF89,    0xff50ff74},
+{6200000, DIF_BPF_COEFF1011,  0x0034014a},
+{6200000, DIF_BPF_COEFF1213,  0x01fa0179},
+{6200000, DIF_BPF_COEFF1415,  0xff97fd2a},
+{6200000, DIF_BPF_COEFF1617,  0xfbd3fcfa},
+{6200000, DIF_BPF_COEFF1819,  0x00a304fe},
+{6200000, DIF_BPF_COEFF2021,  0x07310525},
+{6200000, DIF_BPF_COEFF2223,  0xff37f886},
+{6200000, DIF_BPF_COEFF2425,  0xf55cf86e},
+{6200000, DIF_BPF_COEFF2627,  0x00c709d0},
+{6200000, DIF_BPF_COEFF2829,  0x0de209db},
+{6200000, DIF_BPF_COEFF3031,  0xff6df484},
+{6200000, DIF_BPF_COEFF3233,  0xefcbf481},
+{6200000, DIF_BPF_COEFF3435,  0x00360c18},
+{6200000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 62_quant.dat*/
+
+
+/*case 6300000:*/
+/* BEGIN - DIF BPF register values from 63_quant.dat*/
+{6300000, DIF_BPF_COEFF01,    0xfffffffd},
+{6300000, DIF_BPF_COEFF23,    0xfffe000a},
+{6300000, DIF_BPF_COEFF45,    0x0021002f},
+{6300000, DIF_BPF_COEFF67,    0x0010ffb8},
+{6300000, DIF_BPF_COEFF89,    0xff50ff3b},
+{6300000, DIF_BPF_COEFF1011,  0xffcc00f0},
+{6300000, DIF_BPF_COEFF1213,  0x01fa01fa},
+{6300000, DIF_BPF_COEFF1415,  0x0069fdd4},
+{6300000, DIF_BPF_COEFF1617,  0xfbd3fc26},
+{6300000, DIF_BPF_COEFF1819,  0xff5d0407},
+{6300000, DIF_BPF_COEFF2021,  0x07310638},
+{6300000, DIF_BPF_COEFF2223,  0x00c9f9a8},
+{6300000, DIF_BPF_COEFF2425,  0xf55cf74e},
+{6300000, DIF_BPF_COEFF2627,  0xff3908c3},
+{6300000, DIF_BPF_COEFF2829,  0x0de20ac3},
+{6300000, DIF_BPF_COEFF3031,  0x0093f537},
+{6300000, DIF_BPF_COEFF3233,  0xefcbf410},
+{6300000, DIF_BPF_COEFF3435,  0xffca0bf2},
+{6300000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 63_quant.dat*/
+
+
+/*case 6400000:*/
+/* BEGIN - DIF BPF register values from 64_quant.dat*/
+{6400000, DIF_BPF_COEFF01,    0xfffffffd},
+{6400000, DIF_BPF_COEFF23,    0xfffb0003},
+{6400000, DIF_BPF_COEFF45,    0x001c0037},
+{6400000, DIF_BPF_COEFF67,    0x002fffe2},
+{6400000, DIF_BPF_COEFF89,    0xff66ff17},
+{6400000, DIF_BPF_COEFF1011,  0xff6a007e},
+{6400000, DIF_BPF_COEFF1213,  0x01cd0251},
+{6400000, DIF_BPF_COEFF1415,  0x0134fea5},
+{6400000, DIF_BPF_COEFF1617,  0xfc17fb8b},
+{6400000, DIF_BPF_COEFF1819,  0xfe2002e0},
+{6400000, DIF_BPF_COEFF2021,  0x06e70713},
+{6400000, DIF_BPF_COEFF2223,  0x0255faf5},
+{6400000, DIF_BPF_COEFF2425,  0xf599f658},
+{6400000, DIF_BPF_COEFF2627,  0xfdaf0799},
+{6400000, DIF_BPF_COEFF2829,  0x0dbf0b96},
+{6400000, DIF_BPF_COEFF3031,  0x01b8f5f5},
+{6400000, DIF_BPF_COEFF3233,  0xefd5f3a3},
+{6400000, DIF_BPF_COEFF3435,  0xff5e0bca},
+{6400000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 64_quant.dat*/
+
+
+/*case 6500000:*/
+/* BEGIN - DIF BPF register values from 65_quant.dat*/
+{6500000, DIF_BPF_COEFF01,    0x0000fffd},
+{6500000, DIF_BPF_COEFF23,    0xfff9fffb},
+{6500000, DIF_BPF_COEFF45,    0x00120037},
+{6500000, DIF_BPF_COEFF67,    0x00460010},
+{6500000, DIF_BPF_COEFF89,    0xff8eff0f},
+{6500000, DIF_BPF_COEFF1011,  0xff180000},
+{6500000, DIF_BPF_COEFF1213,  0x01750276},
+{6500000, DIF_BPF_COEFF1415,  0x01e8ff8d},
+{6500000, DIF_BPF_COEFF1617,  0xfc99fb31},
+{6500000, DIF_BPF_COEFF1819,  0xfcfb0198},
+{6500000, DIF_BPF_COEFF2021,  0x065607ad},
+{6500000, DIF_BPF_COEFF2223,  0x03cefc64},
+{6500000, DIF_BPF_COEFF2425,  0xf614f592},
+{6500000, DIF_BPF_COEFF2627,  0xfc2e0656},
+{6500000, DIF_BPF_COEFF2829,  0x0d770c52},
+{6500000, DIF_BPF_COEFF3031,  0x02daf6bd},
+{6500000, DIF_BPF_COEFF3233,  0xefeaf33b},
+{6500000, DIF_BPF_COEFF3435,  0xfef10ba3},
+{6500000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 65_quant.dat*/
+
+
+/*case 6600000:*/
+/* BEGIN - DIF BPF register values from 66_quant.dat*/
+{6600000, DIF_BPF_COEFF01,    0x0000fffe},
+{6600000, DIF_BPF_COEFF23,    0xfff7fff5},
+{6600000, DIF_BPF_COEFF45,    0x0005002f},
+{6600000, DIF_BPF_COEFF67,    0x0054003c},
+{6600000, DIF_BPF_COEFF89,    0xffc5ff22},
+{6600000, DIF_BPF_COEFF1011,  0xfedfff82},
+{6600000, DIF_BPF_COEFF1213,  0x00fc0267},
+{6600000, DIF_BPF_COEFF1415,  0x0276007e},
+{6600000, DIF_BPF_COEFF1617,  0xfd51fb1c},
+{6600000, DIF_BPF_COEFF1819,  0xfbfe003e},
+{6600000, DIF_BPF_COEFF2021,  0x05830802},
+{6600000, DIF_BPF_COEFF2223,  0x0529fdec},
+{6600000, DIF_BPF_COEFF2425,  0xf6c8f4fe},
+{6600000, DIF_BPF_COEFF2627,  0xfabd04ff},
+{6600000, DIF_BPF_COEFF2829,  0x0d0d0cf6},
+{6600000, DIF_BPF_COEFF3031,  0x03f8f78f},
+{6600000, DIF_BPF_COEFF3233,  0xf00af2d7},
+{6600000, DIF_BPF_COEFF3435,  0xfe850b7b},
+{6600000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 66_quant.dat*/
+
+
+/*case 6700000:*/
+/* BEGIN - DIF BPF register values from 67_quant.dat*/
+{6700000, DIF_BPF_COEFF01,    0x0000ffff},
+{6700000, DIF_BPF_COEFF23,    0xfff8fff0},
+{6700000, DIF_BPF_COEFF45,    0xfff80020},
+{6700000, DIF_BPF_COEFF67,    0x00560060},
+{6700000, DIF_BPF_COEFF89,    0x0002ff4e},
+{6700000, DIF_BPF_COEFF1011,  0xfec4ff10},
+{6700000, DIF_BPF_COEFF1213,  0x006d0225},
+{6700000, DIF_BPF_COEFF1415,  0x02d50166},
+{6700000, DIF_BPF_COEFF1617,  0xfe35fb4e},
+{6700000, DIF_BPF_COEFF1819,  0xfb35fee1},
+{6700000, DIF_BPF_COEFF2021,  0x0477080e},
+{6700000, DIF_BPF_COEFF2223,  0x065bff82},
+{6700000, DIF_BPF_COEFF2425,  0xf7b1f4a0},
+{6700000, DIF_BPF_COEFF2627,  0xf9610397},
+{6700000, DIF_BPF_COEFF2829,  0x0c810d80},
+{6700000, DIF_BPF_COEFF3031,  0x0510f869},
+{6700000, DIF_BPF_COEFF3233,  0xf033f278},
+{6700000, DIF_BPF_COEFF3435,  0xfe1a0b52},
+{6700000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 67_quant.dat*/
+
+
+/*case 6800000:*/
+/* BEGIN - DIF BPF register values from 68_quant.dat*/
+{6800000, DIF_BPF_COEFF01,    0x00010000},
+{6800000, DIF_BPF_COEFF23,    0xfffaffee},
+{6800000, DIF_BPF_COEFF45,    0xffec000c},
+{6800000, DIF_BPF_COEFF67,    0x004c0078},
+{6800000, DIF_BPF_COEFF89,    0x0040ff8e},
+{6800000, DIF_BPF_COEFF1011,  0xfecafeb6},
+{6800000, DIF_BPF_COEFF1213,  0xffd301b6},
+{6800000, DIF_BPF_COEFF1415,  0x02fc0235},
+{6800000, DIF_BPF_COEFF1617,  0xff36fbc5},
+{6800000, DIF_BPF_COEFF1819,  0xfaaafd90},
+{6800000, DIF_BPF_COEFF2021,  0x033e07d2},
+{6800000, DIF_BPF_COEFF2223,  0x075b011b},
+{6800000, DIF_BPF_COEFF2425,  0xf8cbf47a},
+{6800000, DIF_BPF_COEFF2627,  0xf81f0224},
+{6800000, DIF_BPF_COEFF2829,  0x0bd50def},
+{6800000, DIF_BPF_COEFF3031,  0x0621f94b},
+{6800000, DIF_BPF_COEFF3233,  0xf067f21e},
+{6800000, DIF_BPF_COEFF3435,  0xfdae0b29},
+{6800000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 68_quant.dat*/
+
+
+/*case 6900000:*/
+/* BEGIN - DIF BPF register values from 69_quant.dat*/
+{6900000, DIF_BPF_COEFF01,    0x00010001},
+{6900000, DIF_BPF_COEFF23,    0xfffdffef},
+{6900000, DIF_BPF_COEFF45,    0xffe3fff6},
+{6900000, DIF_BPF_COEFF67,    0x0037007f},
+{6900000, DIF_BPF_COEFF89,    0x0075ffdc},
+{6900000, DIF_BPF_COEFF1011,  0xfef2fe7c},
+{6900000, DIF_BPF_COEFF1213,  0xff3d0122},
+{6900000, DIF_BPF_COEFF1415,  0x02ea02dd},
+{6900000, DIF_BPF_COEFF1617,  0x0044fc79},
+{6900000, DIF_BPF_COEFF1819,  0xfa65fc5d},
+{6900000, DIF_BPF_COEFF2021,  0x01e3074e},
+{6900000, DIF_BPF_COEFF2223,  0x082102ad},
+{6900000, DIF_BPF_COEFF2425,  0xfa0ff48c},
+{6900000, DIF_BPF_COEFF2627,  0xf6fe00a9},
+{6900000, DIF_BPF_COEFF2829,  0x0b0a0e43},
+{6900000, DIF_BPF_COEFF3031,  0x0729fa33},
+{6900000, DIF_BPF_COEFF3233,  0xf0a5f1c9},
+{6900000, DIF_BPF_COEFF3435,  0xfd430b00},
+{6900000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 69_quant.dat*/
+
+
+/*case 7000000:*/
+/* BEGIN - DIF BPF register values from 70_quant.dat*/
+{7000000, DIF_BPF_COEFF01,    0x00010002},
+{7000000, DIF_BPF_COEFF23,    0x0001fff3},
+{7000000, DIF_BPF_COEFF45,    0xffdeffe2},
+{7000000, DIF_BPF_COEFF67,    0x001b0076},
+{7000000, DIF_BPF_COEFF89,    0x009c002d},
+{7000000, DIF_BPF_COEFF1011,  0xff35fe68},
+{7000000, DIF_BPF_COEFF1213,  0xfeba0076},
+{7000000, DIF_BPF_COEFF1415,  0x029f0352},
+{7000000, DIF_BPF_COEFF1617,  0x014dfd60},
+{7000000, DIF_BPF_COEFF1819,  0xfa69fb53},
+{7000000, DIF_BPF_COEFF2021,  0x00740688},
+{7000000, DIF_BPF_COEFF2223,  0x08a7042d},
+{7000000, DIF_BPF_COEFF2425,  0xfb75f4d6},
+{7000000, DIF_BPF_COEFF2627,  0xf600ff2d},
+{7000000, DIF_BPF_COEFF2829,  0x0a220e7a},
+{7000000, DIF_BPF_COEFF3031,  0x0827fb22},
+{7000000, DIF_BPF_COEFF3233,  0xf0edf17a},
+{7000000, DIF_BPF_COEFF3435,  0xfcd80ad6},
+{7000000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 70_quant.dat*/
+
+
+/*case 7100000:*/
+/* BEGIN - DIF BPF register values from 71_quant.dat*/
+{7100000, DIF_BPF_COEFF01,    0x00000003},
+{7100000, DIF_BPF_COEFF23,    0x0004fff9},
+{7100000, DIF_BPF_COEFF45,    0xffe0ffd2},
+{7100000, DIF_BPF_COEFF67,    0xfffb005e},
+{7100000, DIF_BPF_COEFF89,    0x00b0007a},
+{7100000, DIF_BPF_COEFF1011,  0xff8ffe7c},
+{7100000, DIF_BPF_COEFF1213,  0xfe53ffc1},
+{7100000, DIF_BPF_COEFF1415,  0x0221038c},
+{7100000, DIF_BPF_COEFF1617,  0x0241fe6e},
+{7100000, DIF_BPF_COEFF1819,  0xfab6fa80},
+{7100000, DIF_BPF_COEFF2021,  0xff010587},
+{7100000, DIF_BPF_COEFF2223,  0x08e90590},
+{7100000, DIF_BPF_COEFF2425,  0xfcf5f556},
+{7100000, DIF_BPF_COEFF2627,  0xf52bfdb3},
+{7100000, DIF_BPF_COEFF2829,  0x09210e95},
+{7100000, DIF_BPF_COEFF3031,  0x0919fc15},
+{7100000, DIF_BPF_COEFF3233,  0xf13ff12f},
+{7100000, DIF_BPF_COEFF3435,  0xfc6e0aab},
+{7100000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 71_quant.dat*/
+
+
+/*case 7200000:*/
+/* BEGIN - DIF BPF register values from 72_quant.dat*/
+{7200000, DIF_BPF_COEFF01,    0x00000003},
+{7200000, DIF_BPF_COEFF23,    0x00070000},
+{7200000, DIF_BPF_COEFF45,    0xffe6ffc9},
+{7200000, DIF_BPF_COEFF67,    0xffdb0039},
+{7200000, DIF_BPF_COEFF89,    0x00af00b8},
+{7200000, DIF_BPF_COEFF1011,  0xfff4feb6},
+{7200000, DIF_BPF_COEFF1213,  0xfe13ff10},
+{7200000, DIF_BPF_COEFF1415,  0x01790388},
+{7200000, DIF_BPF_COEFF1617,  0x0311ff92},
+{7200000, DIF_BPF_COEFF1819,  0xfb48f9ed},
+{7200000, DIF_BPF_COEFF2021,  0xfd980453},
+{7200000, DIF_BPF_COEFF2223,  0x08e306cd},
+{7200000, DIF_BPF_COEFF2425,  0xfe88f60a},
+{7200000, DIF_BPF_COEFF2627,  0xf482fc40},
+{7200000, DIF_BPF_COEFF2829,  0x08080e93},
+{7200000, DIF_BPF_COEFF3031,  0x09fdfd0c},
+{7200000, DIF_BPF_COEFF3233,  0xf19af0ea},
+{7200000, DIF_BPF_COEFF3435,  0xfc050a81},
+{7200000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 72_quant.dat*/
+
+
+/*case 7300000:*/
+/* BEGIN - DIF BPF register values from 73_quant.dat*/
+{7300000, DIF_BPF_COEFF01,    0x00000002},
+{7300000, DIF_BPF_COEFF23,    0x00080008},
+{7300000, DIF_BPF_COEFF45,    0xfff0ffc9},
+{7300000, DIF_BPF_COEFF67,    0xffc1000d},
+{7300000, DIF_BPF_COEFF89,    0x009800e2},
+{7300000, DIF_BPF_COEFF1011,  0x005bff10},
+{7300000, DIF_BPF_COEFF1213,  0xfe00fe74},
+{7300000, DIF_BPF_COEFF1415,  0x00b50345},
+{7300000, DIF_BPF_COEFF1617,  0x03b000bc},
+{7300000, DIF_BPF_COEFF1819,  0xfc18f9a1},
+{7300000, DIF_BPF_COEFF2021,  0xfc4802f9},
+{7300000, DIF_BPF_COEFF2223,  0x089807dc},
+{7300000, DIF_BPF_COEFF2425,  0x0022f6f0},
+{7300000, DIF_BPF_COEFF2627,  0xf407fada},
+{7300000, DIF_BPF_COEFF2829,  0x06da0e74},
+{7300000, DIF_BPF_COEFF3031,  0x0ad3fe06},
+{7300000, DIF_BPF_COEFF3233,  0xf1fef0ab},
+{7300000, DIF_BPF_COEFF3435,  0xfb9c0a55},
+{7300000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 73_quant.dat*/
+
+
+/*case 7400000:*/
+/* BEGIN - DIF BPF register values from 74_quant.dat*/
+{7400000, DIF_BPF_COEFF01,    0x00000001},
+{7400000, DIF_BPF_COEFF23,    0x0008000e},
+{7400000, DIF_BPF_COEFF45,    0xfffdffd0},
+{7400000, DIF_BPF_COEFF67,    0xffafffdf},
+{7400000, DIF_BPF_COEFF89,    0x006e00f2},
+{7400000, DIF_BPF_COEFF1011,  0x00b8ff82},
+{7400000, DIF_BPF_COEFF1213,  0xfe1bfdf8},
+{7400000, DIF_BPF_COEFF1415,  0xffe302c8},
+{7400000, DIF_BPF_COEFF1617,  0x041301dc},
+{7400000, DIF_BPF_COEFF1819,  0xfd1af99e},
+{7400000, DIF_BPF_COEFF2021,  0xfb1e0183},
+{7400000, DIF_BPF_COEFF2223,  0x080908b5},
+{7400000, DIF_BPF_COEFF2425,  0x01bcf801},
+{7400000, DIF_BPF_COEFF2627,  0xf3bdf985},
+{7400000, DIF_BPF_COEFF2829,  0x059a0e38},
+{7400000, DIF_BPF_COEFF3031,  0x0b99ff03},
+{7400000, DIF_BPF_COEFF3233,  0xf26cf071},
+{7400000, DIF_BPF_COEFF3435,  0xfb330a2a},
+{7400000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 74_quant.dat*/
+
+
+/*case 7500000:*/
+/* BEGIN - DIF BPF register values from 75_quant.dat*/
+{7500000, DIF_BPF_COEFF01,    0xffff0000},
+{7500000, DIF_BPF_COEFF23,    0x00070011},
+{7500000, DIF_BPF_COEFF45,    0x000affdf},
+{7500000, DIF_BPF_COEFF67,    0xffa9ffb5},
+{7500000, DIF_BPF_COEFF89,    0x003700e6},
+{7500000, DIF_BPF_COEFF1011,  0x01010000},
+{7500000, DIF_BPF_COEFF1213,  0xfe62fda8},
+{7500000, DIF_BPF_COEFF1415,  0xff140219},
+{7500000, DIF_BPF_COEFF1617,  0x043502e1},
+{7500000, DIF_BPF_COEFF1819,  0xfe42f9e6},
+{7500000, DIF_BPF_COEFF2021,  0xfa270000},
+{7500000, DIF_BPF_COEFF2223,  0x073a0953},
+{7500000, DIF_BPF_COEFF2425,  0x034cf939},
+{7500000, DIF_BPF_COEFF2627,  0xf3a4f845},
+{7500000, DIF_BPF_COEFF2829,  0x044c0de1},
+{7500000, DIF_BPF_COEFF3031,  0x0c4f0000},
+{7500000, DIF_BPF_COEFF3233,  0xf2e2f03c},
+{7500000, DIF_BPF_COEFF3435,  0xfacc09fe},
+{7500000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 75_quant.dat*/
+
+
+/*case 7600000:*/
+/* BEGIN - DIF BPF register values from 76_quant.dat*/
+{7600000, DIF_BPF_COEFF01,    0xffffffff},
+{7600000, DIF_BPF_COEFF23,    0x00040012},
+{7600000, DIF_BPF_COEFF45,    0x0016fff3},
+{7600000, DIF_BPF_COEFF67,    0xffafff95},
+{7600000, DIF_BPF_COEFF89,    0xfff900c0},
+{7600000, DIF_BPF_COEFF1011,  0x0130007e},
+{7600000, DIF_BPF_COEFF1213,  0xfecefd89},
+{7600000, DIF_BPF_COEFF1415,  0xfe560146},
+{7600000, DIF_BPF_COEFF1617,  0x041303bc},
+{7600000, DIF_BPF_COEFF1819,  0xff81fa76},
+{7600000, DIF_BPF_COEFF2021,  0xf96cfe7d},
+{7600000, DIF_BPF_COEFF2223,  0x063209b1},
+{7600000, DIF_BPF_COEFF2425,  0x04c9fa93},
+{7600000, DIF_BPF_COEFF2627,  0xf3bdf71e},
+{7600000, DIF_BPF_COEFF2829,  0x02f30d6e},
+{7600000, DIF_BPF_COEFF3031,  0x0cf200fd},
+{7600000, DIF_BPF_COEFF3233,  0xf361f00e},
+{7600000, DIF_BPF_COEFF3435,  0xfa6509d1},
+{7600000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 76_quant.dat*/
+
+
+/*case 7700000:*/
+/* BEGIN - DIF BPF register values from 77_quant.dat*/
+{7700000, DIF_BPF_COEFF01,    0xfffffffe},
+{7700000, DIF_BPF_COEFF23,    0x00010010},
+{7700000, DIF_BPF_COEFF45,    0x001e0008},
+{7700000, DIF_BPF_COEFF67,    0xffc1ff84},
+{7700000, DIF_BPF_COEFF89,    0xffbc0084},
+{7700000, DIF_BPF_COEFF1011,  0x013e00f0},
+{7700000, DIF_BPF_COEFF1213,  0xff56fd9f},
+{7700000, DIF_BPF_COEFF1415,  0xfdb8005c},
+{7700000, DIF_BPF_COEFF1617,  0x03b00460},
+{7700000, DIF_BPF_COEFF1819,  0x00c7fb45},
+{7700000, DIF_BPF_COEFF2021,  0xf8f4fd07},
+{7700000, DIF_BPF_COEFF2223,  0x04fa09ce},
+{7700000, DIF_BPF_COEFF2425,  0x062afc07},
+{7700000, DIF_BPF_COEFF2627,  0xf407f614},
+{7700000, DIF_BPF_COEFF2829,  0x01920ce0},
+{7700000, DIF_BPF_COEFF3031,  0x0d8301fa},
+{7700000, DIF_BPF_COEFF3233,  0xf3e8efe5},
+{7700000, DIF_BPF_COEFF3435,  0xfa0009a4},
+{7700000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 77_quant.dat*/
+
+
+/*case 7800000:*/
+/* BEGIN - DIF BPF register values from 78_quant.dat*/
+{7800000, DIF_BPF_COEFF01,    0x0000fffd},
+{7800000, DIF_BPF_COEFF23,    0xfffd000b},
+{7800000, DIF_BPF_COEFF45,    0x0022001d},
+{7800000, DIF_BPF_COEFF67,    0xffdbff82},
+{7800000, DIF_BPF_COEFF89,    0xff870039},
+{7800000, DIF_BPF_COEFF1011,  0x012a014a},
+{7800000, DIF_BPF_COEFF1213,  0xffedfde7},
+{7800000, DIF_BPF_COEFF1415,  0xfd47ff6b},
+{7800000, DIF_BPF_COEFF1617,  0x031104c6},
+{7800000, DIF_BPF_COEFF1819,  0x0202fc4c},
+{7800000, DIF_BPF_COEFF2021,  0xf8c6fbad},
+{7800000, DIF_BPF_COEFF2223,  0x039909a7},
+{7800000, DIF_BPF_COEFF2425,  0x0767fd8e},
+{7800000, DIF_BPF_COEFF2627,  0xf482f52b},
+{7800000, DIF_BPF_COEFF2829,  0x002d0c39},
+{7800000, DIF_BPF_COEFF3031,  0x0e0002f4},
+{7800000, DIF_BPF_COEFF3233,  0xf477efc2},
+{7800000, DIF_BPF_COEFF3435,  0xf99b0977},
+{7800000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 78_quant.dat*/
+
+
+/*case 7900000:*/
+/* BEGIN - DIF BPF register values from 79_quant.dat*/
+{7900000, DIF_BPF_COEFF01,    0x0000fffd},
+{7900000, DIF_BPF_COEFF23,    0xfffa0004},
+{7900000, DIF_BPF_COEFF45,    0x0020002d},
+{7900000, DIF_BPF_COEFF67,    0xfffbff91},
+{7900000, DIF_BPF_COEFF89,    0xff61ffe8},
+{7900000, DIF_BPF_COEFF1011,  0x00f70184},
+{7900000, DIF_BPF_COEFF1213,  0x0086fe5c},
+{7900000, DIF_BPF_COEFF1415,  0xfd0bfe85},
+{7900000, DIF_BPF_COEFF1617,  0x024104e5},
+{7900000, DIF_BPF_COEFF1819,  0x0323fd7d},
+{7900000, DIF_BPF_COEFF2021,  0xf8e2fa79},
+{7900000, DIF_BPF_COEFF2223,  0x021d093f},
+{7900000, DIF_BPF_COEFF2425,  0x0879ff22},
+{7900000, DIF_BPF_COEFF2627,  0xf52bf465},
+{7900000, DIF_BPF_COEFF2829,  0xfec70b79},
+{7900000, DIF_BPF_COEFF3031,  0x0e6803eb},
+{7900000, DIF_BPF_COEFF3233,  0xf50defa5},
+{7900000, DIF_BPF_COEFF3435,  0xf937094a},
+{7900000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 79_quant.dat*/
+
+
+/*case 8000000:*/
+/* BEGIN - DIF BPF register values from 80_quant.dat*/
+{8000000, DIF_BPF_COEFF01,    0x0000fffe},
+{8000000, DIF_BPF_COEFF23,    0xfff8fffd},
+{8000000, DIF_BPF_COEFF45,    0x00190036},
+{8000000, DIF_BPF_COEFF67,    0x001bffaf},
+{8000000, DIF_BPF_COEFF89,    0xff4fff99},
+{8000000, DIF_BPF_COEFF1011,  0x00aa0198},
+{8000000, DIF_BPF_COEFF1213,  0x0112fef3},
+{8000000, DIF_BPF_COEFF1415,  0xfd09fdb9},
+{8000000, DIF_BPF_COEFF1617,  0x014d04be},
+{8000000, DIF_BPF_COEFF1819,  0x041bfecc},
+{8000000, DIF_BPF_COEFF2021,  0xf947f978},
+{8000000, DIF_BPF_COEFF2223,  0x00900897},
+{8000000, DIF_BPF_COEFF2425,  0x095a00b9},
+{8000000, DIF_BPF_COEFF2627,  0xf600f3c5},
+{8000000, DIF_BPF_COEFF2829,  0xfd650aa3},
+{8000000, DIF_BPF_COEFF3031,  0x0ebc04de},
+{8000000, DIF_BPF_COEFF3233,  0xf5aaef8e},
+{8000000, DIF_BPF_COEFF3435,  0xf8d5091c},
+{8000000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 80_quant.dat*/
+
+
+/*case 8100000:*/
+/* BEGIN - DIF BPF register values from 81_quant.dat*/
+{8100000, DIF_BPF_COEFF01,    0x0000ffff},
+{8100000, DIF_BPF_COEFF23,    0xfff7fff6},
+{8100000, DIF_BPF_COEFF45,    0x000e0038},
+{8100000, DIF_BPF_COEFF67,    0x0037ffd7},
+{8100000, DIF_BPF_COEFF89,    0xff52ff56},
+{8100000, DIF_BPF_COEFF1011,  0x004b0184},
+{8100000, DIF_BPF_COEFF1213,  0x0186ffa1},
+{8100000, DIF_BPF_COEFF1415,  0xfd40fd16},
+{8100000, DIF_BPF_COEFF1617,  0x00440452},
+{8100000, DIF_BPF_COEFF1819,  0x04de0029},
+{8100000, DIF_BPF_COEFF2021,  0xf9f2f8b2},
+{8100000, DIF_BPF_COEFF2223,  0xfefe07b5},
+{8100000, DIF_BPF_COEFF2425,  0x0a05024d},
+{8100000, DIF_BPF_COEFF2627,  0xf6fef34d},
+{8100000, DIF_BPF_COEFF2829,  0xfc0a09b8},
+{8100000, DIF_BPF_COEFF3031,  0x0efa05cd},
+{8100000, DIF_BPF_COEFF3233,  0xf64eef7d},
+{8100000, DIF_BPF_COEFF3435,  0xf87308ed},
+{8100000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 81_quant.dat*/
+
+
+/*case 8200000:*/
+/* BEGIN - DIF BPF register values from 82_quant.dat*/
+{8200000, DIF_BPF_COEFF01,    0x00010000},
+{8200000, DIF_BPF_COEFF23,    0xfff8fff0},
+{8200000, DIF_BPF_COEFF45,    0x00000031},
+{8200000, DIF_BPF_COEFF67,    0x004c0005},
+{8200000, DIF_BPF_COEFF89,    0xff6aff27},
+{8200000, DIF_BPF_COEFF1011,  0xffe4014a},
+{8200000, DIF_BPF_COEFF1213,  0x01d70057},
+{8200000, DIF_BPF_COEFF1415,  0xfdacfca6},
+{8200000, DIF_BPF_COEFF1617,  0xff3603a7},
+{8200000, DIF_BPF_COEFF1819,  0x05610184},
+{8200000, DIF_BPF_COEFF2021,  0xfadbf82e},
+{8200000, DIF_BPF_COEFF2223,  0xfd74069f},
+{8200000, DIF_BPF_COEFF2425,  0x0a7503d6},
+{8200000, DIF_BPF_COEFF2627,  0xf81ff2ff},
+{8200000, DIF_BPF_COEFF2829,  0xfab808b9},
+{8200000, DIF_BPF_COEFF3031,  0x0f2306b5},
+{8200000, DIF_BPF_COEFF3233,  0xf6f9ef72},
+{8200000, DIF_BPF_COEFF3435,  0xf81308bf},
+{8200000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 82_quant.dat*/
+
+
+/*case 8300000:*/
+/* BEGIN - DIF BPF register values from 83_quant.dat*/
+{8300000, DIF_BPF_COEFF01,    0x00010001},
+{8300000, DIF_BPF_COEFF23,    0xfffbffee},
+{8300000, DIF_BPF_COEFF45,    0xfff30022},
+{8300000, DIF_BPF_COEFF67,    0x00560032},
+{8300000, DIF_BPF_COEFF89,    0xff95ff10},
+{8300000, DIF_BPF_COEFF1011,  0xff8000f0},
+{8300000, DIF_BPF_COEFF1213,  0x01fe0106},
+{8300000, DIF_BPF_COEFF1415,  0xfe46fc71},
+{8300000, DIF_BPF_COEFF1617,  0xfe3502c7},
+{8300000, DIF_BPF_COEFF1819,  0x059e02ce},
+{8300000, DIF_BPF_COEFF2021,  0xfbf9f7f2},
+{8300000, DIF_BPF_COEFF2223,  0xfbff055b},
+{8300000, DIF_BPF_COEFF2425,  0x0aa9054c},
+{8300000, DIF_BPF_COEFF2627,  0xf961f2db},
+{8300000, DIF_BPF_COEFF2829,  0xf97507aa},
+{8300000, DIF_BPF_COEFF3031,  0x0f350797},
+{8300000, DIF_BPF_COEFF3233,  0xf7a9ef6d},
+{8300000, DIF_BPF_COEFF3435,  0xf7b40890},
+{8300000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 83_quant.dat*/
+
+
+/*case 8400000:*/
+/* BEGIN - DIF BPF register values from 84_quant.dat*/
+{8400000, DIF_BPF_COEFF01,    0x00010002},
+{8400000, DIF_BPF_COEFF23,    0xfffeffee},
+{8400000, DIF_BPF_COEFF45,    0xffe8000f},
+{8400000, DIF_BPF_COEFF67,    0x00540058},
+{8400000, DIF_BPF_COEFF89,    0xffcdff14},
+{8400000, DIF_BPF_COEFF1011,  0xff29007e},
+{8400000, DIF_BPF_COEFF1213,  0x01f6019e},
+{8400000, DIF_BPF_COEFF1415,  0xff01fc7c},
+{8400000, DIF_BPF_COEFF1617,  0xfd5101bf},
+{8400000, DIF_BPF_COEFF1819,  0x059203f6},
+{8400000, DIF_BPF_COEFF2021,  0xfd41f7fe},
+{8400000, DIF_BPF_COEFF2223,  0xfaa903f3},
+{8400000, DIF_BPF_COEFF2425,  0x0a9e06a9},
+{8400000, DIF_BPF_COEFF2627,  0xfabdf2e2},
+{8400000, DIF_BPF_COEFF2829,  0xf842068b},
+{8400000, DIF_BPF_COEFF3031,  0x0f320871},
+{8400000, DIF_BPF_COEFF3233,  0xf85eef6e},
+{8400000, DIF_BPF_COEFF3435,  0xf7560860},
+{8400000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 84_quant.dat*/
+
+
+/*case 8500000:*/
+/* BEGIN - DIF BPF register values from 85_quant.dat*/
+{8500000, DIF_BPF_COEFF01,    0x00000003},
+{8500000, DIF_BPF_COEFF23,    0x0002fff2},
+{8500000, DIF_BPF_COEFF45,    0xffe1fff9},
+{8500000, DIF_BPF_COEFF67,    0x00460073},
+{8500000, DIF_BPF_COEFF89,    0x000bff34},
+{8500000, DIF_BPF_COEFF1011,  0xfee90000},
+{8500000, DIF_BPF_COEFF1213,  0x01c10215},
+{8500000, DIF_BPF_COEFF1415,  0xffd0fcc5},
+{8500000, DIF_BPF_COEFF1617,  0xfc99009d},
+{8500000, DIF_BPF_COEFF1819,  0x053d04f1},
+{8500000, DIF_BPF_COEFF2021,  0xfea5f853},
+{8500000, DIF_BPF_COEFF2223,  0xf97d0270},
+{8500000, DIF_BPF_COEFF2425,  0x0a5607e4},
+{8500000, DIF_BPF_COEFF2627,  0xfc2ef314},
+{8500000, DIF_BPF_COEFF2829,  0xf723055f},
+{8500000, DIF_BPF_COEFF3031,  0x0f180943},
+{8500000, DIF_BPF_COEFF3233,  0xf919ef75},
+{8500000, DIF_BPF_COEFF3435,  0xf6fa0830},
+{8500000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 85_quant.dat*/
+
+
+/*case 8600000:*/
+/* BEGIN - DIF BPF register values from 86_quant.dat*/
+{8600000, DIF_BPF_COEFF01,    0x00000003},
+{8600000, DIF_BPF_COEFF23,    0x0005fff8},
+{8600000, DIF_BPF_COEFF45,    0xffdeffe4},
+{8600000, DIF_BPF_COEFF67,    0x002f007f},
+{8600000, DIF_BPF_COEFF89,    0x0048ff6b},
+{8600000, DIF_BPF_COEFF1011,  0xfec7ff82},
+{8600000, DIF_BPF_COEFF1213,  0x0163025f},
+{8600000, DIF_BPF_COEFF1415,  0x00a2fd47},
+{8600000, DIF_BPF_COEFF1617,  0xfc17ff73},
+{8600000, DIF_BPF_COEFF1819,  0x04a405b2},
+{8600000, DIF_BPF_COEFF2021,  0x0017f8ed},
+{8600000, DIF_BPF_COEFF2223,  0xf88500dc},
+{8600000, DIF_BPF_COEFF2425,  0x09d208f9},
+{8600000, DIF_BPF_COEFF2627,  0xfdaff370},
+{8600000, DIF_BPF_COEFF2829,  0xf61c0429},
+{8600000, DIF_BPF_COEFF3031,  0x0ee80a0b},
+{8600000, DIF_BPF_COEFF3233,  0xf9d8ef82},
+{8600000, DIF_BPF_COEFF3435,  0xf6a00800},
+{8600000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 86_quant.dat*/
+
+
+/*case 8700000:*/
+/* BEGIN - DIF BPF register values from 87_quant.dat*/
+{8700000, DIF_BPF_COEFF01,    0x00000003},
+{8700000, DIF_BPF_COEFF23,    0x0007ffff},
+{8700000, DIF_BPF_COEFF45,    0xffe1ffd4},
+{8700000, DIF_BPF_COEFF67,    0x0010007a},
+{8700000, DIF_BPF_COEFF89,    0x007cffb2},
+{8700000, DIF_BPF_COEFF1011,  0xfec6ff10},
+{8700000, DIF_BPF_COEFF1213,  0x00e60277},
+{8700000, DIF_BPF_COEFF1415,  0x0168fdf9},
+{8700000, DIF_BPF_COEFF1617,  0xfbd3fe50},
+{8700000, DIF_BPF_COEFF1819,  0x03ce0631},
+{8700000, DIF_BPF_COEFF2021,  0x0188f9c8},
+{8700000, DIF_BPF_COEFF2223,  0xf7c7ff43},
+{8700000, DIF_BPF_COEFF2425,  0x091509e3},
+{8700000, DIF_BPF_COEFF2627,  0xff39f3f6},
+{8700000, DIF_BPF_COEFF2829,  0xf52d02ea},
+{8700000, DIF_BPF_COEFF3031,  0x0ea30ac9},
+{8700000, DIF_BPF_COEFF3233,  0xfa9bef95},
+{8700000, DIF_BPF_COEFF3435,  0xf64607d0},
+{8700000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 87_quant.dat*/
+
+
+/*case 8800000:*/
+/* BEGIN - DIF BPF register values from 88_quant.dat*/
+{8800000, DIF_BPF_COEFF01,    0x00000002},
+{8800000, DIF_BPF_COEFF23,    0x00090007},
+{8800000, DIF_BPF_COEFF45,    0xffe9ffca},
+{8800000, DIF_BPF_COEFF67,    0xfff00065},
+{8800000, DIF_BPF_COEFF89,    0x00a10003},
+{8800000, DIF_BPF_COEFF1011,  0xfee6feb6},
+{8800000, DIF_BPF_COEFF1213,  0x0053025b},
+{8800000, DIF_BPF_COEFF1415,  0x0213fed0},
+{8800000, DIF_BPF_COEFF1617,  0xfbd3fd46},
+{8800000, DIF_BPF_COEFF1819,  0x02c70668},
+{8800000, DIF_BPF_COEFF2021,  0x02eafadb},
+{8800000, DIF_BPF_COEFF2223,  0xf74bfdae},
+{8800000, DIF_BPF_COEFF2425,  0x08230a9c},
+{8800000, DIF_BPF_COEFF2627,  0x00c7f4a3},
+{8800000, DIF_BPF_COEFF2829,  0xf45b01a6},
+{8800000, DIF_BPF_COEFF3031,  0x0e480b7c},
+{8800000, DIF_BPF_COEFF3233,  0xfb61efae},
+{8800000, DIF_BPF_COEFF3435,  0xf5ef079f},
+{8800000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 88_quant.dat*/
+
+
+/*case 8900000:*/
+/* BEGIN - DIF BPF register values from 89_quant.dat*/
+{8900000, DIF_BPF_COEFF01,    0xffff0000},
+{8900000, DIF_BPF_COEFF23,    0x0008000d},
+{8900000, DIF_BPF_COEFF45,    0xfff5ffc8},
+{8900000, DIF_BPF_COEFF67,    0xffd10043},
+{8900000, DIF_BPF_COEFF89,    0x00b20053},
+{8900000, DIF_BPF_COEFF1011,  0xff24fe7c},
+{8900000, DIF_BPF_COEFF1213,  0xffb9020c},
+{8900000, DIF_BPF_COEFF1415,  0x0295ffbb},
+{8900000, DIF_BPF_COEFF1617,  0xfc17fc64},
+{8900000, DIF_BPF_COEFF1819,  0x019b0654},
+{8900000, DIF_BPF_COEFF2021,  0x042dfc1c},
+{8900000, DIF_BPF_COEFF2223,  0xf714fc2a},
+{8900000, DIF_BPF_COEFF2425,  0x07020b21},
+{8900000, DIF_BPF_COEFF2627,  0x0251f575},
+{8900000, DIF_BPF_COEFF2829,  0xf3a7005e},
+{8900000, DIF_BPF_COEFF3031,  0x0dd80c24},
+{8900000, DIF_BPF_COEFF3233,  0xfc2aefcd},
+{8900000, DIF_BPF_COEFF3435,  0xf599076e},
+{8900000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 89_quant.dat*/
+
+
+/*case 9000000:*/
+/* BEGIN - DIF BPF register values from 90_quant.dat*/
+{9000000, DIF_BPF_COEFF01,    0xffffffff},
+{9000000, DIF_BPF_COEFF23,    0x00060011},
+{9000000, DIF_BPF_COEFF45,    0x0002ffcf},
+{9000000, DIF_BPF_COEFF67,    0xffba0018},
+{9000000, DIF_BPF_COEFF89,    0x00ad009a},
+{9000000, DIF_BPF_COEFF1011,  0xff79fe68},
+{9000000, DIF_BPF_COEFF1213,  0xff260192},
+{9000000, DIF_BPF_COEFF1415,  0x02e500ab},
+{9000000, DIF_BPF_COEFF1617,  0xfc99fbb6},
+{9000000, DIF_BPF_COEFF1819,  0x005b05f7},
+{9000000, DIF_BPF_COEFF2021,  0x0545fd81},
+{9000000, DIF_BPF_COEFF2223,  0xf723fabf},
+{9000000, DIF_BPF_COEFF2425,  0x05b80b70},
+{9000000, DIF_BPF_COEFF2627,  0x03d2f669},
+{9000000, DIF_BPF_COEFF2829,  0xf313ff15},
+{9000000, DIF_BPF_COEFF3031,  0x0d550cbf},
+{9000000, DIF_BPF_COEFF3233,  0xfcf6eff2},
+{9000000, DIF_BPF_COEFF3435,  0xf544073d},
+{9000000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 90_quant.dat*/
+
+
+/*case 9100000:*/
+/* BEGIN - DIF BPF register values from 91_quant.dat*/
+{9100000, DIF_BPF_COEFF01,    0xfffffffe},
+{9100000, DIF_BPF_COEFF23,    0x00030012},
+{9100000, DIF_BPF_COEFF45,    0x000fffdd},
+{9100000, DIF_BPF_COEFF67,    0xffacffea},
+{9100000, DIF_BPF_COEFF89,    0x009300cf},
+{9100000, DIF_BPF_COEFF1011,  0xffdcfe7c},
+{9100000, DIF_BPF_COEFF1213,  0xfea600f7},
+{9100000, DIF_BPF_COEFF1415,  0x02fd0190},
+{9100000, DIF_BPF_COEFF1617,  0xfd51fb46},
+{9100000, DIF_BPF_COEFF1819,  0xff150554},
+{9100000, DIF_BPF_COEFF2021,  0x0627fefd},
+{9100000, DIF_BPF_COEFF2223,  0xf778f978},
+{9100000, DIF_BPF_COEFF2425,  0x044d0b87},
+{9100000, DIF_BPF_COEFF2627,  0x0543f77d},
+{9100000, DIF_BPF_COEFF2829,  0xf2a0fdcf},
+{9100000, DIF_BPF_COEFF3031,  0x0cbe0d4e},
+{9100000, DIF_BPF_COEFF3233,  0xfdc4f01d},
+{9100000, DIF_BPF_COEFF3435,  0xf4f2070b},
+{9100000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 91_quant.dat*/
+
+
+/*case 9200000:*/
+/* BEGIN - DIF BPF register values from 92_quant.dat*/
+{9200000, DIF_BPF_COEFF01,    0x0000fffd},
+{9200000, DIF_BPF_COEFF23,    0x00000010},
+{9200000, DIF_BPF_COEFF45,    0x001afff0},
+{9200000, DIF_BPF_COEFF67,    0xffaaffbf},
+{9200000, DIF_BPF_COEFF89,    0x006700ed},
+{9200000, DIF_BPF_COEFF1011,  0x0043feb6},
+{9200000, DIF_BPF_COEFF1213,  0xfe460047},
+{9200000, DIF_BPF_COEFF1415,  0x02db0258},
+{9200000, DIF_BPF_COEFF1617,  0xfe35fb1b},
+{9200000, DIF_BPF_COEFF1819,  0xfddc0473},
+{9200000, DIF_BPF_COEFF2021,  0x06c90082},
+{9200000, DIF_BPF_COEFF2223,  0xf811f85e},
+{9200000, DIF_BPF_COEFF2425,  0x02c90b66},
+{9200000, DIF_BPF_COEFF2627,  0x069ff8ad},
+{9200000, DIF_BPF_COEFF2829,  0xf250fc8d},
+{9200000, DIF_BPF_COEFF3031,  0x0c140dcf},
+{9200000, DIF_BPF_COEFF3233,  0xfe93f04d},
+{9200000, DIF_BPF_COEFF3435,  0xf4a106d9},
+{9200000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 92_quant.dat*/
+
+
+/*case 9300000:*/
+/* BEGIN - DIF BPF register values from 93_quant.dat*/
+{9300000, DIF_BPF_COEFF01,    0x0000fffd},
+{9300000, DIF_BPF_COEFF23,    0xfffc000c},
+{9300000, DIF_BPF_COEFF45,    0x00200006},
+{9300000, DIF_BPF_COEFF67,    0xffb4ff9c},
+{9300000, DIF_BPF_COEFF89,    0x002f00ef},
+{9300000, DIF_BPF_COEFF1011,  0x00a4ff10},
+{9300000, DIF_BPF_COEFF1213,  0xfe0dff92},
+{9300000, DIF_BPF_COEFF1415,  0x028102f7},
+{9300000, DIF_BPF_COEFF1617,  0xff36fb37},
+{9300000, DIF_BPF_COEFF1819,  0xfcbf035e},
+{9300000, DIF_BPF_COEFF2021,  0x07260202},
+{9300000, DIF_BPF_COEFF2223,  0xf8e8f778},
+{9300000, DIF_BPF_COEFF2425,  0x01340b0d},
+{9300000, DIF_BPF_COEFF2627,  0x07e1f9f4},
+{9300000, DIF_BPF_COEFF2829,  0xf223fb51},
+{9300000, DIF_BPF_COEFF3031,  0x0b590e42},
+{9300000, DIF_BPF_COEFF3233,  0xff64f083},
+{9300000, DIF_BPF_COEFF3435,  0xf45206a7},
+{9300000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 93_quant.dat*/
+
+
+/*case 9400000:*/
+/* BEGIN - DIF BPF register values from 94_quant.dat*/
+{9400000, DIF_BPF_COEFF01,    0x0000fffd},
+{9400000, DIF_BPF_COEFF23,    0xfff90005},
+{9400000, DIF_BPF_COEFF45,    0x0022001a},
+{9400000, DIF_BPF_COEFF67,    0xffc9ff86},
+{9400000, DIF_BPF_COEFF89,    0xfff000d7},
+{9400000, DIF_BPF_COEFF1011,  0x00f2ff82},
+{9400000, DIF_BPF_COEFF1213,  0xfe01fee5},
+{9400000, DIF_BPF_COEFF1415,  0x01f60362},
+{9400000, DIF_BPF_COEFF1617,  0x0044fb99},
+{9400000, DIF_BPF_COEFF1819,  0xfbcc0222},
+{9400000, DIF_BPF_COEFF2021,  0x07380370},
+{9400000, DIF_BPF_COEFF2223,  0xf9f7f6cc},
+{9400000, DIF_BPF_COEFF2425,  0xff990a7e},
+{9400000, DIF_BPF_COEFF2627,  0x0902fb50},
+{9400000, DIF_BPF_COEFF2829,  0xf21afa1f},
+{9400000, DIF_BPF_COEFF3031,  0x0a8d0ea6},
+{9400000, DIF_BPF_COEFF3233,  0x0034f0bf},
+{9400000, DIF_BPF_COEFF3435,  0xf4050675},
+{9400000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 94_quant.dat*/
+
+
+/*case 9500000:*/
+/* BEGIN - DIF BPF register values from 95_quant.dat*/
+{9500000, DIF_BPF_COEFF01,    0x0000fffe},
+{9500000, DIF_BPF_COEFF23,    0xfff8fffe},
+{9500000, DIF_BPF_COEFF45,    0x001e002b},
+{9500000, DIF_BPF_COEFF67,    0xffe5ff81},
+{9500000, DIF_BPF_COEFF89,    0xffb400a5},
+{9500000, DIF_BPF_COEFF1011,  0x01280000},
+{9500000, DIF_BPF_COEFF1213,  0xfe24fe50},
+{9500000, DIF_BPF_COEFF1415,  0x01460390},
+{9500000, DIF_BPF_COEFF1617,  0x014dfc3a},
+{9500000, DIF_BPF_COEFF1819,  0xfb1000ce},
+{9500000, DIF_BPF_COEFF2021,  0x070104bf},
+{9500000, DIF_BPF_COEFF2223,  0xfb37f65f},
+{9500000, DIF_BPF_COEFF2425,  0xfe0009bc},
+{9500000, DIF_BPF_COEFF2627,  0x0a00fcbb},
+{9500000, DIF_BPF_COEFF2829,  0xf235f8f8},
+{9500000, DIF_BPF_COEFF3031,  0x09b20efc},
+{9500000, DIF_BPF_COEFF3233,  0x0105f101},
+{9500000, DIF_BPF_COEFF3435,  0xf3ba0642},
+{9500000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 95_quant.dat*/
+
+
+/*case 9600000:*/
+/* BEGIN - DIF BPF register values from 96_quant.dat*/
+{9600000, DIF_BPF_COEFF01,    0x0001ffff},
+{9600000, DIF_BPF_COEFF23,    0xfff8fff7},
+{9600000, DIF_BPF_COEFF45,    0x00150036},
+{9600000, DIF_BPF_COEFF67,    0x0005ff8c},
+{9600000, DIF_BPF_COEFF89,    0xff810061},
+{9600000, DIF_BPF_COEFF1011,  0x013d007e},
+{9600000, DIF_BPF_COEFF1213,  0xfe71fddf},
+{9600000, DIF_BPF_COEFF1415,  0x007c0380},
+{9600000, DIF_BPF_COEFF1617,  0x0241fd13},
+{9600000, DIF_BPF_COEFF1819,  0xfa94ff70},
+{9600000, DIF_BPF_COEFF2021,  0x068005e2},
+{9600000, DIF_BPF_COEFF2223,  0xfc9bf633},
+{9600000, DIF_BPF_COEFF2425,  0xfc7308ca},
+{9600000, DIF_BPF_COEFF2627,  0x0ad5fe30},
+{9600000, DIF_BPF_COEFF2829,  0xf274f7e0},
+{9600000, DIF_BPF_COEFF3031,  0x08c90f43},
+{9600000, DIF_BPF_COEFF3233,  0x01d4f147},
+{9600000, DIF_BPF_COEFF3435,  0xf371060f},
+{9600000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 96_quant.dat*/
+
+
+/*case 9700000:*/
+/* BEGIN - DIF BPF register values from 97_quant.dat*/
+{9700000, DIF_BPF_COEFF01,    0x00010001},
+{9700000, DIF_BPF_COEFF23,    0xfff9fff1},
+{9700000, DIF_BPF_COEFF45,    0x00090038},
+{9700000, DIF_BPF_COEFF67,    0x0025ffa7},
+{9700000, DIF_BPF_COEFF89,    0xff5e0012},
+{9700000, DIF_BPF_COEFF1011,  0x013200f0},
+{9700000, DIF_BPF_COEFF1213,  0xfee3fd9b},
+{9700000, DIF_BPF_COEFF1415,  0xffaa0331},
+{9700000, DIF_BPF_COEFF1617,  0x0311fe15},
+{9700000, DIF_BPF_COEFF1819,  0xfa60fe18},
+{9700000, DIF_BPF_COEFF2021,  0x05bd06d1},
+{9700000, DIF_BPF_COEFF2223,  0xfe1bf64a},
+{9700000, DIF_BPF_COEFF2425,  0xfafa07ae},
+{9700000, DIF_BPF_COEFF2627,  0x0b7effab},
+{9700000, DIF_BPF_COEFF2829,  0xf2d5f6d7},
+{9700000, DIF_BPF_COEFF3031,  0x07d30f7a},
+{9700000, DIF_BPF_COEFF3233,  0x02a3f194},
+{9700000, DIF_BPF_COEFF3435,  0xf32905dc},
+{9700000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 97_quant.dat*/
+
+
+/*case 9800000:*/
+/* BEGIN - DIF BPF register values from 98_quant.dat*/
+{9800000, DIF_BPF_COEFF01,    0x00010002},
+{9800000, DIF_BPF_COEFF23,    0xfffcffee},
+{9800000, DIF_BPF_COEFF45,    0xfffb0032},
+{9800000, DIF_BPF_COEFF67,    0x003fffcd},
+{9800000, DIF_BPF_COEFF89,    0xff4effc1},
+{9800000, DIF_BPF_COEFF1011,  0x0106014a},
+{9800000, DIF_BPF_COEFF1213,  0xff6efd8a},
+{9800000, DIF_BPF_COEFF1415,  0xfedd02aa},
+{9800000, DIF_BPF_COEFF1617,  0x03b0ff34},
+{9800000, DIF_BPF_COEFF1819,  0xfa74fcd7},
+{9800000, DIF_BPF_COEFF2021,  0x04bf0781},
+{9800000, DIF_BPF_COEFF2223,  0xffaaf6a3},
+{9800000, DIF_BPF_COEFF2425,  0xf99e066b},
+{9800000, DIF_BPF_COEFF2627,  0x0bf90128},
+{9800000, DIF_BPF_COEFF2829,  0xf359f5e1},
+{9800000, DIF_BPF_COEFF3031,  0x06d20fa2},
+{9800000, DIF_BPF_COEFF3233,  0x0370f1e5},
+{9800000, DIF_BPF_COEFF3435,  0xf2e405a8},
+{9800000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 98_quant.dat*/
+
+
+/*case 9900000:*/
+/* BEGIN - DIF BPF register values from 99_quant.dat*/
+{9900000, DIF_BPF_COEFF01,    0x00000003},
+{9900000, DIF_BPF_COEFF23,    0xffffffee},
+{9900000, DIF_BPF_COEFF45,    0xffef0024},
+{9900000, DIF_BPF_COEFF67,    0x0051fffa},
+{9900000, DIF_BPF_COEFF89,    0xff54ff77},
+{9900000, DIF_BPF_COEFF1011,  0x00be0184},
+{9900000, DIF_BPF_COEFF1213,  0x0006fdad},
+{9900000, DIF_BPF_COEFF1415,  0xfe2701f3},
+{9900000, DIF_BPF_COEFF1617,  0x0413005e},
+{9900000, DIF_BPF_COEFF1819,  0xfad1fbba},
+{9900000, DIF_BPF_COEFF2021,  0x039007ee},
+{9900000, DIF_BPF_COEFF2223,  0x013bf73d},
+{9900000, DIF_BPF_COEFF2425,  0xf868050a},
+{9900000, DIF_BPF_COEFF2627,  0x0c4302a1},
+{9900000, DIF_BPF_COEFF2829,  0xf3fdf4fe},
+{9900000, DIF_BPF_COEFF3031,  0x05c70fba},
+{9900000, DIF_BPF_COEFF3233,  0x043bf23c},
+{9900000, DIF_BPF_COEFF3435,  0xf2a10575},
+{9900000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 99_quant.dat*/
+
+
+/*case 10000000:*/
+/* BEGIN - DIF BPF register values from 100_quant.dat*/
+{10000000, DIF_BPF_COEFF01,    0x00000003},
+{10000000, DIF_BPF_COEFF23,    0x0003fff1},
+{10000000, DIF_BPF_COEFF45,    0xffe50011},
+{10000000, DIF_BPF_COEFF67,    0x00570027},
+{10000000, DIF_BPF_COEFF89,    0xff70ff3c},
+{10000000, DIF_BPF_COEFF1011,  0x00620198},
+{10000000, DIF_BPF_COEFF1213,  0x009efe01},
+{10000000, DIF_BPF_COEFF1415,  0xfd95011a},
+{10000000, DIF_BPF_COEFF1617,  0x04350183},
+{10000000, DIF_BPF_COEFF1819,  0xfb71fad0},
+{10000000, DIF_BPF_COEFF2021,  0x023c0812},
+{10000000, DIF_BPF_COEFF2223,  0x02c3f811},
+{10000000, DIF_BPF_COEFF2425,  0xf75e0390},
+{10000000, DIF_BPF_COEFF2627,  0x0c5c0411},
+{10000000, DIF_BPF_COEFF2829,  0xf4c1f432},
+{10000000, DIF_BPF_COEFF3031,  0x04b30fc1},
+{10000000, DIF_BPF_COEFF3233,  0x0503f297},
+{10000000, DIF_BPF_COEFF3435,  0xf2610541},
+{10000000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 100_quant.dat*/
+
+
+/*case 10100000:*/
+/* BEGIN - DIF BPF register values from 101_quant.dat*/
+{10100000, DIF_BPF_COEFF01,    0x00000003},
+{10100000, DIF_BPF_COEFF23,    0x0006fff7},
+{10100000, DIF_BPF_COEFF45,    0xffdffffc},
+{10100000, DIF_BPF_COEFF67,    0x00510050},
+{10100000, DIF_BPF_COEFF89,    0xff9dff18},
+{10100000, DIF_BPF_COEFF1011,  0xfffc0184},
+{10100000, DIF_BPF_COEFF1213,  0x0128fe80},
+{10100000, DIF_BPF_COEFF1415,  0xfd32002e},
+{10100000, DIF_BPF_COEFF1617,  0x04130292},
+{10100000, DIF_BPF_COEFF1819,  0xfc4dfa21},
+{10100000, DIF_BPF_COEFF2021,  0x00d107ee},
+{10100000, DIF_BPF_COEFF2223,  0x0435f91c},
+{10100000, DIF_BPF_COEFF2425,  0xf6850205},
+{10100000, DIF_BPF_COEFF2627,  0x0c430573},
+{10100000, DIF_BPF_COEFF2829,  0xf5a1f37d},
+{10100000, DIF_BPF_COEFF3031,  0x03990fba},
+{10100000, DIF_BPF_COEFF3233,  0x05c7f2f8},
+{10100000, DIF_BPF_COEFF3435,  0xf222050d},
+{10100000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 101_quant.dat*/
+
+
+/*case 10200000:*/
+/* BEGIN - DIF BPF register values from 102_quant.dat*/
+{10200000, DIF_BPF_COEFF01,    0x00000002},
+{10200000, DIF_BPF_COEFF23,    0x0008fffe},
+{10200000, DIF_BPF_COEFF45,    0xffdfffe7},
+{10200000, DIF_BPF_COEFF67,    0x003f006e},
+{10200000, DIF_BPF_COEFF89,    0xffd6ff0f},
+{10200000, DIF_BPF_COEFF1011,  0xff96014a},
+{10200000, DIF_BPF_COEFF1213,  0x0197ff1f},
+{10200000, DIF_BPF_COEFF1415,  0xfd05ff3e},
+{10200000, DIF_BPF_COEFF1617,  0x03b0037c},
+{10200000, DIF_BPF_COEFF1819,  0xfd59f9b7},
+{10200000, DIF_BPF_COEFF2021,  0xff5d0781},
+{10200000, DIF_BPF_COEFF2223,  0x0585fa56},
+{10200000, DIF_BPF_COEFF2425,  0xf5e4006f},
+{10200000, DIF_BPF_COEFF2627,  0x0bf906c4},
+{10200000, DIF_BPF_COEFF2829,  0xf69df2e0},
+{10200000, DIF_BPF_COEFF3031,  0x02790fa2},
+{10200000, DIF_BPF_COEFF3233,  0x0688f35d},
+{10200000, DIF_BPF_COEFF3435,  0xf1e604d8},
+{10200000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 102_quant.dat*/
+
+
+/*case 10300000:*/
+/* BEGIN - DIF BPF register values from 103_quant.dat*/
+{10300000, DIF_BPF_COEFF01,    0xffff0001},
+{10300000, DIF_BPF_COEFF23,    0x00090005},
+{10300000, DIF_BPF_COEFF45,    0xffe4ffd6},
+{10300000, DIF_BPF_COEFF67,    0x0025007e},
+{10300000, DIF_BPF_COEFF89,    0x0014ff20},
+{10300000, DIF_BPF_COEFF1011,  0xff3c00f0},
+{10300000, DIF_BPF_COEFF1213,  0x01e1ffd0},
+{10300000, DIF_BPF_COEFF1415,  0xfd12fe5c},
+{10300000, DIF_BPF_COEFF1617,  0x03110433},
+{10300000, DIF_BPF_COEFF1819,  0xfe88f996},
+{10300000, DIF_BPF_COEFF2021,  0xfdf106d1},
+{10300000, DIF_BPF_COEFF2223,  0x06aafbb7},
+{10300000, DIF_BPF_COEFF2425,  0xf57efed8},
+{10300000, DIF_BPF_COEFF2627,  0x0b7e07ff},
+{10300000, DIF_BPF_COEFF2829,  0xf7b0f25e},
+{10300000, DIF_BPF_COEFF3031,  0x01560f7a},
+{10300000, DIF_BPF_COEFF3233,  0x0745f3c7},
+{10300000, DIF_BPF_COEFF3435,  0xf1ac04a4},
+{10300000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 103_quant.dat*/
+
+
+/*case 10400000:*/
+/* BEGIN - DIF BPF register values from 104_quant.dat*/
+{10400000, DIF_BPF_COEFF01,    0xffffffff},
+{10400000, DIF_BPF_COEFF23,    0x0008000c},
+{10400000, DIF_BPF_COEFF45,    0xffedffcb},
+{10400000, DIF_BPF_COEFF67,    0x0005007d},
+{10400000, DIF_BPF_COEFF89,    0x0050ff4c},
+{10400000, DIF_BPF_COEFF1011,  0xfef6007e},
+{10400000, DIF_BPF_COEFF1213,  0x01ff0086},
+{10400000, DIF_BPF_COEFF1415,  0xfd58fd97},
+{10400000, DIF_BPF_COEFF1617,  0x024104ad},
+{10400000, DIF_BPF_COEFF1819,  0xffcaf9c0},
+{10400000, DIF_BPF_COEFF2021,  0xfc9905e2},
+{10400000, DIF_BPF_COEFF2223,  0x079afd35},
+{10400000, DIF_BPF_COEFF2425,  0xf555fd46},
+{10400000, DIF_BPF_COEFF2627,  0x0ad50920},
+{10400000, DIF_BPF_COEFF2829,  0xf8d9f1f6},
+{10400000, DIF_BPF_COEFF3031,  0x00310f43},
+{10400000, DIF_BPF_COEFF3233,  0x07fdf435},
+{10400000, DIF_BPF_COEFF3435,  0xf174046f},
+{10400000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 104_quant.dat*/
+
+
+/*case 10500000:*/
+/* BEGIN - DIF BPF register values from 105_quant.dat*/
+{10500000, DIF_BPF_COEFF01,    0xfffffffe},
+{10500000, DIF_BPF_COEFF23,    0x00050011},
+{10500000, DIF_BPF_COEFF45,    0xfffaffc8},
+{10500000, DIF_BPF_COEFF67,    0xffe5006b},
+{10500000, DIF_BPF_COEFF89,    0x0082ff8c},
+{10500000, DIF_BPF_COEFF1011,  0xfecc0000},
+{10500000, DIF_BPF_COEFF1213,  0x01f00130},
+{10500000, DIF_BPF_COEFF1415,  0xfdd2fcfc},
+{10500000, DIF_BPF_COEFF1617,  0x014d04e3},
+{10500000, DIF_BPF_COEFF1819,  0x010efa32},
+{10500000, DIF_BPF_COEFF2021,  0xfb6404bf},
+{10500000, DIF_BPF_COEFF2223,  0x084efec5},
+{10500000, DIF_BPF_COEFF2425,  0xf569fbc2},
+{10500000, DIF_BPF_COEFF2627,  0x0a000a23},
+{10500000, DIF_BPF_COEFF2829,  0xfa15f1ab},
+{10500000, DIF_BPF_COEFF3031,  0xff0b0efc},
+{10500000, DIF_BPF_COEFF3233,  0x08b0f4a7},
+{10500000, DIF_BPF_COEFF3435,  0xf13f043a},
+{10500000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 105_quant.dat*/
+
+
+/*case 10600000:*/
+/* BEGIN - DIF BPF register values from 106_quant.dat*/
+{10600000, DIF_BPF_COEFF01,    0x0000fffd},
+{10600000, DIF_BPF_COEFF23,    0x00020012},
+{10600000, DIF_BPF_COEFF45,    0x0007ffcd},
+{10600000, DIF_BPF_COEFF67,    0xffc9004c},
+{10600000, DIF_BPF_COEFF89,    0x00a4ffd9},
+{10600000, DIF_BPF_COEFF1011,  0xfec3ff82},
+{10600000, DIF_BPF_COEFF1213,  0x01b401c1},
+{10600000, DIF_BPF_COEFF1415,  0xfe76fc97},
+{10600000, DIF_BPF_COEFF1617,  0x004404d2},
+{10600000, DIF_BPF_COEFF1819,  0x0245fae8},
+{10600000, DIF_BPF_COEFF2021,  0xfa5f0370},
+{10600000, DIF_BPF_COEFF2223,  0x08c1005f},
+{10600000, DIF_BPF_COEFF2425,  0xf5bcfa52},
+{10600000, DIF_BPF_COEFF2627,  0x09020b04},
+{10600000, DIF_BPF_COEFF2829,  0xfb60f17b},
+{10600000, DIF_BPF_COEFF3031,  0xfde70ea6},
+{10600000, DIF_BPF_COEFF3233,  0x095df51e},
+{10600000, DIF_BPF_COEFF3435,  0xf10c0405},
+{10600000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 106_quant.dat*/
+
+
+/*case 10700000:*/
+/* BEGIN - DIF BPF register values from 107_quant.dat*/
+{10700000, DIF_BPF_COEFF01,    0x0000fffd},
+{10700000, DIF_BPF_COEFF23,    0xffff0011},
+{10700000, DIF_BPF_COEFF45,    0x0014ffdb},
+{10700000, DIF_BPF_COEFF67,    0xffb40023},
+{10700000, DIF_BPF_COEFF89,    0x00b2002a},
+{10700000, DIF_BPF_COEFF1011,  0xfedbff10},
+{10700000, DIF_BPF_COEFF1213,  0x0150022d},
+{10700000, DIF_BPF_COEFF1415,  0xff38fc6f},
+{10700000, DIF_BPF_COEFF1617,  0xff36047b},
+{10700000, DIF_BPF_COEFF1819,  0x035efbda},
+{10700000, DIF_BPF_COEFF2021,  0xf9940202},
+{10700000, DIF_BPF_COEFF2223,  0x08ee01f5},
+{10700000, DIF_BPF_COEFF2425,  0xf649f8fe},
+{10700000, DIF_BPF_COEFF2627,  0x07e10bc2},
+{10700000, DIF_BPF_COEFF2829,  0xfcb6f169},
+{10700000, DIF_BPF_COEFF3031,  0xfcc60e42},
+{10700000, DIF_BPF_COEFF3233,  0x0a04f599},
+{10700000, DIF_BPF_COEFF3435,  0xf0db03d0},
+{10700000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 107_quant.dat*/
+
+
+/*case 10800000:*/
+/* BEGIN - DIF BPF register values from 108_quant.dat*/
+{10800000, DIF_BPF_COEFF01,    0x0000fffd},
+{10800000, DIF_BPF_COEFF23,    0xfffb000d},
+{10800000, DIF_BPF_COEFF45,    0x001dffed},
+{10800000, DIF_BPF_COEFF67,    0xffaafff5},
+{10800000, DIF_BPF_COEFF89,    0x00aa0077},
+{10800000, DIF_BPF_COEFF1011,  0xff13feb6},
+{10800000, DIF_BPF_COEFF1213,  0x00ce026b},
+{10800000, DIF_BPF_COEFF1415,  0x000afc85},
+{10800000, DIF_BPF_COEFF1617,  0xfe3503e3},
+{10800000, DIF_BPF_COEFF1819,  0x044cfcfb},
+{10800000, DIF_BPF_COEFF2021,  0xf90c0082},
+{10800000, DIF_BPF_COEFF2223,  0x08d5037f},
+{10800000, DIF_BPF_COEFF2425,  0xf710f7cc},
+{10800000, DIF_BPF_COEFF2627,  0x069f0c59},
+{10800000, DIF_BPF_COEFF2829,  0xfe16f173},
+{10800000, DIF_BPF_COEFF3031,  0xfbaa0dcf},
+{10800000, DIF_BPF_COEFF3233,  0x0aa5f617},
+{10800000, DIF_BPF_COEFF3435,  0xf0ad039b},
+{10800000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 108_quant.dat*/
+
+
+/*case 10900000:*/
+/* BEGIN - DIF BPF register values from 109_quant.dat*/
+{10900000, DIF_BPF_COEFF01,    0x0000fffe},
+{10900000, DIF_BPF_COEFF23,    0xfff90006},
+{10900000, DIF_BPF_COEFF45,    0x00210003},
+{10900000, DIF_BPF_COEFF67,    0xffacffc8},
+{10900000, DIF_BPF_COEFF89,    0x008e00b6},
+{10900000, DIF_BPF_COEFF1011,  0xff63fe7c},
+{10900000, DIF_BPF_COEFF1213,  0x003a0275},
+{10900000, DIF_BPF_COEFF1415,  0x00dafcda},
+{10900000, DIF_BPF_COEFF1617,  0xfd510313},
+{10900000, DIF_BPF_COEFF1819,  0x0501fe40},
+{10900000, DIF_BPF_COEFF2021,  0xf8cbfefd},
+{10900000, DIF_BPF_COEFF2223,  0x087604f0},
+{10900000, DIF_BPF_COEFF2425,  0xf80af6c2},
+{10900000, DIF_BPF_COEFF2627,  0x05430cc8},
+{10900000, DIF_BPF_COEFF2829,  0xff7af19a},
+{10900000, DIF_BPF_COEFF3031,  0xfa940d4e},
+{10900000, DIF_BPF_COEFF3233,  0x0b3ff699},
+{10900000, DIF_BPF_COEFF3435,  0xf0810365},
+{10900000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 109_quant.dat*/
+
+
+/*case 11000000:*/
+/* BEGIN - DIF BPF register values from 110_quant.dat*/
+{11000000, DIF_BPF_COEFF01,    0x0001ffff},
+{11000000, DIF_BPF_COEFF23,    0xfff8ffff},
+{11000000, DIF_BPF_COEFF45,    0x00210018},
+{11000000, DIF_BPF_COEFF67,    0xffbaffa3},
+{11000000, DIF_BPF_COEFF89,    0x006000e1},
+{11000000, DIF_BPF_COEFF1011,  0xffc4fe68},
+{11000000, DIF_BPF_COEFF1213,  0xffa0024b},
+{11000000, DIF_BPF_COEFF1415,  0x019afd66},
+{11000000, DIF_BPF_COEFF1617,  0xfc990216},
+{11000000, DIF_BPF_COEFF1819,  0x0575ff99},
+{11000000, DIF_BPF_COEFF2021,  0xf8d4fd81},
+{11000000, DIF_BPF_COEFF2223,  0x07d40640},
+{11000000, DIF_BPF_COEFF2425,  0xf932f5e6},
+{11000000, DIF_BPF_COEFF2627,  0x03d20d0d},
+{11000000, DIF_BPF_COEFF2829,  0x00dff1de},
+{11000000, DIF_BPF_COEFF3031,  0xf9860cbf},
+{11000000, DIF_BPF_COEFF3233,  0x0bd1f71e},
+{11000000, DIF_BPF_COEFF3435,  0xf058032f},
+{11000000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 110_quant.dat*/
+
+
+/*case 11100000:*/
+/* BEGIN - DIF BPF register values from 111_quant.dat*/
+{11100000, DIF_BPF_COEFF01,    0x00010000},
+{11100000, DIF_BPF_COEFF23,    0xfff8fff8},
+{11100000, DIF_BPF_COEFF45,    0x001b0029},
+{11100000, DIF_BPF_COEFF67,    0xffd1ff8a},
+{11100000, DIF_BPF_COEFF89,    0x002600f2},
+{11100000, DIF_BPF_COEFF1011,  0x002cfe7c},
+{11100000, DIF_BPF_COEFF1213,  0xff0f01f0},
+{11100000, DIF_BPF_COEFF1415,  0x023bfe20},
+{11100000, DIF_BPF_COEFF1617,  0xfc1700fa},
+{11100000, DIF_BPF_COEFF1819,  0x05a200f7},
+{11100000, DIF_BPF_COEFF2021,  0xf927fc1c},
+{11100000, DIF_BPF_COEFF2223,  0x06f40765},
+{11100000, DIF_BPF_COEFF2425,  0xfa82f53b},
+{11100000, DIF_BPF_COEFF2627,  0x02510d27},
+{11100000, DIF_BPF_COEFF2829,  0x0243f23d},
+{11100000, DIF_BPF_COEFF3031,  0xf8810c24},
+{11100000, DIF_BPF_COEFF3233,  0x0c5cf7a7},
+{11100000, DIF_BPF_COEFF3435,  0xf03102fa},
+{11100000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 111_quant.dat*/
+
+
+/*case 11200000:*/
+/* BEGIN - DIF BPF register values from 112_quant.dat*/
+{11200000, DIF_BPF_COEFF01,    0x00010002},
+{11200000, DIF_BPF_COEFF23,    0xfffafff2},
+{11200000, DIF_BPF_COEFF45,    0x00110035},
+{11200000, DIF_BPF_COEFF67,    0xfff0ff81},
+{11200000, DIF_BPF_COEFF89,    0xffe700e7},
+{11200000, DIF_BPF_COEFF1011,  0x008ffeb6},
+{11200000, DIF_BPF_COEFF1213,  0xfe94016d},
+{11200000, DIF_BPF_COEFF1415,  0x02b0fefb},
+{11200000, DIF_BPF_COEFF1617,  0xfbd3ffd1},
+{11200000, DIF_BPF_COEFF1819,  0x05850249},
+{11200000, DIF_BPF_COEFF2021,  0xf9c1fadb},
+{11200000, DIF_BPF_COEFF2223,  0x05de0858},
+{11200000, DIF_BPF_COEFF2425,  0xfbf2f4c4},
+{11200000, DIF_BPF_COEFF2627,  0x00c70d17},
+{11200000, DIF_BPF_COEFF2829,  0x03a0f2b8},
+{11200000, DIF_BPF_COEFF3031,  0xf7870b7c},
+{11200000, DIF_BPF_COEFF3233,  0x0cdff833},
+{11200000, DIF_BPF_COEFF3435,  0xf00d02c4},
+{11200000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 112_quant.dat*/
+
+
+/*case 11300000:*/
+/* BEGIN - DIF BPF register values from 113_quant.dat*/
+{11300000, DIF_BPF_COEFF01,    0x00000003},
+{11300000, DIF_BPF_COEFF23,    0xfffdffee},
+{11300000, DIF_BPF_COEFF45,    0x00040038},
+{11300000, DIF_BPF_COEFF67,    0x0010ff88},
+{11300000, DIF_BPF_COEFF89,    0xffac00c2},
+{11300000, DIF_BPF_COEFF1011,  0x00e2ff10},
+{11300000, DIF_BPF_COEFF1213,  0xfe3900cb},
+{11300000, DIF_BPF_COEFF1415,  0x02f1ffe9},
+{11300000, DIF_BPF_COEFF1617,  0xfbd3feaa},
+{11300000, DIF_BPF_COEFF1819,  0x05210381},
+{11300000, DIF_BPF_COEFF2021,  0xfa9cf9c8},
+{11300000, DIF_BPF_COEFF2223,  0x04990912},
+{11300000, DIF_BPF_COEFF2425,  0xfd7af484},
+{11300000, DIF_BPF_COEFF2627,  0xff390cdb},
+{11300000, DIF_BPF_COEFF2829,  0x04f4f34d},
+{11300000, DIF_BPF_COEFF3031,  0xf69a0ac9},
+{11300000, DIF_BPF_COEFF3233,  0x0d5af8c1},
+{11300000, DIF_BPF_COEFF3435,  0xefec028e},
+{11300000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 113_quant.dat*/
+
+
+/*case 11400000:*/
+/* BEGIN - DIF BPF register values from 114_quant.dat*/
+{11400000, DIF_BPF_COEFF01,    0x00000003},
+{11400000, DIF_BPF_COEFF23,    0x0000ffee},
+{11400000, DIF_BPF_COEFF45,    0xfff60033},
+{11400000, DIF_BPF_COEFF67,    0x002fff9f},
+{11400000, DIF_BPF_COEFF89,    0xff7b0087},
+{11400000, DIF_BPF_COEFF1011,  0x011eff82},
+{11400000, DIF_BPF_COEFF1213,  0xfe080018},
+{11400000, DIF_BPF_COEFF1415,  0x02f900d8},
+{11400000, DIF_BPF_COEFF1617,  0xfc17fd96},
+{11400000, DIF_BPF_COEFF1819,  0x04790490},
+{11400000, DIF_BPF_COEFF2021,  0xfbadf8ed},
+{11400000, DIF_BPF_COEFF2223,  0x032f098e},
+{11400000, DIF_BPF_COEFF2425,  0xff10f47d},
+{11400000, DIF_BPF_COEFF2627,  0xfdaf0c75},
+{11400000, DIF_BPF_COEFF2829,  0x063cf3fc},
+{11400000, DIF_BPF_COEFF3031,  0xf5ba0a0b},
+{11400000, DIF_BPF_COEFF3233,  0x0dccf952},
+{11400000, DIF_BPF_COEFF3435,  0xefcd0258},
+{11400000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 114_quant.dat*/
+
+
+/*case 11500000:*/
+/* BEGIN - DIF BPF register values from 115_quant.dat*/
+{11500000, DIF_BPF_COEFF01,    0x00000003},
+{11500000, DIF_BPF_COEFF23,    0x0004fff1},
+{11500000, DIF_BPF_COEFF45,    0xffea0026},
+{11500000, DIF_BPF_COEFF67,    0x0046ffc3},
+{11500000, DIF_BPF_COEFF89,    0xff5a003c},
+{11500000, DIF_BPF_COEFF1011,  0x013b0000},
+{11500000, DIF_BPF_COEFF1213,  0xfe04ff63},
+{11500000, DIF_BPF_COEFF1415,  0x02c801b8},
+{11500000, DIF_BPF_COEFF1617,  0xfc99fca6},
+{11500000, DIF_BPF_COEFF1819,  0x0397056a},
+{11500000, DIF_BPF_COEFF2021,  0xfcecf853},
+{11500000, DIF_BPF_COEFF2223,  0x01ad09c9},
+{11500000, DIF_BPF_COEFF2425,  0x00acf4ad},
+{11500000, DIF_BPF_COEFF2627,  0xfc2e0be7},
+{11500000, DIF_BPF_COEFF2829,  0x0773f4c2},
+{11500000, DIF_BPF_COEFF3031,  0xf4e90943},
+{11500000, DIF_BPF_COEFF3233,  0x0e35f9e6},
+{11500000, DIF_BPF_COEFF3435,  0xefb10221},
+{11500000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 115_quant.dat*/
+
+
+/*case 11600000:*/
+/* BEGIN - DIF BPF register values from 116_quant.dat*/
+{11600000, DIF_BPF_COEFF01,    0x00000002},
+{11600000, DIF_BPF_COEFF23,    0x0007fff6},
+{11600000, DIF_BPF_COEFF45,    0xffe20014},
+{11600000, DIF_BPF_COEFF67,    0x0054ffee},
+{11600000, DIF_BPF_COEFF89,    0xff4effeb},
+{11600000, DIF_BPF_COEFF1011,  0x0137007e},
+{11600000, DIF_BPF_COEFF1213,  0xfe2efebb},
+{11600000, DIF_BPF_COEFF1415,  0x0260027a},
+{11600000, DIF_BPF_COEFF1617,  0xfd51fbe6},
+{11600000, DIF_BPF_COEFF1819,  0x02870605},
+{11600000, DIF_BPF_COEFF2021,  0xfe4af7fe},
+{11600000, DIF_BPF_COEFF2223,  0x001d09c1},
+{11600000, DIF_BPF_COEFF2425,  0x0243f515},
+{11600000, DIF_BPF_COEFF2627,  0xfabd0b32},
+{11600000, DIF_BPF_COEFF2829,  0x0897f59e},
+{11600000, DIF_BPF_COEFF3031,  0xf4280871},
+{11600000, DIF_BPF_COEFF3233,  0x0e95fa7c},
+{11600000, DIF_BPF_COEFF3435,  0xef9701eb},
+{11600000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 116_quant.dat*/
+
+
+/*case 11700000:*/
+/* BEGIN - DIF BPF register values from 117_quant.dat*/
+{11700000, DIF_BPF_COEFF01,    0xffff0001},
+{11700000, DIF_BPF_COEFF23,    0x0008fffd},
+{11700000, DIF_BPF_COEFF45,    0xffdeffff},
+{11700000, DIF_BPF_COEFF67,    0x0056001d},
+{11700000, DIF_BPF_COEFF89,    0xff57ff9c},
+{11700000, DIF_BPF_COEFF1011,  0x011300f0},
+{11700000, DIF_BPF_COEFF1213,  0xfe82fe2e},
+{11700000, DIF_BPF_COEFF1415,  0x01ca0310},
+{11700000, DIF_BPF_COEFF1617,  0xfe35fb62},
+{11700000, DIF_BPF_COEFF1819,  0x0155065a},
+{11700000, DIF_BPF_COEFF2021,  0xffbaf7f2},
+{11700000, DIF_BPF_COEFF2223,  0xfe8c0977},
+{11700000, DIF_BPF_COEFF2425,  0x03cef5b2},
+{11700000, DIF_BPF_COEFF2627,  0xf9610a58},
+{11700000, DIF_BPF_COEFF2829,  0x09a5f68f},
+{11700000, DIF_BPF_COEFF3031,  0xf3790797},
+{11700000, DIF_BPF_COEFF3233,  0x0eebfb14},
+{11700000, DIF_BPF_COEFF3435,  0xef8001b5},
+{11700000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 117_quant.dat*/
+
+
+/*case 11800000:*/
+/* BEGIN - DIF BPF register values from 118_quant.dat*/
+{11800000, DIF_BPF_COEFF01,    0xffff0000},
+{11800000, DIF_BPF_COEFF23,    0x00080004},
+{11800000, DIF_BPF_COEFF45,    0xffe0ffe9},
+{11800000, DIF_BPF_COEFF67,    0x004c0047},
+{11800000, DIF_BPF_COEFF89,    0xff75ff58},
+{11800000, DIF_BPF_COEFF1011,  0x00d1014a},
+{11800000, DIF_BPF_COEFF1213,  0xfef9fdc8},
+{11800000, DIF_BPF_COEFF1415,  0x0111036f},
+{11800000, DIF_BPF_COEFF1617,  0xff36fb21},
+{11800000, DIF_BPF_COEFF1819,  0x00120665},
+{11800000, DIF_BPF_COEFF2021,  0x012df82e},
+{11800000, DIF_BPF_COEFF2223,  0xfd0708ec},
+{11800000, DIF_BPF_COEFF2425,  0x0542f682},
+{11800000, DIF_BPF_COEFF2627,  0xf81f095c},
+{11800000, DIF_BPF_COEFF2829,  0x0a9af792},
+{11800000, DIF_BPF_COEFF3031,  0xf2db06b5},
+{11800000, DIF_BPF_COEFF3233,  0x0f38fbad},
+{11800000, DIF_BPF_COEFF3435,  0xef6c017e},
+{11800000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 118_quant.dat*/
+
+
+/*case 11900000:*/
+/* BEGIN - DIF BPF register values from 119_quant.dat*/
+{11900000, DIF_BPF_COEFF01,    0xffffffff},
+{11900000, DIF_BPF_COEFF23,    0x0007000b},
+{11900000, DIF_BPF_COEFF45,    0xffe7ffd8},
+{11900000, DIF_BPF_COEFF67,    0x00370068},
+{11900000, DIF_BPF_COEFF89,    0xffa4ff28},
+{11900000, DIF_BPF_COEFF1011,  0x00790184},
+{11900000, DIF_BPF_COEFF1213,  0xff87fd91},
+{11900000, DIF_BPF_COEFF1415,  0x00430392},
+{11900000, DIF_BPF_COEFF1617,  0x0044fb26},
+{11900000, DIF_BPF_COEFF1819,  0xfece0626},
+{11900000, DIF_BPF_COEFF2021,  0x0294f8b2},
+{11900000, DIF_BPF_COEFF2223,  0xfb990825},
+{11900000, DIF_BPF_COEFF2425,  0x0698f77f},
+{11900000, DIF_BPF_COEFF2627,  0xf6fe0842},
+{11900000, DIF_BPF_COEFF2829,  0x0b73f8a7},
+{11900000, DIF_BPF_COEFF3031,  0xf25105cd},
+{11900000, DIF_BPF_COEFF3233,  0x0f7bfc48},
+{11900000, DIF_BPF_COEFF3435,  0xef5a0148},
+{11900000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 119_quant.dat*/
+
+
+/*case 12000000:*/
+/* BEGIN - DIF BPF register values from 120_quant.dat*/
+{12000000, DIF_BPF_COEFF01,    0x0000fffe},
+{12000000, DIF_BPF_COEFF23,    0x00050010},
+{12000000, DIF_BPF_COEFF45,    0xfff2ffcc},
+{12000000, DIF_BPF_COEFF67,    0x001b007b},
+{12000000, DIF_BPF_COEFF89,    0xffdfff10},
+{12000000, DIF_BPF_COEFF1011,  0x00140198},
+{12000000, DIF_BPF_COEFF1213,  0x0020fd8e},
+{12000000, DIF_BPF_COEFF1415,  0xff710375},
+{12000000, DIF_BPF_COEFF1617,  0x014dfb73},
+{12000000, DIF_BPF_COEFF1819,  0xfd9a059f},
+{12000000, DIF_BPF_COEFF2021,  0x03e0f978},
+{12000000, DIF_BPF_COEFF2223,  0xfa4e0726},
+{12000000, DIF_BPF_COEFF2425,  0x07c8f8a7},
+{12000000, DIF_BPF_COEFF2627,  0xf600070c},
+{12000000, DIF_BPF_COEFF2829,  0x0c2ff9c9},
+{12000000, DIF_BPF_COEFF3031,  0xf1db04de},
+{12000000, DIF_BPF_COEFF3233,  0x0fb4fce5},
+{12000000, DIF_BPF_COEFF3435,  0xef4b0111},
+{12000000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 120_quant.dat*/
+
+
+/*case 12100000:*/
+/* BEGIN - DIF BPF register values from 121_quant.dat*/
+{12100000, DIF_BPF_COEFF01,    0x0000fffd},
+{12100000, DIF_BPF_COEFF23,    0x00010012},
+{12100000, DIF_BPF_COEFF45,    0xffffffc8},
+{12100000, DIF_BPF_COEFF67,    0xfffb007e},
+{12100000, DIF_BPF_COEFF89,    0x001dff14},
+{12100000, DIF_BPF_COEFF1011,  0xffad0184},
+{12100000, DIF_BPF_COEFF1213,  0x00b7fdbe},
+{12100000, DIF_BPF_COEFF1415,  0xfea9031b},
+{12100000, DIF_BPF_COEFF1617,  0x0241fc01},
+{12100000, DIF_BPF_COEFF1819,  0xfc8504d6},
+{12100000, DIF_BPF_COEFF2021,  0x0504fa79},
+{12100000, DIF_BPF_COEFF2223,  0xf93005f6},
+{12100000, DIF_BPF_COEFF2425,  0x08caf9f2},
+{12100000, DIF_BPF_COEFF2627,  0xf52b05c0},
+{12100000, DIF_BPF_COEFF2829,  0x0ccbfaf9},
+{12100000, DIF_BPF_COEFF3031,  0xf17903eb},
+{12100000, DIF_BPF_COEFF3233,  0x0fe3fd83},
+{12100000, DIF_BPF_COEFF3435,  0xef3f00db},
+{12100000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 121_quant.dat*/
+
+
+/*case 12200000:*/
+/* BEGIN - DIF BPF register values from 122_quant.dat*/
+{12200000, DIF_BPF_COEFF01,    0x0000fffd},
+{12200000, DIF_BPF_COEFF23,    0xfffe0011},
+{12200000, DIF_BPF_COEFF45,    0x000cffcc},
+{12200000, DIF_BPF_COEFF67,    0xffdb0071},
+{12200000, DIF_BPF_COEFF89,    0x0058ff32},
+{12200000, DIF_BPF_COEFF1011,  0xff4f014a},
+{12200000, DIF_BPF_COEFF1213,  0x013cfe1f},
+{12200000, DIF_BPF_COEFF1415,  0xfdfb028a},
+{12200000, DIF_BPF_COEFF1617,  0x0311fcc9},
+{12200000, DIF_BPF_COEFF1819,  0xfb9d03d6},
+{12200000, DIF_BPF_COEFF2021,  0x05f4fbad},
+{12200000, DIF_BPF_COEFF2223,  0xf848049d},
+{12200000, DIF_BPF_COEFF2425,  0x0999fb5b},
+{12200000, DIF_BPF_COEFF2627,  0xf4820461},
+{12200000, DIF_BPF_COEFF2829,  0x0d46fc32},
+{12200000, DIF_BPF_COEFF3031,  0xf12d02f4},
+{12200000, DIF_BPF_COEFF3233,  0x1007fe21},
+{12200000, DIF_BPF_COEFF3435,  0xef3600a4},
+{12200000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 122_quant.dat*/
+
+
+/*case 12300000:*/
+/* BEGIN - DIF BPF register values from 123_quant.dat*/
+{12300000, DIF_BPF_COEFF01,    0x0000fffe},
+{12300000, DIF_BPF_COEFF23,    0xfffa000e},
+{12300000, DIF_BPF_COEFF45,    0x0017ffd9},
+{12300000, DIF_BPF_COEFF67,    0xffc10055},
+{12300000, DIF_BPF_COEFF89,    0x0088ff68},
+{12300000, DIF_BPF_COEFF1011,  0xff0400f0},
+{12300000, DIF_BPF_COEFF1213,  0x01a6fea7},
+{12300000, DIF_BPF_COEFF1415,  0xfd7501cc},
+{12300000, DIF_BPF_COEFF1617,  0x03b0fdc0},
+{12300000, DIF_BPF_COEFF1819,  0xfaef02a8},
+{12300000, DIF_BPF_COEFF2021,  0x06a7fd07},
+{12300000, DIF_BPF_COEFF2223,  0xf79d0326},
+{12300000, DIF_BPF_COEFF2425,  0x0a31fcda},
+{12300000, DIF_BPF_COEFF2627,  0xf40702f3},
+{12300000, DIF_BPF_COEFF2829,  0x0d9ffd72},
+{12300000, DIF_BPF_COEFF3031,  0xf0f601fa},
+{12300000, DIF_BPF_COEFF3233,  0x1021fec0},
+{12300000, DIF_BPF_COEFF3435,  0xef2f006d},
+{12300000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 123_quant.dat*/
+
+
+/*case 12400000:*/
+/* BEGIN - DIF BPF register values from 124_quant.dat*/
+{12400000, DIF_BPF_COEFF01,    0x0001ffff},
+{12400000, DIF_BPF_COEFF23,    0xfff80007},
+{12400000, DIF_BPF_COEFF45,    0x001fffeb},
+{12400000, DIF_BPF_COEFF67,    0xffaf002d},
+{12400000, DIF_BPF_COEFF89,    0x00a8ffb0},
+{12400000, DIF_BPF_COEFF1011,  0xfed3007e},
+{12400000, DIF_BPF_COEFF1213,  0x01e9ff4c},
+{12400000, DIF_BPF_COEFF1415,  0xfd2000ee},
+{12400000, DIF_BPF_COEFF1617,  0x0413fed8},
+{12400000, DIF_BPF_COEFF1819,  0xfa82015c},
+{12400000, DIF_BPF_COEFF2021,  0x0715fe7d},
+{12400000, DIF_BPF_COEFF2223,  0xf7340198},
+{12400000, DIF_BPF_COEFF2425,  0x0a8dfe69},
+{12400000, DIF_BPF_COEFF2627,  0xf3bd017c},
+{12400000, DIF_BPF_COEFF2829,  0x0dd5feb8},
+{12400000, DIF_BPF_COEFF3031,  0xf0d500fd},
+{12400000, DIF_BPF_COEFF3233,  0x1031ff60},
+{12400000, DIF_BPF_COEFF3435,  0xef2b0037},
+{12400000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 124_quant.dat*/
+
+
+/*case 12500000:*/
+/* BEGIN - DIF BPF register values from 125_quant.dat*/
+{12500000, DIF_BPF_COEFF01,    0x00010000},
+{12500000, DIF_BPF_COEFF23,    0xfff70000},
+{12500000, DIF_BPF_COEFF45,    0x00220000},
+{12500000, DIF_BPF_COEFF67,    0xffa90000},
+{12500000, DIF_BPF_COEFF89,    0x00b30000},
+{12500000, DIF_BPF_COEFF1011,  0xfec20000},
+{12500000, DIF_BPF_COEFF1213,  0x02000000},
+{12500000, DIF_BPF_COEFF1415,  0xfd030000},
+{12500000, DIF_BPF_COEFF1617,  0x04350000},
+{12500000, DIF_BPF_COEFF1819,  0xfa5e0000},
+{12500000, DIF_BPF_COEFF2021,  0x073b0000},
+{12500000, DIF_BPF_COEFF2223,  0xf7110000},
+{12500000, DIF_BPF_COEFF2425,  0x0aac0000},
+{12500000, DIF_BPF_COEFF2627,  0xf3a40000},
+{12500000, DIF_BPF_COEFF2829,  0x0de70000},
+{12500000, DIF_BPF_COEFF3031,  0xf0c90000},
+{12500000, DIF_BPF_COEFF3233,  0x10360000},
+{12500000, DIF_BPF_COEFF3435,  0xef290000},
+{12500000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 125_quant.dat*/
+
+
+/*case 12600000:*/
+/* BEGIN - DIF BPF register values from 126_quant.dat*/
+{12600000, DIF_BPF_COEFF01,    0x00010001},
+{12600000, DIF_BPF_COEFF23,    0xfff8fff9},
+{12600000, DIF_BPF_COEFF45,    0x001f0015},
+{12600000, DIF_BPF_COEFF67,    0xffafffd3},
+{12600000, DIF_BPF_COEFF89,    0x00a80050},
+{12600000, DIF_BPF_COEFF1011,  0xfed3ff82},
+{12600000, DIF_BPF_COEFF1213,  0x01e900b4},
+{12600000, DIF_BPF_COEFF1415,  0xfd20ff12},
+{12600000, DIF_BPF_COEFF1617,  0x04130128},
+{12600000, DIF_BPF_COEFF1819,  0xfa82fea4},
+{12600000, DIF_BPF_COEFF2021,  0x07150183},
+{12600000, DIF_BPF_COEFF2223,  0xf734fe68},
+{12600000, DIF_BPF_COEFF2425,  0x0a8d0197},
+{12600000, DIF_BPF_COEFF2627,  0xf3bdfe84},
+{12600000, DIF_BPF_COEFF2829,  0x0dd50148},
+{12600000, DIF_BPF_COEFF3031,  0xf0d5ff03},
+{12600000, DIF_BPF_COEFF3233,  0x103100a0},
+{12600000, DIF_BPF_COEFF3435,  0xef2bffc9},
+{12600000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 126_quant.dat*/
+
+
+/*case 12700000:*/
+/* BEGIN - DIF BPF register values from 127_quant.dat*/
+{12700000, DIF_BPF_COEFF01,    0x00000002},
+{12700000, DIF_BPF_COEFF23,    0xfffafff2},
+{12700000, DIF_BPF_COEFF45,    0x00170027},
+{12700000, DIF_BPF_COEFF67,    0xffc1ffab},
+{12700000, DIF_BPF_COEFF89,    0x00880098},
+{12700000, DIF_BPF_COEFF1011,  0xff04ff10},
+{12700000, DIF_BPF_COEFF1213,  0x01a60159},
+{12700000, DIF_BPF_COEFF1415,  0xfd75fe34},
+{12700000, DIF_BPF_COEFF1617,  0x03b00240},
+{12700000, DIF_BPF_COEFF1819,  0xfaeffd58},
+{12700000, DIF_BPF_COEFF2021,  0x06a702f9},
+{12700000, DIF_BPF_COEFF2223,  0xf79dfcda},
+{12700000, DIF_BPF_COEFF2425,  0x0a310326},
+{12700000, DIF_BPF_COEFF2627,  0xf407fd0d},
+{12700000, DIF_BPF_COEFF2829,  0x0d9f028e},
+{12700000, DIF_BPF_COEFF3031,  0xf0f6fe06},
+{12700000, DIF_BPF_COEFF3233,  0x10210140},
+{12700000, DIF_BPF_COEFF3435,  0xef2fff93},
+{12700000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 127_quant.dat*/
+
+
+/*case 12800000:*/
+/* BEGIN - DIF BPF register values from 128_quant.dat*/
+{12800000, DIF_BPF_COEFF01,    0x00000003},
+{12800000, DIF_BPF_COEFF23,    0xfffeffef},
+{12800000, DIF_BPF_COEFF45,    0x000c0034},
+{12800000, DIF_BPF_COEFF67,    0xffdbff8f},
+{12800000, DIF_BPF_COEFF89,    0x005800ce},
+{12800000, DIF_BPF_COEFF1011,  0xff4ffeb6},
+{12800000, DIF_BPF_COEFF1213,  0x013c01e1},
+{12800000, DIF_BPF_COEFF1415,  0xfdfbfd76},
+{12800000, DIF_BPF_COEFF1617,  0x03110337},
+{12800000, DIF_BPF_COEFF1819,  0xfb9dfc2a},
+{12800000, DIF_BPF_COEFF2021,  0x05f40453},
+{12800000, DIF_BPF_COEFF2223,  0xf848fb63},
+{12800000, DIF_BPF_COEFF2425,  0x099904a5},
+{12800000, DIF_BPF_COEFF2627,  0xf482fb9f},
+{12800000, DIF_BPF_COEFF2829,  0x0d4603ce},
+{12800000, DIF_BPF_COEFF3031,  0xf12dfd0c},
+{12800000, DIF_BPF_COEFF3233,  0x100701df},
+{12800000, DIF_BPF_COEFF3435,  0xef36ff5c},
+{12800000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 128_quant.dat*/
+
+
+/*case 12900000:*/
+/* BEGIN - DIF BPF register values from 129_quant.dat*/
+{12900000, DIF_BPF_COEFF01,    0x00000003},
+{12900000, DIF_BPF_COEFF23,    0x0001ffee},
+{12900000, DIF_BPF_COEFF45,    0xffff0038},
+{12900000, DIF_BPF_COEFF67,    0xfffbff82},
+{12900000, DIF_BPF_COEFF89,    0x001d00ec},
+{12900000, DIF_BPF_COEFF1011,  0xffadfe7c},
+{12900000, DIF_BPF_COEFF1213,  0x00b70242},
+{12900000, DIF_BPF_COEFF1415,  0xfea9fce5},
+{12900000, DIF_BPF_COEFF1617,  0x024103ff},
+{12900000, DIF_BPF_COEFF1819,  0xfc85fb2a},
+{12900000, DIF_BPF_COEFF2021,  0x05040587},
+{12900000, DIF_BPF_COEFF2223,  0xf930fa0a},
+{12900000, DIF_BPF_COEFF2425,  0x08ca060e},
+{12900000, DIF_BPF_COEFF2627,  0xf52bfa40},
+{12900000, DIF_BPF_COEFF2829,  0x0ccb0507},
+{12900000, DIF_BPF_COEFF3031,  0xf179fc15},
+{12900000, DIF_BPF_COEFF3233,  0x0fe3027d},
+{12900000, DIF_BPF_COEFF3435,  0xef3fff25},
+{12900000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 129_quant.dat*/
+
+
+/*case 113000000:*/
+/* BEGIN - DIF BPF register values from 130_quant.dat*/
+{13000000, DIF_BPF_COEFF01,    0x00000002},
+{13000000, DIF_BPF_COEFF23,    0x0005fff0},
+{13000000, DIF_BPF_COEFF45,    0xfff20034},
+{13000000, DIF_BPF_COEFF67,    0x001bff85},
+{13000000, DIF_BPF_COEFF89,    0xffdf00f0},
+{13000000, DIF_BPF_COEFF1011,  0x0014fe68},
+{13000000, DIF_BPF_COEFF1213,  0x00200272},
+{13000000, DIF_BPF_COEFF1415,  0xff71fc8b},
+{13000000, DIF_BPF_COEFF1617,  0x014d048d},
+{13000000, DIF_BPF_COEFF1819,  0xfd9afa61},
+{13000000, DIF_BPF_COEFF2021,  0x03e00688},
+{13000000, DIF_BPF_COEFF2223,  0xfa4ef8da},
+{13000000, DIF_BPF_COEFF2425,  0x07c80759},
+{13000000, DIF_BPF_COEFF2627,  0xf600f8f4},
+{13000000, DIF_BPF_COEFF2829,  0x0c2f0637},
+{13000000, DIF_BPF_COEFF3031,  0xf1dbfb22},
+{13000000, DIF_BPF_COEFF3233,  0x0fb4031b},
+{13000000, DIF_BPF_COEFF3435,  0xef4bfeef},
+{13000000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 130_quant.dat*/
+
+
+/*case 13100000:*/
+/* BEGIN - DIF BPF register values from 131_quant.dat*/
+{13100000, DIF_BPF_COEFF01,    0xffff0001},
+{13100000, DIF_BPF_COEFF23,    0x0007fff5},
+{13100000, DIF_BPF_COEFF45,    0xffe70028},
+{13100000, DIF_BPF_COEFF67,    0x0037ff98},
+{13100000, DIF_BPF_COEFF89,    0xffa400d8},
+{13100000, DIF_BPF_COEFF1011,  0x0079fe7c},
+{13100000, DIF_BPF_COEFF1213,  0xff87026f},
+{13100000, DIF_BPF_COEFF1415,  0x0043fc6e},
+{13100000, DIF_BPF_COEFF1617,  0x004404da},
+{13100000, DIF_BPF_COEFF1819,  0xfecef9da},
+{13100000, DIF_BPF_COEFF2021,  0x0294074e},
+{13100000, DIF_BPF_COEFF2223,  0xfb99f7db},
+{13100000, DIF_BPF_COEFF2425,  0x06980881},
+{13100000, DIF_BPF_COEFF2627,  0xf6fef7be},
+{13100000, DIF_BPF_COEFF2829,  0x0b730759},
+{13100000, DIF_BPF_COEFF3031,  0xf251fa33},
+{13100000, DIF_BPF_COEFF3233,  0x0f7b03b8},
+{13100000, DIF_BPF_COEFF3435,  0xef5afeb8},
+{13100000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 131_quant.dat*/
+
+
+/*case 13200000:*/
+/* BEGIN - DIF BPF register values from 132_quant.dat*/
+{13200000, DIF_BPF_COEFF01,    0xffff0000},
+{13200000, DIF_BPF_COEFF23,    0x0008fffc},
+{13200000, DIF_BPF_COEFF45,    0xffe00017},
+{13200000, DIF_BPF_COEFF67,    0x004cffb9},
+{13200000, DIF_BPF_COEFF89,    0xff7500a8},
+{13200000, DIF_BPF_COEFF1011,  0x00d1feb6},
+{13200000, DIF_BPF_COEFF1213,  0xfef90238},
+{13200000, DIF_BPF_COEFF1415,  0x0111fc91},
+{13200000, DIF_BPF_COEFF1617,  0xff3604df},
+{13200000, DIF_BPF_COEFF1819,  0x0012f99b},
+{13200000, DIF_BPF_COEFF2021,  0x012d07d2},
+{13200000, DIF_BPF_COEFF2223,  0xfd07f714},
+{13200000, DIF_BPF_COEFF2425,  0x0542097e},
+{13200000, DIF_BPF_COEFF2627,  0xf81ff6a4},
+{13200000, DIF_BPF_COEFF2829,  0x0a9a086e},
+{13200000, DIF_BPF_COEFF3031,  0xf2dbf94b},
+{13200000, DIF_BPF_COEFF3233,  0x0f380453},
+{13200000, DIF_BPF_COEFF3435,  0xef6cfe82},
+{13200000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 132_quant.dat*/
+
+
+/*case 13300000:*/
+/* BEGIN - DIF BPF register values from 133_quant.dat*/
+{13300000, DIF_BPF_COEFF01,    0xffffffff},
+{13300000, DIF_BPF_COEFF23,    0x00080003},
+{13300000, DIF_BPF_COEFF45,    0xffde0001},
+{13300000, DIF_BPF_COEFF67,    0x0056ffe3},
+{13300000, DIF_BPF_COEFF89,    0xff570064},
+{13300000, DIF_BPF_COEFF1011,  0x0113ff10},
+{13300000, DIF_BPF_COEFF1213,  0xfe8201d2},
+{13300000, DIF_BPF_COEFF1415,  0x01cafcf0},
+{13300000, DIF_BPF_COEFF1617,  0xfe35049e},
+{13300000, DIF_BPF_COEFF1819,  0x0155f9a6},
+{13300000, DIF_BPF_COEFF2021,  0xffba080e},
+{13300000, DIF_BPF_COEFF2223,  0xfe8cf689},
+{13300000, DIF_BPF_COEFF2425,  0x03ce0a4e},
+{13300000, DIF_BPF_COEFF2627,  0xf961f5a8},
+{13300000, DIF_BPF_COEFF2829,  0x09a50971},
+{13300000, DIF_BPF_COEFF3031,  0xf379f869},
+{13300000, DIF_BPF_COEFF3233,  0x0eeb04ec},
+{13300000, DIF_BPF_COEFF3435,  0xef80fe4b},
+{13300000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 133_quant.dat*/
+
+
+/*case 13400000:*/
+/* BEGIN - DIF BPF register values from 134_quant.dat*/
+{13400000, DIF_BPF_COEFF01,    0x0000fffe},
+{13400000, DIF_BPF_COEFF23,    0x0007000a},
+{13400000, DIF_BPF_COEFF45,    0xffe2ffec},
+{13400000, DIF_BPF_COEFF67,    0x00540012},
+{13400000, DIF_BPF_COEFF89,    0xff4e0015},
+{13400000, DIF_BPF_COEFF1011,  0x0137ff82},
+{13400000, DIF_BPF_COEFF1213,  0xfe2e0145},
+{13400000, DIF_BPF_COEFF1415,  0x0260fd86},
+{13400000, DIF_BPF_COEFF1617,  0xfd51041a},
+{13400000, DIF_BPF_COEFF1819,  0x0287f9fb},
+{13400000, DIF_BPF_COEFF2021,  0xfe4a0802},
+{13400000, DIF_BPF_COEFF2223,  0x001df63f},
+{13400000, DIF_BPF_COEFF2425,  0x02430aeb},
+{13400000, DIF_BPF_COEFF2627,  0xfabdf4ce},
+{13400000, DIF_BPF_COEFF2829,  0x08970a62},
+{13400000, DIF_BPF_COEFF3031,  0xf428f78f},
+{13400000, DIF_BPF_COEFF3233,  0x0e950584},
+{13400000, DIF_BPF_COEFF3435,  0xef97fe15},
+{13400000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 134_quant.dat*/
+
+
+/*case 13500000:*/
+/* BEGIN - DIF BPF register values from 135_quant.dat*/
+{13500000, DIF_BPF_COEFF01,    0x0000fffd},
+{13500000, DIF_BPF_COEFF23,    0x0004000f},
+{13500000, DIF_BPF_COEFF45,    0xffeaffda},
+{13500000, DIF_BPF_COEFF67,    0x0046003d},
+{13500000, DIF_BPF_COEFF89,    0xff5affc4},
+{13500000, DIF_BPF_COEFF1011,  0x013b0000},
+{13500000, DIF_BPF_COEFF1213,  0xfe04009d},
+{13500000, DIF_BPF_COEFF1415,  0x02c8fe48},
+{13500000, DIF_BPF_COEFF1617,  0xfc99035a},
+{13500000, DIF_BPF_COEFF1819,  0x0397fa96},
+{13500000, DIF_BPF_COEFF2021,  0xfcec07ad},
+{13500000, DIF_BPF_COEFF2223,  0x01adf637},
+{13500000, DIF_BPF_COEFF2425,  0x00ac0b53},
+{13500000, DIF_BPF_COEFF2627,  0xfc2ef419},
+{13500000, DIF_BPF_COEFF2829,  0x07730b3e},
+{13500000, DIF_BPF_COEFF3031,  0xf4e9f6bd},
+{13500000, DIF_BPF_COEFF3233,  0x0e35061a},
+{13500000, DIF_BPF_COEFF3435,  0xefb1fddf},
+{13500000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 135_quant.dat*/
+
+
+/*case 13600000:*/
+/* BEGIN - DIF BPF register values from 136_quant.dat*/
+{13600000, DIF_BPF_COEFF01,    0x0000fffd},
+{13600000, DIF_BPF_COEFF23,    0x00000012},
+{13600000, DIF_BPF_COEFF45,    0xfff6ffcd},
+{13600000, DIF_BPF_COEFF67,    0x002f0061},
+{13600000, DIF_BPF_COEFF89,    0xff7bff79},
+{13600000, DIF_BPF_COEFF1011,  0x011e007e},
+{13600000, DIF_BPF_COEFF1213,  0xfe08ffe8},
+{13600000, DIF_BPF_COEFF1415,  0x02f9ff28},
+{13600000, DIF_BPF_COEFF1617,  0xfc17026a},
+{13600000, DIF_BPF_COEFF1819,  0x0479fb70},
+{13600000, DIF_BPF_COEFF2021,  0xfbad0713},
+{13600000, DIF_BPF_COEFF2223,  0x032ff672},
+{13600000, DIF_BPF_COEFF2425,  0xff100b83},
+{13600000, DIF_BPF_COEFF2627,  0xfdaff38b},
+{13600000, DIF_BPF_COEFF2829,  0x063c0c04},
+{13600000, DIF_BPF_COEFF3031,  0xf5baf5f5},
+{13600000, DIF_BPF_COEFF3233,  0x0dcc06ae},
+{13600000, DIF_BPF_COEFF3435,  0xefcdfda8},
+{13600000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 136_quant.dat*/
+
+
+/*case 13700000:*/
+/* BEGIN - DIF BPF register values from 137_quant.dat*/
+{13700000, DIF_BPF_COEFF01,    0x0000fffd},
+{13700000, DIF_BPF_COEFF23,    0xfffd0012},
+{13700000, DIF_BPF_COEFF45,    0x0004ffc8},
+{13700000, DIF_BPF_COEFF67,    0x00100078},
+{13700000, DIF_BPF_COEFF89,    0xffacff3e},
+{13700000, DIF_BPF_COEFF1011,  0x00e200f0},
+{13700000, DIF_BPF_COEFF1213,  0xfe39ff35},
+{13700000, DIF_BPF_COEFF1415,  0x02f10017},
+{13700000, DIF_BPF_COEFF1617,  0xfbd30156},
+{13700000, DIF_BPF_COEFF1819,  0x0521fc7f},
+{13700000, DIF_BPF_COEFF2021,  0xfa9c0638},
+{13700000, DIF_BPF_COEFF2223,  0x0499f6ee},
+{13700000, DIF_BPF_COEFF2425,  0xfd7a0b7c},
+{13700000, DIF_BPF_COEFF2627,  0xff39f325},
+{13700000, DIF_BPF_COEFF2829,  0x04f40cb3},
+{13700000, DIF_BPF_COEFF3031,  0xf69af537},
+{13700000, DIF_BPF_COEFF3233,  0x0d5a073f},
+{13700000, DIF_BPF_COEFF3435,  0xefecfd72},
+{13700000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 137_quant.dat*/
+
+
+/*case 13800000:*/
+/* BEGIN - DIF BPF register values from 138_quant.dat*/
+{13800000, DIF_BPF_COEFF01,    0x0001fffe},
+{13800000, DIF_BPF_COEFF23,    0xfffa000e},
+{13800000, DIF_BPF_COEFF45,    0x0011ffcb},
+{13800000, DIF_BPF_COEFF67,    0xfff0007f},
+{13800000, DIF_BPF_COEFF89,    0xffe7ff19},
+{13800000, DIF_BPF_COEFF1011,  0x008f014a},
+{13800000, DIF_BPF_COEFF1213,  0xfe94fe93},
+{13800000, DIF_BPF_COEFF1415,  0x02b00105},
+{13800000, DIF_BPF_COEFF1617,  0xfbd3002f},
+{13800000, DIF_BPF_COEFF1819,  0x0585fdb7},
+{13800000, DIF_BPF_COEFF2021,  0xf9c10525},
+{13800000, DIF_BPF_COEFF2223,  0x05def7a8},
+{13800000, DIF_BPF_COEFF2425,  0xfbf20b3c},
+{13800000, DIF_BPF_COEFF2627,  0x00c7f2e9},
+{13800000, DIF_BPF_COEFF2829,  0x03a00d48},
+{13800000, DIF_BPF_COEFF3031,  0xf787f484},
+{13800000, DIF_BPF_COEFF3233,  0x0cdf07cd},
+{13800000, DIF_BPF_COEFF3435,  0xf00dfd3c},
+{13800000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 138_quant.dat*/
+
+
+/*case 13900000:*/
+/* BEGIN - DIF BPF register values from 139_quant.dat*/
+{13900000, DIF_BPF_COEFF01,    0x00010000},
+{13900000, DIF_BPF_COEFF23,    0xfff80008},
+{13900000, DIF_BPF_COEFF45,    0x001bffd7},
+{13900000, DIF_BPF_COEFF67,    0xffd10076},
+{13900000, DIF_BPF_COEFF89,    0x0026ff0e},
+{13900000, DIF_BPF_COEFF1011,  0x002c0184},
+{13900000, DIF_BPF_COEFF1213,  0xff0ffe10},
+{13900000, DIF_BPF_COEFF1415,  0x023b01e0},
+{13900000, DIF_BPF_COEFF1617,  0xfc17ff06},
+{13900000, DIF_BPF_COEFF1819,  0x05a2ff09},
+{13900000, DIF_BPF_COEFF2021,  0xf92703e4},
+{13900000, DIF_BPF_COEFF2223,  0x06f4f89b},
+{13900000, DIF_BPF_COEFF2425,  0xfa820ac5},
+{13900000, DIF_BPF_COEFF2627,  0x0251f2d9},
+{13900000, DIF_BPF_COEFF2829,  0x02430dc3},
+{13900000, DIF_BPF_COEFF3031,  0xf881f3dc},
+{13900000, DIF_BPF_COEFF3233,  0x0c5c0859},
+{13900000, DIF_BPF_COEFF3435,  0xf031fd06},
+{13900000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 139_quant.dat*/
+
+
+/*case 14000000:*/
+/* BEGIN - DIF BPF register values from 140_quant.dat*/
+{14000000, DIF_BPF_COEFF01,    0x00010001},
+{14000000, DIF_BPF_COEFF23,    0xfff80001},
+{14000000, DIF_BPF_COEFF45,    0x0021ffe8},
+{14000000, DIF_BPF_COEFF67,    0xffba005d},
+{14000000, DIF_BPF_COEFF89,    0x0060ff1f},
+{14000000, DIF_BPF_COEFF1011,  0xffc40198},
+{14000000, DIF_BPF_COEFF1213,  0xffa0fdb5},
+{14000000, DIF_BPF_COEFF1415,  0x019a029a},
+{14000000, DIF_BPF_COEFF1617,  0xfc99fdea},
+{14000000, DIF_BPF_COEFF1819,  0x05750067},
+{14000000, DIF_BPF_COEFF2021,  0xf8d4027f},
+{14000000, DIF_BPF_COEFF2223,  0x07d4f9c0},
+{14000000, DIF_BPF_COEFF2425,  0xf9320a1a},
+{14000000, DIF_BPF_COEFF2627,  0x03d2f2f3},
+{14000000, DIF_BPF_COEFF2829,  0x00df0e22},
+{14000000, DIF_BPF_COEFF3031,  0xf986f341},
+{14000000, DIF_BPF_COEFF3233,  0x0bd108e2},
+{14000000, DIF_BPF_COEFF3435,  0xf058fcd1},
+{14000000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 140_quant.dat*/
+
+
+/*case 14100000:*/
+/* BEGIN - DIF BPF register values from 141_quant.dat*/
+{14100000, DIF_BPF_COEFF01,    0x00000002},
+{14100000, DIF_BPF_COEFF23,    0xfff9fffa},
+{14100000, DIF_BPF_COEFF45,    0x0021fffd},
+{14100000, DIF_BPF_COEFF67,    0xffac0038},
+{14100000, DIF_BPF_COEFF89,    0x008eff4a},
+{14100000, DIF_BPF_COEFF1011,  0xff630184},
+{14100000, DIF_BPF_COEFF1213,  0x003afd8b},
+{14100000, DIF_BPF_COEFF1415,  0x00da0326},
+{14100000, DIF_BPF_COEFF1617,  0xfd51fced},
+{14100000, DIF_BPF_COEFF1819,  0x050101c0},
+{14100000, DIF_BPF_COEFF2021,  0xf8cb0103},
+{14100000, DIF_BPF_COEFF2223,  0x0876fb10},
+{14100000, DIF_BPF_COEFF2425,  0xf80a093e},
+{14100000, DIF_BPF_COEFF2627,  0x0543f338},
+{14100000, DIF_BPF_COEFF2829,  0xff7a0e66},
+{14100000, DIF_BPF_COEFF3031,  0xfa94f2b2},
+{14100000, DIF_BPF_COEFF3233,  0x0b3f0967},
+{14100000, DIF_BPF_COEFF3435,  0xf081fc9b},
+{14100000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 141_quant.dat*/
+
+
+/*case 14200000:*/
+/* BEGIN - DIF BPF register values from 142_quant.dat*/
+{14200000, DIF_BPF_COEFF01,    0x00000003},
+{14200000, DIF_BPF_COEFF23,    0xfffbfff3},
+{14200000, DIF_BPF_COEFF45,    0x001d0013},
+{14200000, DIF_BPF_COEFF67,    0xffaa000b},
+{14200000, DIF_BPF_COEFF89,    0x00aaff89},
+{14200000, DIF_BPF_COEFF1011,  0xff13014a},
+{14200000, DIF_BPF_COEFF1213,  0x00cefd95},
+{14200000, DIF_BPF_COEFF1415,  0x000a037b},
+{14200000, DIF_BPF_COEFF1617,  0xfe35fc1d},
+{14200000, DIF_BPF_COEFF1819,  0x044c0305},
+{14200000, DIF_BPF_COEFF2021,  0xf90cff7e},
+{14200000, DIF_BPF_COEFF2223,  0x08d5fc81},
+{14200000, DIF_BPF_COEFF2425,  0xf7100834},
+{14200000, DIF_BPF_COEFF2627,  0x069ff3a7},
+{14200000, DIF_BPF_COEFF2829,  0xfe160e8d},
+{14200000, DIF_BPF_COEFF3031,  0xfbaaf231},
+{14200000, DIF_BPF_COEFF3233,  0x0aa509e9},
+{14200000, DIF_BPF_COEFF3435,  0xf0adfc65},
+{14200000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 142_quant.dat*/
+
+
+/*case 14300000:*/
+/* BEGIN - DIF BPF register values from 143_quant.dat*/
+{14300000, DIF_BPF_COEFF01,    0x00000003},
+{14300000, DIF_BPF_COEFF23,    0xffffffef},
+{14300000, DIF_BPF_COEFF45,    0x00140025},
+{14300000, DIF_BPF_COEFF67,    0xffb4ffdd},
+{14300000, DIF_BPF_COEFF89,    0x00b2ffd6},
+{14300000, DIF_BPF_COEFF1011,  0xfedb00f0},
+{14300000, DIF_BPF_COEFF1213,  0x0150fdd3},
+{14300000, DIF_BPF_COEFF1415,  0xff380391},
+{14300000, DIF_BPF_COEFF1617,  0xff36fb85},
+{14300000, DIF_BPF_COEFF1819,  0x035e0426},
+{14300000, DIF_BPF_COEFF2021,  0xf994fdfe},
+{14300000, DIF_BPF_COEFF2223,  0x08eefe0b},
+{14300000, DIF_BPF_COEFF2425,  0xf6490702},
+{14300000, DIF_BPF_COEFF2627,  0x07e1f43e},
+{14300000, DIF_BPF_COEFF2829,  0xfcb60e97},
+{14300000, DIF_BPF_COEFF3031,  0xfcc6f1be},
+{14300000, DIF_BPF_COEFF3233,  0x0a040a67},
+{14300000, DIF_BPF_COEFF3435,  0xf0dbfc30},
+{14300000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 143_quant.dat*/
+
+
+/*case 14400000:*/
+/* BEGIN - DIF BPF register values from 144_quant.dat*/
+{14400000, DIF_BPF_COEFF01,    0x00000003},
+{14400000, DIF_BPF_COEFF23,    0x0002ffee},
+{14400000, DIF_BPF_COEFF45,    0x00070033},
+{14400000, DIF_BPF_COEFF67,    0xffc9ffb4},
+{14400000, DIF_BPF_COEFF89,    0x00a40027},
+{14400000, DIF_BPF_COEFF1011,  0xfec3007e},
+{14400000, DIF_BPF_COEFF1213,  0x01b4fe3f},
+{14400000, DIF_BPF_COEFF1415,  0xfe760369},
+{14400000, DIF_BPF_COEFF1617,  0x0044fb2e},
+{14400000, DIF_BPF_COEFF1819,  0x02450518},
+{14400000, DIF_BPF_COEFF2021,  0xfa5ffc90},
+{14400000, DIF_BPF_COEFF2223,  0x08c1ffa1},
+{14400000, DIF_BPF_COEFF2425,  0xf5bc05ae},
+{14400000, DIF_BPF_COEFF2627,  0x0902f4fc},
+{14400000, DIF_BPF_COEFF2829,  0xfb600e85},
+{14400000, DIF_BPF_COEFF3031,  0xfde7f15a},
+{14400000, DIF_BPF_COEFF3233,  0x095d0ae2},
+{14400000, DIF_BPF_COEFF3435,  0xf10cfbfb},
+{14400000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 144_quant.dat*/
+
+
+/*case 14500000:*/
+/* BEGIN - DIF BPF register values from 145_quant.dat*/
+{14500000, DIF_BPF_COEFF01,    0xffff0002},
+{14500000, DIF_BPF_COEFF23,    0x0005ffef},
+{14500000, DIF_BPF_COEFF45,    0xfffa0038},
+{14500000, DIF_BPF_COEFF67,    0xffe5ff95},
+{14500000, DIF_BPF_COEFF89,    0x00820074},
+{14500000, DIF_BPF_COEFF1011,  0xfecc0000},
+{14500000, DIF_BPF_COEFF1213,  0x01f0fed0},
+{14500000, DIF_BPF_COEFF1415,  0xfdd20304},
+{14500000, DIF_BPF_COEFF1617,  0x014dfb1d},
+{14500000, DIF_BPF_COEFF1819,  0x010e05ce},
+{14500000, DIF_BPF_COEFF2021,  0xfb64fb41},
+{14500000, DIF_BPF_COEFF2223,  0x084e013b},
+{14500000, DIF_BPF_COEFF2425,  0xf569043e},
+{14500000, DIF_BPF_COEFF2627,  0x0a00f5dd},
+{14500000, DIF_BPF_COEFF2829,  0xfa150e55},
+{14500000, DIF_BPF_COEFF3031,  0xff0bf104},
+{14500000, DIF_BPF_COEFF3233,  0x08b00b59},
+{14500000, DIF_BPF_COEFF3435,  0xf13ffbc6},
+{14500000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 145_quant.dat*/
+
+
+/*case 14600000:*/
+/* BEGIN - DIF BPF register values from 146_quant.dat*/
+{14600000, DIF_BPF_COEFF01,    0xffff0001},
+{14600000, DIF_BPF_COEFF23,    0x0008fff4},
+{14600000, DIF_BPF_COEFF45,    0xffed0035},
+{14600000, DIF_BPF_COEFF67,    0x0005ff83},
+{14600000, DIF_BPF_COEFF89,    0x005000b4},
+{14600000, DIF_BPF_COEFF1011,  0xfef6ff82},
+{14600000, DIF_BPF_COEFF1213,  0x01ffff7a},
+{14600000, DIF_BPF_COEFF1415,  0xfd580269},
+{14600000, DIF_BPF_COEFF1617,  0x0241fb53},
+{14600000, DIF_BPF_COEFF1819,  0xffca0640},
+{14600000, DIF_BPF_COEFF2021,  0xfc99fa1e},
+{14600000, DIF_BPF_COEFF2223,  0x079a02cb},
+{14600000, DIF_BPF_COEFF2425,  0xf55502ba},
+{14600000, DIF_BPF_COEFF2627,  0x0ad5f6e0},
+{14600000, DIF_BPF_COEFF2829,  0xf8d90e0a},
+{14600000, DIF_BPF_COEFF3031,  0x0031f0bd},
+{14600000, DIF_BPF_COEFF3233,  0x07fd0bcb},
+{14600000, DIF_BPF_COEFF3435,  0xf174fb91},
+{14600000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 146_quant.dat*/
+
+
+/*case 14700000:*/
+/* BEGIN - DIF BPF register values from 147_quant.dat*/
+{14700000, DIF_BPF_COEFF01,    0xffffffff},
+{14700000, DIF_BPF_COEFF23,    0x0009fffb},
+{14700000, DIF_BPF_COEFF45,    0xffe4002a},
+{14700000, DIF_BPF_COEFF67,    0x0025ff82},
+{14700000, DIF_BPF_COEFF89,    0x001400e0},
+{14700000, DIF_BPF_COEFF1011,  0xff3cff10},
+{14700000, DIF_BPF_COEFF1213,  0x01e10030},
+{14700000, DIF_BPF_COEFF1415,  0xfd1201a4},
+{14700000, DIF_BPF_COEFF1617,  0x0311fbcd},
+{14700000, DIF_BPF_COEFF1819,  0xfe88066a},
+{14700000, DIF_BPF_COEFF2021,  0xfdf1f92f},
+{14700000, DIF_BPF_COEFF2223,  0x06aa0449},
+{14700000, DIF_BPF_COEFF2425,  0xf57e0128},
+{14700000, DIF_BPF_COEFF2627,  0x0b7ef801},
+{14700000, DIF_BPF_COEFF2829,  0xf7b00da2},
+{14700000, DIF_BPF_COEFF3031,  0x0156f086},
+{14700000, DIF_BPF_COEFF3233,  0x07450c39},
+{14700000, DIF_BPF_COEFF3435,  0xf1acfb5c},
+{14700000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 147_quant.dat*/
+
+
+/*case 14800000:*/
+/* BEGIN - DIF BPF register values from 148_quant.dat*/
+{14800000, DIF_BPF_COEFF01,    0x0000fffe},
+{14800000, DIF_BPF_COEFF23,    0x00080002},
+{14800000, DIF_BPF_COEFF45,    0xffdf0019},
+{14800000, DIF_BPF_COEFF67,    0x003fff92},
+{14800000, DIF_BPF_COEFF89,    0xffd600f1},
+{14800000, DIF_BPF_COEFF1011,  0xff96feb6},
+{14800000, DIF_BPF_COEFF1213,  0x019700e1},
+{14800000, DIF_BPF_COEFF1415,  0xfd0500c2},
+{14800000, DIF_BPF_COEFF1617,  0x03b0fc84},
+{14800000, DIF_BPF_COEFF1819,  0xfd590649},
+{14800000, DIF_BPF_COEFF2021,  0xff5df87f},
+{14800000, DIF_BPF_COEFF2223,  0x058505aa},
+{14800000, DIF_BPF_COEFF2425,  0xf5e4ff91},
+{14800000, DIF_BPF_COEFF2627,  0x0bf9f93c},
+{14800000, DIF_BPF_COEFF2829,  0xf69d0d20},
+{14800000, DIF_BPF_COEFF3031,  0x0279f05e},
+{14800000, DIF_BPF_COEFF3233,  0x06880ca3},
+{14800000, DIF_BPF_COEFF3435,  0xf1e6fb28},
+{14800000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 148_quant.dat*/
+
+
+/*case 14900000:*/
+/* BEGIN - DIF BPF register values from 149_quant.dat*/
+{14900000, DIF_BPF_COEFF01,    0x0000fffd},
+{14900000, DIF_BPF_COEFF23,    0x00060009},
+{14900000, DIF_BPF_COEFF45,    0xffdf0004},
+{14900000, DIF_BPF_COEFF67,    0x0051ffb0},
+{14900000, DIF_BPF_COEFF89,    0xff9d00e8},
+{14900000, DIF_BPF_COEFF1011,  0xfffcfe7c},
+{14900000, DIF_BPF_COEFF1213,  0x01280180},
+{14900000, DIF_BPF_COEFF1415,  0xfd32ffd2},
+{14900000, DIF_BPF_COEFF1617,  0x0413fd6e},
+{14900000, DIF_BPF_COEFF1819,  0xfc4d05df},
+{14900000, DIF_BPF_COEFF2021,  0x00d1f812},
+{14900000, DIF_BPF_COEFF2223,  0x043506e4},
+{14900000, DIF_BPF_COEFF2425,  0xf685fdfb},
+{14900000, DIF_BPF_COEFF2627,  0x0c43fa8d},
+{14900000, DIF_BPF_COEFF2829,  0xf5a10c83},
+{14900000, DIF_BPF_COEFF3031,  0x0399f046},
+{14900000, DIF_BPF_COEFF3233,  0x05c70d08},
+{14900000, DIF_BPF_COEFF3435,  0xf222faf3},
+{14900000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 149_quant.dat*/
+
+
+/*case 15000000:*/
+/* BEGIN - DIF BPF register values from 150_quant.dat*/
+{15000000, DIF_BPF_COEFF01,    0x0000fffd},
+{15000000, DIF_BPF_COEFF23,    0x0003000f},
+{15000000, DIF_BPF_COEFF45,    0xffe5ffef},
+{15000000, DIF_BPF_COEFF67,    0x0057ffd9},
+{15000000, DIF_BPF_COEFF89,    0xff7000c4},
+{15000000, DIF_BPF_COEFF1011,  0x0062fe68},
+{15000000, DIF_BPF_COEFF1213,  0x009e01ff},
+{15000000, DIF_BPF_COEFF1415,  0xfd95fee6},
+{15000000, DIF_BPF_COEFF1617,  0x0435fe7d},
+{15000000, DIF_BPF_COEFF1819,  0xfb710530},
+{15000000, DIF_BPF_COEFF2021,  0x023cf7ee},
+{15000000, DIF_BPF_COEFF2223,  0x02c307ef},
+{15000000, DIF_BPF_COEFF2425,  0xf75efc70},
+{15000000, DIF_BPF_COEFF2627,  0x0c5cfbef},
+{15000000, DIF_BPF_COEFF2829,  0xf4c10bce},
+{15000000, DIF_BPF_COEFF3031,  0x04b3f03f},
+{15000000, DIF_BPF_COEFF3233,  0x05030d69},
+{15000000, DIF_BPF_COEFF3435,  0xf261fabf},
+{15000000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 150_quant.dat*/
+
+
+/*case 15100000:*/
+/* BEGIN - DIF BPF register values from 151_quant.dat*/
+{15100000, DIF_BPF_COEFF01,    0x0000fffd},
+{15100000, DIF_BPF_COEFF23,    0xffff0012},
+{15100000, DIF_BPF_COEFF45,    0xffefffdc},
+{15100000, DIF_BPF_COEFF67,    0x00510006},
+{15100000, DIF_BPF_COEFF89,    0xff540089},
+{15100000, DIF_BPF_COEFF1011,  0x00befe7c},
+{15100000, DIF_BPF_COEFF1213,  0x00060253},
+{15100000, DIF_BPF_COEFF1415,  0xfe27fe0d},
+{15100000, DIF_BPF_COEFF1617,  0x0413ffa2},
+{15100000, DIF_BPF_COEFF1819,  0xfad10446},
+{15100000, DIF_BPF_COEFF2021,  0x0390f812},
+{15100000, DIF_BPF_COEFF2223,  0x013b08c3},
+{15100000, DIF_BPF_COEFF2425,  0xf868faf6},
+{15100000, DIF_BPF_COEFF2627,  0x0c43fd5f},
+{15100000, DIF_BPF_COEFF2829,  0xf3fd0b02},
+{15100000, DIF_BPF_COEFF3031,  0x05c7f046},
+{15100000, DIF_BPF_COEFF3233,  0x043b0dc4},
+{15100000, DIF_BPF_COEFF3435,  0xf2a1fa8b},
+{15100000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 151_quant.dat*/
+
+
+/*case 15200000:*/
+/* BEGIN - DIF BPF register values from 152_quant.dat*/
+{15200000, DIF_BPF_COEFF01,    0x0001fffe},
+{15200000, DIF_BPF_COEFF23,    0xfffc0012},
+{15200000, DIF_BPF_COEFF45,    0xfffbffce},
+{15200000, DIF_BPF_COEFF67,    0x003f0033},
+{15200000, DIF_BPF_COEFF89,    0xff4e003f},
+{15200000, DIF_BPF_COEFF1011,  0x0106feb6},
+{15200000, DIF_BPF_COEFF1213,  0xff6e0276},
+{15200000, DIF_BPF_COEFF1415,  0xfeddfd56},
+{15200000, DIF_BPF_COEFF1617,  0x03b000cc},
+{15200000, DIF_BPF_COEFF1819,  0xfa740329},
+{15200000, DIF_BPF_COEFF2021,  0x04bff87f},
+{15200000, DIF_BPF_COEFF2223,  0xffaa095d},
+{15200000, DIF_BPF_COEFF2425,  0xf99ef995},
+{15200000, DIF_BPF_COEFF2627,  0x0bf9fed8},
+{15200000, DIF_BPF_COEFF2829,  0xf3590a1f},
+{15200000, DIF_BPF_COEFF3031,  0x06d2f05e},
+{15200000, DIF_BPF_COEFF3233,  0x03700e1b},
+{15200000, DIF_BPF_COEFF3435,  0xf2e4fa58},
+{15200000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 152_quant.dat*/
+
+
+/*case 115300000:*/
+/* BEGIN - DIF BPF register values from 153_quant.dat*/
+{15300000, DIF_BPF_COEFF01,    0x0001ffff},
+{15300000, DIF_BPF_COEFF23,    0xfff9000f},
+{15300000, DIF_BPF_COEFF45,    0x0009ffc8},
+{15300000, DIF_BPF_COEFF67,    0x00250059},
+{15300000, DIF_BPF_COEFF89,    0xff5effee},
+{15300000, DIF_BPF_COEFF1011,  0x0132ff10},
+{15300000, DIF_BPF_COEFF1213,  0xfee30265},
+{15300000, DIF_BPF_COEFF1415,  0xffaafccf},
+{15300000, DIF_BPF_COEFF1617,  0x031101eb},
+{15300000, DIF_BPF_COEFF1819,  0xfa6001e8},
+{15300000, DIF_BPF_COEFF2021,  0x05bdf92f},
+{15300000, DIF_BPF_COEFF2223,  0xfe1b09b6},
+{15300000, DIF_BPF_COEFF2425,  0xfafaf852},
+{15300000, DIF_BPF_COEFF2627,  0x0b7e0055},
+{15300000, DIF_BPF_COEFF2829,  0xf2d50929},
+{15300000, DIF_BPF_COEFF3031,  0x07d3f086},
+{15300000, DIF_BPF_COEFF3233,  0x02a30e6c},
+{15300000, DIF_BPF_COEFF3435,  0xf329fa24},
+{15300000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 153_quant.dat*/
+
+
+/*case 115400000:*/
+/* BEGIN - DIF BPF register values from 154_quant.dat*/
+{15400000, DIF_BPF_COEFF01,    0x00010001},
+{15400000, DIF_BPF_COEFF23,    0xfff80009},
+{15400000, DIF_BPF_COEFF45,    0x0015ffca},
+{15400000, DIF_BPF_COEFF67,    0x00050074},
+{15400000, DIF_BPF_COEFF89,    0xff81ff9f},
+{15400000, DIF_BPF_COEFF1011,  0x013dff82},
+{15400000, DIF_BPF_COEFF1213,  0xfe710221},
+{15400000, DIF_BPF_COEFF1415,  0x007cfc80},
+{15400000, DIF_BPF_COEFF1617,  0x024102ed},
+{15400000, DIF_BPF_COEFF1819,  0xfa940090},
+{15400000, DIF_BPF_COEFF2021,  0x0680fa1e},
+{15400000, DIF_BPF_COEFF2223,  0xfc9b09cd},
+{15400000, DIF_BPF_COEFF2425,  0xfc73f736},
+{15400000, DIF_BPF_COEFF2627,  0x0ad501d0},
+{15400000, DIF_BPF_COEFF2829,  0xf2740820},
+{15400000, DIF_BPF_COEFF3031,  0x08c9f0bd},
+{15400000, DIF_BPF_COEFF3233,  0x01d40eb9},
+{15400000, DIF_BPF_COEFF3435,  0xf371f9f1},
+{15400000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 154_quant.dat*/
+
+
+/*case 115500000:*/
+/* BEGIN - DIF BPF register values from 155_quant.dat*/
+{15500000, DIF_BPF_COEFF01,    0x00000002},
+{15500000, DIF_BPF_COEFF23,    0xfff80002},
+{15500000, DIF_BPF_COEFF45,    0x001effd5},
+{15500000, DIF_BPF_COEFF67,    0xffe5007f},
+{15500000, DIF_BPF_COEFF89,    0xffb4ff5b},
+{15500000, DIF_BPF_COEFF1011,  0x01280000},
+{15500000, DIF_BPF_COEFF1213,  0xfe2401b0},
+{15500000, DIF_BPF_COEFF1415,  0x0146fc70},
+{15500000, DIF_BPF_COEFF1617,  0x014d03c6},
+{15500000, DIF_BPF_COEFF1819,  0xfb10ff32},
+{15500000, DIF_BPF_COEFF2021,  0x0701fb41},
+{15500000, DIF_BPF_COEFF2223,  0xfb3709a1},
+{15500000, DIF_BPF_COEFF2425,  0xfe00f644},
+{15500000, DIF_BPF_COEFF2627,  0x0a000345},
+{15500000, DIF_BPF_COEFF2829,  0xf2350708},
+{15500000, DIF_BPF_COEFF3031,  0x09b2f104},
+{15500000, DIF_BPF_COEFF3233,  0x01050eff},
+{15500000, DIF_BPF_COEFF3435,  0xf3baf9be},
+{15500000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 155_quant.dat*/
+
+
+/*case 115600000:*/
+/* BEGIN - DIF BPF register values from 156_quant.dat*/
+{15600000, DIF_BPF_COEFF01,    0x00000003},
+{15600000, DIF_BPF_COEFF23,    0xfff9fffb},
+{15600000, DIF_BPF_COEFF45,    0x0022ffe6},
+{15600000, DIF_BPF_COEFF67,    0xffc9007a},
+{15600000, DIF_BPF_COEFF89,    0xfff0ff29},
+{15600000, DIF_BPF_COEFF1011,  0x00f2007e},
+{15600000, DIF_BPF_COEFF1213,  0xfe01011b},
+{15600000, DIF_BPF_COEFF1415,  0x01f6fc9e},
+{15600000, DIF_BPF_COEFF1617,  0x00440467},
+{15600000, DIF_BPF_COEFF1819,  0xfbccfdde},
+{15600000, DIF_BPF_COEFF2021,  0x0738fc90},
+{15600000, DIF_BPF_COEFF2223,  0xf9f70934},
+{15600000, DIF_BPF_COEFF2425,  0xff99f582},
+{15600000, DIF_BPF_COEFF2627,  0x090204b0},
+{15600000, DIF_BPF_COEFF2829,  0xf21a05e1},
+{15600000, DIF_BPF_COEFF3031,  0x0a8df15a},
+{15600000, DIF_BPF_COEFF3233,  0x00340f41},
+{15600000, DIF_BPF_COEFF3435,  0xf405f98b},
+{15600000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 156_quant.dat*/
+
+
+/*case 115700000:*/
+/* BEGIN - DIF BPF register values from 157_quant.dat*/
+{15700000, DIF_BPF_COEFF01,    0x00000003},
+{15700000, DIF_BPF_COEFF23,    0xfffcfff4},
+{15700000, DIF_BPF_COEFF45,    0x0020fffa},
+{15700000, DIF_BPF_COEFF67,    0xffb40064},
+{15700000, DIF_BPF_COEFF89,    0x002fff11},
+{15700000, DIF_BPF_COEFF1011,  0x00a400f0},
+{15700000, DIF_BPF_COEFF1213,  0xfe0d006e},
+{15700000, DIF_BPF_COEFF1415,  0x0281fd09},
+{15700000, DIF_BPF_COEFF1617,  0xff3604c9},
+{15700000, DIF_BPF_COEFF1819,  0xfcbffca2},
+{15700000, DIF_BPF_COEFF2021,  0x0726fdfe},
+{15700000, DIF_BPF_COEFF2223,  0xf8e80888},
+{15700000, DIF_BPF_COEFF2425,  0x0134f4f3},
+{15700000, DIF_BPF_COEFF2627,  0x07e1060c},
+{15700000, DIF_BPF_COEFF2829,  0xf22304af},
+{15700000, DIF_BPF_COEFF3031,  0x0b59f1be},
+{15700000, DIF_BPF_COEFF3233,  0xff640f7d},
+{15700000, DIF_BPF_COEFF3435,  0xf452f959},
+{15700000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 157_quant.dat*/
+
+
+/*case 115800000:*/
+/* BEGIN - DIF BPF register values from 158_quant.dat*/
+{15800000, DIF_BPF_COEFF01,    0x00000003},
+{15800000, DIF_BPF_COEFF23,    0x0000fff0},
+{15800000, DIF_BPF_COEFF45,    0x001a0010},
+{15800000, DIF_BPF_COEFF67,    0xffaa0041},
+{15800000, DIF_BPF_COEFF89,    0x0067ff13},
+{15800000, DIF_BPF_COEFF1011,  0x0043014a},
+{15800000, DIF_BPF_COEFF1213,  0xfe46ffb9},
+{15800000, DIF_BPF_COEFF1415,  0x02dbfda8},
+{15800000, DIF_BPF_COEFF1617,  0xfe3504e5},
+{15800000, DIF_BPF_COEFF1819,  0xfddcfb8d},
+{15800000, DIF_BPF_COEFF2021,  0x06c9ff7e},
+{15800000, DIF_BPF_COEFF2223,  0xf81107a2},
+{15800000, DIF_BPF_COEFF2425,  0x02c9f49a},
+{15800000, DIF_BPF_COEFF2627,  0x069f0753},
+{15800000, DIF_BPF_COEFF2829,  0xf2500373},
+{15800000, DIF_BPF_COEFF3031,  0x0c14f231},
+{15800000, DIF_BPF_COEFF3233,  0xfe930fb3},
+{15800000, DIF_BPF_COEFF3435,  0xf4a1f927},
+{15800000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 158_quant.dat*/
+
+
+/*case 115900000:*/
+/* BEGIN - DIF BPF register values from 159_quant.dat*/
+{15900000, DIF_BPF_COEFF01,    0xffff0002},
+{15900000, DIF_BPF_COEFF23,    0x0003ffee},
+{15900000, DIF_BPF_COEFF45,    0x000f0023},
+{15900000, DIF_BPF_COEFF67,    0xffac0016},
+{15900000, DIF_BPF_COEFF89,    0x0093ff31},
+{15900000, DIF_BPF_COEFF1011,  0xffdc0184},
+{15900000, DIF_BPF_COEFF1213,  0xfea6ff09},
+{15900000, DIF_BPF_COEFF1415,  0x02fdfe70},
+{15900000, DIF_BPF_COEFF1617,  0xfd5104ba},
+{15900000, DIF_BPF_COEFF1819,  0xff15faac},
+{15900000, DIF_BPF_COEFF2021,  0x06270103},
+{15900000, DIF_BPF_COEFF2223,  0xf7780688},
+{15900000, DIF_BPF_COEFF2425,  0x044df479},
+{15900000, DIF_BPF_COEFF2627,  0x05430883},
+{15900000, DIF_BPF_COEFF2829,  0xf2a00231},
+{15900000, DIF_BPF_COEFF3031,  0x0cbef2b2},
+{15900000, DIF_BPF_COEFF3233,  0xfdc40fe3},
+{15900000, DIF_BPF_COEFF3435,  0xf4f2f8f5},
+{15900000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 159_quant.dat*/
+
+
+/*case 116000000:*/
+/* BEGIN - DIF BPF register values from 160_quant.dat*/
+{16000000, DIF_BPF_COEFF01,    0xffff0001},
+{16000000, DIF_BPF_COEFF23,    0x0006ffef},
+{16000000, DIF_BPF_COEFF45,    0x00020031},
+{16000000, DIF_BPF_COEFF67,    0xffbaffe8},
+{16000000, DIF_BPF_COEFF89,    0x00adff66},
+{16000000, DIF_BPF_COEFF1011,  0xff790198},
+{16000000, DIF_BPF_COEFF1213,  0xff26fe6e},
+{16000000, DIF_BPF_COEFF1415,  0x02e5ff55},
+{16000000, DIF_BPF_COEFF1617,  0xfc99044a},
+{16000000, DIF_BPF_COEFF1819,  0x005bfa09},
+{16000000, DIF_BPF_COEFF2021,  0x0545027f},
+{16000000, DIF_BPF_COEFF2223,  0xf7230541},
+{16000000, DIF_BPF_COEFF2425,  0x05b8f490},
+{16000000, DIF_BPF_COEFF2627,  0x03d20997},
+{16000000, DIF_BPF_COEFF2829,  0xf31300eb},
+{16000000, DIF_BPF_COEFF3031,  0x0d55f341},
+{16000000, DIF_BPF_COEFF3233,  0xfcf6100e},
+{16000000, DIF_BPF_COEFF3435,  0xf544f8c3},
+{16000000, DIF_BPF_COEFF36,    0x110d0000},
+/* END - DIF BPF register values from 160_quant.dat*/
+};
+
+#endif
diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c
new file mode 100644 (file)
index 0000000..7c4e360
--- /dev/null
@@ -0,0 +1,796 @@
+/*
+ DVB device driver for cx231xx
+
+ Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+               Based on em28xx driver
+
+ This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   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/slab.h>
+#include <linux/usb.h>
+
+#include "cx231xx.h"
+#include <media/v4l2-common.h>
+#include <media/videobuf-vmalloc.h>
+
+#include "xc5000.h"
+#include "s5h1432.h"
+#include "tda18271.h"
+#include "s5h1411.h"
+#include "lgdt3305.h"
+#include "mb86a20s.h"
+
+MODULE_DESCRIPTION("driver for cx231xx based DVB cards");
+MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
+MODULE_LICENSE("GPL");
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define dprintk(level, fmt, arg...) do {                       \
+if (debug >= level)                                            \
+       printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \
+} while (0)
+
+#define CX231XX_DVB_NUM_BUFS 5
+#define CX231XX_DVB_MAX_PACKETSIZE 564
+#define CX231XX_DVB_MAX_PACKETS 64
+
+struct cx231xx_dvb {
+       struct dvb_frontend *frontend;
+
+       /* feed count management */
+       struct mutex lock;
+       int nfeeds;
+
+       /* general boilerplate stuff */
+       struct dvb_adapter adapter;
+       struct dvb_demux demux;
+       struct dmxdev dmxdev;
+       struct dmx_frontend fe_hw;
+       struct dmx_frontend fe_mem;
+       struct dvb_net net;
+};
+
+static struct s5h1432_config dvico_s5h1432_config = {
+       .output_mode   = S5H1432_SERIAL_OUTPUT,
+       .gpio          = S5H1432_GPIO_ON,
+       .qam_if        = S5H1432_IF_4000,
+       .vsb_if        = S5H1432_IF_4000,
+       .inversion     = S5H1432_INVERSION_OFF,
+       .status_mode   = S5H1432_DEMODLOCKING,
+       .mpeg_timing   = S5H1432_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct tda18271_std_map cnxt_rde253s_tda18271_std_map = {
+       .dvbt_6   = { .if_freq = 4000, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x37, },
+       .dvbt_7   = { .if_freq = 4000, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x37, },
+       .dvbt_8   = { .if_freq = 4000, .agc_mode = 3, .std = 6,
+                     .if_lvl = 1, .rfagc_top = 0x37, },
+};
+
+static struct tda18271_std_map mb86a20s_tda18271_config = {
+       .dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
+                     .if_lvl = 7, .rfagc_top = 0x37, },
+};
+
+static struct tda18271_config cnxt_rde253s_tunerconfig = {
+       .std_map = &cnxt_rde253s_tda18271_std_map,
+       .gate    = TDA18271_GATE_ANALOG,
+};
+
+static struct s5h1411_config tda18271_s5h1411_config = {
+       .output_mode   = S5H1411_SERIAL_OUTPUT,
+       .gpio          = S5H1411_GPIO_OFF,
+       .vsb_if        = S5H1411_IF_3250,
+       .qam_if        = S5H1411_IF_4000,
+       .inversion     = S5H1411_INVERSION_ON,
+       .status_mode   = S5H1411_DEMODLOCKING,
+       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+static struct s5h1411_config xc5000_s5h1411_config = {
+       .output_mode   = S5H1411_SERIAL_OUTPUT,
+       .gpio          = S5H1411_GPIO_OFF,
+       .vsb_if        = S5H1411_IF_3250,
+       .qam_if        = S5H1411_IF_3250,
+       .inversion     = S5H1411_INVERSION_OFF,
+       .status_mode   = S5H1411_DEMODLOCKING,
+       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
+};
+
+static struct lgdt3305_config hcw_lgdt3305_config = {
+       .i2c_addr           = 0x0e,
+       .mpeg_mode          = LGDT3305_MPEG_SERIAL,
+       .tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
+       .tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
+       .deny_i2c_rptr      = 1,
+       .spectral_inversion = 1,
+       .qam_if_khz         = 4000,
+       .vsb_if_khz         = 3250,
+};
+
+static struct tda18271_std_map hauppauge_tda18271_std_map = {
+       .atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 4,
+                     .if_lvl = 1, .rfagc_top = 0x58, },
+       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 5,
+                     .if_lvl = 1, .rfagc_top = 0x58, },
+};
+
+static struct tda18271_config hcw_tda18271_config = {
+       .std_map = &hauppauge_tda18271_std_map,
+       .gate    = TDA18271_GATE_DIGITAL,
+};
+
+static const struct mb86a20s_config pv_mb86a20s_config = {
+       .demod_address = 0x10,
+       .is_serial = true,
+};
+
+static struct tda18271_config pv_tda18271_config = {
+       .std_map = &mb86a20s_tda18271_config,
+       .gate    = TDA18271_GATE_DIGITAL,
+       .small_i2c = TDA18271_03_BYTE_CHUNK_INIT,
+};
+
+static inline void print_err_status(struct cx231xx *dev, int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+       if (packet < 0) {
+               dprintk(1, "URB status %d [%s].\n", status, errmsg);
+       } else {
+               dprintk(1, "URB packet %d, status %d [%s].\n",
+                       packet, status, errmsg);
+       }
+}
+
+static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb)
+{
+       int i;
+
+       if (!dev)
+               return 0;
+
+       if (dev->state & DEV_DISCONNECTED)
+               return 0;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               if (urb->status == -ENOENT)
+                       return 0;
+       }
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               int status = urb->iso_frame_desc[i].status;
+
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       if (urb->iso_frame_desc[i].status != -EPROTO)
+                               continue;
+               }
+
+               dvb_dmx_swfilter(&dev->dvb->demux,
+                                urb->transfer_buffer +
+                               urb->iso_frame_desc[i].offset,
+                               urb->iso_frame_desc[i].actual_length);
+       }
+
+       return 0;
+}
+
+static inline int dvb_bulk_copy(struct cx231xx *dev, struct urb *urb)
+{
+       if (!dev)
+               return 0;
+
+       if (dev->state & DEV_DISCONNECTED)
+               return 0;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               if (urb->status == -ENOENT)
+                       return 0;
+       }
+
+       /* Feed the transport payload into the kernel demux */
+       dvb_dmx_swfilter(&dev->dvb->demux,
+               urb->transfer_buffer, urb->actual_length);
+
+       return 0;
+}
+
+static int start_streaming(struct cx231xx_dvb *dvb)
+{
+       int rc;
+       struct cx231xx *dev = dvb->adapter.priv;
+
+       if (dev->USE_ISO) {
+               cx231xx_info("DVB transfer mode is ISO.\n");
+               mutex_lock(&dev->i2c_lock);
+               cx231xx_enable_i2c_port_3(dev, false);
+               cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
+               cx231xx_enable_i2c_port_3(dev, true);
+               mutex_unlock(&dev->i2c_lock);
+               rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
+               if (rc < 0)
+                       return rc;
+               dev->mode_tv = 1;
+               return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS,
+                                       CX231XX_DVB_NUM_BUFS,
+                                       dev->ts1_mode.max_pkt_size,
+                                       dvb_isoc_copy);
+       } else {
+               cx231xx_info("DVB transfer mode is BULK.\n");
+               cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
+               rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
+               if (rc < 0)
+                       return rc;
+               dev->mode_tv = 1;
+               return cx231xx_init_bulk(dev, CX231XX_DVB_MAX_PACKETS,
+                                       CX231XX_DVB_NUM_BUFS,
+                                       dev->ts1_mode.max_pkt_size,
+                                       dvb_bulk_copy);
+       }
+
+}
+
+static int stop_streaming(struct cx231xx_dvb *dvb)
+{
+       struct cx231xx *dev = dvb->adapter.priv;
+
+       if (dev->USE_ISO)
+               cx231xx_uninit_isoc(dev);
+       else
+               cx231xx_uninit_bulk(dev);
+
+       cx231xx_set_mode(dev, CX231XX_SUSPEND);
+
+       return 0;
+}
+
+static int start_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct cx231xx_dvb *dvb = demux->priv;
+       int rc, ret;
+
+       if (!demux->dmx.frontend)
+               return -EINVAL;
+
+       mutex_lock(&dvb->lock);
+       dvb->nfeeds++;
+       rc = dvb->nfeeds;
+
+       if (dvb->nfeeds == 1) {
+               ret = start_streaming(dvb);
+               if (ret < 0)
+                       rc = ret;
+       }
+
+       mutex_unlock(&dvb->lock);
+       return rc;
+}
+
+static int stop_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct cx231xx_dvb *dvb = demux->priv;
+       int err = 0;
+
+       mutex_lock(&dvb->lock);
+       dvb->nfeeds--;
+
+       if (0 == dvb->nfeeds)
+               err = stop_streaming(dvb);
+
+       mutex_unlock(&dvb->lock);
+       return err;
+}
+
+/* ------------------------------------------------------------------ */
+static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+       struct cx231xx *dev = fe->dvb->priv;
+
+       if (acquire)
+               return cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
+       else
+               return cx231xx_set_mode(dev, CX231XX_SUSPEND);
+}
+
+/* ------------------------------------------------------------------ */
+
+static struct xc5000_config cnxt_rde250_tunerconfig = {
+       .i2c_address = 0x61,
+       .if_khz = 4000,
+};
+static struct xc5000_config cnxt_rdu250_tunerconfig = {
+       .i2c_address = 0x61,
+       .if_khz = 3250,
+};
+
+/* ------------------------------------------------------------------ */
+#if 0
+static int attach_xc5000(u8 addr, struct cx231xx *dev)
+{
+
+       struct dvb_frontend *fe;
+       struct xc5000_config cfg;
+
+       memset(&cfg, 0, sizeof(cfg));
+       cfg.i2c_adap = &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap;
+       cfg.i2c_addr = addr;
+
+       if (!dev->dvb->frontend) {
+               printk(KERN_ERR "%s/2: dvb frontend not attached. "
+                      "Can't attach xc5000\n", dev->name);
+               return -EINVAL;
+       }
+
+       fe = dvb_attach(xc5000_attach, dev->dvb->frontend, &cfg);
+       if (!fe) {
+               printk(KERN_ERR "%s/2: xc5000 attach failed\n", dev->name);
+               dvb_frontend_detach(dev->dvb->frontend);
+               dev->dvb->frontend = NULL;
+               return -EINVAL;
+       }
+
+       printk(KERN_INFO "%s/2: xc5000 attached\n", dev->name);
+
+       return 0;
+}
+#endif
+
+int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq)
+{
+       int status = 0;
+
+       if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) {
+
+               struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops;
+
+               if (dops->set_analog_params != NULL) {
+                       struct analog_parameters params;
+
+                       params.frequency = freq;
+                       params.std = dev->norm;
+                       params.mode = 0;        /* 0- Air; 1 - cable */
+                       /*params.audmode = ;       */
+
+                       /* Set the analog parameters to set the frequency */
+                       dops->set_analog_params(dev->dvb->frontend, &params);
+               }
+
+       }
+
+       return status;
+}
+
+int cx231xx_reset_analog_tuner(struct cx231xx *dev)
+{
+       int status = 0;
+
+       if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) {
+
+               struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops;
+
+               if (dops->init != NULL && !dev->xc_fw_load_done) {
+
+                       cx231xx_info("Reloading firmware for XC5000\n");
+                       status = dops->init(dev->dvb->frontend);
+                       if (status == 0) {
+                               dev->xc_fw_load_done = 1;
+                               cx231xx_info
+                                   ("XC5000 firmware download completed\n");
+                       } else {
+                               dev->xc_fw_load_done = 0;
+                               cx231xx_info
+                                   ("XC5000 firmware download failed !!!\n");
+                       }
+               }
+
+       }
+
+       return status;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int register_dvb(struct cx231xx_dvb *dvb,
+                       struct module *module,
+                       struct cx231xx *dev, struct device *device)
+{
+       int result;
+
+       mutex_init(&dvb->lock);
+
+       /* register adapter */
+       result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
+                                     adapter_nr);
+       if (result < 0) {
+               printk(KERN_WARNING
+                      "%s: dvb_register_adapter failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_adapter;
+       }
+
+       /* Ensure all frontends negotiate bus access */
+       dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl;
+
+       dvb->adapter.priv = dev;
+
+       /* register frontend */
+       result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+       if (result < 0) {
+               printk(KERN_WARNING
+                      "%s: dvb_register_frontend failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_frontend;
+       }
+
+       /* register demux stuff */
+       dvb->demux.dmx.capabilities =
+           DMX_TS_FILTERING | DMX_SECTION_FILTERING |
+           DMX_MEMORY_BASED_FILTERING;
+       dvb->demux.priv = dvb;
+       dvb->demux.filternum = 256;
+       dvb->demux.feednum = 256;
+       dvb->demux.start_feed = start_feed;
+       dvb->demux.stop_feed = stop_feed;
+
+       result = dvb_dmx_init(&dvb->demux);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_dmx;
+       }
+
+       dvb->dmxdev.filternum = 256;
+       dvb->dmxdev.demux = &dvb->demux.dmx;
+       dvb->dmxdev.capabilities = 0;
+       result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_dmxdev;
+       }
+
+       dvb->fe_hw.source = DMX_FRONTEND_0;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_WARNING
+                      "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
+                      dev->name, result);
+               goto fail_fe_hw;
+       }
+
+       dvb->fe_mem.source = DMX_MEMORY_FE;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       if (result < 0) {
+               printk(KERN_WARNING
+                      "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
+                      dev->name, result);
+               goto fail_fe_mem;
+       }
+
+       result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_WARNING
+                      "%s: connect_frontend failed (errno = %d)\n", dev->name,
+                      result);
+               goto fail_fe_conn;
+       }
+
+       /* register network adapter */
+       dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
+       return 0;
+
+fail_fe_conn:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+fail_fe_mem:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+fail_fe_hw:
+       dvb_dmxdev_release(&dvb->dmxdev);
+fail_dmxdev:
+       dvb_dmx_release(&dvb->demux);
+fail_dmx:
+       dvb_unregister_frontend(dvb->frontend);
+fail_frontend:
+       dvb_frontend_detach(dvb->frontend);
+       dvb_unregister_adapter(&dvb->adapter);
+fail_adapter:
+       return result;
+}
+
+static void unregister_dvb(struct cx231xx_dvb *dvb)
+{
+       dvb_net_release(&dvb->net);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       dvb_dmxdev_release(&dvb->dmxdev);
+       dvb_dmx_release(&dvb->demux);
+       dvb_unregister_frontend(dvb->frontend);
+       dvb_frontend_detach(dvb->frontend);
+       dvb_unregister_adapter(&dvb->adapter);
+}
+
+static int dvb_init(struct cx231xx *dev)
+{
+       int result = 0;
+       struct cx231xx_dvb *dvb;
+
+       if (!dev->board.has_dvb) {
+               /* This device does not support the extension */
+               return 0;
+       }
+
+       dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL);
+
+       if (dvb == NULL) {
+               printk(KERN_INFO "cx231xx_dvb: memory allocation failed\n");
+               return -ENOMEM;
+       }
+       dev->dvb = dvb;
+       dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq;
+       dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner;
+
+       mutex_lock(&dev->lock);
+       cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
+       cx231xx_demod_reset(dev);
+       /* init frontend */
+       switch (dev->model) {
+       case CX231XX_BOARD_CNXT_CARRAERA:
+       case CX231XX_BOARD_CNXT_RDE_250:
+
+               dev->dvb->frontend = dvb_attach(s5h1432_attach,
+                                       &dvico_s5h1432_config,
+                                       &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
+
+               if (dev->dvb->frontend == NULL) {
+                       printk(DRIVER_NAME
+                              ": Failed to attach s5h1432 front end\n");
+                       result = -EINVAL;
+                       goto out_free;
+               }
+
+               /* define general-purpose callback pointer */
+               dvb->frontend->callback = cx231xx_tuner_callback;
+
+               if (!dvb_attach(xc5000_attach, dev->dvb->frontend,
+                              &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
+                              &cnxt_rde250_tunerconfig)) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+
+               break;
+       case CX231XX_BOARD_CNXT_SHELBY:
+       case CX231XX_BOARD_CNXT_RDU_250:
+
+               dev->dvb->frontend = dvb_attach(s5h1411_attach,
+                                              &xc5000_s5h1411_config,
+                                              &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
+
+               if (dev->dvb->frontend == NULL) {
+                       printk(DRIVER_NAME
+                              ": Failed to attach s5h1411 front end\n");
+                       result = -EINVAL;
+                       goto out_free;
+               }
+
+               /* define general-purpose callback pointer */
+               dvb->frontend->callback = cx231xx_tuner_callback;
+
+               if (!dvb_attach(xc5000_attach, dev->dvb->frontend,
+                              &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
+                              &cnxt_rdu250_tunerconfig)) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       case CX231XX_BOARD_CNXT_RDE_253S:
+
+               dev->dvb->frontend = dvb_attach(s5h1432_attach,
+                                       &dvico_s5h1432_config,
+                                       &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
+
+               if (dev->dvb->frontend == NULL) {
+                       printk(DRIVER_NAME
+                              ": Failed to attach s5h1432 front end\n");
+                       result = -EINVAL;
+                       goto out_free;
+               }
+
+               /* define general-purpose callback pointer */
+               dvb->frontend->callback = cx231xx_tuner_callback;
+
+               if (!dvb_attach(tda18271_attach, dev->dvb->frontend,
+                              0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
+                              &cnxt_rde253s_tunerconfig)) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       case CX231XX_BOARD_CNXT_RDU_253S:
+
+               dev->dvb->frontend = dvb_attach(s5h1411_attach,
+                                              &tda18271_s5h1411_config,
+                                              &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
+
+               if (dev->dvb->frontend == NULL) {
+                       printk(DRIVER_NAME
+                              ": Failed to attach s5h1411 front end\n");
+                       result = -EINVAL;
+                       goto out_free;
+               }
+
+               /* define general-purpose callback pointer */
+               dvb->frontend->callback = cx231xx_tuner_callback;
+
+               if (!dvb_attach(tda18271_attach, dev->dvb->frontend,
+                              0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
+                              &cnxt_rde253s_tunerconfig)) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       case CX231XX_BOARD_HAUPPAUGE_EXETER:
+
+               printk(KERN_INFO "%s: looking for tuner / demod on i2c bus: %d\n",
+                      __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap));
+
+               dev->dvb->frontend = dvb_attach(lgdt3305_attach,
+                                               &hcw_lgdt3305_config,
+                                               &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap);
+
+               if (dev->dvb->frontend == NULL) {
+                       printk(DRIVER_NAME
+                              ": Failed to attach LG3305 front end\n");
+                       result = -EINVAL;
+                       goto out_free;
+               }
+
+               /* define general-purpose callback pointer */
+               dvb->frontend->callback = cx231xx_tuner_callback;
+
+               dvb_attach(tda18271_attach, dev->dvb->frontend,
+                          0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
+                          &hcw_tda18271_config);
+               break;
+
+       case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
+       case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID:
+
+               printk(KERN_INFO "%s: looking for demod on i2c bus: %d\n",
+                      __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap));
+
+               dev->dvb->frontend = dvb_attach(mb86a20s_attach,
+                                               &pv_mb86a20s_config,
+                                               &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
+
+               if (dev->dvb->frontend == NULL) {
+                       printk(DRIVER_NAME
+                              ": Failed to attach mb86a20s demod\n");
+                       result = -EINVAL;
+                       goto out_free;
+               }
+
+               /* define general-purpose callback pointer */
+               dvb->frontend->callback = cx231xx_tuner_callback;
+
+               dvb_attach(tda18271_attach, dev->dvb->frontend,
+                          0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
+                          &pv_tda18271_config);
+               break;
+
+       default:
+               printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
+                      " isn't supported yet\n", dev->name);
+               break;
+       }
+       if (NULL == dvb->frontend) {
+               printk(KERN_ERR
+                      "%s/2: frontend initialization failed\n", dev->name);
+               result = -EINVAL;
+               goto out_free;
+       }
+
+       /* register everything */
+       result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
+
+       if (result < 0)
+               goto out_free;
+
+
+       printk(KERN_INFO "Successfully loaded cx231xx-dvb\n");
+
+ret:
+       cx231xx_set_mode(dev, CX231XX_SUSPEND);
+       mutex_unlock(&dev->lock);
+       return result;
+
+out_free:
+       kfree(dvb);
+       dev->dvb = NULL;
+       goto ret;
+}
+
+static int dvb_fini(struct cx231xx *dev)
+{
+       if (!dev->board.has_dvb) {
+               /* This device does not support the extension */
+               return 0;
+       }
+
+       if (dev->dvb) {
+               unregister_dvb(dev->dvb);
+               dev->dvb = NULL;
+       }
+
+       return 0;
+}
+
+static struct cx231xx_ops dvb_ops = {
+       .id = CX231XX_DVB,
+       .name = "Cx231xx dvb Extension",
+       .init = dvb_init,
+       .fini = dvb_fini,
+};
+
+static int __init cx231xx_dvb_register(void)
+{
+       return cx231xx_register_extension(&dvb_ops);
+}
+
+static void __exit cx231xx_dvb_unregister(void)
+{
+       cx231xx_unregister_extension(&dvb_ops);
+}
+
+module_init(cx231xx_dvb_register);
+module_exit(cx231xx_dvb_unregister);
diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c b/drivers/media/usb/cx231xx/cx231xx-i2c.c
new file mode 100644 (file)
index 0000000..781feed
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+   cx231xx-i2c.c - driver for Conexant Cx23100/101/102 USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+               Based on em28xx driver
+               Based on Cx23885 driver
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   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/module.h>
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+
+#include "cx231xx.h"
+
+/* ----------------------------------------------------------- */
+
+static unsigned int i2c_scan;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+#define dprintk1(lvl, fmt, args...)                    \
+do {                                                   \
+       if (i2c_debug >= lvl) {                         \
+               printk(fmt, ##args);                    \
+               }                                       \
+} while (0)
+
+#define dprintk2(lvl, fmt, args...)                    \
+do {                                                   \
+       if (i2c_debug >= lvl) {                         \
+               printk(KERN_DEBUG "%s at %s: " fmt,     \
+                      dev->name, __func__ , ##args);   \
+      }                                                \
+} while (0)
+
+static inline bool is_tuner(struct cx231xx *dev, struct cx231xx_i2c *bus,
+                       const struct i2c_msg *msg, int tuner_type)
+{
+       if (bus->nr != dev->board.tuner_i2c_master)
+               return false;
+
+       if (msg->addr != dev->board.tuner_addr)
+               return false;
+
+       if (dev->tuner_type != tuner_type)
+               return false;
+
+       return true;
+}
+
+/*
+ * cx231xx_i2c_send_bytes()
+ */
+int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap,
+                          const struct i2c_msg *msg)
+{
+       struct cx231xx_i2c *bus = i2c_adap->algo_data;
+       struct cx231xx *dev = bus->dev;
+       struct cx231xx_i2c_xfer_data req_data;
+       int status = 0;
+       u16 size = 0;
+       u8 loop = 0;
+       u8 saddr_len = 1;
+       u8 *buf_ptr = NULL;
+       u16 saddr = 0;
+       u8 need_gpio = 0;
+
+       if (is_tuner(dev, bus, msg, TUNER_XC5000)) {
+               size = msg->len;
+
+               if (size == 2) {        /* register write sub addr */
+                       /* Just writing sub address will cause problem
+                       * to XC5000. So ignore the request */
+                       return 0;
+               } else if (size == 4) { /* register write with sub addr */
+                       if (msg->len >= 2)
+                               saddr = msg->buf[0] << 8 | msg->buf[1];
+                       else if (msg->len == 1)
+                               saddr = msg->buf[0];
+
+                       switch (saddr) {
+                       case 0x0000:    /* start tuner calibration mode */
+                               need_gpio = 1;
+                               /* FW Loading is done */
+                               dev->xc_fw_load_done = 1;
+                               break;
+                       case 0x000D:    /* Set signal source */
+                       case 0x0001:    /* Set TV standard - Video */
+                       case 0x0002:    /* Set TV standard - Audio */
+                       case 0x0003:    /* Set RF Frequency */
+                               need_gpio = 1;
+                               break;
+                       default:
+                               if (dev->xc_fw_load_done)
+                                       need_gpio = 1;
+                               break;
+                       }
+
+                       if (need_gpio) {
+                               dprintk1(1,
+                               "GPIO WRITE: addr 0x%x, len %d, saddr 0x%x\n",
+                               msg->addr, msg->len, saddr);
+
+                               return dev->cx231xx_gpio_i2c_write(dev,
+                                                                  msg->addr,
+                                                                  msg->buf,
+                                                                  msg->len);
+                       }
+               }
+
+               /* special case for Xc5000 tuner case */
+               saddr_len = 1;
+
+               /* adjust the length to correct length */
+               size -= saddr_len;
+               buf_ptr = (u8 *) (msg->buf + 1);
+
+               do {
+                       /* prepare xfer_data struct */
+                       req_data.dev_addr = msg->addr;
+                       req_data.direction = msg->flags;
+                       req_data.saddr_len = saddr_len;
+                       req_data.saddr_dat = msg->buf[0];
+                       req_data.buf_size = size > 16 ? 16 : size;
+                       req_data.p_buffer = (u8 *) (buf_ptr + loop * 16);
+
+                       bus->i2c_nostop = (size > 16) ? 1 : 0;
+                       bus->i2c_reserve = (loop == 0) ? 0 : 1;
+
+                       /* usb send command */
+                       status = dev->cx231xx_send_usb_command(bus, &req_data);
+                       loop++;
+
+                       if (size >= 16)
+                               size -= 16;
+                       else
+                               size = 0;
+
+               } while (size > 0);
+
+               bus->i2c_nostop = 0;
+               bus->i2c_reserve = 0;
+
+       } else {                /* regular case */
+
+               /* prepare xfer_data struct */
+               req_data.dev_addr = msg->addr;
+               req_data.direction = msg->flags;
+               req_data.saddr_len = 0;
+               req_data.saddr_dat = 0;
+               req_data.buf_size = msg->len;
+               req_data.p_buffer = msg->buf;
+
+               /* usb send command */
+               status = dev->cx231xx_send_usb_command(bus, &req_data);
+       }
+
+       return status < 0 ? status : 0;
+}
+
+/*
+ * cx231xx_i2c_recv_bytes()
+ * read a byte from the i2c device
+ */
+static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap,
+                                 const struct i2c_msg *msg)
+{
+       struct cx231xx_i2c *bus = i2c_adap->algo_data;
+       struct cx231xx *dev = bus->dev;
+       struct cx231xx_i2c_xfer_data req_data;
+       int status = 0;
+       u16 saddr = 0;
+       u8 need_gpio = 0;
+
+       if (is_tuner(dev, bus, msg, TUNER_XC5000)) {
+               if (msg->len == 2)
+                       saddr = msg->buf[0] << 8 | msg->buf[1];
+               else if (msg->len == 1)
+                       saddr = msg->buf[0];
+
+               if (dev->xc_fw_load_done) {
+
+                       switch (saddr) {
+                       case 0x0009:    /* BUSY check */
+                               dprintk1(1,
+                               "GPIO R E A D: Special case BUSY check \n");
+                               /*Try read BUSY register, just set it to zero*/
+                               msg->buf[0] = 0;
+                               if (msg->len == 2)
+                                       msg->buf[1] = 0;
+                               return 0;
+                       case 0x0004:    /* read Lock status */
+                               need_gpio = 1;
+                               break;
+
+                       }
+
+                       if (need_gpio) {
+                               /* this is a special case to handle Xceive tuner
+                               clock stretch issue with gpio based I2C */
+
+                               dprintk1(1,
+                               "GPIO R E A D: addr 0x%x, len %d, saddr 0x%x\n",
+                               msg->addr, msg->len,
+                               msg->buf[0] << 8 | msg->buf[1]);
+
+                               status =
+                                   dev->cx231xx_gpio_i2c_write(dev, msg->addr,
+                                                               msg->buf,
+                                                               msg->len);
+                               status =
+                                   dev->cx231xx_gpio_i2c_read(dev, msg->addr,
+                                                              msg->buf,
+                                                              msg->len);
+                               return status;
+                       }
+               }
+
+               /* prepare xfer_data struct */
+               req_data.dev_addr = msg->addr;
+               req_data.direction = msg->flags;
+               req_data.saddr_len = msg->len;
+               req_data.saddr_dat = msg->buf[0] << 8 | msg->buf[1];
+               req_data.buf_size = msg->len;
+               req_data.p_buffer = msg->buf;
+
+               /* usb send command */
+               status = dev->cx231xx_send_usb_command(bus, &req_data);
+
+       } else {
+
+               /* prepare xfer_data struct */
+               req_data.dev_addr = msg->addr;
+               req_data.direction = msg->flags;
+               req_data.saddr_len = 0;
+               req_data.saddr_dat = 0;
+               req_data.buf_size = msg->len;
+               req_data.p_buffer = msg->buf;
+
+               /* usb send command */
+               status = dev->cx231xx_send_usb_command(bus, &req_data);
+       }
+
+       return status < 0 ? status : 0;
+}
+
+/*
+ * cx231xx_i2c_recv_bytes_with_saddr()
+ * read a byte from the i2c device
+ */
+static int cx231xx_i2c_recv_bytes_with_saddr(struct i2c_adapter *i2c_adap,
+                                            const struct i2c_msg *msg1,
+                                            const struct i2c_msg *msg2)
+{
+       struct cx231xx_i2c *bus = i2c_adap->algo_data;
+       struct cx231xx *dev = bus->dev;
+       struct cx231xx_i2c_xfer_data req_data;
+       int status = 0;
+       u16 saddr = 0;
+       u8 need_gpio = 0;
+
+       if (msg1->len == 2)
+               saddr = msg1->buf[0] << 8 | msg1->buf[1];
+       else if (msg1->len == 1)
+               saddr = msg1->buf[0];
+
+       if (is_tuner(dev, bus, msg2, TUNER_XC5000)) {
+               if ((msg2->len < 16)) {
+
+                       dprintk1(1,
+                       "i2c_read: addr 0x%x, len %d, saddr 0x%x, len %d\n",
+                       msg2->addr, msg2->len, saddr, msg1->len);
+
+                       switch (saddr) {
+                       case 0x0008:    /* read FW load status */
+                               need_gpio = 1;
+                               break;
+                       case 0x0004:    /* read Lock status */
+                               need_gpio = 1;
+                               break;
+                       }
+
+                       if (need_gpio) {
+                               status =
+                                   dev->cx231xx_gpio_i2c_write(dev, msg1->addr,
+                                                               msg1->buf,
+                                                               msg1->len);
+                               status =
+                                   dev->cx231xx_gpio_i2c_read(dev, msg2->addr,
+                                                              msg2->buf,
+                                                              msg2->len);
+                               return status;
+                       }
+               }
+       }
+
+       /* prepare xfer_data struct */
+       req_data.dev_addr = msg2->addr;
+       req_data.direction = msg2->flags;
+       req_data.saddr_len = msg1->len;
+       req_data.saddr_dat = saddr;
+       req_data.buf_size = msg2->len;
+       req_data.p_buffer = msg2->buf;
+
+       /* usb send command */
+       status = dev->cx231xx_send_usb_command(bus, &req_data);
+
+       return status < 0 ? status : 0;
+}
+
+/*
+ * cx231xx_i2c_check_for_device()
+ * check if there is a i2c_device at the supplied address
+ */
+static int cx231xx_i2c_check_for_device(struct i2c_adapter *i2c_adap,
+                                       const struct i2c_msg *msg)
+{
+       struct cx231xx_i2c *bus = i2c_adap->algo_data;
+       struct cx231xx *dev = bus->dev;
+       struct cx231xx_i2c_xfer_data req_data;
+       int status = 0;
+
+       /* prepare xfer_data struct */
+       req_data.dev_addr = msg->addr;
+       req_data.direction = msg->flags;
+       req_data.saddr_len = 0;
+       req_data.saddr_dat = 0;
+       req_data.buf_size = 0;
+       req_data.p_buffer = NULL;
+
+       /* usb send command */
+       status = dev->cx231xx_send_usb_command(bus, &req_data);
+
+       return status < 0 ? status : 0;
+}
+
+/*
+ * cx231xx_i2c_xfer()
+ * the main i2c transfer function
+ */
+static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap,
+                           struct i2c_msg msgs[], int num)
+{
+       struct cx231xx_i2c *bus = i2c_adap->algo_data;
+       struct cx231xx *dev = bus->dev;
+       int addr, rc, i, byte;
+
+       if (num <= 0)
+               return 0;
+       mutex_lock(&dev->i2c_lock);
+       for (i = 0; i < num; i++) {
+
+               addr = msgs[i].addr >> 1;
+
+               dprintk2(2, "%s %s addr=%x len=%d:",
+                        (msgs[i].flags & I2C_M_RD) ? "read" : "write",
+                        i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
+               if (!msgs[i].len) {
+                       /* no len: check only for device presence */
+                       rc = cx231xx_i2c_check_for_device(i2c_adap, &msgs[i]);
+                       if (rc < 0) {
+                               dprintk2(2, " no device\n");
+                               mutex_unlock(&dev->i2c_lock);
+                               return rc;
+                       }
+
+               } else if (msgs[i].flags & I2C_M_RD) {
+                       /* read bytes */
+                       rc = cx231xx_i2c_recv_bytes(i2c_adap, &msgs[i]);
+                       if (i2c_debug >= 2) {
+                               for (byte = 0; byte < msgs[i].len; byte++)
+                                       printk(" %02x", msgs[i].buf[byte]);
+                       }
+               } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
+                          msgs[i].addr == msgs[i + 1].addr
+                          && (msgs[i].len <= 2) && (bus->nr < 3)) {
+                       /* read bytes */
+                       rc = cx231xx_i2c_recv_bytes_with_saddr(i2c_adap,
+                                                              &msgs[i],
+                                                              &msgs[i + 1]);
+                       if (i2c_debug >= 2) {
+                               for (byte = 0; byte < msgs[i].len; byte++)
+                                       printk(" %02x", msgs[i].buf[byte]);
+                       }
+                       i++;
+               } else {
+                       /* write bytes */
+                       if (i2c_debug >= 2) {
+                               for (byte = 0; byte < msgs[i].len; byte++)
+                                       printk(" %02x", msgs[i].buf[byte]);
+                       }
+                       rc = cx231xx_i2c_send_bytes(i2c_adap, &msgs[i]);
+               }
+               if (rc < 0)
+                       goto err;
+               if (i2c_debug >= 2)
+                       printk("\n");
+       }
+       mutex_unlock(&dev->i2c_lock);
+       return num;
+err:
+       dprintk2(2, " ERROR: %i\n", rc);
+       mutex_unlock(&dev->i2c_lock);
+       return rc;
+}
+
+/* ----------------------------------------------------------- */
+
+/*
+ * functionality()
+ */
+static u32 functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm cx231xx_algo = {
+       .master_xfer = cx231xx_i2c_xfer,
+       .functionality = functionality,
+};
+
+static struct i2c_adapter cx231xx_adap_template = {
+       .owner = THIS_MODULE,
+       .name = "cx231xx",
+       .algo = &cx231xx_algo,
+};
+
+static struct i2c_client cx231xx_client_template = {
+       .name = "cx231xx internal",
+};
+
+/* ----------------------------------------------------------- */
+
+/*
+ * i2c_devs
+ * incomplete list of known devices
+ */
+static char *i2c_devs[128] = {
+       [0x60 >> 1] = "colibri",
+       [0x88 >> 1] = "hammerhead",
+       [0x8e >> 1] = "CIR",
+       [0x32 >> 1] = "GeminiIII",
+       [0x02 >> 1] = "Aquarius",
+       [0xa0 >> 1] = "eeprom",
+       [0xc0 >> 1] = "tuner",
+       [0xc2 >> 1] = "tuner",
+};
+
+/*
+ * cx231xx_do_i2c_scan()
+ * check i2c address range for devices
+ */
+void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c)
+{
+       unsigned char buf;
+       int i, rc;
+
+       cx231xx_info(": Checking for I2C devices ..\n");
+       for (i = 0; i < 128; i++) {
+               c->addr = i;
+               rc = i2c_master_recv(c, &buf, 0);
+               if (rc < 0)
+                       continue;
+               cx231xx_info("%s: i2c scan: found device @ 0x%x  [%s]\n",
+                            dev->name, i << 1,
+                            i2c_devs[i] ? i2c_devs[i] : "???");
+       }
+       cx231xx_info(": Completed Checking for I2C devices.\n");
+}
+
+/*
+ * cx231xx_i2c_register()
+ * register i2c bus
+ */
+int cx231xx_i2c_register(struct cx231xx_i2c *bus)
+{
+       struct cx231xx *dev = bus->dev;
+
+       BUG_ON(!dev->cx231xx_send_usb_command);
+
+       bus->i2c_adap = cx231xx_adap_template;
+       bus->i2c_client = cx231xx_client_template;
+       bus->i2c_adap.dev.parent = &dev->udev->dev;
+
+       strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
+
+       bus->i2c_adap.algo_data = bus;
+       i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
+       i2c_add_adapter(&bus->i2c_adap);
+
+       bus->i2c_client.adapter = &bus->i2c_adap;
+
+       if (0 == bus->i2c_rc) {
+               if (i2c_scan)
+                       cx231xx_do_i2c_scan(dev, &bus->i2c_client);
+       } else
+               cx231xx_warn("%s: i2c bus %d register FAILED\n",
+                            dev->name, bus->nr);
+
+       return bus->i2c_rc;
+}
+
+/*
+ * cx231xx_i2c_unregister()
+ * unregister i2c_bus
+ */
+int cx231xx_i2c_unregister(struct cx231xx_i2c *bus)
+{
+       i2c_del_adapter(&bus->i2c_adap);
+       return 0;
+}
diff --git a/drivers/media/usb/cx231xx/cx231xx-input.c b/drivers/media/usb/cx231xx/cx231xx-input.c
new file mode 100644 (file)
index 0000000..96176e9
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ *   cx231xx IR glue driver
+ *
+ *   Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ *   Polaris (cx231xx) has its support for IR's with a design close to MCE.
+ *   however, a few designs are using an external I2C chip for IR, instead
+ *   of using the one provided by the chip.
+ *   This driver provides support for those extra devices
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License as
+ *   published by the Free Software Foundation version 2.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *   General Public License for more details.
+ */
+
+#include "cx231xx.h"
+#include <linux/usb.h>
+#include <linux/slab.h>
+
+#define MODULE_NAME "cx231xx-input"
+
+static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key,
+                        u32 *ir_raw)
+{
+       int     rc;
+       u8      cmd, scancode;
+
+       dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__);
+
+               /* poll IR chip */
+       rc = i2c_master_recv(ir->c, &cmd, 1);
+       if (rc < 0)
+               return rc;
+       if (rc != 1)
+               return -EIO;
+
+       /* it seems that 0xFE indicates that a button is still hold
+          down, while 0xff indicates that no button is hold
+          down. 0xfe sequences are sometimes interrupted by 0xFF */
+
+       if (cmd == 0xff)
+               return 0;
+
+       scancode =
+                ((cmd & 0x01) ? 0x80 : 0) |
+                ((cmd & 0x02) ? 0x40 : 0) |
+                ((cmd & 0x04) ? 0x20 : 0) |
+                ((cmd & 0x08) ? 0x10 : 0) |
+                ((cmd & 0x10) ? 0x08 : 0) |
+                ((cmd & 0x20) ? 0x04 : 0) |
+                ((cmd & 0x40) ? 0x02 : 0) |
+                ((cmd & 0x80) ? 0x01 : 0);
+
+       dev_dbg(&ir->rc->input_dev->dev, "cmd %02x, scan = %02x\n",
+               cmd, scancode);
+
+       *ir_key = scancode;
+       *ir_raw = scancode;
+       return 1;
+}
+
+int cx231xx_ir_init(struct cx231xx *dev)
+{
+       struct i2c_board_info info;
+       u8 ir_i2c_bus;
+
+       dev_dbg(&dev->udev->dev, "%s\n", __func__);
+
+       /* Only initialize if a rc keycode map is defined */
+       if (!cx231xx_boards[dev->model].rc_map_name)
+               return -ENODEV;
+
+       request_module("ir-kbd-i2c");
+
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       memset(&dev->init_data, 0, sizeof(dev->init_data));
+       dev->init_data.rc_dev = rc_allocate_device();
+       if (!dev->init_data.rc_dev)
+               return -ENOMEM;
+
+       dev->init_data.name = cx231xx_boards[dev->model].name;
+
+       strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+       info.platform_data = &dev->init_data;
+
+       /*
+        * Board-dependent values
+        *
+        * For now, there's just one type of hardware design using
+        * an i2c device.
+        */
+       dev->init_data.get_key = get_key_isdbt;
+       dev->init_data.ir_codes = cx231xx_boards[dev->model].rc_map_name;
+       /* The i2c micro-controller only outputs the cmd part of NEC protocol */
+       dev->init_data.rc_dev->scanmask = 0xff;
+       dev->init_data.rc_dev->driver_name = "cx231xx";
+       dev->init_data.type = RC_TYPE_NEC;
+       info.addr = 0x30;
+
+       /* Load and bind ir-kbd-i2c */
+       ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master;
+       dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n",
+               ir_i2c_bus, info.addr);
+       dev->ir_i2c_client = i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info);
+
+       return 0;
+}
+
+void cx231xx_ir_exit(struct cx231xx *dev)
+{
+       if (dev->ir_i2c_client)
+               i2c_unregister_device(dev->ir_i2c_client);
+       dev->ir_i2c_client = NULL;
+}
diff --git a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c
new file mode 100644 (file)
index 0000000..7473c33
--- /dev/null
@@ -0,0 +1,795 @@
+/*
+   cx231xx-pcb-config.c - driver for Conexant
+               Cx23100/101/102 USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot 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.
+
+   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 "cx231xx.h"
+#include "cx231xx-conf-reg.h"
+
+static unsigned int pcb_debug;
+module_param(pcb_debug, int, 0644);
+MODULE_PARM_DESC(pcb_debug, "enable pcb config debug messages [video]");
+
+/******************************************************************************/
+
+struct pcb_config cx231xx_Scenario[] = {
+       {
+        INDEX_SELFPOWER_DIGITAL_ONLY,  /* index */
+        USB_SELF_POWER,        /* power_type */
+        0,                     /* speed , not decide yet */
+        MOD_DIGITAL,           /* mode */
+        SOURCE_TS_BDA,         /* ts1_source, digital tv only */
+        NOT_SUPPORTED,         /* ts2_source  */
+        NOT_SUPPORTED,         /* analog source */
+
+        0,                     /* digital_index  */
+        0,                     /* analog index */
+        0,                     /* dif_index   */
+        0,                     /* external_index */
+
+        1,                     /* only one configuration */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           1,                  /* ts1 index */
+           NOT_SUPPORTED,      /* TS2 index */
+           NOT_SUPPORTED,      /* AUDIO */
+           NOT_SUPPORTED,      /* VIDEO */
+           NOT_SUPPORTED,      /* VANC */
+           NOT_SUPPORTED,      /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          ,
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        ,
+        /* full-speed config */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           1,                  /* ts1 index */
+           NOT_SUPPORTED,      /* TS2 index */
+           NOT_SUPPORTED,      /* AUDIO */
+           NOT_SUPPORTED,      /* VIDEO */
+           NOT_SUPPORTED,      /* VANC */
+           NOT_SUPPORTED,      /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        }
+       ,
+
+       {
+        INDEX_SELFPOWER_DUAL_DIGITAL,  /* index */
+        USB_SELF_POWER,        /* power_type */
+        0,                     /* speed , not decide yet */
+        MOD_DIGITAL,           /* mode */
+        SOURCE_TS_BDA,         /* ts1_source, digital tv only */
+        0,                     /* ts2_source,need update from register */
+        NOT_SUPPORTED,         /* analog source */
+        0,                     /* digital_index  */
+        0,                     /* analog index */
+        0,                     /* dif_index */
+        0,                     /* external_index */
+
+        1,                     /* only one configuration */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           1,                  /* ts1 index */
+           2,                  /* TS2 index */
+           NOT_SUPPORTED,      /* AUDIO */
+           NOT_SUPPORTED,      /* VIDEO */
+           NOT_SUPPORTED,      /* VANC */
+           NOT_SUPPORTED,      /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        ,
+        /* full-speed */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           1,                  /* ts1 index */
+           2,                  /* TS2 index */
+           NOT_SUPPORTED,      /* AUDIO */
+           NOT_SUPPORTED,      /* VIDEO */
+           NOT_SUPPORTED,      /* VANC */
+           NOT_SUPPORTED,      /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        }
+       ,
+
+       {
+        INDEX_SELFPOWER_ANALOG_ONLY,   /* index */
+        USB_SELF_POWER,        /* power_type */
+        0,                     /* speed , not decide yet */
+        MOD_ANALOG | MOD_DIF | MOD_EXTERNAL,   /* mode ,analog tv only */
+        NOT_SUPPORTED,         /* ts1_source, NOT SUPPORT */
+        NOT_SUPPORTED,         /* ts2_source,NOT SUPPORT */
+        0,                     /* analog source, need update */
+
+        0,                     /* digital_index  */
+        0,                     /* analog index */
+        0,                     /* dif_index */
+        0,                     /* external_index */
+
+        1,                     /* only one configuration */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           NOT_SUPPORTED,      /* ts1 index */
+           NOT_SUPPORTED,      /* TS2 index */
+           1,                  /* AUDIO */
+           2,                  /* VIDEO */
+           3,                  /* VANC */
+           4,                  /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        ,
+        /* full-speed */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           NOT_SUPPORTED,      /* ts1 index */
+           NOT_SUPPORTED,      /* TS2 index */
+           1,                  /* AUDIO */
+           2,                  /* VIDEO */
+           NOT_SUPPORTED,      /* VANC */
+           NOT_SUPPORTED,      /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        }
+       ,
+
+       {
+        INDEX_SELFPOWER_DUAL,  /* index */
+        USB_SELF_POWER,        /* power_type */
+        0,                     /* speed , not decide yet */
+        /* mode ,analog tv and digital path */
+        MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL,
+        0,                     /* ts1_source,will update in register */
+        NOT_SUPPORTED,         /* ts2_source,NOT SUPPORT */
+        0,                     /* analog source need update */
+        0,                     /* digital_index  */
+        0,                     /* analog index */
+        0,                     /* dif_index */
+        0,                     /* external_index */
+        1,                     /* only one configuration */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           1,                  /* ts1 index */
+           NOT_SUPPORTED,      /* TS2 index */
+           2,                  /* AUDIO */
+           3,                  /* VIDEO */
+           4,                  /* VANC */
+           5,                  /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        ,
+        /* full-speed */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           1,                  /* ts1 index */
+           NOT_SUPPORTED,      /* TS2 index */
+           2,                  /* AUDIO */
+           3,                  /* VIDEO */
+           NOT_SUPPORTED,      /* VANC */
+           NOT_SUPPORTED,      /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        }
+       ,
+
+       {
+        INDEX_SELFPOWER_TRIPLE,        /* index */
+        USB_SELF_POWER,        /* power_type */
+        0,                     /* speed , not decide yet */
+        /* mode ,analog tv and digital path */
+        MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL,
+        0,                     /* ts1_source, update in register */
+        0,                     /* ts2_source,update in register */
+        0,                     /* analog source, need update */
+
+        0,                     /* digital_index  */
+        0,                     /* analog index */
+        0,                     /* dif_index */
+        0,                     /* external_index */
+        1,                     /* only one configuration */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           1,                  /* ts1 index */
+           2,                  /* TS2 index */
+           3,                  /* AUDIO */
+           4,                  /* VIDEO */
+           5,                  /* VANC */
+           6,                  /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        ,
+        /* full-speed */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           1,                  /* ts1 index */
+           2,                  /* TS2 index */
+           3,                  /* AUDIO */
+           4,                  /* VIDEO */
+           NOT_SUPPORTED,      /* VANC */
+           NOT_SUPPORTED,      /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        }
+       ,
+
+       {
+        INDEX_SELFPOWER_COMPRESSOR,    /* index */
+        USB_SELF_POWER,        /* power_type */
+        0,                     /* speed , not decide yet */
+        /* mode ,analog tv AND DIGITAL path */
+        MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL,
+        NOT_SUPPORTED,         /* ts1_source, disable */
+        SOURCE_TS_BDA,         /* ts2_source */
+        0,                     /* analog source,need update */
+        0,                     /* digital_index  */
+        0,                     /* analog index */
+        0,                     /* dif_index */
+        0,                     /* external_index */
+        1,                     /* only one configuration */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           NOT_SUPPORTED,      /* ts1 index */
+           1,                  /* TS2 index */
+           2,                  /* AUDIO */
+           3,                  /* VIDEO */
+           4,                  /* VANC */
+           5,                  /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        ,
+        /* full-speed  */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           NOT_SUPPORTED,      /* ts1 index */
+           1,                  /* TS2 index */
+           2,                  /* AUDIO */
+           3,                  /* VIDEO */
+           NOT_SUPPORTED,      /* VANC */
+           NOT_SUPPORTED,      /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        }
+       ,
+
+       {
+        INDEX_BUSPOWER_DIGITAL_ONLY,   /* index */
+        USB_BUS_POWER,         /* power_type */
+        0,                     /* speed , not decide yet */
+        MOD_DIGITAL,           /* mode ,analog tv AND DIGITAL path */
+        SOURCE_TS_BDA,         /* ts1_source, disable */
+        NOT_SUPPORTED,         /* ts2_source */
+        NOT_SUPPORTED,         /* analog source */
+
+        0,                     /* digital_index  */
+        0,                     /* analog index */
+        0,                     /* dif_index */
+        0,                     /* external_index */
+
+        1,                     /* only one configuration */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index  = 2 */
+           1,                  /* ts1 index */
+           NOT_SUPPORTED,      /* TS2 index */
+           NOT_SUPPORTED,      /* AUDIO */
+           NOT_SUPPORTED,      /* VIDEO */
+           NOT_SUPPORTED,      /* VANC */
+           NOT_SUPPORTED,      /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        ,
+        /* full-speed */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index  = 2 */
+           1,                  /* ts1 index */
+           NOT_SUPPORTED,      /* TS2 index */
+           NOT_SUPPORTED,      /* AUDIO */
+           NOT_SUPPORTED,      /* VIDEO */
+           NOT_SUPPORTED,      /* VANC */
+           NOT_SUPPORTED,      /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        }
+       ,
+       {
+        INDEX_BUSPOWER_ANALOG_ONLY,    /* index */
+        USB_BUS_POWER,         /* power_type */
+        0,                     /* speed , not decide yet */
+        MOD_ANALOG,            /* mode ,analog tv AND DIGITAL path */
+        NOT_SUPPORTED,         /* ts1_source, disable */
+        NOT_SUPPORTED,         /* ts2_source */
+        SOURCE_ANALOG,         /* analog source--analog */
+        0,                     /* digital_index  */
+        0,                     /* analog index */
+        0,                     /* dif_index */
+        0,                     /* external_index */
+        1,                     /* only one configuration */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           NOT_SUPPORTED,      /* ts1 index */
+           NOT_SUPPORTED,      /* TS2 index */
+           1,                  /* AUDIO */
+           2,                  /* VIDEO */
+           3,                  /* VANC */
+           4,                  /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        ,
+        {                      /* full-speed */
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           NOT_SUPPORTED,      /* ts1 index */
+           NOT_SUPPORTED,      /* TS2 index */
+           1,                  /* AUDIO */
+           2,                  /* VIDEO */
+           NOT_SUPPORTED,      /* VANC */
+           NOT_SUPPORTED,      /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        }
+       ,
+       {
+        INDEX_BUSPOWER_DIF_ONLY,       /* index */
+        USB_BUS_POWER,         /* power_type */
+        0,                     /* speed , not decide yet */
+        /* mode ,analog tv AND DIGITAL path */
+        MOD_DIF | MOD_ANALOG | MOD_DIGITAL | MOD_EXTERNAL,
+        SOURCE_TS_BDA,         /* ts1_source, disable */
+        NOT_SUPPORTED,         /* ts2_source */
+        SOURCE_DIF | SOURCE_ANALOG | SOURCE_EXTERNAL,  /* analog source, dif */
+        0,                     /* digital_index  */
+        0,                     /* analog index */
+        0,                     /* dif_index */
+        0,                     /* external_index */
+        1,                     /* only one configuration */
+        {
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           1,                  /* ts1 index */
+           NOT_SUPPORTED,      /* TS2 index */
+           2,                  /* AUDIO */
+           3,                  /* VIDEO */
+           4,                  /* VANC */
+           5,                  /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        ,
+        {                      /* full speed */
+         {
+          0,                   /* config index */
+          {
+           0,                  /* interrupt ep index */
+           1,                  /* ts1 index */
+           NOT_SUPPORTED,      /* TS2 index */
+           2,                  /* AUDIO */
+           3,                  /* VIDEO */
+           NOT_SUPPORTED,      /* VANC */
+           NOT_SUPPORTED,      /* HANC */
+           NOT_SUPPORTED       /* ir_index */
+           }
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         ,
+         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
+                          NOT_SUPPORTED}
+          }
+         }
+        }
+       ,
+
+};
+
+/*****************************************************************/
+
+u32 initialize_cx231xx(struct cx231xx *dev)
+{
+       u32 config_info = 0;
+       struct pcb_config *p_pcb_info;
+       u8 usb_speed = 1;       /* from register,1--HS, 0--FS  */
+       u8 data[4] = { 0, 0, 0, 0 };
+       u32 ts1_source = 0;
+       u32 ts2_source = 0;
+       u32 analog_source = 0;
+       u8 _current_scenario_idx = 0xff;
+
+       ts1_source = SOURCE_TS_BDA;
+       ts2_source = SOURCE_TS_BDA;
+
+       /* read board config register to find out which
+       pcb config it is related to */
+       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, data, 4);
+
+       config_info = *((u32 *) data);
+       usb_speed = (u8) (config_info & 0x1);
+
+       /* Verify this device belongs to Bus power or Self power device */
+       if (config_info & BUS_POWER) {  /* bus-power */
+               switch (config_info & BUSPOWER_MASK) {
+               case TS1_PORT | BUS_POWER:
+                       cx231xx_Scenario[INDEX_BUSPOWER_DIGITAL_ONLY].speed =
+                           usb_speed;
+                       p_pcb_info =
+                           &cx231xx_Scenario[INDEX_BUSPOWER_DIGITAL_ONLY];
+                       _current_scenario_idx = INDEX_BUSPOWER_DIGITAL_ONLY;
+                       break;
+               case AVDEC_ENABLE | BUS_POWER:
+                       cx231xx_Scenario[INDEX_BUSPOWER_ANALOG_ONLY].speed =
+                           usb_speed;
+                       p_pcb_info =
+                           &cx231xx_Scenario[INDEX_BUSPOWER_ANALOG_ONLY];
+                       _current_scenario_idx = INDEX_BUSPOWER_ANALOG_ONLY;
+                       break;
+               case AVDEC_ENABLE | BUS_POWER | TS1_PORT:
+                       cx231xx_Scenario[INDEX_BUSPOWER_DIF_ONLY].speed =
+                           usb_speed;
+                       p_pcb_info = &cx231xx_Scenario[INDEX_BUSPOWER_DIF_ONLY];
+                       _current_scenario_idx = INDEX_BUSPOWER_DIF_ONLY;
+                       break;
+               default:
+                       cx231xx_info("bad config in buspower!!!!\n");
+                       cx231xx_info("config_info=%x\n",
+                                    (config_info & BUSPOWER_MASK));
+                       return 1;
+               }
+       } else {                /* self-power */
+
+               switch (config_info & SELFPOWER_MASK) {
+               case TS1_PORT | SELF_POWER:
+                       cx231xx_Scenario[INDEX_SELFPOWER_DIGITAL_ONLY].speed =
+                           usb_speed;
+                       p_pcb_info =
+                           &cx231xx_Scenario[INDEX_SELFPOWER_DIGITAL_ONLY];
+                       _current_scenario_idx = INDEX_SELFPOWER_DIGITAL_ONLY;
+                       break;
+               case TS1_TS2_PORT | SELF_POWER:
+                       cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL].speed =
+                           usb_speed;
+                       cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL].
+                           ts2_source = ts2_source;
+                       p_pcb_info =
+                           &cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL];
+                       _current_scenario_idx = INDEX_SELFPOWER_DUAL_DIGITAL;
+                       break;
+               case AVDEC_ENABLE | SELF_POWER:
+                       cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY].speed =
+                           usb_speed;
+                       cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY].
+                           analog_source = analog_source;
+                       p_pcb_info =
+                           &cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY];
+                       _current_scenario_idx = INDEX_SELFPOWER_ANALOG_ONLY;
+                       break;
+               case AVDEC_ENABLE | TS1_PORT | SELF_POWER:
+                       cx231xx_Scenario[INDEX_SELFPOWER_DUAL].speed =
+                           usb_speed;
+                       cx231xx_Scenario[INDEX_SELFPOWER_DUAL].ts1_source =
+                           ts1_source;
+                       cx231xx_Scenario[INDEX_SELFPOWER_DUAL].analog_source =
+                           analog_source;
+                       p_pcb_info = &cx231xx_Scenario[INDEX_SELFPOWER_DUAL];
+                       _current_scenario_idx = INDEX_SELFPOWER_DUAL;
+                       break;
+               case AVDEC_ENABLE | TS1_TS2_PORT | SELF_POWER:
+                       cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].speed =
+                           usb_speed;
+                       cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].ts1_source =
+                           ts1_source;
+                       cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].ts2_source =
+                           ts2_source;
+                       cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].analog_source =
+                           analog_source;
+                       p_pcb_info = &cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE];
+                       _current_scenario_idx = INDEX_SELFPOWER_TRIPLE;
+                       break;
+               case AVDEC_ENABLE | TS1VIP_TS2_PORT | SELF_POWER:
+                       cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR].speed =
+                           usb_speed;
+                       cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR].
+                           analog_source = analog_source;
+                       p_pcb_info =
+                           &cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR];
+                       _current_scenario_idx = INDEX_SELFPOWER_COMPRESSOR;
+                       break;
+               default:
+                       cx231xx_info("bad senario!!!!!\n");
+                       cx231xx_info("config_info=%x\n",
+                                    (config_info & SELFPOWER_MASK));
+                       return 1;
+               }
+       }
+
+       dev->current_scenario_idx = _current_scenario_idx;
+
+       memcpy(&dev->current_pcb_config, p_pcb_info,
+                  sizeof(struct pcb_config));
+
+       if (pcb_debug) {
+               cx231xx_info("SC(0x00) register = 0x%x\n", config_info);
+               cx231xx_info("scenario %d\n",
+                           (dev->current_pcb_config.index) + 1);
+               cx231xx_info("type=%x\n", dev->current_pcb_config.type);
+               cx231xx_info("mode=%x\n", dev->current_pcb_config.mode);
+               cx231xx_info("speed=%x\n", dev->current_pcb_config.speed);
+               cx231xx_info("ts1_source=%x\n",
+                            dev->current_pcb_config.ts1_source);
+               cx231xx_info("ts2_source=%x\n",
+                            dev->current_pcb_config.ts2_source);
+               cx231xx_info("analog_source=%x\n",
+                            dev->current_pcb_config.analog_source);
+       }
+
+       return 0;
+}
diff --git a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h
new file mode 100644 (file)
index 0000000..f5e46e8
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+   cx231xx-pcb-cfg.h - driver for Conexant
+               Cx23100/101/102 USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot 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.
+
+   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.
+ */
+
+#ifndef _PCB_CONFIG_H_
+#define _PCB_CONFIG_H_
+
+#include <linux/init.h>
+#include <linux/module.h>
+
+/***************************************************************************
+                               * Class Information *
+***************************************************************************/
+#define CLASS_DEFAULT       0xFF
+
+enum VENDOR_REQUEST_TYPE {
+       /* Set/Get I2C */
+       VRT_SET_I2C0 = 0x0,
+       VRT_SET_I2C1 = 0x1,
+       VRT_SET_I2C2 = 0x2,
+       VRT_GET_I2C0 = 0x4,
+       VRT_GET_I2C1 = 0x5,
+       VRT_GET_I2C2 = 0x6,
+
+       /* Set/Get GPIO */
+       VRT_SET_GPIO = 0x8,
+       VRT_GET_GPIO = 0x9,
+
+       /* Set/Get GPIE */
+       VRT_SET_GPIE = 0xA,
+       VRT_GET_GPIE = 0xB,
+
+       /* Set/Get Register Control/Status */
+       VRT_SET_REGISTER = 0xC,
+       VRT_GET_REGISTER = 0xD,
+
+       /* Get Extended Compat ID Descriptor */
+       VRT_GET_EXTCID_DESC = 0xFF,
+};
+
+enum BYTE_ENABLE_MASK {
+       ENABLE_ONE_BYTE = 0x1,
+       ENABLE_TWE_BYTE = 0x3,
+       ENABLE_THREE_BYTE = 0x7,
+       ENABLE_FOUR_BYTE = 0xF,
+};
+
+#define SPEED_MASK      0x1
+enum USB_SPEED{
+       FULL_SPEED = 0x0,       /* 0: full speed */
+       HIGH_SPEED = 0x1        /* 1: high speed */
+};
+
+enum _true_false{
+       FALSE = 0,
+       TRUE = 1
+};
+
+#define TS_MASK         0x6
+enum TS_PORT{
+       NO_TS_PORT = 0x0,       /* 2'b00: Neither port used. PCB not a Hybrid,
+                                  only offers Analog TV or Video */
+       TS1_PORT = 0x4,         /* 2'b10: TS1 Input (Hybrid mode :
+                               Digital or External Analog/Compressed source) */
+       TS1_TS2_PORT = 0x6,     /* 2'b11: TS1 & TS2 Inputs
+                               (Dual inputs from Digital and/or
+                               External Analog/Compressed sources) */
+       TS1_EXT_CLOCK = 0x6,    /* 2'b11: TS1 & TS2 as selector
+                                               to external clock */
+       TS1VIP_TS2_PORT = 0x2   /* 2'b01: TS1 used as 656/VIP Output,
+                                  TS2 Input (from Compressor) */
+};
+
+#define EAVP_MASK       0x8
+enum EAV_PRESENT{
+       NO_EXTERNAL_AV = 0x0,   /* 0: No External A/V inputs
+                                               (no need for i2s blcok),
+                                               Analog Tuner must be present */
+       EXTERNAL_AV = 0x8       /* 1: External A/V inputs
+                                               present (requires i2s blk) */
+};
+
+#define ATM_MASK        0x30
+enum AT_MODE{
+       DIF_TUNER = 0x30,       /* 2'b11: IF Tuner (requires use of DIF) */
+       BASEBAND_SOUND = 0x20,  /* 2'b10: Baseband Composite &
+                                               Sound-IF Signals present */
+       NO_TUNER = 0x10         /* 2'b0x: No Analog Tuner present */
+};
+
+#define PWR_SEL_MASK    0x40
+enum POWE_TYPE{
+       SELF_POWER = 0x0,       /* 0: self power */
+       BUS_POWER = 0x40        /* 1: bus power */
+};
+
+enum USB_POWE_TYPE{
+       USB_SELF_POWER = 0,
+       USB_BUS_POWER
+};
+
+#define BO_0_MASK       0x80
+enum AVDEC_STATUS{
+       AVDEC_DISABLE = 0x0,    /* 0: A/V Decoder Disabled */
+       AVDEC_ENABLE = 0x80     /* 1: A/V Decoder Enabled */
+};
+
+#define BO_1_MASK       0x100
+
+#define BUSPOWER_MASK   0xC4   /* for Polaris spec 0.8 */
+#define SELFPOWER_MASK  0x86
+
+/***************************************************************************/
+#define NOT_DECIDE_YET  0xFE
+#define NOT_SUPPORTED   0xFF
+
+/***************************************************************************
+                               * for mod field use *
+***************************************************************************/
+#define MOD_DIGITAL     0x1
+#define MOD_ANALOG      0x2
+#define MOD_DIF         0x4
+#define MOD_EXTERNAL    0x8
+#define CAP_ALL_MOD     0x0f
+
+/***************************************************************************
+                               * source define *
+***************************************************************************/
+#define SOURCE_DIGITAL          0x1
+#define SOURCE_ANALOG           0x2
+#define SOURCE_DIF              0x4
+#define SOURCE_EXTERNAL         0x8
+#define SOURCE_TS_BDA                  0x10
+#define SOURCE_TS_ENCODE               0x20
+#define SOURCE_TS_EXTERNAL     0x40
+
+/***************************************************************************
+                               * interface information define *
+***************************************************************************/
+struct INTERFACE_INFO {
+       u8 interrupt_index;
+       u8 ts1_index;
+       u8 ts2_index;
+       u8 audio_index;
+       u8 video_index;
+       u8 vanc_index;          /* VBI */
+       u8 hanc_index;          /* Sliced CC */
+       u8 ir_index;
+};
+
+enum INDEX_INTERFACE_INFO{
+       INDEX_INTERRUPT = 0x0,
+       INDEX_TS1,
+       INDEX_TS2,
+       INDEX_AUDIO,
+       INDEX_VIDEO,
+       INDEX_VANC,
+       INDEX_HANC,
+       INDEX_IR,
+};
+
+/***************************************************************************
+                               * configuration information define *
+***************************************************************************/
+struct CONFIG_INFO {
+       u8 config_index;
+       struct INTERFACE_INFO interface_info;
+};
+
+struct pcb_config {
+       u8 index;
+       u8 type;                /* bus power or self power,
+                                          self power--0, bus_power--1 */
+       u8 speed;               /* usb speed, 2.0--1, 1.1--0 */
+       u8 mode;                /* digital , anlog, dif or external A/V */
+       u32 ts1_source;         /* three source -- BDA,External,encode */
+       u32 ts2_source;
+       u32 analog_source;
+       u8 digital_index;       /* bus-power used */
+       u8 analog_index;        /* bus-power used */
+       u8 dif_index;           /* bus-power used */
+       u8 external_index;      /* bus-power used */
+       u8 config_num;          /* current config num, 0,1,2,
+                                                  for self-power, always 0 */
+       struct CONFIG_INFO hs_config_info[3];
+       struct CONFIG_INFO fs_config_info[3];
+};
+
+enum INDEX_PCB_CONFIG{
+       INDEX_SELFPOWER_DIGITAL_ONLY = 0x0,
+       INDEX_SELFPOWER_DUAL_DIGITAL,
+       INDEX_SELFPOWER_ANALOG_ONLY,
+       INDEX_SELFPOWER_DUAL,
+       INDEX_SELFPOWER_TRIPLE,
+       INDEX_SELFPOWER_COMPRESSOR,
+       INDEX_BUSPOWER_DIGITAL_ONLY,
+       INDEX_BUSPOWER_ANALOG_ONLY,
+       INDEX_BUSPOWER_DIF_ONLY,
+       INDEX_BUSPOWER_EXTERNAL_ONLY,
+       INDEX_BUSPOWER_EXTERNAL_ANALOG,
+       INDEX_BUSPOWER_EXTERNAL_DIF,
+       INDEX_BUSPOWER_EXTERNAL_DIGITAL,
+       INDEX_BUSPOWER_DIGITAL_ANALOG,
+       INDEX_BUSPOWER_DIGITAL_DIF,
+       INDEX_BUSPOWER_DIGITAL_ANALOG_EXTERNAL,
+       INDEX_BUSPOWER_DIGITAL_DIF_EXTERNAL,
+};
+
+/***************************************************************************/
+struct cx231xx;
+
+u32 initialize_cx231xx(struct cx231xx *p_dev);
+
+#endif
diff --git a/drivers/media/usb/cx231xx/cx231xx-reg.h b/drivers/media/usb/cx231xx/cx231xx-reg.h
new file mode 100644 (file)
index 0000000..750c5d3
--- /dev/null
@@ -0,0 +1,1564 @@
+/*
+   cx231xx-reg.h - driver for Conexant Cx23100/101/102
+              USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot 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.
+
+   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.
+ */
+
+#ifndef _CX231XX_REG_H
+#define _CX231XX_REG_H
+
+/*****************************************************************************
+                               * VBI codes *
+*****************************************************************************/
+
+#define SAV_ACTIVE_VIDEO_FIELD1                0x80
+#define EAV_ACTIVE_VIDEO_FIELD1                0x90
+
+#define SAV_ACTIVE_VIDEO_FIELD2                0xc0
+#define EAV_ACTIVE_VIDEO_FIELD2                0xd0
+
+#define SAV_VBLANK_FIELD1              0xa0
+#define EAV_VBLANK_FIELD1              0xb0
+
+#define SAV_VBLANK_FIELD2              0xe0
+#define EAV_VBLANK_FIELD2              0xf0
+
+#define SAV_VBI_FIELD1                 0x20
+#define EAV_VBI_FIELD1                 0x30
+
+#define SAV_VBI_FIELD2                 0x60
+#define EAV_VBI_FIELD2                 0x70
+
+/*****************************************************************************/
+/* Audio ADC Registers */
+#define CH_PWR_CTRL1                   0x0000000e
+#define CH_PWR_CTRL2                   0x0000000f
+/*****************************************************************************/
+
+#define      HOST_REG1                0x000
+#define      FLD_FORCE_CHIP_SEL       0x80
+#define      FLD_AUTO_INC_DIS         0x20
+#define      FLD_PREFETCH_EN          0x10
+/* Reserved [2:3] */
+#define      FLD_DIGITAL_PWR_DN       0x02
+#define      FLD_SLEEP                0x01
+
+/*****************************************************************************/
+#define      HOST_REG2                0x001
+
+/*****************************************************************************/
+#define      HOST_REG3                0x002
+
+/*****************************************************************************/
+/* added for polaris */
+#define      GPIO_PIN_CTL0            0x3
+#define      GPIO_PIN_CTL1            0x4
+#define      GPIO_PIN_CTL2            0x5
+#define      GPIO_PIN_CTL3            0x6
+#define      TS1_PIN_CTL0             0x7
+#define      TS1_PIN_CTL1             0x8
+/*****************************************************************************/
+
+#define      FLD_CLK_IN_EN            0x80
+#define      FLD_XTAL_CTRL            0x70
+#define      FLD_BB_CLK_MODE          0x0C
+#define      FLD_REF_DIV_PLL          0x02
+#define      FLD_REF_SEL_PLL1         0x01
+
+/*****************************************************************************/
+#define      CHIP_CTRL                0x100
+/* Reserved [27] */
+/* Reserved [31:21] */
+#define      FLD_CHIP_ACFG_DIS        0x00100000
+/* Reserved [19] */
+#define      FLD_DUAL_MODE_ADC2       0x00040000
+#define      FLD_SIF_EN               0x00020000
+#define      FLD_SOFT_RST             0x00010000
+#define      FLD_DEVICE_ID            0x0000ffff
+
+/*****************************************************************************/
+#define      AFE_CTRL                 0x104
+#define      AFE_CTRL_C2HH_SRC_CTRL   0x104
+#define      FLD_DIF_OUT_SEL          0xc0000000
+#define      FLD_AUX_PLL_CLK_ALT_SEL  0x3c000000
+#define      FLD_UV_ORDER_MODE        0x02000000
+#define      FLD_FUNC_MODE            0x01800000
+#define      FLD_ROT1_PHASE_CTL       0x007f8000
+#define      FLD_AUD_IN_SEL           0x00004000
+#define      FLD_LUMA_IN_SEL          0x00002000
+#define      FLD_CHROMA_IN_SEL        0x00001000
+/* reserve [11:10] */
+#define      FLD_INV_SPEC_DIS         0x00000200
+#define      FLD_VGA_SEL_CH3          0x00000100
+#define      FLD_VGA_SEL_CH2          0x00000080
+#define      FLD_VGA_SEL_CH1          0x00000040
+#define      FLD_DCR_BYP_CH1          0x00000020
+#define      FLD_DCR_BYP_CH2          0x00000010
+#define      FLD_DCR_BYP_CH3          0x00000008
+#define      FLD_EN_12DB_CH3          0x00000004
+#define      FLD_EN_12DB_CH2          0x00000002
+#define      FLD_EN_12DB_CH1          0x00000001
+
+/* redefine in Cx231xx */
+/*****************************************************************************/
+#define      DC_CTRL1                 0x108
+/* reserve [31:30] */
+#define      FLD_CLAMP_LVL_CH1        0x3fff8000
+#define      FLD_CLAMP_LVL_CH2        0x00007fff
+/*****************************************************************************/
+
+/*****************************************************************************/
+#define      DC_CTRL2                 0x10c
+/* reserve [31:28] */
+#define      FLD_CLAMP_LVL_CH3        0x00fffe00
+#define      FLD_CLAMP_WIND_LENTH     0x000001e0
+#define      FLD_C2HH_SAT_MIN         0x0000001e
+#define      FLD_FLT_BYP_SEL          0x00000001
+/*****************************************************************************/
+
+/*****************************************************************************/
+#define      DC_CTRL3                 0x110
+/* reserve [31:16] */
+#define      FLD_ERR_GAIN_CTL         0x00070000
+#define      FLD_LPF_MIN              0x0000ffff
+/*****************************************************************************/
+
+/*****************************************************************************/
+#define      DC_CTRL4                 0x114
+/* reserve [31:31] */
+#define      FLD_INTG_CH1             0x7fffffff
+/*****************************************************************************/
+
+/*****************************************************************************/
+#define      DC_CTRL5                 0x118
+/* reserve [31:31] */
+#define      FLD_INTG_CH2             0x7fffffff
+/*****************************************************************************/
+
+/*****************************************************************************/
+#define      DC_CTRL6                 0x11c
+/* reserve [31:31] */
+#define      FLD_INTG_CH3             0x7fffffff
+/*****************************************************************************/
+
+/*****************************************************************************/
+#define      PIN_CTRL                 0x120
+#define      FLD_OEF_AGC_RF           0x00000001
+#define      FLD_OEF_AGC_IFVGA        0x00000002
+#define      FLD_OEF_AGC_IF           0x00000004
+#define      FLD_REG_BO_PUD           0x80000000
+#define      FLD_IR_IRQ_STAT          0x40000000
+#define      FLD_AUD_IRQ_STAT         0x20000000
+#define      FLD_VID_IRQ_STAT         0x10000000
+/* Reserved [27:26] */
+#define      FLD_IRQ_N_OUT_EN         0x02000000
+#define      FLD_IRQ_N_POLAR          0x01000000
+/* Reserved [23:6] */
+#define      FLD_OE_AUX_PLL_CLK       0x00000020
+#define      FLD_OE_I2S_BCLK          0x00000010
+#define      FLD_OE_I2S_WCLK          0x00000008
+#define      FLD_OE_AGC_IF            0x00000004
+#define      FLD_OE_AGC_IFVGA         0x00000002
+#define      FLD_OE_AGC_RF            0x00000001
+
+/*****************************************************************************/
+#define      AUD_IO_CTRL              0x124
+/* Reserved [31:8] */
+#define      FLD_I2S_PORT_DIR         0x00000080
+#define      FLD_I2S_OUT_SRC          0x00000040
+#define      FLD_AUD_CHAN3_SRC        0x00000030
+#define      FLD_AUD_CHAN2_SRC        0x0000000c
+#define      FLD_AUD_CHAN1_SRC        0x00000003
+
+/*****************************************************************************/
+#define      AUD_LOCK1                0x128
+#define      FLD_AUD_LOCK_KI_SHIFT    0xc0000000
+#define      FLD_AUD_LOCK_KD_SHIFT    0x30000000
+/* Reserved [27:25] */
+#define      FLD_EN_AV_LOCK           0x01000000
+#define      FLD_VID_COUNT            0x00ffffff
+
+/*****************************************************************************/
+#define      AUD_LOCK2                0x12c
+#define      FLD_AUD_LOCK_KI_MULT     0xf0000000
+#define      FLD_AUD_LOCK_KD_MULT     0x0F000000
+/* Reserved [23:22] */
+#define      FLD_AUD_LOCK_FREQ_SHIFT  0x00300000
+#define      FLD_AUD_COUNT            0x000fffff
+
+/*****************************************************************************/
+#define      AFE_DIAG_CTRL1           0x134
+/* Reserved [31:16] */
+#define      FLD_CUV_DLY_LENGTH       0x0000ff00
+#define      FLD_YC_DLY_LENGTH        0x000000ff
+
+/*****************************************************************************/
+/* Poalris redefine */
+#define      AFE_DIAG_CTRL3           0x138
+/* Reserved [31:26] */
+#define      FLD_AUD_DUAL_FLAG_POL    0x02000000
+#define      FLD_VID_DUAL_FLAG_POL    0x01000000
+/* Reserved [23:23] */
+#define      FLD_COL_CLAMP_DIS_CH1    0x00400000
+#define      FLD_COL_CLAMP_DIS_CH2    0x00200000
+#define      FLD_COL_CLAMP_DIS_CH3    0x00100000
+
+#define      TEST_CTRL1               0x144
+/* Reserved [31:29] */
+#define      FLD_LBIST_EN             0x10000000
+/* Reserved [27:10] */
+#define      FLD_FI_BIST_INTR_R       0x0000200
+#define      FLD_FI_BIST_INTR_L       0x0000100
+#define      FLD_BIST_FAIL_AUD_PLL    0x0000080
+#define      FLD_BIST_INTR_AUD_PLL    0x0000040
+#define      FLD_BIST_FAIL_VID_PLL    0x0000020
+#define      FLD_BIST_INTR_VID_PLL    0x0000010
+/* Reserved [3:1] */
+#define      FLD_CIR_TEST_DIS         0x00000001
+
+/*****************************************************************************/
+#define      TEST_CTRL2               0x148
+#define      FLD_TSXCLK_POL_CTL       0x80000000
+#define      FLD_ISO_CTL_SEL          0x40000000
+#define      FLD_ISO_CTL_EN           0x20000000
+#define      FLD_BIST_DEBUGZ          0x10000000
+#define      FLD_AUD_BIST_TEST_H      0x0f000000
+/* Reserved [23:22] */
+#define      FLD_FLTRN_BIST_TEST_H    0x00020000
+#define      FLD_VID_BIST_TEST_H      0x00010000
+/* Reserved [19:17] */
+#define      FLD_BIST_TEST_H          0x00010000
+/* Reserved [15:13] */
+#define      FLD_TAB_EN               0x00001000
+/* Reserved [11:0] */
+
+/*****************************************************************************/
+#define      BIST_STAT                0x14c
+#define      FLD_AUD_BIST_FAIL_H      0xfff00000
+#define      FLD_FLTRN_BIST_FAIL_H    0x00180000
+#define      FLD_VID_BIST_FAIL_H      0x00070000
+#define      FLD_AUD_BIST_TST_DONE    0x0000fff0
+#define      FLD_FLTRN_BIST_TST_DONE  0x00000008
+#define      FLD_VID_BIST_TST_DONE    0x00000007
+
+/*****************************************************************************/
+/* DirectIF registers definition have been moved to DIF_reg.h                */
+/*****************************************************************************/
+#define      MODE_CTRL                0x400
+#define      FLD_AFD_PAL60_DIS        0x20000000
+#define      FLD_AFD_FORCE_SECAM      0x10000000
+#define      FLD_AFD_FORCE_PALNC      0x08000000
+#define      FLD_AFD_FORCE_PAL        0x04000000
+#define      FLD_AFD_PALM_SEL         0x03000000
+#define      FLD_CKILL_MODE           0x00300000
+#define      FLD_COMB_NOTCH_MODE      0x00c00000       /* bit[19:18] */
+#define      FLD_CLR_LOCK_STAT        0x00020000
+#define      FLD_FAST_LOCK_MD         0x00010000
+#define      FLD_WCEN                 0x00008000
+#define      FLD_CAGCEN               0x00004000
+#define      FLD_CKILLEN              0x00002000
+#define      FLD_AUTO_SC_LOCK         0x00001000
+#define      FLD_MAN_SC_FAST_LOCK     0x00000800
+#define      FLD_INPUT_MODE           0x00000600
+#define      FLD_AFD_ACQUIRE          0x00000100
+#define      FLD_AFD_NTSC_SEL         0x00000080
+#define      FLD_AFD_PAL_SEL          0x00000040
+#define      FLD_ACFG_DIS             0x00000020
+#define      FLD_SQ_PIXEL             0x00000010
+#define      FLD_VID_FMT_SEL          0x0000000f
+
+/*****************************************************************************/
+#define      OUT_CTRL1                0x404
+#define      FLD_POLAR                0x7f000000
+/* Reserved [23] */
+#define      FLD_RND_MODE             0x00600000
+#define      FLD_VIPCLAMP_EN          0x00100000
+#define      FLD_VIPBLANK_EN          0x00080000
+#define      FLD_VIP_OPT_AL           0x00040000
+#define      FLD_IDID0_SOURCE         0x00020000
+#define      FLD_DCMODE               0x00010000
+#define      FLD_CLK_GATING           0x0000c000
+#define      FLD_CLK_INVERT           0x00002000
+#define      FLD_HSFMT                0x00001000
+#define      FLD_VALIDFMT             0x00000800
+#define      FLD_ACTFMT               0x00000400
+#define      FLD_SWAPRAW              0x00000200
+#define      FLD_CLAMPRAW_EN          0x00000100
+#define      FLD_BLUE_FIELD_EN        0x00000080
+#define      FLD_BLUE_FIELD_ACT       0x00000040
+#define      FLD_TASKBIT_VAL          0x00000020
+#define      FLD_ANC_DATA_EN          0x00000010
+#define      FLD_VBIHACTRAW_EN        0x00000008
+#define      FLD_MODE10B              0x00000004
+#define      FLD_OUT_MODE             0x00000003
+
+/*****************************************************************************/
+#define      OUT_CTRL2                0x408
+#define      FLD_AUD_GRP              0xc0000000
+#define      FLD_SAMPLE_RATE          0x30000000
+#define      FLD_AUD_ANC_EN           0x08000000
+#define      FLD_EN_C                 0x04000000
+#define      FLD_EN_B                 0x02000000
+#define      FLD_EN_A                 0x01000000
+/* Reserved [23:20] */
+#define      FLD_IDID1_LSB            0x000c0000
+#define      FLD_IDID0_LSB            0x00030000
+#define      FLD_IDID1_MSB            0x0000ff00
+#define      FLD_IDID0_MSB            0x000000ff
+
+/*****************************************************************************/
+#define      GEN_STAT                 0x40c
+#define      FLD_VCR_DETECT           0x00800000
+#define      FLD_SPECIAL_PLAY_N       0x00400000
+#define      FLD_VPRES                0x00200000
+#define      FLD_AGC_LOCK             0x00100000
+#define      FLD_CSC_LOCK             0x00080000
+#define      FLD_VLOCK                0x00040000
+#define      FLD_SRC_LOCK             0x00020000
+#define      FLD_HLOCK                0x00010000
+#define      FLD_VSYNC_N              0x00008000
+#define      FLD_SRC_FIFO_UFLOW       0x00004000
+#define      FLD_SRC_FIFO_OFLOW       0x00002000
+#define      FLD_FIELD                0x00001000
+#define      FLD_AFD_FMT_STAT         0x00000f00
+#define      FLD_MV_TYPE2_PAIR        0x00000080
+#define      FLD_MV_T3CS              0x00000040
+#define      FLD_MV_CS                0x00000020
+#define      FLD_MV_PSP               0x00000010
+/* Reserved [3] */
+#define      FLD_MV_CDAT              0x00000003
+
+/*****************************************************************************/
+#define      INT_STAT_MASK            0x410
+#define      FLD_COMB_3D_FIFO_MSK     0x80000000
+#define      FLD_WSS_DAT_AVAIL_MSK    0x40000000
+#define      FLD_GS2_DAT_AVAIL_MSK    0x20000000
+#define      FLD_GS1_DAT_AVAIL_MSK    0x10000000
+#define      FLD_CC_DAT_AVAIL_MSK     0x08000000
+#define      FLD_VPRES_CHANGE_MSK     0x04000000
+#define      FLD_MV_CHANGE_MSK        0x02000000
+#define      FLD_END_VBI_EVEN_MSK     0x01000000
+#define      FLD_END_VBI_ODD_MSK      0x00800000
+#define      FLD_FMT_CHANGE_MSK       0x00400000
+#define      FLD_VSYNC_TRAIL_MSK      0x00200000
+#define      FLD_HLOCK_CHANGE_MSK     0x00100000
+#define      FLD_VLOCK_CHANGE_MSK     0x00080000
+#define      FLD_CSC_LOCK_CHANGE_MSK  0x00040000
+#define      FLD_SRC_FIFO_UFLOW_MSK   0x00020000
+#define      FLD_SRC_FIFO_OFLOW_MSK   0x00010000
+#define      FLD_COMB_3D_FIFO_STAT    0x00008000
+#define      FLD_WSS_DAT_AVAIL_STAT   0x00004000
+#define      FLD_GS2_DAT_AVAIL_STAT   0x00002000
+#define      FLD_GS1_DAT_AVAIL_STAT   0x00001000
+#define      FLD_CC_DAT_AVAIL_STAT    0x00000800
+#define      FLD_VPRES_CHANGE_STAT    0x00000400
+#define      FLD_MV_CHANGE_STAT       0x00000200
+#define      FLD_END_VBI_EVEN_STAT    0x00000100
+#define      FLD_END_VBI_ODD_STAT     0x00000080
+#define      FLD_FMT_CHANGE_STAT      0x00000040
+#define      FLD_VSYNC_TRAIL_STAT     0x00000020
+#define      FLD_HLOCK_CHANGE_STAT    0x00000010
+#define      FLD_VLOCK_CHANGE_STAT    0x00000008
+#define      FLD_CSC_LOCK_CHANGE_STAT 0x00000004
+#define      FLD_SRC_FIFO_UFLOW_STAT  0x00000002
+#define      FLD_SRC_FIFO_OFLOW_STAT  0x00000001
+
+/*****************************************************************************/
+#define      LUMA_CTRL                0x414
+#define      BRIGHTNESS_CTRL_BYTE     0x414
+#define      CONTRAST_CTRL_BYTE       0x415
+#define      LUMA_CTRL_BYTE_3         0x416
+#define      FLD_LUMA_CORE_SEL        0x00c00000
+#define      FLD_RANGE                0x00300000
+/* Reserved [19] */
+#define      FLD_PEAK_EN              0x00040000
+#define      FLD_PEAK_SEL             0x00030000
+#define      FLD_CNTRST               0x0000ff00
+#define      FLD_BRITE                0x000000ff
+
+/*****************************************************************************/
+#define      HSCALE_CTRL              0x418
+#define      FLD_HFILT                0x03000000
+#define      FLD_HSCALE               0x00ffffff
+
+/*****************************************************************************/
+#define      VSCALE_CTRL              0x41c
+#define      FLD_LINE_AVG_DIS         0x01000000
+/* Reserved [23:20] */
+#define      FLD_VS_INTRLACE          0x00080000
+#define      FLD_VFILT                0x00070000
+/* Reserved [15:13] */
+#define      FLD_VSCALE               0x00001fff
+
+/*****************************************************************************/
+#define      CHROMA_CTRL              0x420
+#define      USAT_CTRL_BYTE           0x420
+#define      VSAT_CTRL_BYTE           0x421
+#define      HUE_CTRL_BYTE            0x422
+#define      FLD_C_LPF_EN             0x20000000
+#define      FLD_CHR_DELAY            0x1c000000
+#define      FLD_C_CORE_SEL           0x03000000
+#define      FLD_HUE                  0x00ff0000
+#define      FLD_VSAT                 0x0000ff00
+#define      FLD_USAT                 0x000000ff
+
+/*****************************************************************************/
+#define      VBI_LINE_CTRL1           0x424
+#define      FLD_VBI_MD_LINE4         0xff000000
+#define      FLD_VBI_MD_LINE3         0x00ff0000
+#define      FLD_VBI_MD_LINE2         0x0000ff00
+#define      FLD_VBI_MD_LINE1         0x000000ff
+
+/*****************************************************************************/
+#define      VBI_LINE_CTRL2           0x428
+#define      FLD_VBI_MD_LINE8         0xff000000
+#define      FLD_VBI_MD_LINE7         0x00ff0000
+#define      FLD_VBI_MD_LINE6         0x0000ff00
+#define      FLD_VBI_MD_LINE5         0x000000ff
+
+/*****************************************************************************/
+#define      VBI_LINE_CTRL3           0x42c
+#define      FLD_VBI_MD_LINE12        0xff000000
+#define      FLD_VBI_MD_LINE11        0x00ff0000
+#define      FLD_VBI_MD_LINE10        0x0000ff00
+#define      FLD_VBI_MD_LINE9         0x000000ff
+
+/*****************************************************************************/
+#define      VBI_LINE_CTRL4           0x430
+#define      FLD_VBI_MD_LINE16        0xff000000
+#define      FLD_VBI_MD_LINE15        0x00ff0000
+#define      FLD_VBI_MD_LINE14        0x0000ff00
+#define      FLD_VBI_MD_LINE13        0x000000ff
+
+/*****************************************************************************/
+#define      VBI_LINE_CTRL5           0x434
+#define      FLD_VBI_MD_LINE17        0x000000ff
+
+/*****************************************************************************/
+#define      VBI_FC_CFG               0x438
+#define      FLD_FC_ALT2              0xff000000
+#define      FLD_FC_ALT1              0x00ff0000
+#define      FLD_FC_ALT2_TYPE         0x0000f000
+#define      FLD_FC_ALT1_TYPE         0x00000f00
+/* Reserved [7:1] */
+#define      FLD_FC_SEARCH_MODE       0x00000001
+
+/*****************************************************************************/
+#define      VBI_MISC_CFG1            0x43c
+#define      FLD_TTX_PKTADRU          0xfff00000
+#define      FLD_TTX_PKTADRL          0x000fff00
+/* Reserved [7:6] */
+#define      FLD_MOJI_PACK_DIS        0x00000020
+#define      FLD_VPS_DEC_DIS          0x00000010
+#define      FLD_CRI_MARG_SCALE       0x0000000c
+#define      FLD_EDGE_RESYNC_EN       0x00000002
+#define      FLD_ADAPT_SLICE_DIS      0x00000001
+
+/*****************************************************************************/
+#define      VBI_MISC_CFG2            0x440
+#define      FLD_HAMMING_TYPE         0x0f000000
+/* Reserved [23:20] */
+#define      FLD_WSS_FIFO_RST         0x00080000
+#define      FLD_GS2_FIFO_RST         0x00040000
+#define      FLD_GS1_FIFO_RST         0x00020000
+#define      FLD_CC_FIFO_RST          0x00010000
+/* Reserved [15:12] */
+#define      FLD_VBI3_SDID            0x00000f00
+#define      FLD_VBI2_SDID            0x000000f0
+#define      FLD_VBI1_SDID            0x0000000f
+
+/*****************************************************************************/
+#define      VBI_PAY1                 0x444
+#define      FLD_GS1_FIFO_DAT         0xFF000000
+#define      FLD_GS1_STAT             0x00FF0000
+#define      FLD_CC_FIFO_DAT          0x0000FF00
+#define      FLD_CC_STAT              0x000000FF
+
+/*****************************************************************************/
+#define      VBI_PAY2                 0x448
+#define      FLD_WSS_FIFO_DAT         0xff000000
+#define      FLD_WSS_STAT             0x00ff0000
+#define      FLD_GS2_FIFO_DAT         0x0000ff00
+#define      FLD_GS2_STAT             0x000000ff
+
+/*****************************************************************************/
+#define      VBI_CUST1_CFG1           0x44c
+/* Reserved [31] */
+#define      FLD_VBI1_CRIWIN          0x7f000000
+#define      FLD_VBI1_SLICE_DIST      0x00f00000
+#define      FLD_VBI1_BITINC          0x000fff00
+#define      FLD_VBI1_HDELAY          0x000000ff
+
+/*****************************************************************************/
+#define      VBI_CUST1_CFG2           0x450
+#define      FLD_VBI1_FC_LENGTH       0x1f000000
+#define      FLD_VBI1_FRAME_CODE      0x00ffffff
+
+/*****************************************************************************/
+#define      VBI_CUST1_CFG3           0x454
+#define      FLD_VBI1_HAM_EN          0x80000000
+#define      FLD_VBI1_FIFO_MODE       0x70000000
+#define      FLD_VBI1_FORMAT_TYPE     0x0f000000
+#define      FLD_VBI1_PAYLD_LENGTH    0x00ff0000
+#define      FLD_VBI1_CRI_LENGTH      0x0000f000
+#define      FLD_VBI1_CRI_MARGIN      0x00000f00
+#define      FLD_VBI1_CRI_TIME        0x000000ff
+
+/*****************************************************************************/
+#define      VBI_CUST2_CFG1           0x458
+/* Reserved [31] */
+#define      FLD_VBI2_CRIWIN          0x7f000000
+#define      FLD_VBI2_SLICE_DIST      0x00f00000
+#define      FLD_VBI2_BITINC          0x000fff00
+#define      FLD_VBI2_HDELAY          0x000000ff
+
+/*****************************************************************************/
+#define      VBI_CUST2_CFG2           0x45c
+#define      FLD_VBI2_FC_LENGTH       0x1f000000
+#define      FLD_VBI2_FRAME_CODE      0x00ffffff
+
+/*****************************************************************************/
+#define      VBI_CUST2_CFG3           0x460
+#define      FLD_VBI2_HAM_EN          0x80000000
+#define      FLD_VBI2_FIFO_MODE       0x70000000
+#define      FLD_VBI2_FORMAT_TYPE     0x0f000000
+#define      FLD_VBI2_PAYLD_LENGTH    0x00ff0000
+#define      FLD_VBI2_CRI_LENGTH      0x0000f000
+#define      FLD_VBI2_CRI_MARGIN      0x00000f00
+#define      FLD_VBI2_CRI_TIME        0x000000ff
+
+/*****************************************************************************/
+#define      VBI_CUST3_CFG1           0x464
+/* Reserved [31] */
+#define      FLD_VBI3_CRIWIN          0x7f000000
+#define      FLD_VBI3_SLICE_DIST      0x00f00000
+#define      FLD_VBI3_BITINC          0x000fff00
+#define      FLD_VBI3_HDELAY          0x000000ff
+
+/*****************************************************************************/
+#define      VBI_CUST3_CFG2           0x468
+#define      FLD_VBI3_FC_LENGTH       0x1f000000
+#define      FLD_VBI3_FRAME_CODE      0x00ffffff
+
+/*****************************************************************************/
+#define      VBI_CUST3_CFG3           0x46c
+#define      FLD_VBI3_HAM_EN          0x80000000
+#define      FLD_VBI3_FIFO_MODE       0x70000000
+#define      FLD_VBI3_FORMAT_TYPE     0x0f000000
+#define      FLD_VBI3_PAYLD_LENGTH    0x00ff0000
+#define      FLD_VBI3_CRI_LENGTH      0x0000f000
+#define      FLD_VBI3_CRI_MARGIN      0x00000f00
+#define      FLD_VBI3_CRI_TIME        0x000000ff
+
+/*****************************************************************************/
+#define      HORIZ_TIM_CTRL           0x470
+#define      FLD_BGDEL_CNT            0xff000000
+/* Reserved [23:22] */
+#define      FLD_HACTIVE_CNT          0x003ff000
+/* Reserved [11:10] */
+#define      FLD_HBLANK_CNT           0x000003ff
+
+/*****************************************************************************/
+#define      VERT_TIM_CTRL            0x474
+#define      FLD_V656BLANK_CNT        0xff000000
+/* Reserved [23:22] */
+#define      FLD_VACTIVE_CNT          0x003ff000
+/* Reserved [11:10] */
+#define      FLD_VBLANK_CNT           0x000003ff
+
+/*****************************************************************************/
+#define      SRC_COMB_CFG             0x478
+#define      FLD_CCOMB_2LN_CHECK      0x80000000
+#define      FLD_CCOMB_3LN_EN         0x40000000
+#define      FLD_CCOMB_2LN_EN         0x20000000
+#define      FLD_CCOMB_3D_EN          0x10000000
+/* Reserved [27] */
+#define      FLD_LCOMB_3LN_EN         0x04000000
+#define      FLD_LCOMB_2LN_EN         0x02000000
+#define      FLD_LCOMB_3D_EN          0x01000000
+#define      FLD_LUMA_LPF_SEL         0x00c00000
+#define      FLD_UV_LPF_SEL           0x00300000
+#define      FLD_BLEND_SLOPE          0x000f0000
+#define      FLD_CCOMB_REDUCE_EN      0x00008000
+/* Reserved [14:10] */
+#define      FLD_SRC_DECIM_RATIO      0x000003ff
+
+/*****************************************************************************/
+#define      CHROMA_VBIOFF_CFG        0x47c
+#define      FLD_VBI_VOFFSET          0x1f000000
+/* Reserved [23:20] */
+#define      FLD_SC_STEP              0x000fffff
+
+/*****************************************************************************/
+#define      FIELD_COUNT              0x480
+#define      FLD_FIELD_COUNT_FLD      0x000003ff
+
+/*****************************************************************************/
+#define      MISC_TIM_CTRL            0x484
+#define      FLD_DEBOUNCE_COUNT       0xc0000000
+#define      FLD_VT_LINE_CNT_HYST     0x30000000
+/* Reserved [27] */
+#define      FLD_AFD_STAT             0x07ff0000
+#define      FLD_VPRES_VERT_EN        0x00008000
+/* Reserved [14:12] */
+#define      FLD_HR32                 0x00000800
+#define      FLD_TDALGN               0x00000400
+#define      FLD_TDFIELD              0x00000200
+/* Reserved [8:6] */
+#define      FLD_TEMPDEC              0x0000003f
+
+/*****************************************************************************/
+#define      DFE_CTRL1                0x488
+#define      FLD_CLAMP_AUTO_EN        0x80000000
+#define      FLD_AGC_AUTO_EN          0x40000000
+#define      FLD_VGA_CRUSH_EN         0x20000000
+#define      FLD_VGA_AUTO_EN          0x10000000
+#define      FLD_VBI_GATE_EN          0x08000000
+#define      FLD_CLAMP_LEVEL          0x07000000
+/* Reserved [23:22] */
+#define      FLD_CLAMP_SKIP_CNT       0x00300000
+#define      FLD_AGC_GAIN             0x000fff00
+/* Reserved [7:6] */
+#define      FLD_VGA_GAIN             0x0000003f
+
+/*****************************************************************************/
+#define      DFE_CTRL2                0x48c
+#define      FLD_VGA_ACQUIRE_RANGE    0x00ff0000
+#define      FLD_VGA_TRACK_RANGE      0x0000ff00
+#define      FLD_VGA_SYNC             0x000000ff
+
+/*****************************************************************************/
+#define      DFE_CTRL3                0x490
+#define      FLD_BP_PERCENT           0xff000000
+#define      FLD_DFT_THRESHOLD        0x00ff0000
+/* Reserved [15:12] */
+#define      FLD_SYNC_WIDTH_SEL       0x00000600
+#define      FLD_BP_LOOP_GAIN         0x00000300
+#define      FLD_SYNC_LOOP_GAIN       0x000000c0
+/* Reserved [5:4] */
+#define      FLD_AGC_LOOP_GAIN        0x0000000c
+#define      FLD_DCC_LOOP_GAIN        0x00000003
+
+/*****************************************************************************/
+#define      PLL_CTRL                 0x494
+#define      FLD_PLL_KD               0xff000000
+#define      FLD_PLL_KI               0x00ff0000
+#define      FLD_PLL_MAX_OFFSET       0x0000ffff
+
+/*****************************************************************************/
+#define      HTL_CTRL                 0x498
+/* Reserved [31:24] */
+#define      FLD_AUTO_LOCK_SPD        0x00080000
+#define      FLD_MAN_FAST_LOCK        0x00040000
+#define      FLD_HTL_15K_EN           0x00020000
+#define      FLD_HTL_500K_EN          0x00010000
+#define      FLD_HTL_KD               0x0000ff00
+#define      FLD_HTL_KI               0x000000ff
+
+/*****************************************************************************/
+#define      COMB_CTRL                0x49c
+#define      FLD_COMB_PHASE_LIMIT     0xff000000
+#define      FLD_CCOMB_ERR_LIMIT      0x00ff0000
+#define      FLD_LUMA_THRESHOLD       0x0000ff00
+#define      FLD_LCOMB_ERR_LIMIT      0x000000ff
+
+/*****************************************************************************/
+#define      CRUSH_CTRL               0x4a0
+#define      FLD_WTW_EN               0x00400000
+#define      FLD_CRUSH_FREQ           0x00200000
+#define      FLD_MAJ_SEL_EN           0x00100000
+#define      FLD_MAJ_SEL              0x000c0000
+/* Reserved [17:15] */
+#define      FLD_SYNC_TIP_REDUCE      0x00007e00
+/* Reserved [8:6] */
+#define      FLD_SYNC_TIP_INC         0x0000003f
+
+/*****************************************************************************/
+#define      SOFT_RST_CTRL            0x4a4
+#define      FLD_VD_SOFT_RST          0x00008000
+/* Reserved [14:12] */
+#define      FLD_REG_RST_MSK          0x00000800
+#define      FLD_VOF_RST_MSK          0x00000400
+#define      FLD_MVDET_RST_MSK        0x00000200
+#define      FLD_VBI_RST_MSK          0x00000100
+#define      FLD_SCALE_RST_MSK        0x00000080
+#define      FLD_CHROMA_RST_MSK       0x00000040
+#define      FLD_LUMA_RST_MSK         0x00000020
+#define      FLD_VTG_RST_MSK          0x00000010
+#define      FLD_YCSEP_RST_MSK        0x00000008
+#define      FLD_SRC_RST_MSK          0x00000004
+#define      FLD_DFE_RST_MSK          0x00000002
+/* Reserved [0] */
+
+/*****************************************************************************/
+#define      MV_DT_CTRL1              0x4a8
+/* Reserved [31:29] */
+#define      FLD_PSP_STOP_LINE        0x1f000000
+/* Reserved [23:21] */
+#define      FLD_PSP_STRT_LINE        0x001f0000
+/* Reserved [15] */
+#define      FLD_PSP_LLIMW            0x00007f00
+/* Reserved [7] */
+#define      FLD_PSP_ULIMW            0x0000007f
+
+/*****************************************************************************/
+#define      MV_DT_CTRL2              0x4aC
+#define      FLD_CS_STOPWIN           0xff000000
+#define      FLD_CS_STRTWIN           0x00ff0000
+#define      FLD_CS_WIDTH             0x0000ff00
+#define      FLD_PSP_SPEC_VAL         0x000000ff
+
+/*****************************************************************************/
+#define      MV_DT_CTRL3              0x4B0
+#define      FLD_AUTO_RATE_DIS        0x80000000
+#define      FLD_HLOCK_DIS            0x40000000
+#define      FLD_SEL_FIELD_CNT        0x20000000
+#define      FLD_CS_TYPE2_SEL         0x10000000
+#define      FLD_CS_LINE_THRSH_SEL    0x08000000
+#define      FLD_CS_ATHRESH_SEL       0x04000000
+#define      FLD_PSP_SPEC_SEL         0x02000000
+#define      FLD_PSP_LINES_SEL        0x01000000
+#define      FLD_FIELD_CNT            0x00f00000
+#define      FLD_CS_TYPE2_CNT         0x000fc000
+#define      FLD_CS_LINE_CNT          0x00003f00
+#define      FLD_CS_ATHRESH_LEV       0x000000ff
+
+/*****************************************************************************/
+#define      CHIP_VERSION             0x4b4
+/* Cx231xx redefine  */
+#define      VERSION                  0x4b4
+#define      FLD_REV_ID               0x000000ff
+
+/*****************************************************************************/
+#define      MISC_DIAG_CTRL           0x4b8
+/* Reserved [31:24] */
+#define      FLD_SC_CONVERGE_THRESH   0x00ff0000
+#define      FLD_CCOMB_ERR_LIMIT_3D   0x0000ff00
+#define      FLD_LCOMB_ERR_LIMIT_3D   0x000000ff
+
+/*****************************************************************************/
+#define      VBI_PASS_CTRL            0x4bc
+#define      FLD_VBI_PASS_MD          0x00200000
+#define      FLD_VBI_SETUP_DIS        0x00100000
+#define      FLD_PASS_LINE_CTRL       0x000fffff
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      VCR_DET_CTRL             0x4c0
+#define      FLD_EN_FIELD_PHASE_DET   0x80000000
+#define      FLD_EN_HEAD_SW_DET       0x40000000
+#define      FLD_FIELD_PHASE_LENGTH   0x01ff0000
+/* Reserved [29:25] */
+#define      FLD_FIELD_PHASE_DELAY    0x0000ff00
+#define      FLD_FIELD_PHASE_LIMIT    0x000000f0
+#define      FLD_HEAD_SW_DET_LIMIT    0x0000000f
+
+/*****************************************************************************/
+#define      DL_CTL                   0x800
+#define      DL_CTL_ADDRESS_LOW       0x800    /* Byte 1 in DL_CTL */
+#define      DL_CTL_ADDRESS_HIGH      0x801    /* Byte 2 in DL_CTL */
+#define      DL_CTL_DATA              0x802    /* Byte 3 in DL_CTL */
+#define      DL_CTL_CONTROL           0x803    /* Byte 4 in DL_CTL */
+/* Reserved [31:5] */
+#define      FLD_START_8051           0x10000000
+#define      FLD_DL_ENABLE            0x08000000
+#define      FLD_DL_AUTO_INC          0x04000000
+#define      FLD_DL_MAP               0x03000000
+
+/*****************************************************************************/
+#define      STD_DET_STATUS           0x804
+#define      FLD_SPARE_STATUS1        0xff000000
+#define      FLD_SPARE_STATUS0        0x00ff0000
+#define      FLD_MOD_DET_STATUS1      0x0000ff00
+#define      FLD_MOD_DET_STATUS0      0x000000ff
+
+/*****************************************************************************/
+#define      AUD_BUILD_NUM            0x806
+#define      AUD_VER_NUM              0x807
+#define      STD_DET_CTL              0x808
+#define      STD_DET_CTL_AUD_CTL      0x808    /* Byte 1 in STD_DET_CTL */
+#define      STD_DET_CTL_PREF_MODE    0x809    /* Byte 2 in STD_DET_CTL */
+#define      FLD_SPARE_CTL0           0xff000000
+#define      FLD_DIS_DBX              0x00800000
+#define      FLD_DIS_BTSC             0x00400000
+#define      FLD_DIS_NICAM_A2         0x00200000
+#define      FLD_VIDEO_PRESENT        0x00100000
+#define      FLD_DW8051_VIDEO_FORMAT  0x000f0000
+#define      FLD_PREF_DEC_MODE        0x0000ff00
+#define      FLD_AUD_CONFIG           0x000000ff
+
+/*****************************************************************************/
+#define      DW8051_INT               0x80c
+#define      FLD_VIDEO_PRESENT_CHANGE 0x80000000
+#define      FLD_VIDEO_CHANGE         0x40000000
+#define      FLD_RDS_READY            0x20000000
+#define      FLD_AC97_INT             0x10000000
+#define      FLD_NICAM_BIT_ERROR_TOO_HIGH         0x08000000
+#define      FLD_NICAM_LOCK           0x04000000
+#define      FLD_NICAM_UNLOCK         0x02000000
+#define      FLD_DFT4_TH_CMP          0x01000000
+/* Reserved [23:22] */
+#define      FLD_LOCK_IND_INT         0x00200000
+#define      FLD_DFT3_TH_CMP          0x00100000
+#define      FLD_DFT2_TH_CMP          0x00080000
+#define      FLD_DFT1_TH_CMP          0x00040000
+#define      FLD_FM2_DFT_TH_CMP       0x00020000
+#define      FLD_FM1_DFT_TH_CMP       0x00010000
+#define      FLD_VIDEO_PRESENT_EN     0x00008000
+#define      FLD_VIDEO_CHANGE_EN      0x00004000
+#define      FLD_RDS_READY_EN         0x00002000
+#define      FLD_AC97_INT_EN          0x00001000
+#define      FLD_NICAM_BIT_ERROR_TOO_HIGH_EN      0x00000800
+#define      FLD_NICAM_LOCK_EN        0x00000400
+#define      FLD_NICAM_UNLOCK_EN      0x00000200
+#define      FLD_DFT4_TH_CMP_EN       0x00000100
+/* Reserved [7] */
+#define      FLD_DW8051_INT6_CTL1     0x00000040
+#define      FLD_DW8051_INT5_CTL1     0x00000020
+#define      FLD_DW8051_INT4_CTL1     0x00000010
+#define      FLD_DW8051_INT3_CTL1     0x00000008
+#define      FLD_DW8051_INT2_CTL1     0x00000004
+#define      FLD_DW8051_INT1_CTL1     0x00000002
+#define      FLD_DW8051_INT0_CTL1     0x00000001
+
+/*****************************************************************************/
+#define      GENERAL_CTL              0x810
+#define      FLD_RDS_INT              0x80000000
+#define      FLD_NBER_INT             0x40000000
+#define      FLD_NLL_INT              0x20000000
+#define      FLD_IFL_INT              0x10000000
+#define      FLD_FDL_INT              0x08000000
+#define      FLD_AFC_INT              0x04000000
+#define      FLD_AMC_INT              0x02000000
+#define      FLD_AC97_INT_CTL         0x01000000
+#define      FLD_RDS_INT_DIS          0x00800000
+#define      FLD_NBER_INT_DIS         0x00400000
+#define      FLD_NLL_INT_DIS          0x00200000
+#define      FLD_IFL_INT_DIS          0x00100000
+#define      FLD_FDL_INT_DIS          0x00080000
+#define      FLD_FC_INT_DIS           0x00040000
+#define      FLD_AMC_INT_DIS          0x00020000
+#define      FLD_AC97_INT_DIS         0x00010000
+#define      FLD_REV_NUM              0x0000ff00
+/* Reserved [7:5] */
+#define      FLD_DBX_SOFT_RESET_REG   0x00000010
+#define      FLD_AD_SOFT_RESET_REG    0x00000008
+#define      FLD_SRC_SOFT_RESET_REG   0x00000004
+#define      FLD_CDMOD_SOFT_RESET     0x00000002
+#define      FLD_8051_SOFT_RESET      0x00000001
+
+/*****************************************************************************/
+#define      AAGC_CTL                 0x814
+#define      FLD_AFE_12DB_EN          0x80000000
+#define      FLD_AAGC_DEFAULT_EN      0x40000000
+#define      FLD_AAGC_DEFAULT         0x3f000000
+/* Reserved [23] */
+#define      FLD_AAGC_GAIN            0x00600000
+#define      FLD_AAGC_TH              0x001f0000
+/* Reserved [15:14] */
+#define      FLD_AAGC_HYST2           0x00003f00
+/* Reserved [7:6] */
+#define      FLD_AAGC_HYST1           0x0000003f
+
+/*****************************************************************************/
+#define      IF_SRC_CTL               0x818
+#define      FLD_DBX_BYPASS           0x80000000
+/* Reserved [30:25] */
+#define      FLD_IF_SRC_MODE          0x01000000
+/* Reserved [23:18] */
+#define      FLD_IF_SRC_PHASE_INC     0x0001ffff
+
+/*****************************************************************************/
+#define      ANALOG_DEMOD_CTL         0x81c
+#define      FLD_ROT1_PHACC_PROG      0xffff0000
+/* Reserved [15] */
+#define      FLD_FM1_DELAY_FIX        0x00007000
+#define      FLD_PDF4_SHIFT           0x00000c00
+#define      FLD_PDF3_SHIFT           0x00000300
+#define      FLD_PDF2_SHIFT           0x000000c0
+#define      FLD_PDF1_SHIFT           0x00000030
+#define      FLD_FMBYPASS_MODE2       0x00000008
+#define      FLD_FMBYPASS_MODE1       0x00000004
+#define      FLD_NICAM_MODE           0x00000002
+#define      FLD_BTSC_FMRADIO_MODE    0x00000001
+
+/*****************************************************************************/
+#define      ROT_FREQ_CTL             0x820
+#define      FLD_ROT3_PHACC_PROG      0xffff0000
+#define      FLD_ROT2_PHACC_PROG      0x0000ffff
+
+/*****************************************************************************/
+#define      FM_CTL                   0x824
+#define      FLD_FM2_DC_FB_SHIFT      0xf0000000
+#define      FLD_FM2_DC_INT_SHIFT     0x0f000000
+#define      FLD_FM2_AFC_RESET        0x00800000
+#define      FLD_FM2_DC_PASS_IN       0x00400000
+#define      FLD_FM2_DAGC_SHIFT       0x00380000
+#define      FLD_FM2_CORDIC_SHIFT     0x00070000
+#define      FLD_FM1_DC_FB_SHIFT      0x0000f000
+#define      FLD_FM1_DC_INT_SHIFT     0x00000f00
+#define      FLD_FM1_AFC_RESET        0x00000080
+#define      FLD_FM1_DC_PASS_IN       0x00000040
+#define      FLD_FM1_DAGC_SHIFT       0x00000038
+#define      FLD_FM1_CORDIC_SHIFT     0x00000007
+
+/*****************************************************************************/
+#define      LPF_PDF_CTL              0x828
+/* Reserved [31:30] */
+#define      FLD_LPF32_SHIFT1         0x30000000
+#define      FLD_LPF32_SHIFT2         0x0c000000
+#define      FLD_LPF160_SHIFTA        0x03000000
+#define      FLD_LPF160_SHIFTB        0x00c00000
+#define      FLD_LPF160_SHIFTC        0x00300000
+#define      FLD_LPF32_COEF_SEL2      0x000c0000
+#define      FLD_LPF32_COEF_SEL1      0x00030000
+#define      FLD_LPF160_COEF_SELC     0x0000c000
+#define      FLD_LPF160_COEF_SELB     0x00003000
+#define      FLD_LPF160_COEF_SELA     0x00000c00
+#define      FLD_LPF160_IN_EN_REG     0x00000300
+#define      FLD_PDF4_PDF_SEL         0x000000c0
+#define      FLD_PDF3_PDF_SEL         0x00000030
+#define      FLD_PDF2_PDF_SEL         0x0000000c
+#define      FLD_PDF1_PDF_SEL         0x00000003
+
+/*****************************************************************************/
+#define      DFT1_CTL1                0x82c
+#define      FLD_DFT1_DWELL           0xffff0000
+#define      FLD_DFT1_FREQ            0x0000ffff
+
+/*****************************************************************************/
+#define      DFT1_CTL2                0x830
+#define      FLD_DFT1_THRESHOLD       0xffffff00
+#define      FLD_DFT1_CMP_CTL         0x00000080
+#define      FLD_DFT1_AVG             0x00000070
+/* Reserved [3:1] */
+#define      FLD_DFT1_START           0x00000001
+
+/*****************************************************************************/
+#define      DFT1_STATUS              0x834
+#define      FLD_DFT1_DONE            0x80000000
+#define      FLD_DFT1_TH_CMP_STAT     0x40000000
+#define      FLD_DFT1_RESULT          0x3fffffff
+
+/*****************************************************************************/
+#define      DFT2_CTL1                0x838
+#define      FLD_DFT2_DWELL           0xffff0000
+#define      FLD_DFT2_FREQ            0x0000ffff
+
+/*****************************************************************************/
+#define      DFT2_CTL2                0x83C
+#define      FLD_DFT2_THRESHOLD       0xffffff00
+#define      FLD_DFT2_CMP_CTL         0x00000080
+#define      FLD_DFT2_AVG             0x00000070
+/* Reserved [3:1] */
+#define      FLD_DFT2_START           0x00000001
+
+/*****************************************************************************/
+#define      DFT2_STATUS              0x840
+#define      FLD_DFT2_DONE            0x80000000
+#define      FLD_DFT2_TH_CMP_STAT     0x40000000
+#define      FLD_DFT2_RESULT          0x3fffffff
+
+/*****************************************************************************/
+#define      DFT3_CTL1                0x844
+#define      FLD_DFT3_DWELL           0xffff0000
+#define      FLD_DFT3_FREQ            0x0000ffff
+
+/*****************************************************************************/
+#define      DFT3_CTL2                0x848
+#define      FLD_DFT3_THRESHOLD       0xffffff00
+#define      FLD_DFT3_CMP_CTL         0x00000080
+#define      FLD_DFT3_AVG             0x00000070
+/* Reserved [3:1] */
+#define      FLD_DFT3_START           0x00000001
+
+/*****************************************************************************/
+#define      DFT3_STATUS              0x84c
+#define      FLD_DFT3_DONE            0x80000000
+#define      FLD_DFT3_TH_CMP_STAT     0x40000000
+#define      FLD_DFT3_RESULT          0x3fffffff
+
+/*****************************************************************************/
+#define      DFT4_CTL1                0x850
+#define      FLD_DFT4_DWELL           0xffff0000
+#define      FLD_DFT4_FREQ            0x0000ffff
+
+/*****************************************************************************/
+#define      DFT4_CTL2                0x854
+#define      FLD_DFT4_THRESHOLD       0xffffff00
+#define      FLD_DFT4_CMP_CTL         0x00000080
+#define      FLD_DFT4_AVG             0x00000070
+/* Reserved [3:1] */
+#define      FLD_DFT4_START           0x00000001
+
+/*****************************************************************************/
+#define      DFT4_STATUS              0x858
+#define      FLD_DFT4_DONE            0x80000000
+#define      FLD_DFT4_TH_CMP_STAT     0x40000000
+#define      FLD_DFT4_RESULT          0x3fffffff
+
+/*****************************************************************************/
+#define      AM_MTS_DET               0x85c
+#define      FLD_AM_MTS_MODE          0x80000000
+/* Reserved [30:26] */
+#define      FLD_AM_SUB               0x02000000
+#define      FLD_AM_GAIN_EN           0x01000000
+/* Reserved [23:16] */
+#define      FLD_AMMTS_GAIN_SCALE     0x0000e000
+#define      FLD_MTS_PDF_SHIFT        0x00001800
+#define      FLD_AM_REG_GAIN          0x00000700
+#define      FLD_AGC_REF              0x000000ff
+
+/*****************************************************************************/
+#define      ANALOG_MUX_CTL           0x860
+/* Reserved [31:29] */
+#define      FLD_MUX21_SEL            0x10000000
+#define      FLD_MUX20_SEL            0x08000000
+#define      FLD_MUX19_SEL            0x04000000
+#define      FLD_MUX18_SEL            0x02000000
+#define      FLD_MUX17_SEL            0x01000000
+#define      FLD_MUX16_SEL            0x00800000
+#define      FLD_MUX15_SEL            0x00400000
+#define      FLD_MUX14_SEL            0x00300000
+#define      FLD_MUX13_SEL            0x000C0000
+#define      FLD_MUX12_SEL            0x00020000
+#define      FLD_MUX11_SEL            0x00018000
+#define      FLD_MUX10_SEL            0x00004000
+#define      FLD_MUX9_SEL             0x00002000
+#define      FLD_MUX8_SEL             0x00001000
+#define      FLD_MUX7_SEL             0x00000800
+#define      FLD_MUX6_SEL             0x00000600
+#define      FLD_MUX5_SEL             0x00000100
+#define      FLD_MUX4_SEL             0x000000c0
+#define      FLD_MUX3_SEL             0x00000030
+#define      FLD_MUX2_SEL             0x0000000c
+#define      FLD_MUX1_SEL             0x00000003
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DPLL_CTRL1               0x864
+#define      DIG_PLL_CTL1             0x864
+
+#define      FLD_PLL_STATUS           0x07000000
+#define      FLD_BANDWIDTH_SELECT     0x00030000
+#define      FLD_PLL_SHIFT_REG        0x00007000
+#define      FLD_PHASE_SHIFT          0x000007ff
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DPLL_CTRL2               0x868
+#define      DIG_PLL_CTL2             0x868
+#define      FLD_PLL_UNLOCK_THR       0xff000000
+#define      FLD_PLL_LOCK_THR         0x00ff0000
+/* Reserved [15:8] */
+#define      FLD_AM_PDF_SEL2          0x000000c0
+#define      FLD_AM_PDF_SEL1          0x00000030
+#define      FLD_DPLL_FSM_CTRL        0x0000000c
+/* Reserved [1] */
+#define      FLD_PLL_PILOT_DET        0x00000001
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DPLL_CTRL3               0x86c
+#define      DIG_PLL_CTL3             0x86c
+#define      FLD_DISABLE_LOOP         0x01000000
+#define      FLD_A1_DS1_SEL           0x000c0000
+#define      FLD_A1_DS2_SEL           0x00030000
+#define      FLD_A1_KI                0x0000ff00
+#define      FLD_A1_KD                0x000000ff
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DPLL_CTRL4               0x870
+#define      DIG_PLL_CTL4             0x870
+#define      FLD_A2_DS1_SEL           0x000c0000
+#define      FLD_A2_DS2_SEL           0x00030000
+#define      FLD_A2_KI                0x0000ff00
+#define      FLD_A2_KD                0x000000ff
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DPLL_CTRL5               0x874
+#define      DIG_PLL_CTL5             0x874
+#define      FLD_TRK_DS1_SEL          0x000c0000
+#define      FLD_TRK_DS2_SEL          0x00030000
+#define      FLD_TRK_KI               0x0000ff00
+#define      FLD_TRK_KD               0x000000ff
+
+/*****************************************************************************/
+#define      DEEMPH_GAIN_CTL          0x878
+#define      FLD_DEEMPH2_GAIN         0xFFFF0000
+#define      FLD_DEEMPH1_GAIN         0x0000FFFF
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DEEMPH_COEFF1            0x87c
+#define      DEEMPH_COEF1             0x87c
+#define      FLD_DEEMPH_B0            0xffff0000
+#define      FLD_DEEMPH_A0            0x0000ffff
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DEEMPH_COEFF2            0x880
+#define      DEEMPH_COEF2             0x880
+#define      FLD_DEEMPH_B1            0xFFFF0000
+#define      FLD_DEEMPH_A1            0x0000FFFF
+
+/*****************************************************************************/
+#define      DBX1_CTL1                0x884
+#define      FLD_DBX1_WBE_GAIN        0xffff0000
+#define      FLD_DBX1_IN_GAIN         0x0000ffff
+
+/*****************************************************************************/
+#define      DBX1_CTL2                0x888
+#define      FLD_DBX1_SE_BYPASS       0xffff0000
+#define      FLD_DBX1_SE_GAIN         0x0000ffff
+
+/*****************************************************************************/
+#define      DBX1_RMS_SE              0x88C
+#define      FLD_DBX1_RMS_WBE         0xffff0000
+#define      FLD_DBX1_RMS_SE_FLD      0x0000ffff
+
+/*****************************************************************************/
+#define      DBX2_CTL1                0x890
+#define      FLD_DBX2_WBE_GAIN        0xffff0000
+#define      FLD_DBX2_IN_GAIN         0x0000ffff
+
+/*****************************************************************************/
+#define      DBX2_CTL2                0x894
+#define      FLD_DBX2_SE_BYPASS       0xffff0000
+#define      FLD_DBX2_SE_GAIN         0x0000ffff
+
+/*****************************************************************************/
+#define      DBX2_RMS_SE              0x898
+#define      FLD_DBX2_RMS_WBE         0xffff0000
+#define      FLD_DBX2_RMS_SE_FLD      0x0000ffff
+
+/*****************************************************************************/
+#define      AM_FM_DIFF               0x89c
+/* Reserved [31] */
+#define      FLD_FM_DIFF_OUT          0x7fff0000
+/* Reserved [15] */
+#define      FLD_AM_DIFF_OUT          0x00007fff
+
+/*****************************************************************************/
+#define      NICAM_FAW                0x8a0
+#define      FLD_FAWDETWINEND         0xFc000000
+#define      FLD_FAWDETWINSTR         0x03ff0000
+/* Reserved [15:12] */
+#define      FLD_FAWDETTHRSHLD3       0x00000f00
+#define      FLD_FAWDETTHRSHLD2       0x000000f0
+#define      FLD_FAWDETTHRSHLD1       0x0000000f
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DEEMPH_GAIN              0x8a4
+#define      NICAM_DEEMPHGAIN         0x8a4
+/* Reserved [31:18] */
+#define      FLD_DEEMPHGAIN           0x0003ffff
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DEEMPH_NUMER1            0x8a8
+#define      NICAM_DEEMPHNUMER1       0x8a8
+/* Reserved [31:18] */
+#define      FLD_DEEMPHNUMER1         0x0003ffff
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DEEMPH_NUMER2            0x8ac
+#define      NICAM_DEEMPHNUMER2       0x8ac
+/* Reserved [31:18] */
+#define      FLD_DEEMPHNUMER2         0x0003ffff
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DEEMPH_DENOM1            0x8b0
+#define      NICAM_DEEMPHDENOM1       0x8b0
+/* Reserved [31:18] */
+#define      FLD_DEEMPHDENOM1         0x0003ffff
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      DEEMPH_DENOM2            0x8b4
+#define      NICAM_DEEMPHDENOM2       0x8b4
+/* Reserved [31:18] */
+#define      FLD_DEEMPHDENOM2         0x0003ffff
+
+/*****************************************************************************/
+#define      NICAM_ERRLOG_CTL1        0x8B8
+/* Reserved [31:28] */
+#define      FLD_ERRINTRPTTHSHLD1     0x0fff0000
+/* Reserved [15:12] */
+#define      FLD_ERRLOGPERIOD         0x00000fff
+
+/*****************************************************************************/
+#define      NICAM_ERRLOG_CTL2        0x8bc
+/* Reserved [31:28] */
+#define      FLD_ERRINTRPTTHSHLD3     0x0fff0000
+/* Reserved [15:12] */
+#define      FLD_ERRINTRPTTHSHLD2     0x00000fff
+
+/*****************************************************************************/
+#define      NICAM_ERRLOG_STS1        0x8c0
+/* Reserved [31:28] */
+#define      FLD_ERRLOG2              0x0fff0000
+/* Reserved [15:12] */
+#define      FLD_ERRLOG1              0x00000fff
+
+/*****************************************************************************/
+#define      NICAM_ERRLOG_STS2        0x8c4
+/* Reserved [31:12] */
+#define      FLD_ERRLOG3              0x00000fff
+
+/*****************************************************************************/
+#define      NICAM_STATUS             0x8c8
+/* Reserved [31:20] */
+#define      FLD_NICAM_CIB            0x000c0000
+#define      FLD_NICAM_LOCK_STAT      0x00020000
+#define      FLD_NICAM_MUTE           0x00010000
+#define      FLD_NICAMADDIT_DATA      0x0000ffe0
+#define      FLD_NICAMCNTRL           0x0000001f
+
+/*****************************************************************************/
+#define      DEMATRIX_CTL             0x8cc
+#define      FLD_AC97_IN_SHIFT        0xf0000000
+#define      FLD_I2S_IN_SHIFT         0x0f000000
+#define      FLD_DEMATRIX_SEL_CTL     0x00ff0000
+/* Reserved [15:11] */
+#define      FLD_DMTRX_BYPASS         0x00000400
+#define      FLD_DEMATRIX_MODE        0x00000300
+/* Reserved [7:6] */
+#define      FLD_PH_DBX_SEL           0x00000020
+#define      FLD_PH_CH_SEL            0x00000010
+#define      FLD_PHASE_FIX            0x0000000f
+
+/*****************************************************************************/
+#define      PATH1_CTL1               0x8d0
+/* Reserved [31:29] */
+#define      FLD_PATH1_MUTE_CTL       0x1f000000
+/* Reserved [23:22] */
+#define      FLD_PATH1_AVC_CG         0x00300000
+#define      FLD_PATH1_AVC_RT         0x000f0000
+#define      FLD_PATH1_AVC_AT         0x0000f000
+#define      FLD_PATH1_AVC_STEREO     0x00000800
+#define      FLD_PATH1_AVC_CR         0x00000700
+#define      FLD_PATH1_AVC_RMS_CON    0x000000f0
+#define      FLD_PATH1_SEL_CTL        0x0000000f
+
+/*****************************************************************************/
+#define      PATH1_VOL_CTL            0x8d4
+#define      FLD_PATH1_AVC_THRESHOLD  0x7fff0000
+#define      FLD_PATH1_BAL_LEFT       0x00008000
+#define      FLD_PATH1_BAL_LEVEL      0x00007f00
+#define      FLD_PATH1_VOLUME         0x000000ff
+
+/*****************************************************************************/
+#define      PATH1_EQ_CTL             0x8d8
+/* Reserved [31:30] */
+#define      FLD_PATH1_EQ_TREBLE_VOL  0x3f000000
+/* Reserved [23:22] */
+#define      FLD_PATH1_EQ_MID_VOL     0x003f0000
+/* Reserved [15:14] */
+#define      FLD_PATH1_EQ_BASS_VOL    0x00003f00
+/* Reserved [7:1] */
+#define      FLD_PATH1_EQ_BAND_SEL    0x00000001
+
+/*****************************************************************************/
+#define      PATH1_SC_CTL             0x8dc
+#define      FLD_PATH1_SC_THRESHOLD   0x7fff0000
+#define      FLD_PATH1_SC_RT          0x0000f000
+#define      FLD_PATH1_SC_AT          0x00000f00
+#define      FLD_PATH1_SC_STEREO      0x00000080
+#define      FLD_PATH1_SC_CR          0x00000070
+#define      FLD_PATH1_SC_RMS_CON     0x0000000f
+
+/*****************************************************************************/
+#define      PATH2_CTL1               0x8e0
+/* Reserved [31:26] */
+#define      FLD_PATH2_MUTE_CTL       0x03000000
+/* Reserved [23:22] */
+#define      FLD_PATH2_AVC_CG         0x00300000
+#define      FLD_PATH2_AVC_RT         0x000f0000
+#define      FLD_PATH2_AVC_AT         0x0000f000
+#define      FLD_PATH2_AVC_STEREO     0x00000800
+#define      FLD_PATH2_AVC_CR         0x00000700
+#define      FLD_PATH2_AVC_RMS_CON    0x000000f0
+#define      FLD_PATH2_SEL_CTL        0x0000000f
+
+/*****************************************************************************/
+#define      PATH2_VOL_CTL            0x8e4
+#define      FLD_PATH2_AVC_THRESHOLD  0xffff0000
+#define      FLD_PATH2_BAL_LEFT       0x00008000
+#define      FLD_PATH2_BAL_LEVEL      0x00007f00
+#define      FLD_PATH2_VOLUME         0x000000ff
+
+/*****************************************************************************/
+#define      PATH2_EQ_CTL             0x8e8
+/* Reserved [31:30] */
+#define      FLD_PATH2_EQ_TREBLE_VOL  0x3f000000
+/* Reserved [23:22] */
+#define      FLD_PATH2_EQ_MID_VOL     0x003f0000
+/* Reserved [15:14] */
+#define      FLD_PATH2_EQ_BASS_VOL    0x00003f00
+/* Reserved [7:1] */
+#define      FLD_PATH2_EQ_BAND_SEL    0x00000001
+
+/*****************************************************************************/
+#define      PATH2_SC_CTL             0x8eC
+#define      FLD_PATH2_SC_THRESHOLD   0xffff0000
+#define      FLD_PATH2_SC_RT          0x0000f000
+#define      FLD_PATH2_SC_AT          0x00000f00
+#define      FLD_PATH2_SC_STEREO      0x00000080
+#define      FLD_PATH2_SC_CR          0x00000070
+#define      FLD_PATH2_SC_RMS_CON     0x0000000f
+
+/*****************************************************************************/
+#define      SRC_CTL                  0x8f0
+#define      FLD_SRC_STATUS           0xffffff00
+#define      FLD_FIFO_LF_EN           0x000000fc
+#define      FLD_BYPASS_LI            0x00000002
+#define      FLD_BYPASS_PF            0x00000001
+
+/*****************************************************************************/
+#define      SRC_LF_COEF              0x8f4
+#define      FLD_LOOP_FILTER_COEF2    0xffff0000
+#define      FLD_LOOP_FILTER_COEF1    0x0000ffff
+
+/*****************************************************************************/
+#define      SRC1_CTL                 0x8f8
+/* Reserved [31:28] */
+#define      FLD_SRC1_FIFO_RD_TH      0x0f000000
+/* Reserved [23:18] */
+#define      FLD_SRC1_PHASE_INC       0x0003ffff
+
+/*****************************************************************************/
+#define      SRC2_CTL                 0x8fc
+/* Reserved [31:28] */
+#define      FLD_SRC2_FIFO_RD_TH      0x0f000000
+/* Reserved [23:18] */
+#define      FLD_SRC2_PHASE_INC       0x0003ffff
+
+/*****************************************************************************/
+#define      SRC3_CTL                 0x900
+/* Reserved [31:28] */
+#define      FLD_SRC3_FIFO_RD_TH      0x0f000000
+/* Reserved [23:18] */
+#define      FLD_SRC3_PHASE_INC       0x0003ffff
+
+/*****************************************************************************/
+#define      SRC4_CTL                 0x904
+/* Reserved [31:28] */
+#define      FLD_SRC4_FIFO_RD_TH      0x0f000000
+/* Reserved [23:18] */
+#define      FLD_SRC4_PHASE_INC       0x0003ffff
+
+/*****************************************************************************/
+#define      SRC5_CTL                 0x908
+/* Reserved [31:28] */
+#define      FLD_SRC5_FIFO_RD_TH      0x0f000000
+/* Reserved [23:18] */
+#define      FLD_SRC5_PHASE_INC       0x0003ffff
+
+/*****************************************************************************/
+#define      SRC6_CTL                 0x90c
+/* Reserved [31:28] */
+#define      FLD_SRC6_FIFO_RD_TH      0x0f000000
+/* Reserved [23:18] */
+#define      FLD_SRC6_PHASE_INC       0x0003ffff
+
+/*****************************************************************************/
+#define      BAND_OUT_SEL             0x910
+#define      FLD_SRC6_IN_SEL          0xc0000000
+#define      FLD_SRC6_CLK_SEL         0x30000000
+#define      FLD_SRC5_IN_SEL          0x0c000000
+#define      FLD_SRC5_CLK_SEL         0x03000000
+#define      FLD_SRC4_IN_SEL          0x00c00000
+#define      FLD_SRC4_CLK_SEL         0x00300000
+#define      FLD_SRC3_IN_SEL          0x000c0000
+#define      FLD_SRC3_CLK_SEL         0x00030000
+#define      FLD_BASEBAND_BYPASS_CTL  0x0000ff00
+#define      FLD_AC97_SRC_SEL         0x000000c0
+#define      FLD_I2S_SRC_SEL          0x00000030
+#define      FLD_PARALLEL2_SRC_SEL    0x0000000c
+#define      FLD_PARALLEL1_SRC_SEL    0x00000003
+
+/*****************************************************************************/
+#define      I2S_IN_CTL               0x914
+/* Reserved [31:11] */
+#define      FLD_I2S_UP2X_BW20K       0x00000400
+#define      FLD_I2S_UP2X_BYPASS      0x00000200
+#define      FLD_I2S_IN_MASTER_MODE   0x00000100
+#define      FLD_I2S_IN_SONY_MODE     0x00000080
+#define      FLD_I2S_IN_RIGHT_JUST    0x00000040
+#define      FLD_I2S_IN_WS_SEL        0x00000020
+#define      FLD_I2S_IN_BCN_DEL       0x0000001f
+
+/*****************************************************************************/
+#define      I2S_OUT_CTL              0x918
+/* Reserved [31:17] */
+#define      FLD_I2S_OUT_SOFT_RESET_EN  0x00010000
+/* Reserved [15:9] */
+#define      FLD_I2S_OUT_MASTER_MODE  0x00000100
+#define      FLD_I2S_OUT_SONY_MODE    0x00000080
+#define      FLD_I2S_OUT_RIGHT_JUST   0x00000040
+#define      FLD_I2S_OUT_WS_SEL       0x00000020
+#define      FLD_I2S_OUT_BCN_DEL      0x0000001f
+
+/*****************************************************************************/
+#define      AC97_CTL                 0x91c
+/* Reserved [31:26] */
+#define      FLD_AC97_UP2X_BW20K      0x02000000
+#define      FLD_AC97_UP2X_BYPASS     0x01000000
+/* Reserved [23:17] */
+#define      FLD_AC97_RST_ACL         0x00010000
+/* Reserved [15:9] */
+#define      FLD_AC97_WAKE_UP_SYNC    0x00000100
+/* Reserved [7:1] */
+#define      FLD_AC97_SHUTDOWN        0x00000001
+
+/* Cx231xx redefine */
+#define      QPSK_IAGC_CTL1            0x94c
+#define      QPSK_IAGC_CTL2            0x950
+#define      QPSK_FEPR_FREQ            0x954
+#define      QPSK_BTL_CTL1             0x958
+#define      QPSK_BTL_CTL2             0x95c
+#define      QPSK_CTL_CTL1             0x960
+#define      QPSK_CTL_CTL2             0x964
+#define      QPSK_MF_FAGC_CTL          0x968
+#define      QPSK_EQ_CTL               0x96c
+#define      QPSK_LOCK_CTL             0x970
+
+/*****************************************************************************/
+#define      FM1_DFT_CTL              0x9a8
+#define      FLD_FM1_DFT_THRESHOLD    0xffff0000
+/* Reserved [15:8] */
+#define      FLD_FM1_DFT_CMP_CTL      0x00000080
+#define      FLD_FM1_DFT_AVG          0x00000070
+/* Reserved [3:1] */
+#define      FLD_FM1_DFT_START        0x00000001
+
+/*****************************************************************************/
+#define      FM1_DFT_STATUS           0x9ac
+#define      FLD_FM1_DFT_DONE         0x80000000
+/* Reserved [30:19] */
+#define      FLD_FM_DFT_TH_CMP        0x00040000
+#define      FLD_FM1_DFT              0x0003ffff
+
+/*****************************************************************************/
+#define      FM2_DFT_CTL              0x9b0
+#define      FLD_FM2_DFT_THRESHOLD    0xffff0000
+/* Reserved [15:8] */
+#define      FLD_FM2_DFT_CMP_CTL      0x00000080
+#define      FLD_FM2_DFT_AVG          0x00000070
+/* Reserved [3:1] */
+#define      FLD_FM2_DFT_START        0x00000001
+
+/*****************************************************************************/
+#define      FM2_DFT_STATUS           0x9b4
+#define      FLD_FM2_DFT_DONE         0x80000000
+/* Reserved [30:19] */
+#define      FLD_FM2_DFT_TH_CMP_STAT  0x00040000
+#define      FLD_FM2_DFT              0x0003ffff
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      AAGC_STATUS_REG          0x9b8
+#define      AAGC_STATUS              0x9b8
+/* Reserved [31:27] */
+#define      FLD_FM2_DAGC_OUT         0x07000000
+/* Reserved [23:19] */
+#define      FLD_FM1_DAGC_OUT         0x00070000
+/* Reserved [15:6] */
+#define      FLD_AFE_VGA_OUT          0x0000003f
+
+/*****************************************************************************/
+#define      MTS_GAIN_STATUS          0x9bc
+/* Reserved [31:14] */
+#define      FLD_MTS_GAIN             0x00003fff
+
+#define      RDS_OUT                  0x9c0
+#define      FLD_RDS_Q                0xffff0000
+#define      FLD_RDS_I                0x0000ffff
+
+/*****************************************************************************/
+#define      AUTOCONFIG_REG           0x9c4
+/* Reserved [31:4] */
+#define      FLD_AUTOCONFIG_MODE      0x0000000f
+
+#define      FM_AFC                   0x9c8
+#define      FLD_FM2_AFC              0xffff0000
+#define      FLD_FM1_AFC              0x0000ffff
+
+/*****************************************************************************/
+/* Cx231xx redefine */
+#define      NEW_SPARE                0x9cc
+#define      NEW_SPARE_REG            0x9cc
+
+/*****************************************************************************/
+#define      DBX_ADJ                  0x9d0
+/* Reserved [31:28] */
+#define      FLD_DBX2_ADJ             0x0fff0000
+/* Reserved [15:12] */
+#define      FLD_DBX1_ADJ             0x00000fff
+
+#define      VID_FMT_AUTO              0
+#define      VID_FMT_NTSC_M            1
+#define      VID_FMT_NTSC_J            2
+#define      VID_FMT_NTSC_443          3
+#define      VID_FMT_PAL_BDGHI         4
+#define      VID_FMT_PAL_M             5
+#define      VID_FMT_PAL_N             6
+#define      VID_FMT_PAL_NC            7
+#define      VID_FMT_PAL_60            8
+#define      VID_FMT_SECAM             12
+#define      VID_FMT_SECAM_60          13
+
+#define      INPUT_MODE_CVBS_0         0       /* INPUT_MODE_VALUE(0) */
+#define      INPUT_MODE_YC_1           1       /* INPUT_MODE_VALUE(1) */
+#define      INPUT_MODE_YC2_2          2       /* INPUT_MODE_VALUE(2) */
+#define      INPUT_MODE_YUV_3          3       /* INPUT_MODE_VALUE(3) */
+
+#define      LUMA_LPF_LOW_BANDPASS     0       /* 0.6Mhz LPF BW */
+#define      LUMA_LPF_MEDIUM_BANDPASS  1       /* 1.0Mhz LPF BW */
+#define      LUMA_LPF_HIGH_BANDPASS    2       /* 1.5Mhz LPF BW */
+
+#define      UV_LPF_LOW_BANDPASS       0       /* 0.6Mhz LPF BW */
+#define      UV_LPF_MEDIUM_BANDPASS    1       /* 1.0Mhz LPF BW */
+#define      UV_LPF_HIGH_BANDPASS      2       /* 1.5Mhz LPF BW */
+
+#define      TWO_TAP_FILT              0
+#define      THREE_TAP_FILT            1
+#define      FOUR_TAP_FILT             2
+#define      FIVE_TAP_FILT             3
+
+#define      AUD_CHAN_SRC_PARALLEL     0
+#define      AUD_CHAN_SRC_I2S_INPUT    1
+#define      AUD_CHAN_SRC_FLATIRON     2
+#define      AUD_CHAN_SRC_PARALLEL3    3
+
+#define      OUT_MODE_601              0
+#define      OUT_MODE_656              1
+#define      OUT_MODE_VIP11            2
+#define      OUT_MODE_VIP20            3
+
+#define      PHASE_INC_49MHZ          0x0df22
+#define      PHASE_INC_56MHZ          0x0fa5b
+#define      PHASE_INC_28MHZ          0x010000
+
+#endif
diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c
new file mode 100644 (file)
index 0000000..ac7db52
--- /dev/null
@@ -0,0 +1,710 @@
+/*
+   cx231xx_vbi.c - driver for Conexant Cx23100/101/102 USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+       Based on cx88 driver
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   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/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 <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/msp3400.h>
+#include <media/tuner.h>
+
+#include "cx231xx.h"
+#include "cx231xx-vbi.h"
+
+static inline void print_err_status(struct cx231xx *dev, int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+       if (packet < 0) {
+               cx231xx_err(DRIVER_NAME "URB status %d [%s].\n", status,
+                           errmsg);
+       } else {
+               cx231xx_err(DRIVER_NAME "URB packet %d, status %d [%s].\n",
+                           packet, status, errmsg);
+       }
+}
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb)
+{
+       struct cx231xx_dmaqueue *dma_q = urb->context;
+       int rc = 1;
+       unsigned char *p_buffer;
+       u32 bytes_parsed = 0, buffer_size = 0;
+       u8 sav_eav = 0;
+
+       if (!dev)
+               return 0;
+
+       if (dev->state & DEV_DISCONNECTED)
+               return 0;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               if (urb->status == -ENOENT)
+                       return 0;
+       }
+
+       /* get buffer pointer and length */
+       p_buffer = urb->transfer_buffer;
+       buffer_size = urb->actual_length;
+
+       if (buffer_size > 0) {
+               bytes_parsed = 0;
+
+               if (dma_q->is_partial_line) {
+                       /* Handle the case where we were working on a partial
+                          line */
+                       sav_eav = dma_q->last_sav;
+               } else {
+                       /* Check for a SAV/EAV overlapping the
+                          buffer boundary */
+
+                       sav_eav = cx231xx_find_boundary_SAV_EAV(p_buffer,
+                                                         dma_q->partial_buf,
+                                                         &bytes_parsed);
+               }
+
+               sav_eav &= 0xF0;
+               /* Get the first line if we have some portion of an SAV/EAV from
+                  the last buffer or a partial line */
+               if (sav_eav) {
+                       bytes_parsed += cx231xx_get_vbi_line(dev, dma_q,
+                               sav_eav,                       /* SAV/EAV */
+                               p_buffer + bytes_parsed,       /* p_buffer */
+                               buffer_size - bytes_parsed);   /* buffer size */
+               }
+
+               /* Now parse data that is completely in this buffer */
+               dma_q->is_partial_line = 0;
+
+               while (bytes_parsed < buffer_size) {
+                       u32 bytes_used = 0;
+
+                       sav_eav = cx231xx_find_next_SAV_EAV(
+                               p_buffer + bytes_parsed,        /* p_buffer */
+                               buffer_size - bytes_parsed, /* buffer size */
+                               &bytes_used);   /* bytes used to get SAV/EAV */
+
+                       bytes_parsed += bytes_used;
+
+                       sav_eav &= 0xF0;
+                       if (sav_eav && (bytes_parsed < buffer_size)) {
+                               bytes_parsed += cx231xx_get_vbi_line(dev,
+                                       dma_q, sav_eav, /* SAV/EAV */
+                                       p_buffer+bytes_parsed, /* p_buffer */
+                                       buffer_size-bytes_parsed);/*buf size*/
+                       }
+               }
+
+               /* Save the last four bytes of the buffer so we can
+               check the buffer boundary condition next time */
+               memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4);
+               bytes_parsed = 0;
+       }
+
+       return rc;
+}
+
+/* ------------------------------------------------------------------
+       Vbi buf operations
+   ------------------------------------------------------------------*/
+
+static int
+vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count,
+                unsigned int *size)
+{
+       struct cx231xx_fh *fh = vq->priv_data;
+       struct cx231xx *dev = fh->dev;
+       u32 height = 0;
+
+       height = ((dev->norm & V4L2_STD_625_50) ?
+                 PAL_VBI_LINES : NTSC_VBI_LINES);
+
+       *size = (dev->width * height * 2 * 2);
+       if (0 == *count)
+               *count = CX231XX_DEF_VBI_BUF;
+
+       if (*count < CX231XX_MIN_BUF)
+               *count = CX231XX_MIN_BUF;
+
+       return 0;
+}
+
+/* This is called *without* dev->slock held; please keep it that way */
+static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
+{
+       struct cx231xx_fh *fh = vq->priv_data;
+       struct cx231xx *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->vbi_mode.slock, flags);
+       if (dev->vbi_mode.bulk_ctl.buf == buf)
+               dev->vbi_mode.bulk_ctl.buf = NULL;
+       spin_unlock_irqrestore(&dev->vbi_mode.slock, flags);
+
+       videobuf_vmalloc_free(&buf->vb);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int
+vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+                  enum v4l2_field field)
+{
+       struct cx231xx_fh *fh = vq->priv_data;
+       struct cx231xx_buffer *buf =
+           container_of(vb, struct cx231xx_buffer, vb);
+       struct cx231xx *dev = fh->dev;
+       int rc = 0, urb_init = 0;
+       u32 height = 0;
+
+       height = ((dev->norm & V4L2_STD_625_50) ?
+                 PAL_VBI_LINES : NTSC_VBI_LINES);
+       buf->vb.size = ((dev->width << 1) * height * 2);
+
+       if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+               return -EINVAL;
+
+       buf->vb.width = dev->width;
+       buf->vb.height = height;
+       buf->vb.field = field;
+       buf->vb.field = V4L2_FIELD_SEQ_TB;
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               rc = videobuf_iolock(vq, &buf->vb, NULL);
+               if (rc < 0)
+                       goto fail;
+       }
+
+       if (!dev->vbi_mode.bulk_ctl.num_bufs)
+               urb_init = 1;
+
+       if (urb_init) {
+               rc = cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS,
+                                          CX231XX_NUM_VBI_BUFS,
+                                          dev->vbi_mode.alt_max_pkt_size[0],
+                                          cx231xx_isoc_vbi_copy);
+               if (rc < 0)
+                       goto fail;
+       }
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+fail:
+       free_buffer(vq, buf);
+       return rc;
+}
+
+static void
+vbi_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct cx231xx_buffer *buf =
+           container_of(vb, struct cx231xx_buffer, vb);
+       struct cx231xx_fh *fh = vq->priv_data;
+       struct cx231xx *dev = fh->dev;
+       struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq;
+
+       buf->vb.state = VIDEOBUF_QUEUED;
+       list_add_tail(&buf->vb.queue, &vidq->active);
+
+}
+
+static void vbi_buffer_release(struct videobuf_queue *vq,
+                              struct videobuf_buffer *vb)
+{
+       struct cx231xx_buffer *buf =
+           container_of(vb, struct cx231xx_buffer, vb);
+
+
+       free_buffer(vq, buf);
+}
+
+struct videobuf_queue_ops cx231xx_vbi_qops = {
+       .buf_setup   = vbi_buffer_setup,
+       .buf_prepare = vbi_buffer_prepare,
+       .buf_queue   = vbi_buffer_queue,
+       .buf_release = vbi_buffer_release,
+};
+
+/* ------------------------------------------------------------------
+       URB control
+   ------------------------------------------------------------------*/
+
+/*
+ * IRQ callback, called by URB callback
+ */
+static void cx231xx_irq_vbi_callback(struct urb *urb)
+{
+       struct cx231xx_dmaqueue *dma_q = urb->context;
+       struct cx231xx_video_mode *vmode =
+           container_of(dma_q, struct cx231xx_video_mode, vidq);
+       struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode);
+
+       switch (urb->status) {
+       case 0:         /* success */
+       case -ETIMEDOUT:        /* NAK */
+               break;
+       case -ECONNRESET:       /* kill */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+       default:                /* error */
+               cx231xx_err(DRIVER_NAME "urb completition error %d.\n",
+                           urb->status);
+               break;
+       }
+
+       /* Copy data from URB */
+       spin_lock(&dev->vbi_mode.slock);
+       dev->vbi_mode.bulk_ctl.bulk_copy(dev, urb);
+       spin_unlock(&dev->vbi_mode.slock);
+
+       /* Reset status */
+       urb->status = 0;
+
+       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (urb->status) {
+               cx231xx_err(DRIVER_NAME "urb resubmit failed (error=%i)\n",
+                           urb->status);
+       }
+}
+
+/*
+ * Stop and Deallocate URBs
+ */
+void cx231xx_uninit_vbi_isoc(struct cx231xx *dev)
+{
+       struct urb *urb;
+       int i;
+
+       cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_uninit_vbi_isoc\n");
+
+       dev->vbi_mode.bulk_ctl.nfields = -1;
+       for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
+               urb = dev->vbi_mode.bulk_ctl.urb[i];
+               if (urb) {
+                       if (!irqs_disabled())
+                               usb_kill_urb(urb);
+                       else
+                               usb_unlink_urb(urb);
+
+                       if (dev->vbi_mode.bulk_ctl.transfer_buffer[i]) {
+
+                               kfree(dev->vbi_mode.bulk_ctl.
+                                     transfer_buffer[i]);
+                               dev->vbi_mode.bulk_ctl.transfer_buffer[i] =
+                                   NULL;
+                       }
+                       usb_free_urb(urb);
+                       dev->vbi_mode.bulk_ctl.urb[i] = NULL;
+               }
+               dev->vbi_mode.bulk_ctl.transfer_buffer[i] = NULL;
+       }
+
+       kfree(dev->vbi_mode.bulk_ctl.urb);
+       kfree(dev->vbi_mode.bulk_ctl.transfer_buffer);
+
+       dev->vbi_mode.bulk_ctl.urb = NULL;
+       dev->vbi_mode.bulk_ctl.transfer_buffer = NULL;
+       dev->vbi_mode.bulk_ctl.num_bufs = 0;
+
+       cx231xx_capture_start(dev, 0, Vbi);
+}
+EXPORT_SYMBOL_GPL(cx231xx_uninit_vbi_isoc);
+
+/*
+ * Allocate URBs and start IRQ
+ */
+int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
+                         int num_bufs, int max_pkt_size,
+                         int (*bulk_copy) (struct cx231xx *dev,
+                                           struct urb *urb))
+{
+       struct cx231xx_dmaqueue *dma_q = &dev->vbi_mode.vidq;
+       int i;
+       int sb_size, pipe;
+       struct urb *urb;
+       int rc;
+
+       cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_prepare_isoc\n");
+
+       /* De-allocates all pending stuff */
+       cx231xx_uninit_vbi_isoc(dev);
+
+       /* clear if any halt */
+       usb_clear_halt(dev->udev,
+                      usb_rcvbulkpipe(dev->udev,
+                                      dev->vbi_mode.end_point_addr));
+
+       dev->vbi_mode.bulk_ctl.bulk_copy = bulk_copy;
+       dev->vbi_mode.bulk_ctl.num_bufs = num_bufs;
+       dma_q->pos = 0;
+       dma_q->is_partial_line = 0;
+       dma_q->last_sav = 0;
+       dma_q->current_field = -1;
+       dma_q->bytes_left_in_line = dev->width << 1;
+       dma_q->lines_per_field = ((dev->norm & V4L2_STD_625_50) ?
+                                 PAL_VBI_LINES : NTSC_VBI_LINES);
+       dma_q->lines_completed = 0;
+       for (i = 0; i < 8; i++)
+               dma_q->partial_buf[i] = 0;
+
+       dev->vbi_mode.bulk_ctl.urb = kzalloc(sizeof(void *) * num_bufs,
+                                            GFP_KERNEL);
+       if (!dev->vbi_mode.bulk_ctl.urb) {
+               cx231xx_errdev("cannot alloc memory for usb buffers\n");
+               return -ENOMEM;
+       }
+
+       dev->vbi_mode.bulk_ctl.transfer_buffer =
+           kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
+       if (!dev->vbi_mode.bulk_ctl.transfer_buffer) {
+               cx231xx_errdev("cannot allocate memory for usbtransfer\n");
+               kfree(dev->vbi_mode.bulk_ctl.urb);
+               return -ENOMEM;
+       }
+
+       dev->vbi_mode.bulk_ctl.max_pkt_size = max_pkt_size;
+       dev->vbi_mode.bulk_ctl.buf = NULL;
+
+       sb_size = max_packets * dev->vbi_mode.bulk_ctl.max_pkt_size;
+
+       /* allocate urbs and transfer buffers */
+       for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
+
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!urb) {
+                       cx231xx_err(DRIVER_NAME
+                                   ": cannot alloc bulk_ctl.urb %i\n", i);
+                       cx231xx_uninit_vbi_isoc(dev);
+                       return -ENOMEM;
+               }
+               dev->vbi_mode.bulk_ctl.urb[i] = urb;
+               urb->transfer_flags = 0;
+
+               dev->vbi_mode.bulk_ctl.transfer_buffer[i] =
+                   kzalloc(sb_size, GFP_KERNEL);
+               if (!dev->vbi_mode.bulk_ctl.transfer_buffer[i]) {
+                       cx231xx_err(DRIVER_NAME
+                                   ": unable to allocate %i bytes for transfer"
+                                   " buffer %i%s\n", sb_size, i,
+                                   in_interrupt() ? " while in int" : "");
+                       cx231xx_uninit_vbi_isoc(dev);
+                       return -ENOMEM;
+               }
+
+               pipe = usb_rcvbulkpipe(dev->udev, dev->vbi_mode.end_point_addr);
+               usb_fill_bulk_urb(urb, dev->udev, pipe,
+                                 dev->vbi_mode.bulk_ctl.transfer_buffer[i],
+                                 sb_size, cx231xx_irq_vbi_callback, dma_q);
+       }
+
+       init_waitqueue_head(&dma_q->wq);
+
+       /* submit urbs and enables IRQ */
+       for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
+               rc = usb_submit_urb(dev->vbi_mode.bulk_ctl.urb[i], GFP_ATOMIC);
+               if (rc) {
+                       cx231xx_err(DRIVER_NAME
+                                   ": submit of urb %i failed (error=%i)\n", i,
+                                   rc);
+                       cx231xx_uninit_vbi_isoc(dev);
+                       return rc;
+               }
+       }
+
+       cx231xx_capture_start(dev, 1, Vbi);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cx231xx_init_vbi_isoc);
+
+u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+                        u8 sav_eav, u8 *p_buffer, u32 buffer_size)
+{
+       u32 bytes_copied = 0;
+       int current_field = -1;
+
+       switch (sav_eav) {
+
+       case SAV_VBI_FIELD1:
+               current_field = 1;
+               break;
+
+       case SAV_VBI_FIELD2:
+               current_field = 2;
+               break;
+       default:
+               break;
+       }
+
+       if (current_field < 0)
+               return bytes_copied;
+
+       dma_q->last_sav = sav_eav;
+
+       bytes_copied =
+           cx231xx_copy_vbi_line(dev, dma_q, p_buffer, buffer_size,
+                                 current_field);
+
+       return bytes_copied;
+}
+
+/*
+ * Announces that a buffer were filled and request the next
+ */
+static inline void vbi_buffer_filled(struct cx231xx *dev,
+                                    struct cx231xx_dmaqueue *dma_q,
+                                    struct cx231xx_buffer *buf)
+{
+       /* Advice that buffer was filled */
+       /* cx231xx_info(DRIVER_NAME "[%p/%d] wakeup\n", buf, buf->vb.i); */
+
+       buf->vb.state = VIDEOBUF_DONE;
+       buf->vb.field_count++;
+       do_gettimeofday(&buf->vb.ts);
+
+       dev->vbi_mode.bulk_ctl.buf = NULL;
+
+       list_del(&buf->vb.queue);
+       wake_up(&buf->vb.done);
+}
+
+u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+                         u8 *p_line, u32 length, int field_number)
+{
+       u32 bytes_to_copy;
+       struct cx231xx_buffer *buf;
+       u32 _line_size = dev->width * 2;
+
+       if (dma_q->current_field == -1) {
+               /* Just starting up */
+               cx231xx_reset_vbi_buffer(dev, dma_q);
+       }
+
+       if (dma_q->current_field != field_number)
+               dma_q->lines_completed = 0;
+
+       /* get the buffer pointer */
+       buf = dev->vbi_mode.bulk_ctl.buf;
+
+       /* Remember the field number for next time */
+       dma_q->current_field = field_number;
+
+       bytes_to_copy = dma_q->bytes_left_in_line;
+       if (bytes_to_copy > length)
+               bytes_to_copy = length;
+
+       if (dma_q->lines_completed >= dma_q->lines_per_field) {
+               dma_q->bytes_left_in_line -= bytes_to_copy;
+               dma_q->is_partial_line =
+                   (dma_q->bytes_left_in_line == 0) ? 0 : 1;
+               return 0;
+       }
+
+       dma_q->is_partial_line = 1;
+
+       /* If we don't have a buffer, just return the number of bytes we would
+          have copied if we had a buffer. */
+       if (!buf) {
+               dma_q->bytes_left_in_line -= bytes_to_copy;
+               dma_q->is_partial_line =
+                   (dma_q->bytes_left_in_line == 0) ? 0 : 1;
+               return bytes_to_copy;
+       }
+
+       /* copy the data to video buffer */
+       cx231xx_do_vbi_copy(dev, dma_q, p_line, bytes_to_copy);
+
+       dma_q->pos += bytes_to_copy;
+       dma_q->bytes_left_in_line -= bytes_to_copy;
+
+       if (dma_q->bytes_left_in_line == 0) {
+
+               dma_q->bytes_left_in_line = _line_size;
+               dma_q->lines_completed++;
+               dma_q->is_partial_line = 0;
+
+               if (cx231xx_is_vbi_buffer_done(dev, dma_q) && buf) {
+
+                       vbi_buffer_filled(dev, dma_q, buf);
+
+                       dma_q->pos = 0;
+                       dma_q->lines_completed = 0;
+                       cx231xx_reset_vbi_buffer(dev, dma_q);
+               }
+       }
+
+       return bytes_to_copy;
+}
+
+/*
+ * video-buf generic routine to get the next available buffer
+ */
+static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q,
+                                   struct cx231xx_buffer **buf)
+{
+       struct cx231xx_video_mode *vmode =
+           container_of(dma_q, struct cx231xx_video_mode, vidq);
+       struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode);
+       char *outp;
+
+       if (list_empty(&dma_q->active)) {
+               cx231xx_err(DRIVER_NAME ": No active queue to serve\n");
+               dev->vbi_mode.bulk_ctl.buf = NULL;
+               *buf = NULL;
+               return;
+       }
+
+       /* Get the next buffer */
+       *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue);
+
+       /* Cleans up buffer - Useful for testing for frame/URB loss */
+       outp = videobuf_to_vmalloc(&(*buf)->vb);
+       memset(outp, 0, (*buf)->vb.size);
+
+       dev->vbi_mode.bulk_ctl.buf = *buf;
+
+       return;
+}
+
+void cx231xx_reset_vbi_buffer(struct cx231xx *dev,
+                             struct cx231xx_dmaqueue *dma_q)
+{
+       struct cx231xx_buffer *buf;
+
+       buf = dev->vbi_mode.bulk_ctl.buf;
+
+       if (buf == NULL) {
+               /* first try to get the buffer */
+               get_next_vbi_buf(dma_q, &buf);
+
+               dma_q->pos = 0;
+               dma_q->current_field = -1;
+       }
+
+       dma_q->bytes_left_in_line = dev->width << 1;
+       dma_q->lines_completed = 0;
+}
+
+int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+                       u8 *p_buffer, u32 bytes_to_copy)
+{
+       u8 *p_out_buffer = NULL;
+       u32 current_line_bytes_copied = 0;
+       struct cx231xx_buffer *buf;
+       u32 _line_size = dev->width << 1;
+       void *startwrite;
+       int offset, lencopy;
+
+       buf = dev->vbi_mode.bulk_ctl.buf;
+
+       if (buf == NULL)
+               return -EINVAL;
+
+       p_out_buffer = videobuf_to_vmalloc(&buf->vb);
+
+       if (dma_q->bytes_left_in_line != _line_size) {
+               current_line_bytes_copied =
+                   _line_size - dma_q->bytes_left_in_line;
+       }
+
+       offset = (dma_q->lines_completed * _line_size) +
+                current_line_bytes_copied;
+
+       if (dma_q->current_field == 2) {
+               /* Populate the second half of the frame */
+               offset += (dev->width * 2 * dma_q->lines_per_field);
+       }
+
+       /* prepare destination address */
+       startwrite = p_out_buffer + offset;
+
+       lencopy = dma_q->bytes_left_in_line > bytes_to_copy ?
+                 bytes_to_copy : dma_q->bytes_left_in_line;
+
+       memcpy(startwrite, p_buffer, lencopy);
+
+       return 0;
+}
+
+u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev,
+                             struct cx231xx_dmaqueue *dma_q)
+{
+       u32 height = 0;
+
+       height = ((dev->norm & V4L2_STD_625_50) ?
+                 PAL_VBI_LINES : NTSC_VBI_LINES);
+       if (dma_q->lines_completed == height && dma_q->current_field == 2)
+               return 1;
+       else
+               return 0;
+}
diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.h b/drivers/media/usb/cx231xx/cx231xx-vbi.h
new file mode 100644 (file)
index 0000000..16c7d20
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+   cx231xx_vbi.h - driver for Conexant Cx23100/101/102 USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+               Based on cx88 driver
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   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.
+ */
+
+#ifndef _CX231XX_VBI_H
+#define _CX231XX_VBI_H
+
+extern struct videobuf_queue_ops cx231xx_vbi_qops;
+
+#define   NTSC_VBI_START_LINE 10       /* line 10 - 21 */
+#define   NTSC_VBI_END_LINE   21
+#define   NTSC_VBI_LINES         (NTSC_VBI_END_LINE-NTSC_VBI_START_LINE+1)
+
+#define   PAL_VBI_START_LINE  6
+#define   PAL_VBI_END_LINE    23
+#define   PAL_VBI_LINES       (PAL_VBI_END_LINE-PAL_VBI_START_LINE+1)
+
+#define   VBI_STRIDE            1440
+#define   VBI_SAMPLES_PER_LINE  1440
+
+#define   CX231XX_NUM_VBI_PACKETS       4
+#define   CX231XX_NUM_VBI_BUFS          5
+
+/* stream functions */
+int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
+                         int num_bufs, int max_pkt_size,
+                         int (*bulk_copy) (struct cx231xx *dev,
+                                           struct urb *urb));
+
+void cx231xx_uninit_vbi_isoc(struct cx231xx *dev);
+
+/* vbi data copy functions */
+u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+                        u8 sav_eav, u8 *p_buffer, u32 buffer_size);
+
+u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+                         u8 *p_line, u32 length, int field_number);
+
+void cx231xx_reset_vbi_buffer(struct cx231xx *dev,
+                             struct cx231xx_dmaqueue *dma_q);
+
+int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+                       u8 *p_buffer, u32 bytes_to_copy);
+
+u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev,
+                             struct cx231xx_dmaqueue *dma_q);
+
+#endif
diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c
new file mode 100644 (file)
index 0000000..790b28d
--- /dev/null
@@ -0,0 +1,2670 @@
+/*
+   cx231xx-video.c - driver for Conexant Cx23100/101/102
+                    USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+       Based on em28xx driver
+       Based on cx23885 driver
+       Based on cx88 driver
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   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/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 <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/msp3400.h>
+#include <media/tuner.h>
+
+#include "dvb_frontend.h"
+
+#include "cx231xx.h"
+#include "cx231xx-vbi.h"
+
+#define CX231XX_VERSION "0.0.2"
+
+#define DRIVER_AUTHOR   "Srinivasa Deevi <srinivasa.deevi@conexant.com>"
+#define DRIVER_DESC     "Conexant cx231xx based USB video device driver"
+
+#define cx231xx_videodbg(fmt, arg...) do {\
+       if (video_debug) \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); } while (0)
+
+static unsigned int isoc_debug;
+module_param(isoc_debug, int, 0644);
+MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
+
+#define cx231xx_isocdbg(fmt, arg...) \
+do {\
+       if (isoc_debug) { \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); \
+       } \
+  } while (0)
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CX231XX_VERSION);
+
+static unsigned int card[]     = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
+static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
+static unsigned int vbi_nr[]   = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(card, int, NULL, 0444);
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(vbi_nr, int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+
+MODULE_PARM_DESC(card, "card type");
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
+
+static unsigned int video_debug;
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
+
+/* supported video standards */
+static struct cx231xx_fmt format[] = {
+       {
+        .name = "16bpp YUY2, 4:2:2, packed",
+        .fourcc = V4L2_PIX_FMT_YUYV,
+        .depth = 16,
+        .reg = 0,
+        },
+};
+
+/* supported controls */
+/* Common to all boards */
+
+/* ------------------------------------------------------------------- */
+
+static const struct v4l2_queryctrl no_ctl = {
+       .name = "42",
+       .flags = V4L2_CTRL_FLAG_DISABLED,
+};
+
+static struct cx231xx_ctrl cx231xx_ctls[] = {
+       /* --- video --- */
+       {
+               .v = {
+                       .id = V4L2_CID_BRIGHTNESS,
+                       .name = "Brightness",
+                       .minimum = 0x00,
+                       .maximum = 0xff,
+                       .step = 1,
+                       .default_value = 0x7f,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+               },
+               .off = 128,
+               .reg = LUMA_CTRL,
+               .mask = 0x00ff,
+               .shift = 0,
+       }, {
+               .v = {
+                       .id = V4L2_CID_CONTRAST,
+                       .name = "Contrast",
+                       .minimum = 0,
+                       .maximum = 0xff,
+                       .step = 1,
+                       .default_value = 0x3f,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+               },
+               .off = 0,
+               .reg = LUMA_CTRL,
+               .mask = 0xff00,
+               .shift = 8,
+       }, {
+               .v = {
+                       .id = V4L2_CID_HUE,
+                       .name = "Hue",
+                       .minimum = 0,
+                       .maximum = 0xff,
+                       .step = 1,
+                       .default_value = 0x7f,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+               },
+               .off = 128,
+               .reg = CHROMA_CTRL,
+               .mask = 0xff0000,
+               .shift = 16,
+       }, {
+       /* strictly, this only describes only U saturation.
+       * V saturation is handled specially through code.
+       */
+               .v = {
+                       .id = V4L2_CID_SATURATION,
+                       .name = "Saturation",
+                       .minimum = 0,
+                       .maximum = 0xff,
+                       .step = 1,
+                       .default_value = 0x7f,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+               },
+               .off = 0,
+               .reg = CHROMA_CTRL,
+               .mask = 0x00ff,
+               .shift = 0,
+       }, {
+               /* --- audio --- */
+               .v = {
+                       .id = V4L2_CID_AUDIO_MUTE,
+                       .name = "Mute",
+                       .minimum = 0,
+                       .maximum = 1,
+                       .default_value = 1,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+               },
+               .reg = PATH1_CTL1,
+               .mask = (0x1f << 24),
+               .shift = 24,
+       }, {
+               .v = {
+                       .id = V4L2_CID_AUDIO_VOLUME,
+                       .name = "Volume",
+                       .minimum = 0,
+                       .maximum = 0x3f,
+                       .step = 1,
+                       .default_value = 0x3f,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+               },
+               .reg = PATH1_VOL_CTL,
+               .mask = 0xff,
+               .shift = 0,
+       }
+};
+static const int CX231XX_CTLS = ARRAY_SIZE(cx231xx_ctls);
+
+static const u32 cx231xx_user_ctrls[] = {
+       V4L2_CID_USER_CLASS,
+       V4L2_CID_BRIGHTNESS,
+       V4L2_CID_CONTRAST,
+       V4L2_CID_SATURATION,
+       V4L2_CID_HUE,
+       V4L2_CID_AUDIO_VOLUME,
+#if 0
+       V4L2_CID_AUDIO_BALANCE,
+#endif
+       V4L2_CID_AUDIO_MUTE,
+       0
+};
+
+static const u32 *ctrl_classes[] = {
+       cx231xx_user_ctrls,
+       NULL
+};
+
+/* ------------------------------------------------------------------
+       Video buffer and parser functions
+   ------------------------------------------------------------------*/
+
+/*
+ * Announces that a buffer were filled and request the next
+ */
+static inline void buffer_filled(struct cx231xx *dev,
+                                struct cx231xx_dmaqueue *dma_q,
+                                struct cx231xx_buffer *buf)
+{
+       /* Advice that buffer was filled */
+       cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
+       buf->vb.state = VIDEOBUF_DONE;
+       buf->vb.field_count++;
+       do_gettimeofday(&buf->vb.ts);
+
+       if (dev->USE_ISO)
+               dev->video_mode.isoc_ctl.buf = NULL;
+       else
+               dev->video_mode.bulk_ctl.buf = NULL;
+
+       list_del(&buf->vb.queue);
+       wake_up(&buf->vb.done);
+}
+
+static inline void print_err_status(struct cx231xx *dev, int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+       if (packet < 0) {
+               cx231xx_isocdbg("URB status %d [%s].\n", status, errmsg);
+       } else {
+               cx231xx_isocdbg("URB packet %d, status %d [%s].\n",
+                               packet, status, errmsg);
+       }
+}
+
+/*
+ * video-buf generic routine to get the next available buffer
+ */
+static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q,
+                               struct cx231xx_buffer **buf)
+{
+       struct cx231xx_video_mode *vmode =
+           container_of(dma_q, struct cx231xx_video_mode, vidq);
+       struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode);
+
+       char *outp;
+
+       if (list_empty(&dma_q->active)) {
+               cx231xx_isocdbg("No active queue to serve\n");
+               if (dev->USE_ISO)
+                       dev->video_mode.isoc_ctl.buf = NULL;
+               else
+                       dev->video_mode.bulk_ctl.buf = NULL;
+               *buf = NULL;
+               return;
+       }
+
+       /* Get the next buffer */
+       *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue);
+
+       /* Cleans up buffer - Useful for testing for frame/URB loss */
+       outp = videobuf_to_vmalloc(&(*buf)->vb);
+       memset(outp, 0, (*buf)->vb.size);
+
+       if (dev->USE_ISO)
+               dev->video_mode.isoc_ctl.buf = *buf;
+       else
+               dev->video_mode.bulk_ctl.buf = *buf;
+
+       return;
+}
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
+{
+       struct cx231xx_dmaqueue *dma_q = urb->context;
+       int i, rc = 1;
+       unsigned char *p_buffer;
+       u32 bytes_parsed = 0, buffer_size = 0;
+       u8 sav_eav = 0;
+
+       if (!dev)
+               return 0;
+
+       if (dev->state & DEV_DISCONNECTED)
+               return 0;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               if (urb->status == -ENOENT)
+                       return 0;
+       }
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               int status = urb->iso_frame_desc[i].status;
+
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       if (urb->iso_frame_desc[i].status != -EPROTO)
+                               continue;
+               }
+
+               if (urb->iso_frame_desc[i].actual_length <= 0) {
+                       /* cx231xx_isocdbg("packet %d is empty",i); - spammy */
+                       continue;
+               }
+               if (urb->iso_frame_desc[i].actual_length >
+                   dev->video_mode.max_pkt_size) {
+                       cx231xx_isocdbg("packet bigger than packet size");
+                       continue;
+               }
+
+               /*  get buffer pointer and length */
+               p_buffer = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+               buffer_size = urb->iso_frame_desc[i].actual_length;
+               bytes_parsed = 0;
+
+               if (dma_q->is_partial_line) {
+                       /* Handle the case of a partial line */
+                       sav_eav = dma_q->last_sav;
+               } else {
+                       /* Check for a SAV/EAV overlapping
+                               the buffer boundary */
+                       sav_eav =
+                           cx231xx_find_boundary_SAV_EAV(p_buffer,
+                                                         dma_q->partial_buf,
+                                                         &bytes_parsed);
+               }
+
+               sav_eav &= 0xF0;
+               /* Get the first line if we have some portion of an SAV/EAV from
+                  the last buffer or a partial line  */
+               if (sav_eav) {
+                       bytes_parsed += cx231xx_get_video_line(dev, dma_q,
+                               sav_eav,        /* SAV/EAV */
+                               p_buffer + bytes_parsed,        /* p_buffer */
+                               buffer_size - bytes_parsed);/* buf size */
+               }
+
+               /* Now parse data that is completely in this buffer */
+               /* dma_q->is_partial_line = 0;  */
+
+               while (bytes_parsed < buffer_size) {
+                       u32 bytes_used = 0;
+
+                       sav_eav = cx231xx_find_next_SAV_EAV(
+                               p_buffer + bytes_parsed,        /* p_buffer */
+                               buffer_size - bytes_parsed,     /* buf size */
+                               &bytes_used);/* bytes used to get SAV/EAV */
+
+                       bytes_parsed += bytes_used;
+
+                       sav_eav &= 0xF0;
+                       if (sav_eav && (bytes_parsed < buffer_size)) {
+                               bytes_parsed += cx231xx_get_video_line(dev,
+                                       dma_q, sav_eav, /* SAV/EAV */
+                                       p_buffer + bytes_parsed,/* p_buffer */
+                                       buffer_size - bytes_parsed);/*buf size*/
+                       }
+               }
+
+               /* Save the last four bytes of the buffer so we can check the
+                  buffer boundary condition next time */
+               memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4);
+               bytes_parsed = 0;
+
+       }
+       return rc;
+}
+
+static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
+{
+       struct cx231xx_dmaqueue *dma_q = urb->context;
+       int rc = 1;
+       unsigned char *p_buffer;
+       u32 bytes_parsed = 0, buffer_size = 0;
+       u8 sav_eav = 0;
+
+       if (!dev)
+               return 0;
+
+       if (dev->state & DEV_DISCONNECTED)
+               return 0;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               if (urb->status == -ENOENT)
+                       return 0;
+       }
+
+       if (1) {
+
+               /*  get buffer pointer and length */
+               p_buffer = urb->transfer_buffer;
+               buffer_size = urb->actual_length;
+               bytes_parsed = 0;
+
+               if (dma_q->is_partial_line) {
+                       /* Handle the case of a partial line */
+                       sav_eav = dma_q->last_sav;
+               } else {
+                       /* Check for a SAV/EAV overlapping
+                               the buffer boundary */
+                       sav_eav =
+                           cx231xx_find_boundary_SAV_EAV(p_buffer,
+                                                         dma_q->partial_buf,
+                                                         &bytes_parsed);
+               }
+
+               sav_eav &= 0xF0;
+               /* Get the first line if we have some portion of an SAV/EAV from
+                  the last buffer or a partial line  */
+               if (sav_eav) {
+                       bytes_parsed += cx231xx_get_video_line(dev, dma_q,
+                               sav_eav,        /* SAV/EAV */
+                               p_buffer + bytes_parsed,        /* p_buffer */
+                               buffer_size - bytes_parsed);/* buf size */
+               }
+
+               /* Now parse data that is completely in this buffer */
+               /* dma_q->is_partial_line = 0;  */
+
+               while (bytes_parsed < buffer_size) {
+                       u32 bytes_used = 0;
+
+                       sav_eav = cx231xx_find_next_SAV_EAV(
+                               p_buffer + bytes_parsed,        /* p_buffer */
+                               buffer_size - bytes_parsed,     /* buf size */
+                               &bytes_used);/* bytes used to get SAV/EAV */
+
+                       bytes_parsed += bytes_used;
+
+                       sav_eav &= 0xF0;
+                       if (sav_eav && (bytes_parsed < buffer_size)) {
+                               bytes_parsed += cx231xx_get_video_line(dev,
+                                       dma_q, sav_eav, /* SAV/EAV */
+                                       p_buffer + bytes_parsed,/* p_buffer */
+                                       buffer_size - bytes_parsed);/*buf size*/
+                       }
+               }
+
+               /* Save the last four bytes of the buffer so we can check the
+                  buffer boundary condition next time */
+               memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4);
+               bytes_parsed = 0;
+
+       }
+       return rc;
+}
+
+
+u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf,
+                                u32 *p_bytes_used)
+{
+       u32 bytes_used;
+       u8 boundary_bytes[8];
+       u8 sav_eav = 0;
+
+       *p_bytes_used = 0;
+
+       /* Create an array of the last 4 bytes of the last buffer and the first
+          4 bytes of the current buffer. */
+
+       memcpy(boundary_bytes, partial_buf, 4);
+       memcpy(boundary_bytes + 4, p_buffer, 4);
+
+       /* Check for the SAV/EAV in the boundary buffer */
+       sav_eav = cx231xx_find_next_SAV_EAV((u8 *)&boundary_bytes, 8,
+                                           &bytes_used);
+
+       if (sav_eav) {
+               /* found a boundary SAV/EAV.  Updates the bytes used to reflect
+                  only those used in the new buffer */
+               *p_bytes_used = bytes_used - 4;
+       }
+
+       return sav_eav;
+}
+
+u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, u32 *p_bytes_used)
+{
+       u32 i;
+       u8 sav_eav = 0;
+
+       /*
+        * Don't search if the buffer size is less than 4.  It causes a page
+        * fault since buffer_size - 4 evaluates to a large number in that
+        * case.
+        */
+       if (buffer_size < 4) {
+               *p_bytes_used = buffer_size;
+               return 0;
+       }
+
+       for (i = 0; i < (buffer_size - 3); i++) {
+
+               if ((p_buffer[i] == 0xFF) &&
+                   (p_buffer[i + 1] == 0x00) && (p_buffer[i + 2] == 0x00)) {
+
+                       *p_bytes_used = i + 4;
+                       sav_eav = p_buffer[i + 3];
+                       return sav_eav;
+               }
+       }
+
+       *p_bytes_used = buffer_size;
+       return 0;
+}
+
+u32 cx231xx_get_video_line(struct cx231xx *dev,
+                          struct cx231xx_dmaqueue *dma_q, u8 sav_eav,
+                          u8 *p_buffer, u32 buffer_size)
+{
+       u32 bytes_copied = 0;
+       int current_field = -1;
+
+       switch (sav_eav) {
+       case SAV_ACTIVE_VIDEO_FIELD1:
+               /* looking for skipped line which occurred in PAL 720x480 mode.
+                  In this case, there will be no active data contained
+                  between the SAV and EAV */
+               if ((buffer_size > 3) && (p_buffer[0] == 0xFF) &&
+                   (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) &&
+                   ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) ||
+                    (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) ||
+                    (p_buffer[3] == EAV_VBLANK_FIELD1) ||
+                    (p_buffer[3] == EAV_VBLANK_FIELD2)))
+                       return bytes_copied;
+               current_field = 1;
+               break;
+
+       case SAV_ACTIVE_VIDEO_FIELD2:
+               /* looking for skipped line which occurred in PAL 720x480 mode.
+                  In this case, there will be no active data contained between
+                  the SAV and EAV */
+               if ((buffer_size > 3) && (p_buffer[0] == 0xFF) &&
+                   (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) &&
+                   ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) ||
+                    (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) ||
+                    (p_buffer[3] == EAV_VBLANK_FIELD1)       ||
+                    (p_buffer[3] == EAV_VBLANK_FIELD2)))
+                       return bytes_copied;
+               current_field = 2;
+               break;
+       }
+
+       dma_q->last_sav = sav_eav;
+
+       bytes_copied = cx231xx_copy_video_line(dev, dma_q, p_buffer,
+                                              buffer_size, current_field);
+
+       return bytes_copied;
+}
+
+u32 cx231xx_copy_video_line(struct cx231xx *dev,
+                           struct cx231xx_dmaqueue *dma_q, u8 *p_line,
+                           u32 length, int field_number)
+{
+       u32 bytes_to_copy;
+       struct cx231xx_buffer *buf;
+       u32 _line_size = dev->width * 2;
+
+       if (dma_q->current_field != field_number)
+               cx231xx_reset_video_buffer(dev, dma_q);
+
+       /* get the buffer pointer */
+       if (dev->USE_ISO)
+               buf = dev->video_mode.isoc_ctl.buf;
+       else
+               buf = dev->video_mode.bulk_ctl.buf;
+
+       /* Remember the field number for next time */
+       dma_q->current_field = field_number;
+
+       bytes_to_copy = dma_q->bytes_left_in_line;
+       if (bytes_to_copy > length)
+               bytes_to_copy = length;
+
+       if (dma_q->lines_completed >= dma_q->lines_per_field) {
+               dma_q->bytes_left_in_line -= bytes_to_copy;
+               dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ?
+                                         0 : 1;
+               return 0;
+       }
+
+       dma_q->is_partial_line = 1;
+
+       /* If we don't have a buffer, just return the number of bytes we would
+          have copied if we had a buffer. */
+       if (!buf) {
+               dma_q->bytes_left_in_line -= bytes_to_copy;
+               dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0)
+                                        ? 0 : 1;
+               return bytes_to_copy;
+       }
+
+       /* copy the data to video buffer */
+       cx231xx_do_copy(dev, dma_q, p_line, bytes_to_copy);
+
+       dma_q->pos += bytes_to_copy;
+       dma_q->bytes_left_in_line -= bytes_to_copy;
+
+       if (dma_q->bytes_left_in_line == 0) {
+               dma_q->bytes_left_in_line = _line_size;
+               dma_q->lines_completed++;
+               dma_q->is_partial_line = 0;
+
+               if (cx231xx_is_buffer_done(dev, dma_q) && buf) {
+                       buffer_filled(dev, dma_q, buf);
+
+                       dma_q->pos = 0;
+                       buf = NULL;
+                       dma_q->lines_completed = 0;
+               }
+       }
+
+       return bytes_to_copy;
+}
+
+void cx231xx_reset_video_buffer(struct cx231xx *dev,
+                               struct cx231xx_dmaqueue *dma_q)
+{
+       struct cx231xx_buffer *buf;
+
+       /* handle the switch from field 1 to field 2 */
+       if (dma_q->current_field == 1) {
+               if (dma_q->lines_completed >= dma_q->lines_per_field)
+                       dma_q->field1_done = 1;
+               else
+                       dma_q->field1_done = 0;
+       }
+
+       if (dev->USE_ISO)
+               buf = dev->video_mode.isoc_ctl.buf;
+       else
+               buf = dev->video_mode.bulk_ctl.buf;
+
+       if (buf == NULL) {
+               /* first try to get the buffer */
+               get_next_buf(dma_q, &buf);
+
+               dma_q->pos = 0;
+               dma_q->field1_done = 0;
+               dma_q->current_field = -1;
+       }
+
+       /* reset the counters */
+       dma_q->bytes_left_in_line = dev->width << 1;
+       dma_q->lines_completed = 0;
+}
+
+int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+                   u8 *p_buffer, u32 bytes_to_copy)
+{
+       u8 *p_out_buffer = NULL;
+       u32 current_line_bytes_copied = 0;
+       struct cx231xx_buffer *buf;
+       u32 _line_size = dev->width << 1;
+       void *startwrite;
+       int offset, lencopy;
+
+       if (dev->USE_ISO)
+               buf = dev->video_mode.isoc_ctl.buf;
+       else
+               buf = dev->video_mode.bulk_ctl.buf;
+
+       if (buf == NULL)
+               return -1;
+
+       p_out_buffer = videobuf_to_vmalloc(&buf->vb);
+
+       current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line;
+
+       /* Offset field 2 one line from the top of the buffer */
+       offset = (dma_q->current_field == 1) ? 0 : _line_size;
+
+       /* Offset for field 2 */
+       startwrite = p_out_buffer + offset;
+
+       /* lines already completed in the current field */
+       startwrite += (dma_q->lines_completed * _line_size * 2);
+
+       /* bytes already completed in the current line */
+       startwrite += current_line_bytes_copied;
+
+       lencopy = dma_q->bytes_left_in_line > bytes_to_copy ?
+                 bytes_to_copy : dma_q->bytes_left_in_line;
+
+       if ((u8 *)(startwrite + lencopy) > (u8 *)(p_out_buffer + buf->vb.size))
+               return 0;
+
+       /* The below copies the UYVY data straight into video buffer */
+       cx231xx_swab((u16 *) p_buffer, (u16 *) startwrite, (u16) lencopy);
+
+       return 0;
+}
+
+void cx231xx_swab(u16 *from, u16 *to, u16 len)
+{
+       u16 i;
+
+       if (len <= 0)
+               return;
+
+       for (i = 0; i < len / 2; i++)
+               to[i] = (from[i] << 8) | (from[i] >> 8);
+}
+
+u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q)
+{
+       u8 buffer_complete = 0;
+
+       /* Dual field stream */
+       buffer_complete = ((dma_q->current_field == 2) &&
+                          (dma_q->lines_completed >= dma_q->lines_per_field) &&
+                           dma_q->field1_done);
+
+       return buffer_complete;
+}
+
+/* ------------------------------------------------------------------
+       Videobuf operations
+   ------------------------------------------------------------------*/
+
+static int
+buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
+{
+       struct cx231xx_fh *fh = vq->priv_data;
+       struct cx231xx *dev = fh->dev;
+
+       *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7)>>3;
+       if (0 == *count)
+               *count = CX231XX_DEF_BUF;
+
+       if (*count < CX231XX_MIN_BUF)
+               *count = CX231XX_MIN_BUF;
+
+       return 0;
+}
+
+/* This is called *without* dev->slock held; please keep it that way */
+static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
+{
+       struct cx231xx_fh *fh = vq->priv_data;
+       struct cx231xx *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->video_mode.slock, flags);
+       if (dev->USE_ISO) {
+               if (dev->video_mode.isoc_ctl.buf == buf)
+                       dev->video_mode.isoc_ctl.buf = NULL;
+       } else {
+               if (dev->video_mode.bulk_ctl.buf == buf)
+                       dev->video_mode.bulk_ctl.buf = NULL;
+       }
+       spin_unlock_irqrestore(&dev->video_mode.slock, flags);
+
+       videobuf_vmalloc_free(&buf->vb);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+              enum v4l2_field field)
+{
+       struct cx231xx_fh *fh = vq->priv_data;
+       struct cx231xx_buffer *buf =
+           container_of(vb, struct cx231xx_buffer, vb);
+       struct cx231xx *dev = fh->dev;
+       int rc = 0, urb_init = 0;
+
+       /* The only currently supported format is 16 bits/pixel */
+       buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth
+                       + 7) >> 3;
+       if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+               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)
+                       goto fail;
+       }
+
+       if (dev->USE_ISO) {
+               if (!dev->video_mode.isoc_ctl.num_bufs)
+                       urb_init = 1;
+       } else {
+               if (!dev->video_mode.bulk_ctl.num_bufs)
+                       urb_init = 1;
+       }
+       /*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n",
+               urb_init, dev->video_mode.max_pkt_size);*/
+       if (urb_init) {
+               dev->mode_tv = 0;
+               if (dev->USE_ISO)
+                       rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
+                                      CX231XX_NUM_BUFS,
+                                      dev->video_mode.max_pkt_size,
+                                      cx231xx_isoc_copy);
+               else
+                       rc = cx231xx_init_bulk(dev, CX231XX_NUM_PACKETS,
+                                      CX231XX_NUM_BUFS,
+                                      dev->video_mode.max_pkt_size,
+                                      cx231xx_bulk_copy);
+               if (rc < 0)
+                       goto fail;
+       }
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+fail:
+       free_buffer(vq, buf);
+       return rc;
+}
+
+static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct cx231xx_buffer *buf =
+           container_of(vb, struct cx231xx_buffer, vb);
+       struct cx231xx_fh *fh = vq->priv_data;
+       struct cx231xx *dev = fh->dev;
+       struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
+
+       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 cx231xx_buffer *buf =
+           container_of(vb, struct cx231xx_buffer, vb);
+       struct cx231xx_fh *fh = vq->priv_data;
+       struct cx231xx *dev = (struct cx231xx *)fh->dev;
+
+       cx231xx_isocdbg("cx231xx: called buffer_release\n");
+
+       free_buffer(vq, buf);
+}
+
+static struct videobuf_queue_ops cx231xx_video_qops = {
+       .buf_setup = buffer_setup,
+       .buf_prepare = buffer_prepare,
+       .buf_queue = buffer_queue,
+       .buf_release = buffer_release,
+};
+
+/*********************  v4l2 interface  **************************************/
+
+void video_mux(struct cx231xx *dev, int index)
+{
+       dev->video_input = index;
+       dev->ctl_ainput = INPUT(index)->amux;
+
+       cx231xx_set_video_input_mux(dev, index);
+
+       cx25840_call(dev, video, s_routing, INPUT(index)->vmux, 0, 0);
+
+       cx231xx_set_audio_input(dev, dev->ctl_ainput);
+
+       cx231xx_info("video_mux : %d\n", index);
+
+       /* do mode control overrides if required */
+       cx231xx_do_mode_ctrl_overrides(dev);
+}
+
+/* Usage lock check functions */
+static int res_get(struct cx231xx_fh *fh)
+{
+       struct cx231xx *dev = fh->dev;
+       int rc = 0;
+
+       /* This instance already has stream_on */
+       if (fh->stream_on)
+               return rc;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               if (dev->stream_on)
+                       return -EBUSY;
+               dev->stream_on = 1;
+       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+               if (dev->vbi_stream_on)
+                       return -EBUSY;
+               dev->vbi_stream_on = 1;
+       } else
+               return -EINVAL;
+
+       fh->stream_on = 1;
+
+       return rc;
+}
+
+static int res_check(struct cx231xx_fh *fh)
+{
+       return fh->stream_on;
+}
+
+static void res_free(struct cx231xx_fh *fh)
+{
+       struct cx231xx *dev = fh->dev;
+
+       fh->stream_on = 0;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               dev->stream_on = 0;
+       if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+               dev->vbi_stream_on = 0;
+}
+
+static int check_dev(struct cx231xx *dev)
+{
+       if (dev->state & DEV_DISCONNECTED) {
+               cx231xx_errdev("v4l2 ioctl: device not present\n");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+/* ------------------------------------------------------------------
+       IOCTL vidioc handling
+   ------------------------------------------------------------------*/
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+
+       f->fmt.pix.width = dev->width;
+       f->fmt.pix.height = dev->height;
+       f->fmt.pix.pixelformat = dev->format->fourcc;
+       f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;
+       f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+       return 0;
+}
+
+static struct cx231xx_fmt *format_by_fourcc(unsigned int fourcc)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(format); i++)
+               if (format[i].fourcc == fourcc)
+                       return &format[i];
+
+       return NULL;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       unsigned int width = f->fmt.pix.width;
+       unsigned int height = f->fmt.pix.height;
+       unsigned int maxw = norm_maxw(dev);
+       unsigned int maxh = norm_maxh(dev);
+       struct cx231xx_fmt *fmt;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       if (!fmt) {
+               cx231xx_videodbg("Fourcc format (%08x) invalid.\n",
+                                f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       /* width must even because of the YUYV format
+          height must be even because of interlacing */
+       v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0);
+
+       f->fmt.pix.width = width;
+       f->fmt.pix.height = height;
+       f->fmt.pix.pixelformat = fmt->fourcc;
+       f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3;
+       f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+       struct cx231xx_fmt *fmt;
+       struct v4l2_mbus_framefmt mbus_fmt;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       vidioc_try_fmt_vid_cap(file, priv, f);
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       if (!fmt)
+               return -EINVAL;
+
+       if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+               cx231xx_errdev("%s queue busy\n", __func__);
+               return -EBUSY;
+       }
+
+       if (dev->stream_on && !fh->stream_on) {
+               cx231xx_errdev("%s device in use by another fh\n", __func__);
+               return -EBUSY;
+       }
+
+       /* set new image size */
+       dev->width = f->fmt.pix.width;
+       dev->height = f->fmt.pix.height;
+       dev->format = fmt;
+
+       v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
+       call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+       v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
+
+       return rc;
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+
+       *id = dev->norm;
+       return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       struct v4l2_mbus_framefmt mbus_fmt;
+       struct v4l2_format f;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       cx231xx_info("vidioc_s_std : 0x%x\n", (unsigned int)*norm);
+
+       dev->norm = *norm;
+
+       /* Adjusts width/height, if needed */
+       f.fmt.pix.width = dev->width;
+       f.fmt.pix.height = dev->height;
+       vidioc_try_fmt_vid_cap(file, priv, &f);
+
+       call_all(dev, core, s_std, dev->norm);
+
+       /* We need to reset basic properties in the decoder related to
+          resolution (since a standard change effects things like the number
+          of lines in VACT, etc) */
+       v4l2_fill_mbus_format(&mbus_fmt, &f.fmt.pix, V4L2_MBUS_FMT_FIXED);
+       call_all(dev, video, s_mbus_fmt, &mbus_fmt);
+       v4l2_fill_pix_format(&f.fmt.pix, &mbus_fmt);
+
+       /* set new image size */
+       dev->width = f.fmt.pix.width;
+       dev->height = f.fmt.pix.height;
+
+       /* do mode control overrides */
+       cx231xx_do_mode_ctrl_overrides(dev);
+
+       return 0;
+}
+
+static const char *iname[] = {
+       [CX231XX_VMUX_COMPOSITE1] = "Composite1",
+       [CX231XX_VMUX_SVIDEO]     = "S-Video",
+       [CX231XX_VMUX_TELEVISION] = "Television",
+       [CX231XX_VMUX_CABLE]      = "Cable TV",
+       [CX231XX_VMUX_DVB]        = "DVB",
+       [CX231XX_VMUX_DEBUG]      = "for debug only",
+};
+
+static int vidioc_enum_input(struct file *file, void *priv,
+                            struct v4l2_input *i)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       u32 gen_stat;
+       unsigned int ret, n;
+
+       n = i->index;
+       if (n >= MAX_CX231XX_INPUT)
+               return -EINVAL;
+       if (0 == INPUT(n)->type)
+               return -EINVAL;
+
+       i->index = n;
+       i->type = V4L2_INPUT_TYPE_CAMERA;
+
+       strcpy(i->name, iname[INPUT(n)->type]);
+
+       if ((CX231XX_VMUX_TELEVISION == INPUT(n)->type) ||
+           (CX231XX_VMUX_CABLE == INPUT(n)->type))
+               i->type = V4L2_INPUT_TYPE_TUNER;
+
+       i->std = dev->vdev->tvnorms;
+
+       /* If they are asking about the active input, read signal status */
+       if (n == dev->video_input) {
+               ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+                                           GEN_STAT, 2, &gen_stat, 4);
+               if (ret > 0) {
+                       if ((gen_stat & FLD_VPRES) == 0x00)
+                               i->status |= V4L2_IN_ST_NO_SIGNAL;
+                       if ((gen_stat & FLD_HLOCK) == 0x00)
+                               i->status |= V4L2_IN_ST_NO_H_LOCK;
+               }
+       }
+
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+
+       *i = dev->video_input;
+
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       dev->mode_tv = 0;
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (i >= MAX_CX231XX_INPUT)
+               return -EINVAL;
+       if (0 == INPUT(i)->type)
+               return -EINVAL;
+
+       video_mux(dev, i);
+
+       if (INPUT(i)->type == CX231XX_VMUX_TELEVISION ||
+           INPUT(i)->type == CX231XX_VMUX_CABLE) {
+               /* There's a tuner, so reset the standard and put it on the
+                  last known frequency (since it was probably powered down
+                  until now */
+               call_all(dev, core, s_std, dev->norm);
+       }
+
+       return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+
+       switch (a->index) {
+       case CX231XX_AMUX_VIDEO:
+               strcpy(a->name, "Television");
+               break;
+       case CX231XX_AMUX_LINE_IN:
+               strcpy(a->name, "Line In");
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       a->index = dev->ctl_ainput;
+       a->capability = V4L2_AUDCAP_STEREO;
+
+       return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int status = 0;
+
+       /* Doesn't allow manual routing */
+       if (a->index != dev->ctl_ainput)
+               return -EINVAL;
+
+       dev->ctl_ainput = INPUT(a->index)->amux;
+       status = cx231xx_set_audio_input(dev, dev->ctl_ainput);
+
+       return status;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+                           struct v4l2_queryctrl *qc)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int id = qc->id;
+       int i;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       qc->id = v4l2_ctrl_next(ctrl_classes, qc->id);
+       if (unlikely(qc->id == 0))
+               return -EINVAL;
+
+       memset(qc, 0, sizeof(*qc));
+
+       qc->id = id;
+
+       if (qc->id < V4L2_CID_BASE || qc->id >= V4L2_CID_LASTP1)
+               return -EINVAL;
+
+       for (i = 0; i < CX231XX_CTLS; i++)
+               if (cx231xx_ctls[i].v.id == qc->id)
+                       break;
+
+       if (i == CX231XX_CTLS) {
+               *qc = no_ctl;
+               return 0;
+       }
+       *qc = cx231xx_ctls[i].v;
+
+       call_all(dev, core, queryctrl, qc);
+
+       if (qc->type)
+               return 0;
+       else
+               return -EINVAL;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+                        struct v4l2_control *ctrl)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       call_all(dev, core, g_ctrl, ctrl);
+       return rc;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                        struct v4l2_control *ctrl)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       call_all(dev, core, s_ctrl, ctrl);
+       return rc;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (0 != t->index)
+               return -EINVAL;
+
+       strcpy(t->name, "Tuner");
+
+       t->type = V4L2_TUNER_ANALOG_TV;
+       t->capability = V4L2_TUNER_CAP_NORM;
+       t->rangehigh = 0xffffffffUL;
+       t->signal = 0xffff;     /* LOCKED */
+
+       return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (0 != t->index)
+               return -EINVAL;
+#if 0
+       call_all(dev, tuner, s_tuner, t);
+#endif
+       return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+                             struct v4l2_frequency *f)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+
+       f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+       f->frequency = dev->ctl_freq;
+
+       call_all(dev, tuner, g_frequency, f);
+
+       return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+                             struct v4l2_frequency *f)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+       u32 if_frequency = 5400000;
+
+       cx231xx_info("Enter vidioc_s_frequency()f->frequency=%d;f->type=%d\n",
+                f->frequency, f->type);
+       /*cx231xx_info("f->type:  1-radio 2-analogTV 3-digitalTV\n");*/
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (0 != f->tuner)
+               return -EINVAL;
+
+       if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
+               return -EINVAL;
+       if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
+               return -EINVAL;
+
+       /* set pre channel change settings in DIF first */
+       rc = cx231xx_tuner_pre_channel_change(dev);
+
+       dev->ctl_freq = f->frequency;
+       call_all(dev, tuner, s_frequency, f);
+
+       /* set post channel change settings in DIF first */
+       rc = cx231xx_tuner_post_channel_change(dev);
+
+       if (dev->tuner_type == TUNER_NXP_TDA18271) {
+               if (dev->norm & (V4L2_STD_MN | V4L2_STD_NTSC_443))
+                       if_frequency = 5400000;  /*5.4MHz       */
+               else if (dev->norm & V4L2_STD_B)
+                       if_frequency = 6000000;  /*6.0MHz       */
+               else if (dev->norm & (V4L2_STD_PAL_DK | V4L2_STD_SECAM_DK))
+                       if_frequency = 6900000;  /*6.9MHz       */
+               else if (dev->norm & V4L2_STD_GH)
+                       if_frequency = 7100000;  /*7.1MHz       */
+               else if (dev->norm & V4L2_STD_PAL_I)
+                       if_frequency = 7250000;  /*7.25MHz      */
+               else if (dev->norm & V4L2_STD_SECAM_L)
+                       if_frequency = 6900000;  /*6.9MHz       */
+               else if (dev->norm & V4L2_STD_SECAM_LC)
+                       if_frequency = 1250000;  /*1.25MHz      */
+
+               cx231xx_info("if_frequency is set to %d\n", if_frequency);
+               cx231xx_set_Colibri_For_LowIF(dev, if_frequency, 1, 1);
+
+               update_HH_register_after_set_DIF(dev);
+       }
+
+       cx231xx_info("Set New FREQUENCY to %d\n", f->frequency);
+
+       return rc;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+
+/*
+  -R, --list-registers=type=<host/i2cdrv/i2caddr>,
+                               chip=<chip>[,min=<addr>,max=<addr>]
+                    dump registers from <min> to <max> [VIDIOC_DBG_G_REGISTER]
+  -r, --set-register=type=<host/i2cdrv/i2caddr>,
+                               chip=<chip>,reg=<addr>,val=<val>
+                    set the register [VIDIOC_DBG_S_REGISTER]
+
+  if type == host, then <chip> is the hosts chip ID (default 0)
+  if type == i2cdrv (default), then <chip> is the I2C driver name or ID
+  if type == i2caddr, then <chip> is the 7-bit I2C address
+*/
+
+static int vidioc_g_register(struct file *file, void *priv,
+                            struct v4l2_dbg_register *reg)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int ret = 0;
+       u8 value[4] = { 0, 0, 0, 0 };
+       u32 data = 0;
+
+       switch (reg->match.type) {
+       case V4L2_CHIP_MATCH_HOST:
+               switch (reg->match.addr) {
+               case 0: /* Cx231xx - internal registers */
+                       ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER,
+                                                 (u16)reg->reg, value, 4);
+                       reg->val = value[0] | value[1] << 8 |
+                                  value[2] << 16 | value[3] << 24;
+                       break;
+               case 1: /* AFE - read byte */
+                       ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS,
+                                                 (u16)reg->reg, 2, &data, 1);
+                       reg->val = le32_to_cpu(data & 0xff);
+                       break;
+               case 14: /* AFE - read dword */
+                       ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS,
+                                                 (u16)reg->reg, 2, &data, 4);
+                       reg->val = le32_to_cpu(data);
+                       break;
+               case 2: /* Video Block - read byte */
+                       ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+                                                 (u16)reg->reg, 2, &data, 1);
+                       reg->val = le32_to_cpu(data & 0xff);
+                       break;
+               case 24: /* Video Block - read dword */
+                       ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
+                                                 (u16)reg->reg, 2, &data, 4);
+                       reg->val = le32_to_cpu(data);
+                       break;
+               case 3: /* I2S block - read byte */
+                       ret = cx231xx_read_i2c_data(dev,
+                                                   I2S_BLK_DEVICE_ADDRESS,
+                                                   (u16)reg->reg, 1,
+                                                   &data, 1);
+                       reg->val = le32_to_cpu(data & 0xff);
+                       break;
+               case 34: /* I2S Block - read dword */
+                       ret =
+                           cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
+                                                 (u16)reg->reg, 1, &data, 4);
+                       reg->val = le32_to_cpu(data);
+                       break;
+               }
+               return ret < 0 ? ret : 0;
+
+       case V4L2_CHIP_MATCH_I2C_DRIVER:
+               call_all(dev, core, g_register, reg);
+               return 0;
+       case V4L2_CHIP_MATCH_I2C_ADDR:/*for register debug*/
+               switch (reg->match.addr) {
+               case 0: /* Cx231xx - internal registers */
+                       ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER,
+                                                 (u16)reg->reg, value, 4);
+                       reg->val = value[0] | value[1] << 8 |
+                                  value[2] << 16 | value[3] << 24;
+
+                       break;
+               case 0x600:/* AFE - read byte */
+                       ret = cx231xx_read_i2c_master(dev, AFE_DEVICE_ADDRESS,
+                                                (u16)reg->reg, 2,
+                                                &data, 1 , 0);
+                       reg->val = le32_to_cpu(data & 0xff);
+                       break;
+
+               case 0x880:/* Video Block - read byte */
+                       if (reg->reg < 0x0b) {
+                               ret = cx231xx_read_i2c_master(dev,
+                                               VID_BLK_I2C_ADDRESS,
+                                                (u16)reg->reg, 2,
+                                                &data, 1 , 0);
+                               reg->val = le32_to_cpu(data & 0xff);
+                       } else {
+                               ret = cx231xx_read_i2c_master(dev,
+                                               VID_BLK_I2C_ADDRESS,
+                                                (u16)reg->reg, 2,
+                                                &data, 4 , 0);
+                               reg->val = le32_to_cpu(data);
+                       }
+                       break;
+               case 0x980:
+                       ret = cx231xx_read_i2c_master(dev,
+                                               I2S_BLK_DEVICE_ADDRESS,
+                                               (u16)reg->reg, 1,
+                                               &data, 1 , 0);
+                       reg->val = le32_to_cpu(data & 0xff);
+                       break;
+               case 0x400:
+                       ret =
+                           cx231xx_read_i2c_master(dev, 0x40,
+                                                 (u16)reg->reg, 1,
+                                                &data, 1 , 0);
+                       reg->val = le32_to_cpu(data & 0xff);
+                       break;
+               case 0xc01:
+                       ret =
+                               cx231xx_read_i2c_master(dev, 0xc0,
+                                               (u16)reg->reg, 2,
+                                                &data, 38, 1);
+                       reg->val = le32_to_cpu(data);
+                       break;
+               case 0x022:
+                       ret =
+                               cx231xx_read_i2c_master(dev, 0x02,
+                                               (u16)reg->reg, 1,
+                                                &data, 1, 2);
+                       reg->val = le32_to_cpu(data & 0xff);
+                       break;
+               case 0x322:
+                       ret = cx231xx_read_i2c_master(dev,
+                                               0x32,
+                                                (u16)reg->reg, 1,
+                                                &data, 4 , 2);
+                               reg->val = le32_to_cpu(data);
+                       break;
+               case 0x342:
+                       ret = cx231xx_read_i2c_master(dev,
+                                               0x34,
+                                                (u16)reg->reg, 1,
+                                                &data, 4 , 2);
+                               reg->val = le32_to_cpu(data);
+                       break;
+
+               default:
+                       cx231xx_info("no match device address!!\n");
+                       break;
+                       }
+               return ret < 0 ? ret : 0;
+               /*return -EINVAL;*/
+       default:
+               if (!v4l2_chip_match_host(&reg->match))
+                       return -EINVAL;
+       }
+
+       call_all(dev, core, g_register, reg);
+
+       return ret;
+}
+
+static int vidioc_s_register(struct file *file, void *priv,
+                            struct v4l2_dbg_register *reg)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int ret = 0;
+       __le64 buf;
+       u32 value;
+       u8 data[4] = { 0, 0, 0, 0 };
+
+       buf = cpu_to_le64(reg->val);
+
+       switch (reg->match.type) {
+       case V4L2_CHIP_MATCH_HOST:
+               {
+                       value = (u32) buf & 0xffffffff;
+
+                       switch (reg->match.addr) {
+                       case 0: /* cx231xx internal registers */
+                               data[0] = (u8) value;
+                               data[1] = (u8) (value >> 8);
+                               data[2] = (u8) (value >> 16);
+                               data[3] = (u8) (value >> 24);
+                               ret = cx231xx_write_ctrl_reg(dev,
+                                                          VRT_SET_REGISTER,
+                                                          (u16)reg->reg, data,
+                                                          4);
+                               break;
+                       case 1: /* AFE - read byte */
+                               ret = cx231xx_write_i2c_data(dev,
+                                                       AFE_DEVICE_ADDRESS,
+                                                       (u16)reg->reg, 2,
+                                                       value, 1);
+                               break;
+                       case 14: /* AFE - read dword */
+                               ret = cx231xx_write_i2c_data(dev,
+                                                       AFE_DEVICE_ADDRESS,
+                                                       (u16)reg->reg, 2,
+                                                       value, 4);
+                               break;
+                       case 2: /* Video Block - read byte */
+                               ret =
+                                   cx231xx_write_i2c_data(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       (u16)reg->reg, 2,
+                                                       value, 1);
+                               break;
+                       case 24: /* Video Block - read dword */
+                               ret =
+                                   cx231xx_write_i2c_data(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       (u16)reg->reg, 2,
+                                                       value, 4);
+                               break;
+                       case 3: /* I2S block - read byte */
+                               ret =
+                                   cx231xx_write_i2c_data(dev,
+                                                       I2S_BLK_DEVICE_ADDRESS,
+                                                       (u16)reg->reg, 1,
+                                                       value, 1);
+                               break;
+                       case 34: /* I2S block - read dword */
+                               ret =
+                                   cx231xx_write_i2c_data(dev,
+                                                       I2S_BLK_DEVICE_ADDRESS,
+                                                       (u16)reg->reg, 1,
+                                                       value, 4);
+                               break;
+                       }
+               }
+               return ret < 0 ? ret : 0;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               {
+                       value = (u32) buf & 0xffffffff;
+
+                       switch (reg->match.addr) {
+                       case 0:/*cx231xx internal registers*/
+                                       data[0] = (u8) value;
+                                       data[1] = (u8) (value >> 8);
+                                       data[2] = (u8) (value >> 16);
+                                       data[3] = (u8) (value >> 24);
+                                       ret = cx231xx_write_ctrl_reg(dev,
+                                                          VRT_SET_REGISTER,
+                                                          (u16)reg->reg, data,
+                                                          4);
+                                       break;
+                       case 0x600:/* AFE - read byte */
+                                       ret = cx231xx_write_i2c_master(dev,
+                                                       AFE_DEVICE_ADDRESS,
+                                                       (u16)reg->reg, 2,
+                                                       value, 1 , 0);
+                                       break;
+
+                       case 0x880:/* Video Block - read byte */
+                                       if (reg->reg < 0x0b)
+                                               cx231xx_write_i2c_master(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       (u16)reg->reg, 2,
+                                                       value, 1, 0);
+                                       else
+                                               cx231xx_write_i2c_master(dev,
+                                                       VID_BLK_I2C_ADDRESS,
+                                                       (u16)reg->reg, 2,
+                                                       value, 4, 0);
+                                       break;
+                       case 0x980:
+                                       ret =
+                                               cx231xx_write_i2c_master(dev,
+                                                       I2S_BLK_DEVICE_ADDRESS,
+                                                       (u16)reg->reg, 1,
+                                                       value, 1, 0);
+                                       break;
+                       case 0x400:
+                                       ret =
+                                               cx231xx_write_i2c_master(dev,
+                                                       0x40,
+                                                       (u16)reg->reg, 1,
+                                                       value, 1, 0);
+                                       break;
+                       case 0xc01:
+                                       ret =
+                                               cx231xx_write_i2c_master(dev,
+                                                        0xc0,
+                                                        (u16)reg->reg, 1,
+                                                        value, 1, 1);
+                                       break;
+
+                       case 0x022:
+                                       ret =
+                                               cx231xx_write_i2c_master(dev,
+                                                       0x02,
+                                                       (u16)reg->reg, 1,
+                                                       value, 1, 2);
+                       case 0x322:
+                                       ret =
+                                               cx231xx_write_i2c_master(dev,
+                                                       0x32,
+                                                       (u16)reg->reg, 1,
+                                                       value, 4, 2);
+                                       break;
+
+                       case 0x342:
+                                       ret =
+                                               cx231xx_write_i2c_master(dev,
+                                                       0x34,
+                                                       (u16)reg->reg, 1,
+                                                       value, 4, 2);
+                                       break;
+                       default:
+                               cx231xx_info("no match device address, "
+                                       "the value is %x\n", reg->match.addr);
+                                       break;
+
+                                       }
+
+               }
+       default:
+               break;
+       }
+
+       call_all(dev, core, s_register, reg);
+
+       return ret;
+}
+#endif
+
+static int vidioc_cropcap(struct file *file, void *priv,
+                         struct v4l2_cropcap *cc)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+
+       if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       cc->bounds.left = 0;
+       cc->bounds.top = 0;
+       cc->bounds.width = dev->width;
+       cc->bounds.height = dev->height;
+       cc->defrect = cc->bounds;
+       cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */
+       cc->pixelaspect.denominator = 59;
+
+       return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv,
+                          enum v4l2_buf_type type)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       rc = res_get(fh);
+
+       if (likely(rc >= 0))
+               rc = videobuf_streamon(&fh->vb_vidq);
+
+       call_all(dev, video, s_stream, 1);
+
+       return rc;
+}
+
+static int vidioc_streamoff(struct file *file, void *priv,
+                           enum v4l2_buf_type type)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       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;
+
+       cx25840_call(dev, video, s_stream, 0);
+
+       videobuf_streamoff(&fh->vb_vidq);
+       res_free(fh);
+
+       return 0;
+}
+
+static int vidioc_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+
+       strlcpy(cap->driver, "cx231xx", sizeof(cap->driver));
+       strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
+       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
+
+       cap->capabilities = V4L2_CAP_VBI_CAPTURE |
+#if 0
+               V4L2_CAP_SLICED_VBI_CAPTURE |
+#endif
+               V4L2_CAP_VIDEO_CAPTURE  |
+               V4L2_CAP_AUDIO          |
+               V4L2_CAP_READWRITE      |
+               V4L2_CAP_STREAMING;
+
+       if (dev->tuner_type != TUNER_ABSENT)
+               cap->capabilities |= V4L2_CAP_TUNER;
+
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       if (unlikely(f->index >= ARRAY_SIZE(format)))
+               return -EINVAL;
+
+       strlcpy(f->description, format[f->index].name, sizeof(f->description));
+       f->pixelformat = format[f->index].fourcc;
+
+       return 0;
+}
+
+/* Sliced VBI ioctls */
+static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
+                                      struct v4l2_format *f)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       f->fmt.sliced.service_set = 0;
+
+       call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced);
+
+       if (f->fmt.sliced.service_set == 0)
+               rc = -EINVAL;
+
+       return rc;
+}
+
+static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
+                                        struct v4l2_format *f)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced);
+
+       if (f->fmt.sliced.service_set == 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+/* RAW VBI ioctls */
+
+static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       f->fmt.vbi.sampling_rate = 6750000 * 4;
+       f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
+       f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+       f->fmt.vbi.offset = 0;
+       f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ?
+           PAL_VBI_START_LINE : NTSC_VBI_START_LINE;
+       f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ?
+           PAL_VBI_LINES : NTSC_VBI_LINES;
+       f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ?
+           PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263;
+       f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
+
+       return 0;
+
+}
+
+static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+
+       if (dev->vbi_stream_on && !fh->stream_on) {
+               cx231xx_errdev("%s device in use by another fh\n", __func__);
+               return -EBUSY;
+       }
+
+       f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+       f->fmt.vbi.sampling_rate = 6750000 * 4;
+       f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
+       f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+       f->fmt.vbi.offset = 0;
+       f->fmt.vbi.flags = 0;
+       f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ?
+           PAL_VBI_START_LINE : NTSC_VBI_START_LINE;
+       f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ?
+           PAL_VBI_LINES : NTSC_VBI_LINES;
+       f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ?
+           PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263;
+       f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
+
+       return 0;
+
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *rb)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       return videobuf_reqbufs(&fh->vb_vidq, rb);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       return videobuf_querybuf(&fh->vb_vidq, b);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       return videobuf_qbuf(&fh->vb_vidq, b);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct cx231xx_fh *fh = priv;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
+}
+
+/* ----------------------------------------------------------- */
+/* RADIO ESPECIFIC IOCTLS                                      */
+/* ----------------------------------------------------------- */
+
+static int radio_querycap(struct file *file, void *priv,
+                         struct v4l2_capability *cap)
+{
+       struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
+
+       strlcpy(cap->driver, "cx231xx", sizeof(cap->driver));
+       strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
+       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
+
+       cap->capabilities = V4L2_CAP_TUNER;
+       return 0;
+}
+
+static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+       struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
+
+       if (unlikely(t->index > 0))
+               return -EINVAL;
+
+       strcpy(t->name, "Radio");
+       t->type = V4L2_TUNER_RADIO;
+
+       call_all(dev, tuner, s_tuner, t);
+
+       return 0;
+}
+
+static int radio_enum_input(struct file *file, void *priv, struct v4l2_input *i)
+{
+       if (i->index != 0)
+               return -EINVAL;
+       strcpy(i->name, "Radio");
+       i->type = V4L2_INPUT_TYPE_TUNER;
+
+       return 0;
+}
+
+static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+       if (unlikely(a->index))
+               return -EINVAL;
+
+       strcpy(a->name, "Radio");
+       return 0;
+}
+
+static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
+{
+       struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
+
+       if (0 != t->index)
+               return -EINVAL;
+
+       call_all(dev, tuner, s_tuner, t);
+
+       return 0;
+}
+
+static int radio_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+       return 0;
+}
+
+static int radio_s_input(struct file *file, void *fh, unsigned int i)
+{
+       return 0;
+}
+
+static int radio_queryctrl(struct file *file, void *priv,
+                          struct v4l2_queryctrl *c)
+{
+       int i;
+
+       if (c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1)
+               return -EINVAL;
+       if (c->id == V4L2_CID_AUDIO_MUTE) {
+               for (i = 0; i < CX231XX_CTLS; i++) {
+                       if (cx231xx_ctls[i].v.id == c->id)
+                               break;
+               }
+               if (i == CX231XX_CTLS)
+                       return -EINVAL;
+               *c = cx231xx_ctls[i].v;
+       } else
+               *c = no_ctl;
+       return 0;
+}
+
+/*
+ * cx231xx_v4l2_open()
+ * inits the device and starts isoc transfer
+ */
+static int cx231xx_v4l2_open(struct file *filp)
+{
+       int errCode = 0, radio = 0;
+       struct video_device *vdev = video_devdata(filp);
+       struct cx231xx *dev = video_drvdata(filp);
+       struct cx231xx_fh *fh;
+       enum v4l2_buf_type fh_type = 0;
+
+       switch (vdev->vfl_type) {
+       case VFL_TYPE_GRABBER:
+               fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               break;
+       case VFL_TYPE_VBI:
+               fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
+               break;
+       case VFL_TYPE_RADIO:
+               radio = 1;
+               break;
+       }
+
+       cx231xx_videodbg("open dev=%s type=%s users=%d\n",
+                        video_device_node_name(vdev), v4l2_type_names[fh_type],
+                        dev->users);
+
+#if 0
+       errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
+       if (errCode < 0) {
+               cx231xx_errdev
+                   ("Device locked on digital mode. Can't open analog\n");
+               return -EBUSY;
+       }
+#endif
+
+       fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL);
+       if (!fh) {
+               cx231xx_errdev("cx231xx-video.c: Out of memory?!\n");
+               return -ENOMEM;
+       }
+       if (mutex_lock_interruptible(&dev->lock)) {
+               kfree(fh);
+               return -ERESTARTSYS;
+       }
+       fh->dev = dev;
+       fh->radio = radio;
+       fh->type = fh_type;
+       filp->private_data = fh;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
+               dev->width = norm_maxw(dev);
+               dev->height = norm_maxh(dev);
+
+               /* Power up in Analog TV mode */
+               if (dev->board.external_av)
+                       cx231xx_set_power_mode(dev,
+                                POLARIS_AVMODE_ENXTERNAL_AV);
+               else
+                       cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV);
+
+#if 0
+               cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
+#endif
+
+               /* set video alternate setting */
+               cx231xx_set_video_alternate(dev);
+
+               /* Needed, since GPIO might have disabled power of
+                  some i2c device */
+               cx231xx_config_i2c(dev);
+
+               /* device needs to be initialized before isoc transfer */
+               dev->video_input = dev->video_input > 2 ? 2 : dev->video_input;
+
+       }
+       if (fh->radio) {
+               cx231xx_videodbg("video_open: setting radio device\n");
+
+               /* cx231xx_start_radio(dev); */
+
+               call_all(dev, tuner, s_radio);
+       }
+
+       dev->users++;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_video_qops,
+                                           NULL, &dev->video_mode.slock,
+                                           fh->type, V4L2_FIELD_INTERLACED,
+                                           sizeof(struct cx231xx_buffer),
+                                           fh, &dev->lock);
+       if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+               /* Set the required alternate setting  VBI interface works in
+                  Bulk mode only */
+               cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
+
+               videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops,
+                                           NULL, &dev->vbi_mode.slock,
+                                           fh->type, V4L2_FIELD_SEQ_TB,
+                                           sizeof(struct cx231xx_buffer),
+                                           fh, &dev->lock);
+       }
+       mutex_unlock(&dev->lock);
+
+       return errCode;
+}
+
+/*
+ * cx231xx_realease_resources()
+ * unregisters the v4l2,i2c and usb devices
+ * called when the device gets disconected or at module unload
+*/
+void cx231xx_release_analog_resources(struct cx231xx *dev)
+{
+
+       /*FIXME: I2C IR should be disconnected */
+
+       if (dev->radio_dev) {
+               if (video_is_registered(dev->radio_dev))
+                       video_unregister_device(dev->radio_dev);
+               else
+                       video_device_release(dev->radio_dev);
+               dev->radio_dev = NULL;
+       }
+       if (dev->vbi_dev) {
+               cx231xx_info("V4L2 device %s deregistered\n",
+                            video_device_node_name(dev->vbi_dev));
+               if (video_is_registered(dev->vbi_dev))
+                       video_unregister_device(dev->vbi_dev);
+               else
+                       video_device_release(dev->vbi_dev);
+               dev->vbi_dev = NULL;
+       }
+       if (dev->vdev) {
+               cx231xx_info("V4L2 device %s deregistered\n",
+                            video_device_node_name(dev->vdev));
+
+               if (dev->board.has_417)
+                       cx231xx_417_unregister(dev);
+
+               if (video_is_registered(dev->vdev))
+                       video_unregister_device(dev->vdev);
+               else
+                       video_device_release(dev->vdev);
+               dev->vdev = NULL;
+       }
+}
+
+/*
+ * cx231xx_close()
+ * stops streaming and deallocates all resources allocated by the v4l2
+ * calls and ioctls
+ */
+static int cx231xx_close(struct file *filp)
+{
+       struct cx231xx_fh *fh = filp->private_data;
+       struct cx231xx *dev = fh->dev;
+
+       cx231xx_videodbg("users=%d\n", dev->users);
+
+       cx231xx_videodbg("users=%d\n", dev->users);
+       if (res_check(fh))
+               res_free(fh);
+
+       /*
+        * To workaround error number=-71 on EP0 for VideoGrabber,
+        *       need exclude following.
+        * FIXME: It is probably safe to remove most of these, as we're
+        * now avoiding the alternate setting for INDEX_VANC
+        */
+       if (!dev->board.no_alt_vanc)
+               if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+                       videobuf_stop(&fh->vb_vidq);
+                       videobuf_mmap_free(&fh->vb_vidq);
+
+                       /* the device is already disconnect,
+                          free the remaining resources */
+                       if (dev->state & DEV_DISCONNECTED) {
+                               if (atomic_read(&dev->devlist_count) > 0) {
+                                       cx231xx_release_resources(dev);
+                                       fh->dev = NULL;
+                                       return 0;
+                               }
+                               return 0;
+                       }
+
+                       /* do this before setting alternate! */
+                       cx231xx_uninit_vbi_isoc(dev);
+
+                       /* set alternate 0 */
+                       if (!dev->vbi_or_sliced_cc_mode)
+                               cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
+                       else
+                               cx231xx_set_alt_setting(dev, INDEX_HANC, 0);
+
+                       kfree(fh);
+                       dev->users--;
+                       wake_up_interruptible_nr(&dev->open, 1);
+                       return 0;
+               }
+
+       dev->users--;
+       if (!dev->users) {
+               videobuf_stop(&fh->vb_vidq);
+               videobuf_mmap_free(&fh->vb_vidq);
+
+               /* the device is already disconnect,
+                  free the remaining resources */
+               if (dev->state & DEV_DISCONNECTED) {
+                       cx231xx_release_resources(dev);
+                       fh->dev = NULL;
+                       return 0;
+               }
+
+               /* Save some power by putting tuner to sleep */
+               call_all(dev, core, s_power, 0);
+
+               /* do this before setting alternate! */
+               if (dev->USE_ISO)
+                       cx231xx_uninit_isoc(dev);
+               else
+                       cx231xx_uninit_bulk(dev);
+               cx231xx_set_mode(dev, CX231XX_SUSPEND);
+
+               /* set alternate 0 */
+               cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);
+       }
+       kfree(fh);
+       wake_up_interruptible_nr(&dev->open, 1);
+       return 0;
+}
+
+static int cx231xx_v4l2_close(struct file *filp)
+{
+       struct cx231xx_fh *fh = filp->private_data;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       mutex_lock(&dev->lock);
+       rc = cx231xx_close(filp);
+       mutex_unlock(&dev->lock);
+       return rc;
+}
+
+/*
+ * cx231xx_v4l2_read()
+ * will allocate buffers when called for the first time
+ */
+static ssize_t
+cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
+                 loff_t *pos)
+{
+       struct cx231xx_fh *fh = filp->private_data;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if ((fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+           (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)) {
+               rc = res_get(fh);
+
+               if (unlikely(rc < 0))
+                       return rc;
+
+               if (mutex_lock_interruptible(&dev->lock))
+                       return -ERESTARTSYS;
+               rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
+                                           filp->f_flags & O_NONBLOCK);
+               mutex_unlock(&dev->lock);
+               return rc;
+       }
+       return 0;
+}
+
+/*
+ * cx231xx_v4l2_poll()
+ * will allocate buffers when called for the first time
+ */
+static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table *wait)
+{
+       struct cx231xx_fh *fh = filp->private_data;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       rc = res_get(fh);
+
+       if (unlikely(rc < 0))
+               return POLLERR;
+
+       if ((V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) ||
+           (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)) {
+               unsigned int res;
+
+               mutex_lock(&dev->lock);
+               res = videobuf_poll_stream(filp, &fh->vb_vidq, wait);
+               mutex_unlock(&dev->lock);
+               return res;
+       }
+       return POLLERR;
+}
+
+/*
+ * cx231xx_v4l2_mmap()
+ */
+static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       struct cx231xx_fh *fh = filp->private_data;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       rc = res_get(fh);
+
+       if (unlikely(rc < 0))
+               return rc;
+
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
+       rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
+       mutex_unlock(&dev->lock);
+
+       cx231xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
+                        (unsigned long)vma->vm_start,
+                        (unsigned long)vma->vm_end -
+                        (unsigned long)vma->vm_start, rc);
+
+       return rc;
+}
+
+static const struct v4l2_file_operations cx231xx_v4l_fops = {
+       .owner   = THIS_MODULE,
+       .open    = cx231xx_v4l2_open,
+       .release = cx231xx_v4l2_close,
+       .read    = cx231xx_v4l2_read,
+       .poll    = cx231xx_v4l2_poll,
+       .mmap    = cx231xx_v4l2_mmap,
+       .unlocked_ioctl   = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+       .vidioc_querycap               = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap       = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap          = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap        = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap          = vidioc_s_fmt_vid_cap,
+       .vidioc_g_fmt_vbi_cap          = vidioc_g_fmt_vbi_cap,
+       .vidioc_try_fmt_vbi_cap        = vidioc_try_fmt_vbi_cap,
+       .vidioc_s_fmt_vbi_cap          = vidioc_try_fmt_vbi_cap,
+       .vidioc_g_audio                =  vidioc_g_audio,
+       .vidioc_s_audio                = vidioc_s_audio,
+       .vidioc_cropcap                = vidioc_cropcap,
+       .vidioc_g_fmt_sliced_vbi_cap   = vidioc_g_fmt_sliced_vbi_cap,
+       .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
+       .vidioc_reqbufs                = vidioc_reqbufs,
+       .vidioc_querybuf               = vidioc_querybuf,
+       .vidioc_qbuf                   = vidioc_qbuf,
+       .vidioc_dqbuf                  = vidioc_dqbuf,
+       .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_queryctrl              = vidioc_queryctrl,
+       .vidioc_g_ctrl                 = vidioc_g_ctrl,
+       .vidioc_s_ctrl                 = vidioc_s_ctrl,
+       .vidioc_streamon               = vidioc_streamon,
+       .vidioc_streamoff              = vidioc_streamoff,
+       .vidioc_g_tuner                = vidioc_g_tuner,
+       .vidioc_s_tuner                = vidioc_s_tuner,
+       .vidioc_g_frequency            = vidioc_g_frequency,
+       .vidioc_s_frequency            = vidioc_s_frequency,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register             = vidioc_g_register,
+       .vidioc_s_register             = vidioc_s_register,
+#endif
+};
+
+static struct video_device cx231xx_vbi_template;
+
+static const struct video_device cx231xx_video_template = {
+       .fops         = &cx231xx_v4l_fops,
+       .release      = video_device_release,
+       .ioctl_ops    = &video_ioctl_ops,
+       .tvnorms      = V4L2_STD_ALL,
+       .current_norm = V4L2_STD_PAL,
+};
+
+static const struct v4l2_file_operations radio_fops = {
+       .owner   = THIS_MODULE,
+       .open   = cx231xx_v4l2_open,
+       .release = cx231xx_v4l2_close,
+       .ioctl   = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
+       .vidioc_querycap    = radio_querycap,
+       .vidioc_g_tuner     = radio_g_tuner,
+       .vidioc_enum_input  = radio_enum_input,
+       .vidioc_g_audio     = radio_g_audio,
+       .vidioc_s_tuner     = radio_s_tuner,
+       .vidioc_s_audio     = radio_s_audio,
+       .vidioc_s_input     = radio_s_input,
+       .vidioc_queryctrl   = radio_queryctrl,
+       .vidioc_g_ctrl      = vidioc_g_ctrl,
+       .vidioc_s_ctrl      = vidioc_s_ctrl,
+       .vidioc_g_frequency = vidioc_g_frequency,
+       .vidioc_s_frequency = vidioc_s_frequency,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register  = vidioc_g_register,
+       .vidioc_s_register  = vidioc_s_register,
+#endif
+};
+
+static struct video_device cx231xx_radio_template = {
+       .name      = "cx231xx-radio",
+       .fops      = &radio_fops,
+       .ioctl_ops = &radio_ioctl_ops,
+};
+
+/******************************** usb interface ******************************/
+
+static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
+               const struct video_device
+               *template, const char *type_name)
+{
+       struct video_device *vfd;
+
+       vfd = video_device_alloc();
+       if (NULL == vfd)
+               return NULL;
+
+       *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);
+
+       video_set_drvdata(vfd, dev);
+       return vfd;
+}
+
+int cx231xx_register_analog_devices(struct cx231xx *dev)
+{
+       int ret;
+
+       cx231xx_info("%s: v4l2 driver version %s\n",
+                    dev->name, CX231XX_VERSION);
+
+       /* set default norm */
+       /*dev->norm = cx231xx_video_template.current_norm; */
+       dev->width = norm_maxw(dev);
+       dev->height = norm_maxh(dev);
+       dev->interlaced = 0;
+
+       /* Analog specific initialization */
+       dev->format = &format[0];
+
+       /* Set the initial input */
+       video_mux(dev, dev->video_input);
+
+       /* Audio defaults */
+       dev->mute = 1;
+       dev->volume = 0x1f;
+
+       /* enable vbi capturing */
+       /* write code here...  */
+
+       /* allocate and fill video video_device struct */
+       dev->vdev = cx231xx_vdev_init(dev, &cx231xx_video_template, "video");
+       if (!dev->vdev) {
+               cx231xx_errdev("cannot allocate video_device.\n");
+               return -ENODEV;
+       }
+
+       /* register v4l2 video video_device */
+       ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
+                                   video_nr[dev->devno]);
+       if (ret) {
+               cx231xx_errdev("unable to register video device (error=%i).\n",
+                              ret);
+               return ret;
+       }
+
+       cx231xx_info("%s/0: registered device %s [v4l2]\n",
+                    dev->name, video_device_node_name(dev->vdev));
+
+       /* Initialize VBI template */
+       memcpy(&cx231xx_vbi_template, &cx231xx_video_template,
+              sizeof(cx231xx_vbi_template));
+       strcpy(cx231xx_vbi_template.name, "cx231xx-vbi");
+
+       /* Allocate and fill vbi video_device struct */
+       dev->vbi_dev = cx231xx_vdev_init(dev, &cx231xx_vbi_template, "vbi");
+
+       /* register v4l2 vbi video_device */
+       ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
+                                   vbi_nr[dev->devno]);
+       if (ret < 0) {
+               cx231xx_errdev("unable to register vbi device\n");
+               return ret;
+       }
+
+       cx231xx_info("%s/0: registered device %s\n",
+                    dev->name, video_device_node_name(dev->vbi_dev));
+
+       if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) {
+               dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template,
+                                                  "radio");
+               if (!dev->radio_dev) {
+                       cx231xx_errdev("cannot allocate video_device.\n");
+                       return -ENODEV;
+               }
+               ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
+                                           radio_nr[dev->devno]);
+               if (ret < 0) {
+                       cx231xx_errdev("can't register radio device\n");
+                       return ret;
+               }
+               cx231xx_info("Registered radio device as %s\n",
+                            video_device_node_name(dev->radio_dev));
+       }
+
+       cx231xx_info("V4L2 device registered as %s and %s\n",
+                    video_device_node_name(dev->vdev),
+                    video_device_node_name(dev->vbi_dev));
+
+       return 0;
+}
diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h
new file mode 100644 (file)
index 0000000..a89d020
--- /dev/null
@@ -0,0 +1,1012 @@
+/*
+   cx231xx.h - driver for Conexant Cx23100/101/102 USB video capture devices
+
+   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
+       Based on em28xx driver
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   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.
+ */
+
+#ifndef _CX231XX_H
+#define _CX231XX_H
+
+#include <linux/videodev2.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+
+#include <media/cx2341x.h>
+
+#include <media/videobuf-vmalloc.h>
+#include <media/v4l2-device.h>
+#include <media/rc-core.h>
+#include <media/ir-kbd-i2c.h>
+#include <media/videobuf-dvb.h>
+
+#include "cx231xx-reg.h"
+#include "cx231xx-pcb-cfg.h"
+#include "cx231xx-conf-reg.h"
+
+#define DRIVER_NAME                     "cx231xx"
+#define PWR_SLEEP_INTERVAL              10
+
+/* I2C addresses for control block in Cx231xx */
+#define     AFE_DEVICE_ADDRESS         0x60
+#define     I2S_BLK_DEVICE_ADDRESS     0x98
+#define     VID_BLK_I2C_ADDRESS                0x88
+#define     VERVE_I2C_ADDRESS           0x40
+#define     DIF_USE_BASEBAND            0xFFFFFFFF
+
+/* Boards supported by driver */
+#define CX231XX_BOARD_UNKNOWN              0
+#define CX231XX_BOARD_CNXT_CARRAERA    1
+#define CX231XX_BOARD_CNXT_SHELBY      2
+#define CX231XX_BOARD_CNXT_RDE_253S    3
+#define CX231XX_BOARD_CNXT_RDU_253S    4
+#define CX231XX_BOARD_CNXT_VIDEO_GRABBER       5
+#define CX231XX_BOARD_CNXT_RDE_250     6
+#define CX231XX_BOARD_CNXT_RDU_250     7
+#define CX231XX_BOARD_HAUPPAUGE_EXETER  8
+#define CX231XX_BOARD_HAUPPAUGE_USBLIVE2 9
+#define CX231XX_BOARD_PV_PLAYTV_USB_HYBRID 10
+#define CX231XX_BOARD_PV_XCAPTURE_USB 11
+#define CX231XX_BOARD_KWORLD_UB430_USB_HYBRID 12
+#define CX231XX_BOARD_ICONBIT_U100 13
+#define CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL 14
+#define CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC 15
+
+/* Limits minimum and default number of buffers */
+#define CX231XX_MIN_BUF                 4
+#define CX231XX_DEF_BUF                 12
+#define CX231XX_DEF_VBI_BUF             6
+
+#define VBI_LINE_COUNT                  17
+#define VBI_LINE_LENGTH                 1440
+
+/*Limits the max URB message size */
+#define URB_MAX_CTRL_SIZE               80
+
+/* Params for validated field */
+#define CX231XX_BOARD_NOT_VALIDATED     1
+#define CX231XX_BOARD_VALIDATED                0
+
+/* maximum number of cx231xx boards */
+#define CX231XX_MAXBOARDS               8
+
+/* maximum number of frames that can be queued */
+#define CX231XX_NUM_FRAMES              5
+
+/* number of buffers for isoc transfers */
+#define CX231XX_NUM_BUFS                8
+
+/* number of packets for each buffer
+   windows requests only 40 packets .. so we better do the same
+   this is what I found out for all alternate numbers there!
+ */
+#define CX231XX_NUM_PACKETS             40
+
+/* default alternate; 0 means choose the best */
+#define CX231XX_PINOUT                  0
+
+#define CX231XX_INTERLACED_DEFAULT      1
+
+/* time to wait when stopping the isoc transfer */
+#define CX231XX_URB_TIMEOUT            \
+               msecs_to_jiffies(CX231XX_NUM_BUFS * CX231XX_NUM_PACKETS)
+
+#define CX231xx_NORMS (\
+       V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP |  V4L2_STD_NTSC_443 | \
+       V4L2_STD_PAL_BG |  V4L2_STD_PAL_DK    |  V4L2_STD_PAL_I    | \
+       V4L2_STD_PAL_M  |  V4L2_STD_PAL_N     |  V4L2_STD_PAL_Nc   | \
+       V4L2_STD_PAL_60 |  V4L2_STD_SECAM_L   |  V4L2_STD_SECAM_DK)
+
+#define SLEEP_S5H1432    30
+#define CX23417_OSC_EN   8
+#define CX23417_RESET    9
+
+struct cx23417_fmt {
+       char  *name;
+       u32   fourcc;          /* v4l2 format id */
+       int   depth;
+       int   flags;
+       u32   cxformat;
+};
+enum cx231xx_mode {
+       CX231XX_SUSPEND,
+       CX231XX_ANALOG_MODE,
+       CX231XX_DIGITAL_MODE,
+};
+
+enum cx231xx_std_mode {
+       CX231XX_TV_AIR = 0,
+       CX231XX_TV_CABLE
+};
+
+enum cx231xx_stream_state {
+       STREAM_OFF,
+       STREAM_INTERRUPT,
+       STREAM_ON,
+};
+
+struct cx231xx;
+
+struct cx231xx_isoc_ctl {
+       /* max packet size of isoc transaction */
+       int max_pkt_size;
+
+       /* number of allocated urbs */
+       int num_bufs;
+
+       /* urb for isoc transfers */
+       struct urb **urb;
+
+       /* transfer buffers for isoc transfer */
+       char **transfer_buffer;
+
+       /* Last buffer command and region */
+       u8 cmd;
+       int pos, size, pktsize;
+
+       /* Last field: ODD or EVEN? */
+       int field;
+
+       /* Stores incomplete commands */
+       u32 tmp_buf;
+       int tmp_buf_len;
+
+       /* Stores already requested buffers */
+       struct cx231xx_buffer *buf;
+
+       /* Stores the number of received fields */
+       int nfields;
+
+       /* isoc urb callback */
+       int (*isoc_copy) (struct cx231xx *dev, struct urb *urb);
+};
+
+struct cx231xx_bulk_ctl {
+       /* max packet size of bulk transaction */
+       int max_pkt_size;
+
+       /* number of allocated urbs */
+       int num_bufs;
+
+       /* urb for bulk transfers */
+       struct urb **urb;
+
+       /* transfer buffers for bulk transfer */
+       char **transfer_buffer;
+
+       /* Last buffer command and region */
+       u8 cmd;
+       int pos, size, pktsize;
+
+       /* Last field: ODD or EVEN? */
+       int field;
+
+       /* Stores incomplete commands */
+       u32 tmp_buf;
+       int tmp_buf_len;
+
+       /* Stores already requested buffers */
+       struct cx231xx_buffer *buf;
+
+       /* Stores the number of received fields */
+       int nfields;
+
+       /* bulk urb callback */
+       int (*bulk_copy) (struct cx231xx *dev, struct urb *urb);
+};
+
+struct cx231xx_fmt {
+       char *name;
+       u32 fourcc;             /* v4l2 format id */
+       int depth;
+       int reg;
+};
+
+/* buffer for one video frame */
+struct cx231xx_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+
+       struct list_head frame;
+       int top_field;
+       int receiving;
+};
+
+enum ps_package_head {
+       CX231XX_NEED_ADD_PS_PACKAGE_HEAD = 0,
+       CX231XX_NONEED_PS_PACKAGE_HEAD
+};
+
+struct cx231xx_dmaqueue {
+       struct list_head active;
+       struct list_head queued;
+
+       wait_queue_head_t wq;
+
+       /* Counters to control buffer fill */
+       int pos;
+       u8 is_partial_line;
+       u8 partial_buf[8];
+       u8 last_sav;
+       int current_field;
+       u32 bytes_left_in_line;
+       u32 lines_completed;
+       u8 field1_done;
+       u32 lines_per_field;
+
+       /*Mpeg2 control buffer*/
+       u8 *p_left_data;
+       u32 left_data_count;
+       u8 mpeg_buffer_done;
+       u32 mpeg_buffer_completed;
+       enum ps_package_head add_ps_package_head;
+       char ps_head[10];
+};
+
+/* inputs */
+
+#define MAX_CX231XX_INPUT               4
+
+enum cx231xx_itype {
+       CX231XX_VMUX_COMPOSITE1 = 1,
+       CX231XX_VMUX_SVIDEO,
+       CX231XX_VMUX_TELEVISION,
+       CX231XX_VMUX_CABLE,
+       CX231XX_RADIO,
+       CX231XX_VMUX_DVB,
+       CX231XX_VMUX_DEBUG
+};
+
+enum cx231xx_v_input {
+       CX231XX_VIN_1_1 = 0x1,
+       CX231XX_VIN_2_1,
+       CX231XX_VIN_3_1,
+       CX231XX_VIN_4_1,
+       CX231XX_VIN_1_2 = 0x01,
+       CX231XX_VIN_2_2,
+       CX231XX_VIN_3_2,
+       CX231XX_VIN_1_3 = 0x1,
+       CX231XX_VIN_2_3,
+       CX231XX_VIN_3_3,
+};
+
+/* cx231xx has two audio inputs: tuner and line in */
+enum cx231xx_amux {
+       /* This is the only entry for cx231xx tuner input */
+       CX231XX_AMUX_VIDEO,     /* cx231xx tuner */
+       CX231XX_AMUX_LINE_IN,   /* Line In */
+};
+
+struct cx231xx_reg_seq {
+       unsigned char bit;
+       unsigned char val;
+       int sleep;
+};
+
+struct cx231xx_input {
+       enum cx231xx_itype type;
+       unsigned int vmux;
+       enum cx231xx_amux amux;
+       struct cx231xx_reg_seq *gpio;
+};
+
+#define INPUT(nr) (&cx231xx_boards[dev->model].input[nr])
+
+enum cx231xx_decoder {
+       CX231XX_NODECODER,
+       CX231XX_AVDECODER
+};
+
+enum CX231XX_I2C_MASTER_PORT {
+       I2C_0 = 0,
+       I2C_1 = 1,
+       I2C_2 = 2,
+       I2C_3 = 3
+};
+
+struct cx231xx_board {
+       char *name;
+       int vchannels;
+       int tuner_type;
+       int tuner_addr;
+       v4l2_std_id norm;       /* tv norm */
+
+       /* demod related */
+       int demod_addr;
+       u8 demod_xfer_mode;     /* 0 - Serial; 1 - parallel */
+
+       /* GPIO Pins */
+       struct cx231xx_reg_seq *dvb_gpio;
+       struct cx231xx_reg_seq *suspend_gpio;
+       struct cx231xx_reg_seq *tuner_gpio;
+               /* Negative means don't use it */
+       s8 tuner_sif_gpio;
+       s8 tuner_scl_gpio;
+       s8 tuner_sda_gpio;
+
+       /* PIN ctrl */
+       u32 ctl_pin_status_mask;
+       u8 agc_analog_digital_select_gpio;
+       u32 gpio_pin_status_mask;
+
+       /* i2c masters */
+       u8 tuner_i2c_master;
+       u8 demod_i2c_master;
+       u8 ir_i2c_master;
+
+       /* for devices with I2C chips for IR */
+       char *rc_map_name;
+
+       unsigned int max_range_640_480:1;
+       unsigned int has_dvb:1;
+       unsigned int has_417:1;
+       unsigned int valid:1;
+       unsigned int no_alt_vanc:1;
+       unsigned int external_av:1;
+       unsigned int dont_use_port_3:1;
+
+       unsigned char xclk, i2c_speed;
+
+       enum cx231xx_decoder decoder;
+       int output_mode;
+
+       struct cx231xx_input input[MAX_CX231XX_INPUT];
+       struct cx231xx_input radio;
+       struct rc_map *ir_codes;
+};
+
+/* device states */
+enum cx231xx_dev_state {
+       DEV_INITIALIZED = 0x01,
+       DEV_DISCONNECTED = 0x02,
+};
+
+enum AFE_MODE {
+       AFE_MODE_LOW_IF,
+       AFE_MODE_BASEBAND,
+       AFE_MODE_EU_HI_IF,
+       AFE_MODE_US_HI_IF,
+       AFE_MODE_JAPAN_HI_IF
+};
+
+enum AUDIO_INPUT {
+       AUDIO_INPUT_MUTE,
+       AUDIO_INPUT_LINE,
+       AUDIO_INPUT_TUNER_TV,
+       AUDIO_INPUT_SPDIF,
+       AUDIO_INPUT_TUNER_FM
+};
+
+#define CX231XX_AUDIO_BUFS              5
+#define CX231XX_NUM_AUDIO_PACKETS       16
+#define CX231XX_ISO_NUM_AUDIO_PACKETS  64
+
+/* cx231xx extensions */
+#define CX231XX_AUDIO                   0x10
+#define CX231XX_DVB                     0x20
+
+struct cx231xx_audio {
+       char name[50];
+       char *transfer_buffer[CX231XX_AUDIO_BUFS];
+       struct urb *urb[CX231XX_AUDIO_BUFS];
+       struct usb_device *udev;
+       unsigned int capture_transfer_done;
+       struct snd_pcm_substream *capture_pcm_substream;
+
+       unsigned int hwptr_done_capture;
+       struct snd_card *sndcard;
+
+       int users, shutdown;
+       /* locks */
+       spinlock_t slock;
+
+       int alt;                /* alternate */
+       int max_pkt_size;       /* max packet size of isoc transaction */
+       int num_alt;            /* Number of alternative settings */
+       unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
+       u16 end_point_addr;
+};
+
+struct cx231xx;
+
+struct cx231xx_fh {
+       struct cx231xx *dev;
+       unsigned int stream_on:1;       /* Locks streams */
+       int radio;
+
+       struct videobuf_queue vb_vidq;
+
+       enum v4l2_buf_type type;
+
+
+
+/*following is copyed from cx23885.h*/
+       u32                        resources;
+
+       /* video overlay */
+       struct v4l2_window         win;
+       struct v4l2_clip           *clips;
+       unsigned int               nclips;
+
+       /* video capture */
+       struct cx23417_fmt         *fmt;
+       unsigned int               width, height;
+
+       /* vbi capture */
+       struct videobuf_queue      vidq;
+       struct videobuf_queue      vbiq;
+
+       /* MPEG Encoder specifics ONLY */
+
+       atomic_t                   v4l_reading;
+};
+
+/*****************************************************************/
+/* set/get i2c */
+/* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */
+#define I2C_SPEED_1M            0x0
+#define I2C_SPEED_400K          0x1
+#define I2C_SPEED_100K          0x2
+#define I2C_SPEED_5M            0x3
+
+/* 0-- STOP transaction */
+#define I2C_STOP                0x0
+/* 1-- do not transmit STOP at end of transaction */
+#define I2C_NOSTOP              0x1
+/* 1--allow slave to insert clock wait states */
+#define I2C_SYNC                0x1
+
+struct cx231xx_i2c {
+       struct cx231xx *dev;
+
+       int nr;
+
+       /* i2c i/o */
+       struct i2c_adapter i2c_adap;
+       struct i2c_client i2c_client;
+       u32 i2c_rc;
+
+       /* different settings for each bus */
+       u8 i2c_period;
+       u8 i2c_nostop;
+       u8 i2c_reserve;
+};
+
+struct cx231xx_i2c_xfer_data {
+       u8 dev_addr;
+       u8 direction;           /* 1 - IN, 0 - OUT */
+       u8 saddr_len;           /* sub address len */
+       u16 saddr_dat;          /* sub addr data */
+       u8 buf_size;            /* buffer size */
+       u8 *p_buffer;           /* pointer to the buffer */
+};
+
+struct VENDOR_REQUEST_IN {
+       u8 bRequest;
+       u16 wValue;
+       u16 wIndex;
+       u16 wLength;
+       u8 direction;
+       u8 bData;
+       u8 *pBuff;
+};
+
+struct cx231xx_tvnorm {
+       char            *name;
+       v4l2_std_id     id;
+       u32             cxiformat;
+       u32             cxoformat;
+};
+
+struct cx231xx_ctrl {
+       struct v4l2_queryctrl v;
+       u32 off;
+       u32 reg;
+       u32 mask;
+       u32 shift;
+};
+
+enum TRANSFER_TYPE {
+       Raw_Video = 0,
+       Audio,
+       Vbi,                    /* VANC */
+       Sliced_cc,              /* HANC */
+       TS1_serial_mode,
+       TS2,
+       TS1_parallel_mode
+} ;
+
+struct cx231xx_video_mode {
+       /* Isoc control struct */
+       struct cx231xx_dmaqueue vidq;
+       struct cx231xx_isoc_ctl isoc_ctl;
+       struct cx231xx_bulk_ctl bulk_ctl;
+       /* locks */
+       spinlock_t slock;
+
+       /* usb transfer */
+       int alt;                /* alternate */
+       int max_pkt_size;       /* max packet size of isoc transaction */
+       int num_alt;            /* Number of alternative settings */
+       unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
+       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;
+
+       int                        nr;
+       int                        sram_chno;
+
+       struct videobuf_dvb_frontends frontends;
+
+       /* dma queues */
+
+       u32                        ts_packet_size;
+       u32                        ts_packet_count;
+
+       int                        width;
+       int                        height;
+
+       /* locks */
+       spinlock_t                 slock;
+
+       /* registers */
+       u32                        reg_gpcnt;
+       u32                        reg_gpcnt_ctl;
+       u32                        reg_dma_ctl;
+       u32                        reg_lngth;
+       u32                        reg_hw_sop_ctrl;
+       u32                        reg_gen_ctrl;
+       u32                        reg_bd_pkt_status;
+       u32                        reg_sop_status;
+       u32                        reg_fifo_ovfl_stat;
+       u32                        reg_vld_misc;
+       u32                        reg_ts_clk_en;
+       u32                        reg_ts_int_msk;
+       u32                        reg_ts_int_stat;
+       u32                        reg_src_sel;
+
+       /* Default register vals */
+       int                        pci_irqmask;
+       u32                        dma_ctl_val;
+       u32                        ts_int_msk_val;
+       u32                        gen_ctrl_val;
+       u32                        ts_clk_en_val;
+       u32                        src_sel_val;
+       u32                        vld_misc_val;
+       u32                        hw_sop_ctrl_val;
+
+       /* Allow a single tsport to have multiple frontends */
+       u32                        num_frontends;
+       void                       *port_priv;
+};
+
+/* main device struct */
+struct cx231xx {
+       /* generic device properties */
+       char name[30];          /* name (including minor) of the device */
+       int model;              /* index in the device_data struct */
+       int devno;              /* marks the number of this device */
+
+       struct cx231xx_board board;
+
+       /* For I2C IR support */
+       struct IR_i2c_init_data    init_data;
+       struct i2c_client          *ir_i2c_client;
+
+       unsigned int stream_on:1;       /* Locks streams */
+       unsigned int vbi_stream_on:1;   /* Locks streams for VBI */
+       unsigned int has_audio_class:1;
+       unsigned int has_alsa_audio:1;
+
+       struct cx231xx_fmt *format;
+
+       struct v4l2_device v4l2_dev;
+       struct v4l2_subdev *sd_cx25840;
+       struct v4l2_subdev *sd_tuner;
+
+       struct work_struct wq_trigger;          /* Trigger to start/stop audio for alsa module */
+       atomic_t           stream_started;      /* stream should be running if true */
+
+       struct list_head devlist;
+
+       int tuner_type;         /* type of the tuner */
+       int tuner_addr;         /* tuner address */
+
+       /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
+       struct cx231xx_i2c i2c_bus[3];
+       unsigned int xc_fw_load_done:1;
+       /* locks */
+       struct mutex gpio_i2c_lock;
+       struct mutex i2c_lock;
+
+       /* video for linux */
+       int users;              /* user count for exclusive use */
+       struct video_device *vdev;      /* video for linux device struct */
+       v4l2_std_id norm;       /* selected tv norm */
+       int ctl_freq;           /* selected frequency */
+       unsigned int ctl_ainput;        /* selected audio input */
+       int mute;
+       int volume;
+
+       /* frame properties */
+       int width;              /* current frame width */
+       int height;             /* current frame height */
+       int interlaced;         /* 1=interlace fileds, 0=just top fileds */
+
+       struct cx231xx_audio adev;
+
+       /* states */
+       enum cx231xx_dev_state state;
+
+       struct work_struct request_module_wk;
+
+       /* locks */
+       struct mutex lock;
+       struct mutex ctrl_urb_lock;     /* protects urb_buf */
+       struct list_head inqueue, outqueue;
+       wait_queue_head_t open, wait_frame, wait_stream;
+       struct video_device *vbi_dev;
+       struct video_device *radio_dev;
+
+       unsigned char eedata[256];
+
+       struct cx231xx_video_mode video_mode;
+       struct cx231xx_video_mode vbi_mode;
+       struct cx231xx_video_mode sliced_cc_mode;
+       struct cx231xx_video_mode ts1_mode;
+
+       atomic_t devlist_count;
+
+       struct usb_device *udev;        /* the usb device */
+       char urb_buf[URB_MAX_CTRL_SIZE];        /* urb control msg buffer */
+
+       /* helper funcs that call usb_control_msg */
+       int (*cx231xx_read_ctrl_reg) (struct cx231xx *dev, u8 req, u16 reg,
+                                     char *buf, int len);
+       int (*cx231xx_write_ctrl_reg) (struct cx231xx *dev, u8 req, u16 reg,
+                                      char *buf, int len);
+       int (*cx231xx_send_usb_command) (struct cx231xx_i2c *i2c_bus,
+                               struct cx231xx_i2c_xfer_data *req_data);
+       int (*cx231xx_gpio_i2c_read) (struct cx231xx *dev, u8 dev_addr,
+                                     u8 *buf, u8 len);
+       int (*cx231xx_gpio_i2c_write) (struct cx231xx *dev, u8 dev_addr,
+                                      u8 *buf, u8 len);
+
+       int (*cx231xx_set_analog_freq) (struct cx231xx *dev, u32 freq);
+       int (*cx231xx_reset_analog_tuner) (struct cx231xx *dev);
+
+       enum cx231xx_mode mode;
+
+       struct cx231xx_dvb *dvb;
+
+       /* Cx231xx supported PCB config's */
+       struct pcb_config current_pcb_config;
+       u8 current_scenario_idx;
+       u8 interface_count;
+       u8 max_iad_interface_count;
+
+       /* GPIO related register direction and values */
+       u32 gpio_dir;
+       u32 gpio_val;
+
+       /* Power Modes */
+       int power_mode;
+
+       /* afe parameters */
+       enum AFE_MODE afe_mode;
+       u32 afe_ref_count;
+
+       /* video related parameters */
+       u32 video_input;
+       u32 active_mode;
+       u8 vbi_or_sliced_cc_mode;       /* 0 - vbi ; 1 - sliced cc mode */
+       enum cx231xx_std_mode std_mode; /* 0 - Air; 1 - cable */
+
+       /*mode: digital=1 or analog=0*/
+       u8 mode_tv;
+
+       u8 USE_ISO;
+       struct cx231xx_tvnorm      encodernorm;
+       struct cx231xx_tsport      ts1, ts2;
+       struct cx2341x_mpeg_params mpeg_params;
+       struct video_device        *v4l_device;
+       atomic_t                   v4l_reader_count;
+       u32                        freq;
+       unsigned int               input;
+       u32                        cx23417_mailbox;
+       u32                        __iomem *lmmio;
+       u8                         __iomem *bmmio;
+};
+
+extern struct list_head cx231xx_devlist;
+
+#define cx25840_call(cx231xx, o, f, args...) \
+       v4l2_subdev_call(cx231xx->sd_cx25840, o, f, ##args)
+#define tuner_call(cx231xx, o, f, args...) \
+       v4l2_subdev_call(cx231xx->sd_tuner, o, f, ##args)
+#define call_all(dev, o, f, args...) \
+       v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
+
+struct cx231xx_ops {
+       struct list_head next;
+       char *name;
+       int id;
+       int (*init) (struct cx231xx *);
+       int (*fini) (struct cx231xx *);
+};
+
+/* call back functions in dvb module */
+int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq);
+int cx231xx_reset_analog_tuner(struct cx231xx *dev);
+
+/* Provided by cx231xx-i2c.c */
+void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c);
+int cx231xx_i2c_register(struct cx231xx_i2c *bus);
+int cx231xx_i2c_unregister(struct cx231xx_i2c *bus);
+
+/* Internal block control functions */
+int cx231xx_read_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,
+                u8 saddr_len, u32 *data, u8 data_len, int master);
+int cx231xx_write_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,
+                u8 saddr_len, u32 data, u8 data_len, int master);
+int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr,
+                         u16 saddr, u8 saddr_len, u32 *data, u8 data_len);
+int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr,
+                          u16 saddr, u8 saddr_len, u32 data, u8 data_len);
+int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size,
+                          u16 register_address, u8 bit_start, u8 bit_end,
+                          u32 value);
+int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr,
+                                       u16 saddr, u32 mask, u32 value);
+u32 cx231xx_set_field(u32 field_mask, u32 data);
+
+/*verve r/w*/
+void initGPIO(struct cx231xx *dev);
+void uninitGPIO(struct cx231xx *dev);
+/* afe related functions */
+int cx231xx_afe_init_super_block(struct cx231xx *dev, u32 ref_count);
+int cx231xx_afe_init_channels(struct cx231xx *dev);
+int cx231xx_afe_setup_AFE_for_baseband(struct cx231xx *dev);
+int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux);
+int cx231xx_afe_set_mode(struct cx231xx *dev, enum AFE_MODE mode);
+int cx231xx_afe_update_power_control(struct cx231xx *dev,
+                                       enum AV_MODE avmode);
+int cx231xx_afe_adjust_ref_count(struct cx231xx *dev, u32 video_input);
+
+/* i2s block related functions */
+int cx231xx_i2s_blk_initialize(struct cx231xx *dev);
+int cx231xx_i2s_blk_update_power_control(struct cx231xx *dev,
+                                       enum AV_MODE avmode);
+int cx231xx_i2s_blk_set_audio_input(struct cx231xx *dev, u8 audio_input);
+
+/* DIF related functions */
+int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode,
+                                         u32 function_mode, u32 standard);
+void cx231xx_set_Colibri_For_LowIF(struct cx231xx *dev, u32 if_freq,
+                                        u8 spectral_invert, u32 mode);
+u32 cx231xx_Get_Colibri_CarrierOffset(u32 mode, u32 standerd);
+void cx231xx_set_DIF_bandpass(struct cx231xx *dev, u32 if_freq,
+                                        u8 spectral_invert, u32 mode);
+void cx231xx_Setup_AFE_for_LowIF(struct cx231xx *dev);
+void reset_s5h1432_demod(struct cx231xx *dev);
+void cx231xx_dump_HH_reg(struct cx231xx *dev);
+void update_HH_register_after_set_DIF(struct cx231xx *dev);
+void cx231xx_dump_SC_reg(struct cx231xx *dev);
+
+
+
+int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard);
+int cx231xx_tuner_pre_channel_change(struct cx231xx *dev);
+int cx231xx_tuner_post_channel_change(struct cx231xx *dev);
+
+/* video parser functions */
+u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size,
+                            u32 *p_bytes_used);
+u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf,
+                                u32 *p_bytes_used);
+int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+                   u8 *p_buffer, u32 bytes_to_copy);
+void cx231xx_reset_video_buffer(struct cx231xx *dev,
+                               struct cx231xx_dmaqueue *dma_q);
+u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q);
+u32 cx231xx_copy_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+                           u8 *p_line, u32 length, int field_number);
+u32 cx231xx_get_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
+                          u8 sav_eav, u8 *p_buffer, u32 buffer_size);
+void cx231xx_swab(u16 *from, u16 *to, u16 len);
+
+/* Provided by cx231xx-core.c */
+
+u32 cx231xx_request_buffers(struct cx231xx *dev, u32 count);
+void cx231xx_queue_unusedframes(struct cx231xx *dev);
+void cx231xx_release_buffers(struct cx231xx *dev);
+
+/* read from control pipe */
+int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg,
+                         char *buf, int len);
+
+/* write to control pipe */
+int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg,
+                          char *buf, int len);
+int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode);
+
+int cx231xx_send_vendor_cmd(struct cx231xx *dev,
+                               struct VENDOR_REQUEST_IN *ven_req);
+int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus,
+                               struct cx231xx_i2c_xfer_data *req_data);
+
+/* Gpio related functions */
+int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val,
+                         u8 len, u8 request, u8 direction);
+int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val);
+int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val);
+int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value);
+int cx231xx_set_gpio_direction(struct cx231xx *dev, int pin_number,
+                              int pin_value);
+
+int cx231xx_gpio_i2c_start(struct cx231xx *dev);
+int cx231xx_gpio_i2c_end(struct cx231xx *dev);
+int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data);
+int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf);
+int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev);
+int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev);
+int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev);
+
+int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len);
+int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len);
+
+/* audio related functions */
+int cx231xx_set_audio_decoder_input(struct cx231xx *dev,
+                                   enum AUDIO_INPUT audio_input);
+
+int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type);
+int cx231xx_set_video_alternate(struct cx231xx *dev);
+int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt);
+int is_fw_load(struct cx231xx *dev);
+int cx231xx_check_fw(struct cx231xx *dev);
+int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
+                     int num_bufs, int max_pkt_size,
+                     int (*isoc_copy) (struct cx231xx *dev,
+                                       struct urb *urb));
+int cx231xx_init_bulk(struct cx231xx *dev, int max_packets,
+                     int num_bufs, int max_pkt_size,
+                     int (*bulk_copy) (struct cx231xx *dev,
+                                       struct urb *urb));
+void cx231xx_stop_TS1(struct cx231xx *dev);
+void cx231xx_start_TS1(struct cx231xx *dev);
+void cx231xx_uninit_isoc(struct cx231xx *dev);
+void cx231xx_uninit_bulk(struct cx231xx *dev);
+int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode);
+int cx231xx_unmute_audio(struct cx231xx *dev);
+int cx231xx_ep5_bulkout(struct cx231xx *dev, u8 *firmware, u16 size);
+void cx231xx_disable656(struct cx231xx *dev);
+void cx231xx_enable656(struct cx231xx *dev);
+int cx231xx_demod_reset(struct cx231xx *dev);
+int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio);
+
+/* Device list functions */
+void cx231xx_release_resources(struct cx231xx *dev);
+void cx231xx_release_analog_resources(struct cx231xx *dev);
+int cx231xx_register_analog_devices(struct cx231xx *dev);
+void cx231xx_remove_from_devlist(struct cx231xx *dev);
+void cx231xx_add_into_devlist(struct cx231xx *dev);
+void cx231xx_init_extension(struct cx231xx *dev);
+void cx231xx_close_extension(struct cx231xx *dev);
+
+/* hardware init functions */
+int cx231xx_dev_init(struct cx231xx *dev);
+void cx231xx_dev_uninit(struct cx231xx *dev);
+void cx231xx_config_i2c(struct cx231xx *dev);
+int cx231xx_config(struct cx231xx *dev);
+
+/* Stream control functions */
+int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask);
+int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask);
+
+int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type);
+
+/* Power control functions */
+int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode);
+int cx231xx_power_suspend(struct cx231xx *dev);
+
+/* chip specific control functions */
+int cx231xx_init_ctrl_pin_status(struct cx231xx *dev);
+int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev,
+                                             u8 analog_or_digital);
+int cx231xx_enable_i2c_port_3(struct cx231xx *dev, bool is_port_3);
+
+/* video audio decoder related functions */
+void video_mux(struct cx231xx *dev, int index);
+int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input);
+int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input);
+int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev);
+int cx231xx_set_audio_input(struct cx231xx *dev, u8 input);
+
+/* Provided by cx231xx-video.c */
+int cx231xx_register_extension(struct cx231xx_ops *dev);
+void cx231xx_unregister_extension(struct cx231xx_ops *dev);
+void cx231xx_init_extension(struct cx231xx *dev);
+void cx231xx_close_extension(struct cx231xx *dev);
+
+/* Provided by cx231xx-cards.c */
+extern void cx231xx_pre_card_setup(struct cx231xx *dev);
+extern void cx231xx_card_setup(struct cx231xx *dev);
+extern struct cx231xx_board cx231xx_boards[];
+extern struct usb_device_id cx231xx_id_table[];
+extern const unsigned int cx231xx_bcount;
+int cx231xx_tuner_callback(void *ptr, int component, int command, int arg);
+
+/* cx23885-417.c                                               */
+extern int cx231xx_417_register(struct cx231xx *dev);
+extern void cx231xx_417_unregister(struct cx231xx *dev);
+
+/* cx23885-input.c                                             */
+
+#if defined(CONFIG_VIDEO_CX231XX_RC)
+int cx231xx_ir_init(struct cx231xx *dev);
+void cx231xx_ir_exit(struct cx231xx *dev);
+#else
+#define cx231xx_ir_init(dev)   (0)
+#define cx231xx_ir_exit(dev)   (0)
+#endif
+
+
+/* printk macros */
+
+#define cx231xx_err(fmt, arg...) do {\
+       printk(KERN_ERR fmt , ##arg); } while (0)
+
+#define cx231xx_errdev(fmt, arg...) do {\
+       printk(KERN_ERR "%s: "fmt,\
+                       dev->name , ##arg); } while (0)
+
+#define cx231xx_info(fmt, arg...) do {\
+       printk(KERN_INFO "%s: "fmt,\
+                       dev->name , ##arg); } while (0)
+#define cx231xx_warn(fmt, arg...) do {\
+       printk(KERN_WARNING "%s: "fmt,\
+                       dev->name , ##arg); } while (0)
+
+static inline unsigned int norm_maxw(struct cx231xx *dev)
+{
+       if (dev->board.max_range_640_480)
+               return 640;
+       else
+               return 720;
+}
+
+static inline unsigned int norm_maxh(struct cx231xx *dev)
+{
+       if (dev->board.max_range_640_480)
+               return 480;
+       else
+               return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
+}
+#endif
diff --git a/drivers/media/usb/em28xx/Kconfig b/drivers/media/usb/em28xx/Kconfig
new file mode 100644 (file)
index 0000000..928ef0d
--- /dev/null
@@ -0,0 +1,58 @@
+config VIDEO_EM28XX
+       tristate "Empia EM28xx USB video capture support"
+       depends on VIDEO_DEV && I2C
+       select VIDEO_TUNER
+       select VIDEO_TVEEPROM
+       select VIDEOBUF_VMALLOC
+       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO
+
+       ---help---
+         This is a video4linux driver for Empia 28xx based TV cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called em28xx
+
+config VIDEO_EM28XX_ALSA
+       depends on VIDEO_EM28XX && SND
+       select SND_PCM
+       tristate "Empia EM28xx ALSA audio module"
+       ---help---
+         This is an ALSA driver for some Empia 28xx based TV cards.
+
+         This is not required for em2800/em2820/em2821 boards. However,
+         newer em28xx devices uses Vendor Class for audio, instead of
+         implementing the USB Audio Class. For those chips, this module
+         will enable digital audio.
+
+         To compile this driver as a module, choose M here: the
+         module will be called em28xx-alsa
+
+config VIDEO_EM28XX_DVB
+       tristate "DVB/ATSC Support for em28xx based TV cards"
+       depends on VIDEO_EM28XX && DVB_CORE
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+       select DVB_TDA10023 if !DVB_FE_CUSTOMISE
+       select DVB_S921 if !DVB_FE_CUSTOMISE
+       select DVB_DRXD if !DVB_FE_CUSTOMISE
+       select DVB_CXD2820R if !DVB_FE_CUSTOMISE
+       select DVB_DRXK if !DVB_FE_CUSTOMISE
+       select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
+       select DVB_TDA10071 if !DVB_FE_CUSTOMISE
+       select DVB_A8293 if !DVB_FE_CUSTOMISE
+       select VIDEOBUF_DVB
+       ---help---
+         This adds support for DVB cards based on the
+         Empiatech em28xx chips.
+
+config VIDEO_EM28XX_RC
+        tristate "EM28XX Remote Controller support"
+        depends on RC_CORE
+        depends on VIDEO_EM28XX
+        depends on !(RC_CORE=m && VIDEO_EM28XX=y)
+        default VIDEO_EM28XX
+        ---help---
+          Enables Remote Controller support on em28xx driver.
diff --git a/drivers/media/usb/em28xx/Makefile b/drivers/media/usb/em28xx/Makefile
new file mode 100644 (file)
index 0000000..65c7c29
--- /dev/null
@@ -0,0 +1,15 @@
+em28xx-y :=    em28xx-video.o em28xx-i2c.o em28xx-cards.o
+em28xx-y +=    em28xx-core.o  em28xx-vbi.o
+
+em28xx-alsa-objs := em28xx-audio.o
+em28xx-rc-objs := em28xx-input.o
+
+obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
+obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
+obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o
+obj-$(CONFIG_VIDEO_EM28XX_RC) += em28xx-rc.o
+
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c
new file mode 100644 (file)
index 0000000..2fdb66e
--- /dev/null
@@ -0,0 +1,751 @@
+/*
+ *  Empiatech em28x1 audio extension
+ *
+ *  Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com>
+ *
+ *  Copyright (C) 2007-2011 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *     - Port to work with the in-kernel driver
+ *     - Cleanups, fixes, alsa-controls, etc.
+ *
+ *  This driver is based on my previous au600 usb pstn audio driver
+ *  and inherits all the copyrights
+ *
+ *  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/usb.h>
+#include <linux/init.h>
+#include <linux/sound.h>
+#include <linux/spinlock.h>
+#include <linux/soundcard.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
+#include <linux/module.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 <sound/tlv.h>
+#include <sound/ac97_codec.h>
+#include <media/v4l2-common.h>
+#include "em28xx.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
+
+#define dprintk(fmt, arg...) do {                                      \
+           if (debug)                                                  \
+               printk(KERN_INFO "em28xx-audio %s: " fmt,               \
+                                 __func__, ##arg);             \
+       } while (0)
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+
+static int em28xx_deinit_isoc_audio(struct em28xx *dev)
+{
+       int i;
+
+       dprintk("Stopping isoc\n");
+       for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
+               if (!irqs_disabled())
+                       usb_kill_urb(dev->adev.urb[i]);
+               else
+                       usb_unlink_urb(dev->adev.urb[i]);
+
+               usb_free_urb(dev->adev.urb[i]);
+               dev->adev.urb[i] = NULL;
+
+               kfree(dev->adev.transfer_buffer[i]);
+               dev->adev.transfer_buffer[i] = NULL;
+       }
+
+       return 0;
+}
+
+static void em28xx_audio_isocirq(struct urb *urb)
+{
+       struct em28xx            *dev = urb->context;
+       int                      i;
+       unsigned int             oldptr;
+       int                      period_elapsed = 0;
+       int                      status;
+       unsigned char            *cp;
+       unsigned int             stride;
+       struct snd_pcm_substream *substream;
+       struct snd_pcm_runtime   *runtime;
+
+       switch (urb->status) {
+       case 0:             /* success */
+       case -ETIMEDOUT:    /* NAK */
+               break;
+       case -ECONNRESET:   /* kill */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+       default:            /* error */
+               dprintk("urb completition error %d.\n", urb->status);
+               break;
+       }
+
+       if (atomic_read(&dev->stream_started) == 0)
+               return;
+
+       if (dev->adev.capture_pcm_substream) {
+               substream = dev->adev.capture_pcm_substream;
+               runtime = substream->runtime;
+               stride = runtime->frame_bits >> 3;
+
+               for (i = 0; i < urb->number_of_packets; i++) {
+                       int length =
+                           urb->iso_frame_desc[i].actual_length / stride;
+                       cp = (unsigned char *)urb->transfer_buffer +
+                           urb->iso_frame_desc[i].offset;
+
+                       if (!length)
+                               continue;
+
+                       oldptr = dev->adev.hwptr_done_capture;
+                       if (oldptr + length >= 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,
+                                      length * stride - cnt * stride);
+                       } else {
+                               memcpy(runtime->dma_area + oldptr * stride, cp,
+                                      length * stride);
+                       }
+
+                       snd_pcm_stream_lock(substream);
+
+                       dev->adev.hwptr_done_capture += length;
+                       if (dev->adev.hwptr_done_capture >=
+                           runtime->buffer_size)
+                               dev->adev.hwptr_done_capture -=
+                                   runtime->buffer_size;
+
+                       dev->adev.capture_transfer_done += length;
+                       if (dev->adev.capture_transfer_done >=
+                           runtime->period_size) {
+                               dev->adev.capture_transfer_done -=
+                                   runtime->period_size;
+                               period_elapsed = 1;
+                       }
+
+                       snd_pcm_stream_unlock(substream);
+               }
+               if (period_elapsed)
+                       snd_pcm_period_elapsed(substream);
+       }
+       urb->status = 0;
+
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (status < 0) {
+               em28xx_errdev("resubmit of audio urb failed (error=%i)\n",
+                             status);
+       }
+       return;
+}
+
+static int em28xx_init_audio_isoc(struct em28xx *dev)
+{
+       int       i, errCode;
+       const int sb_size = EM28XX_NUM_AUDIO_PACKETS *
+                           EM28XX_AUDIO_MAX_PACKET_SIZE;
+
+       dprintk("Starting isoc transfers\n");
+
+       for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
+               struct urb *urb;
+               int j, k;
+
+               dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
+               if (!dev->adev.transfer_buffer[i])
+                       return -ENOMEM;
+
+               memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
+               urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
+               if (!urb) {
+                       em28xx_errdev("usb_alloc_urb failed!\n");
+                       for (j = 0; j < i; j++) {
+                               usb_free_urb(dev->adev.urb[j]);
+                               kfree(dev->adev.transfer_buffer[j]);
+                       }
+                       return -ENOMEM;
+               }
+
+               urb->dev = dev->udev;
+               urb->context = dev;
+               urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO);
+               urb->transfer_flags = URB_ISO_ASAP;
+               urb->transfer_buffer = dev->adev.transfer_buffer[i];
+               urb->interval = 1;
+               urb->complete = em28xx_audio_isocirq;
+               urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS;
+               urb->transfer_buffer_length = sb_size;
+
+               for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS;
+                            j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length =
+                           EM28XX_AUDIO_MAX_PACKET_SIZE;
+               }
+               dev->adev.urb[i] = urb;
+       }
+
+       for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
+               errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
+               if (errCode) {
+                       em28xx_errdev("submit of audio urb failed\n");
+                       em28xx_deinit_isoc_audio(dev);
+                       atomic_set(&dev->stream_started, 0);
+                       return errCode;
+               }
+
+       }
+
+       return 0;
+}
+
+static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
+                                       size_t size)
+{
+       struct snd_pcm_runtime *runtime = subs->runtime;
+
+       dprintk("Allocating vbuffer\n");
+       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;
+
+       runtime->dma_bytes = size;
+
+       return 0;
+}
+
+static struct snd_pcm_hardware snd_em28xx_hw_capture = {
+       .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP           |
+               SNDRV_PCM_INFO_INTERLEAVED    |
+               SNDRV_PCM_INFO_BATCH          |
+               SNDRV_PCM_INFO_MMAP_VALID,
+
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT,
+
+       .rate_min = 48000,
+       .rate_max = 48000,
+       .channels_min = 2,
+       .channels_max = 2,
+       .buffer_bytes_max = 62720 * 8,  /* just about the value in usbaudio.c */
+       .period_bytes_min = 64,         /* 12544/2, */
+       .period_bytes_max = 12544,
+       .periods_min = 2,
+       .periods_max = 98,              /* 12544, */
+};
+
+static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
+{
+       struct em28xx *dev = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int ret = 0;
+
+       dprintk("opening device and trying to acquire exclusive lock\n");
+
+       if (!dev) {
+               em28xx_err("BUG: em28xx can't find device struct."
+                               " Can't proceed with open\n");
+               return -ENODEV;
+       }
+
+       runtime->hw = snd_em28xx_hw_capture;
+       if ((dev->alt == 0 || dev->audio_ifnum) && dev->adev.users == 0) {
+               if (dev->audio_ifnum)
+                       dev->alt = 1;
+               else
+                       dev->alt = 7;
+
+               dprintk("changing alternate number on interface %d to %d\n",
+                       dev->audio_ifnum, dev->alt);
+               usb_set_interface(dev->udev, dev->audio_ifnum, dev->alt);
+
+               /* Sets volume, mute, etc */
+               dev->mute = 0;
+               mutex_lock(&dev->lock);
+               ret = em28xx_audio_analog_set(dev);
+               if (ret < 0)
+                       goto err;
+
+               dev->adev.users++;
+               mutex_unlock(&dev->lock);
+       }
+
+       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+       dev->adev.capture_pcm_substream = substream;
+
+       return 0;
+err:
+       mutex_unlock(&dev->lock);
+
+       em28xx_err("Error while configuring em28xx mixer\n");
+       return ret;
+}
+
+static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
+{
+       struct em28xx *dev = snd_pcm_substream_chip(substream);
+
+       dprintk("closing device\n");
+
+       dev->mute = 1;
+       mutex_lock(&dev->lock);
+       dev->adev.users--;
+       if (atomic_read(&dev->stream_started) > 0) {
+               atomic_set(&dev->stream_started, 0);
+               schedule_work(&dev->wq_trigger);
+       }
+
+       em28xx_audio_analog_set(dev);
+       if (substream->runtime->dma_area) {
+               dprintk("freeing\n");
+               vfree(substream->runtime->dma_area);
+               substream->runtime->dma_area = NULL;
+       }
+       mutex_unlock(&dev->lock);
+
+       return 0;
+}
+
+static int snd_em28xx_hw_capture_params(struct snd_pcm_substream *substream,
+                                       struct snd_pcm_hw_params *hw_params)
+{
+       int ret;
+
+       dprintk("Setting capture parameters\n");
+
+       ret = snd_pcm_alloc_vmalloc_buffer(substream,
+                               params_buffer_bytes(hw_params));
+       if (ret < 0)
+               return ret;
+#if 0
+       /* TODO: set up em28xx audio chip to deliver the correct audio format,
+          current default is 48000hz multiplexed => 96000hz mono
+          which shouldn't matter since analogue TV only supports mono */
+       unsigned int channels, rate, format;
+
+       format = params_format(hw_params);
+       rate = params_rate(hw_params);
+       channels = params_channels(hw_params);
+#endif
+
+       return 0;
+}
+
+static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream)
+{
+       struct em28xx *dev = snd_pcm_substream_chip(substream);
+
+       dprintk("Stop capture, if needed\n");
+
+       if (atomic_read(&dev->stream_started) > 0) {
+               atomic_set(&dev->stream_started, 0);
+               schedule_work(&dev->wq_trigger);
+       }
+
+       return 0;
+}
+
+static int snd_em28xx_prepare(struct snd_pcm_substream *substream)
+{
+       struct em28xx *dev = snd_pcm_substream_chip(substream);
+
+       dev->adev.hwptr_done_capture = 0;
+       dev->adev.capture_transfer_done = 0;
+
+       return 0;
+}
+
+static void audio_trigger(struct work_struct *work)
+{
+       struct em28xx *dev = container_of(work, struct em28xx, wq_trigger);
+
+       if (atomic_read(&dev->stream_started)) {
+               dprintk("starting capture");
+               em28xx_init_audio_isoc(dev);
+       } else {
+               dprintk("stopping capture");
+               em28xx_deinit_isoc_audio(dev);
+       }
+}
+
+static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream,
+                                     int cmd)
+{
+       struct em28xx *dev = snd_pcm_substream_chip(substream);
+       int retval = 0;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
+       case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
+       case SNDRV_PCM_TRIGGER_START:
+               atomic_set(&dev->stream_started, 1);
+               break;
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
+       case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
+       case SNDRV_PCM_TRIGGER_STOP:
+               atomic_set(&dev->stream_started, 0);
+               break;
+       default:
+               retval = -EINVAL;
+       }
+       schedule_work(&dev->wq_trigger);
+       return retval;
+}
+
+static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream
+                                                   *substream)
+{
+       unsigned long flags;
+       struct em28xx *dev;
+       snd_pcm_uframes_t hwptr_done;
+
+       dev = snd_pcm_substream_chip(substream);
+       spin_lock_irqsave(&dev->adev.slock, flags);
+       hwptr_done = dev->adev.hwptr_done_capture;
+       spin_unlock_irqrestore(&dev->adev.slock, flags);
+
+       return hwptr_done;
+}
+
+static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
+                                            unsigned long offset)
+{
+       void *pageptr = subs->runtime->dma_area + offset;
+
+       return vmalloc_to_page(pageptr);
+}
+
+/*
+ * AC97 volume control support
+ */
+static int em28xx_vol_info(struct snd_kcontrol *kcontrol,
+                               struct snd_ctl_elem_info *info)
+{
+       info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       info->count = 2;
+       info->value.integer.min = 0;
+       info->value.integer.max = 0x1f;
+
+       return 0;
+}
+
+static int em28xx_vol_put(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       struct em28xx *dev = snd_kcontrol_chip(kcontrol);
+       u16 val = (0x1f - (value->value.integer.value[0] & 0x1f)) |
+                 (0x1f - (value->value.integer.value[1] & 0x1f)) << 8;
+       int rc;
+
+       mutex_lock(&dev->lock);
+       rc = em28xx_read_ac97(dev, kcontrol->private_value);
+       if (rc < 0)
+               goto err;
+
+       val |= rc & 0x8000;     /* Preserve the mute flag */
+
+       rc = em28xx_write_ac97(dev, kcontrol->private_value, val);
+       if (rc < 0)
+               goto err;
+
+       dprintk("%sleft vol %d, right vol %d (0x%04x) to ac97 volume control 0x%04x\n",
+               (val & 0x8000) ? "muted " : "",
+               0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
+               val, (int)kcontrol->private_value);
+
+err:
+       mutex_unlock(&dev->lock);
+       return rc;
+}
+
+static int em28xx_vol_get(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       struct em28xx *dev = snd_kcontrol_chip(kcontrol);
+       int val;
+
+       mutex_lock(&dev->lock);
+       val = em28xx_read_ac97(dev, kcontrol->private_value);
+       mutex_unlock(&dev->lock);
+       if (val < 0)
+               return val;
+
+       dprintk("%sleft vol %d, right vol %d (0x%04x) from ac97 volume control 0x%04x\n",
+               (val & 0x8000) ? "muted " : "",
+               0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
+               val, (int)kcontrol->private_value);
+
+       value->value.integer.value[0] = 0x1f - (val & 0x1f);
+       value->value.integer.value[1] = 0x1f - ((val << 8) & 0x1f);
+
+       return 0;
+}
+
+static int em28xx_vol_put_mute(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       struct em28xx *dev = snd_kcontrol_chip(kcontrol);
+       u16 val = value->value.integer.value[0];
+       int rc;
+
+       mutex_lock(&dev->lock);
+       rc = em28xx_read_ac97(dev, kcontrol->private_value);
+       if (rc < 0)
+               goto err;
+
+       if (val)
+               rc &= 0x1f1f;
+       else
+               rc |= 0x8000;
+
+       rc = em28xx_write_ac97(dev, kcontrol->private_value, rc);
+       if (rc < 0)
+               goto err;
+
+       dprintk("%sleft vol %d, right vol %d (0x%04x) to ac97 volume control 0x%04x\n",
+               (val & 0x8000) ? "muted " : "",
+               0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
+               val, (int)kcontrol->private_value);
+
+err:
+       mutex_unlock(&dev->lock);
+       return rc;
+}
+
+static int em28xx_vol_get_mute(struct snd_kcontrol *kcontrol,
+                              struct snd_ctl_elem_value *value)
+{
+       struct em28xx *dev = snd_kcontrol_chip(kcontrol);
+       int val;
+
+       mutex_lock(&dev->lock);
+       val = em28xx_read_ac97(dev, kcontrol->private_value);
+       mutex_unlock(&dev->lock);
+       if (val < 0)
+               return val;
+
+       if (val & 0x8000)
+               value->value.integer.value[0] = 0;
+       else
+               value->value.integer.value[0] = 1;
+
+       dprintk("%sleft vol %d, right vol %d (0x%04x) from ac97 volume control 0x%04x\n",
+               (val & 0x8000) ? "muted " : "",
+               0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
+               val, (int)kcontrol->private_value);
+
+       return 0;
+}
+
+static const DECLARE_TLV_DB_SCALE(em28xx_db_scale, -3450, 150, 0);
+
+static int em28xx_cvol_new(struct snd_card *card, struct em28xx *dev,
+                          char *name, int id)
+{
+       int err;
+       char ctl_name[44];
+       struct snd_kcontrol *kctl;
+       struct snd_kcontrol_new tmp;
+
+       memset (&tmp, 0, sizeof(tmp));
+       tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       tmp.private_value = id,
+       tmp.name  = ctl_name,
+
+       /* Add Mute Control */
+       sprintf(ctl_name, "%s Switch", name);
+       tmp.get  = em28xx_vol_get_mute;
+       tmp.put  = em28xx_vol_put_mute;
+       tmp.info = snd_ctl_boolean_mono_info;
+       kctl = snd_ctl_new1(&tmp, dev);
+       err = snd_ctl_add(card, kctl);
+       if (err < 0)
+               return err;
+       dprintk("Added control %s for ac97 volume control 0x%04x\n",
+               ctl_name, id);
+
+       memset (&tmp, 0, sizeof(tmp));
+       tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       tmp.private_value = id,
+       tmp.name  = ctl_name,
+
+       /* Add Volume Control */
+       sprintf(ctl_name, "%s Volume", name);
+       tmp.get   = em28xx_vol_get;
+       tmp.put   = em28xx_vol_put;
+       tmp.info  = em28xx_vol_info;
+       tmp.tlv.p = em28xx_db_scale,
+       kctl = snd_ctl_new1(&tmp, dev);
+       err = snd_ctl_add(card, kctl);
+       if (err < 0)
+               return err;
+       dprintk("Added control %s for ac97 volume control 0x%04x\n",
+               ctl_name, id);
+
+       return 0;
+}
+
+/*
+ * register/unregister code and data
+ */
+static struct snd_pcm_ops snd_em28xx_pcm_capture = {
+       .open      = snd_em28xx_capture_open,
+       .close     = snd_em28xx_pcm_close,
+       .ioctl     = snd_pcm_lib_ioctl,
+       .hw_params = snd_em28xx_hw_capture_params,
+       .hw_free   = snd_em28xx_hw_capture_free,
+       .prepare   = snd_em28xx_prepare,
+       .trigger   = snd_em28xx_capture_trigger,
+       .pointer   = snd_em28xx_capture_pointer,
+       .page      = snd_pcm_get_vmalloc_page,
+};
+
+static int em28xx_audio_init(struct em28xx *dev)
+{
+       struct em28xx_audio *adev = &dev->adev;
+       struct snd_pcm      *pcm;
+       struct snd_card     *card;
+       static int          devnr;
+       int                 err;
+
+       if (!dev->has_alsa_audio || dev->audio_ifnum < 0) {
+               /* This device does not support the extension (in this case
+                  the device is expecting the snd-usb-audio module or
+                  doesn't have analog audio support at all) */
+               return 0;
+       }
+
+       printk(KERN_INFO "em28xx-audio.c: probing for em28xx Audio Vendor Class\n");
+       printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
+                        "Rechberger\n");
+       printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2007-2011 Mauro Carvalho Chehab\n");
+
+       err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0,
+                             &card);
+       if (err < 0)
+               return err;
+
+       spin_lock_init(&adev->slock);
+       err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_em28xx_pcm_capture);
+       pcm->info_flags = 0;
+       pcm->private_data = dev;
+       strcpy(pcm->name, "Empia 28xx Capture");
+
+       snd_card_set_dev(card, &dev->udev->dev);
+       strcpy(card->driver, "Em28xx-Audio");
+       strcpy(card->shortname, "Em28xx Audio");
+       strcpy(card->longname, "Empia Em28xx Audio");
+
+       INIT_WORK(&dev->wq_trigger, audio_trigger);
+
+       if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
+               em28xx_cvol_new(card, dev, "Video", AC97_VIDEO);
+               em28xx_cvol_new(card, dev, "Line In", AC97_LINE);
+               em28xx_cvol_new(card, dev, "Phone", AC97_PHONE);
+               em28xx_cvol_new(card, dev, "Microphone", AC97_MIC);
+               em28xx_cvol_new(card, dev, "CD", AC97_CD);
+               em28xx_cvol_new(card, dev, "AUX", AC97_AUX);
+               em28xx_cvol_new(card, dev, "PCM", AC97_PCM);
+
+               em28xx_cvol_new(card, dev, "Master", AC97_MASTER);
+               em28xx_cvol_new(card, dev, "Line", AC97_HEADPHONE);
+               em28xx_cvol_new(card, dev, "Mono", AC97_MASTER_MONO);
+               em28xx_cvol_new(card, dev, "LFE", AC97_CENTER_LFE_MASTER);
+               em28xx_cvol_new(card, dev, "Surround", AC97_SURROUND_MASTER);
+       }
+
+       err = snd_card_register(card);
+       if (err < 0) {
+               snd_card_free(card);
+               return err;
+       }
+       adev->sndcard = card;
+       adev->udev = dev->udev;
+
+       return 0;
+}
+
+static int em28xx_audio_fini(struct em28xx *dev)
+{
+       if (dev == NULL)
+               return 0;
+
+       if (dev->has_alsa_audio != 1) {
+               /* This device does not support the extension (in this case
+                  the device is expecting the snd-usb-audio module or
+                  doesn't have analog audio support at all) */
+               return 0;
+       }
+
+       if (dev->adev.sndcard) {
+               snd_card_free(dev->adev.sndcard);
+               dev->adev.sndcard = NULL;
+       }
+
+       return 0;
+}
+
+static struct em28xx_ops audio_ops = {
+       .id   = EM28XX_AUDIO,
+       .name = "Em28xx Audio Extension",
+       .init = em28xx_audio_init,
+       .fini = em28xx_audio_fini,
+};
+
+static int __init em28xx_alsa_register(void)
+{
+       return em28xx_register_extension(&audio_ops);
+}
+
+static void __exit em28xx_alsa_unregister(void)
+{
+       em28xx_unregister_extension(&audio_ops);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_DESCRIPTION("Em28xx Audio driver");
+
+module_init(em28xx_alsa_register);
+module_exit(em28xx_alsa_unregister);
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
new file mode 100644 (file)
index 0000000..ca62b99
--- /dev/null
@@ -0,0 +1,3417 @@
+/*
+   em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB
+                   video capture devices
+
+   Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
+                     Markus Rechberger <mrechberger@gmail.com>
+                     Mauro Carvalho Chehab <mchehab@infradead.org>
+                     Sascha Sommer <saschasommer@freenet.de>
+
+   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/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/usb.h>
+#include <media/tuner.h>
+#include <media/msp3400.h>
+#include <media/saa7115.h>
+#include <media/tvp5150.h>
+#include <media/tvaudio.h>
+#include <media/mt9v011.h>
+#include <media/i2c-addr.h>
+#include <media/tveeprom.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-chip-ident.h>
+
+#include "em28xx.h"
+
+#define DRIVER_NAME         "em28xx"
+
+static int tuner = -1;
+module_param(tuner, int, 0444);
+MODULE_PARM_DESC(tuner, "tuner type");
+
+static unsigned int disable_ir;
+module_param(disable_ir, int, 0444);
+MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
+
+static unsigned int disable_usb_speed_check;
+module_param(disable_usb_speed_check, int, 0444);
+MODULE_PARM_DESC(disable_usb_speed_check,
+                "override min bandwidth requirement of 480M bps");
+
+static unsigned int card[]     = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
+module_param_array(card,  int, NULL, 0444);
+MODULE_PARM_DESC(card,     "card type");
+
+/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS - 1 */
+static unsigned long em28xx_devused;
+
+struct em28xx_hash_table {
+       unsigned long hash;
+       unsigned int  model;
+       unsigned int  tuner;
+};
+
+static void em28xx_pre_card_setup(struct em28xx *dev);
+
+/*
+ *  Reset sequences for analog/digital modes
+ */
+
+/* Reset for the most [analog] boards */
+static struct em28xx_reg_seq default_analog[] = {
+       {EM28XX_R08_GPIO,       0x6d,   ~EM_GPIO_4,     10},
+       {       -1,             -1,     -1,             -1},
+};
+
+/* Reset for the most [digital] boards */
+static struct em28xx_reg_seq default_digital[] = {
+       {EM28XX_R08_GPIO,       0x6e,   ~EM_GPIO_4,     10},
+       {       -1,             -1,     -1,             -1},
+};
+
+/* Board Hauppauge WinTV HVR 900 analog */
+static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = {
+       {EM28XX_R08_GPIO,       0x2d,   ~EM_GPIO_4,     10},
+       {0x05,                  0xff,   0x10,           10},
+       {  -1,                  -1,     -1,             -1},
+};
+
+/* Board Hauppauge WinTV HVR 900 digital */
+static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = {
+       {EM28XX_R08_GPIO,       0x2e,   ~EM_GPIO_4,     10},
+       {EM2880_R04_GPO,        0x04,   0x0f,           10},
+       {EM2880_R04_GPO,        0x0c,   0x0f,           10},
+       { -1,                   -1,     -1,             -1},
+};
+
+/* Board Hauppauge WinTV HVR 900 (R2) digital */
+static struct em28xx_reg_seq hauppauge_wintv_hvr_900R2_digital[] = {
+       {EM28XX_R08_GPIO,       0x2e,   ~EM_GPIO_4,     10},
+       {EM2880_R04_GPO,        0x0c,   0x0f,           10},
+       { -1,                   -1,     -1,             -1},
+};
+
+/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */
+static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = {
+       {EM28XX_R08_GPIO,       0x69,   ~EM_GPIO_4,      10},
+       {       -1,             -1,     -1,              -1},
+};
+
+/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */
+
+/* Board  - EM2870 Kworld 355u
+   Analog - No input analog */
+
+/* Board - EM2882 Kworld 315U digital */
+static struct em28xx_reg_seq em2882_kworld_315u_digital[] = {
+       {EM28XX_R08_GPIO,       0xff,   0xff,           10},
+       {EM28XX_R08_GPIO,       0xfe,   0xff,           10},
+       {EM2880_R04_GPO,        0x04,   0xff,           10},
+       {EM2880_R04_GPO,        0x0c,   0xff,           10},
+       {EM28XX_R08_GPIO,       0x7e,   0xff,           10},
+       {  -1,                  -1,     -1,             -1},
+};
+
+static struct em28xx_reg_seq em2882_kworld_315u_tuner_gpio[] = {
+       {EM2880_R04_GPO,        0x08,   0xff,           10},
+       {EM2880_R04_GPO,        0x0c,   0xff,           10},
+       {EM2880_R04_GPO,        0x08,   0xff,           10},
+       {EM2880_R04_GPO,        0x0c,   0xff,           10},
+       {  -1,                  -1,     -1,             -1},
+};
+
+static struct em28xx_reg_seq kworld_330u_analog[] = {
+       {EM28XX_R08_GPIO,       0x6d,   ~EM_GPIO_4,     10},
+       {EM2880_R04_GPO,        0x00,   0xff,           10},
+       { -1,                   -1,     -1,             -1},
+};
+
+static struct em28xx_reg_seq kworld_330u_digital[] = {
+       {EM28XX_R08_GPIO,       0x6e,   ~EM_GPIO_4,     10},
+       {EM2880_R04_GPO,        0x08,   0xff,           10},
+       { -1,                   -1,     -1,             -1},
+};
+
+/* Evga inDtube
+   GPIO0 - Enable digital power (s5h1409) - low to enable
+   GPIO1 - Enable analog power (tvp5150/emp202) - low to enable
+   GPIO4 - xc3028 reset
+   GOP3  - s5h1409 reset
+ */
+static struct em28xx_reg_seq evga_indtube_analog[] = {
+       {EM28XX_R08_GPIO,       0x79,   0xff,           60},
+       {       -1,             -1,     -1,             -1},
+};
+
+static struct em28xx_reg_seq evga_indtube_digital[] = {
+       {EM28XX_R08_GPIO,       0x7a,   0xff,            1},
+       {EM2880_R04_GPO,        0x04,   0xff,           10},
+       {EM2880_R04_GPO,        0x0c,   0xff,            1},
+       { -1,                   -1,     -1,             -1},
+};
+
+/*
+ * KWorld PlusTV 340U and UB435-Q (ATSC) GPIOs map:
+ * EM_GPIO_0 - currently unknown
+ * EM_GPIO_1 - LED disable/enable (1 = off, 0 = on)
+ * EM_GPIO_2 - currently unknown
+ * EM_GPIO_3 - currently unknown
+ * EM_GPIO_4 - TDA18271HD/C1 tuner (1 = active, 0 = in reset)
+ * EM_GPIO_5 - LGDT3304 ATSC/QAM demod (1 = active, 0 = in reset)
+ * EM_GPIO_6 - currently unknown
+ * EM_GPIO_7 - currently unknown
+ */
+static struct em28xx_reg_seq kworld_a340_digital[] = {
+       {EM28XX_R08_GPIO,       0x6d,           ~EM_GPIO_4,     10},
+       { -1,                   -1,             -1,             -1},
+};
+
+/* Pinnacle Hybrid Pro eb1a:2881 */
+static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = {
+       {EM28XX_R08_GPIO,       0xfd,   ~EM_GPIO_4,     10},
+       {       -1,             -1,     -1,             -1},
+};
+
+static struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = {
+       {EM28XX_R08_GPIO,       0x6e,   ~EM_GPIO_4,     10},
+       {EM2880_R04_GPO,        0x04,   0xff,          100},/* zl10353 reset */
+       {EM2880_R04_GPO,        0x0c,   0xff,            1},
+       {       -1,             -1,     -1,             -1},
+};
+
+static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_analog[] = {
+       {EM28XX_R08_GPIO,       0x6d,   ~EM_GPIO_4,     10},
+       {EM2880_R04_GPO,        0x00,   0xff,           10},
+       { -1,                   -1,     -1,             -1},
+};
+
+static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_digital[] = {
+       {EM28XX_R08_GPIO,       0x6e,   ~EM_GPIO_4,     10},
+       {EM2880_R04_GPO,        0x08,   0xff,           10},
+       { -1,                   -1,     -1,             -1},
+};
+
+/* eb1a:2868 Reddo DVB-C USB TV Box
+   GPIO4 - CU1216L NIM
+   Other GPIOs seems to be don't care. */
+static struct em28xx_reg_seq reddo_dvb_c_usb_box[] = {
+       {EM28XX_R08_GPIO,       0xfe,   0xff,           10},
+       {EM28XX_R08_GPIO,       0xde,   0xff,           10},
+       {EM28XX_R08_GPIO,       0xfe,   0xff,           10},
+       {EM28XX_R08_GPIO,       0xff,   0xff,           10},
+       {EM28XX_R08_GPIO,       0x7f,   0xff,           10},
+       {EM28XX_R08_GPIO,       0x6f,   0xff,           10},
+       {EM28XX_R08_GPIO,       0xff,   0xff,           10},
+       {-1,                    -1,     -1,             -1},
+};
+
+/* Callback for the most boards */
+static struct em28xx_reg_seq default_tuner_gpio[] = {
+       {EM28XX_R08_GPIO,       EM_GPIO_4,      EM_GPIO_4,      10},
+       {EM28XX_R08_GPIO,       0,              EM_GPIO_4,      10},
+       {EM28XX_R08_GPIO,       EM_GPIO_4,      EM_GPIO_4,      10},
+       {  -1,                  -1,             -1,             -1},
+};
+
+/* Mute/unmute */
+static struct em28xx_reg_seq compro_unmute_tv_gpio[] = {
+       {EM28XX_R08_GPIO,       5,              7,              10},
+       {  -1,                  -1,             -1,             -1},
+};
+
+static struct em28xx_reg_seq compro_unmute_svid_gpio[] = {
+       {EM28XX_R08_GPIO,       4,              7,              10},
+       {  -1,                  -1,             -1,             -1},
+};
+
+static struct em28xx_reg_seq compro_mute_gpio[] = {
+       {EM28XX_R08_GPIO,       6,              7,              10},
+       {  -1,                  -1,             -1,             -1},
+};
+
+/* Terratec AV350 */
+static struct em28xx_reg_seq terratec_av350_mute_gpio[] = {
+       {EM28XX_R08_GPIO,       0xff,   0x7f,           10},
+       {       -1,             -1,     -1,             -1},
+};
+
+static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = {
+       {EM28XX_R08_GPIO,       0xff,   0xff,           10},
+       {       -1,             -1,     -1,             -1},
+};
+
+static struct em28xx_reg_seq silvercrest_reg_seq[] = {
+       {EM28XX_R08_GPIO,       0xff,   0xff,           10},
+       {EM28XX_R08_GPIO,       0x01,   0xf7,           10},
+       {       -1,             -1,     -1,             -1},
+};
+
+static struct em28xx_reg_seq vc211a_enable[] = {
+       {EM28XX_R08_GPIO,       0xff,   0x07,           10},
+       {EM28XX_R08_GPIO,       0xff,   0x0f,           10},
+       {EM28XX_R08_GPIO,       0xff,   0x0b,           10},
+       {       -1,             -1,     -1,             -1},
+};
+
+static struct em28xx_reg_seq dikom_dk300_digital[] = {
+       {EM28XX_R08_GPIO,       0x6e,   ~EM_GPIO_4,     10},
+       {EM2880_R04_GPO,        0x08,   0xff,           10},
+       { -1,                   -1,     -1,             -1},
+};
+
+
+/* Reset for the most [digital] boards */
+static struct em28xx_reg_seq leadership_digital[] = {
+       {EM2874_R80_GPIO,       0x70,   0xff,   10},
+       {       -1,             -1,     -1,     -1},
+};
+
+static struct em28xx_reg_seq leadership_reset[] = {
+       {EM2874_R80_GPIO,       0xf0,   0xff,   10},
+       {EM2874_R80_GPIO,       0xb0,   0xff,   10},
+       {EM2874_R80_GPIO,       0xf0,   0xff,   10},
+       {       -1,             -1,     -1,     -1},
+};
+
+/* 2013:024f PCTV nanoStick T2 290e
+ * GPIO_6 - demod reset
+ * GPIO_7 - LED
+ */
+static struct em28xx_reg_seq pctv_290e[] = {
+       {EM2874_R80_GPIO,       0x00,   0xff,           80},
+       {EM2874_R80_GPIO,       0x40,   0xff,           80}, /* GPIO_6 = 1 */
+       {EM2874_R80_GPIO,       0xc0,   0xff,           80}, /* GPIO_7 = 1 */
+       {-1,                    -1,     -1,             -1},
+};
+
+#if 0
+static struct em28xx_reg_seq terratec_h5_gpio[] = {
+       {EM28XX_R08_GPIO,       0xff,   0xff,   10},
+       {EM2874_R80_GPIO,       0xf6,   0xff,   100},
+       {EM2874_R80_GPIO,       0xf2,   0xff,   50},
+       {EM2874_R80_GPIO,       0xf6,   0xff,   50},
+       { -1,                   -1,     -1,     -1},
+};
+
+static struct em28xx_reg_seq terratec_h5_digital[] = {
+       {EM2874_R80_GPIO,       0xf6,   0xff,   10},
+       {EM2874_R80_GPIO,       0xe6,   0xff,   100},
+       {EM2874_R80_GPIO,       0xa6,   0xff,   10},
+       { -1,                   -1,     -1,     -1},
+};
+#endif
+
+/* 2013:024f PCTV DVB-S2 Stick 460e
+ * GPIO_0 - POWER_ON
+ * GPIO_1 - BOOST
+ * GPIO_2 - VUV_LNB (red LED)
+ * GPIO_3 - EXT_12V
+ * GPIO_4 - INT_DEM (DEMOD GPIO_0)
+ * GPIO_5 - INT_LNB
+ * GPIO_6 - RESET_DEM
+ * GPIO_7 - LED (green LED)
+ */
+static struct em28xx_reg_seq pctv_460e[] = {
+       {EM2874_R80_GPIO, 0x01, 0xff,  50},
+       {0x0d,            0xff, 0xff,  50},
+       {EM2874_R80_GPIO, 0x41, 0xff,  50}, /* GPIO_6=1 */
+       {0x0d,            0x42, 0xff,  50},
+       {EM2874_R80_GPIO, 0x61, 0xff,  50}, /* GPIO_5=1 */
+       {             -1,   -1,   -1,  -1},
+};
+
+#if 0
+static struct em28xx_reg_seq hauppauge_930c_gpio[] = {
+       {EM2874_R80_GPIO,       0x6f,   0xff,   10},
+       {EM2874_R80_GPIO,       0x4f,   0xff,   10}, /* xc5000 reset */
+       {EM2874_R80_GPIO,       0x6f,   0xff,   10},
+       {EM2874_R80_GPIO,       0x4f,   0xff,   10},
+       { -1,                   -1,     -1,     -1},
+};
+
+static struct em28xx_reg_seq hauppauge_930c_digital[] = {
+       {EM2874_R80_GPIO,       0xf6,   0xff,   10},
+       {EM2874_R80_GPIO,       0xe6,   0xff,   100},
+       {EM2874_R80_GPIO,       0xa6,   0xff,   10},
+       { -1,                   -1,     -1,     -1},
+};
+#endif
+
+/* 1b80:e425 MaxMedia UB425-TC
+ * GPIO_6 - demod reset, 0=active
+ * GPIO_7 - LED, 0=active
+ */
+static struct em28xx_reg_seq maxmedia_ub425_tc[] = {
+       {EM2874_R80_GPIO,  0x83,  0xff,  100},
+       {EM2874_R80_GPIO,  0xc3,  0xff,  100}, /* GPIO_6 = 1 */
+       {EM2874_R80_GPIO,  0x43,  0xff,  000}, /* GPIO_7 = 0 */
+       {-1,                 -1,    -1,   -1},
+};
+
+/* 2304:0242 PCTV QuatroStick (510e)
+ * GPIO_2: decoder reset, 0=active
+ * GPIO_4: decoder suspend, 0=active
+ * GPIO_6: demod reset, 0=active
+ * GPIO_7: LED, 1=active
+ */
+static struct em28xx_reg_seq pctv_510e[] = {
+       {EM2874_R80_GPIO, 0x10, 0xff, 100},
+       {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */
+       {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */
+       {             -1,   -1,   -1,  -1},
+};
+
+/* 2013:0251 PCTV QuatroStick nano (520e)
+ * GPIO_2: decoder reset, 0=active
+ * GPIO_4: decoder suspend, 0=active
+ * GPIO_6: demod reset, 0=active
+ * GPIO_7: LED, 1=active
+ */
+static struct em28xx_reg_seq pctv_520e[] = {
+       {EM2874_R80_GPIO, 0x10, 0xff, 100},
+       {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */
+       {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */
+       {EM2874_R80_GPIO, 0xd4, 0xff, 000}, /* GPIO_7 = 1 */
+       {             -1,   -1,   -1,  -1},
+};
+
+/*
+ *  Board definitions
+ */
+struct em28xx_board em28xx_boards[] = {
+       [EM2750_BOARD_UNKNOWN] = {
+               .name          = "EM2710/EM2750/EM2751 webcam grabber",
+               .xclk          = EM28XX_XCLK_FREQUENCY_20MHZ,
+               .tuner_type    = TUNER_ABSENT,
+               .is_webcam     = 1,
+               .input         = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = 0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = silvercrest_reg_seq,
+               } },
+       },
+       [EM2800_BOARD_UNKNOWN] = {
+               .name         = "Unknown EM2800 video grabber",
+               .is_em2800    = 1,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA711X,
+               .tuner_type   = TUNER_ABSENT,
+               .input        = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2820_BOARD_UNKNOWN] = {
+               .name          = "Unknown EM2750/28xx video grabber",
+               .tuner_type    = TUNER_ABSENT,
+               .is_webcam     = 1,     /* To enable sensor probe */
+       },
+       [EM2750_BOARD_DLCW_130] = {
+               /* Beijing Huaqi Information Digital Technology Co., Ltd */
+               .name          = "Huaqi DLCW-130",
+               .valid         = EM28XX_BOARD_NOT_VALIDATED,
+               .xclk          = EM28XX_XCLK_FREQUENCY_48MHZ,
+               .tuner_type    = TUNER_ABSENT,
+               .is_webcam     = 1,
+               .input         = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = 0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               } },
+       },
+       [EM2820_BOARD_KWORLD_PVRTV2800RF] = {
+               .name         = "Kworld PVR TV 2800 RF",
+               .tuner_type   = TUNER_TEMIC_PAL,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2820_BOARD_GADMEI_TVR200] = {
+               .name         = "Gadmei TVR200",
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2820_BOARD_TERRATEC_CINERGY_250] = {
+               .name         = "Terratec Cinergy 250 USB",
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+               .has_ir_i2c   = 1,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2820_BOARD_PINNACLE_USB_2] = {
+               .name         = "Pinnacle PCTV USB 2",
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+               .has_ir_i2c   = 1,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2820_BOARD_HAUPPAUGE_WINTV_USB_2] = {
+               .name         = "Hauppauge WinTV USB 2",
+               .tuner_type   = TUNER_PHILIPS_FM1236_MK3,
+               .tda9887_conf = TDA9887_PRESENT |
+                               TDA9887_PORT1_ACTIVE |
+                               TDA9887_PORT2_ACTIVE,
+               .decoder      = EM28XX_TVP5150,
+               .has_msp34xx  = 1,
+               .has_ir_i2c   = 1,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = MSP_INPUT_DEFAULT,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
+                                       MSP_DSP_IN_SCART, MSP_DSP_IN_SCART),
+               } },
+       },
+       [EM2820_BOARD_DLINK_USB_TV] = {
+               .name         = "D-Link DUB-T210 TV Tuner",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2820_BOARD_HERCULES_SMART_TV_USB2] = {
+               .name         = "Hercules Smart TV USB 2.0",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2820_BOARD_PINNACLE_USB_2_FM1216ME] = {
+               .name         = "Pinnacle PCTV USB 2 (Philips FM1216ME)",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_PHILIPS_FM1216ME_MK3,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2820_BOARD_GADMEI_UTV310] = {
+               .name         = "Gadmei UTV310",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_TNF_5335MF,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE] = {
+               .name         = "Leadtek Winfast USB II Deluxe",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_PHILIPS_FM1216ME_MK3,
+               .has_ir_i2c   = 1,
+               .tvaudio_addr = 0x58,
+               .tda9887_conf = TDA9887_PRESENT |
+                               TDA9887_PORT2_ACTIVE |
+                               TDA9887_QSS,
+               .decoder      = EM28XX_SAA711X,
+               .adecoder     = EM28XX_TVAUDIO,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE4,
+                       .amux     = EM28XX_AMUX_AUX,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE5,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+                       .radio    = {
+                       .type     = EM28XX_RADIO,
+                       .amux     = EM28XX_AMUX_AUX,
+                       }
+       },
+       [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = {
+               .name         = "Videology 20K14XUSB USB2.0",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_ABSENT,
+               .is_webcam    = 1,
+               .input        = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = 0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               } },
+       },
+       [EM2820_BOARD_SILVERCREST_WEBCAM] = {
+               .name         = "Silvercrest Webcam 1.3mpix",
+               .tuner_type   = TUNER_ABSENT,
+               .is_webcam    = 1,
+               .input        = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = 0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = silvercrest_reg_seq,
+               } },
+       },
+       [EM2821_BOARD_SUPERCOMP_USB_2] = {
+               .name         = "Supercomp USB 2.0 TV",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_PHILIPS_FM1236_MK3,
+               .tda9887_conf = TDA9887_PRESENT |
+                               TDA9887_PORT1_ACTIVE |
+                               TDA9887_PORT2_ACTIVE,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2821_BOARD_USBGEAR_VD204] = {
+               .name         = "Usbgear VD204v9",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_ABSENT,   /* Capture only device */
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type  = EM28XX_VMUX_COMPOSITE1,
+                       .vmux  = SAA7115_COMPOSITE0,
+                       .amux  = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type  = EM28XX_VMUX_SVIDEO,
+                       .vmux  = SAA7115_SVIDEO3,
+                       .amux  = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2860_BOARD_NETGMBH_CAM] = {
+               /* Beijing Huaqi Information Digital Technology Co., Ltd */
+               .name         = "NetGMBH Cam",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_ABSENT,
+               .is_webcam    = 1,
+               .input        = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = 0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               } },
+       },
+       [EM2860_BOARD_TYPHOON_DVD_MAKER] = {
+               .name         = "Typhoon DVD Maker",
+               .decoder      = EM28XX_SAA711X,
+               .tuner_type   = TUNER_ABSENT,   /* Capture only device */
+               .input        = { {
+                       .type  = EM28XX_VMUX_COMPOSITE1,
+                       .vmux  = SAA7115_COMPOSITE0,
+                       .amux  = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type  = EM28XX_VMUX_SVIDEO,
+                       .vmux  = SAA7115_SVIDEO3,
+                       .amux  = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2860_BOARD_GADMEI_UTV330] = {
+               .name         = "Gadmei UTV330",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_TNF_5335MF,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2861_BOARD_GADMEI_UTV330PLUS] = {
+               .name         = "Gadmei UTV330+",
+               .tuner_type   = TUNER_TNF_5335MF,
+               .tda9887_conf = TDA9887_PRESENT,
+               .ir_codes     = RC_MAP_GADMEI_RM008Z,
+               .decoder      = EM28XX_SAA711X,
+               .xclk         = EM28XX_XCLK_FREQUENCY_12MHZ,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2860_BOARD_TERRATEC_HYBRID_XS] = {
+               .name         = "Terratec Cinergy A Hybrid XS",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .decoder      = EM28XX_TVP5150,
+
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               } },
+       },
+       [EM2861_BOARD_KWORLD_PVRTV_300U] = {
+               .name         = "KWorld PVRTV 300U",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .decoder      = EM28XX_TVP5150,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2861_BOARD_YAKUMO_MOVIE_MIXER] = {
+               .name          = "Yakumo MovieMixer",
+               .tuner_type    = TUNER_ABSENT,  /* Capture only device */
+               .decoder       = EM28XX_TVP5150,
+               .input         = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2860_BOARD_TVP5150_REFERENCE_DESIGN] = {
+               .name          = "EM2860/TVP5150 Reference Design",
+               .tuner_type    = TUNER_ABSENT,  /* Capture only device */
+               .decoder       = EM28XX_TVP5150,
+               .input         = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2861_BOARD_PLEXTOR_PX_TV100U] = {
+               .name         = "Plextor ConvertX PX-TV100U",
+               .tuner_type   = TUNER_TNF_5335MF,
+               .xclk         = EM28XX_XCLK_I2S_MSB_TIMING |
+                               EM28XX_XCLK_FREQUENCY_12MHZ,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_TVP5150,
+               .has_msp34xx  = 1,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = pinnacle_hybrid_pro_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = pinnacle_hybrid_pro_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = pinnacle_hybrid_pro_analog,
+               } },
+       },
+
+       /* Those boards with em2870 are DVB Only*/
+
+       [EM2870_BOARD_TERRATEC_XS] = {
+               .name         = "Terratec Cinergy T XS",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+       },
+       [EM2870_BOARD_TERRATEC_XS_MT2060] = {
+               .name         = "Terratec Cinergy T XS (MT2060)",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_ABSENT, /* MT2060 */
+       },
+       [EM2870_BOARD_KWORLD_350U] = {
+               .name         = "Kworld 350 U DVB-T",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+       },
+       [EM2870_BOARD_KWORLD_355U] = {
+               .name         = "Kworld 355 U DVB-T",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_ABSENT,
+               .tuner_gpio   = default_tuner_gpio,
+               .has_dvb      = 1,
+               .dvb_gpio     = default_digital,
+       },
+       [EM2870_BOARD_PINNACLE_PCTV_DVB] = {
+               .name         = "Pinnacle PCTV DVB-T",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_ABSENT, /* MT2060 */
+               /* djh - I have serious doubts this is right... */
+               .xclk         = EM28XX_XCLK_IR_RC5_MODE |
+                               EM28XX_XCLK_FREQUENCY_10MHZ,
+       },
+       [EM2870_BOARD_COMPRO_VIDEOMATE] = {
+               .name         = "Compro, VideoMate U3",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_ABSENT, /* MT2060 */
+       },
+
+       [EM2880_BOARD_TERRATEC_HYBRID_XS_FR] = {
+               .name         = "Terratec Hybrid XS Secam",
+               .has_msp34xx  = 1,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .decoder      = EM28XX_TVP5150,
+               .has_dvb      = 1,
+               .dvb_gpio     = terratec_cinergy_USB_XS_FR_digital,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = terratec_cinergy_USB_XS_FR_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = terratec_cinergy_USB_XS_FR_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = terratec_cinergy_USB_XS_FR_analog,
+               } },
+       },
+       [EM2884_BOARD_TERRATEC_H5] = {
+               .name         = "Terratec Cinergy H5",
+               .has_dvb      = 1,
+#if 0
+               .tuner_type   = TUNER_PHILIPS_TDA8290,
+               .tuner_addr   = 0x41,
+               .dvb_gpio     = terratec_h5_digital, /* FIXME: probably wrong */
+               .tuner_gpio   = terratec_h5_gpio,
+#else
+               .tuner_type   = TUNER_ABSENT,
+#endif
+               .i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
+                               EM28XX_I2C_CLK_WAIT_ENABLE |
+                               EM28XX_I2C_FREQ_400_KHZ,
+       },
+       [EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C] = {
+               .name         = "Hauppauge WinTV HVR 930C",
+               .has_dvb      = 1,
+#if 0 /* FIXME: Add analog support */
+               .tuner_type   = TUNER_XC5000,
+               .tuner_addr   = 0x41,
+               .dvb_gpio     = hauppauge_930c_digital,
+               .tuner_gpio   = hauppauge_930c_gpio,
+#else
+               .tuner_type   = TUNER_ABSENT,
+#endif
+               .ir_codes     = RC_MAP_HAUPPAUGE,
+               .i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
+                               EM28XX_I2C_CLK_WAIT_ENABLE |
+                               EM28XX_I2C_FREQ_400_KHZ,
+       },
+       [EM2884_BOARD_CINERGY_HTC_STICK] = {
+               .name         = "Terratec Cinergy HTC Stick",
+               .has_dvb      = 1,
+               .ir_codes     = RC_MAP_NEC_TERRATEC_CINERGY_XS,
+               .tuner_type   = TUNER_ABSENT,
+               .i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
+                               EM28XX_I2C_CLK_WAIT_ENABLE |
+                               EM28XX_I2C_FREQ_400_KHZ,
+       },
+       [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = {
+               .name         = "Hauppauge WinTV HVR 900",
+               .tda9887_conf = TDA9887_PRESENT,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .mts_firmware = 1,
+               .has_dvb      = 1,
+               .dvb_gpio     = hauppauge_wintv_hvr_900_digital,
+               .ir_codes     = RC_MAP_HAUPPAUGE,
+               .decoder      = EM28XX_TVP5150,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               } },
+       },
+       [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2] = {
+               .name         = "Hauppauge WinTV HVR 900 (R2)",
+               .tda9887_conf = TDA9887_PRESENT,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .mts_firmware = 1,
+               .has_dvb      = 1,
+               .dvb_gpio     = hauppauge_wintv_hvr_900R2_digital,
+               .ir_codes     = RC_MAP_HAUPPAUGE,
+               .decoder      = EM28XX_TVP5150,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               } },
+       },
+       [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850] = {
+               .name           = "Hauppauge WinTV HVR 850",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_gpio     = default_tuner_gpio,
+               .mts_firmware   = 1,
+               .has_dvb        = 1,
+               .dvb_gpio       = hauppauge_wintv_hvr_900_digital,
+               .ir_codes       = RC_MAP_HAUPPAUGE,
+               .decoder        = EM28XX_TVP5150,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               } },
+       },
+       [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950] = {
+               .name           = "Hauppauge WinTV HVR 950",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_gpio     = default_tuner_gpio,
+               .mts_firmware   = 1,
+               .has_dvb        = 1,
+               .dvb_gpio       = hauppauge_wintv_hvr_900_digital,
+               .ir_codes       = RC_MAP_HAUPPAUGE,
+               .decoder        = EM28XX_TVP5150,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               } },
+       },
+       [EM2880_BOARD_PINNACLE_PCTV_HD_PRO] = {
+               .name           = "Pinnacle PCTV HD Pro Stick",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .mts_firmware   = 1,
+               .has_dvb        = 1,
+               .dvb_gpio       = hauppauge_wintv_hvr_900_digital,
+               .ir_codes       = RC_MAP_PINNACLE_PCTV_HD,
+               .decoder        = EM28XX_TVP5150,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               } },
+       },
+       [EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600] = {
+               .name           = "AMD ATI TV Wonder HD 600",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_gpio     = default_tuner_gpio,
+               .mts_firmware   = 1,
+               .has_dvb        = 1,
+               .dvb_gpio       = hauppauge_wintv_hvr_900_digital,
+               .ir_codes       = RC_MAP_ATI_TV_WONDER_HD_600,
+               .decoder        = EM28XX_TVP5150,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               } },
+       },
+       [EM2880_BOARD_TERRATEC_HYBRID_XS] = {
+               .name           = "Terratec Hybrid XS",
+               .tuner_type     = TUNER_XC2028,
+               .tuner_gpio     = default_tuner_gpio,
+               .decoder        = EM28XX_TVP5150,
+               .has_dvb        = 1,
+               .dvb_gpio       = default_digital,
+               .ir_codes       = RC_MAP_TERRATEC_CINERGY_XS,
+               .xclk           = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = default_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = default_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = default_analog,
+               } },
+       },
+       /* maybe there's a reason behind it why Terratec sells the Hybrid XS
+          as Prodigy XS with a different PID, let's keep it separated for now
+          maybe we'll need it lateron */
+       [EM2880_BOARD_TERRATEC_PRODIGY_XS] = {
+               .name         = "Terratec Prodigy XS",
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .decoder      = EM28XX_TVP5150,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               } },
+       },
+       [EM2820_BOARD_MSI_VOX_USB_2] = {
+               .name              = "MSI VOX USB 2.0",
+               .tuner_type        = TUNER_LG_PAL_NEW_TAPC,
+               .tda9887_conf      = TDA9887_PRESENT      |
+                                    TDA9887_PORT1_ACTIVE |
+                                    TDA9887_PORT2_ACTIVE,
+               .max_range_640_480 = 1,
+               .decoder           = EM28XX_SAA711X,
+               .input             = { {
+                       .type      = EM28XX_VMUX_TELEVISION,
+                       .vmux      = SAA7115_COMPOSITE4,
+                       .amux      = EM28XX_AMUX_VIDEO,
+               }, {
+                       .type      = EM28XX_VMUX_COMPOSITE1,
+                       .vmux      = SAA7115_COMPOSITE0,
+                       .amux      = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type      = EM28XX_VMUX_SVIDEO,
+                       .vmux      = SAA7115_SVIDEO3,
+                       .amux      = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2800_BOARD_TERRATEC_CINERGY_200] = {
+               .name         = "Terratec Cinergy 200 USB",
+               .is_em2800    = 1,
+               .has_ir_i2c   = 1,
+               .tuner_type   = TUNER_LG_TALN,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2800_BOARD_GRABBEEX_USB2800] = {
+               .name       = "eMPIA Technology, Inc. GrabBeeX+ Video Encoder",
+               .is_em2800  = 1,
+               .decoder    = EM28XX_SAA711X,
+               .tuner_type = TUNER_ABSENT, /* capture only board */
+               .input      = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2800_BOARD_VC211A] = {
+               .name         = "Actionmaster/LinXcel/Digitus VC211A",
+               .is_em2800    = 1,
+               .tuner_type   = TUNER_ABSENT,   /* Capture-only board */
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = vc211a_enable,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = vc211a_enable,
+               } },
+       },
+       [EM2800_BOARD_LEADTEK_WINFAST_USBII] = {
+               .name         = "Leadtek Winfast USB II",
+               .is_em2800    = 1,
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2800_BOARD_KWORLD_USB2800] = {
+               .name         = "Kworld USB2800",
+               .is_em2800    = 1,
+               .tuner_type   = TUNER_PHILIPS_FCV1236D,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2820_BOARD_PINNACLE_DVC_90] = {
+               .name         = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker "
+                              "/ Kworld DVD Maker 2 / Plextor ConvertX PX-AV100U",
+               .tuner_type   = TUNER_ABSENT, /* capture only board */
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2800_BOARD_VGEAR_POCKETTV] = {
+               .name         = "V-Gear PocketTV",
+               .is_em2800    = 1,
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2] = {
+               .name         = "Pixelview PlayTV Box 4 USB 2.0",
+               .tda9887_conf = TDA9887_PRESENT,
+               .tuner_type   = TUNER_YMEC_TVF_5533MF,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .aout     = EM28XX_AOUT_MONO |  /* I2S */
+                                   EM28XX_AOUT_MASTER, /* Line out pin */
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2820_BOARD_PROLINK_PLAYTV_USB2] = {
+               .name         = "SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0",
+               .has_snapshot_button = 1,
+               .tda9887_conf = TDA9887_PRESENT,
+               .tuner_type   = TUNER_YMEC_TVF_5533MF,
+               .decoder      = EM28XX_SAA711X,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = SAA7115_COMPOSITE2,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .aout     = EM28XX_AOUT_MONO |  /* I2S */
+                                   EM28XX_AOUT_MASTER, /* Line out pin */
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2860_BOARD_SAA711X_REFERENCE_DESIGN] = {
+               .name                = "EM2860/SAA711X Reference Design",
+               .has_snapshot_button = 1,
+               .tuner_type          = TUNER_ABSENT,
+               .decoder             = EM28XX_SAA711X,
+               .input               = { {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+               } },
+       },
+
+       [EM2874_BOARD_LEADERSHIP_ISDBT] = {
+               .i2c_speed      = EM2874_I2C_SECONDARY_BUS_SELECT |
+                                 EM28XX_I2C_CLK_WAIT_ENABLE |
+                                 EM28XX_I2C_FREQ_100_KHZ,
+               .xclk           = EM28XX_XCLK_FREQUENCY_10MHZ,
+               .name           = "EM2874 Leadership ISDBT",
+               .tuner_type     = TUNER_ABSENT,
+               .tuner_gpio     = leadership_reset,
+               .dvb_gpio       = leadership_digital,
+               .has_dvb        = 1,
+       },
+
+       [EM2880_BOARD_MSI_DIGIVOX_AD] = {
+               .name         = "MSI DigiVox A/D",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .decoder      = EM28XX_TVP5150,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = em2880_msi_digivox_ad_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = em2880_msi_digivox_ad_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = em2880_msi_digivox_ad_analog,
+               } },
+       },
+       [EM2880_BOARD_MSI_DIGIVOX_AD_II] = {
+               .name         = "MSI DigiVox A/D II",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .decoder      = EM28XX_TVP5150,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = em2880_msi_digivox_ad_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = em2880_msi_digivox_ad_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = em2880_msi_digivox_ad_analog,
+               } },
+       },
+       [EM2880_BOARD_KWORLD_DVB_305U] = {
+               .name         = "KWorld DVB-T 305U",
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .decoder      = EM28XX_TVP5150,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2880_BOARD_KWORLD_DVB_310U] = {
+               .name         = "KWorld DVB-T 310U",
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .has_dvb      = 1,
+               .dvb_gpio     = default_digital,
+               .mts_firmware = 1,
+               .decoder      = EM28XX_TVP5150,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = default_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = default_analog,
+               }, {    /* S-video has not been tested yet */
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = default_analog,
+               } },
+       },
+       [EM2882_BOARD_KWORLD_ATSC_315U] = {
+               .name           = "KWorld ATSC 315U HDTV TV Box",
+               .valid          = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type     = TUNER_THOMSON_DTT761X,
+               .tuner_gpio     = em2882_kworld_315u_tuner_gpio,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .decoder        = EM28XX_SAA711X,
+               .has_dvb        = 1,
+               .dvb_gpio       = em2882_kworld_315u_digital,
+               .ir_codes       = RC_MAP_KWORLD_315U,
+               .xclk           = EM28XX_XCLK_FREQUENCY_12MHZ,
+               .i2c_speed      = EM28XX_I2C_CLK_WAIT_ENABLE,
+               /* Analog mode - still not ready */
+               /*.input        = { {
+                       .type = EM28XX_VMUX_TELEVISION,
+                       .vmux = SAA7115_COMPOSITE2,
+                       .amux = EM28XX_AMUX_VIDEO,
+                       .gpio = em2882_kworld_315u_analog,
+                       .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
+               }, {
+                       .type = EM28XX_VMUX_COMPOSITE1,
+                       .vmux = SAA7115_COMPOSITE0,
+                       .amux = EM28XX_AMUX_LINE_IN,
+                       .gpio = em2882_kworld_315u_analog1,
+                       .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
+               }, {
+                       .type = EM28XX_VMUX_SVIDEO,
+                       .vmux = SAA7115_SVIDEO3,
+                       .amux = EM28XX_AMUX_LINE_IN,
+                       .gpio = em2882_kworld_315u_analog1,
+                       .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
+               } }, */
+       },
+       [EM2880_BOARD_EMPIRE_DUAL_TV] = {
+               .name = "Empire dual TV",
+               .tuner_type = TUNER_XC2028,
+               .tuner_gpio = default_tuner_gpio,
+               .has_dvb = 1,
+               .dvb_gpio = default_digital,
+               .mts_firmware = 1,
+               .decoder = EM28XX_TVP5150,
+               .input = { {
+                       .type = EM28XX_VMUX_TELEVISION,
+                       .vmux = TVP5150_COMPOSITE0,
+                       .amux = EM28XX_AMUX_VIDEO,
+                       .gpio = default_analog,
+               }, {
+                       .type = EM28XX_VMUX_COMPOSITE1,
+                       .vmux = TVP5150_COMPOSITE1,
+                       .amux = EM28XX_AMUX_LINE_IN,
+                       .gpio = default_analog,
+               }, {
+                       .type = EM28XX_VMUX_SVIDEO,
+                       .vmux = TVP5150_SVIDEO,
+                       .amux = EM28XX_AMUX_LINE_IN,
+                       .gpio = default_analog,
+               } },
+       },
+       [EM2881_BOARD_DNT_DA2_HYBRID] = {
+               .name         = "DNT DA2 Hybrid",
+               .valid        = EM28XX_BOARD_NOT_VALIDATED,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .decoder      = EM28XX_TVP5150,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = default_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = default_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = default_analog,
+               } },
+       },
+       [EM2881_BOARD_PINNACLE_HYBRID_PRO] = {
+               .name         = "Pinnacle Hybrid Pro",
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .decoder      = EM28XX_TVP5150,
+               .has_dvb      = 1,
+               .dvb_gpio     = pinnacle_hybrid_pro_digital,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = pinnacle_hybrid_pro_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = pinnacle_hybrid_pro_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = pinnacle_hybrid_pro_analog,
+               } },
+       },
+       [EM2882_BOARD_PINNACLE_HYBRID_PRO_330E] = {
+               .name         = "Pinnacle Hybrid Pro (330e)",
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .mts_firmware = 1,
+               .has_dvb      = 1,
+               .dvb_gpio     = hauppauge_wintv_hvr_900R2_digital,
+               .ir_codes     = RC_MAP_PINNACLE_PCTV_HD,
+               .decoder      = EM28XX_TVP5150,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               } },
+       },
+       [EM2882_BOARD_KWORLD_VS_DVBT] = {
+               .name         = "Kworld VS-DVB-T 323UR",
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .decoder      = EM28XX_TVP5150,
+               .mts_firmware = 1,
+               .has_dvb      = 1,
+               .dvb_gpio     = kworld_330u_digital,
+               .xclk         = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */
+               .ir_codes     = RC_MAP_KWORLD_315U,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2882_BOARD_TERRATEC_HYBRID_XS] = {
+               .name         = "Terratec Cinnergy Hybrid T USB XS (em2882)",
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .mts_firmware = 1,
+               .decoder      = EM28XX_TVP5150,
+               .has_dvb      = 1,
+               .dvb_gpio     = hauppauge_wintv_hvr_900_digital,
+               .ir_codes     = RC_MAP_TERRATEC_CINERGY_XS,
+               .xclk         = EM28XX_XCLK_FREQUENCY_12MHZ,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = hauppauge_wintv_hvr_900_analog,
+               } },
+       },
+       [EM2882_BOARD_DIKOM_DK300] = {
+               .name         = "Dikom DK300",
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .decoder      = EM28XX_TVP5150,
+               .mts_firmware = 1,
+               .has_dvb      = 1,
+               .dvb_gpio     = dikom_dk300_digital,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = default_analog,
+               } },
+       },
+       [EM2883_BOARD_KWORLD_HYBRID_330U] = {
+               .name         = "Kworld PlusTV HD Hybrid 330",
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .decoder      = EM28XX_TVP5150,
+               .mts_firmware = 1,
+               .has_dvb      = 1,
+               .dvb_gpio     = kworld_330u_digital,
+               .xclk             = EM28XX_XCLK_FREQUENCY_12MHZ,
+               .i2c_speed        = EM28XX_I2C_CLK_WAIT_ENABLE |
+                                   EM28XX_I2C_EEPROM_ON_BOARD |
+                                   EM28XX_I2C_EEPROM_KEY_VALID,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = kworld_330u_analog,
+                       .aout     = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = kworld_330u_analog,
+                       .aout     = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = kworld_330u_analog,
+               } },
+       },
+       [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = {
+               .name         = "Compro VideoMate ForYou/Stereo",
+               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
+               .tvaudio_addr = 0xb0,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_TVP5150,
+               .adecoder     = EM28XX_TVAUDIO,
+               .mute_gpio    = compro_mute_gpio,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = compro_unmute_tv_gpio,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = compro_unmute_svid_gpio,
+               } },
+       },
+       [EM2860_BOARD_KAIOMY_TVNPC_U2] = {
+               .name         = "Kaiomy TVnPC U2",
+               .vchannels    = 3,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_addr   = 0x61,
+               .mts_firmware = 1,
+               .decoder      = EM28XX_TVP5150,
+               .tuner_gpio   = default_tuner_gpio,
+               .ir_codes     = RC_MAP_KAIOMY,
+               .input          = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+               .radio          = {
+                       .type     = EM28XX_RADIO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }
+       },
+       [EM2860_BOARD_EASYCAP] = {
+               .name         = "Easy Cap Capture DC-60",
+               .vchannels    = 2,
+               .tuner_type   = TUNER_ABSENT,
+               .decoder      = EM28XX_SAA711X,
+               .input           = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2820_BOARD_IODATA_GVMVP_SZ] = {
+               .name       = "IO-DATA GV-MVP/SZ",
+               .tuner_type   = TUNER_PHILIPS_FM1236_MK3,
+               .tuner_gpio   = default_tuner_gpio,
+               .tda9887_conf = TDA9887_PRESENT,
+               .decoder      = EM28XX_TVP5150,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, { /* Composite has not been tested yet */
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               }, { /* S-video has not been tested yet */
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_VIDEO,
+               } },
+       },
+       [EM2860_BOARD_TERRATEC_GRABBY] = {
+               .name            = "Terratec Grabby",
+               .vchannels       = 2,
+               .tuner_type      = TUNER_ABSENT,
+               .decoder         = EM28XX_SAA711X,
+               .xclk            = EM28XX_XCLK_FREQUENCY_12MHZ,
+               .input           = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       [EM2860_BOARD_TERRATEC_AV350] = {
+               .name            = "Terratec AV350",
+               .vchannels       = 2,
+               .tuner_type      = TUNER_ABSENT,
+               .decoder         = EM28XX_TVP5150,
+               .xclk            = EM28XX_XCLK_FREQUENCY_12MHZ,
+               .mute_gpio       = terratec_av350_mute_gpio,
+               .input           = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AUDIO_SRC_LINE,
+                       .gpio     = terratec_av350_unmute_gpio,
+
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AUDIO_SRC_LINE,
+                       .gpio     = terratec_av350_unmute_gpio,
+               } },
+       },
+
+       [EM2860_BOARD_ELGATO_VIDEO_CAPTURE] = {
+               .name         = "Elgato Video Capture",
+               .decoder      = EM28XX_SAA711X,
+               .tuner_type   = TUNER_ABSENT,   /* Capture only device */
+               .input        = { {
+                       .type  = EM28XX_VMUX_COMPOSITE1,
+                       .vmux  = SAA7115_COMPOSITE0,
+                       .amux  = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type  = EM28XX_VMUX_SVIDEO,
+                       .vmux  = SAA7115_SVIDEO3,
+                       .amux  = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+
+       [EM2882_BOARD_EVGA_INDTUBE] = {
+               .name         = "Evga inDtube",
+               .tuner_type   = TUNER_XC2028,
+               .tuner_gpio   = default_tuner_gpio,
+               .decoder      = EM28XX_TVP5150,
+               .xclk         = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */
+               .mts_firmware = 1,
+               .has_dvb      = 1,
+               .dvb_gpio     = evga_indtube_digital,
+               .ir_codes     = RC_MAP_EVGA_INDTUBE,
+               .input        = { {
+                       .type     = EM28XX_VMUX_TELEVISION,
+                       .vmux     = TVP5150_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_VIDEO,
+                       .gpio     = evga_indtube_analog,
+               }, {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = TVP5150_COMPOSITE1,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = evga_indtube_analog,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = TVP5150_SVIDEO,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+                       .gpio     = evga_indtube_analog,
+               } },
+       },
+       /* eb1a:2868 Empia EM2870 + Philips CU1216L NIM (Philips TDA10023 +
+          Infineon TUA6034) */
+       [EM2870_BOARD_REDDO_DVB_C_USB_BOX] = {
+               .name          = "Reddo DVB-C USB TV Box",
+               .tuner_type    = TUNER_ABSENT,
+               .tuner_gpio    = reddo_dvb_c_usb_box,
+               .has_dvb       = 1,
+       },
+       /* 1b80:a340 - Empia EM2870, NXP TDA18271HD and LG DT3304, sold
+        * initially as the KWorld PlusTV 340U, then as the UB435-Q.
+        * Early variants have a TDA18271HD/C1, later ones a TDA18271HD/C2 */
+       [EM2870_BOARD_KWORLD_A340] = {
+               .name       = "KWorld PlusTV 340U or UB435-Q (ATSC)",
+               .tuner_type = TUNER_ABSENT,     /* Digital-only TDA18271HD */
+               .has_dvb    = 1,
+               .dvb_gpio   = kworld_a340_digital,
+               .tuner_gpio = default_tuner_gpio,
+       },
+       /* 2013:024f PCTV nanoStick T2 290e.
+        * Empia EM28174, Sony CXD2820R and NXP TDA18271HD/C2 */
+       [EM28174_BOARD_PCTV_290E] = {
+               .name          = "PCTV nanoStick T2 290e",
+               .i2c_speed      = EM2874_I2C_SECONDARY_BUS_SELECT |
+                       EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ,
+               .tuner_type    = TUNER_ABSENT,
+               .tuner_gpio    = pctv_290e,
+               .has_dvb       = 1,
+               .ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
+       },
+       /* 2013:024f PCTV DVB-S2 Stick 460e
+        * Empia EM28174, NXP TDA10071, Conexant CX24118A and Allegro A8293 */
+       [EM28174_BOARD_PCTV_460E] = {
+               .i2c_speed     = EM2874_I2C_SECONDARY_BUS_SELECT |
+                       EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
+               .name          = "PCTV DVB-S2 Stick (460e)",
+               .tuner_type    = TUNER_ABSENT,
+               .tuner_gpio    = pctv_460e,
+               .has_dvb       = 1,
+               .ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
+       },
+       /* eb1a:5006 Honestech VIDBOX NW03
+        * Empia EM2860, Philips SAA7113, Empia EMP202, No Tuner */
+       [EM2860_BOARD_HT_VIDBOX_NW03] = {
+               .name                = "Honestech Vidbox NW03",
+               .tuner_type          = TUNER_ABSENT,
+               .decoder             = EM28XX_SAA711X,
+               .input               = { {
+                       .type     = EM28XX_VMUX_COMPOSITE1,
+                       .vmux     = SAA7115_COMPOSITE0,
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               }, {
+                       .type     = EM28XX_VMUX_SVIDEO,
+                       .vmux     = SAA7115_SVIDEO3,  /* S-VIDEO needs confirming */
+                       .amux     = EM28XX_AMUX_LINE_IN,
+               } },
+       },
+       /* 1b80:e425 MaxMedia UB425-TC
+        * Empia EM2874B + Micronas DRX 3913KA2 + NXP TDA18271HDC2 */
+       [EM2874_BOARD_MAXMEDIA_UB425_TC] = {
+               .name          = "MaxMedia UB425-TC",
+               .tuner_type    = TUNER_ABSENT,
+               .tuner_gpio    = maxmedia_ub425_tc,
+               .has_dvb       = 1,
+               .i2c_speed     = EM2874_I2C_SECONDARY_BUS_SELECT |
+                               EM28XX_I2C_CLK_WAIT_ENABLE |
+                               EM28XX_I2C_FREQ_400_KHZ,
+       },
+       /* 2304:0242 PCTV QuatroStick (510e)
+        * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */
+       [EM2884_BOARD_PCTV_510E] = {
+               .name          = "PCTV QuatroStick (510e)",
+               .tuner_type    = TUNER_ABSENT,
+               .tuner_gpio    = pctv_510e,
+               .has_dvb       = 1,
+               .ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
+               .i2c_speed     = EM2874_I2C_SECONDARY_BUS_SELECT |
+                               EM28XX_I2C_CLK_WAIT_ENABLE |
+                               EM28XX_I2C_FREQ_400_KHZ,
+       },
+       /* 2013:0251 PCTV QuatroStick nano (520e)
+        * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */
+       [EM2884_BOARD_PCTV_520E] = {
+               .name          = "PCTV QuatroStick nano (520e)",
+               .tuner_type    = TUNER_ABSENT,
+               .tuner_gpio    = pctv_520e,
+               .has_dvb       = 1,
+               .ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
+               .i2c_speed     = EM2874_I2C_SECONDARY_BUS_SELECT |
+                               EM28XX_I2C_CLK_WAIT_ENABLE |
+                               EM28XX_I2C_FREQ_400_KHZ,
+       },
+};
+const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
+
+/* table of devices that work with this driver */
+struct usb_device_id em28xx_id_table[] = {
+       { USB_DEVICE(0xeb1a, 0x2750),
+                       .driver_info = EM2750_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2751),
+                       .driver_info = EM2750_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2800),
+                       .driver_info = EM2800_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2710),
+                       .driver_info = EM2820_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2820),
+                       .driver_info = EM2820_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2821),
+                       .driver_info = EM2820_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2860),
+                       .driver_info = EM2820_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2861),
+                       .driver_info = EM2820_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2862),
+                       .driver_info = EM2820_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2863),
+                       .driver_info = EM2820_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2870),
+                       .driver_info = EM2820_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2881),
+                       .driver_info = EM2820_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2883),
+                       .driver_info = EM2820_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2868),
+                       .driver_info = EM2820_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0x2875),
+                       .driver_info = EM2820_BOARD_UNKNOWN },
+       { USB_DEVICE(0xeb1a, 0xe300),
+                       .driver_info = EM2861_BOARD_KWORLD_PVRTV_300U },
+       { USB_DEVICE(0xeb1a, 0xe303),
+                       .driver_info = EM2860_BOARD_KAIOMY_TVNPC_U2 },
+       { USB_DEVICE(0xeb1a, 0xe305),
+                       .driver_info = EM2880_BOARD_KWORLD_DVB_305U },
+       { USB_DEVICE(0xeb1a, 0xe310),
+                       .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD },
+       { USB_DEVICE(0xeb1a, 0xa313),
+               .driver_info = EM2882_BOARD_KWORLD_ATSC_315U },
+       { USB_DEVICE(0xeb1a, 0xa316),
+                       .driver_info = EM2883_BOARD_KWORLD_HYBRID_330U },
+       { USB_DEVICE(0xeb1a, 0xe320),
+                       .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD_II },
+       { USB_DEVICE(0xeb1a, 0xe323),
+                       .driver_info = EM2882_BOARD_KWORLD_VS_DVBT },
+       { USB_DEVICE(0xeb1a, 0xe350),
+                       .driver_info = EM2870_BOARD_KWORLD_350U },
+       { USB_DEVICE(0xeb1a, 0xe355),
+                       .driver_info = EM2870_BOARD_KWORLD_355U },
+       { USB_DEVICE(0xeb1a, 0x2801),
+                       .driver_info = EM2800_BOARD_GRABBEEX_USB2800 },
+       { USB_DEVICE(0xeb1a, 0xe357),
+                       .driver_info = EM2870_BOARD_KWORLD_355U },
+       { USB_DEVICE(0xeb1a, 0xe359),
+                       .driver_info = EM2870_BOARD_KWORLD_355U },
+       { USB_DEVICE(0x1b80, 0xe302),
+                       .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kaiser Baas Video to DVD maker */
+       { USB_DEVICE(0x1b80, 0xe304),
+                       .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kworld DVD Maker 2 */
+       { USB_DEVICE(0x0ccd, 0x0036),
+                       .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 },
+       { USB_DEVICE(0x0ccd, 0x004c),
+                       .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS_FR },
+       { USB_DEVICE(0x0ccd, 0x004f),
+                       .driver_info = EM2860_BOARD_TERRATEC_HYBRID_XS },
+       { USB_DEVICE(0x0ccd, 0x005e),
+                       .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS },
+       { USB_DEVICE(0x0ccd, 0x0042),
+                       .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS },
+       { USB_DEVICE(0x0ccd, 0x0043),
+                       .driver_info = EM2870_BOARD_TERRATEC_XS },
+       { USB_DEVICE(0x0ccd, 0x008e),   /* Cinergy HTC USB XS Rev. 1 */
+                       .driver_info = EM2884_BOARD_TERRATEC_H5 },
+       { USB_DEVICE(0x0ccd, 0x00ac),   /* Cinergy HTC USB XS Rev. 2 */
+                       .driver_info = EM2884_BOARD_TERRATEC_H5 },
+       { USB_DEVICE(0x0ccd, 0x10a2),   /* H5 Rev. 1 */
+                       .driver_info = EM2884_BOARD_TERRATEC_H5 },
+       { USB_DEVICE(0x0ccd, 0x10ad),   /* H5 Rev. 2 */
+                       .driver_info = EM2884_BOARD_TERRATEC_H5 },
+       { USB_DEVICE(0x0ccd, 0x0084),
+                       .driver_info = EM2860_BOARD_TERRATEC_AV350 },
+       { USB_DEVICE(0x0ccd, 0x0096),
+                       .driver_info = EM2860_BOARD_TERRATEC_GRABBY },
+       { USB_DEVICE(0x0ccd, 0x10AF),
+                       .driver_info = EM2860_BOARD_TERRATEC_GRABBY },
+       { USB_DEVICE(0x0ccd, 0x00b2),
+                       .driver_info = EM2884_BOARD_CINERGY_HTC_STICK },
+       { USB_DEVICE(0x0fd9, 0x0033),
+                       .driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE},
+       { USB_DEVICE(0x185b, 0x2870),
+                       .driver_info = EM2870_BOARD_COMPRO_VIDEOMATE },
+       { USB_DEVICE(0x185b, 0x2041),
+                       .driver_info = EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU },
+       { USB_DEVICE(0x2040, 0x4200),
+                       .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 },
+       { USB_DEVICE(0x2040, 0x4201),
+                       .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 },
+       { USB_DEVICE(0x2040, 0x6500),
+                       .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 },
+       { USB_DEVICE(0x2040, 0x6502),
+                       .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 },
+       { USB_DEVICE(0x2040, 0x6513), /* HCW HVR-980 */
+                       .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 },
+       { USB_DEVICE(0x2040, 0x6517), /* HP  HVR-950 */
+                       .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 },
+       { USB_DEVICE(0x2040, 0x651b), /* RP  HVR-950 */
+                       .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 },
+       { USB_DEVICE(0x2040, 0x651f),
+                       .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 },
+       { USB_DEVICE(0x0438, 0xb002),
+                       .driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 },
+       { USB_DEVICE(0x2001, 0xf112),
+                       .driver_info = EM2820_BOARD_DLINK_USB_TV },
+       { USB_DEVICE(0x2304, 0x0207),
+                       .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
+       { USB_DEVICE(0x2304, 0x0208),
+                       .driver_info = EM2820_BOARD_PINNACLE_USB_2 },
+       { USB_DEVICE(0x2304, 0x021a),
+                       .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
+       { USB_DEVICE(0x2304, 0x0226),
+                       .driver_info = EM2882_BOARD_PINNACLE_HYBRID_PRO_330E },
+       { USB_DEVICE(0x2304, 0x0227),
+                       .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO },
+       { USB_DEVICE(0x0413, 0x6023),
+                       .driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII },
+       { USB_DEVICE(0x093b, 0xa003),
+                      .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
+       { USB_DEVICE(0x093b, 0xa005),
+                       .driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U },
+       { USB_DEVICE(0x04bb, 0x0515),
+                       .driver_info = EM2820_BOARD_IODATA_GVMVP_SZ },
+       { USB_DEVICE(0xeb1a, 0x50a6),
+                       .driver_info = EM2860_BOARD_GADMEI_UTV330 },
+       { USB_DEVICE(0x1b80, 0xa340),
+                       .driver_info = EM2870_BOARD_KWORLD_A340 },
+       { USB_DEVICE(0x2013, 0x024f),
+                       .driver_info = EM28174_BOARD_PCTV_290E },
+       { USB_DEVICE(0x2013, 0x024c),
+                       .driver_info = EM28174_BOARD_PCTV_460E },
+       { USB_DEVICE(0x2040, 0x1605),
+                       .driver_info = EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C },
+       { USB_DEVICE(0xeb1a, 0x5006),
+                       .driver_info = EM2860_BOARD_HT_VIDBOX_NW03 },
+       { USB_DEVICE(0x1b80, 0xe309), /* Sveon STV40 */
+                       .driver_info = EM2860_BOARD_EASYCAP },
+       { USB_DEVICE(0x1b80, 0xe425),
+                       .driver_info = EM2874_BOARD_MAXMEDIA_UB425_TC },
+       { USB_DEVICE(0x2304, 0x0242),
+                       .driver_info = EM2884_BOARD_PCTV_510E },
+       { USB_DEVICE(0x2013, 0x0251),
+                       .driver_info = EM2884_BOARD_PCTV_520E },
+       { },
+};
+MODULE_DEVICE_TABLE(usb, em28xx_id_table);
+
+/*
+ * EEPROM hash table for devices with generic USB IDs
+ */
+static struct em28xx_hash_table em28xx_eeprom_hash[] = {
+       /* P/N: SA 60002070465 Tuner: TVF7533-MF */
+       {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
+       {0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF},
+       {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},
+       {0x166a0441, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028},
+       {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028},
+       {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028},
+       {0x63f653bd, EM2870_BOARD_REDDO_DVB_C_USB_BOX, TUNER_ABSENT},
+       {0x4e913442, EM2882_BOARD_DIKOM_DK300, TUNER_XC2028},
+};
+
+/* I2C devicelist hash table for devices with generic USB IDs */
+static struct em28xx_hash_table em28xx_i2c_hash[] = {
+       {0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC},
+       {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC},
+       {0x1ba50080, EM2860_BOARD_SAA711X_REFERENCE_DESIGN, TUNER_ABSENT},
+       {0x77800080, EM2860_BOARD_TVP5150_REFERENCE_DESIGN, TUNER_ABSENT},
+       {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC},
+       {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF},
+       {0x6b800080, EM2874_BOARD_LEADERSHIP_ISDBT, TUNER_ABSENT},
+};
+
+/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
+static unsigned short saa711x_addrs[] = {
+       0x4a >> 1, 0x48 >> 1,   /* SAA7111, SAA7111A and SAA7113 */
+       0x42 >> 1, 0x40 >> 1,   /* SAA7114, SAA7115 and SAA7118 */
+       I2C_CLIENT_END };
+
+static unsigned short tvp5150_addrs[] = {
+       0xb8 >> 1,
+       0xba >> 1,
+       I2C_CLIENT_END
+};
+
+static unsigned short msp3400_addrs[] = {
+       0x80 >> 1,
+       0x88 >> 1,
+       I2C_CLIENT_END
+};
+
+int em28xx_tuner_callback(void *ptr, int component, int command, int arg)
+{
+       int rc = 0;
+       struct em28xx *dev = ptr;
+
+       if (dev->tuner_type != TUNER_XC2028 && dev->tuner_type != TUNER_XC5000)
+               return 0;
+
+       if (command != XC2028_TUNER_RESET && command != XC5000_TUNER_RESET)
+               return 0;
+
+       rc = em28xx_gpio_set(dev, dev->board.tuner_gpio);
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(em28xx_tuner_callback);
+
+static inline void em28xx_set_model(struct em28xx *dev)
+{
+       memcpy(&dev->board, &em28xx_boards[dev->model], sizeof(dev->board));
+
+       /* Those are the default values for the majority of boards
+          Use those values if not specified otherwise at boards entry
+        */
+       if (!dev->board.xclk)
+               dev->board.xclk = EM28XX_XCLK_IR_RC5_MODE |
+                                 EM28XX_XCLK_FREQUENCY_12MHZ;
+
+       if (!dev->board.i2c_speed)
+               dev->board.i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE |
+                                      EM28XX_I2C_FREQ_100_KHZ;
+}
+
+
+/* FIXME: Should be replaced by a proper mt9m111 driver */
+static int em28xx_initialize_mt9m111(struct em28xx *dev)
+{
+       int i;
+       unsigned char regs[][3] = {
+               { 0x0d, 0x00, 0x01, },  /* reset and use defaults */
+               { 0x0d, 0x00, 0x00, },
+               { 0x0a, 0x00, 0x21, },
+               { 0x21, 0x04, 0x00, },  /* full readout speed, no row/col skipping */
+       };
+
+       for (i = 0; i < ARRAY_SIZE(regs); i++)
+               i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
+
+       return 0;
+}
+
+
+/* FIXME: Should be replaced by a proper mt9m001 driver */
+static int em28xx_initialize_mt9m001(struct em28xx *dev)
+{
+       int i;
+       unsigned char regs[][3] = {
+               { 0x0d, 0x00, 0x01, },
+               { 0x0d, 0x00, 0x00, },
+               { 0x04, 0x05, 0x00, },  /* hres = 1280 */
+               { 0x03, 0x04, 0x00, },  /* vres = 1024 */
+               { 0x20, 0x11, 0x00, },
+               { 0x06, 0x00, 0x10, },
+               { 0x2b, 0x00, 0x24, },
+               { 0x2e, 0x00, 0x24, },
+               { 0x35, 0x00, 0x24, },
+               { 0x2d, 0x00, 0x20, },
+               { 0x2c, 0x00, 0x20, },
+               { 0x09, 0x0a, 0xd4, },
+               { 0x35, 0x00, 0x57, },
+       };
+
+       for (i = 0; i < ARRAY_SIZE(regs); i++)
+               i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
+
+       return 0;
+}
+
+/* HINT method: webcam I2C chips
+ *
+ * This method works for webcams with Micron sensors
+ */
+static int em28xx_hint_sensor(struct em28xx *dev)
+{
+       int rc;
+       char *sensor_name;
+       unsigned char cmd;
+       __be16 version_be;
+       u16 version;
+
+       /* Micron sensor detection */
+       dev->i2c_client.addr = 0xba >> 1;
+       cmd = 0;
+       i2c_master_send(&dev->i2c_client, &cmd, 1);
+       rc = i2c_master_recv(&dev->i2c_client, (char *)&version_be, 2);
+       if (rc != 2)
+               return -EINVAL;
+
+       version = be16_to_cpu(version_be);
+       switch (version) {
+       case 0x8232:            /* mt9v011 640x480 1.3 Mpix sensor */
+       case 0x8243:            /* mt9v011 rev B 640x480 1.3 Mpix sensor */
+               dev->model = EM2820_BOARD_SILVERCREST_WEBCAM;
+               em28xx_set_model(dev);
+
+               sensor_name = "mt9v011";
+               dev->em28xx_sensor = EM28XX_MT9V011;
+               dev->sensor_xres = 640;
+               dev->sensor_yres = 480;
+               /*
+                * FIXME: mt9v011 uses I2S speed as xtal clk - at least with
+                * the Silvercrest cam I have here for testing - for higher
+                * resolutions, a high clock cause horizontal artifacts, so we
+                * need to use a lower xclk frequency.
+                * Yet, it would be possible to adjust xclk depending on the
+                * desired resolution, since this affects directly the
+                * frame rate.
+                */
+               dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ;
+               dev->sensor_xtal = 4300000;
+
+               /* probably means GRGB 16 bit bayer */
+               dev->vinmode = 0x0d;
+               dev->vinctl = 0x00;
+
+               break;
+
+       case 0x143a:    /* MT9M111 as found in the ECS G200 */
+               dev->model = EM2750_BOARD_UNKNOWN;
+               em28xx_set_model(dev);
+
+               sensor_name = "mt9m111";
+               dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ;
+               dev->em28xx_sensor = EM28XX_MT9M111;
+               em28xx_initialize_mt9m111(dev);
+               dev->sensor_xres = 640;
+               dev->sensor_yres = 512;
+
+               dev->vinmode = 0x0a;
+               dev->vinctl = 0x00;
+
+               break;
+
+       case 0x8431:
+               dev->model = EM2750_BOARD_UNKNOWN;
+               em28xx_set_model(dev);
+
+               sensor_name = "mt9m001";
+               dev->em28xx_sensor = EM28XX_MT9M001;
+               em28xx_initialize_mt9m001(dev);
+               dev->sensor_xres = 1280;
+               dev->sensor_yres = 1024;
+
+               /* probably means BGGR 16 bit bayer */
+               dev->vinmode = 0x0c;
+               dev->vinctl = 0x00;
+
+               break;
+       default:
+               printk("Unknown Micron Sensor 0x%04x\n", version);
+               return -EINVAL;
+       }
+
+       /* Setup webcam defaults */
+       em28xx_pre_card_setup(dev);
+
+       em28xx_errdev("Sensor is %s, using model %s entry.\n",
+                     sensor_name, em28xx_boards[dev->model].name);
+
+       return 0;
+}
+
+/* Since em28xx_pre_card_setup() requires a proper dev->model,
+ * this won't work for boards with generic PCI IDs
+ */
+static void em28xx_pre_card_setup(struct em28xx *dev)
+{
+       /* Set the initial XCLK and I2C clock values based on the board
+          definition */
+       em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f);
+       if (!dev->board.is_em2800)
+               em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
+       msleep(50);
+
+       /* request some modules */
+       switch (dev->model) {
+       case EM2861_BOARD_PLEXTOR_PX_TV100U:
+               /* Sets the msp34xx I2S speed */
+               dev->i2s_speed = 2048000;
+               break;
+       case EM2861_BOARD_KWORLD_PVRTV_300U:
+       case EM2880_BOARD_KWORLD_DVB_305U:
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x6d);
+               msleep(10);
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x7d);
+               msleep(10);
+               break;
+       case EM2870_BOARD_COMPRO_VIDEOMATE:
+               /* TODO: someone can do some cleanup here...
+                        not everything's needed */
+               em28xx_write_reg(dev, EM2880_R04_GPO, 0x00);
+               msleep(10);
+               em28xx_write_reg(dev, EM2880_R04_GPO, 0x01);
+               msleep(10);
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
+               mdelay(70);
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc);
+               mdelay(70);
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xdc);
+               mdelay(70);
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc);
+               mdelay(70);
+               break;
+       case EM2870_BOARD_TERRATEC_XS_MT2060:
+               /* this device needs some gpio writes to get the DVB-T
+                  demod work */
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
+               mdelay(70);
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xde);
+               mdelay(70);
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
+               mdelay(70);
+               break;
+       case EM2870_BOARD_PINNACLE_PCTV_DVB:
+               /* this device needs some gpio writes to get the
+                  DVB-T demod work */
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
+               mdelay(70);
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xde);
+               mdelay(70);
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
+               mdelay(70);
+               break;
+       case EM2820_BOARD_GADMEI_UTV310:
+       case EM2820_BOARD_MSI_VOX_USB_2:
+               /* enables audio for that devices */
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
+               break;
+
+       case EM2882_BOARD_KWORLD_ATSC_315U:
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
+               msleep(10);
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
+               msleep(10);
+               em28xx_write_reg(dev, EM2880_R04_GPO, 0x00);
+               msleep(10);
+               em28xx_write_reg(dev, EM2880_R04_GPO, 0x08);
+               msleep(10);
+               break;
+
+       case EM2860_BOARD_KAIOMY_TVNPC_U2:
+               em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x07", 1);
+               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
+               em28xx_write_regs(dev, 0x0d, "\x42", 1);
+               em28xx_write_regs(dev, 0x08, "\xfd", 1);
+               msleep(10);
+               em28xx_write_regs(dev, 0x08, "\xff", 1);
+               msleep(10);
+               em28xx_write_regs(dev, 0x08, "\x7f", 1);
+               msleep(10);
+               em28xx_write_regs(dev, 0x08, "\x6b", 1);
+
+               break;
+       case EM2860_BOARD_EASYCAP:
+               em28xx_write_regs(dev, 0x08, "\xf8", 1);
+               break;
+
+       case EM2820_BOARD_IODATA_GVMVP_SZ:
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
+               msleep(70);
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7);
+               msleep(10);
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
+               msleep(70);
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
+               msleep(70);
+               break;
+       }
+
+       em28xx_gpio_set(dev, dev->board.tuner_gpio);
+       em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
+
+       /* Unlock device */
+       em28xx_set_mode(dev, EM28XX_SUSPEND);
+}
+
+static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
+{
+       memset(ctl, 0, sizeof(*ctl));
+
+       ctl->fname   = XC2028_DEFAULT_FIRMWARE;
+       ctl->max_len = 64;
+       ctl->mts = em28xx_boards[dev->model].mts_firmware;
+
+       switch (dev->model) {
+       case EM2880_BOARD_EMPIRE_DUAL_TV:
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+       case EM2882_BOARD_TERRATEC_HYBRID_XS:
+               ctl->demod = XC3028_FE_ZARLINK456;
+               break;
+       case EM2880_BOARD_TERRATEC_HYBRID_XS:
+       case EM2880_BOARD_TERRATEC_HYBRID_XS_FR:
+       case EM2881_BOARD_PINNACLE_HYBRID_PRO:
+               ctl->demod = XC3028_FE_ZARLINK456;
+               break;
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
+       case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
+               ctl->demod = XC3028_FE_DEFAULT;
+               break;
+       case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
+               ctl->demod = XC3028_FE_DEFAULT;
+               ctl->fname = XC3028L_DEFAULT_FIRMWARE;
+               break;
+       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
+       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
+       case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
+               /* FIXME: Better to specify the needed IF */
+               ctl->demod = XC3028_FE_DEFAULT;
+               break;
+       case EM2883_BOARD_KWORLD_HYBRID_330U:
+       case EM2882_BOARD_DIKOM_DK300:
+       case EM2882_BOARD_KWORLD_VS_DVBT:
+               ctl->demod = XC3028_FE_CHINA;
+               ctl->fname = XC2028_DEFAULT_FIRMWARE;
+               break;
+       case EM2882_BOARD_EVGA_INDTUBE:
+               ctl->demod = XC3028_FE_CHINA;
+               ctl->fname = XC3028L_DEFAULT_FIRMWARE;
+               break;
+       default:
+               ctl->demod = XC3028_FE_OREN538;
+       }
+}
+
+static void em28xx_tuner_setup(struct em28xx *dev)
+{
+       struct tuner_setup           tun_setup;
+       struct v4l2_frequency        f;
+
+       if (dev->tuner_type == TUNER_ABSENT)
+               return;
+
+       memset(&tun_setup, 0, sizeof(tun_setup));
+
+       tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+       tun_setup.tuner_callback = em28xx_tuner_callback;
+
+       if (dev->board.radio.type) {
+               tun_setup.type = dev->board.radio.type;
+               tun_setup.addr = dev->board.radio_addr;
+
+               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
+       }
+
+       if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
+               tun_setup.type   = dev->tuner_type;
+               tun_setup.addr   = dev->tuner_addr;
+
+               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
+       }
+
+       if (dev->tda9887_conf) {
+               struct v4l2_priv_tun_config tda9887_cfg;
+
+               tda9887_cfg.tuner = TUNER_TDA9887;
+               tda9887_cfg.priv = &dev->tda9887_conf;
+
+               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg);
+       }
+
+       if (dev->tuner_type == TUNER_XC2028) {
+               struct v4l2_priv_tun_config  xc2028_cfg;
+               struct xc2028_ctrl           ctl;
+
+               memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
+               memset(&ctl, 0, sizeof(ctl));
+
+               em28xx_setup_xc3028(dev, &ctl);
+
+               xc2028_cfg.tuner = TUNER_XC2028;
+               xc2028_cfg.priv  = &ctl;
+
+               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
+       }
+
+       /* configure tuner */
+       f.tuner = 0;
+       f.type = V4L2_TUNER_ANALOG_TV;
+       f.frequency = 9076;     /* just a magic number */
+       dev->ctl_freq = f.frequency;
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
+}
+
+static int em28xx_hint_board(struct em28xx *dev)
+{
+       int i;
+
+       /* HINT method: EEPROM
+        *
+        * This method works only for boards with eeprom.
+        * Uses a hash of all eeprom bytes. The hash should be
+        * unique for a vendor/tuner pair.
+        * There are a high chance that tuners for different
+        * video standards produce different hashes.
+        */
+       for (i = 0; i < ARRAY_SIZE(em28xx_eeprom_hash); i++) {
+               if (dev->hash == em28xx_eeprom_hash[i].hash) {
+                       dev->model = em28xx_eeprom_hash[i].model;
+                       dev->tuner_type = em28xx_eeprom_hash[i].tuner;
+
+                       em28xx_errdev("Your board has no unique USB ID.\n");
+                       em28xx_errdev("A hint were successfully done, "
+                                     "based on eeprom hash.\n");
+                       em28xx_errdev("This method is not 100%% failproof.\n");
+                       em28xx_errdev("If the board were missdetected, "
+                                     "please email this log to:\n");
+                       em28xx_errdev("\tV4L Mailing List "
+                                     " <linux-media@vger.kernel.org>\n");
+                       em28xx_errdev("Board detected as %s\n",
+                                     em28xx_boards[dev->model].name);
+
+                       return 0;
+               }
+       }
+
+       /* HINT method: I2C attached devices
+        *
+        * This method works for all boards.
+        * Uses a hash of i2c scanned devices.
+        * Devices with the same i2c attached chips will
+        * be considered equal.
+        * This method is less precise than the eeprom one.
+        */
+
+       /* user did not request i2c scanning => do it now */
+       if (!dev->i2c_hash)
+               em28xx_do_i2c_scan(dev);
+
+       for (i = 0; i < ARRAY_SIZE(em28xx_i2c_hash); i++) {
+               if (dev->i2c_hash == em28xx_i2c_hash[i].hash) {
+                       dev->model = em28xx_i2c_hash[i].model;
+                       dev->tuner_type = em28xx_i2c_hash[i].tuner;
+                       em28xx_errdev("Your board has no unique USB ID.\n");
+                       em28xx_errdev("A hint were successfully done, "
+                                     "based on i2c devicelist hash.\n");
+                       em28xx_errdev("This method is not 100%% failproof.\n");
+                       em28xx_errdev("If the board were missdetected, "
+                                     "please email this log to:\n");
+                       em28xx_errdev("\tV4L Mailing List "
+                                     " <linux-media@vger.kernel.org>\n");
+                       em28xx_errdev("Board detected as %s\n",
+                                     em28xx_boards[dev->model].name);
+
+                       return 0;
+               }
+       }
+
+       em28xx_errdev("Your board has no unique USB ID and thus need a "
+                     "hint to be detected.\n");
+       em28xx_errdev("You may try to use card=<n> insmod option to "
+                     "workaround that.\n");
+       em28xx_errdev("Please send an email with this log to:\n");
+       em28xx_errdev("\tV4L Mailing List <linux-media@vger.kernel.org>\n");
+       em28xx_errdev("Board eeprom hash is 0x%08lx\n", dev->hash);
+       em28xx_errdev("Board i2c devicelist hash is 0x%08lx\n", dev->i2c_hash);
+
+       em28xx_errdev("Here is a list of valid choices for the card=<n>"
+                     " insmod option:\n");
+       for (i = 0; i < em28xx_bcount; i++) {
+               em28xx_errdev("    card=%d -> %s\n",
+                               i, em28xx_boards[i].name);
+       }
+       return -1;
+}
+
+static void em28xx_card_setup(struct em28xx *dev)
+{
+       /*
+        * If the device can be a webcam, seek for a sensor.
+        * If sensor is not found, then it isn't a webcam.
+        */
+       if (dev->board.is_webcam) {
+               if (em28xx_hint_sensor(dev) < 0)
+                       dev->board.is_webcam = 0;
+               else
+                       dev->progressive = 1;
+       }
+
+       if (!dev->board.is_webcam) {
+               switch (dev->model) {
+               case EM2820_BOARD_UNKNOWN:
+               case EM2800_BOARD_UNKNOWN:
+               /*
+                * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD.
+                *
+                * This occurs because they share identical USB vendor and
+                * product IDs.
+                *
+                * What we do here is look up the EEPROM hash of the K-WORLD
+                * and if it is found then we decide that we do not have
+                * a DIGIVOX and reset the device to the K-WORLD instead.
+                *
+                * This solution is only valid if they do not share eeprom
+                * hash identities which has not been determined as yet.
+                */
+               if (em28xx_hint_board(dev) < 0)
+                       em28xx_errdev("Board not discovered\n");
+               else {
+                       em28xx_set_model(dev);
+                       em28xx_pre_card_setup(dev);
+               }
+               break;
+               default:
+                       em28xx_set_model(dev);
+               }
+       }
+
+       em28xx_info("Identified as %s (card=%d)\n",
+                   dev->board.name, dev->model);
+
+       dev->tuner_type = em28xx_boards[dev->model].tuner_type;
+       if (em28xx_boards[dev->model].tuner_addr)
+               dev->tuner_addr = em28xx_boards[dev->model].tuner_addr;
+
+       if (em28xx_boards[dev->model].tda9887_conf)
+               dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
+
+       /* request some modules */
+       switch (dev->model) {
+       case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
+       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
+       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
+       {
+               struct tveeprom tv;
+#if defined(CONFIG_MODULES) && defined(MODULE)
+               request_module("tveeprom");
+#endif
+               /* Call first TVeeprom */
+
+               dev->i2c_client.addr = 0xa0 >> 1;
+               tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata);
+
+               dev->tuner_type = tv.tuner_type;
+
+               if (tv.audio_processor == V4L2_IDENT_MSPX4XX) {
+                       dev->i2s_speed = 2048000;
+                       dev->board.has_msp34xx = 1;
+               }
+               break;
+       }
+       case EM2882_BOARD_KWORLD_ATSC_315U:
+               em28xx_write_reg(dev, 0x0d, 0x42);
+               msleep(10);
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
+               msleep(10);
+               break;
+       case EM2820_BOARD_KWORLD_PVRTV2800RF:
+               /* GPIO enables sound on KWORLD PVR TV 2800RF */
+               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf9);
+               break;
+       case EM2820_BOARD_UNKNOWN:
+       case EM2800_BOARD_UNKNOWN:
+               /*
+                * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD.
+                *
+                * This occurs because they share identical USB vendor and
+                * product IDs.
+                *
+                * What we do here is look up the EEPROM hash of the K-WORLD
+                * and if it is found then we decide that we do not have
+                * a DIGIVOX and reset the device to the K-WORLD instead.
+                *
+                * This solution is only valid if they do not share eeprom
+                * hash identities which has not been determined as yet.
+                */
+       case EM2880_BOARD_MSI_DIGIVOX_AD:
+               if (!em28xx_hint_board(dev))
+                       em28xx_set_model(dev);
+
+               /* In cases where we had to use a board hint, the call to
+                  em28xx_set_mode() in em28xx_pre_card_setup() was a no-op,
+                  so make the call now so the analog GPIOs are set properly
+                  before probing the i2c bus. */
+               em28xx_gpio_set(dev, dev->board.tuner_gpio);
+               em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
+               break;
+
+/*
+                * The Dikom DK300 is detected as an Kworld VS-DVB-T 323UR.
+                *
+                * This occurs because they share identical USB vendor and
+                * product IDs.
+                *
+                * What we do here is look up the EEPROM hash of the Dikom
+                * and if it is found then we decide that we do not have
+                * a Kworld and reset the device to the Dikom instead.
+                *
+                * This solution is only valid if they do not share eeprom
+                * hash identities which has not been determined as yet.
+                */
+       case EM2882_BOARD_KWORLD_VS_DVBT:
+               if (!em28xx_hint_board(dev))
+                       em28xx_set_model(dev);
+
+               /* In cases where we had to use a board hint, the call to
+                  em28xx_set_mode() in em28xx_pre_card_setup() was a no-op,
+                  so make the call now so the analog GPIOs are set properly
+                  before probing the i2c bus. */
+               em28xx_gpio_set(dev, dev->board.tuner_gpio);
+               em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
+               break;
+       }
+
+       if (dev->board.valid == EM28XX_BOARD_NOT_VALIDATED) {
+               em28xx_errdev("\n\n");
+               em28xx_errdev("The support for this board weren't "
+                             "valid yet.\n");
+               em28xx_errdev("Please send a report of having this working\n");
+               em28xx_errdev("not to V4L mailing list (and/or to other "
+                               "addresses)\n\n");
+       }
+
+       /* Allow override tuner type by a module parameter */
+       if (tuner >= 0)
+               dev->tuner_type = tuner;
+
+       /* request some modules */
+       if (dev->board.has_msp34xx)
+               v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+                       "msp3400", 0, msp3400_addrs);
+
+       if (dev->board.decoder == EM28XX_SAA711X)
+               v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+                       "saa7115_auto", 0, saa711x_addrs);
+
+       if (dev->board.decoder == EM28XX_TVP5150)
+               v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+                       "tvp5150", 0, tvp5150_addrs);
+
+       if (dev->em28xx_sensor == EM28XX_MT9V011) {
+               struct mt9v011_platform_data pdata;
+               struct i2c_board_info mt9v011_info = {
+                       .type = "mt9v011",
+                       .addr = 0xba >> 1,
+                       .platform_data = &pdata,
+               };
+
+               pdata.xtal = dev->sensor_xtal;
+               v4l2_i2c_new_subdev_board(&dev->v4l2_dev, &dev->i2c_adap,
+                               &mt9v011_info, NULL);
+       }
+
+
+       if (dev->board.adecoder == EM28XX_TVAUDIO)
+               v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+                       "tvaudio", dev->board.tvaudio_addr, NULL);
+
+       if (dev->board.tuner_type != TUNER_ABSENT) {
+               int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
+
+               if (dev->board.radio.type)
+                       v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+                               "tuner", dev->board.radio_addr, NULL);
+
+               if (has_demod)
+                       v4l2_i2c_new_subdev(&dev->v4l2_dev,
+                               &dev->i2c_adap, "tuner",
+                               0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+               if (dev->tuner_addr == 0) {
+                       enum v4l2_i2c_tuner_type type =
+                               has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
+                       struct v4l2_subdev *sd;
+
+                       sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
+                               &dev->i2c_adap, "tuner",
+                               0, v4l2_i2c_tuner_addrs(type));
+
+                       if (sd)
+                               dev->tuner_addr = v4l2_i2c_subdev_addr(sd);
+               } else {
+                       v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+                               "tuner", dev->tuner_addr, NULL);
+               }
+       }
+
+       em28xx_tuner_setup(dev);
+}
+
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
+static void request_module_async(struct work_struct *work)
+{
+       struct em28xx *dev = container_of(work,
+                            struct em28xx, request_module_wk);
+
+       if (dev->has_audio_class)
+               request_module("snd-usb-audio");
+       else if (dev->has_alsa_audio)
+               request_module("em28xx-alsa");
+
+       if (dev->board.has_dvb)
+               request_module("em28xx-dvb");
+       if (dev->board.ir_codes && !disable_ir)
+               request_module("em28xx-rc");
+}
+
+static void request_modules(struct em28xx *dev)
+{
+       INIT_WORK(&dev->request_module_wk, request_module_async);
+       schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_modules(struct em28xx *dev)
+{
+       flush_work_sync(&dev->request_module_wk);
+}
+#else
+#define request_modules(dev)
+#define flush_request_modules(dev)
+#endif /* CONFIG_MODULES */
+
+/*
+ * em28xx_release_resources()
+ * unregisters the v4l2,i2c and usb devices
+ * called when the device gets disconnected or at module unload
+*/
+void em28xx_release_resources(struct em28xx *dev)
+{
+       /*FIXME: I2C IR should be disconnected */
+
+       em28xx_release_analog_resources(dev);
+
+       em28xx_i2c_unregister(dev);
+
+       v4l2_device_unregister(&dev->v4l2_dev);
+
+       usb_put_dev(dev->udev);
+
+       /* Mark device as unused */
+       clear_bit(dev->devno, &em28xx_devused);
+};
+
+/*
+ * em28xx_init_dev()
+ * allocates and inits the device structs, registers i2c bus and v4l device
+ */
+static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
+                          struct usb_interface *interface,
+                          int minor)
+{
+       int retval;
+
+       dev->udev = udev;
+       mutex_init(&dev->ctrl_urb_lock);
+       spin_lock_init(&dev->slock);
+
+       dev->em28xx_write_regs = em28xx_write_regs;
+       dev->em28xx_read_reg = em28xx_read_reg;
+       dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len;
+       dev->em28xx_write_regs_req = em28xx_write_regs_req;
+       dev->em28xx_read_reg_req = em28xx_read_reg_req;
+       dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800;
+
+       em28xx_set_model(dev);
+
+       /* Set the default GPO/GPIO for legacy devices */
+       dev->reg_gpo_num = EM2880_R04_GPO;
+       dev->reg_gpio_num = EM28XX_R08_GPIO;
+
+       dev->wait_after_write = 5;
+
+       /* Based on the Chip ID, set the device configuration */
+       retval = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
+       if (retval > 0) {
+               dev->chip_id = retval;
+
+               switch (dev->chip_id) {
+               case CHIP_ID_EM2800:
+                       em28xx_info("chip ID is em2800\n");
+                       break;
+               case CHIP_ID_EM2710:
+                       em28xx_info("chip ID is em2710\n");
+                       break;
+               case CHIP_ID_EM2750:
+                       em28xx_info("chip ID is em2750\n");
+                       break;
+               case CHIP_ID_EM2820:
+                       em28xx_info("chip ID is em2820 (or em2710)\n");
+                       break;
+               case CHIP_ID_EM2840:
+                       em28xx_info("chip ID is em2840\n");
+                       break;
+               case CHIP_ID_EM2860:
+                       em28xx_info("chip ID is em2860\n");
+                       break;
+               case CHIP_ID_EM2870:
+                       em28xx_info("chip ID is em2870\n");
+                       dev->wait_after_write = 0;
+                       break;
+               case CHIP_ID_EM2874:
+                       em28xx_info("chip ID is em2874\n");
+                       dev->reg_gpio_num = EM2874_R80_GPIO;
+                       dev->wait_after_write = 0;
+                       break;
+               case CHIP_ID_EM28174:
+                       em28xx_info("chip ID is em28174\n");
+                       dev->reg_gpio_num = EM2874_R80_GPIO;
+                       dev->wait_after_write = 0;
+                       break;
+               case CHIP_ID_EM2883:
+                       em28xx_info("chip ID is em2882/em2883\n");
+                       dev->wait_after_write = 0;
+                       break;
+               case CHIP_ID_EM2884:
+                       em28xx_info("chip ID is em2884\n");
+                       dev->reg_gpio_num = EM2874_R80_GPIO;
+                       dev->wait_after_write = 0;
+                       break;
+               default:
+                       em28xx_info("em28xx chip ID = %d\n", dev->chip_id);
+               }
+       }
+
+       if (dev->is_audio_only) {
+               retval = em28xx_audio_setup(dev);
+               if (retval)
+                       return -ENODEV;
+               em28xx_init_extension(dev);
+
+               return 0;
+       }
+
+       /* Prepopulate cached GPO register content */
+       retval = em28xx_read_reg(dev, dev->reg_gpo_num);
+       if (retval >= 0)
+               dev->reg_gpo = retval;
+
+       em28xx_pre_card_setup(dev);
+
+       if (!dev->board.is_em2800) {
+               /* Resets I2C speed */
+               retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
+               if (retval < 0) {
+                       em28xx_errdev("%s: em28xx_write_reg failed!"
+                                     " retval [%d]\n",
+                                     __func__, retval);
+                       return retval;
+               }
+       }
+
+       retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
+       if (retval < 0) {
+               em28xx_errdev("Call to v4l2_device_register() failed!\n");
+               return retval;
+       }
+
+       /* register i2c bus */
+       retval = em28xx_i2c_register(dev);
+       if (retval < 0) {
+               em28xx_errdev("%s: em28xx_i2c_register - error [%d]!\n",
+                       __func__, retval);
+               goto unregister_dev;
+       }
+
+       /*
+        * Default format, used for tvp5150 or saa711x output formats
+        */
+       dev->vinmode = 0x10;
+       dev->vinctl  = EM28XX_VINCTRL_INTERLACED |
+                      EM28XX_VINCTRL_CCIR656_ENABLE;
+
+       /* Do board specific init and eeprom reading */
+       em28xx_card_setup(dev);
+
+       /* Configure audio */
+       retval = em28xx_audio_setup(dev);
+       if (retval < 0) {
+               em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
+                       __func__, retval);
+               goto fail;
+       }
+
+       /* wake i2c devices */
+       em28xx_wake_i2c(dev);
+
+       /* init video dma queues */
+       INIT_LIST_HEAD(&dev->vidq.active);
+       INIT_LIST_HEAD(&dev->vbiq.active);
+
+       if (dev->board.has_msp34xx) {
+               /* Send a reset to other chips via gpio */
+               retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7);
+               if (retval < 0) {
+                       em28xx_errdev("%s: em28xx_write_reg - "
+                                     "msp34xx(1) failed! error [%d]\n",
+                                     __func__, retval);
+                       goto fail;
+               }
+               msleep(3);
+
+               retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
+               if (retval < 0) {
+                       em28xx_errdev("%s: em28xx_write_reg - "
+                                     "msp34xx(2) failed! error [%d]\n",
+                                     __func__, retval);
+                       goto fail;
+               }
+               msleep(3);
+       }
+
+       retval = em28xx_register_analog_devices(dev);
+       if (retval < 0) {
+               goto fail;
+       }
+
+       /* Save some power by putting tuner to sleep */
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
+
+       return 0;
+
+fail:
+       em28xx_i2c_unregister(dev);
+
+unregister_dev:
+       v4l2_device_unregister(&dev->v4l2_dev);
+
+       return retval;
+}
+
+/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
+#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
+
+/*
+ * em28xx_usb_probe()
+ * checks for supported devices
+ */
+static int em28xx_usb_probe(struct usb_interface *interface,
+                           const struct usb_device_id *id)
+{
+       struct usb_device *udev;
+       struct em28xx *dev = NULL;
+       int retval;
+       bool has_audio = false, has_video = false, has_dvb = false;
+       int i, nr;
+       const int ifnum = interface->altsetting[0].desc.bInterfaceNumber;
+       char *speed;
+
+       udev = usb_get_dev(interface_to_usbdev(interface));
+
+       /* Check to see next free device and mark as used */
+       do {
+               nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
+               if (nr >= EM28XX_MAXBOARDS) {
+                       /* No free device slots */
+                       printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
+                                       EM28XX_MAXBOARDS);
+                       retval = -ENOMEM;
+                       goto err_no_slot;
+               }
+       } while (test_and_set_bit(nr, &em28xx_devused));
+
+       /* Don't register audio interfaces */
+       if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
+               em28xx_err(DRIVER_NAME " audio device (%04x:%04x): "
+                       "interface %i, class %i\n",
+                       le16_to_cpu(udev->descriptor.idVendor),
+                       le16_to_cpu(udev->descriptor.idProduct),
+                       ifnum,
+                       interface->altsetting[0].desc.bInterfaceClass);
+
+               retval = -ENODEV;
+               goto err;
+       }
+
+       /* allocate memory for our device state and initialize it */
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               em28xx_err(DRIVER_NAME ": out of memory!\n");
+               retval = -ENOMEM;
+               goto err;
+       }
+
+       /* compute alternate max packet sizes */
+       dev->alt_max_pkt_size = kmalloc(sizeof(dev->alt_max_pkt_size[0]) *
+                                       interface->num_altsetting, GFP_KERNEL);
+       if (dev->alt_max_pkt_size == NULL) {
+               em28xx_errdev("out of memory!\n");
+               kfree(dev);
+               retval = -ENOMEM;
+               goto err;
+       }
+
+       /* Get endpoints */
+       for (i = 0; i < interface->num_altsetting; i++) {
+               int ep;
+
+               for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) {
+                       const struct usb_endpoint_descriptor *e;
+                       int sizedescr, size;
+
+                       e = &interface->altsetting[i].endpoint[ep].desc;
+
+                       sizedescr = le16_to_cpu(e->wMaxPacketSize);
+                       size = sizedescr & 0x7ff;
+
+                       if (udev->speed == USB_SPEED_HIGH)
+                               size = size * hb_mult(sizedescr);
+
+                       if (usb_endpoint_xfer_isoc(e) &&
+                           usb_endpoint_dir_in(e)) {
+                               switch (e->bEndpointAddress) {
+                               case EM28XX_EP_AUDIO:
+                                       has_audio = true;
+                                       break;
+                               case EM28XX_EP_ANALOG:
+                                       has_video = true;
+                                       dev->alt_max_pkt_size[i] = size;
+                                       break;
+                               case EM28XX_EP_DIGITAL:
+                                       has_dvb = true;
+                                       if (size > dev->dvb_max_pkt_size) {
+                                               dev->dvb_max_pkt_size = size;
+                                               dev->dvb_alt = i;
+                                       }
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if (!(has_audio || has_video || has_dvb)) {
+               retval = -ENODEV;
+               goto err_free;
+       }
+
+       switch (udev->speed) {
+       case USB_SPEED_LOW:
+               speed = "1.5";
+               break;
+       case USB_SPEED_UNKNOWN:
+       case USB_SPEED_FULL:
+               speed = "12";
+               break;
+       case USB_SPEED_HIGH:
+               speed = "480";
+               break;
+       default:
+               speed = "unknown";
+       }
+
+       printk(KERN_INFO DRIVER_NAME
+               ": New device %s %s @ %s Mbps "
+               "(%04x:%04x, interface %d, class %d)\n",
+               udev->manufacturer ? udev->manufacturer : "",
+               udev->product ? udev->product : "",
+               speed,
+               le16_to_cpu(udev->descriptor.idVendor),
+               le16_to_cpu(udev->descriptor.idProduct),
+               ifnum,
+               interface->altsetting->desc.bInterfaceNumber);
+
+       if (has_audio)
+               printk(KERN_INFO DRIVER_NAME
+                      ": Audio Vendor Class interface %i found\n",
+                      ifnum);
+       if (has_video)
+               printk(KERN_INFO DRIVER_NAME
+                      ": Video interface %i found\n",
+                      ifnum);
+       if (has_dvb)
+               printk(KERN_INFO DRIVER_NAME
+                      ": DVB interface %i found\n",
+                      ifnum);
+
+       /*
+        * Make sure we have 480 Mbps of bandwidth, otherwise things like
+        * video stream wouldn't likely work, since 12 Mbps is generally
+        * not enough even for most Digital TV streams.
+        */
+       if (udev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {
+               printk(DRIVER_NAME ": Device initialization failed.\n");
+               printk(DRIVER_NAME ": Device must be connected to a high-speed"
+                      " USB 2.0 port.\n");
+               retval = -ENODEV;
+               goto err_free;
+       }
+
+       snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr);
+       dev->devno = nr;
+       dev->model = id->driver_info;
+       dev->alt   = -1;
+       dev->is_audio_only = has_audio && !(has_video || has_dvb);
+       dev->has_alsa_audio = has_audio;
+       dev->audio_ifnum = ifnum;
+
+       /* Checks if audio is provided by some interface */
+       for (i = 0; i < udev->config->desc.bNumInterfaces; i++) {
+               struct usb_interface *uif = udev->config->interface[i];
+               if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
+                       dev->has_audio_class = 1;
+                       break;
+               }
+       }
+
+       dev->num_alt = interface->num_altsetting;
+
+       if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))
+               dev->model = card[nr];
+
+       /* save our data pointer in this interface device */
+       usb_set_intfdata(interface, dev);
+
+       /* allocate device struct */
+       mutex_init(&dev->lock);
+       mutex_lock(&dev->lock);
+       retval = em28xx_init_dev(dev, udev, interface, nr);
+       if (retval) {
+               goto unlock_and_free;
+       }
+
+       if (has_dvb) {
+               /* pre-allocate DVB isoc transfer buffers */
+               retval = em28xx_alloc_isoc(dev, EM28XX_DIGITAL_MODE,
+                                          EM28XX_DVB_MAX_PACKETS,
+                                          EM28XX_DVB_NUM_BUFS,
+                                          dev->dvb_max_pkt_size);
+               if (retval) {
+                       goto unlock_and_free;
+               }
+       }
+
+       request_modules(dev);
+
+       /* Should be the last thing to do, to avoid newer udev's to
+          open the device before fully initializing it
+        */
+       mutex_unlock(&dev->lock);
+
+       /*
+        * These extensions can be modules. If the modules are already
+        * loaded then we can initialise the device now, otherwise we
+        * will initialise it when the modules load instead.
+        */
+       em28xx_init_extension(dev);
+
+       return 0;
+
+unlock_and_free:
+       mutex_unlock(&dev->lock);
+
+err_free:
+       kfree(dev->alt_max_pkt_size);
+       kfree(dev);
+
+err:
+       clear_bit(nr, &em28xx_devused);
+
+err_no_slot:
+       usb_put_dev(udev);
+       return retval;
+}
+
+/*
+ * em28xx_usb_disconnect()
+ * called when the device gets disconnected
+ * video device will be unregistered on v4l2_close in case it is still open
+ */
+static void em28xx_usb_disconnect(struct usb_interface *interface)
+{
+       struct em28xx *dev;
+
+       dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+
+       if (!dev)
+               return;
+
+       if (dev->is_audio_only) {
+               mutex_lock(&dev->lock);
+               em28xx_close_extension(dev);
+               mutex_unlock(&dev->lock);
+               return;
+       }
+
+       em28xx_info("disconnecting %s\n", dev->vdev->name);
+
+       flush_request_modules(dev);
+
+       /* wait until all current v4l2 io is finished then deallocate
+          resources */
+       mutex_lock(&dev->lock);
+
+       v4l2_device_disconnect(&dev->v4l2_dev);
+
+       if (dev->users) {
+               em28xx_warn
+                   ("device %s is open! Deregistration and memory "
+                    "deallocation are deferred on close.\n",
+                    video_device_node_name(dev->vdev));
+
+               dev->state |= DEV_MISCONFIGURED;
+               em28xx_uninit_isoc(dev, dev->mode);
+               dev->state |= DEV_DISCONNECTED;
+       } else {
+               dev->state |= DEV_DISCONNECTED;
+               em28xx_release_resources(dev);
+       }
+
+       /* free DVB isoc buffers */
+       em28xx_uninit_isoc(dev, EM28XX_DIGITAL_MODE);
+
+       mutex_unlock(&dev->lock);
+
+       em28xx_close_extension(dev);
+
+       if (!dev->users) {
+               kfree(dev->alt_max_pkt_size);
+               kfree(dev);
+       }
+}
+
+static struct usb_driver em28xx_usb_driver = {
+       .name = "em28xx",
+       .probe = em28xx_usb_probe,
+       .disconnect = em28xx_usb_disconnect,
+       .id_table = em28xx_id_table,
+};
+
+module_usb_driver(em28xx_usb_driver);
diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c
new file mode 100644 (file)
index 0000000..bed07a6
--- /dev/null
@@ -0,0 +1,1260 @@
+/*
+   em28xx-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
+
+   Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
+                     Markus Rechberger <mrechberger@gmail.com>
+                     Mauro Carvalho Chehab <mchehab@infradead.org>
+                     Sascha Sommer <saschasommer@freenet.de>
+
+   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/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/vmalloc.h>
+#include <sound/ac97_codec.h>
+#include <media/v4l2-common.h>
+
+#include "em28xx.h"
+
+/* #define ENABLE_DEBUG_ISOC_FRAMES */
+
+static unsigned int core_debug;
+module_param(core_debug, int, 0644);
+MODULE_PARM_DESC(core_debug, "enable debug messages [core]");
+
+#define em28xx_coredbg(fmt, arg...) do {\
+       if (core_debug) \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); } while (0)
+
+static unsigned int reg_debug;
+module_param(reg_debug, int, 0644);
+MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]");
+
+#define em28xx_regdbg(fmt, arg...) do {\
+       if (reg_debug) \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); } while (0)
+
+static int alt;
+module_param(alt, int, 0644);
+MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
+
+static unsigned int disable_vbi;
+module_param(disable_vbi, int, 0644);
+MODULE_PARM_DESC(disable_vbi, "disable vbi support");
+
+/* FIXME */
+#define em28xx_isocdbg(fmt, arg...) do {\
+       if (core_debug) \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); } while (0)
+
+/*
+ * em28xx_read_reg_req()
+ * reads data from the usb device specifying bRequest
+ */
+int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
+                                  char *buf, int len)
+{
+       int ret;
+       int pipe = usb_rcvctrlpipe(dev->udev, 0);
+
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
+       if (len > URB_MAX_CTRL_SIZE)
+               return -EINVAL;
+
+       if (reg_debug) {
+               printk(KERN_DEBUG "(pipe 0x%08x): "
+                       "IN:  %02x %02x %02x %02x %02x %02x %02x %02x ",
+                       pipe,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       req, 0, 0,
+                       reg & 0xff, reg >> 8,
+                       len & 0xff, len >> 8);
+       }
+
+       mutex_lock(&dev->ctrl_urb_lock);
+       ret = usb_control_msg(dev->udev, pipe, req,
+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0x0000, reg, dev->urb_buf, len, HZ);
+       if (ret < 0) {
+               if (reg_debug)
+                       printk(" failed!\n");
+               mutex_unlock(&dev->ctrl_urb_lock);
+               return ret;
+       }
+
+       if (len)
+               memcpy(buf, dev->urb_buf, len);
+
+       mutex_unlock(&dev->ctrl_urb_lock);
+
+       if (reg_debug) {
+               int byte;
+
+               printk("<<<");
+               for (byte = 0; byte < len; byte++)
+                       printk(" %02x", (unsigned char)buf[byte]);
+               printk("\n");
+       }
+
+       return ret;
+}
+
+/*
+ * em28xx_read_reg_req()
+ * reads data from the usb device specifying bRequest
+ */
+int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg)
+{
+       int ret;
+       u8 val;
+
+       ret = em28xx_read_reg_req_len(dev, req, reg, &val, 1);
+       if (ret < 0)
+               return ret;
+
+       return val;
+}
+
+int em28xx_read_reg(struct em28xx *dev, u16 reg)
+{
+       return em28xx_read_reg_req(dev, USB_REQ_GET_STATUS, reg);
+}
+EXPORT_SYMBOL_GPL(em28xx_read_reg);
+
+/*
+ * em28xx_write_regs_req()
+ * sends data to the usb device, specifying bRequest
+ */
+int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
+                                int len)
+{
+       int ret;
+       int pipe = usb_sndctrlpipe(dev->udev, 0);
+
+       if (dev->state & DEV_DISCONNECTED)
+               return -ENODEV;
+
+       if ((len < 1) || (len > URB_MAX_CTRL_SIZE))
+               return -EINVAL;
+
+       if (reg_debug) {
+               int byte;
+
+               printk(KERN_DEBUG "(pipe 0x%08x): "
+                       "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>",
+                       pipe,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       req, 0, 0,
+                       reg & 0xff, reg >> 8,
+                       len & 0xff, len >> 8);
+
+               for (byte = 0; byte < len; byte++)
+                       printk(" %02x", (unsigned char)buf[byte]);
+               printk("\n");
+       }
+
+       mutex_lock(&dev->ctrl_urb_lock);
+       memcpy(dev->urb_buf, buf, len);
+       ret = usb_control_msg(dev->udev, pipe, req,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0x0000, reg, dev->urb_buf, len, HZ);
+       mutex_unlock(&dev->ctrl_urb_lock);
+
+       if (dev->wait_after_write)
+               msleep(dev->wait_after_write);
+
+       return ret;
+}
+
+int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len)
+{
+       int rc;
+
+       rc = em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len);
+
+       /* Stores GPO/GPIO values at the cache, if changed
+          Only write values should be stored, since input on a GPIO
+          register will return the input bits.
+          Not sure what happens on reading GPO register.
+        */
+       if (rc >= 0) {
+               if (reg == dev->reg_gpo_num)
+                       dev->reg_gpo = buf[0];
+               else if (reg == dev->reg_gpio_num)
+                       dev->reg_gpio = buf[0];
+       }
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(em28xx_write_regs);
+
+/* Write a single register */
+int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val)
+{
+       return em28xx_write_regs(dev, reg, &val, 1);
+}
+EXPORT_SYMBOL_GPL(em28xx_write_reg);
+
+/*
+ * em28xx_write_reg_bits()
+ * sets only some bits (specified by bitmask) of a register, by first reading
+ * the actual value
+ */
+int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
+                                u8 bitmask)
+{
+       int oldval;
+       u8 newval;
+
+       /* Uses cache for gpo/gpio registers */
+       if (reg == dev->reg_gpo_num)
+               oldval = dev->reg_gpo;
+       else if (reg == dev->reg_gpio_num)
+               oldval = dev->reg_gpio;
+       else
+               oldval = em28xx_read_reg(dev, reg);
+
+       if (oldval < 0)
+               return oldval;
+
+       newval = (((u8) oldval) & ~bitmask) | (val & bitmask);
+
+       return em28xx_write_regs(dev, reg, &newval, 1);
+}
+EXPORT_SYMBOL_GPL(em28xx_write_reg_bits);
+
+/*
+ * em28xx_is_ac97_ready()
+ * Checks if ac97 is ready
+ */
+static int em28xx_is_ac97_ready(struct em28xx *dev)
+{
+       int ret, i;
+
+       /* Wait up to 50 ms for AC97 command to complete */
+       for (i = 0; i < 10; i++, msleep(5)) {
+               ret = em28xx_read_reg(dev, EM28XX_R43_AC97BUSY);
+               if (ret < 0)
+                       return ret;
+
+               if (!(ret & 0x01))
+                       return 0;
+       }
+
+       em28xx_warn("AC97 command still being executed: not handled properly!\n");
+       return -EBUSY;
+}
+
+/*
+ * em28xx_read_ac97()
+ * write a 16 bit value to the specified AC97 address (LSB first!)
+ */
+int em28xx_read_ac97(struct em28xx *dev, u8 reg)
+{
+       int ret;
+       u8 addr = (reg & 0x7f) | 0x80;
+       u16 val;
+
+       ret = em28xx_is_ac97_ready(dev);
+       if (ret < 0)
+               return ret;
+
+       ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1);
+       if (ret < 0)
+               return ret;
+
+       ret = dev->em28xx_read_reg_req_len(dev, 0, EM28XX_R40_AC97LSB,
+                                          (u8 *)&val, sizeof(val));
+
+       if (ret < 0)
+               return ret;
+       return le16_to_cpu(val);
+}
+EXPORT_SYMBOL_GPL(em28xx_read_ac97);
+
+/*
+ * em28xx_write_ac97()
+ * write a 16 bit value to the specified AC97 address (LSB first!)
+ */
+int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val)
+{
+       int ret;
+       u8 addr = reg & 0x7f;
+       __le16 value;
+
+       value = cpu_to_le16(val);
+
+       ret = em28xx_is_ac97_ready(dev);
+       if (ret < 0)
+               return ret;
+
+       ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, (u8 *) &value, 2);
+       if (ret < 0)
+               return ret;
+
+       ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(em28xx_write_ac97);
+
+struct em28xx_vol_itable {
+       enum em28xx_amux mux;
+       u8               reg;
+};
+
+static struct em28xx_vol_itable inputs[] = {
+       { EM28XX_AMUX_VIDEO,    AC97_VIDEO      },
+       { EM28XX_AMUX_LINE_IN,  AC97_LINE       },
+       { EM28XX_AMUX_PHONE,    AC97_PHONE      },
+       { EM28XX_AMUX_MIC,      AC97_MIC        },
+       { EM28XX_AMUX_CD,       AC97_CD         },
+       { EM28XX_AMUX_AUX,      AC97_AUX        },
+       { EM28XX_AMUX_PCM_OUT,  AC97_PCM        },
+};
+
+static int set_ac97_input(struct em28xx *dev)
+{
+       int ret, i;
+       enum em28xx_amux amux = dev->ctl_ainput;
+
+       /* EM28XX_AMUX_VIDEO2 is a special case used to indicate that
+          em28xx should point to LINE IN, while AC97 should use VIDEO
+        */
+       if (amux == EM28XX_AMUX_VIDEO2)
+               amux = EM28XX_AMUX_VIDEO;
+
+       /* Mute all entres but the one that were selected */
+       for (i = 0; i < ARRAY_SIZE(inputs); i++) {
+               if (amux == inputs[i].mux)
+                       ret = em28xx_write_ac97(dev, inputs[i].reg, 0x0808);
+               else
+                       ret = em28xx_write_ac97(dev, inputs[i].reg, 0x8000);
+
+               if (ret < 0)
+                       em28xx_warn("couldn't setup AC97 register %d\n",
+                                    inputs[i].reg);
+       }
+       return 0;
+}
+
+static int em28xx_set_audio_source(struct em28xx *dev)
+{
+       int ret;
+       u8 input;
+
+       if (dev->board.is_em2800) {
+               if (dev->ctl_ainput == EM28XX_AMUX_VIDEO)
+                       input = EM2800_AUDIO_SRC_TUNER;
+               else
+                       input = EM2800_AUDIO_SRC_LINE;
+
+               ret = em28xx_write_regs(dev, EM2800_R08_AUDIOSRC, &input, 1);
+               if (ret < 0)
+                       return ret;
+       }
+
+       if (dev->board.has_msp34xx)
+               input = EM28XX_AUDIO_SRC_TUNER;
+       else {
+               switch (dev->ctl_ainput) {
+               case EM28XX_AMUX_VIDEO:
+                       input = EM28XX_AUDIO_SRC_TUNER;
+                       break;
+               default:
+                       input = EM28XX_AUDIO_SRC_LINE;
+                       break;
+               }
+       }
+
+       if (dev->board.mute_gpio && dev->mute)
+               em28xx_gpio_set(dev, dev->board.mute_gpio);
+       else
+               em28xx_gpio_set(dev, INPUT(dev->ctl_input)->gpio);
+
+       ret = em28xx_write_reg_bits(dev, EM28XX_R0E_AUDIOSRC, input, 0xc0);
+       if (ret < 0)
+               return ret;
+       msleep(5);
+
+       switch (dev->audio_mode.ac97) {
+       case EM28XX_NO_AC97:
+               break;
+       default:
+               ret = set_ac97_input(dev);
+       }
+
+       return ret;
+}
+
+struct em28xx_vol_otable {
+       enum em28xx_aout mux;
+       u8               reg;
+};
+
+static const struct em28xx_vol_otable outputs[] = {
+       { EM28XX_AOUT_MASTER, AC97_MASTER               },
+       { EM28XX_AOUT_LINE,   AC97_HEADPHONE            },
+       { EM28XX_AOUT_MONO,   AC97_MASTER_MONO          },
+       { EM28XX_AOUT_LFE,    AC97_CENTER_LFE_MASTER    },
+       { EM28XX_AOUT_SURR,   AC97_SURROUND_MASTER      },
+};
+
+int em28xx_audio_analog_set(struct em28xx *dev)
+{
+       int ret, i;
+       u8 xclk;
+
+       if (!dev->audio_mode.has_audio)
+               return 0;
+
+       /* It is assumed that all devices use master volume for output.
+          It would be possible to use also line output.
+        */
+       if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
+               /* Mute all outputs */
+               for (i = 0; i < ARRAY_SIZE(outputs); i++) {
+                       ret = em28xx_write_ac97(dev, outputs[i].reg, 0x8000);
+                       if (ret < 0)
+                               em28xx_warn("couldn't setup AC97 register %d\n",
+                                    outputs[i].reg);
+               }
+       }
+
+       xclk = dev->board.xclk & 0x7f;
+       if (!dev->mute)
+               xclk |= EM28XX_XCLK_AUDIO_UNMUTE;
+
+       ret = em28xx_write_reg(dev, EM28XX_R0F_XCLK, xclk);
+       if (ret < 0)
+               return ret;
+       msleep(10);
+
+       /* Selects the proper audio input */
+       ret = em28xx_set_audio_source(dev);
+
+       /* Sets volume */
+       if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
+               int vol;
+
+               em28xx_write_ac97(dev, AC97_POWERDOWN, 0x4200);
+               em28xx_write_ac97(dev, AC97_EXTENDED_STATUS, 0x0031);
+               em28xx_write_ac97(dev, AC97_PCM_LR_ADC_RATE, 0xbb80);
+
+               /* LSB: left channel - both channels with the same level */
+               vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8);
+
+               /* Mute device, if needed */
+               if (dev->mute)
+                       vol |= 0x8000;
+
+               /* Sets volume */
+               for (i = 0; i < ARRAY_SIZE(outputs); i++) {
+                       if (dev->ctl_aoutput & outputs[i].mux)
+                               ret = em28xx_write_ac97(dev, outputs[i].reg,
+                                                       vol);
+                       if (ret < 0)
+                               em28xx_warn("couldn't setup AC97 register %d\n",
+                                    outputs[i].reg);
+               }
+
+               if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) {
+                       int sel = ac97_return_record_select(dev->ctl_aoutput);
+
+                       /* Use the same input for both left and right
+                          channels */
+                       sel |= (sel << 8);
+
+                       em28xx_write_ac97(dev, AC97_REC_SEL, sel);
+               }
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(em28xx_audio_analog_set);
+
+int em28xx_audio_setup(struct em28xx *dev)
+{
+       int vid1, vid2, feat, cfg;
+       u32 vid;
+
+       if (dev->chip_id == CHIP_ID_EM2870 || dev->chip_id == CHIP_ID_EM2874
+               || dev->chip_id == CHIP_ID_EM28174) {
+               /* Digital only device - don't load any alsa module */
+               dev->audio_mode.has_audio = false;
+               dev->has_audio_class = false;
+               dev->has_alsa_audio = false;
+               return 0;
+       }
+
+       dev->audio_mode.has_audio = true;
+
+       /* See how this device is configured */
+       cfg = em28xx_read_reg(dev, EM28XX_R00_CHIPCFG);
+       em28xx_info("Config register raw data: 0x%02x\n", cfg);
+       if (cfg < 0) {
+               /* Register read error?  */
+               cfg = EM28XX_CHIPCFG_AC97; /* Be conservative */
+       } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == 0x00) {
+               /* The device doesn't have vendor audio at all */
+               dev->has_alsa_audio = false;
+               dev->audio_mode.has_audio = false;
+               return 0;
+       } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
+                  EM28XX_CHIPCFG_I2S_3_SAMPRATES) {
+               em28xx_info("I2S Audio (3 sample rates)\n");
+               dev->audio_mode.i2s_3rates = 1;
+       } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
+                  EM28XX_CHIPCFG_I2S_5_SAMPRATES) {
+               em28xx_info("I2S Audio (5 sample rates)\n");
+               dev->audio_mode.i2s_5rates = 1;
+       }
+
+       if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) != EM28XX_CHIPCFG_AC97) {
+               /* Skip the code that does AC97 vendor detection */
+               dev->audio_mode.ac97 = EM28XX_NO_AC97;
+               goto init_audio;
+       }
+
+       dev->audio_mode.ac97 = EM28XX_AC97_OTHER;
+
+       vid1 = em28xx_read_ac97(dev, AC97_VENDOR_ID1);
+       if (vid1 < 0) {
+               /*
+                * Device likely doesn't support AC97
+                * Note: (some) em2800 devices without eeprom reports 0x91 on
+                *       CHIPCFG register, even not having an AC97 chip
+                */
+               em28xx_warn("AC97 chip type couldn't be determined\n");
+               dev->audio_mode.ac97 = EM28XX_NO_AC97;
+               dev->has_alsa_audio = false;
+               dev->audio_mode.has_audio = false;
+               goto init_audio;
+       }
+
+       vid2 = em28xx_read_ac97(dev, AC97_VENDOR_ID2);
+       if (vid2 < 0)
+               goto init_audio;
+
+       vid = vid1 << 16 | vid2;
+
+       dev->audio_mode.ac97_vendor_id = vid;
+       em28xx_warn("AC97 vendor ID = 0x%08x\n", vid);
+
+       feat = em28xx_read_ac97(dev, AC97_RESET);
+       if (feat < 0)
+               goto init_audio;
+
+       dev->audio_mode.ac97_feat = feat;
+       em28xx_warn("AC97 features = 0x%04x\n", feat);
+
+       /* Try to identify what audio processor we have */
+       if (((vid == 0xffffffff) || (vid == 0x83847650)) && (feat == 0x6a90))
+               dev->audio_mode.ac97 = EM28XX_AC97_EM202;
+       else if ((vid >> 8) == 0x838476)
+               dev->audio_mode.ac97 = EM28XX_AC97_SIGMATEL;
+
+init_audio:
+       /* Reports detected AC97 processor */
+       switch (dev->audio_mode.ac97) {
+       case EM28XX_NO_AC97:
+               em28xx_info("No AC97 audio processor\n");
+               break;
+       case EM28XX_AC97_EM202:
+               em28xx_info("Empia 202 AC97 audio processor detected\n");
+               break;
+       case EM28XX_AC97_SIGMATEL:
+               em28xx_info("Sigmatel audio processor detected(stac 97%02x)\n",
+                           dev->audio_mode.ac97_vendor_id & 0xff);
+               break;
+       case EM28XX_AC97_OTHER:
+               em28xx_warn("Unknown AC97 audio processor detected!\n");
+               break;
+       default:
+               break;
+       }
+
+       return em28xx_audio_analog_set(dev);
+}
+EXPORT_SYMBOL_GPL(em28xx_audio_setup);
+
+int em28xx_colorlevels_set_default(struct em28xx *dev)
+{
+       em28xx_write_reg(dev, EM28XX_R20_YGAIN, 0x10);  /* contrast */
+       em28xx_write_reg(dev, EM28XX_R21_YOFFSET, 0x00);        /* brightness */
+       em28xx_write_reg(dev, EM28XX_R22_UVGAIN, 0x10); /* saturation */
+       em28xx_write_reg(dev, EM28XX_R23_UOFFSET, 0x00);
+       em28xx_write_reg(dev, EM28XX_R24_VOFFSET, 0x00);
+       em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, 0x00);
+
+       em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
+       em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
+       em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
+       em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
+       em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
+       em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
+       return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
+}
+
+int em28xx_capture_start(struct em28xx *dev, int start)
+{
+       int rc;
+
+       if (dev->chip_id == CHIP_ID_EM2874 ||
+           dev->chip_id == CHIP_ID_EM2884 ||
+           dev->chip_id == CHIP_ID_EM28174) {
+               /* The Transport Stream Enable Register moved in em2874 */
+               if (!start) {
+                       rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE,
+                                                  0x00,
+                                                  EM2874_TS1_CAPTURE_ENABLE);
+                       return rc;
+               }
+
+               /* Enable Transport Stream */
+               rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE,
+                                          EM2874_TS1_CAPTURE_ENABLE,
+                                          EM2874_TS1_CAPTURE_ENABLE);
+               return rc;
+       }
+
+
+       /* FIXME: which is the best order? */
+       /* video registers are sampled by VREF */
+       rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP,
+                                  start ? 0x10 : 0x00, 0x10);
+       if (rc < 0)
+               return rc;
+
+       if (!start) {
+               /* disable video capture */
+               rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x27);
+               return rc;
+       }
+
+       if (dev->board.is_webcam)
+               rc = em28xx_write_reg(dev, 0x13, 0x0c);
+
+       /* enable video capture */
+       rc = em28xx_write_reg(dev, 0x48, 0x00);
+
+       if (dev->mode == EM28XX_ANALOG_MODE)
+               rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67);
+       else
+               rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37);
+
+       msleep(6);
+
+       return rc;
+}
+
+int em28xx_vbi_supported(struct em28xx *dev)
+{
+       /* Modprobe option to manually disable */
+       if (disable_vbi == 1)
+               return 0;
+
+       if (dev->chip_id == CHIP_ID_EM2860 ||
+           dev->chip_id == CHIP_ID_EM2883)
+               return 1;
+
+       /* Version of em28xx that does not support VBI */
+       return 0;
+}
+
+int em28xx_set_outfmt(struct em28xx *dev)
+{
+       int ret;
+       u8 vinctrl;
+
+       ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT,
+                               dev->format->reg | 0x20, 0xff);
+       if (ret < 0)
+                       return ret;
+
+       ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
+       if (ret < 0)
+               return ret;
+
+       vinctrl = dev->vinctl;
+       if (em28xx_vbi_supported(dev) == 1) {
+               vinctrl |= EM28XX_VINCTRL_VBI_RAW;
+               em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
+               em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4);
+               em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height);
+               if (dev->norm & V4L2_STD_525_60) {
+                       /* NTSC */
+                       em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
+               } else if (dev->norm & V4L2_STD_625_50) {
+                       /* PAL */
+                       em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
+               }
+       }
+
+       return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
+}
+
+static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
+                                 u8 ymin, u8 ymax)
+{
+       em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
+                       xmin, ymin, xmax, ymax);
+
+       em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
+       em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
+       em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
+       return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
+}
+
+static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
+                                  u16 width, u16 height)
+{
+       u8 cwidth = width;
+       u8 cheight = height;
+       u8 overflow = (height >> 7 & 0x02) | (width >> 8 & 0x01);
+
+       em28xx_coredbg("em28xx Area Set: (%d,%d)\n",
+                       (width | (overflow & 2) << 7),
+                       (height | (overflow & 1) << 8));
+
+       em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
+       em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
+       em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
+       em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
+       return em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
+}
+
+static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
+{
+       u8 mode;
+       /* the em2800 scaler only supports scaling down to 50% */
+
+       if (dev->board.is_em2800) {
+               mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
+       } else {
+               u8 buf[2];
+
+               buf[0] = h;
+               buf[1] = h >> 8;
+               em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
+
+               buf[0] = v;
+               buf[1] = v >> 8;
+               em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
+               /* it seems that both H and V scalers must be active
+                  to work correctly */
+               mode = (h || v) ? 0x30 : 0x00;
+       }
+       return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30);
+}
+
+/* FIXME: this only function read values from dev */
+int em28xx_resolution_set(struct em28xx *dev)
+{
+       int width, height;
+       width = norm_maxw(dev);
+       height = norm_maxh(dev);
+
+       /* Properly setup VBI */
+       dev->vbi_width = 720;
+       if (dev->norm & V4L2_STD_525_60)
+               dev->vbi_height = 12;
+       else
+               dev->vbi_height = 18;
+
+       em28xx_set_outfmt(dev);
+
+       em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
+
+       /* If we don't set the start position to 2 in VBI mode, we end up
+          with line 20/21 being YUYV encoded instead of being in 8-bit
+          greyscale.  The core of the issue is that line 21 (and line 23 for
+          PAL WSS) are inside of active video region, and as a result they
+          get the pixelformatting associated with that area.  So by cropping
+          it out, we end up with the same format as the rest of the VBI
+          region */
+       if (em28xx_vbi_supported(dev) == 1)
+               em28xx_capture_area_set(dev, 0, 2, width >> 2, height >> 2);
+       else
+               em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2);
+
+       return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
+}
+
+int em28xx_set_alternate(struct em28xx *dev)
+{
+       int errCode, prev_alt = dev->alt;
+       int i;
+       unsigned int min_pkt_size = dev->width * 2 + 4;
+
+       /*
+        * alt = 0 is used only for control messages, so, only values
+        * greater than 0 can be used for streaming.
+        */
+       if (alt && alt < dev->num_alt) {
+               em28xx_coredbg("alternate forced to %d\n", dev->alt);
+               dev->alt = alt;
+               goto set_alt;
+       }
+
+       /* When image size is bigger than a certain value,
+          the frame size should be increased, otherwise, only
+          green screen will be received.
+        */
+       if (dev->width * 2 * dev->height > 720 * 240 * 2)
+               min_pkt_size *= 2;
+
+       for (i = 0; i < dev->num_alt; i++) {
+               /* stop when the selected alt setting offers enough bandwidth */
+               if (dev->alt_max_pkt_size[i] >= min_pkt_size) {
+                       dev->alt = i;
+                       break;
+               /* otherwise make sure that we end up with the maximum bandwidth
+                  because the min_pkt_size equation might be wrong...
+               */
+               } else if (dev->alt_max_pkt_size[i] >
+                          dev->alt_max_pkt_size[dev->alt])
+                       dev->alt = i;
+       }
+
+set_alt:
+       if (dev->alt != prev_alt) {
+               em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
+                               min_pkt_size, dev->alt);
+               dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
+               em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
+                              dev->alt, dev->max_pkt_size);
+               errCode = usb_set_interface(dev->udev, 0, dev->alt);
+               if (errCode < 0) {
+                       em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
+                                       dev->alt, errCode);
+                       return errCode;
+               }
+       }
+       return 0;
+}
+
+int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
+{
+       int rc = 0;
+
+       if (!gpio)
+               return rc;
+
+       if (dev->mode != EM28XX_SUSPEND) {
+               em28xx_write_reg(dev, 0x48, 0x00);
+               if (dev->mode == EM28XX_ANALOG_MODE)
+                       em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67);
+               else
+                       em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37);
+               msleep(6);
+       }
+
+       /* Send GPIO reset sequences specified at board entry */
+       while (gpio->sleep >= 0) {
+               if (gpio->reg >= 0) {
+                       rc = em28xx_write_reg_bits(dev,
+                                                  gpio->reg,
+                                                  gpio->val,
+                                                  gpio->mask);
+                       if (rc < 0)
+                               return rc;
+               }
+               if (gpio->sleep > 0)
+                       msleep(gpio->sleep);
+
+               gpio++;
+       }
+       return rc;
+}
+EXPORT_SYMBOL_GPL(em28xx_gpio_set);
+
+int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode)
+{
+       if (dev->mode == set_mode)
+               return 0;
+
+       if (set_mode == EM28XX_SUSPEND) {
+               dev->mode = set_mode;
+
+               /* FIXME: add suspend support for ac97 */
+
+               return em28xx_gpio_set(dev, dev->board.suspend_gpio);
+       }
+
+       dev->mode = set_mode;
+
+       if (dev->mode == EM28XX_DIGITAL_MODE)
+               return em28xx_gpio_set(dev, dev->board.dvb_gpio);
+       else
+               return em28xx_gpio_set(dev, INPUT(dev->ctl_input)->gpio);
+}
+EXPORT_SYMBOL_GPL(em28xx_set_mode);
+
+/* ------------------------------------------------------------------
+       URB control
+   ------------------------------------------------------------------*/
+
+/*
+ * IRQ callback, called by URB callback
+ */
+static void em28xx_irq_callback(struct urb *urb)
+{
+       struct em28xx *dev = urb->context;
+       int i;
+
+       switch (urb->status) {
+       case 0:             /* success */
+       case -ETIMEDOUT:    /* NAK */
+               break;
+       case -ECONNRESET:   /* kill */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+       default:            /* error */
+               em28xx_isocdbg("urb completition error %d.\n", urb->status);
+               break;
+       }
+
+       /* Copy data from URB */
+       spin_lock(&dev->slock);
+       dev->isoc_ctl.isoc_copy(dev, urb);
+       spin_unlock(&dev->slock);
+
+       /* Reset urb buffers */
+       for (i = 0; i < urb->number_of_packets; i++) {
+               urb->iso_frame_desc[i].status = 0;
+               urb->iso_frame_desc[i].actual_length = 0;
+       }
+       urb->status = 0;
+
+       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (urb->status) {
+               em28xx_isocdbg("urb resubmit failed (error=%i)\n",
+                              urb->status);
+       }
+}
+
+/*
+ * Stop and Deallocate URBs
+ */
+void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode)
+{
+       struct urb *urb;
+       struct em28xx_usb_isoc_bufs *isoc_bufs;
+       int i;
+
+       em28xx_isocdbg("em28xx: called em28xx_uninit_isoc in mode %d\n", mode);
+
+       if (mode == EM28XX_DIGITAL_MODE)
+               isoc_bufs = &dev->isoc_ctl.digital_bufs;
+       else
+               isoc_bufs = &dev->isoc_ctl.analog_bufs;
+
+       for (i = 0; i < isoc_bufs->num_bufs; i++) {
+               urb = isoc_bufs->urb[i];
+               if (urb) {
+                       if (!irqs_disabled())
+                               usb_kill_urb(urb);
+                       else
+                               usb_unlink_urb(urb);
+
+                       if (isoc_bufs->transfer_buffer[i]) {
+                               usb_free_coherent(dev->udev,
+                                       urb->transfer_buffer_length,
+                                       isoc_bufs->transfer_buffer[i],
+                                       urb->transfer_dma);
+                       }
+                       usb_free_urb(urb);
+                       isoc_bufs->urb[i] = NULL;
+               }
+               isoc_bufs->transfer_buffer[i] = NULL;
+       }
+
+       kfree(isoc_bufs->urb);
+       kfree(isoc_bufs->transfer_buffer);
+
+       isoc_bufs->urb = NULL;
+       isoc_bufs->transfer_buffer = NULL;
+       isoc_bufs->num_bufs = 0;
+
+       em28xx_capture_start(dev, 0);
+}
+EXPORT_SYMBOL_GPL(em28xx_uninit_isoc);
+
+/*
+ * Stop URBs
+ */
+void em28xx_stop_urbs(struct em28xx *dev)
+{
+       int i;
+       struct urb *urb;
+       struct em28xx_usb_isoc_bufs *isoc_bufs = &dev->isoc_ctl.digital_bufs;
+
+       em28xx_isocdbg("em28xx: called em28xx_stop_urbs\n");
+
+       for (i = 0; i < isoc_bufs->num_bufs; i++) {
+               urb = isoc_bufs->urb[i];
+               if (urb) {
+                       if (!irqs_disabled())
+                               usb_kill_urb(urb);
+                       else
+                               usb_unlink_urb(urb);
+               }
+       }
+
+       em28xx_capture_start(dev, 0);
+}
+EXPORT_SYMBOL_GPL(em28xx_stop_urbs);
+
+/*
+ * Allocate URBs
+ */
+int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode,
+                     int max_packets, int num_bufs, int max_pkt_size)
+{
+       struct em28xx_usb_isoc_bufs *isoc_bufs;
+       int i;
+       int sb_size, pipe;
+       struct urb *urb;
+       int j, k;
+
+       em28xx_isocdbg("em28xx: called em28xx_alloc_isoc in mode %d\n", mode);
+
+       if (mode == EM28XX_DIGITAL_MODE)
+               isoc_bufs = &dev->isoc_ctl.digital_bufs;
+       else
+               isoc_bufs = &dev->isoc_ctl.analog_bufs;
+
+       /* De-allocates all pending stuff */
+       em28xx_uninit_isoc(dev, mode);
+
+       isoc_bufs->num_bufs = num_bufs;
+
+       isoc_bufs->urb = kzalloc(sizeof(void *)*num_bufs,  GFP_KERNEL);
+       if (!isoc_bufs->urb) {
+               em28xx_errdev("cannot alloc memory for usb buffers\n");
+               return -ENOMEM;
+       }
+
+       isoc_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
+                                            GFP_KERNEL);
+       if (!isoc_bufs->transfer_buffer) {
+               em28xx_errdev("cannot allocate memory for usb transfer\n");
+               kfree(isoc_bufs->urb);
+               return -ENOMEM;
+       }
+
+       isoc_bufs->max_pkt_size = max_pkt_size;
+       isoc_bufs->num_packets = max_packets;
+       dev->isoc_ctl.vid_buf = NULL;
+       dev->isoc_ctl.vbi_buf = NULL;
+
+       sb_size = isoc_bufs->num_packets * isoc_bufs->max_pkt_size;
+
+       /* allocate urbs and transfer buffers */
+       for (i = 0; i < isoc_bufs->num_bufs; i++) {
+               urb = usb_alloc_urb(isoc_bufs->num_packets, GFP_KERNEL);
+               if (!urb) {
+                       em28xx_err("cannot alloc isoc_ctl.urb %i\n", i);
+                       em28xx_uninit_isoc(dev, mode);
+                       return -ENOMEM;
+               }
+               isoc_bufs->urb[i] = urb;
+
+               isoc_bufs->transfer_buffer[i] = usb_alloc_coherent(dev->udev,
+                       sb_size, GFP_KERNEL, &urb->transfer_dma);
+               if (!isoc_bufs->transfer_buffer[i]) {
+                       em28xx_err("unable to allocate %i bytes for transfer"
+                                       " buffer %i%s\n",
+                                       sb_size, i,
+                                       in_interrupt() ? " while in int" : "");
+                       em28xx_uninit_isoc(dev, mode);
+                       return -ENOMEM;
+               }
+               memset(isoc_bufs->transfer_buffer[i], 0, sb_size);
+
+               /* FIXME: this is a hack - should be
+                       'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK'
+                       should also be using 'desc.bInterval'
+                */
+               pipe = usb_rcvisocpipe(dev->udev,
+                                      mode == EM28XX_ANALOG_MODE ?
+                                      EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL);
+
+               usb_fill_int_urb(urb, dev->udev, pipe,
+                                isoc_bufs->transfer_buffer[i], sb_size,
+                                em28xx_irq_callback, dev, 1);
+
+               urb->number_of_packets = isoc_bufs->num_packets;
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+
+               k = 0;
+               for (j = 0; j < isoc_bufs->num_packets; j++) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length =
+                                               isoc_bufs->max_pkt_size;
+                       k += isoc_bufs->max_pkt_size;
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(em28xx_alloc_isoc);
+
+/*
+ * Allocate URBs and start IRQ
+ */
+int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode,
+                    int max_packets, int num_bufs, int max_pkt_size,
+                    int (*isoc_copy) (struct em28xx *dev, struct urb *urb))
+{
+       struct em28xx_dmaqueue *dma_q = &dev->vidq;
+       struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
+       struct em28xx_usb_isoc_bufs *isoc_bufs;
+       int i;
+       int rc;
+       int alloc;
+
+       em28xx_isocdbg("em28xx: called em28xx_init_isoc in mode %d\n", mode);
+
+       dev->isoc_ctl.isoc_copy = isoc_copy;
+
+       if (mode == EM28XX_DIGITAL_MODE) {
+               isoc_bufs = &dev->isoc_ctl.digital_bufs;
+               /* no need to free/alloc isoc buffers in digital mode */
+               alloc = 0;
+       } else {
+               isoc_bufs = &dev->isoc_ctl.analog_bufs;
+               alloc = 1;
+       }
+
+       if (alloc) {
+               rc = em28xx_alloc_isoc(dev, mode, max_packets,
+                                      num_bufs, max_pkt_size);
+               if (rc)
+                       return rc;
+       }
+
+       init_waitqueue_head(&dma_q->wq);
+       init_waitqueue_head(&vbi_dma_q->wq);
+
+       em28xx_capture_start(dev, 1);
+
+       /* submit urbs and enables IRQ */
+       for (i = 0; i < isoc_bufs->num_bufs; i++) {
+               rc = usb_submit_urb(isoc_bufs->urb[i], GFP_ATOMIC);
+               if (rc) {
+                       em28xx_err("submit of urb %i failed (error=%i)\n", i,
+                                  rc);
+                       em28xx_uninit_isoc(dev, mode);
+                       return rc;
+               }
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(em28xx_init_isoc);
+
+/*
+ * em28xx_wake_i2c()
+ * configure i2c attached devices
+ */
+void em28xx_wake_i2c(struct em28xx *dev)
+{
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core,  reset, 0);
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
+                       INPUT(dev->ctl_input)->vmux, 0, 0);
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
+}
+
+/*
+ * Device control list
+ */
+
+static LIST_HEAD(em28xx_devlist);
+static DEFINE_MUTEX(em28xx_devlist_mutex);
+
+/*
+ * Extension interface
+ */
+
+static LIST_HEAD(em28xx_extension_devlist);
+
+int em28xx_register_extension(struct em28xx_ops *ops)
+{
+       struct em28xx *dev = NULL;
+
+       mutex_lock(&em28xx_devlist_mutex);
+       list_add_tail(&ops->next, &em28xx_extension_devlist);
+       list_for_each_entry(dev, &em28xx_devlist, devlist) {
+               ops->init(dev);
+       }
+       mutex_unlock(&em28xx_devlist_mutex);
+       printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
+       return 0;
+}
+EXPORT_SYMBOL(em28xx_register_extension);
+
+void em28xx_unregister_extension(struct em28xx_ops *ops)
+{
+       struct em28xx *dev = NULL;
+
+       mutex_lock(&em28xx_devlist_mutex);
+       list_for_each_entry(dev, &em28xx_devlist, devlist) {
+               ops->fini(dev);
+       }
+       list_del(&ops->next);
+       mutex_unlock(&em28xx_devlist_mutex);
+       printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
+}
+EXPORT_SYMBOL(em28xx_unregister_extension);
+
+void em28xx_init_extension(struct em28xx *dev)
+{
+       const struct em28xx_ops *ops = NULL;
+
+       mutex_lock(&em28xx_devlist_mutex);
+       list_add_tail(&dev->devlist, &em28xx_devlist);
+       list_for_each_entry(ops, &em28xx_extension_devlist, next) {
+               if (ops->init)
+                       ops->init(dev);
+       }
+       mutex_unlock(&em28xx_devlist_mutex);
+}
+
+void em28xx_close_extension(struct em28xx *dev)
+{
+       const struct em28xx_ops *ops = NULL;
+
+       mutex_lock(&em28xx_devlist_mutex);
+       list_for_each_entry(ops, &em28xx_extension_devlist, next) {
+               if (ops->fini)
+                       ops->fini(dev);
+       }
+       list_del(&dev->devlist);
+       mutex_unlock(&em28xx_devlist_mutex);
+}
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
new file mode 100644 (file)
index 0000000..a16531f
--- /dev/null
@@ -0,0 +1,1197 @@
+/*
+ DVB device driver for em28xx
+
+ (c) 2008-2011 Mauro Carvalho Chehab <mchehab@infradead.org>
+
+ (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
+       - Fixes for the driver to properly work with HVR-950
+       - Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick
+       - Fixes for the driver to properly work with AMD ATI TV Wonder HD 600
+
+ (c) 2008 Aidan Thornton <makosoft@googlemail.com>
+
+ Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by:
+       (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
+       (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+
+ 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include "em28xx.h"
+#include <media/v4l2-common.h>
+#include <media/videobuf-vmalloc.h>
+#include <media/tuner.h>
+#include "tuner-simple.h"
+
+#include "lgdt330x.h"
+#include "lgdt3305.h"
+#include "zl10353.h"
+#include "s5h1409.h"
+#include "mt352.h"
+#include "mt352_priv.h" /* FIXME */
+#include "tda1002x.h"
+#include "tda18271.h"
+#include "s921.h"
+#include "drxd.h"
+#include "cxd2820r.h"
+#include "tda18271c2dd.h"
+#include "drxk.h"
+#include "tda10071.h"
+#include "a8293.h"
+#include "qt1010.h"
+
+MODULE_DESCRIPTION("driver for em28xx based DVB cards");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_LICENSE("GPL");
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define dprintk(level, fmt, arg...) do {                       \
+if (debug >= level)                                            \
+       printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \
+} while (0)
+
+struct em28xx_dvb {
+       struct dvb_frontend        *fe[2];
+
+       /* feed count management */
+       struct mutex               lock;
+       int                        nfeeds;
+
+       /* general boilerplate stuff */
+       struct dvb_adapter         adapter;
+       struct dvb_demux           demux;
+       struct dmxdev              dmxdev;
+       struct dmx_frontend        fe_hw;
+       struct dmx_frontend        fe_mem;
+       struct dvb_net             net;
+
+       /* Due to DRX-K - probably need changes */
+       int (*gate_ctrl)(struct dvb_frontend *, int);
+       struct semaphore      pll_mutex;
+       bool                    dont_attach_fe1;
+};
+
+
+static inline void print_err_status(struct em28xx *dev,
+                                    int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+       if (packet < 0) {
+               dprintk(1, "URB status %d [%s].\n", status, errmsg);
+       } else {
+               dprintk(1, "URB packet %d, status %d [%s].\n",
+                       packet, status, errmsg);
+       }
+}
+
+static inline int em28xx_dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
+{
+       int i;
+
+       if (!dev)
+               return 0;
+
+       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+               return 0;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               if (urb->status == -ENOENT)
+                       return 0;
+       }
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               int status = urb->iso_frame_desc[i].status;
+
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       if (urb->iso_frame_desc[i].status != -EPROTO)
+                               continue;
+               }
+
+               dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer +
+                                urb->iso_frame_desc[i].offset,
+                                urb->iso_frame_desc[i].actual_length);
+       }
+
+       return 0;
+}
+
+static int em28xx_start_streaming(struct em28xx_dvb *dvb)
+{
+       int rc;
+       struct em28xx *dev = dvb->adapter.priv;
+       int max_dvb_packet_size;
+
+       usb_set_interface(dev->udev, 0, dev->dvb_alt);
+       rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
+       if (rc < 0)
+               return rc;
+
+       max_dvb_packet_size = dev->dvb_max_pkt_size;
+       if (max_dvb_packet_size < 0)
+               return max_dvb_packet_size;
+       dprintk(1, "Using %d buffers each with %d x %d bytes\n",
+               EM28XX_DVB_NUM_BUFS,
+               EM28XX_DVB_MAX_PACKETS,
+               max_dvb_packet_size);
+
+       return em28xx_init_isoc(dev, EM28XX_DIGITAL_MODE,
+                               EM28XX_DVB_MAX_PACKETS, EM28XX_DVB_NUM_BUFS,
+                               max_dvb_packet_size, em28xx_dvb_isoc_copy);
+}
+
+static int em28xx_stop_streaming(struct em28xx_dvb *dvb)
+{
+       struct em28xx *dev = dvb->adapter.priv;
+
+       em28xx_stop_urbs(dev);
+
+       em28xx_set_mode(dev, EM28XX_SUSPEND);
+
+       return 0;
+}
+
+static int em28xx_start_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux  = feed->demux;
+       struct em28xx_dvb *dvb = demux->priv;
+       int rc, ret;
+
+       if (!demux->dmx.frontend)
+               return -EINVAL;
+
+       mutex_lock(&dvb->lock);
+       dvb->nfeeds++;
+       rc = dvb->nfeeds;
+
+       if (dvb->nfeeds == 1) {
+               ret = em28xx_start_streaming(dvb);
+               if (ret < 0)
+                       rc = ret;
+       }
+
+       mutex_unlock(&dvb->lock);
+       return rc;
+}
+
+static int em28xx_stop_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux  = feed->demux;
+       struct em28xx_dvb *dvb = demux->priv;
+       int err = 0;
+
+       mutex_lock(&dvb->lock);
+       dvb->nfeeds--;
+
+       if (0 == dvb->nfeeds)
+               err = em28xx_stop_streaming(dvb);
+
+       mutex_unlock(&dvb->lock);
+       return err;
+}
+
+
+
+/* ------------------------------------------------------------------ */
+static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+       struct em28xx *dev = fe->dvb->priv;
+
+       if (acquire)
+               return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
+       else
+               return em28xx_set_mode(dev, EM28XX_SUSPEND);
+}
+
+/* ------------------------------------------------------------------ */
+
+static struct lgdt330x_config em2880_lgdt3303_dev = {
+       .demod_address = 0x0e,
+       .demod_chip = LGDT3303,
+};
+
+static struct lgdt3305_config em2870_lgdt3304_dev = {
+       .i2c_addr           = 0x0e,
+       .demod_chip         = LGDT3304,
+       .spectral_inversion = 1,
+       .deny_i2c_rptr      = 1,
+       .mpeg_mode          = LGDT3305_MPEG_PARALLEL,
+       .tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
+       .tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
+       .vsb_if_khz         = 3250,
+       .qam_if_khz         = 4000,
+};
+
+static struct s921_config sharp_isdbt = {
+       .demod_address = 0x30 >> 1
+};
+
+static struct zl10353_config em28xx_zl10353_with_xc3028 = {
+       .demod_address = (0x1e >> 1),
+       .no_tuner = 1,
+       .parallel_ts = 1,
+       .if2 = 45600,
+};
+
+static struct s5h1409_config em28xx_s5h1409_with_xc3028 = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_PARALLEL_OUTPUT,
+       .gpio          = S5H1409_GPIO_OFF,
+       .inversion     = S5H1409_INVERSION_OFF,
+       .status_mode   = S5H1409_DEMODLOCKING,
+       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
+};
+
+static struct tda18271_std_map kworld_a340_std_map = {
+       .atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 0,
+                     .if_lvl = 1, .rfagc_top = 0x37, },
+       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 1,
+                     .if_lvl = 1, .rfagc_top = 0x37, },
+};
+
+static struct tda18271_config kworld_a340_config = {
+       .std_map           = &kworld_a340_std_map,
+};
+
+static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {
+       .demod_address = (0x1e >> 1),
+       .no_tuner = 1,
+       .disable_i2c_gate_ctrl = 1,
+       .parallel_ts = 1,
+       .if2 = 45600,
+};
+
+static struct drxd_config em28xx_drxd = {
+       .demod_address = 0x70,
+       .demod_revision = 0xa2,
+       .pll_type = DRXD_PLL_NONE,
+       .clock = 12000,
+       .insert_rs_byte = 1,
+       .IF = 42800000,
+       .disable_i2c_gate_ctrl = 1,
+};
+
+static struct drxk_config terratec_h5_drxk = {
+       .adr = 0x29,
+       .single_master = 1,
+       .no_i2c_bridge = 1,
+       .microcode_name = "dvb-usb-terratec-h5-drxk.fw",
+       .qam_demod_parameter_count = 2,
+};
+
+static struct drxk_config hauppauge_930c_drxk = {
+       .adr = 0x29,
+       .single_master = 1,
+       .no_i2c_bridge = 1,
+       .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw",
+       .chunk_size = 56,
+       .qam_demod_parameter_count = 2,
+};
+
+struct drxk_config terratec_htc_stick_drxk = {
+       .adr = 0x29,
+       .single_master = 1,
+       .no_i2c_bridge = 1,
+       .microcode_name = "dvb-usb-terratec-htc-stick-drxk.fw",
+       .chunk_size = 54,
+       .qam_demod_parameter_count = 2,
+       /* Required for the antenna_gpio to disable LNA. */
+       .antenna_dvbt = true,
+       /* The windows driver uses the same. This will disable LNA. */
+       .antenna_gpio = 0x6,
+};
+
+static struct drxk_config maxmedia_ub425_tc_drxk = {
+       .adr = 0x29,
+       .single_master = 1,
+       .no_i2c_bridge = 1,
+};
+
+static struct drxk_config pctv_520e_drxk = {
+       .adr = 0x29,
+       .single_master = 1,
+       .microcode_name = "dvb-demod-drxk-pctv.fw",
+       .qam_demod_parameter_count = 2,
+       .chunk_size = 58,
+       .antenna_dvbt = true, /* disable LNA */
+       .antenna_gpio = (1 << 2), /* disable LNA */
+};
+
+static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct em28xx_dvb *dvb = fe->sec_priv;
+       int status;
+
+       if (!dvb)
+               return -EINVAL;
+
+       if (enable) {
+               down(&dvb->pll_mutex);
+               status = dvb->gate_ctrl(fe, 1);
+       } else {
+               status = dvb->gate_ctrl(fe, 0);
+               up(&dvb->pll_mutex);
+       }
+       return status;
+}
+
+static void hauppauge_hvr930c_init(struct em28xx *dev)
+{
+       int i;
+
+       struct em28xx_reg_seq hauppauge_hvr930c_init[] = {
+               {EM2874_R80_GPIO,       0xff,   0xff,   0x65},
+               {EM2874_R80_GPIO,       0xfb,   0xff,   0x32},
+               {EM2874_R80_GPIO,       0xff,   0xff,   0xb8},
+               { -1,                   -1,     -1,     -1},
+       };
+       struct em28xx_reg_seq hauppauge_hvr930c_end[] = {
+               {EM2874_R80_GPIO,       0xef,   0xff,   0x01},
+               {EM2874_R80_GPIO,       0xaf,   0xff,   0x65},
+               {EM2874_R80_GPIO,       0xef,   0xff,   0x76},
+               {EM2874_R80_GPIO,       0xef,   0xff,   0x01},
+               {EM2874_R80_GPIO,       0xcf,   0xff,   0x0b},
+               {EM2874_R80_GPIO,       0xef,   0xff,   0x40},
+
+               {EM2874_R80_GPIO,       0xcf,   0xff,   0x65},
+               {EM2874_R80_GPIO,       0xef,   0xff,   0x65},
+               {EM2874_R80_GPIO,       0xcf,   0xff,   0x0b},
+               {EM2874_R80_GPIO,       0xef,   0xff,   0x65},
+
+               { -1,                   -1,     -1,     -1},
+       };
+
+       struct {
+               unsigned char r[4];
+               int len;
+       } regs[] = {
+               {{ 0x06, 0x02, 0x00, 0x31 }, 4},
+               {{ 0x01, 0x02 }, 2},
+               {{ 0x01, 0x02, 0x00, 0xc6 }, 4},
+               {{ 0x01, 0x00 }, 2},
+               {{ 0x01, 0x00, 0xff, 0xaf }, 4},
+               {{ 0x01, 0x00, 0x03, 0xa0 }, 4},
+               {{ 0x01, 0x00 }, 2},
+               {{ 0x01, 0x00, 0x73, 0xaf }, 4},
+               {{ 0x04, 0x00 }, 2},
+               {{ 0x00, 0x04 }, 2},
+               {{ 0x00, 0x04, 0x00, 0x0a }, 4},
+               {{ 0x04, 0x14 }, 2},
+               {{ 0x04, 0x14, 0x00, 0x00 }, 4},
+       };
+
+       em28xx_gpio_set(dev, hauppauge_hvr930c_init);
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
+       msleep(10);
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
+       msleep(10);
+
+       dev->i2c_client.addr = 0x82 >> 1;
+
+       for (i = 0; i < ARRAY_SIZE(regs); i++)
+               i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+       em28xx_gpio_set(dev, hauppauge_hvr930c_end);
+
+       msleep(100);
+
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
+       msleep(30);
+
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
+       msleep(10);
+
+}
+
+static void terratec_h5_init(struct em28xx *dev)
+{
+       int i;
+       struct em28xx_reg_seq terratec_h5_init[] = {
+               {EM28XX_R08_GPIO,       0xff,   0xff,   10},
+               {EM2874_R80_GPIO,       0xf6,   0xff,   100},
+               {EM2874_R80_GPIO,       0xf2,   0xff,   50},
+               {EM2874_R80_GPIO,       0xf6,   0xff,   100},
+               { -1,                   -1,     -1,     -1},
+       };
+       struct em28xx_reg_seq terratec_h5_end[] = {
+               {EM2874_R80_GPIO,       0xe6,   0xff,   100},
+               {EM2874_R80_GPIO,       0xa6,   0xff,   50},
+               {EM2874_R80_GPIO,       0xe6,   0xff,   100},
+               { -1,                   -1,     -1,     -1},
+       };
+       struct {
+               unsigned char r[4];
+               int len;
+       } regs[] = {
+               {{ 0x06, 0x02, 0x00, 0x31 }, 4},
+               {{ 0x01, 0x02 }, 2},
+               {{ 0x01, 0x02, 0x00, 0xc6 }, 4},
+               {{ 0x01, 0x00 }, 2},
+               {{ 0x01, 0x00, 0xff, 0xaf }, 4},
+               {{ 0x01, 0x00, 0x03, 0xa0 }, 4},
+               {{ 0x01, 0x00 }, 2},
+               {{ 0x01, 0x00, 0x73, 0xaf }, 4},
+               {{ 0x04, 0x00 }, 2},
+               {{ 0x00, 0x04 }, 2},
+               {{ 0x00, 0x04, 0x00, 0x0a }, 4},
+               {{ 0x04, 0x14 }, 2},
+               {{ 0x04, 0x14, 0x00, 0x00 }, 4},
+       };
+
+       em28xx_gpio_set(dev, terratec_h5_init);
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
+       msleep(10);
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
+       msleep(10);
+
+       dev->i2c_client.addr = 0x82 >> 1;
+
+       for (i = 0; i < ARRAY_SIZE(regs); i++)
+               i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+       em28xx_gpio_set(dev, terratec_h5_end);
+};
+
+static void terratec_htc_stick_init(struct em28xx *dev)
+{
+       int i;
+
+       /*
+        * GPIO configuration:
+        * 0xff: unknown (does not affect DVB-T).
+        * 0xf6: DRX-K (demodulator).
+        * 0xe6: unknown (does not affect DVB-T).
+        * 0xb6: unknown (does not affect DVB-T).
+        */
+       struct em28xx_reg_seq terratec_htc_stick_init[] = {
+               {EM28XX_R08_GPIO,       0xff,   0xff,   10},
+               {EM2874_R80_GPIO,       0xf6,   0xff,   100},
+               {EM2874_R80_GPIO,       0xe6,   0xff,   50},
+               {EM2874_R80_GPIO,       0xf6,   0xff,   100},
+               { -1,                   -1,     -1,     -1},
+       };
+       struct em28xx_reg_seq terratec_htc_stick_end[] = {
+               {EM2874_R80_GPIO,       0xb6,   0xff,   100},
+               {EM2874_R80_GPIO,       0xf6,   0xff,   50},
+               { -1,                   -1,     -1,     -1},
+       };
+
+       /* Init the analog decoder? */
+       struct {
+               unsigned char r[4];
+               int len;
+       } regs[] = {
+               {{ 0x06, 0x02, 0x00, 0x31 }, 4},
+               {{ 0x01, 0x02 }, 2},
+               {{ 0x01, 0x02, 0x00, 0xc6 }, 4},
+               {{ 0x01, 0x00 }, 2},
+               {{ 0x01, 0x00, 0xff, 0xaf }, 4},
+       };
+
+       em28xx_gpio_set(dev, terratec_htc_stick_init);
+
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
+       msleep(10);
+       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
+       msleep(10);
+
+       dev->i2c_client.addr = 0x82 >> 1;
+
+       for (i = 0; i < ARRAY_SIZE(regs); i++)
+               i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+
+       em28xx_gpio_set(dev, terratec_htc_stick_end);
+};
+
+static void pctv_520e_init(struct em28xx *dev)
+{
+       /*
+        * Init AVF4910B analog decoder. Looks like I2C traffic to
+        * digital demodulator and tuner are routed via AVF4910B.
+        */
+       int i;
+       struct {
+               unsigned char r[4];
+               int len;
+       } regs[] = {
+               {{ 0x06, 0x02, 0x00, 0x31 }, 4},
+               {{ 0x01, 0x02 }, 2},
+               {{ 0x01, 0x02, 0x00, 0xc6 }, 4},
+               {{ 0x01, 0x00 }, 2},
+               {{ 0x01, 0x00, 0xff, 0xaf }, 4},
+               {{ 0x01, 0x00, 0x03, 0xa0 }, 4},
+               {{ 0x01, 0x00 }, 2},
+               {{ 0x01, 0x00, 0x73, 0xaf }, 4},
+       };
+
+       dev->i2c_client.addr = 0x82 >> 1; /* 0x41 */
+
+       for (i = 0; i < ARRAY_SIZE(regs); i++)
+               i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
+};
+
+static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe)
+{
+       /* Values extracted from a USB trace of the Terratec Windows driver */
+       static u8 clock_config[]   = { CLOCK_CTL,  0x38, 0x2c };
+       static u8 reset[]          = { RESET,      0x80 };
+       static u8 adc_ctl_1_cfg[]  = { ADC_CTL_1,  0x40 };
+       static u8 agc_cfg[]        = { AGC_TARGET, 0x28, 0xa0 };
+       static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 };
+       static u8 rs_err_cfg[]     = { RS_ERR_PER_1, 0x00, 0x4d };
+       static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
+       static u8 trl_nom_cfg[]    = { TRL_NOMINAL_RATE_1, 0x64, 0x00 };
+       static u8 tps_given_cfg[]  = { TPS_GIVEN_1, 0x40, 0x80, 0x50 };
+       static u8 tuner_go[]       = { TUNER_GO, 0x01};
+
+       mt352_write(fe, clock_config,   sizeof(clock_config));
+       udelay(200);
+       mt352_write(fe, reset,          sizeof(reset));
+       mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
+       mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
+       mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg));
+       mt352_write(fe, rs_err_cfg,     sizeof(rs_err_cfg));
+       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
+       mt352_write(fe, trl_nom_cfg,    sizeof(trl_nom_cfg));
+       mt352_write(fe, tps_given_cfg,  sizeof(tps_given_cfg));
+       mt352_write(fe, tuner_go,       sizeof(tuner_go));
+       return 0;
+}
+
+static struct mt352_config terratec_xs_mt352_cfg = {
+       .demod_address = (0x1e >> 1),
+       .no_tuner = 1,
+       .if2 = 45600,
+       .demod_init = em28xx_mt352_terratec_xs_init,
+};
+
+static struct tda10023_config em28xx_tda10023_config = {
+       .demod_address = 0x0c,
+       .invert = 1,
+};
+
+static struct cxd2820r_config em28xx_cxd2820r_config = {
+       .i2c_address = (0xd8 >> 1),
+       .ts_mode = CXD2820R_TS_SERIAL,
+
+       /* enable LNA for DVB-T, DVB-T2 and DVB-C */
+       .gpio_dvbt[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L,
+       .gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L,
+       .gpio_dvbc[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L,
+};
+
+static struct tda18271_config em28xx_cxd2820r_tda18271_config = {
+       .output_opt = TDA18271_OUTPUT_LT_OFF,
+       .gate = TDA18271_GATE_DIGITAL,
+};
+
+static const struct tda10071_config em28xx_tda10071_config = {
+       .i2c_address = 0x55, /* (0xaa >> 1) */
+       .i2c_wr_max = 64,
+       .ts_mode = TDA10071_TS_SERIAL,
+       .spec_inv = 0,
+       .xtal = 40444000, /* 40.444 MHz */
+       .pll_multiplier = 20,
+};
+
+static const struct a8293_config em28xx_a8293_config = {
+       .i2c_addr = 0x08, /* (0x10 >> 1) */
+};
+
+static struct zl10353_config em28xx_zl10353_no_i2c_gate_dev = {
+       .demod_address = (0x1e >> 1),
+       .disable_i2c_gate_ctrl = 1,
+       .no_tuner = 1,
+       .parallel_ts = 1,
+};
+static struct qt1010_config em28xx_qt1010_config = {
+       .i2c_address = 0x62
+
+};
+
+/* ------------------------------------------------------------------ */
+
+static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
+{
+       struct dvb_frontend *fe;
+       struct xc2028_config cfg;
+
+       memset(&cfg, 0, sizeof(cfg));
+       cfg.i2c_adap  = &dev->i2c_adap;
+       cfg.i2c_addr  = addr;
+
+       if (!dev->dvb->fe[0]) {
+               em28xx_errdev("/2: dvb frontend not attached. "
+                               "Can't attach xc3028\n");
+               return -EINVAL;
+       }
+
+       fe = dvb_attach(xc2028_attach, dev->dvb->fe[0], &cfg);
+       if (!fe) {
+               em28xx_errdev("/2: xc3028 attach failed\n");
+               dvb_frontend_detach(dev->dvb->fe[0]);
+               dev->dvb->fe[0] = NULL;
+               return -EINVAL;
+       }
+
+       em28xx_info("%s/2: xc3028 attached\n", dev->name);
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------ */
+
+static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module,
+                              struct em28xx *dev, struct device *device)
+{
+       int result;
+
+       mutex_init(&dvb->lock);
+
+       /* register adapter */
+       result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
+                                     adapter_nr);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_adapter;
+       }
+
+       /* Ensure all frontends negotiate bus access */
+       dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
+       if (dvb->fe[1])
+               dvb->fe[1]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
+
+       dvb->adapter.priv = dev;
+
+       /* register frontend */
+       result = dvb_register_frontend(&dvb->adapter, dvb->fe[0]);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_frontend0;
+       }
+
+       /* register 2nd frontend */
+       if (dvb->fe[1]) {
+               result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]);
+               if (result < 0) {
+                       printk(KERN_WARNING "%s: 2nd dvb_register_frontend failed (errno = %d)\n",
+                               dev->name, result);
+                       goto fail_frontend1;
+               }
+       }
+
+       /* register demux stuff */
+       dvb->demux.dmx.capabilities =
+               DMX_TS_FILTERING | DMX_SECTION_FILTERING |
+               DMX_MEMORY_BASED_FILTERING;
+       dvb->demux.priv       = dvb;
+       dvb->demux.filternum  = 256;
+       dvb->demux.feednum    = 256;
+       dvb->demux.start_feed = em28xx_start_feed;
+       dvb->demux.stop_feed  = em28xx_stop_feed;
+
+       result = dvb_dmx_init(&dvb->demux);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_dmx;
+       }
+
+       dvb->dmxdev.filternum    = 256;
+       dvb->dmxdev.demux        = &dvb->demux.dmx;
+       dvb->dmxdev.capabilities = 0;
+       result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_dmxdev;
+       }
+
+       dvb->fe_hw.source = DMX_FRONTEND_0;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
+                      dev->name, result);
+               goto fail_fe_hw;
+       }
+
+       dvb->fe_mem.source = DMX_MEMORY_FE;
+       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
+                      dev->name, result);
+               goto fail_fe_mem;
+       }
+
+       result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       if (result < 0) {
+               printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n",
+                      dev->name, result);
+               goto fail_fe_conn;
+       }
+
+       /* register network adapter */
+       dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
+       return 0;
+
+fail_fe_conn:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+fail_fe_mem:
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+fail_fe_hw:
+       dvb_dmxdev_release(&dvb->dmxdev);
+fail_dmxdev:
+       dvb_dmx_release(&dvb->demux);
+fail_dmx:
+       if (dvb->fe[1])
+               dvb_unregister_frontend(dvb->fe[1]);
+       dvb_unregister_frontend(dvb->fe[0]);
+fail_frontend1:
+       if (dvb->fe[1])
+               dvb_frontend_detach(dvb->fe[1]);
+fail_frontend0:
+       dvb_frontend_detach(dvb->fe[0]);
+       dvb_unregister_adapter(&dvb->adapter);
+fail_adapter:
+       return result;
+}
+
+static void em28xx_unregister_dvb(struct em28xx_dvb *dvb)
+{
+       dvb_net_release(&dvb->net);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
+       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
+       dvb_dmxdev_release(&dvb->dmxdev);
+       dvb_dmx_release(&dvb->demux);
+       if (dvb->fe[1])
+               dvb_unregister_frontend(dvb->fe[1]);
+       dvb_unregister_frontend(dvb->fe[0]);
+       if (dvb->fe[1] && !dvb->dont_attach_fe1)
+               dvb_frontend_detach(dvb->fe[1]);
+       dvb_frontend_detach(dvb->fe[0]);
+       dvb_unregister_adapter(&dvb->adapter);
+}
+
+static int em28xx_dvb_init(struct em28xx *dev)
+{
+       int result = 0, mfe_shared = 0;
+       struct em28xx_dvb *dvb;
+
+       if (!dev->board.has_dvb) {
+               /* This device does not support the extension */
+               printk(KERN_INFO "em28xx_dvb: This device does not support the extension\n");
+               return 0;
+       }
+
+       dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL);
+
+       if (dvb == NULL) {
+               em28xx_info("em28xx_dvb: memory allocation failed\n");
+               return -ENOMEM;
+       }
+       dev->dvb = dvb;
+       dvb->fe[0] = dvb->fe[1] = NULL;
+
+       mutex_lock(&dev->lock);
+       em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
+       /* init frontend */
+       switch (dev->model) {
+       case EM2874_BOARD_LEADERSHIP_ISDBT:
+               dvb->fe[0] = dvb_attach(s921_attach,
+                               &sharp_isdbt, &dev->i2c_adap);
+
+               if (!dvb->fe[0]) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+
+               break;
+       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
+       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
+       case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
+       case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
+               dvb->fe[0] = dvb_attach(lgdt330x_attach,
+                                          &em2880_lgdt3303_dev,
+                                          &dev->i2c_adap);
+               if (em28xx_attach_xc3028(0x61, dev) < 0) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       case EM2880_BOARD_KWORLD_DVB_310U:
+               dvb->fe[0] = dvb_attach(zl10353_attach,
+                                          &em28xx_zl10353_with_xc3028,
+                                          &dev->i2c_adap);
+               if (em28xx_attach_xc3028(0x61, dev) < 0) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
+       case EM2882_BOARD_TERRATEC_HYBRID_XS:
+       case EM2880_BOARD_EMPIRE_DUAL_TV:
+               dvb->fe[0] = dvb_attach(zl10353_attach,
+                                          &em28xx_zl10353_xc3028_no_i2c_gate,
+                                          &dev->i2c_adap);
+               if (em28xx_attach_xc3028(0x61, dev) < 0) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       case EM2880_BOARD_TERRATEC_HYBRID_XS:
+       case EM2880_BOARD_TERRATEC_HYBRID_XS_FR:
+       case EM2881_BOARD_PINNACLE_HYBRID_PRO:
+       case EM2882_BOARD_DIKOM_DK300:
+       case EM2882_BOARD_KWORLD_VS_DVBT:
+               dvb->fe[0] = dvb_attach(zl10353_attach,
+                                          &em28xx_zl10353_xc3028_no_i2c_gate,
+                                          &dev->i2c_adap);
+               if (dvb->fe[0] == NULL) {
+                       /* This board could have either a zl10353 or a mt352.
+                          If the chip id isn't for zl10353, try mt352 */
+                       dvb->fe[0] = dvb_attach(mt352_attach,
+                                                  &terratec_xs_mt352_cfg,
+                                                  &dev->i2c_adap);
+               }
+
+               if (em28xx_attach_xc3028(0x61, dev) < 0) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       case EM2870_BOARD_KWORLD_355U:
+               dvb->fe[0] = dvb_attach(zl10353_attach,
+                                          &em28xx_zl10353_no_i2c_gate_dev,
+                                          &dev->i2c_adap);
+               if (dvb->fe[0] != NULL)
+                       dvb_attach(qt1010_attach, dvb->fe[0],
+                                  &dev->i2c_adap, &em28xx_qt1010_config);
+               break;
+       case EM2883_BOARD_KWORLD_HYBRID_330U:
+       case EM2882_BOARD_EVGA_INDTUBE:
+               dvb->fe[0] = dvb_attach(s5h1409_attach,
+                                          &em28xx_s5h1409_with_xc3028,
+                                          &dev->i2c_adap);
+               if (em28xx_attach_xc3028(0x61, dev) < 0) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       case EM2882_BOARD_KWORLD_ATSC_315U:
+               dvb->fe[0] = dvb_attach(lgdt330x_attach,
+                                          &em2880_lgdt3303_dev,
+                                          &dev->i2c_adap);
+               if (dvb->fe[0] != NULL) {
+                       if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
+                               &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) {
+                               result = -EINVAL;
+                               goto out_free;
+                       }
+               }
+               break;
+       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
+       case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
+               dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL,
+                                          &dev->i2c_adap, &dev->udev->dev);
+               if (em28xx_attach_xc3028(0x61, dev) < 0) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       case EM2870_BOARD_REDDO_DVB_C_USB_BOX:
+               /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */
+               dvb->fe[0] = dvb_attach(tda10023_attach,
+                       &em28xx_tda10023_config,
+                       &dev->i2c_adap, 0x48);
+               if (dvb->fe[0]) {
+                       if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
+                               &dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) {
+                               result = -EINVAL;
+                               goto out_free;
+                       }
+               }
+               break;
+       case EM2870_BOARD_KWORLD_A340:
+               dvb->fe[0] = dvb_attach(lgdt3305_attach,
+                                          &em2870_lgdt3304_dev,
+                                          &dev->i2c_adap);
+               if (dvb->fe[0] != NULL)
+                       dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
+                                  &dev->i2c_adap, &kworld_a340_config);
+               break;
+       case EM28174_BOARD_PCTV_290E:
+               dvb->fe[0] = dvb_attach(cxd2820r_attach,
+                                       &em28xx_cxd2820r_config,
+                                       &dev->i2c_adap);
+               if (dvb->fe[0]) {
+                       /* FE 0 attach tuner */
+                       if (!dvb_attach(tda18271_attach,
+                                       dvb->fe[0],
+                                       0x60,
+                                       &dev->i2c_adap,
+                                       &em28xx_cxd2820r_tda18271_config)) {
+
+                               dvb_frontend_detach(dvb->fe[0]);
+                               result = -EINVAL;
+                               goto out_free;
+                       }
+               }
+               break;
+       case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C:
+       {
+               struct xc5000_config cfg;
+               hauppauge_hvr930c_init(dev);
+
+               dvb->fe[0] = dvb_attach(drxk_attach,
+                                       &hauppauge_930c_drxk, &dev->i2c_adap);
+               if (!dvb->fe[0]) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               /* FIXME: do we need a pll semaphore? */
+               dvb->fe[0]->sec_priv = dvb;
+               sema_init(&dvb->pll_mutex, 1);
+               dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
+               dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+
+               /* Attach xc5000 */
+               memset(&cfg, 0, sizeof(cfg));
+               cfg.i2c_address  = 0x61;
+               cfg.if_khz = 4000;
+
+               if (dvb->fe[0]->ops.i2c_gate_ctrl)
+                       dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
+               if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap,
+                               &cfg)) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               if (dvb->fe[0]->ops.i2c_gate_ctrl)
+                       dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
+
+               break;
+       }
+       case EM2884_BOARD_TERRATEC_H5:
+               terratec_h5_init(dev);
+
+               dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap);
+               if (!dvb->fe[0]) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               /* FIXME: do we need a pll semaphore? */
+               dvb->fe[0]->sec_priv = dvb;
+               sema_init(&dvb->pll_mutex, 1);
+               dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
+               dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+
+               /* Attach tda18271 to DVB-C frontend */
+               if (dvb->fe[0]->ops.i2c_gate_ctrl)
+                       dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
+               if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], &dev->i2c_adap, 0x60)) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               if (dvb->fe[0]->ops.i2c_gate_ctrl)
+                       dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
+
+               break;
+       case EM28174_BOARD_PCTV_460E:
+               /* attach demod */
+               dvb->fe[0] = dvb_attach(tda10071_attach,
+                       &em28xx_tda10071_config, &dev->i2c_adap);
+
+               /* attach SEC */
+               if (dvb->fe[0])
+                       dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap,
+                               &em28xx_a8293_config);
+               break;
+       case EM2874_BOARD_MAXMEDIA_UB425_TC:
+               /* attach demodulator */
+               dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk,
+                               &dev->i2c_adap);
+
+               if (dvb->fe[0]) {
+                       /* disable I2C-gate */
+                       dvb->fe[0]->ops.i2c_gate_ctrl = NULL;
+
+                       /* attach tuner */
+                       if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0],
+                                       &dev->i2c_adap, 0x60)) {
+                               dvb_frontend_detach(dvb->fe[0]);
+                               result = -EINVAL;
+                               goto out_free;
+                       }
+               }
+
+               /* TODO: we need drx-3913k firmware in order to support DVB-T */
+               em28xx_info("MaxMedia UB425-TC: only DVB-C supported by that " \
+                               "driver version\n");
+
+               break;
+       case EM2884_BOARD_PCTV_510E:
+       case EM2884_BOARD_PCTV_520E:
+               pctv_520e_init(dev);
+
+               /* attach demodulator */
+               dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk,
+                               &dev->i2c_adap);
+
+               if (dvb->fe[0]) {
+                       /* attach tuner */
+                       if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
+                                       &dev->i2c_adap,
+                                       &em28xx_cxd2820r_tda18271_config)) {
+                               dvb_frontend_detach(dvb->fe[0]);
+                               result = -EINVAL;
+                               goto out_free;
+                       }
+               }
+               break;
+       case EM2884_BOARD_CINERGY_HTC_STICK:
+               terratec_htc_stick_init(dev);
+
+               /* attach demodulator */
+               dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk,
+                                       &dev->i2c_adap);
+               if (!dvb->fe[0]) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+
+               /* Attach the demodulator. */
+               if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
+                               &dev->i2c_adap,
+                               &em28xx_cxd2820r_tda18271_config)) {
+                       result = -EINVAL;
+                       goto out_free;
+               }
+               break;
+       default:
+               em28xx_errdev("/2: The frontend of your DVB/ATSC card"
+                               " isn't supported yet\n");
+               break;
+       }
+       if (NULL == dvb->fe[0]) {
+               em28xx_errdev("/2: frontend initialization failed\n");
+               result = -EINVAL;
+               goto out_free;
+       }
+       /* define general-purpose callback pointer */
+       dvb->fe[0]->callback = em28xx_tuner_callback;
+       if (dvb->fe[1])
+               dvb->fe[1]->callback = em28xx_tuner_callback;
+
+       /* register everything */
+       result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
+
+       if (result < 0)
+               goto out_free;
+
+       /* MFE lock */
+       dvb->adapter.mfe_shared = mfe_shared;
+
+       em28xx_info("Successfully loaded em28xx-dvb\n");
+ret:
+       em28xx_set_mode(dev, EM28XX_SUSPEND);
+       mutex_unlock(&dev->lock);
+       return result;
+
+out_free:
+       kfree(dvb);
+       dev->dvb = NULL;
+       goto ret;
+}
+
+static inline void prevent_sleep(struct dvb_frontend_ops *ops)
+{
+       ops->set_voltage = NULL;
+       ops->sleep = NULL;
+       ops->tuner_ops.sleep = NULL;
+}
+
+static int em28xx_dvb_fini(struct em28xx *dev)
+{
+       if (!dev->board.has_dvb) {
+               /* This device does not support the extension */
+               return 0;
+       }
+
+       if (dev->dvb) {
+               struct em28xx_dvb *dvb = dev->dvb;
+
+               if (dev->state & DEV_DISCONNECTED) {
+                       /* We cannot tell the device to sleep
+                        * once it has been unplugged. */
+                       if (dvb->fe[0])
+                               prevent_sleep(&dvb->fe[0]->ops);
+                       if (dvb->fe[1])
+                               prevent_sleep(&dvb->fe[1]->ops);
+               }
+
+               em28xx_unregister_dvb(dvb);
+               kfree(dvb);
+               dev->dvb = NULL;
+       }
+
+       return 0;
+}
+
+static struct em28xx_ops dvb_ops = {
+       .id   = EM28XX_DVB,
+       .name = "Em28xx dvb Extension",
+       .init = em28xx_dvb_init,
+       .fini = em28xx_dvb_fini,
+};
+
+static int __init em28xx_dvb_register(void)
+{
+       return em28xx_register_extension(&dvb_ops);
+}
+
+static void __exit em28xx_dvb_unregister(void)
+{
+       em28xx_unregister_extension(&dvb_ops);
+}
+
+module_init(em28xx_dvb_register);
+module_exit(em28xx_dvb_unregister);
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c
new file mode 100644 (file)
index 0000000..1683bd9
--- /dev/null
@@ -0,0 +1,568 @@
+/*
+   em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
+
+   Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
+                     Markus Rechberger <mrechberger@gmail.com>
+                     Mauro Carvalho Chehab <mchehab@infradead.org>
+                     Sascha Sommer <saschasommer@freenet.de>
+
+   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/module.h>
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+
+#include "em28xx.h"
+#include "tuner-xc2028.h"
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+
+/* ----------------------------------------------------------- */
+
+static unsigned int i2c_scan;
+module_param(i2c_scan, int, 0444);
+MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+#define dprintk2(lvl, fmt, args...)                    \
+do {                                                   \
+       if (i2c_debug >= lvl) {                         \
+               printk(KERN_DEBUG "%s at %s: " fmt,     \
+                      dev->name, __func__ , ##args);   \
+      }                                                \
+} while (0)
+
+/*
+ * em2800_i2c_send_max4()
+ * send up to 4 bytes to the i2c device
+ */
+static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr,
+                               char *buf, int len)
+{
+       int ret;
+       int write_timeout;
+       unsigned char b2[6];
+       BUG_ON(len < 1 || len > 4);
+       b2[5] = 0x80 + len - 1;
+       b2[4] = addr;
+       b2[3] = buf[0];
+       if (len > 1)
+               b2[2] = buf[1];
+       if (len > 2)
+               b2[1] = buf[2];
+       if (len > 3)
+               b2[0] = buf[3];
+
+       ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
+       if (ret != 2 + len) {
+               em28xx_warn("writing to i2c device failed (error=%i)\n", ret);
+               return -EIO;
+       }
+       for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
+            write_timeout -= 5) {
+               ret = dev->em28xx_read_reg(dev, 0x05);
+               if (ret == 0x80 + len - 1)
+                       return len;
+               msleep(5);
+       }
+       em28xx_warn("i2c write timed out\n");
+       return -EIO;
+}
+
+/*
+ * em2800_i2c_send_bytes()
+ */
+static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf,
+                                short len)
+{
+       char *bufPtr = buf;
+       int ret;
+       int wrcount = 0;
+       int count;
+       int maxLen = 4;
+       struct em28xx *dev = (struct em28xx *)data;
+       while (len > 0) {
+               count = (len > maxLen) ? maxLen : len;
+               ret = em2800_i2c_send_max4(dev, addr, bufPtr, count);
+               if (ret > 0) {
+                       len -= count;
+                       bufPtr += count;
+                       wrcount += count;
+               } else
+                       return (ret < 0) ? ret : -EFAULT;
+       }
+       return wrcount;
+}
+
+/*
+ * em2800_i2c_check_for_device()
+ * check if there is a i2c_device at the supplied address
+ */
+static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
+{
+       char msg;
+       int ret;
+       int write_timeout;
+       msg = addr;
+       ret = dev->em28xx_write_regs(dev, 0x04, &msg, 1);
+       if (ret < 0) {
+               em28xx_warn("setting i2c device address failed (error=%i)\n",
+                           ret);
+               return ret;
+       }
+       msg = 0x84;
+       ret = dev->em28xx_write_regs(dev, 0x05, &msg, 1);
+       if (ret < 0) {
+               em28xx_warn("preparing i2c read failed (error=%i)\n", ret);
+               return ret;
+       }
+       for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
+            write_timeout -= 5) {
+               unsigned reg = dev->em28xx_read_reg(dev, 0x5);
+
+               if (reg == 0x94)
+                       return -ENODEV;
+               else if (reg == 0x84)
+                       return 0;
+               msleep(5);
+       }
+       return -ENODEV;
+}
+
+/*
+ * em2800_i2c_recv_bytes()
+ * read from the i2c device
+ */
+static int em2800_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
+                                char *buf, int len)
+{
+       int ret;
+       /* check for the device and set i2c read address */
+       ret = em2800_i2c_check_for_device(dev, addr);
+       if (ret) {
+               em28xx_warn
+                   ("preparing read at i2c address 0x%x failed (error=%i)\n",
+                    addr, ret);
+               return ret;
+       }
+       ret = dev->em28xx_read_reg_req_len(dev, 0x0, 0x3, buf, len);
+       if (ret < 0) {
+               em28xx_warn("reading from i2c device at 0x%x failed (error=%i)",
+                           addr, ret);
+               return ret;
+       }
+       return ret;
+}
+
+/*
+ * em28xx_i2c_send_bytes()
+ */
+static int em28xx_i2c_send_bytes(void *data, unsigned char addr, char *buf,
+                                short len, int stop)
+{
+       int wrcount = 0;
+       struct em28xx *dev = (struct em28xx *)data;
+       int write_timeout, ret;
+
+       wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
+
+       /* Seems to be required after a write */
+       for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
+            write_timeout -= 5) {
+               ret = dev->em28xx_read_reg(dev, 0x05);
+               if (!ret)
+                       break;
+               msleep(5);
+       }
+
+       return wrcount;
+}
+
+/*
+ * em28xx_i2c_recv_bytes()
+ * read a byte from the i2c device
+ */
+static int em28xx_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
+                                char *buf, int len)
+{
+       int ret;
+       ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
+       if (ret < 0) {
+               em28xx_warn("reading i2c device failed (error=%i)\n", ret);
+               return ret;
+       }
+       if (dev->em28xx_read_reg(dev, 0x5) != 0)
+               return -ENODEV;
+       return ret;
+}
+
+/*
+ * em28xx_i2c_check_for_device()
+ * check if there is a i2c_device at the supplied address
+ */
+static int em28xx_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
+{
+       int ret;
+
+       ret = dev->em28xx_read_reg_req(dev, 2, addr);
+       if (ret < 0) {
+               em28xx_warn("reading from i2c device failed (error=%i)\n", ret);
+               return ret;
+       }
+       if (dev->em28xx_read_reg(dev, 0x5) != 0)
+               return -ENODEV;
+       return 0;
+}
+
+/*
+ * em28xx_i2c_xfer()
+ * the main i2c transfer function
+ */
+static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
+                          struct i2c_msg msgs[], int num)
+{
+       struct em28xx *dev = i2c_adap->algo_data;
+       int addr, rc, i, byte;
+
+       if (num <= 0)
+               return 0;
+       for (i = 0; i < num; i++) {
+               addr = msgs[i].addr << 1;
+               dprintk2(2, "%s %s addr=%x len=%d:",
+                        (msgs[i].flags & I2C_M_RD) ? "read" : "write",
+                        i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
+               if (!msgs[i].len) { /* no len: check only for device presence */
+                       if (dev->board.is_em2800)
+                               rc = em2800_i2c_check_for_device(dev, addr);
+                       else
+                               rc = em28xx_i2c_check_for_device(dev, addr);
+                       if (rc < 0) {
+                               dprintk2(2, " no device\n");
+                               return rc;
+                       }
+
+               } else if (msgs[i].flags & I2C_M_RD) {
+                       /* read bytes */
+                       if (dev->board.is_em2800)
+                               rc = em2800_i2c_recv_bytes(dev, addr,
+                                                          msgs[i].buf,
+                                                          msgs[i].len);
+                       else
+                               rc = em28xx_i2c_recv_bytes(dev, addr,
+                                                          msgs[i].buf,
+                                                          msgs[i].len);
+                       if (i2c_debug >= 2) {
+                               for (byte = 0; byte < msgs[i].len; byte++)
+                                       printk(" %02x", msgs[i].buf[byte]);
+                       }
+               } else {
+                       /* write bytes */
+                       if (i2c_debug >= 2) {
+                               for (byte = 0; byte < msgs[i].len; byte++)
+                                       printk(" %02x", msgs[i].buf[byte]);
+                       }
+                       if (dev->board.is_em2800)
+                               rc = em2800_i2c_send_bytes(dev, addr,
+                                                          msgs[i].buf,
+                                                          msgs[i].len);
+                       else
+                               rc = em28xx_i2c_send_bytes(dev, addr,
+                                                          msgs[i].buf,
+                                                          msgs[i].len,
+                                                          i == num - 1);
+               }
+               if (rc < 0)
+                       goto err;
+               if (i2c_debug >= 2)
+                       printk("\n");
+       }
+
+       return num;
+err:
+       dprintk2(2, " ERROR: %i\n", rc);
+       return rc;
+}
+
+/* based on linux/sunrpc/svcauth.h and linux/hash.h
+ * The original hash function returns a different value, if arch is x86_64
+ *  or i386.
+ */
+static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
+{
+       unsigned long hash = 0;
+       unsigned long l = 0;
+       int len = 0;
+       unsigned char c;
+       do {
+               if (len == length) {
+                       c = (char)len;
+                       len = -1;
+               } else
+                       c = *buf++;
+               l = (l << 8) | c;
+               len++;
+               if ((len & (32 / 8 - 1)) == 0)
+                       hash = ((hash^l) * 0x9e370001UL);
+       } while (len);
+
+       return (hash >> (32 - bits)) & 0xffffffffUL;
+}
+
+static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
+{
+       unsigned char buf, *p = eedata;
+       struct em28xx_eeprom *em_eeprom = (void *)eedata;
+       int i, err, size = len, block;
+
+       if (dev->chip_id == CHIP_ID_EM2874 ||
+           dev->chip_id == CHIP_ID_EM28174 ||
+           dev->chip_id == CHIP_ID_EM2884) {
+               /* Empia switched to a 16-bit addressable eeprom in newer
+                  devices.  While we could certainly write a routine to read
+                  the eeprom, there is nothing of use in there that cannot be
+                  accessed through registers, and there is the risk that we
+                  could corrupt the eeprom (since a 16-bit read call is
+                  interpreted as a write call by 8-bit eeproms).
+               */
+               return 0;
+       }
+
+       dev->i2c_client.addr = 0xa0 >> 1;
+
+       /* Check if board has eeprom */
+       err = i2c_master_recv(&dev->i2c_client, &buf, 0);
+       if (err < 0) {
+               em28xx_errdev("board has no eeprom\n");
+               memset(eedata, 0, len);
+               return -ENODEV;
+       }
+
+       buf = 0;
+
+       err = i2c_master_send(&dev->i2c_client, &buf, 1);
+       if (err != 1) {
+               printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
+                      dev->name, err);
+               return err;
+       }
+       while (size > 0) {
+               if (size > 16)
+                       block = 16;
+               else
+                       block = size;
+
+               if (block !=
+                   (err = i2c_master_recv(&dev->i2c_client, p, block))) {
+                       printk(KERN_WARNING
+                              "%s: i2c eeprom read error (err=%d)\n",
+                              dev->name, err);
+                       return err;
+               }
+               size -= block;
+               p += block;
+       }
+       for (i = 0; i < len; i++) {
+               if (0 == (i % 16))
+                       printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
+               printk(" %02x", eedata[i]);
+               if (15 == (i % 16))
+                       printk("\n");
+       }
+
+       if (em_eeprom->id == 0x9567eb1a)
+               dev->hash = em28xx_hash_mem(eedata, len, 32);
+
+       printk(KERN_INFO "%s: EEPROM ID= 0x%08x, EEPROM hash = 0x%08lx\n",
+              dev->name, em_eeprom->id, dev->hash);
+
+       printk(KERN_INFO "%s: EEPROM info:\n", dev->name);
+
+       switch (em_eeprom->chip_conf >> 4 & 0x3) {
+       case 0:
+               printk(KERN_INFO "%s:\tNo audio on board.\n", dev->name);
+               break;
+       case 1:
+               printk(KERN_INFO "%s:\tAC97 audio (5 sample rates)\n",
+                                dev->name);
+               break;
+       case 2:
+               printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n",
+                                dev->name);
+               break;
+       case 3:
+               printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n",
+                                dev->name);
+               break;
+       }
+
+       if (em_eeprom->chip_conf & 1 << 3)
+               printk(KERN_INFO "%s:\tUSB Remote wakeup capable\n", dev->name);
+
+       if (em_eeprom->chip_conf & 1 << 2)
+               printk(KERN_INFO "%s:\tUSB Self power capable\n", dev->name);
+
+       switch (em_eeprom->chip_conf & 0x3) {
+       case 0:
+               printk(KERN_INFO "%s:\t500mA max power\n", dev->name);
+               break;
+       case 1:
+               printk(KERN_INFO "%s:\t400mA max power\n", dev->name);
+               break;
+       case 2:
+               printk(KERN_INFO "%s:\t300mA max power\n", dev->name);
+               break;
+       case 3:
+               printk(KERN_INFO "%s:\t200mA max power\n", dev->name);
+               break;
+       }
+       printk(KERN_INFO "%s:\tTable at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
+                               dev->name,
+                               em_eeprom->string_idx_table,
+                               em_eeprom->string1,
+                               em_eeprom->string2,
+                               em_eeprom->string3);
+
+       return 0;
+}
+
+/* ----------------------------------------------------------- */
+
+/*
+ * functionality()
+ */
+static u32 functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm em28xx_algo = {
+       .master_xfer   = em28xx_i2c_xfer,
+       .functionality = functionality,
+};
+
+static struct i2c_adapter em28xx_adap_template = {
+       .owner = THIS_MODULE,
+       .name = "em28xx",
+       .algo = &em28xx_algo,
+};
+
+static struct i2c_client em28xx_client_template = {
+       .name = "em28xx internal",
+};
+
+/* ----------------------------------------------------------- */
+
+/*
+ * i2c_devs
+ * incomplete list of known devices
+ */
+static char *i2c_devs[128] = {
+       [0x4a >> 1] = "saa7113h",
+       [0x52 >> 1] = "drxk",
+       [0x60 >> 1] = "remote IR sensor",
+       [0x8e >> 1] = "remote IR sensor",
+       [0x86 >> 1] = "tda9887",
+       [0x80 >> 1] = "msp34xx",
+       [0x88 >> 1] = "msp34xx",
+       [0xa0 >> 1] = "eeprom",
+       [0xb0 >> 1] = "tda9874",
+       [0xb8 >> 1] = "tvp5150a",
+       [0xba >> 1] = "webcam sensor or tvp5150a",
+       [0xc0 >> 1] = "tuner (analog)",
+       [0xc2 >> 1] = "tuner (analog)",
+       [0xc4 >> 1] = "tuner (analog)",
+       [0xc6 >> 1] = "tuner (analog)",
+};
+
+/*
+ * do_i2c_scan()
+ * check i2c address range for devices
+ */
+void em28xx_do_i2c_scan(struct em28xx *dev)
+{
+       u8 i2c_devicelist[128];
+       unsigned char buf;
+       int i, rc;
+
+       memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist));
+
+       for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
+               dev->i2c_client.addr = i;
+               rc = i2c_master_recv(&dev->i2c_client, &buf, 0);
+               if (rc < 0)
+                       continue;
+               i2c_devicelist[i] = i;
+               printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n",
+                      dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
+       }
+
+       dev->i2c_hash = em28xx_hash_mem(i2c_devicelist,
+                                       ARRAY_SIZE(i2c_devicelist), 32);
+}
+
+/*
+ * em28xx_i2c_register()
+ * register i2c bus
+ */
+int em28xx_i2c_register(struct em28xx *dev)
+{
+       int retval;
+
+       BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
+       BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
+       dev->i2c_adap = em28xx_adap_template;
+       dev->i2c_adap.dev.parent = &dev->udev->dev;
+       strcpy(dev->i2c_adap.name, dev->name);
+       dev->i2c_adap.algo_data = dev;
+       i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
+
+       retval = i2c_add_adapter(&dev->i2c_adap);
+       if (retval < 0) {
+               em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n",
+                       __func__, retval);
+               return retval;
+       }
+
+       dev->i2c_client = em28xx_client_template;
+       dev->i2c_client.adapter = &dev->i2c_adap;
+
+       retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
+       if ((retval < 0) && (retval != -ENODEV)) {
+               em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
+                       __func__, retval);
+
+               return retval;
+       }
+
+       if (i2c_scan)
+               em28xx_do_i2c_scan(dev);
+
+       return 0;
+}
+
+/*
+ * em28xx_i2c_unregister()
+ * unregister i2c_bus
+ */
+int em28xx_i2c_unregister(struct em28xx *dev)
+{
+       i2c_del_adapter(&dev->i2c_adap);
+       return 0;
+}
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
new file mode 100644 (file)
index 0000000..97d36b4
--- /dev/null
@@ -0,0 +1,645 @@
+/*
+  handle em28xx IR remotes via linux kernel input layer.
+
+   Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
+                     Markus Rechberger <mrechberger@gmail.com>
+                     Mauro Carvalho Chehab <mchehab@infradead.org>
+                     Sascha Sommer <saschasommer@freenet.de>
+
+  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+
+#include "em28xx.h"
+
+#define EM28XX_SNAPSHOT_KEY KEY_CAMERA
+#define EM28XX_SBUTTON_QUERY_INTERVAL 500
+#define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20
+
+static unsigned int ir_debug;
+module_param(ir_debug, int, 0644);
+MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
+
+#define MODULE_NAME "em28xx"
+
+#define i2cdprintk(fmt, arg...) \
+       if (ir_debug) { \
+               printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
+       }
+
+#define dprintk(fmt, arg...) \
+       if (ir_debug) { \
+               printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
+       }
+
+/**********************************************************
+ Polling structure used by em28xx IR's
+ **********************************************************/
+
+struct em28xx_ir_poll_result {
+       unsigned int toggle_bit:1;
+       unsigned int read_count:7;
+       u8 rc_address;
+       u8 rc_data[4]; /* 1 byte on em2860/2880, 4 on em2874 */
+};
+
+struct em28xx_IR {
+       struct em28xx *dev;
+       struct rc_dev *rc;
+       char name[32];
+       char phys[32];
+
+       /* poll external decoder */
+       int polling;
+       struct delayed_work work;
+       unsigned int full_code:1;
+       unsigned int last_readcount;
+
+       int  (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *);
+};
+
+/**********************************************************
+ I2C IR based get keycodes - should be used with ir-kbd-i2c
+ **********************************************************/
+
+static int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+       unsigned char b;
+
+       /* poll IR chip */
+       if (1 != i2c_master_recv(ir->c, &b, 1)) {
+               i2cdprintk("read error\n");
+               return -EIO;
+       }
+
+       /* it seems that 0xFE indicates that a button is still hold
+          down, while 0xff indicates that no button is hold
+          down. 0xfe sequences are sometimes interrupted by 0xFF */
+
+       i2cdprintk("key %02x\n", b);
+
+       if (b == 0xff)
+               return 0;
+
+       if (b == 0xfe)
+               /* keep old data */
+               return 1;
+
+       *ir_key = b;
+       *ir_raw = b;
+       return 1;
+}
+
+static int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+       unsigned char buf[2];
+       u16 code;
+       int size;
+
+       /* poll IR chip */
+       size = i2c_master_recv(ir->c, buf, sizeof(buf));
+
+       if (size != 2)
+               return -EIO;
+
+       /* Does eliminate repeated parity code */
+       if (buf[1] == 0xff)
+               return 0;
+
+       ir->old = buf[1];
+
+       /*
+        * Rearranges bits to the right order.
+        * The bit order were determined experimentally by using
+        * The original Hauppauge Grey IR and another RC5 that uses addr=0x08
+        * The RC5 code has 14 bits, but we've experimentally determined
+        * the meaning for only 11 bits.
+        * So, the code translation is not complete. Yet, it is enough to
+        * work with the provided RC5 IR.
+        */
+       code =
+                ((buf[0] & 0x01) ? 0x0020 : 0) | /*            0010 0000 */
+                ((buf[0] & 0x02) ? 0x0010 : 0) | /*            0001 0000 */
+                ((buf[0] & 0x04) ? 0x0008 : 0) | /*            0000 1000 */
+                ((buf[0] & 0x08) ? 0x0004 : 0) | /*            0000 0100 */
+                ((buf[0] & 0x10) ? 0x0002 : 0) | /*            0000 0010 */
+                ((buf[0] & 0x20) ? 0x0001 : 0) | /*            0000 0001 */
+                ((buf[1] & 0x08) ? 0x1000 : 0) | /* 0001 0000            */
+                ((buf[1] & 0x10) ? 0x0800 : 0) | /* 0000 1000            */
+                ((buf[1] & 0x20) ? 0x0400 : 0) | /* 0000 0100            */
+                ((buf[1] & 0x40) ? 0x0200 : 0) | /* 0000 0010            */
+                ((buf[1] & 0x80) ? 0x0100 : 0);  /* 0000 0001            */
+
+       i2cdprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x%02x)\n",
+                       code, buf[1], buf[0]);
+
+       /* return key */
+       *ir_key = code;
+       *ir_raw = code;
+       return 1;
+}
+
+static int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
+                                    u32 *ir_raw)
+{
+       unsigned char buf[3];
+
+       /* poll IR chip */
+
+       if (3 != i2c_master_recv(ir->c, buf, 3)) {
+               i2cdprintk("read error\n");
+               return -EIO;
+       }
+
+       i2cdprintk("key %02x\n", buf[2]&0x3f);
+       if (buf[0] != 0x00)
+               return 0;
+
+       *ir_key = buf[2]&0x3f;
+       *ir_raw = buf[2]&0x3f;
+
+       return 1;
+}
+
+static int em28xx_get_key_winfast_usbii_deluxe(struct IR_i2c *ir, u32 *ir_key,
+                                       u32 *ir_raw)
+{
+       unsigned char subaddr, keydetect, key;
+
+       struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0, .buf = &subaddr, .len = 1},
+
+                               { .addr = ir->c->addr, .flags = I2C_M_RD, .buf = &keydetect, .len = 1} };
+
+       subaddr = 0x10;
+       if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
+               i2cdprintk("read error\n");
+               return -EIO;
+       }
+       if (keydetect == 0x00)
+               return 0;
+
+       subaddr = 0x00;
+       msg[1].buf = &key;
+       if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
+               i2cdprintk("read error\n");
+       return -EIO;
+       }
+       if (key == 0x00)
+               return 0;
+
+       *ir_key = key;
+       *ir_raw = key;
+       return 1;
+}
+
+/**********************************************************
+ Poll based get keycode functions
+ **********************************************************/
+
+/* This is for the em2860/em2880 */
+static int default_polling_getkey(struct em28xx_IR *ir,
+                                 struct em28xx_ir_poll_result *poll_result)
+{
+       struct em28xx *dev = ir->dev;
+       int rc;
+       u8 msg[3] = { 0, 0, 0 };
+
+       /* Read key toggle, brand, and key code
+          on registers 0x45, 0x46 and 0x47
+        */
+       rc = dev->em28xx_read_reg_req_len(dev, 0, EM28XX_R45_IR,
+                                         msg, sizeof(msg));
+       if (rc < 0)
+               return rc;
+
+       /* Infrared toggle (Reg 0x45[7]) */
+       poll_result->toggle_bit = (msg[0] >> 7);
+
+       /* Infrared read count (Reg 0x45[6:0] */
+       poll_result->read_count = (msg[0] & 0x7f);
+
+       /* Remote Control Address (Reg 0x46) */
+       poll_result->rc_address = msg[1];
+
+       /* Remote Control Data (Reg 0x47) */
+       poll_result->rc_data[0] = msg[2];
+
+       return 0;
+}
+
+static int em2874_polling_getkey(struct em28xx_IR *ir,
+                                struct em28xx_ir_poll_result *poll_result)
+{
+       struct em28xx *dev = ir->dev;
+       int rc;
+       u8 msg[5] = { 0, 0, 0, 0, 0 };
+
+       /* Read key toggle, brand, and key code
+          on registers 0x51-55
+        */
+       rc = dev->em28xx_read_reg_req_len(dev, 0, EM2874_R51_IR,
+                                         msg, sizeof(msg));
+       if (rc < 0)
+               return rc;
+
+       /* Infrared toggle (Reg 0x51[7]) */
+       poll_result->toggle_bit = (msg[0] >> 7);
+
+       /* Infrared read count (Reg 0x51[6:0] */
+       poll_result->read_count = (msg[0] & 0x7f);
+
+       /* Remote Control Address (Reg 0x52) */
+       poll_result->rc_address = msg[1];
+
+       /* Remote Control Data (Reg 0x53-55) */
+       poll_result->rc_data[0] = msg[2];
+       poll_result->rc_data[1] = msg[3];
+       poll_result->rc_data[2] = msg[4];
+
+       return 0;
+}
+
+/**********************************************************
+ Polling code for em28xx
+ **********************************************************/
+
+static void em28xx_ir_handle_key(struct em28xx_IR *ir)
+{
+       int result;
+       struct em28xx_ir_poll_result poll_result;
+
+       /* read the registers containing the IR status */
+       result = ir->get_key(ir, &poll_result);
+       if (unlikely(result < 0)) {
+               dprintk("ir->get_key() failed %d\n", result);
+               return;
+       }
+
+       if (unlikely(poll_result.read_count != ir->last_readcount)) {
+               dprintk("%s: toggle: %d, count: %d, key 0x%02x%02x\n", __func__,
+                       poll_result.toggle_bit, poll_result.read_count,
+                       poll_result.rc_address, poll_result.rc_data[0]);
+               if (ir->full_code)
+                       rc_keydown(ir->rc,
+                                  poll_result.rc_address << 8 |
+                                  poll_result.rc_data[0],
+                                  poll_result.toggle_bit);
+               else
+                       rc_keydown(ir->rc,
+                                  poll_result.rc_data[0],
+                                  poll_result.toggle_bit);
+
+               if (ir->dev->chip_id == CHIP_ID_EM2874 ||
+                   ir->dev->chip_id == CHIP_ID_EM2884)
+                       /* The em2874 clears the readcount field every time the
+                          register is read.  The em2860/2880 datasheet says that it
+                          is supposed to clear the readcount, but it doesn't.  So with
+                          the em2874, we are looking for a non-zero read count as
+                          opposed to a readcount that is incrementing */
+                       ir->last_readcount = 0;
+               else
+                       ir->last_readcount = poll_result.read_count;
+       }
+}
+
+static void em28xx_ir_work(struct work_struct *work)
+{
+       struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work.work);
+
+       em28xx_ir_handle_key(ir);
+       schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
+}
+
+static int em28xx_ir_start(struct rc_dev *rc)
+{
+       struct em28xx_IR *ir = rc->priv;
+
+       INIT_DELAYED_WORK(&ir->work, em28xx_ir_work);
+       schedule_delayed_work(&ir->work, 0);
+
+       return 0;
+}
+
+static void em28xx_ir_stop(struct rc_dev *rc)
+{
+       struct em28xx_IR *ir = rc->priv;
+
+       cancel_delayed_work_sync(&ir->work);
+}
+
+static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
+{
+       int rc = 0;
+       struct em28xx_IR *ir = rc_dev->priv;
+       struct em28xx *dev = ir->dev;
+       u8 ir_config = EM2874_IR_RC5;
+
+       /* Adjust xclk based o IR table for RC5/NEC tables */
+
+       if (rc_type == RC_TYPE_RC5) {
+               dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
+               ir->full_code = 1;
+       } else if (rc_type == RC_TYPE_NEC) {
+               dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE;
+               ir_config = EM2874_IR_NEC;
+               ir->full_code = 1;
+       } else if (rc_type != RC_TYPE_UNKNOWN)
+               rc = -EINVAL;
+
+       em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk,
+                             EM28XX_XCLK_IR_RC5_MODE);
+
+       /* Setup the proper handler based on the chip */
+       switch (dev->chip_id) {
+       case CHIP_ID_EM2860:
+       case CHIP_ID_EM2883:
+               ir->get_key = default_polling_getkey;
+               break;
+       case CHIP_ID_EM2884:
+       case CHIP_ID_EM2874:
+       case CHIP_ID_EM28174:
+               ir->get_key = em2874_polling_getkey;
+               em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1);
+               break;
+       default:
+               printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n",
+                       dev->chip_id);
+               rc = -EINVAL;
+       }
+
+       return rc;
+}
+
+static void em28xx_register_i2c_ir(struct em28xx *dev)
+{
+       /* Leadtek winfast tv USBII deluxe can find a non working IR-device */
+       /* at address 0x18, so if that address is needed for another board in */
+       /* the future, please put it after 0x1f. */
+       struct i2c_board_info info;
+       const unsigned short addr_list[] = {
+                0x1f, 0x30, 0x47, I2C_CLIENT_END
+       };
+
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       memset(&dev->init_data, 0, sizeof(dev->init_data));
+       strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+
+       /* detect & configure */
+       switch (dev->model) {
+       case EM2800_BOARD_TERRATEC_CINERGY_200:
+       case EM2820_BOARD_TERRATEC_CINERGY_250:
+               dev->init_data.ir_codes = RC_MAP_EM_TERRATEC;
+               dev->init_data.get_key = em28xx_get_key_terratec;
+               dev->init_data.name = "i2c IR (EM28XX Terratec)";
+               break;
+       case EM2820_BOARD_PINNACLE_USB_2:
+               dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY;
+               dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey;
+               dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)";
+               break;
+       case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
+               dev->init_data.ir_codes = RC_MAP_HAUPPAUGE;
+               dev->init_data.get_key = em28xx_get_key_em_haup;
+               dev->init_data.name = "i2c IR (EM2840 Hauppauge)";
+               break;
+       case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE:
+               dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE;
+               dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe;
+               dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)";
+               break;
+       }
+
+       if (dev->init_data.name)
+               info.platform_data = &dev->init_data;
+       i2c_new_probed_device(&dev->i2c_adap, &info, addr_list, NULL);
+}
+
+/**********************************************************
+ Handle Webcam snapshot button
+ **********************************************************/
+
+static void em28xx_query_sbutton(struct work_struct *work)
+{
+       /* Poll the register and see if the button is depressed */
+       struct em28xx *dev =
+               container_of(work, struct em28xx, sbutton_query_work.work);
+       int ret;
+
+       ret = em28xx_read_reg(dev, EM28XX_R0C_USBSUSP);
+
+       if (ret & EM28XX_R0C_USBSUSP_SNAPSHOT) {
+               u8 cleared;
+               /* Button is depressed, clear the register */
+               cleared = ((u8) ret) & ~EM28XX_R0C_USBSUSP_SNAPSHOT;
+               em28xx_write_regs(dev, EM28XX_R0C_USBSUSP, &cleared, 1);
+
+               /* Not emulate the keypress */
+               input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY,
+                                1);
+               /* Now unpress the key */
+               input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY,
+                                0);
+       }
+
+       /* Schedule next poll */
+       schedule_delayed_work(&dev->sbutton_query_work,
+                             msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL));
+}
+
+static void em28xx_register_snapshot_button(struct em28xx *dev)
+{
+       struct input_dev *input_dev;
+       int err;
+
+       em28xx_info("Registering snapshot button...\n");
+       input_dev = input_allocate_device();
+       if (!input_dev) {
+               em28xx_errdev("input_allocate_device failed\n");
+               return;
+       }
+
+       usb_make_path(dev->udev, dev->snapshot_button_path,
+                     sizeof(dev->snapshot_button_path));
+       strlcat(dev->snapshot_button_path, "/sbutton",
+               sizeof(dev->snapshot_button_path));
+       INIT_DELAYED_WORK(&dev->sbutton_query_work, em28xx_query_sbutton);
+
+       input_dev->name = "em28xx snapshot button";
+       input_dev->phys = dev->snapshot_button_path;
+       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+       set_bit(EM28XX_SNAPSHOT_KEY, input_dev->keybit);
+       input_dev->keycodesize = 0;
+       input_dev->keycodemax = 0;
+       input_dev->id.bustype = BUS_USB;
+       input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+       input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
+       input_dev->id.version = 1;
+       input_dev->dev.parent = &dev->udev->dev;
+
+       err = input_register_device(input_dev);
+       if (err) {
+               em28xx_errdev("input_register_device failed\n");
+               input_free_device(input_dev);
+               return;
+       }
+
+       dev->sbutton_input_dev = input_dev;
+       schedule_delayed_work(&dev->sbutton_query_work,
+                             msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL));
+       return;
+
+}
+
+static void em28xx_deregister_snapshot_button(struct em28xx *dev)
+{
+       if (dev->sbutton_input_dev != NULL) {
+               em28xx_info("Deregistering snapshot button\n");
+               cancel_delayed_work_sync(&dev->sbutton_query_work);
+               input_unregister_device(dev->sbutton_input_dev);
+               dev->sbutton_input_dev = NULL;
+       }
+       return;
+}
+
+static int em28xx_ir_init(struct em28xx *dev)
+{
+       struct em28xx_IR *ir;
+       struct rc_dev *rc;
+       int err = -ENOMEM;
+
+       if (dev->board.ir_codes == NULL) {
+               /* No remote control support */
+               em28xx_warn("Remote control support is not available for "
+                               "this card.\n");
+               return 0;
+       }
+
+       ir = kzalloc(sizeof(*ir), GFP_KERNEL);
+       rc = rc_allocate_device();
+       if (!ir || !rc)
+               goto err_out_free;
+
+       /* record handles to ourself */
+       ir->dev = dev;
+       dev->ir = ir;
+       ir->rc = rc;
+
+       /*
+        * em2874 supports more protocols. For now, let's just announce
+        * the two protocols that were already tested
+        */
+       rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
+       rc->priv = ir;
+       rc->change_protocol = em28xx_ir_change_protocol;
+       rc->open = em28xx_ir_start;
+       rc->close = em28xx_ir_stop;
+
+       /* By default, keep protocol field untouched */
+       err = em28xx_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
+       if (err)
+               goto err_out_free;
+
+       /* This is how often we ask the chip for IR information */
+       ir->polling = 100; /* ms */
+
+       /* init input device */
+       snprintf(ir->name, sizeof(ir->name), "em28xx IR (%s)",
+                                               dev->name);
+
+       usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
+       strlcat(ir->phys, "/input0", sizeof(ir->phys));
+
+       rc->input_name = ir->name;
+       rc->input_phys = ir->phys;
+       rc->input_id.bustype = BUS_USB;
+       rc->input_id.version = 1;
+       rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+       rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
+       rc->dev.parent = &dev->udev->dev;
+       rc->map_name = dev->board.ir_codes;
+       rc->driver_name = MODULE_NAME;
+
+       /* all done */
+       err = rc_register_device(rc);
+       if (err)
+               goto err_out_stop;
+
+       em28xx_register_i2c_ir(dev);
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
+       if (dev->board.has_ir_i2c)
+               request_module("ir-kbd-i2c");
+#endif
+       if (dev->board.has_snapshot_button)
+               em28xx_register_snapshot_button(dev);
+
+       return 0;
+
+ err_out_stop:
+       dev->ir = NULL;
+ err_out_free:
+       rc_free_device(rc);
+       kfree(ir);
+       return err;
+}
+
+static int em28xx_ir_fini(struct em28xx *dev)
+{
+       struct em28xx_IR *ir = dev->ir;
+
+       em28xx_deregister_snapshot_button(dev);
+
+       /* skip detach on non attached boards */
+       if (!ir)
+               return 0;
+
+       if (ir->rc)
+               rc_unregister_device(ir->rc);
+
+       /* done */
+       kfree(ir);
+       dev->ir = NULL;
+       return 0;
+}
+
+static struct em28xx_ops rc_ops = {
+       .id   = EM28XX_RC,
+       .name = "Em28xx Input Extension",
+       .init = em28xx_ir_init,
+       .fini = em28xx_ir_fini,
+};
+
+static int __init em28xx_rc_register(void)
+{
+       return em28xx_register_extension(&rc_ops);
+}
+
+static void __exit em28xx_rc_unregister(void)
+{
+       em28xx_unregister_extension(&rc_ops);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_DESCRIPTION("Em28xx Input driver");
+
+module_init(em28xx_rc_register);
+module_exit(em28xx_rc_unregister);
diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h
new file mode 100644 (file)
index 0000000..6ff3682
--- /dev/null
@@ -0,0 +1,226 @@
+#define EM_GPIO_0  (1 << 0)
+#define EM_GPIO_1  (1 << 1)
+#define EM_GPIO_2  (1 << 2)
+#define EM_GPIO_3  (1 << 3)
+#define EM_GPIO_4  (1 << 4)
+#define EM_GPIO_5  (1 << 5)
+#define EM_GPIO_6  (1 << 6)
+#define EM_GPIO_7  (1 << 7)
+
+#define EM_GPO_0   (1 << 0)
+#define EM_GPO_1   (1 << 1)
+#define EM_GPO_2   (1 << 2)
+#define EM_GPO_3   (1 << 3)
+
+/* em28xx endpoints */
+#define EM28XX_EP_ANALOG       0x82
+#define EM28XX_EP_AUDIO                0x83
+#define EM28XX_EP_DIGITAL      0x84
+
+/* em2800 registers */
+#define EM2800_R08_AUDIOSRC 0x08
+
+/* em28xx registers */
+
+#define EM28XX_R00_CHIPCFG     0x00
+
+/* em28xx Chip Configuration 0x00 */
+#define EM28XX_CHIPCFG_VENDOR_AUDIO            0x80
+#define EM28XX_CHIPCFG_I2S_VOLUME_CAPABLE      0x40
+#define EM28XX_CHIPCFG_I2S_5_SAMPRATES         0x30
+#define EM28XX_CHIPCFG_I2S_3_SAMPRATES         0x20
+#define EM28XX_CHIPCFG_AC97                    0x10
+#define EM28XX_CHIPCFG_AUDIOMASK               0x30
+
+#define EM28XX_R01_CHIPCFG2    0x01
+
+/* em28xx Chip Configuration 2 0x01 */
+#define EM28XX_CHIPCFG2_TS_PRESENT             0x10
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_MASK   0x0c /* bits 3-2 */
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_1MF    0x00
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_2MF    0x04
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_4MF    0x08
+#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_8MF    0x0c
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK     0x03 /* bits 0-1 */
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_188      0x00
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_376      0x01
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_564      0x02
+#define EM28XX_CHIPCFG2_TS_PACKETSIZE_752      0x03
+
+
+       /* GPIO/GPO registers */
+#define EM2880_R04_GPO 0x04    /* em2880-em2883 only */
+#define EM28XX_R08_GPIO        0x08    /* em2820 or upper */
+
+#define EM28XX_R06_I2C_CLK     0x06
+
+/* em28xx I2C Clock Register (0x06) */
+#define EM28XX_I2C_CLK_ACK_LAST_READ   0x80
+#define EM28XX_I2C_CLK_WAIT_ENABLE     0x40
+#define EM28XX_I2C_EEPROM_ON_BOARD     0x08
+#define EM28XX_I2C_EEPROM_KEY_VALID    0x04
+#define EM2874_I2C_SECONDARY_BUS_SELECT        0x04 /* em2874 has two i2c busses */
+#define EM28XX_I2C_FREQ_1_5_MHZ                0x03 /* bus frequency (bits [1-0]) */
+#define EM28XX_I2C_FREQ_25_KHZ         0x02
+#define EM28XX_I2C_FREQ_400_KHZ                0x01
+#define EM28XX_I2C_FREQ_100_KHZ                0x00
+
+
+#define EM28XX_R0A_CHIPID      0x0a
+#define EM28XX_R0C_USBSUSP     0x0c    /* */
+
+#define EM28XX_R0E_AUDIOSRC    0x0e
+#define EM28XX_R0F_XCLK        0x0f
+
+/* em28xx XCLK Register (0x0f) */
+#define EM28XX_XCLK_AUDIO_UNMUTE       0x80 /* otherwise audio muted */
+#define EM28XX_XCLK_I2S_MSB_TIMING     0x40 /* otherwise standard timing */
+#define EM28XX_XCLK_IR_RC5_MODE                0x20 /* otherwise NEC mode */
+#define EM28XX_XCLK_IR_NEC_CHK_PARITY  0x10
+#define EM28XX_XCLK_FREQUENCY_30MHZ    0x00 /* Freq. select (bits [3-0]) */
+#define EM28XX_XCLK_FREQUENCY_15MHZ    0x01
+#define EM28XX_XCLK_FREQUENCY_10MHZ    0x02
+#define EM28XX_XCLK_FREQUENCY_7_5MHZ   0x03
+#define EM28XX_XCLK_FREQUENCY_6MHZ     0x04
+#define EM28XX_XCLK_FREQUENCY_5MHZ     0x05
+#define EM28XX_XCLK_FREQUENCY_4_3MHZ   0x06
+#define EM28XX_XCLK_FREQUENCY_12MHZ    0x07
+#define EM28XX_XCLK_FREQUENCY_20MHZ    0x08
+#define EM28XX_XCLK_FREQUENCY_20MHZ_2  0x09
+#define EM28XX_XCLK_FREQUENCY_48MHZ    0x0a
+#define EM28XX_XCLK_FREQUENCY_24MHZ    0x0b
+
+#define EM28XX_R10_VINMODE     0x10
+
+#define EM28XX_R11_VINCTRL     0x11
+
+/* em28xx Video Input Control Register 0x11 */
+#define EM28XX_VINCTRL_VBI_SLICED      0x80
+#define EM28XX_VINCTRL_VBI_RAW         0x40
+#define EM28XX_VINCTRL_VOUT_MODE_IN    0x20 /* HREF,VREF,VACT in output */
+#define EM28XX_VINCTRL_CCIR656_ENABLE  0x10
+#define EM28XX_VINCTRL_VBI_16BIT_RAW   0x08 /* otherwise 8-bit raw */
+#define EM28XX_VINCTRL_FID_ON_HREF     0x04
+#define EM28XX_VINCTRL_DUAL_EDGE_STROBE        0x02
+#define EM28XX_VINCTRL_INTERLACED      0x01
+
+#define EM28XX_R12_VINENABLE   0x12    /* */
+
+#define EM28XX_R14_GAMMA       0x14
+#define EM28XX_R15_RGAIN       0x15
+#define EM28XX_R16_GGAIN       0x16
+#define EM28XX_R17_BGAIN       0x17
+#define EM28XX_R18_ROFFSET     0x18
+#define EM28XX_R19_GOFFSET     0x19
+#define EM28XX_R1A_BOFFSET     0x1a
+
+#define EM28XX_R1B_OFLOW       0x1b
+#define EM28XX_R1C_HSTART      0x1c
+#define EM28XX_R1D_VSTART      0x1d
+#define EM28XX_R1E_CWIDTH      0x1e
+#define EM28XX_R1F_CHEIGHT     0x1f
+
+#define EM28XX_R20_YGAIN       0x20
+#define EM28XX_R21_YOFFSET     0x21
+#define EM28XX_R22_UVGAIN      0x22
+#define EM28XX_R23_UOFFSET     0x23
+#define EM28XX_R24_VOFFSET     0x24
+#define EM28XX_R25_SHARPNESS   0x25
+
+#define EM28XX_R26_COMPR       0x26
+#define EM28XX_R27_OUTFMT      0x27
+
+/* em28xx Output Format Register (0x27) */
+#define EM28XX_OUTFMT_RGB_8_RGRG       0x00
+#define EM28XX_OUTFMT_RGB_8_GRGR       0x01
+#define EM28XX_OUTFMT_RGB_8_GBGB       0x02
+#define EM28XX_OUTFMT_RGB_8_BGBG       0x03
+#define EM28XX_OUTFMT_RGB_16_656       0x04
+#define EM28XX_OUTFMT_RGB_8_BAYER      0x08 /* Pattern in Reg 0x10[1-0] */
+#define EM28XX_OUTFMT_YUV211           0x10
+#define EM28XX_OUTFMT_YUV422_Y0UY1V    0x14
+#define EM28XX_OUTFMT_YUV422_Y1UY0V    0x15
+#define EM28XX_OUTFMT_YUV411           0x18
+
+
+#define EM28XX_R28_XMIN        0x28
+#define EM28XX_R29_XMAX        0x29
+#define EM28XX_R2A_YMIN        0x2a
+#define EM28XX_R2B_YMAX        0x2b
+
+#define EM28XX_R30_HSCALELOW   0x30
+#define EM28XX_R31_HSCALEHIGH  0x31
+#define EM28XX_R32_VSCALELOW   0x32
+#define EM28XX_R33_VSCALEHIGH  0x33
+#define EM28XX_R34_VBI_START_H 0x34
+#define EM28XX_R35_VBI_START_V 0x35
+#define EM28XX_R36_VBI_WIDTH   0x36
+#define EM28XX_R37_VBI_HEIGHT  0x37
+
+#define EM28XX_R40_AC97LSB     0x40
+#define EM28XX_R41_AC97MSB     0x41
+#define EM28XX_R42_AC97ADDR    0x42
+#define EM28XX_R43_AC97BUSY    0x43
+
+#define EM28XX_R45_IR          0x45
+       /* 0x45  bit 7    - parity bit
+                bits 6-0 - count
+          0x46  IR brand
+          0x47  IR data
+        */
+
+/* em2874 registers */
+#define EM2874_R50_IR_CONFIG    0x50
+#define EM2874_R51_IR           0x51
+#define EM2874_R5F_TS_ENABLE    0x5f
+#define EM2874_R80_GPIO         0x80
+
+/* em2874 IR config register (0x50) */
+#define EM2874_IR_NEC           0x00
+#define EM2874_IR_RC5           0x04
+#define EM2874_IR_RC6_MODE_0    0x08
+#define EM2874_IR_RC6_MODE_6A   0x0b
+
+/* em2874 Transport Stream Enable Register (0x5f) */
+#define EM2874_TS1_CAPTURE_ENABLE (1 << 0)
+#define EM2874_TS1_FILTER_ENABLE  (1 << 1)
+#define EM2874_TS1_NULL_DISCARD   (1 << 2)
+#define EM2874_TS2_CAPTURE_ENABLE (1 << 4)
+#define EM2874_TS2_FILTER_ENABLE  (1 << 5)
+#define EM2874_TS2_NULL_DISCARD   (1 << 6)
+
+/* register settings */
+#define EM2800_AUDIO_SRC_TUNER  0x0d
+#define EM2800_AUDIO_SRC_LINE   0x0c
+#define EM28XX_AUDIO_SRC_TUNER 0xc0
+#define EM28XX_AUDIO_SRC_LINE  0x80
+
+/* FIXME: Need to be populated with the other chip ID's */
+enum em28xx_chip_id {
+       CHIP_ID_EM2800 = 7,
+       CHIP_ID_EM2710 = 17,
+       CHIP_ID_EM2820 = 18,    /* Also used by some em2710 */
+       CHIP_ID_EM2840 = 20,
+       CHIP_ID_EM2750 = 33,
+       CHIP_ID_EM2860 = 34,
+       CHIP_ID_EM2870 = 35,
+       CHIP_ID_EM2883 = 36,
+       CHIP_ID_EM2874 = 65,
+       CHIP_ID_EM2884 = 68,
+       CHIP_ID_EM28174 = 113,
+};
+
+/*
+ * Registers used by em202
+ */
+
+/* EMP202 vendor registers */
+#define EM202_EXT_MODEM_CTRL     0x3e
+#define EM202_GPIO_CONF          0x4c
+#define EM202_GPIO_POLARITY      0x4e
+#define EM202_GPIO_STICKY        0x50
+#define EM202_GPIO_MASK          0x52
+#define EM202_GPIO_STATUS        0x54
+#define EM202_SPDIF_OUT_SEL      0x6a
+#define EM202_ANTIPOP            0x72
+#define EM202_EAPD_GPIO_ACCESS   0x74
diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c
new file mode 100644 (file)
index 0000000..2b4c9cb
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+   em28xx-vbi.c - VBI driver for em28xx
+
+   Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
+
+   This work was sponsored by EyeMagnet Limited.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/hardirq.h>
+#include <linux/init.h>
+
+#include "em28xx.h"
+
+static unsigned int vbibufs = 5;
+module_param(vbibufs, int, 0644);
+MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32");
+
+static unsigned int vbi_debug;
+module_param(vbi_debug, int, 0644);
+MODULE_PARM_DESC(vbi_debug, "enable debug messages [vbi]");
+
+#define dprintk(level, fmt, arg...)    if (vbi_debug >= level) \
+       printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg)
+
+/* ------------------------------------------------------------------ */
+
+static void
+free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
+{
+       struct em28xx_fh     *fh  = vq->priv_data;
+       struct em28xx        *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);
+
+       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 em28xx_fh     *fh  = q->priv_data;
+       struct em28xx        *dev = fh->dev;
+
+       *size = dev->vbi_width * dev->vbi_height * 2;
+
+       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)
+{
+       struct em28xx_fh     *fh  = q->priv_data;
+       struct em28xx        *dev = fh->dev;
+       struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
+       int                  rc = 0;
+
+       buf->vb.size = dev->vbi_width * dev->vbi_height * 2;
+
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.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;
+       }
+
+       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 em28xx_buffer    *buf     = container_of(vb,
+                                                       struct em28xx_buffer,
+                                                       vb);
+       struct em28xx_fh        *fh      = vq->priv_data;
+       struct em28xx           *dev     = fh->dev;
+       struct em28xx_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)
+{
+       struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
+       free_buffer(q, buf);
+}
+
+struct videobuf_queue_ops em28xx_vbi_qops = {
+       .buf_setup    = vbi_setup,
+       .buf_prepare  = vbi_prepare,
+       .buf_queue    = vbi_queue,
+       .buf_release  = vbi_release,
+};
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
new file mode 100644 (file)
index 0000000..ecb23df
--- /dev/null
@@ -0,0 +1,2624 @@
+/*
+   em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
+                   video capture devices
+
+   Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
+                     Markus Rechberger <mrechberger@gmail.com>
+                     Mauro Carvalho Chehab <mchehab@infradead.org>
+                     Sascha Sommer <saschasommer@freenet.de>
+
+       Some parts based on SN9C10x PC Camera Controllers GPL driver made
+               by Luca Risolia <luca.risolia@studio.unibo.it>
+
+   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/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 <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+
+#include "em28xx.h"
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/msp3400.h>
+#include <media/tuner.h>
+
+#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
+                     "Markus Rechberger <mrechberger@gmail.com>, " \
+                     "Mauro Carvalho Chehab <mchehab@infradead.org>, " \
+                     "Sascha Sommer <saschasommer@freenet.de>"
+
+#define DRIVER_DESC         "Empia em28xx based USB video device driver"
+
+#define EM28XX_VERSION "0.1.3"
+
+#define em28xx_videodbg(fmt, arg...) do {\
+       if (video_debug) \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); } while (0)
+
+static unsigned int isoc_debug;
+module_param(isoc_debug, int, 0644);
+MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
+
+#define em28xx_isocdbg(fmt, arg...) \
+do {\
+       if (isoc_debug) { \
+               printk(KERN_INFO "%s %s :"fmt, \
+                        dev->name, __func__ , ##arg); \
+       } \
+  } while (0)
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(EM28XX_VERSION);
+
+static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
+static unsigned int vbi_nr[]   = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(video_nr, int, NULL, 0444);
+module_param_array(vbi_nr, int, NULL, 0444);
+module_param_array(radio_nr, int, NULL, 0444);
+MODULE_PARM_DESC(video_nr, "video device numbers");
+MODULE_PARM_DESC(vbi_nr,   "vbi device numbers");
+MODULE_PARM_DESC(radio_nr, "radio device numbers");
+
+static unsigned int video_debug;
+module_param(video_debug, int, 0644);
+MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
+
+/* supported video standards */
+static struct em28xx_fmt format[] = {
+       {
+               .name     = "16 bpp YUY2, 4:2:2, packed",
+               .fourcc   = V4L2_PIX_FMT_YUYV,
+               .depth    = 16,
+               .reg      = EM28XX_OUTFMT_YUV422_Y0UY1V,
+       }, {
+               .name     = "16 bpp RGB 565, LE",
+               .fourcc   = V4L2_PIX_FMT_RGB565,
+               .depth    = 16,
+               .reg      = EM28XX_OUTFMT_RGB_16_656,
+       }, {
+               .name     = "8 bpp Bayer BGBG..GRGR",
+               .fourcc   = V4L2_PIX_FMT_SBGGR8,
+               .depth    = 8,
+               .reg      = EM28XX_OUTFMT_RGB_8_BGBG,
+       }, {
+               .name     = "8 bpp Bayer GRGR..BGBG",
+               .fourcc   = V4L2_PIX_FMT_SGRBG8,
+               .depth    = 8,
+               .reg      = EM28XX_OUTFMT_RGB_8_GRGR,
+       }, {
+               .name     = "8 bpp Bayer GBGB..RGRG",
+               .fourcc   = V4L2_PIX_FMT_SGBRG8,
+               .depth    = 8,
+               .reg      = EM28XX_OUTFMT_RGB_8_GBGB,
+       }, {
+               .name     = "12 bpp YUV411",
+               .fourcc   = V4L2_PIX_FMT_YUV411P,
+               .depth    = 12,
+               .reg      = EM28XX_OUTFMT_YUV411,
+       },
+};
+
+/* supported controls */
+/* Common to all boards */
+static struct v4l2_queryctrl ac97_qctrl[] = {
+       {
+               .id = V4L2_CID_AUDIO_VOLUME,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Volume",
+               .minimum = 0x0,
+               .maximum = 0x1f,
+               .step = 0x1,
+               .default_value = 0x1f,
+               .flags = V4L2_CTRL_FLAG_SLIDER,
+       }, {
+               .id = V4L2_CID_AUDIO_MUTE,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Mute",
+               .minimum = 0,
+               .maximum = 1,
+               .step = 1,
+               .default_value = 1,
+               .flags = 0,
+       }
+};
+
+/* ------------------------------------------------------------------
+       DMA and thread functions
+   ------------------------------------------------------------------*/
+
+/*
+ * Announces that a buffer were filled and request the next
+ */
+static inline void buffer_filled(struct em28xx *dev,
+                                 struct em28xx_dmaqueue *dma_q,
+                                 struct em28xx_buffer *buf)
+{
+       /* Advice that buffer was filled */
+       em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
+       buf->vb.state = VIDEOBUF_DONE;
+       buf->vb.field_count++;
+       do_gettimeofday(&buf->vb.ts);
+
+       dev->isoc_ctl.vid_buf = NULL;
+
+       list_del(&buf->vb.queue);
+       wake_up(&buf->vb.done);
+}
+
+static inline void vbi_buffer_filled(struct em28xx *dev,
+                                    struct em28xx_dmaqueue *dma_q,
+                                    struct em28xx_buffer *buf)
+{
+       /* Advice that buffer was filled */
+       em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
+
+       buf->vb.state = VIDEOBUF_DONE;
+       buf->vb.field_count++;
+       do_gettimeofday(&buf->vb.ts);
+
+       dev->isoc_ctl.vbi_buf = NULL;
+
+       list_del(&buf->vb.queue);
+       wake_up(&buf->vb.done);
+}
+
+/*
+ * Identify the buffer header type and properly handles
+ */
+static void em28xx_copy_video(struct em28xx *dev,
+                             struct em28xx_dmaqueue  *dma_q,
+                             struct em28xx_buffer *buf,
+                             unsigned char *p,
+                             unsigned char *outp, unsigned long len)
+{
+       void *fieldstart, *startwrite, *startread;
+       int  linesdone, currlinedone, offset, lencopy, remain;
+       int bytesperline = dev->width << 1;
+
+       if (dma_q->pos + len > buf->vb.size)
+               len = buf->vb.size - dma_q->pos;
+
+       startread = p;
+       remain = len;
+
+       if (dev->progressive)
+               fieldstart = outp;
+       else {
+               /* Interlaces two half frames */
+               if (buf->top_field)
+                       fieldstart = outp;
+               else
+                       fieldstart = outp + bytesperline;
+       }
+
+       linesdone = dma_q->pos / bytesperline;
+       currlinedone = dma_q->pos % bytesperline;
+
+       if (dev->progressive)
+               offset = linesdone * bytesperline + currlinedone;
+       else
+               offset = linesdone * bytesperline * 2 + currlinedone;
+
+       startwrite = fieldstart + offset;
+       lencopy = bytesperline - currlinedone;
+       lencopy = lencopy > remain ? remain : lencopy;
+
+       if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
+               em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
+                              ((char *)startwrite + lencopy) -
+                              ((char *)outp + buf->vb.size));
+               remain = (char *)outp + buf->vb.size - (char *)startwrite;
+               lencopy = remain;
+       }
+       if (lencopy <= 0)
+               return;
+       memcpy(startwrite, startread, lencopy);
+
+       remain -= lencopy;
+
+       while (remain > 0) {
+               startwrite += lencopy + bytesperline;
+               startread += lencopy;
+               if (bytesperline > remain)
+                       lencopy = remain;
+               else
+                       lencopy = bytesperline;
+
+               if ((char *)startwrite + lencopy > (char *)outp +
+                   buf->vb.size) {
+                       em28xx_isocdbg("Overflow of %zi bytes past buffer end"
+                                      "(2)\n",
+                                      ((char *)startwrite + lencopy) -
+                                      ((char *)outp + buf->vb.size));
+                       lencopy = remain = (char *)outp + buf->vb.size -
+                                          (char *)startwrite;
+               }
+               if (lencopy <= 0)
+                       break;
+
+               memcpy(startwrite, startread, lencopy);
+
+               remain -= lencopy;
+       }
+
+       dma_q->pos += len;
+}
+
+static void em28xx_copy_vbi(struct em28xx *dev,
+                             struct em28xx_dmaqueue  *dma_q,
+                             struct em28xx_buffer *buf,
+                             unsigned char *p,
+                             unsigned char *outp, unsigned long len)
+{
+       void *startwrite, *startread;
+       int  offset;
+       int bytesperline;
+
+       if (dev == NULL) {
+               em28xx_isocdbg("dev is null\n");
+               return;
+       }
+       bytesperline = dev->vbi_width;
+
+       if (dma_q == NULL) {
+               em28xx_isocdbg("dma_q is null\n");
+               return;
+       }
+       if (buf == NULL) {
+               return;
+       }
+       if (p == NULL) {
+               em28xx_isocdbg("p is null\n");
+               return;
+       }
+       if (outp == NULL) {
+               em28xx_isocdbg("outp is null\n");
+               return;
+       }
+
+       if (dma_q->pos + len > buf->vb.size)
+               len = buf->vb.size - dma_q->pos;
+
+       startread = p;
+
+       startwrite = outp + dma_q->pos;
+       offset = dma_q->pos;
+
+       /* Make sure the bottom field populates the second half of the frame */
+       if (buf->top_field == 0) {
+               startwrite += bytesperline * dev->vbi_height;
+               offset += bytesperline * dev->vbi_height;
+       }
+
+       memcpy(startwrite, startread, len);
+       dma_q->pos += len;
+}
+
+static inline void print_err_status(struct em28xx *dev,
+                                    int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+       if (packet < 0) {
+               em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
+       } else {
+               em28xx_isocdbg("URB packet %d, status %d [%s].\n",
+                              packet, status, errmsg);
+       }
+}
+
+/*
+ * video-buf generic routine to get the next available buffer
+ */
+static inline void get_next_buf(struct em28xx_dmaqueue *dma_q,
+                                         struct em28xx_buffer **buf)
+{
+       struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
+       char *outp;
+
+       if (list_empty(&dma_q->active)) {
+               em28xx_isocdbg("No active queue to serve\n");
+               dev->isoc_ctl.vid_buf = NULL;
+               *buf = NULL;
+               return;
+       }
+
+       /* Get the next buffer */
+       *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
+
+       /* Cleans up buffer - Useful for testing for frame/URB loss */
+       outp = videobuf_to_vmalloc(&(*buf)->vb);
+       memset(outp, 0, (*buf)->vb.size);
+
+       dev->isoc_ctl.vid_buf = *buf;
+
+       return;
+}
+
+/*
+ * video-buf generic routine to get the next available VBI buffer
+ */
+static inline void vbi_get_next_buf(struct em28xx_dmaqueue *dma_q,
+                                   struct em28xx_buffer **buf)
+{
+       struct em28xx *dev = container_of(dma_q, struct em28xx, vbiq);
+       char *outp;
+
+       if (list_empty(&dma_q->active)) {
+               em28xx_isocdbg("No active queue to serve\n");
+               dev->isoc_ctl.vbi_buf = NULL;
+               *buf = NULL;
+               return;
+       }
+
+       /* Get the next buffer */
+       *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
+       /* Cleans up buffer - Useful for testing for frame/URB loss */
+       outp = videobuf_to_vmalloc(&(*buf)->vb);
+       memset(outp, 0x00, (*buf)->vb.size);
+
+       dev->isoc_ctl.vbi_buf = *buf;
+
+       return;
+}
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
+{
+       struct em28xx_buffer    *buf;
+       struct em28xx_dmaqueue  *dma_q = &dev->vidq;
+       unsigned char *outp = NULL;
+       int i, len = 0, rc = 1;
+       unsigned char *p;
+
+       if (!dev)
+               return 0;
+
+       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+               return 0;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               if (urb->status == -ENOENT)
+                       return 0;
+       }
+
+       buf = dev->isoc_ctl.vid_buf;
+       if (buf != NULL)
+               outp = videobuf_to_vmalloc(&buf->vb);
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               int status = urb->iso_frame_desc[i].status;
+
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       if (urb->iso_frame_desc[i].status != -EPROTO)
+                               continue;
+               }
+
+               len = urb->iso_frame_desc[i].actual_length - 4;
+
+               if (urb->iso_frame_desc[i].actual_length <= 0) {
+                       /* em28xx_isocdbg("packet %d is empty",i); - spammy */
+                       continue;
+               }
+               if (urb->iso_frame_desc[i].actual_length >
+                                               dev->max_pkt_size) {
+                       em28xx_isocdbg("packet bigger than packet size");
+                       continue;
+               }
+
+               p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+
+               /* FIXME: incomplete buffer checks where removed to make
+                  logic simpler. Impacts of those changes should be evaluated
+                */
+               if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) {
+                       em28xx_isocdbg("VBI HEADER!!!\n");
+                       /* FIXME: Should add vbi copy */
+                       continue;
+               }
+               if (p[0] == 0x22 && p[1] == 0x5a) {
+                       em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
+                                      len, (p[2] & 1) ? "odd" : "even");
+
+                       if (dev->progressive || !(p[2] & 1)) {
+                               if (buf != NULL)
+                                       buffer_filled(dev, dma_q, buf);
+                               get_next_buf(dma_q, &buf);
+                               if (buf == NULL)
+                                       outp = NULL;
+                               else
+                                       outp = videobuf_to_vmalloc(&buf->vb);
+                       }
+
+                       if (buf != NULL) {
+                               if (p[2] & 1)
+                                       buf->top_field = 0;
+                               else
+                                       buf->top_field = 1;
+                       }
+
+                       dma_q->pos = 0;
+               }
+               if (buf != NULL) {
+                       if (p[0] != 0x88 && p[0] != 0x22) {
+                               em28xx_isocdbg("frame is not complete\n");
+                               len += 4;
+                       } else {
+                               p += 4;
+                       }
+                       em28xx_copy_video(dev, dma_q, buf, p, outp, len);
+               }
+       }
+       return rc;
+}
+
+/* Version of isoc handler that takes into account a mixture of video and
+   VBI data */
+static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb)
+{
+       struct em28xx_buffer    *buf, *vbi_buf;
+       struct em28xx_dmaqueue  *dma_q = &dev->vidq;
+       struct em28xx_dmaqueue  *vbi_dma_q = &dev->vbiq;
+       unsigned char *outp = NULL;
+       unsigned char *vbioutp = NULL;
+       int i, len = 0, rc = 1;
+       unsigned char *p;
+       int vbi_size;
+
+       if (!dev)
+               return 0;
+
+       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
+               return 0;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               if (urb->status == -ENOENT)
+                       return 0;
+       }
+
+       buf = dev->isoc_ctl.vid_buf;
+       if (buf != NULL)
+               outp = videobuf_to_vmalloc(&buf->vb);
+
+       vbi_buf = dev->isoc_ctl.vbi_buf;
+       if (vbi_buf != NULL)
+               vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               int status = urb->iso_frame_desc[i].status;
+
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       if (urb->iso_frame_desc[i].status != -EPROTO)
+                               continue;
+               }
+
+               len = urb->iso_frame_desc[i].actual_length;
+               if (urb->iso_frame_desc[i].actual_length <= 0) {
+                       /* em28xx_isocdbg("packet %d is empty",i); - spammy */
+                       continue;
+               }
+               if (urb->iso_frame_desc[i].actual_length >
+                                               dev->max_pkt_size) {
+                       em28xx_isocdbg("packet bigger than packet size");
+                       continue;
+               }
+
+               p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+
+               /* capture type 0 = vbi start
+                  capture type 1 = video start
+                  capture type 2 = video in progress */
+               if (p[0] == 0x33 && p[1] == 0x95) {
+                       dev->capture_type = 0;
+                       dev->vbi_read = 0;
+                       em28xx_isocdbg("VBI START HEADER!!!\n");
+                       dev->cur_field = p[2];
+                       p += 4;
+                       len -= 4;
+               } else if (p[0] == 0x88 && p[1] == 0x88 &&
+                          p[2] == 0x88 && p[3] == 0x88) {
+                       /* continuation */
+                       p += 4;
+                       len -= 4;
+               } else if (p[0] == 0x22 && p[1] == 0x5a) {
+                       /* start video */
+                       p += 4;
+                       len -= 4;
+               }
+
+               vbi_size = dev->vbi_width * dev->vbi_height;
+
+               if (dev->capture_type == 0) {
+                       if (dev->vbi_read >= vbi_size) {
+                               /* We've already read all the VBI data, so
+                                  treat the rest as video */
+                               em28xx_isocdbg("dev->vbi_read > vbi_size\n");
+                       } else if ((dev->vbi_read + len) < vbi_size) {
+                               /* This entire frame is VBI data */
+                               if (dev->vbi_read == 0 &&
+                                   (!(dev->cur_field & 1))) {
+                                       /* Brand new frame */
+                                       if (vbi_buf != NULL)
+                                               vbi_buffer_filled(dev,
+                                                                 vbi_dma_q,
+                                                                 vbi_buf);
+                                       vbi_get_next_buf(vbi_dma_q, &vbi_buf);
+                                       if (vbi_buf == NULL)
+                                               vbioutp = NULL;
+                                       else
+                                               vbioutp = videobuf_to_vmalloc(
+                                                       &vbi_buf->vb);
+                               }
+
+                               if (dev->vbi_read == 0) {
+                                       vbi_dma_q->pos = 0;
+                                       if (vbi_buf != NULL) {
+                                               if (dev->cur_field & 1)
+                                                       vbi_buf->top_field = 0;
+                                               else
+                                                       vbi_buf->top_field = 1;
+                                       }
+                               }
+
+                               dev->vbi_read += len;
+                               em28xx_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
+                                               vbioutp, len);
+                       } else {
+                               /* Some of this frame is VBI data and some is
+                                  video data */
+                               int vbi_data_len = vbi_size - dev->vbi_read;
+                               dev->vbi_read += vbi_data_len;
+                               em28xx_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
+                                               vbioutp, vbi_data_len);
+                               dev->capture_type = 1;
+                               p += vbi_data_len;
+                               len -= vbi_data_len;
+                       }
+               }
+
+               if (dev->capture_type == 1) {
+                       dev->capture_type = 2;
+                       if (dev->progressive || !(dev->cur_field & 1)) {
+                               if (buf != NULL)
+                                       buffer_filled(dev, dma_q, buf);
+                               get_next_buf(dma_q, &buf);
+                               if (buf == NULL)
+                                       outp = NULL;
+                               else
+                                       outp = videobuf_to_vmalloc(&buf->vb);
+                       }
+                       if (buf != NULL) {
+                               if (dev->cur_field & 1)
+                                       buf->top_field = 0;
+                               else
+                                       buf->top_field = 1;
+                       }
+
+                       dma_q->pos = 0;
+               }
+
+               if (buf != NULL && dev->capture_type == 2) {
+                       if (len >= 4 && p[0] == 0x88 && p[1] == 0x88 &&
+                           p[2] == 0x88 && p[3] == 0x88) {
+                               p += 4;
+                               len -= 4;
+                       }
+                       if (len >= 4 && p[0] == 0x22 && p[1] == 0x5a) {
+                               em28xx_isocdbg("Video frame %d, len=%i, %s\n",
+                                              p[2], len, (p[2] & 1) ?
+                                              "odd" : "even");
+                               p += 4;
+                               len -= 4;
+                       }
+
+                       if (len > 0)
+                               em28xx_copy_video(dev, dma_q, buf, p, outp,
+                                                 len);
+               }
+       }
+       return rc;
+}
+
+
+/* ------------------------------------------------------------------
+       Videobuf operations
+   ------------------------------------------------------------------*/
+
+static int
+buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
+{
+       struct em28xx_fh *fh = vq->priv_data;
+       struct em28xx        *dev = fh->dev;
+       struct v4l2_frequency f;
+
+       *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7)
+               >> 3;
+
+       if (0 == *count)
+               *count = EM28XX_DEF_BUF;
+
+       if (*count < EM28XX_MIN_BUF)
+               *count = EM28XX_MIN_BUF;
+
+       /* Ask tuner to go to analog or radio mode */
+       memset(&f, 0, sizeof(f));
+       f.frequency = dev->ctl_freq;
+       f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
+
+       return 0;
+}
+
+/* This is called *without* dev->slock held; please keep it that way */
+static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
+{
+       struct em28xx_fh     *fh  = vq->priv_data;
+       struct em28xx        *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.vid_buf == buf)
+               dev->isoc_ctl.vid_buf = NULL;
+       spin_unlock_irqrestore(&dev->slock, flags);
+
+       videobuf_vmalloc_free(&buf->vb);
+       buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+                                               enum v4l2_field field)
+{
+       struct em28xx_fh     *fh  = vq->priv_data;
+       struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
+       struct em28xx        *dev = fh->dev;
+       int                  rc = 0, urb_init = 0;
+
+       buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth
+                       + 7) >> 3;
+
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+               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)
+                       goto fail;
+       }
+
+       if (!dev->isoc_ctl.analog_bufs.num_bufs)
+               urb_init = 1;
+
+       if (urb_init) {
+               if (em28xx_vbi_supported(dev) == 1)
+                       rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE,
+                                             EM28XX_NUM_PACKETS,
+                                             EM28XX_NUM_BUFS,
+                                             dev->max_pkt_size,
+                                             em28xx_isoc_copy_vbi);
+               else
+                       rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE,
+                                             EM28XX_NUM_PACKETS,
+                                             EM28XX_NUM_BUFS,
+                                             dev->max_pkt_size,
+                                             em28xx_isoc_copy);
+               if (rc < 0)
+                       goto fail;
+       }
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+fail:
+       free_buffer(vq, buf);
+       return rc;
+}
+
+static void
+buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct em28xx_buffer    *buf     = container_of(vb,
+                                                       struct em28xx_buffer,
+                                                       vb);
+       struct em28xx_fh        *fh      = vq->priv_data;
+       struct em28xx           *dev     = fh->dev;
+       struct em28xx_dmaqueue  *vidq    = &dev->vidq;
+
+       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 em28xx_buffer   *buf  = container_of(vb,
+                                                   struct em28xx_buffer,
+                                                   vb);
+       struct em28xx_fh       *fh   = vq->priv_data;
+       struct em28xx          *dev  = (struct em28xx *)fh->dev;
+
+       em28xx_isocdbg("em28xx: called buffer_release\n");
+
+       free_buffer(vq, buf);
+}
+
+static struct videobuf_queue_ops em28xx_video_qops = {
+       .buf_setup      = buffer_setup,
+       .buf_prepare    = buffer_prepare,
+       .buf_queue      = buffer_queue,
+       .buf_release    = buffer_release,
+};
+
+/*********************  v4l2 interface  **************************************/
+
+static void video_mux(struct em28xx *dev, int index)
+{
+       dev->ctl_input = index;
+       dev->ctl_ainput = INPUT(index)->amux;
+       dev->ctl_aoutput = INPUT(index)->aout;
+
+       if (!dev->ctl_aoutput)
+               dev->ctl_aoutput = EM28XX_AOUT_MASTER;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
+                       INPUT(index)->vmux, 0, 0);
+
+       if (dev->board.has_msp34xx) {
+               if (dev->i2s_speed) {
+                       v4l2_device_call_all(&dev->v4l2_dev, 0, audio,
+                               s_i2s_clock_freq, dev->i2s_speed);
+               }
+               /* Note: this is msp3400 specific */
+               v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
+                        dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
+       }
+
+       if (dev->board.adecoder != EM28XX_NOADECODER) {
+               v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
+                       dev->ctl_ainput, dev->ctl_aoutput, 0);
+       }
+
+       em28xx_audio_analog_set(dev);
+}
+
+/* Usage lock check functions */
+static int res_get(struct em28xx_fh *fh, unsigned int bit)
+{
+       struct em28xx    *dev = fh->dev;
+
+       if (fh->resources & bit)
+               /* have it already allocated */
+               return 1;
+
+       /* is it free? */
+       if (dev->resources & bit) {
+               /* no, someone else uses it */
+               return 0;
+       }
+       /* it's free, grab it */
+       fh->resources  |= bit;
+       dev->resources |= bit;
+       em28xx_videodbg("res: get %d\n", bit);
+       return 1;
+}
+
+static int res_check(struct em28xx_fh *fh, unsigned int bit)
+{
+       return fh->resources & bit;
+}
+
+static int res_locked(struct em28xx *dev, unsigned int bit)
+{
+       return dev->resources & bit;
+}
+
+static void res_free(struct em28xx_fh *fh, unsigned int bits)
+{
+       struct em28xx    *dev = fh->dev;
+
+       BUG_ON((fh->resources & bits) != bits);
+
+       fh->resources  &= ~bits;
+       dev->resources &= ~bits;
+       em28xx_videodbg("res: put %d\n", bits);
+}
+
+static int get_ressource(struct em28xx_fh *fh)
+{
+       switch (fh->type) {
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               return EM28XX_RESOURCE_VIDEO;
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               return EM28XX_RESOURCE_VBI;
+       default:
+               BUG();
+               return 0;
+       }
+}
+
+/*
+ * ac97_queryctrl()
+ * return the ac97 supported controls
+ */
+static int ac97_queryctrl(struct v4l2_queryctrl *qc)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) {
+               if (qc->id && qc->id == ac97_qctrl[i].id) {
+                       memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc));
+                       return 0;
+               }
+       }
+
+       /* Control is not ac97 related */
+       return 1;
+}
+
+/*
+ * ac97_get_ctrl()
+ * return the current values for ac97 mute and volume
+ */
+static int ac97_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_AUDIO_MUTE:
+               ctrl->value = dev->mute;
+               return 0;
+       case V4L2_CID_AUDIO_VOLUME:
+               ctrl->value = dev->volume;
+               return 0;
+       default:
+               /* Control is not ac97 related */
+               return 1;
+       }
+}
+
+/*
+ * ac97_set_ctrl()
+ * set values for ac97 mute and volume
+ */
+static int ac97_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++)
+               if (ctrl->id == ac97_qctrl[i].id)
+                       goto handle;
+
+       /* Announce that hasn't handle it */
+       return 1;
+
+handle:
+       if (ctrl->value < ac97_qctrl[i].minimum ||
+           ctrl->value > ac97_qctrl[i].maximum)
+               return -ERANGE;
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUDIO_MUTE:
+               dev->mute = ctrl->value;
+               break;
+       case V4L2_CID_AUDIO_VOLUME:
+               dev->volume = ctrl->value;
+               break;
+       }
+
+       return em28xx_audio_analog_set(dev);
+}
+
+static int check_dev(struct em28xx *dev)
+{
+       if (dev->state & DEV_DISCONNECTED) {
+               em28xx_errdev("v4l2 ioctl: device not present\n");
+               return -ENODEV;
+       }
+
+       if (dev->state & DEV_MISCONFIGURED) {
+               em28xx_errdev("v4l2 ioctl: device is misconfigured; "
+                             "close and open it again\n");
+               return -EIO;
+       }
+       return 0;
+}
+
+static void get_scale(struct em28xx *dev,
+                       unsigned int width, unsigned int height,
+                       unsigned int *hscale, unsigned int *vscale)
+{
+       unsigned int          maxw = norm_maxw(dev);
+       unsigned int          maxh = norm_maxh(dev);
+
+       *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
+       if (*hscale >= 0x4000)
+               *hscale = 0x3fff;
+
+       *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
+       if (*vscale >= 0x4000)
+               *vscale = 0x3fff;
+}
+
+/* ------------------------------------------------------------------
+       IOCTL vidioc handling
+   ------------------------------------------------------------------*/
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+
+       f->fmt.pix.width = dev->width;
+       f->fmt.pix.height = dev->height;
+       f->fmt.pix.pixelformat = dev->format->fourcc;
+       f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;
+       f->fmt.pix.sizeimage = f->fmt.pix.bytesperline  * dev->height;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+       /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
+       if (dev->progressive)
+               f->fmt.pix.field = V4L2_FIELD_NONE;
+       else
+               f->fmt.pix.field = dev->interlaced ?
+                          V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
+       return 0;
+}
+
+static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(format); i++)
+               if (format[i].fourcc == fourcc)
+                       return &format[i];
+
+       return NULL;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                       struct v4l2_format *f)
+{
+       struct em28xx_fh      *fh    = priv;
+       struct em28xx         *dev   = fh->dev;
+       unsigned int          width  = f->fmt.pix.width;
+       unsigned int          height = f->fmt.pix.height;
+       unsigned int          maxw   = norm_maxw(dev);
+       unsigned int          maxh   = norm_maxh(dev);
+       unsigned int          hscale, vscale;
+       struct em28xx_fmt     *fmt;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       if (!fmt) {
+               em28xx_videodbg("Fourcc format (%08x) invalid.\n",
+                               f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       if (dev->board.is_em2800) {
+               /* the em2800 can only scale down to 50% */
+               height = height > (3 * maxh / 4) ? maxh : maxh / 2;
+               width = width > (3 * maxw / 4) ? maxw : maxw / 2;
+                /* MaxPacketSize for em2800 is too small to capture at full resolution
+                 * use half of maxw as the scaler can only scale to 50% */
+               if (width == maxw && height == maxh)
+                       width /= 2;
+       } else {
+               /* width must even because of the YUYV format
+                  height must be even because of interlacing */
+               v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
+                                     1, 0);
+       }
+
+       get_scale(dev, width, height, &hscale, &vscale);
+
+       width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
+       height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
+
+       f->fmt.pix.width = width;
+       f->fmt.pix.height = height;
+       f->fmt.pix.pixelformat = fmt->fourcc;
+       f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3;
+       f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+       if (dev->progressive)
+               f->fmt.pix.field = V4L2_FIELD_NONE;
+       else
+               f->fmt.pix.field = dev->interlaced ?
+                          V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
+
+       return 0;
+}
+
+static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
+                                  unsigned width, unsigned height)
+{
+       struct em28xx_fmt     *fmt;
+
+       fmt = format_by_fourcc(fourcc);
+       if (!fmt)
+               return -EINVAL;
+
+       dev->format = fmt;
+       dev->width  = width;
+       dev->height = height;
+
+       /* set new image size */
+       get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
+
+       em28xx_set_alternate(dev);
+       em28xx_resolution_set(dev);
+
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                       struct v4l2_format *f)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       vidioc_try_fmt_vid_cap(file, priv, f);
+
+       if (videobuf_queue_is_busy(&fh->vb_vidq)) {
+               em28xx_errdev("%s queue busy\n", __func__);
+               return -EBUSY;
+       }
+
+       return em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
+                               f->fmt.pix.width, f->fmt.pix.height);
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       struct em28xx_fh   *fh  = priv;
+       struct em28xx      *dev = fh->dev;
+       int                rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       *norm = dev->norm;
+
+       return 0;
+}
+
+static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       struct em28xx_fh   *fh  = priv;
+       struct em28xx      *dev = fh->dev;
+       int                rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm);
+
+       return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       struct em28xx_fh   *fh  = priv;
+       struct em28xx      *dev = fh->dev;
+       struct v4l2_format f;
+       int                rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       dev->norm = *norm;
+
+       /* Adjusts width/height, if needed */
+       f.fmt.pix.width = dev->width;
+       f.fmt.pix.height = dev->height;
+       vidioc_try_fmt_vid_cap(file, priv, &f);
+
+       /* set new image size */
+       dev->width = f.fmt.pix.width;
+       dev->height = f.fmt.pix.height;
+       get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
+
+       em28xx_resolution_set(dev);
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
+
+       return 0;
+}
+
+static int vidioc_g_parm(struct file *file, void *priv,
+                        struct v4l2_streamparm *p)
+{
+       struct em28xx_fh   *fh  = priv;
+       struct em28xx      *dev = fh->dev;
+       int rc = 0;
+
+       if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (dev->board.is_webcam)
+               rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0,
+                                               video, g_parm, p);
+       else
+               v4l2_video_std_frame_period(dev->norm,
+                                                &p->parm.capture.timeperframe);
+
+       return rc;
+}
+
+static int vidioc_s_parm(struct file *file, void *priv,
+                        struct v4l2_streamparm *p)
+{
+       struct em28xx_fh   *fh  = priv;
+       struct em28xx      *dev = fh->dev;
+
+       if (!dev->board.is_webcam)
+               return -EINVAL;
+
+       if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       return v4l2_device_call_until_err(&dev->v4l2_dev, 0, video, s_parm, p);
+}
+
+static const char *iname[] = {
+       [EM28XX_VMUX_COMPOSITE1] = "Composite1",
+       [EM28XX_VMUX_COMPOSITE2] = "Composite2",
+       [EM28XX_VMUX_COMPOSITE3] = "Composite3",
+       [EM28XX_VMUX_COMPOSITE4] = "Composite4",
+       [EM28XX_VMUX_SVIDEO]     = "S-Video",
+       [EM28XX_VMUX_TELEVISION] = "Television",
+       [EM28XX_VMUX_CABLE]      = "Cable TV",
+       [EM28XX_VMUX_DVB]        = "DVB",
+       [EM28XX_VMUX_DEBUG]      = "for debug only",
+};
+
+static int vidioc_enum_input(struct file *file, void *priv,
+                               struct v4l2_input *i)
+{
+       struct em28xx_fh   *fh  = priv;
+       struct em28xx      *dev = fh->dev;
+       unsigned int       n;
+
+       n = i->index;
+       if (n >= MAX_EM28XX_INPUT)
+               return -EINVAL;
+       if (0 == INPUT(n)->type)
+               return -EINVAL;
+
+       i->index = n;
+       i->type = V4L2_INPUT_TYPE_CAMERA;
+
+       strcpy(i->name, iname[INPUT(n)->type]);
+
+       if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
+               (EM28XX_VMUX_CABLE == INPUT(n)->type))
+               i->type = V4L2_INPUT_TYPE_TUNER;
+
+       i->std = dev->vdev->tvnorms;
+
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct em28xx_fh   *fh  = priv;
+       struct em28xx      *dev = fh->dev;
+
+       *i = dev->ctl_input;
+
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       struct em28xx_fh   *fh  = priv;
+       struct em28xx      *dev = fh->dev;
+       int                rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (i >= MAX_EM28XX_INPUT)
+               return -EINVAL;
+       if (0 == INPUT(i)->type)
+               return -EINVAL;
+
+       video_mux(dev, i);
+       return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+       struct em28xx_fh   *fh    = priv;
+       struct em28xx      *dev   = fh->dev;
+
+       if (!dev->audio_mode.has_audio)
+               return -EINVAL;
+
+       switch (a->index) {
+       case EM28XX_AMUX_VIDEO:
+               strcpy(a->name, "Television");
+               break;
+       case EM28XX_AMUX_LINE_IN:
+               strcpy(a->name, "Line In");
+               break;
+       case EM28XX_AMUX_VIDEO2:
+               strcpy(a->name, "Television alt");
+               break;
+       case EM28XX_AMUX_PHONE:
+               strcpy(a->name, "Phone");
+               break;
+       case EM28XX_AMUX_MIC:
+               strcpy(a->name, "Mic");
+               break;
+       case EM28XX_AMUX_CD:
+               strcpy(a->name, "CD");
+               break;
+       case EM28XX_AMUX_AUX:
+               strcpy(a->name, "Aux");
+               break;
+       case EM28XX_AMUX_PCM_OUT:
+               strcpy(a->name, "PCM");
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       a->index = dev->ctl_ainput;
+       a->capability = V4L2_AUDCAP_STEREO;
+
+       return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+       struct em28xx_fh   *fh  = priv;
+       struct em28xx      *dev = fh->dev;
+
+
+       if (!dev->audio_mode.has_audio)
+               return -EINVAL;
+
+       if (a->index >= MAX_EM28XX_INPUT)
+               return -EINVAL;
+       if (0 == INPUT(a->index)->type)
+               return -EINVAL;
+
+       dev->ctl_ainput = INPUT(a->index)->amux;
+       dev->ctl_aoutput = INPUT(a->index)->aout;
+
+       if (!dev->ctl_aoutput)
+               dev->ctl_aoutput = EM28XX_AOUT_MASTER;
+
+       return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+                               struct v4l2_queryctrl *qc)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   id  = qc->id;
+       int                   rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       memset(qc, 0, sizeof(*qc));
+
+       qc->id = id;
+
+       /* enumerate AC97 controls */
+       if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
+               rc = ac97_queryctrl(qc);
+               if (!rc)
+                       return 0;
+       }
+
+       /* enumerate V4L2 device controls */
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
+
+       if (qc->type)
+               return 0;
+       else
+               return -EINVAL;
+}
+
+/*
+ * FIXME: This is an indirect way to check if a control exists at a
+ * subdev. Instead of that hack, maybe the better would be to change all
+ * subdevs to return -ENOIOCTLCMD, if an ioctl is not supported.
+ */
+static int check_subdev_ctrl(struct em28xx *dev, int id)
+{
+       struct v4l2_queryctrl qc;
+
+       memset(&qc, 0, sizeof(qc));
+       qc.id = id;
+
+       /* enumerate V4L2 device controls */
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, &qc);
+
+       if (qc.type)
+               return 0;
+       else
+               return -EINVAL;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctrl)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+       rc = 0;
+
+       /* Set an AC97 control */
+       if (dev->audio_mode.ac97 != EM28XX_NO_AC97)
+               rc = ac97_get_ctrl(dev, ctrl);
+       else
+               rc = 1;
+
+       /* It were not an AC97 control. Sends it to the v4l2 dev interface */
+       if (rc == 1) {
+               if (check_subdev_ctrl(dev, ctrl->id))
+                       return -EINVAL;
+
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
+               rc = 0;
+       }
+
+       return rc;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctrl)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       /* Set an AC97 control */
+       if (dev->audio_mode.ac97 != EM28XX_NO_AC97)
+               rc = ac97_set_ctrl(dev, ctrl);
+       else
+               rc = 1;
+
+       /* It isn't an AC97 control. Sends it to the v4l2 dev interface */
+       if (rc == 1) {
+               rc = check_subdev_ctrl(dev, ctrl->id);
+               if (!rc)
+                       v4l2_device_call_all(&dev->v4l2_dev, 0,
+                                            core, s_ctrl, ctrl);
+               /*
+                * In the case of non-AC97 volume controls, we still need
+                * to do some setups at em28xx, in order to mute/unmute
+                * and to adjust audio volume. However, the value ranges
+                * should be checked by the corresponding V4L subdriver.
+                */
+               switch (ctrl->id) {
+               case V4L2_CID_AUDIO_MUTE:
+                       dev->mute = ctrl->value;
+                       rc = em28xx_audio_analog_set(dev);
+                       break;
+               case V4L2_CID_AUDIO_VOLUME:
+                       dev->volume = ctrl->value;
+                       rc = em28xx_audio_analog_set(dev);
+               }
+       }
+       return (rc < 0) ? rc : 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (0 != t->index)
+               return -EINVAL;
+
+       strcpy(t->name, "Tuner");
+       t->type = V4L2_TUNER_ANALOG_TV;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
+       return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (0 != t->index)
+               return -EINVAL;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
+       return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+
+       f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+       f->frequency = dev->ctl_freq;
+       return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (0 != f->tuner)
+               return -EINVAL;
+
+       if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
+               return -EINVAL;
+       if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
+               return -EINVAL;
+
+       dev->ctl_freq = f->frequency;
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f);
+
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int em28xx_reg_len(int reg)
+{
+       switch (reg) {
+       case EM28XX_R40_AC97LSB:
+       case EM28XX_R30_HSCALELOW:
+       case EM28XX_R32_VSCALELOW:
+               return 2;
+       default:
+               return 1;
+       }
+}
+
+static int vidioc_g_chip_ident(struct file *file, void *priv,
+              struct v4l2_dbg_chip_ident *chip)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+
+       chip->ident = V4L2_IDENT_NONE;
+       chip->revision = 0;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
+
+       return 0;
+}
+
+
+static int vidioc_g_register(struct file *file, void *priv,
+                            struct v4l2_dbg_register *reg)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int ret;
+
+       switch (reg->match.type) {
+       case V4L2_CHIP_MATCH_AC97:
+               ret = em28xx_read_ac97(dev, reg->reg);
+               if (ret < 0)
+                       return ret;
+
+               reg->val = ret;
+               reg->size = 1;
+               return 0;
+       case V4L2_CHIP_MATCH_I2C_DRIVER:
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
+               return 0;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               /* TODO: is this correct? */
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
+               return 0;
+       default:
+               if (!v4l2_chip_match_host(&reg->match))
+                       return -EINVAL;
+       }
+
+       /* Match host */
+       reg->size = em28xx_reg_len(reg->reg);
+       if (reg->size == 1) {
+               ret = em28xx_read_reg(dev, reg->reg);
+
+               if (ret < 0)
+                       return ret;
+
+               reg->val = ret;
+       } else {
+               __le16 val = 0;
+               ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
+                                                  reg->reg, (char *)&val, 2);
+               if (ret < 0)
+                       return ret;
+
+               reg->val = le16_to_cpu(val);
+       }
+
+       return 0;
+}
+
+static int vidioc_s_register(struct file *file, void *priv,
+                            struct v4l2_dbg_register *reg)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       __le16 buf;
+
+       switch (reg->match.type) {
+       case V4L2_CHIP_MATCH_AC97:
+               return em28xx_write_ac97(dev, reg->reg, reg->val);
+       case V4L2_CHIP_MATCH_I2C_DRIVER:
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
+               return 0;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               /* TODO: is this correct? */
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
+               return 0;
+       default:
+               if (!v4l2_chip_match_host(&reg->match))
+                       return -EINVAL;
+       }
+
+       /* Match host */
+       buf = cpu_to_le16(reg->val);
+
+       return em28xx_write_regs(dev, reg->reg, (char *)&buf,
+                              em28xx_reg_len(reg->reg));
+}
+#endif
+
+
+static int vidioc_cropcap(struct file *file, void *priv,
+                                       struct v4l2_cropcap *cc)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+
+       if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       cc->bounds.left = 0;
+       cc->bounds.top = 0;
+       cc->bounds.width = dev->width;
+       cc->bounds.height = dev->height;
+       cc->defrect = cc->bounds;
+       cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */
+       cc->pixelaspect.denominator = 59;
+
+       return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv,
+                                       enum v4l2_buf_type type)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   rc = -EINVAL;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (unlikely(type != fh->type))
+               return -EINVAL;
+
+       em28xx_videodbg("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;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               rc = videobuf_streamon(&fh->vb_vidq);
+       else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+               rc = videobuf_streamon(&fh->vb_vbiq);
+
+       return rc;
+}
+
+static int vidioc_streamoff(struct file *file, void *priv,
+                                       enum v4l2_buf_type type)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   rc;
+
+       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;
+
+       em28xx_videodbg("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) {
+               if (res_check(fh, EM28XX_RESOURCE_VIDEO)) {
+                       videobuf_streamoff(&fh->vb_vidq);
+                       res_free(fh, EM28XX_RESOURCE_VIDEO);
+               }
+       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+               if (res_check(fh, EM28XX_RESOURCE_VBI)) {
+                       videobuf_streamoff(&fh->vb_vbiq);
+                       res_free(fh, EM28XX_RESOURCE_VBI);
+               }
+       }
+
+       return 0;
+}
+
+static int vidioc_querycap(struct file *file, void  *priv,
+                                       struct v4l2_capability *cap)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+
+       strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
+       strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
+       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
+
+       cap->capabilities =
+                       V4L2_CAP_SLICED_VBI_CAPTURE |
+                       V4L2_CAP_VIDEO_CAPTURE |
+                       V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
+
+       if (dev->vbi_dev)
+               cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
+
+       if (dev->audio_mode.has_audio)
+               cap->capabilities |= V4L2_CAP_AUDIO;
+
+       if (dev->tuner_type != TUNER_ABSENT)
+               cap->capabilities |= V4L2_CAP_TUNER;
+
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       if (unlikely(f->index >= ARRAY_SIZE(format)))
+               return -EINVAL;
+
+       strlcpy(f->description, format[f->index].name, sizeof(f->description));
+       f->pixelformat = format[f->index].fourcc;
+
+       return 0;
+}
+
+static int vidioc_enum_framesizes(struct file *file, void *priv,
+                                 struct v4l2_frmsizeenum *fsize)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       struct em28xx_fmt     *fmt;
+       unsigned int          maxw = norm_maxw(dev);
+       unsigned int          maxh = norm_maxh(dev);
+
+       fmt = format_by_fourcc(fsize->pixel_format);
+       if (!fmt) {
+               em28xx_videodbg("Fourcc format (%08x) invalid.\n",
+                               fsize->pixel_format);
+               return -EINVAL;
+       }
+
+       if (dev->board.is_em2800) {
+               if (fsize->index > 1)
+                       return -EINVAL;
+               fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+               fsize->discrete.width = maxw / (1 + fsize->index);
+               fsize->discrete.height = maxh / (1 + fsize->index);
+               return 0;
+       }
+
+       if (fsize->index != 0)
+               return -EINVAL;
+
+       /* Report a continuous range */
+       fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+       fsize->stepwise.min_width = 48;
+       fsize->stepwise.min_height = 32;
+       fsize->stepwise.max_width = maxw;
+       fsize->stepwise.max_height = maxh;
+       fsize->stepwise.step_width = 1;
+       fsize->stepwise.step_height = 1;
+       return 0;
+}
+
+/* Sliced VBI ioctls */
+static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       f->fmt.sliced.service_set = 0;
+       v4l2_device_call_all(&dev->v4l2_dev, 0, vbi, g_sliced_fmt, &f->fmt.sliced);
+
+       if (f->fmt.sliced.service_set == 0)
+               rc = -EINVAL;
+
+       return rc;
+}
+
+static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
+                       struct v4l2_format *f)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, vbi, g_sliced_fmt, &f->fmt.sliced);
+
+       if (f->fmt.sliced.service_set == 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+/* RAW VBI ioctls */
+
+static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
+                               struct v4l2_format *format)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+
+       format->fmt.vbi.samples_per_line = dev->vbi_width;
+       format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+       format->fmt.vbi.offset = 0;
+       format->fmt.vbi.flags = 0;
+       format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
+       format->fmt.vbi.count[0] = dev->vbi_height;
+       format->fmt.vbi.count[1] = dev->vbi_height;
+
+       /* Varies by video standard (NTSC, PAL, etc.) */
+       if (dev->norm & V4L2_STD_525_60) {
+               /* NTSC */
+               format->fmt.vbi.start[0] = 10;
+               format->fmt.vbi.start[1] = 273;
+       } else if (dev->norm & V4L2_STD_625_50) {
+               /* PAL */
+               format->fmt.vbi.start[0] = 6;
+               format->fmt.vbi.start[1] = 318;
+       }
+
+       return 0;
+}
+
+static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv,
+                               struct v4l2_format *format)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+
+       format->fmt.vbi.samples_per_line = dev->vbi_width;
+       format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
+       format->fmt.vbi.offset = 0;
+       format->fmt.vbi.flags = 0;
+       format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
+       format->fmt.vbi.count[0] = dev->vbi_height;
+       format->fmt.vbi.count[1] = dev->vbi_height;
+
+       /* Varies by video standard (NTSC, PAL, etc.) */
+       if (dev->norm & V4L2_STD_525_60) {
+               /* NTSC */
+               format->fmt.vbi.start[0] = 10;
+               format->fmt.vbi.start[1] = 273;
+       } else if (dev->norm & V4L2_STD_625_50) {
+               /* PAL */
+               format->fmt.vbi.start[0] = 6;
+               format->fmt.vbi.start[1] = 318;
+       }
+
+       return 0;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *rb)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return videobuf_reqbufs(&fh->vb_vidq, rb);
+       else
+               return videobuf_reqbufs(&fh->vb_vbiq, rb);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+                          struct v4l2_buffer *b)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return videobuf_querybuf(&fh->vb_vidq, b);
+       else {
+               /* FIXME: I'm not sure yet whether this is a bug in zvbi or
+                  the videobuf framework, but we probably shouldn't be
+                  returning a buffer larger than that which was asked for.
+                  At a minimum, it causes a crash in zvbi since it does
+                  a memcpy based on the source buffer length */
+               int result = videobuf_querybuf(&fh->vb_vbiq, b);
+               b->length = dev->vbi_width * dev->vbi_height * 2;
+
+               return result;
+       }
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return videobuf_qbuf(&fh->vb_vidq, b);
+       else
+               return videobuf_qbuf(&fh->vb_vbiq, b);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
+{
+       struct em28xx_fh      *fh  = priv;
+       struct em28xx         *dev = fh->dev;
+       int                   rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags &
+                                     O_NONBLOCK);
+       else
+               return videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags &
+                                     O_NONBLOCK);
+}
+
+/* ----------------------------------------------------------- */
+/* RADIO ESPECIFIC IOCTLS                                      */
+/* ----------------------------------------------------------- */
+
+static int radio_querycap(struct file *file, void  *priv,
+                         struct v4l2_capability *cap)
+{
+       struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
+
+       strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
+       strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
+       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
+
+       cap->capabilities = V4L2_CAP_TUNER;
+       return 0;
+}
+
+static int radio_g_tuner(struct file *file, void *priv,
+                        struct v4l2_tuner *t)
+{
+       struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
+
+       if (unlikely(t->index > 0))
+               return -EINVAL;
+
+       strcpy(t->name, "Radio");
+       t->type = V4L2_TUNER_RADIO;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
+
+       return 0;
+}
+
+static int radio_enum_input(struct file *file, void *priv,
+                           struct v4l2_input *i)
+{
+       if (i->index != 0)
+               return -EINVAL;
+       strcpy(i->name, "Radio");
+       i->type = V4L2_INPUT_TYPE_TUNER;
+
+       return 0;
+}
+
+static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+       if (unlikely(a->index))
+               return -EINVAL;
+
+       strcpy(a->name, "Radio");
+       return 0;
+}
+
+static int radio_s_tuner(struct file *file, void *priv,
+                        struct v4l2_tuner *t)
+{
+       struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
+
+       if (0 != t->index)
+               return -EINVAL;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
+
+       return 0;
+}
+
+static int radio_s_audio(struct file *file, void *fh,
+                        struct v4l2_audio *a)
+{
+       return 0;
+}
+
+static int radio_s_input(struct file *file, void *fh, unsigned int i)
+{
+       return 0;
+}
+
+static int radio_queryctrl(struct file *file, void *priv,
+                          struct v4l2_queryctrl *qc)
+{
+       int i;
+
+       if (qc->id <  V4L2_CID_BASE ||
+               qc->id >= V4L2_CID_LASTP1)
+               return -EINVAL;
+
+       for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) {
+               if (qc->id && qc->id == ac97_qctrl[i].id) {
+                       memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc));
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+/*
+ * em28xx_v4l2_open()
+ * inits the device and starts isoc transfer
+ */
+static int em28xx_v4l2_open(struct file *filp)
+{
+       int errCode = 0, radio = 0;
+       struct video_device *vdev = video_devdata(filp);
+       struct em28xx *dev = video_drvdata(filp);
+       enum v4l2_buf_type fh_type = 0;
+       struct em28xx_fh *fh;
+       enum v4l2_field field;
+
+       switch (vdev->vfl_type) {
+       case VFL_TYPE_GRABBER:
+               fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               break;
+       case VFL_TYPE_VBI:
+               fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
+               break;
+       case VFL_TYPE_RADIO:
+               radio = 1;
+               break;
+       }
+
+       em28xx_videodbg("open dev=%s type=%s users=%d\n",
+                       video_device_node_name(vdev), v4l2_type_names[fh_type],
+                       dev->users);
+
+
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
+       fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
+       if (!fh) {
+               em28xx_errdev("em28xx-video.c: Out of memory?!\n");
+               mutex_unlock(&dev->lock);
+               return -ENOMEM;
+       }
+       fh->dev = dev;
+       fh->radio = radio;
+       fh->type = fh_type;
+       filp->private_data = fh;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
+               em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
+               em28xx_set_alternate(dev);
+               em28xx_resolution_set(dev);
+
+               /* Needed, since GPIO might have disabled power of
+                  some i2c device
+                */
+               em28xx_wake_i2c(dev);
+
+       }
+       if (fh->radio) {
+               em28xx_videodbg("video_open: setting radio device\n");
+               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio);
+       }
+
+       dev->users++;
+
+       if (dev->progressive)
+               field = V4L2_FIELD_NONE;
+       else
+               field = V4L2_FIELD_INTERLACED;
+
+       videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
+                                   NULL, &dev->slock,
+                                   V4L2_BUF_TYPE_VIDEO_CAPTURE, field,
+                                   sizeof(struct em28xx_buffer), fh, &dev->lock);
+
+       videobuf_queue_vmalloc_init(&fh->vb_vbiq, &em28xx_vbi_qops,
+                                   NULL, &dev->slock,
+                                   V4L2_BUF_TYPE_VBI_CAPTURE,
+                                   V4L2_FIELD_SEQ_TB,
+                                   sizeof(struct em28xx_buffer), fh, &dev->lock);
+       mutex_unlock(&dev->lock);
+
+       return errCode;
+}
+
+/*
+ * em28xx_realease_resources()
+ * unregisters the v4l2,i2c and usb devices
+ * called when the device gets disconected or at module unload
+*/
+void em28xx_release_analog_resources(struct em28xx *dev)
+{
+
+       /*FIXME: I2C IR should be disconnected */
+
+       if (dev->radio_dev) {
+               if (video_is_registered(dev->radio_dev))
+                       video_unregister_device(dev->radio_dev);
+               else
+                       video_device_release(dev->radio_dev);
+               dev->radio_dev = NULL;
+       }
+       if (dev->vbi_dev) {
+               em28xx_info("V4L2 device %s deregistered\n",
+                           video_device_node_name(dev->vbi_dev));
+               if (video_is_registered(dev->vbi_dev))
+                       video_unregister_device(dev->vbi_dev);
+               else
+                       video_device_release(dev->vbi_dev);
+               dev->vbi_dev = NULL;
+       }
+       if (dev->vdev) {
+               em28xx_info("V4L2 device %s deregistered\n",
+                           video_device_node_name(dev->vdev));
+               if (video_is_registered(dev->vdev))
+                       video_unregister_device(dev->vdev);
+               else
+                       video_device_release(dev->vdev);
+               dev->vdev = NULL;
+       }
+}
+
+/*
+ * em28xx_v4l2_close()
+ * stops streaming and deallocates all resources allocated by the v4l2
+ * calls and ioctls
+ */
+static int em28xx_v4l2_close(struct file *filp)
+{
+       struct em28xx_fh *fh  = filp->private_data;
+       struct em28xx    *dev = fh->dev;
+       int              errCode;
+
+       em28xx_videodbg("users=%d\n", dev->users);
+
+       mutex_lock(&dev->lock);
+       if (res_check(fh, EM28XX_RESOURCE_VIDEO)) {
+               videobuf_stop(&fh->vb_vidq);
+               res_free(fh, EM28XX_RESOURCE_VIDEO);
+       }
+
+       if (res_check(fh, EM28XX_RESOURCE_VBI)) {
+               videobuf_stop(&fh->vb_vbiq);
+               res_free(fh, EM28XX_RESOURCE_VBI);
+       }
+
+       if (dev->users == 1) {
+               /* the device is already disconnect,
+                  free the remaining resources */
+               if (dev->state & DEV_DISCONNECTED) {
+                       em28xx_release_resources(dev);
+                       kfree(dev->alt_max_pkt_size);
+                       kfree(dev);
+                       kfree(fh);
+                       mutex_unlock(&dev->lock);
+                       return 0;
+               }
+
+               /* Save some power by putting tuner to sleep */
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
+
+               /* do this before setting alternate! */
+               em28xx_uninit_isoc(dev, EM28XX_ANALOG_MODE);
+               em28xx_set_mode(dev, EM28XX_SUSPEND);
+
+               /* set alternate 0 */
+               dev->alt = 0;
+               em28xx_videodbg("setting alternate 0\n");
+               errCode = usb_set_interface(dev->udev, 0, 0);
+               if (errCode < 0) {
+                       em28xx_errdev("cannot change alternate number to "
+                                       "0 (error=%i)\n", errCode);
+               }
+       }
+
+       videobuf_mmap_free(&fh->vb_vidq);
+       videobuf_mmap_free(&fh->vb_vbiq);
+       kfree(fh);
+       dev->users--;
+       mutex_unlock(&dev->lock);
+       return 0;
+}
+
+/*
+ * em28xx_v4l2_read()
+ * will allocate buffers when called for the first time
+ */
+static ssize_t
+em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
+                loff_t *pos)
+{
+       struct em28xx_fh *fh = filp->private_data;
+       struct em28xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
+       /* FIXME: read() is not prepared to allow changing the video
+          resolution while streaming. Seems a bug at em28xx_set_fmt
+        */
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               if (res_locked(dev, EM28XX_RESOURCE_VIDEO))
+                       rc = -EBUSY;
+               else
+                       rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
+                                       filp->f_flags & O_NONBLOCK);
+       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+               if (!res_get(fh, EM28XX_RESOURCE_VBI))
+                       rc = -EBUSY;
+               else
+                       rc = videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
+                                       filp->f_flags & O_NONBLOCK);
+       }
+       mutex_unlock(&dev->lock);
+
+       return rc;
+}
+
+/*
+ * em28xx_poll()
+ * will allocate buffers when called for the first time
+ */
+static unsigned int em28xx_poll(struct file *filp, poll_table *wait)
+{
+       struct em28xx_fh *fh = filp->private_data;
+       struct em28xx *dev = fh->dev;
+       int rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               if (!res_get(fh, EM28XX_RESOURCE_VIDEO))
+                       return POLLERR;
+               return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
+       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+               if (!res_get(fh, EM28XX_RESOURCE_VBI))
+                       return POLLERR;
+               return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
+       } else {
+               return POLLERR;
+       }
+}
+
+static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait)
+{
+       struct em28xx_fh *fh = filp->private_data;
+       struct em28xx *dev = fh->dev;
+       unsigned int res;
+
+       mutex_lock(&dev->lock);
+       res = em28xx_poll(filp, wait);
+       mutex_unlock(&dev->lock);
+       return res;
+}
+
+/*
+ * em28xx_v4l2_mmap()
+ */
+static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+       struct em28xx_fh *fh    = filp->private_data;
+       struct em28xx    *dev   = fh->dev;
+       int              rc;
+
+       rc = check_dev(dev);
+       if (rc < 0)
+               return rc;
+
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
+       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);
+       mutex_unlock(&dev->lock);
+
+       em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
+               (unsigned long)vma->vm_start,
+               (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
+               rc);
+
+       return rc;
+}
+
+static const struct v4l2_file_operations em28xx_v4l_fops = {
+       .owner         = THIS_MODULE,
+       .open          = em28xx_v4l2_open,
+       .release       = em28xx_v4l2_close,
+       .read          = em28xx_v4l2_read,
+       .poll          = em28xx_v4l2_poll,
+       .mmap          = em28xx_v4l2_mmap,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+       .vidioc_querycap            = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap    = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap       = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap     = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,
+       .vidioc_g_fmt_vbi_cap       = vidioc_g_fmt_vbi_cap,
+       .vidioc_s_fmt_vbi_cap       = vidioc_s_fmt_vbi_cap,
+       .vidioc_enum_framesizes     = vidioc_enum_framesizes,
+       .vidioc_g_audio             = vidioc_g_audio,
+       .vidioc_s_audio             = vidioc_s_audio,
+       .vidioc_cropcap             = vidioc_cropcap,
+       .vidioc_g_fmt_sliced_vbi_cap   = vidioc_g_fmt_sliced_vbi_cap,
+       .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
+       .vidioc_s_fmt_sliced_vbi_cap   = vidioc_try_set_sliced_vbi_cap,
+
+       .vidioc_reqbufs             = vidioc_reqbufs,
+       .vidioc_querybuf            = vidioc_querybuf,
+       .vidioc_qbuf                = vidioc_qbuf,
+       .vidioc_dqbuf               = vidioc_dqbuf,
+       .vidioc_g_std               = vidioc_g_std,
+       .vidioc_querystd            = vidioc_querystd,
+       .vidioc_s_std               = vidioc_s_std,
+       .vidioc_g_parm              = vidioc_g_parm,
+       .vidioc_s_parm              = vidioc_s_parm,
+       .vidioc_enum_input          = vidioc_enum_input,
+       .vidioc_g_input             = vidioc_g_input,
+       .vidioc_s_input             = vidioc_s_input,
+       .vidioc_queryctrl           = vidioc_queryctrl,
+       .vidioc_g_ctrl              = vidioc_g_ctrl,
+       .vidioc_s_ctrl              = vidioc_s_ctrl,
+       .vidioc_streamon            = vidioc_streamon,
+       .vidioc_streamoff           = vidioc_streamoff,
+       .vidioc_g_tuner             = vidioc_g_tuner,
+       .vidioc_s_tuner             = vidioc_s_tuner,
+       .vidioc_g_frequency         = vidioc_g_frequency,
+       .vidioc_s_frequency         = vidioc_s_frequency,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register          = vidioc_g_register,
+       .vidioc_s_register          = vidioc_s_register,
+       .vidioc_g_chip_ident        = vidioc_g_chip_ident,
+#endif
+};
+
+static const struct video_device em28xx_video_template = {
+       .fops                       = &em28xx_v4l_fops,
+       .release                    = video_device_release,
+       .ioctl_ops                  = &video_ioctl_ops,
+
+       .tvnorms                    = V4L2_STD_ALL,
+       .current_norm               = V4L2_STD_PAL,
+};
+
+static const struct v4l2_file_operations radio_fops = {
+       .owner         = THIS_MODULE,
+       .open          = em28xx_v4l2_open,
+       .release       = em28xx_v4l2_close,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
+       .vidioc_querycap      = radio_querycap,
+       .vidioc_g_tuner       = radio_g_tuner,
+       .vidioc_enum_input    = radio_enum_input,
+       .vidioc_g_audio       = radio_g_audio,
+       .vidioc_s_tuner       = radio_s_tuner,
+       .vidioc_s_audio       = radio_s_audio,
+       .vidioc_s_input       = radio_s_input,
+       .vidioc_queryctrl     = radio_queryctrl,
+       .vidioc_g_ctrl        = vidioc_g_ctrl,
+       .vidioc_s_ctrl        = vidioc_s_ctrl,
+       .vidioc_g_frequency   = vidioc_g_frequency,
+       .vidioc_s_frequency   = vidioc_s_frequency,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register    = vidioc_g_register,
+       .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+static struct video_device em28xx_radio_template = {
+       .name                 = "em28xx-radio",
+       .fops                 = &radio_fops,
+       .ioctl_ops            = &radio_ioctl_ops,
+};
+
+/******************************** usb interface ******************************/
+
+
+
+static struct video_device *em28xx_vdev_init(struct em28xx *dev,
+                                       const struct video_device *template,
+                                       const char *type_name)
+{
+       struct video_device *vfd;
+
+       vfd = video_device_alloc();
+       if (NULL == vfd)
+               return NULL;
+
+       *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);
+
+       video_set_drvdata(vfd, dev);
+       return vfd;
+}
+
+int em28xx_register_analog_devices(struct em28xx *dev)
+{
+      u8 val;
+       int ret;
+       unsigned int maxw;
+
+       printk(KERN_INFO "%s: v4l2 driver version %s\n",
+               dev->name, EM28XX_VERSION);
+
+       /* set default norm */
+       dev->norm = em28xx_video_template.current_norm;
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
+       dev->interlaced = EM28XX_INTERLACED_DEFAULT;
+
+       /* Analog specific initialization */
+       dev->format = &format[0];
+
+       maxw = norm_maxw(dev);
+        /* MaxPacketSize for em2800 is too small to capture at full resolution
+         * use half of maxw as the scaler can only scale to 50% */
+        if (dev->board.is_em2800)
+            maxw /= 2;
+
+       em28xx_set_video_format(dev, format[0].fourcc,
+                               maxw, norm_maxh(dev));
+
+       video_mux(dev, 0);
+
+       /* Audio defaults */
+       dev->mute = 1;
+       dev->volume = 0x1f;
+
+/*     em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
+       val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
+       em28xx_write_reg(dev, EM28XX_R0F_XCLK,
+                        (EM28XX_XCLK_AUDIO_UNMUTE | val));
+
+       em28xx_set_outfmt(dev);
+       em28xx_colorlevels_set_default(dev);
+       em28xx_compression_disable(dev);
+
+       /* allocate and fill video video_device struct */
+       dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
+       if (!dev->vdev) {
+               em28xx_errdev("cannot allocate video_device.\n");
+               return -ENODEV;
+       }
+
+       /* register v4l2 video video_device */
+       ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
+                                      video_nr[dev->devno]);
+       if (ret) {
+               em28xx_errdev("unable to register video device (error=%i).\n",
+                             ret);
+               return ret;
+       }
+
+       /* Allocate and fill vbi video_device struct */
+       if (em28xx_vbi_supported(dev) == 1) {
+               dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
+                                               "vbi");
+
+               /* register v4l2 vbi video_device */
+               ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
+                                           vbi_nr[dev->devno]);
+               if (ret < 0) {
+                       em28xx_errdev("unable to register vbi device\n");
+                       return ret;
+               }
+       }
+
+       if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
+               dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
+                                                 "radio");
+               if (!dev->radio_dev) {
+                       em28xx_errdev("cannot allocate video_device.\n");
+                       return -ENODEV;
+               }
+               ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
+                                           radio_nr[dev->devno]);
+               if (ret < 0) {
+                       em28xx_errdev("can't register radio device\n");
+                       return ret;
+               }
+               em28xx_info("Registered radio device as %s\n",
+                           video_device_node_name(dev->radio_dev));
+       }
+
+       em28xx_info("V4L2 video device registered as %s\n",
+                   video_device_node_name(dev->vdev));
+
+       if (dev->vbi_dev)
+               em28xx_info("V4L2 VBI device registered as %s\n",
+                           video_device_node_name(dev->vbi_dev));
+
+       return 0;
+}
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
new file mode 100644 (file)
index 0000000..8757523
--- /dev/null
@@ -0,0 +1,809 @@
+/*
+   em28xx.h - driver for Empia EM2800/EM2820/2840 USB video capture devices
+
+   Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
+                     Ludovico Cavedon <cavedon@sssup.it>
+                     Mauro Carvalho Chehab <mchehab@infradead.org>
+
+   Based on the em2800 driver from Sascha Sommer <saschasommer@freenet.de>
+
+   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.
+ */
+
+#ifndef _EM28XX_H
+#define _EM28XX_H
+
+#include <linux/workqueue.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/videodev2.h>
+
+#include <media/videobuf-vmalloc.h>
+#include <media/v4l2-device.h>
+#include <media/ir-kbd-i2c.h>
+#include <media/rc-core.h>
+#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE)
+#include <media/videobuf-dvb.h>
+#endif
+#include "tuner-xc2028.h"
+#include "xc5000.h"
+#include "em28xx-reg.h"
+
+/* Boards supported by driver */
+#define EM2800_BOARD_UNKNOWN                   0
+#define EM2820_BOARD_UNKNOWN                   1
+#define EM2820_BOARD_TERRATEC_CINERGY_250      2
+#define EM2820_BOARD_PINNACLE_USB_2            3
+#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2      4
+#define EM2820_BOARD_MSI_VOX_USB_2              5
+#define EM2800_BOARD_TERRATEC_CINERGY_200       6
+#define EM2800_BOARD_LEADTEK_WINFAST_USBII      7
+#define EM2800_BOARD_KWORLD_USB2800             8
+#define EM2820_BOARD_PINNACLE_DVC_90           9
+#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900   10
+#define EM2880_BOARD_TERRATEC_HYBRID_XS                11
+#define EM2820_BOARD_KWORLD_PVRTV2800RF                12
+#define EM2880_BOARD_TERRATEC_PRODIGY_XS       13
+#define EM2820_BOARD_PROLINK_PLAYTV_USB2       14
+#define EM2800_BOARD_VGEAR_POCKETTV             15
+#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950   16
+#define EM2880_BOARD_PINNACLE_PCTV_HD_PRO      17
+#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2        18
+#define EM2860_BOARD_SAA711X_REFERENCE_DESIGN  19
+#define EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600   20
+#define EM2800_BOARD_GRABBEEX_USB2800           21
+#define EM2750_BOARD_UNKNOWN                     22
+#define EM2750_BOARD_DLCW_130                    23
+#define EM2820_BOARD_DLINK_USB_TV                24
+#define EM2820_BOARD_GADMEI_UTV310               25
+#define EM2820_BOARD_HERCULES_SMART_TV_USB2      26
+#define EM2820_BOARD_PINNACLE_USB_2_FM1216ME     27
+#define EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE 28
+#define EM2860_BOARD_TVP5150_REFERENCE_DESIGN    29
+#define EM2820_BOARD_VIDEOLOGY_20K14XUSB         30
+#define EM2821_BOARD_USBGEAR_VD204               31
+#define EM2821_BOARD_SUPERCOMP_USB_2             32
+#define EM2860_BOARD_ELGATO_VIDEO_CAPTURE        33
+#define EM2860_BOARD_TERRATEC_HYBRID_XS                  34
+#define EM2860_BOARD_TYPHOON_DVD_MAKER           35
+#define EM2860_BOARD_NETGMBH_CAM                 36
+#define EM2860_BOARD_GADMEI_UTV330               37
+#define EM2861_BOARD_YAKUMO_MOVIE_MIXER                  38
+#define EM2861_BOARD_KWORLD_PVRTV_300U           39
+#define EM2861_BOARD_PLEXTOR_PX_TV100U           40
+#define EM2870_BOARD_KWORLD_350U                 41
+#define EM2870_BOARD_KWORLD_355U                 42
+#define EM2870_BOARD_TERRATEC_XS                 43
+#define EM2870_BOARD_TERRATEC_XS_MT2060                  44
+#define EM2870_BOARD_PINNACLE_PCTV_DVB           45
+#define EM2870_BOARD_COMPRO_VIDEOMATE            46
+#define EM2880_BOARD_KWORLD_DVB_305U             47
+#define EM2880_BOARD_KWORLD_DVB_310U             48
+#define EM2880_BOARD_MSI_DIGIVOX_AD              49
+#define EM2880_BOARD_MSI_DIGIVOX_AD_II           50
+#define EM2880_BOARD_TERRATEC_HYBRID_XS_FR       51
+#define EM2881_BOARD_DNT_DA2_HYBRID              52
+#define EM2881_BOARD_PINNACLE_HYBRID_PRO         53
+#define EM2882_BOARD_KWORLD_VS_DVBT              54
+#define EM2882_BOARD_TERRATEC_HYBRID_XS                  55
+#define EM2882_BOARD_PINNACLE_HYBRID_PRO_330E    56
+#define EM2883_BOARD_KWORLD_HYBRID_330U                  57
+#define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU     58
+#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850     60
+#define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2    61
+#define EM2820_BOARD_GADMEI_TVR200               62
+#define EM2860_BOARD_KAIOMY_TVNPC_U2              63
+#define EM2860_BOARD_EASYCAP                      64
+#define EM2820_BOARD_IODATA_GVMVP_SZ             65
+#define EM2880_BOARD_EMPIRE_DUAL_TV              66
+#define EM2860_BOARD_TERRATEC_GRABBY             67
+#define EM2860_BOARD_TERRATEC_AV350              68
+#define EM2882_BOARD_KWORLD_ATSC_315U            69
+#define EM2882_BOARD_EVGA_INDTUBE                70
+#define EM2820_BOARD_SILVERCREST_WEBCAM           71
+#define EM2861_BOARD_GADMEI_UTV330PLUS           72
+#define EM2870_BOARD_REDDO_DVB_C_USB_BOX          73
+#define EM2800_BOARD_VC211A                      74
+#define EM2882_BOARD_DIKOM_DK300                 75
+#define EM2870_BOARD_KWORLD_A340                 76
+#define EM2874_BOARD_LEADERSHIP_ISDBT            77
+#define EM28174_BOARD_PCTV_290E                   78
+#define EM2884_BOARD_TERRATEC_H5                 79
+#define EM28174_BOARD_PCTV_460E                   80
+#define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C    81
+#define EM2884_BOARD_CINERGY_HTC_STICK           82
+#define EM2860_BOARD_HT_VIDBOX_NW03              83
+#define EM2874_BOARD_MAXMEDIA_UB425_TC            84
+#define EM2884_BOARD_PCTV_510E                    85
+#define EM2884_BOARD_PCTV_520E                    86
+
+/* Limits minimum and default number of buffers */
+#define EM28XX_MIN_BUF 4
+#define EM28XX_DEF_BUF 8
+
+/*Limits the max URB message size */
+#define URB_MAX_CTRL_SIZE 80
+
+/* Params for validated field */
+#define EM28XX_BOARD_NOT_VALIDATED 1
+#define EM28XX_BOARD_VALIDATED    0
+
+/* Params for em28xx_cmd() audio */
+#define EM28XX_START_AUDIO      1
+#define EM28XX_STOP_AUDIO       0
+
+/* maximum number of em28xx boards */
+#define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
+
+/* maximum number of frames that can be queued */
+#define EM28XX_NUM_FRAMES 5
+/* number of frames that get used for v4l2_read() */
+#define EM28XX_NUM_READ_FRAMES 2
+
+/* number of buffers for isoc transfers */
+#define EM28XX_NUM_BUFS 5
+#define EM28XX_DVB_NUM_BUFS 5
+
+/* number of packets for each buffer
+   windows requests only 64 packets .. so we better do the same
+   this is what I found out for all alternate numbers there!
+ */
+#define EM28XX_NUM_PACKETS 64
+#define EM28XX_DVB_MAX_PACKETS 64
+
+#define EM28XX_INTERLACED_DEFAULT 1
+
+/*
+#define (use usbview if you want to get the other alternate number infos)
+#define
+#define alternate number 2
+#define                        Endpoint Address: 82
+                       Direction: in
+                       Attribute: 1
+                       Type: Isoc
+                       Max Packet Size: 1448
+                       Interval: 125us
+
+  alternate number 7
+
+                       Endpoint Address: 82
+                       Direction: in
+                       Attribute: 1
+                       Type: Isoc
+                       Max Packet Size: 3072
+                       Interval: 125us
+*/
+
+/* time to wait when stopping the isoc transfer */
+#define EM28XX_URB_TIMEOUT \
+                       msecs_to_jiffies(EM28XX_NUM_BUFS * EM28XX_NUM_PACKETS)
+
+/* time in msecs to wait for i2c writes to finish */
+#define EM2800_I2C_WRITE_TIMEOUT 20
+
+enum em28xx_mode {
+       EM28XX_SUSPEND,
+       EM28XX_ANALOG_MODE,
+       EM28XX_DIGITAL_MODE,
+};
+
+
+struct em28xx;
+
+struct em28xx_usb_isoc_bufs {
+               /* max packet size of isoc transaction */
+       int                             max_pkt_size;
+
+               /* number of packets in each buffer */
+       int                             num_packets;
+
+               /* number of allocated urbs */
+       int                             num_bufs;
+
+               /* urb for isoc transfers */
+       struct urb                      **urb;
+
+               /* transfer buffers for isoc transfer */
+       char                            **transfer_buffer;
+};
+
+struct em28xx_usb_isoc_ctl {
+               /* isoc transfer buffers for analog mode */
+       struct em28xx_usb_isoc_bufs     analog_bufs;
+
+               /* isoc transfer buffers for digital mode */
+       struct em28xx_usb_isoc_bufs     digital_bufs;
+
+               /* Stores already requested buffers */
+       struct em28xx_buffer            *vid_buf;
+       struct em28xx_buffer            *vbi_buf;
+
+               /* isoc urb callback */
+       int (*isoc_copy) (struct em28xx *dev, struct urb *urb);
+
+};
+
+/* Struct to enumberate video formats */
+struct em28xx_fmt {
+       char  *name;
+       u32   fourcc;          /* v4l2 format id */
+       int   depth;
+       int   reg;
+};
+
+/* buffer for one video frame */
+struct em28xx_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+
+       struct list_head frame;
+       int top_field;
+};
+
+struct em28xx_dmaqueue {
+       struct list_head       active;
+
+       wait_queue_head_t          wq;
+
+       /* Counters to control buffer fill */
+       int                        pos;
+};
+
+/* inputs */
+
+#define MAX_EM28XX_INPUT 4
+enum enum28xx_itype {
+       EM28XX_VMUX_COMPOSITE1 = 1,
+       EM28XX_VMUX_COMPOSITE2,
+       EM28XX_VMUX_COMPOSITE3,
+       EM28XX_VMUX_COMPOSITE4,
+       EM28XX_VMUX_SVIDEO,
+       EM28XX_VMUX_TELEVISION,
+       EM28XX_VMUX_CABLE,
+       EM28XX_VMUX_DVB,
+       EM28XX_VMUX_DEBUG,
+       EM28XX_RADIO,
+};
+
+enum em28xx_ac97_mode {
+       EM28XX_NO_AC97 = 0,
+       EM28XX_AC97_EM202,
+       EM28XX_AC97_SIGMATEL,
+       EM28XX_AC97_OTHER,
+};
+
+struct em28xx_audio_mode {
+       enum em28xx_ac97_mode ac97;
+
+       u16 ac97_feat;
+       u32 ac97_vendor_id;
+
+       unsigned int has_audio:1;
+
+       unsigned int i2s_3rates:1;
+       unsigned int i2s_5rates:1;
+};
+
+/* em28xx has two audio inputs: tuner and line in.
+   However, on most devices, an auxiliary AC97 codec device is used.
+   The AC97 device may have several different inputs and outputs,
+   depending on their model. So, it is possible to use AC97 mixer to
+   address more than two different entries.
+ */
+enum em28xx_amux {
+       /* This is the only entry for em28xx tuner input */
+       EM28XX_AMUX_VIDEO,      /* em28xx tuner, AC97 mixer Video */
+
+       EM28XX_AMUX_LINE_IN,    /* AC97 mixer Line In */
+
+       /* Some less-common mixer setups */
+       EM28XX_AMUX_VIDEO2,     /* em28xx Line in, AC97 mixer Video */
+       EM28XX_AMUX_PHONE,
+       EM28XX_AMUX_MIC,
+       EM28XX_AMUX_CD,
+       EM28XX_AMUX_AUX,
+       EM28XX_AMUX_PCM_OUT,
+};
+
+enum em28xx_aout {
+       /* AC97 outputs */
+       EM28XX_AOUT_MASTER = 1 << 0,
+       EM28XX_AOUT_LINE   = 1 << 1,
+       EM28XX_AOUT_MONO   = 1 << 2,
+       EM28XX_AOUT_LFE    = 1 << 3,
+       EM28XX_AOUT_SURR   = 1 << 4,
+
+       /* PCM IN Mixer - used by AC97_RECORD_SELECT register */
+       EM28XX_AOUT_PCM_IN = 1 << 7,
+
+       /* Bits 10-8 are used to indicate the PCM IN record select */
+       EM28XX_AOUT_PCM_MIC_PCM = 0 << 8,
+       EM28XX_AOUT_PCM_CD      = 1 << 8,
+       EM28XX_AOUT_PCM_VIDEO   = 2 << 8,
+       EM28XX_AOUT_PCM_AUX     = 3 << 8,
+       EM28XX_AOUT_PCM_LINE    = 4 << 8,
+       EM28XX_AOUT_PCM_STEREO  = 5 << 8,
+       EM28XX_AOUT_PCM_MONO    = 6 << 8,
+       EM28XX_AOUT_PCM_PHONE   = 7 << 8,
+};
+
+static inline int ac97_return_record_select(int a_out)
+{
+       return (a_out & 0x700) >> 8;
+}
+
+struct em28xx_reg_seq {
+       int reg;
+       unsigned char val, mask;
+       int sleep;
+};
+
+struct em28xx_input {
+       enum enum28xx_itype type;
+       unsigned int vmux;
+       enum em28xx_amux amux;
+       enum em28xx_aout aout;
+       struct em28xx_reg_seq *gpio;
+};
+
+#define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
+
+enum em28xx_decoder {
+       EM28XX_NODECODER = 0,
+       EM28XX_TVP5150,
+       EM28XX_SAA711X,
+};
+
+enum em28xx_sensor {
+       EM28XX_NOSENSOR = 0,
+       EM28XX_MT9V011,
+       EM28XX_MT9M001,
+       EM28XX_MT9M111,
+};
+
+enum em28xx_adecoder {
+       EM28XX_NOADECODER = 0,
+       EM28XX_TVAUDIO,
+};
+
+struct em28xx_board {
+       char *name;
+       int vchannels;
+       int tuner_type;
+       int tuner_addr;
+
+       /* i2c flags */
+       unsigned int tda9887_conf;
+
+       /* GPIO sequences */
+       struct em28xx_reg_seq *dvb_gpio;
+       struct em28xx_reg_seq *suspend_gpio;
+       struct em28xx_reg_seq *tuner_gpio;
+       struct em28xx_reg_seq *mute_gpio;
+
+       unsigned int is_em2800:1;
+       unsigned int has_msp34xx:1;
+       unsigned int mts_firmware:1;
+       unsigned int max_range_640_480:1;
+       unsigned int has_dvb:1;
+       unsigned int has_snapshot_button:1;
+       unsigned int is_webcam:1;
+       unsigned int valid:1;
+       unsigned int has_ir_i2c:1;
+
+       unsigned char xclk, i2c_speed;
+       unsigned char radio_addr;
+       unsigned short tvaudio_addr;
+
+       enum em28xx_decoder decoder;
+       enum em28xx_adecoder adecoder;
+
+       struct em28xx_input       input[MAX_EM28XX_INPUT];
+       struct em28xx_input       radio;
+       char                      *ir_codes;
+};
+
+struct em28xx_eeprom {
+       u32 id;                 /* 0x9567eb1a */
+       u16 vendor_ID;
+       u16 product_ID;
+
+       u16 chip_conf;
+
+       u16 board_conf;
+
+       u16 string1, string2, string3;
+
+       u8 string_idx_table;
+};
+
+/* device states */
+enum em28xx_dev_state {
+       DEV_INITIALIZED = 0x01,
+       DEV_DISCONNECTED = 0x02,
+       DEV_MISCONFIGURED = 0x04,
+};
+
+#define EM28XX_AUDIO_BUFS 5
+#define EM28XX_NUM_AUDIO_PACKETS 64
+#define EM28XX_AUDIO_MAX_PACKET_SIZE 196 /* static value */
+#define EM28XX_CAPTURE_STREAM_EN 1
+
+/* em28xx extensions */
+#define EM28XX_AUDIO   0x10
+#define EM28XX_DVB     0x20
+#define EM28XX_RC      0x30
+
+/* em28xx resource types (used for res_get/res_lock etc */
+#define EM28XX_RESOURCE_VIDEO 0x01
+#define EM28XX_RESOURCE_VBI   0x02
+
+struct em28xx_audio {
+       char name[50];
+       char *transfer_buffer[EM28XX_AUDIO_BUFS];
+       struct urb *urb[EM28XX_AUDIO_BUFS];
+       struct usb_device *udev;
+       unsigned int capture_transfer_done;
+       struct snd_pcm_substream   *capture_pcm_substream;
+
+       unsigned int hwptr_done_capture;
+       struct snd_card            *sndcard;
+
+       int users;
+       spinlock_t slock;
+};
+
+struct em28xx;
+
+struct em28xx_fh {
+       struct em28xx *dev;
+       int           radio;
+       unsigned int  resources;
+
+       struct videobuf_queue        vb_vidq;
+       struct videobuf_queue        vb_vbiq;
+
+       enum v4l2_buf_type           type;
+};
+
+/* main device struct */
+struct em28xx {
+       /* generic device properties */
+       char name[30];          /* name (including minor) of the device */
+       int model;              /* index in the device_data struct */
+       int devno;              /* marks the number of this device */
+       enum em28xx_chip_id chip_id;
+
+       int audio_ifnum;
+
+       struct v4l2_device v4l2_dev;
+       struct em28xx_board board;
+
+       /* Webcam specific fields */
+       enum em28xx_sensor em28xx_sensor;
+       int sensor_xres, sensor_yres;
+       int sensor_xtal;
+
+       /* Allows progressive (e. g. non-interlaced) mode */
+       int progressive;
+
+       /* Vinmode/Vinctl used at the driver */
+       int vinmode, vinctl;
+
+       unsigned int has_audio_class:1;
+       unsigned int has_alsa_audio:1;
+       unsigned int is_audio_only:1;
+
+       /* Controls audio streaming */
+       struct work_struct wq_trigger;              /* Trigger to start/stop audio for alsa module */
+        atomic_t       stream_started;      /* stream should be running if true */
+
+       struct em28xx_fmt *format;
+
+       struct em28xx_IR *ir;
+
+       /* Some older em28xx chips needs a waiting time after writing */
+       unsigned int wait_after_write;
+
+       struct list_head        devlist;
+
+       u32 i2s_speed;          /* I2S speed for audio digital stream */
+
+       struct em28xx_audio_mode audio_mode;
+
+       int tuner_type;         /* type of the tuner */
+       int tuner_addr;         /* tuner address */
+       int tda9887_conf;
+       /* i2c i/o */
+       struct i2c_adapter i2c_adap;
+       struct i2c_client i2c_client;
+       /* video for linux */
+       int users;              /* user count for exclusive use */
+       struct video_device *vdev;      /* video for linux device struct */
+       v4l2_std_id norm;       /* selected tv norm */
+       int ctl_freq;           /* selected frequency */
+       unsigned int ctl_input; /* selected input */
+       unsigned int ctl_ainput;/* selected audio input */
+       unsigned int ctl_aoutput;/* selected audio output */
+       int mute;
+       int volume;
+       /* frame properties */
+       int width;              /* current frame width */
+       int height;             /* current frame height */
+       unsigned hscale;        /* horizontal scale factor (see datasheet) */
+       unsigned vscale;        /* vertical scale factor (see datasheet) */
+       int interlaced;         /* 1=interlace fileds, 0=just top fileds */
+       unsigned int video_bytesread;   /* Number of bytes read */
+
+       unsigned long hash;     /* eeprom hash - for boards with generic ID */
+       unsigned long i2c_hash; /* i2c devicelist hash -
+                                  for boards with generic ID */
+
+       struct em28xx_audio adev;
+
+       /* states */
+       enum em28xx_dev_state state;
+
+       /* vbi related state tracking */
+       int capture_type;
+       int vbi_read;
+       unsigned char cur_field;
+       unsigned int vbi_width;
+       unsigned int vbi_height; /* lines per field */
+
+       struct work_struct         request_module_wk;
+
+       /* locks */
+       struct mutex lock;
+       struct mutex ctrl_urb_lock;     /* protects urb_buf */
+       /* spinlock_t queue_lock; */
+       struct list_head inqueue, outqueue;
+       struct video_device *vbi_dev;
+       struct video_device *radio_dev;
+
+       /* resources in use */
+       unsigned int resources;
+
+       unsigned char eedata[256];
+
+       /* Isoc control struct */
+       struct em28xx_dmaqueue vidq;
+       struct em28xx_dmaqueue vbiq;
+       struct em28xx_usb_isoc_ctl isoc_ctl;
+       spinlock_t slock;
+
+       /* usb transfer */
+       struct usb_device *udev;        /* the usb device */
+       int alt;                /* alternate */
+       int max_pkt_size;       /* max packet size of isoc transaction */
+       int num_alt;            /* Number of alternative settings */
+       unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
+       int dvb_alt;                            /* alternate for DVB */
+       unsigned int dvb_max_pkt_size;          /* wMaxPacketSize for DVB */
+       char urb_buf[URB_MAX_CTRL_SIZE];        /* urb control msg buffer */
+
+       /* helper funcs that call usb_control_msg */
+       int (*em28xx_write_regs) (struct em28xx *dev, u16 reg,
+                                       char *buf, int len);
+       int (*em28xx_read_reg) (struct em28xx *dev, u16 reg);
+       int (*em28xx_read_reg_req_len) (struct em28xx *dev, u8 req, u16 reg,
+                                       char *buf, int len);
+       int (*em28xx_write_regs_req) (struct em28xx *dev, u8 req, u16 reg,
+                                     char *buf, int len);
+       int (*em28xx_read_reg_req) (struct em28xx *dev, u8 req, u16 reg);
+
+       enum em28xx_mode mode;
+
+       /* register numbers for GPO/GPIO registers */
+       u16 reg_gpo_num, reg_gpio_num;
+
+       /* Caches GPO and GPIO registers */
+       unsigned char   reg_gpo, reg_gpio;
+
+       /* Snapshot button */
+       char snapshot_button_path[30];  /* path of the input dev */
+       struct input_dev *sbutton_input_dev;
+       struct delayed_work sbutton_query_work;
+
+       struct em28xx_dvb *dvb;
+
+       /* I2C keyboard data */
+       struct IR_i2c_init_data init_data;
+};
+
+struct em28xx_ops {
+       struct list_head next;
+       char *name;
+       int id;
+       int (*init)(struct em28xx *);
+       int (*fini)(struct em28xx *);
+};
+
+/* Provided by em28xx-i2c.c */
+void em28xx_do_i2c_scan(struct em28xx *dev);
+int  em28xx_i2c_register(struct em28xx *dev);
+int  em28xx_i2c_unregister(struct em28xx *dev);
+
+/* Provided by em28xx-core.c */
+
+u32 em28xx_request_buffers(struct em28xx *dev, u32 count);
+void em28xx_queue_unusedframes(struct em28xx *dev);
+void em28xx_release_buffers(struct em28xx *dev);
+
+int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
+                           char *buf, int len);
+int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg);
+int em28xx_read_reg(struct em28xx *dev, u16 reg);
+int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
+                         int len);
+int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len);
+int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val);
+int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
+                                u8 bitmask);
+
+int em28xx_read_ac97(struct em28xx *dev, u8 reg);
+int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val);
+
+int em28xx_audio_analog_set(struct em28xx *dev);
+int em28xx_audio_setup(struct em28xx *dev);
+
+int em28xx_colorlevels_set_default(struct em28xx *dev);
+int em28xx_capture_start(struct em28xx *dev, int start);
+int em28xx_vbi_supported(struct em28xx *dev);
+int em28xx_set_outfmt(struct em28xx *dev);
+int em28xx_resolution_set(struct em28xx *dev);
+int em28xx_set_alternate(struct em28xx *dev);
+int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode,
+                     int max_packets, int num_bufs, int max_pkt_size);
+int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode,
+                    int max_packets, int num_bufs, int max_pkt_size,
+                    int (*isoc_copy) (struct em28xx *dev, struct urb *urb));
+void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode);
+void em28xx_stop_urbs(struct em28xx *dev);
+int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev);
+int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
+int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
+void em28xx_wake_i2c(struct em28xx *dev);
+int em28xx_register_extension(struct em28xx_ops *dev);
+void em28xx_unregister_extension(struct em28xx_ops *dev);
+void em28xx_init_extension(struct em28xx *dev);
+void em28xx_close_extension(struct em28xx *dev);
+
+/* Provided by em28xx-video.c */
+int em28xx_register_analog_devices(struct em28xx *dev);
+void em28xx_release_analog_resources(struct em28xx *dev);
+
+/* Provided by em28xx-cards.c */
+extern int em2800_variant_detect(struct usb_device *udev, int model);
+extern struct em28xx_board em28xx_boards[];
+extern struct usb_device_id em28xx_id_table[];
+extern const unsigned int em28xx_bcount;
+int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
+void em28xx_release_resources(struct em28xx *dev);
+
+/* Provided by em28xx-vbi.c */
+extern struct videobuf_queue_ops em28xx_vbi_qops;
+
+/* printk macros */
+
+#define em28xx_err(fmt, arg...) do {\
+       printk(KERN_ERR fmt , ##arg); } while (0)
+
+#define em28xx_errdev(fmt, arg...) do {\
+       printk(KERN_ERR "%s: "fmt,\
+                       dev->name , ##arg); } while (0)
+
+#define em28xx_info(fmt, arg...) do {\
+       printk(KERN_INFO "%s: "fmt,\
+                       dev->name , ##arg); } while (0)
+#define em28xx_warn(fmt, arg...) do {\
+       printk(KERN_WARNING "%s: "fmt,\
+                       dev->name , ##arg); } while (0)
+
+static inline int em28xx_compression_disable(struct em28xx *dev)
+{
+       /* side effect of disabling scaler and mixer */
+       return em28xx_write_reg(dev, EM28XX_R26_COMPR, 0x00);
+}
+
+static inline int em28xx_contrast_get(struct em28xx *dev)
+{
+       return em28xx_read_reg(dev, EM28XX_R20_YGAIN) & 0x1f;
+}
+
+static inline int em28xx_brightness_get(struct em28xx *dev)
+{
+       return em28xx_read_reg(dev, EM28XX_R21_YOFFSET);
+}
+
+static inline int em28xx_saturation_get(struct em28xx *dev)
+{
+       return em28xx_read_reg(dev, EM28XX_R22_UVGAIN) & 0x1f;
+}
+
+static inline int em28xx_u_balance_get(struct em28xx *dev)
+{
+       return em28xx_read_reg(dev, EM28XX_R23_UOFFSET);
+}
+
+static inline int em28xx_v_balance_get(struct em28xx *dev)
+{
+       return em28xx_read_reg(dev, EM28XX_R24_VOFFSET);
+}
+
+static inline int em28xx_gamma_get(struct em28xx *dev)
+{
+       return em28xx_read_reg(dev, EM28XX_R14_GAMMA) & 0x3f;
+}
+
+static inline int em28xx_contrast_set(struct em28xx *dev, s32 val)
+{
+       u8 tmp = (u8) val;
+       return em28xx_write_regs(dev, EM28XX_R20_YGAIN, &tmp, 1);
+}
+
+static inline int em28xx_brightness_set(struct em28xx *dev, s32 val)
+{
+       u8 tmp = (u8) val;
+       return em28xx_write_regs(dev, EM28XX_R21_YOFFSET, &tmp, 1);
+}
+
+static inline int em28xx_saturation_set(struct em28xx *dev, s32 val)
+{
+       u8 tmp = (u8) val;
+       return em28xx_write_regs(dev, EM28XX_R22_UVGAIN, &tmp, 1);
+}
+
+static inline int em28xx_u_balance_set(struct em28xx *dev, s32 val)
+{
+       u8 tmp = (u8) val;
+       return em28xx_write_regs(dev, EM28XX_R23_UOFFSET, &tmp, 1);
+}
+
+static inline int em28xx_v_balance_set(struct em28xx *dev, s32 val)
+{
+       u8 tmp = (u8) val;
+       return em28xx_write_regs(dev, EM28XX_R24_VOFFSET, &tmp, 1);
+}
+
+static inline int em28xx_gamma_set(struct em28xx *dev, s32 val)
+{
+       u8 tmp = (u8) val;
+       return em28xx_write_regs(dev, EM28XX_R14_GAMMA, &tmp, 1);
+}
+
+/*FIXME: maxw should be dependent of alt mode */
+static inline unsigned int norm_maxw(struct em28xx *dev)
+{
+       if (dev->board.is_webcam)
+               return dev->sensor_xres;
+
+       if (dev->board.max_range_640_480)
+               return 640;
+
+       return 720;
+}
+
+static inline unsigned int norm_maxh(struct em28xx *dev)
+{
+       if (dev->board.is_webcam)
+               return dev->sensor_yres;
+
+       if (dev->board.max_range_640_480)
+               return 480;
+
+       return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
+}
+#endif
diff --git a/drivers/media/usb/gspca/Kconfig b/drivers/media/usb/gspca/Kconfig
new file mode 100644 (file)
index 0000000..6345f93
--- /dev/null
@@ -0,0 +1,425 @@
+menuconfig USB_GSPCA
+       tristate "GSPCA based webcams"
+       depends on VIDEO_V4L2
+       default m
+       ---help---
+         Say Y here if you want to enable selecting webcams based
+         on the GSPCA framework.
+
+         See <file:Documentation/video4linux/gspca.txt> for more info.
+
+         This driver uses the Video For Linux API. You must say Y or M to
+         "Video For Linux" to use this driver.
+
+         To compile this driver as modules, choose M here: the
+         module will be called gspca_main.
+
+
+if USB_GSPCA && VIDEO_V4L2
+
+source "drivers/media/usb/gspca/m5602/Kconfig"
+source "drivers/media/usb/gspca/stv06xx/Kconfig"
+source "drivers/media/usb/gspca/gl860/Kconfig"
+
+config USB_GSPCA_BENQ
+       tristate "Benq USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for the Benq DC E300 camera.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_benq.
+
+config USB_GSPCA_CONEX
+       tristate "Conexant Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the Conexant chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_conex.
+
+config USB_GSPCA_CPIA1
+       tristate "cpia CPiA (version 1) Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for USB cameras based on the cpia
+         CPiA chip. Note that you need atleast version 0.6.4 of libv4l for
+         applications to understand the videoformat generated by this driver.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_cpia1.
+
+config USB_GSPCA_ETOMS
+       tristate "Etoms USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the Etoms chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_etoms.
+
+config USB_GSPCA_FINEPIX
+       tristate "Fujifilm FinePix USB V4L2 driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the FinePix chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_finepix.
+
+config USB_GSPCA_JEILINJ
+       tristate "Jeilin JPEG USB V4L2 driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on this Jeilin chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_jeilinj.
+
+config USB_GSPCA_JL2005BCD
+       tristate "JL2005B/C/D USB V4L2 driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based the
+         JL2005B, JL2005C, or JL2005D chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_jl2005bcd.
+
+config USB_GSPCA_KINECT
+       tristate "Kinect sensor device USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for the Microsoft Kinect sensor device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_kinect.
+
+config USB_GSPCA_KONICA
+       tristate "Konica USB Camera V4L2 driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the Konica chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_konica.
+
+config USB_GSPCA_MARS
+       tristate "Mars USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the Mars chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_mars.
+
+config USB_GSPCA_MR97310A
+       tristate "Mars-Semi MR97310A USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the MR97310A chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_mr97310a.
+
+config USB_GSPCA_NW80X
+       tristate "Divio based (NW80x) USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the NW80x chips.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_nw80x.
+
+config USB_GSPCA_OV519
+       tristate "OV51x / OVFX2 / W996xCF USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on one of these:
+         OV511(+), OV518(+), OV519, OVFX2, W9967CF, W9968CF
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_ov519.
+
+config USB_GSPCA_OV534
+       tristate "OV534 OV772x USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the OV534 chip
+         and sensor OV772x (e.g. Sony Playstation EYE)
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_ov534.
+
+config USB_GSPCA_OV534_9
+       tristate "OV534 OV965x USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the OV534 chip
+         and sensor OV965x (e.g. Hercules Dualpix)
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_ov534_9.
+
+config USB_GSPCA_PAC207
+       tristate "Pixart PAC207 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the PAC207 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_pac207.
+
+config USB_GSPCA_PAC7302
+       tristate "Pixart PAC7302 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the PAC7302 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_pac7302.
+
+config USB_GSPCA_PAC7311
+       tristate "Pixart PAC7311 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the PAC7311 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_pac7311.
+
+config USB_GSPCA_SE401
+       tristate "SE401 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+        Say Y here if you want support for cameras based on the
+        Endpoints (formerly known as AOX) se401 chip.
+
+        To compile this driver as a module, choose M here: the
+        module will be called gspca_se401.
+
+config USB_GSPCA_SN9C2028
+       tristate "SONIX Dual-Mode USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want streaming support for Sonix SN9C2028 cameras.
+         These are supported as stillcams in libgphoto2/camlibs/sonix.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_sn9c2028.
+
+config USB_GSPCA_SN9C20X
+       tristate "SN9C20X USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+        Say Y here if you want support for cameras based on the
+        sn9c20x chips (SN9C201 and SN9C202).
+
+        To compile this driver as a module, choose M here: the
+        module will be called gspca_sn9c20x.
+
+config USB_GSPCA_SONIXB
+       tristate "SONIX Bayer USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the Sonix
+         chips with Bayer format (SN9C101, SN9C102 and SN9C103).
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_sonixb.
+
+config USB_GSPCA_SONIXJ
+       tristate "SONIX JPEG USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the Sonix
+         chips with JPEG format (SN9C102P, SN9C105 and >= SN9C110).
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_sonixj
+
+config USB_GSPCA_SPCA500
+       tristate "SPCA500 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the SPCA500 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_spca500.
+
+config USB_GSPCA_SPCA501
+       tristate "SPCA501 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the SPCA501 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_spca501.
+
+config USB_GSPCA_SPCA505
+       tristate "SPCA505 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the SPCA505 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_spca505.
+
+config USB_GSPCA_SPCA506
+       tristate "SPCA506 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the SPCA506 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_spca506.
+
+config USB_GSPCA_SPCA508
+       tristate "SPCA508 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the SPCA508 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_spca508.
+
+config USB_GSPCA_SPCA561
+       tristate "SPCA561 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the SPCA561 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_spca561.
+
+config USB_GSPCA_SPCA1528
+       tristate "SPCA1528 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the SPCA1528 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_spca1528.
+
+config USB_GSPCA_SQ905
+       tristate "SQ Technologies SQ905 based USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the SQ905 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_sq905.
+
+config USB_GSPCA_SQ905C
+       tristate "SQ Technologies SQ905C based USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the SQ905C chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_sq905c.
+
+config USB_GSPCA_SQ930X
+       tristate "SQ Technologies SQ930X based USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the SQ930X chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_sq930x.
+
+config USB_GSPCA_STK014
+       tristate "Syntek DV4000 (STK014) USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the STK014 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_stk014.
+
+config USB_GSPCA_STV0680
+       tristate "STV0680 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the STV0680 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_stv0680.
+
+config USB_GSPCA_SUNPLUS
+       tristate "SUNPLUS USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the Sunplus
+         SPCA504(abc) SPCA533 SPCA536 chips.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_sunplus.
+
+config USB_GSPCA_T613
+       tristate "T613 (JPEG Compliance) USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the T613 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_t613.
+
+config USB_GSPCA_TOPRO
+       tristate "TOPRO USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the
+         TP6800 and TP6810 Topro chips.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_topro.
+
+config USB_GSPCA_TV8532
+       tristate "TV8532 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the TV8531 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_tv8532.
+
+config USB_GSPCA_VC032X
+       tristate "VC032X USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the VC032X chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_vc032x.
+
+config USB_GSPCA_VICAM
+       tristate "ViCam USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for the 3com homeconnect camera
+         (vicam).
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_vicam.
+
+config USB_GSPCA_XIRLINK_CIT
+       tristate "Xirlink C-It USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for Xirlink C-It bases cameras.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_xirlink_cit.
+
+config USB_GSPCA_ZC3XX
+       tristate "ZC3XX USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the ZC3XX chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_zc3xx.
+
+endif
diff --git a/drivers/media/usb/gspca/Makefile b/drivers/media/usb/gspca/Makefile
new file mode 100644 (file)
index 0000000..c901da0
--- /dev/null
@@ -0,0 +1,93 @@
+obj-$(CONFIG_USB_GSPCA)          += gspca_main.o
+obj-$(CONFIG_USB_GSPCA_BENQ)     += gspca_benq.o
+obj-$(CONFIG_USB_GSPCA_CONEX)    += gspca_conex.o
+obj-$(CONFIG_USB_GSPCA_CPIA1)    += gspca_cpia1.o
+obj-$(CONFIG_USB_GSPCA_ETOMS)    += gspca_etoms.o
+obj-$(CONFIG_USB_GSPCA_FINEPIX)  += gspca_finepix.o
+obj-$(CONFIG_USB_GSPCA_JEILINJ)  += gspca_jeilinj.o
+obj-$(CONFIG_USB_GSPCA_JL2005BCD) += gspca_jl2005bcd.o
+obj-$(CONFIG_USB_GSPCA_KINECT)   += gspca_kinect.o
+obj-$(CONFIG_USB_GSPCA_KONICA)   += gspca_konica.o
+obj-$(CONFIG_USB_GSPCA_MARS)     += gspca_mars.o
+obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o
+obj-$(CONFIG_USB_GSPCA_NW80X)    += gspca_nw80x.o
+obj-$(CONFIG_USB_GSPCA_OV519)    += gspca_ov519.o
+obj-$(CONFIG_USB_GSPCA_OV534)    += gspca_ov534.o
+obj-$(CONFIG_USB_GSPCA_OV534_9)  += gspca_ov534_9.o
+obj-$(CONFIG_USB_GSPCA_PAC207)   += gspca_pac207.o
+obj-$(CONFIG_USB_GSPCA_PAC7302)  += gspca_pac7302.o
+obj-$(CONFIG_USB_GSPCA_PAC7311)  += gspca_pac7311.o
+obj-$(CONFIG_USB_GSPCA_SE401)    += gspca_se401.o
+obj-$(CONFIG_USB_GSPCA_SN9C2028) += gspca_sn9c2028.o
+obj-$(CONFIG_USB_GSPCA_SN9C20X)  += gspca_sn9c20x.o
+obj-$(CONFIG_USB_GSPCA_SONIXB)   += gspca_sonixb.o
+obj-$(CONFIG_USB_GSPCA_SONIXJ)   += gspca_sonixj.o
+obj-$(CONFIG_USB_GSPCA_SPCA500)  += gspca_spca500.o
+obj-$(CONFIG_USB_GSPCA_SPCA501)  += gspca_spca501.o
+obj-$(CONFIG_USB_GSPCA_SPCA505)  += gspca_spca505.o
+obj-$(CONFIG_USB_GSPCA_SPCA506)  += gspca_spca506.o
+obj-$(CONFIG_USB_GSPCA_SPCA508)  += gspca_spca508.o
+obj-$(CONFIG_USB_GSPCA_SPCA561)  += gspca_spca561.o
+obj-$(CONFIG_USB_GSPCA_SPCA1528) += gspca_spca1528.o
+obj-$(CONFIG_USB_GSPCA_SQ905)    += gspca_sq905.o
+obj-$(CONFIG_USB_GSPCA_SQ905C)   += gspca_sq905c.o
+obj-$(CONFIG_USB_GSPCA_SQ930X)   += gspca_sq930x.o
+obj-$(CONFIG_USB_GSPCA_SUNPLUS)  += gspca_sunplus.o
+obj-$(CONFIG_USB_GSPCA_STK014)   += gspca_stk014.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_TV8532)   += gspca_tv8532.o
+obj-$(CONFIG_USB_GSPCA_VC032X)   += gspca_vc032x.o
+obj-$(CONFIG_USB_GSPCA_VICAM)    += gspca_vicam.o
+obj-$(CONFIG_USB_GSPCA_XIRLINK_CIT) += gspca_xirlink_cit.o
+obj-$(CONFIG_USB_GSPCA_ZC3XX)    += gspca_zc3xx.o
+
+gspca_main-objs     := gspca.o autogain_functions.o
+gspca_benq-objs     := benq.o
+gspca_conex-objs    := conex.o
+gspca_cpia1-objs    := cpia1.o
+gspca_etoms-objs    := etoms.o
+gspca_finepix-objs  := finepix.o
+gspca_jeilinj-objs  := jeilinj.o
+gspca_jl2005bcd-objs  := jl2005bcd.o
+gspca_kinect-objs   := kinect.o
+gspca_konica-objs   := konica.o
+gspca_mars-objs     := mars.o
+gspca_mr97310a-objs := mr97310a.o
+gspca_nw80x-objs    := nw80x.o
+gspca_ov519-objs    := ov519.o
+gspca_ov534-objs    := ov534.o
+gspca_ov534_9-objs  := ov534_9.o
+gspca_pac207-objs   := pac207.o
+gspca_pac7302-objs  := pac7302.o
+gspca_pac7311-objs  := pac7311.o
+gspca_se401-objs    := se401.o
+gspca_sn9c2028-objs := sn9c2028.o
+gspca_sn9c20x-objs  := sn9c20x.o
+gspca_sonixb-objs   := sonixb.o
+gspca_sonixj-objs   := sonixj.o
+gspca_spca500-objs  := spca500.o
+gspca_spca501-objs  := spca501.o
+gspca_spca505-objs  := spca505.o
+gspca_spca506-objs  := spca506.o
+gspca_spca508-objs  := spca508.o
+gspca_spca561-objs  := spca561.o
+gspca_spca1528-objs := spca1528.o
+gspca_sq905-objs    := sq905.o
+gspca_sq905c-objs   := sq905c.o
+gspca_sq930x-objs   := sq930x.o
+gspca_stk014-objs   := stk014.o
+gspca_stv0680-objs  := stv0680.o
+gspca_sunplus-objs  := sunplus.o
+gspca_t613-objs     := t613.o
+gspca_topro-objs    := topro.o
+gspca_tv8532-objs   := tv8532.o
+gspca_vc032x-objs   := vc032x.o
+gspca_vicam-objs    := vicam.o
+gspca_xirlink_cit-objs := xirlink_cit.o
+gspca_zc3xx-objs    := zc3xx.o
+
+obj-$(CONFIG_USB_M5602)   += m5602/
+obj-$(CONFIG_USB_STV06XX) += stv06xx/
+obj-$(CONFIG_USB_GL860)   += gl860/
diff --git a/drivers/media/usb/gspca/autogain_functions.c b/drivers/media/usb/gspca/autogain_functions.c
new file mode 100644 (file)
index 0000000..67db674
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Functions for auto gain.
+ *
+ * Copyright (C) 2010-2012 Hans de Goede <hdegoede@redhat.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include "gspca.h"
+
+/* auto gain and exposure algorithm based on the knee algorithm described here:
+   http://ytse.tricolour.net/docs/LowLightOptimization.html
+
+   Returns 0 if no changes were made, 1 if the gain and or exposure settings
+   where changed. */
+int gspca_expo_autogain(
+                       struct gspca_dev *gspca_dev,
+                       int avg_lum,
+                       int desired_avg_lum,
+                       int deadzone,
+                       int gain_knee,
+                       int exposure_knee)
+{
+       s32 gain, orig_gain, exposure, orig_exposure;
+       int i, steps, retval = 0;
+
+       if (v4l2_ctrl_g_ctrl(gspca_dev->autogain) == 0)
+               return 0;
+
+       orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
+       orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
+
+       /* If we are of a multiple of deadzone, do multiple steps to reach the
+          desired lumination fast (with the risc of a slight overshoot) */
+       steps = abs(desired_avg_lum - avg_lum) / deadzone;
+
+       PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
+               avg_lum, desired_avg_lum, steps);
+
+       for (i = 0; i < steps; i++) {
+               if (avg_lum > desired_avg_lum) {
+                       if (gain > gain_knee)
+                               gain--;
+                       else if (exposure > exposure_knee)
+                               exposure--;
+                       else if (gain > gspca_dev->gain->default_value)
+                               gain--;
+                       else if (exposure > gspca_dev->exposure->minimum)
+                               exposure--;
+                       else if (gain > gspca_dev->gain->minimum)
+                               gain--;
+                       else
+                               break;
+               } else {
+                       if (gain < gspca_dev->gain->default_value)
+                               gain++;
+                       else if (exposure < exposure_knee)
+                               exposure++;
+                       else if (gain < gain_knee)
+                               gain++;
+                       else if (exposure < gspca_dev->exposure->maximum)
+                               exposure++;
+                       else if (gain < gspca_dev->gain->maximum)
+                               gain++;
+                       else
+                               break;
+               }
+       }
+
+       if (gain != orig_gain) {
+               v4l2_ctrl_s_ctrl(gspca_dev->gain, gain);
+               retval = 1;
+       }
+       if (exposure != orig_exposure) {
+               v4l2_ctrl_s_ctrl(gspca_dev->exposure, exposure);
+               retval = 1;
+       }
+
+       if (retval)
+               PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
+                       gain, exposure);
+       return retval;
+}
+EXPORT_SYMBOL(gspca_expo_autogain);
+
+/* Autogain + exposure algorithm for cameras with a coarse exposure control
+   (usually this means we can only control the clockdiv to change exposure)
+   As changing the clockdiv so that the fps drops from 30 to 15 fps for
+   example, will lead to a huge exposure change (it effectively doubles),
+   this algorithm normally tries to only adjust the gain (between 40 and
+   80 %) and if that does not help, only then changes exposure. This leads
+   to a much more stable image then using the knee algorithm which at
+   certain points of the knee graph will only try to adjust exposure,
+   which leads to oscilating as one exposure step is huge.
+
+   Returns 0 if no changes were made, 1 if the gain and or exposure settings
+   where changed. */
+int gspca_coarse_grained_expo_autogain(
+                       struct gspca_dev *gspca_dev,
+                       int avg_lum,
+                       int desired_avg_lum,
+                       int deadzone)
+{
+       s32 gain_low, gain_high, gain, orig_gain, exposure, orig_exposure;
+       int steps, retval = 0;
+
+       if (v4l2_ctrl_g_ctrl(gspca_dev->autogain) == 0)
+               return 0;
+
+       orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
+       orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
+
+       gain_low  = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
+                   5 * 2 + gspca_dev->gain->minimum;
+       gain_high = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
+                   5 * 4 + gspca_dev->gain->minimum;
+
+       /* If we are of a multiple of deadzone, do multiple steps to reach the
+          desired lumination fast (with the risc of a slight overshoot) */
+       steps = (desired_avg_lum - avg_lum) / deadzone;
+
+       PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
+               avg_lum, desired_avg_lum, steps);
+
+       if ((gain + steps) > gain_high &&
+           exposure < gspca_dev->exposure->maximum) {
+               gain = gain_high;
+               gspca_dev->exp_too_low_cnt++;
+               gspca_dev->exp_too_high_cnt = 0;
+       } else if ((gain + steps) < gain_low &&
+                  exposure > gspca_dev->exposure->minimum) {
+               gain = gain_low;
+               gspca_dev->exp_too_high_cnt++;
+               gspca_dev->exp_too_low_cnt = 0;
+       } else {
+               gain += steps;
+               if (gain > gspca_dev->gain->maximum)
+                       gain = gspca_dev->gain->maximum;
+               else if (gain < gspca_dev->gain->minimum)
+                       gain = gspca_dev->gain->minimum;
+               gspca_dev->exp_too_high_cnt = 0;
+               gspca_dev->exp_too_low_cnt = 0;
+       }
+
+       if (gspca_dev->exp_too_high_cnt > 3) {
+               exposure--;
+               gspca_dev->exp_too_high_cnt = 0;
+       } else if (gspca_dev->exp_too_low_cnt > 3) {
+               exposure++;
+               gspca_dev->exp_too_low_cnt = 0;
+       }
+
+       if (gain != orig_gain) {
+               v4l2_ctrl_s_ctrl(gspca_dev->gain, gain);
+               retval = 1;
+       }
+       if (exposure != orig_exposure) {
+               v4l2_ctrl_s_ctrl(gspca_dev->exposure, exposure);
+               retval = 1;
+       }
+
+       if (retval)
+               PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
+                       gain, exposure);
+       return retval;
+}
+EXPORT_SYMBOL(gspca_coarse_grained_expo_autogain);
diff --git a/drivers/media/usb/gspca/autogain_functions.h b/drivers/media/usb/gspca/autogain_functions.h
new file mode 100644 (file)
index 0000000..d625eaf
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Functions for auto gain.
+ *
+ * Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef WANT_REGULAR_AUTOGAIN
+/* auto gain and exposure algorithm based on the knee algorithm described here:
+   http://ytse.tricolour.net/docs/LowLightOptimization.html
+
+   Returns 0 if no changes were made, 1 if the gain and or exposure settings
+   where changed. */
+static inline int auto_gain_n_exposure(
+                       struct gspca_dev *gspca_dev,
+                       int avg_lum,
+                       int desired_avg_lum,
+                       int deadzone,
+                       int gain_knee,
+                       int exposure_knee)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i, steps, gain, orig_gain, exposure, orig_exposure;
+       int retval = 0;
+
+       orig_gain = gain = sd->ctrls[GAIN].val;
+       orig_exposure = exposure = sd->ctrls[EXPOSURE].val;
+
+       /* If we are of a multiple of deadzone, do multiple steps to reach the
+          desired lumination fast (with the risc of a slight overshoot) */
+       steps = abs(desired_avg_lum - avg_lum) / deadzone;
+
+       PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
+               avg_lum, desired_avg_lum, steps);
+
+       for (i = 0; i < steps; i++) {
+               if (avg_lum > desired_avg_lum) {
+                       if (gain > gain_knee)
+                               gain--;
+                       else if (exposure > exposure_knee)
+                               exposure--;
+                       else if (gain > sd->ctrls[GAIN].def)
+                               gain--;
+                       else if (exposure > sd->ctrls[EXPOSURE].min)
+                               exposure--;
+                       else if (gain > sd->ctrls[GAIN].min)
+                               gain--;
+                       else
+                               break;
+               } else {
+                       if (gain < sd->ctrls[GAIN].def)
+                               gain++;
+                       else if (exposure < exposure_knee)
+                               exposure++;
+                       else if (gain < gain_knee)
+                               gain++;
+                       else if (exposure < sd->ctrls[EXPOSURE].max)
+                               exposure++;
+                       else if (gain < sd->ctrls[GAIN].max)
+                               gain++;
+                       else
+                               break;
+               }
+       }
+
+       if (gain != orig_gain) {
+               sd->ctrls[GAIN].val = gain;
+               setgain(gspca_dev);
+               retval = 1;
+       }
+       if (exposure != orig_exposure) {
+               sd->ctrls[EXPOSURE].val = exposure;
+               setexposure(gspca_dev);
+               retval = 1;
+       }
+
+       if (retval)
+               PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
+                       gain, exposure);
+       return retval;
+}
+#endif
+
+#ifdef WANT_COARSE_EXPO_AUTOGAIN
+/* Autogain + exposure algorithm for cameras with a coarse exposure control
+   (usually this means we can only control the clockdiv to change exposure)
+   As changing the clockdiv so that the fps drops from 30 to 15 fps for
+   example, will lead to a huge exposure change (it effectively doubles),
+   this algorithm normally tries to only adjust the gain (between 40 and
+   80 %) and if that does not help, only then changes exposure. This leads
+   to a much more stable image then using the knee algorithm which at
+   certain points of the knee graph will only try to adjust exposure,
+   which leads to oscilating as one exposure step is huge.
+
+   Note this assumes that the sd struct for the cam in question has
+   exp_too_low_cnt and exp_too_high_cnt int members for use by this function.
+
+   Returns 0 if no changes were made, 1 if the gain and or exposure settings
+   where changed. */
+static inline int coarse_grained_expo_autogain(
+                       struct gspca_dev *gspca_dev,
+                       int avg_lum,
+                       int desired_avg_lum,
+                       int deadzone)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int steps, gain, orig_gain, exposure, orig_exposure;
+       int gain_low, gain_high;
+       int retval = 0;
+
+       orig_gain = gain = sd->ctrls[GAIN].val;
+       orig_exposure = exposure = sd->ctrls[EXPOSURE].val;
+
+       gain_low = (sd->ctrls[GAIN].max - sd->ctrls[GAIN].min) / 5 * 2;
+       gain_low += sd->ctrls[GAIN].min;
+       gain_high = (sd->ctrls[GAIN].max - sd->ctrls[GAIN].min) / 5 * 4;
+       gain_high += sd->ctrls[GAIN].min;
+
+       /* If we are of a multiple of deadzone, do multiple steps to reach the
+          desired lumination fast (with the risc of a slight overshoot) */
+       steps = (desired_avg_lum - avg_lum) / deadzone;
+
+       PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
+               avg_lum, desired_avg_lum, steps);
+
+       if ((gain + steps) > gain_high &&
+           exposure < sd->ctrls[EXPOSURE].max) {
+               gain = gain_high;
+               sd->exp_too_low_cnt++;
+               sd->exp_too_high_cnt = 0;
+       } else if ((gain + steps) < gain_low &&
+                  exposure > sd->ctrls[EXPOSURE].min) {
+               gain = gain_low;
+               sd->exp_too_high_cnt++;
+               sd->exp_too_low_cnt = 0;
+       } else {
+               gain += steps;
+               if (gain > sd->ctrls[GAIN].max)
+                       gain = sd->ctrls[GAIN].max;
+               else if (gain < sd->ctrls[GAIN].min)
+                       gain = sd->ctrls[GAIN].min;
+               sd->exp_too_high_cnt = 0;
+               sd->exp_too_low_cnt = 0;
+       }
+
+       if (sd->exp_too_high_cnt > 3) {
+               exposure--;
+               sd->exp_too_high_cnt = 0;
+       } else if (sd->exp_too_low_cnt > 3) {
+               exposure++;
+               sd->exp_too_low_cnt = 0;
+       }
+
+       if (gain != orig_gain) {
+               sd->ctrls[GAIN].val = gain;
+               setgain(gspca_dev);
+               retval = 1;
+       }
+       if (exposure != orig_exposure) {
+               sd->ctrls[EXPOSURE].val = exposure;
+               setexposure(gspca_dev);
+               retval = 1;
+       }
+
+       if (retval)
+               PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
+                       gain, exposure);
+       return retval;
+}
+#endif
diff --git a/drivers/media/usb/gspca/benq.c b/drivers/media/usb/gspca/benq.c
new file mode 100644 (file)
index 0000000..352f321
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * Benq DC E300 subdriver
+ *
+ * Copyright (C) 2009 Jean-Francois Moine (http://moinejf.free.fr)
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "benq"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
+MODULE_DESCRIPTION("Benq DC E300 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+};
+
+static void sd_isoc_irq(struct urb *urb);
+
+/* -- write a register -- */
+static void reg_w(struct gspca_dev *gspca_dev,
+                       u16 value, u16 index)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                       0x02,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value,
+                       index,
+                       NULL,
+                       0,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_w err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+/* this function is called at probe time */
+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);
+       gspca_dev->cam.no_urb_create = 1;
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       return 0;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct urb *urb;
+       int i, n;
+
+       /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */
+#if MAX_NURBS < 4
+#error "Not enough URBs in the gspca table"
+#endif
+#define SD_PKT_SZ 64
+#define SD_NPKT 32
+       for (n = 0; n < 4; n++) {
+               urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
+               if (!urb) {
+                       pr_err("usb_alloc_urb failed\n");
+                       return -ENOMEM;
+               }
+               gspca_dev->urb[n] = urb;
+               urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
+                                               SD_PKT_SZ * SD_NPKT,
+                                               GFP_KERNEL,
+                                               &urb->transfer_dma);
+
+               if (urb->transfer_buffer == NULL) {
+                       pr_err("usb_alloc_coherent failed\n");
+                       return -ENOMEM;
+               }
+               urb->dev = gspca_dev->dev;
+               urb->context = gspca_dev;
+               urb->transfer_buffer_length = SD_PKT_SZ * SD_NPKT;
+               urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
+                                       n & 1 ? 0x82 : 0x83);
+               urb->transfer_flags = URB_ISO_ASAP
+                                       | URB_NO_TRANSFER_DMA_MAP;
+               urb->interval = 1;
+               urb->complete = sd_isoc_irq;
+               urb->number_of_packets = SD_NPKT;
+               for (i = 0; i < SD_NPKT; i++) {
+                       urb->iso_frame_desc[i].length = SD_PKT_SZ;
+                       urb->iso_frame_desc[i].offset = SD_PKT_SZ * i;
+               }
+       }
+
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct usb_interface *intf;
+
+       reg_w(gspca_dev, 0x003c, 0x0003);
+       reg_w(gspca_dev, 0x003c, 0x0004);
+       reg_w(gspca_dev, 0x003c, 0x0005);
+       reg_w(gspca_dev, 0x003c, 0x0006);
+       reg_w(gspca_dev, 0x003c, 0x0007);
+
+       intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
+       usb_set_interface(gspca_dev->dev, gspca_dev->iface,
+                                       intf->num_altsetting - 1);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,               /* isoc packet */
+                       int len)                /* iso packet length */
+{
+       /* unused */
+}
+
+/* reception of an URB */
+static void sd_isoc_irq(struct urb *urb)
+{
+       struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
+       struct urb *urb0;
+       u8 *data;
+       int i, st;
+
+       PDEBUG(D_PACK, "sd isoc irq");
+       if (!gspca_dev->streaming)
+               return;
+       if (urb->status != 0) {
+               if (urb->status == -ESHUTDOWN)
+                       return;         /* disconnection */
+#ifdef CONFIG_PM
+               if (gspca_dev->frozen)
+                       return;
+#endif
+               pr_err("urb status: %d\n", urb->status);
+               return;
+       }
+
+       /* if this is a control URN (ep 0x83), wait */
+       if (urb == gspca_dev->urb[0] || urb == gspca_dev->urb[2])
+               return;
+
+       /* scan both received URBs */
+       if (urb == gspca_dev->urb[1])
+               urb0 = gspca_dev->urb[0];
+       else
+               urb0 = gspca_dev->urb[2];
+       for (i = 0; i < urb->number_of_packets; i++) {
+
+               /* check the packet status and length */
+               if (urb0->iso_frame_desc[i].actual_length != SD_PKT_SZ
+                   || urb->iso_frame_desc[i].actual_length != SD_PKT_SZ) {
+                       PDEBUG(D_ERR, "ISOC bad lengths %d / %d",
+                               urb0->iso_frame_desc[i].actual_length,
+                               urb->iso_frame_desc[i].actual_length);
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+                       continue;
+               }
+               st = urb0->iso_frame_desc[i].status;
+               if (st == 0)
+                       st = urb->iso_frame_desc[i].status;
+               if (st) {
+                       pr_err("ISOC data error: [%d] status=%d\n",
+                               i, st);
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+                       continue;
+               }
+
+               /*
+                * The images are received in URBs of different endpoints
+                * (0x83 and 0x82).
+                * Image pieces in URBs of ep 0x83 are continuated in URBs of
+                * ep 0x82 of the same index.
+                * The packets in the URBs of endpoint 0x83 start with:
+                *      - 80 ba/bb 00 00 = start of image followed by 'ff d8'
+                *      - 04 ba/bb oo oo = image piece
+                *              where 'oo oo' is the image offset
+                                               (not cheked)
+                *      - (other -> bad frame)
+                * The images are JPEG encoded with full header and
+                * normal ff escape.
+                * The end of image ('ff d9') may occur in any URB.
+                * (not cheked)
+                */
+               data = (u8 *) urb0->transfer_buffer
+                                       + urb0->iso_frame_desc[i].offset;
+               if (data[0] == 0x80 && (data[1] & 0xfe) == 0xba) {
+
+                       /* new image */
+                       gspca_frame_add(gspca_dev, LAST_PACKET,
+                                       NULL, 0);
+                       gspca_frame_add(gspca_dev, FIRST_PACKET,
+                                       data + 4, SD_PKT_SZ - 4);
+               } else if (data[0] == 0x04 && (data[1] & 0xfe) == 0xba) {
+                       gspca_frame_add(gspca_dev, INTER_PACKET,
+                                       data + 4, SD_PKT_SZ - 4);
+               } else {
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+                       continue;
+               }
+               data = (u8 *) urb->transfer_buffer
+                                       + urb->iso_frame_desc[i].offset;
+                       gspca_frame_add(gspca_dev, INTER_PACKET,
+                                       data, SD_PKT_SZ);
+       }
+
+       /* resubmit the URBs */
+       st = usb_submit_urb(urb0, GFP_ATOMIC);
+       if (st < 0)
+               pr_err("usb_submit_urb(0) ret %d\n", st);
+       st = usb_submit_urb(urb, GFP_ATOMIC);
+       if (st < 0)
+               pr_err("usb_submit_urb() ret %d\n", st);
+}
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name = MODULE_NAME,
+       .config = sd_config,
+       .init = sd_init,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x04a5, 0x3035)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/conex.c b/drivers/media/usb/gspca/conex.c
new file mode 100644 (file)
index 0000000..c9052f2
--- /dev/null
@@ -0,0 +1,966 @@
+/*
+ *             Connexant Cx11646 library
+ *             Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
+ *
+ * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "conex"
+
+#include "gspca.h"
+#define CONEX_CAM 1            /* special JPEG header */
+#include "jpeg.h"
+
+MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
+MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
+MODULE_LICENSE("GPL");
+
+#define QUALITY 50
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+       struct v4l2_ctrl *brightness;
+       struct v4l2_ctrl *contrast;
+       struct v4l2_ctrl *sat;
+
+       u8 jpeg_hdr[JPEG_HDR_SZ];
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 3},
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2},
+       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+
+/* the read bytes are found in gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev,
+                 __u16 index,
+                 __u16 len)
+{
+       struct usb_device *dev = gspca_dev->dev;
+
+#ifdef GSPCA_DEBUG
+       if (len > USB_BUF_SZ) {
+               pr_err("reg_r: buffer overflow\n");
+               return;
+       }
+#endif
+       usb_control_msg(dev,
+                       usb_rcvctrlpipe(dev, 0),
+                       0,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,
+                       index, gspca_dev->usb_buf, len,
+                       500);
+       PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
+                       index, gspca_dev->usb_buf[0]);
+}
+
+/* the bytes to write are in gspca_dev->usb_buf */
+static void reg_w_val(struct gspca_dev *gspca_dev,
+                       __u16 index,
+                       __u8 val)
+{
+       struct usb_device *dev = gspca_dev->dev;
+
+       gspca_dev->usb_buf[0] = val;
+       usb_control_msg(dev,
+                       usb_sndctrlpipe(dev, 0),
+                       0,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,
+                       index, gspca_dev->usb_buf, 1, 500);
+}
+
+static void reg_w(struct gspca_dev *gspca_dev,
+                 __u16 index,
+                 const __u8 *buffer,
+                 __u16 len)
+{
+       struct usb_device *dev = gspca_dev->dev;
+
+#ifdef GSPCA_DEBUG
+       if (len > USB_BUF_SZ) {
+               pr_err("reg_w: buffer overflow\n");
+               return;
+       }
+       PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
+#endif
+       memcpy(gspca_dev->usb_buf, buffer, len);
+       usb_control_msg(dev,
+                       usb_sndctrlpipe(dev, 0),
+                       0,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,
+                       index, gspca_dev->usb_buf, len, 500);
+}
+
+static const __u8 cx_sensor_init[][4] = {
+       {0x88, 0x11, 0x01, 0x01},
+       {0x88, 0x12, 0x70, 0x01},
+       {0x88, 0x0f, 0x00, 0x01},
+       {0x88, 0x05, 0x01, 0x01},
+       {}
+};
+
+static const __u8 cx11646_fw1[][3] = {
+       {0x00, 0x02, 0x00},
+       {0x01, 0x43, 0x00},
+       {0x02, 0xA7, 0x00},
+       {0x03, 0x8B, 0x01},
+       {0x04, 0xE9, 0x02},
+       {0x05, 0x08, 0x04},
+       {0x06, 0x08, 0x05},
+       {0x07, 0x07, 0x06},
+       {0x08, 0xE7, 0x06},
+       {0x09, 0xC6, 0x07},
+       {0x0A, 0x86, 0x08},
+       {0x0B, 0x46, 0x09},
+       {0x0C, 0x05, 0x0A},
+       {0x0D, 0xA5, 0x0A},
+       {0x0E, 0x45, 0x0B},
+       {0x0F, 0xE5, 0x0B},
+       {0x10, 0x85, 0x0C},
+       {0x11, 0x25, 0x0D},
+       {0x12, 0xC4, 0x0D},
+       {0x13, 0x45, 0x0E},
+       {0x14, 0xE4, 0x0E},
+       {0x15, 0x64, 0x0F},
+       {0x16, 0xE4, 0x0F},
+       {0x17, 0x64, 0x10},
+       {0x18, 0xE4, 0x10},
+       {0x19, 0x64, 0x11},
+       {0x1A, 0xE4, 0x11},
+       {0x1B, 0x64, 0x12},
+       {0x1C, 0xE3, 0x12},
+       {0x1D, 0x44, 0x13},
+       {0x1E, 0xC3, 0x13},
+       {0x1F, 0x24, 0x14},
+       {0x20, 0xA3, 0x14},
+       {0x21, 0x04, 0x15},
+       {0x22, 0x83, 0x15},
+       {0x23, 0xE3, 0x15},
+       {0x24, 0x43, 0x16},
+       {0x25, 0xA4, 0x16},
+       {0x26, 0x23, 0x17},
+       {0x27, 0x83, 0x17},
+       {0x28, 0xE3, 0x17},
+       {0x29, 0x43, 0x18},
+       {0x2A, 0xA3, 0x18},
+       {0x2B, 0x03, 0x19},
+       {0x2C, 0x63, 0x19},
+       {0x2D, 0xC3, 0x19},
+       {0x2E, 0x22, 0x1A},
+       {0x2F, 0x63, 0x1A},
+       {0x30, 0xC3, 0x1A},
+       {0x31, 0x23, 0x1B},
+       {0x32, 0x83, 0x1B},
+       {0x33, 0xE2, 0x1B},
+       {0x34, 0x23, 0x1C},
+       {0x35, 0x83, 0x1C},
+       {0x36, 0xE2, 0x1C},
+       {0x37, 0x23, 0x1D},
+       {0x38, 0x83, 0x1D},
+       {0x39, 0xE2, 0x1D},
+       {0x3A, 0x23, 0x1E},
+       {0x3B, 0x82, 0x1E},
+       {0x3C, 0xC3, 0x1E},
+       {0x3D, 0x22, 0x1F},
+       {0x3E, 0x63, 0x1F},
+       {0x3F, 0xC1, 0x1F},
+       {}
+};
+static void cx11646_fw(struct gspca_dev*gspca_dev)
+{
+       int i = 0;
+
+       reg_w_val(gspca_dev, 0x006a, 0x02);
+       while (cx11646_fw1[i][1]) {
+               reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
+               i++;
+       }
+       reg_w_val(gspca_dev, 0x006a, 0x00);
+}
+
+static const __u8 cxsensor[] = {
+       0x88, 0x12, 0x70, 0x01,
+       0x88, 0x0d, 0x02, 0x01,
+       0x88, 0x0f, 0x00, 0x01,
+       0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
+       0x88, 0x02, 0x10, 0x01,
+       0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
+       0x88, 0x0B, 0x00, 0x01,
+       0x88, 0x0A, 0x0A, 0x01,
+       0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
+       0x88, 0x05, 0x01, 0x01,
+       0xA1, 0x18, 0x00, 0x01,
+       0x00
+};
+
+static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
+static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
+static const __u8 reg10[] = { 0xb1, 0xb1 };
+static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e };       /* 640 */
+static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
+       /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
+static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
+                                       /* 320{0x04,0x0c,0x05,0x0f}; //320 */
+static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 };       /* 176 */
+static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
+
+static void cx_sensor(struct gspca_dev*gspca_dev)
+{
+       int i = 0;
+       int length;
+       const __u8 *ptsensor = cxsensor;
+
+       reg_w(gspca_dev, 0x0020, reg20, 8);
+       reg_w(gspca_dev, 0x0028, reg28, 8);
+       reg_w(gspca_dev, 0x0010, reg10, 2);
+       reg_w_val(gspca_dev, 0x0092, 0x03);
+
+       switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
+       case 0:
+               reg_w(gspca_dev, 0x0071, reg71a, 4);
+               break;
+       case 1:
+               reg_w(gspca_dev, 0x0071, reg71b, 4);
+               break;
+       default:
+/*     case 2: */
+               reg_w(gspca_dev, 0x0071, reg71c, 4);
+               break;
+       case 3:
+               reg_w(gspca_dev, 0x0071, reg71d, 4);
+               break;
+       }
+       reg_w(gspca_dev, 0x007b, reg7b, 6);
+       reg_w_val(gspca_dev, 0x00f8, 0x00);
+       reg_w(gspca_dev, 0x0010, reg10, 2);
+       reg_w_val(gspca_dev, 0x0098, 0x41);
+       for (i = 0; i < 11; i++) {
+               if (i == 3 || i == 5 || i == 8)
+                       length = 8;
+               else
+                       length = 4;
+               reg_w(gspca_dev, 0x00e5, ptsensor, length);
+               if (length == 4)
+                       reg_r(gspca_dev, 0x00e8, 1);
+               else
+                       reg_r(gspca_dev, 0x00e8, length);
+               ptsensor += length;
+       }
+       reg_r(gspca_dev, 0x00e7, 8);
+}
+
+static const __u8 cx_inits_176[] = {
+       0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
+       0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
+       0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
+       0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
+       0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
+       0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
+       0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+static const __u8 cx_inits_320[] = {
+       0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
+       0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
+       0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
+       0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+       0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
+       0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
+       0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+static const __u8 cx_inits_352[] = {
+       0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
+       0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
+       0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
+       0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
+       0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
+       0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
+       0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+static const __u8 cx_inits_640[] = {
+       0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
+       0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
+       0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
+       0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+       0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
+       0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
+       0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static void cx11646_initsize(struct gspca_dev *gspca_dev)
+{
+       const __u8 *cxinit;
+       static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
+       static const __u8 reg17[] =
+                       { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
+
+       switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
+       case 0:
+               cxinit = cx_inits_640;
+               break;
+       case 1:
+               cxinit = cx_inits_352;
+               break;
+       default:
+/*     case 2: */
+               cxinit = cx_inits_320;
+               break;
+       case 3:
+               cxinit = cx_inits_176;
+               break;
+       }
+       reg_w_val(gspca_dev, 0x009a, 0x01);
+       reg_w_val(gspca_dev, 0x0010, 0x10);
+       reg_w(gspca_dev, 0x0012, reg12, 5);
+       reg_w(gspca_dev, 0x0017, reg17, 8);
+       reg_w_val(gspca_dev, 0x00c0, 0x00);
+       reg_w_val(gspca_dev, 0x00c1, 0x04);
+       reg_w_val(gspca_dev, 0x00c2, 0x04);
+
+       reg_w(gspca_dev, 0x0061, cxinit, 8);
+       cxinit += 8;
+       reg_w(gspca_dev, 0x00ca, cxinit, 8);
+       cxinit += 8;
+       reg_w(gspca_dev, 0x00d2, cxinit, 8);
+       cxinit += 8;
+       reg_w(gspca_dev, 0x00da, cxinit, 6);
+       cxinit += 8;
+       reg_w(gspca_dev, 0x0041, cxinit, 8);
+       cxinit += 8;
+       reg_w(gspca_dev, 0x0049, cxinit, 8);
+       cxinit += 8;
+       reg_w(gspca_dev, 0x0051, cxinit, 2);
+
+       reg_r(gspca_dev, 0x0010, 1);
+}
+
+static const __u8 cx_jpeg_init[][8] = {
+       {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15},       /* 1 */
+       {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
+       {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
+       {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
+       {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
+       {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
+       {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
+       {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
+       {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
+       {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
+       {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
+       {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
+       {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
+       {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
+       {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
+       {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
+       {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
+       {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
+       {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
+       {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
+       {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
+       {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
+       {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
+       {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
+       {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
+       {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
+       {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
+       {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
+       {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
+       {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
+       {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
+       {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
+       {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
+       {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
+       {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
+       {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
+       {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
+       {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
+       {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
+       {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
+       {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
+       {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
+       {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
+       {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
+       {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
+       {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
+       {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
+       {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
+       {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
+       {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
+       {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
+       {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
+       {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
+       {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
+       {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
+       {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
+       {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
+       {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
+       {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
+       {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
+       {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
+       {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
+       {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
+       {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
+       {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
+       {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
+       {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
+       {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
+       {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
+       {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
+       {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
+       {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
+       {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
+       {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
+       {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
+       {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
+       {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
+       {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00}        /* 79 */
+};
+
+
+static const __u8 cxjpeg_640[][8] = {
+       {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10},       /* 1 */
+       {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
+       {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
+       {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
+       {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
+       {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
+       {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
+       {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
+       {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
+       {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
+       {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
+       {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
+       {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
+       {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
+       {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
+       {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
+       {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
+       {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
+       {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
+       {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
+       {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
+       {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
+       {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
+       {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
+       {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
+       {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
+       {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}        /* 27 */
+};
+static const __u8 cxjpeg_352[][8] = {
+       {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
+       {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
+       {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
+       {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
+       {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
+       {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
+       {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
+       {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
+       {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
+       {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
+       {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
+       {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
+       {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
+       {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
+       {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
+       {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
+       {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
+       {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
+       {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
+       {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
+       {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
+       {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
+       {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
+       {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
+       {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
+       {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
+       {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+static const __u8 cxjpeg_320[][8] = {
+       {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
+       {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
+       {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
+       {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
+       {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
+       {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
+       {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
+       {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
+       {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
+       {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
+       {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
+       {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
+       {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
+       {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
+       {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
+       {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
+       {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
+       {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
+       {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
+       {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
+       {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
+       {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
+       {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
+       {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
+       {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
+       {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
+       {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}        /* 27 */
+};
+static const __u8 cxjpeg_176[][8] = {
+       {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
+       {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
+       {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
+       {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
+       {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
+       {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
+       {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
+       {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
+       {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
+       {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
+       {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
+       {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
+       {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
+       {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
+       {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
+       {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
+       {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
+       {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
+       {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
+       {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
+       {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
+       {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
+       {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
+       {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
+       {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
+       {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
+       {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+};
+/* 640 take with the zcx30x part */
+static const __u8 cxjpeg_qtable[][8] = {
+       {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
+       {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
+       {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
+       {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
+       {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
+       {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
+       {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
+       {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
+       {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
+       {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
+       {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
+       {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
+       {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
+       {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
+       {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
+       {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
+       {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
+       {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}        /* 18 */
+};
+
+
+static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
+{
+       int i;
+       int length;
+
+       reg_w_val(gspca_dev, 0x00c0, 0x01);
+       reg_w_val(gspca_dev, 0x00c3, 0x00);
+       reg_w_val(gspca_dev, 0x00c0, 0x00);
+       reg_r(gspca_dev, 0x0001, 1);
+       length = 8;
+       for (i = 0; i < 79; i++) {
+               if (i == 78)
+                       length = 6;
+               reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
+       }
+       reg_r(gspca_dev, 0x0002, 1);
+       reg_w_val(gspca_dev, 0x0055, 0x14);
+}
+
+static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
+static const __u8 regE5_8[] =
+               { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
+static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
+static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
+static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
+static const __u8 reg51[] = { 0x77, 0x03 };
+#define reg70 0x03
+
+static void cx11646_jpeg(struct gspca_dev*gspca_dev)
+{
+       int i;
+       int length;
+       __u8 Reg55;
+       int retry;
+
+       reg_w_val(gspca_dev, 0x00c0, 0x01);
+       reg_w_val(gspca_dev, 0x00c3, 0x00);
+       reg_w_val(gspca_dev, 0x00c0, 0x00);
+       reg_r(gspca_dev, 0x0001, 1);
+       length = 8;
+       switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) {
+       case 0:
+               for (i = 0; i < 27; i++) {
+                       if (i == 26)
+                               length = 2;
+                       reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
+               }
+               Reg55 = 0x28;
+               break;
+       case 1:
+               for (i = 0; i < 27; i++) {
+                       if (i == 26)
+                               length = 2;
+                       reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
+               }
+               Reg55 = 0x16;
+               break;
+       default:
+/*     case 2: */
+               for (i = 0; i < 27; i++) {
+                       if (i == 26)
+                               length = 2;
+                       reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
+               }
+               Reg55 = 0x14;
+               break;
+       case 3:
+               for (i = 0; i < 27; i++) {
+                       if (i == 26)
+                               length = 2;
+                       reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
+               }
+               Reg55 = 0x0B;
+               break;
+       }
+
+       reg_r(gspca_dev, 0x0002, 1);
+       reg_w_val(gspca_dev, 0x0055, Reg55);
+       reg_r(gspca_dev, 0x0002, 1);
+       reg_w(gspca_dev, 0x0010, reg10, 2);
+       reg_w_val(gspca_dev, 0x0054, 0x02);
+       reg_w_val(gspca_dev, 0x0054, 0x01);
+       reg_w_val(gspca_dev, 0x0000, 0x94);
+       reg_w_val(gspca_dev, 0x0053, 0xc0);
+       reg_w_val(gspca_dev, 0x00fc, 0xe1);
+       reg_w_val(gspca_dev, 0x0000, 0x00);
+       /* wait for completion */
+       retry = 50;
+       do {
+               reg_r(gspca_dev, 0x0002, 1);
+                                                       /* 0x07 until 0x00 */
+               if (gspca_dev->usb_buf[0] == 0x00)
+                       break;
+               reg_w_val(gspca_dev, 0x0053, 0x00);
+       } while (--retry);
+       if (retry == 0)
+               PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
+       /* send the qtable now */
+       reg_r(gspca_dev, 0x0001, 1);            /* -> 0x18 */
+       length = 8;
+       for (i = 0; i < 18; i++) {
+               if (i == 17)
+                       length = 2;
+               reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
+
+       }
+       reg_r(gspca_dev, 0x0002, 1);    /* 0x00 */
+       reg_r(gspca_dev, 0x0053, 1);    /* 0x00 */
+       reg_w_val(gspca_dev, 0x0054, 0x02);
+       reg_w_val(gspca_dev, 0x0054, 0x01);
+       reg_w_val(gspca_dev, 0x0000, 0x94);
+       reg_w_val(gspca_dev, 0x0053, 0xc0);
+
+       reg_r(gspca_dev, 0x0038, 1);            /* 0x40 */
+       reg_r(gspca_dev, 0x0038, 1);            /* 0x40 */
+       reg_r(gspca_dev, 0x001f, 1);            /* 0x38 */
+       reg_w(gspca_dev, 0x0012, reg12, 5);
+       reg_w(gspca_dev, 0x00e5, regE5_8, 8);
+       reg_r(gspca_dev, 0x00e8, 8);
+       reg_w(gspca_dev, 0x00e5, regE5a, 4);
+       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
+       reg_w_val(gspca_dev, 0x009a, 0x01);
+       reg_w(gspca_dev, 0x00e5, regE5b, 4);
+       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
+       reg_w(gspca_dev, 0x00e5, regE5c, 4);
+       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
+
+       reg_w(gspca_dev, 0x0051, reg51, 2);
+       reg_w(gspca_dev, 0x0010, reg10, 2);
+       reg_w_val(gspca_dev, 0x0070, reg70);
+}
+
+static void cx11646_init1(struct gspca_dev *gspca_dev)
+{
+       int i = 0;
+
+       reg_w_val(gspca_dev, 0x0010, 0x00);
+       reg_w_val(gspca_dev, 0x0053, 0x00);
+       reg_w_val(gspca_dev, 0x0052, 0x00);
+       reg_w_val(gspca_dev, 0x009b, 0x2f);
+       reg_w_val(gspca_dev, 0x009c, 0x10);
+       reg_r(gspca_dev, 0x0098, 1);
+       reg_w_val(gspca_dev, 0x0098, 0x40);
+       reg_r(gspca_dev, 0x0099, 1);
+       reg_w_val(gspca_dev, 0x0099, 0x07);
+       reg_w_val(gspca_dev, 0x0039, 0x40);
+       reg_w_val(gspca_dev, 0x003c, 0xff);
+       reg_w_val(gspca_dev, 0x003f, 0x1f);
+       reg_w_val(gspca_dev, 0x003d, 0x40);
+/*     reg_w_val(gspca_dev, 0x003d, 0x60); */
+       reg_r(gspca_dev, 0x0099, 1);                    /* ->0x07 */
+
+       while (cx_sensor_init[i][0]) {
+               reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
+               reg_r(gspca_dev, 0x00e8, 1);            /* -> 0x00 */
+               if (i == 1) {
+                       reg_w_val(gspca_dev, 0x00ed, 0x01);
+                       reg_r(gspca_dev, 0x00ed, 1);    /* -> 0x01 */
+               }
+               i++;
+       }
+       reg_w_val(gspca_dev, 0x00c3, 0x00);
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct cam *cam;
+
+       cam = &gspca_dev->cam;
+       cam->cam_mode = vga_mode;
+       cam->nmodes = ARRAY_SIZE(vga_mode);
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       cx11646_init1(gspca_dev);
+       cx11646_initsize(gspca_dev);
+       cx11646_fw(gspca_dev);
+       cx_sensor(gspca_dev);
+       cx11646_jpegInit(gspca_dev);
+       return 0;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* create the JPEG header */
+       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+                       0x22);          /* JPEG 411 */
+       jpeg_set_qual(sd->jpeg_hdr, QUALITY);
+
+       cx11646_initsize(gspca_dev);
+       cx11646_fw(gspca_dev);
+       cx_sensor(gspca_dev);
+       cx11646_jpeg(gspca_dev);
+       return 0;
+}
+
+/* called on streamoff with alt 0 and on disconnect */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       int retry = 50;
+
+       if (!gspca_dev->present)
+               return;
+       reg_w_val(gspca_dev, 0x0000, 0x00);
+       reg_r(gspca_dev, 0x0002, 1);
+       reg_w_val(gspca_dev, 0x0053, 0x00);
+
+       while (retry--) {
+/*             reg_r(gspca_dev, 0x0002, 1);*/
+               reg_r(gspca_dev, 0x0053, 1);
+               if (gspca_dev->usb_buf[0] == 0)
+                       break;
+       }
+       reg_w_val(gspca_dev, 0x0000, 0x00);
+       reg_r(gspca_dev, 0x0002, 1);
+
+       reg_w_val(gspca_dev, 0x0010, 0x00);
+       reg_r(gspca_dev, 0x0033, 1);
+       reg_w_val(gspca_dev, 0x00fc, 0xe0);
+}
+
+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 (data[0] == 0xff && data[1] == 0xd8) {
+
+               /* start of frame */
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+
+               /* put the JPEG header in the new frame */
+               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                               sd->jpeg_hdr, JPEG_HDR_SZ);
+               data += 2;
+               len -= 2;
+       }
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat)
+{
+       __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
+       __u8 reg51c[2];
+
+       regE5cbx[2] = val;
+       reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
+       reg_r(gspca_dev, 0x00e8, 8);
+       reg_w(gspca_dev, 0x00e5, regE5c, 4);
+       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
+
+       reg51c[0] = 0x77;
+       reg51c[1] = sat;
+       reg_w(gspca_dev, 0x0051, reg51c, 2);
+       reg_w(gspca_dev, 0x0010, reg10, 2);
+       reg_w_val(gspca_dev, 0x0070, reg70);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat)
+{
+       __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 };   /* seem MSB */
+/*     __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01};     * LSB */
+       __u8 reg51c[2];
+
+       regE5acx[2] = val;
+       reg_w(gspca_dev, 0x00e5, regE5acx, 4);
+       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
+       reg51c[0] = 0x77;
+       reg51c[1] = sat;
+       reg_w(gspca_dev, 0x0051, reg51c, 2);
+       reg_w(gspca_dev, 0x0010, reg10, 2);
+       reg_w_val(gspca_dev, 0x0070, reg70);
+}
+
+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_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
+               break;
+       case V4L2_CID_SATURATION:
+               setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val);
+               setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->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, 3);
+       sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 0xd4);
+       sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0x0a, 0x1f, 1, 0x0c);
+       sd->sat = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 7, 1, 3);
+       if (hdl->error) {
+               pr_err("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,
+       .stop0 = sd_stop0,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x0572, 0x0041)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/cpia1.c b/drivers/media/usb/gspca/cpia1.c
new file mode 100644 (file)
index 0000000..2499a88
--- /dev/null
@@ -0,0 +1,1905 @@
+/*
+ * cpia CPiA (1) gspca driver
+ *
+ * Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This module is adapted from the in kernel v4l1 cpia driver which is :
+ *
+ * (C) Copyright 1999-2000 Peter Pregler
+ * (C) Copyright 1999-2000 Scott J. Bertin
+ * (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com>
+ * (C) Copyright 2000 STMicroelectronics
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "cpia1"
+
+#include <linux/input.h>
+#include "gspca.h"
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("Vision CPiA");
+MODULE_LICENSE("GPL");
+
+/* constant value's */
+#define MAGIC_0                0x19
+#define MAGIC_1                0x68
+#define DATA_IN                0xc0
+#define DATA_OUT       0x40
+#define VIDEOSIZE_QCIF 0       /* 176x144 */
+#define VIDEOSIZE_CIF  1       /* 352x288 */
+#define SUBSAMPLE_420  0
+#define SUBSAMPLE_422  1
+#define YUVORDER_YUYV  0
+#define YUVORDER_UYVY  1
+#define NOT_COMPRESSED 0
+#define COMPRESSED     1
+#define NO_DECIMATION  0
+#define DECIMATION_ENAB        1
+#define EOI            0xff    /* End Of Image */
+#define EOL            0xfd    /* End Of Line */
+#define FRAME_HEADER_SIZE      64
+
+/* Image grab modes */
+#define CPIA_GRAB_SINGLE       0
+#define CPIA_GRAB_CONTINEOUS   1
+
+/* Compression parameters */
+#define CPIA_COMPRESSION_NONE  0
+#define CPIA_COMPRESSION_AUTO  1
+#define CPIA_COMPRESSION_MANUAL        2
+#define CPIA_COMPRESSION_TARGET_QUALITY         0
+#define CPIA_COMPRESSION_TARGET_FRAMERATE       1
+
+/* Return offsets for GetCameraState */
+#define SYSTEMSTATE    0
+#define GRABSTATE      1
+#define STREAMSTATE    2
+#define FATALERROR     3
+#define CMDERROR       4
+#define DEBUGFLAGS     5
+#define VPSTATUS       6
+#define ERRORCODE      7
+
+/* SystemState */
+#define UNINITIALISED_STATE    0
+#define PASS_THROUGH_STATE     1
+#define LO_POWER_STATE         2
+#define HI_POWER_STATE         3
+#define WARM_BOOT_STATE                4
+
+/* GrabState */
+#define GRAB_IDLE              0
+#define GRAB_ACTIVE            1
+#define GRAB_DONE              2
+
+/* StreamState */
+#define STREAM_NOT_READY       0
+#define STREAM_READY           1
+#define STREAM_OPEN            2
+#define STREAM_PAUSED          3
+#define STREAM_FINISHED                4
+
+/* Fatal Error, CmdError, and DebugFlags */
+#define CPIA_FLAG        1
+#define SYSTEM_FLAG      2
+#define INT_CTRL_FLAG    4
+#define PROCESS_FLAG     8
+#define COM_FLAG        16
+#define VP_CTRL_FLAG    32
+#define CAPTURE_FLAG    64
+#define DEBUG_FLAG     128
+
+/* VPStatus */
+#define VP_STATE_OK                    0x00
+
+#define VP_STATE_FAILED_VIDEOINIT      0x01
+#define VP_STATE_FAILED_AECACBINIT     0x02
+#define VP_STATE_AEC_MAX               0x04
+#define VP_STATE_ACB_BMAX              0x08
+
+#define VP_STATE_ACB_RMIN              0x10
+#define VP_STATE_ACB_GMIN              0x20
+#define VP_STATE_ACB_RMAX              0x40
+#define VP_STATE_ACB_GMAX              0x80
+
+/* default (minimum) compensation values */
+#define COMP_RED        220
+#define COMP_GREEN1     214
+#define COMP_GREEN2     COMP_GREEN1
+#define COMP_BLUE       230
+
+/* exposure status */
+#define EXPOSURE_VERY_LIGHT 0
+#define EXPOSURE_LIGHT      1
+#define EXPOSURE_NORMAL     2
+#define EXPOSURE_DARK       3
+#define EXPOSURE_VERY_DARK  4
+
+#define CPIA_MODULE_CPIA                       (0 << 5)
+#define CPIA_MODULE_SYSTEM                     (1 << 5)
+#define CPIA_MODULE_VP_CTRL                    (5 << 5)
+#define CPIA_MODULE_CAPTURE                    (6 << 5)
+#define CPIA_MODULE_DEBUG                      (7 << 5)
+
+#define INPUT (DATA_IN << 8)
+#define OUTPUT (DATA_OUT << 8)
+
+#define CPIA_COMMAND_GetCPIAVersion    (INPUT | CPIA_MODULE_CPIA | 1)
+#define CPIA_COMMAND_GetPnPID          (INPUT | CPIA_MODULE_CPIA | 2)
+#define CPIA_COMMAND_GetCameraStatus   (INPUT | CPIA_MODULE_CPIA | 3)
+#define CPIA_COMMAND_GotoHiPower       (OUTPUT | CPIA_MODULE_CPIA | 4)
+#define CPIA_COMMAND_GotoLoPower       (OUTPUT | CPIA_MODULE_CPIA | 5)
+#define CPIA_COMMAND_GotoSuspend       (OUTPUT | CPIA_MODULE_CPIA | 7)
+#define CPIA_COMMAND_GotoPassThrough   (OUTPUT | CPIA_MODULE_CPIA | 8)
+#define CPIA_COMMAND_ModifyCameraStatus        (OUTPUT | CPIA_MODULE_CPIA | 10)
+
+#define CPIA_COMMAND_ReadVCRegs                (INPUT | CPIA_MODULE_SYSTEM | 1)
+#define CPIA_COMMAND_WriteVCReg                (OUTPUT | CPIA_MODULE_SYSTEM | 2)
+#define CPIA_COMMAND_ReadMCPorts       (INPUT | CPIA_MODULE_SYSTEM | 3)
+#define CPIA_COMMAND_WriteMCPort       (OUTPUT | CPIA_MODULE_SYSTEM | 4)
+#define CPIA_COMMAND_SetBaudRate       (OUTPUT | CPIA_MODULE_SYSTEM | 5)
+#define CPIA_COMMAND_SetECPTiming      (OUTPUT | CPIA_MODULE_SYSTEM | 6)
+#define CPIA_COMMAND_ReadIDATA         (INPUT | CPIA_MODULE_SYSTEM | 7)
+#define CPIA_COMMAND_WriteIDATA                (OUTPUT | CPIA_MODULE_SYSTEM | 8)
+#define CPIA_COMMAND_GenericCall       (OUTPUT | CPIA_MODULE_SYSTEM | 9)
+#define CPIA_COMMAND_I2CStart          (OUTPUT | CPIA_MODULE_SYSTEM | 10)
+#define CPIA_COMMAND_I2CStop           (OUTPUT | CPIA_MODULE_SYSTEM | 11)
+#define CPIA_COMMAND_I2CWrite          (OUTPUT | CPIA_MODULE_SYSTEM | 12)
+#define CPIA_COMMAND_I2CRead           (INPUT | CPIA_MODULE_SYSTEM | 13)
+
+#define CPIA_COMMAND_GetVPVersion      (INPUT | CPIA_MODULE_VP_CTRL | 1)
+#define CPIA_COMMAND_ResetFrameCounter (INPUT | CPIA_MODULE_VP_CTRL | 2)
+#define CPIA_COMMAND_SetColourParams   (OUTPUT | CPIA_MODULE_VP_CTRL | 3)
+#define CPIA_COMMAND_SetExposure       (OUTPUT | CPIA_MODULE_VP_CTRL | 4)
+#define CPIA_COMMAND_SetColourBalance  (OUTPUT | CPIA_MODULE_VP_CTRL | 6)
+#define CPIA_COMMAND_SetSensorFPS      (OUTPUT | CPIA_MODULE_VP_CTRL | 7)
+#define CPIA_COMMAND_SetVPDefaults     (OUTPUT | CPIA_MODULE_VP_CTRL | 8)
+#define CPIA_COMMAND_SetApcor          (OUTPUT | CPIA_MODULE_VP_CTRL | 9)
+#define CPIA_COMMAND_SetFlickerCtrl    (OUTPUT | CPIA_MODULE_VP_CTRL | 10)
+#define CPIA_COMMAND_SetVLOffset       (OUTPUT | CPIA_MODULE_VP_CTRL | 11)
+#define CPIA_COMMAND_GetColourParams   (INPUT | CPIA_MODULE_VP_CTRL | 16)
+#define CPIA_COMMAND_GetColourBalance  (INPUT | CPIA_MODULE_VP_CTRL | 17)
+#define CPIA_COMMAND_GetExposure       (INPUT | CPIA_MODULE_VP_CTRL | 18)
+#define CPIA_COMMAND_SetSensorMatrix   (OUTPUT | CPIA_MODULE_VP_CTRL | 19)
+#define CPIA_COMMAND_ColourBars                (OUTPUT | CPIA_MODULE_VP_CTRL | 25)
+#define CPIA_COMMAND_ReadVPRegs                (INPUT | CPIA_MODULE_VP_CTRL | 30)
+#define CPIA_COMMAND_WriteVPReg                (OUTPUT | CPIA_MODULE_VP_CTRL | 31)
+
+#define CPIA_COMMAND_GrabFrame         (OUTPUT | CPIA_MODULE_CAPTURE | 1)
+#define CPIA_COMMAND_UploadFrame       (OUTPUT | CPIA_MODULE_CAPTURE | 2)
+#define CPIA_COMMAND_SetGrabMode       (OUTPUT | CPIA_MODULE_CAPTURE | 3)
+#define CPIA_COMMAND_InitStreamCap     (OUTPUT | CPIA_MODULE_CAPTURE | 4)
+#define CPIA_COMMAND_FiniStreamCap     (OUTPUT | CPIA_MODULE_CAPTURE | 5)
+#define CPIA_COMMAND_StartStreamCap    (OUTPUT | CPIA_MODULE_CAPTURE | 6)
+#define CPIA_COMMAND_EndStreamCap      (OUTPUT | CPIA_MODULE_CAPTURE | 7)
+#define CPIA_COMMAND_SetFormat         (OUTPUT | CPIA_MODULE_CAPTURE | 8)
+#define CPIA_COMMAND_SetROI            (OUTPUT | CPIA_MODULE_CAPTURE | 9)
+#define CPIA_COMMAND_SetCompression    (OUTPUT | CPIA_MODULE_CAPTURE | 10)
+#define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11)
+#define CPIA_COMMAND_SetYUVThresh      (OUTPUT | CPIA_MODULE_CAPTURE | 12)
+#define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13)
+#define CPIA_COMMAND_DiscardFrame      (OUTPUT | CPIA_MODULE_CAPTURE | 14)
+#define CPIA_COMMAND_GrabReset         (OUTPUT | CPIA_MODULE_CAPTURE | 15)
+
+#define CPIA_COMMAND_OutputRS232       (OUTPUT | CPIA_MODULE_DEBUG | 1)
+#define CPIA_COMMAND_AbortProcess      (OUTPUT | CPIA_MODULE_DEBUG | 4)
+#define CPIA_COMMAND_SetDramPage       (OUTPUT | CPIA_MODULE_DEBUG | 5)
+#define CPIA_COMMAND_StartDramUpload   (OUTPUT | CPIA_MODULE_DEBUG | 6)
+#define CPIA_COMMAND_StartDummyDtream  (OUTPUT | CPIA_MODULE_DEBUG | 8)
+#define CPIA_COMMAND_AbortStream       (OUTPUT | CPIA_MODULE_DEBUG | 9)
+#define CPIA_COMMAND_DownloadDRAM      (OUTPUT | CPIA_MODULE_DEBUG | 10)
+#define CPIA_COMMAND_Null              (OUTPUT | CPIA_MODULE_DEBUG | 11)
+
+#define ROUND_UP_EXP_FOR_FLICKER 15
+
+/* Constants for automatic frame rate adjustment */
+#define MAX_EXP       302
+#define MAX_EXP_102   255
+#define LOW_EXP       140
+#define VERY_LOW_EXP   70
+#define TC             94
+#define        EXP_ACC_DARK   50
+#define        EXP_ACC_LIGHT  90
+#define HIGH_COMP_102 160
+#define MAX_COMP      239
+#define DARK_TIME       3
+#define LIGHT_TIME      3
+
+#define FIRMWARE_VERSION(x, y) (sd->params.version.firmwareVersion == (x) && \
+                               sd->params.version.firmwareRevision == (y))
+
+#define CPIA1_CID_COMP_TARGET (V4L2_CTRL_CLASS_USER + 0x1000)
+#define BRIGHTNESS_DEF 50
+#define CONTRAST_DEF 48
+#define SATURATION_DEF 50
+#define FREQ_DEF V4L2_CID_POWER_LINE_FREQUENCY_50HZ
+#define ILLUMINATORS_1_DEF 0
+#define ILLUMINATORS_2_DEF 0
+#define COMP_TARGET_DEF CPIA_COMPRESSION_TARGET_QUALITY
+
+/* Developer's Guide Table 5 p 3-34
+ * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/
+static u8 flicker_jumps[2][2][4] =
+{ { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } },
+  { { 64, 32, 16, 8 }, { 76, 38, 19, 9} }
+};
+
+struct cam_params {
+       struct {
+               u8 firmwareVersion;
+               u8 firmwareRevision;
+               u8 vcVersion;
+               u8 vcRevision;
+       } version;
+       struct {
+               u16 vendor;
+               u16 product;
+               u16 deviceRevision;
+       } pnpID;
+       struct {
+               u8 vpVersion;
+               u8 vpRevision;
+               u16 cameraHeadID;
+       } vpVersion;
+       struct {
+               u8 systemState;
+               u8 grabState;
+               u8 streamState;
+               u8 fatalError;
+               u8 cmdError;
+               u8 debugFlags;
+               u8 vpStatus;
+               u8 errorCode;
+       } status;
+       struct {
+               u8 brightness;
+               u8 contrast;
+               u8 saturation;
+       } colourParams;
+       struct {
+               u8 gainMode;
+               u8 expMode;
+               u8 compMode;
+               u8 centreWeight;
+               u8 gain;
+               u8 fineExp;
+               u8 coarseExpLo;
+               u8 coarseExpHi;
+               u8 redComp;
+               u8 green1Comp;
+               u8 green2Comp;
+               u8 blueComp;
+       } exposure;
+       struct {
+               u8 balanceMode;
+               u8 redGain;
+               u8 greenGain;
+               u8 blueGain;
+       } colourBalance;
+       struct {
+               u8 divisor;
+               u8 baserate;
+       } sensorFps;
+       struct {
+               u8 gain1;
+               u8 gain2;
+               u8 gain4;
+               u8 gain8;
+       } apcor;
+       struct {
+               u8 disabled;
+               u8 flickerMode;
+               u8 coarseJump;
+               u8 allowableOverExposure;
+       } flickerControl;
+       struct {
+               u8 gain1;
+               u8 gain2;
+               u8 gain4;
+               u8 gain8;
+       } vlOffset;
+       struct {
+               u8 mode;
+               u8 decimation;
+       } compression;
+       struct {
+               u8 frTargeting;
+               u8 targetFR;
+               u8 targetQ;
+       } compressionTarget;
+       struct {
+               u8 yThreshold;
+               u8 uvThreshold;
+       } yuvThreshold;
+       struct {
+               u8 hysteresis;
+               u8 threshMax;
+               u8 smallStep;
+               u8 largeStep;
+               u8 decimationHysteresis;
+               u8 frDiffStepThresh;
+               u8 qDiffStepThresh;
+               u8 decimationThreshMod;
+       } compressionParams;
+       struct {
+               u8 videoSize;           /* CIF/QCIF */
+               u8 subSample;
+               u8 yuvOrder;
+       } format;
+       struct {                        /* Intel QX3 specific data */
+               u8 qx3_detected;        /* a QX3 is present */
+               u8 toplight;            /* top light lit , R/W */
+               u8 bottomlight;         /* bottom light lit, R/W */
+               u8 button;              /* snapshot button pressed (R/O) */
+               u8 cradled;             /* microscope is in cradle (R/O) */
+       } qx3;
+       struct {
+               u8 colStart;            /* skip first 8*colStart pixels */
+               u8 colEnd;              /* finish at 8*colEnd pixels */
+               u8 rowStart;            /* skip first 4*rowStart lines */
+               u8 rowEnd;              /* finish at 4*rowEnd lines */
+       } roi;
+       u8 ecpTiming;
+       u8 streamStartLine;
+};
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;             /* !! must be the first item */
+       struct cam_params params;               /* camera settings */
+
+       atomic_t cam_exposure;
+       atomic_t fps;
+       int exposure_count;
+       u8 exposure_status;
+       struct v4l2_ctrl *freq;
+       u8 mainsFreq;                           /* 0 = 50hz, 1 = 60hz */
+       u8 first_frame;
+};
+
+static const struct v4l2_pix_format mode[] = {
+       {160, 120, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
+               /* The sizeimage is trial and error, as with low framerates
+                  the camera will pad out usb frames, making the image
+                  data larger then strictly necessary */
+               .bytesperline = 160,
+               .sizeimage = 65536,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 3},
+       {176, 144, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
+               .bytesperline = 172,
+               .sizeimage = 65536,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+       {320, 240, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 262144,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {352, 288, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 262144,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+/**********************************************************************
+ *
+ * General functions
+ *
+ **********************************************************************/
+
+static int cpia_usb_transferCmd(struct gspca_dev *gspca_dev, u8 *command)
+{
+       u8 requesttype;
+       unsigned int pipe;
+       int ret, databytes = command[6] | (command[7] << 8);
+       /* Sometimes we see spurious EPIPE errors */
+       int retries = 3;
+
+       if (command[0] == DATA_IN) {
+               pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
+               requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+       } else if (command[0] == DATA_OUT) {
+               pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
+               requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+       } else {
+               PDEBUG(D_ERR, "Unexpected first byte of command: %x",
+                      command[0]);
+               return -EINVAL;
+       }
+
+retry:
+       ret = usb_control_msg(gspca_dev->dev, pipe,
+                             command[1],
+                             requesttype,
+                             command[2] | (command[3] << 8),
+                             command[4] | (command[5] << 8),
+                             gspca_dev->usb_buf, databytes, 1000);
+
+       if (ret < 0)
+               pr_err("usb_control_msg %02x, error %d\n", command[1], ret);
+
+       if (ret == -EPIPE && retries > 0) {
+               retries--;
+               goto retry;
+       }
+
+       return (ret < 0) ? ret : 0;
+}
+
+/* send an arbitrary command to the camera */
+static int do_command(struct gspca_dev *gspca_dev, u16 command,
+                     u8 a, u8 b, u8 c, u8 d)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int ret, datasize;
+       u8 cmd[8];
+
+       switch (command) {
+       case CPIA_COMMAND_GetCPIAVersion:
+       case CPIA_COMMAND_GetPnPID:
+       case CPIA_COMMAND_GetCameraStatus:
+       case CPIA_COMMAND_GetVPVersion:
+       case CPIA_COMMAND_GetColourParams:
+       case CPIA_COMMAND_GetColourBalance:
+       case CPIA_COMMAND_GetExposure:
+               datasize = 8;
+               break;
+       case CPIA_COMMAND_ReadMCPorts:
+       case CPIA_COMMAND_ReadVCRegs:
+               datasize = 4;
+               break;
+       default:
+               datasize = 0;
+               break;
+       }
+
+       cmd[0] = command >> 8;
+       cmd[1] = command & 0xff;
+       cmd[2] = a;
+       cmd[3] = b;
+       cmd[4] = c;
+       cmd[5] = d;
+       cmd[6] = datasize;
+       cmd[7] = 0;
+
+       ret = cpia_usb_transferCmd(gspca_dev, cmd);
+       if (ret)
+               return ret;
+
+       switch (command) {
+       case CPIA_COMMAND_GetCPIAVersion:
+               sd->params.version.firmwareVersion = gspca_dev->usb_buf[0];
+               sd->params.version.firmwareRevision = gspca_dev->usb_buf[1];
+               sd->params.version.vcVersion = gspca_dev->usb_buf[2];
+               sd->params.version.vcRevision = gspca_dev->usb_buf[3];
+               break;
+       case CPIA_COMMAND_GetPnPID:
+               sd->params.pnpID.vendor =
+                       gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8);
+               sd->params.pnpID.product =
+                       gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8);
+               sd->params.pnpID.deviceRevision =
+                       gspca_dev->usb_buf[4] | (gspca_dev->usb_buf[5] << 8);
+               break;
+       case CPIA_COMMAND_GetCameraStatus:
+               sd->params.status.systemState = gspca_dev->usb_buf[0];
+               sd->params.status.grabState = gspca_dev->usb_buf[1];
+               sd->params.status.streamState = gspca_dev->usb_buf[2];
+               sd->params.status.fatalError = gspca_dev->usb_buf[3];
+               sd->params.status.cmdError = gspca_dev->usb_buf[4];
+               sd->params.status.debugFlags = gspca_dev->usb_buf[5];
+               sd->params.status.vpStatus = gspca_dev->usb_buf[6];
+               sd->params.status.errorCode = gspca_dev->usb_buf[7];
+               break;
+       case CPIA_COMMAND_GetVPVersion:
+               sd->params.vpVersion.vpVersion = gspca_dev->usb_buf[0];
+               sd->params.vpVersion.vpRevision = gspca_dev->usb_buf[1];
+               sd->params.vpVersion.cameraHeadID =
+                       gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8);
+               break;
+       case CPIA_COMMAND_GetColourParams:
+               sd->params.colourParams.brightness = gspca_dev->usb_buf[0];
+               sd->params.colourParams.contrast = gspca_dev->usb_buf[1];
+               sd->params.colourParams.saturation = gspca_dev->usb_buf[2];
+               break;
+       case CPIA_COMMAND_GetColourBalance:
+               sd->params.colourBalance.redGain = gspca_dev->usb_buf[0];
+               sd->params.colourBalance.greenGain = gspca_dev->usb_buf[1];
+               sd->params.colourBalance.blueGain = gspca_dev->usb_buf[2];
+               break;
+       case CPIA_COMMAND_GetExposure:
+               sd->params.exposure.gain = gspca_dev->usb_buf[0];
+               sd->params.exposure.fineExp = gspca_dev->usb_buf[1];
+               sd->params.exposure.coarseExpLo = gspca_dev->usb_buf[2];
+               sd->params.exposure.coarseExpHi = gspca_dev->usb_buf[3];
+               sd->params.exposure.redComp = gspca_dev->usb_buf[4];
+               sd->params.exposure.green1Comp = gspca_dev->usb_buf[5];
+               sd->params.exposure.green2Comp = gspca_dev->usb_buf[6];
+               sd->params.exposure.blueComp = gspca_dev->usb_buf[7];
+               break;
+
+       case CPIA_COMMAND_ReadMCPorts:
+               /* test button press */
+               a = ((gspca_dev->usb_buf[1] & 0x02) == 0);
+               if (a != sd->params.qx3.button) {
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+                       input_report_key(gspca_dev->input_dev, KEY_CAMERA, a);
+                       input_sync(gspca_dev->input_dev);
+#endif
+                       sd->params.qx3.button = a;
+               }
+               if (sd->params.qx3.button) {
+                       /* button pressed - unlock the latch */
+                       do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
+                                  3, 0xdf, 0xdf, 0);
+                       do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
+                                  3, 0xff, 0xff, 0);
+               }
+
+               /* test whether microscope is cradled */
+               sd->params.qx3.cradled = ((gspca_dev->usb_buf[2] & 0x40) == 0);
+               break;
+       }
+
+       return 0;
+}
+
+/* send a command to the camera with an additional data transaction */
+static int do_command_extended(struct gspca_dev *gspca_dev, u16 command,
+                              u8 a, u8 b, u8 c, u8 d,
+                              u8 e, u8 f, u8 g, u8 h,
+                              u8 i, u8 j, u8 k, u8 l)
+{
+       u8 cmd[8];
+
+       cmd[0] = command >> 8;
+       cmd[1] = command & 0xff;
+       cmd[2] = a;
+       cmd[3] = b;
+       cmd[4] = c;
+       cmd[5] = d;
+       cmd[6] = 8;
+       cmd[7] = 0;
+       gspca_dev->usb_buf[0] = e;
+       gspca_dev->usb_buf[1] = f;
+       gspca_dev->usb_buf[2] = g;
+       gspca_dev->usb_buf[3] = h;
+       gspca_dev->usb_buf[4] = i;
+       gspca_dev->usb_buf[5] = j;
+       gspca_dev->usb_buf[6] = k;
+       gspca_dev->usb_buf[7] = l;
+
+       return cpia_usb_transferCmd(gspca_dev, cmd);
+}
+
+/*  find_over_exposure
+ *  Finds a suitable value of OverExposure for use with SetFlickerCtrl
+ *  Some calculation is required because this value changes with the brightness
+ *  set with SetColourParameters
+ *
+ *  Parameters: Brightness - last brightness value set with SetColourParameters
+ *
+ *  Returns: OverExposure value to use with SetFlickerCtrl
+ */
+#define FLICKER_MAX_EXPOSURE                    250
+#define FLICKER_ALLOWABLE_OVER_EXPOSURE         146
+#define FLICKER_BRIGHTNESS_CONSTANT             59
+static int find_over_exposure(int brightness)
+{
+       int MaxAllowableOverExposure, OverExposure;
+
+       MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness -
+                                  FLICKER_BRIGHTNESS_CONSTANT;
+
+       if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE)
+               OverExposure = MaxAllowableOverExposure;
+       else
+               OverExposure = FLICKER_ALLOWABLE_OVER_EXPOSURE;
+
+       return OverExposure;
+}
+#undef FLICKER_MAX_EXPOSURE
+#undef FLICKER_ALLOWABLE_OVER_EXPOSURE
+#undef FLICKER_BRIGHTNESS_CONSTANT
+
+/* initialise cam_data structure  */
+static void reset_camera_params(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam_params *params = &sd->params;
+
+       /* The following parameter values are the defaults from
+        * "Software Developer's Guide for CPiA Cameras".  Any changes
+        * to the defaults are noted in comments. */
+       params->colourParams.brightness = BRIGHTNESS_DEF;
+       params->colourParams.contrast = CONTRAST_DEF;
+       params->colourParams.saturation = SATURATION_DEF;
+       params->exposure.gainMode = 4;
+       params->exposure.expMode = 2;           /* AEC */
+       params->exposure.compMode = 1;
+       params->exposure.centreWeight = 1;
+       params->exposure.gain = 0;
+       params->exposure.fineExp = 0;
+       params->exposure.coarseExpLo = 185;
+       params->exposure.coarseExpHi = 0;
+       params->exposure.redComp = COMP_RED;
+       params->exposure.green1Comp = COMP_GREEN1;
+       params->exposure.green2Comp = COMP_GREEN2;
+       params->exposure.blueComp = COMP_BLUE;
+       params->colourBalance.balanceMode = 2;  /* ACB */
+       params->colourBalance.redGain = 32;
+       params->colourBalance.greenGain = 6;
+       params->colourBalance.blueGain = 92;
+       params->apcor.gain1 = 0x18;
+       params->apcor.gain2 = 0x16;
+       params->apcor.gain4 = 0x24;
+       params->apcor.gain8 = 0x34;
+       params->vlOffset.gain1 = 20;
+       params->vlOffset.gain2 = 24;
+       params->vlOffset.gain4 = 26;
+       params->vlOffset.gain8 = 26;
+       params->compressionParams.hysteresis = 3;
+       params->compressionParams.threshMax = 11;
+       params->compressionParams.smallStep = 1;
+       params->compressionParams.largeStep = 3;
+       params->compressionParams.decimationHysteresis = 2;
+       params->compressionParams.frDiffStepThresh = 5;
+       params->compressionParams.qDiffStepThresh = 3;
+       params->compressionParams.decimationThreshMod = 2;
+       /* End of default values from Software Developer's Guide */
+
+       /* Set Sensor FPS to 15fps. This seems better than 30fps
+        * for indoor lighting. */
+       params->sensorFps.divisor = 1;
+       params->sensorFps.baserate = 1;
+
+       params->flickerControl.flickerMode = 0;
+       params->flickerControl.disabled = 1;
+       params->flickerControl.coarseJump =
+               flicker_jumps[sd->mainsFreq]
+                            [params->sensorFps.baserate]
+                            [params->sensorFps.divisor];
+       params->flickerControl.allowableOverExposure =
+               find_over_exposure(params->colourParams.brightness);
+
+       params->yuvThreshold.yThreshold = 6; /* From windows driver */
+       params->yuvThreshold.uvThreshold = 6; /* From windows driver */
+
+       params->format.subSample = SUBSAMPLE_420;
+       params->format.yuvOrder = YUVORDER_YUYV;
+
+       params->compression.mode = CPIA_COMPRESSION_AUTO;
+       params->compression.decimation = NO_DECIMATION;
+
+       params->compressionTarget.frTargeting = COMP_TARGET_DEF;
+       params->compressionTarget.targetFR = 15; /* From windows driver */
+       params->compressionTarget.targetQ = 5; /* From windows driver */
+
+       params->qx3.qx3_detected = 0;
+       params->qx3.toplight = 0;
+       params->qx3.bottomlight = 0;
+       params->qx3.button = 0;
+       params->qx3.cradled = 0;
+}
+
+static void printstatus(struct cam_params *params)
+{
+       PDEBUG(D_PROBE, "status: %02x %02x %02x %02x %02x %02x %02x %02x",
+              params->status.systemState, params->status.grabState,
+              params->status.streamState, params->status.fatalError,
+              params->status.cmdError, params->status.debugFlags,
+              params->status.vpStatus, params->status.errorCode);
+}
+
+static int goto_low_power(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int ret;
+
+       ret = do_command(gspca_dev, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0);
+       if (ret)
+               return ret;
+
+       ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
+       if (ret)
+               return ret;
+
+       if (sd->params.status.systemState != LO_POWER_STATE) {
+               if (sd->params.status.systemState != WARM_BOOT_STATE) {
+                       PDEBUG(D_ERR,
+                              "unexpected state after lo power cmd: %02x",
+                              sd->params.status.systemState);
+                       printstatus(&sd->params);
+               }
+               return -EIO;
+       }
+
+       PDEBUG(D_CONF, "camera now in LOW power state");
+       return 0;
+}
+
+static int goto_high_power(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int ret;
+
+       ret = do_command(gspca_dev, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0);
+       if (ret)
+               return ret;
+
+       msleep_interruptible(40);       /* windows driver does it too */
+
+       if (signal_pending(current))
+               return -EINTR;
+
+       do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
+       if (ret)
+               return ret;
+
+       if (sd->params.status.systemState != HI_POWER_STATE) {
+               PDEBUG(D_ERR, "unexpected state after hi power cmd: %02x",
+                              sd->params.status.systemState);
+               printstatus(&sd->params);
+               return -EIO;
+       }
+
+       PDEBUG(D_CONF, "camera now in HIGH power state");
+       return 0;
+}
+
+static int get_version_information(struct gspca_dev *gspca_dev)
+{
+       int ret;
+
+       /* GetCPIAVersion */
+       ret = do_command(gspca_dev, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0);
+       if (ret)
+               return ret;
+
+       /* GetPnPID */
+       return do_command(gspca_dev, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0);
+}
+
+static int save_camera_state(struct gspca_dev *gspca_dev)
+{
+       int ret;
+
+       ret = do_command(gspca_dev, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
+       if (ret)
+               return ret;
+
+       return do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
+}
+
+static int command_setformat(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int ret;
+
+       ret = do_command(gspca_dev, CPIA_COMMAND_SetFormat,
+                        sd->params.format.videoSize,
+                        sd->params.format.subSample,
+                        sd->params.format.yuvOrder, 0);
+       if (ret)
+               return ret;
+
+       return do_command(gspca_dev, CPIA_COMMAND_SetROI,
+                         sd->params.roi.colStart, sd->params.roi.colEnd,
+                         sd->params.roi.rowStart, sd->params.roi.rowEnd);
+}
+
+static int command_setcolourparams(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       return do_command(gspca_dev, CPIA_COMMAND_SetColourParams,
+                         sd->params.colourParams.brightness,
+                         sd->params.colourParams.contrast,
+                         sd->params.colourParams.saturation, 0);
+}
+
+static int command_setapcor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       return do_command(gspca_dev, CPIA_COMMAND_SetApcor,
+                         sd->params.apcor.gain1,
+                         sd->params.apcor.gain2,
+                         sd->params.apcor.gain4,
+                         sd->params.apcor.gain8);
+}
+
+static int command_setvloffset(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       return do_command(gspca_dev, CPIA_COMMAND_SetVLOffset,
+                         sd->params.vlOffset.gain1,
+                         sd->params.vlOffset.gain2,
+                         sd->params.vlOffset.gain4,
+                         sd->params.vlOffset.gain8);
+}
+
+static int command_setexposure(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int ret;
+
+       ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure,
+                                 sd->params.exposure.gainMode,
+                                 1,
+                                 sd->params.exposure.compMode,
+                                 sd->params.exposure.centreWeight,
+                                 sd->params.exposure.gain,
+                                 sd->params.exposure.fineExp,
+                                 sd->params.exposure.coarseExpLo,
+                                 sd->params.exposure.coarseExpHi,
+                                 sd->params.exposure.redComp,
+                                 sd->params.exposure.green1Comp,
+                                 sd->params.exposure.green2Comp,
+                                 sd->params.exposure.blueComp);
+       if (ret)
+               return ret;
+
+       if (sd->params.exposure.expMode != 1) {
+               ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure,
+                                         0,
+                                         sd->params.exposure.expMode,
+                                         0, 0,
+                                         sd->params.exposure.gain,
+                                         sd->params.exposure.fineExp,
+                                         sd->params.exposure.coarseExpLo,
+                                         sd->params.exposure.coarseExpHi,
+                                         0, 0, 0, 0);
+       }
+
+       return ret;
+}
+
+static int command_setcolourbalance(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->params.colourBalance.balanceMode == 1) {
+               int ret;
+
+               ret = do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
+                                1,
+                                sd->params.colourBalance.redGain,
+                                sd->params.colourBalance.greenGain,
+                                sd->params.colourBalance.blueGain);
+               if (ret)
+                       return ret;
+
+               return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
+                                 3, 0, 0, 0);
+       }
+       if (sd->params.colourBalance.balanceMode == 2) {
+               return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
+                                 2, 0, 0, 0);
+       }
+       if (sd->params.colourBalance.balanceMode == 3) {
+               return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
+                                 3, 0, 0, 0);
+       }
+
+       return -EINVAL;
+}
+
+static int command_setcompressiontarget(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       return do_command(gspca_dev, CPIA_COMMAND_SetCompressionTarget,
+                         sd->params.compressionTarget.frTargeting,
+                         sd->params.compressionTarget.targetFR,
+                         sd->params.compressionTarget.targetQ, 0);
+}
+
+static int command_setyuvtresh(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       return do_command(gspca_dev, CPIA_COMMAND_SetYUVThresh,
+                         sd->params.yuvThreshold.yThreshold,
+                         sd->params.yuvThreshold.uvThreshold, 0, 0);
+}
+
+static int command_setcompressionparams(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       return do_command_extended(gspca_dev,
+                           CPIA_COMMAND_SetCompressionParams,
+                           0, 0, 0, 0,
+                           sd->params.compressionParams.hysteresis,
+                           sd->params.compressionParams.threshMax,
+                           sd->params.compressionParams.smallStep,
+                           sd->params.compressionParams.largeStep,
+                           sd->params.compressionParams.decimationHysteresis,
+                           sd->params.compressionParams.frDiffStepThresh,
+                           sd->params.compressionParams.qDiffStepThresh,
+                           sd->params.compressionParams.decimationThreshMod);
+}
+
+static int command_setcompression(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       return do_command(gspca_dev, CPIA_COMMAND_SetCompression,
+                         sd->params.compression.mode,
+                         sd->params.compression.decimation, 0, 0);
+}
+
+static int command_setsensorfps(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       return do_command(gspca_dev, CPIA_COMMAND_SetSensorFPS,
+                         sd->params.sensorFps.divisor,
+                         sd->params.sensorFps.baserate, 0, 0);
+}
+
+static int command_setflickerctrl(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       return do_command(gspca_dev, CPIA_COMMAND_SetFlickerCtrl,
+                         sd->params.flickerControl.flickerMode,
+                         sd->params.flickerControl.coarseJump,
+                         sd->params.flickerControl.allowableOverExposure,
+                         0);
+}
+
+static int command_setecptiming(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       return do_command(gspca_dev, CPIA_COMMAND_SetECPTiming,
+                         sd->params.ecpTiming, 0, 0, 0);
+}
+
+static int command_pause(struct gspca_dev *gspca_dev)
+{
+       return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0);
+}
+
+static int command_resume(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       return do_command(gspca_dev, CPIA_COMMAND_InitStreamCap,
+                         0, sd->params.streamStartLine, 0, 0);
+}
+
+static int command_setlights(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int ret, p1, p2;
+
+       p1 = (sd->params.qx3.bottomlight == 0) << 1;
+       p2 = (sd->params.qx3.toplight == 0) << 3;
+
+       ret = do_command(gspca_dev, CPIA_COMMAND_WriteVCReg,
+                        0x90, 0x8f, 0x50, 0);
+       if (ret)
+               return ret;
+
+       return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0,
+                         p1 | p2 | 0xe0, 0);
+}
+
+static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply)
+{
+       /* Everything in here is from the Windows driver */
+/* define for compgain calculation */
+#if 0
+#define COMPGAIN(base, curexp, newexp) \
+    (u8) ((((float) base - 128.0) * ((float) curexp / (float) newexp)) + 128.5)
+#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
+    (u16)((float)curexp * (float)(u8)(curcomp + 128) / \
+    (float)(u8)(basecomp - 128))
+#else
+  /* equivalent functions without floating point math */
+#define COMPGAIN(base, curexp, newexp) \
+    (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2 * newexp)))
+#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
+    (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128)))
+#endif
+
+       struct sd *sd = (struct sd *) gspca_dev;
+       int currentexp = sd->params.exposure.coarseExpLo +
+                        sd->params.exposure.coarseExpHi * 256;
+       int ret, startexp;
+
+       if (on) {
+               int cj = sd->params.flickerControl.coarseJump;
+               sd->params.flickerControl.flickerMode = 1;
+               sd->params.flickerControl.disabled = 0;
+               if (sd->params.exposure.expMode != 2) {
+                       sd->params.exposure.expMode = 2;
+                       sd->exposure_status = EXPOSURE_NORMAL;
+               }
+               currentexp = currentexp << sd->params.exposure.gain;
+               sd->params.exposure.gain = 0;
+               /* round down current exposure to nearest value */
+               startexp = (currentexp + ROUND_UP_EXP_FOR_FLICKER) / cj;
+               if (startexp < 1)
+                       startexp = 1;
+               startexp = (startexp * cj) - 1;
+               if (FIRMWARE_VERSION(1, 2))
+                       while (startexp > MAX_EXP_102)
+                               startexp -= cj;
+               else
+                       while (startexp > MAX_EXP)
+                               startexp -= cj;
+               sd->params.exposure.coarseExpLo = startexp & 0xff;
+               sd->params.exposure.coarseExpHi = startexp >> 8;
+               if (currentexp > startexp) {
+                       if (currentexp > (2 * startexp))
+                               currentexp = 2 * startexp;
+                       sd->params.exposure.redComp =
+                               COMPGAIN(COMP_RED, currentexp, startexp);
+                       sd->params.exposure.green1Comp =
+                               COMPGAIN(COMP_GREEN1, currentexp, startexp);
+                       sd->params.exposure.green2Comp =
+                               COMPGAIN(COMP_GREEN2, currentexp, startexp);
+                       sd->params.exposure.blueComp =
+                               COMPGAIN(COMP_BLUE, currentexp, startexp);
+               } else {
+                       sd->params.exposure.redComp = COMP_RED;
+                       sd->params.exposure.green1Comp = COMP_GREEN1;
+                       sd->params.exposure.green2Comp = COMP_GREEN2;
+                       sd->params.exposure.blueComp = COMP_BLUE;
+               }
+               if (FIRMWARE_VERSION(1, 2))
+                       sd->params.exposure.compMode = 0;
+               else
+                       sd->params.exposure.compMode = 1;
+
+               sd->params.apcor.gain1 = 0x18;
+               sd->params.apcor.gain2 = 0x18;
+               sd->params.apcor.gain4 = 0x16;
+               sd->params.apcor.gain8 = 0x14;
+       } else {
+               sd->params.flickerControl.flickerMode = 0;
+               sd->params.flickerControl.disabled = 1;
+               /* Average equivalent coarse for each comp channel */
+               startexp = EXP_FROM_COMP(COMP_RED,
+                               sd->params.exposure.redComp, currentexp);
+               startexp += EXP_FROM_COMP(COMP_GREEN1,
+                               sd->params.exposure.green1Comp, currentexp);
+               startexp += EXP_FROM_COMP(COMP_GREEN2,
+                               sd->params.exposure.green2Comp, currentexp);
+               startexp += EXP_FROM_COMP(COMP_BLUE,
+                               sd->params.exposure.blueComp, currentexp);
+               startexp = startexp >> 2;
+               while (startexp > MAX_EXP && sd->params.exposure.gain <
+                      sd->params.exposure.gainMode - 1) {
+                       startexp = startexp >> 1;
+                       ++sd->params.exposure.gain;
+               }
+               if (FIRMWARE_VERSION(1, 2) && startexp > MAX_EXP_102)
+                       startexp = MAX_EXP_102;
+               if (startexp > MAX_EXP)
+                       startexp = MAX_EXP;
+               sd->params.exposure.coarseExpLo = startexp & 0xff;
+               sd->params.exposure.coarseExpHi = startexp >> 8;
+               sd->params.exposure.redComp = COMP_RED;
+               sd->params.exposure.green1Comp = COMP_GREEN1;
+               sd->params.exposure.green2Comp = COMP_GREEN2;
+               sd->params.exposure.blueComp = COMP_BLUE;
+               sd->params.exposure.compMode = 1;
+               sd->params.apcor.gain1 = 0x18;
+               sd->params.apcor.gain2 = 0x16;
+               sd->params.apcor.gain4 = 0x24;
+               sd->params.apcor.gain8 = 0x34;
+       }
+       sd->params.vlOffset.gain1 = 20;
+       sd->params.vlOffset.gain2 = 24;
+       sd->params.vlOffset.gain4 = 26;
+       sd->params.vlOffset.gain8 = 26;
+
+       if (apply) {
+               ret = command_setexposure(gspca_dev);
+               if (ret)
+                       return ret;
+
+               ret = command_setapcor(gspca_dev);
+               if (ret)
+                       return ret;
+
+               ret = command_setvloffset(gspca_dev);
+               if (ret)
+                       return ret;
+
+               ret = command_setflickerctrl(gspca_dev);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+#undef EXP_FROM_COMP
+#undef COMPGAIN
+}
+
+/* monitor the exposure and adjust the sensor frame rate if needed */
+static void monitor_exposure(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 exp_acc, bcomp, cmd[8];
+       int ret, light_exp, dark_exp, very_dark_exp;
+       int old_exposure, new_exposure, framerate;
+       int setfps = 0, setexp = 0, setflicker = 0;
+
+       /* get necessary stats and register settings from camera */
+       /* do_command can't handle this, so do it ourselves */
+       cmd[0] = CPIA_COMMAND_ReadVPRegs >> 8;
+       cmd[1] = CPIA_COMMAND_ReadVPRegs & 0xff;
+       cmd[2] = 30;
+       cmd[3] = 4;
+       cmd[4] = 9;
+       cmd[5] = 8;
+       cmd[6] = 8;
+       cmd[7] = 0;
+       ret = cpia_usb_transferCmd(gspca_dev, cmd);
+       if (ret) {
+               pr_err("ReadVPRegs(30,4,9,8) - failed: %d\n", ret);
+               return;
+       }
+       exp_acc = gspca_dev->usb_buf[0];
+       bcomp = gspca_dev->usb_buf[1];
+
+       light_exp = sd->params.colourParams.brightness +
+                   TC - 50 + EXP_ACC_LIGHT;
+       if (light_exp > 255)
+               light_exp = 255;
+       dark_exp = sd->params.colourParams.brightness +
+                  TC - 50 - EXP_ACC_DARK;
+       if (dark_exp < 0)
+               dark_exp = 0;
+       very_dark_exp = dark_exp / 2;
+
+       old_exposure = sd->params.exposure.coarseExpHi * 256 +
+                      sd->params.exposure.coarseExpLo;
+
+       if (!sd->params.flickerControl.disabled) {
+               /* Flicker control on */
+               int max_comp = FIRMWARE_VERSION(1, 2) ? MAX_COMP :
+                                                       HIGH_COMP_102;
+               bcomp += 128;   /* decode */
+               if (bcomp >= max_comp && exp_acc < dark_exp) {
+                       /* dark */
+                       if (exp_acc < very_dark_exp) {
+                               /* very dark */
+                               if (sd->exposure_status == EXPOSURE_VERY_DARK)
+                                       ++sd->exposure_count;
+                               else {
+                                       sd->exposure_status =
+                                               EXPOSURE_VERY_DARK;
+                                       sd->exposure_count = 1;
+                               }
+                       } else {
+                               /* just dark */
+                               if (sd->exposure_status == EXPOSURE_DARK)
+                                       ++sd->exposure_count;
+                               else {
+                                       sd->exposure_status = EXPOSURE_DARK;
+                                       sd->exposure_count = 1;
+                               }
+                       }
+               } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) {
+                       /* light */
+                       if (old_exposure <= VERY_LOW_EXP) {
+                               /* very light */
+                               if (sd->exposure_status == EXPOSURE_VERY_LIGHT)
+                                       ++sd->exposure_count;
+                               else {
+                                       sd->exposure_status =
+                                               EXPOSURE_VERY_LIGHT;
+                                       sd->exposure_count = 1;
+                               }
+                       } else {
+                               /* just light */
+                               if (sd->exposure_status == EXPOSURE_LIGHT)
+                                       ++sd->exposure_count;
+                               else {
+                                       sd->exposure_status = EXPOSURE_LIGHT;
+                                       sd->exposure_count = 1;
+                               }
+                       }
+               } else {
+                       /* not dark or light */
+                       sd->exposure_status = EXPOSURE_NORMAL;
+               }
+       } else {
+               /* Flicker control off */
+               if (old_exposure >= MAX_EXP && exp_acc < dark_exp) {
+                       /* dark */
+                       if (exp_acc < very_dark_exp) {
+                               /* very dark */
+                               if (sd->exposure_status == EXPOSURE_VERY_DARK)
+                                       ++sd->exposure_count;
+                               else {
+                                       sd->exposure_status =
+                                               EXPOSURE_VERY_DARK;
+                                       sd->exposure_count = 1;
+                               }
+                       } else {
+                               /* just dark */
+                               if (sd->exposure_status == EXPOSURE_DARK)
+                                       ++sd->exposure_count;
+                               else {
+                                       sd->exposure_status = EXPOSURE_DARK;
+                                       sd->exposure_count = 1;
+                               }
+                       }
+               } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) {
+                       /* light */
+                       if (old_exposure <= VERY_LOW_EXP) {
+                               /* very light */
+                               if (sd->exposure_status == EXPOSURE_VERY_LIGHT)
+                                       ++sd->exposure_count;
+                               else {
+                                       sd->exposure_status =
+                                               EXPOSURE_VERY_LIGHT;
+                                       sd->exposure_count = 1;
+                               }
+                       } else {
+                               /* just light */
+                               if (sd->exposure_status == EXPOSURE_LIGHT)
+                                       ++sd->exposure_count;
+                               else {
+                                       sd->exposure_status = EXPOSURE_LIGHT;
+                                       sd->exposure_count = 1;
+                               }
+                       }
+               } else {
+                       /* not dark or light */
+                       sd->exposure_status = EXPOSURE_NORMAL;
+               }
+       }
+
+       framerate = atomic_read(&sd->fps);
+       if (framerate > 30 || framerate < 1)
+               framerate = 1;
+
+       if (!sd->params.flickerControl.disabled) {
+               /* Flicker control on */
+               if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
+                    sd->exposure_status == EXPOSURE_DARK) &&
+                   sd->exposure_count >= DARK_TIME * framerate &&
+                   sd->params.sensorFps.divisor < 2) {
+
+                       /* dark for too long */
+                       ++sd->params.sensorFps.divisor;
+                       setfps = 1;
+
+                       sd->params.flickerControl.coarseJump =
+                               flicker_jumps[sd->mainsFreq]
+                                            [sd->params.sensorFps.baserate]
+                                            [sd->params.sensorFps.divisor];
+                       setflicker = 1;
+
+                       new_exposure = sd->params.flickerControl.coarseJump-1;
+                       while (new_exposure < old_exposure / 2)
+                               new_exposure +=
+                                       sd->params.flickerControl.coarseJump;
+                       sd->params.exposure.coarseExpLo = new_exposure & 0xff;
+                       sd->params.exposure.coarseExpHi = new_exposure >> 8;
+                       setexp = 1;
+                       sd->exposure_status = EXPOSURE_NORMAL;
+                       PDEBUG(D_CONF, "Automatically decreasing sensor_fps");
+
+               } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT ||
+                           sd->exposure_status == EXPOSURE_LIGHT) &&
+                          sd->exposure_count >= LIGHT_TIME * framerate &&
+                          sd->params.sensorFps.divisor > 0) {
+
+                       /* light for too long */
+                       int max_exp = FIRMWARE_VERSION(1, 2) ? MAX_EXP_102 :
+                                                              MAX_EXP;
+                       --sd->params.sensorFps.divisor;
+                       setfps = 1;
+
+                       sd->params.flickerControl.coarseJump =
+                               flicker_jumps[sd->mainsFreq]
+                                            [sd->params.sensorFps.baserate]
+                                            [sd->params.sensorFps.divisor];
+                       setflicker = 1;
+
+                       new_exposure = sd->params.flickerControl.coarseJump-1;
+                       while (new_exposure < 2 * old_exposure &&
+                              new_exposure +
+                              sd->params.flickerControl.coarseJump < max_exp)
+                               new_exposure +=
+                                       sd->params.flickerControl.coarseJump;
+                       sd->params.exposure.coarseExpLo = new_exposure & 0xff;
+                       sd->params.exposure.coarseExpHi = new_exposure >> 8;
+                       setexp = 1;
+                       sd->exposure_status = EXPOSURE_NORMAL;
+                       PDEBUG(D_CONF, "Automatically increasing sensor_fps");
+               }
+       } else {
+               /* Flicker control off */
+               if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
+                    sd->exposure_status == EXPOSURE_DARK) &&
+                   sd->exposure_count >= DARK_TIME * framerate &&
+                   sd->params.sensorFps.divisor < 2) {
+
+                       /* dark for too long */
+                       ++sd->params.sensorFps.divisor;
+                       setfps = 1;
+
+                       if (sd->params.exposure.gain > 0) {
+                               --sd->params.exposure.gain;
+                               setexp = 1;
+                       }
+                       sd->exposure_status = EXPOSURE_NORMAL;
+                       PDEBUG(D_CONF, "Automatically decreasing sensor_fps");
+
+               } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT ||
+                           sd->exposure_status == EXPOSURE_LIGHT) &&
+                          sd->exposure_count >= LIGHT_TIME * framerate &&
+                          sd->params.sensorFps.divisor > 0) {
+
+                       /* light for too long */
+                       --sd->params.sensorFps.divisor;
+                       setfps = 1;
+
+                       if (sd->params.exposure.gain <
+                           sd->params.exposure.gainMode - 1) {
+                               ++sd->params.exposure.gain;
+                               setexp = 1;
+                       }
+                       sd->exposure_status = EXPOSURE_NORMAL;
+                       PDEBUG(D_CONF, "Automatically increasing sensor_fps");
+               }
+       }
+
+       if (setexp)
+               command_setexposure(gspca_dev);
+
+       if (setfps)
+               command_setsensorfps(gspca_dev);
+
+       if (setflicker)
+               command_setflickerctrl(gspca_dev);
+}
+
+/*-----------------------------------------------------------------*/
+/* if flicker is switched off, this function switches it back on.It checks,
+   however, that conditions are suitable before restarting it.
+   This should only be called for firmware version 1.2.
+
+   It also adjust the colour balance when an exposure step is detected - as
+   long as flicker is running
+*/
+static void restart_flicker(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int cam_exposure, old_exp;
+
+       if (!FIRMWARE_VERSION(1, 2))
+               return;
+
+       cam_exposure = atomic_read(&sd->cam_exposure);
+
+       if (sd->params.flickerControl.flickerMode == 0 ||
+           cam_exposure == 0)
+               return;
+
+       old_exp = sd->params.exposure.coarseExpLo +
+                 sd->params.exposure.coarseExpHi*256;
+       /*
+         see how far away camera exposure is from a valid
+         flicker exposure value
+       */
+       cam_exposure %= sd->params.flickerControl.coarseJump;
+       if (!sd->params.flickerControl.disabled &&
+           cam_exposure <= sd->params.flickerControl.coarseJump - 3) {
+               /* Flicker control auto-disabled */
+               sd->params.flickerControl.disabled = 1;
+       }
+
+       if (sd->params.flickerControl.disabled &&
+           old_exp > sd->params.flickerControl.coarseJump +
+                     ROUND_UP_EXP_FOR_FLICKER) {
+               /* exposure is now high enough to switch
+                  flicker control back on */
+               set_flicker(gspca_dev, 1, 1);
+       }
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+
+       sd->mainsFreq = FREQ_DEF == V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
+       reset_camera_params(gspca_dev);
+
+       PDEBUG(D_PROBE, "cpia CPiA camera detected (vid/pid 0x%04X:0x%04X)",
+              id->idVendor, id->idProduct);
+
+       cam = &gspca_dev->cam;
+       cam->cam_mode = mode;
+       cam->nmodes = ARRAY_SIZE(mode);
+
+       goto_low_power(gspca_dev);
+       /* Check the firmware version. */
+       sd->params.version.firmwareVersion = 0;
+       get_version_information(gspca_dev);
+       if (sd->params.version.firmwareVersion != 1) {
+               PDEBUG(D_ERR, "only firmware version 1 is supported (got: %d)",
+                      sd->params.version.firmwareVersion);
+               return -ENODEV;
+       }
+
+       /* A bug in firmware 1-02 limits gainMode to 2 */
+       if (sd->params.version.firmwareRevision <= 2 &&
+           sd->params.exposure.gainMode > 2) {
+               sd->params.exposure.gainMode = 2;
+       }
+
+       /* set QX3 detected flag */
+       sd->params.qx3.qx3_detected = (sd->params.pnpID.vendor == 0x0813 &&
+                                      sd->params.pnpID.product == 0x0001);
+       return 0;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int priv, ret;
+
+       /* Start the camera in low power mode */
+       if (goto_low_power(gspca_dev)) {
+               if (sd->params.status.systemState != WARM_BOOT_STATE) {
+                       PDEBUG(D_ERR, "unexpected systemstate: %02x",
+                              sd->params.status.systemState);
+                       printstatus(&sd->params);
+                       return -ENODEV;
+               }
+
+               /* FIXME: this is just dirty trial and error */
+               ret = goto_high_power(gspca_dev);
+               if (ret)
+                       return ret;
+
+               ret = do_command(gspca_dev, CPIA_COMMAND_DiscardFrame,
+                                0, 0, 0, 0);
+               if (ret)
+                       return ret;
+
+               ret = goto_low_power(gspca_dev);
+               if (ret)
+                       return ret;
+       }
+
+       /* procedure described in developer's guide p3-28 */
+
+       /* Check the firmware version. */
+       sd->params.version.firmwareVersion = 0;
+       get_version_information(gspca_dev);
+
+       /* The fatal error checking should be done after
+        * the camera powers up (developer's guide p 3-38) */
+
+       /* Set streamState before transition to high power to avoid bug
+        * in firmware 1-02 */
+       ret = do_command(gspca_dev, CPIA_COMMAND_ModifyCameraStatus,
+                        STREAMSTATE, 0, STREAM_NOT_READY, 0);
+       if (ret)
+               return ret;
+
+       /* GotoHiPower */
+       ret = goto_high_power(gspca_dev);
+       if (ret)
+               return ret;
+
+       /* Check the camera status */
+       ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
+       if (ret)
+               return ret;
+
+       if (sd->params.status.fatalError) {
+               PDEBUG(D_ERR, "fatal_error: %04x, vp_status: %04x",
+                      sd->params.status.fatalError,
+                      sd->params.status.vpStatus);
+               return -EIO;
+       }
+
+       /* VPVersion can't be retrieved before the camera is in HiPower,
+        * so get it here instead of in get_version_information. */
+       ret = do_command(gspca_dev, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0);
+       if (ret)
+               return ret;
+
+       /* Determine video mode settings */
+       sd->params.streamStartLine = 120;
+
+       priv = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+       if (priv & 0x01) { /* crop */
+               sd->params.roi.colStart = 2;
+               sd->params.roi.rowStart = 6;
+       } else {
+               sd->params.roi.colStart = 0;
+               sd->params.roi.rowStart = 0;
+       }
+
+       if (priv & 0x02) { /* quarter */
+               sd->params.format.videoSize = VIDEOSIZE_QCIF;
+               sd->params.roi.colStart /= 2;
+               sd->params.roi.rowStart /= 2;
+               sd->params.streamStartLine /= 2;
+       } else
+               sd->params.format.videoSize = VIDEOSIZE_CIF;
+
+       sd->params.roi.colEnd = sd->params.roi.colStart +
+                               (gspca_dev->width >> 3);
+       sd->params.roi.rowEnd = sd->params.roi.rowStart +
+                               (gspca_dev->height >> 2);
+
+       /* And now set the camera to a known state */
+       ret = do_command(gspca_dev, CPIA_COMMAND_SetGrabMode,
+                        CPIA_GRAB_CONTINEOUS, 0, 0, 0);
+       if (ret)
+               return ret;
+       /* We start with compression disabled, as we need one uncompressed
+          frame to handle later compressed frames */
+       ret = do_command(gspca_dev, CPIA_COMMAND_SetCompression,
+                        CPIA_COMPRESSION_NONE,
+                        NO_DECIMATION, 0, 0);
+       if (ret)
+               return ret;
+       ret = command_setcompressiontarget(gspca_dev);
+       if (ret)
+               return ret;
+       ret = command_setcolourparams(gspca_dev);
+       if (ret)
+               return ret;
+       ret = command_setformat(gspca_dev);
+       if (ret)
+               return ret;
+       ret = command_setyuvtresh(gspca_dev);
+       if (ret)
+               return ret;
+       ret = command_setecptiming(gspca_dev);
+       if (ret)
+               return ret;
+       ret = command_setcompressionparams(gspca_dev);
+       if (ret)
+               return ret;
+       ret = command_setexposure(gspca_dev);
+       if (ret)
+               return ret;
+       ret = command_setcolourbalance(gspca_dev);
+       if (ret)
+               return ret;
+       ret = command_setsensorfps(gspca_dev);
+       if (ret)
+               return ret;
+       ret = command_setapcor(gspca_dev);
+       if (ret)
+               return ret;
+       ret = command_setflickerctrl(gspca_dev);
+       if (ret)
+               return ret;
+       ret = command_setvloffset(gspca_dev);
+       if (ret)
+               return ret;
+
+       /* Start stream */
+       ret = command_resume(gspca_dev);
+       if (ret)
+               return ret;
+
+       /* Wait 6 frames before turning compression on for the sensor to get
+          all settings and AEC/ACB to settle */
+       sd->first_frame = 6;
+       sd->exposure_status = EXPOSURE_NORMAL;
+       sd->exposure_count = 0;
+       atomic_set(&sd->cam_exposure, 0);
+       atomic_set(&sd->fps, 0);
+
+       return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       command_pause(gspca_dev);
+
+       /* save camera state for later open (developers guide ch 3.5.3) */
+       save_camera_state(gspca_dev);
+
+       /* GotoLoPower */
+       goto_low_power(gspca_dev);
+
+       /* Update the camera status */
+       do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       /* If the last button state is pressed, release it now! */
+       if (sd->params.qx3.button) {
+               /* The camera latch will hold the pressed state until we reset
+                  the latch, so we do not reset sd->params.qx3.button now, to
+                  avoid a false keypress being reported the next sd_start */
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+               input_sync(gspca_dev->input_dev);
+       }
+#endif
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int ret;
+
+       /* Start / Stop the camera to make sure we are talking to
+          a supported camera, and to get some information from it
+          to print. */
+       ret = sd_start(gspca_dev);
+       if (ret)
+               return ret;
+
+       /* Ensure the QX3 illuminators' states are restored upon resume,
+          or disable the illuminator controls, if this isn't a QX3 */
+       if (sd->params.qx3.qx3_detected)
+               command_setlights(gspca_dev);
+
+       sd_stopN(gspca_dev);
+
+       PDEBUG(D_PROBE, "CPIA Version:             %d.%02d (%d.%d)",
+                       sd->params.version.firmwareVersion,
+                       sd->params.version.firmwareRevision,
+                       sd->params.version.vcVersion,
+                       sd->params.version.vcRevision);
+       PDEBUG(D_PROBE, "CPIA PnP-ID:              %04x:%04x:%04x",
+                       sd->params.pnpID.vendor, sd->params.pnpID.product,
+                       sd->params.pnpID.deviceRevision);
+       PDEBUG(D_PROBE, "VP-Version:               %d.%d %04x",
+                       sd->params.vpVersion.vpVersion,
+                       sd->params.vpVersion.vpRevision,
+                       sd->params.vpVersion.cameraHeadID);
+
+       return 0;
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,
+                       int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* Check for SOF */
+       if (len >= 64 &&
+           data[0] == MAGIC_0 && data[1] == MAGIC_1 &&
+           data[16] == sd->params.format.videoSize &&
+           data[17] == sd->params.format.subSample &&
+           data[18] == sd->params.format.yuvOrder &&
+           data[24] == sd->params.roi.colStart &&
+           data[25] == sd->params.roi.colEnd &&
+           data[26] == sd->params.roi.rowStart &&
+           data[27] == sd->params.roi.rowEnd) {
+               u8 *image;
+
+               atomic_set(&sd->cam_exposure, data[39] * 2);
+               atomic_set(&sd->fps, data[41]);
+
+               /* Check for proper EOF for last frame */
+               image = gspca_dev->image;
+               if (image != NULL &&
+                   gspca_dev->image_len > 4 &&
+                   image[gspca_dev->image_len - 4] == 0xff &&
+                   image[gspca_dev->image_len - 3] == 0xff &&
+                   image[gspca_dev->image_len - 2] == 0xff &&
+                   image[gspca_dev->image_len - 1] == 0xff)
+                       gspca_frame_add(gspca_dev, LAST_PACKET,
+                                               NULL, 0);
+
+               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
+               return;
+       }
+
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+static void sd_dq_callback(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* Set the normal compression settings once we have captured a
+          few uncompressed frames (and AEC has hopefully settled) */
+       if (sd->first_frame) {
+               sd->first_frame--;
+               if (sd->first_frame == 0)
+                       command_setcompression(gspca_dev);
+       }
+
+       /* Switch flicker control back on if it got turned off */
+       restart_flicker(gspca_dev);
+
+       /* If AEC is enabled, monitor the exposure and
+          adjust the sensor frame rate if needed */
+       if (sd->params.exposure.expMode == 2)
+               monitor_exposure(gspca_dev);
+
+       /* Update our knowledge of the camera state */
+       do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
+       do_command(gspca_dev, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 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 && ctrl->id != V4L2_CID_POWER_LINE_FREQUENCY)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               sd->params.colourParams.brightness = ctrl->val;
+               sd->params.flickerControl.allowableOverExposure =
+                       find_over_exposure(sd->params.colourParams.brightness);
+               gspca_dev->usb_err = command_setcolourparams(gspca_dev);
+               if (!gspca_dev->usb_err)
+                       gspca_dev->usb_err = command_setflickerctrl(gspca_dev);
+               break;
+       case V4L2_CID_CONTRAST:
+               sd->params.colourParams.contrast = ctrl->val;
+               gspca_dev->usb_err = command_setcolourparams(gspca_dev);
+               break;
+       case V4L2_CID_SATURATION:
+               sd->params.colourParams.saturation = ctrl->val;
+               gspca_dev->usb_err = command_setcolourparams(gspca_dev);
+               break;
+       case V4L2_CID_POWER_LINE_FREQUENCY:
+               sd->mainsFreq = ctrl->val == V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
+               sd->params.flickerControl.coarseJump =
+                       flicker_jumps[sd->mainsFreq]
+                       [sd->params.sensorFps.baserate]
+                       [sd->params.sensorFps.divisor];
+
+               gspca_dev->usb_err = set_flicker(gspca_dev,
+                       ctrl->val != V4L2_CID_POWER_LINE_FREQUENCY_DISABLED,
+                       gspca_dev->streaming);
+               break;
+       case V4L2_CID_ILLUMINATORS_1:
+               sd->params.qx3.bottomlight = ctrl->val;
+               gspca_dev->usb_err = command_setlights(gspca_dev);
+               break;
+       case V4L2_CID_ILLUMINATORS_2:
+               sd->params.qx3.toplight = ctrl->val;
+               gspca_dev->usb_err = command_setlights(gspca_dev);
+               break;
+       case CPIA1_CID_COMP_TARGET:
+               sd->params.compressionTarget.frTargeting = ctrl->val;
+               gspca_dev->usb_err = command_setcompressiontarget(gspca_dev);
+               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;
+       static const char * const comp_target_menu[] = {
+               "Quality",
+               "Framerate",
+               NULL
+       };
+       static const struct v4l2_ctrl_config comp_target = {
+               .ops = &sd_ctrl_ops,
+               .id = CPIA1_CID_COMP_TARGET,
+               .type = V4L2_CTRL_TYPE_MENU,
+               .name = "Compression Target",
+               .qmenu = comp_target_menu,
+               .max = 1,
+               .def = COMP_TARGET_DEF,
+       };
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 7);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 100, 1, BRIGHTNESS_DEF);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 96, 8, CONTRAST_DEF);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 100, 1, SATURATION_DEF);
+       sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
+                       V4L2_CID_POWER_LINE_FREQUENCY,
+                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
+                       FREQ_DEF);
+       if (sd->params.qx3.qx3_detected) {
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                               V4L2_CID_ILLUMINATORS_1, 0, 1, 1,
+                               ILLUMINATORS_1_DEF);
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                               V4L2_CID_ILLUMINATORS_2, 0, 1, 1,
+                               ILLUMINATORS_2_DEF);
+       }
+       v4l2_ctrl_new_custom(hdl, &comp_target, NULL);
+
+       if (hdl->error) {
+               pr_err("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,
+       .stopN = sd_stopN,
+       .dq_callback = sd_dq_callback,
+       .pkt_scan = sd_pkt_scan,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .other_input = 1,
+#endif
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x0553, 0x0002)},
+       {USB_DEVICE(0x0813, 0x0001)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/etoms.c b/drivers/media/usb/gspca/etoms.c
new file mode 100644 (file)
index 0000000..38f68e1
--- /dev/null
@@ -0,0 +1,799 @@
+/*
+ * Etoms Et61x151 GPL Linux driver by Michel Xhaard (09/09/2004)
+ *
+ * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "etoms"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
+MODULE_DESCRIPTION("Etoms USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       unsigned char autogain;
+
+       char sensor;
+#define SENSOR_PAS106 0
+#define SENSOR_TAS5130CXX 1
+       signed char ag_cnt;
+#define AG_CNT_START 13
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+/*     {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0}, */
+};
+
+static const struct v4l2_pix_format sif_mode[] = {
+       {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+#define ETOMS_ALT_SIZE_1000   12
+
+#define ET_GPIO_DIR_CTRL 0x04  /* Control IO bit[0..5] (0 in  1 out) */
+#define ET_GPIO_OUT 0x05       /* Only IO data */
+#define ET_GPIO_IN 0x06                /* Read Only IO data */
+#define ET_RESET_ALL 0x03
+#define ET_ClCK 0x01
+#define ET_CTRL 0x02           /* enable i2c OutClck Powerdown mode */
+
+#define ET_COMP 0x12           /* Compression register */
+#define ET_MAXQt 0x13
+#define ET_MINQt 0x14
+#define ET_COMP_VAL0 0x02
+#define ET_COMP_VAL1 0x03
+
+#define ET_REG1d 0x1d
+#define ET_REG1e 0x1e
+#define ET_REG1f 0x1f
+#define ET_REG20 0x20
+#define ET_REG21 0x21
+#define ET_REG22 0x22
+#define ET_REG23 0x23
+#define ET_REG24 0x24
+#define ET_REG25 0x25
+/* base registers for luma calculation */
+#define ET_LUMA_CENTER 0x39
+
+#define ET_G_RED 0x4d
+#define ET_G_GREEN1 0x4e
+#define ET_G_BLUE 0x4f
+#define ET_G_GREEN2 0x50
+#define ET_G_GR_H 0x51
+#define ET_G_GB_H 0x52
+
+#define ET_O_RED 0x34
+#define ET_O_GREEN1 0x35
+#define ET_O_BLUE 0x36
+#define ET_O_GREEN2 0x37
+
+#define ET_SYNCHRO 0x68
+#define ET_STARTX 0x69
+#define ET_STARTY 0x6a
+#define ET_WIDTH_LOW 0x6b
+#define ET_HEIGTH_LOW 0x6c
+#define ET_W_H_HEIGTH 0x6d
+
+#define ET_REG6e 0x6e          /* OBW */
+#define ET_REG6f 0x6f          /* OBW */
+#define ET_REG70 0x70          /* OBW_AWB */
+#define ET_REG71 0x71          /* OBW_AWB */
+#define ET_REG72 0x72          /* OBW_AWB */
+#define ET_REG73 0x73          /* Clkdelay ns */
+#define ET_REG74 0x74          /* test pattern */
+#define ET_REG75 0x75          /* test pattern */
+
+#define ET_I2C_CLK 0x8c
+#define ET_PXL_CLK 0x60
+
+#define ET_I2C_BASE 0x89
+#define ET_I2C_COUNT 0x8a
+#define ET_I2C_PREFETCH 0x8b
+#define ET_I2C_REG 0x88
+#define ET_I2C_DATA7 0x87
+#define ET_I2C_DATA6 0x86
+#define ET_I2C_DATA5 0x85
+#define ET_I2C_DATA4 0x84
+#define ET_I2C_DATA3 0x83
+#define ET_I2C_DATA2 0x82
+#define ET_I2C_DATA1 0x81
+#define ET_I2C_DATA0 0x80
+
+#define PAS106_REG2 0x02       /* pxlClk = systemClk/(reg2) */
+#define PAS106_REG3 0x03       /* line/frame H [11..4] */
+#define PAS106_REG4 0x04       /* line/frame L [3..0] */
+#define PAS106_REG5 0x05       /* exposure time line offset(default 5) */
+#define PAS106_REG6 0x06       /* exposure time pixel offset(default 6) */
+#define PAS106_REG7 0x07       /* signbit Dac (default 0) */
+#define PAS106_REG9 0x09
+#define PAS106_REG0e 0x0e      /* global gain [4..0](default 0x0e) */
+#define PAS106_REG13 0x13      /* end i2c write */
+
+static const __u8 GainRGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
+
+static const __u8 I2c2[] = { 0x08, 0x08, 0x08, 0x08, 0x0d };
+
+static const __u8 I2c3[] = { 0x12, 0x05 };
+
+static const __u8 I2c4[] = { 0x41, 0x08 };
+
+/* read 'len' bytes to gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev,
+                 __u16 index,
+                 __u16 len)
+{
+       struct usb_device *dev = gspca_dev->dev;
+
+#ifdef GSPCA_DEBUG
+       if (len > USB_BUF_SZ) {
+               pr_err("reg_r: buffer overflow\n");
+               return;
+       }
+#endif
+       usb_control_msg(dev,
+                       usb_rcvctrlpipe(dev, 0),
+                       0,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       0,
+                       index, gspca_dev->usb_buf, len, 500);
+       PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
+                       index, gspca_dev->usb_buf[0]);
+}
+
+static void reg_w_val(struct gspca_dev *gspca_dev,
+                       __u16 index,
+                       __u8 val)
+{
+       struct usb_device *dev = gspca_dev->dev;
+
+       gspca_dev->usb_buf[0] = val;
+       usb_control_msg(dev,
+                       usb_sndctrlpipe(dev, 0),
+                       0,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       0,
+                       index, gspca_dev->usb_buf, 1, 500);
+}
+
+static void reg_w(struct gspca_dev *gspca_dev,
+                 __u16 index,
+                 const __u8 *buffer,
+                 __u16 len)
+{
+       struct usb_device *dev = gspca_dev->dev;
+
+#ifdef GSPCA_DEBUG
+       if (len > USB_BUF_SZ) {
+               pr_err("reg_w: buffer overflow\n");
+               return;
+       }
+       PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
+#endif
+       memcpy(gspca_dev->usb_buf, buffer, len);
+       usb_control_msg(dev,
+                       usb_sndctrlpipe(dev, 0),
+                       0,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       0, index, gspca_dev->usb_buf, len, 500);
+}
+
+static int i2c_w(struct gspca_dev *gspca_dev,
+                __u8 reg,
+                const __u8 *buffer,
+                int len, __u8 mode)
+{
+       /* buffer should be [D0..D7] */
+       __u8 ptchcount;
+
+       /* set the base address */
+       reg_w_val(gspca_dev, ET_I2C_BASE, 0x40);
+                                        /* sensor base for the pas106 */
+       /* set count and prefetch */
+       ptchcount = ((len & 0x07) << 4) | (mode & 0x03);
+       reg_w_val(gspca_dev, ET_I2C_COUNT, ptchcount);
+       /* set the register base */
+       reg_w_val(gspca_dev, ET_I2C_REG, reg);
+       while (--len >= 0)
+               reg_w_val(gspca_dev, ET_I2C_DATA0 + len, buffer[len]);
+       return 0;
+}
+
+static int i2c_r(struct gspca_dev *gspca_dev,
+                       __u8 reg)
+{
+       /* set the base address */
+       reg_w_val(gspca_dev, ET_I2C_BASE, 0x40);
+                                       /* sensor base for the pas106 */
+       /* set count and prefetch (cnd: 4 bits - mode: 4 bits) */
+       reg_w_val(gspca_dev, ET_I2C_COUNT, 0x11);
+       reg_w_val(gspca_dev, ET_I2C_REG, reg);  /* set the register base */
+       reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x02);    /* prefetch */
+       reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x00);
+       reg_r(gspca_dev, ET_I2C_DATA0, 1);      /* read one byte */
+       return 0;
+}
+
+static int Et_WaitStatus(struct gspca_dev *gspca_dev)
+{
+       int retry = 10;
+
+       while (retry--) {
+               reg_r(gspca_dev, ET_ClCK, 1);
+               if (gspca_dev->usb_buf[0] != 0)
+                       return 1;
+       }
+       return 0;
+}
+
+static int et_video(struct gspca_dev *gspca_dev,
+                   int on)
+{
+       int ret;
+
+       reg_w_val(gspca_dev, ET_GPIO_OUT,
+                 on ? 0x10             /* startvideo - set Bit5 */
+                    : 0);              /* stopvideo */
+       ret = Et_WaitStatus(gspca_dev);
+       if (ret != 0)
+               PDEBUG(D_ERR, "timeout video on/off");
+       return ret;
+}
+
+static void Et_init2(struct gspca_dev *gspca_dev)
+{
+       __u8 value;
+       static const __u8 FormLine[] = { 0x84, 0x03, 0x14, 0xf4, 0x01, 0x05 };
+
+       PDEBUG(D_STREAM, "Open Init2 ET");
+       reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 0x2f);
+       reg_w_val(gspca_dev, ET_GPIO_OUT, 0x10);
+       reg_r(gspca_dev, ET_GPIO_IN, 1);
+       reg_w_val(gspca_dev, ET_ClCK, 0x14); /* 0x14 // 0x16 enabled pattern */
+       reg_w_val(gspca_dev, ET_CTRL, 0x1b);
+
+       /*  compression et subsampling */
+       if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
+               value = ET_COMP_VAL1;   /* 320 */
+       else
+               value = ET_COMP_VAL0;   /* 640 */
+       reg_w_val(gspca_dev, ET_COMP, value);
+       reg_w_val(gspca_dev, ET_MAXQt, 0x1f);
+       reg_w_val(gspca_dev, ET_MINQt, 0x04);
+       /* undocumented registers */
+       reg_w_val(gspca_dev, ET_REG1d, 0xff);
+       reg_w_val(gspca_dev, ET_REG1e, 0xff);
+       reg_w_val(gspca_dev, ET_REG1f, 0xff);
+       reg_w_val(gspca_dev, ET_REG20, 0x35);
+       reg_w_val(gspca_dev, ET_REG21, 0x01);
+       reg_w_val(gspca_dev, ET_REG22, 0x00);
+       reg_w_val(gspca_dev, ET_REG23, 0xff);
+       reg_w_val(gspca_dev, ET_REG24, 0xff);
+       reg_w_val(gspca_dev, ET_REG25, 0x0f);
+       /* colors setting */
+       reg_w_val(gspca_dev, 0x30, 0x11);               /* 0x30 */
+       reg_w_val(gspca_dev, 0x31, 0x40);
+       reg_w_val(gspca_dev, 0x32, 0x00);
+       reg_w_val(gspca_dev, ET_O_RED, 0x00);           /* 0x34 */
+       reg_w_val(gspca_dev, ET_O_GREEN1, 0x00);
+       reg_w_val(gspca_dev, ET_O_BLUE, 0x00);
+       reg_w_val(gspca_dev, ET_O_GREEN2, 0x00);
+       /*************/
+       reg_w_val(gspca_dev, ET_G_RED, 0x80);           /* 0x4d */
+       reg_w_val(gspca_dev, ET_G_GREEN1, 0x80);
+       reg_w_val(gspca_dev, ET_G_BLUE, 0x80);
+       reg_w_val(gspca_dev, ET_G_GREEN2, 0x80);
+       reg_w_val(gspca_dev, ET_G_GR_H, 0x00);
+       reg_w_val(gspca_dev, ET_G_GB_H, 0x00);          /* 0x52 */
+       /* Window control registers */
+       reg_w_val(gspca_dev, 0x61, 0x80);               /* use cmc_out */
+       reg_w_val(gspca_dev, 0x62, 0x02);
+       reg_w_val(gspca_dev, 0x63, 0x03);
+       reg_w_val(gspca_dev, 0x64, 0x14);
+       reg_w_val(gspca_dev, 0x65, 0x0e);
+       reg_w_val(gspca_dev, 0x66, 0x02);
+       reg_w_val(gspca_dev, 0x67, 0x02);
+
+       /**************************************/
+       reg_w_val(gspca_dev, ET_SYNCHRO, 0x8f);         /* 0x68 */
+       reg_w_val(gspca_dev, ET_STARTX, 0x69);          /* 0x6a //0x69 */
+       reg_w_val(gspca_dev, ET_STARTY, 0x0d);          /* 0x0d //0x0c */
+       reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x80);
+       reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0xe0);
+       reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x60);      /* 6d */
+       reg_w_val(gspca_dev, ET_REG6e, 0x86);
+       reg_w_val(gspca_dev, ET_REG6f, 0x01);
+       reg_w_val(gspca_dev, ET_REG70, 0x26);
+       reg_w_val(gspca_dev, ET_REG71, 0x7a);
+       reg_w_val(gspca_dev, ET_REG72, 0x01);
+       /* Clock Pattern registers ***************** */
+       reg_w_val(gspca_dev, ET_REG73, 0x00);
+       reg_w_val(gspca_dev, ET_REG74, 0x18);           /* 0x28 */
+       reg_w_val(gspca_dev, ET_REG75, 0x0f);           /* 0x01 */
+       /**********************************************/
+       reg_w_val(gspca_dev, 0x8a, 0x20);
+       reg_w_val(gspca_dev, 0x8d, 0x0f);
+       reg_w_val(gspca_dev, 0x8e, 0x08);
+       /**************************************/
+       reg_w_val(gspca_dev, 0x03, 0x08);
+       reg_w_val(gspca_dev, ET_PXL_CLK, 0x03);
+       reg_w_val(gspca_dev, 0x81, 0xff);
+       reg_w_val(gspca_dev, 0x80, 0x00);
+       reg_w_val(gspca_dev, 0x81, 0xff);
+       reg_w_val(gspca_dev, 0x80, 0x20);
+       reg_w_val(gspca_dev, 0x03, 0x01);
+       reg_w_val(gspca_dev, 0x03, 0x00);
+       reg_w_val(gspca_dev, 0x03, 0x08);
+       /********************************************/
+
+/*     reg_r(gspca_dev, ET_I2C_BASE, 1);
+                                        always 0x40 as the pas106 ??? */
+       /* set the sensor */
+       if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
+               value = 0x04;           /* 320 */
+       else                            /* 640 */
+               value = 0x1e;   /* 0x17  * setting PixelClock
+                                        * 0x03 mean 24/(3+1) = 6 Mhz
+                                        * 0x05 -> 24/(5+1) = 4 Mhz
+                                        * 0x0b -> 24/(11+1) = 2 Mhz
+                                        * 0x17 -> 24/(23+1) = 1 Mhz
+                                        */
+       reg_w_val(gspca_dev, ET_PXL_CLK, value);
+       /* now set by fifo the FormatLine setting */
+       reg_w(gspca_dev, 0x62, FormLine, 6);
+
+       /* set exposure times [ 0..0x78] 0->longvalue 0x78->shortvalue */
+       reg_w_val(gspca_dev, 0x81, 0x47);       /* 0x47; */
+       reg_w_val(gspca_dev, 0x80, 0x40);       /* 0x40; */
+       /* Pedro change */
+       /* Brightness change Brith+ decrease value */
+       /* Brigth- increase value */
+       /* original value = 0x70; */
+       reg_w_val(gspca_dev, 0x81, 0x30);       /* 0x20; - set brightness */
+       reg_w_val(gspca_dev, 0x80, 0x20);       /* 0x20; */
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       int i;
+
+       for (i = 0; i < 4; i++)
+               reg_w_val(gspca_dev, ET_O_RED + i, val);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
+{
+       __u8 RGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
+
+       memset(RGBG, val, sizeof(RGBG) - 2);
+       reg_w(gspca_dev, ET_G_RED, RGBG, 6);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       __u8 I2cc[] = { 0x05, 0x02, 0x02, 0x05, 0x0d };
+       __u8 i2cflags = 0x01;
+       /* __u8 green = 0; */
+
+       I2cc[3] = val;  /* red */
+       I2cc[0] = 15 - val;     /* blue */
+       /* green = 15 - ((((7*I2cc[0]) >> 2 ) + I2cc[3]) >> 1); */
+       /* I2cc[1] = I2cc[2] = green; */
+       if (sd->sensor == SENSOR_PAS106) {
+               i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3);
+               i2c_w(gspca_dev, PAS106_REG9, I2cc, sizeof I2cc, 1);
+       }
+/*     PDEBUG(D_CONF , "Etoms red %d blue %d green %d",
+               I2cc[3], I2cc[0], green); */
+}
+
+static s32 getcolors(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_PAS106) {
+/*             i2c_r(gspca_dev, PAS106_REG9);           * blue */
+               i2c_r(gspca_dev, PAS106_REG9 + 3);      /* red */
+               return gspca_dev->usb_buf[0] & 0x0f;
+       }
+       return 0;
+}
+
+static void setautogain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->autogain)
+               sd->ag_cnt = AG_CNT_START;
+       else
+               sd->ag_cnt = -1;
+}
+
+static void Et_init1(struct gspca_dev *gspca_dev)
+{
+       __u8 value;
+/*     __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0x22, 0xac, 0x00, 0x01, 0x00}; */
+       __u8 I2c0[] = { 0x0a, 0x12, 0x05, 0x6d, 0xcd, 0x00, 0x01, 0x00 };
+                                               /* try 1/120 0x6d 0xcd 0x40 */
+/*     __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0xfe, 0xfe, 0xc0, 0x01, 0x00};
+                                                * 1/60000 hmm ?? */
+
+       PDEBUG(D_STREAM, "Open Init1 ET");
+       reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 7);
+       reg_r(gspca_dev, ET_GPIO_IN, 1);
+       reg_w_val(gspca_dev, ET_RESET_ALL, 1);
+       reg_w_val(gspca_dev, ET_RESET_ALL, 0);
+       reg_w_val(gspca_dev, ET_ClCK, 0x10);
+       reg_w_val(gspca_dev, ET_CTRL, 0x19);
+       /*   compression et subsampling */
+       if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
+               value = ET_COMP_VAL1;
+       else
+               value = ET_COMP_VAL0;
+       PDEBUG(D_STREAM, "Open mode %d Compression %d",
+              gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv,
+              value);
+       reg_w_val(gspca_dev, ET_COMP, value);
+       reg_w_val(gspca_dev, ET_MAXQt, 0x1d);
+       reg_w_val(gspca_dev, ET_MINQt, 0x02);
+       /* undocumented registers */
+       reg_w_val(gspca_dev, ET_REG1d, 0xff);
+       reg_w_val(gspca_dev, ET_REG1e, 0xff);
+       reg_w_val(gspca_dev, ET_REG1f, 0xff);
+       reg_w_val(gspca_dev, ET_REG20, 0x35);
+       reg_w_val(gspca_dev, ET_REG21, 0x01);
+       reg_w_val(gspca_dev, ET_REG22, 0x00);
+       reg_w_val(gspca_dev, ET_REG23, 0xf7);
+       reg_w_val(gspca_dev, ET_REG24, 0xff);
+       reg_w_val(gspca_dev, ET_REG25, 0x07);
+       /* colors setting */
+       reg_w_val(gspca_dev, ET_G_RED, 0x80);
+       reg_w_val(gspca_dev, ET_G_GREEN1, 0x80);
+       reg_w_val(gspca_dev, ET_G_BLUE, 0x80);
+       reg_w_val(gspca_dev, ET_G_GREEN2, 0x80);
+       reg_w_val(gspca_dev, ET_G_GR_H, 0x00);
+       reg_w_val(gspca_dev, ET_G_GB_H, 0x00);
+       /* Window control registers */
+       reg_w_val(gspca_dev, ET_SYNCHRO, 0xf0);
+       reg_w_val(gspca_dev, ET_STARTX, 0x56);          /* 0x56 */
+       reg_w_val(gspca_dev, ET_STARTY, 0x05);          /* 0x04 */
+       reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x60);
+       reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0x20);
+       reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x50);
+       reg_w_val(gspca_dev, ET_REG6e, 0x86);
+       reg_w_val(gspca_dev, ET_REG6f, 0x01);
+       reg_w_val(gspca_dev, ET_REG70, 0x86);
+       reg_w_val(gspca_dev, ET_REG71, 0x14);
+       reg_w_val(gspca_dev, ET_REG72, 0x00);
+       /* Clock Pattern registers */
+       reg_w_val(gspca_dev, ET_REG73, 0x00);
+       reg_w_val(gspca_dev, ET_REG74, 0x00);
+       reg_w_val(gspca_dev, ET_REG75, 0x0a);
+       reg_w_val(gspca_dev, ET_I2C_CLK, 0x04);
+       reg_w_val(gspca_dev, ET_PXL_CLK, 0x01);
+       /* set the sensor */
+       if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
+               I2c0[0] = 0x06;
+               i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1);
+               i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1);
+               value = 0x06;
+               i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1);
+               i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1);
+               /* value = 0x1f; */
+               value = 0x04;
+               i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1);
+       } else {
+               I2c0[0] = 0x0a;
+
+               i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1);
+               i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1);
+               value = 0x0a;
+               i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1);
+               i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1);
+               value = 0x04;
+               /* value = 0x10; */
+               i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1);
+               /* bit 2 enable bit 1:2 select 0 1 2 3
+                  value = 0x07;                                * curve 0 *
+                  i2c_w(gspca_dev, PAS106_REG0f, &value, 1, 1);
+                */
+       }
+
+/*     value = 0x01; */
+/*     value = 0x22; */
+/*     i2c_w(gspca_dev, PAS106_REG5, &value, 1, 1); */
+       /* magnetude and sign bit for DAC */
+       i2c_w(gspca_dev, PAS106_REG7, I2c4, sizeof I2c4, 1);
+       /* now set by fifo the whole colors setting */
+       reg_w(gspca_dev, ET_G_RED, GainRGBG, 6);
+       setcolors(gspca_dev, getcolors(gspca_dev));
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                    const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+
+       cam = &gspca_dev->cam;
+       sd->sensor = id->driver_info;
+       if (sd->sensor == SENSOR_PAS106) {
+               cam->cam_mode = sif_mode;
+               cam->nmodes = ARRAY_SIZE(sif_mode);
+       } else {
+               cam->cam_mode = vga_mode;
+               cam->nmodes = ARRAY_SIZE(vga_mode);
+       }
+       sd->ag_cnt = -1;
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_PAS106)
+               Et_init1(gspca_dev);
+       else
+               Et_init2(gspca_dev);
+       reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
+       et_video(gspca_dev, 0);         /* video off */
+       return 0;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_PAS106)
+               Et_init1(gspca_dev);
+       else
+               Et_init2(gspca_dev);
+
+       setautogain(gspca_dev);
+
+       reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
+       et_video(gspca_dev, 1);         /* video on */
+       return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       et_video(gspca_dev, 0);         /* video off */
+}
+
+static __u8 Et_getgainG(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_PAS106) {
+               i2c_r(gspca_dev, PAS106_REG0e);
+               PDEBUG(D_CONF, "Etoms gain G %d", gspca_dev->usb_buf[0]);
+               return gspca_dev->usb_buf[0];
+       }
+       return 0x1f;
+}
+
+static void Et_setgainG(struct gspca_dev *gspca_dev, __u8 gain)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_PAS106) {
+               __u8 i2cflags = 0x01;
+
+               i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3);
+               i2c_w(gspca_dev, PAS106_REG0e, &gain, 1, 1);
+       }
+}
+
+#define BLIMIT(bright) \
+       (u8)((bright > 0x1f) ? 0x1f : ((bright < 4) ? 3 : bright))
+#define LIMIT(color) \
+       (u8)((color > 0xff) ? 0xff : ((color < 0) ? 0 : color))
+
+static void do_autogain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       __u8 luma;
+       __u8 luma_mean = 128;
+       __u8 luma_delta = 20;
+       __u8 spring = 4;
+       int Gbright;
+       __u8 r, g, b;
+
+       if (sd->ag_cnt < 0)
+               return;
+       if (--sd->ag_cnt >= 0)
+               return;
+       sd->ag_cnt = AG_CNT_START;
+
+       Gbright = Et_getgainG(gspca_dev);
+       reg_r(gspca_dev, ET_LUMA_CENTER, 4);
+       g = (gspca_dev->usb_buf[0] + gspca_dev->usb_buf[3]) >> 1;
+       r = gspca_dev->usb_buf[1];
+       b = gspca_dev->usb_buf[2];
+       r = ((r << 8) - (r << 4) - (r << 3)) >> 10;
+       b = ((b << 7) >> 10);
+       g = ((g << 9) + (g << 7) + (g << 5)) >> 10;
+       luma = LIMIT(r + g + b);
+       PDEBUG(D_FRAM, "Etoms luma G %d", luma);
+       if (luma < luma_mean - luma_delta || luma > luma_mean + luma_delta) {
+               Gbright += (luma_mean - luma) >> spring;
+               Gbright = BLIMIT(Gbright);
+               PDEBUG(D_FRAM, "Etoms Gbright %d", Gbright);
+               Et_setgainG(gspca_dev, (__u8) Gbright);
+       }
+}
+
+#undef BLIMIT
+#undef LIMIT
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,                       /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       int seqframe;
+
+       seqframe = data[0] & 0x3f;
+       len = (int) (((data[0] & 0xc0) << 2) | data[1]);
+       if (seqframe == 0x3f) {
+               PDEBUG(D_FRAM,
+                      "header packet found datalength %d !!", len);
+               PDEBUG(D_FRAM, "G %d R %d G %d B %d",
+                      data[2], data[3], data[4], data[5]);
+               data += 30;
+               /* don't change datalength as the chips provided it */
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
+               return;
+       }
+       if (len) {
+               data += 8;
+               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+       } else {                        /* Drop Packet */
+               gspca_dev->last_packet_type = DISCARD_PACKET;
+       }
+}
+
+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_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               setcolors(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               sd->autogain = ctrl->val;
+               setautogain(gspca_dev);
+               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);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 1, 127, 1, 63);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 255, 1, 127);
+       if (sd->sensor == SENSOR_PAS106)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 15, 1, 7);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+       if (hdl->error) {
+               pr_err("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,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+       .dq_callback = do_autogain,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106},
+#if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE
+       {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX},
+#endif
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/finepix.c b/drivers/media/usb/gspca/finepix.c
new file mode 100644 (file)
index 0000000..c8f2201
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * Fujifilm Finepix subdriver
+ *
+ * Copyright (C) 2008 Frank Zago
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "finepix"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Frank Zago <frank@zago.net>");
+MODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver");
+MODULE_LICENSE("GPL");
+
+/* Default timeout, in ms */
+#define FPIX_TIMEOUT 250
+
+/* Maximum transfer size to use. The windows driver reads by chunks of
+ * 0x2000 bytes, so do the same. Note: reading more seems to work
+ * too. */
+#define FPIX_MAX_TRANSFER 0x2000
+
+/* Structure to hold all of our device specific stuff */
+struct usb_fpix {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       struct work_struct work_struct;
+       struct workqueue_struct *work_thread;
+};
+
+/* Delay after which claim the next frame. If the delay is too small,
+ * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms
+ * will fail every 4 or 5 frames, but 30ms is perfect. On the A210,
+ * 30ms is bad while 35ms is perfect. */
+#define NEXT_FRAME_DELAY 35
+
+/* These cameras only support 320x200. */
+static const struct v4l2_pix_format fpix_mode[1] = {
+       { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0}
+};
+
+/* send a command to the webcam */
+static int command(struct gspca_dev *gspca_dev,
+               int order)      /* 0: reset, 1: frame request */
+{
+       static u8 order_values[2][12] = {
+               {0xc6, 0, 0, 0, 0, 0, 0,    0, 0x20, 0, 0, 0},  /* reset */
+               {0xd3, 0, 0, 0, 0, 0, 0, 0x01,    0, 0, 0, 0},  /* fr req */
+       };
+
+       memcpy(gspca_dev->usb_buf, order_values[order], 12);
+       return usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       USB_REQ_GET_STATUS,
+                       USB_DIR_OUT | USB_TYPE_CLASS |
+                       USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
+                       12, FPIX_TIMEOUT);
+}
+
+/* workqueue */
+static void dostream(struct work_struct *work)
+{
+       struct usb_fpix *dev = container_of(work, struct usb_fpix, work_struct);
+       struct gspca_dev *gspca_dev = &dev->gspca_dev;
+       struct urb *urb = gspca_dev->urb[0];
+       u8 *data = urb->transfer_buffer;
+       int ret = 0;
+       int len;
+
+       /* synchronize with the main driver */
+       mutex_lock(&gspca_dev->usb_lock);
+       mutex_unlock(&gspca_dev->usb_lock);
+       PDEBUG(D_STREAM, "dostream started");
+
+       /* loop reading a frame */
+again:
+       while (gspca_dev->dev && gspca_dev->streaming) {
+#ifdef CONFIG_PM
+               if (gspca_dev->frozen)
+                       break;
+#endif
+
+               /* request a frame */
+               mutex_lock(&gspca_dev->usb_lock);
+               ret = command(gspca_dev, 1);
+               mutex_unlock(&gspca_dev->usb_lock);
+               if (ret < 0)
+                       break;
+#ifdef CONFIG_PM
+               if (gspca_dev->frozen)
+                       break;
+#endif
+               if (!gspca_dev->dev || !gspca_dev->streaming)
+                       break;
+
+               /* the frame comes in parts */
+               for (;;) {
+                       ret = usb_bulk_msg(gspca_dev->dev,
+                                       urb->pipe,
+                                       data,
+                                       FPIX_MAX_TRANSFER,
+                                       &len, FPIX_TIMEOUT);
+                       if (ret < 0) {
+                               /* Most of the time we get a timeout
+                                * error. Just restart. */
+                               goto again;
+                       }
+#ifdef CONFIG_PM
+                       if (gspca_dev->frozen)
+                               goto out;
+#endif
+                       if (!gspca_dev->dev || !gspca_dev->streaming)
+                               goto out;
+                       if (len < FPIX_MAX_TRANSFER ||
+                               (data[len - 2] == 0xff &&
+                                       data[len - 1] == 0xd9)) {
+
+                               /* If the result is less than what was asked
+                                * for, then it's the end of the
+                                * frame. Sometimes the jpeg is not complete,
+                                * but there's nothing we can do. We also end
+                                * here if the the jpeg ends right at the end
+                                * of the frame. */
+                               gspca_frame_add(gspca_dev, LAST_PACKET,
+                                               data, len);
+                               break;
+                       }
+
+                       /* got a partial image */
+                       gspca_frame_add(gspca_dev,
+                                       gspca_dev->last_packet_type
+                                               == LAST_PACKET
+                                       ? FIRST_PACKET : INTER_PACKET,
+                                       data, len);
+               }
+
+               /* We must wait before trying reading the next
+                * frame. If we don't, or if the delay is too short,
+                * the camera will disconnect. */
+               msleep(NEXT_FRAME_DELAY);
+       }
+
+out:
+       PDEBUG(D_STREAM, "dostream stopped");
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+               const struct usb_device_id *id)
+{
+       struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
+       struct cam *cam = &gspca_dev->cam;
+
+       cam->cam_mode = fpix_mode;
+       cam->nmodes = 1;
+       cam->bulk = 1;
+       cam->bulk_size = FPIX_MAX_TRANSFER;
+
+       INIT_WORK(&dev->work_struct, dostream);
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       return 0;
+}
+
+/* start the camera */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
+       int ret, len;
+
+       /* Init the device */
+       ret = command(gspca_dev, 0);
+       if (ret < 0) {
+               pr_err("init failed %d\n", ret);
+               return ret;
+       }
+
+       /* Read the result of the command. Ignore the result, for it
+        * varies with the device. */
+       ret = usb_bulk_msg(gspca_dev->dev,
+                       gspca_dev->urb[0]->pipe,
+                       gspca_dev->urb[0]->transfer_buffer,
+                       FPIX_MAX_TRANSFER, &len,
+                       FPIX_TIMEOUT);
+       if (ret < 0) {
+               pr_err("usb_bulk_msg failed %d\n", ret);
+               return ret;
+       }
+
+       /* Request a frame, but don't read it */
+       ret = command(gspca_dev, 1);
+       if (ret < 0) {
+               pr_err("frame request failed %d\n", ret);
+               return ret;
+       }
+
+       /* Again, reset bulk in endpoint */
+       usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
+
+       /* Start the workqueue function to do the streaming */
+       dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
+       queue_work(dev->work_thread, &dev->work_struct);
+
+       return 0;
+}
+
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
+
+       /* wait for the work queue to terminate */
+       mutex_unlock(&gspca_dev->usb_lock);
+       destroy_workqueue(dev->work_thread);
+       mutex_lock(&gspca_dev->usb_lock);
+       dev->work_thread = NULL;
+}
+
+/* Table of supported USB devices */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x04cb, 0x0104)},
+       {USB_DEVICE(0x04cb, 0x0109)},
+       {USB_DEVICE(0x04cb, 0x010b)},
+       {USB_DEVICE(0x04cb, 0x010f)},
+       {USB_DEVICE(0x04cb, 0x0111)},
+       {USB_DEVICE(0x04cb, 0x0113)},
+       {USB_DEVICE(0x04cb, 0x0115)},
+       {USB_DEVICE(0x04cb, 0x0117)},
+       {USB_DEVICE(0x04cb, 0x0119)},
+       {USB_DEVICE(0x04cb, 0x011b)},
+       {USB_DEVICE(0x04cb, 0x011d)},
+       {USB_DEVICE(0x04cb, 0x0121)},
+       {USB_DEVICE(0x04cb, 0x0123)},
+       {USB_DEVICE(0x04cb, 0x0125)},
+       {USB_DEVICE(0x04cb, 0x0127)},
+       {USB_DEVICE(0x04cb, 0x0129)},
+       {USB_DEVICE(0x04cb, 0x012b)},
+       {USB_DEVICE(0x04cb, 0x012d)},
+       {USB_DEVICE(0x04cb, 0x012f)},
+       {USB_DEVICE(0x04cb, 0x0131)},
+       {USB_DEVICE(0x04cb, 0x013b)},
+       {USB_DEVICE(0x04cb, 0x013d)},
+       {USB_DEVICE(0x04cb, 0x013f)},
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name   = MODULE_NAME,
+       .config = sd_config,
+       .init   = sd_init,
+       .start  = sd_start,
+       .stop0  = sd_stop0,
+};
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+               const struct usb_device_id *id)
+{
+       return gspca_dev_probe(intf, id,
+                       &sd_desc,
+                       sizeof(struct usb_fpix),
+                       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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/gl860/Kconfig b/drivers/media/usb/gspca/gl860/Kconfig
new file mode 100644 (file)
index 0000000..22772f5
--- /dev/null
@@ -0,0 +1,8 @@
+config USB_GL860
+       tristate "GL860 USB Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the GL860 chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_gl860.
diff --git a/drivers/media/usb/gspca/gl860/Makefile b/drivers/media/usb/gspca/gl860/Makefile
new file mode 100644 (file)
index 0000000..cf63974
--- /dev/null
@@ -0,0 +1,10 @@
+obj-$(CONFIG_USB_GL860) += gspca_gl860.o
+
+gspca_gl860-objs := gl860.o \
+                   gl860-mi1320.o \
+                   gl860-ov2640.o \
+                   gl860-ov9655.o \
+                   gl860-mi2020.o
+
+ccflags-y += -I$(srctree)/drivers/media/usb/gspca
+
diff --git a/drivers/media/usb/gspca/gl860/gl860-mi1320.c b/drivers/media/usb/gspca/gl860/gl860-mi1320.c
new file mode 100644 (file)
index 0000000..b57160e
--- /dev/null
@@ -0,0 +1,536 @@
+/* Subdriver for the GL860 chip with the MI1320 sensor
+ * Author Olivier LORIN from own logs
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Sensor : MI1320 */
+
+#include "gl860.h"
+
+static struct validx tbl_common[] = {
+       {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba51, 0x0066}, {0xba02, 0x00f1},
+       {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
+       {0xffff, 0xffff},
+       {0xba00, 0x00f0}, {0xba02, 0x00f1}, {0xbafa, 0x0028}, {0xba02, 0x00f1},
+       {0xba00, 0x00f0}, {0xba01, 0x00f1}, {0xbaf0, 0x0006}, {0xba0e, 0x00f1},
+       {0xba70, 0x0006}, {0xba0e, 0x00f1},
+       {0xffff, 0xffff},
+       {0xba74, 0x0006}, {0xba0e, 0x00f1},
+       {0xffff, 0xffff},
+       {0x0061, 0x0000}, {0x0068, 0x000d},
+};
+
+static struct validx tbl_init_at_startup[] = {
+       {0x0000, 0x0000}, {0x0010, 0x0010},
+       {35, 0xffff},
+       {0x0008, 0x00c0}, {0x0001, 0x00c1}, {0x0001, 0x00c2}, {0x0020, 0x0006},
+       {0x006a, 0x000d},
+};
+
+static struct validx tbl_sensor_settings_common[] = {
+       {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2}, {0x0040, 0x0000},
+       {0x006a, 0x0007}, {0x006a, 0x000d}, {0x0063, 0x0006},
+};
+static struct validx tbl_sensor_settings_1280[] = {
+       {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba5a, 0x0066}, {0xba02, 0x00f1},
+       {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xba20, 0x0065}, {0xba00, 0x00f1},
+};
+static struct validx tbl_sensor_settings_800[] = {
+       {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba5a, 0x0066}, {0xba02, 0x00f1},
+       {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xba20, 0x0065}, {0xba00, 0x00f1},
+};
+static struct validx tbl_sensor_settings_640[] = {
+       {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
+       {0xba51, 0x0066}, {0xba02, 0x00f1}, {0xba05, 0x0067}, {0xba05, 0x00f1},
+       {0xba20, 0x0065}, {0xba00, 0x00f1},
+};
+static struct validx tbl_post_unset_alt[] = {
+       {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
+       {0x0061, 0x0000}, {0x0068, 0x000d},
+};
+
+static u8 *tbl_1280[] = {
+       "\x0d\x80\xf1\x08\x03\x04\xf1\x00" "\x04\x05\xf1\x02\x05\x00\xf1\xf1"
+       "\x06\x00\xf1\x0d\x20\x01\xf1\x00" "\x21\x84\xf1\x00\x0d\x00\xf1\x08"
+       "\xf0\x00\xf1\x01\x34\x00\xf1\x00" "\x9b\x43\xf1\x00\xa6\x05\xf1\x00"
+       "\xa9\x04\xf1\x00\xa1\x05\xf1\x00" "\xa4\x04\xf1\x00\xae\x0a\xf1\x08"
+       ,
+       "\xf0\x00\xf1\x02\x3a\x05\xf1\xf1" "\x3c\x05\xf1\xf1\x59\x01\xf1\x47"
+       "\x5a\x01\xf1\x88\x5c\x0a\xf1\x06" "\x5d\x0e\xf1\x0a\x64\x5e\xf1\x1c"
+       "\xd2\x00\xf1\xcf\xcb\x00\xf1\x01"
+       ,
+       "\xd3\x02\xd4\x28\xd5\x01\xd0\x02" "\xd1\x18\xd2\xc1"
+};
+
+static u8 *tbl_800[] = {
+       "\x0d\x80\xf1\x08\x03\x03\xf1\xc0" "\x04\x05\xf1\x02\x05\x00\xf1\xf1"
+       "\x06\x00\xf1\x0d\x20\x01\xf1\x00" "\x21\x84\xf1\x00\x0d\x00\xf1\x08"
+       "\xf0\x00\xf1\x01\x34\x00\xf1\x00" "\x9b\x43\xf1\x00\xa6\x05\xf1\x00"
+       "\xa9\x03\xf1\xc0\xa1\x03\xf1\x20" "\xa4\x02\xf1\x5a\xae\x0a\xf1\x08"
+       ,
+       "\xf0\x00\xf1\x02\x3a\x05\xf1\xf1" "\x3c\x05\xf1\xf1\x59\x01\xf1\x47"
+       "\x5a\x01\xf1\x88\x5c\x0a\xf1\x06" "\x5d\x0e\xf1\x0a\x64\x5e\xf1\x1c"
+       "\xd2\x00\xf1\xcf\xcb\x00\xf1\x01"
+       ,
+       "\xd3\x02\xd4\x18\xd5\x21\xd0\x02" "\xd1\x10\xd2\x59"
+};
+
+static u8 *tbl_640[] = {
+       "\x0d\x80\xf1\x08\x03\x04\xf1\x04" "\x04\x05\xf1\x02\x07\x01\xf1\x7c"
+       "\x08\x00\xf1\x0e\x21\x80\xf1\x00" "\x0d\x00\xf1\x08\xf0\x00\xf1\x01"
+       "\x34\x10\xf1\x10\x3a\x43\xf1\x00" "\xa6\x05\xf1\x02\xa9\x04\xf1\x04"
+       "\xa7\x02\xf1\x81\xaa\x01\xf1\xe2" "\xae\x0c\xf1\x09"
+       ,
+       "\xf0\x00\xf1\x02\x39\x03\xf1\xfc" "\x3b\x04\xf1\x04\x57\x01\xf1\xb6"
+       "\x58\x02\xf1\x0d\x5c\x1f\xf1\x19" "\x5d\x24\xf1\x1e\x64\x5e\xf1\x1c"
+       "\xd2\x00\xf1\x00\xcb\x00\xf1\x01"
+       ,
+       "\xd3\x02\xd4\x10\xd5\x81\xd0\x02" "\xd1\x08\xd2\xe1"
+};
+
+static s32 tbl_sat[] = {0x25, 0x1d, 0x15, 0x0d, 0x05, 0x4d, 0x55, 0x5d, 0x2d};
+static s32 tbl_bright[] = {0, 8, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70};
+static s32 tbl_backlight[] = {0x0e, 0x06, 0x02};
+
+static s32 tbl_cntr1[] = {
+       0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xe0, 0xf0};
+static s32 tbl_cntr2[] = {
+       0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40, 0x38, 0x30, 0x20, 0x10};
+
+static u8 dat_wbalNL[] =
+       "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x3b\x04\xf1\x2a\x47\x10\xf1\x10"
+       "\x9d\x3c\xf1\xae\xaf\x10\xf1\x00" "\xf0\x00\xf1\x02\x2f\x91\xf1\x20"
+       "\x9c\x91\xf1\x20\x37\x03\xf1\x00" "\x9d\xc5\xf1\x0f\xf0\x00\xf1\x00";
+
+static u8 dat_wbalLL[] =
+       "\xf0\x00\xf1\x01\x05\x00\xf1\x0c" "\x3b\x04\xf1\x2a\x47\x40\xf1\x40"
+       "\x9d\x20\xf1\xae\xaf\x10\xf1\x00" "\xf0\x00\xf1\x02\x2f\xd1\xf1\x00"
+       "\x9c\xd1\xf1\x00\x37\x03\xf1\x00" "\x9d\xc5\xf1\x3f\xf0\x00\xf1\x00";
+
+static u8 dat_wbalBL[] =
+       "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x47\x10\xf1\x30\x9d\x3c\xf1\xae"
+       "\xaf\x10\xf1\x00\xf0\x00\xf1\x02" "\x2f\x91\xf1\x20\x9c\x91\xf1\x20"
+       "\x37\x03\xf1\x00\x9d\xc5\xf1\x2f" "\xf0\x00\xf1\x00";
+
+static u8 dat_hvflip1[] = {0xf0, 0x00, 0xf1, 0x00};
+
+static u8 dat_common00[] =
+       "\x00\x01\x07\x6a\x06\x63\x0d\x6a" "\xc0\x00\x10\x10\xc1\x03\xc2\x42"
+       "\xd8\x04\x58\x00\x04\x02";
+static u8 dat_common01[] =
+       "\x0d\x00\xf1\x0b\x0d\x00\xf1\x08" "\x35\x00\xf1\x22\x68\x00\xf1\x5d"
+       "\xf0\x00\xf1\x01\x06\x70\xf1\x0e" "\xf0\x00\xf1\x02\xdd\x18\xf1\xe0";
+static u8 dat_common02[] =
+       "\x05\x01\xf1\x84\x06\x00\xf1\x44" "\x07\x00\xf1\xbe\x08\x00\xf1\x1e"
+       "\x20\x01\xf1\x03\x21\x84\xf1\x00" "\x22\x0d\xf1\x0f\x24\x80\xf1\x00"
+       "\x34\x18\xf1\x2d\x35\x00\xf1\x22" "\x43\x83\xf1\x83\x59\x00\xf1\xff";
+static u8 dat_common03[] =
+       "\xf0\x00\xf1\x02\x39\x06\xf1\x8c" "\x3a\x06\xf1\x8c\x3b\x03\xf1\xda"
+       "\x3c\x05\xf1\x30\x57\x01\xf1\x0c" "\x58\x01\xf1\x42\x59\x01\xf1\x0c"
+       "\x5a\x01\xf1\x42\x5c\x13\xf1\x0e" "\x5d\x17\xf1\x12\x64\x1e\xf1\x1c";
+static u8 dat_common04[] =
+       "\xf0\x00\xf1\x02\x24\x5f\xf1\x20" "\x28\xea\xf1\x02\x5f\x41\xf1\x43";
+static u8 dat_common05[] =
+       "\x02\x00\xf1\xee\x03\x29\xf1\x1a" "\x04\x02\xf1\xa4\x09\x00\xf1\x68"
+       "\x0a\x00\xf1\x2a\x0b\x00\xf1\x04" "\x0c\x00\xf1\x93\x0d\x00\xf1\x82"
+       "\x0e\x00\xf1\x40\x0f\x00\xf1\x5f" "\x10\x00\xf1\x4e\x11\x00\xf1\x5b";
+static u8 dat_common06[] =
+       "\x15\x00\xf1\xc9\x16\x00\xf1\x5e" "\x17\x00\xf1\x9d\x18\x00\xf1\x06"
+       "\x19\x00\xf1\x89\x1a\x00\xf1\x12" "\x1b\x00\xf1\xa1\x1c\x00\xf1\xe4"
+       "\x1d\x00\xf1\x7a\x1e\x00\xf1\x64" "\xf6\x00\xf1\x5f";
+static u8 dat_common07[] =
+       "\xf0\x00\xf1\x01\x53\x09\xf1\x03" "\x54\x3d\xf1\x1c\x55\x99\xf1\x72"
+       "\x56\xc1\xf1\xb1\x57\xd8\xf1\xce" "\x58\xe0\xf1\x00\xdc\x0a\xf1\x03"
+       "\xdd\x45\xf1\x20\xde\xae\xf1\x82" "\xdf\xdc\xf1\xc9\xe0\xf6\xf1\xea"
+       "\xe1\xff\xf1\x00";
+static u8 dat_common08[] =
+       "\xf0\x00\xf1\x01\x80\x00\xf1\x06" "\x81\xf6\xf1\x08\x82\xfb\xf1\xf7"
+       "\x83\x00\xf1\xfe\xb6\x07\xf1\x03" "\xb7\x18\xf1\x0c\x84\xfb\xf1\x06"
+       "\x85\xfb\xf1\xf9\x86\x00\xf1\xff" "\xb8\x07\xf1\x04\xb9\x16\xf1\x0a";
+static u8 dat_common09[] =
+       "\x87\xfa\xf1\x05\x88\xfc\xf1\xf9" "\x89\x00\xf1\xff\xba\x06\xf1\x03"
+       "\xbb\x17\xf1\x09\x8a\xe8\xf1\x14" "\x8b\xf7\xf1\xf0\x8c\xfd\xf1\xfa"
+       "\x8d\x00\xf1\x00\xbc\x05\xf1\x01" "\xbd\x0c\xf1\x08\xbe\x00\xf1\x14";
+static u8 dat_common10[] =
+       "\x8e\xea\xf1\x13\x8f\xf7\xf1\xf2" "\x90\xfd\xf1\xfa\x91\x00\xf1\x00"
+       "\xbf\x05\xf1\x01\xc0\x0a\xf1\x08" "\xc1\x00\xf1\x0c\x92\xed\xf1\x0f"
+       "\x93\xf9\xf1\xf4\x94\xfe\xf1\xfb" "\x95\x00\xf1\x00\xc2\x04\xf1\x01"
+       "\xc3\x0a\xf1\x07\xc4\x00\xf1\x10";
+static u8 dat_common11[] =
+       "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x25\x00\xf1\x55\x34\x10\xf1\x10"
+       "\x35\xf0\xf1\x10\x3a\x02\xf1\x03" "\x3b\x04\xf1\x2a\x9b\x43\xf1\x00"
+       "\xa4\x03\xf1\xc0\xa7\x02\xf1\x81";
+
+static int  mi1320_init_at_startup(struct gspca_dev *gspca_dev);
+static int  mi1320_configure_alt(struct gspca_dev *gspca_dev);
+static int  mi1320_init_pre_alt(struct gspca_dev *gspca_dev);
+static int  mi1320_init_post_alt(struct gspca_dev *gspca_dev);
+static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev);
+static int  mi1320_sensor_settings(struct gspca_dev *gspca_dev);
+static int  mi1320_camera_settings(struct gspca_dev *gspca_dev);
+/*==========================================================================*/
+
+void mi1320_init_settings(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->vcur.backlight  =  0;
+       sd->vcur.brightness =  0;
+       sd->vcur.sharpness  =  6;
+       sd->vcur.contrast   = 10;
+       sd->vcur.gamma      = 20;
+       sd->vcur.hue        =  0;
+       sd->vcur.saturation =  6;
+       sd->vcur.whitebal   =  0;
+       sd->vcur.mirror     = 0;
+       sd->vcur.flip       = 0;
+       sd->vcur.AC50Hz     = 1;
+
+       sd->vmax.backlight  =  2;
+       sd->vmax.brightness =  8;
+       sd->vmax.sharpness  =  7;
+       sd->vmax.contrast   =  0; /* 10 but not working with this driver */
+       sd->vmax.gamma      = 40;
+       sd->vmax.hue        =  5 + 1;
+       sd->vmax.saturation =  8;
+       sd->vmax.whitebal   =  2;
+       sd->vmax.mirror     = 1;
+       sd->vmax.flip       = 1;
+       sd->vmax.AC50Hz     = 1;
+
+       sd->dev_camera_settings = mi1320_camera_settings;
+       sd->dev_init_at_startup = mi1320_init_at_startup;
+       sd->dev_configure_alt   = mi1320_configure_alt;
+       sd->dev_init_pre_alt    = mi1320_init_pre_alt;
+       sd->dev_post_unset_alt  = mi1320_post_unset_alt;
+}
+
+/*==========================================================================*/
+
+static void common(struct gspca_dev *gspca_dev)
+{
+       s32 n; /* reserved for FETCH functions */
+
+       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 22, dat_common00);
+       ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL);
+       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 32, dat_common01);
+       n = fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common));
+       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common02);
+       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common03);
+       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 16, dat_common04);
+       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common05);
+       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 44, dat_common06);
+       keep_on_fetching_validx(gspca_dev, tbl_common,
+                                       ARRAY_SIZE(tbl_common), n);
+       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 52, dat_common07);
+       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common08);
+       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common09);
+       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 56, dat_common10);
+       keep_on_fetching_validx(gspca_dev, tbl_common,
+                                       ARRAY_SIZE(tbl_common), n);
+       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, dat_common11);
+       keep_on_fetching_validx(gspca_dev, tbl_common,
+                                       ARRAY_SIZE(tbl_common), n);
+}
+
+static int mi1320_init_at_startup(struct gspca_dev *gspca_dev)
+{
+       fetch_validx(gspca_dev, tbl_init_at_startup,
+                               ARRAY_SIZE(tbl_init_at_startup));
+
+       common(gspca_dev);
+
+/*     ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */
+
+       return 0;
+}
+
+static int mi1320_init_pre_alt(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->mirrorMask = 0;
+
+       sd->vold.backlight  = -1;
+       sd->vold.brightness = -1;
+       sd->vold.sharpness  = -1;
+       sd->vold.contrast   = -1;
+       sd->vold.saturation = -1;
+       sd->vold.gamma    = -1;
+       sd->vold.hue      = -1;
+       sd->vold.whitebal = -1;
+       sd->vold.mirror   = -1;
+       sd->vold.flip     = -1;
+       sd->vold.AC50Hz   = -1;
+
+       common(gspca_dev);
+
+       mi1320_sensor_settings(gspca_dev);
+
+       mi1320_init_post_alt(gspca_dev);
+
+       return 0;
+}
+
+static int mi1320_init_post_alt(struct gspca_dev *gspca_dev)
+{
+       mi1320_camera_settings(gspca_dev);
+
+       return 0;
+}
+
+static int mi1320_sensor_settings(struct gspca_dev *gspca_dev)
+{
+       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
+
+       ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
+
+       fetch_validx(gspca_dev, tbl_sensor_settings_common,
+                               ARRAY_SIZE(tbl_sensor_settings_common));
+
+       switch (reso) {
+       case IMAGE_1280:
+               fetch_validx(gspca_dev, tbl_sensor_settings_1280,
+                                       ARRAY_SIZE(tbl_sensor_settings_1280));
+               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 64, tbl_1280[0]);
+               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_1280[1]);
+               ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_1280[2]);
+               break;
+
+       case IMAGE_800:
+               fetch_validx(gspca_dev, tbl_sensor_settings_800,
+                                       ARRAY_SIZE(tbl_sensor_settings_800));
+               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 64, tbl_800[0]);
+               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_800[1]);
+               ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_800[2]);
+               break;
+
+       default:
+               fetch_validx(gspca_dev, tbl_sensor_settings_640,
+                                       ARRAY_SIZE(tbl_sensor_settings_640));
+               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 60, tbl_640[0]);
+               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_640[1]);
+               ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_640[2]);
+               break;
+       }
+       return 0;
+}
+
+static int mi1320_configure_alt(struct gspca_dev *gspca_dev)
+{
+       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
+
+       switch (reso) {
+       case IMAGE_640:
+               gspca_dev->alt = 3 + 1;
+               break;
+
+       case IMAGE_800:
+       case IMAGE_1280:
+               gspca_dev->alt = 1 + 1;
+               break;
+       }
+       return 0;
+}
+
+static int mi1320_camera_settings(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       s32 backlight = sd->vcur.backlight;
+       s32 bright = sd->vcur.brightness;
+       s32 sharp  = sd->vcur.sharpness;
+       s32 cntr   = sd->vcur.contrast;
+       s32 gam    = sd->vcur.gamma;
+       s32 hue    = sd->vcur.hue;
+       s32 sat    = sd->vcur.saturation;
+       s32 wbal   = sd->vcur.whitebal;
+       s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
+       s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) > 0);
+       s32 freq   = (sd->vcur.AC50Hz > 0);
+       s32 i;
+
+       if (freq != sd->vold.AC50Hz) {
+               sd->vold.AC50Hz = freq;
+
+               freq = 2 * (freq == 0);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba02, 0x00f1, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00       , 0x005b, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba01 + freq, 0x00f1, 0, NULL);
+       }
+
+       if (wbal != sd->vold.whitebal) {
+               sd->vold.whitebal = wbal;
+               if (wbal < 0 || wbal > sd->vmax.whitebal)
+                       wbal = 0;
+
+               for (i = 0; i < 2; i++) {
+                       if (wbal == 0) { /* Normal light */
+                               ctrl_out(gspca_dev, 0x40, 1,
+                                               0x0010, 0x0010, 0, NULL);
+                               ctrl_out(gspca_dev, 0x40, 1,
+                                               0x0003, 0x00c1, 0, NULL);
+                               ctrl_out(gspca_dev, 0x40, 1,
+                                               0x0042, 0x00c2, 0, NULL);
+                               ctrl_out(gspca_dev, 0x40, 3,
+                                               0xba00, 0x0200, 48, dat_wbalNL);
+                       }
+
+                       if (wbal == 1) { /* Low light */
+                               ctrl_out(gspca_dev, 0x40, 1,
+                                               0x0010, 0x0010, 0, NULL);
+                               ctrl_out(gspca_dev, 0x40, 1,
+                                               0x0004, 0x00c1, 0, NULL);
+                               ctrl_out(gspca_dev, 0x40, 1,
+                                               0x0043, 0x00c2, 0, NULL);
+                               ctrl_out(gspca_dev, 0x40, 3,
+                                               0xba00, 0x0200, 48, dat_wbalLL);
+                       }
+
+                       if (wbal == 2) { /* Back light */
+                               ctrl_out(gspca_dev, 0x40, 1,
+                                               0x0010, 0x0010, 0, NULL);
+                               ctrl_out(gspca_dev, 0x40, 1,
+                                               0x0003, 0x00c1, 0, NULL);
+                               ctrl_out(gspca_dev, 0x40, 1,
+                                               0x0042, 0x00c2, 0, NULL);
+                               ctrl_out(gspca_dev, 0x40, 3,
+                                               0xba00, 0x0200, 44, dat_wbalBL);
+                       }
+               }
+       }
+
+       if (bright != sd->vold.brightness) {
+               sd->vold.brightness = bright;
+               if (bright < 0 || bright > sd->vmax.brightness)
+                       bright = 0;
+
+               bright = tbl_bright[bright];
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + bright, 0x0034, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + bright, 0x00f1, 0, NULL);
+       }
+
+       if (sat != sd->vold.saturation) {
+               sd->vold.saturation = sat;
+               if (sat < 0 || sat > sd->vmax.saturation)
+                       sat = 0;
+
+               sat = tbl_sat[sat];
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00      , 0x0025, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + sat, 0x00f1, 0, NULL);
+       }
+
+       if (sharp != sd->vold.sharpness) {
+               sd->vold.sharpness = sharp;
+               if (sharp < 0 || sharp > sd->vmax.sharpness)
+                       sharp = 0;
+
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00        , 0x0005, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + sharp, 0x00f1, 0, NULL);
+       }
+
+       if (hue != sd->vold.hue) {
+               /* 0=normal  1=NB  2="sepia"  3=negative  4=other  5=other2 */
+               if (hue < 0 || hue > sd->vmax.hue)
+                       hue = 0;
+               if (hue == sd->vmax.hue)
+                       sd->swapRB = 1;
+               else
+                       sd->swapRB = 0;
+
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba70, 0x00e2, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + hue * (hue < 6), 0x00f1,
+                                                       0, NULL);
+       }
+
+       if (backlight != sd->vold.backlight) {
+               sd->vold.backlight = backlight;
+               if (backlight < 0 || backlight > sd->vmax.backlight)
+                       backlight = 0;
+
+               backlight = tbl_backlight[backlight];
+               for (i = 0; i < 2; i++) {
+                       ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
+                       ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
+                       ctrl_out(gspca_dev, 0x40, 1, 0xba74, 0x0006, 0, NULL);
+                       ctrl_out(gspca_dev, 0x40, 1, 0xba80 + backlight, 0x00f1,
+                                                               0, NULL);
+               }
+       }
+
+       if (hue != sd->vold.hue) {
+               sd->vold.hue = hue;
+
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba70, 0x00e2, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + hue * (hue < 6), 0x00f1,
+                                                       0, NULL);
+       }
+
+       if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
+               u8 dat_hvflip2[4] = {0x20, 0x01, 0xf1, 0x00};
+               sd->vold.mirror = mirror;
+               sd->vold.flip = flip;
+
+               dat_hvflip2[3] = flip + 2 * mirror;
+               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 4, dat_hvflip1);
+               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 4, dat_hvflip2);
+       }
+
+       if (gam != sd->vold.gamma) {
+               sd->vold.gamma = gam;
+               if (gam < 0 || gam > sd->vmax.gamma)
+                       gam = 0;
+
+               gam = 2 * gam;
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba04      , 0x003b, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba02 + gam, 0x00f1, 0, NULL);
+       }
+
+       if (cntr != sd->vold.contrast) {
+               sd->vold.contrast = cntr;
+               if (cntr < 0 || cntr > sd->vmax.contrast)
+                       cntr = 0;
+
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + tbl_cntr1[cntr], 0x0035,
+                                                       0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + tbl_cntr2[cntr], 0x00f1,
+                                                       0, NULL);
+       }
+
+       return 0;
+}
+
+static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev)
+{
+       ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
+
+       fetch_validx(gspca_dev, tbl_post_unset_alt,
+                               ARRAY_SIZE(tbl_post_unset_alt));
+}
diff --git a/drivers/media/usb/gspca/gl860/gl860-mi2020.c b/drivers/media/usb/gspca/gl860/gl860-mi2020.c
new file mode 100644 (file)
index 0000000..2edda6b
--- /dev/null
@@ -0,0 +1,733 @@
+/* Subdriver for the GL860 chip with the MI2020 sensor
+ * Author Olivier LORIN, from logs by Iceman/Soro2005 + Fret_saw/Hulkie/Tricid
+ * with the help of Kytrix/BUGabundo/Blazercist.
+ * Driver achieved thanks to a webcam gift by Kytrix.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Sensor : MI2020 */
+
+#include "gl860.h"
+
+static u8 dat_wbal1[] = {0x8c, 0xa2, 0x0c};
+
+static u8 dat_bright1[] = {0x8c, 0xa2, 0x06};
+static u8 dat_bright3[] = {0x8c, 0xa1, 0x02};
+static u8 dat_bright4[] = {0x90, 0x00, 0x0f};
+static u8 dat_bright5[] = {0x8c, 0xa1, 0x03};
+static u8 dat_bright6[] = {0x90, 0x00, 0x05};
+
+static u8 dat_hvflip1[] = {0x8c, 0x27, 0x19};
+static u8 dat_hvflip3[] = {0x8c, 0x27, 0x3b};
+static u8 dat_hvflip5[] = {0x8c, 0xa1, 0x03};
+static u8 dat_hvflip6[] = {0x90, 0x00, 0x06};
+
+static struct idxdata tbl_middle_hvflip_low[] = {
+       {0x33, "\x90\x00\x06"},
+       {6, "\xff\xff\xff"},
+       {0x33, "\x90\x00\x06"},
+       {6, "\xff\xff\xff"},
+       {0x33, "\x90\x00\x06"},
+       {6, "\xff\xff\xff"},
+       {0x33, "\x90\x00\x06"},
+       {6, "\xff\xff\xff"},
+};
+
+static struct idxdata tbl_middle_hvflip_big[] = {
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa1\x20"},
+       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"},
+       {102, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa1\x20"},
+       {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
+};
+
+static struct idxdata tbl_end_hvflip[] = {
+       {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
+       {6, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
+       {6, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
+       {6, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
+};
+
+static u8 dat_freq1[] = { 0x8c, 0xa4, 0x04 };
+
+static u8 dat_multi5[] = { 0x8c, 0xa1, 0x03 };
+static u8 dat_multi6[] = { 0x90, 0x00, 0x05 };
+
+static struct validx tbl_init_at_startup[] = {
+       {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1},
+       {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d},
+       {53, 0xffff},
+       {0x0040, 0x0000}, {0x0063, 0x0006},
+};
+
+static struct validx tbl_common_0B[] = {
+       {0x0002, 0x0004}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a, 0x000d},
+       {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2},
+       {0x0004, 0x00d8}, {0x0000, 0x0058}, {0x0041, 0x0000},
+};
+
+static struct idxdata tbl_common_3B[] = {
+       {0x33, "\x86\x25\x01"}, {0x33, "\x86\x25\x00"},
+       {2, "\xff\xff\xff"},
+       {0x30, "\x1a\x0a\xcc"}, {0x32, "\x02\x00\x08"}, {0x33, "\xf4\x03\x1d"},
+       {6, "\xff\xff\xff"}, /* 12 */
+       {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
+       {2, "\xff\xff\xff"}, /* - */
+       {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\x22\x23"},
+       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa2\x0f"}, {0x33, "\x90\x00\x0d"},
+       {0x33, "\x8c\xa2\x10"}, {0x33, "\x90\x00\x0b"}, {0x33, "\x8c\xa2\x11"},
+       {0x33, "\x90\x00\x07"}, {0x33, "\xf4\x03\x1d"}, {0x35, "\xa2\x00\xe2"},
+       {0x33, "\x8c\xab\x05"}, {0x33, "\x90\x00\x01"}, {0x32, "\x6e\x00\x86"},
+       {0x32, "\x70\x0f\xaa"}, {0x32, "\x72\x0f\xe4"}, {0x33, "\x8c\xa3\x4a"},
+       {0x33, "\x90\x00\x5a"}, {0x33, "\x8c\xa3\x4b"}, {0x33, "\x90\x00\xa6"},
+       {0x33, "\x8c\xa3\x61"}, {0x33, "\x90\x00\xc8"}, {0x33, "\x8c\xa3\x62"},
+       {0x33, "\x90\x00\xe1"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"},
+       {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"},
+       {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"},
+       {0x34, "\xde\x01\x5b"}, {0x34, "\xe6\x01\x13"}, {0x34, "\xee\x0b\xf0"},
+       {0x34, "\xf6\x0b\xa4"}, {0x35, "\x00\xf6\xe7"}, {0x35, "\x08\x0d\xfd"},
+       {0x35, "\x10\x25\x63"}, {0x35, "\x18\x35\x6c"}, {0x35, "\x20\x42\x7e"},
+       {0x35, "\x28\x19\x44"}, {0x35, "\x30\x39\xd4"}, {0x35, "\x38\xf5\xa8"},
+       {0x35, "\x4c\x07\x90"}, {0x35, "\x44\x07\xb8"}, {0x35, "\x5c\x06\x88"},
+       {0x35, "\x54\x07\xff"}, {0x34, "\xe0\x01\x52"}, {0x34, "\xe8\x00\xcc"},
+       {0x34, "\xf0\x0d\x83"}, {0x34, "\xf8\x0c\xb3"}, {0x35, "\x02\xfe\xba"},
+       {0x35, "\x0a\x04\xe0"}, {0x35, "\x12\x1c\x63"}, {0x35, "\x1a\x2b\x5a"},
+       {0x35, "\x22\x32\x5e"}, {0x35, "\x2a\x0d\x28"}, {0x35, "\x32\x2c\x02"},
+       {0x35, "\x3a\xf4\xfa"}, {0x35, "\x4e\x07\xef"}, {0x35, "\x46\x07\x88"},
+       {0x35, "\x5e\x07\xc1"}, {0x35, "\x56\x04\x64"}, {0x34, "\xe4\x01\x15"},
+       {0x34, "\xec\x00\x82"}, {0x34, "\xf4\x0c\xce"}, {0x34, "\xfc\x0c\xba"},
+       {0x35, "\x06\x1f\x02"}, {0x35, "\x0e\x02\xe3"}, {0x35, "\x16\x1a\x50"},
+       {0x35, "\x1e\x24\x39"}, {0x35, "\x26\x23\x4c"}, {0x35, "\x2e\xf9\x1b"},
+       {0x35, "\x36\x23\x19"}, {0x35, "\x3e\x12\x08"}, {0x35, "\x52\x07\x22"},
+       {0x35, "\x4a\x03\xd3"}, {0x35, "\x62\x06\x54"}, {0x35, "\x5a\x04\x5d"},
+       {0x34, "\xe2\x01\x04"}, {0x34, "\xea\x00\xa0"}, {0x34, "\xf2\x0c\xbc"},
+       {0x34, "\xfa\x0c\x5b"}, {0x35, "\x04\x17\xf2"}, {0x35, "\x0c\x02\x08"},
+       {0x35, "\x14\x28\x43"}, {0x35, "\x1c\x28\x62"}, {0x35, "\x24\x2b\x60"},
+       {0x35, "\x2c\x07\x33"}, {0x35, "\x34\x1f\xb0"}, {0x35, "\x3c\xed\xcd"},
+       {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"},
+       {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"},
+       {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"},
+       {0x33, "\x78\x00\x00"},
+       {2, "\xff\xff\xff"},
+       {0x35, "\xb8\x1f\x20"}, {0x33, "\x8c\xa2\x06"}, {0x33, "\x90\x00\x10"},
+       {0x33, "\x8c\xa2\x07"}, {0x33, "\x90\x00\x08"}, {0x33, "\x8c\xa2\x42"},
+       {0x33, "\x90\x00\x0b"}, {0x33, "\x8c\xa2\x4a"}, {0x33, "\x90\x00\x8c"},
+       {0x35, "\xba\xfa\x08"}, {0x33, "\x8c\xa2\x02"}, {0x33, "\x90\x00\x22"},
+       {0x33, "\x8c\xa2\x03"}, {0x33, "\x90\x00\xbb"}, {0x33, "\x8c\xa4\x04"},
+       {0x33, "\x90\x00\x80"}, {0x33, "\x8c\xa7\x9d"}, {0x33, "\x90\x00\x00"},
+       {0x33, "\x8c\xa7\x9e"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa2\x0c"},
+       {0x33, "\x90\x00\x17"}, {0x33, "\x8c\xa2\x15"}, {0x33, "\x90\x00\x04"},
+       {0x33, "\x8c\xa2\x14"}, {0x33, "\x90\x00\x20"}, {0x33, "\x8c\xa1\x03"},
+       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"}, {0x33, "\x90\x21\x11"},
+       {0x33, "\x8c\x27\x1b"}, {0x33, "\x90\x02\x4f"}, {0x33, "\x8c\x27\x25"},
+       {0x33, "\x90\x06\x0f"}, {0x33, "\x8c\x27\x39"}, {0x33, "\x90\x21\x11"},
+       {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"}, {0x33, "\x8c\x27\x47"},
+       {0x33, "\x90\x09\x4c"}, {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x02\x84"},
+       {0x33, "\x8c\x27\x05"}, {0x33, "\x90\x01\xe2"}, {0x33, "\x8c\x27\x07"},
+       {0x33, "\x90\x06\x40"}, {0x33, "\x8c\x27\x09"}, {0x33, "\x90\x04\xb0"},
+       {0x33, "\x8c\x27\x0d"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x0f"},
+       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x11"}, {0x33, "\x90\x04\xbd"},
+       {0x33, "\x8c\x27\x13"}, {0x33, "\x90\x06\x4d"}, {0x33, "\x8c\x27\x15"},
+       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"}, {0x33, "\x90\x21\x11"},
+       {0x33, "\x8c\x27\x19"}, {0x33, "\x90\x04\x6c"}, {0x33, "\x8c\x27\x1b"},
+       {0x33, "\x90\x02\x4f"}, {0x33, "\x8c\x27\x1d"}, {0x33, "\x90\x01\x02"},
+       {0x33, "\x8c\x27\x1f"}, {0x33, "\x90\x02\x79"}, {0x33, "\x8c\x27\x21"},
+       {0x33, "\x90\x01\x55"}, {0x33, "\x8c\x27\x23"}, {0x33, "\x90\x02\x85"},
+       {0x33, "\x8c\x27\x25"}, {0x33, "\x90\x06\x0f"}, {0x33, "\x8c\x27\x27"},
+       {0x33, "\x90\x20\x20"}, {0x33, "\x8c\x27\x29"}, {0x33, "\x90\x20\x20"},
+       {0x33, "\x8c\x27\x2b"}, {0x33, "\x90\x10\x20"}, {0x33, "\x8c\x27\x2d"},
+       {0x33, "\x90\x20\x07"}, {0x33, "\x8c\x27\x2f"}, {0x33, "\x90\x00\x04"},
+       {0x33, "\x8c\x27\x31"}, {0x33, "\x90\x00\x04"}, {0x33, "\x8c\x27\x33"},
+       {0x33, "\x90\x04\xbb"}, {0x33, "\x8c\x27\x35"}, {0x33, "\x90\x06\x4b"},
+       {0x33, "\x8c\x27\x37"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x39"},
+       {0x33, "\x90\x21\x11"}, {0x33, "\x8c\x27\x3b"}, {0x33, "\x90\x00\x24"},
+       {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"}, {0x33, "\x8c\x27\x41"},
+       {0x33, "\x90\x01\x69"}, {0x33, "\x8c\x27\x45"}, {0x33, "\x90\x04\xed"},
+       {0x33, "\x8c\x27\x47"}, {0x33, "\x90\x09\x4c"}, {0x33, "\x8c\x27\x51"},
+       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x53"}, {0x33, "\x90\x03\x20"},
+       {0x33, "\x8c\x27\x55"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x57"},
+       {0x33, "\x90\x02\x58"}, {0x33, "\x8c\x27\x5f"}, {0x33, "\x90\x00\x00"},
+       {0x33, "\x8c\x27\x61"}, {0x33, "\x90\x06\x40"}, {0x33, "\x8c\x27\x63"},
+       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x65"}, {0x33, "\x90\x04\xb0"},
+       {0x33, "\x8c\x22\x2e"}, {0x33, "\x90\x00\xa1"}, {0x33, "\x8c\xa4\x08"},
+       {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x21"},
+       {0x33, "\x8c\xa4\x0a"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\xa4\x0b"},
+       {0x33, "\x90\x00\x27"}, {0x33, "\x8c\x24\x11"}, {0x33, "\x90\x00\xa1"},
+       {0x33, "\x8c\x24\x13"}, {0x33, "\x90\x00\xc1"}, {0x33, "\x8c\x24\x15"},
+       {0x33, "\x90\x00\x6a"}, {0x33, "\x8c\x24\x17"}, {0x33, "\x90\x00\x80"},
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
+       {2, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
+       {3, "\xff\xff\xff"},
+};
+
+static struct idxdata tbl_init_post_alt_low1[] = {
+       {0x33, "\x8c\x27\x15"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\x22\x2e"},
+       {0x33, "\x90\x00\x81"}, {0x33, "\x8c\xa4\x08"}, {0x33, "\x90\x00\x17"},
+       {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x1a"}, {0x33, "\x8c\xa4\x0a"},
+       {0x33, "\x90\x00\x1d"}, {0x33, "\x8c\xa4\x0b"}, {0x33, "\x90\x00\x20"},
+       {0x33, "\x8c\x24\x11"}, {0x33, "\x90\x00\x81"}, {0x33, "\x8c\x24\x13"},
+       {0x33, "\x90\x00\x9b"},
+};
+
+static struct idxdata tbl_init_post_alt_low2[] = {
+       {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x03\x24"}, {0x33, "\x8c\x27\x05"},
+       {0x33, "\x90\x02\x58"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
+       {2, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
+       {2, "\xff\xff\xff"},
+};
+
+static struct idxdata tbl_init_post_alt_low3[] = {
+       {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
+       {2, "\xff\xff\xff"},
+       {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x20"},
+       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x01"},
+       {0x33, "\x2e\x01\x00"}, {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"},
+       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x95"}, {0x33, "\x90\x01\x00"},
+       {2, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x03"},
+       {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
+       {2, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"},
+       {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"},
+       {2, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
+       {2, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
+       {2, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
+       {2, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
+};
+
+static struct idxdata tbl_init_post_alt_big[] = {
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
+       {2, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
+       {2, "\xff\xff\xff"},
+       {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
+       {2, "\xff\xff\xff"},
+       {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x03"},
+       {0x33, "\x90\x00\x05"},
+       {2, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
+       {2, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
+       {2, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, {0x33, "\x8c\xa1\x20"},
+       {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x30"}, {0x33, "\x90\x00\x03"},
+       {0x33, "\x8c\xa1\x31"}, {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa1\x32"},
+       {0x33, "\x90\x00\x03"}, {0x33, "\x8c\xa1\x34"}, {0x33, "\x90\x00\x03"},
+       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x02"}, {0x33, "\x2e\x01\x00"},
+       {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
+       {0x33, "\x8c\x27\x97"}, {0x33, "\x90\x01\x00"},
+       {51, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"},
+       {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"},
+       {51, "\xff\xff\xff"},
+       {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x03"},
+       {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
+       {51, "\xff\xff\xff"},
+};
+
+static struct idxdata tbl_init_post_alt_3B[] = {
+       {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"},
+       {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"},
+       {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"},
+       {0x34, "\xde\x01\x5b"}, {0x34, "\xe6\x01\x13"}, {0x34, "\xee\x0b\xf0"},
+       {0x34, "\xf6\x0b\xa4"}, {0x35, "\x00\xf6\xe7"}, {0x35, "\x08\x0d\xfd"},
+       {0x35, "\x10\x25\x63"}, {0x35, "\x18\x35\x6c"}, {0x35, "\x20\x42\x7e"},
+       {0x35, "\x28\x19\x44"}, {0x35, "\x30\x39\xd4"}, {0x35, "\x38\xf5\xa8"},
+       {0x35, "\x4c\x07\x90"}, {0x35, "\x44\x07\xb8"}, {0x35, "\x5c\x06\x88"},
+       {0x35, "\x54\x07\xff"}, {0x34, "\xe0\x01\x52"}, {0x34, "\xe8\x00\xcc"},
+       {0x34, "\xf0\x0d\x83"}, {0x34, "\xf8\x0c\xb3"}, {0x35, "\x02\xfe\xba"},
+       {0x35, "\x0a\x04\xe0"}, {0x35, "\x12\x1c\x63"}, {0x35, "\x1a\x2b\x5a"},
+       {0x35, "\x22\x32\x5e"}, {0x35, "\x2a\x0d\x28"}, {0x35, "\x32\x2c\x02"},
+       {0x35, "\x3a\xf4\xfa"}, {0x35, "\x4e\x07\xef"}, {0x35, "\x46\x07\x88"},
+       {0x35, "\x5e\x07\xc1"}, {0x35, "\x56\x04\x64"}, {0x34, "\xe4\x01\x15"},
+       {0x34, "\xec\x00\x82"}, {0x34, "\xf4\x0c\xce"}, {0x34, "\xfc\x0c\xba"},
+       {0x35, "\x06\x1f\x02"}, {0x35, "\x0e\x02\xe3"}, {0x35, "\x16\x1a\x50"},
+       {0x35, "\x1e\x24\x39"}, {0x35, "\x26\x23\x4c"}, {0x35, "\x2e\xf9\x1b"},
+       {0x35, "\x36\x23\x19"}, {0x35, "\x3e\x12\x08"}, {0x35, "\x52\x07\x22"},
+       {0x35, "\x4a\x03\xd3"}, {0x35, "\x62\x06\x54"}, {0x35, "\x5a\x04\x5d"},
+       {0x34, "\xe2\x01\x04"}, {0x34, "\xea\x00\xa0"}, {0x34, "\xf2\x0c\xbc"},
+       {0x34, "\xfa\x0c\x5b"}, {0x35, "\x04\x17\xf2"}, {0x35, "\x0c\x02\x08"},
+       {0x35, "\x14\x28\x43"}, {0x35, "\x1c\x28\x62"}, {0x35, "\x24\x2b\x60"},
+       {0x35, "\x2c\x07\x33"}, {0x35, "\x34\x1f\xb0"}, {0x35, "\x3c\xed\xcd"},
+       {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"},
+       {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"},
+       {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"},
+};
+
+static u8 *dat_640  = "\xd0\x02\xd1\x08\xd2\xe1\xd3\x02\xd4\x10\xd5\x81";
+static u8 *dat_800  = "\xd0\x02\xd1\x10\xd2\x57\xd3\x02\xd4\x18\xd5\x21";
+static u8 *dat_1280 = "\xd0\x02\xd1\x20\xd2\x01\xd3\x02\xd4\x28\xd5\x01";
+static u8 *dat_1600 = "\xd0\x02\xd1\x20\xd2\xaf\xd3\x02\xd4\x30\xd5\x41";
+
+static int  mi2020_init_at_startup(struct gspca_dev *gspca_dev);
+static int  mi2020_configure_alt(struct gspca_dev *gspca_dev);
+static int  mi2020_init_pre_alt(struct gspca_dev *gspca_dev);
+static int  mi2020_init_post_alt(struct gspca_dev *gspca_dev);
+static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev);
+static int  mi2020_camera_settings(struct gspca_dev *gspca_dev);
+/*==========================================================================*/
+
+void mi2020_init_settings(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->vcur.backlight  =  0;
+       sd->vcur.brightness = 70;
+       sd->vcur.sharpness  = 20;
+       sd->vcur.contrast   =  0;
+       sd->vcur.gamma      =  0;
+       sd->vcur.hue        =  0;
+       sd->vcur.saturation = 60;
+       sd->vcur.whitebal   =  0; /* 50, not done by hardware */
+       sd->vcur.mirror = 0;
+       sd->vcur.flip   = 0;
+       sd->vcur.AC50Hz = 1;
+
+       sd->vmax.backlight  =  64;
+       sd->vmax.brightness = 128;
+       sd->vmax.sharpness  =  40;
+       sd->vmax.contrast   =   3;
+       sd->vmax.gamma      =   2;
+       sd->vmax.hue        =   0 + 1; /* 200, not done by hardware */
+       sd->vmax.saturation =   0;     /* 100, not done by hardware */
+       sd->vmax.whitebal   =   2;     /* 100, not done by hardware */
+       sd->vmax.mirror = 1;
+       sd->vmax.flip   = 1;
+       sd->vmax.AC50Hz = 1;
+
+       sd->dev_camera_settings = mi2020_camera_settings;
+       sd->dev_init_at_startup = mi2020_init_at_startup;
+       sd->dev_configure_alt   = mi2020_configure_alt;
+       sd->dev_init_pre_alt    = mi2020_init_pre_alt;
+       sd->dev_post_unset_alt  = mi2020_post_unset_alt;
+}
+
+/*==========================================================================*/
+
+static void common(struct gspca_dev *gspca_dev)
+{
+       fetch_validx(gspca_dev, tbl_common_0B, ARRAY_SIZE(tbl_common_0B));
+       fetch_idxdata(gspca_dev, tbl_common_3B, ARRAY_SIZE(tbl_common_3B));
+       ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL);
+}
+
+static int mi2020_init_at_startup(struct gspca_dev *gspca_dev)
+{
+       u8 c;
+
+       ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &c);
+       ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &c);
+
+       fetch_validx(gspca_dev, tbl_init_at_startup,
+                       ARRAY_SIZE(tbl_init_at_startup));
+
+       ctrl_out(gspca_dev, 0x40,  1, 0x7a00, 0x8030,  0, NULL);
+       ctrl_in(gspca_dev, 0xc0,  2, 0x7a00, 0x8030,  1, &c);
+
+       common(gspca_dev);
+
+       msleep(61);
+/*     ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000,  0, NULL); */
+/*     msleep(36); */
+       ctrl_out(gspca_dev, 0x40,  1, 0x0001, 0x0000,  0, NULL);
+
+       return 0;
+}
+
+static int mi2020_init_pre_alt(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->mirrorMask =  0;
+       sd->vold.hue   = -1;
+
+       /* These controls need to be reset */
+       sd->vold.brightness = -1;
+       sd->vold.sharpness  = -1;
+
+       /* If not different from default, they do not need to be set */
+       sd->vold.contrast  = 0;
+       sd->vold.gamma     = 0;
+       sd->vold.backlight = 0;
+
+       mi2020_init_post_alt(gspca_dev);
+
+       return 0;
+}
+
+static int mi2020_init_post_alt(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
+
+       s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
+       s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) > 0);
+       s32 freq   = (sd->vcur.AC50Hz  > 0);
+       s32 wbal   = sd->vcur.whitebal;
+
+       u8 dat_freq2[] = {0x90, 0x00, 0x80};
+       u8 dat_multi1[] = {0x8c, 0xa7, 0x00};
+       u8 dat_multi2[] = {0x90, 0x00, 0x00};
+       u8 dat_multi3[] = {0x8c, 0xa7, 0x00};
+       u8 dat_multi4[] = {0x90, 0x00, 0x00};
+       u8 dat_hvflip2[] = {0x90, 0x04, 0x6c};
+       u8 dat_hvflip4[] = {0x90, 0x00, 0x24};
+       u8 dat_wbal2[] = {0x90, 0x00, 0x00};
+       u8 c;
+
+       sd->nbIm = -1;
+
+       dat_freq2[2] = freq ? 0xc0 : 0x80;
+       dat_multi1[2] = 0x9d;
+       dat_multi3[2] = dat_multi1[2] + 1;
+       if (wbal == 0) {
+               dat_multi4[2] = dat_multi2[2] = 0;
+               dat_wbal2[2] = 0x17;
+       } else if (wbal == 1) {
+               dat_multi4[2] = dat_multi2[2] = 0;
+               dat_wbal2[2] = 0x35;
+       } else if (wbal == 2) {
+               dat_multi4[2] = dat_multi2[2] = 0x20;
+               dat_wbal2[2] = 0x17;
+       }
+       dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror);
+       dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror);
+
+       msleep(200);
+       ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
+       msleep(2);
+
+       common(gspca_dev);
+
+       msleep(142);
+       ctrl_out(gspca_dev, 0x40,  1, 0x0010, 0x0010,  0, NULL);
+       ctrl_out(gspca_dev, 0x40,  1, 0x0003, 0x00c1,  0, NULL);
+       ctrl_out(gspca_dev, 0x40,  1, 0x0042, 0x00c2,  0, NULL);
+       ctrl_out(gspca_dev, 0x40,  1, 0x006a, 0x000d,  0, NULL);
+
+       switch (reso) {
+       case IMAGE_640:
+       case IMAGE_800:
+               if (reso != IMAGE_800)
+                       ctrl_out(gspca_dev, 0x40,  3, 0x0000, 0x0200,
+                               12, dat_640);
+               else
+                       ctrl_out(gspca_dev, 0x40,  3, 0x0000, 0x0200,
+                               12, dat_800);
+
+               fetch_idxdata(gspca_dev, tbl_init_post_alt_low1,
+                                       ARRAY_SIZE(tbl_init_post_alt_low1));
+
+               if (reso == IMAGE_800)
+                       fetch_idxdata(gspca_dev, tbl_init_post_alt_low2,
+                                       ARRAY_SIZE(tbl_init_post_alt_low2));
+
+               fetch_idxdata(gspca_dev, tbl_init_post_alt_low3,
+                               ARRAY_SIZE(tbl_init_post_alt_low3));
+
+               ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
+               msleep(120);
+               break;
+
+       case IMAGE_1280:
+       case IMAGE_1600:
+               if (reso == IMAGE_1280) {
+                       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
+                                       12, dat_1280);
+                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
+                                       3, "\x8c\x27\x07");
+                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
+                                       3, "\x90\x05\x04");
+                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
+                                       3, "\x8c\x27\x09");
+                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
+                                       3, "\x90\x04\x02");
+               } else {
+                       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
+                                       12, dat_1600);
+                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
+                                       3, "\x8c\x27\x07");
+                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
+                                       3, "\x90\x06\x40");
+                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
+                                       3, "\x8c\x27\x09");
+                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
+                                       3, "\x90\x04\xb0");
+               }
+
+               fetch_idxdata(gspca_dev, tbl_init_post_alt_big,
+                               ARRAY_SIZE(tbl_init_post_alt_big));
+
+               ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
+               msleep(1850);
+       }
+
+       ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
+       msleep(40);
+
+       /* AC power frequency */
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1);
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2);
+       msleep(33);
+       /* light source */
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal1);
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal2);
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
+       msleep(7);
+       ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c);
+
+       fetch_idxdata(gspca_dev, tbl_init_post_alt_3B,
+                       ARRAY_SIZE(tbl_init_post_alt_3B));
+
+       /* hvflip */
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1);
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2);
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3);
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4);
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5);
+       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6);
+       msleep(250);
+
+       if (reso == IMAGE_640 || reso == IMAGE_800)
+               fetch_idxdata(gspca_dev, tbl_middle_hvflip_low,
+                               ARRAY_SIZE(tbl_middle_hvflip_low));
+       else
+               fetch_idxdata(gspca_dev, tbl_middle_hvflip_big,
+                               ARRAY_SIZE(tbl_middle_hvflip_big));
+
+       fetch_idxdata(gspca_dev, tbl_end_hvflip,
+                       ARRAY_SIZE(tbl_end_hvflip));
+
+       sd->nbIm = 0;
+
+       sd->vold.mirror    = mirror;
+       sd->vold.flip      = flip;
+       sd->vold.AC50Hz    = freq;
+       sd->vold.whitebal  = wbal;
+
+       mi2020_camera_settings(gspca_dev);
+
+       return 0;
+}
+
+static int mi2020_configure_alt(struct gspca_dev *gspca_dev)
+{
+       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
+
+       switch (reso) {
+       case IMAGE_640:
+               gspca_dev->alt = 3 + 1;
+               break;
+
+       case IMAGE_800:
+       case IMAGE_1280:
+       case IMAGE_1600:
+               gspca_dev->alt = 1 + 1;
+               break;
+       }
+       return 0;
+}
+
+static int mi2020_camera_settings(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
+
+       s32 backlight = sd->vcur.backlight;
+       s32 bright =  sd->vcur.brightness;
+       s32 sharp  =  sd->vcur.sharpness;
+       s32 cntr   =  sd->vcur.contrast;
+       s32 gam    =  sd->vcur.gamma;
+       s32 hue    = (sd->vcur.hue > 0);
+       s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
+       s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) > 0);
+       s32 freq   = (sd->vcur.AC50Hz > 0);
+       s32 wbal   = sd->vcur.whitebal;
+
+       u8 dat_sharp[] = {0x6c, 0x00, 0x08};
+       u8 dat_bright2[] = {0x90, 0x00, 0x00};
+       u8 dat_freq2[] = {0x90, 0x00, 0x80};
+       u8 dat_multi1[] = {0x8c, 0xa7, 0x00};
+       u8 dat_multi2[] = {0x90, 0x00, 0x00};
+       u8 dat_multi3[] = {0x8c, 0xa7, 0x00};
+       u8 dat_multi4[] = {0x90, 0x00, 0x00};
+       u8 dat_hvflip2[] = {0x90, 0x04, 0x6c};
+       u8 dat_hvflip4[] = {0x90, 0x00, 0x24};
+       u8 dat_wbal2[] = {0x90, 0x00, 0x00};
+
+       /* Less than 4 images received -> too early to set the settings */
+       if (sd->nbIm < 4) {
+               sd->waitSet = 1;
+               return 0;
+       }
+       sd->waitSet = 0;
+
+       if (freq != sd->vold.AC50Hz) {
+               sd->vold.AC50Hz = freq;
+
+               dat_freq2[2] = freq ? 0xc0 : 0x80;
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2);
+               msleep(20);
+       }
+
+       if (wbal != sd->vold.whitebal) {
+               sd->vold.whitebal = wbal;
+               if (wbal < 0 || wbal > sd->vmax.whitebal)
+                       wbal = 0;
+
+               dat_multi1[2] = 0x9d;
+               dat_multi3[2] = dat_multi1[2] + 1;
+               if (wbal == 0) {
+                       dat_multi4[2] = dat_multi2[2] = 0;
+                       dat_wbal2[2] = 0x17;
+               } else if (wbal == 1) {
+                       dat_multi4[2] = dat_multi2[2] = 0;
+                       dat_wbal2[2] = 0x35;
+               } else if (wbal == 2) {
+                       dat_multi4[2] = dat_multi2[2] = 0x20;
+                       dat_wbal2[2] = 0x17;
+               }
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal1);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal2);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
+       }
+
+       if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
+               sd->vold.mirror = mirror;
+               sd->vold.flip   = flip;
+
+               dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror);
+               dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror);
+
+               fetch_idxdata(gspca_dev, tbl_init_post_alt_3B,
+                               ARRAY_SIZE(tbl_init_post_alt_3B));
+
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6);
+               msleep(40);
+
+               if (reso == IMAGE_640 || reso == IMAGE_800)
+                       fetch_idxdata(gspca_dev, tbl_middle_hvflip_low,
+                                       ARRAY_SIZE(tbl_middle_hvflip_low));
+               else
+                       fetch_idxdata(gspca_dev, tbl_middle_hvflip_big,
+                                       ARRAY_SIZE(tbl_middle_hvflip_big));
+
+               fetch_idxdata(gspca_dev, tbl_end_hvflip,
+                               ARRAY_SIZE(tbl_end_hvflip));
+       }
+
+       if (bright != sd->vold.brightness) {
+               sd->vold.brightness = bright;
+               if (bright < 0 || bright > sd->vmax.brightness)
+                       bright = 0;
+
+               dat_bright2[2] = bright;
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright1);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright2);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright3);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright4);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright5);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright6);
+       }
+
+       if (cntr != sd->vold.contrast || gam != sd->vold.gamma) {
+               sd->vold.contrast = cntr;
+               if (cntr < 0 || cntr > sd->vmax.contrast)
+                       cntr = 0;
+               sd->vold.gamma = gam;
+               if (gam < 0 || gam > sd->vmax.gamma)
+                       gam = 0;
+
+               dat_multi1[2] = 0x6d;
+               dat_multi3[2] = dat_multi1[2] + 1;
+               if (cntr == 0)
+                       cntr = 4;
+               dat_multi4[2] = dat_multi2[2] = cntr * 0x10 + 2 - gam;
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
+       }
+
+       if (backlight != sd->vold.backlight) {
+               sd->vold.backlight = backlight;
+               if (backlight < 0 || backlight > sd->vmax.backlight)
+                       backlight = 0;
+
+               dat_multi1[2] = 0x9d;
+               dat_multi3[2] = dat_multi1[2] + 1;
+               dat_multi4[2] = dat_multi2[2] = backlight;
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
+       }
+
+       if (sharp != sd->vold.sharpness) {
+               sd->vold.sharpness = sharp;
+               if (sharp < 0 || sharp > sd->vmax.sharpness)
+                       sharp = 0;
+
+               dat_sharp[1] = sharp;
+               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0032, 3, dat_sharp);
+       }
+
+       if (hue != sd->vold.hue) {
+               sd->swapRB = hue;
+               sd->vold.hue = hue;
+       }
+
+       return 0;
+}
+
+static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev)
+{
+       ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
+       msleep(40);
+       ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0000, 0, NULL);
+}
diff --git a/drivers/media/usb/gspca/gl860/gl860-ov2640.c b/drivers/media/usb/gspca/gl860/gl860-ov2640.c
new file mode 100644 (file)
index 0000000..768cac5
--- /dev/null
@@ -0,0 +1,489 @@
+/* Subdriver for the GL860 chip with the OV2640 sensor
+ * Author Olivier LORIN, from Malmostoso's logs
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Sensor : OV2640 */
+
+#include "gl860.h"
+
+static u8 dat_init1[] = "\x00\x41\x07\x6a\x06\x61\x0d\x6a" "\x10\x10\xc1\x01";
+
+static u8 c61[] = {0x61}; /* expected */
+static u8 c51[] = {0x51}; /* expected */
+static u8 c50[] = {0x50}; /* expected */
+static u8 c28[] = {0x28}; /* expected */
+static u8 ca8[] = {0xa8}; /* expected */
+
+static u8 dat_post[] =
+       "\x00\x41\x07\x6a\x06\xef\x0d\x6a" "\x10\x10\xc1\x01";
+
+static u8 dat_640[]  = "\xd0\x01\xd1\x08\xd2\xe0\xd3\x02\xd4\x10\xd5\x81";
+static u8 dat_800[]  = "\xd0\x01\xd1\x10\xd2\x58\xd3\x02\xd4\x18\xd5\x21";
+static u8 dat_1280[] = "\xd0\x01\xd1\x18\xd2\xc0\xd3\x02\xd4\x28\xd5\x01";
+static u8 dat_1600[] = "\xd0\x01\xd1\x20\xd2\xb0\xd3\x02\xd4\x30\xd5\x41";
+
+static struct validx tbl_init_at_startup[] = {
+       {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1},
+       {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d},
+       {0x0050, 0x0000}, {0x0041, 0x0000}, {0x006a, 0x0007}, {0x0061, 0x0006},
+       {0x006a, 0x000d}, {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1},
+       {0x0041, 0x00c2}, {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058},
+       {0x0041, 0x0000}, {0x0061, 0x0000},
+};
+
+static struct validx tbl_common[] = {
+       {0x6000, 0x00ff}, {0x60ff, 0x002c}, {0x60df, 0x002e}, {0x6001, 0x00ff},
+       {0x6080, 0x0012}, {0x6000, 0x0000}, {0x6000, 0x0045}, {0x6000, 0x0010},
+       {0x6035, 0x003c}, {0x6000, 0x0011}, {0x6028, 0x0004}, {0x60e5, 0x0013},
+       {0x6088, 0x0014}, {0x600c, 0x002c}, {0x6078, 0x0033}, {0x60f7, 0x003b},
+       {0x6000, 0x003e}, {0x6011, 0x0043}, {0x6010, 0x0016}, {0x6082, 0x0039},
+       {0x6088, 0x0035}, {0x600a, 0x0022}, {0x6040, 0x0037}, {0x6000, 0x0023},
+       {0x60a0, 0x0034}, {0x601a, 0x0036}, {0x6002, 0x0006}, {0x60c0, 0x0007},
+       {0x60b7, 0x000d}, {0x6001, 0x000e}, {0x6000, 0x004c}, {0x6081, 0x004a},
+       {0x6099, 0x0021}, {0x6002, 0x0009}, {0x603e, 0x0024}, {0x6034, 0x0025},
+       {0x6081, 0x0026}, {0x6000, 0x0000}, {0x6000, 0x0045}, {0x6000, 0x0010},
+       {0x6000, 0x005c}, {0x6000, 0x0063}, {0x6000, 0x007c}, {0x6070, 0x0061},
+       {0x6080, 0x0062}, {0x6080, 0x0020}, {0x6030, 0x0028}, {0x6000, 0x006c},
+       {0x6000, 0x006e}, {0x6002, 0x0070}, {0x6094, 0x0071}, {0x60c1, 0x0073},
+       {0x6034, 0x003d}, {0x6057, 0x005a}, {0x60bb, 0x004f}, {0x609c, 0x0050},
+       {0x6080, 0x006d}, {0x6002, 0x0039}, {0x6033, 0x003a}, {0x60f1, 0x003b},
+       {0x6031, 0x003c}, {0x6000, 0x00ff}, {0x6014, 0x00e0}, {0x60ff, 0x0076},
+       {0x60a0, 0x0033}, {0x6020, 0x0042}, {0x6018, 0x0043}, {0x6000, 0x004c},
+       {0x60d0, 0x0087}, {0x600f, 0x0088}, {0x6003, 0x00d7}, {0x6010, 0x00d9},
+       {0x6005, 0x00da}, {0x6082, 0x00d3}, {0x60c0, 0x00f9}, {0x6006, 0x0044},
+       {0x6007, 0x00d1}, {0x6002, 0x00d2}, {0x6000, 0x00d2}, {0x6011, 0x00d8},
+       {0x6008, 0x00c8}, {0x6080, 0x00c9}, {0x6008, 0x007c}, {0x6020, 0x007d},
+       {0x6020, 0x007d}, {0x6000, 0x0090}, {0x600e, 0x0091}, {0x601a, 0x0091},
+       {0x6031, 0x0091}, {0x605a, 0x0091}, {0x6069, 0x0091}, {0x6075, 0x0091},
+       {0x607e, 0x0091}, {0x6088, 0x0091}, {0x608f, 0x0091}, {0x6096, 0x0091},
+       {0x60a3, 0x0091}, {0x60af, 0x0091}, {0x60c4, 0x0091}, {0x60d7, 0x0091},
+       {0x60e8, 0x0091}, {0x6020, 0x0091}, {0x6000, 0x0092}, {0x6006, 0x0093},
+       {0x60e3, 0x0093}, {0x6005, 0x0093}, {0x6005, 0x0093}, {0x6000, 0x0093},
+       {0x6004, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093},
+       {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093},
+       {0x6000, 0x0096}, {0x6008, 0x0097}, {0x6019, 0x0097}, {0x6002, 0x0097},
+       {0x600c, 0x0097}, {0x6024, 0x0097}, {0x6030, 0x0097}, {0x6028, 0x0097},
+       {0x6026, 0x0097}, {0x6002, 0x0097}, {0x6098, 0x0097}, {0x6080, 0x0097},
+       {0x6000, 0x0097}, {0x6000, 0x0097}, {0x60ed, 0x00c3}, {0x609a, 0x00c4},
+       {0x6000, 0x00a4}, {0x6011, 0x00c5}, {0x6051, 0x00c6}, {0x6010, 0x00c7},
+       {0x6066, 0x00b6}, {0x60a5, 0x00b8}, {0x6064, 0x00b7}, {0x607c, 0x00b9},
+       {0x60af, 0x00b3}, {0x6097, 0x00b4}, {0x60ff, 0x00b5}, {0x60c5, 0x00b0},
+       {0x6094, 0x00b1}, {0x600f, 0x00b2}, {0x605c, 0x00c4}, {0x6000, 0x00a8},
+       {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x601d, 0x0086}, {0x6000, 0x0050},
+       {0x6090, 0x0051}, {0x6018, 0x0052}, {0x6000, 0x0053}, {0x6000, 0x0054},
+       {0x6088, 0x0055}, {0x6000, 0x0057}, {0x6090, 0x005a}, {0x6018, 0x005b},
+       {0x6005, 0x005c}, {0x60ed, 0x00c3}, {0x6000, 0x007f}, {0x6005, 0x00da},
+       {0x601f, 0x00e5}, {0x6067, 0x00e1}, {0x6000, 0x00e0}, {0x60ff, 0x00dd},
+       {0x6000, 0x0005}, {0x6001, 0x00ff}, {0x6000, 0x0000}, {0x6000, 0x0045},
+       {0x6000, 0x0010},
+};
+
+static struct validx tbl_sensor_settings_common1[] = {
+       {0x0041, 0x0000}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a, 0x000d},
+       {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, {0x0041, 0x00c2},
+       {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, {0x0041, 0x0000},
+       {50, 0xffff},
+       {0x0061, 0x0000},
+       {0xffff, 0xffff},
+       {0x6000, 0x00ff}, {0x6000, 0x007c}, {0x6007, 0x007d},
+       {30, 0xffff},
+       {0x0040, 0x0000},
+};
+
+static struct validx tbl_sensor_settings_common2[] = {
+       {0x6001, 0x00ff}, {0x6038, 0x000c},
+       {10, 0xffff},
+       {0x6000, 0x0011},
+};
+
+static struct validx tbl_640[] = {
+       {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, {0x6067, 0x00e1},
+       {0x6004, 0x00da}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0},
+       {0x6001, 0x00ff}, {0x6000, 0x0012}, {0x6000, 0x0011}, {0x6011, 0x0017},
+       {0x6075, 0x0018}, {0x6001, 0x0019}, {0x6097, 0x001a}, {0x6036, 0x0032},
+       {0x60bb, 0x004f}, {0x6057, 0x005a}, {0x609c, 0x0050}, {0x6080, 0x006d},
+       {0x6092, 0x0026}, {0x60ff, 0x0020}, {0x6000, 0x0027}, {0x6000, 0x00ff},
+       {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x6000, 0x008c}, {0x603d, 0x0086},
+       {0x6089, 0x0050}, {0x6090, 0x0051}, {0x602c, 0x0052}, {0x6000, 0x0053},
+       {0x6000, 0x0054}, {0x6088, 0x0055}, {0x6000, 0x0057}, {0x60a0, 0x005a},
+       {0x6078, 0x005b}, {0x6000, 0x005c}, {0x6004, 0x00d3}, {0x6000, 0x00e0},
+       {0x60ff, 0x00dd}, {0x60a1, 0x005a},
+};
+
+static struct validx tbl_800[] = {
+       {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, {0x6067, 0x00e1},
+       {0x6004, 0x00da}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0},
+       {0x6001, 0x00ff}, {0x6040, 0x0012}, {0x6000, 0x0011}, {0x6011, 0x0017},
+       {0x6043, 0x0018}, {0x6000, 0x0019}, {0x604b, 0x001a}, {0x6009, 0x0032},
+       {0x60ca, 0x004f}, {0x60a8, 0x0050}, {0x6000, 0x006d}, {0x6038, 0x003d},
+       {0x60c8, 0x0035}, {0x6000, 0x0022}, {0x6092, 0x0026}, {0x60ff, 0x0020},
+       {0x6000, 0x0027}, {0x6000, 0x00ff}, {0x6064, 0x00c0}, {0x604b, 0x00c1},
+       {0x6000, 0x008c}, {0x601d, 0x0086}, {0x6082, 0x00d3}, {0x6000, 0x00e0},
+       {0x60ff, 0x00dd}, {0x6020, 0x008c}, {0x6001, 0x00ff}, {0x6044, 0x0018},
+};
+
+static struct validx tbl_big1[] = {
+       {0x0002, 0x00c1}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0},
+       {0x6001, 0x00ff}, {0x6000, 0x0012}, {0x6000, 0x0000}, {0x6000, 0x0045},
+       {0x6000, 0x0010}, {0x6000, 0x0011}, {0x6011, 0x0017}, {0x6075, 0x0018},
+       {0x6001, 0x0019}, {0x6097, 0x001a}, {0x6036, 0x0032}, {0x60bb, 0x004f},
+       {0x609c, 0x0050}, {0x6057, 0x005a}, {0x6080, 0x006d}, {0x6043, 0x000f},
+       {0x608f, 0x0003}, {0x6005, 0x007c}, {0x6081, 0x0026}, {0x6000, 0x00ff},
+       {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x6000, 0x008c},
+};
+
+static struct validx tbl_big2[] = {
+       {0x603d, 0x0086}, {0x6000, 0x0050}, {0x6090, 0x0051}, {0x602c, 0x0052},
+       {0x6000, 0x0053}, {0x6000, 0x0054}, {0x6088, 0x0055}, {0x6000, 0x0057},
+       {0x6040, 0x005a}, {0x60f0, 0x005b}, {0x6001, 0x005c}, {0x6082, 0x00d3},
+       {0x6000, 0x008e},
+};
+
+static struct validx tbl_big3[] = {
+       {0x6004, 0x00da}, {0x6000, 0x00e0}, {0x6067, 0x00e1}, {0x60ff, 0x00dd},
+       {0x6001, 0x00ff}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0},
+       {0x6001, 0x00ff}, {0x6000, 0x0011}, {0x6000, 0x00ff}, {0x6010, 0x00c7},
+       {0x6000, 0x0092}, {0x6006, 0x0093}, {0x60e3, 0x0093}, {0x6005, 0x0093},
+       {0x6005, 0x0093}, {0x60ed, 0x00c3}, {0x6000, 0x00a4}, {0x60d0, 0x0087},
+       {0x6003, 0x0096}, {0x600c, 0x0097}, {0x6024, 0x0097}, {0x6030, 0x0097},
+       {0x6028, 0x0097}, {0x6026, 0x0097}, {0x6002, 0x0097}, {0x6001, 0x00ff},
+       {0x6043, 0x000f}, {0x608f, 0x0003}, {0x6000, 0x002d}, {0x6000, 0x002e},
+       {0x600a, 0x0022}, {0x6002, 0x0070}, {0x6008, 0x0014}, {0x6048, 0x0014},
+       {0x6000, 0x00ff}, {0x6000, 0x00e0}, {0x60ff, 0x00dd},
+};
+
+static struct validx tbl_post_unset_alt[] = {
+       {0x006a, 0x000d}, {0x6001, 0x00ff}, {0x6081, 0x0026}, {0x6000, 0x0000},
+       {0x6000, 0x0045}, {0x6000, 0x0010}, {0x6068, 0x000d},
+       {50, 0xffff},
+       {0x0021, 0x0000},
+};
+
+static int  ov2640_init_at_startup(struct gspca_dev *gspca_dev);
+static int  ov2640_configure_alt(struct gspca_dev *gspca_dev);
+static int  ov2640_init_pre_alt(struct gspca_dev *gspca_dev);
+static int  ov2640_init_post_alt(struct gspca_dev *gspca_dev);
+static void ov2640_post_unset_alt(struct gspca_dev *gspca_dev);
+static int  ov2640_camera_settings(struct gspca_dev *gspca_dev);
+/*==========================================================================*/
+
+void ov2640_init_settings(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->vcur.backlight  =  32;
+       sd->vcur.brightness =   0;
+       sd->vcur.sharpness  =   6;
+       sd->vcur.contrast   =   0;
+       sd->vcur.gamma      =  32;
+       sd->vcur.hue        =   0;
+       sd->vcur.saturation = 128;
+       sd->vcur.whitebal   =  64;
+       sd->vcur.mirror     =   0;
+       sd->vcur.flip       =   0;
+
+       sd->vmax.backlight  =  64;
+       sd->vmax.brightness = 255;
+       sd->vmax.sharpness  =  31;
+       sd->vmax.contrast   = 255;
+       sd->vmax.gamma      =  64;
+       sd->vmax.hue        = 254 + 2;
+       sd->vmax.saturation = 255;
+       sd->vmax.whitebal   = 128;
+       sd->vmax.mirror     = 1;
+       sd->vmax.flip       = 1;
+       sd->vmax.AC50Hz     = 0;
+
+       sd->dev_camera_settings = ov2640_camera_settings;
+       sd->dev_init_at_startup = ov2640_init_at_startup;
+       sd->dev_configure_alt   = ov2640_configure_alt;
+       sd->dev_init_pre_alt    = ov2640_init_pre_alt;
+       sd->dev_post_unset_alt  = ov2640_post_unset_alt;
+}
+
+/*==========================================================================*/
+
+static void common(struct gspca_dev *gspca_dev)
+{
+       fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common));
+}
+
+static int ov2640_init_at_startup(struct gspca_dev *gspca_dev)
+{
+       fetch_validx(gspca_dev, tbl_init_at_startup,
+                       ARRAY_SIZE(tbl_init_at_startup));
+
+       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_init1);
+
+       common(gspca_dev);
+
+       ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0006, 1, c61);
+
+       ctrl_out(gspca_dev, 0x40, 1, 0x00ef, 0x0006, 0, NULL);
+
+       ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c51);
+
+       ctrl_out(gspca_dev, 0x40, 1, 0x0051, 0x0000, 0, NULL);
+/*     ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */
+
+       return 0;
+}
+
+static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->mirrorMask = 0;
+
+       sd->vold.backlight  = -1;
+       sd->vold.brightness = -1;
+       sd->vold.sharpness  = -1;
+       sd->vold.contrast   = -1;
+       sd->vold.saturation = -1;
+       sd->vold.gamma    = -1;
+       sd->vold.hue      = -1;
+       sd->vold.whitebal = -1;
+       sd->vold.mirror = -1;
+       sd->vold.flip   = -1;
+
+       ov2640_init_post_alt(gspca_dev);
+
+       return 0;
+}
+
+static int ov2640_init_post_alt(struct gspca_dev *gspca_dev)
+{
+       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
+       s32 n; /* reserved for FETCH functions */
+
+       ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
+
+       n = fetch_validx(gspca_dev, tbl_sensor_settings_common1,
+                       ARRAY_SIZE(tbl_sensor_settings_common1));
+       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_post);
+       common(gspca_dev);
+       keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common1,
+                               ARRAY_SIZE(tbl_sensor_settings_common1), n);
+
+       switch (reso) {
+       case IMAGE_640:
+               n = fetch_validx(gspca_dev, tbl_640, ARRAY_SIZE(tbl_640));
+               ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_640);
+               break;
+
+       case IMAGE_800:
+               n = fetch_validx(gspca_dev, tbl_800, ARRAY_SIZE(tbl_800));
+               ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_800);
+               break;
+
+       case IMAGE_1600:
+       case IMAGE_1280:
+               n = fetch_validx(gspca_dev, tbl_big1, ARRAY_SIZE(tbl_big1));
+
+               if (reso == IMAGE_1280) {
+                       n = fetch_validx(gspca_dev, tbl_big2,
+                                       ARRAY_SIZE(tbl_big2));
+               } else {
+                       ctrl_out(gspca_dev, 0x40, 1, 0x601d, 0x0086, 0, NULL);
+                       ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00d7, 0, NULL);
+                       ctrl_out(gspca_dev, 0x40, 1, 0x6082, 0x00d3, 0, NULL);
+               }
+
+               n = fetch_validx(gspca_dev, tbl_big3, ARRAY_SIZE(tbl_big3));
+
+               if (reso == IMAGE_1280) {
+                       ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL);
+                       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
+                                       12, dat_1280);
+               } else {
+                       ctrl_out(gspca_dev, 0x40, 1, 0x6020, 0x008c, 0, NULL);
+                       ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL);
+                       ctrl_out(gspca_dev, 0x40, 1, 0x6076, 0x0018, 0, NULL);
+                       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
+                                       12, dat_1600);
+               }
+               break;
+       }
+
+       n = fetch_validx(gspca_dev, tbl_sensor_settings_common2,
+                       ARRAY_SIZE(tbl_sensor_settings_common2));
+
+       ov2640_camera_settings(gspca_dev);
+
+       return 0;
+}
+
+static int ov2640_configure_alt(struct gspca_dev *gspca_dev)
+{
+       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
+
+       switch (reso) {
+       case IMAGE_640:
+               gspca_dev->alt = 3 + 1;
+               break;
+
+       case IMAGE_800:
+       case IMAGE_1280:
+       case IMAGE_1600:
+               gspca_dev->alt = 1 + 1;
+               break;
+       }
+       return 0;
+}
+
+static int ov2640_camera_settings(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       s32 backlight = sd->vcur.backlight;
+       s32 bright = sd->vcur.brightness;
+       s32 sharp  = sd->vcur.sharpness;
+       s32 gam    = sd->vcur.gamma;
+       s32 cntr   = sd->vcur.contrast;
+       s32 sat    = sd->vcur.saturation;
+       s32 hue    = sd->vcur.hue;
+       s32 wbal   = sd->vcur.whitebal;
+       s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) == 0);
+       s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) == 0);
+
+       if (backlight != sd->vold.backlight) {
+               /* No sd->vold.backlight=backlight; (to be done again later) */
+               if (backlight < 0 || backlight > sd->vmax.backlight)
+                       backlight = 0;
+
+               ctrl_out(gspca_dev, 0x40, 1, 0x6001                 , 0x00ff,
+                               0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight     , 0x0024,
+                               0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025,
+                               0, NULL);
+       }
+
+       if (bright != sd->vold.brightness) {
+               sd->vold.brightness = bright;
+               if (bright < 0 || bright > sd->vmax.brightness)
+                       bright = 0;
+
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000         , 0x00ff, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6009         , 0x007c, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000 + bright, 0x007d, 0, NULL);
+       }
+
+       if (wbal != sd->vold.whitebal) {
+               sd->vold.whitebal = wbal;
+               if (wbal < 0 || wbal > sd->vmax.whitebal)
+                       wbal = 0;
+
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000       , 0x00ff, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6003       , 0x007c, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000 + wbal, 0x007d, 0, NULL);
+       }
+
+       if (cntr != sd->vold.contrast) {
+               sd->vold.contrast = cntr;
+               if (cntr < 0 || cntr > sd->vmax.contrast)
+                       cntr = 0;
+
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000       , 0x00ff, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6007       , 0x007c, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000 + cntr, 0x007d, 0, NULL);
+       }
+
+       if (sat != sd->vold.saturation) {
+               sd->vold.saturation = sat;
+               if (sat < 0 || sat > sd->vmax.saturation)
+                       sat = 0;
+
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000      , 0x00ff, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6001      , 0x007c, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000 + sat, 0x007d, 0, NULL);
+       }
+
+       if (sharp != sd->vold.sharpness) {
+               sd->vold.sharpness = sharp;
+               if (sharp < 0 || sharp > sd->vmax.sharpness)
+                       sharp = 0;
+
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000        , 0x00ff, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6001        , 0x0092, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x60c0 + sharp, 0x0093, 0, NULL);
+       }
+
+       if (hue != sd->vold.hue) {
+               sd->vold.hue = hue;
+               if (hue < 0 || hue > sd->vmax.hue)
+                       hue = 0;
+
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000     , 0x00ff, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6002     , 0x007c, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000 + hue * (hue < 255), 0x007d,
+                               0, NULL);
+               if (hue >= 255)
+                       sd->swapRB = 1;
+               else
+                       sd->swapRB = 0;
+       }
+
+       if (gam != sd->vold.gamma) {
+               sd->vold.gamma = gam;
+               if (gam < 0 || gam > sd->vmax.gamma)
+                       gam = 0;
+
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000      , 0x00ff, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6008      , 0x007c, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000 + gam, 0x007d, 0, NULL);
+       }
+
+       if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
+               sd->vold.mirror = mirror;
+               sd->vold.flip   = flip;
+
+               mirror = 0x80 * mirror;
+               ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL);
+               ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, c28);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6028 + mirror, 0x0004, 0, NULL);
+
+               flip = 0x50 * flip + mirror;
+               ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL);
+               ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, ca8);
+               ctrl_out(gspca_dev, 0x40, 1, 0x6028 + flip, 0x0004, 0, NULL);
+
+               ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50);
+       }
+
+       if (backlight != sd->vold.backlight) {
+               sd->vold.backlight = backlight;
+
+               ctrl_out(gspca_dev, 0x40, 1, 0x6001                 , 0x00ff,
+                               0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight     , 0x0024,
+                               0, NULL);
+               ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025,
+                               0, NULL);
+       }
+
+       return 0;
+}
+
+static void ov2640_post_unset_alt(struct gspca_dev *gspca_dev)
+{
+       ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
+       msleep(20);
+       fetch_validx(gspca_dev, tbl_post_unset_alt,
+                       ARRAY_SIZE(tbl_post_unset_alt));
+}
diff --git a/drivers/media/usb/gspca/gl860/gl860-ov9655.c b/drivers/media/usb/gspca/gl860/gl860-ov9655.c
new file mode 100644 (file)
index 0000000..5ae9619
--- /dev/null
@@ -0,0 +1,336 @@
+/* Subdriver for the GL860 chip with the OV9655 sensor
+ * Author Olivier LORIN, from logs done by Simon (Sur3) and Almighurt
+ * on dsd's weblog
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Sensor : OV9655 */
+
+#include "gl860.h"
+
+static struct validx tbl_init_at_startup[] = {
+       {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1},
+       {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d},
+
+       {0x0040, 0x0000},
+};
+
+static struct validx tbl_commmon[] = {
+       {0x0041, 0x0000}, {0x006a, 0x0007}, {0x0063, 0x0006}, {0x006a, 0x000d},
+       {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, {0x0041, 0x00c2},
+       {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, {0x0040, 0x0000},
+       {0x00f3, 0x0006}, {0x0058, 0x0000}, {0x0048, 0x0000}, {0x0061, 0x0000},
+};
+
+static s32 tbl_length[] = {12, 56, 52, 54, 56, 42, 32, 12};
+
+static u8 *tbl_640[] = {
+       "\x00\x40\x07\x6a\x06\xf3\x0d\x6a" "\x10\x10\xc1\x01"
+       ,
+       "\x12\x80\x00\x00\x01\x98\x02\x80" "\x03\x12\x04\x03\x0b\x57\x0e\x61"
+       "\x0f\x42\x11\x01\x12\x60\x13\x00" "\x14\x3a\x16\x24\x17\x14\x18\x00"
+       "\x19\x01\x1a\x3d\x1e\x04\x24\x3c" "\x25\x36\x26\x72\x27\x08\x28\x08"
+       "\x29\x15\x2a\x00\x2b\x00\x2c\x08"
+       ,
+       "\x32\xff\x33\x00\x34\x3d\x35\x00" "\x36\xfa\x38\x72\x39\x57\x3a\x00"
+       "\x3b\x0c\x3d\x99\x3e\x0c\x3f\xc1" "\x40\xc0\x41\x00\x42\xc0\x43\x0a"
+       "\x44\xf0\x45\x46\x46\x62\x47\x2a" "\x48\x3c\x4a\xee\x4b\xe7\x4c\xe7"
+       "\x4d\xe7\x4e\xe7"
+       ,
+       "\x4f\x98\x50\x98\x51\x00\x52\x28" "\x53\x70\x54\x98\x58\x1a\x59\x85"
+       "\x5a\xa9\x5b\x64\x5c\x84\x5d\x53" "\x5e\x0e\x5f\xf0\x60\xf0\x61\xf0"
+       "\x62\x00\x63\x00\x64\x02\x65\x20" "\x66\x00\x69\x0a\x6b\x5a\x6c\x04"
+       "\x6d\x55\x6e\x00\x6f\x9d"
+       ,
+       "\x70\x15\x71\x78\x72\x00\x73\x00" "\x74\x3a\x75\x35\x76\x01\x77\x02"
+       "\x7a\x24\x7b\x04\x7c\x07\x7d\x10" "\x7e\x28\x7f\x36\x80\x44\x81\x52"
+       "\x82\x60\x83\x6c\x84\x78\x85\x8c" "\x86\x9e\x87\xbb\x88\xd2\x89\xe5"
+       "\x8a\x23\x8c\x8d\x90\x7c\x91\x7b"
+       ,
+       "\x9d\x02\x9e\x02\x9f\x74\xa0\x73" "\xa1\x40\xa4\x50\xa5\x68\xa6\x70"
+       "\xa8\xc1\xa9\xef\xaa\x92\xab\x04" "\xac\x80\xad\x80\xae\x80\xaf\x80"
+       "\xb2\xf2\xb3\x20\xb4\x20\xb5\x00" "\xb6\xaf"
+       ,
+       "\xbb\xae\xbc\x4f\xbd\x4e\xbe\x6a" "\xbf\x68\xc0\xaa\xc1\xc0\xc2\x01"
+       "\xc3\x4e\xc6\x85\xc7\x81\xc9\xe0" "\xca\xe8\xcb\xf0\xcc\xd8\xcd\x93"
+       ,
+       "\xd0\x01\xd1\x08\xd2\xe0\xd3\x01" "\xd4\x10\xd5\x80"
+};
+
+static u8 *tbl_1280[] = {
+       "\x00\x40\x07\x6a\x06\xf3\x0d\x6a" "\x10\x10\xc1\x01"
+       ,
+       "\x12\x80\x00\x00\x01\x98\x02\x80" "\x03\x12\x04\x01\x0b\x57\x0e\x61"
+       "\x0f\x42\x11\x00\x12\x00\x13\x00" "\x14\x3a\x16\x24\x17\x1b\x18\xbb"
+       "\x19\x01\x1a\x81\x1e\x04\x24\x3c" "\x25\x36\x26\x72\x27\x08\x28\x08"
+       "\x29\x15\x2a\x00\x2b\x00\x2c\x08"
+       ,
+       "\x32\xa4\x33\x00\x34\x3d\x35\x00" "\x36\xf8\x38\x72\x39\x57\x3a\x00"
+       "\x3b\x0c\x3d\x99\x3e\x0c\x3f\xc2" "\x40\xc0\x41\x00\x42\xc0\x43\x0a"
+       "\x44\xf0\x45\x46\x46\x62\x47\x2a" "\x48\x3c\x4a\xec\x4b\xe8\x4c\xe8"
+       "\x4d\xe8\x4e\xe8"
+       ,
+       "\x4f\x98\x50\x98\x51\x00\x52\x28" "\x53\x70\x54\x98\x58\x1a\x59\x85"
+       "\x5a\xa9\x5b\x64\x5c\x84\x5d\x53" "\x5e\x0e\x5f\xf0\x60\xf0\x61\xf0"
+       "\x62\x00\x63\x00\x64\x02\x65\x20" "\x66\x00\x69\x02\x6b\x5a\x6c\x04"
+       "\x6d\x55\x6e\x00\x6f\x9d"
+       ,
+       "\x70\x08\x71\x78\x72\x00\x73\x01" "\x74\x3a\x75\x35\x76\x01\x77\x02"
+       "\x7a\x24\x7b\x04\x7c\x07\x7d\x10" "\x7e\x28\x7f\x36\x80\x44\x81\x52"
+       "\x82\x60\x83\x6c\x84\x78\x85\x8c" "\x86\x9e\x87\xbb\x88\xd2\x89\xe5"
+       "\x8a\x23\x8c\x0d\x90\x90\x91\x90"
+       ,
+       "\x9d\x02\x9e\x02\x9f\x94\xa0\x94" "\xa1\x01\xa4\x50\xa5\x68\xa6\x70"
+       "\xa8\xc1\xa9\xef\xaa\x92\xab\x04" "\xac\x80\xad\x80\xae\x80\xaf\x80"
+       "\xb2\xf2\xb3\x20\xb4\x20\xb5\x00" "\xb6\xaf"
+       ,
+       "\xbb\xae\xbc\x38\xbd\x39\xbe\x01" "\xbf\x01\xc0\xe2\xc1\xc0\xc2\x01"
+       "\xc3\x4e\xc6\x85\xc7\x81\xc9\xe0" "\xca\xe8\xcb\xf0\xcc\xd8\xcd\x93"
+       ,
+       "\xd0\x21\xd1\x18\xd2\xe0\xd3\x01" "\xd4\x28\xd5\x00"
+};
+
+static u8 c04[] = {0x04};
+static u8 dat_post1[] = "\x04\x00\x10\x20\xa1\x00\x00\x02";
+static u8 dat_post2[] = "\x10\x10\xc1\x02";
+static u8 dat_post3[] = "\x04\x00\x10\x7c\xa1\x00\x00\x04";
+static u8 dat_post4[] = "\x10\x02\xc1\x06";
+static u8 dat_post5[] = "\x04\x00\x10\x7b\xa1\x00\x00\x08";
+static u8 dat_post6[] = "\x10\x10\xc1\x05";
+static u8 dat_post7[] = "\x04\x00\x10\x7c\xa1\x00\x00\x08";
+static u8 dat_post8[] = "\x04\x00\x10\x7c\xa1\x00\x00\x09";
+
+static struct validx tbl_init_post_alt[] = {
+       {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x603c, 0x00ff},
+       {0x6003, 0x00ff}, {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x6001, 0x00ff},
+       {0x6000, 0x801e},
+       {0xffff, 0xffff},
+       {0x6004, 0x001e}, {0x6000, 0x801e},
+       {0xffff, 0xffff},
+       {0x6004, 0x001e}, {0x6012, 0x0003}, {0x6000, 0x801e},
+       {0xffff, 0xffff},
+       {0x6004, 0x001e}, {0x6000, 0x801e},
+       {0xffff, 0xffff},
+       {0x6004, 0x001e}, {0x6012, 0x0003},
+       {0xffff, 0xffff},
+       {0x6000, 0x801e},
+       {0xffff, 0xffff},
+       {0x6004, 0x001e}, {0x6000, 0x801e},
+       {0xffff, 0xffff},
+       {0x6004, 0x001e}, {0x6012, 0x0003}, {0x6000, 0x801e},
+       {0xffff, 0xffff},
+       {0x6004, 0x001e}, {0x6000, 0x801e},
+       {0xffff, 0xffff},
+       {0x6004, 0x001e}, {0x6012, 0x0003},
+       {0xffff, 0xffff},
+       {0x6000, 0x801e},
+       {0xffff, 0xffff},
+       {0x6004, 0x001e}, {0x6000, 0x801e},
+       {0xffff, 0xffff},
+       {0x6004, 0x001e}, {0x6012, 0x0003},
+};
+
+static int  ov9655_init_at_startup(struct gspca_dev *gspca_dev);
+static int  ov9655_configure_alt(struct gspca_dev *gspca_dev);
+static int  ov9655_init_pre_alt(struct gspca_dev *gspca_dev);
+static int  ov9655_init_post_alt(struct gspca_dev *gspca_dev);
+static void ov9655_post_unset_alt(struct gspca_dev *gspca_dev);
+static int  ov9655_camera_settings(struct gspca_dev *gspca_dev);
+/*==========================================================================*/
+
+void ov9655_init_settings(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->vcur.backlight  =   0;
+       sd->vcur.brightness = 128;
+       sd->vcur.sharpness  =   0;
+       sd->vcur.contrast   =   0;
+       sd->vcur.gamma      =   0;
+       sd->vcur.hue        =   0;
+       sd->vcur.saturation =   0;
+       sd->vcur.whitebal   =   0;
+
+       sd->vmax.backlight  =   0;
+       sd->vmax.brightness = 255;
+       sd->vmax.sharpness  =   0;
+       sd->vmax.contrast   =   0;
+       sd->vmax.gamma      =   0;
+       sd->vmax.hue        =   0 + 1;
+       sd->vmax.saturation =   0;
+       sd->vmax.whitebal   =   0;
+       sd->vmax.mirror     = 0;
+       sd->vmax.flip       = 0;
+       sd->vmax.AC50Hz     = 0;
+
+       sd->dev_camera_settings = ov9655_camera_settings;
+       sd->dev_init_at_startup = ov9655_init_at_startup;
+       sd->dev_configure_alt   = ov9655_configure_alt;
+       sd->dev_init_pre_alt    = ov9655_init_pre_alt;
+       sd->dev_post_unset_alt  = ov9655_post_unset_alt;
+}
+
+/*==========================================================================*/
+
+static int ov9655_init_at_startup(struct gspca_dev *gspca_dev)
+{
+       fetch_validx(gspca_dev, tbl_init_at_startup,
+                       ARRAY_SIZE(tbl_init_at_startup));
+       fetch_validx(gspca_dev, tbl_commmon, ARRAY_SIZE(tbl_commmon));
+/*     ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL);*/
+
+       return 0;
+}
+
+static int ov9655_init_pre_alt(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->vold.brightness = -1;
+       sd->vold.hue = -1;
+
+       fetch_validx(gspca_dev, tbl_commmon, ARRAY_SIZE(tbl_commmon));
+
+       ov9655_init_post_alt(gspca_dev);
+
+       return 0;
+}
+
+static int ov9655_init_post_alt(struct gspca_dev *gspca_dev)
+{
+       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
+       s32 n; /* reserved for FETCH functions */
+       s32 i;
+       u8 **tbl;
+
+       ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
+
+       tbl = (reso == IMAGE_640) ? tbl_640 : tbl_1280;
+
+       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
+                       tbl_length[0], tbl[0]);
+       for (i = 1; i < 7; i++)
+               ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200,
+                               tbl_length[i], tbl[i]);
+       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
+                       tbl_length[7], tbl[7]);
+
+       n = fetch_validx(gspca_dev, tbl_init_post_alt,
+                       ARRAY_SIZE(tbl_init_post_alt));
+
+       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
+       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
+                                       ARRAY_SIZE(tbl_init_post_alt), n);
+       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
+       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
+                                       ARRAY_SIZE(tbl_init_post_alt), n);
+       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
+       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
+                                       ARRAY_SIZE(tbl_init_post_alt), n);
+       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
+       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
+                                       ARRAY_SIZE(tbl_init_post_alt), n);
+       ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1);
+       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
+                                       ARRAY_SIZE(tbl_init_post_alt), n);
+
+       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
+       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
+                                       ARRAY_SIZE(tbl_init_post_alt), n);
+       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
+       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
+                                       ARRAY_SIZE(tbl_init_post_alt), n);
+       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
+       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
+                                       ARRAY_SIZE(tbl_init_post_alt), n);
+       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
+       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
+                                       ARRAY_SIZE(tbl_init_post_alt), n);
+       ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1);
+       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
+                                       ARRAY_SIZE(tbl_init_post_alt), n);
+
+       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
+       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
+                                       ARRAY_SIZE(tbl_init_post_alt), n);
+       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
+       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
+                                       ARRAY_SIZE(tbl_init_post_alt), n);
+
+       ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1);
+
+       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post2);
+       ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post3);
+
+       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post4);
+       ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post5);
+
+       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post6);
+       ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post7);
+
+       ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post8);
+
+       ov9655_camera_settings(gspca_dev);
+
+       return 0;
+}
+
+static int ov9655_configure_alt(struct gspca_dev *gspca_dev)
+{
+       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
+
+       switch (reso) {
+       case IMAGE_640:
+               gspca_dev->alt = 1 + 1;
+               break;
+
+       default:
+               gspca_dev->alt = 1 + 1;
+               break;
+       }
+       return 0;
+}
+
+static int ov9655_camera_settings(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       u8 dat_bright[] = "\x04\x00\x10\x7c\xa1\x00\x00\x70";
+
+       s32 bright = sd->vcur.brightness;
+       s32 hue    = sd->vcur.hue;
+
+       if (bright != sd->vold.brightness) {
+               sd->vold.brightness = bright;
+               if (bright < 0 || bright > sd->vmax.brightness)
+                       bright = 0;
+
+               dat_bright[3] = bright;
+               ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_bright);
+       }
+
+       if (hue != sd->vold.hue) {
+               sd->vold.hue = hue;
+               sd->swapRB = (hue != 0);
+       }
+
+       return 0;
+}
+
+static void ov9655_post_unset_alt(struct gspca_dev *gspca_dev)
+{
+       ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
+       ctrl_out(gspca_dev, 0x40, 1, 0x0061, 0x0000, 0, NULL);
+}
diff --git a/drivers/media/usb/gspca/gl860/gl860.c b/drivers/media/usb/gspca/gl860/gl860.c
new file mode 100644 (file)
index 0000000..ced3b71
--- /dev/null
@@ -0,0 +1,725 @@
+/* GSPCA subdrivers for Genesys Logic webcams with the GL860 chip
+ * Subdriver core
+ *
+ * 2009/09/24 Olivier Lorin <o.lorin@laposte.net>
+ * GSPCA by Jean-Francois Moine <http://moinejf.free.fr>
+ * Thanks BUGabundo and Malmostoso for your amazing help!
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "gspca.h"
+#include "gl860.h"
+
+MODULE_AUTHOR("Olivier Lorin <o.lorin@laposte.net>");
+MODULE_DESCRIPTION("Genesys Logic USB PC Camera Driver");
+MODULE_LICENSE("GPL");
+
+/*======================== static function declarations ====================*/
+
+static void (*dev_init_settings)(struct gspca_dev *gspca_dev);
+
+static int  sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id);
+static int  sd_init(struct gspca_dev *gspca_dev);
+static int  sd_isoc_init(struct gspca_dev *gspca_dev);
+static int  sd_start(struct gspca_dev *gspca_dev);
+static void sd_stop0(struct gspca_dev *gspca_dev);
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data, int len);
+static void sd_callback(struct gspca_dev *gspca_dev);
+
+static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
+                               u16 vendor_id, u16 product_id);
+
+/*============================ driver options ==============================*/
+
+static s32 AC50Hz = 0xff;
+module_param(AC50Hz, int, 0644);
+MODULE_PARM_DESC(AC50Hz, " Does AC power frequency is 50Hz? (0/1)");
+
+static char sensor[7];
+module_param_string(sensor, sensor, sizeof(sensor), 0644);
+MODULE_PARM_DESC(sensor,
+               " Driver sensor ('MI1320'/'MI2020'/'OV9655'/'OV2640')");
+
+/*============================ webcam controls =============================*/
+
+/* Functions to get and set a control value */
+#define SD_SETGET(thename) \
+static int sd_set_##thename(struct gspca_dev *gspca_dev, s32 val)\
+{\
+       struct sd *sd = (struct sd *) gspca_dev;\
+\
+       sd->vcur.thename = val;\
+       if (gspca_dev->streaming)\
+               sd->waitSet = 1;\
+       return 0;\
+} \
+static int sd_get_##thename(struct gspca_dev *gspca_dev, s32 *val)\
+{\
+       struct sd *sd = (struct sd *) gspca_dev;\
+\
+       *val = sd->vcur.thename;\
+       return 0;\
+}
+
+SD_SETGET(mirror)
+SD_SETGET(flip)
+SD_SETGET(AC50Hz)
+SD_SETGET(backlight)
+SD_SETGET(brightness)
+SD_SETGET(gamma)
+SD_SETGET(hue)
+SD_SETGET(saturation)
+SD_SETGET(sharpness)
+SD_SETGET(whitebal)
+SD_SETGET(contrast)
+
+#define GL860_NCTRLS 11
+
+/* control table */
+static struct ctrl sd_ctrls_mi1320[GL860_NCTRLS];
+static struct ctrl sd_ctrls_mi2020[GL860_NCTRLS];
+static struct ctrl sd_ctrls_ov2640[GL860_NCTRLS];
+static struct ctrl sd_ctrls_ov9655[GL860_NCTRLS];
+
+#define SET_MY_CTRL(theid, \
+       thetype, thelabel, thename) \
+       if (sd->vmax.thename != 0) {\
+               sd_ctrls[nCtrls].qctrl.id   = theid;\
+               sd_ctrls[nCtrls].qctrl.type = thetype;\
+               strcpy(sd_ctrls[nCtrls].qctrl.name, thelabel);\
+               sd_ctrls[nCtrls].qctrl.minimum = 0;\
+               sd_ctrls[nCtrls].qctrl.maximum = sd->vmax.thename;\
+               sd_ctrls[nCtrls].qctrl.default_value = sd->vcur.thename;\
+               sd_ctrls[nCtrls].qctrl.step = \
+                       (sd->vmax.thename < 16) ? 1 : sd->vmax.thename/16;\
+               sd_ctrls[nCtrls].set = sd_set_##thename;\
+               sd_ctrls[nCtrls].get = sd_get_##thename;\
+               nCtrls++;\
+       }
+
+static int gl860_build_control_table(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct ctrl *sd_ctrls;
+       int nCtrls = 0;
+
+       if (_MI1320_)
+               sd_ctrls = sd_ctrls_mi1320;
+       else if (_MI2020_)
+               sd_ctrls = sd_ctrls_mi2020;
+       else if (_OV2640_)
+               sd_ctrls = sd_ctrls_ov2640;
+       else if (_OV9655_)
+               sd_ctrls = sd_ctrls_ov9655;
+       else
+               return 0;
+
+       memset(sd_ctrls, 0, GL860_NCTRLS * sizeof(struct ctrl));
+
+       SET_MY_CTRL(V4L2_CID_BRIGHTNESS,
+               V4L2_CTRL_TYPE_INTEGER, "Brightness", brightness)
+       SET_MY_CTRL(V4L2_CID_SHARPNESS,
+               V4L2_CTRL_TYPE_INTEGER, "Sharpness", sharpness)
+       SET_MY_CTRL(V4L2_CID_CONTRAST,
+               V4L2_CTRL_TYPE_INTEGER, "Contrast", contrast)
+       SET_MY_CTRL(V4L2_CID_GAMMA,
+               V4L2_CTRL_TYPE_INTEGER, "Gamma", gamma)
+       SET_MY_CTRL(V4L2_CID_HUE,
+               V4L2_CTRL_TYPE_INTEGER, "Palette", hue)
+       SET_MY_CTRL(V4L2_CID_SATURATION,
+               V4L2_CTRL_TYPE_INTEGER, "Saturation", saturation)
+       SET_MY_CTRL(V4L2_CID_WHITE_BALANCE_TEMPERATURE,
+               V4L2_CTRL_TYPE_INTEGER, "White Bal.", whitebal)
+       SET_MY_CTRL(V4L2_CID_BACKLIGHT_COMPENSATION,
+               V4L2_CTRL_TYPE_INTEGER, "Backlight" , backlight)
+
+       SET_MY_CTRL(V4L2_CID_HFLIP,
+               V4L2_CTRL_TYPE_BOOLEAN, "Mirror", mirror)
+       SET_MY_CTRL(V4L2_CID_VFLIP,
+               V4L2_CTRL_TYPE_BOOLEAN, "Flip", flip)
+       SET_MY_CTRL(V4L2_CID_POWER_LINE_FREQUENCY,
+               V4L2_CTRL_TYPE_BOOLEAN, "AC power 50Hz", AC50Hz)
+
+       return nCtrls;
+}
+
+/*==================== sud-driver structure initialisation =================*/
+
+static const struct sd_desc sd_desc_mi1320 = {
+       .name        = MODULE_NAME,
+       .ctrls       = sd_ctrls_mi1320,
+       .nctrls      = GL860_NCTRLS,
+       .config      = sd_config,
+       .init        = sd_init,
+       .isoc_init   = sd_isoc_init,
+       .start       = sd_start,
+       .stop0       = sd_stop0,
+       .pkt_scan    = sd_pkt_scan,
+       .dq_callback = sd_callback,
+};
+
+static const struct sd_desc sd_desc_mi2020 = {
+       .name        = MODULE_NAME,
+       .ctrls       = sd_ctrls_mi2020,
+       .nctrls      = GL860_NCTRLS,
+       .config      = sd_config,
+       .init        = sd_init,
+       .isoc_init   = sd_isoc_init,
+       .start       = sd_start,
+       .stop0       = sd_stop0,
+       .pkt_scan    = sd_pkt_scan,
+       .dq_callback = sd_callback,
+};
+
+static const struct sd_desc sd_desc_ov2640 = {
+       .name        = MODULE_NAME,
+       .ctrls       = sd_ctrls_ov2640,
+       .nctrls      = GL860_NCTRLS,
+       .config      = sd_config,
+       .init        = sd_init,
+       .isoc_init   = sd_isoc_init,
+       .start       = sd_start,
+       .stop0       = sd_stop0,
+       .pkt_scan    = sd_pkt_scan,
+       .dq_callback = sd_callback,
+};
+
+static const struct sd_desc sd_desc_ov9655 = {
+       .name        = MODULE_NAME,
+       .ctrls       = sd_ctrls_ov9655,
+       .nctrls      = GL860_NCTRLS,
+       .config      = sd_config,
+       .init        = sd_init,
+       .isoc_init   = sd_isoc_init,
+       .start       = sd_start,
+       .stop0       = sd_stop0,
+       .pkt_scan    = sd_pkt_scan,
+       .dq_callback = sd_callback,
+};
+
+/*=========================== sub-driver image sizes =======================*/
+
+static struct v4l2_pix_format mi2020_mode[] = {
+       { 640,  480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0
+       },
+       { 800,  598, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 800,
+               .sizeimage = 800 * 598,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1
+       },
+       {1280, 1024, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 1280,
+               .sizeimage = 1280 * 1024,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2
+       },
+       {1600, 1198, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 1600,
+               .sizeimage = 1600 * 1198,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 3
+       },
+};
+
+static struct v4l2_pix_format ov2640_mode[] = {
+       { 640,  480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0
+       },
+       { 800,  600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 800,
+               .sizeimage = 800 * 600,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1
+       },
+       {1280,  960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 1280,
+               .sizeimage = 1280 * 960,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2
+       },
+       {1600, 1200, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 1600,
+               .sizeimage = 1600 * 1200,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 3
+       },
+};
+
+static struct v4l2_pix_format mi1320_mode[] = {
+       { 640,  480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0
+       },
+       { 800,  600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 800,
+               .sizeimage = 800 * 600,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1
+       },
+       {1280,  960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 1280,
+               .sizeimage = 1280 * 960,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2
+       },
+};
+
+static struct v4l2_pix_format ov9655_mode[] = {
+       { 640,  480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0
+       },
+       {1280,  960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 1280,
+               .sizeimage = 1280 * 960,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1
+       },
+};
+
+/*========================= sud-driver functions ===========================*/
+
+/* This function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+       u16 vendor_id, product_id;
+
+       /* Get USB VendorID and ProductID */
+       vendor_id  = id->idVendor;
+       product_id = id->idProduct;
+
+       sd->nbRightUp = 1;
+       sd->nbIm = -1;
+
+       sd->sensor = 0xff;
+       if (strcmp(sensor, "MI1320") == 0)
+               sd->sensor = ID_MI1320;
+       else if (strcmp(sensor, "OV2640") == 0)
+               sd->sensor = ID_OV2640;
+       else if (strcmp(sensor, "OV9655") == 0)
+               sd->sensor = ID_OV9655;
+       else if (strcmp(sensor, "MI2020") == 0)
+               sd->sensor = ID_MI2020;
+
+       /* Get sensor and set the suitable init/start/../stop functions */
+       if (gl860_guess_sensor(gspca_dev, vendor_id, product_id) == -1)
+               return -1;
+
+       cam = &gspca_dev->cam;
+
+       switch (sd->sensor) {
+       case ID_MI1320:
+               gspca_dev->sd_desc = &sd_desc_mi1320;
+               cam->cam_mode = mi1320_mode;
+               cam->nmodes = ARRAY_SIZE(mi1320_mode);
+               dev_init_settings   = mi1320_init_settings;
+               break;
+
+       case ID_MI2020:
+               gspca_dev->sd_desc = &sd_desc_mi2020;
+               cam->cam_mode = mi2020_mode;
+               cam->nmodes = ARRAY_SIZE(mi2020_mode);
+               dev_init_settings   = mi2020_init_settings;
+               break;
+
+       case ID_OV2640:
+               gspca_dev->sd_desc = &sd_desc_ov2640;
+               cam->cam_mode = ov2640_mode;
+               cam->nmodes = ARRAY_SIZE(ov2640_mode);
+               dev_init_settings   = ov2640_init_settings;
+               break;
+
+       case ID_OV9655:
+               gspca_dev->sd_desc = &sd_desc_ov9655;
+               cam->cam_mode = ov9655_mode;
+               cam->nmodes = ARRAY_SIZE(ov9655_mode);
+               dev_init_settings   = ov9655_init_settings;
+               break;
+       }
+
+       dev_init_settings(gspca_dev);
+       if (AC50Hz != 0xff)
+               ((struct sd *) gspca_dev)->vcur.AC50Hz = AC50Hz;
+       gl860_build_control_table(gspca_dev);
+
+       return 0;
+}
+
+/* This function is called at probe time after sd_config */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       return sd->dev_init_at_startup(gspca_dev);
+}
+
+/* This function is called before to choose the alt setting */
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       return sd->dev_configure_alt(gspca_dev);
+}
+
+/* This function is called to start the webcam */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       return sd->dev_init_pre_alt(gspca_dev);
+}
+
+/* This function is called to stop the webcam */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (!sd->gspca_dev.present)
+               return;
+
+       return sd->dev_post_unset_alt(gspca_dev);
+}
+
+/* This function is called when an image is being received */
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data, int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       static s32 nSkipped;
+
+       s32 mode = (s32) gspca_dev->curr_mode;
+       s32 nToSkip =
+               sd->swapRB * (gspca_dev->cam.cam_mode[mode].bytesperline + 1);
+
+       /* Test only against 0202h, so endianess does not matter */
+       switch (*(s16 *) data) {
+       case 0x0202:            /* End of frame, start a new one */
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+               nSkipped = 0;
+               if (sd->nbIm >= 0 && sd->nbIm < 10)
+                       sd->nbIm++;
+               gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
+               break;
+
+       default:
+               data += 2;
+               len  -= 2;
+               if (nSkipped + len <= nToSkip)
+                       nSkipped += len;
+               else {
+                       if (nSkipped < nToSkip && nSkipped + len > nToSkip) {
+                               data += nToSkip - nSkipped;
+                               len  -= nToSkip - nSkipped;
+                               nSkipped = nToSkip + 1;
+                       }
+                       gspca_frame_add(gspca_dev,
+                               INTER_PACKET, data, len);
+               }
+               break;
+       }
+}
+
+/* This function is called when an image has been read */
+/* This function is used to monitor webcam orientation */
+static void sd_callback(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (!_OV9655_) {
+               u8 state;
+               u8 upsideDown;
+
+               /* Probe sensor orientation */
+               ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, (void *)&state);
+
+               /* C8/40 means upside-down (looking backwards) */
+               /* D8/50 means right-up (looking onwards) */
+               upsideDown = (state == 0xc8 || state == 0x40);
+
+               if (upsideDown && sd->nbRightUp > -4) {
+                       if (sd->nbRightUp > 0)
+                               sd->nbRightUp = 0;
+                       if (sd->nbRightUp == -3) {
+                               sd->mirrorMask = 1;
+                               sd->waitSet = 1;
+                       }
+                       sd->nbRightUp--;
+               }
+               if (!upsideDown && sd->nbRightUp < 4) {
+                       if (sd->nbRightUp  < 0)
+                               sd->nbRightUp = 0;
+                       if (sd->nbRightUp == 3) {
+                               sd->mirrorMask = 0;
+                               sd->waitSet = 1;
+                       }
+                       sd->nbRightUp++;
+               }
+       }
+
+       if (sd->waitSet)
+               sd->dev_camera_settings(gspca_dev);
+}
+
+/*=================== USB driver structure initialisation ==================*/
+
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x05e3, 0x0503)},
+       {USB_DEVICE(0x05e3, 0xf191)},
+       {}
+};
+
+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_mi1320, sizeof(struct sd), THIS_MODULE);
+}
+
+static void sd_disconnect(struct usb_interface *intf)
+{
+       gspca_disconnect(intf);
+}
+
+static struct usb_driver sd_driver = {
+       .name       = MODULE_NAME,
+       .id_table   = device_table,
+       .probe      = sd_probe,
+       .disconnect = sd_disconnect,
+#ifdef CONFIG_PM
+       .suspend    = gspca_suspend,
+       .resume     = gspca_resume,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+/*====================== Init and Exit module functions ====================*/
+
+module_usb_driver(sd_driver);
+
+/*==========================================================================*/
+
+int gl860_RTx(struct gspca_dev *gspca_dev,
+               unsigned char pref, u32 req, u16 val, u16 index,
+               s32 len, void *pdata)
+{
+       struct usb_device *udev = gspca_dev->dev;
+       s32 r = 0;
+
+       if (pref == 0x40) { /* Send */
+               if (len > 0) {
+                       memcpy(gspca_dev->usb_buf, pdata, len);
+                       r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                                       req, pref, val, index,
+                                       gspca_dev->usb_buf,
+                                       len, 400 + 200 * (len > 1));
+               } else {
+                       r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                                       req, pref, val, index, NULL, len, 400);
+               }
+       } else { /* Receive */
+               if (len > 0) {
+                       r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                                       req, pref, val, index,
+                                       gspca_dev->usb_buf,
+                                       len, 400 + 200 * (len > 1));
+                       memcpy(pdata, gspca_dev->usb_buf, len);
+               } else {
+                       r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                                       req, pref, val, index, NULL, len, 400);
+               }
+       }
+
+       if (r < 0)
+               pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n",
+                      r, pref, req, val, index, len);
+       else if (len > 1 && r < len)
+               PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len);
+
+       msleep(1);
+
+       return r;
+}
+
+int fetch_validx(struct gspca_dev *gspca_dev, struct validx *tbl, int len)
+{
+       int n;
+
+       for (n = 0; n < len; n++) {
+               if (tbl[n].idx != 0xffff)
+                       ctrl_out(gspca_dev, 0x40, 1, tbl[n].val,
+                                       tbl[n].idx, 0, NULL);
+               else if (tbl[n].val == 0xffff)
+                       break;
+               else
+                       msleep(tbl[n].val);
+       }
+       return n;
+}
+
+int keep_on_fetching_validx(struct gspca_dev *gspca_dev, struct validx *tbl,
+                               int len, int n)
+{
+       while (++n < len) {
+               if (tbl[n].idx != 0xffff)
+                       ctrl_out(gspca_dev, 0x40, 1, tbl[n].val, tbl[n].idx,
+                                       0, NULL);
+               else if (tbl[n].val == 0xffff)
+                       break;
+               else
+                       msleep(tbl[n].val);
+       }
+       return n;
+}
+
+void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len)
+{
+       int n;
+
+       for (n = 0; n < len; n++) {
+               if (memcmp(tbl[n].data, "\xff\xff\xff", 3) != 0)
+                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, tbl[n].idx,
+                                       3, tbl[n].data);
+               else
+                       msleep(tbl[n].idx);
+       }
+}
+
+static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
+                               u16 vendor_id, u16 product_id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 probe, nb26, nb96, nOV, ntry;
+
+       if (product_id == 0xf191)
+               sd->sensor = ID_MI1320;
+
+       if (sd->sensor == 0xff) {
+               ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);
+               ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);
+
+               ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x0000, 0, NULL);
+               msleep(3);
+               ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
+               msleep(3);
+               ctrl_out(gspca_dev, 0x40, 1, 0x0008, 0x00c0, 0, NULL);
+               msleep(3);
+               ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c1, 0, NULL);
+               msleep(3);
+               ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c2, 0, NULL);
+               msleep(3);
+               ctrl_out(gspca_dev, 0x40, 1, 0x0020, 0x0006, 0, NULL);
+               msleep(3);
+               ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL);
+               msleep(56);
+
+               PDEBUG(D_PROBE, "probing for sensor MI2020 or OVXXXX");
+               nOV = 0;
+               for (ntry = 0; ntry < 4; ntry++) {
+                       ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
+                       msleep(3);
+                       ctrl_out(gspca_dev, 0x40, 1, 0x0063, 0x0006, 0, NULL);
+                       msleep(3);
+                       ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL);
+                       msleep(10);
+                       ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &probe);
+                       PDEBUG(D_PROBE, "probe=0x%02x", probe);
+                       if (probe == 0xff)
+                               nOV++;
+               }
+
+               if (nOV) {
+                       PDEBUG(D_PROBE, "0xff -> OVXXXX");
+                       PDEBUG(D_PROBE, "probing for sensor OV2640 or OV9655");
+
+                       nb26 = nb96 = 0;
+                       for (ntry = 0; ntry < 4; ntry++) {
+                               ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000,
+                                               0, NULL);
+                               msleep(3);
+                               ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x800a,
+                                               0, NULL);
+                               msleep(10);
+
+                               /* Wait for 26(OV2640) or 96(OV9655) */
+                               ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x800a,
+                                               1, &probe);
+
+                               if (probe == 0x26 || probe == 0x40) {
+                                       PDEBUG(D_PROBE,
+                                               "probe=0x%02x -> OV2640",
+                                               probe);
+                                       sd->sensor = ID_OV2640;
+                                       nb26 += 4;
+                                       break;
+                               }
+                               if (probe == 0x96 || probe == 0x55) {
+                                       PDEBUG(D_PROBE,
+                                               "probe=0x%02x -> OV9655",
+                                               probe);
+                                       sd->sensor = ID_OV9655;
+                                       nb96 += 4;
+                                       break;
+                               }
+                               PDEBUG(D_PROBE, "probe=0x%02x", probe);
+                               if (probe == 0x00)
+                                       nb26++;
+                               if (probe == 0xff)
+                                       nb96++;
+                               msleep(3);
+                       }
+                       if (nb26 < 4 && nb96 < 4)
+                               return -1;
+               } else {
+                       PDEBUG(D_PROBE, "Not any 0xff -> MI2020");
+                       sd->sensor = ID_MI2020;
+               }
+       }
+
+       if (_MI1320_) {
+               PDEBUG(D_PROBE, "05e3:f191 sensor MI1320 (1.3M)");
+       } else if (_MI2020_) {
+               PDEBUG(D_PROBE, "05e3:0503 sensor MI2020 (2.0M)");
+       } else if (_OV9655_) {
+               PDEBUG(D_PROBE, "05e3:0503 sensor OV9655 (1.3M)");
+       } else if (_OV2640_) {
+               PDEBUG(D_PROBE, "05e3:0503 sensor OV2640 (2.0M)");
+       } else {
+               PDEBUG(D_PROBE, "***** Unknown sensor *****");
+               return -1;
+       }
+
+       return 0;
+}
diff --git a/drivers/media/usb/gspca/gl860/gl860.h b/drivers/media/usb/gspca/gl860/gl860.h
new file mode 100644 (file)
index 0000000..0330a02
--- /dev/null
@@ -0,0 +1,105 @@
+/* GSPCA subdrivers for Genesys Logic webcams with the GL860 chip
+ * Subdriver declarations
+ *
+ * 2009/10/14 Olivier LORIN <o.lorin@laposte.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GL860_DEV_H
+#define GL860_DEV_H
+
+#include "gspca.h"
+
+#define MODULE_NAME "gspca_gl860"
+#define DRIVER_VERSION "0.9d10"
+
+#define ctrl_in  gl860_RTx
+#define ctrl_out gl860_RTx
+
+#define ID_MI1320   1
+#define ID_OV2640   2
+#define ID_OV9655   4
+#define ID_MI2020   8
+
+#define _MI1320_  (((struct sd *) gspca_dev)->sensor == ID_MI1320)
+#define _MI2020_  (((struct sd *) gspca_dev)->sensor == ID_MI2020)
+#define _OV2640_  (((struct sd *) gspca_dev)->sensor == ID_OV2640)
+#define _OV9655_  (((struct sd *) gspca_dev)->sensor == ID_OV9655)
+
+#define IMAGE_640   0
+#define IMAGE_800   1
+#define IMAGE_1280  2
+#define IMAGE_1600  3
+
+struct sd_gl860 {
+       u16 backlight;
+       u16 brightness;
+       u16 sharpness;
+       u16 contrast;
+       u16 gamma;
+       u16 hue;
+       u16 saturation;
+       u16 whitebal;
+       u8  mirror;
+       u8  flip;
+       u8  AC50Hz;
+};
+
+/* Specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       struct sd_gl860 vcur;
+       struct sd_gl860 vold;
+       struct sd_gl860 vmax;
+
+       int  (*dev_configure_alt)  (struct gspca_dev *);
+       int  (*dev_init_at_startup)(struct gspca_dev *);
+       int  (*dev_init_pre_alt)   (struct gspca_dev *);
+       void (*dev_post_unset_alt) (struct gspca_dev *);
+       int  (*dev_camera_settings)(struct gspca_dev *);
+
+       u8   swapRB;
+       u8   mirrorMask;
+       u8   sensor;
+       s32  nbIm;
+       s32  nbRightUp;
+       u8   waitSet;
+};
+
+struct validx {
+       u16 val;
+       u16 idx;
+};
+
+struct idxdata {
+       u8 idx;
+       u8 data[3];
+};
+
+int fetch_validx(struct gspca_dev *gspca_dev, struct validx *tbl, int len);
+int keep_on_fetching_validx(struct gspca_dev *gspca_dev, struct validx *tbl,
+                               int len, int n);
+void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len);
+
+int gl860_RTx(struct gspca_dev *gspca_dev,
+                       unsigned char pref, u32 req, u16 val, u16 index,
+                       s32 len, void *pdata);
+
+void mi1320_init_settings(struct gspca_dev *);
+void ov2640_init_settings(struct gspca_dev *);
+void ov9655_init_settings(struct gspca_dev *);
+void mi2020_init_settings(struct gspca_dev *);
+
+#endif
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
new file mode 100644 (file)
index 0000000..d4e8343
--- /dev/null
@@ -0,0 +1,2456 @@
+/*
+ * Main USB camera driver
+ *
+ * Copyright (C) 2008-2011 Jean-François Moine <http://moinejf.free.fr>
+ *
+ * Camera button input handling by Márton Németh
+ * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define GSPCA_VERSION  "2.14.0"
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pagemap.h>
+#include <linux/io.h>
+#include <asm/page.h>
+#include <linux/uaccess.h>
+#include <linux/ktime.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+
+#include "gspca.h"
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+#include <linux/input.h>
+#include <linux/usb/input.h>
+#endif
+
+/* global values */
+#define DEF_NURBS 3            /* default number of URBs */
+#if DEF_NURBS > MAX_NURBS
+#error "DEF_NURBS too big"
+#endif
+
+MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
+MODULE_DESCRIPTION("GSPCA USB Camera Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(GSPCA_VERSION);
+
+#ifdef GSPCA_DEBUG
+int gspca_debug = D_ERR | D_PROBE;
+EXPORT_SYMBOL(gspca_debug);
+
+static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
+{
+       if ((pixfmt >> 24) >= '0' && (pixfmt >> 24) <= 'z') {
+               PDEBUG(D_CONF|D_STREAM, "%s %c%c%c%c %dx%d",
+                       txt,
+                       pixfmt & 0xff,
+                       (pixfmt >> 8) & 0xff,
+                       (pixfmt >> 16) & 0xff,
+                       pixfmt >> 24,
+                       w, h);
+       } else {
+               PDEBUG(D_CONF|D_STREAM, "%s 0x%08x %dx%d",
+                       txt,
+                       pixfmt,
+                       w, h);
+       }
+}
+#else
+#define PDEBUG_MODE(txt, pixfmt, w, h)
+#endif
+
+/* specific memory types - !! should be different from V4L2_MEMORY_xxx */
+#define GSPCA_MEMORY_NO 0      /* V4L2_MEMORY_xxx starts from 1 */
+#define GSPCA_MEMORY_READ 7
+
+#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)
+
+/*
+ * VMA operations.
+ */
+static void gspca_vm_open(struct vm_area_struct *vma)
+{
+       struct gspca_frame *frame = vma->vm_private_data;
+
+       frame->vma_use_count++;
+       frame->v4l2_buf.flags |= V4L2_BUF_FLAG_MAPPED;
+}
+
+static void gspca_vm_close(struct vm_area_struct *vma)
+{
+       struct gspca_frame *frame = vma->vm_private_data;
+
+       if (--frame->vma_use_count <= 0)
+               frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_MAPPED;
+}
+
+static const struct vm_operations_struct gspca_vm_ops = {
+       .open           = gspca_vm_open,
+       .close          = gspca_vm_close,
+};
+
+/*
+ * Input and interrupt endpoint handling functions
+ */
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static void int_irq(struct urb *urb)
+{
+       struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
+       int ret;
+
+       ret = urb->status;
+       switch (ret) {
+       case 0:
+               if (gspca_dev->sd_desc->int_pkt_scan(gspca_dev,
+                   urb->transfer_buffer, urb->actual_length) < 0) {
+                       PDEBUG(D_ERR, "Unknown packet received");
+               }
+               break;
+
+       case -ENOENT:
+       case -ECONNRESET:
+       case -ENODEV:
+       case -ESHUTDOWN:
+               /* Stop is requested either by software or hardware is gone,
+                * keep the ret value non-zero and don't resubmit later.
+                */
+               break;
+
+       default:
+               PDEBUG(D_ERR, "URB error %i, resubmitting", urb->status);
+               urb->status = 0;
+               ret = 0;
+       }
+
+       if (ret == 0) {
+               ret = usb_submit_urb(urb, GFP_ATOMIC);
+               if (ret < 0)
+                       pr_err("Resubmit URB failed with error %i\n", ret);
+       }
+}
+
+static int gspca_input_connect(struct gspca_dev *dev)
+{
+       struct input_dev *input_dev;
+       int err = 0;
+
+       dev->input_dev = NULL;
+       if (dev->sd_desc->int_pkt_scan || dev->sd_desc->other_input)  {
+               input_dev = input_allocate_device();
+               if (!input_dev)
+                       return -ENOMEM;
+
+               usb_make_path(dev->dev, dev->phys, sizeof(dev->phys));
+               strlcat(dev->phys, "/input0", sizeof(dev->phys));
+
+               input_dev->name = dev->sd_desc->name;
+               input_dev->phys = dev->phys;
+
+               usb_to_input_id(dev->dev, &input_dev->id);
+
+               input_dev->evbit[0] = BIT_MASK(EV_KEY);
+               input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
+               input_dev->dev.parent = &dev->dev->dev;
+
+               err = input_register_device(input_dev);
+               if (err) {
+                       pr_err("Input device registration failed with error %i\n",
+                              err);
+                       input_dev->dev.parent = NULL;
+                       input_free_device(input_dev);
+               } else {
+                       dev->input_dev = input_dev;
+               }
+       }
+
+       return err;
+}
+
+static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
+                         struct usb_endpoint_descriptor *ep)
+{
+       unsigned int buffer_len;
+       int interval;
+       struct urb *urb;
+       struct usb_device *dev;
+       void *buffer = NULL;
+       int ret = -EINVAL;
+
+       buffer_len = le16_to_cpu(ep->wMaxPacketSize);
+       interval = ep->bInterval;
+       PDEBUG(D_CONF, "found int in endpoint: 0x%x, "
+               "buffer_len=%u, interval=%u",
+               ep->bEndpointAddress, buffer_len, interval);
+
+       dev = gspca_dev->dev;
+
+       urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!urb) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       buffer = usb_alloc_coherent(dev, buffer_len,
+                               GFP_KERNEL, &urb->transfer_dma);
+       if (!buffer) {
+               ret = -ENOMEM;
+               goto error_buffer;
+       }
+       usb_fill_int_urb(urb, dev,
+               usb_rcvintpipe(dev, ep->bEndpointAddress),
+               buffer, buffer_len,
+               int_irq, (void *)gspca_dev, interval);
+       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+       ret = usb_submit_urb(urb, GFP_KERNEL);
+       if (ret < 0) {
+               PDEBUG(D_ERR, "submit int URB failed with error %i", ret);
+               goto error_submit;
+       }
+       gspca_dev->int_urb = urb;
+       return ret;
+
+error_submit:
+       usb_free_coherent(dev,
+                         urb->transfer_buffer_length,
+                         urb->transfer_buffer,
+                         urb->transfer_dma);
+error_buffer:
+       usb_free_urb(urb);
+error:
+       return ret;
+}
+
+static void gspca_input_create_urb(struct gspca_dev *gspca_dev)
+{
+       struct usb_interface *intf;
+       struct usb_host_interface *intf_desc;
+       struct usb_endpoint_descriptor *ep;
+       int i;
+
+       if (gspca_dev->sd_desc->int_pkt_scan)  {
+               intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
+               intf_desc = intf->cur_altsetting;
+               for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
+                       ep = &intf_desc->endpoint[i].desc;
+                       if (usb_endpoint_dir_in(ep) &&
+                           usb_endpoint_xfer_int(ep)) {
+
+                               alloc_and_submit_int_urb(gspca_dev, ep);
+                               break;
+                       }
+               }
+       }
+}
+
+static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev)
+{
+       struct urb *urb;
+
+       urb = gspca_dev->int_urb;
+       if (urb) {
+               gspca_dev->int_urb = NULL;
+               usb_kill_urb(urb);
+               usb_free_coherent(gspca_dev->dev,
+                                 urb->transfer_buffer_length,
+                                 urb->transfer_buffer,
+                                 urb->transfer_dma);
+               usb_free_urb(urb);
+       }
+}
+#else
+static inline void gspca_input_destroy_urb(struct gspca_dev *gspca_dev)
+{
+}
+
+static inline void gspca_input_create_urb(struct gspca_dev *gspca_dev)
+{
+}
+
+static inline int gspca_input_connect(struct gspca_dev *dev)
+{
+       return 0;
+}
+#endif
+
+/*
+ * fill a video frame from an URB and resubmit
+ */
+static void fill_frame(struct gspca_dev *gspca_dev,
+                       struct urb *urb)
+{
+       u8 *data;               /* address of data in the iso message */
+       int i, len, st;
+       cam_pkt_op pkt_scan;
+
+       if (urb->status != 0) {
+               if (urb->status == -ESHUTDOWN)
+                       return;         /* disconnection */
+#ifdef CONFIG_PM
+               if (gspca_dev->frozen)
+                       return;
+#endif
+               PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
+               urb->status = 0;
+               goto resubmit;
+       }
+       pkt_scan = gspca_dev->sd_desc->pkt_scan;
+       for (i = 0; i < urb->number_of_packets; i++) {
+               len = urb->iso_frame_desc[i].actual_length;
+
+               /* check the packet status and length */
+               st = urb->iso_frame_desc[i].status;
+               if (st) {
+                       pr_err("ISOC data error: [%d] len=%d, status=%d\n",
+                              i, len, st);
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+                       continue;
+               }
+               if (len == 0) {
+                       if (gspca_dev->empty_packet == 0)
+                               gspca_dev->empty_packet = 1;
+                       continue;
+               }
+
+               /* let the packet be analyzed by the subdriver */
+               PDEBUG(D_PACK, "packet [%d] o:%d l:%d",
+                       i, urb->iso_frame_desc[i].offset, len);
+               data = (u8 *) urb->transfer_buffer
+                                       + urb->iso_frame_desc[i].offset;
+               pkt_scan(gspca_dev, data, len);
+       }
+
+resubmit:
+       /* resubmit the URB */
+       st = usb_submit_urb(urb, GFP_ATOMIC);
+       if (st < 0)
+               pr_err("usb_submit_urb() ret %d\n", st);
+}
+
+/*
+ * ISOC message interrupt from the USB device
+ *
+ * Analyse each packet and call the subdriver for copy to the frame buffer.
+ */
+static void isoc_irq(struct urb *urb)
+{
+       struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
+
+       PDEBUG(D_PACK, "isoc irq");
+       if (!gspca_dev->streaming)
+               return;
+       fill_frame(gspca_dev, urb);
+}
+
+/*
+ * bulk message interrupt from the USB device
+ */
+static void bulk_irq(struct urb *urb)
+{
+       struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
+       int st;
+
+       PDEBUG(D_PACK, "bulk irq");
+       if (!gspca_dev->streaming)
+               return;
+       switch (urb->status) {
+       case 0:
+               break;
+       case -ESHUTDOWN:
+               return;         /* disconnection */
+       default:
+#ifdef CONFIG_PM
+               if (gspca_dev->frozen)
+                       return;
+#endif
+               PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
+               urb->status = 0;
+               goto resubmit;
+       }
+
+       PDEBUG(D_PACK, "packet l:%d", urb->actual_length);
+       gspca_dev->sd_desc->pkt_scan(gspca_dev,
+                               urb->transfer_buffer,
+                               urb->actual_length);
+
+resubmit:
+       /* resubmit the URB */
+       if (gspca_dev->cam.bulk_nurbs != 0) {
+               st = usb_submit_urb(urb, GFP_ATOMIC);
+               if (st < 0)
+                       pr_err("usb_submit_urb() ret %d\n", st);
+       }
+}
+
+/*
+ * add data to the current frame
+ *
+ * This function is called by the subdrivers at interrupt level.
+ *
+ * To build a frame, these ones must add
+ *     - one FIRST_PACKET
+ *     - 0 or many INTER_PACKETs
+ *     - one LAST_PACKET
+ * DISCARD_PACKET invalidates the whole frame.
+ */
+void gspca_frame_add(struct gspca_dev *gspca_dev,
+                       enum gspca_packet_type packet_type,
+                       const u8 *data,
+                       int len)
+{
+       struct gspca_frame *frame;
+       int i, j;
+
+       PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len);
+
+       if (packet_type == FIRST_PACKET) {
+               i = atomic_read(&gspca_dev->fr_i);
+
+               /* if there are no queued buffer, discard the whole frame */
+               if (i == atomic_read(&gspca_dev->fr_q)) {
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+                       gspca_dev->sequence++;
+                       return;
+               }
+               j = gspca_dev->fr_queue[i];
+               frame = &gspca_dev->frame[j];
+               frame->v4l2_buf.timestamp = ktime_to_timeval(ktime_get());
+               frame->v4l2_buf.sequence = gspca_dev->sequence++;
+               gspca_dev->image = frame->data;
+               gspca_dev->image_len = 0;
+       } else {
+               switch (gspca_dev->last_packet_type) {
+               case DISCARD_PACKET:
+                       if (packet_type == LAST_PACKET) {
+                               gspca_dev->last_packet_type = packet_type;
+                               gspca_dev->image = NULL;
+                               gspca_dev->image_len = 0;
+                       }
+                       return;
+               case LAST_PACKET:
+                       return;
+               }
+       }
+
+       /* append the packet to the frame buffer */
+       if (len > 0) {
+               if (gspca_dev->image_len + len > gspca_dev->frsz) {
+                       PDEBUG(D_ERR|D_PACK, "frame overflow %d > %d",
+                               gspca_dev->image_len + len,
+                               gspca_dev->frsz);
+                       packet_type = DISCARD_PACKET;
+               } else {
+/* !! image is NULL only when last pkt is LAST or DISCARD
+                       if (gspca_dev->image == NULL) {
+                               pr_err("gspca_frame_add() image == NULL\n");
+                               return;
+                       }
+ */
+                       memcpy(gspca_dev->image + gspca_dev->image_len,
+                               data, len);
+                       gspca_dev->image_len += len;
+               }
+       }
+       gspca_dev->last_packet_type = packet_type;
+
+       /* if last packet, invalidate packet concatenation until
+        * next first packet, wake up the application and advance
+        * in the queue */
+       if (packet_type == LAST_PACKET) {
+               i = atomic_read(&gspca_dev->fr_i);
+               j = gspca_dev->fr_queue[i];
+               frame = &gspca_dev->frame[j];
+               frame->v4l2_buf.bytesused = gspca_dev->image_len;
+               frame->v4l2_buf.flags = (frame->v4l2_buf.flags
+                                        | V4L2_BUF_FLAG_DONE)
+                                       & ~V4L2_BUF_FLAG_QUEUED;
+               i = (i + 1) % GSPCA_MAX_FRAMES;
+               atomic_set(&gspca_dev->fr_i, i);
+               wake_up_interruptible(&gspca_dev->wq);  /* event = new frame */
+               PDEBUG(D_FRAM, "frame complete len:%d",
+                       frame->v4l2_buf.bytesused);
+               gspca_dev->image = NULL;
+               gspca_dev->image_len = 0;
+       }
+}
+EXPORT_SYMBOL(gspca_frame_add);
+
+static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file,
+                       enum v4l2_memory memory, unsigned int count)
+{
+       struct gspca_frame *frame;
+       unsigned int frsz;
+       int i;
+
+       i = gspca_dev->curr_mode;
+       frsz = gspca_dev->cam.cam_mode[i].sizeimage;
+       PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz);
+       frsz = PAGE_ALIGN(frsz);
+       if (count >= GSPCA_MAX_FRAMES)
+               count = GSPCA_MAX_FRAMES - 1;
+       gspca_dev->frbuf = vmalloc_32(frsz * count);
+       if (!gspca_dev->frbuf) {
+               pr_err("frame alloc failed\n");
+               return -ENOMEM;
+       }
+       gspca_dev->capt_file = file;
+       gspca_dev->memory = memory;
+       gspca_dev->frsz = frsz;
+       gspca_dev->nframes = count;
+       for (i = 0; i < count; i++) {
+               frame = &gspca_dev->frame[i];
+               frame->v4l2_buf.index = i;
+               frame->v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               frame->v4l2_buf.flags = 0;
+               frame->v4l2_buf.field = V4L2_FIELD_NONE;
+               frame->v4l2_buf.length = frsz;
+               frame->v4l2_buf.memory = memory;
+               frame->v4l2_buf.sequence = 0;
+               frame->data = gspca_dev->frbuf + i * frsz;
+               frame->v4l2_buf.m.offset = i * frsz;
+       }
+       atomic_set(&gspca_dev->fr_q, 0);
+       atomic_set(&gspca_dev->fr_i, 0);
+       gspca_dev->fr_o = 0;
+       return 0;
+}
+
+static void frame_free(struct gspca_dev *gspca_dev)
+{
+       int i;
+
+       PDEBUG(D_STREAM, "frame free");
+       if (gspca_dev->frbuf != NULL) {
+               vfree(gspca_dev->frbuf);
+               gspca_dev->frbuf = NULL;
+               for (i = 0; i < gspca_dev->nframes; i++)
+                       gspca_dev->frame[i].data = NULL;
+       }
+       gspca_dev->nframes = 0;
+       gspca_dev->frsz = 0;
+       gspca_dev->capt_file = NULL;
+       gspca_dev->memory = GSPCA_MEMORY_NO;
+}
+
+static void destroy_urbs(struct gspca_dev *gspca_dev)
+{
+       struct urb *urb;
+       unsigned int i;
+
+       PDEBUG(D_STREAM, "kill transfer");
+       for (i = 0; i < MAX_NURBS; i++) {
+               urb = gspca_dev->urb[i];
+               if (urb == NULL)
+                       break;
+
+               gspca_dev->urb[i] = NULL;
+               usb_kill_urb(urb);
+               if (urb->transfer_buffer != NULL)
+                       usb_free_coherent(gspca_dev->dev,
+                                         urb->transfer_buffer_length,
+                                         urb->transfer_buffer,
+                                         urb->transfer_dma);
+               usb_free_urb(urb);
+       }
+}
+
+static int gspca_set_alt0(struct gspca_dev *gspca_dev)
+{
+       int ret;
+
+       if (gspca_dev->alt == 0)
+               return 0;
+       ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
+       if (ret < 0)
+               pr_err("set alt 0 err %d\n", ret);
+       return ret;
+}
+
+/* Note: both the queue and the usb locks should be held when calling this */
+static void gspca_stream_off(struct gspca_dev *gspca_dev)
+{
+       gspca_dev->streaming = 0;
+       gspca_dev->usb_err = 0;
+       if (gspca_dev->sd_desc->stopN)
+               gspca_dev->sd_desc->stopN(gspca_dev);
+       destroy_urbs(gspca_dev);
+       gspca_input_destroy_urb(gspca_dev);
+       gspca_set_alt0(gspca_dev);
+       gspca_input_create_urb(gspca_dev);
+       if (gspca_dev->sd_desc->stop0)
+               gspca_dev->sd_desc->stop0(gspca_dev);
+       PDEBUG(D_STREAM, "stream off OK");
+}
+
+/*
+ * look for an input transfer endpoint in an alternate setting
+ */
+static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
+                                         int xfer)
+{
+       struct usb_host_endpoint *ep;
+       int i, attr;
+
+       for (i = 0; i < alt->desc.bNumEndpoints; i++) {
+               ep = &alt->endpoint[i];
+               attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+               if (attr == xfer
+                   && ep->desc.wMaxPacketSize != 0
+                   && usb_endpoint_dir_in(&ep->desc))
+                       return ep;
+       }
+       return NULL;
+}
+
+/* compute the minimum bandwidth for the current transfer */
+static u32 which_bandwidth(struct gspca_dev *gspca_dev)
+{
+       u32 bandwidth;
+       int i;
+
+       /* get the (max) image size */
+       i = gspca_dev->curr_mode;
+       bandwidth = gspca_dev->cam.cam_mode[i].sizeimage;
+
+       /* if the image is compressed, estimate its mean size */
+       if (!gspca_dev->cam.needs_full_bandwidth &&
+           bandwidth < gspca_dev->cam.cam_mode[i].width *
+                               gspca_dev->cam.cam_mode[i].height)
+               bandwidth = bandwidth * 3 / 8;  /* 0.375 */
+
+       /* estimate the frame rate */
+       if (gspca_dev->sd_desc->get_streamparm) {
+               struct v4l2_streamparm parm;
+
+               gspca_dev->sd_desc->get_streamparm(gspca_dev, &parm);
+               bandwidth *= parm.parm.capture.timeperframe.denominator;
+               bandwidth /= parm.parm.capture.timeperframe.numerator;
+       } else {
+
+               /* don't hope more than 15 fps with USB 1.1 and
+                * image resolution >= 640x480 */
+               if (gspca_dev->width >= 640
+                && gspca_dev->dev->speed == USB_SPEED_FULL)
+                       bandwidth *= 15;                /* 15 fps */
+               else
+                       bandwidth *= 30;                /* 30 fps */
+       }
+
+       PDEBUG(D_STREAM, "min bandwidth: %d", bandwidth);
+       return bandwidth;
+}
+
+/* endpoint table */
+#define MAX_ALT 16
+struct ep_tb_s {
+       u32 alt;
+       u32 bandwidth;
+};
+
+/*
+ * build the table of the endpoints
+ * and compute the minimum bandwidth for the image transfer
+ */
+static int build_isoc_ep_tb(struct gspca_dev *gspca_dev,
+                       struct usb_interface *intf,
+                       struct ep_tb_s *ep_tb)
+{
+       struct usb_host_endpoint *ep;
+       int i, j, nbalt, psize, found;
+       u32 bandwidth, last_bw;
+
+       nbalt = intf->num_altsetting;
+       if (nbalt > MAX_ALT)
+               nbalt = MAX_ALT;        /* fixme: should warn */
+
+       /* build the endpoint table */
+       i = 0;
+       last_bw = 0;
+       for (;;) {
+               ep_tb->bandwidth = 2000 * 2000 * 120;
+               found = 0;
+               for (j = 0; j < nbalt; j++) {
+                       ep = alt_xfer(&intf->altsetting[j],
+                                     USB_ENDPOINT_XFER_ISOC);
+                       if (ep == NULL)
+                               continue;
+                       if (ep->desc.bInterval == 0) {
+                               pr_err("alt %d iso endp with 0 interval\n", j);
+                               continue;
+                       }
+                       psize = le16_to_cpu(ep->desc.wMaxPacketSize);
+                       psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+                       bandwidth = psize * 1000;
+                       if (gspca_dev->dev->speed == USB_SPEED_HIGH
+                        || gspca_dev->dev->speed == USB_SPEED_SUPER)
+                               bandwidth *= 8;
+                       bandwidth /= 1 << (ep->desc.bInterval - 1);
+                       if (bandwidth <= last_bw)
+                               continue;
+                       if (bandwidth < ep_tb->bandwidth) {
+                               ep_tb->bandwidth = bandwidth;
+                               ep_tb->alt = j;
+                               found = 1;
+                       }
+               }
+               if (!found)
+                       break;
+               PDEBUG(D_STREAM, "alt %d bandwidth %d",
+                               ep_tb->alt, ep_tb->bandwidth);
+               last_bw = ep_tb->bandwidth;
+               i++;
+               ep_tb++;
+       }
+
+       /*
+        * If the camera:
+        * has a usb audio class interface (a built in usb mic); and
+        * is a usb 1 full speed device; and
+        * uses the max full speed iso bandwidth; and
+        * and has more than 1 alt setting
+        * then skip the highest alt setting to spare bandwidth for the mic
+        */
+       if (gspca_dev->audio &&
+                       gspca_dev->dev->speed == USB_SPEED_FULL &&
+                       last_bw >= 1000000 &&
+                       i > 1) {
+               PDEBUG(D_STREAM, "dev has usb audio, skipping highest alt");
+               i--;
+               ep_tb--;
+       }
+
+       /* get the requested bandwidth and start at the highest atlsetting */
+       bandwidth = which_bandwidth(gspca_dev);
+       ep_tb--;
+       while (i > 1) {
+               ep_tb--;
+               if (ep_tb->bandwidth < bandwidth)
+                       break;
+               i--;
+       }
+       return i;
+}
+
+/*
+ * create the URBs for image transfer
+ */
+static int create_urbs(struct gspca_dev *gspca_dev,
+                       struct usb_host_endpoint *ep)
+{
+       struct urb *urb;
+       int n, nurbs, i, psize, npkt, bsize;
+
+       /* calculate the packet size and the number of packets */
+       psize = le16_to_cpu(ep->desc.wMaxPacketSize);
+
+       if (!gspca_dev->cam.bulk) {             /* isoc */
+
+               /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
+               if (gspca_dev->pkt_size == 0)
+                       psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+               else
+                       psize = gspca_dev->pkt_size;
+               npkt = gspca_dev->cam.npkt;
+               if (npkt == 0)
+                       npkt = 32;              /* default value */
+               bsize = psize * npkt;
+               PDEBUG(D_STREAM,
+                       "isoc %d pkts size %d = bsize:%d",
+                       npkt, psize, bsize);
+               nurbs = DEF_NURBS;
+       } else {                                /* bulk */
+               npkt = 0;
+               bsize = gspca_dev->cam.bulk_size;
+               if (bsize == 0)
+                       bsize = psize;
+               PDEBUG(D_STREAM, "bulk bsize:%d", bsize);
+               if (gspca_dev->cam.bulk_nurbs != 0)
+                       nurbs = gspca_dev->cam.bulk_nurbs;
+               else
+                       nurbs = 1;
+       }
+
+       for (n = 0; n < nurbs; n++) {
+               urb = usb_alloc_urb(npkt, GFP_KERNEL);
+               if (!urb) {
+                       pr_err("usb_alloc_urb failed\n");
+                       return -ENOMEM;
+               }
+               gspca_dev->urb[n] = urb;
+               urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
+                                               bsize,
+                                               GFP_KERNEL,
+                                               &urb->transfer_dma);
+
+               if (urb->transfer_buffer == NULL) {
+                       pr_err("usb_alloc_coherent failed\n");
+                       return -ENOMEM;
+               }
+               urb->dev = gspca_dev->dev;
+               urb->context = gspca_dev;
+               urb->transfer_buffer_length = bsize;
+               if (npkt != 0) {                /* ISOC */
+                       urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
+                                                   ep->desc.bEndpointAddress);
+                       urb->transfer_flags = URB_ISO_ASAP
+                                       | URB_NO_TRANSFER_DMA_MAP;
+                       urb->interval = 1 << (ep->desc.bInterval - 1);
+                       urb->complete = isoc_irq;
+                       urb->number_of_packets = npkt;
+                       for (i = 0; i < npkt; i++) {
+                               urb->iso_frame_desc[i].length = psize;
+                               urb->iso_frame_desc[i].offset = psize * i;
+                       }
+               } else {                /* bulk */
+                       urb->pipe = usb_rcvbulkpipe(gspca_dev->dev,
+                                               ep->desc.bEndpointAddress);
+                       urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+                       urb->complete = bulk_irq;
+               }
+       }
+       return 0;
+}
+
+/*
+ * start the USB transfer
+ */
+static int gspca_init_transfer(struct gspca_dev *gspca_dev)
+{
+       struct usb_interface *intf;
+       struct usb_host_endpoint *ep;
+       struct urb *urb;
+       struct ep_tb_s ep_tb[MAX_ALT];
+       int n, ret, xfer, alt, alt_idx;
+
+       /* reset the streaming variables */
+       gspca_dev->image = NULL;
+       gspca_dev->image_len = 0;
+       gspca_dev->last_packet_type = DISCARD_PACKET;
+       gspca_dev->sequence = 0;
+
+       gspca_dev->usb_err = 0;
+
+       /* do the specific subdriver stuff before endpoint selection */
+       intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
+       gspca_dev->alt = gspca_dev->cam.bulk ? intf->num_altsetting : 0;
+       if (gspca_dev->sd_desc->isoc_init) {
+               ret = gspca_dev->sd_desc->isoc_init(gspca_dev);
+               if (ret < 0)
+                       return ret;
+       }
+       xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
+                                  : USB_ENDPOINT_XFER_ISOC;
+
+       /* if bulk or the subdriver forced an altsetting, get the endpoint */
+       if (gspca_dev->alt != 0) {
+               gspca_dev->alt--;       /* (previous version compatibility) */
+               ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer);
+               if (ep == NULL) {
+                       pr_err("bad altsetting %d\n", gspca_dev->alt);
+                       return -EIO;
+               }
+               ep_tb[0].alt = gspca_dev->alt;
+               alt_idx = 1;
+       } else {
+
+       /* else, compute the minimum bandwidth
+        * and build the endpoint table */
+               alt_idx = build_isoc_ep_tb(gspca_dev, intf, ep_tb);
+               if (alt_idx <= 0) {
+                       pr_err("no transfer endpoint found\n");
+                       return -EIO;
+               }
+       }
+
+       /* set the highest alternate setting and
+        * loop until urb submit succeeds */
+       gspca_input_destroy_urb(gspca_dev);
+
+       gspca_dev->alt = ep_tb[--alt_idx].alt;
+       alt = -1;
+       for (;;) {
+               if (alt != gspca_dev->alt) {
+                       alt = gspca_dev->alt;
+                       if (intf->num_altsetting > 1) {
+                               ret = usb_set_interface(gspca_dev->dev,
+                                                       gspca_dev->iface,
+                                                       alt);
+                               if (ret < 0) {
+                                       if (ret == -ENOSPC)
+                                               goto retry; /*fixme: ugly*/
+                                       pr_err("set alt %d err %d\n", alt, ret);
+                                       goto out;
+                               }
+                       }
+               }
+               if (!gspca_dev->cam.no_urb_create) {
+                       PDEBUG(D_STREAM, "init transfer alt %d", alt);
+                       ret = create_urbs(gspca_dev,
+                               alt_xfer(&intf->altsetting[alt], xfer));
+                       if (ret < 0) {
+                               destroy_urbs(gspca_dev);
+                               goto out;
+                       }
+               }
+
+               /* clear the bulk endpoint */
+               if (gspca_dev->cam.bulk)
+                       usb_clear_halt(gspca_dev->dev,
+                                       gspca_dev->urb[0]->pipe);
+
+               /* start the cam */
+               ret = gspca_dev->sd_desc->start(gspca_dev);
+               if (ret < 0) {
+                       destroy_urbs(gspca_dev);
+                       goto out;
+               }
+               gspca_dev->streaming = 1;
+               v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler);
+
+               /* some bulk transfers are started by the subdriver */
+               if (gspca_dev->cam.bulk && gspca_dev->cam.bulk_nurbs == 0)
+                       break;
+
+               /* submit the URBs */
+               for (n = 0; n < MAX_NURBS; n++) {
+                       urb = gspca_dev->urb[n];
+                       if (urb == NULL)
+                               break;
+                       ret = usb_submit_urb(urb, GFP_KERNEL);
+                       if (ret < 0)
+                               break;
+               }
+               if (ret >= 0)
+                       break;                  /* transfer is started */
+
+               /* something when wrong
+                * stop the webcam and free the transfer resources */
+               gspca_stream_off(gspca_dev);
+               if (ret != -ENOSPC) {
+                       pr_err("usb_submit_urb alt %d err %d\n",
+                              gspca_dev->alt, ret);
+                       goto out;
+               }
+
+               /* the bandwidth is not wide enough
+                * negotiate or try a lower alternate setting */
+retry:
+               PDEBUG(D_ERR|D_STREAM,
+                       "alt %d - bandwidth not wide enough - trying again",
+                       alt);
+               msleep(20);     /* wait for kill complete */
+               if (gspca_dev->sd_desc->isoc_nego) {
+                       ret = gspca_dev->sd_desc->isoc_nego(gspca_dev);
+                       if (ret < 0)
+                               goto out;
+               } else {
+                       if (alt_idx <= 0) {
+                               pr_err("no transfer endpoint found\n");
+                               ret = -EIO;
+                               goto out;
+                       }
+                       gspca_dev->alt = ep_tb[--alt_idx].alt;
+               }
+       }
+out:
+       gspca_input_create_urb(gspca_dev);
+       return ret;
+}
+
+static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
+{
+       struct gspca_ctrl *ctrl;
+       int i;
+
+       i = gspca_dev->cam.nmodes - 1;  /* take the highest mode */
+       gspca_dev->curr_mode = i;
+       gspca_dev->width = gspca_dev->cam.cam_mode[i].width;
+       gspca_dev->height = gspca_dev->cam.cam_mode[i].height;
+       gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixelformat;
+
+       /* set the current control values to their default values
+        * which may have changed in sd_init() */
+       /* does nothing if ctrl_handler == NULL */
+       v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler);
+       ctrl = gspca_dev->cam.ctrls;
+       if (ctrl != NULL) {
+               for (i = 0;
+                    i < gspca_dev->sd_desc->nctrls;
+                    i++, ctrl++)
+                       ctrl->val = ctrl->def;
+       }
+}
+
+static int wxh_to_mode(struct gspca_dev *gspca_dev,
+                       int width, int height)
+{
+       int i;
+
+       for (i = gspca_dev->cam.nmodes; --i > 0; ) {
+               if (width >= gspca_dev->cam.cam_mode[i].width
+                   && height >= gspca_dev->cam.cam_mode[i].height)
+                       break;
+       }
+       return i;
+}
+
+/*
+ * search a mode with the right pixel format
+ */
+static int gspca_get_mode(struct gspca_dev *gspca_dev,
+                       int mode,
+                       int pixfmt)
+{
+       int modeU, modeD;
+
+       modeU = modeD = mode;
+       while ((modeU < gspca_dev->cam.nmodes) || modeD >= 0) {
+               if (--modeD >= 0) {
+                       if (gspca_dev->cam.cam_mode[modeD].pixelformat
+                                                               == pixfmt)
+                               return modeD;
+               }
+               if (++modeU < gspca_dev->cam.nmodes) {
+                       if (gspca_dev->cam.cam_mode[modeU].pixelformat
+                                                               == pixfmt)
+                               return modeU;
+               }
+       }
+       return -EINVAL;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register(struct file *file, void *priv,
+                       struct v4l2_dbg_register *reg)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+
+       gspca_dev->usb_err = 0;
+       return gspca_dev->sd_desc->get_register(gspca_dev, reg);
+}
+
+static int vidioc_s_register(struct file *file, void *priv,
+                       struct v4l2_dbg_register *reg)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+
+       gspca_dev->usb_err = 0;
+       return gspca_dev->sd_desc->set_register(gspca_dev, reg);
+}
+#endif
+
+static int vidioc_g_chip_ident(struct file *file, void *priv,
+                       struct v4l2_dbg_chip_ident *chip)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+
+       gspca_dev->usb_err = 0;
+       return gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip);
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+                               struct v4l2_fmtdesc *fmtdesc)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       int i, j, index;
+       __u32 fmt_tb[8];
+
+       /* give an index to each format */
+       index = 0;
+       j = 0;
+       for (i = gspca_dev->cam.nmodes; --i >= 0; ) {
+               fmt_tb[index] = gspca_dev->cam.cam_mode[i].pixelformat;
+               j = 0;
+               for (;;) {
+                       if (fmt_tb[j] == fmt_tb[index])
+                               break;
+                       j++;
+               }
+               if (j == index) {
+                       if (fmtdesc->index == index)
+                               break;          /* new format */
+                       index++;
+                       if (index >= ARRAY_SIZE(fmt_tb))
+                               return -EINVAL;
+               }
+       }
+       if (i < 0)
+               return -EINVAL;         /* no more format */
+
+       fmtdesc->pixelformat = fmt_tb[index];
+       if (gspca_dev->cam.cam_mode[i].sizeimage <
+                       gspca_dev->cam.cam_mode[i].width *
+                               gspca_dev->cam.cam_mode[i].height)
+               fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
+       fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
+       fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
+       fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff;
+       fmtdesc->description[3] = fmtdesc->pixelformat >> 24;
+       fmtdesc->description[4] = '\0';
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                           struct v4l2_format *fmt)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       int mode;
+
+       mode = gspca_dev->curr_mode;
+       fmt->fmt.pix = gspca_dev->cam.cam_mode[mode];
+       /* some drivers use priv internally, zero it before giving it to
+          userspace */
+       fmt->fmt.pix.priv = 0;
+       return 0;
+}
+
+static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
+                       struct v4l2_format *fmt)
+{
+       int w, h, mode, mode2;
+
+       w = fmt->fmt.pix.width;
+       h = fmt->fmt.pix.height;
+
+#ifdef GSPCA_DEBUG
+       if (gspca_debug & D_CONF)
+               PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
+#endif
+       /* search the closest mode for width and height */
+       mode = wxh_to_mode(gspca_dev, w, h);
+
+       /* OK if right palette */
+       if (gspca_dev->cam.cam_mode[mode].pixelformat
+                                               != fmt->fmt.pix.pixelformat) {
+
+               /* else, search the closest mode with the same pixel format */
+               mode2 = gspca_get_mode(gspca_dev, mode,
+                                       fmt->fmt.pix.pixelformat);
+               if (mode2 >= 0)
+                       mode = mode2;
+/*             else
+                       ;                * no chance, return this mode */
+       }
+       fmt->fmt.pix = gspca_dev->cam.cam_mode[mode];
+       /* some drivers use priv internally, zero it before giving it to
+          userspace */
+       fmt->fmt.pix.priv = 0;
+       return mode;                    /* used when s_fmt */
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file,
+                             void *priv,
+                             struct v4l2_format *fmt)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       int ret;
+
+       ret = try_fmt_vid_cap(gspca_dev, fmt);
+       if (ret < 0)
+               return ret;
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                           struct v4l2_format *fmt)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       int ret;
+
+       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
+               return -ERESTARTSYS;
+
+       ret = try_fmt_vid_cap(gspca_dev, fmt);
+       if (ret < 0)
+               goto out;
+
+       if (gspca_dev->nframes != 0
+           && fmt->fmt.pix.sizeimage > gspca_dev->frsz) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (ret == gspca_dev->curr_mode) {
+               ret = 0;
+               goto out;                       /* same mode */
+       }
+
+       if (gspca_dev->streaming) {
+               ret = -EBUSY;
+               goto out;
+       }
+       gspca_dev->width = fmt->fmt.pix.width;
+       gspca_dev->height = fmt->fmt.pix.height;
+       gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
+       gspca_dev->curr_mode = ret;
+
+       ret = 0;
+out:
+       mutex_unlock(&gspca_dev->queue_lock);
+       return ret;
+}
+
+static int vidioc_enum_framesizes(struct file *file, void *priv,
+                                 struct v4l2_frmsizeenum *fsize)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       int i;
+       __u32 index = 0;
+
+       for (i = 0; i < gspca_dev->cam.nmodes; i++) {
+               if (fsize->pixel_format !=
+                               gspca_dev->cam.cam_mode[i].pixelformat)
+                       continue;
+
+               if (fsize->index == index) {
+                       fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+                       fsize->discrete.width =
+                               gspca_dev->cam.cam_mode[i].width;
+                       fsize->discrete.height =
+                               gspca_dev->cam.cam_mode[i].height;
+                       return 0;
+               }
+               index++;
+       }
+
+       return -EINVAL;
+}
+
+static int vidioc_enum_frameintervals(struct file *filp, void *priv,
+                                     struct v4l2_frmivalenum *fival)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(filp);
+       int mode = wxh_to_mode(gspca_dev, fival->width, fival->height);
+       __u32 i;
+
+       if (gspca_dev->cam.mode_framerates == NULL ||
+                       gspca_dev->cam.mode_framerates[mode].nrates == 0)
+               return -EINVAL;
+
+       if (fival->pixel_format !=
+                       gspca_dev->cam.cam_mode[mode].pixelformat)
+               return -EINVAL;
+
+       for (i = 0; i < gspca_dev->cam.mode_framerates[mode].nrates; i++) {
+               if (fival->index == i) {
+                       fival->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+                       fival->discrete.numerator = 1;
+                       fival->discrete.denominator =
+                               gspca_dev->cam.mode_framerates[mode].rates[i];
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static void gspca_release(struct v4l2_device *v4l2_device)
+{
+       struct gspca_dev *gspca_dev =
+               container_of(v4l2_device, struct gspca_dev, v4l2_dev);
+
+       v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler);
+       v4l2_device_unregister(&gspca_dev->v4l2_dev);
+       kfree(gspca_dev->usb_buf);
+       kfree(gspca_dev);
+}
+
+static int dev_open(struct file *file)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+
+       PDEBUG(D_STREAM, "[%s] open", current->comm);
+
+       /* protect the subdriver against rmmod */
+       if (!try_module_get(gspca_dev->module))
+               return -ENODEV;
+
+#ifdef GSPCA_DEBUG
+       /* activate the v4l2 debug */
+       if (gspca_debug & D_V4L2)
+               gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL
+                                       | V4L2_DEBUG_IOCTL_ARG;
+       else
+               gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL
+                                       | V4L2_DEBUG_IOCTL_ARG);
+#endif
+       return v4l2_fh_open(file);
+}
+
+static int dev_close(struct file *file)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+
+       PDEBUG(D_STREAM, "[%s] close", current->comm);
+
+       /* Needed for gspca_stream_off, always lock before queue_lock! */
+       if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+               return -ERESTARTSYS;
+
+       if (mutex_lock_interruptible(&gspca_dev->queue_lock)) {
+               mutex_unlock(&gspca_dev->usb_lock);
+               return -ERESTARTSYS;
+       }
+
+       /* if the file did the capture, free the streaming resources */
+       if (gspca_dev->capt_file == file) {
+               if (gspca_dev->streaming)
+                       gspca_stream_off(gspca_dev);
+               frame_free(gspca_dev);
+       }
+       module_put(gspca_dev->module);
+       mutex_unlock(&gspca_dev->queue_lock);
+       mutex_unlock(&gspca_dev->usb_lock);
+
+       PDEBUG(D_STREAM, "close done");
+
+       return v4l2_fh_release(file);
+}
+
+static int vidioc_querycap(struct file *file, void  *priv,
+                          struct v4l2_capability *cap)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+
+       strlcpy((char *) cap->driver, gspca_dev->sd_desc->name,
+                       sizeof cap->driver);
+       if (gspca_dev->dev->product != NULL) {
+               strlcpy((char *) cap->card, gspca_dev->dev->product,
+                       sizeof cap->card);
+       } else {
+               snprintf((char *) cap->card, sizeof cap->card,
+                       "USB Camera (%04x:%04x)",
+                       le16_to_cpu(gspca_dev->dev->descriptor.idVendor),
+                       le16_to_cpu(gspca_dev->dev->descriptor.idProduct));
+       }
+       usb_make_path(gspca_dev->dev, (char *) cap->bus_info,
+                       sizeof(cap->bus_info));
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
+                         | V4L2_CAP_STREAMING
+                         | V4L2_CAP_READWRITE;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       return 0;
+}
+
+static int get_ctrl(struct gspca_dev *gspca_dev,
+                                  int id)
+{
+       const struct ctrl *ctrls;
+       int i;
+
+       for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
+            i < gspca_dev->sd_desc->nctrls;
+            i++, ctrls++) {
+               if (gspca_dev->ctrl_dis & (1 << i))
+                       continue;
+               if (id == ctrls->qctrl.id)
+                       return i;
+       }
+       return -1;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+                          struct v4l2_queryctrl *q_ctrl)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       const struct ctrl *ctrls;
+       struct gspca_ctrl *gspca_ctrl;
+       int i, idx;
+       u32 id;
+
+       id = q_ctrl->id;
+       if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
+               id &= V4L2_CTRL_ID_MASK;
+               id++;
+               idx = -1;
+               for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
+                       if (gspca_dev->ctrl_dis & (1 << i))
+                               continue;
+                       if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id)
+                               continue;
+                       if (idx >= 0
+                        && gspca_dev->sd_desc->ctrls[i].qctrl.id
+                                   > gspca_dev->sd_desc->ctrls[idx].qctrl.id)
+                               continue;
+                       idx = i;
+               }
+       } else {
+               idx = get_ctrl(gspca_dev, id);
+       }
+       if (idx < 0)
+               return -EINVAL;
+       ctrls = &gspca_dev->sd_desc->ctrls[idx];
+       memcpy(q_ctrl, &ctrls->qctrl, sizeof *q_ctrl);
+       if (gspca_dev->cam.ctrls != NULL) {
+               gspca_ctrl = &gspca_dev->cam.ctrls[idx];
+               q_ctrl->default_value = gspca_ctrl->def;
+               q_ctrl->minimum = gspca_ctrl->min;
+               q_ctrl->maximum = gspca_ctrl->max;
+       }
+       if (gspca_dev->ctrl_inac & (1 << idx))
+               q_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+       return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                        struct v4l2_control *ctrl)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       const struct ctrl *ctrls;
+       struct gspca_ctrl *gspca_ctrl;
+       int idx;
+
+       idx = get_ctrl(gspca_dev, ctrl->id);
+       if (idx < 0)
+               return -EINVAL;
+       if (gspca_dev->ctrl_inac & (1 << idx))
+               return -EINVAL;
+       ctrls = &gspca_dev->sd_desc->ctrls[idx];
+       if (gspca_dev->cam.ctrls != NULL) {
+               gspca_ctrl = &gspca_dev->cam.ctrls[idx];
+               if (ctrl->value < gspca_ctrl->min
+                   || ctrl->value > gspca_ctrl->max)
+                       return -ERANGE;
+       } else {
+               gspca_ctrl = NULL;
+               if (ctrl->value < ctrls->qctrl.minimum
+                   || ctrl->value > ctrls->qctrl.maximum)
+                       return -ERANGE;
+       }
+       PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
+       gspca_dev->usb_err = 0;
+       if (ctrls->set != NULL)
+               return ctrls->set(gspca_dev, ctrl->value);
+       if (gspca_ctrl != NULL) {
+               gspca_ctrl->val = ctrl->value;
+               if (ctrls->set_control != NULL
+                && gspca_dev->streaming)
+                       ctrls->set_control(gspca_dev);
+       }
+       return gspca_dev->usb_err;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+                        struct v4l2_control *ctrl)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       const struct ctrl *ctrls;
+       int idx;
+
+       idx = get_ctrl(gspca_dev, ctrl->id);
+       if (idx < 0)
+               return -EINVAL;
+       ctrls = &gspca_dev->sd_desc->ctrls[idx];
+
+       gspca_dev->usb_err = 0;
+       if (ctrls->get != NULL)
+               return ctrls->get(gspca_dev, &ctrl->value);
+       if (gspca_dev->cam.ctrls != NULL)
+               ctrl->value = gspca_dev->cam.ctrls[idx].val;
+       return 0;
+}
+
+static int vidioc_querymenu(struct file *file, void *priv,
+                           struct v4l2_querymenu *qmenu)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+
+       if (!gspca_dev->sd_desc->querymenu)
+               return -ENOTTY;
+       return gspca_dev->sd_desc->querymenu(gspca_dev, qmenu);
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+                               struct v4l2_input *input)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+
+       if (input->index != 0)
+               return -EINVAL;
+       input->type = V4L2_INPUT_TYPE_CAMERA;
+       input->status = gspca_dev->cam.input_flags;
+       strlcpy(input->name, gspca_dev->sd_desc->name,
+               sizeof input->name);
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       if (i > 0)
+               return -EINVAL;
+       return (0);
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *rb)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       int i, ret = 0, streaming;
+
+       i = rb->memory;                 /* (avoid compilation warning) */
+       switch (i) {
+       case GSPCA_MEMORY_READ:                 /* (internal call) */
+       case V4L2_MEMORY_MMAP:
+       case V4L2_MEMORY_USERPTR:
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
+               return -ERESTARTSYS;
+
+       if (gspca_dev->memory != GSPCA_MEMORY_NO
+           && gspca_dev->memory != GSPCA_MEMORY_READ
+           && gspca_dev->memory != rb->memory) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       /* only one file may do the capture */
+       if (gspca_dev->capt_file != NULL
+           && gspca_dev->capt_file != file) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       /* if allocated, the buffers must not be mapped */
+       for (i = 0; i < gspca_dev->nframes; i++) {
+               if (gspca_dev->frame[i].vma_use_count) {
+                       ret = -EBUSY;
+                       goto out;
+               }
+       }
+
+       /* stop streaming */
+       streaming = gspca_dev->streaming;
+       if (streaming) {
+               gspca_stream_off(gspca_dev);
+
+               /* Don't restart the stream when switching from read
+                * to mmap mode */
+               if (gspca_dev->memory == GSPCA_MEMORY_READ)
+                       streaming = 0;
+       }
+
+       /* free the previous allocated buffers, if any */
+       if (gspca_dev->nframes != 0)
+               frame_free(gspca_dev);
+       if (rb->count == 0)                     /* unrequest */
+               goto out;
+       ret = frame_alloc(gspca_dev, file, rb->memory, rb->count);
+       if (ret == 0) {
+               rb->count = gspca_dev->nframes;
+               if (streaming)
+                       ret = gspca_init_transfer(gspca_dev);
+       }
+out:
+       mutex_unlock(&gspca_dev->queue_lock);
+       PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count);
+       return ret;
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+                          struct v4l2_buffer *v4l2_buf)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       struct gspca_frame *frame;
+
+       if (v4l2_buf->index < 0
+           || v4l2_buf->index >= gspca_dev->nframes)
+               return -EINVAL;
+
+       frame = &gspca_dev->frame[v4l2_buf->index];
+       memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
+       return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv,
+                          enum v4l2_buf_type buf_type)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       int ret;
+
+       if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
+               return -ERESTARTSYS;
+
+       /* check the capture file */
+       if (gspca_dev->capt_file != file) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       if (gspca_dev->nframes == 0
+           || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) {
+               ret = -EINVAL;
+               goto out;
+       }
+       if (!gspca_dev->streaming) {
+               ret = gspca_init_transfer(gspca_dev);
+               if (ret < 0)
+                       goto out;
+       }
+#ifdef GSPCA_DEBUG
+       if (gspca_debug & D_STREAM) {
+               PDEBUG_MODE("stream on OK",
+                       gspca_dev->pixfmt,
+                       gspca_dev->width,
+                       gspca_dev->height);
+       }
+#endif
+       ret = 0;
+out:
+       mutex_unlock(&gspca_dev->queue_lock);
+       return ret;
+}
+
+static int vidioc_streamoff(struct file *file, void *priv,
+                               enum v4l2_buf_type buf_type)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       int i, ret;
+
+       if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
+               return -ERESTARTSYS;
+
+       if (!gspca_dev->streaming) {
+               ret = 0;
+               goto out;
+       }
+
+       /* check the capture file */
+       if (gspca_dev->capt_file != file) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       /* stop streaming */
+       gspca_stream_off(gspca_dev);
+       /* In case another thread is waiting in dqbuf */
+       wake_up_interruptible(&gspca_dev->wq);
+
+       /* empty the transfer queues */
+       for (i = 0; i < gspca_dev->nframes; i++)
+               gspca_dev->frame[i].v4l2_buf.flags &= ~BUF_ALL_FLAGS;
+       atomic_set(&gspca_dev->fr_q, 0);
+       atomic_set(&gspca_dev->fr_i, 0);
+       gspca_dev->fr_o = 0;
+       ret = 0;
+out:
+       mutex_unlock(&gspca_dev->queue_lock);
+       return ret;
+}
+
+static int vidioc_g_jpegcomp(struct file *file, void *priv,
+                       struct v4l2_jpegcompression *jpegcomp)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+
+       gspca_dev->usb_err = 0;
+       return gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
+}
+
+static int vidioc_s_jpegcomp(struct file *file, void *priv,
+                       struct v4l2_jpegcompression *jpegcomp)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+
+       gspca_dev->usb_err = 0;
+       return gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
+}
+
+static int vidioc_g_parm(struct file *filp, void *priv,
+                       struct v4l2_streamparm *parm)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(filp);
+
+       parm->parm.capture.readbuffers = gspca_dev->nbufread;
+
+       if (gspca_dev->sd_desc->get_streamparm) {
+               gspca_dev->usb_err = 0;
+               gspca_dev->sd_desc->get_streamparm(gspca_dev, parm);
+               return gspca_dev->usb_err;
+       }
+       return 0;
+}
+
+static int vidioc_s_parm(struct file *filp, void *priv,
+                       struct v4l2_streamparm *parm)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(filp);
+       int n;
+
+       n = parm->parm.capture.readbuffers;
+       if (n == 0 || n >= GSPCA_MAX_FRAMES)
+               parm->parm.capture.readbuffers = gspca_dev->nbufread;
+       else
+               gspca_dev->nbufread = n;
+
+       if (gspca_dev->sd_desc->set_streamparm) {
+               gspca_dev->usb_err = 0;
+               gspca_dev->sd_desc->set_streamparm(gspca_dev, parm);
+               return gspca_dev->usb_err;
+       }
+
+       return 0;
+}
+
+static int dev_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       struct gspca_frame *frame;
+       struct page *page;
+       unsigned long addr, start, size;
+       int i, ret;
+
+       start = vma->vm_start;
+       size = vma->vm_end - vma->vm_start;
+       PDEBUG(D_STREAM, "mmap start:%08x size:%d", (int) start, (int) size);
+
+       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
+               return -ERESTARTSYS;
+       if (gspca_dev->capt_file != file) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       frame = NULL;
+       for (i = 0; i < gspca_dev->nframes; ++i) {
+               if (gspca_dev->frame[i].v4l2_buf.memory != V4L2_MEMORY_MMAP) {
+                       PDEBUG(D_STREAM, "mmap bad memory type");
+                       break;
+               }
+               if ((gspca_dev->frame[i].v4l2_buf.m.offset >> PAGE_SHIFT)
+                                               == vma->vm_pgoff) {
+                       frame = &gspca_dev->frame[i];
+                       break;
+               }
+       }
+       if (frame == NULL) {
+               PDEBUG(D_STREAM, "mmap no frame buffer found");
+               ret = -EINVAL;
+               goto out;
+       }
+       if (size != frame->v4l2_buf.length) {
+               PDEBUG(D_STREAM, "mmap bad size");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /*
+        * - VM_IO marks the area as being a mmaped region for I/O to a
+        *   device. It also prevents the region from being core dumped.
+        */
+       vma->vm_flags |= VM_IO;
+
+       addr = (unsigned long) frame->data;
+       while (size > 0) {
+               page = vmalloc_to_page((void *) addr);
+               ret = vm_insert_page(vma, start, page);
+               if (ret < 0)
+                       goto out;
+               start += PAGE_SIZE;
+               addr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       vma->vm_ops = &gspca_vm_ops;
+       vma->vm_private_data = frame;
+       gspca_vm_open(vma);
+       ret = 0;
+out:
+       mutex_unlock(&gspca_dev->queue_lock);
+       return ret;
+}
+
+static int frame_ready_nolock(struct gspca_dev *gspca_dev, struct file *file,
+                               enum v4l2_memory memory)
+{
+       if (!gspca_dev->present)
+               return -ENODEV;
+       if (gspca_dev->capt_file != file || gspca_dev->memory != memory ||
+                       !gspca_dev->streaming)
+               return -EINVAL;
+
+       /* check if a frame is ready */
+       return gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i);
+}
+
+static int frame_ready(struct gspca_dev *gspca_dev, struct file *file,
+                       enum v4l2_memory memory)
+{
+       int ret;
+
+       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
+               return -ERESTARTSYS;
+       ret = frame_ready_nolock(gspca_dev, file, memory);
+       mutex_unlock(&gspca_dev->queue_lock);
+       return ret;
+}
+
+/*
+ * dequeue a video buffer
+ *
+ * If nonblock_ing is false, block until a buffer is available.
+ */
+static int vidioc_dqbuf(struct file *file, void *priv,
+                       struct v4l2_buffer *v4l2_buf)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       struct gspca_frame *frame;
+       int i, j, ret;
+
+       PDEBUG(D_FRAM, "dqbuf");
+
+       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
+               return -ERESTARTSYS;
+
+       for (;;) {
+               ret = frame_ready_nolock(gspca_dev, file, v4l2_buf->memory);
+               if (ret < 0)
+                       goto out;
+               if (ret > 0)
+                       break;
+
+               mutex_unlock(&gspca_dev->queue_lock);
+
+               if (file->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+
+               /* wait till a frame is ready */
+               ret = wait_event_interruptible_timeout(gspca_dev->wq,
+                       frame_ready(gspca_dev, file, v4l2_buf->memory),
+                       msecs_to_jiffies(3000));
+               if (ret < 0)
+                       return ret;
+               if (ret == 0)
+                       return -EIO;
+
+               if (mutex_lock_interruptible(&gspca_dev->queue_lock))
+                       return -ERESTARTSYS;
+       }
+
+       i = gspca_dev->fr_o;
+       j = gspca_dev->fr_queue[i];
+       frame = &gspca_dev->frame[j];
+
+       gspca_dev->fr_o = (i + 1) % GSPCA_MAX_FRAMES;
+
+       frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
+       memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
+       PDEBUG(D_FRAM, "dqbuf %d", j);
+       ret = 0;
+
+       if (gspca_dev->memory == V4L2_MEMORY_USERPTR) {
+               if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr,
+                                frame->data,
+                                frame->v4l2_buf.bytesused)) {
+                       PDEBUG(D_ERR|D_STREAM,
+                               "dqbuf cp to user failed");
+                       ret = -EFAULT;
+               }
+       }
+out:
+       mutex_unlock(&gspca_dev->queue_lock);
+
+       if (ret == 0 && gspca_dev->sd_desc->dq_callback) {
+               mutex_lock(&gspca_dev->usb_lock);
+               gspca_dev->usb_err = 0;
+               if (gspca_dev->present)
+                       gspca_dev->sd_desc->dq_callback(gspca_dev);
+               mutex_unlock(&gspca_dev->usb_lock);
+       }
+
+       return ret;
+}
+
+/*
+ * queue a video buffer
+ *
+ * Attempting to queue a buffer that has already been
+ * queued will return -EINVAL.
+ */
+static int vidioc_qbuf(struct file *file, void *priv,
+                       struct v4l2_buffer *v4l2_buf)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       struct gspca_frame *frame;
+       int i, index, ret;
+
+       PDEBUG(D_FRAM, "qbuf %d", v4l2_buf->index);
+
+       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
+               return -ERESTARTSYS;
+
+       index = v4l2_buf->index;
+       if ((unsigned) index >= gspca_dev->nframes) {
+               PDEBUG(D_FRAM,
+                       "qbuf idx %d >= %d", index, gspca_dev->nframes);
+               ret = -EINVAL;
+               goto out;
+       }
+       if (v4l2_buf->memory != gspca_dev->memory) {
+               PDEBUG(D_FRAM, "qbuf bad memory type");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       frame = &gspca_dev->frame[index];
+       if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) {
+               PDEBUG(D_FRAM, "qbuf bad state");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
+
+       if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) {
+               frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr;
+               frame->v4l2_buf.length = v4l2_buf->length;
+       }
+
+       /* put the buffer in the 'queued' queue */
+       i = atomic_read(&gspca_dev->fr_q);
+       gspca_dev->fr_queue[i] = index;
+       atomic_set(&gspca_dev->fr_q, (i + 1) % GSPCA_MAX_FRAMES);
+
+       v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
+       v4l2_buf->flags &= ~V4L2_BUF_FLAG_DONE;
+       ret = 0;
+out:
+       mutex_unlock(&gspca_dev->queue_lock);
+       return ret;
+}
+
+/*
+ * allocate the resources for read()
+ */
+static int read_alloc(struct gspca_dev *gspca_dev,
+                       struct file *file)
+{
+       struct v4l2_buffer v4l2_buf;
+       int i, ret;
+
+       PDEBUG(D_STREAM, "read alloc");
+
+       if (mutex_lock_interruptible(&gspca_dev->usb_lock))
+               return -ERESTARTSYS;
+
+       if (gspca_dev->nframes == 0) {
+               struct v4l2_requestbuffers rb;
+
+               memset(&rb, 0, sizeof rb);
+               rb.count = gspca_dev->nbufread;
+               rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               rb.memory = GSPCA_MEMORY_READ;
+               ret = vidioc_reqbufs(file, gspca_dev, &rb);
+               if (ret != 0) {
+                       PDEBUG(D_STREAM, "read reqbuf err %d", ret);
+                       goto out;
+               }
+               memset(&v4l2_buf, 0, sizeof v4l2_buf);
+               v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               v4l2_buf.memory = GSPCA_MEMORY_READ;
+               for (i = 0; i < gspca_dev->nbufread; i++) {
+                       v4l2_buf.index = i;
+                       ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
+                       if (ret != 0) {
+                               PDEBUG(D_STREAM, "read qbuf err: %d", ret);
+                               goto out;
+                       }
+               }
+       }
+
+       /* start streaming */
+       ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+       if (ret != 0)
+               PDEBUG(D_STREAM, "read streamon err %d", ret);
+out:
+       mutex_unlock(&gspca_dev->usb_lock);
+       return ret;
+}
+
+static unsigned int dev_poll(struct file *file, poll_table *wait)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       unsigned long req_events = poll_requested_events(wait);
+       int ret = 0;
+
+       PDEBUG(D_FRAM, "poll");
+
+       if (req_events & POLLPRI)
+               ret |= v4l2_ctrl_poll(file, wait);
+
+       if (req_events & (POLLIN | POLLRDNORM)) {
+               /* if reqbufs is not done, the user would use read() */
+               if (gspca_dev->memory == GSPCA_MEMORY_NO) {
+                       if (read_alloc(gspca_dev, file) != 0) {
+                               ret |= POLLERR;
+                               goto out;
+                       }
+               }
+
+               poll_wait(file, &gspca_dev->wq, wait);
+
+               /* check if an image has been received */
+               if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0) {
+                       ret |= POLLERR;
+                       goto out;
+               }
+               if (gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i))
+                       ret |= POLLIN | POLLRDNORM;
+               mutex_unlock(&gspca_dev->queue_lock);
+       }
+
+out:
+       if (!gspca_dev->present)
+               ret |= POLLHUP;
+
+       return ret;
+}
+
+static ssize_t dev_read(struct file *file, char __user *data,
+                   size_t count, loff_t *ppos)
+{
+       struct gspca_dev *gspca_dev = video_drvdata(file);
+       struct gspca_frame *frame;
+       struct v4l2_buffer v4l2_buf;
+       struct timeval timestamp;
+       int n, ret, ret2;
+
+       PDEBUG(D_FRAM, "read (%zd)", count);
+       if (gspca_dev->memory == GSPCA_MEMORY_NO) { /* first time ? */
+               ret = read_alloc(gspca_dev, file);
+               if (ret != 0)
+                       return ret;
+       }
+
+       /* get a frame */
+       timestamp = ktime_to_timeval(ktime_get());
+       timestamp.tv_sec--;
+       n = 2;
+       for (;;) {
+               memset(&v4l2_buf, 0, sizeof v4l2_buf);
+               v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               v4l2_buf.memory = GSPCA_MEMORY_READ;
+               ret = vidioc_dqbuf(file, gspca_dev, &v4l2_buf);
+               if (ret != 0) {
+                       PDEBUG(D_STREAM, "read dqbuf err %d", ret);
+                       return ret;
+               }
+
+               /* if the process slept for more than 1 second,
+                * get a newer frame */
+               frame = &gspca_dev->frame[v4l2_buf.index];
+               if (--n < 0)
+                       break;                  /* avoid infinite loop */
+               if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec)
+                       break;
+               ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
+               if (ret != 0) {
+                       PDEBUG(D_STREAM, "read qbuf err %d", ret);
+                       return ret;
+               }
+       }
+
+       /* copy the frame */
+       if (count > frame->v4l2_buf.bytesused)
+               count = frame->v4l2_buf.bytesused;
+       ret = copy_to_user(data, frame->data, count);
+       if (ret != 0) {
+               PDEBUG(D_ERR|D_STREAM,
+                       "read cp to user lack %d / %zd", ret, count);
+               ret = -EFAULT;
+               goto out;
+       }
+       ret = count;
+out:
+       /* in each case, requeue the buffer */
+       ret2 = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
+       if (ret2 != 0)
+               return ret2;
+       return ret;
+}
+
+static struct v4l2_file_operations dev_fops = {
+       .owner = THIS_MODULE,
+       .open = dev_open,
+       .release = dev_close,
+       .read = dev_read,
+       .mmap = dev_mmap,
+       .unlocked_ioctl = video_ioctl2,
+       .poll   = dev_poll,
+};
+
+static const struct v4l2_ioctl_ops dev_ioctl_ops = {
+       .vidioc_querycap        = vidioc_querycap,
+       .vidioc_dqbuf           = vidioc_dqbuf,
+       .vidioc_qbuf            = vidioc_qbuf,
+       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap   = vidioc_g_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap   = vidioc_s_fmt_vid_cap,
+       .vidioc_streamon        = vidioc_streamon,
+       .vidioc_queryctrl       = vidioc_queryctrl,
+       .vidioc_g_ctrl          = vidioc_g_ctrl,
+       .vidioc_s_ctrl          = vidioc_s_ctrl,
+       .vidioc_querymenu       = vidioc_querymenu,
+       .vidioc_enum_input      = vidioc_enum_input,
+       .vidioc_g_input         = vidioc_g_input,
+       .vidioc_s_input         = vidioc_s_input,
+       .vidioc_reqbufs         = vidioc_reqbufs,
+       .vidioc_querybuf        = vidioc_querybuf,
+       .vidioc_streamoff       = vidioc_streamoff,
+       .vidioc_g_jpegcomp      = vidioc_g_jpegcomp,
+       .vidioc_s_jpegcomp      = vidioc_s_jpegcomp,
+       .vidioc_g_parm          = vidioc_g_parm,
+       .vidioc_s_parm          = vidioc_s_parm,
+       .vidioc_enum_framesizes = vidioc_enum_framesizes,
+       .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register      = vidioc_g_register,
+       .vidioc_s_register      = vidioc_s_register,
+#endif
+       .vidioc_g_chip_ident    = vidioc_g_chip_ident,
+       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static const struct video_device gspca_template = {
+       .name = "gspca main driver",
+       .fops = &dev_fops,
+       .ioctl_ops = &dev_ioctl_ops,
+       .release = video_device_release_empty, /* We use v4l2_dev.release */
+};
+
+/* initialize the controls */
+static void ctrls_init(struct gspca_dev *gspca_dev)
+{
+       struct gspca_ctrl *ctrl;
+       int i;
+
+       for (i = 0, ctrl = gspca_dev->cam.ctrls;
+            i < gspca_dev->sd_desc->nctrls;
+            i++, ctrl++) {
+               ctrl->def = gspca_dev->sd_desc->ctrls[i].qctrl.default_value;
+               ctrl->val = ctrl->def;
+               ctrl->min = gspca_dev->sd_desc->ctrls[i].qctrl.minimum;
+               ctrl->max = gspca_dev->sd_desc->ctrls[i].qctrl.maximum;
+       }
+}
+
+/*
+ * probe and create a new gspca device
+ *
+ * This function must be called by the sub-driver when it is
+ * called for probing a new device.
+ */
+int gspca_dev_probe2(struct usb_interface *intf,
+               const struct usb_device_id *id,
+               const struct sd_desc *sd_desc,
+               int dev_size,
+               struct module *module)
+{
+       struct gspca_dev *gspca_dev;
+       struct usb_device *dev = interface_to_usbdev(intf);
+       int ret;
+
+       pr_info("%s-" GSPCA_VERSION " probing %04x:%04x\n",
+               sd_desc->name, id->idVendor, id->idProduct);
+
+       /* create the device */
+       if (dev_size < sizeof *gspca_dev)
+               dev_size = sizeof *gspca_dev;
+       gspca_dev = kzalloc(dev_size, GFP_KERNEL);
+       if (!gspca_dev) {
+               pr_err("couldn't kzalloc gspca struct\n");
+               return -ENOMEM;
+       }
+       gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL);
+       if (!gspca_dev->usb_buf) {
+               pr_err("out of memory\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+       gspca_dev->dev = dev;
+       gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber;
+
+       /* check if any audio device */
+       if (dev->actconfig->desc.bNumInterfaces != 1) {
+               int i;
+               struct usb_interface *intf2;
+
+               for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
+                       intf2 = dev->actconfig->interface[i];
+                       if (intf2 != NULL
+                        && intf2->altsetting != NULL
+                        && intf2->altsetting->desc.bInterfaceClass ==
+                                        USB_CLASS_AUDIO) {
+                               gspca_dev->audio = 1;
+                               break;
+                       }
+               }
+       }
+
+       gspca_dev->v4l2_dev.release = gspca_release;
+       ret = v4l2_device_register(&intf->dev, &gspca_dev->v4l2_dev);
+       if (ret)
+               goto out;
+       gspca_dev->sd_desc = sd_desc;
+       gspca_dev->nbufread = 2;
+       gspca_dev->empty_packet = -1;   /* don't check the empty packets */
+       gspca_dev->vdev = gspca_template;
+       gspca_dev->vdev.v4l2_dev = &gspca_dev->v4l2_dev;
+       video_set_drvdata(&gspca_dev->vdev, gspca_dev);
+       set_bit(V4L2_FL_USE_FH_PRIO, &gspca_dev->vdev.flags);
+       gspca_dev->module = module;
+       gspca_dev->present = 1;
+
+       mutex_init(&gspca_dev->usb_lock);
+       gspca_dev->vdev.lock = &gspca_dev->usb_lock;
+       mutex_init(&gspca_dev->queue_lock);
+       init_waitqueue_head(&gspca_dev->wq);
+
+       /* configure the subdriver and initialize the USB device */
+       ret = sd_desc->config(gspca_dev, id);
+       if (ret < 0)
+               goto out;
+       if (gspca_dev->cam.ctrls != NULL)
+               ctrls_init(gspca_dev);
+       ret = sd_desc->init(gspca_dev);
+       if (ret < 0)
+               goto out;
+       if (sd_desc->init_controls)
+               ret = sd_desc->init_controls(gspca_dev);
+       if (ret < 0)
+               goto out;
+       gspca_set_default_mode(gspca_dev);
+
+       ret = gspca_input_connect(gspca_dev);
+       if (ret)
+               goto out;
+
+       /*
+        * Don't take usb_lock for these ioctls. This improves latency if
+        * usb_lock is taken for a long time, e.g. when changing a control
+        * value, and a new frame is ready to be dequeued.
+        */
+       v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_DQBUF);
+       v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_QBUF);
+       v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_QUERYBUF);
+       if (!gspca_dev->sd_desc->get_chip_ident)
+               v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_G_CHIP_IDENT);
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       if (!gspca_dev->sd_desc->get_chip_ident ||
+           !gspca_dev->sd_desc->get_register)
+               v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_G_REGISTER);
+       if (!gspca_dev->sd_desc->get_chip_ident ||
+           !gspca_dev->sd_desc->set_register)
+               v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_S_REGISTER);
+#endif
+       if (!gspca_dev->sd_desc->get_jcomp)
+               v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_G_JPEGCOMP);
+       if (!gspca_dev->sd_desc->set_jcomp)
+               v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_S_JPEGCOMP);
+
+       /* init video stuff */
+       ret = video_register_device(&gspca_dev->vdev,
+                                 VFL_TYPE_GRABBER,
+                                 -1);
+       if (ret < 0) {
+               pr_err("video_register_device err %d\n", ret);
+               goto out;
+       }
+
+       usb_set_intfdata(intf, gspca_dev);
+       PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev));
+
+       gspca_input_create_urb(gspca_dev);
+
+       return 0;
+out:
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       if (gspca_dev->input_dev)
+               input_unregister_device(gspca_dev->input_dev);
+#endif
+       v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler);
+       kfree(gspca_dev->usb_buf);
+       kfree(gspca_dev);
+       return ret;
+}
+EXPORT_SYMBOL(gspca_dev_probe2);
+
+/* same function as the previous one, but check the interface */
+int gspca_dev_probe(struct usb_interface *intf,
+               const struct usb_device_id *id,
+               const struct sd_desc *sd_desc,
+               int dev_size,
+               struct module *module)
+{
+       struct usb_device *dev = interface_to_usbdev(intf);
+
+       /* we don't handle multi-config cameras */
+       if (dev->descriptor.bNumConfigurations != 1) {
+               pr_err("%04x:%04x too many config\n",
+                      id->idVendor, id->idProduct);
+               return -ENODEV;
+       }
+
+       /* the USB video interface must be the first one */
+       if (dev->actconfig->desc.bNumInterfaces != 1
+        && intf->cur_altsetting->desc.bInterfaceNumber != 0)
+               return -ENODEV;
+
+       return gspca_dev_probe2(intf, id, sd_desc, dev_size, module);
+}
+EXPORT_SYMBOL(gspca_dev_probe);
+
+/*
+ * USB disconnection
+ *
+ * This function must be called by the sub-driver
+ * when the device disconnects, after the specific resources are freed.
+ */
+void gspca_disconnect(struct usb_interface *intf)
+{
+       struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       struct input_dev *input_dev;
+#endif
+
+       PDEBUG(D_PROBE, "%s disconnect",
+               video_device_node_name(&gspca_dev->vdev));
+
+       mutex_lock(&gspca_dev->usb_lock);
+
+       usb_set_intfdata(intf, NULL);
+       gspca_dev->dev = NULL;
+       gspca_dev->present = 0;
+       destroy_urbs(gspca_dev);
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       gspca_input_destroy_urb(gspca_dev);
+       input_dev = gspca_dev->input_dev;
+       if (input_dev) {
+               gspca_dev->input_dev = NULL;
+               input_unregister_device(input_dev);
+       }
+#endif
+       /* Free subdriver's streaming resources / stop sd workqueue(s) */
+       if (gspca_dev->sd_desc->stop0 && gspca_dev->streaming)
+               gspca_dev->sd_desc->stop0(gspca_dev);
+       gspca_dev->streaming = 0;
+       wake_up_interruptible(&gspca_dev->wq);
+
+       v4l2_device_disconnect(&gspca_dev->v4l2_dev);
+       video_unregister_device(&gspca_dev->vdev);
+
+       mutex_unlock(&gspca_dev->usb_lock);
+
+       /* (this will call gspca_release() immediately or on last close) */
+       v4l2_device_put(&gspca_dev->v4l2_dev);
+}
+EXPORT_SYMBOL(gspca_disconnect);
+
+#ifdef CONFIG_PM
+int gspca_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+
+       if (!gspca_dev->streaming)
+               return 0;
+       mutex_lock(&gspca_dev->usb_lock);
+       gspca_dev->frozen = 1;          /* avoid urb error messages */
+       gspca_dev->usb_err = 0;
+       if (gspca_dev->sd_desc->stopN)
+               gspca_dev->sd_desc->stopN(gspca_dev);
+       destroy_urbs(gspca_dev);
+       gspca_input_destroy_urb(gspca_dev);
+       gspca_set_alt0(gspca_dev);
+       if (gspca_dev->sd_desc->stop0)
+               gspca_dev->sd_desc->stop0(gspca_dev);
+       mutex_unlock(&gspca_dev->usb_lock);
+       return 0;
+}
+EXPORT_SYMBOL(gspca_suspend);
+
+int gspca_resume(struct usb_interface *intf)
+{
+       struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+       int streaming, ret = 0;
+
+       mutex_lock(&gspca_dev->usb_lock);
+       gspca_dev->frozen = 0;
+       gspca_dev->usb_err = 0;
+       gspca_dev->sd_desc->init(gspca_dev);
+       gspca_input_create_urb(gspca_dev);
+       /*
+        * Most subdrivers send all ctrl values on sd_start and thus
+        * only write to the device registers on s_ctrl when streaming ->
+        * Clear streaming to avoid setting all ctrls twice.
+        */
+       streaming = gspca_dev->streaming;
+       gspca_dev->streaming = 0;
+       if (streaming)
+               ret = gspca_init_transfer(gspca_dev);
+       mutex_unlock(&gspca_dev->usb_lock);
+       return ret;
+}
+EXPORT_SYMBOL(gspca_resume);
+#endif
+
+/* -- module insert / remove -- */
+static int __init gspca_init(void)
+{
+       pr_info("v" GSPCA_VERSION " registered\n");
+       return 0;
+}
+static void __exit gspca_exit(void)
+{
+}
+
+module_init(gspca_init);
+module_exit(gspca_exit);
+
+#ifdef GSPCA_DEBUG
+module_param_named(debug, gspca_debug, int, 0644);
+MODULE_PARM_DESC(debug,
+               "Debug (bit) 0x01:error 0x02:probe 0x04:config"
+               " 0x08:stream 0x10:frame 0x20:packet"
+               " 0x0100: v4l2");
+#endif
diff --git a/drivers/media/usb/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h
new file mode 100644 (file)
index 0000000..dc688c7
--- /dev/null
@@ -0,0 +1,259 @@
+#ifndef GSPCAV2_H
+#define GSPCAV2_H
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <linux/mutex.h>
+
+/* compilation option */
+/*#define GSPCA_DEBUG 1*/
+
+#ifdef GSPCA_DEBUG
+/* GSPCA our debug messages */
+extern int gspca_debug;
+#define PDEBUG(level, fmt, ...)                                        \
+do {                                                           \
+       if (gspca_debug & (level))                              \
+               pr_info(fmt, ##__VA_ARGS__);                    \
+} while (0)
+
+#define D_ERR  0x01
+#define D_PROBE 0x02
+#define D_CONF 0x04
+#define D_STREAM 0x08
+#define D_FRAM 0x10
+#define D_PACK 0x20
+#define D_USBI 0x00
+#define D_USBO 0x00
+#define D_V4L2 0x0100
+#else
+#define PDEBUG(level, fmt, ...)
+#endif
+
+#define GSPCA_MAX_FRAMES 16    /* maximum number of video frame buffers */
+/* image transfers */
+#define MAX_NURBS 4            /* max number of URBs */
+
+
+/* used to list framerates supported by a camera mode (resolution) */
+struct framerates {
+       const u8 *rates;
+       int nrates;
+};
+
+/* control definition */
+struct gspca_ctrl {
+       s16 val;        /* current value */
+       s16 def;        /* default value */
+       s16 min, max;   /* minimum and maximum values */
+};
+
+/* device information - set at probe time */
+struct cam {
+       const struct v4l2_pix_format *cam_mode; /* size nmodes */
+       const struct framerates *mode_framerates; /* must have size nmodes,
+                                                  * just like cam_mode */
+       struct gspca_ctrl *ctrls;       /* control table - size nctrls */
+                                       /* may be NULL */
+       u32 bulk_size;          /* buffer size when image transfer by bulk */
+       u32 input_flags;        /* value for ENUM_INPUT status flags */
+       u8 nmodes;              /* size of cam_mode */
+       u8 no_urb_create;       /* don't create transfer URBs */
+       u8 bulk_nurbs;          /* number of URBs in bulk mode
+                                * - cannot be > MAX_NURBS
+                                * - when 0 and bulk_size != 0 means
+                                *   1 URB and submit done by subdriver */
+       u8 bulk;                /* image transfer by 0:isoc / 1:bulk */
+       u8 npkt;                /* number of packets in an ISOC message
+                                * 0 is the default value: 32 packets */
+       u8 needs_full_bandwidth;/* Set this flag to notify the bandwidth calc.
+                                * code that the cam fills all image buffers to
+                                * the max, even when using compression. */
+};
+
+struct gspca_dev;
+struct gspca_frame;
+
+/* subdriver operations */
+typedef int (*cam_op) (struct gspca_dev *);
+typedef void (*cam_v_op) (struct gspca_dev *);
+typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *);
+typedef int (*cam_jpg_op) (struct gspca_dev *,
+                               struct v4l2_jpegcompression *);
+typedef int (*cam_reg_op) (struct gspca_dev *,
+                               struct v4l2_dbg_register *);
+typedef int (*cam_ident_op) (struct gspca_dev *,
+                               struct v4l2_dbg_chip_ident *);
+typedef void (*cam_streamparm_op) (struct gspca_dev *,
+                                 struct v4l2_streamparm *);
+typedef int (*cam_qmnu_op) (struct gspca_dev *,
+                       struct v4l2_querymenu *);
+typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev,
+                               u8 *data,
+                               int len);
+typedef int (*cam_int_pkt_op) (struct gspca_dev *gspca_dev,
+                               u8 *data,
+                               int len);
+
+struct ctrl {
+       struct v4l2_queryctrl qctrl;
+       int (*set)(struct gspca_dev *, __s32);
+       int (*get)(struct gspca_dev *, __s32 *);
+       cam_v_op set_control;
+};
+
+/* subdriver description */
+struct sd_desc {
+/* information */
+       const char *name;       /* sub-driver name */
+/* controls */
+       const struct ctrl *ctrls;       /* static control definition */
+       int nctrls;
+/* mandatory operations */
+       cam_cf_op config;       /* called on probe */
+       cam_op init;            /* called on probe and resume */
+       cam_op init_controls;   /* called on probe */
+       cam_op start;           /* called on stream on after URBs creation */
+       cam_pkt_op pkt_scan;
+/* optional operations */
+       cam_op isoc_init;       /* called on stream on before getting the EP */
+       cam_op isoc_nego;       /* called when URB submit failed with NOSPC */
+       cam_v_op stopN;         /* called on stream off - main alt */
+       cam_v_op stop0;         /* called on stream off & disconnect - alt 0 */
+       cam_v_op dq_callback;   /* called when a frame has been dequeued */
+       cam_jpg_op get_jcomp;
+       cam_jpg_op set_jcomp;
+       cam_qmnu_op querymenu;
+       cam_streamparm_op get_streamparm;
+       cam_streamparm_op set_streamparm;
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       cam_reg_op set_register;
+       cam_reg_op get_register;
+#endif
+       cam_ident_op get_chip_ident;
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       cam_int_pkt_op int_pkt_scan;
+       /* other_input makes the gspca core create gspca_dev->input even when
+          int_pkt_scan is NULL, for cams with non interrupt driven buttons */
+       u8 other_input;
+#endif
+};
+
+/* packet types when moving from iso buf to frame buf */
+enum gspca_packet_type {
+       DISCARD_PACKET,
+       FIRST_PACKET,
+       INTER_PACKET,
+       LAST_PACKET
+};
+
+struct gspca_frame {
+       __u8 *data;                     /* frame buffer */
+       int vma_use_count;
+       struct v4l2_buffer v4l2_buf;
+};
+
+struct gspca_dev {
+       struct video_device vdev;       /* !! must be the first item */
+       struct module *module;          /* subdriver handling the device */
+       struct v4l2_device v4l2_dev;
+       struct usb_device *dev;
+       struct file *capt_file;         /* file doing video capture */
+                                       /* protected by queue_lock */
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       struct input_dev *input_dev;
+       char phys[64];                  /* physical device path */
+#endif
+
+       struct cam cam;                         /* device information */
+       const struct sd_desc *sd_desc;          /* subdriver description */
+       unsigned ctrl_dis;              /* disabled controls (bit map) */
+       unsigned ctrl_inac;             /* inactive controls (bit map) */
+       struct v4l2_ctrl_handler ctrl_handler;
+
+       /* autogain and exposure or gain control cluster, these are global as
+          the autogain/exposure functions in autogain_functions.c use them */
+       struct {
+               struct v4l2_ctrl *autogain;
+               struct v4l2_ctrl *exposure;
+               struct v4l2_ctrl *gain;
+               int exp_too_low_cnt, exp_too_high_cnt;
+       };
+
+#define USB_BUF_SZ 64
+       __u8 *usb_buf;                          /* buffer for USB exchanges */
+       struct urb *urb[MAX_NURBS];
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       struct urb *int_urb;
+#endif
+
+       __u8 *frbuf;                            /* buffer for nframes */
+       struct gspca_frame frame[GSPCA_MAX_FRAMES];
+       u8 *image;                              /* image beeing filled */
+       __u32 frsz;                             /* frame size */
+       u32 image_len;                          /* current length of image */
+       atomic_t fr_q;                          /* next frame to queue */
+       atomic_t fr_i;                          /* frame being filled */
+       signed char fr_queue[GSPCA_MAX_FRAMES]; /* frame queue */
+       char nframes;                           /* number of frames */
+       u8 fr_o;                                /* next frame to dequeue */
+       __u8 last_packet_type;
+       __s8 empty_packet;              /* if (-1) don't check empty packets */
+       __u8 streaming;                 /* protected by both mutexes (*) */
+
+       __u8 curr_mode;                 /* current camera mode */
+       __u32 pixfmt;                   /* current mode parameters */
+       __u16 width;
+       __u16 height;
+       __u32 sequence;                 /* frame sequence number */
+
+       wait_queue_head_t wq;           /* wait queue */
+       struct mutex usb_lock;          /* usb exchange protection */
+       struct mutex queue_lock;        /* ISOC queue protection */
+       int usb_err;                    /* USB error - protected by usb_lock */
+       u16 pkt_size;                   /* ISOC packet size */
+#ifdef CONFIG_PM
+       char frozen;                    /* suspend - resume */
+#endif
+       char present;                   /* device connected */
+       char nbufread;                  /* number of buffers for read() */
+       char memory;                    /* memory type (V4L2_MEMORY_xxx) */
+       __u8 iface;                     /* USB interface number */
+       __u8 alt;                       /* USB alternate setting */
+       u8 audio;                       /* presence of audio device */
+
+       /* (*) These variables are proteced by both usb_lock and queue_lock,
+          that is any code setting them is holding *both*, which means that
+          any code getting them needs to hold at least one of them */
+};
+
+int gspca_dev_probe(struct usb_interface *intf,
+               const struct usb_device_id *id,
+               const struct sd_desc *sd_desc,
+               int dev_size,
+               struct module *module);
+int gspca_dev_probe2(struct usb_interface *intf,
+               const struct usb_device_id *id,
+               const struct sd_desc *sd_desc,
+               int dev_size,
+               struct module *module);
+void gspca_disconnect(struct usb_interface *intf);
+void gspca_frame_add(struct gspca_dev *gspca_dev,
+                       enum gspca_packet_type packet_type,
+                       const u8 *data,
+                       int len);
+#ifdef CONFIG_PM
+int gspca_suspend(struct usb_interface *intf, pm_message_t message);
+int gspca_resume(struct usb_interface *intf);
+#endif
+int gspca_expo_autogain(struct gspca_dev *gspca_dev, int avg_lum,
+       int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee);
+int gspca_coarse_grained_expo_autogain(struct gspca_dev *gspca_dev,
+        int avg_lum, int desired_avg_lum, int deadzone);
+
+#endif /* GSPCAV2_H */
diff --git a/drivers/media/usb/gspca/jeilinj.c b/drivers/media/usb/gspca/jeilinj.c
new file mode 100644 (file)
index 0000000..26b9931
--- /dev/null
@@ -0,0 +1,548 @@
+/*
+ * Jeilinj subdriver
+ *
+ * Supports some Jeilin dual-mode cameras which use bulk transport and
+ * download raw JPEG data.
+ *
+ * Copyright (C) 2009 Theodore Kilgore
+ *
+ * Sportscam DV15 support and control settings are
+ * Copyright (C) 2011 Patrice Chotard
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "jeilinj"
+
+#include <linux/slab.h>
+#include "gspca.h"
+#include "jpeg.h"
+
+MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
+MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* Default timeouts, in ms */
+#define JEILINJ_CMD_TIMEOUT 500
+#define JEILINJ_CMD_DELAY 160
+#define JEILINJ_DATA_TIMEOUT 1000
+
+/* Maximum transfer size to use. */
+#define JEILINJ_MAX_TRANSFER 0x200
+#define FRAME_HEADER_LEN 0x10
+#define FRAME_START 0xFFFFFFFF
+
+enum {
+       SAKAR_57379,
+       SPORTSCAM_DV15,
+};
+
+#define CAMQUALITY_MIN 0       /* highest cam quality */
+#define CAMQUALITY_MAX 97      /* lowest cam quality  */
+
+/* Structure to hold all of our device specific stuff */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+       int blocks_left;
+       const struct v4l2_pix_format *cap_mode;
+       struct v4l2_ctrl *freq;
+       struct v4l2_ctrl *jpegqual;
+       /* Driver stuff */
+       u8 type;
+       u8 quality;                              /* image quality */
+#define QUALITY_MIN 35
+#define QUALITY_MAX 85
+#define QUALITY_DEF 85
+       u8 jpeg_hdr[JPEG_HDR_SZ];
+};
+
+struct jlj_command {
+       unsigned char instruction[2];
+       unsigned char ack_wanted;
+       unsigned char delay;
+};
+
+/* AFAICT these cameras will only do 320x240. */
+static struct v4l2_pix_format jlj_mode[] = {
+       { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+       { 640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0}
+};
+
+/*
+ * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
+ * and 0x82 for bulk transfer.
+ */
+
+/* All commands are two bytes only */
+static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)
+{
+       int retval;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       memcpy(gspca_dev->usb_buf, command, 2);
+       retval = usb_bulk_msg(gspca_dev->dev,
+                       usb_sndbulkpipe(gspca_dev->dev, 3),
+                       gspca_dev->usb_buf, 2, NULL, 500);
+       if (retval < 0) {
+               pr_err("command write [%02x] error %d\n",
+                      gspca_dev->usb_buf[0], retval);
+               gspca_dev->usb_err = retval;
+       }
+}
+
+/* Responses are one byte only */
+static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char response)
+{
+       int retval;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       retval = usb_bulk_msg(gspca_dev->dev,
+       usb_rcvbulkpipe(gspca_dev->dev, 0x84),
+                               gspca_dev->usb_buf, 1, NULL, 500);
+       response = gspca_dev->usb_buf[0];
+       if (retval < 0) {
+               pr_err("read command [%02x] error %d\n",
+                      gspca_dev->usb_buf[0], retval);
+               gspca_dev->usb_err = retval;
+       }
+}
+
+static void setfreq(struct gspca_dev *gspca_dev, s32 val)
+{
+       u8 freq_commands[][2] = {
+               {0x71, 0x80},
+               {0x70, 0x07}
+       };
+
+       freq_commands[0][1] |= val >> 1;
+
+       jlj_write2(gspca_dev, freq_commands[0]);
+       jlj_write2(gspca_dev, freq_commands[1]);
+}
+
+static void setcamquality(struct gspca_dev *gspca_dev, s32 val)
+{
+       u8 quality_commands[][2] = {
+               {0x71, 0x1E},
+               {0x70, 0x06}
+       };
+       u8 camquality;
+
+       /* adapt camera quality from jpeg quality */
+       camquality = ((QUALITY_MAX - val) * CAMQUALITY_MAX)
+               / (QUALITY_MAX - QUALITY_MIN);
+       quality_commands[0][1] += camquality;
+
+       jlj_write2(gspca_dev, quality_commands[0]);
+       jlj_write2(gspca_dev, quality_commands[1]);
+}
+
+static void setautogain(struct gspca_dev *gspca_dev, s32 val)
+{
+       u8 autogain_commands[][2] = {
+               {0x94, 0x02},
+               {0xcf, 0x00}
+       };
+
+       autogain_commands[1][1] = val << 4;
+
+       jlj_write2(gspca_dev, autogain_commands[0]);
+       jlj_write2(gspca_dev, autogain_commands[1]);
+}
+
+static void setred(struct gspca_dev *gspca_dev, s32 val)
+{
+       u8 setred_commands[][2] = {
+               {0x94, 0x02},
+               {0xe6, 0x00}
+       };
+
+       setred_commands[1][1] = val;
+
+       jlj_write2(gspca_dev, setred_commands[0]);
+       jlj_write2(gspca_dev, setred_commands[1]);
+}
+
+static void setgreen(struct gspca_dev *gspca_dev, s32 val)
+{
+       u8 setgreen_commands[][2] = {
+               {0x94, 0x02},
+               {0xe7, 0x00}
+       };
+
+       setgreen_commands[1][1] = val;
+
+       jlj_write2(gspca_dev, setgreen_commands[0]);
+       jlj_write2(gspca_dev, setgreen_commands[1]);
+}
+
+static void setblue(struct gspca_dev *gspca_dev, s32 val)
+{
+       u8 setblue_commands[][2] = {
+               {0x94, 0x02},
+               {0xe9, 0x00}
+       };
+
+       setblue_commands[1][1] = val;
+
+       jlj_write2(gspca_dev, setblue_commands[0]);
+       jlj_write2(gspca_dev, setblue_commands[1]);
+}
+
+static int jlj_start(struct gspca_dev *gspca_dev)
+{
+       int i;
+       int start_commands_size;
+       u8 response = 0xff;
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct jlj_command start_commands[] = {
+               {{0x71, 0x81}, 0, 0},
+               {{0x70, 0x05}, 0, JEILINJ_CMD_DELAY},
+               {{0x95, 0x70}, 1, 0},
+               {{0x71, 0x81 - gspca_dev->curr_mode}, 0, 0},
+               {{0x70, 0x04}, 0, JEILINJ_CMD_DELAY},
+               {{0x95, 0x70}, 1, 0},
+               {{0x71, 0x00}, 0, 0},   /* start streaming ??*/
+               {{0x70, 0x08}, 0, JEILINJ_CMD_DELAY},
+               {{0x95, 0x70}, 1, 0},
+#define SPORTSCAM_DV15_CMD_SIZE 9
+               {{0x94, 0x02}, 0, 0},
+               {{0xde, 0x24}, 0, 0},
+               {{0x94, 0x02}, 0, 0},
+               {{0xdd, 0xf0}, 0, 0},
+               {{0x94, 0x02}, 0, 0},
+               {{0xe3, 0x2c}, 0, 0},
+               {{0x94, 0x02}, 0, 0},
+               {{0xe4, 0x00}, 0, 0},
+               {{0x94, 0x02}, 0, 0},
+               {{0xe5, 0x00}, 0, 0},
+               {{0x94, 0x02}, 0, 0},
+               {{0xe6, 0x2c}, 0, 0},
+               {{0x94, 0x03}, 0, 0},
+               {{0xaa, 0x00}, 0, 0}
+       };
+
+       sd->blocks_left = 0;
+       /* Under Windows, USB spy shows that only the 9 first start
+        * commands are used for SPORTSCAM_DV15 webcam
+        */
+       if (sd->type == SPORTSCAM_DV15)
+               start_commands_size = SPORTSCAM_DV15_CMD_SIZE;
+       else
+               start_commands_size = ARRAY_SIZE(start_commands);
+
+       for (i = 0; i < start_commands_size; i++) {
+               jlj_write2(gspca_dev, start_commands[i].instruction);
+               if (start_commands[i].delay)
+                       msleep(start_commands[i].delay);
+               if (start_commands[i].ack_wanted)
+                       jlj_read1(gspca_dev, response);
+       }
+       setcamquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
+       msleep(2);
+       setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
+       if (gspca_dev->usb_err < 0)
+               PDEBUG(D_ERR, "Start streaming command failed");
+       return gspca_dev->usb_err;
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data, int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int packet_type;
+       u32 header_marker;
+
+       PDEBUG(D_STREAM, "Got %d bytes out of %d for Block 0",
+                       len, JEILINJ_MAX_TRANSFER);
+       if (len != JEILINJ_MAX_TRANSFER) {
+               PDEBUG(D_PACK, "bad length");
+               goto discard;
+       }
+       /* check if it's start of frame */
+       header_marker = ((u32 *)data)[0];
+       if (header_marker == FRAME_START) {
+               sd->blocks_left = data[0x0a] - 1;
+               PDEBUG(D_STREAM, "blocks_left = 0x%x", sd->blocks_left);
+               /* Start a new frame, and add the JPEG header, first thing */
+               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                               sd->jpeg_hdr, JPEG_HDR_SZ);
+               /* Toss line 0 of data block 0, keep the rest. */
+               gspca_frame_add(gspca_dev, INTER_PACKET,
+                               data + FRAME_HEADER_LEN,
+                               JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN);
+       } else if (sd->blocks_left > 0) {
+               PDEBUG(D_STREAM, "%d blocks remaining for frame",
+                               sd->blocks_left);
+               sd->blocks_left -= 1;
+               if (sd->blocks_left == 0)
+                       packet_type = LAST_PACKET;
+               else
+                       packet_type = INTER_PACKET;
+               gspca_frame_add(gspca_dev, packet_type,
+                               data, JEILINJ_MAX_TRANSFER);
+       } else
+               goto discard;
+       return;
+discard:
+       /* Discard data until a new frame starts. */
+       gspca_dev->last_packet_type = DISCARD_PACKET;
+}
+
+/* This function is called at probe time just before sd_init */
+static int sd_config(struct gspca_dev *gspca_dev,
+               const struct usb_device_id *id)
+{
+       struct cam *cam = &gspca_dev->cam;
+       struct sd *dev  = (struct sd *) gspca_dev;
+
+       dev->type = id->driver_info;
+       dev->quality = QUALITY_DEF;
+
+       cam->cam_mode = jlj_mode;
+       cam->nmodes = ARRAY_SIZE(jlj_mode);
+       cam->bulk = 1;
+       cam->bulk_nurbs = 1;
+       cam->bulk_size = JEILINJ_MAX_TRANSFER;
+       return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       int i;
+       u8 *buf;
+       static u8 stop_commands[][2] = {
+               {0x71, 0x00},
+               {0x70, 0x09},
+               {0x71, 0x80},
+               {0x70, 0x05}
+       };
+
+       for (;;) {
+               /* get the image remaining blocks */
+               usb_bulk_msg(gspca_dev->dev,
+                               gspca_dev->urb[0]->pipe,
+                               gspca_dev->urb[0]->transfer_buffer,
+                               JEILINJ_MAX_TRANSFER, NULL,
+                               JEILINJ_DATA_TIMEOUT);
+
+               /* search for 0xff 0xd9  (EOF for JPEG) */
+               i = 0;
+               buf = gspca_dev->urb[0]->transfer_buffer;
+               while ((i < (JEILINJ_MAX_TRANSFER - 1)) &&
+                       ((buf[i] != 0xff) || (buf[i+1] != 0xd9)))
+                       i++;
+
+               if (i != (JEILINJ_MAX_TRANSFER - 1))
+                       /* last remaining block found */
+                       break;
+               }
+
+       for (i = 0; i < ARRAY_SIZE(stop_commands); i++)
+               jlj_write2(gspca_dev, stop_commands[i]);
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       return gspca_dev->usb_err;
+}
+
+/* Set up for getting frames. */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *dev = (struct sd *) gspca_dev;
+
+       /* create the JPEG header */
+       jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+                       0x21);          /* JPEG 422 */
+       jpeg_set_qual(dev->jpeg_hdr, dev->quality);
+       PDEBUG(D_STREAM, "Start streaming at %dx%d",
+               gspca_dev->height, gspca_dev->width);
+       jlj_start(gspca_dev);
+       return gspca_dev->usb_err;
+}
+
+/* Table of supported USB devices */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x0979, 0x0280), .driver_info = SAKAR_57379},
+       {USB_DEVICE(0x0979, 0x0270), .driver_info = SPORTSCAM_DV15},
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+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_POWER_LINE_FREQUENCY:
+               setfreq(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_RED_BALANCE:
+               setred(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_GAIN:
+               setgreen(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               setblue(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               setautogain(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+               jpeg_set_qual(sd->jpeg_hdr, ctrl->val);
+               setcamquality(gspca_dev, ctrl->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;
+       static const struct v4l2_ctrl_config custom_autogain = {
+               .ops = &sd_ctrl_ops,
+               .id = V4L2_CID_AUTOGAIN,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Automatic Gain (and Exposure)",
+               .max = 3,
+               .step = 1,
+               .def = 0,
+       };
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 6);
+       sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
+                       V4L2_CID_POWER_LINE_FREQUENCY,
+                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
+                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ);
+       v4l2_ctrl_new_custom(hdl, &custom_autogain, NULL);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_RED_BALANCE, 0, 3, 1, 2);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 3, 1, 2);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BLUE_BALANCE, 0, 3, 1, 2);
+       sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_JPEG_COMPRESSION_QUALITY,
+                       QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       return 0;
+}
+
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+                       struct v4l2_jpegcompression *jcomp)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
+       return 0;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+                       struct v4l2_jpegcompression *jcomp)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       memset(jcomp, 0, sizeof *jcomp);
+       jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
+       jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+                       | V4L2_JPEG_MARKER_DQT;
+       return 0;
+}
+
+
+/* sub-driver description */
+static const struct sd_desc sd_desc_sakar_57379 = {
+       .name   = MODULE_NAME,
+       .config = sd_config,
+       .init   = sd_init,
+       .start  = sd_start,
+       .stopN  = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* sub-driver description */
+static const struct sd_desc sd_desc_sportscam_dv15 = {
+       .name   = MODULE_NAME,
+       .config = sd_config,
+       .init   = sd_init,
+       .init_controls = sd_init_controls,
+       .start  = sd_start,
+       .stopN  = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+       .get_jcomp = sd_get_jcomp,
+       .set_jcomp = sd_set_jcomp,
+};
+
+static const struct sd_desc *sd_desc[2] = {
+       &sd_desc_sakar_57379,
+       &sd_desc_sportscam_dv15
+};
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+               const struct usb_device_id *id)
+{
+       return gspca_dev_probe(intf, id,
+                       sd_desc[id->driver_info],
+                       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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/jl2005bcd.c b/drivers/media/usb/gspca/jl2005bcd.c
new file mode 100644 (file)
index 0000000..cf9d9fc
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+ * Jeilin JL2005B/C/D library
+ *
+ * Copyright (C) 2011 Theodore Kilgore <kilgota@auburn.edu>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define MODULE_NAME "jl2005bcd"
+
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include "gspca.h"
+
+
+MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
+MODULE_DESCRIPTION("JL2005B/C/D USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* Default timeouts, in ms */
+#define JL2005C_CMD_TIMEOUT 500
+#define JL2005C_DATA_TIMEOUT 1000
+
+/* Maximum transfer size to use. */
+#define JL2005C_MAX_TRANSFER 0x200
+#define FRAME_HEADER_LEN 16
+
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;  /* !! must be the first item */
+       unsigned char firmware_id[6];
+       const struct v4l2_pix_format *cap_mode;
+       /* Driver stuff */
+       struct work_struct work_struct;
+       struct workqueue_struct *work_thread;
+       u8 frame_brightness;
+       int block_size; /* block size of camera */
+       int vga;        /* 1 if vga cam, 0 if cif cam */
+};
+
+
+/* Camera has two resolution settings. What they are depends on model. */
+static const struct v4l2_pix_format cif_mode[] = {
+       {176, 144, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+       {352, 288, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+       {640, 480, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+/*
+ * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
+ * and 0x82 for bulk data transfer.
+ */
+
+/* All commands are two bytes only */
+static int jl2005c_write2(struct gspca_dev *gspca_dev, unsigned char *command)
+{
+       int retval;
+
+       memcpy(gspca_dev->usb_buf, command, 2);
+       retval = usb_bulk_msg(gspca_dev->dev,
+                       usb_sndbulkpipe(gspca_dev->dev, 3),
+                       gspca_dev->usb_buf, 2, NULL, 500);
+       if (retval < 0)
+               pr_err("command write [%02x] error %d\n",
+                      gspca_dev->usb_buf[0], retval);
+       return retval;
+}
+
+/* Response to a command is one byte in usb_buf[0], only if requested. */
+static int jl2005c_read1(struct gspca_dev *gspca_dev)
+{
+       int retval;
+
+       retval = usb_bulk_msg(gspca_dev->dev,
+                               usb_rcvbulkpipe(gspca_dev->dev, 0x84),
+                               gspca_dev->usb_buf, 1, NULL, 500);
+       if (retval < 0)
+               pr_err("read command [0x%02x] error %d\n",
+                      gspca_dev->usb_buf[0], retval);
+       return retval;
+}
+
+/* Response appears in gspca_dev->usb_buf[0] */
+static int jl2005c_read_reg(struct gspca_dev *gspca_dev, unsigned char reg)
+{
+       int retval;
+
+       static u8 instruction[2] = {0x95, 0x00};
+       /* put register to read in byte 1 */
+       instruction[1] = reg;
+       /* Send the read request */
+       retval = jl2005c_write2(gspca_dev, instruction);
+       if (retval < 0)
+               return retval;
+       retval = jl2005c_read1(gspca_dev);
+
+       return retval;
+}
+
+static int jl2005c_start_new_frame(struct gspca_dev *gspca_dev)
+{
+       int i;
+       int retval;
+       int frame_brightness = 0;
+
+       static u8 instruction[2] = {0x7f, 0x01};
+
+       retval = jl2005c_write2(gspca_dev, instruction);
+       if (retval < 0)
+               return retval;
+
+       i = 0;
+       while (i < 20 && !frame_brightness) {
+               /* If we tried 20 times, give up. */
+               retval = jl2005c_read_reg(gspca_dev, 0x7e);
+               if (retval < 0)
+                       return retval;
+               frame_brightness = gspca_dev->usb_buf[0];
+               retval = jl2005c_read_reg(gspca_dev, 0x7d);
+               if (retval < 0)
+                       return retval;
+               i++;
+       }
+       PDEBUG(D_FRAM, "frame_brightness is 0x%02x", gspca_dev->usb_buf[0]);
+       return retval;
+}
+
+static int jl2005c_write_reg(struct gspca_dev *gspca_dev, unsigned char reg,
+                                                   unsigned char value)
+{
+       int retval;
+       u8 instruction[2];
+
+       instruction[0] = reg;
+       instruction[1] = value;
+
+       retval = jl2005c_write2(gspca_dev, instruction);
+       if (retval < 0)
+                       return retval;
+
+       return retval;
+}
+
+static int jl2005c_get_firmware_id(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+       int i = 0;
+       int retval = -1;
+       unsigned char regs_to_read[] = {0x57, 0x02, 0x03, 0x5d, 0x5e, 0x5f};
+
+       PDEBUG(D_PROBE, "Running jl2005c_get_firmware_id");
+       /* Read the first ID byte once for warmup */
+       retval = jl2005c_read_reg(gspca_dev, regs_to_read[0]);
+       PDEBUG(D_PROBE, "response is %02x", gspca_dev->usb_buf[0]);
+       if (retval < 0)
+               return retval;
+       /* Now actually get the ID string */
+       for (i = 0; i < 6; i++) {
+               retval = jl2005c_read_reg(gspca_dev, regs_to_read[i]);
+               if (retval < 0)
+                       return retval;
+               sd->firmware_id[i] = gspca_dev->usb_buf[0];
+       }
+       PDEBUG(D_PROBE, "firmware ID is %02x%02x%02x%02x%02x%02x",
+                                               sd->firmware_id[0],
+                                               sd->firmware_id[1],
+                                               sd->firmware_id[2],
+                                               sd->firmware_id[3],
+                                               sd->firmware_id[4],
+                                               sd->firmware_id[5]);
+       return 0;
+}
+
+static int jl2005c_stream_start_vga_lg
+                   (struct gspca_dev *gspca_dev)
+{
+       int i;
+       int retval = -1;
+       static u8 instruction[][2] = {
+               {0x05, 0x00},
+               {0x7c, 0x00},
+               {0x7d, 0x18},
+               {0x02, 0x00},
+               {0x01, 0x00},
+               {0x04, 0x52},
+       };
+
+       for (i = 0; i < ARRAY_SIZE(instruction); i++) {
+               msleep(60);
+               retval = jl2005c_write2(gspca_dev, instruction[i]);
+               if (retval < 0)
+                       return retval;
+       }
+       msleep(60);
+       return retval;
+}
+
+static int jl2005c_stream_start_vga_small(struct gspca_dev *gspca_dev)
+{
+       int i;
+       int retval = -1;
+       static u8 instruction[][2] = {
+               {0x06, 0x00},
+               {0x7c, 0x00},
+               {0x7d, 0x1a},
+               {0x02, 0x00},
+               {0x01, 0x00},
+               {0x04, 0x52},
+       };
+
+       for (i = 0; i < ARRAY_SIZE(instruction); i++) {
+               msleep(60);
+               retval = jl2005c_write2(gspca_dev, instruction[i]);
+               if (retval < 0)
+                       return retval;
+       }
+       msleep(60);
+       return retval;
+}
+
+static int jl2005c_stream_start_cif_lg(struct gspca_dev *gspca_dev)
+{
+       int i;
+       int retval = -1;
+       static u8 instruction[][2] = {
+               {0x05, 0x00},
+               {0x7c, 0x00},
+               {0x7d, 0x30},
+               {0x02, 0x00},
+               {0x01, 0x00},
+               {0x04, 0x42},
+       };
+
+       for (i = 0; i < ARRAY_SIZE(instruction); i++) {
+               msleep(60);
+               retval = jl2005c_write2(gspca_dev, instruction[i]);
+               if (retval < 0)
+                       return retval;
+       }
+       msleep(60);
+       return retval;
+}
+
+static int jl2005c_stream_start_cif_small(struct gspca_dev *gspca_dev)
+{
+       int i;
+       int retval = -1;
+       static u8 instruction[][2] = {
+               {0x06, 0x00},
+               {0x7c, 0x00},
+               {0x7d, 0x32},
+               {0x02, 0x00},
+               {0x01, 0x00},
+               {0x04, 0x42},
+       };
+
+       for (i = 0; i < ARRAY_SIZE(instruction); i++) {
+               msleep(60);
+               retval = jl2005c_write2(gspca_dev, instruction[i]);
+               if (retval < 0)
+                       return retval;
+       }
+       msleep(60);
+       return retval;
+}
+
+
+static int jl2005c_stop(struct gspca_dev *gspca_dev)
+{
+       int retval;
+
+       retval = jl2005c_write_reg(gspca_dev, 0x07, 0x00);
+       return retval;
+}
+
+/* This function is called as a workqueue function and runs whenever the camera
+ * is streaming data. Because it is a workqueue function it is allowed to sleep
+ * so we can use synchronous USB calls. To avoid possible collisions with other
+ * threads attempting to use the camera's USB interface the gspca usb_lock is
+ * used when performing the one USB control operation inside the workqueue,
+ * which tells the camera to close the stream. In practice the only thing
+ * which needs to be protected against is the usb_set_interface call that
+ * gspca makes during stream_off. Otherwise the camera doesn't provide any
+ * controls that the user could try to change.
+ */
+static void jl2005c_dostream(struct work_struct *work)
+{
+       struct sd *dev = container_of(work, struct sd, work_struct);
+       struct gspca_dev *gspca_dev = &dev->gspca_dev;
+       int bytes_left = 0; /* bytes remaining in current frame. */
+       int data_len;   /* size to use for the next read. */
+       int header_read = 0;
+       unsigned char header_sig[2] = {0x4a, 0x4c};
+       int act_len;
+       int packet_type;
+       int ret;
+       u8 *buffer;
+
+       buffer = kmalloc(JL2005C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
+       if (!buffer) {
+               pr_err("Couldn't allocate USB buffer\n");
+               goto quit_stream;
+       }
+
+       while (gspca_dev->dev && gspca_dev->streaming) {
+#ifdef CONFIG_PM
+               if (gspca_dev->frozen)
+                       break;
+#endif
+               /* Check if this is a new frame. If so, start the frame first */
+               if (!header_read) {
+                       mutex_lock(&gspca_dev->usb_lock);
+                       ret = jl2005c_start_new_frame(gspca_dev);
+                       mutex_unlock(&gspca_dev->usb_lock);
+                       if (ret < 0)
+                               goto quit_stream;
+                       ret = usb_bulk_msg(gspca_dev->dev,
+                               usb_rcvbulkpipe(gspca_dev->dev, 0x82),
+                               buffer, JL2005C_MAX_TRANSFER, &act_len,
+                               JL2005C_DATA_TIMEOUT);
+                       PDEBUG(D_PACK,
+                               "Got %d bytes out of %d for header",
+                                       act_len, JL2005C_MAX_TRANSFER);
+                       if (ret < 0 || act_len < JL2005C_MAX_TRANSFER)
+                               goto quit_stream;
+                       /* Check whether we actually got the first blodk */
+                       if (memcmp(header_sig, buffer, 2) != 0) {
+                               pr_err("First block is not the first block\n");
+                               goto quit_stream;
+                       }
+                       /* total size to fetch is byte 7, times blocksize
+                        * of which we already got act_len */
+                       bytes_left = buffer[0x07] * dev->block_size - act_len;
+                       PDEBUG(D_PACK, "bytes_left = 0x%x", bytes_left);
+                       /* We keep the header. It has other information, too.*/
+                       packet_type = FIRST_PACKET;
+                       gspca_frame_add(gspca_dev, packet_type,
+                                       buffer, act_len);
+                       header_read = 1;
+               }
+               while (bytes_left > 0 && gspca_dev->dev) {
+                       data_len = bytes_left > JL2005C_MAX_TRANSFER ?
+                               JL2005C_MAX_TRANSFER : bytes_left;
+                       ret = usb_bulk_msg(gspca_dev->dev,
+                               usb_rcvbulkpipe(gspca_dev->dev, 0x82),
+                               buffer, data_len, &act_len,
+                               JL2005C_DATA_TIMEOUT);
+                       if (ret < 0 || act_len < data_len)
+                               goto quit_stream;
+                       PDEBUG(D_PACK,
+                               "Got %d bytes out of %d for frame",
+                                               data_len, bytes_left);
+                       bytes_left -= data_len;
+                       if (bytes_left == 0) {
+                               packet_type = LAST_PACKET;
+                               header_read = 0;
+                       } else
+                               packet_type = INTER_PACKET;
+                       gspca_frame_add(gspca_dev, packet_type,
+                                       buffer, data_len);
+               }
+       }
+quit_stream:
+       if (gspca_dev->dev) {
+               mutex_lock(&gspca_dev->usb_lock);
+               jl2005c_stop(gspca_dev);
+               mutex_unlock(&gspca_dev->usb_lock);
+       }
+       kfree(buffer);
+}
+
+
+
+
+/* This function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct cam *cam;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       cam = &gspca_dev->cam;
+       /* We don't use the buffer gspca allocates so make it small. */
+       cam->bulk_size = 64;
+       cam->bulk = 1;
+       /* For the rest, the camera needs to be detected */
+       jl2005c_get_firmware_id(gspca_dev);
+       /* Here are some known firmware IDs
+        * First some JL2005B cameras
+        * {0x41, 0x07, 0x04, 0x2c, 0xe8, 0xf2} Sakar KidzCam
+        * {0x45, 0x02, 0x08, 0xb9, 0x00, 0xd2} No-name JL2005B
+        * JL2005C cameras
+        * {0x01, 0x0c, 0x16, 0x10, 0xf8, 0xc8} Argus DC-1512
+        * {0x12, 0x04, 0x03, 0xc0, 0x00, 0xd8} ICarly
+        * {0x86, 0x08, 0x05, 0x02, 0x00, 0xd4} Jazz
+        *
+        * Based upon this scanty evidence, we can detect a CIF camera by
+        * testing byte 0 for 0x4x.
+        */
+       if ((sd->firmware_id[0] & 0xf0) == 0x40) {
+               cam->cam_mode   = cif_mode;
+               cam->nmodes     = ARRAY_SIZE(cif_mode);
+               sd->block_size  = 0x80;
+       } else {
+               cam->cam_mode   = vga_mode;
+               cam->nmodes     = ARRAY_SIZE(vga_mode);
+               sd->block_size  = 0x200;
+       }
+
+       INIT_WORK(&sd->work_struct, jl2005c_dostream);
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       return 0;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+
+       struct sd *sd = (struct sd *) gspca_dev;
+       sd->cap_mode = gspca_dev->cam.cam_mode;
+
+       switch (gspca_dev->width) {
+       case 640:
+               PDEBUG(D_STREAM, "Start streaming at vga resolution");
+               jl2005c_stream_start_vga_lg(gspca_dev);
+               break;
+       case 320:
+               PDEBUG(D_STREAM, "Start streaming at qvga resolution");
+               jl2005c_stream_start_vga_small(gspca_dev);
+               break;
+       case 352:
+               PDEBUG(D_STREAM, "Start streaming at cif resolution");
+               jl2005c_stream_start_cif_lg(gspca_dev);
+               break;
+       case 176:
+               PDEBUG(D_STREAM, "Start streaming at qcif resolution");
+               jl2005c_stream_start_cif_small(gspca_dev);
+               break;
+       default:
+               pr_err("Unknown resolution specified\n");
+               return -1;
+       }
+
+       /* Start the workqueue function to do the streaming */
+       sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
+       queue_work(sd->work_thread, &sd->work_struct);
+
+       return 0;
+}
+
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct sd *dev = (struct sd *) gspca_dev;
+
+       /* wait for the work queue to terminate */
+       mutex_unlock(&gspca_dev->usb_lock);
+       /* This waits for sq905c_dostream to finish */
+       destroy_workqueue(dev->work_thread);
+       dev->work_thread = NULL;
+       mutex_lock(&gspca_dev->usb_lock);
+}
+
+
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name = MODULE_NAME,
+       .config = sd_config,
+       .init = sd_init,
+       .start = sd_start,
+       .stop0 = sd_stop0,
+};
+
+/* -- module initialisation -- */
+static const __devinitdata struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x0979, 0x0227)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+       int ret;
+
+       ret = usb_register(&sd_driver);
+       if (ret < 0)
+               return ret;
+       return 0;
+}
+static void __exit sd_mod_exit(void)
+{
+       usb_deregister(&sd_driver);
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
diff --git a/drivers/media/usb/gspca/jpeg.h b/drivers/media/usb/gspca/jpeg.h
new file mode 100644 (file)
index 0000000..ab54910
--- /dev/null
@@ -0,0 +1,168 @@
+#ifndef JPEG_H
+#define JPEG_H 1
+/*
+ * Insert a JPEG header at start of frame
+ *
+ * This module is used by the gspca subdrivers.
+ * A special case is done for Conexant webcams.
+ *
+ * Copyright (C) Jean-Francois Moine (http://moinejf.free.fr)
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * generation options
+ *     CONEX_CAM       Conexant if present
+ */
+
+/* JPEG header */
+static const u8 jpeg_head[] = {
+       0xff, 0xd8,                     /* jpeg */
+
+/* quantization table quality 50% */
+       0xff, 0xdb, 0x00, 0x84,         /* DQT */
+0,
+#define JPEG_QT0_OFFSET 7
+       0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
+       0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
+       0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+       0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+       0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+       0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+       0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+       0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+1,
+#define JPEG_QT1_OFFSET 72
+       0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+       0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+
+/* huffman table */
+       0xff, 0xc4, 0x01, 0xa2,
+       0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+       0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, 0x00, 0x03,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+       0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03,
+       0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00,
+       0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
+       0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13,
+       0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81,
+       0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15,
+       0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82,
+       0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
+       0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36,
+       0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
+       0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56,
+       0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66,
+       0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
+       0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86,
+       0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95,
+       0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,
+       0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3,
+       0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
+       0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca,
+       0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
+       0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+       0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
+       0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
+       0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
+       0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
+       0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06,
+       0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22,
+       0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
+       0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62,
+       0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
+       0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28,
+       0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
+       0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
+       0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
+       0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
+       0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
+       0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+       0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+       0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+       0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+       0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+       0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+       0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
+       0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2,
+       0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
+#ifdef CONEX_CAM
+/* the Conexant frames start with SOF0 */
+#define JPEG_HDR_SZ 556
+#else
+       0xff, 0xc0, 0x00, 0x11,         /* SOF0 (start of frame 0 */
+       0x08,                           /* data precision */
+#define JPEG_HEIGHT_OFFSET 561
+       0x01, 0xe0,                     /* height */
+       0x02, 0x80,                     /* width */
+       0x03,                           /* component number */
+               0x01,
+                       0x21,           /* samples Y */
+                       0x00,           /* quant Y */
+               0x02, 0x11, 0x01,       /* samples CbCr - quant CbCr */
+               0x03, 0x11, 0x01,
+
+       0xff, 0xda, 0x00, 0x0c,         /* SOS (start of scan) */
+       0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
+#define JPEG_HDR_SZ 589
+#endif
+};
+
+/* define the JPEG header */
+static void jpeg_define(u8 *jpeg_hdr,
+                       int height,
+                       int width,
+                       int samplesY)
+{
+       memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head);
+#ifndef CONEX_CAM
+       jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8;
+       jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height;
+       jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8;
+       jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width;
+       jpeg_hdr[JPEG_HEIGHT_OFFSET + 6] = samplesY;
+#endif
+}
+
+/* set the JPEG quality */
+static void jpeg_set_qual(u8 *jpeg_hdr,
+                         int quality)
+{
+       int i, sc;
+
+       if (quality < 50)
+               sc = 5000 / quality;
+       else
+               sc = 200 - quality * 2;
+       for (i = 0; i < 64; i++) {
+               jpeg_hdr[JPEG_QT0_OFFSET + i] =
+                       (jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100;
+               jpeg_hdr[JPEG_QT1_OFFSET + i] =
+                       (jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100;
+       }
+}
+#endif
diff --git a/drivers/media/usb/gspca/kinect.c b/drivers/media/usb/gspca/kinect.c
new file mode 100644 (file)
index 0000000..40ad668
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * kinect sensor device camera, gspca driver
+ *
+ * Copyright (C) 2011  Antonio Ospite <ospite@studenti.unina.it>
+ *
+ * Based on the OpenKinect project and libfreenect
+ * http://openkinect.org/wiki/Init_Analysis
+ *
+ * Special thanks to Steven Toth and kernellabs.com for sponsoring a Kinect
+ * sensor device which I tested the driver on.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "kinect"
+
+#include "gspca.h"
+
+#define CTRL_TIMEOUT 500
+
+MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
+MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+struct pkt_hdr {
+       uint8_t magic[2];
+       uint8_t pad;
+       uint8_t flag;
+       uint8_t unk1;
+       uint8_t seq;
+       uint8_t unk2;
+       uint8_t unk3;
+       uint32_t timestamp;
+};
+
+struct cam_hdr {
+       uint8_t magic[2];
+       uint16_t len;
+       uint16_t cmd;
+       uint16_t tag;
+};
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev; /* !! must be the first item */
+       uint16_t cam_tag;           /* a sequence number for packets */
+       uint8_t stream_flag;        /* to identify different stream types */
+       uint8_t obuf[0x400];        /* output buffer for control commands */
+       uint8_t ibuf[0x200];        /* input buffer for control commands */
+};
+
+#define MODE_640x480   0x0001
+#define MODE_640x488   0x0002
+#define MODE_1280x1024 0x0004
+
+#define FORMAT_BAYER   0x0010
+#define FORMAT_UYVY    0x0020
+#define FORMAT_Y10B    0x0040
+
+#define FPS_HIGH       0x0100
+
+static const struct v4l2_pix_format video_camera_mode[] = {
+       {640, 480, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
+        .bytesperline = 640,
+        .sizeimage = 640 * 480,
+        .colorspace = V4L2_COLORSPACE_SRGB,
+        .priv = MODE_640x480 | FORMAT_BAYER | FPS_HIGH},
+       {640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
+        .bytesperline = 640 * 2,
+        .sizeimage = 640 * 480 * 2,
+        .colorspace = V4L2_COLORSPACE_SRGB,
+        .priv = MODE_640x480 | FORMAT_UYVY},
+       {1280, 1024, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
+        .bytesperline = 1280,
+        .sizeimage = 1280 * 1024,
+        .colorspace = V4L2_COLORSPACE_SRGB,
+        .priv = MODE_1280x1024 | FORMAT_BAYER},
+       {640, 488, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
+        .bytesperline = 640 * 10 / 8,
+        .sizeimage =  640 * 488 * 10 / 8,
+        .colorspace = V4L2_COLORSPACE_SRGB,
+        .priv = MODE_640x488 | FORMAT_Y10B | FPS_HIGH},
+       {1280, 1024, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
+        .bytesperline = 1280 * 10 / 8,
+        .sizeimage =  1280 * 1024 * 10 / 8,
+        .colorspace = V4L2_COLORSPACE_SRGB,
+        .priv = MODE_1280x1024 | FORMAT_Y10B},
+};
+
+static int kinect_write(struct usb_device *udev, uint8_t *data,
+                       uint16_t wLength)
+{
+       return usb_control_msg(udev,
+                             usb_sndctrlpipe(udev, 0),
+                             0x00,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0, 0, data, wLength, CTRL_TIMEOUT);
+}
+
+static int kinect_read(struct usb_device *udev, uint8_t *data, uint16_t wLength)
+{
+       return usb_control_msg(udev,
+                             usb_rcvctrlpipe(udev, 0),
+                             0x00,
+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0, 0, data, wLength, CTRL_TIMEOUT);
+}
+
+static int send_cmd(struct gspca_dev *gspca_dev, uint16_t cmd, void *cmdbuf,
+               unsigned int cmd_len, void *replybuf, unsigned int reply_len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct usb_device *udev = gspca_dev->dev;
+       int res, actual_len;
+       uint8_t *obuf = sd->obuf;
+       uint8_t *ibuf = sd->ibuf;
+       struct cam_hdr *chdr = (void *)obuf;
+       struct cam_hdr *rhdr = (void *)ibuf;
+
+       if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) {
+               pr_err("send_cmd: Invalid command length (0x%x)\n", cmd_len);
+               return -1;
+       }
+
+       chdr->magic[0] = 0x47;
+       chdr->magic[1] = 0x4d;
+       chdr->cmd = cpu_to_le16(cmd);
+       chdr->tag = cpu_to_le16(sd->cam_tag);
+       chdr->len = cpu_to_le16(cmd_len / 2);
+
+       memcpy(obuf+sizeof(*chdr), cmdbuf, cmd_len);
+
+       res = kinect_write(udev, obuf, cmd_len + sizeof(*chdr));
+       PDEBUG(D_USBO, "Control cmd=%04x tag=%04x len=%04x: %d", cmd,
+               sd->cam_tag, cmd_len, res);
+       if (res < 0) {
+               pr_err("send_cmd: Output control transfer failed (%d)\n", res);
+               return res;
+       }
+
+       do {
+               actual_len = kinect_read(udev, ibuf, 0x200);
+       } while (actual_len == 0);
+       PDEBUG(D_USBO, "Control reply: %d", res);
+       if (actual_len < sizeof(*rhdr)) {
+               pr_err("send_cmd: Input control transfer failed (%d)\n", res);
+               return res;
+       }
+       actual_len -= sizeof(*rhdr);
+
+       if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) {
+               pr_err("send_cmd: Bad magic %02x %02x\n",
+                      rhdr->magic[0], rhdr->magic[1]);
+               return -1;
+       }
+       if (rhdr->cmd != chdr->cmd) {
+               pr_err("send_cmd: Bad cmd %02x != %02x\n",
+                      rhdr->cmd, chdr->cmd);
+               return -1;
+       }
+       if (rhdr->tag != chdr->tag) {
+               pr_err("send_cmd: Bad tag %04x != %04x\n",
+                      rhdr->tag, chdr->tag);
+               return -1;
+       }
+       if (cpu_to_le16(rhdr->len) != (actual_len/2)) {
+               pr_err("send_cmd: Bad len %04x != %04x\n",
+                      cpu_to_le16(rhdr->len), (int)(actual_len/2));
+               return -1;
+       }
+
+       if (actual_len > reply_len) {
+               pr_warn("send_cmd: Data buffer is %d bytes long, but got %d bytes\n",
+                       reply_len, actual_len);
+               memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len);
+       } else {
+               memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len);
+       }
+
+       sd->cam_tag++;
+
+       return actual_len;
+}
+
+static int write_register(struct gspca_dev *gspca_dev, uint16_t reg,
+                       uint16_t data)
+{
+       uint16_t reply[2];
+       uint16_t cmd[2];
+       int res;
+
+       cmd[0] = cpu_to_le16(reg);
+       cmd[1] = cpu_to_le16(data);
+
+       PDEBUG(D_USBO, "Write Reg 0x%04x <= 0x%02x", reg, data);
+       res = send_cmd(gspca_dev, 0x03, cmd, 4, reply, 4);
+       if (res < 0)
+               return res;
+       if (res != 2) {
+               pr_warn("send_cmd returned %d [%04x %04x], 0000 expected\n",
+                       res, reply[0], reply[1]);
+       }
+       return 0;
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                    const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+
+       sd->cam_tag = 0;
+
+       /* Only video stream is supported for now,
+        * which has stream flag = 0x80 */
+       sd->stream_flag = 0x80;
+
+       cam = &gspca_dev->cam;
+
+       cam->cam_mode = video_camera_mode;
+       cam->nmodes = ARRAY_SIZE(video_camera_mode);
+
+#if 0
+       /* Setting those values is not needed for video stream */
+       cam->npkt = 15;
+       gspca_dev->pkt_size = 960 * 2;
+#endif
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       PDEBUG(D_PROBE, "Kinect Camera device.");
+
+       return 0;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       int mode;
+       uint8_t fmt_reg, fmt_val;
+       uint8_t res_reg, res_val;
+       uint8_t fps_reg, fps_val;
+       uint8_t mode_val;
+
+       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+
+       if (mode & FORMAT_Y10B) {
+               fmt_reg = 0x19;
+               res_reg = 0x1a;
+               fps_reg = 0x1b;
+               mode_val = 0x03;
+       } else {
+               fmt_reg = 0x0c;
+               res_reg = 0x0d;
+               fps_reg = 0x0e;
+               mode_val = 0x01;
+       }
+
+       /* format */
+       if (mode & FORMAT_UYVY)
+               fmt_val = 0x05;
+       else
+               fmt_val = 0x00;
+
+       if (mode & MODE_1280x1024)
+               res_val = 0x02;
+       else
+               res_val = 0x01;
+
+       if (mode & FPS_HIGH)
+               fps_val = 0x1e;
+       else
+               fps_val = 0x0f;
+
+
+       /* turn off IR-reset function */
+       write_register(gspca_dev, 0x105, 0x00);
+
+       /* Reset video stream */
+       write_register(gspca_dev, 0x05, 0x00);
+
+       /* Due to some ridiculous condition in the firmware, we have to start
+        * and stop the depth stream before the camera will hand us 1280x1024
+        * IR.  This is a stupid workaround, but we've yet to find a better
+        * solution.
+        *
+        * Thanks to Drew Fisher for figuring this out.
+        */
+       if (mode & (FORMAT_Y10B | MODE_1280x1024)) {
+               write_register(gspca_dev, 0x13, 0x01);
+               write_register(gspca_dev, 0x14, 0x1e);
+               write_register(gspca_dev, 0x06, 0x02);
+               write_register(gspca_dev, 0x06, 0x00);
+       }
+
+       write_register(gspca_dev, fmt_reg, fmt_val);
+       write_register(gspca_dev, res_reg, res_val);
+       write_register(gspca_dev, fps_reg, fps_val);
+
+       /* Start video stream */
+       write_register(gspca_dev, 0x05, mode_val);
+
+       /* disable Hflip */
+       write_register(gspca_dev, 0x47, 0x00);
+
+       return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       /* reset video stream */
+       write_register(gspca_dev, 0x05, 0x00);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       struct pkt_hdr *hdr = (void *)__data;
+       uint8_t *data = __data + sizeof(*hdr);
+       int datalen = len - sizeof(*hdr);
+
+       uint8_t sof = sd->stream_flag | 1;
+       uint8_t mof = sd->stream_flag | 2;
+       uint8_t eof = sd->stream_flag | 5;
+
+       if (len < 12)
+               return;
+
+       if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') {
+               pr_warn("[Stream %02x] Invalid magic %02x%02x\n",
+                       sd->stream_flag, hdr->magic[0], hdr->magic[1]);
+               return;
+       }
+
+       if (hdr->flag == sof)
+               gspca_frame_add(gspca_dev, FIRST_PACKET, data, datalen);
+
+       else if (hdr->flag == mof)
+               gspca_frame_add(gspca_dev, INTER_PACKET, data, datalen);
+
+       else if (hdr->flag == eof)
+               gspca_frame_add(gspca_dev, LAST_PACKET, data, datalen);
+
+       else
+               pr_warn("Packet type not recognized...\n");
+}
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name      = MODULE_NAME,
+       .config    = sd_config,
+       .init      = sd_init,
+       .start     = sd_start,
+       .stopN     = sd_stopN,
+       .pkt_scan  = sd_pkt_scan,
+       /*
+       .get_streamparm = sd_get_streamparm,
+       .set_streamparm = sd_set_streamparm,
+       */
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x045e, 0x02ae)},
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/konica.c b/drivers/media/usb/gspca/konica.c
new file mode 100644 (file)
index 0000000..bbf91e0
--- /dev/null
@@ -0,0 +1,487 @@
+/*
+ * Driver for USB webcams based on Konica chipset. This
+ * chipset is used in Intel YC76 camera.
+ *
+ * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on the usbvideo v4l1 konicawc driver which is:
+ *
+ * Copyright (C) 2002 Simon Evans <spse@secret.org.uk>
+ *
+ * The code for making gspca work with a webcam with 2 isoc endpoints was
+ * taken from the benq gspca subdriver which is:
+ *
+ * Copyright (C) 2009 Jean-Francois Moine (http://moinejf.free.fr)
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "konica"
+
+#include <linux/input.h>
+#include "gspca.h"
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("Konica chipset USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+#define WHITEBAL_REG   0x01
+#define BRIGHTNESS_REG 0x02
+#define SHARPNESS_REG  0x03
+#define CONTRAST_REG   0x04
+#define SATURATION_REG 0x05
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+       struct urb *last_data_urb;
+       u8 snapshot_pressed;
+};
+
+
+/* .priv is what goes to register 8 for this mode, known working values:
+   0x00 -> 176x144, cropped
+   0x01 -> 176x144, cropped
+   0x02 -> 176x144, cropped
+   0x03 -> 176x144, cropped
+   0x04 -> 176x144, binned
+   0x05 -> 320x240
+   0x06 -> 320x240
+   0x07 -> 160x120, cropped
+   0x08 -> 160x120, cropped
+   0x09 -> 160x120, binned (note has 136 lines)
+   0x0a -> 160x120, binned (note has 136 lines)
+   0x0b -> 160x120, cropped
+*/
+static const struct v4l2_pix_format vga_mode[] = {
+       {160, 120, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 136 * 3 / 2 + 960,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0x0a},
+       {176, 144, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 2 + 960,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0x04},
+       {320, 240, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 2 + 960,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0x05},
+};
+
+static void sd_isoc_irq(struct urb *urb);
+
+static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                       0x02,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value,
+                       index,
+                       NULL,
+                       0,
+                       1000);
+       if (ret < 0) {
+               pr_err("reg_w err writing %02x to %02x: %d\n",
+                      value, index, ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void reg_r(struct gspca_dev *gspca_dev, u16 value, u16 index)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                       0x03,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value,
+                       index,
+                       gspca_dev->usb_buf,
+                       2,
+                       1000);
+       if (ret < 0) {
+               pr_err("reg_r err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void konica_stream_on(struct gspca_dev *gspca_dev)
+{
+       reg_w(gspca_dev, 1, 0x0b);
+}
+
+static void konica_stream_off(struct gspca_dev *gspca_dev)
+{
+       reg_w(gspca_dev, 0, 0x0b);
+}
+
+/* this function is called at probe time */
+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);
+       gspca_dev->cam.no_urb_create = 1;
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       int i;
+
+       /*
+        * The konica needs a freaking large time to "boot" (approx 6.5 sec.),
+        * and does not want to be bothered while doing so :|
+        * Register 0x10 counts from 1 - 3, with 3 being "ready"
+        */
+       msleep(6000);
+       for (i = 0; i < 20; i++) {
+               reg_r(gspca_dev, 0, 0x10);
+               if (gspca_dev->usb_buf[0] == 3)
+                       break;
+               msleep(100);
+       }
+       reg_w(gspca_dev, 0, 0x0d);
+
+       return gspca_dev->usb_err;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct urb *urb;
+       int i, n, packet_size;
+       struct usb_host_interface *alt;
+       struct usb_interface *intf;
+
+       intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+       alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+       if (!alt) {
+               pr_err("Couldn't get altsetting\n");
+               return -EIO;
+       }
+
+       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+
+       n = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+       reg_w(gspca_dev, n, 0x08);
+
+       konica_stream_on(gspca_dev);
+
+       if (gspca_dev->usb_err)
+               return gspca_dev->usb_err;
+
+       /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */
+#if MAX_NURBS < 4
+#error "Not enough URBs in the gspca table"
+#endif
+#define SD_NPKT 32
+       for (n = 0; n < 4; n++) {
+               i = n & 1 ? 0 : 1;
+               packet_size =
+                       le16_to_cpu(alt->endpoint[i].desc.wMaxPacketSize);
+               urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
+               if (!urb) {
+                       pr_err("usb_alloc_urb failed\n");
+                       return -ENOMEM;
+               }
+               gspca_dev->urb[n] = urb;
+               urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
+                                               packet_size * SD_NPKT,
+                                               GFP_KERNEL,
+                                               &urb->transfer_dma);
+               if (urb->transfer_buffer == NULL) {
+                       pr_err("usb_buffer_alloc failed\n");
+                       return -ENOMEM;
+               }
+
+               urb->dev = gspca_dev->dev;
+               urb->context = gspca_dev;
+               urb->transfer_buffer_length = packet_size * SD_NPKT;
+               urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
+                                       n & 1 ? 0x81 : 0x82);
+               urb->transfer_flags = URB_ISO_ASAP
+                                       | URB_NO_TRANSFER_DMA_MAP;
+               urb->interval = 1;
+               urb->complete = sd_isoc_irq;
+               urb->number_of_packets = SD_NPKT;
+               for (i = 0; i < SD_NPKT; i++) {
+                       urb->iso_frame_desc[i].length = packet_size;
+                       urb->iso_frame_desc[i].offset = packet_size * i;
+               }
+       }
+
+       return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       konica_stream_off(gspca_dev);
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       /* Don't keep the button in the pressed state "forever" if it was
+          pressed when streaming is stopped */
+       if (sd->snapshot_pressed) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+               input_sync(gspca_dev->input_dev);
+               sd->snapshot_pressed = 0;
+       }
+#endif
+}
+
+/* reception of an URB */
+static void sd_isoc_irq(struct urb *urb)
+{
+       struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct urb *data_urb, *status_urb;
+       u8 *data;
+       int i, st;
+
+       PDEBUG(D_PACK, "sd isoc irq");
+       if (!gspca_dev->streaming)
+               return;
+
+       if (urb->status != 0) {
+               if (urb->status == -ESHUTDOWN)
+                       return;         /* disconnection */
+#ifdef CONFIG_PM
+               if (gspca_dev->frozen)
+                       return;
+#endif
+               PDEBUG(D_ERR, "urb status: %d", urb->status);
+               st = usb_submit_urb(urb, GFP_ATOMIC);
+               if (st < 0)
+                       pr_err("resubmit urb error %d\n", st);
+               return;
+       }
+
+       /* if this is a data URB (ep 0x82), wait */
+       if (urb->transfer_buffer_length > 32) {
+               sd->last_data_urb = urb;
+               return;
+       }
+
+       status_urb = urb;
+       data_urb   = sd->last_data_urb;
+       sd->last_data_urb = NULL;
+
+       if (!data_urb || data_urb->start_frame != status_urb->start_frame) {
+               PDEBUG(D_ERR|D_PACK, "lost sync on frames");
+               goto resubmit;
+       }
+
+       if (data_urb->number_of_packets != status_urb->number_of_packets) {
+               PDEBUG(D_ERR|D_PACK,
+                      "no packets does not match, data: %d, status: %d",
+                      data_urb->number_of_packets,
+                      status_urb->number_of_packets);
+               goto resubmit;
+       }
+
+       for (i = 0; i < status_urb->number_of_packets; i++) {
+               if (data_urb->iso_frame_desc[i].status ||
+                   status_urb->iso_frame_desc[i].status) {
+                       PDEBUG(D_ERR|D_PACK,
+                              "pkt %d data-status %d, status-status %d", i,
+                              data_urb->iso_frame_desc[i].status,
+                              status_urb->iso_frame_desc[i].status);
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+                       continue;
+               }
+
+               if (status_urb->iso_frame_desc[i].actual_length != 1) {
+                       PDEBUG(D_ERR|D_PACK,
+                              "bad status packet length %d",
+                              status_urb->iso_frame_desc[i].actual_length);
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+                       continue;
+               }
+
+               st = *((u8 *)status_urb->transfer_buffer
+                               + status_urb->iso_frame_desc[i].offset);
+
+               data = (u8 *)data_urb->transfer_buffer
+                               + data_urb->iso_frame_desc[i].offset;
+
+               /* st: 0x80-0xff: frame start with frame number (ie 0-7f)
+                * otherwise:
+                * bit 0 0: keep packet
+                *       1: drop packet (padding data)
+                *
+                * bit 4 0 button not clicked
+                *       1 button clicked
+                * button is used to `take a picture' (in software)
+                */
+               if (st & 0x80) {
+                       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+                       gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
+               } else {
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+                       u8 button_state = st & 0x40 ? 1 : 0;
+                       if (sd->snapshot_pressed != button_state) {
+                               input_report_key(gspca_dev->input_dev,
+                                                KEY_CAMERA,
+                                                button_state);
+                               input_sync(gspca_dev->input_dev);
+                               sd->snapshot_pressed = button_state;
+                       }
+#endif
+                       if (st & 0x01)
+                               continue;
+               }
+               gspca_frame_add(gspca_dev, INTER_PACKET, data,
+                               data_urb->iso_frame_desc[i].actual_length);
+       }
+
+resubmit:
+       if (data_urb) {
+               st = usb_submit_urb(data_urb, GFP_ATOMIC);
+               if (st < 0)
+                       PDEBUG(D_ERR|D_PACK,
+                              "usb_submit_urb(data_urb) ret %d", st);
+       }
+       st = usb_submit_urb(status_urb, GFP_ATOMIC);
+       if (st < 0)
+               pr_err("usb_submit_urb(status_urb) ret %d\n", st);
+}
+
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct gspca_dev *gspca_dev =
+               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+
+       gspca_dev->usb_err = 0;
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               konica_stream_off(gspca_dev);
+               reg_w(gspca_dev, ctrl->val, BRIGHTNESS_REG);
+               konica_stream_on(gspca_dev);
+               break;
+       case V4L2_CID_CONTRAST:
+               konica_stream_off(gspca_dev);
+               reg_w(gspca_dev, ctrl->val, CONTRAST_REG);
+               konica_stream_on(gspca_dev);
+               break;
+       case V4L2_CID_SATURATION:
+               konica_stream_off(gspca_dev);
+               reg_w(gspca_dev, ctrl->val, SATURATION_REG);
+               konica_stream_on(gspca_dev);
+               break;
+       case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
+               konica_stream_off(gspca_dev);
+               reg_w(gspca_dev, ctrl->val, WHITEBAL_REG);
+               konica_stream_on(gspca_dev);
+               break;
+       case V4L2_CID_SHARPNESS:
+               konica_stream_off(gspca_dev);
+               reg_w(gspca_dev, ctrl->val, SHARPNESS_REG);
+               konica_stream_on(gspca_dev);
+               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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 5);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 9, 1, 4);
+       /* Needs to be verified */
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 9, 1, 4);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 9, 1, 4);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_WHITE_BALANCE_TEMPERATURE,
+                       0, 33, 1, 25);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SHARPNESS, 0, 9, 1, 4);
+
+       if (hdl->error) {
+               pr_err("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,
+       .stopN = sd_stopN,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .other_input = 1,
+#endif
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x04c8, 0x0720)}, /* Intel YC 76 */
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/m5602/Kconfig b/drivers/media/usb/gspca/m5602/Kconfig
new file mode 100644 (file)
index 0000000..5a69016
--- /dev/null
@@ -0,0 +1,11 @@
+config USB_M5602
+       tristate "ALi USB m5602 Camera Driver"
+       depends on VIDEO_V4L2 && USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on the
+         ALi m5602 connected to various image sensors.
+
+         See <file:Documentation/video4linux/m5602.txt> for more info.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_m5602.
diff --git a/drivers/media/usb/gspca/m5602/Makefile b/drivers/media/usb/gspca/m5602/Makefile
new file mode 100644 (file)
index 0000000..8e1fb5a
--- /dev/null
@@ -0,0 +1,11 @@
+obj-$(CONFIG_USB_M5602) += gspca_m5602.o
+
+gspca_m5602-objs := m5602_core.o \
+                   m5602_ov9650.o \
+                   m5602_ov7660.o \
+                   m5602_mt9m111.o \
+                   m5602_po1030.o \
+                   m5602_s5k83a.o \
+                   m5602_s5k4aa.o
+
+ccflags-y += -I$(srctree)/drivers/media/usb/gspca
diff --git a/drivers/media/usb/gspca/m5602/m5602_bridge.h b/drivers/media/usb/gspca/m5602/m5602_bridge.h
new file mode 100644 (file)
index 0000000..51af3ee
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * USB Driver for ALi m5602 based webcams
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#ifndef M5602_BRIDGE_H_
+#define M5602_BRIDGE_H_
+
+#include <linux/slab.h>
+#include "gspca.h"
+
+#define MODULE_NAME "ALi m5602"
+
+/*****************************************************************************/
+
+#define M5602_XB_SENSOR_TYPE           0x00
+#define M5602_XB_SENSOR_CTRL           0x01
+#define M5602_XB_LINE_OF_FRAME_H       0x02
+#define M5602_XB_LINE_OF_FRAME_L       0x03
+#define M5602_XB_PIX_OF_LINE_H         0x04
+#define M5602_XB_PIX_OF_LINE_L         0x05
+#define M5602_XB_VSYNC_PARA            0x06
+#define M5602_XB_HSYNC_PARA            0x07
+#define M5602_XB_TEST_MODE_1           0x08
+#define M5602_XB_TEST_MODE_2           0x09
+#define M5602_XB_SIG_INI               0x0a
+#define M5602_XB_DS_PARA               0x0e
+#define M5602_XB_TRIG_PARA             0x0f
+#define M5602_XB_CLK_PD                        0x10
+#define M5602_XB_MCU_CLK_CTRL          0x12
+#define M5602_XB_MCU_CLK_DIV           0x13
+#define M5602_XB_SEN_CLK_CTRL          0x14
+#define M5602_XB_SEN_CLK_DIV           0x15
+#define M5602_XB_AUD_CLK_CTRL          0x16
+#define M5602_XB_AUD_CLK_DIV           0x17
+#define M5602_OB_AC_LINK_STATE         0x22
+#define M5602_OB_PCM_SLOT_INDEX                0x24
+#define M5602_OB_GPIO_SLOT_INDEX       0x25
+#define M5602_OB_ACRX_STATUS_ADDRESS_H 0x28
+#define M5602_OB_ACRX_STATUS_DATA_L    0x29
+#define M5602_OB_ACRX_STATUS_DATA_H    0x2a
+#define M5602_OB_ACTX_COMMAND_ADDRESS  0x31
+#define M5602_OB_ACRX_COMMAND_DATA_L   0x32
+#define M5602_OB_ACTX_COMMAND_DATA_H   0X33
+#define M5602_XB_DEVCTR1               0x41
+#define M5602_XB_EPSETR0               0x42
+#define M5602_XB_EPAFCTR               0x47
+#define M5602_XB_EPBFCTR               0x49
+#define M5602_XB_EPEFCTR               0x4f
+#define M5602_XB_TEST_REG              0x53
+#define M5602_XB_ALT2SIZE              0x54
+#define M5602_XB_ALT3SIZE              0x55
+#define M5602_XB_OBSFRAME              0x56
+#define M5602_XB_PWR_CTL               0x59
+#define M5602_XB_ADC_CTRL              0x60
+#define M5602_XB_ADC_DATA              0x61
+#define M5602_XB_MISC_CTRL             0x62
+#define M5602_XB_SNAPSHOT              0x63
+#define M5602_XB_SCRATCH_1             0x64
+#define M5602_XB_SCRATCH_2             0x65
+#define M5602_XB_SCRATCH_3             0x66
+#define M5602_XB_SCRATCH_4             0x67
+#define M5602_XB_I2C_CTRL              0x68
+#define M5602_XB_I2C_CLK_DIV           0x69
+#define M5602_XB_I2C_DEV_ADDR          0x6a
+#define M5602_XB_I2C_REG_ADDR          0x6b
+#define M5602_XB_I2C_DATA              0x6c
+#define M5602_XB_I2C_STATUS            0x6d
+#define M5602_XB_GPIO_DAT_H            0x70
+#define M5602_XB_GPIO_DAT_L            0x71
+#define M5602_XB_GPIO_DIR_H            0x72
+#define M5602_XB_GPIO_DIR_L            0x73
+#define M5602_XB_GPIO_EN_H             0x74
+#define M5602_XB_GPIO_EN_L             0x75
+#define M5602_XB_GPIO_DAT              0x76
+#define M5602_XB_GPIO_DIR              0x77
+#define M5602_XB_SEN_CLK_CONTROL       0x80
+#define M5602_XB_SEN_CLK_DIVISION      0x81
+#define M5602_XB_CPR_CLK_CONTROL       0x82
+#define M5602_XB_CPR_CLK_DIVISION      0x83
+#define M5602_XB_MCU_CLK_CONTROL       0x84
+#define M5602_XB_MCU_CLK_DIVISION      0x85
+#define M5602_XB_DCT_CLK_CONTROL       0x86
+#define M5602_XB_DCT_CLK_DIVISION      0x87
+#define M5602_XB_EC_CLK_CONTROL                0x88
+#define M5602_XB_EC_CLK_DIVISION       0x89
+#define M5602_XB_LBUF_CLK_CONTROL      0x8a
+#define M5602_XB_LBUF_CLK_DIVISION     0x8b
+
+#define I2C_BUSY 0x80
+
+/*****************************************************************************/
+
+/* Driver info */
+#define DRIVER_AUTHOR "ALi m5602 Linux Driver Project"
+#define DRIVER_DESC "ALi m5602 webcam driver"
+
+#define M5602_ISOC_ENDPOINT_ADDR 0x81
+#define M5602_INTR_ENDPOINT_ADDR 0x82
+
+#define M5602_URB_MSG_TIMEOUT   5000
+
+/*****************************************************************************/
+
+/* A skeleton used for sending messages to the m5602 bridge */
+static const unsigned char bridge_urb_skeleton[] = {
+       0x13, 0x00, 0x81, 0x00
+};
+
+/* A skeleton used for sending messages to the sensor */
+static const unsigned char sensor_urb_skeleton[] = {
+       0x23, M5602_XB_GPIO_EN_H, 0x81, 0x06,
+       0x23, M5602_XB_MISC_CTRL, 0x81, 0x80,
+       0x13, M5602_XB_I2C_DEV_ADDR, 0x81, 0x00,
+       0x13, M5602_XB_I2C_REG_ADDR, 0x81, 0x00,
+       0x13, M5602_XB_I2C_DATA, 0x81, 0x00,
+       0x13, M5602_XB_I2C_CTRL, 0x81, 0x11
+};
+
+struct sd {
+       struct gspca_dev gspca_dev;
+
+       /* A pointer to the currently connected sensor */
+       const struct m5602_sensor *sensor;
+
+       struct sd_desc *desc;
+
+       /* Sensor private data */
+       void *sensor_priv;
+
+       /* The current frame's id, used to detect frame boundaries */
+       u8 frame_id;
+
+       /* The current frame count */
+       u32 frame_count;
+};
+
+int m5602_read_bridge(
+       struct sd *sd, const u8 address, u8 *i2c_data);
+
+int m5602_write_bridge(
+       struct sd *sd, const u8 address, const u8 i2c_data);
+
+int m5602_write_sensor(struct sd *sd, const u8 address,
+                      u8 *i2c_data, const u8 len);
+
+int m5602_read_sensor(struct sd *sd, const u8 address,
+                     u8 *i2c_data, const u8 len);
+
+#endif
diff --git a/drivers/media/usb/gspca/m5602/m5602_core.c b/drivers/media/usb/gspca/m5602/m5602_core.c
new file mode 100644 (file)
index 0000000..ed22638
--- /dev/null
@@ -0,0 +1,424 @@
+ /*
+ * USB Driver for ALi m5602 based webcams
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "m5602_ov9650.h"
+#include "m5602_ov7660.h"
+#include "m5602_mt9m111.h"
+#include "m5602_po1030.h"
+#include "m5602_s5k83a.h"
+#include "m5602_s5k4aa.h"
+
+/* Kernel module parameters */
+int force_sensor;
+static bool dump_bridge;
+bool dump_sensor;
+
+static const struct usb_device_id m5602_table[] = {
+       {USB_DEVICE(0x0402, 0x5602)},
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, m5602_table);
+
+/* Reads a byte from the m5602 */
+int m5602_read_bridge(struct sd *sd, const u8 address, u8 *i2c_data)
+{
+       int err;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                             0x04, 0xc0, 0x14,
+                             0x8100 + address, buf,
+                             1, M5602_URB_MSG_TIMEOUT);
+       *i2c_data = buf[0];
+
+       PDEBUG(D_CONF, "Reading bridge register 0x%x containing 0x%x",
+              address, *i2c_data);
+
+       /* usb_control_msg(...) returns the number of bytes sent upon success,
+       mask that and return zero instead*/
+       return (err < 0) ? err : 0;
+}
+
+/* Writes a byte to the m5602 */
+int m5602_write_bridge(struct sd *sd, const u8 address, const u8 i2c_data)
+{
+       int err;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       PDEBUG(D_CONF, "Writing bridge register 0x%x with 0x%x",
+              address, i2c_data);
+
+       memcpy(buf, bridge_urb_skeleton,
+              sizeof(bridge_urb_skeleton));
+       buf[1] = address;
+       buf[3] = i2c_data;
+
+       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                               0x04, 0x40, 0x19,
+                               0x0000, buf,
+                               4, M5602_URB_MSG_TIMEOUT);
+
+       /* usb_control_msg(...) returns the number of bytes sent upon success,
+          mask that and return zero instead */
+       return (err < 0) ? err : 0;
+}
+
+static int m5602_wait_for_i2c(struct sd *sd)
+{
+       int err;
+       u8 data;
+
+       do {
+               err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, &data);
+       } while ((data & I2C_BUSY) && !err);
+       return err;
+}
+
+int m5602_read_sensor(struct sd *sd, const u8 address,
+                      u8 *i2c_data, const u8 len)
+{
+       int err, i;
+
+       if (!len || len > sd->sensor->i2c_regW)
+               return -EINVAL;
+
+       err = m5602_wait_for_i2c(sd);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
+                                sd->sensor->i2c_slave_id);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
+       if (err < 0)
+               return err;
+
+       /* Sensors with registers that are of only
+          one byte width are differently read */
+
+       /* FIXME: This works with the ov9650, but has issues with the po1030 */
+       if (sd->sensor->i2c_regW == 1) {
+               err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 1);
+               if (err < 0)
+                       return err;
+
+               err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
+       } else {
+               err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
+       }
+
+       for (i = 0; (i < len) && !err; i++) {
+               err = m5602_wait_for_i2c(sd);
+               if (err < 0)
+                       return err;
+
+               err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
+
+               PDEBUG(D_CONF, "Reading sensor register "
+                              "0x%x containing 0x%x ", address, *i2c_data);
+       }
+       return err;
+}
+
+int m5602_write_sensor(struct sd *sd, const u8 address,
+                       u8 *i2c_data, const u8 len)
+{
+       int err, i;
+       u8 *p;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       /* No sensor with a data width larger than 16 bits has yet been seen */
+       if (len > sd->sensor->i2c_regW || !len)
+               return -EINVAL;
+
+       memcpy(buf, sensor_urb_skeleton,
+              sizeof(sensor_urb_skeleton));
+
+       buf[11] = sd->sensor->i2c_slave_id;
+       buf[15] = address;
+
+       /* Special case larger sensor writes */
+       p = buf + 16;
+
+       /* Copy a four byte write sequence for each byte to be written to */
+       for (i = 0; i < len; i++) {
+               memcpy(p, sensor_urb_skeleton + 16, 4);
+               p[3] = i2c_data[i];
+               p += 4;
+               PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
+                      address, i2c_data[i]);
+       }
+
+       /* Copy the tailer */
+       memcpy(p, sensor_urb_skeleton + 20, 4);
+
+       /* Set the total length */
+       p[3] = 0x10 + len;
+
+       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                             0x04, 0x40, 0x19,
+                             0x0000, buf,
+                             20 + len * 4, M5602_URB_MSG_TIMEOUT);
+
+       return (err < 0) ? err : 0;
+}
+
+/* Dump all the registers of the m5602 bridge,
+   unfortunately this breaks the camera until it's power cycled */
+static void m5602_dump_bridge(struct sd *sd)
+{
+       int i;
+       for (i = 0; i < 0x80; i++) {
+               unsigned char val = 0;
+               m5602_read_bridge(sd, i, &val);
+               pr_info("ALi m5602 address 0x%x contains 0x%x\n", i, val);
+       }
+       pr_info("Warning: The ALi m5602 webcam probably won't work until it's power cycled\n");
+}
+
+static int m5602_probe_sensor(struct sd *sd)
+{
+       /* Try the po1030 */
+       sd->sensor = &po1030;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       /* Try the mt9m111 sensor */
+       sd->sensor = &mt9m111;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       /* Try the s5k4aa */
+       sd->sensor = &s5k4aa;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       /* Try the ov9650 */
+       sd->sensor = &ov9650;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       /* Try the ov7660 */
+       sd->sensor = &ov7660;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       /* Try the s5k83a */
+       sd->sensor = &s5k83a;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       /* More sensor probe function goes here */
+       pr_info("Failed to find a sensor\n");
+       sd->sensor = NULL;
+       return -ENODEV;
+}
+
+static int m5602_configure(struct gspca_dev *gspca_dev,
+                          const struct usb_device_id *id);
+
+static int m5602_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int err;
+
+       PDEBUG(D_CONF, "Initializing ALi m5602 webcam");
+       /* Run the init sequence */
+       err = sd->sensor->init(sd);
+
+       return err;
+}
+
+static int m5602_start_transfer(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+       int err;
+
+       /* Send start command to the camera */
+       const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01};
+
+       if (sd->sensor->start)
+               sd->sensor->start(sd);
+
+       memcpy(buf, buffer, sizeof(buffer));
+       err = usb_control_msg(gspca_dev->dev,
+                             usb_sndctrlpipe(gspca_dev->dev, 0),
+                             0x04, 0x40, 0x19, 0x0000, buf,
+                             sizeof(buffer), M5602_URB_MSG_TIMEOUT);
+
+       PDEBUG(D_STREAM, "Transfer started");
+       return (err < 0) ? err : 0;
+}
+
+static void m5602_urb_complete(struct gspca_dev *gspca_dev,
+                               u8 *data, int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (len < 6) {
+               PDEBUG(D_PACK, "Packet is less than 6 bytes");
+               return;
+       }
+
+       /* Frame delimiter: ff xx xx xx ff ff */
+       if (data[0] == 0xff && data[4] == 0xff && data[5] == 0xff &&
+           data[2] != sd->frame_id) {
+               PDEBUG(D_FRAM, "Frame delimiter detected");
+               sd->frame_id = data[2];
+
+               /* Remove the extra fluff appended on each header */
+               data += 6;
+               len -= 6;
+
+               /* Complete the last frame (if any) */
+               gspca_frame_add(gspca_dev, LAST_PACKET,
+                               NULL, 0);
+               sd->frame_count++;
+
+               /* Create a new frame */
+               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
+
+               PDEBUG(D_FRAM, "Starting new frame %d",
+                      sd->frame_count);
+
+       } else {
+               int cur_frame_len;
+
+               cur_frame_len = gspca_dev->image_len;
+               /* Remove urb header */
+               data += 4;
+               len -= 4;
+
+               if (cur_frame_len + len <= gspca_dev->frsz) {
+                       PDEBUG(D_FRAM, "Continuing frame %d copying %d bytes",
+                              sd->frame_count, len);
+
+                       gspca_frame_add(gspca_dev, INTER_PACKET,
+                                       data, len);
+               } else {
+                       /* Add the remaining data up to frame size */
+                       gspca_frame_add(gspca_dev, INTER_PACKET, data,
+                                   gspca_dev->frsz - cur_frame_len);
+               }
+       }
+}
+
+static void m5602_stop_transfer(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* Run the sensor specific end transfer sequence */
+       if (sd->sensor->stop)
+               sd->sensor->stop(sd);
+}
+
+/* sub-driver description, the ctrl and nctrl is filled at probe time */
+static struct sd_desc sd_desc = {
+       .name           = MODULE_NAME,
+       .config         = m5602_configure,
+       .init           = m5602_init,
+       .start          = m5602_start_transfer,
+       .stopN          = m5602_stop_transfer,
+       .pkt_scan       = m5602_urb_complete
+};
+
+/* this function is called at probe time */
+static int m5602_configure(struct gspca_dev *gspca_dev,
+                          const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+       int err;
+
+       cam = &gspca_dev->cam;
+       sd->desc = &sd_desc;
+
+       if (dump_bridge)
+               m5602_dump_bridge(sd);
+
+       /* Probe sensor */
+       err = m5602_probe_sensor(sd);
+       if (err)
+               goto fail;
+
+       return 0;
+
+fail:
+       PDEBUG(D_ERR, "ALi m5602 webcam failed");
+       cam->cam_mode = NULL;
+       cam->nmodes = 0;
+
+       return err;
+}
+
+static int m5602_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 void m5602_disconnect(struct usb_interface *intf)
+{
+       struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor->disconnect)
+               sd->sensor->disconnect(sd);
+
+       gspca_disconnect(intf);
+}
+
+static struct usb_driver sd_driver = {
+       .name = MODULE_NAME,
+       .id_table = m5602_table,
+       .probe = m5602_probe,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+       .reset_resume = gspca_resume,
+#endif
+       .disconnect = m5602_disconnect
+};
+
+module_usb_driver(sd_driver);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+module_param(force_sensor, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(force_sensor,
+               "forces detection of a sensor, "
+               "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, "
+               "4 = MT9M111, 5 = PO1030, 6 = OV7660");
+
+module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
+
+module_param(dump_sensor, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dump_sensor, "Dumps all usb sensor registers "
+               "at startup providing a sensor is found");
diff --git a/drivers/media/usb/gspca/m5602/m5602_mt9m111.c b/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
new file mode 100644 (file)
index 0000000..6268aa2
--- /dev/null
@@ -0,0 +1,647 @@
+/*
+ * Driver for the mt9m111 sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "m5602_mt9m111.h"
+
+static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
+                                        __s32 val);
+static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
+                                         __s32 *val);
+static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+
+static struct v4l2_pix_format mt9m111_modes[] = {
+       {
+               640,
+               480,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage = 640 * 480,
+               .bytesperline = 640,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0
+       }
+};
+
+static const struct ctrl mt9m111_ctrls[] = {
+#define VFLIP_IDX 0
+       {
+               {
+                       .id             = V4L2_CID_VFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "vertical flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = mt9m111_set_vflip,
+               .get = mt9m111_get_vflip
+       },
+#define HFLIP_IDX 1
+       {
+               {
+                       .id             = V4L2_CID_HFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "horizontal flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = mt9m111_set_hflip,
+               .get = mt9m111_get_hflip
+       },
+#define GAIN_IDX 2
+       {
+               {
+                       .id             = V4L2_CID_GAIN,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "gain",
+                       .minimum        = 0,
+                       .maximum        = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
+                       .step           = 1,
+                       .default_value  = MT9M111_DEFAULT_GAIN,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = mt9m111_set_gain,
+               .get = mt9m111_get_gain
+       },
+#define AUTO_WHITE_BALANCE_IDX 3
+       {
+               {
+                       .id             = V4L2_CID_AUTO_WHITE_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "auto white balance",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0,
+               },
+               .set = mt9m111_set_auto_white_balance,
+               .get = mt9m111_get_auto_white_balance
+       },
+#define GREEN_BALANCE_IDX 4
+       {
+               {
+                       .id             = M5602_V4L2_CID_GREEN_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "green balance",
+                       .minimum        = 0x00,
+                       .maximum        = 0x7ff,
+                       .step           = 0x1,
+                       .default_value  = MT9M111_GREEN_GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = mt9m111_set_green_balance,
+               .get = mt9m111_get_green_balance
+       },
+#define BLUE_BALANCE_IDX 5
+       {
+               {
+                       .id             = V4L2_CID_BLUE_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "blue balance",
+                       .minimum        = 0x00,
+                       .maximum        = 0x7ff,
+                       .step           = 0x1,
+                       .default_value  = MT9M111_BLUE_GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = mt9m111_set_blue_balance,
+               .get = mt9m111_get_blue_balance
+       },
+#define RED_BALANCE_IDX 5
+       {
+               {
+                       .id             = V4L2_CID_RED_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "red balance",
+                       .minimum        = 0x00,
+                       .maximum        = 0x7ff,
+                       .step           = 0x1,
+                       .default_value  = MT9M111_RED_GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = mt9m111_set_red_balance,
+               .get = mt9m111_get_red_balance
+       },
+};
+
+static void mt9m111_dump_registers(struct sd *sd);
+
+int mt9m111_probe(struct sd *sd)
+{
+       u8 data[2] = {0x00, 0x00};
+       int i;
+       s32 *sensor_settings;
+
+       if (force_sensor) {
+               if (force_sensor == MT9M111_SENSOR) {
+                       pr_info("Forcing a %s sensor\n", mt9m111.name);
+                       goto sensor_found;
+               }
+               /* If we want to force another sensor, don't try to probe this
+                * one */
+               return -ENODEV;
+       }
+
+       PDEBUG(D_PROBE, "Probing for a mt9m111 sensor");
+
+       /* Do the preinit */
+       for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
+               if (preinit_mt9m111[i][0] == BRIDGE) {
+                       m5602_write_bridge(sd,
+                               preinit_mt9m111[i][1],
+                               preinit_mt9m111[i][2]);
+               } else {
+                       data[0] = preinit_mt9m111[i][2];
+                       data[1] = preinit_mt9m111[i][3];
+                       m5602_write_sensor(sd,
+                               preinit_mt9m111[i][1], data, 2);
+               }
+       }
+
+       if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
+               return -ENODEV;
+
+       if ((data[0] == 0x14) && (data[1] == 0x3a)) {
+               pr_info("Detected a mt9m111 sensor\n");
+               goto sensor_found;
+       }
+
+       return -ENODEV;
+
+sensor_found:
+       sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32),
+                                 GFP_KERNEL);
+       if (!sensor_settings)
+               return -ENOMEM;
+
+       sd->gspca_dev.cam.cam_mode = mt9m111_modes;
+       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
+       sd->desc->ctrls = mt9m111_ctrls;
+       sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls);
+
+       for (i = 0; i < ARRAY_SIZE(mt9m111_ctrls); i++)
+               sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value;
+       sd->sensor_priv = sensor_settings;
+
+       return 0;
+}
+
+int mt9m111_init(struct sd *sd)
+{
+       int i, err = 0;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       /* Init the sensor */
+       for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
+               u8 data[2];
+
+               if (init_mt9m111[i][0] == BRIDGE) {
+                       err = m5602_write_bridge(sd,
+                               init_mt9m111[i][1],
+                               init_mt9m111[i][2]);
+               } else {
+                       data[0] = init_mt9m111[i][2];
+                       data[1] = init_mt9m111[i][3];
+                       err = m5602_write_sensor(sd,
+                               init_mt9m111[i][1], data, 2);
+               }
+       }
+
+       if (dump_sensor)
+               mt9m111_dump_registers(sd);
+
+       err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+       if (err < 0)
+               return err;
+
+       err = mt9m111_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
+       if (err < 0)
+               return err;
+
+       err = mt9m111_set_green_balance(&sd->gspca_dev,
+                                        sensor_settings[GREEN_BALANCE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = mt9m111_set_blue_balance(&sd->gspca_dev,
+                                        sensor_settings[BLUE_BALANCE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = mt9m111_set_red_balance(&sd->gspca_dev,
+                                       sensor_settings[RED_BALANCE_IDX]);
+       if (err < 0)
+               return err;
+
+       return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+}
+
+int mt9m111_start(struct sd *sd)
+{
+       int i, err = 0;
+       u8 data[2];
+       struct cam *cam = &sd->gspca_dev.cam;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1;
+       int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
+
+       for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) {
+               if (start_mt9m111[i][0] == BRIDGE) {
+                       err = m5602_write_bridge(sd,
+                               start_mt9m111[i][1],
+                               start_mt9m111[i][2]);
+               } else {
+                       data[0] = start_mt9m111[i][2];
+                       data[1] = start_mt9m111[i][3];
+                       err = m5602_write_sensor(sd,
+                               start_mt9m111[i][1], data, 2);
+               }
+       }
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
+       if (err < 0)
+               return err;
+
+       for (i = 0; i < 2 && !err; i++)
+               err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
+       if (err < 0)
+               return err;
+
+       for (i = 0; i < 2 && !err; i++)
+               err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
+                                (width >> 8) & 0xff);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+       if (err < 0)
+               return err;
+
+       switch (width) {
+       case 640:
+               PDEBUG(D_V4L2, "Configuring camera for VGA mode");
+               data[0] = MT9M111_RMB_OVER_SIZED;
+               data[1] = MT9M111_RMB_ROW_SKIP_2X |
+                         MT9M111_RMB_COLUMN_SKIP_2X |
+                         (sensor_settings[VFLIP_IDX] << 0) |
+                         (sensor_settings[HFLIP_IDX] << 1);
+
+               err = m5602_write_sensor(sd,
+                                        MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+               break;
+
+       case 320:
+               PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
+               data[0] = MT9M111_RMB_OVER_SIZED;
+               data[1] = MT9M111_RMB_ROW_SKIP_4X |
+                               MT9M111_RMB_COLUMN_SKIP_4X |
+                               (sensor_settings[VFLIP_IDX] << 0) |
+                               (sensor_settings[HFLIP_IDX] << 1);
+               err = m5602_write_sensor(sd,
+                                        MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+               break;
+       }
+       return err;
+}
+
+void mt9m111_disconnect(struct sd *sd)
+{
+       sd->sensor = NULL;
+       kfree(sd->sensor_priv);
+}
+
+static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[VFLIP_IDX];
+       PDEBUG(D_V4L2, "Read vertical flip %d", *val);
+
+       return 0;
+}
+
+static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 data[2] = {0x00, 0x00};
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Set vertical flip to %d", val);
+
+       sensor_settings[VFLIP_IDX] = val;
+
+       /* The mt9m111 is flipped by default */
+       val = !val;
+
+       /* Set the correct page map */
+       err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+       if (err < 0)
+               return err;
+
+       err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+       if (err < 0)
+               return err;
+
+       data[1] = (data[1] & 0xfe) | val;
+       err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+                                  data, 2);
+       return err;
+}
+
+static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[HFLIP_IDX];
+       PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
+
+       return 0;
+}
+
+static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 data[2] = {0x00, 0x00};
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
+
+       sensor_settings[HFLIP_IDX] = val;
+
+       /* The mt9m111 is flipped by default */
+       val = !val;
+
+       /* Set the correct page map */
+       err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+       if (err < 0)
+               return err;
+
+       err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+       if (err < 0)
+               return err;
+
+       data[1] = (data[1] & 0xfd) | ((val << 1) & 0x02);
+       err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+                                       data, 2);
+       return err;
+}
+
+static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[GAIN_IDX];
+       PDEBUG(D_V4L2, "Read gain %d", *val);
+
+       return 0;
+}
+
+static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
+                                         __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       int err;
+       u8 data[2];
+
+       err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
+       if (err < 0)
+               return err;
+
+       sensor_settings[AUTO_WHITE_BALANCE_IDX] = val & 0x01;
+       data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1));
+
+       err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
+
+       PDEBUG(D_V4L2, "Set auto white balance %d", val);
+       return err;
+}
+
+static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
+                                         __s32 *val) {
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
+       PDEBUG(D_V4L2, "Read auto white balance %d", *val);
+       return 0;
+}
+
+static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err, tmp;
+       u8 data[2] = {0x00, 0x00};
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       sensor_settings[GAIN_IDX] = val;
+
+       /* Set the correct page map */
+       err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+       if (err < 0)
+               return err;
+
+       if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
+               return -EINVAL;
+
+       if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
+           (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
+               tmp = (1 << 10) | (val << 9) |
+                               (val << 8) | (val / 8);
+       else if ((val >= INITIAL_MAX_GAIN * 2) &&
+                (val <  INITIAL_MAX_GAIN * 2 * 2))
+               tmp = (1 << 9) | (1 << 8) | (val / 4);
+       else if ((val >= INITIAL_MAX_GAIN) &&
+                (val < INITIAL_MAX_GAIN * 2))
+               tmp = (1 << 8) | (val / 2);
+       else
+               tmp = val;
+
+       data[1] = (tmp & 0xff);
+       data[0] = (tmp & 0xff00) >> 8;
+       PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
+              data[1], data[0]);
+
+       err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
+                                  data, 2);
+
+       return err;
+}
+
+static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 data[2];
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       sensor_settings[GREEN_BALANCE_IDX] = val;
+       data[1] = (val & 0xff);
+       data[0] = (val & 0xff00) >> 8;
+
+       PDEBUG(D_V4L2, "Set green balance %d", val);
+       err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN,
+                                data, 2);
+       if (err < 0)
+               return err;
+
+       return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN,
+                                 data, 2);
+}
+
+static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[GREEN_BALANCE_IDX];
+       PDEBUG(D_V4L2, "Read green balance %d", *val);
+       return 0;
+}
+
+static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       u8 data[2];
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       sensor_settings[BLUE_BALANCE_IDX] = val;
+       data[1] = (val & 0xff);
+       data[0] = (val & 0xff00) >> 8;
+
+       PDEBUG(D_V4L2, "Set blue balance %d", val);
+
+       return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN,
+                                 data, 2);
+}
+
+static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[BLUE_BALANCE_IDX];
+       PDEBUG(D_V4L2, "Read blue balance %d", *val);
+       return 0;
+}
+
+static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       u8 data[2];
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       sensor_settings[RED_BALANCE_IDX] = val;
+       data[1] = (val & 0xff);
+       data[0] = (val & 0xff00) >> 8;
+
+       PDEBUG(D_V4L2, "Set red balance %d", val);
+
+       return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN,
+                                 data, 2);
+}
+
+static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[RED_BALANCE_IDX];
+       PDEBUG(D_V4L2, "Read red balance %d", *val);
+       return 0;
+}
+
+static void mt9m111_dump_registers(struct sd *sd)
+{
+       u8 address, value[2] = {0x00, 0x00};
+
+       pr_info("Dumping the mt9m111 register state\n");
+
+       pr_info("Dumping the mt9m111 sensor core registers\n");
+       value[1] = MT9M111_SENSOR_CORE;
+       m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+       for (address = 0; address < 0xff; address++) {
+               m5602_read_sensor(sd, address, value, 2);
+               pr_info("register 0x%x contains 0x%x%x\n",
+                       address, value[0], value[1]);
+       }
+
+       pr_info("Dumping the mt9m111 color pipeline registers\n");
+       value[1] = MT9M111_COLORPIPE;
+       m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+       for (address = 0; address < 0xff; address++) {
+               m5602_read_sensor(sd, address, value, 2);
+               pr_info("register 0x%x contains 0x%x%x\n",
+                       address, value[0], value[1]);
+       }
+
+       pr_info("Dumping the mt9m111 camera control registers\n");
+       value[1] = MT9M111_CAMERA_CONTROL;
+       m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+       for (address = 0; address < 0xff; address++) {
+               m5602_read_sensor(sd, address, value, 2);
+               pr_info("register 0x%x contains 0x%x%x\n",
+                       address, value[0], value[1]);
+       }
+
+       pr_info("mt9m111 register state dump complete\n");
+}
diff --git a/drivers/media/usb/gspca/m5602/m5602_mt9m111.h b/drivers/media/usb/gspca/m5602/m5602_mt9m111.h
new file mode 100644 (file)
index 0000000..8c672b5
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Driver for the mt9m111 sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * Some defines taken from the mt9m111 sensor driver
+ * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#ifndef M5602_MT9M111_H_
+#define M5602_MT9M111_H_
+
+#include "m5602_sensor.h"
+
+/*****************************************************************************/
+
+#define MT9M111_SC_CHIPVER                     0x00
+#define MT9M111_SC_ROWSTART                    0x01
+#define MT9M111_SC_COLSTART                    0x02
+#define MT9M111_SC_WINDOW_HEIGHT               0x03
+#define MT9M111_SC_WINDOW_WIDTH                        0x04
+#define MT9M111_SC_HBLANK_CONTEXT_B            0x05
+#define MT9M111_SC_VBLANK_CONTEXT_B            0x06
+#define MT9M111_SC_HBLANK_CONTEXT_A            0x07
+#define MT9M111_SC_VBLANK_CONTEXT_A            0x08
+#define MT9M111_SC_SHUTTER_WIDTH               0x09
+#define MT9M111_SC_ROW_SPEED                   0x0a
+#define MT9M111_SC_EXTRA_DELAY                 0x0b
+#define MT9M111_SC_SHUTTER_DELAY               0x0c
+#define MT9M111_SC_RESET                       0x0d
+#define MT9M111_SC_R_MODE_CONTEXT_B            0x20
+#define MT9M111_SC_R_MODE_CONTEXT_A            0x21
+#define MT9M111_SC_FLASH_CONTROL               0x23
+#define MT9M111_SC_GREEN_1_GAIN                        0x2b
+#define MT9M111_SC_BLUE_GAIN                   0x2c
+#define MT9M111_SC_RED_GAIN                    0x2d
+#define MT9M111_SC_GREEN_2_GAIN                        0x2e
+#define MT9M111_SC_GLOBAL_GAIN                 0x2f
+
+#define MT9M111_CONTEXT_CONTROL                        0xc8
+#define MT9M111_PAGE_MAP                       0xf0
+#define MT9M111_BYTEWISE_ADDRESS               0xf1
+
+#define MT9M111_CP_OPERATING_MODE_CTL          0x06
+#define MT9M111_CP_LUMA_OFFSET                 0x34
+#define MT9M111_CP_LUMA_CLIP                   0x35
+#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A 0x3a
+#define MT9M111_CP_LENS_CORRECTION_1           0x3b
+#define MT9M111_CP_DEFECT_CORR_CONTEXT_A       0x4c
+#define MT9M111_CP_DEFECT_CORR_CONTEXT_B       0x4d
+#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B 0x9b
+#define MT9M111_CP_GLOBAL_CLK_CONTROL          0xb3
+
+#define MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18   0x65
+#define MT9M111_CC_AWB_PARAMETER_7             0x28
+
+#define MT9M111_SENSOR_CORE                    0x00
+#define MT9M111_COLORPIPE                      0x01
+#define MT9M111_CAMERA_CONTROL                 0x02
+
+#define MT9M111_RESET                          (1 << 0)
+#define MT9M111_RESTART                                (1 << 1)
+#define MT9M111_ANALOG_STANDBY                 (1 << 2)
+#define MT9M111_CHIP_ENABLE                    (1 << 3)
+#define MT9M111_CHIP_DISABLE                   (0 << 3)
+#define MT9M111_OUTPUT_DISABLE                 (1 << 4)
+#define MT9M111_SHOW_BAD_FRAMES                        (1 << 0)
+#define MT9M111_RESTART_BAD_FRAMES             (1 << 1)
+#define MT9M111_SYNCHRONIZE_CHANGES            (1 << 7)
+
+#define MT9M111_RMB_OVER_SIZED                 (1 << 0)
+#define MT9M111_RMB_MIRROR_ROWS                        (1 << 0)
+#define MT9M111_RMB_MIRROR_COLS                        (1 << 1)
+#define MT9M111_RMB_ROW_SKIP_2X                        (1 << 2)
+#define MT9M111_RMB_COLUMN_SKIP_2X             (1 << 3)
+#define MT9M111_RMB_ROW_SKIP_4X                        (1 << 4)
+#define MT9M111_RMB_COLUMN_SKIP_4X             (1 << 5)
+
+#define MT9M111_COLOR_MATRIX_BYPASS            (1 << 4)
+#define MT9M111_SEL_CONTEXT_B                  (1 << 3)
+
+#define MT9M111_TRISTATE_PIN_IN_STANDBY                (1 << 1)
+#define MT9M111_SOC_SOFT_STANDBY               (1 << 0)
+
+#define MT9M111_2D_DEFECT_CORRECTION_ENABLE    (1 << 0)
+
+#define INITIAL_MAX_GAIN                       64
+#define MT9M111_DEFAULT_GAIN                   283
+#define MT9M111_GREEN_GAIN_DEFAULT             0x20
+#define MT9M111_BLUE_GAIN_DEFAULT              0x20
+#define MT9M111_RED_GAIN_DEFAULT               0x20
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern bool dump_sensor;
+
+int mt9m111_probe(struct sd *sd);
+int mt9m111_init(struct sd *sd);
+int mt9m111_start(struct sd *sd);
+void mt9m111_disconnect(struct sd *sd);
+
+static const struct m5602_sensor mt9m111 = {
+       .name = "MT9M111",
+
+       .i2c_slave_id = 0xba,
+       .i2c_regW = 2,
+
+       .probe = mt9m111_probe,
+       .init = mt9m111_init,
+       .disconnect = mt9m111_disconnect,
+       .start = mt9m111_start,
+};
+
+static const unsigned char preinit_mt9m111[][4] = {
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET,
+               MT9M111_RESET |
+               MT9M111_RESTART |
+               MT9M111_ANALOG_STANDBY |
+               MT9M111_CHIP_DISABLE,
+               MT9M111_SHOW_BAD_FRAMES |
+               MT9M111_RESTART_BAD_FRAMES |
+               MT9M111_SYNCHRONIZE_CHANGES},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}
+};
+
+static const unsigned char init_mt9m111[][4] = {
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
+
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
+       {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00,
+                       MT9M111_CP_OPERATING_MODE_CTL},
+       {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
+       {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00,
+                               MT9M111_2D_DEFECT_CORRECTION_ENABLE},
+       {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00,
+                               MT9M111_2D_DEFECT_CORRECTION_ENABLE},
+       {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
+       {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
+       {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
+       {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
+       {SENSOR, 0xcd, 0x00, 0x0e},
+       {SENSOR, 0xd0, 0x00, 0x40},
+
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
+       {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
+       {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
+
+       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, 0x33, 0x03, 0x49},
+       {SENSOR, 0x34, 0xc0, 0x19},
+       {SENSOR, 0x3f, 0x20, 0x20},
+       {SENSOR, 0x40, 0x20, 0x20},
+       {SENSOR, 0x5a, 0xc0, 0x0a},
+       {SENSOR, 0x70, 0x7b, 0x0a},
+       {SENSOR, 0x71, 0xff, 0x00},
+       {SENSOR, 0x72, 0x19, 0x0e},
+       {SENSOR, 0x73, 0x18, 0x0f},
+       {SENSOR, 0x74, 0x57, 0x32},
+       {SENSOR, 0x75, 0x56, 0x34},
+       {SENSOR, 0x76, 0x73, 0x35},
+       {SENSOR, 0x77, 0x30, 0x12},
+       {SENSOR, 0x78, 0x79, 0x02},
+       {SENSOR, 0x79, 0x75, 0x06},
+       {SENSOR, 0x7a, 0x77, 0x0a},
+       {SENSOR, 0x7b, 0x78, 0x09},
+       {SENSOR, 0x7c, 0x7d, 0x06},
+       {SENSOR, 0x7d, 0x31, 0x10},
+       {SENSOR, 0x7e, 0x00, 0x7e},
+       {SENSOR, 0x80, 0x59, 0x04},
+       {SENSOR, 0x81, 0x59, 0x04},
+       {SENSOR, 0x82, 0x57, 0x0a},
+       {SENSOR, 0x83, 0x58, 0x0b},
+       {SENSOR, 0x84, 0x47, 0x0c},
+       {SENSOR, 0x85, 0x48, 0x0e},
+       {SENSOR, 0x86, 0x5b, 0x02},
+       {SENSOR, 0x87, 0x00, 0x5c},
+       {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, MT9M111_SEL_CONTEXT_B},
+       {SENSOR, 0x60, 0x00, 0x80},
+       {SENSOR, 0x61, 0x00, 0x00},
+       {SENSOR, 0x62, 0x00, 0x00},
+       {SENSOR, 0x63, 0x00, 0x00},
+       {SENSOR, 0x64, 0x00, 0x00},
+
+       {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, /* 13 */
+       {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, /* 18 */
+       {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, /* 1024 */
+       {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, /* 1296 */
+       {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, /* 352 */
+       {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, /* 17 */
+       {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, /* 352 */
+       {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, /* 17 */
+       {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, /* 271 */
+       {SENSOR, 0x30, 0x04, 0x00},
+       /* Set number of blank rows chosen to 400 */
+       {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
+};
+
+static const unsigned char start_mt9m111[][4] = {
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+};
+#endif
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov7660.c b/drivers/media/usb/gspca/m5602/m5602_ov7660.c
new file mode 100644 (file)
index 0000000..9a14835
--- /dev/null
@@ -0,0 +1,488 @@
+/*
+ * Driver for the ov7660 sensor
+ *
+ * Copyright (C) 2009 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "m5602_ov7660.h"
+
+static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
+                                        __s32 *val);
+static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
+                                        __s32 val);
+static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+
+static const struct ctrl ov7660_ctrls[] = {
+#define GAIN_IDX 1
+       {
+               {
+                       .id             = V4L2_CID_GAIN,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "gain",
+                       .minimum        = 0x00,
+                       .maximum        = 0xff,
+                       .step           = 0x1,
+                       .default_value  = OV7660_DEFAULT_GAIN,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = ov7660_set_gain,
+               .get = ov7660_get_gain
+       },
+#define BLUE_BALANCE_IDX 2
+#define RED_BALANCE_IDX 3
+#define AUTO_WHITE_BALANCE_IDX 4
+       {
+               {
+                       .id             = V4L2_CID_AUTO_WHITE_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "auto white balance",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 1
+               },
+               .set = ov7660_set_auto_white_balance,
+               .get = ov7660_get_auto_white_balance
+       },
+#define AUTO_GAIN_CTRL_IDX 5
+       {
+               {
+                       .id             = V4L2_CID_AUTOGAIN,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "auto gain control",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 1
+               },
+               .set = ov7660_set_auto_gain,
+               .get = ov7660_get_auto_gain
+       },
+#define AUTO_EXPOSURE_IDX 6
+       {
+               {
+                       .id             = V4L2_CID_EXPOSURE_AUTO,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "auto exposure",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 1
+               },
+               .set = ov7660_set_auto_exposure,
+               .get = ov7660_get_auto_exposure
+       },
+#define HFLIP_IDX 7
+       {
+               {
+                       .id             = V4L2_CID_HFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "horizontal flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = ov7660_set_hflip,
+               .get = ov7660_get_hflip
+       },
+#define VFLIP_IDX 8
+       {
+               {
+                       .id             = V4L2_CID_VFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "vertical flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = ov7660_set_vflip,
+               .get = ov7660_get_vflip
+       },
+
+};
+
+static struct v4l2_pix_format ov7660_modes[] = {
+       {
+               640,
+               480,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       640 * 480,
+               .bytesperline = 640,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0
+       }
+};
+
+static void ov7660_dump_registers(struct sd *sd);
+
+int ov7660_probe(struct sd *sd)
+{
+       int err = 0, i;
+       u8 prod_id = 0, ver_id = 0;
+
+       s32 *sensor_settings;
+
+       if (force_sensor) {
+               if (force_sensor == OV7660_SENSOR) {
+                       pr_info("Forcing an %s sensor\n", ov7660.name);
+                       goto sensor_found;
+               }
+               /* If we want to force another sensor,
+               don't try to probe this one */
+               return -ENODEV;
+       }
+
+       /* Do the preinit */
+       for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) {
+               u8 data[2];
+
+               if (preinit_ov7660[i][0] == BRIDGE) {
+                       err = m5602_write_bridge(sd,
+                               preinit_ov7660[i][1],
+                               preinit_ov7660[i][2]);
+               } else {
+                       data[0] = preinit_ov7660[i][2];
+                       err = m5602_write_sensor(sd,
+                               preinit_ov7660[i][1], data, 1);
+               }
+       }
+       if (err < 0)
+               return err;
+
+       if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1))
+               return -ENODEV;
+
+       if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1))
+               return -ENODEV;
+
+       pr_info("Sensor reported 0x%x%x\n", prod_id, ver_id);
+
+       if ((prod_id == 0x76) && (ver_id == 0x60)) {
+               pr_info("Detected a ov7660 sensor\n");
+               goto sensor_found;
+       }
+       return -ENODEV;
+
+sensor_found:
+       sensor_settings = kmalloc(
+               ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL);
+       if (!sensor_settings)
+               return -ENOMEM;
+
+       sd->gspca_dev.cam.cam_mode = ov7660_modes;
+       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes);
+       sd->desc->ctrls = ov7660_ctrls;
+       sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls);
+
+       for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++)
+               sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value;
+       sd->sensor_priv = sensor_settings;
+
+       return 0;
+}
+
+int ov7660_init(struct sd *sd)
+{
+       int i, err = 0;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       /* Init the sensor */
+       for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) {
+               u8 data[2];
+
+               if (init_ov7660[i][0] == BRIDGE) {
+                       err = m5602_write_bridge(sd,
+                               init_ov7660[i][1],
+                               init_ov7660[i][2]);
+               } else {
+                       data[0] = init_ov7660[i][2];
+                       err = m5602_write_sensor(sd,
+                               init_ov7660[i][1], data, 1);
+               }
+       }
+
+       if (dump_sensor)
+               ov7660_dump_registers(sd);
+
+       err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+       if (err < 0)
+               return err;
+
+       err = ov7660_set_auto_white_balance(&sd->gspca_dev,
+               sensor_settings[AUTO_WHITE_BALANCE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = ov7660_set_auto_gain(&sd->gspca_dev,
+               sensor_settings[AUTO_GAIN_CTRL_IDX]);
+       if (err < 0)
+               return err;
+
+       err = ov7660_set_auto_exposure(&sd->gspca_dev,
+               sensor_settings[AUTO_EXPOSURE_IDX]);
+       if (err < 0)
+               return err;
+       err = ov7660_set_hflip(&sd->gspca_dev,
+               sensor_settings[HFLIP_IDX]);
+       if (err < 0)
+               return err;
+
+       err = ov7660_set_vflip(&sd->gspca_dev,
+               sensor_settings[VFLIP_IDX]);
+
+       return err;
+}
+
+int ov7660_start(struct sd *sd)
+{
+       return 0;
+}
+
+int ov7660_stop(struct sd *sd)
+{
+       return 0;
+}
+
+void ov7660_disconnect(struct sd *sd)
+{
+       ov7660_stop(sd);
+
+       sd->sensor = NULL;
+       kfree(sd->sensor_priv);
+}
+
+static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[GAIN_IDX];
+       PDEBUG(D_V4L2, "Read gain %d", *val);
+       return 0;
+}
+
+static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Setting gain to %d", val);
+
+       sensor_settings[GAIN_IDX] = val;
+
+       err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1);
+       return err;
+}
+
+
+static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
+                                        __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
+       return 0;
+}
+
+static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
+                                        __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Set auto white balance to %d", val);
+
+       sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
+       err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
+       err = m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
+
+       return err;
+}
+
+static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
+       PDEBUG(D_V4L2, "Read auto gain control %d", *val);
+       return 0;
+}
+
+static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Set auto gain control to %d", val);
+
+       sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
+       err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
+
+       return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
+}
+
+static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[AUTO_EXPOSURE_IDX];
+       PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
+       return 0;
+}
+
+static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev,
+                                   __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
+
+       sensor_settings[AUTO_EXPOSURE_IDX] = val;
+       err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
+
+       return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
+}
+
+static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[HFLIP_IDX];
+       PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
+       return 0;
+}
+
+static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
+
+       sensor_settings[HFLIP_IDX] = val;
+
+       i2c_data = ((val & 0x01) << 5) |
+               (sensor_settings[VFLIP_IDX] << 4);
+
+       err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
+
+       return err;
+}
+
+static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[VFLIP_IDX];
+       PDEBUG(D_V4L2, "Read vertical flip %d", *val);
+
+       return 0;
+}
+
+static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Set vertical flip to %d", val);
+       sensor_settings[VFLIP_IDX] = val;
+
+       i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
+       err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       /* When vflip is toggled we need to readjust the bridge hsync/vsync */
+       if (gspca_dev->streaming)
+               err = ov7660_start(sd);
+
+       return err;
+}
+
+static void ov7660_dump_registers(struct sd *sd)
+{
+       int address;
+       pr_info("Dumping the ov7660 register state\n");
+       for (address = 0; address < 0xa9; address++) {
+               u8 value;
+               m5602_read_sensor(sd, address, &value, 1);
+               pr_info("register 0x%x contains 0x%x\n", address, value);
+       }
+
+       pr_info("ov7660 register state dump complete\n");
+
+       pr_info("Probing for which registers that are read/write\n");
+       for (address = 0; address < 0xff; address++) {
+               u8 old_value, ctrl_value;
+               u8 test_value[2] = {0xff, 0xff};
+
+               m5602_read_sensor(sd, address, &old_value, 1);
+               m5602_write_sensor(sd, address, test_value, 1);
+               m5602_read_sensor(sd, address, &ctrl_value, 1);
+
+               if (ctrl_value == test_value[0])
+                       pr_info("register 0x%x is writeable\n", address);
+               else
+                       pr_info("register 0x%x is read only\n", address);
+
+               /* Restore original value */
+               m5602_write_sensor(sd, address, &old_value, 1);
+       }
+}
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov7660.h b/drivers/media/usb/gspca/m5602/m5602_ov7660.h
new file mode 100644 (file)
index 0000000..2b6a13b
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Driver for the ov7660 sensor
+ *
+ * Copyright (C) 2009 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#ifndef M5602_OV7660_H_
+#define M5602_OV7660_H_
+
+#include "m5602_sensor.h"
+
+#define OV7660_GAIN            0x00
+#define OV7660_BLUE_GAIN       0x01
+#define OV7660_RED_GAIN                0x02
+#define OV7660_VREF            0x03
+#define OV7660_COM1            0x04
+#define OV7660_BAVE            0x05
+#define OV7660_GEAVE           0x06
+#define OV7660_AECHH           0x07
+#define OV7660_RAVE            0x08
+#define OV7660_COM2            0x09
+#define OV7660_PID             0x0a
+#define OV7660_VER             0x0b
+#define OV7660_COM3            0x0c
+#define OV7660_COM4            0x0d
+#define OV7660_COM5            0x0e
+#define OV7660_COM6            0x0f
+#define OV7660_AECH            0x10
+#define OV7660_CLKRC           0x11
+#define OV7660_COM7            0x12
+#define OV7660_COM8            0x13
+#define OV7660_COM9            0x14
+#define OV7660_COM10           0x15
+#define OV7660_RSVD16          0x16
+#define OV7660_HSTART          0x17
+#define OV7660_HSTOP           0x18
+#define OV7660_VSTART          0x19
+#define OV7660_VSTOP           0x1a
+#define OV7660_PSHFT           0x1b
+#define OV7660_MIDH            0x1c
+#define OV7660_MIDL            0x1d
+#define OV7660_MVFP            0x1e
+#define OV7660_LAEC            0x1f
+#define OV7660_BOS             0x20
+#define OV7660_GBOS            0x21
+#define OV7660_GROS            0x22
+#define OV7660_ROS             0x23
+#define OV7660_AEW             0x24
+#define OV7660_AEB             0x25
+#define OV7660_VPT             0x26
+#define OV7660_BBIAS           0x27
+#define OV7660_GbBIAS          0x28
+#define OV7660_RSVD29          0x29
+#define OV7660_RBIAS           0x2c
+#define OV7660_HREF            0x32
+#define OV7660_ADC             0x37
+#define OV7660_OFON            0x39
+#define OV7660_TSLB            0x3a
+#define OV7660_COM12           0x3c
+#define OV7660_COM13           0x3d
+#define OV7660_LCC1            0x62
+#define OV7660_LCC2            0x63
+#define OV7660_LCC3            0x64
+#define OV7660_LCC4            0x65
+#define OV7660_LCC5            0x66
+#define OV7660_HV              0x69
+#define OV7660_RSVDA1          0xa1
+
+#define OV7660_DEFAULT_GAIN            0x0e
+#define OV7660_DEFAULT_RED_GAIN                0x80
+#define OV7660_DEFAULT_BLUE_GAIN       0x80
+#define OV7660_DEFAULT_SATURATION      0x00
+#define OV7660_DEFAULT_EXPOSURE                0x20
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern bool dump_sensor;
+
+int ov7660_probe(struct sd *sd);
+int ov7660_init(struct sd *sd);
+int ov7660_start(struct sd *sd);
+int ov7660_stop(struct sd *sd);
+void ov7660_disconnect(struct sd *sd);
+
+static const struct m5602_sensor ov7660 = {
+       .name = "ov7660",
+       .i2c_slave_id = 0x42,
+       .i2c_regW = 1,
+       .probe = ov7660_probe,
+       .init = ov7660_init,
+       .start = ov7660_start,
+       .stop = ov7660_stop,
+       .disconnect = ov7660_disconnect,
+};
+
+static const unsigned char preinit_ov7660[][4] = {
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x03},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x03},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+
+       {SENSOR, OV7660_OFON, 0x0c},
+       {SENSOR, OV7660_COM2, 0x11},
+       {SENSOR, OV7660_COM7, 0x05},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}
+};
+
+static const unsigned char init_ov7660[][4] = {
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
+       {SENSOR, OV7660_COM7, 0x80},
+       {SENSOR, OV7660_CLKRC, 0x80},
+       {SENSOR, OV7660_COM9, 0x4c},
+       {SENSOR, OV7660_OFON, 0x43},
+       {SENSOR, OV7660_COM12, 0x28},
+       {SENSOR, OV7660_COM8, 0x00},
+       {SENSOR, OV7660_COM10, 0x40},
+       {SENSOR, OV7660_HSTART, 0x0c},
+       {SENSOR, OV7660_HSTOP, 0x61},
+       {SENSOR, OV7660_HREF, 0xa4},
+       {SENSOR, OV7660_PSHFT, 0x0b},
+       {SENSOR, OV7660_VSTART, 0x01},
+       {SENSOR, OV7660_VSTOP, 0x7a},
+       {SENSOR, OV7660_VSTOP, 0x00},
+       {SENSOR, OV7660_COM7, 0x05},
+       {SENSOR, OV7660_COM6, 0x42},
+       {SENSOR, OV7660_BBIAS, 0x94},
+       {SENSOR, OV7660_GbBIAS, 0x94},
+       {SENSOR, OV7660_RSVD29, 0x94},
+       {SENSOR, OV7660_RBIAS, 0x94},
+       {SENSOR, OV7660_COM1, 0x00},
+       {SENSOR, OV7660_AECH, 0x00},
+       {SENSOR, OV7660_AECHH, 0x00},
+       {SENSOR, OV7660_ADC, 0x05},
+       {SENSOR, OV7660_COM13, 0x00},
+       {SENSOR, OV7660_RSVDA1, 0x23},
+       {SENSOR, OV7660_TSLB, 0x0d},
+       {SENSOR, OV7660_HV, 0x80},
+       {SENSOR, OV7660_LCC1, 0x00},
+       {SENSOR, OV7660_LCC2, 0x00},
+       {SENSOR, OV7660_LCC3, 0x10},
+       {SENSOR, OV7660_LCC4, 0x40},
+       {SENSOR, OV7660_LCC5, 0x01},
+
+       {SENSOR, OV7660_AECH, 0x20},
+       {SENSOR, OV7660_COM1, 0x00},
+       {SENSOR, OV7660_OFON, 0x0c},
+       {SENSOR, OV7660_COM2, 0x11},
+       {SENSOR, OV7660_COM7, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
+       {SENSOR, OV7660_AECH, 0x5f},
+       {SENSOR, OV7660_COM1, 0x03},
+       {SENSOR, OV7660_OFON, 0x0c},
+       {SENSOR, OV7660_COM2, 0x11},
+       {SENSOR, OV7660_COM7, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x08},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x27},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0xa7},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+};
+#endif
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov9650.c b/drivers/media/usb/gspca/m5602/m5602_ov9650.c
new file mode 100644 (file)
index 0000000..2114a8b
--- /dev/null
@@ -0,0 +1,881 @@
+/*
+ * Driver for the ov9650 sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "m5602_ov9650.h"
+
+static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
+                                        __s32 *val);
+static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
+                                        __s32 val);
+static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
+
+/* Vertically and horizontally flips the image if matched, needed for machines
+   where the sensor is mounted upside down */
+static
+    const
+       struct dmi_system_id ov9650_flip_dmi_table[] = {
+       {
+               .ident = "ASUS A6Ja",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
+               }
+       },
+       {
+               .ident = "ASUS A6JC",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
+               }
+       },
+       {
+               .ident = "ASUS A6K",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "A6K")
+               }
+       },
+       {
+               .ident = "ASUS A6Kt",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
+               }
+       },
+       {
+               .ident = "ASUS A6VA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "A6VA")
+               }
+       },
+       {
+
+               .ident = "ASUS A6VC",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
+               }
+       },
+       {
+               .ident = "ASUS A6VM",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
+               }
+       },
+       {
+               .ident = "ASUS A7V",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "A7V")
+               }
+       },
+       {
+               .ident = "Alienware Aurora m9700",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "alienware"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700")
+               }
+       },
+       {}
+};
+
+static const struct ctrl ov9650_ctrls[] = {
+#define EXPOSURE_IDX 0
+       {
+               {
+                       .id             = V4L2_CID_EXPOSURE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "exposure",
+                       .minimum        = 0x00,
+                       .maximum        = 0x1ff,
+                       .step           = 0x4,
+                       .default_value  = EXPOSURE_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = ov9650_set_exposure,
+               .get = ov9650_get_exposure
+       },
+#define GAIN_IDX 1
+       {
+               {
+                       .id             = V4L2_CID_GAIN,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "gain",
+                       .minimum        = 0x00,
+                       .maximum        = 0x3ff,
+                       .step           = 0x1,
+                       .default_value  = GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = ov9650_set_gain,
+               .get = ov9650_get_gain
+       },
+#define RED_BALANCE_IDX 2
+       {
+               {
+                       .id             = V4L2_CID_RED_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "red balance",
+                       .minimum        = 0x00,
+                       .maximum        = 0xff,
+                       .step           = 0x1,
+                       .default_value  = RED_GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = ov9650_set_red_balance,
+               .get = ov9650_get_red_balance
+       },
+#define BLUE_BALANCE_IDX 3
+       {
+               {
+                       .id             = V4L2_CID_BLUE_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "blue balance",
+                       .minimum        = 0x00,
+                       .maximum        = 0xff,
+                       .step           = 0x1,
+                       .default_value  = BLUE_GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = ov9650_set_blue_balance,
+               .get = ov9650_get_blue_balance
+       },
+#define HFLIP_IDX 4
+       {
+               {
+                       .id             = V4L2_CID_HFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "horizontal flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = ov9650_set_hflip,
+               .get = ov9650_get_hflip
+       },
+#define VFLIP_IDX 5
+       {
+               {
+                       .id             = V4L2_CID_VFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "vertical flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = ov9650_set_vflip,
+               .get = ov9650_get_vflip
+       },
+#define AUTO_WHITE_BALANCE_IDX 6
+       {
+               {
+                       .id             = V4L2_CID_AUTO_WHITE_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "auto white balance",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 1
+               },
+               .set = ov9650_set_auto_white_balance,
+               .get = ov9650_get_auto_white_balance
+       },
+#define AUTO_GAIN_CTRL_IDX 7
+       {
+               {
+                       .id             = V4L2_CID_AUTOGAIN,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "auto gain control",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 1
+               },
+               .set = ov9650_set_auto_gain,
+               .get = ov9650_get_auto_gain
+       },
+#define AUTO_EXPOSURE_IDX 8
+       {
+               {
+                       .id             = V4L2_CID_EXPOSURE_AUTO,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "auto exposure",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 1
+               },
+               .set = ov9650_set_auto_exposure,
+               .get = ov9650_get_auto_exposure
+       }
+
+};
+
+static struct v4l2_pix_format ov9650_modes[] = {
+       {
+               176,
+               144,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       176 * 144,
+               .bytesperline = 176,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 9
+       }, {
+               320,
+               240,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       320 * 240,
+               .bytesperline = 320,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 8
+       }, {
+               352,
+               288,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       352 * 288,
+               .bytesperline = 352,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 9
+       }, {
+               640,
+               480,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       640 * 480,
+               .bytesperline = 640,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 9
+       }
+};
+
+static void ov9650_dump_registers(struct sd *sd);
+
+int ov9650_probe(struct sd *sd)
+{
+       int err = 0;
+       u8 prod_id = 0, ver_id = 0, i;
+       s32 *sensor_settings;
+
+       if (force_sensor) {
+               if (force_sensor == OV9650_SENSOR) {
+                       pr_info("Forcing an %s sensor\n", ov9650.name);
+                       goto sensor_found;
+               }
+               /* If we want to force another sensor,
+                  don't try to probe this one */
+               return -ENODEV;
+       }
+
+       PDEBUG(D_PROBE, "Probing for an ov9650 sensor");
+
+       /* Run the pre-init before probing the sensor */
+       for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) {
+               u8 data = preinit_ov9650[i][2];
+               if (preinit_ov9650[i][0] == SENSOR)
+                       err = m5602_write_sensor(sd,
+                               preinit_ov9650[i][1], &data, 1);
+               else
+                       err = m5602_write_bridge(sd,
+                               preinit_ov9650[i][1], data);
+       }
+
+       if (err < 0)
+               return err;
+
+       if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1))
+               return -ENODEV;
+
+       if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1))
+               return -ENODEV;
+
+       if ((prod_id == 0x96) && (ver_id == 0x52)) {
+               pr_info("Detected an ov9650 sensor\n");
+               goto sensor_found;
+       }
+       return -ENODEV;
+
+sensor_found:
+       sensor_settings = kmalloc(
+               ARRAY_SIZE(ov9650_ctrls) * sizeof(s32), GFP_KERNEL);
+       if (!sensor_settings)
+               return -ENOMEM;
+
+       sd->gspca_dev.cam.cam_mode = ov9650_modes;
+       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
+       sd->desc->ctrls = ov9650_ctrls;
+       sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls);
+
+       for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++)
+               sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value;
+       sd->sensor_priv = sensor_settings;
+       return 0;
+}
+
+int ov9650_init(struct sd *sd)
+{
+       int i, err = 0;
+       u8 data;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       if (dump_sensor)
+               ov9650_dump_registers(sd);
+
+       for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
+               data = init_ov9650[i][2];
+               if (init_ov9650[i][0] == SENSOR)
+                       err = m5602_write_sensor(sd, init_ov9650[i][1],
+                                                 &data, 1);
+               else
+                       err = m5602_write_bridge(sd, init_ov9650[i][1], data);
+       }
+
+       err = ov9650_set_exposure(&sd->gspca_dev,
+                                  sensor_settings[EXPOSURE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = ov9650_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+       if (err < 0)
+               return err;
+
+       err = ov9650_set_red_balance(&sd->gspca_dev,
+                                     sensor_settings[RED_BALANCE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = ov9650_set_blue_balance(&sd->gspca_dev,
+                                      sensor_settings[BLUE_BALANCE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = ov9650_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
+       if (err < 0)
+               return err;
+
+       err = ov9650_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+       if (err < 0)
+               return err;
+
+       err = ov9650_set_auto_exposure(&sd->gspca_dev,
+                               sensor_settings[AUTO_EXPOSURE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = ov9650_set_auto_white_balance(&sd->gspca_dev,
+                               sensor_settings[AUTO_WHITE_BALANCE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = ov9650_set_auto_gain(&sd->gspca_dev,
+                               sensor_settings[AUTO_GAIN_CTRL_IDX]);
+       return err;
+}
+
+int ov9650_start(struct sd *sd)
+{
+       u8 data;
+       int i, err = 0;
+       struct cam *cam = &sd->gspca_dev.cam;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
+       int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
+       int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
+       int hor_offs = OV9650_LEFT_OFFSET;
+
+       if ((!dmi_check_system(ov9650_flip_dmi_table) &&
+               sensor_settings[VFLIP_IDX]) ||
+               (dmi_check_system(ov9650_flip_dmi_table) &&
+               !sensor_settings[VFLIP_IDX]))
+               ver_offs--;
+
+       if (width <= 320)
+               hor_offs /= 2;
+
+       /* Synthesize the vsync/hsync setup */
+       for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
+               if (res_init_ov9650[i][0] == BRIDGE)
+                       err = m5602_write_bridge(sd, res_init_ov9650[i][1],
+                               res_init_ov9650[i][2]);
+               else if (res_init_ov9650[i][0] == SENSOR) {
+                       data = res_init_ov9650[i][2];
+                       err = m5602_write_sensor(sd,
+                               res_init_ov9650[i][1], &data, 1);
+               }
+       }
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
+                                ((ver_offs >> 8) & 0xff));
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
+       if (err < 0)
+               return err;
+
+       for (i = 0; i < 2 && !err; i++)
+               err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
+                                (hor_offs >> 8) & 0xff);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
+                                ((width + hor_offs) >> 8) & 0xff);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
+                                ((width + hor_offs) & 0xff));
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+       if (err < 0)
+               return err;
+
+       switch (width) {
+       case 640:
+               PDEBUG(D_V4L2, "Configuring camera for VGA mode");
+
+               data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
+                      OV9650_RAW_RGB_SELECT;
+               err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
+               break;
+
+       case 352:
+               PDEBUG(D_V4L2, "Configuring camera for CIF mode");
+
+               data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
+                               OV9650_RAW_RGB_SELECT;
+               err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
+               break;
+
+       case 320:
+               PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
+
+               data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
+                               OV9650_RAW_RGB_SELECT;
+               err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
+               break;
+
+       case 176:
+               PDEBUG(D_V4L2, "Configuring camera for QCIF mode");
+
+               data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
+                       OV9650_RAW_RGB_SELECT;
+               err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
+               break;
+       }
+       return err;
+}
+
+int ov9650_stop(struct sd *sd)
+{
+       u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X;
+       return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
+}
+
+void ov9650_disconnect(struct sd *sd)
+{
+       ov9650_stop(sd);
+
+       sd->sensor = NULL;
+       kfree(sd->sensor_priv);
+}
+
+static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[EXPOSURE_IDX];
+       PDEBUG(D_V4L2, "Read exposure %d", *val);
+       return 0;
+}
+
+static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 i2c_data;
+       int err;
+
+       PDEBUG(D_V4L2, "Set exposure to %d", val);
+
+       sensor_settings[EXPOSURE_IDX] = val;
+       /* The 6 MSBs */
+       i2c_data = (val >> 10) & 0x3f;
+       err = m5602_write_sensor(sd, OV9650_AECHM,
+                                 &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       /* The 8 middle bits */
+       i2c_data = (val >> 2) & 0xff;
+       err = m5602_write_sensor(sd, OV9650_AECH,
+                                 &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       /* The 2 LSBs */
+       i2c_data = val & 0x03;
+       err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
+       return err;
+}
+
+static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[GAIN_IDX];
+       PDEBUG(D_V4L2, "Read gain %d", *val);
+       return 0;
+}
+
+static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Setting gain to %d", val);
+
+       sensor_settings[GAIN_IDX] = val;
+
+       /* The 2 MSB */
+       /* Read the OV9650_VREF register first to avoid
+          corrupting the VREF high and low bits */
+       err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       /* Mask away all uninteresting bits */
+       i2c_data = ((val & 0x0300) >> 2) |
+                       (i2c_data & 0x3f);
+       err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       /* The 8 LSBs */
+       i2c_data = val & 0xff;
+       err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
+       return err;
+}
+
+static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[RED_BALANCE_IDX];
+       PDEBUG(D_V4L2, "Read red gain %d", *val);
+       return 0;
+}
+
+static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Set red gain to %d", val);
+
+       sensor_settings[RED_BALANCE_IDX] = val;
+
+       i2c_data = val & 0xff;
+       err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
+       return err;
+}
+
+static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[BLUE_BALANCE_IDX];
+       PDEBUG(D_V4L2, "Read blue gain %d", *val);
+
+       return 0;
+}
+
+static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Set blue gain to %d", val);
+
+       sensor_settings[BLUE_BALANCE_IDX] = val;
+
+       i2c_data = val & 0xff;
+       err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
+       return err;
+}
+
+static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[HFLIP_IDX];
+       PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
+       return 0;
+}
+
+static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
+
+       sensor_settings[HFLIP_IDX] = val;
+
+       if (!dmi_check_system(ov9650_flip_dmi_table))
+               i2c_data = ((val & 0x01) << 5) |
+                               (sensor_settings[VFLIP_IDX] << 4);
+       else
+               i2c_data = ((val & 0x01) << 5) |
+                               (!sensor_settings[VFLIP_IDX] << 4);
+
+       err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+
+       return err;
+}
+
+static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[VFLIP_IDX];
+       PDEBUG(D_V4L2, "Read vertical flip %d", *val);
+
+       return 0;
+}
+
+static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Set vertical flip to %d", val);
+       sensor_settings[VFLIP_IDX] = val;
+
+       if (dmi_check_system(ov9650_flip_dmi_table))
+               val = !val;
+
+       i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
+       err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       /* When vflip is toggled we need to readjust the bridge hsync/vsync */
+       if (gspca_dev->streaming)
+               err = ov9650_start(sd);
+
+       return err;
+}
+
+static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[AUTO_EXPOSURE_IDX];
+       PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
+       return 0;
+}
+
+static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev,
+                                   __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
+
+       sensor_settings[AUTO_EXPOSURE_IDX] = val;
+       err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
+
+       return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
+}
+
+static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
+                                        __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
+       return 0;
+}
+
+static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
+                                        __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Set auto white balance to %d", val);
+
+       sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
+       err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
+       err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
+
+       return err;
+}
+
+static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
+       PDEBUG(D_V4L2, "Read auto gain control %d", *val);
+       return 0;
+}
+
+static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       PDEBUG(D_V4L2, "Set auto gain control to %d", val);
+
+       sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
+       err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
+
+       return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
+}
+
+static void ov9650_dump_registers(struct sd *sd)
+{
+       int address;
+       pr_info("Dumping the ov9650 register state\n");
+       for (address = 0; address < 0xa9; address++) {
+               u8 value;
+               m5602_read_sensor(sd, address, &value, 1);
+               pr_info("register 0x%x contains 0x%x\n", address, value);
+       }
+
+       pr_info("ov9650 register state dump complete\n");
+
+       pr_info("Probing for which registers that are read/write\n");
+       for (address = 0; address < 0xff; address++) {
+               u8 old_value, ctrl_value;
+               u8 test_value[2] = {0xff, 0xff};
+
+               m5602_read_sensor(sd, address, &old_value, 1);
+               m5602_write_sensor(sd, address, test_value, 1);
+               m5602_read_sensor(sd, address, &ctrl_value, 1);
+
+               if (ctrl_value == test_value[0])
+                       pr_info("register 0x%x is writeable\n", address);
+               else
+                       pr_info("register 0x%x is read only\n", address);
+
+               /* Restore original value */
+               m5602_write_sensor(sd, address, &old_value, 1);
+       }
+}
diff --git a/drivers/media/usb/gspca/m5602/m5602_ov9650.h b/drivers/media/usb/gspca/m5602/m5602_ov9650.h
new file mode 100644 (file)
index 0000000..f7aa5bf
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Driver for the ov9650 sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#ifndef M5602_OV9650_H_
+#define M5602_OV9650_H_
+
+#include <linux/dmi.h>
+#include "m5602_sensor.h"
+
+/*****************************************************************************/
+
+#define OV9650_GAIN                    0x00
+#define OV9650_BLUE                    0x01
+#define OV9650_RED                     0x02
+#define OV9650_VREF                    0x03
+#define OV9650_COM1                    0x04
+#define OV9650_BAVE                    0x05
+#define OV9650_GEAVE                   0x06
+#define OV9650_RSVD7                   0x07
+#define OV9650_COM2                    0x09
+#define OV9650_PID                     0x0a
+#define OV9650_VER                     0x0b
+#define OV9650_COM3                    0x0c
+#define OV9650_COM4                    0x0d
+#define OV9650_COM5                    0x0e
+#define OV9650_COM6                    0x0f
+#define OV9650_AECH                    0x10
+#define OV9650_CLKRC                   0x11
+#define OV9650_COM7                    0x12
+#define OV9650_COM8                    0x13
+#define OV9650_COM9                    0x14
+#define OV9650_COM10                   0x15
+#define OV9650_RSVD16                  0x16
+#define OV9650_HSTART                  0x17
+#define OV9650_HSTOP                   0x18
+#define OV9650_VSTRT                   0x19
+#define OV9650_VSTOP                   0x1a
+#define OV9650_PSHFT                   0x1b
+#define OV9650_MVFP                    0x1e
+#define OV9650_AEW                     0x24
+#define OV9650_AEB                     0x25
+#define OV9650_VPT                     0x26
+#define OV9650_BBIAS                   0x27
+#define OV9650_GbBIAS                  0x28
+#define OV9650_Gr_COM                  0x29
+#define OV9650_RBIAS                   0x2c
+#define OV9650_HREF                    0x32
+#define OV9650_CHLF                    0x33
+#define OV9650_ARBLM                   0x34
+#define OV9650_RSVD35                  0x35
+#define OV9650_RSVD36                  0x36
+#define OV9650_ADC                     0x37
+#define OV9650_ACOM38                  0x38
+#define OV9650_OFON                    0x39
+#define OV9650_TSLB                    0x3a
+#define OV9650_COM12                   0x3c
+#define OV9650_COM13                   0x3d
+#define OV9650_COM15                   0x40
+#define OV9650_COM16                   0x41
+#define OV9650_LCC1                    0x62
+#define OV9650_LCC2                    0x63
+#define OV9650_LCC3                    0x64
+#define OV9650_LCC4                    0x65
+#define OV9650_LCC5                    0x66
+#define OV9650_HV                      0x69
+#define OV9650_DBLV                    0x6b
+#define OV9650_COM21                   0x8b
+#define OV9650_COM22                   0x8c
+#define OV9650_COM24                   0x8e
+#define OV9650_DBLC1                   0x8f
+#define OV9650_RSVD94                  0x94
+#define OV9650_RSVD95                  0x95
+#define OV9650_RSVD96                  0x96
+#define OV9650_LCCFB                   0x9d
+#define OV9650_LCCFR                   0x9e
+#define OV9650_AECHM                   0xa1
+#define OV9650_COM26                   0xa5
+#define OV9650_ACOMA8                  0xa8
+#define OV9650_ACOMA9                  0xa9
+
+#define OV9650_REGISTER_RESET          (1 << 7)
+#define OV9650_VGA_SELECT              (1 << 6)
+#define OV9650_CIF_SELECT              (1 << 5)
+#define OV9650_QVGA_SELECT             (1 << 4)
+#define OV9650_QCIF_SELECT             (1 << 3)
+#define OV9650_RGB_SELECT              (1 << 2)
+#define OV9650_RAW_RGB_SELECT          (1 << 0)
+
+#define OV9650_FAST_AGC_AEC            (1 << 7)
+#define OV9650_AEC_UNLIM_STEP_SIZE     (1 << 6)
+#define OV9650_BANDING                 (1 << 5)
+#define OV9650_AGC_EN                  (1 << 2)
+#define OV9650_AWB_EN                  (1 << 1)
+#define OV9650_AEC_EN                  (1 << 0)
+
+#define OV9650_VARIOPIXEL              (1 << 2)
+#define OV9650_SYSTEM_CLK_SEL          (1 << 7)
+#define OV9650_SLAM_MODE               (1 << 4)
+
+#define OV9650_QVGA_VARIOPIXEL         (1 << 7)
+
+#define OV9650_VFLIP                   (1 << 4)
+#define OV9650_HFLIP                   (1 << 5)
+
+#define OV9650_SOFT_SLEEP              (1 << 4)
+#define OV9650_OUTPUT_DRIVE_2X         (1 << 0)
+
+#define OV9650_DENOISE_ENABLE          (1 << 5)
+#define OV9650_WHITE_PIXEL_ENABLE      (1 << 1)
+#define OV9650_WHITE_PIXEL_OPTION      (1 << 0)
+
+#define OV9650_LEFT_OFFSET             0x62
+
+#define GAIN_DEFAULT                   0x14
+#define RED_GAIN_DEFAULT               0x70
+#define BLUE_GAIN_DEFAULT              0x20
+#define EXPOSURE_DEFAULT               0x1ff
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern bool dump_sensor;
+
+int ov9650_probe(struct sd *sd);
+int ov9650_init(struct sd *sd);
+int ov9650_start(struct sd *sd);
+int ov9650_stop(struct sd *sd);
+void ov9650_disconnect(struct sd *sd);
+
+static const struct m5602_sensor ov9650 = {
+       .name = "OV9650",
+       .i2c_slave_id = 0x60,
+       .i2c_regW = 1,
+       .probe = ov9650_probe,
+       .init = ov9650_init,
+       .start = ov9650_start,
+       .stop = ov9650_stop,
+       .disconnect = ov9650_disconnect,
+};
+
+static const unsigned char preinit_ov9650[][3] = {
+       /* [INITCAM] */
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
+       /* Reset chip */
+       {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
+       /* Enable double clock */
+       {SENSOR, OV9650_CLKRC, 0x80},
+       /* Do something out of spec with the power */
+       {SENSOR, OV9650_OFON, 0x40}
+};
+
+static const unsigned char init_ov9650[][3] = {
+       /* [INITCAM] */
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
+
+       /* Reset chip */
+       {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
+       /* One extra reset is needed in order to make the sensor behave
+          properly when resuming from ram, could be a timing issue */
+       {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
+
+       /* Enable double clock */
+       {SENSOR, OV9650_CLKRC, 0x80},
+       /* Do something out of spec with the power */
+       {SENSOR, OV9650_OFON, 0x40},
+
+       /* Set fast AGC/AEC algorithm with unlimited step size */
+       {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC |
+                             OV9650_AEC_UNLIM_STEP_SIZE},
+
+       {SENSOR, OV9650_CHLF, 0x10},
+       {SENSOR, OV9650_ARBLM, 0xbf},
+       {SENSOR, OV9650_ACOM38, 0x81},
+       /* Turn off color matrix coefficient double option */
+       {SENSOR, OV9650_COM16, 0x00},
+       /* Enable color matrix for RGB/YUV, Delay Y channel,
+       set output Y/UV delay to 1 */
+       {SENSOR, OV9650_COM13, 0x19},
+       /* Enable digital BLC, Set output mode to U Y V Y */
+       {SENSOR, OV9650_TSLB, 0x0c},
+       /* Limit the AGC/AEC stable upper region */
+       {SENSOR, OV9650_COM24, 0x00},
+       /* Enable HREF and some out of spec things */
+       {SENSOR, OV9650_COM12, 0x73},
+       /* Set all DBLC offset signs to positive and
+       do some out of spec stuff */
+       {SENSOR, OV9650_DBLC1, 0xdf},
+       {SENSOR, OV9650_COM21, 0x06},
+       {SENSOR, OV9650_RSVD35, 0x91},
+       /* Necessary, no camera stream without it */
+       {SENSOR, OV9650_RSVD16, 0x06},
+       {SENSOR, OV9650_RSVD94, 0x99},
+       {SENSOR, OV9650_RSVD95, 0x99},
+       {SENSOR, OV9650_RSVD96, 0x04},
+       /* Enable full range output */
+       {SENSOR, OV9650_COM15, 0x0},
+       /* Enable HREF at optical black, enable ADBLC bias,
+       enable ADBLC, reset timings at format change */
+       {SENSOR, OV9650_COM6, 0x4b},
+       /* Subtract 32 from the B channel bias */
+       {SENSOR, OV9650_BBIAS, 0xa0},
+       /* Subtract 32 from the Gb channel bias */
+       {SENSOR, OV9650_GbBIAS, 0xa0},
+       /* Do not bypass the analog BLC and to some out of spec stuff */
+       {SENSOR, OV9650_Gr_COM, 0x00},
+       /* Subtract 32 from the R channel bias */
+       {SENSOR, OV9650_RBIAS, 0xa0},
+       /* Subtract 32 from the R channel bias */
+       {SENSOR, OV9650_RBIAS, 0x0},
+       {SENSOR, OV9650_COM26, 0x80},
+       {SENSOR, OV9650_ACOMA9, 0x98},
+       /* Set the AGC/AEC stable region upper limit */
+       {SENSOR, OV9650_AEW, 0x68},
+       /* Set the AGC/AEC stable region lower limit */
+       {SENSOR, OV9650_AEB, 0x5c},
+       /* Set the high and low limit nibbles to 3 */
+       {SENSOR, OV9650_VPT, 0xc3},
+       /* Set the Automatic Gain Ceiling (AGC) to 128x,
+       drop VSYNC at frame drop,
+       limit exposure timing,
+       drop frame when the AEC step is larger than the exposure gap */
+       {SENSOR, OV9650_COM9, 0x6e},
+       /* Set VSYNC negative, Set RESET to SLHS (slave mode horizontal sync)
+       and set PWDN to SLVS (slave mode vertical sync) */
+       {SENSOR, OV9650_COM10, 0x42},
+       /* Set horizontal column start high to default value */
+       {SENSOR, OV9650_HSTART, 0x1a}, /* 210 */
+       /* Set horizontal column end */
+       {SENSOR, OV9650_HSTOP, 0xbf}, /* 1534 */
+       /* Complementing register to the two writes above */
+       {SENSOR, OV9650_HREF, 0xb2},
+       /* Set vertical row start high bits */
+       {SENSOR, OV9650_VSTRT, 0x02},
+       /* Set vertical row end low bits */
+       {SENSOR, OV9650_VSTOP, 0x7e},
+       /* Set complementing vertical frame control */
+       {SENSOR, OV9650_VREF, 0x10},
+       {SENSOR, OV9650_ADC, 0x04},
+       {SENSOR, OV9650_HV, 0x40},
+
+       /* Enable denoise, and white-pixel erase */
+       {SENSOR, OV9650_COM22, OV9650_DENOISE_ENABLE |
+                OV9650_WHITE_PIXEL_ENABLE |
+                OV9650_WHITE_PIXEL_OPTION},
+
+       /* Enable VARIOPIXEL */
+       {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
+       {SENSOR, OV9650_COM4, OV9650_QVGA_VARIOPIXEL},
+
+       /* Put the sensor in soft sleep mode */
+       {SENSOR, OV9650_COM2, OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X},
+};
+
+static const unsigned char res_init_ov9650[][3] = {
+       {SENSOR, OV9650_COM2, OV9650_OUTPUT_DRIVE_2X},
+
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01}
+};
+#endif
diff --git a/drivers/media/usb/gspca/m5602/m5602_po1030.c b/drivers/media/usb/gspca/m5602/m5602_po1030.c
new file mode 100644 (file)
index 0000000..b877169
--- /dev/null
@@ -0,0 +1,763 @@
+/*
+ * Driver for the po1030 sensor
+ *
+ * Copyright (c) 2008 Erik Andrén
+ * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "m5602_po1030.h"
+
+static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
+                                        __s32 val);
+static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
+                                        __s32 *val);
+static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
+                                        __s32 val);
+static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
+                                        __s32 *val);
+
+static struct v4l2_pix_format po1030_modes[] = {
+       {
+               640,
+               480,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage = 640 * 480,
+               .bytesperline = 640,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2
+       }
+};
+
+static const struct ctrl po1030_ctrls[] = {
+#define GAIN_IDX 0
+       {
+               {
+                       .id             = V4L2_CID_GAIN,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "gain",
+                       .minimum        = 0x00,
+                       .maximum        = 0x4f,
+                       .step           = 0x1,
+                       .default_value  = PO1030_GLOBAL_GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = po1030_set_gain,
+               .get = po1030_get_gain
+       },
+#define EXPOSURE_IDX 1
+       {
+               {
+                       .id             = V4L2_CID_EXPOSURE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "exposure",
+                       .minimum        = 0x00,
+                       .maximum        = 0x02ff,
+                       .step           = 0x1,
+                       .default_value  = PO1030_EXPOSURE_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = po1030_set_exposure,
+               .get = po1030_get_exposure
+       },
+#define RED_BALANCE_IDX 2
+       {
+               {
+                       .id             = V4L2_CID_RED_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "red balance",
+                       .minimum        = 0x00,
+                       .maximum        = 0xff,
+                       .step           = 0x1,
+                       .default_value  = PO1030_RED_GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = po1030_set_red_balance,
+               .get = po1030_get_red_balance
+       },
+#define BLUE_BALANCE_IDX 3
+       {
+               {
+                       .id             = V4L2_CID_BLUE_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "blue balance",
+                       .minimum        = 0x00,
+                       .maximum        = 0xff,
+                       .step           = 0x1,
+                       .default_value  = PO1030_BLUE_GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = po1030_set_blue_balance,
+               .get = po1030_get_blue_balance
+       },
+#define HFLIP_IDX 4
+       {
+               {
+                       .id             = V4L2_CID_HFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "horizontal flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0,
+               },
+               .set = po1030_set_hflip,
+               .get = po1030_get_hflip
+       },
+#define VFLIP_IDX 5
+       {
+               {
+                       .id             = V4L2_CID_VFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "vertical flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0,
+               },
+               .set = po1030_set_vflip,
+               .get = po1030_get_vflip
+       },
+#define AUTO_WHITE_BALANCE_IDX 6
+       {
+               {
+                       .id             = V4L2_CID_AUTO_WHITE_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "auto white balance",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0,
+               },
+               .set = po1030_set_auto_white_balance,
+               .get = po1030_get_auto_white_balance
+       },
+#define AUTO_EXPOSURE_IDX 7
+       {
+               {
+                       .id             = V4L2_CID_EXPOSURE_AUTO,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "auto exposure",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0,
+               },
+               .set = po1030_set_auto_exposure,
+               .get = po1030_get_auto_exposure
+       },
+#define GREEN_BALANCE_IDX 8
+       {
+               {
+                       .id             = M5602_V4L2_CID_GREEN_BALANCE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "green balance",
+                       .minimum        = 0x00,
+                       .maximum        = 0xff,
+                       .step           = 0x1,
+                       .default_value  = PO1030_GREEN_GAIN_DEFAULT,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = po1030_set_green_balance,
+               .get = po1030_get_green_balance
+       },
+};
+
+static void po1030_dump_registers(struct sd *sd);
+
+int po1030_probe(struct sd *sd)
+{
+       u8 dev_id_h = 0, i;
+       s32 *sensor_settings;
+
+       if (force_sensor) {
+               if (force_sensor == PO1030_SENSOR) {
+                       pr_info("Forcing a %s sensor\n", po1030.name);
+                       goto sensor_found;
+               }
+               /* If we want to force another sensor, don't try to probe this
+                * one */
+               return -ENODEV;
+       }
+
+       PDEBUG(D_PROBE, "Probing for a po1030 sensor");
+
+       /* Run the pre-init to actually probe the unit */
+       for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
+               u8 data = preinit_po1030[i][2];
+               if (preinit_po1030[i][0] == SENSOR)
+                       m5602_write_sensor(sd,
+                               preinit_po1030[i][1], &data, 1);
+               else
+                       m5602_write_bridge(sd, preinit_po1030[i][1], data);
+       }
+
+       if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1))
+               return -ENODEV;
+
+       if (dev_id_h == 0x30) {
+               pr_info("Detected a po1030 sensor\n");
+               goto sensor_found;
+       }
+       return -ENODEV;
+
+sensor_found:
+       sensor_settings = kmalloc(
+               ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL);
+       if (!sensor_settings)
+               return -ENOMEM;
+
+       sd->gspca_dev.cam.cam_mode = po1030_modes;
+       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
+       sd->desc->ctrls = po1030_ctrls;
+       sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
+
+       for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++)
+               sensor_settings[i] = po1030_ctrls[i].qctrl.default_value;
+       sd->sensor_priv = sensor_settings;
+
+       return 0;
+}
+
+int po1030_init(struct sd *sd)
+{
+       s32 *sensor_settings = sd->sensor_priv;
+       int i, err = 0;
+
+       /* Init the sensor */
+       for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) {
+               u8 data[2] = {0x00, 0x00};
+
+               switch (init_po1030[i][0]) {
+               case BRIDGE:
+                       err = m5602_write_bridge(sd,
+                               init_po1030[i][1],
+                               init_po1030[i][2]);
+                       break;
+
+               case SENSOR:
+                       data[0] = init_po1030[i][2];
+                       err = m5602_write_sensor(sd,
+                               init_po1030[i][1], data, 1);
+                       break;
+
+               default:
+                       pr_info("Invalid stream command, exiting init\n");
+                       return -EINVAL;
+               }
+       }
+       if (err < 0)
+               return err;
+
+       if (dump_sensor)
+               po1030_dump_registers(sd);
+
+       err = po1030_set_exposure(&sd->gspca_dev,
+                                  sensor_settings[EXPOSURE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+       if (err < 0)
+               return err;
+
+       err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
+       if (err < 0)
+               return err;
+
+       err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+       if (err < 0)
+               return err;
+
+       err = po1030_set_red_balance(&sd->gspca_dev,
+                                     sensor_settings[RED_BALANCE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = po1030_set_blue_balance(&sd->gspca_dev,
+                                     sensor_settings[BLUE_BALANCE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = po1030_set_green_balance(&sd->gspca_dev,
+                                      sensor_settings[GREEN_BALANCE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = po1030_set_auto_white_balance(&sd->gspca_dev,
+                               sensor_settings[AUTO_WHITE_BALANCE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = po1030_set_auto_exposure(&sd->gspca_dev,
+                               sensor_settings[AUTO_EXPOSURE_IDX]);
+       return err;
+}
+
+int po1030_start(struct sd *sd)
+{
+       struct cam *cam = &sd->gspca_dev.cam;
+       int i, err = 0;
+       int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
+       int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
+       int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
+       u8 data;
+
+       switch (width) {
+       case 320:
+               data = PO1030_SUBSAMPLING;
+               err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
+               if (err < 0)
+                       return err;
+
+               data = ((width + 3) >> 8) & 0xff;
+               err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
+               if (err < 0)
+                       return err;
+
+               data = (width + 3) & 0xff;
+               err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
+               if (err < 0)
+                       return err;
+
+               data = ((height + 1) >> 8) & 0xff;
+               err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
+               if (err < 0)
+                       return err;
+
+               data = (height + 1) & 0xff;
+               err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
+
+               height += 6;
+               width -= 1;
+               break;
+
+       case 640:
+               data = 0;
+               err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
+               if (err < 0)
+                       return err;
+
+               data = ((width + 7) >> 8) & 0xff;
+               err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
+               if (err < 0)
+                       return err;
+
+               data = (width + 7) & 0xff;
+               err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
+               if (err < 0)
+                       return err;
+
+               data = ((height + 3) >> 8) & 0xff;
+               err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
+               if (err < 0)
+                       return err;
+
+               data = (height + 3) & 0xff;
+               err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
+
+               height += 12;
+               width -= 2;
+               break;
+       }
+       err = m5602_write_bridge(sd, M5602_XB_SENSOR_TYPE, 0x0c);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_LINE_OF_FRAME_H, 0x81);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_PIX_OF_LINE_H, 0x82);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0x01);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
+                                ((ver_offs >> 8) & 0xff));
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
+       if (err < 0)
+               return err;
+
+       for (i = 0; i < 2 && !err; i++)
+               err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
+       if (err < 0)
+               return err;
+
+       for (i = 0; i < 2 && !err; i++)
+               err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
+
+       for (i = 0; i < 2 && !err; i++)
+               err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+
+       for (i = 0; i < 2 && !err; i++)
+               err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width >> 8) & 0xff);
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width & 0xff));
+       if (err < 0)
+               return err;
+
+       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
+       return err;
+}
+
+static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[EXPOSURE_IDX];
+       PDEBUG(D_V4L2, "Exposure read as %d", *val);
+       return 0;
+}
+
+static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 i2c_data;
+       int err;
+
+       sensor_settings[EXPOSURE_IDX] = val;
+       PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
+
+       i2c_data = ((val & 0xff00) >> 8);
+       PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
+              i2c_data);
+
+       err = m5602_write_sensor(sd, PO1030_INTEGLINES_H,
+                                 &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       i2c_data = (val & 0xff);
+       PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
+              i2c_data);
+       err = m5602_write_sensor(sd, PO1030_INTEGLINES_M,
+                                 &i2c_data, 1);
+
+       return err;
+}
+
+static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[GAIN_IDX];
+       PDEBUG(D_V4L2, "Read global gain %d", *val);
+       return 0;
+}
+
+static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 i2c_data;
+       int err;
+
+       sensor_settings[GAIN_IDX] = val;
+
+       i2c_data = val & 0xff;
+       PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
+       err = m5602_write_sensor(sd, PO1030_GLOBALGAIN,
+                                &i2c_data, 1);
+       return err;
+}
+
+static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[HFLIP_IDX];
+       PDEBUG(D_V4L2, "Read hflip %d", *val);
+
+       return 0;
+}
+
+static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 i2c_data;
+       int err;
+
+       sensor_settings[HFLIP_IDX] = val;
+
+       PDEBUG(D_V4L2, "Set hflip %d", val);
+       err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
+
+       err = m5602_write_sensor(sd, PO1030_CONTROL2,
+                                &i2c_data, 1);
+
+       return err;
+}
+
+static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[VFLIP_IDX];
+       PDEBUG(D_V4L2, "Read vflip %d", *val);
+
+       return 0;
+}
+
+static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 i2c_data;
+       int err;
+
+       sensor_settings[VFLIP_IDX] = val;
+
+       PDEBUG(D_V4L2, "Set vflip %d", val);
+       err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
+
+       err = m5602_write_sensor(sd, PO1030_CONTROL2,
+                                &i2c_data, 1);
+
+       return err;
+}
+
+static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[RED_BALANCE_IDX];
+       PDEBUG(D_V4L2, "Read red gain %d", *val);
+       return 0;
+}
+
+static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 i2c_data;
+       int err;
+
+       sensor_settings[RED_BALANCE_IDX] = val;
+
+       i2c_data = val & 0xff;
+       PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
+       err = m5602_write_sensor(sd, PO1030_RED_GAIN,
+                                 &i2c_data, 1);
+       return err;
+}
+
+static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[BLUE_BALANCE_IDX];
+       PDEBUG(D_V4L2, "Read blue gain %d", *val);
+
+       return 0;
+}
+
+static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 i2c_data;
+       int err;
+
+       sensor_settings[BLUE_BALANCE_IDX] = val;
+
+       i2c_data = val & 0xff;
+       PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
+       err = m5602_write_sensor(sd, PO1030_BLUE_GAIN,
+                                 &i2c_data, 1);
+
+       return err;
+}
+
+static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[GREEN_BALANCE_IDX];
+       PDEBUG(D_V4L2, "Read green gain %d", *val);
+
+       return 0;
+}
+
+static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 i2c_data;
+       int err;
+
+       sensor_settings[GREEN_BALANCE_IDX] = val;
+       i2c_data = val & 0xff;
+       PDEBUG(D_V4L2, "Set green gain to %d", i2c_data);
+
+       err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN,
+                          &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       return m5602_write_sensor(sd, PO1030_GREEN_2_GAIN,
+                                &i2c_data, 1);
+}
+
+static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
+                                        __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
+       PDEBUG(D_V4L2, "Auto white balancing is %d", *val);
+
+       return 0;
+}
+
+static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
+                                        __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 i2c_data;
+       int err;
+
+       sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
+
+       err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       PDEBUG(D_V4L2, "Set auto white balance to %d", val);
+       i2c_data = (i2c_data & 0xfe) | (val & 0x01);
+       err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
+       return err;
+}
+
+static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
+                                   __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[AUTO_EXPOSURE_IDX];
+       PDEBUG(D_V4L2, "Auto exposure is %d", *val);
+       return 0;
+}
+
+static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
+                                   __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 i2c_data;
+       int err;
+
+       sensor_settings[AUTO_EXPOSURE_IDX] = val;
+       err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
+       if (err < 0)
+               return err;
+
+       PDEBUG(D_V4L2, "Set auto exposure to %d", val);
+       i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1);
+       return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
+}
+
+void po1030_disconnect(struct sd *sd)
+{
+       sd->sensor = NULL;
+       kfree(sd->sensor_priv);
+}
+
+static void po1030_dump_registers(struct sd *sd)
+{
+       int address;
+       u8 value = 0;
+
+       pr_info("Dumping the po1030 sensor core registers\n");
+       for (address = 0; address < 0x7f; address++) {
+               m5602_read_sensor(sd, address, &value, 1);
+               pr_info("register 0x%x contains 0x%x\n", address, value);
+       }
+
+       pr_info("po1030 register state dump complete\n");
+
+       pr_info("Probing for which registers that are read/write\n");
+       for (address = 0; address < 0xff; address++) {
+               u8 old_value, ctrl_value;
+               u8 test_value[2] = {0xff, 0xff};
+
+               m5602_read_sensor(sd, address, &old_value, 1);
+               m5602_write_sensor(sd, address, test_value, 1);
+               m5602_read_sensor(sd, address, &ctrl_value, 1);
+
+               if (ctrl_value == test_value[0])
+                       pr_info("register 0x%x is writeable\n", address);
+               else
+                       pr_info("register 0x%x is read only\n", address);
+
+               /* Restore original value */
+               m5602_write_sensor(sd, address, &old_value, 1);
+       }
+}
diff --git a/drivers/media/usb/gspca/m5602/m5602_po1030.h b/drivers/media/usb/gspca/m5602/m5602_po1030.h
new file mode 100644 (file)
index 0000000..81a2bcb
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Driver for the po1030 sensor.
+ *
+ * Copyright (c) 2008 Erik Andrén
+ * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * Register defines taken from Pascal Stangs Procyon Armlib
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#ifndef M5602_PO1030_H_
+#define M5602_PO1030_H_
+
+#include "m5602_sensor.h"
+
+/*****************************************************************************/
+
+#define PO1030_DEVID_H         0x00
+#define PO1030_DEVID_L         0x01
+#define PO1030_FRAMEWIDTH_H    0x04
+#define PO1030_FRAMEWIDTH_L    0x05
+#define PO1030_FRAMEHEIGHT_H   0x06
+#define PO1030_FRAMEHEIGHT_L   0x07
+#define PO1030_WINDOWX_H       0x08
+#define PO1030_WINDOWX_L       0x09
+#define PO1030_WINDOWY_H       0x0a
+#define PO1030_WINDOWY_L       0x0b
+#define PO1030_WINDOWWIDTH_H   0x0c
+#define PO1030_WINDOWWIDTH_L   0x0d
+#define PO1030_WINDOWHEIGHT_H  0x0e
+#define PO1030_WINDOWHEIGHT_L  0x0f
+
+#define PO1030_GLOBALIBIAS     0x12
+#define PO1030_PIXELIBIAS      0x13
+
+#define PO1030_GLOBALGAIN      0x15
+#define PO1030_RED_GAIN                0x16
+#define PO1030_GREEN_1_GAIN    0x17
+#define PO1030_BLUE_GAIN       0x18
+#define PO1030_GREEN_2_GAIN    0x19
+
+#define PO1030_INTEGLINES_H    0x1a
+#define PO1030_INTEGLINES_M    0x1b
+#define PO1030_INTEGLINES_L    0x1c
+
+#define PO1030_CONTROL1                0x1d
+#define PO1030_CONTROL2                0x1e
+#define PO1030_CONTROL3                0x1f
+#define PO1030_CONTROL4                0x20
+
+#define PO1030_PERIOD50_H      0x23
+#define PO1030_PERIOD50_L      0x24
+#define PO1030_PERIOD60_H      0x25
+#define PO1030_PERIOD60_L      0x26
+#define PO1030_REGCLK167       0x27
+#define PO1030_FLICKER_DELTA50 0x28
+#define PO1030_FLICKERDELTA60  0x29
+
+#define PO1030_ADCOFFSET       0x2c
+
+/* Gamma Correction Coeffs */
+#define PO1030_GC0             0x2d
+#define PO1030_GC1             0x2e
+#define PO1030_GC2             0x2f
+#define PO1030_GC3             0x30
+#define PO1030_GC4             0x31
+#define PO1030_GC5             0x32
+#define PO1030_GC6             0x33
+#define PO1030_GC7             0x34
+
+/* Color Transform Matrix */
+#define PO1030_CT0             0x35
+#define PO1030_CT1             0x36
+#define PO1030_CT2             0x37
+#define PO1030_CT3             0x38
+#define PO1030_CT4             0x39
+#define PO1030_CT5             0x3a
+#define PO1030_CT6             0x3b
+#define PO1030_CT7             0x3c
+#define PO1030_CT8             0x3d
+
+#define PO1030_AUTOCTRL1       0x3e
+#define PO1030_AUTOCTRL2       0x3f
+
+#define PO1030_YTARGET         0x40
+#define PO1030_GLOBALGAINMIN   0x41
+#define PO1030_GLOBALGAINMAX   0x42
+
+#define PO1030_AWB_RED_TUNING  0x47
+#define PO1030_AWB_BLUE_TUNING 0x48
+
+/* Output format control */
+#define PO1030_OUTFORMCTRL1    0x5a
+#define PO1030_OUTFORMCTRL2    0x5b
+#define PO1030_OUTFORMCTRL3    0x5c
+#define PO1030_OUTFORMCTRL4    0x5d
+#define PO1030_OUTFORMCTRL5    0x5e
+
+#define PO1030_EDGE_ENH_OFF    0x5f
+#define PO1030_EGA             0x60
+
+#define PO1030_Cb_U_GAIN       0x63
+#define PO1030_Cr_V_GAIN       0x64
+
+#define PO1030_YCONTRAST       0x74
+#define PO1030_YSATURATION     0x75
+
+#define PO1030_HFLIP           (1 << 7)
+#define PO1030_VFLIP           (1 << 6)
+
+#define PO1030_HREF_ENABLE     (1 << 6)
+
+#define PO1030_RAW_RGB_BAYER   0x4
+
+#define PO1030_FRAME_EQUAL     (1 << 3)
+#define PO1030_AUTO_SUBSAMPLING (1 << 4)
+
+#define PO1030_WEIGHT_WIN_2X   (1 << 3)
+
+#define PO1030_SHUTTER_MODE    (1 << 6)
+#define PO1030_AUTO_SUBSAMPLING        (1 << 4)
+#define PO1030_FRAME_EQUAL     (1 << 3)
+
+#define PO1030_SENSOR_RESET    (1 << 5)
+
+#define PO1030_SUBSAMPLING     (1 << 6)
+
+/*****************************************************************************/
+
+#define PO1030_GLOBAL_GAIN_DEFAULT     0x12
+#define PO1030_EXPOSURE_DEFAULT                0x0085
+#define PO1030_BLUE_GAIN_DEFAULT       0x36
+#define PO1030_RED_GAIN_DEFAULT                0x36
+#define PO1030_GREEN_GAIN_DEFAULT      0x40
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern bool dump_sensor;
+
+int po1030_probe(struct sd *sd);
+int po1030_init(struct sd *sd);
+int po1030_start(struct sd *sd);
+void po1030_disconnect(struct sd *sd);
+
+static const struct m5602_sensor po1030 = {
+       .name = "PO1030",
+
+       .i2c_slave_id = 0xdc,
+       .i2c_regW = 1,
+
+       .probe = po1030_probe,
+       .init = po1030_init,
+       .start = po1030_start,
+       .disconnect = po1030_disconnect,
+};
+
+static const unsigned char preinit_po1030[][3] = {
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
+
+       {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)},
+
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00}
+};
+
+static const unsigned char init_po1030[][3] = {
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
+
+       {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+
+       {SENSOR, PO1030_AUTOCTRL2, 0x04},
+
+       {SENSOR, PO1030_OUTFORMCTRL2, PO1030_RAW_RGB_BAYER},
+       {SENSOR, PO1030_AUTOCTRL1, PO1030_WEIGHT_WIN_2X},
+
+       {SENSOR, PO1030_CONTROL2, 0x03},
+       {SENSOR, 0x21, 0x90},
+       {SENSOR, PO1030_YTARGET, 0x60},
+       {SENSOR, 0x59, 0x13},
+       {SENSOR, PO1030_OUTFORMCTRL1, PO1030_HREF_ENABLE},
+       {SENSOR, PO1030_EDGE_ENH_OFF, 0x00},
+       {SENSOR, PO1030_EGA, 0x80},
+       {SENSOR, 0x78, 0x14},
+       {SENSOR, 0x6f, 0x01},
+       {SENSOR, PO1030_GLOBALGAINMAX, 0x14},
+       {SENSOR, PO1030_Cb_U_GAIN, 0x38},
+       {SENSOR, PO1030_Cr_V_GAIN, 0x38},
+       {SENSOR, PO1030_CONTROL1, PO1030_SHUTTER_MODE |
+                                 PO1030_AUTO_SUBSAMPLING |
+                                 PO1030_FRAME_EQUAL},
+       {SENSOR, PO1030_GC0, 0x10},
+       {SENSOR, PO1030_GC1, 0x20},
+       {SENSOR, PO1030_GC2, 0x40},
+       {SENSOR, PO1030_GC3, 0x60},
+       {SENSOR, PO1030_GC4, 0x80},
+       {SENSOR, PO1030_GC5, 0xa0},
+       {SENSOR, PO1030_GC6, 0xc0},
+       {SENSOR, PO1030_GC7, 0xff},
+
+       /* Set the width to 751 */
+       {SENSOR, PO1030_FRAMEWIDTH_H, 0x02},
+       {SENSOR, PO1030_FRAMEWIDTH_L, 0xef},
+
+       /* Set the height to 540 */
+       {SENSOR, PO1030_FRAMEHEIGHT_H, 0x02},
+       {SENSOR, PO1030_FRAMEHEIGHT_L, 0x1c},
+
+       /* Set the x window to 1 */
+       {SENSOR, PO1030_WINDOWX_H, 0x00},
+       {SENSOR, PO1030_WINDOWX_L, 0x01},
+
+       /* Set the y window to 1 */
+       {SENSOR, PO1030_WINDOWY_H, 0x00},
+       {SENSOR, PO1030_WINDOWY_L, 0x01},
+
+       /* with a very low lighted environment increase the exposure but
+        * decrease the FPS (Frame Per Second) */
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
+};
+#endif
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.c
new file mode 100644 (file)
index 0000000..cc8ec3f
--- /dev/null
@@ -0,0 +1,726 @@
+/*
+ * Driver for the s5k4aa sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "m5602_s5k4aa.h"
+
+static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
+
+static
+    const
+       struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
+       {
+               .ident = "BRUNEINIT",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "BRUNENIT"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "BRUNENIT"),
+                       DMI_MATCH(DMI_BOARD_VERSION, "00030D0000000001")
+               }
+       }, {
+               .ident = "Fujitsu-Siemens Amilo Xa 2528",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528")
+               }
+       }, {
+               .ident = "Fujitsu-Siemens Amilo Xi 2428",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2428")
+               }
+       }, {
+               .ident = "Fujitsu-Siemens Amilo Xi 2528",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2528")
+               }
+       }, {
+               .ident = "Fujitsu-Siemens Amilo Xi 2550",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550")
+               }
+       }, {
+               .ident = "Fujitsu-Siemens Amilo Pa 2548",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2548")
+               }
+       }, {
+               .ident = "MSI GX700",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
+                       DMI_MATCH(DMI_BIOS_DATE, "12/02/2008")
+               }
+       }, {
+               .ident = "MSI GX700",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
+                       DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
+               }
+       }, {
+               .ident = "MSI GX700",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
+                       DMI_MATCH(DMI_BIOS_DATE, "07/19/2007")
+               }
+       }, {
+               .ident = "MSI GX700/GX705/EX700",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700")
+               }
+       }, {
+               .ident = "MSI L735",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X")
+               }
+       }, {
+               .ident = "Lenovo Y300",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Y300")
+               }
+       },
+       { }
+};
+
+static struct v4l2_pix_format s5k4aa_modes[] = {
+       {
+               640,
+               480,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       640 * 480,
+               .bytesperline = 640,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0
+       },
+       {
+               1280,
+               1024,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       1280 * 1024,
+               .bytesperline = 1280,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0
+       }
+};
+
+static const struct ctrl s5k4aa_ctrls[] = {
+#define VFLIP_IDX 0
+       {
+               {
+                       .id             = V4L2_CID_VFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "vertical flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = s5k4aa_set_vflip,
+               .get = s5k4aa_get_vflip
+       },
+#define HFLIP_IDX 1
+       {
+               {
+                       .id             = V4L2_CID_HFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "horizontal flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = s5k4aa_set_hflip,
+               .get = s5k4aa_get_hflip
+       },
+#define GAIN_IDX 2
+       {
+               {
+                       .id             = V4L2_CID_GAIN,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "Gain",
+                       .minimum        = 0,
+                       .maximum        = 127,
+                       .step           = 1,
+                       .default_value  = S5K4AA_DEFAULT_GAIN,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = s5k4aa_set_gain,
+               .get = s5k4aa_get_gain
+       },
+#define EXPOSURE_IDX 3
+       {
+               {
+                       .id             = V4L2_CID_EXPOSURE,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "Exposure",
+                       .minimum        = 13,
+                       .maximum        = 0xfff,
+                       .step           = 1,
+                       .default_value  = 0x100,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = s5k4aa_set_exposure,
+               .get = s5k4aa_get_exposure
+       },
+#define NOISE_SUPP_IDX 4
+       {
+               {
+                       .id             = V4L2_CID_PRIVATE_BASE,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "Noise suppression (smoothing)",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 1,
+               },
+                       .set = s5k4aa_set_noise,
+                       .get = s5k4aa_get_noise
+       },
+#define BRIGHTNESS_IDX 5
+       {
+               {
+                       .id             = V4L2_CID_BRIGHTNESS,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "Brightness",
+                       .minimum        = 0,
+                       .maximum        = 0x1f,
+                       .step           = 1,
+                       .default_value  = S5K4AA_DEFAULT_BRIGHTNESS,
+               },
+                       .set = s5k4aa_set_brightness,
+                       .get = s5k4aa_get_brightness
+       },
+
+};
+
+static void s5k4aa_dump_registers(struct sd *sd);
+
+int s5k4aa_probe(struct sd *sd)
+{
+       u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+       const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
+       int i, err = 0;
+       s32 *sensor_settings;
+
+       if (force_sensor) {
+               if (force_sensor == S5K4AA_SENSOR) {
+                       pr_info("Forcing a %s sensor\n", s5k4aa.name);
+                       goto sensor_found;
+               }
+               /* If we want to force another sensor, don't try to probe this
+                * one */
+               return -ENODEV;
+       }
+
+       PDEBUG(D_PROBE, "Probing for a s5k4aa sensor");
+
+       /* Preinit the sensor */
+       for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
+               u8 data[2] = {0x00, 0x00};
+
+               switch (preinit_s5k4aa[i][0]) {
+               case BRIDGE:
+                       err = m5602_write_bridge(sd,
+                                                preinit_s5k4aa[i][1],
+                                                preinit_s5k4aa[i][2]);
+                       break;
+
+               case SENSOR:
+                       data[0] = preinit_s5k4aa[i][2];
+                       err = m5602_write_sensor(sd,
+                                                 preinit_s5k4aa[i][1],
+                                                 data, 1);
+                       break;
+
+               case SENSOR_LONG:
+                       data[0] = preinit_s5k4aa[i][2];
+                       data[1] = preinit_s5k4aa[i][3];
+                       err = m5602_write_sensor(sd,
+                                                 preinit_s5k4aa[i][1],
+                                                 data, 2);
+                       break;
+               default:
+                       pr_info("Invalid stream command, exiting init\n");
+                       return -EINVAL;
+               }
+       }
+
+       /* Test some registers, but we don't know their exact meaning yet */
+       if (m5602_read_sensor(sd, 0x00, prod_id, 2))
+               return -ENODEV;
+       if (m5602_read_sensor(sd, 0x02, prod_id+2, 2))
+               return -ENODEV;
+       if (m5602_read_sensor(sd, 0x04, prod_id+4, 2))
+               return -ENODEV;
+
+       if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
+               return -ENODEV;
+       else
+               pr_info("Detected a s5k4aa sensor\n");
+
+sensor_found:
+       sensor_settings = kmalloc(
+               ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL);
+       if (!sensor_settings)
+               return -ENOMEM;
+
+       sd->gspca_dev.cam.cam_mode = s5k4aa_modes;
+       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes);
+       sd->desc->ctrls = s5k4aa_ctrls;
+       sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls);
+
+       for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++)
+               sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value;
+       sd->sensor_priv = sensor_settings;
+
+       return 0;
+}
+
+int s5k4aa_start(struct sd *sd)
+{
+       int i, err = 0;
+       u8 data[2];
+       struct cam *cam = &sd->gspca_dev.cam;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
+       case 1280:
+               PDEBUG(D_V4L2, "Configuring camera for SXGA mode");
+
+               for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) {
+                       switch (SXGA_s5k4aa[i][0]) {
+                       case BRIDGE:
+                               err = m5602_write_bridge(sd,
+                                                SXGA_s5k4aa[i][1],
+                                                SXGA_s5k4aa[i][2]);
+                       break;
+
+                       case SENSOR:
+                               data[0] = SXGA_s5k4aa[i][2];
+                               err = m5602_write_sensor(sd,
+                                                SXGA_s5k4aa[i][1],
+                                                data, 1);
+                       break;
+
+                       case SENSOR_LONG:
+                               data[0] = SXGA_s5k4aa[i][2];
+                               data[1] = SXGA_s5k4aa[i][3];
+                               err = m5602_write_sensor(sd,
+                                                 SXGA_s5k4aa[i][1],
+                                                 data, 2);
+                       break;
+
+                       default:
+                               pr_err("Invalid stream command, exiting init\n");
+                               return -EINVAL;
+                       }
+               }
+               err = s5k4aa_set_noise(&sd->gspca_dev, 0);
+               if (err < 0)
+                       return err;
+               break;
+
+       case 640:
+               PDEBUG(D_V4L2, "Configuring camera for VGA mode");
+
+               for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) {
+                       switch (VGA_s5k4aa[i][0]) {
+                       case BRIDGE:
+                               err = m5602_write_bridge(sd,
+                                                VGA_s5k4aa[i][1],
+                                                VGA_s5k4aa[i][2]);
+                       break;
+
+                       case SENSOR:
+                               data[0] = VGA_s5k4aa[i][2];
+                               err = m5602_write_sensor(sd,
+                                                VGA_s5k4aa[i][1],
+                                                data, 1);
+                       break;
+
+                       case SENSOR_LONG:
+                               data[0] = VGA_s5k4aa[i][2];
+                               data[1] = VGA_s5k4aa[i][3];
+                               err = m5602_write_sensor(sd,
+                                                 VGA_s5k4aa[i][1],
+                                                 data, 2);
+                       break;
+
+                       default:
+                               pr_err("Invalid stream command, exiting init\n");
+                               return -EINVAL;
+                       }
+               }
+               err = s5k4aa_set_noise(&sd->gspca_dev, 1);
+               if (err < 0)
+                       return err;
+               break;
+       }
+       if (err < 0)
+               return err;
+
+       err = s5k4aa_set_exposure(&sd->gspca_dev,
+                                  sensor_settings[EXPOSURE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+       if (err < 0)
+               return err;
+
+       err = s5k4aa_set_brightness(&sd->gspca_dev,
+                                    sensor_settings[BRIGHTNESS_IDX]);
+       if (err < 0)
+               return err;
+
+       err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]);
+       if (err < 0)
+               return err;
+
+       err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+       if (err < 0)
+               return err;
+
+       return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
+}
+
+int s5k4aa_init(struct sd *sd)
+{
+       int i, err = 0;
+
+       for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
+               u8 data[2] = {0x00, 0x00};
+
+               switch (init_s5k4aa[i][0]) {
+               case BRIDGE:
+                       err = m5602_write_bridge(sd,
+                               init_s5k4aa[i][1],
+                               init_s5k4aa[i][2]);
+                       break;
+
+               case SENSOR:
+                       data[0] = init_s5k4aa[i][2];
+                       err = m5602_write_sensor(sd,
+                               init_s5k4aa[i][1], data, 1);
+                       break;
+
+               case SENSOR_LONG:
+                       data[0] = init_s5k4aa[i][2];
+                       data[1] = init_s5k4aa[i][3];
+                       err = m5602_write_sensor(sd,
+                               init_s5k4aa[i][1], data, 2);
+                       break;
+               default:
+                       pr_info("Invalid stream command, exiting init\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (dump_sensor)
+               s5k4aa_dump_registers(sd);
+
+       return err;
+}
+
+static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[EXPOSURE_IDX];
+       PDEBUG(D_V4L2, "Read exposure %d", *val);
+
+       return 0;
+}
+
+static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 data = S5K4AA_PAGE_MAP_2;
+       int err;
+
+       sensor_settings[EXPOSURE_IDX] = val;
+       PDEBUG(D_V4L2, "Set exposure to %d", val);
+       err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       if (err < 0)
+               return err;
+       data = (val >> 8) & 0xff;
+       err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
+       if (err < 0)
+               return err;
+       data = val & 0xff;
+       err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
+
+       return err;
+}
+
+static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[VFLIP_IDX];
+       PDEBUG(D_V4L2, "Read vertical flip %d", *val);
+
+       return 0;
+}
+
+static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 data = S5K4AA_PAGE_MAP_2;
+       int err;
+
+       sensor_settings[VFLIP_IDX] = val;
+
+       PDEBUG(D_V4L2, "Set vertical flip to %d", val);
+       err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       if (err < 0)
+               return err;
+
+       err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+       if (err < 0)
+               return err;
+
+       if (dmi_check_system(s5k4aa_vflip_dmi_table))
+               val = !val;
+
+       data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7));
+       err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+       if (err < 0)
+               return err;
+
+       err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+       if (err < 0)
+               return err;
+       if (val)
+               data &= 0xfe;
+       else
+               data |= 0x01;
+       err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
+       return err;
+}
+
+static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[HFLIP_IDX];
+       PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
+
+       return 0;
+}
+
+static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 data = S5K4AA_PAGE_MAP_2;
+       int err;
+
+       sensor_settings[HFLIP_IDX] = val;
+
+       PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
+       err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       if (err < 0)
+               return err;
+
+       err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+       if (err < 0)
+               return err;
+
+       if (dmi_check_system(s5k4aa_vflip_dmi_table))
+               val = !val;
+
+       data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
+       err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
+       if (err < 0)
+               return err;
+
+       err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+       if (err < 0)
+               return err;
+       if (val)
+               data &= 0xfe;
+       else
+               data |= 0x01;
+       err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
+       return err;
+}
+
+static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[GAIN_IDX];
+       PDEBUG(D_V4L2, "Read gain %d", *val);
+       return 0;
+}
+
+static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 data = S5K4AA_PAGE_MAP_2;
+       int err;
+
+       sensor_settings[GAIN_IDX] = val;
+
+       PDEBUG(D_V4L2, "Set gain to %d", val);
+       err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       if (err < 0)
+               return err;
+
+       data = val & 0xff;
+       err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1);
+
+       return err;
+}
+
+static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[BRIGHTNESS_IDX];
+       PDEBUG(D_V4L2, "Read brightness %d", *val);
+       return 0;
+}
+
+static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 data = S5K4AA_PAGE_MAP_2;
+       int err;
+
+       sensor_settings[BRIGHTNESS_IDX] = val;
+
+       PDEBUG(D_V4L2, "Set brightness to %d", val);
+       err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       if (err < 0)
+               return err;
+
+       data = val & 0xff;
+       return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1);
+}
+
+static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+
+       *val = sensor_settings[NOISE_SUPP_IDX];
+       PDEBUG(D_V4L2, "Read noise %d", *val);
+       return 0;
+}
+
+static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 *sensor_settings = sd->sensor_priv;
+       u8 data = S5K4AA_PAGE_MAP_2;
+       int err;
+
+       sensor_settings[NOISE_SUPP_IDX] = val;
+
+       PDEBUG(D_V4L2, "Set noise to %d", val);
+       err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
+       if (err < 0)
+               return err;
+
+       data = val & 0x01;
+       return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1);
+}
+
+void s5k4aa_disconnect(struct sd *sd)
+{
+       sd->sensor = NULL;
+       kfree(sd->sensor_priv);
+}
+
+static void s5k4aa_dump_registers(struct sd *sd)
+{
+       int address;
+       u8 page, old_page;
+       m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
+       for (page = 0; page < 16; page++) {
+               m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
+               pr_info("Dumping the s5k4aa register state for page 0x%x\n",
+                       page);
+               for (address = 0; address <= 0xff; address++) {
+                       u8 value = 0;
+                       m5602_read_sensor(sd, address, &value, 1);
+                       pr_info("register 0x%x contains 0x%x\n",
+                               address, value);
+               }
+       }
+       pr_info("s5k4aa register state dump complete\n");
+
+       for (page = 0; page < 16; page++) {
+               m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
+               pr_info("Probing for which registers that are read/write for page 0x%x\n",
+                       page);
+               for (address = 0; address <= 0xff; address++) {
+                       u8 old_value, ctrl_value, test_value = 0xff;
+
+                       m5602_read_sensor(sd, address, &old_value, 1);
+                       m5602_write_sensor(sd, address, &test_value, 1);
+                       m5602_read_sensor(sd, address, &ctrl_value, 1);
+
+                       if (ctrl_value == test_value)
+                               pr_info("register 0x%x is writeable\n",
+                                       address);
+                       else
+                               pr_info("register 0x%x is read only\n",
+                                       address);
+
+                       /* Restore original value */
+                       m5602_write_sensor(sd, address, &old_value, 1);
+               }
+       }
+       pr_info("Read/write register probing complete\n");
+       m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
+}
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h b/drivers/media/usb/gspca/m5602/m5602_s5k4aa.h
new file mode 100644 (file)
index 0000000..8e0035e
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Driver for the s5k4aa sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#ifndef M5602_S5K4AA_H_
+#define M5602_S5K4AA_H_
+
+#include <linux/dmi.h>
+
+#include "m5602_sensor.h"
+
+/*****************************************************************************/
+
+#define S5K4AA_PAGE_MAP                        0xec
+
+#define S5K4AA_PAGE_MAP_0              0x00
+#define S5K4AA_PAGE_MAP_1              0x01
+#define S5K4AA_PAGE_MAP_2              0x02
+
+/* Sensor register definitions for page 0x02 */
+#define S5K4AA_READ_MODE               0x03
+#define S5K4AA_ROWSTART_HI             0x04
+#define S5K4AA_ROWSTART_LO             0x05
+#define S5K4AA_COLSTART_HI             0x06
+#define S5K4AA_COLSTART_LO             0x07
+#define S5K4AA_WINDOW_HEIGHT_HI                0x08
+#define S5K4AA_WINDOW_HEIGHT_LO                0x09
+#define S5K4AA_WINDOW_WIDTH_HI         0x0a
+#define S5K4AA_WINDOW_WIDTH_LO         0x0b
+#define S5K4AA_GLOBAL_GAIN__           0x0f
+/* sync lost, if too low, reduces frame rate if too high */
+#define S5K4AA_H_BLANK_HI__            0x1d
+#define S5K4AA_H_BLANK_LO__            0x1e
+#define S5K4AA_EXPOSURE_HI             0x17
+#define S5K4AA_EXPOSURE_LO             0x18
+#define S5K4AA_BRIGHTNESS              0x1f /* (digital?) gain : 5 bits */
+#define S5K4AA_GAIN                    0x20 /* (analogue?) gain : 7 bits */
+#define S5K4AA_NOISE_SUPP              0x37
+
+#define S5K4AA_RM_ROW_SKIP_4X          0x08
+#define S5K4AA_RM_ROW_SKIP_2X          0x04
+#define S5K4AA_RM_COL_SKIP_4X          0x02
+#define S5K4AA_RM_COL_SKIP_2X          0x01
+#define S5K4AA_RM_H_FLIP               0x40
+#define S5K4AA_RM_V_FLIP               0x80
+
+#define S5K4AA_DEFAULT_GAIN            0x5f
+#define S5K4AA_DEFAULT_BRIGHTNESS      0x10
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern bool dump_sensor;
+
+int s5k4aa_probe(struct sd *sd);
+int s5k4aa_init(struct sd *sd);
+int s5k4aa_start(struct sd *sd);
+void s5k4aa_disconnect(struct sd *sd);
+
+static const struct m5602_sensor s5k4aa = {
+       .name = "S5K4AA",
+       .i2c_slave_id = 0x5a,
+       .i2c_regW = 2,
+
+       .probe = s5k4aa_probe,
+       .init = s5k4aa_init,
+       .start = s5k4aa_start,
+       .disconnect = s5k4aa_disconnect,
+};
+
+static const unsigned char preinit_s5k4aa[][4] = {
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
+
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+
+       {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00}
+};
+
+static const unsigned char init_s5k4aa[][4] = {
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
+
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
+
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+
+       {SENSOR, S5K4AA_PAGE_MAP, 0x07, 0x00},
+       {SENSOR, 0x36, 0x01, 0x00},
+       {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, 0x7b, 0xff, 0x00},
+       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+       {SENSOR, 0x0c, 0x05, 0x00},
+       {SENSOR, 0x02, 0x0e, 0x00},
+       {SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00},
+       {SENSOR, 0x37, 0x00, 0x00},
+};
+
+static const unsigned char VGA_s5k4aa[][4] = {
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */
+
+       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+       {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X
+               | S5K4AA_RM_COL_SKIP_2X, 0x00},
+       /* 0x37 : Fix image stability when light is too bright and improves
+        * image quality in 640x480, but worsens it in 1280x1024 */
+       {SENSOR, 0x37, 0x01, 0x00},
+       /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */
+       {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
+       {SENSOR, S5K4AA_ROWSTART_LO, 0x29, 0x00},
+       {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
+       {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00},
+       /* window_height_hi, window_height_lo : 960 = 0x03c0 */
+       {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00},
+       {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00},
+       /* window_width_hi, window_width_lo : 1280 = 0x0500 */
+       {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
+       {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00},
+       {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00},
+       {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */
+       {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00},
+       {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00},
+       {SENSOR, 0x11, 0x04, 0x00},
+       {SENSOR, 0x12, 0xc3, 0x00},
+       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+       {SENSOR, 0x02, 0x0e, 0x00},
+};
+
+static const unsigned char SXGA_s5k4aa[][4] = {
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       /* VSYNC_PARA, VSYNC_PARA : img height 1024 = 0x0400 */
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       /* HSYNC_PARA, HSYNC_PARA : img width 1280 = 0x0500 */
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */
+
+       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+       {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP, 0x00},
+       {SENSOR, 0x37, 0x01, 0x00},
+       {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
+       {SENSOR, S5K4AA_ROWSTART_LO, 0x09, 0x00},
+       {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
+       {SENSOR, S5K4AA_COLSTART_LO, 0x0a, 0x00},
+       {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x04, 0x00},
+       {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0x00, 0x00},
+       {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
+       {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00},
+       {SENSOR, S5K4AA_H_BLANK_HI__, 0x01, 0x00},
+       {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00},
+       {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00},
+       {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00},
+       {SENSOR, 0x11, 0x04, 0x00},
+       {SENSOR, 0x12, 0xc3, 0x00},
+       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
+       {SENSOR, 0x02, 0x0e, 0x00},
+};
+#endif
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k83a.c b/drivers/media/usb/gspca/m5602/m5602_s5k83a.c
new file mode 100644 (file)
index 0000000..1de743a
--- /dev/null
@@ -0,0 +1,605 @@
+/*
+ * Driver for the s5k83a sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kthread.h>
+#include "m5602_s5k83a.h"
+
+static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+
+static struct v4l2_pix_format s5k83a_modes[] = {
+       {
+               640,
+               480,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       640 * 480,
+               .bytesperline = 640,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0
+       }
+};
+
+static const struct ctrl s5k83a_ctrls[] = {
+#define GAIN_IDX 0
+       {
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "gain",
+                       .minimum = 0x00,
+                       .maximum = 0xff,
+                       .step = 0x01,
+                       .default_value = S5K83A_DEFAULT_GAIN,
+                       .flags = V4L2_CTRL_FLAG_SLIDER
+               },
+                       .set = s5k83a_set_gain,
+                       .get = s5k83a_get_gain
+
+       },
+#define BRIGHTNESS_IDX 1
+       {
+               {
+                       .id = V4L2_CID_BRIGHTNESS,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "brightness",
+                       .minimum = 0x00,
+                       .maximum = 0xff,
+                       .step = 0x01,
+                       .default_value = S5K83A_DEFAULT_BRIGHTNESS,
+                       .flags = V4L2_CTRL_FLAG_SLIDER
+               },
+                       .set = s5k83a_set_brightness,
+                       .get = s5k83a_get_brightness,
+       },
+#define EXPOSURE_IDX 2
+       {
+               {
+                       .id = V4L2_CID_EXPOSURE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "exposure",
+                       .minimum = 0x00,
+                       .maximum = S5K83A_MAXIMUM_EXPOSURE,
+                       .step = 0x01,
+                       .default_value = S5K83A_DEFAULT_EXPOSURE,
+                       .flags = V4L2_CTRL_FLAG_SLIDER
+               },
+                       .set = s5k83a_set_exposure,
+                       .get = s5k83a_get_exposure
+       },
+#define HFLIP_IDX 3
+       {
+               {
+                       .id = V4L2_CID_HFLIP,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "horizontal flip",
+                       .minimum = 0,
+                       .maximum = 1,
+                       .step = 1,
+                       .default_value = 0
+               },
+                       .set = s5k83a_set_hflip,
+                       .get = s5k83a_get_hflip
+       },
+#define VFLIP_IDX 4
+       {
+               {
+                       .id = V4L2_CID_VFLIP,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "vertical flip",
+                       .minimum = 0,
+                       .maximum = 1,
+                       .step = 1,
+                       .default_value = 0
+               },
+               .set = s5k83a_set_vflip,
+               .get = s5k83a_get_vflip
+       }
+};
+
+static void s5k83a_dump_registers(struct sd *sd);
+static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
+static int s5k83a_set_led_indication(struct sd *sd, u8 val);
+static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
+                               __s32 vflip, __s32 hflip);
+
+int s5k83a_probe(struct sd *sd)
+{
+       struct s5k83a_priv *sens_priv;
+       u8 prod_id = 0, ver_id = 0;
+       int i, err = 0;
+
+       if (force_sensor) {
+               if (force_sensor == S5K83A_SENSOR) {
+                       pr_info("Forcing a %s sensor\n", s5k83a.name);
+                       goto sensor_found;
+               }
+               /* If we want to force another sensor, don't try to probe this
+                * one */
+               return -ENODEV;
+       }
+
+       PDEBUG(D_PROBE, "Probing for a s5k83a sensor");
+
+       /* Preinit the sensor */
+       for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
+               u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
+               if (preinit_s5k83a[i][0] == SENSOR)
+                       err = m5602_write_sensor(sd, preinit_s5k83a[i][1],
+                               data, 2);
+               else
+                       err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
+                               data[0]);
+       }
+
+       /* We don't know what register (if any) that contain the product id
+        * Just pick the first addresses that seem to produce the same results
+        * on multiple machines */
+       if (m5602_read_sensor(sd, 0x00, &prod_id, 1))
+               return -ENODEV;
+
+       if (m5602_read_sensor(sd, 0x01, &ver_id, 1))
+               return -ENODEV;
+
+       if ((prod_id == 0xff) || (ver_id == 0xff))
+               return -ENODEV;
+       else
+               pr_info("Detected a s5k83a sensor\n");
+
+sensor_found:
+       sens_priv = kmalloc(
+               sizeof(struct s5k83a_priv), GFP_KERNEL);
+       if (!sens_priv)
+               return -ENOMEM;
+
+       sens_priv->settings =
+       kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL);
+       if (!sens_priv->settings) {
+               kfree(sens_priv);
+               return -ENOMEM;
+       }
+
+       sd->gspca_dev.cam.cam_mode = s5k83a_modes;
+       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
+       sd->desc->ctrls = s5k83a_ctrls;
+       sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls);
+
+       /* null the pointer! thread is't running now */
+       sens_priv->rotation_thread = NULL;
+
+       for (i = 0; i < ARRAY_SIZE(s5k83a_ctrls); i++)
+               sens_priv->settings[i] = s5k83a_ctrls[i].qctrl.default_value;
+
+       sd->sensor_priv = sens_priv;
+       return 0;
+}
+
+int s5k83a_init(struct sd *sd)
+{
+       int i, err = 0;
+       s32 *sensor_settings =
+                       ((struct s5k83a_priv *) sd->sensor_priv)->settings;
+
+       for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
+               u8 data[2] = {0x00, 0x00};
+
+               switch (init_s5k83a[i][0]) {
+               case BRIDGE:
+                       err = m5602_write_bridge(sd,
+                                       init_s5k83a[i][1],
+                                       init_s5k83a[i][2]);
+                       break;
+
+               case SENSOR:
+                       data[0] = init_s5k83a[i][2];
+                       err = m5602_write_sensor(sd,
+                               init_s5k83a[i][1], data, 1);
+                       break;
+
+               case SENSOR_LONG:
+                       data[0] = init_s5k83a[i][2];
+                       data[1] = init_s5k83a[i][3];
+                       err = m5602_write_sensor(sd,
+                               init_s5k83a[i][1], data, 2);
+                       break;
+               default:
+                       pr_info("Invalid stream command, exiting init\n");
+                       return -EINVAL;
+               }
+       }
+
+       if (dump_sensor)
+               s5k83a_dump_registers(sd);
+
+       err = s5k83a_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
+       if (err < 0)
+               return err;
+
+       err = s5k83a_set_brightness(&sd->gspca_dev,
+                                    sensor_settings[BRIGHTNESS_IDX]);
+       if (err < 0)
+               return err;
+
+       err = s5k83a_set_exposure(&sd->gspca_dev,
+                                  sensor_settings[EXPOSURE_IDX]);
+       if (err < 0)
+               return err;
+
+       err = s5k83a_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
+       if (err < 0)
+               return err;
+
+       err = s5k83a_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
+
+       return err;
+}
+
+static int rotation_thread_function(void *data)
+{
+       struct sd *sd = (struct sd *) data;
+       struct s5k83a_priv *sens_priv = sd->sensor_priv;
+       u8 reg, previous_rotation = 0;
+       __s32 vflip, hflip;
+
+       set_current_state(TASK_INTERRUPTIBLE);
+       while (!schedule_timeout(100)) {
+               if (mutex_lock_interruptible(&sd->gspca_dev.usb_lock))
+                       break;
+
+               s5k83a_get_rotation(sd, &reg);
+               if (previous_rotation != reg) {
+                       previous_rotation = reg;
+                       pr_info("Camera was flipped\n");
+
+                       s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
+                       s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
+
+                       if (reg) {
+                               vflip = !vflip;
+                               hflip = !hflip;
+                       }
+                       s5k83a_set_flip_real((struct gspca_dev *) sd,
+                                             vflip, hflip);
+               }
+
+               mutex_unlock(&sd->gspca_dev.usb_lock);
+               set_current_state(TASK_INTERRUPTIBLE);
+       }
+
+       /* return to "front" flip */
+       if (previous_rotation) {
+               s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
+               s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
+               s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
+       }
+
+       sens_priv->rotation_thread = NULL;
+       return 0;
+}
+
+int s5k83a_start(struct sd *sd)
+{
+       int i, err = 0;
+       struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+       /* Create another thread, polling the GPIO ports of the camera to check
+          if it got rotated. This is how the windows driver does it so we have
+          to assume that there is no better way of accomplishing this */
+       sens_priv->rotation_thread = kthread_create(rotation_thread_function,
+                                                   sd, "rotation thread");
+       wake_up_process(sens_priv->rotation_thread);
+
+       /* Preinit the sensor */
+       for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) {
+               u8 data[2] = {start_s5k83a[i][2], start_s5k83a[i][3]};
+               if (start_s5k83a[i][0] == SENSOR)
+                       err = m5602_write_sensor(sd, start_s5k83a[i][1],
+                               data, 2);
+               else
+                       err = m5602_write_bridge(sd, start_s5k83a[i][1],
+                               data[0]);
+       }
+       if (err < 0)
+               return err;
+
+       return s5k83a_set_led_indication(sd, 1);
+}
+
+int s5k83a_stop(struct sd *sd)
+{
+       struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+       if (sens_priv->rotation_thread)
+               kthread_stop(sens_priv->rotation_thread);
+
+       return s5k83a_set_led_indication(sd, 0);
+}
+
+void s5k83a_disconnect(struct sd *sd)
+{
+       struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+       s5k83a_stop(sd);
+
+       sd->sensor = NULL;
+       kfree(sens_priv->settings);
+       kfree(sens_priv);
+}
+
+static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+       *val = sens_priv->settings[GAIN_IDX];
+       return 0;
+}
+
+static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 data[2];
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+       sens_priv->settings[GAIN_IDX] = val;
+
+       data[0] = 0x00;
+       data[1] = 0x20;
+       err = m5602_write_sensor(sd, 0x14, data, 2);
+       if (err < 0)
+               return err;
+
+       data[0] = 0x01;
+       data[1] = 0x00;
+       err = m5602_write_sensor(sd, 0x0d, data, 2);
+       if (err < 0)
+               return err;
+
+       /* FIXME: This is not sane, we need to figure out the composition
+                 of these registers */
+       data[0] = val >> 3; /* gain, high 5 bits */
+       data[1] = val >> 1; /* gain, high 7 bits */
+       err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
+
+       return err;
+}
+
+static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+       *val = sens_priv->settings[BRIGHTNESS_IDX];
+       return 0;
+}
+
+static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 data[1];
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+       sens_priv->settings[BRIGHTNESS_IDX] = val;
+       data[0] = val;
+       err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
+       return err;
+}
+
+static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+       *val = sens_priv->settings[EXPOSURE_IDX];
+       return 0;
+}
+
+static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 data[2];
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+       sens_priv->settings[EXPOSURE_IDX] = val;
+       data[0] = 0;
+       data[1] = val;
+       err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
+       return err;
+}
+
+static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+       *val = sens_priv->settings[VFLIP_IDX];
+       return 0;
+}
+
+static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
+                               __s32 vflip, __s32 hflip)
+{
+       int err;
+       u8 data[1];
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       data[0] = 0x05;
+       err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
+       if (err < 0)
+               return err;
+
+       /* six bit is vflip, seven is hflip */
+       data[0] = S5K83A_FLIP_MASK;
+       data[0] = (vflip) ? data[0] | 0x40 : data[0];
+       data[0] = (hflip) ? data[0] | 0x80 : data[0];
+
+       err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
+       if (err < 0)
+               return err;
+
+       data[0] = (vflip) ? 0x0b : 0x0a;
+       err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
+       if (err < 0)
+               return err;
+
+       data[0] = (hflip) ? 0x0a : 0x0b;
+       err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
+       return err;
+}
+
+static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 reg;
+       __s32 hflip;
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+       sens_priv->settings[VFLIP_IDX] = val;
+
+       s5k83a_get_hflip(gspca_dev, &hflip);
+
+       err = s5k83a_get_rotation(sd, &reg);
+       if (err < 0)
+               return err;
+       if (reg) {
+               val = !val;
+               hflip = !hflip;
+       }
+
+       err = s5k83a_set_flip_real(gspca_dev, val, hflip);
+       return err;
+}
+
+static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+       *val = sens_priv->settings[HFLIP_IDX];
+       return 0;
+}
+
+static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u8 reg;
+       __s32 vflip;
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct s5k83a_priv *sens_priv = sd->sensor_priv;
+
+       sens_priv->settings[HFLIP_IDX] = val;
+
+       s5k83a_get_vflip(gspca_dev, &vflip);
+
+       err = s5k83a_get_rotation(sd, &reg);
+       if (err < 0)
+               return err;
+       if (reg) {
+               val = !val;
+               vflip = !vflip;
+       }
+
+       err = s5k83a_set_flip_real(gspca_dev, vflip, val);
+       return err;
+}
+
+static int s5k83a_set_led_indication(struct sd *sd, u8 val)
+{
+       int err = 0;
+       u8 data[1];
+
+       err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, data);
+       if (err < 0)
+               return err;
+
+       if (val)
+               data[0] = data[0] | S5K83A_GPIO_LED_MASK;
+       else
+               data[0] = data[0] & ~S5K83A_GPIO_LED_MASK;
+
+       err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]);
+
+       return err;
+}
+
+/* Get camera rotation on Acer notebooks */
+static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data)
+{
+       int err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, reg_data);
+       *reg_data = (*reg_data & S5K83A_GPIO_ROTATION_MASK) ? 0 : 1;
+       return err;
+}
+
+static void s5k83a_dump_registers(struct sd *sd)
+{
+       int address;
+       u8 page, old_page;
+       m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
+
+       for (page = 0; page < 16; page++) {
+               m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
+               pr_info("Dumping the s5k83a register state for page 0x%x\n",
+                       page);
+               for (address = 0; address <= 0xff; address++) {
+                       u8 val = 0;
+                       m5602_read_sensor(sd, address, &val, 1);
+                       pr_info("register 0x%x contains 0x%x\n", address, val);
+               }
+       }
+       pr_info("s5k83a register state dump complete\n");
+
+       for (page = 0; page < 16; page++) {
+               m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
+               pr_info("Probing for which registers that are read/write for page 0x%x\n",
+                       page);
+               for (address = 0; address <= 0xff; address++) {
+                       u8 old_val, ctrl_val, test_val = 0xff;
+
+                       m5602_read_sensor(sd, address, &old_val, 1);
+                       m5602_write_sensor(sd, address, &test_val, 1);
+                       m5602_read_sensor(sd, address, &ctrl_val, 1);
+
+                       if (ctrl_val == test_val)
+                               pr_info("register 0x%x is writeable\n",
+                                       address);
+                       else
+                               pr_info("register 0x%x is read only\n",
+                                       address);
+
+                       /* Restore original val */
+                       m5602_write_sensor(sd, address, &old_val, 1);
+               }
+       }
+       pr_info("Read/write register probing complete\n");
+       m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
+}
diff --git a/drivers/media/usb/gspca/m5602/m5602_s5k83a.h b/drivers/media/usb/gspca/m5602/m5602_s5k83a.h
new file mode 100644 (file)
index 0000000..7995224
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Driver for the s5k83a sensor
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#ifndef M5602_S5K83A_H_
+#define M5602_S5K83A_H_
+
+#include "m5602_sensor.h"
+
+#define S5K83A_FLIP                    0x01
+#define S5K83A_HFLIP_TUNE              0x03
+#define S5K83A_VFLIP_TUNE              0x05
+#define S5K83A_BRIGHTNESS              0x0a
+#define S5K83A_EXPOSURE                        0x18
+#define S5K83A_GAIN                    0x1b
+#define S5K83A_PAGE_MAP                        0xec
+
+#define S5K83A_DEFAULT_GAIN            0x71
+#define S5K83A_DEFAULT_BRIGHTNESS      0x7e
+#define S5K83A_DEFAULT_EXPOSURE                0x00
+#define S5K83A_MAXIMUM_EXPOSURE                0x3c
+#define S5K83A_FLIP_MASK               0x10
+#define S5K83A_GPIO_LED_MASK           0x10
+#define S5K83A_GPIO_ROTATION_MASK      0x40
+
+/*****************************************************************************/
+
+/* Kernel module parameters */
+extern int force_sensor;
+extern bool dump_sensor;
+
+int s5k83a_probe(struct sd *sd);
+int s5k83a_init(struct sd *sd);
+int s5k83a_start(struct sd *sd);
+int s5k83a_stop(struct sd *sd);
+void s5k83a_disconnect(struct sd *sd);
+
+static const struct m5602_sensor s5k83a = {
+       .name = "S5K83A",
+       .probe = s5k83a_probe,
+       .init = s5k83a_init,
+       .start = s5k83a_start,
+       .stop = s5k83a_stop,
+       .disconnect = s5k83a_disconnect,
+       .i2c_slave_id = 0x5a,
+       .i2c_regW = 2,
+};
+
+struct s5k83a_priv {
+       /* We use another thread periodically
+          probing the orientation of the camera */
+       struct task_struct *rotation_thread;
+       s32 *settings;
+};
+
+static const unsigned char preinit_s5k83a[][4] = {
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
+
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+};
+
+/* This could probably be considerably shortened.
+   I don't have the hardware to experiment with it, patches welcome
+*/
+static const unsigned char init_s5k83a[][4] = {
+       /* The following sequence is useless after a clean boot
+          but is necessary after resume from suspend */
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
+       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
+       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
+       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
+       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
+
+       {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
+       {SENSOR, 0xaf, 0x01, 0x00},
+       {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
+       {SENSOR, 0x7b, 0xff, 0x00},
+       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
+       {SENSOR, 0x01, 0x50, 0x00},
+       {SENSOR, 0x12, 0x20, 0x00},
+       {SENSOR, 0x17, 0x40, 0x00},
+       {SENSOR, 0x1c, 0x00, 0x00},
+       {SENSOR, 0x02, 0x70, 0x00},
+       {SENSOR, 0x03, 0x0b, 0x00},
+       {SENSOR, 0x04, 0xf0, 0x00},
+       {SENSOR, 0x05, 0x0b, 0x00},
+       {SENSOR, 0x06, 0x71, 0x00},
+       {SENSOR, 0x07, 0xe8, 0x00}, /* 488 */
+       {SENSOR, 0x08, 0x02, 0x00},
+       {SENSOR, 0x09, 0x88, 0x00}, /* 648 */
+       {SENSOR, 0x14, 0x00, 0x00},
+       {SENSOR, 0x15, 0x20, 0x00}, /* 32 */
+       {SENSOR, 0x19, 0x00, 0x00},
+       {SENSOR, 0x1a, 0x98, 0x00}, /* 152 */
+       {SENSOR, 0x0f, 0x02, 0x00},
+       {SENSOR, 0x10, 0xe5, 0x00}, /* 741 */
+       /* normal colors
+       (this is value after boot, but after tries can be different) */
+       {SENSOR, 0x00, 0x06, 0x00},
+};
+
+static const unsigned char start_s5k83a[][4] = {
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
+       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
+       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
+       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, /* 484 */
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
+       {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, /* 639 */
+       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
+       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
+};
+#endif
diff --git a/drivers/media/usb/gspca/m5602/m5602_sensor.h b/drivers/media/usb/gspca/m5602/m5602_sensor.h
new file mode 100644 (file)
index 0000000..edff4f1
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * USB Driver for ALi m5602 based webcams
+ *
+ * Copyright (C) 2008 Erik Andrén
+ * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
+ * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
+ *
+ * Portions of code to USB interface and ALi driver software,
+ * Copyright (c) 2006 Willem Duinker
+ * v4l2 interface modeled after the V4L2 driver
+ * for SN9C10x PC Camera Controllers
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2.
+ *
+ */
+
+#ifndef M5602_SENSOR_H_
+#define M5602_SENSOR_H_
+
+#include "m5602_bridge.h"
+
+#define M5602_V4L2_CID_GREEN_BALANCE   (V4L2_CID_PRIVATE_BASE + 0)
+#define M5602_V4L2_CID_NOISE_SUPPRESION        (V4L2_CID_PRIVATE_BASE + 1)
+
+/* Enumerates all supported sensors */
+enum sensors {
+       OV9650_SENSOR   = 1,
+       S5K83A_SENSOR   = 2,
+       S5K4AA_SENSOR   = 3,
+       MT9M111_SENSOR  = 4,
+       PO1030_SENSOR   = 5,
+       OV7660_SENSOR   = 6,
+};
+
+/* Enumerates all possible instruction types */
+enum instruction {
+       BRIDGE,
+       SENSOR,
+       SENSOR_LONG
+};
+
+struct m5602_sensor {
+       /* Defines the name of a sensor */
+       char name[32];
+
+       /* What i2c address the sensor is connected to */
+       u8 i2c_slave_id;
+
+       /* Width of each i2c register (in bytes) */
+       u8 i2c_regW;
+
+       /* Probes if the sensor is connected */
+       int (*probe)(struct sd *sd);
+
+       /* Performs a initialization sequence */
+       int (*init)(struct sd *sd);
+
+       /* Executed when the camera starts to send data */
+       int (*start)(struct sd *sd);
+
+       /* Executed when the camera ends to send data */
+       int (*stop)(struct sd *sd);
+
+       /* Executed when the device is disconnected */
+       void (*disconnect)(struct sd *sd);
+};
+
+#endif
diff --git a/drivers/media/usb/gspca/mars.c b/drivers/media/usb/gspca/mars.c
new file mode 100644 (file)
index 0000000..ff2c5ab
--- /dev/null
@@ -0,0 +1,439 @@
+/*
+ *             Mars-Semi MR97311A library
+ *             Copyright (C) 2005 <bradlch@hotmail.com>
+ *
+ * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "mars"
+
+#include "gspca.h"
+#include "jpeg.h"
+
+MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
+MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+#define QUALITY 50
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       struct v4l2_ctrl *brightness;
+       struct v4l2_ctrl *saturation;
+       struct v4l2_ctrl *sharpness;
+       struct v4l2_ctrl *gamma;
+       struct { /* illuminator control cluster */
+               struct v4l2_ctrl *illum_top;
+               struct v4l2_ctrl *illum_bottom;
+       };
+       u8 jpeg_hdr[JPEG_HDR_SZ];
+};
+
+/* V4L2 controls supported by the driver */
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val);
+static void setcolors(struct gspca_dev *gspca_dev, s32 val);
+static void setgamma(struct gspca_dev *gspca_dev, s32 val);
+static void setsharpness(struct gspca_dev *gspca_dev, s32 val);
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+};
+
+static const __u8 mi_data[0x20] = {
+/*      01    02   03     04    05    06    07    08 */
+       0x48, 0x22, 0x01, 0x47, 0x10, 0x00, 0x00, 0x00,
+/*      09    0a   0b     0c    0d    0e    0f    10 */
+       0x00, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01,
+/*      11    12   13     14    15    16    17    18 */
+       0x30, 0x00, 0x04, 0x00, 0x06, 0x01, 0xe2, 0x02,
+/*      19    1a   1b     1c    1d    1e    1f    20 */
+       0x82, 0x00, 0x20, 0x17, 0x80, 0x08, 0x0c, 0x00
+};
+
+/* write <len> bytes from gspca_dev->usb_buf */
+static void reg_w(struct gspca_dev *gspca_dev,
+                int len)
+{
+       int alen, ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       ret = usb_bulk_msg(gspca_dev->dev,
+                       usb_sndbulkpipe(gspca_dev->dev, 4),
+                       gspca_dev->usb_buf,
+                       len,
+                       &alen,
+                       500);   /* timeout in milliseconds */
+       if (ret < 0) {
+               pr_err("reg write [%02x] error %d\n",
+                      gspca_dev->usb_buf[0], ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void mi_w(struct gspca_dev *gspca_dev,
+                u8 addr,
+                u8 value)
+{
+       gspca_dev->usb_buf[0] = 0x1f;
+       gspca_dev->usb_buf[1] = 0;                      /* control byte */
+       gspca_dev->usb_buf[2] = addr;
+       gspca_dev->usb_buf[3] = value;
+
+       reg_w(gspca_dev, 4);
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       gspca_dev->usb_buf[0] = 0x61;
+       gspca_dev->usb_buf[1] = val;
+       reg_w(gspca_dev, 2);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev, s32 val)
+{
+       gspca_dev->usb_buf[0] = 0x5f;
+       gspca_dev->usb_buf[1] = val << 3;
+       gspca_dev->usb_buf[2] = ((val >> 2) & 0xf8) | 0x04;
+       reg_w(gspca_dev, 3);
+}
+
+static void setgamma(struct gspca_dev *gspca_dev, s32 val)
+{
+       gspca_dev->usb_buf[0] = 0x06;
+       gspca_dev->usb_buf[1] = val * 0x40;
+       reg_w(gspca_dev, 2);
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
+{
+       gspca_dev->usb_buf[0] = 0x67;
+       gspca_dev->usb_buf[1] = val * 4 + 3;
+       reg_w(gspca_dev, 2);
+}
+
+static void setilluminators(struct gspca_dev *gspca_dev, bool top, bool bottom)
+{
+       /* both are off if not streaming */
+       gspca_dev->usb_buf[0] = 0x22;
+       if (top)
+               gspca_dev->usb_buf[1] = 0x76;
+       else if (bottom)
+               gspca_dev->usb_buf[1] = 0x7a;
+       else
+               gspca_dev->usb_buf[1] = 0x7e;
+       reg_w(gspca_dev, 2);
+}
+
+static int mars_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 (ctrl->id == V4L2_CID_ILLUMINATORS_1) {
+               /* only one can be on at a time */
+               if (ctrl->is_new && ctrl->val)
+                       sd->illum_bottom->val = 0;
+               if (sd->illum_bottom->is_new && sd->illum_bottom->val)
+                       sd->illum_top->val = 0;
+       }
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               setcolors(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_GAMMA:
+               setgamma(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_ILLUMINATORS_1:
+               setilluminators(gspca_dev, sd->illum_top->val,
+                                          sd->illum_bottom->val);
+               break;
+       case V4L2_CID_SHARPNESS:
+               setsharpness(gspca_dev, ctrl->val);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return gspca_dev->usb_err;
+}
+
+static const struct v4l2_ctrl_ops mars_ctrl_ops = {
+       .s_ctrl = mars_s_ctrl,
+};
+
+/* this function is called at probe time */
+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, 6);
+       sd->brightness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 30, 1, 15);
+       sd->saturation = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 255, 1, 200);
+       sd->gamma = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
+                       V4L2_CID_GAMMA, 0, 3, 1, 1);
+       sd->sharpness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
+                       V4L2_CID_SHARPNESS, 0, 2, 1, 1);
+       sd->illum_top = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
+                       V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
+       sd->illum_top->flags |= V4L2_CTRL_FLAG_UPDATE;
+       sd->illum_bottom = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
+                       V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0);
+       sd->illum_bottom->flags |= V4L2_CTRL_FLAG_UPDATE;
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       v4l2_ctrl_cluster(2, &sd->illum_top);
+       return 0;
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct cam *cam;
+
+       cam = &gspca_dev->cam;
+       cam->cam_mode = vga_mode;
+       cam->nmodes = ARRAY_SIZE(vga_mode);
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       return 0;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 *data;
+       int i;
+
+       /* create the JPEG header */
+       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+                       0x21);          /* JPEG 422 */
+       jpeg_set_qual(sd->jpeg_hdr, QUALITY);
+
+       data = gspca_dev->usb_buf;
+
+       data[0] = 0x01;         /* address */
+       data[1] = 0x01;
+       reg_w(gspca_dev, 2);
+
+       /*
+          Initialize the MR97113 chip register
+        */
+       data[0] = 0x00;         /* address */
+       data[1] = 0x0c | 0x01;  /* reg 0 */
+       data[2] = 0x01;         /* reg 1 */
+       data[3] = gspca_dev->width / 8;         /* h_size , reg 2 */
+       data[4] = gspca_dev->height / 8;        /* v_size , reg 3 */
+       data[5] = 0x30;         /* reg 4, MI, PAS5101 :
+                                *      0x30 for 24mhz , 0x28 for 12mhz */
+       data[6] = 0x02;         /* reg 5, H start - was 0x04 */
+       data[7] = v4l2_ctrl_g_ctrl(sd->gamma) * 0x40;   /* reg 0x06: gamma */
+       data[8] = 0x01;         /* reg 7, V start - was 0x03 */
+/*     if (h_size == 320 ) */
+/*             data[9]= 0x56;   * reg 8, 24MHz, 2:1 scale down */
+/*     else */
+       data[9] = 0x52;         /* reg 8, 24MHz, no scale down */
+/*jfm: from win trace*/
+       data[10] = 0x18;
+
+       reg_w(gspca_dev, 11);
+
+       data[0] = 0x23;         /* address */
+       data[1] = 0x09;         /* reg 35, append frame header */
+
+       reg_w(gspca_dev, 2);
+
+       data[0] = 0x3c;         /* address */
+/*     if (gspca_dev->width == 1280) */
+/*             data[1] = 200;   * reg 60, pc-cam frame size
+                                *      (unit: 4KB) 800KB */
+/*     else */
+       data[1] = 50;           /* 50 reg 60, pc-cam frame size
+                                *      (unit: 4KB) 200KB */
+       reg_w(gspca_dev, 2);
+
+       /* auto dark-gain */
+       data[0] = 0x5e;         /* address */
+       data[1] = 0;            /* reg 94, Y Gain (auto) */
+/*jfm: from win trace*/
+                               /* reg 0x5f/0x60 (LE) = saturation */
+                               /* h (60): xxxx x100
+                                * l (5f): xxxx x000 */
+       data[2] = v4l2_ctrl_g_ctrl(sd->saturation) << 3;
+       data[3] = ((v4l2_ctrl_g_ctrl(sd->saturation) >> 2) & 0xf8) | 0x04;
+       data[4] = v4l2_ctrl_g_ctrl(sd->brightness); /* reg 0x61 = brightness */
+       data[5] = 0x00;
+
+       reg_w(gspca_dev, 6);
+
+       data[0] = 0x67;
+/*jfm: from win trace*/
+       data[1] = v4l2_ctrl_g_ctrl(sd->sharpness) * 4 + 3;
+       data[2] = 0x14;
+       reg_w(gspca_dev, 3);
+
+       data[0] = 0x69;
+       data[1] = 0x2f;
+       data[2] = 0x28;
+       data[3] = 0x42;
+       reg_w(gspca_dev, 4);
+
+       data[0] = 0x63;
+       data[1] = 0x07;
+       reg_w(gspca_dev, 2);
+/*jfm: win trace - many writes here to reg 0x64*/
+
+       /* initialize the MI sensor */
+       for (i = 0; i < sizeof mi_data; i++)
+               mi_w(gspca_dev, i + 1, mi_data[i]);
+
+       data[0] = 0x00;
+       data[1] = 0x4d;         /* ISOC transferring enable... */
+       reg_w(gspca_dev, 2);
+
+       setilluminators(gspca_dev, v4l2_ctrl_g_ctrl(sd->illum_top),
+                                  v4l2_ctrl_g_ctrl(sd->illum_bottom));
+
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (v4l2_ctrl_g_ctrl(sd->illum_top) ||
+           v4l2_ctrl_g_ctrl(sd->illum_bottom)) {
+               setilluminators(gspca_dev, false, false);
+               msleep(20);
+       }
+
+       gspca_dev->usb_buf[0] = 1;
+       gspca_dev->usb_buf[1] = 0;
+       reg_w(gspca_dev, 2);
+}
+
+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;
+       int p;
+
+       if (len < 6) {
+/*             gspca_dev->last_packet_type = DISCARD_PACKET; */
+               return;
+       }
+       for (p = 0; p < len - 6; p++) {
+               if (data[0 + p] == 0xff
+                   && data[1 + p] == 0xff
+                   && data[2 + p] == 0x00
+                   && data[3 + p] == 0xff
+                   && data[4 + p] == 0x96) {
+                       if (data[5 + p] == 0x64
+                           || data[5 + p] == 0x65
+                           || data[5 + p] == 0x66
+                           || data[5 + p] == 0x67) {
+                               PDEBUG(D_PACK, "sof offset: %d len: %d",
+                                       p, len);
+                               gspca_frame_add(gspca_dev, LAST_PACKET,
+                                               data, p);
+
+                               /* put the JPEG header */
+                               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                                       sd->jpeg_hdr, JPEG_HDR_SZ);
+                               data += p + 16;
+                               len -= p + 16;
+                               break;
+                       }
+               }
+       }
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+/* 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,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x093a, 0x050f)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/mr97310a.c b/drivers/media/usb/gspca/mr97310a.c
new file mode 100644 (file)
index 0000000..8f4714d
--- /dev/null
@@ -0,0 +1,1091 @@
+/*
+ * Mars MR97310A library
+ *
+ * The original mr97310a driver, which supported the Aiptek Pencam VGA+, is
+ * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com>
+ *
+ * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+
+ * and for the routines for detecting and classifying these various cameras,
+ * is Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
+ *
+ * Support for the control settings for the CIF cameras is
+ * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> and
+ * Thomas Kaiser <thomas@kaiser-linux.li>
+ *
+ * Support for the control settings for the VGA cameras is
+ * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
+ *
+ * Several previously unsupported cameras are owned and have been tested by
+ * Hans de Goede <hdegoede@redhat.com> and
+ * Thomas Kaiser <thomas@kaiser-linux.li> and
+ * Theodore Kilgore <kilgota@auburn.edu> and
+ * Edmond Rodriguez <erodrig_97@yahoo.com> and
+ * Aurelien Jacobs <aurel@gnuage.org>
+ *
+ * The MR97311A support in gspca/mars.c has been helpful in understanding some
+ * of the registers in these cameras.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "mr97310a"
+
+#include "gspca.h"
+
+#define CAM_TYPE_CIF                   0
+#define CAM_TYPE_VGA                   1
+
+#define MR97310A_BRIGHTNESS_DEFAULT    0
+
+#define MR97310A_EXPOSURE_MIN          0
+#define MR97310A_EXPOSURE_MAX          4095
+#define MR97310A_EXPOSURE_DEFAULT      1000
+
+#define MR97310A_GAIN_MIN              0
+#define MR97310A_GAIN_MAX              31
+#define MR97310A_GAIN_DEFAULT          25
+
+#define MR97310A_CONTRAST_MIN          0
+#define MR97310A_CONTRAST_MAX          31
+#define MR97310A_CONTRAST_DEFAULT      23
+
+#define MR97310A_CS_GAIN_MIN           0
+#define MR97310A_CS_GAIN_MAX           0x7ff
+#define MR97310A_CS_GAIN_DEFAULT       0x110
+
+#define MR97310A_CID_CLOCKDIV (V4L2_CTRL_CLASS_USER + 0x1000)
+#define MR97310A_MIN_CLOCKDIV_MIN      3
+#define MR97310A_MIN_CLOCKDIV_MAX      8
+#define MR97310A_MIN_CLOCKDIV_DEFAULT  3
+
+MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>,"
+             "Theodore Kilgore <kilgota@auburn.edu>");
+MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* global parameters */
+static int force_sensor_type = -1;
+module_param(force_sensor_type, int, 0644);
+MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;  /* !! must be the first item */
+       struct { /* exposure/min_clockdiv control cluster */
+               struct v4l2_ctrl *exposure;
+               struct v4l2_ctrl *min_clockdiv;
+       };
+       u8 sof_read;
+       u8 cam_type;    /* 0 is CIF and 1 is VGA */
+       u8 sensor_type; /* We use 0 and 1 here, too. */
+       u8 do_lcd_stop;
+       u8 adj_colors;
+};
+
+struct sensor_w_data {
+       u8 reg;
+       u8 flags;
+       u8 data[16];
+       int len;
+};
+
+static void sd_stopN(struct gspca_dev *gspca_dev);
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 4},
+       {176, 144, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 3},
+       {320, 240, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+       {352, 288, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+/* the bytes to write are in gspca_dev->usb_buf */
+static int mr_write(struct gspca_dev *gspca_dev, int len)
+{
+       int rc;
+
+       rc = usb_bulk_msg(gspca_dev->dev,
+                         usb_sndbulkpipe(gspca_dev->dev, 4),
+                         gspca_dev->usb_buf, len, NULL, 500);
+       if (rc < 0)
+               pr_err("reg write [%02x] error %d\n",
+                      gspca_dev->usb_buf[0], rc);
+       return rc;
+}
+
+/* the bytes are read into gspca_dev->usb_buf */
+static int mr_read(struct gspca_dev *gspca_dev, int len)
+{
+       int rc;
+
+       rc = usb_bulk_msg(gspca_dev->dev,
+                         usb_rcvbulkpipe(gspca_dev->dev, 3),
+                         gspca_dev->usb_buf, len, NULL, 500);
+       if (rc < 0)
+               pr_err("reg read [%02x] error %d\n",
+                      gspca_dev->usb_buf[0], rc);
+       return rc;
+}
+
+static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags,
+       const u8 *data, int len)
+{
+       gspca_dev->usb_buf[0] = 0x1f;
+       gspca_dev->usb_buf[1] = flags;
+       gspca_dev->usb_buf[2] = reg;
+       memcpy(gspca_dev->usb_buf + 3, data, len);
+
+       return mr_write(gspca_dev, len + 3);
+}
+
+static int sensor_write_regs(struct gspca_dev *gspca_dev,
+       const struct sensor_w_data *data, int len)
+{
+       int i, rc;
+
+       for (i = 0; i < len; i++) {
+               rc = sensor_write_reg(gspca_dev, data[i].reg, data[i].flags,
+                                         data[i].data, data[i].len);
+               if (rc < 0)
+                       return rc;
+       }
+
+       return 0;
+}
+
+static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 buf, confirm_reg;
+       int rc;
+
+       buf = data;
+       if (sd->cam_type == CAM_TYPE_CIF) {
+               rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1);
+               confirm_reg = sd->sensor_type ? 0x13 : 0x11;
+       } else {
+               rc = sensor_write_reg(gspca_dev, reg, 0x00, &buf, 1);
+               confirm_reg = 0x11;
+       }
+       if (rc < 0)
+               return rc;
+
+       buf = 0x01;
+       rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1);
+       if (rc < 0)
+               return rc;
+
+       return 0;
+}
+
+static int cam_get_response16(struct gspca_dev *gspca_dev, u8 reg, int verbose)
+{
+       int err_code;
+
+       gspca_dev->usb_buf[0] = reg;
+       err_code = mr_write(gspca_dev, 1);
+       if (err_code < 0)
+               return err_code;
+
+       err_code = mr_read(gspca_dev, 16);
+       if (err_code < 0)
+               return err_code;
+
+       if (verbose)
+               PDEBUG(D_PROBE, "Register: %02x reads %02x%02x%02x", reg,
+                      gspca_dev->usb_buf[0],
+                      gspca_dev->usb_buf[1],
+                      gspca_dev->usb_buf[2]);
+
+       return 0;
+}
+
+static int zero_the_pointer(struct gspca_dev *gspca_dev)
+{
+       __u8 *data = gspca_dev->usb_buf;
+       int err_code;
+       u8 status = 0;
+       int tries = 0;
+
+       err_code = cam_get_response16(gspca_dev, 0x21, 0);
+       if (err_code < 0)
+               return err_code;
+
+       data[0] = 0x19;
+       data[1] = 0x51;
+       err_code = mr_write(gspca_dev, 2);
+       if (err_code < 0)
+               return err_code;
+
+       err_code = cam_get_response16(gspca_dev, 0x21, 0);
+       if (err_code < 0)
+               return err_code;
+
+       data[0] = 0x19;
+       data[1] = 0xba;
+       err_code = mr_write(gspca_dev, 2);
+       if (err_code < 0)
+               return err_code;
+
+       err_code = cam_get_response16(gspca_dev, 0x21, 0);
+       if (err_code < 0)
+               return err_code;
+
+       data[0] = 0x19;
+       data[1] = 0x00;
+       err_code = mr_write(gspca_dev, 2);
+       if (err_code < 0)
+               return err_code;
+
+       err_code = cam_get_response16(gspca_dev, 0x21, 0);
+       if (err_code < 0)
+               return err_code;
+
+       data[0] = 0x19;
+       data[1] = 0x00;
+       err_code = mr_write(gspca_dev, 2);
+       if (err_code < 0)
+               return err_code;
+
+       while (status != 0x0a && tries < 256) {
+               err_code = cam_get_response16(gspca_dev, 0x21, 0);
+               status = data[0];
+               tries++;
+               if (err_code < 0)
+                       return err_code;
+       }
+       if (status != 0x0a)
+               PDEBUG(D_ERR, "status is %02x", status);
+
+       tries = 0;
+       while (tries < 4) {
+               data[0] = 0x19;
+               data[1] = 0x00;
+               err_code = mr_write(gspca_dev, 2);
+               if (err_code < 0)
+                       return err_code;
+
+               err_code = cam_get_response16(gspca_dev, 0x21, 0);
+               status = data[0];
+               tries++;
+               if (err_code < 0)
+                       return err_code;
+       }
+
+       data[0] = 0x19;
+       err_code = mr_write(gspca_dev, 1);
+       if (err_code < 0)
+               return err_code;
+
+       err_code = mr_read(gspca_dev, 16);
+       if (err_code < 0)
+               return err_code;
+
+       return 0;
+}
+
+static int stream_start(struct gspca_dev *gspca_dev)
+{
+       gspca_dev->usb_buf[0] = 0x01;
+       gspca_dev->usb_buf[1] = 0x01;
+       return mr_write(gspca_dev, 2);
+}
+
+static void stream_stop(struct gspca_dev *gspca_dev)
+{
+       gspca_dev->usb_buf[0] = 0x01;
+       gspca_dev->usb_buf[1] = 0x00;
+       if (mr_write(gspca_dev, 2) < 0)
+               PDEBUG(D_ERR, "Stream Stop failed");
+}
+
+static void lcd_stop(struct gspca_dev *gspca_dev)
+{
+       gspca_dev->usb_buf[0] = 0x19;
+       gspca_dev->usb_buf[1] = 0x54;
+       if (mr_write(gspca_dev, 2) < 0)
+               PDEBUG(D_ERR, "LCD Stop failed");
+}
+
+static int isoc_enable(struct gspca_dev *gspca_dev)
+{
+       gspca_dev->usb_buf[0] = 0x00;
+       gspca_dev->usb_buf[1] = 0x4d;  /* ISOC transferring enable... */
+       return mr_write(gspca_dev, 2);
+}
+
+/* This function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                    const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+       int err_code;
+
+       cam = &gspca_dev->cam;
+       cam->cam_mode = vga_mode;
+       cam->nmodes = ARRAY_SIZE(vga_mode);
+       sd->do_lcd_stop = 0;
+
+       /* Several of the supported CIF cameras share the same USB ID but
+        * require different initializations and different control settings.
+        * The same is true of the VGA cameras. Therefore, we are forced
+        * to start the initialization process in order to determine which
+        * camera is present. Some of the supported cameras require the
+        * memory pointer to be set to 0 as the very first item of business
+        * or else they will not stream. So we do that immediately.
+        */
+       err_code = zero_the_pointer(gspca_dev);
+       if (err_code < 0)
+               return err_code;
+
+       err_code = stream_start(gspca_dev);
+       if (err_code < 0)
+               return err_code;
+
+       /* Now, the query for sensor type. */
+       err_code = cam_get_response16(gspca_dev, 0x07, 1);
+       if (err_code < 0)
+               return err_code;
+
+       if (id->idProduct == 0x0110 || id->idProduct == 0x010e) {
+               sd->cam_type = CAM_TYPE_CIF;
+               cam->nmodes--;
+               /*
+                * All but one of the known CIF cameras share the same USB ID,
+                * but two different init routines are in use, and the control
+                * settings are different, too. We need to detect which camera
+                * of the two known varieties is connected!
+                *
+                * A list of known CIF cameras follows. They all report either
+                * 0200 for type 0 or 0300 for type 1.
+                * If you have another to report, please do
+                *
+                * Name         sd->sensor_type         reported by
+                *
+                * Sakar 56379 Spy-shot 0               T. Kilgore
+                * Innovage             0               T. Kilgore
+                * Vivitar Mini         0               H. De Goede
+                * Vivitar Mini         0               E. Rodriguez
+                * Vivitar Mini         1               T. Kilgore
+                * Elta-Media 8212dc    1               T. Kaiser
+                * Philips dig. keych.  1               T. Kilgore
+                * Trust Spyc@m 100     1               A. Jacobs
+                */
+               switch (gspca_dev->usb_buf[0]) {
+               case 2:
+                       sd->sensor_type = 0;
+                       break;
+               case 3:
+                       sd->sensor_type = 1;
+                       break;
+               default:
+                       pr_err("Unknown CIF Sensor id : %02x\n",
+                              gspca_dev->usb_buf[1]);
+                       return -ENODEV;
+               }
+               PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d",
+                      sd->sensor_type);
+       } else {
+               sd->cam_type = CAM_TYPE_VGA;
+
+               /*
+                * Here is a table of the responses to the query for sensor
+                * type, from the known MR97310A VGA cameras. Six different
+                * cameras of which five share the same USB ID.
+                *
+                * Name                 gspca_dev->usb_buf[]    sd->sensor_type
+                *                              sd->do_lcd_stop
+                * Aiptek Pencam VGA+   0300            0               1
+                * ION digital          0300            0               1
+                * Argus DC-1620        0450            1               0
+                * Argus QuickClix      0420            1               1
+                * Sakar 77379 Digital  0350            0               1
+                * Sakar 1638x CyberPix 0120            0               2
+                *
+                * Based upon these results, we assume default settings
+                * and then correct as necessary, as follows.
+                *
+                */
+
+               sd->sensor_type = 1;
+               sd->do_lcd_stop = 0;
+               sd->adj_colors = 0;
+               if (gspca_dev->usb_buf[0] == 0x01) {
+                       sd->sensor_type = 2;
+               } else if ((gspca_dev->usb_buf[0] != 0x03) &&
+                                       (gspca_dev->usb_buf[0] != 0x04)) {
+                       pr_err("Unknown VGA Sensor id Byte 0: %02x\n",
+                              gspca_dev->usb_buf[0]);
+                       pr_err("Defaults assumed, may not work\n");
+                       pr_err("Please report this\n");
+               }
+               /* Sakar Digital color needs to be adjusted. */
+               if ((gspca_dev->usb_buf[0] == 0x03) &&
+                                       (gspca_dev->usb_buf[1] == 0x50))
+                       sd->adj_colors = 1;
+               if (gspca_dev->usb_buf[0] == 0x04) {
+                       sd->do_lcd_stop = 1;
+                       switch (gspca_dev->usb_buf[1]) {
+                       case 0x50:
+                               sd->sensor_type = 0;
+                               PDEBUG(D_PROBE, "sensor_type corrected to 0");
+                               break;
+                       case 0x20:
+                               /* Nothing to do here. */
+                               break;
+                       default:
+                               pr_err("Unknown VGA Sensor id Byte 1: %02x\n",
+                                      gspca_dev->usb_buf[1]);
+                               pr_err("Defaults assumed, may not work\n");
+                               pr_err("Please report this\n");
+                       }
+               }
+               PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d",
+                      sd->sensor_type);
+       }
+       /* Stop streaming as we've started it only to probe the sensor type. */
+       sd_stopN(gspca_dev);
+
+       if (force_sensor_type != -1) {
+               sd->sensor_type = !!force_sensor_type;
+               PDEBUG(D_PROBE, "Forcing sensor type to: %d",
+                      sd->sensor_type);
+       }
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       return 0;
+}
+
+static int start_cif_cam(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       __u8 *data = gspca_dev->usb_buf;
+       int err_code;
+       static const __u8 startup_string[] = {
+               0x00,
+               0x0d,
+               0x01,
+               0x00, /* Hsize/8 for 352 or 320 */
+               0x00, /* Vsize/4 for 288 or 240 */
+               0x13, /* or 0xbb, depends on sensor */
+               0x00, /* Hstart, depends on res. */
+               0x00, /* reserved ? */
+               0x00, /* Vstart, depends on res. and sensor */
+               0x50, /* 0x54 to get 176 or 160 */
+               0xc0
+       };
+
+       /* Note: Some of the above descriptions guessed from MR97113A driver */
+
+       memcpy(data, startup_string, 11);
+       if (sd->sensor_type)
+               data[5] = 0xbb;
+
+       switch (gspca_dev->width) {
+       case 160:
+               data[9] |= 0x04;  /* reg 8, 2:1 scale down from 320 */
+               /* fall thru */
+       case 320:
+       default:
+               data[3] = 0x28;                    /* reg 2, H size/8 */
+               data[4] = 0x3c;                    /* reg 3, V size/4 */
+               data[6] = 0x14;                    /* reg 5, H start  */
+               data[8] = 0x1a + sd->sensor_type;  /* reg 7, V start  */
+               break;
+       case 176:
+               data[9] |= 0x04;  /* reg 8, 2:1 scale down from 352 */
+               /* fall thru */
+       case 352:
+               data[3] = 0x2c;                    /* reg 2, H size/8 */
+               data[4] = 0x48;                    /* reg 3, V size/4 */
+               data[6] = 0x06;                    /* reg 5, H start  */
+               data[8] = 0x06 - sd->sensor_type;  /* reg 7, V start  */
+               break;
+       }
+       err_code = mr_write(gspca_dev, 11);
+       if (err_code < 0)
+               return err_code;
+
+       if (!sd->sensor_type) {
+               static const struct sensor_w_data cif_sensor0_init_data[] = {
+                       {0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01,
+                                     0x0f, 0x14, 0x0f, 0x10}, 8},
+                       {0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5},
+                       {0x12, 0x00, {0x07}, 1},
+                       {0x1f, 0x00, {0x06}, 1},
+                       {0x27, 0x00, {0x04}, 1},
+                       {0x29, 0x00, {0x0c}, 1},
+                       {0x40, 0x00, {0x40, 0x00, 0x04}, 3},
+                       {0x50, 0x00, {0x60}, 1},
+                       {0x60, 0x00, {0x06}, 1},
+                       {0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6},
+                       {0x72, 0x00, {0x1e, 0x56}, 2},
+                       {0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02,
+                                     0x31, 0x80, 0x00}, 9},
+                       {0x11, 0x00, {0x01}, 1},
+                       {0, 0, {0}, 0}
+               };
+               err_code = sensor_write_regs(gspca_dev, cif_sensor0_init_data,
+                                        ARRAY_SIZE(cif_sensor0_init_data));
+       } else {        /* sd->sensor_type = 1 */
+               static const struct sensor_w_data cif_sensor1_init_data[] = {
+                       /* Reg 3,4, 7,8 get set by the controls */
+                       {0x02, 0x00, {0x10}, 1},
+                       {0x05, 0x01, {0x22}, 1}, /* 5/6 also seen as 65h/32h */
+                       {0x06, 0x01, {0x00}, 1},
+                       {0x09, 0x02, {0x0e}, 1},
+                       {0x0a, 0x02, {0x05}, 1},
+                       {0x0b, 0x02, {0x05}, 1},
+                       {0x0c, 0x02, {0x0f}, 1},
+                       {0x0d, 0x02, {0x07}, 1},
+                       {0x0e, 0x02, {0x0c}, 1},
+                       {0x0f, 0x00, {0x00}, 1},
+                       {0x10, 0x00, {0x06}, 1},
+                       {0x11, 0x00, {0x07}, 1},
+                       {0x12, 0x00, {0x00}, 1},
+                       {0x13, 0x00, {0x01}, 1},
+                       {0, 0, {0}, 0}
+               };
+               /* Without this command the cam won't work with USB-UHCI */
+               gspca_dev->usb_buf[0] = 0x0a;
+               gspca_dev->usb_buf[1] = 0x00;
+               err_code = mr_write(gspca_dev, 2);
+               if (err_code < 0)
+                       return err_code;
+               err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,
+                                        ARRAY_SIZE(cif_sensor1_init_data));
+       }
+       return err_code;
+}
+
+static int start_vga_cam(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       __u8 *data = gspca_dev->usb_buf;
+       int err_code;
+       static const __u8 startup_string[] =
+               {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, 0x00, 0x00,
+                0x00, 0x50, 0xc0};
+       /* What some of these mean is explained in start_cif_cam(), above */
+
+       memcpy(data, startup_string, 11);
+       if (!sd->sensor_type) {
+               data[5]  = 0x00;
+               data[10] = 0x91;
+       }
+       if (sd->sensor_type == 2) {
+               data[5]  = 0x00;
+               data[10] = 0x18;
+       }
+
+       switch (gspca_dev->width) {
+       case 160:
+               data[9] |= 0x0c;  /* reg 8, 4:1 scale down */
+               /* fall thru */
+       case 320:
+               data[9] |= 0x04;  /* reg 8, 2:1 scale down */
+               /* fall thru */
+       case 640:
+       default:
+               data[3] = 0x50;  /* reg 2, H size/8 */
+               data[4] = 0x78;  /* reg 3, V size/4 */
+               data[6] = 0x04;  /* reg 5, H start */
+               data[8] = 0x03;  /* reg 7, V start */
+               if (sd->sensor_type == 2) {
+                       data[6] = 2;
+                       data[8] = 1;
+               }
+               if (sd->do_lcd_stop)
+                       data[8] = 0x04;  /* Bayer tile shifted */
+               break;
+
+       case 176:
+               data[9] |= 0x04;  /* reg 8, 2:1 scale down */
+               /* fall thru */
+       case 352:
+               data[3] = 0x2c;  /* reg 2, H size */
+               data[4] = 0x48;  /* reg 3, V size */
+               data[6] = 0x94;  /* reg 5, H start */
+               data[8] = 0x63;  /* reg 7, V start */
+               if (sd->do_lcd_stop)
+                       data[8] = 0x64;  /* Bayer tile shifted */
+               break;
+       }
+
+       err_code = mr_write(gspca_dev, 11);
+       if (err_code < 0)
+               return err_code;
+
+       if (!sd->sensor_type) {
+               static const struct sensor_w_data vga_sensor0_init_data[] = {
+                       {0x01, 0x00, {0x0c, 0x00, 0x04}, 3},
+                       {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4},
+                       {0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4},
+                       {0x25, 0x00, {0x03, 0xa9, 0x80}, 3},
+                       {0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4},
+                       {0, 0, {0}, 0}
+               };
+               err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data,
+                                        ARRAY_SIZE(vga_sensor0_init_data));
+       } else if (sd->sensor_type == 1) {
+               static const struct sensor_w_data color_adj[] = {
+                       {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
+                               /* adjusted blue, green, red gain correct
+                                  too much blue from the Sakar Digital */
+                               0x05, 0x01, 0x04}, 8}
+               };
+
+               static const struct sensor_w_data color_no_adj[] = {
+                       {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
+                               /* default blue, green, red gain settings */
+                               0x07, 0x00, 0x01}, 8}
+               };
+
+               static const struct sensor_w_data vga_sensor1_init_data[] = {
+                       {0x11, 0x04, {0x01}, 1},
+                       {0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01,
+                       /* These settings may be better for some cameras */
+                       /* {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, */
+                               0x00, 0x0a}, 7},
+                       {0x11, 0x04, {0x01}, 1},
+                       {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6},
+                       {0x11, 0x04, {0x01}, 1},
+                       {0, 0, {0}, 0}
+               };
+
+               if (sd->adj_colors)
+                       err_code = sensor_write_regs(gspca_dev, color_adj,
+                                        ARRAY_SIZE(color_adj));
+               else
+                       err_code = sensor_write_regs(gspca_dev, color_no_adj,
+                                        ARRAY_SIZE(color_no_adj));
+
+               if (err_code < 0)
+                       return err_code;
+
+               err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data,
+                                        ARRAY_SIZE(vga_sensor1_init_data));
+       } else {        /* sensor type == 2 */
+               static const struct sensor_w_data vga_sensor2_init_data[] = {
+
+                       {0x01, 0x00, {0x48}, 1},
+                       {0x02, 0x00, {0x22}, 1},
+                       /* Reg 3 msb and 4 is lsb of the exposure setting*/
+                       {0x05, 0x00, {0x10}, 1},
+                       {0x06, 0x00, {0x00}, 1},
+                       {0x07, 0x00, {0x00}, 1},
+                       {0x08, 0x00, {0x00}, 1},
+                       {0x09, 0x00, {0x00}, 1},
+                       /* The following are used in the gain control
+                        * which is BTW completely borked in the OEM driver
+                        * The values for each color go from 0 to 0x7ff
+                        *{0x0a, 0x00, {0x01}, 1},  green1 gain msb
+                        *{0x0b, 0x00, {0x10}, 1},  green1 gain lsb
+                        *{0x0c, 0x00, {0x01}, 1},  red gain msb
+                        *{0x0d, 0x00, {0x10}, 1},  red gain lsb
+                        *{0x0e, 0x00, {0x01}, 1},  blue gain msb
+                        *{0x0f, 0x00, {0x10}, 1},  blue gain lsb
+                        *{0x10, 0x00, {0x01}, 1}, green2 gain msb
+                        *{0x11, 0x00, {0x10}, 1}, green2 gain lsb
+                        */
+                       {0x12, 0x00, {0x00}, 1},
+                       {0x13, 0x00, {0x04}, 1}, /* weird effect on colors */
+                       {0x14, 0x00, {0x00}, 1},
+                       {0x15, 0x00, {0x06}, 1},
+                       {0x16, 0x00, {0x01}, 1},
+                       {0x17, 0x00, {0xe2}, 1}, /* vertical alignment */
+                       {0x18, 0x00, {0x02}, 1},
+                       {0x19, 0x00, {0x82}, 1}, /* don't mess with */
+                       {0x1a, 0x00, {0x00}, 1},
+                       {0x1b, 0x00, {0x20}, 1},
+                       /* {0x1c, 0x00, {0x17}, 1}, contrast control */
+                       {0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */
+                       {0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */
+                       {0x1f, 0x00, {0x0c}, 1},
+                       {0x20, 0x00, {0x00}, 1},
+                       {0, 0, {0}, 0}
+               };
+               err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data,
+                                        ARRAY_SIZE(vga_sensor2_init_data));
+       }
+       return err_code;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int err_code;
+
+       sd->sof_read = 0;
+
+       /* Some of the VGA cameras require the memory pointer
+        * to be set to 0 again. We have been forced to start the
+        * stream in sd_config() to detect the hardware, and closed it.
+        * Thus, we need here to do a completely fresh and clean start. */
+       err_code = zero_the_pointer(gspca_dev);
+       if (err_code < 0)
+               return err_code;
+
+       err_code = stream_start(gspca_dev);
+       if (err_code < 0)
+               return err_code;
+
+       if (sd->cam_type == CAM_TYPE_CIF) {
+               err_code = start_cif_cam(gspca_dev);
+       } else {
+               err_code = start_vga_cam(gspca_dev);
+       }
+       if (err_code < 0)
+               return err_code;
+
+       return isoc_enable(gspca_dev);
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       stream_stop(gspca_dev);
+       /* Not all the cams need this, but even if not, probably a good idea */
+       zero_the_pointer(gspca_dev);
+       if (sd->do_lcd_stop)
+               lcd_stop(gspca_dev);
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 sign_reg = 7;  /* This reg and the next one used on CIF cams. */
+       u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */
+       static const u8 quick_clix_table[] =
+       /*        0  1  2   3  4  5  6  7  8  9  10  11  12  13  14  15 */
+               { 0, 4, 8, 12, 1, 2, 3, 5, 6, 9,  7, 10, 13, 11, 14, 15};
+       if (sd->cam_type == CAM_TYPE_VGA) {
+               sign_reg += 4;
+               value_reg += 4;
+       }
+
+       /* Note register 7 is also seen as 0x8x or 0xCx in some dumps */
+       if (val > 0) {
+               sensor_write1(gspca_dev, sign_reg, 0x00);
+       } else {
+               sensor_write1(gspca_dev, sign_reg, 0x01);
+               val = 257 - val;
+       }
+       /* Use lookup table for funky Argus QuickClix brightness */
+       if (sd->do_lcd_stop)
+               val = quick_clix_table[val];
+
+       sensor_write1(gspca_dev, value_reg, val);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 min_clockdiv)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int exposure = MR97310A_EXPOSURE_DEFAULT;
+       u8 buf[2];
+
+       if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) {
+               /* This cam does not like exposure settings < 300,
+                  so scale 0 - 4095 to 300 - 4095 */
+               exposure = (expo * 9267) / 10000 + 300;
+               sensor_write1(gspca_dev, 3, exposure >> 4);
+               sensor_write1(gspca_dev, 4, exposure & 0x0f);
+       } else if (sd->sensor_type == 2) {
+               exposure = expo;
+               exposure >>= 3;
+               sensor_write1(gspca_dev, 3, exposure >> 8);
+               sensor_write1(gspca_dev, 4, exposure & 0xff);
+       } else {
+               /* We have both a clock divider and an exposure register.
+                  We first calculate the clock divider, as that determines
+                  the maximum exposure and then we calculate the exposure
+                  register setting (which goes from 0 - 511).
+
+                  Note our 0 - 4095 exposure is mapped to 0 - 511
+                  milliseconds exposure time */
+               u8 clockdiv = (60 * expo + 7999) / 8000;
+
+               /* Limit framerate to not exceed usb bandwidth */
+               if (clockdiv < min_clockdiv && gspca_dev->width >= 320)
+                       clockdiv = min_clockdiv;
+               else if (clockdiv < 2)
+                       clockdiv = 2;
+
+               if (sd->cam_type == CAM_TYPE_VGA && clockdiv < 4)
+                       clockdiv = 4;
+
+               /* Frame exposure time in ms = 1000 * clockdiv / 60 ->
+               exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */
+               exposure = (60 * 511 * expo) / (8000 * clockdiv);
+               if (exposure > 511)
+                       exposure = 511;
+
+               /* exposure register value is reversed! */
+               exposure = 511 - exposure;
+
+               buf[0] = exposure & 0xff;
+               buf[1] = exposure >> 8;
+               sensor_write_reg(gspca_dev, 0x0e, 0, buf, 2);
+               sensor_write1(gspca_dev, 0x02, clockdiv);
+       }
+}
+
+static void setgain(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 gainreg;
+
+       if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1)
+               sensor_write1(gspca_dev, 0x0e, val);
+       else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2)
+               for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) {
+                       sensor_write1(gspca_dev, gainreg, val >> 8);
+                       sensor_write1(gspca_dev, gainreg + 1, val & 0xff);
+               }
+       else
+               sensor_write1(gspca_dev, 0x10, val);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
+{
+       sensor_write1(gspca_dev, 0x1c, val);
+}
+
+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_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_EXPOSURE:
+               setexposure(gspca_dev, sd->exposure->val,
+                           sd->min_clockdiv ? sd->min_clockdiv->val : 0);
+               break;
+       case V4L2_CID_GAIN:
+               setgain(gspca_dev, ctrl->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;
+       static const struct v4l2_ctrl_config clockdiv = {
+               .ops = &sd_ctrl_ops,
+               .id = MR97310A_CID_CLOCKDIV,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Minimum Clock Divider",
+               .min = MR97310A_MIN_CLOCKDIV_MIN,
+               .max = MR97310A_MIN_CLOCKDIV_MAX,
+               .step = 1,
+               .def = MR97310A_MIN_CLOCKDIV_DEFAULT,
+       };
+       bool has_brightness = false;
+       bool has_argus_brightness = false;
+       bool has_contrast = false;
+       bool has_gain = false;
+       bool has_cs_gain = false;
+       bool has_exposure = false;
+       bool has_clockdiv = false;
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 4);
+
+       /* Setup controls depending on camera type */
+       if (sd->cam_type == CAM_TYPE_CIF) {
+               /* No brightness for sensor_type 0 */
+               if (sd->sensor_type == 0)
+                       has_exposure = has_gain = has_clockdiv = true;
+               else
+                       has_exposure = has_gain = has_brightness = true;
+       } else {
+               /* All controls need to be disabled if VGA sensor_type is 0 */
+               if (sd->sensor_type == 0)
+                       ; /* no controls! */
+               else if (sd->sensor_type == 2)
+                       has_exposure = has_cs_gain = has_contrast = true;
+               else if (sd->do_lcd_stop)
+                       has_exposure = has_gain = has_argus_brightness =
+                               has_clockdiv = true;
+               else
+                       has_exposure = has_gain = has_brightness =
+                               has_clockdiv = true;
+       }
+
+       /* Separate brightness control description for Argus QuickClix as it has
+        * different limits from the other mr97310a cameras, and separate gain
+        * control for Sakar CyberPix camera. */
+       /*
+        * This control is disabled for CIF type 1 and VGA type 0 cameras.
+        * It does not quite act linearly for the Argus QuickClix camera,
+        * but it does control brightness. The values are 0 - 15 only, and
+        * the table above makes them act consecutively.
+        */
+       if (has_brightness)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, -254, 255, 1,
+                       MR97310A_BRIGHTNESS_DEFAULT);
+       else if (has_argus_brightness)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 15, 1,
+                       MR97310A_BRIGHTNESS_DEFAULT);
+       if (has_contrast)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, MR97310A_CONTRAST_MIN,
+                       MR97310A_CONTRAST_MAX, 1, MR97310A_CONTRAST_DEFAULT);
+       if (has_gain)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAIN, MR97310A_GAIN_MIN, MR97310A_GAIN_MAX,
+                       1, MR97310A_GAIN_DEFAULT);
+       else if (has_cs_gain)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAIN,
+                       MR97310A_CS_GAIN_MIN, MR97310A_CS_GAIN_MAX,
+                       1, MR97310A_CS_GAIN_DEFAULT);
+       if (has_exposure)
+               sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_EXPOSURE, MR97310A_EXPOSURE_MIN,
+                       MR97310A_EXPOSURE_MAX, 1, MR97310A_EXPOSURE_DEFAULT);
+       if (has_clockdiv)
+               sd->min_clockdiv = v4l2_ctrl_new_custom(hdl, &clockdiv, NULL);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       if (has_exposure && has_clockdiv)
+               v4l2_ctrl_cluster(2, &sd->exposure);
+       return 0;
+}
+
+/* Include pac common sof detection functions */
+#include "pac_common.h"
+
+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;
+       unsigned char *sof;
+
+       sof = pac_find_sof(&sd->sof_read, data, len);
+       if (sof) {
+               int n;
+
+               /* finish decoding current frame */
+               n = sof - data;
+               if (n > sizeof pac_sof_marker)
+                       n -= sizeof pac_sof_marker;
+               else
+                       n = 0;
+               gspca_frame_add(gspca_dev, LAST_PACKET,
+                                       data, n);
+               /* Start next frame. */
+               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                       pac_sof_marker, sizeof pac_sof_marker);
+               len -= sof - data;
+               data = sof;
+       }
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+/* 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,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x08ca, 0x0110)},   /* Trust Spyc@m 100 */
+       {USB_DEVICE(0x08ca, 0x0111)},   /* Aiptek Pencam VGA+ */
+       {USB_DEVICE(0x093a, 0x010f)},   /* All other known MR97310A VGA cams */
+       {USB_DEVICE(0x093a, 0x010e)},   /* All known MR97310A CIF cams */
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/nw80x.c b/drivers/media/usb/gspca/nw80x.c
new file mode 100644 (file)
index 0000000..44c9964
--- /dev/null
@@ -0,0 +1,2110 @@
+/*
+ * DivIO nw80x subdriver
+ *
+ * Copyright (C) 2011 Jean-François Moine (http://moinejf.free.fr)
+ * Copyright (C) 2003 Sylvain Munaut <tnt@246tNt.com>
+ *                     Kjell Claesson <keyson@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "nw80x"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
+MODULE_DESCRIPTION("NW80x USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+static int webcam;
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       u32 ae_res;
+       s8 ag_cnt;
+#define AG_CNT_START 13
+       u8 exp_too_low_cnt;
+       u8 exp_too_high_cnt;
+
+       u8 bridge;
+       u8 webcam;
+};
+
+enum bridges {
+       BRIDGE_NW800,   /* and et31x110 */
+       BRIDGE_NW801,
+       BRIDGE_NW802,
+};
+enum webcams {
+       Generic800,
+       SpaceCam,       /* Trust 120 SpaceCam */
+       SpaceCam2,      /* other Trust 120 SpaceCam */
+       Cvideopro,      /* Conceptronic Video Pro */
+       Dlink350c,
+       DS3303u,
+       Kr651us,
+       Kritter,
+       Mustek300,
+       Proscope,
+       Twinkle,
+       DvcV6,
+       P35u,
+       Generic802,
+       NWEBCAMS        /* number of webcams */
+};
+
+static const u8 webcam_chip[NWEBCAMS] = {
+       [Generic800]    = BRIDGE_NW800, /* 06a5:0000
+                                        * Typhoon Webcam 100 USB */
+
+       [SpaceCam]      = BRIDGE_NW800, /* 06a5:d800
+                               * Trust SpaceCam120 or SpaceCam100 PORTABLE */
+
+       [SpaceCam2]     = BRIDGE_NW800, /* 06a5:d800 - pas106
+                       * other Trust SpaceCam120 or SpaceCam100 PORTABLE */
+
+       [Cvideopro]     = BRIDGE_NW802, /* 06a5:d001
+                       * Conceptronic Video Pro 'CVIDEOPRO USB Webcam CCD' */
+
+       [Dlink350c]     = BRIDGE_NW802, /* 06a5:d001
+                                        * D-Link NetQam Pro 250plus */
+
+       [DS3303u]       = BRIDGE_NW801, /* 06a5:d001
+                               * Plustek Opticam 500U or ProLink DS3303u */
+
+       [Kr651us]       = BRIDGE_NW802, /* 06a5:d001
+                                        * Panasonic GP-KR651US */
+
+       [Kritter]       = BRIDGE_NW802, /* 06a5:d001
+                                        * iRez Kritter cam */
+
+       [Mustek300]     = BRIDGE_NW802, /* 055f:d001
+                                        * Mustek Wcam 300 mini */
+
+       [Proscope]      = BRIDGE_NW802, /* 06a5:d001
+                                        * Scalar USB Microscope (ProScope) */
+
+       [Twinkle]       = BRIDGE_NW800, /* 06a5:d800 - hv7121b? (seems pas106)
+                                        * Divio Chicony TwinkleCam
+                                        * DSB-C110 */
+
+       [DvcV6]         = BRIDGE_NW802, /* 0502:d001
+                                        * DVC V6 */
+
+       [P35u]          = BRIDGE_NW801, /* 052b:d001, 06a5:d001 and 06be:d001
+                                        * EZCam Pro p35u */
+
+       [Generic802]    = BRIDGE_NW802,
+};
+/*
+ * other webcams:
+ *     - nw801 046d:d001
+ *             Logitech QuickCam Pro (dark focus ring)
+ *     - nw801 0728:d001
+ *             AVerMedia Camguard
+ *     - nw??? 06a5:d001
+ *             D-Link NetQam Pro 250plus
+ *     - nw800 065a:d800
+ *             Showcam NGS webcam
+ *     - nw??? ????:????
+ *             Sceptre svc300
+ */
+
+/*
+ * registers
+ *    nw800/et31x110     nw801           nw802
+ *     0000..009e      0000..00a1      0000..009e
+ *     0200..0211         id              id
+ *     0300..0302         id              id
+ *     0400..0406        (inex)        0400..0406
+ *     0500..0505      0500..0506        (inex)
+ *     0600..061a      0600..0601      0600..0601
+ *     0800..0814         id              id
+ *     1000..109c      1000..10a1      1000..109a
+ */
+
+/* resolutions
+ *     nw800: 320x240, 352x288
+ *     nw801/802: 320x240, 640x480
+ */
+static const struct v4l2_pix_format cif_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 4 / 8,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+       {352, 288, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 4 / 8,
+               .colorspace = V4L2_COLORSPACE_JPEG}
+};
+static const struct v4l2_pix_format vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 4 / 8,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+       {640, 480, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+};
+
+/*
+ * The sequences below contain:
+ *     - 1st and 2nd bytes: either
+ *             - register number (BE)
+ *             - I2C0 + i2c address
+ *     - 3rd byte: data length (=0 for end of sequence)
+ *     - n bytes: data
+ */
+#define I2C0 0xff
+
+static const u8 nw800_init[] = {
+       0x04, 0x05, 0x01, 0x61,
+       0x04, 0x04, 0x01, 0x01,
+       0x04, 0x06, 0x01, 0x04,
+       0x04, 0x04, 0x03, 0x00, 0x00, 0x00,
+       0x05, 0x05, 0x01, 0x00,
+       0, 0, 0
+};
+static const u8 nw800_start[] = {
+       0x04, 0x06, 0x01, 0xc0,
+       0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
+                         0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
+                         0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+       0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
+                         0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
+                         0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
+       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0xc0,
+       0x05, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x20,
+       0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+       0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
+                         0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
+                         0x01, 0x60, 0x01, 0x00, 0x00,
+
+       0x04, 0x04, 0x01, 0xff,
+       0x04, 0x06, 0x01, 0xc4,
+
+       0x04, 0x06, 0x01, 0xc0,
+       0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
+                         0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
+                         0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+       0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
+                         0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
+                         0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
+       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0xc0,
+       0x05, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x20,
+       0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+       0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
+                         0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
+                         0x01, 0x60, 0x01, 0x00, 0x00,
+
+       0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
+                         0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
+                         0x40,
+       0x00, 0x80, 0x01, 0xa0,
+       0x10, 0x1a, 0x01, 0x00,
+       0x00, 0x91, 0x02, 0x6c, 0x01,
+       0x00, 0x03, 0x02, 0xc8, 0x01,
+       0x10, 0x1a, 0x01, 0x00,
+       0x10, 0x00, 0x01, 0x83,
+       0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
+                         0x20, 0x01, 0x60, 0x01,
+       0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+       0x10, 0x1b, 0x02, 0x69, 0x00,
+       0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+       0x05, 0x02, 0x01, 0x02,
+       0x06, 0x00, 0x02, 0x04, 0xd9,
+       0x05, 0x05, 0x01, 0x20,
+       0x05, 0x05, 0x01, 0x21,
+       0x10, 0x0e, 0x01, 0x08,
+       0x10, 0x41, 0x11, 0x00, 0x08, 0x21, 0x3d, 0x52, 0x63, 0x75, 0x83,
+                         0x91, 0x9e, 0xaa, 0xb6, 0xc1, 0xcc, 0xd6, 0xe0,
+                         0xea,
+       0x10, 0x03, 0x01, 0x00,
+       0x10, 0x0f, 0x02, 0x13, 0x13,
+       0x10, 0x03, 0x01, 0x14,
+       0x10, 0x41, 0x11, 0x00, 0x08, 0x21, 0x3d, 0x52, 0x63, 0x75, 0x83,
+                         0x91, 0x9e, 0xaa, 0xb6, 0xc1, 0xcc, 0xd6, 0xe0,
+                         0xea,
+       0x10, 0x0b, 0x01, 0x14,
+       0x10, 0x0d, 0x01, 0x20,
+       0x10, 0x0c, 0x01, 0x34,
+       0x04, 0x06, 0x01, 0xc3,
+       0x04, 0x04, 0x01, 0x00,
+       0x05, 0x02, 0x01, 0x02,
+       0x06, 0x00, 0x02, 0x00, 0x48,
+       0x05, 0x05, 0x01, 0x20,
+       0x05, 0x05, 0x01, 0x21,
+       0, 0, 0
+};
+
+/* 06a5:d001 - nw801 - Panasonic
+ *             P35u */
+static const u8 nw801_start_1[] = {
+       0x05, 0x06, 0x01, 0x04,
+       0x00, 0x00, 0x40, 0x0e, 0x00, 0x00, 0xf9, 0x02, 0x11, 0x00, 0x0e,
+                         0x01, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
+                         0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+       0x00, 0x80, 0x22, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x08, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x69, 0xa8, 0x1f, 0x00,
+                         0x0d, 0x02, 0x07, 0x00, 0x01, 0x00, 0x19, 0x00,
+                         0xf2, 0x00, 0x18, 0x06, 0x10, 0x06, 0x10, 0x00,
+                         0x36, 0x00,
+       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
+       0x05, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x06, 0x00, 0x02, 0x09, 0x99,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0x22, 0x02, 0x80, 0x00, 0x1e, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x0a, 0x15, 0x08, 0x08, 0x0a,
+                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x01, 0x35, 0xfd, 0x07, 0x3d, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x14, 0x02,
+                         0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+                         0x40, 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x06,
+                         0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, 0xf7,
+       0x10, 0x40, 0x40, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, 0x80,
+                         0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, 0xa4,
+                         0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, 0xcf,
+                         0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64,
+                         0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2,
+                         0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+       0x10, 0x80, 0x22, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x82, 0x02,
+                         0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, 0x01,
+                         0xf0, 0x00,
+       0, 0, 0,
+};
+static const u8 nw801_start_qvga[] = {
+       0x02, 0x00, 0x10, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
+                         0x00, 0x78, 0x18, 0x0b, 0x06, 0xa2, 0x86, 0x78,
+       0x02, 0x0f, 0x01, 0x6b,
+       0x10, 0x1a, 0x01, 0x15,
+       0x00, 0x00, 0x01, 0x1e,
+       0x10, 0x00, 0x01, 0x2f,
+       0x10, 0x8c, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+       0x10, 0x11, 0x08, 0x29, 0x00, 0x18, 0x01, 0x1f, 0x00, 0xd2, 0x00,
+                                                       /* AE window */
+       0, 0, 0,
+};
+static const u8 nw801_start_vga[] = {
+       0x02, 0x00, 0x10, 0x78, 0xa0, 0x97, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xf0,
+       0x02, 0x0f, 0x01, 0xd5,
+       0x10, 0x1a, 0x01, 0x15,
+       0x00, 0x00, 0x01, 0x0e,
+       0x10, 0x00, 0x01, 0x22,
+       0x10, 0x8c, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
+       0x10, 0x11, 0x08, 0x51, 0x00, 0x30, 0x02, 0x3d, 0x00, 0xa4, 0x01,
+       0, 0, 0,
+};
+static const u8 nw801_start_2[] = {
+       0x10, 0x04, 0x01, 0x1a,
+       0x10, 0x19, 0x01, 0x09,                         /* clock */
+       0x10, 0x24, 0x06, 0xc0, 0x00, 0x3f, 0x02, 0x00, 0x01,
+                                                        /* .. gain .. */
+       0x00, 0x03, 0x02, 0x92, 0x03,
+       0x00, 0x1d, 0x04, 0xf2, 0x00, 0x24, 0x07,
+       0x00, 0x7b, 0x01, 0xcf,
+       0x10, 0x94, 0x01, 0x07,
+       0x05, 0x05, 0x01, 0x01,
+       0x05, 0x04, 0x01, 0x01,
+       0x10, 0x0e, 0x01, 0x08,
+       0x10, 0x48, 0x11, 0x00, 0x37, 0x55, 0x6b, 0x7d, 0x8d, 0x9b, 0xa8,
+                         0xb4, 0xbf, 0xca, 0xd4, 0xdd, 0xe6, 0xef, 0xf0,
+                         0xf0,
+       0x10, 0x03, 0x01, 0x00,
+       0x10, 0x0f, 0x02, 0x0c, 0x0c,
+       0x10, 0x03, 0x01, 0x08,
+       0x10, 0x48, 0x11, 0x00, 0x37, 0x55, 0x6b, 0x7d, 0x8d, 0x9b, 0xa8,
+                         0xb4, 0xbf, 0xca, 0xd4, 0xdd, 0xe6, 0xef, 0xf0,
+                         0xf0,
+       0x10, 0x0b, 0x01, 0x0b,
+       0x10, 0x0d, 0x01, 0x0b,
+       0x10, 0x0c, 0x01, 0x1f,
+       0x05, 0x06, 0x01, 0x03,
+       0, 0, 0
+};
+
+/* nw802 (sharp IR3Y38M?) */
+static const u8 nw802_start[] = {
+       0x04, 0x06, 0x01, 0x04,
+       0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0xf9, 0x02, 0x10, 0x00, 0x4d,
+                         0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
+                         0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+       0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+                         0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
+                         0x00, 0x10, 0x06, 0x08, 0x00, 0x18, 0x00,
+       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
+       0x06, 0x00, 0x02, 0x09, 0x99,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x1d, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x49, 0x13, 0xff, 0x01, 0xc0, 0x00, 0x14,
+                         0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
+                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x05, 0x82,
+                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+                         0x01, 0xf0, 0x00,
+       0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
+                         0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
+                         0x40,
+       0x10, 0x1a, 0x01, 0x00,
+       0x10, 0x00, 0x01, 0xad,
+       0x00, 0x00, 0x01, 0x08,
+       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+       0x10, 0x1b, 0x02, 0x00, 0x00,
+       0x10, 0x11, 0x08, 0x51, 0x00, 0xf0, 0x00, 0x3d, 0x00, 0xb4, 0x00,
+       0x10, 0x1d, 0x08, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
+       0x10, 0x0e, 0x01, 0x27,
+       0x10, 0x41, 0x11, 0x00, 0x0e, 0x35, 0x4f, 0x62, 0x71, 0x7f, 0x8b,
+                         0x96, 0xa0, 0xa9, 0xb2, 0xbb, 0xc3, 0xca, 0xd2,
+                         0xd8,
+       0x10, 0x03, 0x01, 0x00,
+       0x10, 0x0f, 0x02, 0x14, 0x14,
+       0x10, 0x03, 0x01, 0x0c,
+       0x10, 0x41, 0x11, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64, 0x74,
+                         0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2, 0xf1,
+                         0xff,
+/*                       0x00, 0x0e, 0x35, 0x4f, 0x62, 0x71, 0x7f, 0x8b,
+ *                       0x96, 0xa0, 0xa9, 0xb2, 0xbb, 0xc3, 0xca, 0xd2,
+ *                       0xd8, */
+       0x10, 0x0b, 0x01, 0x10,
+       0x10, 0x0d, 0x01, 0x11,
+       0x10, 0x0c, 0x01, 0x1c,
+       0x04, 0x06, 0x01, 0x03,
+       0x04, 0x04, 0x01, 0x00,
+       0, 0, 0
+};
+/* et31x110 - Trust 120 SpaceCam */
+static const u8 spacecam_init[] = {
+       0x04, 0x05, 0x01, 0x01,
+       0x04, 0x04, 0x01, 0x01,
+       0x04, 0x06, 0x01, 0x04,
+       0x04, 0x04, 0x03, 0x00, 0x00, 0x00,
+       0x05, 0x05, 0x01, 0x00,
+       0, 0, 0
+};
+static const u8 spacecam_start[] = {
+       0x04, 0x06, 0x01, 0x44,
+       0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
+                         0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
+                         0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+       0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
+                         0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
+                         0x00, 0x4b, 0x00, 0x7c, 0x00, 0x80, 0x00,
+       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+       0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
+                         0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
+                         0x01, 0x60, 0x01, 0x00, 0x00,
+       0x04, 0x06, 0x01, 0xc0,
+       0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+       0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
+                         0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
+                         0x40,
+       0x00, 0x80, 0x01, 0xa0,
+       0x10, 0x1a, 0x01, 0x00,
+       0x00, 0x91, 0x02, 0x32, 0x01,
+       0x00, 0x03, 0x02, 0x08, 0x02,
+       0x10, 0x00, 0x01, 0x83,
+       0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
+                         0x20, 0x01, 0x60, 0x01,
+       0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+       0x10, 0x0e, 0x01, 0x08,
+       0x10, 0x41, 0x11, 0x00, 0x64, 0x99, 0xc0, 0xe2, 0xf9, 0xf9, 0xf9,
+                         0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+                         0xf9,
+       0x10, 0x03, 0x01, 0x00,
+       0x10, 0x0f, 0x02, 0x13, 0x13,
+       0x10, 0x03, 0x01, 0x06,
+       0x10, 0x41, 0x11, 0x00, 0x64, 0x99, 0xc0, 0xe2, 0xf9, 0xf9, 0xf9,
+                         0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+                         0xf9,
+       0x10, 0x0b, 0x01, 0x08,
+       0x10, 0x0d, 0x01, 0x10,
+       0x10, 0x0c, 0x01, 0x1f,
+       0x04, 0x06, 0x01, 0xc3,
+       0x04, 0x05, 0x01, 0x40,
+       0x04, 0x04, 0x01, 0x40,
+       0, 0, 0
+};
+/* et31x110 - pas106 - other Trust SpaceCam120 */
+static const u8 spacecam2_start[] = {
+       0x04, 0x06, 0x01, 0x44,
+       0x04, 0x06, 0x01, 0x00,
+       0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f,
+                         0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc,
+                         0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+       0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03,
+                         0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
+                         0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
+       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00,
+       0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+       0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62,
+                         0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
+                         0x01, 0x60, 0x01, 0x00, 0x00,
+       0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+       0x04, 0x04, 0x01, 0x40,
+       0x04, 0x04, 0x01, 0x00,
+       I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x05,
+                         0x00, 0x00, 0x05, 0x05,
+       I2C0, 0x40, 0x02, 0x11, 0x06,
+       I2C0, 0x40, 0x02, 0x14, 0x00,
+       I2C0, 0x40, 0x02, 0x13, 0x01,           /* i2c end */
+       0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
+                         0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
+                         0x40,
+       I2C0, 0x40, 0x02, 0x02, 0x0c,           /* pixel clock */
+       I2C0, 0x40, 0x02, 0x0f, 0x00,
+       I2C0, 0x40, 0x02, 0x13, 0x01,           /* i2c end */
+       0x10, 0x00, 0x01, 0x01,
+       0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
+                         0x20, 0x01, 0x60, 0x01,
+       I2C0, 0x40, 0x02, 0x05, 0x0f,           /* exposure */
+       I2C0, 0x40, 0x02, 0x13, 0x01,           /* i2c end */
+       I2C0, 0x40, 0x07, 0x09, 0x0b, 0x0f, 0x05, 0x05, 0x0f, 0x00,
+                                               /* gains */
+       I2C0, 0x40, 0x03, 0x12, 0x04, 0x01,
+       0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+       0x10, 0x0e, 0x01, 0x08,
+       0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
+                         0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
+                         0xf9,
+       0x10, 0x03, 0x01, 0x00,
+       0x10, 0x0f, 0x02, 0x13, 0x13,
+       0x10, 0x03, 0x01, 0x06,
+       0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
+                         0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
+                         0xf9,
+       0x10, 0x0b, 0x01, 0x11,
+       0x10, 0x0d, 0x01, 0x10,
+       0x10, 0x0c, 0x01, 0x14,
+       0x04, 0x06, 0x01, 0x03,
+       0x04, 0x05, 0x01, 0x61,
+       0x04, 0x04, 0x01, 0x00,
+       0, 0, 0
+};
+
+/* nw802 - Conceptronic Video Pro */
+static const u8 cvideopro_start[] = {
+       0x04, 0x06, 0x01, 0x04,
+       0x00, 0x00, 0x40, 0x54, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x4c,
+                         0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
+                         0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
+                         0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
+                         0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
+       0x00, 0x80, 0x1f, 0x98, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
+                         0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+                         0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
+                         0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
+       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
+       0x06, 0x00, 0x02, 0x09, 0x99,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
+                         0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
+                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+                         0x01, 0xf0, 0x00,
+       0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00,
+                         0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
+                         0x40,
+       0x10, 0x1a, 0x01, 0x03,
+       0x10, 0x00, 0x01, 0xac,
+       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+       0x10, 0x1b, 0x02, 0x3b, 0x01,
+       0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
+       0x10, 0x1f, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
+       0x10, 0x1d, 0x02, 0x40, 0x06,
+       0x10, 0x0e, 0x01, 0x08,
+       0x10, 0x41, 0x11, 0x00, 0x0f, 0x46, 0x62, 0x76, 0x86, 0x94, 0xa0,
+                         0xab, 0xb6, 0xbf, 0xc8, 0xcf, 0xd7, 0xdc, 0xdc,
+                         0xdc,
+       0x10, 0x03, 0x01, 0x00,
+       0x10, 0x0f, 0x02, 0x12, 0x12,
+       0x10, 0x03, 0x01, 0x0c,
+       0x10, 0x41, 0x11, 0x00, 0x0f, 0x46, 0x62, 0x76, 0x86, 0x94, 0xa0,
+                         0xab, 0xb6, 0xbf, 0xc8, 0xcf, 0xd7, 0xdc, 0xdc,
+                         0xdc,
+       0x10, 0x0b, 0x01, 0x09,
+       0x10, 0x0d, 0x01, 0x10,
+       0x10, 0x0c, 0x01, 0x2f,
+       0x04, 0x06, 0x01, 0x03,
+       0x04, 0x04, 0x01, 0x00,
+       0, 0, 0
+};
+
+/* nw802 - D-link dru-350c cam */
+static const u8 dlink_start[] = {
+       0x04, 0x06, 0x01, 0x04,
+       0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x92, 0x03, 0x10, 0x00, 0x4d,
+                         0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
+                         0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+       0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+                         0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
+                         0x00, 0x10, 0x06, 0x10, 0x00, 0x36, 0x00,
+       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
+       0x06, 0x00, 0x02, 0x09, 0x99,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x49, 0x13, 0x00, 0x00, 0xc0, 0x00, 0x14,
+                         0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
+                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x01, 0x82,
+                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+                         0x01, 0xf0, 0x00,
+       0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
+                         0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
+                         0x40,
+       0x10, 0x1a, 0x01, 0x00,
+       0x10, 0x00, 0x01, 0xad,
+       0x00, 0x00, 0x01, 0x08,
+       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+       0x10, 0x1b, 0x02, 0x00, 0x00,
+       0x10, 0x11, 0x08, 0x51, 0x00, 0xf0, 0x00, 0x3d, 0x00, 0xb4, 0x00,
+       0x10, 0x1d, 0x08, 0x40, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
+       0x10, 0x0e, 0x01, 0x20,
+       0x10, 0x41, 0x11, 0x00, 0x07, 0x1e, 0x38, 0x4d, 0x60, 0x70, 0x7f,
+                         0x8e, 0x9b, 0xa8, 0xb4, 0xbf, 0xca, 0xd5, 0xdf,
+                         0xea,
+       0x10, 0x03, 0x01, 0x00,
+       0x10, 0x0f, 0x02, 0x11, 0x11,
+       0x10, 0x03, 0x01, 0x10,
+       0x10, 0x41, 0x11, 0x00, 0x07, 0x1e, 0x38, 0x4d, 0x60, 0x70, 0x7f,
+                         0x8e, 0x9b, 0xa8, 0xb4, 0xbf, 0xca, 0xd5, 0xdf,
+                         0xea,
+       0x10, 0x0b, 0x01, 0x19,
+       0x10, 0x0d, 0x01, 0x10,
+       0x10, 0x0c, 0x01, 0x1e,
+       0x04, 0x06, 0x01, 0x03,
+       0x04, 0x04, 0x01, 0x00,
+       0, 0, 0
+};
+
+/* 06a5:d001 - nw801 - Sony
+ *             Plustek Opticam 500U or ProLink DS3303u (Hitachi HD49322BF) */
+/*fixme: 320x240 only*/
+static const u8 ds3303_start[] = {
+       0x05, 0x06, 0x01, 0x04,
+       0x00, 0x00, 0x40, 0x16, 0x00, 0x00, 0xf9, 0x02, 0x11, 0x00, 0x0e,
+                         0x01, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
+                         0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+       0x00, 0x80, 0x22, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x08, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0xa9, 0xa8, 0x1f, 0x00,
+                         0x0d, 0x02, 0x07, 0x00, 0x01, 0x00, 0x19, 0x00,
+                         0xf2, 0x00, 0x18, 0x06, 0x10, 0x06, 0x10, 0x00,
+                         0x36, 0x00,
+       0x02, 0x00, 0x12, 0x03, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0x50,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+       0x05, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
+       0x06, 0x00, 0x02, 0x09, 0x99,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0x2f, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x10, 0x1f, 0x10, 0x08, 0x0a,
+                         0x0a, 0x51, 0x00, 0xf1, 0x00, 0x3c, 0x00, 0xb4,
+                         0x00, 0x01, 0x15, 0xfd, 0x07, 0x3d, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x8c, 0x04, 0x01, 0x20,
+                         0x02, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00,
+                         0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x03,
+                         0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, 0xf7,
+       0x10, 0x40, 0x40, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, 0x80,
+                         0x00, 0x2d, 0x46, 0x58, 0x67, 0x74, 0x7f, 0x88,
+                         0x94, 0x9d, 0xa6, 0xae, 0xb5, 0xbd, 0xc4, 0xcb,
+                         0xd1, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64,
+                         0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2,
+                         0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+       0x10, 0x80, 0x22, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x3f, 0x01,
+                         0x00, 0x00, 0xef, 0x00, 0x02, 0x0a, 0x82, 0x02,
+                         0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, 0x01,
+                         0xf0, 0x00,
+
+       0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
+                         0x00, 0x78, 0x3f, 0x3f, 0x00, 0xf2, 0x8f, 0x81,
+                         0x40,
+       0x10, 0x1a, 0x01, 0x15,
+       0x10, 0x00, 0x01, 0x2f,
+       0x10, 0x8c, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+       0x10, 0x1b, 0x02, 0x00, 0x00,
+       0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
+       0x10, 0x26, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
+       0x10, 0x24, 0x02, 0x40, 0x06,
+       0x10, 0x0e, 0x01, 0x08,
+       0x10, 0x48, 0x11, 0x00, 0x15, 0x40, 0x67, 0x84, 0x9d, 0xb2, 0xc6,
+                         0xd6, 0xe7, 0xf6, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+                         0xf9,
+       0x10, 0x03, 0x01, 0x00,
+       0x10, 0x0f, 0x02, 0x16, 0x16,
+       0x10, 0x03, 0x01, 0x0c,
+       0x10, 0x48, 0x11, 0x00, 0x15, 0x40, 0x67, 0x84, 0x9d, 0xb2, 0xc6,
+                         0xd6, 0xe7, 0xf6, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+                         0xf9,
+       0x10, 0x0b, 0x01, 0x26,
+       0x10, 0x0d, 0x01, 0x10,
+       0x10, 0x0c, 0x01, 0x1c,
+       0x05, 0x06, 0x01, 0x03,
+       0x05, 0x04, 0x01, 0x00,
+       0, 0, 0
+};
+
+/* 06a5:d001 - nw802 - Panasonic
+ *             GP-KR651US (Philips TDA8786) */
+static const u8 kr651_start_1[] = {
+       0x04, 0x06, 0x01, 0x04,
+       0x00, 0x00, 0x40, 0x44, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x48,
+                         0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
+                         0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
+                         0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
+                         0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
+       0x00, 0x80, 0x1f, 0x18, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
+                         0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+                         0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
+                         0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
+       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x02, 0x00, 0x00,
+       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
+       0x06, 0x00, 0x02, 0x09, 0x99,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
+                         0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
+                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+                         0x01, 0xf0, 0x00,
+       0, 0, 0
+};
+static const u8 kr651_start_qvga[] = {
+       0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
+                         0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
+                         0x40,
+       0x10, 0x1a, 0x01, 0x03,
+       0x10, 0x00, 0x01, 0xac,
+       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+       0x10, 0x1b, 0x02, 0x00, 0x00,
+       0x10, 0x11, 0x08, 0x29, 0x00, 0x18, 0x01, 0x1f, 0x00, 0xd2, 0x00,
+       0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
+       0x10, 0x1d, 0x02, 0x28, 0x01,
+       0, 0, 0
+};
+static const u8 kr651_start_vga[] = {
+       0x02, 0x00, 0x11, 0x78, 0xa0, 0x8c, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x30, 0x03, 0x01, 0x82, 0x82, 0x98,
+                         0x80,
+       0x10, 0x1a, 0x01, 0x03,
+       0x10, 0x00, 0x01, 0xa0,
+       0x10, 0x85, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
+       0x10, 0x1b, 0x02, 0x00, 0x00,
+       0x10, 0x11, 0x08, 0x51, 0x00, 0x30, 0x02, 0x3d, 0x00, 0xa4, 0x01,
+       0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
+       0x10, 0x1d, 0x02, 0x68, 0x00,
+};
+static const u8 kr651_start_2[] = {
+       0x10, 0x0e, 0x01, 0x08,
+       0x10, 0x41, 0x11, 0x00, 0x11, 0x3c, 0x5c, 0x74, 0x88, 0x99, 0xa8,
+                         0xb7, 0xc4, 0xd0, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
+                         0xdc,
+       0x10, 0x03, 0x01, 0x00,
+       0x10, 0x0f, 0x02, 0x0c, 0x0c,
+       0x10, 0x03, 0x01, 0x0c,
+       0x10, 0x41, 0x11, 0x00, 0x11, 0x3c, 0x5c, 0x74, 0x88, 0x99, 0xa8,
+                         0xb7, 0xc4, 0xd0, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
+                         0xdc,
+       0x10, 0x0b, 0x01, 0x10,
+       0x10, 0x0d, 0x01, 0x10,
+       0x10, 0x0c, 0x01, 0x2d,
+       0x04, 0x06, 0x01, 0x03,
+       0x04, 0x04, 0x01, 0x00,
+       0, 0, 0
+};
+
+/* nw802 - iRez Kritter cam */
+static const u8 kritter_start[] = {
+       0x04, 0x06, 0x01, 0x06,
+       0x00, 0x00, 0x40, 0x44, 0x96, 0x98, 0x94, 0x03, 0x18, 0x00, 0x48,
+                         0x0f, 0x1e, 0x00, 0x0c, 0x02, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x0b, 0x00, 0x1b, 0x00, 0x0a, 0x01, 0x28,
+                         0x07, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
+                         0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
+                         0x00, 0x5d, 0x00, 0x0e, 0x00, 0x7e, 0x00, 0x30,
+       0x00, 0x80, 0x1f, 0x18, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
+                         0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+                         0x00, 0x0b, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
+                         0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
+       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x02, 0x00, 0x00,
+       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
+       0x06, 0x00, 0x02, 0x09, 0x99,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
+                         0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x82,
+                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+                         0x01, 0xf0, 0x00,
+       0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00,
+                         0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
+                         0x40,
+       0x10, 0x1a, 0x01, 0x03,
+       0x10, 0x00, 0x01, 0xaf,
+       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+       0x10, 0x1b, 0x02, 0x3b, 0x01,
+       0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
+       0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
+       0x10, 0x1d, 0x02, 0x00, 0x00,
+       0x10, 0x0e, 0x01, 0x08,
+       0x10, 0x41, 0x11, 0x00, 0x0d, 0x36, 0x4e, 0x60, 0x6f, 0x7b, 0x86,
+                         0x90, 0x98, 0xa1, 0xa9, 0xb1, 0xb7, 0xbe, 0xc4,
+                         0xcb,
+       0x10, 0x03, 0x01, 0x00,
+       0x10, 0x0f, 0x02, 0x0d, 0x0d,
+       0x10, 0x03, 0x01, 0x02,
+       0x10, 0x41, 0x11, 0x00, 0x0d, 0x36, 0x4e, 0x60, 0x6f, 0x7b, 0x86,
+                         0x90, 0x98, 0xa1, 0xa9, 0xb1, 0xb7, 0xbe, 0xc4,
+                         0xcb,
+       0x10, 0x0b, 0x01, 0x17,
+       0x10, 0x0d, 0x01, 0x10,
+       0x10, 0x0c, 0x01, 0x1e,
+       0x04, 0x06, 0x01, 0x03,
+       0x04, 0x04, 0x01, 0x00,
+       0, 0, 0
+};
+
+/* nw802 - Mustek Wcam 300 mini */
+static const u8 mustek_start[] = {
+       0x04, 0x06, 0x01, 0x04,
+       0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x92, 0x03, 0x10, 0x00, 0x4d,
+                         0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
+                         0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+       0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+                         0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
+                         0x00, 0x10, 0x06, 0xfc, 0x05, 0x0c, 0x06,
+       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
+       0x06, 0x00, 0x02, 0x09, 0x99,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x13, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x49, 0x13, 0x00, 0x00, 0xc0, 0x00, 0x14,
+                         0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
+                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x82,
+                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+                         0x01, 0xf0, 0x00,
+       0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
+                         0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
+                         0x40,
+       0x10, 0x1a, 0x01, 0x00,
+       0x10, 0x00, 0x01, 0xad,
+       0x00, 0x00, 0x01, 0x08,
+       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+       0x10, 0x1b, 0x02, 0x00, 0x00,
+       0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+       0x10, 0x1d, 0x08, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
+       0x10, 0x0e, 0x01, 0x0f,
+       0x10, 0x41, 0x11, 0x00, 0x0f, 0x29, 0x4a, 0x64, 0x7a, 0x8c, 0x9e,
+                         0xad, 0xba, 0xc7, 0xd3, 0xde, 0xe8, 0xf1, 0xf9,
+                         0xff,
+       0x10, 0x0f, 0x02, 0x11, 0x11,
+       0x10, 0x03, 0x01, 0x0c,
+       0x10, 0x41, 0x11, 0x00, 0x0f, 0x29, 0x4a, 0x64, 0x7a, 0x8c, 0x9e,
+                         0xad, 0xba, 0xc7, 0xd3, 0xde, 0xe8, 0xf1, 0xf9,
+                         0xff,
+       0x10, 0x0b, 0x01, 0x1c,
+       0x10, 0x0d, 0x01, 0x1a,
+       0x10, 0x0c, 0x01, 0x34,
+       0x04, 0x05, 0x01, 0x61,
+       0x04, 0x04, 0x01, 0x40,
+       0x04, 0x06, 0x01, 0x03,
+       0, 0, 0
+};
+
+/* nw802 - Scope USB Microscope M2 (ProScope) (Hitachi HD49322BF) */
+static const u8 proscope_init[] = {
+       0x04, 0x05, 0x01, 0x21,
+       0x04, 0x04, 0x01, 0x01,
+       0, 0, 0
+};
+static const u8 proscope_start_1[] = {
+       0x04, 0x06, 0x01, 0x04,
+       0x00, 0x00, 0x40, 0x10, 0x01, 0x00, 0xf9, 0x02, 0x10, 0x00, 0x04,
+                         0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x08, 0x00, 0x17, 0x00, 0xce, 0x00, 0xf4,
+                         0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+                         0x00, 0xce, 0x00, 0xf8, 0x03, 0x3e, 0x00, 0x86,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0xb6,
+                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xf6, 0x03, 0x34, 0x04, 0xf6, 0x03, 0x34,
+                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xe8,
+                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+       0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x1f, 0x0f, 0x08, 0x20, 0xa8, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+                         0x00, 0x0c, 0x02, 0x01, 0x00, 0x19, 0x00, 0x94,
+                         0x00, 0x10, 0x06, 0x10, 0x00, 0x36, 0x00,
+       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
+       0x06, 0x00, 0x02, 0x09, 0x99,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0xad, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x10, 0x1f, 0x10, 0x08, 0x0a,
+                         0x0a, 0x51, 0x00, 0xf1, 0x00, 0x3c, 0x00, 0xb4,
+                         0x00, 0x49, 0x13, 0x00, 0x00, 0x8c, 0x04, 0x01,
+                         0x20, 0x02, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00,
+                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+       0x10, 0x40, 0x40, 0x80, 0x00, 0x2d, 0x46, 0x58, 0x67, 0x74, 0x7f,
+                         0x88, 0x94, 0x9d, 0xa6, 0xae, 0xb5, 0xbd, 0xc4,
+                         0xcb, 0xd1, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x3f,
+                         0x01, 0x00, 0x00, 0xef, 0x00, 0x09, 0x05, 0x82,
+                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+                         0x01, 0xf0, 0x00,
+       0, 0, 0
+};
+static const u8 proscope_start_qvga[] = {
+       0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
+                         0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
+                         0x40,
+       0x10, 0x1a, 0x01, 0x06,
+       0x00, 0x03, 0x02, 0xf9, 0x02,
+       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+       0x10, 0x1b, 0x02, 0x00, 0x00,
+       0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+       0x10, 0x1d, 0x08, 0xc0, 0x0d, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
+       0x10, 0x0e, 0x01, 0x10,
+       0, 0, 0
+};
+static const u8 proscope_start_vga[] = {
+       0x00, 0x03, 0x02, 0xf9, 0x02,
+       0x10, 0x85, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
+       0x02, 0x00, 0x11, 0x78, 0xa0, 0x8c, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x16, 0x00, 0x00, 0x82, 0x84, 0x00,
+                         0x80,
+       0x10, 0x1a, 0x01, 0x06,
+       0x10, 0x00, 0x01, 0xa1,
+       0x10, 0x1b, 0x02, 0x00, 0x00,
+       0x10, 0x1d, 0x08, 0xc0, 0x0d, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
+       0x10, 0x11, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
+       0x10, 0x0e, 0x01, 0x10,
+       0x10, 0x41, 0x11, 0x00, 0x10, 0x51, 0x6e, 0x83, 0x93, 0xa1, 0xae,
+                         0xb9, 0xc3, 0xcc, 0xd4, 0xdd, 0xe4, 0xeb, 0xf2,
+                         0xf9,
+       0x10, 0x03, 0x01, 0x00,
+       0, 0, 0
+};
+static const u8 proscope_start_2[] = {
+       0x10, 0x0f, 0x02, 0x0c, 0x0c,
+       0x10, 0x03, 0x01, 0x0c,
+       0x10, 0x41, 0x11, 0x00, 0x10, 0x51, 0x6e, 0x83, 0x93, 0xa1, 0xae,
+                         0xb9, 0xc3, 0xcc, 0xd4, 0xdd, 0xe4, 0xeb, 0xf2,
+                         0xf9,
+       0x10, 0x0b, 0x01, 0x0b,
+       0x10, 0x0d, 0x01, 0x10,
+       0x10, 0x0c, 0x01, 0x1b,
+       0x04, 0x06, 0x01, 0x03,
+       0x04, 0x05, 0x01, 0x21,
+       0x04, 0x04, 0x01, 0x00,
+       0, 0, 0
+};
+
+/* nw800 - hv7121b? (seems pas106) - Divio Chicony TwinkleCam */
+static const u8 twinkle_start[] = {
+       0x04, 0x06, 0x01, 0x44,
+       0x04, 0x06, 0x01, 0x00,
+       0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f,
+                         0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc,
+                         0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+       0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03,
+                         0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
+                         0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
+       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00,
+       0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x08,
+                         0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+                         0x03, 0x00, 0x00, 0x10, 0x00, 0x20, 0x10, 0x06,
+                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x00, 0x80,
+       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+       0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62,
+                         0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
+                         0x01, 0x60, 0x01, 0x00, 0x00,
+
+       0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+       0x04, 0x04, 0x01, 0x10,
+       0x04, 0x04, 0x01, 0x00,
+       0x04, 0x05, 0x01, 0x61,
+       0x04, 0x04, 0x01, 0x01,
+       I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x0a,
+       I2C0, 0x40, 0x02, 0x11, 0x06,
+       I2C0, 0x40, 0x02, 0x14, 0x00,
+       I2C0, 0x40, 0x02, 0x13, 0x01,           /* i2c end */
+       I2C0, 0x40, 0x02, 0x07, 0x01,
+       0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
+                         0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
+                         0x40,
+       I2C0, 0x40, 0x02, 0x02, 0x0c,
+       I2C0, 0x40, 0x02, 0x13, 0x01,
+       0x10, 0x00, 0x01, 0x01,
+       0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
+                         0x20, 0x01, 0x60, 0x01,
+       I2C0, 0x40, 0x02, 0x05, 0x0f,
+       I2C0, 0x40, 0x02, 0x13, 0x01,
+       I2C0, 0x40, 0x08, 0x08, 0x04, 0x0b, 0x01, 0x01, 0x02, 0x00, 0x17,
+       I2C0, 0x40, 0x03, 0x12, 0x00, 0x01,
+       0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+       I2C0, 0x40, 0x02, 0x12, 0x00,
+       I2C0, 0x40, 0x02, 0x0e, 0x00,
+       I2C0, 0x40, 0x02, 0x11, 0x06,
+       0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
+                         0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
+                         0xf9,
+       0x10, 0x03, 0x01, 0x00,
+       0x10, 0x0f, 0x02, 0x0c, 0x0c,
+       0x10, 0x03, 0x01, 0x06,
+       0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
+                         0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
+                         0xf9,
+       0x10, 0x0b, 0x01, 0x19,
+       0x10, 0x0d, 0x01, 0x10,
+       0x10, 0x0c, 0x01, 0x0d,
+       0x04, 0x06, 0x01, 0x03,
+       0x04, 0x05, 0x01, 0x61,
+       0x04, 0x04, 0x01, 0x41,
+       0, 0, 0
+};
+
+/* nw802 dvc-v6 */
+static const u8 dvcv6_start[] = {
+       0x04, 0x06, 0x01, 0x06,
+       0x00, 0x00, 0x40, 0x54, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x4c,
+                         0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+                         0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
+                         0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+       0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
+                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+                         0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
+                         0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
+                         0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
+       0x00, 0x80, 0x1f, 0x98, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
+                         0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+                         0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
+                         0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
+       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+                         0x40, 0x20,
+       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
+       0x06, 0x00, 0x02, 0x09, 0x99,
+       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00,
+       0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                         0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
+                         0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+                         0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
+                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+                         0x01, 0xf0, 0x00,
+       0x00, 0x03, 0x02, 0x94, 0x03,
+       0x00, 0x1d, 0x04, 0x0a, 0x01, 0x28, 0x07,
+       0x00, 0x7b, 0x02, 0xe0, 0x00,
+       0x10, 0x8d, 0x01, 0x00,
+       0x00, 0x09, 0x04, 0x1e, 0x00, 0x0c, 0x02,
+       0x00, 0x91, 0x02, 0x0b, 0x02,
+       0x10, 0x00, 0x01, 0xaf,
+       0x02, 0x00, 0x11, 0x3c, 0x50, 0x8f, 0x3c, 0x50, 0x00, 0x00, 0x00,
+                         0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
+                         0x40,
+       0x10, 0x1a, 0x01, 0x02,
+       0x10, 0x00, 0x01, 0xaf,
+       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+       0x10, 0x1b, 0x02, 0x07, 0x01,
+       0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
+       0x10, 0x1f, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
+       0x10, 0x1d, 0x02, 0x40, 0x06,
+       0x10, 0x0e, 0x01, 0x08,
+       0x10, 0x41, 0x11, 0x00, 0x0f, 0x54, 0x6f, 0x82, 0x91, 0x9f, 0xaa,
+                         0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xdb, 0xdc, 0xdc,
+                         0xdc,
+       0x10, 0x03, 0x01, 0x00,
+       0x10, 0x0f, 0x02, 0x12, 0x12,
+       0x10, 0x03, 0x01, 0x11,
+       0x10, 0x41, 0x11, 0x00, 0x0f, 0x54, 0x6f, 0x82, 0x91, 0x9f, 0xaa,
+                         0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xdb, 0xdc, 0xdc,
+                         0xdc,
+       0x10, 0x0b, 0x01, 0x16,
+       0x10, 0x0d, 0x01, 0x10,
+       0x10, 0x0c, 0x01, 0x1a,
+       0x04, 0x06, 0x01, 0x03,
+       0x04, 0x04, 0x01, 0x00,
+};
+
+static const u8 *webcam_start[] = {
+       [Generic800] = nw800_start,
+       [SpaceCam] = spacecam_start,
+       [SpaceCam2] = spacecam2_start,
+       [Cvideopro] = cvideopro_start,
+       [Dlink350c] = dlink_start,
+       [DS3303u] = ds3303_start,
+       [Kr651us] = kr651_start_1,
+       [Kritter] = kritter_start,
+       [Mustek300] = mustek_start,
+       [Proscope] = proscope_start_1,
+       [Twinkle] = twinkle_start,
+       [DvcV6] = dvcv6_start,
+       [P35u] = nw801_start_1,
+       [Generic802] = nw802_start,
+};
+
+/* -- write a register -- */
+static void reg_w(struct gspca_dev *gspca_dev,
+                       u16 index,
+                       const u8 *data,
+                       int len)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       if (len == 1)
+               PDEBUG(D_USBO, "SET 00 0000 %04x %02x", index, *data);
+       else
+               PDEBUG(D_USBO, "SET 00 0000 %04x %02x %02x ...",
+                               index, *data, data[1]);
+       memcpy(gspca_dev->usb_buf, data, len);
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                       0x00,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0x00,           /* value */
+                       index,
+                       gspca_dev->usb_buf,
+                       len,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_w err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+/* -- read registers in usb_buf -- */
+static void reg_r(struct gspca_dev *gspca_dev,
+                       u16 index,
+                       int len)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                       0x00,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0x00, index,
+                       gspca_dev->usb_buf, len, 500);
+       if (ret < 0) {
+               pr_err("reg_r err %d\n", ret);
+               gspca_dev->usb_err = ret;
+               return;
+       }
+       if (len == 1)
+               PDEBUG(D_USBI, "GET 00 0000 %04x %02x",
+                               index, gspca_dev->usb_buf[0]);
+       else
+               PDEBUG(D_USBI, "GET 00 0000 %04x %02x %02x ..",
+                               index, gspca_dev->usb_buf[0],
+                               gspca_dev->usb_buf[1]);
+}
+
+static void i2c_w(struct gspca_dev *gspca_dev,
+                       u8 i2c_addr,
+                       const u8 *data,
+                       int len)
+{
+       u8 val[2];
+       int i;
+
+       reg_w(gspca_dev, 0x0600, data + 1, len - 1);
+       reg_w(gspca_dev, 0x0600, data, len);
+       val[0] = len;
+       val[1] = i2c_addr;
+       reg_w(gspca_dev, 0x0502, val, 2);
+       val[0] = 0x01;
+       reg_w(gspca_dev, 0x0501, val, 1);
+       for (i = 5; --i >= 0; ) {
+               msleep(4);
+               reg_r(gspca_dev, 0x0505, 1);
+               if (gspca_dev->usb_err < 0)
+                       return;
+               if (gspca_dev->usb_buf[0] == 0)
+                       return;
+       }
+       gspca_dev->usb_err = -ETIME;
+}
+
+static void reg_w_buf(struct gspca_dev *gspca_dev,
+                       const u8 *cmd)
+{
+       u16 reg;
+       int len;
+
+       for (;;) {
+               reg = *cmd++ << 8;
+               reg += *cmd++;
+               len = *cmd++;
+               if (len == 0)
+                       break;
+               if (cmd[-3] != I2C0)
+                       reg_w(gspca_dev, reg, cmd, len);
+               else
+                       i2c_w(gspca_dev, reg, cmd, len);
+               cmd += len;
+       }
+}
+
+static int swap_bits(int v)
+{
+       int r, i;
+
+       r = 0;
+       for (i = 0; i < 8; i++) {
+               r <<= 1;
+               if (v & 1)
+                       r++;
+               v >>= 1;
+       }
+       return r;
+}
+
+static void setgain(struct gspca_dev *gspca_dev, u8 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 v[2];
+
+       switch (sd->webcam) {
+       case P35u:
+               reg_w(gspca_dev, 0x1026, &val, 1);
+               break;
+       case Kr651us:
+               /* 0 - 253 */
+               val = swap_bits(val);
+               v[0] = val << 3;
+               v[1] = val >> 5;
+               reg_w(gspca_dev, 0x101d, v, 2); /* SIF reg0/1 (AGC) */
+               break;
+       }
+}
+
+static void setexposure(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 v[2];
+
+       switch (sd->webcam) {
+       case P35u:
+               v[0] = ((9 - val) << 3) | 0x01;
+               reg_w(gspca_dev, 0x1019, v, 1);
+               break;
+       case Cvideopro:
+       case DvcV6:
+       case Kritter:
+       case Kr651us:
+               v[0] = val;
+               v[1] = val >> 8;
+               reg_w(gspca_dev, 0x101b, v, 2);
+               break;
+       }
+}
+
+static void setautogain(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int w, h;
+
+       if (!val) {
+               sd->ag_cnt = -1;
+               return;
+       }
+       sd->ag_cnt = AG_CNT_START;
+
+       reg_r(gspca_dev, 0x1004, 1);
+       if (gspca_dev->usb_buf[0] & 0x04) {     /* if AE_FULL_FRM */
+               sd->ae_res = gspca_dev->width * gspca_dev->height;
+       } else {                                /* get the AE window size */
+               reg_r(gspca_dev, 0x1011, 8);
+               w = (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]
+                 - (gspca_dev->usb_buf[3] << 8) - gspca_dev->usb_buf[2];
+               h = (gspca_dev->usb_buf[5] << 8) + gspca_dev->usb_buf[4]
+                 - (gspca_dev->usb_buf[7] << 8) - gspca_dev->usb_buf[6];
+               sd->ae_res = h * w;
+               if (sd->ae_res == 0)
+                       sd->ae_res = gspca_dev->width * gspca_dev->height;
+       }
+}
+
+static int nw802_test_reg(struct gspca_dev *gspca_dev,
+                       u16 index,
+                       u8 value)
+{
+       /* write the value */
+       reg_w(gspca_dev, index, &value, 1);
+
+       /* read it */
+       reg_r(gspca_dev, index, 1);
+
+       return gspca_dev->usb_buf[0] == value;
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if ((unsigned) webcam >= NWEBCAMS)
+               webcam = 0;
+       sd->webcam = webcam;
+       gspca_dev->cam.needs_full_bandwidth = 1;
+       sd->ag_cnt = -1;
+
+       /*
+        * Autodetect sequence inspired from some log.
+        * We try to detect what registers exist or not.
+        * If 0x0500 does not exist => NW802
+        * If it does, test 0x109b. If it doesn't exist,
+        * then it's a NW801. Else, a NW800
+        * If a et31x110 (nw800 and 06a5:d800)
+        *      get the sensor ID
+        */
+       if (!nw802_test_reg(gspca_dev, 0x0500, 0x55)) {
+               sd->bridge = BRIDGE_NW802;
+               if (sd->webcam == Generic800)
+                       sd->webcam = Generic802;
+       } else if (!nw802_test_reg(gspca_dev, 0x109b, 0xaa)) {
+               sd->bridge = BRIDGE_NW801;
+               if (sd->webcam == Generic800)
+                       sd->webcam = P35u;
+       } else if (id->idVendor == 0x06a5 && id->idProduct == 0xd800) {
+               reg_r(gspca_dev, 0x0403, 1);            /* GPIO */
+               PDEBUG(D_PROBE, "et31x110 sensor type %02x",
+                               gspca_dev->usb_buf[0]);
+               switch (gspca_dev->usb_buf[0] >> 1) {
+               case 0x00:                              /* ?? */
+                       if (sd->webcam == Generic800)
+                               sd->webcam = SpaceCam;
+                       break;
+               case 0x01:                              /* Hynix? */
+                       if (sd->webcam == Generic800)
+                               sd->webcam = Twinkle;
+                       break;
+               case 0x0a:                              /* Pixart */
+                       if (sd->webcam == Generic800)
+                               sd->webcam = SpaceCam2;
+                       break;
+               }
+       }
+       if (webcam_chip[sd->webcam] != sd->bridge) {
+               pr_err("Bad webcam type %d for NW80%d\n",
+                      sd->webcam, sd->bridge);
+               gspca_dev->usb_err = -ENODEV;
+               return gspca_dev->usb_err;
+       }
+       PDEBUG(D_PROBE, "Bridge nw80%d - type: %d", sd->bridge, sd->webcam);
+
+       if (sd->bridge == BRIDGE_NW800) {
+               switch (sd->webcam) {
+               case DS3303u:
+                       gspca_dev->cam.cam_mode = cif_mode;     /* qvga */
+                       break;
+               default:
+                       gspca_dev->cam.cam_mode = &cif_mode[1]; /* cif */
+                       break;
+               }
+               gspca_dev->cam.nmodes = 1;
+       } else {
+               gspca_dev->cam.cam_mode = vga_mode;
+               switch (sd->webcam) {
+               case Kr651us:
+               case Proscope:
+               case P35u:
+                       gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
+                       break;
+               default:
+                       gspca_dev->cam.nmodes = 1;      /* qvga only */
+                       break;
+               }
+       }
+
+       return gspca_dev->usb_err;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->bridge) {
+       case BRIDGE_NW800:
+               switch (sd->webcam) {
+               case SpaceCam:
+                       reg_w_buf(gspca_dev, spacecam_init);
+                       break;
+               default:
+                       reg_w_buf(gspca_dev, nw800_init);
+                       break;
+               }
+               break;
+       default:
+               switch (sd->webcam) {
+               case Mustek300:
+               case P35u:
+               case Proscope:
+                       reg_w_buf(gspca_dev, proscope_init);
+                       break;
+               }
+               break;
+       }
+       return gspca_dev->usb_err;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       const u8 *cmd;
+
+       cmd = webcam_start[sd->webcam];
+       reg_w_buf(gspca_dev, cmd);
+       switch (sd->webcam) {
+       case P35u:
+               if (gspca_dev->width == 320)
+                       reg_w_buf(gspca_dev, nw801_start_qvga);
+               else
+                       reg_w_buf(gspca_dev, nw801_start_vga);
+               reg_w_buf(gspca_dev, nw801_start_2);
+               break;
+       case Kr651us:
+               if (gspca_dev->width == 320)
+                       reg_w_buf(gspca_dev, kr651_start_qvga);
+               else
+                       reg_w_buf(gspca_dev, kr651_start_vga);
+               reg_w_buf(gspca_dev, kr651_start_2);
+               break;
+       case Proscope:
+               if (gspca_dev->width == 320)
+                       reg_w_buf(gspca_dev, proscope_start_qvga);
+               else
+                       reg_w_buf(gspca_dev, proscope_start_vga);
+               reg_w_buf(gspca_dev, proscope_start_2);
+               break;
+       }
+
+       sd->exp_too_high_cnt = 0;
+       sd->exp_too_low_cnt = 0;
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 value;
+
+       /* 'go' off */
+       if (sd->bridge != BRIDGE_NW801) {
+               value = 0x02;
+               reg_w(gspca_dev, 0x0406, &value, 1);
+       }
+
+       /* LED off */
+       switch (sd->webcam) {
+       case Cvideopro:
+       case Kr651us:
+       case DvcV6:
+       case Kritter:
+               value = 0xff;
+               break;
+       case Dlink350c:
+               value = 0x21;
+               break;
+       case SpaceCam:
+       case SpaceCam2:
+       case Proscope:
+       case Twinkle:
+               value = 0x01;
+               break;
+       default:
+               return;
+       }
+       reg_w(gspca_dev, 0x0404, &value, 1);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,                       /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       /*
+        * frame header = '00 00 hh ww ss xx ff ff'
+        * with:
+        *      - 'hh': height / 4
+        *      - 'ww': width / 4
+        *      - 'ss': frame sequence number c0..dd
+        */
+       if (data[0] == 0x00 && data[1] == 0x00
+        && data[6] == 0xff && data[7] == 0xff) {
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+               gspca_frame_add(gspca_dev, FIRST_PACKET, data + 8, len - 8);
+       } else {
+               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+       }
+}
+
+static void do_autogain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int luma;
+
+       if (sd->ag_cnt < 0)
+               return;
+       if (--sd->ag_cnt >= 0)
+               return;
+       sd->ag_cnt = AG_CNT_START;
+
+       /* get the average luma */
+       reg_r(gspca_dev, sd->bridge == BRIDGE_NW801 ? 0x080d : 0x080c, 4);
+       luma = (gspca_dev->usb_buf[3] << 24) + (gspca_dev->usb_buf[2] << 16)
+               + (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
+       luma /= sd->ae_res;
+
+       switch (sd->webcam) {
+       case P35u:
+               gspca_coarse_grained_expo_autogain(gspca_dev, luma, 100, 5);
+               break;
+       default:
+               gspca_expo_autogain(gspca_dev, luma, 100, 5, 230, 0);
+               break;
+       }
+}
+
+
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct gspca_dev *gspca_dev =
+               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+
+       gspca_dev->usb_err = 0;
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       /* autogain/gain/exposure control cluster */
+       case V4L2_CID_AUTOGAIN:
+               if (ctrl->is_new)
+                       setautogain(gspca_dev, ctrl->val);
+               if (!ctrl->val) {
+                       if (gspca_dev->gain->is_new)
+                               setgain(gspca_dev, gspca_dev->gain->val);
+                       if (gspca_dev->exposure->is_new)
+                               setexposure(gspca_dev,
+                                           gspca_dev->exposure->val);
+               }
+               break;
+       /* Some webcams only have exposure, so handle that separately from the
+          autogain/gain/exposure cluster in the previous case. */
+       case V4L2_CID_EXPOSURE:
+               setexposure(gspca_dev, gspca_dev->exposure->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, 3);
+       switch (sd->webcam) {
+       case P35u:
+               gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+               /* For P35u choose coarse expo auto gain function gain minimum,
+                * to avoid a large settings jump the first auto adjustment */
+               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 127, 1, 127 / 5 * 2);
+               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0, 9, 1, 9);
+               break;
+       case Kr651us:
+               gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 253, 1, 128);
+               /* fall through */
+       case Cvideopro:
+       case DvcV6:
+       case Kritter:
+               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0, 315, 1, 150);
+               break;
+       default:
+               break;
+       }
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       if (gspca_dev->autogain)
+               v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
+       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,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+       .dq_callback = do_autogain,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x046d, 0xd001)},
+       {USB_DEVICE(0x0502, 0xd001)},
+       {USB_DEVICE(0x052b, 0xd001)},
+       {USB_DEVICE(0x055f, 0xd001)},
+       {USB_DEVICE(0x06a5, 0x0000)},
+       {USB_DEVICE(0x06a5, 0xd001)},
+       {USB_DEVICE(0x06a5, 0xd800)},
+       {USB_DEVICE(0x06be, 0xd001)},
+       {USB_DEVICE(0x0728, 0xd001)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
+
+module_param(webcam, int, 0644);
+MODULE_PARM_DESC(webcam,
+       "Webcam type\n"
+       "0: generic\n"
+       "1: Trust 120 SpaceCam\n"
+       "2: other Trust 120 SpaceCam\n"
+       "3: Conceptronic Video Pro\n"
+       "4: D-link dru-350c\n"
+       "5: Plustek Opticam 500U\n"
+       "6: Panasonic GP-KR651US\n"
+       "7: iRez Kritter\n"
+       "8: Mustek Wcam 300 mini\n"
+       "9: Scalar USB Microscope M2 (Proscope)\n"
+       "10: Divio Chicony TwinkleCam\n"
+       "11: DVC-V6\n");
diff --git a/drivers/media/usb/gspca/ov519.c b/drivers/media/usb/gspca/ov519.c
new file mode 100644 (file)
index 0000000..bfc7cef
--- /dev/null
@@ -0,0 +1,4991 @@
+/**
+ * OV519 driver
+ *
+ * Copyright (C) 2008-2011 Jean-François Moine <moinejf@free.fr>
+ * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This module is adapted from the ov51x-jpeg package, which itself
+ * was adapted from the ov511 driver.
+ *
+ * Original copyright for the ov511 driver is:
+ *
+ * Copyright (c) 1999-2006 Mark W. McClelland
+ * Support for OV519, OV8610 Copyright (c) 2003 Joerg Heckenbach
+ * Many improvements by Bret Wallach <bwallac1@san.rr.com>
+ * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000)
+ * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org>
+ * Changes by Claudio Matsuoka <claudio@conectiva.com>
+ *
+ * ov51x-jpeg original copyright is:
+ *
+ * Copyright (c) 2004-2007 Romain Beauxis <toots@rastageeks.org>
+ * Support for OV7670 sensors was contributed by Sam Skipsey <aoanla@yahoo.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
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "ov519"
+
+#include <linux/input.h>
+#include "gspca.h"
+
+/* The jpeg_hdr is used by w996Xcf only */
+/* The CONEX_CAM define for jpeg.h needs renaming, now its used here too */
+#define CONEX_CAM
+#include "jpeg.h"
+
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
+MODULE_DESCRIPTION("OV519 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* global parameters */
+static int frame_rate;
+
+/* Number of times to retry a failed I2C transaction. Increase this if you
+ * are getting "Failed to read sensor ID..." */
+static int i2c_detect_tries = 10;
+
+/* ov519 device descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;             /* !! must be the first item */
+
+       struct v4l2_ctrl *jpegqual;
+       struct v4l2_ctrl *freq;
+       struct { /* h/vflip control cluster */
+               struct v4l2_ctrl *hflip;
+               struct v4l2_ctrl *vflip;
+       };
+       struct { /* autobrightness/brightness control cluster */
+               struct v4l2_ctrl *autobright;
+               struct v4l2_ctrl *brightness;
+       };
+
+       u8 packet_nr;
+
+       char bridge;
+#define BRIDGE_OV511           0
+#define BRIDGE_OV511PLUS       1
+#define BRIDGE_OV518           2
+#define BRIDGE_OV518PLUS       3
+#define BRIDGE_OV519           4               /* = ov530 */
+#define BRIDGE_OVFX2           5
+#define BRIDGE_W9968CF         6
+#define BRIDGE_MASK            7
+
+       char invert_led;
+#define BRIDGE_INVERT_LED      8
+
+       char snapshot_pressed;
+       char snapshot_needs_reset;
+
+       /* Determined by sensor type */
+       u8 sif;
+
+#define QUALITY_MIN 50
+#define QUALITY_MAX 70
+#define QUALITY_DEF 50
+
+       u8 stopped;             /* Streaming is temporarily paused */
+       u8 first_frame;
+
+       u8 frame_rate;          /* current Framerate */
+       u8 clockdiv;            /* clockdiv override */
+
+       s8 sensor;              /* Type of image sensor chip (SEN_*) */
+
+       u8 sensor_addr;
+       u16 sensor_width;
+       u16 sensor_height;
+       s16 sensor_reg_cache[256];
+
+       u8 jpeg_hdr[JPEG_HDR_SZ];
+};
+enum sensors {
+       SEN_OV2610,
+       SEN_OV2610AE,
+       SEN_OV3610,
+       SEN_OV6620,
+       SEN_OV6630,
+       SEN_OV66308AF,
+       SEN_OV7610,
+       SEN_OV7620,
+       SEN_OV7620AE,
+       SEN_OV7640,
+       SEN_OV7648,
+       SEN_OV7660,
+       SEN_OV7670,
+       SEN_OV76BE,
+       SEN_OV8610,
+       SEN_OV9600,
+};
+
+/* Note this is a bit of a hack, but the w9968cf driver needs the code for all
+   the ov sensors which is already present here. When we have the time we
+   really should move the sensor drivers to v4l2 sub drivers. */
+#include "w996Xcf.c"
+
+/* table of the disabled controls */
+struct ctrl_valid {
+       int has_brightness:1;
+       int has_contrast:1;
+       int has_exposure:1;
+       int has_autogain:1;
+       int has_sat:1;
+       int has_hvflip:1;
+       int has_autobright:1;
+       int has_freq:1;
+};
+
+static const struct ctrl_valid valid_controls[] = {
+       [SEN_OV2610] = {
+               .has_exposure = 1,
+               .has_autogain = 1,
+       },
+       [SEN_OV2610AE] = {
+               .has_exposure = 1,
+               .has_autogain = 1,
+       },
+       [SEN_OV3610] = {
+               /* No controls */
+       },
+       [SEN_OV6620] = {
+               .has_brightness = 1,
+               .has_contrast = 1,
+               .has_sat = 1,
+               .has_autobright = 1,
+               .has_freq = 1,
+       },
+       [SEN_OV6630] = {
+               .has_brightness = 1,
+               .has_contrast = 1,
+               .has_sat = 1,
+               .has_autobright = 1,
+               .has_freq = 1,
+       },
+       [SEN_OV66308AF] = {
+               .has_brightness = 1,
+               .has_contrast = 1,
+               .has_sat = 1,
+               .has_autobright = 1,
+               .has_freq = 1,
+       },
+       [SEN_OV7610] = {
+               .has_brightness = 1,
+               .has_contrast = 1,
+               .has_sat = 1,
+               .has_autobright = 1,
+               .has_freq = 1,
+       },
+       [SEN_OV7620] = {
+               .has_brightness = 1,
+               .has_contrast = 1,
+               .has_sat = 1,
+               .has_autobright = 1,
+               .has_freq = 1,
+       },
+       [SEN_OV7620AE] = {
+               .has_brightness = 1,
+               .has_contrast = 1,
+               .has_sat = 1,
+               .has_autobright = 1,
+               .has_freq = 1,
+       },
+       [SEN_OV7640] = {
+               .has_brightness = 1,
+               .has_sat = 1,
+               .has_freq = 1,
+       },
+       [SEN_OV7648] = {
+               .has_brightness = 1,
+               .has_sat = 1,
+               .has_freq = 1,
+       },
+       [SEN_OV7660] = {
+               .has_brightness = 1,
+               .has_contrast = 1,
+               .has_sat = 1,
+               .has_hvflip = 1,
+               .has_freq = 1,
+       },
+       [SEN_OV7670] = {
+               .has_brightness = 1,
+               .has_contrast = 1,
+               .has_hvflip = 1,
+               .has_freq = 1,
+       },
+       [SEN_OV76BE] = {
+               .has_brightness = 1,
+               .has_contrast = 1,
+               .has_sat = 1,
+               .has_autobright = 1,
+               .has_freq = 1,
+       },
+       [SEN_OV8610] = {
+               .has_brightness = 1,
+               .has_contrast = 1,
+               .has_sat = 1,
+               .has_autobright = 1,
+       },
+       [SEN_OV9600] = {
+               .has_exposure = 1,
+               .has_autogain = 1,
+       },
+};
+
+static const struct v4l2_pix_format ov519_vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+static const struct v4l2_pix_format ov519_sif_mode[] = {
+       {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 3},
+       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2},
+       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+
+/* Note some of the sizeimage values for the ov511 / ov518 may seem
+   larger then necessary, however they need to be this big as the ov511 /
+   ov518 always fills the entire isoc frame, using 0 padding bytes when
+   it doesn't have any data. So with low framerates the amount of data
+   transferred can become quite large (libv4l will remove all the 0 padding
+   in userspace). */
+static const struct v4l2_pix_format ov518_vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 2,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+static const struct v4l2_pix_format ov518_sif_mode[] = {
+       {160, 120, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 70000,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 3},
+       {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 70000,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2},
+       {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+
+static const struct v4l2_pix_format ov511_vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 2,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+static const struct v4l2_pix_format ov511_sif_mode[] = {
+       {160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 70000,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 3},
+       {176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 70000,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2},
+       {352, 288, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+
+static const struct v4l2_pix_format ovfx2_vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+static const struct v4l2_pix_format ovfx2_cif_mode[] = {
+       {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 3},
+       {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+       {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+static const struct v4l2_pix_format ovfx2_ov2610_mode[] = {
+       {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 800,
+               .sizeimage = 800 * 600,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 1600,
+               .sizeimage = 1600 * 1200,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+};
+static const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
+       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 800,
+               .sizeimage = 800 * 600,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 1024,
+               .sizeimage = 1024 * 768,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 1600,
+               .sizeimage = 1600 * 1200,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+       {2048, 1536, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 2048,
+               .sizeimage = 2048 * 1536,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+static const struct v4l2_pix_format ovfx2_ov9600_mode[] = {
+       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 1280,
+               .sizeimage = 1280 * 1024,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+};
+
+/* Registers common to OV511 / OV518 */
+#define R51x_FIFO_PSIZE                        0x30    /* 2 bytes wide w/ OV518(+) */
+#define R51x_SYS_RESET                 0x50
+       /* Reset type flags */
+       #define OV511_RESET_OMNICE      0x08
+#define R51x_SYS_INIT                  0x53
+#define R51x_SYS_SNAP                  0x52
+#define R51x_SYS_CUST_ID               0x5f
+#define R51x_COMP_LUT_BEGIN            0x80
+
+/* OV511 Camera interface register numbers */
+#define R511_CAM_DELAY                 0x10
+#define R511_CAM_EDGE                  0x11
+#define R511_CAM_PXCNT                 0x12
+#define R511_CAM_LNCNT                 0x13
+#define R511_CAM_PXDIV                 0x14
+#define R511_CAM_LNDIV                 0x15
+#define R511_CAM_UV_EN                 0x16
+#define R511_CAM_LINE_MODE             0x17
+#define R511_CAM_OPTS                  0x18
+
+#define R511_SNAP_FRAME                        0x19
+#define R511_SNAP_PXCNT                        0x1a
+#define R511_SNAP_LNCNT                        0x1b
+#define R511_SNAP_PXDIV                        0x1c
+#define R511_SNAP_LNDIV                        0x1d
+#define R511_SNAP_UV_EN                        0x1e
+#define R511_SNAP_OPTS                 0x1f
+
+#define R511_DRAM_FLOW_CTL             0x20
+#define R511_FIFO_OPTS                 0x31
+#define R511_I2C_CTL                   0x40
+#define R511_SYS_LED_CTL               0x55    /* OV511+ only */
+#define R511_COMP_EN                   0x78
+#define R511_COMP_LUT_EN               0x79
+
+/* OV518 Camera interface register numbers */
+#define R518_GPIO_OUT                  0x56    /* OV518(+) only */
+#define R518_GPIO_CTL                  0x57    /* OV518(+) only */
+
+/* OV519 Camera interface register numbers */
+#define OV519_R10_H_SIZE               0x10
+#define OV519_R11_V_SIZE               0x11
+#define OV519_R12_X_OFFSETL            0x12
+#define OV519_R13_X_OFFSETH            0x13
+#define OV519_R14_Y_OFFSETL            0x14
+#define OV519_R15_Y_OFFSETH            0x15
+#define OV519_R16_DIVIDER              0x16
+#define OV519_R20_DFR                  0x20
+#define OV519_R25_FORMAT               0x25
+
+/* OV519 System Controller register numbers */
+#define OV519_R51_RESET1               0x51
+#define OV519_R54_EN_CLK1              0x54
+#define OV519_R57_SNAPSHOT             0x57
+
+#define OV519_GPIO_DATA_OUT0           0x71
+#define OV519_GPIO_IO_CTRL0            0x72
+
+/*#define OV511_ENDPOINT_ADDRESS 1      * Isoc endpoint number */
+
+/*
+ * The FX2 chip does not give us a zero length read at end of frame.
+ * It does, however, give a short read at the end of a frame, if
+ * necessary, rather than run two frames together.
+ *
+ * By choosing the right bulk transfer size, we are guaranteed to always
+ * get a short read for the last read of each frame.  Frame sizes are
+ * always a composite number (width * height, or a multiple) so if we
+ * choose a prime number, we are guaranteed that the last read of a
+ * frame will be short.
+ *
+ * But it isn't that easy: the 2.6 kernel requires a multiple of 4KB,
+ * otherwise EOVERFLOW "babbling" errors occur.  I have not been able
+ * to figure out why.  [PMiller]
+ *
+ * The constant (13 * 4096) is the largest "prime enough" number less than 64KB.
+ *
+ * It isn't enough to know the number of bytes per frame, in case we
+ * have data dropouts or buffer overruns (even though the FX2 double
+ * buffers, there are some pretty strict real time constraints for
+ * isochronous transfer for larger frame sizes).
+ */
+/*jfm: this value does not work for 800x600 - see isoc_init */
+#define OVFX2_BULK_SIZE (13 * 4096)
+
+/* I2C registers */
+#define R51x_I2C_W_SID         0x41
+#define R51x_I2C_SADDR_3       0x42
+#define R51x_I2C_SADDR_2       0x43
+#define R51x_I2C_R_SID         0x44
+#define R51x_I2C_DATA          0x45
+#define R518_I2C_CTL           0x47    /* OV518(+) only */
+#define OVFX2_I2C_ADDR         0x00
+
+/* I2C ADDRESSES */
+#define OV7xx0_SID   0x42
+#define OV_HIRES_SID 0x60              /* OV9xxx / OV2xxx / OV3xxx */
+#define OV8xx0_SID   0xa0
+#define OV6xx0_SID   0xc0
+
+/* OV7610 registers */
+#define OV7610_REG_GAIN                0x00    /* gain setting (5:0) */
+#define OV7610_REG_BLUE                0x01    /* blue channel balance */
+#define OV7610_REG_RED         0x02    /* red channel balance */
+#define OV7610_REG_SAT         0x03    /* saturation */
+#define OV8610_REG_HUE         0x04    /* 04 reserved */
+#define OV7610_REG_CNT         0x05    /* Y contrast */
+#define OV7610_REG_BRT         0x06    /* Y brightness */
+#define OV7610_REG_COM_C       0x14    /* misc common regs */
+#define OV7610_REG_ID_HIGH     0x1c    /* manufacturer ID MSB */
+#define OV7610_REG_ID_LOW      0x1d    /* manufacturer ID LSB */
+#define OV7610_REG_COM_I       0x29    /* misc settings */
+
+/* OV7660 and OV7670 registers */
+#define OV7670_R00_GAIN                0x00    /* Gain lower 8 bits (rest in vref) */
+#define OV7670_R01_BLUE                0x01    /* blue gain */
+#define OV7670_R02_RED         0x02    /* red gain */
+#define OV7670_R03_VREF                0x03    /* Pieces of GAIN, VSTART, VSTOP */
+#define OV7670_R04_COM1                0x04    /* Control 1 */
+/*#define OV7670_R07_AECHH     0x07     * AEC MS 5 bits */
+#define OV7670_R0C_COM3                0x0c    /* Control 3 */
+#define OV7670_R0D_COM4                0x0d    /* Control 4 */
+#define OV7670_R0E_COM5                0x0e    /* All "reserved" */
+#define OV7670_R0F_COM6                0x0f    /* Control 6 */
+#define OV7670_R10_AECH                0x10    /* More bits of AEC value */
+#define OV7670_R11_CLKRC       0x11    /* Clock control */
+#define OV7670_R12_COM7                0x12    /* Control 7 */
+#define   OV7670_COM7_FMT_VGA   0x00
+/*#define   OV7670_COM7_YUV     0x00    * YUV */
+#define   OV7670_COM7_FMT_QVGA  0x10   /* QVGA format */
+#define   OV7670_COM7_FMT_MASK  0x38
+#define   OV7670_COM7_RESET     0x80   /* Register reset */
+#define OV7670_R13_COM8                0x13    /* Control 8 */
+#define   OV7670_COM8_AEC       0x01   /* Auto exposure enable */
+#define   OV7670_COM8_AWB       0x02   /* White balance enable */
+#define   OV7670_COM8_AGC       0x04   /* Auto gain enable */
+#define   OV7670_COM8_BFILT     0x20   /* Band filter enable */
+#define   OV7670_COM8_AECSTEP   0x40   /* Unlimited AEC step size */
+#define   OV7670_COM8_FASTAEC   0x80   /* Enable fast AGC/AEC */
+#define OV7670_R14_COM9                0x14    /* Control 9 - gain ceiling */
+#define OV7670_R15_COM10       0x15    /* Control 10 */
+#define OV7670_R17_HSTART      0x17    /* Horiz start high bits */
+#define OV7670_R18_HSTOP       0x18    /* Horiz stop high bits */
+#define OV7670_R19_VSTART      0x19    /* Vert start high bits */
+#define OV7670_R1A_VSTOP       0x1a    /* Vert stop high bits */
+#define OV7670_R1E_MVFP                0x1e    /* Mirror / vflip */
+#define   OV7670_MVFP_VFLIP     0x10   /* vertical flip */
+#define   OV7670_MVFP_MIRROR    0x20   /* Mirror image */
+#define OV7670_R24_AEW         0x24    /* AGC upper limit */
+#define OV7670_R25_AEB         0x25    /* AGC lower limit */
+#define OV7670_R26_VPT         0x26    /* AGC/AEC fast mode op region */
+#define OV7670_R32_HREF                0x32    /* HREF pieces */
+#define OV7670_R3A_TSLB                0x3a    /* lots of stuff */
+#define OV7670_R3B_COM11       0x3b    /* Control 11 */
+#define   OV7670_COM11_EXP      0x02
+#define   OV7670_COM11_HZAUTO   0x10   /* Auto detect 50/60 Hz */
+#define OV7670_R3C_COM12       0x3c    /* Control 12 */
+#define OV7670_R3D_COM13       0x3d    /* Control 13 */
+#define   OV7670_COM13_GAMMA    0x80   /* Gamma enable */
+#define   OV7670_COM13_UVSAT    0x40   /* UV saturation auto adjustment */
+#define OV7670_R3E_COM14       0x3e    /* Control 14 */
+#define OV7670_R3F_EDGE                0x3f    /* Edge enhancement factor */
+#define OV7670_R40_COM15       0x40    /* Control 15 */
+/*#define   OV7670_COM15_R00FF  0xc0    *      00 to FF */
+#define OV7670_R41_COM16       0x41    /* Control 16 */
+#define   OV7670_COM16_AWBGAIN  0x08   /* AWB gain enable */
+/* end of ov7660 common registers */
+#define OV7670_R55_BRIGHT      0x55    /* Brightness */
+#define OV7670_R56_CONTRAS     0x56    /* Contrast control */
+#define OV7670_R69_GFIX                0x69    /* Fix gain control */
+/*#define OV7670_R8C_RGB444    0x8c     * RGB 444 control */
+#define OV7670_R9F_HAECC1      0x9f    /* Hist AEC/AGC control 1 */
+#define OV7670_RA0_HAECC2      0xa0    /* Hist AEC/AGC control 2 */
+#define OV7670_RA5_BD50MAX     0xa5    /* 50hz banding step limit */
+#define OV7670_RA6_HAECC3      0xa6    /* Hist AEC/AGC control 3 */
+#define OV7670_RA7_HAECC4      0xa7    /* Hist AEC/AGC control 4 */
+#define OV7670_RA8_HAECC5      0xa8    /* Hist AEC/AGC control 5 */
+#define OV7670_RA9_HAECC6      0xa9    /* Hist AEC/AGC control 6 */
+#define OV7670_RAA_HAECC7      0xaa    /* Hist AEC/AGC control 7 */
+#define OV7670_RAB_BD60MAX     0xab    /* 60hz banding step limit */
+
+struct ov_regvals {
+       u8 reg;
+       u8 val;
+};
+struct ov_i2c_regvals {
+       u8 reg;
+       u8 val;
+};
+
+/* Settings for OV2610 camera chip */
+static const struct ov_i2c_regvals norm_2610[] = {
+       { 0x12, 0x80 }, /* reset */
+};
+
+static const struct ov_i2c_regvals norm_2610ae[] = {
+       {0x12, 0x80},   /* reset */
+       {0x13, 0xcd},
+       {0x09, 0x01},
+       {0x0d, 0x00},
+       {0x11, 0x80},
+       {0x12, 0x20},   /* 1600x1200 */
+       {0x33, 0x0c},
+       {0x35, 0x90},
+       {0x36, 0x37},
+/* ms-win traces */
+       {0x11, 0x83},   /* clock / 3 ? */
+       {0x2d, 0x00},   /* 60 Hz filter */
+       {0x24, 0xb0},   /* normal colors */
+       {0x25, 0x90},
+       {0x10, 0x43},
+};
+
+static const struct ov_i2c_regvals norm_3620b[] = {
+       /*
+        * From the datasheet: "Note that after writing to register COMH
+        * (0x12) to change the sensor mode, registers related to the
+        * sensor’s cropping window will be reset back to their default
+        * values."
+        *
+        * "wait 4096 external clock ... to make sure the sensor is
+        * stable and ready to access registers" i.e. 160us at 24MHz
+        */
+       { 0x12, 0x80 }, /* COMH reset */
+       { 0x12, 0x00 }, /* QXGA, master */
+
+       /*
+        * 11 CLKRC "Clock Rate Control"
+        * [7] internal frequency doublers: on
+        * [6] video port mode: master
+        * [5:0] clock divider: 1
+        */
+       { 0x11, 0x80 },
+
+       /*
+        * 13 COMI "Common Control I"
+        *                  = 192 (0xC0) 11000000
+        *    COMI[7] "AEC speed selection"
+        *                  =   1 (0x01) 1....... "Faster AEC correction"
+        *    COMI[6] "AEC speed step selection"
+        *                  =   1 (0x01) .1...... "Big steps, fast"
+        *    COMI[5] "Banding filter on off"
+        *                  =   0 (0x00) ..0..... "Off"
+        *    COMI[4] "Banding filter option"
+        *                  =   0 (0x00) ...0.... "Main clock is 48 MHz and
+        *                                         the PLL is ON"
+        *    COMI[3] "Reserved"
+        *                  =   0 (0x00) ....0...
+        *    COMI[2] "AGC auto manual control selection"
+        *                  =   0 (0x00) .....0.. "Manual"
+        *    COMI[1] "AWB auto manual control selection"
+        *                  =   0 (0x00) ......0. "Manual"
+        *    COMI[0] "Exposure control"
+        *                  =   0 (0x00) .......0 "Manual"
+        */
+       { 0x13, 0xc0 },
+
+       /*
+        * 09 COMC "Common Control C"
+        *                  =   8 (0x08) 00001000
+        *    COMC[7:5] "Reserved"
+        *                  =   0 (0x00) 000.....
+        *    COMC[4] "Sleep Mode Enable"
+        *                  =   0 (0x00) ...0.... "Normal mode"
+        *    COMC[3:2] "Sensor sampling reset timing selection"
+        *                  =   2 (0x02) ....10.. "Longer reset time"
+        *    COMC[1:0] "Output drive current select"
+        *                  =   0 (0x00) ......00 "Weakest"
+        */
+       { 0x09, 0x08 },
+
+       /*
+        * 0C COMD "Common Control D"
+        *                  =   8 (0x08) 00001000
+        *    COMD[7] "Reserved"
+        *                  =   0 (0x00) 0.......
+        *    COMD[6] "Swap MSB and LSB at the output port"
+        *                  =   0 (0x00) .0...... "False"
+        *    COMD[5:3] "Reserved"
+        *                  =   1 (0x01) ..001...
+        *    COMD[2] "Output Average On Off"
+        *                  =   0 (0x00) .....0.. "Output Normal"
+        *    COMD[1] "Sensor precharge voltage selection"
+        *                  =   0 (0x00) ......0. "Selects internal
+        *                                         reference precharge
+        *                                         voltage"
+        *    COMD[0] "Snapshot option"
+        *                  =   0 (0x00) .......0 "Enable live video output
+        *                                         after snapshot sequence"
+        */
+       { 0x0c, 0x08 },
+
+       /*
+        * 0D COME "Common Control E"
+        *                  = 161 (0xA1) 10100001
+        *    COME[7] "Output average option"
+        *                  =   1 (0x01) 1....... "Output average of 4 pixels"
+        *    COME[6] "Anti-blooming control"
+        *                  =   0 (0x00) .0...... "Off"
+        *    COME[5:3] "Reserved"
+        *                  =   4 (0x04) ..100...
+        *    COME[2] "Clock output power down pin status"
+        *                  =   0 (0x00) .....0.. "Tri-state data output pin
+        *                                         on power down"
+        *    COME[1] "Data output pin status selection at power down"
+        *                  =   0 (0x00) ......0. "Tri-state VSYNC, PCLK,
+        *                                         HREF, and CHSYNC pins on
+        *                                         power down"
+        *    COME[0] "Auto zero circuit select"
+        *                  =   1 (0x01) .......1 "On"
+        */
+       { 0x0d, 0xa1 },
+
+       /*
+        * 0E COMF "Common Control F"
+        *                  = 112 (0x70) 01110000
+        *    COMF[7] "System clock selection"
+        *                  =   0 (0x00) 0....... "Use 24 MHz system clock"
+        *    COMF[6:4] "Reserved"
+        *                  =   7 (0x07) .111....
+        *    COMF[3] "Manual auto negative offset canceling selection"
+        *                  =   0 (0x00) ....0... "Auto detect negative
+        *                                         offset and cancel it"
+        *    COMF[2:0] "Reserved"
+        *                  =   0 (0x00) .....000
+        */
+       { 0x0e, 0x70 },
+
+       /*
+        * 0F COMG "Common Control G"
+        *                  =  66 (0x42) 01000010
+        *    COMG[7] "Optical black output selection"
+        *                  =   0 (0x00) 0....... "Disable"
+        *    COMG[6] "Black level calibrate selection"
+        *                  =   1 (0x01) .1...... "Use optical black pixels
+        *                                         to calibrate"
+        *    COMG[5:4] "Reserved"
+        *                  =   0 (0x00) ..00....
+        *    COMG[3] "Channel offset adjustment"
+        *                  =   0 (0x00) ....0... "Disable offset adjustment"
+        *    COMG[2] "ADC black level calibration option"
+        *                  =   0 (0x00) .....0.. "Use B/G line and G/R
+        *                                         line to calibrate each
+        *                                         channel's black level"
+        *    COMG[1] "Reserved"
+        *                  =   1 (0x01) ......1.
+        *    COMG[0] "ADC black level calibration enable"
+        *                  =   0 (0x00) .......0 "Disable"
+        */
+       { 0x0f, 0x42 },
+
+       /*
+        * 14 COMJ "Common Control J"
+        *                  = 198 (0xC6) 11000110
+        *    COMJ[7:6] "AGC gain ceiling"
+        *                  =   3 (0x03) 11...... "8x"
+        *    COMJ[5:4] "Reserved"
+        *                  =   0 (0x00) ..00....
+        *    COMJ[3] "Auto banding filter"
+        *                  =   0 (0x00) ....0... "Banding filter is always
+        *                                         on off depending on
+        *                                         COMI[5] setting"
+        *    COMJ[2] "VSYNC drop option"
+        *                  =   1 (0x01) .....1.. "SYNC is dropped if frame
+        *                                         data is dropped"
+        *    COMJ[1] "Frame data drop"
+        *                  =   1 (0x01) ......1. "Drop frame data if
+        *                                         exposure is not within
+        *                                         tolerance.  In AEC mode,
+        *                                         data is normally dropped
+        *                                         when data is out of
+        *                                         range."
+        *    COMJ[0] "Reserved"
+        *                  =   0 (0x00) .......0
+        */
+       { 0x14, 0xc6 },
+
+       /*
+        * 15 COMK "Common Control K"
+        *                  =   2 (0x02) 00000010
+        *    COMK[7] "CHSYNC pin output swap"
+        *                  =   0 (0x00) 0....... "CHSYNC"
+        *    COMK[6] "HREF pin output swap"
+        *                  =   0 (0x00) .0...... "HREF"
+        *    COMK[5] "PCLK output selection"
+        *                  =   0 (0x00) ..0..... "PCLK always output"
+        *    COMK[4] "PCLK edge selection"
+        *                  =   0 (0x00) ...0.... "Data valid on falling edge"
+        *    COMK[3] "HREF output polarity"
+        *                  =   0 (0x00) ....0... "positive"
+        *    COMK[2] "Reserved"
+        *                  =   0 (0x00) .....0..
+        *    COMK[1] "VSYNC polarity"
+        *                  =   1 (0x01) ......1. "negative"
+        *    COMK[0] "HSYNC polarity"
+        *                  =   0 (0x00) .......0 "positive"
+        */
+       { 0x15, 0x02 },
+
+       /*
+        * 33 CHLF "Current Control"
+        *                  =   9 (0x09) 00001001
+        *    CHLF[7:6] "Sensor current control"
+        *                  =   0 (0x00) 00......
+        *    CHLF[5] "Sensor current range control"
+        *                  =   0 (0x00) ..0..... "normal range"
+        *    CHLF[4] "Sensor current"
+        *                  =   0 (0x00) ...0.... "normal current"
+        *    CHLF[3] "Sensor buffer current control"
+        *                  =   1 (0x01) ....1... "half current"
+        *    CHLF[2] "Column buffer current control"
+        *                  =   0 (0x00) .....0.. "normal current"
+        *    CHLF[1] "Analog DSP current control"
+        *                  =   0 (0x00) ......0. "normal current"
+        *    CHLF[1] "ADC current control"
+        *                  =   0 (0x00) ......0. "normal current"
+        */
+       { 0x33, 0x09 },
+
+       /*
+        * 34 VBLM "Blooming Control"
+        *                  =  80 (0x50) 01010000
+        *    VBLM[7] "Hard soft reset switch"
+        *                  =   0 (0x00) 0....... "Hard reset"
+        *    VBLM[6:4] "Blooming voltage selection"
+        *                  =   5 (0x05) .101....
+        *    VBLM[3:0] "Sensor current control"
+        *                  =   0 (0x00) ....0000
+        */
+       { 0x34, 0x50 },
+
+       /*
+        * 36 VCHG "Sensor Precharge Voltage Control"
+        *                  =   0 (0x00) 00000000
+        *    VCHG[7] "Reserved"
+        *                  =   0 (0x00) 0.......
+        *    VCHG[6:4] "Sensor precharge voltage control"
+        *                  =   0 (0x00) .000....
+        *    VCHG[3:0] "Sensor array common reference"
+        *                  =   0 (0x00) ....0000
+        */
+       { 0x36, 0x00 },
+
+       /*
+        * 37 ADC "ADC Reference Control"
+        *                  =   4 (0x04) 00000100
+        *    ADC[7:4] "Reserved"
+        *                  =   0 (0x00) 0000....
+        *    ADC[3] "ADC input signal range"
+        *                  =   0 (0x00) ....0... "Input signal 1.0x"
+        *    ADC[2:0] "ADC range control"
+        *                  =   4 (0x04) .....100
+        */
+       { 0x37, 0x04 },
+
+       /*
+        * 38 ACOM "Analog Common Ground"
+        *                  =  82 (0x52) 01010010
+        *    ACOM[7] "Analog gain control"
+        *                  =   0 (0x00) 0....... "Gain 1x"
+        *    ACOM[6] "Analog black level calibration"
+        *                  =   1 (0x01) .1...... "On"
+        *    ACOM[5:0] "Reserved"
+        *                  =  18 (0x12) ..010010
+        */
+       { 0x38, 0x52 },
+
+       /*
+        * 3A FREFA "Internal Reference Adjustment"
+        *                  =   0 (0x00) 00000000
+        *    FREFA[7:0] "Range"
+        *                  =   0 (0x00) 00000000
+        */
+       { 0x3a, 0x00 },
+
+       /*
+        * 3C FVOPT "Internal Reference Adjustment"
+        *                  =  31 (0x1F) 00011111
+        *    FVOPT[7:0] "Range"
+        *                  =  31 (0x1F) 00011111
+        */
+       { 0x3c, 0x1f },
+
+       /*
+        * 44 Undocumented  =   0 (0x00) 00000000
+        *    44[7:0] "It's a secret"
+        *                  =   0 (0x00) 00000000
+        */
+       { 0x44, 0x00 },
+
+       /*
+        * 40 Undocumented  =   0 (0x00) 00000000
+        *    40[7:0] "It's a secret"
+        *                  =   0 (0x00) 00000000
+        */
+       { 0x40, 0x00 },
+
+       /*
+        * 41 Undocumented  =   0 (0x00) 00000000
+        *    41[7:0] "It's a secret"
+        *                  =   0 (0x00) 00000000
+        */
+       { 0x41, 0x00 },
+
+       /*
+        * 42 Undocumented  =   0 (0x00) 00000000
+        *    42[7:0] "It's a secret"
+        *                  =   0 (0x00) 00000000
+        */
+       { 0x42, 0x00 },
+
+       /*
+        * 43 Undocumented  =   0 (0x00) 00000000
+        *    43[7:0] "It's a secret"
+        *                  =   0 (0x00) 00000000
+        */
+       { 0x43, 0x00 },
+
+       /*
+        * 45 Undocumented  = 128 (0x80) 10000000
+        *    45[7:0] "It's a secret"
+        *                  = 128 (0x80) 10000000
+        */
+       { 0x45, 0x80 },
+
+       /*
+        * 48 Undocumented  = 192 (0xC0) 11000000
+        *    48[7:0] "It's a secret"
+        *                  = 192 (0xC0) 11000000
+        */
+       { 0x48, 0xc0 },
+
+       /*
+        * 49 Undocumented  =  25 (0x19) 00011001
+        *    49[7:0] "It's a secret"
+        *                  =  25 (0x19) 00011001
+        */
+       { 0x49, 0x19 },
+
+       /*
+        * 4B Undocumented  = 128 (0x80) 10000000
+        *    4B[7:0] "It's a secret"
+        *                  = 128 (0x80) 10000000
+        */
+       { 0x4b, 0x80 },
+
+       /*
+        * 4D Undocumented  = 196 (0xC4) 11000100
+        *    4D[7:0] "It's a secret"
+        *                  = 196 (0xC4) 11000100
+        */
+       { 0x4d, 0xc4 },
+
+       /*
+        * 35 VREF "Reference Voltage Control"
+        *                  =  76 (0x4c) 01001100
+        *    VREF[7:5] "Column high reference control"
+        *                  =   2 (0x02) 010..... "higher voltage"
+        *    VREF[4:2] "Column low reference control"
+        *                  =   3 (0x03) ...011.. "Highest voltage"
+        *    VREF[1:0] "Reserved"
+        *                  =   0 (0x00) ......00
+        */
+       { 0x35, 0x4c },
+
+       /*
+        * 3D Undocumented  =   0 (0x00) 00000000
+        *    3D[7:0] "It's a secret"
+        *                  =   0 (0x00) 00000000
+        */
+       { 0x3d, 0x00 },
+
+       /*
+        * 3E Undocumented  =   0 (0x00) 00000000
+        *    3E[7:0] "It's a secret"
+        *                  =   0 (0x00) 00000000
+        */
+       { 0x3e, 0x00 },
+
+       /*
+        * 3B FREFB "Internal Reference Adjustment"
+        *                  =  24 (0x18) 00011000
+        *    FREFB[7:0] "Range"
+        *                  =  24 (0x18) 00011000
+        */
+       { 0x3b, 0x18 },
+
+       /*
+        * 33 CHLF "Current Control"
+        *                  =  25 (0x19) 00011001
+        *    CHLF[7:6] "Sensor current control"
+        *                  =   0 (0x00) 00......
+        *    CHLF[5] "Sensor current range control"
+        *                  =   0 (0x00) ..0..... "normal range"
+        *    CHLF[4] "Sensor current"
+        *                  =   1 (0x01) ...1.... "double current"
+        *    CHLF[3] "Sensor buffer current control"
+        *                  =   1 (0x01) ....1... "half current"
+        *    CHLF[2] "Column buffer current control"
+        *                  =   0 (0x00) .....0.. "normal current"
+        *    CHLF[1] "Analog DSP current control"
+        *                  =   0 (0x00) ......0. "normal current"
+        *    CHLF[1] "ADC current control"
+        *                  =   0 (0x00) ......0. "normal current"
+        */
+       { 0x33, 0x19 },
+
+       /*
+        * 34 VBLM "Blooming Control"
+        *                  =  90 (0x5A) 01011010
+        *    VBLM[7] "Hard soft reset switch"
+        *                  =   0 (0x00) 0....... "Hard reset"
+        *    VBLM[6:4] "Blooming voltage selection"
+        *                  =   5 (0x05) .101....
+        *    VBLM[3:0] "Sensor current control"
+        *                  =  10 (0x0A) ....1010
+        */
+       { 0x34, 0x5a },
+
+       /*
+        * 3B FREFB "Internal Reference Adjustment"
+        *                  =   0 (0x00) 00000000
+        *    FREFB[7:0] "Range"
+        *                  =   0 (0x00) 00000000
+        */
+       { 0x3b, 0x00 },
+
+       /*
+        * 33 CHLF "Current Control"
+        *                  =   9 (0x09) 00001001
+        *    CHLF[7:6] "Sensor current control"
+        *                  =   0 (0x00) 00......
+        *    CHLF[5] "Sensor current range control"
+        *                  =   0 (0x00) ..0..... "normal range"
+        *    CHLF[4] "Sensor current"
+        *                  =   0 (0x00) ...0.... "normal current"
+        *    CHLF[3] "Sensor buffer current control"
+        *                  =   1 (0x01) ....1... "half current"
+        *    CHLF[2] "Column buffer current control"
+        *                  =   0 (0x00) .....0.. "normal current"
+        *    CHLF[1] "Analog DSP current control"
+        *                  =   0 (0x00) ......0. "normal current"
+        *    CHLF[1] "ADC current control"
+        *                  =   0 (0x00) ......0. "normal current"
+        */
+       { 0x33, 0x09 },
+
+       /*
+        * 34 VBLM "Blooming Control"
+        *                  =  80 (0x50) 01010000
+        *    VBLM[7] "Hard soft reset switch"
+        *                  =   0 (0x00) 0....... "Hard reset"
+        *    VBLM[6:4] "Blooming voltage selection"
+        *                  =   5 (0x05) .101....
+        *    VBLM[3:0] "Sensor current control"
+        *                  =   0 (0x00) ....0000
+        */
+       { 0x34, 0x50 },
+
+       /*
+        * 12 COMH "Common Control H"
+        *                  =  64 (0x40) 01000000
+        *    COMH[7] "SRST"
+        *                  =   0 (0x00) 0....... "No-op"
+        *    COMH[6:4] "Resolution selection"
+        *                  =   4 (0x04) .100.... "XGA"
+        *    COMH[3] "Master slave selection"
+        *                  =   0 (0x00) ....0... "Master mode"
+        *    COMH[2] "Internal B/R channel option"
+        *                  =   0 (0x00) .....0.. "B/R use same channel"
+        *    COMH[1] "Color bar test pattern"
+        *                  =   0 (0x00) ......0. "Off"
+        *    COMH[0] "Reserved"
+        *                  =   0 (0x00) .......0
+        */
+       { 0x12, 0x40 },
+
+       /*
+        * 17 HREFST "Horizontal window start"
+        *                  =  31 (0x1F) 00011111
+        *    HREFST[7:0] "Horizontal window start, 8 MSBs"
+        *                  =  31 (0x1F) 00011111
+        */
+       { 0x17, 0x1f },
+
+       /*
+        * 18 HREFEND "Horizontal window end"
+        *                  =  95 (0x5F) 01011111
+        *    HREFEND[7:0] "Horizontal Window End, 8 MSBs"
+        *                  =  95 (0x5F) 01011111
+        */
+       { 0x18, 0x5f },
+
+       /*
+        * 19 VSTRT "Vertical window start"
+        *                  =   0 (0x00) 00000000
+        *    VSTRT[7:0] "Vertical Window Start, 8 MSBs"
+        *                  =   0 (0x00) 00000000
+        */
+       { 0x19, 0x00 },
+
+       /*
+        * 1A VEND "Vertical window end"
+        *                  =  96 (0x60) 01100000
+        *    VEND[7:0] "Vertical Window End, 8 MSBs"
+        *                  =  96 (0x60) 01100000
+        */
+       { 0x1a, 0x60 },
+
+       /*
+        * 32 COMM "Common Control M"
+        *                  =  18 (0x12) 00010010
+        *    COMM[7:6] "Pixel clock divide option"
+        *                  =   0 (0x00) 00...... "/1"
+        *    COMM[5:3] "Horizontal window end position, 3 LSBs"
+        *                  =   2 (0x02) ..010...
+        *    COMM[2:0] "Horizontal window start position, 3 LSBs"
+        *                  =   2 (0x02) .....010
+        */
+       { 0x32, 0x12 },
+
+       /*
+        * 03 COMA "Common Control A"
+        *                  =  74 (0x4A) 01001010
+        *    COMA[7:4] "AWB Update Threshold"
+        *                  =   4 (0x04) 0100....
+        *    COMA[3:2] "Vertical window end line control 2 LSBs"
+        *                  =   2 (0x02) ....10..
+        *    COMA[1:0] "Vertical window start line control 2 LSBs"
+        *                  =   2 (0x02) ......10
+        */
+       { 0x03, 0x4a },
+
+       /*
+        * 11 CLKRC "Clock Rate Control"
+        *                  = 128 (0x80) 10000000
+        *    CLKRC[7] "Internal frequency doublers on off seclection"
+        *                  =   1 (0x01) 1....... "On"
+        *    CLKRC[6] "Digital video master slave selection"
+        *                  =   0 (0x00) .0...... "Master mode, sensor
+        *                                         provides PCLK"
+        *    CLKRC[5:0] "Clock divider { CLK = PCLK/(1+CLKRC[5:0]) }"
+        *                  =   0 (0x00) ..000000
+        */
+       { 0x11, 0x80 },
+
+       /*
+        * 12 COMH "Common Control H"
+        *                  =   0 (0x00) 00000000
+        *    COMH[7] "SRST"
+        *                  =   0 (0x00) 0....... "No-op"
+        *    COMH[6:4] "Resolution selection"
+        *                  =   0 (0x00) .000.... "QXGA"
+        *    COMH[3] "Master slave selection"
+        *                  =   0 (0x00) ....0... "Master mode"
+        *    COMH[2] "Internal B/R channel option"
+        *                  =   0 (0x00) .....0.. "B/R use same channel"
+        *    COMH[1] "Color bar test pattern"
+        *                  =   0 (0x00) ......0. "Off"
+        *    COMH[0] "Reserved"
+        *                  =   0 (0x00) .......0
+        */
+       { 0x12, 0x00 },
+
+       /*
+        * 12 COMH "Common Control H"
+        *                  =  64 (0x40) 01000000
+        *    COMH[7] "SRST"
+        *                  =   0 (0x00) 0....... "No-op"
+        *    COMH[6:4] "Resolution selection"
+        *                  =   4 (0x04) .100.... "XGA"
+        *    COMH[3] "Master slave selection"
+        *                  =   0 (0x00) ....0... "Master mode"
+        *    COMH[2] "Internal B/R channel option"
+        *                  =   0 (0x00) .....0.. "B/R use same channel"
+        *    COMH[1] "Color bar test pattern"
+        *                  =   0 (0x00) ......0. "Off"
+        *    COMH[0] "Reserved"
+        *                  =   0 (0x00) .......0
+        */
+       { 0x12, 0x40 },
+
+       /*
+        * 17 HREFST "Horizontal window start"
+        *                  =  31 (0x1F) 00011111
+        *    HREFST[7:0] "Horizontal window start, 8 MSBs"
+        *                  =  31 (0x1F) 00011111
+        */
+       { 0x17, 0x1f },
+
+       /*
+        * 18 HREFEND "Horizontal window end"
+        *                  =  95 (0x5F) 01011111
+        *    HREFEND[7:0] "Horizontal Window End, 8 MSBs"
+        *                  =  95 (0x5F) 01011111
+        */
+       { 0x18, 0x5f },
+
+       /*
+        * 19 VSTRT "Vertical window start"
+        *                  =   0 (0x00) 00000000
+        *    VSTRT[7:0] "Vertical Window Start, 8 MSBs"
+        *                  =   0 (0x00) 00000000
+        */
+       { 0x19, 0x00 },
+
+       /*
+        * 1A VEND "Vertical window end"
+        *                  =  96 (0x60) 01100000
+        *    VEND[7:0] "Vertical Window End, 8 MSBs"
+        *                  =  96 (0x60) 01100000
+        */
+       { 0x1a, 0x60 },
+
+       /*
+        * 32 COMM "Common Control M"
+        *                  =  18 (0x12) 00010010
+        *    COMM[7:6] "Pixel clock divide option"
+        *                  =   0 (0x00) 00...... "/1"
+        *    COMM[5:3] "Horizontal window end position, 3 LSBs"
+        *                  =   2 (0x02) ..010...
+        *    COMM[2:0] "Horizontal window start position, 3 LSBs"
+        *                  =   2 (0x02) .....010
+        */
+       { 0x32, 0x12 },
+
+       /*
+        * 03 COMA "Common Control A"
+        *                  =  74 (0x4A) 01001010
+        *    COMA[7:4] "AWB Update Threshold"
+        *                  =   4 (0x04) 0100....
+        *    COMA[3:2] "Vertical window end line control 2 LSBs"
+        *                  =   2 (0x02) ....10..
+        *    COMA[1:0] "Vertical window start line control 2 LSBs"
+        *                  =   2 (0x02) ......10
+        */
+       { 0x03, 0x4a },
+
+       /*
+        * 02 RED "Red Gain Control"
+        *                  = 175 (0xAF) 10101111
+        *    RED[7] "Action"
+        *                  =   1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))"
+        *    RED[6:0] "Value"
+        *                  =  47 (0x2F) .0101111
+        */
+       { 0x02, 0xaf },
+
+       /*
+        * 2D ADDVSL "VSYNC Pulse Width"
+        *                  = 210 (0xD2) 11010010
+        *    ADDVSL[7:0] "VSYNC pulse width, LSB"
+        *                  = 210 (0xD2) 11010010
+        */
+       { 0x2d, 0xd2 },
+
+       /*
+        * 00 GAIN          =  24 (0x18) 00011000
+        *    GAIN[7:6] "Reserved"
+        *                  =   0 (0x00) 00......
+        *    GAIN[5] "Double"
+        *                  =   0 (0x00) ..0..... "False"
+        *    GAIN[4] "Double"
+        *                  =   1 (0x01) ...1.... "True"
+        *    GAIN[3:0] "Range"
+        *                  =   8 (0x08) ....1000
+        */
+       { 0x00, 0x18 },
+
+       /*
+        * 01 BLUE "Blue Gain Control"
+        *                  = 240 (0xF0) 11110000
+        *    BLUE[7] "Action"
+        *                  =   1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))"
+        *    BLUE[6:0] "Value"
+        *                  = 112 (0x70) .1110000
+        */
+       { 0x01, 0xf0 },
+
+       /*
+        * 10 AEC "Automatic Exposure Control"
+        *                  =  10 (0x0A) 00001010
+        *    AEC[7:0] "Automatic Exposure Control, 8 MSBs"
+        *                  =  10 (0x0A) 00001010
+        */
+       { 0x10, 0x0a },
+
+       { 0xe1, 0x67 },
+       { 0xe3, 0x03 },
+       { 0xe4, 0x26 },
+       { 0xe5, 0x3e },
+       { 0xf8, 0x01 },
+       { 0xff, 0x01 },
+};
+
+static const struct ov_i2c_regvals norm_6x20[] = {
+       { 0x12, 0x80 }, /* reset */
+       { 0x11, 0x01 },
+       { 0x03, 0x60 },
+       { 0x05, 0x7f }, /* For when autoadjust is off */
+       { 0x07, 0xa8 },
+       /* The ratio of 0x0c and 0x0d controls the white point */
+       { 0x0c, 0x24 },
+       { 0x0d, 0x24 },
+       { 0x0f, 0x15 }, /* COMS */
+       { 0x10, 0x75 }, /* AEC Exposure time */
+       { 0x12, 0x24 }, /* Enable AGC */
+       { 0x14, 0x04 },
+       /* 0x16: 0x06 helps frame stability with moving objects */
+       { 0x16, 0x06 },
+/*     { 0x20, 0x30 },  * Aperture correction enable */
+       { 0x26, 0xb2 }, /* BLC enable */
+       /* 0x28: 0x05 Selects RGB format if RGB on */
+       { 0x28, 0x05 },
+       { 0x2a, 0x04 }, /* Disable framerate adjust */
+/*     { 0x2b, 0xac },  * Framerate; Set 2a[7] first */
+       { 0x2d, 0x85 },
+       { 0x33, 0xa0 }, /* Color Processing Parameter */
+       { 0x34, 0xd2 }, /* Max A/D range */
+       { 0x38, 0x8b },
+       { 0x39, 0x40 },
+
+       { 0x3c, 0x39 }, /* Enable AEC mode changing */
+       { 0x3c, 0x3c }, /* Change AEC mode */
+       { 0x3c, 0x24 }, /* Disable AEC mode changing */
+
+       { 0x3d, 0x80 },
+       /* These next two registers (0x4a, 0x4b) are undocumented.
+        * They control the color balance */
+       { 0x4a, 0x80 },
+       { 0x4b, 0x80 },
+       { 0x4d, 0xd2 }, /* This reduces noise a bit */
+       { 0x4e, 0xc1 },
+       { 0x4f, 0x04 },
+/* Do 50-53 have any effect? */
+/* Toggle 0x12[2] off and on here? */
+};
+
+static const struct ov_i2c_regvals norm_6x30[] = {
+       { 0x12, 0x80 }, /* Reset */
+       { 0x00, 0x1f }, /* Gain */
+       { 0x01, 0x99 }, /* Blue gain */
+       { 0x02, 0x7c }, /* Red gain */
+       { 0x03, 0xc0 }, /* Saturation */
+       { 0x05, 0x0a }, /* Contrast */
+       { 0x06, 0x95 }, /* Brightness */
+       { 0x07, 0x2d }, /* Sharpness */
+       { 0x0c, 0x20 },
+       { 0x0d, 0x20 },
+       { 0x0e, 0xa0 }, /* Was 0x20, bit7 enables a 2x gain which we need */
+       { 0x0f, 0x05 },
+       { 0x10, 0x9a },
+       { 0x11, 0x00 }, /* Pixel clock = fastest */
+       { 0x12, 0x24 }, /* Enable AGC and AWB */
+       { 0x13, 0x21 },
+       { 0x14, 0x80 },
+       { 0x15, 0x01 },
+       { 0x16, 0x03 },
+       { 0x17, 0x38 },
+       { 0x18, 0xea },
+       { 0x19, 0x04 },
+       { 0x1a, 0x93 },
+       { 0x1b, 0x00 },
+       { 0x1e, 0xc4 },
+       { 0x1f, 0x04 },
+       { 0x20, 0x20 },
+       { 0x21, 0x10 },
+       { 0x22, 0x88 },
+       { 0x23, 0xc0 }, /* Crystal circuit power level */
+       { 0x25, 0x9a }, /* Increase AEC black ratio */
+       { 0x26, 0xb2 }, /* BLC enable */
+       { 0x27, 0xa2 },
+       { 0x28, 0x00 },
+       { 0x29, 0x00 },
+       { 0x2a, 0x84 }, /* 60 Hz power */
+       { 0x2b, 0xa8 }, /* 60 Hz power */
+       { 0x2c, 0xa0 },
+       { 0x2d, 0x95 }, /* Enable auto-brightness */
+       { 0x2e, 0x88 },
+       { 0x33, 0x26 },
+       { 0x34, 0x03 },
+       { 0x36, 0x8f },
+       { 0x37, 0x80 },
+       { 0x38, 0x83 },
+       { 0x39, 0x80 },
+       { 0x3a, 0x0f },
+       { 0x3b, 0x3c },
+       { 0x3c, 0x1a },
+       { 0x3d, 0x80 },
+       { 0x3e, 0x80 },
+       { 0x3f, 0x0e },
+       { 0x40, 0x00 }, /* White bal */
+       { 0x41, 0x00 }, /* White bal */
+       { 0x42, 0x80 },
+       { 0x43, 0x3f }, /* White bal */
+       { 0x44, 0x80 },
+       { 0x45, 0x20 },
+       { 0x46, 0x20 },
+       { 0x47, 0x80 },
+       { 0x48, 0x7f },
+       { 0x49, 0x00 },
+       { 0x4a, 0x00 },
+       { 0x4b, 0x80 },
+       { 0x4c, 0xd0 },
+       { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
+       { 0x4e, 0x40 },
+       { 0x4f, 0x07 }, /* UV avg., col. killer: max */
+       { 0x50, 0xff },
+       { 0x54, 0x23 }, /* Max AGC gain: 18dB */
+       { 0x55, 0xff },
+       { 0x56, 0x12 },
+       { 0x57, 0x81 },
+       { 0x58, 0x75 },
+       { 0x59, 0x01 }, /* AGC dark current comp.: +1 */
+       { 0x5a, 0x2c },
+       { 0x5b, 0x0f }, /* AWB chrominance levels */
+       { 0x5c, 0x10 },
+       { 0x3d, 0x80 },
+       { 0x27, 0xa6 },
+       { 0x12, 0x20 }, /* Toggle AWB */
+       { 0x12, 0x24 },
+};
+
+/* Lawrence Glaister <lg@jfm.bc.ca> reports:
+ *
+ * Register 0x0f in the 7610 has the following effects:
+ *
+ * 0x85 (AEC method 1): Best overall, good contrast range
+ * 0x45 (AEC method 2): Very overexposed
+ * 0xa5 (spec sheet default): Ok, but the black level is
+ *     shifted resulting in loss of contrast
+ * 0x05 (old driver setting): very overexposed, too much
+ *     contrast
+ */
+static const struct ov_i2c_regvals norm_7610[] = {
+       { 0x10, 0xff },
+       { 0x16, 0x06 },
+       { 0x28, 0x24 },
+       { 0x2b, 0xac },
+       { 0x12, 0x00 },
+       { 0x38, 0x81 },
+       { 0x28, 0x24 }, /* 0c */
+       { 0x0f, 0x85 }, /* lg's setting */
+       { 0x15, 0x01 },
+       { 0x20, 0x1c },
+       { 0x23, 0x2a },
+       { 0x24, 0x10 },
+       { 0x25, 0x8a },
+       { 0x26, 0xa2 },
+       { 0x27, 0xc2 },
+       { 0x2a, 0x04 },
+       { 0x2c, 0xfe },
+       { 0x2d, 0x93 },
+       { 0x30, 0x71 },
+       { 0x31, 0x60 },
+       { 0x32, 0x26 },
+       { 0x33, 0x20 },
+       { 0x34, 0x48 },
+       { 0x12, 0x24 },
+       { 0x11, 0x01 },
+       { 0x0c, 0x24 },
+       { 0x0d, 0x24 },
+};
+
+static const struct ov_i2c_regvals norm_7620[] = {
+       { 0x12, 0x80 },         /* reset */
+       { 0x00, 0x00 },         /* gain */
+       { 0x01, 0x80 },         /* blue gain */
+       { 0x02, 0x80 },         /* red gain */
+       { 0x03, 0xc0 },         /* OV7670_R03_VREF */
+       { 0x06, 0x60 },
+       { 0x07, 0x00 },
+       { 0x0c, 0x24 },
+       { 0x0c, 0x24 },
+       { 0x0d, 0x24 },
+       { 0x11, 0x01 },
+       { 0x12, 0x24 },
+       { 0x13, 0x01 },
+       { 0x14, 0x84 },
+       { 0x15, 0x01 },
+       { 0x16, 0x03 },
+       { 0x17, 0x2f },
+       { 0x18, 0xcf },
+       { 0x19, 0x06 },
+       { 0x1a, 0xf5 },
+       { 0x1b, 0x00 },
+       { 0x20, 0x18 },
+       { 0x21, 0x80 },
+       { 0x22, 0x80 },
+       { 0x23, 0x00 },
+       { 0x26, 0xa2 },
+       { 0x27, 0xea },
+       { 0x28, 0x22 }, /* Was 0x20, bit1 enables a 2x gain which we need */
+       { 0x29, 0x00 },
+       { 0x2a, 0x10 },
+       { 0x2b, 0x00 },
+       { 0x2c, 0x88 },
+       { 0x2d, 0x91 },
+       { 0x2e, 0x80 },
+       { 0x2f, 0x44 },
+       { 0x60, 0x27 },
+       { 0x61, 0x02 },
+       { 0x62, 0x5f },
+       { 0x63, 0xd5 },
+       { 0x64, 0x57 },
+       { 0x65, 0x83 },
+       { 0x66, 0x55 },
+       { 0x67, 0x92 },
+       { 0x68, 0xcf },
+       { 0x69, 0x76 },
+       { 0x6a, 0x22 },
+       { 0x6b, 0x00 },
+       { 0x6c, 0x02 },
+       { 0x6d, 0x44 },
+       { 0x6e, 0x80 },
+       { 0x6f, 0x1d },
+       { 0x70, 0x8b },
+       { 0x71, 0x00 },
+       { 0x72, 0x14 },
+       { 0x73, 0x54 },
+       { 0x74, 0x00 },
+       { 0x75, 0x8e },
+       { 0x76, 0x00 },
+       { 0x77, 0xff },
+       { 0x78, 0x80 },
+       { 0x79, 0x80 },
+       { 0x7a, 0x80 },
+       { 0x7b, 0xe2 },
+       { 0x7c, 0x00 },
+};
+
+/* 7640 and 7648. The defaults should be OK for most registers. */
+static const struct ov_i2c_regvals norm_7640[] = {
+       { 0x12, 0x80 },
+       { 0x12, 0x14 },
+};
+
+static const struct ov_regvals init_519_ov7660[] = {
+       { 0x5d, 0x03 }, /* Turn off suspend mode */
+       { 0x53, 0x9b }, /* 0x9f enables the (unused) microcontroller */
+       { 0x54, 0x0f }, /* bit2 (jpeg enable) */
+       { 0xa2, 0x20 }, /* a2-a5 are undocumented */
+       { 0xa3, 0x18 },
+       { 0xa4, 0x04 },
+       { 0xa5, 0x28 },
+       { 0x37, 0x00 }, /* SetUsbInit */
+       { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
+       /* Enable both fields, YUV Input, disable defect comp (why?) */
+       { 0x20, 0x0c }, /* 0x0d does U <-> V swap */
+       { 0x21, 0x38 },
+       { 0x22, 0x1d },
+       { 0x17, 0x50 }, /* undocumented */
+       { 0x37, 0x00 }, /* undocumented */
+       { 0x40, 0xff }, /* I2C timeout counter */
+       { 0x46, 0x00 }, /* I2C clock prescaler */
+};
+static const struct ov_i2c_regvals norm_7660[] = {
+       {OV7670_R12_COM7, OV7670_COM7_RESET},
+       {OV7670_R11_CLKRC, 0x81},
+       {0x92, 0x00},                   /* DM_LNL */
+       {0x93, 0x00},                   /* DM_LNH */
+       {0x9d, 0x4c},                   /* BD50ST */
+       {0x9e, 0x3f},                   /* BD60ST */
+       {OV7670_R3B_COM11, 0x02},
+       {OV7670_R13_COM8, 0xf5},
+       {OV7670_R10_AECH, 0x00},
+       {OV7670_R00_GAIN, 0x00},
+       {OV7670_R01_BLUE, 0x7c},
+       {OV7670_R02_RED, 0x9d},
+       {OV7670_R12_COM7, 0x00},
+       {OV7670_R04_COM1, 00},
+       {OV7670_R18_HSTOP, 0x01},
+       {OV7670_R17_HSTART, 0x13},
+       {OV7670_R32_HREF, 0x92},
+       {OV7670_R19_VSTART, 0x02},
+       {OV7670_R1A_VSTOP, 0x7a},
+       {OV7670_R03_VREF, 0x00},
+       {OV7670_R0E_COM5, 0x04},
+       {OV7670_R0F_COM6, 0x62},
+       {OV7670_R15_COM10, 0x00},
+       {0x16, 0x02},                   /* RSVD */
+       {0x1b, 0x00},                   /* PSHFT */
+       {OV7670_R1E_MVFP, 0x01},
+       {0x29, 0x3c},                   /* RSVD */
+       {0x33, 0x00},                   /* CHLF */
+       {0x34, 0x07},                   /* ARBLM */
+       {0x35, 0x84},                   /* RSVD */
+       {0x36, 0x00},                   /* RSVD */
+       {0x37, 0x04},                   /* ADC */
+       {0x39, 0x43},                   /* OFON */
+       {OV7670_R3A_TSLB, 0x00},
+       {OV7670_R3C_COM12, 0x6c},
+       {OV7670_R3D_COM13, 0x98},
+       {OV7670_R3F_EDGE, 0x23},
+       {OV7670_R40_COM15, 0xc1},
+       {OV7670_R41_COM16, 0x22},
+       {0x6b, 0x0a},                   /* DBLV */
+       {0xa1, 0x08},                   /* RSVD */
+       {0x69, 0x80},                   /* HV */
+       {0x43, 0xf0},                   /* RSVD.. */
+       {0x44, 0x10},
+       {0x45, 0x78},
+       {0x46, 0xa8},
+       {0x47, 0x60},
+       {0x48, 0x80},
+       {0x59, 0xba},
+       {0x5a, 0x9a},
+       {0x5b, 0x22},
+       {0x5c, 0xb9},
+       {0x5d, 0x9b},
+       {0x5e, 0x10},
+       {0x5f, 0xe0},
+       {0x60, 0x85},
+       {0x61, 0x60},
+       {0x9f, 0x9d},                   /* RSVD */
+       {0xa0, 0xa0},                   /* DSPC2 */
+       {0x4f, 0x60},                   /* matrix */
+       {0x50, 0x64},
+       {0x51, 0x04},
+       {0x52, 0x18},
+       {0x53, 0x3c},
+       {0x54, 0x54},
+       {0x55, 0x40},
+       {0x56, 0x40},
+       {0x57, 0x40},
+       {0x58, 0x0d},                   /* matrix sign */
+       {0x8b, 0xcc},                   /* RSVD */
+       {0x8c, 0xcc},
+       {0x8d, 0xcf},
+       {0x6c, 0x40},                   /* gamma curve */
+       {0x6d, 0xe0},
+       {0x6e, 0xa0},
+       {0x6f, 0x80},
+       {0x70, 0x70},
+       {0x71, 0x80},
+       {0x72, 0x60},
+       {0x73, 0x60},
+       {0x74, 0x50},
+       {0x75, 0x40},
+       {0x76, 0x38},
+       {0x77, 0x3c},
+       {0x78, 0x32},
+       {0x79, 0x1a},
+       {0x7a, 0x28},
+       {0x7b, 0x24},
+       {0x7c, 0x04},                   /* gamma curve */
+       {0x7d, 0x12},
+       {0x7e, 0x26},
+       {0x7f, 0x46},
+       {0x80, 0x54},
+       {0x81, 0x64},
+       {0x82, 0x70},
+       {0x83, 0x7c},
+       {0x84, 0x86},
+       {0x85, 0x8e},
+       {0x86, 0x9c},
+       {0x87, 0xab},
+       {0x88, 0xc4},
+       {0x89, 0xd1},
+       {0x8a, 0xe5},
+       {OV7670_R14_COM9, 0x1e},
+       {OV7670_R24_AEW, 0x80},
+       {OV7670_R25_AEB, 0x72},
+       {OV7670_R26_VPT, 0xb3},
+       {0x62, 0x80},                   /* LCC1 */
+       {0x63, 0x80},                   /* LCC2 */
+       {0x64, 0x06},                   /* LCC3 */
+       {0x65, 0x00},                   /* LCC4 */
+       {0x66, 0x01},                   /* LCC5 */
+       {0x94, 0x0e},                   /* RSVD.. */
+       {0x95, 0x14},
+       {OV7670_R13_COM8, OV7670_COM8_FASTAEC
+                       | OV7670_COM8_AECSTEP
+                       | OV7670_COM8_BFILT
+                       | 0x10
+                       | OV7670_COM8_AGC
+                       | OV7670_COM8_AWB
+                       | OV7670_COM8_AEC},
+       {0xa1, 0xc8}
+};
+static const struct ov_i2c_regvals norm_9600[] = {
+       {0x12, 0x80},
+       {0x0c, 0x28},
+       {0x11, 0x80},
+       {0x13, 0xb5},
+       {0x14, 0x3e},
+       {0x1b, 0x04},
+       {0x24, 0xb0},
+       {0x25, 0x90},
+       {0x26, 0x94},
+       {0x35, 0x90},
+       {0x37, 0x07},
+       {0x38, 0x08},
+       {0x01, 0x8e},
+       {0x02, 0x85}
+};
+
+/* 7670. Defaults taken from OmniVision provided data,
+*  as provided by Jonathan Corbet of OLPC              */
+static const struct ov_i2c_regvals norm_7670[] = {
+       { OV7670_R12_COM7, OV7670_COM7_RESET },
+       { OV7670_R3A_TSLB, 0x04 },              /* OV */
+       { OV7670_R12_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
+       { OV7670_R11_CLKRC, 0x01 },
+/*
+ * Set the hardware window.  These values from OV don't entirely
+ * make sense - hstop is less than hstart.  But they work...
+ */
+       { OV7670_R17_HSTART, 0x13 },
+       { OV7670_R18_HSTOP, 0x01 },
+       { OV7670_R32_HREF, 0xb6 },
+       { OV7670_R19_VSTART, 0x02 },
+       { OV7670_R1A_VSTOP, 0x7a },
+       { OV7670_R03_VREF, 0x0a },
+
+       { OV7670_R0C_COM3, 0x00 },
+       { OV7670_R3E_COM14, 0x00 },
+/* Mystery scaling numbers */
+       { 0x70, 0x3a },
+       { 0x71, 0x35 },
+       { 0x72, 0x11 },
+       { 0x73, 0xf0 },
+       { 0xa2, 0x02 },
+/*     { OV7670_R15_COM10, 0x0 }, */
+
+/* Gamma curve values */
+       { 0x7a, 0x20 },
+       { 0x7b, 0x10 },
+       { 0x7c, 0x1e },
+       { 0x7d, 0x35 },
+       { 0x7e, 0x5a },
+       { 0x7f, 0x69 },
+       { 0x80, 0x76 },
+       { 0x81, 0x80 },
+       { 0x82, 0x88 },
+       { 0x83, 0x8f },
+       { 0x84, 0x96 },
+       { 0x85, 0xa3 },
+       { 0x86, 0xaf },
+       { 0x87, 0xc4 },
+       { 0x88, 0xd7 },
+       { 0x89, 0xe8 },
+
+/* AGC and AEC parameters.  Note we start by disabling those features,
+   then turn them only after tweaking the values. */
+       { OV7670_R13_COM8, OV7670_COM8_FASTAEC
+                        | OV7670_COM8_AECSTEP
+                        | OV7670_COM8_BFILT },
+       { OV7670_R00_GAIN, 0x00 },
+       { OV7670_R10_AECH, 0x00 },
+       { OV7670_R0D_COM4, 0x40 }, /* magic reserved bit */
+       { OV7670_R14_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
+       { OV7670_RA5_BD50MAX, 0x05 },
+       { OV7670_RAB_BD60MAX, 0x07 },
+       { OV7670_R24_AEW, 0x95 },
+       { OV7670_R25_AEB, 0x33 },
+       { OV7670_R26_VPT, 0xe3 },
+       { OV7670_R9F_HAECC1, 0x78 },
+       { OV7670_RA0_HAECC2, 0x68 },
+       { 0xa1, 0x03 }, /* magic */
+       { OV7670_RA6_HAECC3, 0xd8 },
+       { OV7670_RA7_HAECC4, 0xd8 },
+       { OV7670_RA8_HAECC5, 0xf0 },
+       { OV7670_RA9_HAECC6, 0x90 },
+       { OV7670_RAA_HAECC7, 0x94 },
+       { OV7670_R13_COM8, OV7670_COM8_FASTAEC
+                       | OV7670_COM8_AECSTEP
+                       | OV7670_COM8_BFILT
+                       | OV7670_COM8_AGC
+                       | OV7670_COM8_AEC },
+
+/* Almost all of these are magic "reserved" values.  */
+       { OV7670_R0E_COM5, 0x61 },
+       { OV7670_R0F_COM6, 0x4b },
+       { 0x16, 0x02 },
+       { OV7670_R1E_MVFP, 0x07 },
+       { 0x21, 0x02 },
+       { 0x22, 0x91 },
+       { 0x29, 0x07 },
+       { 0x33, 0x0b },
+       { 0x35, 0x0b },
+       { 0x37, 0x1d },
+       { 0x38, 0x71 },
+       { 0x39, 0x2a },
+       { OV7670_R3C_COM12, 0x78 },
+       { 0x4d, 0x40 },
+       { 0x4e, 0x20 },
+       { OV7670_R69_GFIX, 0x00 },
+       { 0x6b, 0x4a },
+       { 0x74, 0x10 },
+       { 0x8d, 0x4f },
+       { 0x8e, 0x00 },
+       { 0x8f, 0x00 },
+       { 0x90, 0x00 },
+       { 0x91, 0x00 },
+       { 0x96, 0x00 },
+       { 0x9a, 0x00 },
+       { 0xb0, 0x84 },
+       { 0xb1, 0x0c },
+       { 0xb2, 0x0e },
+       { 0xb3, 0x82 },
+       { 0xb8, 0x0a },
+
+/* More reserved magic, some of which tweaks white balance */
+       { 0x43, 0x0a },
+       { 0x44, 0xf0 },
+       { 0x45, 0x34 },
+       { 0x46, 0x58 },
+       { 0x47, 0x28 },
+       { 0x48, 0x3a },
+       { 0x59, 0x88 },
+       { 0x5a, 0x88 },
+       { 0x5b, 0x44 },
+       { 0x5c, 0x67 },
+       { 0x5d, 0x49 },
+       { 0x5e, 0x0e },
+       { 0x6c, 0x0a },
+       { 0x6d, 0x55 },
+       { 0x6e, 0x11 },
+       { 0x6f, 0x9f },                 /* "9e for advance AWB" */
+       { 0x6a, 0x40 },
+       { OV7670_R01_BLUE, 0x40 },
+       { OV7670_R02_RED, 0x60 },
+       { OV7670_R13_COM8, OV7670_COM8_FASTAEC
+                       | OV7670_COM8_AECSTEP
+                       | OV7670_COM8_BFILT
+                       | OV7670_COM8_AGC
+                       | OV7670_COM8_AEC
+                       | OV7670_COM8_AWB },
+
+/* Matrix coefficients */
+       { 0x4f, 0x80 },
+       { 0x50, 0x80 },
+       { 0x51, 0x00 },
+       { 0x52, 0x22 },
+       { 0x53, 0x5e },
+       { 0x54, 0x80 },
+       { 0x58, 0x9e },
+
+       { OV7670_R41_COM16, OV7670_COM16_AWBGAIN },
+       { OV7670_R3F_EDGE, 0x00 },
+       { 0x75, 0x05 },
+       { 0x76, 0xe1 },
+       { 0x4c, 0x00 },
+       { 0x77, 0x01 },
+       { OV7670_R3D_COM13, OV7670_COM13_GAMMA
+                         | OV7670_COM13_UVSAT
+                         | 2},         /* was 3 */
+       { 0x4b, 0x09 },
+       { 0xc9, 0x60 },
+       { OV7670_R41_COM16, 0x38 },
+       { 0x56, 0x40 },
+
+       { 0x34, 0x11 },
+       { OV7670_R3B_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
+       { 0xa4, 0x88 },
+       { 0x96, 0x00 },
+       { 0x97, 0x30 },
+       { 0x98, 0x20 },
+       { 0x99, 0x30 },
+       { 0x9a, 0x84 },
+       { 0x9b, 0x29 },
+       { 0x9c, 0x03 },
+       { 0x9d, 0x4c },
+       { 0x9e, 0x3f },
+       { 0x78, 0x04 },
+
+/* Extra-weird stuff.  Some sort of multiplexor register */
+       { 0x79, 0x01 },
+       { 0xc8, 0xf0 },
+       { 0x79, 0x0f },
+       { 0xc8, 0x00 },
+       { 0x79, 0x10 },
+       { 0xc8, 0x7e },
+       { 0x79, 0x0a },
+       { 0xc8, 0x80 },
+       { 0x79, 0x0b },
+       { 0xc8, 0x01 },
+       { 0x79, 0x0c },
+       { 0xc8, 0x0f },
+       { 0x79, 0x0d },
+       { 0xc8, 0x20 },
+       { 0x79, 0x09 },
+       { 0xc8, 0x80 },
+       { 0x79, 0x02 },
+       { 0xc8, 0xc0 },
+       { 0x79, 0x03 },
+       { 0xc8, 0x40 },
+       { 0x79, 0x05 },
+       { 0xc8, 0x30 },
+       { 0x79, 0x26 },
+};
+
+static const struct ov_i2c_regvals norm_8610[] = {
+       { 0x12, 0x80 },
+       { 0x00, 0x00 },
+       { 0x01, 0x80 },
+       { 0x02, 0x80 },
+       { 0x03, 0xc0 },
+       { 0x04, 0x30 },
+       { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */
+       { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */
+       { 0x0a, 0x86 },
+       { 0x0b, 0xb0 },
+       { 0x0c, 0x20 },
+       { 0x0d, 0x20 },
+       { 0x11, 0x01 },
+       { 0x12, 0x25 },
+       { 0x13, 0x01 },
+       { 0x14, 0x04 },
+       { 0x15, 0x01 }, /* Lin and Win think different about UV order */
+       { 0x16, 0x03 },
+       { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */
+       { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */
+       { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */
+       { 0x1a, 0xf5 },
+       { 0x1b, 0x00 },
+       { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */
+       { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */
+       { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */
+       { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */
+       { 0x26, 0xa2 },
+       { 0x27, 0xea },
+       { 0x28, 0x00 },
+       { 0x29, 0x00 },
+       { 0x2a, 0x80 },
+       { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */
+       { 0x2c, 0xac },
+       { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */
+       { 0x2e, 0x80 },
+       { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */
+       { 0x4c, 0x00 },
+       { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */
+       { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */
+       { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */
+       { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */
+       { 0x63, 0xff },
+       { 0x64, 0x53 }, /* new windrv 090403 says 0x57,
+                        * maybe thats wrong */
+       { 0x65, 0x00 },
+       { 0x66, 0x55 },
+       { 0x67, 0xb0 },
+       { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */
+       { 0x69, 0x02 },
+       { 0x6a, 0x22 },
+       { 0x6b, 0x00 },
+       { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but
+                        * deleting bit7 colors the first images red */
+       { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */
+       { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */
+       { 0x6f, 0x01 },
+       { 0x70, 0x8b },
+       { 0x71, 0x00 },
+       { 0x72, 0x14 },
+       { 0x73, 0x54 },
+       { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */
+       { 0x75, 0x0e },
+       { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */
+       { 0x77, 0xff },
+       { 0x78, 0x80 },
+       { 0x79, 0x80 },
+       { 0x7a, 0x80 },
+       { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */
+       { 0x7c, 0x00 },
+       { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */
+       { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */
+       { 0x7f, 0xfb },
+       { 0x80, 0x28 },
+       { 0x81, 0x00 },
+       { 0x82, 0x23 },
+       { 0x83, 0x0b },
+       { 0x84, 0x00 },
+       { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */
+       { 0x86, 0xc9 },
+       { 0x87, 0x00 },
+       { 0x88, 0x00 },
+       { 0x89, 0x01 },
+       { 0x12, 0x20 },
+       { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */
+};
+
+static unsigned char ov7670_abs_to_sm(unsigned char v)
+{
+       if (v > 127)
+               return v & 0x7f;
+       return (128 - v) | 0x80;
+}
+
+/* Write a OV519 register */
+static void reg_w(struct sd *sd, u16 index, u16 value)
+{
+       int ret, req = 0;
+
+       if (sd->gspca_dev.usb_err < 0)
+               return;
+
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+       case BRIDGE_OV511PLUS:
+               req = 2;
+               break;
+       case BRIDGE_OVFX2:
+               req = 0x0a;
+               /* fall through */
+       case BRIDGE_W9968CF:
+               PDEBUG(D_USBO, "SET %02x %04x %04x",
+                               req, value, index);
+               ret = usb_control_msg(sd->gspca_dev.dev,
+                       usb_sndctrlpipe(sd->gspca_dev.dev, 0),
+                       req,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index, NULL, 0, 500);
+               goto leave;
+       default:
+               req = 1;
+       }
+
+       PDEBUG(D_USBO, "SET %02x 0000 %04x %02x",
+                       req, index, value);
+       sd->gspca_dev.usb_buf[0] = value;
+       ret = usb_control_msg(sd->gspca_dev.dev,
+                       usb_sndctrlpipe(sd->gspca_dev.dev, 0),
+                       req,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0, index,
+                       sd->gspca_dev.usb_buf, 1, 500);
+leave:
+       if (ret < 0) {
+               pr_err("reg_w %02x failed %d\n", index, ret);
+               sd->gspca_dev.usb_err = ret;
+               return;
+       }
+}
+
+/* Read from a OV519 register, note not valid for the w9968cf!! */
+/* returns: negative is error, pos or zero is data */
+static int reg_r(struct sd *sd, u16 index)
+{
+       int ret;
+       int req;
+
+       if (sd->gspca_dev.usb_err < 0)
+               return -1;
+
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+       case BRIDGE_OV511PLUS:
+               req = 3;
+               break;
+       case BRIDGE_OVFX2:
+               req = 0x0b;
+               break;
+       default:
+               req = 1;
+       }
+
+       ret = usb_control_msg(sd->gspca_dev.dev,
+                       usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
+                       req,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0, index, sd->gspca_dev.usb_buf, 1, 500);
+
+       if (ret >= 0) {
+               ret = sd->gspca_dev.usb_buf[0];
+               PDEBUG(D_USBI, "GET %02x 0000 %04x %02x",
+                       req, index, ret);
+       } else {
+               pr_err("reg_r %02x failed %d\n", index, ret);
+               sd->gspca_dev.usb_err = ret;
+       }
+
+       return ret;
+}
+
+/* Read 8 values from a OV519 register */
+static int reg_r8(struct sd *sd,
+                 u16 index)
+{
+       int ret;
+
+       if (sd->gspca_dev.usb_err < 0)
+               return -1;
+
+       ret = usb_control_msg(sd->gspca_dev.dev,
+                       usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
+                       1,                      /* REQ_IO */
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0, index, sd->gspca_dev.usb_buf, 8, 500);
+
+       if (ret >= 0) {
+               ret = sd->gspca_dev.usb_buf[0];
+       } else {
+               pr_err("reg_r8 %02x failed %d\n", index, ret);
+               sd->gspca_dev.usb_err = ret;
+       }
+
+       return ret;
+}
+
+/*
+ * Writes bits at positions specified by mask to an OV51x reg. Bits that are in
+ * the same position as 1's in "mask" are cleared and set to "value". Bits
+ * that are in the same position as 0's in "mask" are preserved, regardless
+ * of their respective state in "value".
+ */
+static void reg_w_mask(struct sd *sd,
+                       u16 index,
+                       u8 value,
+                       u8 mask)
+{
+       int ret;
+       u8 oldval;
+
+       if (mask != 0xff) {
+               value &= mask;                  /* Enforce mask on value */
+               ret = reg_r(sd, index);
+               if (ret < 0)
+                       return;
+
+               oldval = ret & ~mask;           /* Clear the masked bits */
+               value |= oldval;                /* Set the desired bits */
+       }
+       reg_w(sd, index, value);
+}
+
+/*
+ * Writes multiple (n) byte value to a single register. Only valid with certain
+ * registers (0x30 and 0xc4 - 0xce).
+ */
+static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
+{
+       int ret;
+
+       if (sd->gspca_dev.usb_err < 0)
+               return;
+
+       *((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value);
+
+       ret = usb_control_msg(sd->gspca_dev.dev,
+                       usb_sndctrlpipe(sd->gspca_dev.dev, 0),
+                       1 /* REG_IO */,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0, index,
+                       sd->gspca_dev.usb_buf, n, 500);
+       if (ret < 0) {
+               pr_err("reg_w32 %02x failed %d\n", index, ret);
+               sd->gspca_dev.usb_err = ret;
+       }
+}
+
+static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value)
+{
+       int rc, retries;
+
+       PDEBUG(D_USBO, "ov511_i2c_w %02x %02x", reg, value);
+
+       /* Three byte write cycle */
+       for (retries = 6; ; ) {
+               /* Select camera register */
+               reg_w(sd, R51x_I2C_SADDR_3, reg);
+
+               /* Write "value" to I2C data port of OV511 */
+               reg_w(sd, R51x_I2C_DATA, value);
+
+               /* Initiate 3-byte write cycle */
+               reg_w(sd, R511_I2C_CTL, 0x01);
+
+               do {
+                       rc = reg_r(sd, R511_I2C_CTL);
+               } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
+
+               if (rc < 0)
+                       return;
+
+               if ((rc & 2) == 0) /* Ack? */
+                       break;
+               if (--retries < 0) {
+                       PDEBUG(D_USBO, "i2c write retries exhausted");
+                       return;
+               }
+       }
+}
+
+static int ov511_i2c_r(struct sd *sd, u8 reg)
+{
+       int rc, value, retries;
+
+       /* Two byte write cycle */
+       for (retries = 6; ; ) {
+               /* Select camera register */
+               reg_w(sd, R51x_I2C_SADDR_2, reg);
+
+               /* Initiate 2-byte write cycle */
+               reg_w(sd, R511_I2C_CTL, 0x03);
+
+               do {
+                       rc = reg_r(sd, R511_I2C_CTL);
+               } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
+
+               if (rc < 0)
+                       return rc;
+
+               if ((rc & 2) == 0) /* Ack? */
+                       break;
+
+               /* I2C abort */
+               reg_w(sd, R511_I2C_CTL, 0x10);
+
+               if (--retries < 0) {
+                       PDEBUG(D_USBI, "i2c write retries exhausted");
+                       return -1;
+               }
+       }
+
+       /* Two byte read cycle */
+       for (retries = 6; ; ) {
+               /* Initiate 2-byte read cycle */
+               reg_w(sd, R511_I2C_CTL, 0x05);
+
+               do {
+                       rc = reg_r(sd, R511_I2C_CTL);
+               } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
+
+               if (rc < 0)
+                       return rc;
+
+               if ((rc & 2) == 0) /* Ack? */
+                       break;
+
+               /* I2C abort */
+               reg_w(sd, R511_I2C_CTL, 0x10);
+
+               if (--retries < 0) {
+                       PDEBUG(D_USBI, "i2c read retries exhausted");
+                       return -1;
+               }
+       }
+
+       value = reg_r(sd, R51x_I2C_DATA);
+
+       PDEBUG(D_USBI, "ov511_i2c_r %02x %02x", reg, value);
+
+       /* This is needed to make i2c_w() work */
+       reg_w(sd, R511_I2C_CTL, 0x05);
+
+       return value;
+}
+
+/*
+ * The OV518 I2C I/O procedure is different, hence, this function.
+ * This is normally only called from i2c_w(). Note that this function
+ * always succeeds regardless of whether the sensor is present and working.
+ */
+static void ov518_i2c_w(struct sd *sd,
+               u8 reg,
+               u8 value)
+{
+       PDEBUG(D_USBO, "ov518_i2c_w %02x %02x", reg, value);
+
+       /* Select camera register */
+       reg_w(sd, R51x_I2C_SADDR_3, reg);
+
+       /* Write "value" to I2C data port of OV511 */
+       reg_w(sd, R51x_I2C_DATA, value);
+
+       /* Initiate 3-byte write cycle */
+       reg_w(sd, R518_I2C_CTL, 0x01);
+
+       /* wait for write complete */
+       msleep(4);
+       reg_r8(sd, R518_I2C_CTL);
+}
+
+/*
+ * returns: negative is error, pos or zero is data
+ *
+ * The OV518 I2C I/O procedure is different, hence, this function.
+ * This is normally only called from i2c_r(). Note that this function
+ * always succeeds regardless of whether the sensor is present and working.
+ */
+static int ov518_i2c_r(struct sd *sd, u8 reg)
+{
+       int value;
+
+       /* Select camera register */
+       reg_w(sd, R51x_I2C_SADDR_2, reg);
+
+       /* Initiate 2-byte write cycle */
+       reg_w(sd, R518_I2C_CTL, 0x03);
+       reg_r8(sd, R518_I2C_CTL);
+
+       /* Initiate 2-byte read cycle */
+       reg_w(sd, R518_I2C_CTL, 0x05);
+       reg_r8(sd, R518_I2C_CTL);
+
+       value = reg_r(sd, R51x_I2C_DATA);
+       PDEBUG(D_USBI, "ov518_i2c_r %02x %02x", reg, value);
+       return value;
+}
+
+static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
+{
+       int ret;
+
+       if (sd->gspca_dev.usb_err < 0)
+               return;
+
+       ret = usb_control_msg(sd->gspca_dev.dev,
+                       usb_sndctrlpipe(sd->gspca_dev.dev, 0),
+                       0x02,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       (u16) value, (u16) reg, NULL, 0, 500);
+
+       if (ret < 0) {
+               pr_err("ovfx2_i2c_w %02x failed %d\n", reg, ret);
+               sd->gspca_dev.usb_err = ret;
+       }
+
+       PDEBUG(D_USBO, "ovfx2_i2c_w %02x %02x", reg, value);
+}
+
+static int ovfx2_i2c_r(struct sd *sd, u8 reg)
+{
+       int ret;
+
+       if (sd->gspca_dev.usb_err < 0)
+               return -1;
+
+       ret = usb_control_msg(sd->gspca_dev.dev,
+                       usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
+                       0x03,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0, (u16) reg, sd->gspca_dev.usb_buf, 1, 500);
+
+       if (ret >= 0) {
+               ret = sd->gspca_dev.usb_buf[0];
+               PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret);
+       } else {
+               pr_err("ovfx2_i2c_r %02x failed %d\n", reg, ret);
+               sd->gspca_dev.usb_err = ret;
+       }
+
+       return ret;
+}
+
+static void i2c_w(struct sd *sd, u8 reg, u8 value)
+{
+       if (sd->sensor_reg_cache[reg] == value)
+               return;
+
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+       case BRIDGE_OV511PLUS:
+               ov511_i2c_w(sd, reg, value);
+               break;
+       case BRIDGE_OV518:
+       case BRIDGE_OV518PLUS:
+       case BRIDGE_OV519:
+               ov518_i2c_w(sd, reg, value);
+               break;
+       case BRIDGE_OVFX2:
+               ovfx2_i2c_w(sd, reg, value);
+               break;
+       case BRIDGE_W9968CF:
+               w9968cf_i2c_w(sd, reg, value);
+               break;
+       }
+
+       if (sd->gspca_dev.usb_err >= 0) {
+               /* Up on sensor reset empty the register cache */
+               if (reg == 0x12 && (value & 0x80))
+                       memset(sd->sensor_reg_cache, -1,
+                               sizeof(sd->sensor_reg_cache));
+               else
+                       sd->sensor_reg_cache[reg] = value;
+       }
+}
+
+static int i2c_r(struct sd *sd, u8 reg)
+{
+       int ret = -1;
+
+       if (sd->sensor_reg_cache[reg] != -1)
+               return sd->sensor_reg_cache[reg];
+
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+       case BRIDGE_OV511PLUS:
+               ret = ov511_i2c_r(sd, reg);
+               break;
+       case BRIDGE_OV518:
+       case BRIDGE_OV518PLUS:
+       case BRIDGE_OV519:
+               ret = ov518_i2c_r(sd, reg);
+               break;
+       case BRIDGE_OVFX2:
+               ret = ovfx2_i2c_r(sd, reg);
+               break;
+       case BRIDGE_W9968CF:
+               ret = w9968cf_i2c_r(sd, reg);
+               break;
+       }
+
+       if (ret >= 0)
+               sd->sensor_reg_cache[reg] = ret;
+
+       return ret;
+}
+
+/* Writes bits at positions specified by mask to an I2C reg. Bits that are in
+ * the same position as 1's in "mask" are cleared and set to "value". Bits
+ * that are in the same position as 0's in "mask" are preserved, regardless
+ * of their respective state in "value".
+ */
+static void i2c_w_mask(struct sd *sd,
+                       u8 reg,
+                       u8 value,
+                       u8 mask)
+{
+       int rc;
+       u8 oldval;
+
+       value &= mask;                  /* Enforce mask on value */
+       rc = i2c_r(sd, reg);
+       if (rc < 0)
+               return;
+       oldval = rc & ~mask;            /* Clear the masked bits */
+       value |= oldval;                /* Set the desired bits */
+       i2c_w(sd, reg, value);
+}
+
+/* Temporarily stops OV511 from functioning. Must do this before changing
+ * registers while the camera is streaming */
+static inline void ov51x_stop(struct sd *sd)
+{
+       PDEBUG(D_STREAM, "stopping");
+       sd->stopped = 1;
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+       case BRIDGE_OV511PLUS:
+               reg_w(sd, R51x_SYS_RESET, 0x3d);
+               break;
+       case BRIDGE_OV518:
+       case BRIDGE_OV518PLUS:
+               reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a);
+               break;
+       case BRIDGE_OV519:
+               reg_w(sd, OV519_R51_RESET1, 0x0f);
+               reg_w(sd, OV519_R51_RESET1, 0x00);
+               reg_w(sd, 0x22, 0x00);          /* FRAR */
+               break;
+       case BRIDGE_OVFX2:
+               reg_w_mask(sd, 0x0f, 0x00, 0x02);
+               break;
+       case BRIDGE_W9968CF:
+               reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */
+               break;
+       }
+}
+
+/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
+ * actually stopped (for performance). */
+static inline void ov51x_restart(struct sd *sd)
+{
+       PDEBUG(D_STREAM, "restarting");
+       if (!sd->stopped)
+               return;
+       sd->stopped = 0;
+
+       /* Reinitialize the stream */
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+       case BRIDGE_OV511PLUS:
+               reg_w(sd, R51x_SYS_RESET, 0x00);
+               break;
+       case BRIDGE_OV518:
+       case BRIDGE_OV518PLUS:
+               reg_w(sd, 0x2f, 0x80);
+               reg_w(sd, R51x_SYS_RESET, 0x00);
+               break;
+       case BRIDGE_OV519:
+               reg_w(sd, OV519_R51_RESET1, 0x0f);
+               reg_w(sd, OV519_R51_RESET1, 0x00);
+               reg_w(sd, 0x22, 0x1d);          /* FRAR */
+               break;
+       case BRIDGE_OVFX2:
+               reg_w_mask(sd, 0x0f, 0x02, 0x02);
+               break;
+       case BRIDGE_W9968CF:
+               reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */
+               break;
+       }
+}
+
+static void ov51x_set_slave_ids(struct sd *sd, u8 slave);
+
+/* This does an initial reset of an OmniVision sensor and ensures that I2C
+ * is synchronized. Returns <0 on failure.
+ */
+static int init_ov_sensor(struct sd *sd, u8 slave)
+{
+       int i;
+
+       ov51x_set_slave_ids(sd, slave);
+
+       /* Reset the sensor */
+       i2c_w(sd, 0x12, 0x80);
+
+       /* Wait for it to initialize */
+       msleep(150);
+
+       for (i = 0; i < i2c_detect_tries; i++) {
+               if (i2c_r(sd, OV7610_REG_ID_HIGH) == 0x7f &&
+                   i2c_r(sd, OV7610_REG_ID_LOW) == 0xa2) {
+                       PDEBUG(D_PROBE, "I2C synced in %d attempt(s)", i);
+                       return 0;
+               }
+
+               /* Reset the sensor */
+               i2c_w(sd, 0x12, 0x80);
+
+               /* Wait for it to initialize */
+               msleep(150);
+
+               /* Dummy read to sync I2C */
+               if (i2c_r(sd, 0x00) < 0)
+                       return -1;
+       }
+       return -1;
+}
+
+/* Set the read and write slave IDs. The "slave" argument is the write slave,
+ * and the read slave will be set to (slave + 1).
+ * This should not be called from outside the i2c I/O functions.
+ * Sets I2C read and write slave IDs. Returns <0 for error
+ */
+static void ov51x_set_slave_ids(struct sd *sd,
+                               u8 slave)
+{
+       switch (sd->bridge) {
+       case BRIDGE_OVFX2:
+               reg_w(sd, OVFX2_I2C_ADDR, slave);
+               return;
+       case BRIDGE_W9968CF:
+               sd->sensor_addr = slave;
+               return;
+       }
+
+       reg_w(sd, R51x_I2C_W_SID, slave);
+       reg_w(sd, R51x_I2C_R_SID, slave + 1);
+}
+
+static void write_regvals(struct sd *sd,
+                        const struct ov_regvals *regvals,
+                        int n)
+{
+       while (--n >= 0) {
+               reg_w(sd, regvals->reg, regvals->val);
+               regvals++;
+       }
+}
+
+static void write_i2c_regvals(struct sd *sd,
+                       const struct ov_i2c_regvals *regvals,
+                       int n)
+{
+       while (--n >= 0) {
+               i2c_w(sd, regvals->reg, regvals->val);
+               regvals++;
+       }
+}
+
+/****************************************************************************
+ *
+ * OV511 and sensor configuration
+ *
+ ***************************************************************************/
+
+/* This initializes the OV2x10 / OV3610 / OV3620 / OV9600 */
+static void ov_hires_configure(struct sd *sd)
+{
+       int high, low;
+
+       if (sd->bridge != BRIDGE_OVFX2) {
+               pr_err("error hires sensors only supported with ovfx2\n");
+               return;
+       }
+
+       PDEBUG(D_PROBE, "starting ov hires configuration");
+
+       /* Detect sensor (sub)type */
+       high = i2c_r(sd, 0x0a);
+       low = i2c_r(sd, 0x0b);
+       /* info("%x, %x", high, low); */
+       switch (high) {
+       case 0x96:
+               switch (low) {
+               case 0x40:
+                       PDEBUG(D_PROBE, "Sensor is a OV2610");
+                       sd->sensor = SEN_OV2610;
+                       return;
+               case 0x41:
+                       PDEBUG(D_PROBE, "Sensor is a OV2610AE");
+                       sd->sensor = SEN_OV2610AE;
+                       return;
+               case 0xb1:
+                       PDEBUG(D_PROBE, "Sensor is a OV9600");
+                       sd->sensor = SEN_OV9600;
+                       return;
+               }
+               break;
+       case 0x36:
+               if ((low & 0x0f) == 0x00) {
+                       PDEBUG(D_PROBE, "Sensor is a OV3610");
+                       sd->sensor = SEN_OV3610;
+                       return;
+               }
+               break;
+       }
+       pr_err("Error unknown sensor type: %02x%02x\n", high, low);
+}
+
+/* This initializes the OV8110, OV8610 sensor. The OV8110 uses
+ * the same register settings as the OV8610, since they are very similar.
+ */
+static void ov8xx0_configure(struct sd *sd)
+{
+       int rc;
+
+       PDEBUG(D_PROBE, "starting ov8xx0 configuration");
+
+       /* Detect sensor (sub)type */
+       rc = i2c_r(sd, OV7610_REG_COM_I);
+       if (rc < 0) {
+               PDEBUG(D_ERR, "Error detecting sensor type");
+               return;
+       }
+       if ((rc & 3) == 1)
+               sd->sensor = SEN_OV8610;
+       else
+               pr_err("Unknown image sensor version: %d\n", rc & 3);
+}
+
+/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
+ * the same register settings as the OV7610, since they are very similar.
+ */
+static void ov7xx0_configure(struct sd *sd)
+{
+       int rc, high, low;
+
+       PDEBUG(D_PROBE, "starting OV7xx0 configuration");
+
+       /* Detect sensor (sub)type */
+       rc = i2c_r(sd, OV7610_REG_COM_I);
+
+       /* add OV7670 here
+        * it appears to be wrongly detected as a 7610 by default */
+       if (rc < 0) {
+               pr_err("Error detecting sensor type\n");
+               return;
+       }
+       if ((rc & 3) == 3) {
+               /* quick hack to make OV7670s work */
+               high = i2c_r(sd, 0x0a);
+               low = i2c_r(sd, 0x0b);
+               /* info("%x, %x", high, low); */
+               if (high == 0x76 && (low & 0xf0) == 0x70) {
+                       PDEBUG(D_PROBE, "Sensor is an OV76%02x", low);
+                       sd->sensor = SEN_OV7670;
+               } else {
+                       PDEBUG(D_PROBE, "Sensor is an OV7610");
+                       sd->sensor = SEN_OV7610;
+               }
+       } else if ((rc & 3) == 1) {
+               /* I don't know what's different about the 76BE yet. */
+               if (i2c_r(sd, 0x15) & 1) {
+                       PDEBUG(D_PROBE, "Sensor is an OV7620AE");
+                       sd->sensor = SEN_OV7620AE;
+               } else {
+                       PDEBUG(D_PROBE, "Sensor is an OV76BE");
+                       sd->sensor = SEN_OV76BE;
+               }
+       } else if ((rc & 3) == 0) {
+               /* try to read product id registers */
+               high = i2c_r(sd, 0x0a);
+               if (high < 0) {
+                       pr_err("Error detecting camera chip PID\n");
+                       return;
+               }
+               low = i2c_r(sd, 0x0b);
+               if (low < 0) {
+                       pr_err("Error detecting camera chip VER\n");
+                       return;
+               }
+               if (high == 0x76) {
+                       switch (low) {
+                       case 0x30:
+                               pr_err("Sensor is an OV7630/OV7635\n");
+                               pr_err("7630 is not supported by this driver\n");
+                               return;
+                       case 0x40:
+                               PDEBUG(D_PROBE, "Sensor is an OV7645");
+                               sd->sensor = SEN_OV7640; /* FIXME */
+                               break;
+                       case 0x45:
+                               PDEBUG(D_PROBE, "Sensor is an OV7645B");
+                               sd->sensor = SEN_OV7640; /* FIXME */
+                               break;
+                       case 0x48:
+                               PDEBUG(D_PROBE, "Sensor is an OV7648");
+                               sd->sensor = SEN_OV7648;
+                               break;
+                       case 0x60:
+                               PDEBUG(D_PROBE, "Sensor is a OV7660");
+                               sd->sensor = SEN_OV7660;
+                               break;
+                       default:
+                               pr_err("Unknown sensor: 0x76%02x\n", low);
+                               return;
+                       }
+               } else {
+                       PDEBUG(D_PROBE, "Sensor is an OV7620");
+                       sd->sensor = SEN_OV7620;
+               }
+       } else {
+               pr_err("Unknown image sensor version: %d\n", rc & 3);
+       }
+}
+
+/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
+static void ov6xx0_configure(struct sd *sd)
+{
+       int rc;
+       PDEBUG(D_PROBE, "starting OV6xx0 configuration");
+
+       /* Detect sensor (sub)type */
+       rc = i2c_r(sd, OV7610_REG_COM_I);
+       if (rc < 0) {
+               pr_err("Error detecting sensor type\n");
+               return;
+       }
+
+       /* Ugh. The first two bits are the version bits, but
+        * the entire register value must be used. I guess OVT
+        * underestimated how many variants they would make. */
+       switch (rc) {
+       case 0x00:
+               sd->sensor = SEN_OV6630;
+               pr_warn("WARNING: Sensor is an OV66308. Your camera may have been misdetected in previous driver versions.\n");
+               break;
+       case 0x01:
+               sd->sensor = SEN_OV6620;
+               PDEBUG(D_PROBE, "Sensor is an OV6620");
+               break;
+       case 0x02:
+               sd->sensor = SEN_OV6630;
+               PDEBUG(D_PROBE, "Sensor is an OV66308AE");
+               break;
+       case 0x03:
+               sd->sensor = SEN_OV66308AF;
+               PDEBUG(D_PROBE, "Sensor is an OV66308AF");
+               break;
+       case 0x90:
+               sd->sensor = SEN_OV6630;
+               pr_warn("WARNING: Sensor is an OV66307. Your camera may have been misdetected in previous driver versions.\n");
+               break;
+       default:
+               pr_err("FATAL: Unknown sensor version: 0x%02x\n", rc);
+               return;
+       }
+
+       /* Set sensor-specific vars */
+       sd->sif = 1;
+}
+
+/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
+static void ov51x_led_control(struct sd *sd, int on)
+{
+       if (sd->invert_led)
+               on = !on;
+
+       switch (sd->bridge) {
+       /* OV511 has no LED control */
+       case BRIDGE_OV511PLUS:
+               reg_w(sd, R511_SYS_LED_CTL, on);
+               break;
+       case BRIDGE_OV518:
+       case BRIDGE_OV518PLUS:
+               reg_w_mask(sd, R518_GPIO_OUT, 0x02 * on, 0x02);
+               break;
+       case BRIDGE_OV519:
+               reg_w_mask(sd, OV519_GPIO_DATA_OUT0, on, 1);
+               break;
+       }
+}
+
+static void sd_reset_snapshot(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (!sd->snapshot_needs_reset)
+               return;
+
+       /* Note it is important that we clear sd->snapshot_needs_reset,
+          before actually clearing the snapshot state in the bridge
+          otherwise we might race with the pkt_scan interrupt handler */
+       sd->snapshot_needs_reset = 0;
+
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+       case BRIDGE_OV511PLUS:
+               reg_w(sd, R51x_SYS_SNAP, 0x02);
+               reg_w(sd, R51x_SYS_SNAP, 0x00);
+               break;
+       case BRIDGE_OV518:
+       case BRIDGE_OV518PLUS:
+               reg_w(sd, R51x_SYS_SNAP, 0x02); /* Reset */
+               reg_w(sd, R51x_SYS_SNAP, 0x01); /* Enable */
+               break;
+       case BRIDGE_OV519:
+               reg_w(sd, R51x_SYS_RESET, 0x40);
+               reg_w(sd, R51x_SYS_RESET, 0x00);
+               break;
+       }
+}
+
+static void ov51x_upload_quan_tables(struct sd *sd)
+{
+       const unsigned char yQuanTable511[] = {
+               0, 1, 1, 2, 2, 3, 3, 4,
+               1, 1, 1, 2, 2, 3, 4, 4,
+               1, 1, 2, 2, 3, 4, 4, 4,
+               2, 2, 2, 3, 4, 4, 4, 4,
+               2, 2, 3, 4, 4, 5, 5, 5,
+               3, 3, 4, 4, 5, 5, 5, 5,
+               3, 4, 4, 4, 5, 5, 5, 5,
+               4, 4, 4, 4, 5, 5, 5, 5
+       };
+
+       const unsigned char uvQuanTable511[] = {
+               0, 2, 2, 3, 4, 4, 4, 4,
+               2, 2, 2, 4, 4, 4, 4, 4,
+               2, 2, 3, 4, 4, 4, 4, 4,
+               3, 4, 4, 4, 4, 4, 4, 4,
+               4, 4, 4, 4, 4, 4, 4, 4,
+               4, 4, 4, 4, 4, 4, 4, 4,
+               4, 4, 4, 4, 4, 4, 4, 4,
+               4, 4, 4, 4, 4, 4, 4, 4
+       };
+
+       /* OV518 quantization tables are 8x4 (instead of 8x8) */
+       const unsigned char yQuanTable518[] = {
+               5, 4, 5, 6, 6, 7, 7, 7,
+               5, 5, 5, 5, 6, 7, 7, 7,
+               6, 6, 6, 6, 7, 7, 7, 8,
+               7, 7, 6, 7, 7, 7, 8, 8
+       };
+       const unsigned char uvQuanTable518[] = {
+               6, 6, 6, 7, 7, 7, 7, 7,
+               6, 6, 6, 7, 7, 7, 7, 7,
+               6, 6, 6, 7, 7, 7, 7, 8,
+               7, 7, 7, 7, 7, 7, 8, 8
+       };
+
+       const unsigned char *pYTable, *pUVTable;
+       unsigned char val0, val1;
+       int i, size, reg = R51x_COMP_LUT_BEGIN;
+
+       PDEBUG(D_PROBE, "Uploading quantization tables");
+
+       if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) {
+               pYTable = yQuanTable511;
+               pUVTable = uvQuanTable511;
+               size = 32;
+       } else {
+               pYTable = yQuanTable518;
+               pUVTable = uvQuanTable518;
+               size = 16;
+       }
+
+       for (i = 0; i < size; i++) {
+               val0 = *pYTable++;
+               val1 = *pYTable++;
+               val0 &= 0x0f;
+               val1 &= 0x0f;
+               val0 |= val1 << 4;
+               reg_w(sd, reg, val0);
+
+               val0 = *pUVTable++;
+               val1 = *pUVTable++;
+               val0 &= 0x0f;
+               val1 &= 0x0f;
+               val0 |= val1 << 4;
+               reg_w(sd, reg + size, val0);
+
+               reg++;
+       }
+}
+
+/* This initializes the OV511/OV511+ and the sensor */
+static void ov511_configure(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* For 511 and 511+ */
+       const struct ov_regvals init_511[] = {
+               { R51x_SYS_RESET,       0x7f },
+               { R51x_SYS_INIT,        0x01 },
+               { R51x_SYS_RESET,       0x7f },
+               { R51x_SYS_INIT,        0x01 },
+               { R51x_SYS_RESET,       0x3f },
+               { R51x_SYS_INIT,        0x01 },
+               { R51x_SYS_RESET,       0x3d },
+       };
+
+       const struct ov_regvals norm_511[] = {
+               { R511_DRAM_FLOW_CTL,   0x01 },
+               { R51x_SYS_SNAP,        0x00 },
+               { R51x_SYS_SNAP,        0x02 },
+               { R51x_SYS_SNAP,        0x00 },
+               { R511_FIFO_OPTS,       0x1f },
+               { R511_COMP_EN,         0x00 },
+               { R511_COMP_LUT_EN,     0x03 },
+       };
+
+       const struct ov_regvals norm_511_p[] = {
+               { R511_DRAM_FLOW_CTL,   0xff },
+               { R51x_SYS_SNAP,        0x00 },
+               { R51x_SYS_SNAP,        0x02 },
+               { R51x_SYS_SNAP,        0x00 },
+               { R511_FIFO_OPTS,       0xff },
+               { R511_COMP_EN,         0x00 },
+               { R511_COMP_LUT_EN,     0x03 },
+       };
+
+       const struct ov_regvals compress_511[] = {
+               { 0x70, 0x1f },
+               { 0x71, 0x05 },
+               { 0x72, 0x06 },
+               { 0x73, 0x06 },
+               { 0x74, 0x14 },
+               { 0x75, 0x03 },
+               { 0x76, 0x04 },
+               { 0x77, 0x04 },
+       };
+
+       PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID));
+
+       write_regvals(sd, init_511, ARRAY_SIZE(init_511));
+
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+               write_regvals(sd, norm_511, ARRAY_SIZE(norm_511));
+               break;
+       case BRIDGE_OV511PLUS:
+               write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p));
+               break;
+       }
+
+       /* Init compression */
+       write_regvals(sd, compress_511, ARRAY_SIZE(compress_511));
+
+       ov51x_upload_quan_tables(sd);
+}
+
+/* This initializes the OV518/OV518+ and the sensor */
+static void ov518_configure(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* For 518 and 518+ */
+       const struct ov_regvals init_518[] = {
+               { R51x_SYS_RESET,       0x40 },
+               { R51x_SYS_INIT,        0xe1 },
+               { R51x_SYS_RESET,       0x3e },
+               { R51x_SYS_INIT,        0xe1 },
+               { R51x_SYS_RESET,       0x00 },
+               { R51x_SYS_INIT,        0xe1 },
+               { 0x46,                 0x00 },
+               { 0x5d,                 0x03 },
+       };
+
+       const struct ov_regvals norm_518[] = {
+               { R51x_SYS_SNAP,        0x02 }, /* Reset */
+               { R51x_SYS_SNAP,        0x01 }, /* Enable */
+               { 0x31,                 0x0f },
+               { 0x5d,                 0x03 },
+               { 0x24,                 0x9f },
+               { 0x25,                 0x90 },
+               { 0x20,                 0x00 },
+               { 0x51,                 0x04 },
+               { 0x71,                 0x19 },
+               { 0x2f,                 0x80 },
+       };
+
+       const struct ov_regvals norm_518_p[] = {
+               { R51x_SYS_SNAP,        0x02 }, /* Reset */
+               { R51x_SYS_SNAP,        0x01 }, /* Enable */
+               { 0x31,                 0x0f },
+               { 0x5d,                 0x03 },
+               { 0x24,                 0x9f },
+               { 0x25,                 0x90 },
+               { 0x20,                 0x60 },
+               { 0x51,                 0x02 },
+               { 0x71,                 0x19 },
+               { 0x40,                 0xff },
+               { 0x41,                 0x42 },
+               { 0x46,                 0x00 },
+               { 0x33,                 0x04 },
+               { 0x21,                 0x19 },
+               { 0x3f,                 0x10 },
+               { 0x2f,                 0x80 },
+       };
+
+       /* First 5 bits of custom ID reg are a revision ID on OV518 */
+       PDEBUG(D_PROBE, "Device revision %d",
+               0x1f & reg_r(sd, R51x_SYS_CUST_ID));
+
+       write_regvals(sd, init_518, ARRAY_SIZE(init_518));
+
+       /* Set LED GPIO pin to output mode */
+       reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02);
+
+       switch (sd->bridge) {
+       case BRIDGE_OV518:
+               write_regvals(sd, norm_518, ARRAY_SIZE(norm_518));
+               break;
+       case BRIDGE_OV518PLUS:
+               write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p));
+               break;
+       }
+
+       ov51x_upload_quan_tables(sd);
+
+       reg_w(sd, 0x2f, 0x80);
+}
+
+static void ov519_configure(struct sd *sd)
+{
+       static const struct ov_regvals init_519[] = {
+               { 0x5a, 0x6d }, /* EnableSystem */
+               { 0x53, 0x9b }, /* don't enable the microcontroller */
+               { OV519_R54_EN_CLK1, 0xff }, /* set bit2 to enable jpeg */
+               { 0x5d, 0x03 },
+               { 0x49, 0x01 },
+               { 0x48, 0x00 },
+               /* Set LED pin to output mode. Bit 4 must be cleared or sensor
+                * detection will fail. This deserves further investigation. */
+               { OV519_GPIO_IO_CTRL0,   0xee },
+               { OV519_R51_RESET1, 0x0f },
+               { OV519_R51_RESET1, 0x00 },
+               { 0x22, 0x00 },
+               /* windows reads 0x55 at this point*/
+       };
+
+       write_regvals(sd, init_519, ARRAY_SIZE(init_519));
+}
+
+static void ovfx2_configure(struct sd *sd)
+{
+       static const struct ov_regvals init_fx2[] = {
+               { 0x00, 0x60 },
+               { 0x02, 0x01 },
+               { 0x0f, 0x1d },
+               { 0xe9, 0x82 },
+               { 0xea, 0xc7 },
+               { 0xeb, 0x10 },
+               { 0xec, 0xf6 },
+       };
+
+       sd->stopped = 1;
+
+       write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2));
+}
+
+/* set the mode */
+/* This function works for ov7660 only */
+static void ov519_set_mode(struct sd *sd)
+{
+       static const struct ov_regvals bridge_ov7660[2][10] = {
+               {{0x10, 0x14}, {0x11, 0x1e}, {0x12, 0x00}, {0x13, 0x00},
+                {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c},
+                {0x25, 0x01}, {0x26, 0x00}},
+               {{0x10, 0x28}, {0x11, 0x3c}, {0x12, 0x00}, {0x13, 0x00},
+                {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c},
+                {0x25, 0x03}, {0x26, 0x00}}
+       };
+       static const struct ov_i2c_regvals sensor_ov7660[2][3] = {
+               {{0x12, 0x00}, {0x24, 0x00}, {0x0c, 0x0c}},
+               {{0x12, 0x00}, {0x04, 0x00}, {0x0c, 0x00}}
+       };
+       static const struct ov_i2c_regvals sensor_ov7660_2[] = {
+               {OV7670_R17_HSTART, 0x13},
+               {OV7670_R18_HSTOP, 0x01},
+               {OV7670_R32_HREF, 0x92},
+               {OV7670_R19_VSTART, 0x02},
+               {OV7670_R1A_VSTOP, 0x7a},
+               {OV7670_R03_VREF, 0x00},
+/*             {0x33, 0x00}, */
+/*             {0x34, 0x07}, */
+/*             {0x36, 0x00}, */
+/*             {0x6b, 0x0a}, */
+       };
+
+       write_regvals(sd, bridge_ov7660[sd->gspca_dev.curr_mode],
+                       ARRAY_SIZE(bridge_ov7660[0]));
+       write_i2c_regvals(sd, sensor_ov7660[sd->gspca_dev.curr_mode],
+                       ARRAY_SIZE(sensor_ov7660[0]));
+       write_i2c_regvals(sd, sensor_ov7660_2,
+                       ARRAY_SIZE(sensor_ov7660_2));
+}
+
+/* set the frame rate */
+/* This function works for sensors ov7640, ov7648 ov7660 and ov7670 only */
+static void ov519_set_fr(struct sd *sd)
+{
+       int fr;
+       u8 clock;
+       /* frame rate table with indices:
+        *      - mode = 0: 320x240, 1: 640x480
+        *      - fr rate = 0: 30, 1: 25, 2: 20, 3: 15, 4: 10, 5: 5
+        *      - reg = 0: bridge a4, 1: bridge 23, 2: sensor 11 (clock)
+        */
+       static const u8 fr_tb[2][6][3] = {
+               {{0x04, 0xff, 0x00},
+                {0x04, 0x1f, 0x00},
+                {0x04, 0x1b, 0x00},
+                {0x04, 0x15, 0x00},
+                {0x04, 0x09, 0x00},
+                {0x04, 0x01, 0x00}},
+               {{0x0c, 0xff, 0x00},
+                {0x0c, 0x1f, 0x00},
+                {0x0c, 0x1b, 0x00},
+                {0x04, 0xff, 0x01},
+                {0x04, 0x1f, 0x01},
+                {0x04, 0x1b, 0x01}},
+       };
+
+       if (frame_rate > 0)
+               sd->frame_rate = frame_rate;
+       if (sd->frame_rate >= 30)
+               fr = 0;
+       else if (sd->frame_rate >= 25)
+               fr = 1;
+       else if (sd->frame_rate >= 20)
+               fr = 2;
+       else if (sd->frame_rate >= 15)
+               fr = 3;
+       else if (sd->frame_rate >= 10)
+               fr = 4;
+       else
+               fr = 5;
+       reg_w(sd, 0xa4, fr_tb[sd->gspca_dev.curr_mode][fr][0]);
+       reg_w(sd, 0x23, fr_tb[sd->gspca_dev.curr_mode][fr][1]);
+       clock = fr_tb[sd->gspca_dev.curr_mode][fr][2];
+       if (sd->sensor == SEN_OV7660)
+               clock |= 0x80;          /* enable double clock */
+       ov518_i2c_w(sd, OV7670_R11_CLKRC, clock);
+}
+
+static void setautogain(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       i2c_w_mask(sd, 0x13, val ? 0x05 : 0x00, 0x05);
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam = &gspca_dev->cam;
+
+       sd->bridge = id->driver_info & BRIDGE_MASK;
+       sd->invert_led = (id->driver_info & BRIDGE_INVERT_LED) != 0;
+
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+       case BRIDGE_OV511PLUS:
+               cam->cam_mode = ov511_vga_mode;
+               cam->nmodes = ARRAY_SIZE(ov511_vga_mode);
+               break;
+       case BRIDGE_OV518:
+       case BRIDGE_OV518PLUS:
+               cam->cam_mode = ov518_vga_mode;
+               cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
+               break;
+       case BRIDGE_OV519:
+               cam->cam_mode = ov519_vga_mode;
+               cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
+               break;
+       case BRIDGE_OVFX2:
+               cam->cam_mode = ov519_vga_mode;
+               cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
+               cam->bulk_size = OVFX2_BULK_SIZE;
+               cam->bulk_nurbs = MAX_NURBS;
+               cam->bulk = 1;
+               break;
+       case BRIDGE_W9968CF:
+               cam->cam_mode = w9968cf_vga_mode;
+               cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
+               break;
+       }
+
+       sd->frame_rate = 15;
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam = &gspca_dev->cam;
+
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+       case BRIDGE_OV511PLUS:
+               ov511_configure(gspca_dev);
+               break;
+       case BRIDGE_OV518:
+       case BRIDGE_OV518PLUS:
+               ov518_configure(gspca_dev);
+               break;
+       case BRIDGE_OV519:
+               ov519_configure(sd);
+               break;
+       case BRIDGE_OVFX2:
+               ovfx2_configure(sd);
+               break;
+       case BRIDGE_W9968CF:
+               w9968cf_configure(sd);
+               break;
+       }
+
+       /* The OV519 must be more aggressive about sensor detection since
+        * I2C write will never fail if the sensor is not present. We have
+        * to try to initialize the sensor to detect its presence */
+       sd->sensor = -1;
+
+       /* Test for 76xx */
+       if (init_ov_sensor(sd, OV7xx0_SID) >= 0) {
+               ov7xx0_configure(sd);
+
+       /* Test for 6xx0 */
+       } else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) {
+               ov6xx0_configure(sd);
+
+       /* Test for 8xx0 */
+       } else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) {
+               ov8xx0_configure(sd);
+
+       /* Test for 3xxx / 2xxx */
+       } else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) {
+               ov_hires_configure(sd);
+       } else {
+               pr_err("Can't determine sensor slave IDs\n");
+               goto error;
+       }
+
+       if (sd->sensor < 0)
+               goto error;
+
+       ov51x_led_control(sd, 0);       /* turn LED off */
+
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+       case BRIDGE_OV511PLUS:
+               if (sd->sif) {
+                       cam->cam_mode = ov511_sif_mode;
+                       cam->nmodes = ARRAY_SIZE(ov511_sif_mode);
+               }
+               break;
+       case BRIDGE_OV518:
+       case BRIDGE_OV518PLUS:
+               if (sd->sif) {
+                       cam->cam_mode = ov518_sif_mode;
+                       cam->nmodes = ARRAY_SIZE(ov518_sif_mode);
+               }
+               break;
+       case BRIDGE_OV519:
+               if (sd->sif) {
+                       cam->cam_mode = ov519_sif_mode;
+                       cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
+               }
+               break;
+       case BRIDGE_OVFX2:
+               switch (sd->sensor) {
+               case SEN_OV2610:
+               case SEN_OV2610AE:
+                       cam->cam_mode = ovfx2_ov2610_mode;
+                       cam->nmodes = ARRAY_SIZE(ovfx2_ov2610_mode);
+                       break;
+               case SEN_OV3610:
+                       cam->cam_mode = ovfx2_ov3610_mode;
+                       cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode);
+                       break;
+               case SEN_OV9600:
+                       cam->cam_mode = ovfx2_ov9600_mode;
+                       cam->nmodes = ARRAY_SIZE(ovfx2_ov9600_mode);
+                       break;
+               default:
+                       if (sd->sif) {
+                               cam->cam_mode = ov519_sif_mode;
+                               cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
+                       }
+                       break;
+               }
+               break;
+       case BRIDGE_W9968CF:
+               if (sd->sif)
+                       cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode) - 1;
+
+               /* w9968cf needs initialisation once the sensor is known */
+               w9968cf_init(sd);
+               break;
+       }
+
+       /* initialize the sensor */
+       switch (sd->sensor) {
+       case SEN_OV2610:
+               write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610));
+
+               /* Enable autogain, autoexpo, awb, bandfilter */
+               i2c_w_mask(sd, 0x13, 0x27, 0x27);
+               break;
+       case SEN_OV2610AE:
+               write_i2c_regvals(sd, norm_2610ae, ARRAY_SIZE(norm_2610ae));
+
+               /* enable autoexpo */
+               i2c_w_mask(sd, 0x13, 0x05, 0x05);
+               break;
+       case SEN_OV3610:
+               write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b));
+
+               /* Enable autogain, autoexpo, awb, bandfilter */
+               i2c_w_mask(sd, 0x13, 0x27, 0x27);
+               break;
+       case SEN_OV6620:
+               write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20));
+               break;
+       case SEN_OV6630:
+       case SEN_OV66308AF:
+               write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30));
+               break;
+       default:
+/*     case SEN_OV7610: */
+/*     case SEN_OV76BE: */
+               write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610));
+               i2c_w_mask(sd, 0x0e, 0x00, 0x40);
+               break;
+       case SEN_OV7620:
+       case SEN_OV7620AE:
+               write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620));
+               break;
+       case SEN_OV7640:
+       case SEN_OV7648:
+               write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640));
+               break;
+       case SEN_OV7660:
+               i2c_w(sd, OV7670_R12_COM7, OV7670_COM7_RESET);
+               msleep(14);
+               reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
+               write_regvals(sd, init_519_ov7660,
+                               ARRAY_SIZE(init_519_ov7660));
+               write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660));
+               sd->gspca_dev.curr_mode = 1;    /* 640x480 */
+               ov519_set_mode(sd);
+               ov519_set_fr(sd);
+               sd_reset_snapshot(gspca_dev);
+               ov51x_restart(sd);
+               ov51x_stop(sd);                 /* not in win traces */
+               ov51x_led_control(sd, 0);
+               break;
+       case SEN_OV7670:
+               write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670));
+               break;
+       case SEN_OV8610:
+               write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610));
+               break;
+       case SEN_OV9600:
+               write_i2c_regvals(sd, norm_9600, ARRAY_SIZE(norm_9600));
+
+               /* enable autoexpo */
+/*             i2c_w_mask(sd, 0x13, 0x05, 0x05); */
+               break;
+       }
+       return gspca_dev->usb_err;
+error:
+       PDEBUG(D_ERR, "OV519 Config failed");
+       return -EINVAL;
+}
+
+/* function called at start time before URB creation */
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->bridge) {
+       case BRIDGE_OVFX2:
+               if (gspca_dev->width != 800)
+                       gspca_dev->cam.bulk_size = OVFX2_BULK_SIZE;
+               else
+                       gspca_dev->cam.bulk_size = 7 * 4096;
+               break;
+       }
+       return 0;
+}
+
+/* Set up the OV511/OV511+ with the given image parameters.
+ *
+ * Do not put any sensor-specific code in here (including I2C I/O functions)
+ */
+static void ov511_mode_init_regs(struct sd *sd)
+{
+       int hsegs, vsegs, packet_size, fps, needed;
+       int interlaced = 0;
+       struct usb_host_interface *alt;
+       struct usb_interface *intf;
+
+       intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+       alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+       if (!alt) {
+               pr_err("Couldn't get altsetting\n");
+               sd->gspca_dev.usb_err = -EIO;
+               return;
+       }
+
+       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+       reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5);
+
+       reg_w(sd, R511_CAM_UV_EN, 0x01);
+       reg_w(sd, R511_SNAP_UV_EN, 0x01);
+       reg_w(sd, R511_SNAP_OPTS, 0x03);
+
+       /* Here I'm assuming that snapshot size == image size.
+        * I hope that's always true. --claudio
+        */
+       hsegs = (sd->gspca_dev.width >> 3) - 1;
+       vsegs = (sd->gspca_dev.height >> 3) - 1;
+
+       reg_w(sd, R511_CAM_PXCNT, hsegs);
+       reg_w(sd, R511_CAM_LNCNT, vsegs);
+       reg_w(sd, R511_CAM_PXDIV, 0x00);
+       reg_w(sd, R511_CAM_LNDIV, 0x00);
+
+       /* YUV420, low pass filter on */
+       reg_w(sd, R511_CAM_OPTS, 0x03);
+
+       /* Snapshot additions */
+       reg_w(sd, R511_SNAP_PXCNT, hsegs);
+       reg_w(sd, R511_SNAP_LNCNT, vsegs);
+       reg_w(sd, R511_SNAP_PXDIV, 0x00);
+       reg_w(sd, R511_SNAP_LNDIV, 0x00);
+
+       /******** Set the framerate ********/
+       if (frame_rate > 0)
+               sd->frame_rate = frame_rate;
+
+       switch (sd->sensor) {
+       case SEN_OV6620:
+               /* No framerate control, doesn't like higher rates yet */
+               sd->clockdiv = 3;
+               break;
+
+       /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed
+          for more sensors we need to do this for them too */
+       case SEN_OV7620:
+       case SEN_OV7620AE:
+       case SEN_OV7640:
+       case SEN_OV7648:
+       case SEN_OV76BE:
+               if (sd->gspca_dev.width == 320)
+                       interlaced = 1;
+               /* Fall through */
+       case SEN_OV6630:
+       case SEN_OV7610:
+       case SEN_OV7670:
+               switch (sd->frame_rate) {
+               case 30:
+               case 25:
+                       /* Not enough bandwidth to do 640x480 @ 30 fps */
+                       if (sd->gspca_dev.width != 640) {
+                               sd->clockdiv = 0;
+                               break;
+                       }
+                       /* Fall through for 640x480 case */
+               default:
+/*             case 20: */
+/*             case 15: */
+                       sd->clockdiv = 1;
+                       break;
+               case 10:
+                       sd->clockdiv = 2;
+                       break;
+               case 5:
+                       sd->clockdiv = 5;
+                       break;
+               }
+               if (interlaced) {
+                       sd->clockdiv = (sd->clockdiv + 1) * 2 - 1;
+                       /* Higher then 10 does not work */
+                       if (sd->clockdiv > 10)
+                               sd->clockdiv = 10;
+               }
+               break;
+
+       case SEN_OV8610:
+               /* No framerate control ?? */
+               sd->clockdiv = 0;
+               break;
+       }
+
+       /* Check if we have enough bandwidth to disable compression */
+       fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1;
+       needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2;
+       /* 1000 isoc packets/sec */
+       if (needed > 1000 * packet_size) {
+               /* Enable Y and UV quantization and compression */
+               reg_w(sd, R511_COMP_EN, 0x07);
+               reg_w(sd, R511_COMP_LUT_EN, 0x03);
+       } else {
+               reg_w(sd, R511_COMP_EN, 0x06);
+               reg_w(sd, R511_COMP_LUT_EN, 0x00);
+       }
+
+       reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE);
+       reg_w(sd, R51x_SYS_RESET, 0);
+}
+
+/* Sets up the OV518/OV518+ with the given image parameters
+ *
+ * OV518 needs a completely different approach, until we can figure out what
+ * the individual registers do. Also, only 15 FPS is supported now.
+ *
+ * Do not put any sensor-specific code in here (including I2C I/O functions)
+ */
+static void ov518_mode_init_regs(struct sd *sd)
+{
+       int hsegs, vsegs, packet_size;
+       struct usb_host_interface *alt;
+       struct usb_interface *intf;
+
+       intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+       alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+       if (!alt) {
+               pr_err("Couldn't get altsetting\n");
+               sd->gspca_dev.usb_err = -EIO;
+               return;
+       }
+
+       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+       ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2);
+
+       /******** Set the mode ********/
+       reg_w(sd, 0x2b, 0);
+       reg_w(sd, 0x2c, 0);
+       reg_w(sd, 0x2d, 0);
+       reg_w(sd, 0x2e, 0);
+       reg_w(sd, 0x3b, 0);
+       reg_w(sd, 0x3c, 0);
+       reg_w(sd, 0x3d, 0);
+       reg_w(sd, 0x3e, 0);
+
+       if (sd->bridge == BRIDGE_OV518) {
+               /* Set 8-bit (YVYU) input format */
+               reg_w_mask(sd, 0x20, 0x08, 0x08);
+
+               /* Set 12-bit (4:2:0) output format */
+               reg_w_mask(sd, 0x28, 0x80, 0xf0);
+               reg_w_mask(sd, 0x38, 0x80, 0xf0);
+       } else {
+               reg_w(sd, 0x28, 0x80);
+               reg_w(sd, 0x38, 0x80);
+       }
+
+       hsegs = sd->gspca_dev.width / 16;
+       vsegs = sd->gspca_dev.height / 4;
+
+       reg_w(sd, 0x29, hsegs);
+       reg_w(sd, 0x2a, vsegs);
+
+       reg_w(sd, 0x39, hsegs);
+       reg_w(sd, 0x3a, vsegs);
+
+       /* Windows driver does this here; who knows why */
+       reg_w(sd, 0x2f, 0x80);
+
+       /******** Set the framerate ********/
+       sd->clockdiv = 1;
+
+       /* Mode independent, but framerate dependent, regs */
+       /* 0x51: Clock divider; Only works on some cams which use 2 crystals */
+       reg_w(sd, 0x51, 0x04);
+       reg_w(sd, 0x22, 0x18);
+       reg_w(sd, 0x23, 0xff);
+
+       if (sd->bridge == BRIDGE_OV518PLUS) {
+               switch (sd->sensor) {
+               case SEN_OV7620AE:
+                       if (sd->gspca_dev.width == 320) {
+                               reg_w(sd, 0x20, 0x00);
+                               reg_w(sd, 0x21, 0x19);
+                       } else {
+                               reg_w(sd, 0x20, 0x60);
+                               reg_w(sd, 0x21, 0x1f);
+                       }
+                       break;
+               case SEN_OV7620:
+                       reg_w(sd, 0x20, 0x00);
+                       reg_w(sd, 0x21, 0x19);
+                       break;
+               default:
+                       reg_w(sd, 0x21, 0x19);
+               }
+       } else
+               reg_w(sd, 0x71, 0x17);  /* Compression-related? */
+
+       /* FIXME: Sensor-specific */
+       /* Bit 5 is what matters here. Of course, it is "reserved" */
+       i2c_w(sd, 0x54, 0x23);
+
+       reg_w(sd, 0x2f, 0x80);
+
+       if (sd->bridge == BRIDGE_OV518PLUS) {
+               reg_w(sd, 0x24, 0x94);
+               reg_w(sd, 0x25, 0x90);
+               ov518_reg_w32(sd, 0xc4,    400, 2);     /* 190h   */
+               ov518_reg_w32(sd, 0xc6,    540, 2);     /* 21ch   */
+               ov518_reg_w32(sd, 0xc7,    540, 2);     /* 21ch   */
+               ov518_reg_w32(sd, 0xc8,    108, 2);     /* 6ch    */
+               ov518_reg_w32(sd, 0xca, 131098, 3);     /* 2001ah */
+               ov518_reg_w32(sd, 0xcb,    532, 2);     /* 214h   */
+               ov518_reg_w32(sd, 0xcc,   2400, 2);     /* 960h   */
+               ov518_reg_w32(sd, 0xcd,     32, 2);     /* 20h    */
+               ov518_reg_w32(sd, 0xce,    608, 2);     /* 260h   */
+       } else {
+               reg_w(sd, 0x24, 0x9f);
+               reg_w(sd, 0x25, 0x90);
+               ov518_reg_w32(sd, 0xc4,    400, 2);     /* 190h   */
+               ov518_reg_w32(sd, 0xc6,    381, 2);     /* 17dh   */
+               ov518_reg_w32(sd, 0xc7,    381, 2);     /* 17dh   */
+               ov518_reg_w32(sd, 0xc8,    128, 2);     /* 80h    */
+               ov518_reg_w32(sd, 0xca, 183331, 3);     /* 2cc23h */
+               ov518_reg_w32(sd, 0xcb,    746, 2);     /* 2eah   */
+               ov518_reg_w32(sd, 0xcc,   1750, 2);     /* 6d6h   */
+               ov518_reg_w32(sd, 0xcd,     45, 2);     /* 2dh    */
+               ov518_reg_w32(sd, 0xce,    851, 2);     /* 353h   */
+       }
+
+       reg_w(sd, 0x2f, 0x80);
+}
+
+/* Sets up the OV519 with the given image parameters
+ *
+ * OV519 needs a completely different approach, until we can figure out what
+ * the individual registers do.
+ *
+ * Do not put any sensor-specific code in here (including I2C I/O functions)
+ */
+static void ov519_mode_init_regs(struct sd *sd)
+{
+       static const struct ov_regvals mode_init_519_ov7670[] = {
+               { 0x5d, 0x03 }, /* Turn off suspend mode */
+               { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
+               { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */
+               { 0xa2, 0x20 }, /* a2-a5 are undocumented */
+               { 0xa3, 0x18 },
+               { 0xa4, 0x04 },
+               { 0xa5, 0x28 },
+               { 0x37, 0x00 }, /* SetUsbInit */
+               { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
+               /* Enable both fields, YUV Input, disable defect comp (why?) */
+               { 0x20, 0x0c },
+               { 0x21, 0x38 },
+               { 0x22, 0x1d },
+               { 0x17, 0x50 }, /* undocumented */
+               { 0x37, 0x00 }, /* undocumented */
+               { 0x40, 0xff }, /* I2C timeout counter */
+               { 0x46, 0x00 }, /* I2C clock prescaler */
+               { 0x59, 0x04 }, /* new from windrv 090403 */
+               { 0xff, 0x00 }, /* undocumented */
+               /* windows reads 0x55 at this point, why? */
+       };
+
+       static const struct ov_regvals mode_init_519[] = {
+               { 0x5d, 0x03 }, /* Turn off suspend mode */
+               { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
+               { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */
+               { 0xa2, 0x20 }, /* a2-a5 are undocumented */
+               { 0xa3, 0x18 },
+               { 0xa4, 0x04 },
+               { 0xa5, 0x28 },
+               { 0x37, 0x00 }, /* SetUsbInit */
+               { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
+               /* Enable both fields, YUV Input, disable defect comp (why?) */
+               { 0x22, 0x1d },
+               { 0x17, 0x50 }, /* undocumented */
+               { 0x37, 0x00 }, /* undocumented */
+               { 0x40, 0xff }, /* I2C timeout counter */
+               { 0x46, 0x00 }, /* I2C clock prescaler */
+               { 0x59, 0x04 }, /* new from windrv 090403 */
+               { 0xff, 0x00 }, /* undocumented */
+               /* windows reads 0x55 at this point, why? */
+       };
+
+       /******** Set the mode ********/
+       switch (sd->sensor) {
+       default:
+               write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519));
+               if (sd->sensor == SEN_OV7640 ||
+                   sd->sensor == SEN_OV7648) {
+                       /* Select 8-bit input mode */
+                       reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10);
+               }
+               break;
+       case SEN_OV7660:
+               return;         /* done by ov519_set_mode/fr() */
+       case SEN_OV7670:
+               write_regvals(sd, mode_init_519_ov7670,
+                               ARRAY_SIZE(mode_init_519_ov7670));
+               break;
+       }
+
+       reg_w(sd, OV519_R10_H_SIZE,     sd->gspca_dev.width >> 4);
+       reg_w(sd, OV519_R11_V_SIZE,     sd->gspca_dev.height >> 3);
+       if (sd->sensor == SEN_OV7670 &&
+           sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
+               reg_w(sd, OV519_R12_X_OFFSETL, 0x04);
+       else if (sd->sensor == SEN_OV7648 &&
+           sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
+               reg_w(sd, OV519_R12_X_OFFSETL, 0x01);
+       else
+               reg_w(sd, OV519_R12_X_OFFSETL, 0x00);
+       reg_w(sd, OV519_R13_X_OFFSETH,  0x00);
+       reg_w(sd, OV519_R14_Y_OFFSETL,  0x00);
+       reg_w(sd, OV519_R15_Y_OFFSETH,  0x00);
+       reg_w(sd, OV519_R16_DIVIDER,    0x00);
+       reg_w(sd, OV519_R25_FORMAT,     0x03); /* YUV422 */
+       reg_w(sd, 0x26,                 0x00); /* Undocumented */
+
+       /******** Set the framerate ********/
+       if (frame_rate > 0)
+               sd->frame_rate = frame_rate;
+
+/* FIXME: These are only valid at the max resolution. */
+       sd->clockdiv = 0;
+       switch (sd->sensor) {
+       case SEN_OV7640:
+       case SEN_OV7648:
+               switch (sd->frame_rate) {
+               default:
+/*             case 30: */
+                       reg_w(sd, 0xa4, 0x0c);
+                       reg_w(sd, 0x23, 0xff);
+                       break;
+               case 25:
+                       reg_w(sd, 0xa4, 0x0c);
+                       reg_w(sd, 0x23, 0x1f);
+                       break;
+               case 20:
+                       reg_w(sd, 0xa4, 0x0c);
+                       reg_w(sd, 0x23, 0x1b);
+                       break;
+               case 15:
+                       reg_w(sd, 0xa4, 0x04);
+                       reg_w(sd, 0x23, 0xff);
+                       sd->clockdiv = 1;
+                       break;
+               case 10:
+                       reg_w(sd, 0xa4, 0x04);
+                       reg_w(sd, 0x23, 0x1f);
+                       sd->clockdiv = 1;
+                       break;
+               case 5:
+                       reg_w(sd, 0xa4, 0x04);
+                       reg_w(sd, 0x23, 0x1b);
+                       sd->clockdiv = 1;
+                       break;
+               }
+               break;
+       case SEN_OV8610:
+               switch (sd->frame_rate) {
+               default:        /* 15 fps */
+/*             case 15: */
+                       reg_w(sd, 0xa4, 0x06);
+                       reg_w(sd, 0x23, 0xff);
+                       break;
+               case 10:
+                       reg_w(sd, 0xa4, 0x06);
+                       reg_w(sd, 0x23, 0x1f);
+                       break;
+               case 5:
+                       reg_w(sd, 0xa4, 0x06);
+                       reg_w(sd, 0x23, 0x1b);
+                       break;
+               }
+               break;
+       case SEN_OV7670:                /* guesses, based on 7640 */
+               PDEBUG(D_STREAM, "Setting framerate to %d fps",
+                                (sd->frame_rate == 0) ? 15 : sd->frame_rate);
+               reg_w(sd, 0xa4, 0x10);
+               switch (sd->frame_rate) {
+               case 30:
+                       reg_w(sd, 0x23, 0xff);
+                       break;
+               case 20:
+                       reg_w(sd, 0x23, 0x1b);
+                       break;
+               default:
+/*             case 15: */
+                       reg_w(sd, 0x23, 0xff);
+                       sd->clockdiv = 1;
+                       break;
+               }
+               break;
+       }
+}
+
+static void mode_init_ov_sensor_regs(struct sd *sd)
+{
+       struct gspca_dev *gspca_dev;
+       int qvga, xstart, xend, ystart, yend;
+       u8 v;
+
+       gspca_dev = &sd->gspca_dev;
+       qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
+
+       /******** Mode (VGA/QVGA) and sensor specific regs ********/
+       switch (sd->sensor) {
+       case SEN_OV2610:
+               i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
+               i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
+               i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
+               i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
+               i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
+               i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
+               i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
+               return;
+       case SEN_OV2610AE: {
+               u8 v;
+
+               /* frame rates:
+                *      10fps / 5 fps for 1600x1200
+                *      40fps / 20fps for 800x600
+                */
+               v = 80;
+               if (qvga) {
+                       if (sd->frame_rate < 25)
+                               v = 0x81;
+               } else {
+                       if (sd->frame_rate < 10)
+                               v = 0x81;
+               }
+               i2c_w(sd, 0x11, v);
+               i2c_w(sd, 0x12, qvga ? 0x60 : 0x20);
+               return;
+           }
+       case SEN_OV3610:
+               if (qvga) {
+                       xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4);
+                       ystart = (776 - gspca_dev->height) / 2;
+               } else {
+                       xstart = (2076 - gspca_dev->width) / 2 + (0x10 << 4);
+                       ystart = (1544 - gspca_dev->height) / 2;
+               }
+               xend = xstart + gspca_dev->width;
+               yend = ystart + gspca_dev->height;
+               /* Writing to the COMH register resets the other windowing regs
+                  to their default values, so we must do this first. */
+               i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0xf0);
+               i2c_w_mask(sd, 0x32,
+                          (((xend >> 1) & 7) << 3) | ((xstart >> 1) & 7),
+                          0x3f);
+               i2c_w_mask(sd, 0x03,
+                          (((yend >> 1) & 3) << 2) | ((ystart >> 1) & 3),
+                          0x0f);
+               i2c_w(sd, 0x17, xstart >> 4);
+               i2c_w(sd, 0x18, xend >> 4);
+               i2c_w(sd, 0x19, ystart >> 3);
+               i2c_w(sd, 0x1a, yend >> 3);
+               return;
+       case SEN_OV8610:
+               /* For OV8610 qvga means qsvga */
+               i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5);
+               i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
+               i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
+               i2c_w_mask(sd, 0x2d, 0x00, 0x40); /* from windrv 090403 */
+               i2c_w_mask(sd, 0x28, 0x20, 0x20); /* progressive mode on */
+               break;
+       case SEN_OV7610:
+               i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
+               i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e);
+               i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
+               i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
+               break;
+       case SEN_OV7620:
+       case SEN_OV7620AE:
+       case SEN_OV76BE:
+               i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
+               i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
+               i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
+               i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
+               i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
+               i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0);
+               i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
+               i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
+               i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
+               if (sd->sensor == SEN_OV76BE)
+                       i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e);
+               break;
+       case SEN_OV7640:
+       case SEN_OV7648:
+               i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
+               i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
+               /* Setting this undocumented bit in qvga mode removes a very
+                  annoying vertical shaking of the image */
+               i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
+               /* Unknown */
+               i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
+               /* Allow higher automatic gain (to allow higher framerates) */
+               i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
+               i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */
+               break;
+       case SEN_OV7670:
+               /* set COM7_FMT_VGA or COM7_FMT_QVGA
+                * do we need to set anything else?
+                *      HSTART etc are set in set_ov_sensor_window itself */
+               i2c_w_mask(sd, OV7670_R12_COM7,
+                        qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA,
+                        OV7670_COM7_FMT_MASK);
+               i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
+               i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_AWB,
+                               OV7670_COM8_AWB);
+               if (qvga) {             /* QVGA from ov7670.c by
+                                        * Jonathan Corbet */
+                       xstart = 164;
+                       xend = 28;
+                       ystart = 14;
+                       yend = 494;
+               } else {                /* VGA */
+                       xstart = 158;
+                       xend = 14;
+                       ystart = 10;
+                       yend = 490;
+               }
+               /* OV7670 hardware window registers are split across
+                * multiple locations */
+               i2c_w(sd, OV7670_R17_HSTART, xstart >> 3);
+               i2c_w(sd, OV7670_R18_HSTOP, xend >> 3);
+               v = i2c_r(sd, OV7670_R32_HREF);
+               v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07);
+               msleep(10);     /* need to sleep between read and write to
+                                * same reg! */
+               i2c_w(sd, OV7670_R32_HREF, v);
+
+               i2c_w(sd, OV7670_R19_VSTART, ystart >> 2);
+               i2c_w(sd, OV7670_R1A_VSTOP, yend >> 2);
+               v = i2c_r(sd, OV7670_R03_VREF);
+               v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03);
+               msleep(10);     /* need to sleep between read and write to
+                                * same reg! */
+               i2c_w(sd, OV7670_R03_VREF, v);
+               break;
+       case SEN_OV6620:
+               i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
+               i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
+               i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
+               break;
+       case SEN_OV6630:
+       case SEN_OV66308AF:
+               i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
+               i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
+               break;
+       case SEN_OV9600: {
+               const struct ov_i2c_regvals *vals;
+               static const struct ov_i2c_regvals sxga_15[] = {
+                       {0x11, 0x80}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75}
+               };
+               static const struct ov_i2c_regvals sxga_7_5[] = {
+                       {0x11, 0x81}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75}
+               };
+               static const struct ov_i2c_regvals vga_30[] = {
+                       {0x11, 0x81}, {0x14, 0x7e}, {0x24, 0x70}, {0x25, 0x60}
+               };
+               static const struct ov_i2c_regvals vga_15[] = {
+                       {0x11, 0x83}, {0x14, 0x3e}, {0x24, 0x80}, {0x25, 0x70}
+               };
+
+               /* frame rates:
+                *      15fps / 7.5 fps for 1280x1024
+                *      30fps / 15fps for 640x480
+                */
+               i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0x40);
+               if (qvga)
+                       vals = sd->frame_rate < 30 ? vga_15 : vga_30;
+               else
+                       vals = sd->frame_rate < 15 ? sxga_7_5 : sxga_15;
+               write_i2c_regvals(sd, vals, ARRAY_SIZE(sxga_15));
+               return;
+           }
+       default:
+               return;
+       }
+
+       /******** Clock programming ********/
+       i2c_w(sd, 0x11, sd->clockdiv);
+}
+
+/* this function works for bridge ov519 and sensors ov7660 and ov7670 only */
+static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->gspca_dev.streaming)
+               reg_w(sd, OV519_R51_RESET1, 0x0f);      /* block stream */
+       i2c_w_mask(sd, OV7670_R1E_MVFP,
+               OV7670_MVFP_MIRROR * hflip | OV7670_MVFP_VFLIP * vflip,
+               OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP);
+       if (sd->gspca_dev.streaming)
+               reg_w(sd, OV519_R51_RESET1, 0x00);      /* restart stream */
+}
+
+static void set_ov_sensor_window(struct sd *sd)
+{
+       struct gspca_dev *gspca_dev;
+       int qvga, crop;
+       int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
+
+       /* mode setup is fully handled in mode_init_ov_sensor_regs for these */
+       switch (sd->sensor) {
+       case SEN_OV2610:
+       case SEN_OV2610AE:
+       case SEN_OV3610:
+       case SEN_OV7670:
+       case SEN_OV9600:
+               mode_init_ov_sensor_regs(sd);
+               return;
+       case SEN_OV7660:
+               ov519_set_mode(sd);
+               ov519_set_fr(sd);
+               return;
+       }
+
+       gspca_dev = &sd->gspca_dev;
+       qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
+       crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2;
+
+       /* The different sensor ICs handle setting up of window differently.
+        * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */
+       switch (sd->sensor) {
+       case SEN_OV8610:
+               hwsbase = 0x1e;
+               hwebase = 0x1e;
+               vwsbase = 0x02;
+               vwebase = 0x02;
+               break;
+       case SEN_OV7610:
+       case SEN_OV76BE:
+               hwsbase = 0x38;
+               hwebase = 0x3a;
+               vwsbase = vwebase = 0x05;
+               break;
+       case SEN_OV6620:
+       case SEN_OV6630:
+       case SEN_OV66308AF:
+               hwsbase = 0x38;
+               hwebase = 0x3a;
+               vwsbase = 0x05;
+               vwebase = 0x06;
+               if (sd->sensor == SEN_OV66308AF && qvga)
+                       /* HDG: this fixes U and V getting swapped */
+                       hwsbase++;
+               if (crop) {
+                       hwsbase += 8;
+                       hwebase += 8;
+                       vwsbase += 11;
+                       vwebase += 11;
+               }
+               break;
+       case SEN_OV7620:
+       case SEN_OV7620AE:
+               hwsbase = 0x2f;         /* From 7620.SET (spec is wrong) */
+               hwebase = 0x2f;
+               vwsbase = vwebase = 0x05;
+               break;
+       case SEN_OV7640:
+       case SEN_OV7648:
+               hwsbase = 0x1a;
+               hwebase = 0x1a;
+               vwsbase = vwebase = 0x03;
+               break;
+       default:
+               return;
+       }
+
+       switch (sd->sensor) {
+       case SEN_OV6620:
+       case SEN_OV6630:
+       case SEN_OV66308AF:
+               if (qvga) {             /* QCIF */
+                       hwscale = 0;
+                       vwscale = 0;
+               } else {                /* CIF */
+                       hwscale = 1;
+                       vwscale = 1;    /* The datasheet says 0;
+                                        * it's wrong */
+               }
+               break;
+       case SEN_OV8610:
+               if (qvga) {             /* QSVGA */
+                       hwscale = 1;
+                       vwscale = 1;
+               } else {                /* SVGA */
+                       hwscale = 2;
+                       vwscale = 2;
+               }
+               break;
+       default:                        /* SEN_OV7xx0 */
+               if (qvga) {             /* QVGA */
+                       hwscale = 1;
+                       vwscale = 0;
+               } else {                /* VGA */
+                       hwscale = 2;
+                       vwscale = 1;
+               }
+       }
+
+       mode_init_ov_sensor_regs(sd);
+
+       i2c_w(sd, 0x17, hwsbase);
+       i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale));
+       i2c_w(sd, 0x19, vwsbase);
+       i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale));
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* Default for most bridges, allow bridge_mode_init_regs to override */
+       sd->sensor_width = sd->gspca_dev.width;
+       sd->sensor_height = sd->gspca_dev.height;
+
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+       case BRIDGE_OV511PLUS:
+               ov511_mode_init_regs(sd);
+               break;
+       case BRIDGE_OV518:
+       case BRIDGE_OV518PLUS:
+               ov518_mode_init_regs(sd);
+               break;
+       case BRIDGE_OV519:
+               ov519_mode_init_regs(sd);
+               break;
+       /* case BRIDGE_OVFX2: nothing to do */
+       case BRIDGE_W9968CF:
+               w9968cf_mode_init_regs(sd);
+               break;
+       }
+
+       set_ov_sensor_window(sd);
+
+       /* Force clear snapshot state in case the snapshot button was
+          pressed while we weren't streaming */
+       sd->snapshot_needs_reset = 1;
+       sd_reset_snapshot(gspca_dev);
+
+       sd->first_frame = 3;
+
+       ov51x_restart(sd);
+       ov51x_led_control(sd, 1);
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       ov51x_stop(sd);
+       ov51x_led_control(sd, 0);
+}
+
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (!sd->gspca_dev.present)
+               return;
+       if (sd->bridge == BRIDGE_W9968CF)
+               w9968cf_stop0(sd);
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       /* If the last button state is pressed, release it now! */
+       if (sd->snapshot_pressed) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+               input_sync(gspca_dev->input_dev);
+               sd->snapshot_pressed = 0;
+       }
+#endif
+       if (sd->bridge == BRIDGE_OV519)
+               reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
+}
+
+static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->snapshot_pressed != state) {
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, state);
+               input_sync(gspca_dev->input_dev);
+#endif
+               if (state)
+                       sd->snapshot_needs_reset = 1;
+
+               sd->snapshot_pressed = state;
+       } else {
+               /* On the ov511 / ov519 we need to reset the button state
+                  multiple times, as resetting does not work as long as the
+                  button stays pressed */
+               switch (sd->bridge) {
+               case BRIDGE_OV511:
+               case BRIDGE_OV511PLUS:
+               case BRIDGE_OV519:
+                       if (state)
+                               sd->snapshot_needs_reset = 1;
+                       break;
+               }
+       }
+}
+
+static void ov511_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *in,                 /* isoc packet */
+                       int len)                /* iso packet length */
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
+        * byte non-zero. The EOF packet has image width/height in the
+        * 10th and 11th bytes. The 9th byte is given as follows:
+        *
+        * bit 7: EOF
+        *     6: compression enabled
+        *     5: 422/420/400 modes
+        *     4: 422/420/400 modes
+        *     3: 1
+        *     2: snapshot button on
+        *     1: snapshot frame
+        *     0: even/odd field
+        */
+       if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) &&
+           (in[8] & 0x08)) {
+               ov51x_handle_button(gspca_dev, (in[8] >> 2) & 1);
+               if (in[8] & 0x80) {
+                       /* Frame end */
+                       if ((in[9] + 1) * 8 != gspca_dev->width ||
+                           (in[10] + 1) * 8 != gspca_dev->height) {
+                               PDEBUG(D_ERR, "Invalid frame size, got: %dx%d,"
+                                       " requested: %dx%d\n",
+                                       (in[9] + 1) * 8, (in[10] + 1) * 8,
+                                       gspca_dev->width, gspca_dev->height);
+                               gspca_dev->last_packet_type = DISCARD_PACKET;
+                               return;
+                       }
+                       /* Add 11 byte footer to frame, might be useful */
+                       gspca_frame_add(gspca_dev, LAST_PACKET, in, 11);
+                       return;
+               } else {
+                       /* Frame start */
+                       gspca_frame_add(gspca_dev, FIRST_PACKET, in, 0);
+                       sd->packet_nr = 0;
+               }
+       }
+
+       /* Ignore the packet number */
+       len--;
+
+       /* intermediate packet */
+       gspca_frame_add(gspca_dev, INTER_PACKET, in, len);
+}
+
+static void ov518_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,                       /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* A false positive here is likely, until OVT gives me
+        * the definitive SOF/EOF format */
+       if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) {
+               ov51x_handle_button(gspca_dev, (data[6] >> 1) & 1);
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+               gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
+               sd->packet_nr = 0;
+       }
+
+       if (gspca_dev->last_packet_type == DISCARD_PACKET)
+               return;
+
+       /* Does this device use packet numbers ? */
+       if (len & 7) {
+               len--;
+               if (sd->packet_nr == data[len])
+                       sd->packet_nr++;
+               /* The last few packets of the frame (which are all 0's
+                  except that they may contain part of the footer), are
+                  numbered 0 */
+               else if (sd->packet_nr == 0 || data[len]) {
+                       PDEBUG(D_ERR, "Invalid packet nr: %d (expect: %d)",
+                               (int)data[len], (int)sd->packet_nr);
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+                       return;
+               }
+       }
+
+       /* intermediate packet */
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,                       /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       /* Header of ov519 is 16 bytes:
+        *     Byte     Value      Description
+        *      0       0xff    magic
+        *      1       0xff    magic
+        *      2       0xff    magic
+        *      3       0xXX    0x50 = SOF, 0x51 = EOF
+        *      9       0xXX    0x01 initial frame without data,
+        *                      0x00 standard frame with image
+        *      14      Lo      in EOF: length of image data / 8
+        *      15      Hi
+        */
+
+       if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) {
+               switch (data[3]) {
+               case 0x50:              /* start of frame */
+                       /* Don't check the button state here, as the state
+                          usually (always ?) changes at EOF and checking it
+                          here leads to unnecessary snapshot state resets. */
+#define HDRSZ 16
+                       data += HDRSZ;
+                       len -= HDRSZ;
+#undef HDRSZ
+                       if (data[0] == 0xff || data[1] == 0xd8)
+                               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                                               data, len);
+                       else
+                               gspca_dev->last_packet_type = DISCARD_PACKET;
+                       return;
+               case 0x51:              /* end of frame */
+                       ov51x_handle_button(gspca_dev, data[11] & 1);
+                       if (data[9] != 0)
+                               gspca_dev->last_packet_type = DISCARD_PACKET;
+                       gspca_frame_add(gspca_dev, LAST_PACKET,
+                                       NULL, 0);
+                       return;
+               }
+       }
+
+       /* intermediate packet */
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,                       /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+
+       /* A short read signals EOF */
+       if (len < gspca_dev->cam.bulk_size) {
+               /* If the frame is short, and it is one of the first ones
+                  the sensor and bridge are still syncing, so drop it. */
+               if (sd->first_frame) {
+                       sd->first_frame--;
+                       if (gspca_dev->image_len <
+                                 sd->gspca_dev.width * sd->gspca_dev.height)
+                               gspca_dev->last_packet_type = DISCARD_PACKET;
+               }
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+               gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 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;
+
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+       case BRIDGE_OV511PLUS:
+               ov511_pkt_scan(gspca_dev, data, len);
+               break;
+       case BRIDGE_OV518:
+       case BRIDGE_OV518PLUS:
+               ov518_pkt_scan(gspca_dev, data, len);
+               break;
+       case BRIDGE_OV519:
+               ov519_pkt_scan(gspca_dev, data, len);
+               break;
+       case BRIDGE_OVFX2:
+               ovfx2_pkt_scan(gspca_dev, data, len);
+               break;
+       case BRIDGE_W9968CF:
+               w9968cf_pkt_scan(gspca_dev, data, len);
+               break;
+       }
+}
+
+/* -- management routines -- */
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       static const struct ov_i2c_regvals brit_7660[][7] = {
+               {{0x0f, 0x6a}, {0x24, 0x40}, {0x25, 0x2b}, {0x26, 0x90},
+                       {0x27, 0xe0}, {0x28, 0xe0}, {0x2c, 0xe0}},
+               {{0x0f, 0x6a}, {0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa1},
+                       {0x27, 0xc0}, {0x28, 0xc0}, {0x2c, 0xc0}},
+               {{0x0f, 0x6a}, {0x24, 0x68}, {0x25, 0x58}, {0x26, 0xc2},
+                       {0x27, 0xa0}, {0x28, 0xa0}, {0x2c, 0xa0}},
+               {{0x0f, 0x6a}, {0x24, 0x70}, {0x25, 0x68}, {0x26, 0xd3},
+                       {0x27, 0x80}, {0x28, 0x80}, {0x2c, 0x80}},
+               {{0x0f, 0x6a}, {0x24, 0x80}, {0x25, 0x70}, {0x26, 0xd3},
+                       {0x27, 0x20}, {0x28, 0x20}, {0x2c, 0x20}},
+               {{0x0f, 0x6a}, {0x24, 0x88}, {0x25, 0x78}, {0x26, 0xd3},
+                       {0x27, 0x40}, {0x28, 0x40}, {0x2c, 0x40}},
+               {{0x0f, 0x6a}, {0x24, 0x90}, {0x25, 0x80}, {0x26, 0xd4},
+                       {0x27, 0x60}, {0x28, 0x60}, {0x2c, 0x60}}
+       };
+
+       switch (sd->sensor) {
+       case SEN_OV8610:
+       case SEN_OV7610:
+       case SEN_OV76BE:
+       case SEN_OV6620:
+       case SEN_OV6630:
+       case SEN_OV66308AF:
+       case SEN_OV7640:
+       case SEN_OV7648:
+               i2c_w(sd, OV7610_REG_BRT, val);
+               break;
+       case SEN_OV7620:
+       case SEN_OV7620AE:
+               i2c_w(sd, OV7610_REG_BRT, val);
+               break;
+       case SEN_OV7660:
+               write_i2c_regvals(sd, brit_7660[val],
+                               ARRAY_SIZE(brit_7660[0]));
+               break;
+       case SEN_OV7670:
+/*win trace
+ *             i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */
+               i2c_w(sd, OV7670_R55_BRIGHT, ov7670_abs_to_sm(val));
+               break;
+       }
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       static const struct ov_i2c_regvals contrast_7660[][31] = {
+               {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0xa0},
+                {0x70, 0x58}, {0x71, 0x38}, {0x72, 0x30}, {0x73, 0x30},
+                {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x24}, {0x77, 0x24},
+                {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x34},
+                {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x65},
+                {0x80, 0x70}, {0x81, 0x77}, {0x82, 0x7d}, {0x83, 0x83},
+                {0x84, 0x88}, {0x85, 0x8d}, {0x86, 0x96}, {0x87, 0x9f},
+                {0x88, 0xb0}, {0x89, 0xc4}, {0x8a, 0xd9}},
+               {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0x94},
+                {0x70, 0x58}, {0x71, 0x40}, {0x72, 0x30}, {0x73, 0x30},
+                {0x74, 0x30}, {0x75, 0x30}, {0x76, 0x2c}, {0x77, 0x24},
+                {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x31},
+                {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x62},
+                {0x80, 0x6d}, {0x81, 0x75}, {0x82, 0x7b}, {0x83, 0x81},
+                {0x84, 0x87}, {0x85, 0x8d}, {0x86, 0x98}, {0x87, 0xa1},
+                {0x88, 0xb2}, {0x89, 0xc6}, {0x8a, 0xdb}},
+               {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x84},
+                {0x70, 0x58}, {0x71, 0x48}, {0x72, 0x40}, {0x73, 0x40},
+                {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x28}, {0x77, 0x24},
+                {0x78, 0x26}, {0x79, 0x28}, {0x7a, 0x28}, {0x7b, 0x34},
+                {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x5d},
+                {0x80, 0x68}, {0x81, 0x71}, {0x82, 0x79}, {0x83, 0x81},
+                {0x84, 0x86}, {0x85, 0x8b}, {0x86, 0x95}, {0x87, 0x9e},
+                {0x88, 0xb1}, {0x89, 0xc5}, {0x8a, 0xd9}},
+               {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x70},
+                {0x70, 0x58}, {0x71, 0x58}, {0x72, 0x48}, {0x73, 0x48},
+                {0x74, 0x38}, {0x75, 0x40}, {0x76, 0x34}, {0x77, 0x34},
+                {0x78, 0x2e}, {0x79, 0x28}, {0x7a, 0x24}, {0x7b, 0x22},
+                {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x58},
+                {0x80, 0x63}, {0x81, 0x6e}, {0x82, 0x77}, {0x83, 0x80},
+                {0x84, 0x87}, {0x85, 0x8f}, {0x86, 0x9c}, {0x87, 0xa9},
+                {0x88, 0xc0}, {0x89, 0xd4}, {0x8a, 0xe6}},
+               {{0x6c, 0xa0}, {0x6d, 0xf0}, {0x6e, 0x90}, {0x6f, 0x80},
+                {0x70, 0x70}, {0x71, 0x80}, {0x72, 0x60}, {0x73, 0x60},
+                {0x74, 0x58}, {0x75, 0x60}, {0x76, 0x4c}, {0x77, 0x38},
+                {0x78, 0x38}, {0x79, 0x2a}, {0x7a, 0x20}, {0x7b, 0x0e},
+                {0x7c, 0x0a}, {0x7d, 0x14}, {0x7e, 0x26}, {0x7f, 0x46},
+                {0x80, 0x54}, {0x81, 0x64}, {0x82, 0x70}, {0x83, 0x7c},
+                {0x84, 0x87}, {0x85, 0x93}, {0x86, 0xa6}, {0x87, 0xb4},
+                {0x88, 0xd0}, {0x89, 0xe5}, {0x8a, 0xf5}},
+               {{0x6c, 0x60}, {0x6d, 0x80}, {0x6e, 0x60}, {0x6f, 0x80},
+                {0x70, 0x80}, {0x71, 0x80}, {0x72, 0x88}, {0x73, 0x30},
+                {0x74, 0x70}, {0x75, 0x68}, {0x76, 0x64}, {0x77, 0x50},
+                {0x78, 0x3c}, {0x79, 0x22}, {0x7a, 0x10}, {0x7b, 0x08},
+                {0x7c, 0x06}, {0x7d, 0x0e}, {0x7e, 0x1a}, {0x7f, 0x3a},
+                {0x80, 0x4a}, {0x81, 0x5a}, {0x82, 0x6b}, {0x83, 0x7b},
+                {0x84, 0x89}, {0x85, 0x96}, {0x86, 0xaf}, {0x87, 0xc3},
+                {0x88, 0xe1}, {0x89, 0xf2}, {0x8a, 0xfa}},
+               {{0x6c, 0x20}, {0x6d, 0x40}, {0x6e, 0x20}, {0x6f, 0x60},
+                {0x70, 0x88}, {0x71, 0xc8}, {0x72, 0xc0}, {0x73, 0xb8},
+                {0x74, 0xa8}, {0x75, 0xb8}, {0x76, 0x80}, {0x77, 0x5c},
+                {0x78, 0x26}, {0x79, 0x10}, {0x7a, 0x08}, {0x7b, 0x04},
+                {0x7c, 0x02}, {0x7d, 0x06}, {0x7e, 0x0a}, {0x7f, 0x22},
+                {0x80, 0x33}, {0x81, 0x4c}, {0x82, 0x64}, {0x83, 0x7b},
+                {0x84, 0x90}, {0x85, 0xa7}, {0x86, 0xc7}, {0x87, 0xde},
+                {0x88, 0xf1}, {0x89, 0xf9}, {0x8a, 0xfd}},
+       };
+
+       switch (sd->sensor) {
+       case SEN_OV7610:
+       case SEN_OV6620:
+               i2c_w(sd, OV7610_REG_CNT, val);
+               break;
+       case SEN_OV6630:
+       case SEN_OV66308AF:
+               i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f);
+               break;
+       case SEN_OV8610: {
+               static const u8 ctab[] = {
+                       0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f
+               };
+
+               /* Use Y gamma control instead. Bit 0 enables it. */
+               i2c_w(sd, 0x64, ctab[val >> 5]);
+               break;
+           }
+       case SEN_OV7620:
+       case SEN_OV7620AE: {
+               static const u8 ctab[] = {
+                       0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
+                       0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
+               };
+
+               /* Use Y gamma control instead. Bit 0 enables it. */
+               i2c_w(sd, 0x64, ctab[val >> 4]);
+               break;
+           }
+       case SEN_OV7660:
+               write_i2c_regvals(sd, contrast_7660[val],
+                                       ARRAY_SIZE(contrast_7660[0]));
+               break;
+       case SEN_OV7670:
+               /* check that this isn't just the same as ov7610 */
+               i2c_w(sd, OV7670_R56_CONTRAS, val >> 1);
+               break;
+       }
+}
+
+static void setexposure(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       i2c_w(sd, 0x10, val);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       static const struct ov_i2c_regvals colors_7660[][6] = {
+               {{0x4f, 0x28}, {0x50, 0x2a}, {0x51, 0x02}, {0x52, 0x0a},
+                {0x53, 0x19}, {0x54, 0x23}},
+               {{0x4f, 0x47}, {0x50, 0x4a}, {0x51, 0x03}, {0x52, 0x11},
+                {0x53, 0x2c}, {0x54, 0x3e}},
+               {{0x4f, 0x66}, {0x50, 0x6b}, {0x51, 0x05}, {0x52, 0x19},
+                {0x53, 0x40}, {0x54, 0x59}},
+               {{0x4f, 0x84}, {0x50, 0x8b}, {0x51, 0x06}, {0x52, 0x20},
+                {0x53, 0x53}, {0x54, 0x73}},
+               {{0x4f, 0xa3}, {0x50, 0xab}, {0x51, 0x08}, {0x52, 0x28},
+                {0x53, 0x66}, {0x54, 0x8e}},
+       };
+
+       switch (sd->sensor) {
+       case SEN_OV8610:
+       case SEN_OV7610:
+       case SEN_OV76BE:
+       case SEN_OV6620:
+       case SEN_OV6630:
+       case SEN_OV66308AF:
+               i2c_w(sd, OV7610_REG_SAT, val);
+               break;
+       case SEN_OV7620:
+       case SEN_OV7620AE:
+               /* Use UV gamma control instead. Bits 0 & 7 are reserved. */
+/*             rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e);
+               if (rc < 0)
+                       goto out; */
+               i2c_w(sd, OV7610_REG_SAT, val);
+               break;
+       case SEN_OV7640:
+       case SEN_OV7648:
+               i2c_w(sd, OV7610_REG_SAT, val & 0xf0);
+               break;
+       case SEN_OV7660:
+               write_i2c_regvals(sd, colors_7660[val],
+                                       ARRAY_SIZE(colors_7660[0]));
+               break;
+       case SEN_OV7670:
+               /* supported later once I work out how to do it
+                * transparently fail now! */
+               /* set REG_COM13 values for UV sat auto mode */
+               break;
+       }
+}
+
+static void setautobright(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       i2c_w_mask(sd, 0x2d, val ? 0x10 : 0x00, 0x10);
+}
+
+static void setfreq_i(struct sd *sd, s32 val)
+{
+       if (sd->sensor == SEN_OV7660
+        || sd->sensor == SEN_OV7670) {
+               switch (val) {
+               case 0: /* Banding filter disabled */
+                       i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT);
+                       break;
+               case 1: /* 50 hz */
+                       i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
+                                  OV7670_COM8_BFILT);
+                       i2c_w_mask(sd, OV7670_R3B_COM11, 0x08, 0x18);
+                       break;
+               case 2: /* 60 hz */
+                       i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
+                                  OV7670_COM8_BFILT);
+                       i2c_w_mask(sd, OV7670_R3B_COM11, 0x00, 0x18);
+                       break;
+               case 3: /* Auto hz - ov7670 only */
+                       i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
+                                  OV7670_COM8_BFILT);
+                       i2c_w_mask(sd, OV7670_R3B_COM11, OV7670_COM11_HZAUTO,
+                                  0x18);
+                       break;
+               }
+       } else {
+               switch (val) {
+               case 0: /* Banding filter disabled */
+                       i2c_w_mask(sd, 0x2d, 0x00, 0x04);
+                       i2c_w_mask(sd, 0x2a, 0x00, 0x80);
+                       break;
+               case 1: /* 50 hz (filter on and framerate adj) */
+                       i2c_w_mask(sd, 0x2d, 0x04, 0x04);
+                       i2c_w_mask(sd, 0x2a, 0x80, 0x80);
+                       /* 20 fps -> 16.667 fps */
+                       if (sd->sensor == SEN_OV6620 ||
+                           sd->sensor == SEN_OV6630 ||
+                           sd->sensor == SEN_OV66308AF)
+                               i2c_w(sd, 0x2b, 0x5e);
+                       else
+                               i2c_w(sd, 0x2b, 0xac);
+                       break;
+               case 2: /* 60 hz (filter on, ...) */
+                       i2c_w_mask(sd, 0x2d, 0x04, 0x04);
+                       if (sd->sensor == SEN_OV6620 ||
+                           sd->sensor == SEN_OV6630 ||
+                           sd->sensor == SEN_OV66308AF) {
+                               /* 20 fps -> 15 fps */
+                               i2c_w_mask(sd, 0x2a, 0x80, 0x80);
+                               i2c_w(sd, 0x2b, 0xa8);
+                       } else {
+                               /* no framerate adj. */
+                               i2c_w_mask(sd, 0x2a, 0x00, 0x80);
+                       }
+                       break;
+               }
+       }
+}
+
+static void setfreq(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       setfreq_i(sd, val);
+
+       /* Ugly but necessary */
+       if (sd->bridge == BRIDGE_W9968CF)
+               w9968cf_set_crop_window(sd);
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+                       struct v4l2_jpegcompression *jcomp)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->bridge != BRIDGE_W9968CF)
+               return -ENOTTY;
+
+       memset(jcomp, 0, sizeof *jcomp);
+       jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
+       jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT |
+                             V4L2_JPEG_MARKER_DRI;
+       return 0;
+}
+
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+                       struct v4l2_jpegcompression *jcomp)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->bridge != BRIDGE_W9968CF)
+               return -ENOTTY;
+
+       v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
+       return 0;
+}
+
+static int sd_g_volatile_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;
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUTOGAIN:
+               gspca_dev->exposure->val = i2c_r(sd, 0x10);
+               break;
+       }
+       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_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_POWER_LINE_FREQUENCY:
+               setfreq(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_AUTOBRIGHTNESS:
+               if (ctrl->is_new)
+                       setautobright(gspca_dev, ctrl->val);
+               if (!ctrl->val && sd->brightness->is_new)
+                       setbrightness(gspca_dev, sd->brightness->val);
+               break;
+       case V4L2_CID_SATURATION:
+               setcolors(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_HFLIP:
+               sethvflip(gspca_dev, ctrl->val, sd->vflip->val);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if (ctrl->is_new)
+                       setautogain(gspca_dev, ctrl->val);
+               if (!ctrl->val && gspca_dev->exposure->is_new)
+                       setexposure(gspca_dev, gspca_dev->exposure->val);
+               break;
+       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+               return -EBUSY; /* Should never happen, as we grab the ctrl */
+       }
+       return gspca_dev->usb_err;
+}
+
+static const struct v4l2_ctrl_ops sd_ctrl_ops = {
+       .g_volatile_ctrl = sd_g_volatile_ctrl,
+       .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, 10);
+       if (valid_controls[sd->sensor].has_brightness)
+               sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0,
+                       sd->sensor == SEN_OV7660 ? 6 : 255, 1,
+                       sd->sensor == SEN_OV7660 ? 3 : 127);
+       if (valid_controls[sd->sensor].has_contrast) {
+               if (sd->sensor == SEN_OV7660)
+                       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                               V4L2_CID_CONTRAST, 0, 6, 1, 3);
+               else
+                       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                               V4L2_CID_CONTRAST, 0, 255, 1,
+                               (sd->sensor == SEN_OV6630 ||
+                                sd->sensor == SEN_OV66308AF) ? 200 : 127);
+       }
+       if (valid_controls[sd->sensor].has_sat)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0,
+                       sd->sensor == SEN_OV7660 ? 4 : 255, 1,
+                       sd->sensor == SEN_OV7660 ? 2 : 127);
+       if (valid_controls[sd->sensor].has_exposure)
+               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0, 255, 1, 127);
+       if (valid_controls[sd->sensor].has_hvflip) {
+               sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+               sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       }
+       if (valid_controls[sd->sensor].has_autobright)
+               sd->autobright = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_AUTOBRIGHTNESS, 0, 1, 1, 1);
+       if (valid_controls[sd->sensor].has_autogain)
+               gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+       if (valid_controls[sd->sensor].has_freq) {
+               if (sd->sensor == SEN_OV7670)
+                       sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
+                               V4L2_CID_POWER_LINE_FREQUENCY,
+                               V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
+                               V4L2_CID_POWER_LINE_FREQUENCY_AUTO);
+               else
+                       sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
+                               V4L2_CID_POWER_LINE_FREQUENCY,
+                               V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
+       }
+       if (sd->bridge == BRIDGE_W9968CF)
+               sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_JPEG_COMPRESSION_QUALITY,
+                       QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       if (gspca_dev->autogain)
+               v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, true);
+       if (sd->autobright)
+               v4l2_ctrl_auto_cluster(2, &sd->autobright, 0, false);
+       if (sd->hflip)
+               v4l2_ctrl_cluster(2, &sd->hflip);
+       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,
+       .isoc_init = sd_isoc_init,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .stop0 = sd_stop0,
+       .pkt_scan = sd_pkt_scan,
+       .dq_callback = sd_reset_snapshot,
+       .get_jcomp = sd_get_jcomp,
+       .set_jcomp = sd_set_jcomp,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .other_input = 1,
+#endif
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF },
+       {USB_DEVICE(0x041e, 0x4052),
+               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+       {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
+       {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
+       {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
+       {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 },
+       {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 },
+       {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 },
+       {USB_DEVICE(0x045e, 0x028c),
+               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+       {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 },
+       {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 },
+       {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 },
+       {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 },
+       {USB_DEVICE(0x05a9, 0x0519),
+               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+       {USB_DEVICE(0x05a9, 0x0530),
+               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
+       {USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 },
+       {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 },
+       {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 },
+       {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS },
+       {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS },
+       {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS },
+       {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 },
+       {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 },
+       {USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF },
+       {USB_DEVICE(0x8020, 0xef04), .driver_info = BRIDGE_OVFX2 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
+
+module_param(frame_rate, int, 0644);
+MODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)");
diff --git a/drivers/media/usb/gspca/ov534.c b/drivers/media/usb/gspca/ov534.c
new file mode 100644 (file)
index 0000000..bb09d78
--- /dev/null
@@ -0,0 +1,1544 @@
+/*
+ * ov534-ov7xxx gspca driver
+ *
+ * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
+ * Copyright (C) 2008 Jim Paris <jim@jtan.com>
+ * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr
+ *
+ * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>
+ * USB protocol reverse engineered by Jim Paris <jim@jtan.com>
+ * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/
+ *
+ * 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>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "ov534"
+
+#include "gspca.h"
+
+#include <linux/fixp-arith.h>
+#include <media/v4l2-ctrls.h>
+
+#define OV534_REG_ADDRESS      0xf1    /* sensor address */
+#define OV534_REG_SUBADDR      0xf2
+#define OV534_REG_WRITE                0xf3
+#define OV534_REG_READ         0xf4
+#define OV534_REG_OPERATION    0xf5
+#define OV534_REG_STATUS       0xf6
+
+#define OV534_OP_WRITE_3       0x37
+#define OV534_OP_WRITE_2       0x33
+#define OV534_OP_READ_2                0xf9
+
+#define CTRL_TIMEOUT 500
+
+MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
+MODULE_DESCRIPTION("GSPCA/OV534 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       struct v4l2_ctrl_handler ctrl_handler;
+       struct v4l2_ctrl *hue;
+       struct v4l2_ctrl *saturation;
+       struct v4l2_ctrl *brightness;
+       struct v4l2_ctrl *contrast;
+       struct { /* gain control cluster */
+               struct v4l2_ctrl *autogain;
+               struct v4l2_ctrl *gain;
+       };
+       struct v4l2_ctrl *autowhitebalance;
+       struct { /* exposure control cluster */
+               struct v4l2_ctrl *autoexposure;
+               struct v4l2_ctrl *exposure;
+       };
+       struct v4l2_ctrl *sharpness;
+       struct v4l2_ctrl *hflip;
+       struct v4l2_ctrl *vflip;
+       struct v4l2_ctrl *plfreq;
+
+       __u32 last_pts;
+       u16 last_fid;
+       u8 frame_rate;
+
+       u8 sensor;
+};
+enum sensors {
+       SENSOR_OV767x,
+       SENSOR_OV772x,
+       NSENSORS
+};
+
+static int sd_start(struct gspca_dev *gspca_dev);
+static void sd_stopN(struct gspca_dev *gspca_dev);
+
+
+static const struct v4l2_pix_format ov772x_mode[] = {
+       {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
+        .bytesperline = 320 * 2,
+        .sizeimage = 320 * 240 * 2,
+        .colorspace = V4L2_COLORSPACE_SRGB,
+        .priv = 1},
+       {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
+        .bytesperline = 640 * 2,
+        .sizeimage = 640 * 480 * 2,
+        .colorspace = V4L2_COLORSPACE_SRGB,
+        .priv = 0},
+};
+static const struct v4l2_pix_format ov767x_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+};
+
+static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30};
+static const u8 vga_rates[] = {60, 50, 40, 30, 15};
+
+static const struct framerates ov772x_framerates[] = {
+       { /* 320x240 */
+               .rates = qvga_rates,
+               .nrates = ARRAY_SIZE(qvga_rates),
+       },
+       { /* 640x480 */
+               .rates = vga_rates,
+               .nrates = ARRAY_SIZE(vga_rates),
+       },
+};
+
+struct reg_array {
+       const u8 (*val)[2];
+       int len;
+};
+
+static const u8 bridge_init_767x[][2] = {
+/* comments from the ms-win file apollo7670.set */
+/* str1 */
+       {0xf1, 0x42},
+       {0x88, 0xf8},
+       {0x89, 0xff},
+       {0x76, 0x03},
+       {0x92, 0x03},
+       {0x95, 0x10},
+       {0xe2, 0x00},
+       {0xe7, 0x3e},
+       {0x8d, 0x1c},
+       {0x8e, 0x00},
+       {0x8f, 0x00},
+       {0x1f, 0x00},
+       {0xc3, 0xf9},
+       {0x89, 0xff},
+       {0x88, 0xf8},
+       {0x76, 0x03},
+       {0x92, 0x01},
+       {0x93, 0x18},
+       {0x1c, 0x00},
+       {0x1d, 0x48},
+       {0x1d, 0x00},
+       {0x1d, 0xff},
+       {0x1d, 0x02},
+       {0x1d, 0x58},
+       {0x1d, 0x00},
+       {0x1c, 0x0a},
+       {0x1d, 0x0a},
+       {0x1d, 0x0e},
+       {0xc0, 0x50},   /* HSize 640 */
+       {0xc1, 0x3c},   /* VSize 480 */
+       {0x34, 0x05},   /* enable Audio Suspend mode */
+       {0xc2, 0x0c},   /* Input YUV */
+       {0xc3, 0xf9},   /* enable PRE */
+       {0x34, 0x05},   /* enable Audio Suspend mode */
+       {0xe7, 0x2e},   /* this solves failure of "SuspendResumeTest" */
+       {0x31, 0xf9},   /* enable 1.8V Suspend */
+       {0x35, 0x02},   /* turn on JPEG */
+       {0xd9, 0x10},
+       {0x25, 0x42},   /* GPIO[8]:Input */
+       {0x94, 0x11},   /* If the default setting is loaded when
+                        * system boots up, this flag is closed here */
+};
+static const u8 sensor_init_767x[][2] = {
+       {0x12, 0x80},
+       {0x11, 0x03},
+       {0x3a, 0x04},
+       {0x12, 0x00},
+       {0x17, 0x13},
+       {0x18, 0x01},
+       {0x32, 0xb6},
+       {0x19, 0x02},
+       {0x1a, 0x7a},
+       {0x03, 0x0a},
+       {0x0c, 0x00},
+       {0x3e, 0x00},
+       {0x70, 0x3a},
+       {0x71, 0x35},
+       {0x72, 0x11},
+       {0x73, 0xf0},
+       {0xa2, 0x02},
+       {0x7a, 0x2a},   /* set Gamma=1.6 below */
+       {0x7b, 0x12},
+       {0x7c, 0x1d},
+       {0x7d, 0x2d},
+       {0x7e, 0x45},
+       {0x7f, 0x50},
+       {0x80, 0x59},
+       {0x81, 0x62},
+       {0x82, 0x6b},
+       {0x83, 0x73},
+       {0x84, 0x7b},
+       {0x85, 0x8a},
+       {0x86, 0x98},
+       {0x87, 0xb2},
+       {0x88, 0xca},
+       {0x89, 0xe0},
+       {0x13, 0xe0},
+       {0x00, 0x00},
+       {0x10, 0x00},
+       {0x0d, 0x40},
+       {0x14, 0x38},   /* gain max 16x */
+       {0xa5, 0x05},
+       {0xab, 0x07},
+       {0x24, 0x95},
+       {0x25, 0x33},
+       {0x26, 0xe3},
+       {0x9f, 0x78},
+       {0xa0, 0x68},
+       {0xa1, 0x03},
+       {0xa6, 0xd8},
+       {0xa7, 0xd8},
+       {0xa8, 0xf0},
+       {0xa9, 0x90},
+       {0xaa, 0x94},
+       {0x13, 0xe5},
+       {0x0e, 0x61},
+       {0x0f, 0x4b},
+       {0x16, 0x02},
+       {0x21, 0x02},
+       {0x22, 0x91},
+       {0x29, 0x07},
+       {0x33, 0x0b},
+       {0x35, 0x0b},
+       {0x37, 0x1d},
+       {0x38, 0x71},
+       {0x39, 0x2a},
+       {0x3c, 0x78},
+       {0x4d, 0x40},
+       {0x4e, 0x20},
+       {0x69, 0x00},
+       {0x6b, 0x4a},
+       {0x74, 0x10},
+       {0x8d, 0x4f},
+       {0x8e, 0x00},
+       {0x8f, 0x00},
+       {0x90, 0x00},
+       {0x91, 0x00},
+       {0x96, 0x00},
+       {0x9a, 0x80},
+       {0xb0, 0x84},
+       {0xb1, 0x0c},
+       {0xb2, 0x0e},
+       {0xb3, 0x82},
+       {0xb8, 0x0a},
+       {0x43, 0x0a},
+       {0x44, 0xf0},
+       {0x45, 0x34},
+       {0x46, 0x58},
+       {0x47, 0x28},
+       {0x48, 0x3a},
+       {0x59, 0x88},
+       {0x5a, 0x88},
+       {0x5b, 0x44},
+       {0x5c, 0x67},
+       {0x5d, 0x49},
+       {0x5e, 0x0e},
+       {0x6c, 0x0a},
+       {0x6d, 0x55},
+       {0x6e, 0x11},
+       {0x6f, 0x9f},
+       {0x6a, 0x40},
+       {0x01, 0x40},
+       {0x02, 0x40},
+       {0x13, 0xe7},
+       {0x4f, 0x80},
+       {0x50, 0x80},
+       {0x51, 0x00},
+       {0x52, 0x22},
+       {0x53, 0x5e},
+       {0x54, 0x80},
+       {0x58, 0x9e},
+       {0x41, 0x08},
+       {0x3f, 0x00},
+       {0x75, 0x04},
+       {0x76, 0xe1},
+       {0x4c, 0x00},
+       {0x77, 0x01},
+       {0x3d, 0xc2},
+       {0x4b, 0x09},
+       {0xc9, 0x60},
+       {0x41, 0x38},   /* jfm: auto sharpness + auto de-noise  */
+       {0x56, 0x40},
+       {0x34, 0x11},
+       {0x3b, 0xc2},
+       {0xa4, 0x8a},   /* Night mode trigger point */
+       {0x96, 0x00},
+       {0x97, 0x30},
+       {0x98, 0x20},
+       {0x99, 0x20},
+       {0x9a, 0x84},
+       {0x9b, 0x29},
+       {0x9c, 0x03},
+       {0x9d, 0x4c},
+       {0x9e, 0x3f},
+       {0x78, 0x04},
+       {0x79, 0x01},
+       {0xc8, 0xf0},
+       {0x79, 0x0f},
+       {0xc8, 0x00},
+       {0x79, 0x10},
+       {0xc8, 0x7e},
+       {0x79, 0x0a},
+       {0xc8, 0x80},
+       {0x79, 0x0b},
+       {0xc8, 0x01},
+       {0x79, 0x0c},
+       {0xc8, 0x0f},
+       {0x79, 0x0d},
+       {0xc8, 0x20},
+       {0x79, 0x09},
+       {0xc8, 0x80},
+       {0x79, 0x02},
+       {0xc8, 0xc0},
+       {0x79, 0x03},
+       {0xc8, 0x20},
+       {0x79, 0x26},
+};
+static const u8 bridge_start_vga_767x[][2] = {
+/* str59 JPG */
+       {0x94, 0xaa},
+       {0xf1, 0x42},
+       {0xe5, 0x04},
+       {0xc0, 0x50},
+       {0xc1, 0x3c},
+       {0xc2, 0x0c},
+       {0x35, 0x02},   /* turn on JPEG */
+       {0xd9, 0x10},
+       {0xda, 0x00},   /* for higher clock rate(30fps) */
+       {0x34, 0x05},   /* enable Audio Suspend mode */
+       {0xc3, 0xf9},   /* enable PRE */
+       {0x8c, 0x00},   /* CIF VSize LSB[2:0] */
+       {0x8d, 0x1c},   /* output YUV */
+/*     {0x34, 0x05},    * enable Audio Suspend mode (?) */
+       {0x50, 0x00},   /* H/V divider=0 */
+       {0x51, 0xa0},   /* input H=640/4 */
+       {0x52, 0x3c},   /* input V=480/4 */
+       {0x53, 0x00},   /* offset X=0 */
+       {0x54, 0x00},   /* offset Y=0 */
+       {0x55, 0x00},   /* H/V size[8]=0 */
+       {0x57, 0x00},   /* H-size[9]=0 */
+       {0x5c, 0x00},   /* output size[9:8]=0 */
+       {0x5a, 0xa0},   /* output H=640/4 */
+       {0x5b, 0x78},   /* output V=480/4 */
+       {0x1c, 0x0a},
+       {0x1d, 0x0a},
+       {0x94, 0x11},
+};
+static const u8 sensor_start_vga_767x[][2] = {
+       {0x11, 0x01},
+       {0x1e, 0x04},
+       {0x19, 0x02},
+       {0x1a, 0x7a},
+};
+static const u8 bridge_start_qvga_767x[][2] = {
+/* str86 JPG */
+       {0x94, 0xaa},
+       {0xf1, 0x42},
+       {0xe5, 0x04},
+       {0xc0, 0x80},
+       {0xc1, 0x60},
+       {0xc2, 0x0c},
+       {0x35, 0x02},   /* turn on JPEG */
+       {0xd9, 0x10},
+       {0xc0, 0x50},   /* CIF HSize 640 */
+       {0xc1, 0x3c},   /* CIF VSize 480 */
+       {0x8c, 0x00},   /* CIF VSize LSB[2:0] */
+       {0x8d, 0x1c},   /* output YUV */
+       {0x34, 0x05},   /* enable Audio Suspend mode */
+       {0xc2, 0x4c},   /* output YUV and Enable DCW */
+       {0xc3, 0xf9},   /* enable PRE */
+       {0x1c, 0x00},   /* indirect addressing */
+       {0x1d, 0x48},   /* output YUV422 */
+       {0x50, 0x89},   /* H/V divider=/2; plus DCW AVG */
+       {0x51, 0xa0},   /* DCW input H=640/4 */
+       {0x52, 0x78},   /* DCW input V=480/4 */
+       {0x53, 0x00},   /* offset X=0 */
+       {0x54, 0x00},   /* offset Y=0 */
+       {0x55, 0x00},   /* H/V size[8]=0 */
+       {0x57, 0x00},   /* H-size[9]=0 */
+       {0x5c, 0x00},   /* DCW output size[9:8]=0 */
+       {0x5a, 0x50},   /* DCW output H=320/4 */
+       {0x5b, 0x3c},   /* DCW output V=240/4 */
+       {0x1c, 0x0a},
+       {0x1d, 0x0a},
+       {0x94, 0x11},
+};
+static const u8 sensor_start_qvga_767x[][2] = {
+       {0x11, 0x01},
+       {0x1e, 0x04},
+       {0x19, 0x02},
+       {0x1a, 0x7a},
+};
+
+static const u8 bridge_init_772x[][2] = {
+       { 0xc2, 0x0c },
+       { 0x88, 0xf8 },
+       { 0xc3, 0x69 },
+       { 0x89, 0xff },
+       { 0x76, 0x03 },
+       { 0x92, 0x01 },
+       { 0x93, 0x18 },
+       { 0x94, 0x10 },
+       { 0x95, 0x10 },
+       { 0xe2, 0x00 },
+       { 0xe7, 0x3e },
+
+       { 0x96, 0x00 },
+
+       { 0x97, 0x20 },
+       { 0x97, 0x20 },
+       { 0x97, 0x20 },
+       { 0x97, 0x0a },
+       { 0x97, 0x3f },
+       { 0x97, 0x4a },
+       { 0x97, 0x20 },
+       { 0x97, 0x15 },
+       { 0x97, 0x0b },
+
+       { 0x8e, 0x40 },
+       { 0x1f, 0x81 },
+       { 0x34, 0x05 },
+       { 0xe3, 0x04 },
+       { 0x88, 0x00 },
+       { 0x89, 0x00 },
+       { 0x76, 0x00 },
+       { 0xe7, 0x2e },
+       { 0x31, 0xf9 },
+       { 0x25, 0x42 },
+       { 0x21, 0xf0 },
+
+       { 0x1c, 0x00 },
+       { 0x1d, 0x40 },
+       { 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */
+       { 0x1d, 0x00 }, /* payload size */
+
+       { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */
+       { 0x1d, 0x58 }, /* frame size */
+       { 0x1d, 0x00 }, /* frame size */
+
+       { 0x1c, 0x0a },
+       { 0x1d, 0x08 }, /* turn on UVC header */
+       { 0x1d, 0x0e }, /* .. */
+
+       { 0x8d, 0x1c },
+       { 0x8e, 0x80 },
+       { 0xe5, 0x04 },
+
+       { 0xc0, 0x50 },
+       { 0xc1, 0x3c },
+       { 0xc2, 0x0c },
+};
+static const u8 sensor_init_772x[][2] = {
+       { 0x12, 0x80 },
+       { 0x11, 0x01 },
+/*fixme: better have a delay?*/
+       { 0x11, 0x01 },
+       { 0x11, 0x01 },
+       { 0x11, 0x01 },
+       { 0x11, 0x01 },
+       { 0x11, 0x01 },
+       { 0x11, 0x01 },
+       { 0x11, 0x01 },
+       { 0x11, 0x01 },
+       { 0x11, 0x01 },
+       { 0x11, 0x01 },
+
+       { 0x3d, 0x03 },
+       { 0x17, 0x26 },
+       { 0x18, 0xa0 },
+       { 0x19, 0x07 },
+       { 0x1a, 0xf0 },
+       { 0x32, 0x00 },
+       { 0x29, 0xa0 },
+       { 0x2c, 0xf0 },
+       { 0x65, 0x20 },
+       { 0x11, 0x01 },
+       { 0x42, 0x7f },
+       { 0x63, 0xaa },         /* AWB - was e0 */
+       { 0x64, 0xff },
+       { 0x66, 0x00 },
+       { 0x13, 0xf0 },         /* com8 */
+       { 0x0d, 0x41 },
+       { 0x0f, 0xc5 },
+       { 0x14, 0x11 },
+
+       { 0x22, 0x7f },
+       { 0x23, 0x03 },
+       { 0x24, 0x40 },
+       { 0x25, 0x30 },
+       { 0x26, 0xa1 },
+       { 0x2a, 0x00 },
+       { 0x2b, 0x00 },
+       { 0x6b, 0xaa },
+       { 0x13, 0xff },         /* AWB */
+
+       { 0x90, 0x05 },
+       { 0x91, 0x01 },
+       { 0x92, 0x03 },
+       { 0x93, 0x00 },
+       { 0x94, 0x60 },
+       { 0x95, 0x3c },
+       { 0x96, 0x24 },
+       { 0x97, 0x1e },
+       { 0x98, 0x62 },
+       { 0x99, 0x80 },
+       { 0x9a, 0x1e },
+       { 0x9b, 0x08 },
+       { 0x9c, 0x20 },
+       { 0x9e, 0x81 },
+
+       { 0xa6, 0x07 },
+       { 0x7e, 0x0c },
+       { 0x7f, 0x16 },
+       { 0x80, 0x2a },
+       { 0x81, 0x4e },
+       { 0x82, 0x61 },
+       { 0x83, 0x6f },
+       { 0x84, 0x7b },
+       { 0x85, 0x86 },
+       { 0x86, 0x8e },
+       { 0x87, 0x97 },
+       { 0x88, 0xa4 },
+       { 0x89, 0xaf },
+       { 0x8a, 0xc5 },
+       { 0x8b, 0xd7 },
+       { 0x8c, 0xe8 },
+       { 0x8d, 0x20 },
+
+       { 0x0c, 0x90 },
+
+       { 0x2b, 0x00 },
+       { 0x22, 0x7f },
+       { 0x23, 0x03 },
+       { 0x11, 0x01 },
+       { 0x0c, 0xd0 },
+       { 0x64, 0xff },
+       { 0x0d, 0x41 },
+
+       { 0x14, 0x41 },
+       { 0x0e, 0xcd },
+       { 0xac, 0xbf },
+       { 0x8e, 0x00 },         /* De-noise threshold */
+       { 0x0c, 0xd0 }
+};
+static const u8 bridge_start_vga_772x[][2] = {
+       {0x1c, 0x00},
+       {0x1d, 0x40},
+       {0x1d, 0x02},
+       {0x1d, 0x00},
+       {0x1d, 0x02},
+       {0x1d, 0x58},
+       {0x1d, 0x00},
+       {0xc0, 0x50},
+       {0xc1, 0x3c},
+};
+static const u8 sensor_start_vga_772x[][2] = {
+       {0x12, 0x00},
+       {0x17, 0x26},
+       {0x18, 0xa0},
+       {0x19, 0x07},
+       {0x1a, 0xf0},
+       {0x29, 0xa0},
+       {0x2c, 0xf0},
+       {0x65, 0x20},
+};
+static const u8 bridge_start_qvga_772x[][2] = {
+       {0x1c, 0x00},
+       {0x1d, 0x40},
+       {0x1d, 0x02},
+       {0x1d, 0x00},
+       {0x1d, 0x01},
+       {0x1d, 0x4b},
+       {0x1d, 0x00},
+       {0xc0, 0x28},
+       {0xc1, 0x1e},
+};
+static const u8 sensor_start_qvga_772x[][2] = {
+       {0x12, 0x40},
+       {0x17, 0x3f},
+       {0x18, 0x50},
+       {0x19, 0x03},
+       {0x1a, 0x78},
+       {0x29, 0x50},
+       {0x2c, 0x78},
+       {0x65, 0x2f},
+};
+
+static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
+{
+       struct usb_device *udev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       PDEBUG(D_USBO, "SET 01 0000 %04x %02x", reg, val);
+       gspca_dev->usb_buf[0] = val;
+       ret = usb_control_msg(udev,
+                             usb_sndctrlpipe(udev, 0),
+                             0x01,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
+       if (ret < 0) {
+               pr_err("write failed %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg)
+{
+       struct usb_device *udev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return 0;
+       ret = usb_control_msg(udev,
+                             usb_rcvctrlpipe(udev, 0),
+                             0x01,
+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
+       PDEBUG(D_USBI, "GET 01 0000 %04x %02x", reg, gspca_dev->usb_buf[0]);
+       if (ret < 0) {
+               pr_err("read failed %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+       return gspca_dev->usb_buf[0];
+}
+
+/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
+ * (direction and output)? */
+static void ov534_set_led(struct gspca_dev *gspca_dev, int status)
+{
+       u8 data;
+
+       PDEBUG(D_CONF, "led status: %d", status);
+
+       data = ov534_reg_read(gspca_dev, 0x21);
+       data |= 0x80;
+       ov534_reg_write(gspca_dev, 0x21, data);
+
+       data = ov534_reg_read(gspca_dev, 0x23);
+       if (status)
+               data |= 0x80;
+       else
+               data &= ~0x80;
+
+       ov534_reg_write(gspca_dev, 0x23, data);
+
+       if (!status) {
+               data = ov534_reg_read(gspca_dev, 0x21);
+               data &= ~0x80;
+               ov534_reg_write(gspca_dev, 0x21, data);
+       }
+}
+
+static int sccb_check_status(struct gspca_dev *gspca_dev)
+{
+       u8 data;
+       int i;
+
+       for (i = 0; i < 5; i++) {
+               msleep(10);
+               data = ov534_reg_read(gspca_dev, OV534_REG_STATUS);
+
+               switch (data) {
+               case 0x00:
+                       return 1;
+               case 0x04:
+                       return 0;
+               case 0x03:
+                       break;
+               default:
+                       PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5",
+                              data, i + 1);
+               }
+       }
+       return 0;
+}
+
+static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
+{
+       PDEBUG(D_USBO, "sccb write: %02x %02x", reg, val);
+       ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
+       ov534_reg_write(gspca_dev, OV534_REG_WRITE, val);
+       ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
+
+       if (!sccb_check_status(gspca_dev)) {
+               pr_err("sccb_reg_write failed\n");
+               gspca_dev->usb_err = -EIO;
+       }
+}
+
+static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg)
+{
+       ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
+       ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
+       if (!sccb_check_status(gspca_dev))
+               pr_err("sccb_reg_read failed 1\n");
+
+       ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
+       if (!sccb_check_status(gspca_dev))
+               pr_err("sccb_reg_read failed 2\n");
+
+       return ov534_reg_read(gspca_dev, OV534_REG_READ);
+}
+
+/* output a bridge sequence (reg - val) */
+static void reg_w_array(struct gspca_dev *gspca_dev,
+                       const u8 (*data)[2], int len)
+{
+       while (--len >= 0) {
+               ov534_reg_write(gspca_dev, (*data)[0], (*data)[1]);
+               data++;
+       }
+}
+
+/* output a sensor sequence (reg - val) */
+static void sccb_w_array(struct gspca_dev *gspca_dev,
+                       const u8 (*data)[2], int len)
+{
+       while (--len >= 0) {
+               if ((*data)[0] != 0xff) {
+                       sccb_reg_write(gspca_dev, (*data)[0], (*data)[1]);
+               } else {
+                       sccb_reg_read(gspca_dev, (*data)[1]);
+                       sccb_reg_write(gspca_dev, 0xff, 0x00);
+               }
+               data++;
+       }
+}
+
+/* ov772x specific controls */
+static void set_frame_rate(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+       struct rate_s {
+               u8 fps;
+               u8 r11;
+               u8 r0d;
+               u8 re5;
+       };
+       const struct rate_s *r;
+       static const struct rate_s rate_0[] = { /* 640x480 */
+               {60, 0x01, 0xc1, 0x04},
+               {50, 0x01, 0x41, 0x02},
+               {40, 0x02, 0xc1, 0x04},
+               {30, 0x04, 0x81, 0x02},
+               {15, 0x03, 0x41, 0x04},
+       };
+       static const struct rate_s rate_1[] = { /* 320x240 */
+               {125, 0x02, 0x81, 0x02},
+               {100, 0x02, 0xc1, 0x04},
+               {75, 0x03, 0xc1, 0x04},
+               {60, 0x04, 0xc1, 0x04},
+               {50, 0x02, 0x41, 0x04},
+               {40, 0x03, 0x41, 0x04},
+               {30, 0x04, 0x41, 0x04},
+       };
+
+       if (sd->sensor != SENSOR_OV772x)
+               return;
+       if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) {
+               r = rate_0;
+               i = ARRAY_SIZE(rate_0);
+       } else {
+               r = rate_1;
+               i = ARRAY_SIZE(rate_1);
+       }
+       while (--i > 0) {
+               if (sd->frame_rate >= r->fps)
+                       break;
+               r++;
+       }
+
+       sccb_reg_write(gspca_dev, 0x11, r->r11);
+       sccb_reg_write(gspca_dev, 0x0d, r->r0d);
+       ov534_reg_write(gspca_dev, 0xe5, r->re5);
+
+       PDEBUG(D_PROBE, "frame_rate: %d", r->fps);
+}
+
+static void sethue(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_OV767x) {
+               /* TBD */
+       } else {
+               s16 huesin;
+               s16 huecos;
+
+               /* fixp_sin and fixp_cos accept only positive values, while
+                * our val is between -90 and 90
+                */
+               val += 360;
+
+               /* According to the datasheet the registers expect HUESIN and
+                * HUECOS to be the result of the trigonometric functions,
+                * scaled by 0x80.
+                *
+                * The 0x100 here represents the maximun absolute value
+                * returned byt fixp_sin and fixp_cos, so the scaling will
+                * consider the result like in the interval [-1.0, 1.0].
+                */
+               huesin = fixp_sin(val) * 0x80 / 0x100;
+               huecos = fixp_cos(val) * 0x80 / 0x100;
+
+               if (huesin < 0) {
+                       sccb_reg_write(gspca_dev, 0xab,
+                               sccb_reg_read(gspca_dev, 0xab) | 0x2);
+                       huesin = -huesin;
+               } else {
+                       sccb_reg_write(gspca_dev, 0xab,
+                               sccb_reg_read(gspca_dev, 0xab) & ~0x2);
+
+               }
+               sccb_reg_write(gspca_dev, 0xa9, (u8)huecos);
+               sccb_reg_write(gspca_dev, 0xaa, (u8)huesin);
+       }
+}
+
+static void setsaturation(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_OV767x) {
+               int i;
+               static u8 color_tb[][6] = {
+                       {0x42, 0x42, 0x00, 0x11, 0x30, 0x41},
+                       {0x52, 0x52, 0x00, 0x16, 0x3c, 0x52},
+                       {0x66, 0x66, 0x00, 0x1b, 0x4b, 0x66},
+                       {0x80, 0x80, 0x00, 0x22, 0x5e, 0x80},
+                       {0x9a, 0x9a, 0x00, 0x29, 0x71, 0x9a},
+                       {0xb8, 0xb8, 0x00, 0x31, 0x87, 0xb8},
+                       {0xdd, 0xdd, 0x00, 0x3b, 0xa2, 0xdd},
+               };
+
+               for (i = 0; i < ARRAY_SIZE(color_tb[0]); i++)
+                       sccb_reg_write(gspca_dev, 0x4f + i, color_tb[val][i]);
+       } else {
+               sccb_reg_write(gspca_dev, 0xa7, val); /* U saturation */
+               sccb_reg_write(gspca_dev, 0xa8, val); /* V saturation */
+       }
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_OV767x) {
+               if (val < 0)
+                       val = 0x80 - val;
+               sccb_reg_write(gspca_dev, 0x55, val);   /* bright */
+       } else {
+               sccb_reg_write(gspca_dev, 0x9b, val);
+       }
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_OV767x)
+               sccb_reg_write(gspca_dev, 0x56, val);   /* contras */
+       else
+               sccb_reg_write(gspca_dev, 0x9c, val);
+}
+
+static void setgain(struct gspca_dev *gspca_dev, s32 val)
+{
+       switch (val & 0x30) {
+       case 0x00:
+               val &= 0x0f;
+               break;
+       case 0x10:
+               val &= 0x0f;
+               val |= 0x30;
+               break;
+       case 0x20:
+               val &= 0x0f;
+               val |= 0x70;
+               break;
+       default:
+/*     case 0x30: */
+               val &= 0x0f;
+               val |= 0xf0;
+               break;
+       }
+       sccb_reg_write(gspca_dev, 0x00, val);
+}
+
+static s32 getgain(struct gspca_dev *gspca_dev)
+{
+       return sccb_reg_read(gspca_dev, 0x00);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_OV767x) {
+
+               /* set only aec[9:2] */
+               sccb_reg_write(gspca_dev, 0x10, val);   /* aech */
+       } else {
+
+               /* 'val' is one byte and represents half of the exposure value
+                * we are going to set into registers, a two bytes value:
+                *
+                *    MSB: ((u16) val << 1) >> 8   == val >> 7
+                *    LSB: ((u16) val << 1) & 0xff == val << 1
+                */
+               sccb_reg_write(gspca_dev, 0x08, val >> 7);
+               sccb_reg_write(gspca_dev, 0x10, val << 1);
+       }
+}
+
+static s32 getexposure(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_OV767x) {
+               /* get only aec[9:2] */
+               return sccb_reg_read(gspca_dev, 0x10);  /* aech */
+       } else {
+               u8 hi = sccb_reg_read(gspca_dev, 0x08);
+               u8 lo = sccb_reg_read(gspca_dev, 0x10);
+               return (hi << 8 | lo) >> 1;
+       }
+}
+
+static void setagc(struct gspca_dev *gspca_dev, s32 val)
+{
+       if (val) {
+               sccb_reg_write(gspca_dev, 0x13,
+                               sccb_reg_read(gspca_dev, 0x13) | 0x04);
+               sccb_reg_write(gspca_dev, 0x64,
+                               sccb_reg_read(gspca_dev, 0x64) | 0x03);
+       } else {
+               sccb_reg_write(gspca_dev, 0x13,
+                               sccb_reg_read(gspca_dev, 0x13) & ~0x04);
+               sccb_reg_write(gspca_dev, 0x64,
+                               sccb_reg_read(gspca_dev, 0x64) & ~0x03);
+       }
+}
+
+static void setawb(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (val) {
+               sccb_reg_write(gspca_dev, 0x13,
+                               sccb_reg_read(gspca_dev, 0x13) | 0x02);
+               if (sd->sensor == SENSOR_OV772x)
+                       sccb_reg_write(gspca_dev, 0x63,
+                               sccb_reg_read(gspca_dev, 0x63) | 0xc0);
+       } else {
+               sccb_reg_write(gspca_dev, 0x13,
+                               sccb_reg_read(gspca_dev, 0x13) & ~0x02);
+               if (sd->sensor == SENSOR_OV772x)
+                       sccb_reg_write(gspca_dev, 0x63,
+                               sccb_reg_read(gspca_dev, 0x63) & ~0xc0);
+       }
+}
+
+static void setaec(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 data;
+
+       data = sd->sensor == SENSOR_OV767x ?
+                       0x05 :          /* agc + aec */
+                       0x01;           /* agc */
+       switch (val) {
+       case V4L2_EXPOSURE_AUTO:
+               sccb_reg_write(gspca_dev, 0x13,
+                               sccb_reg_read(gspca_dev, 0x13) | data);
+               break;
+       case V4L2_EXPOSURE_MANUAL:
+               sccb_reg_write(gspca_dev, 0x13,
+                               sccb_reg_read(gspca_dev, 0x13) & ~data);
+               break;
+       }
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
+{
+       sccb_reg_write(gspca_dev, 0x91, val);   /* Auto de-noise threshold */
+       sccb_reg_write(gspca_dev, 0x8e, val);   /* De-noise threshold */
+}
+
+static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 val;
+
+       if (sd->sensor == SENSOR_OV767x) {
+               val = sccb_reg_read(gspca_dev, 0x1e);   /* mvfp */
+               val &= ~0x30;
+               if (hflip)
+                       val |= 0x20;
+               if (vflip)
+                       val |= 0x10;
+               sccb_reg_write(gspca_dev, 0x1e, val);
+       } else {
+               val = sccb_reg_read(gspca_dev, 0x0c);
+               val &= ~0xc0;
+               if (hflip == 0)
+                       val |= 0x40;
+               if (vflip == 0)
+                       val |= 0x80;
+               sccb_reg_write(gspca_dev, 0x0c, val);
+       }
+}
+
+static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       val = val ? 0x9e : 0x00;
+       if (sd->sensor == SENSOR_OV767x) {
+               sccb_reg_write(gspca_dev, 0x2a, 0x00);
+               if (val)
+                       val = 0x9d;     /* insert dummy to 25fps for 50Hz */
+       }
+       sccb_reg_write(gspca_dev, 0x2b, val);
+}
+
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                    const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+
+       cam = &gspca_dev->cam;
+
+       cam->cam_mode = ov772x_mode;
+       cam->nmodes = ARRAY_SIZE(ov772x_mode);
+
+       sd->frame_rate = 30;
+
+       return 0;
+}
+
+static int ov534_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct sd *sd = container_of(ctrl->handler, struct sd, ctrl_handler);
+       struct gspca_dev *gspca_dev = &sd->gspca_dev;
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUTOGAIN:
+               gspca_dev->usb_err = 0;
+               if (ctrl->val && sd->gain && gspca_dev->streaming)
+                       sd->gain->val = getgain(gspca_dev);
+               return gspca_dev->usb_err;
+
+       case V4L2_CID_EXPOSURE_AUTO:
+               gspca_dev->usb_err = 0;
+               if (ctrl->val == V4L2_EXPOSURE_AUTO && sd->exposure &&
+                   gspca_dev->streaming)
+                       sd->exposure->val = getexposure(gspca_dev);
+               return gspca_dev->usb_err;
+       }
+       return -EINVAL;
+}
+
+static int ov534_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct sd *sd = container_of(ctrl->handler, struct sd, ctrl_handler);
+       struct gspca_dev *gspca_dev = &sd->gspca_dev;
+
+       gspca_dev->usb_err = 0;
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_HUE:
+               sethue(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               setsaturation(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_AUTOGAIN:
+       /* case V4L2_CID_GAIN: */
+               setagc(gspca_dev, ctrl->val);
+               if (!gspca_dev->usb_err && !ctrl->val && sd->gain)
+                       setgain(gspca_dev, sd->gain->val);
+               break;
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               setawb(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_EXPOSURE_AUTO:
+       /* case V4L2_CID_EXPOSURE: */
+               setaec(gspca_dev, ctrl->val);
+               if (!gspca_dev->usb_err && ctrl->val == V4L2_EXPOSURE_MANUAL &&
+                   sd->exposure)
+                       setexposure(gspca_dev, sd->exposure->val);
+               break;
+       case V4L2_CID_SHARPNESS:
+               setsharpness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_HFLIP:
+               sethvflip(gspca_dev, ctrl->val, sd->vflip->val);
+               break;
+       case V4L2_CID_VFLIP:
+               sethvflip(gspca_dev, sd->hflip->val, ctrl->val);
+               break;
+       case V4L2_CID_POWER_LINE_FREQUENCY:
+               setlightfreq(gspca_dev, ctrl->val);
+               break;
+       }
+       return gspca_dev->usb_err;
+}
+
+static const struct v4l2_ctrl_ops ov534_ctrl_ops = {
+       .g_volatile_ctrl = ov534_g_volatile_ctrl,
+       .s_ctrl = ov534_s_ctrl,
+};
+
+static int sd_init_controls(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct v4l2_ctrl_handler *hdl = &sd->ctrl_handler;
+       /* parameters with different values between the supported sensors */
+       int saturation_min;
+       int saturation_max;
+       int saturation_def;
+       int brightness_min;
+       int brightness_max;
+       int brightness_def;
+       int contrast_max;
+       int contrast_def;
+       int exposure_min;
+       int exposure_max;
+       int exposure_def;
+       int hflip_def;
+
+       if (sd->sensor == SENSOR_OV767x) {
+               saturation_min = 0,
+               saturation_max = 6,
+               saturation_def = 3,
+               brightness_min = -127;
+               brightness_max = 127;
+               brightness_def = 0;
+               contrast_max = 0x80;
+               contrast_def = 0x40;
+               exposure_min = 0x08;
+               exposure_max = 0x60;
+               exposure_def = 0x13;
+               hflip_def = 1;
+       } else {
+               saturation_min = 0,
+               saturation_max = 255,
+               saturation_def = 64,
+               brightness_min = 0;
+               brightness_max = 255;
+               brightness_def = 0;
+               contrast_max = 255;
+               contrast_def = 32;
+               exposure_min = 0;
+               exposure_max = 255;
+               exposure_def = 120;
+               hflip_def = 0;
+       }
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+
+       v4l2_ctrl_handler_init(hdl, 13);
+
+       if (sd->sensor == SENSOR_OV772x)
+               sd->hue = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
+                               V4L2_CID_HUE, -90, 90, 1, 0);
+
+       sd->saturation = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
+                       V4L2_CID_SATURATION, saturation_min, saturation_max, 1,
+                       saturation_def);
+       sd->brightness = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, brightness_min, brightness_max, 1,
+                       brightness_def);
+       sd->contrast = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, contrast_max, 1, contrast_def);
+
+       if (sd->sensor == SENSOR_OV772x) {
+               sd->autogain = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
+                               V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+               sd->gain = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
+                               V4L2_CID_GAIN, 0, 63, 1, 20);
+       }
+
+       sd->autoexposure = v4l2_ctrl_new_std_menu(hdl, &ov534_ctrl_ops,
+                       V4L2_CID_EXPOSURE_AUTO,
+                       V4L2_EXPOSURE_MANUAL, 0,
+                       V4L2_EXPOSURE_AUTO);
+       sd->exposure = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
+                       V4L2_CID_EXPOSURE, exposure_min, exposure_max, 1,
+                       exposure_def);
+
+       sd->autowhitebalance = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
+                       V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+
+       if (sd->sensor == SENSOR_OV772x)
+               sd->sharpness = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
+                               V4L2_CID_SHARPNESS, 0, 63, 1, 0);
+
+       sd->hflip = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, hflip_def);
+       sd->vflip = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &ov534_ctrl_ops,
+                       V4L2_CID_POWER_LINE_FREQUENCY,
+                       V4L2_CID_POWER_LINE_FREQUENCY_50HZ, 0,
+                       V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+
+       if (sd->sensor == SENSOR_OV772x)
+               v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, true);
+
+       v4l2_ctrl_auto_cluster(2, &sd->autoexposure, V4L2_EXPOSURE_MANUAL,
+                              true);
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u16 sensor_id;
+       static const struct reg_array bridge_init[NSENSORS] = {
+       [SENSOR_OV767x] = {bridge_init_767x, ARRAY_SIZE(bridge_init_767x)},
+       [SENSOR_OV772x] = {bridge_init_772x, ARRAY_SIZE(bridge_init_772x)},
+       };
+       static const struct reg_array sensor_init[NSENSORS] = {
+       [SENSOR_OV767x] = {sensor_init_767x, ARRAY_SIZE(sensor_init_767x)},
+       [SENSOR_OV772x] = {sensor_init_772x, ARRAY_SIZE(sensor_init_772x)},
+       };
+
+       /* reset bridge */
+       ov534_reg_write(gspca_dev, 0xe7, 0x3a);
+       ov534_reg_write(gspca_dev, 0xe0, 0x08);
+       msleep(100);
+
+       /* initialize the sensor address */
+       ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, 0x42);
+
+       /* reset sensor */
+       sccb_reg_write(gspca_dev, 0x12, 0x80);
+       msleep(10);
+
+       /* probe the sensor */
+       sccb_reg_read(gspca_dev, 0x0a);
+       sensor_id = sccb_reg_read(gspca_dev, 0x0a) << 8;
+       sccb_reg_read(gspca_dev, 0x0b);
+       sensor_id |= sccb_reg_read(gspca_dev, 0x0b);
+       PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
+
+       if ((sensor_id & 0xfff0) == 0x7670) {
+               sd->sensor = SENSOR_OV767x;
+               gspca_dev->cam.cam_mode = ov767x_mode;
+               gspca_dev->cam.nmodes = ARRAY_SIZE(ov767x_mode);
+       } else {
+               sd->sensor = SENSOR_OV772x;
+               gspca_dev->cam.bulk = 1;
+               gspca_dev->cam.bulk_size = 16384;
+               gspca_dev->cam.bulk_nurbs = 2;
+               gspca_dev->cam.mode_framerates = ov772x_framerates;
+       }
+
+       /* initialize */
+       reg_w_array(gspca_dev, bridge_init[sd->sensor].val,
+                       bridge_init[sd->sensor].len);
+       ov534_set_led(gspca_dev, 1);
+       sccb_w_array(gspca_dev, sensor_init[sd->sensor].val,
+                       sensor_init[sd->sensor].len);
+       if (sd->sensor == SENSOR_OV767x)
+               sd_start(gspca_dev);
+       sd_stopN(gspca_dev);
+/*     set_frame_rate(gspca_dev);      */
+
+       return gspca_dev->usb_err;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int mode;
+       static const struct reg_array bridge_start[NSENSORS][2] = {
+       [SENSOR_OV767x] = {{bridge_start_qvga_767x,
+                                       ARRAY_SIZE(bridge_start_qvga_767x)},
+                       {bridge_start_vga_767x,
+                                       ARRAY_SIZE(bridge_start_vga_767x)}},
+       [SENSOR_OV772x] = {{bridge_start_qvga_772x,
+                                       ARRAY_SIZE(bridge_start_qvga_772x)},
+                       {bridge_start_vga_772x,
+                                       ARRAY_SIZE(bridge_start_vga_772x)}},
+       };
+       static const struct reg_array sensor_start[NSENSORS][2] = {
+       [SENSOR_OV767x] = {{sensor_start_qvga_767x,
+                                       ARRAY_SIZE(sensor_start_qvga_767x)},
+                       {sensor_start_vga_767x,
+                                       ARRAY_SIZE(sensor_start_vga_767x)}},
+       [SENSOR_OV772x] = {{sensor_start_qvga_772x,
+                                       ARRAY_SIZE(sensor_start_qvga_772x)},
+                       {sensor_start_vga_772x,
+                                       ARRAY_SIZE(sensor_start_vga_772x)}},
+       };
+
+       /* (from ms-win trace) */
+       if (sd->sensor == SENSOR_OV767x)
+               sccb_reg_write(gspca_dev, 0x1e, 0x04);
+                                       /* black sun enable ? */
+
+       mode = gspca_dev->curr_mode;    /* 0: 320x240, 1: 640x480 */
+       reg_w_array(gspca_dev, bridge_start[sd->sensor][mode].val,
+                               bridge_start[sd->sensor][mode].len);
+       sccb_w_array(gspca_dev, sensor_start[sd->sensor][mode].val,
+                               sensor_start[sd->sensor][mode].len);
+
+       set_frame_rate(gspca_dev);
+
+       if (sd->hue)
+               sethue(gspca_dev, v4l2_ctrl_g_ctrl(sd->hue));
+       setsaturation(gspca_dev, v4l2_ctrl_g_ctrl(sd->saturation));
+       if (sd->autogain)
+               setagc(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
+       setawb(gspca_dev, v4l2_ctrl_g_ctrl(sd->autowhitebalance));
+       setaec(gspca_dev, v4l2_ctrl_g_ctrl(sd->autoexposure));
+       if (sd->gain)
+               setgain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
+       setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
+       setbrightness(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness));
+       setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast));
+       if (sd->sharpness)
+               setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
+       sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip),
+                 v4l2_ctrl_g_ctrl(sd->vflip));
+       setlightfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->plfreq));
+
+       ov534_set_led(gspca_dev, 1);
+       ov534_reg_write(gspca_dev, 0xe0, 0x00);
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       ov534_reg_write(gspca_dev, 0xe0, 0x09);
+       ov534_set_led(gspca_dev, 0);
+}
+
+/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
+#define UVC_STREAM_EOH (1 << 7)
+#define UVC_STREAM_ERR (1 << 6)
+#define UVC_STREAM_STI (1 << 5)
+#define UVC_STREAM_RES (1 << 4)
+#define UVC_STREAM_SCR (1 << 3)
+#define UVC_STREAM_PTS (1 << 2)
+#define UVC_STREAM_EOF (1 << 1)
+#define UVC_STREAM_FID (1 << 0)
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data, int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       __u32 this_pts;
+       u16 this_fid;
+       int remaining_len = len;
+       int payload_len;
+
+       payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
+       do {
+               len = min(remaining_len, payload_len);
+
+               /* Payloads are prefixed with a UVC-style header.  We
+                  consider a frame to start when the FID toggles, or the PTS
+                  changes.  A frame ends when EOF is set, and we've received
+                  the correct number of bytes. */
+
+               /* Verify UVC header.  Header length is always 12 */
+               if (data[0] != 12 || len < 12) {
+                       PDEBUG(D_PACK, "bad header");
+                       goto discard;
+               }
+
+               /* Check errors */
+               if (data[1] & UVC_STREAM_ERR) {
+                       PDEBUG(D_PACK, "payload error");
+                       goto discard;
+               }
+
+               /* Extract PTS and FID */
+               if (!(data[1] & UVC_STREAM_PTS)) {
+                       PDEBUG(D_PACK, "PTS not present");
+                       goto discard;
+               }
+               this_pts = (data[5] << 24) | (data[4] << 16)
+                                               | (data[3] << 8) | data[2];
+               this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0;
+
+               /* If PTS or FID has changed, start a new frame. */
+               if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
+                       if (gspca_dev->last_packet_type == INTER_PACKET)
+                               gspca_frame_add(gspca_dev, LAST_PACKET,
+                                               NULL, 0);
+                       sd->last_pts = this_pts;
+                       sd->last_fid = this_fid;
+                       gspca_frame_add(gspca_dev, FIRST_PACKET,
+                                       data + 12, len - 12);
+               /* If this packet is marked as EOF, end the frame */
+               } else if (data[1] & UVC_STREAM_EOF) {
+                       sd->last_pts = 0;
+                       if (gspca_dev->pixfmt == V4L2_PIX_FMT_YUYV
+                        && gspca_dev->image_len + len - 12 !=
+                                  gspca_dev->width * gspca_dev->height * 2) {
+                               PDEBUG(D_PACK, "wrong sized frame");
+                               goto discard;
+                       }
+                       gspca_frame_add(gspca_dev, LAST_PACKET,
+                                       data + 12, len - 12);
+               } else {
+
+                       /* Add the data from this payload */
+                       gspca_frame_add(gspca_dev, INTER_PACKET,
+                                       data + 12, len - 12);
+               }
+
+               /* Done this payload */
+               goto scan_next;
+
+discard:
+               /* Discard data until a new frame starts. */
+               gspca_dev->last_packet_type = DISCARD_PACKET;
+
+scan_next:
+               remaining_len -= len;
+               data += len;
+       } while (remaining_len > 0);
+}
+
+/* get stream parameters (framerate) */
+static void sd_get_streamparm(struct gspca_dev *gspca_dev,
+                            struct v4l2_streamparm *parm)
+{
+       struct v4l2_captureparm *cp = &parm->parm.capture;
+       struct v4l2_fract *tpf = &cp->timeperframe;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       cp->capability |= V4L2_CAP_TIMEPERFRAME;
+       tpf->numerator = 1;
+       tpf->denominator = sd->frame_rate;
+}
+
+/* set stream parameters (framerate) */
+static void sd_set_streamparm(struct gspca_dev *gspca_dev,
+                            struct v4l2_streamparm *parm)
+{
+       struct v4l2_captureparm *cp = &parm->parm.capture;
+       struct v4l2_fract *tpf = &cp->timeperframe;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* Set requested framerate */
+       sd->frame_rate = tpf->denominator / tpf->numerator;
+       if (gspca_dev->streaming)
+               set_frame_rate(gspca_dev);
+
+       /* Return the actual framerate */
+       tpf->numerator = 1;
+       tpf->denominator = sd->frame_rate;
+}
+
+/* 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,
+       .stopN    = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+       .get_streamparm = sd_get_streamparm,
+       .set_streamparm = sd_set_streamparm,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x1415, 0x2000)},
+       {USB_DEVICE(0x06f8, 0x3002)},
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/ov534_9.c b/drivers/media/usb/gspca/ov534_9.c
new file mode 100644 (file)
index 0000000..c4cd028
--- /dev/null
@@ -0,0 +1,1500 @@
+/*
+ * ov534-ov9xxx gspca driver
+ *
+ * Copyright (C) 2009-2011 Jean-Francois Moine http://moinejf.free.fr
+ * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
+ * Copyright (C) 2008 Jim Paris <jim@jtan.com>
+ *
+ * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>
+ * USB protocol reverse engineered by Jim Paris <jim@jtan.com>
+ * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "ov534_9"
+
+#include "gspca.h"
+
+#define OV534_REG_ADDRESS      0xf1    /* sensor address */
+#define OV534_REG_SUBADDR      0xf2
+#define OV534_REG_WRITE                0xf3
+#define OV534_REG_READ         0xf4
+#define OV534_REG_OPERATION    0xf5
+#define OV534_REG_STATUS       0xf6
+
+#define OV534_OP_WRITE_3       0x37
+#define OV534_OP_WRITE_2       0x33
+#define OV534_OP_READ_2                0xf9
+
+#define CTRL_TIMEOUT 500
+
+MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
+MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+       __u32 last_pts;
+       u8 last_fid;
+
+       u8 sensor;
+};
+enum sensors {
+       SENSOR_OV965x,          /* ov9657 */
+       SENSOR_OV971x,          /* ov9712 */
+       SENSOR_OV562x,          /* ov5621 */
+       NSENSORS
+};
+
+static const struct v4l2_pix_format ov965x_mode[] = {
+#define QVGA_MODE 0
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+#define VGA_MODE 1
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+#define SVGA_MODE 2
+       {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 800,
+               .sizeimage = 800 * 600 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+#define XGA_MODE 3
+       {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 1024,
+               .sizeimage = 1024 * 768 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+#define SXGA_MODE 4
+       {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 1280,
+               .sizeimage = 1280 * 1024 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+};
+
+static const struct v4l2_pix_format ov971x_mode[] = {
+       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB
+       }
+};
+
+static const struct v4l2_pix_format ov562x_mode[] = {
+       {2592, 1680, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 2592,
+               .sizeimage = 2592 * 1680,
+               .colorspace = V4L2_COLORSPACE_SRGB
+       }
+};
+
+static const u8 bridge_init[][2] = {
+       {0x88, 0xf8},
+       {0x89, 0xff},
+       {0x76, 0x03},
+       {0x92, 0x03},
+       {0x95, 0x10},
+       {0xe2, 0x00},
+       {0xe7, 0x3e},
+       {0x8d, 0x1c},
+       {0x8e, 0x00},
+       {0x8f, 0x00},
+       {0x1f, 0x00},
+       {0xc3, 0xf9},
+       {0x89, 0xff},
+       {0x88, 0xf8},
+       {0x76, 0x03},
+       {0x92, 0x01},
+       {0x93, 0x18},
+       {0x1c, 0x0a},
+       {0x1d, 0x48},
+       {0xc0, 0x50},
+       {0xc1, 0x3c},
+       {0x34, 0x05},
+       {0xc2, 0x0c},
+       {0xc3, 0xf9},
+       {0x34, 0x05},
+       {0xe7, 0x2e},
+       {0x31, 0xf9},
+       {0x35, 0x02},
+       {0xd9, 0x10},
+       {0x25, 0x42},
+       {0x94, 0x11},
+};
+
+static const u8 ov965x_init[][2] = {
+       {0x12, 0x80},   /* com7 - SSCB reset */
+       {0x00, 0x00},   /* gain */
+       {0x01, 0x80},   /* blue */
+       {0x02, 0x80},   /* red */
+       {0x03, 0x1b},   /* vref */
+       {0x04, 0x03},   /* com1 - exposure low bits */
+       {0x0b, 0x57},   /* ver */
+       {0x0e, 0x61},   /* com5 */
+       {0x0f, 0x42},   /* com6 */
+       {0x11, 0x00},   /* clkrc */
+       {0x12, 0x02},   /* com7 - 15fps VGA YUYV */
+       {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
+       {0x14, 0x28},   /* com9 */
+       {0x16, 0x24},   /* reg16 */
+       {0x17, 0x1d},   /* hstart*/
+       {0x18, 0xbd},   /* hstop */
+       {0x19, 0x01},   /* vstrt */
+       {0x1a, 0x81},   /* vstop*/
+       {0x1e, 0x04},   /* mvfp */
+       {0x24, 0x3c},   /* aew */
+       {0x25, 0x36},   /* aeb */
+       {0x26, 0x71},   /* vpt */
+       {0x27, 0x08},   /* bbias */
+       {0x28, 0x08},   /* gbbias */
+       {0x29, 0x15},   /* gr com */
+       {0x2a, 0x00},   /* exhch */
+       {0x2b, 0x00},   /* exhcl */
+       {0x2c, 0x08},   /* rbias */
+       {0x32, 0xff},   /* href */
+       {0x33, 0x00},   /* chlf */
+       {0x34, 0x3f},   /* aref1 */
+       {0x35, 0x00},   /* aref2 */
+       {0x36, 0xf8},   /* aref3 */
+       {0x38, 0x72},   /* adc2 */
+       {0x39, 0x57},   /* aref4 */
+       {0x3a, 0x80},   /* tslb - yuyv */
+       {0x3b, 0xc4},   /* com11 - night mode 1/4 frame rate */
+       {0x3d, 0x99},   /* com13 */
+       {0x3f, 0xc1},   /* edge */
+       {0x40, 0xc0},   /* com15 */
+       {0x41, 0x40},   /* com16 */
+       {0x42, 0xc0},   /* com17 */
+       {0x43, 0x0a},   /* rsvd */
+       {0x44, 0xf0},
+       {0x45, 0x46},
+       {0x46, 0x62},
+       {0x47, 0x2a},
+       {0x48, 0x3c},
+       {0x4a, 0xfc},
+       {0x4b, 0xfc},
+       {0x4c, 0x7f},
+       {0x4d, 0x7f},
+       {0x4e, 0x7f},
+       {0x4f, 0x98},   /* matrix */
+       {0x50, 0x98},
+       {0x51, 0x00},
+       {0x52, 0x28},
+       {0x53, 0x70},
+       {0x54, 0x98},
+       {0x58, 0x1a},   /* matrix coef sign */
+       {0x59, 0x85},   /* AWB control */
+       {0x5a, 0xa9},
+       {0x5b, 0x64},
+       {0x5c, 0x84},
+       {0x5d, 0x53},
+       {0x5e, 0x0e},
+       {0x5f, 0xf0},   /* AWB blue limit */
+       {0x60, 0xf0},   /* AWB red limit */
+       {0x61, 0xf0},   /* AWB green limit */
+       {0x62, 0x00},   /* lcc1 */
+       {0x63, 0x00},   /* lcc2 */
+       {0x64, 0x02},   /* lcc3 */
+       {0x65, 0x16},   /* lcc4 */
+       {0x66, 0x01},   /* lcc5 */
+       {0x69, 0x02},   /* hv */
+       {0x6b, 0x5a},   /* dbvl */
+       {0x6c, 0x04},
+       {0x6d, 0x55},
+       {0x6e, 0x00},
+       {0x6f, 0x9d},
+       {0x70, 0x21},   /* dnsth */
+       {0x71, 0x78},
+       {0x72, 0x00},   /* poidx */
+       {0x73, 0x01},   /* pckdv */
+       {0x74, 0x3a},   /* xindx */
+       {0x75, 0x35},   /* yindx */
+       {0x76, 0x01},
+       {0x77, 0x02},
+       {0x7a, 0x12},   /* gamma curve */
+       {0x7b, 0x08},
+       {0x7c, 0x16},
+       {0x7d, 0x30},
+       {0x7e, 0x5e},
+       {0x7f, 0x72},
+       {0x80, 0x82},
+       {0x81, 0x8e},
+       {0x82, 0x9a},
+       {0x83, 0xa4},
+       {0x84, 0xac},
+       {0x85, 0xb8},
+       {0x86, 0xc3},
+       {0x87, 0xd6},
+       {0x88, 0xe6},
+       {0x89, 0xf2},
+       {0x8a, 0x03},
+       {0x8c, 0x89},   /* com19 */
+       {0x14, 0x28},   /* com9 */
+       {0x90, 0x7d},
+       {0x91, 0x7b},
+       {0x9d, 0x03},   /* lcc6 */
+       {0x9e, 0x04},   /* lcc7 */
+       {0x9f, 0x7a},
+       {0xa0, 0x79},
+       {0xa1, 0x40},   /* aechm */
+       {0xa4, 0x50},   /* com21 */
+       {0xa5, 0x68},   /* com26 */
+       {0xa6, 0x4a},   /* AWB green */
+       {0xa8, 0xc1},   /* refa8 */
+       {0xa9, 0xef},   /* refa9 */
+       {0xaa, 0x92},
+       {0xab, 0x04},
+       {0xac, 0x80},   /* black level control */
+       {0xad, 0x80},
+       {0xae, 0x80},
+       {0xaf, 0x80},
+       {0xb2, 0xf2},
+       {0xb3, 0x20},
+       {0xb4, 0x20},   /* ctrlb4 */
+       {0xb5, 0x00},
+       {0xb6, 0xaf},
+       {0xbb, 0xae},
+       {0xbc, 0x7f},   /* ADC channel offsets */
+       {0xdb, 0x7f},
+       {0xbe, 0x7f},
+       {0xbf, 0x7f},
+       {0xc0, 0xe2},
+       {0xc1, 0xc0},
+       {0xc2, 0x01},
+       {0xc3, 0x4e},
+       {0xc6, 0x85},
+       {0xc7, 0x80},   /* com24 */
+       {0xc9, 0xe0},
+       {0xca, 0xe8},
+       {0xcb, 0xf0},
+       {0xcc, 0xd8},
+       {0xcd, 0xf1},
+       {0x4f, 0x98},   /* matrix */
+       {0x50, 0x98},
+       {0x51, 0x00},
+       {0x52, 0x28},
+       {0x53, 0x70},
+       {0x54, 0x98},
+       {0x58, 0x1a},
+       {0xff, 0x41},   /* read 41, write ff 00 */
+       {0x41, 0x40},   /* com16 */
+
+       {0xc5, 0x03},   /* 60 Hz banding filter */
+       {0x6a, 0x02},   /* 50 Hz banding filter */
+
+       {0x12, 0x62},   /* com7 - 30fps VGA YUV */
+       {0x36, 0xfa},   /* aref3 */
+       {0x69, 0x0a},   /* hv */
+       {0x8c, 0x89},   /* com22 */
+       {0x14, 0x28},   /* com9 */
+       {0x3e, 0x0c},
+       {0x41, 0x40},   /* com16 */
+       {0x72, 0x00},
+       {0x73, 0x00},
+       {0x74, 0x3a},
+       {0x75, 0x35},
+       {0x76, 0x01},
+       {0xc7, 0x80},
+       {0x03, 0x12},   /* vref */
+       {0x17, 0x16},   /* hstart */
+       {0x18, 0x02},   /* hstop */
+       {0x19, 0x01},   /* vstrt */
+       {0x1a, 0x3d},   /* vstop */
+       {0x32, 0xff},   /* href */
+       {0xc0, 0xaa},
+};
+
+static const u8 bridge_init_2[][2] = {
+       {0x94, 0xaa},
+       {0xf1, 0x60},
+       {0xe5, 0x04},
+       {0xc0, 0x50},
+       {0xc1, 0x3c},
+       {0x8c, 0x00},
+       {0x8d, 0x1c},
+       {0x34, 0x05},
+
+       {0xc2, 0x0c},
+       {0xc3, 0xf9},
+       {0xda, 0x01},
+       {0x50, 0x00},
+       {0x51, 0xa0},
+       {0x52, 0x3c},
+       {0x53, 0x00},
+       {0x54, 0x00},
+       {0x55, 0x00},
+       {0x57, 0x00},
+       {0x5c, 0x00},
+       {0x5a, 0xa0},
+       {0x5b, 0x78},
+       {0x35, 0x02},
+       {0xd9, 0x10},
+       {0x94, 0x11},
+};
+
+static const u8 ov965x_init_2[][2] = {
+       {0x3b, 0xc4},
+       {0x1e, 0x04},   /* mvfp */
+       {0x13, 0xe0},   /* com8 */
+       {0x00, 0x00},   /* gain */
+       {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
+       {0x11, 0x03},   /* clkrc */
+       {0x6b, 0x5a},   /* dblv */
+       {0x6a, 0x05},
+       {0xc5, 0x07},
+       {0xa2, 0x4b},
+       {0xa3, 0x3e},
+       {0x2d, 0x00},
+       {0xff, 0x42},   /* read 42, write ff 00 */
+       {0x42, 0xc0},   /* com17 */
+       {0x2d, 0x00},
+       {0xff, 0x42},   /* read 42, write ff 00 */
+       {0x42, 0xc1},   /* com17 */
+/* sharpness */
+       {0x3f, 0x01},
+       {0xff, 0x42},   /* read 42, write ff 00 */
+       {0x42, 0xc1},   /* com17 */
+/* saturation */
+       {0x4f, 0x98},   /* matrix */
+       {0x50, 0x98},
+       {0x51, 0x00},
+       {0x52, 0x28},
+       {0x53, 0x70},
+       {0x54, 0x98},
+       {0x58, 0x1a},
+       {0xff, 0x41},   /* read 41, write ff 00 */
+       {0x41, 0x40},   /* com16 */
+/* contrast */
+       {0x56, 0x40},
+/* brightness */
+       {0x55, 0x8f},
+/* expo */
+       {0x10, 0x25},   /* aech - exposure high bits */
+       {0xff, 0x13},   /* read 13, write ff 00 */
+       {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
+};
+
+static const u8 ov971x_init[][2] = {
+       {0x12, 0x80},
+       {0x09, 0x10},
+       {0x1e, 0x07},
+       {0x5f, 0x18},
+       {0x69, 0x04},
+       {0x65, 0x2a},
+       {0x68, 0x0a},
+       {0x39, 0x28},
+       {0x4d, 0x90},
+       {0xc1, 0x80},
+       {0x0c, 0x30},
+       {0x6d, 0x02},
+       {0x96, 0xf1},
+       {0xbc, 0x68},
+       {0x12, 0x00},
+       {0x3b, 0x00},
+       {0x97, 0x80},
+       {0x17, 0x25},
+       {0x18, 0xa2},
+       {0x19, 0x01},
+       {0x1a, 0xca},
+       {0x03, 0x0a},
+       {0x32, 0x07},
+       {0x98, 0x40},   /*{0x98, 0x00},*/
+       {0x99, 0xA0},   /*{0x99, 0x00},*/
+       {0x9a, 0x01},   /*{0x9a, 0x00},*/
+       {0x57, 0x00},
+       {0x58, 0x78},   /*{0x58, 0xc8},*/
+       {0x59, 0x50},   /*{0x59, 0xa0},*/
+       {0x4c, 0x13},
+       {0x4b, 0x36},
+       {0x3d, 0x3c},
+       {0x3e, 0x03},
+       {0xbd, 0x50},   /*{0xbd, 0xa0},*/
+       {0xbe, 0x78},   /*{0xbe, 0xc8},*/
+       {0x4e, 0x55},
+       {0x4f, 0x55},
+       {0x50, 0x55},
+       {0x51, 0x55},
+       {0x24, 0x55},
+       {0x25, 0x40},
+       {0x26, 0xa1},
+       {0x5c, 0x59},
+       {0x5d, 0x00},
+       {0x11, 0x00},
+       {0x2a, 0x98},
+       {0x2b, 0x06},
+       {0x2d, 0x00},
+       {0x2e, 0x00},
+       {0x13, 0xa5},
+       {0x14, 0x40},
+       {0x4a, 0x00},
+       {0x49, 0xce},
+       {0x22, 0x03},
+       {0x09, 0x00}
+};
+
+static const u8 ov965x_start_1_vga[][2] = {    /* same for qvga */
+       {0x12, 0x62},   /* com7 - 30fps VGA YUV */
+       {0x36, 0xfa},   /* aref3 */
+       {0x69, 0x0a},   /* hv */
+       {0x8c, 0x89},   /* com22 */
+       {0x14, 0x28},   /* com9 */
+       {0x3e, 0x0c},   /* com14 */
+       {0x41, 0x40},   /* com16 */
+       {0x72, 0x00},
+       {0x73, 0x00},
+       {0x74, 0x3a},
+       {0x75, 0x35},
+       {0x76, 0x01},
+       {0xc7, 0x80},   /* com24 */
+       {0x03, 0x12},   /* vref */
+       {0x17, 0x16},   /* hstart */
+       {0x18, 0x02},   /* hstop */
+       {0x19, 0x01},   /* vstrt */
+       {0x1a, 0x3d},   /* vstop */
+       {0x32, 0xff},   /* href */
+       {0xc0, 0xaa},
+};
+
+static const u8 ov965x_start_1_svga[][2] = {
+       {0x12, 0x02},   /* com7 - YUYV - VGA 15 full resolution */
+       {0x36, 0xf8},   /* aref3 */
+       {0x69, 0x02},   /* hv */
+       {0x8c, 0x0d},   /* com22 */
+       {0x3e, 0x0c},   /* com14 */
+       {0x41, 0x40},   /* com16 */
+       {0x72, 0x00},
+       {0x73, 0x01},
+       {0x74, 0x3a},
+       {0x75, 0x35},
+       {0x76, 0x01},
+       {0xc7, 0x80},   /* com24 */
+       {0x03, 0x1b},   /* vref */
+       {0x17, 0x1d},   /* hstart */
+       {0x18, 0xbd},   /* hstop */
+       {0x19, 0x01},   /* vstrt */
+       {0x1a, 0x81},   /* vstop */
+       {0x32, 0xff},   /* href */
+       {0xc0, 0xe2},
+};
+
+static const u8 ov965x_start_1_xga[][2] = {
+       {0x12, 0x02},   /* com7 */
+       {0x36, 0xf8},   /* aref3 */
+       {0x69, 0x02},   /* hv */
+       {0x8c, 0x89},   /* com22 */
+       {0x14, 0x28},   /* com9 */
+       {0x3e, 0x0c},   /* com14 */
+       {0x41, 0x40},   /* com16 */
+       {0x72, 0x00},
+       {0x73, 0x01},
+       {0x74, 0x3a},
+       {0x75, 0x35},
+       {0x76, 0x01},
+       {0xc7, 0x80},   /* com24 */
+       {0x03, 0x1b},   /* vref */
+       {0x17, 0x1d},   /* hstart */
+       {0x18, 0xbd},   /* hstop */
+       {0x19, 0x01},   /* vstrt */
+       {0x1a, 0x81},   /* vstop */
+       {0x32, 0xff},   /* href */
+       {0xc0, 0xe2},
+};
+
+static const u8 ov965x_start_1_sxga[][2] = {
+       {0x12, 0x02},   /* com7 */
+       {0x36, 0xf8},   /* aref3 */
+       {0x69, 0x02},   /* hv */
+       {0x8c, 0x89},   /* com22 */
+       {0x14, 0x28},   /* com9 */
+       {0x3e, 0x0c},   /* com14 */
+       {0x41, 0x40},   /* com16 */
+       {0x72, 0x00},
+       {0x73, 0x01},
+       {0x74, 0x3a},
+       {0x75, 0x35},
+       {0x76, 0x01},
+       {0xc7, 0x80},   /* com24 */
+       {0x03, 0x1b},   /* vref */
+       {0x17, 0x1d},   /* hstart */
+       {0x18, 0x02},   /* hstop */
+       {0x19, 0x01},   /* vstrt */
+       {0x1a, 0x81},   /* vstop */
+       {0x32, 0xff},   /* href */
+       {0xc0, 0xe2},
+};
+
+static const u8 bridge_start_qvga[][2] = {
+       {0x94, 0xaa},
+       {0xf1, 0x60},
+       {0xe5, 0x04},
+       {0xc0, 0x50},
+       {0xc1, 0x3c},
+       {0x8c, 0x00},
+       {0x8d, 0x1c},
+       {0x34, 0x05},
+
+       {0xc2, 0x4c},
+       {0xc3, 0xf9},
+       {0xda, 0x00},
+       {0x50, 0x00},
+       {0x51, 0xa0},
+       {0x52, 0x78},
+       {0x53, 0x00},
+       {0x54, 0x00},
+       {0x55, 0x00},
+       {0x57, 0x00},
+       {0x5c, 0x00},
+       {0x5a, 0x50},
+       {0x5b, 0x3c},
+       {0x35, 0x02},
+       {0xd9, 0x10},
+       {0x94, 0x11},
+};
+
+static const u8 bridge_start_vga[][2] = {
+       {0x94, 0xaa},
+       {0xf1, 0x60},
+       {0xe5, 0x04},
+       {0xc0, 0x50},
+       {0xc1, 0x3c},
+       {0x8c, 0x00},
+       {0x8d, 0x1c},
+       {0x34, 0x05},
+       {0xc2, 0x0c},
+       {0xc3, 0xf9},
+       {0xda, 0x01},
+       {0x50, 0x00},
+       {0x51, 0xa0},
+       {0x52, 0x3c},
+       {0x53, 0x00},
+       {0x54, 0x00},
+       {0x55, 0x00},
+       {0x57, 0x00},
+       {0x5c, 0x00},
+       {0x5a, 0xa0},
+       {0x5b, 0x78},
+       {0x35, 0x02},
+       {0xd9, 0x10},
+       {0x94, 0x11},
+};
+
+static const u8 bridge_start_svga[][2] = {
+       {0x94, 0xaa},
+       {0xf1, 0x60},
+       {0xe5, 0x04},
+       {0xc0, 0xa0},
+       {0xc1, 0x80},
+       {0x8c, 0x00},
+       {0x8d, 0x1c},
+       {0x34, 0x05},
+       {0xc2, 0x4c},
+       {0xc3, 0xf9},
+       {0x50, 0x00},
+       {0x51, 0x40},
+       {0x52, 0x00},
+       {0x53, 0x00},
+       {0x54, 0x00},
+       {0x55, 0x88},
+       {0x57, 0x00},
+       {0x5c, 0x00},
+       {0x5a, 0xc8},
+       {0x5b, 0x96},
+       {0x35, 0x02},
+       {0xd9, 0x10},
+       {0xda, 0x00},
+       {0x94, 0x11},
+};
+
+static const u8 bridge_start_xga[][2] = {
+       {0x94, 0xaa},
+       {0xf1, 0x60},
+       {0xe5, 0x04},
+       {0xc0, 0xa0},
+       {0xc1, 0x80},
+       {0x8c, 0x00},
+       {0x8d, 0x1c},
+       {0x34, 0x05},
+       {0xc2, 0x4c},
+       {0xc3, 0xf9},
+       {0x50, 0x00},
+       {0x51, 0x40},
+       {0x52, 0x00},
+       {0x53, 0x00},
+       {0x54, 0x00},
+       {0x55, 0x88},
+       {0x57, 0x00},
+       {0x5c, 0x01},
+       {0x5a, 0x00},
+       {0x5b, 0xc0},
+       {0x35, 0x02},
+       {0xd9, 0x10},
+       {0xda, 0x01},
+       {0x94, 0x11},
+};
+
+static const u8 bridge_start_sxga[][2] = {
+       {0x94, 0xaa},
+       {0xf1, 0x60},
+       {0xe5, 0x04},
+       {0xc0, 0xa0},
+       {0xc1, 0x80},
+       {0x8c, 0x00},
+       {0x8d, 0x1c},
+       {0x34, 0x05},
+       {0xc2, 0x0c},
+       {0xc3, 0xf9},
+       {0xda, 0x00},
+       {0x35, 0x02},
+       {0xd9, 0x10},
+       {0x94, 0x11},
+};
+
+static const u8 ov965x_start_2_qvga[][2] = {
+       {0x3b, 0xe4},   /* com11 - night mode 1/4 frame rate */
+       {0x1e, 0x04},   /* mvfp */
+       {0x13, 0xe0},   /* com8 */
+       {0x00, 0x00},
+       {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
+       {0x11, 0x01},   /* clkrc */
+       {0x6b, 0x5a},   /* dblv */
+       {0x6a, 0x02},   /* 50 Hz banding filter */
+       {0xc5, 0x03},   /* 60 Hz banding filter */
+       {0xa2, 0x96},   /* bd50 */
+       {0xa3, 0x7d},   /* bd60 */
+
+       {0xff, 0x13},   /* read 13, write ff 00 */
+       {0x13, 0xe7},
+       {0x3a, 0x80},   /* tslb - yuyv */
+};
+
+static const u8 ov965x_start_2_vga[][2] = {
+       {0x3b, 0xc4},   /* com11 - night mode 1/4 frame rate */
+       {0x1e, 0x04},   /* mvfp */
+       {0x13, 0xe0},   /* com8 */
+       {0x00, 0x00},
+       {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
+       {0x11, 0x03},   /* clkrc */
+       {0x6b, 0x5a},   /* dblv */
+       {0x6a, 0x05},   /* 50 Hz banding filter */
+       {0xc5, 0x07},   /* 60 Hz banding filter */
+       {0xa2, 0x4b},   /* bd50 */
+       {0xa3, 0x3e},   /* bd60 */
+
+       {0x2d, 0x00},   /* advfl */
+};
+
+static const u8 ov965x_start_2_svga[][2] = {   /* same for xga */
+       {0x3b, 0xc4},   /* com11 - night mode 1/4 frame rate */
+       {0x1e, 0x04},   /* mvfp */
+       {0x13, 0xe0},   /* com8 */
+       {0x00, 0x00},
+       {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
+       {0x11, 0x01},   /* clkrc */
+       {0x6b, 0x5a},   /* dblv */
+       {0x6a, 0x0c},   /* 50 Hz banding filter */
+       {0xc5, 0x0f},   /* 60 Hz banding filter */
+       {0xa2, 0x4e},   /* bd50 */
+       {0xa3, 0x41},   /* bd60 */
+};
+
+static const u8 ov965x_start_2_sxga[][2] = {
+       {0x13, 0xe0},   /* com8 */
+       {0x00, 0x00},
+       {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
+       {0x3b, 0xc4},   /* com11 - night mode 1/4 frame rate */
+       {0x1e, 0x04},   /* mvfp */
+       {0x11, 0x01},   /* clkrc */
+       {0x6b, 0x5a},   /* dblv */
+       {0x6a, 0x0c},   /* 50 Hz banding filter */
+       {0xc5, 0x0f},   /* 60 Hz banding filter */
+       {0xa2, 0x4e},   /* bd50 */
+       {0xa3, 0x41},   /* bd60 */
+};
+
+static const u8 ov562x_init[][2] = {
+       {0x88, 0x20},
+       {0x89, 0x0a},
+       {0x8a, 0x90},
+       {0x8b, 0x06},
+       {0x8c, 0x01},
+       {0x8d, 0x10},
+       {0x1c, 0x00},
+       {0x1d, 0x48},
+       {0x1d, 0x00},
+       {0x1d, 0xff},
+       {0x1c, 0x0a},
+       {0x1d, 0x2e},
+       {0x1d, 0x1e},
+};
+
+static const u8 ov562x_init_2[][2] = {
+       {0x12, 0x80},
+       {0x11, 0x41},
+       {0x13, 0x00},
+       {0x10, 0x1e},
+       {0x3b, 0x07},
+       {0x5b, 0x40},
+       {0x39, 0x07},
+       {0x53, 0x02},
+       {0x54, 0x60},
+       {0x04, 0x20},
+       {0x27, 0x04},
+       {0x3d, 0x40},
+       {0x36, 0x00},
+       {0xc5, 0x04},
+       {0x4e, 0x00},
+       {0x4f, 0x93},
+       {0x50, 0x7b},
+       {0xca, 0x0c},
+       {0xcb, 0x0f},
+       {0x39, 0x07},
+       {0x4a, 0x10},
+       {0x3e, 0x0a},
+       {0x3d, 0x00},
+       {0x0c, 0x38},
+       {0x38, 0x90},
+       {0x46, 0x30},
+       {0x4f, 0x93},
+       {0x50, 0x7b},
+       {0xab, 0x00},
+       {0xca, 0x0c},
+       {0xcb, 0x0f},
+       {0x37, 0x02},
+       {0x44, 0x48},
+       {0x8d, 0x44},
+       {0x2a, 0x00},
+       {0x2b, 0x00},
+       {0x32, 0x00},
+       {0x38, 0x90},
+       {0x53, 0x02},
+       {0x54, 0x60},
+       {0x12, 0x00},
+       {0x17, 0x12},
+       {0x18, 0xb4},
+       {0x19, 0x0c},
+       {0x1a, 0xf4},
+       {0x03, 0x4a},
+       {0x89, 0x20},
+       {0x83, 0x80},
+       {0xb7, 0x9d},
+       {0xb6, 0x11},
+       {0xb5, 0x55},
+       {0xb4, 0x00},
+       {0xa9, 0xf0},
+       {0xa8, 0x0a},
+       {0xb8, 0xf0},
+       {0xb9, 0xf0},
+       {0xba, 0xf0},
+       {0x81, 0x07},
+       {0x63, 0x44},
+       {0x13, 0xc7},
+       {0x14, 0x60},
+       {0x33, 0x75},
+       {0x2c, 0x00},
+       {0x09, 0x00},
+       {0x35, 0x30},
+       {0x27, 0x04},
+       {0x3c, 0x07},
+       {0x3a, 0x0a},
+       {0x3b, 0x07},
+       {0x01, 0x40},
+       {0x02, 0x40},
+       {0x16, 0x40},
+       {0x52, 0xb0},
+       {0x51, 0x83},
+       {0x21, 0xbb},
+       {0x22, 0x10},
+       {0x23, 0x03},
+       {0x35, 0x38},
+       {0x20, 0x90},
+       {0x28, 0x30},
+       {0x73, 0xe1},
+       {0x6c, 0x00},
+       {0x6d, 0x80},
+       {0x6e, 0x00},
+       {0x70, 0x04},
+       {0x71, 0x00},
+       {0x8d, 0x04},
+       {0x64, 0x00},
+       {0x65, 0x00},
+       {0x66, 0x00},
+       {0x67, 0x00},
+       {0x68, 0x00},
+       {0x69, 0x00},
+       {0x6a, 0x00},
+       {0x6b, 0x00},
+       {0x71, 0x94},
+       {0x74, 0x20},
+       {0x80, 0x09},
+       {0x85, 0xc0},
+};
+
+static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)
+{
+       struct usb_device *udev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       gspca_dev->usb_buf[0] = val;
+       ret = usb_control_msg(udev,
+                             usb_sndctrlpipe(udev, 0),
+                             0x01,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
+       if (ret < 0) {
+               pr_err("reg_w failed %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void reg_w(struct gspca_dev *gspca_dev, u16 reg, u8 val)
+{
+       PDEBUG(D_USBO, "reg_w [%04x] = %02x", reg, val);
+       reg_w_i(gspca_dev, reg, val);
+}
+
+static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg)
+{
+       struct usb_device *udev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return 0;
+       ret = usb_control_msg(udev,
+                             usb_rcvctrlpipe(udev, 0),
+                             0x01,
+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
+       PDEBUG(D_USBI, "reg_r [%04x] -> %02x", reg, gspca_dev->usb_buf[0]);
+       if (ret < 0) {
+               pr_err("reg_r err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+       return gspca_dev->usb_buf[0];
+}
+
+static int sccb_check_status(struct gspca_dev *gspca_dev)
+{
+       u8 data;
+       int i;
+
+       for (i = 0; i < 5; i++) {
+               msleep(10);
+               data = reg_r(gspca_dev, OV534_REG_STATUS);
+
+               switch (data) {
+               case 0x00:
+                       return 1;
+               case 0x04:
+                       return 0;
+               case 0x03:
+                       break;
+               default:
+                       PDEBUG(D_USBI|D_USBO,
+                               "sccb status 0x%02x, attempt %d/5",
+                               data, i + 1);
+               }
+       }
+       return 0;
+}
+
+static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
+{
+       PDEBUG(D_USBO, "sccb_write [%02x] = %02x", reg, val);
+       reg_w_i(gspca_dev, OV534_REG_SUBADDR, reg);
+       reg_w_i(gspca_dev, OV534_REG_WRITE, val);
+       reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
+
+       if (!sccb_check_status(gspca_dev))
+               pr_err("sccb_write failed\n");
+}
+
+static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
+{
+       reg_w(gspca_dev, OV534_REG_SUBADDR, reg);
+       reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
+       if (!sccb_check_status(gspca_dev))
+               pr_err("sccb_read failed 1\n");
+
+       reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
+       if (!sccb_check_status(gspca_dev))
+               pr_err("sccb_read failed 2\n");
+
+       return reg_r(gspca_dev, OV534_REG_READ);
+}
+
+/* output a bridge sequence (reg - val) */
+static void reg_w_array(struct gspca_dev *gspca_dev,
+                       const u8 (*data)[2], int len)
+{
+       while (--len >= 0) {
+               reg_w(gspca_dev, (*data)[0], (*data)[1]);
+               data++;
+       }
+}
+
+/* output a sensor sequence (reg - val) */
+static void sccb_w_array(struct gspca_dev *gspca_dev,
+                       const u8 (*data)[2], int len)
+{
+       while (--len >= 0) {
+               if ((*data)[0] != 0xff) {
+                       sccb_write(gspca_dev, (*data)[0], (*data)[1]);
+               } else {
+                       sccb_read(gspca_dev, (*data)[1]);
+                       sccb_write(gspca_dev, 0xff, 0x00);
+               }
+               data++;
+       }
+}
+
+/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
+ * (direction and output)? */
+static void set_led(struct gspca_dev *gspca_dev, int status)
+{
+       u8 data;
+
+       PDEBUG(D_CONF, "led status: %d", status);
+
+       data = reg_r(gspca_dev, 0x21);
+       data |= 0x80;
+       reg_w(gspca_dev, 0x21, data);
+
+       data = reg_r(gspca_dev, 0x23);
+       if (status)
+               data |= 0x80;
+       else
+               data &= ~0x80;
+
+       reg_w(gspca_dev, 0x23, data);
+
+       if (!status) {
+               data = reg_r(gspca_dev, 0x21);
+               data &= ~0x80;
+               reg_w(gspca_dev, 0x21, data);
+       }
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 val;
+       s8 sval;
+
+       if (sd->sensor == SENSOR_OV562x) {
+               sval = brightness;
+               val = 0x76;
+               val += sval;
+               sccb_write(gspca_dev, 0x24, val);
+               val = 0x6a;
+               val += sval;
+               sccb_write(gspca_dev, 0x25, val);
+               if (sval < -40)
+                       val = 0x71;
+               else if (sval < 20)
+                       val = 0x94;
+               else
+                       val = 0xe6;
+               sccb_write(gspca_dev, 0x26, val);
+       } else {
+               val = brightness;
+               if (val < 8)
+                       val = 15 - val;         /* f .. 8 */
+               else
+                       val = val - 8;          /* 0 .. 7 */
+               sccb_write(gspca_dev, 0x55,     /* brtn - brightness adjustment */
+                               0x0f | (val << 4));
+       }
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
+{
+       sccb_write(gspca_dev, 0x56,     /* cnst1 - contrast 1 ctrl coeff */
+                       val << 4);
+}
+
+static void setautogain(struct gspca_dev *gspca_dev, s32 autogain)
+{
+       u8 val;
+
+/*fixme: should adjust agc/awb/aec by different controls */
+       val = sccb_read(gspca_dev, 0x13);               /* com8 */
+       sccb_write(gspca_dev, 0xff, 0x00);
+       if (autogain)
+               val |= 0x05;            /* agc & aec */
+       else
+               val &= 0xfa;
+       sccb_write(gspca_dev, 0x13, val);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev, s32 exposure)
+{
+       static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
+       u8 val;
+
+       sccb_write(gspca_dev, 0x10, expo[exposure]);    /* aec[9:2] */
+
+       val = sccb_read(gspca_dev, 0x13);               /* com8 */
+       sccb_write(gspca_dev, 0xff, 0x00);
+       sccb_write(gspca_dev, 0x13, val);
+
+       val = sccb_read(gspca_dev, 0xa1);               /* aech */
+       sccb_write(gspca_dev, 0xff, 0x00);
+       sccb_write(gspca_dev, 0xa1, val & 0xe0);        /* aec[15:10] = 0 */
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
+{
+       if (val < 0) {                          /* auto */
+               val = sccb_read(gspca_dev, 0x42);       /* com17 */
+               sccb_write(gspca_dev, 0xff, 0x00);
+               sccb_write(gspca_dev, 0x42, val | 0x40);
+                               /* Edge enhancement strength auto adjust */
+               return;
+       }
+       if (val != 0)
+               val = 1 << (val - 1);
+       sccb_write(gspca_dev, 0x3f,     /* edge - edge enhance. factor */
+                       val);
+       val = sccb_read(gspca_dev, 0x42);               /* com17 */
+       sccb_write(gspca_dev, 0xff, 0x00);
+       sccb_write(gspca_dev, 0x42, val & 0xbf);
+}
+
+static void setsatur(struct gspca_dev *gspca_dev, s32 val)
+{
+       u8 val1, val2, val3;
+       static const u8 matrix[5][2] = {
+               {0x14, 0x38},
+               {0x1e, 0x54},
+               {0x28, 0x70},
+               {0x32, 0x8c},
+               {0x48, 0x90}
+       };
+
+       val1 = matrix[val][0];
+       val2 = matrix[val][1];
+       val3 = val1 + val2;
+       sccb_write(gspca_dev, 0x4f, val3);      /* matrix coeff */
+       sccb_write(gspca_dev, 0x50, val3);
+       sccb_write(gspca_dev, 0x51, 0x00);
+       sccb_write(gspca_dev, 0x52, val1);
+       sccb_write(gspca_dev, 0x53, val2);
+       sccb_write(gspca_dev, 0x54, val3);
+       sccb_write(gspca_dev, 0x58, 0x1a);      /* mtxs - coeff signs */
+
+       val1 = sccb_read(gspca_dev, 0x41);      /* com16 */
+       sccb_write(gspca_dev, 0xff, 0x00);
+       sccb_write(gspca_dev, 0x41, val1);
+}
+
+static void setlightfreq(struct gspca_dev *gspca_dev, s32 freq)
+{
+       u8 val;
+
+       val = sccb_read(gspca_dev, 0x13);               /* com8 */
+       sccb_write(gspca_dev, 0xff, 0x00);
+       if (freq == 0) {
+               sccb_write(gspca_dev, 0x13, val & 0xdf);
+               return;
+       }
+       sccb_write(gspca_dev, 0x13, val | 0x20);
+
+       val = sccb_read(gspca_dev, 0x42);               /* com17 */
+       sccb_write(gspca_dev, 0xff, 0x00);
+       if (freq == 1)
+               val |= 0x01;
+       else
+               val &= 0xfe;
+       sccb_write(gspca_dev, 0x42, val);
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                    const struct usb_device_id *id)
+{
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u16 sensor_id;
+
+       /* reset bridge */
+       reg_w(gspca_dev, 0xe7, 0x3a);
+       reg_w(gspca_dev, 0xe0, 0x08);
+       msleep(100);
+
+       /* initialize the sensor address */
+       reg_w(gspca_dev, OV534_REG_ADDRESS, 0x60);
+
+       /* reset sensor */
+       sccb_write(gspca_dev, 0x12, 0x80);
+       msleep(10);
+
+       /* probe the sensor */
+       sccb_read(gspca_dev, 0x0a);
+       sensor_id = sccb_read(gspca_dev, 0x0a) << 8;
+       sccb_read(gspca_dev, 0x0b);
+       sensor_id |= sccb_read(gspca_dev, 0x0b);
+       PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
+
+       /* initialize */
+       if ((sensor_id & 0xfff0) == 0x9650) {
+               sd->sensor = SENSOR_OV965x;
+
+               gspca_dev->cam.cam_mode = ov965x_mode;
+               gspca_dev->cam.nmodes = ARRAY_SIZE(ov965x_mode);
+
+               reg_w_array(gspca_dev, bridge_init,
+                               ARRAY_SIZE(bridge_init));
+               sccb_w_array(gspca_dev, ov965x_init,
+                               ARRAY_SIZE(ov965x_init));
+               reg_w_array(gspca_dev, bridge_init_2,
+                               ARRAY_SIZE(bridge_init_2));
+               sccb_w_array(gspca_dev, ov965x_init_2,
+                               ARRAY_SIZE(ov965x_init_2));
+               reg_w(gspca_dev, 0xe0, 0x00);
+               reg_w(gspca_dev, 0xe0, 0x01);
+               set_led(gspca_dev, 0);
+               reg_w(gspca_dev, 0xe0, 0x00);
+       } else if ((sensor_id & 0xfff0) == 0x9710) {
+               const char *p;
+               int l;
+
+               sd->sensor = SENSOR_OV971x;
+
+               gspca_dev->cam.cam_mode = ov971x_mode;
+               gspca_dev->cam.nmodes = ARRAY_SIZE(ov971x_mode);
+
+               gspca_dev->cam.bulk = 1;
+               gspca_dev->cam.bulk_size = 16384;
+               gspca_dev->cam.bulk_nurbs = 2;
+
+               sccb_w_array(gspca_dev, ov971x_init,
+                               ARRAY_SIZE(ov971x_init));
+
+               /* set video format on bridge processor */
+               /* access bridge processor's video format registers at: 0x00 */
+               reg_w(gspca_dev, 0x1c, 0x00);
+               /*set register: 0x00 is 'RAW8', 0x40 is 'YUV422' (YUYV?)*/
+               reg_w(gspca_dev, 0x1d, 0x00);
+
+               /* Will W. specific stuff
+                * set VSYNC to
+                *      output (0x1f) if first webcam
+                *      input (0x17) if 2nd or 3rd webcam */
+               p = video_device_node_name(&gspca_dev->vdev);
+               l = strlen(p) - 1;
+               if (p[l] == '0')
+                       reg_w(gspca_dev, 0x56, 0x1f);
+               else
+                       reg_w(gspca_dev, 0x56, 0x17);
+       } else if ((sensor_id & 0xfff0) == 0x5620) {
+               sd->sensor = SENSOR_OV562x;
+               gspca_dev->cam.cam_mode = ov562x_mode;
+               gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode);
+
+               reg_w_array(gspca_dev, ov562x_init,
+                               ARRAY_SIZE(ov562x_init));
+               sccb_w_array(gspca_dev, ov562x_init_2,
+                               ARRAY_SIZE(ov562x_init_2));
+               reg_w(gspca_dev, 0xe0, 0x00);
+       } else {
+               pr_err("Unknown sensor %04x", sensor_id);
+               return -EINVAL;
+       }
+
+       return gspca_dev->usb_err;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_OV971x)
+               return gspca_dev->usb_err;
+       if (sd->sensor == SENSOR_OV562x)
+               return gspca_dev->usb_err;
+
+       switch (gspca_dev->curr_mode) {
+       case QVGA_MODE:                 /* 320x240 */
+               sccb_w_array(gspca_dev, ov965x_start_1_vga,
+                               ARRAY_SIZE(ov965x_start_1_vga));
+               reg_w_array(gspca_dev, bridge_start_qvga,
+                               ARRAY_SIZE(bridge_start_qvga));
+               sccb_w_array(gspca_dev, ov965x_start_2_qvga,
+                               ARRAY_SIZE(ov965x_start_2_qvga));
+               break;
+       case VGA_MODE:                  /* 640x480 */
+               sccb_w_array(gspca_dev, ov965x_start_1_vga,
+                               ARRAY_SIZE(ov965x_start_1_vga));
+               reg_w_array(gspca_dev, bridge_start_vga,
+                               ARRAY_SIZE(bridge_start_vga));
+               sccb_w_array(gspca_dev, ov965x_start_2_vga,
+                               ARRAY_SIZE(ov965x_start_2_vga));
+               break;
+       case SVGA_MODE:                 /* 800x600 */
+               sccb_w_array(gspca_dev, ov965x_start_1_svga,
+                               ARRAY_SIZE(ov965x_start_1_svga));
+               reg_w_array(gspca_dev, bridge_start_svga,
+                               ARRAY_SIZE(bridge_start_svga));
+               sccb_w_array(gspca_dev, ov965x_start_2_svga,
+                               ARRAY_SIZE(ov965x_start_2_svga));
+               break;
+       case XGA_MODE:                  /* 1024x768 */
+               sccb_w_array(gspca_dev, ov965x_start_1_xga,
+                               ARRAY_SIZE(ov965x_start_1_xga));
+               reg_w_array(gspca_dev, bridge_start_xga,
+                               ARRAY_SIZE(bridge_start_xga));
+               sccb_w_array(gspca_dev, ov965x_start_2_svga,
+                               ARRAY_SIZE(ov965x_start_2_svga));
+               break;
+       default:
+/*     case SXGA_MODE:                  * 1280x1024 */
+               sccb_w_array(gspca_dev, ov965x_start_1_sxga,
+                               ARRAY_SIZE(ov965x_start_1_sxga));
+               reg_w_array(gspca_dev, bridge_start_sxga,
+                               ARRAY_SIZE(bridge_start_sxga));
+               sccb_w_array(gspca_dev, ov965x_start_2_sxga,
+                               ARRAY_SIZE(ov965x_start_2_sxga));
+               break;
+       }
+
+       reg_w(gspca_dev, 0xe0, 0x00);
+       reg_w(gspca_dev, 0xe0, 0x00);
+       set_led(gspca_dev, 1);
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       reg_w(gspca_dev, 0xe0, 0x01);
+       set_led(gspca_dev, 0);
+       reg_w(gspca_dev, 0xe0, 0x00);
+}
+
+/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
+#define UVC_STREAM_EOH (1 << 7)
+#define UVC_STREAM_ERR (1 << 6)
+#define UVC_STREAM_STI (1 << 5)
+#define UVC_STREAM_RES (1 << 4)
+#define UVC_STREAM_SCR (1 << 3)
+#define UVC_STREAM_PTS (1 << 2)
+#define UVC_STREAM_EOF (1 << 1)
+#define UVC_STREAM_FID (1 << 0)
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data, int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       __u32 this_pts;
+       u8 this_fid;
+       int remaining_len = len;
+       int payload_len;
+
+       payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
+       do {
+               len = min(remaining_len, payload_len);
+
+               /* Payloads are prefixed with a UVC-style header.  We
+                  consider a frame to start when the FID toggles, or the PTS
+                  changes.  A frame ends when EOF is set, and we've received
+                  the correct number of bytes. */
+
+               /* Verify UVC header.  Header length is always 12 */
+               if (data[0] != 12 || len < 12) {
+                       PDEBUG(D_PACK, "bad header");
+                       goto discard;
+               }
+
+               /* Check errors */
+               if (data[1] & UVC_STREAM_ERR) {
+                       PDEBUG(D_PACK, "payload error");
+                       goto discard;
+               }
+
+               /* Extract PTS and FID */
+               if (!(data[1] & UVC_STREAM_PTS)) {
+                       PDEBUG(D_PACK, "PTS not present");
+                       goto discard;
+               }
+               this_pts = (data[5] << 24) | (data[4] << 16)
+                                               | (data[3] << 8) | data[2];
+               this_fid = data[1] & UVC_STREAM_FID;
+
+               /* If PTS or FID has changed, start a new frame. */
+               if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
+                       if (gspca_dev->last_packet_type == INTER_PACKET)
+                               gspca_frame_add(gspca_dev, LAST_PACKET,
+                                               NULL, 0);
+                       sd->last_pts = this_pts;
+                       sd->last_fid = this_fid;
+                       gspca_frame_add(gspca_dev, FIRST_PACKET,
+                                       data + 12, len - 12);
+               /* If this packet is marked as EOF, end the frame */
+               } else if (data[1] & UVC_STREAM_EOF) {
+                       sd->last_pts = 0;
+                       gspca_frame_add(gspca_dev, LAST_PACKET,
+                                       data + 12, len - 12);
+               } else {
+
+                       /* Add the data from this payload */
+                       gspca_frame_add(gspca_dev, INTER_PACKET,
+                                       data + 12, len - 12);
+               }
+
+               /* Done this payload */
+               goto scan_next;
+
+discard:
+               /* Discard data until a new frame starts. */
+               gspca_dev->last_packet_type = DISCARD_PACKET;
+
+scan_next:
+               remaining_len -= len;
+               data += len;
+       } while (remaining_len > 0);
+}
+
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct gspca_dev *gspca_dev =
+               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+
+       gspca_dev->usb_err = 0;
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               setsatur(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_POWER_LINE_FREQUENCY:
+               setlightfreq(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SHARPNESS:
+               setsharpness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if (ctrl->is_new)
+                       setautogain(gspca_dev, ctrl->val);
+               if (!ctrl->val && gspca_dev->exposure->is_new)
+                       setexposure(gspca_dev, gspca_dev->exposure->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;
+
+       if (sd->sensor == SENSOR_OV971x)
+               return 0;
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 7);
+       if (sd->sensor == SENSOR_OV562x) {
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, -90, 90, 1, 0);
+       } else {
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 15, 1, 7);
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 15, 1, 3);
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 4, 1, 2);
+               /* -1 = auto */
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SHARPNESS, -1, 4, 1, -1);
+               gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0, 3, 1, 0);
+               v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
+                       V4L2_CID_POWER_LINE_FREQUENCY,
+                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
+               v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
+       }
+
+       if (hdl->error) {
+               pr_err("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,
+       .stopN    = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x05a9, 0x8065)},
+       {USB_DEVICE(0x06f8, 0x3003)},
+       {USB_DEVICE(0x05a9, 0x1550)},
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/pac207.c b/drivers/media/usb/gspca/pac207.c
new file mode 100644 (file)
index 0000000..d236d17
--- /dev/null
@@ -0,0 +1,469 @@
+/*
+ * Pixart PAC207BCA library
+ *
+ * Copyright (C) 2008 Hans de Goede <hdegoede@redhat.com>
+ * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
+ * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr
+ *
+ * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "pac207"
+
+#include <linux/input.h>
+#include "gspca.h"
+/* Include pac common sof detection functions */
+#include "pac_common.h"
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("Pixart PAC207");
+MODULE_LICENSE("GPL");
+
+#define PAC207_CTRL_TIMEOUT            100  /* ms */
+
+#define PAC207_BRIGHTNESS_MIN          0
+#define PAC207_BRIGHTNESS_MAX          255
+#define PAC207_BRIGHTNESS_DEFAULT      46
+#define PAC207_BRIGHTNESS_REG          0x08
+
+#define PAC207_EXPOSURE_MIN            3
+#define PAC207_EXPOSURE_MAX            90 /* 1 sec expo time / 1 fps */
+#define PAC207_EXPOSURE_DEFAULT                5 /* power on default: 3 */
+#define PAC207_EXPOSURE_REG            0x02
+
+#define PAC207_GAIN_MIN                        0
+#define PAC207_GAIN_MAX                        31
+#define PAC207_GAIN_DEFAULT            7 /* power on default: 9 */
+#define PAC207_GAIN_REG                        0x0e
+
+#define PAC207_AUTOGAIN_DEADZONE       30
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;             /* !! must be the first item */
+
+       struct v4l2_ctrl *brightness;
+
+       u8 mode;
+       u8 sof_read;
+       u8 header_read;
+       u8 autogain_ignore_frames;
+
+       atomic_t avg_lum;
+};
+
+static const struct v4l2_pix_format sif_mode[] = {
+       {176, 144, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = (176 + 2) * 144,
+                       /* uncompressed, add 2 bytes / line for line header */
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {352, 288, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+                       /* compressed, but only when needed (not compressed
+                          when the framerate is low) */
+               .sizeimage = (352 + 2) * 288,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+static const __u8 pac207_sensor_init[][8] = {
+       {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0x84},
+       {0x49, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
+       {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
+       {0x32, 0x00, 0x96, 0x00, 0xa2, 0x02, 0xaf, 0x00},
+};
+
+static void pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
+       const u8 *buffer, u16 length)
+{
+       struct usb_device *udev = gspca_dev->dev;
+       int err;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       memcpy(gspca_dev->usb_buf, buffer, length);
+
+       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       0x00, index,
+                       gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT);
+       if (err < 0) {
+               pr_err("Failed to write registers to index 0x%04X, error %d\n",
+                      index, err);
+               gspca_dev->usb_err = err;
+       }
+}
+
+static void pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
+{
+       struct usb_device *udev = gspca_dev->dev;
+       int err;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
+       if (err) {
+               pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
+                      index, value, err);
+               gspca_dev->usb_err = err;
+       }
+}
+
+static int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
+{
+       struct usb_device *udev = gspca_dev->dev;
+       int res;
+
+       if (gspca_dev->usb_err < 0)
+               return 0;
+
+       res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       0x00, index,
+                       gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT);
+       if (res < 0) {
+               pr_err("Failed to read a register (index 0x%04X, error %d)\n",
+                      index, res);
+               gspca_dev->usb_err = res;
+               return 0;
+       }
+
+       return gspca_dev->usb_buf[0];
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct cam *cam;
+       u8 idreg[2];
+
+       idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
+       idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
+       idreg[0] = ((idreg[0] & 0x0f) << 4) | ((idreg[1] & 0xf0) >> 4);
+       idreg[1] = idreg[1] & 0x0f;
+       PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X",
+               idreg[0], idreg[1]);
+
+       if (idreg[0] != 0x27) {
+               PDEBUG(D_PROBE, "Error invalid sensor ID!");
+               return -ENODEV;
+       }
+
+       PDEBUG(D_PROBE,
+               "Pixart PAC207BCA Image Processor and Control Chip detected"
+               " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+
+       cam = &gspca_dev->cam;
+       cam->cam_mode = sif_mode;
+       cam->nmodes = ARRAY_SIZE(sif_mode);
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       pac207_write_reg(gspca_dev, 0x41, 0x00);
+                               /* Bit_0=Image Format,
+                                * Bit_1=LED,
+                                * Bit_2=Compression test mode enable */
+       pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
+
+       return gspca_dev->usb_err;
+}
+
+static void setcontrol(struct gspca_dev *gspca_dev, u16 reg, u16 val)
+{
+       pac207_write_reg(gspca_dev, reg, val);
+       pac207_write_reg(gspca_dev, 0x13, 0x01);        /* Bit 0, auto clear */
+       pac207_write_reg(gspca_dev, 0x1c, 0x01);        /* not documented */
+}
+
+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 (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
+               /* when switching to autogain set defaults to make sure
+                  we are on a valid point of the autogain gain /
+                  exposure knee graph, and give this change time to
+                  take effect before doing autogain. */
+               gspca_dev->exposure->val    = PAC207_EXPOSURE_DEFAULT;
+               gspca_dev->gain->val        = PAC207_GAIN_DEFAULT;
+               sd->autogain_ignore_frames  = PAC_AUTOGAIN_IGNORE_FRAMES;
+       }
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setcontrol(gspca_dev, PAC207_BRIGHTNESS_REG, ctrl->val);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
+                       setcontrol(gspca_dev, PAC207_EXPOSURE_REG,
+                                  gspca_dev->exposure->val);
+               if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
+                       setcontrol(gspca_dev, PAC207_GAIN_REG,
+                                  gspca_dev->gain->val);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return gspca_dev->usb_err;
+}
+
+static const struct v4l2_ctrl_ops sd_ctrl_ops = {
+       .s_ctrl = sd_s_ctrl,
+};
+
+/* this function is called at probe time */
+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);
+
+       sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                               V4L2_CID_BRIGHTNESS,
+                               PAC207_BRIGHTNESS_MIN, PAC207_BRIGHTNESS_MAX,
+                               1, PAC207_BRIGHTNESS_DEFAULT);
+       gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                               V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+       gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                               V4L2_CID_EXPOSURE,
+                               PAC207_EXPOSURE_MIN, PAC207_EXPOSURE_MAX,
+                               1, PAC207_EXPOSURE_DEFAULT);
+       gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                               V4L2_CID_GAIN,
+                               PAC207_GAIN_MIN, PAC207_GAIN_MAX,
+                               1, PAC207_GAIN_DEFAULT);
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
+       return 0;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       __u8 mode;
+
+       pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
+       pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
+       pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
+       pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
+       pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[3], 8);
+
+       /* Compression Balance */
+       if (gspca_dev->width == 176)
+               pac207_write_reg(gspca_dev, 0x4a, 0xff);
+       else
+               pac207_write_reg(gspca_dev, 0x4a, 0x30);
+       pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
+       pac207_write_reg(gspca_dev, 0x08, v4l2_ctrl_g_ctrl(sd->brightness));
+
+       /* PGA global gain (Bit 4-0) */
+       pac207_write_reg(gspca_dev, 0x0e,
+               v4l2_ctrl_g_ctrl(gspca_dev->gain));
+       pac207_write_reg(gspca_dev, 0x02,
+               v4l2_ctrl_g_ctrl(gspca_dev->exposure)); /* PXCK = 12MHz /n */
+
+       mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
+       if (gspca_dev->width == 176) {  /* 176x144 */
+               mode |= 0x01;
+               PDEBUG(D_STREAM, "pac207_start mode 176x144");
+       } else {                                /* 352x288 */
+               PDEBUG(D_STREAM, "pac207_start mode 352x288");
+       }
+       pac207_write_reg(gspca_dev, 0x41, mode);
+
+       pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
+       pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
+       msleep(10);
+       pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
+
+       sd->sof_read = 0;
+       sd->autogain_ignore_frames = 0;
+       atomic_set(&sd->avg_lum, -1);
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
+       pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
+       pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
+}
+
+
+static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int avg_lum = atomic_read(&sd->avg_lum);
+
+       if (avg_lum == -1)
+               return;
+
+       if (sd->autogain_ignore_frames > 0)
+               sd->autogain_ignore_frames--;
+       else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
+                       90, PAC207_AUTOGAIN_DEADZONE))
+               sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,
+                       int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       unsigned char *sof;
+
+       sof = pac_find_sof(&sd->sof_read, data, len);
+       if (sof) {
+               int n;
+
+               /* finish decoding current frame */
+               n = sof - data;
+               if (n > sizeof pac_sof_marker)
+                       n -= sizeof pac_sof_marker;
+               else
+                       n = 0;
+               gspca_frame_add(gspca_dev, LAST_PACKET,
+                               data, n);
+               sd->header_read = 0;
+               gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
+               len -= sof - data;
+               data = sof;
+       }
+       if (sd->header_read < 11) {
+               int needed;
+
+               /* get average lumination from frame header (byte 5) */
+               if (sd->header_read < 5) {
+                       needed = 5 - sd->header_read;
+                       if (len >= needed)
+                               atomic_set(&sd->avg_lum, data[needed - 1]);
+               }
+               /* skip the rest of the header */
+               needed = 11 - sd->header_read;
+               if (len <= needed) {
+                       sd->header_read += len;
+                       return;
+               }
+               data += needed;
+               len -= needed;
+               sd->header_read = 11;
+       }
+
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,               /* interrupt packet data */
+                       int len)                /* interrput packet length */
+{
+       int ret = -EINVAL;
+
+       if (len == 2 && data[0] == 0x5a && data[1] == 0x5a) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
+               input_sync(gspca_dev->input_dev);
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+               input_sync(gspca_dev->input_dev);
+               ret = 0;
+       }
+
+       return ret;
+}
+#endif
+
+/* 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,
+       .stopN = sd_stopN,
+       .dq_callback = pac207_do_auto_gain,
+       .pkt_scan = sd_pkt_scan,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .int_pkt_scan = sd_int_pkt_scan,
+#endif
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x041e, 0x4028)},
+       {USB_DEVICE(0x093a, 0x2460)},
+       {USB_DEVICE(0x093a, 0x2461)},
+       {USB_DEVICE(0x093a, 0x2463)},
+       {USB_DEVICE(0x093a, 0x2464)},
+       {USB_DEVICE(0x093a, 0x2468)},
+       {USB_DEVICE(0x093a, 0x2470)},
+       {USB_DEVICE(0x093a, 0x2471)},
+       {USB_DEVICE(0x093a, 0x2472)},
+       {USB_DEVICE(0x093a, 0x2474)},
+       {USB_DEVICE(0x093a, 0x2476)},
+       {USB_DEVICE(0x145f, 0x013a)},
+       {USB_DEVICE(0x2001, 0xf115)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c
new file mode 100644 (file)
index 0000000..4877f7a
--- /dev/null
@@ -0,0 +1,932 @@
+/*
+ * Pixart PAC7302 driver
+ *
+ * Copyright (C) 2008-2012 Jean-Francois Moine <http://moinejf.free.fr>
+ * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
+ *
+ * Separated from Pixart PAC7311 library by Márton Németh
+ * Camera button input handling by Márton Németh <nm127@freemail.hu>
+ * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Some documentation about various registers as determined by trial and error.
+ *
+ * Register page 1:
+ *
+ * Address     Description
+ * 0x78                Global control, bit 6 controls the LED (inverted)
+ * 0x80                Compression balance, 2 interesting settings:
+ *             0x0f Default
+ *             0x50 Values >= this switch the camera to a lower compression,
+ *                  using the same table for both luminance and chrominance.
+ *                  This gives a sharper picture. Only usable when running
+ *                  at < 15 fps! Note currently the driver does not use this
+ *                  as the quality gain is small and the generated JPG-s are
+ *                  only understood by v4l-utils >= 0.8.9
+ *
+ * Register page 3:
+ *
+ * Address     Description
+ * 0x02                Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on
+ *             the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
+ * 0x03                Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps
+ * 0x04                Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps,
+ *             63 -> ~27 fps, the 2 msb's must always be 1 !!
+ * 0x05                Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0:
+ *             1 -> ~30 fps, 2 -> ~20 fps
+ * 0x0e                Exposure bits 0-7, 0-448, 0 = use full frame time
+ * 0x0f                Exposure bit 8, 0-448, 448 = no exposure at all
+ * 0x10                Gain 0-31
+ * 0x12                Another gain 0-31, unlike 0x10 this one seems to start with an
+ *             amplification value of 1 rather then 0 at its lowest setting
+ * 0x21                Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
+ * 0x80                Another framerate control, best left at 1, moving it from 1 to
+ *             2 causes the framerate to become 3/4th of what it was, and
+ *             also seems to cause pixel averaging, resulting in an effective
+ *             resolution of 320x240 and thus a much blockier image
+ *
+ * The registers are accessed in the following functions:
+ *
+ * Page | Register   | Function
+ * -----+------------+---------------------------------------------------
+ *  0   | 0x0f..0x20 | setcolors()
+ *  0   | 0xa2..0xab | setbrightcont()
+ *  0   | 0xc5       | setredbalance()
+ *  0   | 0xc6       | setwhitebalance()
+ *  0   | 0xc7       | setbluebalance()
+ *  0   | 0xdc       | setbrightcont(), setcolors()
+ *  3   | 0x02       | setexposure()
+ *  3   | 0x10, 0x12 | setgain()
+ *  3   | 0x11       | setcolors(), setgain(), setexposure(), sethvflip()
+ *  3   | 0x21       | sethvflip()
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/input.h>
+#include <media/v4l2-chip-ident.h>
+#include "gspca.h"
+/* Include pac common sof detection functions */
+#include "pac_common.h"
+
+#define PAC7302_GAIN_DEFAULT      15
+#define PAC7302_GAIN_KNEE         42
+#define PAC7302_EXPOSURE_DEFAULT  66 /* 33 ms / 30 fps */
+#define PAC7302_EXPOSURE_KNEE    133 /* 66 ms / 15 fps */
+
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
+               "Thomas Kaiser thomas@kaiser-linux.li");
+MODULE_DESCRIPTION("Pixart PAC7302");
+MODULE_LICENSE("GPL");
+
+struct sd {
+       struct gspca_dev gspca_dev;             /* !! must be the first item */
+
+       struct { /* brightness / contrast cluster */
+               struct v4l2_ctrl *brightness;
+               struct v4l2_ctrl *contrast;
+       };
+       struct v4l2_ctrl *saturation;
+       struct v4l2_ctrl *white_balance;
+       struct v4l2_ctrl *red_balance;
+       struct v4l2_ctrl *blue_balance;
+       struct { /* flip cluster */
+               struct v4l2_ctrl *hflip;
+               struct v4l2_ctrl *vflip;
+       };
+       u8 flags;
+#define FL_HFLIP 0x01          /* mirrored by default */
+#define FL_VFLIP 0x02          /* vertical flipped by default */
+
+       u8 sof_read;
+       s8 autogain_ignore_frames;
+
+       atomic_t avg_lum;
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+       },
+};
+
+#define LOAD_PAGE3             255
+#define END_OF_SEQUENCE                0
+
+static const u8 init_7302[] = {
+/*     index,value */
+       0xff, 0x01,             /* page 1 */
+       0x78, 0x00,             /* deactivate */
+       0xff, 0x01,
+       0x78, 0x40,             /* led off */
+};
+static const u8 start_7302[] = {
+/*     index, len, [value]* */
+       0xff, 1,        0x00,           /* page 0 */
+       0x00, 12,       0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
+                       0x00, 0x00, 0x00, 0x00,
+       0x0d, 24,       0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
+                       0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
+                       0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
+       0x26, 2,        0xaa, 0xaa,
+       0x2e, 1,        0x31,
+       0x38, 1,        0x01,
+       0x3a, 3,        0x14, 0xff, 0x5a,
+       0x43, 11,       0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
+                       0x00, 0x54, 0x11,
+       0x55, 1,        0x00,
+       0x62, 4,        0x10, 0x1e, 0x1e, 0x18,
+       0x6b, 1,        0x00,
+       0x6e, 3,        0x08, 0x06, 0x00,
+       0x72, 3,        0x00, 0xff, 0x00,
+       0x7d, 23,       0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
+                       0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
+                       0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
+       0xa2, 10,       0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
+                       0xd2, 0xeb,
+       0xaf, 1,        0x02,
+       0xb5, 2,        0x08, 0x08,
+       0xb8, 2,        0x08, 0x88,
+       0xc4, 4,        0xae, 0x01, 0x04, 0x01,
+       0xcc, 1,        0x00,
+       0xd1, 11,       0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
+                       0xc1, 0xd7, 0xec,
+       0xdc, 1,        0x01,
+       0xff, 1,        0x01,           /* page 1 */
+       0x12, 3,        0x02, 0x00, 0x01,
+       0x3e, 2,        0x00, 0x00,
+       0x76, 5,        0x01, 0x20, 0x40, 0x00, 0xf2,
+       0x7c, 1,        0x00,
+       0x7f, 10,       0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
+                       0x02, 0x00,
+       0x96, 5,        0x01, 0x10, 0x04, 0x01, 0x04,
+       0xc8, 14,       0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+                       0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
+       0xd8, 1,        0x01,
+       0xdb, 2,        0x00, 0x01,
+       0xde, 7,        0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
+       0xe6, 4,        0x00, 0x00, 0x00, 0x01,
+       0xeb, 1,        0x00,
+       0xff, 1,        0x02,           /* page 2 */
+       0x22, 1,        0x00,
+       0xff, 1,        0x03,           /* page 3 */
+       0, LOAD_PAGE3,                  /* load the page 3 */
+       0x11, 1,        0x01,
+       0xff, 1,        0x02,           /* page 2 */
+       0x13, 1,        0x00,
+       0x22, 4,        0x1f, 0xa4, 0xf0, 0x96,
+       0x27, 2,        0x14, 0x0c,
+       0x2a, 5,        0xc8, 0x00, 0x18, 0x12, 0x22,
+       0x64, 8,        0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
+       0x6e, 1,        0x08,
+       0xff, 1,        0x01,           /* page 1 */
+       0x78, 1,        0x00,
+       0, END_OF_SEQUENCE              /* end of sequence */
+};
+
+#define SKIP           0xaa
+/* page 3 - the value SKIP says skip the index - see reg_w_page() */
+static const u8 page3_7302[] = {
+       0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
+       0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
+       0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
+       0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
+       0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
+       0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
+       0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
+       SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
+       0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
+       0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
+       0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
+       0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
+       0x00
+};
+
+static void reg_w_buf(struct gspca_dev *gspca_dev,
+               u8 index,
+                 const u8 *buffer, int len)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       memcpy(gspca_dev->usb_buf, buffer, len);
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0,              /* request */
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,              /* value */
+                       index, gspca_dev->usb_buf, len,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_w_buf failed i: %02x error %d\n",
+                      index, ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+
+static void reg_w(struct gspca_dev *gspca_dev,
+               u8 index,
+               u8 value)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       gspca_dev->usb_buf[0] = value;
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0,                      /* request */
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0, index, gspca_dev->usb_buf, 1,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_w() failed i: %02x v: %02x error %d\n",
+                      index, value, ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void reg_w_seq(struct gspca_dev *gspca_dev,
+               const u8 *seq, int len)
+{
+       while (--len >= 0) {
+               reg_w(gspca_dev, seq[0], seq[1]);
+               seq += 2;
+       }
+}
+
+/* load the beginning of a page */
+static void reg_w_page(struct gspca_dev *gspca_dev,
+                       const u8 *page, int len)
+{
+       int index;
+       int ret = 0;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       for (index = 0; index < len; index++) {
+               if (page[index] == SKIP)                /* skip this index */
+                       continue;
+               gspca_dev->usb_buf[0] = page[index];
+               ret = usb_control_msg(gspca_dev->dev,
+                               usb_sndctrlpipe(gspca_dev->dev, 0),
+                               0,                      /* request */
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               0, index, gspca_dev->usb_buf, 1,
+                               500);
+               if (ret < 0) {
+                       pr_err("reg_w_page() failed i: %02x v: %02x error %d\n",
+                              index, page[index], ret);
+                       gspca_dev->usb_err = ret;
+                       break;
+               }
+       }
+}
+
+/* output a variable sequence */
+static void reg_w_var(struct gspca_dev *gspca_dev,
+                       const u8 *seq,
+                       const u8 *page3, unsigned int page3_len)
+{
+       int index, len;
+
+       for (;;) {
+               index = *seq++;
+               len = *seq++;
+               switch (len) {
+               case END_OF_SEQUENCE:
+                       return;
+               case LOAD_PAGE3:
+                       reg_w_page(gspca_dev, page3, page3_len);
+                       break;
+               default:
+#ifdef GSPCA_DEBUG
+                       if (len > USB_BUF_SZ) {
+                               PDEBUG(D_ERR|D_STREAM,
+                                       "Incorrect variable sequence");
+                               return;
+                       }
+#endif
+                       while (len > 0) {
+                               if (len < 8) {
+                                       reg_w_buf(gspca_dev,
+                                               index, seq, len);
+                                       seq += len;
+                                       break;
+                               }
+                               reg_w_buf(gspca_dev, index, seq, 8);
+                               seq += 8;
+                               index += 8;
+                               len -= 8;
+                       }
+               }
+       }
+       /* not reached */
+}
+
+/* this function is called at probe time for pac7302 */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+
+       cam = &gspca_dev->cam;
+
+       cam->cam_mode = vga_mode;       /* only 640x480 */
+       cam->nmodes = ARRAY_SIZE(vga_mode);
+
+       sd->flags = id->driver_info;
+       return 0;
+}
+
+static void setbrightcont(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i, v;
+       static const u8 max[10] =
+               {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
+                0xd4, 0xec};
+       static const u8 delta[10] =
+               {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
+                0x11, 0x0b};
+
+       reg_w(gspca_dev, 0xff, 0x00);           /* page 0 */
+       for (i = 0; i < 10; i++) {
+               v = max[i];
+               v += (sd->brightness->val - sd->brightness->maximum)
+                       * 150 / sd->brightness->maximum; /* 200 ? */
+               v -= delta[i] * sd->contrast->val / sd->contrast->maximum;
+               if (v < 0)
+                       v = 0;
+               else if (v > 0xff)
+                       v = 0xff;
+               reg_w(gspca_dev, 0xa2 + i, v);
+       }
+       reg_w(gspca_dev, 0xdc, 0x01);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i, v;
+       static const int a[9] =
+               {217, -212, 0, -101, 170, -67, -38, -315, 355};
+       static const int b[9] =
+               {19, 106, 0, 19, 106, 1, 19, 106, 1};
+
+       reg_w(gspca_dev, 0xff, 0x03);                   /* page 3 */
+       reg_w(gspca_dev, 0x11, 0x01);
+       reg_w(gspca_dev, 0xff, 0x00);                   /* page 0 */
+       for (i = 0; i < 9; i++) {
+               v = a[i] * sd->saturation->val / sd->saturation->maximum;
+               v += b[i];
+               reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
+               reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
+       }
+       reg_w(gspca_dev, 0xdc, 0x01);
+}
+
+static void setwhitebalance(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       reg_w(gspca_dev, 0xff, 0x00);           /* page 0 */
+       reg_w(gspca_dev, 0xc6, sd->white_balance->val);
+
+       reg_w(gspca_dev, 0xdc, 0x01);
+}
+
+static void setredbalance(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       reg_w(gspca_dev, 0xff, 0x00);           /* page 0 */
+       reg_w(gspca_dev, 0xc5, sd->red_balance->val);
+
+       reg_w(gspca_dev, 0xdc, 0x01);
+}
+
+static void setbluebalance(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       reg_w(gspca_dev, 0xff, 0x00);                   /* page 0 */
+       reg_w(gspca_dev, 0xc7, sd->blue_balance->val);
+
+       reg_w(gspca_dev, 0xdc, 0x01);
+}
+
+static void setgain(struct gspca_dev *gspca_dev)
+{
+       u8 reg10, reg12;
+
+       if (gspca_dev->gain->val < 32) {
+               reg10 = gspca_dev->gain->val;
+               reg12 = 0;
+       } else {
+               reg10 = 31;
+               reg12 = gspca_dev->gain->val - 31;
+       }
+
+       reg_w(gspca_dev, 0xff, 0x03);                   /* page 3 */
+       reg_w(gspca_dev, 0x10, reg10);
+       reg_w(gspca_dev, 0x12, reg12);
+
+       /* load registers to sensor (Bit 0, auto clear) */
+       reg_w(gspca_dev, 0x11, 0x01);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+       u8 clockdiv;
+       u16 exposure;
+
+       /*
+        * Register 2 of frame 3 contains the clock divider configuring the
+        * no fps according to the formula: 90 / reg. sd->exposure is the
+        * desired exposure time in 0.5 ms.
+        */
+       clockdiv = (90 * gspca_dev->exposure->val + 1999) / 2000;
+
+       /*
+        * Note clockdiv = 3 also works, but when running at 30 fps, depending
+        * on the scene being recorded, the camera switches to another
+        * quantization table for certain JPEG blocks, and we don't know how
+        * to decompress these blocks. So we cap the framerate at 15 fps.
+        */
+       if (clockdiv < 6)
+               clockdiv = 6;
+       else if (clockdiv > 63)
+               clockdiv = 63;
+
+       /*
+        * Register 2 MUST be a multiple of 3, except when between 6 and 12?
+        * Always round up, otherwise we cannot get the desired frametime
+        * using the partial frame time exposure control.
+        */
+       if (clockdiv < 6 || clockdiv > 12)
+               clockdiv = ((clockdiv + 2) / 3) * 3;
+
+       /*
+        * frame exposure time in ms = 1000 * clockdiv / 90    ->
+        * exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90)
+        */
+       exposure = (gspca_dev->exposure->val * 45 * 448) / (1000 * clockdiv);
+       /* 0 = use full frametime, 448 = no exposure, reverse it */
+       exposure = 448 - exposure;
+
+       reg_w(gspca_dev, 0xff, 0x03);                   /* page 3 */
+       reg_w(gspca_dev, 0x02, clockdiv);
+       reg_w(gspca_dev, 0x0e, exposure & 0xff);
+       reg_w(gspca_dev, 0x0f, exposure >> 8);
+
+       /* load registers to sensor (Bit 0, auto clear) */
+       reg_w(gspca_dev, 0x11, 0x01);
+}
+
+static void sethvflip(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 data, hflip, vflip;
+
+       hflip = sd->hflip->val;
+       if (sd->flags & FL_HFLIP)
+               hflip = !hflip;
+       vflip = sd->vflip->val;
+       if (sd->flags & FL_VFLIP)
+               vflip = !vflip;
+
+       reg_w(gspca_dev, 0xff, 0x03);                   /* page 3 */
+       data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
+       reg_w(gspca_dev, 0x21, data);
+
+       /* load registers to sensor (Bit 0, auto clear) */
+       reg_w(gspca_dev, 0x11, 0x01);
+}
+
+/* this function is called at probe and resume time for pac7302 */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
+       return gspca_dev->usb_err;
+}
+
+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 (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
+               /* when switching to autogain set defaults to make sure
+                  we are on a valid point of the autogain gain /
+                  exposure knee graph, and give this change time to
+                  take effect before doing autogain. */
+               gspca_dev->exposure->val    = PAC7302_EXPOSURE_DEFAULT;
+               gspca_dev->gain->val        = PAC7302_GAIN_DEFAULT;
+               sd->autogain_ignore_frames  = PAC_AUTOGAIN_IGNORE_FRAMES;
+       }
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setbrightcont(gspca_dev);
+               break;
+       case V4L2_CID_SATURATION:
+               setcolors(gspca_dev);
+               break;
+       case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
+               setwhitebalance(gspca_dev);
+               break;
+       case V4L2_CID_RED_BALANCE:
+               setredbalance(gspca_dev);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               setbluebalance(gspca_dev);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
+                       setexposure(gspca_dev);
+               if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
+                       setgain(gspca_dev);
+               break;
+       case V4L2_CID_HFLIP:
+               sethvflip(gspca_dev);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return gspca_dev->usb_err;
+}
+
+static const struct v4l2_ctrl_ops sd_ctrl_ops = {
+       .s_ctrl = sd_s_ctrl,
+};
+
+/* this function is called at probe time */
+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, 11);
+
+       sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_BRIGHTNESS, 0, 32, 1, 16);
+       sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_CONTRAST, 0, 255, 1, 127);
+
+       sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_SATURATION, 0, 255, 1, 127);
+       sd->white_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_WHITE_BALANCE_TEMPERATURE,
+                                       0, 255, 1, 4);
+       sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_RED_BALANCE, 0, 3, 1, 1);
+       sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_RED_BALANCE, 0, 3, 1, 1);
+
+       gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+       gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_EXPOSURE, 0, 1023, 1,
+                                       PAC7302_EXPOSURE_DEFAULT);
+       gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_GAIN, 0, 62, 1,
+                                       PAC7302_GAIN_DEFAULT);
+
+       sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+               V4L2_CID_HFLIP, 0, 1, 1, 0);
+       sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+               V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+
+       v4l2_ctrl_cluster(2, &sd->brightness);
+       v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
+       v4l2_ctrl_cluster(2, &sd->hflip);
+       return 0;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       reg_w_var(gspca_dev, start_7302,
+               page3_7302, sizeof(page3_7302));
+       setbrightcont(gspca_dev);
+       setcolors(gspca_dev);
+       setwhitebalance(gspca_dev);
+       setredbalance(gspca_dev);
+       setbluebalance(gspca_dev);
+       setexposure(gspca_dev);
+       setgain(gspca_dev);
+       sethvflip(gspca_dev);
+
+       sd->sof_read = 0;
+       sd->autogain_ignore_frames = 0;
+       atomic_set(&sd->avg_lum, 270 + sd->brightness->val);
+
+       /* start stream */
+       reg_w(gspca_dev, 0xff, 0x01);
+       reg_w(gspca_dev, 0x78, 0x01);
+
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+
+       /* stop stream */
+       reg_w(gspca_dev, 0xff, 0x01);
+       reg_w(gspca_dev, 0x78, 0x00);
+}
+
+/* called on streamoff with alt 0 and on disconnect for pac7302 */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       if (!gspca_dev->present)
+               return;
+       reg_w(gspca_dev, 0xff, 0x01);
+       reg_w(gspca_dev, 0x78, 0x40);
+}
+
+static void do_autogain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int avg_lum = atomic_read(&sd->avg_lum);
+       int desired_lum;
+       const int deadzone = 30;
+
+       if (sd->autogain_ignore_frames < 0)
+               return;
+
+       if (sd->autogain_ignore_frames > 0) {
+               sd->autogain_ignore_frames--;
+       } else {
+               desired_lum = 270 + sd->brightness->val;
+
+               if (gspca_expo_autogain(gspca_dev, avg_lum, desired_lum,
+                                       deadzone, PAC7302_GAIN_KNEE,
+                                       PAC7302_EXPOSURE_KNEE))
+                       sd->autogain_ignore_frames =
+                                               PAC_AUTOGAIN_IGNORE_FRAMES;
+       }
+}
+
+/* JPEG header */
+static const u8 jpeg_header[] = {
+       0xff, 0xd8,     /* SOI: Start of Image */
+
+       0xff, 0xc0,     /* SOF0: Start of Frame (Baseline DCT) */
+       0x00, 0x11,     /* length = 17 bytes (including this length field) */
+       0x08,           /* Precision: 8 */
+       0x02, 0x80,     /* height = 640 (image rotated) */
+       0x01, 0xe0,     /* width = 480 */
+       0x03,           /* Number of image components: 3 */
+       0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
+       0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
+       0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
+
+       0xff, 0xda,     /* SOS: Start Of Scan */
+       0x00, 0x0c,     /* length = 12 bytes (including this length field) */
+       0x03,           /* number of components: 3 */
+       0x01, 0x00,     /* selector 1, table 0x00 */
+       0x02, 0x11,     /* selector 2, table 0x11 */
+       0x03, 0x11,     /* selector 3, table 0x11 */
+       0x00, 0x3f,     /* Spectral selection: 0 .. 63 */
+       0x00            /* Successive approximation: 0 */
+};
+
+/* this function is run at interrupt level */
+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;
+       u8 *image;
+       u8 *sof;
+
+       sof = pac_find_sof(&sd->sof_read, data, len);
+       if (sof) {
+               int n, lum_offset, footer_length;
+
+               /*
+                * 6 bytes after the FF D9 EOF marker a number of lumination
+                * bytes are send corresponding to different parts of the
+                * image, the 14th and 15th byte after the EOF seem to
+                * correspond to the center of the image.
+                */
+               lum_offset = 61 + sizeof pac_sof_marker;
+               footer_length = 74;
+
+               /* Finish decoding current frame */
+               n = (sof - data) - (footer_length + sizeof pac_sof_marker);
+               if (n < 0) {
+                       gspca_dev->image_len += n;
+                       n = 0;
+               } else {
+                       gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
+               }
+
+               image = gspca_dev->image;
+               if (image != NULL
+                && image[gspca_dev->image_len - 2] == 0xff
+                && image[gspca_dev->image_len - 1] == 0xd9)
+                       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+
+               n = sof - data;
+               len -= n;
+               data = sof;
+
+               /* Get average lumination */
+               if (gspca_dev->last_packet_type == LAST_PACKET &&
+                               n >= lum_offset)
+                       atomic_set(&sd->avg_lum, data[-lum_offset] +
+                                               data[-lum_offset + 1]);
+
+               /* Start the new frame with the jpeg header */
+               /* The PAC7302 has the image rotated 90 degrees */
+               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                               jpeg_header, sizeof jpeg_header);
+       }
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
+                       struct v4l2_dbg_register *reg)
+{
+       u8 index;
+       u8 value;
+
+       /*
+        * reg->reg: bit0..15: reserved for register index (wIndex is 16bit
+        *                     long on the USB bus)
+        */
+       if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
+           reg->match.addr == 0 &&
+           (reg->reg < 0x000000ff) &&
+           (reg->val <= 0x000000ff)
+       ) {
+               /* Currently writing to page 0 is only supported. */
+               /* reg_w() only supports 8bit index */
+               index = reg->reg;
+               value = reg->val;
+
+               /*
+                * Note that there shall be no access to other page
+                * by any other function between the page switch and
+                * the actual register write.
+                */
+               reg_w(gspca_dev, 0xff, 0x00);           /* page 0 */
+               reg_w(gspca_dev, index, value);
+
+               reg_w(gspca_dev, 0xdc, 0x01);
+       }
+       return gspca_dev->usb_err;
+}
+
+static int sd_chip_ident(struct gspca_dev *gspca_dev,
+                       struct v4l2_dbg_chip_ident *chip)
+{
+       int ret = -EINVAL;
+
+       if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
+           chip->match.addr == 0) {
+               chip->revision = 0;
+               chip->ident = V4L2_IDENT_UNKNOWN;
+               ret = 0;
+       }
+       return ret;
+}
+#endif
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,               /* interrupt packet data */
+                       int len)                /* interrput packet length */
+{
+       int ret = -EINVAL;
+       u8 data0, data1;
+
+       if (len == 2) {
+               data0 = data[0];
+               data1 = data[1];
+               if ((data0 == 0x00 && data1 == 0x11) ||
+                   (data0 == 0x22 && data1 == 0x33) ||
+                   (data0 == 0x44 && data1 == 0x55) ||
+                   (data0 == 0x66 && data1 == 0x77) ||
+                   (data0 == 0x88 && data1 == 0x99) ||
+                   (data0 == 0xaa && data1 == 0xbb) ||
+                   (data0 == 0xcc && data1 == 0xdd) ||
+                   (data0 == 0xee && data1 == 0xff)) {
+                       input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
+                       input_sync(gspca_dev->input_dev);
+                       input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+                       input_sync(gspca_dev->input_dev);
+                       ret = 0;
+               }
+       }
+
+       return ret;
+}
+#endif
+
+/* sub-driver description for pac7302 */
+static const struct sd_desc sd_desc = {
+       .name = KBUILD_MODNAME,
+       .config = sd_config,
+       .init = sd_init,
+       .init_controls = sd_init_controls,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .stop0 = sd_stop0,
+       .pkt_scan = sd_pkt_scan,
+       .dq_callback = do_autogain,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .set_register = sd_dbg_s_register,
+       .get_chip_ident = sd_chip_ident,
+#endif
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .int_pkt_scan = sd_int_pkt_scan,
+#endif
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x06f8, 0x3009)},
+       {USB_DEVICE(0x06f8, 0x301b)},
+       {USB_DEVICE(0x093a, 0x2620)},
+       {USB_DEVICE(0x093a, 0x2621)},
+       {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
+       {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
+       {USB_DEVICE(0x093a, 0x2625)},
+       {USB_DEVICE(0x093a, 0x2626)},
+       {USB_DEVICE(0x093a, 0x2627), .driver_info = FL_VFLIP},
+       {USB_DEVICE(0x093a, 0x2628)},
+       {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
+       {USB_DEVICE(0x093a, 0x262a)},
+       {USB_DEVICE(0x093a, 0x262c)},
+       {USB_DEVICE(0x145f, 0x013c)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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 = KBUILD_MODNAME,
+       .id_table = device_table,
+       .probe = sd_probe,
+       .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/pac7311.c b/drivers/media/usb/gspca/pac7311.c
new file mode 100644 (file)
index 0000000..ba3558d
--- /dev/null
@@ -0,0 +1,701 @@
+/*
+ *             Pixart PAC7311 library
+ *             Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
+ *
+ * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* Some documentation about various registers as determined by trial and error.
+ *
+ * Register page 1:
+ *
+ * Address     Description
+ * 0x08                Unknown compressor related, must always be 8 except when not
+ *             in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
+ * 0x1b                Auto white balance related, bit 0 is AWB enable (inverted)
+ *             bits 345 seem to toggle per color gains on/off (inverted)
+ * 0x78                Global control, bit 6 controls the LED (inverted)
+ * 0x80                Compression balance, interesting settings:
+ *             0x01 Use this to allow the camera to switch to higher compr.
+ *                  on the fly. Needed to stay within bandwidth @ 640x480@30
+ *             0x1c From usb captures under Windows for 640x480
+ *             0x2a Values >= this switch the camera to a lower compression,
+ *                  using the same table for both luminance and chrominance.
+ *                  This gives a sharper picture. Usable only at 640x480@ <
+ *                  15 fps or 320x240 / 160x120. Note currently the driver
+ *                  does not use this as the quality gain is small and the
+ *                  generated JPG-s are only understood by v4l-utils >= 0.8.9
+ *             0x3f From usb captures under Windows for 320x240
+ *             0x69 From usb captures under Windows for 160x120
+ *
+ * Register page 4:
+ *
+ * Address     Description
+ * 0x02                Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
+ *             the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
+ * 0x0f                Master gain 1-245, low value = high gain
+ * 0x10                Another gain 0-15, limited influence (1-2x gain I guess)
+ * 0x21                Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
+ *             Note setting vflip disabled leads to a much lower image quality,
+ *             so we always vflip, and tell userspace to flip it back
+ * 0x27                Seems to toggle various gains on / off, Setting bit 7 seems to
+ *             completely disable the analog amplification block. Set to 0x68
+ *             for max gain, 0x14 for minimal gain.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "pac7311"
+
+#include <linux/input.h>
+#include "gspca.h"
+/* Include pac common sof detection functions */
+#include "pac_common.h"
+
+#define PAC7311_GAIN_DEFAULT     122
+#define PAC7311_EXPOSURE_DEFAULT   3 /* 20 fps, avoid using high compr. */
+
+MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
+MODULE_DESCRIPTION("Pixart PAC7311");
+MODULE_LICENSE("GPL");
+
+struct sd {
+       struct gspca_dev gspca_dev;             /* !! must be the first item */
+
+       struct v4l2_ctrl *contrast;
+       struct v4l2_ctrl *hflip;
+
+       u8 sof_read;
+       u8 autogain_ignore_frames;
+
+       atomic_t avg_lum;
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2},
+       {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+
+#define LOAD_PAGE4             254
+#define END_OF_SEQUENCE                0
+
+static const __u8 init_7311[] = {
+       0xff, 0x01,
+       0x78, 0x40,     /* Bit_0=start stream, Bit_6=LED */
+       0x78, 0x40,     /* Bit_0=start stream, Bit_6=LED */
+       0x78, 0x44,     /* Bit_0=start stream, Bit_6=LED */
+       0xff, 0x04,
+       0x27, 0x80,
+       0x28, 0xca,
+       0x29, 0x53,
+       0x2a, 0x0e,
+       0xff, 0x01,
+       0x3e, 0x20,
+};
+
+static const __u8 start_7311[] = {
+/*     index, len, [value]* */
+       0xff, 1,        0x01,           /* page 1 */
+       0x02, 43,       0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
+                       0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
+                       0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
+                       0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00,
+       0x3e, 42,       0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
+                       0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
+                       0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
+                       0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
+                       0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
+                       0xd0, 0xff,
+       0x78, 6,        0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
+       0x7f, 18,       0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
+                       0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
+                       0x18, 0x20,
+       0x96, 3,        0x01, 0x08, 0x04,
+       0xa0, 4,        0x44, 0x44, 0x44, 0x04,
+       0xf0, 13,       0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
+                       0x3f, 0x00, 0x0a, 0x01, 0x00,
+       0xff, 1,        0x04,           /* page 4 */
+       0, LOAD_PAGE4,                  /* load the page 4 */
+       0x11, 1,        0x01,
+       0, END_OF_SEQUENCE              /* end of sequence */
+};
+
+#define SKIP           0xaa
+/* page 4 - the value SKIP says skip the index - see reg_w_page() */
+static const __u8 page4_7311[] = {
+       SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
+       0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
+       0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
+       SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
+       0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
+       0x23, 0x28, 0x04, 0x11, 0x00, 0x00
+};
+
+static void reg_w_buf(struct gspca_dev *gspca_dev,
+                 __u8 index,
+                 const u8 *buffer, int len)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       memcpy(gspca_dev->usb_buf, buffer, len);
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0,              /* request */
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,              /* value */
+                       index, gspca_dev->usb_buf, len,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
+                      index, ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+
+static void reg_w(struct gspca_dev *gspca_dev,
+                 __u8 index,
+                 __u8 value)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       gspca_dev->usb_buf[0] = value;
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0,                      /* request */
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0, index, gspca_dev->usb_buf, 1,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
+                      index, value, ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void reg_w_seq(struct gspca_dev *gspca_dev,
+               const __u8 *seq, int len)
+{
+       while (--len >= 0) {
+               reg_w(gspca_dev, seq[0], seq[1]);
+               seq += 2;
+       }
+}
+
+/* load the beginning of a page */
+static void reg_w_page(struct gspca_dev *gspca_dev,
+                       const __u8 *page, int len)
+{
+       int index;
+       int ret = 0;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       for (index = 0; index < len; index++) {
+               if (page[index] == SKIP)                /* skip this index */
+                       continue;
+               gspca_dev->usb_buf[0] = page[index];
+               ret = usb_control_msg(gspca_dev->dev,
+                               usb_sndctrlpipe(gspca_dev->dev, 0),
+                               0,                      /* request */
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               0, index, gspca_dev->usb_buf, 1,
+                               500);
+               if (ret < 0) {
+                       pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
+                              index, page[index], ret);
+                       gspca_dev->usb_err = ret;
+                       break;
+               }
+       }
+}
+
+/* output a variable sequence */
+static void reg_w_var(struct gspca_dev *gspca_dev,
+                       const __u8 *seq,
+                       const __u8 *page4, unsigned int page4_len)
+{
+       int index, len;
+
+       for (;;) {
+               index = *seq++;
+               len = *seq++;
+               switch (len) {
+               case END_OF_SEQUENCE:
+                       return;
+               case LOAD_PAGE4:
+                       reg_w_page(gspca_dev, page4, page4_len);
+                       break;
+               default:
+                       if (len > USB_BUF_SZ) {
+                               PDEBUG(D_ERR|D_STREAM,
+                                       "Incorrect variable sequence");
+                               return;
+                       }
+                       while (len > 0) {
+                               if (len < 8) {
+                                       reg_w_buf(gspca_dev,
+                                               index, seq, len);
+                                       seq += len;
+                                       break;
+                               }
+                               reg_w_buf(gspca_dev, index, seq, 8);
+                               seq += 8;
+                               index += 8;
+                               len -= 8;
+                       }
+               }
+       }
+       /* not reached */
+}
+
+/* this function is called at probe time for pac7311 */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct cam *cam = &gspca_dev->cam;
+
+       cam->cam_mode = vga_mode;
+       cam->nmodes = ARRAY_SIZE(vga_mode);
+       cam->input_flags = V4L2_IN_ST_VFLIP;
+
+       return 0;
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_w(gspca_dev, 0xff, 0x04);
+       reg_w(gspca_dev, 0x10, val);
+       /* load registers to sensor (Bit 0, auto clear) */
+       reg_w(gspca_dev, 0x11, 0x01);
+}
+
+static void setgain(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_w(gspca_dev, 0xff, 0x04);                   /* page 4 */
+       reg_w(gspca_dev, 0x0e, 0x00);
+       reg_w(gspca_dev, 0x0f, gspca_dev->gain->maximum - val + 1);
+
+       /* load registers to sensor (Bit 0, auto clear) */
+       reg_w(gspca_dev, 0x11, 0x01);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_w(gspca_dev, 0xff, 0x04);                   /* page 4 */
+       reg_w(gspca_dev, 0x02, val);
+
+       /* load registers to sensor (Bit 0, auto clear) */
+       reg_w(gspca_dev, 0x11, 0x01);
+
+       /*
+        * Page 1 register 8 must always be 0x08 except when not in
+        *  640x480 mode and page 4 reg 2 <= 3 then it must be 9
+        */
+       reg_w(gspca_dev, 0xff, 0x01);
+       if (gspca_dev->width != 640 && val <= 3)
+               reg_w(gspca_dev, 0x08, 0x09);
+       else
+               reg_w(gspca_dev, 0x08, 0x08);
+
+       /*
+        * Page1 register 80 sets the compression balance, normally we
+        * want / use 0x1c, but for 640x480@30fps we must allow the
+        * camera to use higher compression or we may run out of
+        * bandwidth.
+        */
+       if (gspca_dev->width == 640 && val == 2)
+               reg_w(gspca_dev, 0x80, 0x01);
+       else
+               reg_w(gspca_dev, 0x80, 0x1c);
+
+       /* load registers to sensor (Bit 0, auto clear) */
+       reg_w(gspca_dev, 0x11, 0x01);
+}
+
+static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
+{
+       __u8 data;
+
+       reg_w(gspca_dev, 0xff, 0x04);                   /* page 4 */
+       data = (hflip ? 0x04 : 0x00) |
+              (vflip ? 0x08 : 0x00);
+       reg_w(gspca_dev, 0x21, data);
+
+       /* load registers to sensor (Bit 0, auto clear) */
+       reg_w(gspca_dev, 0x11, 0x01);
+}
+
+/* this function is called at probe and resume time for pac7311 */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
+       return gspca_dev->usb_err;
+}
+
+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 (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
+               /* when switching to autogain set defaults to make sure
+                  we are on a valid point of the autogain gain /
+                  exposure knee graph, and give this change time to
+                  take effect before doing autogain. */
+               gspca_dev->exposure->val    = PAC7311_EXPOSURE_DEFAULT;
+               gspca_dev->gain->val        = PAC7311_GAIN_DEFAULT;
+               sd->autogain_ignore_frames  = PAC_AUTOGAIN_IGNORE_FRAMES;
+       }
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
+                       setexposure(gspca_dev, gspca_dev->exposure->val);
+               if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
+                       setgain(gspca_dev, gspca_dev->gain->val);
+               break;
+       case V4L2_CID_HFLIP:
+               sethvflip(gspca_dev, sd->hflip->val, 1);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return gspca_dev->usb_err;
+}
+
+static const struct v4l2_ctrl_ops sd_ctrl_ops = {
+       .s_ctrl = sd_s_ctrl,
+};
+
+/* this function is called at probe time */
+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, 5);
+
+       sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_CONTRAST, 0, 15, 1, 7);
+       gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+       gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_EXPOSURE, 2, 63, 1,
+                                       PAC7311_EXPOSURE_DEFAULT);
+       gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_GAIN, 0, 244, 1,
+                                       PAC7311_GAIN_DEFAULT);
+       sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+               V4L2_CID_HFLIP, 0, 1, 1, 0);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+
+       v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
+       return 0;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->sof_read = 0;
+
+       reg_w_var(gspca_dev, start_7311,
+               page4_7311, sizeof(page4_7311));
+       setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast));
+       setgain(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->gain));
+       setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
+       sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), 1);
+
+       /* set correct resolution */
+       switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
+       case 2:                                 /* 160x120 */
+               reg_w(gspca_dev, 0xff, 0x01);
+               reg_w(gspca_dev, 0x17, 0x20);
+               reg_w(gspca_dev, 0x87, 0x10);
+               break;
+       case 1:                                 /* 320x240 */
+               reg_w(gspca_dev, 0xff, 0x01);
+               reg_w(gspca_dev, 0x17, 0x30);
+               reg_w(gspca_dev, 0x87, 0x11);
+               break;
+       case 0:                                 /* 640x480 */
+               reg_w(gspca_dev, 0xff, 0x01);
+               reg_w(gspca_dev, 0x17, 0x00);
+               reg_w(gspca_dev, 0x87, 0x12);
+               break;
+       }
+
+       sd->sof_read = 0;
+       sd->autogain_ignore_frames = 0;
+       atomic_set(&sd->avg_lum, -1);
+
+       /* start stream */
+       reg_w(gspca_dev, 0xff, 0x01);
+       reg_w(gspca_dev, 0x78, 0x05);
+
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       reg_w(gspca_dev, 0xff, 0x04);
+       reg_w(gspca_dev, 0x27, 0x80);
+       reg_w(gspca_dev, 0x28, 0xca);
+       reg_w(gspca_dev, 0x29, 0x53);
+       reg_w(gspca_dev, 0x2a, 0x0e);
+       reg_w(gspca_dev, 0xff, 0x01);
+       reg_w(gspca_dev, 0x3e, 0x20);
+       reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
+       reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
+       reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
+}
+
+static void do_autogain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int avg_lum = atomic_read(&sd->avg_lum);
+       int desired_lum, deadzone;
+
+       if (avg_lum == -1)
+               return;
+
+       desired_lum = 170;
+       deadzone = 20;
+
+       if (sd->autogain_ignore_frames > 0)
+               sd->autogain_ignore_frames--;
+       else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
+                                                   desired_lum, deadzone))
+               sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
+}
+
+/* JPEG header, part 1 */
+static const unsigned char pac_jpeg_header1[] = {
+  0xff, 0xd8,          /* SOI: Start of Image */
+
+  0xff, 0xc0,          /* SOF0: Start of Frame (Baseline DCT) */
+  0x00, 0x11,          /* length = 17 bytes (including this length field) */
+  0x08                 /* Precision: 8 */
+  /* 2 bytes is placed here: number of image lines */
+  /* 2 bytes is placed here: samples per line */
+};
+
+/* JPEG header, continued */
+static const unsigned char pac_jpeg_header2[] = {
+  0x03,                        /* Number of image components: 3 */
+  0x01, 0x21, 0x00,    /* ID=1, Subsampling 1x1, Quantization table: 0 */
+  0x02, 0x11, 0x01,    /* ID=2, Subsampling 2x1, Quantization table: 1 */
+  0x03, 0x11, 0x01,    /* ID=3, Subsampling 2x1, Quantization table: 1 */
+
+  0xff, 0xda,          /* SOS: Start Of Scan */
+  0x00, 0x0c,          /* length = 12 bytes (including this length field) */
+  0x03,                        /* number of components: 3 */
+  0x01, 0x00,          /* selector 1, table 0x00 */
+  0x02, 0x11,          /* selector 2, table 0x11 */
+  0x03, 0x11,          /* selector 3, table 0x11 */
+  0x00, 0x3f,          /* Spectral selection: 0 .. 63 */
+  0x00                 /* Successive approximation: 0 */
+};
+
+static void pac_start_frame(struct gspca_dev *gspca_dev,
+               __u16 lines, __u16 samples_per_line)
+{
+       unsigned char tmpbuf[4];
+
+       gspca_frame_add(gspca_dev, FIRST_PACKET,
+               pac_jpeg_header1, sizeof(pac_jpeg_header1));
+
+       tmpbuf[0] = lines >> 8;
+       tmpbuf[1] = lines & 0xff;
+       tmpbuf[2] = samples_per_line >> 8;
+       tmpbuf[3] = samples_per_line & 0xff;
+
+       gspca_frame_add(gspca_dev, INTER_PACKET,
+               tmpbuf, sizeof(tmpbuf));
+       gspca_frame_add(gspca_dev, INTER_PACKET,
+               pac_jpeg_header2, sizeof(pac_jpeg_header2));
+}
+
+/* this function is run at interrupt level */
+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;
+       u8 *image;
+       unsigned char *sof;
+
+       sof = pac_find_sof(&sd->sof_read, data, len);
+       if (sof) {
+               int n, lum_offset, footer_length;
+
+               /*
+                * 6 bytes after the FF D9 EOF marker a number of lumination
+                * bytes are send corresponding to different parts of the
+                * image, the 14th and 15th byte after the EOF seem to
+                * correspond to the center of the image.
+                */
+               lum_offset = 24 + sizeof pac_sof_marker;
+               footer_length = 26;
+
+               /* Finish decoding current frame */
+               n = (sof - data) - (footer_length + sizeof pac_sof_marker);
+               if (n < 0) {
+                       gspca_dev->image_len += n;
+                       n = 0;
+               } else {
+                       gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
+               }
+               image = gspca_dev->image;
+               if (image != NULL
+                && image[gspca_dev->image_len - 2] == 0xff
+                && image[gspca_dev->image_len - 1] == 0xd9)
+                       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+
+               n = sof - data;
+               len -= n;
+               data = sof;
+
+               /* Get average lumination */
+               if (gspca_dev->last_packet_type == LAST_PACKET &&
+                               n >= lum_offset)
+                       atomic_set(&sd->avg_lum, data[-lum_offset] +
+                                               data[-lum_offset + 1]);
+               else
+                       atomic_set(&sd->avg_lum, -1);
+
+               /* Start the new frame with the jpeg header */
+               pac_start_frame(gspca_dev,
+                       gspca_dev->height, gspca_dev->width);
+       }
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,               /* interrupt packet data */
+                       int len)                /* interrupt packet length */
+{
+       int ret = -EINVAL;
+       u8 data0, data1;
+
+       if (len == 2) {
+               data0 = data[0];
+               data1 = data[1];
+               if ((data0 == 0x00 && data1 == 0x11) ||
+                   (data0 == 0x22 && data1 == 0x33) ||
+                   (data0 == 0x44 && data1 == 0x55) ||
+                   (data0 == 0x66 && data1 == 0x77) ||
+                   (data0 == 0x88 && data1 == 0x99) ||
+                   (data0 == 0xaa && data1 == 0xbb) ||
+                   (data0 == 0xcc && data1 == 0xdd) ||
+                   (data0 == 0xee && data1 == 0xff)) {
+                       input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
+                       input_sync(gspca_dev->input_dev);
+                       input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+                       input_sync(gspca_dev->input_dev);
+                       ret = 0;
+               }
+       }
+
+       return ret;
+}
+#endif
+
+static const struct sd_desc sd_desc = {
+       .name = MODULE_NAME,
+       .config = sd_config,
+       .init = sd_init,
+       .init_controls = sd_init_controls,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+       .dq_callback = do_autogain,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .int_pkt_scan = sd_int_pkt_scan,
+#endif
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x093a, 0x2600)},
+       {USB_DEVICE(0x093a, 0x2601)},
+       {USB_DEVICE(0x093a, 0x2603)},
+       {USB_DEVICE(0x093a, 0x2608)},
+       {USB_DEVICE(0x093a, 0x260e)},
+       {USB_DEVICE(0x093a, 0x260f)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/pac_common.h b/drivers/media/usb/gspca/pac_common.h
new file mode 100644 (file)
index 0000000..8462a7c
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Pixart PAC207BCA / PAC73xx common functions
+ *
+ * Copyright (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
+ * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
+ * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr
+ *
+ * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/* We calculate the autogain at the end of the transfer of a frame, at this
+   moment a frame with the old settings is being captured and transmitted. So
+   if we adjust the gain or exposure we must ignore atleast the next frame for
+   the new settings to come into effect before doing any other adjustments. */
+#define PAC_AUTOGAIN_IGNORE_FRAMES     2
+
+static const unsigned char pac_sof_marker[5] =
+               { 0xff, 0xff, 0x00, 0xff, 0x96 };
+
+/*
+   The following state machine finds the SOF marker sequence
+   0xff, 0xff, 0x00, 0xff, 0x96 in a byte stream.
+
+          +----------+
+          | 0: START |<---------------\
+          +----------+<-\             |
+            |       \---/otherwise    |
+            v 0xff                    |
+          +----------+ otherwise      |
+          |     1    |--------------->*
+          |          |                ^
+          +----------+                |
+            |                         |
+            v 0xff                    |
+          +----------+<-\0xff         |
+       /->|          |--/             |
+       |  |     2    |--------------->*
+       |  |          | otherwise      ^
+       |  +----------+                |
+       |    |                         |
+       |    v 0x00                    |
+       |  +----------+                |
+       |  |     3    |                |
+       |  |          |--------------->*
+       |  +----------+ otherwise      ^
+       |    |                         |
+   0xff |    v 0xff                    |
+       |  +----------+                |
+       \--|     4    |                |
+          |          |----------------/
+          +----------+ otherwise
+            |
+            v 0x96
+          +----------+
+          |  FOUND   |
+          +----------+
+*/
+
+static unsigned char *pac_find_sof(u8 *sof_read,
+                                       unsigned char *m, int len)
+{
+       int i;
+
+       /* Search for the SOF marker (fixed part) in the header */
+       for (i = 0; i < len; i++) {
+               switch (*sof_read) {
+               case 0:
+                       if (m[i] == 0xff)
+                               *sof_read = 1;
+                       break;
+               case 1:
+                       if (m[i] == 0xff)
+                               *sof_read = 2;
+                       else
+                               *sof_read = 0;
+                       break;
+               case 2:
+                       switch (m[i]) {
+                       case 0x00:
+                               *sof_read = 3;
+                               break;
+                       case 0xff:
+                               /* stay in this state */
+                               break;
+                       default:
+                               *sof_read = 0;
+                       }
+                       break;
+               case 3:
+                       if (m[i] == 0xff)
+                               *sof_read = 4;
+                       else
+                               *sof_read = 0;
+                       break;
+               case 4:
+                       switch (m[i]) {
+                       case 0x96:
+                               /* Pattern found */
+                               PDEBUG(D_FRAM,
+                                       "SOF found, bytes to analyze: %u."
+                                       " Frame starts at byte #%u",
+                                       len, i + 1);
+                               *sof_read = 0;
+                               return m + i + 1;
+                               break;
+                       case 0xff:
+                               *sof_read = 2;
+                               break;
+                       default:
+                               *sof_read = 0;
+                       }
+                       break;
+               default:
+                       *sof_read = 0;
+               }
+       }
+
+       return NULL;
+}
diff --git a/drivers/media/usb/gspca/se401.c b/drivers/media/usb/gspca/se401.c
new file mode 100644 (file)
index 0000000..a33cb78
--- /dev/null
@@ -0,0 +1,739 @@
+/*
+ * GSPCA Endpoints (formerly known as AOX) se401 USB Camera sub Driver
+ *
+ * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on the v4l1 se401 driver which is:
+ *
+ * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "se401"
+
+#define BULK_SIZE 4096
+#define PACKET_SIZE 1024
+#define READ_REQ_SIZE 64
+#define MAX_MODES ((READ_REQ_SIZE - 6) / 4)
+/* The se401 compression algorithm uses a fixed quant factor, which
+   can be configured by setting the high nibble of the SE401_OPERATINGMODE
+   feature. This needs to exactly match what is in libv4l! */
+#define SE401_QUANT_FACT 8
+
+#include <linux/input.h>
+#include <linux/slab.h>
+#include "gspca.h"
+#include "se401.h"
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("Endpoints se401");
+MODULE_LICENSE("GPL");
+
+/* exposure change state machine states */
+enum {
+       EXPO_CHANGED,
+       EXPO_DROP_FRAME,
+       EXPO_NO_CHANGE,
+};
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+       struct { /* exposure/freq control cluster */
+               struct v4l2_ctrl *exposure;
+               struct v4l2_ctrl *freq;
+       };
+       bool has_brightness;
+       struct v4l2_pix_format fmts[MAX_MODES];
+       int pixels_read;
+       int packet_read;
+       u8 packet[PACKET_SIZE];
+       u8 restart_stream;
+       u8 button_state;
+       u8 resetlevel;
+       u8 resetlevel_frame_count;
+       int resetlevel_adjust_dir;
+       int expo_change_state;
+};
+
+
+static void se401_write_req(struct gspca_dev *gspca_dev, u16 req, u16 value,
+                           int silent)
+{
+       int err;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       err = usb_control_msg(gspca_dev->dev,
+                             usb_sndctrlpipe(gspca_dev->dev, 0), req,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             value, 0, NULL, 0, 1000);
+       if (err < 0) {
+               if (!silent)
+                       pr_err("write req failed req %#04x val %#04x error %d\n",
+                              req, value, err);
+               gspca_dev->usb_err = err;
+       }
+}
+
+static void se401_read_req(struct gspca_dev *gspca_dev, u16 req, int silent)
+{
+       int err;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       if (USB_BUF_SZ < READ_REQ_SIZE) {
+               pr_err("USB_BUF_SZ too small!!\n");
+               gspca_dev->usb_err = -ENOBUFS;
+               return;
+       }
+
+       err = usb_control_msg(gspca_dev->dev,
+                             usb_rcvctrlpipe(gspca_dev->dev, 0), req,
+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0, 0, gspca_dev->usb_buf, READ_REQ_SIZE, 1000);
+       if (err < 0) {
+               if (!silent)
+                       pr_err("read req failed req %#04x error %d\n",
+                              req, err);
+               gspca_dev->usb_err = err;
+       }
+}
+
+static void se401_set_feature(struct gspca_dev *gspca_dev,
+                             u16 selector, u16 param)
+{
+       int err;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       err = usb_control_msg(gspca_dev->dev,
+                             usb_sndctrlpipe(gspca_dev->dev, 0),
+                             SE401_REQ_SET_EXT_FEATURE,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             param, selector, NULL, 0, 1000);
+       if (err < 0) {
+               pr_err("set feature failed sel %#04x param %#04x error %d\n",
+                      selector, param, err);
+               gspca_dev->usb_err = err;
+       }
+}
+
+static int se401_get_feature(struct gspca_dev *gspca_dev, u16 selector)
+{
+       int err;
+
+       if (gspca_dev->usb_err < 0)
+               return gspca_dev->usb_err;
+
+       if (USB_BUF_SZ < 2) {
+               pr_err("USB_BUF_SZ too small!!\n");
+               gspca_dev->usb_err = -ENOBUFS;
+               return gspca_dev->usb_err;
+       }
+
+       err = usb_control_msg(gspca_dev->dev,
+                             usb_rcvctrlpipe(gspca_dev->dev, 0),
+                             SE401_REQ_GET_EXT_FEATURE,
+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0, selector, gspca_dev->usb_buf, 2, 1000);
+       if (err < 0) {
+               pr_err("get feature failed sel %#04x error %d\n",
+                      selector, err);
+               gspca_dev->usb_err = err;
+               return err;
+       }
+       return gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8);
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       /* HDG: this does not seem to do anything on my cam */
+       se401_write_req(gspca_dev, SE401_REQ_SET_BRT, val, 0);
+}
+
+static void setgain(struct gspca_dev *gspca_dev, s32 val)
+{
+       u16 gain = 63 - val;
+
+       /* red color gain */
+       se401_set_feature(gspca_dev, HV7131_REG_ARCG, gain);
+       /* green color gain */
+       se401_set_feature(gspca_dev, HV7131_REG_AGCG, gain);
+       /* blue color gain */
+       se401_set_feature(gspca_dev, HV7131_REG_ABCG, gain);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev, s32 val, s32 freq)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int integration = val << 6;
+       u8 expose_h, expose_m, expose_l;
+
+       /* Do this before the set_feature calls, for proper timing wrt
+          the interrupt driven pkt_scan. Note we may still race but that
+          is not a big issue, the expo change state machine is merely for
+          avoiding underexposed frames getting send out, if one sneaks
+          through so be it */
+       sd->expo_change_state = EXPO_CHANGED;
+
+       if (freq == V4L2_CID_POWER_LINE_FREQUENCY_50HZ)
+               integration = integration - integration % 106667;
+       if (freq == V4L2_CID_POWER_LINE_FREQUENCY_60HZ)
+               integration = integration - integration % 88889;
+
+       expose_h = (integration >> 16);
+       expose_m = (integration >> 8);
+       expose_l = integration;
+
+       /* integration time low */
+       se401_set_feature(gspca_dev, HV7131_REG_TITL, expose_l);
+       /* integration time mid */
+       se401_set_feature(gspca_dev, HV7131_REG_TITM, expose_m);
+       /* integration time high */
+       se401_set_feature(gspca_dev, HV7131_REG_TITU, expose_h);
+}
+
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+       struct cam *cam = &gspca_dev->cam;
+       u8 *cd = gspca_dev->usb_buf;
+       int i, j, n;
+       int widths[MAX_MODES], heights[MAX_MODES];
+
+       /* Read the camera descriptor */
+       se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, 1);
+       if (gspca_dev->usb_err) {
+               /* Sometimes after being idle for a while the se401 won't
+                  respond and needs a good kicking  */
+               usb_reset_device(gspca_dev->dev);
+               gspca_dev->usb_err = 0;
+               se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0);
+       }
+
+       /* Some cameras start with their LED on */
+       se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 0, 0);
+       if (gspca_dev->usb_err)
+               return gspca_dev->usb_err;
+
+       if (cd[1] != 0x41) {
+               pr_err("Wrong descriptor type\n");
+               return -ENODEV;
+       }
+
+       if (!(cd[2] & SE401_FORMAT_BAYER)) {
+               pr_err("Bayer format not supported!\n");
+               return -ENODEV;
+       }
+
+       if (cd[3])
+               pr_info("ExtraFeatures: %d\n", cd[3]);
+
+       n = cd[4] | (cd[5] << 8);
+       if (n > MAX_MODES) {
+               pr_err("Too many frame sizes\n");
+               return -ENODEV;
+       }
+
+       for (i = 0; i < n ; i++) {
+               widths[i] = cd[6 + i * 4 + 0] | (cd[6 + i * 4 + 1] << 8);
+               heights[i] = cd[6 + i * 4 + 2] | (cd[6 + i * 4 + 3] << 8);
+       }
+
+       for (i = 0; i < n ; i++) {
+               sd->fmts[i].width = widths[i];
+               sd->fmts[i].height = heights[i];
+               sd->fmts[i].field = V4L2_FIELD_NONE;
+               sd->fmts[i].colorspace = V4L2_COLORSPACE_SRGB;
+               sd->fmts[i].priv = 1;
+
+               /* janggu compression only works for 1/4th or 1/16th res */
+               for (j = 0; j < n; j++) {
+                       if (widths[j] / 2 == widths[i] &&
+                           heights[j] / 2 == heights[i]) {
+                               sd->fmts[i].priv = 2;
+                               break;
+                       }
+               }
+               /* 1/16th if available too is better then 1/4th, because
+                  we then use a larger area of the sensor */
+               for (j = 0; j < n; j++) {
+                       if (widths[j] / 4 == widths[i] &&
+                           heights[j] / 4 == heights[i]) {
+                               sd->fmts[i].priv = 4;
+                               break;
+                       }
+               }
+
+               if (sd->fmts[i].priv == 1) {
+                       /* Not a 1/4th or 1/16th res, use bayer */
+                       sd->fmts[i].pixelformat = V4L2_PIX_FMT_SBGGR8;
+                       sd->fmts[i].bytesperline = widths[i];
+                       sd->fmts[i].sizeimage = widths[i] * heights[i];
+                       pr_info("Frame size: %dx%d bayer\n",
+                               widths[i], heights[i]);
+               } else {
+                       /* Found a match use janggu compression */
+                       sd->fmts[i].pixelformat = V4L2_PIX_FMT_SE401;
+                       sd->fmts[i].bytesperline = 0;
+                       sd->fmts[i].sizeimage = widths[i] * heights[i] * 3;
+                       pr_info("Frame size: %dx%d 1/%dth janggu\n",
+                               widths[i], heights[i],
+                               sd->fmts[i].priv * sd->fmts[i].priv);
+               }
+       }
+
+       cam->cam_mode = sd->fmts;
+       cam->nmodes = n;
+       cam->bulk = 1;
+       cam->bulk_size = BULK_SIZE;
+       cam->bulk_nurbs = 4;
+       sd->resetlevel = 0x2d; /* Set initial resetlevel */
+
+       /* See if the camera supports brightness */
+       se401_read_req(gspca_dev, SE401_REQ_GET_BRT, 1);
+       sd->has_brightness = !!gspca_dev->usb_err;
+       gspca_dev->usb_err = 0;
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       return 0;
+}
+
+/* function called at start time before URB creation */
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+       gspca_dev->alt = 1;     /* Ignore the bogus isoc alt settings */
+
+       return gspca_dev->usb_err;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+       int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+       int mode = 0;
+
+       se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 1, 1);
+       if (gspca_dev->usb_err) {
+               /* Sometimes after being idle for a while the se401 won't
+                  respond and needs a good kicking  */
+               usb_reset_device(gspca_dev->dev);
+               gspca_dev->usb_err = 0;
+               se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 1, 0);
+       }
+       se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 1, 0);
+
+       se401_set_feature(gspca_dev, HV7131_REG_MODE_B, 0x05);
+
+       /* set size + mode */
+       se401_write_req(gspca_dev, SE401_REQ_SET_WIDTH,
+                       gspca_dev->width * mult, 0);
+       se401_write_req(gspca_dev, SE401_REQ_SET_HEIGHT,
+                       gspca_dev->height * mult, 0);
+       /*
+        * HDG: disabled this as it does not seem to do anything
+        * se401_write_req(gspca_dev, SE401_REQ_SET_OUTPUT_MODE,
+        *                 SE401_FORMAT_BAYER, 0);
+        */
+
+       switch (mult) {
+       case 1: /* Raw bayer */
+               mode = 0x03; break;
+       case 2: /* 1/4th janggu */
+               mode = SE401_QUANT_FACT << 4; break;
+       case 4: /* 1/16th janggu */
+               mode = (SE401_QUANT_FACT << 4) | 0x02; break;
+       }
+       se401_set_feature(gspca_dev, SE401_OPERATINGMODE, mode);
+
+       se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel);
+
+       sd->packet_read = 0;
+       sd->pixels_read = 0;
+       sd->restart_stream = 0;
+       sd->resetlevel_frame_count = 0;
+       sd->resetlevel_adjust_dir = 0;
+       sd->expo_change_state = EXPO_NO_CHANGE;
+
+       se401_write_req(gspca_dev, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, 0);
+
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       se401_write_req(gspca_dev, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, 0);
+       se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 0, 0);
+       se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 0, 0);
+}
+
+static void sd_dq_callback(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+       unsigned int ahrc, alrc;
+       int oldreset, adjust_dir;
+
+       /* Restart the stream if requested do so by pkt_scan */
+       if (sd->restart_stream) {
+               sd_stopN(gspca_dev);
+               sd_start(gspca_dev);
+               sd->restart_stream = 0;
+       }
+
+       /* Automatically adjust sensor reset level
+          Hyundai have some really nice docs about this and other sensor
+          related stuff on their homepage: www.hei.co.kr */
+       sd->resetlevel_frame_count++;
+       if (sd->resetlevel_frame_count < 20)
+               return;
+
+       /* For some reason this normally read-only register doesn't get reset
+          to zero after reading them just once... */
+       se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH);
+       se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL);
+       se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH);
+       se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL);
+       ahrc = 256*se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH) +
+           se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL);
+       alrc = 256*se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH) +
+           se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL);
+
+       /* Not an exact science, but it seems to work pretty well... */
+       oldreset = sd->resetlevel;
+       if (alrc > 10) {
+               while (alrc >= 10 && sd->resetlevel < 63) {
+                       sd->resetlevel++;
+                       alrc /= 2;
+               }
+       } else if (ahrc > 20) {
+               while (ahrc >= 20 && sd->resetlevel > 0) {
+                       sd->resetlevel--;
+                       ahrc /= 2;
+               }
+       }
+       /* Detect ping-pong-ing and halve adjustment to avoid overshoot */
+       if (sd->resetlevel > oldreset)
+               adjust_dir = 1;
+       else
+               adjust_dir = -1;
+       if (sd->resetlevel_adjust_dir &&
+           sd->resetlevel_adjust_dir != adjust_dir)
+               sd->resetlevel = oldreset + (sd->resetlevel - oldreset) / 2;
+
+       if (sd->resetlevel != oldreset) {
+               sd->resetlevel_adjust_dir = adjust_dir;
+               se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel);
+       }
+
+       sd->resetlevel_frame_count = 0;
+}
+
+static void sd_complete_frame(struct gspca_dev *gspca_dev, u8 *data, int len)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+
+       switch (sd->expo_change_state) {
+       case EXPO_CHANGED:
+               /* The exposure was changed while this frame
+                  was being send, so this frame is ok */
+               sd->expo_change_state = EXPO_DROP_FRAME;
+               break;
+       case EXPO_DROP_FRAME:
+               /* The exposure was changed while this frame
+                  was being captured, drop it! */
+               gspca_dev->last_packet_type = DISCARD_PACKET;
+               sd->expo_change_state = EXPO_NO_CHANGE;
+               break;
+       case EXPO_NO_CHANGE:
+               break;
+       }
+       gspca_frame_add(gspca_dev, LAST_PACKET, data, len);
+}
+
+static void sd_pkt_scan_janggu(struct gspca_dev *gspca_dev, u8 *data, int len)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+       int imagesize = gspca_dev->width * gspca_dev->height;
+       int i, plen, bits, pixels, info, count;
+
+       if (sd->restart_stream)
+               return;
+
+       /* Sometimes a 1024 bytes garbage bulk packet is send between frames */
+       if (gspca_dev->last_packet_type == LAST_PACKET && len == 1024) {
+               gspca_dev->last_packet_type = DISCARD_PACKET;
+               return;
+       }
+
+       i = 0;
+       while (i < len) {
+               /* Read header if not already be present from prev bulk pkt */
+               if (sd->packet_read < 4) {
+                       count = 4 - sd->packet_read;
+                       if (count > len - i)
+                               count = len - i;
+                       memcpy(&sd->packet[sd->packet_read], &data[i], count);
+                       sd->packet_read += count;
+                       i += count;
+                       if (sd->packet_read < 4)
+                               break;
+               }
+               bits   = sd->packet[3] + (sd->packet[2] << 8);
+               pixels = sd->packet[1] + ((sd->packet[0] & 0x3f) << 8);
+               info   = (sd->packet[0] & 0xc0) >> 6;
+               plen   = ((bits + 47) >> 4) << 1;
+               /* Sanity checks */
+               if (plen > 1024) {
+                       pr_err("invalid packet len %d restarting stream\n",
+                              plen);
+                       goto error;
+               }
+               if (info == 3) {
+                       pr_err("unknown frame info value restarting stream\n");
+                       goto error;
+               }
+
+               /* Read (remainder of) packet contents */
+               count = plen - sd->packet_read;
+               if (count > len - i)
+                       count = len - i;
+               memcpy(&sd->packet[sd->packet_read], &data[i], count);
+               sd->packet_read += count;
+               i += count;
+               if (sd->packet_read < plen)
+                       break;
+
+               sd->pixels_read += pixels;
+               sd->packet_read = 0;
+
+               switch (info) {
+               case 0: /* Frame data */
+                       gspca_frame_add(gspca_dev, INTER_PACKET, sd->packet,
+                                       plen);
+                       break;
+               case 1: /* EOF */
+                       if (sd->pixels_read != imagesize) {
+                               pr_err("frame size %d expected %d\n",
+                                      sd->pixels_read, imagesize);
+                               goto error;
+                       }
+                       sd_complete_frame(gspca_dev, sd->packet, plen);
+                       return; /* Discard the rest of the bulk packet !! */
+               case 2: /* SOF */
+                       gspca_frame_add(gspca_dev, FIRST_PACKET, sd->packet,
+                                       plen);
+                       sd->pixels_read = pixels;
+                       break;
+               }
+       }
+       return;
+
+error:
+       sd->restart_stream = 1;
+       /* Give userspace a 0 bytes frame, so our dq callback gets
+          called and it can restart the stream */
+       gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
+       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+}
+
+static void sd_pkt_scan_bayer(struct gspca_dev *gspca_dev, u8 *data, int len)
+{
+       struct cam *cam = &gspca_dev->cam;
+       int imagesize = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
+
+       if (gspca_dev->image_len == 0) {
+               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
+               return;
+       }
+
+       if (gspca_dev->image_len + len >= imagesize) {
+               sd_complete_frame(gspca_dev, data, len);
+               return;
+       }
+
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
+{
+       int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+
+       if (len == 0)
+               return;
+
+       if (mult == 1) /* mult == 1 means raw bayer */
+               sd_pkt_scan_bayer(gspca_dev, data, len);
+       else
+               sd_pkt_scan_janggu(gspca_dev, data, len);
+}
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+       u8 state;
+
+       if (len != 2)
+               return -EINVAL;
+
+       switch (data[0]) {
+       case 0:
+       case 1:
+               state = data[0];
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (sd->button_state != state) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, state);
+               input_sync(gspca_dev->input_dev);
+               sd->button_state = state;
+       }
+
+       return 0;
+}
+#endif
+
+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_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_GAIN:
+               setgain(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_EXPOSURE:
+               setexposure(gspca_dev, ctrl->val, sd->freq->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);
+       if (sd->has_brightness)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 15);
+       /* max is really 63 but > 50 is not pretty */
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 50, 1, 25);
+       sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0, 32767, 1, 15000);
+       sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
+                       V4L2_CID_POWER_LINE_FREQUENCY,
+                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       v4l2_ctrl_cluster(2, &sd->exposure);
+       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,
+       .isoc_init = sd_isoc_init,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .dq_callback = sd_dq_callback,
+       .pkt_scan = sd_pkt_scan,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .int_pkt_scan = sd_int_pkt_scan,
+#endif
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x03e8, 0x0004)}, /* Endpoints/Aox SE401 */
+       {USB_DEVICE(0x0471, 0x030b)}, /* Philips PCVC665K */
+       {USB_DEVICE(0x047d, 0x5001)}, /* Kensington 67014 */
+       {USB_DEVICE(0x047d, 0x5002)}, /* Kensington 6701(5/7) */
+       {USB_DEVICE(0x047d, 0x5003)}, /* Kensington 67016 */
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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 int sd_pre_reset(struct usb_interface *intf)
+{
+       return 0;
+}
+
+static int sd_post_reset(struct usb_interface *intf)
+{
+       return 0;
+}
+
+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,
+       .reset_resume = gspca_resume,
+#endif
+       .pre_reset = sd_pre_reset,
+       .post_reset = sd_post_reset,
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/se401.h b/drivers/media/usb/gspca/se401.h
new file mode 100644 (file)
index 0000000..96d8ebf
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * GSPCA Endpoints (formerly known as AOX) se401 USB Camera sub Driver
+ *
+ * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on the v4l1 se401 driver which is:
+ *
+ * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define SE401_REQ_GET_CAMERA_DESCRIPTOR                0x06
+#define SE401_REQ_START_CONTINUOUS_CAPTURE     0x41
+#define SE401_REQ_STOP_CONTINUOUS_CAPTURE      0x42
+#define SE401_REQ_CAPTURE_FRAME                        0x43
+#define SE401_REQ_GET_BRT                      0x44
+#define SE401_REQ_SET_BRT                      0x45
+#define SE401_REQ_GET_WIDTH                    0x4c
+#define SE401_REQ_SET_WIDTH                    0x4d
+#define SE401_REQ_GET_HEIGHT                   0x4e
+#define SE401_REQ_SET_HEIGHT                   0x4f
+#define SE401_REQ_GET_OUTPUT_MODE              0x50
+#define SE401_REQ_SET_OUTPUT_MODE              0x51
+#define SE401_REQ_GET_EXT_FEATURE              0x52
+#define SE401_REQ_SET_EXT_FEATURE              0x53
+#define SE401_REQ_CAMERA_POWER                 0x56
+#define SE401_REQ_LED_CONTROL                  0x57
+#define SE401_REQ_BIOS                         0xff
+
+#define SE401_BIOS_READ                                0x07
+
+#define SE401_FORMAT_BAYER     0x40
+
+/* Hyundai hv7131b registers
+   7121 and 7141 should be the same (haven't really checked...) */
+/* Mode registers: */
+#define HV7131_REG_MODE_A              0x00
+#define HV7131_REG_MODE_B              0x01
+#define HV7131_REG_MODE_C              0x02
+/* Frame registers: */
+#define HV7131_REG_FRSU                0x10
+#define HV7131_REG_FRSL                0x11
+#define HV7131_REG_FCSU                0x12
+#define HV7131_REG_FCSL                0x13
+#define HV7131_REG_FWHU                0x14
+#define HV7131_REG_FWHL                0x15
+#define HV7131_REG_FWWU                0x16
+#define HV7131_REG_FWWL                0x17
+/* Timing registers: */
+#define HV7131_REG_THBU                0x20
+#define HV7131_REG_THBL                0x21
+#define HV7131_REG_TVBU                0x22
+#define HV7131_REG_TVBL                0x23
+#define HV7131_REG_TITU                0x25
+#define HV7131_REG_TITM                0x26
+#define HV7131_REG_TITL                0x27
+#define HV7131_REG_TMCD                0x28
+/* Adjust Registers: */
+#define HV7131_REG_ARLV                0x30
+#define HV7131_REG_ARCG                0x31
+#define HV7131_REG_AGCG                0x32
+#define HV7131_REG_ABCG                0x33
+#define HV7131_REG_APBV                0x34
+#define HV7131_REG_ASLP                0x54
+/* Offset Registers: */
+#define HV7131_REG_OFSR                0x50
+#define HV7131_REG_OFSG                0x51
+#define HV7131_REG_OFSB                0x52
+/* REset level statistics registers: */
+#define HV7131_REG_LOREFNOH    0x57
+#define HV7131_REG_LOREFNOL    0x58
+#define HV7131_REG_HIREFNOH    0x59
+#define HV7131_REG_HIREFNOL    0x5a
+
+/* se401 registers */
+#define SE401_OPERATINGMODE    0x2000
diff --git a/drivers/media/usb/gspca/sn9c2028.c b/drivers/media/usb/gspca/sn9c2028.c
new file mode 100644 (file)
index 0000000..03fa3fd
--- /dev/null
@@ -0,0 +1,735 @@
+/*
+ * SN9C2028 library
+ *
+ * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "sn9c2028"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Theodore Kilgore");
+MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;  /* !! must be the first item */
+       u8 sof_read;
+       u16 model;
+};
+
+struct init_command {
+       unsigned char instruction[6];
+       unsigned char to_read; /* length to read. 0 means no reply requested */
+};
+
+/* How to change the resolution of any of the VGA cams is unknown */
+static const struct v4l2_pix_format vga_mode[] = {
+       {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 4,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+/* No way to change the resolution of the CIF cams is known */
+static const struct v4l2_pix_format cif_mode[] = {
+       {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3 / 4,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+/* the bytes to write are in gspca_dev->usb_buf */
+static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command)
+{
+       int rc;
+
+       PDEBUG(D_USBO, "sending command %02x%02x%02x%02x%02x%02x", command[0],
+              command[1], command[2], command[3], command[4], command[5]);
+
+       memcpy(gspca_dev->usb_buf, command, 6);
+       rc = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       USB_REQ_GET_CONFIGURATION,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       2, 0, gspca_dev->usb_buf, 6, 500);
+       if (rc < 0) {
+               pr_err("command write [%02x] error %d\n",
+                      gspca_dev->usb_buf[0], rc);
+               return rc;
+       }
+
+       return 0;
+}
+
+static int sn9c2028_read1(struct gspca_dev *gspca_dev)
+{
+       int rc;
+
+       rc = usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       USB_REQ_GET_STATUS,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       1, 0, gspca_dev->usb_buf, 1, 500);
+       if (rc != 1) {
+               pr_err("read1 error %d\n", rc);
+               return (rc < 0) ? rc : -EIO;
+       }
+       PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]);
+       return gspca_dev->usb_buf[0];
+}
+
+static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading)
+{
+       int rc;
+       rc = usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       USB_REQ_GET_STATUS,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       4, 0, gspca_dev->usb_buf, 4, 500);
+       if (rc != 4) {
+               pr_err("read4 error %d\n", rc);
+               return (rc < 0) ? rc : -EIO;
+       }
+       memcpy(reading, gspca_dev->usb_buf, 4);
+       PDEBUG(D_USBI, "read4 response %02x%02x%02x%02x", reading[0],
+              reading[1], reading[2], reading[3]);
+       return rc;
+}
+
+static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command)
+{
+       int i, status;
+       __u8 reading[4];
+
+       status = sn9c2028_command(gspca_dev, command);
+       if (status < 0)
+               return status;
+
+       status = -1;
+       for (i = 0; i < 256 && status < 2; i++)
+               status = sn9c2028_read1(gspca_dev);
+       if (status != 2) {
+               pr_err("long command status read error %d\n", status);
+               return (status < 0) ? status : -EIO;
+       }
+
+       memset(reading, 0, 4);
+       status = sn9c2028_read4(gspca_dev, reading);
+       if (status < 0)
+               return status;
+
+       /* in general, the first byte of the response is the first byte of
+        * the command, or'ed with 8 */
+       status = sn9c2028_read1(gspca_dev);
+       if (status < 0)
+               return status;
+
+       return 0;
+}
+
+static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command)
+{
+       int err_code;
+
+       err_code = sn9c2028_command(gspca_dev, command);
+       if (err_code < 0)
+               return err_code;
+
+       err_code = sn9c2028_read1(gspca_dev);
+       if (err_code < 0)
+               return err_code;
+
+       return 0;
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                    const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam = &gspca_dev->cam;
+
+       PDEBUG(D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)",
+              id->idVendor, id->idProduct);
+
+       sd->model = id->idProduct;
+
+       switch (sd->model) {
+       case 0x7005:
+               PDEBUG(D_PROBE, "Genius Smart 300 camera");
+               break;
+       case 0x8000:
+               PDEBUG(D_PROBE, "DC31VC");
+               break;
+       case 0x8001:
+               PDEBUG(D_PROBE, "Spy camera");
+               break;
+       case 0x8003:
+               PDEBUG(D_PROBE, "CIF camera");
+               break;
+       case 0x8008:
+               PDEBUG(D_PROBE, "Mini-Shotz ms-350 camera");
+               break;
+       case 0x800a:
+               PDEBUG(D_PROBE, "Vivitar 3350b type camera");
+               cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
+               break;
+       }
+
+       switch (sd->model) {
+       case 0x8000:
+       case 0x8001:
+       case 0x8003:
+               cam->cam_mode = cif_mode;
+               cam->nmodes = ARRAY_SIZE(cif_mode);
+               break;
+       default:
+               cam->cam_mode = vga_mode;
+               cam->nmodes = ARRAY_SIZE(vga_mode);
+       }
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       int status = -1;
+
+       sn9c2028_read1(gspca_dev);
+       sn9c2028_read1(gspca_dev);
+       status = sn9c2028_read1(gspca_dev);
+
+       return (status < 0) ? status : 0;
+}
+
+static int run_start_commands(struct gspca_dev *gspca_dev,
+                             struct init_command *cam_commands, int n)
+{
+       int i, err_code = -1;
+
+       for (i = 0; i < n; i++) {
+               switch (cam_commands[i].to_read) {
+               case 4:
+                       err_code = sn9c2028_long_command(gspca_dev,
+                                       cam_commands[i].instruction);
+                       break;
+               case 1:
+                       err_code = sn9c2028_short_command(gspca_dev,
+                                       cam_commands[i].instruction);
+                       break;
+               case 0:
+                       err_code = sn9c2028_command(gspca_dev,
+                                       cam_commands[i].instruction);
+                       break;
+               }
+               if (err_code < 0)
+                       return err_code;
+       }
+       return 0;
+}
+
+static int start_spy_cam(struct gspca_dev *gspca_dev)
+{
+       struct init_command spy_start_commands[] = {
+               {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
+               {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
+               {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width  352 */
+               {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */
+               /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */
+               {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4},
+               {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/
+               /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */
+               {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
+               /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */
+               {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
+               /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */
+               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
+               {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
+               /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */
+               {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
+               {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
+               {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
+               {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/
+               /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
+               {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
+               /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */
+               {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
+               {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */
+               {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4},
+               /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
+               {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4},
+               /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */
+               /* brightness or gain. 0 is default. 4 is good
+                * indoors at night with incandescent lighting */
+               {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/
+               {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4},
+               /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */
+               {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */
+               /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */
+               {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1},
+               {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */
+               /* Camera should start to capture now. */
+       };
+
+       return run_start_commands(gspca_dev, spy_start_commands,
+                                 ARRAY_SIZE(spy_start_commands));
+}
+
+static int start_cif_cam(struct gspca_dev *gspca_dev)
+{
+       struct init_command cif_start_commands[] = {
+               {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
+               /* The entire sequence below seems redundant */
+               /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4},
+               {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4},
+               {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width?
+               {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height?
+               {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
+               {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
+               {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
+               {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
+               {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
+               {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
+               {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
+               {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/
+               {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
+               {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */
+               {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */
+               /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
+                * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing
+                * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */
+               /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
+                * causes subsampling
+                * but not a change in the resolution setting! */
+               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
+               {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4},
+               {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4},
+               {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4},
+               {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1},
+               {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1},
+               {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
+               {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */
+               /* Camera should start to capture now. */
+       };
+
+       return run_start_commands(gspca_dev, cif_start_commands,
+                                 ARRAY_SIZE(cif_start_commands));
+}
+
+static int start_ms350_cam(struct gspca_dev *gspca_dev)
+{
+       struct init_command ms350_start_commands[] = {
+               {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
+               {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
+               {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
+               {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
+               {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
+               {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4},
+               {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
+               {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
+               {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
+               {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
+               {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
+               {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width  */
+               {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */
+               {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */
+               {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
+               {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */
+               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
+               {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
+               {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
+               {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
+               {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
+               {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0},
+               /* Camera should start to capture now. */
+       };
+
+       return run_start_commands(gspca_dev, ms350_start_commands,
+                                 ARRAY_SIZE(ms350_start_commands));
+}
+
+static int start_genius_cam(struct gspca_dev *gspca_dev)
+{
+       struct init_command genius_start_commands[] = {
+               {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
+               {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
+               /* "preliminary" width and height settings */
+               {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
+               {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
+               {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
+               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
+               {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
+               {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
+               {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
+               {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */
+               {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */
+               {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
+               {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
+               {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4},
+               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
+               {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
+               {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
+               {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
+               {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4},
+               {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4},
+               {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
+               {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
+               {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0}
+               /* Camera should start to capture now. */
+       };
+
+       return run_start_commands(gspca_dev, genius_start_commands,
+                                 ARRAY_SIZE(genius_start_commands));
+}
+
+static int start_vivitar_cam(struct gspca_dev *gspca_dev)
+{
+       struct init_command vivitar_start_commands[] = {
+               {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4},
+               {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4},
+               {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
+               {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
+               {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
+               {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4},
+               /*
+                * Above is changed from OEM 0x0b. Fixes Bayer tiling.
+                * Presumably gives a vertical shift of one row.
+                */
+               {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
+               /* Above seems to do horizontal shift. */
+               {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
+               {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
+               {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
+               {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
+               /* Above three commands seem to relate to brightness. */
+               {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
+               {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1},
+               /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
+               {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
+               {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */
+               {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1},
+               {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1},
+               {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
+               {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1},
+               /* Above is brightness; OEM driver setting is 0x10 */
+               {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
+               {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
+               {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}
+       };
+
+       return run_start_commands(gspca_dev, vivitar_start_commands,
+                                 ARRAY_SIZE(vivitar_start_commands));
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int err_code;
+
+       sd->sof_read = 0;
+
+       switch (sd->model) {
+       case 0x7005:
+               err_code = start_genius_cam(gspca_dev);
+               break;
+       case 0x8001:
+               err_code = start_spy_cam(gspca_dev);
+               break;
+       case 0x8003:
+               err_code = start_cif_cam(gspca_dev);
+               break;
+       case 0x8008:
+               err_code = start_ms350_cam(gspca_dev);
+               break;
+       case 0x800a:
+               err_code = start_vivitar_cam(gspca_dev);
+               break;
+       default:
+               pr_err("Starting unknown camera, please report this\n");
+               return -ENXIO;
+       }
+
+       return err_code;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       int result;
+       __u8 data[6];
+
+       result = sn9c2028_read1(gspca_dev);
+       if (result < 0)
+               PDEBUG(D_ERR, "Camera Stop read failed");
+
+       memset(data, 0, 6);
+       data[0] = 0x14;
+       result = sn9c2028_command(gspca_dev, data);
+       if (result < 0)
+               PDEBUG(D_ERR, "Camera Stop command failed");
+}
+
+/* Include sn9c2028 sof detection functions */
+#include "sn9c2028.h"
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       __u8 *data,                     /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       unsigned char *sof;
+
+       sof = sn9c2028_find_sof(gspca_dev, data, len);
+       if (sof) {
+               int n;
+
+               /* finish decoding current frame */
+               n = sof - data;
+               if (n > sizeof sn9c2028_sof_marker)
+                       n -= sizeof sn9c2028_sof_marker;
+               else
+                       n = 0;
+               gspca_frame_add(gspca_dev, LAST_PACKET, data, n);
+               /* Start next frame. */
+               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                       sn9c2028_sof_marker, sizeof sn9c2028_sof_marker);
+               len -= sof - data;
+               data = sof;
+       }
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name = MODULE_NAME,
+       .config = sd_config,
+       .init = sd_init,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */
+       /* The Genius Smart is untested. I can't find an owner ! */
+       /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */
+       {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */
+       {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */
+       /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */
+       {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */
+       {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/sn9c2028.h b/drivers/media/usb/gspca/sn9c2028.h
new file mode 100644 (file)
index 0000000..8fd1d3e
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * SN9C2028 common functions
+ *
+ * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn,edu>
+ *
+ * Based closely upon the file gspca/pac_common.h
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+static const unsigned char sn9c2028_sof_marker[5] =
+       { 0xff, 0xff, 0x00, 0xc4, 0xc4 };
+
+static unsigned char *sn9c2028_find_sof(struct gspca_dev *gspca_dev,
+                                       unsigned char *m, int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+
+       /* Search for the SOF marker (fixed part) in the header */
+       for (i = 0; i < len; i++) {
+               if (m[i] == sn9c2028_sof_marker[sd->sof_read]) {
+                       sd->sof_read++;
+                       if (sd->sof_read == sizeof(sn9c2028_sof_marker)) {
+                               PDEBUG(D_FRAM,
+                                       "SOF found, bytes to analyze: %u."
+                                       " Frame starts at byte #%u",
+                                       len, i + 1);
+                               sd->sof_read = 0;
+                               return m + i + 1;
+                       }
+               } else {
+                       sd->sof_read = 0;
+               }
+       }
+
+       return NULL;
+}
diff --git a/drivers/media/usb/gspca/sn9c20x.c b/drivers/media/usb/gspca/sn9c20x.c
new file mode 100644 (file)
index 0000000..b9c6f17
--- /dev/null
@@ -0,0 +1,2428 @@
+/*
+ *     Sonix sn9c201 sn9c202 library
+ *
+ * Copyright (C) 2012 Jean-Francois Moine <http://moinejf.free.fr>
+ *     Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
+ *     Copyright (C) 2009 Brian Johnson <brijohn@gmail.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
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/input.h>
+
+#include "gspca.h"
+#include "jpeg.h"
+
+#include <media/v4l2-chip-ident.h>
+#include <linux/dmi.h>
+
+MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
+               "microdia project <microdia@googlegroups.com>");
+MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/*
+ * Pixel format private data
+ */
+#define SCALE_MASK     0x0f
+#define SCALE_160x120  0
+#define SCALE_320x240  1
+#define SCALE_640x480  2
+#define SCALE_1280x1024        3
+#define MODE_RAW       0x10
+#define MODE_JPEG      0x20
+#define MODE_SXGA      0x80
+
+#define SENSOR_OV9650  0
+#define SENSOR_OV9655  1
+#define SENSOR_SOI968  2
+#define SENSOR_OV7660  3
+#define SENSOR_OV7670  4
+#define SENSOR_MT9V011 5
+#define SENSOR_MT9V111 6
+#define SENSOR_MT9V112 7
+#define SENSOR_MT9M001 8
+#define SENSOR_MT9M111 9
+#define SENSOR_MT9M112  10
+#define SENSOR_HV7131R 11
+#define SENSOR_MT9VPRB 12
+
+/* camera flags */
+#define HAS_NO_BUTTON  0x1
+#define LED_REVERSE    0x2 /* some cameras unset gpio to turn on leds */
+#define FLIP_DETECT    0x4
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;
+
+       struct { /* color control cluster */
+               struct v4l2_ctrl *brightness;
+               struct v4l2_ctrl *contrast;
+               struct v4l2_ctrl *saturation;
+               struct v4l2_ctrl *hue;
+       };
+       struct { /* blue/red balance control cluster */
+               struct v4l2_ctrl *blue;
+               struct v4l2_ctrl *red;
+       };
+       struct { /* h/vflip control cluster */
+               struct v4l2_ctrl *hflip;
+               struct v4l2_ctrl *vflip;
+       };
+       struct v4l2_ctrl *gamma;
+       struct { /* autogain and exposure or gain control cluster */
+               struct v4l2_ctrl *autogain;
+               struct v4l2_ctrl *exposure;
+               struct v4l2_ctrl *gain;
+       };
+       struct v4l2_ctrl *jpegqual;
+
+       struct work_struct work;
+       struct workqueue_struct *work_thread;
+
+       u32 pktsz;                      /* (used by pkt_scan) */
+       u16 npkt;
+       s8 nchg;
+       u8 fmt;                         /* (used for JPEG QTAB update */
+
+#define MIN_AVG_LUM 80
+#define MAX_AVG_LUM 130
+       atomic_t avg_lum;
+       u8 old_step;
+       u8 older_step;
+       u8 exposure_step;
+
+       u8 i2c_addr;
+       u8 i2c_intf;
+       u8 sensor;
+       u8 hstart;
+       u8 vstart;
+
+       u8 jpeg_hdr[JPEG_HDR_SZ];
+
+       u8 flags;
+};
+
+static void qual_upd(struct work_struct *work);
+
+struct i2c_reg_u8 {
+       u8 reg;
+       u8 val;
+};
+
+struct i2c_reg_u16 {
+       u8 reg;
+       u16 val;
+};
+
+static const struct dmi_system_id flip_dmi_table[] = {
+       {
+               .ident = "MSI MS-1034",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
+               }
+       },
+       {
+               .ident = "MSI MS-1632",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
+                       DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
+               }
+       },
+       {
+               .ident = "MSI MS-1633X",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
+                       DMI_MATCH(DMI_BOARD_NAME, "MS-1633X")
+               }
+       },
+       {
+               .ident = "MSI MS-1635X",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
+                       DMI_MATCH(DMI_BOARD_NAME, "MS-1635X")
+               }
+       },
+       {
+               .ident = "ASUSTeK W7J",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
+                       DMI_MATCH(DMI_BOARD_NAME, "W7J       ")
+               }
+       },
+       {}
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 4 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = SCALE_160x120 | MODE_JPEG},
+       {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_160x120 | MODE_RAW},
+       {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 240 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_160x120},
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 4 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = SCALE_320x240 | MODE_JPEG},
+       {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 ,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_320x240 | MODE_RAW},
+       {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 480 * 240 ,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_320x240},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 4 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = SCALE_640x480 | MODE_JPEG},
+       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_640x480 | MODE_RAW},
+       {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 960 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_640x480},
+};
+
+static const struct v4l2_pix_format sxga_mode[] = {
+       {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 4 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = SCALE_160x120 | MODE_JPEG},
+       {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_160x120 | MODE_RAW},
+       {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 240 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_160x120},
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 4 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = SCALE_320x240 | MODE_JPEG},
+       {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 ,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_320x240 | MODE_RAW},
+       {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 480 * 240 ,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_320x240},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 4 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = SCALE_640x480 | MODE_JPEG},
+       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_640x480 | MODE_RAW},
+       {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 960 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_640x480},
+       {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 1280,
+               .sizeimage = 1280 * 1024,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
+};
+
+static const struct v4l2_pix_format mono_mode[] = {
+       {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_160x120 | MODE_RAW},
+       {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 ,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_320x240 | MODE_RAW},
+       {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_640x480 | MODE_RAW},
+       {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
+               .bytesperline = 1280,
+               .sizeimage = 1280 * 1024,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
+};
+
+static const s16 hsv_red_x[] = {
+       41,  44,  46,  48,  50,  52,  54,  56,
+       58,  60,  62,  64,  66,  68,  70,  72,
+       74,  76,  78,  80,  81,  83,  85,  87,
+       88,  90,  92,  93,  95,  97,  98, 100,
+       101, 102, 104, 105, 107, 108, 109, 110,
+       112, 113, 114, 115, 116, 117, 118, 119,
+       120, 121, 122, 123, 123, 124, 125, 125,
+       126, 127, 127, 128, 128, 129, 129, 129,
+       130, 130, 130, 130, 131, 131, 131, 131,
+       131, 131, 131, 131, 130, 130, 130, 130,
+       129, 129, 129, 128, 128, 127, 127, 126,
+       125, 125, 124, 123, 122, 122, 121, 120,
+       119, 118, 117, 116, 115, 114, 112, 111,
+       110, 109, 107, 106, 105, 103, 102, 101,
+       99,  98,  96,  94,  93,  91,  90,  88,
+       86,  84,  83,  81,  79,  77,  75,  74,
+       72,  70,  68,  66,  64,  62,  60,  58,
+       56,  54,  52,  49,  47,  45,  43,  41,
+       39,  36,  34,  32,  30,  28,  25,  23,
+       21,  19,  16,  14,  12,   9,   7,   5,
+       3,   0,  -1,  -3,  -6,  -8, -10, -12,
+       -15, -17, -19, -22, -24, -26, -28, -30,
+       -33, -35, -37, -39, -41, -44, -46, -48,
+       -50, -52, -54, -56, -58, -60, -62, -64,
+       -66, -68, -70, -72, -74, -76, -78, -80,
+       -81, -83, -85, -87, -88, -90, -92, -93,
+       -95, -97, -98, -100, -101, -102, -104, -105,
+       -107, -108, -109, -110, -112, -113, -114, -115,
+       -116, -117, -118, -119, -120, -121, -122, -123,
+       -123, -124, -125, -125, -126, -127, -127, -128,
+       -128, -128, -128, -128, -128, -128, -128, -128,
+       -128, -128, -128, -128, -128, -128, -128, -128,
+       -128, -128, -128, -128, -128, -128, -128, -128,
+       -128, -127, -127, -126, -125, -125, -124, -123,
+       -122, -122, -121, -120, -119, -118, -117, -116,
+       -115, -114, -112, -111, -110, -109, -107, -106,
+       -105, -103, -102, -101, -99, -98, -96, -94,
+       -93, -91, -90, -88, -86, -84, -83, -81,
+       -79, -77, -75, -74, -72, -70, -68, -66,
+       -64, -62, -60, -58, -56, -54, -52, -49,
+       -47, -45, -43, -41, -39, -36, -34, -32,
+       -30, -28, -25, -23, -21, -19, -16, -14,
+       -12,  -9,  -7,  -5,  -3,   0,   1,   3,
+       6,   8,  10,  12,  15,  17,  19,  22,
+       24,  26,  28,  30,  33,  35,  37,  39, 41
+};
+
+static const s16 hsv_red_y[] = {
+       82,  80,  78,  76,  74,  73,  71,  69,
+       67,  65,  63,  61,  58,  56,  54,  52,
+       50,  48,  46,  44,  41,  39,  37,  35,
+       32,  30,  28,  26,  23,  21,  19,  16,
+       14,  12,  10,   7,   5,   3,   0,  -1,
+       -3,  -6,  -8, -10, -13, -15, -17, -19,
+       -22, -24, -26, -29, -31, -33, -35, -38,
+       -40, -42, -44, -46, -48, -51, -53, -55,
+       -57, -59, -61, -63, -65, -67, -69, -71,
+       -73, -75, -77, -79, -81, -82, -84, -86,
+       -88, -89, -91, -93, -94, -96, -98, -99,
+       -101, -102, -104, -105, -106, -108, -109, -110,
+       -112, -113, -114, -115, -116, -117, -119, -120,
+       -120, -121, -122, -123, -124, -125, -126, -126,
+       -127, -128, -128, -128, -128, -128, -128, -128,
+       -128, -128, -128, -128, -128, -128, -128, -128,
+       -128, -128, -128, -128, -128, -128, -128, -128,
+       -128, -128, -128, -128, -128, -128, -128, -128,
+       -127, -127, -126, -125, -125, -124, -123, -122,
+       -121, -120, -119, -118, -117, -116, -115, -114,
+       -113, -111, -110, -109, -107, -106, -105, -103,
+       -102, -100, -99, -97, -96, -94, -92, -91,
+       -89, -87, -85, -84, -82, -80, -78, -76,
+       -74, -73, -71, -69, -67, -65, -63, -61,
+       -58, -56, -54, -52, -50, -48, -46, -44,
+       -41, -39, -37, -35, -32, -30, -28, -26,
+       -23, -21, -19, -16, -14, -12, -10,  -7,
+       -5,  -3,   0,   1,   3,   6,   8,  10,
+       13,  15,  17,  19,  22,  24,  26,  29,
+       31,  33,  35,  38,  40,  42,  44,  46,
+       48,  51,  53,  55,  57,  59,  61,  63,
+       65,  67,  69,  71,  73,  75,  77,  79,
+       81,  82,  84,  86,  88,  89,  91,  93,
+       94,  96,  98,  99, 101, 102, 104, 105,
+       106, 108, 109, 110, 112, 113, 114, 115,
+       116, 117, 119, 120, 120, 121, 122, 123,
+       124, 125, 126, 126, 127, 128, 128, 129,
+       129, 130, 130, 131, 131, 131, 131, 132,
+       132, 132, 132, 132, 132, 132, 132, 132,
+       132, 132, 132, 131, 131, 131, 130, 130,
+       130, 129, 129, 128, 127, 127, 126, 125,
+       125, 124, 123, 122, 121, 120, 119, 118,
+       117, 116, 115, 114, 113, 111, 110, 109,
+       107, 106, 105, 103, 102, 100,  99,  97,
+       96, 94, 92, 91, 89, 87, 85, 84, 82
+};
+
+static const s16 hsv_green_x[] = {
+       -124, -124, -125, -125, -125, -125, -125, -125,
+       -125, -126, -126, -125, -125, -125, -125, -125,
+       -125, -124, -124, -124, -123, -123, -122, -122,
+       -121, -121, -120, -120, -119, -118, -117, -117,
+       -116, -115, -114, -113, -112, -111, -110, -109,
+       -108, -107, -105, -104, -103, -102, -100, -99,
+       -98, -96, -95, -93, -92, -91, -89, -87,
+       -86, -84, -83, -81, -79, -77, -76, -74,
+       -72, -70, -69, -67, -65, -63, -61, -59,
+       -57, -55, -53, -51, -49, -47, -45, -43,
+       -41, -39, -37, -35, -33, -30, -28, -26,
+       -24, -22, -20, -18, -15, -13, -11,  -9,
+       -7,  -4,  -2,   0,   1,   3,   6,   8,
+       10,  12,  14,  17,  19,  21,  23,  25,
+       27,  29,  32,  34,  36,  38,  40,  42,
+       44,  46,  48,  50,  52,  54,  56,  58,
+       60,  62,  64,  66,  68,  70,  71,  73,
+       75,  77,  78,  80,  82,  83,  85,  87,
+       88,  90,  91,  93,  94,  96,  97,  98,
+       100, 101, 102, 104, 105, 106, 107, 108,
+       109, 111, 112, 113, 113, 114, 115, 116,
+       117, 118, 118, 119, 120, 120, 121, 122,
+       122, 123, 123, 124, 124, 124, 125, 125,
+       125, 125, 125, 125, 125, 126, 126, 125,
+       125, 125, 125, 125, 125, 124, 124, 124,
+       123, 123, 122, 122, 121, 121, 120, 120,
+       119, 118, 117, 117, 116, 115, 114, 113,
+       112, 111, 110, 109, 108, 107, 105, 104,
+       103, 102, 100,  99,  98,  96,  95,  93,
+       92,  91,  89,  87,  86,  84,  83,  81,
+       79,  77,  76,  74,  72,  70,  69,  67,
+       65,  63,  61,  59,  57,  55,  53,  51,
+       49,  47,  45,  43,  41,  39,  37,  35,
+       33,  30,  28,  26,  24,  22,  20,  18,
+       15,  13,  11,   9,   7,   4,   2,   0,
+       -1,  -3,  -6,  -8, -10, -12, -14, -17,
+       -19, -21, -23, -25, -27, -29, -32, -34,
+       -36, -38, -40, -42, -44, -46, -48, -50,
+       -52, -54, -56, -58, -60, -62, -64, -66,
+       -68, -70, -71, -73, -75, -77, -78, -80,
+       -82, -83, -85, -87, -88, -90, -91, -93,
+       -94, -96, -97, -98, -100, -101, -102, -104,
+       -105, -106, -107, -108, -109, -111, -112, -113,
+       -113, -114, -115, -116, -117, -118, -118, -119,
+       -120, -120, -121, -122, -122, -123, -123, -124, -124
+};
+
+static const s16 hsv_green_y[] = {
+       -100, -99, -98, -97, -95, -94, -93, -91,
+       -90, -89, -87, -86, -84, -83, -81, -80,
+       -78, -76, -75, -73, -71, -70, -68, -66,
+       -64, -63, -61, -59, -57, -55, -53, -51,
+       -49, -48, -46, -44, -42, -40, -38, -36,
+       -34, -32, -30, -27, -25, -23, -21, -19,
+       -17, -15, -13, -11,  -9,  -7,  -4,  -2,
+       0,   1,   3,   5,   7,   9,  11,  14,
+       16,  18,  20,  22,  24,  26,  28,  30,
+       32,  34,  36,  38,  40,  42,  44,  46,
+       48,  50,  52,  54,  56,  58,  59,  61,
+       63,  65,  67,  68,  70,  72,  74,  75,
+       77,  78,  80,  82,  83,  85,  86,  88,
+       89,  90,  92,  93,  95,  96,  97,  98,
+       100, 101, 102, 103, 104, 105, 106, 107,
+       108, 109, 110, 111, 112, 112, 113, 114,
+       115, 115, 116, 116, 117, 117, 118, 118,
+       119, 119, 119, 120, 120, 120, 120, 120,
+       121, 121, 121, 121, 121, 121, 120, 120,
+       120, 120, 120, 119, 119, 119, 118, 118,
+       117, 117, 116, 116, 115, 114, 114, 113,
+       112, 111, 111, 110, 109, 108, 107, 106,
+       105, 104, 103, 102, 100,  99,  98,  97,
+       95,  94,  93,  91,  90,  89,  87,  86,
+       84,  83,  81,  80,  78,  76,  75,  73,
+       71,  70,  68,  66,  64,  63,  61,  59,
+       57,  55,  53,  51,  49,  48,  46,  44,
+       42,  40,  38,  36,  34,  32,  30,  27,
+       25,  23,  21,  19,  17,  15,  13,  11,
+       9,   7,   4,   2,   0,  -1,  -3,  -5,
+       -7,  -9, -11, -14, -16, -18, -20, -22,
+       -24, -26, -28, -30, -32, -34, -36, -38,
+       -40, -42, -44, -46, -48, -50, -52, -54,
+       -56, -58, -59, -61, -63, -65, -67, -68,
+       -70, -72, -74, -75, -77, -78, -80, -82,
+       -83, -85, -86, -88, -89, -90, -92, -93,
+       -95, -96, -97, -98, -100, -101, -102, -103,
+       -104, -105, -106, -107, -108, -109, -110, -111,
+       -112, -112, -113, -114, -115, -115, -116, -116,
+       -117, -117, -118, -118, -119, -119, -119, -120,
+       -120, -120, -120, -120, -121, -121, -121, -121,
+       -121, -121, -120, -120, -120, -120, -120, -119,
+       -119, -119, -118, -118, -117, -117, -116, -116,
+       -115, -114, -114, -113, -112, -111, -111, -110,
+       -109, -108, -107, -106, -105, -104, -103, -102, -100
+};
+
+static const s16 hsv_blue_x[] = {
+       112, 113, 114, 114, 115, 116, 117, 117,
+       118, 118, 119, 119, 120, 120, 120, 121,
+       121, 121, 122, 122, 122, 122, 122, 122,
+       122, 122, 122, 122, 122, 122, 121, 121,
+       121, 120, 120, 120, 119, 119, 118, 118,
+       117, 116, 116, 115, 114, 113, 113, 112,
+       111, 110, 109, 108, 107, 106, 105, 104,
+       103, 102, 100,  99,  98,  97,  95,  94,
+       93,  91,  90,  88,  87,  85,  84,  82,
+       80,  79,  77,  76,  74,  72,  70,  69,
+       67,  65,  63,  61,  60,  58,  56,  54,
+       52,  50,  48,  46,  44,  42,  40,  38,
+       36,  34,  32,  30,  28,  26,  24,  22,
+       19,  17,  15,  13,  11,   9,   7,   5,
+       2,   0,  -1,  -3,  -5,  -7,  -9, -12,
+       -14, -16, -18, -20, -22, -24, -26, -28,
+       -31, -33, -35, -37, -39, -41, -43, -45,
+       -47, -49, -51, -53, -54, -56, -58, -60,
+       -62, -64, -66, -67, -69, -71, -73, -74,
+       -76, -78, -79, -81, -83, -84, -86, -87,
+       -89, -90, -92, -93, -94, -96, -97, -98,
+       -99, -101, -102, -103, -104, -105, -106, -107,
+       -108, -109, -110, -111, -112, -113, -114, -114,
+       -115, -116, -117, -117, -118, -118, -119, -119,
+       -120, -120, -120, -121, -121, -121, -122, -122,
+       -122, -122, -122, -122, -122, -122, -122, -122,
+       -122, -122, -121, -121, -121, -120, -120, -120,
+       -119, -119, -118, -118, -117, -116, -116, -115,
+       -114, -113, -113, -112, -111, -110, -109, -108,
+       -107, -106, -105, -104, -103, -102, -100, -99,
+       -98, -97, -95, -94, -93, -91, -90, -88,
+       -87, -85, -84, -82, -80, -79, -77, -76,
+       -74, -72, -70, -69, -67, -65, -63, -61,
+       -60, -58, -56, -54, -52, -50, -48, -46,
+       -44, -42, -40, -38, -36, -34, -32, -30,
+       -28, -26, -24, -22, -19, -17, -15, -13,
+       -11,  -9,  -7,  -5,  -2,   0,   1,   3,
+       5,   7,   9,  12,  14,  16,  18,  20,
+       22,  24,  26,  28,  31,  33,  35,  37,
+       39,  41,  43,  45,  47,  49,  51,  53,
+       54,  56,  58,  60,  62,  64,  66,  67,
+       69,  71,  73,  74,  76,  78,  79,  81,
+       83,  84,  86,  87,  89,  90,  92,  93,
+       94,  96,  97,  98,  99, 101, 102, 103,
+       104, 105, 106, 107, 108, 109, 110, 111, 112
+};
+
+static const s16 hsv_blue_y[] = {
+       -11, -13, -15, -17, -19, -21, -23, -25,
+       -27, -29, -31, -33, -35, -37, -39, -41,
+       -43, -45, -46, -48, -50, -52, -54, -55,
+       -57, -59, -61, -62, -64, -66, -67, -69,
+       -71, -72, -74, -75, -77, -78, -80, -81,
+       -83, -84, -86, -87, -88, -90, -91, -92,
+       -93, -95, -96, -97, -98, -99, -100, -101,
+       -102, -103, -104, -105, -106, -106, -107, -108,
+       -109, -109, -110, -111, -111, -112, -112, -113,
+       -113, -114, -114, -114, -115, -115, -115, -115,
+       -116, -116, -116, -116, -116, -116, -116, -116,
+       -116, -115, -115, -115, -115, -114, -114, -114,
+       -113, -113, -112, -112, -111, -111, -110, -110,
+       -109, -108, -108, -107, -106, -105, -104, -103,
+       -102, -101, -100, -99, -98, -97, -96, -95,
+       -94, -93, -91, -90, -89, -88, -86, -85,
+       -84, -82, -81, -79, -78, -76, -75, -73,
+       -71, -70, -68, -67, -65, -63, -62, -60,
+       -58, -56, -55, -53, -51, -49, -47, -45,
+       -44, -42, -40, -38, -36, -34, -32, -30,
+       -28, -26, -24, -22, -20, -18, -16, -14,
+       -12, -10,  -8,  -6,  -4,  -2,   0,   1,
+       3,   5,   7,   9,  11,  13,  15,  17,
+       19,  21,  23,  25,  27,  29,  31,  33,
+       35,  37,  39,  41,  43,  45,  46,  48,
+       50,  52,  54,  55,  57,  59,  61,  62,
+       64,  66,  67,  69,  71,  72,  74,  75,
+       77,  78,  80,  81,  83,  84,  86,  87,
+       88,  90,  91,  92,  93,  95,  96,  97,
+       98,  99, 100, 101, 102, 103, 104, 105,
+       106, 106, 107, 108, 109, 109, 110, 111,
+       111, 112, 112, 113, 113, 114, 114, 114,
+       115, 115, 115, 115, 116, 116, 116, 116,
+       116, 116, 116, 116, 116, 115, 115, 115,
+       115, 114, 114, 114, 113, 113, 112, 112,
+       111, 111, 110, 110, 109, 108, 108, 107,
+       106, 105, 104, 103, 102, 101, 100,  99,
+       98,  97,  96,  95,  94,  93,  91,  90,
+       89,  88,  86,  85,  84,  82,  81,  79,
+       78,  76,  75,  73,  71,  70,  68,  67,
+       65,  63,  62,  60,  58,  56,  55,  53,
+       51,  49,  47,  45,  44,  42,  40,  38,
+       36,  34,  32,  30,  28,  26,  24,  22,
+       20,  18,  16,  14,  12,  10,   8,   6,
+       4,   2,   0,  -1,  -3,  -5,  -7,  -9, -11
+};
+
+static const u16 i2c_ident[] = {
+       V4L2_IDENT_OV9650,
+       V4L2_IDENT_OV9655,
+       V4L2_IDENT_SOI968,
+       V4L2_IDENT_OV7660,
+       V4L2_IDENT_OV7670,
+       V4L2_IDENT_MT9V011,
+       V4L2_IDENT_MT9V111,
+       V4L2_IDENT_MT9V112,
+       V4L2_IDENT_MT9M001C12ST,
+       V4L2_IDENT_MT9M111,
+       V4L2_IDENT_MT9M112,
+       V4L2_IDENT_HV7131R,
+[SENSOR_MT9VPRB] = V4L2_IDENT_UNKNOWN,
+};
+
+static const u16 bridge_init[][2] = {
+       {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
+       {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
+       {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
+       {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
+       {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
+       {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
+       {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
+       {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
+       {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
+       {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
+       {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
+       {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
+       {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
+       {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
+       {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
+       {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
+       {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
+       {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
+       {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
+       {0x1007, 0x00}
+};
+
+/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
+static const u8 ov_gain[] = {
+       0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
+       0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
+       0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
+       0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
+       0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
+       0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
+       0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
+       0x70 /* 8x */
+};
+
+/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
+static const u16 micron1_gain[] = {
+       /* 1x   1.25x   1.5x    1.75x */
+       0x0020, 0x0028, 0x0030, 0x0038,
+       /* 2x   2.25x   2.5x    2.75x */
+       0x00a0, 0x00a4, 0x00a8, 0x00ac,
+       /* 3x   3.25x   3.5x    3.75x */
+       0x00b0, 0x00b4, 0x00b8, 0x00bc,
+       /* 4x   4.25x   4.5x    4.75x */
+       0x00c0, 0x00c4, 0x00c8, 0x00cc,
+       /* 5x   5.25x   5.5x    5.75x */
+       0x00d0, 0x00d4, 0x00d8, 0x00dc,
+       /* 6x   6.25x   6.5x    6.75x */
+       0x00e0, 0x00e4, 0x00e8, 0x00ec,
+       /* 7x   7.25x   7.5x    7.75x */
+       0x00f0, 0x00f4, 0x00f8, 0x00fc,
+       /* 8x */
+       0x01c0
+};
+
+/* mt9m001 sensor uses a different gain formula then other micron sensors */
+/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
+static const u16 micron2_gain[] = {
+       /* 1x   1.25x   1.5x    1.75x */
+       0x0008, 0x000a, 0x000c, 0x000e,
+       /* 2x   2.25x   2.5x    2.75x */
+       0x0010, 0x0012, 0x0014, 0x0016,
+       /* 3x   3.25x   3.5x    3.75x */
+       0x0018, 0x001a, 0x001c, 0x001e,
+       /* 4x   4.25x   4.5x    4.75x */
+       0x0020, 0x0051, 0x0052, 0x0053,
+       /* 5x   5.25x   5.5x    5.75x */
+       0x0054, 0x0055, 0x0056, 0x0057,
+       /* 6x   6.25x   6.5x    6.75x */
+       0x0058, 0x0059, 0x005a, 0x005b,
+       /* 7x   7.25x   7.5x    7.75x */
+       0x005c, 0x005d, 0x005e, 0x005f,
+       /* 8x */
+       0x0060
+};
+
+/* Gain = .5 + bit[7:0] / 16 */
+static const u8 hv7131r_gain[] = {
+       0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
+       0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
+       0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
+       0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
+       0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
+       0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
+       0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
+       0x78 /* 8x */
+};
+
+static const struct i2c_reg_u8 soi968_init[] = {
+       {0x0c, 0x00}, {0x0f, 0x1f},
+       {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
+       {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
+       {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
+       {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
+       {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
+       {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
+       {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
+       {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
+       {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
+       {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
+};
+
+static const struct i2c_reg_u8 ov7660_init[] = {
+       {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
+       {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
+       {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
+       /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
+          0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
+       {0x17, 0x10}, {0x18, 0x61},
+       {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
+       {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0x00},
+       {0x2e, 0x00}, {0x01, 0x78}, {0x02, 0x50},
+};
+
+static const struct i2c_reg_u8 ov7670_init[] = {
+       {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
+       {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
+       {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
+       {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
+       {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
+       {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
+       {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
+       {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
+       {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
+       {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
+       {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
+       {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
+       {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
+       {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
+       {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
+       {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
+       {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
+       {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
+       {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
+       {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
+       {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
+       {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
+       {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
+       {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
+       {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
+       {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
+       {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
+       {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
+       {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
+       {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
+       {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
+       {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
+       {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
+       {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
+       {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
+       {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
+       {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
+       {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
+       {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
+       {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
+       {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
+       {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
+       {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
+       {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
+       {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
+       {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
+       {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
+       {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
+       {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
+       {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
+       {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
+       {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
+       {0x93, 0x00},
+};
+
+static const struct i2c_reg_u8 ov9650_init[] = {
+       {0x00, 0x00}, {0x01, 0x78},
+       {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
+       {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
+       {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
+       {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
+       {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
+       {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
+       {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
+       {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
+       {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
+       {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
+       {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
+       {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
+       {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
+       {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
+       {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
+       {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
+       {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
+       {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
+       {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
+       {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
+       {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
+       {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
+       {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
+       {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
+       {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
+       {0xaa, 0x92}, {0xab, 0x0a},
+};
+
+static const struct i2c_reg_u8 ov9655_init[] = {
+       {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
+       {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
+       {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
+       {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
+       {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
+       {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
+       {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
+       {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
+       {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
+       {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
+       {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
+       {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
+       {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
+       {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
+       {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
+       {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
+       {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
+       {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
+       {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
+       {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
+       {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
+       {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
+       {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
+       {0x04, 0x03}, {0x00, 0x13},
+};
+
+static const struct i2c_reg_u16 mt9v112_init[] = {
+       {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
+       {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
+       {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
+       {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
+       {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
+       {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
+       {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
+       {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
+       {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
+       {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
+       {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
+       {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
+       {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
+       {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
+       {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
+       {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
+};
+
+static const struct i2c_reg_u16 mt9v111_init[] = {
+       {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
+       {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
+       {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
+       {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
+       {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
+       {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
+       {0x0e, 0x0008}, {0x20, 0x0000}
+};
+
+static const struct i2c_reg_u16 mt9v011_init[] = {
+       {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
+       {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
+       {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
+       {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
+       {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
+       {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
+       {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
+       {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
+       {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
+       {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
+       {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
+       {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
+       {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
+       {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
+       {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
+       {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
+       {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
+       {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
+       {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
+       {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
+       {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
+       {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
+       {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
+       {0x06, 0x0029}, {0x05, 0x0009},
+};
+
+static const struct i2c_reg_u16 mt9m001_init[] = {
+       {0x0d, 0x0001},
+       {0x0d, 0x0000},
+       {0x04, 0x0500},         /* hres = 1280 */
+       {0x03, 0x0400},         /* vres = 1024 */
+       {0x20, 0x1100},
+       {0x06, 0x0010},
+       {0x2b, 0x0024},
+       {0x2e, 0x0024},
+       {0x35, 0x0024},
+       {0x2d, 0x0020},
+       {0x2c, 0x0020},
+       {0x09, 0x0ad4},
+       {0x35, 0x0057},
+};
+
+static const struct i2c_reg_u16 mt9m111_init[] = {
+       {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
+       {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
+       {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
+       {0xf0, 0x0000},
+};
+
+static const struct i2c_reg_u16 mt9m112_init[] = {
+       {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
+       {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
+       {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
+       {0xf0, 0x0000},
+};
+
+static const struct i2c_reg_u8 hv7131r_init[] = {
+       {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
+       {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
+       {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
+       {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
+       {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
+       {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
+       {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
+       {0x23, 0x09}, {0x01, 0x08},
+};
+
+static void reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int result;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                       0x00,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       reg,
+                       0x00,
+                       gspca_dev->usb_buf,
+                       length,
+                       500);
+       if (unlikely(result < 0 || result != length)) {
+               pr_err("Read register %02x failed %d\n", reg, result);
+               gspca_dev->usb_err = result;
+       }
+}
+
+static void reg_w(struct gspca_dev *gspca_dev, u16 reg,
+                const u8 *buffer, int length)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int result;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       memcpy(gspca_dev->usb_buf, buffer, length);
+       result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                       0x08,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       reg,
+                       0x00,
+                       gspca_dev->usb_buf,
+                       length,
+                       500);
+       if (unlikely(result < 0 || result != length)) {
+               pr_err("Write register %02x failed %d\n", reg, result);
+               gspca_dev->usb_err = result;
+       }
+}
+
+static void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
+{
+       reg_w(gspca_dev, reg, &value, 1);
+}
+
+static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
+{
+       int i;
+
+       reg_w(gspca_dev, 0x10c0, buffer, 8);
+       for (i = 0; i < 5; i++) {
+               reg_r(gspca_dev, 0x10c0, 1);
+               if (gspca_dev->usb_err < 0)
+                       return;
+               if (gspca_dev->usb_buf[0] & 0x04) {
+                       if (gspca_dev->usb_buf[0] & 0x08) {
+                               pr_err("i2c_w error\n");
+                               gspca_dev->usb_err = -EIO;
+                       }
+                       return;
+               }
+               msleep(10);
+       }
+       pr_err("i2c_w reg %02x no response\n", buffer[2]);
+/*     gspca_dev->usb_err = -EIO;      fixme: may occur */
+}
+
+static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 row[8];
+
+       /*
+        * from the point of view of the bridge, the length
+        * includes the address
+        */
+       row[0] = sd->i2c_intf | (2 << 4);
+       row[1] = sd->i2c_addr;
+       row[2] = reg;
+       row[3] = val;
+       row[4] = 0x00;
+       row[5] = 0x00;
+       row[6] = 0x00;
+       row[7] = 0x10;
+
+       i2c_w(gspca_dev, row);
+}
+
+static void i2c_w1_buf(struct gspca_dev *gspca_dev,
+                       const struct i2c_reg_u8 *buf, int sz)
+{
+       while (--sz >= 0) {
+               i2c_w1(gspca_dev, buf->reg, buf->val);
+               buf++;
+       }
+}
+
+static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 row[8];
+
+       /*
+        * from the point of view of the bridge, the length
+        * includes the address
+        */
+       row[0] = sd->i2c_intf | (3 << 4);
+       row[1] = sd->i2c_addr;
+       row[2] = reg;
+       row[3] = val >> 8;
+       row[4] = val;
+       row[5] = 0x00;
+       row[6] = 0x00;
+       row[7] = 0x10;
+
+       i2c_w(gspca_dev, row);
+}
+
+static void i2c_w2_buf(struct gspca_dev *gspca_dev,
+                       const struct i2c_reg_u16 *buf, int sz)
+{
+       while (--sz >= 0) {
+               i2c_w2(gspca_dev, buf->reg, buf->val);
+               buf++;
+       }
+}
+
+static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 row[8];
+
+       row[0] = sd->i2c_intf | (1 << 4);
+       row[1] = sd->i2c_addr;
+       row[2] = reg;
+       row[3] = 0;
+       row[4] = 0;
+       row[5] = 0;
+       row[6] = 0;
+       row[7] = 0x10;
+       i2c_w(gspca_dev, row);
+       row[0] = sd->i2c_intf | (1 << 4) | 0x02;
+       row[2] = 0;
+       i2c_w(gspca_dev, row);
+       reg_r(gspca_dev, 0x10c2, 5);
+       *val = gspca_dev->usb_buf[4];
+}
+
+static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 row[8];
+
+       row[0] = sd->i2c_intf | (1 << 4);
+       row[1] = sd->i2c_addr;
+       row[2] = reg;
+       row[3] = 0;
+       row[4] = 0;
+       row[5] = 0;
+       row[6] = 0;
+       row[7] = 0x10;
+       i2c_w(gspca_dev, row);
+       row[0] = sd->i2c_intf | (2 << 4) | 0x02;
+       row[2] = 0;
+       i2c_w(gspca_dev, row);
+       reg_r(gspca_dev, 0x10c2, 5);
+       *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
+}
+
+static void ov9650_init_sensor(struct gspca_dev *gspca_dev)
+{
+       u16 id;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       i2c_r2(gspca_dev, 0x1c, &id);
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       if (id != 0x7fa2) {
+               pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
+               gspca_dev->usb_err = -ENODEV;
+               return;
+       }
+
+       i2c_w1(gspca_dev, 0x12, 0x80);          /* sensor reset */
+       msleep(200);
+       i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init));
+       if (gspca_dev->usb_err < 0)
+               pr_err("OV9650 sensor initialization failed\n");
+       sd->hstart = 1;
+       sd->vstart = 7;
+}
+
+static void ov9655_init_sensor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       i2c_w1(gspca_dev, 0x12, 0x80);          /* sensor reset */
+       msleep(200);
+       i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init));
+       if (gspca_dev->usb_err < 0)
+               pr_err("OV9655 sensor initialization failed\n");
+
+       sd->hstart = 1;
+       sd->vstart = 2;
+}
+
+static void soi968_init_sensor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       i2c_w1(gspca_dev, 0x12, 0x80);          /* sensor reset */
+       msleep(200);
+       i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init));
+       if (gspca_dev->usb_err < 0)
+               pr_err("SOI968 sensor initialization failed\n");
+
+       sd->hstart = 60;
+       sd->vstart = 11;
+}
+
+static void ov7660_init_sensor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       i2c_w1(gspca_dev, 0x12, 0x80);          /* sensor reset */
+       msleep(200);
+       i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init));
+       if (gspca_dev->usb_err < 0)
+               pr_err("OV7660 sensor initialization failed\n");
+       sd->hstart = 3;
+       sd->vstart = 3;
+}
+
+static void ov7670_init_sensor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       i2c_w1(gspca_dev, 0x12, 0x80);          /* sensor reset */
+       msleep(200);
+       i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init));
+       if (gspca_dev->usb_err < 0)
+               pr_err("OV7670 sensor initialization failed\n");
+
+       sd->hstart = 0;
+       sd->vstart = 1;
+}
+
+static void mt9v_init_sensor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u16 value;
+
+       sd->i2c_addr = 0x5d;
+       i2c_r2(gspca_dev, 0xff, &value);
+       if (gspca_dev->usb_err >= 0
+        && value == 0x8243) {
+               i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init));
+               if (gspca_dev->usb_err < 0) {
+                       pr_err("MT9V011 sensor initialization failed\n");
+                       return;
+               }
+               sd->hstart = 2;
+               sd->vstart = 2;
+               sd->sensor = SENSOR_MT9V011;
+               pr_info("MT9V011 sensor detected\n");
+               return;
+       }
+
+       gspca_dev->usb_err = 0;
+       sd->i2c_addr = 0x5c;
+       i2c_w2(gspca_dev, 0x01, 0x0004);
+       i2c_r2(gspca_dev, 0xff, &value);
+       if (gspca_dev->usb_err >= 0
+        && value == 0x823a) {
+               i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init));
+               if (gspca_dev->usb_err < 0) {
+                       pr_err("MT9V111 sensor initialization failed\n");
+                       return;
+               }
+               sd->hstart = 2;
+               sd->vstart = 2;
+               sd->sensor = SENSOR_MT9V111;
+               pr_info("MT9V111 sensor detected\n");
+               return;
+       }
+
+       gspca_dev->usb_err = 0;
+       sd->i2c_addr = 0x5d;
+       i2c_w2(gspca_dev, 0xf0, 0x0000);
+       if (gspca_dev->usb_err < 0) {
+               gspca_dev->usb_err = 0;
+               sd->i2c_addr = 0x48;
+               i2c_w2(gspca_dev, 0xf0, 0x0000);
+       }
+       i2c_r2(gspca_dev, 0x00, &value);
+       if (gspca_dev->usb_err >= 0
+        && value == 0x1229) {
+               i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init));
+               if (gspca_dev->usb_err < 0) {
+                       pr_err("MT9V112 sensor initialization failed\n");
+                       return;
+               }
+               sd->hstart = 6;
+               sd->vstart = 2;
+               sd->sensor = SENSOR_MT9V112;
+               pr_info("MT9V112 sensor detected\n");
+               return;
+       }
+
+       gspca_dev->usb_err = -ENODEV;
+}
+
+static void mt9m112_init_sensor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init));
+       if (gspca_dev->usb_err < 0)
+               pr_err("MT9M112 sensor initialization failed\n");
+
+       sd->hstart = 0;
+       sd->vstart = 2;
+}
+
+static void mt9m111_init_sensor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init));
+       if (gspca_dev->usb_err < 0)
+               pr_err("MT9M111 sensor initialization failed\n");
+
+       sd->hstart = 0;
+       sd->vstart = 2;
+}
+
+static void mt9m001_init_sensor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u16 id;
+
+       i2c_r2(gspca_dev, 0x00, &id);
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
+       switch (id) {
+       case 0x8411:
+       case 0x8421:
+               pr_info("MT9M001 color sensor detected\n");
+               break;
+       case 0x8431:
+               pr_info("MT9M001 mono sensor detected\n");
+               break;
+       default:
+               pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
+               gspca_dev->usb_err = -ENODEV;
+               return;
+       }
+
+       i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init));
+       if (gspca_dev->usb_err < 0)
+               pr_err("MT9M001 sensor initialization failed\n");
+
+       sd->hstart = 1;
+       sd->vstart = 1;
+}
+
+static void hv7131r_init_sensor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init));
+       if (gspca_dev->usb_err < 0)
+               pr_err("HV7131R Sensor initialization failed\n");
+
+       sd->hstart = 0;
+       sd->vstart = 1;
+}
+
+static void set_cmatrix(struct gspca_dev *gspca_dev,
+               s32 brightness, s32 contrast, s32 satur, s32 hue)
+{
+       s32 hue_coord, hue_index = 180 + hue;
+       u8 cmatrix[21];
+
+       memset(cmatrix, 0, sizeof cmatrix);
+       cmatrix[2] = (contrast * 0x25 / 0x100) + 0x26;
+       cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
+       cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
+       cmatrix[18] = brightness - 0x80;
+
+       hue_coord = (hsv_red_x[hue_index] * satur) >> 8;
+       cmatrix[6] = hue_coord;
+       cmatrix[7] = (hue_coord >> 8) & 0x0f;
+
+       hue_coord = (hsv_red_y[hue_index] * satur) >> 8;
+       cmatrix[8] = hue_coord;
+       cmatrix[9] = (hue_coord >> 8) & 0x0f;
+
+       hue_coord = (hsv_green_x[hue_index] * satur) >> 8;
+       cmatrix[10] = hue_coord;
+       cmatrix[11] = (hue_coord >> 8) & 0x0f;
+
+       hue_coord = (hsv_green_y[hue_index] * satur) >> 8;
+       cmatrix[12] = hue_coord;
+       cmatrix[13] = (hue_coord >> 8) & 0x0f;
+
+       hue_coord = (hsv_blue_x[hue_index] * satur) >> 8;
+       cmatrix[14] = hue_coord;
+       cmatrix[15] = (hue_coord >> 8) & 0x0f;
+
+       hue_coord = (hsv_blue_y[hue_index] * satur) >> 8;
+       cmatrix[16] = hue_coord;
+       cmatrix[17] = (hue_coord >> 8) & 0x0f;
+
+       reg_w(gspca_dev, 0x10e1, cmatrix, 21);
+}
+
+static void set_gamma(struct gspca_dev *gspca_dev, s32 val)
+{
+       u8 gamma[17];
+       u8 gval = val * 0xb8 / 0x100;
+
+       gamma[0] = 0x0a;
+       gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
+       gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
+       gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
+       gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
+       gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
+       gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
+       gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
+       gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
+       gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
+       gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
+       gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
+       gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
+       gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
+       gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
+       gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
+       gamma[16] = 0xf5;
+
+       reg_w(gspca_dev, 0x1190, gamma, 17);
+}
+
+static void set_redblue(struct gspca_dev *gspca_dev, s32 blue, s32 red)
+{
+       reg_w1(gspca_dev, 0x118c, red);
+       reg_w1(gspca_dev, 0x118f, blue);
+}
+
+static void set_hvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
+{
+       u8 value, tslb;
+       u16 value2;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
+               hflip = !hflip;
+               vflip = !vflip;
+       }
+
+       switch (sd->sensor) {
+       case SENSOR_OV7660:
+               value = 0x01;
+               if (hflip)
+                       value |= 0x20;
+               if (vflip) {
+                       value |= 0x10;
+                       sd->vstart = 2;
+               } else {
+                       sd->vstart = 3;
+               }
+               reg_w1(gspca_dev, 0x1182, sd->vstart);
+               i2c_w1(gspca_dev, 0x1e, value);
+               break;
+       case SENSOR_OV9650:
+               i2c_r1(gspca_dev, 0x1e, &value);
+               value &= ~0x30;
+               tslb = 0x01;
+               if (hflip)
+                       value |= 0x20;
+               if (vflip) {
+                       value |= 0x10;
+                       tslb = 0x49;
+               }
+               i2c_w1(gspca_dev, 0x1e, value);
+               i2c_w1(gspca_dev, 0x3a, tslb);
+               break;
+       case SENSOR_MT9V111:
+       case SENSOR_MT9V011:
+               i2c_r2(gspca_dev, 0x20, &value2);
+               value2 &= ~0xc0a0;
+               if (hflip)
+                       value2 |= 0x8080;
+               if (vflip)
+                       value2 |= 0x4020;
+               i2c_w2(gspca_dev, 0x20, value2);
+               break;
+       case SENSOR_MT9M112:
+       case SENSOR_MT9M111:
+       case SENSOR_MT9V112:
+               i2c_r2(gspca_dev, 0x20, &value2);
+               value2 &= ~0x0003;
+               if (hflip)
+                       value2 |= 0x0002;
+               if (vflip)
+                       value2 |= 0x0001;
+               i2c_w2(gspca_dev, 0x20, value2);
+               break;
+       case SENSOR_HV7131R:
+               i2c_r1(gspca_dev, 0x01, &value);
+               value &= ~0x03;
+               if (vflip)
+                       value |= 0x01;
+               if (hflip)
+                       value |= 0x02;
+               i2c_w1(gspca_dev, 0x01, value);
+               break;
+       }
+}
+
+static void set_exposure(struct gspca_dev *gspca_dev, s32 expo)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 exp[8] = {sd->i2c_intf, sd->i2c_addr,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
+       int expo2;
+
+       if (gspca_dev->streaming)
+               exp[7] = 0x1e;
+
+       switch (sd->sensor) {
+       case SENSOR_OV7660:
+       case SENSOR_OV7670:
+       case SENSOR_OV9655:
+       case SENSOR_OV9650:
+               if (expo > 547)
+                       expo2 = 547;
+               else
+                       expo2 = expo;
+               exp[0] |= (2 << 4);
+               exp[2] = 0x10;                  /* AECH */
+               exp[3] = expo2 >> 2;
+               exp[7] = 0x10;
+               i2c_w(gspca_dev, exp);
+               exp[2] = 0x04;                  /* COM1 */
+               exp[3] = expo2 & 0x0003;
+               exp[7] = 0x10;
+               i2c_w(gspca_dev, exp);
+               expo -= expo2;
+               exp[7] = 0x1e;
+               exp[0] |= (3 << 4);
+               exp[2] = 0x2d;                  /* ADVFL & ADVFH */
+               exp[3] = expo;
+               exp[4] = expo >> 8;
+               break;
+       case SENSOR_MT9M001:
+       case SENSOR_MT9V112:
+       case SENSOR_MT9V011:
+               exp[0] |= (3 << 4);
+               exp[2] = 0x09;
+               exp[3] = expo >> 8;
+               exp[4] = expo;
+               break;
+       case SENSOR_HV7131R:
+               exp[0] |= (4 << 4);
+               exp[2] = 0x25;
+               exp[3] = expo >> 5;
+               exp[4] = expo << 3;
+               exp[5] = 0;
+               break;
+       default:
+               return;
+       }
+       i2c_w(gspca_dev, exp);
+}
+
+static void set_gain(struct gspca_dev *gspca_dev, s32 g)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 gain[8] = {sd->i2c_intf, sd->i2c_addr,
+                               0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
+
+       if (gspca_dev->streaming)
+               gain[7] = 0x15;         /* or 1d ? */
+
+       switch (sd->sensor) {
+       case SENSOR_OV7660:
+       case SENSOR_OV7670:
+       case SENSOR_SOI968:
+       case SENSOR_OV9655:
+       case SENSOR_OV9650:
+               gain[0] |= (2 << 4);
+               gain[3] = ov_gain[g];
+               break;
+       case SENSOR_MT9V011:
+               gain[0] |= (3 << 4);
+               gain[2] = 0x35;
+               gain[3] = micron1_gain[g] >> 8;
+               gain[4] = micron1_gain[g];
+               break;
+       case SENSOR_MT9V112:
+               gain[0] |= (3 << 4);
+               gain[2] = 0x2f;
+               gain[3] = micron1_gain[g] >> 8;
+               gain[4] = micron1_gain[g];
+               break;
+       case SENSOR_MT9M001:
+               gain[0] |= (3 << 4);
+               gain[2] = 0x2f;
+               gain[3] = micron2_gain[g] >> 8;
+               gain[4] = micron2_gain[g];
+               break;
+       case SENSOR_HV7131R:
+               gain[0] |= (2 << 4);
+               gain[2] = 0x30;
+               gain[3] = hv7131r_gain[g];
+               break;
+       default:
+               return;
+       }
+       i2c_w(gspca_dev, gain);
+}
+
+static void set_quality(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       jpeg_set_qual(sd->jpeg_hdr, val);
+       reg_w1(gspca_dev, 0x1061, 0x01);        /* stop transfer */
+       reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */
+       reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
+       reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
+       reg_w1(gspca_dev, 0x1061, 0x03);        /* restart transfer */
+       reg_w1(gspca_dev, 0x10e0, sd->fmt);
+       sd->fmt ^= 0x0c;                        /* invert QTAB use + write */
+       reg_w1(gspca_dev, 0x10e0, sd->fmt);
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
+                       struct v4l2_dbg_register *reg)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (reg->match.type) {
+       case V4L2_CHIP_MATCH_HOST:
+               if (reg->match.addr != 0)
+                       return -EINVAL;
+               if (reg->reg < 0x1000 || reg->reg > 0x11ff)
+                       return -EINVAL;
+               reg_r(gspca_dev, reg->reg, 1);
+               reg->val = gspca_dev->usb_buf[0];
+               return gspca_dev->usb_err;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               if (reg->match.addr != sd->i2c_addr)
+                       return -EINVAL;
+               if (sd->sensor >= SENSOR_MT9V011 &&
+                   sd->sensor <= SENSOR_MT9M112) {
+                       i2c_r2(gspca_dev, reg->reg, (u16 *) &reg->val);
+               } else {
+                       i2c_r1(gspca_dev, reg->reg, (u8 *) &reg->val);
+               }
+               return gspca_dev->usb_err;
+       }
+       return -EINVAL;
+}
+
+static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
+                       struct v4l2_dbg_register *reg)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (reg->match.type) {
+       case V4L2_CHIP_MATCH_HOST:
+               if (reg->match.addr != 0)
+                       return -EINVAL;
+               if (reg->reg < 0x1000 || reg->reg > 0x11ff)
+                       return -EINVAL;
+               reg_w1(gspca_dev, reg->reg, reg->val);
+               return gspca_dev->usb_err;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               if (reg->match.addr != sd->i2c_addr)
+                       return -EINVAL;
+               if (sd->sensor >= SENSOR_MT9V011 &&
+                   sd->sensor <= SENSOR_MT9M112) {
+                       i2c_w2(gspca_dev, reg->reg, reg->val);
+               } else {
+                       i2c_w1(gspca_dev, reg->reg, reg->val);
+               }
+               return gspca_dev->usb_err;
+       }
+       return -EINVAL;
+}
+#endif
+
+static int sd_chip_ident(struct gspca_dev *gspca_dev,
+                       struct v4l2_dbg_chip_ident *chip)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (chip->match.type) {
+       case V4L2_CHIP_MATCH_HOST:
+               if (chip->match.addr != 0)
+                       return -EINVAL;
+               chip->revision = 0;
+               chip->ident = V4L2_IDENT_SN9C20X;
+               return 0;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               if (chip->match.addr != sd->i2c_addr)
+                       return -EINVAL;
+               chip->revision = 0;
+               chip->ident = i2c_ident[sd->sensor];
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+
+       cam = &gspca_dev->cam;
+       cam->needs_full_bandwidth = 1;
+
+       sd->sensor = id->driver_info >> 8;
+       sd->i2c_addr = id->driver_info;
+       sd->flags = id->driver_info >> 16;
+       sd->i2c_intf = 0x80;                    /* i2c 100 Kb/s */
+
+       switch (sd->sensor) {
+       case SENSOR_MT9M112:
+       case SENSOR_MT9M111:
+       case SENSOR_OV9650:
+       case SENSOR_SOI968:
+               cam->cam_mode = sxga_mode;
+               cam->nmodes = ARRAY_SIZE(sxga_mode);
+               break;
+       case SENSOR_MT9M001:
+               cam->cam_mode = mono_mode;
+               cam->nmodes = ARRAY_SIZE(mono_mode);
+               break;
+       case SENSOR_HV7131R:
+               sd->i2c_intf = 0x81;                    /* i2c 400 Kb/s */
+               /* fall thru */
+       default:
+               cam->cam_mode = vga_mode;
+               cam->nmodes = ARRAY_SIZE(vga_mode);
+               break;
+       }
+
+       sd->old_step = 0;
+       sd->older_step = 0;
+       sd->exposure_step = 16;
+
+       INIT_WORK(&sd->work, qual_upd);
+
+       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) {
+       /* color control cluster */
+       case V4L2_CID_BRIGHTNESS:
+               set_cmatrix(gspca_dev, sd->brightness->val,
+                       sd->contrast->val, sd->saturation->val, sd->hue->val);
+               break;
+       case V4L2_CID_GAMMA:
+               set_gamma(gspca_dev, ctrl->val);
+               break;
+       /* blue/red balance cluster */
+       case V4L2_CID_BLUE_BALANCE:
+               set_redblue(gspca_dev, sd->blue->val, sd->red->val);
+               break;
+       /* h/vflip cluster */
+       case V4L2_CID_HFLIP:
+               set_hvflip(gspca_dev, sd->hflip->val, sd->vflip->val);
+               break;
+       /* standalone exposure control */
+       case V4L2_CID_EXPOSURE:
+               set_exposure(gspca_dev, ctrl->val);
+               break;
+       /* standalone gain control */
+       case V4L2_CID_GAIN:
+               set_gain(gspca_dev, ctrl->val);
+               break;
+       /* autogain + exposure or gain control cluster */
+       case V4L2_CID_AUTOGAIN:
+               if (sd->sensor == SENSOR_SOI968)
+                       set_gain(gspca_dev, sd->gain->val);
+               else
+                       set_exposure(gspca_dev, sd->exposure->val);
+               break;
+       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+               set_quality(gspca_dev, ctrl->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, 13);
+
+       sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
+       sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 255, 1, 127);
+       sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 255, 1, 127);
+       sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_HUE, -180, 180, 1, 0);
+
+       sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAMMA, 0, 255, 1, 0x10);
+
+       sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BLUE_BALANCE, 0, 127, 1, 0x28);
+       sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_RED_BALANCE, 0, 127, 1, 0x28);
+
+       if (sd->sensor != SENSOR_OV9655 && sd->sensor != SENSOR_SOI968 &&
+           sd->sensor != SENSOR_OV7670 && sd->sensor != SENSOR_MT9M001 &&
+           sd->sensor != SENSOR_MT9VPRB) {
+               sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+               sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       }
+
+       if (sd->sensor != SENSOR_SOI968 && sd->sensor != SENSOR_MT9VPRB &&
+           sd->sensor != SENSOR_MT9M112 && sd->sensor != SENSOR_MT9M111 &&
+           sd->sensor != SENSOR_MT9V111)
+               sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0, 0x1780, 1, 0x33);
+
+       if (sd->sensor != SENSOR_MT9VPRB && sd->sensor != SENSOR_MT9M112 &&
+           sd->sensor != SENSOR_MT9M111 && sd->sensor != SENSOR_MT9V111) {
+               sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 28, 1, 0);
+               sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+       }
+
+       sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_JPEG_COMPRESSION_QUALITY, 50, 90, 1, 80);
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+
+       v4l2_ctrl_cluster(4, &sd->brightness);
+       v4l2_ctrl_cluster(2, &sd->blue);
+       if (sd->hflip)
+               v4l2_ctrl_cluster(2, &sd->hflip);
+       if (sd->autogain) {
+               if (sd->sensor == SENSOR_SOI968)
+                       /* this sensor doesn't have the exposure control and
+                          autogain is clustered with gain instead. This works
+                          because sd->exposure == NULL. */
+                       v4l2_ctrl_auto_cluster(3, &sd->autogain, 0, false);
+               else
+                       /* Otherwise autogain is clustered with exposure. */
+                       v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false);
+       }
+       return 0;
+}
+
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+       u8 value;
+       u8 i2c_init[9] =
+               {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
+
+       for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
+               value = bridge_init[i][1];
+               reg_w(gspca_dev, bridge_init[i][0], &value, 1);
+               if (gspca_dev->usb_err < 0) {
+                       pr_err("Device initialization failed\n");
+                       return gspca_dev->usb_err;
+               }
+       }
+
+       if (sd->flags & LED_REVERSE)
+               reg_w1(gspca_dev, 0x1006, 0x00);
+       else
+               reg_w1(gspca_dev, 0x1006, 0x20);
+
+       reg_w(gspca_dev, 0x10c0, i2c_init, 9);
+       if (gspca_dev->usb_err < 0) {
+               pr_err("Device initialization failed\n");
+               return gspca_dev->usb_err;
+       }
+
+       switch (sd->sensor) {
+       case SENSOR_OV9650:
+               ov9650_init_sensor(gspca_dev);
+               if (gspca_dev->usb_err < 0)
+                       break;
+               pr_info("OV9650 sensor detected\n");
+               break;
+       case SENSOR_OV9655:
+               ov9655_init_sensor(gspca_dev);
+               if (gspca_dev->usb_err < 0)
+                       break;
+               pr_info("OV9655 sensor detected\n");
+               break;
+       case SENSOR_SOI968:
+               soi968_init_sensor(gspca_dev);
+               if (gspca_dev->usb_err < 0)
+                       break;
+               pr_info("SOI968 sensor detected\n");
+               break;
+       case SENSOR_OV7660:
+               ov7660_init_sensor(gspca_dev);
+               if (gspca_dev->usb_err < 0)
+                       break;
+               pr_info("OV7660 sensor detected\n");
+               break;
+       case SENSOR_OV7670:
+               ov7670_init_sensor(gspca_dev);
+               if (gspca_dev->usb_err < 0)
+                       break;
+               pr_info("OV7670 sensor detected\n");
+               break;
+       case SENSOR_MT9VPRB:
+               mt9v_init_sensor(gspca_dev);
+               if (gspca_dev->usb_err < 0)
+                       break;
+               pr_info("MT9VPRB sensor detected\n");
+               break;
+       case SENSOR_MT9M111:
+               mt9m111_init_sensor(gspca_dev);
+               if (gspca_dev->usb_err < 0)
+                       break;
+               pr_info("MT9M111 sensor detected\n");
+               break;
+       case SENSOR_MT9M112:
+               mt9m112_init_sensor(gspca_dev);
+               if (gspca_dev->usb_err < 0)
+                       break;
+               pr_info("MT9M112 sensor detected\n");
+               break;
+       case SENSOR_MT9M001:
+               mt9m001_init_sensor(gspca_dev);
+               if (gspca_dev->usb_err < 0)
+                       break;
+               break;
+       case SENSOR_HV7131R:
+               hv7131r_init_sensor(gspca_dev);
+               if (gspca_dev->usb_err < 0)
+                       break;
+               pr_info("HV7131R sensor detected\n");
+               break;
+       default:
+               pr_err("Unsupported sensor\n");
+               gspca_dev->usb_err = -ENODEV;
+       }
+       return gspca_dev->usb_err;
+}
+
+static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 value;
+
+       switch (sd->sensor) {
+       case SENSOR_SOI968:
+               if (mode & MODE_SXGA) {
+                       i2c_w1(gspca_dev, 0x17, 0x1d);
+                       i2c_w1(gspca_dev, 0x18, 0xbd);
+                       i2c_w1(gspca_dev, 0x19, 0x01);
+                       i2c_w1(gspca_dev, 0x1a, 0x81);
+                       i2c_w1(gspca_dev, 0x12, 0x00);
+                       sd->hstart = 140;
+                       sd->vstart = 19;
+               } else {
+                       i2c_w1(gspca_dev, 0x17, 0x13);
+                       i2c_w1(gspca_dev, 0x18, 0x63);
+                       i2c_w1(gspca_dev, 0x19, 0x01);
+                       i2c_w1(gspca_dev, 0x1a, 0x79);
+                       i2c_w1(gspca_dev, 0x12, 0x40);
+                       sd->hstart = 60;
+                       sd->vstart = 11;
+               }
+               break;
+       case SENSOR_OV9650:
+               if (mode & MODE_SXGA) {
+                       i2c_w1(gspca_dev, 0x17, 0x1b);
+                       i2c_w1(gspca_dev, 0x18, 0xbc);
+                       i2c_w1(gspca_dev, 0x19, 0x01);
+                       i2c_w1(gspca_dev, 0x1a, 0x82);
+                       i2c_r1(gspca_dev, 0x12, &value);
+                       i2c_w1(gspca_dev, 0x12, value & 0x07);
+               } else {
+                       i2c_w1(gspca_dev, 0x17, 0x24);
+                       i2c_w1(gspca_dev, 0x18, 0xc5);
+                       i2c_w1(gspca_dev, 0x19, 0x00);
+                       i2c_w1(gspca_dev, 0x1a, 0x3c);
+                       i2c_r1(gspca_dev, 0x12, &value);
+                       i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
+               }
+               break;
+       case SENSOR_MT9M112:
+       case SENSOR_MT9M111:
+               if (mode & MODE_SXGA) {
+                       i2c_w2(gspca_dev, 0xf0, 0x0002);
+                       i2c_w2(gspca_dev, 0xc8, 0x970b);
+                       i2c_w2(gspca_dev, 0xf0, 0x0000);
+               } else {
+                       i2c_w2(gspca_dev, 0xf0, 0x0002);
+                       i2c_w2(gspca_dev, 0xc8, 0x8000);
+                       i2c_w2(gspca_dev, 0xf0, 0x0000);
+               }
+               break;
+       }
+}
+
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+       struct usb_interface *intf;
+       u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
+
+       /*
+        * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
+        * than our regular bandwidth calculations reserve, so we force the
+        * use of a specific altsetting when using the SN9C20X_I420 fmt.
+        */
+       if (!(flags & (MODE_RAW | MODE_JPEG))) {
+               intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
+
+               if (intf->num_altsetting != 9) {
+                       pr_warn("sn9c20x camera with unknown number of alt "
+                               "settings (%d), please report!\n",
+                               intf->num_altsetting);
+                       gspca_dev->alt = intf->num_altsetting;
+                       return 0;
+               }
+
+               switch (gspca_dev->width) {
+               case 160: /* 160x120 */
+                       gspca_dev->alt = 2;
+                       break;
+               case 320: /* 320x240 */
+                       gspca_dev->alt = 6;
+                       break;
+               default:  /* >= 640x480 */
+                       gspca_dev->alt = 9;
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+#define HW_WIN(mode, hstart, vstart) \
+((const u8 []){hstart, 0, vstart, 0, \
+(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
+(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
+
+#define CLR_WIN(width, height) \
+((const u8 [])\
+{0, width >> 2, 0, height >> 1,\
+((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+       int width = gspca_dev->width;
+       int height = gspca_dev->height;
+       u8 fmt, scale = 0;
+
+       jpeg_define(sd->jpeg_hdr, height, width,
+                       0x21);
+       jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
+
+       if (mode & MODE_RAW)
+               fmt = 0x2d;
+       else if (mode & MODE_JPEG)
+               fmt = 0x24;
+       else
+               fmt = 0x2f;     /* YUV 420 */
+       sd->fmt = fmt;
+
+       switch (mode & SCALE_MASK) {
+       case SCALE_1280x1024:
+               scale = 0xc0;
+               pr_info("Set 1280x1024\n");
+               break;
+       case SCALE_640x480:
+               scale = 0x80;
+               pr_info("Set 640x480\n");
+               break;
+       case SCALE_320x240:
+               scale = 0x90;
+               pr_info("Set 320x240\n");
+               break;
+       case SCALE_160x120:
+               scale = 0xa0;
+               pr_info("Set 160x120\n");
+               break;
+       }
+
+       configure_sensor_output(gspca_dev, mode);
+       reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
+       reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
+       reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
+       reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
+       reg_w1(gspca_dev, 0x1189, scale);
+       reg_w1(gspca_dev, 0x10e0, fmt);
+
+       set_cmatrix(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness),
+                       v4l2_ctrl_g_ctrl(sd->contrast),
+                       v4l2_ctrl_g_ctrl(sd->saturation),
+                       v4l2_ctrl_g_ctrl(sd->hue));
+       set_gamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
+       set_redblue(gspca_dev, v4l2_ctrl_g_ctrl(sd->blue),
+                       v4l2_ctrl_g_ctrl(sd->red));
+       if (sd->gain)
+               set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
+       if (sd->exposure)
+               set_exposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
+       if (sd->hflip)
+               set_hvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip),
+                               v4l2_ctrl_g_ctrl(sd->vflip));
+
+       reg_w1(gspca_dev, 0x1007, 0x20);
+       reg_w1(gspca_dev, 0x1061, 0x03);
+
+       /* if JPEG, prepare the compression quality update */
+       if (mode & MODE_JPEG) {
+               sd->pktsz = sd->npkt = 0;
+               sd->nchg = 0;
+               sd->work_thread =
+                       create_singlethread_workqueue(KBUILD_MODNAME);
+       }
+
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       reg_w1(gspca_dev, 0x1007, 0x00);
+       reg_w1(gspca_dev, 0x1061, 0x01);
+}
+
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->work_thread != NULL) {
+               mutex_unlock(&gspca_dev->usb_lock);
+               destroy_workqueue(sd->work_thread);
+               mutex_lock(&gspca_dev->usb_lock);
+               sd->work_thread = NULL;
+       }
+}
+
+static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 cur_exp = v4l2_ctrl_g_ctrl(sd->exposure);
+       s32 max = sd->exposure->maximum - sd->exposure_step;
+       s32 min = sd->exposure->minimum + sd->exposure_step;
+       s16 new_exp;
+
+       /*
+        * some hardcoded values are present
+        * like those for maximal/minimal exposure
+        * and exposure steps
+        */
+       if (avg_lum < MIN_AVG_LUM) {
+               if (cur_exp > max)
+                       return;
+
+               new_exp = cur_exp + sd->exposure_step;
+               if (new_exp > max)
+                       new_exp = max;
+               if (new_exp < min)
+                       new_exp = min;
+               v4l2_ctrl_s_ctrl(sd->exposure, new_exp);
+
+               sd->older_step = sd->old_step;
+               sd->old_step = 1;
+
+               if (sd->old_step ^ sd->older_step)
+                       sd->exposure_step /= 2;
+               else
+                       sd->exposure_step += 2;
+       }
+       if (avg_lum > MAX_AVG_LUM) {
+               if (cur_exp < min)
+                       return;
+               new_exp = cur_exp - sd->exposure_step;
+               if (new_exp > max)
+                       new_exp = max;
+               if (new_exp < min)
+                       new_exp = min;
+               v4l2_ctrl_s_ctrl(sd->exposure, new_exp);
+               sd->older_step = sd->old_step;
+               sd->old_step = 0;
+
+               if (sd->old_step ^ sd->older_step)
+                       sd->exposure_step /= 2;
+               else
+                       sd->exposure_step += 2;
+       }
+}
+
+static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain);
+
+       if (avg_lum < MIN_AVG_LUM && cur_gain < sd->gain->maximum)
+               v4l2_ctrl_s_ctrl(sd->gain, cur_gain + 1);
+       if (avg_lum > MAX_AVG_LUM && cur_gain > sd->gain->minimum)
+               v4l2_ctrl_s_ctrl(sd->gain, cur_gain - 1);
+}
+
+static void sd_dqcallback(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int avg_lum;
+
+       if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain))
+               return;
+
+       avg_lum = atomic_read(&sd->avg_lum);
+       if (sd->sensor == SENSOR_SOI968)
+               do_autogain(gspca_dev, avg_lum);
+       else
+               do_autoexposure(gspca_dev, avg_lum);
+}
+
+/* JPEG quality update */
+/* This function is executed from a work queue. */
+static void qual_upd(struct work_struct *work)
+{
+       struct sd *sd = container_of(work, struct sd, work);
+       struct gspca_dev *gspca_dev = &sd->gspca_dev;
+       s32 qual = v4l2_ctrl_g_ctrl(sd->jpegqual);
+
+       mutex_lock(&gspca_dev->usb_lock);
+       PDEBUG(D_STREAM, "qual_upd %d%%", qual);
+       set_quality(gspca_dev, qual);
+       mutex_unlock(&gspca_dev->usb_lock);
+}
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,               /* interrupt packet */
+                       int len)                /* interrupt packet length */
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
+               input_sync(gspca_dev->input_dev);
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+               input_sync(gspca_dev->input_dev);
+               return 0;
+       }
+       return -EINVAL;
+}
+#endif
+
+/* check the JPEG compression */
+static void transfer_check(struct gspca_dev *gspca_dev,
+                       u8 *data)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int new_qual, r;
+
+       new_qual = 0;
+
+       /* if USB error, discard the frame and decrease the quality */
+       if (data[6] & 0x08) {                           /* USB FIFO full */
+               gspca_dev->last_packet_type = DISCARD_PACKET;
+               new_qual = -5;
+       } else {
+
+               /* else, compute the filling rate and a new JPEG quality */
+               r = (sd->pktsz * 100) /
+                       (sd->npkt *
+                               gspca_dev->urb[0]->iso_frame_desc[0].length);
+               if (r >= 85)
+                       new_qual = -3;
+               else if (r < 75)
+                       new_qual = 2;
+       }
+       if (new_qual != 0) {
+               sd->nchg += new_qual;
+               if (sd->nchg < -6 || sd->nchg >= 12) {
+                       /* Note: we are in interrupt context, so we can't
+                          use v4l2_ctrl_g/s_ctrl here. Access the value
+                          directly instead. */
+                       s32 curqual = sd->jpegqual->cur.val;
+                       sd->nchg = 0;
+                       new_qual += curqual;
+                       if (new_qual < sd->jpegqual->minimum)
+                               new_qual = sd->jpegqual->minimum;
+                       else if (new_qual > sd->jpegqual->maximum)
+                               new_qual = sd->jpegqual->maximum;
+                       if (new_qual != curqual) {
+                               sd->jpegqual->cur.val = new_qual;
+                               queue_work(sd->work_thread, &sd->work);
+                       }
+               }
+       } else {
+               sd->nchg = 0;
+       }
+       sd->pktsz = sd->npkt = 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;
+       int avg_lum, is_jpeg;
+       static const u8 frame_header[] =
+               {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
+
+       is_jpeg = (sd->fmt & 0x03) == 0;
+       if (len >= 64 && memcmp(data, frame_header, 6) == 0) {
+               avg_lum = ((data[35] >> 2) & 3) |
+                          (data[20] << 2) |
+                          (data[19] << 10);
+               avg_lum += ((data[35] >> 4) & 3) |
+                           (data[22] << 2) |
+                           (data[21] << 10);
+               avg_lum += ((data[35] >> 6) & 3) |
+                           (data[24] << 2) |
+                           (data[23] << 10);
+               avg_lum += (data[36] & 3) |
+                          (data[26] << 2) |
+                          (data[25] << 10);
+               avg_lum += ((data[36] >> 2) & 3) |
+                           (data[28] << 2) |
+                           (data[27] << 10);
+               avg_lum += ((data[36] >> 4) & 3) |
+                           (data[30] << 2) |
+                           (data[29] << 10);
+               avg_lum += ((data[36] >> 6) & 3) |
+                           (data[32] << 2) |
+                           (data[31] << 10);
+               avg_lum += ((data[44] >> 4) & 3) |
+                           (data[34] << 2) |
+                           (data[33] << 10);
+               avg_lum >>= 9;
+               atomic_set(&sd->avg_lum, avg_lum);
+
+               if (is_jpeg)
+                       transfer_check(gspca_dev, data);
+
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+               len -= 64;
+               if (len == 0)
+                       return;
+               data += 64;
+       }
+       if (gspca_dev->last_packet_type == LAST_PACKET) {
+               if (is_jpeg) {
+                       gspca_frame_add(gspca_dev, FIRST_PACKET,
+                               sd->jpeg_hdr, JPEG_HDR_SZ);
+                       gspca_frame_add(gspca_dev, INTER_PACKET,
+                               data, len);
+               } else {
+                       gspca_frame_add(gspca_dev, FIRST_PACKET,
+                               data, len);
+               }
+       } else {
+               /* if JPEG, count the packets and their size */
+               if (is_jpeg) {
+                       sd->npkt++;
+                       sd->pktsz += len;
+               }
+               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+       }
+}
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name = KBUILD_MODNAME,
+       .config = sd_config,
+       .init = sd_init,
+       .init_controls = sd_init_controls,
+       .isoc_init = sd_isoc_init,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .stop0 = sd_stop0,
+       .pkt_scan = sd_pkt_scan,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .int_pkt_scan = sd_int_pkt_scan,
+#endif
+       .dq_callback = sd_dqcallback,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .set_register = sd_dbg_s_register,
+       .get_register = sd_dbg_g_register,
+#endif
+       .get_chip_ident = sd_chip_ident,
+};
+
+#define SN9C20X(sensor, i2c_addr, flags) \
+       .driver_info =  ((flags & 0xff) << 16) \
+                       | (SENSOR_ ## sensor << 8) \
+                       | (i2c_addr)
+
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
+       {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
+       {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
+       {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
+       {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
+                                            (FLIP_DETECT | HAS_NO_BUTTON))},
+       {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
+       {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
+       {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
+       {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
+       {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
+       {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
+       {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
+       {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
+       {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
+       {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
+       {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
+       {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
+       {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
+       {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
+       {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
+       {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
+       {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
+       {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
+       {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
+       {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
+       {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
+       {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
+       {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
+       {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
+       {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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 = KBUILD_MODNAME,
+       .id_table = device_table,
+       .probe = sd_probe,
+       .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c
new file mode 100644 (file)
index 0000000..fd1f8d2
--- /dev/null
@@ -0,0 +1,1493 @@
+/*
+ *             sonix sn9c102 (bayer) library
+ *
+ * Copyright (C) 2009-2011 Jean-François Moine <http://moinejf.free.fr>
+ * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
+ * Add Pas106 Stefano Mozzi (C) 2004
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* Some documentation on known sonixb registers:
+
+Reg    Use
+sn9c101 / sn9c102:
+0x10   high nibble red gain low nibble blue gain
+0x11   low nibble green gain
+sn9c103:
+0x05   red gain 0-127
+0x06   blue gain 0-127
+0x07   green gain 0-127
+all:
+0x08-0x0f i2c / 3wire registers
+0x12   hstart
+0x13   vstart
+0x15   hsize (hsize = register-value * 16)
+0x16   vsize (vsize = register-value * 16)
+0x17   bit 0 toggle compression quality (according to sn9c102 driver)
+0x18   bit 7 enables compression, bit 4-5 set image down scaling:
+       00 scale 1, 01 scale 1/2, 10, scale 1/4
+0x19   high-nibble is sensor clock divider, changes exposure on sensors which
+       use a clock generated by the bridge. Some sensors have their own clock.
+0x1c   auto_exposure area (for avg_lum) startx (startx = register-value * 32)
+0x1d   auto_exposure area (for avg_lum) starty (starty = register-value * 32)
+0x1e   auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32)
+0x1f   auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32)
+*/
+
+#define MODULE_NAME "sonixb"
+
+#include <linux/input.h>
+#include "gspca.h"
+
+MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
+MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       struct v4l2_ctrl *brightness;
+       struct v4l2_ctrl *plfreq;
+
+       atomic_t avg_lum;
+       int prev_avg_lum;
+       int exposure_knee;
+       int header_read;
+       u8 header[12]; /* Header without sof marker */
+
+       unsigned char autogain_ignore_frames;
+       unsigned char frames_to_drop;
+
+       __u8 bridge;                    /* Type of bridge */
+#define BRIDGE_101 0
+#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
+#define BRIDGE_103 1
+
+       __u8 sensor;                    /* Type of image sensor chip */
+#define SENSOR_HV7131D 0
+#define SENSOR_HV7131R 1
+#define SENSOR_OV6650 2
+#define SENSOR_OV7630 3
+#define SENSOR_PAS106 4
+#define SENSOR_PAS202 5
+#define SENSOR_TAS5110C 6
+#define SENSOR_TAS5110D 7
+#define SENSOR_TAS5130CXX 8
+       __u8 reg11;
+};
+
+typedef const __u8 sensor_init_t[8];
+
+struct sensor_data {
+       const __u8 *bridge_init;
+       sensor_init_t *sensor_init;
+       int sensor_init_size;
+       int flags;
+       __u8 sensor_addr;
+};
+
+/* sensor_data flags */
+#define F_SIF          0x01    /* sif or vga */
+
+/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
+#define MODE_RAW 0x10          /* raw bayer mode */
+#define MODE_REDUCED_SIF 0x20  /* vga mode (320x240 / 160x120) on sif cam */
+
+#define COMP 0xc7              /* 0x87 //0x07 */
+#define COMP1 0xc9             /* 0x89 //0x09 */
+
+#define MCK_INIT 0x63
+#define MCK_INIT1 0x20         /*fixme: Bayer - 0x50 for JPEG ??*/
+
+#define SYS_CLK 0x04
+
+#define SENS(bridge, sensor, _flags, _sensor_addr) \
+{ \
+       .bridge_init = bridge, \
+       .sensor_init = sensor, \
+       .sensor_init_size = sizeof(sensor), \
+       .flags = _flags, .sensor_addr = _sensor_addr \
+}
+
+/* We calculate the autogain at the end of the transfer of a frame, at this
+   moment a frame with the old settings is being captured and transmitted. So
+   if we adjust the gain or exposure we must ignore atleast the next frame for
+   the new settings to come into effect before doing any other adjustments. */
+#define AUTOGAIN_IGNORE_FRAMES 1
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2 | MODE_RAW},
+       {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 5 / 4,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+       {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 5 / 4,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 5 / 4,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+static const struct v4l2_pix_format sif_mode[] = {
+       {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
+       {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 5 / 4,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1 | MODE_REDUCED_SIF},
+       {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1 | MODE_RAW},
+       {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 5 / 4,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 5 / 4,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0 | MODE_REDUCED_SIF},
+       {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 5 / 4,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+static const __u8 initHv7131d[] = {
+       0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
+       0x00, 0x00,
+       0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
+       0x28, 0x1e, 0x60, 0x8e, 0x42,
+};
+static const __u8 hv7131d_sensor_init[][8] = {
+       {0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17},
+       {0xa0, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x17},
+       {0xa0, 0x11, 0x28, 0x00, 0x00, 0x00, 0x00, 0x17},
+       {0xa0, 0x11, 0x30, 0x30, 0x00, 0x00, 0x00, 0x17}, /* reset level */
+       {0xa0, 0x11, 0x34, 0x02, 0x00, 0x00, 0x00, 0x17}, /* pixel bias volt */
+};
+
+static const __u8 initHv7131r[] = {
+       0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
+       0x00, 0x00,
+       0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
+       0x28, 0x1e, 0x60, 0x8a, 0x20,
+};
+static const __u8 hv7131r_sensor_init[][8] = {
+       {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
+       {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
+       {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
+       {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
+       {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
+};
+static const __u8 initOv6650[] = {
+       0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
+       0x10,
+};
+static const __u8 ov6650_sensor_init[][8] = {
+       /* Bright, contrast, etc are set through SCBB interface.
+        * AVCAP on win2 do not send any data on this controls. */
+       /* Anyway, some registers appears to alter bright and constrat */
+
+       /* Reset sensor */
+       {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
+       /* Set clock register 0x11 low nibble is clock divider */
+       {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
+       /* Next some unknown stuff */
+       {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
+/*     {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
+                * THIS SET GREEN SCREEN
+                * (pixels could be innverted in decode kind of "brg",
+                * but blue wont be there. Avoid this data ... */
+       {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
+       {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
+       {0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10},
+       /* Enable rgb brightness control */
+       {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
+       /* HDG: Note windows uses the line below, which sets both register 0x60
+          and 0x61 I believe these registers of the ov6650 are identical as
+          those of the ov7630, because if this is true the windows settings
+          add a bit additional red gain and a lot additional blue gain, which
+          matches my findings that the windows settings make blue much too
+          blue and red a little too red.
+       {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
+       /* Some more unknown stuff */
+       {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
+       {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
+};
+
+static const __u8 initOv7630[] = {
+       0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
+       0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
+       0x00, 0x01, 0x01, 0x0a,                         /* r11 .. r14 */
+       0x28, 0x1e,                     /* H & V sizes     r15 .. r16 */
+       0x68, 0x8f, MCK_INIT1,                          /* r17 .. r19 */
+};
+static const __u8 ov7630_sensor_init[][8] = {
+       {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
+/*     {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10},          jfm */
+       {0xd0, 0x21, 0x12, 0x5c, 0x00, 0x80, 0x34, 0x10},       /* jfm */
+       {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
+       {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
+       {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
+       {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
+       {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
+       {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
+       {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
+       {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
+/*     {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10},        * jfm */
+       {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
+       {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
+       {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
+       {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
+       {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
+       {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
+};
+
+static const __u8 initPas106[] = {
+       0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
+       0x00, 0x00,
+       0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
+       0x16, 0x12, 0x24, COMP1, MCK_INIT1,
+};
+/* compression 0x86 mckinit1 0x2b */
+
+/* "Known" PAS106B registers:
+  0x02 clock divider
+  0x03 Variable framerate bits 4-11
+  0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !!
+       The variable framerate control must never be set lower then 300,
+       which sets the framerate at 90 / reg02, otherwise vsync is lost.
+  0x05 Shutter Time Line Offset, this can be used as an exposure control:
+       0 = use full frame time, 255 = no exposure at all
+       Note this may never be larger then "var-framerate control" / 2 - 2.
+       When var-framerate control is < 514, no exposure is reached at the max
+       allowed value for the framerate control value, rather then at 255.
+  0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but
+       only a very little bit, leave at 0xcd
+  0x07 offset sign bit (bit0 1 > negative offset)
+  0x08 offset
+  0x09 Blue Gain
+  0x0a Green1 Gain
+  0x0b Green2 Gain
+  0x0c Red Gain
+  0x0e Global gain
+  0x13 Write 1 to commit settings to sensor
+*/
+
+static const __u8 pas106_sensor_init[][8] = {
+       /* Pixel Clock Divider 6 */
+       { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
+       /* Frame Time MSB (also seen as 0x12) */
+       { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
+       /* Frame Time LSB (also seen as 0x05) */
+       { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
+       /* Shutter Time Line Offset (also seen as 0x6d) */
+       { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
+       /* Shutter Time Pixel Offset (also seen as 0xb1) */
+       { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
+       /* Black Level Subtract Sign (also seen 0x00) */
+       { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
+       /* Black Level Subtract Level (also seen 0x01) */
+       { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
+       { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
+       /* Color Gain B Pixel 5 a */
+       { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
+       /* Color Gain G1 Pixel 1 5 */
+       { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
+       /* Color Gain G2 Pixel 1 0 5 */
+       { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
+       /* Color Gain R Pixel 3 1 */
+       { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
+       /* Color GainH  Pixel */
+       { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
+       /* Global Gain */
+       { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
+       /* Contrast */
+       { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
+       /* H&V synchro polarity */
+       { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
+       /* ?default */
+       { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
+       /* DAC scale */
+       { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
+       /* ?default */
+       { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
+       /* Validate Settings */
+       { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
+};
+
+static const __u8 initPas202[] = {
+       0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
+       0x00, 0x00,
+       0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
+       0x28, 0x1e, 0x20, 0x89, 0x20,
+};
+
+/* "Known" PAS202BCB registers:
+  0x02 clock divider
+  0x04 Variable framerate bits 6-11 (*)
+  0x05 Var framerate  bits 0-5, one must leave the 2 msb's at 0 !!
+  0x07 Blue Gain
+  0x08 Green Gain
+  0x09 Red Gain
+  0x0b offset sign bit (bit0 1 > negative offset)
+  0x0c offset
+  0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too,
+       leave at 1 otherwise we get a jump in our exposure control
+  0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all
+  0x10 Master gain 0 - 31
+  0x11 write 1 to apply changes
+  (*) The variable framerate control must never be set lower then 500
+      which sets the framerate at 30 / reg02, otherwise vsync is lost.
+*/
+static const __u8 pas202_sensor_init[][8] = {
+       /* Set the clock divider to 4 -> 30 / 4 = 7.5 fps, we would like
+          to set it lower, but for some reason the bridge starts missing
+          vsync's then */
+       {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10},
+       {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
+       {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
+       {0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10},
+       {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
+       {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
+       {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
+       {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
+       {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
+       {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
+};
+
+static const __u8 initTas5110c[] = {
+       0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
+       0x00, 0x00,
+       0x00, 0x00, 0x00, 0x45, 0x09, 0x0a,
+       0x16, 0x12, 0x60, 0x86, 0x2b,
+};
+/* Same as above, except a different hstart */
+static const __u8 initTas5110d[] = {
+       0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
+       0x00, 0x00,
+       0x00, 0x00, 0x00, 0x41, 0x09, 0x0a,
+       0x16, 0x12, 0x60, 0x86, 0x2b,
+};
+/* tas5110c is 3 wire, tas5110d is 2 wire (regular i2c) */
+static const __u8 tas5110c_sensor_init[][8] = {
+       {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
+       {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
+};
+/* Known TAS5110D registers
+ * reg02: gain, bit order reversed!! 0 == max gain, 255 == min gain
+ * reg03: bit3: vflip, bit4: ~hflip, bit7: ~gainboost (~ == inverted)
+ *        Note: writing reg03 seems to only work when written together with 02
+ */
+static const __u8 tas5110d_sensor_init[][8] = {
+       {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17}, /* reset */
+};
+
+static const __u8 initTas5130[] = {
+       0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
+       0x00, 0x00,
+       0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a,
+       0x28, 0x1e, 0x60, COMP, MCK_INIT,
+};
+static const __u8 tas5130_sensor_init[][8] = {
+/*     {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
+                                       * shutter 0x47 short exposure? */
+       {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
+                                       /* shutter 0x01 long exposure */
+       {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
+};
+
+static const struct sensor_data sensor_data[] = {
+       SENS(initHv7131d, hv7131d_sensor_init, 0, 0),
+       SENS(initHv7131r, hv7131r_sensor_init, 0, 0),
+       SENS(initOv6650, ov6650_sensor_init, F_SIF, 0x60),
+       SENS(initOv7630, ov7630_sensor_init, 0, 0x21),
+       SENS(initPas106, pas106_sensor_init, F_SIF, 0),
+       SENS(initPas202, pas202_sensor_init, 0, 0),
+       SENS(initTas5110c, tas5110c_sensor_init, F_SIF, 0),
+       SENS(initTas5110d, tas5110d_sensor_init, F_SIF, 0),
+       SENS(initTas5130, tas5130_sensor_init, 0, 0),
+};
+
+/* get one byte in gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev,
+                 __u16 value)
+{
+       int res;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       res = usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       0,                      /* request */
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       value,
+                       0,                      /* index */
+                       gspca_dev->usb_buf, 1,
+                       500);
+
+       if (res < 0) {
+               dev_err(gspca_dev->v4l2_dev.dev,
+                       "Error reading register %02x: %d\n", value, res);
+               gspca_dev->usb_err = res;
+       }
+}
+
+static void reg_w(struct gspca_dev *gspca_dev,
+                 __u16 value,
+                 const __u8 *buffer,
+                 int len)
+{
+       int res;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       memcpy(gspca_dev->usb_buf, buffer, len);
+       res = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x08,                   /* request */
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       value,
+                       0,                      /* index */
+                       gspca_dev->usb_buf, len,
+                       500);
+
+       if (res < 0) {
+               dev_err(gspca_dev->v4l2_dev.dev,
+                       "Error writing register %02x: %d\n", value, res);
+               gspca_dev->usb_err = res;
+       }
+}
+
+static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
+{
+       int retry = 60;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       /* is i2c ready */
+       reg_w(gspca_dev, 0x08, buffer, 8);
+       while (retry--) {
+               if (gspca_dev->usb_err < 0)
+                       return;
+               msleep(10);
+               reg_r(gspca_dev, 0x08);
+               if (gspca_dev->usb_buf[0] & 0x04) {
+                       if (gspca_dev->usb_buf[0] & 0x08) {
+                               dev_err(gspca_dev->v4l2_dev.dev,
+                                       "i2c write error\n");
+                               gspca_dev->usb_err = -EIO;
+                       }
+                       return;
+               }
+       }
+
+       dev_err(gspca_dev->v4l2_dev.dev, "i2c write timeout\n");
+       gspca_dev->usb_err = -EIO;
+}
+
+static void i2c_w_vector(struct gspca_dev *gspca_dev,
+                       const __u8 buffer[][8], int len)
+{
+       for (;;) {
+               if (gspca_dev->usb_err < 0)
+                       return;
+               reg_w(gspca_dev, 0x08, *buffer, 8);
+               len -= 8;
+               if (len <= 0)
+                       break;
+               buffer++;
+       }
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->sensor) {
+       case  SENSOR_OV6650:
+       case  SENSOR_OV7630: {
+               __u8 i2cOV[] =
+                       {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
+
+               /* change reg 0x06 */
+               i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
+               i2cOV[3] = sd->brightness->val;
+               i2c_w(gspca_dev, i2cOV);
+               break;
+       }
+       case SENSOR_PAS106:
+       case SENSOR_PAS202: {
+               __u8 i2cpbright[] =
+                       {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16};
+               __u8 i2cpdoit[] =
+                       {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
+
+               /* PAS106 uses reg 7 and 8 instead of b and c */
+               if (sd->sensor == SENSOR_PAS106) {
+                       i2cpbright[2] = 7;
+                       i2cpdoit[2] = 0x13;
+               }
+
+               if (sd->brightness->val < 127) {
+                       /* change reg 0x0b, signreg */
+                       i2cpbright[3] = 0x01;
+                       /* set reg 0x0c, offset */
+                       i2cpbright[4] = 127 - sd->brightness->val;
+               } else
+                       i2cpbright[4] = sd->brightness->val - 127;
+
+               i2c_w(gspca_dev, i2cpbright);
+               i2c_w(gspca_dev, i2cpdoit);
+               break;
+       }
+       default:
+               break;
+       }
+}
+
+static void setgain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 gain = gspca_dev->gain->val;
+
+       switch (sd->sensor) {
+       case SENSOR_HV7131D: {
+               __u8 i2c[] =
+                       {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17};
+
+               i2c[3] = 0x3f - gain;
+               i2c[4] = 0x3f - gain;
+               i2c[5] = 0x3f - gain;
+
+               i2c_w(gspca_dev, i2c);
+               break;
+       }
+       case SENSOR_TAS5110C:
+       case SENSOR_TAS5130CXX: {
+               __u8 i2c[] =
+                       {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
+
+               i2c[4] = 255 - gain;
+               i2c_w(gspca_dev, i2c);
+               break;
+       }
+       case SENSOR_TAS5110D: {
+               __u8 i2c[] = {
+                       0xb0, 0x61, 0x02, 0x00, 0x10, 0x00, 0x00, 0x17 };
+               gain = 255 - gain;
+               /* The bits in the register are the wrong way around!! */
+               i2c[3] |= (gain & 0x80) >> 7;
+               i2c[3] |= (gain & 0x40) >> 5;
+               i2c[3] |= (gain & 0x20) >> 3;
+               i2c[3] |= (gain & 0x10) >> 1;
+               i2c[3] |= (gain & 0x08) << 1;
+               i2c[3] |= (gain & 0x04) << 3;
+               i2c[3] |= (gain & 0x02) << 5;
+               i2c[3] |= (gain & 0x01) << 7;
+               i2c_w(gspca_dev, i2c);
+               break;
+       }
+       case SENSOR_OV6650:
+       case SENSOR_OV7630: {
+               __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
+
+               /*
+                * The ov7630's gain is weird, at 32 the gain drops to the
+                * same level as at 16, so skip 32-47 (of the 0-63 scale).
+                */
+               if (sd->sensor == SENSOR_OV7630 && gain >= 32)
+                       gain += 16;
+
+               i2c[1] = sensor_data[sd->sensor].sensor_addr;
+               i2c[3] = gain;
+               i2c_w(gspca_dev, i2c);
+               break;
+       }
+       case SENSOR_PAS106:
+       case SENSOR_PAS202: {
+               __u8 i2cpgain[] =
+                       {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15};
+               __u8 i2cpcolorgain[] =
+                       {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15};
+               __u8 i2cpdoit[] =
+                       {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
+
+               /* PAS106 uses different regs (and has split green gains) */
+               if (sd->sensor == SENSOR_PAS106) {
+                       i2cpgain[2] = 0x0e;
+                       i2cpcolorgain[0] = 0xd0;
+                       i2cpcolorgain[2] = 0x09;
+                       i2cpdoit[2] = 0x13;
+               }
+
+               i2cpgain[3] = gain;
+               i2cpcolorgain[3] = gain >> 1;
+               i2cpcolorgain[4] = gain >> 1;
+               i2cpcolorgain[5] = gain >> 1;
+               i2cpcolorgain[6] = gain >> 1;
+
+               i2c_w(gspca_dev, i2cpgain);
+               i2c_w(gspca_dev, i2cpcolorgain);
+               i2c_w(gspca_dev, i2cpdoit);
+               break;
+       }
+       default:
+               if (sd->bridge == BRIDGE_103) {
+                       u8 buf[3] = { gain, gain, gain }; /* R, G, B */
+                       reg_w(gspca_dev, 0x05, buf, 3);
+               } else {
+                       u8 buf[2];
+                       buf[0] = gain << 4 | gain; /* Red and blue */
+                       buf[1] = gain; /* Green */
+                       reg_w(gspca_dev, 0x10, buf, 2);
+               }
+       }
+}
+
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->sensor) {
+       case SENSOR_HV7131D: {
+               /* Note the datasheet wrongly says line mode exposure uses reg
+                  0x26 and 0x27, testing has shown 0x25 + 0x26 */
+               __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17};
+               u16 reg = gspca_dev->exposure->val;
+
+               i2c[3] = reg >> 8;
+               i2c[4] = reg & 0xff;
+               i2c_w(gspca_dev, i2c);
+               break;
+       }
+       case SENSOR_TAS5110C:
+       case SENSOR_TAS5110D: {
+               /* register 19's high nibble contains the sn9c10x clock divider
+                  The high nibble configures the no fps according to the
+                  formula: 60 / high_nibble. With a maximum of 30 fps */
+               u8 reg = gspca_dev->exposure->val;
+
+               reg = (reg << 4) | 0x0b;
+               reg_w(gspca_dev, 0x19, &reg, 1);
+               break;
+       }
+       case SENSOR_OV6650:
+       case SENSOR_OV7630: {
+               /* The ov6650 / ov7630 have 2 registers which both influence
+                  exposure, register 11, whose low nibble sets the nr off fps
+                  according to: fps = 30 / (low_nibble + 1)
+
+                  The fps configures the maximum exposure setting, but it is
+                  possible to use less exposure then what the fps maximum
+                  allows by setting register 10. register 10 configures the
+                  actual exposure as quotient of the full exposure, with 0
+                  being no exposure at all (not very useful) and reg10_max
+                  being max exposure possible at that framerate.
+
+                  The code maps our 0 - 510 ms exposure ctrl to these 2
+                  registers, trying to keep fps as high as possible.
+               */
+               __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
+               int reg10, reg11, reg10_max;
+
+               /* ov6645 datasheet says reg10_max is 9a, but that uses
+                  tline * 2 * reg10 as formula for calculating texpo, the
+                  ov6650 probably uses the same formula as the 7730 which uses
+                  tline * 4 * reg10, which explains why the reg10max we've
+                  found experimentally for the ov6650 is exactly half that of
+                  the ov6645. The ov7630 datasheet says the max is 0x41. */
+               if (sd->sensor == SENSOR_OV6650) {
+                       reg10_max = 0x4d;
+                       i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
+               } else
+                       reg10_max = 0x41;
+
+               reg11 = (15 * gspca_dev->exposure->val + 999) / 1000;
+               if (reg11 < 1)
+                       reg11 = 1;
+               else if (reg11 > 16)
+                       reg11 = 16;
+
+               /* In 640x480, if the reg11 has less than 4, the image is
+                  unstable (the bridge goes into a higher compression mode
+                  which we have not reverse engineered yet). */
+               if (gspca_dev->width == 640 && reg11 < 4)
+                       reg11 = 4;
+
+               /* frame exposure time in ms = 1000 * reg11 / 30    ->
+               reg10 = (gspca_dev->exposure->val / 2) * reg10_max
+                               / (1000 * reg11 / 30) */
+               reg10 = (gspca_dev->exposure->val * 15 * reg10_max)
+                               / (1000 * reg11);
+
+               /* Don't allow this to get below 10 when using autogain, the
+                  steps become very large (relatively) when below 10 causing
+                  the image to oscilate from much too dark, to much too bright
+                  and back again. */
+               if (gspca_dev->autogain->val && reg10 < 10)
+                       reg10 = 10;
+               else if (reg10 > reg10_max)
+                       reg10 = reg10_max;
+
+               /* Write reg 10 and reg11 low nibble */
+               i2c[1] = sensor_data[sd->sensor].sensor_addr;
+               i2c[3] = reg10;
+               i2c[4] |= reg11 - 1;
+
+               /* If register 11 didn't change, don't change it */
+               if (sd->reg11 == reg11)
+                       i2c[0] = 0xa0;
+
+               i2c_w(gspca_dev, i2c);
+               if (gspca_dev->usb_err == 0)
+                       sd->reg11 = reg11;
+               break;
+       }
+       case SENSOR_PAS202: {
+               __u8 i2cpframerate[] =
+                       {0xb0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x16};
+               __u8 i2cpexpo[] =
+                       {0xa0, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x16};
+               const __u8 i2cpdoit[] =
+                       {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
+               int framerate_ctrl;
+
+               /* The exposure knee for the autogain algorithm is 200
+                  (100 ms / 10 fps on other sensors), for values below this
+                  use the control for setting the partial frame expose time,
+                  above that use variable framerate. This way we run at max
+                  framerate (640x480@7.5 fps, 320x240@10fps) until the knee
+                  is reached. Using the variable framerate control above 200
+                  is better then playing around with both clockdiv + partial
+                  frame exposure times (like we are doing with the ov chips),
+                  as that sometimes leads to jumps in the exposure control,
+                  which are bad for auto exposure. */
+               if (gspca_dev->exposure->val < 200) {
+                       i2cpexpo[3] = 255 - (gspca_dev->exposure->val * 255)
+                                               / 200;
+                       framerate_ctrl = 500;
+               } else {
+                       /* The PAS202's exposure control goes from 0 - 4095,
+                          but anything below 500 causes vsync issues, so scale
+                          our 200-1023 to 500-4095 */
+                       framerate_ctrl = (gspca_dev->exposure->val - 200)
+                                                       * 1000 / 229 +  500;
+               }
+
+               i2cpframerate[3] = framerate_ctrl >> 6;
+               i2cpframerate[4] = framerate_ctrl & 0x3f;
+               i2c_w(gspca_dev, i2cpframerate);
+               i2c_w(gspca_dev, i2cpexpo);
+               i2c_w(gspca_dev, i2cpdoit);
+               break;
+       }
+       case SENSOR_PAS106: {
+               __u8 i2cpframerate[] =
+                       {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14};
+               __u8 i2cpexpo[] =
+                       {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14};
+               const __u8 i2cpdoit[] =
+                       {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14};
+               int framerate_ctrl;
+
+               /* For values below 150 use partial frame exposure, above
+                  that use framerate ctrl */
+               if (gspca_dev->exposure->val < 150) {
+                       i2cpexpo[3] = 150 - gspca_dev->exposure->val;
+                       framerate_ctrl = 300;
+               } else {
+                       /* The PAS106's exposure control goes from 0 - 4095,
+                          but anything below 300 causes vsync issues, so scale
+                          our 150-1023 to 300-4095 */
+                       framerate_ctrl = (gspca_dev->exposure->val - 150)
+                                               * 1000 / 230 + 300;
+               }
+
+               i2cpframerate[3] = framerate_ctrl >> 4;
+               i2cpframerate[4] = framerate_ctrl & 0x0f;
+               i2c_w(gspca_dev, i2cpframerate);
+               i2c_w(gspca_dev, i2cpexpo);
+               i2c_w(gspca_dev, i2cpdoit);
+               break;
+       }
+       default:
+               break;
+       }
+}
+
+static void setfreq(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630) {
+               /* Framerate adjust register for artificial light 50 hz flicker
+                  compensation, for the ov6650 this is identical to ov6630
+                  0x2b register, see ov6630 datasheet.
+                  0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
+               __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
+               switch (sd->plfreq->val) {
+               default:
+/*             case 0:                  * no filter*/
+/*             case 2:                  * 60 hz */
+                       i2c[3] = 0;
+                       break;
+               case 1:                 /* 50 hz */
+                       i2c[3] = (sd->sensor == SENSOR_OV6650)
+                                       ? 0x4f : 0x8a;
+                       break;
+               }
+               i2c[1] = sensor_data[sd->sensor].sensor_addr;
+               i2c_w(gspca_dev, i2c);
+       }
+}
+
+static void do_autogain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int deadzone, desired_avg_lum, avg_lum;
+
+       avg_lum = atomic_read(&sd->avg_lum);
+       if (avg_lum == -1)
+               return;
+
+       if (sd->autogain_ignore_frames > 0) {
+               sd->autogain_ignore_frames--;
+               return;
+       }
+
+       /* SIF / VGA sensors have a different autoexposure area and thus
+          different avg_lum values for the same picture brightness */
+       if (sensor_data[sd->sensor].flags & F_SIF) {
+               deadzone = 500;
+               /* SIF sensors tend to overexpose, so keep this small */
+               desired_avg_lum = 5000;
+       } else {
+               deadzone = 1500;
+               desired_avg_lum = 13000;
+       }
+
+       if (sd->brightness)
+               desired_avg_lum = sd->brightness->val * desired_avg_lum / 127;
+
+       if (gspca_dev->exposure->maximum < 500) {
+               if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
+                               desired_avg_lum, deadzone))
+                       sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
+       } else {
+               int gain_knee = gspca_dev->gain->maximum * 9 / 10;
+               if (gspca_expo_autogain(gspca_dev, avg_lum, desired_avg_lum,
+                               deadzone, gain_knee, sd->exposure_knee))
+                       sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
+       }
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+
+       reg_r(gspca_dev, 0x00);
+       if (gspca_dev->usb_buf[0] != 0x10)
+               return -ENODEV;
+
+       /* copy the webcam info from the device id */
+       sd->sensor = id->driver_info >> 8;
+       sd->bridge = id->driver_info & 0xff;
+
+       cam = &gspca_dev->cam;
+       if (!(sensor_data[sd->sensor].flags & F_SIF)) {
+               cam->cam_mode = vga_mode;
+               cam->nmodes = ARRAY_SIZE(vga_mode);
+       } else {
+               cam->cam_mode = sif_mode;
+               cam->nmodes = ARRAY_SIZE(sif_mode);
+       }
+       cam->npkt = 36;                 /* 36 packets per ISOC message */
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       const __u8 stop = 0x09; /* Disable stream turn of LED */
+
+       reg_w(gspca_dev, 0x01, &stop, 1);
+
+       return gspca_dev->usb_err;
+}
+
+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 (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
+               /* when switching to autogain set defaults to make sure
+                  we are on a valid point of the autogain gain /
+                  exposure knee graph, and give this change time to
+                  take effect before doing autogain. */
+               gspca_dev->gain->val = gspca_dev->gain->default_value;
+               gspca_dev->exposure->val = gspca_dev->exposure->default_value;
+               sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
+       }
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setbrightness(gspca_dev);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
+                       setexposure(gspca_dev);
+               if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
+                       setgain(gspca_dev);
+               break;
+       case V4L2_CID_POWER_LINE_FREQUENCY:
+               setfreq(gspca_dev);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return gspca_dev->usb_err;
+}
+
+static const struct v4l2_ctrl_ops sd_ctrl_ops = {
+       .s_ctrl = sd_s_ctrl,
+};
+
+/* this function is called at probe time */
+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, 5);
+
+       if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630 ||
+           sd->sensor == SENSOR_PAS106 || sd->sensor == SENSOR_PAS202)
+               sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
+
+       /* Gain range is sensor dependent */
+       switch (sd->sensor) {
+       case SENSOR_OV6650:
+       case SENSOR_PAS106:
+       case SENSOR_PAS202:
+               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_GAIN, 0, 31, 1, 15);
+               break;
+       case SENSOR_OV7630:
+               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_GAIN, 0, 47, 1, 31);
+               break;
+       case SENSOR_HV7131D:
+               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_GAIN, 0, 63, 1, 31);
+               break;
+       case SENSOR_TAS5110C:
+       case SENSOR_TAS5110D:
+       case SENSOR_TAS5130CXX:
+               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_GAIN, 0, 255, 1, 127);
+               break;
+       default:
+               if (sd->bridge == BRIDGE_103) {
+                       gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                               V4L2_CID_GAIN, 0, 127, 1, 63);
+               } else {
+                       gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                               V4L2_CID_GAIN, 0, 15, 1, 7);
+               }
+       }
+
+       /* Exposure range is sensor dependent, and not all have exposure */
+       switch (sd->sensor) {
+       case SENSOR_HV7131D:
+               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_EXPOSURE, 0, 8191, 1, 482);
+               sd->exposure_knee = 964;
+               break;
+       case SENSOR_OV6650:
+       case SENSOR_OV7630:
+       case SENSOR_PAS106:
+       case SENSOR_PAS202:
+               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_EXPOSURE, 0, 1023, 1, 66);
+               sd->exposure_knee = 200;
+               break;
+       case SENSOR_TAS5110C:
+       case SENSOR_TAS5110D:
+               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_EXPOSURE, 2, 15, 1, 2);
+               break;
+       }
+
+       if (gspca_dev->exposure) {
+               gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                               V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+       }
+
+       if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630)
+               sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
+                       V4L2_CID_POWER_LINE_FREQUENCY,
+                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
+                       V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+
+       if (gspca_dev->autogain)
+               v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
+
+       return 0;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam = &gspca_dev->cam;
+       int i, mode;
+       __u8 regs[0x31];
+
+       mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
+       /* Copy registers 0x01 - 0x19 from the template */
+       memcpy(&regs[0x01], sensor_data[sd->sensor].bridge_init, 0x19);
+       /* Set the mode */
+       regs[0x18] |= mode << 4;
+
+       /* Set bridge gain to 1.0 */
+       if (sd->bridge == BRIDGE_103) {
+               regs[0x05] = 0x20; /* Red */
+               regs[0x06] = 0x20; /* Green */
+               regs[0x07] = 0x20; /* Blue */
+       } else {
+               regs[0x10] = 0x00; /* Red and blue */
+               regs[0x11] = 0x00; /* Green */
+       }
+
+       /* Setup pixel numbers and auto exposure window */
+       if (sensor_data[sd->sensor].flags & F_SIF) {
+               regs[0x1a] = 0x14; /* HO_SIZE 640, makes no sense */
+               regs[0x1b] = 0x0a; /* VO_SIZE 320, makes no sense */
+               regs[0x1c] = 0x02; /* AE H-start 64 */
+               regs[0x1d] = 0x02; /* AE V-start 64 */
+               regs[0x1e] = 0x09; /* AE H-end 288 */
+               regs[0x1f] = 0x07; /* AE V-end 224 */
+       } else {
+               regs[0x1a] = 0x1d; /* HO_SIZE 960, makes no sense */
+               regs[0x1b] = 0x10; /* VO_SIZE 512, makes no sense */
+               regs[0x1c] = 0x05; /* AE H-start 160 */
+               regs[0x1d] = 0x03; /* AE V-start 96 */
+               regs[0x1e] = 0x0f; /* AE H-end 480 */
+               regs[0x1f] = 0x0c; /* AE V-end 384 */
+       }
+
+       /* Setup the gamma table (only used with the sn9c103 bridge) */
+       for (i = 0; i < 16; i++)
+               regs[0x20 + i] = i * 16;
+       regs[0x20 + i] = 255;
+
+       /* Special cases where some regs depend on mode or bridge */
+       switch (sd->sensor) {
+       case SENSOR_TAS5130CXX:
+               /* FIXME / TESTME
+                  probably not mode specific at all most likely the upper
+                  nibble of 0x19 is exposure (clock divider) just as with
+                  the tas5110, we need someone to test this. */
+               regs[0x19] = mode ? 0x23 : 0x43;
+               break;
+       case SENSOR_OV7630:
+               /* FIXME / TESTME for some reason with the 101/102 bridge the
+                  clock is set to 12 Mhz (reg1 == 0x04), rather then 24.
+                  Also the hstart needs to go from 1 to 2 when using a 103,
+                  which is likely related. This does not seem right. */
+               if (sd->bridge == BRIDGE_103) {
+                       regs[0x01] = 0x44; /* Select 24 Mhz clock */
+                       regs[0x12] = 0x02; /* Set hstart to 2 */
+               }
+       }
+       /* Disable compression when the raw bayer format has been selected */
+       if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
+               regs[0x18] &= ~0x80;
+
+       /* Vga mode emulation on SIF sensor? */
+       if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
+               regs[0x12] += 16;       /* hstart adjust */
+               regs[0x13] += 24;       /* vstart adjust */
+               regs[0x15]  = 320 / 16; /* hsize */
+               regs[0x16]  = 240 / 16; /* vsize */
+       }
+
+       /* reg 0x01 bit 2 video transfert on */
+       reg_w(gspca_dev, 0x01, &regs[0x01], 1);
+       /* reg 0x17 SensorClk enable inv Clk 0x60 */
+       reg_w(gspca_dev, 0x17, &regs[0x17], 1);
+       /* Set the registers from the template */
+       reg_w(gspca_dev, 0x01, &regs[0x01],
+             (sd->bridge == BRIDGE_103) ? 0x30 : 0x1f);
+
+       /* Init the sensor */
+       i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
+                       sensor_data[sd->sensor].sensor_init_size);
+
+       /* Mode / bridge specific sensor setup */
+       switch (sd->sensor) {
+       case SENSOR_PAS202: {
+               const __u8 i2cpclockdiv[] =
+                       {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10};
+               /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */
+               if (mode)
+                       i2c_w(gspca_dev, i2cpclockdiv);
+               break;
+           }
+       case SENSOR_OV7630:
+               /* FIXME / TESTME We should be able to handle this identical
+                  for the 101/102 and the 103 case */
+               if (sd->bridge == BRIDGE_103) {
+                       const __u8 i2c[] = { 0xa0, 0x21, 0x13,
+                                            0x80, 0x00, 0x00, 0x00, 0x10 };
+                       i2c_w(gspca_dev, i2c);
+               }
+               break;
+       }
+       /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
+       reg_w(gspca_dev, 0x15, &regs[0x15], 2);
+       /* compression register */
+       reg_w(gspca_dev, 0x18, &regs[0x18], 1);
+       /* H_start */
+       reg_w(gspca_dev, 0x12, &regs[0x12], 1);
+       /* V_START */
+       reg_w(gspca_dev, 0x13, &regs[0x13], 1);
+       /* reset 0x17 SensorClk enable inv Clk 0x60 */
+                               /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
+       reg_w(gspca_dev, 0x17, &regs[0x17], 1);
+       /*MCKSIZE ->3 */        /*fixme: not ov7630*/
+       reg_w(gspca_dev, 0x19, &regs[0x19], 1);
+       /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
+       reg_w(gspca_dev, 0x1c, &regs[0x1c], 4);
+       /* Enable video transfert */
+       reg_w(gspca_dev, 0x01, &regs[0x01], 1);
+       /* Compression */
+       reg_w(gspca_dev, 0x18, &regs[0x18], 2);
+       msleep(20);
+
+       sd->reg11 = -1;
+
+       setgain(gspca_dev);
+       setbrightness(gspca_dev);
+       setexposure(gspca_dev);
+       setfreq(gspca_dev);
+
+       sd->frames_to_drop = 0;
+       sd->autogain_ignore_frames = 0;
+       gspca_dev->exp_too_high_cnt = 0;
+       gspca_dev->exp_too_low_cnt = 0;
+       atomic_set(&sd->avg_lum, -1);
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       sd_init(gspca_dev);
+}
+
+static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12;
+
+       /* frames start with:
+        *      ff ff 00 c4 c4 96       synchro
+        *      00              (unknown)
+        *      xx              (frame sequence / size / compression)
+        *      (xx)            (idem - extra byte for sn9c103)
+        *      ll mm           brightness sum inside auto exposure
+        *      ll mm           brightness sum outside auto exposure
+        *      (xx xx xx xx xx)        audio values for snc103
+        */
+       for (i = 0; i < len; i++) {
+               switch (sd->header_read) {
+               case 0:
+                       if (data[i] == 0xff)
+                               sd->header_read++;
+                       break;
+               case 1:
+                       if (data[i] == 0xff)
+                               sd->header_read++;
+                       else
+                               sd->header_read = 0;
+                       break;
+               case 2:
+                       if (data[i] == 0x00)
+                               sd->header_read++;
+                       else if (data[i] != 0xff)
+                               sd->header_read = 0;
+                       break;
+               case 3:
+                       if (data[i] == 0xc4)
+                               sd->header_read++;
+                       else if (data[i] == 0xff)
+                               sd->header_read = 1;
+                       else
+                               sd->header_read = 0;
+                       break;
+               case 4:
+                       if (data[i] == 0xc4)
+                               sd->header_read++;
+                       else if (data[i] == 0xff)
+                               sd->header_read = 1;
+                       else
+                               sd->header_read = 0;
+                       break;
+               case 5:
+                       if (data[i] == 0x96)
+                               sd->header_read++;
+                       else if (data[i] == 0xff)
+                               sd->header_read = 1;
+                       else
+                               sd->header_read = 0;
+                       break;
+               default:
+                       sd->header[sd->header_read - 6] = data[i];
+                       sd->header_read++;
+                       if (sd->header_read == header_size) {
+                               sd->header_read = 0;
+                               return data + i + 1;
+                       }
+               }
+       }
+       return NULL;
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,                       /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0;
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam = &gspca_dev->cam;
+       u8 *sof;
+
+       sof = find_sof(gspca_dev, data, len);
+       if (sof) {
+               if (sd->bridge == BRIDGE_103) {
+                       fr_h_sz = 18;
+                       lum_offset = 3;
+               } else {
+                       fr_h_sz = 12;
+                       lum_offset = 2;
+               }
+
+               len_after_sof = len - (sof - data);
+               len = (sof - data) - fr_h_sz;
+               if (len < 0)
+                       len = 0;
+       }
+
+       if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
+               /* In raw mode we sometimes get some garbage after the frame
+                  ignore this */
+               int used;
+               int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
+
+               used = gspca_dev->image_len;
+               if (used + len > size)
+                       len = size - used;
+       }
+
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+
+       if (sof) {
+               int  lum = sd->header[lum_offset] +
+                         (sd->header[lum_offset + 1] << 8);
+
+               /* When exposure changes midway a frame we
+                  get a lum of 0 in this case drop 2 frames
+                  as the frames directly after an exposure
+                  change have an unstable image. Sometimes lum
+                  *really* is 0 (cam used in low light with
+                  low exposure setting), so do not drop frames
+                  if the previous lum was 0 too. */
+               if (lum == 0 && sd->prev_avg_lum != 0) {
+                       lum = -1;
+                       sd->frames_to_drop = 2;
+                       sd->prev_avg_lum = 0;
+               } else
+                       sd->prev_avg_lum = lum;
+               atomic_set(&sd->avg_lum, lum);
+
+               if (sd->frames_to_drop)
+                       sd->frames_to_drop--;
+               else
+                       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+
+               gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof);
+       }
+}
+
+static int sd_querymenu(struct gspca_dev *gspca_dev,
+                       struct v4l2_querymenu *menu)
+{
+       switch (menu->id) {
+       case V4L2_CID_POWER_LINE_FREQUENCY:
+               switch (menu->index) {
+               case 0:         /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
+                       strcpy((char *) menu->name, "NoFliker");
+                       return 0;
+               case 1:         /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
+                       strcpy((char *) menu->name, "50 Hz");
+                       return 0;
+               case 2:         /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
+                       strcpy((char *) menu->name, "60 Hz");
+                       return 0;
+               }
+               break;
+       }
+       return -EINVAL;
+}
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,               /* interrupt packet data */
+                       int len)                /* interrupt packet length */
+{
+       int ret = -EINVAL;
+
+       if (len == 1 && data[0] == 1) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
+               input_sync(gspca_dev->input_dev);
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+               input_sync(gspca_dev->input_dev);
+               ret = 0;
+       }
+
+       return ret;
+}
+#endif
+
+/* 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,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+       .querymenu = sd_querymenu,
+       .dq_callback = do_autogain,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .int_pkt_scan = sd_int_pkt_scan,
+#endif
+};
+
+/* -- module initialisation -- */
+#define SB(sensor, bridge) \
+       .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
+
+
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */
+       {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */
+       {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */
+       {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
+       {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
+       {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
+       {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
+#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
+       {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
+       {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
+#endif
+       {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
+       {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
+       {USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)},
+       /* {USB_DEVICE(0x0c45, 0x602b), SB(MI0343, 102)}, */
+       {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
+       {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
+       {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
+       /* {USB_DEVICE(0x0c45, 0x6030), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */
+       /* {USB_DEVICE(0x0c45, 0x6082), SB(MI03XX, 103)}, */ /* MI0343 MI0360 */
+       {USB_DEVICE(0x0c45, 0x6083), SB(HV7131D, 103)},
+       {USB_DEVICE(0x0c45, 0x608c), SB(HV7131R, 103)},
+       /* {USB_DEVICE(0x0c45, 0x608e), SB(CISVF10, 103)}, */
+       {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
+       {USB_DEVICE(0x0c45, 0x60a8), SB(PAS106, 103)},
+       {USB_DEVICE(0x0c45, 0x60aa), SB(TAS5130CXX, 103)},
+       {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
+       {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/sonixj.c b/drivers/media/usb/gspca/sonixj.c
new file mode 100644 (file)
index 0000000..150b2df
--- /dev/null
@@ -0,0 +1,3206 @@
+/*
+ * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver
+ *
+ * Copyright (C) 2009-2011 Jean-François Moine <http://moinejf.free.fr>
+ * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "sonixj"
+
+#include <linux/input.h>
+#include "gspca.h"
+#include "jpeg.h"
+
+MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
+MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* controls */
+enum e_ctrl {
+       BRIGHTNESS,
+       CONTRAST,
+       COLORS,
+       BLUE,
+       RED,
+       GAMMA,
+       EXPOSURE,
+       AUTOGAIN,
+       GAIN,
+       HFLIP,
+       VFLIP,
+       SHARPNESS,
+       ILLUM,
+       FREQ,
+       NCTRLS          /* number of controls */
+};
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       struct gspca_ctrl ctrls[NCTRLS];
+
+       atomic_t avg_lum;
+       u32 exposure;
+
+       struct work_struct work;
+       struct workqueue_struct *work_thread;
+
+       u32 pktsz;                      /* (used by pkt_scan) */
+       u16 npkt;
+       s8 nchg;
+       s8 short_mark;
+
+       u8 quality;                     /* image quality */
+#define QUALITY_MIN 25
+#define QUALITY_MAX 90
+#define QUALITY_DEF 70
+
+       u8 reg01;
+       u8 reg17;
+       u8 reg18;
+       u8 flags;
+
+       s8 ag_cnt;
+#define AG_CNT_START 13
+
+       u8 bridge;
+#define BRIDGE_SN9C102P 0
+#define BRIDGE_SN9C105 1
+#define BRIDGE_SN9C110 2
+#define BRIDGE_SN9C120 3
+       u8 sensor;                      /* Type of image sensor chip */
+       u8 i2c_addr;
+
+       u8 jpeg_hdr[JPEG_HDR_SZ];
+};
+enum sensors {
+       SENSOR_ADCM1700,
+       SENSOR_GC0307,
+       SENSOR_HV7131R,
+       SENSOR_MI0360,
+       SENSOR_MI0360B,
+       SENSOR_MO4000,
+       SENSOR_MT9V111,
+       SENSOR_OM6802,
+       SENSOR_OV7630,
+       SENSOR_OV7648,
+       SENSOR_OV7660,
+       SENSOR_PO1030,
+       SENSOR_PO2030N,
+       SENSOR_SOI768,
+       SENSOR_SP80708,
+};
+
+static void qual_upd(struct work_struct *work);
+
+/* device flags */
+#define F_PDN_INV      0x01    /* inverse pin S_PWR_DN / sn_xxx tables */
+#define F_ILLUM                0x02    /* presence of illuminator */
+
+/* sn9c1xx definitions */
+/* register 0x01 */
+#define S_PWR_DN       0x01    /* sensor power down */
+#define S_PDN_INV      0x02    /* inverse pin S_PWR_DN */
+#define V_TX_EN                0x04    /* video transfer enable */
+#define LED            0x08    /* output to pin LED */
+#define SCL_SEL_OD     0x20    /* open-drain mode */
+#define SYS_SEL_48M    0x40    /* system clock 0: 24MHz, 1: 48MHz */
+/* register 0x17 */
+#define MCK_SIZE_MASK  0x1f    /* sensor master clock */
+#define SEN_CLK_EN     0x20    /* enable sensor clock */
+#define DEF_EN         0x80    /* defect pixel by 0: soft, 1: hard */
+
+/* V4L2 controls supported by the driver */
+static void setbrightness(struct gspca_dev *gspca_dev);
+static void setcontrast(struct gspca_dev *gspca_dev);
+static void setcolors(struct gspca_dev *gspca_dev);
+static void setredblue(struct gspca_dev *gspca_dev);
+static void setgamma(struct gspca_dev *gspca_dev);
+static void setexposure(struct gspca_dev *gspca_dev);
+static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
+static void setgain(struct gspca_dev *gspca_dev);
+static void sethvflip(struct gspca_dev *gspca_dev);
+static void setsharpness(struct gspca_dev *gspca_dev);
+static void setillum(struct gspca_dev *gspca_dev);
+static void setfreq(struct gspca_dev *gspca_dev);
+
+static const struct ctrl sd_ctrls[NCTRLS] = {
+[BRIGHTNESS] = {
+           {
+               .id      = V4L2_CID_BRIGHTNESS,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Brightness",
+               .minimum = 0,
+               .maximum = 0xff,
+               .step    = 1,
+               .default_value = 0x80,
+           },
+           .set_control = setbrightness
+       },
+[CONTRAST] = {
+           {
+               .id      = V4L2_CID_CONTRAST,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Contrast",
+               .minimum = 0,
+#define CONTRAST_MAX 127
+               .maximum = CONTRAST_MAX,
+               .step    = 1,
+               .default_value = 20,
+           },
+           .set_control = setcontrast
+       },
+[COLORS] = {
+           {
+               .id      = V4L2_CID_SATURATION,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Saturation",
+               .minimum = 0,
+               .maximum = 40,
+               .step    = 1,
+#define COLORS_DEF 25
+               .default_value = COLORS_DEF,
+           },
+           .set_control = setcolors
+       },
+[BLUE] = {
+           {
+               .id      = V4L2_CID_BLUE_BALANCE,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Blue Balance",
+               .minimum = 24,
+               .maximum = 40,
+               .step    = 1,
+               .default_value = 32,
+           },
+           .set_control = setredblue
+       },
+[RED] = {
+           {
+               .id      = V4L2_CID_RED_BALANCE,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Red Balance",
+               .minimum = 24,
+               .maximum = 40,
+               .step    = 1,
+               .default_value = 32,
+           },
+           .set_control = setredblue
+       },
+[GAMMA] = {
+           {
+               .id      = V4L2_CID_GAMMA,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Gamma",
+               .minimum = 0,
+               .maximum = 40,
+               .step    = 1,
+#define GAMMA_DEF 20
+               .default_value = GAMMA_DEF,
+           },
+           .set_control = setgamma
+       },
+[EXPOSURE] = {
+           {
+               .id      = V4L2_CID_EXPOSURE,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Exposure",
+               .minimum = 500,
+               .maximum = 1500,
+               .step    = 1,
+               .default_value = 1024
+           },
+           .set_control = setexposure
+       },
+[AUTOGAIN] = {
+           {
+               .id      = V4L2_CID_AUTOGAIN,
+               .type    = V4L2_CTRL_TYPE_BOOLEAN,
+               .name    = "Auto Gain",
+               .minimum = 0,
+               .maximum = 1,
+               .step    = 1,
+               .default_value = 1
+           },
+           .set = sd_setautogain,
+       },
+[GAIN] = {
+           {
+               .id      = V4L2_CID_GAIN,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Gain",
+               .minimum = 4,
+               .maximum = 49,
+               .step    = 1,
+               .default_value = 15
+           },
+           .set_control = setgain
+       },
+[HFLIP] = {
+           {
+               .id      = V4L2_CID_HFLIP,
+               .type    = V4L2_CTRL_TYPE_BOOLEAN,
+               .name    = "Mirror",
+               .minimum = 0,
+               .maximum = 1,
+               .step    = 1,
+               .default_value = 0,
+           },
+           .set_control = sethvflip
+       },
+[VFLIP] = {
+           {
+               .id      = V4L2_CID_VFLIP,
+               .type    = V4L2_CTRL_TYPE_BOOLEAN,
+               .name    = "Vflip",
+               .minimum = 0,
+               .maximum = 1,
+               .step    = 1,
+               .default_value = 0,
+           },
+           .set_control = sethvflip
+       },
+[SHARPNESS] = {
+           {
+               .id      = V4L2_CID_SHARPNESS,
+               .type    = V4L2_CTRL_TYPE_INTEGER,
+               .name    = "Sharpness",
+               .minimum = 0,
+               .maximum = 255,
+               .step    = 1,
+               .default_value = 90,
+           },
+           .set_control = setsharpness
+       },
+[ILLUM] = {
+           {
+               .id      = V4L2_CID_ILLUMINATORS_1,
+               .type    = V4L2_CTRL_TYPE_BOOLEAN,
+               .name    = "Illuminator / infrared",
+               .minimum = 0,
+               .maximum = 1,
+               .step    = 1,
+               .default_value = 0,
+           },
+           .set_control = setillum
+       },
+/* ov7630/ov7648/ov7660 only */
+[FREQ] = {
+           {
+               .id      = V4L2_CID_POWER_LINE_FREQUENCY,
+               .type    = V4L2_CTRL_TYPE_MENU,
+               .name    = "Light frequency filter",
+               .minimum = 0,
+               .maximum = 2,   /* 0: 0, 1: 50Hz, 2:60Hz */
+               .step    = 1,
+               .default_value = 1,
+           },
+           .set_control = setfreq
+       },
+};
+
+/* table of the disabled controls */
+static const __u32 ctrl_dis[] = {
+[SENSOR_ADCM1700] =    (1 << EXPOSURE) |
+                       (1 << AUTOGAIN) |
+                       (1 << GAIN) |
+                       (1 << HFLIP) |
+                       (1 << VFLIP) |
+                       (1 << FREQ),
+
+[SENSOR_GC0307] =      (1 << EXPOSURE) |
+                       (1 << GAIN) |
+                       (1 << HFLIP) |
+                       (1 << VFLIP) |
+                       (1 << FREQ),
+
+[SENSOR_HV7131R] =     (1 << EXPOSURE) |
+                       (1 << GAIN) |
+                       (1 << HFLIP) |
+                       (1 << FREQ),
+
+[SENSOR_MI0360] =      (1 << EXPOSURE) |
+                       (1 << GAIN) |
+                       (1 << HFLIP) |
+                       (1 << VFLIP) |
+                       (1 << FREQ),
+
+[SENSOR_MI0360B] =     (1 << EXPOSURE) |
+                       (1 << GAIN) |
+                       (1 << HFLIP) |
+                       (1 << VFLIP) |
+                       (1 << FREQ),
+
+[SENSOR_MO4000] =      (1 << EXPOSURE) |
+                       (1 << GAIN) |
+                       (1 << HFLIP) |
+                       (1 << VFLIP) |
+                       (1 << FREQ),
+
+[SENSOR_MT9V111] =     (1 << EXPOSURE) |
+                       (1 << GAIN) |
+                       (1 << HFLIP) |
+                       (1 << VFLIP) |
+                       (1 << FREQ),
+
+[SENSOR_OM6802] =      (1 << EXPOSURE) |
+                       (1 << GAIN) |
+                       (1 << HFLIP) |
+                       (1 << VFLIP) |
+                       (1 << FREQ),
+
+[SENSOR_OV7630] =      (1 << EXPOSURE) |
+                       (1 << GAIN) |
+                       (1 << HFLIP),
+
+[SENSOR_OV7648] =      (1 << EXPOSURE) |
+                       (1 << GAIN) |
+                       (1 << HFLIP),
+
+[SENSOR_OV7660] =      (1 << EXPOSURE) |
+                       (1 << AUTOGAIN) |
+                       (1 << GAIN) |
+                       (1 << HFLIP) |
+                       (1 << VFLIP),
+
+[SENSOR_PO1030] =      (1 << EXPOSURE) |
+                       (1 << AUTOGAIN) |
+                       (1 << GAIN) |
+                       (1 << HFLIP) |
+                       (1 << VFLIP) |
+                       (1 << FREQ),
+
+[SENSOR_PO2030N] =     (1 << FREQ),
+
+[SENSOR_SOI768] =      (1 << EXPOSURE) |
+                       (1 << AUTOGAIN) |
+                       (1 << GAIN) |
+                       (1 << HFLIP) |
+                       (1 << VFLIP) |
+                       (1 << FREQ),
+
+[SENSOR_SP80708] =     (1 << EXPOSURE) |
+                       (1 << AUTOGAIN) |
+                       (1 << GAIN) |
+                       (1 << HFLIP) |
+                       (1 << VFLIP) |
+                       (1 << FREQ),
+};
+
+static const struct v4l2_pix_format cif_mode[] = {
+       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 4 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+static const struct v4l2_pix_format vga_mode[] = {
+       {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 4 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2},
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               /* Note 3 / 8 is not large enough, not even 5 / 8 is ?! */
+               .sizeimage = 640 * 480 * 3 / 4 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+
+static const u8 sn_adcm1700[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x43,   0x60,   0x00,   0x1a,   0x00,   0x00,   0x00,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x80,   0x51,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x05,   0x01,   0x05,   0x16,   0x12,   0x42,
+/*     reg18   reg19   reg1a   reg1b */
+       0x06,   0x00,   0x00,   0x00
+};
+
+static const u8 sn_gc0307[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x61,   0x62,   0x00,   0x1a,   0x00,   0x00,   0x00,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x80,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x03,   0x01,   0x08,   0x28,   0x1e,   0x02,
+/*     reg18   reg19   reg1a   reg1b */
+       0x06,   0x00,   0x00,   0x00
+};
+
+static const u8 sn_hv7131[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x03,   0x60,   0x00,   0x1a,   0x20,   0x20,   0x20,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x81,   0x11,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x00,   0x01,   0x03,   0x28,   0x1e,   0x41,
+/*     reg18   reg19   reg1a   reg1b */
+       0x0a,   0x00,   0x00,   0x00
+};
+
+static const u8 sn_mi0360[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x63,   0x40,   0x00,   0x1a,   0x20,   0x20,   0x20,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x81,   0x5d,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x00,   0x02,   0x0a,   0x28,   0x1e,   0x61,
+/*     reg18   reg19   reg1a   reg1b */
+       0x06,   0x00,   0x00,   0x00
+};
+
+static const u8 sn_mi0360b[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x61,   0x40,   0x00,   0x1a,   0x00,   0x00,   0x00,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x81,   0x5d,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x00,   0x02,   0x0a,   0x28,   0x1e,   0x40,
+/*     reg18   reg19   reg1a   reg1b */
+       0x06,   0x00,   0x00,   0x00
+};
+
+static const u8 sn_mo4000[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x23,   0x60,   0x00,   0x1a,   0x00,   0x20,   0x18,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x81,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,    0x00,  0x0b,   0x0f,   0x14,   0x28,   0x1e,   0x40,
+/*     reg18   reg19   reg1a   reg1b */
+       0x08,   0x00,   0x00,   0x00
+};
+
+static const u8 sn_mt9v111[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x61,   0x40,   0x00,   0x1a,   0x20,   0x20,   0x20,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x81,   0x5c,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x00,   0x02,   0x1c,   0x28,   0x1e,   0x40,
+/*     reg18   reg19   reg1a   reg1b */
+       0x06,   0x00,   0x00,   0x00
+};
+
+static const u8 sn_om6802[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x23,   0x72,   0x00,   0x1a,   0x20,   0x20,   0x19,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x80,   0x34,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x51,   0x01,   0x00,   0x28,   0x1e,   0x40,
+/*     reg18   reg19   reg1a   reg1b */
+       0x05,   0x00,   0x00,   0x00
+};
+
+static const u8 sn_ov7630[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x21,   0x40,   0x00,   0x1a,   0x00,   0x00,   0x00,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x81,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x04,   0x01,   0x0a,   0x28,   0x1e,   0xc2,
+/*     reg18   reg19   reg1a   reg1b */
+       0x0b,   0x00,   0x00,   0x00
+};
+
+static const u8 sn_ov7648[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x63,   0x40,   0x00,   0x1a,   0x20,   0x20,   0x20,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x81,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x00,   0x01,   0x00,   0x28,   0x1e,   0x00,
+/*     reg18   reg19   reg1a   reg1b */
+       0x0b,   0x00,   0x00,   0x00
+};
+
+static const u8 sn_ov7660[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x61,   0x40,   0x00,   0x1a,   0x00,   0x00,   0x00,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x81,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x01,   0x01,   0x08,   0x28,   0x1e,   0x20,
+/*     reg18   reg19   reg1a   reg1b */
+       0x07,   0x00,   0x00,   0x00
+};
+
+static const u8 sn_po1030[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x21,   0x62,   0x00,   0x1a,   0x20,   0x20,   0x20,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x81,   0x6e,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x00,   0x06,   0x06,   0x28,   0x1e,   0x00,
+/*     reg18   reg19   reg1a   reg1b */
+       0x07,   0x00,   0x00,   0x00
+};
+
+static const u8 sn_po2030n[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x63,   0x40,   0x00,   0x1a,   0x00,   0x00,   0x00,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x81,   0x6e,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x00,   0x01,   0x14,   0x28,   0x1e,   0x00,
+/*     reg18   reg19   reg1a   reg1b */
+       0x07,   0x00,   0x00,   0x00
+};
+
+static const u8 sn_soi768[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x21,   0x40,   0x00,   0x1a,   0x00,   0x00,   0x00,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x81,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x00,   0x01,   0x08,   0x28,   0x1e,   0x00,
+/*     reg18   reg19   reg1a   reg1b */
+       0x07,   0x00,   0x00,   0x00
+};
+
+static const u8 sn_sp80708[0x1c] = {
+/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
+       0x00,   0x63,   0x60,   0x00,   0x1a,   0x20,   0x20,   0x20,
+/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
+       0x81,   0x18,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
+/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
+       0x03,   0x00,   0x00,   0x03,   0x04,   0x28,   0x1e,   0x00,
+/*     reg18   reg19   reg1a   reg1b */
+       0x07,   0x00,   0x00,   0x00
+};
+
+/* sequence specific to the sensors - !! index = SENSOR_xxx */
+static const u8 *sn_tb[] = {
+[SENSOR_ADCM1700] =    sn_adcm1700,
+[SENSOR_GC0307] =      sn_gc0307,
+[SENSOR_HV7131R] =     sn_hv7131,
+[SENSOR_MI0360] =      sn_mi0360,
+[SENSOR_MI0360B] =     sn_mi0360b,
+[SENSOR_MO4000] =      sn_mo4000,
+[SENSOR_MT9V111] =     sn_mt9v111,
+[SENSOR_OM6802] =      sn_om6802,
+[SENSOR_OV7630] =      sn_ov7630,
+[SENSOR_OV7648] =      sn_ov7648,
+[SENSOR_OV7660] =      sn_ov7660,
+[SENSOR_PO1030] =      sn_po1030,
+[SENSOR_PO2030N] =     sn_po2030n,
+[SENSOR_SOI768] =      sn_soi768,
+[SENSOR_SP80708] =     sn_sp80708,
+};
+
+/* default gamma table */
+static const u8 gamma_def[17] = {
+       0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
+       0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
+};
+/* gamma for sensor ADCM1700 */
+static const u8 gamma_spec_0[17] = {
+       0x0f, 0x39, 0x5a, 0x74, 0x86, 0x95, 0xa6, 0xb4,
+       0xbd, 0xc4, 0xcc, 0xd4, 0xd5, 0xde, 0xe4, 0xed, 0xf5
+};
+/* gamma for sensors HV7131R and MT9V111 */
+static const u8 gamma_spec_1[17] = {
+       0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d,
+       0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5
+};
+/* gamma for sensor GC0307 */
+static const u8 gamma_spec_2[17] = {
+       0x14, 0x37, 0x50, 0x6a, 0x7c, 0x8d, 0x9d, 0xab,
+       0xb5, 0xbf, 0xc2, 0xcb, 0xd1, 0xd6, 0xdb, 0xe1, 0xeb
+};
+/* gamma for sensor SP80708 */
+static const u8 gamma_spec_3[17] = {
+       0x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab,
+       0xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6
+};
+
+/* color matrix and offsets */
+static const u8 reg84[] = {
+       0x14, 0x00, 0x27, 0x00, 0x07, 0x00,     /* YR YG YB gains */
+       0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00,     /* UR UG UB */
+       0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f,     /* VR VG VB */
+       0x00, 0x00, 0x00                        /* YUV offsets */
+};
+
+#define DELAY  0xdd
+
+static const u8 adcm1700_sensor_init[][8] = {
+       {0xa0, 0x51, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10},       /* reset */
+       {DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+       {0xb0, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+       {0xb0, 0x51, 0x0c, 0xe0, 0x2e, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x10, 0x02, 0x02, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x14, 0x0e, 0x0e, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x20, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+       {0xb0, 0x51, 0x04, 0x04, 0x00, 0x00, 0x00, 0x10},
+       {DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+       {0xb0, 0x51, 0x04, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x14, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+static const u8 adcm1700_sensor_param1[][8] = {
+       {0xb0, 0x51, 0x26, 0xf9, 0x01, 0x00, 0x00, 0x10},       /* exposure? */
+       {0xd0, 0x51, 0x1e, 0x8e, 0x8e, 0x8e, 0x8e, 0x10},
+
+       {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x32, 0x00, 0x72, 0x00, 0x00, 0x10},
+       {0xd0, 0x51, 0x1e, 0xbe, 0xd7, 0xe8, 0xbe, 0x10},       /* exposure? */
+
+       {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
+       {0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10},
+       {}
+};
+static const u8 gc0307_sensor_init[][8] = {
+       {0xa0, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x44, 0xa2, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x01, 0x6a, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x02, 0x70, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x11, 0x05, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x08, 0x02, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x09, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x0a, 0xe8, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x0b, 0x02, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x0d, 0x22, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x0f, 0xb2, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x12, 0x70, 0x00, 0x00, 0x00, 0x10},
+       {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 10ms*/
+       {0xa0, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x15, 0xb8, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x16, 0x13, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x17, 0x52, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x18, 0x50, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x1e, 0x0d, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x1f, 0x32, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x61, 0x90, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x63, 0x70, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x65, 0x98, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x67, 0x90, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x04, 0x96, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x45, 0x27, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x47, 0x2c, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x43, 0x47, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x44, 0xd8, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+static const u8 gc0307_sensor_param1[][8] = {
+       {0xa0, 0x21, 0x68, 0x13, 0x00, 0x00, 0x00, 0x10},
+       {0xd0, 0x21, 0x61, 0x80, 0x00, 0x80, 0x00, 0x10},
+       {0xc0, 0x21, 0x65, 0x80, 0x00, 0x80, 0x00, 0x10},
+       {0xc0, 0x21, 0x63, 0xa0, 0x00, 0xa6, 0x00, 0x10},
+/*param3*/
+       {0xa0, 0x21, 0x01, 0x6e, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x21, 0x02, 0x88, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+
+static const u8 hv7131r_sensor_init[][8] = {
+       {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
+       {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10},
+       {0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10},
+/*     {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, */
+       {0xd1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x11, 0x14, 0x01, 0xe2, 0x02, 0x82, 0x10},
+/*     {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, */
+
+       {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
+       {0xc1, 0x11, 0x25, 0x00, 0x61, 0xa8, 0x00, 0x10},
+       {0xa1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
+       {0xc1, 0x11, 0x31, 0x20, 0x2e, 0x20, 0x00, 0x10},
+       {0xc1, 0x11, 0x25, 0x00, 0xc3, 0x50, 0x00, 0x10},
+       {0xa1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
+       {0xc1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
+
+       {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
+
+       {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10},
+                                                       /* set sensor clock */
+       {}
+};
+static const u8 mi0360_sensor_init[][8] = {
+       {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
+       {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
+       {0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
+       {0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
+       {0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
+       {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
+       {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
+       {0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
+       {0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
+       {0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
+
+       {0xb1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x2b, 0x00, 0xa0, 0x00, 0xb0, 0x10},
+       {0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0xa0, 0x10},
+
+       {0xb1, 0x5d, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
+       {0xb1, 0x5d, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
+
+       {0xd1, 0x5d, 0x2b, 0x00, 0xb9, 0x00, 0xe3, 0x10},
+       {0xd1, 0x5d, 0x2d, 0x00, 0x5f, 0x00, 0xb9, 0x10}, /* 42 */
+/*     {0xb1, 0x5d, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
+/*     {0xb1, 0x5d, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
+       {0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
+       {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
+       {}
+};
+static const u8 mi0360b_sensor_init[][8] = {
+       {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
+       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/
+       {0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/
+       {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
+       {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
+       {0xd1, 0x5d, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
+       {0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
+       {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
+       {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
+       {0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
+       {0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
+       {0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
+
+       {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
+       {0xd1, 0x5d, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10},
+       {0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10},
+       {}
+};
+static const u8 mi0360b_sensor_param1[][8] = {
+       {0xb1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x06, 0x00, 0x53, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10},
+       {0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
+
+       {0xd1, 0x5d, 0x2b, 0x00, 0xd1, 0x01, 0xc9, 0x10},
+       {0xd1, 0x5d, 0x2d, 0x00, 0xed, 0x00, 0xd1, 0x10},
+       {0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
+       {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
+       {}
+};
+static const u8 mo4000_sensor_init[][8] = {
+       {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+static const u8 mt9v111_sensor_init[][8] = {
+       {0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */
+       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
+       {0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */
+       {0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */
+       {0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */
+       {0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */
+       {0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */
+       {0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */
+       {0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */
+       {0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */
+       {0xb1, 0x5c, 0x07, 0x30, 0x02, 0x00, 0x00, 0x10}, /* output ctrl */
+       {0xb1, 0x5c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, /* shutter delay */
+       {0xb1, 0x5c, 0x12, 0x00, 0xb0, 0x00, 0x00, 0x10}, /* zoom col start */
+       {0xb1, 0x5c, 0x13, 0x00, 0x7c, 0x00, 0x00, 0x10}, /* zoom row start */
+       {0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */
+       {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */
+       {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+static const u8 mt9v111_sensor_param1[][8] = {
+       {0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xad, 0x10}, /* G1 and B gains */
+       {0xd1, 0x5c, 0x2d, 0x00, 0xad, 0x00, 0x33, 0x10}, /* R and G2 gains */
+       {0xb1, 0x5c, 0x06, 0x00, 0x40, 0x00, 0x00, 0x10}, /* vert blanking */
+       {0xb1, 0x5c, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10}, /* horiz blanking */
+       {0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */
+       {}
+};
+static const u8 om6802_init0[2][8] = {
+/*fixme: variable*/
+       {0xa0, 0x34, 0x29, 0x0e, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x34, 0x23, 0xb0, 0x00, 0x00, 0x00, 0x10},
+};
+static const u8 om6802_sensor_init[][8] = {
+       {0xa0, 0x34, 0xdf, 0x6d, 0x00, 0x00, 0x00, 0x10},
+                                               /* factory mode */
+       {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
+                                               /* output raw RGB */
+       {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
+/*     {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
+       {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
+               /* auto-exposure speed (0) / white balance mode (auto RGB) */
+/*     {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
+                                                        * set color mode */
+/*     {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
+                                                * max AGC value in AE */
+/*     {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
+                                                        * preset AGC */
+/*     {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
+                                                * preset brightness */
+/*     {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
+                                                        * preset contrast */
+/*     {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
+                                                        * preset gamma */
+       {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
+                               /* luminance mode (0x4f -> AutoExpo on) */
+       {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
+                                                       /* preset shutter */
+/*     {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
+                                                        * auto frame rate */
+/*     {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
+       {0xa0, 0x34, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+static const u8 om6802_sensor_param1[][8] = {
+       {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+static const u8 ov7630_sensor_init[][8] = {
+       {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
+       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
+       {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
+       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
+       {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
+/* win: i2c_r from 00 to 80 */
+       {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
+       {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
+/* HDG: 0x11 was 0x00 change to 0x01 for better exposure (15 fps instead of 30)
+       0x13 was 0xc0 change to 0xc3 for auto gain and exposure */
+       {0xd1, 0x21, 0x11, 0x01, 0x48, 0xc3, 0x00, 0x10},
+       {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
+       {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
+       {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
+       {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
+       {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
+       {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
+       {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
+       {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
+       {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
+       {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
+       {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
+       {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
+       {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
+       {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
+       {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
+       {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+static const u8 ov7630_sensor_param1[][8] = {
+       {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
+/*fixme: + 0x12, 0x04*/
+/*     {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},  * COMN
+                                                        * set by setvflip */
+       {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
+/* */
+/*     {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
+/*     {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
+/* */
+       {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
+/*     {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
+       {}
+};
+
+static const u8 ov7648_sensor_init[][8] = {
+       {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},       /* reset */
+       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
+       {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},
+       {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},
+       {0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},
+       {0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},
+       {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},
+       {0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},
+       {0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},
+       {0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},
+       {0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},
+       {0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},
+       {0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},
+       {0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},
+       {0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},
+       {0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},
+       {0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},
+       {0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},
+
+       {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
+/*     {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
+/*     {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
+/*     {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */
+       {}
+};
+static const u8 ov7648_sensor_param1[][8] = {
+/*     {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
+/*     {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10},   * COMN
+                                                        * set by setvflip */
+       {0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
+/*     {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
+/*     {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},  * GAIN - def */
+/*     {0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10},  * B R - def: 80 */
+/*...*/
+       {0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */
+/*     {0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
+/*     {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
+/*     {0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */
+/*     {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
+/*     {0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10},  * B R - def: 80 */
+
+       {}
+};
+
+static const u8 ov7660_sensor_init[][8] = {
+       {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
+       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
+       {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
+                                               /* Outformat = rawRGB */
+       {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
+       {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
+                                               /* GAIN BLUE RED VREF */
+       {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
+                                               /* COM 1 BAVE GEAVE AECHH */
+       {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
+       {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
+       {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
+                                               /* AECH CLKRC COM7 COM8 */
+       {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
+       {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
+                                               /* HSTART HSTOP VSTRT VSTOP */
+       {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
+       {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
+       {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
+                                       /* BOS GBOS GROS ROS (BGGR offset) */
+/*     {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
+       {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
+                                               /* AEW AEB VPT BBIAS */
+       {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
+                                               /* GbBIAS RSVD EXHCH EXHCL */
+       {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
+                                               /* RBIAS ADVFL ASDVFH YAVE */
+       {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
+                                               /* HSYST HSYEN HREF */
+       {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
+       {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
+                                               /* ADC ACOM OFON TSLB */
+       {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
+                                               /* COM11 COM12 COM13 COM14 */
+       {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
+                                               /* EDGE COM15 COM16 COM17 */
+       {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
+       {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
+       {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
+       {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
+       {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
+       {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
+       {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
+       {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
+       {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
+       {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
+                                               /* LCC1 LCC2 LCC3 LCC4 */
+       {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
+       {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
+       {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
+                                       /* band gap reference [0:3] DBLV */
+       {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
+       {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
+       {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
+       {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
+       {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
+       {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
+       {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
+       {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
+       {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
+       {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
+/* not in all ms-win traces*/
+       {0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+static const u8 ov7660_sensor_param1[][8] = {
+       {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
+                                               /* bits[3..0]reserved */
+       {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
+                                               /* VREF vertical frame ctrl */
+       {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
+       {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
+       {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
+       {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
+/*     {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
+/****** (some exchanges in the win trace) ******/
+/*fixme:param2*/
+       {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
+       {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
+       {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
+       {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
+/*     {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},  * RED */
+/****** (some exchanges in the win trace) ******/
+/******!! startsensor KO if changed !!****/
+/*fixme: param3*/
+       {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+
+static const u8 po1030_sensor_init[][8] = {
+/* the sensor registers are described in m5602/m5602_po1030.h */
+       {0xa1, 0x6e, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x10}, /* sensor reset */
+       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
+       {0xa1, 0x6e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x6e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x04, 0x02, 0xb1, 0x02, 0x39, 0x10},
+       {0xd1, 0x6e, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x0c, 0x02, 0x7f, 0x01, 0xe0, 0x10},
+       {0xd1, 0x6e, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
+       {0xd1, 0x6e, 0x16, 0x85, 0x40, 0x4a, 0x40, 0x10}, /* r/g1/b/g2 gains */
+       {0xc1, 0x6e, 0x1a, 0x00, 0x80, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x1d, 0x08, 0x03, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x23, 0x00, 0xb0, 0x00, 0x94, 0x10},
+       {0xd1, 0x6e, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x6e, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x2d, 0x14, 0x35, 0x61, 0x84, 0x10}, /* gamma corr */
+       {0xd1, 0x6e, 0x31, 0xa2, 0xbd, 0xd8, 0xff, 0x10},
+       {0xd1, 0x6e, 0x35, 0x06, 0x1e, 0x12, 0x02, 0x10}, /* color matrix */
+       {0xd1, 0x6e, 0x39, 0xaa, 0x53, 0x37, 0xd5, 0x10},
+       {0xa1, 0x6e, 0x3d, 0xf2, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x3e, 0x00, 0x00, 0x80, 0x03, 0x10},
+       {0xd1, 0x6e, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
+       {0xc1, 0x6e, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
+       {0xd1, 0x6e, 0x4b, 0x02, 0xef, 0x08, 0xcd, 0x10},
+       {0xd1, 0x6e, 0x4f, 0x00, 0xd0, 0x00, 0xa0, 0x10},
+       {0xd1, 0x6e, 0x53, 0x01, 0xaa, 0x01, 0x40, 0x10},
+       {0xd1, 0x6e, 0x5a, 0x50, 0x04, 0x30, 0x03, 0x10}, /* raw rgb bayer */
+       {0xa1, 0x6e, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x5f, 0x10, 0x40, 0xff, 0x00, 0x10},
+
+       {0xd1, 0x6e, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xc1, 0x6e, 0x73, 0x10, 0x80, 0xeb, 0x00, 0x10},
+       {}
+};
+static const u8 po1030_sensor_param1[][8] = {
+/* from ms-win traces - these values change with auto gain/expo/wb.. */
+       {0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},
+/* mean values */
+       {0xc1, 0x6e, 0x1a, 0x02, 0xd4, 0xa4, 0x00, 0x10}, /* integlines */
+       {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, /* global gain */
+       {0xc1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10}, /* r/g1/b gains */
+
+       {0xa1, 0x6e, 0x1d, 0x08, 0x00, 0x00, 0x00, 0x10}, /* control1 */
+       {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, /* frameheight */
+       {0xa1, 0x6e, 0x07, 0xd5, 0x00, 0x00, 0x00, 0x10},
+/*     {0xc1, 0x6e, 0x16, 0x49, 0x40, 0x45, 0x00, 0x10}, */
+       {}
+};
+
+static const u8 po2030n_sensor_init[][8] = {
+       {0xa1, 0x6e, 0x1e, 0x1a, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x6e, 0x1f, 0x99, 0x00, 0x00, 0x00, 0x10},
+       {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */
+       {0xa1, 0x6e, 0x1e, 0x0a, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x6e, 0x1f, 0x19, 0x00, 0x00, 0x00, 0x10},
+       {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */
+       {0xa1, 0x6e, 0x20, 0x44, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x6e, 0x05, 0x70, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x08, 0x00, 0xd0, 0x00, 0x08, 0x10},
+       {0xd1, 0x6e, 0x0c, 0x03, 0x50, 0x01, 0xe8, 0x10},
+       {0xd1, 0x6e, 0x1d, 0x20, 0x0a, 0x19, 0x44, 0x10},
+       {0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x35, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x39, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x45, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x4d, 0x00, 0x00, 0x00, 0xed, 0x10},
+       {0xd1, 0x6e, 0x51, 0x17, 0x4a, 0x2f, 0xc0, 0x10},
+       {0xd1, 0x6e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x59, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x61, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x69, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x79, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x85, 0x00, 0x00, 0x00, 0x08, 0x10},
+       {0xd1, 0x6e, 0x89, 0x01, 0xe8, 0x00, 0x01, 0x10},
+       {0xa1, 0x6e, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x01, 0x10},
+       {0xd1, 0x6e, 0x29, 0xe6, 0x00, 0xbd, 0x03, 0x10},
+       {0xd1, 0x6e, 0x2d, 0x41, 0x38, 0x68, 0x40, 0x10},
+       {0xd1, 0x6e, 0x31, 0x2b, 0x00, 0x36, 0x00, 0x10},
+       {0xd1, 0x6e, 0x35, 0x30, 0x30, 0x08, 0x00, 0x10},
+       {0xd1, 0x6e, 0x39, 0x00, 0x00, 0x33, 0x06, 0x10},
+       {0xb1, 0x6e, 0x3d, 0x06, 0x02, 0x00, 0x00, 0x10},
+       {}
+};
+static const u8 po2030n_sensor_param1[][8] = {
+       {0xa1, 0x6e, 0x1a, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {DELAY, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */
+       {0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10},
+       {0xd1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x40, 0x10}, /* RGBG gains */
+/*param2*/
+       {0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+
+static const u8 soi768_sensor_init[][8] = {
+       {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
+       {DELAY, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 96ms */
+       {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+static const u8 soi768_sensor_param1[][8] = {
+       {0xa1, 0x21, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x21, 0x01, 0x7f, 0x7f, 0x00, 0x00, 0x10},
+/* */
+/*     {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, */
+/*     {0xa1, 0x21, 0x2d, 0x25, 0x00, 0x00, 0x00, 0x10}, */
+       {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
+/*     {0xb1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, */
+       {0xa1, 0x21, 0x02, 0x8d, 0x00, 0x00, 0x00, 0x10},
+/* the next sequence should be used for auto gain */
+       {0xa1, 0x21, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10},
+                       /* global gain ? : 07 - change with 0x15 at the end */
+       {0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */
+       {0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x21, 0x2d, 0x63, 0x03, 0x00, 0x00, 0x10},
+                       /* exposure ? : 0200 - change with 0x1e at the end */
+       {}
+};
+
+static const u8 sp80708_sensor_init[][8] = {
+       {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x10, 0x40, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x11, 0x4e, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x12, 0x53, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x15, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x19, 0x18, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x1a, 0x10, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x1c, 0x28, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x1d, 0x02, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x26, 0x04, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x27, 0x1e, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x28, 0x5a, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x29, 0x28, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x2a, 0x78, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x2c, 0xf7, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x2d, 0x2d, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x2e, 0xd5, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x39, 0x42, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x3a, 0x67, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x3b, 0x87, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x3c, 0xa3, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x3d, 0xb0, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x3e, 0xbc, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x3f, 0xc8, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x40, 0xd4, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x41, 0xdf, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x42, 0xea, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x43, 0xf5, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x45, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x46, 0x60, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x47, 0x50, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x48, 0x30, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x49, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x4d, 0xae, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x4e, 0x03, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x4f, 0x66, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x50, 0x1c, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x4a, 0x30, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x51, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x52, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x53, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x54, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x55, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x56, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x57, 0xe0, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x58, 0xc0, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x59, 0xab, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x5a, 0xa0, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x5b, 0x99, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x5c, 0x90, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x5e, 0x24, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x61, 0x73, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x63, 0x42, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x64, 0x42, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x65, 0x42, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x66, 0x24, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10},
+       {}
+};
+static const u8 sp80708_sensor_param1[][8] = {
+       {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x04, 0xa4, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x14, 0x3f, 0x00, 0x00, 0x00, 0x10},
+       {0xa1, 0x18, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
+       {0xb1, 0x18, 0x11, 0x40, 0x40, 0x00, 0x00, 0x10},
+       {}
+};
+
+static const u8 (*sensor_init[])[8] = {
+[SENSOR_ADCM1700] =    adcm1700_sensor_init,
+[SENSOR_GC0307] =      gc0307_sensor_init,
+[SENSOR_HV7131R] =     hv7131r_sensor_init,
+[SENSOR_MI0360] =      mi0360_sensor_init,
+[SENSOR_MI0360B] =     mi0360b_sensor_init,
+[SENSOR_MO4000] =      mo4000_sensor_init,
+[SENSOR_MT9V111] =     mt9v111_sensor_init,
+[SENSOR_OM6802] =      om6802_sensor_init,
+[SENSOR_OV7630] =      ov7630_sensor_init,
+[SENSOR_OV7648] =      ov7648_sensor_init,
+[SENSOR_OV7660] =      ov7660_sensor_init,
+[SENSOR_PO1030] =      po1030_sensor_init,
+[SENSOR_PO2030N] =     po2030n_sensor_init,
+[SENSOR_SOI768] =      soi768_sensor_init,
+[SENSOR_SP80708] =     sp80708_sensor_init,
+};
+
+/* read <len> bytes to gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev,
+                 u16 value, int len)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+#ifdef GSPCA_DEBUG
+       if (len > USB_BUF_SZ) {
+               pr_err("reg_r: buffer overflow\n");
+               return;
+       }
+#endif
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       0,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       value, 0,
+                       gspca_dev->usb_buf, len,
+                       500);
+       PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
+       if (ret < 0) {
+               pr_err("reg_r err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void reg_w1(struct gspca_dev *gspca_dev,
+                  u16 value,
+                  u8 data)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       PDEBUG(D_USBO, "reg_w1 [%04x] = %02x", value, data);
+       gspca_dev->usb_buf[0] = data;
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x08,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       value,
+                       0,
+                       gspca_dev->usb_buf, 1,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_w1 err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+static void reg_w(struct gspca_dev *gspca_dev,
+                         u16 value,
+                         const u8 *buffer,
+                         int len)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       PDEBUG(D_USBO, "reg_w [%04x] = %02x %02x ..",
+               value, buffer[0], buffer[1]);
+#ifdef GSPCA_DEBUG
+       if (len > USB_BUF_SZ) {
+               pr_err("reg_w: buffer overflow\n");
+               return;
+       }
+#endif
+       memcpy(gspca_dev->usb_buf, buffer, len);
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x08,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       value, 0,
+                       gspca_dev->usb_buf, len,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_w err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+/* I2C write 1 byte */
+static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       PDEBUG(D_USBO, "i2c_w1 [%02x] = %02x", reg, val);
+       switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+       case SENSOR_OM6802:
+       case SENSOR_GC0307:             /* i2c command = a0 (100 kHz) */
+               gspca_dev->usb_buf[0] = 0x80 | (2 << 4);
+               break;
+       default:                        /* i2c command = a1 (400 kHz) */
+               gspca_dev->usb_buf[0] = 0x81 | (2 << 4);
+               break;
+       }
+       gspca_dev->usb_buf[1] = sd->i2c_addr;
+       gspca_dev->usb_buf[2] = reg;
+       gspca_dev->usb_buf[3] = val;
+       gspca_dev->usb_buf[4] = 0;
+       gspca_dev->usb_buf[5] = 0;
+       gspca_dev->usb_buf[6] = 0;
+       gspca_dev->usb_buf[7] = 0x10;
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x08,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       0x08,                   /* value = i2c */
+                       0,
+                       gspca_dev->usb_buf, 8,
+                       500);
+       if (ret < 0) {
+               pr_err("i2c_w1 err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+/* I2C write 8 bytes */
+static void i2c_w8(struct gspca_dev *gspca_dev,
+                  const u8 *buffer)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       PDEBUG(D_USBO, "i2c_w8 [%02x] = %02x ..",
+               buffer[2], buffer[3]);
+       memcpy(gspca_dev->usb_buf, buffer, 8);
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x08,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       0x08, 0,                /* value, index */
+                       gspca_dev->usb_buf, 8,
+                       500);
+       msleep(2);
+       if (ret < 0) {
+               pr_err("i2c_w8 err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+/* sensor read 'len' (1..5) bytes in gspca_dev->usb_buf */
+static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 mode[8];
+
+       switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+       case SENSOR_OM6802:
+       case SENSOR_GC0307:             /* i2c command = a0 (100 kHz) */
+               mode[0] = 0x80 | 0x10;
+               break;
+       default:                        /* i2c command = 91 (400 kHz) */
+               mode[0] = 0x81 | 0x10;
+               break;
+       }
+       mode[1] = sd->i2c_addr;
+       mode[2] = reg;
+       mode[3] = 0;
+       mode[4] = 0;
+       mode[5] = 0;
+       mode[6] = 0;
+       mode[7] = 0x10;
+       i2c_w8(gspca_dev, mode);
+       msleep(2);
+       mode[0] = (mode[0] & 0x81) | (len << 4) | 0x02;
+       mode[2] = 0;
+       i2c_w8(gspca_dev, mode);
+       msleep(2);
+       reg_r(gspca_dev, 0x0a, 5);
+}
+
+static void i2c_w_seq(struct gspca_dev *gspca_dev,
+                       const u8 (*data)[8])
+{
+       while ((*data)[0] != 0) {
+               if ((*data)[0] != DELAY)
+                       i2c_w8(gspca_dev, *data);
+               else
+                       msleep((*data)[1]);
+               data++;
+       }
+}
+
+/* check the ID of the hv7131 sensor */
+/* this sequence is needed because it activates the sensor */
+static void hv7131r_probe(struct gspca_dev *gspca_dev)
+{
+       i2c_w1(gspca_dev, 0x02, 0);             /* sensor wakeup */
+       msleep(10);
+       reg_w1(gspca_dev, 0x02, 0x66);          /* Gpio on */
+       msleep(10);
+       i2c_r(gspca_dev, 0, 5);                 /* read sensor id */
+       if (gspca_dev->usb_buf[0] == 0x02       /* chip ID (02 is R) */
+           && gspca_dev->usb_buf[1] == 0x09
+           && gspca_dev->usb_buf[2] == 0x01) {
+               PDEBUG(D_PROBE, "Sensor HV7131R found");
+               return;
+       }
+       pr_warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x\n",
+               gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
+               gspca_dev->usb_buf[2]);
+}
+
+static void mi0360_probe(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i, j;
+       u16 val = 0;
+       static const u8 probe_tb[][4][8] = {
+           {                                   /* mi0360 */
+               {0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
+               {0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+               {0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+               {0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10}
+           },
+           {                                   /* mt9v111 */
+               {0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10},
+               {0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10},
+               {0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
+               {}
+           },
+       };
+
+       for (i = 0; i < ARRAY_SIZE(probe_tb); i++) {
+               reg_w1(gspca_dev, 0x17, 0x62);
+               reg_w1(gspca_dev, 0x01, 0x08);
+               for (j = 0; j < 3; j++)
+                       i2c_w8(gspca_dev, probe_tb[i][j]);
+               msleep(2);
+               reg_r(gspca_dev, 0x0a, 5);
+               val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
+               if (probe_tb[i][3][0] != 0)
+                       i2c_w8(gspca_dev, probe_tb[i][3]);
+               reg_w1(gspca_dev, 0x01, 0x29);
+               reg_w1(gspca_dev, 0x17, 0x42);
+               if (val != 0xffff)
+                       break;
+       }
+       if (gspca_dev->usb_err < 0)
+               return;
+       switch (val) {
+       case 0x8221:
+               PDEBUG(D_PROBE, "Sensor mi0360b");
+               sd->sensor = SENSOR_MI0360B;
+               break;
+       case 0x823a:
+               PDEBUG(D_PROBE, "Sensor mt9v111");
+               sd->sensor = SENSOR_MT9V111;
+               break;
+       case 0x8243:
+               PDEBUG(D_PROBE, "Sensor mi0360");
+               break;
+       default:
+               PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val);
+               break;
+       }
+}
+
+static void ov7630_probe(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u16 val;
+
+       /* check ov76xx */
+       reg_w1(gspca_dev, 0x17, 0x62);
+       reg_w1(gspca_dev, 0x01, 0x08);
+       sd->i2c_addr = 0x21;
+       i2c_r(gspca_dev, 0x0a, 2);
+       val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
+       reg_w1(gspca_dev, 0x01, 0x29);
+       reg_w1(gspca_dev, 0x17, 0x42);
+       if (gspca_dev->usb_err < 0)
+               return;
+       if (val == 0x7628) {                    /* soi768 */
+               sd->sensor = SENSOR_SOI768;
+/*fixme: only valid for 0c45:613e?*/
+               gspca_dev->cam.input_flags =
+                               V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
+               PDEBUG(D_PROBE, "Sensor soi768");
+               return;
+       }
+       PDEBUG(D_PROBE, "Sensor ov%04x", val);
+}
+
+static void ov7648_probe(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u16 val;
+
+       /* check ov76xx */
+       reg_w1(gspca_dev, 0x17, 0x62);
+       reg_w1(gspca_dev, 0x01, 0x08);
+       sd->i2c_addr = 0x21;
+       i2c_r(gspca_dev, 0x0a, 2);
+       val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
+       reg_w1(gspca_dev, 0x01, 0x29);
+       reg_w1(gspca_dev, 0x17, 0x42);
+       if ((val & 0xff00) == 0x7600) {         /* ov76xx */
+               PDEBUG(D_PROBE, "Sensor ov%04x", val);
+               return;
+       }
+
+       /* check po1030 */
+       reg_w1(gspca_dev, 0x17, 0x62);
+       reg_w1(gspca_dev, 0x01, 0x08);
+       sd->i2c_addr = 0x6e;
+       i2c_r(gspca_dev, 0x00, 2);
+       val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
+       reg_w1(gspca_dev, 0x01, 0x29);
+       reg_w1(gspca_dev, 0x17, 0x42);
+       if (gspca_dev->usb_err < 0)
+               return;
+       if (val == 0x1030) {                    /* po1030 */
+               PDEBUG(D_PROBE, "Sensor po1030");
+               sd->sensor = SENSOR_PO1030;
+               return;
+       }
+       pr_err("Unknown sensor %04x\n", val);
+}
+
+/* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */
+static void po2030n_probe(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u16 val;
+
+       /* check gc0307 */
+       reg_w1(gspca_dev, 0x17, 0x62);
+       reg_w1(gspca_dev, 0x01, 0x08);
+       reg_w1(gspca_dev, 0x02, 0x22);
+       sd->i2c_addr = 0x21;
+       i2c_r(gspca_dev, 0x00, 1);
+       val = gspca_dev->usb_buf[4];
+       reg_w1(gspca_dev, 0x01, 0x29);          /* reset */
+       reg_w1(gspca_dev, 0x17, 0x42);
+       if (val == 0x99) {                      /* gc0307 (?) */
+               PDEBUG(D_PROBE, "Sensor gc0307");
+               sd->sensor = SENSOR_GC0307;
+               return;
+       }
+
+       /* check po2030n */
+       reg_w1(gspca_dev, 0x17, 0x62);
+       reg_w1(gspca_dev, 0x01, 0x0a);
+       sd->i2c_addr = 0x6e;
+       i2c_r(gspca_dev, 0x00, 2);
+       val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
+       reg_w1(gspca_dev, 0x01, 0x29);
+       reg_w1(gspca_dev, 0x17, 0x42);
+       if (gspca_dev->usb_err < 0)
+               return;
+       if (val == 0x2030) {
+               PDEBUG(D_PROBE, "Sensor po2030n");
+/*             sd->sensor = SENSOR_PO2030N; */
+       } else {
+               pr_err("Unknown sensor ID %04x\n", val);
+       }
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+
+       sd->bridge = id->driver_info >> 16;
+       sd->sensor = id->driver_info >> 8;
+       sd->flags = id->driver_info;
+
+       cam = &gspca_dev->cam;
+       if (sd->sensor == SENSOR_ADCM1700) {
+               cam->cam_mode = cif_mode;
+               cam->nmodes = ARRAY_SIZE(cif_mode);
+       } else {
+               cam->cam_mode = vga_mode;
+               cam->nmodes = ARRAY_SIZE(vga_mode);
+       }
+       cam->npkt = 24;                 /* 24 packets per ISOC message */
+       cam->ctrls = sd->ctrls;
+
+       sd->ag_cnt = -1;
+       sd->quality = QUALITY_DEF;
+
+       INIT_WORK(&sd->work, qual_upd);
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       const u8 *sn9c1xx;
+       u8 regGpio[] = { 0x29, 0x70 };          /* no audio */
+       u8 regF1;
+
+       /* setup a selector by bridge */
+       reg_w1(gspca_dev, 0xf1, 0x01);
+       reg_r(gspca_dev, 0x00, 1);
+       reg_w1(gspca_dev, 0xf1, 0x00);
+       reg_r(gspca_dev, 0x00, 1);              /* get sonix chip id */
+       regF1 = gspca_dev->usb_buf[0];
+       if (gspca_dev->usb_err < 0)
+               return gspca_dev->usb_err;
+       PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
+       if (gspca_dev->audio)
+               regGpio[1] |= 0x04;             /* with audio */
+       switch (sd->bridge) {
+       case BRIDGE_SN9C102P:
+       case BRIDGE_SN9C105:
+               if (regF1 != 0x11)
+                       return -ENODEV;
+               break;
+       default:
+/*     case BRIDGE_SN9C110: */
+/*     case BRIDGE_SN9C120: */
+               if (regF1 != 0x12)
+                       return -ENODEV;
+       }
+
+       switch (sd->sensor) {
+       case SENSOR_MI0360:
+               mi0360_probe(gspca_dev);
+               break;
+       case SENSOR_OV7630:
+               ov7630_probe(gspca_dev);
+               break;
+       case SENSOR_OV7648:
+               ov7648_probe(gspca_dev);
+               break;
+       case SENSOR_PO2030N:
+               po2030n_probe(gspca_dev);
+               break;
+       }
+
+       switch (sd->bridge) {
+       case BRIDGE_SN9C102P:
+               reg_w1(gspca_dev, 0x02, regGpio[1]);
+               break;
+       default:
+               reg_w(gspca_dev, 0x01, regGpio, 2);
+               break;
+       }
+
+       if (sd->sensor == SENSOR_OM6802)
+               sd->ctrls[SHARPNESS].def = 0x10;
+
+       /* Note we do not disable the sensor clock here (power saving mode),
+          as that also disables the button on the cam. */
+       reg_w1(gspca_dev, 0xf1, 0x00);
+
+       /* set the i2c address */
+       sn9c1xx = sn_tb[sd->sensor];
+       sd->i2c_addr = sn9c1xx[9];
+
+       gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
+       if (!(sd->flags & F_ILLUM))
+               gspca_dev->ctrl_dis |= (1 << ILLUM);
+
+       return gspca_dev->usb_err;
+}
+
+static u32 expo_adjust(struct gspca_dev *gspca_dev,
+                       u32 expo)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->sensor) {
+       case SENSOR_GC0307: {
+               int a, b;
+
+               /* expo = 0..255 -> a = 19..43 */
+               a = 19 + expo * 25 / 256;
+               i2c_w1(gspca_dev, 0x68, a);
+               a -= 12;
+               b = a * a * 4;                  /* heuristic */
+               i2c_w1(gspca_dev, 0x03, b >> 8);
+               i2c_w1(gspca_dev, 0x04, b);
+               break;
+           }
+       case SENSOR_HV7131R: {
+               u8 Expodoit[] =
+                       { 0xc1, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16 };
+
+               Expodoit[3] = expo >> 16;
+               Expodoit[4] = expo >> 8;
+               Expodoit[5] = expo;
+               i2c_w8(gspca_dev, Expodoit);
+               break;
+           }
+       case SENSOR_MI0360:
+       case SENSOR_MI0360B: {
+               u8 expoMi[] =           /* exposure 0x0635 -> 4 fp/s 0x10 */
+                       { 0xb1, 0x5d, 0x09, 0x00, 0x00, 0x00, 0x00, 0x16 };
+               static const u8 doit[] =                /* update sensor */
+                       { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
+               static const u8 sensorgo[] =            /* sensor on */
+                       { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
+
+               if (expo > 0x0635)
+                       expo = 0x0635;
+               else if (expo < 0x0001)
+                       expo = 0x0001;
+               expoMi[3] = expo >> 8;
+               expoMi[4] = expo;
+               i2c_w8(gspca_dev, expoMi);
+               i2c_w8(gspca_dev, doit);
+               i2c_w8(gspca_dev, sensorgo);
+               break;
+           }
+       case SENSOR_MO4000: {
+               u8 expoMof[] =
+                       { 0xa1, 0x21, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x10 };
+               u8 expoMo10[] =
+                       { 0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10 };
+               static const u8 gainMo[] =
+                       { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
+
+               if (expo > 0x1fff)
+                       expo = 0x1fff;
+               else if (expo < 0x0001)
+                       expo = 0x0001;
+               expoMof[3] = (expo & 0x03fc) >> 2;
+               i2c_w8(gspca_dev, expoMof);
+               expoMo10[3] = ((expo & 0x1c00) >> 10)
+                               | ((expo & 0x0003) << 4);
+               i2c_w8(gspca_dev, expoMo10);
+               i2c_w8(gspca_dev, gainMo);
+               PDEBUG(D_FRAM, "set exposure %d",
+                       ((expoMo10[3] & 0x07) << 10)
+                       | (expoMof[3] << 2)
+                       | ((expoMo10[3] & 0x30) >> 4));
+               break;
+           }
+       case SENSOR_MT9V111: {
+               u8 expo_c1[] =
+                       { 0xb1, 0x5c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x10 };
+
+               if (expo > 0x0390)
+                       expo = 0x0390;
+               else if (expo < 0x0060)
+                       expo = 0x0060;
+               expo_c1[3] = expo >> 8;
+               expo_c1[4] = expo;
+               i2c_w8(gspca_dev, expo_c1);
+               break;
+           }
+       case SENSOR_OM6802: {
+               u8 gainOm[] =
+                       { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
+                               /* preset AGC - works when AutoExpo = off */
+
+               if (expo > 0x03ff)
+                       expo = 0x03ff;
+                if (expo < 0x0001)
+                       expo = 0x0001;
+               gainOm[3] = expo >> 2;
+               i2c_w8(gspca_dev, gainOm);
+               reg_w1(gspca_dev, 0x96, expo >> 5);
+               PDEBUG(D_FRAM, "set exposure %d", gainOm[3]);
+               break;
+           }
+       }
+       return expo;
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       unsigned int expo;
+       int brightness;
+       u8 k2;
+
+       brightness = sd->ctrls[BRIGHTNESS].val;
+       k2 = (brightness - 0x80) >> 2;
+       switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+               if (k2 > 0x1f)
+                       k2 = 0;         /* only positive Y offset */
+               break;
+       case SENSOR_HV7131R:
+               expo = brightness << 12;
+               if (expo > 0x002dc6c0)
+                       expo = 0x002dc6c0;
+               else if (expo < 0x02a0)
+                       expo = 0x02a0;
+               sd->exposure = expo_adjust(gspca_dev, expo);
+               break;
+       case SENSOR_MI0360:
+       case SENSOR_MO4000:
+               expo = brightness << 4;
+               sd->exposure = expo_adjust(gspca_dev, expo);
+               break;
+       case SENSOR_MI0360B:
+               expo = brightness << 2;
+               sd->exposure = expo_adjust(gspca_dev, expo);
+               break;
+       case SENSOR_GC0307:
+               expo = brightness;
+               sd->exposure = expo_adjust(gspca_dev, expo);
+               return;                 /* don't set the Y offset */
+       case SENSOR_MT9V111:
+               expo = brightness << 2;
+               sd->exposure = expo_adjust(gspca_dev, expo);
+               return;                 /* don't set the Y offset */
+       case SENSOR_OM6802:
+               expo = brightness << 2;
+               sd->exposure = expo_adjust(gspca_dev, expo);
+               return;                 /* Y offset already set */
+       }
+
+       reg_w1(gspca_dev, 0x96, k2);    /* color matrix Y offset */
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 k2;
+       u8 contrast[6];
+
+       k2 = sd->ctrls[CONTRAST].val * 37 / (CONTRAST_MAX + 1)
+                               + 37;           /* 37..73 */
+       contrast[0] = (k2 + 1) / 2;             /* red */
+       contrast[1] = 0;
+       contrast[2] = k2;                       /* green */
+       contrast[3] = 0;
+       contrast[4] = k2 / 5;                   /* blue */
+       contrast[5] = 0;
+       reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i, v, colors;
+       const s16 *uv;
+       u8 reg8a[12];                   /* U & V gains */
+       static const s16 uv_com[6] = {  /* same as reg84 in signed decimal */
+               -24, -38, 64,           /* UR UG UB */
+                62, -51, -9            /* VR VG VB */
+       };
+       static const s16 uv_mi0360b[6] = {
+               -20, -38, 64,           /* UR UG UB */
+                60, -51, -9            /* VR VG VB */
+       };
+
+       colors = sd->ctrls[COLORS].val;
+       if (sd->sensor == SENSOR_MI0360B)
+               uv = uv_mi0360b;
+       else
+               uv = uv_com;
+       for (i = 0; i < 6; i++) {
+               v = uv[i] * colors / COLORS_DEF;
+               reg8a[i * 2] = v;
+               reg8a[i * 2 + 1] = (v >> 8) & 0x0f;
+       }
+       reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a);
+}
+
+static void setredblue(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_PO2030N) {
+               u8 rg1b[] =             /* red  green1 blue (no g2) */
+                       {0xc1, 0x6e, 0x16, 0x00, 0x40, 0x00, 0x00, 0x10};
+
+               /* 0x40 = normal value = gain x 1 */
+               rg1b[3] = sd->ctrls[RED].val * 2;
+               rg1b[5] = sd->ctrls[BLUE].val * 2;
+               i2c_w8(gspca_dev, rg1b);
+               return;
+       }
+       reg_w1(gspca_dev, 0x05, sd->ctrls[RED].val);
+/*     reg_w1(gspca_dev, 0x07, 32); */
+       reg_w1(gspca_dev, 0x06, sd->ctrls[BLUE].val);
+}
+
+static void setgamma(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i, val;
+       u8 gamma[17];
+       const u8 *gamma_base;
+       static const u8 delta[17] = {
+               0x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a,
+               0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00
+       };
+
+       switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+               gamma_base = gamma_spec_0;
+               break;
+       case SENSOR_HV7131R:
+       case SENSOR_MI0360B:
+       case SENSOR_MT9V111:
+               gamma_base = gamma_spec_1;
+               break;
+       case SENSOR_GC0307:
+               gamma_base = gamma_spec_2;
+               break;
+       case SENSOR_SP80708:
+               gamma_base = gamma_spec_3;
+               break;
+       default:
+               gamma_base = gamma_def;
+               break;
+       }
+
+       val = sd->ctrls[GAMMA].val;
+       for (i = 0; i < sizeof gamma; i++)
+               gamma[i] = gamma_base[i]
+                       + delta[i] * (val - GAMMA_DEF) / 32;
+       reg_w(gspca_dev, 0x20, gamma, sizeof gamma);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_PO2030N) {
+               u8 rexpo[] =            /* 1a: expo H, 1b: expo M */
+                       {0xa1, 0x6e, 0x1a, 0x00, 0x40, 0x00, 0x00, 0x10};
+
+               rexpo[3] = sd->ctrls[EXPOSURE].val >> 8;
+               i2c_w8(gspca_dev, rexpo);
+               msleep(6);
+               rexpo[2] = 0x1b;
+               rexpo[3] = sd->ctrls[EXPOSURE].val;
+               i2c_w8(gspca_dev, rexpo);
+       }
+}
+
+static void setautogain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
+               return;
+       switch (sd->sensor) {
+       case SENSOR_OV7630:
+       case SENSOR_OV7648: {
+               u8 comb;
+
+               if (sd->sensor == SENSOR_OV7630)
+                       comb = 0xc0;
+               else
+                       comb = 0xa0;
+               if (sd->ctrls[AUTOGAIN].val)
+                       comb |= 0x03;
+               i2c_w1(&sd->gspca_dev, 0x13, comb);
+               return;
+           }
+       }
+       if (sd->ctrls[AUTOGAIN].val)
+               sd->ag_cnt = AG_CNT_START;
+       else
+               sd->ag_cnt = -1;
+}
+
+static void setgain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_PO2030N) {
+               u8 rgain[] =            /* 15: gain */
+                       {0xa1, 0x6e, 0x15, 0x00, 0x40, 0x00, 0x00, 0x15};
+
+               rgain[3] = sd->ctrls[GAIN].val;
+               i2c_w8(gspca_dev, rgain);
+       }
+}
+
+static void sethvflip(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 comn;
+
+       switch (sd->sensor) {
+       case SENSOR_HV7131R:
+               comn = 0x18;                    /* clkdiv = 1, ablcen = 1 */
+               if (sd->ctrls[VFLIP].val)
+                       comn |= 0x01;
+               i2c_w1(gspca_dev, 0x01, comn);  /* sctra */
+               break;
+       case SENSOR_OV7630:
+               comn = 0x02;
+               if (!sd->ctrls[VFLIP].val)
+                       comn |= 0x80;
+               i2c_w1(gspca_dev, 0x75, comn);
+               break;
+       case SENSOR_OV7648:
+               comn = 0x06;
+               if (sd->ctrls[VFLIP].val)
+                       comn |= 0x80;
+               i2c_w1(gspca_dev, 0x75, comn);
+               break;
+       case SENSOR_PO2030N:
+               /* Reg. 0x1E: Timing Generator Control Register 2 (Tgcontrol2)
+                * (reset value: 0x0A)
+                * bit7: HM: Horizontal Mirror: 0: disable, 1: enable
+                * bit6: VM: Vertical Mirror: 0: disable, 1: enable
+                * bit5: ST: Shutter Selection: 0: electrical, 1: mechanical
+                * bit4: FT: Single Frame Transfer: 0: disable, 1: enable
+                * bit3-0: X
+                */
+               comn = 0x0a;
+               if (sd->ctrls[HFLIP].val)
+                       comn |= 0x80;
+               if (sd->ctrls[VFLIP].val)
+                       comn |= 0x40;
+               i2c_w1(&sd->gspca_dev, 0x1e, comn);
+               break;
+       }
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       reg_w1(gspca_dev, 0x99, sd->ctrls[SHARPNESS].val);
+}
+
+static void setillum(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (gspca_dev->ctrl_dis & (1 << ILLUM))
+               return;
+       switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+               reg_w1(gspca_dev, 0x02,                         /* gpio */
+                       sd->ctrls[ILLUM].val ? 0x64 : 0x60);
+               break;
+       case SENSOR_MT9V111:
+               reg_w1(gspca_dev, 0x02,
+                       sd->ctrls[ILLUM].val ? 0x77 : 0x74);
+/* should have been: */
+/*                                             0x55 : 0x54);   * 370i */
+/*                                             0x66 : 0x64);   * Clip */
+               break;
+       }
+}
+
+static void setfreq(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (gspca_dev->ctrl_dis & (1 << FREQ))
+               return;
+       if (sd->sensor == SENSOR_OV7660) {
+               u8 com8;
+
+               com8 = 0xdf;            /* auto gain/wb/expo */
+               switch (sd->ctrls[FREQ].val) {
+               case 0: /* Banding filter disabled */
+                       i2c_w1(gspca_dev, 0x13, com8 | 0x20);
+                       break;
+               case 1: /* 50 hz */
+                       i2c_w1(gspca_dev, 0x13, com8);
+                       i2c_w1(gspca_dev, 0x3b, 0x0a);
+                       break;
+               case 2: /* 60 hz */
+                       i2c_w1(gspca_dev, 0x13, com8);
+                       i2c_w1(gspca_dev, 0x3b, 0x02);
+                       break;
+               }
+       } else {
+               u8 reg2a = 0, reg2b = 0, reg2d = 0;
+
+               /* Get reg2a / reg2d base values */
+               switch (sd->sensor) {
+               case SENSOR_OV7630:
+                       reg2a = 0x08;
+                       reg2d = 0x01;
+                       break;
+               case SENSOR_OV7648:
+                       reg2a = 0x11;
+                       reg2d = 0x81;
+                       break;
+               }
+
+               switch (sd->ctrls[FREQ].val) {
+               case 0: /* Banding filter disabled */
+                       break;
+               case 1: /* 50 hz (filter on and framerate adj) */
+                       reg2a |= 0x80;
+                       reg2b = 0xac;
+                       reg2d |= 0x04;
+                       break;
+               case 2: /* 60 hz (filter on, no framerate adj) */
+                       reg2a |= 0x80;
+                       reg2d |= 0x04;
+                       break;
+               }
+               i2c_w1(gspca_dev, 0x2a, reg2a);
+               i2c_w1(gspca_dev, 0x2b, reg2b);
+               i2c_w1(gspca_dev, 0x2d, reg2d);
+       }
+}
+
+static void setjpegqual(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+#if USB_BUF_SZ < 64
+#error "No room enough in usb_buf for quantization table"
+#endif
+       memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
+       usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x08,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       0x0100, 0,
+                       gspca_dev->usb_buf, 64,
+                       500);
+       memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
+       usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x08,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
+                       0x0140, 0,
+                       gspca_dev->usb_buf, 64,
+                       500);
+
+       sd->reg18 ^= 0x40;
+       reg_w1(gspca_dev, 0x18, sd->reg18);
+}
+
+/* JPEG quality update */
+/* This function is executed from a work queue. */
+static void qual_upd(struct work_struct *work)
+{
+       struct sd *sd = container_of(work, struct sd, work);
+       struct gspca_dev *gspca_dev = &sd->gspca_dev;
+
+       mutex_lock(&gspca_dev->usb_lock);
+       PDEBUG(D_STREAM, "qual_upd %d%%", sd->quality);
+       setjpegqual(gspca_dev);
+       mutex_unlock(&gspca_dev->usb_lock);
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+       u8 reg01, reg17;
+       u8 reg0102[2];
+       const u8 *sn9c1xx;
+       const u8 (*init)[8];
+       const u8 *reg9a;
+       int mode;
+       static const u8 reg9a_def[] =
+               {0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
+       static const u8 reg9a_spec[] =
+               {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
+       static const u8 regd4[] = {0x60, 0x00, 0x00};
+       static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
+       static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
+       static const u8 CA_adcm1700[] =
+                               { 0x14, 0xec, 0x0a, 0xf6 };
+       static const u8 CA_po2030n[] =
+                               { 0x1e, 0xe2, 0x14, 0xec };
+       static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd };      /* MI0360 */
+       static const u8 CE_gc0307[] =
+                               { 0x32, 0xce, 0x2d, 0xd3 };
+       static const u8 CE_ov76xx[] =
+                               { 0x32, 0xdd, 0x32, 0xdd };
+       static const u8 CE_po2030n[] =
+                               { 0x14, 0xe7, 0x1e, 0xdd };
+
+       /* create the JPEG header */
+       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+                       0x21);          /* JPEG 422 */
+
+       /* initialize the bridge */
+       sn9c1xx = sn_tb[sd->sensor];
+
+       /* sensor clock already enabled in sd_init */
+       /* reg_w1(gspca_dev, 0xf1, 0x00); */
+       reg01 = sn9c1xx[1];
+       if (sd->flags & F_PDN_INV)
+               reg01 ^= S_PDN_INV;             /* power down inverted */
+       reg_w1(gspca_dev, 0x01, reg01);
+
+       /* configure gpio */
+       reg0102[0] = reg01;
+       reg0102[1] = sn9c1xx[2];
+       if (gspca_dev->audio)
+               reg0102[1] |= 0x04;     /* keep the audio connection */
+       reg_w(gspca_dev, 0x01, reg0102, 2);
+       reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
+       reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
+       switch (sd->sensor) {
+       case SENSOR_GC0307:
+       case SENSOR_OV7660:
+       case SENSOR_PO1030:
+       case SENSOR_PO2030N:
+       case SENSOR_SOI768:
+       case SENSOR_SP80708:
+               reg9a = reg9a_spec;
+               break;
+       default:
+               reg9a = reg9a_def;
+               break;
+       }
+       reg_w(gspca_dev, 0x9a, reg9a, 6);
+
+       reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);
+
+       reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
+
+       reg17 = sn9c1xx[0x17];
+       switch (sd->sensor) {
+       case SENSOR_GC0307:
+               msleep(50);             /*fixme: is it useful? */
+               break;
+       case SENSOR_OM6802:
+               msleep(10);
+               reg_w1(gspca_dev, 0x02, 0x73);
+               reg17 |= SEN_CLK_EN;
+               reg_w1(gspca_dev, 0x17, reg17);
+               reg_w1(gspca_dev, 0x01, 0x22);
+               msleep(100);
+               reg01 = SCL_SEL_OD | S_PDN_INV;
+               reg17 &= ~MCK_SIZE_MASK;
+               reg17 |= 0x04;          /* clock / 4 */
+               break;
+       }
+       reg01 |= SYS_SEL_48M;
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg17 |= SEN_CLK_EN;
+       reg_w1(gspca_dev, 0x17, reg17);
+       reg01 &= ~S_PWR_DN;             /* sensor power on */
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg01 &= ~SCL_SEL_OD;           /* remove open-drain mode */
+       reg_w1(gspca_dev, 0x01, reg01);
+
+       switch (sd->sensor) {
+       case SENSOR_HV7131R:
+               hv7131r_probe(gspca_dev);       /*fixme: is it useful? */
+               break;
+       case SENSOR_OM6802:
+               msleep(10);
+               reg_w1(gspca_dev, 0x01, reg01);
+               i2c_w8(gspca_dev, om6802_init0[0]);
+               i2c_w8(gspca_dev, om6802_init0[1]);
+               msleep(15);
+               reg_w1(gspca_dev, 0x02, 0x71);
+               msleep(150);
+               break;
+       case SENSOR_SP80708:
+               msleep(100);
+               reg_w1(gspca_dev, 0x02, 0x62);
+               break;
+       }
+
+       /* initialize the sensor */
+       i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);
+
+       reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
+       reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
+       reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
+       reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
+       reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
+       if (sd->sensor == SENSOR_ADCM1700) {
+               reg_w1(gspca_dev, 0xd2, 0x3a);  /* AE_H_SIZE = 116 */
+               reg_w1(gspca_dev, 0xd3, 0x30);  /* AE_V_SIZE = 96 */
+       } else {
+               reg_w1(gspca_dev, 0xd2, 0x6a);  /* AE_H_SIZE = 212 */
+               reg_w1(gspca_dev, 0xd3, 0x50);  /* AE_V_SIZE = 160 */
+       }
+       reg_w1(gspca_dev, 0xc6, 0x00);
+       reg_w1(gspca_dev, 0xc7, 0x00);
+       if (sd->sensor == SENSOR_ADCM1700) {
+               reg_w1(gspca_dev, 0xc8, 0x2c);  /* AW_H_STOP = 352 */
+               reg_w1(gspca_dev, 0xc9, 0x24);  /* AW_V_STOP = 288 */
+       } else {
+               reg_w1(gspca_dev, 0xc8, 0x50);  /* AW_H_STOP = 640 */
+               reg_w1(gspca_dev, 0xc9, 0x3c);  /* AW_V_STOP = 480 */
+       }
+       reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
+       switch (sd->sensor) {
+       case SENSOR_OM6802:
+/*     case SENSOR_OV7648:             * fixme: sometimes */
+               break;
+       default:
+               reg17 |= DEF_EN;
+               break;
+       }
+       reg_w1(gspca_dev, 0x17, reg17);
+
+       reg_w1(gspca_dev, 0x05, 0x00);          /* red */
+       reg_w1(gspca_dev, 0x07, 0x00);          /* green */
+       reg_w1(gspca_dev, 0x06, 0x00);          /* blue */
+       reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
+
+       setgamma(gspca_dev);
+
+/*fixme: 8 times with all zeroes and 1 or 2 times with normal values */
+       for (i = 0; i < 8; i++)
+               reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
+       switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+       case SENSOR_OV7660:
+       case SENSOR_SP80708:
+               reg_w1(gspca_dev, 0x9a, 0x05);
+               break;
+       case SENSOR_GC0307:
+       case SENSOR_MT9V111:
+       case SENSOR_MI0360B:
+               reg_w1(gspca_dev, 0x9a, 0x07);
+               break;
+       case SENSOR_OV7630:
+       case SENSOR_OV7648:
+               reg_w1(gspca_dev, 0x9a, 0x0a);
+               break;
+       case SENSOR_PO2030N:
+       case SENSOR_SOI768:
+               reg_w1(gspca_dev, 0x9a, 0x06);
+               break;
+       default:
+               reg_w1(gspca_dev, 0x9a, 0x08);
+               break;
+       }
+       setsharpness(gspca_dev);
+
+       reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
+       reg_w1(gspca_dev, 0x05, 0x20);          /* red */
+       reg_w1(gspca_dev, 0x07, 0x20);          /* green */
+       reg_w1(gspca_dev, 0x06, 0x20);          /* blue */
+
+       init = NULL;
+       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+       reg01 |= SYS_SEL_48M | V_TX_EN;
+       reg17 &= ~MCK_SIZE_MASK;
+       reg17 |= 0x02;                  /* clock / 2 */
+       switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+               init = adcm1700_sensor_param1;
+               break;
+       case SENSOR_GC0307:
+               init = gc0307_sensor_param1;
+               break;
+       case SENSOR_HV7131R:
+       case SENSOR_MI0360:
+               if (!mode)
+                       reg01 &= ~SYS_SEL_48M;  /* 640x480: clk 24Mhz */
+               reg17 &= ~MCK_SIZE_MASK;
+               reg17 |= 0x01;                  /* clock / 1 */
+               break;
+       case SENSOR_MI0360B:
+               init = mi0360b_sensor_param1;
+               break;
+       case SENSOR_MO4000:
+               if (mode) {                     /* if 320x240 */
+                       reg01 &= ~SYS_SEL_48M;  /* clk 24Mz */
+                       reg17 &= ~MCK_SIZE_MASK;
+                       reg17 |= 0x01;          /* clock / 1 */
+               }
+               break;
+       case SENSOR_MT9V111:
+               init = mt9v111_sensor_param1;
+               break;
+       case SENSOR_OM6802:
+               init = om6802_sensor_param1;
+               if (!mode) {                    /* if 640x480 */
+                       reg17 &= ~MCK_SIZE_MASK;
+                       reg17 |= 0x04;          /* clock / 4 */
+               } else {
+                       reg01 &= ~SYS_SEL_48M;  /* clk 24Mz */
+                       reg17 &= ~MCK_SIZE_MASK;
+                       reg17 |= 0x02;          /* clock / 2 */
+               }
+               break;
+       case SENSOR_OV7630:
+               init = ov7630_sensor_param1;
+               break;
+       case SENSOR_OV7648:
+               init = ov7648_sensor_param1;
+               reg17 &= ~MCK_SIZE_MASK;
+               reg17 |= 0x01;                  /* clock / 1 */
+               break;
+       case SENSOR_OV7660:
+               init = ov7660_sensor_param1;
+               break;
+       case SENSOR_PO1030:
+               init = po1030_sensor_param1;
+               break;
+       case SENSOR_PO2030N:
+               init = po2030n_sensor_param1;
+               break;
+       case SENSOR_SOI768:
+               init = soi768_sensor_param1;
+               break;
+       case SENSOR_SP80708:
+               init = sp80708_sensor_param1;
+               break;
+       }
+
+       /* more sensor initialization - param1 */
+       if (init != NULL) {
+               i2c_w_seq(gspca_dev, init);
+/*             init = NULL; */
+       }
+
+       reg_w(gspca_dev, 0xc0, C0, 6);
+       switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+       case SENSOR_GC0307:
+       case SENSOR_SOI768:
+               reg_w(gspca_dev, 0xca, CA_adcm1700, 4);
+               break;
+       case SENSOR_PO2030N:
+               reg_w(gspca_dev, 0xca, CA_po2030n, 4);
+               break;
+       default:
+               reg_w(gspca_dev, 0xca, CA, 4);
+               break;
+       }
+       switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+       case SENSOR_OV7630:
+       case SENSOR_OV7648:
+       case SENSOR_OV7660:
+       case SENSOR_SOI768:
+               reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
+               break;
+       case SENSOR_GC0307:
+               reg_w(gspca_dev, 0xce, CE_gc0307, 4);
+               break;
+       case SENSOR_PO2030N:
+               reg_w(gspca_dev, 0xce, CE_po2030n, 4);
+               break;
+       default:
+               reg_w(gspca_dev, 0xce, CE, 4);
+                                       /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
+               break;
+       }
+
+       /* here change size mode 0 -> VGA; 1 -> CIF */
+       sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40;
+       reg_w1(gspca_dev, 0x18, sd->reg18);
+       setjpegqual(gspca_dev);
+
+       reg_w1(gspca_dev, 0x17, reg17);
+       reg_w1(gspca_dev, 0x01, reg01);
+       sd->reg01 = reg01;
+       sd->reg17 = reg17;
+
+       sethvflip(gspca_dev);
+       setbrightness(gspca_dev);
+       setcontrast(gspca_dev);
+       setcolors(gspca_dev);
+       setautogain(gspca_dev);
+       if (!(gspca_dev->ctrl_inac & ((1 << EXPOSURE) | (1 << GAIN)))) {
+               setexposure(gspca_dev);
+               setgain(gspca_dev);
+       }
+       setfreq(gspca_dev);
+
+       sd->pktsz = sd->npkt = 0;
+       sd->nchg = sd->short_mark = 0;
+       sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
+
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       static const u8 stophv7131[] =
+               { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
+       static const u8 stopmi0360[] =
+               { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
+       static const u8 stopov7648[] =
+               { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
+       static const u8 stopsoi768[] =
+               { 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };
+       u8 reg01;
+       u8 reg17;
+
+       reg01 = sd->reg01;
+       reg17 = sd->reg17 & ~SEN_CLK_EN;
+       switch (sd->sensor) {
+       case SENSOR_ADCM1700:
+       case SENSOR_GC0307:
+       case SENSOR_PO2030N:
+       case SENSOR_SP80708:
+               reg01 |= LED;
+               reg_w1(gspca_dev, 0x01, reg01);
+               reg01 &= ~(LED | V_TX_EN);
+               reg_w1(gspca_dev, 0x01, reg01);
+/*             reg_w1(gspca_dev, 0x02, 0x??);   * LED off ? */
+               break;
+       case SENSOR_HV7131R:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
+               i2c_w8(gspca_dev, stophv7131);
+               break;
+       case SENSOR_MI0360:
+       case SENSOR_MI0360B:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
+/*             reg_w1(gspca_dev, 0x02, 0x40);    * LED off ? */
+               i2c_w8(gspca_dev, stopmi0360);
+               break;
+       case SENSOR_MT9V111:
+       case SENSOR_OM6802:
+       case SENSOR_PO1030:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
+               break;
+       case SENSOR_OV7630:
+       case SENSOR_OV7648:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
+               i2c_w8(gspca_dev, stopov7648);
+               break;
+       case SENSOR_OV7660:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
+               break;
+       case SENSOR_SOI768:
+               i2c_w8(gspca_dev, stopsoi768);
+               break;
+       }
+
+       reg01 |= SCL_SEL_OD;
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg01 |= S_PWR_DN;              /* sensor power down */
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg_w1(gspca_dev, 0x17, reg17);
+       reg01 &= ~SYS_SEL_48M;          /* clock 24MHz */
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg01 |= LED;
+       reg_w1(gspca_dev, 0x01, reg01);
+       /* Don't disable sensor clock as that disables the button on the cam */
+       /* reg_w1(gspca_dev, 0xf1, 0x01); */
+}
+
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->work_thread != NULL) {
+               mutex_unlock(&gspca_dev->usb_lock);
+               destroy_workqueue(sd->work_thread);
+               mutex_lock(&gspca_dev->usb_lock);
+               sd->work_thread = NULL;
+       }
+}
+
+#define WANT_REGULAR_AUTOGAIN
+#include "autogain_functions.h"
+
+static void do_autogain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int delta;
+       int expotimes;
+       u8 luma_mean = 130;
+       u8 luma_delta = 20;
+
+       /* Thanks S., without your advice, autobright should not work :) */
+       if (sd->ag_cnt < 0)
+               return;
+       if (--sd->ag_cnt >= 0)
+               return;
+       sd->ag_cnt = AG_CNT_START;
+
+       delta = atomic_read(&sd->avg_lum);
+       PDEBUG(D_FRAM, "mean lum %d", delta);
+
+       if (sd->sensor == SENSOR_PO2030N) {
+               auto_gain_n_exposure(gspca_dev, delta, luma_mean, luma_delta,
+                                       15, 1024);
+               return;
+       }
+
+       if (delta < luma_mean - luma_delta ||
+           delta > luma_mean + luma_delta) {
+               switch (sd->sensor) {
+               case SENSOR_GC0307:
+                       expotimes = sd->exposure;
+                       expotimes += (luma_mean - delta) >> 6;
+                       if (expotimes < 0)
+                               expotimes = 0;
+                       sd->exposure = expo_adjust(gspca_dev,
+                                                  (unsigned int) expotimes);
+                       break;
+               case SENSOR_HV7131R:
+                       expotimes = sd->exposure >> 8;
+                       expotimes += (luma_mean - delta) >> 4;
+                       if (expotimes < 0)
+                               expotimes = 0;
+                       sd->exposure = expo_adjust(gspca_dev,
+                                       (unsigned int) (expotimes << 8));
+                       break;
+               case SENSOR_OM6802:
+               case SENSOR_MT9V111:
+                       expotimes = sd->exposure;
+                       expotimes += (luma_mean - delta) >> 2;
+                       if (expotimes < 0)
+                               expotimes = 0;
+                       sd->exposure = expo_adjust(gspca_dev,
+                                                  (unsigned int) expotimes);
+                       setredblue(gspca_dev);
+                       break;
+               default:
+/*             case SENSOR_MO4000: */
+/*             case SENSOR_MI0360: */
+/*             case SENSOR_MI0360B: */
+                       expotimes = sd->exposure;
+                       expotimes += (luma_mean - delta) >> 6;
+                       if (expotimes < 0)
+                               expotimes = 0;
+                       sd->exposure = expo_adjust(gspca_dev,
+                                                  (unsigned int) expotimes);
+                       setredblue(gspca_dev);
+                       break;
+               }
+       }
+}
+
+/* set the average luminosity from an isoc marker */
+static void set_lum(struct sd *sd,
+                   u8 *data)
+{
+       int avg_lum;
+
+       /*      w0 w1 w2
+        *      w3 w4 w5
+        *      w6 w7 w8
+        */
+       avg_lum = (data[27] << 8) + data[28]            /* w3 */
+
+               + (data[31] << 8) + data[32]            /* w5 */
+
+               + (data[23] << 8) + data[24]            /* w1 */
+
+               + (data[35] << 8) + data[36]            /* w7 */
+
+               + (data[29] << 10) + (data[30] << 2);   /* w4 * 4 */
+       avg_lum >>= 10;
+       atomic_set(&sd->avg_lum, avg_lum);
+}
+
+/* scan the URB packets */
+/* This function is run at interrupt level. */
+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;
+       int i, new_qual;
+
+       /*
+        * A frame ends on the marker
+        *              ff ff 00 c4 c4 96 ..
+        * which is 62 bytes long and is followed by various information
+        * including statuses and luminosity.
+        *
+        * A marker may be splitted on two packets.
+        *
+        * The 6th byte of a marker contains the bits:
+        *      0x08: USB full
+        *      0xc0: frame sequence
+        * When the bit 'USB full' is set, the frame must be discarded;
+        * this is also the case when the 2 bytes before the marker are
+        * not the JPEG end of frame ('ff d9').
+        */
+
+       /* count the packets and their size */
+       sd->npkt++;
+       sd->pktsz += len;
+
+/*fixme: assumption about the following code:
+ *     - there can be only one marker in a packet
+ */
+
+       /* skip the remaining bytes of a short marker */
+       i = sd->short_mark;
+       if (i != 0) {
+               sd->short_mark = 0;
+               if (i < 0       /* if 'ff' at end of previous packet */
+                && data[0] == 0xff
+                && data[1] == 0x00)
+                       goto marker_found;
+               if (data[0] == 0xff && data[1] == 0xff) {
+                       i = 0;
+                       goto marker_found;
+               }
+               len -= i;
+               if (len <= 0)
+                       return;
+               data += i;
+       }
+
+       /* search backwards if there is a marker in the packet */
+       for (i = len - 1; --i >= 0; ) {
+               if (data[i] != 0xff) {
+                       i--;
+                       continue;
+               }
+               if (data[i + 1] == 0xff) {
+
+                       /* (there may be 'ff ff' inside a marker) */
+                       if (i + 2 >= len || data[i + 2] == 0x00)
+                               goto marker_found;
+               }
+       }
+
+       /* no marker found */
+       /* add the JPEG header if first fragment */
+       if (data[len - 1] == 0xff)
+               sd->short_mark = -1;
+       if (gspca_dev->last_packet_type == LAST_PACKET)
+               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                               sd->jpeg_hdr, JPEG_HDR_SZ);
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+       return;
+
+       /* marker found */
+       /* if some error, discard the frame and decrease the quality */
+marker_found:
+       new_qual = 0;
+       if (i > 2) {
+               if (data[i - 2] != 0xff || data[i - 1] != 0xd9) {
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+                       new_qual = -3;
+               }
+       } else if (i + 6 < len) {
+               if (data[i + 6] & 0x08) {
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+                       new_qual = -5;
+               }
+       }
+
+       gspca_frame_add(gspca_dev, LAST_PACKET, data, i);
+
+       /* compute the filling rate and a new JPEG quality */
+       if (new_qual == 0) {
+               int r;
+
+               r = (sd->pktsz * 100) /
+                       (sd->npkt *
+                               gspca_dev->urb[0]->iso_frame_desc[0].length);
+               if (r >= 85)
+                       new_qual = -3;
+               else if (r < 75)
+                       new_qual = 2;
+       }
+       if (new_qual != 0) {
+               sd->nchg += new_qual;
+               if (sd->nchg < -6 || sd->nchg >= 12) {
+                       sd->nchg = 0;
+                       new_qual += sd->quality;
+                       if (new_qual < QUALITY_MIN)
+                               new_qual = QUALITY_MIN;
+                       else if (new_qual > QUALITY_MAX)
+                               new_qual = QUALITY_MAX;
+                       if (new_qual != sd->quality) {
+                               sd->quality = new_qual;
+                               queue_work(sd->work_thread, &sd->work);
+                       }
+               }
+       } else {
+               sd->nchg = 0;
+       }
+       sd->pktsz = sd->npkt = 0;
+
+       /* if the marker is smaller than 62 bytes,
+        * memorize the number of bytes to skip in the next packet */
+       if (i + 62 > len) {                     /* no more usable data */
+               sd->short_mark = i + 62 - len;
+               return;
+       }
+       if (sd->ag_cnt >= 0)
+               set_lum(sd, data + i);
+
+       /* if more data, start a new frame */
+       i += 62;
+       if (i < len) {
+               data += i;
+               len -= i;
+               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                               sd->jpeg_hdr, JPEG_HDR_SZ);
+               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+       }
+}
+
+static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->ctrls[AUTOGAIN].val = val;
+       if (val)
+               gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
+       else
+               gspca_dev->ctrl_inac &= ~(1 << EXPOSURE) & ~(1 << GAIN);
+       if (gspca_dev->streaming)
+               setautogain(gspca_dev);
+       return gspca_dev->usb_err;
+}
+
+static int sd_querymenu(struct gspca_dev *gspca_dev,
+                       struct v4l2_querymenu *menu)
+{
+       switch (menu->id) {
+       case V4L2_CID_POWER_LINE_FREQUENCY:
+               switch (menu->index) {
+               case 0:         /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
+                       strcpy((char *) menu->name, "NoFliker");
+                       return 0;
+               case 1:         /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
+                       strcpy((char *) menu->name, "50 Hz");
+                       return 0;
+               case 2:         /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
+                       strcpy((char *) menu->name, "60 Hz");
+                       return 0;
+               }
+               break;
+       }
+       return -EINVAL;
+}
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,               /* interrupt packet data */
+                       int len)                /* interrupt packet length */
+{
+       int ret = -EINVAL;
+
+       if (len == 1 && data[0] == 1) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
+               input_sync(gspca_dev->input_dev);
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+               input_sync(gspca_dev->input_dev);
+               ret = 0;
+       }
+
+       return ret;
+}
+#endif
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name = MODULE_NAME,
+       .ctrls = sd_ctrls,
+       .nctrls = NCTRLS,
+       .config = sd_config,
+       .init = sd_init,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .stop0 = sd_stop0,
+       .pkt_scan = sd_pkt_scan,
+       .dq_callback = do_autogain,
+       .querymenu = sd_querymenu,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .int_pkt_scan = sd_int_pkt_scan,
+#endif
+};
+
+/* -- module initialisation -- */
+#define BS(bridge, sensor) \
+       .driver_info = (BRIDGE_ ## bridge << 16) \
+                       | (SENSOR_ ## sensor << 8)
+#define BSF(bridge, sensor, flags) \
+       .driver_info = (BRIDGE_ ## bridge << 16) \
+                       | (SENSOR_ ## sensor << 8) \
+                       | (flags)
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x0458, 0x7025), BSF(SN9C120, MI0360B, F_PDN_INV)},
+       {USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},
+       {USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, F_PDN_INV)},
+       {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, F_PDN_INV)},
+       {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},
+       {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},
+       {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},
+       {USB_DEVICE(0x06f8, 0x3004), BS(SN9C105, OV7660)},
+       {USB_DEVICE(0x06f8, 0x3008), BS(SN9C105, OV7660)},
+/*     {USB_DEVICE(0x0c45, 0x603a), BS(SN9C102P, OV7648)}, */
+       {USB_DEVICE(0x0c45, 0x6040), BS(SN9C102P, HV7131R)},
+/*     {USB_DEVICE(0x0c45, 0x607a), BS(SN9C102P, OV7648)}, */
+/*     {USB_DEVICE(0x0c45, 0x607b), BS(SN9C102P, OV7660)}, */
+       {USB_DEVICE(0x0c45, 0x607c), BS(SN9C102P, HV7131R)},
+/*     {USB_DEVICE(0x0c45, 0x607e), BS(SN9C102P, OV7630)}, */
+       {USB_DEVICE(0x0c45, 0x60c0), BSF(SN9C105, MI0360, F_ILLUM)},
+                                               /* or MT9V111 */
+/*     {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */
+/*     {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */
+/*     {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */
+       {USB_DEVICE(0x0c45, 0x60ce), BS(SN9C105, SP80708)},
+       {USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)},
+/*     {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */
+/*     {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */
+/*     {USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */
+       {USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)},
+       {USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)},
+       {USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)},
+       {USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)},      /*sn9c128*/
+       {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)},     /* /GC0305*/
+/*     {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */
+       {USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)},      /*sn9c128*/
+       {USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)},      /*sn9c128*/
+       {USB_DEVICE(0x0c45, 0x610c), BS(SN9C120, HV7131R)},     /*sn9c128*/
+       {USB_DEVICE(0x0c45, 0x610e), BS(SN9C120, OV7630)},      /*sn9c128*/
+/*     {USB_DEVICE(0x0c45, 0x610f), BS(SN9C120, S5K53BEB)}, */
+/*     {USB_DEVICE(0x0c45, 0x6122), BS(SN9C110, ICM105C)}, */
+/*     {USB_DEVICE(0x0c45, 0x6123), BS(SN9C110, SanyoCCD)}, */
+       {USB_DEVICE(0x0c45, 0x6128), BS(SN9C120, OM6802)},      /*sn9c325?*/
+/*bw600.inf:*/
+       {USB_DEVICE(0x0c45, 0x612a), BS(SN9C120, OV7648)},      /*sn9c325?*/
+       {USB_DEVICE(0x0c45, 0x612b), BS(SN9C110, ADCM1700)},
+       {USB_DEVICE(0x0c45, 0x612c), BS(SN9C110, MO4000)},
+       {USB_DEVICE(0x0c45, 0x612e), BS(SN9C110, OV7630)},
+/*     {USB_DEVICE(0x0c45, 0x612f), BS(SN9C110, ICM105C)}, */
+       {USB_DEVICE(0x0c45, 0x6130), BS(SN9C120, MI0360)},
+                                               /* or MT9V111 / MI0360B */
+/*     {USB_DEVICE(0x0c45, 0x6132), BS(SN9C120, OV7670)}, */
+       {USB_DEVICE(0x0c45, 0x6138), BS(SN9C120, MO4000)},
+       {USB_DEVICE(0x0c45, 0x613a), BS(SN9C120, OV7648)},
+       {USB_DEVICE(0x0c45, 0x613b), BS(SN9C120, OV7660)},
+       {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)},
+       {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)},
+       {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)},     /*sn9c120b*/
+                                               /* or GC0305 / GC0307 */
+       {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)},     /*sn9c120b*/
+       {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)},      /*sn9c120b*/
+       {USB_DEVICE(0x0c45, 0x614a), BSF(SN9C120, ADCM1700, F_ILLUM)},
+/*     {USB_DEVICE(0x0c45, 0x614c), BS(SN9C120, GC0306)}, */   /*sn9c120b*/
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/spca1528.c b/drivers/media/usb/gspca/spca1528.c
new file mode 100644 (file)
index 0000000..14d6352
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * spca1528 subdriver
+ *
+ * Copyright (C) 2010-2011 Jean-Francois Moine (http://moinejf.free.fr)
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "spca1528"
+
+#include "gspca.h"
+#include "jpeg.h"
+
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
+MODULE_DESCRIPTION("SPCA1528 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       u8 pkt_seq;
+
+       u8 jpeg_hdr[JPEG_HDR_SZ];
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+/*             (does not work correctly)
+       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 5 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 3},
+*/
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 4 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+};
+
+/* read <len> bytes to gspca usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev,
+                       u8 req,
+                       u16 index,
+                       int len)
+{
+#if USB_BUF_SZ < 64
+#error "USB buffer too small"
+#endif
+       struct usb_device *dev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                       req,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0x0000,                 /* value */
+                       index,
+                       gspca_dev->usb_buf, len,
+                       500);
+       PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", req, index,
+                        gspca_dev->usb_buf[0]);
+       if (ret < 0) {
+               pr_err("reg_r err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void reg_w(struct gspca_dev *gspca_dev,
+                       u8 req,
+                       u16 value,
+                       u16 index)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                       req,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index,
+                       NULL, 0, 500);
+       if (ret < 0) {
+               pr_err("reg_w err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void reg_wb(struct gspca_dev *gspca_dev,
+                       u8 req,
+                       u16 value,
+                       u16 index,
+                       u8 byte)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       PDEBUG(D_USBO, "SET %02x %04x %04x %02x", req, value, index, byte);
+       gspca_dev->usb_buf[0] = byte;
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                       req,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index,
+                       gspca_dev->usb_buf, 1, 500);
+       if (ret < 0) {
+               pr_err("reg_w err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void wait_status_0(struct gspca_dev *gspca_dev)
+{
+       int i, w;
+
+       i = 16;
+       w = 0;
+       do {
+               reg_r(gspca_dev, 0x21, 0x0000, 1);
+               if (gspca_dev->usb_buf[0] == 0)
+                       return;
+               w += 15;
+               msleep(w);
+       } while (--i > 0);
+       PDEBUG(D_ERR, "wait_status_0 timeout");
+       gspca_dev->usb_err = -ETIME;
+}
+
+static void wait_status_1(struct gspca_dev *gspca_dev)
+{
+       int i;
+
+       i = 10;
+       do {
+               reg_r(gspca_dev, 0x21, 0x0001, 1);
+               msleep(10);
+               if (gspca_dev->usb_buf[0] == 1) {
+                       reg_wb(gspca_dev, 0x21, 0x0000, 0x0001, 0x00);
+                       reg_r(gspca_dev, 0x21, 0x0001, 1);
+                       return;
+               }
+       } while (--i > 0);
+       PDEBUG(D_ERR, "wait_status_1 timeout");
+       gspca_dev->usb_err = -ETIME;
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_wb(gspca_dev, 0xc0, 0x0000, 0x00c0, val);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_wb(gspca_dev, 0xc1, 0x0000, 0x00c1, val);
+}
+
+static void sethue(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_wb(gspca_dev, 0xc2, 0x0000, 0x0000, val);
+}
+
+static void setcolor(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_wb(gspca_dev, 0xc3, 0x0000, 0x00c3, val);
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_wb(gspca_dev, 0xc4, 0x0000, 0x00c4, val);
+}
+
+/* this function is called at probe time */
+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);
+       gspca_dev->cam.npkt = 128; /* number of packets per ISOC message */
+                       /*fixme: 256 in ms-win traces*/
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       reg_w(gspca_dev, 0x00, 0x0001, 0x2067);
+       reg_w(gspca_dev, 0x00, 0x00d0, 0x206b);
+       reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
+       reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
+       msleep(8);
+       reg_w(gspca_dev, 0x00, 0x00c0, 0x206b);
+       reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
+       reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
+
+       reg_r(gspca_dev, 0x20, 0x0000, 1);
+       reg_r(gspca_dev, 0x20, 0x0000, 5);
+       reg_r(gspca_dev, 0x23, 0x0000, 64);
+       PDEBUG(D_PROBE, "%s%s", &gspca_dev->usb_buf[0x1c],
+                               &gspca_dev->usb_buf[0x30]);
+       reg_r(gspca_dev, 0x23, 0x0001, 64);
+       return gspca_dev->usb_err;
+}
+
+/* function called at start time before URB creation */
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+       u8 mode;
+
+       reg_r(gspca_dev, 0x00, 0x2520, 1);
+       wait_status_0(gspca_dev);
+       reg_w(gspca_dev, 0xc5, 0x0003, 0x0000);
+       wait_status_1(gspca_dev);
+
+       wait_status_0(gspca_dev);
+       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+       reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode);
+       reg_r(gspca_dev, 0x25, 0x0004, 1);
+       reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06);  /* 420 */
+       reg_r(gspca_dev, 0x27, 0x0000, 1);
+
+/* not useful..
+       gspca_dev->alt = 4;             * use alternate setting 3 */
+
+       return gspca_dev->usb_err;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* initialize the JPEG header */
+       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+                       0x22);          /* JPEG 411 */
+
+       /* the JPEG quality shall be 85% */
+       jpeg_set_qual(sd->jpeg_hdr, 85);
+
+       reg_r(gspca_dev, 0x00, 0x2520, 1);
+       msleep(8);
+
+       /* start the capture */
+       wait_status_0(gspca_dev);
+       reg_w(gspca_dev, 0x31, 0x0000, 0x0004); /* start request */
+       wait_status_1(gspca_dev);
+       wait_status_0(gspca_dev);
+       msleep(200);
+
+       sd->pkt_seq = 0;
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       /* stop the capture */
+       wait_status_0(gspca_dev);
+       reg_w(gspca_dev, 0x31, 0x0000, 0x0000); /* stop request */
+       wait_status_1(gspca_dev);
+       wait_status_0(gspca_dev);
+}
+
+/* move a packet adding 0x00 after 0xff */
+static void add_packet(struct gspca_dev *gspca_dev,
+                       u8 *data,
+                       int len)
+{
+       int i;
+
+       i = 0;
+       do {
+               if (data[i] == 0xff) {
+                       gspca_frame_add(gspca_dev, INTER_PACKET,
+                                       data, i + 1);
+                       len -= i;
+                       data += i;
+                       *data = 0x00;
+                       i = 0;
+               }
+       } while (++i < len);
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+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;
+       static const u8 ffd9[] = {0xff, 0xd9};
+
+       /* image packets start with:
+        *      02 8n
+        * with <n> bit:
+        *      0x01: even (0) / odd (1) image
+        *      0x02: end of image when set
+        */
+       if (len < 3)
+               return;                         /* empty packet */
+       if (*data == 0x02) {
+               if (data[1] & 0x02) {
+                       sd->pkt_seq = !(data[1] & 1);
+                       add_packet(gspca_dev, data + 2, len - 2);
+                       gspca_frame_add(gspca_dev, LAST_PACKET,
+                                       ffd9, 2);
+                       return;
+               }
+               if ((data[1] & 1) != sd->pkt_seq)
+                       goto err;
+               if (gspca_dev->last_packet_type == LAST_PACKET)
+                       gspca_frame_add(gspca_dev, FIRST_PACKET,
+                                       sd->jpeg_hdr, JPEG_HDR_SZ);
+               add_packet(gspca_dev, data + 2, len - 2);
+               return;
+       }
+err:
+       gspca_dev->last_packet_type = DISCARD_PACKET;
+}
+
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct gspca_dev *gspca_dev =
+               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+
+       gspca_dev->usb_err = 0;
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_HUE:
+               sethue(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               setcolor(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SHARPNESS:
+               setsharpness(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 5);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 8, 1, 1);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_HUE, 0, 255, 1, 0);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 8, 1, 1);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SHARPNESS, 0, 255, 1, 0);
+
+       if (hdl->error) {
+               pr_err("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,
+       .isoc_init = sd_isoc_init,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x04fc, 0x1528)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+                       const struct usb_device_id *id)
+{
+       /* the video interface for isochronous transfer is 1 */
+       if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
+               return -ENODEV;
+
+       return gspca_dev_probe2(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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/spca500.c b/drivers/media/usb/gspca/spca500.c
new file mode 100644 (file)
index 0000000..25cb68d
--- /dev/null
@@ -0,0 +1,990 @@
+/*
+ * SPCA500 chip based cameras initialization data
+ *
+ * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "spca500"
+
+#include "gspca.h"
+#include "jpeg.h"
+
+MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
+MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+#define QUALITY 85
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;             /* !! must be the first item */
+
+       char subtype;
+#define AgfaCl20 0
+#define AiptekPocketDV 1
+#define BenqDC1016 2
+#define CreativePCCam300 3
+#define DLinkDSC350 4
+#define Gsmartmini 5
+#define IntelPocketPCCamera 6
+#define KodakEZ200 7
+#define LogitechClickSmart310 8
+#define LogitechClickSmart510 9
+#define LogitechTraveler 10
+#define MustekGsmart300 11
+#define Optimedia 12
+#define PalmPixDC85 13
+#define ToptroIndus 14
+
+       u8 jpeg_hdr[JPEG_HDR_SZ];
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+
+static const struct v4l2_pix_format sif_mode[] = {
+       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+
+/* Frame packet header offsets for the spca500 */
+#define SPCA500_OFFSET_PADDINGLB 2
+#define SPCA500_OFFSET_PADDINGHB 3
+#define SPCA500_OFFSET_MODE      4
+#define SPCA500_OFFSET_IMGWIDTH  5
+#define SPCA500_OFFSET_IMGHEIGHT 6
+#define SPCA500_OFFSET_IMGMODE   7
+#define SPCA500_OFFSET_QTBLINDEX 8
+#define SPCA500_OFFSET_FRAMSEQ   9
+#define SPCA500_OFFSET_CDSPINFO  10
+#define SPCA500_OFFSET_GPIO      11
+#define SPCA500_OFFSET_AUGPIO    12
+#define SPCA500_OFFSET_DATA      16
+
+
+static const __u16 spca500_visual_defaults[][3] = {
+       {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
+                                * hue (H byte) = 0,
+                                * saturation/hue enable,
+                                * brightness/contrast enable.
+                                */
+       {0x00, 0x0000, 0x8167}, /* brightness = 0 */
+       {0x00, 0x0020, 0x8168}, /* contrast = 0 */
+       {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
+                                * hue (H byte) = 0, saturation/hue enable,
+                                * brightness/contrast enable.
+                                * was 0x0003, now 0x0000.
+                                */
+       {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
+       {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
+       {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
+       {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
+       {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
+       {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
+       {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
+       {0x0c, 0x0004, 0x0000},
+       /* set interface */
+       {}
+};
+static const __u16 Clicksmart510_defaults[][3] = {
+       {0x00, 0x00, 0x8211},
+       {0x00, 0x01, 0x82c0},
+       {0x00, 0x10, 0x82cb},
+       {0x00, 0x0f, 0x800d},
+       {0x00, 0x82, 0x8225},
+       {0x00, 0x21, 0x8228},
+       {0x00, 0x00, 0x8203},
+       {0x00, 0x00, 0x8204},
+       {0x00, 0x08, 0x8205},
+       {0x00, 0xf8, 0x8206},
+       {0x00, 0x28, 0x8207},
+       {0x00, 0xa0, 0x8208},
+       {0x00, 0x08, 0x824a},
+       {0x00, 0x08, 0x8214},
+       {0x00, 0x80, 0x82c1},
+       {0x00, 0x00, 0x82c2},
+       {0x00, 0x00, 0x82ca},
+       {0x00, 0x80, 0x82c1},
+       {0x00, 0x04, 0x82c2},
+       {0x00, 0x00, 0x82ca},
+       {0x00, 0xfc, 0x8100},
+       {0x00, 0xfc, 0x8105},
+       {0x00, 0x30, 0x8101},
+       {0x00, 0x00, 0x8102},
+       {0x00, 0x00, 0x8103},
+       {0x00, 0x66, 0x8107},
+       {0x00, 0x00, 0x816b},
+       {0x00, 0x00, 0x8155},
+       {0x00, 0x01, 0x8156},
+       {0x00, 0x60, 0x8157},
+       {0x00, 0x40, 0x8158},
+       {0x00, 0x0a, 0x8159},
+       {0x00, 0x06, 0x815a},
+       {0x00, 0x00, 0x813f},
+       {0x00, 0x00, 0x8200},
+       {0x00, 0x19, 0x8201},
+       {0x00, 0x00, 0x82c1},
+       {0x00, 0xa0, 0x82c2},
+       {0x00, 0x00, 0x82ca},
+       {0x00, 0x00, 0x8117},
+       {0x00, 0x00, 0x8118},
+       {0x00, 0x65, 0x8119},
+       {0x00, 0x00, 0x811a},
+       {0x00, 0x00, 0x811b},
+       {0x00, 0x55, 0x811c},
+       {0x00, 0x65, 0x811d},
+       {0x00, 0x55, 0x811e},
+       {0x00, 0x16, 0x811f},
+       {0x00, 0x19, 0x8120},
+       {0x00, 0x80, 0x8103},
+       {0x00, 0x83, 0x816b},
+       {0x00, 0x25, 0x8168},
+       {0x00, 0x01, 0x820f},
+       {0x00, 0xff, 0x8115},
+       {0x00, 0x48, 0x8116},
+       {0x00, 0x50, 0x8151},
+       {0x00, 0x40, 0x8152},
+       {0x00, 0x78, 0x8153},
+       {0x00, 0x40, 0x8154},
+       {0x00, 0x00, 0x8167},
+       {0x00, 0x20, 0x8168},
+       {0x00, 0x00, 0x816a},
+       {0x00, 0x03, 0x816b},
+       {0x00, 0x20, 0x8169},
+       {0x00, 0x60, 0x8157},
+       {0x00, 0x00, 0x8190},
+       {0x00, 0x00, 0x81a1},
+       {0x00, 0x00, 0x81b2},
+       {0x00, 0x27, 0x8191},
+       {0x00, 0x27, 0x81a2},
+       {0x00, 0x27, 0x81b3},
+       {0x00, 0x4b, 0x8192},
+       {0x00, 0x4b, 0x81a3},
+       {0x00, 0x4b, 0x81b4},
+       {0x00, 0x66, 0x8193},
+       {0x00, 0x66, 0x81a4},
+       {0x00, 0x66, 0x81b5},
+       {0x00, 0x79, 0x8194},
+       {0x00, 0x79, 0x81a5},
+       {0x00, 0x79, 0x81b6},
+       {0x00, 0x8a, 0x8195},
+       {0x00, 0x8a, 0x81a6},
+       {0x00, 0x8a, 0x81b7},
+       {0x00, 0x9b, 0x8196},
+       {0x00, 0x9b, 0x81a7},
+       {0x00, 0x9b, 0x81b8},
+       {0x00, 0xa6, 0x8197},
+       {0x00, 0xa6, 0x81a8},
+       {0x00, 0xa6, 0x81b9},
+       {0x00, 0xb2, 0x8198},
+       {0x00, 0xb2, 0x81a9},
+       {0x00, 0xb2, 0x81ba},
+       {0x00, 0xbe, 0x8199},
+       {0x00, 0xbe, 0x81aa},
+       {0x00, 0xbe, 0x81bb},
+       {0x00, 0xc8, 0x819a},
+       {0x00, 0xc8, 0x81ab},
+       {0x00, 0xc8, 0x81bc},
+       {0x00, 0xd2, 0x819b},
+       {0x00, 0xd2, 0x81ac},
+       {0x00, 0xd2, 0x81bd},
+       {0x00, 0xdb, 0x819c},
+       {0x00, 0xdb, 0x81ad},
+       {0x00, 0xdb, 0x81be},
+       {0x00, 0xe4, 0x819d},
+       {0x00, 0xe4, 0x81ae},
+       {0x00, 0xe4, 0x81bf},
+       {0x00, 0xed, 0x819e},
+       {0x00, 0xed, 0x81af},
+       {0x00, 0xed, 0x81c0},
+       {0x00, 0xf7, 0x819f},
+       {0x00, 0xf7, 0x81b0},
+       {0x00, 0xf7, 0x81c1},
+       {0x00, 0xff, 0x81a0},
+       {0x00, 0xff, 0x81b1},
+       {0x00, 0xff, 0x81c2},
+       {0x00, 0x03, 0x8156},
+       {0x00, 0x00, 0x8211},
+       {0x00, 0x20, 0x8168},
+       {0x00, 0x01, 0x8202},
+       {0x00, 0x30, 0x8101},
+       {0x00, 0x00, 0x8111},
+       {0x00, 0x00, 0x8112},
+       {0x00, 0x00, 0x8113},
+       {0x00, 0x00, 0x8114},
+       {}
+};
+
+static const __u8 qtable_creative_pccam[2][64] = {
+       {                               /* Q-table Y-components */
+        0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
+        0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
+        0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
+        0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
+        0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
+        0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
+        0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
+        0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
+       {                               /* Q-table C-components */
+        0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
+};
+
+static const __u8 qtable_kodak_ez200[2][64] = {
+       {                               /* Q-table Y-components */
+        0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
+        0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
+        0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
+        0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
+        0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
+        0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
+        0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
+        0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
+       {                               /* Q-table C-components */
+        0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
+        0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
+        0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+        0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+        0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+        0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+        0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+        0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
+};
+
+static const __u8 qtable_pocketdv[2][64] = {
+       {               /* Q-table Y-components start registers 0x8800 */
+        0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
+        0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
+        0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
+        0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
+        0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
+        0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
+        0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
+        0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
+        },
+       {               /* Q-table C-components start registers 0x8840 */
+        0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
+        0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
+        0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
+        0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+        0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+        0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+        0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+        0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
+};
+
+/* read 'len' bytes to gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev,
+                 __u16 index,
+                 __u16 length)
+{
+       usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       0,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,              /* value */
+                       index, gspca_dev->usb_buf, length, 500);
+}
+
+static int reg_w(struct gspca_dev *gspca_dev,
+                    __u16 req, __u16 index, __u16 value)
+{
+       int ret;
+
+       PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       req,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index, NULL, 0, 500);
+       if (ret < 0)
+               pr_err("reg write: error %d\n", ret);
+       return ret;
+}
+
+/* returns: negative is error, pos or zero is data */
+static int reg_r_12(struct gspca_dev *gspca_dev,
+                       __u16 req,      /* bRequest */
+                       __u16 index,    /* wIndex */
+                       __u16 length)   /* wLength (1 or 2 only) */
+{
+       int ret;
+
+       gspca_dev->usb_buf[1] = 0;
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       req,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,              /* value */
+                       index,
+                       gspca_dev->usb_buf, length,
+                       500);           /* timeout */
+       if (ret < 0) {
+               pr_err("reg_r_12 err %d\n", ret);
+               return ret;
+       }
+       return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
+}
+
+/*
+ * Simple function to wait for a given 8-bit value to be returned from
+ * a reg_read call.
+ * Returns: negative is error or timeout, zero is success.
+ */
+static int reg_r_wait(struct gspca_dev *gspca_dev,
+                       __u16 reg, __u16 index, __u16 value)
+{
+       int ret, cnt = 20;
+
+       while (--cnt > 0) {
+               ret = reg_r_12(gspca_dev, reg, index, 1);
+               if (ret == value)
+                       return 0;
+               msleep(50);
+       }
+       return -EIO;
+}
+
+static int write_vector(struct gspca_dev *gspca_dev,
+                       const __u16 data[][3])
+{
+       int ret, i = 0;
+
+       while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
+               ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
+               if (ret < 0)
+                       return ret;
+               i++;
+       }
+       return 0;
+}
+
+static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
+                               unsigned int request,
+                               unsigned int ybase,
+                               unsigned int cbase,
+                               const __u8 qtable[2][64])
+{
+       int i, err;
+
+       /* loop over y components */
+       for (i = 0; i < 64; i++) {
+               err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
+               if (err < 0)
+                       return err;
+       }
+
+       /* loop over c components */
+       for (i = 0; i < 64; i++) {
+               err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
+               if (err < 0)
+                       return err;
+       }
+       return 0;
+}
+
+static void spca500_ping310(struct gspca_dev *gspca_dev)
+{
+       reg_r(gspca_dev, 0x0d04, 2);
+       PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
+               gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
+}
+
+static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
+{
+       reg_r(gspca_dev, 0x0d05, 2);
+       PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
+               gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
+       reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
+       spca500_ping310(gspca_dev);
+
+       reg_w(gspca_dev, 0x00, 0x8168, 0x22);
+       reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
+       reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
+       reg_w(gspca_dev, 0x00, 0x8169, 0x25);
+       reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
+       reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
+       reg_w(gspca_dev, 0x00, 0x813f, 0x03);
+       reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
+       reg_w(gspca_dev, 0x00, 0x8153, 0x78);
+       reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
+                                               /* 00 for adjust shutter */
+       reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
+       reg_w(gspca_dev, 0x00, 0x8169, 0x25);
+       reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
+}
+
+static void spca500_setmode(struct gspca_dev *gspca_dev,
+                       __u8 xmult, __u8 ymult)
+{
+       int mode;
+
+       /* set x multiplier */
+       reg_w(gspca_dev, 0, 0x8001, xmult);
+
+       /* set y multiplier */
+       reg_w(gspca_dev, 0, 0x8002, ymult);
+
+       /* use compressed mode, VGA, with mode specific subsample */
+       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+       reg_w(gspca_dev, 0, 0x8003, mode << 4);
+}
+
+static int spca500_full_reset(struct gspca_dev *gspca_dev)
+{
+       int err;
+
+       /* send the reset command */
+       err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
+       if (err < 0)
+               return err;
+
+       /* wait for the reset to complete */
+       err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
+       if (err < 0)
+               return err;
+       err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
+       if (err < 0)
+               return err;
+       err = reg_r_wait(gspca_dev, 0x06, 0, 0);
+       if (err < 0) {
+               PDEBUG(D_ERR, "reg_r_wait() failed");
+               return err;
+       }
+       /* all ok */
+       return 0;
+}
+
+/* Synchro the Bridge with sensor */
+/* Maybe that will work on all spca500 chip */
+/* because i only own a clicksmart310 try for that chip */
+/* using spca50x_set_packet_size() cause an Ooops here */
+/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
+/* up-port the same feature as in 2.4.x kernel */
+static int spca500_synch310(struct gspca_dev *gspca_dev)
+{
+       if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
+               PDEBUG(D_ERR, "Set packet size: set interface error");
+               goto error;
+       }
+       spca500_ping310(gspca_dev);
+
+       reg_r(gspca_dev, 0x0d00, 1);
+
+       /* need alt setting here */
+       PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
+
+       /* Windoze use pipe with altsetting 6 why 7 here */
+       if (usb_set_interface(gspca_dev->dev,
+                               gspca_dev->iface,
+                               gspca_dev->alt) < 0) {
+               PDEBUG(D_ERR, "Set packet size: set interface error");
+               goto error;
+       }
+       return 0;
+error:
+       return -EBUSY;
+}
+
+static void spca500_reinit(struct gspca_dev *gspca_dev)
+{
+       int err;
+       __u8 Data;
+
+       /* some unknown command from Aiptek pocket dv and family300 */
+
+       reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
+       reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
+       reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
+
+       /* enable drop packet */
+       reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
+
+       err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
+                                qtable_pocketdv);
+       if (err < 0)
+               PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
+
+       /* set qtable index */
+       reg_w(gspca_dev, 0x00, 0x8880, 2);
+       /* family cam Quicksmart stuff */
+       reg_w(gspca_dev, 0x00, 0x800a, 0x00);
+       /* Set agc transfer: synced between frames */
+       reg_w(gspca_dev, 0x00, 0x820f, 0x01);
+       /* Init SDRAM - needed for SDRAM access */
+       reg_w(gspca_dev, 0x00, 0x870a, 0x04);
+       /*Start init sequence or stream */
+       reg_w(gspca_dev, 0, 0x8003, 0x00);
+       /* switch to video camera mode */
+       reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
+       msleep(2000);
+       if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
+               reg_r(gspca_dev, 0x816b, 1);
+               Data = gspca_dev->usb_buf[0];
+               reg_w(gspca_dev, 0x00, 0x816b, Data);
+       }
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+
+       cam = &gspca_dev->cam;
+       sd->subtype = id->driver_info;
+       if (sd->subtype != LogitechClickSmart310) {
+               cam->cam_mode = vga_mode;
+               cam->nmodes = ARRAY_SIZE(vga_mode);
+       } else {
+               cam->cam_mode = sif_mode;
+               cam->nmodes = ARRAY_SIZE(sif_mode);
+       }
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* initialisation of spca500 based cameras is deferred */
+       PDEBUG(D_STREAM, "SPCA500 init");
+       if (sd->subtype == LogitechClickSmart310)
+               spca500_clksmart310_init(gspca_dev);
+/*     else
+               spca500_initialise(gspca_dev); */
+       PDEBUG(D_STREAM, "SPCA500 init done");
+       return 0;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int err;
+       __u8 Data;
+       __u8 xmult, ymult;
+
+       /* create the JPEG header */
+       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+                       0x22);          /* JPEG 411 */
+       jpeg_set_qual(sd->jpeg_hdr, QUALITY);
+
+       if (sd->subtype == LogitechClickSmart310) {
+               xmult = 0x16;
+               ymult = 0x12;
+       } else {
+               xmult = 0x28;
+               ymult = 0x1e;
+       }
+
+       /* is there a sensor here ? */
+       reg_r(gspca_dev, 0x8a04, 1);
+       PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
+               gspca_dev->usb_buf[0]);
+       PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
+               gspca_dev->curr_mode, xmult, ymult);
+
+       /* setup qtable */
+       switch (sd->subtype) {
+       case LogitechClickSmart310:
+                spca500_setmode(gspca_dev, xmult, ymult);
+
+               /* enable drop packet */
+               reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
+               reg_w(gspca_dev, 0x00, 0x8880, 3);
+               err = spca50x_setup_qtable(gspca_dev,
+                                          0x00, 0x8800, 0x8840,
+                                          qtable_creative_pccam);
+               if (err < 0)
+                       PDEBUG(D_ERR, "spca50x_setup_qtable failed");
+               /* Init SDRAM - needed for SDRAM access */
+               reg_w(gspca_dev, 0x00, 0x870a, 0x04);
+
+               /* switch to video camera mode */
+               reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
+               msleep(500);
+               if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
+                       PDEBUG(D_ERR, "reg_r_wait() failed");
+
+               reg_r(gspca_dev, 0x816b, 1);
+               Data = gspca_dev->usb_buf[0];
+               reg_w(gspca_dev, 0x00, 0x816b, Data);
+
+               spca500_synch310(gspca_dev);
+
+               write_vector(gspca_dev, spca500_visual_defaults);
+               spca500_setmode(gspca_dev, xmult, ymult);
+               /* enable drop packet */
+               err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
+               if (err < 0)
+                       PDEBUG(D_ERR, "failed to enable drop packet");
+               reg_w(gspca_dev, 0x00, 0x8880, 3);
+               err = spca50x_setup_qtable(gspca_dev,
+                                          0x00, 0x8800, 0x8840,
+                                          qtable_creative_pccam);
+               if (err < 0)
+                       PDEBUG(D_ERR, "spca50x_setup_qtable failed");
+
+               /* Init SDRAM - needed for SDRAM access */
+               reg_w(gspca_dev, 0x00, 0x870a, 0x04);
+
+               /* switch to video camera mode */
+               reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
+
+               if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
+                       PDEBUG(D_ERR, "reg_r_wait() failed");
+
+               reg_r(gspca_dev, 0x816b, 1);
+               Data = gspca_dev->usb_buf[0];
+               reg_w(gspca_dev, 0x00, 0x816b, Data);
+               break;
+       case CreativePCCam300:          /* Creative PC-CAM 300 640x480 CCD */
+       case IntelPocketPCCamera:       /* FIXME: Temporary fix for
+                                        *      Intel Pocket PC Camera
+                                        *      - NWG (Sat 29th March 2003) */
+
+               /* do a full reset */
+               err = spca500_full_reset(gspca_dev);
+               if (err < 0)
+                       PDEBUG(D_ERR, "spca500_full_reset failed");
+
+               /* enable drop packet */
+               err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
+               if (err < 0)
+                       PDEBUG(D_ERR, "failed to enable drop packet");
+               reg_w(gspca_dev, 0x00, 0x8880, 3);
+               err = spca50x_setup_qtable(gspca_dev,
+                                          0x00, 0x8800, 0x8840,
+                                          qtable_creative_pccam);
+               if (err < 0)
+                       PDEBUG(D_ERR, "spca50x_setup_qtable failed");
+
+               spca500_setmode(gspca_dev, xmult, ymult);
+               reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
+
+               /* switch to video camera mode */
+               reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
+
+               if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
+                       PDEBUG(D_ERR, "reg_r_wait() failed");
+
+               reg_r(gspca_dev, 0x816b, 1);
+               Data = gspca_dev->usb_buf[0];
+               reg_w(gspca_dev, 0x00, 0x816b, Data);
+
+/*             write_vector(gspca_dev, spca500_visual_defaults); */
+               break;
+       case KodakEZ200:                /* Kodak EZ200 */
+
+               /* do a full reset */
+               err = spca500_full_reset(gspca_dev);
+               if (err < 0)
+                       PDEBUG(D_ERR, "spca500_full_reset failed");
+               /* enable drop packet */
+               reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
+               reg_w(gspca_dev, 0x00, 0x8880, 0);
+               err = spca50x_setup_qtable(gspca_dev,
+                                          0x00, 0x8800, 0x8840,
+                                          qtable_kodak_ez200);
+               if (err < 0)
+                       PDEBUG(D_ERR, "spca50x_setup_qtable failed");
+               spca500_setmode(gspca_dev, xmult, ymult);
+
+               reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
+
+               /* switch to video camera mode */
+               reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
+
+               if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
+                       PDEBUG(D_ERR, "reg_r_wait() failed");
+
+               reg_r(gspca_dev, 0x816b, 1);
+               Data = gspca_dev->usb_buf[0];
+               reg_w(gspca_dev, 0x00, 0x816b, Data);
+
+/*             write_vector(gspca_dev, spca500_visual_defaults); */
+               break;
+
+       case BenqDC1016:
+       case DLinkDSC350:               /* FamilyCam 300 */
+       case AiptekPocketDV:            /* Aiptek PocketDV */
+       case Gsmartmini:                /*Mustek Gsmart Mini */
+       case MustekGsmart300:           /* Mustek Gsmart 300 */
+       case PalmPixDC85:
+       case Optimedia:
+       case ToptroIndus:
+       case AgfaCl20:
+               spca500_reinit(gspca_dev);
+               reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
+               /* enable drop packet */
+               reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
+
+               err = spca50x_setup_qtable(gspca_dev,
+                                  0x00, 0x8800, 0x8840, qtable_pocketdv);
+               if (err < 0)
+                       PDEBUG(D_ERR, "spca50x_setup_qtable failed");
+               reg_w(gspca_dev, 0x00, 0x8880, 2);
+
+               /* familycam Quicksmart pocketDV stuff */
+               reg_w(gspca_dev, 0x00, 0x800a, 0x00);
+               /* Set agc transfer: synced between frames */
+               reg_w(gspca_dev, 0x00, 0x820f, 0x01);
+               /* Init SDRAM - needed for SDRAM access */
+               reg_w(gspca_dev, 0x00, 0x870a, 0x04);
+
+               spca500_setmode(gspca_dev, xmult, ymult);
+               /* switch to video camera mode */
+               reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
+
+               reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
+
+               reg_r(gspca_dev, 0x816b, 1);
+               Data = gspca_dev->usb_buf[0];
+               reg_w(gspca_dev, 0x00, 0x816b, Data);
+               break;
+       case LogitechTraveler:
+       case LogitechClickSmart510:
+               reg_w(gspca_dev, 0x02, 0x00, 0x00);
+               /* enable drop packet */
+               reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
+
+               err = spca50x_setup_qtable(gspca_dev,
+                                       0x00, 0x8800,
+                                       0x8840, qtable_creative_pccam);
+               if (err < 0)
+                       PDEBUG(D_ERR, "spca50x_setup_qtable failed");
+               reg_w(gspca_dev, 0x00, 0x8880, 3);
+               reg_w(gspca_dev, 0x00, 0x800a, 0x00);
+               /* Init SDRAM - needed for SDRAM access */
+               reg_w(gspca_dev, 0x00, 0x870a, 0x04);
+
+               spca500_setmode(gspca_dev, xmult, ymult);
+
+               /* switch to video camera mode */
+               reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
+               reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
+
+               reg_r(gspca_dev, 0x816b, 1);
+               Data = gspca_dev->usb_buf[0];
+               reg_w(gspca_dev, 0x00, 0x816b, Data);
+               write_vector(gspca_dev, Clicksmart510_defaults);
+               break;
+       }
+       return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       reg_w(gspca_dev, 0, 0x8003, 0x00);
+
+       /* switch to video camera mode */
+       reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
+       reg_r(gspca_dev, 0x8000, 1);
+       PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
+               gspca_dev->usb_buf[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;
+       int i;
+       static __u8 ffd9[] = {0xff, 0xd9};
+
+/* frames are jpeg 4.1.1 without 0xff escape */
+       if (data[0] == 0xff) {
+               if (data[1] != 0x01) {  /* drop packet */
+/*                     gspca_dev->last_packet_type = DISCARD_PACKET; */
+                       return;
+               }
+               gspca_frame_add(gspca_dev, LAST_PACKET,
+                                       ffd9, 2);
+
+               /* put the JPEG header in the new frame */
+               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                       sd->jpeg_hdr, JPEG_HDR_SZ);
+
+               data += SPCA500_OFFSET_DATA;
+               len -= SPCA500_OFFSET_DATA;
+       } else {
+               data += 1;
+               len -= 1;
+       }
+
+       /* add 0x00 after 0xff */
+       i = 0;
+       do {
+               if (data[i] == 0xff) {
+                       gspca_frame_add(gspca_dev, INTER_PACKET,
+                                       data, i + 1);
+                       len -= i;
+                       data += i;
+                       *data = 0x00;
+                       i = 0;
+               }
+               i++;
+       } while (i < len);
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_w(gspca_dev, 0x00, 0x8167,
+                       (__u8) (val - 128));
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_w(gspca_dev, 0x00, 0x8168, val);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_w(gspca_dev, 0x00, 0x8169, val);
+}
+
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct gspca_dev *gspca_dev =
+               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+
+       gspca_dev->usb_err = 0;
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               setcolors(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 3);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 63, 1, 31);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 63, 1, 31);
+
+       if (hdl->error) {
+               pr_err("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,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
+       {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
+       {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
+       {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
+       {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
+       {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
+       {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
+       {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
+       {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
+       {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
+       {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
+       {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
+       {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
+       {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
+       {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/spca501.c b/drivers/media/usb/gspca/spca501.c
new file mode 100644 (file)
index 0000000..3b7f777
--- /dev/null
@@ -0,0 +1,2054 @@
+/*
+ * SPCA501 chip based cameras initialization data
+ *
+ * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "spca501"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
+MODULE_DESCRIPTION("GSPCA/SPCA501 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       unsigned short contrast;
+       __u8 brightness;
+       __u8 colors;
+       __u8 blue_balance;
+       __u8 red_balance;
+
+       char subtype;
+#define Arowana300KCMOSCamera 0
+#define IntelCreateAndShare 1
+#define KodakDVC325 2
+#define MystFromOriUnknownCamera 3
+#define SmileIntlCamera 4
+#define ThreeComHomeConnectLite 5
+#define ViewQuestM318B 6
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {160, 120, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+       {320, 240, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+#define SPCA50X_REG_USB 0x2    /* spca505 501 */
+/*
+ * Data to initialize a SPCA501. From a capture file provided by Bill Roehl
+ * With SPCA501 chip description
+ */
+#define CCDSP_SET              /* set CCDSP parameters */
+#define TG_SET                 /* set time generator set */
+#undef DSPWIN_SET              /* set DSP windows parameters */
+#undef ALTER_GAMA      /* Set alternate set to YUV transform coeffs. */
+#define SPCA501_SNAPBIT 0x80
+#define SPCA501_SNAPCTRL 0x10
+/* Frame packet header offsets for the spca501 */
+#define SPCA501_OFFSET_GPIO   1
+#define SPCA501_OFFSET_TYPE   2
+#define SPCA501_OFFSET_TURN3A 3
+#define SPCA501_OFFSET_FRAMSEQ 4
+#define SPCA501_OFFSET_COMPRESS 5
+#define SPCA501_OFFSET_QUANT 6
+#define SPCA501_OFFSET_QUANT2 7
+#define SPCA501_OFFSET_DATA 8
+
+#define SPCA501_PROP_COMP_ENABLE(d) ((d) & 1)
+#define SPCA501_PROP_SNAP(d) ((d) & 0x40)
+#define SPCA501_PROP_SNAP_CTRL(d) ((d) & 0x10)
+#define SPCA501_PROP_COMP_THRESH(d) (((d) & 0x0e) >> 1)
+#define SPCA501_PROP_COMP_QUANT(d) (((d) & 0x70) >> 4)
+
+/* SPCA501 CCDSP control */
+#define SPCA501_REG_CCDSP 0x01
+/* SPCA501 control/status registers */
+#define SPCA501_REG_CTLRL 0x02
+
+/* registers for color correction and YUV transformation */
+#define SPCA501_A11 0x08
+#define SPCA501_A12 0x09
+#define SPCA501_A13 0x0A
+#define SPCA501_A21 0x0B
+#define SPCA501_A22 0x0C
+#define SPCA501_A23 0x0D
+#define SPCA501_A31 0x0E
+#define SPCA501_A32 0x0F
+#define SPCA501_A33 0x10
+
+/* Data for video camera initialization before capturing */
+static const __u16 spca501_open_data[][3] = {
+       /* bmRequest,value,index */
+
+       {0x2, 0x50, 0x00},      /* C/S enable soft reset */
+       {0x2, 0x40, 0x00},      /* C/S disable soft reset */
+       {0x2, 0x02, 0x05},      /* C/S general purpose I/O data */
+       {0x2, 0x03, 0x05},      /* C/S general purpose I/O data */
+
+#ifdef CCDSP_SET
+       {0x1, 0x38, 0x01},      /* CCDSP options */
+       {0x1, 0x05, 0x02}, /* CCDSP Optical black level for user settings */
+       {0x1, 0xC0, 0x03},      /* CCDSP Optical black settings */
+
+       {0x1, 0x67, 0x07},
+       {0x1, 0x63, 0x3f},      /* CCDSP CCD gamma enable */
+       {0x1, 0x03, 0x56},      /* Add gamma correction */
+
+       {0x1, 0xFF, 0x15},      /* CCDSP High luminance for white balance */
+       {0x1, 0x01, 0x16},      /* CCDSP Low luminance for white balance */
+
+/* Color correction and RGB-to-YUV transformation coefficients changing */
+#ifdef ALTER_GAMA
+       {0x0, 0x00, 0x08},      /* A11 */
+       {0x0, 0x00, 0x09},      /* A12 */
+       {0x0, 0x90, 0x0A},      /* A13 */
+       {0x0, 0x12, 0x0B},      /* A21 */
+       {0x0, 0x00, 0x0C},      /* A22 */
+       {0x0, 0x00, 0x0D},      /* A23 */
+       {0x0, 0x00, 0x0E},      /* A31 */
+       {0x0, 0x02, 0x0F},      /* A32 */
+       {0x0, 0x00, 0x10},      /* A33 */
+#else
+       {0x1, 0x2a, 0x08},      /* A11 0x31 */
+       {0x1, 0xf8, 0x09},      /* A12 f8 */
+       {0x1, 0xf8, 0x0A},      /* A13 f8 */
+       {0x1, 0xf8, 0x0B},      /* A21 f8 */
+       {0x1, 0x14, 0x0C},      /* A22 0x14 */
+       {0x1, 0xf8, 0x0D},      /* A23 f8 */
+       {0x1, 0xf8, 0x0E},      /* A31 f8 */
+       {0x1, 0xf8, 0x0F},      /* A32 f8 */
+       {0x1, 0x20, 0x10},      /* A33 0x20 */
+#endif
+       {0x1, 0x00, 0x11},      /* R offset */
+       {0x1, 0x00, 0x12},      /* G offset */
+       {0x1, 0x00, 0x13},      /* B offset */
+       {0x1, 0x00, 0x14},      /* GB offset */
+
+#endif
+
+#ifdef TG_SET
+       /* Time generator manipulations */
+       {0x0, 0xfc, 0x0},       /* Set up high bits of shutter speed */
+       {0x0, 0x01, 0x1},       /* Set up low bits of shutter speed */
+
+       {0x0, 0xe4, 0x04},      /* DCLK*2 clock phase adjustment */
+       {0x0, 0x08, 0x05},      /* ADCK phase adjustment, inv. ext. VB */
+       {0x0, 0x03, 0x06},      /* FR phase adjustment */
+       {0x0, 0x01, 0x07},      /* FCDS phase adjustment */
+       {0x0, 0x39, 0x08},      /* FS phase adjustment */
+       {0x0, 0x88, 0x0a},      /* FH1 phase and delay adjustment */
+       {0x0, 0x03, 0x0f},      /* pixel identification */
+       {0x0, 0x00, 0x11},      /* clock source selection (default) */
+
+       /*VERY strange manipulations with
+        * select DMCLP or OBPX to be ADCLP output (0x0C)
+        * OPB always toggle or not (0x0D) but they allow
+        * us to set up brightness
+        */
+       {0x0, 0x01, 0x0c},
+       {0x0, 0xe0, 0x0d},
+       /* Done */
+#endif
+
+#ifdef DSPWIN_SET
+       {0x1, 0xa0, 0x01},      /* Setting image processing parameters */
+       {0x1, 0x1c, 0x17},      /* Changing Windows positions X1 */
+       {0x1, 0xe2, 0x19},      /* X2 */
+       {0x1, 0x1c, 0x1b},      /* X3 */
+       {0x1, 0xe2, 0x1d},      /* X4 */
+       {0x1, 0x5f, 0x1f},      /* X5 */
+       {0x1, 0x32, 0x20},      /* Y5 */
+       {0x1, 0x01, 0x10},      /* Changing A33 */
+#endif
+
+       {0x2, 0x204a, 0x07},/* Setting video compression & resolution 160x120 */
+       {0x2, 0x94, 0x06},      /* Setting video no compression */
+       {}
+};
+
+/*
+   The SPCAxxx docs from Sunplus document these values
+   in tables, one table per register number.  In the data
+   below, dmRequest is the register number, index is the Addr,
+   and value is a combination of Bit values.
+   Bit  Value (hex)
+   0    01
+   1    02
+   2    04
+   3    08
+   4    10
+   5    20
+   6    40
+   7    80
+ */
+
+/* Data for chip initialization (set default values) */
+static const __u16 spca501_init_data[][3] = {
+       /* Set all the values to powerup defaults */
+       /* bmRequest,value,index */
+       {0x0, 0xAA, 0x00},
+       {0x0, 0x02, 0x01},
+       {0x0, 0x01, 0x02},
+       {0x0, 0x02, 0x03},
+       {0x0, 0xCE, 0x04},
+       {0x0, 0x00, 0x05},
+       {0x0, 0x00, 0x06},
+       {0x0, 0x00, 0x07},
+       {0x0, 0x00, 0x08},
+       {0x0, 0x00, 0x09},
+       {0x0, 0x90, 0x0A},
+       {0x0, 0x12, 0x0B},
+       {0x0, 0x00, 0x0C},
+       {0x0, 0x00, 0x0D},
+       {0x0, 0x00, 0x0E},
+       {0x0, 0x02, 0x0F},
+       {0x0, 0x00, 0x10},
+       {0x0, 0x00, 0x11},
+       {0x0, 0x00, 0x12},
+       {0x0, 0x00, 0x13},
+       {0x0, 0x00, 0x14},
+       {0x0, 0x00, 0x15},
+       {0x0, 0x00, 0x16},
+       {0x0, 0x00, 0x17},
+       {0x0, 0x00, 0x18},
+       {0x0, 0x00, 0x19},
+       {0x0, 0x00, 0x1A},
+       {0x0, 0x00, 0x1B},
+       {0x0, 0x00, 0x1C},
+       {0x0, 0x00, 0x1D},
+       {0x0, 0x00, 0x1E},
+       {0x0, 0x00, 0x1F},
+       {0x0, 0x00, 0x20},
+       {0x0, 0x00, 0x21},
+       {0x0, 0x00, 0x22},
+       {0x0, 0x00, 0x23},
+       {0x0, 0x00, 0x24},
+       {0x0, 0x00, 0x25},
+       {0x0, 0x00, 0x26},
+       {0x0, 0x00, 0x27},
+       {0x0, 0x00, 0x28},
+       {0x0, 0x00, 0x29},
+       {0x0, 0x00, 0x2A},
+       {0x0, 0x00, 0x2B},
+       {0x0, 0x00, 0x2C},
+       {0x0, 0x00, 0x2D},
+       {0x0, 0x00, 0x2E},
+       {0x0, 0x00, 0x2F},
+       {0x0, 0x00, 0x30},
+       {0x0, 0x00, 0x31},
+       {0x0, 0x00, 0x32},
+       {0x0, 0x00, 0x33},
+       {0x0, 0x00, 0x34},
+       {0x0, 0x00, 0x35},
+       {0x0, 0x00, 0x36},
+       {0x0, 0x00, 0x37},
+       {0x0, 0x00, 0x38},
+       {0x0, 0x00, 0x39},
+       {0x0, 0x00, 0x3A},
+       {0x0, 0x00, 0x3B},
+       {0x0, 0x00, 0x3C},
+       {0x0, 0x00, 0x3D},
+       {0x0, 0x00, 0x3E},
+       {0x0, 0x00, 0x3F},
+       {0x0, 0x00, 0x40},
+       {0x0, 0x00, 0x41},
+       {0x0, 0x00, 0x42},
+       {0x0, 0x00, 0x43},
+       {0x0, 0x00, 0x44},
+       {0x0, 0x00, 0x45},
+       {0x0, 0x00, 0x46},
+       {0x0, 0x00, 0x47},
+       {0x0, 0x00, 0x48},
+       {0x0, 0x00, 0x49},
+       {0x0, 0x00, 0x4A},
+       {0x0, 0x00, 0x4B},
+       {0x0, 0x00, 0x4C},
+       {0x0, 0x00, 0x4D},
+       {0x0, 0x00, 0x4E},
+       {0x0, 0x00, 0x4F},
+       {0x0, 0x00, 0x50},
+       {0x0, 0x00, 0x51},
+       {0x0, 0x00, 0x52},
+       {0x0, 0x00, 0x53},
+       {0x0, 0x00, 0x54},
+       {0x0, 0x00, 0x55},
+       {0x0, 0x00, 0x56},
+       {0x0, 0x00, 0x57},
+       {0x0, 0x00, 0x58},
+       {0x0, 0x00, 0x59},
+       {0x0, 0x00, 0x5A},
+       {0x0, 0x00, 0x5B},
+       {0x0, 0x00, 0x5C},
+       {0x0, 0x00, 0x5D},
+       {0x0, 0x00, 0x5E},
+       {0x0, 0x00, 0x5F},
+       {0x0, 0x00, 0x60},
+       {0x0, 0x00, 0x61},
+       {0x0, 0x00, 0x62},
+       {0x0, 0x00, 0x63},
+       {0x0, 0x00, 0x64},
+       {0x0, 0x00, 0x65},
+       {0x0, 0x00, 0x66},
+       {0x0, 0x00, 0x67},
+       {0x0, 0x00, 0x68},
+       {0x0, 0x00, 0x69},
+       {0x0, 0x00, 0x6A},
+       {0x0, 0x00, 0x6B},
+       {0x0, 0x00, 0x6C},
+       {0x0, 0x00, 0x6D},
+       {0x0, 0x00, 0x6E},
+       {0x0, 0x00, 0x6F},
+       {0x0, 0x00, 0x70},
+       {0x0, 0x00, 0x71},
+       {0x0, 0x00, 0x72},
+       {0x0, 0x00, 0x73},
+       {0x0, 0x00, 0x74},
+       {0x0, 0x00, 0x75},
+       {0x0, 0x00, 0x76},
+       {0x0, 0x00, 0x77},
+       {0x0, 0x00, 0x78},
+       {0x0, 0x00, 0x79},
+       {0x0, 0x00, 0x7A},
+       {0x0, 0x00, 0x7B},
+       {0x0, 0x00, 0x7C},
+       {0x0, 0x00, 0x7D},
+       {0x0, 0x00, 0x7E},
+       {0x0, 0x00, 0x7F},
+       {0x0, 0x00, 0x80},
+       {0x0, 0x00, 0x81},
+       {0x0, 0x00, 0x82},
+       {0x0, 0x00, 0x83},
+       {0x0, 0x00, 0x84},
+       {0x0, 0x00, 0x85},
+       {0x0, 0x00, 0x86},
+       {0x0, 0x00, 0x87},
+       {0x0, 0x00, 0x88},
+       {0x0, 0x00, 0x89},
+       {0x0, 0x00, 0x8A},
+       {0x0, 0x00, 0x8B},
+       {0x0, 0x00, 0x8C},
+       {0x0, 0x00, 0x8D},
+       {0x0, 0x00, 0x8E},
+       {0x0, 0x00, 0x8F},
+       {0x0, 0x00, 0x90},
+       {0x0, 0x00, 0x91},
+       {0x0, 0x00, 0x92},
+       {0x0, 0x00, 0x93},
+       {0x0, 0x00, 0x94},
+       {0x0, 0x00, 0x95},
+       {0x0, 0x00, 0x96},
+       {0x0, 0x00, 0x97},
+       {0x0, 0x00, 0x98},
+       {0x0, 0x00, 0x99},
+       {0x0, 0x00, 0x9A},
+       {0x0, 0x00, 0x9B},
+       {0x0, 0x00, 0x9C},
+       {0x0, 0x00, 0x9D},
+       {0x0, 0x00, 0x9E},
+       {0x0, 0x00, 0x9F},
+       {0x0, 0x00, 0xA0},
+       {0x0, 0x00, 0xA1},
+       {0x0, 0x00, 0xA2},
+       {0x0, 0x00, 0xA3},
+       {0x0, 0x00, 0xA4},
+       {0x0, 0x00, 0xA5},
+       {0x0, 0x00, 0xA6},
+       {0x0, 0x00, 0xA7},
+       {0x0, 0x00, 0xA8},
+       {0x0, 0x00, 0xA9},
+       {0x0, 0x00, 0xAA},
+       {0x0, 0x00, 0xAB},
+       {0x0, 0x00, 0xAC},
+       {0x0, 0x00, 0xAD},
+       {0x0, 0x00, 0xAE},
+       {0x0, 0x00, 0xAF},
+       {0x0, 0x00, 0xB0},
+       {0x0, 0x00, 0xB1},
+       {0x0, 0x00, 0xB2},
+       {0x0, 0x00, 0xB3},
+       {0x0, 0x00, 0xB4},
+       {0x0, 0x00, 0xB5},
+       {0x0, 0x00, 0xB6},
+       {0x0, 0x00, 0xB7},
+       {0x0, 0x00, 0xB8},
+       {0x0, 0x00, 0xB9},
+       {0x0, 0x00, 0xBA},
+       {0x0, 0x00, 0xBB},
+       {0x0, 0x00, 0xBC},
+       {0x0, 0x00, 0xBD},
+       {0x0, 0x00, 0xBE},
+       {0x0, 0x00, 0xBF},
+       {0x0, 0x00, 0xC0},
+       {0x0, 0x00, 0xC1},
+       {0x0, 0x00, 0xC2},
+       {0x0, 0x00, 0xC3},
+       {0x0, 0x00, 0xC4},
+       {0x0, 0x00, 0xC5},
+       {0x0, 0x00, 0xC6},
+       {0x0, 0x00, 0xC7},
+       {0x0, 0x00, 0xC8},
+       {0x0, 0x00, 0xC9},
+       {0x0, 0x00, 0xCA},
+       {0x0, 0x00, 0xCB},
+       {0x0, 0x00, 0xCC},
+       {0x1, 0xF4, 0x00},
+       {0x1, 0x38, 0x01},
+       {0x1, 0x40, 0x02},
+       {0x1, 0x0A, 0x03},
+       {0x1, 0x40, 0x04},
+       {0x1, 0x40, 0x05},
+       {0x1, 0x40, 0x06},
+       {0x1, 0x67, 0x07},
+       {0x1, 0x31, 0x08},
+       {0x1, 0x00, 0x09},
+       {0x1, 0x00, 0x0A},
+       {0x1, 0x00, 0x0B},
+       {0x1, 0x14, 0x0C},
+       {0x1, 0x00, 0x0D},
+       {0x1, 0x00, 0x0E},
+       {0x1, 0x00, 0x0F},
+       {0x1, 0x1E, 0x10},
+       {0x1, 0x00, 0x11},
+       {0x1, 0x00, 0x12},
+       {0x1, 0x00, 0x13},
+       {0x1, 0x00, 0x14},
+       {0x1, 0xFF, 0x15},
+       {0x1, 0x01, 0x16},
+       {0x1, 0x32, 0x17},
+       {0x1, 0x23, 0x18},
+       {0x1, 0xCE, 0x19},
+       {0x1, 0x23, 0x1A},
+       {0x1, 0x32, 0x1B},
+       {0x1, 0x8D, 0x1C},
+       {0x1, 0xCE, 0x1D},
+       {0x1, 0x8D, 0x1E},
+       {0x1, 0x00, 0x1F},
+       {0x1, 0x00, 0x20},
+       {0x1, 0xFF, 0x3E},
+       {0x1, 0x02, 0x3F},
+       {0x1, 0x00, 0x40},
+       {0x1, 0x00, 0x41},
+       {0x1, 0x00, 0x42},
+       {0x1, 0x00, 0x43},
+       {0x1, 0x00, 0x44},
+       {0x1, 0x00, 0x45},
+       {0x1, 0x00, 0x46},
+       {0x1, 0x00, 0x47},
+       {0x1, 0x00, 0x48},
+       {0x1, 0x00, 0x49},
+       {0x1, 0x00, 0x4A},
+       {0x1, 0x00, 0x4B},
+       {0x1, 0x00, 0x4C},
+       {0x1, 0x00, 0x4D},
+       {0x1, 0x00, 0x4E},
+       {0x1, 0x00, 0x4F},
+       {0x1, 0x00, 0x50},
+       {0x1, 0x00, 0x51},
+       {0x1, 0x00, 0x52},
+       {0x1, 0x00, 0x53},
+       {0x1, 0x00, 0x54},
+       {0x1, 0x00, 0x55},
+       {0x1, 0x00, 0x56},
+       {0x1, 0x00, 0x57},
+       {0x1, 0x00, 0x58},
+       {0x1, 0x00, 0x59},
+       {0x1, 0x00, 0x5A},
+       {0x2, 0x03, 0x00},
+       {0x2, 0x00, 0x01},
+       {0x2, 0x00, 0x05},
+       {0x2, 0x00, 0x06},
+       {0x2, 0x00, 0x07},
+       {0x2, 0x00, 0x10},
+       {0x2, 0x00, 0x11},
+       /* Strange - looks like the 501 driver doesn't do anything
+        * at insert time except read the EEPROM
+        */
+       {}
+};
+
+/* Data for video camera init before capture.
+ * Capture and decoding by Colin Peart.
+ * This is is for the 3com HomeConnect Lite which is spca501a based.
+ */
+static const __u16 spca501_3com_open_data[][3] = {
+       /* bmRequest,value,index */
+       {0x2, 0x0050, 0x0000},  /* C/S Enable TG soft reset, timing mode=010 */
+       {0x2, 0x0043, 0x0000},  /* C/S Disable TG soft reset, timing mode=010 */
+       {0x2, 0x0002, 0x0005},  /* C/S GPIO */
+       {0x2, 0x0003, 0x0005},  /* C/S GPIO */
+
+#ifdef CCDSP_SET
+       {0x1, 0x0020, 0x0001},  /* CCDSP Options */
+
+       {0x1, 0x0020, 0x0002},  /* CCDSP Black Level */
+       {0x1, 0x006e, 0x0007},  /* CCDSP Gamma options */
+       {0x1, 0x0090, 0x0015},  /* CCDSP Luminance Low */
+       {0x1, 0x00ff, 0x0016},  /* CCDSP Luminance High */
+       {0x1, 0x0003, 0x003F},  /* CCDSP Gamma correction toggle */
+
+#ifdef ALTER_GAMMA
+       {0x1, 0x0010, 0x0008},  /* CCDSP YUV A11 */
+       {0x1, 0x0000, 0x0009},  /* CCDSP YUV A12 */
+       {0x1, 0x0000, 0x000a},  /* CCDSP YUV A13 */
+       {0x1, 0x0000, 0x000b},  /* CCDSP YUV A21 */
+       {0x1, 0x0010, 0x000c},  /* CCDSP YUV A22 */
+       {0x1, 0x0000, 0x000d},  /* CCDSP YUV A23 */
+       {0x1, 0x0000, 0x000e},  /* CCDSP YUV A31 */
+       {0x1, 0x0000, 0x000f},  /* CCDSP YUV A32 */
+       {0x1, 0x0010, 0x0010},  /* CCDSP YUV A33 */
+       {0x1, 0x0000, 0x0011},  /* CCDSP R Offset */
+       {0x1, 0x0000, 0x0012},  /* CCDSP G Offset */
+       {0x1, 0x0001, 0x0013},  /* CCDSP B Offset */
+       {0x1, 0x0001, 0x0014},  /* CCDSP BG Offset */
+       {0x1, 0x003f, 0x00C1},  /* CCDSP Gamma Correction Enable */
+#endif
+#endif
+
+#ifdef TG_SET
+       {0x0, 0x00fc, 0x0000},  /* TG Shutter Speed High Bits */
+       {0x0, 0x0000, 0x0001},  /* TG Shutter Speed Low Bits */
+       {0x0, 0x00e4, 0x0004},  /* TG DCLK*2 Adjust */
+       {0x0, 0x0008, 0x0005},  /* TG ADCK Adjust */
+       {0x0, 0x0003, 0x0006},  /* TG FR Phase Adjust */
+       {0x0, 0x0001, 0x0007},  /* TG FCDS Phase Adjust */
+       {0x0, 0x0039, 0x0008},  /* TG FS Phase Adjust */
+       {0x0, 0x0088, 0x000a},  /* TG MH1 */
+       {0x0, 0x0003, 0x000f},  /* TG Pixel ID */
+
+       /* Like below, unexplained toglleing */
+       {0x0, 0x0080, 0x000c},
+       {0x0, 0x0000, 0x000d},
+       {0x0, 0x0080, 0x000c},
+       {0x0, 0x0004, 0x000d},
+       {0x0, 0x0000, 0x000c},
+       {0x0, 0x0000, 0x000d},
+       {0x0, 0x0040, 0x000c},
+       {0x0, 0x0017, 0x000d},
+       {0x0, 0x00c0, 0x000c},
+       {0x0, 0x0000, 0x000d},
+       {0x0, 0x0080, 0x000c},
+       {0x0, 0x0006, 0x000d},
+       {0x0, 0x0080, 0x000c},
+       {0x0, 0x0004, 0x000d},
+       {0x0, 0x0002, 0x0003},
+#endif
+
+#ifdef DSPWIN_SET
+       {0x1, 0x001c, 0x0017},  /* CCDSP W1 Start X */
+       {0x1, 0x00e2, 0x0019},  /* CCDSP W2 Start X */
+       {0x1, 0x001c, 0x001b},  /* CCDSP W3 Start X */
+       {0x1, 0x00e2, 0x001d},  /* CCDSP W4 Start X */
+       {0x1, 0x00aa, 0x001f},  /* CCDSP W5 Start X */
+       {0x1, 0x0070, 0x0020},  /* CCDSP W5 Start Y */
+#endif
+       {0x0, 0x0001, 0x0010},  /* TG Start Clock */
+
+/*     {0x2, 0x006a, 0x0001},   * C/S Enable ISOSYNCH Packet Engine */
+       {0x2, 0x0068, 0x0001},  /* C/S Diable ISOSYNCH Packet Engine */
+       {0x2, 0x0000, 0x0005},
+       {0x2, 0x0043, 0x0000},  /* C/S Set Timing Mode, Disable TG soft reset */
+       {0x2, 0x0043, 0x0000},  /* C/S Set Timing Mode, Disable TG soft reset */
+       {0x2, 0x0002, 0x0005},  /* C/S GPIO */
+       {0x2, 0x0003, 0x0005},  /* C/S GPIO */
+
+       {0x2, 0x006a, 0x0001},  /* C/S Enable ISOSYNCH Packet Engine */
+       {}
+};
+
+/*
+ * Data used to initialize a SPCA501C with HV7131B sensor.
+ * From a capture file taken with USBSnoop v 1.5
+ * I have a "SPCA501C pc camera chipset" manual by sunplus, but some
+ * of the value meanings are obscure or simply "reserved".
+ * to do list:
+ * 1) Understand what every value means
+ * 2) Understand why some values seem to appear more than once
+ * 3) Write a small comment for each line of the following arrays.
+ */
+static const __u16 spca501c_arowana_open_data[][3] = {
+       /* bmRequest,value,index */
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x01, 0x0006, 0x0011},
+       {0x01, 0x00ff, 0x0012},
+       {0x01, 0x0014, 0x0013},
+       {0x01, 0x0000, 0x0014},
+       {0x01, 0x0042, 0x0051},
+       {0x01, 0x0040, 0x0052},
+       {0x01, 0x0051, 0x0053},
+       {0x01, 0x0040, 0x0054},
+       {0x01, 0x0000, 0x0055},
+       {0x00, 0x0025, 0x0000},
+       {0x00, 0x0026, 0x0000},
+       {0x00, 0x0001, 0x0000},
+       {0x00, 0x0027, 0x0000},
+       {0x00, 0x008a, 0x0000},
+       {}
+};
+
+static const __u16 spca501c_arowana_init_data[][3] = {
+       /* bmRequest,value,index */
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x01, 0x0006, 0x0011},
+       {0x01, 0x00ff, 0x0012},
+       {0x01, 0x0014, 0x0013},
+       {0x01, 0x0000, 0x0014},
+       {0x01, 0x0042, 0x0051},
+       {0x01, 0x0040, 0x0052},
+       {0x01, 0x0051, 0x0053},
+       {0x01, 0x0040, 0x0054},
+       {0x01, 0x0000, 0x0055},
+       {0x00, 0x0025, 0x0000},
+       {0x00, 0x0026, 0x0000},
+       {0x00, 0x0001, 0x0000},
+       {0x00, 0x0027, 0x0000},
+       {0x00, 0x008a, 0x0000},
+       {0x02, 0x0000, 0x0005},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0x2000, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x05, 0x0015, 0x0001},
+       {0x05, 0x00ea, 0x0000},
+       {0x05, 0x0021, 0x0001},
+       {0x05, 0x00d2, 0x0000},
+       {0x05, 0x0023, 0x0001},
+       {0x05, 0x0003, 0x0000},
+       {0x05, 0x0030, 0x0001},
+       {0x05, 0x002b, 0x0000},
+       {0x05, 0x0031, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0032, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0033, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0034, 0x0001},
+       {0x05, 0x0002, 0x0000},
+       {0x05, 0x0050, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0051, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0052, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0054, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x00, 0x0000, 0x0001},
+       {0x00, 0x0000, 0x0002},
+       {0x00, 0x000c, 0x0003},
+       {0x00, 0x0000, 0x0004},
+       {0x00, 0x0090, 0x0005},
+       {0x00, 0x0000, 0x0006},
+       {0x00, 0x0040, 0x0007},
+       {0x00, 0x00c0, 0x0008},
+       {0x00, 0x004a, 0x0009},
+       {0x00, 0x0000, 0x000a},
+       {0x00, 0x0000, 0x000b},
+       {0x00, 0x0001, 0x000c},
+       {0x00, 0x0001, 0x000d},
+       {0x00, 0x0000, 0x000e},
+       {0x00, 0x0002, 0x000f},
+       {0x00, 0x0001, 0x0010},
+       {0x00, 0x0000, 0x0011},
+       {0x00, 0x0000, 0x0012},
+       {0x00, 0x0002, 0x0020},
+       {0x00, 0x0080, 0x0021},
+       {0x00, 0x0001, 0x0022},
+       {0x00, 0x00e0, 0x0023},
+       {0x00, 0x0000, 0x0024},
+       {0x00, 0x00d5, 0x0025},
+       {0x00, 0x0000, 0x0026},
+       {0x00, 0x000b, 0x0027},
+       {0x00, 0x0000, 0x0046},
+       {0x00, 0x0000, 0x0047},
+       {0x00, 0x0000, 0x0048},
+       {0x00, 0x0000, 0x0049},
+       {0x00, 0x0008, 0x004a},
+       {0xff, 0x0000, 0x00d0},
+       {0xff, 0x00d8, 0x00d1},
+       {0xff, 0x0000, 0x00d4},
+       {0xff, 0x0000, 0x00d5},
+       {0x01, 0x00a6, 0x0000},
+       {0x01, 0x0028, 0x0001},
+       {0x01, 0x0000, 0x0002},
+       {0x01, 0x000a, 0x0003},
+       {0x01, 0x0040, 0x0004},
+       {0x01, 0x0066, 0x0007},
+       {0x01, 0x0011, 0x0008},
+       {0x01, 0x0032, 0x0009},
+       {0x01, 0x00fd, 0x000a},
+       {0x01, 0x0038, 0x000b},
+       {0x01, 0x00d1, 0x000c},
+       {0x01, 0x00f7, 0x000d},
+       {0x01, 0x00ed, 0x000e},
+       {0x01, 0x00d8, 0x000f},
+       {0x01, 0x0038, 0x0010},
+       {0x01, 0x00ff, 0x0015},
+       {0x01, 0x0001, 0x0016},
+       {0x01, 0x0032, 0x0017},
+       {0x01, 0x0023, 0x0018},
+       {0x01, 0x00ce, 0x0019},
+       {0x01, 0x0023, 0x001a},
+       {0x01, 0x0032, 0x001b},
+       {0x01, 0x008d, 0x001c},
+       {0x01, 0x00ce, 0x001d},
+       {0x01, 0x008d, 0x001e},
+       {0x01, 0x0000, 0x001f},
+       {0x01, 0x0000, 0x0020},
+       {0x01, 0x00ff, 0x003e},
+       {0x01, 0x0003, 0x003f},
+       {0x01, 0x0000, 0x0040},
+       {0x01, 0x0035, 0x0041},
+       {0x01, 0x0053, 0x0042},
+       {0x01, 0x0069, 0x0043},
+       {0x01, 0x007c, 0x0044},
+       {0x01, 0x008c, 0x0045},
+       {0x01, 0x009a, 0x0046},
+       {0x01, 0x00a8, 0x0047},
+       {0x01, 0x00b4, 0x0048},
+       {0x01, 0x00bf, 0x0049},
+       {0x01, 0x00ca, 0x004a},
+       {0x01, 0x00d4, 0x004b},
+       {0x01, 0x00dd, 0x004c},
+       {0x01, 0x00e7, 0x004d},
+       {0x01, 0x00ef, 0x004e},
+       {0x01, 0x00f8, 0x004f},
+       {0x01, 0x00ff, 0x0050},
+       {0x01, 0x0001, 0x0056},
+       {0x01, 0x0060, 0x0057},
+       {0x01, 0x0040, 0x0058},
+       {0x01, 0x0011, 0x0059},
+       {0x01, 0x0001, 0x005a},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0x0015, 0x0006},
+       {0x02, 0x100a, 0x0007},
+       {0x02, 0xa048, 0x0000},
+       {0x02, 0xc002, 0x0001},
+       {0x02, 0x000f, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x05, 0x0025, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0026, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x05, 0x0027, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0001, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0021, 0x0001},
+       {0x05, 0x00d2, 0x0000},
+       {0x05, 0x0020, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x00, 0x0090, 0x0005},
+       {0x01, 0x00a6, 0x0000},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0x2000, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x05, 0x0015, 0x0001},
+       {0x05, 0x00ea, 0x0000},
+       {0x05, 0x0021, 0x0001},
+       {0x05, 0x00d2, 0x0000},
+       {0x05, 0x0023, 0x0001},
+       {0x05, 0x0003, 0x0000},
+       {0x05, 0x0030, 0x0001},
+       {0x05, 0x002b, 0x0000},
+       {0x05, 0x0031, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0032, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0033, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0034, 0x0001},
+       {0x05, 0x0002, 0x0000},
+       {0x05, 0x0050, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0051, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0052, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0054, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x00, 0x0000, 0x0001},
+       {0x00, 0x0000, 0x0002},
+       {0x00, 0x000c, 0x0003},
+       {0x00, 0x0000, 0x0004},
+       {0x00, 0x0090, 0x0005},
+       {0x00, 0x0000, 0x0006},
+       {0x00, 0x0040, 0x0007},
+       {0x00, 0x00c0, 0x0008},
+       {0x00, 0x004a, 0x0009},
+       {0x00, 0x0000, 0x000a},
+       {0x00, 0x0000, 0x000b},
+       {0x00, 0x0001, 0x000c},
+       {0x00, 0x0001, 0x000d},
+       {0x00, 0x0000, 0x000e},
+       {0x00, 0x0002, 0x000f},
+       {0x00, 0x0001, 0x0010},
+       {0x00, 0x0000, 0x0011},
+       {0x00, 0x0000, 0x0012},
+       {0x00, 0x0002, 0x0020},
+       {0x00, 0x0080, 0x0021},
+       {0x00, 0x0001, 0x0022},
+       {0x00, 0x00e0, 0x0023},
+       {0x00, 0x0000, 0x0024},
+       {0x00, 0x00d5, 0x0025},
+       {0x00, 0x0000, 0x0026},
+       {0x00, 0x000b, 0x0027},
+       {0x00, 0x0000, 0x0046},
+       {0x00, 0x0000, 0x0047},
+       {0x00, 0x0000, 0x0048},
+       {0x00, 0x0000, 0x0049},
+       {0x00, 0x0008, 0x004a},
+       {0xff, 0x0000, 0x00d0},
+       {0xff, 0x00d8, 0x00d1},
+       {0xff, 0x0000, 0x00d4},
+       {0xff, 0x0000, 0x00d5},
+       {0x01, 0x00a6, 0x0000},
+       {0x01, 0x0028, 0x0001},
+       {0x01, 0x0000, 0x0002},
+       {0x01, 0x000a, 0x0003},
+       {0x01, 0x0040, 0x0004},
+       {0x01, 0x0066, 0x0007},
+       {0x01, 0x0011, 0x0008},
+       {0x01, 0x0032, 0x0009},
+       {0x01, 0x00fd, 0x000a},
+       {0x01, 0x0038, 0x000b},
+       {0x01, 0x00d1, 0x000c},
+       {0x01, 0x00f7, 0x000d},
+       {0x01, 0x00ed, 0x000e},
+       {0x01, 0x00d8, 0x000f},
+       {0x01, 0x0038, 0x0010},
+       {0x01, 0x00ff, 0x0015},
+       {0x01, 0x0001, 0x0016},
+       {0x01, 0x0032, 0x0017},
+       {0x01, 0x0023, 0x0018},
+       {0x01, 0x00ce, 0x0019},
+       {0x01, 0x0023, 0x001a},
+       {0x01, 0x0032, 0x001b},
+       {0x01, 0x008d, 0x001c},
+       {0x01, 0x00ce, 0x001d},
+       {0x01, 0x008d, 0x001e},
+       {0x01, 0x0000, 0x001f},
+       {0x01, 0x0000, 0x0020},
+       {0x01, 0x00ff, 0x003e},
+       {0x01, 0x0003, 0x003f},
+       {0x01, 0x0000, 0x0040},
+       {0x01, 0x0035, 0x0041},
+       {0x01, 0x0053, 0x0042},
+       {0x01, 0x0069, 0x0043},
+       {0x01, 0x007c, 0x0044},
+       {0x01, 0x008c, 0x0045},
+       {0x01, 0x009a, 0x0046},
+       {0x01, 0x00a8, 0x0047},
+       {0x01, 0x00b4, 0x0048},
+       {0x01, 0x00bf, 0x0049},
+       {0x01, 0x00ca, 0x004a},
+       {0x01, 0x00d4, 0x004b},
+       {0x01, 0x00dd, 0x004c},
+       {0x01, 0x00e7, 0x004d},
+       {0x01, 0x00ef, 0x004e},
+       {0x01, 0x00f8, 0x004f},
+       {0x01, 0x00ff, 0x0050},
+       {0x01, 0x0001, 0x0056},
+       {0x01, 0x0060, 0x0057},
+       {0x01, 0x0040, 0x0058},
+       {0x01, 0x0011, 0x0059},
+       {0x01, 0x0001, 0x005a},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0x0015, 0x0006},
+       {0x02, 0x100a, 0x0007},
+       {0x02, 0xa048, 0x0000},
+       {0x02, 0xc002, 0x0001},
+       {0x02, 0x000f, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x05, 0x0025, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0026, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x05, 0x0027, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0001, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0021, 0x0001},
+       {0x05, 0x00d2, 0x0000},
+       {0x05, 0x0020, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x00, 0x0090, 0x0005},
+       {0x01, 0x00a6, 0x0000},
+       {0x01, 0x0003, 0x003f},
+       {0x01, 0x0001, 0x0056},
+       {0x01, 0x0011, 0x0008},
+       {0x01, 0x0032, 0x0009},
+       {0x01, 0xfffd, 0x000a},
+       {0x01, 0x0023, 0x000b},
+       {0x01, 0xffea, 0x000c},
+       {0x01, 0xfff4, 0x000d},
+       {0x01, 0xfffc, 0x000e},
+       {0x01, 0xffe3, 0x000f},
+       {0x01, 0x001f, 0x0010},
+       {0x01, 0x00a8, 0x0001},
+       {0x01, 0x0067, 0x0007},
+       {0x01, 0x0032, 0x0017},
+       {0x01, 0x0023, 0x0018},
+       {0x01, 0x00ce, 0x0019},
+       {0x01, 0x0023, 0x001a},
+       {0x01, 0x0032, 0x001b},
+       {0x01, 0x008d, 0x001c},
+       {0x01, 0x00ce, 0x001d},
+       {0x01, 0x008d, 0x001e},
+       {0x01, 0x00c8, 0x0015},
+       {0x01, 0x0032, 0x0016},
+       {0x01, 0x0000, 0x0011},
+       {0x01, 0x0000, 0x0012},
+       {0x01, 0x0000, 0x0013},
+       {0x01, 0x000a, 0x0003},
+       {0x02, 0xc002, 0x0001},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0xc000, 0x0001},
+       {0x02, 0x0000, 0x0005},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0x2000, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x05, 0x0015, 0x0001},
+       {0x05, 0x00ea, 0x0000},
+       {0x05, 0x0021, 0x0001},
+       {0x05, 0x00d2, 0x0000},
+       {0x05, 0x0023, 0x0001},
+       {0x05, 0x0003, 0x0000},
+       {0x05, 0x0030, 0x0001},
+       {0x05, 0x002b, 0x0000},
+       {0x05, 0x0031, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0032, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0033, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0034, 0x0001},
+       {0x05, 0x0002, 0x0000},
+       {0x05, 0x0050, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0051, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0052, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0054, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x00, 0x0000, 0x0001},
+       {0x00, 0x0000, 0x0002},
+       {0x00, 0x000c, 0x0003},
+       {0x00, 0x0000, 0x0004},
+       {0x00, 0x0090, 0x0005},
+       {0x00, 0x0000, 0x0006},
+       {0x00, 0x0040, 0x0007},
+       {0x00, 0x00c0, 0x0008},
+       {0x00, 0x004a, 0x0009},
+       {0x00, 0x0000, 0x000a},
+       {0x00, 0x0000, 0x000b},
+       {0x00, 0x0001, 0x000c},
+       {0x00, 0x0001, 0x000d},
+       {0x00, 0x0000, 0x000e},
+       {0x00, 0x0002, 0x000f},
+       {0x00, 0x0001, 0x0010},
+       {0x00, 0x0000, 0x0011},
+       {0x00, 0x0000, 0x0012},
+       {0x00, 0x0002, 0x0020},
+       {0x00, 0x0080, 0x0021},
+       {0x00, 0x0001, 0x0022},
+       {0x00, 0x00e0, 0x0023},
+       {0x00, 0x0000, 0x0024},
+       {0x00, 0x00d5, 0x0025},
+       {0x00, 0x0000, 0x0026},
+       {0x00, 0x000b, 0x0027},
+       {0x00, 0x0000, 0x0046},
+       {0x00, 0x0000, 0x0047},
+       {0x00, 0x0000, 0x0048},
+       {0x00, 0x0000, 0x0049},
+       {0x00, 0x0008, 0x004a},
+       {0xff, 0x0000, 0x00d0},
+       {0xff, 0x00d8, 0x00d1},
+       {0xff, 0x0000, 0x00d4},
+       {0xff, 0x0000, 0x00d5},
+       {0x01, 0x00a6, 0x0000},
+       {0x01, 0x0028, 0x0001},
+       {0x01, 0x0000, 0x0002},
+       {0x01, 0x000a, 0x0003},
+       {0x01, 0x0040, 0x0004},
+       {0x01, 0x0066, 0x0007},
+       {0x01, 0x0011, 0x0008},
+       {0x01, 0x0032, 0x0009},
+       {0x01, 0x00fd, 0x000a},
+       {0x01, 0x0038, 0x000b},
+       {0x01, 0x00d1, 0x000c},
+       {0x01, 0x00f7, 0x000d},
+       {0x01, 0x00ed, 0x000e},
+       {0x01, 0x00d8, 0x000f},
+       {0x01, 0x0038, 0x0010},
+       {0x01, 0x00ff, 0x0015},
+       {0x01, 0x0001, 0x0016},
+       {0x01, 0x0032, 0x0017},
+       {0x01, 0x0023, 0x0018},
+       {0x01, 0x00ce, 0x0019},
+       {0x01, 0x0023, 0x001a},
+       {0x01, 0x0032, 0x001b},
+       {0x01, 0x008d, 0x001c},
+       {0x01, 0x00ce, 0x001d},
+       {0x01, 0x008d, 0x001e},
+       {0x01, 0x0000, 0x001f},
+       {0x01, 0x0000, 0x0020},
+       {0x01, 0x00ff, 0x003e},
+       {0x01, 0x0003, 0x003f},
+       {0x01, 0x0000, 0x0040},
+       {0x01, 0x0035, 0x0041},
+       {0x01, 0x0053, 0x0042},
+       {0x01, 0x0069, 0x0043},
+       {0x01, 0x007c, 0x0044},
+       {0x01, 0x008c, 0x0045},
+       {0x01, 0x009a, 0x0046},
+       {0x01, 0x00a8, 0x0047},
+       {0x01, 0x00b4, 0x0048},
+       {0x01, 0x00bf, 0x0049},
+       {0x01, 0x00ca, 0x004a},
+       {0x01, 0x00d4, 0x004b},
+       {0x01, 0x00dd, 0x004c},
+       {0x01, 0x00e7, 0x004d},
+       {0x01, 0x00ef, 0x004e},
+       {0x01, 0x00f8, 0x004f},
+       {0x01, 0x00ff, 0x0050},
+       {0x01, 0x0001, 0x0056},
+       {0x01, 0x0060, 0x0057},
+       {0x01, 0x0040, 0x0058},
+       {0x01, 0x0011, 0x0059},
+       {0x01, 0x0001, 0x005a},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0x0015, 0x0006},
+       {0x02, 0x100a, 0x0007},
+       {0x02, 0xa048, 0x0000},
+       {0x02, 0xc002, 0x0001},
+       {0x02, 0x000f, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x05, 0x0025, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0026, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x05, 0x0027, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0001, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0021, 0x0001},
+       {0x05, 0x00d2, 0x0000},
+       {0x05, 0x0020, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x00, 0x0090, 0x0005},
+       {0x01, 0x00a6, 0x0000},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0x2000, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x05, 0x0015, 0x0001},
+       {0x05, 0x00ea, 0x0000},
+       {0x05, 0x0021, 0x0001},
+       {0x05, 0x00d2, 0x0000},
+       {0x05, 0x0023, 0x0001},
+       {0x05, 0x0003, 0x0000},
+       {0x05, 0x0030, 0x0001},
+       {0x05, 0x002b, 0x0000},
+       {0x05, 0x0031, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0032, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0033, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0034, 0x0001},
+       {0x05, 0x0002, 0x0000},
+       {0x05, 0x0050, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0051, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0052, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0054, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x00, 0x0000, 0x0001},
+       {0x00, 0x0000, 0x0002},
+       {0x00, 0x000c, 0x0003},
+       {0x00, 0x0000, 0x0004},
+       {0x00, 0x0090, 0x0005},
+       {0x00, 0x0000, 0x0006},
+       {0x00, 0x0040, 0x0007},
+       {0x00, 0x00c0, 0x0008},
+       {0x00, 0x004a, 0x0009},
+       {0x00, 0x0000, 0x000a},
+       {0x00, 0x0000, 0x000b},
+       {0x00, 0x0001, 0x000c},
+       {0x00, 0x0001, 0x000d},
+       {0x00, 0x0000, 0x000e},
+       {0x00, 0x0002, 0x000f},
+       {0x00, 0x0001, 0x0010},
+       {0x00, 0x0000, 0x0011},
+       {0x00, 0x0000, 0x0012},
+       {0x00, 0x0002, 0x0020},
+       {0x00, 0x0080, 0x0021},
+       {0x00, 0x0001, 0x0022},
+       {0x00, 0x00e0, 0x0023},
+       {0x00, 0x0000, 0x0024},
+       {0x00, 0x00d5, 0x0025},
+       {0x00, 0x0000, 0x0026},
+       {0x00, 0x000b, 0x0027},
+       {0x00, 0x0000, 0x0046},
+       {0x00, 0x0000, 0x0047},
+       {0x00, 0x0000, 0x0048},
+       {0x00, 0x0000, 0x0049},
+       {0x00, 0x0008, 0x004a},
+       {0xff, 0x0000, 0x00d0},
+       {0xff, 0x00d8, 0x00d1},
+       {0xff, 0x0000, 0x00d4},
+       {0xff, 0x0000, 0x00d5},
+       {0x01, 0x00a6, 0x0000},
+       {0x01, 0x0028, 0x0001},
+       {0x01, 0x0000, 0x0002},
+       {0x01, 0x000a, 0x0003},
+       {0x01, 0x0040, 0x0004},
+       {0x01, 0x0066, 0x0007},
+       {0x01, 0x0011, 0x0008},
+       {0x01, 0x0032, 0x0009},
+       {0x01, 0x00fd, 0x000a},
+       {0x01, 0x0038, 0x000b},
+       {0x01, 0x00d1, 0x000c},
+       {0x01, 0x00f7, 0x000d},
+       {0x01, 0x00ed, 0x000e},
+       {0x01, 0x00d8, 0x000f},
+       {0x01, 0x0038, 0x0010},
+       {0x01, 0x00ff, 0x0015},
+       {0x01, 0x0001, 0x0016},
+       {0x01, 0x0032, 0x0017},
+       {0x01, 0x0023, 0x0018},
+       {0x01, 0x00ce, 0x0019},
+       {0x01, 0x0023, 0x001a},
+       {0x01, 0x0032, 0x001b},
+       {0x01, 0x008d, 0x001c},
+       {0x01, 0x00ce, 0x001d},
+       {0x01, 0x008d, 0x001e},
+       {0x01, 0x0000, 0x001f},
+       {0x01, 0x0000, 0x0020},
+       {0x01, 0x00ff, 0x003e},
+       {0x01, 0x0003, 0x003f},
+       {0x01, 0x0000, 0x0040},
+       {0x01, 0x0035, 0x0041},
+       {0x01, 0x0053, 0x0042},
+       {0x01, 0x0069, 0x0043},
+       {0x01, 0x007c, 0x0044},
+       {0x01, 0x008c, 0x0045},
+       {0x01, 0x009a, 0x0046},
+       {0x01, 0x00a8, 0x0047},
+       {0x01, 0x00b4, 0x0048},
+       {0x01, 0x00bf, 0x0049},
+       {0x01, 0x00ca, 0x004a},
+       {0x01, 0x00d4, 0x004b},
+       {0x01, 0x00dd, 0x004c},
+       {0x01, 0x00e7, 0x004d},
+       {0x01, 0x00ef, 0x004e},
+       {0x01, 0x00f8, 0x004f},
+       {0x01, 0x00ff, 0x0050},
+       {0x01, 0x0001, 0x0056},
+       {0x01, 0x0060, 0x0057},
+       {0x01, 0x0040, 0x0058},
+       {0x01, 0x0011, 0x0059},
+       {0x01, 0x0001, 0x005a},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0x0015, 0x0006},
+       {0x02, 0x100a, 0x0007},
+       {0x02, 0xa048, 0x0000},
+       {0x02, 0xc002, 0x0001},
+       {0x02, 0x000f, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x05, 0x0025, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0026, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x05, 0x0027, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0001, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0021, 0x0001},
+       {0x05, 0x00d2, 0x0000},
+       {0x05, 0x0020, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x00, 0x0090, 0x0005},
+       {0x01, 0x00a6, 0x0000},
+       {0x05, 0x0026, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x05, 0x0027, 0x0001},
+       {0x05, 0x000f, 0x0000},
+       {0x01, 0x0003, 0x003f},
+       {0x01, 0x0001, 0x0056},
+       {0x01, 0x0011, 0x0008},
+       {0x01, 0x0032, 0x0009},
+       {0x01, 0xfffd, 0x000a},
+       {0x01, 0x0023, 0x000b},
+       {0x01, 0xffea, 0x000c},
+       {0x01, 0xfff4, 0x000d},
+       {0x01, 0xfffc, 0x000e},
+       {0x01, 0xffe3, 0x000f},
+       {0x01, 0x001f, 0x0010},
+       {0x01, 0x00a8, 0x0001},
+       {0x01, 0x0067, 0x0007},
+       {0x01, 0x0042, 0x0051},
+       {0x01, 0x0051, 0x0053},
+       {0x01, 0x000a, 0x0003},
+       {0x02, 0xc002, 0x0001},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0xc000, 0x0001},
+       {0x02, 0x0000, 0x0005},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0x2000, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x05, 0x0015, 0x0001},
+       {0x05, 0x00ea, 0x0000},
+       {0x05, 0x0021, 0x0001},
+       {0x05, 0x00d2, 0x0000},
+       {0x05, 0x0023, 0x0001},
+       {0x05, 0x0003, 0x0000},
+       {0x05, 0x0030, 0x0001},
+       {0x05, 0x002b, 0x0000},
+       {0x05, 0x0031, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0032, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0033, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0034, 0x0001},
+       {0x05, 0x0002, 0x0000},
+       {0x05, 0x0050, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0051, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0052, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0054, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x00, 0x0000, 0x0001},
+       {0x00, 0x0000, 0x0002},
+       {0x00, 0x000c, 0x0003},
+       {0x00, 0x0000, 0x0004},
+       {0x00, 0x0090, 0x0005},
+       {0x00, 0x0000, 0x0006},
+       {0x00, 0x0040, 0x0007},
+       {0x00, 0x00c0, 0x0008},
+       {0x00, 0x004a, 0x0009},
+       {0x00, 0x0000, 0x000a},
+       {0x00, 0x0000, 0x000b},
+       {0x00, 0x0001, 0x000c},
+       {0x00, 0x0001, 0x000d},
+       {0x00, 0x0000, 0x000e},
+       {0x00, 0x0002, 0x000f},
+       {0x00, 0x0001, 0x0010},
+       {0x00, 0x0000, 0x0011},
+       {0x00, 0x0000, 0x0012},
+       {0x00, 0x0002, 0x0020},
+       {0x00, 0x0080, 0x0021},
+       {0x00, 0x0001, 0x0022},
+       {0x00, 0x00e0, 0x0023},
+       {0x00, 0x0000, 0x0024},
+       {0x00, 0x00d5, 0x0025},
+       {0x00, 0x0000, 0x0026},
+       {0x00, 0x000b, 0x0027},
+       {0x00, 0x0000, 0x0046},
+       {0x00, 0x0000, 0x0047},
+       {0x00, 0x0000, 0x0048},
+       {0x00, 0x0000, 0x0049},
+       {0x00, 0x0008, 0x004a},
+       {0xff, 0x0000, 0x00d0},
+       {0xff, 0x00d8, 0x00d1},
+       {0xff, 0x0000, 0x00d4},
+       {0xff, 0x0000, 0x00d5},
+       {0x01, 0x00a6, 0x0000},
+       {0x01, 0x0028, 0x0001},
+       {0x01, 0x0000, 0x0002},
+       {0x01, 0x000a, 0x0003},
+       {0x01, 0x0040, 0x0004},
+       {0x01, 0x0066, 0x0007},
+       {0x01, 0x0011, 0x0008},
+       {0x01, 0x0032, 0x0009},
+       {0x01, 0x00fd, 0x000a},
+       {0x01, 0x0038, 0x000b},
+       {0x01, 0x00d1, 0x000c},
+       {0x01, 0x00f7, 0x000d},
+       {0x01, 0x00ed, 0x000e},
+       {0x01, 0x00d8, 0x000f},
+       {0x01, 0x0038, 0x0010},
+       {0x01, 0x00ff, 0x0015},
+       {0x01, 0x0001, 0x0016},
+       {0x01, 0x0032, 0x0017},
+       {0x01, 0x0023, 0x0018},
+       {0x01, 0x00ce, 0x0019},
+       {0x01, 0x0023, 0x001a},
+       {0x01, 0x0032, 0x001b},
+       {0x01, 0x008d, 0x001c},
+       {0x01, 0x00ce, 0x001d},
+       {0x01, 0x008d, 0x001e},
+       {0x01, 0x0000, 0x001f},
+       {0x01, 0x0000, 0x0020},
+       {0x01, 0x00ff, 0x003e},
+       {0x01, 0x0003, 0x003f},
+       {0x01, 0x0000, 0x0040},
+       {0x01, 0x0035, 0x0041},
+       {0x01, 0x0053, 0x0042},
+       {0x01, 0x0069, 0x0043},
+       {0x01, 0x007c, 0x0044},
+       {0x01, 0x008c, 0x0045},
+       {0x01, 0x009a, 0x0046},
+       {0x01, 0x00a8, 0x0047},
+       {0x01, 0x00b4, 0x0048},
+       {0x01, 0x00bf, 0x0049},
+       {0x01, 0x00ca, 0x004a},
+       {0x01, 0x00d4, 0x004b},
+       {0x01, 0x00dd, 0x004c},
+       {0x01, 0x00e7, 0x004d},
+       {0x01, 0x00ef, 0x004e},
+       {0x01, 0x00f8, 0x004f},
+       {0x01, 0x00ff, 0x0050},
+       {0x01, 0x0001, 0x0056},
+       {0x01, 0x0060, 0x0057},
+       {0x01, 0x0040, 0x0058},
+       {0x01, 0x0011, 0x0059},
+       {0x01, 0x0001, 0x005a},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0x0015, 0x0006},
+       {0x02, 0x100a, 0x0007},
+       {0x02, 0xa048, 0x0000},
+       {0x02, 0xc002, 0x0001},
+       {0x02, 0x000f, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x05, 0x0025, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0026, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x05, 0x0027, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0001, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0021, 0x0001},
+       {0x05, 0x00d2, 0x0000},
+       {0x05, 0x0020, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x00, 0x0090, 0x0005},
+       {0x01, 0x00a6, 0x0000},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0x2000, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x05, 0x0015, 0x0001},
+       {0x05, 0x00ea, 0x0000},
+       {0x05, 0x0021, 0x0001},
+       {0x05, 0x00d2, 0x0000},
+       {0x05, 0x0023, 0x0001},
+       {0x05, 0x0003, 0x0000},
+       {0x05, 0x0030, 0x0001},
+       {0x05, 0x002b, 0x0000},
+       {0x05, 0x0031, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0032, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0033, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0034, 0x0001},
+       {0x05, 0x0002, 0x0000},
+       {0x05, 0x0050, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0051, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0052, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0054, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x00, 0x0000, 0x0001},
+       {0x00, 0x0000, 0x0002},
+       {0x00, 0x000c, 0x0003},
+       {0x00, 0x0000, 0x0004},
+       {0x00, 0x0090, 0x0005},
+       {0x00, 0x0000, 0x0006},
+       {0x00, 0x0040, 0x0007},
+       {0x00, 0x00c0, 0x0008},
+       {0x00, 0x004a, 0x0009},
+       {0x00, 0x0000, 0x000a},
+       {0x00, 0x0000, 0x000b},
+       {0x00, 0x0001, 0x000c},
+       {0x00, 0x0001, 0x000d},
+       {0x00, 0x0000, 0x000e},
+       {0x00, 0x0002, 0x000f},
+       {0x00, 0x0001, 0x0010},
+       {0x00, 0x0000, 0x0011},
+       {0x00, 0x0000, 0x0012},
+       {0x00, 0x0002, 0x0020},
+       {0x00, 0x0080, 0x0021},
+       {0x00, 0x0001, 0x0022},
+       {0x00, 0x00e0, 0x0023},
+       {0x00, 0x0000, 0x0024},
+       {0x00, 0x00d5, 0x0025},
+       {0x00, 0x0000, 0x0026},
+       {0x00, 0x000b, 0x0027},
+       {0x00, 0x0000, 0x0046},
+       {0x00, 0x0000, 0x0047},
+       {0x00, 0x0000, 0x0048},
+       {0x00, 0x0000, 0x0049},
+       {0x00, 0x0008, 0x004a},
+       {0xff, 0x0000, 0x00d0},
+       {0xff, 0x00d8, 0x00d1},
+       {0xff, 0x0000, 0x00d4},
+       {0xff, 0x0000, 0x00d5},
+       {0x01, 0x00a6, 0x0000},
+       {0x01, 0x0028, 0x0001},
+       {0x01, 0x0000, 0x0002},
+       {0x01, 0x000a, 0x0003},
+       {0x01, 0x0040, 0x0004},
+       {0x01, 0x0066, 0x0007},
+       {0x01, 0x0011, 0x0008},
+       {0x01, 0x0032, 0x0009},
+       {0x01, 0x00fd, 0x000a},
+       {0x01, 0x0038, 0x000b},
+       {0x01, 0x00d1, 0x000c},
+       {0x01, 0x00f7, 0x000d},
+       {0x01, 0x00ed, 0x000e},
+       {0x01, 0x00d8, 0x000f},
+       {0x01, 0x0038, 0x0010},
+       {0x01, 0x00ff, 0x0015},
+       {0x01, 0x0001, 0x0016},
+       {0x01, 0x0032, 0x0017},
+       {0x01, 0x0023, 0x0018},
+       {0x01, 0x00ce, 0x0019},
+       {0x01, 0x0023, 0x001a},
+       {0x01, 0x0032, 0x001b},
+       {0x01, 0x008d, 0x001c},
+       {0x01, 0x00ce, 0x001d},
+       {0x01, 0x008d, 0x001e},
+       {0x01, 0x0000, 0x001f},
+       {0x01, 0x0000, 0x0020},
+       {0x01, 0x00ff, 0x003e},
+       {0x01, 0x0003, 0x003f},
+       {0x01, 0x0000, 0x0040},
+       {0x01, 0x0035, 0x0041},
+       {0x01, 0x0053, 0x0042},
+       {0x01, 0x0069, 0x0043},
+       {0x01, 0x007c, 0x0044},
+       {0x01, 0x008c, 0x0045},
+       {0x01, 0x009a, 0x0046},
+       {0x01, 0x00a8, 0x0047},
+       {0x01, 0x00b4, 0x0048},
+       {0x01, 0x00bf, 0x0049},
+       {0x01, 0x00ca, 0x004a},
+       {0x01, 0x00d4, 0x004b},
+       {0x01, 0x00dd, 0x004c},
+       {0x01, 0x00e7, 0x004d},
+       {0x01, 0x00ef, 0x004e},
+       {0x01, 0x00f8, 0x004f},
+       {0x01, 0x00ff, 0x0050},
+       {0x01, 0x0001, 0x0056},
+       {0x01, 0x0060, 0x0057},
+       {0x01, 0x0040, 0x0058},
+       {0x01, 0x0011, 0x0059},
+       {0x01, 0x0001, 0x005a},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0x0015, 0x0006},
+       {0x02, 0x100a, 0x0007},
+       {0x02, 0xa048, 0x0000},
+       {0x02, 0xc002, 0x0001},
+       {0x02, 0x000f, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x05, 0x0025, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0026, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x05, 0x0027, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0001, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0021, 0x0001},
+       {0x05, 0x00d2, 0x0000},
+       {0x05, 0x0020, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x00, 0x0090, 0x0005},
+       {0x01, 0x00a6, 0x0000},
+       {0x05, 0x0026, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x05, 0x0027, 0x0001},
+       {0x05, 0x001e, 0x0000},
+       {0x01, 0x0003, 0x003f},
+       {0x01, 0x0001, 0x0056},
+       {0x01, 0x0011, 0x0008},
+       {0x01, 0x0032, 0x0009},
+       {0x01, 0xfffd, 0x000a},
+       {0x01, 0x0023, 0x000b},
+       {0x01, 0xffea, 0x000c},
+       {0x01, 0xfff4, 0x000d},
+       {0x01, 0xfffc, 0x000e},
+       {0x01, 0xffe3, 0x000f},
+       {0x01, 0x001f, 0x0010},
+       {0x01, 0x00a8, 0x0001},
+       {0x01, 0x0067, 0x0007},
+       {0x01, 0x0042, 0x0051},
+       {0x01, 0x0051, 0x0053},
+       {0x01, 0x000a, 0x0003},
+       {0x02, 0xc002, 0x0001},
+       {0x02, 0x0007, 0x0005},
+       {0x01, 0x0042, 0x0051},
+       {0x01, 0x0051, 0x0053},
+       {0x05, 0x0026, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x05, 0x0027, 0x0001},
+       {0x05, 0x002d, 0x0000},
+       {0x01, 0x0003, 0x003f},
+       {0x01, 0x0001, 0x0056},
+       {0x02, 0xc000, 0x0001},
+       {0x02, 0x0000, 0x0005},
+       {}
+};
+
+/* Unknown camera from Ori Usbid 0x0000:0x0000 */
+/* Based on snoops from Ori Cohen */
+static const __u16 spca501c_mysterious_open_data[][3] = {
+       {0x02, 0x000f, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x05, 0x0022, 0x0004},
+/* DSP Registers */
+       {0x01, 0x0016, 0x0011}, /* RGB offset */
+       {0x01, 0x0000, 0x0012},
+       {0x01, 0x0006, 0x0013},
+       {0x01, 0x0078, 0x0051},
+       {0x01, 0x0040, 0x0052},
+       {0x01, 0x0046, 0x0053},
+       {0x01, 0x0040, 0x0054},
+       {0x00, 0x0025, 0x0000},
+/*     {0x00, 0x0000, 0x0000 }, */
+/* Part 2 */
+/* TG Registers */
+       {0x00, 0x0026, 0x0000},
+       {0x00, 0x0001, 0x0000},
+       {0x00, 0x0027, 0x0000},
+       {0x00, 0x008a, 0x0000},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0x2000, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x05, 0x0015, 0x0001},
+       {0x05, 0x00ea, 0x0000},
+       {0x05, 0x0021, 0x0001},
+       {0x05, 0x00d2, 0x0000},
+       {0x05, 0x0023, 0x0001},
+       {0x05, 0x0003, 0x0000},
+       {0x05, 0x0030, 0x0001},
+       {0x05, 0x002b, 0x0000},
+       {0x05, 0x0031, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0032, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0033, 0x0001},
+       {0x05, 0x0023, 0x0000},
+       {0x05, 0x0034, 0x0001},
+       {0x05, 0x0002, 0x0000},
+       {0x05, 0x0050, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0051, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0052, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0054, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {}
+};
+
+/* Based on snoops from Ori Cohen */
+static const __u16 spca501c_mysterious_init_data[][3] = {
+/* Part 3 */
+/* TG registers */
+/*     {0x00, 0x0000, 0x0000}, */
+       {0x00, 0x0000, 0x0001},
+       {0x00, 0x0000, 0x0002},
+       {0x00, 0x0006, 0x0003},
+       {0x00, 0x0000, 0x0004},
+       {0x00, 0x0090, 0x0005},
+       {0x00, 0x0000, 0x0006},
+       {0x00, 0x0040, 0x0007},
+       {0x00, 0x00c0, 0x0008},
+       {0x00, 0x004a, 0x0009},
+       {0x00, 0x0000, 0x000a},
+       {0x00, 0x0000, 0x000b},
+       {0x00, 0x0001, 0x000c},
+       {0x00, 0x0001, 0x000d},
+       {0x00, 0x0000, 0x000e},
+       {0x00, 0x0002, 0x000f},
+       {0x00, 0x0001, 0x0010},
+       {0x00, 0x0000, 0x0011},
+       {0x00, 0x0001, 0x0012},
+       {0x00, 0x0002, 0x0020},
+       {0x00, 0x0080, 0x0021}, /* 640 */
+       {0x00, 0x0001, 0x0022},
+       {0x00, 0x00e0, 0x0023}, /* 480 */
+       {0x00, 0x0000, 0x0024}, /* Offset H hight */
+       {0x00, 0x00d3, 0x0025}, /* low */
+       {0x00, 0x0000, 0x0026}, /* Offset V */
+       {0x00, 0x000d, 0x0027}, /* low */
+       {0x00, 0x0000, 0x0046},
+       {0x00, 0x0000, 0x0047},
+       {0x00, 0x0000, 0x0048},
+       {0x00, 0x0000, 0x0049},
+       {0x00, 0x0008, 0x004a},
+/* DSP Registers       */
+       {0x01, 0x00a6, 0x0000},
+       {0x01, 0x0028, 0x0001},
+       {0x01, 0x0000, 0x0002},
+       {0x01, 0x000a, 0x0003}, /* Level Calc bit7 ->1 Auto */
+       {0x01, 0x0040, 0x0004},
+       {0x01, 0x0066, 0x0007},
+       {0x01, 0x000f, 0x0008}, /* A11 Color correction coeff */
+       {0x01, 0x002d, 0x0009}, /* A12 */
+       {0x01, 0x0005, 0x000a}, /* A13 */
+       {0x01, 0x0023, 0x000b}, /* A21 */
+       {0x01, 0x00e0, 0x000c}, /* A22 */
+       {0x01, 0x00fd, 0x000d}, /* A23 */
+       {0x01, 0x00f4, 0x000e}, /* A31 */
+       {0x01, 0x00e4, 0x000f}, /* A32 */
+       {0x01, 0x0028, 0x0010}, /* A33 */
+       {0x01, 0x00ff, 0x0015}, /* Reserved */
+       {0x01, 0x0001, 0x0016}, /* Reserved */
+       {0x01, 0x0032, 0x0017}, /* Win1 Start begin */
+       {0x01, 0x0023, 0x0018},
+       {0x01, 0x00ce, 0x0019},
+       {0x01, 0x0023, 0x001a},
+       {0x01, 0x0032, 0x001b},
+       {0x01, 0x008d, 0x001c},
+       {0x01, 0x00ce, 0x001d},
+       {0x01, 0x008d, 0x001e},
+       {0x01, 0x0000, 0x001f},
+       {0x01, 0x0000, 0x0020}, /* Win1 Start end */
+       {0x01, 0x00ff, 0x003e}, /* Reserved begin */
+       {0x01, 0x0002, 0x003f},
+       {0x01, 0x0000, 0x0040},
+       {0x01, 0x0035, 0x0041},
+       {0x01, 0x0053, 0x0042},
+       {0x01, 0x0069, 0x0043},
+       {0x01, 0x007c, 0x0044},
+       {0x01, 0x008c, 0x0045},
+       {0x01, 0x009a, 0x0046},
+       {0x01, 0x00a8, 0x0047},
+       {0x01, 0x00b4, 0x0048},
+       {0x01, 0x00bf, 0x0049},
+       {0x01, 0x00ca, 0x004a},
+       {0x01, 0x00d4, 0x004b},
+       {0x01, 0x00dd, 0x004c},
+       {0x01, 0x00e7, 0x004d},
+       {0x01, 0x00ef, 0x004e},
+       {0x01, 0x00f8, 0x004f},
+       {0x01, 0x00ff, 0x0050},
+       {0x01, 0x0003, 0x0056}, /* Reserved end */
+       {0x01, 0x0060, 0x0057}, /* Edge Gain */
+       {0x01, 0x0040, 0x0058},
+       {0x01, 0x0011, 0x0059}, /* Edge Bandwidth */
+       {0x01, 0x0001, 0x005a},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x02, 0x0007, 0x0005},
+       {0x02, 0x0015, 0x0006},
+       {0x02, 0x200a, 0x0007},
+       {0x02, 0xa048, 0x0000},
+       {0x02, 0xc000, 0x0001},
+       {0x02, 0x000f, 0x0005},
+       {0x02, 0xa048, 0x0000},
+       {0x05, 0x0022, 0x0004},
+       {0x05, 0x0025, 0x0001},
+       {0x05, 0x0000, 0x0000},
+/* Part 4 */
+       {0x05, 0x0026, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x05, 0x0027, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0001, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x05, 0x0021, 0x0001},
+       {0x05, 0x00d2, 0x0000},
+       {0x05, 0x0020, 0x0001},
+       {0x05, 0x0000, 0x0000},
+       {0x00, 0x0090, 0x0005},
+       {0x01, 0x00a6, 0x0000},
+       {0x02, 0x0000, 0x0005},
+       {0x05, 0x0026, 0x0001},
+       {0x05, 0x0001, 0x0000},
+       {0x05, 0x0027, 0x0001},
+       {0x05, 0x004e, 0x0000},
+/* Part 5 */
+       {0x01, 0x0003, 0x003f},
+       {0x01, 0x0001, 0x0056},
+       {0x01, 0x000f, 0x0008},
+       {0x01, 0x002d, 0x0009},
+       {0x01, 0x0005, 0x000a},
+       {0x01, 0x0023, 0x000b},
+       {0x01, 0xffe0, 0x000c},
+       {0x01, 0xfffd, 0x000d},
+       {0x01, 0xfff4, 0x000e},
+       {0x01, 0xffe4, 0x000f},
+       {0x01, 0x0028, 0x0010},
+       {0x01, 0x00a8, 0x0001},
+       {0x01, 0x0066, 0x0007},
+       {0x01, 0x0032, 0x0017},
+       {0x01, 0x0023, 0x0018},
+       {0x01, 0x00ce, 0x0019},
+       {0x01, 0x0023, 0x001a},
+       {0x01, 0x0032, 0x001b},
+       {0x01, 0x008d, 0x001c},
+       {0x01, 0x00ce, 0x001d},
+       {0x01, 0x008d, 0x001e},
+       {0x01, 0x00c8, 0x0015}, /* c8 Poids fort Luma */
+       {0x01, 0x0032, 0x0016}, /* 32 */
+       {0x01, 0x0016, 0x0011}, /* R 00 */
+       {0x01, 0x0016, 0x0012}, /* G 00 */
+       {0x01, 0x0016, 0x0013}, /* B 00 */
+       {0x01, 0x000a, 0x0003},
+       {0x02, 0xc002, 0x0001},
+       {0x02, 0x0007, 0x0005},
+       {}
+};
+
+static int reg_write(struct usb_device *dev,
+                    __u16 req, __u16 index, __u16 value)
+{
+       int ret;
+
+       ret = usb_control_msg(dev,
+                       usb_sndctrlpipe(dev, 0),
+                       req,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index, NULL, 0, 500);
+       PDEBUG(D_USBO, "reg write: 0x%02x 0x%02x 0x%02x",
+               req, index, value);
+       if (ret < 0)
+               pr_err("reg write: error %d\n", ret);
+       return ret;
+}
+
+
+static int write_vector(struct gspca_dev *gspca_dev,
+                       const __u16 data[][3])
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret, i = 0;
+
+       while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
+               ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
+               if (ret < 0) {
+                       PDEBUG(D_ERR,
+                               "Reg write failed for 0x%02x,0x%02x,0x%02x",
+                               data[i][0], data[i][1], data[i][2]);
+                       return ret;
+               }
+               i++;
+       }
+       return 0;
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x12, val);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_write(gspca_dev->dev, 0x00, 0x00,
+                                 (val >> 8) & 0xff);
+       reg_write(gspca_dev->dev, 0x00, 0x01,
+                                 val & 0xff);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x0c, val);
+}
+
+static void setblue_balance(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x11, val);
+}
+
+static void setred_balance(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x13, val);
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+
+       cam = &gspca_dev->cam;
+       cam->cam_mode = vga_mode;
+       cam->nmodes = ARRAY_SIZE(vga_mode);
+       sd->subtype = id->driver_info;
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->subtype) {
+       case Arowana300KCMOSCamera:
+       case SmileIntlCamera:
+               /* Arowana 300k CMOS Camera data */
+               if (write_vector(gspca_dev, spca501c_arowana_init_data))
+                       goto error;
+               break;
+       case MystFromOriUnknownCamera:
+               /* Unknown Ori CMOS Camera data */
+               if (write_vector(gspca_dev, spca501c_mysterious_open_data))
+                       goto error;
+               break;
+       default:
+               /* generic spca501 init data */
+               if (write_vector(gspca_dev, spca501_init_data))
+                       goto error;
+               break;
+       }
+       PDEBUG(D_STREAM, "Initializing SPCA501 finished");
+       return 0;
+error:
+       return -EINVAL;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct usb_device *dev = gspca_dev->dev;
+       int mode;
+
+       switch (sd->subtype) {
+       case ThreeComHomeConnectLite:
+               /* Special handling for 3com data */
+               write_vector(gspca_dev, spca501_3com_open_data);
+               break;
+       case Arowana300KCMOSCamera:
+       case SmileIntlCamera:
+               /* Arowana 300k CMOS Camera data */
+               write_vector(gspca_dev, spca501c_arowana_open_data);
+               break;
+       case MystFromOriUnknownCamera:
+               /* Unknown CMOS Camera data */
+               write_vector(gspca_dev, spca501c_mysterious_init_data);
+               break;
+       default:
+               /* Generic 501 open data */
+               write_vector(gspca_dev, spca501_open_data);
+       }
+
+       /* memorize the wanted pixel format */
+       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+
+       /* Enable ISO packet machine CTRL reg=2,
+        * index=1 bitmask=0x2 (bit ordinal 1) */
+       reg_write(dev, SPCA50X_REG_USB, 0x6, 0x94);
+       switch (mode) {
+       case 0: /* 640x480 */
+               reg_write(dev, SPCA50X_REG_USB, 0x07, 0x004a);
+               break;
+       case 1: /* 320x240 */
+               reg_write(dev, SPCA50X_REG_USB, 0x07, 0x104a);
+               break;
+       default:
+/*     case 2:  * 160x120 */
+               reg_write(dev, SPCA50X_REG_USB, 0x07, 0x204a);
+               break;
+       }
+       reg_write(dev, SPCA501_REG_CTLRL, 0x01, 0x02);
+
+       return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       /* Disable ISO packet
+        * machine CTRL reg=2, index=1 bitmask=0x0 (bit ordinal 1) */
+       reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00);
+}
+
+/* called on streamoff with alt 0 and on disconnect */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       if (!gspca_dev->present)
+               return;
+       reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,                       /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       switch (data[0]) {
+       case 0:                         /* start of frame */
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+               data += SPCA501_OFFSET_DATA;
+               len -= SPCA501_OFFSET_DATA;
+               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
+               return;
+       case 0xff:                      /* drop */
+/*             gspca_dev->last_packet_type = DISCARD_PACKET; */
+               return;
+       }
+       data++;
+       len--;
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct gspca_dev *gspca_dev =
+               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+
+       gspca_dev->usb_err = 0;
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               setcolors(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               setblue_balance(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_RED_BALANCE:
+               setred_balance(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 5);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 127, 1, 0);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 64725, 1, 64725);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 63, 1, 20);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BLUE_BALANCE, 0, 127, 1, 0);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_RED_BALANCE, 0, 127, 1, 0);
+
+       if (hdl->error) {
+               pr_err("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,
+       .stopN = sd_stopN,
+       .stop0 = sd_stop0,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x040a, 0x0002), .driver_info = KodakDVC325},
+       {USB_DEVICE(0x0497, 0xc001), .driver_info = SmileIntlCamera},
+       {USB_DEVICE(0x0506, 0x00df), .driver_info = ThreeComHomeConnectLite},
+       {USB_DEVICE(0x0733, 0x0401), .driver_info = IntelCreateAndShare},
+       {USB_DEVICE(0x0733, 0x0402), .driver_info = ViewQuestM318B},
+       {USB_DEVICE(0x1776, 0x501c), .driver_info = Arowana300KCMOSCamera},
+       {USB_DEVICE(0x0000, 0x0000), .driver_info = MystFromOriUnknownCamera},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/spca505.c b/drivers/media/usb/gspca/spca505.c
new file mode 100644 (file)
index 0000000..bc7d67c
--- /dev/null
@@ -0,0 +1,807 @@
+/*
+ * SPCA505 chip based cameras initialization data
+ *
+ * V4L2 by Jean-Francis Moine <http://moinejf.free.fr>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "spca505"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
+MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;             /* !! must be the first item */
+
+       u8 subtype;
+#define IntelPCCameraPro 0
+#define Nxultra 1
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 4},
+       {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 3},
+       {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+       {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+#define SPCA50X_OFFSET_DATA 10
+
+#define SPCA50X_REG_USB 0x02   /* spca505 501 */
+
+#define SPCA50X_USB_CTRL 0x00  /* spca505 */
+#define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */
+
+#define SPCA50X_REG_GLOBAL 0x03        /* spca505 */
+#define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */
+#define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */
+
+#define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */
+#define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */
+#define SPCA50X_GMISC3_SAA7113RST 0x20 /* Not sure about this one spca505 */
+
+/* Image format and compression control */
+#define SPCA50X_REG_COMPRESS 0x04
+
+/*
+ * Data to initialize a SPCA505. Common to the CCD and external modes
+ */
+static const u8 spca505_init_data[][3] = {
+       /* bmRequest,value,index */
+       {SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},
+       /* Sensor reset */
+       {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},
+       {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},
+       /* Block USB reset */
+       {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, SPCA50X_GLOBAL_MISC0},
+
+       {0x05, 0x01, 0x10},
+                                       /* Maybe power down some stuff */
+       {0x05, 0x0f, 0x11},
+
+       /* Setup internal CCD  ? */
+       {0x06, 0x10, 0x08},
+       {0x06, 0x00, 0x09},
+       {0x06, 0x00, 0x0a},
+       {0x06, 0x00, 0x0b},
+       {0x06, 0x10, 0x0c},
+       {0x06, 0x00, 0x0d},
+       {0x06, 0x00, 0x0e},
+       {0x06, 0x00, 0x0f},
+       {0x06, 0x10, 0x10},
+       {0x06, 0x02, 0x11},
+       {0x06, 0x00, 0x12},
+       {0x06, 0x04, 0x13},
+       {0x06, 0x02, 0x14},
+       {0x06, 0x8a, 0x51},
+       {0x06, 0x40, 0x52},
+       {0x06, 0xb6, 0x53},
+       {0x06, 0x3d, 0x54},
+       {}
+};
+
+/*
+ * Data to initialize the camera using the internal CCD
+ */
+static const u8 spca505_open_data_ccd[][3] = {
+       /* bmRequest,value,index */
+       /* Internal CCD data set */
+       {0x03, 0x04, 0x01},
+       /* This could be a reset */
+       {0x03, 0x00, 0x01},
+
+       /* Setup compression and image registers. 0x6 and 0x7 seem to be
+          related to H&V hold, and are resolution mode specific */
+               {0x04, 0x10, 0x01},
+               /* DIFF(0x50), was (0x10) */
+       {0x04, 0x00, 0x04},
+       {0x04, 0x00, 0x05},
+       {0x04, 0x20, 0x06},
+       {0x04, 0x20, 0x07},
+
+       {0x08, 0x0a, 0x00},
+       /* DIFF (0x4a), was (0xa) */
+
+       {0x05, 0x00, 0x10},
+       {0x05, 0x00, 0x11},
+       {0x05, 0x00, 0x00},
+       /* DIFF not written */
+       {0x05, 0x00, 0x01},
+       /* DIFF not written */
+       {0x05, 0x00, 0x02},
+       /* DIFF not written */
+       {0x05, 0x00, 0x03},
+       /* DIFF not written */
+       {0x05, 0x00, 0x04},
+       /* DIFF not written */
+               {0x05, 0x80, 0x05},
+               /* DIFF not written */
+               {0x05, 0xe0, 0x06},
+               /* DIFF not written */
+               {0x05, 0x20, 0x07},
+               /* DIFF not written */
+               {0x05, 0xa0, 0x08},
+               /* DIFF not written */
+               {0x05, 0x0, 0x12},
+               /* DIFF not written */
+       {0x05, 0x02, 0x0f},
+       /* DIFF not written */
+               {0x05, 0x10, 0x46},
+               /* DIFF not written */
+               {0x05, 0x8, 0x4a},
+               /* DIFF not written */
+
+       {0x03, 0x08, 0x03},
+       /* DIFF (0x3,0x28,0x3) */
+       {0x03, 0x08, 0x01},
+       {0x03, 0x0c, 0x03},
+       /* DIFF not written */
+               {0x03, 0x21, 0x00},
+               /* DIFF (0x39) */
+
+/* Extra block copied from init to hopefully ensure CCD is in a sane state */
+       {0x06, 0x10, 0x08},
+       {0x06, 0x00, 0x09},
+       {0x06, 0x00, 0x0a},
+       {0x06, 0x00, 0x0b},
+       {0x06, 0x10, 0x0c},
+       {0x06, 0x00, 0x0d},
+       {0x06, 0x00, 0x0e},
+       {0x06, 0x00, 0x0f},
+       {0x06, 0x10, 0x10},
+       {0x06, 0x02, 0x11},
+       {0x06, 0x00, 0x12},
+       {0x06, 0x04, 0x13},
+       {0x06, 0x02, 0x14},
+       {0x06, 0x8a, 0x51},
+       {0x06, 0x40, 0x52},
+       {0x06, 0xb6, 0x53},
+       {0x06, 0x3d, 0x54},
+       /* End of extra block */
+
+               {0x06, 0x3f, 0x1},
+               /* Block skipped */
+       {0x06, 0x10, 0x02},
+       {0x06, 0x64, 0x07},
+       {0x06, 0x10, 0x08},
+       {0x06, 0x00, 0x09},
+       {0x06, 0x00, 0x0a},
+       {0x06, 0x00, 0x0b},
+       {0x06, 0x10, 0x0c},
+       {0x06, 0x00, 0x0d},
+       {0x06, 0x00, 0x0e},
+       {0x06, 0x00, 0x0f},
+       {0x06, 0x10, 0x10},
+       {0x06, 0x02, 0x11},
+       {0x06, 0x00, 0x12},
+       {0x06, 0x04, 0x13},
+       {0x06, 0x02, 0x14},
+       {0x06, 0x8a, 0x51},
+       {0x06, 0x40, 0x52},
+       {0x06, 0xb6, 0x53},
+       {0x06, 0x3d, 0x54},
+       {0x06, 0x60, 0x57},
+       {0x06, 0x20, 0x58},
+       {0x06, 0x15, 0x59},
+       {0x06, 0x05, 0x5a},
+
+       {0x05, 0x01, 0xc0},
+       {0x05, 0x10, 0xcb},
+               {0x05, 0x80, 0xc1},
+               /* */
+               {0x05, 0x0, 0xc2},
+               /* 4 was 0 */
+       {0x05, 0x00, 0xca},
+               {0x05, 0x80, 0xc1},
+               /*  */
+       {0x05, 0x04, 0xc2},
+       {0x05, 0x00, 0xca},
+               {0x05, 0x0, 0xc1},
+               /*  */
+       {0x05, 0x00, 0xc2},
+       {0x05, 0x00, 0xca},
+               {0x05, 0x40, 0xc1},
+               /* */
+       {0x05, 0x17, 0xc2},
+       {0x05, 0x00, 0xca},
+               {0x05, 0x80, 0xc1},
+               /* */
+       {0x05, 0x06, 0xc2},
+       {0x05, 0x00, 0xca},
+               {0x05, 0x80, 0xc1},
+               /* */
+       {0x05, 0x04, 0xc2},
+       {0x05, 0x00, 0xca},
+
+       {0x03, 0x4c, 0x3},
+       {0x03, 0x18, 0x1},
+
+       {0x06, 0x70, 0x51},
+       {0x06, 0xbe, 0x53},
+       {0x06, 0x71, 0x57},
+       {0x06, 0x20, 0x58},
+       {0x06, 0x05, 0x59},
+       {0x06, 0x15, 0x5a},
+
+       {0x04, 0x00, 0x08},
+       /* Compress = OFF (0x1 to turn on) */
+       {0x04, 0x12, 0x09},
+       {0x04, 0x21, 0x0a},
+       {0x04, 0x10, 0x0b},
+       {0x04, 0x21, 0x0c},
+       {0x04, 0x05, 0x00},
+       /* was 5 (Image Type ? ) */
+       {0x04, 0x00, 0x01},
+
+       {0x06, 0x3f, 0x01},
+
+       {0x04, 0x00, 0x04},
+       {0x04, 0x00, 0x05},
+       {0x04, 0x40, 0x06},
+       {0x04, 0x40, 0x07},
+
+       {0x06, 0x1c, 0x17},
+       {0x06, 0xe2, 0x19},
+       {0x06, 0x1c, 0x1b},
+       {0x06, 0xe2, 0x1d},
+       {0x06, 0xaa, 0x1f},
+       {0x06, 0x70, 0x20},
+
+       {0x05, 0x01, 0x10},
+       {0x05, 0x00, 0x11},
+       {0x05, 0x01, 0x00},
+       {0x05, 0x05, 0x01},
+               {0x05, 0x00, 0xc1},
+               /* */
+       {0x05, 0x00, 0xc2},
+       {0x05, 0x00, 0xca},
+
+       {0x06, 0x70, 0x51},
+       {0x06, 0xbe, 0x53},
+       {}
+};
+
+/*
+ * Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)
+ * SPCA505b chip based cameras initialization data
+ */
+/* jfm */
+#define initial_brightness 0x7f        /* 0x0(white)-0xff(black) */
+/* #define initial_brightness 0x0      //0x0(white)-0xff(black) */
+/*
+ * Data to initialize a SPCA505. Common to the CCD and external modes
+ */
+static const u8 spca505b_init_data[][3] = {
+/* start */
+       {0x02, 0x00, 0x00},             /* init */
+       {0x02, 0x00, 0x01},
+       {0x02, 0x00, 0x02},
+       {0x02, 0x00, 0x03},
+       {0x02, 0x00, 0x04},
+       {0x02, 0x00, 0x05},
+       {0x02, 0x00, 0x06},
+       {0x02, 0x00, 0x07},
+       {0x02, 0x00, 0x08},
+       {0x02, 0x00, 0x09},
+       {0x03, 0x00, 0x00},
+       {0x03, 0x00, 0x01},
+       {0x03, 0x00, 0x02},
+       {0x03, 0x00, 0x03},
+       {0x03, 0x00, 0x04},
+       {0x03, 0x00, 0x05},
+       {0x03, 0x00, 0x06},
+       {0x04, 0x00, 0x00},
+       {0x04, 0x00, 0x02},
+       {0x04, 0x00, 0x04},
+       {0x04, 0x00, 0x05},
+       {0x04, 0x00, 0x06},
+       {0x04, 0x00, 0x07},
+       {0x04, 0x00, 0x08},
+       {0x04, 0x00, 0x09},
+       {0x04, 0x00, 0x0a},
+       {0x04, 0x00, 0x0b},
+       {0x04, 0x00, 0x0c},
+       {0x07, 0x00, 0x00},
+       {0x07, 0x00, 0x03},
+       {0x08, 0x00, 0x00},
+       {0x08, 0x00, 0x01},
+       {0x08, 0x00, 0x02},
+       {0x06, 0x18, 0x08},
+       {0x06, 0xfc, 0x09},
+       {0x06, 0xfc, 0x0a},
+       {0x06, 0xfc, 0x0b},
+       {0x06, 0x18, 0x0c},
+       {0x06, 0xfc, 0x0d},
+       {0x06, 0xfc, 0x0e},
+       {0x06, 0xfc, 0x0f},
+       {0x06, 0x18, 0x10},
+       {0x06, 0xfe, 0x12},
+       {0x06, 0x00, 0x11},
+       {0x06, 0x00, 0x14},
+       {0x06, 0x00, 0x13},
+       {0x06, 0x28, 0x51},
+       {0x06, 0xff, 0x53},
+       {0x02, 0x00, 0x08},
+
+       {0x03, 0x00, 0x03},
+       {0x03, 0x10, 0x03},
+       {}
+};
+
+/*
+ * Data to initialize the camera using the internal CCD
+ */
+static const u8 spca505b_open_data_ccd[][3] = {
+
+/* {0x02,0x00,0x00}, */
+       {0x03, 0x04, 0x01},             /* rst */
+       {0x03, 0x00, 0x01},
+       {0x03, 0x00, 0x00},
+       {0x03, 0x21, 0x00},
+       {0x03, 0x00, 0x04},
+       {0x03, 0x00, 0x03},
+       {0x03, 0x18, 0x03},
+       {0x03, 0x08, 0x01},
+       {0x03, 0x1c, 0x03},
+       {0x03, 0x5c, 0x03},
+       {0x03, 0x5c, 0x03},
+       {0x03, 0x18, 0x01},
+
+/* same as 505 */
+       {0x04, 0x10, 0x01},
+       {0x04, 0x00, 0x04},
+       {0x04, 0x00, 0x05},
+       {0x04, 0x20, 0x06},
+       {0x04, 0x20, 0x07},
+
+       {0x08, 0x0a, 0x00},
+
+       {0x05, 0x00, 0x10},
+       {0x05, 0x00, 0x11},
+       {0x05, 0x00, 0x12},
+       {0x05, 0x6f, 0x00},
+       {0x05, initial_brightness >> 6, 0x00},
+       {0x05, (initial_brightness << 2) & 0xff, 0x01},
+       {0x05, 0x00, 0x02},
+       {0x05, 0x01, 0x03},
+       {0x05, 0x00, 0x04},
+       {0x05, 0x03, 0x05},
+       {0x05, 0xe0, 0x06},
+       {0x05, 0x20, 0x07},
+       {0x05, 0xa0, 0x08},
+       {0x05, 0x00, 0x12},
+       {0x05, 0x02, 0x0f},
+       {0x05, 0x80, 0x14},             /* max exposure off (0=on) */
+       {0x05, 0x01, 0xb0},
+       {0x05, 0x01, 0xbf},
+       {0x03, 0x02, 0x06},
+       {0x05, 0x10, 0x46},
+       {0x05, 0x08, 0x4a},
+
+       {0x06, 0x00, 0x01},
+       {0x06, 0x10, 0x02},
+       {0x06, 0x64, 0x07},
+       {0x06, 0x18, 0x08},
+       {0x06, 0xfc, 0x09},
+       {0x06, 0xfc, 0x0a},
+       {0x06, 0xfc, 0x0b},
+       {0x04, 0x00, 0x01},
+       {0x06, 0x18, 0x0c},
+       {0x06, 0xfc, 0x0d},
+       {0x06, 0xfc, 0x0e},
+       {0x06, 0xfc, 0x0f},
+       {0x06, 0x11, 0x10},             /* contrast */
+       {0x06, 0x00, 0x11},
+       {0x06, 0xfe, 0x12},
+       {0x06, 0x00, 0x13},
+       {0x06, 0x00, 0x14},
+       {0x06, 0x9d, 0x51},
+       {0x06, 0x40, 0x52},
+       {0x06, 0x7c, 0x53},
+       {0x06, 0x40, 0x54},
+       {0x06, 0x02, 0x57},
+       {0x06, 0x03, 0x58},
+       {0x06, 0x15, 0x59},
+       {0x06, 0x05, 0x5a},
+       {0x06, 0x03, 0x56},
+       {0x06, 0x02, 0x3f},
+       {0x06, 0x00, 0x40},
+       {0x06, 0x39, 0x41},
+       {0x06, 0x69, 0x42},
+       {0x06, 0x87, 0x43},
+       {0x06, 0x9e, 0x44},
+       {0x06, 0xb1, 0x45},
+       {0x06, 0xbf, 0x46},
+       {0x06, 0xcc, 0x47},
+       {0x06, 0xd5, 0x48},
+       {0x06, 0xdd, 0x49},
+       {0x06, 0xe3, 0x4a},
+       {0x06, 0xe8, 0x4b},
+       {0x06, 0xed, 0x4c},
+       {0x06, 0xf2, 0x4d},
+       {0x06, 0xf7, 0x4e},
+       {0x06, 0xfc, 0x4f},
+       {0x06, 0xff, 0x50},
+
+       {0x05, 0x01, 0xc0},
+       {0x05, 0x10, 0xcb},
+       {0x05, 0x40, 0xc1},
+       {0x05, 0x04, 0xc2},
+       {0x05, 0x00, 0xca},
+       {0x05, 0x40, 0xc1},
+       {0x05, 0x09, 0xc2},
+       {0x05, 0x00, 0xca},
+       {0x05, 0xc0, 0xc1},
+       {0x05, 0x09, 0xc2},
+       {0x05, 0x00, 0xca},
+       {0x05, 0x40, 0xc1},
+       {0x05, 0x59, 0xc2},
+       {0x05, 0x00, 0xca},
+       {0x04, 0x00, 0x01},
+       {0x05, 0x80, 0xc1},
+       {0x05, 0xec, 0xc2},
+       {0x05, 0x0, 0xca},
+
+       {0x06, 0x02, 0x57},
+       {0x06, 0x01, 0x58},
+       {0x06, 0x15, 0x59},
+       {0x06, 0x0a, 0x5a},
+       {0x06, 0x01, 0x57},
+       {0x06, 0x8a, 0x03},
+       {0x06, 0x0a, 0x6c},
+       {0x06, 0x30, 0x01},
+       {0x06, 0x20, 0x02},
+       {0x06, 0x00, 0x03},
+
+       {0x05, 0x8c, 0x25},
+
+       {0x06, 0x4d, 0x51},             /* maybe saturation (4d) */
+       {0x06, 0x84, 0x53},             /* making green (84) */
+       {0x06, 0x00, 0x57},             /* sharpness (1) */
+       {0x06, 0x18, 0x08},
+       {0x06, 0xfc, 0x09},
+       {0x06, 0xfc, 0x0a},
+       {0x06, 0xfc, 0x0b},
+       {0x06, 0x18, 0x0c},             /* maybe hue (18) */
+       {0x06, 0xfc, 0x0d},
+       {0x06, 0xfc, 0x0e},
+       {0x06, 0xfc, 0x0f},
+       {0x06, 0x18, 0x10},             /* maybe contrast (18) */
+
+       {0x05, 0x01, 0x02},
+
+       {0x04, 0x00, 0x08},             /* compression */
+       {0x04, 0x12, 0x09},
+       {0x04, 0x21, 0x0a},
+       {0x04, 0x10, 0x0b},
+       {0x04, 0x21, 0x0c},
+       {0x04, 0x1d, 0x00},             /* imagetype (1d) */
+       {0x04, 0x41, 0x01},             /* hardware snapcontrol */
+
+       {0x04, 0x00, 0x04},
+       {0x04, 0x00, 0x05},
+       {0x04, 0x10, 0x06},
+       {0x04, 0x10, 0x07},
+       {0x04, 0x40, 0x06},
+       {0x04, 0x40, 0x07},
+       {0x04, 0x00, 0x04},
+       {0x04, 0x00, 0x05},
+
+       {0x06, 0x1c, 0x17},
+       {0x06, 0xe2, 0x19},
+       {0x06, 0x1c, 0x1b},
+       {0x06, 0xe2, 0x1d},
+       {0x06, 0x5f, 0x1f},
+       {0x06, 0x32, 0x20},
+
+       {0x05, initial_brightness >> 6, 0x00},
+       {0x05, (initial_brightness << 2) & 0xff, 0x01},
+       {0x05, 0x06, 0xc1},
+       {0x05, 0x58, 0xc2},
+       {0x05, 0x00, 0xca},
+       {0x05, 0x00, 0x11},
+       {}
+};
+
+static int reg_write(struct usb_device *dev,
+                    u16 req, u16 index, u16 value)
+{
+       int ret;
+
+       ret = usb_control_msg(dev,
+                       usb_sndctrlpipe(dev, 0),
+                       req,
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index, NULL, 0, 500);
+       PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
+               req, index, value, ret);
+       if (ret < 0)
+               pr_err("reg write: error %d\n", ret);
+       return ret;
+}
+
+/* returns: negative is error, pos or zero is data */
+static int reg_read(struct gspca_dev *gspca_dev,
+                       u16 req,        /* bRequest */
+                       u16 index)      /* wIndex */
+{
+       int ret;
+
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       req,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,                      /* value */
+                       index,
+                       gspca_dev->usb_buf, 2,
+                       500);                   /* timeout */
+       if (ret < 0)
+               return ret;
+       return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
+}
+
+static int write_vector(struct gspca_dev *gspca_dev,
+                       const u8 data[][3])
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret, i = 0;
+
+       while (data[i][0] != 0) {
+               ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
+               if (ret < 0)
+                       return ret;
+               i++;
+       }
+       return 0;
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+
+       cam = &gspca_dev->cam;
+       cam->cam_mode = vga_mode;
+       sd->subtype = id->driver_info;
+       if (sd->subtype != IntelPCCameraPro)
+               cam->nmodes = ARRAY_SIZE(vga_mode);
+       else                    /* no 640x480 for IntelPCCameraPro */
+               cam->nmodes = ARRAY_SIZE(vga_mode) - 1;
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (write_vector(gspca_dev,
+                        sd->subtype == Nxultra
+                               ? spca505b_init_data
+                               : spca505_init_data))
+               return -EIO;
+       return 0;
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
+{
+       reg_write(gspca_dev->dev, 0x05, 0x00, (255 - brightness) >> 6);
+       reg_write(gspca_dev->dev, 0x05, 0x01, (255 - brightness) << 2);
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct usb_device *dev = gspca_dev->dev;
+       int ret, mode;
+       static u8 mode_tb[][3] = {
+       /*        r00   r06   r07       */
+               {0x00, 0x10, 0x10},     /* 640x480 */
+               {0x01, 0x1a, 0x1a},     /* 352x288 */
+               {0x02, 0x1c, 0x1d},     /* 320x240 */
+               {0x04, 0x34, 0x34},     /* 176x144 */
+               {0x05, 0x40, 0x40}      /* 160x120 */
+       };
+
+       if (sd->subtype == Nxultra)
+               write_vector(gspca_dev, spca505b_open_data_ccd);
+       else
+               write_vector(gspca_dev, spca505_open_data_ccd);
+       ret = reg_read(gspca_dev, 0x06, 0x16);
+
+       if (ret < 0) {
+               PDEBUG(D_ERR|D_CONF,
+                      "register read failed err: %d",
+                      ret);
+               return ret;
+       }
+       if (ret != 0x0101) {
+               pr_err("After vector read returns 0x%04x should be 0x0101\n",
+                      ret);
+       }
+
+       ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a);
+       if (ret < 0)
+               return ret;
+       reg_write(gspca_dev->dev, 0x05, 0xc2, 0x12);
+
+       /* necessary because without it we can see stream
+        * only once after loading module */
+       /* stopping usb registers Tomasz change */
+       reg_write(dev, 0x02, 0x00, 0x00);
+
+       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+       reg_write(dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);
+       reg_write(dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);
+       reg_write(dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);
+
+       return reg_write(dev, SPCA50X_REG_USB,
+                        SPCA50X_USB_CTRL,
+                        SPCA50X_CUSB_ENABLE);
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       /* Disable ISO packet machine */
+       reg_write(gspca_dev->dev, 0x02, 0x00, 0x00);
+}
+
+/* called on streamoff with alt 0 and on disconnect */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       if (!gspca_dev->present)
+               return;
+
+       /* This maybe reset or power control */
+       reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
+       reg_write(gspca_dev->dev, 0x03, 0x01, 0x00);
+       reg_write(gspca_dev->dev, 0x03, 0x00, 0x01);
+       reg_write(gspca_dev->dev, 0x05, 0x10, 0x01);
+       reg_write(gspca_dev->dev, 0x05, 0x11, 0x0f);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,                       /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       switch (data[0]) {
+       case 0:                         /* start of frame */
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+               data += SPCA50X_OFFSET_DATA;
+               len -= SPCA50X_OFFSET_DATA;
+               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
+               break;
+       case 0xff:                      /* drop */
+               break;
+       default:
+               data += 1;
+               len -= 1;
+               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+               break;
+       }
+}
+
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct gspca_dev *gspca_dev =
+               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+
+       gspca_dev->usb_err = 0;
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 5);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
+
+       if (hdl->error) {
+               pr_err("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_controls = sd_init_controls,
+       .init = sd_init,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .stop0 = sd_stop0,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra},
+       {USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro},
+/*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/spca506.c b/drivers/media/usb/gspca/spca506.c
new file mode 100644 (file)
index 0000000..969bb5a
--- /dev/null
@@ -0,0 +1,612 @@
+/*
+ * SPCA506 chip based cameras function
+ * M Xhaard 15/04/2004 based on different work Mark Taylor and others
+ * and my own snoopy file on a pv-321c donate by a german compagny
+ *                "Firma Frank Gmbh" from  Saarbruecken
+ *
+ * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define MODULE_NAME "spca506"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
+MODULE_DESCRIPTION("GSPCA/SPCA506 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       char norme;
+       char channel;
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 5},
+       {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 4},
+       {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+       {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+#define SPCA50X_OFFSET_DATA 10
+
+#define SAA7113_bright 0x0a    /* defaults 0x80 */
+#define SAA7113_contrast 0x0b  /* defaults 0x47 */
+#define SAA7113_saturation 0x0c        /* defaults 0x40 */
+#define SAA7113_hue 0x0d       /* defaults 0x00 */
+#define SAA7113_I2C_BASE_WRITE 0x4a
+
+/* read 'len' bytes to gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev,
+                 __u16 req,
+                 __u16 index,
+                 __u16 length)
+{
+       usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       req,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,              /* value */
+                       index, gspca_dev->usb_buf, length,
+                       500);
+}
+
+static void reg_w(struct usb_device *dev,
+                 __u16 req,
+                 __u16 value,
+                 __u16 index)
+{
+       usb_control_msg(dev,
+                       usb_sndctrlpipe(dev, 0),
+                       req,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index,
+                       NULL, 0, 500);
+}
+
+static void spca506_Initi2c(struct gspca_dev *gspca_dev)
+{
+       reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);
+}
+
+static void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur,
+                            __u16 reg)
+{
+       int retry = 60;
+
+       reg_w(gspca_dev->dev, 0x07, reg, 0x0001);
+       reg_w(gspca_dev->dev, 0x07, valeur, 0x0000);
+       while (retry--) {
+               reg_r(gspca_dev, 0x07, 0x0003, 2);
+               if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00)
+                       break;
+       }
+}
+
+static void spca506_SetNormeInput(struct gspca_dev *gspca_dev,
+                                __u16 norme,
+                                __u16 channel)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+/* fixme: check if channel == 0..3 and 6..9 (8 values) */
+       __u8 setbit0 = 0x00;
+       __u8 setbit1 = 0x00;
+       __u8 videomask = 0x00;
+
+       PDEBUG(D_STREAM, "** Open Set Norme **");
+       spca506_Initi2c(gspca_dev);
+       /* NTSC bit0 -> 1(525 l) PAL SECAM bit0 -> 0 (625 l) */
+       /* Composite channel bit1 -> 1 S-video bit 1 -> 0 */
+       /* and exclude SAA7113 reserved channel set default 0 otherwise */
+       if (norme & V4L2_STD_NTSC)
+               setbit0 = 0x01;
+       if (channel == 4 || channel == 5 || channel > 9)
+               channel = 0;
+       if (channel < 4)
+               setbit1 = 0x02;
+       videomask = (0x48 | setbit0 | setbit1);
+       reg_w(gspca_dev->dev, 0x08, videomask, 0x0000);
+       spca506_WriteI2c(gspca_dev, (0xc0 | (channel & 0x0F)), 0x02);
+
+       if (norme & V4L2_STD_NTSC)
+               spca506_WriteI2c(gspca_dev, 0x33, 0x0e);
+                                       /* Chrominance Control NTSC N */
+       else if (norme & V4L2_STD_SECAM)
+               spca506_WriteI2c(gspca_dev, 0x53, 0x0e);
+                                       /* Chrominance Control SECAM */
+       else
+               spca506_WriteI2c(gspca_dev, 0x03, 0x0e);
+                                       /* Chrominance Control PAL BGHIV */
+
+       sd->norme = norme;
+       sd->channel = channel;
+       PDEBUG(D_STREAM, "Set Video Byte to 0x%2x", videomask);
+       PDEBUG(D_STREAM, "Set Norme: %08x Channel %d", norme, channel);
+}
+
+static void spca506_GetNormeInput(struct gspca_dev *gspca_dev,
+                                 __u16 *norme, __u16 *channel)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* Read the register is not so good value change so
+          we use your own copy in spca50x struct */
+       *norme = sd->norme;
+       *channel = sd->channel;
+       PDEBUG(D_STREAM, "Get Norme: %d Channel %d", *norme, *channel);
+}
+
+static void spca506_Setsize(struct gspca_dev *gspca_dev, __u16 code,
+                           __u16 xmult, __u16 ymult)
+{
+       struct usb_device *dev = gspca_dev->dev;
+
+       PDEBUG(D_STREAM, "** SetSize **");
+       reg_w(dev, 0x04, (0x18 | (code & 0x07)), 0x0000);
+       /* Soft snap 0x40 Hard 0x41 */
+       reg_w(dev, 0x04, 0x41, 0x0001);
+       reg_w(dev, 0x04, 0x00, 0x0002);
+       /* reserved */
+       reg_w(dev, 0x04, 0x00, 0x0003);
+
+       /* reserved */
+       reg_w(dev, 0x04, 0x00, 0x0004);
+       /* reserved */
+       reg_w(dev, 0x04, 0x01, 0x0005);
+       /* reserced */
+       reg_w(dev, 0x04, xmult, 0x0006);
+       /* reserved */
+       reg_w(dev, 0x04, ymult, 0x0007);
+       /* compression 1 */
+       reg_w(dev, 0x04, 0x00, 0x0008);
+       /* T=64 -> 2 */
+       reg_w(dev, 0x04, 0x00, 0x0009);
+       /* threshold2D */
+       reg_w(dev, 0x04, 0x21, 0x000a);
+       /* quantization */
+       reg_w(dev, 0x04, 0x00, 0x000b);
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct cam *cam;
+
+       cam = &gspca_dev->cam;
+       cam->cam_mode = vga_mode;
+       cam->nmodes = ARRAY_SIZE(vga_mode);
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct usb_device *dev = gspca_dev->dev;
+
+       reg_w(dev, 0x03, 0x00, 0x0004);
+       reg_w(dev, 0x03, 0xFF, 0x0003);
+       reg_w(dev, 0x03, 0x00, 0x0000);
+       reg_w(dev, 0x03, 0x1c, 0x0001);
+       reg_w(dev, 0x03, 0x18, 0x0001);
+       /* Init on PAL and composite input0 */
+       spca506_SetNormeInput(gspca_dev, 0, 0);
+       reg_w(dev, 0x03, 0x1c, 0x0001);
+       reg_w(dev, 0x03, 0x18, 0x0001);
+       reg_w(dev, 0x05, 0x00, 0x0000);
+       reg_w(dev, 0x05, 0xef, 0x0001);
+       reg_w(dev, 0x05, 0x00, 0x00c1);
+       reg_w(dev, 0x05, 0x00, 0x00c2);
+       reg_w(dev, 0x06, 0x18, 0x0002);
+       reg_w(dev, 0x06, 0xf5, 0x0011);
+       reg_w(dev, 0x06, 0x02, 0x0012);
+       reg_w(dev, 0x06, 0xfb, 0x0013);
+       reg_w(dev, 0x06, 0x00, 0x0014);
+       reg_w(dev, 0x06, 0xa4, 0x0051);
+       reg_w(dev, 0x06, 0x40, 0x0052);
+       reg_w(dev, 0x06, 0x71, 0x0053);
+       reg_w(dev, 0x06, 0x40, 0x0054);
+       /************************************************/
+       reg_w(dev, 0x03, 0x00, 0x0004);
+       reg_w(dev, 0x03, 0x00, 0x0003);
+       reg_w(dev, 0x03, 0x00, 0x0004);
+       reg_w(dev, 0x03, 0xFF, 0x0003);
+       reg_w(dev, 0x02, 0x00, 0x0000);
+       reg_w(dev, 0x03, 0x60, 0x0000);
+       reg_w(dev, 0x03, 0x18, 0x0001);
+       /* for a better reading mx :)     */
+       /*sdca506_WriteI2c(value,register) */
+       spca506_Initi2c(gspca_dev);
+       spca506_WriteI2c(gspca_dev, 0x08, 0x01);
+       spca506_WriteI2c(gspca_dev, 0xc0, 0x02);
+                                               /* input composite video */
+       spca506_WriteI2c(gspca_dev, 0x33, 0x03);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x04);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x05);
+       spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
+       spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
+       spca506_WriteI2c(gspca_dev, 0x98, 0x08);
+       spca506_WriteI2c(gspca_dev, 0x03, 0x09);
+       spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
+       spca506_WriteI2c(gspca_dev, 0x47, 0x0b);
+       spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
+       spca506_WriteI2c(gspca_dev, 0x03, 0x0e);        /* Chroma Pal adjust */
+       spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x10);
+       spca506_WriteI2c(gspca_dev, 0x0c, 0x11);
+       spca506_WriteI2c(gspca_dev, 0xb8, 0x12);
+       spca506_WriteI2c(gspca_dev, 0x01, 0x13);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x14);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x15);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x16);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x17);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x18);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x19);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
+       spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
+       spca506_WriteI2c(gspca_dev, 0x02, 0x40);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x41);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x42);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x43);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x44);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x45);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x46);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x47);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x48);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x49);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x50);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x51);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x52);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x53);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x54);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x55);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x56);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x57);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x58);
+       spca506_WriteI2c(gspca_dev, 0x54, 0x59);
+       spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
+       spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x60);
+       spca506_WriteI2c(gspca_dev, 0x05, 0x61);
+       spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
+       PDEBUG(D_STREAM, "** Close Init *");
+       return 0;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       __u16 norme;
+       __u16 channel;
+
+       /**************************************/
+       reg_w(dev, 0x03, 0x00, 0x0004);
+       reg_w(dev, 0x03, 0x00, 0x0003);
+       reg_w(dev, 0x03, 0x00, 0x0004);
+       reg_w(dev, 0x03, 0xFF, 0x0003);
+       reg_w(dev, 0x02, 0x00, 0x0000);
+       reg_w(dev, 0x03, 0x60, 0x0000);
+       reg_w(dev, 0x03, 0x18, 0x0001);
+
+       /*sdca506_WriteI2c(value,register) */
+       spca506_Initi2c(gspca_dev);
+       spca506_WriteI2c(gspca_dev, 0x08, 0x01);        /* Increment Delay */
+/*     spca506_WriteI2c(gspca_dev, 0xc0, 0x02); * Analog Input Control 1 */
+       spca506_WriteI2c(gspca_dev, 0x33, 0x03);
+                                               /* Analog Input Control 2 */
+       spca506_WriteI2c(gspca_dev, 0x00, 0x04);
+                                               /* Analog Input Control 3 */
+       spca506_WriteI2c(gspca_dev, 0x00, 0x05);
+                                               /* Analog Input Control 4 */
+       spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
+                                       /* Horizontal Sync Start 0xe9-0x0d */
+       spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
+                                       /* Horizontal Sync Stop  0x0d-0xf0 */
+
+       spca506_WriteI2c(gspca_dev, 0x98, 0x08);        /* Sync Control */
+/*             Defaults value                  */
+       spca506_WriteI2c(gspca_dev, 0x03, 0x09);        /* Luminance Control */
+       spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
+                                               /* Luminance Brightness */
+       spca506_WriteI2c(gspca_dev, 0x47, 0x0b);        /* Luminance Contrast */
+       spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
+                                               /* Chrominance Saturation */
+       spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
+                                               /* Chrominance Hue Control */
+       spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
+                                               /* Chrominance Gain Control */
+       /**************************************/
+       spca506_WriteI2c(gspca_dev, 0x00, 0x10);
+                                               /* Format/Delay Control */
+       spca506_WriteI2c(gspca_dev, 0x0c, 0x11);        /* Output Control 1 */
+       spca506_WriteI2c(gspca_dev, 0xb8, 0x12);        /* Output Control 2 */
+       spca506_WriteI2c(gspca_dev, 0x01, 0x13);        /* Output Control 3 */
+       spca506_WriteI2c(gspca_dev, 0x00, 0x14);        /* reserved */
+       spca506_WriteI2c(gspca_dev, 0x00, 0x15);        /* VGATE START */
+       spca506_WriteI2c(gspca_dev, 0x00, 0x16);        /* VGATE STOP */
+       spca506_WriteI2c(gspca_dev, 0x00, 0x17);    /* VGATE Control (MSB) */
+       spca506_WriteI2c(gspca_dev, 0x00, 0x18);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x19);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
+       spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
+       spca506_WriteI2c(gspca_dev, 0x02, 0x40);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x41);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x42);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x43);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x44);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x45);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x46);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x47);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x48);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x49);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x50);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x51);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x52);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x53);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x54);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x55);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x56);
+       spca506_WriteI2c(gspca_dev, 0xff, 0x57);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x58);
+       spca506_WriteI2c(gspca_dev, 0x54, 0x59);
+       spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
+       spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
+       spca506_WriteI2c(gspca_dev, 0x00, 0x60);
+       spca506_WriteI2c(gspca_dev, 0x05, 0x61);
+       spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
+       /**************************************/
+       reg_w(dev, 0x05, 0x00, 0x0003);
+       reg_w(dev, 0x05, 0x00, 0x0004);
+       reg_w(dev, 0x03, 0x10, 0x0001);
+       reg_w(dev, 0x03, 0x78, 0x0000);
+       switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
+       case 0:
+               spca506_Setsize(gspca_dev, 0, 0x10, 0x10);
+               break;
+       case 1:
+               spca506_Setsize(gspca_dev, 1, 0x1a, 0x1a);
+               break;
+       case 2:
+               spca506_Setsize(gspca_dev, 2, 0x1c, 0x1c);
+               break;
+       case 4:
+               spca506_Setsize(gspca_dev, 4, 0x34, 0x34);
+               break;
+       default:
+/*     case 5: */
+               spca506_Setsize(gspca_dev, 5, 0x40, 0x40);
+               break;
+       }
+
+       /* compress setting and size */
+       /* set i2c luma */
+       reg_w(dev, 0x02, 0x01, 0x0000);
+       reg_w(dev, 0x03, 0x12, 0x0000);
+       reg_r(gspca_dev, 0x04, 0x0001, 2);
+       PDEBUG(D_STREAM, "webcam started");
+       spca506_GetNormeInput(gspca_dev, &norme, &channel);
+       spca506_SetNormeInput(gspca_dev, norme, channel);
+       return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct usb_device *dev = gspca_dev->dev;
+
+       reg_w(dev, 0x02, 0x00, 0x0000);
+       reg_w(dev, 0x03, 0x00, 0x0004);
+       reg_w(dev, 0x03, 0x00, 0x0003);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,                       /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       switch (data[0]) {
+       case 0:                         /* start of frame */
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+               data += SPCA50X_OFFSET_DATA;
+               len -= SPCA50X_OFFSET_DATA;
+               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
+               break;
+       case 0xff:                      /* drop */
+/*             gspca_dev->last_packet_type = DISCARD_PACKET; */
+               break;
+       default:
+               data += 1;
+               len -= 1;
+               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+               break;
+       }
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       spca506_Initi2c(gspca_dev);
+       spca506_WriteI2c(gspca_dev, val, SAA7113_bright);
+       spca506_WriteI2c(gspca_dev, 0x01, 0x09);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
+{
+       spca506_Initi2c(gspca_dev);
+       spca506_WriteI2c(gspca_dev, val, SAA7113_contrast);
+       spca506_WriteI2c(gspca_dev, 0x01, 0x09);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev, s32 val)
+{
+       spca506_Initi2c(gspca_dev);
+       spca506_WriteI2c(gspca_dev, val, SAA7113_saturation);
+       spca506_WriteI2c(gspca_dev, 0x01, 0x09);
+}
+
+static void sethue(struct gspca_dev *gspca_dev, s32 val)
+{
+       spca506_Initi2c(gspca_dev);
+       spca506_WriteI2c(gspca_dev, val, SAA7113_hue);
+       spca506_WriteI2c(gspca_dev, 0x01, 0x09);
+}
+
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct gspca_dev *gspca_dev =
+               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+
+       gspca_dev->usb_err = 0;
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               setcolors(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_HUE:
+               sethue(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 4);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 255, 1, 0x47);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 255, 1, 0x40);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_HUE, 0, 255, 1, 0);
+
+       if (hdl->error) {
+               pr_err("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,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] __devinitconst = {
+       {USB_DEVICE(0x06e1, 0xa190)},
+/*fixme: may be IntelPCCameraPro BRIDGE_SPCA505
+       {USB_DEVICE(0x0733, 0x0430)}, */
+       {USB_DEVICE(0x0734, 0x043b)},
+       {USB_DEVICE(0x99fa, 0x8988)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+static int __devinit 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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/spca508.c b/drivers/media/usb/gspca/spca508.c
new file mode 100644 (file)
index 0000000..1286b41
--- /dev/null
@@ -0,0 +1,1540 @@
+/*
+ * SPCA508 chip based cameras subdriver
+ *
+ * Copyright (C) 2009 Jean-Francois Moine <http://moinejf.free.fr>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "spca508"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
+MODULE_DESCRIPTION("GSPCA/SPCA508 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;             /* !! must be the first item */
+
+       u8 subtype;
+#define CreativeVista 0
+#define HamaUSBSightcam 1
+#define HamaUSBSightcam2 2
+#define IntelEasyPCCamera 3
+#define MicroInnovationIC200 4
+#define ViewQuestVQ110 5
+};
+
+static const struct v4l2_pix_format sif_mode[] = {
+       {160, 120, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 3},
+       {176, 144, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+       {320, 240, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {352, 288, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+/* Frame packet header offsets for the spca508 */
+#define SPCA508_OFFSET_DATA 37
+
+/*
+ * Initialization data: this is the first set-up data written to the
+ * device (before the open data).
+ */
+static const u16 spca508_init_data[][2] = {
+       {0x0000, 0x870b},
+
+       {0x0020, 0x8112},       /* Video drop enable, ISO streaming disable */
+       {0x0003, 0x8111},       /* Reset compression & memory */
+       {0x0000, 0x8110},       /* Disable all outputs */
+       /* READ {0x0000, 0x8114} -> 0000: 00  */
+       {0x0000, 0x8114},       /* SW GPIO data */
+       {0x0008, 0x8110},       /* Enable charge pump output */
+       {0x0002, 0x8116},       /* 200 kHz pump clock */
+       /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE:) */
+       {0x0003, 0x8111},       /* Reset compression & memory */
+       {0x0000, 0x8111},       /* Normal mode (not reset) */
+       {0x0098, 0x8110},
+               /* Enable charge pump output, sync.serial,external 2x clock */
+       {0x000d, 0x8114},       /* SW GPIO data */
+       {0x0002, 0x8116},       /* 200 kHz pump clock */
+       {0x0020, 0x8112},       /* Video drop enable, ISO streaming disable */
+/* --------------------------------------- */
+       {0x000f, 0x8402},       /* memory bank */
+       {0x0000, 0x8403},       /* ... address */
+/* --------------------------------------- */
+/* 0x88__ is Synchronous Serial Interface. */
+/* TBD: This table could be expressed more compactly */
+/* using spca508_write_i2c_vector(). */
+/* TBD: Should see if the values in spca50x_i2c_data */
+/* would work with the VQ110 instead of the values */
+/* below. */
+       {0x00c0, 0x8804},       /* SSI slave addr */
+       {0x0008, 0x8802},       /* 375 Khz SSI clock */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},       /* 375 Khz SSI clock */
+       {0x0012, 0x8801},       /* SSI reg addr */
+       {0x0080, 0x8800},       /* SSI data to write */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},       /* 375 Khz SSI clock */
+       {0x0012, 0x8801},       /* SSI reg addr */
+       {0x0000, 0x8800},       /* SSI data to write */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},       /* 375 Khz SSI clock */
+       {0x0011, 0x8801},       /* SSI reg addr */
+       {0x0040, 0x8800},       /* SSI data to write */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0013, 0x8801},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0014, 0x8801},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0015, 0x8801},
+       {0x0001, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0016, 0x8801},
+       {0x0003, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0017, 0x8801},
+       {0x0036, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0018, 0x8801},
+       {0x00ec, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x001a, 0x8801},
+       {0x0094, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x001b, 0x8801},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0027, 0x8801},
+       {0x00a2, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0028, 0x8801},
+       {0x0040, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x002a, 0x8801},
+       {0x0084, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00 */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x002b, 0x8801},
+       {0x00a8, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x002c, 0x8801},
+       {0x00fe, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x002d, 0x8801},
+       {0x0003, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0038, 0x8801},
+       {0x0083, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0033, 0x8801},
+       {0x0081, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0034, 0x8801},
+       {0x004a, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0039, 0x8801},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0010, 0x8801},
+       {0x00a8, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0006, 0x8801},
+       {0x0058, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00 */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0000, 0x8801},
+       {0x0004, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0040, 0x8801},
+       {0x0080, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0041, 0x8801},
+       {0x000c, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0042, 0x8801},
+       {0x000c, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0043, 0x8801},
+       {0x0028, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0044, 0x8801},
+       {0x0080, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0045, 0x8801},
+       {0x0020, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0046, 0x8801},
+       {0x0020, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0047, 0x8801},
+       {0x0080, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0048, 0x8801},
+       {0x004c, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x0049, 0x8801},
+       {0x0084, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x004a, 0x8801},
+       {0x0084, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x0008, 0x8802},
+       {0x004b, 0x8801},
+       {0x0084, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* --------------------------------------- */
+       {0x0012, 0x8700},       /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
+       {0x0000, 0x8701},       /* CKx1 clock delay adj */
+       {0x0000, 0x8701},       /* CKx1 clock delay adj */
+       {0x0001, 0x870c},       /* CKOx2 output */
+       /* --------------------------------------- */
+       {0x0080, 0x8600},       /* Line memory read counter (L) */
+       {0x0001, 0x8606},       /* reserved */
+       {0x0064, 0x8607},       /* Line memory read counter (H) 0x6480=25,728 */
+       {0x002a, 0x8601},       /* CDSP sharp interpolation mode,
+        *                      line sel for color sep, edge enhance enab */
+       {0x0000, 0x8602},       /* optical black level for user settng = 0 */
+       {0x0080, 0x8600},       /* Line memory read counter (L) */
+       {0x000a, 0x8603},       /* optical black level calc mode:
+                                * auto; optical black offset = 10 */
+       {0x00df, 0x865b},       /* Horiz offset for valid pixels (L)=0xdf */
+       {0x0012, 0x865c},       /* Vert offset for valid lines (L)=0x12 */
+
+/* The following two lines seem to be the "wrong" resolution. */
+/* But perhaps these indicate the actual size of the sensor */
+/* rather than the size of the current video mode. */
+       {0x0058, 0x865d},       /* Horiz valid pixels (*4) (L) = 352 */
+       {0x0048, 0x865e},       /* Vert valid lines (*4) (L) = 288 */
+
+       {0x0015, 0x8608},       /* A11 Coef ... */
+       {0x0030, 0x8609},
+       {0x00fb, 0x860a},
+       {0x003e, 0x860b},
+       {0x00ce, 0x860c},
+       {0x00f4, 0x860d},
+       {0x00eb, 0x860e},
+       {0x00dc, 0x860f},
+       {0x0039, 0x8610},
+       {0x0001, 0x8611},       /* R offset for white balance ... */
+       {0x0000, 0x8612},
+       {0x0001, 0x8613},
+       {0x0000, 0x8614},
+       {0x005b, 0x8651},       /* R gain for white balance ... */
+       {0x0040, 0x8652},
+       {0x0060, 0x8653},
+       {0x0040, 0x8654},
+       {0x0000, 0x8655},
+       {0x0001, 0x863f},       /* Fixed gamma correction enable, USB control,
+                                * lum filter disable, lum noise clip disable */
+       {0x00a1, 0x8656},       /* Window1 size 256x256, Windows2 size 64x64,
+                                * gamma look-up disable,
+                                * new edge enhancement enable */
+       {0x0018, 0x8657},       /* Edge gain high thresh */
+       {0x0020, 0x8658},       /* Edge gain low thresh */
+       {0x000a, 0x8659},       /* Edge bandwidth high threshold */
+       {0x0005, 0x865a},       /* Edge bandwidth low threshold */
+       /* -------------------------------- */
+       {0x0030, 0x8112},       /* Video drop enable, ISO streaming enable */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0xa908, 0x8802},
+       {0x0034, 0x8801},       /* SSI reg addr */
+       {0x00ca, 0x8800},
+       /* SSI data to write */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0x1f08, 0x8802},
+       {0x0006, 0x8801},
+       {0x0080, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+/* ----- Read back coefs we wrote earlier. */
+       /* READ { 0x0000, 0x8608 } -> 0000: 15  */
+       /* READ { 0x0000, 0x8609 } -> 0000: 30  */
+       /* READ { 0x0000, 0x860a } -> 0000: fb  */
+       /* READ { 0x0000, 0x860b } -> 0000: 3e  */
+       /* READ { 0x0000, 0x860c } -> 0000: ce  */
+       /* READ { 0x0000, 0x860d } -> 0000: f4  */
+       /* READ { 0x0000, 0x860e } -> 0000: eb  */
+       /* READ { 0x0000, 0x860f } -> 0000: dc  */
+       /* READ { 0x0000, 0x8610 } -> 0000: 39  */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
+       {0xb008, 0x8802},
+       {0x0006, 0x8801},
+       {0x007d, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+
+       /* This chunk is seemingly redundant with */
+       /* earlier commands (A11 Coef...), but if I disable it, */
+       /* the image appears too dark.  Maybe there was some kind of */
+       /* reset since the earlier commands, so this is necessary again. */
+       {0x0015, 0x8608},
+       {0x0030, 0x8609},
+       {0xfffb, 0x860a},
+       {0x003e, 0x860b},
+       {0xffce, 0x860c},
+       {0xfff4, 0x860d},
+       {0xffeb, 0x860e},
+       {0xffdc, 0x860f},
+       {0x0039, 0x8610},
+       {0x0018, 0x8657},
+
+       {0x0000, 0x8508},       /* Disable compression. */
+       /* Previous line was:
+       {0x0021, 0x8508},        * Enable compression. */
+       {0x0032, 0x850b},       /* compression stuff */
+       {0x0003, 0x8509},       /* compression stuff */
+       {0x0011, 0x850a},       /* compression stuff */
+       {0x0021, 0x850d},       /* compression stuff */
+       {0x0010, 0x850c},       /* compression stuff */
+       {0x0003, 0x8500},       /* *** Video mode: 160x120 */
+       {0x0001, 0x8501},       /* Hardware-dominated snap control */
+       {0x0061, 0x8656},       /* Window1 size 128x128, Windows2 size 128x128,
+                                * gamma look-up disable,
+                                * new edge enhancement enable */
+       {0x0018, 0x8617},       /* Window1 start X (*2) */
+       {0x0008, 0x8618},       /* Window1 start Y (*2) */
+       {0x0061, 0x8656},       /* Window1 size 128x128, Windows2 size 128x128,
+                                * gamma look-up disable,
+                                * new edge enhancement enable */
+       {0x0058, 0x8619},       /* Window2 start X (*2) */
+       {0x0008, 0x861a},       /* Window2 start Y (*2) */
+       {0x00ff, 0x8615},       /* High lum thresh for white balance */
+       {0x0000, 0x8616},       /* Low lum thresh for white balance */
+       {0x0012, 0x8700},       /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
+       {0x0012, 0x8700},       /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
+       /* READ { 0x0000, 0x8656 } -> 0000: 61  */
+       {0x0028, 0x8802},    /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 28  */
+       {0x1f28, 0x8802},    /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
+       {0x0010, 0x8801},       /* SSI reg addr */
+       {0x003e, 0x8800},       /* SSI data to write */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       {0x0028, 0x8802},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 28  */
+       {0x1f28, 0x8802},
+       {0x0000, 0x8801},
+       {0x001f, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       {0x0001, 0x8602},    /* optical black level for user settning = 1 */
+
+       /* Original: */
+       {0x0023, 0x8700},       /* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */
+       {0x000f, 0x8602},    /* optical black level for user settning = 15 */
+
+       {0x0028, 0x8802},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 28  */
+       {0x1f28, 0x8802},
+       {0x0010, 0x8801},
+       {0x007b, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       {0x002f, 0x8651},       /* R gain for white balance ... */
+       {0x0080, 0x8653},
+       /* READ { 0x0000, 0x8655 } -> 0000: 00  */
+       {0x0000, 0x8655},
+
+       {0x0030, 0x8112},       /* Video drop enable, ISO streaming enable */
+       {0x0020, 0x8112},       /* Video drop enable, ISO streaming disable */
+       /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */
+       {}
+};
+
+/*
+ * Initialization data for Intel EasyPC Camera CS110
+ */
+static const u16 spca508cs110_init_data[][2] = {
+       {0x0000, 0x870b},       /* Reset CTL3 */
+       {0x0003, 0x8111},       /* Soft Reset compression, memory, TG & CDSP */
+       {0x0000, 0x8111},       /* Normal operation on reset */
+       {0x0090, 0x8110},
+                /* External Clock 2x & Synchronous Serial Interface Output */
+       {0x0020, 0x8112},       /* Video Drop packet enable */
+       {0x0000, 0x8114},       /* Software GPIO output data */
+       {0x0001, 0x8114},
+       {0x0001, 0x8114},
+       {0x0001, 0x8114},
+       {0x0003, 0x8114},
+
+       /* Initial sequence Synchronous Serial Interface */
+       {0x000f, 0x8402},       /* Memory bank Address */
+       {0x0000, 0x8403},       /* Memory bank Address */
+       {0x00ba, 0x8804},       /* SSI Slave address */
+       {0x0010, 0x8802},       /* 93.75kHz SSI Clock Two DataByte */
+       {0x0010, 0x8802},       /* 93.75kHz SSI Clock two DataByte */
+
+       {0x0001, 0x8801},
+       {0x000a, 0x8805},       /* a - NWG: Dunno what this is about */
+       {0x0000, 0x8800},
+       {0x0010, 0x8802},
+
+       {0x0002, 0x8801},
+       {0x0000, 0x8805},
+       {0x0000, 0x8800},
+       {0x0010, 0x8802},
+
+       {0x0003, 0x8801},
+       {0x0027, 0x8805},
+       {0x0001, 0x8800},
+       {0x0010, 0x8802},
+
+       {0x0004, 0x8801},
+       {0x0065, 0x8805},
+       {0x0001, 0x8800},
+       {0x0010, 0x8802},
+
+       {0x0005, 0x8801},
+       {0x0003, 0x8805},
+       {0x0000, 0x8800},
+       {0x0010, 0x8802},
+
+       {0x0006, 0x8801},
+       {0x001c, 0x8805},
+       {0x0000, 0x8800},
+       {0x0010, 0x8802},
+
+       {0x0007, 0x8801},
+       {0x002a, 0x8805},
+       {0x0000, 0x8800},
+       {0x0010, 0x8802},
+
+       {0x0002, 0x8704},       /* External input CKIx1 */
+       {0x0001, 0x8606},    /* 1 Line memory Read Counter (H) Result: (d)410 */
+       {0x009a, 0x8600},       /* Line memory Read Counter (L) */
+       {0x0001, 0x865b},       /* 1 Horizontal Offset for Valid Pixel(L) */
+       {0x0003, 0x865c},       /* 3 Vertical Offset for Valid Lines(L) */
+       {0x0058, 0x865d},       /* 58 Horizontal Valid Pixel Window(L) */
+
+       {0x0006, 0x8660},       /* Nibble data + input order */
+
+       {0x000a, 0x8602},       /* Optical black level set to 0x0a */
+       {0x0000, 0x8603},       /* Optical black level Offset */
+
+/*     {0x0000, 0x8611},        * 0 R  Offset for white Balance */
+/*     {0x0000, 0x8612},        * 1 Gr Offset for white Balance */
+/*     {0x0000, 0x8613},        * 1f B  Offset for white Balance */
+/*     {0x0000, 0x8614},        * f0 Gb Offset for white Balance */
+
+       {0x0040, 0x8651},   /* 2b BLUE gain for white balance  good at all 60 */
+       {0x0030, 0x8652},       /* 41 Gr Gain for white Balance (L) */
+       {0x0035, 0x8653},       /* 26 RED gain for white balance */
+       {0x0035, 0x8654},       /* 40Gb Gain for white Balance (L) */
+       {0x0041, 0x863f},
+             /* Fixed Gamma correction enabled (makes colours look better) */
+
+       {0x0000, 0x8655},
+               /* High bits for white balance*****brightness control*** */
+       {}
+};
+
+static const u16 spca508_sightcam_init_data[][2] = {
+/* This line seems to setup the frame/canvas */
+       {0x000f, 0x8402},
+
+/* These 6 lines are needed to startup the webcam */
+       {0x0090, 0x8110},
+       {0x0001, 0x8114},
+       {0x0001, 0x8114},
+       {0x0001, 0x8114},
+       {0x0003, 0x8114},
+       {0x0080, 0x8804},
+
+/* This part seems to make the pictures darker? (autobrightness?) */
+       {0x0001, 0x8801},
+       {0x0004, 0x8800},
+       {0x0003, 0x8801},
+       {0x00e0, 0x8800},
+       {0x0004, 0x8801},
+       {0x00b4, 0x8800},
+       {0x0005, 0x8801},
+       {0x0000, 0x8800},
+
+       {0x0006, 0x8801},
+       {0x00e0, 0x8800},
+       {0x0007, 0x8801},
+       {0x000c, 0x8800},
+
+/* This section is just needed, it probably
+ * does something like the previous section,
+ * but the cam won't start if it's not included.
+ */
+       {0x0014, 0x8801},
+       {0x0008, 0x8800},
+       {0x0015, 0x8801},
+       {0x0067, 0x8800},
+       {0x0016, 0x8801},
+       {0x0000, 0x8800},
+       {0x0017, 0x8801},
+       {0x0020, 0x8800},
+       {0x0018, 0x8801},
+       {0x0044, 0x8800},
+
+/* Makes the picture darker - and the
+ * cam won't start if not included
+ */
+       {0x001e, 0x8801},
+       {0x00ea, 0x8800},
+       {0x001f, 0x8801},
+       {0x0001, 0x8800},
+       {0x0003, 0x8801},
+       {0x00e0, 0x8800},
+
+/* seems to place the colors ontop of each other #1 */
+       {0x0006, 0x8704},
+       {0x0001, 0x870c},
+       {0x0016, 0x8600},
+       {0x0002, 0x8606},
+
+/* if not included the pictures becomes _very_ dark */
+       {0x0064, 0x8607},
+       {0x003a, 0x8601},
+       {0x0000, 0x8602},
+
+/* seems to place the colors ontop of each other #2 */
+       {0x0016, 0x8600},
+       {0x0018, 0x8617},
+       {0x0008, 0x8618},
+       {0x00a1, 0x8656},
+
+/* webcam won't start if not included */
+       {0x0007, 0x865b},
+       {0x0001, 0x865c},
+       {0x0058, 0x865d},
+       {0x0048, 0x865e},
+
+/* adjusts the colors */
+       {0x0049, 0x8651},
+       {0x0040, 0x8652},
+       {0x004c, 0x8653},
+       {0x0040, 0x8654},
+       {}
+};
+
+static const u16 spca508_sightcam2_init_data[][2] = {
+       {0x0020, 0x8112},
+
+       {0x000f, 0x8402},
+       {0x0000, 0x8403},
+
+       {0x0008, 0x8201},
+       {0x0008, 0x8200},
+       {0x0001, 0x8200},
+       {0x0009, 0x8201},
+       {0x0008, 0x8200},
+       {0x0001, 0x8200},
+       {0x000a, 0x8201},
+       {0x0008, 0x8200},
+       {0x0001, 0x8200},
+       {0x000b, 0x8201},
+       {0x0008, 0x8200},
+       {0x0001, 0x8200},
+       {0x000c, 0x8201},
+       {0x0008, 0x8200},
+       {0x0001, 0x8200},
+       {0x000d, 0x8201},
+       {0x0008, 0x8200},
+       {0x0001, 0x8200},
+       {0x000e, 0x8201},
+       {0x0008, 0x8200},
+       {0x0001, 0x8200},
+       {0x0007, 0x8201},
+       {0x0008, 0x8200},
+       {0x0001, 0x8200},
+       {0x000f, 0x8201},
+       {0x0008, 0x8200},
+       {0x0001, 0x8200},
+
+       {0x0018, 0x8660},
+       {0x0010, 0x8201},
+
+       {0x0008, 0x8200},
+       {0x0001, 0x8200},
+       {0x0011, 0x8201},
+       {0x0008, 0x8200},
+       {0x0001, 0x8200},
+
+       {0x0000, 0x86b0},
+       {0x0034, 0x86b1},
+       {0x0000, 0x86b2},
+       {0x0049, 0x86b3},
+       {0x0000, 0x86b4},
+       {0x0000, 0x86b4},
+
+       {0x0012, 0x8201},
+       {0x0008, 0x8200},
+       {0x0001, 0x8200},
+       {0x0013, 0x8201},
+       {0x0008, 0x8200},
+       {0x0001, 0x8200},
+
+       {0x0001, 0x86b0},
+       {0x00aa, 0x86b1},
+       {0x0000, 0x86b2},
+       {0x00e4, 0x86b3},
+       {0x0000, 0x86b4},
+       {0x0000, 0x86b4},
+
+       {0x0018, 0x8660},
+
+       {0x0090, 0x8110},
+       {0x0001, 0x8114},
+       {0x0001, 0x8114},
+       {0x0001, 0x8114},
+       {0x0003, 0x8114},
+
+       {0x0080, 0x8804},
+       {0x0003, 0x8801},
+       {0x0012, 0x8800},
+       {0x0004, 0x8801},
+       {0x0005, 0x8800},
+       {0x0005, 0x8801},
+       {0x0000, 0x8800},
+       {0x0006, 0x8801},
+       {0x0000, 0x8800},
+       {0x0007, 0x8801},
+       {0x0000, 0x8800},
+       {0x0008, 0x8801},
+       {0x0005, 0x8800},
+       {0x000a, 0x8700},
+       {0x000e, 0x8801},
+       {0x0004, 0x8800},
+       {0x0005, 0x8801},
+       {0x0047, 0x8800},
+       {0x0006, 0x8801},
+       {0x0000, 0x8800},
+       {0x0007, 0x8801},
+       {0x00c0, 0x8800},
+       {0x0008, 0x8801},
+       {0x0003, 0x8800},
+       {0x0013, 0x8801},
+       {0x0001, 0x8800},
+       {0x0009, 0x8801},
+       {0x0000, 0x8800},
+       {0x000a, 0x8801},
+       {0x0000, 0x8800},
+       {0x000b, 0x8801},
+       {0x0000, 0x8800},
+       {0x000c, 0x8801},
+       {0x0000, 0x8800},
+       {0x000e, 0x8801},
+       {0x0004, 0x8800},
+       {0x000f, 0x8801},
+       {0x0000, 0x8800},
+       {0x0010, 0x8801},
+       {0x0006, 0x8800},
+       {0x0011, 0x8801},
+       {0x0006, 0x8800},
+       {0x0012, 0x8801},
+       {0x0000, 0x8800},
+       {0x0013, 0x8801},
+       {0x0001, 0x8800},
+
+       {0x000a, 0x8700},
+       {0x0000, 0x8702},
+       {0x0000, 0x8703},
+       {0x00c2, 0x8704},
+       {0x0001, 0x870c},
+
+       {0x0044, 0x8600},
+       {0x0002, 0x8606},
+       {0x0064, 0x8607},
+       {0x003a, 0x8601},
+       {0x0008, 0x8602},
+       {0x0044, 0x8600},
+       {0x0018, 0x8617},
+       {0x0008, 0x8618},
+       {0x00a1, 0x8656},
+       {0x0004, 0x865b},
+       {0x0002, 0x865c},
+       {0x0058, 0x865d},
+       {0x0048, 0x865e},
+       {0x0012, 0x8608},
+       {0x002c, 0x8609},
+       {0x0002, 0x860a},
+       {0x002c, 0x860b},
+       {0x00db, 0x860c},
+       {0x00f9, 0x860d},
+       {0x00f1, 0x860e},
+       {0x00e3, 0x860f},
+       {0x002c, 0x8610},
+       {0x006c, 0x8651},
+       {0x0041, 0x8652},
+       {0x0059, 0x8653},
+       {0x0040, 0x8654},
+       {0x00fa, 0x8611},
+       {0x00ff, 0x8612},
+       {0x00f8, 0x8613},
+       {0x0000, 0x8614},
+       {0x0001, 0x863f},
+       {0x0000, 0x8640},
+       {0x0026, 0x8641},
+       {0x0045, 0x8642},
+       {0x0060, 0x8643},
+       {0x0075, 0x8644},
+       {0x0088, 0x8645},
+       {0x009b, 0x8646},
+       {0x00b0, 0x8647},
+       {0x00c5, 0x8648},
+       {0x00d2, 0x8649},
+       {0x00dc, 0x864a},
+       {0x00e5, 0x864b},
+       {0x00eb, 0x864c},
+       {0x00f0, 0x864d},
+       {0x00f6, 0x864e},
+       {0x00fa, 0x864f},
+       {0x00ff, 0x8650},
+       {0x0060, 0x8657},
+       {0x0010, 0x8658},
+       {0x0018, 0x8659},
+       {0x0005, 0x865a},
+       {0x0018, 0x8660},
+       {0x0003, 0x8509},
+       {0x0011, 0x850a},
+       {0x0032, 0x850b},
+       {0x0010, 0x850c},
+       {0x0021, 0x850d},
+       {0x0001, 0x8500},
+       {0x0000, 0x8508},
+       {0x0012, 0x8608},
+       {0x002c, 0x8609},
+       {0x0002, 0x860a},
+       {0x0039, 0x860b},
+       {0x00d0, 0x860c},
+       {0x00f7, 0x860d},
+       {0x00ed, 0x860e},
+       {0x00db, 0x860f},
+       {0x0039, 0x8610},
+       {0x0012, 0x8657},
+       {0x000c, 0x8619},
+       {0x0004, 0x861a},
+       {0x00a1, 0x8656},
+       {0x00c8, 0x8615},
+       {0x0032, 0x8616},
+
+       {0x0030, 0x8112},
+       {0x0020, 0x8112},
+       {0x0020, 0x8112},
+       {0x000f, 0x8402},
+       {0x0000, 0x8403},
+
+       {0x0090, 0x8110},
+       {0x0001, 0x8114},
+       {0x0001, 0x8114},
+       {0x0001, 0x8114},
+       {0x0003, 0x8114},
+       {0x0080, 0x8804},
+
+       {0x0003, 0x8801},
+       {0x0012, 0x8800},
+       {0x0004, 0x8801},
+       {0x0005, 0x8800},
+       {0x0005, 0x8801},
+       {0x0047, 0x8800},
+       {0x0006, 0x8801},
+       {0x0000, 0x8800},
+       {0x0007, 0x8801},
+       {0x00c0, 0x8800},
+       {0x0008, 0x8801},
+       {0x0003, 0x8800},
+       {0x000a, 0x8700},
+       {0x000e, 0x8801},
+       {0x0004, 0x8800},
+       {0x0005, 0x8801},
+       {0x0047, 0x8800},
+       {0x0006, 0x8801},
+       {0x0000, 0x8800},
+       {0x0007, 0x8801},
+       {0x00c0, 0x8800},
+       {0x0008, 0x8801},
+       {0x0003, 0x8800},
+       {0x0013, 0x8801},
+       {0x0001, 0x8800},
+       {0x0009, 0x8801},
+       {0x0000, 0x8800},
+       {0x000a, 0x8801},
+       {0x0000, 0x8800},
+       {0x000b, 0x8801},
+       {0x0000, 0x8800},
+       {0x000c, 0x8801},
+       {0x0000, 0x8800},
+       {0x000e, 0x8801},
+       {0x0004, 0x8800},
+       {0x000f, 0x8801},
+       {0x0000, 0x8800},
+       {0x0010, 0x8801},
+       {0x0006, 0x8800},
+       {0x0011, 0x8801},
+       {0x0006, 0x8800},
+       {0x0012, 0x8801},
+       {0x0000, 0x8800},
+       {0x0013, 0x8801},
+       {0x0001, 0x8800},
+       {0x000a, 0x8700},
+       {0x0000, 0x8702},
+       {0x0000, 0x8703},
+       {0x00c2, 0x8704},
+       {0x0001, 0x870c},
+       {0x0044, 0x8600},
+       {0x0002, 0x8606},
+       {0x0064, 0x8607},
+       {0x003a, 0x8601},
+       {0x0008, 0x8602},
+       {0x0044, 0x8600},
+       {0x0018, 0x8617},
+       {0x0008, 0x8618},
+       {0x00a1, 0x8656},
+       {0x0004, 0x865b},
+       {0x0002, 0x865c},
+       {0x0058, 0x865d},
+       {0x0048, 0x865e},
+       {0x0012, 0x8608},
+       {0x002c, 0x8609},
+       {0x0002, 0x860a},
+       {0x002c, 0x860b},
+       {0x00db, 0x860c},
+       {0x00f9, 0x860d},
+       {0x00f1, 0x860e},
+       {0x00e3, 0x860f},
+       {0x002c, 0x8610},
+       {0x006c, 0x8651},
+       {0x0041, 0x8652},
+       {0x0059, 0x8653},
+       {0x0040, 0x8654},
+       {0x00fa, 0x8611},
+       {0x00ff, 0x8612},
+       {0x00f8, 0x8613},
+       {0x0000, 0x8614},
+       {0x0001, 0x863f},
+       {0x0000, 0x8640},
+       {0x0026, 0x8641},
+       {0x0045, 0x8642},
+       {0x0060, 0x8643},
+       {0x0075, 0x8644},
+       {0x0088, 0x8645},
+       {0x009b, 0x8646},
+       {0x00b0, 0x8647},
+       {0x00c5, 0x8648},
+       {0x00d2, 0x8649},
+       {0x00dc, 0x864a},
+       {0x00e5, 0x864b},
+       {0x00eb, 0x864c},
+       {0x00f0, 0x864d},
+       {0x00f6, 0x864e},
+       {0x00fa, 0x864f},
+       {0x00ff, 0x8650},
+       {0x0060, 0x8657},
+       {0x0010, 0x8658},
+       {0x0018, 0x8659},
+       {0x0005, 0x865a},
+       {0x0018, 0x8660},
+       {0x0003, 0x8509},
+       {0x0011, 0x850a},
+       {0x0032, 0x850b},
+       {0x0010, 0x850c},
+       {0x0021, 0x850d},
+       {0x0001, 0x8500},
+       {0x0000, 0x8508},
+
+       {0x0012, 0x8608},
+       {0x002c, 0x8609},
+       {0x0002, 0x860a},
+       {0x0039, 0x860b},
+       {0x00d0, 0x860c},
+       {0x00f7, 0x860d},
+       {0x00ed, 0x860e},
+       {0x00db, 0x860f},
+       {0x0039, 0x8610},
+       {0x0012, 0x8657},
+       {0x0064, 0x8619},
+
+/* This line starts it all, it is not needed here */
+/* since it has been build into the driver */
+/* jfm: don't start now */
+/*     {0x0030, 0x8112}, */
+       {}
+};
+
+/*
+ * Initialization data for Creative Webcam Vista
+ */
+static const u16 spca508_vista_init_data[][2] = {
+       {0x0008, 0x8200},       /* Clear register */
+       {0x0000, 0x870b},       /* Reset CTL3 */
+       {0x0020, 0x8112},       /* Video Drop packet enable */
+       {0x0003, 0x8111},       /* Soft Reset compression, memory, TG & CDSP */
+       {0x0000, 0x8110},       /* Disable everything */
+       {0x0000, 0x8114},       /* Software GPIO output data */
+       {0x0000, 0x8114},
+
+       {0x0003, 0x8111},
+       {0x0000, 0x8111},
+       {0x0090, 0x8110},    /* Enable: SSI output, External 2X clock output */
+       {0x0020, 0x8112},
+       {0x0000, 0x8114},
+       {0x0001, 0x8114},
+       {0x0001, 0x8114},
+       {0x0001, 0x8114},
+       {0x0003, 0x8114},
+
+       {0x000f, 0x8402},       /* Memory bank Address */
+       {0x0000, 0x8403},       /* Memory bank Address */
+       {0x00ba, 0x8804},       /* SSI Slave address */
+       {0x0010, 0x8802},       /* 93.75kHz SSI Clock Two DataByte */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},       /* Will write 2 bytes (DATA1+DATA2) */
+       {0x0020, 0x8801},       /* Register address for SSI read/write */
+       {0x0044, 0x8805},       /* DATA2 */
+       {0x0004, 0x8800},       /* DATA1 -> write triggered */
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x0009, 0x8801},
+       {0x0042, 0x8805},
+       {0x0001, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x003c, 0x8801},
+       {0x0001, 0x8805},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x0001, 0x8801},
+       {0x000a, 0x8805},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x0002, 0x8801},
+       {0x0000, 0x8805},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x0003, 0x8801},
+       {0x0027, 0x8805},
+       {0x0001, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x0004, 0x8801},
+       {0x0065, 0x8805},
+       {0x0001, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x0005, 0x8801},
+       {0x0003, 0x8805},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x0006, 0x8801},
+       {0x001c, 0x8805},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x0007, 0x8801},
+       {0x002a, 0x8805},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x000e, 0x8801},
+       {0x0000, 0x8805},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x0028, 0x8801},
+       {0x002e, 0x8805},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x0039, 0x8801},
+       {0x0013, 0x8805},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x003b, 0x8801},
+       {0x000c, 0x8805},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x0035, 0x8801},
+       {0x0028, 0x8805},
+       {0x0000, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
+       {0x0010, 0x8802},
+       {0x0009, 0x8801},
+       {0x0042, 0x8805},
+       {0x0001, 0x8800},
+       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
+
+       {0x0050, 0x8703},
+       {0x0002, 0x8704},       /* External input CKIx1 */
+       {0x0001, 0x870c},       /* Select CKOx2 output */
+       {0x009a, 0x8600},       /* Line memory Read Counter (L) */
+       {0x0001, 0x8606},    /* 1 Line memory Read Counter (H) Result: (d)410 */
+       {0x0023, 0x8601},
+       {0x0010, 0x8602},
+       {0x000a, 0x8603},
+       {0x009a, 0x8600},
+       {0x0001, 0x865b},       /* 1 Horizontal Offset for Valid Pixel(L) */
+       {0x0003, 0x865c},       /* Vertical offset for valid lines (L) */
+       {0x0058, 0x865d},       /* Horizontal valid pixels window (L) */
+       {0x0048, 0x865e},       /* Vertical valid lines window (L) */
+       {0x0000, 0x865f},
+
+       {0x0006, 0x8660},
+                   /* Enable nibble data input, select nibble input order */
+
+       {0x0013, 0x8608},       /* A11 Coeficients for color correction */
+       {0x0028, 0x8609},
+                   /* Note: these values are confirmed at the end of array */
+       {0x0005, 0x860a},       /* ... */
+       {0x0025, 0x860b},
+       {0x00e1, 0x860c},
+       {0x00fa, 0x860d},
+       {0x00f4, 0x860e},
+       {0x00e8, 0x860f},
+       {0x0025, 0x8610},       /* A33 Coef. */
+       {0x00fc, 0x8611},       /* White balance offset: R */
+       {0x0001, 0x8612},       /* White balance offset: Gr */
+       {0x00fe, 0x8613},       /* White balance offset: B */
+       {0x0000, 0x8614},       /* White balance offset: Gb */
+
+       {0x0064, 0x8651},       /* R gain for white balance (L) */
+       {0x0040, 0x8652},       /* Gr gain for white balance (L) */
+       {0x0066, 0x8653},       /* B gain for white balance (L) */
+       {0x0040, 0x8654},       /* Gb gain for white balance (L) */
+       {0x0001, 0x863f},       /* Enable fixed gamma correction */
+
+       {0x00a1, 0x8656},       /* Size - Window1: 256x256, Window2: 128x128,
+                                * UV division: UV no change,
+                                * Enable New edge enhancement */
+       {0x0018, 0x8657},       /* Edge gain high threshold */
+       {0x0020, 0x8658},       /* Edge gain low threshold */
+       {0x000a, 0x8659},       /* Edge bandwidth high threshold */
+       {0x0005, 0x865a},       /* Edge bandwidth low threshold */
+       {0x0064, 0x8607},       /* UV filter enable */
+
+       {0x0016, 0x8660},
+       {0x0000, 0x86b0},       /* Bad pixels compensation address */
+       {0x00dc, 0x86b1},       /* X coord for bad pixels compensation (L) */
+       {0x0000, 0x86b2},
+       {0x0009, 0x86b3},       /* Y coord for bad pixels compensation (L) */
+       {0x0000, 0x86b4},
+
+       {0x0001, 0x86b0},
+       {0x00f5, 0x86b1},
+       {0x0000, 0x86b2},
+       {0x00c6, 0x86b3},
+       {0x0000, 0x86b4},
+
+       {0x0002, 0x86b0},
+       {0x001c, 0x86b1},
+       {0x0001, 0x86b2},
+       {0x00d7, 0x86b3},
+       {0x0000, 0x86b4},
+
+       {0x0003, 0x86b0},
+       {0x001c, 0x86b1},
+       {0x0001, 0x86b2},
+       {0x00d8, 0x86b3},
+       {0x0000, 0x86b4},
+
+       {0x0004, 0x86b0},
+       {0x001d, 0x86b1},
+       {0x0001, 0x86b2},
+       {0x00d8, 0x86b3},
+       {0x0000, 0x86b4},
+       {0x001e, 0x8660},
+
+       /* READ { 0x0000, 0x8608 } -> 0000: 13  */
+       /* READ { 0x0000, 0x8609 } -> 0000: 28  */
+       /* READ { 0x0000, 0x8610 } -> 0000: 05  */
+       /* READ { 0x0000, 0x8611 } -> 0000: 25  */
+       /* READ { 0x0000, 0x8612 } -> 0000: e1  */
+       /* READ { 0x0000, 0x8613 } -> 0000: fa  */
+       /* READ { 0x0000, 0x8614 } -> 0000: f4  */
+       /* READ { 0x0000, 0x8615 } -> 0000: e8  */
+       /* READ { 0x0000, 0x8616 } -> 0000: 25  */
+       {}
+};
+
+static int reg_write(struct usb_device *dev,
+                       u16 index, u16 value)
+{
+       int ret;
+
+       ret = usb_control_msg(dev,
+                       usb_sndctrlpipe(dev, 0),
+                       0,              /* request */
+                       USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index, NULL, 0, 500);
+       PDEBUG(D_USBO, "reg write i:0x%04x = 0x%02x",
+               index, value);
+       if (ret < 0)
+               pr_err("reg write: error %d\n", ret);
+       return ret;
+}
+
+/* read 1 byte */
+/* returns: negative is error, pos or zero is data */
+static int reg_read(struct gspca_dev *gspca_dev,
+                       u16 index)      /* wIndex */
+{
+       int ret;
+
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       0,                      /* register */
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,              /* value */
+                       index,
+                       gspca_dev->usb_buf, 1,
+                       500);                   /* timeout */
+       PDEBUG(D_USBI, "reg read i:%04x --> %02x",
+               index, gspca_dev->usb_buf[0]);
+       if (ret < 0) {
+               pr_err("reg_read err %d\n", ret);
+               return ret;
+       }
+       return gspca_dev->usb_buf[0];
+}
+
+/* send 1 or 2 bytes to the sensor via the Synchronous Serial Interface */
+static int ssi_w(struct gspca_dev *gspca_dev,
+               u16 reg, u16 val)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret, retry;
+
+       ret = reg_write(dev, 0x8802, reg >> 8);
+       if (ret < 0)
+               goto out;
+       ret = reg_write(dev, 0x8801, reg & 0x00ff);
+       if (ret < 0)
+               goto out;
+       if ((reg & 0xff00) == 0x1000) {         /* if 2 bytes */
+               ret = reg_write(dev, 0x8805, val & 0x00ff);
+               if (ret < 0)
+                       goto out;
+               val >>= 8;
+       }
+       ret = reg_write(dev, 0x8800, val);
+       if (ret < 0)
+               goto out;
+
+       /* poll until not busy */
+       retry = 10;
+       for (;;) {
+               ret = reg_read(gspca_dev, 0x8803);
+               if (ret < 0)
+                       break;
+               if (gspca_dev->usb_buf[0] == 0)
+                       break;
+               if (--retry <= 0) {
+                       PDEBUG(D_ERR, "ssi_w busy %02x",
+                                       gspca_dev->usb_buf[0]);
+                       ret = -1;
+                       break;
+               }
+               msleep(8);
+       }
+
+out:
+       return ret;
+}
+
+static int write_vector(struct gspca_dev *gspca_dev,
+                       const u16 (*data)[2])
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret = 0;
+
+       while ((*data)[1] != 0) {
+               if ((*data)[1] & 0x8000) {
+                       if ((*data)[1] == 0xdd00)       /* delay */
+                               msleep((*data)[0]);
+                       else
+                               ret = reg_write(dev, (*data)[1], (*data)[0]);
+               } else {
+                       ret = ssi_w(gspca_dev, (*data)[1], (*data)[0]);
+               }
+               if (ret < 0)
+                       break;
+               data++;
+       }
+       return ret;
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+       const u16 (*init_data)[2];
+       static const u16 (*(init_data_tb[]))[2] = {
+               spca508_vista_init_data,        /* CreativeVista 0 */
+               spca508_sightcam_init_data,     /* HamaUSBSightcam 1 */
+               spca508_sightcam2_init_data,    /* HamaUSBSightcam2 2 */
+               spca508cs110_init_data,         /* IntelEasyPCCamera 3 */
+               spca508cs110_init_data,         /* MicroInnovationIC200 4 */
+               spca508_init_data,              /* ViewQuestVQ110 5 */
+       };
+
+#ifdef GSPCA_DEBUG
+       int data1, data2;
+
+       /* Read from global register the USB product and vendor IDs, just to
+        * prove that we can communicate with the device.  This works, which
+        * confirms at we are communicating properly and that the device
+        * is a 508. */
+       data1 = reg_read(gspca_dev, 0x8104);
+       data2 = reg_read(gspca_dev, 0x8105);
+       PDEBUG(D_PROBE, "Webcam Vendor ID: 0x%02x%02x", data2, data1);
+
+       data1 = reg_read(gspca_dev, 0x8106);
+       data2 = reg_read(gspca_dev, 0x8107);
+       PDEBUG(D_PROBE, "Webcam Product ID: 0x%02x%02x", data2, data1);
+
+       data1 = reg_read(gspca_dev, 0x8621);
+       PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);
+#endif
+
+       cam = &gspca_dev->cam;
+       cam->cam_mode = sif_mode;
+       cam->nmodes = ARRAY_SIZE(sif_mode);
+
+       sd->subtype = id->driver_info;
+
+       init_data = init_data_tb[sd->subtype];
+       return write_vector(gspca_dev, init_data);
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       return 0;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       int mode;
+
+       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+       reg_write(gspca_dev->dev, 0x8500, mode);
+       switch (mode) {
+       case 0:
+       case 1:
+               reg_write(gspca_dev->dev, 0x8700, 0x28);        /* clock */
+               break;
+       default:
+/*     case 2: */
+/*     case 3: */
+               reg_write(gspca_dev->dev, 0x8700, 0x23);        /* clock */
+               break;
+       }
+       reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20);
+       return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       /* Video ISO disable, Video Drop Packet enable: */
+       reg_write(gspca_dev->dev, 0x8112, 0x20);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,                       /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       switch (data[0]) {
+       case 0:                         /* start of frame */
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+               data += SPCA508_OFFSET_DATA;
+               len -= SPCA508_OFFSET_DATA;
+               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
+               break;
+       case 0xff:                      /* drop */
+               break;
+       default:
+               data += 1;
+               len -= 1;
+               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+               break;
+       }
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
+{
+       /* MX seem contrast */
+       reg_write(gspca_dev->dev, 0x8651, brightness);
+       reg_write(gspca_dev->dev, 0x8652, brightness);
+       reg_write(gspca_dev->dev, 0x8653, brightness);
+       reg_write(gspca_dev->dev, 0x8654, brightness);
+}
+
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct gspca_dev *gspca_dev =
+               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+
+       gspca_dev->usb_err = 0;
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 5);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+
+       if (hdl->error) {
+               pr_err("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,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam},
+       {USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista},
+       {USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110},
+       {USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam},
+       {USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2},
+       {USB_DEVICE(0x8086, 0x0110), .driver_info = IntelEasyPCCamera},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/spca561.c b/drivers/media/usb/gspca/spca561.c
new file mode 100644 (file)
index 0000000..cfe71dd
--- /dev/null
@@ -0,0 +1,936 @@
+/*
+ * Sunplus spca561 subdriver
+ *
+ * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
+ *
+ * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "spca561"
+
+#include <linux/input.h>
+#include "gspca.h"
+
+MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
+MODULE_DESCRIPTION("GSPCA/SPCA561 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+#define EXPOSURE_MAX (2047 + 325)
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       struct { /* hue/contrast control cluster */
+               struct v4l2_ctrl *contrast;
+               struct v4l2_ctrl *hue;
+       };
+       struct v4l2_ctrl *autogain;
+
+#define EXPO12A_DEF 3
+       __u8 expo12a;           /* expo/gain? for rev 12a */
+
+       __u8 chip_revision;
+#define Rev012A 0
+#define Rev072A 1
+
+       signed char ag_cnt;
+#define AG_CNT_START 13
+};
+
+static const struct v4l2_pix_format sif_012a_mode[] = {
+       {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 3},
+       {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+       {320, 240, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 4 / 8,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {352, 288, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 4 / 8,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+static const struct v4l2_pix_format sif_072a_mode[] = {
+       {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 3},
+       {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+       {320, 240, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {352, 288, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+/*
+ * Initialization data
+ * I'm not very sure how to split initialization from open data
+ * chunks. For now, we'll consider everything as initialization
+ */
+/* Frame packet header offsets for the spca561 */
+#define SPCA561_OFFSET_SNAP 1
+#define SPCA561_OFFSET_TYPE 2
+#define SPCA561_OFFSET_COMPRESS 3
+#define SPCA561_OFFSET_FRAMSEQ   4
+#define SPCA561_OFFSET_GPIO 5
+#define SPCA561_OFFSET_USBBUFF 6
+#define SPCA561_OFFSET_WIN2GRAVE 7
+#define SPCA561_OFFSET_WIN2RAVE 8
+#define SPCA561_OFFSET_WIN2BAVE 9
+#define SPCA561_OFFSET_WIN2GBAVE 10
+#define SPCA561_OFFSET_WIN1GRAVE 11
+#define SPCA561_OFFSET_WIN1RAVE 12
+#define SPCA561_OFFSET_WIN1BAVE 13
+#define SPCA561_OFFSET_WIN1GBAVE 14
+#define SPCA561_OFFSET_FREQ 15
+#define SPCA561_OFFSET_VSYNC 16
+#define SPCA561_INDEX_I2C_BASE 0x8800
+#define SPCA561_SNAPBIT 0x20
+#define SPCA561_SNAPCTRL 0x40
+
+static const u16 rev72a_reset[][2] = {
+       {0x0000, 0x8114},       /* Software GPIO output data */
+       {0x0001, 0x8114},       /* Software GPIO output data */
+       {0x0000, 0x8112},       /* Some kind of reset */
+       {}
+};
+static const __u16 rev72a_init_data1[][2] = {
+       {0x0003, 0x8701},       /* PCLK clock delay adjustment */
+       {0x0001, 0x8703},       /* HSYNC from cmos inverted */
+       {0x0011, 0x8118},       /* Enable and conf sensor */
+       {0x0001, 0x8118},       /* Conf sensor */
+       {0x0092, 0x8804},       /* I know nothing about these */
+       {0x0010, 0x8802},       /* 0x88xx registers, so I won't */
+       {}
+};
+static const u16 rev72a_init_sensor1[][2] = {
+       {0x0001, 0x000d},
+       {0x0002, 0x0018},
+       {0x0004, 0x0165},
+       {0x0005, 0x0021},
+       {0x0007, 0x00aa},
+       {0x0020, 0x1504},
+       {0x0039, 0x0002},
+       {0x0035, 0x0010},
+       {0x0009, 0x1049},
+       {0x0028, 0x000b},
+       {0x003b, 0x000f},
+       {0x003c, 0x0000},
+       {}
+};
+static const __u16 rev72a_init_data2[][2] = {
+       {0x0018, 0x8601},       /* Pixel/line selection for color separation */
+       {0x0000, 0x8602},       /* Optical black level for user setting */
+       {0x0060, 0x8604},       /* Optical black horizontal offset */
+       {0x0002, 0x8605},       /* Optical black vertical offset */
+       {0x0000, 0x8603},       /* Non-automatic optical black level */
+       {0x0002, 0x865b},       /* Horizontal offset for valid pixels */
+       {0x0000, 0x865f},       /* Vertical valid pixels window (x2) */
+       {0x00b0, 0x865d},       /* Horizontal valid pixels window (x2) */
+       {0x0090, 0x865e},       /* Vertical valid lines window (x2) */
+       {0x00e0, 0x8406},       /* Memory buffer threshold */
+       {0x0000, 0x8660},       /* Compensation memory stuff */
+       {0x0002, 0x8201},       /* Output address for r/w serial EEPROM */
+       {0x0008, 0x8200},       /* Clear valid bit for serial EEPROM */
+       {0x0001, 0x8200},       /* OprMode to be executed by hardware */
+/* from ms-win */
+       {0x0000, 0x8611},       /* R offset for white balance */
+       {0x00fd, 0x8612},       /* Gr offset for white balance */
+       {0x0003, 0x8613},       /* B offset for white balance */
+       {0x0000, 0x8614},       /* Gb offset for white balance */
+/* from ms-win */
+       {0x0035, 0x8651},       /* R gain for white balance */
+       {0x0040, 0x8652},       /* Gr gain for white balance */
+       {0x005f, 0x8653},       /* B gain for white balance */
+       {0x0040, 0x8654},       /* Gb gain for white balance */
+       {0x0002, 0x8502},       /* Maximum average bit rate stuff */
+       {0x0011, 0x8802},
+
+       {0x0087, 0x8700},       /* Set master clock (96Mhz????) */
+       {0x0081, 0x8702},       /* Master clock output enable */
+
+       {0x0000, 0x8500},       /* Set image type (352x288 no compression) */
+       /* Originally was 0x0010 (352x288 compression) */
+
+       {0x0002, 0x865b},       /* Horizontal offset for valid pixels */
+       {0x0003, 0x865c},       /* Vertical offset for valid lines */
+       {}
+};
+static const u16 rev72a_init_sensor2[][2] = {
+       {0x0003, 0x0121},
+       {0x0004, 0x0165},
+       {0x0005, 0x002f},       /* blanking control column */
+       {0x0006, 0x0000},       /* blanking mode row*/
+       {0x000a, 0x0002},
+       {0x0009, 0x1061},       /* setexposure times && pixel clock
+                                * 0001 0 | 000 0110 0001 */
+       {0x0035, 0x0014},
+       {}
+};
+
+/******************** QC Express etch2 stuff ********************/
+static const __u16 Pb100_1map8300[][2] = {
+       /* reg, value */
+       {0x8320, 0x3304},
+
+       {0x8303, 0x0125},       /* image area */
+       {0x8304, 0x0169},
+       {0x8328, 0x000b},
+       {0x833c, 0x0001},               /*fixme: win:07*/
+
+       {0x832f, 0x1904},               /*fixme: was 0419*/
+       {0x8307, 0x00aa},
+       {0x8301, 0x0003},
+       {0x8302, 0x000e},
+       {}
+};
+static const __u16 Pb100_2map8300[][2] = {
+       /* reg, value */
+       {0x8339, 0x0000},
+       {0x8307, 0x00aa},
+       {}
+};
+
+static const __u16 spca561_161rev12A_data1[][2] = {
+       {0x29, 0x8118},         /* Control register (various enable bits) */
+       {0x08, 0x8114},         /* GPIO: Led off */
+       {0x0e, 0x8112},         /* 0x0e stream off 0x3e stream on */
+       {0x00, 0x8102},         /* white balance - new */
+       {0x92, 0x8804},
+       {0x04, 0x8802},         /* windows uses 08 */
+       {}
+};
+static const __u16 spca561_161rev12A_data2[][2] = {
+       {0x21, 0x8118},
+       {0x10, 0x8500},
+       {0x07, 0x8601},
+       {0x07, 0x8602},
+       {0x04, 0x8501},
+
+       {0x07, 0x8201},         /* windows uses 02 */
+       {0x08, 0x8200},
+       {0x01, 0x8200},
+
+       {0x90, 0x8604},
+       {0x00, 0x8605},
+       {0xb0, 0x8603},
+
+       /* sensor gains */
+       {0x07, 0x8601},         /* white balance - new */
+       {0x07, 0x8602},         /* white balance - new */
+       {0x00, 0x8610},         /* *red */
+       {0x00, 0x8611},         /* 3f   *green */
+       {0x00, 0x8612},         /* green *blue */
+       {0x00, 0x8613},         /* blue *green */
+       {0x43, 0x8614},         /* green *red - white balance - was 0x35 */
+       {0x40, 0x8615},         /* 40   *green - white balance - was 0x35 */
+       {0x71, 0x8616},         /* 7a   *blue - white balance - was 0x35 */
+       {0x40, 0x8617},         /* 40   *green - white balance - was 0x35 */
+
+       {0x0c, 0x8620},         /* 0c */
+       {0xc8, 0x8631},         /* c8 */
+       {0xc8, 0x8634},         /* c8 */
+       {0x23, 0x8635},         /* 23 */
+       {0x1f, 0x8636},         /* 1f */
+       {0xdd, 0x8637},         /* dd */
+       {0xe1, 0x8638},         /* e1 */
+       {0x1d, 0x8639},         /* 1d */
+       {0x21, 0x863a},         /* 21 */
+       {0xe3, 0x863b},         /* e3 */
+       {0xdf, 0x863c},         /* df */
+       {0xf0, 0x8505},
+       {0x32, 0x850a},
+/*     {0x99, 0x8700},          * - white balance - new (removed) */
+       /* HDG we used to do this in stop0, making the init state and the state
+          after a start / stop different, so do this here instead. */
+       {0x29, 0x8118},
+       {}
+};
+
+static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
+{
+       int ret;
+
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                             0,                /* request */
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             value, index, NULL, 0, 500);
+       PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
+       if (ret < 0)
+               pr_err("reg write: error %d\n", ret);
+}
+
+static void write_vector(struct gspca_dev *gspca_dev,
+                       const __u16 data[][2])
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int i;
+
+       i = 0;
+       while (data[i][1] != 0) {
+               reg_w_val(dev, data[i][1], data[i][0]);
+               i++;
+       }
+}
+
+/* read 'len' bytes to gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev,
+                 __u16 index, __u16 length)
+{
+       usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       0,                      /* request */
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,                      /* value */
+                       index, gspca_dev->usb_buf, length, 500);
+}
+
+/* write 'len' bytes from gspca_dev->usb_buf */
+static void reg_w_buf(struct gspca_dev *gspca_dev,
+                     __u16 index, __u16 len)
+{
+       usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0,                      /* request */
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,                      /* value */
+                       index, gspca_dev->usb_buf, len, 500);
+}
+
+static void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg)
+{
+       int retry = 60;
+
+       reg_w_val(gspca_dev->dev, 0x8801, reg);
+       reg_w_val(gspca_dev->dev, 0x8805, value);
+       reg_w_val(gspca_dev->dev, 0x8800, value >> 8);
+       do {
+               reg_r(gspca_dev, 0x8803, 1);
+               if (!gspca_dev->usb_buf[0])
+                       return;
+               msleep(10);
+       } while (--retry);
+}
+
+static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
+{
+       int retry = 60;
+       __u8 value;
+
+       reg_w_val(gspca_dev->dev, 0x8804, 0x92);
+       reg_w_val(gspca_dev->dev, 0x8801, reg);
+       reg_w_val(gspca_dev->dev, 0x8802, mode | 0x01);
+       do {
+               reg_r(gspca_dev, 0x8803, 1);
+               if (!gspca_dev->usb_buf[0]) {
+                       reg_r(gspca_dev, 0x8800, 1);
+                       value = gspca_dev->usb_buf[0];
+                       reg_r(gspca_dev, 0x8805, 1);
+                       return ((int) value << 8) | gspca_dev->usb_buf[0];
+               }
+               msleep(10);
+       } while (--retry);
+       return -1;
+}
+
+static void sensor_mapwrite(struct gspca_dev *gspca_dev,
+                           const __u16 (*sensormap)[2])
+{
+       while ((*sensormap)[0]) {
+               gspca_dev->usb_buf[0] = (*sensormap)[1];
+               gspca_dev->usb_buf[1] = (*sensormap)[1] >> 8;
+               reg_w_buf(gspca_dev, (*sensormap)[0], 2);
+               sensormap++;
+       }
+}
+
+static void write_sensor_72a(struct gspca_dev *gspca_dev,
+                           const __u16 (*sensor)[2])
+{
+       while ((*sensor)[0]) {
+               i2c_write(gspca_dev, (*sensor)[1], (*sensor)[0]);
+               sensor++;
+       }
+}
+
+static void init_161rev12A(struct gspca_dev *gspca_dev)
+{
+       write_vector(gspca_dev, spca561_161rev12A_data1);
+       sensor_mapwrite(gspca_dev, Pb100_1map8300);
+/*fixme: should be in sd_start*/
+       write_vector(gspca_dev, spca561_161rev12A_data2);
+       sensor_mapwrite(gspca_dev, Pb100_2map8300);
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                    const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+       __u16 vendor, product;
+       __u8 data1, data2;
+
+       /* Read frm global register the USB product and vendor IDs, just to
+        * prove that we can communicate with the device.  This works, which
+        * confirms at we are communicating properly and that the device
+        * is a 561. */
+       reg_r(gspca_dev, 0x8104, 1);
+       data1 = gspca_dev->usb_buf[0];
+       reg_r(gspca_dev, 0x8105, 1);
+       data2 = gspca_dev->usb_buf[0];
+       vendor = (data2 << 8) | data1;
+       reg_r(gspca_dev, 0x8106, 1);
+       data1 = gspca_dev->usb_buf[0];
+       reg_r(gspca_dev, 0x8107, 1);
+       data2 = gspca_dev->usb_buf[0];
+       product = (data2 << 8) | data1;
+       if (vendor != id->idVendor || product != id->idProduct) {
+               PDEBUG(D_PROBE, "Bad vendor / product from device");
+               return -EINVAL;
+       }
+
+       cam = &gspca_dev->cam;
+       cam->needs_full_bandwidth = 1;
+
+       sd->chip_revision = id->driver_info;
+       if (sd->chip_revision == Rev012A) {
+               cam->cam_mode = sif_012a_mode;
+               cam->nmodes = ARRAY_SIZE(sif_012a_mode);
+       } else {
+               cam->cam_mode = sif_072a_mode;
+               cam->nmodes = ARRAY_SIZE(sif_072a_mode);
+       }
+       sd->expo12a = EXPO12A_DEF;
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init_12a(struct gspca_dev *gspca_dev)
+{
+       PDEBUG(D_STREAM, "Chip revision: 012a");
+       init_161rev12A(gspca_dev);
+       return 0;
+}
+static int sd_init_72a(struct gspca_dev *gspca_dev)
+{
+       PDEBUG(D_STREAM, "Chip revision: 072a");
+       write_vector(gspca_dev, rev72a_reset);
+       msleep(200);
+       write_vector(gspca_dev, rev72a_init_data1);
+       write_sensor_72a(gspca_dev, rev72a_init_sensor1);
+       write_vector(gspca_dev, rev72a_init_data2);
+       write_sensor_72a(gspca_dev, rev72a_init_sensor2);
+       reg_w_val(gspca_dev->dev, 0x8112, 0x30);
+       return 0;
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct usb_device *dev = gspca_dev->dev;
+       __u16 reg;
+
+       if (sd->chip_revision == Rev012A)
+               reg = 0x8610;
+       else
+               reg = 0x8611;
+
+       reg_w_val(dev, reg + 0, val);           /* R */
+       reg_w_val(dev, reg + 1, val);           /* Gr */
+       reg_w_val(dev, reg + 2, val);           /* B */
+       reg_w_val(dev, reg + 3, val);           /* Gb */
+}
+
+static void setwhite(struct gspca_dev *gspca_dev, s32 white, s32 contrast)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct usb_device *dev = gspca_dev->dev;
+       __u8 blue, red;
+       __u16 reg;
+
+       /* try to emulate MS-win as possible */
+       red = 0x20 + white * 3 / 8;
+       blue = 0x90 - white * 5 / 8;
+       if (sd->chip_revision == Rev012A) {
+               reg = 0x8614;
+       } else {
+               reg = 0x8651;
+               red += contrast - 0x20;
+               blue += contrast - 0x20;
+               reg_w_val(dev, 0x8652, contrast + 0x20); /* Gr */
+               reg_w_val(dev, 0x8654, contrast + 0x20); /* Gb */
+       }
+       reg_w_val(dev, reg, red);
+       reg_w_val(dev, reg + 2, blue);
+}
+
+/* rev 12a only */
+static void setexposure(struct gspca_dev *gspca_dev, s32 val)
+{
+       int i, expo = 0;
+
+       /* Register 0x8309 controls exposure for the spca561,
+          the basic exposure setting goes from 1-2047, where 1 is completely
+          dark and 2047 is very bright. It not only influences exposure but
+          also the framerate (to allow for longer exposure) from 1 - 300 it
+          only raises the exposure time then from 300 - 600 it halves the
+          framerate to be able to further raise the exposure time and for every
+          300 more it halves the framerate again. This allows for a maximum
+          exposure time of circa 0.2 - 0.25 seconds (30 / (2000/3000) fps).
+          Sometimes this is not enough, the 1-2047 uses bits 0-10, bits 11-12
+          configure a divider for the base framerate which us used at the
+          exposure setting of 1-300. These bits configure the base framerate
+          according to the following formula: fps = 60 / (value + 2) */
+
+       /* We choose to use the high bits setting the fixed framerate divisor
+          asap, as setting high basic exposure setting without the fixed
+          divider in combination with high gains makes the cam stop */
+       int table[] =  { 0, 450, 550, 625, EXPOSURE_MAX };
+
+       for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
+               if (val <= table[i + 1]) {
+                       expo  = val - table[i];
+                       if (i)
+                               expo += 300;
+                       expo |= i << 11;
+                       break;
+               }
+       }
+
+       gspca_dev->usb_buf[0] = expo;
+       gspca_dev->usb_buf[1] = expo >> 8;
+       reg_w_buf(gspca_dev, 0x8309, 2);
+}
+
+/* rev 12a only */
+static void setgain(struct gspca_dev *gspca_dev, s32 val)
+{
+       /* gain reg low 6 bits  0-63 gain, bit 6 and 7, both double the
+          sensitivity when set, so 31 + one of them set == 63, and 15
+          with both of them set == 63 */
+       if (val < 64)
+               gspca_dev->usb_buf[0] = val;
+       else if (val < 128)
+               gspca_dev->usb_buf[0] = (val / 2) | 0x40;
+       else
+               gspca_dev->usb_buf[0] = (val / 4) | 0xc0;
+
+       gspca_dev->usb_buf[1] = 0;
+       reg_w_buf(gspca_dev, 0x8335, 2);
+}
+
+static void setautogain(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (val)
+               sd->ag_cnt = AG_CNT_START;
+       else
+               sd->ag_cnt = -1;
+}
+
+static int sd_start_12a(struct gspca_dev *gspca_dev)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int mode;
+       static const __u8 Reg8391[8] =
+               {0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00};
+
+       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+       if (mode <= 1) {
+               /* Use compression on 320x240 and above */
+               reg_w_val(dev, 0x8500, 0x10 | mode);
+       } else {
+               /* I couldn't get the compression to work below 320x240
+                * Fortunately at these resolutions the bandwidth
+                * is sufficient to push raw frames at ~20fps */
+               reg_w_val(dev, 0x8500, mode);
+       }               /* -- qq@kuku.eu.org */
+
+       gspca_dev->usb_buf[0] = 0xaa;
+       gspca_dev->usb_buf[1] = 0x00;
+       reg_w_buf(gspca_dev, 0x8307, 2);
+       /* clock - lower 0x8X values lead to fps > 30 */
+       reg_w_val(gspca_dev->dev, 0x8700, 0x8a);
+                                       /* 0x8f 0x85 0x27 clock */
+       reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
+       reg_w_val(gspca_dev->dev, 0x850b, 0x03);
+       memcpy(gspca_dev->usb_buf, Reg8391, 8);
+       reg_w_buf(gspca_dev, 0x8391, 8);
+       reg_w_buf(gspca_dev, 0x8390, 8);
+
+       /* Led ON (bit 3 -> 0 */
+       reg_w_val(gspca_dev->dev, 0x8114, 0x00);
+       return 0;
+}
+static int sd_start_72a(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct usb_device *dev = gspca_dev->dev;
+       int Clck;
+       int mode;
+
+       write_vector(gspca_dev, rev72a_reset);
+       msleep(200);
+       write_vector(gspca_dev, rev72a_init_data1);
+       write_sensor_72a(gspca_dev, rev72a_init_sensor1);
+
+       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+       switch (mode) {
+       default:
+       case 0:
+               Clck = 0x27;            /* ms-win 0x87 */
+               break;
+       case 1:
+               Clck = 0x25;
+               break;
+       case 2:
+               Clck = 0x22;
+               break;
+       case 3:
+               Clck = 0x21;
+               break;
+       }
+       reg_w_val(dev, 0x8700, Clck);   /* 0x27 clock */
+       reg_w_val(dev, 0x8702, 0x81);
+       reg_w_val(dev, 0x8500, mode);   /* mode */
+       write_sensor_72a(gspca_dev, rev72a_init_sensor2);
+       setwhite(gspca_dev, v4l2_ctrl_g_ctrl(sd->hue),
+                       v4l2_ctrl_g_ctrl(sd->contrast));
+/*     setbrightness(gspca_dev);        * fixme: bad values */
+       setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
+       reg_w_val(dev, 0x8112, 0x10 | 0x20);
+       return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->chip_revision == Rev012A) {
+               reg_w_val(gspca_dev->dev, 0x8112, 0x0e);
+               /* Led Off (bit 3 -> 1 */
+               reg_w_val(gspca_dev->dev, 0x8114, 0x08);
+       } else {
+               reg_w_val(gspca_dev->dev, 0x8112, 0x20);
+/*             reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */
+       }
+}
+
+static void do_autogain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int expotimes;
+       int pixelclk;
+       int gainG;
+       __u8 R, Gr, Gb, B;
+       int y;
+       __u8 luma_mean = 110;
+       __u8 luma_delta = 20;
+       __u8 spring = 4;
+
+       if (sd->ag_cnt < 0)
+               return;
+       if (--sd->ag_cnt >= 0)
+               return;
+       sd->ag_cnt = AG_CNT_START;
+
+       switch (sd->chip_revision) {
+       case Rev072A:
+               reg_r(gspca_dev, 0x8621, 1);
+               Gr = gspca_dev->usb_buf[0];
+               reg_r(gspca_dev, 0x8622, 1);
+               R = gspca_dev->usb_buf[0];
+               reg_r(gspca_dev, 0x8623, 1);
+               B = gspca_dev->usb_buf[0];
+               reg_r(gspca_dev, 0x8624, 1);
+               Gb = gspca_dev->usb_buf[0];
+               y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8;
+               /* u= (128*B-(43*(Gr+Gb+R))) >> 8; */
+               /* v= (128*R-(53*(Gr+Gb))-21*B) >> 8; */
+               /* PDEBUG(D_CONF,"reading Y %d U %d V %d ",y,u,v); */
+
+               if (y < luma_mean - luma_delta ||
+                   y > luma_mean + luma_delta) {
+                       expotimes = i2c_read(gspca_dev, 0x09, 0x10);
+                       pixelclk = 0x0800;
+                       expotimes = expotimes & 0x07ff;
+                       /* PDEBUG(D_PACK,
+                               "Exposition Times 0x%03X Clock 0x%04X ",
+                               expotimes,pixelclk); */
+                       gainG = i2c_read(gspca_dev, 0x35, 0x10);
+                       /* PDEBUG(D_PACK,
+                               "reading Gain register %d", gainG); */
+
+                       expotimes += (luma_mean - y) >> spring;
+                       gainG += (luma_mean - y) / 50;
+                       /* PDEBUG(D_PACK,
+                               "compute expotimes %d gain %d",
+                               expotimes,gainG); */
+
+                       if (gainG > 0x3f)
+                               gainG = 0x3f;
+                       else if (gainG < 3)
+                               gainG = 3;
+                       i2c_write(gspca_dev, gainG, 0x35);
+
+                       if (expotimes > 0x0256)
+                               expotimes = 0x0256;
+                       else if (expotimes < 3)
+                               expotimes = 3;
+                       i2c_write(gspca_dev, expotimes | pixelclk, 0x09);
+               }
+               break;
+       }
+}
+
+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;
+
+       len--;
+       switch (*data++) {                      /* sequence number */
+       case 0:                                 /* start of frame */
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+
+               /* This should never happen */
+               if (len < 2) {
+                       PDEBUG(D_ERR, "Short SOF packet, ignoring");
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+                       return;
+               }
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+               if (data[0] & 0x20) {
+                       input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
+                       input_sync(gspca_dev->input_dev);
+                       input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+                       input_sync(gspca_dev->input_dev);
+               }
+#endif
+
+               if (data[1] & 0x10) {
+                       /* compressed bayer */
+                       gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
+               } else {
+                       /* raw bayer (with a header, which we skip) */
+                       if (sd->chip_revision == Rev012A) {
+                               data += 20;
+                               len -= 20;
+                       } else {
+                               data += 16;
+                               len -= 16;
+                       }
+                       gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
+               }
+               return;
+       case 0xff:                      /* drop (empty mpackets) */
+               return;
+       }
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+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_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               /* hue/contrast control cluster for 72a */
+               setwhite(gspca_dev, sd->hue->val, ctrl->val);
+               break;
+       case V4L2_CID_HUE:
+               /* just plain hue control for 12a */
+               setwhite(gspca_dev, ctrl->val, 0);
+               break;
+       case V4L2_CID_EXPOSURE:
+               setexposure(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_GAIN:
+               setgain(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               setautogain(gspca_dev, ctrl->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_12a(struct gspca_dev *gspca_dev)
+{
+       struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 3);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_HUE, 1, 0x7f, 1, 0x40);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 1, EXPOSURE_MAX, 1, 700);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 255, 1, 63);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       return 0;
+}
+
+static int sd_init_controls_72a(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);
+       sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 0x3f, 1, 0x20);
+       sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_HUE, 1, 0x7f, 1, 0x40);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 0x3f, 1, 0x20);
+       sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       v4l2_ctrl_cluster(2, &sd->contrast);
+       return 0;
+}
+
+/* sub-driver description */
+static const struct sd_desc sd_desc_12a = {
+       .name = MODULE_NAME,
+       .init_controls = sd_init_controls_12a,
+       .config = sd_config,
+       .init = sd_init_12a,
+       .start = sd_start_12a,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .other_input = 1,
+#endif
+};
+static const struct sd_desc sd_desc_72a = {
+       .name = MODULE_NAME,
+       .init_controls = sd_init_controls_72a,
+       .config = sd_config,
+       .init = sd_init_72a,
+       .start = sd_start_72a,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+       .dq_callback = do_autogain,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .other_input = 1,
+#endif
+};
+static const struct sd_desc *sd_desc[2] = {
+       &sd_desc_12a,
+       &sd_desc_72a
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A},
+       {USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A},
+       {USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A},
+       {USB_DEVICE(0x0461, 0x0815), .driver_info = Rev072A},
+       {USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A},
+       {USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A},
+       {USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A},
+       {USB_DEVICE(0x046d, 0x092b), .driver_info = Rev012A},
+       {USB_DEVICE(0x046d, 0x092c), .driver_info = Rev012A},
+       {USB_DEVICE(0x046d, 0x092d), .driver_info = Rev012A},
+       {USB_DEVICE(0x046d, 0x092e), .driver_info = Rev012A},
+       {USB_DEVICE(0x046d, 0x092f), .driver_info = Rev012A},
+       {USB_DEVICE(0x04fc, 0x0561), .driver_info = Rev072A},
+       {USB_DEVICE(0x060b, 0xa001), .driver_info = Rev072A},
+       {USB_DEVICE(0x10fd, 0x7e50), .driver_info = Rev072A},
+       {USB_DEVICE(0xabcd, 0xcdee), .driver_info = Rev072A},
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+                   const struct usb_device_id *id)
+{
+       return gspca_dev_probe(intf, id,
+                               sd_desc[id->driver_info],
+                               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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/sq905.c b/drivers/media/usb/gspca/sq905.c
new file mode 100644 (file)
index 0000000..a8ac979
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * SQ905 subdriver
+ *
+ * Copyright (C) 2008, 2009 Adam Baker and Theodore Kilgore
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * History and Acknowledgments
+ *
+ * The original Linux driver for SQ905 based cameras was written by
+ * Marcell Lengyel and furter developed by many other contributors
+ * and is available from http://sourceforge.net/projects/sqcam/
+ *
+ * This driver takes advantage of the reverse engineering work done for
+ * that driver and for libgphoto2 but shares no code with them.
+ *
+ * This driver has used as a base the finepix driver and other gspca
+ * based drivers and may still contain code fragments taken from those
+ * drivers.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "sq905"
+
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include "gspca.h"
+
+MODULE_AUTHOR("Adam Baker <linux@baker-net.org.uk>, "
+               "Theodore Kilgore <kilgota@auburn.edu>");
+MODULE_DESCRIPTION("GSPCA/SQ905 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* Default timeouts, in ms */
+#define SQ905_CMD_TIMEOUT 500
+#define SQ905_DATA_TIMEOUT 1000
+
+/* Maximum transfer size to use. */
+#define SQ905_MAX_TRANSFER 0x8000
+#define FRAME_HEADER_LEN 64
+
+/* The known modes, or registers. These go in the "value" slot. */
+
+/* 00 is "none" obviously */
+
+#define SQ905_BULK_READ        0x03    /* precedes any bulk read */
+#define SQ905_COMMAND  0x06    /* precedes the command codes below */
+#define SQ905_PING     0x07    /* when reading an "idling" command */
+#define SQ905_READ_DONE 0xc0    /* ack bulk read completed */
+
+/* Any non-zero value in the bottom 2 bits of the 2nd byte of
+ * the ID appears to indicate the camera can do 640*480. If the
+ * LSB of that byte is set the image is just upside down, otherwise
+ * it is rotated 180 degrees. */
+#define SQ905_HIRES_MASK       0x00000300
+#define SQ905_ORIENTATION_MASK 0x00000100
+
+/* Some command codes. These go in the "index" slot. */
+
+#define SQ905_ID      0xf0     /* asks for model string */
+#define SQ905_CONFIG  0x20     /* gets photo alloc. table, not used here */
+#define SQ905_DATA    0x30     /* accesses photo data, not used here */
+#define SQ905_CLEAR   0xa0     /* clear everything */
+#define SQ905_CAPTURE_LOW  0x60        /* Starts capture at 160x120 */
+#define SQ905_CAPTURE_MED  0x61        /* Starts capture at 320x240 */
+#define SQ905_CAPTURE_HIGH 0x62        /* Starts capture at 640x480 (some cams only) */
+/* note that the capture command also controls the output dimensions */
+
+/* Structure to hold all of our device specific stuff */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       /*
+        * Driver stuff
+        */
+       struct work_struct work_struct;
+       struct workqueue_struct *work_thread;
+};
+
+static struct v4l2_pix_format sq905_mode[] = {
+       { 160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+       { 320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+       { 640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0}
+};
+
+/*
+ * Send a command to the camera.
+ */
+static int sq905_command(struct gspca_dev *gspca_dev, u16 index)
+{
+       int ret;
+
+       gspca_dev->usb_buf[0] = '\0';
+       ret = usb_control_msg(gspca_dev->dev,
+                             usb_sndctrlpipe(gspca_dev->dev, 0),
+                             USB_REQ_SYNCH_FRAME,                /* request */
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             SQ905_COMMAND, index, gspca_dev->usb_buf, 1,
+                             SQ905_CMD_TIMEOUT);
+       if (ret < 0) {
+               pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
+               return ret;
+       }
+
+       ret = usb_control_msg(gspca_dev->dev,
+                             usb_sndctrlpipe(gspca_dev->dev, 0),
+                             USB_REQ_SYNCH_FRAME,                /* request */
+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             SQ905_PING, 0, gspca_dev->usb_buf, 1,
+                             SQ905_CMD_TIMEOUT);
+       if (ret < 0) {
+               pr_err("%s: usb_control_msg failed 2 (%d)\n", __func__, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+/*
+ * Acknowledge the end of a frame - see warning on sq905_command.
+ */
+static int sq905_ack_frame(struct gspca_dev *gspca_dev)
+{
+       int ret;
+
+       gspca_dev->usb_buf[0] = '\0';
+       ret = usb_control_msg(gspca_dev->dev,
+                             usb_sndctrlpipe(gspca_dev->dev, 0),
+                             USB_REQ_SYNCH_FRAME,                /* request */
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             SQ905_READ_DONE, 0, gspca_dev->usb_buf, 1,
+                             SQ905_CMD_TIMEOUT);
+       if (ret < 0) {
+               pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+/*
+ *  request and read a block of data - see warning on sq905_command.
+ */
+static int
+sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock)
+{
+       int ret;
+       int act_len;
+
+       gspca_dev->usb_buf[0] = '\0';
+       if (need_lock)
+               mutex_lock(&gspca_dev->usb_lock);
+       ret = usb_control_msg(gspca_dev->dev,
+                             usb_sndctrlpipe(gspca_dev->dev, 0),
+                             USB_REQ_SYNCH_FRAME,                /* request */
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             SQ905_BULK_READ, size, gspca_dev->usb_buf,
+                             1, SQ905_CMD_TIMEOUT);
+       if (need_lock)
+               mutex_unlock(&gspca_dev->usb_lock);
+       if (ret < 0) {
+               pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
+               return ret;
+       }
+       ret = usb_bulk_msg(gspca_dev->dev,
+                          usb_rcvbulkpipe(gspca_dev->dev, 0x81),
+                          data, size, &act_len, SQ905_DATA_TIMEOUT);
+
+       /* successful, it returns 0, otherwise  negative */
+       if (ret < 0 || act_len != size) {
+               pr_err("bulk read fail (%d) len %d/%d\n", ret, act_len, size);
+               return -EIO;
+       }
+       return 0;
+}
+
+/* This function is called as a workqueue function and runs whenever the camera
+ * is streaming data. Because it is a workqueue function it is allowed to sleep
+ * so we can use synchronous USB calls. To avoid possible collisions with other
+ * threads attempting to use the camera's USB interface we take the gspca
+ * usb_lock when performing USB operations. In practice the only thing we need
+ * to protect against is the usb_set_interface call that gspca makes during
+ * stream_off as the camera doesn't provide any controls that the user could try
+ * to change.
+ */
+static void sq905_dostream(struct work_struct *work)
+{
+       struct sd *dev = container_of(work, struct sd, work_struct);
+       struct gspca_dev *gspca_dev = &dev->gspca_dev;
+       int bytes_left; /* bytes remaining in current frame. */
+       int data_len;   /* size to use for the next read. */
+       int header_read; /* true if we have already read the frame header. */
+       int packet_type;
+       int frame_sz;
+       int ret;
+       u8 *data;
+       u8 *buffer;
+
+       buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
+       if (!buffer) {
+               pr_err("Couldn't allocate USB buffer\n");
+               goto quit_stream;
+       }
+
+       frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage
+                       + FRAME_HEADER_LEN;
+
+       while (gspca_dev->dev && gspca_dev->streaming) {
+#ifdef CONFIG_PM
+               if (gspca_dev->frozen)
+                       break;
+#endif
+               /* request some data and then read it until we have
+                * a complete frame. */
+               bytes_left = frame_sz;
+               header_read = 0;
+
+               /* Note we do not check for gspca_dev->streaming here, as
+                  we must finish reading an entire frame, otherwise the
+                  next time we stream we start reading in the middle of a
+                  frame. */
+               while (bytes_left > 0 && gspca_dev->dev) {
+                       data_len = bytes_left > SQ905_MAX_TRANSFER ?
+                               SQ905_MAX_TRANSFER : bytes_left;
+                       ret = sq905_read_data(gspca_dev, buffer, data_len, 1);
+                       if (ret < 0)
+                               goto quit_stream;
+                       PDEBUG(D_PACK,
+                               "Got %d bytes out of %d for frame",
+                               data_len, bytes_left);
+                       bytes_left -= data_len;
+                       data = buffer;
+                       if (!header_read) {
+                               packet_type = FIRST_PACKET;
+                               /* The first 64 bytes of each frame are
+                                * a header full of FF 00 bytes */
+                               data += FRAME_HEADER_LEN;
+                               data_len -= FRAME_HEADER_LEN;
+                               header_read = 1;
+                       } else if (bytes_left == 0) {
+                               packet_type = LAST_PACKET;
+                       } else {
+                               packet_type = INTER_PACKET;
+                       }
+                       gspca_frame_add(gspca_dev, packet_type,
+                                       data, data_len);
+                       /* If entire frame fits in one packet we still
+                          need to add a LAST_PACKET */
+                       if (packet_type == FIRST_PACKET &&
+                           bytes_left == 0)
+                               gspca_frame_add(gspca_dev, LAST_PACKET,
+                                               NULL, 0);
+               }
+               if (gspca_dev->dev) {
+                       /* acknowledge the frame */
+                       mutex_lock(&gspca_dev->usb_lock);
+                       ret = sq905_ack_frame(gspca_dev);
+                       mutex_unlock(&gspca_dev->usb_lock);
+                       if (ret < 0)
+                               goto quit_stream;
+               }
+       }
+quit_stream:
+       if (gspca_dev->dev) {
+               mutex_lock(&gspca_dev->usb_lock);
+               sq905_command(gspca_dev, SQ905_CLEAR);
+               mutex_unlock(&gspca_dev->usb_lock);
+       }
+       kfree(buffer);
+}
+
+/* This function is called at probe time just before sd_init */
+static int sd_config(struct gspca_dev *gspca_dev,
+               const struct usb_device_id *id)
+{
+       struct cam *cam = &gspca_dev->cam;
+       struct sd *dev = (struct sd *) gspca_dev;
+
+       /* We don't use the buffer gspca allocates so make it small. */
+       cam->bulk = 1;
+       cam->bulk_size = 64;
+
+       INIT_WORK(&dev->work_struct, sq905_dostream);
+
+       return 0;
+}
+
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct sd *dev = (struct sd *) gspca_dev;
+
+       /* wait for the work queue to terminate */
+       mutex_unlock(&gspca_dev->usb_lock);
+       /* This waits for sq905_dostream to finish */
+       destroy_workqueue(dev->work_thread);
+       dev->work_thread = NULL;
+       mutex_lock(&gspca_dev->usb_lock);
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       u32 ident;
+       int ret;
+
+       /* connect to the camera and read
+        * the model ID and process that and put it away.
+        */
+       ret = sq905_command(gspca_dev, SQ905_CLEAR);
+       if (ret < 0)
+               return ret;
+       ret = sq905_command(gspca_dev, SQ905_ID);
+       if (ret < 0)
+               return ret;
+       ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4, 0);
+       if (ret < 0)
+               return ret;
+       /* usb_buf is allocated with kmalloc so is aligned.
+        * Camera model number is the right way round if we assume this
+        * reverse engineered ID is supposed to be big endian. */
+       ident = be32_to_cpup((__be32 *)gspca_dev->usb_buf);
+       ret = sq905_command(gspca_dev, SQ905_CLEAR);
+       if (ret < 0)
+               return ret;
+       PDEBUG(D_CONF, "SQ905 camera ID %08x detected", ident);
+       gspca_dev->cam.cam_mode = sq905_mode;
+       gspca_dev->cam.nmodes = ARRAY_SIZE(sq905_mode);
+       if (!(ident & SQ905_HIRES_MASK))
+               gspca_dev->cam.nmodes--;
+
+       if (ident & SQ905_ORIENTATION_MASK)
+               gspca_dev->cam.input_flags = V4L2_IN_ST_VFLIP;
+       else
+               gspca_dev->cam.input_flags = V4L2_IN_ST_VFLIP |
+                                            V4L2_IN_ST_HFLIP;
+       return 0;
+}
+
+/* Set up for getting frames. */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *dev = (struct sd *) gspca_dev;
+       int ret;
+
+       /* "Open the shutter" and set size, to start capture */
+       switch (gspca_dev->curr_mode) {
+       default:
+/*     case 2: */
+               PDEBUG(D_STREAM, "Start streaming at high resolution");
+               ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_HIGH);
+               break;
+       case 1:
+               PDEBUG(D_STREAM, "Start streaming at medium resolution");
+               ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED);
+               break;
+       case 0:
+               PDEBUG(D_STREAM, "Start streaming at low resolution");
+               ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_LOW);
+       }
+
+       if (ret < 0) {
+               PDEBUG(D_ERR, "Start streaming command failed");
+               return ret;
+       }
+       /* Start the workqueue function to do the streaming */
+       dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
+       queue_work(dev->work_thread, &dev->work_struct);
+
+       return 0;
+}
+
+/* Table of supported USB devices */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x2770, 0x9120)},
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name   = MODULE_NAME,
+       .config = sd_config,
+       .init   = sd_init,
+       .start  = sd_start,
+       .stop0  = sd_stop0,
+};
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/sq905c.c b/drivers/media/usb/gspca/sq905c.c
new file mode 100644 (file)
index 0000000..70fae69
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * SQ905C subdriver
+ *
+ * Copyright (C) 2009 Theodore Kilgore
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ *
+ * This driver uses work done in
+ * libgphoto2/camlibs/digigr8, Copyright (C) Theodore Kilgore.
+ *
+ * This driver has also used as a base the sq905c driver
+ * and may contain code fragments from it.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "sq905c"
+
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include "gspca.h"
+
+MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
+MODULE_DESCRIPTION("GSPCA/SQ905C USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* Default timeouts, in ms */
+#define SQ905C_CMD_TIMEOUT 500
+#define SQ905C_DATA_TIMEOUT 1000
+
+/* Maximum transfer size to use. */
+#define SQ905C_MAX_TRANSFER 0x8000
+
+#define FRAME_HEADER_LEN 0x50
+
+/* Commands. These go in the "value" slot. */
+#define SQ905C_CLEAR   0xa0            /* clear everything */
+#define SQ905C_GET_ID  0x14f4          /* Read version number */
+#define SQ905C_CAPTURE_LOW 0xa040      /* Starts capture at 160x120 */
+#define SQ905C_CAPTURE_MED 0x1440      /* Starts capture at 320x240 */
+#define SQ905C_CAPTURE_HI 0x2840       /* Starts capture at 320x240 */
+
+/* For capture, this must go in the "index" slot. */
+#define SQ905C_CAPTURE_INDEX 0x110f
+
+/* Structure to hold all of our device specific stuff */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+       const struct v4l2_pix_format *cap_mode;
+       /* Driver stuff */
+       struct work_struct work_struct;
+       struct workqueue_struct *work_thread;
+};
+
+/*
+ * Most of these cameras will do 640x480 and 320x240. 160x120 works
+ * in theory but gives very poor output. Therefore, not supported.
+ * The 0x2770:0x9050 cameras have max resolution of 320x240.
+ */
+static struct v4l2_pix_format sq905c_mode[] = {
+       { 320, 240, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+       { 640, 480, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0}
+};
+
+/* Send a command to the camera. */
+static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index)
+{
+       int ret;
+
+       ret = usb_control_msg(gspca_dev->dev,
+                             usb_sndctrlpipe(gspca_dev->dev, 0),
+                             USB_REQ_SYNCH_FRAME,                /* request */
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             command, index, NULL, 0,
+                             SQ905C_CMD_TIMEOUT);
+       if (ret < 0) {
+               pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index,
+                      int size)
+{
+       int ret;
+
+       ret = usb_control_msg(gspca_dev->dev,
+                             usb_rcvctrlpipe(gspca_dev->dev, 0),
+                             USB_REQ_SYNCH_FRAME,              /* request */
+                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             command, index, gspca_dev->usb_buf, size,
+                             SQ905C_CMD_TIMEOUT);
+       if (ret < 0) {
+               pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+/* This function is called as a workqueue function and runs whenever the camera
+ * is streaming data. Because it is a workqueue function it is allowed to sleep
+ * so we can use synchronous USB calls. To avoid possible collisions with other
+ * threads attempting to use the camera's USB interface the gspca usb_lock is
+ * used when performing the one USB control operation inside the workqueue,
+ * which tells the camera to close the stream. In practice the only thing
+ * which needs to be protected against is the usb_set_interface call that
+ * gspca makes during stream_off. Otherwise the camera doesn't provide any
+ * controls that the user could try to change.
+ */
+static void sq905c_dostream(struct work_struct *work)
+{
+       struct sd *dev = container_of(work, struct sd, work_struct);
+       struct gspca_dev *gspca_dev = &dev->gspca_dev;
+       int bytes_left; /* bytes remaining in current frame. */
+       int data_len;   /* size to use for the next read. */
+       int act_len;
+       int packet_type;
+       int ret;
+       u8 *buffer;
+
+       buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
+       if (!buffer) {
+               pr_err("Couldn't allocate USB buffer\n");
+               goto quit_stream;
+       }
+
+       while (gspca_dev->dev && gspca_dev->streaming) {
+#ifdef CONFIG_PM
+               if (gspca_dev->frozen)
+                       break;
+#endif
+               /* Request the header, which tells the size to download */
+               ret = usb_bulk_msg(gspca_dev->dev,
+                               usb_rcvbulkpipe(gspca_dev->dev, 0x81),
+                               buffer, FRAME_HEADER_LEN, &act_len,
+                               SQ905C_DATA_TIMEOUT);
+               PDEBUG(D_STREAM,
+                       "Got %d bytes out of %d for header",
+                       act_len, FRAME_HEADER_LEN);
+               if (ret < 0 || act_len < FRAME_HEADER_LEN)
+                       goto quit_stream;
+               /* size is read from 4 bytes starting 0x40, little endian */
+               bytes_left = buffer[0x40]|(buffer[0x41]<<8)|(buffer[0x42]<<16)
+                                       |(buffer[0x43]<<24);
+               PDEBUG(D_STREAM, "bytes_left = 0x%x", bytes_left);
+               /* We keep the header. It has other information, too. */
+               packet_type = FIRST_PACKET;
+               gspca_frame_add(gspca_dev, packet_type,
+                               buffer, FRAME_HEADER_LEN);
+               while (bytes_left > 0 && gspca_dev->dev) {
+                       data_len = bytes_left > SQ905C_MAX_TRANSFER ?
+                               SQ905C_MAX_TRANSFER : bytes_left;
+                       ret = usb_bulk_msg(gspca_dev->dev,
+                               usb_rcvbulkpipe(gspca_dev->dev, 0x81),
+                               buffer, data_len, &act_len,
+                               SQ905C_DATA_TIMEOUT);
+                       if (ret < 0 || act_len < data_len)
+                               goto quit_stream;
+                       PDEBUG(D_STREAM,
+                               "Got %d bytes out of %d for frame",
+                               data_len, bytes_left);
+                       bytes_left -= data_len;
+                       if (bytes_left == 0)
+                               packet_type = LAST_PACKET;
+                       else
+                               packet_type = INTER_PACKET;
+                       gspca_frame_add(gspca_dev, packet_type,
+                                       buffer, data_len);
+               }
+       }
+quit_stream:
+       if (gspca_dev->dev) {
+               mutex_lock(&gspca_dev->usb_lock);
+               sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
+               mutex_unlock(&gspca_dev->usb_lock);
+       }
+       kfree(buffer);
+}
+
+/* This function is called at probe time just before sd_init */
+static int sd_config(struct gspca_dev *gspca_dev,
+               const struct usb_device_id *id)
+{
+       struct cam *cam = &gspca_dev->cam;
+       struct sd *dev = (struct sd *) gspca_dev;
+       int ret;
+
+       PDEBUG(D_PROBE,
+               "SQ9050 camera detected"
+               " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+
+       ret = sq905c_command(gspca_dev, SQ905C_GET_ID, 0);
+       if (ret < 0) {
+               PDEBUG(D_ERR, "Get version command failed");
+               return ret;
+       }
+
+       ret = sq905c_read(gspca_dev, 0xf5, 0, 20);
+       if (ret < 0) {
+               PDEBUG(D_ERR, "Reading version command failed");
+               return ret;
+       }
+       /* Note we leave out the usb id and the manufacturing date */
+       PDEBUG(D_PROBE,
+              "SQ9050 ID string: %02x - %*ph",
+               gspca_dev->usb_buf[3], 6, gspca_dev->usb_buf + 14);
+
+       cam->cam_mode = sq905c_mode;
+       cam->nmodes = 2;
+       if (gspca_dev->usb_buf[15] == 0)
+               cam->nmodes = 1;
+       /* We don't use the buffer gspca allocates so make it small. */
+       cam->bulk_size = 32;
+       cam->bulk = 1;
+       INIT_WORK(&dev->work_struct, sq905c_dostream);
+       return 0;
+}
+
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct sd *dev = (struct sd *) gspca_dev;
+
+       /* wait for the work queue to terminate */
+       mutex_unlock(&gspca_dev->usb_lock);
+       /* This waits for sq905c_dostream to finish */
+       destroy_workqueue(dev->work_thread);
+       dev->work_thread = NULL;
+       mutex_lock(&gspca_dev->usb_lock);
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       int ret;
+
+       /* connect to the camera and reset it. */
+       ret = sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
+       return ret;
+}
+
+/* Set up for getting frames. */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *dev = (struct sd *) gspca_dev;
+       int ret;
+
+       dev->cap_mode = gspca_dev->cam.cam_mode;
+       /* "Open the shutter" and set size, to start capture */
+       switch (gspca_dev->width) {
+       case 640:
+               PDEBUG(D_STREAM, "Start streaming at high resolution");
+               dev->cap_mode++;
+               ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_HI,
+                                               SQ905C_CAPTURE_INDEX);
+               break;
+       default: /* 320 */
+       PDEBUG(D_STREAM, "Start streaming at medium resolution");
+               ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_MED,
+                                               SQ905C_CAPTURE_INDEX);
+       }
+
+       if (ret < 0) {
+               PDEBUG(D_ERR, "Start streaming command failed");
+               return ret;
+       }
+       /* Start the workqueue function to do the streaming */
+       dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
+       queue_work(dev->work_thread, &dev->work_struct);
+
+       return 0;
+}
+
+/* Table of supported USB devices */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x2770, 0x905c)},
+       {USB_DEVICE(0x2770, 0x9050)},
+       {USB_DEVICE(0x2770, 0x9051)},
+       {USB_DEVICE(0x2770, 0x9052)},
+       {USB_DEVICE(0x2770, 0x913d)},
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name   = MODULE_NAME,
+       .config = sd_config,
+       .init   = sd_init,
+       .start  = sd_start,
+       .stop0  = sd_stop0,
+};
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/sq930x.c b/drivers/media/usb/gspca/sq930x.c
new file mode 100644 (file)
index 0000000..7e8748b
--- /dev/null
@@ -0,0 +1,1164 @@
+/*
+ * SQ930x subdriver
+ *
+ * Copyright (C) 2010 Jean-François Moine <http://moinejf.free.fr>
+ * Copyright (C) 2006 -2008 Gerard Klaver <gerard at gkall dot hobby dot nl>
+ * Copyright (C) 2007 Sam Revitch <samr7@cs.washington.edu>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "sq930x"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>\n"
+               "Gerard Klaver <gerard at gkall dot hobby dot nl\n"
+               "Sam Revitch <samr7@cs.washington.edu>");
+MODULE_DESCRIPTION("GSPCA/SQ930x USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* Structure to hold all of our device specific stuff */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       struct { /* exposure/gain control cluster */
+               struct v4l2_ctrl *exposure;
+               struct v4l2_ctrl *gain;
+       };
+
+       u8 do_ctrl;
+       u8 gpio[2];
+       u8 sensor;
+       u8 type;
+#define Generic 0
+#define Creative_live_motion 1
+};
+enum sensors {
+       SENSOR_ICX098BQ,
+       SENSOR_LZ24BP,
+       SENSOR_MI0360,
+       SENSOR_MT9V111,         /* = MI360SOC */
+       SENSOR_OV7660,
+       SENSOR_OV9630,
+};
+
+static struct v4l2_pix_format vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_SRGGB8, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+       {640, 480, V4L2_PIX_FMT_SRGGB8, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+};
+
+/* sq930x registers */
+#define SQ930_CTRL_UCBUS_IO    0x0001
+#define SQ930_CTRL_I2C_IO      0x0002
+#define SQ930_CTRL_GPIO                0x0005
+#define SQ930_CTRL_CAP_START   0x0010
+#define SQ930_CTRL_CAP_STOP    0x0011
+#define SQ930_CTRL_SET_EXPOSURE 0x001d
+#define SQ930_CTRL_RESET       0x001e
+#define SQ930_CTRL_GET_DEV_INFO 0x001f
+
+/* gpio 1 (8..15) */
+#define SQ930_GPIO_DFL_I2C_SDA 0x0001
+#define SQ930_GPIO_DFL_I2C_SCL 0x0002
+#define SQ930_GPIO_RSTBAR      0x0004
+#define SQ930_GPIO_EXTRA1      0x0040
+#define SQ930_GPIO_EXTRA2      0x0080
+/* gpio 3 (24..31) */
+#define SQ930_GPIO_POWER       0x0200
+#define SQ930_GPIO_DFL_LED     0x1000
+
+struct ucbus_write_cmd {
+       u16     bw_addr;
+       u8      bw_data;
+};
+struct i2c_write_cmd {
+       u8      reg;
+       u16     val;
+};
+
+static const struct ucbus_write_cmd icx098bq_start_0[] = {
+       {0x0354, 0x00}, {0x03fa, 0x00}, {0xf800, 0x02}, {0xf801, 0xce},
+       {0xf802, 0xc1}, {0xf804, 0x00}, {0xf808, 0x00}, {0xf809, 0x0e},
+       {0xf80a, 0x01}, {0xf80b, 0xee}, {0xf807, 0x60}, {0xf80c, 0x02},
+       {0xf80d, 0xf0}, {0xf80e, 0x03}, {0xf80f, 0x0a}, {0xf81c, 0x02},
+       {0xf81d, 0xf0}, {0xf81e, 0x03}, {0xf81f, 0x0a}, {0xf83a, 0x00},
+       {0xf83b, 0x10}, {0xf83c, 0x00}, {0xf83d, 0x4e}, {0xf810, 0x04},
+       {0xf811, 0x00}, {0xf812, 0x02}, {0xf813, 0x10}, {0xf803, 0x00},
+       {0xf814, 0x01}, {0xf815, 0x18}, {0xf816, 0x00}, {0xf817, 0x48},
+       {0xf818, 0x00}, {0xf819, 0x25}, {0xf81a, 0x00}, {0xf81b, 0x3c},
+       {0xf82f, 0x03}, {0xf820, 0xff}, {0xf821, 0x0d}, {0xf822, 0xff},
+       {0xf823, 0x07}, {0xf824, 0xff}, {0xf825, 0x03}, {0xf826, 0xff},
+       {0xf827, 0x06}, {0xf828, 0xff}, {0xf829, 0x03}, {0xf82a, 0xff},
+       {0xf82b, 0x0c}, {0xf82c, 0xfd}, {0xf82d, 0x01}, {0xf82e, 0x00},
+       {0xf830, 0x00}, {0xf831, 0x47}, {0xf832, 0x00}, {0xf833, 0x00},
+       {0xf850, 0x00}, {0xf851, 0x00}, {0xf852, 0x00}, {0xf853, 0x24},
+       {0xf854, 0x00}, {0xf855, 0x18}, {0xf856, 0x00}, {0xf857, 0x3c},
+       {0xf858, 0x00}, {0xf859, 0x0c}, {0xf85a, 0x00}, {0xf85b, 0x30},
+       {0xf85c, 0x00}, {0xf85d, 0x0c}, {0xf85e, 0x00}, {0xf85f, 0x30},
+       {0xf860, 0x00}, {0xf861, 0x48}, {0xf862, 0x01}, {0xf863, 0xdc},
+       {0xf864, 0xff}, {0xf865, 0x98}, {0xf866, 0xff}, {0xf867, 0xc0},
+       {0xf868, 0xff}, {0xf869, 0x70}, {0xf86c, 0xff}, {0xf86d, 0x00},
+       {0xf86a, 0xff}, {0xf86b, 0x48}, {0xf86e, 0xff}, {0xf86f, 0x00},
+       {0xf870, 0x01}, {0xf871, 0xdb}, {0xf872, 0x01}, {0xf873, 0xfa},
+       {0xf874, 0x01}, {0xf875, 0xdb}, {0xf876, 0x01}, {0xf877, 0xfa},
+       {0xf878, 0x0f}, {0xf879, 0x0f}, {0xf87a, 0xff}, {0xf87b, 0xff},
+       {0xf800, 0x03}
+};
+static const struct ucbus_write_cmd icx098bq_start_1[] = {
+       {0xf5f0, 0x00}, {0xf5f1, 0xcd}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
+       {0xf5f4, 0xc0},
+       {0xf5f0, 0x49}, {0xf5f1, 0xcd}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
+       {0xf5f4, 0xc0},
+       {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
+       {0xf5f9, 0x00}
+};
+
+static const struct ucbus_write_cmd icx098bq_start_2[] = {
+       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x82}, {0xf806, 0x00},
+       {0xf807, 0x7f}, {0xf800, 0x03},
+       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x40}, {0xf806, 0x00},
+       {0xf807, 0x7f}, {0xf800, 0x03},
+       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0xcf}, {0xf806, 0xd0},
+       {0xf807, 0x7f}, {0xf800, 0x03},
+       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x00}, {0xf806, 0x00},
+       {0xf807, 0x7f}, {0xf800, 0x03}
+};
+
+static const struct ucbus_write_cmd lz24bp_start_0[] = {
+       {0x0354, 0x00}, {0x03fa, 0x00}, {0xf800, 0x02}, {0xf801, 0xbe},
+       {0xf802, 0xc6}, {0xf804, 0x00}, {0xf808, 0x00}, {0xf809, 0x06},
+       {0xf80a, 0x01}, {0xf80b, 0xfe}, {0xf807, 0x84}, {0xf80c, 0x02},
+       {0xf80d, 0xf7}, {0xf80e, 0x03}, {0xf80f, 0x0b}, {0xf81c, 0x00},
+       {0xf81d, 0x49}, {0xf81e, 0x03}, {0xf81f, 0x0b}, {0xf83a, 0x00},
+       {0xf83b, 0x01}, {0xf83c, 0x00}, {0xf83d, 0x6b}, {0xf810, 0x03},
+       {0xf811, 0x10}, {0xf812, 0x02}, {0xf813, 0x6f}, {0xf803, 0x00},
+       {0xf814, 0x00}, {0xf815, 0x44}, {0xf816, 0x00}, {0xf817, 0x48},
+       {0xf818, 0x00}, {0xf819, 0x25}, {0xf81a, 0x00}, {0xf81b, 0x3c},
+       {0xf82f, 0x03}, {0xf820, 0xff}, {0xf821, 0x0d}, {0xf822, 0xff},
+       {0xf823, 0x07}, {0xf824, 0xfd}, {0xf825, 0x07}, {0xf826, 0xf0},
+       {0xf827, 0x0c}, {0xf828, 0xff}, {0xf829, 0x03}, {0xf82a, 0xff},
+       {0xf82b, 0x0c}, {0xf82c, 0xfc}, {0xf82d, 0x01}, {0xf82e, 0x00},
+       {0xf830, 0x00}, {0xf831, 0x47}, {0xf832, 0x00}, {0xf833, 0x00},
+       {0xf850, 0x00}, {0xf851, 0x00}, {0xf852, 0x00}, {0xf853, 0x24},
+       {0xf854, 0x00}, {0xf855, 0x0c}, {0xf856, 0x00}, {0xf857, 0x30},
+       {0xf858, 0x00}, {0xf859, 0x18}, {0xf85a, 0x00}, {0xf85b, 0x3c},
+       {0xf85c, 0x00}, {0xf85d, 0x18}, {0xf85e, 0x00}, {0xf85f, 0x3c},
+       {0xf860, 0xff}, {0xf861, 0x37}, {0xf862, 0xff}, {0xf863, 0x1d},
+       {0xf864, 0xff}, {0xf865, 0x98}, {0xf866, 0xff}, {0xf867, 0xc0},
+       {0xf868, 0x00}, {0xf869, 0x37}, {0xf86c, 0x02}, {0xf86d, 0x1d},
+       {0xf86a, 0x00}, {0xf86b, 0x37}, {0xf86e, 0x02}, {0xf86f, 0x1d},
+       {0xf870, 0x01}, {0xf871, 0xc6}, {0xf872, 0x02}, {0xf873, 0x04},
+       {0xf874, 0x01}, {0xf875, 0xc6}, {0xf876, 0x02}, {0xf877, 0x04},
+       {0xf878, 0x0f}, {0xf879, 0x0f}, {0xf87a, 0xff}, {0xf87b, 0xff},
+       {0xf800, 0x03}
+};
+static const struct ucbus_write_cmd lz24bp_start_1_gen[] = {
+       {0xf5f0, 0x00}, {0xf5f1, 0xff}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
+       {0xf5f4, 0xb3},
+       {0xf5f0, 0x40}, {0xf5f1, 0xff}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
+       {0xf5f4, 0xb3},
+       {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
+       {0xf5f9, 0x00}
+};
+
+static const struct ucbus_write_cmd lz24bp_start_1_clm[] = {
+       {0xf5f0, 0x00}, {0xf5f1, 0xff}, {0xf5f2, 0x88}, {0xf5f3, 0x88},
+       {0xf5f4, 0xc0},
+       {0xf5f0, 0x40}, {0xf5f1, 0xff}, {0xf5f2, 0x88}, {0xf5f3, 0x88},
+       {0xf5f4, 0xc0},
+       {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
+       {0xf5f9, 0x00}
+};
+
+static const struct ucbus_write_cmd lz24bp_start_2[] = {
+       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x80}, {0xf806, 0x00},
+       {0xf807, 0x7f}, {0xf800, 0x03},
+       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x4e}, {0xf806, 0x00},
+       {0xf807, 0x7f}, {0xf800, 0x03},
+       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0xc0}, {0xf806, 0x48},
+       {0xf807, 0x7f}, {0xf800, 0x03},
+       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x00}, {0xf806, 0x00},
+       {0xf807, 0x7f}, {0xf800, 0x03}
+};
+
+static const struct ucbus_write_cmd mi0360_start_0[] = {
+       {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0xcc}, {0xf333, 0xcc},
+       {0xf334, 0xcc}, {0xf335, 0xcc}, {0xf33f, 0x00}
+};
+static const struct i2c_write_cmd mi0360_init_23[] = {
+       {0x30, 0x0040},         /* reserved - def 0x0005 */
+       {0x31, 0x0000},         /* reserved - def 0x002a */
+       {0x34, 0x0100},         /* reserved - def 0x0100 */
+       {0x3d, 0x068f},         /* reserved - def 0x068f */
+};
+static const struct i2c_write_cmd mi0360_init_24[] = {
+       {0x03, 0x01e5},         /* window height */
+       {0x04, 0x0285},         /* window width */
+};
+static const struct i2c_write_cmd mi0360_init_25[] = {
+       {0x35, 0x0020},         /* global gain */
+       {0x2b, 0x0020},         /* green1 gain */
+       {0x2c, 0x002a},         /* blue gain */
+       {0x2d, 0x0028},         /* red gain */
+       {0x2e, 0x0020},         /* green2 gain */
+};
+static const struct ucbus_write_cmd mi0360_start_1[] = {
+       {0xf5f0, 0x11}, {0xf5f1, 0x99}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
+       {0xf5f4, 0xa6},
+       {0xf5f0, 0x51}, {0xf5f1, 0x99}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
+       {0xf5f4, 0xa6},
+       {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
+       {0xf5f9, 0x00}
+};
+static const struct i2c_write_cmd mi0360_start_2[] = {
+       {0x62, 0x041d},         /* reserved - def 0x0418 */
+};
+static const struct i2c_write_cmd mi0360_start_3[] = {
+       {0x05, 0x007b},         /* horiz blanking */
+};
+static const struct i2c_write_cmd mi0360_start_4[] = {
+       {0x05, 0x03f5},         /* horiz blanking */
+};
+
+static const struct i2c_write_cmd mt9v111_init_0[] = {
+       {0x01, 0x0001},         /* select IFP/SOC registers */
+       {0x06, 0x300c},         /* operating mode control */
+       {0x08, 0xcc00},         /* output format control (RGB) */
+       {0x01, 0x0004},         /* select sensor core registers */
+};
+static const struct i2c_write_cmd mt9v111_init_1[] = {
+       {0x03, 0x01e5},         /* window height */
+       {0x04, 0x0285},         /* window width */
+};
+static const struct i2c_write_cmd mt9v111_init_2[] = {
+       {0x30, 0x7800},
+       {0x31, 0x0000},
+       {0x07, 0x3002},         /* output control */
+       {0x35, 0x0020},         /* global gain */
+       {0x2b, 0x0020},         /* green1 gain */
+       {0x2c, 0x0020},         /* blue gain */
+       {0x2d, 0x0020},         /* red gain */
+       {0x2e, 0x0020},         /* green2 gain */
+};
+static const struct ucbus_write_cmd mt9v111_start_1[] = {
+       {0xf5f0, 0x11}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
+       {0xf5f4, 0xaa},
+       {0xf5f0, 0x51}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
+       {0xf5f4, 0xaa},
+       {0xf5fa, 0x00}, {0xf5f6, 0x0a}, {0xf5f7, 0x0a}, {0xf5f8, 0x0a},
+       {0xf5f9, 0x0a}
+};
+static const struct i2c_write_cmd mt9v111_init_3[] = {
+       {0x62, 0x0405},
+};
+static const struct i2c_write_cmd mt9v111_init_4[] = {
+/*     {0x05, 0x00ce}, */
+       {0x05, 0x005d},         /* horizontal blanking */
+};
+
+static const struct ucbus_write_cmd ov7660_start_0[] = {
+       {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0xc0},
+       {0xf334, 0x39}, {0xf335, 0xe7}, {0xf33f, 0x03}
+};
+
+static const struct ucbus_write_cmd ov9630_start_0[] = {
+       {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0x00},
+       {0xf334, 0x3e}, {0xf335, 0xf8}, {0xf33f, 0x03}
+};
+
+/* start parameters indexed by [sensor][mode] */
+static const struct cap_s {
+       u8      cc_sizeid;
+       u8      cc_bytes[32];
+} capconfig[4][2] = {
+       [SENSOR_ICX098BQ] = {
+               {2,                             /* Bayer 320x240 */
+                 {0x05, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee,
+                  0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
+               {4,                             /* Bayer 640x480 */
+                 {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee,
+                  0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
+       },
+       [SENSOR_LZ24BP] = {
+               {2,                             /* Bayer 320x240 */
+                 {0x05, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee,
+                  0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
+               {4,                             /* Bayer 640x480 */
+                 {0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee,
+                  0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
+       },
+       [SENSOR_MI0360] = {
+               {2,                             /* Bayer 320x240 */
+                 {0x05, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
+                  0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
+               {4,                             /* Bayer 640x480 */
+                 {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
+                  0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
+       },
+       [SENSOR_MT9V111] = {
+               {2,                             /* Bayer 320x240 */
+                 {0x05, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
+                  0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
+               {4,                             /* Bayer 640x480 */
+                 {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
+                  0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
+       },
+};
+
+struct sensor_s {
+       const char *name;
+       u8 i2c_addr;
+       u8 i2c_dum;
+       u8 gpio[5];
+       u8 cmd_len;
+       const struct ucbus_write_cmd *cmd;
+};
+
+static const struct sensor_s sensor_tb[] = {
+       [SENSOR_ICX098BQ] = {
+               "icx098bp",
+               0x00, 0x00,
+               {0,
+                SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
+                SQ930_GPIO_DFL_I2C_SDA,
+                0,
+                SQ930_GPIO_RSTBAR
+               },
+               8, icx098bq_start_0
+           },
+       [SENSOR_LZ24BP] = {
+               "lz24bp",
+               0x00, 0x00,
+               {0,
+                SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
+                SQ930_GPIO_DFL_I2C_SDA,
+                0,
+                SQ930_GPIO_RSTBAR
+               },
+               8, lz24bp_start_0
+           },
+       [SENSOR_MI0360] = {
+               "mi0360",
+               0x5d, 0x80,
+               {SQ930_GPIO_RSTBAR,
+                SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
+                SQ930_GPIO_DFL_I2C_SDA,
+                0,
+                0
+               },
+               7, mi0360_start_0
+           },
+       [SENSOR_MT9V111] = {
+               "mt9v111",
+               0x5c, 0x7f,
+               {SQ930_GPIO_RSTBAR,
+                SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
+                SQ930_GPIO_DFL_I2C_SDA,
+                0,
+                0
+               },
+               7, mi0360_start_0
+           },
+       [SENSOR_OV7660] = {
+               "ov7660",
+               0x21, 0x00,
+               {0,
+                SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
+                SQ930_GPIO_DFL_I2C_SDA,
+                0,
+                SQ930_GPIO_RSTBAR
+               },
+               7, ov7660_start_0
+           },
+       [SENSOR_OV9630] = {
+               "ov9630",
+               0x30, 0x00,
+               {0,
+                SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
+                SQ930_GPIO_DFL_I2C_SDA,
+                0,
+                SQ930_GPIO_RSTBAR
+               },
+               7, ov9630_start_0
+           },
+};
+
+static void reg_r(struct gspca_dev *gspca_dev,
+               u16 value, int len)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       0x0c,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, 0, gspca_dev->usb_buf, len,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_r %04x failed %d\n", value, ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       PDEBUG(D_USBO, "reg_w v: %04x i: %04x", value, index);
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x0c,                   /* request */
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index, NULL, 0,
+                       500);
+       msleep(30);
+       if (ret < 0) {
+               pr_err("reg_w %04x %04x failed %d\n", value, index, ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void reg_wb(struct gspca_dev *gspca_dev, u16 value, u16 index,
+               const u8 *data, int len)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       PDEBUG(D_USBO, "reg_wb v: %04x i: %04x %02x...%02x",
+                       value, index, *data, data[len - 1]);
+       memcpy(gspca_dev->usb_buf, data, len);
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x0c,                   /* request */
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index, gspca_dev->usb_buf, len,
+                       1000);
+       msleep(30);
+       if (ret < 0) {
+               pr_err("reg_wb %04x %04x failed %d\n", value, index, ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void i2c_write(struct sd *sd,
+                       const struct i2c_write_cmd *cmd,
+                       int ncmds)
+{
+       struct gspca_dev *gspca_dev = &sd->gspca_dev;
+       const struct sensor_s *sensor;
+       u16 val, idx;
+       u8 *buf;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+       sensor = &sensor_tb[sd->sensor];
+
+       val = (sensor->i2c_addr << 8) | SQ930_CTRL_I2C_IO;
+       idx = (cmd->val & 0xff00) | cmd->reg;
+
+       buf = gspca_dev->usb_buf;
+       *buf++ = sensor->i2c_dum;
+       *buf++ = cmd->val;
+
+       while (--ncmds > 0) {
+               cmd++;
+               *buf++ = cmd->reg;
+               *buf++ = cmd->val >> 8;
+               *buf++ = sensor->i2c_dum;
+               *buf++ = cmd->val;
+       }
+
+       PDEBUG(D_USBO, "i2c_w v: %04x i: %04x %02x...%02x",
+                       val, idx, gspca_dev->usb_buf[0], buf[-1]);
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x0c,                   /* request */
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       val, idx,
+                       gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
+                       500);
+       if (ret < 0) {
+               pr_err("i2c_write failed %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void ucbus_write(struct gspca_dev *gspca_dev,
+                       const struct ucbus_write_cmd *cmd,
+                       int ncmds,
+                       int batchsize)
+{
+       u8 *buf;
+       u16 val, idx;
+       int len, ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+
+#ifdef GSPCA_DEBUG
+       if ((batchsize - 1) * 3 > USB_BUF_SZ) {
+               pr_err("Bug: usb_buf overflow\n");
+               gspca_dev->usb_err = -ENOMEM;
+               return;
+       }
+#endif
+
+       for (;;) {
+               len = ncmds;
+               if (len > batchsize)
+                       len = batchsize;
+               ncmds -= len;
+
+               val = (cmd->bw_addr << 8) | SQ930_CTRL_UCBUS_IO;
+               idx = (cmd->bw_data << 8) | (cmd->bw_addr >> 8);
+
+               buf = gspca_dev->usb_buf;
+               while (--len > 0) {
+                       cmd++;
+                       *buf++ = cmd->bw_addr;
+                       *buf++ = cmd->bw_addr >> 8;
+                       *buf++ = cmd->bw_data;
+               }
+               if (buf != gspca_dev->usb_buf)
+                       PDEBUG(D_USBO, "ucbus v: %04x i: %04x %02x...%02x",
+                                       val, idx,
+                                       gspca_dev->usb_buf[0], buf[-1]);
+               else
+                       PDEBUG(D_USBO, "ucbus v: %04x i: %04x",
+                                       val, idx);
+               ret = usb_control_msg(gspca_dev->dev,
+                               usb_sndctrlpipe(gspca_dev->dev, 0),
+                               0x0c,                   /* request */
+                          USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               val, idx,
+                               gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
+                               500);
+               if (ret < 0) {
+                       pr_err("ucbus_write failed %d\n", ret);
+                       gspca_dev->usb_err = ret;
+                       return;
+               }
+               msleep(30);
+               if (ncmds <= 0)
+                       break;
+               cmd++;
+       }
+}
+
+static void gpio_set(struct sd *sd, u16 val, u16 mask)
+{
+       struct gspca_dev *gspca_dev = &sd->gspca_dev;
+
+       if (mask & 0x00ff) {
+               sd->gpio[0] &= ~mask;
+               sd->gpio[0] |= val;
+               reg_w(gspca_dev, 0x0100 | SQ930_CTRL_GPIO,
+                       ~sd->gpio[0] << 8);
+       }
+       mask >>= 8;
+       val >>= 8;
+       if (mask) {
+               sd->gpio[1] &= ~mask;
+               sd->gpio[1] |= val;
+               reg_w(gspca_dev, 0x0300 | SQ930_CTRL_GPIO,
+                       ~sd->gpio[1] << 8);
+       }
+}
+
+static void gpio_init(struct sd *sd,
+                       const u8 *gpio)
+{
+       gpio_set(sd, *gpio++, 0x000f);
+       gpio_set(sd, *gpio++, 0x000f);
+       gpio_set(sd, *gpio++, 0x000f);
+       gpio_set(sd, *gpio++, 0x000f);
+       gpio_set(sd, *gpio, 0x000f);
+}
+
+static void bridge_init(struct sd *sd)
+{
+       static const struct ucbus_write_cmd clkfreq_cmd = {
+                               0xf031, 0       /* SQ930_CLKFREQ_60MHZ */
+       };
+
+       ucbus_write(&sd->gspca_dev, &clkfreq_cmd, 1, 1);
+
+       gpio_set(sd, SQ930_GPIO_POWER, 0xff00);
+}
+
+static void cmos_probe(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+       const struct sensor_s *sensor;
+       static const u8 probe_order[] = {
+/*             SENSOR_LZ24BP,          (tested as ccd) */
+               SENSOR_OV9630,
+               SENSOR_MI0360,
+               SENSOR_OV7660,
+               SENSOR_MT9V111,
+       };
+
+       for (i = 0; i < ARRAY_SIZE(probe_order); i++) {
+               sensor = &sensor_tb[probe_order[i]];
+               ucbus_write(&sd->gspca_dev, sensor->cmd, sensor->cmd_len, 8);
+               gpio_init(sd, sensor->gpio);
+               msleep(100);
+               reg_r(gspca_dev, (sensor->i2c_addr << 8) | 0x001c, 1);
+               msleep(100);
+               if (gspca_dev->usb_buf[0] != 0)
+                       break;
+       }
+       if (i >= ARRAY_SIZE(probe_order)) {
+               pr_err("Unknown sensor\n");
+               gspca_dev->usb_err = -EINVAL;
+               return;
+       }
+       sd->sensor = probe_order[i];
+       switch (sd->sensor) {
+       case SENSOR_OV7660:
+       case SENSOR_OV9630:
+               pr_err("Sensor %s not yet treated\n",
+                      sensor_tb[sd->sensor].name);
+               gspca_dev->usb_err = -EINVAL;
+               break;
+       }
+}
+
+static void mt9v111_init(struct gspca_dev *gspca_dev)
+{
+       int i, nwait;
+       static const u8 cmd_001b[] = {
+               0x00, 0x3b, 0xf6, 0x01, 0x03, 0x02, 0x00, 0x00,
+               0x00, 0x00, 0x00
+       };
+       static const u8 cmd_011b[][7] = {
+               {0x10, 0x01, 0x66, 0x08, 0x00, 0x00, 0x00},
+               {0x01, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x00},
+               {0x20, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00},
+               {0x02, 0x01, 0xae, 0x01, 0x00, 0x00, 0x00},
+       };
+
+       reg_wb(gspca_dev, 0x001b, 0x0000, cmd_001b, sizeof cmd_001b);
+       for (i = 0; i < ARRAY_SIZE(cmd_011b); i++) {
+               reg_wb(gspca_dev, 0x001b, 0x0000, cmd_011b[i],
+                               ARRAY_SIZE(cmd_011b[0]));
+               msleep(400);
+               nwait = 20;
+               for (;;) {
+                       reg_r(gspca_dev, 0x031b, 1);
+                       if (gspca_dev->usb_buf[0] == 0
+                        || gspca_dev->usb_err != 0)
+                               break;
+                       if (--nwait < 0) {
+                               PDEBUG(D_PROBE, "mt9v111_init timeout");
+                               gspca_dev->usb_err = -ETIME;
+                               return;
+                       }
+                       msleep(50);
+               }
+       }
+}
+
+static void global_init(struct sd *sd, int first_time)
+{
+       switch (sd->sensor) {
+       case SENSOR_ICX098BQ:
+               if (first_time)
+                       ucbus_write(&sd->gspca_dev,
+                                       icx098bq_start_0,
+                                       8, 8);
+               gpio_init(sd, sensor_tb[sd->sensor].gpio);
+               break;
+       case SENSOR_LZ24BP:
+               if (sd->type != Creative_live_motion)
+                       gpio_set(sd, SQ930_GPIO_EXTRA1, 0x00ff);
+               else
+                       gpio_set(sd, 0, 0x00ff);
+               msleep(50);
+               if (first_time)
+                       ucbus_write(&sd->gspca_dev,
+                                       lz24bp_start_0,
+                                       8, 8);
+               gpio_init(sd, sensor_tb[sd->sensor].gpio);
+               break;
+       case SENSOR_MI0360:
+               if (first_time)
+                       ucbus_write(&sd->gspca_dev,
+                                       mi0360_start_0,
+                                       ARRAY_SIZE(mi0360_start_0),
+                                       8);
+               gpio_init(sd, sensor_tb[sd->sensor].gpio);
+               gpio_set(sd, SQ930_GPIO_EXTRA2, SQ930_GPIO_EXTRA2);
+               break;
+       default:
+/*     case SENSOR_MT9V111: */
+               if (first_time)
+                       mt9v111_init(&sd->gspca_dev);
+               else
+                       gpio_init(sd, sensor_tb[sd->sensor].gpio);
+               break;
+       }
+}
+
+static void lz24bp_ppl(struct sd *sd, u16 ppl)
+{
+       struct ucbus_write_cmd cmds[2] = {
+               {0xf810, ppl >> 8},
+               {0xf811, ppl}
+       };
+
+       ucbus_write(&sd->gspca_dev, cmds, ARRAY_SIZE(cmds), 2);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 gain)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i, integclks, intstartclk, frameclks, min_frclk;
+       const struct sensor_s *sensor;
+       u16 cmd;
+       u8 buf[15];
+
+       integclks = expo;
+       i = 0;
+       cmd = SQ930_CTRL_SET_EXPOSURE;
+
+       switch (sd->sensor) {
+       case SENSOR_ICX098BQ:                   /* ccd */
+       case SENSOR_LZ24BP:
+               min_frclk = sd->sensor == SENSOR_ICX098BQ ? 0x210 : 0x26f;
+               if (integclks >= min_frclk) {
+                       intstartclk = 0;
+                       frameclks = integclks;
+               } else {
+                       intstartclk = min_frclk - integclks;
+                       frameclks = min_frclk;
+               }
+               buf[i++] = intstartclk >> 8;
+               buf[i++] = intstartclk;
+               buf[i++] = frameclks >> 8;
+               buf[i++] = frameclks;
+               buf[i++] = gain;
+               break;
+       default:                                /* cmos */
+/*     case SENSOR_MI0360: */
+/*     case SENSOR_MT9V111: */
+               cmd |= 0x0100;
+               sensor = &sensor_tb[sd->sensor];
+               buf[i++] = sensor->i2c_addr;    /* i2c_slave_addr */
+               buf[i++] = 0x08;        /* 2 * ni2c */
+               buf[i++] = 0x09;        /* reg = shutter width */
+               buf[i++] = integclks >> 8; /* val H */
+               buf[i++] = sensor->i2c_dum;
+               buf[i++] = integclks;   /* val L */
+               buf[i++] = 0x35;        /* reg = global gain */
+               buf[i++] = 0x00;        /* val H */
+               buf[i++] = sensor->i2c_dum;
+               buf[i++] = 0x80 + gain / 2; /* val L */
+               buf[i++] = 0x00;
+               buf[i++] = 0x00;
+               buf[i++] = 0x00;
+               buf[i++] = 0x00;
+               buf[i++] = 0x83;
+               break;
+       }
+       reg_wb(gspca_dev, cmd, 0, buf, i);
+}
+
+/* This function is called at probe time just before sd_init */
+static int sd_config(struct gspca_dev *gspca_dev,
+               const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam = &gspca_dev->cam;
+
+       sd->sensor = id->driver_info >> 8;
+       sd->type = id->driver_info;
+
+       cam->cam_mode = vga_mode;
+       cam->nmodes = ARRAY_SIZE(vga_mode);
+
+       cam->bulk = 1;
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->gpio[0] = sd->gpio[1] = 0xff;       /* force gpio rewrite */
+
+/*fixme: is this needed for icx098bp and mi0360?
+       if (sd->sensor != SENSOR_LZ24BP)
+               reg_w(gspca_dev, SQ930_CTRL_RESET, 0x0000);
+ */
+
+       reg_r(gspca_dev, SQ930_CTRL_GET_DEV_INFO, 8);
+       if (gspca_dev->usb_err < 0)
+               return gspca_dev->usb_err;
+
+/* it returns:
+ * 03 00 12 93 0b f6 c9 00     live! ultra
+ * 03 00 07 93 0b f6 ca 00     live! ultra for notebook
+ * 03 00 12 93 0b fe c8 00     Trust WB-3500T
+ * 02 00 06 93 0b fe c8 00     Joy-IT 318S
+ * 03 00 12 93 0b f6 cf 00     icam tracer - sensor icx098bq
+ * 02 00 12 93 0b fe cf 00     ProQ Motion Webcam
+ *
+ * byte
+ * 0: 02 = usb 1.0 (12Mbit) / 03 = usb2.0 (480Mbit)
+ * 1: 00
+ * 2: 06 / 07 / 12 = mode webcam? firmware??
+ * 3: 93 chip = 930b (930b or 930c)
+ * 4: 0b
+ * 5: f6 = cdd (icx098bq, lz24bp) / fe or de = cmos (i2c) (other sensors)
+ * 6: c8 / c9 / ca / cf = mode webcam?, sensor? webcam?
+ * 7: 00
+ */
+       PDEBUG(D_PROBE, "info: %*ph", 8, gspca_dev->usb_buf);
+
+       bridge_init(sd);
+
+       if (sd->sensor == SENSOR_MI0360) {
+
+               /* no sensor probe for icam tracer */
+               if (gspca_dev->usb_buf[5] == 0xf6)      /* if ccd */
+                       sd->sensor = SENSOR_ICX098BQ;
+               else
+                       cmos_probe(gspca_dev);
+       }
+       if (gspca_dev->usb_err >= 0) {
+               PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name);
+               global_init(sd, 1);
+       }
+       return gspca_dev->usb_err;
+}
+
+/* send the start/stop commands to the webcam */
+static void send_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       const struct cap_s *cap;
+       int mode;
+
+       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+       cap = &capconfig[sd->sensor][mode];
+       reg_wb(gspca_dev, 0x0900 | SQ930_CTRL_CAP_START,
+                       0x0a00 | cap->cc_sizeid,
+                       cap->cc_bytes, 32);
+}
+
+static void send_stop(struct gspca_dev *gspca_dev)
+{
+       reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0);
+}
+
+/* function called at start time before URB creation */
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       gspca_dev->cam.bulk_nurbs = 1;  /* there must be one URB only */
+       sd->do_ctrl = 0;
+       gspca_dev->cam.bulk_size = gspca_dev->width * gspca_dev->height + 8;
+       return 0;
+}
+
+/* start the capture */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int mode;
+
+       bridge_init(sd);
+       global_init(sd, 0);
+       msleep(100);
+
+       switch (sd->sensor) {
+       case SENSOR_ICX098BQ:
+               ucbus_write(gspca_dev, icx098bq_start_0,
+                               ARRAY_SIZE(icx098bq_start_0),
+                               8);
+               ucbus_write(gspca_dev, icx098bq_start_1,
+                               ARRAY_SIZE(icx098bq_start_1),
+                               5);
+               ucbus_write(gspca_dev, icx098bq_start_2,
+                               ARRAY_SIZE(icx098bq_start_2),
+                               6);
+               msleep(50);
+
+               /* 1st start */
+               send_start(gspca_dev);
+               gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, 0x00ff);
+               msleep(70);
+               reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0x0000);
+               gpio_set(sd, 0x7f, 0x00ff);
+
+               /* 2nd start */
+               send_start(gspca_dev);
+               gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, 0x00ff);
+               goto out;
+       case SENSOR_LZ24BP:
+               ucbus_write(gspca_dev, lz24bp_start_0,
+                               ARRAY_SIZE(lz24bp_start_0),
+                               8);
+               if (sd->type != Creative_live_motion)
+                       ucbus_write(gspca_dev, lz24bp_start_1_gen,
+                                       ARRAY_SIZE(lz24bp_start_1_gen),
+                                       5);
+               else
+                       ucbus_write(gspca_dev, lz24bp_start_1_clm,
+                                       ARRAY_SIZE(lz24bp_start_1_clm),
+                                       5);
+               ucbus_write(gspca_dev, lz24bp_start_2,
+                               ARRAY_SIZE(lz24bp_start_2),
+                               6);
+               mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+               lz24bp_ppl(sd, mode == 1 ? 0x0564 : 0x0310);
+               msleep(10);
+               break;
+       case SENSOR_MI0360:
+               ucbus_write(gspca_dev, mi0360_start_0,
+                               ARRAY_SIZE(mi0360_start_0),
+                               8);
+               i2c_write(sd, mi0360_init_23,
+                               ARRAY_SIZE(mi0360_init_23));
+               i2c_write(sd, mi0360_init_24,
+                               ARRAY_SIZE(mi0360_init_24));
+               i2c_write(sd, mi0360_init_25,
+                               ARRAY_SIZE(mi0360_init_25));
+               ucbus_write(gspca_dev, mi0360_start_1,
+                               ARRAY_SIZE(mi0360_start_1),
+                               5);
+               i2c_write(sd, mi0360_start_2,
+                               ARRAY_SIZE(mi0360_start_2));
+               i2c_write(sd, mi0360_start_3,
+                               ARRAY_SIZE(mi0360_start_3));
+
+               /* 1st start */
+               send_start(gspca_dev);
+               msleep(60);
+               send_stop(gspca_dev);
+
+               i2c_write(sd,
+                       mi0360_start_4, ARRAY_SIZE(mi0360_start_4));
+               break;
+       default:
+/*     case SENSOR_MT9V111: */
+               ucbus_write(gspca_dev, mi0360_start_0,
+                               ARRAY_SIZE(mi0360_start_0),
+                               8);
+               i2c_write(sd, mt9v111_init_0,
+                               ARRAY_SIZE(mt9v111_init_0));
+               i2c_write(sd, mt9v111_init_1,
+                               ARRAY_SIZE(mt9v111_init_1));
+               i2c_write(sd, mt9v111_init_2,
+                               ARRAY_SIZE(mt9v111_init_2));
+               ucbus_write(gspca_dev, mt9v111_start_1,
+                               ARRAY_SIZE(mt9v111_start_1),
+                               5);
+               i2c_write(sd, mt9v111_init_3,
+                               ARRAY_SIZE(mt9v111_init_3));
+               i2c_write(sd, mt9v111_init_4,
+                               ARRAY_SIZE(mt9v111_init_4));
+               break;
+       }
+
+       send_start(gspca_dev);
+out:
+       msleep(1000);
+
+       if (sd->sensor == SENSOR_MT9V111)
+               gpio_set(sd, SQ930_GPIO_DFL_LED, SQ930_GPIO_DFL_LED);
+
+       sd->do_ctrl = 1;        /* set the exposure */
+
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_MT9V111)
+               gpio_set(sd, 0, SQ930_GPIO_DFL_LED);
+       send_stop(gspca_dev);
+}
+
+/* function called when the application gets a new frame */
+/* It sets the exposure if required and restart the bulk transfer. */
+static void sd_dq_callback(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int ret;
+
+       if (!sd->do_ctrl || gspca_dev->cam.bulk_nurbs != 0)
+               return;
+       sd->do_ctrl = 0;
+
+       setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure),
+                       v4l2_ctrl_g_ctrl(sd->gain));
+
+       gspca_dev->cam.bulk_nurbs = 1;
+       ret = usb_submit_urb(gspca_dev->urb[0], GFP_ATOMIC);
+       if (ret < 0)
+               pr_err("sd_dq_callback() err %d\n", ret);
+
+       /* wait a little time, otherwise the webcam crashes */
+       msleep(100);
+}
+
+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 (sd->do_ctrl)
+               gspca_dev->cam.bulk_nurbs = 0;
+       gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len - 8);
+       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 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, sd->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 2);
+       sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 1, 0xfff, 1, 0x356);
+       sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAIN, 1, 255, 1, 0x8d);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       v4l2_ctrl_cluster(2, &sd->exposure);
+       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,
+       .isoc_init = sd_isoc_init,
+       .start  = sd_start,
+       .stopN  = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+       .dq_callback = sd_dq_callback,
+};
+
+/* Table of supported USB devices */
+#define ST(sensor, type) \
+       .driver_info = (SENSOR_ ## sensor << 8) \
+                       | (type)
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x041e, 0x4038), ST(MI0360, 0)},
+       {USB_DEVICE(0x041e, 0x403c), ST(LZ24BP, 0)},
+       {USB_DEVICE(0x041e, 0x403d), ST(LZ24BP, 0)},
+       {USB_DEVICE(0x041e, 0x4041), ST(LZ24BP, Creative_live_motion)},
+       {USB_DEVICE(0x2770, 0x930b), ST(MI0360, 0)},
+       {USB_DEVICE(0x2770, 0x930c), ST(MI0360, 0)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/stk014.c b/drivers/media/usb/gspca/stk014.c
new file mode 100644 (file)
index 0000000..8c09826
--- /dev/null
@@ -0,0 +1,446 @@
+/*
+ * Syntek DV4000 (STK014) subdriver
+ *
+ * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr)
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "stk014"
+
+#include "gspca.h"
+#include "jpeg.h"
+
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
+MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+#define QUALITY 50
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+       u8 jpeg_hdr[JPEG_HDR_SZ];
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+
+/* -- read a register -- */
+static u8 reg_r(struct gspca_dev *gspca_dev,
+                       __u16 index)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return 0;
+       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                       0x00,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0x00,
+                       index,
+                       gspca_dev->usb_buf, 1,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_r err %d\n", ret);
+               gspca_dev->usb_err = ret;
+               return 0;
+       }
+       return gspca_dev->usb_buf[0];
+}
+
+/* -- write a register -- */
+static void reg_w(struct gspca_dev *gspca_dev,
+                       __u16 index, __u16 value)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                       0x01,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value,
+                       index,
+                       NULL,
+                       0,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_w err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+/* -- get a bulk value (4 bytes) -- */
+static void rcv_val(struct gspca_dev *gspca_dev,
+                       int ads)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int alen, ret;
+
+       reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff);
+       reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff);
+       reg_w(gspca_dev, 0x636, ads & 0xff);
+       reg_w(gspca_dev, 0x637, 0);
+       reg_w(gspca_dev, 0x638, 4);     /* len & 0xff */
+       reg_w(gspca_dev, 0x639, 0);     /* len >> 8 */
+       reg_w(gspca_dev, 0x63a, 0);
+       reg_w(gspca_dev, 0x63b, 0);
+       reg_w(gspca_dev, 0x630, 5);
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_bulk_msg(dev,
+                       usb_rcvbulkpipe(dev, 0x05),
+                       gspca_dev->usb_buf,
+                       4,              /* length */
+                       &alen,
+                       500);           /* timeout in milliseconds */
+       if (ret < 0) {
+               pr_err("rcv_val err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+/* -- send a bulk value -- */
+static void snd_val(struct gspca_dev *gspca_dev,
+                       int ads,
+                       unsigned int val)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int alen, ret;
+       __u8 seq = 0;
+
+       if (ads == 0x003f08) {
+               reg_r(gspca_dev, 0x0704);
+               seq = reg_r(gspca_dev, 0x0705);
+               reg_r(gspca_dev, 0x0650);
+               reg_w(gspca_dev, 0x654, seq);
+       } else {
+               reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
+       }
+       reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff);
+       reg_w(gspca_dev, 0x656, ads & 0xff);
+       reg_w(gspca_dev, 0x657, 0);
+       reg_w(gspca_dev, 0x658, 0x04);  /* size */
+       reg_w(gspca_dev, 0x659, 0);
+       reg_w(gspca_dev, 0x65a, 0);
+       reg_w(gspca_dev, 0x65b, 0);
+       reg_w(gspca_dev, 0x650, 5);
+       if (gspca_dev->usb_err < 0)
+               return;
+       gspca_dev->usb_buf[0] = val >> 24;
+       gspca_dev->usb_buf[1] = val >> 16;
+       gspca_dev->usb_buf[2] = val >> 8;
+       gspca_dev->usb_buf[3] = val;
+       ret = usb_bulk_msg(dev,
+                       usb_sndbulkpipe(dev, 6),
+                       gspca_dev->usb_buf,
+                       4,
+                       &alen,
+                       500);   /* timeout in milliseconds */
+       if (ret < 0) {
+               pr_err("snd_val err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       } else {
+               if (ads == 0x003f08) {
+                       seq += 4;
+                       seq &= 0x3f;
+                       reg_w(gspca_dev, 0x705, seq);
+               }
+       }
+}
+
+/* set a camera parameter */
+static void set_par(struct gspca_dev *gspca_dev,
+                  int parval)
+{
+       snd_val(gspca_dev, 0x003f08, parval);
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       int parval;
+
+       parval = 0x06000000             /* whiteness */
+               + (val << 16);
+       set_par(gspca_dev, parval);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
+{
+       int parval;
+
+       parval = 0x07000000             /* contrast */
+               + (val << 16);
+       set_par(gspca_dev, parval);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev, s32 val)
+{
+       int parval;
+
+       parval = 0x08000000             /* saturation */
+               + (val << 16);
+       set_par(gspca_dev, parval);
+}
+
+static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
+{
+       set_par(gspca_dev, val == 1
+                       ? 0x33640000            /* 50 Hz */
+                       : 0x33780000);          /* 60 Hz */
+}
+
+/* this function is called at probe time */
+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);
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       u8 ret;
+
+       /* check if the device responds */
+       usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
+       ret = reg_r(gspca_dev, 0x0740);
+       if (gspca_dev->usb_err >= 0) {
+               if (ret != 0xff) {
+                       pr_err("init reg: 0x%02x\n", ret);
+                       gspca_dev->usb_err = -EIO;
+               }
+       }
+       return gspca_dev->usb_err;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int ret, value;
+
+       /* create the JPEG header */
+       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+                       0x22);          /* JPEG 411 */
+       jpeg_set_qual(sd->jpeg_hdr, QUALITY);
+
+       /* work on alternate 1 */
+       usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
+
+       set_par(gspca_dev, 0x10000000);
+       set_par(gspca_dev, 0x00000000);
+       set_par(gspca_dev, 0x8002e001);
+       set_par(gspca_dev, 0x14000000);
+       if (gspca_dev->width > 320)
+               value = 0x8002e001;             /* 640x480 */
+       else
+               value = 0x4001f000;             /* 320x240 */
+       set_par(gspca_dev, value);
+       ret = usb_set_interface(gspca_dev->dev,
+                                       gspca_dev->iface,
+                                       gspca_dev->alt);
+       if (ret < 0) {
+               pr_err("set intf %d %d failed\n",
+                      gspca_dev->iface, gspca_dev->alt);
+               gspca_dev->usb_err = ret;
+               goto out;
+       }
+        reg_r(gspca_dev, 0x0630);
+       rcv_val(gspca_dev, 0x000020);   /* << (value ff ff ff ff) */
+       reg_r(gspca_dev, 0x0650);
+       snd_val(gspca_dev, 0x000020, 0xffffffff);
+       reg_w(gspca_dev, 0x0620, 0);
+       reg_w(gspca_dev, 0x0630, 0);
+       reg_w(gspca_dev, 0x0640, 0);
+       reg_w(gspca_dev, 0x0650, 0);
+       reg_w(gspca_dev, 0x0660, 0);
+       set_par(gspca_dev, 0x09800000);         /* Red ? */
+       set_par(gspca_dev, 0x0a800000);         /* Green ? */
+       set_par(gspca_dev, 0x0b800000);         /* Blue ? */
+       set_par(gspca_dev, 0x0d030000);         /* Gamma ? */
+
+       /* start the video flow */
+       set_par(gspca_dev, 0x01000000);
+       set_par(gspca_dev, 0x01000000);
+       if (gspca_dev->usb_err >= 0)
+               PDEBUG(D_STREAM, "camera started alt: 0x%02x",
+                               gspca_dev->alt);
+out:
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct usb_device *dev = gspca_dev->dev;
+
+       set_par(gspca_dev, 0x02000000);
+       set_par(gspca_dev, 0x02000000);
+       usb_set_interface(dev, gspca_dev->iface, 1);
+       reg_r(gspca_dev, 0x0630);
+       rcv_val(gspca_dev, 0x000020);   /* << (value ff ff ff ff) */
+       reg_r(gspca_dev, 0x0650);
+       snd_val(gspca_dev, 0x000020, 0xffffffff);
+       reg_w(gspca_dev, 0x0620, 0);
+       reg_w(gspca_dev, 0x0630, 0);
+       reg_w(gspca_dev, 0x0640, 0);
+       reg_w(gspca_dev, 0x0650, 0);
+       reg_w(gspca_dev, 0x0660, 0);
+       PDEBUG(D_STREAM, "camera stopped");
+}
+
+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;
+       static unsigned char ffd9[] = {0xff, 0xd9};
+
+       /* a frame starts with:
+        *      - 0xff 0xfe
+        *      - 0x08 0x00     - length (little endian ?!)
+        *      - 4 bytes = size of whole frame (BE - including header)
+        *      - 0x00 0x0c
+        *      - 0xff 0xd8
+        *      - ..    JPEG image with escape sequences (ff 00)
+        *              (without ending - ff d9)
+        */
+       if (data[0] == 0xff && data[1] == 0xfe) {
+               gspca_frame_add(gspca_dev, LAST_PACKET,
+                               ffd9, 2);
+
+               /* put the JPEG 411 header */
+               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                       sd->jpeg_hdr, JPEG_HDR_SZ);
+
+               /* beginning of the frame */
+#define STKHDRSZ 12
+               data += STKHDRSZ;
+               len -= STKHDRSZ;
+       }
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct gspca_dev *gspca_dev =
+               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+
+       gspca_dev->usb_err = 0;
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               setcolors(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_POWER_LINE_FREQUENCY:
+               setlightfreq(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 4);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 255, 1, 127);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 255, 1, 127);
+       v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
+                       V4L2_CID_POWER_LINE_FREQUENCY,
+                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
+                       V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
+
+       if (hdl->error) {
+               pr_err("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,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x05e1, 0x0893)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/stv0680.c b/drivers/media/usb/gspca/stv0680.c
new file mode 100644 (file)
index 0000000..6760527
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * STV0680 USB Camera Driver
+ *
+ * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This module is adapted from the in kernel v4l1 stv680 driver:
+ *
+ *  STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net)
+ *
+ * Thanks to STMicroelectronics for information on the usb commands, and
+ * to Steve Miller at STM for his help and encouragement while I was
+ * writing this driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "stv0680"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("STV0680 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;             /* !! must be the first item */
+       struct v4l2_pix_format mode;
+       u8 orig_mode;
+       u8 video_mode;
+       u8 current_mode;
+};
+
+static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val,
+                      int size)
+{
+       int ret = -1;
+       u8 req_type = 0;
+       unsigned int pipe = 0;
+
+       switch (set) {
+       case 0: /*  0xc1  */
+               req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
+               pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
+               break;
+       case 1: /*  0x41  */
+               req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
+               pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
+               break;
+       case 2: /*  0x80  */
+               req_type = USB_DIR_IN | USB_RECIP_DEVICE;
+               pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
+               break;
+       case 3: /*  0x40  */
+               req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+               pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
+               break;
+       }
+
+       ret = usb_control_msg(gspca_dev->dev, pipe,
+                             req, req_type,
+                             val, 0, gspca_dev->usb_buf, size, 500);
+
+       if ((ret < 0) && (req != 0x0a))
+               pr_err("usb_control_msg error %i, request = 0x%x, error = %i\n",
+                      set, req, ret);
+
+       return ret;
+}
+
+static int stv0680_handle_error(struct gspca_dev *gspca_dev, int ret)
+{
+       stv_sndctrl(gspca_dev, 0, 0x80, 0, 0x02); /* Get Last Error */
+       PDEBUG(D_ERR, "last error: %i,  command = 0x%x",
+              gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
+       return ret;
+}
+
+static int stv0680_get_video_mode(struct gspca_dev *gspca_dev)
+{
+       /* Note not sure if this init of usb_buf is really necessary */
+       memset(gspca_dev->usb_buf, 0, 8);
+       gspca_dev->usb_buf[0] = 0x0f;
+
+       if (stv_sndctrl(gspca_dev, 0, 0x87, 0, 0x08) != 0x08) {
+               PDEBUG(D_ERR, "Get_Camera_Mode failed");
+               return stv0680_handle_error(gspca_dev, -EIO);
+       }
+
+       return gspca_dev->usb_buf[0]; /* 01 = VGA, 03 = QVGA, 00 = CIF */
+}
+
+static int stv0680_set_video_mode(struct gspca_dev *gspca_dev, u8 mode)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->current_mode == mode)
+               return 0;
+
+       memset(gspca_dev->usb_buf, 0, 8);
+       gspca_dev->usb_buf[0] = mode;
+
+       if (stv_sndctrl(gspca_dev, 3, 0x07, 0x0100, 0x08) != 0x08) {
+               PDEBUG(D_ERR, "Set_Camera_Mode failed");
+               return stv0680_handle_error(gspca_dev, -EIO);
+       }
+
+       /* Verify we got what we've asked for */
+       if (stv0680_get_video_mode(gspca_dev) != mode) {
+               PDEBUG(D_ERR, "Error setting camera video mode!");
+               return -EIO;
+       }
+
+       sd->current_mode = mode;
+
+       return 0;
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       int ret;
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam = &gspca_dev->cam;
+
+       /* Give the camera some time to settle, otherwise initalization will
+          fail on hotplug, and yes it really needs a full second. */
+       msleep(1000);
+
+       /* ping camera to be sure STV0680 is present */
+       if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 ||
+           gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) {
+               PDEBUG(D_ERR, "STV(e): camera ping failed!!");
+               return stv0680_handle_error(gspca_dev, -ENODEV);
+       }
+
+       /* get camera descriptor */
+       if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x09) != 0x09)
+               return stv0680_handle_error(gspca_dev, -ENODEV);
+
+       if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x22) != 0x22 ||
+           gspca_dev->usb_buf[7] != 0xa0 || gspca_dev->usb_buf[8] != 0x23) {
+               PDEBUG(D_ERR, "Could not get descriptor 0200.");
+               return stv0680_handle_error(gspca_dev, -ENODEV);
+       }
+       if (stv_sndctrl(gspca_dev, 0, 0x8a, 0, 0x02) != 0x02)
+               return stv0680_handle_error(gspca_dev, -ENODEV);
+       if (stv_sndctrl(gspca_dev, 0, 0x8b, 0, 0x24) != 0x24)
+               return stv0680_handle_error(gspca_dev, -ENODEV);
+       if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10)
+               return stv0680_handle_error(gspca_dev, -ENODEV);
+
+       if (!(gspca_dev->usb_buf[7] & 0x09)) {
+               PDEBUG(D_ERR, "Camera supports neither CIF nor QVGA mode");
+               return -ENODEV;
+       }
+       if (gspca_dev->usb_buf[7] & 0x01)
+               PDEBUG(D_PROBE, "Camera supports CIF mode");
+       if (gspca_dev->usb_buf[7] & 0x02)
+               PDEBUG(D_PROBE, "Camera supports VGA mode");
+       if (gspca_dev->usb_buf[7] & 0x04)
+               PDEBUG(D_PROBE, "Camera supports QCIF mode");
+       if (gspca_dev->usb_buf[7] & 0x08)
+               PDEBUG(D_PROBE, "Camera supports QVGA mode");
+
+       if (gspca_dev->usb_buf[7] & 0x01)
+               sd->video_mode = 0x00; /* CIF */
+       else
+               sd->video_mode = 0x03; /* QVGA */
+
+       /* FW rev, ASIC rev, sensor ID  */
+       PDEBUG(D_PROBE, "Firmware rev is %i.%i",
+              gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
+       PDEBUG(D_PROBE, "ASIC rev is %i.%i",
+              gspca_dev->usb_buf[2], gspca_dev->usb_buf[3]);
+       PDEBUG(D_PROBE, "Sensor ID is %i",
+              (gspca_dev->usb_buf[4]*16) + (gspca_dev->usb_buf[5]>>4));
+
+
+       ret = stv0680_get_video_mode(gspca_dev);
+       if (ret < 0)
+               return ret;
+       sd->current_mode = sd->orig_mode = ret;
+
+       ret = stv0680_set_video_mode(gspca_dev, sd->video_mode);
+       if (ret < 0)
+               return ret;
+
+       /* Get mode details */
+       if (stv_sndctrl(gspca_dev, 0, 0x8f, 0, 0x10) != 0x10)
+               return stv0680_handle_error(gspca_dev, -EIO);
+
+       cam->bulk = 1;
+       cam->bulk_nurbs = 1; /* The cam cannot handle more */
+       cam->bulk_size = (gspca_dev->usb_buf[0] << 24) |
+                        (gspca_dev->usb_buf[1] << 16) |
+                        (gspca_dev->usb_buf[2] << 8) |
+                        (gspca_dev->usb_buf[3]);
+       sd->mode.width = (gspca_dev->usb_buf[4] << 8) |
+                        (gspca_dev->usb_buf[5]);  /* 322, 356, 644 */
+       sd->mode.height = (gspca_dev->usb_buf[6] << 8) |
+                         (gspca_dev->usb_buf[7]); /* 242, 292, 484 */
+       sd->mode.pixelformat = V4L2_PIX_FMT_STV0680;
+       sd->mode.field = V4L2_FIELD_NONE;
+       sd->mode.bytesperline = sd->mode.width;
+       sd->mode.sizeimage = cam->bulk_size;
+       sd->mode.colorspace = V4L2_COLORSPACE_SRGB;
+
+       /* origGain = gspca_dev->usb_buf[12]; */
+
+       cam->cam_mode = &sd->mode;
+       cam->nmodes = 1;
+
+
+       ret = stv0680_set_video_mode(gspca_dev, sd->orig_mode);
+       if (ret < 0)
+               return ret;
+
+       if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0100, 0x12) != 0x12 ||
+           gspca_dev->usb_buf[8] != 0x53 || gspca_dev->usb_buf[9] != 0x05) {
+               pr_err("Could not get descriptor 0100\n");
+               return stv0680_handle_error(gspca_dev, -EIO);
+       }
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       return 0;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       int ret;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       ret = stv0680_set_video_mode(gspca_dev, sd->video_mode);
+       if (ret < 0)
+               return ret;
+
+       if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10)
+               return stv0680_handle_error(gspca_dev, -EIO);
+
+       /* Start stream at:
+          0x0000 = CIF (352x288)
+          0x0100 = VGA (640x480)
+          0x0300 = QVGA (320x240) */
+       if (stv_sndctrl(gspca_dev, 1, 0x09, sd->video_mode << 8, 0x0) != 0x0)
+               return stv0680_handle_error(gspca_dev, -EIO);
+
+       return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       /* This is a high priority command; it stops all lower order cmds */
+       if (stv_sndctrl(gspca_dev, 1, 0x04, 0x0000, 0x0) != 0x0)
+               stv0680_handle_error(gspca_dev, -EIO);
+}
+
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (!sd->gspca_dev.present)
+               return;
+
+       stv0680_set_video_mode(gspca_dev, sd->orig_mode);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,
+                       int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* Every now and then the camera sends a 16 byte packet, no idea
+          what it contains, but it is not image data, when this
+          happens the frame received before this packet is corrupt,
+          so discard it. */
+       if (len != sd->mode.sizeimage) {
+               gspca_dev->last_packet_type = DISCARD_PACKET;
+               return;
+       }
+
+       /* Finish the previous frame, we do this upon reception of the next
+          packet, even though it is already complete so that the strange 16
+          byte packets send after a corrupt frame can discard it. */
+       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+
+       /* Store the just received frame */
+       gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
+}
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name = MODULE_NAME,
+       .config = sd_config,
+       .init = sd_init,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .stop0 = sd_stop0,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x0553, 0x0202)},
+       {USB_DEVICE(0x041e, 0x4007)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/stv06xx/Kconfig b/drivers/media/usb/gspca/stv06xx/Kconfig
new file mode 100644 (file)
index 0000000..634ad38
--- /dev/null
@@ -0,0 +1,9 @@
+config USB_STV06XX
+       tristate "STV06XX USB Camera Driver"
+       depends on USB_GSPCA
+       help
+         Say Y here if you want support for cameras based on
+         the ST STV06XX chip.
+
+         To compile this driver as a module, choose M here: the
+         module will be called gspca_stv06xx.
diff --git a/drivers/media/usb/gspca/stv06xx/Makefile b/drivers/media/usb/gspca/stv06xx/Makefile
new file mode 100644 (file)
index 0000000..3a4b2f8
--- /dev/null
@@ -0,0 +1,10 @@
+obj-$(CONFIG_USB_STV06XX) += gspca_stv06xx.o
+
+gspca_stv06xx-objs := stv06xx.o \
+                     stv06xx_vv6410.o \
+                     stv06xx_hdcs.o \
+                     stv06xx_pb0100.o \
+                     stv06xx_st6422.o
+
+ccflags-y += -I$(srctree)/drivers/media/usb/gspca
+
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx.c b/drivers/media/usb/gspca/stv06xx/stv06xx.c
new file mode 100644 (file)
index 0000000..999ec77
--- /dev/null
@@ -0,0 +1,634 @@
+/*
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ * Copyright (c) 2008 Erik Andrén
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * P/N 861037:      Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
+ * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
+ * P/N 861075-0040: Sensor HDCS1000        ASIC
+ * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
+ * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/input.h>
+#include "stv06xx_sensor.h"
+
+MODULE_AUTHOR("Erik Andrén");
+MODULE_DESCRIPTION("STV06XX USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+static bool dump_bridge;
+static bool dump_sensor;
+
+int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data)
+{
+       int err;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+       u8 len = (i2c_data > 0xff) ? 2 : 1;
+
+       buf[0] = i2c_data & 0xff;
+       buf[1] = (i2c_data >> 8) & 0xff;
+
+       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                             0x04, 0x40, address, 0, buf, len,
+                             STV06XX_URB_MSG_TIMEOUT);
+
+       PDEBUG(D_CONF, "Written 0x%x to address 0x%x, status: %d",
+              i2c_data, address, err);
+
+       return (err < 0) ? err : 0;
+}
+
+int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data)
+{
+       int err;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                             0x04, 0xc0, address, 0, buf, 1,
+                             STV06XX_URB_MSG_TIMEOUT);
+
+       *i2c_data = buf[0];
+
+       PDEBUG(D_CONF, "Reading 0x%x from address 0x%x, status %d",
+              *i2c_data, address, err);
+
+       return (err < 0) ? err : 0;
+}
+
+/* Wraps the normal write sensor bytes / words functions for writing a
+   single value */
+int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value)
+{
+       if (sd->sensor->i2c_len == 2) {
+               u16 data[2] = { address, value };
+               return stv06xx_write_sensor_words(sd, data, 1);
+       } else {
+               u8 data[2] = { address, value };
+               return stv06xx_write_sensor_bytes(sd, data, 1);
+       }
+}
+
+static int stv06xx_write_sensor_finish(struct sd *sd)
+{
+       int err = 0;
+
+       if (sd->bridge == BRIDGE_STV610) {
+               struct usb_device *udev = sd->gspca_dev.dev;
+               __u8 *buf = sd->gspca_dev.usb_buf;
+
+               buf[0] = 0;
+               err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                                     0x04, 0x40, 0x1704, 0, buf, 1,
+                                     STV06XX_URB_MSG_TIMEOUT);
+       }
+
+       return (err < 0) ? err : 0;
+}
+
+int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len)
+{
+       int err, i, j;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       PDEBUG(D_CONF, "I2C: Command buffer contains %d entries", len);
+       for (i = 0; i < len;) {
+               /* Build the command buffer */
+               memset(buf, 0, I2C_BUFFER_LENGTH);
+               for (j = 0; j < I2C_MAX_BYTES && i < len; j++, i++) {
+                       buf[j] = data[2*i];
+                       buf[0x10 + j] = data[2*i+1];
+                       PDEBUG(D_CONF, "I2C: Writing 0x%02x to reg 0x%02x",
+                       data[2*i+1], data[2*i]);
+               }
+               buf[0x20] = sd->sensor->i2c_addr;
+               buf[0x21] = j - 1; /* Number of commands to send - 1 */
+               buf[0x22] = I2C_WRITE_CMD;
+               err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                                     0x04, 0x40, 0x0400, 0, buf,
+                                     I2C_BUFFER_LENGTH,
+                                     STV06XX_URB_MSG_TIMEOUT);
+               if (err < 0)
+                       return err;
+       }
+       return stv06xx_write_sensor_finish(sd);
+}
+
+int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len)
+{
+       int err, i, j;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       PDEBUG(D_CONF, "I2C: Command buffer contains %d entries", len);
+
+       for (i = 0; i < len;) {
+               /* Build the command buffer */
+               memset(buf, 0, I2C_BUFFER_LENGTH);
+               for (j = 0; j < I2C_MAX_WORDS && i < len; j++, i++) {
+                       buf[j] = data[2*i];
+                       buf[0x10 + j * 2] = data[2*i+1];
+                       buf[0x10 + j * 2 + 1] = data[2*i+1] >> 8;
+                       PDEBUG(D_CONF, "I2C: Writing 0x%04x to reg 0x%02x",
+                               data[2*i+1], data[2*i]);
+               }
+               buf[0x20] = sd->sensor->i2c_addr;
+               buf[0x21] = j - 1; /* Number of commands to send - 1 */
+               buf[0x22] = I2C_WRITE_CMD;
+               err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                               0x04, 0x40, 0x0400, 0, buf,
+                               I2C_BUFFER_LENGTH,
+                               STV06XX_URB_MSG_TIMEOUT);
+               if (err < 0)
+                       return err;
+       }
+       return stv06xx_write_sensor_finish(sd);
+}
+
+int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value)
+{
+       int err;
+       struct usb_device *udev = sd->gspca_dev.dev;
+       __u8 *buf = sd->gspca_dev.usb_buf;
+
+       err = stv06xx_write_bridge(sd, STV_I2C_FLUSH, sd->sensor->i2c_flush);
+       if (err < 0)
+               return err;
+
+       /* Clear mem */
+       memset(buf, 0, I2C_BUFFER_LENGTH);
+
+       buf[0] = address;
+       buf[0x20] = sd->sensor->i2c_addr;
+       buf[0x21] = 0;
+
+       /* Read I2C register */
+       buf[0x22] = I2C_READ_CMD;
+
+       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                             0x04, 0x40, 0x1400, 0, buf, I2C_BUFFER_LENGTH,
+                             STV06XX_URB_MSG_TIMEOUT);
+       if (err < 0) {
+               pr_err("I2C: Read error writing address: %d\n", err);
+               return err;
+       }
+
+       err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                             0x04, 0xc0, 0x1410, 0, buf, sd->sensor->i2c_len,
+                             STV06XX_URB_MSG_TIMEOUT);
+       if (sd->sensor->i2c_len == 2)
+               *value = buf[0] | (buf[1] << 8);
+       else
+               *value = buf[0];
+
+       PDEBUG(D_CONF, "I2C: Read 0x%x from address 0x%x, status: %d",
+              *value, address, err);
+
+       return (err < 0) ? err : 0;
+}
+
+/* Dumps all bridge registers */
+static void stv06xx_dump_bridge(struct sd *sd)
+{
+       int i;
+       u8 data, buf;
+
+       pr_info("Dumping all stv06xx bridge registers\n");
+       for (i = 0x1400; i < 0x160f; i++) {
+               stv06xx_read_bridge(sd, i, &data);
+
+               pr_info("Read 0x%x from address 0x%x\n", data, i);
+       }
+
+       pr_info("Testing stv06xx bridge registers for writability\n");
+       for (i = 0x1400; i < 0x160f; i++) {
+               stv06xx_read_bridge(sd, i, &data);
+               buf = data;
+
+               stv06xx_write_bridge(sd, i, 0xff);
+               stv06xx_read_bridge(sd, i, &data);
+               if (data == 0xff)
+                       pr_info("Register 0x%x is read/write\n", i);
+               else if (data != buf)
+                       pr_info("Register 0x%x is read/write, but only partially\n",
+                               i);
+               else
+                       pr_info("Register 0x%x is read-only\n", i);
+
+               stv06xx_write_bridge(sd, i, buf);
+       }
+}
+
+/* this function is called at probe and resume time */
+static int stv06xx_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int err;
+
+       PDEBUG(D_PROBE, "Initializing camera");
+
+       /* Let the usb init settle for a bit
+          before performing the initialization */
+       msleep(250);
+
+       err = sd->sensor->init(sd);
+
+       if (dump_sensor && sd->sensor->dump)
+               sd->sensor->dump(sd);
+
+       return (err < 0) ? err : 0;
+}
+
+/* this function is called at probe time */
+static int stv06xx_init_controls(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       PDEBUG(D_PROBE, "Initializing controls");
+
+       gspca_dev->vdev.ctrl_handler = &gspca_dev->ctrl_handler;
+       return sd->sensor->init_controls(sd);
+}
+
+/* Start the camera */
+static int stv06xx_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct usb_host_interface *alt;
+       struct usb_interface *intf;
+       int err, packet_size;
+
+       intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+       alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+       if (!alt) {
+               PDEBUG(D_ERR, "Couldn't get altsetting");
+               return -EIO;
+       }
+
+       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+       err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size);
+       if (err < 0)
+               return err;
+
+       /* Prepare the sensor for start */
+       err = sd->sensor->start(sd);
+       if (err < 0)
+               goto out;
+
+       /* Start isochronous streaming */
+       err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 1);
+
+out:
+       if (err < 0)
+               PDEBUG(D_STREAM, "Starting stream failed");
+       else
+               PDEBUG(D_STREAM, "Started streaming");
+
+       return (err < 0) ? err : 0;
+}
+
+static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
+{
+       struct usb_host_interface *alt;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
+       alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
+       alt->endpoint[0].desc.wMaxPacketSize =
+               cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
+
+       return 0;
+}
+
+static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev)
+{
+       int ret, packet_size, min_packet_size;
+       struct usb_host_interface *alt;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
+       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+       min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
+       if (packet_size <= min_packet_size)
+               return -EIO;
+
+       packet_size -= 100;
+       if (packet_size < min_packet_size)
+               packet_size = min_packet_size;
+       alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
+
+       ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
+       if (ret < 0)
+               PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret);
+
+       return ret;
+}
+
+static void stv06xx_stopN(struct gspca_dev *gspca_dev)
+{
+       int err;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* stop ISO-streaming */
+       err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 0);
+       if (err < 0)
+               goto out;
+
+       err = sd->sensor->stop(sd);
+
+out:
+       if (err < 0)
+               PDEBUG(D_STREAM, "Failed to stop stream");
+       else
+               PDEBUG(D_STREAM, "Stopped streaming");
+}
+
+/*
+ * Analyse an USB packet of the data stream and store it appropriately.
+ * Each packet contains an integral number of chunks. Each chunk has
+ * 2-bytes identification, followed by 2-bytes that describe the chunk
+ * length. Known/guessed chunk identifications are:
+ * 8001/8005/C001/C005 - Begin new frame
+ * 8002/8006/C002/C006 - End frame
+ * 0200/4200           - Contains actual image data, bayer or compressed
+ * 0005                - 11 bytes of unknown data
+ * 0100                - 2 bytes of unknown data
+ * The 0005 and 0100 chunks seem to appear only in compressed stream.
+ */
+static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,                       /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       PDEBUG(D_PACK, "Packet of length %d arrived", len);
+
+       /* A packet may contain several frames
+          loop until the whole packet is reached */
+       while (len) {
+               int id, chunk_len;
+
+               if (len < 4) {
+                       PDEBUG(D_PACK, "Packet is smaller than 4 bytes");
+                       return;
+               }
+
+               /* Capture the id */
+               id = (data[0] << 8) | data[1];
+
+               /* Capture the chunk length */
+               chunk_len = (data[2] << 8) | data[3];
+               PDEBUG(D_PACK, "Chunk id: %x, length: %d", id, chunk_len);
+
+               data += 4;
+               len -= 4;
+
+               if (len < chunk_len) {
+                       PDEBUG(D_ERR, "URB packet length is smaller"
+                               " than the specified chunk length");
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+                       return;
+               }
+
+               /* First byte seem to be 02=data 2nd byte is unknown??? */
+               if (sd->bridge == BRIDGE_ST6422 && (id & 0xff00) == 0x0200)
+                       goto frame_data;
+
+               switch (id) {
+               case 0x0200:
+               case 0x4200:
+frame_data:
+                       PDEBUG(D_PACK, "Frame data packet detected");
+
+                       if (sd->to_skip) {
+                               int skip = (sd->to_skip < chunk_len) ?
+                                           sd->to_skip : chunk_len;
+                               data += skip;
+                               len -= skip;
+                               chunk_len -= skip;
+                               sd->to_skip -= skip;
+                       }
+
+                       gspca_frame_add(gspca_dev, INTER_PACKET,
+                                       data, chunk_len);
+                       break;
+
+               case 0x8001:
+               case 0x8005:
+               case 0xc001:
+               case 0xc005:
+                       PDEBUG(D_PACK, "Starting new frame");
+
+                       /* Create a new frame, chunk length should be zero */
+                       gspca_frame_add(gspca_dev, FIRST_PACKET,
+                                       NULL, 0);
+
+                       if (sd->bridge == BRIDGE_ST6422)
+                               sd->to_skip = gspca_dev->width * 4;
+
+                       if (chunk_len)
+                               PDEBUG(D_ERR, "Chunk length is "
+                                             "non-zero on a SOF");
+                       break;
+
+               case 0x8002:
+               case 0x8006:
+               case 0xc002:
+                       PDEBUG(D_PACK, "End of frame detected");
+
+                       /* Complete the last frame (if any) */
+                       gspca_frame_add(gspca_dev, LAST_PACKET,
+                                       NULL, 0);
+
+                       if (chunk_len)
+                               PDEBUG(D_ERR, "Chunk length is "
+                                             "non-zero on a EOF");
+                       break;
+
+               case 0x0005:
+                       PDEBUG(D_PACK, "Chunk 0x005 detected");
+                       /* Unknown chunk with 11 bytes of data,
+                          occurs just before end of each frame
+                          in compressed mode */
+                       break;
+
+               case 0x0100:
+                       PDEBUG(D_PACK, "Chunk 0x0100 detected");
+                       /* Unknown chunk with 2 bytes of data,
+                          occurs 2-3 times per USB interrupt */
+                       break;
+               case 0x42ff:
+                       PDEBUG(D_PACK, "Chunk 0x42ff detected");
+                       /* Special chunk seen sometimes on the ST6422 */
+                       break;
+               default:
+                       PDEBUG(D_PACK, "Unknown chunk 0x%04x detected", id);
+                       /* Unknown chunk */
+               }
+               data    += chunk_len;
+               len     -= chunk_len;
+       }
+}
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,               /* interrupt packet data */
+                       int len)                /* interrupt packet length */
+{
+       int ret = -EINVAL;
+
+       if (len == 1 && data[0] == 0x80) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
+               input_sync(gspca_dev->input_dev);
+               ret = 0;
+       }
+
+       if (len == 1 && data[0] == 0x88) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+               input_sync(gspca_dev->input_dev);
+               ret = 0;
+       }
+
+       return ret;
+}
+#endif
+
+static int stv06xx_config(struct gspca_dev *gspca_dev,
+                         const struct usb_device_id *id);
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name = MODULE_NAME,
+       .config = stv06xx_config,
+       .init = stv06xx_init,
+       .init_controls = stv06xx_init_controls,
+       .start = stv06xx_start,
+       .stopN = stv06xx_stopN,
+       .pkt_scan = stv06xx_pkt_scan,
+       .isoc_init = stv06xx_isoc_init,
+       .isoc_nego = stv06xx_isoc_nego,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .int_pkt_scan = sd_int_pkt_scan,
+#endif
+};
+
+/* This function is called at probe time */
+static int stv06xx_config(struct gspca_dev *gspca_dev,
+                         const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       PDEBUG(D_PROBE, "Configuring camera");
+
+       sd->bridge = id->driver_info;
+       gspca_dev->sd_desc = &sd_desc;
+
+       if (dump_bridge)
+               stv06xx_dump_bridge(sd);
+
+       sd->sensor = &stv06xx_sensor_st6422;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       sd->sensor = &stv06xx_sensor_vv6410;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       sd->sensor = &stv06xx_sensor_hdcs1x00;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       sd->sensor = &stv06xx_sensor_hdcs1020;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       sd->sensor = &stv06xx_sensor_pb0100;
+       if (!sd->sensor->probe(sd))
+               return 0;
+
+       sd->sensor = NULL;
+       return -ENODEV;
+}
+
+
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       /* QuickCam Express */
+       {USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 },
+       /* LEGO cam / QuickCam Web */
+       {USB_DEVICE(0x046d, 0x0850), .driver_info = BRIDGE_STV610 },
+       /* Dexxa WebCam USB */
+       {USB_DEVICE(0x046d, 0x0870), .driver_info = BRIDGE_STV602 },
+       /* QuickCam Messenger */
+       {USB_DEVICE(0x046D, 0x08F0), .driver_info = BRIDGE_ST6422 },
+       /* QuickCam Communicate */
+       {USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 },
+       /* QuickCam Messenger (new) */
+       {USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 },
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+                       const struct usb_device_id *id)
+{
+       PDEBUG(D_PROBE, "Probing for a stv06xx device");
+       return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
+                              THIS_MODULE);
+}
+
+static void sd_disconnect(struct usb_interface *intf)
+{
+       struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+       struct sd *sd = (struct sd *) gspca_dev;
+       void *priv = sd->sensor_priv;
+       PDEBUG(D_PROBE, "Disconnecting the stv06xx device");
+
+       sd->sensor = NULL;
+       gspca_disconnect(intf);
+       kfree(priv);
+}
+
+static struct usb_driver sd_driver = {
+       .name = MODULE_NAME,
+       .id_table = device_table,
+       .probe = sd_probe,
+       .disconnect = sd_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
+
+module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
+
+module_param(dump_sensor, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dump_sensor, "Dumps all sensor registers at startup");
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx.h b/drivers/media/usb/gspca/stv06xx/stv06xx.h
new file mode 100644 (file)
index 0000000..34957a4
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ * Copyright (c) 2008 Erik Andrén
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * P/N 861037:      Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
+ * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
+ * P/N 861075-0040: Sensor HDCS1000        ASIC
+ * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
+ * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
+ */
+
+#ifndef STV06XX_H_
+#define STV06XX_H_
+
+#include <linux/slab.h>
+#include "gspca.h"
+
+#define MODULE_NAME "STV06xx"
+
+#define STV_ISOC_ENDPOINT_ADDR         0x81
+
+#define STV_R                           0x0509
+
+#define STV_REG23                      0x0423
+
+/* Control registers of the STV0600 ASIC */
+#define STV_I2C_PARTNER                        0x1420
+#define STV_I2C_VAL_REG_VAL_PAIRS_MIN1 0x1421
+#define STV_I2C_READ_WRITE_TOGGLE      0x1422
+#define STV_I2C_FLUSH                  0x1423
+#define STV_I2C_SUCC_READ_REG_VALS     0x1424
+
+#define STV_ISO_ENABLE                 0x1440
+#define STV_SCAN_RATE                  0x1443
+#define STV_LED_CTRL                   0x1445
+#define STV_STV0600_EMULATION          0x1446
+#define STV_REG00                      0x1500
+#define STV_REG01                      0x1501
+#define STV_REG02                      0x1502
+#define STV_REG03                      0x1503
+#define STV_REG04                      0x1504
+
+#define STV_ISO_SIZE_L                 0x15c1
+#define STV_ISO_SIZE_H                 0x15c2
+
+/* Refers to the CIF 352x288 and QCIF 176x144 */
+/* 1: 288 lines, 2: 144 lines */
+#define STV_Y_CTRL                     0x15c3
+
+#define STV_RESET                       0x1620
+
+/* 0xa: 352 columns, 0x6: 176 columns */
+#define STV_X_CTRL                     0x1680
+
+#define STV06XX_URB_MSG_TIMEOUT                5000
+
+#define I2C_MAX_BYTES                  16
+#define I2C_MAX_WORDS                  8
+
+#define I2C_BUFFER_LENGTH              0x23
+#define I2C_READ_CMD                   3
+#define I2C_WRITE_CMD                  1
+
+#define LED_ON                         1
+#define LED_OFF                                0
+
+/* STV06xx device descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;
+
+       /* A pointer to the currently connected sensor */
+       const struct stv06xx_sensor *sensor;
+
+       /* Sensor private data */
+       void *sensor_priv;
+
+       /* The first 4 lines produced by the stv6422 are no good, this keeps
+          track of how many bytes we still need to skip during a frame */
+       int to_skip;
+
+       /* Bridge / Camera type */
+       u8 bridge;
+       #define BRIDGE_STV600 0
+       #define BRIDGE_STV602 1
+       #define BRIDGE_STV610 2
+       #define BRIDGE_ST6422 3 /* With integrated sensor */
+};
+
+int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data);
+int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data);
+
+int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len);
+int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len);
+
+int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value);
+int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value);
+
+#endif
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c
new file mode 100644 (file)
index 0000000..06fa54c
--- /dev/null
@@ -0,0 +1,540 @@
+/*
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ * Copyright (c) 2008 Erik Andrén
+ * Copyright (c) 2008 Chia-I Wu
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * P/N 861037:      Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
+ * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
+ * P/N 861075-0040: Sensor HDCS1000        ASIC
+ * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
+ * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "stv06xx_hdcs.h"
+
+static struct v4l2_pix_format hdcs1x00_mode[] = {
+       {
+               HDCS_1X00_DEF_WIDTH,
+               HDCS_1X00_DEF_HEIGHT,
+               V4L2_PIX_FMT_SGRBG8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT,
+               .bytesperline = HDCS_1X00_DEF_WIDTH,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1
+       }
+};
+
+static struct v4l2_pix_format hdcs1020_mode[] = {
+       {
+               HDCS_1020_DEF_WIDTH,
+               HDCS_1020_DEF_HEIGHT,
+               V4L2_PIX_FMT_SGRBG8,
+               V4L2_FIELD_NONE,
+               .sizeimage =
+                       HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT,
+               .bytesperline = HDCS_1020_DEF_WIDTH,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1
+       }
+};
+
+enum hdcs_power_state {
+       HDCS_STATE_SLEEP,
+       HDCS_STATE_IDLE,
+       HDCS_STATE_RUN
+};
+
+/* no lock? */
+struct hdcs {
+       enum hdcs_power_state state;
+       int w, h;
+
+       /* visible area of the sensor array */
+       struct {
+               int left, top;
+               int width, height;
+               int border;
+       } array;
+
+       struct {
+               /* Column timing overhead */
+               u8 cto;
+               /* Column processing overhead */
+               u8 cpo;
+               /* Row sample period constant */
+               u16 rs;
+               /* Exposure reset duration */
+               u16 er;
+       } exp;
+
+       int psmp;
+};
+
+static int hdcs_reg_write_seq(struct sd *sd, u8 reg, u8 *vals, u8 len)
+{
+       u8 regs[I2C_MAX_BYTES * 2];
+       int i;
+
+       if (unlikely((len <= 0) || (len >= I2C_MAX_BYTES) ||
+                    (reg + len > 0xff)))
+               return -EINVAL;
+
+       for (i = 0; i < len; i++) {
+               regs[2 * i] = reg;
+               regs[2 * i + 1] = vals[i];
+               /* All addresses are shifted left one bit
+                * as bit 0 toggles r/w */
+               reg += 2;
+       }
+
+       return stv06xx_write_sensor_bytes(sd, regs, len);
+}
+
+static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state)
+{
+       struct hdcs *hdcs = sd->sensor_priv;
+       u8 val;
+       int ret;
+
+       if (hdcs->state == state)
+               return 0;
+
+       /* we need to go idle before running or sleeping */
+       if (hdcs->state != HDCS_STATE_IDLE) {
+               ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
+               if (ret)
+                       return ret;
+       }
+
+       hdcs->state = HDCS_STATE_IDLE;
+
+       if (state == HDCS_STATE_IDLE)
+               return 0;
+
+       switch (state) {
+       case HDCS_STATE_SLEEP:
+               val = HDCS_SLEEP_MODE;
+               break;
+
+       case HDCS_STATE_RUN:
+               val = HDCS_RUN_ENABLE;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val);
+
+       /* Update the state if the write succeeded */
+       if (!ret)
+               hdcs->state = state;
+
+       return ret;
+}
+
+static int hdcs_reset(struct sd *sd)
+{
+       struct hdcs *hdcs = sd->sensor_priv;
+       int err;
+
+       err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 1);
+       if (err < 0)
+               return err;
+
+       err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
+       if (err < 0)
+               hdcs->state = HDCS_STATE_IDLE;
+
+       return err;
+}
+
+static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct hdcs *hdcs = sd->sensor_priv;
+       int rowexp, srowexp;
+       int max_srowexp;
+       /* Column time period */
+       int ct;
+       /* Column processing period */
+       int cp;
+       /* Row processing period */
+       int rp;
+       /* Minimum number of column timing periods
+          within the column processing period */
+       int mnct;
+       int cycles, err;
+       u8 exp[14];
+
+       cycles = val * HDCS_CLK_FREQ_MHZ * 257;
+
+       ct = hdcs->exp.cto + hdcs->psmp + (HDCS_ADC_START_SIG_DUR + 2);
+       cp = hdcs->exp.cto + (hdcs->w * ct / 2);
+
+       /* the cycles one row takes */
+       rp = hdcs->exp.rs + cp;
+
+       rowexp = cycles / rp;
+
+       /* the remaining cycles */
+       cycles -= rowexp * rp;
+
+       /* calculate sub-row exposure */
+       if (IS_1020(sd)) {
+               /* see HDCS-1020 datasheet 3.5.6.4, p. 63 */
+               srowexp = hdcs->w - (cycles + hdcs->exp.er + 13) / ct;
+
+               mnct = (hdcs->exp.er + 12 + ct - 1) / ct;
+               max_srowexp = hdcs->w - mnct;
+       } else {
+               /* see HDCS-1000 datasheet 3.4.5.5, p. 61 */
+               srowexp = cp - hdcs->exp.er - 6 - cycles;
+
+               mnct = (hdcs->exp.er + 5 + ct - 1) / ct;
+               max_srowexp = cp - mnct * ct - 1;
+       }
+
+       if (srowexp < 0)
+               srowexp = 0;
+       else if (srowexp > max_srowexp)
+               srowexp = max_srowexp;
+
+       if (IS_1020(sd)) {
+               exp[0] = HDCS20_CONTROL;
+               exp[1] = 0x00;          /* Stop streaming */
+               exp[2] = HDCS_ROWEXPL;
+               exp[3] = rowexp & 0xff;
+               exp[4] = HDCS_ROWEXPH;
+               exp[5] = rowexp >> 8;
+               exp[6] = HDCS20_SROWEXP;
+               exp[7] = (srowexp >> 2) & 0xff;
+               exp[8] = HDCS20_ERROR;
+               exp[9] = 0x10;          /* Clear exposure error flag*/
+               exp[10] = HDCS20_CONTROL;
+               exp[11] = 0x04;         /* Restart streaming */
+               err = stv06xx_write_sensor_bytes(sd, exp, 6);
+       } else {
+               exp[0] = HDCS00_CONTROL;
+               exp[1] = 0x00;         /* Stop streaming */
+               exp[2] = HDCS_ROWEXPL;
+               exp[3] = rowexp & 0xff;
+               exp[4] = HDCS_ROWEXPH;
+               exp[5] = rowexp >> 8;
+               exp[6] = HDCS00_SROWEXPL;
+               exp[7] = srowexp & 0xff;
+               exp[8] = HDCS00_SROWEXPH;
+               exp[9] = srowexp >> 8;
+               exp[10] = HDCS_STATUS;
+               exp[11] = 0x10;         /* Clear exposure error flag*/
+               exp[12] = HDCS00_CONTROL;
+               exp[13] = 0x04;         /* Restart streaming */
+               err = stv06xx_write_sensor_bytes(sd, exp, 7);
+               if (err < 0)
+                       return err;
+       }
+       PDEBUG(D_V4L2, "Writing exposure %d, rowexp %d, srowexp %d",
+              val, rowexp, srowexp);
+       return err;
+}
+
+static int hdcs_set_gains(struct sd *sd, u8 g)
+{
+       int err;
+       u8 gains[4];
+
+       /* the voltage gain Av = (1 + 19 * val / 127) * (1 + bit7) */
+       if (g > 127)
+               g = 0x80 | (g / 2);
+
+       gains[0] = g;
+       gains[1] = g;
+       gains[2] = g;
+       gains[3] = g;
+
+       err = hdcs_reg_write_seq(sd, HDCS_ERECPGA, gains, 4);
+       return err;
+}
+
+static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       PDEBUG(D_V4L2, "Writing gain %d", val);
+       return hdcs_set_gains((struct sd *) gspca_dev,
+                              val & 0xff);
+}
+
+static int hdcs_set_size(struct sd *sd,
+               unsigned int width, unsigned int height)
+{
+       struct hdcs *hdcs = sd->sensor_priv;
+       u8 win[4];
+       unsigned int x, y;
+       int err;
+
+       /* must be multiple of 4 */
+       width = (width + 3) & ~0x3;
+       height = (height + 3) & ~0x3;
+
+       if (width > hdcs->array.width)
+               width = hdcs->array.width;
+
+       if (IS_1020(sd)) {
+               /* the borders are also invalid */
+               if (height + 2 * hdcs->array.border + HDCS_1020_BOTTOM_Y_SKIP
+                                 > hdcs->array.height)
+                       height = hdcs->array.height - 2 * hdcs->array.border -
+                               HDCS_1020_BOTTOM_Y_SKIP;
+
+               y = (hdcs->array.height - HDCS_1020_BOTTOM_Y_SKIP - height) / 2
+                               + hdcs->array.top;
+       } else {
+               if (height > hdcs->array.height)
+                       height = hdcs->array.height;
+
+               y = hdcs->array.top + (hdcs->array.height - height) / 2;
+       }
+
+       x = hdcs->array.left + (hdcs->array.width - width) / 2;
+
+       win[0] = y / 4;
+       win[1] = x / 4;
+       win[2] = (y + height) / 4 - 1;
+       win[3] = (x + width) / 4 - 1;
+
+       err = hdcs_reg_write_seq(sd, HDCS_FWROW, win, 4);
+       if (err < 0)
+               return err;
+
+       /* Update the current width and height */
+       hdcs->w = width;
+       hdcs->h = height;
+       return err;
+}
+
+static int hdcs_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct gspca_dev *gspca_dev =
+               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+       int err = -EINVAL;
+
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+               err = hdcs_set_gain(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_EXPOSURE:
+               err = hdcs_set_exposure(gspca_dev, ctrl->val);
+               break;
+       }
+       return err;
+}
+
+static const struct v4l2_ctrl_ops hdcs_ctrl_ops = {
+       .s_ctrl = hdcs_s_ctrl,
+};
+
+static int hdcs_init_controls(struct sd *sd)
+{
+       struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
+
+       v4l2_ctrl_handler_init(hdl, 2);
+       v4l2_ctrl_new_std(hdl, &hdcs_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0, 0xff, 1, HDCS_DEFAULT_EXPOSURE);
+       v4l2_ctrl_new_std(hdl, &hdcs_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 0xff, 1, HDCS_DEFAULT_GAIN);
+       return hdl->error;
+}
+
+static int hdcs_probe_1x00(struct sd *sd)
+{
+       struct hdcs *hdcs;
+       u16 sensor;
+       int ret;
+
+       ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
+       if (ret < 0 || sensor != 0x08)
+               return -ENODEV;
+
+       pr_info("HDCS-1000/1100 sensor detected\n");
+
+       sd->gspca_dev.cam.cam_mode = hdcs1x00_mode;
+       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode);
+
+       hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
+       if (!hdcs)
+               return -ENOMEM;
+
+       hdcs->array.left = 8;
+       hdcs->array.top = 8;
+       hdcs->array.width = HDCS_1X00_DEF_WIDTH;
+       hdcs->array.height = HDCS_1X00_DEF_HEIGHT;
+       hdcs->array.border = 4;
+
+       hdcs->exp.cto = 4;
+       hdcs->exp.cpo = 2;
+       hdcs->exp.rs = 186;
+       hdcs->exp.er = 100;
+
+       /*
+        * Frame rate on HDCS-1000 with STV600 depends on PSMP:
+        *  4 = doesn't work at all
+        *  5 = 7.8 fps,
+        *  6 = 6.9 fps,
+        *  8 = 6.3 fps,
+        * 10 = 5.5 fps,
+        * 15 = 4.4 fps,
+        * 31 = 2.8 fps
+        *
+        * Frame rate on HDCS-1000 with STV602 depends on PSMP:
+        * 15 = doesn't work at all
+        * 18 = doesn't work at all
+        * 19 = 7.3 fps
+        * 20 = 7.4 fps
+        * 21 = 7.4 fps
+        * 22 = 7.4 fps
+        * 24 = 6.3 fps
+        * 30 = 5.4 fps
+        */
+       hdcs->psmp = (sd->bridge == BRIDGE_STV602) ? 20 : 5;
+
+       sd->sensor_priv = hdcs;
+
+       return 0;
+}
+
+static int hdcs_probe_1020(struct sd *sd)
+{
+       struct hdcs *hdcs;
+       u16 sensor;
+       int ret;
+
+       ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
+       if (ret < 0 || sensor != 0x10)
+               return -ENODEV;
+
+       pr_info("HDCS-1020 sensor detected\n");
+
+       sd->gspca_dev.cam.cam_mode = hdcs1020_mode;
+       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode);
+
+       hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
+       if (!hdcs)
+               return -ENOMEM;
+
+       /*
+        * From Andrey's test image: looks like HDCS-1020 upper-left
+        * visible pixel is at 24,8 (y maybe even smaller?) and lower-right
+        * visible pixel at 375,299 (x maybe even larger?)
+        */
+       hdcs->array.left = 24;
+       hdcs->array.top  = 4;
+       hdcs->array.width = HDCS_1020_DEF_WIDTH;
+       hdcs->array.height = 304;
+       hdcs->array.border = 4;
+
+       hdcs->psmp = 6;
+
+       hdcs->exp.cto = 3;
+       hdcs->exp.cpo = 3;
+       hdcs->exp.rs = 155;
+       hdcs->exp.er = 96;
+
+       sd->sensor_priv = hdcs;
+
+       return 0;
+}
+
+static int hdcs_start(struct sd *sd)
+{
+       PDEBUG(D_STREAM, "Starting stream");
+
+       return hdcs_set_state(sd, HDCS_STATE_RUN);
+}
+
+static int hdcs_stop(struct sd *sd)
+{
+       PDEBUG(D_STREAM, "Halting stream");
+
+       return hdcs_set_state(sd, HDCS_STATE_SLEEP);
+}
+
+static int hdcs_init(struct sd *sd)
+{
+       struct hdcs *hdcs = sd->sensor_priv;
+       int i, err = 0;
+
+       /* Set the STV0602AA in STV0600 emulation mode */
+       if (sd->bridge == BRIDGE_STV602)
+               stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1);
+
+       /* Execute the bridge init */
+       for (i = 0; i < ARRAY_SIZE(stv_bridge_init) && !err; i++) {
+               err = stv06xx_write_bridge(sd, stv_bridge_init[i][0],
+                                          stv_bridge_init[i][1]);
+       }
+       if (err < 0)
+               return err;
+
+       /* sensor soft reset */
+       hdcs_reset(sd);
+
+       /* Execute the sensor init */
+       for (i = 0; i < ARRAY_SIZE(stv_sensor_init) && !err; i++) {
+               err = stv06xx_write_sensor(sd, stv_sensor_init[i][0],
+                                            stv_sensor_init[i][1]);
+       }
+       if (err < 0)
+               return err;
+
+       /* Enable continuous frame capture, bit 2: stop when frame complete */
+       err = stv06xx_write_sensor(sd, HDCS_REG_CONFIG(sd), BIT(3));
+       if (err < 0)
+               return err;
+
+       /* Set PGA sample duration
+       (was 0x7E for the STV602, but caused slow framerate with HDCS-1020) */
+       if (IS_1020(sd))
+               err = stv06xx_write_sensor(sd, HDCS_TCTRL,
+                               (HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp);
+       else
+               err = stv06xx_write_sensor(sd, HDCS_TCTRL,
+                               (HDCS_ADC_START_SIG_DUR << 5) | hdcs->psmp);
+       if (err < 0)
+               return err;
+
+       return hdcs_set_size(sd, hdcs->array.width, hdcs->array.height);
+}
+
+static int hdcs_dump(struct sd *sd)
+{
+       u16 reg, val;
+
+       pr_info("Dumping sensor registers:\n");
+
+       for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) {
+               stv06xx_read_sensor(sd, reg, &val);
+               pr_info("reg 0x%02x = 0x%02x\n", reg, val);
+       }
+       return 0;
+}
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.h
new file mode 100644 (file)
index 0000000..1ba9158
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ * Copyright (c) 2008 Erik Andrén
+ * Copyright (c) 2008 Chia-I Wu
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * P/N 861037:      Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
+ * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
+ * P/N 861075-0040: Sensor HDCS1000        ASIC
+ * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
+ * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
+ */
+
+#ifndef STV06XX_HDCS_H_
+#define STV06XX_HDCS_H_
+
+#include "stv06xx_sensor.h"
+
+#define HDCS_REG_CONFIG(sd)    (IS_1020(sd) ? HDCS20_CONFIG : HDCS00_CONFIG)
+#define HDCS_REG_CONTROL(sd)   (IS_1020(sd) ? HDCS20_CONTROL : HDCS00_CONTROL)
+
+#define HDCS_1X00_DEF_WIDTH    360
+#define HDCS_1X00_DEF_HEIGHT   296
+
+#define HDCS_1020_DEF_WIDTH    352
+#define HDCS_1020_DEF_HEIGHT   292
+
+#define HDCS_1020_BOTTOM_Y_SKIP        4
+
+#define HDCS_CLK_FREQ_MHZ      25
+
+#define HDCS_ADC_START_SIG_DUR 3
+
+/* LSB bit of I2C or register address signifies write (0) or read (1) */
+/* I2C Registers common for both HDCS-1000/1100 and HDCS-1020 */
+/* Identifications Register */
+#define HDCS_IDENT             (0x00 << 1)
+/* Status Register */
+#define HDCS_STATUS            (0x01 << 1)
+/* Interrupt Mask Register */
+#define HDCS_IMASK             (0x02 << 1)
+/* Pad Control Register */
+#define HDCS_PCTRL             (0x03 << 1)
+/* Pad Drive Control Register */
+#define HDCS_PDRV              (0x04 << 1)
+/* Interface Control Register */
+#define HDCS_ICTRL             (0x05 << 1)
+/* Interface Timing Register */
+#define HDCS_ITMG              (0x06 << 1)
+/* Baud Fraction Register */
+#define HDCS_BFRAC             (0x07 << 1)
+/* Baud Rate Register */
+#define HDCS_BRATE             (0x08 << 1)
+/* ADC Control Register */
+#define HDCS_ADCCTRL           (0x09 << 1)
+/* First Window Row Register */
+#define HDCS_FWROW             (0x0a << 1)
+/* First Window Column Register */
+#define HDCS_FWCOL             (0x0b << 1)
+/* Last Window Row Register */
+#define HDCS_LWROW             (0x0c << 1)
+/* Last Window Column Register */
+#define HDCS_LWCOL             (0x0d << 1)
+/* Timing Control Register */
+#define HDCS_TCTRL             (0x0e << 1)
+/* PGA Gain Register: Even Row, Even Column */
+#define HDCS_ERECPGA           (0x0f << 1)
+/* PGA Gain Register: Even Row, Odd Column */
+#define HDCS_EROCPGA           (0x10 << 1)
+/* PGA Gain Register: Odd Row, Even Column */
+#define HDCS_ORECPGA           (0x11 << 1)
+/* PGA Gain Register: Odd Row, Odd Column */
+#define HDCS_OROCPGA           (0x12 << 1)
+/* Row Exposure Low Register */
+#define HDCS_ROWEXPL           (0x13 << 1)
+/* Row Exposure High Register */
+#define HDCS_ROWEXPH           (0x14 << 1)
+
+/* I2C Registers only for HDCS-1000/1100 */
+/* Sub-Row Exposure Low Register */
+#define HDCS00_SROWEXPL                (0x15 << 1)
+/* Sub-Row Exposure High Register */
+#define HDCS00_SROWEXPH                (0x16 << 1)
+/* Configuration Register */
+#define HDCS00_CONFIG          (0x17 << 1)
+/* Control Register */
+#define HDCS00_CONTROL         (0x18 << 1)
+
+/* I2C Registers only for HDCS-1020 */
+/* Sub-Row Exposure Register */
+#define HDCS20_SROWEXP         (0x15 << 1)
+/* Error Control Register */
+#define HDCS20_ERROR           (0x16 << 1)
+/* Interface Timing 2 Register */
+#define HDCS20_ITMG2           (0x17 << 1)
+/* Interface Control 2 Register        */
+#define HDCS20_ICTRL2          (0x18 << 1)
+/* Horizontal Blank Register */
+#define HDCS20_HBLANK          (0x19 << 1)
+/* Vertical Blank Register */
+#define HDCS20_VBLANK          (0x1a << 1)
+/* Configuration Register */
+#define HDCS20_CONFIG          (0x1b << 1)
+/* Control Register */
+#define HDCS20_CONTROL         (0x1c << 1)
+
+#define HDCS_RUN_ENABLE                (1 << 2)
+#define HDCS_SLEEP_MODE                (1 << 1)
+
+#define HDCS_DEFAULT_EXPOSURE  48
+#define HDCS_DEFAULT_GAIN      50
+
+static int hdcs_probe_1x00(struct sd *sd);
+static int hdcs_probe_1020(struct sd *sd);
+static int hdcs_start(struct sd *sd);
+static int hdcs_init(struct sd *sd);
+static int hdcs_init_controls(struct sd *sd);
+static int hdcs_stop(struct sd *sd);
+static int hdcs_dump(struct sd *sd);
+
+static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+
+const struct stv06xx_sensor stv06xx_sensor_hdcs1x00 = {
+       .name = "HP HDCS-1000/1100",
+       .i2c_flush = 0,
+       .i2c_addr = (0x55 << 1),
+       .i2c_len = 1,
+
+       /* FIXME (see if we can lower min_packet_size, needs testing, and also
+          adjusting framerate when the bandwidth gets lower) */
+       .min_packet_size = { 847 },
+       .max_packet_size = { 847 },
+
+       .init = hdcs_init,
+       .init_controls = hdcs_init_controls,
+       .probe = hdcs_probe_1x00,
+       .start = hdcs_start,
+       .stop = hdcs_stop,
+       .dump = hdcs_dump,
+};
+
+const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = {
+       .name = "HDCS-1020",
+       .i2c_flush = 0,
+       .i2c_addr = (0x55 << 1),
+       .i2c_len = 1,
+
+       /* FIXME (see if we can lower min_packet_size, needs testing, and also
+          adjusting framerate when the bandwidthm gets lower) */
+       .min_packet_size = { 847 },
+       .max_packet_size = { 847 },
+
+       .init = hdcs_init,
+       .init_controls = hdcs_init_controls,
+       .probe = hdcs_probe_1020,
+       .start = hdcs_start,
+       .stop = hdcs_stop,
+       .dump = hdcs_dump,
+};
+
+static const u16 stv_bridge_init[][2] = {
+       {STV_ISO_ENABLE, 0},
+       {STV_REG23, 0},
+       {STV_REG00, 0x1d},
+       {STV_REG01, 0xb5},
+       {STV_REG02, 0xa8},
+       {STV_REG03, 0x95},
+       {STV_REG04, 0x07},
+
+       {STV_SCAN_RATE, 0x20},
+       {STV_Y_CTRL, 0x01},
+       {STV_X_CTRL, 0x0a}
+};
+
+static const u8 stv_sensor_init[][2] = {
+       /* Clear status (writing 1 will clear the corresponding status bit) */
+       {HDCS_STATUS, BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
+       /* Disable all interrupts */
+       {HDCS_IMASK, 0x00},
+       {HDCS_PCTRL, BIT(6) | BIT(5) | BIT(1) | BIT(0)},
+       {HDCS_PDRV,  0x00},
+       {HDCS_ICTRL, BIT(5)},
+       {HDCS_ITMG,  BIT(4) | BIT(1)},
+       /* ADC output resolution to 10 bits */
+       {HDCS_ADCCTRL, 10}
+};
+
+#endif
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
new file mode 100644 (file)
index 0000000..cdfc3d0
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ * Copyright (c) 2008 Erik Andrén
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * P/N 861037:      Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
+ * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
+ * P/N 861075-0040: Sensor HDCS1000        ASIC
+ * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
+ * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
+ */
+
+/*
+ * The spec file for the PB-0100 suggests the following for best quality
+ * images after the sensor has been reset :
+ *
+ * PB_ADCGAINL      = R60 = 0x03 (3 dec)      : sets low reference of ADC
+                                               to produce good black level
+ * PB_PREADCTRL     = R32 = 0x1400 (5120 dec) : Enables global gain changes
+                                               through R53
+ * PB_ADCMINGAIN    = R52 = 0x10 (16 dec)     : Sets the minimum gain for
+                                               auto-exposure
+ * PB_ADCGLOBALGAIN = R53 = 0x10 (16 dec)     : Sets the global gain
+ * PB_EXPGAIN       = R14 = 0x11 (17 dec)     : Sets the auto-exposure value
+ * PB_UPDATEINT     = R23 = 0x02 (2 dec)      : Sets the speed on
+                                               auto-exposure routine
+ * PB_CFILLIN       = R5  = 0x0E (14 dec)     : Sets the frame rate
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "stv06xx_pb0100.h"
+
+struct pb0100_ctrls {
+       struct { /* one big happy control cluster... */
+               struct v4l2_ctrl *autogain;
+               struct v4l2_ctrl *gain;
+               struct v4l2_ctrl *exposure;
+               struct v4l2_ctrl *red;
+               struct v4l2_ctrl *blue;
+               struct v4l2_ctrl *natural;
+       };
+       struct v4l2_ctrl *target;
+};
+
+static struct v4l2_pix_format pb0100_mode[] = {
+/* low res / subsample modes disabled as they are only half res horizontal,
+   halving the vertical resolution does not seem to work */
+       {
+               320,
+               240,
+               V4L2_PIX_FMT_SGRBG8,
+               V4L2_FIELD_NONE,
+               .sizeimage = 320 * 240,
+               .bytesperline = 320,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = PB0100_CROP_TO_VGA
+       },
+       {
+               352,
+               288,
+               V4L2_PIX_FMT_SGRBG8,
+               V4L2_FIELD_NONE,
+               .sizeimage = 352 * 288,
+               .bytesperline = 352,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0
+       }
+};
+
+static int pb0100_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;
+       struct pb0100_ctrls *ctrls = sd->sensor_priv;
+       int err = -EINVAL;
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUTOGAIN:
+               err = pb0100_set_autogain(gspca_dev, ctrl->val);
+               if (err)
+                       break;
+               if (ctrl->val)
+                       break;
+               err = pb0100_set_gain(gspca_dev, ctrls->gain->val);
+               if (err)
+                       break;
+               err = pb0100_set_exposure(gspca_dev, ctrls->exposure->val);
+               break;
+       case V4L2_CTRL_CLASS_USER + 0x1001:
+               err = pb0100_set_autogain_target(gspca_dev, ctrl->val);
+               break;
+       }
+       return err;
+}
+
+static const struct v4l2_ctrl_ops pb0100_ctrl_ops = {
+       .s_ctrl = pb0100_s_ctrl,
+};
+
+static int pb0100_init_controls(struct sd *sd)
+{
+       struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
+       struct pb0100_ctrls *ctrls;
+       static const struct v4l2_ctrl_config autogain_target = {
+               .ops = &pb0100_ctrl_ops,
+               .id = V4L2_CTRL_CLASS_USER + 0x1000,
+               .type = V4L2_CTRL_TYPE_INTEGER,
+               .name = "Automatic Gain Target",
+               .max = 255,
+               .step = 1,
+               .def = 128,
+       };
+       static const struct v4l2_ctrl_config natural_light = {
+               .ops = &pb0100_ctrl_ops,
+               .id = V4L2_CTRL_CLASS_USER + 0x1001,
+               .type = V4L2_CTRL_TYPE_BOOLEAN,
+               .name = "Natural Light Source",
+               .max = 1,
+               .step = 1,
+               .def = 1,
+       };
+
+       ctrls = kzalloc(sizeof(*ctrls), GFP_KERNEL);
+       if (!ctrls)
+               return -ENOMEM;
+
+       v4l2_ctrl_handler_init(hdl, 6);
+       ctrls->autogain = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+       ctrls->exposure = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0, 511, 1, 12);
+       ctrls->gain = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 255, 1, 128);
+       ctrls->red = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
+                       V4L2_CID_RED_BALANCE, -255, 255, 1, 0);
+       ctrls->blue = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
+                       V4L2_CID_BLUE_BALANCE, -255, 255, 1, 0);
+       ctrls->natural = v4l2_ctrl_new_custom(hdl, &natural_light, NULL);
+       ctrls->target = v4l2_ctrl_new_custom(hdl, &autogain_target, NULL);
+       if (hdl->error) {
+               kfree(ctrls);
+               return hdl->error;
+       }
+       sd->sensor_priv = ctrls;
+       v4l2_ctrl_auto_cluster(5, &ctrls->autogain, 0, false);
+       return 0;
+}
+
+static int pb0100_probe(struct sd *sd)
+{
+       u16 sensor;
+       int err;
+
+       err = stv06xx_read_sensor(sd, PB_IDENT, &sensor);
+
+       if (err < 0)
+               return -ENODEV;
+       if ((sensor >> 8) != 0x64)
+               return -ENODEV;
+
+       pr_info("Photobit pb0100 sensor detected\n");
+
+       sd->gspca_dev.cam.cam_mode = pb0100_mode;
+       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode);
+
+       return 0;
+}
+
+static int pb0100_start(struct sd *sd)
+{
+       int err, packet_size, max_packet_size;
+       struct usb_host_interface *alt;
+       struct usb_interface *intf;
+       struct cam *cam = &sd->gspca_dev.cam;
+       u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
+
+       intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+       alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+       if (!alt)
+               return -ENODEV;
+       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+
+       /* If we don't have enough bandwidth use a lower framerate */
+       max_packet_size = sd->sensor->max_packet_size[sd->gspca_dev.curr_mode];
+       if (packet_size < max_packet_size)
+               stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
+       else
+               stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(5)|BIT(3)|BIT(1));
+
+       /* Setup sensor window */
+       if (mode & PB0100_CROP_TO_VGA) {
+               stv06xx_write_sensor(sd, PB_RSTART, 30);
+               stv06xx_write_sensor(sd, PB_CSTART, 20);
+               stv06xx_write_sensor(sd, PB_RWSIZE, 240 - 1);
+               stv06xx_write_sensor(sd, PB_CWSIZE, 320 - 1);
+       } else {
+               stv06xx_write_sensor(sd, PB_RSTART, 8);
+               stv06xx_write_sensor(sd, PB_CSTART, 4);
+               stv06xx_write_sensor(sd, PB_RWSIZE, 288 - 1);
+               stv06xx_write_sensor(sd, PB_CWSIZE, 352 - 1);
+       }
+
+       if (mode & PB0100_SUBSAMPLE) {
+               stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02); /* Wrong, FIXME */
+               stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
+
+               stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
+       } else {
+               stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
+               stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
+               /* larger -> slower */
+               stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20);
+       }
+
+       err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)|BIT(1));
+       PDEBUG(D_STREAM, "Started stream, status: %d", err);
+
+       return (err < 0) ? err : 0;
+}
+
+static int pb0100_stop(struct sd *sd)
+{
+       int err;
+
+       err = stv06xx_write_sensor(sd, PB_ABORTFRAME, 1);
+
+       if (err < 0)
+               goto out;
+
+       /* Set bit 1 to zero */
+       err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3));
+
+       PDEBUG(D_STREAM, "Halting stream");
+out:
+       return (err < 0) ? err : 0;
+}
+
+/* FIXME: Sort the init commands out and put them into tables,
+         this is only for getting the camera to work */
+/* FIXME: No error handling for now,
+         add this once the init has been converted to proper tables */
+static int pb0100_init(struct sd *sd)
+{
+       stv06xx_write_bridge(sd, STV_REG00, 1);
+       stv06xx_write_bridge(sd, STV_SCAN_RATE, 0);
+
+       /* Reset sensor */
+       stv06xx_write_sensor(sd, PB_RESET, 1);
+       stv06xx_write_sensor(sd, PB_RESET, 0);
+
+       /* Disable chip */
+       stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3));
+
+       /* Gain stuff...*/
+       stv06xx_write_sensor(sd, PB_PREADCTRL, BIT(12)|BIT(10)|BIT(6));
+       stv06xx_write_sensor(sd, PB_ADCGLOBALGAIN, 12);
+
+       /* Set up auto-exposure */
+       /* ADC VREF_HI new setting for a transition
+         from the Expose1 to the Expose2 setting */
+       stv06xx_write_sensor(sd, PB_R28, 12);
+       /* gain max for autoexposure */
+       stv06xx_write_sensor(sd, PB_ADCMAXGAIN, 180);
+       /* gain min for autoexposure  */
+       stv06xx_write_sensor(sd, PB_ADCMINGAIN, 12);
+       /* Maximum frame integration time (programmed into R8)
+          allowed for auto-exposure routine */
+       stv06xx_write_sensor(sd, PB_R54, 3);
+       /* Minimum frame integration time (programmed into R8)
+          allowed for auto-exposure routine */
+       stv06xx_write_sensor(sd, PB_R55, 0);
+       stv06xx_write_sensor(sd, PB_UPDATEINT, 1);
+       /* R15  Expose0 (maximum that auto-exposure may use) */
+       stv06xx_write_sensor(sd, PB_R15, 800);
+       /* R17  Expose2 (minimum that auto-exposure may use) */
+       stv06xx_write_sensor(sd, PB_R17, 10);
+
+       stv06xx_write_sensor(sd, PB_EXPGAIN, 0);
+
+       /* 0x14 */
+       stv06xx_write_sensor(sd, PB_VOFFSET, 0);
+       /* 0x0D */
+       stv06xx_write_sensor(sd, PB_ADCGAINH, 11);
+       /* Set black level (important!) */
+       stv06xx_write_sensor(sd, PB_ADCGAINL, 0);
+
+       /* ??? */
+       stv06xx_write_bridge(sd, STV_REG00, 0x11);
+       stv06xx_write_bridge(sd, STV_REG03, 0x45);
+       stv06xx_write_bridge(sd, STV_REG04, 0x07);
+
+       /* Scan/timing for the sensor */
+       stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
+       stv06xx_write_sensor(sd, PB_CFILLIN, 14);
+       stv06xx_write_sensor(sd, PB_VBL, 0);
+       stv06xx_write_sensor(sd, PB_FINTTIME, 0);
+       stv06xx_write_sensor(sd, PB_RINTTIME, 123);
+
+       stv06xx_write_bridge(sd, STV_REG01, 0xc2);
+       stv06xx_write_bridge(sd, STV_REG02, 0xb0);
+       return 0;
+}
+
+static int pb0100_dump(struct sd *sd)
+{
+       return 0;
+}
+
+static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct pb0100_ctrls *ctrls = sd->sensor_priv;
+
+       err = stv06xx_write_sensor(sd, PB_G1GAIN, val);
+       if (!err)
+               err = stv06xx_write_sensor(sd, PB_G2GAIN, val);
+       PDEBUG(D_V4L2, "Set green gain to %d, status: %d", val, err);
+
+       if (!err)
+               err = pb0100_set_red_balance(gspca_dev, ctrls->red->val);
+       if (!err)
+               err = pb0100_set_blue_balance(gspca_dev, ctrls->blue->val);
+
+       return err;
+}
+
+static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct pb0100_ctrls *ctrls = sd->sensor_priv;
+
+       val += ctrls->gain->val;
+       if (val < 0)
+               val = 0;
+       else if (val > 255)
+               val = 255;
+
+       err = stv06xx_write_sensor(sd, PB_RGAIN, val);
+       PDEBUG(D_V4L2, "Set red gain to %d, status: %d", val, err);
+
+       return err;
+}
+
+static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct pb0100_ctrls *ctrls = sd->sensor_priv;
+
+       val += ctrls->gain->val;
+       if (val < 0)
+               val = 0;
+       else if (val > 255)
+               val = 255;
+
+       err = stv06xx_write_sensor(sd, PB_BGAIN, val);
+       PDEBUG(D_V4L2, "Set blue gain to %d, status: %d", val, err);
+
+       return err;
+}
+
+static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int err;
+
+       err = stv06xx_write_sensor(sd, PB_RINTTIME, val);
+       PDEBUG(D_V4L2, "Set exposure to %d, status: %d", val, err);
+
+       return err;
+}
+
+static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct pb0100_ctrls *ctrls = sd->sensor_priv;
+
+       if (val) {
+               if (ctrls->natural->val)
+                       val = BIT(6)|BIT(4)|BIT(0);
+               else
+                       val = BIT(4)|BIT(0);
+       } else
+               val = 0;
+
+       err = stv06xx_write_sensor(sd, PB_EXPGAIN, val);
+       PDEBUG(D_V4L2, "Set autogain to %d (natural: %d), status: %d",
+              val, ctrls->natural->val, err);
+
+       return err;
+}
+
+static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err, totalpixels, brightpixels, darkpixels;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* Number of pixels counted by the sensor when subsampling the pixels.
+        * Slightly larger than the real value to avoid oscillation */
+       totalpixels = gspca_dev->width * gspca_dev->height;
+       totalpixels = totalpixels/(8*8) + totalpixels/(64*64);
+
+       brightpixels = (totalpixels * val) >> 8;
+       darkpixels   = totalpixels - brightpixels;
+       err = stv06xx_write_sensor(sd, PB_R21, brightpixels);
+       if (!err)
+               err = stv06xx_write_sensor(sd, PB_R22, darkpixels);
+
+       PDEBUG(D_V4L2, "Set autogain target to %d, status: %d", val, err);
+
+       return err;
+}
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.h
new file mode 100644 (file)
index 0000000..5071e53
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ * Copyright (c) 2008 Erik Andrén
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * P/N 861037:      Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
+ * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
+ * P/N 861075-0040: Sensor HDCS1000        ASIC
+ * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
+ * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
+ */
+
+#ifndef STV06XX_PB0100_H_
+#define STV06XX_PB0100_H_
+
+#include "stv06xx_sensor.h"
+
+/* mode priv field flags */
+#define PB0100_CROP_TO_VGA     0x01
+#define PB0100_SUBSAMPLE       0x02
+
+/* I2C Registers */
+#define PB_IDENT               0x00    /* Chip Version */
+#define PB_RSTART              0x01    /* Row Window Start */
+#define PB_CSTART              0x02    /* Column Window Start */
+#define PB_RWSIZE              0x03    /* Row Window Size */
+#define PB_CWSIZE              0x04    /* Column  Window Size */
+#define PB_CFILLIN             0x05    /* Column Fill-In */
+#define PB_VBL                 0x06    /* Vertical Blank Count */
+#define PB_CONTROL             0x07    /* Control Mode */
+#define PB_FINTTIME            0x08    /* Integration Time/Frame Unit Count */
+#define PB_RINTTIME            0x09    /* Integration Time/Row Unit Count */
+#define PB_ROWSPEED            0x0a    /* Row Speed Control */
+#define PB_ABORTFRAME          0x0b    /* Abort Frame */
+#define PB_R12                 0x0c    /* Reserved */
+#define PB_RESET               0x0d    /* Reset */
+#define PB_EXPGAIN             0x0e    /* Exposure Gain Command */
+#define PB_R15                 0x0f    /* Expose0 */
+#define PB_R16                 0x10    /* Expose1 */
+#define PB_R17                 0x11    /* Expose2 */
+#define PB_R18                 0x12    /* Low0_DAC */
+#define PB_R19                 0x13    /* Low1_DAC */
+#define PB_R20                 0x14    /* Low2_DAC */
+#define PB_R21                 0x15    /* Threshold11 */
+#define PB_R22                 0x16    /* Threshold0x */
+#define PB_UPDATEINT           0x17    /* Update Interval */
+#define PB_R24                 0x18    /* High_DAC */
+#define PB_R25                 0x19    /* Trans0H */
+#define PB_R26                 0x1a    /* Trans1L */
+#define PB_R27                 0x1b    /* Trans1H */
+#define PB_R28                 0x1c    /* Trans2L */
+#define PB_R29                 0x1d    /* Reserved */
+#define PB_R30                 0x1e    /* Reserved */
+#define PB_R31                 0x1f    /* Wait to Read */
+#define PB_PREADCTRL           0x20    /* Pixel Read Control Mode */
+#define PB_R33                 0x21    /* IREF_VLN */
+#define PB_R34                 0x22    /* IREF_VLP */
+#define PB_R35                 0x23    /* IREF_VLN_INTEG */
+#define PB_R36                 0x24    /* IREF_MASTER */
+#define PB_R37                 0x25    /* IDACP */
+#define PB_R38                 0x26    /* IDACN */
+#define PB_R39                 0x27    /* DAC_Control_Reg */
+#define PB_R40                 0x28    /* VCL */
+#define PB_R41                 0x29    /* IREF_VLN_ADCIN */
+#define PB_R42                 0x2a    /* Reserved */
+#define PB_G1GAIN              0x2b    /* Green 1 Gain */
+#define PB_BGAIN               0x2c    /* Blue Gain */
+#define PB_RGAIN               0x2d    /* Red Gain */
+#define PB_G2GAIN              0x2e    /* Green 2 Gain */
+#define PB_R47                 0x2f    /* Dark Row Address */
+#define PB_R48                 0x30    /* Dark Row Options */
+#define PB_R49                 0x31    /* Reserved */
+#define PB_R50                 0x32    /* Image Test Data */
+#define PB_ADCMAXGAIN          0x33    /* Maximum Gain */
+#define PB_ADCMINGAIN          0x34    /* Minimum Gain */
+#define PB_ADCGLOBALGAIN       0x35    /* Global Gain */
+#define PB_R54                 0x36    /* Maximum Frame */
+#define PB_R55                 0x37    /* Minimum Frame */
+#define PB_R56                 0x38    /* Reserved */
+#define PB_VOFFSET             0x39    /* VOFFSET */
+#define PB_R58                 0x3a    /* Snap-Shot Sequence Trigger */
+#define PB_ADCGAINH            0x3b    /* VREF_HI */
+#define PB_ADCGAINL            0x3c    /* VREF_LO */
+#define PB_R61                 0x3d    /* Reserved */
+#define PB_R62                 0x3e    /* Reserved */
+#define PB_R63                 0x3f    /* Reserved */
+#define PB_R64                 0x40    /* Red/Blue Gain */
+#define PB_R65                 0x41    /* Green 2/Green 1 Gain */
+#define PB_R66                 0x42    /* VREF_HI/LO */
+#define PB_R67                 0x43    /* Integration Time/Row Unit Count */
+#define PB_R240                        0xf0    /* ADC Test */
+#define PB_R241                        0xf1    /* Chip Enable */
+#define PB_R242                        0xf2    /* Reserved */
+
+static int pb0100_probe(struct sd *sd);
+static int pb0100_start(struct sd *sd);
+static int pb0100_init(struct sd *sd);
+static int pb0100_init_controls(struct sd *sd);
+static int pb0100_stop(struct sd *sd);
+static int pb0100_dump(struct sd *sd);
+
+/* V4L2 controls supported by the driver */
+static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
+static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val);
+static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val);
+
+const struct stv06xx_sensor stv06xx_sensor_pb0100 = {
+       .name = "PB-0100",
+       .i2c_flush = 1,
+       .i2c_addr = 0xba,
+       .i2c_len = 2,
+
+       .min_packet_size = { 635, 847 },
+       .max_packet_size = { 847, 923 },
+
+       .init = pb0100_init,
+       .init_controls = pb0100_init_controls,
+       .probe = pb0100_probe,
+       .start = pb0100_start,
+       .stop = pb0100_stop,
+       .dump = pb0100_dump,
+};
+
+#endif
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/usb/gspca/stv06xx/stv06xx_sensor.h
new file mode 100644 (file)
index 0000000..3a498c2
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ * Copyright (c) 2008 Erik Andrén
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * P/N 861037:      Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
+ * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
+ * P/N 861075-0040: Sensor HDCS1000        ASIC
+ * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
+ * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
+ */
+
+#ifndef STV06XX_SENSOR_H_
+#define STV06XX_SENSOR_H_
+
+#include "stv06xx.h"
+
+#define IS_1020(sd)    ((sd)->sensor == &stv06xx_sensor_hdcs1020)
+
+extern const struct stv06xx_sensor stv06xx_sensor_vv6410;
+extern const struct stv06xx_sensor stv06xx_sensor_hdcs1x00;
+extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020;
+extern const struct stv06xx_sensor stv06xx_sensor_pb0100;
+extern const struct stv06xx_sensor stv06xx_sensor_st6422;
+
+struct stv06xx_sensor {
+       /* Defines the name of a sensor */
+       char name[32];
+
+       /* Sensor i2c address */
+       u8 i2c_addr;
+
+       /* Flush value*/
+       u8 i2c_flush;
+
+       /* length of an i2c word */
+       u8 i2c_len;
+
+       /* Isoc packet size (per mode) */
+       int min_packet_size[4];
+       int max_packet_size[4];
+
+       /* Probes if the sensor is connected */
+       int (*probe)(struct sd *sd);
+
+       /* Performs a initialization sequence */
+       int (*init)(struct sd *sd);
+
+       /* Initializes the controls */
+       int (*init_controls)(struct sd *sd);
+
+       /* Reads a sensor register */
+       int (*read_sensor)(struct sd *sd, const u8 address,
+             u8 *i2c_data, const u8 len);
+
+       /* Writes to a sensor register */
+       int (*write_sensor)(struct sd *sd, const u8 address,
+             u8 *i2c_data, const u8 len);
+
+       /* Instructs the sensor to start streaming */
+       int (*start)(struct sd *sd);
+
+       /* Instructs the sensor to stop streaming */
+       int (*stop)(struct sd *sd);
+
+       /* Instructs the sensor to dump all its contents */
+       int (*dump)(struct sd *sd);
+};
+
+#endif
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c
new file mode 100644 (file)
index 0000000..8a57990
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * Support for the sensor part which is integrated (I think) into the
+ * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
+ * but instead direct bridge writes.
+ *
+ * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Strongly based on qc-usb-messenger, which is:
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "stv06xx_st6422.h"
+
+static struct v4l2_pix_format st6422_mode[] = {
+       /* Note we actually get 124 lines of data, of which we skip the 4st
+          4 as they are garbage */
+       {
+               162,
+               120,
+               V4L2_PIX_FMT_SGRBG8,
+               V4L2_FIELD_NONE,
+               .sizeimage = 162 * 120,
+               .bytesperline = 162,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1
+       },
+       /* Note we actually get 248 lines of data, of which we skip the 4st
+          4 as they are garbage, and we tell the app it only gets the
+          first 240 of the 244 lines it actually gets, so that it ignores
+          the last 4. */
+       {
+               324,
+               240,
+               V4L2_PIX_FMT_SGRBG8,
+               V4L2_FIELD_NONE,
+               .sizeimage = 324 * 244,
+               .bytesperline = 324,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0
+       },
+};
+
+/* V4L2 controls supported by the driver */
+static int setbrightness(struct sd *sd, s32 val);
+static int setcontrast(struct sd *sd, s32 val);
+static int setgain(struct sd *sd, u8 gain);
+static int setexposure(struct sd *sd, s16 expo);
+
+static int st6422_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;
+       int err = -EINVAL;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               err = setbrightness(sd, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               err = setcontrast(sd, ctrl->val);
+               break;
+       case V4L2_CID_GAIN:
+               err = setgain(sd, ctrl->val);
+               break;
+       case V4L2_CID_EXPOSURE:
+               err = setexposure(sd, ctrl->val);
+               break;
+       }
+
+       /* commit settings */
+       if (err >= 0)
+               err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+       sd->gspca_dev.usb_err = err;
+       return err;
+}
+
+static const struct v4l2_ctrl_ops st6422_ctrl_ops = {
+       .s_ctrl = st6422_s_ctrl,
+};
+
+static int st6422_init_controls(struct sd *sd)
+{
+       struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
+
+       v4l2_ctrl_handler_init(hdl, 4);
+       v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 31, 1, 3);
+       v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 15, 1, 11);
+       v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0, 1023, 1, 256);
+       v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 255, 1, 64);
+
+       return hdl->error;
+}
+
+static int st6422_probe(struct sd *sd)
+{
+       if (sd->bridge != BRIDGE_ST6422)
+               return -ENODEV;
+
+       pr_info("st6422 sensor detected\n");
+
+       sd->gspca_dev.cam.cam_mode = st6422_mode;
+       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
+       return 0;
+}
+
+static int st6422_init(struct sd *sd)
+{
+       int err = 0, i;
+
+       const u16 st6422_bridge_init[][2] = {
+               { STV_ISO_ENABLE, 0x00 }, /* disable capture */
+               { 0x1436, 0x00 },
+               { 0x1432, 0x03 },       /* 0x00-0x1F brightness */
+               { 0x143a, 0xf9 },       /* 0x00-0x0F contrast */
+               { 0x0509, 0x38 },       /* R */
+               { 0x050a, 0x38 },       /* G */
+               { 0x050b, 0x38 },       /* B */
+               { 0x050c, 0x2a },
+               { 0x050d, 0x01 },
+
+
+               { 0x1431, 0x00 },       /* 0x00-0x07 ??? */
+               { 0x1433, 0x34 },       /* 160x120, 0x00-0x01 night filter */
+               { 0x1438, 0x18 },       /* 640x480 */
+/* 18 bayes */
+/* 10 compressed? */
+
+               { 0x1439, 0x00 },
+/* anti-noise?  0xa2 gives a perfect image */
+
+               { 0x143b, 0x05 },
+               { 0x143c, 0x00 },       /* 0x00-0x01 - ??? */
+
+
+/* shutter time 0x0000-0x03FF */
+/* low value  give good picures on moving objects (but requires much light) */
+/* high value gives good picures in darkness (but tends to be overexposed) */
+               { 0x143e, 0x01 },
+               { 0x143d, 0x00 },
+
+               { 0x1442, 0xe2 },
+/* write: 1x1x xxxx */
+/* read:  1x1x xxxx */
+/*        bit 5 == button pressed and hold if 0 */
+/* write 0xe2,0xea */
+
+/* 0x144a */
+/* 0x00 init */
+/* bit 7 == button has been pressed, but not handled */
+
+/* interrupt */
+/* if(urb->iso_frame_desc[i].status == 0x80) { */
+/* if(urb->iso_frame_desc[i].status == 0x88) { */
+
+               { 0x1500, 0xd0 },
+               { 0x1500, 0xd0 },
+               { 0x1500, 0x50 },       /* 0x00 - 0xFF  0x80 == compr ? */
+
+               { 0x1501, 0xaf },
+/* high val-> light area gets darker */
+/* low val -> light area gets lighter */
+               { 0x1502, 0xc2 },
+/* high val-> light area gets darker */
+/* low val -> light area gets lighter */
+               { 0x1503, 0x45 },
+/* high val-> light area gets darker */
+/* low val -> light area gets lighter */
+               { 0x1505, 0x02 },
+/* 2  : 324x248  80352 bytes */
+/* 7  : 248x162  40176 bytes */
+/* c+f: 162*124  20088 bytes */
+
+               { 0x150e, 0x8e },
+               { 0x150f, 0x37 },
+               { 0x15c0, 0x00 },
+               { 0x15c3, 0x08 },       /* 0x04/0x14 ... test pictures ??? */
+
+
+               { 0x143f, 0x01 },       /* commit settings */
+
+       };
+
+       for (i = 0; i < ARRAY_SIZE(st6422_bridge_init) && !err; i++) {
+               err = stv06xx_write_bridge(sd, st6422_bridge_init[i][0],
+                                              st6422_bridge_init[i][1]);
+       }
+
+       return err;
+}
+
+static int setbrightness(struct sd *sd, s32 val)
+{
+       /* val goes from 0 -> 31 */
+       return stv06xx_write_bridge(sd, 0x1432, val);
+}
+
+static int setcontrast(struct sd *sd, s32 val)
+{
+       /* Val goes from 0 -> 15 */
+       return stv06xx_write_bridge(sd, 0x143a, val | 0xf0);
+}
+
+static int setgain(struct sd *sd, u8 gain)
+{
+       int err;
+
+       /* Set red, green, blue, gain */
+       err = stv06xx_write_bridge(sd, 0x0509, gain);
+       if (err < 0)
+               return err;
+
+       err = stv06xx_write_bridge(sd, 0x050a, gain);
+       if (err < 0)
+               return err;
+
+       err = stv06xx_write_bridge(sd, 0x050b, gain);
+       if (err < 0)
+               return err;
+
+       /* 2 mystery writes */
+       err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
+       if (err < 0)
+               return err;
+
+       return stv06xx_write_bridge(sd, 0x050d, 0x01);
+}
+
+static int setexposure(struct sd *sd, s16 expo)
+{
+       int err;
+
+       err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff);
+       if (err < 0)
+               return err;
+
+       return stv06xx_write_bridge(sd, 0x143e, expo >> 8);
+}
+
+static int st6422_start(struct sd *sd)
+{
+       int err;
+       struct cam *cam = &sd->gspca_dev.cam;
+
+       if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
+               err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
+       else
+               err = stv06xx_write_bridge(sd, 0x1505, 0x02);
+       if (err < 0)
+               return err;
+
+       /* commit settings */
+       err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+       return (err < 0) ? err : 0;
+}
+
+static int st6422_stop(struct sd *sd)
+{
+       PDEBUG(D_STREAM, "Halting stream");
+
+       return 0;
+}
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/usb/gspca/stv06xx/stv06xx_st6422.h
new file mode 100644 (file)
index 0000000..8f20fbf
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Support for the sensor part which is integrated (I think) into the
+ * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
+ * but instead direct bridge writes.
+ *
+ * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Strongly based on qc-usb-messenger, which is:
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef STV06XX_ST6422_H_
+#define STV06XX_ST6422_H_
+
+#include "stv06xx_sensor.h"
+
+static int st6422_probe(struct sd *sd);
+static int st6422_start(struct sd *sd);
+static int st6422_init(struct sd *sd);
+static int st6422_init_controls(struct sd *sd);
+static int st6422_stop(struct sd *sd);
+
+const struct stv06xx_sensor stv06xx_sensor_st6422 = {
+       .name = "ST6422",
+       /* No known way to lower framerate in case of less bandwidth */
+       .min_packet_size = { 300, 847 },
+       .max_packet_size = { 300, 847 },
+       .init = st6422_init,
+       .init_controls = st6422_init_controls,
+       .probe = st6422_probe,
+       .start = st6422_start,
+       .stop = st6422_stop,
+};
+
+#endif
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c
new file mode 100644 (file)
index 0000000..748e142
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ * Copyright (c) 2008 Erik Andrén
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * P/N 861037:      Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
+ * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
+ * P/N 861075-0040: Sensor HDCS1000        ASIC
+ * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
+ * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "stv06xx_vv6410.h"
+
+static struct v4l2_pix_format vv6410_mode[] = {
+       {
+               356,
+               292,
+               V4L2_PIX_FMT_SGRBG8,
+               V4L2_FIELD_NONE,
+               .sizeimage = 356 * 292,
+               .bytesperline = 356,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0
+       }
+};
+
+static int vv6410_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct gspca_dev *gspca_dev =
+               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+       int err = -EINVAL;
+
+       switch (ctrl->id) {
+       case V4L2_CID_HFLIP:
+               err = vv6410_set_hflip(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_VFLIP:
+               err = vv6410_set_vflip(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_GAIN:
+               err = vv6410_set_analog_gain(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_EXPOSURE:
+               err = vv6410_set_exposure(gspca_dev, ctrl->val);
+               break;
+       }
+       return err;
+}
+
+static const struct v4l2_ctrl_ops vv6410_ctrl_ops = {
+       .s_ctrl = vv6410_s_ctrl,
+};
+
+static int vv6410_probe(struct sd *sd)
+{
+       u16 data;
+       int err;
+
+       err = stv06xx_read_sensor(sd, VV6410_DEVICEH, &data);
+       if (err < 0)
+               return -ENODEV;
+
+       if (data != 0x19)
+               return -ENODEV;
+
+       pr_info("vv6410 sensor detected\n");
+
+       sd->gspca_dev.cam.cam_mode = vv6410_mode;
+       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(vv6410_mode);
+       return 0;
+}
+
+static int vv6410_init_controls(struct sd *sd)
+{
+       struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
+
+       v4l2_ctrl_handler_init(hdl, 4);
+       v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0, 32768, 1, 20000);
+       v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 15, 1, 10);
+       return hdl->error;
+}
+
+static int vv6410_init(struct sd *sd)
+{
+       int err = 0, i;
+
+       for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++)
+               stv06xx_write_bridge(sd, stv_bridge_init[i].addr, stv_bridge_init[i].data);
+
+       if (err < 0)
+               return err;
+
+       err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init,
+                                        ARRAY_SIZE(vv6410_sensor_init));
+       return (err < 0) ? err : 0;
+}
+
+static int vv6410_start(struct sd *sd)
+{
+       int err;
+       struct cam *cam = &sd->gspca_dev.cam;
+       u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
+
+       if (priv & VV6410_SUBSAMPLE) {
+               PDEBUG(D_CONF, "Enabling subsampling");
+               stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02);
+               stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
+
+               stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
+       } else {
+               stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
+               stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
+               stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x00);
+
+       }
+
+       /* Turn on LED */
+       err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_ON);
+       if (err < 0)
+               return err;
+
+       err = stv06xx_write_sensor(sd, VV6410_SETUP0, 0);
+       if (err < 0)
+               return err;
+
+       PDEBUG(D_STREAM, "Starting stream");
+
+       return 0;
+}
+
+static int vv6410_stop(struct sd *sd)
+{
+       int err;
+
+       /* Turn off LED */
+       err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_OFF);
+       if (err < 0)
+               return err;
+
+       err = stv06xx_write_sensor(sd, VV6410_SETUP0, VV6410_LOW_POWER_MODE);
+       if (err < 0)
+               return err;
+
+       PDEBUG(D_STREAM, "Halting stream");
+
+       return (err < 0) ? err : 0;
+}
+
+static int vv6410_dump(struct sd *sd)
+{
+       u8 i;
+       int err = 0;
+
+       pr_info("Dumping all vv6410 sensor registers\n");
+       for (i = 0; i < 0xff && !err; i++) {
+               u16 data;
+               err = stv06xx_read_sensor(sd, i, &data);
+               pr_info("Register 0x%x contained 0x%x\n", i, data);
+       }
+       return (err < 0) ? err : 0;
+}
+
+static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u16 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
+       if (err < 0)
+               return err;
+
+       if (val)
+               i2c_data |= VV6410_HFLIP;
+       else
+               i2c_data &= ~VV6410_HFLIP;
+
+       PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
+       err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
+
+       return (err < 0) ? err : 0;
+}
+
+static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       u16 i2c_data;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
+       if (err < 0)
+               return err;
+
+       if (val)
+               i2c_data |= VV6410_VFLIP;
+       else
+               i2c_data &= ~VV6410_VFLIP;
+
+       PDEBUG(D_V4L2, "Set vertical flip to %d", val);
+       err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
+
+       return (err < 0) ? err : 0;
+}
+
+static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       PDEBUG(D_V4L2, "Set analog gain to %d", val);
+       err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf));
+
+       return (err < 0) ? err : 0;
+}
+
+static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+{
+       int err;
+       struct sd *sd = (struct sd *) gspca_dev;
+       unsigned int fine, coarse;
+
+       val = (val * val >> 14) + val / 4;
+
+       fine = val % VV6410_CIF_LINELENGTH;
+       coarse = min(512, val / VV6410_CIF_LINELENGTH);
+
+       PDEBUG(D_V4L2, "Set coarse exposure to %d, fine expsure to %d",
+              coarse, fine);
+
+       err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8);
+       if (err < 0)
+               goto out;
+
+       err = stv06xx_write_sensor(sd, VV6410_FINEL, fine & 0xff);
+       if (err < 0)
+               goto out;
+
+       err = stv06xx_write_sensor(sd, VV6410_COARSEH, coarse >> 8);
+       if (err < 0)
+               goto out;
+
+       err = stv06xx_write_sensor(sd, VV6410_COARSEL, coarse & 0xff);
+
+out:
+       return err;
+}
diff --git a/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.h
new file mode 100644 (file)
index 0000000..53e67b4
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
+ *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
+ * Copyright (c) 2002, 2003 Tuukka Toivonen
+ * Copyright (c) 2008 Erik Andrén
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * P/N 861037:      Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
+ * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
+ * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
+ * P/N 861075-0040: Sensor HDCS1000        ASIC
+ * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
+ * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
+ */
+
+#ifndef STV06XX_VV6410_H_
+#define STV06XX_VV6410_H_
+
+#include "stv06xx_sensor.h"
+
+#define VV6410_COLS                    416
+#define VV6410_ROWS                    320
+
+/* Status registers */
+/* Chip identification number including revision indicator */
+#define VV6410_DEVICEH                 0x00
+#define VV6410_DEVICEL                 0x01
+
+/* User can determine whether timed I2C data
+   has been consumed by interrogating flag states */
+#define VV6410_STATUS0                 0x02
+
+/* Current line counter value */
+#define VV6410_LINECOUNTH              0x03
+#define VV6410_LINECOUNTL              0x04
+
+/* End x coordinate of image size */
+#define VV6410_XENDH                   0x05
+#define VV6410_XENDL                   0x06
+
+/* End y coordinate of image size */
+#define VV6410_YENDH                   0x07
+#define VV6410_YENDL                   0x08
+
+/* This is the average pixel value returned from the
+   dark line offset cancellation algorithm */
+#define VV6410_DARKAVGH                        0x09
+#define VV6410_DARKAVGL                        0x0a
+
+/* This is the average pixel value returned from the
+   black line offset cancellation algorithm  */
+#define VV6410_BLACKAVGH               0x0b
+#define VV6410_BLACKAVGL               0x0c
+
+/* Flags to indicate whether the x or y image coordinates have been clipped */
+#define VV6410_STATUS1                 0x0d
+
+/* Setup registers */
+
+/* Low-power/sleep modes & video timing */
+#define VV6410_SETUP0                  0x10
+
+/* Various parameters */
+#define VV6410_SETUP1                  0x11
+
+/* Contains pixel counter reset value used by external sync */
+#define VV6410_SYNCVALUE               0x12
+
+/* Frame grabbing modes (FST, LST and QCK) */
+#define VV6410_FGMODES                 0x14
+
+/* FST and QCK mapping modes. */
+#define VV6410_PINMAPPING              0x15
+
+/* Data resolution */
+#define VV6410_DATAFORMAT              0x16
+
+/* Output coding formats */
+#define VV6410_OPFORMAT                        0x17
+
+/* Various mode select bits */
+#define VV6410_MODESELECT              0x18
+
+/* Exposure registers */
+/* Fine exposure. */
+#define VV6410_FINEH                   0x20
+#define VV6410_FINEL                   0x21
+
+/* Coarse exposure */
+#define VV6410_COARSEH                 0x22
+#define VV6410_COARSEL                 0x23
+
+/* Analog gain setting */
+#define VV6410_ANALOGGAIN              0x24
+
+/* Clock division */
+#define VV6410_CLKDIV                  0x25
+
+/* Dark line offset cancellation value */
+#define VV6410_DARKOFFSETH             0x2c
+#define VV6410_DARKOFFSETL             0x2d
+
+/* Dark line offset cancellation enable */
+#define VV6410_DARKOFFSETSETUP         0x2e
+
+/* Video timing registers */
+/* Line Length (Pixel Clocks) */
+#define VV6410_LINELENGTHH             0x52
+#define VV6410_LINELENGTHL             0x53
+
+/* X-co-ordinate of top left corner of region of interest (x-offset) */
+#define VV6410_XOFFSETH                        0x57
+#define VV6410_XOFFSETL                        0x58
+
+/* Y-coordinate of top left corner of region of interest (y-offset) */
+#define VV6410_YOFFSETH                        0x59
+#define VV6410_YOFFSETL                        0x5a
+
+/* Field length (Lines) */
+#define VV6410_FIELDLENGTHH            0x61
+#define VV6410_FIELDLENGTHL            0x62
+
+/* System registers */
+/* Black offset cancellation default value */
+#define VV6410_BLACKOFFSETH            0x70
+#define VV6410_BLACKOFFSETL            0x71
+
+/* Black offset cancellation setup */
+#define VV6410_BLACKOFFSETSETUP                0x72
+
+/* Analog Control Register 0 */
+#define VV6410_CR0                     0x75
+
+/* Analog Control Register 1 */
+#define VV6410_CR1                     0x76
+
+/* ADC Setup Register */
+#define VV6410_AS0                     0x77
+
+/* Analog Test Register */
+#define VV6410_AT0                     0x78
+
+/* Audio Amplifier Setup Register */
+#define VV6410_AT1                     0x79
+
+#define VV6410_HFLIP                   (1 << 3)
+#define VV6410_VFLIP                   (1 << 4)
+
+#define VV6410_LOW_POWER_MODE          (1 << 0)
+#define VV6410_SOFT_RESET              (1 << 2)
+#define VV6410_PAL_25_FPS              (0 << 3)
+
+#define VV6410_CLK_DIV_2               (1 << 1)
+
+#define VV6410_FINE_EXPOSURE           320
+#define VV6410_COARSE_EXPOSURE         192
+#define VV6410_DEFAULT_GAIN            5
+
+#define VV6410_SUBSAMPLE               0x01
+#define VV6410_CROP_TO_QVGA            0x02
+
+#define VV6410_CIF_LINELENGTH          415
+
+static int vv6410_probe(struct sd *sd);
+static int vv6410_start(struct sd *sd);
+static int vv6410_init(struct sd *sd);
+static int vv6410_init_controls(struct sd *sd);
+static int vv6410_stop(struct sd *sd);
+static int vv6410_dump(struct sd *sd);
+
+/* V4L2 controls supported by the driver */
+static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
+static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
+static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val);
+static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
+
+const struct stv06xx_sensor stv06xx_sensor_vv6410 = {
+       .name = "ST VV6410",
+       .i2c_flush = 5,
+       .i2c_addr = 0x20,
+       .i2c_len = 1,
+       /* FIXME (see if we can lower packet_size-s, needs testing, and also
+          adjusting framerate when the bandwidth gets lower) */
+       .min_packet_size = { 1023 },
+       .max_packet_size = { 1023 },
+       .init = vv6410_init,
+       .init_controls = vv6410_init_controls,
+       .probe = vv6410_probe,
+       .start = vv6410_start,
+       .stop = vv6410_stop,
+       .dump = vv6410_dump,
+};
+
+/* If NULL, only single value to write, stored in len */
+struct stv_init {
+       u16 addr;
+       u8 data;
+};
+
+static const struct stv_init stv_bridge_init[] = {
+       /* This reg is written twice. Some kind of reset? */
+       {STV_RESET, 0x80},
+       {STV_RESET, 0x00},
+       {STV_SCAN_RATE, 0x00},
+       {STV_I2C_FLUSH, 0x04},
+       {STV_REG00, 0x0b},
+       {STV_REG01, 0xa7},
+       {STV_REG02, 0xb7},
+       {STV_REG03, 0x00},
+       {STV_REG04, 0x00},
+       {0x1536, 0x02},
+       {0x1537, 0x00},
+       {0x1538, 0x60},
+       {0x1539, 0x01},
+       {0x153a, 0x20},
+       {0x153b, 0x01},
+};
+
+static const u8 vv6410_sensor_init[][2] = {
+       /* Setup registers */
+       {VV6410_SETUP0, VV6410_SOFT_RESET},
+       {VV6410_SETUP0, VV6410_LOW_POWER_MODE},
+       /* Use shuffled read-out mode */
+       {VV6410_SETUP1, BIT(6)},
+       /* All modes to 1, FST, Fast QCK, Free running QCK, Free running LST, FST will qualify visible pixels */
+       {VV6410_FGMODES, BIT(6) | BIT(4) | BIT(2) | BIT(0)},
+       {VV6410_PINMAPPING, 0x00},
+       /* Pre-clock generator divide off */
+       {VV6410_DATAFORMAT, BIT(7) | BIT(0)},
+
+       {VV6410_CLKDIV, VV6410_CLK_DIV_2},
+
+       /* System registers */
+       /* Enable voltage doubler */
+       {VV6410_AS0, BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
+       {VV6410_AT0, 0x00},
+       /* Power up audio, differential */
+       {VV6410_AT1, BIT(4) | BIT(0)},
+};
+
+#endif
diff --git a/drivers/media/usb/gspca/sunplus.c b/drivers/media/usb/gspca/sunplus.c
new file mode 100644 (file)
index 0000000..9ccfcb1
--- /dev/null
@@ -0,0 +1,1085 @@
+/*
+ *             Sunplus spca504(abc) spca533 spca536 library
+ *             Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
+ *
+ * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "sunplus"
+
+#include "gspca.h"
+#include "jpeg.h"
+
+MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
+MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+#define QUALITY 85
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       bool autogain;
+
+       u8 bridge;
+#define BRIDGE_SPCA504 0
+#define BRIDGE_SPCA504B 1
+#define BRIDGE_SPCA504C 2
+#define BRIDGE_SPCA533 3
+#define BRIDGE_SPCA536 4
+       u8 subtype;
+#define AiptekMiniPenCam13 1
+#define LogitechClickSmart420 2
+#define LogitechClickSmart820 3
+#define MegapixV4 4
+#define MegaImageVI 5
+
+       u8 jpeg_hdr[JPEG_HDR_SZ];
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+};
+
+static const struct v4l2_pix_format custom_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2},
+       {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 464,
+               .sizeimage = 464 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+};
+
+static const struct v4l2_pix_format vga_mode2[] = {
+       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 4},
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 3},
+       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+};
+
+#define SPCA50X_OFFSET_DATA 10
+#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
+#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
+#define SPCA504_PCCAM600_OFFSET_MODE    5
+#define SPCA504_PCCAM600_OFFSET_DATA    14
+ /* Frame packet header offsets for the spca533 */
+#define SPCA533_OFFSET_DATA    16
+#define SPCA533_OFFSET_FRAMSEQ 15
+/* Frame packet header offsets for the spca536 */
+#define SPCA536_OFFSET_DATA    4
+#define SPCA536_OFFSET_FRAMSEQ 1
+
+struct cmd {
+       u8 req;
+       u16 val;
+       u16 idx;
+};
+
+/* Initialisation data for the Creative PC-CAM 600 */
+static const struct cmd spca504_pccam600_init_data[] = {
+/*     {0xa0, 0x0000, 0x0503},  * capture mode */
+       {0x00, 0x0000, 0x2000},
+       {0x00, 0x0013, 0x2301},
+       {0x00, 0x0003, 0x2000},
+       {0x00, 0x0001, 0x21ac},
+       {0x00, 0x0001, 0x21a6},
+       {0x00, 0x0000, 0x21a7}, /* brightness */
+       {0x00, 0x0020, 0x21a8}, /* contrast */
+       {0x00, 0x0001, 0x21ac}, /* sat/hue */
+       {0x00, 0x0000, 0x21ad}, /* hue */
+       {0x00, 0x001a, 0x21ae}, /* saturation */
+       {0x00, 0x0002, 0x21a3}, /* gamma */
+       {0x30, 0x0154, 0x0008},
+       {0x30, 0x0004, 0x0006},
+       {0x30, 0x0258, 0x0009},
+       {0x30, 0x0004, 0x0000},
+       {0x30, 0x0093, 0x0004},
+       {0x30, 0x0066, 0x0005},
+       {0x00, 0x0000, 0x2000},
+       {0x00, 0x0013, 0x2301},
+       {0x00, 0x0003, 0x2000},
+       {0x00, 0x0013, 0x2301},
+       {0x00, 0x0003, 0x2000},
+};
+
+/* Creative PC-CAM 600 specific open data, sent before using the
+ * generic initialisation data from spca504_open_data.
+ */
+static const struct cmd spca504_pccam600_open_data[] = {
+       {0x00, 0x0001, 0x2501},
+       {0x20, 0x0500, 0x0001}, /* snapshot mode */
+       {0x00, 0x0003, 0x2880},
+       {0x00, 0x0001, 0x2881},
+};
+
+/* Initialisation data for the logitech clicksmart 420 */
+static const struct cmd spca504A_clicksmart420_init_data[] = {
+/*     {0xa0, 0x0000, 0x0503},  * capture mode */
+       {0x00, 0x0000, 0x2000},
+       {0x00, 0x0013, 0x2301},
+       {0x00, 0x0003, 0x2000},
+       {0x00, 0x0001, 0x21ac},
+       {0x00, 0x0001, 0x21a6},
+       {0x00, 0x0000, 0x21a7}, /* brightness */
+       {0x00, 0x0020, 0x21a8}, /* contrast */
+       {0x00, 0x0001, 0x21ac}, /* sat/hue */
+       {0x00, 0x0000, 0x21ad}, /* hue */
+       {0x00, 0x001a, 0x21ae}, /* saturation */
+       {0x00, 0x0002, 0x21a3}, /* gamma */
+       {0x30, 0x0004, 0x000a},
+       {0xb0, 0x0001, 0x0000},
+
+       {0xa1, 0x0080, 0x0001},
+       {0x30, 0x0049, 0x0000},
+       {0x30, 0x0060, 0x0005},
+       {0x0c, 0x0004, 0x0000},
+       {0x00, 0x0000, 0x0000},
+       {0x00, 0x0000, 0x2000},
+       {0x00, 0x0013, 0x2301},
+       {0x00, 0x0003, 0x2000},
+};
+
+/* clicksmart 420 open data ? */
+static const struct cmd spca504A_clicksmart420_open_data[] = {
+       {0x00, 0x0001, 0x2501},
+       {0x20, 0x0502, 0x0000},
+       {0x06, 0x0000, 0x0000},
+       {0x00, 0x0004, 0x2880},
+       {0x00, 0x0001, 0x2881},
+
+       {0xa0, 0x0000, 0x0503},
+};
+
+static const u8 qtable_creative_pccam[2][64] = {
+       {                               /* Q-table Y-components */
+        0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
+        0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
+        0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
+        0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
+        0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
+        0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
+        0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
+        0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
+       {                               /* Q-table C-components */
+        0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
+};
+
+/* FIXME: This Q-table is identical to the Creative PC-CAM one,
+ *             except for one byte. Possibly a typo?
+ *             NWG: 18/05/2003.
+ */
+static const u8 qtable_spca504_default[2][64] = {
+       {                               /* Q-table Y-components */
+        0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
+        0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
+        0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
+        0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
+        0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
+        0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
+        0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
+        0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
+        },
+       {                               /* Q-table C-components */
+        0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
+        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
+};
+
+/* read <len> bytes to gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev,
+                 u8 req,
+                 u16 index,
+                 u16 len)
+{
+       int ret;
+
+#ifdef GSPCA_DEBUG
+       if (len > USB_BUF_SZ) {
+               pr_err("reg_r: buffer overflow\n");
+               return;
+       }
+#endif
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       req,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,              /* value */
+                       index,
+                       len ? gspca_dev->usb_buf : NULL, len,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_r err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+/* write one byte */
+static void reg_w_1(struct gspca_dev *gspca_dev,
+                  u8 req,
+                  u16 value,
+                  u16 index,
+                  u16 byte)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       gspca_dev->usb_buf[0] = byte;
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       req,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index,
+                       gspca_dev->usb_buf, 1,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_w_1 err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+/* write req / index / value */
+static void reg_w_riv(struct gspca_dev *gspca_dev,
+                    u8 req, u16 index, u16 value)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_control_msg(dev,
+                       usb_sndctrlpipe(dev, 0),
+                       req,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index, NULL, 0, 500);
+       if (ret < 0) {
+               pr_err("reg_w_riv err %d\n", ret);
+               gspca_dev->usb_err = ret;
+               return;
+       }
+       PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
+               req, index, value);
+}
+
+static void write_vector(struct gspca_dev *gspca_dev,
+                       const struct cmd *data, int ncmds)
+{
+       while (--ncmds >= 0) {
+               reg_w_riv(gspca_dev, data->req, data->idx, data->val);
+               data++;
+       }
+}
+
+static void setup_qtable(struct gspca_dev *gspca_dev,
+                       const u8 qtable[2][64])
+{
+       int i;
+
+       /* loop over y components */
+       for (i = 0; i < 64; i++)
+               reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
+
+       /* loop over c components */
+       for (i = 0; i < 64; i++)
+               reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
+}
+
+static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
+                            u8 req, u16 idx, u16 val)
+{
+       reg_w_riv(gspca_dev, req, idx, val);
+       reg_r(gspca_dev, 0x01, 0x0001, 1);
+       PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
+       reg_w_riv(gspca_dev, req, idx, val);
+
+       msleep(200);
+       reg_r(gspca_dev, 0x01, 0x0001, 1);
+       PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
+}
+
+#ifdef GSPCA_DEBUG
+static void spca504_read_info(struct gspca_dev *gspca_dev)
+{
+       int i;
+       u8 info[6];
+
+       for (i = 0; i < 6; i++) {
+               reg_r(gspca_dev, 0, i, 1);
+               info[i] = gspca_dev->usb_buf[0];
+       }
+       PDEBUG(D_STREAM,
+               "Read info: %d %d %d %d %d %d."
+               " Should be 1,0,2,2,0,0",
+               info[0], info[1], info[2],
+               info[3], info[4], info[5]);
+}
+#endif
+
+static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
+                       u8 req,
+                       u16 idx, u16 val, u8 endcode, u8 count)
+{
+       u16 status;
+
+       reg_w_riv(gspca_dev, req, idx, val);
+       reg_r(gspca_dev, 0x01, 0x0001, 1);
+       if (gspca_dev->usb_err < 0)
+               return;
+       PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
+                       gspca_dev->usb_buf[0], endcode);
+       if (!count)
+               return;
+       count = 200;
+       while (--count > 0) {
+               msleep(10);
+               /* gsmart mini2 write a each wait setting 1 ms is enough */
+/*             reg_w_riv(gspca_dev, req, idx, val); */
+               reg_r(gspca_dev, 0x01, 0x0001, 1);
+               status = gspca_dev->usb_buf[0];
+               if (status == endcode) {
+                       PDEBUG(D_FRAM, "status 0x%04x after wait %d",
+                               status, 200 - count);
+                               break;
+               }
+       }
+}
+
+static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
+{
+       int count = 10;
+
+       while (--count > 0) {
+               reg_r(gspca_dev, 0x21, 0, 1);
+               if ((gspca_dev->usb_buf[0] & 0x01) == 0)
+                       break;
+               msleep(10);
+       }
+}
+
+static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
+{
+       int count = 50;
+
+       while (--count > 0) {
+               reg_r(gspca_dev, 0x21, 1, 1);
+               if (gspca_dev->usb_buf[0] != 0) {
+                       reg_w_1(gspca_dev, 0x21, 0, 1, 0);
+                       reg_r(gspca_dev, 0x21, 1, 1);
+                       spca504B_PollingDataReady(gspca_dev);
+                       break;
+               }
+               msleep(10);
+       }
+}
+
+#ifdef GSPCA_DEBUG
+static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
+{
+       u8 *data;
+
+       data = gspca_dev->usb_buf;
+       reg_r(gspca_dev, 0x20, 0, 5);
+       PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
+               data[0], data[1], data[2], data[3], data[4]);
+       reg_r(gspca_dev, 0x23, 0, 64);
+       reg_r(gspca_dev, 0x23, 1, 64);
+}
+#endif
+
+static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 Size;
+
+       Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+       switch (sd->bridge) {
+       case BRIDGE_SPCA533:
+               reg_w_riv(gspca_dev, 0x31, 0, 0);
+               spca504B_WaitCmdStatus(gspca_dev);
+               spca504B_PollingDataReady(gspca_dev);
+#ifdef GSPCA_DEBUG
+               spca50x_GetFirmware(gspca_dev);
+#endif
+               reg_w_1(gspca_dev, 0x24, 0, 8, 2);              /* type */
+               reg_r(gspca_dev, 0x24, 8, 1);
+
+               reg_w_1(gspca_dev, 0x25, 0, 4, Size);
+               reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
+               spca504B_PollingDataReady(gspca_dev);
+
+               /* Init the cam width height with some values get on init ? */
+               reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
+               spca504B_WaitCmdStatus(gspca_dev);
+               spca504B_PollingDataReady(gspca_dev);
+               break;
+       default:
+/* case BRIDGE_SPCA504B: */
+/* case BRIDGE_SPCA536: */
+               reg_w_1(gspca_dev, 0x25, 0, 4, Size);
+               reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
+               reg_w_1(gspca_dev, 0x27, 0, 0, 6);
+               reg_r(gspca_dev, 0x27, 0, 1);                   /* type */
+               spca504B_PollingDataReady(gspca_dev);
+               break;
+       case BRIDGE_SPCA504:
+               Size += 3;
+               if (sd->subtype == AiptekMiniPenCam13) {
+                       /* spca504a aiptek */
+                       spca504A_acknowledged_command(gspca_dev,
+                                               0x08, Size, 0,
+                                               0x80 | (Size & 0x0f), 1);
+                       spca504A_acknowledged_command(gspca_dev,
+                                                       1, 3, 0, 0x9f, 0);
+               } else {
+                       spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
+               }
+               break;
+       case BRIDGE_SPCA504C:
+               /* capture mode */
+               reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
+               reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
+               break;
+       }
+}
+
+static void spca504_wait_status(struct gspca_dev *gspca_dev)
+{
+       int cnt;
+
+       cnt = 256;
+       while (--cnt > 0) {
+               /* With this we get the status, when return 0 it's all ok */
+               reg_r(gspca_dev, 0x06, 0x00, 1);
+               if (gspca_dev->usb_buf[0] == 0)
+                       return;
+               msleep(10);
+       }
+}
+
+static void spca504B_setQtable(struct gspca_dev *gspca_dev)
+{
+       reg_w_1(gspca_dev, 0x26, 0, 0, 3);
+       reg_r(gspca_dev, 0x26, 0, 1);
+       spca504B_PollingDataReady(gspca_dev);
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u16 reg;
+
+       reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
+       reg_w_riv(gspca_dev, 0x00, reg, val);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u16 reg;
+
+       reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
+       reg_w_riv(gspca_dev, 0x00, reg, val);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u16 reg;
+
+       reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
+       reg_w_riv(gspca_dev, 0x00, reg, val);
+}
+
+static void init_ctl_reg(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int pollreg = 1;
+
+       switch (sd->bridge) {
+       case BRIDGE_SPCA504:
+       case BRIDGE_SPCA504C:
+               pollreg = 0;
+               /* fall thru */
+       default:
+/*     case BRIDGE_SPCA533: */
+/*     case BRIDGE_SPCA504B: */
+               reg_w_riv(gspca_dev, 0, 0x21ad, 0x00);  /* hue */
+               reg_w_riv(gspca_dev, 0, 0x21ac, 0x01);  /* sat/hue */
+               reg_w_riv(gspca_dev, 0, 0x21a3, 0x00);  /* gamma */
+               break;
+       case BRIDGE_SPCA536:
+               reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
+               reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
+               reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
+               break;
+       }
+       if (pollreg)
+               spca504B_PollingDataReady(gspca_dev);
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+
+       cam = &gspca_dev->cam;
+
+       sd->bridge = id->driver_info >> 8;
+       sd->subtype = id->driver_info;
+
+       if (sd->subtype == AiptekMiniPenCam13) {
+
+               /* try to get the firmware as some cam answer 2.0.1.2.2
+                * and should be a spca504b then overwrite that setting */
+               reg_r(gspca_dev, 0x20, 0, 1);
+               switch (gspca_dev->usb_buf[0]) {
+               case 1:
+                       break;          /* (right bridge/subtype) */
+               case 2:
+                       sd->bridge = BRIDGE_SPCA504B;
+                       sd->subtype = 0;
+                       break;
+               default:
+                       return -ENODEV;
+               }
+       }
+
+       switch (sd->bridge) {
+       default:
+/*     case BRIDGE_SPCA504B: */
+/*     case BRIDGE_SPCA504: */
+/*     case BRIDGE_SPCA536: */
+               cam->cam_mode = vga_mode;
+               cam->nmodes = ARRAY_SIZE(vga_mode);
+               break;
+       case BRIDGE_SPCA533:
+               cam->cam_mode = custom_mode;
+               if (sd->subtype == MegaImageVI)         /* 320x240 only */
+                       cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
+               else
+                       cam->nmodes = ARRAY_SIZE(custom_mode);
+               break;
+       case BRIDGE_SPCA504C:
+               cam->cam_mode = vga_mode2;
+               cam->nmodes = ARRAY_SIZE(vga_mode2);
+               break;
+       }
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->bridge) {
+       case BRIDGE_SPCA504B:
+               reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
+               reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
+               reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
+               reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
+               reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
+               reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
+               /* fall thru */
+       case BRIDGE_SPCA533:
+               spca504B_PollingDataReady(gspca_dev);
+#ifdef GSPCA_DEBUG
+               spca50x_GetFirmware(gspca_dev);
+#endif
+               break;
+       case BRIDGE_SPCA536:
+#ifdef GSPCA_DEBUG
+               spca50x_GetFirmware(gspca_dev);
+#endif
+               reg_r(gspca_dev, 0x00, 0x5002, 1);
+               reg_w_1(gspca_dev, 0x24, 0, 0, 0);
+               reg_r(gspca_dev, 0x24, 0, 1);
+               spca504B_PollingDataReady(gspca_dev);
+               reg_w_riv(gspca_dev, 0x34, 0, 0);
+               spca504B_WaitCmdStatus(gspca_dev);
+               break;
+       case BRIDGE_SPCA504C:   /* pccam600 */
+               PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
+               reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
+               reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001);     /* reset */
+               spca504_wait_status(gspca_dev);
+               if (sd->subtype == LogitechClickSmart420)
+                       write_vector(gspca_dev,
+                               spca504A_clicksmart420_open_data,
+                               ARRAY_SIZE(spca504A_clicksmart420_open_data));
+               else
+                       write_vector(gspca_dev, spca504_pccam600_open_data,
+                               ARRAY_SIZE(spca504_pccam600_open_data));
+               setup_qtable(gspca_dev, qtable_creative_pccam);
+               break;
+       default:
+/*     case BRIDGE_SPCA504: */
+               PDEBUG(D_STREAM, "Opening SPCA504");
+               if (sd->subtype == AiptekMiniPenCam13) {
+#ifdef GSPCA_DEBUG
+                       spca504_read_info(gspca_dev);
+#endif
+
+                       /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
+                       spca504A_acknowledged_command(gspca_dev, 0x24,
+                                                       8, 3, 0x9e, 1);
+                       /* Twice sequential need status 0xff->0x9e->0x9d */
+                       spca504A_acknowledged_command(gspca_dev, 0x24,
+                                                       8, 3, 0x9e, 0);
+
+                       spca504A_acknowledged_command(gspca_dev, 0x24,
+                                                       0, 0, 0x9d, 1);
+                       /******************************/
+                       /* spca504a aiptek */
+                       spca504A_acknowledged_command(gspca_dev, 0x08,
+                                                       6, 0, 0x86, 1);
+/*                     reg_write (dev, 0, 0x2000, 0); */
+/*                     reg_write (dev, 0, 0x2883, 1); */
+/*                     spca504A_acknowledged_command (gspca_dev, 0x08,
+                                                       6, 0, 0x86, 1); */
+/*                     spca504A_acknowledged_command (gspca_dev, 0x24,
+                                                       0, 0, 0x9D, 1); */
+                       reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
+                                                       /* L92 sno1t.txt */
+                       reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
+                       spca504A_acknowledged_command(gspca_dev, 0x01,
+                                                       0x0f, 0, 0xff, 0);
+               }
+               /* setup qtable */
+               reg_w_riv(gspca_dev, 0, 0x2000, 0);
+               reg_w_riv(gspca_dev, 0, 0x2883, 1);
+               setup_qtable(gspca_dev, qtable_spca504_default);
+               break;
+       }
+       return gspca_dev->usb_err;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int enable;
+
+       /* create the JPEG header */
+       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+                       0x22);          /* JPEG 411 */
+       jpeg_set_qual(sd->jpeg_hdr, QUALITY);
+
+       if (sd->bridge == BRIDGE_SPCA504B)
+               spca504B_setQtable(gspca_dev);
+       spca504B_SetSizeType(gspca_dev);
+       switch (sd->bridge) {
+       default:
+/*     case BRIDGE_SPCA504B: */
+/*     case BRIDGE_SPCA533: */
+/*     case BRIDGE_SPCA536: */
+               switch (sd->subtype) {
+               case MegapixV4:
+               case LogitechClickSmart820:
+               case MegaImageVI:
+                       reg_w_riv(gspca_dev, 0xf0, 0, 0);
+                       spca504B_WaitCmdStatus(gspca_dev);
+                       reg_r(gspca_dev, 0xf0, 4, 0);
+                       spca504B_WaitCmdStatus(gspca_dev);
+                       break;
+               default:
+                       reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
+                       spca504B_WaitCmdStatus(gspca_dev);
+                       spca504B_PollingDataReady(gspca_dev);
+                       break;
+               }
+               break;
+       case BRIDGE_SPCA504:
+               if (sd->subtype == AiptekMiniPenCam13) {
+#ifdef GSPCA_DEBUG
+                       spca504_read_info(gspca_dev);
+#endif
+
+                       /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
+                       spca504A_acknowledged_command(gspca_dev, 0x24,
+                                                       8, 3, 0x9e, 1);
+                       /* Twice sequential need status 0xff->0x9e->0x9d */
+                       spca504A_acknowledged_command(gspca_dev, 0x24,
+                                                       8, 3, 0x9e, 0);
+                       spca504A_acknowledged_command(gspca_dev, 0x24,
+                                                       0, 0, 0x9d, 1);
+               } else {
+                       spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
+#ifdef GSPCA_DEBUG
+                       spca504_read_info(gspca_dev);
+#endif
+                       spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
+                       spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
+               }
+               spca504B_SetSizeType(gspca_dev);
+               reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
+                                                       /* L92 sno1t.txt */
+               reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
+               break;
+       case BRIDGE_SPCA504C:
+               if (sd->subtype == LogitechClickSmart420) {
+                       write_vector(gspca_dev,
+                               spca504A_clicksmart420_init_data,
+                               ARRAY_SIZE(spca504A_clicksmart420_init_data));
+               } else {
+                       write_vector(gspca_dev, spca504_pccam600_init_data,
+                               ARRAY_SIZE(spca504_pccam600_init_data));
+               }
+               enable = (sd->autogain ? 0x04 : 0x01);
+               reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
+                                                       /* auto exposure */
+               reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
+                                                       /* auto whiteness */
+
+               /* set default exposure compensation and whiteness balance */
+               reg_w_riv(gspca_dev, 0x30, 0x0001, 800);        /* ~ 20 fps */
+               reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
+               spca504B_SetSizeType(gspca_dev);
+               break;
+       }
+       init_ctl_reg(gspca_dev);
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->bridge) {
+       default:
+/*     case BRIDGE_SPCA533: */
+/*     case BRIDGE_SPCA536: */
+/*     case BRIDGE_SPCA504B: */
+               reg_w_riv(gspca_dev, 0x31, 0, 0);
+               spca504B_WaitCmdStatus(gspca_dev);
+               spca504B_PollingDataReady(gspca_dev);
+               break;
+       case BRIDGE_SPCA504:
+       case BRIDGE_SPCA504C:
+               reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
+
+               if (sd->subtype == AiptekMiniPenCam13) {
+                       /* spca504a aiptek */
+/*                     spca504A_acknowledged_command(gspca_dev, 0x08,
+                                                        6, 0, 0x86, 1); */
+                       spca504A_acknowledged_command(gspca_dev, 0x24,
+                                                       0x00, 0x00, 0x9d, 1);
+                       spca504A_acknowledged_command(gspca_dev, 0x01,
+                                                       0x0f, 0x00, 0xff, 1);
+               } else {
+                       spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
+                       reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
+               }
+               break;
+       }
+}
+
+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;
+       int i, sof = 0;
+       static u8 ffd9[] = {0xff, 0xd9};
+
+/* frames are jpeg 4.1.1 without 0xff escape */
+       switch (sd->bridge) {
+       case BRIDGE_SPCA533:
+               if (data[0] == 0xff) {
+                       if (data[1] != 0x01) {  /* drop packet */
+/*                             gspca_dev->last_packet_type = DISCARD_PACKET; */
+                               return;
+                       }
+                       sof = 1;
+                       data += SPCA533_OFFSET_DATA;
+                       len -= SPCA533_OFFSET_DATA;
+               } else {
+                       data += 1;
+                       len -= 1;
+               }
+               break;
+       case BRIDGE_SPCA536:
+               if (data[0] == 0xff) {
+                       sof = 1;
+                       data += SPCA536_OFFSET_DATA;
+                       len -= SPCA536_OFFSET_DATA;
+               } else {
+                       data += 2;
+                       len -= 2;
+               }
+               break;
+       default:
+/*     case BRIDGE_SPCA504: */
+/*     case BRIDGE_SPCA504B: */
+               switch (data[0]) {
+               case 0xfe:                      /* start of frame */
+                       sof = 1;
+                       data += SPCA50X_OFFSET_DATA;
+                       len -= SPCA50X_OFFSET_DATA;
+                       break;
+               case 0xff:                      /* drop packet */
+/*                     gspca_dev->last_packet_type = DISCARD_PACKET; */
+                       return;
+               default:
+                       data += 1;
+                       len -= 1;
+                       break;
+               }
+               break;
+       case BRIDGE_SPCA504C:
+               switch (data[0]) {
+               case 0xfe:                      /* start of frame */
+                       sof = 1;
+                       data += SPCA504_PCCAM600_OFFSET_DATA;
+                       len -= SPCA504_PCCAM600_OFFSET_DATA;
+                       break;
+               case 0xff:                      /* drop packet */
+/*                     gspca_dev->last_packet_type = DISCARD_PACKET; */
+                       return;
+               default:
+                       data += 1;
+                       len -= 1;
+                       break;
+               }
+               break;
+       }
+       if (sof) {              /* start of frame */
+               gspca_frame_add(gspca_dev, LAST_PACKET,
+                               ffd9, 2);
+
+               /* put the JPEG header in the new frame */
+               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                       sd->jpeg_hdr, JPEG_HDR_SZ);
+       }
+
+       /* add 0x00 after 0xff */
+       i = 0;
+       do {
+               if (data[i] == 0xff) {
+                       gspca_frame_add(gspca_dev, INTER_PACKET,
+                                       data, i + 1);
+                       len -= i;
+                       data += i;
+                       *data = 0x00;
+                       i = 0;
+               }
+               i++;
+       } while (i < len);
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+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_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               setcolors(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               sd->autogain = ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 4);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+
+       if (hdl->error) {
+               pr_err("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,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+#define BS(bridge, subtype) \
+       .driver_info = (BRIDGE_ ## bridge << 8) \
+                       | (subtype)
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
+       {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
+       {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
+       {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
+       {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
+       {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
+       {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
+       {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
+       {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
+       {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
+       {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
+       {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
+       {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
+       {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
+       {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
+       {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
+       {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
+       {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
+       {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
+       {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
+       {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
+       {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
+       {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
+       {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
+       {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
+       {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
+       {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
+       {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
+       {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
+       {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
+       {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
+       {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
+       {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
+       {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
+       {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
+       {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
+       {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
+       {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
+       {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
+       {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
+       {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
+       {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
+       {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
+       {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
+       {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
+       {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
+       {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/t613.c b/drivers/media/usb/gspca/t613.c
new file mode 100644 (file)
index 0000000..8bc6c3c
--- /dev/null
@@ -0,0 +1,1054 @@
+/*
+ * T613 subdriver
+ *
+ * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *Notes: * t613  + tas5130A
+ *     * Focus to light do not balance well as in win.
+ *       Quality in win is not good, but its kinda better.
+ *      * Fix some "extraneous bytes", most of apps will show the image anyway
+ *      * Gamma table, is there, but its really doing something?
+ *      * 7~8 Fps, its ok, max on win its 10.
+ *                     Costantino Leandro
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "t613"
+
+#include <linux/input.h>
+#include <linux/slab.h>
+#include "gspca.h"
+
+MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
+MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+       struct v4l2_ctrl *freq;
+       struct { /* awb / color gains control cluster */
+               struct v4l2_ctrl *awb;
+               struct v4l2_ctrl *gain;
+               struct v4l2_ctrl *red_balance;
+               struct v4l2_ctrl *blue_balance;
+       };
+
+       u8 sensor;
+       u8 button_pressed;
+};
+enum sensors {
+       SENSOR_OM6802,
+       SENSOR_OTHER,
+       SENSOR_TAS5130A,
+       SENSOR_LT168G,          /* must verify if this is the actual model */
+};
+
+static const struct v4l2_pix_format vga_mode_t16[] = {
+       {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 4 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 4},
+#if 0 /* HDG: broken with my test cam, so lets disable it */
+       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 3},
+#endif
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2},
+#if 0 /* HDG: broken with my test cam, so lets disable it */
+       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+#endif
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+
+/* sensor specific data */
+struct additional_sensor_data {
+       const u8 n3[6];
+       const u8 *n4, n4sz;
+       const u8 reg80, reg8e;
+       const u8 nset8[6];
+       const u8 data1[10];
+       const u8 data2[9];
+       const u8 data3[9];
+       const u8 data5[6];
+       const u8 stream[4];
+};
+
+static const u8 n4_om6802[] = {
+       0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
+       0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
+       0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
+       0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
+       0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
+       0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
+       0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
+       0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
+       0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
+};
+static const u8 n4_other[] = {
+       0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
+       0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
+       0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
+       0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
+       0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
+       0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
+       0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
+       0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
+};
+static const u8 n4_tas5130a[] = {
+       0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
+       0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
+       0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
+       0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
+       0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
+       0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
+       0xc6, 0xda
+};
+static const u8 n4_lt168g[] = {
+       0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
+       0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
+       0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
+       0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
+       0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
+       0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
+       0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
+       0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
+       0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
+};
+
+static const struct additional_sensor_data sensor_data[] = {
+[SENSOR_OM6802] = {
+       .n3 =
+               {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
+       .n4 = n4_om6802,
+       .n4sz = sizeof n4_om6802,
+       .reg80 = 0x3c,
+       .reg8e = 0x33,
+       .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
+       .data1 =
+               {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
+                0xb3, 0xfc},
+       .data2 =
+               {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
+                0xff},
+       .data3 =
+               {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
+                0xff},
+       .data5 =        /* this could be removed later */
+               {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
+       .stream =
+               {0x0b, 0x04, 0x0a, 0x78},
+    },
+[SENSOR_OTHER] = {
+       .n3 =
+               {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
+       .n4 = n4_other,
+       .n4sz = sizeof n4_other,
+       .reg80 = 0xac,
+       .reg8e = 0xb8,
+       .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
+       .data1 =
+               {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
+                0xe8, 0xfc},
+       .data2 =
+               {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
+                0xd9},
+       .data3 =
+               {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
+                0xd9},
+       .data5 =
+               {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
+       .stream =
+               {0x0b, 0x04, 0x0a, 0x00},
+    },
+[SENSOR_TAS5130A] = {
+       .n3 =
+               {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
+       .n4 = n4_tas5130a,
+       .n4sz = sizeof n4_tas5130a,
+       .reg80 = 0x3c,
+       .reg8e = 0xb4,
+       .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
+       .data1 =
+               {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
+                0xc8, 0xfc},
+       .data2 =
+               {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
+                0xe0},
+       .data3 =
+               {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
+                0xe0},
+       .data5 =
+               {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
+       .stream =
+               {0x0b, 0x04, 0x0a, 0x40},
+    },
+[SENSOR_LT168G] = {
+       .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
+       .n4 = n4_lt168g,
+       .n4sz = sizeof n4_lt168g,
+       .reg80 = 0x7c,
+       .reg8e = 0xb3,
+       .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
+       .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
+                0xb0, 0xf4},
+       .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
+                0xff},
+       .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
+                0xff},
+       .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
+       .stream = {0x0b, 0x04, 0x0a, 0x28},
+    },
+};
+
+#define MAX_EFFECTS 7
+static const u8 effects_table[MAX_EFFECTS][6] = {
+       {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00},   /* Normal */
+       {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04},   /* Repujar */
+       {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20},   /* Monochrome */
+       {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80},   /* Sepia */
+       {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02},   /* Croquis */
+       {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10},   /* Sun Effect */
+       {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40},   /* Negative */
+};
+
+#define GAMMA_MAX (15)
+static const u8 gamma_table[GAMMA_MAX+1][17] = {
+/* gamma table from cam1690.ini */
+       {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21,        /* 0 */
+        0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
+        0xff},
+       {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d,        /* 1 */
+        0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
+        0xff},
+       {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35,        /* 2 */
+        0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
+        0xff},
+       {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f,        /* 3 */
+        0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
+        0xff},
+       {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a,        /* 4 */
+        0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
+        0xff},
+       {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58,        /* 5 */
+        0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
+        0xff},
+       {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67,        /* 6 */
+        0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
+        0xff},
+       {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,        /* 7 */
+        0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
+        0xff},
+       {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79,        /* 8 */
+        0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
+        0xff},
+       {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84,        /* 9 */
+        0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
+        0xff},
+       {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e,        /* 10 */
+        0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
+        0xff},
+       {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b,        /* 11 */
+        0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
+        0xff},
+       {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8,        /* 12 */
+        0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
+        0xff},
+       {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7,        /* 13 */
+        0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
+        0xff},
+       {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6,        /* 14 */
+        0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
+        0xff},
+       {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8,        /* 15 */
+        0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
+        0xff}
+};
+
+static const u8 tas5130a_sensor_init[][8] = {
+       {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
+       {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
+       {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
+};
+
+static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
+
+/* read 1 byte */
+static u8 reg_r(struct gspca_dev *gspca_dev,
+                  u16 index)
+{
+       usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       0,              /* request */
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,              /* value */
+                       index,
+                       gspca_dev->usb_buf, 1, 500);
+       return gspca_dev->usb_buf[0];
+}
+
+static void reg_w(struct gspca_dev *gspca_dev,
+                 u16 index)
+{
+       usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0, index,
+                       NULL, 0, 500);
+}
+
+static void reg_w_buf(struct gspca_dev *gspca_dev,
+                 const u8 *buffer, u16 len)
+{
+       if (len <= USB_BUF_SZ) {
+               memcpy(gspca_dev->usb_buf, buffer, len);
+               usb_control_msg(gspca_dev->dev,
+                               usb_sndctrlpipe(gspca_dev->dev, 0),
+                               0,
+                          USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               0x01, 0,
+                               gspca_dev->usb_buf, len, 500);
+       } else {
+               u8 *tmpbuf;
+
+               tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
+               if (!tmpbuf) {
+                       pr_err("Out of memory\n");
+                       return;
+               }
+               usb_control_msg(gspca_dev->dev,
+                               usb_sndctrlpipe(gspca_dev->dev, 0),
+                               0,
+                          USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               0x01, 0,
+                               tmpbuf, len, 500);
+               kfree(tmpbuf);
+       }
+}
+
+/* write values to consecutive registers */
+static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
+                       u8 reg,
+                       const u8 *buffer, u16 len)
+{
+       int i;
+       u8 *p, *tmpbuf;
+
+       if (len * 2 <= USB_BUF_SZ) {
+               p = tmpbuf = gspca_dev->usb_buf;
+       } else {
+               p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
+               if (!tmpbuf) {
+                       pr_err("Out of memory\n");
+                       return;
+               }
+       }
+       i = len;
+       while (--i >= 0) {
+               *p++ = reg++;
+               *p++ = *buffer++;
+       }
+       usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0x01, 0,
+                       tmpbuf, len * 2, 500);
+       if (len * 2 > USB_BUF_SZ)
+               kfree(tmpbuf);
+}
+
+static void om6802_sensor_init(struct gspca_dev *gspca_dev)
+{
+       int i;
+       const u8 *p;
+       u8 byte;
+       u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
+       static const u8 sensor_init[] = {
+               0xdf, 0x6d,
+               0xdd, 0x18,
+               0x5a, 0xe0,
+               0x5c, 0x07,
+               0x5d, 0xb0,
+               0x5e, 0x1e,
+               0x60, 0x71,
+               0xef, 0x00,
+               0xe9, 0x00,
+               0xea, 0x00,
+               0x90, 0x24,
+               0x91, 0xb2,
+               0x82, 0x32,
+               0xfd, 0x41,
+               0x00                    /* table end */
+       };
+
+       reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
+       msleep(100);
+       i = 4;
+       while (--i > 0) {
+               byte = reg_r(gspca_dev, 0x0060);
+               if (!(byte & 0x01))
+                       break;
+               msleep(100);
+       }
+       byte = reg_r(gspca_dev, 0x0063);
+       if (byte != 0x17) {
+               pr_err("Bad sensor reset %02x\n", byte);
+               /* continue? */
+       }
+
+       p = sensor_init;
+       while (*p != 0) {
+               val[1] = *p++;
+               val[3] = *p++;
+               if (*p == 0)
+                       reg_w(gspca_dev, 0x3c80);
+               reg_w_buf(gspca_dev, val, sizeof val);
+               i = 4;
+               while (--i >= 0) {
+                       msleep(15);
+                       byte = reg_r(gspca_dev, 0x60);
+                       if (!(byte & 0x01))
+                               break;
+               }
+       }
+       msleep(15);
+       reg_w(gspca_dev, 0x3c80);
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                    const struct usb_device_id *id)
+{
+       struct cam *cam  = &gspca_dev->cam;
+
+       cam->cam_mode = vga_mode_t16;
+       cam->nmodes = ARRAY_SIZE(vga_mode_t16);
+
+       return 0;
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
+{
+       u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
+
+       if (brightness < 7) {
+               set6[1] = 0x26;
+               set6[3] = 0x70 - brightness * 0x10;
+       } else {
+               set6[3] = 0x00 + ((brightness - 7) * 0x10);
+       }
+
+       reg_w_buf(gspca_dev, set6, sizeof set6);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, s32 contrast)
+{
+       u16 reg_to_write;
+
+       if (contrast < 7)
+               reg_to_write = 0x8ea9 - contrast * 0x200;
+       else
+               reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
+
+       reg_w(gspca_dev, reg_to_write);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev, s32 val)
+{
+       u16 reg_to_write;
+
+       reg_to_write = 0x80bb + val * 0x100;    /* was 0xc0 */
+       reg_w(gspca_dev, reg_to_write);
+}
+
+static void setgamma(struct gspca_dev *gspca_dev, s32 val)
+{
+       PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
+       reg_w_ixbuf(gspca_dev, 0x90,
+               gamma_table[val], sizeof gamma_table[0]);
+}
+
+static void setawb_n_RGB(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 all_gain_reg[8] = {
+               0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00 };
+       s32 red_gain, blue_gain, green_gain;
+
+       green_gain = sd->gain->val;
+
+       red_gain = green_gain + sd->red_balance->val;
+       if (red_gain > 0x40)
+               red_gain = 0x40;
+       else if (red_gain < 0x10)
+               red_gain = 0x10;
+
+       blue_gain = green_gain + sd->blue_balance->val;
+       if (blue_gain > 0x40)
+               blue_gain = 0x40;
+       else if (blue_gain < 0x10)
+               blue_gain = 0x10;
+
+       all_gain_reg[1] = red_gain;
+       all_gain_reg[3] = blue_gain;
+       all_gain_reg[5] = green_gain;
+       all_gain_reg[7] = sensor_data[sd->sensor].reg80;
+       if (!sd->awb->val)
+               all_gain_reg[7] &= ~0x04; /* AWB off */
+
+       reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
+{
+       u16 reg_to_write;
+
+       reg_to_write = 0x0aa6 + 0x1000 * val;
+
+       reg_w(gspca_dev, reg_to_write);
+}
+
+static void setfreq(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 reg66;
+       u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
+
+       switch (sd->sensor) {
+       case SENSOR_LT168G:
+               if (val != 0)
+                       freq[3] = 0xa8;
+               reg66 = 0x41;
+               break;
+       case SENSOR_OM6802:
+               reg66 = 0xca;
+               break;
+       default:
+               reg66 = 0x40;
+               break;
+       }
+       switch (val) {
+       case 0:                         /* no flicker */
+               freq[3] = 0xf0;
+               break;
+       case 2:                         /* 60Hz */
+               reg66 &= ~0x40;
+               break;
+       }
+       freq[1] = reg66;
+
+       reg_w_buf(gspca_dev, freq, sizeof freq);
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       /* some of this registers are not really neded, because
+        * they are overriden by setbrigthness, setcontrast, etc,
+        * but wont hurt anyway, and can help someone with similar webcam
+        * to see the initial parameters.*/
+       struct sd *sd = (struct sd *) gspca_dev;
+       const struct additional_sensor_data *sensor;
+       int i;
+       u16 sensor_id;
+       u8 test_byte = 0;
+
+       static const u8 read_indexs[] =
+               { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
+                 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
+       static const u8 n1[] =
+                       {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
+       static const u8 n2[] =
+                       {0x08, 0x00};
+
+       sensor_id = (reg_r(gspca_dev, 0x06) << 8)
+                       | reg_r(gspca_dev, 0x07);
+       switch (sensor_id & 0xff0f) {
+       case 0x0801:
+               PDEBUG(D_PROBE, "sensor tas5130a");
+               sd->sensor = SENSOR_TAS5130A;
+               break;
+       case 0x0802:
+               PDEBUG(D_PROBE, "sensor lt168g");
+               sd->sensor = SENSOR_LT168G;
+               break;
+       case 0x0803:
+               PDEBUG(D_PROBE, "sensor 'other'");
+               sd->sensor = SENSOR_OTHER;
+               break;
+       case 0x0807:
+               PDEBUG(D_PROBE, "sensor om6802");
+               sd->sensor = SENSOR_OM6802;
+               break;
+       default:
+               pr_err("unknown sensor %04x\n", sensor_id);
+               return -EINVAL;
+       }
+
+       if (sd->sensor == SENSOR_OM6802) {
+               reg_w_buf(gspca_dev, n1, sizeof n1);
+               i = 5;
+               while (--i >= 0) {
+                       reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
+                       test_byte = reg_r(gspca_dev, 0x0063);
+                       msleep(100);
+                       if (test_byte == 0x17)
+                               break;          /* OK */
+               }
+               if (i < 0) {
+                       pr_err("Bad sensor reset %02x\n", test_byte);
+                       return -EIO;
+               }
+               reg_w_buf(gspca_dev, n2, sizeof n2);
+       }
+
+       i = 0;
+       while (read_indexs[i] != 0x00) {
+               test_byte = reg_r(gspca_dev, read_indexs[i]);
+               PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
+                      test_byte);
+               i++;
+       }
+
+       sensor = &sensor_data[sd->sensor];
+       reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
+       reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
+
+       if (sd->sensor == SENSOR_LT168G) {
+               test_byte = reg_r(gspca_dev, 0x80);
+               PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
+                      test_byte);
+               reg_w(gspca_dev, 0x6c80);
+       }
+
+       reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
+       reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
+       reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
+
+       reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
+       reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
+       reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
+       reg_w(gspca_dev, (0x20 << 8) + 0x87);
+       reg_w(gspca_dev, (0x20 << 8) + 0x88);
+       reg_w(gspca_dev, (0x20 << 8) + 0x89);
+
+       reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
+       reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
+       reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
+
+       if (sd->sensor == SENSOR_LT168G) {
+               test_byte = reg_r(gspca_dev, 0x80);
+               PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
+                      test_byte);
+               reg_w(gspca_dev, 0x6c80);
+       }
+
+       reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
+       reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
+       reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
+
+       return 0;
+}
+
+static void setmirror(struct gspca_dev *gspca_dev, s32 val)
+{
+       u8 hflipcmd[8] =
+               {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
+
+       if (val)
+               hflipcmd[3] = 0x01;
+
+       reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
+}
+
+static void seteffect(struct gspca_dev *gspca_dev, s32 val)
+{
+       int idx = 0;
+
+       switch (val) {
+       case V4L2_COLORFX_NONE:
+               break;
+       case V4L2_COLORFX_BW:
+               idx = 2;
+               break;
+       case V4L2_COLORFX_SEPIA:
+               idx = 3;
+               break;
+       case V4L2_COLORFX_SKETCH:
+               idx = 4;
+               break;
+       case V4L2_COLORFX_NEGATIVE:
+               idx = 6;
+               break;
+       default:
+               break;
+       }
+
+       reg_w_buf(gspca_dev, effects_table[idx],
+                               sizeof effects_table[0]);
+
+       if (val == V4L2_COLORFX_SKETCH)
+               reg_w(gspca_dev, 0x4aa6);
+       else
+               reg_w(gspca_dev, 0xfaa6);
+}
+
+/* Is this really needed?
+ * i added some module parameters for test with some users */
+static void poll_sensor(struct gspca_dev *gspca_dev)
+{
+       static const u8 poll1[] =
+               {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
+                0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
+                0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
+                0x60, 0x14};
+       static const u8 poll2[] =
+               {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
+                0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
+       static const u8 noise03[] =     /* (some differences / ms-drv) */
+               {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
+                0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
+                0xc2, 0x80, 0xc3, 0x10};
+
+       PDEBUG(D_STREAM, "[Sensor requires polling]");
+       reg_w_buf(gspca_dev, poll1, sizeof poll1);
+       reg_w_buf(gspca_dev, poll2, sizeof poll2);
+       reg_w_buf(gspca_dev, noise03, sizeof noise03);
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       const struct additional_sensor_data *sensor;
+       int i, mode;
+       u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
+       static const u8 t3[] =
+               { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
+
+       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+       switch (mode) {
+       case 0:         /* 640x480 (0x00) */
+               break;
+       case 1:         /* 352x288 */
+               t2[1] = 0x40;
+               break;
+       case 2:         /* 320x240 */
+               t2[1] = 0x10;
+               break;
+       case 3:         /* 176x144 */
+               t2[1] = 0x50;
+               break;
+       default:
+/*     case 4:          * 160x120 */
+               t2[1] = 0x20;
+               break;
+       }
+
+       switch (sd->sensor) {
+       case SENSOR_OM6802:
+               om6802_sensor_init(gspca_dev);
+               break;
+       case SENSOR_TAS5130A:
+               i = 0;
+               for (;;) {
+                       reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
+                                        sizeof tas5130a_sensor_init[0]);
+                       if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
+                               break;
+                       i++;
+               }
+               reg_w(gspca_dev, 0x3c80);
+               /* just in case and to keep sync with logs (for mine) */
+               reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
+                                sizeof tas5130a_sensor_init[0]);
+               reg_w(gspca_dev, 0x3c80);
+               break;
+       }
+       sensor = &sensor_data[sd->sensor];
+       setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
+       reg_r(gspca_dev, 0x0012);
+       reg_w_buf(gspca_dev, t2, sizeof t2);
+       reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
+       reg_w(gspca_dev, 0x0013);
+       msleep(15);
+       reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
+       reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
+
+       if (sd->sensor == SENSOR_OM6802)
+               poll_sensor(gspca_dev);
+
+       return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
+                       sizeof sensor_data[sd->sensor].stream);
+       reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
+                       sizeof sensor_data[sd->sensor].stream);
+       if (sd->sensor == SENSOR_OM6802) {
+               msleep(20);
+               reg_w(gspca_dev, 0x0309);
+       }
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       /* If the last button state is pressed, release it now! */
+       if (sd->button_pressed) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+               input_sync(gspca_dev->input_dev);
+               sd->button_pressed = 0;
+       }
+#endif
+}
+
+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;
+       int pkt_type;
+
+       if (data[0] == 0x5a) {
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+               if (len > 20) {
+                       u8 state = (data[20] & 0x80) ? 1 : 0;
+                       if (sd->button_pressed != state) {
+                               input_report_key(gspca_dev->input_dev,
+                                                KEY_CAMERA, state);
+                               input_sync(gspca_dev->input_dev);
+                               sd->button_pressed = state;
+                       }
+               }
+#endif
+               /* Control Packet, after this came the header again,
+                * but extra bytes came in the packet before this,
+                * sometimes an EOF arrives, sometimes not... */
+               return;
+       }
+       data += 2;
+       len -= 2;
+       if (data[0] == 0xff && data[1] == 0xd8)
+               pkt_type = FIRST_PACKET;
+       else if (data[len - 2] == 0xff && data[len - 1] == 0xd9)
+               pkt_type = LAST_PACKET;
+       else
+               pkt_type = INTER_PACKET;
+       gspca_frame_add(gspca_dev, pkt_type, data, len);
+}
+
+static int sd_g_volatile_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;
+       s32 red_gain, blue_gain, green_gain;
+
+       gspca_dev->usb_err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               red_gain = reg_r(gspca_dev, 0x0087);
+               if (red_gain > 0x40)
+                       red_gain = 0x40;
+               else if (red_gain < 0x10)
+                       red_gain = 0x10;
+
+               blue_gain = reg_r(gspca_dev, 0x0088);
+               if (blue_gain > 0x40)
+                       blue_gain = 0x40;
+               else if (blue_gain < 0x10)
+                       blue_gain = 0x10;
+
+               green_gain = reg_r(gspca_dev, 0x0089);
+               if (green_gain > 0x40)
+                       green_gain = 0x40;
+               else if (green_gain < 0x10)
+                       green_gain = 0x10;
+
+               sd->gain->val = green_gain;
+               sd->red_balance->val = red_gain - green_gain;
+               sd->blue_balance->val = blue_gain - green_gain;
+               break;
+       }
+       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);
+
+       gspca_dev->usb_err = 0;
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               setcolors(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_GAMMA:
+               setgamma(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_HFLIP:
+               setmirror(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SHARPNESS:
+               setsharpness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_POWER_LINE_FREQUENCY:
+               setfreq(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_BACKLIGHT_COMPENSATION:
+               reg_w(gspca_dev, ctrl->val ? 0xf48e : 0xb48e);
+               break;
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               setawb_n_RGB(gspca_dev);
+               break;
+       case V4L2_CID_COLORFX:
+               seteffect(gspca_dev, ctrl->val);
+               break;
+       }
+       return gspca_dev->usb_err;
+}
+
+static const struct v4l2_ctrl_ops sd_ctrl_ops = {
+       .g_volatile_ctrl = sd_g_volatile_ctrl,
+       .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, 12);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 14, 1, 8);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 0x0d, 1, 7);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 0xf, 1, 5);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAMMA, 0, GAMMA_MAX, 1, 10);
+       /* Activate lowlight, some apps dont bring up the
+          backlight_compensation control) */
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BACKLIGHT_COMPENSATION, 0, 1, 1, 1);
+       if (sd->sensor == SENSOR_TAS5130A)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                               V4L2_CID_HFLIP, 0, 1, 1, 0);
+       sd->awb = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+       sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAIN, 0x10, 0x40, 1, 0x20);
+       sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BLUE_BALANCE, -0x30, 0x30, 1, 0);
+       sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_RED_BALANCE, -0x30, 0x30, 1, 0);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SHARPNESS, 0, 15, 1, 6);
+       v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
+                       V4L2_CID_COLORFX, V4L2_COLORFX_SKETCH,
+                       ~((1 << V4L2_COLORFX_NONE) |
+                         (1 << V4L2_COLORFX_BW) |
+                         (1 << V4L2_COLORFX_SEPIA) |
+                         (1 << V4L2_COLORFX_SKETCH) |
+                         (1 << V4L2_COLORFX_NEGATIVE)),
+                       V4L2_COLORFX_NONE);
+       sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
+                       V4L2_CID_POWER_LINE_FREQUENCY,
+                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
+                       V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+
+       v4l2_ctrl_auto_cluster(4, &sd->awb, 0, true);
+
+       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,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .other_input = 1,
+#endif
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x17a1, 0x0128)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/topro.c b/drivers/media/usb/gspca/topro.c
new file mode 100644 (file)
index 0000000..a605524
--- /dev/null
@@ -0,0 +1,4969 @@
+/*
+ * Topro TP6800/6810 webcam driver.
+ *
+ * Copyright (C) 2011 Jean-François Moine (http://moinejf.free.fr)
+ * Copyright (C) 2009 Anders Blomdell (anders.blomdell@control.lth.se)
+ * Copyright (C) 2008 Thomas Champagne (lafeuil@gmail.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.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "gspca.h"
+
+MODULE_DESCRIPTION("Topro TP6800/6810 gspca webcam driver");
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
+               "Anders Blomdell <anders.blomdell@control.lth.se>");
+MODULE_LICENSE("GPL");
+
+static int force_sensor = -1;
+
+/* JPEG header */
+static const u8 jpeg_head[] = {
+       0xff, 0xd8,                     /* jpeg */
+
+/* quantization table quality 50% */
+       0xff, 0xdb, 0x00, 0x84,         /* DQT */
+0,
+#define JPEG_QT0_OFFSET 7
+       0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
+       0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
+       0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
+       0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
+       0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
+       0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
+       0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
+       0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
+1,
+#define JPEG_QT1_OFFSET 72
+       0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+       0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+
+       /* Define Huffman table (thanks to Thomas Kaiser) */
+       0xff, 0xc4, 0x01, 0x5e,
+       0x00, 0x00, 0x02, 0x03,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+       0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
+       0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+       0x07, 0x05, 0x04, 0x06, 0x01, 0x00, 0x00, 0x57,
+       0x01, 0x02, 0x03, 0x00, 0x11, 0x04, 0x12, 0x21,
+       0x31, 0x13, 0x41, 0x51, 0x61, 0x05, 0x22, 0x32,
+       0x14, 0x71, 0x81, 0x91, 0x15, 0x23, 0x42, 0x52,
+       0x62, 0xa1, 0xb1, 0x06, 0x33, 0x72, 0xc1, 0xd1,
+       0x24, 0x43, 0x53, 0x82, 0x16, 0x34, 0x92, 0xa2,
+       0xe1, 0xf1, 0xf0, 0x07, 0x08, 0x17, 0x18, 0x25,
+       0x26, 0x27, 0x28, 0x35, 0x36, 0x37, 0x38, 0x44,
+       0x45, 0x46, 0x47, 0x48, 0x54, 0x55, 0x56, 0x57,
+       0x58, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x73,
+       0x74, 0x75, 0x76, 0x77, 0x78, 0x83, 0x84, 0x85,
+       0x86, 0x87, 0x88, 0x93, 0x94, 0x95, 0x96, 0x97,
+       0x98, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xb2,
+       0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xc2, 0xc3,
+       0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xd2, 0xd3, 0xd4,
+       0xd5, 0xd6, 0xd7, 0xd8, 0xe2, 0xe3, 0xe4, 0xe5,
+       0xe6, 0xe7, 0xe8, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
+       0xf7, 0xf8, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+       0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
+       0x05, 0x06, 0x07, 0x08, 0x09, 0x11, 0x00, 0x02,
+       0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
+       0x04, 0x06, 0x01, 0x00, 0x00, 0x57, 0x00, 0x01,
+       0x11, 0x02, 0x21, 0x03, 0x12, 0x31, 0x41, 0x13,
+       0x22, 0x51, 0x61, 0x04, 0x32, 0x71, 0x05, 0x14,
+       0x23, 0x42, 0x33, 0x52, 0x81, 0x91, 0xa1, 0xb1,
+       0xf0, 0x06, 0x15, 0xc1, 0xd1, 0xe1, 0x24, 0x43,
+       0x62, 0xf1, 0x16, 0x25, 0x34, 0x53, 0x72, 0x82,
+       0x92, 0x07, 0x08, 0x17, 0x18, 0x26, 0x27, 0x28,
+       0x35, 0x36, 0x37, 0x38, 0x44, 0x45, 0x46, 0x47,
+       0x48, 0x54, 0x55, 0x56, 0x57, 0x58, 0x63, 0x64,
+       0x65, 0x66, 0x67, 0x68, 0x73, 0x74, 0x75, 0x76,
+       0x77, 0x78, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+       0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0xa2, 0xa3,
+       0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xb2, 0xb3, 0xb4,
+       0xb5, 0xb6, 0xb7, 0xb8, 0xc2, 0xc3, 0xc4, 0xc5,
+       0xc6, 0xc7, 0xc8, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
+       0xd7, 0xd8, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+       0xe8, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+       0xff, 0xc0, 0x00, 0x11,         /* SOF0 (start of frame 0 */
+       0x08,                           /* data precision */
+#define JPEG_HEIGHT_OFFSET 493
+       0x01, 0xe0,                     /* height */
+       0x02, 0x80,                     /* width */
+       0x03,                           /* component number */
+               0x01,
+                       0x21,           /* samples Y = jpeg 422 */
+                       0x00,           /* quant Y */
+               0x02, 0x11, 0x01,       /* samples CbCr - quant CbCr */
+               0x03, 0x11, 0x01,
+
+       0xff, 0xda, 0x00, 0x0c,         /* SOS (start of scan) */
+       0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
+#define JPEG_HDR_SZ 521
+};
+
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+       struct v4l2_ctrl *jpegqual;
+       struct v4l2_ctrl *sharpness;
+       struct v4l2_ctrl *gamma;
+       struct v4l2_ctrl *blue;
+       struct v4l2_ctrl *red;
+
+       u8 framerate;
+       u8 quality;             /* webcam current JPEG quality (0..16) */
+       s8 ag_cnt;              /* autogain / start counter for tp6810 */
+#define AG_CNT_START 13                /* check gain every N frames */
+
+       u8 bridge;
+       u8 sensor;
+
+       u8 jpeg_hdr[JPEG_HDR_SZ];
+};
+
+enum bridges {
+       BRIDGE_TP6800,
+       BRIDGE_TP6810,
+};
+
+enum sensors {
+       SENSOR_CX0342,
+       SENSOR_SOI763A,         /* ~= ov7630 / ov7648 */
+       NSENSORS
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 4 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG}
+};
+
+/*
+ * JPEG quality
+ * index: webcam compression
+ * value: JPEG quality in %
+ */
+static const u8 jpeg_q[17] = {
+       88, 77, 67, 57, 55, 55, 45, 45, 36, 36, 30, 30, 26, 26, 22, 22, 94
+};
+
+#define BULK_OUT_SIZE          0x20
+#if BULK_OUT_SIZE > USB_BUF_SZ
+#error "USB buffer too small"
+#endif
+
+static const u8 rates[] = {30, 20, 15, 10, 7, 5};
+static const struct framerates framerates[] = {
+       {
+               .rates = rates,
+               .nrates = ARRAY_SIZE(rates)
+       },
+       {
+               .rates = rates,
+               .nrates = ARRAY_SIZE(rates)
+       }
+};
+static const u8 rates_6810[] = {30, 15, 10, 7, 5};
+static const struct framerates framerates_6810[] = {
+       {
+               .rates = rates_6810,
+               .nrates = ARRAY_SIZE(rates_6810)
+       },
+       {
+               .rates = rates_6810,
+               .nrates = ARRAY_SIZE(rates_6810)
+       }
+};
+
+/*
+ * webcam quality in %
+ * the last value is the ultra fine quality
+ */
+
+/* TP6800 register offsets */
+#define TP6800_R10_SIF_TYPE            0x10
+#define TP6800_R11_SIF_CONTROL         0x11
+#define TP6800_R12_SIF_ADDR_S          0x12
+#define TP6800_R13_SIF_TX_DATA         0x13
+#define TP6800_R14_SIF_RX_DATA         0x14
+#define TP6800_R15_GPIO_PU             0x15
+#define TP6800_R16_GPIO_PD             0x16
+#define TP6800_R17_GPIO_IO             0x17
+#define TP6800_R18_GPIO_DATA           0x18
+#define TP6800_R19_SIF_ADDR_S2         0x19
+#define TP6800_R1A_SIF_TX_DATA2                0x1a
+#define TP6800_R1B_SIF_RX_DATA2                0x1b
+#define TP6800_R21_ENDP_1_CTL          0x21
+#define TP6800_R2F_TIMING_CFG          0x2f
+#define TP6800_R30_SENSOR_CFG          0x30
+#define TP6800_R31_PIXEL_START         0x31
+#define TP6800_R32_PIXEL_END_L         0x32
+#define TP6800_R33_PIXEL_END_H         0x33
+#define TP6800_R34_LINE_START          0x34
+#define TP6800_R35_LINE_END_L          0x35
+#define TP6800_R36_LINE_END_H          0x36
+#define TP6800_R37_FRONT_DARK_ST       0x37
+#define TP6800_R38_FRONT_DARK_END      0x38
+#define TP6800_R39_REAR_DARK_ST_L      0x39
+#define TP6800_R3A_REAR_DARK_ST_H      0x3a
+#define TP6800_R3B_REAR_DARK_END_L     0x3b
+#define TP6800_R3C_REAR_DARK_END_H     0x3c
+#define TP6800_R3D_HORIZ_DARK_LINE_L   0x3d
+#define TP6800_R3E_HORIZ_DARK_LINE_H   0x3e
+#define TP6800_R3F_FRAME_RATE          0x3f
+#define TP6800_R50                     0x50
+#define TP6800_R51                     0x51
+#define TP6800_R52                     0x52
+#define TP6800_R53                     0x53
+#define TP6800_R54_DARK_CFG            0x54
+#define TP6800_R55_GAMMA_R             0x55
+#define TP6800_R56_GAMMA_G             0x56
+#define TP6800_R57_GAMMA_B             0x57
+#define TP6800_R5C_EDGE_THRLD          0x5c
+#define TP6800_R5D_DEMOSAIC_CFG                0x5d
+#define TP6800_R78_FORMAT              0x78
+#define TP6800_R79_QUALITY             0x79
+#define TP6800_R7A_BLK_THRLD           0x7a
+
+/* CX0342 register offsets */
+
+#define CX0342_SENSOR_ID               0x00
+#define CX0342_VERSION_NO              0x01
+#define CX0342_ORG_X_L                 0x02
+#define CX0342_ORG_X_H                 0x03
+#define CX0342_ORG_Y_L                 0x04
+#define CX0342_ORG_Y_H                 0x05
+#define CX0342_STOP_X_L                        0x06
+#define CX0342_STOP_X_H                        0x07
+#define CX0342_STOP_Y_L                        0x08
+#define CX0342_STOP_Y_H                        0x09
+#define CX0342_FRAME_WIDTH_L           0x0a
+#define CX0342_FRAME_WIDTH_H           0x0b
+#define CX0342_FRAME_HEIGH_L           0x0c
+#define CX0342_FRAME_HEIGH_H           0x0d
+#define CX0342_EXPO_LINE_L             0x10
+#define CX0342_EXPO_LINE_H             0x11
+#define CX0342_EXPO_CLK_L              0x12
+#define CX0342_EXPO_CLK_H              0x13
+#define CX0342_RAW_GRGAIN_L            0x14
+#define CX0342_RAW_GRGAIN_H            0x15
+#define CX0342_RAW_GBGAIN_L            0x16
+#define CX0342_RAW_GBGAIN_H            0x17
+#define CX0342_RAW_RGAIN_L             0x18
+#define CX0342_RAW_RGAIN_H             0x19
+#define CX0342_RAW_BGAIN_L             0x1a
+#define CX0342_RAW_BGAIN_H             0x1b
+#define CX0342_GLOBAL_GAIN             0x1c
+#define CX0342_SYS_CTRL_0              0x20
+#define CX0342_SYS_CTRL_1              0x21
+#define CX0342_SYS_CTRL_2              0x22
+#define CX0342_BYPASS_MODE             0x23
+#define CX0342_SYS_CTRL_3              0x24
+#define CX0342_TIMING_EN               0x25
+#define CX0342_OUTPUT_CTRL             0x26
+#define CX0342_AUTO_ADC_CALIB          0x27
+#define CX0342_SYS_CTRL_4              0x28
+#define CX0342_ADCGN                   0x30
+#define CX0342_SLPCR                   0x31
+#define CX0342_SLPFN_LO                        0x32
+#define CX0342_ADC_CTL                 0x33
+#define CX0342_LVRST_BLBIAS            0x34
+#define CX0342_VTHSEL                  0x35
+#define CX0342_RAMP_RIV                        0x36
+#define CX0342_LDOSEL                  0x37
+#define CX0342_CLOCK_GEN               0x40
+#define CX0342_SOFT_RESET              0x41
+#define CX0342_PLL                     0x42
+#define CX0342_DR_ENH_PULSE_OFFSET_L   0x43
+#define CX0342_DR_ENH_PULSE_OFFSET_H   0x44
+#define CX0342_DR_ENH_PULSE_POS_L      0x45
+#define CX0342_DR_ENH_PULSE_POS_H      0x46
+#define CX0342_DR_ENH_PULSE_WIDTH      0x47
+#define CX0342_AS_CURRENT_CNT_L                0x48
+#define CX0342_AS_CURRENT_CNT_H                0x49
+#define CX0342_AS_PREVIOUS_CNT_L       0x4a
+#define CX0342_AS_PREVIOUS_CNT_H       0x4b
+#define CX0342_SPV_VALUE_L             0x4c
+#define CX0342_SPV_VALUE_H             0x4d
+#define CX0342_GPXLTHD_L               0x50
+#define CX0342_GPXLTHD_H               0x51
+#define CX0342_RBPXLTHD_L              0x52
+#define CX0342_RBPXLTHD_H              0x53
+#define CX0342_PLANETHD_L              0x54
+#define CX0342_PLANETHD_H              0x55
+#define CX0342_ROWDARK_TH              0x56
+#define CX0342_ROWDARK_TOL             0x57
+#define CX0342_RB_GAP_L                        0x58
+#define CX0342_RB_GAP_H                        0x59
+#define CX0342_G_GAP_L                 0x5a
+#define CX0342_G_GAP_H                 0x5b
+#define CX0342_AUTO_ROW_DARK           0x60
+#define CX0342_MANUAL_DARK_VALUE       0x61
+#define CX0342_GB_DARK_OFFSET          0x62
+#define CX0342_GR_DARK_OFFSET          0x63
+#define CX0342_RED_DARK_OFFSET         0x64
+#define CX0342_BLUE_DARK_OFFSET                0x65
+#define CX0342_DATA_SCALING_MULTI      0x66
+#define CX0342_AUTOD_Q_FRAME           0x67
+#define CX0342_AUTOD_ALLOW_VARI                0x68
+#define CX0342_AUTO_DARK_VALUE_L       0x69
+#define CX0342_AUTO_DARK_VALUE_H       0x6a
+#define CX0342_IO_CTRL_0               0x70
+#define CX0342_IO_CTRL_1               0x71
+#define CX0342_IO_CTRL_2               0x72
+#define CX0342_IDLE_CTRL               0x73
+#define CX0342_TEST_MODE               0x74
+#define CX0342_FRAME_FIX_DATA_TEST     0x75
+#define CX0342_FRAME_CNT_TEST          0x76
+#define CX0342_RST_OVERFLOW_L          0x80
+#define CX0342_RST_OVERFLOW_H          0x81
+#define CX0342_RST_UNDERFLOW_L         0x82
+#define CX0342_RST_UNDERFLOW_H         0x83
+#define CX0342_DATA_OVERFLOW_L         0x84
+#define CX0342_DATA_OVERFLOW_H         0x85
+#define CX0342_DATA_UNDERFLOW_L                0x86
+#define CX0342_DATA_UNDERFLOW_H                0x87
+#define CX0342_CHANNEL_0_0_L_irst      0x90
+#define CX0342_CHANNEL_0_0_H_irst      0x91
+#define CX0342_CHANNEL_0_1_L_irst      0x92
+#define CX0342_CHANNEL_0_1_H_irst      0x93
+#define CX0342_CHANNEL_0_2_L_irst      0x94
+#define CX0342_CHANNEL_0_2_H_irst      0x95
+#define CX0342_CHANNEL_0_3_L_irst      0x96
+#define CX0342_CHANNEL_0_3_H_irst      0x97
+#define CX0342_CHANNEL_0_4_L_irst      0x98
+#define CX0342_CHANNEL_0_4_H_irst      0x99
+#define CX0342_CHANNEL_0_5_L_irst      0x9a
+#define CX0342_CHANNEL_0_5_H_irst      0x9b
+#define CX0342_CHANNEL_0_6_L_irst      0x9c
+#define CX0342_CHANNEL_0_6_H_irst      0x9d
+#define CX0342_CHANNEL_0_7_L_irst      0x9e
+#define CX0342_CHANNEL_0_7_H_irst      0x9f
+#define CX0342_CHANNEL_1_0_L_itx       0xa0
+#define CX0342_CHANNEL_1_0_H_itx       0xa1
+#define CX0342_CHANNEL_1_1_L_itx       0xa2
+#define CX0342_CHANNEL_1_1_H_itx       0xa3
+#define CX0342_CHANNEL_1_2_L_itx       0xa4
+#define CX0342_CHANNEL_1_2_H_itx       0xa5
+#define CX0342_CHANNEL_1_3_L_itx       0xa6
+#define CX0342_CHANNEL_1_3_H_itx       0xa7
+#define CX0342_CHANNEL_1_4_L_itx       0xa8
+#define CX0342_CHANNEL_1_4_H_itx       0xa9
+#define CX0342_CHANNEL_1_5_L_itx       0xaa
+#define CX0342_CHANNEL_1_5_H_itx       0xab
+#define CX0342_CHANNEL_1_6_L_itx       0xac
+#define CX0342_CHANNEL_1_6_H_itx       0xad
+#define CX0342_CHANNEL_1_7_L_itx       0xae
+#define CX0342_CHANNEL_1_7_H_itx       0xaf
+#define CX0342_CHANNEL_2_0_L_iwl       0xb0
+#define CX0342_CHANNEL_2_0_H_iwl       0xb1
+#define CX0342_CHANNEL_2_1_L_iwl       0xb2
+#define CX0342_CHANNEL_2_1_H_iwl       0xb3
+#define CX0342_CHANNEL_2_2_L_iwl       0xb4
+#define CX0342_CHANNEL_2_2_H_iwl       0xb5
+#define CX0342_CHANNEL_2_3_L_iwl       0xb6
+#define CX0342_CHANNEL_2_3_H_iwl       0xb7
+#define CX0342_CHANNEL_2_4_L_iwl       0xb8
+#define CX0342_CHANNEL_2_4_H_iwl       0xb9
+#define CX0342_CHANNEL_2_5_L_iwl       0xba
+#define CX0342_CHANNEL_2_5_H_iwl       0xbb
+#define CX0342_CHANNEL_2_6_L_iwl       0xbc
+#define CX0342_CHANNEL_2_6_H_iwl       0xbd
+#define CX0342_CHANNEL_2_7_L_iwl       0xbe
+#define CX0342_CHANNEL_2_7_H_iwl       0xbf
+#define CX0342_CHANNEL_3_0_L_ensp      0xc0
+#define CX0342_CHANNEL_3_0_H_ensp      0xc1
+#define CX0342_CHANNEL_3_1_L_ensp      0xc2
+#define CX0342_CHANNEL_3_1_H_ensp      0xc3
+#define CX0342_CHANNEL_3_2_L_ensp      0xc4
+#define CX0342_CHANNEL_3_2_H_ensp      0xc5
+#define CX0342_CHANNEL_3_3_L_ensp      0xc6
+#define CX0342_CHANNEL_3_3_H_ensp      0xc7
+#define CX0342_CHANNEL_3_4_L_ensp      0xc8
+#define CX0342_CHANNEL_3_4_H_ensp      0xc9
+#define CX0342_CHANNEL_3_5_L_ensp      0xca
+#define CX0342_CHANNEL_3_5_H_ensp      0xcb
+#define CX0342_CHANNEL_3_6_L_ensp      0xcc
+#define CX0342_CHANNEL_3_6_H_ensp      0xcd
+#define CX0342_CHANNEL_3_7_L_ensp      0xce
+#define CX0342_CHANNEL_3_7_H_ensp      0xcf
+#define CX0342_CHANNEL_4_0_L_sela      0xd0
+#define CX0342_CHANNEL_4_0_H_sela      0xd1
+#define CX0342_CHANNEL_4_1_L_sela      0xd2
+#define CX0342_CHANNEL_4_1_H_sela      0xd3
+#define CX0342_CHANNEL_5_0_L_intla     0xe0
+#define CX0342_CHANNEL_5_0_H_intla     0xe1
+#define CX0342_CHANNEL_5_1_L_intla     0xe2
+#define CX0342_CHANNEL_5_1_H_intla     0xe3
+#define CX0342_CHANNEL_5_2_L_intla     0xe4
+#define CX0342_CHANNEL_5_2_H_intla     0xe5
+#define CX0342_CHANNEL_5_3_L_intla     0xe6
+#define CX0342_CHANNEL_5_3_H_intla     0xe7
+#define CX0342_CHANNEL_6_0_L_xa_sel_pos 0xf0
+#define CX0342_CHANNEL_6_0_H_xa_sel_pos 0xf1
+#define CX0342_CHANNEL_7_1_L_cds_pos   0xf2
+#define CX0342_CHANNEL_7_1_H_cds_pos   0xf3
+#define CX0342_SENSOR_HEIGHT_L         0xfb
+#define CX0342_SENSOR_HEIGHT_H         0xfc
+#define CX0342_SENSOR_WIDTH_L          0xfd
+#define CX0342_SENSOR_WIDTH_H          0xfe
+#define CX0342_VSYNC_HSYNC_READ                0xff
+
+struct cmd {
+       u8 reg;
+       u8 val;
+};
+
+static const u8 DQT[17][130] = {
+       /* Define quantization table (thanks to Thomas Kaiser) */
+       {                       /* Quality 0 */
+        0x00,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x01,
+        0x04, 0x04, 0x04, 0x06, 0x05, 0x06, 0x0b, 0x06,
+        0x06, 0x0b, 0x18, 0x10, 0x0e, 0x10, 0x18, 0x18,
+        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+        },
+       {                       /* Quality 1 */
+        0x00,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x09, 0x09, 0x09, 0x09, 0x09,
+        0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+        0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+        0x01,
+        0x08, 0x09, 0x09, 0x0c, 0x0a, 0x0c, 0x17, 0x0d,
+        0x0d, 0x17, 0x31, 0x21, 0x1c, 0x21, 0x31, 0x31,
+        0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+        0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+        0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+        0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+        0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+        0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
+        },
+       {                       /* Quality 2 */
+        0x00,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x06, 0x06, 0x06, 0x04, 0x04, 0x04,
+        0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+        0x06, 0x06, 0x06, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+        0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+        0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+        0x01,
+        0x0c, 0x0d, 0x0d, 0x12, 0x0f, 0x12, 0x23, 0x13,
+        0x13, 0x23, 0x4a, 0x31, 0x2a, 0x31, 0x4a, 0x4a,
+        0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+        0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+        0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+        0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+        0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+        0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
+        },
+       {                       /* Quality 3 */
+        0x00,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04,
+        0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+        0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+        0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+        0x08, 0x08, 0x08, 0x13, 0x13, 0x13, 0x13, 0x13,
+        0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
+        0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
+        0x01,
+        0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
+        0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
+        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+        },
+       {                       /* Quality 4 */
+        0x00,
+        0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+        0x05, 0x05, 0x0a, 0x0a, 0x0a, 0x05, 0x05, 0x05,
+        0x05, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+        0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+        0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+        0x0a, 0x0a, 0x0a, 0x17, 0x17, 0x17, 0x17, 0x17,
+        0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+        0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+        0x01,
+        0x11, 0x16, 0x16, 0x1e, 0x1a, 0x1e, 0x3a, 0x20,
+        0x20, 0x3a, 0x7b, 0x52, 0x46, 0x52, 0x7b, 0x7b,
+        0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+        0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+        0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+        0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+        0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+        0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
+        },
+       {                       /* Quality 5 */
+        0x00,
+        0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+        0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x06, 0x06, 0x06,
+        0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+        0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+        0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+        0x0c, 0x0c, 0x0c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+        0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+        0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+        0x01,
+        0x11, 0x1b, 0x1b, 0x24, 0x1f, 0x24, 0x46, 0x27,
+        0x27, 0x46, 0x94, 0x63, 0x54, 0x63, 0x94, 0x94,
+        0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+        0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+        0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+        0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+        0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+        0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
+        },
+       {                       /* Quality 6 */
+        0x00,
+        0x05, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+        0x07, 0x07, 0x0e, 0x0e, 0x0e, 0x07, 0x07, 0x07,
+        0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+        0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+        0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+        0x0e, 0x0e, 0x0e, 0x21, 0x21, 0x21, 0x21, 0x21,
+        0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
+        0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
+        0x01,
+        0x15, 0x1f, 0x1f, 0x2a, 0x24, 0x2a, 0x52, 0x2d,
+        0x2d, 0x52, 0xad, 0x73, 0x62, 0x73, 0xad, 0xad,
+        0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+        0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+        0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+        0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+        0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+        0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
+        },
+       {                       /* Quality 7 */
+        0x00,
+        0x05, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+        0x08, 0x08, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08,
+        0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+        0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+        0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+        0x10, 0x10, 0x10, 0x26, 0x26, 0x26, 0x26, 0x26,
+        0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
+        0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
+        0x01,
+        0x15, 0x24, 0x24, 0x30, 0x2a, 0x30, 0x5e, 0x34,
+        0x34, 0x5e, 0xc6, 0x84, 0x70, 0x84, 0xc6, 0xc6,
+        0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+        0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+        0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+        0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+        0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+        0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+        },
+       {                       /* Quality 8 */
+        0x00,
+        0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+        0x0a, 0x0a, 0x14, 0x14, 0x14, 0x0a, 0x0a, 0x0a,
+        0x0a, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+        0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+        0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+        0x14, 0x14, 0x14, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
+        0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
+        0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
+        0x01,
+        0x19, 0x2d, 0x2d, 0x3c, 0x34, 0x3c, 0x75, 0x41,
+        0x41, 0x75, 0xf7, 0xa5, 0x8c, 0xa5, 0xf7, 0xf7,
+        0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+        0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+        0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+        0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+        0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+        0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+        },
+       {                       /* Quality 9 */
+        0x00,
+        0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+        0x0c, 0x0c, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c,
+        0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+        0x18, 0x18, 0x18, 0x39, 0x39, 0x39, 0x39, 0x39,
+        0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
+        0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
+        0x01,
+        0x19, 0x36, 0x36, 0x48, 0x3f, 0x48, 0x8d, 0x4e,
+        0x4e, 0x8d, 0xff, 0xc6, 0xa8, 0xc6, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        },
+       {                       /* Quality 10 */
+        0x00,
+        0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
+        0x0e, 0x0e, 0x1c, 0x1c, 0x1c, 0x0e, 0x0e, 0x0e,
+        0x0e, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+        0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+        0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+        0x1c, 0x1c, 0x1c, 0x42, 0x42, 0x42, 0x42, 0x42,
+        0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
+        0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
+        0x01,
+        0x1d, 0x3f, 0x3f, 0x54, 0x49, 0x54, 0xa4, 0x5b,
+        0x5b, 0xa4, 0xff, 0xe7, 0xc4, 0xe7, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        },
+       {                       /* Quality 11 */
+        0x00,
+        0x07, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+        0x10, 0x10, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10,
+        0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+        0x20, 0x20, 0x20, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
+        0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
+        0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
+        0x01,
+        0x1d, 0x48, 0x48, 0x60, 0x54, 0x60, 0xbc, 0x68,
+        0x68, 0xbc, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        },
+       {                       /* Quality 12 */
+        0x00,
+        0x08, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
+        0x14, 0x14, 0x28, 0x28, 0x28, 0x14, 0x14, 0x14,
+        0x14, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+        0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+        0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+        0x28, 0x28, 0x28, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+        0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+        0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
+        0x01,
+        0x22, 0x5a, 0x5a, 0x78, 0x69, 0x78, 0xeb, 0x82,
+        0x82, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        },
+       {                       /* Quality 13 */
+        0x00,
+        0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+        0x18, 0x18, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18,
+        0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+        0x30, 0x30, 0x30, 0x72, 0x72, 0x72, 0x72, 0x72,
+        0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+        0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
+        0x01,
+        0x22, 0x6c, 0x6c, 0x90, 0x7e, 0x90, 0xff, 0x9c,
+        0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        },
+       {                       /* Quality 14 */
+        0x00,
+        0x0a, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
+        0x1c, 0x1c, 0x38, 0x38, 0x38, 0x1c, 0x1c, 0x1c,
+        0x1c, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+        0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+        0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
+        0x38, 0x38, 0x38, 0x85, 0x85, 0x85, 0x85, 0x85,
+        0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+        0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
+        0x01,
+        0x2a, 0x7e, 0x7e, 0xa8, 0x93, 0xa8, 0xff, 0xb6,
+        0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        },
+       {                       /* Quality 15 */
+        0x00,
+        0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+        0x20, 0x20, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20,
+        0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+        0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+        0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+        0x40, 0x40, 0x40, 0x98, 0x98, 0x98, 0x98, 0x98,
+        0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+        0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
+        0x01,
+        0x2a, 0x90, 0x90, 0xc0, 0xa8, 0xc0, 0xff, 0xd0,
+        0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        },
+       {                       /* Quality 16-31 */
+        0x00,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x01,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+        }
+};
+
+static const struct cmd tp6810_cx_init_common[] = {
+       {0x1c, 0x00},
+       {TP6800_R10_SIF_TYPE, 0x00},
+       {0x4e, 0x00},
+       {0x4f, 0x00},
+       {TP6800_R50, 0xff},
+       {TP6800_R51, 0x03},
+       {0x00, 0x07},
+       {TP6800_R79_QUALITY, 0x03},
+       {TP6800_R2F_TIMING_CFG, 0x37},
+       {TP6800_R30_SENSOR_CFG, 0x10},
+       {TP6800_R21_ENDP_1_CTL, 0x00},
+       {TP6800_R52, 0x40},
+       {TP6800_R53, 0x40},
+       {TP6800_R54_DARK_CFG, 0x40},
+       {TP6800_R30_SENSOR_CFG, 0x18},
+       {0x4b, 0x00},
+       {TP6800_R3F_FRAME_RATE, 0x83},
+       {TP6800_R79_QUALITY, 0x05},
+       {TP6800_R21_ENDP_1_CTL, 0x00},
+       {0x7c, 0x04},
+       {0x25, 0x14},
+       {0x26, 0x0f},
+       {0x7b, 0x10},
+};
+
+static const struct cmd tp6810_ov_init_common[] = {
+       {0x1c, 0x00},
+       {TP6800_R10_SIF_TYPE, 0x00},
+       {0x4e, 0x00},
+       {0x4f, 0x00},
+       {TP6800_R50, 0xff},
+       {TP6800_R51, 0x03},
+       {0x00, 0x07},
+       {TP6800_R52, 0x40},
+       {TP6800_R53, 0x40},
+       {TP6800_R54_DARK_CFG, 0x40},
+       {TP6800_R79_QUALITY, 0x03},
+       {TP6800_R2F_TIMING_CFG, 0x17},
+       {TP6800_R30_SENSOR_CFG, 0x18},
+       {TP6800_R21_ENDP_1_CTL, 0x00},
+       {TP6800_R3F_FRAME_RATE, 0x86},
+       {0x25, 0x18},
+       {0x26, 0x0f},
+       {0x7b, 0x90},
+};
+
+static const struct cmd tp6810_bridge_start[] = {
+       {0x59, 0x88},
+       {0x5a, 0x0f},
+       {0x5b, 0x4e},
+       {TP6800_R5C_EDGE_THRLD, 0x63},
+       {TP6800_R5D_DEMOSAIC_CFG, 0x00},
+       {0x03, 0x7f},
+       {0x04, 0x80},
+       {0x06, 0x00},
+       {0x00, 0x00},
+};
+
+static const struct cmd tp6810_late_start[] = {
+       {0x7d, 0x01},
+       {0xb0, 0x04},
+       {0xb1, 0x04},
+       {0xb2, 0x04},
+       {0xb3, 0x04},
+       {0xb4, 0x04},
+       {0xb5, 0x04},
+       {0xb6, 0x08},
+       {0xb7, 0x08},
+       {0xb8, 0x04},
+       {0xb9, 0x04},
+       {0xba, 0x04},
+       {0xbb, 0x04},
+       {0xbc, 0x04},
+       {0xbd, 0x08},
+       {0xbe, 0x08},
+       {0xbf, 0x08},
+       {0xc0, 0x04},
+       {0xc1, 0x04},
+       {0xc2, 0x08},
+       {0xc3, 0x08},
+       {0xc4, 0x08},
+       {0xc5, 0x08},
+       {0xc6, 0x08},
+       {0xc7, 0x13},
+       {0xc8, 0x04},
+       {0xc9, 0x08},
+       {0xca, 0x08},
+       {0xcb, 0x08},
+       {0xcc, 0x08},
+       {0xcd, 0x08},
+       {0xce, 0x13},
+       {0xcf, 0x13},
+       {0xd0, 0x08},
+       {0xd1, 0x08},
+       {0xd2, 0x08},
+       {0xd3, 0x08},
+       {0xd4, 0x08},
+       {0xd5, 0x13},
+       {0xd6, 0x13},
+       {0xd7, 0x13},
+       {0xd8, 0x08},
+       {0xd9, 0x08},
+       {0xda, 0x08},
+       {0xdb, 0x08},
+       {0xdc, 0x13},
+       {0xdd, 0x13},
+       {0xde, 0x13},
+       {0xdf, 0x13},
+       {0xe0, 0x08},
+       {0xe1, 0x08},
+       {0xe2, 0x08},
+       {0xe3, 0x13},
+       {0xe4, 0x13},
+       {0xe5, 0x13},
+       {0xe6, 0x13},
+       {0xe7, 0x13},
+       {0xe8, 0x08},
+       {0xe9, 0x08},
+       {0xea, 0x13},
+       {0xeb, 0x13},
+       {0xec, 0x13},
+       {0xed, 0x13},
+       {0xee, 0x13},
+       {0xef, 0x13},
+       {0x7d, 0x02},
+
+       /* later after isoc start */
+       {0x7d, 0x08},
+       {0x7d, 0x00},
+};
+
+static const struct cmd cx0342_timing_seq[] = {
+       {CX0342_CHANNEL_0_1_L_irst, 0x20},
+       {CX0342_CHANNEL_0_2_L_irst, 0x24},
+       {CX0342_CHANNEL_0_2_H_irst, 0x00},
+       {CX0342_CHANNEL_0_3_L_irst, 0x2f},
+       {CX0342_CHANNEL_0_3_H_irst, 0x00},
+       {CX0342_CHANNEL_1_0_L_itx, 0x02},
+       {CX0342_CHANNEL_1_0_H_itx, 0x00},
+       {CX0342_CHANNEL_1_1_L_itx, 0x20},
+       {CX0342_CHANNEL_1_1_H_itx, 0x00},
+       {CX0342_CHANNEL_1_2_L_itx, 0xe4},
+       {CX0342_CHANNEL_1_2_H_itx, 0x00},
+       {CX0342_CHANNEL_1_3_L_itx, 0xee},
+       {CX0342_CHANNEL_1_3_H_itx, 0x00},
+       {CX0342_CHANNEL_2_0_L_iwl, 0x30},
+       {CX0342_CHANNEL_2_0_H_iwl, 0x00},
+       {CX0342_CHANNEL_3_0_L_ensp, 0x34},
+       {CX0342_CHANNEL_3_1_L_ensp, 0xe2},
+       {CX0342_CHANNEL_3_1_H_ensp, 0x00},
+       {CX0342_CHANNEL_3_2_L_ensp, 0xf6},
+       {CX0342_CHANNEL_3_2_H_ensp, 0x00},
+       {CX0342_CHANNEL_3_3_L_ensp, 0xf4},
+       {CX0342_CHANNEL_3_3_H_ensp, 0x02},
+       {CX0342_CHANNEL_4_0_L_sela, 0x26},
+       {CX0342_CHANNEL_4_0_H_sela, 0x00},
+       {CX0342_CHANNEL_4_1_L_sela, 0xe2},
+       {CX0342_CHANNEL_4_1_H_sela, 0x00},
+       {CX0342_CHANNEL_5_0_L_intla, 0x26},
+       {CX0342_CHANNEL_5_1_L_intla, 0x29},
+       {CX0342_CHANNEL_5_2_L_intla, 0xf0},
+       {CX0342_CHANNEL_5_2_H_intla, 0x00},
+       {CX0342_CHANNEL_5_3_L_intla, 0xf3},
+       {CX0342_CHANNEL_5_3_H_intla, 0x00},
+       {CX0342_CHANNEL_6_0_L_xa_sel_pos, 0x24},
+       {CX0342_CHANNEL_7_1_L_cds_pos, 0x02},
+       {CX0342_TIMING_EN, 0x01},
+};
+
+/* define the JPEG header */
+static void jpeg_define(u8 *jpeg_hdr,
+                       int height,
+                       int width)
+{
+       memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head);
+       jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8;
+       jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height;
+       jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8;
+       jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width;
+}
+
+/* set the JPEG quality for sensor soi763a */
+static void jpeg_set_qual(u8 *jpeg_hdr,
+                         int quality)
+{
+       int i, sc;
+
+       if (quality < 50)
+               sc = 5000 / quality;
+       else
+               sc = 200 - quality * 2;
+       for (i = 0; i < 64; i++) {
+               jpeg_hdr[JPEG_QT0_OFFSET + i] =
+                       (jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100;
+               jpeg_hdr[JPEG_QT1_OFFSET + i] =
+                       (jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100;
+       }
+}
+
+static void reg_w(struct gspca_dev *gspca_dev, u8 index, u8 value)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                       0x0e,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index, NULL, 0, 500);
+       if (ret < 0) {
+               pr_err("reg_w err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+/* the returned value is in gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev, u8 index)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                       0x0d,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0, index, gspca_dev->usb_buf, 1, 500);
+       if (ret < 0) {
+               pr_err("reg_r err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static void reg_w_buf(struct gspca_dev *gspca_dev,
+                       const struct cmd *p, int l)
+{
+       do {
+               reg_w(gspca_dev, p->reg, p->val);
+               p++;
+       } while (--l > 0);
+}
+
+static int i2c_w(struct gspca_dev *gspca_dev, u8 index, u8 value)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
+       reg_w(gspca_dev, TP6800_R19_SIF_ADDR_S2, index);
+       reg_w(gspca_dev, TP6800_R13_SIF_TX_DATA, value);
+       reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x01);
+       if (sd->bridge == BRIDGE_TP6800)
+               return 0;
+       msleep(5);
+       reg_r(gspca_dev, TP6800_R11_SIF_CONTROL);
+       if (gspca_dev->usb_buf[0] == 0)
+               return 0;
+       reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
+       return -1;                              /* error */
+}
+
+static void i2c_w_buf(struct gspca_dev *gspca_dev,
+                       const struct cmd *p, int l)
+{
+       do {
+               i2c_w(gspca_dev, p->reg, p->val);
+               p++;
+       } while (--l > 0);
+}
+
+static int i2c_r(struct gspca_dev *gspca_dev, u8 index, int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int v;
+
+       reg_w(gspca_dev, TP6800_R19_SIF_ADDR_S2, index);
+       reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x02);
+       msleep(5);
+       reg_r(gspca_dev, TP6800_R14_SIF_RX_DATA);
+       v = gspca_dev->usb_buf[0];
+       if (sd->bridge == BRIDGE_TP6800)
+               return v;
+       if (len > 1) {
+               reg_r(gspca_dev, TP6800_R1B_SIF_RX_DATA2);
+               v |= (gspca_dev->usb_buf[0] << 8);
+       }
+       reg_r(gspca_dev, TP6800_R11_SIF_CONTROL);
+       if (gspca_dev->usb_buf[0] == 0)
+               return v;
+       reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
+       return -1;
+}
+
+static void bulk_w(struct gspca_dev *gspca_dev,
+                 u8 tag,
+                 const u8 *data,
+                 int length)
+{
+       struct usb_device *dev = gspca_dev->dev;
+       int count, actual_count, ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       for (;;) {
+               count = length > BULK_OUT_SIZE - 1
+                               ? BULK_OUT_SIZE - 1 : length;
+               gspca_dev->usb_buf[0] = tag;
+               memcpy(&gspca_dev->usb_buf[1], data, count);
+               ret = usb_bulk_msg(dev,
+                                  usb_sndbulkpipe(dev, 3),
+                                  gspca_dev->usb_buf, count + 1,
+                                  &actual_count, 500);
+               if (ret < 0) {
+                       pr_err("bulk write error %d tag=%02x\n",
+                               ret, tag);
+                       gspca_dev->usb_err = ret;
+                       return;
+               }
+               length -= count;
+               if (length <= 0)
+                       break;
+               data += count;
+       }
+}
+
+static int probe_6810(struct gspca_dev *gspca_dev)
+{
+       u8 gpio;
+       int ret;
+
+       reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
+       gpio = gspca_dev->usb_buf[0];
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+       reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x04);    /* i2c 16 bits */
+       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x21);  /* ov??? */
+       reg_w(gspca_dev, TP6800_R1A_SIF_TX_DATA2, 0x00);
+       if (i2c_w(gspca_dev, 0x00, 0x00) >= 0)
+               return SENSOR_SOI763A;
+
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+       reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00);    /* i2c 8 bits */
+       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x7f);  /* (unknown i2c) */
+       if (i2c_w(gspca_dev, 0x00, 0x00) >= 0)
+               return -2;
+
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+       reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00);    /* i2c 8 bits */
+       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x11);  /* tas??? / hv??? */
+       ret = i2c_r(gspca_dev, 0x00, 1);
+       if (ret > 0)
+               return -3;
+
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x6e);  /* po??? */
+       ret = i2c_r(gspca_dev, 0x00, 1);
+       if (ret > 0)
+               return -4;
+
+       ret = i2c_r(gspca_dev, 0x01, 1);
+       if (ret > 0)
+               return -5;
+
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+       reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x04);    /* i2c 16 bits */
+       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x5d);  /* mi/mt??? */
+       ret = i2c_r(gspca_dev, 0x00, 2);
+       if (ret > 0)
+               return -6;
+
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x5c);  /* mi/mt??? */
+       ret = i2c_r(gspca_dev, 0x36, 2);
+       if (ret > 0)
+               return -7;
+
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x61);  /* (unknown i2c) */
+       reg_w(gspca_dev, TP6800_R1A_SIF_TX_DATA2, 0x10);
+       if (i2c_w(gspca_dev, 0xff, 0x00) >= 0)
+               return -8;
+
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
+       reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00);    /* i2c 8 bits */
+       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20);  /* cx0342 */
+       ret = i2c_r(gspca_dev, 0x00, 1);
+       if (ret > 0)
+               return SENSOR_CX0342;
+       return -9;
+}
+
+static void cx0342_6810_init(struct gspca_dev *gspca_dev)
+{
+       static const struct cmd reg_init_1[] = {
+               {TP6800_R2F_TIMING_CFG, 0x2f},
+               {0x25, 0x02},
+               {TP6800_R21_ENDP_1_CTL, 0x00},
+               {TP6800_R3F_FRAME_RATE, 0x80},
+               {TP6800_R2F_TIMING_CFG, 0x2f},
+               {TP6800_R18_GPIO_DATA, 0xe1},
+               {TP6800_R18_GPIO_DATA, 0xc1},
+               {TP6800_R18_GPIO_DATA, 0xe1},
+               {TP6800_R11_SIF_CONTROL, 0x00},
+       };
+       static const struct cmd reg_init_2[] = {
+               {TP6800_R78_FORMAT, 0x48},
+               {TP6800_R11_SIF_CONTROL, 0x00},
+       };
+       static const struct cmd sensor_init[] = {
+               {CX0342_OUTPUT_CTRL, 0x07},
+               {CX0342_BYPASS_MODE, 0x58},
+               {CX0342_GPXLTHD_L, 0x28},
+               {CX0342_RBPXLTHD_L, 0x28},
+               {CX0342_PLANETHD_L, 0x50},
+               {CX0342_PLANETHD_H, 0x03},
+               {CX0342_RB_GAP_L, 0xff},
+               {CX0342_RB_GAP_H, 0x07},
+               {CX0342_G_GAP_L, 0xff},
+               {CX0342_G_GAP_H, 0x07},
+               {CX0342_RST_OVERFLOW_L, 0x5c},
+               {CX0342_RST_OVERFLOW_H, 0x01},
+               {CX0342_DATA_OVERFLOW_L, 0xfc},
+               {CX0342_DATA_OVERFLOW_H, 0x03},
+               {CX0342_DATA_UNDERFLOW_L, 0x00},
+               {CX0342_DATA_UNDERFLOW_H, 0x00},
+               {CX0342_SYS_CTRL_0, 0x40},
+               {CX0342_GLOBAL_GAIN, 0x01},
+               {CX0342_CLOCK_GEN, 0x00},
+               {CX0342_SYS_CTRL_0, 0x02},
+               {CX0342_IDLE_CTRL, 0x05},
+               {CX0342_ADCGN, 0x00},
+               {CX0342_ADC_CTL, 0x00},
+               {CX0342_LVRST_BLBIAS, 0x01},
+               {CX0342_VTHSEL, 0x0b},
+               {CX0342_RAMP_RIV, 0x0b},
+               {CX0342_LDOSEL, 0x07},
+               {CX0342_SPV_VALUE_L, 0x40},
+               {CX0342_SPV_VALUE_H, 0x02},
+
+               {CX0342_AUTO_ADC_CALIB, 0x81},
+               {CX0342_TIMING_EN, 0x01},
+       };
+
+       reg_w_buf(gspca_dev, reg_init_1, ARRAY_SIZE(reg_init_1));
+       reg_w_buf(gspca_dev, tp6810_cx_init_common,
+                       ARRAY_SIZE(tp6810_cx_init_common));
+       reg_w_buf(gspca_dev, reg_init_2, ARRAY_SIZE(reg_init_2));
+
+       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20);  /* cx0342 I2C addr */
+       i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+       i2c_w_buf(gspca_dev, cx0342_timing_seq, ARRAY_SIZE(cx0342_timing_seq));
+}
+
+static void soi763a_6810_init(struct gspca_dev *gspca_dev)
+{
+       static const struct cmd reg_init_1[] = {
+               {TP6800_R2F_TIMING_CFG, 0x2f},
+               {TP6800_R18_GPIO_DATA, 0xe1},
+               {0x25, 0x02},
+               {TP6800_R21_ENDP_1_CTL, 0x00},
+               {TP6800_R3F_FRAME_RATE, 0x80},
+               {TP6800_R2F_TIMING_CFG, 0x2f},
+               {TP6800_R18_GPIO_DATA, 0xc1},
+       };
+       static const struct cmd reg_init_2[] = {
+               {TP6800_R78_FORMAT, 0x54},
+       };
+       static const struct cmd sensor_init[] = {
+               {0x00, 0x00},
+               {0x01, 0x80},
+               {0x02, 0x80},
+               {0x03, 0x90},
+               {0x04, 0x20},
+               {0x05, 0x20},
+               {0x06, 0x80},
+               {0x07, 0x00},
+               {0x08, 0xff},
+               {0x09, 0xff},
+               {0x0a, 0x76},           /* 7630 = soi673a */
+               {0x0b, 0x30},
+               {0x0c, 0x20},
+               {0x0d, 0x20},
+               {0x0e, 0xff},
+               {0x0f, 0xff},
+               {0x10, 0x41},
+               {0x15, 0x14},
+               {0x11, 0x40},
+               {0x12, 0x48},
+               {0x13, 0x80},
+               {0x14, 0x80},
+               {0x16, 0x03},
+               {0x28, 0xb0},
+               {0x71, 0x20},
+               {0x75, 0x8e},
+               {0x17, 0x1b},
+               {0x18, 0xbd},
+               {0x19, 0x05},
+               {0x1a, 0xf6},
+               {0x1b, 0x04},
+               {0x1c, 0x7f},           /* omnivision */
+               {0x1d, 0xa2},
+               {0x1e, 0x00},
+               {0x1f, 0x00},
+               {0x20, 0x45},
+               {0x21, 0x80},
+               {0x22, 0x80},
+               {0x23, 0xee},
+               {0x24, 0x50},
+               {0x25, 0x7a},
+               {0x26, 0xa0},
+               {0x27, 0x9a},
+               {0x29, 0x30},
+               {0x2a, 0x80},
+               {0x2b, 0x00},
+               {0x2c, 0xac},
+               {0x2d, 0x05},
+               {0x2e, 0x80},
+               {0x2f, 0x3c},
+               {0x30, 0x22},
+               {0x31, 0x00},
+               {0x32, 0x86},
+               {0x33, 0x08},
+               {0x34, 0xff},
+               {0x35, 0xff},
+               {0x36, 0xff},
+               {0x37, 0xff},
+               {0x38, 0xff},
+               {0x39, 0xff},
+               {0x3a, 0xfe},
+               {0x3b, 0xfe},
+               {0x3c, 0xfe},
+               {0x3d, 0xfe},
+               {0x3e, 0xfe},
+               {0x3f, 0x71},
+               {0x40, 0xff},
+               {0x41, 0xff},
+               {0x42, 0xff},
+               {0x43, 0xff},
+               {0x44, 0xff},
+               {0x45, 0xff},
+               {0x46, 0xff},
+               {0x47, 0xff},
+               {0x48, 0xff},
+               {0x49, 0xff},
+               {0x4a, 0xfe},
+               {0x4b, 0xff},
+               {0x4c, 0x00},
+               {0x4d, 0x00},
+               {0x4e, 0xff},
+               {0x4f, 0xff},
+               {0x50, 0xff},
+               {0x51, 0xff},
+               {0x52, 0xff},
+               {0x53, 0xff},
+               {0x54, 0xff},
+               {0x55, 0xff},
+               {0x56, 0xff},
+               {0x57, 0xff},
+               {0x58, 0xff},
+               {0x59, 0xff},
+               {0x5a, 0xff},
+               {0x5b, 0xfe},
+               {0x5c, 0xff},
+               {0x5d, 0x8f},
+               {0x5e, 0xff},
+               {0x5f, 0x8f},
+               {0x60, 0xa2},
+               {0x61, 0x4a},
+               {0x62, 0xf3},
+               {0x63, 0x75},
+               {0x64, 0xf0},
+               {0x65, 0x00},
+               {0x66, 0x55},
+               {0x67, 0x92},
+               {0x68, 0xa0},
+               {0x69, 0x4a},
+               {0x6a, 0x22},
+               {0x6b, 0x00},
+               {0x6c, 0x33},
+               {0x6d, 0x44},
+               {0x6e, 0x22},
+               {0x6f, 0x84},
+               {0x70, 0x0b},
+               {0x72, 0x10},
+               {0x73, 0x50},
+               {0x74, 0x21},
+               {0x76, 0x00},
+               {0x77, 0xa5},
+               {0x78, 0x80},
+               {0x79, 0x80},
+               {0x7a, 0x80},
+               {0x7b, 0xe2},
+               {0x7c, 0x00},
+               {0x7d, 0xf7},
+               {0x7e, 0x00},
+               {0x7f, 0x00},
+       };
+
+       reg_w_buf(gspca_dev, reg_init_1, ARRAY_SIZE(reg_init_1));
+       reg_w_buf(gspca_dev, tp6810_ov_init_common,
+                       ARRAY_SIZE(tp6810_ov_init_common));
+       reg_w_buf(gspca_dev, reg_init_2, ARRAY_SIZE(reg_init_2));
+
+       i2c_w(gspca_dev, 0x12, 0x80);           /* sensor reset */
+       msleep(10);
+       i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+}
+
+/* set the gain and exposure */
+static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 gain,
+                                                       s32 blue, s32 red)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor == SENSOR_CX0342) {
+               expo = (expo << 2) - 1;
+               i2c_w(gspca_dev, CX0342_EXPO_LINE_L, expo);
+               i2c_w(gspca_dev, CX0342_EXPO_LINE_H, expo >> 8);
+               if (sd->bridge == BRIDGE_TP6800)
+                       i2c_w(gspca_dev, CX0342_RAW_GBGAIN_H,
+                                               gain >> 8);
+               i2c_w(gspca_dev, CX0342_RAW_GBGAIN_L, gain);
+               if (sd->bridge == BRIDGE_TP6800)
+                       i2c_w(gspca_dev, CX0342_RAW_GRGAIN_H,
+                                       gain >> 8);
+               i2c_w(gspca_dev, CX0342_RAW_GRGAIN_L, gain);
+               if (sd->sensor == SENSOR_CX0342) {
+                       if (sd->bridge == BRIDGE_TP6800)
+                               i2c_w(gspca_dev, CX0342_RAW_BGAIN_H,
+                                               blue >> 8);
+                       i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, blue);
+                       if (sd->bridge == BRIDGE_TP6800)
+                               i2c_w(gspca_dev, CX0342_RAW_RGAIN_H,
+                                               red >> 8);
+                       i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, red);
+               }
+               i2c_w(gspca_dev, CX0342_SYS_CTRL_0,
+                               sd->bridge == BRIDGE_TP6800 ? 0x80 : 0x81);
+               return;
+       }
+
+       /* soi763a */
+       i2c_w(gspca_dev, 0x10,          /* AEC_H (exposure time) */
+                        expo);
+/*     i2c_w(gspca_dev, 0x76, 0x02);    * AEC_L ([1:0] */
+       i2c_w(gspca_dev, 0x00,          /* gain */
+                        gain);
+}
+
+/* set the JPEG quantization tables */
+static void set_dqt(struct gspca_dev *gspca_dev, u8 q)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* update the jpeg quantization tables */
+       PDEBUG(D_STREAM, "q %d -> %d", sd->quality, q);
+       sd->quality = q;
+       if (q > 16)
+               q = 16;
+       if (sd->sensor == SENSOR_SOI763A)
+               jpeg_set_qual(sd->jpeg_hdr, jpeg_q[q]);
+       else
+               memcpy(&sd->jpeg_hdr[JPEG_QT0_OFFSET - 1],
+                       DQT[q], sizeof DQT[0]);
+}
+
+/* set the JPEG compression quality factor */
+static void setquality(struct gspca_dev *gspca_dev, s32 q)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (q != 16)
+               q = 15 - q;
+
+       reg_w(gspca_dev, TP6800_R7A_BLK_THRLD, 0x00);
+       reg_w(gspca_dev, TP6800_R79_QUALITY, 0x04);
+       reg_w(gspca_dev, TP6800_R79_QUALITY, q);
+
+       /* auto quality */
+       if (q == 15 && sd->bridge == BRIDGE_TP6810) {
+               msleep(4);
+               reg_w(gspca_dev, TP6800_R7A_BLK_THRLD, 0x19);
+       }
+}
+
+static const u8 color_null[18] = {
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+static const u8 color_gain[NSENSORS][18] = {
+[SENSOR_CX0342] =
+       {0x4c, 0x00, 0xa9, 0x00, 0x31, 0x00,    /* Y R/G/B (LE values) */
+        0xb6, 0x03, 0x6c, 0x03, 0xe0, 0x00,    /* U R/G/B */
+        0xdf, 0x00, 0x46, 0x03, 0xdc, 0x03},   /* V R/G/B */
+[SENSOR_SOI763A] =
+       {0x4c, 0x00, 0x95, 0x00, 0x1d, 0x00,    /* Y R/G/B (LE values) */
+        0xb6, 0x03, 0x6c, 0x03, 0xd7, 0x00,    /* U R/G/B */
+        0xd5, 0x00, 0x46, 0x03, 0xdc, 0x03},   /* V R/G/B */
+};
+
+static void setgamma(struct gspca_dev *gspca_dev, s32 gamma)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+#define NGAMMA 6
+       static const u8 gamma_tb[NGAMMA][3][1024] = {
+           {                           /* gamma 0 - from tp6800 + soi763a */
+               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+                0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
+                0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
+                0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
+                0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+                0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
+                0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
+                0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
+                0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
+                0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
+                0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
+                0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
+                0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
+                0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
+                0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
+                0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
+                0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
+                0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
+                0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+                0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
+                0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+                0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
+                0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
+                0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
+                0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+                0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+                0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
+                0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
+                0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
+                0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+                0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+                0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
+                0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+                0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+                0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+                0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
+                0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
+                0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
+                0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+                0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
+                0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
+                0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+                0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+                0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+                0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+                0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
+                0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
+                0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+                0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
+                0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+                0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+                0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+                0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
+                0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+                0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+                0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+                0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+                0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+                0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+                0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+                0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+                0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+                0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+                0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+                0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+                0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+                0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+                0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+                0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
+                0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+                0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+                0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
+                0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+                0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
+                0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+                0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+                0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+                0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+                0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+                0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+                0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+                0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+                0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+                0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
+                0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+                0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+                0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+                0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+                0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+                0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+                0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+                0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+                0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+                0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+                0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
+                0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
+                0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
+                0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+                0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
+                0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
+                0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
+                0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
+                0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
+                0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
+                0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
+                0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
+                0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
+                0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
+                0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
+                0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
+                0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
+                0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+                0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
+                0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+                0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
+                0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
+                0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
+                0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+                0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+                0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
+                0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
+                0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
+                0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+                0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+                0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
+                0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+                0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+                0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+                0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
+                0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
+                0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
+                0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+                0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
+                0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
+                0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+                0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+                0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+                0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+                0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
+                0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
+                0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+                0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
+                0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+                0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+                0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+                0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
+                0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+                0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+                0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+                0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+                0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+                0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+                0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+                0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+                0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+                0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+                0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+                0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+                0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+                0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+                0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+                0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
+                0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+                0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+                0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
+                0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+                0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
+                0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+                0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+                0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+                0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+                0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+                0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+                0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+                0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+                0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+                0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
+                0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+                0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+                0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+                0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+                0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+                0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+                0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+                0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+                0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+                0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+                0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
+                0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
+                0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
+                0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+                0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
+                0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
+                0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
+                0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
+                0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
+                0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
+                0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
+                0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
+                0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
+                0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
+                0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
+                0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
+                0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
+                0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+                0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
+                0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
+                0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
+                0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
+                0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
+                0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+                0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+                0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
+                0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x76,
+                0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
+                0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+                0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+                0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
+                0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+                0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+                0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+                0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
+                0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
+                0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
+                0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+                0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
+                0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
+                0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+                0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+                0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+                0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+                0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
+                0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
+                0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+                0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
+                0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+                0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+                0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+                0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
+                0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+                0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+                0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+                0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+                0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+                0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+                0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+                0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+                0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+                0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+                0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+                0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+                0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+                0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+                0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+                0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
+                0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+                0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+                0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
+                0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+                0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
+                0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+                0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+                0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+                0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+                0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+                0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+                0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+                0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+                0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+                0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
+                0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+                0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+                0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+                0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+                0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+                0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+                0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+                0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+                0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+                0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
+           },
+           {                           /* gamma 1 - from tp6810 + soi763a */
+               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x01, 0x02, 0x03, 0x05, 0x07, 0x08, 0x09, 0x0a,
+                0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15,
+                0x16, 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1c, 0x1e,
+                0x1f, 0x20, 0x22, 0x22, 0x23, 0x25, 0x26, 0x27,
+                0x27, 0x28, 0x29, 0x2b, 0x2b, 0x2c, 0x2d, 0x2f,
+                0x2f, 0x30, 0x31, 0x33, 0x33, 0x34, 0x35, 0x35,
+                0x37, 0x38, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c,
+                0x3c, 0x3d, 0x3f, 0x3f, 0x40, 0x42, 0x42, 0x43,
+                0x43, 0x44, 0x45, 0x45, 0x47, 0x47, 0x48, 0x49,
+                0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d,
+                0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
+                0x54, 0x54, 0x55, 0x56, 0x56, 0x58, 0x58, 0x59,
+                0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5e,
+                0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x61,
+                0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x65, 0x66,
+                0x66, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69, 0x69,
+                0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
+                0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71,
+                0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75,
+                0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79,
+                0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c,
+                0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x80,
+                0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x84, 0x84,
+                0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x88,
+                0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a,
+                0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e,
+                0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91,
+                0x91, 0x91, 0x92, 0x92, 0x92, 0x92, 0x93, 0x93,
+                0x93, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x97,
+                0x97, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
+                0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b,
+                0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9e,
+                0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
+                0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3,
+                0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5,
+                0xa5, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+                0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xab,
+                0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xae,
+                0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0,
+                0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+                0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4,
+                0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
+                0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
+                0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
+                0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
+                0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+                0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
+                0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4,
+                0xc4, 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6,
+                0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7,
+                0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+                0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
+                0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+                0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+                0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
+                0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4,
+                0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+                0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+                0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda,
+                0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb,
+                0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+                0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
+                0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
+                0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+                0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+                0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+                0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8,
+                0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9,
+                0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec,
+                0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed,
+                0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+                0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+                0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3,
+                0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
+                0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
+                0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+                0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
+                0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+                0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe,
+                0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
+                0x05, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0c, 0x0d,
+                0x0e, 0x10, 0x10, 0x11, 0x12, 0x14, 0x15, 0x15,
+                0x16, 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1c, 0x1e,
+                0x1e, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x25, 0x25,
+                0x26, 0x27, 0x27, 0x28, 0x29, 0x29, 0x2b, 0x2c,
+                0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x30, 0x31, 0x31,
+                0x33, 0x34, 0x34, 0x35, 0x35, 0x37, 0x38, 0x38,
+                0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d,
+                0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x42, 0x43,
+                0x43, 0x44, 0x44, 0x45, 0x45, 0x47, 0x47, 0x48,
+                0x48, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c,
+                0x4c, 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50,
+                0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x55,
+                0x55, 0x56, 0x56, 0x56, 0x58, 0x58, 0x59, 0x59,
+                0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c,
+                0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60,
+                0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x65,
+                0x65, 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67,
+                0x68, 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a,
+                0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e,
+                0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
+                0x71, 0x71, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74,
+                0x75, 0x75, 0x75, 0x77, 0x77, 0x77, 0x78, 0x78,
+                0x78, 0x79, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a,
+                0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d,
+                0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80,
+                0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
+                0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
+                0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89, 0x89,
+                0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b,
+                0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e,
+                0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
+                0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
+                0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+                0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97,
+                0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
+                0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b,
+                0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
+                0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0,
+                0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+                0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
+                0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
+                0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
+                0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab,
+                0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+                0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
+                0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+                0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+                0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+                0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
+                0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
+                0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+                0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
+                0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
+                0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf,
+                0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+                0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
+                0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
+                0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
+                0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9,
+                0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+                0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
+                0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd,
+                0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xcf,
+                0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+                0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+                0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4,
+                0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+                0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8,
+                0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9,
+                0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb,
+                0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+                0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
+                0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+                0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2,
+                0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3,
+                0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+                0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+                0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+                0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
+                0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+                0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
+                0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+                0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+                0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
+                0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4,
+                0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5,
+                0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7,
+                0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8,
+                0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
+                0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+                0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe,
+                0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x01, 0x02, 0x03, 0x05, 0x05, 0x07,
+                0x08, 0x09, 0x0a, 0x0a, 0x0c, 0x0d, 0x0e, 0x0e,
+                0x10, 0x11, 0x12, 0x12, 0x14, 0x15, 0x16, 0x16,
+                0x17, 0x18, 0x18, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
+                0x1e, 0x1f, 0x1f, 0x20, 0x22, 0x22, 0x23, 0x23,
+                0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x29, 0x29,
+                0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f, 0x30,
+                0x30, 0x31, 0x31, 0x33, 0x33, 0x34, 0x34, 0x35,
+                0x35, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x3a,
+                0x3a, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d,
+                0x3f, 0x3f, 0x40, 0x40, 0x42, 0x42, 0x42, 0x43,
+                0x43, 0x44, 0x44, 0x45, 0x45, 0x47, 0x47, 0x47,
+                0x48, 0x48, 0x49, 0x49, 0x49, 0x4a, 0x4a, 0x4b,
+                0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4f,
+                0x4f, 0x50, 0x50, 0x50, 0x52, 0x52, 0x52, 0x53,
+                0x53, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x56,
+                0x56, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x5a,
+                0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c,
+                0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60,
+                0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63,
+                0x63, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x66,
+                0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69,
+                0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
+                0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e,
+                0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
+                0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x74, 0x74,
+                0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x77, 0x77,
+                0x77, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79,
+                0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b,
+                0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
+                0x7d, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80,
+                0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82,
+                0x82, 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85,
+                0x85, 0x86, 0x86, 0x86, 0x86, 0x88, 0x88, 0x88,
+                0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a,
+                0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d,
+                0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
+                0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
+                0x90, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92,
+                0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94, 0x94,
+                0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96, 0x96,
+                0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
+                0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+                0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
+                0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
+                0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0,
+                0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1,
+                0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3,
+                0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
+                0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6,
+                0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
+                0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab,
+                0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac,
+                0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae,
+                0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
+                0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+                0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2,
+                0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4,
+                0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6,
+                0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
+                0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
+                0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba,
+                0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+                0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
+                0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+                0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
+                0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3,
+                0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
+                0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
+                0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+                0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+                0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb,
+                0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
+                0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce,
+                0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+                0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
+                0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
+                0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
+                0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7,
+                0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+                0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9,
+                0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+                0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+                0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
+                0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0,
+                0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
+                0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3,
+                0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4,
+                0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
+                0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7,
+                0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
+                0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb,
+                0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+                0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee,
+                0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, 0xef,
+                0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1,
+                0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3,
+                0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5,
+                0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+                0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
+                0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc,
+                0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd,
+                0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+           },
+           {                                                   /* gamma 2 */
+               {0x00, 0x01, 0x02, 0x05, 0x07, 0x08, 0x0a, 0x0c,
+                0x0d, 0x0e, 0x10, 0x12, 0x14, 0x15, 0x16, 0x17,
+                0x18, 0x1a, 0x1b, 0x1c, 0x1e, 0x1f, 0x20, 0x22,
+                0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2c,
+                0x2d, 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x34,
+                0x35, 0x37, 0x38, 0x38, 0x39, 0x3a, 0x3b, 0x3b,
+                0x3c, 0x3d, 0x3f, 0x3f, 0x40, 0x42, 0x42, 0x43,
+                0x44, 0x44, 0x45, 0x47, 0x47, 0x48, 0x49, 0x49,
+                0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4f, 0x4f,
+                0x50, 0x50, 0x52, 0x53, 0x53, 0x54, 0x54, 0x55,
+                0x55, 0x56, 0x56, 0x58, 0x58, 0x59, 0x5a, 0x5a,
+                0x5b, 0x5b, 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f,
+                0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x63, 0x63,
+                0x65, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
+                0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
+                0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x70,
+                0x70, 0x70, 0x71, 0x71, 0x73, 0x73, 0x73, 0x74,
+                0x74, 0x75, 0x75, 0x75, 0x77, 0x77, 0x78, 0x78,
+                0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b,
+                0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f,
+                0x7f, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82,
+                0x82, 0x82, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85,
+                0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x89, 0x89,
+                0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8d,
+                0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f,
+                0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+                0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94,
+                0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+                0x97, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99,
+                0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b,
+                0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
+                0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1,
+                0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3,
+                0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5,
+                0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8,
+                0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+                0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad,
+                0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
+                0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0,
+                0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2,
+                0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4,
+                0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
+                0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
+                0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba,
+                0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
+                0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
+                0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0,
+                0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3,
+                0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4,
+                0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6,
+                0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7,
+                0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+                0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb,
+                0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+                0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce,
+                0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0,
+                0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1,
+                0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4,
+                0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
+                0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
+                0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+                0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda,
+                0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd,
+                0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde,
+                0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
+                0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1,
+                0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+                0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4,
+                0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5,
+                0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
+                0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8,
+                0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9,
+                0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+                0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed,
+                0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+                0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+                0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1,
+                0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
+                0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
+                0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+                0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+                0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9,
+                0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+               {0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x05,
+                0x07, 0x08, 0x09, 0x0a, 0x0d, 0x0e, 0x10, 0x11,
+                0x12, 0x14, 0x15, 0x16, 0x16, 0x17, 0x18, 0x1a,
+                0x1b, 0x1c, 0x1e, 0x1f, 0x20, 0x20, 0x22, 0x23,
+                0x25, 0x26, 0x26, 0x27, 0x28, 0x29, 0x29, 0x2b,
+                0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x30, 0x31, 0x33,
+                0x33, 0x34, 0x35, 0x35, 0x37, 0x38, 0x38, 0x39,
+                0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3d, 0x3f,
+                0x3f, 0x40, 0x42, 0x42, 0x43, 0x43, 0x44, 0x44,
+                0x45, 0x45, 0x47, 0x47, 0x48, 0x48, 0x49, 0x4a,
+                0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d,
+                0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
+                0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x58,
+                0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
+                0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f,
+                0x60, 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x63,
+                0x63, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x67,
+                0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69,
+                0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d,
+                0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
+                0x70, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x73,
+                0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77, 0x77,
+                0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79,
+                0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7b, 0x7c,
+                0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7f, 0x7f,
+                0x7f, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81,
+                0x82, 0x82, 0x82, 0x82, 0x84, 0x84, 0x84, 0x84,
+                0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x88,
+                0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a,
+                0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d,
+                0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f,
+                0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x91,
+                0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
+                0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+                0x94, 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+                0x97, 0x98, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99,
+                0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b,
+                0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9c,
+                0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e,
+                0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1,
+                0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2,
+                0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+                0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+                0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
+                0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+                0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac,
+                0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae,
+                0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf,
+                0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1,
+                0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2,
+                0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
+                0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6,
+                0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
+                0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9,
+                0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
+                0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
+                0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe,
+                0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf,
+                0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+                0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
+                0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4,
+                0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
+                0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7,
+                0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
+                0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
+                0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
+                0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+                0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+                0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
+                0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1,
+                0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
+                0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+                0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+                0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
+                0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
+                0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
+                0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
+                0xdb, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+                0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf,
+                0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0,
+                0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1,
+                0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+                0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
+                0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+                0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6,
+                0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+                0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
+                0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+                0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+                0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+                0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xef,
+                0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+                0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
+                0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4,
+                0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5,
+                0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
+                0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+                0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9,
+                0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+               {0x00, 0x00, 0x00, 0x01, 0x02, 0x05, 0x07, 0x08,
+                0x09, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x12, 0x14,
+                0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1e,
+                0x1f, 0x20, 0x20, 0x22, 0x23, 0x25, 0x26, 0x27,
+                0x28, 0x28, 0x29, 0x2b, 0x2c, 0x2d, 0x2d, 0x2f,
+                0x30, 0x31, 0x31, 0x33, 0x34, 0x35, 0x35, 0x37,
+                0x38, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3c,
+                0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x43, 0x43,
+                0x44, 0x44, 0x45, 0x47, 0x47, 0x48, 0x48, 0x49,
+                0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d,
+                0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
+                0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58,
+                0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c,
+                0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
+                0x61, 0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65,
+                0x65, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68,
+                0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
+                0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f,
+                0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x73, 0x73,
+                0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
+                0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x7a,
+                0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c,
+                0x7c, 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80,
+                0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82,
+                0x82, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85,
+                0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
+                0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b,
+                0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e,
+                0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90,
+                0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
+                0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
+                0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97,
+                0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
+                0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b,
+                0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
+                0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0,
+                0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+                0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
+                0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
+                0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
+                0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+                0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac,
+                0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
+                0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0,
+                0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1,
+                0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3,
+                0xb3, 0xb3, 0xb3, 0xb4, 0xb3, 0xb4, 0xb4, 0xb4,
+                0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+                0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
+                0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+                0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
+                0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe,
+                0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
+                0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
+                0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
+                0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
+                0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
+                0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+                0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+                0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb,
+                0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
+                0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce,
+                0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+                0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
+                0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
+                0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+                0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
+                0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8,
+                0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9,
+                0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda,
+                0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
+                0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+                0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
+                0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
+                0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+                0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3,
+                0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+                0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6,
+                0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
+                0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
+                0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9,
+                0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec,
+                0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed,
+                0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+                0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+                0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1,
+                0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3,
+                0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
+                0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
+                0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7,
+                0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+                0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
+           },
+           {                           /* gamma 3 - from tp6810 + cx0342 */
+               {0x08, 0x09, 0x0c, 0x0d, 0x10, 0x11, 0x14, 0x15,
+                0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x1f, 0x20, 0x23,
+                0x25, 0x26, 0x27, 0x28, 0x2b, 0x2c, 0x2d, 0x2f,
+                0x30, 0x31, 0x33, 0x34, 0x35, 0x37, 0x38, 0x39,
+                0x3a, 0x3b, 0x3c, 0x3d, 0x3f, 0x40, 0x42, 0x43,
+                0x44, 0x45, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b,
+                0x4c, 0x4d, 0x4d, 0x4f, 0x50, 0x52, 0x53, 0x53,
+                0x54, 0x55, 0x56, 0x56, 0x58, 0x59, 0x5a, 0x5a,
+                0x5b, 0x5c, 0x5c, 0x5e, 0x5f, 0x5f, 0x60, 0x61,
+                0x61, 0x62, 0x63, 0x63, 0x65, 0x66, 0x66, 0x67,
+                0x68, 0x68, 0x69, 0x69, 0x6a, 0x6c, 0x6c, 0x6d,
+                0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x73,
+                0x73, 0x74, 0x74, 0x75, 0x75, 0x77, 0x77, 0x78,
+                0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c,
+                0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81,
+                0x82, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
+                0x86, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b,
+                0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f,
+                0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92, 0x93,
+                0x93, 0x93, 0x94, 0x94, 0x96, 0x96, 0x97, 0x97,
+                0x97, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+                0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d,
+                0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
+                0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+                0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa8, 0xa8,
+                0xa8, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac,
+                0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
+                0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+                0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3,
+                0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+                0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
+                0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
+                0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf,
+                0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2,
+                0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5,
+                0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
+                0xc7, 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+                0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
+                0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce,
+                0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+                0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3,
+                0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6,
+                0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+                0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda,
+                0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd,
+                0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf,
+                0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1,
+                0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+                0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4,
+                0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+                0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8,
+                0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb,
+                0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+                0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
+                0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
+                0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
+                0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
+                0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
+                0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+                0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
+                0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+                0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
+                0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               {0x03, 0x05, 0x07, 0x09, 0x0a, 0x0c, 0x0d, 0x10,
+                0x11, 0x12, 0x14, 0x15, 0x17, 0x18, 0x1a, 0x1b,
+                0x1c, 0x1e, 0x1f, 0x20, 0x22, 0x23, 0x25, 0x26,
+                0x27, 0x28, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2f,
+                0x30, 0x31, 0x33, 0x33, 0x34, 0x35, 0x37, 0x38,
+                0x38, 0x39, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3f,
+                0x3f, 0x40, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45,
+                0x47, 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4b,
+                0x4c, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52,
+                0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, 0x58,
+                0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c,
+                0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
+                0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x66,
+                0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69,
+                0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e,
+                0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71,
+                0x71, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75,
+                0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79,
+                0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c,
+                0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80,
+                0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x84,
+                0x84, 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86,
+                0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a,
+                0x8a, 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e,
+                0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90,
+                0x90, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92,
+                0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x96,
+                0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x98, 0x98,
+                0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a,
+                0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c,
+                0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e,
+                0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1,
+                0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3,
+                0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
+                0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
+                0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
+                0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad,
+                0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf,
+                0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1,
+                0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
+                0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4,
+                0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+                0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9,
+                0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
+                0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+                0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+                0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0,
+                0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3,
+                0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4,
+                0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
+                0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+                0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
+                0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb,
+                0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+                0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+                0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0,
+                0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1,
+                0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4,
+                0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6,
+                0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
+                0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
+                0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
+                0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
+                0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+                0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
+                0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1,
+                0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2,
+                0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
+                0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
+                0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+                0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+                0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
+                0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
+                0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec,
+                0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee,
+                0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+                0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+                0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+                0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
+                0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
+                0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+                0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
+                0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
+                0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc,
+                0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+                0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe,
+                0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               {0x07, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14,
+                0x16, 0x17, 0x18, 0x1b, 0x1c, 0x1e, 0x1f, 0x20,
+                0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2d,
+                0x2f, 0x30, 0x31, 0x33, 0x34, 0x35, 0x37, 0x38,
+                0x39, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3f, 0x40,
+                0x42, 0x43, 0x44, 0x44, 0x45, 0x47, 0x48, 0x49,
+                0x4a, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4f, 0x50,
+                0x52, 0x52, 0x53, 0x54, 0x55, 0x55, 0x56, 0x58,
+                0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e,
+                0x5f, 0x5f, 0x60, 0x61, 0x61, 0x62, 0x63, 0x63,
+                0x65, 0x65, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69,
+                0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e,
+                0x6f, 0x70, 0x70, 0x71, 0x71, 0x73, 0x73, 0x74,
+                0x74, 0x75, 0x75, 0x77, 0x77, 0x78, 0x78, 0x79,
+                0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7d,
+                0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81,
+                0x82, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
+                0x88, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b,
+                0x8b, 0x8b, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f,
+                0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92,
+                0x92, 0x93, 0x93, 0x94, 0x94, 0x94, 0x96, 0x96,
+                0x96, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
+                0x99, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+                0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0xa0,
+                0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3,
+                0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5,
+                0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9,
+                0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac,
+                0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xaf, 0xaf,
+                0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1,
+                0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4,
+                0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+                0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
+                0xb9, 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc,
+                0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf,
+                0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
+                0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4,
+                0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
+                0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9,
+                0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb,
+                0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
+                0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xcf,
+                0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1,
+                0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3,
+                0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
+                0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
+                0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda,
+                0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
+                0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde,
+                0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
+                0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+                0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
+                0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5,
+                0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
+                0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
+                0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb,
+                0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
+                0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+                0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+                0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+                0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+                0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
+                0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
+                0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
+                0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+                0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd,
+                0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
+           },
+           {                           /* gamma 4 - from tp6800 + soi763a */
+               {0x11, 0x14, 0x15, 0x17, 0x1a, 0x1b, 0x1e, 0x1f,
+                0x22, 0x23, 0x25, 0x27, 0x28, 0x2b, 0x2c, 0x2d,
+                0x2f, 0x31, 0x33, 0x34, 0x35, 0x38, 0x39, 0x3a,
+                0x3b, 0x3c, 0x3d, 0x40, 0x42, 0x43, 0x44, 0x45,
+                0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4f,
+                0x50, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56, 0x58,
+                0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5f, 0x60,
+                0x61, 0x61, 0x62, 0x63, 0x65, 0x65, 0x66, 0x67,
+                0x68, 0x68, 0x69, 0x6a, 0x6c, 0x6c, 0x6d, 0x6e,
+                0x6f, 0x6f, 0x70, 0x71, 0x71, 0x73, 0x74, 0x74,
+                0x75, 0x77, 0x77, 0x78, 0x79, 0x79, 0x7a, 0x7a,
+                0x7b, 0x7c, 0x7c, 0x7d, 0x7f, 0x7f, 0x80, 0x80,
+                0x81, 0x81, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86,
+                0x86, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8b,
+                0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x90, 0x90, 0x91,
+                0x91, 0x92, 0x92, 0x93, 0x93, 0x94, 0x94, 0x96,
+                0x96, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
+                0x9a, 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d,
+                0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2,
+                0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5,
+                0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9, 0xab,
+                0xab, 0xab, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae,
+                0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1,
+                0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4,
+                0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8,
+                0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xbc,
+                0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf,
+                0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2,
+                0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+                0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc9,
+                0xc9, 0xc9, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
+                0xcb, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xce,
+                0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0,
+                0xd0, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+                0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+                0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
+                0xd9, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb,
+                0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf,
+                0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1,
+                0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+                0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
+                0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
+                0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9,
+                0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec,
+                0xec, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
+                0xee, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+                0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3,
+                0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5,
+                0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
+                0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9,
+                0xf9, 0xf9, 0xfa, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+               {0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x14, 0x15,
+                0x16, 0x17, 0x1a, 0x1b, 0x1c, 0x1e, 0x1f, 0x20,
+                0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2c,
+                0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x34, 0x35,
+                0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d,
+                0x3f, 0x40, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45,
+                0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4b, 0x4c,
+                0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52, 0x53, 0x54,
+                0x54, 0x55, 0x55, 0x56, 0x58, 0x58, 0x59, 0x5a,
+                0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f,
+                0x60, 0x60, 0x61, 0x61, 0x62, 0x63, 0x63, 0x65,
+                0x65, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69,
+                0x69, 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e,
+                0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71, 0x73,
+                0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x77, 0x77,
+                0x78, 0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b,
+                0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f,
+                0x7f, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82,
+                0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, 0x86,
+                0x88, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8a,
+                0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e,
+                0x8e, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91,
+                0x91, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x94,
+                0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+                0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a,
+                0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c,
+                0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0xa0,
+                0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+                0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4,
+                0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6,
+                0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
+                0xaa, 0xab, 0xab, 0xac, 0xac, 0xac, 0xad, 0xad,
+                0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf,
+                0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+                0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3,
+                0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6,
+                0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8,
+                0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+                0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
+                0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+                0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0,
+                0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
+                0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+                0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
+                0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, 0xc9,
+                0xca, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
+                0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd,
+                0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+                0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+                0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3,
+                0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+                0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+                0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+                0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda,
+                0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
+                0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+                0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
+                0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1,
+                0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
+                0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4,
+                0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
+                0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7,
+                0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
+                0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb,
+                0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+                0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+                0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+                0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+                0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+                0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
+                0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
+                0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
+                0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+                0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
+               {0x0d, 0x10, 0x11, 0x14, 0x15, 0x17, 0x18, 0x1b,
+                0x1c, 0x1e, 0x20, 0x22, 0x23, 0x26, 0x27, 0x28,
+                0x29, 0x2b, 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34,
+                0x35, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d,
+                0x3f, 0x40, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48,
+                0x49, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4f, 0x50,
+                0x52, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58,
+                0x59, 0x5a, 0x5a, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f,
+                0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x65, 0x65,
+                0x66, 0x67, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6c,
+                0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
+                0x71, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x77,
+                0x78, 0x78, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b,
+                0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80,
+                0x81, 0x81, 0x82, 0x82, 0x84, 0x84, 0x85, 0x85,
+                0x86, 0x86, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a,
+                0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f,
+                0x8f, 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92,
+                0x93, 0x93, 0x94, 0x94, 0x94, 0x96, 0x96, 0x97,
+                0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a,
+                0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d,
+                0x9d, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
+                0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+                0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa8, 0xa8,
+                0xa8, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac,
+                0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
+                0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
+                0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4,
+                0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
+                0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba,
+                0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+                0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
+                0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc3,
+                0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+                0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7,
+                0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+                0xca, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc,
+                0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
+                0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0,
+                0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
+                0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
+                0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8,
+                0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
+                0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
+                0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf,
+                0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1,
+                0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+                0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
+                0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6,
+                0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8,
+                0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb,
+                0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
+                0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
+                0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
+                0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
+                0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
+                0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
+                0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8,
+                0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
+                0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
+           },
+           {                                                   /* gamma 5 */
+               {0x16, 0x18, 0x19, 0x1b, 0x1d, 0x1e, 0x20, 0x21,
+                0x23, 0x24, 0x25, 0x27, 0x28, 0x2a, 0x2b, 0x2c,
+                0x2d, 0x2f, 0x30, 0x31, 0x32, 0x34, 0x35, 0x36,
+                0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+                0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+                0x48, 0x49, 0x4a, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
+                0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55,
+                0x56, 0x56, 0x57, 0x58, 0x59, 0x59, 0x5a, 0x5b,
+                0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x5f, 0x60, 0x61,
+                0x62, 0x62, 0x63, 0x64, 0x64, 0x65, 0x66, 0x66,
+                0x67, 0x68, 0x68, 0x69, 0x6a, 0x6a, 0x6b, 0x6b,
+                0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
+                0x71, 0x71, 0x72, 0x73, 0x73, 0x74, 0x74, 0x75,
+                0x75, 0x76, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79,
+                0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7e,
+                0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x82,
+                0x82, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85,
+                0x86, 0x86, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89,
+                0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8d,
+                0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x90, 0x90,
+                0x91, 0x91, 0x91, 0x92, 0x92, 0x93, 0x93, 0x94,
+                0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x96, 0x97,
+                0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a,
+                0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d,
+                0x9d, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f, 0xa0, 0xa0,
+                0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3,
+                0xa3, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6,
+                0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8,
+                0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
+                0xab, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae,
+                0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+                0xb0, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3,
+                0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5,
+                0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7,
+                0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+                0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc,
+                0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
+                0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
+                0xc1, 0xc1, 0xc1, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
+                0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+                0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7,
+                0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9, 0xc9,
+                0xc9, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
+                0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd,
+                0xcd, 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf,
+                0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
+                0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3,
+                0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd5, 0xd5, 0xd5,
+                0xd5, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+                0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
+                0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
+                0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdd,
+                0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde,
+                0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0,
+                0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+                0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
+                0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
+                0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7,
+                0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
+                0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea, 0xeb,
+                0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
+                0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
+                0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+                0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
+                0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3,
+                0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
+                0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
+                0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
+                0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd,
+                0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               {0x0f, 0x11, 0x12, 0x14, 0x15, 0x16, 0x18, 0x19,
+                0x1a, 0x1b, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
+                0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
+                0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x31, 0x32,
+                0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x38, 0x39,
+                0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3e, 0x3f, 0x3f,
+                0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x44, 0x45,
+                0x46, 0x47, 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b,
+                0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0x4e, 0x4f, 0x50,
+                0x50, 0x51, 0x51, 0x52, 0x53, 0x53, 0x54, 0x54,
+                0x55, 0x55, 0x56, 0x56, 0x57, 0x58, 0x58, 0x59,
+                0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5d,
+                0x5d, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
+                0x61, 0x62, 0x62, 0x63, 0x63, 0x64, 0x64, 0x65,
+                0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68,
+                0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c,
+                0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f,
+                0x6f, 0x70, 0x70, 0x71, 0x71, 0x71, 0x72, 0x72,
+                0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x75,
+                0x76, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x78,
+                0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
+                0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e,
+                0x7e, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x81,
+                0x81, 0x81, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83,
+                0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x86,
+                0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88,
+                0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b,
+                0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d,
+                0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f,
+                0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
+                0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94,
+                0x94, 0x94, 0x94, 0x95, 0x95, 0x95, 0x96, 0x96,
+                0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98,
+                0x98, 0x98, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+                0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
+                0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e,
+                0x9e, 0x9e, 0x9f, 0x9f, 0x9f, 0x9f, 0xa0, 0xa0,
+                0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
+                0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
+                0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
+                0xa6, 0xa6, 0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa7,
+                0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9,
+                0xa9, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
+                0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
+                0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
+                0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
+                0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
+                0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+                0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5,
+                0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
+                0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
+                0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
+                0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
+                0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
+                0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
+                0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0,
+                0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
+                0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
+                0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
+                0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
+                0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
+                0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9,
+                0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca,
+                0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
+                0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd,
+                0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce,
+                0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
+                0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
+                0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3,
+                0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
+                0xd4, 0xd4, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
+                0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
+                0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
+                0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda,
+                0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb,
+                0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
+                0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde,
+                0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf,
+                0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
+                0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
+                0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3,
+                0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
+                0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
+                0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+                0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
+                0xe9, 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea,
+                0xea, 0xea, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
+                0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
+                0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
+                0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
+                0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
+                0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+                0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
+                0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
+                0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
+                0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+                0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd,
+                0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+                0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+               {0x13, 0x15, 0x16, 0x18, 0x19, 0x1b, 0x1c, 0x1e,
+                0x1f, 0x20, 0x22, 0x23, 0x24, 0x26, 0x27, 0x28,
+                0x29, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
+                0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+                0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41,
+                0x42, 0x43, 0x44, 0x44, 0x45, 0x46, 0x47, 0x48,
+                0x49, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e,
+                0x4f, 0x50, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54,
+                0x55, 0x55, 0x56, 0x57, 0x57, 0x58, 0x59, 0x59,
+                0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5f,
+                0x5f, 0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x63,
+                0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
+                0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c,
+                0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
+                0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x74, 0x74,
+                0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78,
+                0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c,
+                0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f,
+                0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x83,
+                0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
+                0x86, 0x87, 0x87, 0x88, 0x88, 0x88, 0x89, 0x89,
+                0x89, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c,
+                0x8c, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f,
+                0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92,
+                0x92, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x95,
+                0x95, 0x95, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
+                0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a,
+                0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d,
+                0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f,
+                0x9f, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2,
+                0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
+                0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6,
+                0xa7, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8, 0xa9,
+                0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
+                0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad,
+                0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf,
+                0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1,
+                0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
+                0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5,
+                0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7,
+                0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
+                0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb,
+                0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
+                0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf,
+                0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1,
+                0xc1, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
+                0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
+                0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
+                0xc7, 0xc7, 0xc7, 0xc7, 0xc8, 0xc8, 0xc8, 0xc8,
+                0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
+                0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
+                0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
+                0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
+                0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
+                0xd1, 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3,
+                0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
+                0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd6, 0xd6, 0xd6,
+                0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
+                0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9,
+                0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb,
+                0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
+                0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
+                0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
+                0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
+                0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
+                0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
+                0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6,
+                0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
+                0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9,
+                0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea,
+                0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec,
+                0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
+                0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
+                0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+                0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2,
+                0xf2, 0xf2, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
+                0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5,
+                0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
+                0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
+                0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb,
+                0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
+                0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe,
+                0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+           },
+       };
+
+       reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
+       if (sd->bridge == BRIDGE_TP6810)
+               reg_w(gspca_dev, 0x02, 0x28);
+/*     msleep(50); */
+       bulk_w(gspca_dev, 0x00, gamma_tb[gamma][0], 1024);
+       bulk_w(gspca_dev, 0x01, gamma_tb[gamma][1], 1024);
+       bulk_w(gspca_dev, 0x02, gamma_tb[gamma][2], 1024);
+       if (sd->bridge == BRIDGE_TP6810) {
+               int i;
+
+               reg_w(gspca_dev, 0x02, 0x2b);
+               reg_w(gspca_dev, 0x02, 0x28);
+               for (i = 0; i < 6; i++)
+                       reg_w(gspca_dev, TP6800_R55_GAMMA_R,
+                               gamma_tb[gamma][0][i]);
+               reg_w(gspca_dev, 0x02, 0x2b);
+               reg_w(gspca_dev, 0x02, 0x28);
+               for (i = 0; i < 6; i++)
+                       reg_w(gspca_dev, TP6800_R56_GAMMA_G,
+                               gamma_tb[gamma][1][i]);
+               reg_w(gspca_dev, 0x02, 0x2b);
+               reg_w(gspca_dev, 0x02, 0x28);
+               for (i = 0; i < 6; i++)
+                       reg_w(gspca_dev, TP6800_R57_GAMMA_B,
+                               gamma_tb[gamma][2][i]);
+               reg_w(gspca_dev, 0x02, 0x28);
+       }
+       reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
+/*     msleep(50); */
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->bridge == BRIDGE_TP6800) {
+               val |= 0x08;            /* grid compensation enable */
+               if (gspca_dev->width == 640)
+                       reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
+               else
+                       val |= 0x04;            /* scaling down enable */
+               reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, val);
+       } else {
+               val = (val << 5) | 0x08;
+               reg_w(gspca_dev, 0x59, val);
+       }
+}
+
+static void setautogain(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->ag_cnt = val ? AG_CNT_START : -1;
+}
+
+/* set the resolution for sensor cx0342 */
+static void set_resolution(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
+       if (gspca_dev->width == 320) {
+               reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x06);
+               msleep(100);
+               i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
+               msleep(100);
+               reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
+               reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01);      /* qvga */
+               reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, 0x0d);
+               i2c_w(gspca_dev, CX0342_EXPO_LINE_L, 0x37);
+               i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x01);
+       } else {
+               reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x05);
+               msleep(100);
+               i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
+               msleep(100);
+               reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
+               reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00);      /* vga */
+               reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, 0x09);
+               i2c_w(gspca_dev, CX0342_EXPO_LINE_L, 0xcf);
+               i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00);
+       }
+       i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
+       bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
+                               ARRAY_SIZE(color_gain[0]));
+       setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
+       if (sd->sensor == SENSOR_SOI763A)
+               setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
+}
+
+/* convert the frame rate to a tp68x0 value */
+static int get_fr_idx(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+
+       if (sd->bridge == BRIDGE_TP6800) {
+               for (i = 0; i < ARRAY_SIZE(rates) - 1; i++) {
+                       if (sd->framerate >= rates[i])
+                               break;
+               }
+               i = 6 - i;              /* 1 = 5fps .. 6 = 30fps */
+
+               /* 640x480 * 30 fps does not work */
+               if (i == 6                      /* if 30 fps */
+                && gspca_dev->width == 640)
+                       i = 0x05;               /* 15 fps */
+       } else {
+               for (i = 0; i < ARRAY_SIZE(rates_6810) - 1; i++) {
+                       if (sd->framerate >= rates_6810[i])
+                               break;
+               }
+               i = 7 - i;              /* 3 = 5fps .. 7 = 30fps */
+
+               /* 640x480 * 30 fps does not work */
+               if (i == 7                      /* if 30 fps */
+                && gspca_dev->width == 640)
+                       i = 6;                  /* 15 fps */
+               i |= 0x80;                      /* clock * 1 */
+       }
+       return i;
+}
+
+static void setframerate(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 fr_idx;
+
+       fr_idx = get_fr_idx(gspca_dev);
+
+       if (sd->bridge == BRIDGE_TP6810) {
+               reg_r(gspca_dev, 0x7b);
+               reg_w(gspca_dev, 0x7b,
+                       sd->sensor == SENSOR_CX0342 ? 0x10 : 0x90);
+               if (val >= 128)
+                       fr_idx = 0xf0;          /* lower frame rate */
+       }
+
+       reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, fr_idx);
+
+       if (sd->sensor == SENSOR_CX0342)
+               i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
+}
+
+static void setrgain(struct gspca_dev *gspca_dev, s32 rgain)
+{
+       i2c_w(gspca_dev, CX0342_RAW_RGAIN_H, rgain >> 8);
+       i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, rgain);
+       i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
+}
+
+static int sd_setgain(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       s32 val = gspca_dev->gain->val;
+
+       if (sd->sensor == SENSOR_CX0342) {
+               s32 old = gspca_dev->gain->cur.val ?
+                                       gspca_dev->gain->cur.val : 1;
+
+               sd->blue->val = sd->blue->val * val / old;
+               if (sd->blue->val > 4095)
+                       sd->blue->val = 4095;
+               sd->red->val = sd->red->val * val / old;
+               if (sd->red->val > 4095)
+                       sd->red->val = 4095;
+       }
+       if (gspca_dev->streaming) {
+               if (sd->sensor == SENSOR_CX0342)
+                       setexposure(gspca_dev, gspca_dev->exposure->val,
+                                       gspca_dev->gain->val,
+                                       sd->blue->val, sd->red->val);
+               else
+                       setexposure(gspca_dev, gspca_dev->exposure->val,
+                                       gspca_dev->gain->val, 0, 0);
+       }
+       return gspca_dev->usb_err;
+}
+
+static void setbgain(struct gspca_dev *gspca_dev, s32 bgain)
+{
+       i2c_w(gspca_dev, CX0342_RAW_BGAIN_H, bgain >> 8);
+       i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, bgain);
+       i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                    const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->bridge = id->driver_info;
+
+       gspca_dev->cam.cam_mode = vga_mode;
+       gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
+       gspca_dev->cam.mode_framerates = sd->bridge == BRIDGE_TP6800 ?
+                       framerates : framerates_6810;
+
+       sd->framerate = 30;             /* default: 30 fps */
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       static const struct cmd tp6800_preinit[] = {
+               {TP6800_R10_SIF_TYPE, 0x01},    /* sif */
+               {TP6800_R11_SIF_CONTROL, 0x01},
+               {TP6800_R15_GPIO_PU, 0x9f},
+               {TP6800_R16_GPIO_PD, 0x9f},
+               {TP6800_R17_GPIO_IO, 0x80},
+               {TP6800_R18_GPIO_DATA, 0x40},   /* LED off */
+       };
+       static const struct cmd tp6810_preinit[] = {
+               {TP6800_R2F_TIMING_CFG, 0x2f},
+               {TP6800_R15_GPIO_PU, 0x6f},
+               {TP6800_R16_GPIO_PD, 0x40},
+               {TP6800_R17_GPIO_IO, 0x9f},
+               {TP6800_R18_GPIO_DATA, 0xc1},   /* LED off */
+       };
+
+       if (sd->bridge == BRIDGE_TP6800)
+               reg_w_buf(gspca_dev, tp6800_preinit,
+                               ARRAY_SIZE(tp6800_preinit));
+       else
+               reg_w_buf(gspca_dev, tp6810_preinit,
+                               ARRAY_SIZE(tp6810_preinit));
+       msleep(15);
+       reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
+       PDEBUG(D_PROBE, "gpio: %02x", gspca_dev->usb_buf[0]);
+/* values:
+ *     0x80: snapshot button
+ *     0x40: LED
+ *     0x20: (bridge / sensor) reset for tp6810 ?
+ *     0x07: sensor type ?
+ */
+
+       /* guess the sensor type */
+       if (force_sensor >= 0) {
+               sd->sensor = force_sensor;
+       } else {
+               if (sd->bridge == BRIDGE_TP6800) {
+/*fixme: not sure this is working*/
+                       switch (gspca_dev->usb_buf[0] & 0x07) {
+                       case 0:
+                               sd->sensor = SENSOR_SOI763A;
+                               break;
+                       case 1:
+                               sd->sensor = SENSOR_CX0342;
+                               break;
+                       }
+               } else {
+                       int sensor;
+
+                       sensor = probe_6810(gspca_dev);
+                       if (sensor < 0) {
+                               pr_warn("Unknown sensor %d - forced to soi763a\n",
+                                       -sensor);
+                               sensor = SENSOR_SOI763A;
+                       }
+                       sd->sensor = sensor;
+               }
+       }
+       if (sd->sensor == SENSOR_SOI763A) {
+               pr_info("Sensor soi763a\n");
+               if (sd->bridge == BRIDGE_TP6810) {
+                       soi763a_6810_init(gspca_dev);
+               }
+       } else {
+               pr_info("Sensor cx0342\n");
+               if (sd->bridge == BRIDGE_TP6810) {
+                       cx0342_6810_init(gspca_dev);
+               }
+       }
+
+       set_dqt(gspca_dev, 0);
+       return 0;
+}
+
+/* This function is called before choosing the alt setting */
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       static const struct cmd cx_sensor_init[] = {
+               {CX0342_AUTO_ADC_CALIB, 0x81},
+               {CX0342_EXPO_LINE_L, 0x37},
+               {CX0342_EXPO_LINE_H, 0x01},
+               {CX0342_RAW_GRGAIN_L, 0x00},
+               {CX0342_RAW_GBGAIN_L, 0x00},
+               {CX0342_RAW_RGAIN_L, 0x00},
+               {CX0342_RAW_BGAIN_L, 0x00},
+               {CX0342_SYS_CTRL_0, 0x81},
+       };
+       static const struct cmd cx_bridge_init[] = {
+               {0x4d, 0x00},
+               {0x4c, 0xff},
+               {0x4e, 0xff},
+               {0x4f, 0x00},
+       };
+       static const struct cmd ov_sensor_init[] = {
+               {0x10, 0x75},           /* exposure */
+               {0x76, 0x03},
+               {0x00, 0x00},           /* gain */
+       };
+       static const struct cmd ov_bridge_init[] = {
+               {0x7b, 0x90},
+               {TP6800_R3F_FRAME_RATE, 0x87},
+       };
+
+       if (sd->bridge == BRIDGE_TP6800)
+               return 0;
+       if (sd->sensor == SENSOR_CX0342) {
+               reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20);
+               reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87);
+               i2c_w_buf(gspca_dev, cx_sensor_init,
+                               ARRAY_SIZE(cx_sensor_init));
+               reg_w_buf(gspca_dev, cx_bridge_init,
+                               ARRAY_SIZE(cx_bridge_init));
+               bulk_w(gspca_dev, 0x03, color_null, sizeof color_null);
+               reg_w(gspca_dev, 0x59, 0x40);
+       } else {
+               reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x21);
+               i2c_w_buf(gspca_dev, ov_sensor_init,
+                               ARRAY_SIZE(ov_sensor_init));
+               reg_r(gspca_dev, 0x7b);
+               reg_w_buf(gspca_dev, ov_bridge_init,
+                               ARRAY_SIZE(ov_bridge_init));
+       }
+       reg_w(gspca_dev, TP6800_R78_FORMAT,
+                       gspca_dev->curr_mode ? 0x00 : 0x01);
+       return gspca_dev->usb_err;
+}
+
+static void set_led(struct gspca_dev *gspca_dev, int on)
+{
+       u8 data;
+
+       reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
+       data = gspca_dev->usb_buf[0];
+       if (on)
+               data &= ~0x40;
+       else
+               data |= 0x40;
+       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, data);
+}
+
+static void cx0342_6800_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       static const struct cmd reg_init[] = {
+               /* fixme: is this useful? */
+               {TP6800_R17_GPIO_IO, 0x9f},
+               {TP6800_R16_GPIO_PD, 0x40},
+               {TP6800_R10_SIF_TYPE, 0x00},    /* i2c 8 bits */
+               {TP6800_R50, 0x00},
+               {TP6800_R51, 0x00},
+               {TP6800_R52, 0xff},
+               {TP6800_R53, 0x03},
+               {TP6800_R54_DARK_CFG, 0x07},
+               {TP6800_R5C_EDGE_THRLD, 0x40},
+               {TP6800_R7A_BLK_THRLD, 0x40},
+               {TP6800_R2F_TIMING_CFG, 0x17},
+               {TP6800_R30_SENSOR_CFG, 0x18},  /* G1B..RG0 */
+               {TP6800_R37_FRONT_DARK_ST, 0x00},
+               {TP6800_R38_FRONT_DARK_END, 0x00},
+               {TP6800_R39_REAR_DARK_ST_L, 0x00},
+               {TP6800_R3A_REAR_DARK_ST_H, 0x00},
+               {TP6800_R3B_REAR_DARK_END_L, 0x00},
+               {TP6800_R3C_REAR_DARK_END_H, 0x00},
+               {TP6800_R3D_HORIZ_DARK_LINE_L, 0x00},
+               {TP6800_R3E_HORIZ_DARK_LINE_H, 0x00},
+               {TP6800_R21_ENDP_1_CTL, 0x03},
+
+               {TP6800_R31_PIXEL_START, 0x0b},
+               {TP6800_R32_PIXEL_END_L, 0x8a},
+               {TP6800_R33_PIXEL_END_H, 0x02},
+               {TP6800_R34_LINE_START, 0x0e},
+               {TP6800_R35_LINE_END_L, 0xf4},
+               {TP6800_R36_LINE_END_H, 0x01},
+               {TP6800_R78_FORMAT, 0x00},
+               {TP6800_R12_SIF_ADDR_S, 0x20},  /* cx0342 i2c addr */
+       };
+       static const struct cmd sensor_init[] = {
+               {CX0342_OUTPUT_CTRL, 0x07},
+               {CX0342_BYPASS_MODE, 0x58},
+               {CX0342_GPXLTHD_L, 0x16},
+               {CX0342_RBPXLTHD_L, 0x16},
+               {CX0342_PLANETHD_L, 0xc0},
+               {CX0342_PLANETHD_H, 0x03},
+               {CX0342_RB_GAP_L, 0xff},
+               {CX0342_RB_GAP_H, 0x07},
+               {CX0342_G_GAP_L, 0xff},
+               {CX0342_G_GAP_H, 0x07},
+               {CX0342_RST_OVERFLOW_L, 0x5c},
+               {CX0342_RST_OVERFLOW_H, 0x01},
+               {CX0342_DATA_OVERFLOW_L, 0xfc},
+               {CX0342_DATA_OVERFLOW_H, 0x03},
+               {CX0342_DATA_UNDERFLOW_L, 0x00},
+               {CX0342_DATA_UNDERFLOW_H, 0x00},
+               {CX0342_SYS_CTRL_0, 0x40},
+               {CX0342_GLOBAL_GAIN, 0x01},
+               {CX0342_CLOCK_GEN, 0x00},
+               {CX0342_SYS_CTRL_0, 0x02},
+               {CX0342_IDLE_CTRL, 0x05},
+               {CX0342_ADCGN, 0x00},
+               {CX0342_ADC_CTL, 0x00},
+               {CX0342_LVRST_BLBIAS, 0x01},
+               {CX0342_VTHSEL, 0x0b},
+               {CX0342_RAMP_RIV, 0x0b},
+               {CX0342_LDOSEL, 0x07},
+               {CX0342_SPV_VALUE_L, 0x40},
+               {CX0342_SPV_VALUE_H, 0x02},
+       };
+
+       reg_w_buf(gspca_dev, reg_init, ARRAY_SIZE(reg_init));
+       i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+       i2c_w_buf(gspca_dev, cx0342_timing_seq, ARRAY_SIZE(cx0342_timing_seq));
+       reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10);
+       reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
+       i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00);
+       i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
+       if (sd->sensor == SENSOR_CX0342)
+               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
+                       v4l2_ctrl_g_ctrl(gspca_dev->gain),
+                       v4l2_ctrl_g_ctrl(sd->blue),
+                       v4l2_ctrl_g_ctrl(sd->red));
+       else
+               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
+                       v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
+       set_led(gspca_dev, 1);
+       set_resolution(gspca_dev);
+}
+
+static void cx0342_6810_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       static const struct cmd sensor_init_2[] = {
+               {CX0342_EXPO_LINE_L, 0x6f},
+               {CX0342_EXPO_LINE_H, 0x02},
+               {CX0342_RAW_GRGAIN_L, 0x00},
+               {CX0342_RAW_GBGAIN_L, 0x00},
+               {CX0342_RAW_RGAIN_L, 0x00},
+               {CX0342_RAW_BGAIN_L, 0x00},
+               {CX0342_SYS_CTRL_0, 0x81},
+       };
+       static const struct cmd bridge_init_2[] = {
+               {0x4d, 0x00},
+               {0x4c, 0xff},
+               {0x4e, 0xff},
+               {0x4f, 0x00},
+               {TP6800_R7A_BLK_THRLD, 0x00},
+               {TP6800_R79_QUALITY, 0x04},
+               {TP6800_R79_QUALITY, 0x01},
+       };
+       static const struct cmd bridge_init_3[] = {
+               {TP6800_R31_PIXEL_START, 0x08},
+               {TP6800_R32_PIXEL_END_L, 0x87},
+               {TP6800_R33_PIXEL_END_H, 0x02},
+               {TP6800_R34_LINE_START, 0x0e},
+               {TP6800_R35_LINE_END_L, 0xf4},
+               {TP6800_R36_LINE_END_H, 0x01},
+       };
+       static const struct cmd sensor_init_3[] = {
+               {CX0342_AUTO_ADC_CALIB, 0x81},
+               {CX0342_EXPO_LINE_L, 0x6f},
+               {CX0342_EXPO_LINE_H, 0x02},
+               {CX0342_RAW_GRGAIN_L, 0x00},
+               {CX0342_RAW_GBGAIN_L, 0x00},
+               {CX0342_RAW_RGAIN_L, 0x00},
+               {CX0342_RAW_BGAIN_L, 0x00},
+               {CX0342_SYS_CTRL_0, 0x81},
+       };
+       static const struct cmd bridge_init_5[] = {
+               {0x4d, 0x00},
+               {0x4c, 0xff},
+               {0x4e, 0xff},
+               {0x4f, 0x00},
+       };
+       static const struct cmd sensor_init_4[] = {
+               {CX0342_EXPO_LINE_L, 0xd3},
+               {CX0342_EXPO_LINE_H, 0x01},
+/*fixme: gains, but 00..80 only*/
+               {CX0342_RAW_GRGAIN_L, 0x40},
+               {CX0342_RAW_GBGAIN_L, 0x40},
+               {CX0342_RAW_RGAIN_L, 0x40},
+               {CX0342_RAW_BGAIN_L, 0x40},
+               {CX0342_SYS_CTRL_0, 0x81},
+       };
+       static const struct cmd sensor_init_5[] = {
+               {CX0342_IDLE_CTRL, 0x05},
+               {CX0342_ADCGN, 0x00},
+               {CX0342_ADC_CTL, 0x00},
+               {CX0342_LVRST_BLBIAS, 0x01},
+               {CX0342_VTHSEL, 0x0b},
+               {CX0342_RAMP_RIV, 0x0b},
+               {CX0342_LDOSEL, 0x07},
+               {CX0342_SPV_VALUE_L, 0x40},
+               {CX0342_SPV_VALUE_H, 0x02},
+               {CX0342_AUTO_ADC_CALIB, 0x81},
+       };
+
+       reg_w(gspca_dev, 0x22, gspca_dev->alt);
+       i2c_w_buf(gspca_dev, sensor_init_2, ARRAY_SIZE(sensor_init_2));
+       reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2));
+       reg_w_buf(gspca_dev, tp6810_cx_init_common,
+                       ARRAY_SIZE(tp6810_cx_init_common));
+       reg_w_buf(gspca_dev, bridge_init_3, ARRAY_SIZE(bridge_init_3));
+       if (gspca_dev->curr_mode) {
+               reg_w(gspca_dev, 0x4a, 0x7f);
+               reg_w(gspca_dev, 0x07, 0x05);
+               reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00);      /* vga */
+       } else {
+               reg_w(gspca_dev, 0x4a, 0xff);
+               reg_w(gspca_dev, 0x07, 0x85);
+               reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01);      /* qvga */
+       }
+       setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
+       reg_w_buf(gspca_dev, tp6810_bridge_start,
+                       ARRAY_SIZE(tp6810_bridge_start));
+       setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
+       bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
+                               ARRAY_SIZE(color_gain[0]));
+       reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87);
+       i2c_w_buf(gspca_dev, sensor_init_3, ARRAY_SIZE(sensor_init_3));
+       reg_w_buf(gspca_dev, bridge_init_5, ARRAY_SIZE(bridge_init_5));
+       i2c_w_buf(gspca_dev, sensor_init_4, ARRAY_SIZE(sensor_init_4));
+       reg_w_buf(gspca_dev, bridge_init_5, ARRAY_SIZE(bridge_init_5));
+       i2c_w_buf(gspca_dev, sensor_init_5, ARRAY_SIZE(sensor_init_5));
+
+       set_led(gspca_dev, 1);
+/*     setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual)); */
+}
+
+static void soi763a_6800_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       static const struct cmd reg_init[] = {
+               {TP6800_R79_QUALITY, 0x04},
+               {TP6800_R79_QUALITY, 0x01},
+               {TP6800_R10_SIF_TYPE, 0x00},    /* i2c 8 bits */
+
+               {TP6800_R50, 0x00},
+               {TP6800_R51, 0x00},
+               {TP6800_R52, 0xff},
+               {TP6800_R53, 0x03},
+               {TP6800_R54_DARK_CFG, 0x07},
+               {TP6800_R5C_EDGE_THRLD, 0x40},
+
+               {TP6800_R79_QUALITY, 0x03},
+               {TP6800_R7A_BLK_THRLD, 0x40},
+
+               {TP6800_R2F_TIMING_CFG, 0x46},
+               {TP6800_R30_SENSOR_CFG, 0x10},  /* BG1..G0R */
+               {TP6800_R37_FRONT_DARK_ST, 0x00},
+               {TP6800_R38_FRONT_DARK_END, 0x00},
+               {TP6800_R39_REAR_DARK_ST_L, 0x00},
+               {TP6800_R3A_REAR_DARK_ST_H, 0x00},
+               {TP6800_R3B_REAR_DARK_END_L, 0x00},
+               {TP6800_R3C_REAR_DARK_END_H, 0x00},
+               {TP6800_R3D_HORIZ_DARK_LINE_L, 0x00},
+               {TP6800_R3E_HORIZ_DARK_LINE_H, 0x00},
+               {TP6800_R21_ENDP_1_CTL, 0x03},
+
+               {TP6800_R3F_FRAME_RATE, 0x04},  /* 15 fps */
+               {TP6800_R5D_DEMOSAIC_CFG, 0x0e}, /* scale down - medium edge */
+
+               {TP6800_R31_PIXEL_START, 0x1b},
+               {TP6800_R32_PIXEL_END_L, 0x9a},
+               {TP6800_R33_PIXEL_END_H, 0x02},
+               {TP6800_R34_LINE_START, 0x0f},
+               {TP6800_R35_LINE_END_L, 0xf4},
+               {TP6800_R36_LINE_END_H, 0x01},
+               {TP6800_R78_FORMAT, 0x01},      /* qvga */
+               {TP6800_R12_SIF_ADDR_S, 0x21},  /* soi763a i2c addr */
+               {TP6800_R1A_SIF_TX_DATA2, 0x00},
+       };
+       static const struct cmd sensor_init[] = {
+               {0x12, 0x48},           /* mirror - RGB */
+               {0x13, 0xa0},           /* clock - no AGC nor AEC */
+               {0x03, 0xa4},           /* saturation */
+               {0x04, 0x30},           /* hue */
+               {0x05, 0x88},           /* contrast */
+               {0x06, 0x60},           /* brightness */
+               {0x10, 0x41},           /* AEC */
+               {0x11, 0x40},           /* clock rate */
+               {0x13, 0xa0},
+               {0x14, 0x00},           /* 640x480 */
+               {0x15, 0x14},
+               {0x1f, 0x41},
+               {0x20, 0x80},
+               {0x23, 0xee},
+               {0x24, 0x50},
+               {0x25, 0x7a},
+               {0x26, 0x00},
+               {0x27, 0xe2},
+               {0x28, 0xb0},
+               {0x2a, 0x00},
+               {0x2b, 0x00},
+               {0x2d, 0x81},
+               {0x2f, 0x9d},
+               {0x60, 0x80},
+               {0x61, 0x00},
+               {0x62, 0x88},
+               {0x63, 0x11},
+               {0x64, 0x89},
+               {0x65, 0x00},
+               {0x67, 0x94},
+               {0x68, 0x7a},
+               {0x69, 0x0f},
+               {0x6c, 0x80},
+               {0x6d, 0x80},
+               {0x6e, 0x80},
+               {0x6f, 0xff},
+               {0x71, 0x20},
+               {0x74, 0x20},
+               {0x75, 0x86},
+               {0x77, 0xb5},
+               {0x17, 0x18},           /* H href start */
+               {0x18, 0xbf},           /* H href end */
+               {0x19, 0x03},           /* V start */
+               {0x1a, 0xf8},           /* V end */
+               {0x01, 0x80},           /* blue gain */
+               {0x02, 0x80},           /* red gain */
+       };
+
+       reg_w_buf(gspca_dev, reg_init, ARRAY_SIZE(reg_init));
+
+       i2c_w(gspca_dev, 0x12, 0x80);           /* sensor reset */
+       msleep(10);
+
+       i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
+
+       reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10);
+       reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
+
+       setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
+
+       bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A],
+                               ARRAY_SIZE(color_gain[0]));
+
+       set_led(gspca_dev, 1);
+       if (sd->sensor == SENSOR_CX0342)
+               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
+                       v4l2_ctrl_g_ctrl(gspca_dev->gain),
+                       v4l2_ctrl_g_ctrl(sd->blue),
+                       v4l2_ctrl_g_ctrl(sd->red));
+       else
+               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
+                       v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
+       if (sd->sensor == SENSOR_SOI763A)
+               setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
+       setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
+}
+
+static void soi763a_6810_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       static const struct cmd bridge_init_2[] = {
+               {TP6800_R7A_BLK_THRLD, 0x00},
+               {TP6800_R79_QUALITY, 0x04},
+               {TP6800_R79_QUALITY, 0x01},
+       };
+       static const struct cmd bridge_init_3[] = {
+               {TP6800_R31_PIXEL_START, 0x20},
+               {TP6800_R32_PIXEL_END_L, 0x9f},
+               {TP6800_R33_PIXEL_END_H, 0x02},
+               {TP6800_R34_LINE_START, 0x13},
+               {TP6800_R35_LINE_END_L, 0xf8},
+               {TP6800_R36_LINE_END_H, 0x01},
+       };
+       static const struct cmd bridge_init_6[] = {
+               {0x08, 0xff},
+               {0x09, 0xff},
+               {0x0a, 0x5f},
+               {0x0b, 0x80},
+       };
+
+       reg_w(gspca_dev, 0x22, gspca_dev->alt);
+       bulk_w(gspca_dev, 0x03, color_null, sizeof color_null);
+       reg_w(gspca_dev, 0x59, 0x40);
+       if (sd->sensor == SENSOR_CX0342)
+               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
+                       v4l2_ctrl_g_ctrl(gspca_dev->gain),
+                       v4l2_ctrl_g_ctrl(sd->blue),
+                       v4l2_ctrl_g_ctrl(sd->red));
+       else
+               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
+                       v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
+       reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2));
+       reg_w_buf(gspca_dev, tp6810_ov_init_common,
+                       ARRAY_SIZE(tp6810_ov_init_common));
+       reg_w_buf(gspca_dev, bridge_init_3, ARRAY_SIZE(bridge_init_3));
+       if (gspca_dev->curr_mode) {
+               reg_w(gspca_dev, 0x4a, 0x7f);
+               reg_w(gspca_dev, 0x07, 0x05);
+               reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00);      /* vga */
+       } else {
+               reg_w(gspca_dev, 0x4a, 0xff);
+               reg_w(gspca_dev, 0x07, 0x85);
+               reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01);      /* qvga */
+       }
+       setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
+       reg_w_buf(gspca_dev, tp6810_bridge_start,
+                       ARRAY_SIZE(tp6810_bridge_start));
+
+       if (gspca_dev->curr_mode) {
+               reg_w(gspca_dev, 0x4f, 0x00);
+               reg_w(gspca_dev, 0x4e, 0x7c);
+       }
+
+       reg_w(gspca_dev, 0x00, 0x00);
+
+       setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
+       bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A],
+                               ARRAY_SIZE(color_gain[0]));
+       set_led(gspca_dev, 1);
+       reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0xf0);
+       if (sd->sensor == SENSOR_CX0342)
+               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
+                       v4l2_ctrl_g_ctrl(gspca_dev->gain),
+                       v4l2_ctrl_g_ctrl(sd->blue),
+                       v4l2_ctrl_g_ctrl(sd->red));
+       else
+               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
+                       v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
+       reg_w_buf(gspca_dev, bridge_init_6, ARRAY_SIZE(bridge_init_6));
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width);
+       set_dqt(gspca_dev, sd->quality);
+       if (sd->bridge == BRIDGE_TP6800) {
+               if (sd->sensor == SENSOR_CX0342)
+                       cx0342_6800_start(gspca_dev);
+               else
+                       soi763a_6800_start(gspca_dev);
+       } else {
+               if (sd->sensor == SENSOR_CX0342)
+                       cx0342_6810_start(gspca_dev);
+               else
+                       soi763a_6810_start(gspca_dev);
+               reg_w_buf(gspca_dev, tp6810_late_start,
+                               ARRAY_SIZE(tp6810_late_start));
+               reg_w(gspca_dev, 0x80, 0x03);
+               reg_w(gspca_dev, 0x82, gspca_dev->curr_mode ? 0x0a : 0x0e);
+
+               if (sd->sensor == SENSOR_CX0342)
+                       setexposure(gspca_dev,
+                               v4l2_ctrl_g_ctrl(gspca_dev->exposure),
+                               v4l2_ctrl_g_ctrl(gspca_dev->gain),
+                               v4l2_ctrl_g_ctrl(sd->blue),
+                               v4l2_ctrl_g_ctrl(sd->red));
+               else
+                       setexposure(gspca_dev,
+                               v4l2_ctrl_g_ctrl(gspca_dev->exposure),
+                               v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
+               if (sd->sensor == SENSOR_SOI763A)
+                       setquality(gspca_dev,
+                                  v4l2_ctrl_g_ctrl(sd->jpegqual));
+               if (sd->bridge == BRIDGE_TP6810)
+                       setautogain(gspca_dev,
+                                   v4l2_ctrl_g_ctrl(gspca_dev->autogain));
+       }
+
+       setframerate(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
+
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->bridge == BRIDGE_TP6800)
+               reg_w(gspca_dev, TP6800_R2F_TIMING_CFG, 0x03);
+       set_led(gspca_dev, 0);
+       reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,
+                       int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* the start of frame contains:
+        *      ff d8
+        *      ff fe
+        *      width / 16
+        *      height / 8
+        *      quality
+        */
+       if (sd->bridge == BRIDGE_TP6810) {
+               if (*data != 0x5a) {
+/*fixme: don't discard the whole frame..*/
+                       if (*data == 0xaa || *data == 0x00)
+                               return;
+                       if (*data > 0xc0) {
+                               PDEBUG(D_FRAM, "bad frame");
+                               gspca_dev->last_packet_type = DISCARD_PACKET;
+                               return;
+                       }
+               }
+               data++;
+               len--;
+               if (*data == 0xff && data[1] == 0xd8) {
+/*fixme: there may be information in the 4 high bits*/
+                       if ((data[6] & 0x0f) != sd->quality)
+                               set_dqt(gspca_dev, data[6] & 0x0f);
+                       gspca_frame_add(gspca_dev, FIRST_PACKET,
+                                       sd->jpeg_hdr, JPEG_HDR_SZ);
+                       gspca_frame_add(gspca_dev, INTER_PACKET,
+                                       data + 7, len - 7);
+               } else if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
+                       gspca_frame_add(gspca_dev, LAST_PACKET,
+                                       data, len);
+               } else {
+                       gspca_frame_add(gspca_dev, INTER_PACKET,
+                                       data, len);
+               }
+               return;
+       }
+
+       switch (*data) {
+       case 0x55:
+               gspca_frame_add(gspca_dev, LAST_PACKET, data, 0);
+
+               if (len < 8
+                || data[1] != 0xff || data[2] != 0xd8
+                || data[3] != 0xff || data[4] != 0xfe) {
+
+                       /* Have only seen this with corrupt frames */
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+                       return;
+               }
+               if (data[7] != sd->quality)
+                       set_dqt(gspca_dev, data[7]);
+               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                               sd->jpeg_hdr, JPEG_HDR_SZ);
+               gspca_frame_add(gspca_dev, INTER_PACKET,
+                               data + 8, len - 8);
+               break;
+       case 0xaa:
+               gspca_dev->last_packet_type = DISCARD_PACKET;
+               break;
+       case 0xcc:
+               if (data[1] != 0xff || data[2] != 0xd8)
+                       gspca_frame_add(gspca_dev, INTER_PACKET,
+                                       data + 1, len - 1);
+               else
+                       gspca_dev->last_packet_type = DISCARD_PACKET;
+               break;
+       }
+}
+
+static void sd_dq_callback(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int ret, alen;
+       int luma, expo;
+
+       if (sd->ag_cnt < 0)
+               return;
+       if (--sd->ag_cnt > 5)
+               return;
+       switch (sd->ag_cnt) {
+/*     case 5: */
+       default:
+               reg_w(gspca_dev, 0x7d, 0x00);
+               break;
+       case 4:
+               reg_w(gspca_dev, 0x27, 0xb0);
+               break;
+       case 3:
+               reg_w(gspca_dev, 0x0c, 0x01);
+               break;
+       case 2:
+               ret = usb_bulk_msg(gspca_dev->dev,
+                               usb_rcvbulkpipe(gspca_dev->dev, 0x02),
+                               gspca_dev->usb_buf,
+                               32,
+                               &alen,
+                               500);
+               if (ret < 0) {
+                       pr_err("bulk err %d\n", ret);
+                       break;
+               }
+               /* values not used (unknown) */
+               break;
+       case 1:
+               reg_w(gspca_dev, 0x27, 0xd0);
+               break;
+       case 0:
+               ret = usb_bulk_msg(gspca_dev->dev,
+                               usb_rcvbulkpipe(gspca_dev->dev, 0x02),
+                               gspca_dev->usb_buf,
+                               32,
+                               &alen,
+                               500);
+               if (ret < 0) {
+                       pr_err("bulk err %d\n", ret);
+                       break;
+               }
+               luma = ((gspca_dev->usb_buf[8] << 8) + gspca_dev->usb_buf[7] +
+                       (gspca_dev->usb_buf[11] << 8) + gspca_dev->usb_buf[10] +
+                       (gspca_dev->usb_buf[14] << 8) + gspca_dev->usb_buf[13] +
+                       (gspca_dev->usb_buf[17] << 8) + gspca_dev->usb_buf[16] +
+                       (gspca_dev->usb_buf[20] << 8) + gspca_dev->usb_buf[19] +
+                       (gspca_dev->usb_buf[23] << 8) + gspca_dev->usb_buf[22] +
+                       (gspca_dev->usb_buf[26] << 8) + gspca_dev->usb_buf[25] +
+                       (gspca_dev->usb_buf[29] << 8) + gspca_dev->usb_buf[28])
+                               / 8;
+               if (gspca_dev->width == 640)
+                       luma /= 4;
+               reg_w(gspca_dev, 0x7d, 0x00);
+
+               expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
+               ret = gspca_expo_autogain(gspca_dev, luma,
+                               60,     /* desired luma */
+                               6,      /* dead zone */
+                               2,      /* gain knee */
+                               70);    /* expo knee */
+               sd->ag_cnt = AG_CNT_START;
+               if (sd->bridge == BRIDGE_TP6810) {
+                       int new_expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
+
+                       if ((expo >= 128 && new_expo < 128)
+                        || (expo < 128 && new_expo >= 128))
+                               setframerate(gspca_dev, new_expo);
+               }
+               break;
+       }
+}
+
+/* get stream parameters (framerate) */
+static void sd_get_streamparm(struct gspca_dev *gspca_dev,
+                            struct v4l2_streamparm *parm)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct v4l2_captureparm *cp = &parm->parm.capture;
+       struct v4l2_fract *tpf = &cp->timeperframe;
+       int fr, i;
+
+       cp->capability |= V4L2_CAP_TIMEPERFRAME;
+       tpf->numerator = 1;
+       i = get_fr_idx(gspca_dev);
+       if (i & 0x80) {
+               if (sd->bridge == BRIDGE_TP6800)
+                       fr = rates[6 - (i & 0x07)];
+               else
+                       fr = rates_6810[7 - (i & 0x07)];
+       } else {
+               fr = rates[6 - i];
+       }
+       tpf->denominator = fr;
+}
+
+/* set stream parameters (framerate) */
+static void sd_set_streamparm(struct gspca_dev *gspca_dev,
+                            struct v4l2_streamparm *parm)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct v4l2_captureparm *cp = &parm->parm.capture;
+       struct v4l2_fract *tpf = &cp->timeperframe;
+       int fr, i;
+
+       sd->framerate = tpf->denominator / tpf->numerator;
+       if (gspca_dev->streaming)
+               setframerate(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
+
+       /* Return the actual framerate */
+       i = get_fr_idx(gspca_dev);
+       if (i & 0x80)
+               fr = rates_6810[7 - (i & 0x07)];
+       else
+               fr = rates[6 - i];
+       tpf->numerator = 1;
+       tpf->denominator = fr;
+}
+
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+                       struct v4l2_jpegcompression *jcomp)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor != SENSOR_SOI763A)
+               return -ENOTTY;
+       v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
+       return 0;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+                       struct v4l2_jpegcompression *jcomp)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->sensor != SENSOR_SOI763A)
+               return -ENOTTY;
+       memset(jcomp, 0, sizeof *jcomp);
+       jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
+       jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+                       | V4L2_JPEG_MARKER_DQT;
+       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_SHARPNESS:
+               setsharpness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_GAMMA:
+               setgamma(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               setbgain(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_RED_BALANCE:
+               setrgain(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_EXPOSURE:
+               sd_setgain(gspca_dev);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if (ctrl->val)
+                       break;
+               sd_setgain(gspca_dev);
+               break;
+       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+               jpeg_set_qual(sd->jpeg_hdr, ctrl->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,
+                       V4L2_CID_EXPOSURE, 1, 0xdc, 1, 0x4e);
+       if (sd->sensor == SENSOR_CX0342) {
+               sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_RED_BALANCE, 0, 4095, 1, 256);
+               sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BLUE_BALANCE, 0, 4095, 1, 256);
+       }
+       if (sd->sensor == SENSOR_SOI763A)
+               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 15, 1, 3);
+       else
+               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 4095, 1, 256);
+       sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SHARPNESS, 0, 3, 1, 2);
+       sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAMMA, 0, NGAMMA - 1, 1,
+                       (sd->sensor == SENSOR_SOI763A &&
+                        sd->bridge == BRIDGE_TP6800) ? 0 : 1);
+       if (sd->bridge == BRIDGE_TP6810)
+               gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+       if (sd->sensor == SENSOR_SOI763A)
+               sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_JPEG_COMPRESSION_QUALITY,
+                       0, 15, 1, (sd->bridge == BRIDGE_TP6810) ? 0 : 13);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       if (gspca_dev->autogain)
+               v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
+       else
+               v4l2_ctrl_cluster(2, &gspca_dev->exposure);
+       return 0;
+}
+
+static const struct sd_desc sd_desc = {
+       .name = KBUILD_MODNAME,
+       .config = sd_config,
+       .init = sd_init,
+       .init_controls = sd_init_controls,
+       .isoc_init = sd_isoc_init,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+       .dq_callback = sd_dq_callback,
+       .get_streamparm = sd_get_streamparm,
+       .set_streamparm = sd_set_streamparm,
+       .get_jcomp = sd_get_jcomp,
+       .set_jcomp = sd_set_jcomp,
+};
+
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x06a2, 0x0003), .driver_info = BRIDGE_TP6800},
+       {USB_DEVICE(0x06a2, 0x6810), .driver_info = BRIDGE_TP6810},
+       {}                      /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+static int sd_probe(struct usb_interface *interface,
+                   const struct usb_device_id *id)
+{
+       return gspca_dev_probe(interface, id, &sd_desc, sizeof(struct sd),
+                              THIS_MODULE);
+}
+
+static struct usb_driver sd_driver = {
+       .name = KBUILD_MODNAME,
+       .id_table = device_table,
+       .probe = sd_probe,
+       .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
+
+module_param(force_sensor, int, 0644);
+MODULE_PARM_DESC(force_sensor,
+       "Force sensor. 0: cx0342, 1: soi763a");
diff --git a/drivers/media/usb/gspca/tv8532.c b/drivers/media/usb/gspca/tv8532.c
new file mode 100644 (file)
index 0000000..8591324
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * Quickcam cameras initialization data
+ *
+ * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#define MODULE_NAME "tv8532"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
+MODULE_DESCRIPTION("TV8532 USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       __u8 packet;
+};
+
+static const struct v4l2_pix_format sif_mode[] = {
+       {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+
+/* TV-8532A (ICM532A) registers (LE) */
+#define R00_PART_CONTROL 0x00
+#define                LATENT_CHANGE   0x80
+#define                EXPO_CHANGE     0x04
+#define R01_TIMING_CONTROL_LOW 0x01
+#define                CMD_EEprom_Open 0x30
+#define                CMD_EEprom_Close 0x29
+#define R03_TABLE_ADDR 0x03
+#define R04_WTRAM_DATA_L 0x04
+#define R05_WTRAM_DATA_M 0x05
+#define R06_WTRAM_DATA_H 0x06
+#define R07_TABLE_LEN  0x07
+#define R08_RAM_WRITE_ACTION 0x08
+#define R0C_AD_WIDTHL  0x0c
+#define R0D_AD_WIDTHH  0x0d
+#define R0E_AD_HEIGHTL 0x0e
+#define R0F_AD_HEIGHTH 0x0f
+#define R10_AD_COL_BEGINL 0x10
+#define R11_AD_COL_BEGINH 0x11
+#define                MIRROR          0x04    /* [10] */
+#define R14_AD_ROW_BEGINL 0x14
+#define R15_AD_ROWBEGINH  0x15
+#define R1C_AD_EXPOSE_TIMEL 0x1c
+#define R20_GAIN_G1L   0x20
+#define R21_GAIN_G1H   0x21
+#define R22_GAIN_RL    0x22
+#define R23_GAIN_RH    0x23
+#define R24_GAIN_BL    0x24
+#define R25_GAIN_BH    0x25
+#define R26_GAIN_G2L   0x26
+#define R27_GAIN_G2H   0x27
+#define R28_QUANT      0x28
+#define R29_LINE       0x29
+#define R2C_POLARITY   0x2c
+#define R2D_POINT      0x2d
+#define R2E_POINTH     0x2e
+#define R2F_POINTB     0x2f
+#define R30_POINTBH    0x30
+#define R31_UPD                0x31
+#define R2A_HIGH_BUDGET 0x2a
+#define R2B_LOW_BUDGET 0x2b
+#define R34_VID                0x34
+#define R35_VIDH       0x35
+#define R36_PID                0x36
+#define R37_PIDH       0x37
+#define R39_Test1      0x39            /* GPIO */
+#define R3B_Test3      0x3b            /* GPIO */
+#define R83_AD_IDH     0x83
+#define R91_AD_SLOPEREG 0x91
+#define R94_AD_BITCONTROL 0x94
+
+static const u8 eeprom_data[][3] = {
+/*     dataH dataM dataL */
+       {0x01, 0x00, 0x01},
+       {0x01, 0x80, 0x11},
+       {0x05, 0x00, 0x14},
+       {0x05, 0x00, 0x1c},
+       {0x0d, 0x00, 0x1e},
+       {0x05, 0x00, 0x1f},
+       {0x05, 0x05, 0x19},
+       {0x05, 0x01, 0x1b},
+       {0x05, 0x09, 0x1e},
+       {0x0d, 0x89, 0x2e},
+       {0x05, 0x89, 0x2f},
+       {0x05, 0x0d, 0xd9},
+       {0x05, 0x09, 0xf1},
+};
+
+
+/* write 1 byte */
+static void reg_w1(struct gspca_dev *gspca_dev,
+                 __u16 index, __u8 value)
+{
+       gspca_dev->usb_buf[0] = value;
+       usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x02,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,      /* value */
+                       index, gspca_dev->usb_buf, 1, 500);
+}
+
+/* write 2 bytes */
+static void reg_w2(struct gspca_dev *gspca_dev,
+                 u16 index, u16 value)
+{
+       gspca_dev->usb_buf[0] = value;
+       gspca_dev->usb_buf[1] = value >> 8;
+       usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0x02,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,      /* value */
+                       index, gspca_dev->usb_buf, 2, 500);
+}
+
+static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev)
+{
+       int i;
+
+       reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Open);
+       for (i = 0; i < ARRAY_SIZE(eeprom_data); i++) {
+               reg_w1(gspca_dev, R03_TABLE_ADDR, i);
+               reg_w1(gspca_dev, R04_WTRAM_DATA_L, eeprom_data[i][2]);
+               reg_w1(gspca_dev, R05_WTRAM_DATA_M, eeprom_data[i][1]);
+               reg_w1(gspca_dev, R06_WTRAM_DATA_H, eeprom_data[i][0]);
+               reg_w1(gspca_dev, R08_RAM_WRITE_ACTION, 0);
+       }
+       reg_w1(gspca_dev, R07_TABLE_LEN, i);
+       reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close);
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                    const struct usb_device_id *id)
+{
+       struct cam *cam;
+
+       cam = &gspca_dev->cam;
+       cam->cam_mode = sif_mode;
+       cam->nmodes = ARRAY_SIZE(sif_mode);
+
+       return 0;
+}
+
+static void tv_8532_setReg(struct gspca_dev *gspca_dev)
+{
+       reg_w1(gspca_dev, R3B_Test3, 0x0a);     /* Test0Sel = 10 */
+       /******************************************************/
+       reg_w1(gspca_dev, R0E_AD_HEIGHTL, 0x90);
+       reg_w1(gspca_dev, R0F_AD_HEIGHTH, 0x01);
+       reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, 0x018f);
+       reg_w1(gspca_dev, R10_AD_COL_BEGINL, 0x44);
+                                               /* begin active line */
+       reg_w1(gspca_dev, R11_AD_COL_BEGINH, 0x00);
+                                               /* mirror and digital gain */
+       reg_w1(gspca_dev, R14_AD_ROW_BEGINL, 0x0a);
+
+       reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x02);
+       reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00);
+       reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE);
+                                               /* = 0x84 */
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       tv_8532WriteEEprom(gspca_dev);
+
+       return 0;
+}
+
+static void setexposure(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, val);
+       reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE);
+                                               /* 0x84 */
+}
+
+static void setgain(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_w2(gspca_dev, R20_GAIN_G1L, val);
+       reg_w2(gspca_dev, R22_GAIN_RL, val);
+       reg_w2(gspca_dev, R24_GAIN_BL, val);
+       reg_w2(gspca_dev, R26_GAIN_G2L, val);
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8);         /* 0x20; 0x0c */
+       reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03);
+
+       /************************************************/
+       reg_w1(gspca_dev, R28_QUANT, 0x90);
+                                       /* 0x72 compressed mode 0x28 */
+       if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
+               /* 176x144 */
+               reg_w1(gspca_dev, R29_LINE, 0x41);
+                                       /* CIF - 2 lines/packet */
+       } else {
+               /* 352x288 */
+               reg_w1(gspca_dev, R29_LINE, 0x81);
+                                       /* CIF - 2 lines/packet */
+       }
+       /************************************************/
+       reg_w1(gspca_dev, R2C_POLARITY, 0x10);          /* slow clock */
+       reg_w1(gspca_dev, R2D_POINT, 0x14);
+       reg_w1(gspca_dev, R2E_POINTH, 0x01);
+       reg_w1(gspca_dev, R2F_POINTB, 0x12);
+       reg_w1(gspca_dev, R30_POINTBH, 0x01);
+
+       tv_8532_setReg(gspca_dev);
+
+       /************************************************/
+       reg_w1(gspca_dev, R31_UPD, 0x01);       /* update registers */
+       msleep(200);
+       reg_w1(gspca_dev, R31_UPD, 0x00);       /* end update */
+
+       gspca_dev->empty_packet = 0;            /* check the empty packets */
+       sd->packet = 0;                         /* ignore the first packets */
+
+       return 0;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       reg_w1(gspca_dev, R3B_Test3, 0x0b);     /* Test0Sel = 11 = GPIO */
+}
+
+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;
+       int packet_type0, packet_type1;
+
+       packet_type0 = packet_type1 = INTER_PACKET;
+       if (gspca_dev->empty_packet) {
+               gspca_dev->empty_packet = 0;
+               sd->packet = gspca_dev->height / 2;
+               packet_type0 = FIRST_PACKET;
+       } else if (sd->packet == 0)
+               return;                 /* 2 more lines in 352x288 ! */
+       sd->packet--;
+       if (sd->packet == 0)
+               packet_type1 = LAST_PACKET;
+
+       /* each packet contains:
+        * - header 2 bytes
+        * - RGRG line
+        * - 4 bytes
+        * - GBGB line
+        * - 4 bytes
+        */
+       gspca_frame_add(gspca_dev, packet_type0,
+                       data + 2, gspca_dev->width);
+       gspca_frame_add(gspca_dev, packet_type1,
+                       data + gspca_dev->width + 5, gspca_dev->width);
+}
+
+static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct gspca_dev *gspca_dev =
+               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
+
+       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:
+               setgain(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 2);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0, 0x18f, 1, 0x18f);
+       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 0x7ff, 1, 0x100);
+
+       if (hdl->error) {
+               pr_err("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,
+       .stopN = sd_stopN,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x046d, 0x0920)},
+       {USB_DEVICE(0x046d, 0x0921)},
+       {USB_DEVICE(0x0545, 0x808b)},
+       {USB_DEVICE(0x0545, 0x8333)},
+       {USB_DEVICE(0x0923, 0x010f)},
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/vc032x.c b/drivers/media/usb/gspca/vc032x.c
new file mode 100644 (file)
index 0000000..e500795
--- /dev/null
@@ -0,0 +1,3850 @@
+/*
+ * Z-star vc0321 library
+ *
+ * Copyright (C) 2009-2010 Jean-François Moine <http://moinejf.free.fr>
+ * Copyright (C) 2006 Koninski Artur takeshi87@o2.pl
+ * Copyright (C) 2006 Michel Xhaard
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "vc032x"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
+MODULE_DESCRIPTION("GSPCA/VC032X USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+       struct { /* hvflip cluster */
+               struct v4l2_ctrl *hflip;
+               struct v4l2_ctrl *vflip;
+       };
+
+       u8 image_offset;
+
+       u8 bridge;
+       u8 sensor;
+       u8 flags;
+#define FL_SAMSUNG 0x01                /* SamsungQ1 (2 sensors) */
+#define FL_HFLIP 0x02          /* mirrored by default */
+#define FL_VFLIP 0x04          /* vertical flipped by default */
+};
+enum bridges {
+       BRIDGE_VC0321,
+       BRIDGE_VC0323,
+};
+enum sensors {
+       SENSOR_HV7131R,
+       SENSOR_MI0360,
+       SENSOR_MI1310_SOC,
+       SENSOR_MI1320,
+       SENSOR_MI1320_SOC,
+       SENSOR_OV7660,
+       SENSOR_OV7670,
+       SENSOR_PO1200,
+       SENSOR_PO3130NC,
+       SENSOR_POxxxx,
+       NSENSORS
+};
+
+
+static const struct v4l2_pix_format vc0321_mode[] = {
+       {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+static const struct v4l2_pix_format vc0323_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+       {1280, 960, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi1310_soc only */
+               .bytesperline = 1280,
+               .sizeimage = 1280 * 960 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2},
+};
+static const struct v4l2_pix_format bi_mode[] = {
+       {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+       {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {1280, 1024, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
+               .bytesperline = 1280,
+               .sizeimage = 1280 * 1024 * 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
+};
+static const struct v4l2_pix_format svga_mode[] = {
+       {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 800,
+               .sizeimage = 800 * 600 * 1 / 4 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+
+/* OV7660/7670 registers */
+#define OV7660_REG_MVFP 0x1e
+#define OV7660_MVFP_MIRROR     0x20
+#define OV7660_MVFP_VFLIP      0x10
+
+static const u8 mi0360_matrix[9] = {
+       0x50, 0xf8, 0xf8, 0xf5, 0x50, 0xfb, 0xff, 0xf1, 0x50
+};
+
+static const u8 mi0360_initVGA_JPG[][4] = {
+       {0xb0, 0x03, 0x19, 0xcc},
+       {0xb0, 0x04, 0x02, 0xcc},
+       {0xb3, 0x00, 0x24, 0xcc},
+       {0xb3, 0x00, 0x25, 0xcc},
+       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},
+       {0xb3, 0x05, 0x01, 0xcc},
+       {0xb3, 0x06, 0x03, 0xcc},
+       {0xb3, 0x03, 0x0a, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x01, 0xcc},
+       {0xb3, 0x23, 0xe0, 0xcc},
+       {0xb3, 0x04, 0x05, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},
+       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x02, 0xcc},
+       {0xb3, 0x17, 0x7f, 0xcc},
+       {0xb3, 0x35, 0xdd, 0xcc},       /* i2c add: 5d */
+       {0xb3, 0x34, 0x02, 0xcc},
+       {0xb3, 0x00, 0x25, 0xcc},
+       {0xbc, 0x00, 0x71, 0xcc},
+       {0xb8, 0x00, 0x13, 0xcc},
+       {0xb8, 0x27, 0x20, 0xcc},
+       {0xb8, 0x2c, 0x50, 0xcc},
+       {0xb8, 0x2d, 0xf8, 0xcc},
+       {0xb8, 0x2e, 0xf8, 0xcc},
+       {0xb8, 0x2f, 0xf8, 0xcc},
+       {0xb8, 0x30, 0x50, 0xcc},
+       {0xb8, 0x31, 0xf8, 0xcc},
+       {0xb8, 0x32, 0xf8, 0xcc},
+       {0xb8, 0x33, 0xf8, 0xcc},
+       {0xb8, 0x34, 0x50, 0xcc},
+       {0xb8, 0x35, 0x00, 0xcc},
+       {0xb8, 0x36, 0x00, 0xcc},
+       {0xb8, 0x37, 0x00, 0xcc},
+       {0xb8, 0x01, 0x79, 0xcc},
+       {0xb8, 0x08, 0xe0, 0xcc},
+       {0xb3, 0x01, 0x41, 0xcc},
+       {0xb8, 0x01, 0x79, 0xcc},
+       {0xb8, 0x14, 0x18, 0xcc},
+       {0xb8, 0xb2, 0x0a, 0xcc},
+       {0xb8, 0xb4, 0x0a, 0xcc},
+       {0xb8, 0xb5, 0x0a, 0xcc},
+       {0xb8, 0xfe, 0x00, 0xcc},
+       {0xb8, 0xff, 0x28, 0xcc},
+       {0xb9, 0x00, 0x28, 0xcc},
+       {0xb9, 0x01, 0x28, 0xcc},
+       {0xb9, 0x02, 0x28, 0xcc},
+       {0xb9, 0x03, 0x00, 0xcc},
+       {0xb9, 0x04, 0x00, 0xcc},
+       {0xb9, 0x05, 0x3c, 0xcc},
+       {0xb9, 0x06, 0x3c, 0xcc},
+       {0xb9, 0x07, 0x3c, 0xcc},
+       {0xb9, 0x08, 0x3c, 0xcc},
+       {0xb8, 0x8e, 0x00, 0xcc},
+       {0xb8, 0x8f, 0xff, 0xcc},
+       {0xb8, 0x81, 0x09, 0xcc},
+       {0x31, 0x00, 0x00, 0xbb},
+       {0x09, 0x01, 0xc7, 0xbb},
+       {0x34, 0x01, 0x00, 0xbb},
+       {0x2b, 0x00, 0x28, 0xbb},
+       {0x2c, 0x00, 0x30, 0xbb},
+       {0x2d, 0x00, 0x30, 0xbb},
+       {0x2e, 0x00, 0x28, 0xbb},
+       {0x62, 0x04, 0x11, 0xbb},
+       {0x03, 0x01, 0xe0, 0xbb},
+       {0x2c, 0x00, 0x2c, 0xbb},
+       {0x20, 0xd0, 0x00, 0xbb},
+       {0x01, 0x00, 0x08, 0xbb},
+       {0x06, 0x00, 0x10, 0xbb},
+       {0x05, 0x00, 0x20, 0xbb},
+       {0x20, 0x00, 0x00, 0xbb},
+       {0xb6, 0x00, 0x00, 0xcc},
+       {0xb6, 0x03, 0x02, 0xcc},
+       {0xb6, 0x02, 0x80, 0xcc},
+       {0xb6, 0x05, 0x01, 0xcc},
+       {0xb6, 0x04, 0xe0, 0xcc},
+       {0xb6, 0x12, 0x78, 0xcc},
+       {0xb6, 0x18, 0x02, 0xcc},
+       {0xb6, 0x17, 0x58, 0xcc},
+       {0xb6, 0x16, 0x00, 0xcc},
+       {0xb6, 0x22, 0x12, 0xcc},
+       {0xb6, 0x23, 0x0b, 0xcc},
+       {0xb3, 0x02, 0x02, 0xcc},
+       {0xbf, 0xc0, 0x39, 0xcc},
+       {0xbf, 0xc1, 0x04, 0xcc},
+       {0xbf, 0xcc, 0x10, 0xcc},
+       {0xb9, 0x12, 0x00, 0xcc},
+       {0xb9, 0x13, 0x0a, 0xcc},
+       {0xb9, 0x14, 0x0a, 0xcc},
+       {0xb9, 0x15, 0x0a, 0xcc},
+       {0xb9, 0x16, 0x0a, 0xcc},
+       {0xb9, 0x18, 0x00, 0xcc},
+       {0xb9, 0x19, 0x0f, 0xcc},
+       {0xb9, 0x1a, 0x0f, 0xcc},
+       {0xb9, 0x1b, 0x0f, 0xcc},
+       {0xb9, 0x1c, 0x0f, 0xcc},
+       {0xb8, 0x8e, 0x00, 0xcc},
+       {0xb8, 0x8f, 0xff, 0xcc},
+       {0xb6, 0x12, 0xf8, 0xcc},
+       {0xb8, 0x0c, 0x20, 0xcc},
+       {0xb8, 0x0d, 0x70, 0xcc},
+       {0xb6, 0x13, 0x13, 0xcc},
+       {0x35, 0x00, 0x60, 0xbb},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {}
+};
+static const u8 mi0360_initQVGA_JPG[][4] = {
+       {0xb0, 0x03, 0x19, 0xcc},
+       {0xb0, 0x04, 0x02, 0xcc},
+       {0xb3, 0x00, 0x24, 0xcc},
+       {0xb3, 0x00, 0x25, 0xcc},
+       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},
+       {0xb3, 0x05, 0x01, 0xcc},
+       {0xb3, 0x06, 0x03, 0xcc},
+       {0xb3, 0x03, 0x0a, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x01, 0xcc},
+       {0xb3, 0x23, 0xe0, 0xcc},
+       {0xb3, 0x04, 0x05, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},
+       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x02, 0xcc},
+       {0xb3, 0x17, 0x7f, 0xcc},
+       {0xb3, 0x35, 0xdd, 0xcc},
+       {0xb3, 0x34, 0x02, 0xcc},
+       {0xb3, 0x00, 0x25, 0xcc},
+       {0xbc, 0x00, 0xd1, 0xcc},
+       {0xb8, 0x00, 0x13, 0xcc},
+       {0xb8, 0x27, 0x20, 0xcc},
+       {0xb8, 0x2c, 0x50, 0xcc},
+       {0xb8, 0x2d, 0xf8, 0xcc},
+       {0xb8, 0x2e, 0xf8, 0xcc},
+       {0xb8, 0x2f, 0xf8, 0xcc},
+       {0xb8, 0x30, 0x50, 0xcc},
+       {0xb8, 0x31, 0xf8, 0xcc},
+       {0xb8, 0x32, 0xf8, 0xcc},
+       {0xb8, 0x33, 0xf8, 0xcc},
+       {0xb8, 0x34, 0x50, 0xcc},
+       {0xb8, 0x35, 0x00, 0xcc},
+       {0xb8, 0x36, 0x00, 0xcc},
+       {0xb8, 0x37, 0x00, 0xcc},
+       {0xb8, 0x01, 0x79, 0xcc},
+       {0xb8, 0x08, 0xe0, 0xcc},
+       {0xb3, 0x01, 0x41, 0xcc},
+       {0xb8, 0x01, 0x79, 0xcc},
+       {0xb8, 0x14, 0x18, 0xcc},
+       {0xb8, 0xb2, 0x0a, 0xcc},
+       {0xb8, 0xb4, 0x0a, 0xcc},
+       {0xb8, 0xb5, 0x0a, 0xcc},
+       {0xb8, 0xfe, 0x00, 0xcc},
+       {0xb8, 0xff, 0x28, 0xcc},
+       {0xb9, 0x00, 0x28, 0xcc},
+       {0xb9, 0x01, 0x28, 0xcc},
+       {0xb9, 0x02, 0x28, 0xcc},
+       {0xb9, 0x03, 0x00, 0xcc},
+       {0xb9, 0x04, 0x00, 0xcc},
+       {0xb9, 0x05, 0x3c, 0xcc},
+       {0xb9, 0x06, 0x3c, 0xcc},
+       {0xb9, 0x07, 0x3c, 0xcc},
+       {0xb9, 0x08, 0x3c, 0xcc},
+       {0xb8, 0x8e, 0x00, 0xcc},
+       {0xb8, 0x8f, 0xff, 0xcc},
+       {0xb8, 0x81, 0x09, 0xcc},
+       {0x31, 0x00, 0x00, 0xbb},
+       {0x09, 0x01, 0xc7, 0xbb},
+       {0x34, 0x01, 0x00, 0xbb},
+       {0x2b, 0x00, 0x28, 0xbb},
+       {0x2c, 0x00, 0x30, 0xbb},
+       {0x2d, 0x00, 0x30, 0xbb},
+       {0x2e, 0x00, 0x28, 0xbb},
+       {0x62, 0x04, 0x11, 0xbb},
+       {0x03, 0x01, 0xe0, 0xbb},
+       {0x2c, 0x00, 0x2c, 0xbb},
+       {0x20, 0xd0, 0x00, 0xbb},
+       {0x01, 0x00, 0x08, 0xbb},
+       {0x06, 0x00, 0x10, 0xbb},
+       {0x05, 0x00, 0x20, 0xbb},
+       {0x20, 0x00, 0x00, 0xbb},
+       {0xb6, 0x00, 0x00, 0xcc},
+       {0xb6, 0x03, 0x01, 0xcc},
+       {0xb6, 0x02, 0x40, 0xcc},
+       {0xb6, 0x05, 0x00, 0xcc},
+       {0xb6, 0x04, 0xf0, 0xcc},
+       {0xb6, 0x12, 0x78, 0xcc},
+       {0xb6, 0x18, 0x00, 0xcc},
+       {0xb6, 0x17, 0x96, 0xcc},
+       {0xb6, 0x16, 0x00, 0xcc},
+       {0xb6, 0x22, 0x12, 0xcc},
+       {0xb6, 0x23, 0x0b, 0xcc},
+       {0xb3, 0x02, 0x02, 0xcc},
+       {0xbf, 0xc0, 0x39, 0xcc},
+       {0xbf, 0xc1, 0x04, 0xcc},
+       {0xbf, 0xcc, 0x10, 0xcc},
+       {0xb9, 0x12, 0x00, 0xcc},
+       {0xb9, 0x13, 0x0a, 0xcc},
+       {0xb9, 0x14, 0x0a, 0xcc},
+       {0xb9, 0x15, 0x0a, 0xcc},
+       {0xb9, 0x16, 0x0a, 0xcc},
+       {0xb9, 0x18, 0x00, 0xcc},
+       {0xb9, 0x19, 0x0f, 0xcc},
+       {0xb9, 0x1a, 0x0f, 0xcc},
+       {0xb9, 0x1b, 0x0f, 0xcc},
+       {0xb9, 0x1c, 0x0f, 0xcc},
+       {0xb8, 0x8e, 0x00, 0xcc},
+       {0xb8, 0x8f, 0xff, 0xcc},
+       {0xb6, 0x12, 0xf8, 0xcc},
+       {0xb6, 0x13, 0x13, 0xcc},
+       {0xbc, 0x02, 0x18, 0xcc},
+       {0xbc, 0x03, 0x50, 0xcc},
+       {0xbc, 0x04, 0x18, 0xcc},
+       {0xbc, 0x05, 0x00, 0xcc},
+       {0xbc, 0x06, 0x00, 0xcc},
+       {0xbc, 0x08, 0x30, 0xcc},
+       {0xbc, 0x09, 0x40, 0xcc},
+       {0xbc, 0x0a, 0x10, 0xcc},
+       {0xb8, 0x0c, 0x20, 0xcc},
+       {0xb8, 0x0d, 0x70, 0xcc},
+       {0xbc, 0x0b, 0x00, 0xcc},
+       {0xbc, 0x0c, 0x00, 0xcc},
+       {0x35, 0x00, 0xef, 0xbb},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {}
+};
+
+static const u8 mi1310_socinitVGA_JPG[][4] = {
+       {0xb0, 0x03, 0x19, 0xcc},
+       {0xb0, 0x04, 0x02, 0xcc},
+       {0xb3, 0x00, 0x64, 0xcc},
+       {0xb3, 0x00, 0x65, 0xcc},
+       {0xb3, 0x05, 0x00, 0xcc},
+       {0xb3, 0x06, 0x00, 0xcc},
+       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},
+       {0xb3, 0x34, 0x02, 0xcc},
+       {0xb3, 0x35, 0xdd, 0xcc},       /* i2c add: 5d */
+       {0xb3, 0x02, 0x00, 0xcc},
+       {0xb3, 0x03, 0x0a, 0xcc},
+       {0xb3, 0x04, 0x05, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x03, 0xcc},
+       {0xb3, 0x23, 0xc0, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},
+       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x04, 0xcc},
+       {0xb3, 0x17, 0xff, 0xcc},
+       {0xb3, 0x00, 0x65, 0xcc},
+       {0xb8, 0x00, 0x00, 0xcc},
+       {0xbc, 0x00, 0xd0, 0xcc},
+       {0xbc, 0x01, 0x01, 0xcc},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0xc8, 0x9f, 0x0b, 0xbb},
+       {0x5b, 0x00, 0x01, 0xbb},
+       {0x2f, 0xde, 0x20, 0xbb},
+       {0xf0, 0x00, 0x00, 0xbb},
+       {0x20, 0x03, 0x02, 0xbb},       /* h/v flip */
+       {0xf0, 0x00, 0x01, 0xbb},
+       {0x05, 0x00, 0x07, 0xbb},
+       {0x34, 0x00, 0x00, 0xbb},
+       {0x35, 0xff, 0x00, 0xbb},
+       {0xdc, 0x07, 0x02, 0xbb},
+       {0xdd, 0x3c, 0x18, 0xbb},
+       {0xde, 0x92, 0x6d, 0xbb},
+       {0xdf, 0xcd, 0xb1, 0xbb},
+       {0xe0, 0xff, 0xe7, 0xbb},
+       {0x06, 0xf0, 0x0d, 0xbb},
+       {0x06, 0x70, 0x0e, 0xbb},
+       {0x4c, 0x00, 0x01, 0xbb},
+       {0x4d, 0x00, 0x01, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x2e, 0x0c, 0x55, 0xbb},
+       {0x21, 0xb6, 0x6e, 0xbb},
+       {0x36, 0x30, 0x10, 0xbb},
+       {0x37, 0x00, 0xc1, 0xbb},
+       {0xf0, 0x00, 0x00, 0xbb},
+       {0x07, 0x00, 0x84, 0xbb},
+       {0x08, 0x02, 0x4a, 0xbb},
+       {0x05, 0x01, 0x10, 0xbb},
+       {0x06, 0x00, 0x39, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x58, 0x02, 0x67, 0xbb},
+       {0x57, 0x02, 0x00, 0xbb},
+       {0x5a, 0x02, 0x67, 0xbb},
+       {0x59, 0x02, 0x00, 0xbb},
+       {0x5c, 0x12, 0x0d, 0xbb},
+       {0x5d, 0x16, 0x11, 0xbb},
+       {0x39, 0x06, 0x18, 0xbb},
+       {0x3a, 0x06, 0x18, 0xbb},
+       {0x3b, 0x06, 0x18, 0xbb},
+       {0x3c, 0x06, 0x18, 0xbb},
+       {0x64, 0x7b, 0x5b, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x36, 0x30, 0x10, 0xbb},
+       {0x37, 0x00, 0xc0, 0xbb},
+       {0xbc, 0x0e, 0x00, 0xcc},
+       {0xbc, 0x0f, 0x05, 0xcc},
+       {0xbc, 0x10, 0xc0, 0xcc},
+       {0xbc, 0x11, 0x03, 0xcc},
+       {0xb6, 0x00, 0x00, 0xcc},
+       {0xb6, 0x03, 0x02, 0xcc},
+       {0xb6, 0x02, 0x80, 0xcc},
+       {0xb6, 0x05, 0x01, 0xcc},
+       {0xb6, 0x04, 0xe0, 0xcc},
+       {0xb6, 0x12, 0xf8, 0xcc},
+       {0xb6, 0x13, 0x25, 0xcc},
+       {0xb6, 0x18, 0x02, 0xcc},
+       {0xb6, 0x17, 0x58, 0xcc},
+       {0xb6, 0x16, 0x00, 0xcc},
+       {0xb6, 0x22, 0x12, 0xcc},
+       {0xb6, 0x23, 0x0b, 0xcc},
+       {0xbf, 0xc0, 0x39, 0xcc},
+       {0xbf, 0xc1, 0x04, 0xcc},
+       {0xbf, 0xcc, 0x00, 0xcc},
+       {0xbc, 0x02, 0x18, 0xcc},
+       {0xbc, 0x03, 0x50, 0xcc},
+       {0xbc, 0x04, 0x18, 0xcc},
+       {0xbc, 0x05, 0x00, 0xcc},
+       {0xbc, 0x06, 0x00, 0xcc},
+       {0xbc, 0x08, 0x30, 0xcc},
+       {0xbc, 0x09, 0x40, 0xcc},
+       {0xbc, 0x0a, 0x10, 0xcc},
+       {0xbc, 0x0b, 0x00, 0xcc},
+       {0xbc, 0x0c, 0x00, 0xcc},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {0xf0, 0x00, 0x01, 0xbb},
+       {0x80, 0x00, 0x03, 0xbb},
+       {0x81, 0xc7, 0x14, 0xbb},
+       {0x82, 0xeb, 0xe8, 0xbb},
+       {0x83, 0xfe, 0xf4, 0xbb},
+       {0x84, 0xcd, 0x10, 0xbb},
+       {0x85, 0xf3, 0xee, 0xbb},
+       {0x86, 0xff, 0xf1, 0xbb},
+       {0x87, 0xcd, 0x10, 0xbb},
+       {0x88, 0xf3, 0xee, 0xbb},
+       {0x89, 0x01, 0xf1, 0xbb},
+       {0x8a, 0xe5, 0x17, 0xbb},
+       {0x8b, 0xe8, 0xe2, 0xbb},
+       {0x8c, 0xf7, 0xed, 0xbb},
+       {0x8d, 0x00, 0xff, 0xbb},
+       {0x8e, 0xec, 0x10, 0xbb},
+       {0x8f, 0xf0, 0xed, 0xbb},
+       {0x90, 0xf9, 0xf2, 0xbb},
+       {0x91, 0x00, 0x00, 0xbb},
+       {0x92, 0xe9, 0x0d, 0xbb},
+       {0x93, 0xf4, 0xf2, 0xbb},
+       {0x94, 0xfb, 0xf5, 0xbb},
+       {0x95, 0x00, 0xff, 0xbb},
+       {0xb6, 0x0f, 0x08, 0xbb},
+       {0xb7, 0x3d, 0x16, 0xbb},
+       {0xb8, 0x0c, 0x04, 0xbb},
+       {0xb9, 0x1c, 0x07, 0xbb},
+       {0xba, 0x0a, 0x03, 0xbb},
+       {0xbb, 0x1b, 0x09, 0xbb},
+       {0xbc, 0x17, 0x0d, 0xbb},
+       {0xbd, 0x23, 0x1d, 0xbb},
+       {0xbe, 0x00, 0x28, 0xbb},
+       {0xbf, 0x11, 0x09, 0xbb},
+       {0xc0, 0x16, 0x15, 0xbb},
+       {0xc1, 0x00, 0x1b, 0xbb},
+       {0xc2, 0x0e, 0x07, 0xbb},
+       {0xc3, 0x14, 0x10, 0xbb},
+       {0xc4, 0x00, 0x17, 0xbb},
+       {0x06, 0x74, 0x8e, 0xbb},
+       {0xf0, 0x00, 0x01, 0xbb},
+       {0x06, 0xf4, 0x8e, 0xbb},
+       {0x00, 0x00, 0x50, 0xdd},
+       {0x06, 0x74, 0x8e, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x24, 0x50, 0x20, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x34, 0x0c, 0x50, 0xbb},
+       {0xb3, 0x01, 0x41, 0xcc},
+       {0xf0, 0x00, 0x00, 0xbb},
+       {0x03, 0x03, 0xc0, 0xbb},
+       {},
+};
+static const u8 mi1310_socinitQVGA_JPG[][4] = {
+       {0xb0, 0x03, 0x19, 0xcc},       {0xb0, 0x04, 0x02, 0xcc},
+       {0xb3, 0x00, 0x64, 0xcc},       {0xb3, 0x00, 0x65, 0xcc},
+       {0xb3, 0x05, 0x00, 0xcc},       {0xb3, 0x06, 0x00, 0xcc},
+       {0xb3, 0x08, 0x01, 0xcc},       {0xb3, 0x09, 0x0c, 0xcc},
+       {0xb3, 0x34, 0x02, 0xcc},       {0xb3, 0x35, 0xdd, 0xcc},
+       {0xb3, 0x02, 0x00, 0xcc},       {0xb3, 0x03, 0x0a, 0xcc},
+       {0xb3, 0x04, 0x05, 0xcc},       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},       {0xb3, 0x22, 0x03, 0xcc},
+       {0xb3, 0x23, 0xc0, 0xcc},       {0xb3, 0x14, 0x00, 0xcc},
+       {0xb3, 0x15, 0x00, 0xcc},       {0xb3, 0x16, 0x04, 0xcc},
+       {0xb3, 0x17, 0xff, 0xcc},       {0xb3, 0x00, 0x65, 0xcc},
+       {0xb8, 0x00, 0x00, 0xcc},       {0xbc, 0x00, 0xf0, 0xcc},
+       {0xbc, 0x01, 0x01, 0xcc},       {0xf0, 0x00, 0x02, 0xbb},
+       {0xc8, 0x9f, 0x0b, 0xbb},       {0x5b, 0x00, 0x01, 0xbb},
+       {0x2f, 0xde, 0x20, 0xbb},       {0xf0, 0x00, 0x00, 0xbb},
+       {0x20, 0x03, 0x02, 0xbb},       /* h/v flip */
+       {0xf0, 0x00, 0x01, 0xbb},
+       {0x05, 0x00, 0x07, 0xbb},       {0x34, 0x00, 0x00, 0xbb},
+       {0x35, 0xff, 0x00, 0xbb},       {0xdc, 0x07, 0x02, 0xbb},
+       {0xdd, 0x3c, 0x18, 0xbb},       {0xde, 0x92, 0x6d, 0xbb},
+       {0xdf, 0xcd, 0xb1, 0xbb},       {0xe0, 0xff, 0xe7, 0xbb},
+       {0x06, 0xf0, 0x0d, 0xbb},       {0x06, 0x70, 0x0e, 0xbb},
+       {0x4c, 0x00, 0x01, 0xbb},       {0x4d, 0x00, 0x01, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},       {0x2e, 0x0c, 0x55, 0xbb},
+       {0x21, 0xb6, 0x6e, 0xbb},       {0x36, 0x30, 0x10, 0xbb},
+       {0x37, 0x00, 0xc1, 0xbb},       {0xf0, 0x00, 0x00, 0xbb},
+       {0x07, 0x00, 0x84, 0xbb},       {0x08, 0x02, 0x4a, 0xbb},
+       {0x05, 0x01, 0x10, 0xbb},       {0x06, 0x00, 0x39, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},       {0x58, 0x02, 0x67, 0xbb},
+       {0x57, 0x02, 0x00, 0xbb},       {0x5a, 0x02, 0x67, 0xbb},
+       {0x59, 0x02, 0x00, 0xbb},       {0x5c, 0x12, 0x0d, 0xbb},
+       {0x5d, 0x16, 0x11, 0xbb},       {0x39, 0x06, 0x18, 0xbb},
+       {0x3a, 0x06, 0x18, 0xbb},       {0x3b, 0x06, 0x18, 0xbb},
+       {0x3c, 0x06, 0x18, 0xbb},       {0x64, 0x7b, 0x5b, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},       {0x36, 0x30, 0x10, 0xbb},
+       {0x37, 0x00, 0xc0, 0xbb},       {0xbc, 0x0e, 0x00, 0xcc},
+       {0xbc, 0x0f, 0x05, 0xcc},       {0xbc, 0x10, 0xc0, 0xcc},
+       {0xbc, 0x11, 0x03, 0xcc},       {0xb6, 0x00, 0x00, 0xcc},
+       {0xb6, 0x03, 0x01, 0xcc},       {0xb6, 0x02, 0x40, 0xcc},
+       {0xb6, 0x05, 0x00, 0xcc},       {0xb6, 0x04, 0xf0, 0xcc},
+       {0xb6, 0x12, 0xf8, 0xcc},       {0xb6, 0x13, 0x25, 0xcc},
+       {0xb6, 0x18, 0x00, 0xcc},       {0xb6, 0x17, 0x96, 0xcc},
+       {0xb6, 0x16, 0x00, 0xcc},       {0xb6, 0x22, 0x12, 0xcc},
+       {0xb6, 0x23, 0x0b, 0xcc},       {0xbf, 0xc0, 0x39, 0xcc},
+       {0xbf, 0xc1, 0x04, 0xcc},       {0xbf, 0xcc, 0x00, 0xcc},
+       {0xb3, 0x5c, 0x01, 0xcc},       {0xf0, 0x00, 0x01, 0xbb},
+       {0x80, 0x00, 0x03, 0xbb},       {0x81, 0xc7, 0x14, 0xbb},
+       {0x82, 0xeb, 0xe8, 0xbb},       {0x83, 0xfe, 0xf4, 0xbb},
+       {0x84, 0xcd, 0x10, 0xbb},       {0x85, 0xf3, 0xee, 0xbb},
+       {0x86, 0xff, 0xf1, 0xbb},       {0x87, 0xcd, 0x10, 0xbb},
+       {0x88, 0xf3, 0xee, 0xbb},       {0x89, 0x01, 0xf1, 0xbb},
+       {0x8a, 0xe5, 0x17, 0xbb},       {0x8b, 0xe8, 0xe2, 0xbb},
+       {0x8c, 0xf7, 0xed, 0xbb},       {0x8d, 0x00, 0xff, 0xbb},
+       {0x8e, 0xec, 0x10, 0xbb},       {0x8f, 0xf0, 0xed, 0xbb},
+       {0x90, 0xf9, 0xf2, 0xbb},       {0x91, 0x00, 0x00, 0xbb},
+       {0x92, 0xe9, 0x0d, 0xbb},       {0x93, 0xf4, 0xf2, 0xbb},
+       {0x94, 0xfb, 0xf5, 0xbb},       {0x95, 0x00, 0xff, 0xbb},
+       {0xb6, 0x0f, 0x08, 0xbb},       {0xb7, 0x3d, 0x16, 0xbb},
+       {0xb8, 0x0c, 0x04, 0xbb},       {0xb9, 0x1c, 0x07, 0xbb},
+       {0xba, 0x0a, 0x03, 0xbb},       {0xbb, 0x1b, 0x09, 0xbb},
+       {0xbc, 0x17, 0x0d, 0xbb},       {0xbd, 0x23, 0x1d, 0xbb},
+       {0xbe, 0x00, 0x28, 0xbb},       {0xbf, 0x11, 0x09, 0xbb},
+       {0xc0, 0x16, 0x15, 0xbb},       {0xc1, 0x00, 0x1b, 0xbb},
+       {0xc2, 0x0e, 0x07, 0xbb},       {0xc3, 0x14, 0x10, 0xbb},
+       {0xc4, 0x00, 0x17, 0xbb},       {0x06, 0x74, 0x8e, 0xbb},
+       {0xf0, 0x00, 0x01, 0xbb},       {0x06, 0xf4, 0x8e, 0xbb},
+       {0x00, 0x00, 0x50, 0xdd},       {0x06, 0x74, 0x8e, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},       {0x24, 0x50, 0x20, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},       {0x34, 0x0c, 0x50, 0xbb},
+       {0xb3, 0x01, 0x41, 0xcc},       {0xf0, 0x00, 0x00, 0xbb},
+       {0x03, 0x03, 0xc0, 0xbb},
+       {},
+};
+static const u8 mi1310_soc_InitSXGA_JPG[][4] = {
+       {0xb0, 0x03, 0x19, 0xcc},
+       {0xb0, 0x04, 0x02, 0xcc},
+       {0xb3, 0x00, 0x64, 0xcc},
+       {0xb3, 0x00, 0x65, 0xcc},
+       {0xb3, 0x05, 0x00, 0xcc},
+       {0xb3, 0x06, 0x00, 0xcc},
+       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},
+       {0xb3, 0x34, 0x02, 0xcc},
+       {0xb3, 0x35, 0xdd, 0xcc},
+       {0xb3, 0x02, 0x00, 0xcc},
+       {0xb3, 0x03, 0x0a, 0xcc},
+       {0xb3, 0x04, 0x0d, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x03, 0xcc},
+       {0xb3, 0x23, 0xc0, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},
+       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x04, 0xcc},
+       {0xb3, 0x17, 0xff, 0xcc},
+       {0xb3, 0x00, 0x65, 0xcc},
+       {0xb8, 0x00, 0x00, 0xcc},
+       {0xbc, 0x00, 0x70, 0xcc},
+       {0xbc, 0x01, 0x01, 0xcc},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0xc8, 0x9f, 0x0b, 0xbb},
+       {0x5b, 0x00, 0x01, 0xbb},
+       {0xf0, 0x00, 0x00, 0xbb},
+       {0x20, 0x03, 0x02, 0xbb},       /* h/v flip */
+       {0xf0, 0x00, 0x01, 0xbb},
+       {0x05, 0x00, 0x07, 0xbb},
+       {0x34, 0x00, 0x00, 0xbb},
+       {0x35, 0xff, 0x00, 0xbb},
+       {0xdc, 0x07, 0x02, 0xbb},
+       {0xdd, 0x3c, 0x18, 0xbb},
+       {0xde, 0x92, 0x6d, 0xbb},
+       {0xdf, 0xcd, 0xb1, 0xbb},
+       {0xe0, 0xff, 0xe7, 0xbb},
+       {0x06, 0xf0, 0x0d, 0xbb},
+       {0x06, 0x70, 0x0e, 0xbb},
+       {0x4c, 0x00, 0x01, 0xbb},
+       {0x4d, 0x00, 0x01, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x2e, 0x0c, 0x60, 0xbb},
+       {0x21, 0xb6, 0x6e, 0xbb},
+       {0x37, 0x01, 0x40, 0xbb},
+       {0xf0, 0x00, 0x00, 0xbb},
+       {0x07, 0x00, 0x84, 0xbb},
+       {0x08, 0x02, 0x4a, 0xbb},
+       {0x05, 0x01, 0x10, 0xbb},
+       {0x06, 0x00, 0x39, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x58, 0x02, 0x67, 0xbb},
+       {0x57, 0x02, 0x00, 0xbb},
+       {0x5a, 0x02, 0x67, 0xbb},
+       {0x59, 0x02, 0x00, 0xbb},
+       {0x5c, 0x12, 0x0d, 0xbb},
+       {0x5d, 0x16, 0x11, 0xbb},
+       {0x39, 0x06, 0x18, 0xbb},
+       {0x3a, 0x06, 0x18, 0xbb},
+       {0x3b, 0x06, 0x18, 0xbb},
+       {0x3c, 0x06, 0x18, 0xbb},
+       {0x64, 0x7b, 0x5b, 0xbb},
+       {0xb6, 0x00, 0x00, 0xcc},
+       {0xb6, 0x03, 0x05, 0xcc},
+       {0xb6, 0x02, 0x00, 0xcc},
+       {0xb6, 0x05, 0x03, 0xcc},
+       {0xb6, 0x04, 0xc0, 0xcc},
+       {0xb6, 0x12, 0xf8, 0xcc},
+       {0xb6, 0x13, 0x29, 0xcc},
+       {0xb6, 0x18, 0x09, 0xcc},
+       {0xb6, 0x17, 0x60, 0xcc},
+       {0xb6, 0x16, 0x00, 0xcc},
+       {0xb6, 0x22, 0x12, 0xcc},
+       {0xb6, 0x23, 0x0b, 0xcc},
+       {0xbf, 0xc0, 0x39, 0xcc},
+       {0xbf, 0xc1, 0x04, 0xcc},
+       {0xbf, 0xcc, 0x00, 0xcc},
+       {0xb3, 0x01, 0x41, 0xcc},
+       {0x00, 0x00, 0x80, 0xdd},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x00, 0x00, 0x10, 0xdd},
+       {0x22, 0xa0, 0x78, 0xbb},
+       {0x23, 0xa0, 0x78, 0xbb},
+       {0x24, 0x7f, 0x00, 0xbb},
+       {0x28, 0xea, 0x02, 0xbb},
+       {0x29, 0x86, 0x7a, 0xbb},
+       {0x5e, 0x52, 0x4c, 0xbb},
+       {0x5f, 0x20, 0x24, 0xbb},
+       {0x60, 0x00, 0x02, 0xbb},
+       {0x02, 0x00, 0xee, 0xbb},
+       {0x03, 0x39, 0x23, 0xbb},
+       {0x04, 0x07, 0x24, 0xbb},
+       {0x09, 0x00, 0xc0, 0xbb},
+       {0x0a, 0x00, 0x79, 0xbb},
+       {0x0b, 0x00, 0x04, 0xbb},
+       {0x0c, 0x00, 0x5c, 0xbb},
+       {0x0d, 0x00, 0xd9, 0xbb},
+       {0x0e, 0x00, 0x53, 0xbb},
+       {0x0f, 0x00, 0x21, 0xbb},
+       {0x10, 0x00, 0xa4, 0xbb},
+       {0x11, 0x00, 0xe5, 0xbb},
+       {0x15, 0x00, 0x00, 0xbb},
+       {0x16, 0x00, 0x00, 0xbb},
+       {0x17, 0x00, 0x00, 0xbb},
+       {0x18, 0x00, 0x00, 0xbb},
+       {0x19, 0x00, 0x00, 0xbb},
+       {0x1a, 0x00, 0x00, 0xbb},
+       {0x1b, 0x00, 0x00, 0xbb},
+       {0x1c, 0x00, 0x00, 0xbb},
+       {0x1d, 0x00, 0x00, 0xbb},
+       {0x1e, 0x00, 0x00, 0xbb},
+       {0xf0, 0x00, 0x01, 0xbb},
+       {0x00, 0x00, 0x20, 0xdd},
+       {0x06, 0xf0, 0x8e, 0xbb},
+       {0x00, 0x00, 0x80, 0xdd},
+       {0x06, 0x70, 0x8e, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x00, 0x00, 0x20, 0xdd},
+       {0x5e, 0x6a, 0x53, 0xbb},
+       {0x5f, 0x40, 0x2c, 0xbb},
+       {0xf0, 0x00, 0x01, 0xbb},
+       {0x00, 0x00, 0x20, 0xdd},
+       {0x58, 0x00, 0x00, 0xbb},
+       {0x53, 0x09, 0x03, 0xbb},
+       {0x54, 0x31, 0x18, 0xbb},
+       {0x55, 0x8b, 0x5f, 0xbb},
+       {0x56, 0xc0, 0xa9, 0xbb},
+       {0x57, 0xe0, 0xd2, 0xbb},
+       {0xe1, 0x00, 0x00, 0xbb},
+       {0xdc, 0x09, 0x03, 0xbb},
+       {0xdd, 0x31, 0x18, 0xbb},
+       {0xde, 0x8b, 0x5f, 0xbb},
+       {0xdf, 0xc0, 0xa9, 0xbb},
+       {0xe0, 0xe0, 0xd2, 0xbb},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {0xf0, 0x00, 0x01, 0xbb},
+       {0x06, 0xf0, 0x8e, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x2f, 0xde, 0x20, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x24, 0x50, 0x20, 0xbb},
+       {0xbc, 0x0e, 0x00, 0xcc},
+       {0xbc, 0x0f, 0x05, 0xcc},
+       {0xbc, 0x10, 0xc0, 0xcc},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x34, 0x0c, 0x50, 0xbb},
+       {0xbc, 0x11, 0x03, 0xcc},
+       {0xf0, 0x00, 0x01, 0xbb},
+       {0x80, 0x00, 0x03, 0xbb},
+       {0x81, 0xc7, 0x14, 0xbb},
+       {0x82, 0xeb, 0xe8, 0xbb},
+       {0x83, 0xfe, 0xf4, 0xbb},
+       {0x84, 0xcd, 0x10, 0xbb},
+       {0x85, 0xf3, 0xee, 0xbb},
+       {0x86, 0xff, 0xf1, 0xbb},
+       {0x87, 0xcd, 0x10, 0xbb},
+       {0x88, 0xf3, 0xee, 0xbb},
+       {0x89, 0x01, 0xf1, 0xbb},
+       {0x8a, 0xe5, 0x17, 0xbb},
+       {0x8b, 0xe8, 0xe2, 0xbb},
+       {0x8c, 0xf7, 0xed, 0xbb},
+       {0x8d, 0x00, 0xff, 0xbb},
+       {0x8e, 0xec, 0x10, 0xbb},
+       {0x8f, 0xf0, 0xed, 0xbb},
+       {0x90, 0xf9, 0xf2, 0xbb},
+       {0x91, 0x00, 0x00, 0xbb},
+       {0x92, 0xe9, 0x0d, 0xbb},
+       {0x93, 0xf4, 0xf2, 0xbb},
+       {0x94, 0xfb, 0xf5, 0xbb},
+       {0x95, 0x00, 0xff, 0xbb},
+       {0xb6, 0x0f, 0x08, 0xbb},
+       {0xb7, 0x3d, 0x16, 0xbb},
+       {0xb8, 0x0c, 0x04, 0xbb},
+       {0xb9, 0x1c, 0x07, 0xbb},
+       {0xba, 0x0a, 0x03, 0xbb},
+       {0xbb, 0x1b, 0x09, 0xbb},
+       {0xbc, 0x17, 0x0d, 0xbb},
+       {0xbd, 0x23, 0x1d, 0xbb},
+       {0xbe, 0x00, 0x28, 0xbb},
+       {0xbf, 0x11, 0x09, 0xbb},
+       {0xc0, 0x16, 0x15, 0xbb},
+       {0xc1, 0x00, 0x1b, 0xbb},
+       {0xc2, 0x0e, 0x07, 0xbb},
+       {0xc3, 0x14, 0x10, 0xbb},
+       {0xc4, 0x00, 0x17, 0xbb},
+       {0x06, 0x74, 0x8e, 0xbb},
+       {0xf0, 0x00, 0x00, 0xbb},
+       {0x03, 0x03, 0xc0, 0xbb},
+       {}
+};
+
+static const u8 mi1320_gamma[17] = {
+       0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
+       0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
+};
+static const u8 mi1320_matrix[9] = {
+       0x54, 0xda, 0x06, 0xf1, 0x50, 0xf4, 0xf7, 0xea, 0x52
+};
+static const u8 mi1320_initVGA_data[][4] = {
+       {0xb3, 0x01, 0x01, 0xcc},       {0x00, 0x00, 0x33, 0xdd},
+       {0xb0, 0x03, 0x19, 0xcc},       {0x00, 0x00, 0x33, 0xdd},
+       {0xb0, 0x04, 0x02, 0xcc},       {0x00, 0x00, 0x33, 0xdd},
+       {0xb3, 0x00, 0x64, 0xcc},       {0xb3, 0x00, 0x65, 0xcc},
+       {0xb0, 0x16, 0x03, 0xcc},       {0xb3, 0x05, 0x00, 0xcc},
+       {0xb3, 0x06, 0x00, 0xcc},       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},       {0xb3, 0x34, 0x02, 0xcc},
+       {0xb3, 0x35, 0xc8, 0xcc},       /* i2c add: 48 */
+       {0xb3, 0x02, 0x00, 0xcc},
+       {0xb3, 0x03, 0x0a, 0xcc},       {0xb3, 0x04, 0x05, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x03, 0xcc},       {0xb3, 0x23, 0xc0, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x04, 0xcc},       {0xb3, 0x17, 0xff, 0xcc},
+       {0xb3, 0x00, 0x67, 0xcc},       {0xbc, 0x00, 0xd0, 0xcc},
+       {0xbc, 0x01, 0x01, 0xcc},       {0xf0, 0x00, 0x00, 0xbb},
+       {0x0d, 0x00, 0x09, 0xbb},       {0x00, 0x01, 0x00, 0xdd},
+       {0x0d, 0x00, 0x08, 0xbb},       {0xf0, 0x00, 0x01, 0xbb},
+       {0xa1, 0x05, 0x00, 0xbb},       {0xa4, 0x03, 0xc0, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},       {0x00, 0x00, 0x10, 0xdd},
+       {0xc8, 0x9f, 0x0b, 0xbb},       {0x00, 0x00, 0x10, 0xdd},
+       {0xf0, 0x00, 0x00, 0xbb},       {0x00, 0x00, 0x10, 0xdd},
+       {0x20, 0x01, 0x00, 0xbb},       {0x00, 0x00, 0x10, 0xdd},
+       {0xf0, 0x00, 0x01, 0xbb},       {0x9d, 0x3c, 0xa0, 0xbb},
+       {0x47, 0x30, 0x30, 0xbb},       {0xf0, 0x00, 0x00, 0xbb},
+       {0x0a, 0x80, 0x11, 0xbb},       {0x35, 0x00, 0x22, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},       {0x9d, 0xc5, 0x05, 0xbb},
+       {0xdc, 0x0f, 0xfc, 0xbb},       {0xf0, 0x00, 0x01, 0xbb},
+       {0x06, 0x74, 0x0e, 0xbb},       {0x80, 0x00, 0x06, 0xbb},
+       {0x81, 0x04, 0x00, 0xbb},       {0x82, 0x01, 0x02, 0xbb},
+       {0x83, 0x03, 0x02, 0xbb},       {0x84, 0x05, 0x00, 0xbb},
+       {0x85, 0x01, 0x00, 0xbb},       {0x86, 0x03, 0x02, 0xbb},
+       {0x87, 0x05, 0x00, 0xbb},       {0x88, 0x01, 0x00, 0xbb},
+       {0x89, 0x02, 0x02, 0xbb},       {0x8a, 0xfd, 0x04, 0xbb},
+       {0x8b, 0xfc, 0xfd, 0xbb},       {0x8c, 0xff, 0xfd, 0xbb},
+       {0x8d, 0x00, 0x00, 0xbb},       {0x8e, 0xfe, 0x05, 0xbb},
+       {0x8f, 0xfc, 0xfd, 0xbb},       {0x90, 0xfe, 0xfd, 0xbb},
+       {0x91, 0x00, 0x00, 0xbb},       {0x92, 0xfe, 0x03, 0xbb},
+       {0x93, 0xfd, 0xfe, 0xbb},       {0x94, 0xff, 0xfd, 0xbb},
+       {0x95, 0x00, 0x00, 0xbb},       {0xb6, 0x07, 0x05, 0xbb},
+       {0xb7, 0x13, 0x06, 0xbb},       {0xb8, 0x08, 0x06, 0xbb},
+       {0xb9, 0x14, 0x08, 0xbb},       {0xba, 0x06, 0x05, 0xbb},
+       {0xbb, 0x13, 0x06, 0xbb},       {0xbc, 0x03, 0x01, 0xbb},
+       {0xbd, 0x03, 0x04, 0xbb},       {0xbe, 0x00, 0x02, 0xbb},
+       {0xbf, 0x03, 0x01, 0xbb},       {0xc0, 0x02, 0x04, 0xbb},
+       {0xc1, 0x00, 0x04, 0xbb},       {0xc2, 0x02, 0x01, 0xbb},
+       {0xc3, 0x01, 0x03, 0xbb},       {0xc4, 0x00, 0x04, 0xbb},
+       {0xf0, 0x00, 0x00, 0xbb},       {0x05, 0x01, 0x13, 0xbb},
+       {0x06, 0x00, 0x11, 0xbb},       {0x07, 0x00, 0x85, 0xbb},
+       {0x08, 0x00, 0x27, 0xbb},
+       {0x20, 0x01, 0x00, 0xbb},       /* h/v flips - was 03 */
+       {0x21, 0x80, 0x00, 0xbb},       {0x22, 0x0d, 0x0f, 0xbb},
+       {0x24, 0x80, 0x00, 0xbb},       {0x59, 0x00, 0xff, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},       {0x39, 0x03, 0x0d, 0xbb},
+       {0x3a, 0x06, 0x1b, 0xbb},       {0x3b, 0x00, 0x95, 0xbb},
+       {0x3c, 0x04, 0xdb, 0xbb},       {0x57, 0x02, 0x00, 0xbb},
+       {0x58, 0x02, 0x66, 0xbb},       {0x59, 0x00, 0xff, 0xbb},
+       {0x5a, 0x01, 0x33, 0xbb},       {0x5c, 0x12, 0x0d, 0xbb},
+       {0x5d, 0x16, 0x11, 0xbb},       {0x64, 0x5e, 0x1c, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},       {0x2f, 0xd1, 0x00, 0xbb},
+       {0x5b, 0x00, 0x01, 0xbb},       {0xf0, 0x00, 0x02, 0xbb},
+       {0x36, 0x68, 0x10, 0xbb},       {0x00, 0x00, 0x30, 0xdd},
+       {0x37, 0x82, 0x00, 0xbb},       {0xbc, 0x0e, 0x00, 0xcc},
+       {0xbc, 0x0f, 0x05, 0xcc},       {0xbc, 0x10, 0xc0, 0xcc},
+       {0xbc, 0x11, 0x03, 0xcc},       {0xb6, 0x00, 0x00, 0xcc},
+       {0xb6, 0x03, 0x05, 0xcc},       {0xb6, 0x02, 0x00, 0xcc},
+       {0xb6, 0x05, 0x04, 0xcc},       {0xb6, 0x04, 0x00, 0xcc},
+       {0xb6, 0x12, 0xf8, 0xcc},       {0xb6, 0x13, 0x29, 0xcc},
+       {0xb6, 0x18, 0x0a, 0xcc},       {0xb6, 0x17, 0x00, 0xcc},
+       {0xb6, 0x16, 0x00, 0xcc},       {0xb6, 0x22, 0x12, 0xcc},
+       {0xb6, 0x23, 0x0b, 0xcc},       {0xbf, 0xc0, 0x26, 0xcc},
+       {0xbf, 0xc1, 0x02, 0xcc},       {0xbf, 0xcc, 0x04, 0xcc},
+       {0xbc, 0x02, 0x18, 0xcc},       {0xbc, 0x03, 0x50, 0xcc},
+       {0xbc, 0x04, 0x18, 0xcc},       {0xbc, 0x05, 0x00, 0xcc},
+       {0xbc, 0x06, 0x00, 0xcc},       {0xbc, 0x08, 0x30, 0xcc},
+       {0xbc, 0x09, 0x40, 0xcc},       {0xbc, 0x0a, 0x10, 0xcc},
+       {0xbc, 0x0b, 0x00, 0xcc},       {0xbc, 0x0c, 0x00, 0xcc},
+       {0xb3, 0x5c, 0x01, 0xcc},       {0xb3, 0x01, 0x41, 0xcc},
+       {}
+};
+static const u8 mi1320_initQVGA_data[][4] = {
+       {0xb3, 0x01, 0x01, 0xcc},       {0x00, 0x00, 0x33, 0xdd},
+       {0xb0, 0x03, 0x19, 0xcc},       {0x00, 0x00, 0x33, 0xdd},
+       {0xb0, 0x04, 0x02, 0xcc},       {0x00, 0x00, 0x33, 0xdd},
+       {0xb3, 0x00, 0x64, 0xcc},       {0xb3, 0x00, 0x65, 0xcc},
+       {0xb0, 0x16, 0x03, 0xcc},       {0xb3, 0x05, 0x01, 0xcc},
+       {0xb3, 0x06, 0x01, 0xcc},       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},       {0xb3, 0x34, 0x02, 0xcc},
+       {0xb3, 0x35, 0xc8, 0xcc},       {0xb3, 0x02, 0x00, 0xcc},
+       {0xb3, 0x03, 0x0a, 0xcc},       {0xb3, 0x04, 0x05, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x01, 0xcc},       {0xb3, 0x23, 0xe0, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x02, 0xcc},       {0xb3, 0x17, 0x7f, 0xcc},
+       {0xb3, 0x00, 0x65, 0xcc},       {0xb8, 0x00, 0x00, 0xcc},
+       {0xbc, 0x00, 0xd0, 0xcc},       {0xbc, 0x01, 0x01, 0xcc},
+       {0xf0, 0x00, 0x00, 0xbb},       {0x0d, 0x00, 0x09, 0xbb},
+       {0x00, 0x01, 0x00, 0xdd},       {0x0d, 0x00, 0x08, 0xbb},
+       {0xf0, 0x00, 0x00, 0xbb},       {0x02, 0x00, 0x64, 0xbb},
+       {0x05, 0x01, 0x78, 0xbb},       {0x06, 0x00, 0x11, 0xbb},
+       {0x07, 0x01, 0x42, 0xbb},       {0x08, 0x00, 0x11, 0xbb},
+       {0x20, 0x01, 0x00, 0xbb},       {0x21, 0x80, 0x00, 0xbb},
+       {0x22, 0x0d, 0x0f, 0xbb},       {0x24, 0x80, 0x00, 0xbb},
+       {0x59, 0x00, 0xff, 0xbb},       {0xf0, 0x00, 0x01, 0xbb},
+       {0x9d, 0x3c, 0xa0, 0xbb},       {0x47, 0x30, 0x30, 0xbb},
+       {0xf0, 0x00, 0x00, 0xbb},       {0x0a, 0x80, 0x11, 0xbb},
+       {0x35, 0x00, 0x22, 0xbb},       {0xf0, 0x00, 0x02, 0xbb},
+       {0x9d, 0xc5, 0x05, 0xbb},       {0xdc, 0x0f, 0xfc, 0xbb},
+       {0xf0, 0x00, 0x01, 0xbb},       {0x06, 0x74, 0x0e, 0xbb},
+       {0x80, 0x00, 0x06, 0xbb},       {0x81, 0x04, 0x00, 0xbb},
+       {0x82, 0x01, 0x02, 0xbb},       {0x83, 0x03, 0x02, 0xbb},
+       {0x84, 0x05, 0x00, 0xbb},       {0x85, 0x01, 0x00, 0xbb},
+       {0x86, 0x03, 0x02, 0xbb},       {0x87, 0x05, 0x00, 0xbb},
+       {0x88, 0x01, 0x00, 0xbb},       {0x89, 0x02, 0x02, 0xbb},
+       {0x8a, 0xfd, 0x04, 0xbb},       {0x8b, 0xfc, 0xfd, 0xbb},
+       {0x8c, 0xff, 0xfd, 0xbb},       {0x8d, 0x00, 0x00, 0xbb},
+       {0x8e, 0xfe, 0x05, 0xbb},       {0x8f, 0xfc, 0xfd, 0xbb},
+       {0x90, 0xfe, 0xfd, 0xbb},       {0x91, 0x00, 0x00, 0xbb},
+       {0x92, 0xfe, 0x03, 0xbb},       {0x93, 0xfd, 0xfe, 0xbb},
+       {0x94, 0xff, 0xfd, 0xbb},       {0x95, 0x00, 0x00, 0xbb},
+       {0xb6, 0x07, 0x05, 0xbb},       {0xb7, 0x13, 0x06, 0xbb},
+       {0xb8, 0x08, 0x06, 0xbb},       {0xb9, 0x14, 0x08, 0xbb},
+       {0xba, 0x06, 0x05, 0xbb},       {0xbb, 0x13, 0x06, 0xbb},
+       {0xbc, 0x03, 0x01, 0xbb},       {0xbd, 0x03, 0x04, 0xbb},
+       {0xbe, 0x00, 0x02, 0xbb},       {0xbf, 0x03, 0x01, 0xbb},
+       {0xc0, 0x02, 0x04, 0xbb},       {0xc1, 0x00, 0x04, 0xbb},
+       {0xc2, 0x02, 0x01, 0xbb},       {0xc3, 0x01, 0x03, 0xbb},
+       {0xc4, 0x00, 0x04, 0xbb},       {0xf0, 0x00, 0x02, 0xbb},
+       {0xc8, 0x00, 0x00, 0xbb},       {0x2e, 0x00, 0x00, 0xbb},
+       {0x2e, 0x0c, 0x5b, 0xbb},       {0x2f, 0xd1, 0x00, 0xbb},
+       {0x39, 0x03, 0xca, 0xbb},       {0x3a, 0x06, 0x80, 0xbb},
+       {0x3b, 0x01, 0x52, 0xbb},       {0x3c, 0x05, 0x40, 0xbb},
+       {0x57, 0x01, 0x9c, 0xbb},       {0x58, 0x01, 0xee, 0xbb},
+       {0x59, 0x00, 0xf0, 0xbb},       {0x5a, 0x01, 0x20, 0xbb},
+       {0x5c, 0x1d, 0x17, 0xbb},       {0x5d, 0x22, 0x1c, 0xbb},
+       {0x64, 0x1e, 0x1c, 0xbb},       {0x5b, 0x00, 0x01, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},       {0x36, 0x68, 0x10, 0xbb},
+       {0x00, 0x00, 0x30, 0xdd},       {0x37, 0x81, 0x00, 0xbb},
+       {0xbc, 0x02, 0x18, 0xcc},       {0xbc, 0x03, 0x50, 0xcc},
+       {0xbc, 0x04, 0x18, 0xcc},       {0xbc, 0x05, 0x00, 0xcc},
+       {0xbc, 0x06, 0x00, 0xcc},       {0xbc, 0x08, 0x30, 0xcc},
+       {0xbc, 0x09, 0x40, 0xcc},       {0xbc, 0x0a, 0x10, 0xcc},
+       {0xbc, 0x0b, 0x00, 0xcc},       {0xbc, 0x0c, 0x00, 0xcc},
+       {0xbf, 0xc0, 0x26, 0xcc},       {0xbf, 0xc1, 0x02, 0xcc},
+       {0xbf, 0xcc, 0x04, 0xcc},       {0xb3, 0x5c, 0x01, 0xcc},
+       {0xb3, 0x01, 0x41, 0xcc},
+       {}
+};
+
+static const u8 mi1320_soc_InitVGA[][4] = {
+       {0xb3, 0x01, 0x01, 0xcc},
+       {0xb0, 0x03, 0x19, 0xcc},
+       {0xb0, 0x04, 0x02, 0xcc},
+       {0x00, 0x00, 0x30, 0xdd},
+       {0xb3, 0x00, 0x64, 0xcc},
+       {0xb3, 0x00, 0x67, 0xcc},
+       {0xb3, 0x05, 0x01, 0xcc},
+       {0xb3, 0x06, 0x01, 0xcc},
+       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},
+       {0xb3, 0x34, 0x02, 0xcc},
+       {0xb3, 0x35, 0xc8, 0xcc},       /* i2c add: 48 */
+       {0xb3, 0x02, 0x00, 0xcc},
+       {0xb3, 0x03, 0x0a, 0xcc},
+       {0xb3, 0x04, 0x05, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x01, 0xcc},
+       {0xb3, 0x23, 0xe0, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},
+       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x02, 0xcc},
+       {0xb3, 0x17, 0x7f, 0xcc},
+       {0xb3, 0x00, 0x67, 0xcc},
+       {0xb8, 0x00, 0x00, 0xcc},
+       {0xbc, 0x00, 0x71, 0xcc},
+       {0xbc, 0x01, 0x01, 0xcc},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x00, 0x00, 0x10, 0xdd},
+       {0xc8, 0x00, 0x00, 0xbb},
+       {0x00, 0x00, 0x30, 0xdd},
+       {0xf0, 0x00, 0x00, 0xbb},
+       {0x00, 0x00, 0x10, 0xdd},
+       {0x07, 0x00, 0xe0, 0xbb},
+       {0x08, 0x00, 0x0b, 0xbb},
+       {0x21, 0x00, 0x0c, 0xbb},
+       {0x20, 0x01, 0x03, 0xbb},       /* h/v flip */
+       {0xbf, 0xc0, 0x26, 0xcc},
+       {0xbf, 0xc1, 0x02, 0xcc},
+       {0xbf, 0xcc, 0x04, 0xcc},
+       {0xb3, 0x01, 0x41, 0xcc},
+       {0xf0, 0x00, 0x00, 0xbb},
+       {0x05, 0x01, 0x78, 0xbb},
+       {0x06, 0x00, 0x11, 0xbb},
+       {0x07, 0x01, 0x42, 0xbb},
+       {0x08, 0x00, 0x11, 0xbb},
+       {0x20, 0x01, 0x03, 0xbb},       /* h/v flip */
+       {0x21, 0x80, 0x00, 0xbb},
+       {0x22, 0x0d, 0x0f, 0xbb},
+       {0x24, 0x80, 0x00, 0xbb},
+       {0x59, 0x00, 0xff, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x39, 0x03, 0xca, 0xbb},
+       {0x3a, 0x06, 0x80, 0xbb},
+       {0x3b, 0x01, 0x52, 0xbb},
+       {0x3c, 0x05, 0x40, 0xbb},
+       {0x57, 0x01, 0x9c, 0xbb},
+       {0x58, 0x01, 0xee, 0xbb},
+       {0x59, 0x00, 0xf0, 0xbb},
+       {0x5a, 0x01, 0x20, 0xbb},
+       {0x5c, 0x1d, 0x17, 0xbb},
+       {0x5d, 0x22, 0x1c, 0xbb},
+       {0x64, 0x1e, 0x1c, 0xbb},
+       {0x5b, 0x00, 0x00, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x22, 0xa0, 0x78, 0xbb},
+       {0x23, 0xa0, 0x78, 0xbb},
+       {0x24, 0x7f, 0x00, 0xbb},
+       {0x28, 0xea, 0x02, 0xbb},
+       {0x29, 0x86, 0x7a, 0xbb},
+       {0x5e, 0x52, 0x4c, 0xbb},
+       {0x5f, 0x20, 0x24, 0xbb},
+       {0x60, 0x00, 0x02, 0xbb},
+       {0x02, 0x00, 0xee, 0xbb},
+       {0x03, 0x39, 0x23, 0xbb},
+       {0x04, 0x07, 0x24, 0xbb},
+       {0x09, 0x00, 0xc0, 0xbb},
+       {0x0a, 0x00, 0x79, 0xbb},
+       {0x0b, 0x00, 0x04, 0xbb},
+       {0x0c, 0x00, 0x5c, 0xbb},
+       {0x0d, 0x00, 0xd9, 0xbb},
+       {0x0e, 0x00, 0x53, 0xbb},
+       {0x0f, 0x00, 0x21, 0xbb},
+       {0x10, 0x00, 0xa4, 0xbb},
+       {0x11, 0x00, 0xe5, 0xbb},
+       {0x15, 0x00, 0x00, 0xbb},
+       {0x16, 0x00, 0x00, 0xbb},
+       {0x17, 0x00, 0x00, 0xbb},
+       {0x18, 0x00, 0x00, 0xbb},
+       {0x19, 0x00, 0x00, 0xbb},
+       {0x1a, 0x00, 0x00, 0xbb},
+       {0x1b, 0x00, 0x00, 0xbb},
+       {0x1c, 0x00, 0x00, 0xbb},
+       {0x1d, 0x00, 0x00, 0xbb},
+       {0x1e, 0x00, 0x00, 0xbb},
+       {0xf0, 0x00, 0x01, 0xbb},
+       {0x06, 0xe0, 0x0e, 0xbb},
+       {0x06, 0x60, 0x0e, 0xbb},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {}
+};
+static const u8 mi1320_soc_InitQVGA[][4] = {
+       {0xb3, 0x01, 0x01, 0xcc},
+       {0xb0, 0x03, 0x19, 0xcc},
+       {0xb0, 0x04, 0x02, 0xcc},
+       {0x00, 0x00, 0x30, 0xdd},
+       {0xb3, 0x00, 0x64, 0xcc},
+       {0xb3, 0x00, 0x67, 0xcc},
+       {0xb3, 0x05, 0x01, 0xcc},
+       {0xb3, 0x06, 0x01, 0xcc},
+       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},
+       {0xb3, 0x34, 0x02, 0xcc},
+       {0xb3, 0x35, 0xc8, 0xcc},
+       {0xb3, 0x02, 0x00, 0xcc},
+       {0xb3, 0x03, 0x0a, 0xcc},
+       {0xb3, 0x04, 0x05, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x01, 0xcc},
+       {0xb3, 0x23, 0xe0, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},
+       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x02, 0xcc},
+       {0xb3, 0x17, 0x7f, 0xcc},
+       {0xb3, 0x00, 0x67, 0xcc},
+       {0xb8, 0x00, 0x00, 0xcc},
+       {0xbc, 0x00, 0xd1, 0xcc},
+       {0xbc, 0x01, 0x01, 0xcc},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x00, 0x00, 0x10, 0xdd},
+       {0xc8, 0x00, 0x00, 0xbb},
+       {0x00, 0x00, 0x30, 0xdd},
+       {0xf0, 0x00, 0x00, 0xbb},
+       {0x00, 0x00, 0x10, 0xdd},
+       {0x07, 0x00, 0xe0, 0xbb},
+       {0x08, 0x00, 0x0b, 0xbb},
+       {0x21, 0x00, 0x0c, 0xbb},
+       {0x20, 0x01, 0x03, 0xbb},       /* h/v flip */
+       {0xbf, 0xc0, 0x26, 0xcc},
+       {0xbf, 0xc1, 0x02, 0xcc},
+       {0xbf, 0xcc, 0x04, 0xcc},
+       {0xbc, 0x02, 0x18, 0xcc},
+       {0xbc, 0x03, 0x50, 0xcc},
+       {0xbc, 0x04, 0x18, 0xcc},
+       {0xbc, 0x05, 0x00, 0xcc},
+       {0xbc, 0x06, 0x00, 0xcc},
+       {0xbc, 0x08, 0x30, 0xcc},
+       {0xbc, 0x09, 0x40, 0xcc},
+       {0xbc, 0x0a, 0x10, 0xcc},
+       {0xbc, 0x0b, 0x00, 0xcc},
+       {0xbc, 0x0c, 0x00, 0xcc},
+       {0xb3, 0x01, 0x41, 0xcc},
+       {0xf0, 0x00, 0x00, 0xbb},
+       {0x05, 0x01, 0x78, 0xbb},
+       {0x06, 0x00, 0x11, 0xbb},
+       {0x07, 0x01, 0x42, 0xbb},
+       {0x08, 0x00, 0x11, 0xbb},
+       {0x20, 0x01, 0x03, 0xbb},       /* h/v flip */
+       {0x21, 0x80, 0x00, 0xbb},
+       {0x22, 0x0d, 0x0f, 0xbb},
+       {0x24, 0x80, 0x00, 0xbb},
+       {0x59, 0x00, 0xff, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x39, 0x03, 0xca, 0xbb},
+       {0x3a, 0x06, 0x80, 0xbb},
+       {0x3b, 0x01, 0x52, 0xbb},
+       {0x3c, 0x05, 0x40, 0xbb},
+       {0x57, 0x01, 0x9c, 0xbb},
+       {0x58, 0x01, 0xee, 0xbb},
+       {0x59, 0x00, 0xf0, 0xbb},
+       {0x5a, 0x01, 0x20, 0xbb},
+       {0x5c, 0x1d, 0x17, 0xbb},
+       {0x5d, 0x22, 0x1c, 0xbb},
+       {0x64, 0x1e, 0x1c, 0xbb},
+       {0x5b, 0x00, 0x00, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x22, 0xa0, 0x78, 0xbb},
+       {0x23, 0xa0, 0x78, 0xbb},
+       {0x24, 0x7f, 0x00, 0xbb},
+       {0x28, 0xea, 0x02, 0xbb},
+       {0x29, 0x86, 0x7a, 0xbb},
+       {0x5e, 0x52, 0x4c, 0xbb},
+       {0x5f, 0x20, 0x24, 0xbb},
+       {0x60, 0x00, 0x02, 0xbb},
+       {0x02, 0x00, 0xee, 0xbb},
+       {0x03, 0x39, 0x23, 0xbb},
+       {0x04, 0x07, 0x24, 0xbb},
+       {0x09, 0x00, 0xc0, 0xbb},
+       {0x0a, 0x00, 0x79, 0xbb},
+       {0x0b, 0x00, 0x04, 0xbb},
+       {0x0c, 0x00, 0x5c, 0xbb},
+       {0x0d, 0x00, 0xd9, 0xbb},
+       {0x0e, 0x00, 0x53, 0xbb},
+       {0x0f, 0x00, 0x21, 0xbb},
+       {0x10, 0x00, 0xa4, 0xbb},
+       {0x11, 0x00, 0xe5, 0xbb},
+       {0x15, 0x00, 0x00, 0xbb},
+       {0x16, 0x00, 0x00, 0xbb},
+       {0x17, 0x00, 0x00, 0xbb},
+       {0x18, 0x00, 0x00, 0xbb},
+       {0x19, 0x00, 0x00, 0xbb},
+       {0x1a, 0x00, 0x00, 0xbb},
+       {0x1b, 0x00, 0x00, 0xbb},
+       {0x1c, 0x00, 0x00, 0xbb},
+       {0x1d, 0x00, 0x00, 0xbb},
+       {0x1e, 0x00, 0x00, 0xbb},
+       {0xf0, 0x00, 0x01, 0xbb},
+       {0x06, 0xe0, 0x0e, 0xbb},
+       {0x06, 0x60, 0x0e, 0xbb},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {}
+};
+static const u8 mi1320_soc_InitSXGA[][4] = {
+       {0xb3, 0x01, 0x01, 0xcc},
+       {0xb0, 0x03, 0x19, 0xcc},
+       {0x00, 0x00, 0x30, 0xdd},
+       {0xb3, 0x00, 0x64, 0xcc},
+       {0xb3, 0x00, 0x67, 0xcc},
+       {0xb3, 0x05, 0x01, 0xcc},
+       {0xb3, 0x06, 0x01, 0xcc},
+       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},
+       {0xb3, 0x34, 0x02, 0xcc},
+       {0xb3, 0x35, 0xc8, 0xcc},
+       {0xb3, 0x02, 0x00, 0xcc},
+       {0xb3, 0x03, 0x0a, 0xcc},
+       {0xb3, 0x04, 0x05, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x04, 0xcc},
+       {0xb3, 0x23, 0x00, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},
+       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x04, 0xcc},
+       {0xb3, 0x17, 0xff, 0xcc},
+       {0xb3, 0x00, 0x67, 0xcc},
+       {0xbc, 0x00, 0x71, 0xcc},
+       {0xbc, 0x01, 0x01, 0xcc},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x00, 0x00, 0x30, 0xdd},
+       {0xc8, 0x9f, 0x0b, 0xbb},
+       {0x00, 0x00, 0x20, 0xdd},
+       {0x5b, 0x00, 0x01, 0xbb},
+       {0x00, 0x00, 0x20, 0xdd},
+       {0xf0, 0x00, 0x00, 0xbb},
+       {0x00, 0x00, 0x30, 0xdd},
+       {0x20, 0x01, 0x03, 0xbb},       /* h/v flip */
+       {0x00, 0x00, 0x20, 0xdd},
+       {0xbf, 0xc0, 0x26, 0xcc},
+       {0xbf, 0xc1, 0x02, 0xcc},
+       {0xbf, 0xcc, 0x04, 0xcc},
+       {0xb3, 0x01, 0x41, 0xcc},
+       {0xf0, 0x00, 0x00, 0xbb},
+       {0x05, 0x01, 0x78, 0xbb},
+       {0x06, 0x00, 0x11, 0xbb},
+       {0x07, 0x01, 0x42, 0xbb},
+       {0x08, 0x00, 0x11, 0xbb},
+       {0x20, 0x01, 0x03, 0xbb},       /* h/v flip */
+       {0x21, 0x80, 0x00, 0xbb},
+       {0x22, 0x0d, 0x0f, 0xbb},
+       {0x24, 0x80, 0x00, 0xbb},
+       {0x59, 0x00, 0xff, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x39, 0x03, 0xca, 0xbb},
+       {0x3a, 0x06, 0x80, 0xbb},
+       {0x3b, 0x01, 0x52, 0xbb},
+       {0x3c, 0x05, 0x40, 0xbb},
+       {0x57, 0x01, 0x9c, 0xbb},
+       {0x58, 0x01, 0xee, 0xbb},
+       {0x59, 0x00, 0xf0, 0xbb},
+       {0x5a, 0x01, 0x20, 0xbb},
+       {0x5c, 0x1d, 0x17, 0xbb},
+       {0x5d, 0x22, 0x1c, 0xbb},
+       {0x64, 0x1e, 0x1c, 0xbb},
+       {0x5b, 0x00, 0x00, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x22, 0xa0, 0x78, 0xbb},
+       {0x23, 0xa0, 0x78, 0xbb},
+       {0x24, 0x7f, 0x00, 0xbb},
+       {0x28, 0xea, 0x02, 0xbb},
+       {0x29, 0x86, 0x7a, 0xbb},
+       {0x5e, 0x52, 0x4c, 0xbb},
+       {0x5f, 0x20, 0x24, 0xbb},
+       {0x60, 0x00, 0x02, 0xbb},
+       {0x02, 0x00, 0xee, 0xbb},
+       {0x03, 0x39, 0x23, 0xbb},
+       {0x04, 0x07, 0x24, 0xbb},
+       {0x09, 0x00, 0xc0, 0xbb},
+       {0x0a, 0x00, 0x79, 0xbb},
+       {0x0b, 0x00, 0x04, 0xbb},
+       {0x0c, 0x00, 0x5c, 0xbb},
+       {0x0d, 0x00, 0xd9, 0xbb},
+       {0x0e, 0x00, 0x53, 0xbb},
+       {0x0f, 0x00, 0x21, 0xbb},
+       {0x10, 0x00, 0xa4, 0xbb},
+       {0x11, 0x00, 0xe5, 0xbb},
+       {0x15, 0x00, 0x00, 0xbb},
+       {0x16, 0x00, 0x00, 0xbb},
+       {0x17, 0x00, 0x00, 0xbb},
+       {0x18, 0x00, 0x00, 0xbb},
+       {0x19, 0x00, 0x00, 0xbb},
+       {0x1a, 0x00, 0x00, 0xbb},
+       {0x1b, 0x00, 0x00, 0xbb},
+       {0x1c, 0x00, 0x00, 0xbb},
+       {0x1d, 0x00, 0x00, 0xbb},
+       {0x1e, 0x00, 0x00, 0xbb},
+       {0xf0, 0x00, 0x01, 0xbb},
+       {0x06, 0xe0, 0x0e, 0xbb},
+       {0x06, 0x60, 0x0e, 0xbb},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {0xf0, 0x00, 0x00, 0xbb},
+       {0x05, 0x01, 0x13, 0xbb},
+       {0x06, 0x00, 0x11, 0xbb},
+       {0x07, 0x00, 0x85, 0xbb},
+       {0x08, 0x00, 0x27, 0xbb},
+       {0x20, 0x01, 0x03, 0xbb},       /* h/v flip */
+       {0x21, 0x80, 0x00, 0xbb},
+       {0x22, 0x0d, 0x0f, 0xbb},
+       {0x24, 0x80, 0x00, 0xbb},
+       {0x59, 0x00, 0xff, 0xbb},
+       {0xf0, 0x00, 0x02, 0xbb},
+       {0x39, 0x03, 0x0d, 0xbb},
+       {0x3a, 0x06, 0x1b, 0xbb},
+       {0x3b, 0x00, 0x95, 0xbb},
+       {0x3c, 0x04, 0xdb, 0xbb},
+       {0x57, 0x02, 0x00, 0xbb},
+       {0x58, 0x02, 0x66, 0xbb},
+       {0x59, 0x00, 0xff, 0xbb},
+       {0x5a, 0x01, 0x33, 0xbb},
+       {0x5c, 0x12, 0x0d, 0xbb},
+       {0x5d, 0x16, 0x11, 0xbb},
+       {0x64, 0x5e, 0x1c, 0xbb},
+       {}
+};
+static const u8 po3130_gamma[17] = {
+       0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
+       0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
+};
+static const u8 po3130_matrix[9] = {
+       0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63
+};
+
+static const u8 po3130_initVGA_data[][4] = {
+       {0xb0, 0x4d, 0x00, 0xcc},       {0xb3, 0x01, 0x01, 0xcc},
+       {0x00, 0x00, 0x50, 0xdd},       {0xb0, 0x03, 0x01, 0xcc},
+       {0xb3, 0x00, 0x04, 0xcc},       {0xb3, 0x00, 0x24, 0xcc},
+       {0xb3, 0x00, 0x25, 0xcc},       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},       {0xb3, 0x05, 0x00, 0xcc},
+       {0xb3, 0x06, 0x01, 0xcc},       {0xb3, 0x03, 0x1a, 0xcc},
+       {0xb3, 0x04, 0x15, 0xcc},       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},       {0xb3, 0x22, 0x01, 0xcc},
+       {0xb3, 0x23, 0xe8, 0xcc},       {0xb8, 0x08, 0xe8, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x02, 0xcc},       {0xb3, 0x17, 0x7f, 0xcc},
+       {0xb3, 0x34, 0x01, 0xcc},
+       {0xb3, 0x35, 0xf6, 0xcc},       /* i2c add: 76 */
+       {0xb3, 0x00, 0x27, 0xcc},       {0xbc, 0x00, 0x71, 0xcc},
+       {0xb8, 0x00, 0x21, 0xcc},       {0xb8, 0x27, 0x20, 0xcc},
+       {0xb8, 0x01, 0x79, 0xcc},       {0xb8, 0x81, 0x09, 0xcc},
+       {0xb8, 0x2c, 0x50, 0xcc},       {0xb8, 0x2d, 0xf8, 0xcc},
+       {0xb8, 0x2e, 0xf8, 0xcc},       {0xb8, 0x2f, 0xf8, 0xcc},
+       {0xb8, 0x30, 0x50, 0xcc},       {0xb8, 0x31, 0xf8, 0xcc},
+       {0xb8, 0x32, 0xf8, 0xcc},       {0xb8, 0x33, 0xf8, 0xcc},
+       {0xb8, 0x34, 0x50, 0xcc},       {0xb8, 0x35, 0x00, 0xcc},
+       {0xb8, 0x36, 0x00, 0xcc},       {0xb8, 0x37, 0x00, 0xcc},
+       {0x00, 0x1e, 0xc6, 0xaa},       {0x00, 0x20, 0x44, 0xaa},
+       {0x00, 0xad, 0x02, 0xaa},       {0x00, 0xae, 0x2c, 0xaa},
+       {0x00, 0x12, 0x08, 0xaa},       {0x00, 0x17, 0x41, 0xaa},
+       {0x00, 0x19, 0x41, 0xaa},       {0x00, 0x1e, 0x06, 0xaa},
+       {0x00, 0x21, 0x00, 0xaa},       {0x00, 0x36, 0xc0, 0xaa},
+       {0x00, 0x37, 0xc8, 0xaa},       {0x00, 0x3b, 0x36, 0xaa},
+       {0x00, 0x4b, 0xfe, 0xaa},       {0x00, 0x51, 0x1c, 0xaa},
+       {0x00, 0x52, 0x01, 0xaa},       {0x00, 0x55, 0x0a, 0xaa},
+       {0x00, 0x59, 0x02, 0xaa},       {0x00, 0x5a, 0x04, 0xaa},
+       {0x00, 0x5c, 0x10, 0xaa},       {0x00, 0x5d, 0x10, 0xaa},
+       {0x00, 0x5e, 0x10, 0xaa},       {0x00, 0x5f, 0x10, 0xaa},
+       {0x00, 0x61, 0x00, 0xaa},       {0x00, 0x62, 0x18, 0xaa},
+       {0x00, 0x63, 0x30, 0xaa},       {0x00, 0x70, 0x68, 0xaa},
+       {0x00, 0x80, 0x71, 0xaa},       {0x00, 0x81, 0x08, 0xaa},
+       {0x00, 0x82, 0x00, 0xaa},       {0x00, 0x83, 0x55, 0xaa},
+       {0x00, 0x84, 0x06, 0xaa},       {0x00, 0x85, 0x06, 0xaa},
+       {0x00, 0x86, 0x13, 0xaa},       {0x00, 0x87, 0x18, 0xaa},
+       {0x00, 0xaa, 0x3f, 0xaa},       {0x00, 0xab, 0x44, 0xaa},
+       {0x00, 0xb0, 0x68, 0xaa},       {0x00, 0xb5, 0x10, 0xaa},
+       {0x00, 0xb8, 0x20, 0xaa},       {0x00, 0xb9, 0xa0, 0xaa},
+       {0x00, 0xbc, 0x04, 0xaa},       {0x00, 0x8b, 0x40, 0xaa},
+       {0x00, 0x8c, 0x91, 0xaa},       {0x00, 0x8d, 0x8f, 0xaa},
+       {0x00, 0x8e, 0x91, 0xaa},       {0x00, 0x8f, 0x43, 0xaa},
+       {0x00, 0x90, 0x92, 0xaa},       {0x00, 0x91, 0x89, 0xaa},
+       {0x00, 0x92, 0x9d, 0xaa},       {0x00, 0x93, 0x46, 0xaa},
+       {0x00, 0xd6, 0x22, 0xaa},       {0x00, 0x73, 0x00, 0xaa},
+       {0x00, 0x74, 0x10, 0xaa},       {0x00, 0x75, 0x20, 0xaa},
+       {0x00, 0x76, 0x2b, 0xaa},       {0x00, 0x77, 0x36, 0xaa},
+       {0x00, 0x78, 0x49, 0xaa},       {0x00, 0x79, 0x5a, 0xaa},
+       {0x00, 0x7a, 0x7f, 0xaa},       {0x00, 0x7b, 0x9b, 0xaa},
+       {0x00, 0x7c, 0xba, 0xaa},       {0x00, 0x7d, 0xd4, 0xaa},
+       {0x00, 0x7e, 0xea, 0xaa},       {0x00, 0xd6, 0x62, 0xaa},
+       {0x00, 0x73, 0x00, 0xaa},       {0x00, 0x74, 0x10, 0xaa},
+       {0x00, 0x75, 0x20, 0xaa},       {0x00, 0x76, 0x2b, 0xaa},
+       {0x00, 0x77, 0x36, 0xaa},       {0x00, 0x78, 0x49, 0xaa},
+       {0x00, 0x79, 0x5a, 0xaa},       {0x00, 0x7a, 0x7f, 0xaa},
+       {0x00, 0x7b, 0x9b, 0xaa},       {0x00, 0x7c, 0xba, 0xaa},
+       {0x00, 0x7d, 0xd4, 0xaa},       {0x00, 0x7e, 0xea, 0xaa},
+       {0x00, 0xd6, 0xa2, 0xaa},       {0x00, 0x73, 0x00, 0xaa},
+       {0x00, 0x74, 0x10, 0xaa},       {0x00, 0x75, 0x20, 0xaa},
+       {0x00, 0x76, 0x2b, 0xaa},       {0x00, 0x77, 0x36, 0xaa},
+       {0x00, 0x78, 0x49, 0xaa},       {0x00, 0x79, 0x5a, 0xaa},
+       {0x00, 0x7a, 0x7f, 0xaa},       {0x00, 0x7b, 0x9b, 0xaa},
+       {0x00, 0x7c, 0xba, 0xaa},       {0x00, 0x7d, 0xd4, 0xaa},
+       {0x00, 0x7e, 0xea, 0xaa},
+       {0x00, 0x4c, 0x07, 0xaa},
+       {0x00, 0x4b, 0xe0, 0xaa},       {0x00, 0x4e, 0x77, 0xaa},
+       {0x00, 0x59, 0x02, 0xaa},       {0x00, 0x4d, 0x0a, 0xaa},
+/*     {0x00, 0xd1, 0x00, 0xaa},       {0x00, 0x20, 0xc4, 0xaa},
+       {0xb8, 0x8e, 0x00, 0xcc},       {0xb8, 0x8f, 0xff, 0xcc}, */
+       {0x00, 0xd1, 0x3c, 0xaa},       {0x00, 0x20, 0xc4, 0xaa},
+       {0xb8, 0x8e, 0x00, 0xcc},       {0xb8, 0x8f, 0xff, 0xcc},
+       {0xb8, 0xfe, 0x00, 0xcc},       {0xb8, 0xff, 0x28, 0xcc},
+       {0xb9, 0x00, 0x28, 0xcc},       {0xb9, 0x01, 0x28, 0xcc},
+       {0xb9, 0x02, 0x28, 0xcc},       {0xb9, 0x03, 0x00, 0xcc},
+       {0xb9, 0x04, 0x00, 0xcc},       {0xb9, 0x05, 0x3c, 0xcc},
+       {0xb9, 0x06, 0x3c, 0xcc},       {0xb9, 0x07, 0x3c, 0xcc},
+       {0xb9, 0x08, 0x3c, 0xcc},       {0x00, 0x05, 0x00, 0xaa},
+       {0xb3, 0x5c, 0x00, 0xcc},       {0xb3, 0x01, 0x41, 0xcc},
+       {}
+};
+static const u8 po3130_rundata[][4] = {
+       {0x00, 0x47, 0x45, 0xaa},       {0x00, 0x48, 0x9b, 0xaa},
+       {0x00, 0x49, 0x3a, 0xaa},       {0x00, 0x4a, 0x01, 0xaa},
+       {0x00, 0x44, 0x40, 0xaa},
+/*     {0x00, 0xd5, 0x7c, 0xaa}, */
+       {0x00, 0xad, 0x04, 0xaa},       {0x00, 0xae, 0x00, 0xaa},
+       {0x00, 0xb0, 0x78, 0xaa},       {0x00, 0x98, 0x02, 0xaa},
+       {0x00, 0x94, 0x25, 0xaa},       {0x00, 0x95, 0x25, 0xaa},
+       {0x00, 0x59, 0x68, 0xaa},       {0x00, 0x44, 0x20, 0xaa},
+       {0x00, 0x17, 0x50, 0xaa},       {0x00, 0x19, 0x50, 0xaa},
+       {0x00, 0xd1, 0x3c, 0xaa},       {0x00, 0xd1, 0x3c, 0xaa},
+       {0x00, 0x1e, 0x06, 0xaa},       {0x00, 0x1e, 0x06, 0xaa},
+       {}
+};
+
+static const u8 po3130_initQVGA_data[][4] = {
+       {0xb0, 0x4d, 0x00, 0xcc},       {0xb3, 0x01, 0x01, 0xcc},
+       {0x00, 0x00, 0x50, 0xdd},       {0xb0, 0x03, 0x09, 0xcc},
+       {0xb3, 0x00, 0x04, 0xcc},       {0xb3, 0x00, 0x24, 0xcc},
+       {0xb3, 0x00, 0x25, 0xcc},       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},       {0xb3, 0x05, 0x00, 0xcc},
+       {0xb3, 0x06, 0x01, 0xcc},       {0xb3, 0x03, 0x1a, 0xcc},
+       {0xb3, 0x04, 0x15, 0xcc},       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},       {0xb3, 0x22, 0x01, 0xcc},
+       {0xb3, 0x23, 0xe0, 0xcc},       {0xb8, 0x08, 0xe0, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x02, 0xcc},       {0xb3, 0x17, 0x7f, 0xcc},
+       {0xb3, 0x34, 0x01, 0xcc},       {0xb3, 0x35, 0xf6, 0xcc},
+       {0xb3, 0x00, 0x27, 0xcc},       {0xbc, 0x00, 0xd1, 0xcc},
+       {0xb8, 0x00, 0x21, 0xcc},       {0xb8, 0x27, 0x20, 0xcc},
+       {0xb8, 0x01, 0x79, 0xcc},       {0xb8, 0x81, 0x09, 0xcc},
+       {0xb8, 0x2c, 0x50, 0xcc},       {0xb8, 0x2d, 0xf8, 0xcc},
+       {0xb8, 0x2e, 0xf8, 0xcc},       {0xb8, 0x2f, 0xf8, 0xcc},
+       {0xb8, 0x30, 0x50, 0xcc},       {0xb8, 0x31, 0xf8, 0xcc},
+       {0xb8, 0x32, 0xf8, 0xcc},       {0xb8, 0x33, 0xf8, 0xcc},
+       {0xb8, 0x34, 0x50, 0xcc},       {0xb8, 0x35, 0x00, 0xcc},
+       {0xb8, 0x36, 0x00, 0xcc},       {0xb8, 0x37, 0x00, 0xcc},
+       {0x00, 0x1e, 0xc6, 0xaa},       {0x00, 0x20, 0x44, 0xaa},
+       {0x00, 0xad, 0x02, 0xaa},       {0x00, 0xae, 0x2c, 0xaa},
+       {0x00, 0x12, 0x08, 0xaa},       {0x00, 0x17, 0x41, 0xaa},
+       {0x00, 0x19, 0x41, 0xaa},       {0x00, 0x1e, 0x06, 0xaa},
+       {0x00, 0x21, 0x00, 0xaa},       {0x00, 0x36, 0xc0, 0xaa},
+       {0x00, 0x37, 0xc8, 0xaa},       {0x00, 0x3b, 0x36, 0xaa},
+       {0x00, 0x4b, 0xfe, 0xaa},       {0x00, 0x51, 0x1c, 0xaa},
+       {0x00, 0x52, 0x01, 0xaa},       {0x00, 0x55, 0x0a, 0xaa},
+       {0x00, 0x59, 0x6f, 0xaa},       {0x00, 0x5a, 0x04, 0xaa},
+       {0x00, 0x5c, 0x10, 0xaa},       {0x00, 0x5d, 0x10, 0xaa},
+       {0x00, 0x5e, 0x10, 0xaa},       {0x00, 0x5f, 0x10, 0xaa},
+       {0x00, 0x61, 0x00, 0xaa},       {0x00, 0x62, 0x18, 0xaa},
+       {0x00, 0x63, 0x30, 0xaa},       {0x00, 0x70, 0x68, 0xaa},
+       {0x00, 0x80, 0x71, 0xaa},       {0x00, 0x81, 0x08, 0xaa},
+       {0x00, 0x82, 0x00, 0xaa},       {0x00, 0x83, 0x55, 0xaa},
+       {0x00, 0x84, 0x06, 0xaa},       {0x00, 0x85, 0x06, 0xaa},
+       {0x00, 0x86, 0x13, 0xaa},       {0x00, 0x87, 0x18, 0xaa},
+       {0x00, 0xaa, 0x3f, 0xaa},       {0x00, 0xab, 0x44, 0xaa},
+       {0x00, 0xb0, 0x68, 0xaa},       {0x00, 0xb5, 0x10, 0xaa},
+       {0x00, 0xb8, 0x20, 0xaa},       {0x00, 0xb9, 0xa0, 0xaa},
+       {0x00, 0xbc, 0x04, 0xaa},       {0x00, 0x8b, 0x40, 0xaa},
+       {0x00, 0x8c, 0x91, 0xaa},       {0x00, 0x8d, 0x8f, 0xaa},
+       {0x00, 0x8e, 0x91, 0xaa},       {0x00, 0x8f, 0x43, 0xaa},
+       {0x00, 0x90, 0x92, 0xaa},       {0x00, 0x91, 0x89, 0xaa},
+       {0x00, 0x92, 0x9d, 0xaa},       {0x00, 0x93, 0x46, 0xaa},
+       {0x00, 0xd6, 0x22, 0xaa},       {0x00, 0x73, 0x00, 0xaa},
+       {0x00, 0x74, 0x10, 0xaa},       {0x00, 0x75, 0x20, 0xaa},
+       {0x00, 0x76, 0x2b, 0xaa},       {0x00, 0x77, 0x36, 0xaa},
+       {0x00, 0x78, 0x49, 0xaa},       {0x00, 0x79, 0x5a, 0xaa},
+       {0x00, 0x7a, 0x7f, 0xaa},       {0x00, 0x7b, 0x9b, 0xaa},
+       {0x00, 0x7c, 0xba, 0xaa},       {0x00, 0x7d, 0xd4, 0xaa},
+       {0x00, 0x7e, 0xea, 0xaa},       {0x00, 0xd6, 0x62, 0xaa},
+       {0x00, 0x73, 0x00, 0xaa},       {0x00, 0x74, 0x10, 0xaa},
+       {0x00, 0x75, 0x20, 0xaa},       {0x00, 0x76, 0x2b, 0xaa},
+       {0x00, 0x77, 0x36, 0xaa},       {0x00, 0x78, 0x49, 0xaa},
+       {0x00, 0x79, 0x5a, 0xaa},       {0x00, 0x7a, 0x7f, 0xaa},
+       {0x00, 0x7b, 0x9b, 0xaa},       {0x00, 0x7c, 0xba, 0xaa},
+       {0x00, 0x7d, 0xd4, 0xaa},       {0x00, 0x7e, 0xea, 0xaa},
+       {0x00, 0xd6, 0xa2, 0xaa},       {0x00, 0x73, 0x00, 0xaa},
+       {0x00, 0x74, 0x10, 0xaa},       {0x00, 0x75, 0x20, 0xaa},
+       {0x00, 0x76, 0x2b, 0xaa},       {0x00, 0x77, 0x36, 0xaa},
+       {0x00, 0x78, 0x49, 0xaa},       {0x00, 0x79, 0x5a, 0xaa},
+       {0x00, 0x7a, 0x7f, 0xaa},       {0x00, 0x7b, 0x9b, 0xaa},
+       {0x00, 0x7c, 0xba, 0xaa},       {0x00, 0x7d, 0xd4, 0xaa},
+       {0x00, 0x7e, 0xea, 0xaa},       {0x00, 0x4c, 0x07, 0xaa},
+       {0x00, 0x4b, 0xe0, 0xaa},       {0x00, 0x4e, 0x77, 0xaa},
+       {0x00, 0x59, 0x66, 0xaa},       {0x00, 0x4d, 0x0a, 0xaa},
+       {0x00, 0xd1, 0x00, 0xaa},       {0x00, 0x20, 0xc4, 0xaa},
+       {0xb8, 0x8e, 0x00, 0xcc},       {0xb8, 0x8f, 0xff, 0xcc},
+       {0xb8, 0xfe, 0x00, 0xcc},       {0xb8, 0xff, 0x28, 0xcc},
+       {0xb9, 0x00, 0x28, 0xcc},       {0xb9, 0x01, 0x28, 0xcc},
+       {0xb9, 0x02, 0x28, 0xcc},       {0xb9, 0x03, 0x00, 0xcc},
+       {0xb9, 0x04, 0x00, 0xcc},       {0xb9, 0x05, 0x3c, 0xcc},
+       {0xb9, 0x06, 0x3c, 0xcc},       {0xb9, 0x07, 0x3c, 0xcc},
+       {0xb9, 0x08, 0x3c, 0xcc},       {0xbc, 0x02, 0x18, 0xcc},
+       {0xbc, 0x03, 0x50, 0xcc},       {0xbc, 0x04, 0x18, 0xcc},
+       {0xbc, 0x05, 0x00, 0xcc},       {0xbc, 0x06, 0x00, 0xcc},
+       {0xbc, 0x08, 0x30, 0xcc},       {0xbc, 0x09, 0x40, 0xcc},
+       {0xbc, 0x0a, 0x10, 0xcc},       {0xbc, 0x0b, 0x00, 0xcc},
+       {0xbc, 0x0c, 0x00, 0xcc},       {0x00, 0x05, 0x00, 0xaa},
+       {0xb3, 0x5c, 0x00, 0xcc},       {0xb3, 0x01, 0x41, 0xcc},
+       {}
+};
+
+static const u8 hv7131r_gamma[17] = {
+       0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
+       0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
+};
+static const u8 hv7131r_matrix[9] = {
+       0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63
+};
+static const u8 hv7131r_initVGA_data[][4] = {
+       {0xb3, 0x01, 0x01, 0xcc},
+       {0xb0, 0x03, 0x19, 0xcc},
+       {0xb0, 0x04, 0x02, 0xcc},
+       {0x00, 0x00, 0x20, 0xdd},
+       {0xb3, 0x00, 0x24, 0xcc},
+       {0xb3, 0x00, 0x25, 0xcc},
+       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},
+       {0xb3, 0x05, 0x01, 0xcc},
+       {0xb3, 0x06, 0x03, 0xcc},
+       {0xb3, 0x01, 0x45, 0xcc},
+       {0xb3, 0x03, 0x0b, 0xcc},
+       {0xb3, 0x04, 0x05, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x01, 0xcc},
+       {0xb3, 0x23, 0xe0, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},
+       {0xb3, 0x15, 0x02, 0xcc},
+       {0xb3, 0x16, 0x02, 0xcc},
+       {0xb3, 0x17, 0x7f, 0xcc},
+       {0xb3, 0x34, 0x01, 0xcc},
+       {0xb3, 0x35, 0x91, 0xcc},       /* i2c add: 11 */
+       {0xb3, 0x00, 0x27, 0xcc},
+       {0xbc, 0x00, 0x73, 0xcc},
+       {0xb8, 0x00, 0x23, 0xcc},
+       {0xb8, 0x2c, 0x50, 0xcc},
+       {0xb8, 0x2d, 0xf8, 0xcc},
+       {0xb8, 0x2e, 0xf8, 0xcc},
+       {0xb8, 0x2f, 0xf8, 0xcc},
+       {0xb8, 0x30, 0x50, 0xcc},
+       {0xb8, 0x31, 0xf8, 0xcc},
+       {0xb8, 0x32, 0xf8, 0xcc},
+       {0xb8, 0x33, 0xf8, 0xcc},
+       {0xb8, 0x34, 0x58, 0xcc},
+       {0xb8, 0x35, 0x00, 0xcc},
+       {0xb8, 0x36, 0x00, 0xcc},
+       {0xb8, 0x37, 0x00, 0xcc},
+       {0xb8, 0x27, 0x20, 0xcc},
+       {0xb8, 0x01, 0x7d, 0xcc},
+       {0xb8, 0x81, 0x09, 0xcc},
+       {0xb3, 0x01, 0x41, 0xcc},
+       {0xb8, 0x8e, 0x00, 0xcc},
+       {0xb8, 0x8f, 0xff, 0xcc},
+       {0x00, 0x01, 0x0c, 0xaa},
+       {0x00, 0x14, 0x01, 0xaa},
+       {0x00, 0x15, 0xe6, 0xaa},
+       {0x00, 0x16, 0x02, 0xaa},
+       {0x00, 0x17, 0x86, 0xaa},
+       {0x00, 0x23, 0x00, 0xaa},
+       {0x00, 0x25, 0x03, 0xaa},
+       {0x00, 0x26, 0xa9, 0xaa},
+       {0x00, 0x27, 0x80, 0xaa},
+       {0x00, 0x30, 0x18, 0xaa},
+       {0xb6, 0x00, 0x00, 0xcc},
+       {0xb6, 0x03, 0x02, 0xcc},
+       {0xb6, 0x02, 0x80, 0xcc},
+       {0xb6, 0x05, 0x01, 0xcc},
+       {0xb6, 0x04, 0xe0, 0xcc},
+       {0xb6, 0x12, 0x78, 0xcc},
+       {0xb6, 0x18, 0x02, 0xcc},
+       {0xb6, 0x17, 0x58, 0xcc},
+       {0xb6, 0x16, 0x00, 0xcc},
+       {0xb6, 0x22, 0x12, 0xcc},
+       {0xb6, 0x23, 0x0b, 0xcc},
+       {0xb3, 0x02, 0x02, 0xcc},
+       {0xbf, 0xc0, 0x39, 0xcc},
+       {0xbf, 0xc1, 0x04, 0xcc},
+       {0xbf, 0xcc, 0x10, 0xcc},
+       {0xb6, 0x12, 0xf8, 0xcc},
+       {0xb6, 0x13, 0x13, 0xcc},
+       {0xb9, 0x12, 0x00, 0xcc},
+       {0xb9, 0x13, 0x0a, 0xcc},
+       {0xb9, 0x14, 0x0a, 0xcc},
+       {0xb9, 0x15, 0x0a, 0xcc},
+       {0xb9, 0x16, 0x0a, 0xcc},
+       {0xb8, 0x0c, 0x20, 0xcc},
+       {0xb8, 0x0d, 0x70, 0xcc},
+       {0xb9, 0x18, 0x00, 0xcc},
+       {0xb9, 0x19, 0x0f, 0xcc},
+       {0xb9, 0x1a, 0x0f, 0xcc},
+       {0xb9, 0x1b, 0x0f, 0xcc},
+       {0xb9, 0x1c, 0x0f, 0xcc},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {}
+};
+
+static const u8 hv7131r_initQVGA_data[][4] = {
+       {0xb3, 0x01, 0x01, 0xcc},
+       {0xb0, 0x03, 0x19, 0xcc},
+       {0xb0, 0x04, 0x02, 0xcc},
+       {0x00, 0x00, 0x20, 0xdd},
+       {0xb3, 0x00, 0x24, 0xcc},
+       {0xb3, 0x00, 0x25, 0xcc},
+       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},
+       {0xb3, 0x05, 0x01, 0xcc},
+       {0xb3, 0x06, 0x03, 0xcc},
+       {0xb3, 0x01, 0x45, 0xcc},
+       {0xb3, 0x03, 0x0b, 0xcc},
+       {0xb3, 0x04, 0x05, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x01, 0xcc},
+       {0xb3, 0x23, 0xe0, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},
+       {0xb3, 0x15, 0x02, 0xcc},
+       {0xb3, 0x16, 0x02, 0xcc},
+       {0xb3, 0x17, 0x7f, 0xcc},
+       {0xb3, 0x34, 0x01, 0xcc},
+       {0xb3, 0x35, 0x91, 0xcc},
+       {0xb3, 0x00, 0x27, 0xcc},
+       {0xbc, 0x00, 0xd3, 0xcc},
+       {0xb8, 0x00, 0x23, 0xcc},
+       {0xb8, 0x2c, 0x50, 0xcc},
+       {0xb8, 0x2d, 0xf8, 0xcc},
+       {0xb8, 0x2e, 0xf8, 0xcc},
+       {0xb8, 0x2f, 0xf8, 0xcc},
+       {0xb8, 0x30, 0x50, 0xcc},
+       {0xb8, 0x31, 0xf8, 0xcc},
+       {0xb8, 0x32, 0xf8, 0xcc},
+       {0xb8, 0x33, 0xf8, 0xcc},
+       {0xb8, 0x34, 0x58, 0xcc},
+       {0xb8, 0x35, 0x00, 0xcc},
+       {0xb8, 0x36, 0x00, 0xcc},
+       {0xb8, 0x37, 0x00, 0xcc},
+       {0xb8, 0x27, 0x20, 0xcc},
+       {0xb8, 0x01, 0x7d, 0xcc},
+       {0xb8, 0x81, 0x09, 0xcc},
+       {0xb3, 0x01, 0x41, 0xcc},
+       {0xb8, 0x8e, 0x00, 0xcc},
+       {0xb8, 0x8f, 0xff, 0xcc},
+       {0x00, 0x01, 0x0c, 0xaa},
+       {0x00, 0x14, 0x01, 0xaa},
+       {0x00, 0x15, 0xe6, 0xaa},
+       {0x00, 0x16, 0x02, 0xaa},
+       {0x00, 0x17, 0x86, 0xaa},
+       {0x00, 0x23, 0x00, 0xaa},
+       {0x00, 0x25, 0x03, 0xaa},
+       {0x00, 0x26, 0xa9, 0xaa},
+       {0x00, 0x27, 0x80, 0xaa},
+       {0x00, 0x30, 0x18, 0xaa},
+       {0xb6, 0x00, 0x00, 0xcc},
+       {0xb6, 0x03, 0x01, 0xcc},
+       {0xb6, 0x02, 0x40, 0xcc},
+       {0xb6, 0x05, 0x00, 0xcc},
+       {0xb6, 0x04, 0xf0, 0xcc},
+       {0xb6, 0x12, 0x78, 0xcc},
+       {0xb6, 0x18, 0x00, 0xcc},
+       {0xb6, 0x17, 0x96, 0xcc},
+       {0xb6, 0x16, 0x00, 0xcc},
+       {0xb6, 0x22, 0x12, 0xcc},
+       {0xb6, 0x23, 0x0b, 0xcc},
+       {0xb3, 0x02, 0x02, 0xcc},
+       {0xbf, 0xc0, 0x39, 0xcc},
+       {0xbf, 0xc1, 0x04, 0xcc},
+       {0xbf, 0xcc, 0x10, 0xcc},
+       {0xbc, 0x02, 0x18, 0xcc},
+       {0xbc, 0x03, 0x50, 0xcc},
+       {0xbc, 0x04, 0x18, 0xcc},
+       {0xbc, 0x05, 0x00, 0xcc},
+       {0xbc, 0x06, 0x00, 0xcc},
+       {0xbc, 0x08, 0x30, 0xcc},
+       {0xbc, 0x09, 0x40, 0xcc},
+       {0xbc, 0x0a, 0x10, 0xcc},
+       {0xbc, 0x0b, 0x00, 0xcc},
+       {0xbc, 0x0c, 0x00, 0xcc},
+       {0xb9, 0x12, 0x00, 0xcc},
+       {0xb9, 0x13, 0x0a, 0xcc},
+       {0xb9, 0x14, 0x0a, 0xcc},
+       {0xb9, 0x15, 0x0a, 0xcc},
+       {0xb9, 0x16, 0x0a, 0xcc},
+       {0xb9, 0x18, 0x00, 0xcc},
+       {0xb9, 0x19, 0x0f, 0xcc},
+       {0xb8, 0x0c, 0x20, 0xcc},
+       {0xb8, 0x0d, 0x70, 0xcc},
+       {0xb9, 0x1a, 0x0f, 0xcc},
+       {0xb9, 0x1b, 0x0f, 0xcc},
+       {0xb9, 0x1c, 0x0f, 0xcc},
+       {0xb6, 0x12, 0xf8, 0xcc},
+       {0xb6, 0x13, 0x13, 0xcc},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {}
+};
+
+static const u8 ov7660_gamma[17] = {
+       0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
+       0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
+};
+static const u8 ov7660_matrix[9] = {
+       0x5a, 0xf0, 0xf6, 0xf3, 0x57, 0xf6, 0xf3, 0xef, 0x62
+};
+static const u8 ov7660_initVGA_data[][4] = {
+       {0xb0, 0x4d, 0x00, 0xcc},       {0xb3, 0x01, 0x01, 0xcc},
+       {0x00, 0x00, 0x50, 0xdd},
+       {0xb0, 0x03, 0x01, 0xcc},
+       {0xb3, 0x00, 0x21, 0xcc},       {0xb3, 0x00, 0x26, 0xcc},
+       {0xb3, 0x05, 0x01, 0xcc},
+       {0xb3, 0x06, 0x03, 0xcc},
+       {0xb3, 0x03, 0x1f, 0xcc},       {0xb3, 0x04, 0x05, 0xcc},
+       {0xb3, 0x05, 0x00, 0xcc},
+       {0xb3, 0x06, 0x01, 0xcc},
+       {0xb3, 0x15, 0x00, 0xcc},/* 0xb315  <-0 href startl */
+       {0xb3, 0x16, 0x02, 0xcc},       {0xb3, 0x17, 0x7f, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x23, 0xe0, 0xcc},       {0xb3, 0x1d, 0x01, 0xcc},
+       {0xb3, 0x1f, 0x02, 0xcc},
+       {0xb3, 0x34, 0x01, 0xcc},
+       {0xb3, 0x35, 0xa1, 0xcc},       /* i2c add: 21 */
+       {0xb3, 0x00, 0x26, 0xcc},
+       {0xb8, 0x00, 0x33, 0xcc}, /* 13 */
+       {0xb8, 0x01, 0x7d, 0xcc},
+       {0xbc, 0x00, 0x73, 0xcc},       {0xb8, 0x81, 0x09, 0xcc},
+       {0xb8, 0x27, 0x20, 0xcc},
+       {0xb8, 0x8f, 0x50, 0xcc},
+       {0x00, 0x01, 0x80, 0xaa},       {0x00, 0x02, 0x80, 0xaa},
+       {0x00, 0x12, 0x80, 0xaa},
+       {0x00, 0x12, 0x05, 0xaa},
+       {0x00, 0x1e, 0x01, 0xaa},       /* MVFP */
+       {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */
+       {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */
+       {0x00, 0x0d, 0x48, 0xaa},       {0x00, 0x0e, 0x04, 0xaa},
+       {0x00, 0x13, 0xa7, 0xaa},
+       {0x00, 0x40, 0xc1, 0xaa},       {0x00, 0x35, 0x00, 0xaa},
+       {0x00, 0x36, 0x00, 0xaa},
+       {0x00, 0x3c, 0x68, 0xaa},       {0x00, 0x1b, 0x05, 0xaa},
+       {0x00, 0x39, 0x43, 0xaa},
+       {0x00, 0x8d, 0xcf, 0xaa},
+       {0x00, 0x8b, 0xcc, 0xaa},       {0x00, 0x8c, 0xcc, 0xaa},
+       {0x00, 0x0f, 0x62, 0xaa},
+       {0x00, 0x35, 0x84, 0xaa},
+       {0x00, 0x3b, 0x08, 0xaa}, /* 0 * Nightframe 1/4 + 50Hz -> 0xC8 */
+       {0x00, 0x3a, 0x00, 0xaa}, /* mx change yuyv format 00, 04, 01; 08, 0c*/
+       {0x00, 0x14, 0x2a, 0xaa}, /* agc ampli */
+       {0x00, 0x9e, 0x40, 0xaa},       {0xb8, 0x8f, 0x50, 0xcc},
+       {0x00, 0x01, 0x80, 0xaa},
+       {0x00, 0x02, 0x80, 0xaa},
+       {0xb8, 0xfe, 0x00, 0xcc},       {0xb8, 0xff, 0x28, 0xcc},
+       {0xb9, 0x00, 0x28, 0xcc},
+       {0xb9, 0x01, 0x28, 0xcc},       {0xb9, 0x02, 0x28, 0xcc},
+       {0xb9, 0x03, 0x00, 0xcc},
+       {0xb9, 0x04, 0x00, 0xcc},
+       {0xb9, 0x05, 0x3c, 0xcc},       {0xb9, 0x06, 0x3c, 0xcc},
+       {0xb9, 0x07, 0x3c, 0xcc},
+       {0xb9, 0x08, 0x3c, 0xcc},
+
+       {0xb8, 0x8e, 0x00, 0xcc},       {0xb8, 0x8f, 0xff, 0xcc},
+
+       {0x00, 0x29, 0x3c, 0xaa},       {0xb3, 0x01, 0x45, 0xcc},
+       {}
+};
+static const u8 ov7660_initQVGA_data[][4] = {
+       {0xb0, 0x4d, 0x00, 0xcc},       {0xb3, 0x01, 0x01, 0xcc},
+       {0x00, 0x00, 0x50, 0xdd},       {0xb0, 0x03, 0x01, 0xcc},
+       {0xb3, 0x00, 0x21, 0xcc},       {0xb3, 0x00, 0x26, 0xcc},
+       {0xb3, 0x05, 0x01, 0xcc},       {0xb3, 0x06, 0x03, 0xcc},
+       {0xb3, 0x03, 0x1f, 0xcc},       {0xb3, 0x04, 0x05, 0xcc},
+       {0xb3, 0x05, 0x00, 0xcc},       {0xb3, 0x06, 0x01, 0xcc},
+       {0xb3, 0x15, 0x00, 0xcc},/* 0xb315  <-0 href startl */
+       {0xb3, 0x16, 0x02, 0xcc},       {0xb3, 0x17, 0x7f, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x23, 0xe0, 0xcc},       {0xb3, 0x1d, 0x01, 0xcc},
+       {0xb3, 0x1f, 0x02, 0xcc},       {0xb3, 0x34, 0x01, 0xcc},
+       {0xb3, 0x35, 0xa1, 0xcc},       {0xb3, 0x00, 0x26, 0xcc},
+       {0xb8, 0x00, 0x33, 0xcc}, /* 13 */
+       {0xb8, 0x01, 0x7d, 0xcc},
+/* sizer */
+       {0xbc, 0x00, 0xd3, 0xcc},
+       {0xb8, 0x81, 0x09, 0xcc},       {0xb8, 0x81, 0x09, 0xcc},
+       {0xb8, 0x27, 0x20, 0xcc},       {0xb8, 0x8f, 0x50, 0xcc},
+       {0x00, 0x01, 0x80, 0xaa},       {0x00, 0x02, 0x80, 0xaa},
+       {0x00, 0x12, 0x80, 0xaa},       {0x00, 0x12, 0x05, 0xaa},
+       {0x00, 0x1e, 0x01, 0xaa},       /* MVFP */
+       {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */
+       {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */
+       {0x00, 0x0d, 0x48, 0xaa},       {0x00, 0x0e, 0x04, 0xaa},
+       {0x00, 0x13, 0xa7, 0xaa},
+       {0x00, 0x40, 0xc1, 0xaa},       {0x00, 0x35, 0x00, 0xaa},
+       {0x00, 0x36, 0x00, 0xaa},
+       {0x00, 0x3c, 0x68, 0xaa},       {0x00, 0x1b, 0x05, 0xaa},
+       {0x00, 0x39, 0x43, 0xaa},       {0x00, 0x8d, 0xcf, 0xaa},
+       {0x00, 0x8b, 0xcc, 0xaa},       {0x00, 0x8c, 0xcc, 0xaa},
+       {0x00, 0x0f, 0x62, 0xaa},       {0x00, 0x35, 0x84, 0xaa},
+       {0x00, 0x3b, 0x08, 0xaa}, /* 0  * Nightframe 1/4 + 50Hz -> 0xC8 */
+       {0x00, 0x3a, 0x00, 0xaa}, /* mx change yuyv format 00, 04, 01; 08, 0c*/
+       {0x00, 0x14, 0x2a, 0xaa}, /* agc ampli */
+       {0x00, 0x9e, 0x40, 0xaa},       {0xb8, 0x8f, 0x50, 0xcc},
+       {0x00, 0x01, 0x80, 0xaa},
+       {0x00, 0x02, 0x80, 0xaa},
+/* sizer filters */
+       {0xbc, 0x02, 0x08, 0xcc},
+       {0xbc, 0x03, 0x70, 0xcc},
+       {0xb8, 0x35, 0x00, 0xcc},
+       {0xb8, 0x36, 0x00, 0xcc},
+       {0xb8, 0x37, 0x00, 0xcc},
+       {0xbc, 0x04, 0x08, 0xcc},
+       {0xbc, 0x05, 0x00, 0xcc},
+       {0xbc, 0x06, 0x00, 0xcc},
+       {0xbc, 0x08, 0x3c, 0xcc},
+       {0xbc, 0x09, 0x40, 0xcc},
+       {0xbc, 0x0a, 0x04, 0xcc},
+       {0xbc, 0x0b, 0x00, 0xcc},
+       {0xbc, 0x0c, 0x00, 0xcc},
+/* */
+       {0xb8, 0xfe, 0x00, 0xcc},
+       {0xb8, 0xff, 0x28, 0xcc},
+/* */
+       {0xb9, 0x00, 0x28, 0xcc},       {0xb9, 0x01, 0x28, 0xcc},
+       {0xb9, 0x02, 0x28, 0xcc},       {0xb9, 0x03, 0x00, 0xcc},
+       {0xb9, 0x04, 0x00, 0xcc},       {0xb9, 0x05, 0x3c, 0xcc},
+       {0xb9, 0x06, 0x3c, 0xcc},       {0xb9, 0x07, 0x3c, 0xcc},
+       {0xb9, 0x08, 0x3c, 0xcc},
+/* */
+       {0xb8, 0x8e, 0x00, 0xcc},
+       {0xb8, 0x8f, 0xff, 0xcc}, /* ff */
+       {0x00, 0x29, 0x3c, 0xaa},
+       {0xb3, 0x01, 0x45, 0xcc}, /* 45 */
+       {}
+};
+
+static const u8 ov7660_50HZ[][4] = {
+       {0x00, 0x3b, 0x08, 0xaa},
+       {0x00, 0x9d, 0x40, 0xaa},
+       {0x00, 0x13, 0xa7, 0xaa},
+       {}
+};
+
+static const u8 ov7660_60HZ[][4] = {
+       {0x00, 0x3b, 0x00, 0xaa},
+       {0x00, 0x9e, 0x40, 0xaa},
+       {0x00, 0x13, 0xa7, 0xaa},
+       {}
+};
+
+static const u8 ov7660_NoFliker[][4] = {
+       {0x00, 0x13, 0x87, 0xaa},
+       {}
+};
+
+static const u8 ov7670_InitVGA[][4] = {
+       {0xb3, 0x01, 0x05, 0xcc},
+       {0x00, 0x00, 0x30, 0xdd},
+       {0xb0, 0x03, 0x19, 0xcc},
+       {0x00, 0x00, 0x10, 0xdd},
+       {0xb0, 0x04, 0x02, 0xcc},
+       {0x00, 0x00, 0x10, 0xdd},
+       {0xb3, 0x00, 0x66, 0xcc},
+       {0xb3, 0x00, 0x67, 0xcc},
+       {0xb0, 0x16, 0x01, 0xcc},
+       {0xb3, 0x35, 0xa1, 0xcc},       /* i2c add: 21 */
+       {0xb3, 0x34, 0x01, 0xcc},
+       {0xb3, 0x05, 0x01, 0xcc},
+       {0xb3, 0x06, 0x01, 0xcc},
+       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},
+       {0xb3, 0x02, 0x02, 0xcc},
+       {0xb3, 0x03, 0x1f, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},
+       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x02, 0xcc},
+       {0xb3, 0x17, 0x7f, 0xcc},
+       {0xb3, 0x04, 0x05, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x01, 0xcc},
+       {0xb3, 0x23, 0xe0, 0xcc},
+       {0xbc, 0x00, 0x41, 0xcc},
+       {0xbc, 0x01, 0x01, 0xcc},
+       {0x00, 0x12, 0x80, 0xaa},
+       {0x00, 0x00, 0x20, 0xdd},
+       {0x00, 0x12, 0x00, 0xaa},
+       {0x00, 0x11, 0x40, 0xaa},
+       {0x00, 0x6b, 0x0a, 0xaa},
+       {0x00, 0x3a, 0x04, 0xaa},
+       {0x00, 0x40, 0xc0, 0xaa},
+       {0x00, 0x8c, 0x00, 0xaa},
+       {0x00, 0x7a, 0x29, 0xaa},
+       {0x00, 0x7b, 0x0e, 0xaa},
+       {0x00, 0x7c, 0x1a, 0xaa},
+       {0x00, 0x7d, 0x31, 0xaa},
+       {0x00, 0x7e, 0x53, 0xaa},
+       {0x00, 0x7f, 0x60, 0xaa},
+       {0x00, 0x80, 0x6b, 0xaa},
+       {0x00, 0x81, 0x73, 0xaa},
+       {0x00, 0x82, 0x7b, 0xaa},
+       {0x00, 0x83, 0x82, 0xaa},
+       {0x00, 0x84, 0x89, 0xaa},
+       {0x00, 0x85, 0x96, 0xaa},
+       {0x00, 0x86, 0xa1, 0xaa},
+       {0x00, 0x87, 0xb7, 0xaa},
+       {0x00, 0x88, 0xcc, 0xaa},
+       {0x00, 0x89, 0xe1, 0xaa},
+       {0x00, 0x13, 0xe0, 0xaa},
+       {0x00, 0x00, 0x00, 0xaa},
+       {0x00, 0x10, 0x00, 0xaa},
+       {0x00, 0x0d, 0x40, 0xaa},
+       {0x00, 0x14, 0x28, 0xaa},
+       {0x00, 0xa5, 0x05, 0xaa},
+       {0x00, 0xab, 0x07, 0xaa},
+       {0x00, 0x24, 0x95, 0xaa},
+       {0x00, 0x25, 0x33, 0xaa},
+       {0x00, 0x26, 0xe3, 0xaa},
+       {0x00, 0x9f, 0x88, 0xaa},
+       {0x00, 0xa0, 0x78, 0xaa},
+       {0x00, 0x55, 0x90, 0xaa},
+       {0x00, 0xa1, 0x03, 0xaa},
+       {0x00, 0xa6, 0xe0, 0xaa},
+       {0x00, 0xa7, 0xd8, 0xaa},
+       {0x00, 0xa8, 0xf0, 0xaa},
+       {0x00, 0xa9, 0x90, 0xaa},
+       {0x00, 0xaa, 0x14, 0xaa},
+       {0x00, 0x13, 0xe5, 0xaa},
+       {0x00, 0x0e, 0x61, 0xaa},
+       {0x00, 0x0f, 0x4b, 0xaa},
+       {0x00, 0x16, 0x02, 0xaa},
+       {0x00, 0x1e, 0x07, 0xaa},       /* MVFP */
+       {0x00, 0x21, 0x02, 0xaa},
+       {0x00, 0x22, 0x91, 0xaa},
+       {0x00, 0x29, 0x07, 0xaa},
+       {0x00, 0x33, 0x0b, 0xaa},
+       {0x00, 0x35, 0x0b, 0xaa},
+       {0x00, 0x37, 0x1d, 0xaa},
+       {0x00, 0x38, 0x71, 0xaa},
+       {0x00, 0x39, 0x2a, 0xaa},
+       {0x00, 0x3c, 0x78, 0xaa},
+       {0x00, 0x4d, 0x40, 0xaa},
+       {0x00, 0x4e, 0x20, 0xaa},
+       {0x00, 0x74, 0x19, 0xaa},
+       {0x00, 0x8d, 0x4f, 0xaa},
+       {0x00, 0x8e, 0x00, 0xaa},
+       {0x00, 0x8f, 0x00, 0xaa},
+       {0x00, 0x90, 0x00, 0xaa},
+       {0x00, 0x91, 0x00, 0xaa},
+       {0x00, 0x96, 0x00, 0xaa},
+       {0x00, 0x9a, 0x80, 0xaa},
+       {0x00, 0xb0, 0x84, 0xaa},
+       {0x00, 0xb1, 0x0c, 0xaa},
+       {0x00, 0xb2, 0x0e, 0xaa},
+       {0x00, 0xb3, 0x82, 0xaa},
+       {0x00, 0xb8, 0x0a, 0xaa},
+       {0x00, 0x43, 0x14, 0xaa},
+       {0x00, 0x44, 0xf0, 0xaa},
+       {0x00, 0x45, 0x45, 0xaa},
+       {0x00, 0x46, 0x63, 0xaa},
+       {0x00, 0x47, 0x2d, 0xaa},
+       {0x00, 0x48, 0x46, 0xaa},
+       {0x00, 0x59, 0x88, 0xaa},
+       {0x00, 0x5a, 0xa0, 0xaa},
+       {0x00, 0x5b, 0xc6, 0xaa},
+       {0x00, 0x5c, 0x7d, 0xaa},
+       {0x00, 0x5d, 0x5f, 0xaa},
+       {0x00, 0x5e, 0x19, 0xaa},
+       {0x00, 0x6c, 0x0a, 0xaa},
+       {0x00, 0x6d, 0x55, 0xaa},
+       {0x00, 0x6e, 0x11, 0xaa},
+       {0x00, 0x6f, 0x9e, 0xaa},
+       {0x00, 0x69, 0x00, 0xaa},
+       {0x00, 0x6a, 0x40, 0xaa},
+       {0x00, 0x01, 0x40, 0xaa},
+       {0x00, 0x02, 0x40, 0xaa},
+       {0x00, 0x13, 0xe7, 0xaa},
+       {0x00, 0x5f, 0xf0, 0xaa},
+       {0x00, 0x60, 0xf0, 0xaa},
+       {0x00, 0x61, 0xf0, 0xaa},
+       {0x00, 0x27, 0xa0, 0xaa},
+       {0x00, 0x28, 0x80, 0xaa},
+       {0x00, 0x2c, 0x90, 0xaa},
+       {0x00, 0x4f, 0x66, 0xaa},
+       {0x00, 0x50, 0x66, 0xaa},
+       {0x00, 0x51, 0x00, 0xaa},
+       {0x00, 0x52, 0x22, 0xaa},
+       {0x00, 0x53, 0x5e, 0xaa},
+       {0x00, 0x54, 0x80, 0xaa},
+       {0x00, 0x58, 0x9e, 0xaa},
+       {0x00, 0x41, 0x08, 0xaa},
+       {0x00, 0x3f, 0x00, 0xaa},
+       {0x00, 0x75, 0x85, 0xaa},
+       {0x00, 0x76, 0xe1, 0xaa},
+       {0x00, 0x4c, 0x00, 0xaa},
+       {0x00, 0x77, 0x0a, 0xaa},
+       {0x00, 0x3d, 0x88, 0xaa},
+       {0x00, 0x4b, 0x09, 0xaa},
+       {0x00, 0xc9, 0x60, 0xaa},
+       {0x00, 0x41, 0x38, 0xaa},
+       {0x00, 0x62, 0x30, 0xaa},
+       {0x00, 0x63, 0x30, 0xaa},
+       {0x00, 0x64, 0x08, 0xaa},
+       {0x00, 0x94, 0x07, 0xaa},
+       {0x00, 0x95, 0x0b, 0xaa},
+       {0x00, 0x65, 0x00, 0xaa},
+       {0x00, 0x66, 0x05, 0xaa},
+       {0x00, 0x56, 0x50, 0xaa},
+       {0x00, 0x34, 0x11, 0xaa},
+       {0x00, 0xa4, 0x88, 0xaa},
+       {0x00, 0x96, 0x00, 0xaa},
+       {0x00, 0x97, 0x30, 0xaa},
+       {0x00, 0x98, 0x20, 0xaa},
+       {0x00, 0x99, 0x30, 0xaa},
+       {0x00, 0x9a, 0x84, 0xaa},
+       {0x00, 0x9b, 0x29, 0xaa},
+       {0x00, 0x9c, 0x03, 0xaa},
+       {0x00, 0x78, 0x04, 0xaa},
+       {0x00, 0x79, 0x01, 0xaa},
+       {0x00, 0xc8, 0xf0, 0xaa},
+       {0x00, 0x79, 0x0f, 0xaa},
+       {0x00, 0xc8, 0x00, 0xaa},
+       {0x00, 0x79, 0x10, 0xaa},
+       {0x00, 0xc8, 0x7e, 0xaa},
+       {0x00, 0x79, 0x0a, 0xaa},
+       {0x00, 0xc8, 0x80, 0xaa},
+       {0x00, 0x79, 0x0b, 0xaa},
+       {0x00, 0xc8, 0x01, 0xaa},
+       {0x00, 0x79, 0x0c, 0xaa},
+       {0x00, 0xc8, 0x0f, 0xaa},
+       {0x00, 0x79, 0x0d, 0xaa},
+       {0x00, 0xc8, 0x20, 0xaa},
+       {0x00, 0x79, 0x09, 0xaa},
+       {0x00, 0xc8, 0x80, 0xaa},
+       {0x00, 0x79, 0x02, 0xaa},
+       {0x00, 0xc8, 0xc0, 0xaa},
+       {0x00, 0x79, 0x03, 0xaa},
+       {0x00, 0xc8, 0x40, 0xaa},
+       {0x00, 0x79, 0x05, 0xaa},
+       {0x00, 0xc8, 0x30, 0xaa},
+       {0x00, 0x79, 0x26, 0xaa},
+       {0x00, 0x11, 0x40, 0xaa},
+       {0x00, 0x3a, 0x04, 0xaa},
+       {0x00, 0x12, 0x00, 0xaa},
+       {0x00, 0x40, 0xc0, 0xaa},
+       {0x00, 0x8c, 0x00, 0xaa},
+       {0x00, 0x17, 0x14, 0xaa},
+       {0x00, 0x18, 0x02, 0xaa},
+       {0x00, 0x32, 0x92, 0xaa},
+       {0x00, 0x19, 0x02, 0xaa},
+       {0x00, 0x1a, 0x7a, 0xaa},
+       {0x00, 0x03, 0x0a, 0xaa},
+       {0x00, 0x0c, 0x00, 0xaa},
+       {0x00, 0x3e, 0x00, 0xaa},
+       {0x00, 0x70, 0x3a, 0xaa},
+       {0x00, 0x71, 0x35, 0xaa},
+       {0x00, 0x72, 0x11, 0xaa},
+       {0x00, 0x73, 0xf0, 0xaa},
+       {0x00, 0xa2, 0x02, 0xaa},
+       {0x00, 0xb1, 0x00, 0xaa},
+       {0x00, 0xb1, 0x0c, 0xaa},
+       {0x00, 0x1e, 0x37, 0xaa},       /* MVFP */
+       {0x00, 0xaa, 0x14, 0xaa},
+       {0x00, 0x24, 0x80, 0xaa},
+       {0x00, 0x25, 0x74, 0xaa},
+       {0x00, 0x26, 0xd3, 0xaa},
+       {0x00, 0x0d, 0x00, 0xaa},
+       {0x00, 0x14, 0x18, 0xaa},
+       {0x00, 0x9d, 0x99, 0xaa},
+       {0x00, 0x9e, 0x7f, 0xaa},
+       {0x00, 0x64, 0x08, 0xaa},
+       {0x00, 0x94, 0x07, 0xaa},
+       {0x00, 0x95, 0x06, 0xaa},
+       {0x00, 0x66, 0x05, 0xaa},
+       {0x00, 0x41, 0x08, 0xaa},
+       {0x00, 0x3f, 0x00, 0xaa},
+       {0x00, 0x75, 0x07, 0xaa},
+       {0x00, 0x76, 0xe1, 0xaa},
+       {0x00, 0x4c, 0x00, 0xaa},
+       {0x00, 0x77, 0x00, 0xaa},
+       {0x00, 0x3d, 0xc2, 0xaa},
+       {0x00, 0x4b, 0x09, 0xaa},
+       {0x00, 0xc9, 0x60, 0xaa},
+       {0x00, 0x41, 0x38, 0xaa},
+       {0xbf, 0xc0, 0x26, 0xcc},
+       {0xbf, 0xc1, 0x02, 0xcc},
+       {0xbf, 0xcc, 0x04, 0xcc},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {0xb3, 0x01, 0x45, 0xcc},
+       {0x00, 0x77, 0x05, 0xaa},
+       {},
+};
+
+static const u8 ov7670_InitQVGA[][4] = {
+       {0xb3, 0x01, 0x05, 0xcc},
+       {0x00, 0x00, 0x30, 0xdd},
+       {0xb0, 0x03, 0x19, 0xcc},
+       {0x00, 0x00, 0x10, 0xdd},
+       {0xb0, 0x04, 0x02, 0xcc},
+       {0x00, 0x00, 0x10, 0xdd},
+       {0xb3, 0x00, 0x66, 0xcc},
+       {0xb3, 0x00, 0x67, 0xcc},
+       {0xb0, 0x16, 0x01, 0xcc},
+       {0xb3, 0x35, 0xa1, 0xcc},       /* i2c add: 21 */
+       {0xb3, 0x34, 0x01, 0xcc},
+       {0xb3, 0x05, 0x01, 0xcc},
+       {0xb3, 0x06, 0x01, 0xcc},
+       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},
+       {0xb3, 0x02, 0x02, 0xcc},
+       {0xb3, 0x03, 0x1f, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},
+       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x02, 0xcc},
+       {0xb3, 0x17, 0x7f, 0xcc},
+       {0xb3, 0x04, 0x05, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x01, 0xcc},
+       {0xb3, 0x23, 0xe0, 0xcc},
+       {0xbc, 0x00, 0xd1, 0xcc},
+       {0xbc, 0x01, 0x01, 0xcc},
+       {0x00, 0x12, 0x80, 0xaa},
+       {0x00, 0x00, 0x20, 0xdd},
+       {0x00, 0x12, 0x00, 0xaa},
+       {0x00, 0x11, 0x40, 0xaa},
+       {0x00, 0x6b, 0x0a, 0xaa},
+       {0x00, 0x3a, 0x04, 0xaa},
+       {0x00, 0x40, 0xc0, 0xaa},
+       {0x00, 0x8c, 0x00, 0xaa},
+       {0x00, 0x7a, 0x29, 0xaa},
+       {0x00, 0x7b, 0x0e, 0xaa},
+       {0x00, 0x7c, 0x1a, 0xaa},
+       {0x00, 0x7d, 0x31, 0xaa},
+       {0x00, 0x7e, 0x53, 0xaa},
+       {0x00, 0x7f, 0x60, 0xaa},
+       {0x00, 0x80, 0x6b, 0xaa},
+       {0x00, 0x81, 0x73, 0xaa},
+       {0x00, 0x82, 0x7b, 0xaa},
+       {0x00, 0x83, 0x82, 0xaa},
+       {0x00, 0x84, 0x89, 0xaa},
+       {0x00, 0x85, 0x96, 0xaa},
+       {0x00, 0x86, 0xa1, 0xaa},
+       {0x00, 0x87, 0xb7, 0xaa},
+       {0x00, 0x88, 0xcc, 0xaa},
+       {0x00, 0x89, 0xe1, 0xaa},
+       {0x00, 0x13, 0xe0, 0xaa},
+       {0x00, 0x00, 0x00, 0xaa},
+       {0x00, 0x10, 0x00, 0xaa},
+       {0x00, 0x0d, 0x40, 0xaa},
+       {0x00, 0x14, 0x28, 0xaa},
+       {0x00, 0xa5, 0x05, 0xaa},
+       {0x00, 0xab, 0x07, 0xaa},
+       {0x00, 0x24, 0x95, 0xaa},
+       {0x00, 0x25, 0x33, 0xaa},
+       {0x00, 0x26, 0xe3, 0xaa},
+       {0x00, 0x9f, 0x88, 0xaa},
+       {0x00, 0xa0, 0x78, 0xaa},
+       {0x00, 0x55, 0x90, 0xaa},
+       {0x00, 0xa1, 0x03, 0xaa},
+       {0x00, 0xa6, 0xe0, 0xaa},
+       {0x00, 0xa7, 0xd8, 0xaa},
+       {0x00, 0xa8, 0xf0, 0xaa},
+       {0x00, 0xa9, 0x90, 0xaa},
+       {0x00, 0xaa, 0x14, 0xaa},
+       {0x00, 0x13, 0xe5, 0xaa},
+       {0x00, 0x0e, 0x61, 0xaa},
+       {0x00, 0x0f, 0x4b, 0xaa},
+       {0x00, 0x16, 0x02, 0xaa},
+       {0x00, 0x1e, 0x07, 0xaa},       /* MVFP */
+       {0x00, 0x21, 0x02, 0xaa},
+       {0x00, 0x22, 0x91, 0xaa},
+       {0x00, 0x29, 0x07, 0xaa},
+       {0x00, 0x33, 0x0b, 0xaa},
+       {0x00, 0x35, 0x0b, 0xaa},
+       {0x00, 0x37, 0x1d, 0xaa},
+       {0x00, 0x38, 0x71, 0xaa},
+       {0x00, 0x39, 0x2a, 0xaa},
+       {0x00, 0x3c, 0x78, 0xaa},
+       {0x00, 0x4d, 0x40, 0xaa},
+       {0x00, 0x4e, 0x20, 0xaa},
+       {0x00, 0x74, 0x19, 0xaa},
+       {0x00, 0x8d, 0x4f, 0xaa},
+       {0x00, 0x8e, 0x00, 0xaa},
+       {0x00, 0x8f, 0x00, 0xaa},
+       {0x00, 0x90, 0x00, 0xaa},
+       {0x00, 0x91, 0x00, 0xaa},
+       {0x00, 0x96, 0x00, 0xaa},
+       {0x00, 0x9a, 0x80, 0xaa},
+       {0x00, 0xb0, 0x84, 0xaa},
+       {0x00, 0xb1, 0x0c, 0xaa},
+       {0x00, 0xb2, 0x0e, 0xaa},
+       {0x00, 0xb3, 0x82, 0xaa},
+       {0x00, 0xb8, 0x0a, 0xaa},
+       {0x00, 0x43, 0x14, 0xaa},
+       {0x00, 0x44, 0xf0, 0xaa},
+       {0x00, 0x45, 0x45, 0xaa},
+       {0x00, 0x46, 0x63, 0xaa},
+       {0x00, 0x47, 0x2d, 0xaa},
+       {0x00, 0x48, 0x46, 0xaa},
+       {0x00, 0x59, 0x88, 0xaa},
+       {0x00, 0x5a, 0xa0, 0xaa},
+       {0x00, 0x5b, 0xc6, 0xaa},
+       {0x00, 0x5c, 0x7d, 0xaa},
+       {0x00, 0x5d, 0x5f, 0xaa},
+       {0x00, 0x5e, 0x19, 0xaa},
+       {0x00, 0x6c, 0x0a, 0xaa},
+       {0x00, 0x6d, 0x55, 0xaa},
+       {0x00, 0x6e, 0x11, 0xaa},
+       {0x00, 0x6f, 0x9e, 0xaa},
+       {0x00, 0x69, 0x00, 0xaa},
+       {0x00, 0x6a, 0x40, 0xaa},
+       {0x00, 0x01, 0x40, 0xaa},
+       {0x00, 0x02, 0x40, 0xaa},
+       {0x00, 0x13, 0xe7, 0xaa},
+       {0x00, 0x5f, 0xf0, 0xaa},
+       {0x00, 0x60, 0xf0, 0xaa},
+       {0x00, 0x61, 0xf0, 0xaa},
+       {0x00, 0x27, 0xa0, 0xaa},
+       {0x00, 0x28, 0x80, 0xaa},
+       {0x00, 0x2c, 0x90, 0xaa},
+       {0x00, 0x4f, 0x66, 0xaa},
+       {0x00, 0x50, 0x66, 0xaa},
+       {0x00, 0x51, 0x00, 0xaa},
+       {0x00, 0x52, 0x22, 0xaa},
+       {0x00, 0x53, 0x5e, 0xaa},
+       {0x00, 0x54, 0x80, 0xaa},
+       {0x00, 0x58, 0x9e, 0xaa},
+       {0x00, 0x41, 0x08, 0xaa},
+       {0x00, 0x3f, 0x00, 0xaa},
+       {0x00, 0x75, 0x85, 0xaa},
+       {0x00, 0x76, 0xe1, 0xaa},
+       {0x00, 0x4c, 0x00, 0xaa},
+       {0x00, 0x77, 0x0a, 0xaa},
+       {0x00, 0x3d, 0x88, 0xaa},
+       {0x00, 0x4b, 0x09, 0xaa},
+       {0x00, 0xc9, 0x60, 0xaa},
+       {0x00, 0x41, 0x38, 0xaa},
+       {0x00, 0x62, 0x30, 0xaa},
+       {0x00, 0x63, 0x30, 0xaa},
+       {0x00, 0x64, 0x08, 0xaa},
+       {0x00, 0x94, 0x07, 0xaa},
+       {0x00, 0x95, 0x0b, 0xaa},
+       {0x00, 0x65, 0x00, 0xaa},
+       {0x00, 0x66, 0x05, 0xaa},
+       {0x00, 0x56, 0x50, 0xaa},
+       {0x00, 0x34, 0x11, 0xaa},
+       {0x00, 0xa4, 0x88, 0xaa},
+       {0x00, 0x96, 0x00, 0xaa},
+       {0x00, 0x97, 0x30, 0xaa},
+       {0x00, 0x98, 0x20, 0xaa},
+       {0x00, 0x99, 0x30, 0xaa},
+       {0x00, 0x9a, 0x84, 0xaa},
+       {0x00, 0x9b, 0x29, 0xaa},
+       {0x00, 0x9c, 0x03, 0xaa},
+       {0x00, 0x78, 0x04, 0xaa},
+       {0x00, 0x79, 0x01, 0xaa},
+       {0x00, 0xc8, 0xf0, 0xaa},
+       {0x00, 0x79, 0x0f, 0xaa},
+       {0x00, 0xc8, 0x00, 0xaa},
+       {0x00, 0x79, 0x10, 0xaa},
+       {0x00, 0xc8, 0x7e, 0xaa},
+       {0x00, 0x79, 0x0a, 0xaa},
+       {0x00, 0xc8, 0x80, 0xaa},
+       {0x00, 0x79, 0x0b, 0xaa},
+       {0x00, 0xc8, 0x01, 0xaa},
+       {0x00, 0x79, 0x0c, 0xaa},
+       {0x00, 0xc8, 0x0f, 0xaa},
+       {0x00, 0x79, 0x0d, 0xaa},
+       {0x00, 0xc8, 0x20, 0xaa},
+       {0x00, 0x79, 0x09, 0xaa},
+       {0x00, 0xc8, 0x80, 0xaa},
+       {0x00, 0x79, 0x02, 0xaa},
+       {0x00, 0xc8, 0xc0, 0xaa},
+       {0x00, 0x79, 0x03, 0xaa},
+       {0x00, 0xc8, 0x40, 0xaa},
+       {0x00, 0x79, 0x05, 0xaa},
+       {0x00, 0xc8, 0x30, 0xaa},
+       {0x00, 0x79, 0x26, 0xaa},
+       {0x00, 0x11, 0x40, 0xaa},
+       {0x00, 0x3a, 0x04, 0xaa},
+       {0x00, 0x12, 0x00, 0xaa},
+       {0x00, 0x40, 0xc0, 0xaa},
+       {0x00, 0x8c, 0x00, 0xaa},
+       {0x00, 0x17, 0x14, 0xaa},
+       {0x00, 0x18, 0x02, 0xaa},
+       {0x00, 0x32, 0x92, 0xaa},
+       {0x00, 0x19, 0x02, 0xaa},
+       {0x00, 0x1a, 0x7a, 0xaa},
+       {0x00, 0x03, 0x0a, 0xaa},
+       {0x00, 0x0c, 0x00, 0xaa},
+       {0x00, 0x3e, 0x00, 0xaa},
+       {0x00, 0x70, 0x3a, 0xaa},
+       {0x00, 0x71, 0x35, 0xaa},
+       {0x00, 0x72, 0x11, 0xaa},
+       {0x00, 0x73, 0xf0, 0xaa},
+       {0x00, 0xa2, 0x02, 0xaa},
+       {0x00, 0xb1, 0x00, 0xaa},
+       {0x00, 0xb1, 0x0c, 0xaa},
+       {0x00, 0x1e, 0x37, 0xaa},       /* MVFP */
+       {0x00, 0xaa, 0x14, 0xaa},
+       {0x00, 0x24, 0x80, 0xaa},
+       {0x00, 0x25, 0x74, 0xaa},
+       {0x00, 0x26, 0xd3, 0xaa},
+       {0x00, 0x0d, 0x00, 0xaa},
+       {0x00, 0x14, 0x18, 0xaa},
+       {0x00, 0x9d, 0x99, 0xaa},
+       {0x00, 0x9e, 0x7f, 0xaa},
+       {0x00, 0x64, 0x08, 0xaa},
+       {0x00, 0x94, 0x07, 0xaa},
+       {0x00, 0x95, 0x06, 0xaa},
+       {0x00, 0x66, 0x05, 0xaa},
+       {0x00, 0x41, 0x08, 0xaa},
+       {0x00, 0x3f, 0x00, 0xaa},
+       {0x00, 0x75, 0x07, 0xaa},
+       {0x00, 0x76, 0xe1, 0xaa},
+       {0x00, 0x4c, 0x00, 0xaa},
+       {0x00, 0x77, 0x00, 0xaa},
+       {0x00, 0x3d, 0xc2, 0xaa},
+       {0x00, 0x4b, 0x09, 0xaa},
+       {0x00, 0xc9, 0x60, 0xaa},
+       {0x00, 0x41, 0x38, 0xaa},
+       {0xbc, 0x02, 0x18, 0xcc},
+       {0xbc, 0x03, 0x50, 0xcc},
+       {0xbc, 0x04, 0x18, 0xcc},
+       {0xbc, 0x05, 0x00, 0xcc},
+       {0xbc, 0x06, 0x00, 0xcc},
+       {0xbc, 0x08, 0x30, 0xcc},
+       {0xbc, 0x09, 0x40, 0xcc},
+       {0xbc, 0x0a, 0x10, 0xcc},
+       {0xbc, 0x0b, 0x00, 0xcc},
+       {0xbc, 0x0c, 0x00, 0xcc},
+       {0xbf, 0xc0, 0x26, 0xcc},
+       {0xbf, 0xc1, 0x02, 0xcc},
+       {0xbf, 0xcc, 0x04, 0xcc},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {0xb3, 0x01, 0x45, 0xcc},
+       {0x00, 0x77, 0x05, 0xaa},
+       {},
+};
+
+/* PO1200 - values from usbvm326.inf and ms-win trace */
+static const u8 po1200_gamma[17] = {
+       0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
+       0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
+};
+static const u8 po1200_matrix[9] = {
+       0x60, 0xf9, 0xe5, 0xe7, 0x50, 0x05, 0xf3, 0xe6, 0x5e
+};
+static const u8 po1200_initVGA_data[][4] = {
+       {0xb0, 0x03, 0x19, 0xcc},       /* reset? */
+       {0xb0, 0x03, 0x19, 0xcc},
+/*     {0x00, 0x00, 0x33, 0xdd}, */
+       {0xb0, 0x04, 0x02, 0xcc},
+       {0xb0, 0x02, 0x02, 0xcc},
+       {0xb3, 0x5d, 0x00, 0xcc},
+       {0xb3, 0x01, 0x01, 0xcc},
+       {0xb3, 0x00, 0x64, 0xcc},
+       {0xb3, 0x00, 0x65, 0xcc},
+       {0xb3, 0x05, 0x01, 0xcc},
+       {0xb3, 0x06, 0x01, 0xcc},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},
+       {0xb3, 0x00, 0x67, 0xcc},
+       {0xb3, 0x02, 0xb2, 0xcc},
+       {0xb3, 0x03, 0x18, 0xcc},
+       {0xb3, 0x04, 0x15, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x02, 0xcc},
+       {0xb3, 0x23, 0x58, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},
+       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x03, 0xcc},
+       {0xb3, 0x17, 0x1f, 0xcc},
+       {0xbc, 0x00, 0x71, 0xcc},
+       {0xbc, 0x01, 0x01, 0xcc},
+       {0xb0, 0x54, 0x13, 0xcc},
+       {0xb3, 0x00, 0x67, 0xcc},
+       {0xb3, 0x34, 0x01, 0xcc},
+       {0xb3, 0x35, 0xdc, 0xcc},       /* i2c add: 5c */
+       {0x00, 0x03, 0x00, 0xaa},
+       {0x00, 0x12, 0x05, 0xaa},
+       {0x00, 0x13, 0x02, 0xaa},
+       {0x00, 0x1e, 0xc6, 0xaa},       /* h/v flip */
+       {0x00, 0x21, 0x00, 0xaa},
+       {0x00, 0x25, 0x02, 0xaa},
+       {0x00, 0x3c, 0x4f, 0xaa},
+       {0x00, 0x3f, 0xe0, 0xaa},
+       {0x00, 0x42, 0xff, 0xaa},
+       {0x00, 0x45, 0x34, 0xaa},
+       {0x00, 0x55, 0xfe, 0xaa},
+       {0x00, 0x59, 0xd3, 0xaa},
+       {0x00, 0x5e, 0x04, 0xaa},
+       {0x00, 0x61, 0xb8, 0xaa},       /* sharpness */
+       {0x00, 0x62, 0x02, 0xaa},
+       {0x00, 0xa7, 0x31, 0xaa},
+       {0x00, 0xa9, 0x66, 0xaa},
+       {0x00, 0xb0, 0x00, 0xaa},
+       {0x00, 0xb1, 0x00, 0xaa},
+       {0x00, 0xb3, 0x11, 0xaa},
+       {0x00, 0xb6, 0x26, 0xaa},
+       {0x00, 0xb7, 0x20, 0xaa},
+       {0x00, 0xba, 0x04, 0xaa},
+       {0x00, 0x88, 0x42, 0xaa},
+       {0x00, 0x89, 0x9a, 0xaa},
+       {0x00, 0x8a, 0x88, 0xaa},
+       {0x00, 0x8b, 0x8e, 0xaa},
+       {0x00, 0x8c, 0x3e, 0xaa},
+       {0x00, 0x8d, 0x90, 0xaa},
+       {0x00, 0x8e, 0x87, 0xaa},
+       {0x00, 0x8f, 0x96, 0xaa},
+       {0x00, 0x90, 0x3d, 0xaa},
+       {0x00, 0x64, 0x00, 0xaa},
+       {0x00, 0x65, 0x10, 0xaa},
+       {0x00, 0x66, 0x20, 0xaa},
+       {0x00, 0x67, 0x2b, 0xaa},
+       {0x00, 0x68, 0x36, 0xaa},
+       {0x00, 0x69, 0x49, 0xaa},
+       {0x00, 0x6a, 0x5a, 0xaa},
+       {0x00, 0x6b, 0x7f, 0xaa},
+       {0x00, 0x6c, 0x9b, 0xaa},
+       {0x00, 0x6d, 0xba, 0xaa},
+       {0x00, 0x6e, 0xd4, 0xaa},
+       {0x00, 0x6f, 0xea, 0xaa},
+       {0x00, 0x70, 0x00, 0xaa},
+       {0x00, 0x71, 0x10, 0xaa},
+       {0x00, 0x72, 0x20, 0xaa},
+       {0x00, 0x73, 0x2b, 0xaa},
+       {0x00, 0x74, 0x36, 0xaa},
+       {0x00, 0x75, 0x49, 0xaa},
+       {0x00, 0x76, 0x5a, 0xaa},
+       {0x00, 0x77, 0x7f, 0xaa},
+       {0x00, 0x78, 0x9b, 0xaa},
+       {0x00, 0x79, 0xba, 0xaa},
+       {0x00, 0x7a, 0xd4, 0xaa},
+       {0x00, 0x7b, 0xea, 0xaa},
+       {0x00, 0x7c, 0x00, 0xaa},
+       {0x00, 0x7d, 0x10, 0xaa},
+       {0x00, 0x7e, 0x20, 0xaa},
+       {0x00, 0x7f, 0x2b, 0xaa},
+       {0x00, 0x80, 0x36, 0xaa},
+       {0x00, 0x81, 0x49, 0xaa},
+       {0x00, 0x82, 0x5a, 0xaa},
+       {0x00, 0x83, 0x7f, 0xaa},
+       {0x00, 0x84, 0x9b, 0xaa},
+       {0x00, 0x85, 0xba, 0xaa},
+       {0x00, 0x86, 0xd4, 0xaa},
+       {0x00, 0x87, 0xea, 0xaa},
+       {0x00, 0x57, 0x2a, 0xaa},
+       {0x00, 0x03, 0x01, 0xaa},
+       {0x00, 0x04, 0x10, 0xaa},
+       {0x00, 0x05, 0x10, 0xaa},
+       {0x00, 0x06, 0x10, 0xaa},
+       {0x00, 0x07, 0x10, 0xaa},
+       {0x00, 0x08, 0x13, 0xaa},
+       {0x00, 0x0a, 0x00, 0xaa},
+       {0x00, 0x0b, 0x10, 0xaa},
+       {0x00, 0x0c, 0x20, 0xaa},
+       {0x00, 0x0d, 0x18, 0xaa},
+       {0x00, 0x22, 0x01, 0xaa},
+       {0x00, 0x23, 0x60, 0xaa},
+       {0x00, 0x25, 0x08, 0xaa},
+       {0x00, 0x26, 0x82, 0xaa},
+       {0x00, 0x2e, 0x0f, 0xaa},
+       {0x00, 0x2f, 0x1e, 0xaa},
+       {0x00, 0x30, 0x2d, 0xaa},
+       {0x00, 0x31, 0x3c, 0xaa},
+       {0x00, 0x32, 0x4b, 0xaa},
+       {0x00, 0x33, 0x5a, 0xaa},
+       {0x00, 0x34, 0x69, 0xaa},
+       {0x00, 0x35, 0x78, 0xaa},
+       {0x00, 0x36, 0x87, 0xaa},
+       {0x00, 0x37, 0x96, 0xaa},
+       {0x00, 0x38, 0xa5, 0xaa},
+       {0x00, 0x39, 0xb4, 0xaa},
+       {0x00, 0x3a, 0xc3, 0xaa},
+       {0x00, 0x3b, 0xd2, 0xaa},
+       {0x00, 0x3c, 0xe1, 0xaa},
+       {0x00, 0x3e, 0xff, 0xaa},
+       {0x00, 0x3f, 0xff, 0xaa},
+       {0x00, 0x40, 0xff, 0xaa},
+       {0x00, 0x41, 0xff, 0xaa},
+       {0x00, 0x42, 0xff, 0xaa},
+       {0x00, 0x43, 0xff, 0xaa},
+       {0x00, 0x03, 0x00, 0xaa},
+       {0x00, 0x03, 0x00, 0xaa},
+       {0x00, 0x20, 0xc4, 0xaa},
+       {0x00, 0x13, 0x03, 0xaa},
+       {0x00, 0x3c, 0x50, 0xaa},
+       {0x00, 0x61, 0x6a, 0xaa},       /* sharpness? */
+       {0x00, 0x51, 0x5b, 0xaa},
+       {0x00, 0x52, 0x91, 0xaa},
+       {0x00, 0x53, 0x4c, 0xaa},
+       {0x00, 0x54, 0x50, 0xaa},
+       {0x00, 0x56, 0x02, 0xaa},
+       {0xb6, 0x00, 0x00, 0xcc},
+       {0xb6, 0x03, 0x03, 0xcc},
+       {0xb6, 0x02, 0x20, 0xcc},
+       {0xb6, 0x05, 0x02, 0xcc},
+       {0xb6, 0x04, 0x58, 0xcc},
+       {0xb6, 0x12, 0xf8, 0xcc},
+       {0xb6, 0x13, 0x21, 0xcc},
+       {0xb6, 0x18, 0x03, 0xcc},
+       {0xb6, 0x17, 0xa9, 0xcc},
+       {0xb6, 0x16, 0x80, 0xcc},
+       {0xb6, 0x22, 0x12, 0xcc},
+       {0xb6, 0x23, 0x0b, 0xcc},
+       {0xbf, 0xc0, 0x39, 0xcc},
+       {0xbf, 0xc1, 0x04, 0xcc},
+       {0xbf, 0xcc, 0x00, 0xcc},
+       {0xb8, 0x06, 0x20, 0xcc},
+       {0xb8, 0x07, 0x03, 0xcc},
+       {0xb8, 0x08, 0x58, 0xcc},
+       {0xb8, 0x09, 0x02, 0xcc},
+       {0xb3, 0x01, 0x41, 0xcc},
+       {0x00, 0x03, 0x00, 0xaa},
+       {0x00, 0xd9, 0x0f, 0xaa},
+       {0x00, 0xda, 0xaa, 0xaa},
+       {0x00, 0xd9, 0x10, 0xaa},
+       {0x00, 0xda, 0xaa, 0xaa},
+       {0x00, 0xd9, 0x11, 0xaa},
+       {0x00, 0xda, 0x00, 0xaa},
+       {0x00, 0xd9, 0x12, 0xaa},
+       {0x00, 0xda, 0xff, 0xaa},
+       {0x00, 0xd9, 0x13, 0xaa},
+       {0x00, 0xda, 0xff, 0xaa},
+       {0x00, 0xe8, 0x11, 0xaa},
+       {0x00, 0xe9, 0x12, 0xaa},
+       {0x00, 0xea, 0x5c, 0xaa},
+       {0x00, 0xeb, 0xff, 0xaa},
+       {0x00, 0xd8, 0x80, 0xaa},
+       {0x00, 0xe6, 0x02, 0xaa},
+       {0x00, 0xd6, 0x40, 0xaa},
+       {0x00, 0xe3, 0x05, 0xaa},
+       {0x00, 0xe0, 0x40, 0xaa},
+       {0x00, 0xde, 0x03, 0xaa},
+       {0x00, 0xdf, 0x03, 0xaa},
+       {0x00, 0xdb, 0x02, 0xaa},
+       {0x00, 0xdc, 0x00, 0xaa},
+       {0x00, 0xdd, 0x03, 0xaa},
+       {0x00, 0xe1, 0x08, 0xaa},
+       {0x00, 0xe2, 0x01, 0xaa},
+       {0x00, 0xd6, 0x40, 0xaa},
+       {0x00, 0xe4, 0x40, 0xaa},
+       {0x00, 0xa8, 0x8f, 0xaa},
+       {0x00, 0xb4, 0x16, 0xaa},
+       {0xb0, 0x02, 0x06, 0xcc},
+       {0xb0, 0x18, 0x06, 0xcc},
+       {0xb0, 0x19, 0x06, 0xcc},
+       {0xb3, 0x5d, 0x18, 0xcc},
+       {0xb3, 0x05, 0x00, 0xcc},
+       {0xb3, 0x06, 0x00, 0xcc},
+       {0x00, 0xb4, 0x0e, 0xaa},
+       {0x00, 0xb5, 0x49, 0xaa},
+       {0x00, 0xb6, 0x1c, 0xaa},
+       {0x00, 0xb7, 0x96, 0xaa},
+/* end of usbvm326.inf - start of ms-win trace */
+       {0xb6, 0x12, 0xf8, 0xcc},
+       {0xb6, 0x13, 0x3d, 0xcc},
+/*read b306*/
+       {0x00, 0x03, 0x00, 0xaa},
+       {0x00, 0x1a, 0x09, 0xaa},
+       {0x00, 0x1b, 0x8a, 0xaa},
+/*read b827*/
+       {0xb8, 0x27, 0x00, 0xcc},
+       {0xb8, 0x26, 0x60, 0xcc},
+       {0xb8, 0x26, 0x60, 0xcc},
+/*gamma - to do?*/
+       {0x00, 0x03, 0x00, 0xaa},
+       {0x00, 0xae, 0x84, 0xaa},
+/*gamma again*/
+       {0x00, 0x03, 0x00, 0xaa},
+       {0x00, 0x96, 0xa0, 0xaa},
+/*matrix*/
+       {0x00, 0x03, 0x00, 0xaa},
+       {0x00, 0x91, 0x35, 0xaa},
+       {0x00, 0x92, 0x22, 0xaa},
+/*gamma*/
+       {0x00, 0x03, 0x00, 0xaa},
+       {0x00, 0x95, 0x85, 0xaa},
+/*matrix*/
+       {0x00, 0x03, 0x00, 0xaa},
+       {0x00, 0x4d, 0x20, 0xaa},
+       {0xb8, 0x22, 0x40, 0xcc},
+       {0xb8, 0x23, 0x40, 0xcc},
+       {0xb8, 0x24, 0x40, 0xcc},
+       {0xb8, 0x81, 0x09, 0xcc},
+       {0x00, 0x00, 0x64, 0xdd},
+       {0x00, 0x03, 0x01, 0xaa},
+/*read 46*/
+       {0x00, 0x46, 0x3c, 0xaa},
+       {0x00, 0x03, 0x00, 0xaa},
+       {0x00, 0x16, 0x40, 0xaa},
+       {0x00, 0x17, 0x40, 0xaa},
+       {0x00, 0x18, 0x40, 0xaa},
+       {0x00, 0x19, 0x41, 0xaa},
+       {0x00, 0x03, 0x01, 0xaa},
+       {0x00, 0x46, 0x3c, 0xaa},
+       {0x00, 0x00, 0x18, 0xdd},
+/*read bfff*/
+       {0x00, 0x03, 0x00, 0xaa},
+       {0x00, 0xb4, 0x1c, 0xaa},
+       {0x00, 0xb5, 0x92, 0xaa},
+       {0x00, 0xb6, 0x39, 0xaa},
+       {0x00, 0xb7, 0x24, 0xaa},
+/*write 89 0400 1415*/
+       {}
+};
+
+static const u8 poxxxx_init_common[][4] = {
+       {0xb3, 0x00, 0x04, 0xcc},
+       {0x00, 0x00, 0x10, 0xdd},
+       {0xb3, 0x00, 0x64, 0xcc},
+       {0x00, 0x00, 0x10, 0xdd},
+       {0xb3, 0x00, 0x65, 0xcc},
+       {0x00, 0x00, 0x10, 0xdd},
+       {0xb3, 0x00, 0x67, 0xcc},
+       {0xb0, 0x03, 0x09, 0xcc},
+       {0xb3, 0x05, 0x00, 0xcc},
+       {0xb3, 0x06, 0x00, 0xcc},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {0xb3, 0x08, 0x01, 0xcc},
+       {0xb3, 0x09, 0x0c, 0xcc},
+       {0xb3, 0x34, 0x01, 0xcc},
+       {0xb3, 0x35, 0xf6, 0xcc},       /* i2c add: 76 */
+       {0xb3, 0x02, 0xb0, 0xcc},
+       {0xb3, 0x03, 0x18, 0xcc},
+       {0xb3, 0x04, 0x15, 0xcc},
+       {0xb3, 0x20, 0x00, 0xcc},
+       {0xb3, 0x21, 0x00, 0xcc},
+       {0xb3, 0x22, 0x04, 0xcc},       /* sensor height = 1024 */
+       {0xb3, 0x23, 0x00, 0xcc},
+       {0xb3, 0x14, 0x00, 0xcc},
+       {0xb3, 0x15, 0x00, 0xcc},
+       {0xb3, 0x16, 0x04, 0xcc},       /* sensor width = 1280 */
+       {0xb3, 0x17, 0xff, 0xcc},
+       {0xb3, 0x2c, 0x03, 0xcc},
+       {0xb3, 0x2d, 0x56, 0xcc},
+       {0xb3, 0x2e, 0x02, 0xcc},
+       {0xb3, 0x2f, 0x0a, 0xcc},
+       {0xb3, 0x40, 0x00, 0xcc},
+       {0xb3, 0x41, 0x34, 0xcc},
+       {0xb3, 0x42, 0x01, 0xcc},
+       {0xb3, 0x43, 0xe0, 0xcc},
+       {0xbc, 0x00, 0x71, 0xcc},
+       {0xbc, 0x01, 0x01, 0xcc},
+       {0xb3, 0x01, 0x41, 0xcc},
+       {0xb3, 0x4d, 0x00, 0xcc},
+       {0x00, 0x0b, 0x2a, 0xaa},
+       {0x00, 0x0e, 0x03, 0xaa},
+       {0x00, 0x0f, 0xea, 0xaa},
+       {0x00, 0x12, 0x08, 0xaa},
+       {0x00, 0x1e, 0x06, 0xaa},
+       {0x00, 0x21, 0x00, 0xaa},
+       {0x00, 0x31, 0x1f, 0xaa},
+       {0x00, 0x33, 0x38, 0xaa},
+       {0x00, 0x36, 0xc0, 0xaa},
+       {0x00, 0x37, 0xc8, 0xaa},
+       {0x00, 0x3b, 0x36, 0xaa},
+       {0x00, 0x4b, 0xfe, 0xaa},
+       {0x00, 0x4d, 0x2e, 0xaa},
+       {0x00, 0x51, 0x1c, 0xaa},
+       {0x00, 0x52, 0x01, 0xaa},
+       {0x00, 0x55, 0x0a, 0xaa},
+       {0x00, 0x56, 0x0a, 0xaa},
+       {0x00, 0x57, 0x07, 0xaa},
+       {0x00, 0x58, 0x07, 0xaa},
+       {0x00, 0x59, 0x04, 0xaa},
+       {0x00, 0x70, 0x68, 0xaa},
+       {0x00, 0x71, 0x04, 0xaa},
+       {0x00, 0x72, 0x10, 0xaa},
+       {0x00, 0x80, 0x71, 0xaa},
+       {0x00, 0x81, 0x08, 0xaa},
+       {0x00, 0x82, 0x00, 0xaa},
+       {0x00, 0x83, 0x55, 0xaa},
+       {0x00, 0x84, 0x06, 0xaa},
+       {0x00, 0x85, 0x06, 0xaa},
+       {0x00, 0x8b, 0x25, 0xaa},
+       {0x00, 0x8c, 0x00, 0xaa},
+       {0x00, 0x8d, 0x86, 0xaa},
+       {0x00, 0x8e, 0x82, 0xaa},
+       {0x00, 0x8f, 0x2d, 0xaa},
+       {0x00, 0x90, 0x8b, 0xaa},
+       {0x00, 0x91, 0x81, 0xaa},
+       {0x00, 0x92, 0x81, 0xaa},
+       {0x00, 0x93, 0x23, 0xaa},
+       {0x00, 0xa3, 0x2a, 0xaa},
+       {0x00, 0xa4, 0x03, 0xaa},
+       {0x00, 0xa5, 0xea, 0xaa},
+       {0x00, 0xb0, 0x68, 0xaa},
+       {0x00, 0xbc, 0x04, 0xaa},
+       {0x00, 0xbe, 0x3b, 0xaa},
+       {0x00, 0x4e, 0x40, 0xaa},
+       {0x00, 0x06, 0x04, 0xaa},
+       {0x00, 0x07, 0x03, 0xaa},
+       {0x00, 0xcd, 0x18, 0xaa},
+       {0x00, 0x28, 0x03, 0xaa},
+       {0x00, 0x29, 0xef, 0xaa},
+/* reinit on alt 2 (qvga) or alt7 (vga) */
+       {0xb3, 0x05, 0x00, 0xcc},
+       {0xb3, 0x06, 0x00, 0xcc},
+       {0xb8, 0x00, 0x01, 0xcc},
+
+       {0x00, 0x1d, 0x85, 0xaa},
+       {0x00, 0x1e, 0xc6, 0xaa},
+       {0x00, 0x00, 0x40, 0xdd},
+       {0x00, 0x1d, 0x05, 0xaa},
+       {}
+};
+static const u8 poxxxx_gamma[][4] = {
+       {0x00, 0xd6, 0x22, 0xaa},       /* gamma 0 */
+       {0x00, 0x73, 0x00, 0xaa},
+       {0x00, 0x74, 0x0a, 0xaa},
+       {0x00, 0x75, 0x16, 0xaa},
+       {0x00, 0x76, 0x25, 0xaa},
+       {0x00, 0x77, 0x34, 0xaa},
+       {0x00, 0x78, 0x49, 0xaa},
+       {0x00, 0x79, 0x5a, 0xaa},
+       {0x00, 0x7a, 0x7f, 0xaa},
+       {0x00, 0x7b, 0x9b, 0xaa},
+       {0x00, 0x7c, 0xba, 0xaa},
+       {0x00, 0x7d, 0xd4, 0xaa},
+       {0x00, 0x7e, 0xea, 0xaa},
+
+       {0x00, 0xd6, 0x62, 0xaa},       /* gamma 1 */
+       {0x00, 0x73, 0x00, 0xaa},
+       {0x00, 0x74, 0x0a, 0xaa},
+       {0x00, 0x75, 0x16, 0xaa},
+       {0x00, 0x76, 0x25, 0xaa},
+       {0x00, 0x77, 0x34, 0xaa},
+       {0x00, 0x78, 0x49, 0xaa},
+       {0x00, 0x79, 0x5a, 0xaa},
+       {0x00, 0x7a, 0x7f, 0xaa},
+       {0x00, 0x7b, 0x9b, 0xaa},
+       {0x00, 0x7c, 0xba, 0xaa},
+       {0x00, 0x7d, 0xd4, 0xaa},
+       {0x00, 0x7e, 0xea, 0xaa},
+
+       {0x00, 0xd6, 0xa2, 0xaa},       /* gamma 2 */
+       {0x00, 0x73, 0x00, 0xaa},
+       {0x00, 0x74, 0x0a, 0xaa},
+       {0x00, 0x75, 0x16, 0xaa},
+       {0x00, 0x76, 0x25, 0xaa},
+       {0x00, 0x77, 0x34, 0xaa},
+       {0x00, 0x78, 0x49, 0xaa},
+       {0x00, 0x79, 0x5a, 0xaa},
+       {0x00, 0x7a, 0x7f, 0xaa},
+       {0x00, 0x7b, 0x9b, 0xaa},
+       {0x00, 0x7c, 0xba, 0xaa},
+       {0x00, 0x7d, 0xd4, 0xaa},
+       {0x00, 0x7e, 0xea, 0xaa},
+       {}
+};
+static const u8 poxxxx_init_start_3[][4] = {
+       {0x00, 0xb8, 0x28, 0xaa},
+       {0x00, 0xb9, 0x1e, 0xaa},
+       {0x00, 0xb6, 0x14, 0xaa},
+       {0x00, 0xb7, 0x0f, 0xaa},
+       {0x00, 0x5c, 0x10, 0xaa},
+       {0x00, 0x5d, 0x18, 0xaa},
+       {0x00, 0x5e, 0x24, 0xaa},
+       {0x00, 0x5f, 0x24, 0xaa},
+       {0x00, 0x86, 0x1a, 0xaa},
+       {0x00, 0x60, 0x00, 0xaa},
+       {0x00, 0x61, 0x1b, 0xaa},
+       {0x00, 0x62, 0x30, 0xaa},
+       {0x00, 0x63, 0x40, 0xaa},
+       {0x00, 0x87, 0x1a, 0xaa},
+       {0x00, 0x64, 0x00, 0xaa},
+       {0x00, 0x65, 0x08, 0xaa},
+       {0x00, 0x66, 0x10, 0xaa},
+       {0x00, 0x67, 0x20, 0xaa},
+       {0x00, 0x88, 0x10, 0xaa},
+       {0x00, 0x68, 0x00, 0xaa},
+       {0x00, 0x69, 0x08, 0xaa},
+       {0x00, 0x6a, 0x0f, 0xaa},
+       {0x00, 0x6b, 0x0f, 0xaa},
+       {0x00, 0x89, 0x07, 0xaa},
+       {0x00, 0xd5, 0x4c, 0xaa},
+       {0x00, 0x0a, 0x00, 0xaa},
+       {0x00, 0x0b, 0x2a, 0xaa},
+       {0x00, 0x0e, 0x03, 0xaa},
+       {0x00, 0x0f, 0xea, 0xaa},
+       {0x00, 0xa2, 0x00, 0xaa},
+       {0x00, 0xa3, 0x2a, 0xaa},
+       {0x00, 0xa4, 0x03, 0xaa},
+       {0x00, 0xa5, 0xea, 0xaa},
+       {}
+};
+static const u8 poxxxx_initVGA[][4] = {
+       {0x00, 0x20, 0x11, 0xaa},
+       {0x00, 0x33, 0x38, 0xaa},
+       {0x00, 0xbb, 0x0d, 0xaa},
+       {0xb3, 0x22, 0x01, 0xcc},       /* change to 640x480 */
+       {0xb3, 0x23, 0xe0, 0xcc},
+       {0xb3, 0x16, 0x02, 0xcc},
+       {0xb3, 0x17, 0x7f, 0xcc},
+       {0xb3, 0x02, 0xb0, 0xcc},
+       {0xb3, 0x06, 0x00, 0xcc},
+       {0xb3, 0x5c, 0x01, 0xcc},
+       {0x00, 0x04, 0x06, 0xaa},
+       {0x00, 0x05, 0x3f, 0xaa},
+       {0x00, 0x04, 0x00, 0xdd},       /* delay 1s */
+       {}
+};
+static const u8 poxxxx_initQVGA[][4] = {
+       {0x00, 0x20, 0x33, 0xaa},
+       {0x00, 0x33, 0x38, 0xaa},
+       {0x00, 0xbb, 0x0d, 0xaa},
+       {0xb3, 0x22, 0x00, 0xcc},       /* change to 320x240 */
+       {0xb3, 0x23, 0xf0, 0xcc},
+       {0xb3, 0x16, 0x01, 0xcc},
+       {0xb3, 0x17, 0x3f, 0xcc},
+       {0xb3, 0x02, 0xb0, 0xcc},
+       {0xb3, 0x06, 0x01, 0xcc},
+       {0xb3, 0x5c, 0x00, 0xcc},
+       {0x00, 0x04, 0x06, 0xaa},
+       {0x00, 0x05, 0x3f, 0xaa},
+       {0x00, 0x04, 0x00, 0xdd},       /* delay 1s */
+       {}
+};
+static const u8 poxxxx_init_end_1[][4] = {
+       {0x00, 0x47, 0x25, 0xaa},
+       {0x00, 0x48, 0x80, 0xaa},
+       {0x00, 0x49, 0x1f, 0xaa},
+       {0x00, 0x4a, 0x40, 0xaa},
+       {0x00, 0x44, 0x40, 0xaa},
+       {0x00, 0xab, 0x4a, 0xaa},
+       {0x00, 0xb1, 0x00, 0xaa},
+       {0x00, 0xb2, 0x04, 0xaa},
+       {0x00, 0xb3, 0x08, 0xaa},
+       {0x00, 0xb4, 0x0b, 0xaa},
+       {0x00, 0xb5, 0x0d, 0xaa},
+       {}
+};
+static const u8 poxxxx_init_end_2[][4] = {
+       {0x00, 0x1d, 0x85, 0xaa},
+       {0x00, 0x1e, 0x06, 0xaa},
+       {0x00, 0x1d, 0x05, 0xaa},
+       {}
+};
+
+struct sensor_info {
+       s8 sensorId;
+       u8 I2cAdd;
+       u8 IdAdd;
+       u16 VpId;
+       u8 m1;
+       u8 m2;
+       u8 op;
+};
+
+/* probe values */
+static const struct sensor_info vc0321_probe_data[] = {
+/*      sensorId,         I2cAdd,      IdAdd,  VpId,  m1,    m2,  op */
+/* 0 OV9640 */
+       {-1,                0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
+/* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */
+       {-1,                0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01},
+/* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/
+       {-1,                0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01},
+/* 3 MI1310 */
+       {-1,                0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01},
+/* 4 MI360 - tested in vc032x_probe_sensor */
+/*     {SENSOR_MI0360,     0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */
+/* 5 7131R */
+       {SENSOR_HV7131R,    0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
+/* 6 OV7649 */
+       {-1,                0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05},
+/* 7 PAS302BCW */
+       {-1,                0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05},
+/* 8 OV7660 */
+       {SENSOR_OV7660,     0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05},
+/* 9 PO3130NC - (tested in vc032x_probe_sensor) */
+/*     {SENSOR_PO3130NC,   0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */
+/* 10 PO1030KC */
+       {-1,                0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
+/* 11 MI1310_SOC */
+       {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01},
+/* 12 OV9650 */
+       {-1,                0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
+/* 13 S5K532 */
+       {-1,                0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01},
+/* 14 MI360_SOC - ??? */
+/* 15 PO1200N */
+       {SENSOR_PO1200,     0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01},
+/* 16 PO3030K */
+       {-1,                0x80 | 0x18, 0x00, 0x0000, 0x24, 0x25, 0x01},
+/* 17 PO2030 */
+       {-1,                0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
+/* ?? */
+       {-1,                0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01},
+       {SENSOR_MI1320,     0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01},
+};
+static const struct sensor_info vc0323_probe_data[] = {
+/*      sensorId,         I2cAdd,      IdAdd,  VpId,  m1,    m2,  op */
+/* 0 OV9640 */
+       {-1,                0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
+/* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */
+       {-1,                0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01},
+/* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/
+       {-1,                0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01},
+/* 3 MI1310 */
+       {-1,                0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01},
+/* 4 MI360 - tested in vc032x_probe_sensor */
+/*     {SENSOR_MI0360,     0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */
+/* 5 7131R */
+       {SENSOR_HV7131R,    0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
+/* 6 OV7649 */
+       {-1,                0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05},
+/* 7 PAS302BCW */
+       {-1,                0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05},
+/* 8 OV7660 */
+       {SENSOR_OV7660,     0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05},
+/* 9 PO3130NC - (tested in vc032x_probe_sensor) */
+/*     {SENSOR_PO3130NC,   0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */
+/* 10 PO1030KC */
+       {-1,                0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
+/* 11 MI1310_SOC */
+       {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01},
+/* 12 OV9650 */
+       {-1,                0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
+/* 13 S5K532 */
+       {-1,                0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01},
+/* 14 MI360_SOC - ??? */
+/* 15 PO1200N */
+       {SENSOR_PO1200,     0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01},
+/* 16 ?? */
+       {-1,                0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01},
+/* 17 PO2030 */
+       {-1,                0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
+/* ?? */
+       {-1,                0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01},
+       {SENSOR_MI1320_SOC, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x67, 0x01},
+/*fixme: not in the ms-win probe - may be found before? */
+       {SENSOR_OV7670,     0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05},
+};
+
+/* read 'len' bytes in gspca_dev->usb_buf */
+static void reg_r_i(struct gspca_dev *gspca_dev,
+                 u16 req,
+                 u16 index,
+                 u16 len)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       req,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       1,                      /* value */
+                       index, gspca_dev->usb_buf, len,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_r err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+static void reg_r(struct gspca_dev *gspca_dev,
+                 u16 req,
+                 u16 index,
+                 u16 len)
+{
+       reg_r_i(gspca_dev, req, index, len);
+#ifdef GSPCA_DEBUG
+       if (gspca_dev->usb_err < 0)
+               return;
+       if (len == 1)
+               PDEBUG(D_USBI, "GET %02x 0001 %04x %02x", req, index,
+                               gspca_dev->usb_buf[0]);
+       else
+               PDEBUG(D_USBI, "GET %02x 0001 %04x %*ph",
+                               req, index, 3, gspca_dev->usb_buf);
+#endif
+}
+
+static void reg_w_i(struct gspca_dev *gspca_dev,
+                           u16 req,
+                           u16 value,
+                           u16 index)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       req,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index, NULL, 0,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_w err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+static void reg_w(struct gspca_dev *gspca_dev,
+                           u16 req,
+                           u16 value,
+                           u16 index)
+{
+#ifdef GSPCA_DEBUG
+       if (gspca_dev->usb_err < 0)
+               return;
+       PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
+#endif
+       reg_w_i(gspca_dev, req, value, index);
+}
+
+static u16 read_sensor_register(struct gspca_dev *gspca_dev,
+                               u16 address)
+{
+       u8 ldata, mdata, hdata;
+       int retry = 50;
+
+       reg_r(gspca_dev, 0xa1, 0xb33f, 1);
+       if (!(gspca_dev->usb_buf[0] & 0x02)) {
+               pr_err("I2c Bus Busy Wait %02x\n", gspca_dev->usb_buf[0]);
+               return 0;
+       }
+       reg_w(gspca_dev, 0xa0, address, 0xb33a);
+       reg_w(gspca_dev, 0xa0, 0x02, 0xb339);
+
+       do {
+               reg_r(gspca_dev, 0xa1, 0xb33b, 1);
+               if (gspca_dev->usb_buf[0] == 0x00)
+                       break;
+               msleep(40);
+       } while (--retry >= 0);
+
+       reg_r(gspca_dev, 0xa1, 0xb33e, 1);
+       ldata = gspca_dev->usb_buf[0];
+       reg_r(gspca_dev, 0xa1, 0xb33d, 1);
+       mdata = gspca_dev->usb_buf[0];
+       reg_r(gspca_dev, 0xa1, 0xb33c, 1);
+       hdata = gspca_dev->usb_buf[0];
+       if (hdata != 0 && mdata != 0 && ldata != 0)
+               PDEBUG(D_PROBE, "Read Sensor %02x%02x %02x",
+                       hdata, mdata, ldata);
+       reg_r(gspca_dev, 0xa1, 0xb334, 1);
+       if (gspca_dev->usb_buf[0] == 0x02)
+               return (hdata << 8) + mdata;
+       return hdata;
+}
+
+static int vc032x_probe_sensor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i, n;
+       u16 value;
+       const struct sensor_info *ptsensor_info;
+
+/*fixme: should also check the other sensor (back mi1320_soc, front mc501cb)*/
+       if (sd->flags & FL_SAMSUNG) {
+               reg_w(gspca_dev, 0xa0, 0x01, 0xb301);
+               reg_w(gspca_dev, 0x89, 0xf0ff, 0xffff);
+                                               /* select the back sensor */
+       }
+
+       reg_r(gspca_dev, 0xa1, 0xbfcf, 1);
+       PDEBUG(D_PROBE, "vc032%d check sensor header %02x",
+               sd->bridge == BRIDGE_VC0321 ? 1 : 3, gspca_dev->usb_buf[0]);
+       if (sd->bridge == BRIDGE_VC0321) {
+               ptsensor_info = vc0321_probe_data;
+               n = ARRAY_SIZE(vc0321_probe_data);
+       } else {
+               ptsensor_info = vc0323_probe_data;
+               n = ARRAY_SIZE(vc0323_probe_data);
+       }
+       for (i = 0; i < n; i++) {
+               reg_w(gspca_dev, 0xa0, 0x02, 0xb334);
+               reg_w(gspca_dev, 0xa0, ptsensor_info->m1, 0xb300);
+               reg_w(gspca_dev, 0xa0, ptsensor_info->m2, 0xb300);
+               reg_w(gspca_dev, 0xa0, 0x01, 0xb308);
+               reg_w(gspca_dev, 0xa0, 0x0c, 0xb309);
+               reg_w(gspca_dev, 0xa0, ptsensor_info->I2cAdd, 0xb335);
+               reg_w(gspca_dev, 0xa0, ptsensor_info->op, 0xb301);
+               value = read_sensor_register(gspca_dev, ptsensor_info->IdAdd);
+               if (value == 0 && ptsensor_info->IdAdd == 0x82)
+                       value = read_sensor_register(gspca_dev, 0x83);
+               if (value != 0) {
+                       PDEBUG(D_ERR|D_PROBE, "Sensor ID %04x (%d)",
+                               value, i);
+                       if (value == ptsensor_info->VpId)
+                               return ptsensor_info->sensorId;
+
+                       switch (value) {
+                       case 0x3130:
+                               return SENSOR_PO3130NC;
+                       case 0x7673:
+                               return SENSOR_OV7670;
+                       case 0x8243:
+                               return SENSOR_MI0360;
+                       }
+               }
+               ptsensor_info++;
+       }
+       return -1;
+}
+
+static void i2c_write(struct gspca_dev *gspca_dev,
+                       u8 reg, const u8 *val,
+                       u8 size)                /* 1 or 2 */
+{
+       int retry;
+
+#ifdef GSPCA_DEBUG
+       if (gspca_dev->usb_err < 0)
+               return;
+       if (size == 1)
+               PDEBUG(D_USBO, "i2c_w %02x %02x", reg, *val);
+       else
+               PDEBUG(D_USBO, "i2c_w %02x %02x%02x", reg, *val, val[1]);
+#endif
+       reg_r_i(gspca_dev, 0xa1, 0xb33f, 1);
+/*fixme:should check if (!(gspca_dev->usb_buf[0] & 0x02)) error*/
+       reg_w_i(gspca_dev, 0xa0, size, 0xb334);
+       reg_w_i(gspca_dev, 0xa0, reg, 0xb33a);
+       reg_w_i(gspca_dev, 0xa0, val[0], 0xb336);
+       if (size > 1)
+               reg_w_i(gspca_dev, 0xa0, val[1], 0xb337);
+       reg_w_i(gspca_dev, 0xa0, 0x01, 0xb339);
+       retry = 4;
+       do {
+               reg_r_i(gspca_dev, 0xa1, 0xb33b, 1);
+               if (gspca_dev->usb_buf[0] == 0)
+                       break;
+               msleep(20);
+       } while (--retry > 0);
+       if (retry <= 0)
+               pr_err("i2c_write timeout\n");
+}
+
+static void put_tab_to_reg(struct gspca_dev *gspca_dev,
+                       const u8 *tab, u8 tabsize, u16 addr)
+{
+       int j;
+       u16 ad = addr;
+
+       for (j = 0; j < tabsize; j++)
+               reg_w(gspca_dev, 0xa0, tab[j], ad++);
+}
+
+static void usb_exchange(struct gspca_dev *gspca_dev,
+                       const u8 data[][4])
+{
+       int i = 0;
+
+       for (;;) {
+               switch (data[i][3]) {
+               default:
+                       return;
+               case 0xcc:                      /* normal write */
+                       reg_w(gspca_dev, 0xa0, data[i][2],
+                                       (data[i][0]) << 8 | data[i][1]);
+                       break;
+               case 0xaa:                      /* i2c op */
+                       i2c_write(gspca_dev, data[i][1], &data[i][2], 1);
+                       break;
+               case 0xbb:                      /* i2c op */
+                       i2c_write(gspca_dev, data[i][0], &data[i][1], 2);
+                       break;
+               case 0xdd:
+                       msleep(data[i][1] * 256 + data[i][2] + 10);
+                       break;
+               }
+               i++;
+       }
+       /*not reached*/
+}
+
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       sd->bridge = id->driver_info >> 8;
+       sd->flags = id->driver_info & 0xff;
+
+       if (id->idVendor == 0x046d &&
+           (id->idProduct == 0x0892 || id->idProduct == 0x0896))
+               sd->sensor = SENSOR_POxxxx;     /* no probe */
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+       int sensor;
+       /* number of packets per ISOC message */
+       static u8 npkt[NSENSORS] = {
+               [SENSOR_HV7131R] =      64,
+               [SENSOR_MI0360] =       32,
+               [SENSOR_MI1310_SOC] =   32,
+               [SENSOR_MI1320] =       64,
+               [SENSOR_MI1320_SOC] =   128,
+               [SENSOR_OV7660] =       32,
+               [SENSOR_OV7670] =       64,
+               [SENSOR_PO1200] =       128,
+               [SENSOR_PO3130NC] =     128,
+               [SENSOR_POxxxx] =       128,
+       };
+
+       if (sd->sensor != SENSOR_POxxxx)
+               sensor = vc032x_probe_sensor(gspca_dev);
+       else
+               sensor = sd->sensor;
+
+       switch (sensor) {
+       case -1:
+               pr_err("Unknown sensor...\n");
+               return -EINVAL;
+       case SENSOR_HV7131R:
+               PDEBUG(D_PROBE, "Find Sensor HV7131R");
+               break;
+       case SENSOR_MI0360:
+               PDEBUG(D_PROBE, "Find Sensor MI0360");
+               sd->bridge = BRIDGE_VC0323;
+               break;
+       case SENSOR_MI1310_SOC:
+               PDEBUG(D_PROBE, "Find Sensor MI1310_SOC");
+               break;
+       case SENSOR_MI1320:
+               PDEBUG(D_PROBE, "Find Sensor MI1320");
+               break;
+       case SENSOR_MI1320_SOC:
+               PDEBUG(D_PROBE, "Find Sensor MI1320_SOC");
+               break;
+       case SENSOR_OV7660:
+               PDEBUG(D_PROBE, "Find Sensor OV7660");
+               break;
+       case SENSOR_OV7670:
+               PDEBUG(D_PROBE, "Find Sensor OV7670");
+               break;
+       case SENSOR_PO1200:
+               PDEBUG(D_PROBE, "Find Sensor PO1200");
+               break;
+       case SENSOR_PO3130NC:
+               PDEBUG(D_PROBE, "Find Sensor PO3130NC");
+               break;
+       case SENSOR_POxxxx:
+               PDEBUG(D_PROBE, "Sensor POxxxx");
+               break;
+       }
+       sd->sensor = sensor;
+
+       cam = &gspca_dev->cam;
+       if (sd->bridge == BRIDGE_VC0321) {
+               cam->cam_mode = vc0321_mode;
+               cam->nmodes = ARRAY_SIZE(vc0321_mode);
+       } else {
+               switch (sensor) {
+               case SENSOR_PO1200:
+                       cam->cam_mode = svga_mode;
+                       cam->nmodes = ARRAY_SIZE(svga_mode);
+                       break;
+               case SENSOR_MI1310_SOC:
+                       cam->cam_mode = vc0323_mode;
+                       cam->nmodes = ARRAY_SIZE(vc0323_mode);
+                       break;
+               case SENSOR_MI1320_SOC:
+                       cam->cam_mode = bi_mode;
+                       cam->nmodes = ARRAY_SIZE(bi_mode);
+                       break;
+               case SENSOR_OV7670:
+                       cam->cam_mode = bi_mode;
+                       cam->nmodes = ARRAY_SIZE(bi_mode) - 1;
+                       break;
+               default:
+                       cam->cam_mode = vc0323_mode;
+                       cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1;
+                       break;
+               }
+       }
+       cam->npkt = npkt[sd->sensor];
+
+       if (sd->sensor == SENSOR_OV7670)
+               sd->flags |= FL_HFLIP | FL_VFLIP;
+
+       if (sd->bridge == BRIDGE_VC0321) {
+               reg_r(gspca_dev, 0x8a, 0, 3);
+               reg_w(gspca_dev, 0x87, 0x00, 0x0f0f);
+               reg_r(gspca_dev, 0x8b, 0, 3);
+               reg_w(gspca_dev, 0x88, 0x00, 0x0202);
+               if (sd->sensor == SENSOR_POxxxx) {
+                       reg_r(gspca_dev, 0xa1, 0xb300, 1);
+                       if (gspca_dev->usb_buf[0] != 0) {
+                               reg_w(gspca_dev, 0xa0, 0x26, 0xb300);
+                               reg_w(gspca_dev, 0xa0, 0x04, 0xb300);
+                       }
+                       reg_w(gspca_dev, 0xa0, 0x00, 0xb300);
+               }
+       }
+       return gspca_dev->usb_err;
+}
+
+static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       u8 data;
+
+       data = val;
+       if (data >= 0x80)
+               data &= 0x7f;
+       else
+               data = 0xff ^ data;
+       i2c_write(gspca_dev, 0x98, &data, 1);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev, u8 val)
+{
+       i2c_write(gspca_dev, 0x99, &val, 1);
+}
+
+static void setcolors(struct gspca_dev *gspca_dev, u8 val)
+{
+       u8 data;
+
+       data = val - (val >> 3) - 1;
+       i2c_write(gspca_dev, 0x94, &data, 1);
+       i2c_write(gspca_dev, 0x95, &val, 1);
+}
+
+static void sethvflip(struct gspca_dev *gspca_dev, bool hflip, bool vflip)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 data[2];
+
+       if (sd->flags & FL_HFLIP)
+               hflip = !hflip;
+       if (sd->flags & FL_VFLIP)
+               vflip = !vflip;
+       switch (sd->sensor) {
+       case SENSOR_MI1310_SOC:
+       case SENSOR_MI1320:
+       case SENSOR_MI1320_SOC:
+               data[0] = data[1] = 0;          /* select page 0 */
+               i2c_write(gspca_dev, 0xf0, data, 2);
+               data[0] = sd->sensor == SENSOR_MI1310_SOC ? 0x03 : 0x01;
+               data[1] = 0x02 * hflip
+                       | 0x01 * vflip;
+               i2c_write(gspca_dev, 0x20, data, 2);
+               break;
+       case SENSOR_OV7660:
+       case SENSOR_OV7670:
+               data[0] = sd->sensor == SENSOR_OV7660 ? 0x01 : 0x07;
+               data[0] |= OV7660_MVFP_MIRROR * hflip
+                       | OV7660_MVFP_VFLIP * vflip;
+               i2c_write(gspca_dev, OV7660_REG_MVFP, data, 1);
+               break;
+       case SENSOR_PO1200:
+               data[0] = 0;
+               i2c_write(gspca_dev, 0x03, data, 1);
+               data[0] = 0x80 * hflip
+                       | 0x40 * vflip
+                       | 0x06;
+               i2c_write(gspca_dev, 0x1e, data, 1);
+               break;
+       }
+}
+
+static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       static const u8 (*ov7660_freq_tb[3])[4] =
+               {ov7660_NoFliker, ov7660_50HZ, ov7660_60HZ};
+
+       if (sd->sensor != SENSOR_OV7660)
+               return;
+       usb_exchange(gspca_dev, ov7660_freq_tb[val]);
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 data;
+
+       switch (sd->sensor) {
+       case SENSOR_PO1200:
+               data = 0;
+               i2c_write(gspca_dev, 0x03, &data, 1);
+               if (val < 0)
+                       data = 0x6a;
+               else
+                       data = 0xb5 + val * 3;
+               i2c_write(gspca_dev, 0x61, &data, 1);
+               break;
+       case SENSOR_POxxxx:
+               if (val < 0)
+                       data = 0x7e;    /* def = max */
+               else
+                       data = 0x60 + val * 0x0f;
+               i2c_write(gspca_dev, 0x59, &data, 1);
+               break;
+       }
+}
+static void setgain(struct gspca_dev *gspca_dev, u8 val)
+{
+       i2c_write(gspca_dev, 0x15, &val, 1);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev, s32 val)
+{
+       u8 data;
+
+       data = val >> 8;
+       i2c_write(gspca_dev, 0x1a, &data, 1);
+       data = val;
+       i2c_write(gspca_dev, 0x1b, &data, 1);
+}
+
+static void setautogain(struct gspca_dev *gspca_dev, s32 val)
+{
+       static const u8 data[2] = {0x28, 0x3c};
+
+       i2c_write(gspca_dev, 0xd1, &data[val], 1);
+}
+
+static void setgamma(struct gspca_dev *gspca_dev)
+{
+/*fixme:to do */
+       usb_exchange(gspca_dev, poxxxx_gamma);
+}
+
+static void setbacklight(struct gspca_dev *gspca_dev, s32 val)
+{
+       u16 v;
+       u8 data;
+
+       data = (val << 4) | 0x0f;
+       i2c_write(gspca_dev, 0xaa, &data, 1);
+       v = 613 + 12 * val;
+       data = v >> 8;
+       i2c_write(gspca_dev, 0xc4, &data, 1);
+       data = v;
+       i2c_write(gspca_dev, 0xc5, &data, 1);
+       v = 1093 - 12 * val;
+       data = v >> 8;
+       i2c_write(gspca_dev, 0xc6, &data, 1);
+       data = v;
+       i2c_write(gspca_dev, 0xc7, &data, 1);
+       v = 342 + 9 * val;
+       data = v >> 8;
+       i2c_write(gspca_dev, 0xc8, &data, 1);
+       data = v;
+       i2c_write(gspca_dev, 0xc9, &data, 1);
+       v = 702 - 9 * val;
+       data = v >> 8;
+       i2c_write(gspca_dev, 0xca, &data, 1);
+       data = v;
+       i2c_write(gspca_dev, 0xcb, &data, 1);
+}
+
+static void setwb(struct gspca_dev *gspca_dev)
+{
+/*fixme:to do - valid when reg d1 = 0x1c - (reg16 + reg15 = 0xa3)*/
+       static const u8 data[2] = {0x00, 0x00};
+
+       i2c_write(gspca_dev, 0x16, &data[0], 1);
+       i2c_write(gspca_dev, 0x18, &data[1], 1);
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       const u8 (*init)[4];
+       const u8 *GammaT = NULL;
+       const u8 *MatrixT = NULL;
+       int mode;
+       static const u8 (*mi1320_soc_init[])[4] = {
+               mi1320_soc_InitSXGA,
+               mi1320_soc_InitVGA,
+               mi1320_soc_InitQVGA,
+       };
+
+/*fixme: back sensor only*/
+       if (sd->flags & FL_SAMSUNG) {
+               reg_w(gspca_dev, 0x89, 0xf0ff, 0xffff);
+               reg_w(gspca_dev, 0xa9, 0x8348, 0x000e);
+               reg_w(gspca_dev, 0xa9, 0x0000, 0x001a);
+       }
+
+       /* Assume start use the good resolution from gspca_dev->mode */
+       if (sd->bridge == BRIDGE_VC0321) {
+               reg_w(gspca_dev, 0xa0, 0xff, 0xbfec);
+               reg_w(gspca_dev, 0xa0, 0xff, 0xbfed);
+               reg_w(gspca_dev, 0xa0, 0xff, 0xbfee);
+               reg_w(gspca_dev, 0xa0, 0xff, 0xbfef);
+               sd->image_offset = 46;
+       } else {
+               if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].pixelformat
+                               == V4L2_PIX_FMT_JPEG)
+                       sd->image_offset = 0;
+               else
+                       sd->image_offset = 32;
+       }
+
+       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
+       switch (sd->sensor) {
+       case SENSOR_HV7131R:
+               GammaT = hv7131r_gamma;
+               MatrixT = hv7131r_matrix;
+               if (mode)
+                       init = hv7131r_initQVGA_data;   /* 320x240 */
+               else
+                       init = hv7131r_initVGA_data;    /* 640x480 */
+               break;
+       case SENSOR_OV7660:
+               GammaT = ov7660_gamma;
+               MatrixT = ov7660_matrix;
+               if (mode)
+                       init = ov7660_initQVGA_data;    /* 320x240 */
+               else
+                       init = ov7660_initVGA_data;     /* 640x480 */
+               break;
+       case SENSOR_MI0360:
+               GammaT = mi1320_gamma;
+               MatrixT = mi0360_matrix;
+               if (mode)
+                       init = mi0360_initQVGA_JPG;     /* 320x240 */
+               else
+                       init = mi0360_initVGA_JPG;      /* 640x480 */
+               break;
+       case SENSOR_MI1310_SOC:
+               GammaT = mi1320_gamma;
+               MatrixT = mi1320_matrix;
+               switch (mode) {
+               case 1:
+                       init = mi1310_socinitQVGA_JPG;  /* 320x240 */
+                       break;
+               case 0:
+                       init = mi1310_socinitVGA_JPG;   /* 640x480 */
+                       break;
+               default:
+                       init = mi1310_soc_InitSXGA_JPG; /* 1280x1024 */
+                       break;
+               }
+               break;
+       case SENSOR_MI1320:
+               GammaT = mi1320_gamma;
+               MatrixT = mi1320_matrix;
+               if (mode)
+                       init = mi1320_initQVGA_data;    /* 320x240 */
+               else
+                       init = mi1320_initVGA_data;     /* 640x480 */
+               break;
+       case SENSOR_MI1320_SOC:
+               GammaT = mi1320_gamma;
+               MatrixT = mi1320_matrix;
+               init = mi1320_soc_init[mode];
+               break;
+       case SENSOR_OV7670:
+               init = mode == 1 ? ov7670_InitVGA : ov7670_InitQVGA;
+               break;
+       case SENSOR_PO3130NC:
+               GammaT = po3130_gamma;
+               MatrixT = po3130_matrix;
+               if (mode)
+                       init = po3130_initQVGA_data;    /* 320x240 */
+               else
+                       init = po3130_initVGA_data;     /* 640x480 */
+               usb_exchange(gspca_dev, init);
+               init = po3130_rundata;
+               break;
+       case SENSOR_PO1200:
+               GammaT = po1200_gamma;
+               MatrixT = po1200_matrix;
+               init = po1200_initVGA_data;
+               break;
+       default:
+/*     case SENSOR_POxxxx: */
+               usb_exchange(gspca_dev, poxxxx_init_common);
+               setgamma(gspca_dev);
+               usb_exchange(gspca_dev, poxxxx_init_start_3);
+               if (mode)
+                       init = poxxxx_initQVGA;
+               else
+                       init = poxxxx_initVGA;
+               usb_exchange(gspca_dev, init);
+               reg_r(gspca_dev, 0x8c, 0x0000, 3);
+               reg_w(gspca_dev, 0xa0,
+                               gspca_dev->usb_buf[2] & 1 ? 0 : 1,
+                               0xb35c);
+               msleep(300);
+/*fixme: i2c read 04 and 05*/
+               init = poxxxx_init_end_1;
+               break;
+       }
+       usb_exchange(gspca_dev, init);
+       if (GammaT && MatrixT) {
+               put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a);
+               put_tab_to_reg(gspca_dev, GammaT, 17, 0xb85b);
+               put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c);
+               put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c);
+
+               switch (sd->sensor) {
+               case SENSOR_PO1200:
+               case SENSOR_HV7131R:
+                       reg_w(gspca_dev, 0x89, 0x0400, 0x1415);
+                       break;
+               case SENSOR_MI1310_SOC:
+                       reg_w(gspca_dev, 0x89, 0x058c, 0x0000);
+                       break;
+               }
+               msleep(100);
+       }
+       switch (sd->sensor) {
+       case SENSOR_OV7670:
+               reg_w(gspca_dev, 0x87, 0xffff, 0xffff);
+               reg_w(gspca_dev, 0x88, 0xff00, 0xf0f1);
+               reg_w(gspca_dev, 0xa0, 0x0000, 0xbfff);
+               break;
+       case SENSOR_POxxxx:
+               usb_exchange(gspca_dev, poxxxx_init_end_2);
+               setwb(gspca_dev);
+               msleep(80);             /* led on */
+               reg_w(gspca_dev, 0x89, 0xffff, 0xfdff);
+               break;
+       }
+       return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->sensor) {
+       case SENSOR_MI1310_SOC:
+               reg_w(gspca_dev, 0x89, 0x058c, 0x00ff);
+               break;
+       case SENSOR_POxxxx:
+               return;
+       default:
+               if (!(sd->flags & FL_SAMSUNG))
+                       reg_w(gspca_dev, 0x89, 0xffff, 0xffff);
+               break;
+       }
+       reg_w(gspca_dev, 0xa0, 0x01, 0xb301);
+       reg_w(gspca_dev, 0xa0, 0x09, 0xb003);
+}
+
+/* called on streamoff with alt 0 and on disconnect */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (!gspca_dev->present)
+               return;
+/*fixme: is this useful?*/
+       if (sd->sensor == SENSOR_MI1310_SOC)
+               reg_w(gspca_dev, 0x89, 0x058c, 0x00ff);
+       else if (!(sd->flags & FL_SAMSUNG))
+               reg_w(gspca_dev, 0x89, 0xffff, 0xffff);
+
+       if (sd->sensor == SENSOR_POxxxx) {
+               reg_w(gspca_dev, 0xa0, 0x26, 0xb300);
+               reg_w(gspca_dev, 0xa0, 0x04, 0xb300);
+               reg_w(gspca_dev, 0xa0, 0x00, 0xb300);
+       }
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,                       /* isoc packet */
+                       int len)                        /* iso pkt length */
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (data[0] == 0xff && data[1] == 0xd8) {
+               PDEBUG(D_PACK,
+                       "vc032x header packet found len %d", len);
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+               data += sd->image_offset;
+               len -= sd->image_offset;
+               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
+               return;
+       }
+
+       /* The vc0321 sends some additional data after sending the complete
+        * frame, we ignore this. */
+       if (sd->bridge == BRIDGE_VC0321) {
+               int size, l;
+
+               l = gspca_dev->image_len;
+               size = gspca_dev->frsz;
+               if (len > size - l)
+                       len = size - l;
+       }
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+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 && ctrl->id != V4L2_CID_POWER_LINE_FREQUENCY)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               setbrightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               setcontrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               setcolors(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_HFLIP:
+               sethvflip(gspca_dev, sd->hflip->val, sd->vflip->val);
+               break;
+       case V4L2_CID_SHARPNESS:
+               setsharpness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               setautogain(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_GAIN:
+               setgain(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_EXPOSURE:
+               setexposure(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_BACKLIGHT_COMPENSATION:
+               setbacklight(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_POWER_LINE_FREQUENCY:
+               setlightfreq(gspca_dev, ctrl->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;
+       bool has_brightness = false;
+       bool has_contrast = false;
+       bool has_sat = false;
+       bool has_hvflip = false;
+       bool has_freq = false;
+       bool has_backlight = false;
+       bool has_exposure = false;
+       bool has_autogain = false;
+       bool has_gain = false;
+       bool has_sharpness = false;
+
+       switch (sd->sensor) {
+       case SENSOR_HV7131R:
+       case SENSOR_MI0360:
+       case SENSOR_PO3130NC:
+               break;
+       case SENSOR_MI1310_SOC:
+       case SENSOR_MI1320:
+       case SENSOR_MI1320_SOC:
+       case SENSOR_OV7660:
+               has_hvflip = true;
+               break;
+       case SENSOR_OV7670:
+               has_hvflip = has_freq = true;
+               break;
+       case SENSOR_PO1200:
+               has_hvflip = has_sharpness = true;
+               break;
+       case SENSOR_POxxxx:
+               has_brightness = has_contrast = has_sat = has_backlight =
+                       has_exposure = has_autogain = has_gain =
+                       has_sharpness = true;
+               break;
+       }
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 8);
+       if (has_brightness)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+       if (has_contrast)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 255, 1, 127);
+       if (has_sat)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SATURATION, 1, 127, 1, 63);
+       if (has_hvflip) {
+               sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+               sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_VFLIP, 0, 1, 1, 0);
+       }
+       if (has_sharpness)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SHARPNESS, -1, 2, 1, -1);
+       if (has_freq)
+               v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
+                       V4L2_CID_POWER_LINE_FREQUENCY,
+                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
+                       V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
+       if (has_autogain)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+       if (has_gain)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_GAIN, 0, 78, 1, 0);
+       if (has_exposure)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0, 4095, 1, 450);
+       if (has_backlight)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BACKLIGHT_COMPENSATION, 0, 15, 1, 15);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       if (sd->hflip)
+               v4l2_ctrl_cluster(2, &sd->hflip);
+       return 0;
+}
+
+/* sub-driver description */
+static const struct sd_desc sd_desc = {
+       .name = MODULE_NAME,
+       .init_controls = sd_init_controls,
+       .config = sd_config,
+       .init = sd_init,
+       .start = sd_start,
+       .stopN = sd_stopN,
+       .stop0 = sd_stop0,
+       .pkt_scan = sd_pkt_scan,
+};
+
+/* -- module initialisation -- */
+#define BF(bridge, flags) \
+       .driver_info = (BRIDGE_ ## bridge << 8) \
+               | (flags)
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x041e, 0x405b), BF(VC0323, FL_VFLIP)},
+       {USB_DEVICE(0x046d, 0x0892), BF(VC0321, 0)},
+       {USB_DEVICE(0x046d, 0x0896), BF(VC0321, 0)},
+       {USB_DEVICE(0x046d, 0x0897), BF(VC0321, 0)},
+       {USB_DEVICE(0x0ac8, 0x0321), BF(VC0321, 0)},
+       {USB_DEVICE(0x0ac8, 0x0323), BF(VC0323, 0)},
+       {USB_DEVICE(0x0ac8, 0x0328), BF(VC0321, 0)},
+       {USB_DEVICE(0x0ac8, 0xc001), BF(VC0321, 0)},
+       {USB_DEVICE(0x0ac8, 0xc002), BF(VC0321, 0)},
+       {USB_DEVICE(0x0ac8, 0xc301), BF(VC0323, FL_SAMSUNG)},
+       {USB_DEVICE(0x15b8, 0x6001), BF(VC0323, 0)},
+       {USB_DEVICE(0x15b8, 0x6002), BF(VC0323, 0)},
+       {USB_DEVICE(0x17ef, 0x4802), BF(VC0323, 0)},
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/vicam.c b/drivers/media/usb/gspca/vicam.c
new file mode 100644 (file)
index 0000000..b1a64b9
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * gspca ViCam subdriver
+ *
+ * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on the usbvideo vicam driver, which is:
+ *
+ * Copyright (c) 2002 Joe Burks (jburks@wavicle.org),
+ *                    Christopher L Cheney (ccheney@cheney.cx),
+ *                    Pavel Machek (pavel@ucw.cz),
+ *                    John Tyner (jtyner@cs.ucr.edu),
+ *                    Monroe Williams (monroe@pobox.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
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "vicam"
+#define HEADER_SIZE 64
+
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+#include <linux/ihex.h>
+#include "gspca.h"
+
+#define VICAM_FIRMWARE "vicam/firmware.fw"
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("GSPCA ViCam USB Camera Driver");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(VICAM_FIRMWARE);
+
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+       struct work_struct work_struct;
+       struct workqueue_struct *work_thread;
+};
+
+/* The vicam sensor has a resolution of 512 x 244, with I believe square
+   pixels, but this is forced to a 4:3 ratio by optics. So it has
+   non square pixels :( */
+static struct v4l2_pix_format vicam_mode[] = {
+       { 256, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
+               .bytesperline = 256,
+               .sizeimage = 256 * 122,
+               .colorspace = V4L2_COLORSPACE_SRGB,},
+       /* 2 modes with somewhat more square pixels */
+       { 256, 200, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
+               .bytesperline = 256,
+               .sizeimage = 256 * 200,
+               .colorspace = V4L2_COLORSPACE_SRGB,},
+       { 256, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
+               .bytesperline = 256,
+               .sizeimage = 256 * 240,
+               .colorspace = V4L2_COLORSPACE_SRGB,},
+#if 0   /* This mode has extremely non square pixels, testing use only */
+       { 512, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
+               .bytesperline = 512,
+               .sizeimage = 512 * 122,
+               .colorspace = V4L2_COLORSPACE_SRGB,},
+#endif
+       { 512, 244, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
+               .bytesperline = 512,
+               .sizeimage = 512 * 244,
+               .colorspace = V4L2_COLORSPACE_SRGB,},
+};
+
+static int vicam_control_msg(struct gspca_dev *gspca_dev, u8 request,
+       u16 value, u16 index, u8 *data, u16 len)
+{
+       int ret;
+
+       ret = usb_control_msg(gspca_dev->dev,
+                             usb_sndctrlpipe(gspca_dev->dev, 0),
+                             request,
+                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             value, index, data, len, 1000);
+       if (ret < 0)
+               pr_err("control msg req %02X error %d\n", request, ret);
+
+       return ret;
+}
+
+static int vicam_set_camera_power(struct gspca_dev *gspca_dev, int state)
+{
+       int ret;
+
+       ret = vicam_control_msg(gspca_dev, 0x50, state, 0, NULL, 0);
+       if (ret < 0)
+               return ret;
+
+       if (state)
+               ret = vicam_control_msg(gspca_dev, 0x55, 1, 0, NULL, 0);
+
+       return ret;
+}
+
+/*
+ *  request and read a block of data - see warning on vicam_command.
+ */
+static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size)
+{
+       int ret, unscaled_height, act_len = 0;
+       u8 *req_data = gspca_dev->usb_buf;
+       s32 expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
+       s32 gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
+
+       memset(req_data, 0, 16);
+       req_data[0] = gain;
+       if (gspca_dev->width == 256)
+               req_data[1] |= 0x01; /* low nibble x-scale */
+       if (gspca_dev->height <= 122) {
+               req_data[1] |= 0x10; /* high nibble y-scale */
+               unscaled_height = gspca_dev->height * 2;
+       } else
+               unscaled_height = gspca_dev->height;
+       req_data[2] = 0x90; /* unknown, does not seem to do anything */
+       if (unscaled_height <= 200)
+               req_data[3] = 0x06; /* vend? */
+       else if (unscaled_height <= 242) /* Yes 242 not 240 */
+               req_data[3] = 0x07; /* vend? */
+       else /* Up to 244 lines with req_data[3] == 0x08 */
+               req_data[3] = 0x08; /* vend? */
+
+       if (expo < 256) {
+               /* Frame rate maxed out, use partial frame expo time */
+               req_data[4] = 255 - expo;
+               req_data[5] = 0x00;
+               req_data[6] = 0x00;
+               req_data[7] = 0x01;
+       } else {
+               /* Modify frame rate */
+               req_data[4] = 0x00;
+               req_data[5] = 0x00;
+               req_data[6] = expo & 0xFF;
+               req_data[7] = expo >> 8;
+       }
+       req_data[8] = ((244 - unscaled_height) / 2) & ~0x01; /* vstart */
+       /* bytes 9-15 do not seem to affect exposure or image quality */
+
+       mutex_lock(&gspca_dev->usb_lock);
+       ret = vicam_control_msg(gspca_dev, 0x51, 0x80, 0, req_data, 16);
+       mutex_unlock(&gspca_dev->usb_lock);
+       if (ret < 0)
+               return ret;
+
+       ret = usb_bulk_msg(gspca_dev->dev,
+                          usb_rcvbulkpipe(gspca_dev->dev, 0x81),
+                          data, size, &act_len, 10000);
+       /* successful, it returns 0, otherwise  negative */
+       if (ret < 0 || act_len != size) {
+               pr_err("bulk read fail (%d) len %d/%d\n",
+                      ret, act_len, size);
+               return -EIO;
+       }
+       return 0;
+}
+
+/* This function is called as a workqueue function and runs whenever the camera
+ * is streaming data. Because it is a workqueue function it is allowed to sleep
+ * so we can use synchronous USB calls. To avoid possible collisions with other
+ * threads attempting to use the camera's USB interface we take the gspca
+ * usb_lock when performing USB operations. In practice the only thing we need
+ * to protect against is the usb_set_interface call that gspca makes during
+ * stream_off as the camera doesn't provide any controls that the user could try
+ * to change.
+ */
+static void vicam_dostream(struct work_struct *work)
+{
+       struct sd *sd = container_of(work, struct sd, work_struct);
+       struct gspca_dev *gspca_dev = &sd->gspca_dev;
+       int ret, frame_sz;
+       u8 *buffer;
+
+       frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage +
+                  HEADER_SIZE;
+       buffer = kmalloc(frame_sz, GFP_KERNEL | GFP_DMA);
+       if (!buffer) {
+               pr_err("Couldn't allocate USB buffer\n");
+               goto exit;
+       }
+
+       while (gspca_dev->dev && gspca_dev->streaming) {
+#ifdef CONFIG_PM
+               if (gspca_dev->frozen)
+                       break;
+#endif
+               ret = vicam_read_frame(gspca_dev, buffer, frame_sz);
+               if (ret < 0)
+                       break;
+
+               /* Note the frame header contents seem to be completely
+                  constant, they do not change with either image, or
+                  settings. So we simply discard it. The frames have
+                  a very similar 64 byte footer, which we don't even
+                  bother reading from the cam */
+               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                               buffer + HEADER_SIZE,
+                               frame_sz - HEADER_SIZE);
+               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+       }
+exit:
+       kfree(buffer);
+}
+
+/* This function is called at probe time just before sd_init */
+static int sd_config(struct gspca_dev *gspca_dev,
+               const struct usb_device_id *id)
+{
+       struct cam *cam = &gspca_dev->cam;
+       struct sd *sd = (struct sd *)gspca_dev;
+
+       /* We don't use the buffer gspca allocates so make it small. */
+       cam->bulk = 1;
+       cam->bulk_size = 64;
+       cam->cam_mode = vicam_mode;
+       cam->nmodes = ARRAY_SIZE(vicam_mode);
+
+       INIT_WORK(&sd->work_struct, vicam_dostream);
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       int ret;
+       const struct ihex_binrec *rec;
+       const struct firmware *uninitialized_var(fw);
+       u8 *firmware_buf;
+
+       ret = request_ihex_firmware(&fw, VICAM_FIRMWARE,
+                                   &gspca_dev->dev->dev);
+       if (ret) {
+               pr_err("Failed to load \"vicam/firmware.fw\": %d\n", ret);
+               return ret;
+       }
+
+       firmware_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!firmware_buf) {
+               ret = -ENOMEM;
+               goto exit;
+       }
+       for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) {
+               memcpy(firmware_buf, rec->data, be16_to_cpu(rec->len));
+               ret = vicam_control_msg(gspca_dev, 0xff, 0, 0, firmware_buf,
+                                       be16_to_cpu(rec->len));
+               if (ret < 0)
+                       break;
+       }
+
+       kfree(firmware_buf);
+exit:
+       release_firmware(fw);
+       return ret;
+}
+
+/* Set up for getting frames. */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *)gspca_dev;
+       int ret;
+
+       ret = vicam_set_camera_power(gspca_dev, 1);
+       if (ret < 0)
+               return ret;
+
+       /* Start the workqueue function to do the streaming */
+       sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
+       queue_work(sd->work_thread, &sd->work_struct);
+
+       return 0;
+}
+
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct sd *dev = (struct sd *)gspca_dev;
+
+       /* wait for the work queue to terminate */
+       mutex_unlock(&gspca_dev->usb_lock);
+       /* This waits for vicam_dostream to finish */
+       destroy_workqueue(dev->work_thread);
+       dev->work_thread = NULL;
+       mutex_lock(&gspca_dev->usb_lock);
+
+       if (gspca_dev->dev)
+               vicam_set_camera_power(gspca_dev, 0);
+}
+
+static int sd_init_controls(struct gspca_dev *gspca_dev)
+{
+       struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 2);
+       gspca_dev->exposure = v4l2_ctrl_new_std(hdl, NULL,
+                       V4L2_CID_EXPOSURE, 0, 2047, 1, 256);
+       gspca_dev->gain = v4l2_ctrl_new_std(hdl, NULL,
+                       V4L2_CID_GAIN, 0, 255, 1, 200);
+
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       return 0;
+}
+
+/* Table of supported USB devices */
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x04c1, 0x009d)},
+       {USB_DEVICE(0x0602, 0x1001)},
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* 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,
+       .stop0  = sd_stop0,
+};
+
+/* -- device connect -- */
+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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/w996Xcf.c b/drivers/media/usb/gspca/w996Xcf.c
new file mode 100644 (file)
index 0000000..9e3a909
--- /dev/null
@@ -0,0 +1,567 @@
+/**
+ *
+ * GSPCA sub driver for W996[78]CF JPEG USB Dual Mode Camera Chip.
+ *
+ * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This module is adapted from the in kernel v4l1 w9968cf driver:
+ *
+ * Copyright (C) 2002-2004 by Luca Risolia <luca.risolia@studio.unibo.it>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* Note this is not a stand alone driver, it gets included in ov519.c, this
+   is a bit of a hack, but it needs the driver code for a lot of different
+   ov sensors which is already present in ov519.c (the old v4l1 driver used
+   the ovchipcam framework). When we have the time we really should move
+   the sensor drivers to v4l2 sub drivers, and properly split of this
+   driver from ov519.c */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define W9968CF_I2C_BUS_DELAY    4 /* delay in us for I2C bit r/w operations */
+
+#define Y_QUANTABLE (&sd->jpeg_hdr[JPEG_QT0_OFFSET])
+#define UV_QUANTABLE (&sd->jpeg_hdr[JPEG_QT1_OFFSET])
+
+static const struct v4l2_pix_format w9968cf_vga_mode[] = {
+       {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
+               .bytesperline = 160 * 2,
+               .sizeimage = 160 * 120 * 2,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+       {176, 144, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
+               .bytesperline = 176 * 2,
+               .sizeimage = 176 * 144 * 2,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320 * 2,
+               .sizeimage = 320 * 240 * 2,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 352 * 2,
+               .sizeimage = 352 * 288 * 2,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640 * 2,
+               .sizeimage = 640 * 480 * 2,
+               .colorspace = V4L2_COLORSPACE_JPEG},
+};
+
+static void reg_w(struct sd *sd, u16 index, u16 value);
+
+/*--------------------------------------------------------------------------
+  Write 64-bit data to the fast serial bus registers.
+  Return 0 on success, -1 otherwise.
+  --------------------------------------------------------------------------*/
+static void w9968cf_write_fsb(struct sd *sd, u16* data)
+{
+       struct usb_device *udev = sd->gspca_dev.dev;
+       u16 value;
+       int ret;
+
+       if (sd->gspca_dev.usb_err < 0)
+               return;
+
+       value = *data++;
+       memcpy(sd->gspca_dev.usb_buf, data, 6);
+
+       ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0,
+                             USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+                             value, 0x06, sd->gspca_dev.usb_buf, 6, 500);
+       if (ret < 0) {
+               pr_err("Write FSB registers failed (%d)\n", ret);
+               sd->gspca_dev.usb_err = ret;
+       }
+}
+
+/*--------------------------------------------------------------------------
+  Write data to the serial bus control register.
+  Return 0 on success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static void w9968cf_write_sb(struct sd *sd, u16 value)
+{
+       int ret;
+
+       if (sd->gspca_dev.usb_err < 0)
+               return;
+
+       /* We don't use reg_w here, as that would cause all writes when
+          bitbanging i2c to be logged, making the logs impossible to read */
+       ret = usb_control_msg(sd->gspca_dev.dev,
+               usb_sndctrlpipe(sd->gspca_dev.dev, 0),
+               0,
+               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+               value, 0x01, NULL, 0, 500);
+
+       udelay(W9968CF_I2C_BUS_DELAY);
+
+       if (ret < 0) {
+               pr_err("Write SB reg [01] %04x failed\n", value);
+               sd->gspca_dev.usb_err = ret;
+       }
+}
+
+/*--------------------------------------------------------------------------
+  Read data from the serial bus control register.
+  Return 0 on success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static int w9968cf_read_sb(struct sd *sd)
+{
+       int ret;
+
+       if (sd->gspca_dev.usb_err < 0)
+               return -1;
+
+       /* We don't use reg_r here, as the w9968cf is special and has 16
+          bit registers instead of 8 bit */
+       ret = usb_control_msg(sd->gspca_dev.dev,
+                       usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
+                       1,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0, 0x01, sd->gspca_dev.usb_buf, 2, 500);
+       if (ret >= 0) {
+               ret = sd->gspca_dev.usb_buf[0] |
+                     (sd->gspca_dev.usb_buf[1] << 8);
+       } else {
+               pr_err("Read SB reg [01] failed\n");
+               sd->gspca_dev.usb_err = ret;
+       }
+
+       udelay(W9968CF_I2C_BUS_DELAY);
+
+       return ret;
+}
+
+/*--------------------------------------------------------------------------
+  Upload quantization tables for the JPEG compression.
+  This function is called by w9968cf_start_transfer().
+  Return 0 on success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static void w9968cf_upload_quantizationtables(struct sd *sd)
+{
+       u16 a, b;
+       int i, j;
+
+       reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */
+
+       for (i = 0, j = 0; i < 32; i++, j += 2) {
+               a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j + 1]) << 8);
+               b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j + 1]) << 8);
+               reg_w(sd, 0x40 + i, a);
+               reg_w(sd, 0x60 + i, b);
+       }
+       reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */
+}
+
+/****************************************************************************
+ * Low-level I2C I/O functions.                                             *
+ * The adapter supports the following I2C transfer functions:               *
+ * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only)           *
+ * i2c_adap_read_byte_data()                                                *
+ * i2c_adap_read_byte()                                                     *
+ ****************************************************************************/
+
+static void w9968cf_smbus_start(struct sd *sd)
+{
+       w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
+       w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
+}
+
+static void w9968cf_smbus_stop(struct sd *sd)
+{
+       w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
+       w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
+       w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
+}
+
+static void w9968cf_smbus_write_byte(struct sd *sd, u8 v)
+{
+       u8 bit;
+       int sda;
+
+       for (bit = 0 ; bit < 8 ; bit++) {
+               sda = (v & 0x80) ? 2 : 0;
+               v <<= 1;
+               /* SDE=1, SDA=sda, SCL=0 */
+               w9968cf_write_sb(sd, 0x10 | sda);
+               /* SDE=1, SDA=sda, SCL=1 */
+               w9968cf_write_sb(sd, 0x11 | sda);
+               /* SDE=1, SDA=sda, SCL=0 */
+               w9968cf_write_sb(sd, 0x10 | sda);
+       }
+}
+
+static void w9968cf_smbus_read_byte(struct sd *sd, u8 *v)
+{
+       u8 bit;
+
+       /* No need to ensure SDA is high as we are always called after
+          read_ack which ends with SDA high */
+       *v = 0;
+       for (bit = 0 ; bit < 8 ; bit++) {
+               *v <<= 1;
+               /* SDE=1, SDA=1, SCL=1 */
+               w9968cf_write_sb(sd, 0x0013);
+               *v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0;
+               /* SDE=1, SDA=1, SCL=0 */
+               w9968cf_write_sb(sd, 0x0012);
+       }
+}
+
+static void w9968cf_smbus_write_nack(struct sd *sd)
+{
+       /* No need to ensure SDA is high as we are always called after
+          read_byte which ends with SDA high */
+       w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
+       w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
+}
+
+static void w9968cf_smbus_read_ack(struct sd *sd)
+{
+       int sda;
+
+       /* Ensure SDA is high before raising clock to avoid a spurious stop */
+       w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
+       w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
+       sda = w9968cf_read_sb(sd);
+       w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
+       if (sda >= 0 && (sda & 0x08)) {
+               PDEBUG(D_USBI, "Did not receive i2c ACK");
+               sd->gspca_dev.usb_err = -EIO;
+       }
+}
+
+/* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */
+static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
+{
+       u16* data = (u16 *)sd->gspca_dev.usb_buf;
+
+       data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0);
+       data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0;
+       data[1] = 0x2082 | ((sd->sensor_addr & 0x40) ? 0x0005 : 0x0);
+       data[1] |= (sd->sensor_addr & 0x20) ? 0x0150 : 0x0;
+       data[1] |= (sd->sensor_addr & 0x10) ? 0x5400 : 0x0;
+       data[2] = 0x8208 | ((sd->sensor_addr & 0x08) ? 0x0015 : 0x0);
+       data[2] |= (sd->sensor_addr & 0x04) ? 0x0540 : 0x0;
+       data[2] |= (sd->sensor_addr & 0x02) ? 0x5000 : 0x0;
+       data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0);
+       data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0;
+
+       w9968cf_write_fsb(sd, data);
+
+       data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0);
+       data[0] |= (reg & 0x40) ? 0x0540 : 0x0;
+       data[0] |= (reg & 0x20) ? 0x5000 : 0x0;
+       data[1] = 0x0820 | ((reg & 0x20) ? 0x0001 : 0x0);
+       data[1] |= (reg & 0x10) ? 0x0054 : 0x0;
+       data[1] |= (reg & 0x08) ? 0x1500 : 0x0;
+       data[1] |= (reg & 0x04) ? 0x4000 : 0x0;
+       data[2] = 0x2082 | ((reg & 0x04) ? 0x0005 : 0x0);
+       data[2] |= (reg & 0x02) ? 0x0150 : 0x0;
+       data[2] |= (reg & 0x01) ? 0x5400 : 0x0;
+       data[3] = 0x001d;
+
+       w9968cf_write_fsb(sd, data);
+
+       data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0);
+       data[0] |= (value & 0x40) ? 0x0540 : 0x0;
+       data[0] |= (value & 0x20) ? 0x5000 : 0x0;
+       data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0);
+       data[1] |= (value & 0x10) ? 0x0054 : 0x0;
+       data[1] |= (value & 0x08) ? 0x1500 : 0x0;
+       data[1] |= (value & 0x04) ? 0x4000 : 0x0;
+       data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0);
+       data[2] |= (value & 0x02) ? 0x0150 : 0x0;
+       data[2] |= (value & 0x01) ? 0x5400 : 0x0;
+       data[3] = 0xfe1d;
+
+       w9968cf_write_fsb(sd, data);
+
+       PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
+}
+
+/* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */
+static int w9968cf_i2c_r(struct sd *sd, u8 reg)
+{
+       int ret = 0;
+       u8 value;
+
+       /* Fast serial bus data control disable */
+       w9968cf_write_sb(sd, 0x0013); /* don't change ! */
+
+       w9968cf_smbus_start(sd);
+       w9968cf_smbus_write_byte(sd, sd->sensor_addr);
+       w9968cf_smbus_read_ack(sd);
+       w9968cf_smbus_write_byte(sd, reg);
+       w9968cf_smbus_read_ack(sd);
+       w9968cf_smbus_stop(sd);
+       w9968cf_smbus_start(sd);
+       w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1);
+       w9968cf_smbus_read_ack(sd);
+       w9968cf_smbus_read_byte(sd, &value);
+       /* signal we don't want to read anymore, the v4l1 driver used to
+          send an ack here which is very wrong! (and then fixed
+          the issues this gave by retrying reads) */
+       w9968cf_smbus_write_nack(sd);
+       w9968cf_smbus_stop(sd);
+
+       /* Fast serial bus data control re-enable */
+       w9968cf_write_sb(sd, 0x0030);
+
+       if (sd->gspca_dev.usb_err >= 0) {
+               ret = value;
+               PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
+       } else
+               PDEBUG(D_ERR, "i2c read [0x%02x] failed", reg);
+
+       return ret;
+}
+
+/*--------------------------------------------------------------------------
+  Turn on the LED on some webcams. A beep should be heard too.
+  Return 0 on success, a negative number otherwise.
+  --------------------------------------------------------------------------*/
+static void w9968cf_configure(struct sd *sd)
+{
+       reg_w(sd, 0x00, 0xff00); /* power-down */
+       reg_w(sd, 0x00, 0xbf17); /* reset everything */
+       reg_w(sd, 0x00, 0xbf10); /* normal operation */
+       reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */
+       reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */
+       reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */
+       reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */
+
+       sd->stopped = 1;
+}
+
+static void w9968cf_init(struct sd *sd)
+{
+       unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2),
+                     y0 = 0x0000,
+                     u0 = y0 + hw_bufsize / 2,
+                     v0 = u0 + hw_bufsize / 4,
+                     y1 = v0 + hw_bufsize / 4,
+                     u1 = y1 + hw_bufsize / 2,
+                     v1 = u1 + hw_bufsize / 4;
+
+       reg_w(sd, 0x00, 0xff00); /* power off */
+       reg_w(sd, 0x00, 0xbf10); /* power on */
+
+       reg_w(sd, 0x03, 0x405d); /* DRAM timings */
+       reg_w(sd, 0x04, 0x0030); /* SDRAM timings */
+
+       reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */
+       reg_w(sd, 0x21, y0 >> 16);    /* Y buf.0, high */
+       reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */
+       reg_w(sd, 0x25, u0 >> 16);    /* U buf.0, high */
+       reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */
+       reg_w(sd, 0x29, v0 >> 16);    /* V buf.0, high */
+
+       reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */
+       reg_w(sd, 0x23, y1 >> 16);    /* Y buf.1, high */
+       reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */
+       reg_w(sd, 0x27, u1 >> 16);    /* U buf.1, high */
+       reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */
+       reg_w(sd, 0x2b, v1 >> 16);    /* V buf.1, high */
+
+       reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */
+       reg_w(sd, 0x33, y1 >> 16);    /* JPEG buf 0 high */
+
+       reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */
+       reg_w(sd, 0x35, y1 >> 16);    /* JPEG bug 1 high */
+
+       reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */
+       reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/
+       reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */
+       reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */
+}
+
+static void w9968cf_set_crop_window(struct sd *sd)
+{
+       int start_cropx, start_cropy,  x, y, fw, fh, cw, ch,
+           max_width, max_height;
+
+       if (sd->sif) {
+               max_width  = 352;
+               max_height = 288;
+       } else {
+               max_width  = 640;
+               max_height = 480;
+       }
+
+       if (sd->sensor == SEN_OV7620) {
+               /*
+                * Sigh, this is dependend on the clock / framerate changes
+                * made by the frequency control, sick.
+                *
+                * Note we cannot use v4l2_ctrl_g_ctrl here, as we get called
+                * from ov519.c:setfreq() with the ctrl lock held!
+                */
+               if (sd->freq->val == 1) {
+                       start_cropx = 277;
+                       start_cropy = 37;
+               } else {
+                       start_cropx = 105;
+                       start_cropy = 37;
+               }
+       } else {
+               start_cropx = 320;
+               start_cropy = 35;
+       }
+
+       /* Work around to avoid FP arithmetics */
+       #define SC(x) ((x) << 10)
+
+       /* Scaling factors */
+       fw = SC(sd->gspca_dev.width) / max_width;
+       fh = SC(sd->gspca_dev.height) / max_height;
+
+       cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width) / fh;
+       ch = (fw >= fh) ? SC(sd->gspca_dev.height) / fw : max_height;
+
+       sd->sensor_width = max_width;
+       sd->sensor_height = max_height;
+
+       x = (max_width - cw) / 2;
+       y = (max_height - ch) / 2;
+
+       reg_w(sd, 0x10, start_cropx + x);
+       reg_w(sd, 0x11, start_cropy + y);
+       reg_w(sd, 0x12, start_cropx + x + cw);
+       reg_w(sd, 0x13, start_cropy + y + ch);
+}
+
+static void w9968cf_mode_init_regs(struct sd *sd)
+{
+       int val, vs_polarity, hs_polarity;
+
+       w9968cf_set_crop_window(sd);
+
+       reg_w(sd, 0x14, sd->gspca_dev.width);
+       reg_w(sd, 0x15, sd->gspca_dev.height);
+
+       /* JPEG width & height */
+       reg_w(sd, 0x30, sd->gspca_dev.width);
+       reg_w(sd, 0x31, sd->gspca_dev.height);
+
+       /* Y & UV frame buffer strides (in WORD) */
+       if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
+           V4L2_PIX_FMT_JPEG) {
+               reg_w(sd, 0x2c, sd->gspca_dev.width / 2);
+               reg_w(sd, 0x2d, sd->gspca_dev.width / 4);
+       } else
+               reg_w(sd, 0x2c, sd->gspca_dev.width);
+
+       reg_w(sd, 0x00, 0xbf17); /* reset everything */
+       reg_w(sd, 0x00, 0xbf10); /* normal operation */
+
+       /* Transfer size in WORDS (for UYVY format only) */
+       val = sd->gspca_dev.width * sd->gspca_dev.height;
+       reg_w(sd, 0x3d, val & 0xffff); /* low bits */
+       reg_w(sd, 0x3e, val >> 16);    /* high bits */
+
+       if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
+           V4L2_PIX_FMT_JPEG) {
+               /* We may get called multiple times (usb isoc bw negotiat.) */
+               jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height,
+                           sd->gspca_dev.width, 0x22); /* JPEG 420 */
+               jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
+               w9968cf_upload_quantizationtables(sd);
+               v4l2_ctrl_grab(sd->jpegqual, true);
+       }
+
+       /* Video Capture Control Register */
+       if (sd->sensor == SEN_OV7620) {
+               /* Seems to work around a bug in the image sensor */
+               vs_polarity = 1;
+               hs_polarity = 1;
+       } else {
+               vs_polarity = 1;
+               hs_polarity = 0;
+       }
+
+       val = (vs_polarity << 12) | (hs_polarity << 11);
+
+       /* NOTE: We may not have enough memory to do double buffering while
+          doing compression (amount of memory differs per model cam).
+          So we use the second image buffer also as jpeg stream buffer
+          (see w9968cf_init), and disable double buffering. */
+       if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
+           V4L2_PIX_FMT_JPEG) {
+               /* val |= 0x0002; YUV422P */
+               val |= 0x0003; /* YUV420P */
+       } else
+               val |= 0x0080; /* Enable HW double buffering */
+
+       /* val |= 0x0020; enable clamping */
+       /* val |= 0x0008; enable (1-2-1) filter */
+       /* val |= 0x000c; enable (2-3-6-3-2) filter */
+
+       val |= 0x8000; /* capt. enable */
+
+       reg_w(sd, 0x16, val);
+
+       sd->gspca_dev.empty_packet = 0;
+}
+
+static void w9968cf_stop0(struct sd *sd)
+{
+       v4l2_ctrl_grab(sd->jpegqual, false);
+       reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */
+       reg_w(sd, 0x16, 0x0000); /* stop video capture */
+}
+
+/* The w9968cf docs say that a 0 sized packet means EOF (and also SOF
+   for the next frame). This seems to simply not be true when operating
+   in JPEG mode, in this case there may be empty packets within the
+   frame. So in JPEG mode use the JPEG SOI marker to detect SOF.
+
+   Note to make things even more interesting the w9968cf sends *PLANAR* jpeg,
+   to be precise it sends: SOI, SOF, DRI, SOS, Y-data, SOS, U-data, SOS,
+   V-data, EOI. */
+static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,                       /* isoc packet */
+                       int len)                        /* iso packet length */
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (w9968cf_vga_mode[gspca_dev->curr_mode].pixelformat ==
+           V4L2_PIX_FMT_JPEG) {
+               if (len >= 2 &&
+                   data[0] == 0xff &&
+                   data[1] == 0xd8) {
+                       gspca_frame_add(gspca_dev, LAST_PACKET,
+                                       NULL, 0);
+                       gspca_frame_add(gspca_dev, FIRST_PACKET,
+                                       sd->jpeg_hdr, JPEG_HDR_SZ);
+                       /* Strip the ff d8, our own header (which adds
+                          huffman and quantization tables) already has this */
+                       len -= 2;
+                       data += 2;
+               }
+       } else {
+               /* In UYVY mode an empty packet signals EOF */
+               if (gspca_dev->empty_packet) {
+                       gspca_frame_add(gspca_dev, LAST_PACKET,
+                                               NULL, 0);
+                       gspca_frame_add(gspca_dev, FIRST_PACKET,
+                                       NULL, 0);
+                       gspca_dev->empty_packet = 0;
+               }
+       }
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
diff --git a/drivers/media/usb/gspca/xirlink_cit.c b/drivers/media/usb/gspca/xirlink_cit.c
new file mode 100644 (file)
index 0000000..13b8d39
--- /dev/null
@@ -0,0 +1,3145 @@
+/*
+ * USB IBM C-It Video Camera driver
+ *
+ * Supports Xirlink C-It Video Camera, IBM PC Camera,
+ * IBM NetCamera and Veo Stingray.
+ *
+ * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.com>
+ *
+ * This driver is based on earlier work of:
+ *
+ * (C) Copyright 1999 Johannes Erdfelt
+ * (C) Copyright 1999 Randy Dunlap
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define MODULE_NAME "xirlink-cit"
+
+#include <linux/input.h>
+#include "gspca.h"
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("Xirlink C-IT");
+MODULE_LICENSE("GPL");
+
+/* FIXME we should autodetect this */
+static int ibm_netcam_pro;
+module_param(ibm_netcam_pro, int, 0);
+MODULE_PARM_DESC(ibm_netcam_pro,
+                "Use IBM Netcamera Pro init sequences for Model 3 cams");
+
+/* FIXME this should be handled through the V4L2 input selection API */
+static int rca_input;
+module_param(rca_input, int, 0644);
+MODULE_PARM_DESC(rca_input,
+                "Use rca input instead of ccd sensor on Model 3 cams");
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;             /* !! must be the first item */
+       struct v4l2_ctrl *lighting;
+       u8 model;
+#define CIT_MODEL0 0 /* bcd version 0.01 cams ie the xvp-500 */
+#define CIT_MODEL1 1 /* The model 1 - 4 nomenclature comes from the old */
+#define CIT_MODEL2 2 /* ibmcam driver */
+#define CIT_MODEL3 3
+#define CIT_MODEL4 4
+#define CIT_IBM_NETCAM_PRO 5
+       u8 input_index;
+       u8 button_state;
+       u8 stop_on_control_change;
+       u8 sof_read;
+       u8 sof_len;
+};
+
+static void sd_stop0(struct gspca_dev *gspca_dev);
+
+static const struct v4l2_pix_format cif_yuv_mode[] = {
+       {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 2 + 4,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+       {352, 288, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3 / 2 + 4,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+};
+
+static const struct v4l2_pix_format vga_yuv_mode[] = {
+       {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 3 / 2 + 4,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+       {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 2 + 4,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+       {640, 480, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 2 + 4,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+};
+
+static const struct v4l2_pix_format model0_mode[] = {
+       {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 3 / 2 + 4,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+       {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 2 + 4,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+       {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 2 + 4,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+};
+
+static const struct v4l2_pix_format model2_mode[] = {
+       {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 3 / 2 + 4,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+       {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 2 + 4,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+       {320, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 + 4,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+       {352, 288, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 + 4,
+               .colorspace = V4L2_COLORSPACE_SRGB},
+};
+
+/*
+ * 01.01.08 - Added for RCA video in support -LO
+ * This struct is used to init the Model3 cam to use the RCA video in port
+ * instead of the CCD sensor.
+ */
+static const u16 rca_initdata[][3] = {
+       {0, 0x0000, 0x010c},
+       {0, 0x0006, 0x012c},
+       {0, 0x0078, 0x012d},
+       {0, 0x0046, 0x012f},
+       {0, 0xd141, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfea8, 0x0124},
+       {1, 0x0000, 0x0116},
+       {0, 0x0064, 0x0116},
+       {1, 0x0000, 0x0115},
+       {0, 0x0003, 0x0115},
+       {0, 0x0008, 0x0123},
+       {0, 0x0000, 0x0117},
+       {0, 0x0000, 0x0112},
+       {0, 0x0080, 0x0100},
+       {0, 0x0000, 0x0100},
+       {1, 0x0000, 0x0116},
+       {0, 0x0060, 0x0116},
+       {0, 0x0002, 0x0112},
+       {0, 0x0000, 0x0123},
+       {0, 0x0001, 0x0117},
+       {0, 0x0040, 0x0108},
+       {0, 0x0019, 0x012c},
+       {0, 0x0040, 0x0116},
+       {0, 0x000a, 0x0115},
+       {0, 0x000b, 0x0115},
+       {0, 0x0078, 0x012d},
+       {0, 0x0046, 0x012f},
+       {0, 0xd141, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfea8, 0x0124},
+       {0, 0x0064, 0x0116},
+       {0, 0x0000, 0x0115},
+       {0, 0x0001, 0x0115},
+       {0, 0xffff, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x00aa, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xffff, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x00f2, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x000f, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xffff, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x00f8, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x00fc, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xffff, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x00f9, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x003c, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xffff, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0027, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0019, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0021, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0006, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0045, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x002a, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x000e, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x002b, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x00f4, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x002c, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0004, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x002d, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0014, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x002e, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0003, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x002f, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0003, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0014, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0040, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0040, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0053, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0x0000, 0x0101},
+       {0, 0x00a0, 0x0103},
+       {0, 0x0078, 0x0105},
+       {0, 0x0000, 0x010a},
+       {0, 0x0024, 0x010b},
+       {0, 0x0028, 0x0119},
+       {0, 0x0088, 0x011b},
+       {0, 0x0002, 0x011d},
+       {0, 0x0003, 0x011e},
+       {0, 0x0000, 0x0129},
+       {0, 0x00fc, 0x012b},
+       {0, 0x0008, 0x0102},
+       {0, 0x0000, 0x0104},
+       {0, 0x0008, 0x011a},
+       {0, 0x0028, 0x011c},
+       {0, 0x0021, 0x012a},
+       {0, 0x0000, 0x0118},
+       {0, 0x0000, 0x0132},
+       {0, 0x0000, 0x0109},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0031, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0040, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0040, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x00dc, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0032, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0020, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0001, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0040, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0040, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0037, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0030, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0xfff9, 0x0124},
+       {0, 0x0086, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0038, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0008, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0x0000, 0x0127},
+       {0, 0xfff8, 0x0124},
+       {0, 0xfffd, 0x0124},
+       {0, 0xfffa, 0x0124},
+       {0, 0x0003, 0x0111},
+};
+
+/* TESTME the old ibmcam driver repeats certain commands to Model1 cameras, we
+   do the same for now (testing needed to see if this is really necessary) */
+static const int cit_model1_ntries = 5;
+static const int cit_model1_ntries2 = 2;
+
+static int cit_write_reg(struct gspca_dev *gspca_dev, u16 value, u16 index)
+{
+       struct usb_device *udev = gspca_dev->dev;
+       int err;
+
+       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
+                       value, index, NULL, 0, 1000);
+       if (err < 0)
+               pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
+                      index, value, err);
+
+       return 0;
+}
+
+static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index, int verbose)
+{
+       struct usb_device *udev = gspca_dev->dev;
+       __u8 *buf = gspca_dev->usb_buf;
+       int res;
+
+       res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x01,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
+                       0x00, index, buf, 8, 1000);
+       if (res < 0) {
+               pr_err("Failed to read a register (index 0x%04X, error %d)\n",
+                      index, res);
+               return res;
+       }
+
+       if (verbose)
+               PDEBUG(D_PROBE, "Register %04x value: %02x", index, buf[0]);
+
+       return 0;
+}
+
+/*
+ * cit_send_FF_04_02()
+ *
+ * This procedure sends magic 3-command prefix to the camera.
+ * The purpose of this prefix is not known.
+ *
+ * History:
+ * 1/2/00   Created.
+ */
+static void cit_send_FF_04_02(struct gspca_dev *gspca_dev)
+{
+       cit_write_reg(gspca_dev, 0x00FF, 0x0127);
+       cit_write_reg(gspca_dev, 0x0004, 0x0124);
+       cit_write_reg(gspca_dev, 0x0002, 0x0124);
+}
+
+static void cit_send_00_04_06(struct gspca_dev *gspca_dev)
+{
+       cit_write_reg(gspca_dev, 0x0000, 0x0127);
+       cit_write_reg(gspca_dev, 0x0004, 0x0124);
+       cit_write_reg(gspca_dev, 0x0006, 0x0124);
+}
+
+static void cit_send_x_00(struct gspca_dev *gspca_dev, unsigned short x)
+{
+       cit_write_reg(gspca_dev, x,      0x0127);
+       cit_write_reg(gspca_dev, 0x0000, 0x0124);
+}
+
+static void cit_send_x_00_05(struct gspca_dev *gspca_dev, unsigned short x)
+{
+       cit_send_x_00(gspca_dev, x);
+       cit_write_reg(gspca_dev, 0x0005, 0x0124);
+}
+
+static void cit_send_x_00_05_02(struct gspca_dev *gspca_dev, unsigned short x)
+{
+       cit_write_reg(gspca_dev, x,      0x0127);
+       cit_write_reg(gspca_dev, 0x0000, 0x0124);
+       cit_write_reg(gspca_dev, 0x0005, 0x0124);
+       cit_write_reg(gspca_dev, 0x0002, 0x0124);
+}
+
+static void cit_send_x_01_00_05(struct gspca_dev *gspca_dev, u16 x)
+{
+       cit_write_reg(gspca_dev, x,      0x0127);
+       cit_write_reg(gspca_dev, 0x0001, 0x0124);
+       cit_write_reg(gspca_dev, 0x0000, 0x0124);
+       cit_write_reg(gspca_dev, 0x0005, 0x0124);
+}
+
+static void cit_send_x_00_05_02_01(struct gspca_dev *gspca_dev, u16 x)
+{
+       cit_write_reg(gspca_dev, x,      0x0127);
+       cit_write_reg(gspca_dev, 0x0000, 0x0124);
+       cit_write_reg(gspca_dev, 0x0005, 0x0124);
+       cit_write_reg(gspca_dev, 0x0002, 0x0124);
+       cit_write_reg(gspca_dev, 0x0001, 0x0124);
+}
+
+static void cit_send_x_00_05_02_08_01(struct gspca_dev *gspca_dev, u16 x)
+{
+       cit_write_reg(gspca_dev, x,      0x0127);
+       cit_write_reg(gspca_dev, 0x0000, 0x0124);
+       cit_write_reg(gspca_dev, 0x0005, 0x0124);
+       cit_write_reg(gspca_dev, 0x0002, 0x0124);
+       cit_write_reg(gspca_dev, 0x0008, 0x0124);
+       cit_write_reg(gspca_dev, 0x0001, 0x0124);
+}
+
+static void cit_Packet_Format1(struct gspca_dev *gspca_dev, u16 fkey, u16 val)
+{
+       cit_send_x_01_00_05(gspca_dev, 0x0088);
+       cit_send_x_00_05(gspca_dev, fkey);
+       cit_send_x_00_05_02_08_01(gspca_dev, val);
+       cit_send_x_00_05(gspca_dev, 0x0088);
+       cit_send_x_00_05_02_01(gspca_dev, fkey);
+       cit_send_x_00_05(gspca_dev, 0x0089);
+       cit_send_x_00(gspca_dev, fkey);
+       cit_send_00_04_06(gspca_dev);
+       cit_read_reg(gspca_dev, 0x0126, 0);
+       cit_send_FF_04_02(gspca_dev);
+}
+
+static void cit_PacketFormat2(struct gspca_dev *gspca_dev, u16 fkey, u16 val)
+{
+       cit_send_x_01_00_05(gspca_dev, 0x0088);
+       cit_send_x_00_05(gspca_dev, fkey);
+       cit_send_x_00_05_02(gspca_dev, val);
+}
+
+static void cit_model2_Packet2(struct gspca_dev *gspca_dev)
+{
+       cit_write_reg(gspca_dev, 0x00ff, 0x012d);
+       cit_write_reg(gspca_dev, 0xfea3, 0x0124);
+}
+
+static void cit_model2_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
+{
+       cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+       cit_write_reg(gspca_dev, 0x00ff, 0x012e);
+       cit_write_reg(gspca_dev, v1,     0x012f);
+       cit_write_reg(gspca_dev, 0x00ff, 0x0130);
+       cit_write_reg(gspca_dev, 0xc719, 0x0124);
+       cit_write_reg(gspca_dev, v2,     0x0127);
+
+       cit_model2_Packet2(gspca_dev);
+}
+
+/*
+ * cit_model3_Packet1()
+ *
+ * 00_0078_012d
+ * 00_0097_012f
+ * 00_d141_0124
+ * 00_0096_0127
+ * 00_fea8_0124
+*/
+static void cit_model3_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
+{
+       cit_write_reg(gspca_dev, 0x0078, 0x012d);
+       cit_write_reg(gspca_dev, v1,     0x012f);
+       cit_write_reg(gspca_dev, 0xd141, 0x0124);
+       cit_write_reg(gspca_dev, v2,     0x0127);
+       cit_write_reg(gspca_dev, 0xfea8, 0x0124);
+}
+
+static void cit_model4_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
+{
+       cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+       cit_write_reg(gspca_dev, v1,     0x012f);
+       cit_write_reg(gspca_dev, 0xd141, 0x0124);
+       cit_write_reg(gspca_dev, v2,     0x0127);
+       cit_write_reg(gspca_dev, 0xfea8, 0x0124);
+}
+
+static void cit_model4_BrightnessPacket(struct gspca_dev *gspca_dev, u16 val)
+{
+       cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+       cit_write_reg(gspca_dev, 0x0026, 0x012f);
+       cit_write_reg(gspca_dev, 0xd141, 0x0124);
+       cit_write_reg(gspca_dev, val,    0x0127);
+       cit_write_reg(gspca_dev, 0x00aa, 0x0130);
+       cit_write_reg(gspca_dev, 0x82a8, 0x0124);
+       cit_write_reg(gspca_dev, 0x0038, 0x012d);
+       cit_write_reg(gspca_dev, 0x0004, 0x012f);
+       cit_write_reg(gspca_dev, 0xd145, 0x0124);
+       cit_write_reg(gspca_dev, 0xfffa, 0x0124);
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                    const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+
+       sd->model = id->driver_info;
+       if (sd->model == CIT_MODEL3 && ibm_netcam_pro)
+               sd->model = CIT_IBM_NETCAM_PRO;
+
+       cam = &gspca_dev->cam;
+       switch (sd->model) {
+       case CIT_MODEL0:
+               cam->cam_mode = model0_mode;
+               cam->nmodes = ARRAY_SIZE(model0_mode);
+               sd->sof_len = 4;
+               break;
+       case CIT_MODEL1:
+               cam->cam_mode = cif_yuv_mode;
+               cam->nmodes = ARRAY_SIZE(cif_yuv_mode);
+               sd->sof_len = 4;
+               break;
+       case CIT_MODEL2:
+               cam->cam_mode = model2_mode + 1; /* no 160x120 */
+               cam->nmodes = 3;
+               break;
+       case CIT_MODEL3:
+               cam->cam_mode = vga_yuv_mode;
+               cam->nmodes = ARRAY_SIZE(vga_yuv_mode);
+               sd->stop_on_control_change = 1;
+               sd->sof_len = 4;
+               break;
+       case CIT_MODEL4:
+               cam->cam_mode = model2_mode;
+               cam->nmodes = ARRAY_SIZE(model2_mode);
+               break;
+       case CIT_IBM_NETCAM_PRO:
+               cam->cam_mode = vga_yuv_mode;
+               cam->nmodes = 2; /* no 640 x 480 */
+               cam->input_flags = V4L2_IN_ST_VFLIP;
+               sd->stop_on_control_change = 1;
+               sd->sof_len = 4;
+               break;
+       }
+
+       return 0;
+}
+
+static int cit_init_model0(struct gspca_dev *gspca_dev)
+{
+       cit_write_reg(gspca_dev, 0x0000, 0x0100); /* turn on led */
+       cit_write_reg(gspca_dev, 0x0001, 0x0112); /* turn on autogain ? */
+       cit_write_reg(gspca_dev, 0x0000, 0x0400);
+       cit_write_reg(gspca_dev, 0x0001, 0x0400);
+       cit_write_reg(gspca_dev, 0x0000, 0x0420);
+       cit_write_reg(gspca_dev, 0x0001, 0x0420);
+       cit_write_reg(gspca_dev, 0x000d, 0x0409);
+       cit_write_reg(gspca_dev, 0x0002, 0x040a);
+       cit_write_reg(gspca_dev, 0x0018, 0x0405);
+       cit_write_reg(gspca_dev, 0x0008, 0x0435);
+       cit_write_reg(gspca_dev, 0x0026, 0x040b);
+       cit_write_reg(gspca_dev, 0x0007, 0x0437);
+       cit_write_reg(gspca_dev, 0x0015, 0x042f);
+       cit_write_reg(gspca_dev, 0x002b, 0x0439);
+       cit_write_reg(gspca_dev, 0x0026, 0x043a);
+       cit_write_reg(gspca_dev, 0x0008, 0x0438);
+       cit_write_reg(gspca_dev, 0x001e, 0x042b);
+       cit_write_reg(gspca_dev, 0x0041, 0x042c);
+
+       return 0;
+}
+
+static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev)
+{
+       cit_read_reg(gspca_dev, 0x128, 1);
+       cit_write_reg(gspca_dev, 0x0003, 0x0133);
+       cit_write_reg(gspca_dev, 0x0000, 0x0117);
+       cit_write_reg(gspca_dev, 0x0008, 0x0123);
+       cit_write_reg(gspca_dev, 0x0000, 0x0100);
+       cit_read_reg(gspca_dev, 0x0116, 0);
+       cit_write_reg(gspca_dev, 0x0060, 0x0116);
+       cit_write_reg(gspca_dev, 0x0002, 0x0112);
+       cit_write_reg(gspca_dev, 0x0000, 0x0133);
+       cit_write_reg(gspca_dev, 0x0000, 0x0123);
+       cit_write_reg(gspca_dev, 0x0001, 0x0117);
+       cit_write_reg(gspca_dev, 0x0040, 0x0108);
+       cit_write_reg(gspca_dev, 0x0019, 0x012c);
+       cit_write_reg(gspca_dev, 0x0060, 0x0116);
+       cit_write_reg(gspca_dev, 0x0002, 0x0115);
+       cit_write_reg(gspca_dev, 0x000b, 0x0115);
+
+       cit_write_reg(gspca_dev, 0x0078, 0x012d);
+       cit_write_reg(gspca_dev, 0x0001, 0x012f);
+       cit_write_reg(gspca_dev, 0xd141, 0x0124);
+       cit_write_reg(gspca_dev, 0x0079, 0x012d);
+       cit_write_reg(gspca_dev, 0x00ff, 0x0130);
+       cit_write_reg(gspca_dev, 0xcd41, 0x0124);
+       cit_write_reg(gspca_dev, 0xfffa, 0x0124);
+       cit_read_reg(gspca_dev, 0x0126, 1);
+
+       cit_model3_Packet1(gspca_dev, 0x0000, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0000, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x000b, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x000c, 0x0008);
+       cit_model3_Packet1(gspca_dev, 0x000d, 0x003a);
+       cit_model3_Packet1(gspca_dev, 0x000e, 0x0060);
+       cit_model3_Packet1(gspca_dev, 0x000f, 0x0060);
+       cit_model3_Packet1(gspca_dev, 0x0010, 0x0008);
+       cit_model3_Packet1(gspca_dev, 0x0011, 0x0004);
+       cit_model3_Packet1(gspca_dev, 0x0012, 0x0028);
+       cit_model3_Packet1(gspca_dev, 0x0013, 0x0002);
+       cit_model3_Packet1(gspca_dev, 0x0014, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0015, 0x00fb);
+       cit_model3_Packet1(gspca_dev, 0x0016, 0x0002);
+       cit_model3_Packet1(gspca_dev, 0x0017, 0x0037);
+       cit_model3_Packet1(gspca_dev, 0x0018, 0x0036);
+       cit_model3_Packet1(gspca_dev, 0x001e, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x001f, 0x0008);
+       cit_model3_Packet1(gspca_dev, 0x0020, 0x00c1);
+       cit_model3_Packet1(gspca_dev, 0x0021, 0x0034);
+       cit_model3_Packet1(gspca_dev, 0x0022, 0x0034);
+       cit_model3_Packet1(gspca_dev, 0x0025, 0x0002);
+       cit_model3_Packet1(gspca_dev, 0x0028, 0x0022);
+       cit_model3_Packet1(gspca_dev, 0x0029, 0x000a);
+       cit_model3_Packet1(gspca_dev, 0x002b, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x002c, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x002d, 0x00ff);
+       cit_model3_Packet1(gspca_dev, 0x002e, 0x00ff);
+       cit_model3_Packet1(gspca_dev, 0x002f, 0x00ff);
+       cit_model3_Packet1(gspca_dev, 0x0030, 0x00ff);
+       cit_model3_Packet1(gspca_dev, 0x0031, 0x00ff);
+       cit_model3_Packet1(gspca_dev, 0x0032, 0x0007);
+       cit_model3_Packet1(gspca_dev, 0x0033, 0x0005);
+       cit_model3_Packet1(gspca_dev, 0x0037, 0x0040);
+       cit_model3_Packet1(gspca_dev, 0x0039, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x003a, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x003b, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x003c, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0040, 0x000c);
+       cit_model3_Packet1(gspca_dev, 0x0041, 0x00fb);
+       cit_model3_Packet1(gspca_dev, 0x0042, 0x0002);
+       cit_model3_Packet1(gspca_dev, 0x0043, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0045, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0046, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0047, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0048, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0049, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x004a, 0x00ff);
+       cit_model3_Packet1(gspca_dev, 0x004b, 0x00ff);
+       cit_model3_Packet1(gspca_dev, 0x004c, 0x00ff);
+       cit_model3_Packet1(gspca_dev, 0x004f, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0050, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0051, 0x0002);
+       cit_model3_Packet1(gspca_dev, 0x0055, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0056, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0057, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0058, 0x0002);
+       cit_model3_Packet1(gspca_dev, 0x0059, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x005c, 0x0016);
+       cit_model3_Packet1(gspca_dev, 0x005d, 0x0022);
+       cit_model3_Packet1(gspca_dev, 0x005e, 0x003c);
+       cit_model3_Packet1(gspca_dev, 0x005f, 0x0050);
+       cit_model3_Packet1(gspca_dev, 0x0060, 0x0044);
+       cit_model3_Packet1(gspca_dev, 0x0061, 0x0005);
+       cit_model3_Packet1(gspca_dev, 0x006a, 0x007e);
+       cit_model3_Packet1(gspca_dev, 0x006f, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0072, 0x001b);
+       cit_model3_Packet1(gspca_dev, 0x0073, 0x0005);
+       cit_model3_Packet1(gspca_dev, 0x0074, 0x000a);
+       cit_model3_Packet1(gspca_dev, 0x0075, 0x001b);
+       cit_model3_Packet1(gspca_dev, 0x0076, 0x002a);
+       cit_model3_Packet1(gspca_dev, 0x0077, 0x003c);
+       cit_model3_Packet1(gspca_dev, 0x0078, 0x0050);
+       cit_model3_Packet1(gspca_dev, 0x007b, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x007c, 0x0011);
+       cit_model3_Packet1(gspca_dev, 0x007d, 0x0024);
+       cit_model3_Packet1(gspca_dev, 0x007e, 0x0043);
+       cit_model3_Packet1(gspca_dev, 0x007f, 0x005a);
+       cit_model3_Packet1(gspca_dev, 0x0084, 0x0020);
+       cit_model3_Packet1(gspca_dev, 0x0085, 0x0033);
+       cit_model3_Packet1(gspca_dev, 0x0086, 0x000a);
+       cit_model3_Packet1(gspca_dev, 0x0087, 0x0030);
+       cit_model3_Packet1(gspca_dev, 0x0088, 0x0070);
+       cit_model3_Packet1(gspca_dev, 0x008b, 0x0008);
+       cit_model3_Packet1(gspca_dev, 0x008f, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0090, 0x0006);
+       cit_model3_Packet1(gspca_dev, 0x0091, 0x0028);
+       cit_model3_Packet1(gspca_dev, 0x0092, 0x005a);
+       cit_model3_Packet1(gspca_dev, 0x0093, 0x0082);
+       cit_model3_Packet1(gspca_dev, 0x0096, 0x0014);
+       cit_model3_Packet1(gspca_dev, 0x0097, 0x0020);
+       cit_model3_Packet1(gspca_dev, 0x0098, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00b0, 0x0046);
+       cit_model3_Packet1(gspca_dev, 0x00b1, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00b2, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00b3, 0x0004);
+       cit_model3_Packet1(gspca_dev, 0x00b4, 0x0007);
+       cit_model3_Packet1(gspca_dev, 0x00b6, 0x0002);
+       cit_model3_Packet1(gspca_dev, 0x00b7, 0x0004);
+       cit_model3_Packet1(gspca_dev, 0x00bb, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00bc, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x00bd, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00bf, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00c0, 0x00c8);
+       cit_model3_Packet1(gspca_dev, 0x00c1, 0x0014);
+       cit_model3_Packet1(gspca_dev, 0x00c2, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x00c3, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00c4, 0x0004);
+       cit_model3_Packet1(gspca_dev, 0x00cb, 0x00bf);
+       cit_model3_Packet1(gspca_dev, 0x00cc, 0x00bf);
+       cit_model3_Packet1(gspca_dev, 0x00cd, 0x00bf);
+       cit_model3_Packet1(gspca_dev, 0x00ce, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00cf, 0x0020);
+       cit_model3_Packet1(gspca_dev, 0x00d0, 0x0040);
+       cit_model3_Packet1(gspca_dev, 0x00d1, 0x00bf);
+       cit_model3_Packet1(gspca_dev, 0x00d1, 0x00bf);
+       cit_model3_Packet1(gspca_dev, 0x00d2, 0x00bf);
+       cit_model3_Packet1(gspca_dev, 0x00d3, 0x00bf);
+       cit_model3_Packet1(gspca_dev, 0x00ea, 0x0008);
+       cit_model3_Packet1(gspca_dev, 0x00eb, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00ec, 0x00e8);
+       cit_model3_Packet1(gspca_dev, 0x00ed, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x00ef, 0x0022);
+       cit_model3_Packet1(gspca_dev, 0x00f0, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00f2, 0x0028);
+       cit_model3_Packet1(gspca_dev, 0x00f4, 0x0002);
+       cit_model3_Packet1(gspca_dev, 0x00f5, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00fa, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00fb, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x00fc, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00fd, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00fe, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00ff, 0x0000);
+
+       cit_model3_Packet1(gspca_dev, 0x00be, 0x0003);
+       cit_model3_Packet1(gspca_dev, 0x00c8, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00c9, 0x0020);
+       cit_model3_Packet1(gspca_dev, 0x00ca, 0x0040);
+       cit_model3_Packet1(gspca_dev, 0x0053, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x0082, 0x000e);
+       cit_model3_Packet1(gspca_dev, 0x0083, 0x0020);
+       cit_model3_Packet1(gspca_dev, 0x0034, 0x003c);
+       cit_model3_Packet1(gspca_dev, 0x006e, 0x0055);
+       cit_model3_Packet1(gspca_dev, 0x0062, 0x0005);
+       cit_model3_Packet1(gspca_dev, 0x0063, 0x0008);
+       cit_model3_Packet1(gspca_dev, 0x0066, 0x000a);
+       cit_model3_Packet1(gspca_dev, 0x0067, 0x0006);
+       cit_model3_Packet1(gspca_dev, 0x006b, 0x0010);
+       cit_model3_Packet1(gspca_dev, 0x005a, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x005b, 0x000a);
+       cit_model3_Packet1(gspca_dev, 0x0023, 0x0006);
+       cit_model3_Packet1(gspca_dev, 0x0026, 0x0004);
+       cit_model3_Packet1(gspca_dev, 0x0036, 0x0069);
+       cit_model3_Packet1(gspca_dev, 0x0038, 0x0064);
+       cit_model3_Packet1(gspca_dev, 0x003d, 0x0003);
+       cit_model3_Packet1(gspca_dev, 0x003e, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x00b8, 0x0014);
+       cit_model3_Packet1(gspca_dev, 0x00b9, 0x0014);
+       cit_model3_Packet1(gspca_dev, 0x00e6, 0x0004);
+       cit_model3_Packet1(gspca_dev, 0x00e8, 0x0001);
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->model) {
+       case CIT_MODEL0:
+               cit_init_model0(gspca_dev);
+               sd_stop0(gspca_dev);
+               break;
+       case CIT_MODEL1:
+       case CIT_MODEL2:
+       case CIT_MODEL3:
+       case CIT_MODEL4:
+               break; /* All is done in sd_start */
+       case CIT_IBM_NETCAM_PRO:
+               cit_init_ibm_netcam_pro(gspca_dev);
+               sd_stop0(gspca_dev);
+               break;
+       }
+       return 0;
+}
+
+static int cit_set_brightness(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+
+       switch (sd->model) {
+       case CIT_MODEL0:
+       case CIT_IBM_NETCAM_PRO:
+               /* No (known) brightness control for these */
+               break;
+       case CIT_MODEL1:
+               /* Model 1: Brightness range 0 - 63 */
+               cit_Packet_Format1(gspca_dev, 0x0031, val);
+               cit_Packet_Format1(gspca_dev, 0x0032, val);
+               cit_Packet_Format1(gspca_dev, 0x0033, val);
+               break;
+       case CIT_MODEL2:
+               /* Model 2: Brightness range 0x60 - 0xee */
+               /* Scale 0 - 63 to 0x60 - 0xee */
+               i = 0x60 + val * 2254 / 1000;
+               cit_model2_Packet1(gspca_dev, 0x001a, i);
+               break;
+       case CIT_MODEL3:
+               /* Model 3: Brightness range 'i' in [0x0C..0x3F] */
+               i = val;
+               if (i < 0x0c)
+                       i = 0x0c;
+               cit_model3_Packet1(gspca_dev, 0x0036, i);
+               break;
+       case CIT_MODEL4:
+               /* Model 4: Brightness range 'i' in [0x04..0xb4] */
+               /* Scale 0 - 63 to 0x04 - 0xb4 */
+               i = 0x04 + val * 2794 / 1000;
+               cit_model4_BrightnessPacket(gspca_dev, i);
+               break;
+       }
+
+       return 0;
+}
+
+static int cit_set_contrast(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->model) {
+       case CIT_MODEL0: {
+               int i;
+               /* gain 0-15, 0-20 -> 0-15 */
+               i = val * 1000 / 1333;
+               cit_write_reg(gspca_dev, i, 0x0422);
+               /* gain 0-31, may not be lower then 0x0422, 0-20 -> 0-31 */
+               i = val * 2000 / 1333;
+               cit_write_reg(gspca_dev, i, 0x0423);
+               /* gain 0-127, may not be lower then 0x0423, 0-20 -> 0-63  */
+               i = val * 4000 / 1333;
+               cit_write_reg(gspca_dev, i, 0x0424);
+               /* gain 0-127, may not be lower then 0x0424, , 0-20 -> 0-127 */
+               i = val * 8000 / 1333;
+               cit_write_reg(gspca_dev, i, 0x0425);
+               break;
+       }
+       case CIT_MODEL2:
+       case CIT_MODEL4:
+               /* These models do not have this control. */
+               break;
+       case CIT_MODEL1:
+       {
+               /* Scale 0 - 20 to 15 - 0 */
+               int i, new_contrast = (20 - val) * 1000 / 1333;
+               for (i = 0; i < cit_model1_ntries; i++) {
+                       cit_Packet_Format1(gspca_dev, 0x0014, new_contrast);
+                       cit_send_FF_04_02(gspca_dev);
+               }
+               break;
+       }
+       case CIT_MODEL3:
+       {       /* Preset hardware values */
+               static const struct {
+                       unsigned short cv1;
+                       unsigned short cv2;
+                       unsigned short cv3;
+               } cv[7] = {
+                       { 0x05, 0x05, 0x0f },   /* Minimum */
+                       { 0x04, 0x04, 0x16 },
+                       { 0x02, 0x03, 0x16 },
+                       { 0x02, 0x08, 0x16 },
+                       { 0x01, 0x0c, 0x16 },
+                       { 0x01, 0x0e, 0x16 },
+                       { 0x01, 0x10, 0x16 }    /* Maximum */
+               };
+               int i = val / 3;
+               cit_model3_Packet1(gspca_dev, 0x0067, cv[i].cv1);
+               cit_model3_Packet1(gspca_dev, 0x005b, cv[i].cv2);
+               cit_model3_Packet1(gspca_dev, 0x005c, cv[i].cv3);
+               break;
+       }
+       case CIT_IBM_NETCAM_PRO:
+               cit_model3_Packet1(gspca_dev, 0x005b, val + 1);
+               break;
+       }
+       return 0;
+}
+
+static int cit_set_hue(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->model) {
+       case CIT_MODEL0:
+       case CIT_MODEL1:
+       case CIT_IBM_NETCAM_PRO:
+               /* No hue control for these models */
+               break;
+       case CIT_MODEL2:
+               cit_model2_Packet1(gspca_dev, 0x0024, val);
+               /* cit_model2_Packet1(gspca_dev, 0x0020, sat); */
+               break;
+       case CIT_MODEL3: {
+               /* Model 3: Brightness range 'i' in [0x05..0x37] */
+               /* TESTME according to the ibmcam driver this does not work */
+               if (0) {
+                       /* Scale 0 - 127 to 0x05 - 0x37 */
+                       int i = 0x05 + val * 1000 / 2540;
+                       cit_model3_Packet1(gspca_dev, 0x007e, i);
+               }
+               break;
+       }
+       case CIT_MODEL4:
+               /* HDG: taken from ibmcam, setting the color gains does not
+                * really belong here.
+                *
+                * I am not sure r/g/b_gain variables exactly control gain
+                * of those channels. Most likely they subtly change some
+                * very internal image processing settings in the camera.
+                * In any case, here is what they do, and feel free to tweak:
+                *
+                * r_gain: seriously affects red gain
+                * g_gain: seriously affects green gain
+                * b_gain: seriously affects blue gain
+                * hue: changes average color from violet (0) to red (0xFF)
+                */
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x001e, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev,    160, 0x0127);  /* Green gain */
+               cit_write_reg(gspca_dev,    160, 0x012e);  /* Red gain */
+               cit_write_reg(gspca_dev,    160, 0x0130);  /* Blue gain */
+               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
+               cit_write_reg(gspca_dev, val, 0x012d); /* Hue */
+               cit_write_reg(gspca_dev, 0xf545, 0x0124);
+               break;
+       }
+       return 0;
+}
+
+static int cit_set_sharpness(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->model) {
+       case CIT_MODEL0:
+       case CIT_MODEL2:
+       case CIT_MODEL4:
+       case CIT_IBM_NETCAM_PRO:
+               /* These models do not have this control */
+               break;
+       case CIT_MODEL1: {
+               int i;
+               const unsigned short sa[] = {
+                       0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a };
+
+               for (i = 0; i < cit_model1_ntries; i++)
+                       cit_PacketFormat2(gspca_dev, 0x0013, sa[val]);
+               break;
+       }
+       case CIT_MODEL3:
+       {       /*
+                * "Use a table of magic numbers.
+                *  This setting doesn't really change much.
+                *  But that's how Windows does it."
+                */
+               static const struct {
+                       unsigned short sv1;
+                       unsigned short sv2;
+                       unsigned short sv3;
+                       unsigned short sv4;
+               } sv[7] = {
+                       { 0x00, 0x00, 0x05, 0x14 },     /* Smoothest */
+                       { 0x01, 0x04, 0x05, 0x14 },
+                       { 0x02, 0x04, 0x05, 0x14 },
+                       { 0x03, 0x04, 0x05, 0x14 },
+                       { 0x03, 0x05, 0x05, 0x14 },
+                       { 0x03, 0x06, 0x05, 0x14 },
+                       { 0x03, 0x07, 0x05, 0x14 }      /* Sharpest */
+               };
+               cit_model3_Packet1(gspca_dev, 0x0060, sv[val].sv1);
+               cit_model3_Packet1(gspca_dev, 0x0061, sv[val].sv2);
+               cit_model3_Packet1(gspca_dev, 0x0062, sv[val].sv3);
+               cit_model3_Packet1(gspca_dev, 0x0063, sv[val].sv4);
+               break;
+       }
+       }
+       return 0;
+}
+
+/*
+ * cit_set_lighting()
+ *
+ * Camera model 1:
+ * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low.
+ *
+ * Camera model 2:
+ * We have 16 levels of lighting, 0 for bright light and up to 15 for
+ * low light. But values above 5 or so are useless because camera is
+ * not really capable to produce anything worth viewing at such light.
+ * This setting may be altered only in certain camera state.
+ *
+ * Low lighting forces slower FPS.
+ *
+ * History:
+ * 1/5/00   Created.
+ * 2/20/00  Added support for Model 2 cameras.
+ */
+static void cit_set_lighting(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->model) {
+       case CIT_MODEL0:
+       case CIT_MODEL2:
+       case CIT_MODEL3:
+       case CIT_MODEL4:
+       case CIT_IBM_NETCAM_PRO:
+               break;
+       case CIT_MODEL1: {
+               int i;
+               for (i = 0; i < cit_model1_ntries; i++)
+                       cit_Packet_Format1(gspca_dev, 0x0027, val);
+               break;
+       }
+       }
+}
+
+static void cit_set_hflip(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->model) {
+       case CIT_MODEL0:
+               if (val)
+                       cit_write_reg(gspca_dev, 0x0020, 0x0115);
+               else
+                       cit_write_reg(gspca_dev, 0x0040, 0x0115);
+               break;
+       case CIT_MODEL1:
+       case CIT_MODEL2:
+       case CIT_MODEL3:
+       case CIT_MODEL4:
+       case CIT_IBM_NETCAM_PRO:
+               break;
+       }
+}
+
+static int cit_restart_stream(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       switch (sd->model) {
+       case CIT_MODEL0:
+       case CIT_MODEL1:
+               cit_write_reg(gspca_dev, 0x0001, 0x0114);
+               /* Fall through */
+       case CIT_MODEL2:
+       case CIT_MODEL4:
+               cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */
+               usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
+               break;
+       case CIT_MODEL3:
+       case CIT_IBM_NETCAM_PRO:
+               cit_write_reg(gspca_dev, 0x0001, 0x0114);
+               cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */
+               usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
+               /* Clear button events from while we were not streaming */
+               cit_write_reg(gspca_dev, 0x0001, 0x0113);
+               break;
+       }
+
+       sd->sof_read = 0;
+
+       return 0;
+}
+
+static int cit_get_packet_size(struct gspca_dev *gspca_dev)
+{
+       struct usb_host_interface *alt;
+       struct usb_interface *intf;
+
+       intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
+       alt = usb_altnum_to_altsetting(intf, gspca_dev->alt);
+       if (!alt) {
+               pr_err("Couldn't get altsetting\n");
+               return -EIO;
+       }
+
+       return le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+}
+
+/* Calculate the clockdiv giving us max fps given the available bandwidth */
+static int cit_get_clock_div(struct gspca_dev *gspca_dev)
+{
+       int clock_div = 7; /* 0=30 1=25 2=20 3=15 4=12 5=7.5 6=6 7=3fps ?? */
+       int fps[8] = { 30, 25, 20, 15, 12, 8, 6, 3 };
+       int packet_size;
+
+       packet_size = cit_get_packet_size(gspca_dev);
+       if (packet_size < 0)
+               return packet_size;
+
+       while (clock_div > 3 &&
+                       1000 * packet_size >
+                       gspca_dev->width * gspca_dev->height *
+                       fps[clock_div - 1] * 3 / 2)
+               clock_div--;
+
+       PDEBUG(D_PROBE,
+              "PacketSize: %d, res: %dx%d -> using clockdiv: %d (%d fps)",
+              packet_size, gspca_dev->width, gspca_dev->height, clock_div,
+              fps[clock_div]);
+
+       return clock_div;
+}
+
+static int cit_start_model0(struct gspca_dev *gspca_dev)
+{
+       const unsigned short compression = 0; /* 0=none, 7=best frame rate */
+       int clock_div;
+
+       clock_div = cit_get_clock_div(gspca_dev);
+       if (clock_div < 0)
+               return clock_div;
+
+       cit_write_reg(gspca_dev, 0x0000, 0x0100); /* turn on led */
+       cit_write_reg(gspca_dev, 0x0003, 0x0438);
+       cit_write_reg(gspca_dev, 0x001e, 0x042b);
+       cit_write_reg(gspca_dev, 0x0041, 0x042c);
+       cit_write_reg(gspca_dev, 0x0008, 0x0436);
+       cit_write_reg(gspca_dev, 0x0024, 0x0403);
+       cit_write_reg(gspca_dev, 0x002c, 0x0404);
+       cit_write_reg(gspca_dev, 0x0002, 0x0426);
+       cit_write_reg(gspca_dev, 0x0014, 0x0427);
+
+       switch (gspca_dev->width) {
+       case 160: /* 160x120 */
+               cit_write_reg(gspca_dev, 0x0004, 0x010b);
+               cit_write_reg(gspca_dev, 0x0001, 0x010a);
+               cit_write_reg(gspca_dev, 0x0010, 0x0102);
+               cit_write_reg(gspca_dev, 0x00a0, 0x0103);
+               cit_write_reg(gspca_dev, 0x0000, 0x0104);
+               cit_write_reg(gspca_dev, 0x0078, 0x0105);
+               break;
+
+       case 176: /* 176x144 */
+               cit_write_reg(gspca_dev, 0x0006, 0x010b);
+               cit_write_reg(gspca_dev, 0x0000, 0x010a);
+               cit_write_reg(gspca_dev, 0x0005, 0x0102);
+               cit_write_reg(gspca_dev, 0x00b0, 0x0103);
+               cit_write_reg(gspca_dev, 0x0000, 0x0104);
+               cit_write_reg(gspca_dev, 0x0090, 0x0105);
+               break;
+
+       case 320: /* 320x240 */
+               cit_write_reg(gspca_dev, 0x0008, 0x010b);
+               cit_write_reg(gspca_dev, 0x0004, 0x010a);
+               cit_write_reg(gspca_dev, 0x0005, 0x0102);
+               cit_write_reg(gspca_dev, 0x00a0, 0x0103);
+               cit_write_reg(gspca_dev, 0x0010, 0x0104);
+               cit_write_reg(gspca_dev, 0x0078, 0x0105);
+               break;
+       }
+
+       cit_write_reg(gspca_dev, compression, 0x0109);
+       cit_write_reg(gspca_dev, clock_div, 0x0111);
+
+       return 0;
+}
+
+static int cit_start_model1(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i, clock_div;
+
+       clock_div = cit_get_clock_div(gspca_dev);
+       if (clock_div < 0)
+               return clock_div;
+
+       cit_read_reg(gspca_dev, 0x0128, 1);
+       cit_read_reg(gspca_dev, 0x0100, 0);
+       cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On  */
+       cit_read_reg(gspca_dev, 0x0100, 0);
+       cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */
+       cit_read_reg(gspca_dev, 0x0100, 0);
+       cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On  */
+       cit_write_reg(gspca_dev, 0x01, 0x0108);
+
+       cit_write_reg(gspca_dev, 0x03, 0x0112);
+       cit_read_reg(gspca_dev, 0x0115, 0);
+       cit_write_reg(gspca_dev, 0x06, 0x0115);
+       cit_read_reg(gspca_dev, 0x0116, 0);
+       cit_write_reg(gspca_dev, 0x44, 0x0116);
+       cit_read_reg(gspca_dev, 0x0116, 0);
+       cit_write_reg(gspca_dev, 0x40, 0x0116);
+       cit_read_reg(gspca_dev, 0x0115, 0);
+       cit_write_reg(gspca_dev, 0x0e, 0x0115);
+       cit_write_reg(gspca_dev, 0x19, 0x012c);
+
+       cit_Packet_Format1(gspca_dev, 0x00, 0x1e);
+       cit_Packet_Format1(gspca_dev, 0x39, 0x0d);
+       cit_Packet_Format1(gspca_dev, 0x39, 0x09);
+       cit_Packet_Format1(gspca_dev, 0x3b, 0x00);
+       cit_Packet_Format1(gspca_dev, 0x28, 0x22);
+       cit_Packet_Format1(gspca_dev, 0x27, 0x00);
+       cit_Packet_Format1(gspca_dev, 0x2b, 0x1f);
+       cit_Packet_Format1(gspca_dev, 0x39, 0x08);
+
+       for (i = 0; i < cit_model1_ntries; i++)
+               cit_Packet_Format1(gspca_dev, 0x2c, 0x00);
+
+       for (i = 0; i < cit_model1_ntries; i++)
+               cit_Packet_Format1(gspca_dev, 0x30, 0x14);
+
+       cit_PacketFormat2(gspca_dev, 0x39, 0x02);
+       cit_PacketFormat2(gspca_dev, 0x01, 0xe1);
+       cit_PacketFormat2(gspca_dev, 0x02, 0xcd);
+       cit_PacketFormat2(gspca_dev, 0x03, 0xcd);
+       cit_PacketFormat2(gspca_dev, 0x04, 0xfa);
+       cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
+       cit_PacketFormat2(gspca_dev, 0x39, 0x00);
+
+       cit_PacketFormat2(gspca_dev, 0x39, 0x02);
+       cit_PacketFormat2(gspca_dev, 0x0a, 0x37);
+       cit_PacketFormat2(gspca_dev, 0x0b, 0xb8);
+       cit_PacketFormat2(gspca_dev, 0x0c, 0xf3);
+       cit_PacketFormat2(gspca_dev, 0x0d, 0xe3);
+       cit_PacketFormat2(gspca_dev, 0x0e, 0x0d);
+       cit_PacketFormat2(gspca_dev, 0x0f, 0xf2);
+       cit_PacketFormat2(gspca_dev, 0x10, 0xd5);
+       cit_PacketFormat2(gspca_dev, 0x11, 0xba);
+       cit_PacketFormat2(gspca_dev, 0x12, 0x53);
+       cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
+       cit_PacketFormat2(gspca_dev, 0x39, 0x00);
+
+       cit_PacketFormat2(gspca_dev, 0x39, 0x02);
+       cit_PacketFormat2(gspca_dev, 0x16, 0x00);
+       cit_PacketFormat2(gspca_dev, 0x17, 0x28);
+       cit_PacketFormat2(gspca_dev, 0x18, 0x7d);
+       cit_PacketFormat2(gspca_dev, 0x19, 0xbe);
+       cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
+       cit_PacketFormat2(gspca_dev, 0x39, 0x00);
+
+       for (i = 0; i < cit_model1_ntries; i++)
+               cit_Packet_Format1(gspca_dev, 0x00, 0x18);
+       for (i = 0; i < cit_model1_ntries; i++)
+               cit_Packet_Format1(gspca_dev, 0x13, 0x18);
+       for (i = 0; i < cit_model1_ntries; i++)
+               cit_Packet_Format1(gspca_dev, 0x14, 0x06);
+
+       /* TESTME These are handled through controls
+          KEEP until someone can test leaving this out is ok */
+       if (0) {
+               /* This is default brightness */
+               for (i = 0; i < cit_model1_ntries; i++)
+                       cit_Packet_Format1(gspca_dev, 0x31, 0x37);
+               for (i = 0; i < cit_model1_ntries; i++)
+                       cit_Packet_Format1(gspca_dev, 0x32, 0x46);
+               for (i = 0; i < cit_model1_ntries; i++)
+                       cit_Packet_Format1(gspca_dev, 0x33, 0x55);
+       }
+
+       cit_Packet_Format1(gspca_dev, 0x2e, 0x04);
+       for (i = 0; i < cit_model1_ntries; i++)
+               cit_Packet_Format1(gspca_dev, 0x2d, 0x04);
+       for (i = 0; i < cit_model1_ntries; i++)
+               cit_Packet_Format1(gspca_dev, 0x29, 0x80);
+       cit_Packet_Format1(gspca_dev, 0x2c, 0x01);
+       cit_Packet_Format1(gspca_dev, 0x30, 0x17);
+       cit_Packet_Format1(gspca_dev, 0x39, 0x08);
+       for (i = 0; i < cit_model1_ntries; i++)
+               cit_Packet_Format1(gspca_dev, 0x34, 0x00);
+
+       cit_write_reg(gspca_dev, 0x00, 0x0101);
+       cit_write_reg(gspca_dev, 0x00, 0x010a);
+
+       switch (gspca_dev->width) {
+       case 128: /* 128x96 */
+               cit_write_reg(gspca_dev, 0x80, 0x0103);
+               cit_write_reg(gspca_dev, 0x60, 0x0105);
+               cit_write_reg(gspca_dev, 0x0c, 0x010b);
+               cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x0b, 0x011d);
+               cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x00, 0x0129);
+               break;
+       case 176: /* 176x144 */
+               cit_write_reg(gspca_dev, 0xb0, 0x0103);
+               cit_write_reg(gspca_dev, 0x8f, 0x0105);
+               cit_write_reg(gspca_dev, 0x06, 0x010b);
+               cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x0d, 0x011d);
+               cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x03, 0x0129);
+               break;
+       case 352: /* 352x288 */
+               cit_write_reg(gspca_dev, 0xb0, 0x0103);
+               cit_write_reg(gspca_dev, 0x90, 0x0105);
+               cit_write_reg(gspca_dev, 0x02, 0x010b);
+               cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x05, 0x011d);
+               cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x00, 0x0129);
+               break;
+       }
+
+       cit_write_reg(gspca_dev, 0xff, 0x012b);
+
+       /* TESTME These are handled through controls
+          KEEP until someone can test leaving this out is ok */
+       if (0) {
+               /* This is another brightness - don't know why */
+               for (i = 0; i < cit_model1_ntries; i++)
+                       cit_Packet_Format1(gspca_dev, 0x31, 0xc3);
+               for (i = 0; i < cit_model1_ntries; i++)
+                       cit_Packet_Format1(gspca_dev, 0x32, 0xd2);
+               for (i = 0; i < cit_model1_ntries; i++)
+                       cit_Packet_Format1(gspca_dev, 0x33, 0xe1);
+
+               /* Default contrast */
+               for (i = 0; i < cit_model1_ntries; i++)
+                       cit_Packet_Format1(gspca_dev, 0x14, 0x0a);
+
+               /* Default sharpness */
+               for (i = 0; i < cit_model1_ntries2; i++)
+                       cit_PacketFormat2(gspca_dev, 0x13, 0x1a);
+
+               /* Default lighting conditions */
+               cit_Packet_Format1(gspca_dev, 0x0027,
+                                  v4l2_ctrl_g_ctrl(sd->lighting));
+       }
+
+       /* Assorted init */
+       switch (gspca_dev->width) {
+       case 128: /* 128x96 */
+               cit_Packet_Format1(gspca_dev, 0x2b, 0x1e);
+               cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x36, 0x0102);
+               cit_write_reg(gspca_dev, 0x1a, 0x0104);
+               cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x2b, 0x011c);
+               cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
+               break;
+       case 176: /* 176x144 */
+               cit_Packet_Format1(gspca_dev, 0x2b, 0x1e);
+               cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x04, 0x0102);
+               cit_write_reg(gspca_dev, 0x02, 0x0104);
+               cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x2b, 0x011c);
+               cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
+               break;
+       case 352: /* 352x288 */
+               cit_Packet_Format1(gspca_dev, 0x2b, 0x1f);
+               cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x08, 0x0102);
+               cit_write_reg(gspca_dev, 0x01, 0x0104);
+               cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
+               cit_write_reg(gspca_dev, 0x2f, 0x011c);
+               cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
+               break;
+       }
+
+       cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On  */
+       cit_write_reg(gspca_dev, clock_div, 0x0111);
+
+       return 0;
+}
+
+static int cit_start_model2(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int clock_div = 0;
+
+       cit_write_reg(gspca_dev, 0x0000, 0x0100);       /* LED on */
+       cit_read_reg(gspca_dev, 0x0116, 0);
+       cit_write_reg(gspca_dev, 0x0060, 0x0116);
+       cit_write_reg(gspca_dev, 0x0002, 0x0112);
+       cit_write_reg(gspca_dev, 0x00bc, 0x012c);
+       cit_write_reg(gspca_dev, 0x0008, 0x012b);
+       cit_write_reg(gspca_dev, 0x0000, 0x0108);
+       cit_write_reg(gspca_dev, 0x0001, 0x0133);
+       cit_write_reg(gspca_dev, 0x0001, 0x0102);
+       switch (gspca_dev->width) {
+       case 176: /* 176x144 */
+               cit_write_reg(gspca_dev, 0x002c, 0x0103);       /* All except 320x240 */
+               cit_write_reg(gspca_dev, 0x0000, 0x0104);       /* Same */
+               cit_write_reg(gspca_dev, 0x0024, 0x0105);       /* 176x144, 352x288 */
+               cit_write_reg(gspca_dev, 0x00b9, 0x010a);       /* Unique to this mode */
+               cit_write_reg(gspca_dev, 0x0038, 0x0119);       /* Unique to this mode */
+               /* TESTME HDG: this does not seem right
+                  (it is 2 for all other resolutions) */
+               sd->sof_len = 10;
+               break;
+       case 320: /* 320x240 */
+               cit_write_reg(gspca_dev, 0x0028, 0x0103);       /* Unique to this mode */
+               cit_write_reg(gspca_dev, 0x0000, 0x0104);       /* Same */
+               cit_write_reg(gspca_dev, 0x001e, 0x0105);       /* 320x240, 352x240 */
+               cit_write_reg(gspca_dev, 0x0039, 0x010a);       /* All except 176x144 */
+               cit_write_reg(gspca_dev, 0x0070, 0x0119);       /* All except 176x144 */
+               sd->sof_len = 2;
+               break;
+       /* case VIDEOSIZE_352x240: */
+               cit_write_reg(gspca_dev, 0x002c, 0x0103);       /* All except 320x240 */
+               cit_write_reg(gspca_dev, 0x0000, 0x0104);       /* Same */
+               cit_write_reg(gspca_dev, 0x001e, 0x0105);       /* 320x240, 352x240 */
+               cit_write_reg(gspca_dev, 0x0039, 0x010a);       /* All except 176x144 */
+               cit_write_reg(gspca_dev, 0x0070, 0x0119);       /* All except 176x144 */
+               sd->sof_len = 2;
+               break;
+       case 352: /* 352x288 */
+               cit_write_reg(gspca_dev, 0x002c, 0x0103);       /* All except 320x240 */
+               cit_write_reg(gspca_dev, 0x0000, 0x0104);       /* Same */
+               cit_write_reg(gspca_dev, 0x0024, 0x0105);       /* 176x144, 352x288 */
+               cit_write_reg(gspca_dev, 0x0039, 0x010a);       /* All except 176x144 */
+               cit_write_reg(gspca_dev, 0x0070, 0x0119);       /* All except 176x144 */
+               sd->sof_len = 2;
+               break;
+       }
+
+       cit_write_reg(gspca_dev, 0x0000, 0x0100);       /* LED on */
+
+       switch (gspca_dev->width) {
+       case 176: /* 176x144 */
+               cit_write_reg(gspca_dev, 0x0050, 0x0111);
+               cit_write_reg(gspca_dev, 0x00d0, 0x0111);
+               break;
+       case 320: /* 320x240 */
+       case 352: /* 352x288 */
+               cit_write_reg(gspca_dev, 0x0040, 0x0111);
+               cit_write_reg(gspca_dev, 0x00c0, 0x0111);
+               break;
+       }
+       cit_write_reg(gspca_dev, 0x009b, 0x010f);
+       cit_write_reg(gspca_dev, 0x00bb, 0x010f);
+
+       /*
+        * Hardware settings, may affect CMOS sensor; not user controls!
+        * -------------------------------------------------------------
+        * 0x0004: no effect
+        * 0x0006: hardware effect
+        * 0x0008: no effect
+        * 0x000a: stops video stream, probably important h/w setting
+        * 0x000c: changes color in hardware manner (not user setting)
+        * 0x0012: changes number of colors (does not affect speed)
+        * 0x002a: no effect
+        * 0x002c: hardware setting (related to scan lines)
+        * 0x002e: stops video stream, probably important h/w setting
+        */
+       cit_model2_Packet1(gspca_dev, 0x000a, 0x005c);
+       cit_model2_Packet1(gspca_dev, 0x0004, 0x0000);
+       cit_model2_Packet1(gspca_dev, 0x0006, 0x00fb);
+       cit_model2_Packet1(gspca_dev, 0x0008, 0x0000);
+       cit_model2_Packet1(gspca_dev, 0x000c, 0x0009);
+       cit_model2_Packet1(gspca_dev, 0x0012, 0x000a);
+       cit_model2_Packet1(gspca_dev, 0x002a, 0x0000);
+       cit_model2_Packet1(gspca_dev, 0x002c, 0x0000);
+       cit_model2_Packet1(gspca_dev, 0x002e, 0x0008);
+
+       /*
+        * Function 0x0030 pops up all over the place. Apparently
+        * it is a hardware control register, with every bit assigned to
+        * do something.
+        */
+       cit_model2_Packet1(gspca_dev, 0x0030, 0x0000);
+
+       /*
+        * Magic control of CMOS sensor. Only lower values like
+        * 0-3 work, and picture shifts left or right. Don't change.
+        */
+       switch (gspca_dev->width) {
+       case 176: /* 176x144 */
+               cit_model2_Packet1(gspca_dev, 0x0014, 0x0002);
+               cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */
+               cit_model2_Packet1(gspca_dev, 0x0018, 0x004a); /* Another hardware setting */
+               clock_div = 6;
+               break;
+       case 320: /* 320x240 */
+               cit_model2_Packet1(gspca_dev, 0x0014, 0x0009);
+               cit_model2_Packet1(gspca_dev, 0x0016, 0x0005); /* Horizontal shift */
+               cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Another hardware setting */
+               clock_div = 8;
+               break;
+       /* case VIDEOSIZE_352x240: */
+               /* This mode doesn't work as Windows programs it; changed to work */
+               cit_model2_Packet1(gspca_dev, 0x0014, 0x0009); /* Windows sets this to 8 */
+               cit_model2_Packet1(gspca_dev, 0x0016, 0x0003); /* Horizontal shift */
+               cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Windows sets this to 0x0045 */
+               clock_div = 10;
+               break;
+       case 352: /* 352x288 */
+               cit_model2_Packet1(gspca_dev, 0x0014, 0x0003);
+               cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */
+               cit_model2_Packet1(gspca_dev, 0x0018, 0x004a); /* Another hardware setting */
+               clock_div = 16;
+               break;
+       }
+
+       /* TESTME These are handled through controls
+          KEEP until someone can test leaving this out is ok */
+       if (0)
+               cit_model2_Packet1(gspca_dev, 0x001a, 0x005a);
+
+       /*
+        * We have our own frame rate setting varying from 0 (slowest) to 6
+        * (fastest). The camera model 2 allows frame rate in range [0..0x1F]
+        # where 0 is also the slowest setting. However for all practical
+        # reasons high settings make no sense because USB is not fast enough
+        # to support high FPS. Be aware that the picture datastream will be
+        # severely disrupted if you ask for frame rate faster than allowed
+        # for the video size - see below:
+        *
+        * Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz):
+        * -----------------------------------------------------------------
+        * 176x144: [6..31]
+        * 320x240: [8..31]
+        * 352x240: [10..31]
+        * 352x288: [16..31] I have to raise lower threshold for stability...
+        *
+        * As usual, slower FPS provides better sensitivity.
+        */
+       cit_model2_Packet1(gspca_dev, 0x001c, clock_div);
+
+       /*
+        * This setting does not visibly affect pictures; left it here
+        * because it was present in Windows USB data stream. This function
+        * does not allow arbitrary values and apparently is a bit mask, to
+        * be activated only at appropriate time. Don't change it randomly!
+        */
+       switch (gspca_dev->width) {
+       case 176: /* 176x144 */
+               cit_model2_Packet1(gspca_dev, 0x0026, 0x00c2);
+               break;
+       case 320: /* 320x240 */
+               cit_model2_Packet1(gspca_dev, 0x0026, 0x0044);
+               break;
+       /* case VIDEOSIZE_352x240: */
+               cit_model2_Packet1(gspca_dev, 0x0026, 0x0046);
+               break;
+       case 352: /* 352x288 */
+               cit_model2_Packet1(gspca_dev, 0x0026, 0x0048);
+               break;
+       }
+
+       cit_model2_Packet1(gspca_dev, 0x0028, v4l2_ctrl_g_ctrl(sd->lighting));
+       /* model2 cannot change the backlight compensation while streaming */
+       v4l2_ctrl_grab(sd->lighting, true);
+
+       /* color balance rg2 */
+       cit_model2_Packet1(gspca_dev, 0x001e, 0x002f);
+       /* saturation */
+       cit_model2_Packet1(gspca_dev, 0x0020, 0x0034);
+       /* color balance yb */
+       cit_model2_Packet1(gspca_dev, 0x0022, 0x00a0);
+
+       /* Hardware control command */
+       cit_model2_Packet1(gspca_dev, 0x0030, 0x0004);
+
+       return 0;
+}
+
+static int cit_start_model3(struct gspca_dev *gspca_dev)
+{
+       const unsigned short compression = 0; /* 0=none, 7=best frame rate */
+       int i, clock_div = 0;
+
+       /* HDG not in ibmcam driver, added to see if it helps with
+          auto-detecting between model3 and ibm netcamera pro */
+       cit_read_reg(gspca_dev, 0x128, 1);
+
+       cit_write_reg(gspca_dev, 0x0000, 0x0100);
+       cit_read_reg(gspca_dev, 0x0116, 0);
+       cit_write_reg(gspca_dev, 0x0060, 0x0116);
+       cit_write_reg(gspca_dev, 0x0002, 0x0112);
+       cit_write_reg(gspca_dev, 0x0000, 0x0123);
+       cit_write_reg(gspca_dev, 0x0001, 0x0117);
+       cit_write_reg(gspca_dev, 0x0040, 0x0108);
+       cit_write_reg(gspca_dev, 0x0019, 0x012c);
+       cit_write_reg(gspca_dev, 0x0060, 0x0116);
+       cit_write_reg(gspca_dev, 0x0002, 0x0115);
+       cit_write_reg(gspca_dev, 0x0003, 0x0115);
+       cit_read_reg(gspca_dev, 0x0115, 0);
+       cit_write_reg(gspca_dev, 0x000b, 0x0115);
+
+       /* TESTME HDG not in ibmcam driver, added to see if it helps with
+          auto-detecting between model3 and ibm netcamera pro */
+       if (0) {
+               cit_write_reg(gspca_dev, 0x0078, 0x012d);
+               cit_write_reg(gspca_dev, 0x0001, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x0079, 0x012d);
+               cit_write_reg(gspca_dev, 0x00ff, 0x0130);
+               cit_write_reg(gspca_dev, 0xcd41, 0x0124);
+               cit_write_reg(gspca_dev, 0xfffa, 0x0124);
+               cit_read_reg(gspca_dev, 0x0126, 1);
+       }
+
+       cit_model3_Packet1(gspca_dev, 0x000a, 0x0040);
+       cit_model3_Packet1(gspca_dev, 0x000b, 0x00f6);
+       cit_model3_Packet1(gspca_dev, 0x000c, 0x0002);
+       cit_model3_Packet1(gspca_dev, 0x000d, 0x0020);
+       cit_model3_Packet1(gspca_dev, 0x000e, 0x0033);
+       cit_model3_Packet1(gspca_dev, 0x000f, 0x0007);
+       cit_model3_Packet1(gspca_dev, 0x0010, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0011, 0x0070);
+       cit_model3_Packet1(gspca_dev, 0x0012, 0x0030);
+       cit_model3_Packet1(gspca_dev, 0x0013, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0014, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x0015, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x0016, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x0017, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x0018, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x001e, 0x00c3);
+       cit_model3_Packet1(gspca_dev, 0x0020, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0028, 0x0010);
+       cit_model3_Packet1(gspca_dev, 0x0029, 0x0054);
+       cit_model3_Packet1(gspca_dev, 0x002a, 0x0013);
+       cit_model3_Packet1(gspca_dev, 0x002b, 0x0007);
+       cit_model3_Packet1(gspca_dev, 0x002d, 0x0028);
+       cit_model3_Packet1(gspca_dev, 0x002e, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0031, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0032, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0033, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0034, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0035, 0x0038);
+       cit_model3_Packet1(gspca_dev, 0x003a, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x003c, 0x001e);
+       cit_model3_Packet1(gspca_dev, 0x003f, 0x000a);
+       cit_model3_Packet1(gspca_dev, 0x0041, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0046, 0x003f);
+       cit_model3_Packet1(gspca_dev, 0x0047, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0050, 0x0005);
+       cit_model3_Packet1(gspca_dev, 0x0052, 0x001a);
+       cit_model3_Packet1(gspca_dev, 0x0053, 0x0003);
+       cit_model3_Packet1(gspca_dev, 0x005a, 0x006b);
+       cit_model3_Packet1(gspca_dev, 0x005d, 0x001e);
+       cit_model3_Packet1(gspca_dev, 0x005e, 0x0030);
+       cit_model3_Packet1(gspca_dev, 0x005f, 0x0041);
+       cit_model3_Packet1(gspca_dev, 0x0064, 0x0008);
+       cit_model3_Packet1(gspca_dev, 0x0065, 0x0015);
+       cit_model3_Packet1(gspca_dev, 0x0068, 0x000f);
+       cit_model3_Packet1(gspca_dev, 0x0079, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x007a, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x007c, 0x003f);
+       cit_model3_Packet1(gspca_dev, 0x0082, 0x000f);
+       cit_model3_Packet1(gspca_dev, 0x0085, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0099, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x009b, 0x0023);
+       cit_model3_Packet1(gspca_dev, 0x009c, 0x0022);
+       cit_model3_Packet1(gspca_dev, 0x009d, 0x0096);
+       cit_model3_Packet1(gspca_dev, 0x009e, 0x0096);
+       cit_model3_Packet1(gspca_dev, 0x009f, 0x000a);
+
+       switch (gspca_dev->width) {
+       case 160:
+               cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
+               cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
+               cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
+               cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
+               cit_write_reg(gspca_dev, 0x0024, 0x010b); /* Differs everywhere */
+               cit_write_reg(gspca_dev, 0x00a9, 0x0119);
+               cit_write_reg(gspca_dev, 0x0016, 0x011b);
+               cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same on 160x120, 320x240 */
+               cit_write_reg(gspca_dev, 0x0003, 0x011e); /* Same on 160x120, 640x480 */
+               cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
+               cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
+               cit_write_reg(gspca_dev, 0x0018, 0x0102);
+               cit_write_reg(gspca_dev, 0x0004, 0x0104);
+               cit_write_reg(gspca_dev, 0x0004, 0x011a);
+               cit_write_reg(gspca_dev, 0x0028, 0x011c);
+               cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
+               cit_write_reg(gspca_dev, 0x0000, 0x0118);
+               cit_write_reg(gspca_dev, 0x0000, 0x0132);
+               cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
+               cit_write_reg(gspca_dev, compression, 0x0109);
+               clock_div = 3;
+               break;
+       case 320:
+               cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
+               cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
+               cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
+               cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
+               cit_write_reg(gspca_dev, 0x0028, 0x010b); /* Differs everywhere */
+               cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same */
+               cit_write_reg(gspca_dev, 0x0000, 0x011e);
+               cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
+               cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
+               /* 4 commands from 160x120 skipped */
+               cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
+               cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
+               cit_write_reg(gspca_dev, compression, 0x0109);
+               cit_write_reg(gspca_dev, 0x00d9, 0x0119);
+               cit_write_reg(gspca_dev, 0x0006, 0x011b);
+               cit_write_reg(gspca_dev, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
+               cit_write_reg(gspca_dev, 0x0010, 0x0104);
+               cit_write_reg(gspca_dev, 0x0004, 0x011a);
+               cit_write_reg(gspca_dev, 0x003f, 0x011c);
+               cit_write_reg(gspca_dev, 0x001c, 0x0118);
+               cit_write_reg(gspca_dev, 0x0000, 0x0132);
+               clock_div = 5;
+               break;
+       case 640:
+               cit_write_reg(gspca_dev, 0x00f0, 0x0105);
+               cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
+               cit_write_reg(gspca_dev, 0x0038, 0x010b); /* Differs everywhere */
+               cit_write_reg(gspca_dev, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */
+               cit_write_reg(gspca_dev, 0x0006, 0x011b); /* Same on 320x240, 640x480 */
+               cit_write_reg(gspca_dev, 0x0004, 0x011d); /* NC */
+               cit_write_reg(gspca_dev, 0x0003, 0x011e); /* Same on 160x120, 640x480 */
+               cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
+               cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
+               cit_write_reg(gspca_dev, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
+               cit_write_reg(gspca_dev, 0x0016, 0x0104); /* NC */
+               cit_write_reg(gspca_dev, 0x0004, 0x011a); /* Same on 320x240, 640x480 */
+               cit_write_reg(gspca_dev, 0x003f, 0x011c); /* Same on 320x240, 640x480 */
+               cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
+               cit_write_reg(gspca_dev, 0x001c, 0x0118); /* Same on 320x240, 640x480 */
+               cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
+               cit_write_reg(gspca_dev, compression, 0x0109);
+               cit_write_reg(gspca_dev, 0x0040, 0x0101);
+               cit_write_reg(gspca_dev, 0x0040, 0x0103);
+               cit_write_reg(gspca_dev, 0x0000, 0x0132); /* Same on 320x240, 640x480 */
+               clock_div = 7;
+               break;
+       }
+
+       cit_model3_Packet1(gspca_dev, 0x007e, 0x000e);  /* Hue */
+       cit_model3_Packet1(gspca_dev, 0x0036, 0x0011);  /* Brightness */
+       cit_model3_Packet1(gspca_dev, 0x0060, 0x0002);  /* Sharpness */
+       cit_model3_Packet1(gspca_dev, 0x0061, 0x0004);  /* Sharpness */
+       cit_model3_Packet1(gspca_dev, 0x0062, 0x0005);  /* Sharpness */
+       cit_model3_Packet1(gspca_dev, 0x0063, 0x0014);  /* Sharpness */
+       cit_model3_Packet1(gspca_dev, 0x0096, 0x00a0);  /* Red sharpness */
+       cit_model3_Packet1(gspca_dev, 0x0097, 0x0096);  /* Blue sharpness */
+       cit_model3_Packet1(gspca_dev, 0x0067, 0x0001);  /* Contrast */
+       cit_model3_Packet1(gspca_dev, 0x005b, 0x000c);  /* Contrast */
+       cit_model3_Packet1(gspca_dev, 0x005c, 0x0016);  /* Contrast */
+       cit_model3_Packet1(gspca_dev, 0x0098, 0x000b);
+       cit_model3_Packet1(gspca_dev, 0x002c, 0x0003);  /* Was 1, broke 640x480 */
+       cit_model3_Packet1(gspca_dev, 0x002f, 0x002a);
+       cit_model3_Packet1(gspca_dev, 0x0030, 0x0029);
+       cit_model3_Packet1(gspca_dev, 0x0037, 0x0002);
+       cit_model3_Packet1(gspca_dev, 0x0038, 0x0059);
+       cit_model3_Packet1(gspca_dev, 0x003d, 0x002e);
+       cit_model3_Packet1(gspca_dev, 0x003e, 0x0028);
+       cit_model3_Packet1(gspca_dev, 0x0078, 0x0005);
+       cit_model3_Packet1(gspca_dev, 0x007b, 0x0011);
+       cit_model3_Packet1(gspca_dev, 0x007d, 0x004b);
+       cit_model3_Packet1(gspca_dev, 0x007f, 0x0022);
+       cit_model3_Packet1(gspca_dev, 0x0080, 0x000c);
+       cit_model3_Packet1(gspca_dev, 0x0081, 0x000b);
+       cit_model3_Packet1(gspca_dev, 0x0083, 0x00fd);
+       cit_model3_Packet1(gspca_dev, 0x0086, 0x000b);
+       cit_model3_Packet1(gspca_dev, 0x0087, 0x000b);
+       cit_model3_Packet1(gspca_dev, 0x007e, 0x000e);
+       cit_model3_Packet1(gspca_dev, 0x0096, 0x00a0);  /* Red sharpness */
+       cit_model3_Packet1(gspca_dev, 0x0097, 0x0096);  /* Blue sharpness */
+       cit_model3_Packet1(gspca_dev, 0x0098, 0x000b);
+
+       /* FIXME we should probably use cit_get_clock_div() here (in
+          combination with isoc negotiation using the programmable isoc size)
+          like with the IBM netcam pro). */
+       cit_write_reg(gspca_dev, clock_div, 0x0111); /* Clock Divider */
+
+       switch (gspca_dev->width) {
+       case 160:
+               cit_model3_Packet1(gspca_dev, 0x001f, 0x0000); /* Same */
+               cit_model3_Packet1(gspca_dev, 0x0039, 0x001f); /* Same */
+               cit_model3_Packet1(gspca_dev, 0x003b, 0x003c); /* Same */
+               cit_model3_Packet1(gspca_dev, 0x0040, 0x000a);
+               cit_model3_Packet1(gspca_dev, 0x0051, 0x000a);
+               break;
+       case 320:
+               cit_model3_Packet1(gspca_dev, 0x001f, 0x0000); /* Same */
+               cit_model3_Packet1(gspca_dev, 0x0039, 0x001f); /* Same */
+               cit_model3_Packet1(gspca_dev, 0x003b, 0x003c); /* Same */
+               cit_model3_Packet1(gspca_dev, 0x0040, 0x0008);
+               cit_model3_Packet1(gspca_dev, 0x0051, 0x000b);
+               break;
+       case 640:
+               cit_model3_Packet1(gspca_dev, 0x001f, 0x0002);  /* !Same */
+               cit_model3_Packet1(gspca_dev, 0x0039, 0x003e);  /* !Same */
+               cit_model3_Packet1(gspca_dev, 0x0040, 0x0008);
+               cit_model3_Packet1(gspca_dev, 0x0051, 0x000a);
+               break;
+       }
+
+/*     if (sd->input_index) { */
+       if (rca_input) {
+               for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) {
+                       if (rca_initdata[i][0])
+                               cit_read_reg(gspca_dev, rca_initdata[i][2], 0);
+                       else
+                               cit_write_reg(gspca_dev, rca_initdata[i][1],
+                                             rca_initdata[i][2]);
+               }
+       }
+
+       return 0;
+}
+
+static int cit_start_model4(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       cit_write_reg(gspca_dev, 0x0000, 0x0100);
+       cit_write_reg(gspca_dev, 0x00c0, 0x0111);
+       cit_write_reg(gspca_dev, 0x00bc, 0x012c);
+       cit_write_reg(gspca_dev, 0x0080, 0x012b);
+       cit_write_reg(gspca_dev, 0x0000, 0x0108);
+       cit_write_reg(gspca_dev, 0x0001, 0x0133);
+       cit_write_reg(gspca_dev, 0x009b, 0x010f);
+       cit_write_reg(gspca_dev, 0x00bb, 0x010f);
+       cit_model4_Packet1(gspca_dev, 0x0038, 0x0000);
+       cit_model4_Packet1(gspca_dev, 0x000a, 0x005c);
+
+       cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+       cit_write_reg(gspca_dev, 0x0004, 0x012f);
+       cit_write_reg(gspca_dev, 0xd141, 0x0124);
+       cit_write_reg(gspca_dev, 0x0000, 0x0127);
+       cit_write_reg(gspca_dev, 0x00fb, 0x012e);
+       cit_write_reg(gspca_dev, 0x0000, 0x0130);
+       cit_write_reg(gspca_dev, 0x8a28, 0x0124);
+       cit_write_reg(gspca_dev, 0x00aa, 0x012f);
+       cit_write_reg(gspca_dev, 0xd055, 0x0124);
+       cit_write_reg(gspca_dev, 0x000c, 0x0127);
+       cit_write_reg(gspca_dev, 0x0009, 0x012e);
+       cit_write_reg(gspca_dev, 0xaa28, 0x0124);
+
+       cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+       cit_write_reg(gspca_dev, 0x0012, 0x012f);
+       cit_write_reg(gspca_dev, 0xd141, 0x0124);
+       cit_write_reg(gspca_dev, 0x0008, 0x0127);
+       cit_write_reg(gspca_dev, 0x00aa, 0x0130);
+       cit_write_reg(gspca_dev, 0x82a8, 0x0124);
+       cit_write_reg(gspca_dev, 0x002a, 0x012d);
+       cit_write_reg(gspca_dev, 0x0000, 0x012f);
+       cit_write_reg(gspca_dev, 0xd145, 0x0124);
+       cit_write_reg(gspca_dev, 0xfffa, 0x0124);
+       cit_model4_Packet1(gspca_dev, 0x0034, 0x0000);
+
+       switch (gspca_dev->width) {
+       case 128: /* 128x96 */
+               cit_write_reg(gspca_dev, 0x0070, 0x0119);
+               cit_write_reg(gspca_dev, 0x00d0, 0x0111);
+               cit_write_reg(gspca_dev, 0x0039, 0x010a);
+               cit_write_reg(gspca_dev, 0x0001, 0x0102);
+               cit_write_reg(gspca_dev, 0x0028, 0x0103);
+               cit_write_reg(gspca_dev, 0x0000, 0x0104);
+               cit_write_reg(gspca_dev, 0x001e, 0x0105);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x0016, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x000a, 0x0127);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
+               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
+               cit_write_reg(gspca_dev, 0x0014, 0x012d);
+               cit_write_reg(gspca_dev, 0x0008, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012e);
+               cit_write_reg(gspca_dev, 0x001a, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
+               cit_write_reg(gspca_dev, 0x005a, 0x012d);
+               cit_write_reg(gspca_dev, 0x9545, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0127);
+               cit_write_reg(gspca_dev, 0x0018, 0x012e);
+               cit_write_reg(gspca_dev, 0x0043, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012f);
+               cit_write_reg(gspca_dev, 0xd055, 0x0124);
+               cit_write_reg(gspca_dev, 0x001c, 0x0127);
+               cit_write_reg(gspca_dev, 0x00eb, 0x012e);
+               cit_write_reg(gspca_dev, 0xaa28, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x0032, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x0000, 0x0127);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
+               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
+               cit_write_reg(gspca_dev, 0x0036, 0x012d);
+               cit_write_reg(gspca_dev, 0x0008, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0xfffa, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x001e, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x0017, 0x0127);
+               cit_write_reg(gspca_dev, 0x0013, 0x012e);
+               cit_write_reg(gspca_dev, 0x0031, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
+               cit_write_reg(gspca_dev, 0x0017, 0x012d);
+               cit_write_reg(gspca_dev, 0x0078, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0x0000, 0x0127);
+               cit_write_reg(gspca_dev, 0xfea8, 0x0124);
+               sd->sof_len = 2;
+               break;
+       case 160: /* 160x120 */
+               cit_write_reg(gspca_dev, 0x0038, 0x0119);
+               cit_write_reg(gspca_dev, 0x00d0, 0x0111);
+               cit_write_reg(gspca_dev, 0x00b9, 0x010a);
+               cit_write_reg(gspca_dev, 0x0001, 0x0102);
+               cit_write_reg(gspca_dev, 0x0028, 0x0103);
+               cit_write_reg(gspca_dev, 0x0000, 0x0104);
+               cit_write_reg(gspca_dev, 0x001e, 0x0105);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x0016, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x000b, 0x0127);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
+               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
+               cit_write_reg(gspca_dev, 0x0014, 0x012d);
+               cit_write_reg(gspca_dev, 0x0008, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012e);
+               cit_write_reg(gspca_dev, 0x001a, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
+               cit_write_reg(gspca_dev, 0x005a, 0x012d);
+               cit_write_reg(gspca_dev, 0x9545, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0127);
+               cit_write_reg(gspca_dev, 0x0018, 0x012e);
+               cit_write_reg(gspca_dev, 0x0043, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012f);
+               cit_write_reg(gspca_dev, 0xd055, 0x0124);
+               cit_write_reg(gspca_dev, 0x001c, 0x0127);
+               cit_write_reg(gspca_dev, 0x00c7, 0x012e);
+               cit_write_reg(gspca_dev, 0xaa28, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x0032, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x0025, 0x0127);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
+               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
+               cit_write_reg(gspca_dev, 0x0036, 0x012d);
+               cit_write_reg(gspca_dev, 0x0008, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0xfffa, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x001e, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x0048, 0x0127);
+               cit_write_reg(gspca_dev, 0x0035, 0x012e);
+               cit_write_reg(gspca_dev, 0x00d0, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
+               cit_write_reg(gspca_dev, 0x0048, 0x012d);
+               cit_write_reg(gspca_dev, 0x0090, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0x0001, 0x0127);
+               cit_write_reg(gspca_dev, 0xfea8, 0x0124);
+               sd->sof_len = 2;
+               break;
+       case 176: /* 176x144 */
+               cit_write_reg(gspca_dev, 0x0038, 0x0119);
+               cit_write_reg(gspca_dev, 0x00d0, 0x0111);
+               cit_write_reg(gspca_dev, 0x00b9, 0x010a);
+               cit_write_reg(gspca_dev, 0x0001, 0x0102);
+               cit_write_reg(gspca_dev, 0x002c, 0x0103);
+               cit_write_reg(gspca_dev, 0x0000, 0x0104);
+               cit_write_reg(gspca_dev, 0x0024, 0x0105);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x0016, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x0007, 0x0127);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
+               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
+               cit_write_reg(gspca_dev, 0x0014, 0x012d);
+               cit_write_reg(gspca_dev, 0x0001, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012e);
+               cit_write_reg(gspca_dev, 0x001a, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
+               cit_write_reg(gspca_dev, 0x005e, 0x012d);
+               cit_write_reg(gspca_dev, 0x9545, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0127);
+               cit_write_reg(gspca_dev, 0x0018, 0x012e);
+               cit_write_reg(gspca_dev, 0x0049, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012f);
+               cit_write_reg(gspca_dev, 0xd055, 0x0124);
+               cit_write_reg(gspca_dev, 0x001c, 0x0127);
+               cit_write_reg(gspca_dev, 0x00c7, 0x012e);
+               cit_write_reg(gspca_dev, 0xaa28, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x0032, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x0028, 0x0127);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
+               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
+               cit_write_reg(gspca_dev, 0x0036, 0x012d);
+               cit_write_reg(gspca_dev, 0x0008, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0xfffa, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x001e, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x0010, 0x0127);
+               cit_write_reg(gspca_dev, 0x0013, 0x012e);
+               cit_write_reg(gspca_dev, 0x002a, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
+               cit_write_reg(gspca_dev, 0x0010, 0x012d);
+               cit_write_reg(gspca_dev, 0x006d, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0x0001, 0x0127);
+               cit_write_reg(gspca_dev, 0xfea8, 0x0124);
+               /* TESTME HDG: this does not seem right
+                  (it is 2 for all other resolutions) */
+               sd->sof_len = 10;
+               break;
+       case 320: /* 320x240 */
+               cit_write_reg(gspca_dev, 0x0070, 0x0119);
+               cit_write_reg(gspca_dev, 0x00d0, 0x0111);
+               cit_write_reg(gspca_dev, 0x0039, 0x010a);
+               cit_write_reg(gspca_dev, 0x0001, 0x0102);
+               cit_write_reg(gspca_dev, 0x0028, 0x0103);
+               cit_write_reg(gspca_dev, 0x0000, 0x0104);
+               cit_write_reg(gspca_dev, 0x001e, 0x0105);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x0016, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x000a, 0x0127);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
+               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
+               cit_write_reg(gspca_dev, 0x0014, 0x012d);
+               cit_write_reg(gspca_dev, 0x0008, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012e);
+               cit_write_reg(gspca_dev, 0x001a, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
+               cit_write_reg(gspca_dev, 0x005a, 0x012d);
+               cit_write_reg(gspca_dev, 0x9545, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0127);
+               cit_write_reg(gspca_dev, 0x0018, 0x012e);
+               cit_write_reg(gspca_dev, 0x0043, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012f);
+               cit_write_reg(gspca_dev, 0xd055, 0x0124);
+               cit_write_reg(gspca_dev, 0x001c, 0x0127);
+               cit_write_reg(gspca_dev, 0x00eb, 0x012e);
+               cit_write_reg(gspca_dev, 0xaa28, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x0032, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x0000, 0x0127);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
+               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
+               cit_write_reg(gspca_dev, 0x0036, 0x012d);
+               cit_write_reg(gspca_dev, 0x0008, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0xfffa, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x001e, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x0017, 0x0127);
+               cit_write_reg(gspca_dev, 0x0013, 0x012e);
+               cit_write_reg(gspca_dev, 0x0031, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
+               cit_write_reg(gspca_dev, 0x0017, 0x012d);
+               cit_write_reg(gspca_dev, 0x0078, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0x0000, 0x0127);
+               cit_write_reg(gspca_dev, 0xfea8, 0x0124);
+               sd->sof_len = 2;
+               break;
+       case 352: /* 352x288 */
+               cit_write_reg(gspca_dev, 0x0070, 0x0119);
+               cit_write_reg(gspca_dev, 0x00c0, 0x0111);
+               cit_write_reg(gspca_dev, 0x0039, 0x010a);
+               cit_write_reg(gspca_dev, 0x0001, 0x0102);
+               cit_write_reg(gspca_dev, 0x002c, 0x0103);
+               cit_write_reg(gspca_dev, 0x0000, 0x0104);
+               cit_write_reg(gspca_dev, 0x0024, 0x0105);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x0016, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x0006, 0x0127);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
+               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
+               cit_write_reg(gspca_dev, 0x0014, 0x012d);
+               cit_write_reg(gspca_dev, 0x0002, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012e);
+               cit_write_reg(gspca_dev, 0x001a, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
+               cit_write_reg(gspca_dev, 0x005e, 0x012d);
+               cit_write_reg(gspca_dev, 0x9545, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0127);
+               cit_write_reg(gspca_dev, 0x0018, 0x012e);
+               cit_write_reg(gspca_dev, 0x0049, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012f);
+               cit_write_reg(gspca_dev, 0xd055, 0x0124);
+               cit_write_reg(gspca_dev, 0x001c, 0x0127);
+               cit_write_reg(gspca_dev, 0x00cf, 0x012e);
+               cit_write_reg(gspca_dev, 0xaa28, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x0032, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x0000, 0x0127);
+               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
+               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
+               cit_write_reg(gspca_dev, 0x0036, 0x012d);
+               cit_write_reg(gspca_dev, 0x0008, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0xfffa, 0x0124);
+               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
+               cit_write_reg(gspca_dev, 0x001e, 0x012f);
+               cit_write_reg(gspca_dev, 0xd141, 0x0124);
+               cit_write_reg(gspca_dev, 0x0010, 0x0127);
+               cit_write_reg(gspca_dev, 0x0013, 0x012e);
+               cit_write_reg(gspca_dev, 0x0025, 0x0130);
+               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
+               cit_write_reg(gspca_dev, 0x0010, 0x012d);
+               cit_write_reg(gspca_dev, 0x0048, 0x012f);
+               cit_write_reg(gspca_dev, 0xd145, 0x0124);
+               cit_write_reg(gspca_dev, 0x0000, 0x0127);
+               cit_write_reg(gspca_dev, 0xfea8, 0x0124);
+               sd->sof_len = 2;
+               break;
+       }
+
+       cit_model4_Packet1(gspca_dev, 0x0038, 0x0004);
+
+       return 0;
+}
+
+static int cit_start_ibm_netcam_pro(struct gspca_dev *gspca_dev)
+{
+       const unsigned short compression = 0; /* 0=none, 7=best frame rate */
+       int i, clock_div;
+
+       clock_div = cit_get_clock_div(gspca_dev);
+       if (clock_div < 0)
+               return clock_div;
+
+       cit_write_reg(gspca_dev, 0x0003, 0x0133);
+       cit_write_reg(gspca_dev, 0x0000, 0x0117);
+       cit_write_reg(gspca_dev, 0x0008, 0x0123);
+       cit_write_reg(gspca_dev, 0x0000, 0x0100);
+       cit_write_reg(gspca_dev, 0x0060, 0x0116);
+       /* cit_write_reg(gspca_dev, 0x0002, 0x0112); see sd_stop0 */
+       cit_write_reg(gspca_dev, 0x0000, 0x0133);
+       cit_write_reg(gspca_dev, 0x0000, 0x0123);
+       cit_write_reg(gspca_dev, 0x0001, 0x0117);
+       cit_write_reg(gspca_dev, 0x0040, 0x0108);
+       cit_write_reg(gspca_dev, 0x0019, 0x012c);
+       cit_write_reg(gspca_dev, 0x0060, 0x0116);
+       /* cit_write_reg(gspca_dev, 0x000b, 0x0115); see sd_stop0 */
+
+       cit_model3_Packet1(gspca_dev, 0x0049, 0x0000);
+
+       cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
+       cit_write_reg(gspca_dev, 0x003a, 0x0102); /* Hstart */
+       cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
+       cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
+       cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
+       cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same on 160x120, 320x240 */
+       cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
+       cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
+       cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
+
+       switch (gspca_dev->width) {
+       case 160: /* 160x120 */
+               cit_write_reg(gspca_dev, 0x0024, 0x010b);
+               cit_write_reg(gspca_dev, 0x0089, 0x0119);
+               cit_write_reg(gspca_dev, 0x000a, 0x011b);
+               cit_write_reg(gspca_dev, 0x0003, 0x011e);
+               cit_write_reg(gspca_dev, 0x0007, 0x0104);
+               cit_write_reg(gspca_dev, 0x0009, 0x011a);
+               cit_write_reg(gspca_dev, 0x008b, 0x011c);
+               cit_write_reg(gspca_dev, 0x0008, 0x0118);
+               cit_write_reg(gspca_dev, 0x0000, 0x0132);
+               break;
+       case 320: /* 320x240 */
+               cit_write_reg(gspca_dev, 0x0028, 0x010b);
+               cit_write_reg(gspca_dev, 0x00d9, 0x0119);
+               cit_write_reg(gspca_dev, 0x0006, 0x011b);
+               cit_write_reg(gspca_dev, 0x0000, 0x011e);
+               cit_write_reg(gspca_dev, 0x000e, 0x0104);
+               cit_write_reg(gspca_dev, 0x0004, 0x011a);
+               cit_write_reg(gspca_dev, 0x003f, 0x011c);
+               cit_write_reg(gspca_dev, 0x000c, 0x0118);
+               cit_write_reg(gspca_dev, 0x0000, 0x0132);
+               break;
+       }
+
+       cit_model3_Packet1(gspca_dev, 0x0019, 0x0031);
+       cit_model3_Packet1(gspca_dev, 0x001a, 0x0003);
+       cit_model3_Packet1(gspca_dev, 0x001b, 0x0038);
+       cit_model3_Packet1(gspca_dev, 0x001c, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0024, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x0027, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x002a, 0x0004);
+       cit_model3_Packet1(gspca_dev, 0x0035, 0x000b);
+       cit_model3_Packet1(gspca_dev, 0x003f, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x0044, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x0054, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00c4, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00e7, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x00e9, 0x0001);
+       cit_model3_Packet1(gspca_dev, 0x00ee, 0x0000);
+       cit_model3_Packet1(gspca_dev, 0x00f3, 0x00c0);
+
+       cit_write_reg(gspca_dev, compression, 0x0109);
+       cit_write_reg(gspca_dev, clock_div, 0x0111);
+
+/*     if (sd->input_index) { */
+       if (rca_input) {
+               for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) {
+                       if (rca_initdata[i][0])
+                               cit_read_reg(gspca_dev, rca_initdata[i][2], 0);
+                       else
+                               cit_write_reg(gspca_dev, rca_initdata[i][1],
+                                             rca_initdata[i][2]);
+               }
+       }
+
+       return 0;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int packet_size;
+
+       packet_size = cit_get_packet_size(gspca_dev);
+       if (packet_size < 0)
+               return packet_size;
+
+       switch (sd->model) {
+       case CIT_MODEL0:
+               cit_start_model0(gspca_dev);
+               break;
+       case CIT_MODEL1:
+               cit_start_model1(gspca_dev);
+               break;
+       case CIT_MODEL2:
+               cit_start_model2(gspca_dev);
+               break;
+       case CIT_MODEL3:
+               cit_start_model3(gspca_dev);
+               break;
+       case CIT_MODEL4:
+               cit_start_model4(gspca_dev);
+               break;
+       case CIT_IBM_NETCAM_PRO:
+               cit_start_ibm_netcam_pro(gspca_dev);
+               break;
+       }
+
+       /* Program max isoc packet size */
+       cit_write_reg(gspca_dev, packet_size >> 8, 0x0106);
+       cit_write_reg(gspca_dev, packet_size & 0xff, 0x0107);
+
+       cit_restart_stream(gspca_dev);
+
+       return 0;
+}
+
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+       struct usb_host_interface *alt;
+       int max_packet_size;
+
+       switch (gspca_dev->width) {
+       case 160:
+               max_packet_size = 450;
+               break;
+       case 176:
+               max_packet_size = 600;
+               break;
+       default:
+               max_packet_size = 1022;
+               break;
+       }
+
+       /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
+       alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
+       alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size);
+
+       return 0;
+}
+
+static int sd_isoc_nego(struct gspca_dev *gspca_dev)
+{
+       int ret, packet_size, min_packet_size;
+       struct usb_host_interface *alt;
+
+       switch (gspca_dev->width) {
+       case 160:
+               min_packet_size = 200;
+               break;
+       case 176:
+               min_packet_size = 266;
+               break;
+       default:
+               min_packet_size = 400;
+               break;
+       }
+
+       alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
+       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+       if (packet_size <= min_packet_size)
+               return -EIO;
+
+       packet_size -= 100;
+       if (packet_size < min_packet_size)
+               packet_size = min_packet_size;
+       alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
+
+       ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
+       if (ret < 0)
+               pr_err("set alt 1 err %d\n", ret);
+
+       return ret;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+       cit_write_reg(gspca_dev, 0x0000, 0x010c);
+}
+
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* We cannot use gspca_dev->present here as that is not set when
+          sd_init gets called and we get called from sd_init */
+       if (!gspca_dev->dev)
+               return;
+
+       switch (sd->model) {
+       case CIT_MODEL0:
+               /* HDG windows does this, but it causes the cams autogain to
+                  restart from a gain of 0, which does not look good when
+                  changing resolutions. */
+               /* cit_write_reg(gspca_dev, 0x0000, 0x0112); */
+               cit_write_reg(gspca_dev, 0x00c0, 0x0100); /* LED Off */
+               break;
+       case CIT_MODEL1:
+               cit_send_FF_04_02(gspca_dev);
+               cit_read_reg(gspca_dev, 0x0100, 0);
+               cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */
+               break;
+       case CIT_MODEL2:
+               v4l2_ctrl_grab(sd->lighting, false);
+               /* Fall through! */
+       case CIT_MODEL4:
+               cit_model2_Packet1(gspca_dev, 0x0030, 0x0004);
+
+               cit_write_reg(gspca_dev, 0x0080, 0x0100);       /* LED Off */
+               cit_write_reg(gspca_dev, 0x0020, 0x0111);
+               cit_write_reg(gspca_dev, 0x00a0, 0x0111);
+
+               cit_model2_Packet1(gspca_dev, 0x0030, 0x0002);
+
+               cit_write_reg(gspca_dev, 0x0020, 0x0111);
+               cit_write_reg(gspca_dev, 0x0000, 0x0112);
+               break;
+       case CIT_MODEL3:
+               cit_write_reg(gspca_dev, 0x0006, 0x012c);
+               cit_model3_Packet1(gspca_dev, 0x0046, 0x0000);
+               cit_read_reg(gspca_dev, 0x0116, 0);
+               cit_write_reg(gspca_dev, 0x0064, 0x0116);
+               cit_read_reg(gspca_dev, 0x0115, 0);
+               cit_write_reg(gspca_dev, 0x0003, 0x0115);
+               cit_write_reg(gspca_dev, 0x0008, 0x0123);
+               cit_write_reg(gspca_dev, 0x0000, 0x0117);
+               cit_write_reg(gspca_dev, 0x0000, 0x0112);
+               cit_write_reg(gspca_dev, 0x0080, 0x0100);
+               break;
+       case CIT_IBM_NETCAM_PRO:
+               cit_model3_Packet1(gspca_dev, 0x0049, 0x00ff);
+               cit_write_reg(gspca_dev, 0x0006, 0x012c);
+               cit_write_reg(gspca_dev, 0x0000, 0x0116);
+               /* HDG windows does this, but I cannot get the camera
+                  to restart with this without redoing the entire init
+                  sequence which makes switching modes really slow */
+               /* cit_write_reg(gspca_dev, 0x0006, 0x0115); */
+               cit_write_reg(gspca_dev, 0x0008, 0x0123);
+               cit_write_reg(gspca_dev, 0x0000, 0x0117);
+               cit_write_reg(gspca_dev, 0x0003, 0x0133);
+               cit_write_reg(gspca_dev, 0x0000, 0x0111);
+               /* HDG windows does this, but I get a green picture when
+                  restarting the stream after this */
+               /* cit_write_reg(gspca_dev, 0x0000, 0x0112); */
+               cit_write_reg(gspca_dev, 0x00c0, 0x0100);
+               break;
+       }
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       /* If the last button state is pressed, release it now! */
+       if (sd->button_state) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+               input_sync(gspca_dev->input_dev);
+               sd->button_state = 0;
+       }
+#endif
+}
+
+static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       u8 byte3 = 0, byte4 = 0;
+       int i;
+
+       switch (sd->model) {
+       case CIT_MODEL0:
+       case CIT_MODEL1:
+       case CIT_MODEL3:
+       case CIT_IBM_NETCAM_PRO:
+               switch (gspca_dev->width) {
+               case 160: /* 160x120 */
+                       byte3 = 0x02;
+                       byte4 = 0x0a;
+                       break;
+               case 176: /* 176x144 */
+                       byte3 = 0x02;
+                       byte4 = 0x0e;
+                       break;
+               case 320: /* 320x240 */
+                       byte3 = 0x02;
+                       byte4 = 0x08;
+                       break;
+               case 352: /* 352x288 */
+                       byte3 = 0x02;
+                       byte4 = 0x00;
+                       break;
+               case 640:
+                       byte3 = 0x03;
+                       byte4 = 0x08;
+                       break;
+               }
+
+               /* These have a different byte3 */
+               if (sd->model <= CIT_MODEL1)
+                       byte3 = 0x00;
+
+               for (i = 0; i < len; i++) {
+                       /* For this model the SOF always starts at offset 0
+                          so no need to search the entire frame */
+                       if (sd->model == CIT_MODEL0 && sd->sof_read != i)
+                               break;
+
+                       switch (sd->sof_read) {
+                       case 0:
+                               if (data[i] == 0x00)
+                                       sd->sof_read++;
+                               break;
+                       case 1:
+                               if (data[i] == 0xff)
+                                       sd->sof_read++;
+                               else if (data[i] == 0x00)
+                                       sd->sof_read = 1;
+                               else
+                                       sd->sof_read = 0;
+                               break;
+                       case 2:
+                               if (data[i] == byte3)
+                                       sd->sof_read++;
+                               else if (data[i] == 0x00)
+                                       sd->sof_read = 1;
+                               else
+                                       sd->sof_read = 0;
+                               break;
+                       case 3:
+                               if (data[i] == byte4) {
+                                       sd->sof_read = 0;
+                                       return data + i + (sd->sof_len - 3);
+                               }
+                               if (byte3 == 0x00 && data[i] == 0xff)
+                                       sd->sof_read = 2;
+                               else if (data[i] == 0x00)
+                                       sd->sof_read = 1;
+                               else
+                                       sd->sof_read = 0;
+                               break;
+                       }
+               }
+               break;
+       case CIT_MODEL2:
+       case CIT_MODEL4:
+               /* TESTME we need to find a longer sof signature to avoid
+                  false positives */
+               for (i = 0; i < len; i++) {
+                       switch (sd->sof_read) {
+                       case 0:
+                               if (data[i] == 0x00)
+                                       sd->sof_read++;
+                               break;
+                       case 1:
+                               sd->sof_read = 0;
+                               if (data[i] == 0xff) {
+                                       if (i >= 4)
+                                               PDEBUG(D_FRAM,
+                                                      "header found at offset: %d: %02x %02x 00 %02x %02x %02x\n",
+                                                      i - 1,
+                                                      data[i - 4],
+                                                      data[i - 3],
+                                                      data[i],
+                                                      data[i + 1],
+                                                      data[i + 2]);
+                                       else
+                                               PDEBUG(D_FRAM,
+                                                      "header found at offset: %d: 00 %02x %02x %02x\n",
+                                                      i - 1,
+                                                      data[i],
+                                                      data[i + 1],
+                                                      data[i + 2]);
+                                       return data + i + (sd->sof_len - 1);
+                               }
+                               break;
+                       }
+               }
+               break;
+       }
+       return NULL;
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data, int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       unsigned char *sof;
+
+       sof = cit_find_sof(gspca_dev, data, len);
+       if (sof) {
+               int n;
+
+               /* finish decoding current frame */
+               n = sof - data;
+               if (n > sd->sof_len)
+                       n -= sd->sof_len;
+               else
+                       n = 0;
+               gspca_frame_add(gspca_dev, LAST_PACKET,
+                               data, n);
+               gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
+               len -= sof - data;
+               data = sof;
+       }
+
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static void cit_check_button(struct gspca_dev *gspca_dev)
+{
+       int new_button_state;
+       struct sd *sd = (struct sd *)gspca_dev;
+
+       switch (sd->model) {
+       case CIT_MODEL3:
+       case CIT_IBM_NETCAM_PRO:
+               break;
+       default: /* TEST ME unknown if this works on other models too */
+               return;
+       }
+
+       /* Read the button state */
+       cit_read_reg(gspca_dev, 0x0113, 0);
+       new_button_state = !gspca_dev->usb_buf[0];
+
+       /* Tell the cam we've seen the button press, notice that this
+          is a nop (iow the cam keeps reporting pressed) until the
+          button is actually released. */
+       if (new_button_state)
+               cit_write_reg(gspca_dev, 0x01, 0x0113);
+
+       if (sd->button_state != new_button_state) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA,
+                                new_button_state);
+               input_sync(gspca_dev->input_dev);
+               sd->button_state = new_button_state;
+       }
+}
+#endif
+
+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;
+
+       if (sd->stop_on_control_change)
+               sd_stopN(gspca_dev);
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               cit_set_brightness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               cit_set_contrast(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_HUE:
+               cit_set_hue(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_HFLIP:
+               cit_set_hflip(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SHARPNESS:
+               cit_set_sharpness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_BACKLIGHT_COMPENSATION:
+               cit_set_lighting(gspca_dev, ctrl->val);
+               break;
+       }
+       if (sd->stop_on_control_change)
+               cit_restart_stream(gspca_dev);
+       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;
+       bool has_brightness;
+       bool has_contrast;
+       bool has_hue;
+       bool has_sharpness;
+       bool has_lighting;
+       bool has_hflip;
+
+       has_brightness = has_contrast = has_hue =
+               has_sharpness = has_hflip = has_lighting = false;
+       switch (sd->model) {
+       case CIT_MODEL0:
+               has_contrast = has_hflip = true;
+               break;
+       case CIT_MODEL1:
+               has_brightness = has_contrast =
+                       has_sharpness = has_lighting = true;
+               break;
+       case CIT_MODEL2:
+               has_brightness = has_hue = has_lighting = true;
+               break;
+       case CIT_MODEL3:
+               has_brightness = has_contrast = has_sharpness = true;
+               break;
+       case CIT_MODEL4:
+               has_brightness = has_hue = true;
+               break;
+       case CIT_IBM_NETCAM_PRO:
+               has_brightness = has_hue =
+                       has_sharpness = has_hflip = has_lighting = true;
+               break;
+       }
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 5);
+       if (has_brightness)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 63, 1, 32);
+       if (has_contrast)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 20, 1, 10);
+       if (has_hue)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_HUE, 0, 127, 1, 63);
+       if (has_sharpness)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_SHARPNESS, 0, 6, 1, 3);
+       if (has_lighting)
+               sd->lighting = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_BACKLIGHT_COMPENSATION, 0, 2, 1, 1);
+       if (has_hflip)
+               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                       V4L2_CID_HFLIP, 0, 1, 1, 0);
+
+       if (hdl->error) {
+               pr_err("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,
+       .stopN = sd_stopN,
+       .stop0 = sd_stop0,
+       .pkt_scan = sd_pkt_scan,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .dq_callback = cit_check_button,
+       .other_input = 1,
+#endif
+};
+
+static const struct sd_desc sd_desc_isoc_nego = {
+       .name = MODULE_NAME,
+       .config = sd_config,
+       .init = sd_init,
+       .init_controls = sd_init_controls,
+       .start = sd_start,
+       .isoc_init = sd_isoc_init,
+       .isoc_nego = sd_isoc_nego,
+       .stopN = sd_stopN,
+       .stop0 = sd_stop0,
+       .pkt_scan = sd_pkt_scan,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .dq_callback = cit_check_button,
+       .other_input = 1,
+#endif
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+       { USB_DEVICE_VER(0x0545, 0x8080, 0x0001, 0x0001), .driver_info = CIT_MODEL0 },
+       { USB_DEVICE_VER(0x0545, 0x8080, 0x0002, 0x0002), .driver_info = CIT_MODEL1 },
+       { USB_DEVICE_VER(0x0545, 0x8080, 0x030a, 0x030a), .driver_info = CIT_MODEL2 },
+       { USB_DEVICE_VER(0x0545, 0x8080, 0x0301, 0x0301), .driver_info = CIT_MODEL3 },
+       { USB_DEVICE_VER(0x0545, 0x8002, 0x030a, 0x030a), .driver_info = CIT_MODEL4 },
+       { USB_DEVICE_VER(0x0545, 0x800c, 0x030a, 0x030a), .driver_info = CIT_MODEL2 },
+       { USB_DEVICE_VER(0x0545, 0x800d, 0x030a, 0x030a), .driver_info = CIT_MODEL4 },
+       {}
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+static int sd_probe(struct usb_interface *intf,
+                       const struct usb_device_id *id)
+{
+       const struct sd_desc *desc = &sd_desc;
+
+       switch (id->driver_info) {
+       case CIT_MODEL0:
+       case CIT_MODEL1:
+               if (intf->cur_altsetting->desc.bInterfaceNumber != 2)
+                       return -ENODEV;
+               break;
+       case CIT_MODEL2:
+       case CIT_MODEL4:
+               if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+                       return -ENODEV;
+               break;
+       case CIT_MODEL3:
+               if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
+                       return -ENODEV;
+               /* FIXME this likely applies to all model3 cams and probably
+                  to other models too. */
+               if (ibm_netcam_pro)
+                       desc = &sd_desc_isoc_nego;
+               break;
+       }
+
+       return gspca_dev_probe2(intf, id, 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,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
diff --git a/drivers/media/usb/gspca/zc3xx-reg.h b/drivers/media/usb/gspca/zc3xx-reg.h
new file mode 100644 (file)
index 0000000..a1bd94e
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * zc030x registers
+ *
+ * Copyright (c) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ * The register aliases used here came from this driver:
+ *     http://zc0302.sourceforge.net/zc0302.php
+ *
+ * This code is placed under the terms of the GNU General Public License v2
+ */
+
+/* Define the register map */
+#define ZC3XX_R000_SYSTEMCONTROL       0x0000
+#define ZC3XX_R001_SYSTEMOPERATING     0x0001
+
+/* Picture size */
+#define ZC3XX_R002_CLOCKSELECT         0x0002
+#define ZC3XX_R003_FRAMEWIDTHHIGH      0x0003
+#define ZC3XX_R004_FRAMEWIDTHLOW       0x0004
+#define ZC3XX_R005_FRAMEHEIGHTHIGH     0x0005
+#define ZC3XX_R006_FRAMEHEIGHTLOW      0x0006
+
+/* JPEG control */
+#define ZC3XX_R008_CLOCKSETTING        0x0008
+
+/* Test mode */
+#define ZC3XX_R00B_TESTMODECONTROL     0x000b
+
+/* Frame retreiving */
+#define ZC3XX_R00C_LASTACQTIME         0x000c
+#define ZC3XX_R00D_MONITORRES          0x000d
+#define ZC3XX_R00E_TIMESTAMPHIGH       0x000e
+#define ZC3XX_R00F_TIMESTAMPLOW        0x000f
+#define ZC3XX_R018_FRAMELOST           0x0018
+#define ZC3XX_R019_AUTOADJUSTFPS       0x0019
+#define ZC3XX_R01A_LASTFRAMESTATE      0x001a
+#define ZC3XX_R025_DATACOUNTER         0x0025
+
+/* Stream and sensor specific */
+#define ZC3XX_R010_CMOSSENSORSELECT    0x0010
+#define ZC3XX_R011_VIDEOSTATUS         0x0011
+#define ZC3XX_R012_VIDEOCONTROLFUNC    0x0012
+
+/* Horizontal and vertical synchros */
+#define ZC3XX_R01D_HSYNC_0             0x001d
+#define ZC3XX_R01E_HSYNC_1             0x001e
+#define ZC3XX_R01F_HSYNC_2             0x001f
+#define ZC3XX_R020_HSYNC_3             0x0020
+
+/* Target picture size in byte */
+#define ZC3XX_R022_TARGETPICTSIZE_0    0x0022
+#define ZC3XX_R023_TARGETPICTSIZE_1    0x0023
+#define ZC3XX_R024_TARGETPICTSIZE_2    0x0024
+
+/* Audio registers */
+#define ZC3XX_R030_AUDIOADC            0x0030
+#define ZC3XX_R031_AUDIOSTREAMSTATUS   0x0031
+#define ZC3XX_R032_AUDIOSTATUS         0x0032
+
+/* Sensor interface */
+#define ZC3XX_R080_HBLANKHIGH          0x0080
+#define ZC3XX_R081_HBLANKLOW           0x0081
+#define ZC3XX_R082_RESETLEVELADDR      0x0082
+#define ZC3XX_R083_RGAINADDR           0x0083
+#define ZC3XX_R084_GGAINADDR           0x0084
+#define ZC3XX_R085_BGAINADDR           0x0085
+#define ZC3XX_R086_EXPTIMEHIGH         0x0086
+#define ZC3XX_R087_EXPTIMEMID          0x0087
+#define ZC3XX_R088_EXPTIMELOW          0x0088
+#define ZC3XX_R089_RESETBLACKHIGH      0x0089
+#define ZC3XX_R08A_RESETWHITEHIGH      0x008a
+#define ZC3XX_R08B_I2CDEVICEADDR       0x008b
+#define ZC3XX_R08C_I2CIDLEANDNACK      0x008c
+#define ZC3XX_R08D_COMPABILITYMODE     0x008d
+#define ZC3XX_R08E_COMPABILITYMODE2    0x008e
+
+/* I2C control */
+#define ZC3XX_R090_I2CCOMMAND          0x0090
+#define ZC3XX_R091_I2CSTATUS           0x0091
+#define ZC3XX_R092_I2CADDRESSSELECT    0x0092
+#define ZC3XX_R093_I2CSETVALUE         0x0093
+#define ZC3XX_R094_I2CWRITEACK         0x0094
+#define ZC3XX_R095_I2CREAD             0x0095
+#define ZC3XX_R096_I2CREADACK          0x0096
+
+/* Window inside the sensor array */
+#define ZC3XX_R097_WINYSTARTHIGH       0x0097
+#define ZC3XX_R098_WINYSTARTLOW        0x0098
+#define ZC3XX_R099_WINXSTARTHIGH       0x0099
+#define ZC3XX_R09A_WINXSTARTLOW        0x009a
+#define ZC3XX_R09B_WINHEIGHTHIGH       0x009b
+#define ZC3XX_R09C_WINHEIGHTLOW        0x009c
+#define ZC3XX_R09D_WINWIDTHHIGH        0x009d
+#define ZC3XX_R09E_WINWIDTHLOW         0x009e
+#define ZC3XX_R119_FIRSTYHIGH          0x0119
+#define ZC3XX_R11A_FIRSTYLOW           0x011a
+#define ZC3XX_R11B_FIRSTXHIGH          0x011b
+#define ZC3XX_R11C_FIRSTXLOW           0x011c
+
+/* Max sensor array size */
+#define ZC3XX_R09F_MAXXHIGH            0x009f
+#define ZC3XX_R0A0_MAXXLOW             0x00a0
+#define ZC3XX_R0A1_MAXYHIGH            0x00a1
+#define ZC3XX_R0A2_MAXYLOW             0x00a2
+#define ZC3XX_R0A3_EXPOSURETIMEHIGH    0x00a3
+#define ZC3XX_R0A4_EXPOSURETIMELOW     0x00a4
+#define ZC3XX_R0A5_EXPOSUREGAIN        0x00a5
+#define ZC3XX_R0A6_EXPOSUREBLACKLVL    0x00a6
+
+/* Other registers */
+#define ZC3XX_R100_OPERATIONMODE       0x0100
+#define ZC3XX_R101_SENSORCORRECTION    0x0101
+
+/* Gains */
+#define ZC3XX_R116_RGAIN               0x0116
+#define ZC3XX_R117_GGAIN               0x0117
+#define ZC3XX_R118_BGAIN               0x0118
+#define ZC3XX_R11D_GLOBALGAIN          0x011d
+#define ZC3XX_R1A8_DIGITALGAIN         0x01a8
+#define ZC3XX_R1A9_DIGITALLIMITDIFF    0x01a9
+#define ZC3XX_R1AA_DIGITALGAINSTEP     0x01aa
+
+/* Auto correction */
+#define ZC3XX_R180_AUTOCORRECTENABLE   0x0180
+#define ZC3XX_R181_WINXSTART           0x0181
+#define ZC3XX_R182_WINXWIDTH           0x0182
+#define ZC3XX_R183_WINXCENTER          0x0183
+#define ZC3XX_R184_WINYSTART           0x0184
+#define ZC3XX_R185_WINYWIDTH           0x0185
+#define ZC3XX_R186_WINYCENTER          0x0186
+
+/* Gain range */
+#define ZC3XX_R187_MAXGAIN             0x0187
+#define ZC3XX_R188_MINGAIN             0x0188
+
+/* Auto exposure and white balance */
+#define ZC3XX_R189_AWBSTATUS           0x0189
+#define ZC3XX_R18A_AWBFREEZE           0x018a
+#define ZC3XX_R18B_AESTATUS            0x018b
+#define ZC3XX_R18C_AEFREEZE            0x018c
+#define ZC3XX_R18F_AEUNFREEZE          0x018f
+#define ZC3XX_R190_EXPOSURELIMITHIGH   0x0190
+#define ZC3XX_R191_EXPOSURELIMITMID    0x0191
+#define ZC3XX_R192_EXPOSURELIMITLOW    0x0192
+#define ZC3XX_R195_ANTIFLICKERHIGH     0x0195
+#define ZC3XX_R196_ANTIFLICKERMID      0x0196
+#define ZC3XX_R197_ANTIFLICKERLOW      0x0197
+
+/* What is this ? */
+#define ZC3XX_R18D_YTARGET             0x018d
+#define ZC3XX_R18E_RESETLVL            0x018e
+
+/* Color */
+#define ZC3XX_R1A0_REDMEANAFTERAGC     0x01a0
+#define ZC3XX_R1A1_GREENMEANAFTERAGC   0x01a1
+#define ZC3XX_R1A2_BLUEMEANAFTERAGC    0x01a2
+#define ZC3XX_R1A3_REDMEANAFTERAWB     0x01a3
+#define ZC3XX_R1A4_GREENMEANAFTERAWB   0x01a4
+#define ZC3XX_R1A5_BLUEMEANAFTERAWB    0x01a5
+#define ZC3XX_R1A6_YMEANAFTERAE        0x01a6
+#define ZC3XX_R1A7_CALCGLOBALMEAN      0x01a7
+
+/* Matrixes */
+
+/* Color matrix is like :
+   R' = R * RGB00 + G * RGB01 + B * RGB02 + RGB03
+   G' = R * RGB10 + G * RGB11 + B * RGB22 + RGB13
+   B' = R * RGB20 + G * RGB21 + B * RGB12 + RGB23
+ */
+#define ZC3XX_R10A_RGB00               0x010a
+#define ZC3XX_R10B_RGB01               0x010b
+#define ZC3XX_R10C_RGB02               0x010c
+#define ZC3XX_R113_RGB03               0x0113
+#define ZC3XX_R10D_RGB10               0x010d
+#define ZC3XX_R10E_RGB11               0x010e
+#define ZC3XX_R10F_RGB12               0x010f
+#define ZC3XX_R114_RGB13               0x0114
+#define ZC3XX_R110_RGB20               0x0110
+#define ZC3XX_R111_RGB21               0x0111
+#define ZC3XX_R112_RGB22               0x0112
+#define ZC3XX_R115_RGB23               0x0115
+
+/* Gamma matrix */
+#define ZC3XX_R120_GAMMA00             0x0120
+#define ZC3XX_R121_GAMMA01             0x0121
+#define ZC3XX_R122_GAMMA02             0x0122
+#define ZC3XX_R123_GAMMA03             0x0123
+#define ZC3XX_R124_GAMMA04             0x0124
+#define ZC3XX_R125_GAMMA05             0x0125
+#define ZC3XX_R126_GAMMA06             0x0126
+#define ZC3XX_R127_GAMMA07             0x0127
+#define ZC3XX_R128_GAMMA08             0x0128
+#define ZC3XX_R129_GAMMA09             0x0129
+#define ZC3XX_R12A_GAMMA0A             0x012a
+#define ZC3XX_R12B_GAMMA0B             0x012b
+#define ZC3XX_R12C_GAMMA0C             0x012c
+#define ZC3XX_R12D_GAMMA0D             0x012d
+#define ZC3XX_R12E_GAMMA0E             0x012e
+#define ZC3XX_R12F_GAMMA0F             0x012f
+#define ZC3XX_R130_GAMMA10             0x0130
+#define ZC3XX_R131_GAMMA11             0x0131
+#define ZC3XX_R132_GAMMA12             0x0132
+#define ZC3XX_R133_GAMMA13             0x0133
+#define ZC3XX_R134_GAMMA14             0x0134
+#define ZC3XX_R135_GAMMA15             0x0135
+#define ZC3XX_R136_GAMMA16             0x0136
+#define ZC3XX_R137_GAMMA17             0x0137
+#define ZC3XX_R138_GAMMA18             0x0138
+#define ZC3XX_R139_GAMMA19             0x0139
+#define ZC3XX_R13A_GAMMA1A             0x013a
+#define ZC3XX_R13B_GAMMA1B             0x013b
+#define ZC3XX_R13C_GAMMA1C             0x013c
+#define ZC3XX_R13D_GAMMA1D             0x013d
+#define ZC3XX_R13E_GAMMA1E             0x013e
+#define ZC3XX_R13F_GAMMA1F             0x013f
+
+/* Luminance gamma */
+#define ZC3XX_R140_YGAMMA00            0x0140
+#define ZC3XX_R141_YGAMMA01            0x0141
+#define ZC3XX_R142_YGAMMA02            0x0142
+#define ZC3XX_R143_YGAMMA03            0x0143
+#define ZC3XX_R144_YGAMMA04            0x0144
+#define ZC3XX_R145_YGAMMA05            0x0145
+#define ZC3XX_R146_YGAMMA06            0x0146
+#define ZC3XX_R147_YGAMMA07            0x0147
+#define ZC3XX_R148_YGAMMA08            0x0148
+#define ZC3XX_R149_YGAMMA09            0x0149
+#define ZC3XX_R14A_YGAMMA0A            0x014a
+#define ZC3XX_R14B_YGAMMA0B            0x014b
+#define ZC3XX_R14C_YGAMMA0C            0x014c
+#define ZC3XX_R14D_YGAMMA0D            0x014d
+#define ZC3XX_R14E_YGAMMA0E            0x014e
+#define ZC3XX_R14F_YGAMMA0F            0x014f
+#define ZC3XX_R150_YGAMMA10            0x0150
+#define ZC3XX_R151_YGAMMA11            0x0151
+
+#define ZC3XX_R1C5_SHARPNESSMODE       0x01c5
+#define ZC3XX_R1C6_SHARPNESS00         0x01c6
+#define ZC3XX_R1C7_SHARPNESS01         0x01c7
+#define ZC3XX_R1C8_SHARPNESS02         0x01c8
+#define ZC3XX_R1C9_SHARPNESS03         0x01c9
+#define ZC3XX_R1CA_SHARPNESS04         0x01ca
+#define ZC3XX_R1CB_SHARPNESS05         0x01cb
+
+/* Dead pixels */
+#define ZC3XX_R250_DEADPIXELSMODE      0x0250
+
+/* EEPROM */
+#define ZC3XX_R300_EEPROMCONFIG        0x0300
+#define ZC3XX_R301_EEPROMACCESS        0x0301
+#define ZC3XX_R302_EEPROMSTATUS        0x0302
diff --git a/drivers/media/usb/gspca/zc3xx.c b/drivers/media/usb/gspca/zc3xx.c
new file mode 100644 (file)
index 0000000..f0bacee
--- /dev/null
@@ -0,0 +1,7024 @@
+/*
+ * Z-Star/Vimicro zc301/zc302p/vc30x driver
+ *
+ * Copyright (C) 2009-2012 Jean-Francois Moine <http://moinejf.free.fr>
+ * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/input.h>
+#include "gspca.h"
+#include "jpeg.h"
+
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
+               "Serge A. Suchkov <Serge.A.S@tochka.ru>");
+MODULE_DESCRIPTION("GSPCA ZC03xx/VC3xx USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+static int force_sensor = -1;
+
+#define REG08_DEF 3            /* default JPEG compression (75%) */
+#include "zc3xx-reg.h"
+
+/* specific webcam descriptor */
+struct sd {
+       struct gspca_dev gspca_dev;     /* !! must be the first item */
+
+       struct { /* gamma/brightness/contrast control cluster */
+               struct v4l2_ctrl *gamma;
+               struct v4l2_ctrl *brightness;
+               struct v4l2_ctrl *contrast;
+       };
+       struct { /* autogain/exposure control cluster */
+               struct v4l2_ctrl *autogain;
+               struct v4l2_ctrl *exposure;
+       };
+       struct v4l2_ctrl *plfreq;
+       struct v4l2_ctrl *sharpness;
+       struct v4l2_ctrl *jpegqual;
+
+       struct work_struct work;
+       struct workqueue_struct *work_thread;
+
+       u8 reg08;               /* webcam compression quality */
+
+       u8 bridge;
+       u8 sensor;              /* Type of image sensor chip */
+       u16 chip_revision;
+
+       u8 jpeg_hdr[JPEG_HDR_SZ];
+};
+enum bridges {
+       BRIDGE_ZC301,
+       BRIDGE_ZC303,
+};
+enum sensors {
+       SENSOR_ADCM2700,
+       SENSOR_CS2102,
+       SENSOR_CS2102K,
+       SENSOR_GC0303,
+       SENSOR_GC0305,
+       SENSOR_HDCS2020,
+       SENSOR_HV7131B,
+       SENSOR_HV7131R,
+       SENSOR_ICM105A,
+       SENSOR_MC501CB,
+       SENSOR_MT9V111_1,       /* (mi360soc) zc301 */
+       SENSOR_MT9V111_3,       /* (mi360soc) zc303 */
+       SENSOR_OV7620,          /* OV7648 - same values */
+       SENSOR_OV7630C,
+       SENSOR_PAS106,
+       SENSOR_PAS202B,
+       SENSOR_PB0330,
+       SENSOR_PO2030,
+       SENSOR_TAS5130C,
+       SENSOR_MAX
+};
+
+static const struct v4l2_pix_format vga_mode[] = {
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+
+static const struct v4l2_pix_format broken_vga_mode[] = {
+       {320, 232, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 232 * 4 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {640, 472, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 472 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+
+static const struct v4l2_pix_format sif_mode[] = {
+       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
+};
+
+/*
+ * Bridge reg08 bits 1-2 -> JPEG quality conversion table. Note the highest
+ * quality setting is not usable as USB 1 does not have enough bandwidth.
+ */
+static u8 jpeg_qual[] = {50, 75, 87, /* 94 */};
+
+/* usb exchanges */
+struct usb_action {
+       u8      req;
+       u8      val;
+       u16     idx;
+};
+
+static const struct usb_action adcm2700_Initial[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},         /* 00,00,01,cc */
+       {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT},           /* 00,02,04,cc */
+       {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING},          /* 00,08,03,cc */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,d3,cc */
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc */
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},         /* 00,04,80,cc */
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc */
+       {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW},        /* 00,06,d8,cc */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc */
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc */
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,05,cc */
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},          /* 00,98,00,cc */
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},          /* 00,9a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},             /* 01,1a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},             /* 01,1c,00,cc */
+       {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW},          /* 00,9c,de,cc */
+       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},           /* 00,9e,86,cc */
+       {0xbb, 0x00, 0x0400},                           /* 04,00,00,bb */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xbb, 0x0f, 0x140f},                           /* 14,0f,0f,bb */
+       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,37,cc */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0d,cc */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},             /* 01,89,06,cc */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},         /* 01,c5,03,cc */
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},           /* 01,cb,13,cc */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},          /* 03,01,08,cc */
+       {0xa0, 0x58, ZC3XX_R116_RGAIN},                 /* 01,16,58,cc */
+       {0xa0, 0x5a, ZC3XX_R118_BGAIN},                 /* 01,18,5a,cc */
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,02,cc */
+       {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,d3,cc */
+       {0xbb, 0x00, 0x0408},                           /* 04,00,08,bb */
+       {0xdd, 0x00, 0x0200},                           /* 00,02,00,dd */
+       {0xbb, 0x00, 0x0400},                           /* 04,00,00,bb */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xbb, 0x0f, 0x140f},                           /* 14,0f,0f,bb */
+       {0xbb, 0xe0, 0x0c2e},                           /* 0c,e0,2e,bb */
+       {0xbb, 0x01, 0x2000},                           /* 20,01,00,bb */
+       {0xbb, 0x96, 0x2400},                           /* 24,96,00,bb */
+       {0xbb, 0x06, 0x1006},                           /* 10,06,06,bb */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xaa, 0xfe, 0x0002},                           /* 00,fe,02,aa */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xbb, 0x5f, 0x2090},                           /* 20,5f,90,bb */
+       {0xbb, 0x01, 0x8000},                           /* 80,01,00,bb */
+       {0xbb, 0x09, 0x8400},                           /* 84,09,00,bb */
+       {0xbb, 0x86, 0x0002},                           /* 00,86,02,bb */
+       {0xbb, 0xe6, 0x0401},                           /* 04,e6,01,bb */
+       {0xbb, 0x86, 0x0802},                           /* 08,86,02,bb */
+       {0xbb, 0xe6, 0x0c01},                           /* 0c,e6,01,bb */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xaa, 0xfe, 0x0000},                           /* 00,fe,00,aa */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xaa, 0xfe, 0x0020},                           /* 00,fe,20,aa */
+/*mswin+*/
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xaa, 0xfe, 0x0002},
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xaa, 0xb4, 0xcd37},
+       {0xaa, 0xa4, 0x0004},
+       {0xaa, 0xa8, 0x0007},
+       {0xaa, 0xac, 0x0004},
+/*mswin-*/
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xaa, 0xfe, 0x0000},                           /* 00,fe,00,aa */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xbb, 0x04, 0x0400},                           /* 04,04,00,bb */
+       {0xdd, 0x00, 0x0100},                           /* 00,01,00,dd */
+       {0xbb, 0x01, 0x0400},                           /* 04,01,00,bb */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xaa, 0xfe, 0x0002},                           /* 00,fe,02,aa */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xbb, 0x41, 0x2803},                           /* 28,41,03,bb */
+       {0xbb, 0x40, 0x2c03},                           /* 2c,40,03,bb */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xaa, 0xfe, 0x0010},                           /* 00,fe,10,aa */
+       {}
+};
+static const struct usb_action adcm2700_InitialScale[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},         /* 00,00,01,cc */
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},           /* 00,02,10,cc */
+       {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING},          /* 00,08,03,cc */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,d3,cc */
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc */
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},         /* 00,04,80,cc */
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc */
+       {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW},        /* 00,06,d0,cc */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc */
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc */
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,05,cc */
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},          /* 00,98,00,cc */
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},          /* 00,9a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},             /* 01,1a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},             /* 01,1c,00,cc */
+       {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW},          /* 00,9c,d8,cc */
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},           /* 00,9e,88,cc */
+       {0xbb, 0x00, 0x0400},                           /* 04,00,00,bb */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xbb, 0x0f, 0x140f},                           /* 14,0f,0f,bb */
+       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,37,cc */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0d,cc */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},             /* 01,89,06,cc */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},         /* 01,c5,03,cc */
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},           /* 01,cb,13,cc */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},          /* 03,01,08,cc */
+       {0xa0, 0x58, ZC3XX_R116_RGAIN},                 /* 01,16,58,cc */
+       {0xa0, 0x5a, ZC3XX_R118_BGAIN},                 /* 01,18,5a,cc */
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,02,cc */
+       {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,d3,cc */
+       {0xbb, 0x00, 0x0408},                           /* 04,00,08,bb */
+       {0xdd, 0x00, 0x0200},                           /* 00,02,00,dd */
+       {0xbb, 0x00, 0x0400},                           /* 04,00,00,bb */
+       {0xdd, 0x00, 0x0050},                           /* 00,00,50,dd */
+       {0xbb, 0x0f, 0x140f},                           /* 14,0f,0f,bb */
+       {0xbb, 0xe0, 0x0c2e},                           /* 0c,e0,2e,bb */
+       {0xbb, 0x01, 0x2000},                           /* 20,01,00,bb */
+       {0xbb, 0x96, 0x2400},                           /* 24,96,00,bb */
+       {0xbb, 0x06, 0x1006},                           /* 10,06,06,bb */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xaa, 0xfe, 0x0002},                           /* 00,fe,02,aa */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xbb, 0x5f, 0x2090},                           /* 20,5f,90,bb */
+       {0xbb, 0x01, 0x8000},                           /* 80,01,00,bb */
+       {0xbb, 0x09, 0x8400},                           /* 84,09,00,bb */
+       {0xbb, 0x86, 0x0002},                           /* 00,88,02,bb */
+       {0xbb, 0xe6, 0x0401},                           /* 04,e6,01,bb */
+       {0xbb, 0x86, 0x0802},                           /* 08,88,02,bb */
+       {0xbb, 0xe6, 0x0c01},                           /* 0c,e6,01,bb */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xaa, 0xfe, 0x0000},                           /* 00,fe,00,aa */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xaa, 0xfe, 0x0020},                           /* 00,fe,20,aa */
+       /*******/
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xaa, 0xfe, 0x0000},                           /* 00,fe,00,aa */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
+       {0xbb, 0x04, 0x0400},                           /* 04,04,00,bb */
+       {0xdd, 0x00, 0x0100},                           /* 00,01,00,dd */
+       {0xbb, 0x01, 0x0400},                           /* 04,01,00,bb */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xaa, 0xfe, 0x0002},                           /* 00,fe,02,aa */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xbb, 0x41, 0x2803},                           /* 28,41,03,bb */
+       {0xbb, 0x40, 0x2c03},                           /* 2c,40,03,bb */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xaa, 0xfe, 0x0010},                           /* 00,fe,10,aa */
+       {}
+};
+static const struct usb_action adcm2700_50HZ[] = {
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xaa, 0xfe, 0x0002},                           /* 00,fe,02,aa */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xbb, 0x05, 0x8400},                           /* 84,05,00,bb */
+       {0xbb, 0xd0, 0xb007},                           /* b0,d0,07,bb */
+       {0xbb, 0xa0, 0xb80f},                           /* b8,a0,0f,bb */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xaa, 0xfe, 0x0010},                           /* 00,fe,10,aa */
+       {0xaa, 0x26, 0x00d0},                           /* 00,26,d0,aa */
+       {0xaa, 0x28, 0x0002},                           /* 00,28,02,aa */
+       {}
+};
+static const struct usb_action adcm2700_60HZ[] = {
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xaa, 0xfe, 0x0002},                           /* 00,fe,02,aa */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xbb, 0x07, 0x8400},                           /* 84,07,00,bb */
+       {0xbb, 0x82, 0xb006},                           /* b0,82,06,bb */
+       {0xbb, 0x04, 0xb80d},                           /* b8,04,0d,bb */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xaa, 0xfe, 0x0010},                           /* 00,fe,10,aa */
+       {0xaa, 0x26, 0x0057},                           /* 00,26,57,aa */
+       {0xaa, 0x28, 0x0002},                           /* 00,28,02,aa */
+       {}
+};
+static const struct usb_action adcm2700_NoFliker[] = {
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xaa, 0xfe, 0x0002},                           /* 00,fe,02,aa */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
+       {0xbb, 0x07, 0x8400},                           /* 84,07,00,bb */
+       {0xbb, 0x05, 0xb000},                           /* b0,05,00,bb */
+       {0xbb, 0xa0, 0xb801},                           /* b8,a0,01,bb */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xaa, 0xfe, 0x0010},                           /* 00,fe,10,aa */
+       {}
+};
+static const struct usb_action cs2102_InitialScale[] = {       /* 320x240 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x20, ZC3XX_R080_HBLANKHIGH},
+       {0xa0, 0x21, ZC3XX_R081_HBLANKLOW},
+       {0xa0, 0x30, ZC3XX_R083_RGAINADDR},
+       {0xa0, 0x31, ZC3XX_R084_GGAINADDR},
+       {0xa0, 0x32, ZC3XX_R085_BGAINADDR},
+       {0xa0, 0x23, ZC3XX_R086_EXPTIMEHIGH},
+       {0xa0, 0x24, ZC3XX_R087_EXPTIMEMID},
+       {0xa0, 0x25, ZC3XX_R088_EXPTIMELOW},
+       {0xa0, 0xb3, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00 */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xaa, 0x02, 0x0008},
+       {0xaa, 0x03, 0x0000},
+       {0xaa, 0x11, 0x0000},
+       {0xaa, 0x12, 0x0089},
+       {0xaa, 0x13, 0x0000},
+       {0xaa, 0x14, 0x00e9},
+       {0xaa, 0x20, 0x0000},
+       {0xaa, 0x22, 0x0000},
+       {0xaa, 0x0b, 0x0004},
+       {0xaa, 0x30, 0x0030},
+       {0xaa, 0x31, 0x0030},
+       {0xaa, 0x32, 0x0030},
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x10, 0x01ae},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa0, 0x68, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x00, 0x01ad},
+       {}
+};
+
+static const struct usb_action cs2102_Initial[] = {    /* 640x480 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x20, ZC3XX_R080_HBLANKHIGH},
+       {0xa0, 0x21, ZC3XX_R081_HBLANKLOW},
+       {0xa0, 0x30, ZC3XX_R083_RGAINADDR},
+       {0xa0, 0x31, ZC3XX_R084_GGAINADDR},
+       {0xa0, 0x32, ZC3XX_R085_BGAINADDR},
+       {0xa0, 0x23, ZC3XX_R086_EXPTIMEHIGH},
+       {0xa0, 0x24, ZC3XX_R087_EXPTIMEMID},
+       {0xa0, 0x25, ZC3XX_R088_EXPTIMELOW},
+       {0xa0, 0xb3, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00 */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xaa, 0x02, 0x0008},
+       {0xaa, 0x03, 0x0000},
+       {0xaa, 0x11, 0x0001},
+       {0xaa, 0x12, 0x0087},
+       {0xaa, 0x13, 0x0001},
+       {0xaa, 0x14, 0x00e7},
+       {0xaa, 0x20, 0x0000},
+       {0xaa, 0x22, 0x0000},
+       {0xaa, 0x0b, 0x0004},
+       {0xaa, 0x30, 0x0030},
+       {0xaa, 0x31, 0x0030},
+       {0xaa, 0x32, 0x0030},
+       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x15, 0x01ae},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa0, 0x68, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x00, 0x01ad},
+       {}
+};
+static const struct usb_action cs2102_50HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x23, 0x0001},
+       {0xaa, 0x24, 0x005f},
+       {0xaa, 0x25, 0x0090},
+       {0xaa, 0x21, 0x00dd},
+       {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0xbf, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x3a, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x98, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xdd, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xe4, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action cs2102_50HZ[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x23, 0x0000},
+       {0xaa, 0x24, 0x00af},
+       {0xaa, 0x25, 0x00c8},
+       {0xaa, 0x21, 0x0068},
+       {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x5f, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x90, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x1d, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x4c, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x68, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xe3, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action cs2102_60HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x23, 0x0001},
+       {0xaa, 0x24, 0x0055},
+       {0xaa, 0x25, 0x00cc},
+       {0xaa, 0x21, 0x003f},
+       {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0xab, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x98, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x30, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0xd4, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x39, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x70, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xb0, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action cs2102_60HZ[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x23, 0x0000},
+       {0xaa, 0x24, 0x00aa},
+       {0xaa, 0x25, 0x00e6},
+       {0xaa, 0x21, 0x003f},
+       {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x55, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xcc, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x18, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x6a, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x3f, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xa5, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action cs2102_NoFlikerScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x23, 0x0001},
+       {0xaa, 0x24, 0x005f},
+       {0xaa, 0x25, 0x0000},
+       {0xaa, 0x21, 0x0001},
+       {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0xbf, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x80, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x01, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xa0, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action cs2102_NoFliker[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x23, 0x0000},
+       {0xaa, 0x24, 0x00af},
+       {0xaa, 0x25, 0x0080},
+       {0xaa, 0x21, 0x0001},
+       {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x5f, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x80, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x01, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xa0, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {}
+};
+
+/* CS2102_KOCOM */
+static const struct usb_action cs2102K_InitialScale[] = {
+       {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
+       {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x0a, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x0b, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x0c, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x7c, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x0d, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0xa3, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x0e, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x78, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
+       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa0, 0x00, 0x01ad},
+       {0xa0, 0x01, 0x01b1},
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x60, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x4c, ZC3XX_R118_BGAIN},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
+       {0xa0, 0x13, ZC3XX_R120_GAMMA00},       /* gamma 4 */
+       {0xa0, 0x38, ZC3XX_R121_GAMMA01},
+       {0xa0, 0x59, ZC3XX_R122_GAMMA02},
+       {0xa0, 0x79, ZC3XX_R123_GAMMA03},
+       {0xa0, 0x92, ZC3XX_R124_GAMMA04},
+       {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
+       {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
+       {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
+       {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
+       {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
+       {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
+       {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
+       {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
+       {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
+       {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
+       {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
+       {0xa0, 0x26, ZC3XX_R130_GAMMA10},
+       {0xa0, 0x22, ZC3XX_R131_GAMMA11},
+       {0xa0, 0x20, ZC3XX_R132_GAMMA12},
+       {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
+       {0xa0, 0x16, ZC3XX_R134_GAMMA14},
+       {0xa0, 0x13, ZC3XX_R135_GAMMA15},
+       {0xa0, 0x10, ZC3XX_R136_GAMMA16},
+       {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
+       {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
+       {0xa0, 0x09, ZC3XX_R139_GAMMA19},
+       {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
+       {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
+       {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
+       {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
+       {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
+       {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
+       {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
+       {0xa0, 0xf4, ZC3XX_R10B_RGB01},
+       {0xa0, 0xf4, ZC3XX_R10C_RGB02},
+       {0xa0, 0xf4, ZC3XX_R10D_RGB10},
+       {0xa0, 0x58, ZC3XX_R10E_RGB11},
+       {0xa0, 0xf4, ZC3XX_R10F_RGB12},
+       {0xa0, 0xf4, ZC3XX_R110_RGB20},
+       {0xa0, 0xf4, ZC3XX_R111_RGB21},
+       {0xa0, 0x58, ZC3XX_R112_RGB22},
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
+       {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x60, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x4c, ZC3XX_R118_BGAIN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {}
+};
+
+static const struct usb_action cs2102K_Initial[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
+/*fixme: next sequence = i2c exchanges*/
+       {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x0a, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x0b, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x0c, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x7b, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x0d, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0xa3, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x0e, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x78, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
+       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa0, 0x00, 0x01ad},
+       {0xa0, 0x01, 0x01b1},
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x60, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x4c, ZC3XX_R118_BGAIN},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
+       {0xa0, 0x13, ZC3XX_R120_GAMMA00},       /* gamma 4 */
+       {0xa0, 0x38, ZC3XX_R121_GAMMA01},
+       {0xa0, 0x59, ZC3XX_R122_GAMMA02},
+       {0xa0, 0x79, ZC3XX_R123_GAMMA03},
+       {0xa0, 0x92, ZC3XX_R124_GAMMA04},
+       {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
+       {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
+       {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
+       {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
+       {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
+       {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
+       {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
+       {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
+       {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
+       {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
+       {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
+       {0xa0, 0x26, ZC3XX_R130_GAMMA10},
+       {0xa0, 0x22, ZC3XX_R131_GAMMA11},
+       {0xa0, 0x20, ZC3XX_R132_GAMMA12},
+       {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
+       {0xa0, 0x16, ZC3XX_R134_GAMMA14},
+       {0xa0, 0x13, ZC3XX_R135_GAMMA15},
+       {0xa0, 0x10, ZC3XX_R136_GAMMA16},
+       {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
+       {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
+       {0xa0, 0x09, ZC3XX_R139_GAMMA19},
+       {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
+       {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
+       {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
+       {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
+       {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
+       {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
+       {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
+       {0xa0, 0xf4, ZC3XX_R10B_RGB01},
+       {0xa0, 0xf4, ZC3XX_R10C_RGB02},
+       {0xa0, 0xf4, ZC3XX_R10D_RGB10},
+       {0xa0, 0x58, ZC3XX_R10E_RGB11},
+       {0xa0, 0xf4, ZC3XX_R10F_RGB12},
+       {0xa0, 0xf4, ZC3XX_R110_RGB20},
+       {0xa0, 0xf4, ZC3XX_R111_RGB21},
+       {0xa0, 0x58, ZC3XX_R112_RGB22},
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
+       {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x60, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x4c, ZC3XX_R118_BGAIN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+/*fixme:what does the next sequence?*/
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0xd0, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0xd0, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x0a, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x0a, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x44, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x44, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x7e, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x7e, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {}
+};
+
+static const struct usb_action gc0305_Initial[] = {    /* 640x480 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00,08,03,cc */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT},   /* 00,02,04,cc */
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc */
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc */
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},        /* 00,06,e0,cc */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc */
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc */
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},  /* 00,98,00,cc */
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},  /* 00,9a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},     /* 01,1a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},     /* 01,1c,00,cc */
+       {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},  /* 00,9c,e6,cc */
+       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},   /* 00,9e,86,cc */
+       {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc */
+       {0xaa, 0x13, 0x0002},   /* 00,13,02,aa */
+       {0xaa, 0x15, 0x0003},   /* 00,15,03,aa */
+       {0xaa, 0x01, 0x0000},   /* 00,01,00,aa */
+       {0xaa, 0x02, 0x0000},   /* 00,02,00,aa */
+       {0xaa, 0x1a, 0x0000},   /* 00,1a,00,aa */
+       {0xaa, 0x1c, 0x0017},   /* 00,1c,17,aa */
+       {0xaa, 0x1d, 0x0080},   /* 00,1d,80,aa */
+       {0xaa, 0x1f, 0x0008},   /* 00,1f,08,aa */
+       {0xaa, 0x21, 0x0012},   /* 00,21,12,aa */
+       {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH},   /* 00,86,82,cc */
+       {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID},    /* 00,87,83,cc */
+       {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW},    /* 00,88,84,cc */
+       {0xaa, 0x05, 0x0000},   /* 00,05,00,aa */
+       {0xaa, 0x0a, 0x0000},   /* 00,0a,00,aa */
+       {0xaa, 0x0b, 0x00b0},   /* 00,0b,b0,aa */
+       {0xaa, 0x0c, 0x0000},   /* 00,0c,00,aa */
+       {0xaa, 0x0d, 0x00b0},   /* 00,0d,b0,aa */
+       {0xaa, 0x0e, 0x0000},   /* 00,0e,00,aa */
+       {0xaa, 0x0f, 0x00b0},   /* 00,0f,b0,aa */
+       {0xaa, 0x10, 0x0000},   /* 00,10,00,aa */
+       {0xaa, 0x11, 0x00b0},   /* 00,11,b0,aa */
+       {0xaa, 0x16, 0x0001},   /* 00,16,01,aa */
+       {0xaa, 0x17, 0x00e6},   /* 00,17,e6,aa */
+       {0xaa, 0x18, 0x0002},   /* 00,18,02,aa */
+       {0xaa, 0x19, 0x0086},   /* 00,19,86,aa */
+       {0xaa, 0x20, 0x0000},   /* 00,20,00,aa */
+       {0xaa, 0x1b, 0x0020},   /* 00,1b,20,aa */
+       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,b7,cc */
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,05,cc */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
+       {0xa0, 0x76, ZC3XX_R189_AWBSTATUS},     /* 01,89,76,cc */
+       {0xa0, 0x09, 0x01ad},   /* 01,ad,09,cc */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},   /* 01,cb,13,cc */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},  /* 03,01,08,cc */
+       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},   /* 01,a8,60,cc */
+       {0xa0, 0x85, ZC3XX_R18D_YTARGET},       /* 01,8d,85,cc */
+       {0xa0, 0x00, 0x011e},   /* 01,1e,00,cc */
+       {0xa0, 0x52, ZC3XX_R116_RGAIN}, /* 01,16,52,cc */
+       {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* 01,17,40,cc */
+       {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
+       {0xa0, 0x03, ZC3XX_R113_RGB03}, /* 01,13,03,cc */
+       {}
+};
+static const struct usb_action gc0305_InitialScale[] = { /* 320x240 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00,08,03,cc */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},   /* 00,02,10,cc */
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc */
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc */
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},        /* 00,06,e0,cc */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc */
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc */
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},  /* 00,98,00,cc */
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},  /* 00,9a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},     /* 01,1a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},     /* 01,1c,00,cc */
+       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},  /* 00,9c,e8,cc */
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},   /* 00,9e,88,cc */
+       {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc */
+       {0xaa, 0x13, 0x0000},   /* 00,13,00,aa */
+       {0xaa, 0x15, 0x0001},   /* 00,15,01,aa */
+       {0xaa, 0x01, 0x0000},   /* 00,01,00,aa */
+       {0xaa, 0x02, 0x0000},   /* 00,02,00,aa */
+       {0xaa, 0x1a, 0x0000},   /* 00,1a,00,aa */
+       {0xaa, 0x1c, 0x0017},   /* 00,1c,17,aa */
+       {0xaa, 0x1d, 0x0080},   /* 00,1d,80,aa */
+       {0xaa, 0x1f, 0x0008},   /* 00,1f,08,aa */
+       {0xaa, 0x21, 0x0012},   /* 00,21,12,aa */
+       {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH},   /* 00,86,82,cc */
+       {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID},    /* 00,87,83,cc */
+       {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW},    /* 00,88,84,cc */
+       {0xaa, 0x05, 0x0000},   /* 00,05,00,aa */
+       {0xaa, 0x0a, 0x0000},   /* 00,0a,00,aa */
+       {0xaa, 0x0b, 0x00b0},   /* 00,0b,b0,aa */
+       {0xaa, 0x0c, 0x0000},   /* 00,0c,00,aa */
+       {0xaa, 0x0d, 0x00b0},   /* 00,0d,b0,aa */
+       {0xaa, 0x0e, 0x0000},   /* 00,0e,00,aa */
+       {0xaa, 0x0f, 0x00b0},   /* 00,0f,b0,aa */
+       {0xaa, 0x10, 0x0000},   /* 00,10,00,aa */
+       {0xaa, 0x11, 0x00b0},   /* 00,11,b0,aa */
+       {0xaa, 0x16, 0x0001},   /* 00,16,01,aa */
+       {0xaa, 0x17, 0x00e8},   /* 00,17,e8,aa */
+       {0xaa, 0x18, 0x0002},   /* 00,18,02,aa */
+       {0xaa, 0x19, 0x0088},   /* 00,19,88,aa */
+       {0xaa, 0x20, 0x0000},   /* 00,20,00,aa */
+       {0xaa, 0x1b, 0x0020},   /* 00,1b,20,aa */
+       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,b7,cc */
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,05,cc */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
+       {0xa0, 0x76, ZC3XX_R189_AWBSTATUS},     /* 01,89,76,cc */
+       {0xa0, 0x09, 0x01ad},   /* 01,ad,09,cc */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},   /* 01,cb,13,cc */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},  /* 03,01,08,cc */
+       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},   /* 01,a8,60,cc */
+       {0xa0, 0x00, 0x011e},   /* 01,1e,00,cc */
+       {0xa0, 0x52, ZC3XX_R116_RGAIN}, /* 01,16,52,cc */
+       {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* 01,17,40,cc */
+       {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
+       {0xa0, 0x03, ZC3XX_R113_RGB03}, /* 01,13,03,cc */
+       {}
+};
+static const struct usb_action gc0305_50HZ[] = {
+       {0xaa, 0x82, 0x0000},   /* 00,82,00,aa */
+       {0xaa, 0x83, 0x0002},   /* 00,83,02,aa */
+       {0xaa, 0x84, 0x0038},   /* 00,84,38,aa */       /* win: 00,84,ec */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
+       {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,0b,cc */
+       {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,18,cc */
+                                                       /* win: 01,92,10 */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
+       {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,8e,cc */
+                                                       /* win: 01,97,ec */
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},      /* 01,8c,0e,cc */
+       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,15,cc */
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,10,cc */
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
+       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},       /* 00,1d,62,cc */
+       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},       /* 00,1e,90,cc */
+       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},       /* 00,1f,c8,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},       /* 00,20,ff,cc */
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},    /* 01,1d,60,cc */
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc */
+/*     {0xa0, 0x85, ZC3XX_R18D_YTARGET},        * 01,8d,85,cc *
+                                                * if 640x480 */
+       {}
+};
+static const struct usb_action gc0305_60HZ[] = {
+       {0xaa, 0x82, 0x0000},   /* 00,82,00,aa */
+       {0xaa, 0x83, 0x0000},   /* 00,83,00,aa */
+       {0xaa, 0x84, 0x00ec},   /* 00,84,ec,aa */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
+       {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,0b,cc */
+       {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,10,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
+       {0xa0, 0xec, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,ec,cc */
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},      /* 01,8c,0e,cc */
+       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,15,cc */
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,10,cc */
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
+       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},       /* 00,1d,62,cc */
+       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},       /* 00,1e,90,cc */
+       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},       /* 00,1f,c8,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},       /* 00,20,ff,cc */
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},    /* 01,1d,60,cc */
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc */
+       {0xa0, 0x80, ZC3XX_R18D_YTARGET},       /* 01,8d,80,cc */
+       {}
+};
+
+static const struct usb_action gc0305_NoFliker[] = {
+       {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc */
+       {0xaa, 0x82, 0x0000},   /* 00,82,00,aa */
+       {0xaa, 0x83, 0x0000},   /* 00,83,00,aa */
+       {0xaa, 0x84, 0x0020},   /* 00,84,20,aa */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
+       {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,00,cc */
+       {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,48,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
+       {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,10,cc */
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},      /* 01,8c,0e,cc */
+       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,15,cc */
+       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},       /* 00,1d,62,cc */
+       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},       /* 00,1e,90,cc */
+       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},       /* 00,1f,c8,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},       /* 00,20,ff,cc */
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},    /* 01,1d,60,cc */
+       {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,03,cc */
+       {0xa0, 0x80, ZC3XX_R18D_YTARGET},       /* 01,8d,80,cc */
+       {}
+};
+
+static const struct usb_action hdcs2020_InitialScale[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* qtable 0x05 */
+       {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
+       {0xaa, 0x1c, 0x0000},
+       {0xaa, 0x0a, 0x0001},
+       {0xaa, 0x0b, 0x0006},
+       {0xaa, 0x0c, 0x007b},
+       {0xaa, 0x0d, 0x00a7},
+       {0xaa, 0x03, 0x00fb},
+       {0xaa, 0x05, 0x0000},
+       {0xaa, 0x06, 0x0003},
+       {0xaa, 0x09, 0x0008},
+
+       {0xaa, 0x0f, 0x0018},   /* set sensor gain */
+       {0xaa, 0x10, 0x0018},
+       {0xaa, 0x11, 0x0018},
+       {0xaa, 0x12, 0x0018},
+
+       {0xaa, 0x15, 0x004e},
+       {0xaa, 0x1c, 0x0004},
+       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x70, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa1, 0x01, 0x0002},
+       {0xa1, 0x01, 0x0008},
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x40, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x40, ZC3XX_R118_BGAIN},
+       {0xa1, 0x01, 0x0008},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
+       {0xa1, 0x01, 0x01c8},
+       {0xa1, 0x01, 0x01c9},
+       {0xa1, 0x01, 0x01ca},
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
+       {0xa0, 0x13, ZC3XX_R120_GAMMA00},       /* gamma 4 */
+       {0xa0, 0x38, ZC3XX_R121_GAMMA01},
+       {0xa0, 0x59, ZC3XX_R122_GAMMA02},
+       {0xa0, 0x79, ZC3XX_R123_GAMMA03},
+       {0xa0, 0x92, ZC3XX_R124_GAMMA04},
+       {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
+       {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
+       {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
+       {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
+       {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
+       {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
+       {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
+       {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
+       {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
+       {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
+       {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
+       {0xa0, 0x26, ZC3XX_R130_GAMMA10},
+       {0xa0, 0x22, ZC3XX_R131_GAMMA11},
+       {0xa0, 0x20, ZC3XX_R132_GAMMA12},
+       {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
+       {0xa0, 0x16, ZC3XX_R134_GAMMA14},
+       {0xa0, 0x13, ZC3XX_R135_GAMMA15},
+       {0xa0, 0x10, ZC3XX_R136_GAMMA16},
+       {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
+       {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
+       {0xa0, 0x09, ZC3XX_R139_GAMMA19},
+       {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
+       {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
+       {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
+       {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
+       {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
+       {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
+
+       {0xa0, 0x66, ZC3XX_R10A_RGB00}, /* matrix */
+       {0xa0, 0xed, ZC3XX_R10B_RGB01},
+       {0xa0, 0xed, ZC3XX_R10C_RGB02},
+       {0xa0, 0xed, ZC3XX_R10D_RGB10},
+       {0xa0, 0x66, ZC3XX_R10E_RGB11},
+       {0xa0, 0xed, ZC3XX_R10F_RGB12},
+       {0xa0, 0xed, ZC3XX_R110_RGB20},
+       {0xa0, 0xed, ZC3XX_R111_RGB21},
+       {0xa0, 0x66, ZC3XX_R112_RGB22},
+
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x13, 0x0031},
+       {0xaa, 0x14, 0x0001},
+       {0xaa, 0x0e, 0x0004},
+       {0xaa, 0x19, 0x00cd},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+
+       {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 0x14 */
+       {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x18, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0x41, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x40, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x40, ZC3XX_R118_BGAIN},
+       {}
+};
+static const struct usb_action hdcs2020_Initial[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
+       {0xaa, 0x1c, 0x0000},
+       {0xaa, 0x0a, 0x0001},
+       {0xaa, 0x0b, 0x0006},
+       {0xaa, 0x0c, 0x007a},
+       {0xaa, 0x0d, 0x00a7},
+       {0xaa, 0x03, 0x00fb},
+       {0xaa, 0x05, 0x0000},
+       {0xaa, 0x06, 0x0003},
+       {0xaa, 0x09, 0x0008},
+       {0xaa, 0x0f, 0x0018},   /* original setting */
+       {0xaa, 0x10, 0x0018},
+       {0xaa, 0x11, 0x0018},
+       {0xaa, 0x12, 0x0018},
+       {0xaa, 0x15, 0x004e},
+       {0xaa, 0x1c, 0x0004},
+       {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x70, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa1, 0x01, 0x0002},
+       {0xa1, 0x01, 0x0008},
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x40, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x40, ZC3XX_R118_BGAIN},
+       {0xa1, 0x01, 0x0008},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
+       {0xa1, 0x01, 0x01c8},
+       {0xa1, 0x01, 0x01c9},
+       {0xa1, 0x01, 0x01ca},
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
+       {0xa0, 0x13, ZC3XX_R120_GAMMA00},       /* gamma 4 */
+       {0xa0, 0x38, ZC3XX_R121_GAMMA01},
+       {0xa0, 0x59, ZC3XX_R122_GAMMA02},
+       {0xa0, 0x79, ZC3XX_R123_GAMMA03},
+       {0xa0, 0x92, ZC3XX_R124_GAMMA04},
+       {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
+       {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
+       {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
+       {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
+       {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
+       {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
+       {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
+       {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
+       {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
+       {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
+       {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
+       {0xa0, 0x26, ZC3XX_R130_GAMMA10},
+       {0xa0, 0x22, ZC3XX_R131_GAMMA11},
+       {0xa0, 0x20, ZC3XX_R132_GAMMA12},
+       {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
+       {0xa0, 0x16, ZC3XX_R134_GAMMA14},
+       {0xa0, 0x13, ZC3XX_R135_GAMMA15},
+       {0xa0, 0x10, ZC3XX_R136_GAMMA16},
+       {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
+       {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
+       {0xa0, 0x09, ZC3XX_R139_GAMMA19},
+       {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
+       {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
+       {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
+       {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
+       {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
+       {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
+       {0xa0, 0x66, ZC3XX_R10A_RGB00}, /* matrix */
+       {0xa0, 0xed, ZC3XX_R10B_RGB01},
+       {0xa0, 0xed, ZC3XX_R10C_RGB02},
+       {0xa0, 0xed, ZC3XX_R10D_RGB10},
+       {0xa0, 0x66, ZC3XX_R10E_RGB11},
+       {0xa0, 0xed, ZC3XX_R10F_RGB12},
+       {0xa0, 0xed, ZC3XX_R110_RGB20},
+       {0xa0, 0xed, ZC3XX_R111_RGB21},
+       {0xa0, 0x66, ZC3XX_R112_RGB22},
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+ /**** set exposure ***/
+       {0xaa, 0x13, 0x0031},
+       {0xaa, 0x14, 0x0001},
+       {0xaa, 0x0e, 0x0004},
+       {0xaa, 0x19, 0x00cd},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x18, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0x41, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x40, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x40, ZC3XX_R118_BGAIN},
+       {}
+};
+static const struct usb_action hdcs2020_50HZ[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x13, 0x0018},                   /* 00,13,18,aa */
+       {0xaa, 0x14, 0x0001},                   /* 00,14,01,aa */
+       {0xaa, 0x0e, 0x0005},                   /* 00,0e,05,aa */
+       {0xaa, 0x19, 0x001f},                   /* 00,19,1f,aa */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
+       {0xa0, 0x76, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,76,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x46, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,46,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
+       {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
+       {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,28,cc */
+       {0xa0, 0x05, ZC3XX_R01D_HSYNC_0}, /* 00,1d,05,cc */
+       {0xa0, 0x1a, ZC3XX_R01E_HSYNC_1}, /* 00,1e,1a,cc */
+       {0xa0, 0x2f, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2f,cc */
+       {}
+};
+static const struct usb_action hdcs2020_60HZ[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x13, 0x0031},                   /* 00,13,31,aa */
+       {0xaa, 0x14, 0x0001},                   /* 00,14,01,aa */
+       {0xaa, 0x0e, 0x0004},                   /* 00,0e,04,aa */
+       {0xaa, 0x19, 0x00cd},                   /* 00,19,cd,aa */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
+       {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,62,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3d,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
+       {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
+       {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,28,cc */
+       {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, /* 00,1d,04,cc */
+       {0xa0, 0x18, ZC3XX_R01E_HSYNC_1}, /* 00,1e,18,cc */
+       {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2c,cc */
+       {}
+};
+static const struct usb_action hdcs2020_NoFliker[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x13, 0x0010},                   /* 00,13,10,aa */
+       {0xaa, 0x14, 0x0001},                   /* 00,14,01,aa */
+       {0xaa, 0x0e, 0x0004},                   /* 00,0e,04,aa */
+       {0xaa, 0x19, 0x0000},                   /* 00,19,00,aa */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
+       {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
+       {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, /* 00,1d,04,cc */
+       {0xa0, 0x17, ZC3XX_R01E_HSYNC_1}, /* 00,1e,17,cc */
+       {0xa0, 0x2a, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2a,cc */
+       {}
+};
+
+static const struct usb_action hv7131b_InitialScale[] = {      /* 320x240 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00 */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xaa, 0x30, 0x002d},
+       {0xaa, 0x01, 0x0005},
+       {0xaa, 0x11, 0x0000},
+       {0xaa, 0x13, 0x0001},   /* {0xaa, 0x13, 0x0000}, */
+       {0xaa, 0x14, 0x0001},
+       {0xaa, 0x15, 0x00e8},
+       {0xaa, 0x16, 0x0002},
+       {0xaa, 0x17, 0x0086},           /* 00,17,88,aa */
+       {0xaa, 0x31, 0x0038},
+       {0xaa, 0x32, 0x0038},
+       {0xaa, 0x33, 0x0038},
+       {0xaa, 0x5b, 0x0001},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x68, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0x00, 0x01ad},
+       {0xa0, 0xc0, 0x019b},
+       {0xa0, 0xa0, 0x019c},
+       {0xa0, 0x02, ZC3XX_R188_MINGAIN},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xaa, 0x02, 0x0090},                   /* 00,02,80,aa */
+       {}
+};
+
+static const struct usb_action hv7131b_Initial[] = {   /* 640x480*/
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00 */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xaa, 0x30, 0x002d},
+       {0xaa, 0x01, 0x0005},
+       {0xaa, 0x11, 0x0001},
+       {0xaa, 0x13, 0x0000},   /* {0xaa, 0x13, 0x0001}; */
+       {0xaa, 0x14, 0x0001},
+       {0xaa, 0x15, 0x00e6},
+       {0xaa, 0x16, 0x0002},
+       {0xaa, 0x17, 0x0086},
+       {0xaa, 0x31, 0x0038},
+       {0xaa, 0x32, 0x0038},
+       {0xaa, 0x33, 0x0038},
+       {0xaa, 0x5b, 0x0001},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x70, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0x00, 0x01ad},
+       {0xa0, 0xc0, 0x019b},
+       {0xa0, 0xa0, 0x019c},
+       {0xa0, 0x02, ZC3XX_R188_MINGAIN},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xaa, 0x02, 0x0090},   /* {0xaa, 0x02, 0x0080}, */
+       {}
+};
+static const struct usb_action hv7131b_50HZ[] = {      /* 640x480*/
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x25, 0x0007},                   /* 00,25,07,aa */
+       {0xaa, 0x26, 0x0053},                   /* 00,26,53,aa */
+       {0xaa, 0x27, 0x0000},                   /* 00,27,00,aa */
+       {0xaa, 0x20, 0x0000},                   /* 00,20,00,aa */
+       {0xaa, 0x21, 0x0050},                   /* 00,21,50,aa */
+       {0xaa, 0x22, 0x001b},                   /* 00,22,1b,aa */
+       {0xaa, 0x23, 0x00fc},                   /* 00,23,fc,aa */
+       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,2f,cc */
+       {0xa0, 0x9b, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,9b,cc */
+       {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,80,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
+       {0xa0, 0xea, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,ea,cc */
+       {0xa0, 0x60, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,60,cc */
+       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},      /* 01,8c,0c,cc */
+       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,18,cc */
+       {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,18,cc */
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
+       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},       /* 00,1d,00,cc */
+       {0xa0, 0x50, ZC3XX_R01E_HSYNC_1},       /* 00,1e,50,cc */
+       {0xa0, 0x1b, ZC3XX_R01F_HSYNC_2},       /* 00,1f,1b,cc */
+       {0xa0, 0xfc, ZC3XX_R020_HSYNC_3},       /* 00,20,fc,cc */
+       {}
+};
+static const struct usb_action hv7131b_50HZScale[] = { /* 320x240 */
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x25, 0x0007},                   /* 00,25,07,aa */
+       {0xaa, 0x26, 0x0053},                   /* 00,26,53,aa */
+       {0xaa, 0x27, 0x0000},                   /* 00,27,00,aa */
+       {0xaa, 0x20, 0x0000},                   /* 00,20,00,aa */
+       {0xaa, 0x21, 0x0050},                   /* 00,21,50,aa */
+       {0xaa, 0x22, 0x0012},                   /* 00,22,12,aa */
+       {0xaa, 0x23, 0x0080},                   /* 00,23,80,aa */
+       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,2f,cc */
+       {0xa0, 0x9b, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,9b,cc */
+       {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,80,cc */
+       {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,01,cc */
+       {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,d4,cc */
+       {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,c0,cc */
+       {0xa0, 0x07, ZC3XX_R18C_AEFREEZE},      /* 01,8c,07,cc */
+       {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,0f,cc */
+       {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,18,cc */
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
+       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},       /* 00,1d,00,cc */
+       {0xa0, 0x50, ZC3XX_R01E_HSYNC_1},       /* 00,1e,50,cc */
+       {0xa0, 0x12, ZC3XX_R01F_HSYNC_2},       /* 00,1f,12,cc */
+       {0xa0, 0x80, ZC3XX_R020_HSYNC_3},       /* 00,20,80,cc */
+       {}
+};
+static const struct usb_action hv7131b_60HZ[] = {      /* 640x480*/
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x25, 0x0007},                   /* 00,25,07,aa */
+       {0xaa, 0x26, 0x00a1},                   /* 00,26,a1,aa */
+       {0xaa, 0x27, 0x0020},                   /* 00,27,20,aa */
+       {0xaa, 0x20, 0x0000},                   /* 00,20,00,aa */
+       {0xaa, 0x21, 0x0040},                   /* 00,21,40,aa */
+       {0xaa, 0x22, 0x0013},                   /* 00,22,13,aa */
+       {0xaa, 0x23, 0x004c},                   /* 00,23,4c,aa */
+       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,2f,cc */
+       {0xa0, 0x4d, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,4d,cc */
+       {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,60,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
+       {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,c3,cc */
+       {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,50,cc */
+       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},      /* 01,8c,0c,cc */
+       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,18,cc */
+       {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,18,cc */
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
+       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},       /* 00,1d,00,cc */
+       {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},       /* 00,1e,40,cc */
+       {0xa0, 0x13, ZC3XX_R01F_HSYNC_2},       /* 00,1f,13,cc */
+       {0xa0, 0x4c, ZC3XX_R020_HSYNC_3},       /* 00,20,4c,cc */
+       {}
+};
+static const struct usb_action hv7131b_60HZScale[] = { /* 320x240 */
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x25, 0x0007},                   /* 00,25,07,aa */
+       {0xaa, 0x26, 0x00a1},                   /* 00,26,a1,aa */
+       {0xaa, 0x27, 0x0020},                   /* 00,27,20,aa */
+       {0xaa, 0x20, 0x0000},                   /* 00,20,00,aa */
+       {0xaa, 0x21, 0x00a0},                   /* 00,21,a0,aa */
+       {0xaa, 0x22, 0x0016},                   /* 00,22,16,aa */
+       {0xaa, 0x23, 0x0040},                   /* 00,23,40,aa */
+       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,2f,cc */
+       {0xa0, 0x4d, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,4d,cc */
+       {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,60,cc */
+       {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,01,cc */
+       {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,86,cc */
+       {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,a0,cc */
+       {0xa0, 0x07, ZC3XX_R18C_AEFREEZE},      /* 01,8c,07,cc */
+       {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,0f,cc */
+       {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,18,cc */
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
+       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},       /* 00,1d,00,cc */
+       {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1},       /* 00,1e,a0,cc */
+       {0xa0, 0x16, ZC3XX_R01F_HSYNC_2},       /* 00,1f,16,cc */
+       {0xa0, 0x40, ZC3XX_R020_HSYNC_3},       /* 00,20,40,cc */
+       {}
+};
+static const struct usb_action hv7131b_NoFliker[] = {  /* 640x480*/
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x25, 0x0003},                   /* 00,25,03,aa */
+       {0xaa, 0x26, 0x0000},                   /* 00,26,00,aa */
+       {0xaa, 0x27, 0x0000},                   /* 00,27,00,aa */
+       {0xaa, 0x20, 0x0000},                   /* 00,20,00,aa */
+       {0xaa, 0x21, 0x0010},                   /* 00,21,10,aa */
+       {0xaa, 0x22, 0x0000},                   /* 00,22,00,aa */
+       {0xaa, 0x23, 0x0003},                   /* 00,23,03,aa */
+       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,2f,cc */
+       {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,f8,cc */
+       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,00,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
+       {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,02,cc */
+       {0xa0, 0x00, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,00,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},      /* 01,8c,10,cc */
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,20,cc */
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,00,cc */
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,00,cc */
+       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},       /* 00,1d,00,cc */
+       {0xa0, 0x10, ZC3XX_R01E_HSYNC_1},       /* 00,1e,10,cc */
+       {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},       /* 00,1f,00,cc */
+       {0xa0, 0x03, ZC3XX_R020_HSYNC_3},       /* 00,20,03,cc */
+       {}
+};
+static const struct usb_action hv7131b_NoFlikerScale[] = { /* 320x240 */
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x25, 0x0003},                   /* 00,25,03,aa */
+       {0xaa, 0x26, 0x0000},                   /* 00,26,00,aa */
+       {0xaa, 0x27, 0x0000},                   /* 00,27,00,aa */
+       {0xaa, 0x20, 0x0000},                   /* 00,20,00,aa */
+       {0xaa, 0x21, 0x00a0},                   /* 00,21,a0,aa */
+       {0xaa, 0x22, 0x0016},                   /* 00,22,16,aa */
+       {0xaa, 0x23, 0x0040},                   /* 00,23,40,aa */
+       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,2f,cc */
+       {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,f8,cc */
+       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,00,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
+       {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,02,cc */
+       {0xa0, 0x00, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,00,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},      /* 01,8c,10,cc */
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,20,cc */
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,00,cc */
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,00,cc */
+       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},       /* 00,1d,00,cc */
+       {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1},       /* 00,1e,a0,cc */
+       {0xa0, 0x16, ZC3XX_R01F_HSYNC_2},       /* 00,1f,16,cc */
+       {0xa0, 0x40, ZC3XX_R020_HSYNC_3},       /* 00,20,40,cc */
+       {}
+};
+
+/* from lPEPI264v.inf (hv7131b!) */
+static const struct usb_action hv7131r_InitialScale[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
+       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xdd, 0x00, 0x0200},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xaa, 0x01, 0x000c},
+       {0xaa, 0x11, 0x0000},
+       {0xaa, 0x13, 0x0000},
+       {0xaa, 0x14, 0x0001},
+       {0xaa, 0x15, 0x00e8},
+       {0xaa, 0x16, 0x0002},
+       {0xaa, 0x17, 0x0088},
+       {0xaa, 0x30, 0x000b},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x78, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0x00, 0x01ad},
+       {0xa0, 0xc0, 0x019b},
+       {0xa0, 0xa0, 0x019c},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {}
+};
+static const struct usb_action hv7131r_Initial[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
+       {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
+       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xdd, 0x00, 0x0200},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xaa, 0x01, 0x000c},
+       {0xaa, 0x11, 0x0000},
+       {0xaa, 0x13, 0x0000},
+       {0xaa, 0x14, 0x0001},
+       {0xaa, 0x15, 0x00e6},
+       {0xaa, 0x16, 0x0002},
+       {0xaa, 0x17, 0x0086},
+       {0xaa, 0x30, 0x000b},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x78, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0x00, 0x01ad},
+       {0xa0, 0xc0, 0x019b},
+       {0xa0, 0xa0, 0x019c},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {}
+};
+static const struct usb_action hv7131r_50HZ[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xa0, 0x06, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x68, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0xea, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x60, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action hv7131r_50HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xa0, 0x0c, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0xd1, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x40, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action hv7131r_60HZ[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xa0, 0x06, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x1a, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action hv7131r_60HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xa0, 0x0c, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x35, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action hv7131r_NoFliker[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x58, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action hv7131r_NoFlikerScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x04, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0xb0, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
+       {}
+};
+
+static const struct usb_action icm105a_InitialScale[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x0c, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xa0, 0x00, ZC3XX_R097_WINYSTARTHIGH},
+       {0xa0, 0x01, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R099_WINXSTARTHIGH},
+       {0xa0, 0x01, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x01, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x01, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
+       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xaa, 0x01, 0x0010},
+       {0xaa, 0x03, 0x0000},
+       {0xaa, 0x04, 0x0001},
+       {0xaa, 0x05, 0x0020},
+       {0xaa, 0x06, 0x0001},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0001},
+       {0xaa, 0x04, 0x0011},
+       {0xaa, 0x05, 0x00a0},
+       {0xaa, 0x06, 0x0001},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0002},
+       {0xaa, 0x04, 0x0013},
+       {0xaa, 0x05, 0x0020},
+       {0xaa, 0x06, 0x0001},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0003},
+       {0xaa, 0x04, 0x0015},
+       {0xaa, 0x05, 0x0020},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0004},
+       {0xaa, 0x04, 0x0017},
+       {0xaa, 0x05, 0x0020},
+       {0xaa, 0x06, 0x000d},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0005},
+       {0xaa, 0x04, 0x0019},
+       {0xaa, 0x05, 0x0020},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0006},
+       {0xaa, 0x04, 0x0017},
+       {0xaa, 0x05, 0x0026},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0007},
+       {0xaa, 0x04, 0x0019},
+       {0xaa, 0x05, 0x0022},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0008},
+       {0xaa, 0x04, 0x0021},
+       {0xaa, 0x05, 0x00aa},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0009},
+       {0xaa, 0x04, 0x0023},
+       {0xaa, 0x05, 0x00aa},
+       {0xaa, 0x06, 0x000d},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x000a},
+       {0xaa, 0x04, 0x0025},
+       {0xaa, 0x05, 0x00aa},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x000b},
+       {0xaa, 0x04, 0x00ec},
+       {0xaa, 0x05, 0x002e},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x000c},
+       {0xaa, 0x04, 0x00fa},
+       {0xaa, 0x05, 0x002a},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x07, 0x000d},
+       {0xaa, 0x01, 0x0005},
+       {0xaa, 0x94, 0x0002},
+       {0xaa, 0x90, 0x0000},
+       {0xaa, 0x91, 0x001f},
+       {0xaa, 0x10, 0x0064},
+       {0xaa, 0x9b, 0x00f0},
+       {0xaa, 0x9c, 0x0002},
+       {0xaa, 0x14, 0x001a},
+       {0xaa, 0x20, 0x0080},
+       {0xaa, 0x22, 0x0080},
+       {0xaa, 0x24, 0x0080},
+       {0xaa, 0x26, 0x0080},
+       {0xaa, 0x00, 0x0084},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xaa, 0xa8, 0x00c0},
+       {0xa1, 0x01, 0x0002},
+       {0xa1, 0x01, 0x0008},
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x40, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x40, ZC3XX_R118_BGAIN},
+       {0xa1, 0x01, 0x0008},
+
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
+       {0xa1, 0x01, 0x01c8},
+       {0xa1, 0x01, 0x01c9},
+       {0xa1, 0x01, 0x01ca},
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
+       {0xa0, 0x52, ZC3XX_R10A_RGB00}, /* matrix */
+       {0xa0, 0xf7, ZC3XX_R10B_RGB01},
+       {0xa0, 0xf7, ZC3XX_R10C_RGB02},
+       {0xa0, 0xf7, ZC3XX_R10D_RGB10},
+       {0xa0, 0x52, ZC3XX_R10E_RGB11},
+       {0xa0, 0xf7, ZC3XX_R10F_RGB12},
+       {0xa0, 0xf7, ZC3XX_R110_RGB20},
+       {0xa0, 0xf7, ZC3XX_R111_RGB21},
+       {0xa0, 0x52, ZC3XX_R112_RGB22},
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x0d, 0x0003},
+       {0xaa, 0x0c, 0x008c},
+       {0xaa, 0x0e, 0x0095},
+       {0xaa, 0x0f, 0x0002},
+       {0xaa, 0x1c, 0x0094},
+       {0xaa, 0x1d, 0x0002},
+       {0xaa, 0x20, 0x0080},
+       {0xaa, 0x22, 0x0080},
+       {0xaa, 0x24, 0x0080},
+       {0xaa, 0x26, 0x0080},
+       {0xaa, 0x00, 0x0084},
+       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH},
+       {0xa0, 0x94, ZC3XX_R0A4_EXPOSURETIMELOW},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x84, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xe3, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xec, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xf5, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0xc0, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x40, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x40, ZC3XX_R118_BGAIN},
+       {}
+};
+
+static const struct usb_action icm105a_Initial[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x0c, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xa0, 0x00, ZC3XX_R097_WINYSTARTHIGH},
+       {0xa0, 0x02, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R099_WINXSTARTHIGH},
+       {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x02, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
+       {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
+       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
+       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xaa, 0x01, 0x0010},
+       {0xaa, 0x03, 0x0000},
+       {0xaa, 0x04, 0x0001},
+       {0xaa, 0x05, 0x0020},
+       {0xaa, 0x06, 0x0001},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0001},
+       {0xaa, 0x04, 0x0011},
+       {0xaa, 0x05, 0x00a0},
+       {0xaa, 0x06, 0x0001},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0002},
+       {0xaa, 0x04, 0x0013},
+       {0xaa, 0x05, 0x0020},
+       {0xaa, 0x06, 0x0001},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0003},
+       {0xaa, 0x04, 0x0015},
+       {0xaa, 0x05, 0x0020},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0004},
+       {0xaa, 0x04, 0x0017},
+       {0xaa, 0x05, 0x0020},
+       {0xaa, 0x06, 0x000d},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0005},
+       {0xa0, 0x04, ZC3XX_R092_I2CADDRESSSELECT},
+       {0xa0, 0x19, ZC3XX_R093_I2CSETVALUE},
+       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
+       {0xa1, 0x01, 0x0091},
+       {0xaa, 0x05, 0x0020},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0006},
+       {0xaa, 0x04, 0x0017},
+       {0xaa, 0x05, 0x0026},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0007},
+       {0xaa, 0x04, 0x0019},
+       {0xaa, 0x05, 0x0022},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0008},
+       {0xaa, 0x04, 0x0021},
+       {0xaa, 0x05, 0x00aa},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x0009},
+       {0xaa, 0x04, 0x0023},
+       {0xaa, 0x05, 0x00aa},
+       {0xaa, 0x06, 0x000d},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x000a},
+       {0xaa, 0x04, 0x0025},
+       {0xaa, 0x05, 0x00aa},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x000b},
+       {0xaa, 0x04, 0x00ec},
+       {0xaa, 0x05, 0x002e},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x03, 0x000c},
+       {0xaa, 0x04, 0x00fa},
+       {0xaa, 0x05, 0x002a},
+       {0xaa, 0x06, 0x0005},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x07, 0x000d},
+       {0xaa, 0x01, 0x0005},
+       {0xaa, 0x94, 0x0002},
+       {0xaa, 0x90, 0x0000},
+       {0xaa, 0x91, 0x0010},
+       {0xaa, 0x10, 0x0064},
+       {0xaa, 0x9b, 0x00f0},
+       {0xaa, 0x9c, 0x0002},
+       {0xaa, 0x14, 0x001a},
+       {0xaa, 0x20, 0x0080},
+       {0xaa, 0x22, 0x0080},
+       {0xaa, 0x24, 0x0080},
+       {0xaa, 0x26, 0x0080},
+       {0xaa, 0x00, 0x0084},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xaa, 0xa8, 0x0080},
+       {0xa0, 0x78, ZC3XX_R18D_YTARGET},
+       {0xa1, 0x01, 0x0002},
+       {0xa1, 0x01, 0x0008},
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x40, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x40, ZC3XX_R118_BGAIN},
+       {0xa1, 0x01, 0x0008},
+
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
+       {0xa1, 0x01, 0x01c8},
+       {0xa1, 0x01, 0x01c9},
+       {0xa1, 0x01, 0x01ca},
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
+
+       {0xa0, 0x52, ZC3XX_R10A_RGB00}, /* matrix */
+       {0xa0, 0xf7, ZC3XX_R10B_RGB01},
+       {0xa0, 0xf7, ZC3XX_R10C_RGB02},
+       {0xa0, 0xf7, ZC3XX_R10D_RGB10},
+       {0xa0, 0x52, ZC3XX_R10E_RGB11},
+       {0xa0, 0xf7, ZC3XX_R10F_RGB12},
+       {0xa0, 0xf7, ZC3XX_R110_RGB20},
+       {0xa0, 0xf7, ZC3XX_R111_RGB21},
+       {0xa0, 0x52, ZC3XX_R112_RGB22},
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x0d, 0x0003},
+       {0xaa, 0x0c, 0x0020},
+       {0xaa, 0x0e, 0x000e},
+       {0xaa, 0x0f, 0x0002},
+       {0xaa, 0x1c, 0x000d},
+       {0xaa, 0x1d, 0x0002},
+       {0xaa, 0x20, 0x0080},
+       {0xaa, 0x22, 0x0080},
+       {0xaa, 0x24, 0x0080},
+       {0xaa, 0x26, 0x0080},
+       {0xaa, 0x00, 0x0084},
+       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH},
+       {0xa0, 0x0d, ZC3XX_R0A4_EXPOSURETIMELOW},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x1a, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x4b, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xd8, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xea, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x40, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x40, ZC3XX_R118_BGAIN},
+       {}
+};
+static const struct usb_action icm105a_50HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
+       {0xaa, 0x0c, 0x0020}, /* 00,0c,20,aa */
+       {0xaa, 0x0e, 0x000e}, /* 00,0e,0e,aa */
+       {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
+       {0xaa, 0x1c, 0x000d}, /* 00,1c,0d,aa */
+       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
+       {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
+       {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
+       {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
+       {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
+       {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
+       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
+       {0xa0, 0x0d, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,0d,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
+       {0xa0, 0x1a, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,1a,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x4b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4b,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
+       {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
+       {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */
+       {0xa0, 0xd8, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d8,cc */
+       {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
+       {}
+};
+static const struct usb_action icm105a_50HZ[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
+       {0xaa, 0x0c, 0x008c}, /* 00,0c,8c,aa */
+       {0xaa, 0x0e, 0x0095}, /* 00,0e,95,aa */
+       {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
+       {0xaa, 0x1c, 0x0094}, /* 00,1c,94,aa */
+       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
+       {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
+       {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
+       {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
+       {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
+       {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
+       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
+       {0xa0, 0x94, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,94,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
+       {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x84, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,84,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
+       {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
+       {0xa0, 0xe3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,e3,cc */
+       {0xa0, 0xec, ZC3XX_R01E_HSYNC_1}, /* 00,1e,ec,cc */
+       {0xa0, 0xf5, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f5,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
+       {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
+       {}
+};
+static const struct usb_action icm105a_60HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
+       {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
+       {0xaa, 0x0e, 0x000d}, /* 00,0e,0d,aa */
+       {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
+       {0xaa, 0x1c, 0x0008}, /* 00,1c,08,aa */
+       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
+       {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
+       {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
+       {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
+       {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
+       {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
+       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
+       {0xa0, 0x08, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,08,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
+       {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x41, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,41,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
+       {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
+       {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
+       {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
+       {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
+       {}
+};
+static const struct usb_action icm105a_60HZ[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
+       {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */
+       {0xaa, 0x0e, 0x0086}, /* 00,0e,86,aa */
+       {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
+       {0xaa, 0x1c, 0x0085}, /* 00,1c,85,aa */
+       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
+       {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
+       {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
+       {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
+       {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
+       {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
+       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
+       {0xa0, 0x85, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,85,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
+       {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,08,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
+       {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
+       {0xa0, 0xc2, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c2,cc */
+       {0xa0, 0xd6, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d6,cc */
+       {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
+       {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
+       {}
+};
+static const struct usb_action icm105a_NoFlikerScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
+       {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
+       {0xaa, 0x0e, 0x000d}, /* 00,0e,0d,aa */
+       {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
+       {0xaa, 0x1c, 0x0000}, /* 00,1c,00,aa */
+       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
+       {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
+       {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
+       {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
+       {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
+       {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
+       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
+       {0xa0, 0x00, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,00,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
+       {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
+       {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
+       {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
+       {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
+       {}
+};
+static const struct usb_action icm105a_NoFliker[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
+       {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
+       {0xaa, 0x0e, 0x0081}, /* 00,0e,81,aa */
+       {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
+       {0xaa, 0x1c, 0x0080}, /* 00,1c,80,aa */
+       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
+       {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
+       {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
+       {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
+       {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
+       {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
+       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
+       {0xa0, 0x80, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,80,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
+       {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
+       {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
+       {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
+       {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
+       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
+       {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
+       {}
+};
+
+static const struct usb_action mc501cb_Initial[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
+       {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
+       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
+       {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */
+       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
+       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
+       {0xa0, 0x33, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,33,cc */
+       {0xa0, 0x34, ZC3XX_R087_EXPTIMEMID}, /* 00,87,34,cc */
+       {0xa0, 0x35, ZC3XX_R088_EXPTIMELOW}, /* 00,88,35,cc */
+       {0xa0, 0xb0, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,b0,cc */
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
+       {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
+       {0xaa, 0x01, 0x0003}, /* 00,01,03,aa */
+       {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
+       {0xaa, 0x03, 0x0000}, /* 00,03,00,aa */
+       {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
+       {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
+       {0xaa, 0x12, 0x0000}, /* 00,12,00,aa */
+       {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
+       {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
+       {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
+       {0xaa, 0x16, 0x0000}, /* 00,16,00,aa */
+       {0xaa, 0x17, 0x0001}, /* 00,17,01,aa */
+       {0xaa, 0x18, 0x00de}, /* 00,18,de,aa */
+       {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
+       {0xaa, 0x1a, 0x0086}, /* 00,1a,86,aa */
+       {0xaa, 0x20, 0x00a8}, /* 00,20,a8,aa */
+       {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
+       {0xaa, 0x23, 0x0000}, /* 00,23,00,aa */
+       {0xaa, 0x24, 0x0000}, /* 00,24,00,aa */
+       {0xaa, 0x40, 0x0033}, /* 00,40,33,aa */
+       {0xaa, 0x41, 0x0077}, /* 00,41,77,aa */
+       {0xaa, 0x42, 0x0053}, /* 00,42,53,aa */
+       {0xaa, 0x43, 0x00b0}, /* 00,43,b0,aa */
+       {0xaa, 0x4b, 0x0001}, /* 00,4b,01,aa */
+       {0xaa, 0x72, 0x0020}, /* 00,72,20,aa */
+       {0xaa, 0x73, 0x0000}, /* 00,73,00,aa */
+       {0xaa, 0x80, 0x0000}, /* 00,80,00,aa */
+       {0xaa, 0x85, 0x0050}, /* 00,85,50,aa */
+       {0xaa, 0x91, 0x0070}, /* 00,91,70,aa */
+       {0xaa, 0x92, 0x0072}, /* 00,92,72,aa */
+       {0xaa, 0x03, 0x0001}, /* 00,03,01,aa */
+       {0xaa, 0x10, 0x00a0}, /* 00,10,a0,aa */
+       {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */
+       {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */
+       {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */
+       {0xaa, 0xa0, 0x001a}, /* 00,a0,1a,aa */
+       {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */
+       {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */
+       {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */
+       {0xaa, 0xa4, 0x0010}, /* 00,a4,10,aa */
+       {0xaa, 0xa5, 0x0020}, /* 00,a5,20,aa */
+       {0xaa, 0xb1, 0x0044}, /* 00,b1,44,aa */
+       {0xaa, 0xd0, 0x0001}, /* 00,d0,01,aa */
+       {0xaa, 0xd1, 0x0085}, /* 00,d1,85,aa */
+       {0xaa, 0xd2, 0x0080}, /* 00,d2,80,aa */
+       {0xaa, 0xd3, 0x0080}, /* 00,d3,80,aa */
+       {0xaa, 0xd4, 0x0080}, /* 00,d4,80,aa */
+       {0xaa, 0xd5, 0x0080}, /* 00,d5,80,aa */
+       {0xaa, 0xc0, 0x00c3}, /* 00,c0,c3,aa */
+       {0xaa, 0xc2, 0x0044}, /* 00,c2,44,aa */
+       {0xaa, 0xc4, 0x0040}, /* 00,c4,40,aa */
+       {0xaa, 0xc5, 0x0020}, /* 00,c5,20,aa */
+       {0xaa, 0xc6, 0x0008}, /* 00,c6,08,aa */
+       {0xaa, 0x03, 0x0004}, /* 00,03,04,aa */
+       {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
+       {0xaa, 0x40, 0x0030}, /* 00,40,30,aa */
+       {0xaa, 0x41, 0x0020}, /* 00,41,20,aa */
+       {0xaa, 0x42, 0x002d}, /* 00,42,2d,aa */
+       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
+       {0xaa, 0x1c, 0x0050}, /* 00,1C,50,aa */
+       {0xaa, 0x11, 0x0081}, /* 00,11,81,aa */
+       {0xaa, 0x3b, 0x001d}, /* 00,3b,1D,aa */
+       {0xaa, 0x3c, 0x004c}, /* 00,3c,4C,aa */
+       {0xaa, 0x3d, 0x0018}, /* 00,3d,18,aa */
+       {0xaa, 0x3e, 0x006a}, /* 00,3e,6A,aa */
+       {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
+       {0xaa, 0x52, 0x00ff}, /* 00,52,FF,aa */
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
+       {0xaa, 0x03, 0x0002}, /* 00,03,02,aa */
+       {0xaa, 0x51, 0x0027}, /* 00,51,27,aa */
+       {0xaa, 0x52, 0x0020}, /* 00,52,20,aa */
+       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
+       {0xaa, 0x50, 0x0010}, /* 00,50,10,aa */
+       {0xaa, 0x51, 0x0010}, /* 00,51,10,aa */
+       {0xaa, 0x54, 0x0010}, /* 00,54,10,aa */
+       {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */
+       {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */
+       {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */
+
+       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
+       {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
+       {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
+       {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */
+       {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */
+       {}
+};
+
+static const struct usb_action mc501cb_InitialScale[] = {      /* 320x240 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
+       {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
+       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
+       {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */
+       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
+       {0xa0, 0x33, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,33,cc */
+       {0xa0, 0x34, ZC3XX_R087_EXPTIMEMID}, /* 00,87,34,cc */
+       {0xa0, 0x35, ZC3XX_R088_EXPTIMELOW}, /* 00,88,35,cc */
+       {0xa0, 0xb0, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,b0,cc */
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
+       {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
+       {0xaa, 0x01, 0x0003}, /* 00,01,03,aa */
+       {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
+       {0xaa, 0x03, 0x0000}, /* 00,03,00,aa */
+       {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
+       {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
+       {0xaa, 0x12, 0x0000}, /* 00,12,00,aa */
+       {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
+       {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
+       {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
+       {0xaa, 0x16, 0x0000}, /* 00,16,00,aa */
+       {0xaa, 0x17, 0x0001}, /* 00,17,01,aa */
+       {0xaa, 0x18, 0x00d8}, /* 00,18,d8,aa */
+       {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
+       {0xaa, 0x1a, 0x0088}, /* 00,1a,88,aa */
+       {0xaa, 0x20, 0x00a8}, /* 00,20,a8,aa */
+       {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
+       {0xaa, 0x23, 0x0000}, /* 00,23,00,aa */
+       {0xaa, 0x24, 0x0000}, /* 00,24,00,aa */
+       {0xaa, 0x40, 0x0033}, /* 00,40,33,aa */
+       {0xaa, 0x41, 0x0077}, /* 00,41,77,aa */
+       {0xaa, 0x42, 0x0053}, /* 00,42,53,aa */
+       {0xaa, 0x43, 0x00b0}, /* 00,43,b0,aa */
+       {0xaa, 0x4b, 0x0001}, /* 00,4b,01,aa */
+       {0xaa, 0x72, 0x0020}, /* 00,72,20,aa */
+       {0xaa, 0x73, 0x0000}, /* 00,73,00,aa */
+       {0xaa, 0x80, 0x0000}, /* 00,80,00,aa */
+       {0xaa, 0x85, 0x0050}, /* 00,85,50,aa */
+       {0xaa, 0x91, 0x0070}, /* 00,91,70,aa */
+       {0xaa, 0x92, 0x0072}, /* 00,92,72,aa */
+       {0xaa, 0x03, 0x0001}, /* 00,03,01,aa */
+       {0xaa, 0x10, 0x00a0}, /* 00,10,a0,aa */
+       {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */
+       {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */
+       {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */
+       {0xaa, 0xa0, 0x001a}, /* 00,a0,1a,aa */
+       {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */
+       {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */
+       {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */
+       {0xaa, 0xa4, 0x0010}, /* 00,a4,10,aa */
+       {0xaa, 0xa5, 0x0020}, /* 00,a5,20,aa */
+       {0xaa, 0xb1, 0x0044}, /* 00,b1,44,aa */
+       {0xaa, 0xd0, 0x0001}, /* 00,d0,01,aa */
+       {0xaa, 0xd1, 0x0085}, /* 00,d1,85,aa */
+       {0xaa, 0xd2, 0x0080}, /* 00,d2,80,aa */
+       {0xaa, 0xd3, 0x0080}, /* 00,d3,80,aa */
+       {0xaa, 0xd4, 0x0080}, /* 00,d4,80,aa */
+       {0xaa, 0xd5, 0x0080}, /* 00,d5,80,aa */
+       {0xaa, 0xc0, 0x00c3}, /* 00,c0,c3,aa */
+       {0xaa, 0xc2, 0x0044}, /* 00,c2,44,aa */
+       {0xaa, 0xc4, 0x0040}, /* 00,c4,40,aa */
+       {0xaa, 0xc5, 0x0020}, /* 00,c5,20,aa */
+       {0xaa, 0xc6, 0x0008}, /* 00,c6,08,aa */
+       {0xaa, 0x03, 0x0004}, /* 00,03,04,aa */
+       {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
+       {0xaa, 0x40, 0x0030}, /* 00,40,30,aa */
+       {0xaa, 0x41, 0x0020}, /* 00,41,20,aa */
+       {0xaa, 0x42, 0x002d}, /* 00,42,2d,aa */
+       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
+       {0xaa, 0x1c, 0x0050}, /* 00,1c,50,aa */
+       {0xaa, 0x11, 0x0081}, /* 00,11,81,aa */
+       {0xaa, 0x3b, 0x003a}, /* 00,3b,3A,aa */
+       {0xaa, 0x3c, 0x0098}, /* 00,3c,98,aa */
+       {0xaa, 0x3d, 0x0030}, /* 00,3d,30,aa */
+       {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
+       {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
+       {0xaa, 0x52, 0x00ff}, /* 00,52,FF,aa */
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
+       {0xaa, 0x03, 0x0002}, /* 00,03,02,aa */
+       {0xaa, 0x51, 0x004e}, /* 00,51,4E,aa */
+       {0xaa, 0x52, 0x0041}, /* 00,52,41,aa */
+       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
+       {0xaa, 0x50, 0x0010}, /* 00,50,10,aa */
+       {0xaa, 0x51, 0x0010}, /* 00,51,10,aa */
+       {0xaa, 0x54, 0x0010}, /* 00,54,10,aa */
+       {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */
+       {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */
+       {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */
+       {}
+};
+
+static const struct usb_action mc501cb_50HZ[] = {
+       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
+       {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
+       {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
+       {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */
+       {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */
+       {0xaa, 0x3c, 0x004c}, /* 00,3C,4C,aa */
+       {0xaa, 0x3d, 0x001d}, /* 00,3D,1D,aa */
+       {0xaa, 0x3e, 0x004c}, /* 00,3E,4C,aa */
+       {}
+};
+
+static const struct usb_action mc501cb_50HZScale[] = {
+       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
+       {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
+       {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */
+       {0xaa, 0x37, 0x0098}, /* 00,37,98,aa */
+       {0xaa, 0x3b, 0x003a}, /* 00,3B,3A,aa */
+       {0xaa, 0x3c, 0x0098}, /* 00,3C,98,aa */
+       {0xaa, 0x3d, 0x003a}, /* 00,3D,3A,aa */
+       {0xaa, 0x3e, 0x0098}, /* 00,3E,98,aa */
+       {}
+};
+
+static const struct usb_action mc501cb_60HZ[] = {
+       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
+       {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
+       {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
+       {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
+       {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
+       {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */
+       {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */
+       {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */
+       {}
+};
+
+static const struct usb_action mc501cb_60HZScale[] = {
+       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
+       {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
+       {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
+       {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
+       {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
+       {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
+       {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */
+       {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */
+       {}
+};
+
+static const struct usb_action mc501cb_NoFliker[] = {
+       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
+       {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
+       {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
+       {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
+       {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
+       {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */
+       {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */
+       {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */
+       {}
+};
+
+static const struct usb_action mc501cb_NoFlikerScale[] = {
+       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
+       {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
+       {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
+       {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
+       {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
+       {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
+       {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */
+       {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */
+       {}
+};
+
+/* from zs211.inf */
+static const struct usb_action ov7620_Initial[] = {    /* 640x480 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
+       {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, /* 00,02,40,cc */
+       {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
+       {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */
+       {0xa0, 0x02, ZC3XX_R083_RGAINADDR}, /* 00,83,02,cc */
+       {0xa0, 0x01, ZC3XX_R085_BGAINADDR}, /* 00,85,01,cc */
+       {0xa0, 0x80, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,80,cc */
+       {0xa0, 0x81, ZC3XX_R087_EXPTIMEMID}, /* 00,87,81,cc */
+       {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW}, /* 00,88,10,cc */
+       {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,a1,cc */
+       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
+       {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
+       {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */
+       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
+       {0xaa, 0x12, 0x0088}, /* 00,12,88,aa */
+       {0xaa, 0x12, 0x0048}, /* 00,12,48,aa */
+       {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
+       {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
+       {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
+       {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
+       {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
+       {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
+       {0xaa, 0x17, 0x0018}, /* 00,17,18,aa */
+       {0xaa, 0x18, 0x00ba}, /* 00,18,ba,aa */
+       {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
+       {0xaa, 0x1a, 0x00f1}, /* 00,1a,f1,aa */
+       {0xaa, 0x20, 0x0040}, /* 00,20,40,aa */
+       {0xaa, 0x24, 0x0088}, /* 00,24,88,aa */
+       {0xaa, 0x25, 0x0078}, /* 00,25,78,aa */
+       {0xaa, 0x27, 0x00f6}, /* 00,27,f6,aa */
+       {0xaa, 0x28, 0x00a0}, /* 00,28,a0,aa */
+       {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
+       {0xaa, 0x2a, 0x0083}, /* 00,2a,83,aa */
+       {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
+       {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
+       {0xaa, 0x74, 0x0020}, /* 00,74,20,aa */
+       {0xaa, 0x61, 0x0068}, /* 00,61,68,aa */
+       {0xaa, 0x64, 0x0088}, /* 00,64,88,aa */
+       {0xaa, 0x00, 0x0000}, /* 00,00,00,aa */
+       {0xaa, 0x06, 0x0080}, /* 00,06,80,aa */
+       {0xaa, 0x01, 0x0090}, /* 00,01,90,aa */
+       {0xaa, 0x02, 0x0030}, /* 00,02,30,aa */
+       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,77,cc */
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
+       {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
+       {0xa0, 0x68, ZC3XX_R116_RGAIN}, /* 01,16,68,cc */
+       {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
+       {0xa0, 0x40, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,40,cc */
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
+       {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */
+       {}
+};
+static const struct usb_action ov7620_InitialScale[] = {       /* 320x240 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
+       {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT},   /* 00,02,50,cc */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00,08,00,cc */
+                                               /* mx change? */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
+       {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */
+       {0xa0, 0x02, ZC3XX_R083_RGAINADDR},     /* 00,83,02,cc */
+       {0xa0, 0x01, ZC3XX_R085_BGAINADDR},     /* 00,85,01,cc */
+       {0xa0, 0x80, ZC3XX_R086_EXPTIMEHIGH},   /* 00,86,80,cc */
+       {0xa0, 0x81, ZC3XX_R087_EXPTIMEMID},    /* 00,87,81,cc */
+       {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW},    /* 00,88,10,cc */
+       {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,a1,cc */
+       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
+       {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},  /* 00,98,00,cc */
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},  /* 00,9a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},     /* 01,1a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},     /* 01,1c,00,cc */
+       {0xa0, 0xd6, ZC3XX_R09C_WINHEIGHTLOW},  /* 00,9c,d6,cc */
+                                               /* OV7648 00,9c,d8,cc */
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},   /* 00,9e,88,cc */
+       {0xaa, 0x12, 0x0088}, /* 00,12,88,aa */
+       {0xaa, 0x12, 0x0048}, /* 00,12,48,aa */
+       {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
+       {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
+       {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
+       {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
+       {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
+       {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
+       {0xaa, 0x24, 0x0088}, /* 00,24,88,aa */
+       {0xaa, 0x25, 0x0078}, /* 00,25,78,aa */
+       {0xaa, 0x17, 0x0018}, /* 00,17,18,aa */
+       {0xaa, 0x18, 0x00ba}, /* 00,18,ba,aa */
+       {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
+       {0xaa, 0x1a, 0x00f2}, /* 00,1a,f2,aa */
+       {0xaa, 0x20, 0x0040}, /* 00,20,40,aa */
+       {0xaa, 0x27, 0x00f6}, /* 00,27,f6,aa */
+       {0xaa, 0x28, 0x00a0}, /* 00,28,a0,aa */
+       {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
+       {0xaa, 0x2a, 0x0083}, /* 00,2a,83,aa */
+       {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
+       {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
+       {0xaa, 0x74, 0x0020}, /* 00,74,20,aa */
+       {0xaa, 0x61, 0x0068}, /* 00,61,68,aa */
+       {0xaa, 0x64, 0x0088}, /* 00,64,88,aa */
+       {0xaa, 0x00, 0x0000}, /* 00,00,00,aa */
+       {0xaa, 0x06, 0x0080}, /* 00,06,80,aa */
+       {0xaa, 0x01, 0x0090}, /* 00,01,90,aa */
+       {0xaa, 0x02, 0x0030}, /* 00,02,30,aa */
+       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,77,cc */
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},     /* 01,89,06,cc */
+       {0xa0, 0x00, 0x01ad},                   /* 01,ad,00,cc */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},   /* 01,cb,13,cc */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},  /* 03,01,08,cc */
+       {0xa0, 0x68, ZC3XX_R116_RGAIN},         /* 01,16,68,cc */
+       {0xa0, 0x52, ZC3XX_R118_BGAIN},         /* 01,18,52,cc */
+       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},    /* 01,1d,50,cc */
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
+       {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},   /* 01,a8,50,cc */
+       {}
+};
+static const struct usb_action ov7620_50HZ[] = {
+       {0xaa, 0x13, 0x00a3},   /* 00,13,a3,aa */
+       {0xdd, 0x00, 0x0100},   /* 00,01,00,dd */
+       {0xaa, 0x2b, 0x0096},   /* 00,2b,96,aa */
+       {0xaa, 0x75, 0x008a},   /* 00,75,8a,aa */
+       {0xaa, 0x2d, 0x0005},   /* 00,2d,05,aa */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,04,cc */
+       {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,18,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
+       {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,83,cc */
+       {0xaa, 0x10, 0x0082},                           /* 00,10,82,aa */
+       {0xaa, 0x76, 0x0003},                           /* 00,76,03,aa */
+/*     {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT},            * 00,02,40,cc
+                                                        * if mode0 (640x480) */
+       {}
+};
+static const struct usb_action ov7620_60HZ[] = {
+       {0xaa, 0x13, 0x00a3},                   /* 00,13,a3,aa */
+                                               /* (bug in zs211.inf) */
+       {0xdd, 0x00, 0x0100},                   /* 00,01,00,dd */
+       {0xaa, 0x2b, 0x0000},                   /* 00,2b,00,aa */
+       {0xaa, 0x75, 0x008a},                   /* 00,75,8a,aa */
+       {0xaa, 0x2d, 0x0005},                   /* 00,2d,05,aa */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
+       {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */
+       {0xaa, 0x10, 0x0020},                   /* 00,10,20,aa */
+       {0xaa, 0x76, 0x0003},                   /* 00,76,03,aa */
+/*     {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT},    * 00,02,40,cc
+                                                * if mode0 (640x480) */
+/* ?? in gspca v1, it was
+       {0xa0, 0x00, 0x0039},  * 00,00,00,dd *
+       {0xa1, 0x01, 0x0037},           */
+       {}
+};
+static const struct usb_action ov7620_NoFliker[] = {
+       {0xaa, 0x13, 0x00a3},                   /* 00,13,a3,aa */
+                                               /* (bug in zs211.inf) */
+       {0xdd, 0x00, 0x0100},                   /* 00,01,00,dd */
+       {0xaa, 0x2b, 0x0000},                   /* 00,2b,00,aa */
+       {0xaa, 0x75, 0x008e},                   /* 00,75,8e,aa */
+       {0xaa, 0x2d, 0x0001},                   /* 00,2d,01,aa */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
+       {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,01,cc */
+/*     {0xa0, 0x44, ZC3XX_R002_CLOCKSELECT},    * 00,02,44,cc
+                                                * if mode1 (320x240) */
+/* ?? was
+       {0xa0, 0x00, 0x0039},  * 00,00,00,dd *
+       {0xa1, 0x01, 0x0037},           */
+       {}
+};
+
+static const struct usb_action ov7630c_InitialScale[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xaa, 0x12, 0x0080},
+       {0xa0, 0x02, ZC3XX_R083_RGAINADDR},
+       {0xa0, 0x01, ZC3XX_R085_BGAINADDR},
+       {0xa0, 0x90, ZC3XX_R086_EXPTIMEHIGH},
+       {0xa0, 0x91, ZC3XX_R087_EXPTIMEMID},
+       {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
+       {0xaa, 0x12, 0x0069},
+       {0xaa, 0x04, 0x0020},
+       {0xaa, 0x06, 0x0050},
+       {0xaa, 0x13, 0x0083},
+       {0xaa, 0x14, 0x0000},
+       {0xaa, 0x15, 0x0024},
+       {0xaa, 0x17, 0x0018},
+       {0xaa, 0x18, 0x00ba},
+       {0xaa, 0x19, 0x0002},
+       {0xaa, 0x1a, 0x00f6},
+       {0xaa, 0x1b, 0x0002},
+       {0xaa, 0x20, 0x00c2},
+       {0xaa, 0x24, 0x0060},
+       {0xaa, 0x25, 0x0040},
+       {0xaa, 0x26, 0x0030},
+       {0xaa, 0x27, 0x00ea},
+       {0xaa, 0x28, 0x00a0},
+       {0xaa, 0x21, 0x0000},
+       {0xaa, 0x2a, 0x0081},
+       {0xaa, 0x2b, 0x0096},
+       {0xaa, 0x2d, 0x0094},
+       {0xaa, 0x2f, 0x003d},
+       {0xaa, 0x30, 0x0024},
+       {0xaa, 0x60, 0x0000},
+       {0xaa, 0x61, 0x0040},
+       {0xaa, 0x68, 0x007c},
+       {0xaa, 0x6f, 0x0015},
+       {0xaa, 0x75, 0x0088},
+       {0xaa, 0x77, 0x00b5},
+       {0xaa, 0x01, 0x0060},
+       {0xaa, 0x02, 0x0060},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x00, 0x01ad},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa0, 0x60, ZC3XX_R116_RGAIN},
+       {0xa0, 0x46, ZC3XX_R118_BGAIN},
+       {0xa0, 0x04, ZC3XX_R113_RGB03},
+/* 0x10, */
+       {0xa1, 0x01, 0x0002},
+       {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
+       {0xa0, 0xf8, ZC3XX_R10B_RGB01},
+       {0xa0, 0xf8, ZC3XX_R10C_RGB02},
+       {0xa0, 0xf8, ZC3XX_R10D_RGB10},
+       {0xa0, 0x50, ZC3XX_R10E_RGB11},
+       {0xa0, 0xf8, ZC3XX_R10F_RGB12},
+       {0xa0, 0xf8, ZC3XX_R110_RGB20},
+       {0xa0, 0xf8, ZC3XX_R111_RGB21},
+       {0xa0, 0x50, ZC3XX_R112_RGB22},
+       {0xa1, 0x01, 0x0008},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
+       {0xa1, 0x01, 0x01c8},
+       {0xa1, 0x01, 0x01c9},
+       {0xa1, 0x01, 0x01ca},
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
+       {0xa0, 0x01, ZC3XX_R120_GAMMA00},       /* gamma 2 ?*/
+       {0xa0, 0x0c, ZC3XX_R121_GAMMA01},
+       {0xa0, 0x1f, ZC3XX_R122_GAMMA02},
+       {0xa0, 0x3a, ZC3XX_R123_GAMMA03},
+       {0xa0, 0x53, ZC3XX_R124_GAMMA04},
+       {0xa0, 0x6d, ZC3XX_R125_GAMMA05},
+       {0xa0, 0x85, ZC3XX_R126_GAMMA06},
+       {0xa0, 0x9c, ZC3XX_R127_GAMMA07},
+       {0xa0, 0xb0, ZC3XX_R128_GAMMA08},
+       {0xa0, 0xc2, ZC3XX_R129_GAMMA09},
+       {0xa0, 0xd1, ZC3XX_R12A_GAMMA0A},
+       {0xa0, 0xde, ZC3XX_R12B_GAMMA0B},
+       {0xa0, 0xe9, ZC3XX_R12C_GAMMA0C},
+       {0xa0, 0xf2, ZC3XX_R12D_GAMMA0D},
+       {0xa0, 0xf9, ZC3XX_R12E_GAMMA0E},
+       {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
+       {0xa0, 0x05, ZC3XX_R130_GAMMA10},
+       {0xa0, 0x0f, ZC3XX_R131_GAMMA11},
+       {0xa0, 0x16, ZC3XX_R132_GAMMA12},
+       {0xa0, 0x1a, ZC3XX_R133_GAMMA13},
+       {0xa0, 0x19, ZC3XX_R134_GAMMA14},
+       {0xa0, 0x19, ZC3XX_R135_GAMMA15},
+       {0xa0, 0x17, ZC3XX_R136_GAMMA16},
+       {0xa0, 0x15, ZC3XX_R137_GAMMA17},
+       {0xa0, 0x12, ZC3XX_R138_GAMMA18},
+       {0xa0, 0x10, ZC3XX_R139_GAMMA19},
+       {0xa0, 0x0e, ZC3XX_R13A_GAMMA1A},
+       {0xa0, 0x0b, ZC3XX_R13B_GAMMA1B},
+       {0xa0, 0x09, ZC3XX_R13C_GAMMA1C},
+       {0xa0, 0x08, ZC3XX_R13D_GAMMA1D},
+       {0xa0, 0x06, ZC3XX_R13E_GAMMA1E},
+       {0xa0, 0x03, ZC3XX_R13F_GAMMA1F},
+       {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
+       {0xa0, 0xf8, ZC3XX_R10B_RGB01},
+       {0xa0, 0xf8, ZC3XX_R10C_RGB02},
+       {0xa0, 0xf8, ZC3XX_R10D_RGB10},
+       {0xa0, 0x50, ZC3XX_R10E_RGB11},
+       {0xa0, 0xf8, ZC3XX_R10F_RGB12},
+       {0xa0, 0xf8, ZC3XX_R110_RGB20},
+       {0xa0, 0xf8, ZC3XX_R111_RGB21},
+       {0xa0, 0x50, ZC3XX_R112_RGB22},
+
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xaa, 0x10, 0x001b},
+       {0xaa, 0x76, 0x0002},
+       {0xaa, 0x2a, 0x0081},
+       {0xaa, 0x2b, 0x0000},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xb8, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x37, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xaa, 0x13, 0x0083},   /* 40 */
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {}
+};
+
+static const struct usb_action ov7630c_Initial[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+
+       {0xaa, 0x12, 0x0080},
+       {0xa0, 0x02, ZC3XX_R083_RGAINADDR},
+       {0xa0, 0x01, ZC3XX_R085_BGAINADDR},
+       {0xa0, 0x90, ZC3XX_R086_EXPTIMEHIGH},
+       {0xa0, 0x91, ZC3XX_R087_EXPTIMEMID},
+       {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
+       {0xaa, 0x12, 0x0069},   /* i2c */
+       {0xaa, 0x04, 0x0020},
+       {0xaa, 0x06, 0x0050},
+       {0xaa, 0x13, 0x00c3},
+       {0xaa, 0x14, 0x0000},
+       {0xaa, 0x15, 0x0024},
+       {0xaa, 0x19, 0x0003},
+       {0xaa, 0x1a, 0x00f6},
+       {0xaa, 0x1b, 0x0002},
+       {0xaa, 0x20, 0x00c2},
+       {0xaa, 0x24, 0x0060},
+       {0xaa, 0x25, 0x0040},
+       {0xaa, 0x26, 0x0030},
+       {0xaa, 0x27, 0x00ea},
+       {0xaa, 0x28, 0x00a0},
+       {0xaa, 0x21, 0x0000},
+       {0xaa, 0x2a, 0x0081},
+       {0xaa, 0x2b, 0x0096},
+       {0xaa, 0x2d, 0x0084},
+       {0xaa, 0x2f, 0x003d},
+       {0xaa, 0x30, 0x0024},
+       {0xaa, 0x60, 0x0000},
+       {0xaa, 0x61, 0x0040},
+       {0xaa, 0x68, 0x007c},
+       {0xaa, 0x6f, 0x0015},
+       {0xaa, 0x75, 0x0088},
+       {0xaa, 0x77, 0x00b5},
+       {0xaa, 0x01, 0x0060},
+       {0xaa, 0x02, 0x0060},
+       {0xaa, 0x17, 0x0018},
+       {0xaa, 0x18, 0x00ba},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
+       {0xa0, 0x00, 0x01ad},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa0, 0x60, ZC3XX_R116_RGAIN},
+       {0xa0, 0x46, ZC3XX_R118_BGAIN},
+       {0xa0, 0x04, ZC3XX_R113_RGB03},
+
+       {0xa1, 0x01, 0x0002},
+       {0xa0, 0x4e, ZC3XX_R10A_RGB00}, /* matrix */
+       {0xa0, 0xfe, ZC3XX_R10B_RGB01},
+       {0xa0, 0xf4, ZC3XX_R10C_RGB02},
+       {0xa0, 0xf7, ZC3XX_R10D_RGB10},
+       {0xa0, 0x4d, ZC3XX_R10E_RGB11},
+       {0xa0, 0xfc, ZC3XX_R10F_RGB12},
+       {0xa0, 0x00, ZC3XX_R110_RGB20},
+       {0xa0, 0xf6, ZC3XX_R111_RGB21},
+       {0xa0, 0x4a, ZC3XX_R112_RGB22},
+
+       {0xa1, 0x01, 0x0008},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
+       {0xa1, 0x01, 0x01c8},
+       {0xa1, 0x01, 0x01c9},
+       {0xa1, 0x01, 0x01ca},
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
+       {0xa0, 0x16, ZC3XX_R120_GAMMA00},       /* gamma ~4 */
+       {0xa0, 0x3a, ZC3XX_R121_GAMMA01},
+       {0xa0, 0x5b, ZC3XX_R122_GAMMA02},
+       {0xa0, 0x7c, ZC3XX_R123_GAMMA03},
+       {0xa0, 0x94, ZC3XX_R124_GAMMA04},
+       {0xa0, 0xa9, ZC3XX_R125_GAMMA05},
+       {0xa0, 0xbb, ZC3XX_R126_GAMMA06},
+       {0xa0, 0xca, ZC3XX_R127_GAMMA07},
+       {0xa0, 0xd7, ZC3XX_R128_GAMMA08},
+       {0xa0, 0xe1, ZC3XX_R129_GAMMA09},
+       {0xa0, 0xea, ZC3XX_R12A_GAMMA0A},
+       {0xa0, 0xf1, ZC3XX_R12B_GAMMA0B},
+       {0xa0, 0xf7, ZC3XX_R12C_GAMMA0C},
+       {0xa0, 0xfc, ZC3XX_R12D_GAMMA0D},
+       {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
+       {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
+       {0xa0, 0x20, ZC3XX_R130_GAMMA10},
+       {0xa0, 0x22, ZC3XX_R131_GAMMA11},
+       {0xa0, 0x20, ZC3XX_R132_GAMMA12},
+       {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
+       {0xa0, 0x16, ZC3XX_R134_GAMMA14},
+       {0xa0, 0x13, ZC3XX_R135_GAMMA15},
+       {0xa0, 0x10, ZC3XX_R136_GAMMA16},
+       {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
+       {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
+       {0xa0, 0x09, ZC3XX_R139_GAMMA19},
+       {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
+       {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
+       {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
+       {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
+       {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
+       {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
+       {0xa0, 0x4e, ZC3XX_R10A_RGB00}, /* matrix */
+       {0xa0, 0xfe, ZC3XX_R10B_RGB01},
+       {0xa0, 0xf4, ZC3XX_R10C_RGB02},
+       {0xa0, 0xf7, ZC3XX_R10D_RGB10},
+       {0xa0, 0x4d, ZC3XX_R10E_RGB11},
+       {0xa0, 0xfc, ZC3XX_R10F_RGB12},
+       {0xa0, 0x00, ZC3XX_R110_RGB20},
+       {0xa0, 0xf6, ZC3XX_R111_RGB21},
+       {0xa0, 0x4a, ZC3XX_R112_RGB22},
+
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xaa, 0x10, 0x000d},
+       {0xaa, 0x76, 0x0002},
+       {0xaa, 0x2a, 0x0081},
+       {0xaa, 0x2b, 0x0000},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xd8, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x1b, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xaa, 0x13, 0x00c3},
+
+       {0xa1, 0x01, 0x0180},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {}
+};
+
+static const struct usb_action pas106b_Initial_com[] = {
+/* Sream and Sensor specific */
+       {0xa1, 0x01, 0x0010},   /* CMOSSensorSelect */
+/* System */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* SystemControl */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* SystemControl */
+/* Picture size */
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},   /* ClockSelect */
+       {0xa0, 0x03, 0x003a},
+       {0xa0, 0x0c, 0x003b},
+       {0xa0, 0x04, 0x0038},
+       {}
+};
+
+static const struct usb_action pas106b_InitialScale[] = {      /* 176x144 */
+/* JPEG control */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+/* Sream and Sensor specific */
+       {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT},
+/* Picture size */
+       {0xa0, 0x00, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0xb0, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x00, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0x90, ZC3XX_R006_FRAMEHEIGHTLOW},
+/* System */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+/* Sream and Sensor specific */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+/* Sensor Interface */
+       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
+/* Window inside sensor array */
+       {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW},
+/* Init the sensor */
+       {0xaa, 0x02, 0x0004},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x09, 0x0005},
+       {0xaa, 0x0a, 0x0002},
+       {0xaa, 0x0b, 0x0002},
+       {0xaa, 0x0c, 0x0005},
+       {0xaa, 0x0d, 0x0000},
+       {0xaa, 0x0e, 0x0002},
+       {0xaa, 0x14, 0x0081},
+/* Other registers */
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
+/* Frame retreiving */
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+/* Gains */
+       {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN},
+/* Unknown */
+       {0xa0, 0x00, 0x01ad},
+/* Sharpness */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+/* Other registers */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+/* Auto exposure and white balance */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+/*Dead pixels */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+/* EEPROM */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+/* JPEG control */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
+/* Other registers */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+/* Auto exposure and white balance */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+/*Dead pixels */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+/* EEPROM */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+/* JPEG control */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
+
+       {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
+       {0xa0, 0xf4, ZC3XX_R10B_RGB01},
+       {0xa0, 0xf4, ZC3XX_R10C_RGB02},
+       {0xa0, 0xf4, ZC3XX_R10D_RGB10},
+       {0xa0, 0x58, ZC3XX_R10E_RGB11},
+       {0xa0, 0xf4, ZC3XX_R10F_RGB12},
+       {0xa0, 0xf4, ZC3XX_R110_RGB20},
+       {0xa0, 0xf4, ZC3XX_R111_RGB21},
+       {0xa0, 0x58, ZC3XX_R112_RGB22},
+/* Auto correction */
+       {0xa0, 0x03, ZC3XX_R181_WINXSTART},
+       {0xa0, 0x08, ZC3XX_R182_WINXWIDTH},
+       {0xa0, 0x16, ZC3XX_R183_WINXCENTER},
+       {0xa0, 0x03, ZC3XX_R184_WINYSTART},
+       {0xa0, 0x05, ZC3XX_R185_WINYWIDTH},
+       {0xa0, 0x14, ZC3XX_R186_WINYCENTER},
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+/* Auto exposure and white balance */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
+/* sensor on */
+       {0xaa, 0x07, 0x00b1},
+       {0xaa, 0x05, 0x0003},
+       {0xaa, 0x04, 0x0001},
+       {0xaa, 0x03, 0x003b},
+/* Gains */
+       {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+/* Auto correction */
+       {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa1, 0x01, 0x0180},                           /* AutoCorrectEnable */
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+/* Gains */
+       {0xa0, 0x40, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x40, ZC3XX_R118_BGAIN},
+       {}
+};
+
+static const struct usb_action pas106b_Initial[] = {   /* 352x288 */
+/* JPEG control */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+/* Sream and Sensor specific */
+       {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT},
+/* Picture size */
+       {0xa0, 0x01, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x60, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0x20, ZC3XX_R006_FRAMEHEIGHTLOW},
+/* System */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+/* Sream and Sensor specific */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+/* Sensor Interface */
+       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
+/* Window inside sensor array */
+       {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW},
+/* Init the sensor */
+       {0xaa, 0x02, 0x0004},
+       {0xaa, 0x08, 0x0000},
+       {0xaa, 0x09, 0x0005},
+       {0xaa, 0x0a, 0x0002},
+       {0xaa, 0x0b, 0x0002},
+       {0xaa, 0x0c, 0x0005},
+       {0xaa, 0x0d, 0x0000},
+       {0xaa, 0x0e, 0x0002},
+       {0xaa, 0x14, 0x0081},
+/* Other registers */
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
+/* Frame retreiving */
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+/* Gains */
+       {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN},
+/* Unknown */
+       {0xa0, 0x00, 0x01ad},
+/* Sharpness */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+/* Other registers */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+/* Auto exposure and white balance */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x80, ZC3XX_R18D_YTARGET},
+/*Dead pixels */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+/* EEPROM */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+/* JPEG control */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
+/* Other registers */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+/* Auto exposure and white balance */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+/*Dead pixels */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+/* EEPROM */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+/* JPEG control */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
+       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
+
+       {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
+       {0xa0, 0xf4, ZC3XX_R10B_RGB01},
+       {0xa0, 0xf4, ZC3XX_R10C_RGB02},
+       {0xa0, 0xf4, ZC3XX_R10D_RGB10},
+       {0xa0, 0x58, ZC3XX_R10E_RGB11},
+       {0xa0, 0xf4, ZC3XX_R10F_RGB12},
+       {0xa0, 0xf4, ZC3XX_R110_RGB20},
+       {0xa0, 0xf4, ZC3XX_R111_RGB21},
+       {0xa0, 0x58, ZC3XX_R112_RGB22},
+/* Auto correction */
+       {0xa0, 0x03, ZC3XX_R181_WINXSTART},
+       {0xa0, 0x08, ZC3XX_R182_WINXWIDTH},
+       {0xa0, 0x16, ZC3XX_R183_WINXCENTER},
+       {0xa0, 0x03, ZC3XX_R184_WINYSTART},
+       {0xa0, 0x05, ZC3XX_R185_WINYWIDTH},
+       {0xa0, 0x14, ZC3XX_R186_WINYCENTER},
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+
+/* Auto exposure and white balance */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW},
+
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW},
+
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+/* sensor on */
+       {0xaa, 0x07, 0x00b1},
+       {0xaa, 0x05, 0x0003},
+       {0xaa, 0x04, 0x0001},
+       {0xaa, 0x03, 0x003b},
+/* Gains */
+       {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+/* Auto correction */
+       {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa1, 0x01, 0x0180},                           /* AutoCorrectEnable */
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+/* Gains */
+       {0xa0, 0x40, ZC3XX_R116_RGAIN},
+       {0xa0, 0x40, ZC3XX_R117_GGAIN},
+       {0xa0, 0x40, ZC3XX_R118_BGAIN},
+
+       {0xa0, 0x00, 0x0007},                   /* AutoCorrectEnable */
+       {0xa0, 0xff, ZC3XX_R018_FRAMELOST},     /* Frame adjust */
+       {}
+};
+static const struct usb_action pas106b_50HZ[] = {
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
+       {0xa0, 0x54, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,54,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,87,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},      /* 01,8c,10,cc */
+       {0xa0, 0x30, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,30,cc */
+       {0xaa, 0x03, 0x0021},                   /* 00,03,21,aa */
+       {0xaa, 0x04, 0x000c},                   /* 00,04,0c,aa */
+       {0xaa, 0x05, 0x0002},                   /* 00,05,02,aa */
+       {0xaa, 0x07, 0x001c},                   /* 00,07,1c,aa */
+       {0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
+       {}
+};
+static const struct usb_action pas106b_60HZ[] = {
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
+       {0xa0, 0x2e, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,2e,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x71, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,71,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},      /* 01,8c,10,cc */
+       {0xa0, 0x30, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,30,cc */
+       {0xaa, 0x03, 0x001c},                   /* 00,03,1c,aa */
+       {0xaa, 0x04, 0x0004},                   /* 00,04,04,aa */
+       {0xaa, 0x05, 0x0001},                   /* 00,05,01,aa */
+       {0xaa, 0x07, 0x00c4},                   /* 00,07,c4,aa */
+       {0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
+       {}
+};
+static const struct usb_action pas106b_NoFliker[] = {
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
+       {0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},      /* 01,8c,10,cc */
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,20,cc */
+       {0xaa, 0x03, 0x0013},                   /* 00,03,13,aa */
+       {0xaa, 0x04, 0x0000},                   /* 00,04,00,aa */
+       {0xaa, 0x05, 0x0001},                   /* 00,05,01,aa */
+       {0xaa, 0x07, 0x0030},                   /* 00,07,30,aa */
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
+       {}
+};
+
+/* from lvWIMv.inf 046d:08a2/:08aa 2007/06/03 */
+static const struct usb_action pas202b_Initial[] = {   /* 640x480 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},         /* 00,00,01,cc */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0e,cc */
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},           /* 00,02,00,cc */
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc */
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},         /* 00,04,80,cc */
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc */
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},        /* 00,06,e0,cc */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc */
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc */
+       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},       /* 00,8d,08,cc */
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},          /* 00,98,00,cc */
+       {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},          /* 00,9a,03,cc */
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},             /* 01,1a,00,cc */
+       {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},             /* 01,1c,03,cc */
+       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},         /* 00,9b,01,cc */
+       {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},          /* 00,9c,e6,cc */
+       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},          /* 00,9d,02,cc */
+       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},           /* 00,9e,86,cc */
+       {0xaa, 0x02, 0x0002},                   /* 00,02,04,aa --> 02 */
+       {0xaa, 0x07, 0x0006},                           /* 00,07,06,aa */
+       {0xaa, 0x08, 0x0002},                           /* 00,08,02,aa */
+       {0xaa, 0x09, 0x0006},                           /* 00,09,06,aa */
+       {0xaa, 0x0a, 0x0001},                           /* 00,0a,01,aa */
+       {0xaa, 0x0b, 0x0001},                           /* 00,0b,01,aa */
+       {0xaa, 0x0c, 0x0006},
+       {0xaa, 0x0d, 0x0000},                           /* 00,0d,00,aa */
+       {0xaa, 0x10, 0x0000},                           /* 00,10,00,aa */
+       {0xaa, 0x12, 0x0005},                           /* 00,12,05,aa */
+       {0xaa, 0x13, 0x0063},                           /* 00,13,63,aa */
+       {0xaa, 0x15, 0x0070},                           /* 00,15,70,aa */
+       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,b7,cc */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0d,cc */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},             /* 01,89,06,cc */
+       {0xa0, 0x00, 0x01ad},                           /* 01,ad,00,cc */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},         /* 01,c5,03,cc */
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},           /* 01,cb,13,cc */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},          /* 03,01,08,cc */
+       {0xa0, 0x70, ZC3XX_R18D_YTARGET},               /* 01,8d,70,cc */
+       {}
+};
+static const struct usb_action pas202b_InitialScale[] = {      /* 320x240 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},         /* 00,00,01,cc */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0e,cc */
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},           /* 00,02,10,cc */
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc */
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},         /* 00,04,80,cc */
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc */
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc */
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc */
+       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},       /* 00,8d,08,cc */
+       {0xa0, 0x08, ZC3XX_R098_WINYSTARTLOW},          /* 00,98,08,cc */
+       {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW},          /* 00,9a,02,cc */
+       {0xa0, 0x08, ZC3XX_R11A_FIRSTYLOW},             /* 01,1a,08,cc */
+       {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW},             /* 01,1c,02,cc */
+       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},         /* 00,9b,01,cc */
+       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},          /* 00,9d,02,cc */
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},           /* 00,9e,88,cc */
+       {0xaa, 0x02, 0x0002},                           /* 00,02,02,aa */
+       {0xaa, 0x07, 0x0006},                           /* 00,07,06,aa */
+       {0xaa, 0x08, 0x0002},                           /* 00,08,02,aa */
+       {0xaa, 0x09, 0x0006},                           /* 00,09,06,aa */
+       {0xaa, 0x0a, 0x0001},                           /* 00,0a,01,aa */
+       {0xaa, 0x0b, 0x0001},                           /* 00,0b,01,aa */
+       {0xaa, 0x0c, 0x0006},
+       {0xaa, 0x0d, 0x0000},                           /* 00,0d,00,aa */
+       {0xaa, 0x10, 0x0000},                           /* 00,10,00,aa */
+       {0xaa, 0x12, 0x0005},                           /* 00,12,05,aa */
+       {0xaa, 0x13, 0x0063},                           /* 00,13,63,aa */
+       {0xaa, 0x15, 0x0070},                           /* 00,15,70,aa */
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,37,cc */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0d,cc */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},             /* 01,89,06,cc */
+       {0xa0, 0x00, 0x01ad},                           /* 01,ad,00,cc */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},         /* 01,c5,03,cc */
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},           /* 01,cb,13,cc */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},          /* 03,01,08,cc */
+       {0xa0, 0x70, ZC3XX_R18D_YTARGET},               /* 01,8d,70,cc */
+       {0xa0, 0xff, ZC3XX_R097_WINYSTARTHIGH},
+       {0xa0, 0xfe, ZC3XX_R098_WINYSTARTLOW},
+       {}
+};
+static const struct usb_action pas202b_50HZ[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},         /* 00,19,00,cc */
+       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},            /* 00,87,20,cc */
+       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},            /* 00,88,21,cc */
+       {0xaa, 0x20, 0x0002},                           /* 00,20,02,aa */
+       {0xaa, 0x21, 0x001b},
+       {0xaa, 0x03, 0x0044},                           /* 00,03,44,aa */
+       {0xaa, 0x04, 0x0008},
+       {0xaa, 0x05, 0x001b},
+       {0xaa, 0x0e, 0x0001},                           /* 00,0e,01,aa */
+       {0xaa, 0x0f, 0x0000},                           /* 00,0f,00,aa */
+       {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
+       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x1b, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
+       {0xa0, 0x4d, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,4d,cc */
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x44, ZC3XX_R01D_HSYNC_0},               /* 00,1d,44,cc */
+       {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1},               /* 00,1e,6f,cc */
+       {0xa0, 0xad, ZC3XX_R01F_HSYNC_2},               /* 00,1f,ad,cc */
+       {0xa0, 0xeb, ZC3XX_R020_HSYNC_3},               /* 00,20,eb,cc */
+       {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},            /* 00,87,0f,cc */
+       {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},            /* 00,88,0e,cc */
+       {}
+};
+static const struct usb_action pas202b_50HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},         /* 00,19,00,cc */
+       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},            /* 00,87,20,cc */
+       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},            /* 00,88,21,cc */
+       {0xaa, 0x20, 0x0004},
+       {0xaa, 0x21, 0x003d},
+       {0xaa, 0x03, 0x0041},                           /* 00,03,41,aa */
+       {0xaa, 0x04, 0x0010},
+       {0xaa, 0x05, 0x003d},
+       {0xaa, 0x0e, 0x0001},                           /* 00,0e,01,aa */
+       {0xaa, 0x0f, 0x0000},                           /* 00,0f,00,aa */
+       {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x3d, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
+       {0xa0, 0x9b, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,9b,cc */
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x41, ZC3XX_R01D_HSYNC_0},               /* 00,1d,41,cc */
+       {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1},               /* 00,1e,6f,cc */
+       {0xa0, 0xad, ZC3XX_R01F_HSYNC_2},               /* 00,1f,ad,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc */
+       {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},            /* 00,87,0f,cc */
+       {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},            /* 00,88,0e,cc */
+       {}
+};
+static const struct usb_action pas202b_60HZ[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},         /* 00,19,00,cc */
+       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},            /* 00,87,20,cc */
+       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},            /* 00,88,21,cc */
+       {0xaa, 0x20, 0x0002},                           /* 00,20,02,aa */
+       {0xaa, 0x21, 0x0000},                           /* 00,21,00,aa */
+       {0xaa, 0x03, 0x0045},                           /* 00,03,45,aa */
+       {0xaa, 0x04, 0x0008},                           /* 00,04,08,aa */
+       {0xaa, 0x05, 0x0000},                           /* 00,05,00,aa */
+       {0xaa, 0x0e, 0x0001},                           /* 00,0e,01,aa */
+       {0xaa, 0x0f, 0x0000},                           /* 00,0f,00,aa */
+       {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
+       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
+       {0xa0, 0x40, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,40,cc */
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x45, ZC3XX_R01D_HSYNC_0},               /* 00,1d,45,cc */
+       {0xa0, 0x8e, ZC3XX_R01E_HSYNC_1},               /* 00,1e,8e,cc */
+       {0xa0, 0xc1, ZC3XX_R01F_HSYNC_2},               /* 00,1f,c1,cc */
+       {0xa0, 0xf5, ZC3XX_R020_HSYNC_3},               /* 00,20,f5,cc */
+       {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},            /* 00,87,0f,cc */
+       {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},            /* 00,88,0e,cc */
+       {}
+};
+static const struct usb_action pas202b_60HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},         /* 00,19,00,cc */
+       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},            /* 00,87,20,cc */
+       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},            /* 00,88,21,cc */
+       {0xaa, 0x20, 0x0004},
+       {0xaa, 0x21, 0x0008},
+       {0xaa, 0x03, 0x0042},                           /* 00,03,42,aa */
+       {0xaa, 0x04, 0x0010},
+       {0xaa, 0x05, 0x0008},
+       {0xaa, 0x0e, 0x0001},                           /* 00,0e,01,aa */
+       {0xaa, 0x0f, 0x0000},                           /* 00,0f,00,aa */
+       {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
+       {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,81,cc */
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x42, ZC3XX_R01D_HSYNC_0},               /* 00,1d,42,cc */
+       {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1},               /* 00,1e,6f,cc */
+       {0xa0, 0xaf, ZC3XX_R01F_HSYNC_2},               /* 00,1f,af,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc */
+       {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},            /* 00,87,0f,cc */
+       {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},            /* 00,88,0e,cc */
+       {}
+};
+static const struct usb_action pas202b_NoFliker[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},         /* 00,19,00,cc */
+       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},            /* 00,87,20,cc */
+       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},            /* 00,88,21,cc */
+       {0xaa, 0x20, 0x0002},                           /* 00,20,02,aa */
+       {0xaa, 0x21, 0x0006},
+       {0xaa, 0x03, 0x0040},                           /* 00,03,40,aa */
+       {0xaa, 0x04, 0x0008},                           /* 00,04,08,aa */
+       {0xaa, 0x05, 0x0006},
+       {0xaa, 0x0e, 0x0001},                           /* 00,0e,01,aa */
+       {0xaa, 0x0f, 0x0000},                           /* 00,0f,00,aa */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
+       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x06, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
+       {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},              /* 01,8c,10,cc */
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,20,cc */
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,00,cc */
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x40, ZC3XX_R01D_HSYNC_0},               /* 00,1d,40,cc */
+       {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},               /* 00,1e,60,cc */
+       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},               /* 00,1f,90,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc */
+       {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},            /* 00,87,0f,cc */
+       {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},            /* 00,88,0e,cc */
+       {}
+};
+static const struct usb_action pas202b_NoFlikerScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},         /* 00,19,00,cc */
+       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},            /* 00,87,20,cc */
+       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},            /* 00,88,21,cc */
+       {0xaa, 0x20, 0x0004},
+       {0xaa, 0x21, 0x000c},
+       {0xaa, 0x03, 0x0040},                           /* 00,03,40,aa */
+       {0xaa, 0x04, 0x0010},
+       {0xaa, 0x05, 0x000c},
+       {0xaa, 0x0e, 0x0001},                           /* 00,0e,01,aa */
+       {0xaa, 0x0f, 0x0000},                           /* 00,0f,00,aa */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x0c, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
+       {0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,02,cc */
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},              /* 01,8c,10,cc */
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,20,cc */
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,00,cc */
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x40, ZC3XX_R01D_HSYNC_0},               /* 00,1d,40,cc */
+       {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},               /* 00,1e,60,cc */
+       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},               /* 00,1f,90,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc */
+       {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},            /* 00,87,0f,cc */
+       {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},            /* 00,88,0e,cc */
+       {}
+};
+
+/* mt9v111 (mi0360soc) and pb0330 from vm30x.inf 0ac8:301b 07/02/13 */
+static const struct usb_action mt9v111_1_Initial[] = { /* 640x480 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xdd, 0x00, 0x0200},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xaa, 0x01, 0x0001},
+       {0xaa, 0x06, 0x0000},
+       {0xaa, 0x08, 0x0483},
+       {0xaa, 0x01, 0x0004},
+       {0xaa, 0x08, 0x0006},
+       {0xaa, 0x02, 0x0011},
+       {0xaa, 0x03, 0x01e5},                   /*jfm: was 01e7*/
+       {0xaa, 0x04, 0x0285},                   /*jfm: was 0287*/
+       {0xaa, 0x07, 0x3002},
+       {0xaa, 0x20, 0x5100},
+       {0xaa, 0x35, 0x507f},
+       {0xaa, 0x30, 0x0005},
+       {0xaa, 0x31, 0x0000},
+       {0xaa, 0x58, 0x0078},
+       {0xaa, 0x62, 0x0411},
+       {0xaa, 0x2b, 0x007f},
+       {0xaa, 0x2c, 0x007f},                   /*jfm: was 0030*/
+       {0xaa, 0x2d, 0x007f},                   /*jfm: was 0030*/
+       {0xaa, 0x2e, 0x007f},                   /*jfm: was 0030*/
+       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
+       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x09, 0x01ad},                   /*jfm: was 00*/
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x61, ZC3XX_R116_RGAIN},
+       {0xa0, 0x65, ZC3XX_R118_BGAIN},
+       {}
+};
+static const struct usb_action mt9v111_1_InitialScale[] = {    /* 320x240 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xdd, 0x00, 0x0200},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xaa, 0x01, 0x0001},
+       {0xaa, 0x06, 0x0000},
+       {0xaa, 0x08, 0x0483},
+       {0xaa, 0x01, 0x0004},
+       {0xaa, 0x08, 0x0006},
+       {0xaa, 0x02, 0x0011},
+       {0xaa, 0x03, 0x01e7},
+       {0xaa, 0x04, 0x0287},
+       {0xaa, 0x07, 0x3002},
+       {0xaa, 0x20, 0x5100},
+       {0xaa, 0x35, 0x007f},                   /*jfm: was 0050*/
+       {0xaa, 0x30, 0x0005},
+       {0xaa, 0x31, 0x0000},
+       {0xaa, 0x58, 0x0078},
+       {0xaa, 0x62, 0x0411},
+       {0xaa, 0x2b, 0x007f},                   /*jfm: was 28*/
+       {0xaa, 0x2c, 0x007f},                   /*jfm: was 30*/
+       {0xaa, 0x2d, 0x007f},                   /*jfm: was 30*/
+       {0xaa, 0x2e, 0x007f},                   /*jfm: was 28*/
+       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
+       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x09, 0x01ad},                   /*jfm: was 00*/
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x61, ZC3XX_R116_RGAIN},
+       {0xa0, 0x65, ZC3XX_R118_BGAIN},
+       {}
+};
+static const struct usb_action mt9v111_1_AE50HZ[] = {
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xbb, 0x00, 0x0562},
+       {0xbb, 0x01, 0x09aa},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x9b, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {}
+};
+static const struct usb_action mt9v111_1_AE50HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xbb, 0x00, 0x0509},
+       {0xbb, 0x01, 0x0934},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {}
+};
+static const struct usb_action mt9v111_1_AE60HZ[] = {
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x05, 0x003d},
+       {0xaa, 0x09, 0x016e},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xdd, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {}
+};
+static const struct usb_action mt9v111_1_AE60HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xbb, 0x00, 0x0509},
+       {0xbb, 0x01, 0x0983},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {}
+};
+static const struct usb_action mt9v111_1_AENoFliker[] = {
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xbb, 0x00, 0x0509},
+       {0xbb, 0x01, 0x0960},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x09, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {}
+};
+static const struct usb_action mt9v111_1_AENoFlikerScale[] = {
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xbb, 0x00, 0x0534},
+       {0xbb, 0x02, 0x0960},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x34, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {}
+};
+/* from usbvm303.inf 0ac8:303b 07/03/25 (3 - tas5130c) */
+static const struct usb_action mt9v111_3_Initial[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xdd, 0x00, 0x0200},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xaa, 0x01, 0x0001},           /* select IFP/SOC registers */
+       {0xaa, 0x06, 0x0000},           /* operating mode control */
+       {0xaa, 0x08, 0x0483},           /* output format control */
+                                       /* H red first, V red or blue first,
+                                        * raw Bayer, auto flicker */
+       {0xaa, 0x01, 0x0004},           /* select sensor core registers */
+       {0xaa, 0x08, 0x0006},           /* row start */
+       {0xaa, 0x02, 0x0011},           /* column start */
+       {0xaa, 0x03, 0x01e5},           /* window height - 1 */
+       {0xaa, 0x04, 0x0285},           /* window width - 1 */
+       {0xaa, 0x07, 0x3002},           /* output control */
+       {0xaa, 0x20, 0x1100},           /* read mode: bits 8 & 12 (?) */
+       {0xaa, 0x35, 0x007f},           /* global gain */
+       {0xaa, 0x30, 0x0005},
+       {0xaa, 0x31, 0x0000},
+       {0xaa, 0x58, 0x0078},
+       {0xaa, 0x62, 0x0411},
+       {0xaa, 0x2b, 0x007f},           /* green1 gain */
+       {0xaa, 0x2c, 0x007f},           /* blue gain */
+       {0xaa, 0x2d, 0x007f},           /* red gain */
+       {0xaa, 0x2e, 0x007f},           /* green2 gain */
+       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x00, 0x01ad},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0x80, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x61, ZC3XX_R116_RGAIN},
+       {0xa0, 0x65, ZC3XX_R118_BGAIN},
+       {}
+};
+static const struct usb_action mt9v111_3_InitialScale[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
+       {0xdd, 0x00, 0x0200},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xaa, 0x01, 0x0001},
+       {0xaa, 0x06, 0x0000},
+       {0xaa, 0x08, 0x0483},
+       {0xaa, 0x01, 0x0004},
+       {0xaa, 0x08, 0x0006},
+       {0xaa, 0x02, 0x0011},
+       {0xaa, 0x03, 0x01e7},
+       {0xaa, 0x04, 0x0287},
+       {0xaa, 0x07, 0x3002},
+       {0xaa, 0x20, 0x1100},
+       {0xaa, 0x35, 0x007f},
+       {0xaa, 0x30, 0x0005},
+       {0xaa, 0x31, 0x0000},
+       {0xaa, 0x58, 0x0078},
+       {0xaa, 0x62, 0x0411},
+       {0xaa, 0x2b, 0x007f},
+       {0xaa, 0x2c, 0x007f},
+       {0xaa, 0x2d, 0x007f},
+       {0xaa, 0x2e, 0x007f},
+       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x00, 0x01ad},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0x80, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x61, ZC3XX_R116_RGAIN},
+       {0xa0, 0x65, ZC3XX_R118_BGAIN},
+       {}
+};
+static const struct usb_action mt9v111_3_AE50HZ[] = {
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x05, 0x0009},           /* horizontal blanking */
+       {0xaa, 0x09, 0x01ce},           /* shutter width */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {}
+};
+static const struct usb_action mt9v111_3_AE50HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x05, 0x0009},
+       {0xaa, 0x09, 0x01ce},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {}
+};
+static const struct usb_action mt9v111_3_AE60HZ[] = {
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x05, 0x0009},
+       {0xaa, 0x09, 0x0083},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {}
+};
+static const struct usb_action mt9v111_3_AE60HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x05, 0x0009},
+       {0xaa, 0x09, 0x0083},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {}
+};
+static const struct usb_action mt9v111_3_AENoFliker[] = {
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x05, 0x0034},
+       {0xaa, 0x09, 0x0260},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x34, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {}
+};
+static const struct usb_action mt9v111_3_AENoFlikerScale[] = {
+       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xaa, 0x05, 0x0034},
+       {0xaa, 0x09, 0x0260},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x34, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
+       {}
+};
+
+static const struct usb_action pb0330_Initial[] = {    /* 640x480 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00 */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xdd, 0x00, 0x0200},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xaa, 0x01, 0x0006},
+       {0xaa, 0x02, 0x0011},
+       {0xaa, 0x03, 0x01e5},                   /*jfm: was 1e7*/
+       {0xaa, 0x04, 0x0285},                   /*jfm: was 0287*/
+       {0xaa, 0x06, 0x0003},
+       {0xaa, 0x07, 0x3002},
+       {0xaa, 0x20, 0x1100},
+       {0xaa, 0x2f, 0xf7b0},
+       {0xaa, 0x30, 0x0005},
+       {0xaa, 0x31, 0x0000},
+       {0xaa, 0x34, 0x0100},
+       {0xaa, 0x35, 0x0060},
+       {0xaa, 0x3d, 0x068f},
+       {0xaa, 0x40, 0x01e0},
+       {0xaa, 0x58, 0x0078},
+       {0xaa, 0x62, 0x0411},
+       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x09, 0x01ad},                   /*jfm: was 00 */
+       {0xa0, 0x15, 0x01ae},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0x78, ZC3XX_R18D_YTARGET},       /*jfm: was 6c*/
+       {}
+};
+static const struct usb_action pb0330_InitialScale[] = {       /* 320x240 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00 */
+       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
+       {0xdd, 0x00, 0x0200},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xaa, 0x01, 0x0006},
+       {0xaa, 0x02, 0x0011},
+       {0xaa, 0x03, 0x01e7},
+       {0xaa, 0x04, 0x0287},
+       {0xaa, 0x06, 0x0003},
+       {0xaa, 0x07, 0x3002},
+       {0xaa, 0x20, 0x1100},
+       {0xaa, 0x2f, 0xf7b0},
+       {0xaa, 0x30, 0x0005},
+       {0xaa, 0x31, 0x0000},
+       {0xaa, 0x34, 0x0100},
+       {0xaa, 0x35, 0x0060},
+       {0xaa, 0x3d, 0x068f},
+       {0xaa, 0x40, 0x01e0},
+       {0xaa, 0x58, 0x0078},
+       {0xaa, 0x62, 0x0411},
+       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x09, 0x01ad},
+       {0xa0, 0x15, 0x01ae},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0x78, ZC3XX_R18D_YTARGET},       /*jfm: was 6c*/
+       {}
+};
+static const struct usb_action pb0330_50HZ[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xbb, 0x00, 0x055c},
+       {0xbb, 0x01, 0x09aa},
+       {0xbb, 0x00, 0x1001},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xc4, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x5c, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action pb0330_50HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xbb, 0x00, 0x0566},
+       {0xbb, 0x02, 0x09b2},
+       {0xbb, 0x00, 0x1002},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x8c, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action pb0330_60HZ[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xbb, 0x00, 0x0535},
+       {0xbb, 0x01, 0x0974},
+       {0xbb, 0x00, 0x1001},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xfe, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x35, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x50, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xd0, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action pb0330_60HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xbb, 0x00, 0x0535},
+       {0xbb, 0x02, 0x096c},
+       {0xbb, 0x00, 0x1002},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xc0, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x7c, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x35, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x50, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xd0, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action pb0330_NoFliker[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xbb, 0x00, 0x0509},
+       {0xbb, 0x02, 0x0940},
+       {0xbb, 0x00, 0x1002},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x09, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
+       {}
+};
+static const struct usb_action pb0330_NoFlikerScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
+       {0xbb, 0x00, 0x0535},
+       {0xbb, 0x01, 0x0980},
+       {0xbb, 0x00, 0x1001},
+       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x35, ZC3XX_R01D_HSYNC_0},
+       {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
+       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
+       {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
+       {}
+};
+
+/* from oem9.inf */
+static const struct usb_action po2030_Initial[] = {    /* 640x480 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
+       {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT},   /* 00,02,04,cc */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
+       {0xa0, 0x04, ZC3XX_R080_HBLANKHIGH}, /* 00,80,04,cc */
+       {0xa0, 0x05, ZC3XX_R081_HBLANKLOW}, /* 00,81,05,cc */
+       {0xa0, 0x16, ZC3XX_R083_RGAINADDR}, /* 00,83,16,cc */
+       {0xa0, 0x18, ZC3XX_R085_BGAINADDR}, /* 00,85,18,cc */
+       {0xa0, 0x1a, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,1a,cc */
+       {0xa0, 0x1b, ZC3XX_R087_EXPTIMEMID}, /* 00,87,1b,cc */
+       {0xa0, 0x1c, ZC3XX_R088_EXPTIMELOW}, /* 00,88,1c,cc */
+       {0xa0, 0xee, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,ee,cc */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
+       {0xaa, 0x8d, 0x0008},                   /* 00,8d,08,aa */
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},  /* 00,98,00,cc */
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},  /* 00,9a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},     /* 01,1a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},     /* 01,1c,00,cc */
+       {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},  /* 00,9c,e6,cc */
+       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},   /* 00,9e,86,cc */
+       {0xaa, 0x09, 0x00ce}, /* 00,09,ce,aa */
+       {0xaa, 0x0b, 0x0005}, /* 00,0b,05,aa */
+       {0xaa, 0x0d, 0x0054}, /* 00,0d,54,aa */
+       {0xaa, 0x0f, 0x00eb}, /* 00,0f,eb,aa */
+       {0xaa, 0x87, 0x0000}, /* 00,87,00,aa */
+       {0xaa, 0x88, 0x0004}, /* 00,88,04,aa */
+       {0xaa, 0x89, 0x0000}, /* 00,89,00,aa */
+       {0xaa, 0x8a, 0x0005}, /* 00,8a,05,aa */
+       {0xaa, 0x13, 0x0003}, /* 00,13,03,aa */
+       {0xaa, 0x16, 0x0040}, /* 00,16,40,aa */
+       {0xaa, 0x18, 0x0040}, /* 00,18,40,aa */
+       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
+       {0xaa, 0x29, 0x00e8}, /* 00,29,e8,aa */
+       {0xaa, 0x45, 0x0045}, /* 00,45,45,aa */
+       {0xaa, 0x50, 0x00ed}, /* 00,50,ed,aa */
+       {0xaa, 0x51, 0x0025}, /* 00,51,25,aa */
+       {0xaa, 0x52, 0x0042}, /* 00,52,42,aa */
+       {0xaa, 0x53, 0x002f}, /* 00,53,2f,aa */
+       {0xaa, 0x79, 0x0025}, /* 00,79,25,aa */
+       {0xaa, 0x7b, 0x0000}, /* 00,7b,00,aa */
+       {0xaa, 0x7e, 0x0025}, /* 00,7e,25,aa */
+       {0xaa, 0x7f, 0x0025}, /* 00,7f,25,aa */
+       {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
+       {0xaa, 0x33, 0x0036}, /* 00,33,36,aa */
+       {0xaa, 0x36, 0x0060}, /* 00,36,60,aa */
+       {0xaa, 0x37, 0x0008}, /* 00,37,08,aa */
+       {0xaa, 0x3b, 0x0031}, /* 00,3b,31,aa */
+       {0xaa, 0x44, 0x000f}, /* 00,44,0f,aa */
+       {0xaa, 0x58, 0x0002}, /* 00,58,02,aa */
+       {0xaa, 0x66, 0x00c0}, /* 00,66,c0,aa */
+       {0xaa, 0x67, 0x0044}, /* 00,67,44,aa */
+       {0xaa, 0x6b, 0x00a0}, /* 00,6b,a0,aa */
+       {0xaa, 0x6c, 0x0054}, /* 00,6c,54,aa */
+       {0xaa, 0xd6, 0x0007}, /* 00,d6,07,aa */
+       {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,f7,cc */
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
+       {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
+       {0xa0, 0x7a, ZC3XX_R116_RGAIN}, /* 01,16,7a,cc */
+       {0xa0, 0x4a, ZC3XX_R118_BGAIN}, /* 01,18,4a,cc */
+       {}
+};
+
+/* from oem9.inf */
+static const struct usb_action po2030_InitialScale[] = {       /* 320x240 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
+       {0xa0, 0x04, ZC3XX_R080_HBLANKHIGH}, /* 00,80,04,cc */
+       {0xa0, 0x05, ZC3XX_R081_HBLANKLOW}, /* 00,81,05,cc */
+       {0xa0, 0x16, ZC3XX_R083_RGAINADDR}, /* 00,83,16,cc */
+       {0xa0, 0x18, ZC3XX_R085_BGAINADDR}, /* 00,85,18,cc */
+       {0xa0, 0x1a, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,1a,cc */
+       {0xa0, 0x1b, ZC3XX_R087_EXPTIMEMID}, /* 00,87,1b,cc */
+       {0xa0, 0x1c, ZC3XX_R088_EXPTIMELOW}, /* 00,88,1c,cc */
+       {0xa0, 0xee, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,ee,cc */
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
+       {0xaa, 0x8d, 0x0008},                   /* 00,8d,08,aa */
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
+       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc */
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
+       {0xaa, 0x09, 0x00cc}, /* 00,09,cc,aa */
+       {0xaa, 0x0b, 0x0005}, /* 00,0b,05,aa */
+       {0xaa, 0x0d, 0x0058}, /* 00,0d,58,aa */
+       {0xaa, 0x0f, 0x00ed}, /* 00,0f,ed,aa */
+       {0xaa, 0x87, 0x0000}, /* 00,87,00,aa */
+       {0xaa, 0x88, 0x0004}, /* 00,88,04,aa */
+       {0xaa, 0x89, 0x0000}, /* 00,89,00,aa */
+       {0xaa, 0x8a, 0x0005}, /* 00,8a,05,aa */
+       {0xaa, 0x13, 0x0003}, /* 00,13,03,aa */
+       {0xaa, 0x16, 0x0040}, /* 00,16,40,aa */
+       {0xaa, 0x18, 0x0040}, /* 00,18,40,aa */
+       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
+       {0xaa, 0x29, 0x00e8}, /* 00,29,e8,aa */
+       {0xaa, 0x45, 0x0045}, /* 00,45,45,aa */
+       {0xaa, 0x50, 0x00ed}, /* 00,50,ed,aa */
+       {0xaa, 0x51, 0x0025}, /* 00,51,25,aa */
+       {0xaa, 0x52, 0x0042}, /* 00,52,42,aa */
+       {0xaa, 0x53, 0x002f}, /* 00,53,2f,aa */
+       {0xaa, 0x79, 0x0025}, /* 00,79,25,aa */
+       {0xaa, 0x7b, 0x0000}, /* 00,7b,00,aa */
+       {0xaa, 0x7e, 0x0025}, /* 00,7e,25,aa */
+       {0xaa, 0x7f, 0x0025}, /* 00,7f,25,aa */
+       {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
+       {0xaa, 0x33, 0x0036}, /* 00,33,36,aa */
+       {0xaa, 0x36, 0x0060}, /* 00,36,60,aa */
+       {0xaa, 0x37, 0x0008}, /* 00,37,08,aa */
+       {0xaa, 0x3b, 0x0031}, /* 00,3b,31,aa */
+       {0xaa, 0x44, 0x000f}, /* 00,44,0f,aa */
+       {0xaa, 0x58, 0x0002}, /* 00,58,02,aa */
+       {0xaa, 0x66, 0x00c0}, /* 00,66,c0,aa */
+       {0xaa, 0x67, 0x0044}, /* 00,67,44,aa */
+       {0xaa, 0x6b, 0x00a0}, /* 00,6b,a0,aa */
+       {0xaa, 0x6c, 0x0054}, /* 00,6c,54,aa */
+       {0xaa, 0xd6, 0x0007}, /* 00,d6,07,aa */
+       {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,f7,cc */
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
+       {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
+       {0xa0, 0x7a, ZC3XX_R116_RGAIN}, /* 01,16,7a,cc */
+       {0xa0, 0x4a, ZC3XX_R118_BGAIN}, /* 01,18,4a,cc */
+       {}
+};
+
+static const struct usb_action po2030_50HZ[] = {
+       {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
+       {0xaa, 0x1a, 0x0001}, /* 00,1a,01,aa */
+       {0xaa, 0x1b, 0x000a}, /* 00,1b,0a,aa */
+       {0xaa, 0x1c, 0x00b0}, /* 00,1c,b0,aa */
+       {0xa0, 0x05, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,05,cc */
+       {0xa0, 0x35, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,35,cc */
+       {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x85, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,85,cc */
+       {0xa0, 0x58, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,58,cc */
+       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
+       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
+       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
+       {0xa0, 0x22, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,22,cc */
+       {0xa0, 0x88, ZC3XX_R18D_YTARGET}, /* 01,8d,88,cc */
+       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc */
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
+       {}
+};
+
+static const struct usb_action po2030_60HZ[] = {
+       {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
+       {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
+       {0xaa, 0x1b, 0x00de}, /* 00,1b,de,aa */
+       {0xaa, 0x1c, 0x0040}, /* 00,1c,40,aa */
+       {0xa0, 0x08, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,08,cc */
+       {0xa0, 0xae, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,ae,cc */
+       {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x6f, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,6f,cc */
+       {0xa0, 0x20, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,20,cc */
+       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
+       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
+       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
+       {0xa0, 0x22, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,22,cc */
+       {0xa0, 0x88, ZC3XX_R18D_YTARGET},               /* 01,8d,88,cc */
+                                                       /* win: 01,8d,80 */
+       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc */
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc */
+       {}
+};
+
+static const struct usb_action po2030_NoFliker[] = {
+       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
+       {0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */
+       {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
+       {0xaa, 0x1b, 0x0002}, /* 00,1b,02,aa */
+       {0xaa, 0x1c, 0x0078}, /* 00,1c,78,aa */
+       {0xaa, 0x46, 0x0000}, /* 00,46,00,aa */
+       {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
+       {}
+};
+
+static const struct usb_action tas5130c_InitialScale[] = {     /* 320x240 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+
+       {0xa0, 0x04, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x0f, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x04, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x0f, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
+       {0xa0, 0x06, ZC3XX_R08D_COMPABILITYMODE},
+       {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x70, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0x00, 0x01ad},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
+       {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
+       {}
+};
+static const struct usb_action tas5130c_Initial[] = {  /* 640x480 */
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
+       {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING},
+       {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
+       {0xa0, 0x05, ZC3XX_R098_WINYSTARTLOW},
+       {0xa0, 0x0f, ZC3XX_R09A_WINXSTARTLOW},
+       {0xa0, 0x05, ZC3XX_R11A_FIRSTYLOW},
+       {0xa0, 0x0f, ZC3XX_R11C_FIRSTXLOW},
+       {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
+       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
+       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
+       {0xa0, 0x06, ZC3XX_R08D_COMPABILITYMODE},
+       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
+       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
+       {0xa0, 0x70, ZC3XX_R18D_YTARGET},
+       {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0x00, 0x01ad},
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
+       {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
+       {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
+       {}
+};
+static const struct usb_action tas5130c_50HZ[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
+       {0xaa, 0xa4, 0x0063}, /* 00,a4,63,aa */
+       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
+       {0xa0, 0x63, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,63,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xfe, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc */
+       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xd3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,d3,cc */
+       {0xa0, 0xda, ZC3XX_R01E_HSYNC_1}, /* 00,1e,da,cc */
+       {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
+       {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
+       {0xa0, 0x4c, ZC3XX_R0A0_MAXXLOW},
+       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
+       {}
+};
+static const struct usb_action tas5130c_50HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
+       {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */
+       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
+       {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xd0, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */
+       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xf0, ZC3XX_R01D_HSYNC_0}, /* 00,1d,f0,cc */
+       {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,f4,cc */
+       {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f8,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
+       {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
+       {0xa0, 0xc0, ZC3XX_R0A0_MAXXLOW},
+       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
+       {}
+};
+static const struct usb_action tas5130c_60HZ[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
+       {0xaa, 0xa4, 0x0036}, /* 00,a4,36,aa */
+       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
+       {0xa0, 0x36, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,36,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x54, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3e,cc */
+       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xca, ZC3XX_R01D_HSYNC_0}, /* 00,1d,ca,cc */
+       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
+       {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
+       {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
+       {0xa0, 0x28, ZC3XX_R0A0_MAXXLOW},
+       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
+       {}
+};
+static const struct usb_action tas5130c_60HZScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
+       {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */
+       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
+       {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x09, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x47, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
+       {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */
+       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */
+       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
+       {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
+       {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
+       {0xa0, 0x20, ZC3XX_R0A0_MAXXLOW},
+       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
+       {}
+};
+static const struct usb_action tas5130c_NoFliker[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
+       {0xaa, 0xa4, 0x0040}, /* 00,a4,40,aa */
+       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
+       {0xa0, 0x40, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,40,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
+       {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */
+       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
+       {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
+       {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */
+       {0xa0, 0xf0, ZC3XX_R0A0_MAXXLOW},
+       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
+       {}
+};
+
+static const struct usb_action tas5130c_NoFlikerScale[] = {
+       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
+       {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
+       {0xaa, 0xa4, 0x0090}, /* 00,a4,90,aa */
+       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
+       {0xa0, 0x90, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,90,cc */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
+       {0xa0, 0x0a, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
+       {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
+       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
+       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
+       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
+       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
+       {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */
+       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
+       {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
+       {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */
+       {0xa0, 0xf0, ZC3XX_R0A0_MAXXLOW},
+       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
+       {}
+};
+
+/* from usbvm305.inf 0ac8:305b 07/06/15 (3 - tas5130c) */
+static const struct usb_action gc0303_Initial[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},         /* 00,00,01,cc, */
+       {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},          /* 00,08,02,cc, */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc, */
+       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc, */
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},         /* 00,04,80,cc, */
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc, */
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},        /* 00,06,e0,cc, */
+       {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,98,cc, */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc, */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc, */
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc, */
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},          /* 00,98,00,cc, */
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},          /* 00,9a,00,cc, */
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},             /* 01,1a,00,cc, */
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},             /* 01,1c,00,cc, */
+       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},          /* 00,9c,e6,cc,
+                                                        * 6<->8 */
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},           /* 00,9e,86,cc,
+                                                        * 6<->8 */
+       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},            /* 00,87,10,cc, */
+       {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,98,cc, */
+       {0xaa, 0x01, 0x0000},
+       {0xaa, 0x1a, 0x0000},           /* 00,1a,00,aa, */
+       {0xaa, 0x1c, 0x0017},           /* 00,1c,17,aa, */
+       {0xaa, 0x1b, 0x0000},
+       {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH},           /* 00,86,82,cc, */
+       {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID},            /* 00,87,83,cc, */
+       {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW},            /* 00,88,84,cc, */
+       {0xaa, 0x05, 0x0010},           /* 00,05,10,aa, */
+       {0xaa, 0x0a, 0x0002},
+       {0xaa, 0x0b, 0x0000},
+       {0xaa, 0x0c, 0x0002},
+       {0xaa, 0x0d, 0x0000},
+       {0xaa, 0x0e, 0x0002},
+       {0xaa, 0x0f, 0x0000},
+       {0xaa, 0x10, 0x0002},
+       {0xaa, 0x11, 0x0000},
+       {0xaa, 0x16, 0x0001},           /* 00,16,01,aa, */
+       {0xaa, 0x17, 0x00e8},           /* 00,17,e6,aa, (e6 -> e8) */
+       {0xaa, 0x18, 0x0002},           /* 00,18,02,aa, */
+       {0xaa, 0x19, 0x0088},           /* 00,19,86,aa, */
+       {0xaa, 0x20, 0x0020},           /* 00,20,20,aa, */
+       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,b7,cc, */
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,05,cc, */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0d,cc, */
+       {0xa0, 0x76, ZC3XX_R189_AWBSTATUS},             /* 01,89,76,cc, */
+       {0xa0, 0x09, 0x01ad},                           /* 01,ad,09,cc, */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},         /* 01,c5,03,cc, */
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},           /* 01,cb,13,cc, */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc, */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},          /* 03,01,08,cc, */
+       {0xa0, 0x58, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0x61, ZC3XX_R116_RGAIN},                 /* 01,16,61,cc, */
+       {0xa0, 0x65, ZC3XX_R118_BGAIN},                 /* 01,18,65,cc */
+       {0xaa, 0x1b, 0x0000},
+       {}
+};
+
+static const struct usb_action gc0303_InitialScale[] = {
+       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},         /* 00,00,01,cc, */
+       {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},          /* 00,08,02,cc, */
+       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc, */
+       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
+       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc, */
+       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},         /* 00,04,80,cc, */
+       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc, */
+       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},        /* 00,06,e0,cc, */
+       {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,98,cc, */
+       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc, */
+       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc, */
+       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc, */
+       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},          /* 00,98,00,cc, */
+       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},          /* 00,9a,00,cc, */
+       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},             /* 01,1a,00,cc, */
+       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},             /* 01,1c,00,cc, */
+       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},          /* 00,9c,e8,cc,
+                                                        * 8<->6 */
+       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},           /* 00,9e,88,cc,
+                                                        * 8<->6 */
+       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},            /* 00,87,10,cc, */
+       {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,98,cc, */
+       {0xaa, 0x01, 0x0000},
+       {0xaa, 0x1a, 0x0000},           /* 00,1a,00,aa, */
+       {0xaa, 0x1c, 0x0017},           /* 00,1c,17,aa, */
+       {0xaa, 0x1b, 0x0000},
+       {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH},   /* 00,86,82,cc, */
+       {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID},    /* 00,87,83,cc, */
+       {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW},    /* 00,88,84,cc, */
+       {0xaa, 0x05, 0x0010},           /* 00,05,10,aa, */
+       {0xaa, 0x0a, 0x0001},
+       {0xaa, 0x0b, 0x0000},
+       {0xaa, 0x0c, 0x0001},
+       {0xaa, 0x0d, 0x0000},
+       {0xaa, 0x0e, 0x0001},
+       {0xaa, 0x0f, 0x0000},
+       {0xaa, 0x10, 0x0001},
+       {0xaa, 0x11, 0x0000},
+       {0xaa, 0x16, 0x0001},           /* 00,16,01,aa, */
+       {0xaa, 0x17, 0x00e8},           /* 00,17,e6,aa (e6 -> e8) */
+       {0xaa, 0x18, 0x0002},           /* 00,18,02,aa, */
+       {0xaa, 0x19, 0x0088},           /* 00,19,88,aa, */
+       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,b7,cc, */
+       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,05,cc, */
+       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0d,cc, */
+       {0xa0, 0x76, ZC3XX_R189_AWBSTATUS},             /* 01,89,76,cc, */
+       {0xa0, 0x09, 0x01ad},                           /* 01,ad,09,cc, */
+       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},         /* 01,c5,03,cc, */
+       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},           /* 01,cb,13,cc, */
+       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc, */
+       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},          /* 03,01,08,cc, */
+       {0xa0, 0x58, ZC3XX_R1A8_DIGITALGAIN},
+       {0xa0, 0x61, ZC3XX_R116_RGAIN},         /* 01,16,61,cc, */
+       {0xa0, 0x65, ZC3XX_R118_BGAIN},         /* 01,18,65,cc */
+       {0xaa, 0x1b, 0x0000},
+       {}
+};
+static const struct usb_action gc0303_50HZ[] = {
+       {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
+       {0xaa, 0x83, 0x0001},           /* 00,83,01,aa */
+       {0xaa, 0x84, 0x0063},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc, */
+       {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,0d,cc, */
+       {0xa0, 0xa8, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,50,cc, */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc, */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc, */
+       {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,47,cc, */
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},              /* 01,8c,0e,cc, */
+       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,15,cc, */
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,10,cc, */
+       {0xa0, 0x48, ZC3XX_R1AA_DIGITALGAINSTEP},
+       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},               /* 00,1d,62,cc, */
+       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},               /* 00,1e,90,cc, */
+       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},               /* 00,1f,c8,cc, */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc, */
+       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc, */
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc, */
+       {0xa0, 0x7f, ZC3XX_R18D_YTARGET},
+       {}
+};
+
+static const struct usb_action gc0303_50HZScale[] = {
+       {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
+       {0xaa, 0x83, 0x0003},           /* 00,83,03,aa */
+       {0xaa, 0x84, 0x0054},           /* 00,84,54,aa */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc, */
+       {0xa0, 0x0d, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,0d,cc, */
+       {0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,50,cc, */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc, */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc, */
+       {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,8e,cc, */
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},              /* 01,8c,0e,cc, */
+       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,15,cc, */
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,10,cc, */
+       {0xa0, 0x48, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc, */
+       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},               /* 00,1d,62,cc, */
+       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},               /* 00,1e,90,cc, */
+       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},               /* 00,1f,c8,cc, */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc, */
+       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc, */
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc, */
+       {0xa0, 0x7f, ZC3XX_R18D_YTARGET},
+       {}
+};
+
+static const struct usb_action gc0303_60HZ[] = {
+       {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
+       {0xaa, 0x83, 0x0000},
+       {0xaa, 0x84, 0x003b},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc, */
+       {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,05,cc, */
+       {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,88,cc, */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc, */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc, */
+       {0xa0, 0x3b, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,3b,cc, */
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},              /* 01,8c,0e,cc, */
+       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,15,cc, */
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,10,cc, */
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc, */
+       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},               /* 00,1d,62,cc, */
+       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},               /* 00,1e,90,cc, */
+       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},               /* 00,1f,c8,cc, */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc, */
+       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc, */
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc, */
+       {0xa0, 0x80, ZC3XX_R18D_YTARGET},
+       {}
+};
+
+static const struct usb_action gc0303_60HZScale[] = {
+       {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
+       {0xaa, 0x83, 0x0000},
+       {0xaa, 0x84, 0x0076},
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc, */
+       {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,1,0b,cc, */
+       {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,2,10,cc, */
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,5,00,cc, */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,6,00,cc, */
+       {0xa0, 0x76, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,7,76,cc, */
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},              /* 01,c,0e,cc, */
+       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},            /* 01,f,15,cc, */
+       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,9,10,cc, */
+       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,a,24,cc, */
+       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},               /* 00,d,62,cc, */
+       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},               /* 00,e,90,cc, */
+       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},               /* 00,f,c8,cc, */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,0,ff,cc, */
+       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,d,58,cc, */
+       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc, */
+       {0xa0, 0x80, ZC3XX_R18D_YTARGET},
+       {}
+};
+
+static const struct usb_action gc0303_NoFliker[] = {
+       {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0c,cc, */
+       {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
+       {0xaa, 0x83, 0x0000},           /* 00,83,00,aa */
+       {0xaa, 0x84, 0x0020},           /* 00,84,20,aa */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,0,00,cc, */
+       {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc, */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc, */
+       {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,10,cc, */
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},              /* 01,8c,0e,cc, */
+       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,15,cc, */
+       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},               /* 00,1d,62,cc, */
+       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},               /* 00,1e,90,cc, */
+       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},               /* 00,1f,c8,cc, */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc, */
+       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc, */
+       {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,03,cc */
+       {}
+};
+
+static const struct usb_action gc0303_NoFlikerScale[] = {
+       {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0c,cc, */
+       {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
+       {0xaa, 0x83, 0x0000},           /* 00,83,00,aa */
+       {0xaa, 0x84, 0x0020},           /* 00,84,20,aa */
+       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc, */
+       {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
+       {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW},
+       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc, */
+       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc, */
+       {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,10,cc, */
+       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},              /* 01,8c,0e,cc, */
+       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,15,cc, */
+       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},               /* 00,1d,62,cc, */
+       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},               /* 00,1e,90,cc, */
+       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},               /* 00,1f,c8,cc, */
+       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc, */
+       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc, */
+       {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,03,cc */
+       {}
+};
+
+static u8 reg_r(struct gspca_dev *gspca_dev,
+               u16 index)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return 0;
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
+                       0xa1,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0x01,                   /* value */
+                       index, gspca_dev->usb_buf, 1,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_r err %d\n", ret);
+               gspca_dev->usb_err = ret;
+               return 0;
+       }
+       return gspca_dev->usb_buf[0];
+}
+
+static void reg_w(struct gspca_dev *gspca_dev,
+                       u8 value,
+                       u16 index)
+{
+       int ret;
+
+       if (gspca_dev->usb_err < 0)
+               return;
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_sndctrlpipe(gspca_dev->dev, 0),
+                       0xa0,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index, NULL, 0,
+                       500);
+       if (ret < 0) {
+               pr_err("reg_w_i err %d\n", ret);
+               gspca_dev->usb_err = ret;
+       }
+}
+
+static u16 i2c_read(struct gspca_dev *gspca_dev,
+                       u8 reg)
+{
+       u8 retbyte;
+       u16 retval;
+
+       if (gspca_dev->usb_err < 0)
+               return 0;
+       reg_w(gspca_dev, reg, 0x0092);
+       reg_w(gspca_dev, 0x02, 0x0090);                 /* <- read command */
+       msleep(20);
+       retbyte = reg_r(gspca_dev, 0x0091);             /* read status */
+       if (retbyte != 0x00)
+               pr_err("i2c_r status error %02x\n", retbyte);
+       retval = reg_r(gspca_dev, 0x0095);              /* read Lowbyte */
+       retval |= reg_r(gspca_dev, 0x0096) << 8;        /* read Hightbyte */
+       return retval;
+}
+
+static u8 i2c_write(struct gspca_dev *gspca_dev,
+                       u8 reg,
+                       u8 valL,
+                       u8 valH)
+{
+       u8 retbyte;
+
+       if (gspca_dev->usb_err < 0)
+               return 0;
+       reg_w(gspca_dev, reg, 0x92);
+       reg_w(gspca_dev, valL, 0x93);
+       reg_w(gspca_dev, valH, 0x94);
+       reg_w(gspca_dev, 0x01, 0x90);           /* <- write command */
+       msleep(1);
+       retbyte = reg_r(gspca_dev, 0x0091);             /* read status */
+       if (retbyte != 0x00)
+               pr_err("i2c_w status error %02x\n", retbyte);
+       return retbyte;
+}
+
+static void usb_exchange(struct gspca_dev *gspca_dev,
+                       const struct usb_action *action)
+{
+       while (action->req) {
+               switch (action->req) {
+               case 0xa0:      /* write register */
+                       reg_w(gspca_dev, action->val, action->idx);
+                       break;
+               case 0xa1:      /* read status */
+                       reg_r(gspca_dev, action->idx);
+                       break;
+               case 0xaa:
+                       i2c_write(gspca_dev,
+                                 action->val,                  /* reg */
+                                 action->idx & 0xff,           /* valL */
+                                 action->idx >> 8);            /* valH */
+                       break;
+               case 0xbb:
+                       i2c_write(gspca_dev,
+                                 action->idx >> 8,             /* reg */
+                                 action->idx & 0xff,           /* valL */
+                                 action->val);                 /* valH */
+                       break;
+               default:
+/*             case 0xdd:       * delay */
+                       msleep(action->idx);
+                       break;
+               }
+               action++;
+               msleep(1);
+       }
+}
+
+static void setmatrix(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+       const u8 *matrix;
+       static const u8 adcm2700_matrix[9] =
+/*             {0x66, 0xed, 0xed, 0xed, 0x66, 0xed, 0xed, 0xed, 0x66}; */
+/*ms-win*/
+               {0x74, 0xed, 0xed, 0xed, 0x74, 0xed, 0xed, 0xed, 0x74};
+       static const u8 gc0305_matrix[9] =
+               {0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50};
+       static const u8 ov7620_matrix[9] =
+               {0x58, 0xf4, 0xf4, 0xf4, 0x58, 0xf4, 0xf4, 0xf4, 0x58};
+       static const u8 pas202b_matrix[9] =
+               {0x4c, 0xf5, 0xff, 0xf9, 0x51, 0xf5, 0xfb, 0xed, 0x5f};
+       static const u8 po2030_matrix[9] =
+               {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60};
+       static const u8 tas5130c_matrix[9] =
+               {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68};
+       static const u8 gc0303_matrix[9] =
+               {0x6c, 0xea, 0xea, 0xea, 0x6c, 0xea, 0xea, 0xea, 0x6c};
+       static const u8 *matrix_tb[SENSOR_MAX] = {
+               [SENSOR_ADCM2700] =     adcm2700_matrix,
+               [SENSOR_CS2102] =       ov7620_matrix,
+               [SENSOR_CS2102K] =      NULL,
+               [SENSOR_GC0303] =       gc0303_matrix,
+               [SENSOR_GC0305] =       gc0305_matrix,
+               [SENSOR_HDCS2020] =     NULL,
+               [SENSOR_HV7131B] =      NULL,
+               [SENSOR_HV7131R] =      po2030_matrix,
+               [SENSOR_ICM105A] =      po2030_matrix,
+               [SENSOR_MC501CB] =      NULL,
+               [SENSOR_MT9V111_1] =    gc0305_matrix,
+               [SENSOR_MT9V111_3] =    gc0305_matrix,
+               [SENSOR_OV7620] =       ov7620_matrix,
+               [SENSOR_OV7630C] =      NULL,
+               [SENSOR_PAS106] =       NULL,
+               [SENSOR_PAS202B] =      pas202b_matrix,
+               [SENSOR_PB0330] =       gc0305_matrix,
+               [SENSOR_PO2030] =       po2030_matrix,
+               [SENSOR_TAS5130C] =     tas5130c_matrix,
+       };
+
+       matrix = matrix_tb[sd->sensor];
+       if (matrix == NULL)
+               return;         /* matrix already loaded */
+       for (i = 0; i < ARRAY_SIZE(ov7620_matrix); i++)
+               reg_w(gspca_dev, matrix[i], 0x010a + i);
+}
+
+static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
+{
+       static const u8 sharpness_tb[][2] = {
+               {0x02, 0x03},
+               {0x04, 0x07},
+               {0x08, 0x0f},
+               {0x10, 0x1e}
+       };
+
+       reg_w(gspca_dev, sharpness_tb[val][0], 0x01c6);
+       reg_r(gspca_dev, 0x01c8);
+       reg_r(gspca_dev, 0x01c9);
+       reg_r(gspca_dev, 0x01ca);
+       reg_w(gspca_dev, sharpness_tb[val][1], 0x01cb);
+}
+
+static void setcontrast(struct gspca_dev *gspca_dev,
+               s32 gamma, s32 brightness, s32 contrast)
+{
+       const u8 *Tgamma;
+       int g, i, adj, gp1, gp2;
+       u8 gr[16];
+       static const u8 delta_b[16] =           /* delta for brightness */
+               {0x50, 0x38, 0x2d, 0x28, 0x24, 0x21, 0x1e, 0x1d,
+                0x1d, 0x1b, 0x1b, 0x1b, 0x19, 0x18, 0x18, 0x18};
+       static const u8 delta_c[16] =           /* delta for contrast */
+               {0x2c, 0x1a, 0x12, 0x0c, 0x0a, 0x06, 0x06, 0x06,
+                0x04, 0x06, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02};
+       static const u8 gamma_tb[6][16] = {
+               {0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f,
+                0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff},
+               {0x01, 0x0c, 0x1f, 0x3a, 0x53, 0x6d, 0x85, 0x9c,
+                0xb0, 0xc2, 0xd1, 0xde, 0xe9, 0xf2, 0xf9, 0xff},
+               {0x04, 0x16, 0x30, 0x4e, 0x68, 0x81, 0x98, 0xac,
+                0xbe, 0xcd, 0xda, 0xe4, 0xed, 0xf5, 0xfb, 0xff},
+               {0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
+                0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff},
+               {0x20, 0x4b, 0x6e, 0x8d, 0xa3, 0xb5, 0xc5, 0xd2,
+                0xdc, 0xe5, 0xec, 0xf2, 0xf6, 0xfa, 0xfd, 0xff},
+               {0x24, 0x44, 0x64, 0x84, 0x9d, 0xb2, 0xc4, 0xd3,
+                0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff},
+       };
+
+       Tgamma = gamma_tb[gamma - 1];
+
+       contrast -= 128; /* -128 / 127 */
+       brightness -= 128; /* -128 / 92 */
+       adj = 0;
+       gp1 = gp2 = 0;
+       for (i = 0; i < 16; i++) {
+               g = Tgamma[i] + delta_b[i] * brightness / 256
+                               - delta_c[i] * contrast / 256 - adj / 2;
+               if (g > 0xff)
+                       g = 0xff;
+               else if (g < 0)
+                       g = 0;
+               reg_w(gspca_dev, g, 0x0120 + i);        /* gamma */
+               if (contrast > 0)
+                       adj--;
+               else if (contrast < 0)
+                       adj++;
+               if (i > 1)
+                       gr[i - 1] = (g - gp2) / 2;
+               else if (i != 0)
+                       gr[0] = gp1 == 0 ? 0 : (g - gp1);
+               gp2 = gp1;
+               gp1 = g;
+       }
+       gr[15] = (0xff - gp2) / 2;
+       for (i = 0; i < 16; i++)
+               reg_w(gspca_dev, gr[i], 0x0130 + i);    /* gradient */
+}
+
+static s32 getexposure(struct gspca_dev *gspca_dev)
+{
+       return (i2c_read(gspca_dev, 0x25) << 9)
+               | (i2c_read(gspca_dev, 0x26) << 1)
+               | (i2c_read(gspca_dev, 0x27) >> 7);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev, s32 val)
+{
+       i2c_write(gspca_dev, 0x25, val >> 9, 0x00);
+       i2c_write(gspca_dev, 0x26, val >> 1, 0x00);
+       i2c_write(gspca_dev, 0x27, val << 7, 0x00);
+}
+
+static void setquality(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       jpeg_set_qual(sd->jpeg_hdr, jpeg_qual[sd->reg08 >> 1]);
+       reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING);
+}
+
+/* Matches the sensor's internal frame rate to the lighting frequency.
+ * Valid frequencies are:
+ *     50Hz, for European and Asian lighting (default)
+ *     60Hz, for American lighting
+ *     0 = No Fliker (for outdoore usage)
+ */
+static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i, mode;
+       const struct usb_action *zc3_freq;
+       static const struct usb_action *freq_tb[SENSOR_MAX][6] = {
+       [SENSOR_ADCM2700] =
+               {adcm2700_NoFliker, adcm2700_NoFliker,
+                adcm2700_50HZ, adcm2700_50HZ,
+                adcm2700_60HZ, adcm2700_60HZ},
+       [SENSOR_CS2102] =
+               {cs2102_NoFliker, cs2102_NoFlikerScale,
+                cs2102_50HZ, cs2102_50HZScale,
+                cs2102_60HZ, cs2102_60HZScale},
+       [SENSOR_CS2102K] =
+               {cs2102_NoFliker, cs2102_NoFlikerScale,
+                NULL, NULL, /* currently disabled */
+                NULL, NULL},
+       [SENSOR_GC0303] =
+               {gc0303_NoFliker, gc0303_NoFlikerScale,
+                gc0303_50HZ, gc0303_50HZScale,
+                gc0303_60HZ, gc0303_60HZScale},
+       [SENSOR_GC0305] =
+               {gc0305_NoFliker, gc0305_NoFliker,
+                gc0305_50HZ, gc0305_50HZ,
+                gc0305_60HZ, gc0305_60HZ},
+       [SENSOR_HDCS2020] =
+               {hdcs2020_NoFliker, hdcs2020_NoFliker,
+                hdcs2020_50HZ, hdcs2020_50HZ,
+                hdcs2020_60HZ, hdcs2020_60HZ},
+       [SENSOR_HV7131B] =
+               {hv7131b_NoFliker, hv7131b_NoFlikerScale,
+                hv7131b_50HZ, hv7131b_50HZScale,
+                hv7131b_60HZ, hv7131b_60HZScale},
+       [SENSOR_HV7131R] =
+               {hv7131r_NoFliker, hv7131r_NoFlikerScale,
+                hv7131r_50HZ, hv7131r_50HZScale,
+                hv7131r_60HZ, hv7131r_60HZScale},
+       [SENSOR_ICM105A] =
+               {icm105a_NoFliker, icm105a_NoFlikerScale,
+                icm105a_50HZ, icm105a_50HZScale,
+                icm105a_60HZ, icm105a_60HZScale},
+       [SENSOR_MC501CB] =
+               {mc501cb_NoFliker, mc501cb_NoFlikerScale,
+                mc501cb_50HZ, mc501cb_50HZScale,
+                mc501cb_60HZ, mc501cb_60HZScale},
+       [SENSOR_MT9V111_1] =
+               {mt9v111_1_AENoFliker, mt9v111_1_AENoFlikerScale,
+                mt9v111_1_AE50HZ, mt9v111_1_AE50HZScale,
+                mt9v111_1_AE60HZ, mt9v111_1_AE60HZScale},
+       [SENSOR_MT9V111_3] =
+               {mt9v111_3_AENoFliker, mt9v111_3_AENoFlikerScale,
+                mt9v111_3_AE50HZ, mt9v111_3_AE50HZScale,
+                mt9v111_3_AE60HZ, mt9v111_3_AE60HZScale},
+       [SENSOR_OV7620] =
+               {ov7620_NoFliker, ov7620_NoFliker,
+                ov7620_50HZ, ov7620_50HZ,
+                ov7620_60HZ, ov7620_60HZ},
+       [SENSOR_OV7630C] =
+               {NULL, NULL,
+                NULL, NULL,
+                NULL, NULL},
+       [SENSOR_PAS106] =
+               {pas106b_NoFliker, pas106b_NoFliker,
+                pas106b_50HZ, pas106b_50HZ,
+                pas106b_60HZ, pas106b_60HZ},
+       [SENSOR_PAS202B] =
+               {pas202b_NoFliker, pas202b_NoFlikerScale,
+                pas202b_50HZ, pas202b_50HZScale,
+                pas202b_60HZ, pas202b_60HZScale},
+       [SENSOR_PB0330] =
+               {pb0330_NoFliker, pb0330_NoFlikerScale,
+                pb0330_50HZ, pb0330_50HZScale,
+                pb0330_60HZ, pb0330_60HZScale},
+       [SENSOR_PO2030] =
+               {po2030_NoFliker, po2030_NoFliker,
+                po2030_50HZ, po2030_50HZ,
+                po2030_60HZ, po2030_60HZ},
+       [SENSOR_TAS5130C] =
+               {tas5130c_NoFliker, tas5130c_NoFlikerScale,
+                tas5130c_50HZ, tas5130c_50HZScale,
+                tas5130c_60HZ, tas5130c_60HZScale},
+       };
+
+       i = val * 2;
+       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+       if (mode)
+               i++;                    /* 320x240 */
+       zc3_freq = freq_tb[sd->sensor][i];
+       if (zc3_freq == NULL)
+               return;
+       usb_exchange(gspca_dev, zc3_freq);
+       switch (sd->sensor) {
+       case SENSOR_GC0305:
+               if (mode                /* if 320x240 */
+                   && val == 1)        /* and 50Hz */
+                       reg_w(gspca_dev, 0x85, 0x018d);
+                                       /* win: 0x80, 0x018d */
+               break;
+       case SENSOR_OV7620:
+               if (!mode) {            /* if 640x480 */
+                       if (val != 0)   /* and filter */
+                               reg_w(gspca_dev, 0x40, 0x0002);
+                       else
+                               reg_w(gspca_dev, 0x44, 0x0002);
+               }
+               break;
+       case SENSOR_PAS202B:
+               reg_w(gspca_dev, 0x00, 0x01a7);
+               break;
+       }
+}
+
+static void setautogain(struct gspca_dev *gspca_dev, s32 val)
+{
+       reg_w(gspca_dev, val ? 0x42 : 0x02, 0x0180);
+}
+
+/*
+ * Update the transfer parameters.
+ * This function is executed from a work queue.
+ */
+static void transfer_update(struct work_struct *work)
+{
+       struct sd *sd = container_of(work, struct sd, work);
+       struct gspca_dev *gspca_dev = &sd->gspca_dev;
+       int change, good;
+       u8 reg07, reg11;
+
+       /* reg07 gets set to 0 by sd_start before starting us */
+       reg07 = 0;
+
+       good = 0;
+       for (;;) {
+               msleep(100);
+
+               mutex_lock(&gspca_dev->usb_lock);
+#ifdef CONFIG_PM
+               if (gspca_dev->frozen)
+                       goto err;
+#endif
+               if (!gspca_dev->dev || !gspca_dev->streaming)
+                       goto err;
+
+               /* Bit 0 of register 11 indicates FIFO overflow */
+               gspca_dev->usb_err = 0;
+               reg11 = reg_r(gspca_dev, 0x0011);
+               if (gspca_dev->usb_err)
+                       goto err;
+
+               change = reg11 & 0x01;
+               if (change) {                           /* overflow */
+                       good = 0;
+
+                       if (reg07 == 0) /* Bit Rate Control not enabled? */
+                               reg07 = 0x32; /* Allow 98 bytes / unit */
+                       else if (reg07 > 2)
+                               reg07 -= 2; /* Decrease allowed bytes / unit */
+                       else
+                               change = 0;
+               } else {                                /* no overflow */
+                       good++;
+                       if (good >= 10) {
+                               good = 0;
+                               if (reg07) { /* BRC enabled? */
+                                       change = 1;
+                                       if (reg07 < 0x32)
+                                               reg07 += 2;
+                                       else
+                                               reg07 = 0;
+                               }
+                       }
+               }
+               if (change) {
+                       gspca_dev->usb_err = 0;
+                       reg_w(gspca_dev, reg07, 0x0007);
+                       if (gspca_dev->usb_err)
+                               goto err;
+               }
+               mutex_unlock(&gspca_dev->usb_lock);
+       }
+       return;
+err:
+       mutex_unlock(&gspca_dev->usb_lock);
+}
+
+static void send_unknown(struct gspca_dev *gspca_dev, int sensor)
+{
+       reg_w(gspca_dev, 0x01, 0x0000);         /* bridge reset */
+       switch (sensor) {
+       case SENSOR_PAS106:
+               reg_w(gspca_dev, 0x03, 0x003a);
+               reg_w(gspca_dev, 0x0c, 0x003b);
+               reg_w(gspca_dev, 0x08, 0x0038);
+               break;
+       case SENSOR_ADCM2700:
+       case SENSOR_GC0305:
+       case SENSOR_OV7620:
+       case SENSOR_MT9V111_1:
+       case SENSOR_MT9V111_3:
+       case SENSOR_PB0330:
+       case SENSOR_PO2030:
+               reg_w(gspca_dev, 0x0d, 0x003a);
+               reg_w(gspca_dev, 0x02, 0x003b);
+               reg_w(gspca_dev, 0x00, 0x0038);
+               break;
+       case SENSOR_HV7131R:
+       case SENSOR_PAS202B:
+               reg_w(gspca_dev, 0x03, 0x003b);
+               reg_w(gspca_dev, 0x0c, 0x003a);
+               reg_w(gspca_dev, 0x0b, 0x0039);
+               if (sensor == SENSOR_PAS202B)
+                       reg_w(gspca_dev, 0x0b, 0x0038);
+               break;
+       }
+}
+
+/* start probe 2 wires */
+static void start_2wr_probe(struct gspca_dev *gspca_dev, int sensor)
+{
+       reg_w(gspca_dev, 0x01, 0x0000);
+       reg_w(gspca_dev, sensor, 0x0010);
+       reg_w(gspca_dev, 0x01, 0x0001);
+       reg_w(gspca_dev, 0x03, 0x0012);
+       reg_w(gspca_dev, 0x01, 0x0012);
+/*     msleep(2); */
+}
+
+static int sif_probe(struct gspca_dev *gspca_dev)
+{
+       u16 checkword;
+
+       start_2wr_probe(gspca_dev, 0x0f);               /* PAS106 */
+       reg_w(gspca_dev, 0x08, 0x008d);
+       msleep(150);
+       checkword = ((i2c_read(gspca_dev, 0x00) & 0x0f) << 4)
+                       | ((i2c_read(gspca_dev, 0x01) & 0xf0) >> 4);
+       PDEBUG(D_PROBE, "probe sif 0x%04x", checkword);
+       if (checkword == 0x0007) {
+               send_unknown(gspca_dev, SENSOR_PAS106);
+               return 0x0f;                    /* PAS106 */
+       }
+       return -1;
+}
+
+static int vga_2wr_probe(struct gspca_dev *gspca_dev)
+{
+       u16 retword;
+
+       start_2wr_probe(gspca_dev, 0x00);       /* HV7131B */
+       i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
+       retword = i2c_read(gspca_dev, 0x01);
+       if (retword != 0)
+               return 0x00;                    /* HV7131B */
+
+       start_2wr_probe(gspca_dev, 0x04);       /* CS2102 */
+       i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
+       retword = i2c_read(gspca_dev, 0x01);
+       if (retword != 0)
+               return 0x04;                    /* CS2102 */
+
+       start_2wr_probe(gspca_dev, 0x06);       /* OmniVision */
+       reg_w(gspca_dev, 0x08, 0x008d);
+       i2c_write(gspca_dev, 0x11, 0xaa, 0x00);
+       retword = i2c_read(gspca_dev, 0x11);
+       if (retword != 0) {
+               /* (should have returned 0xaa) --> Omnivision? */
+               /* reg_r 0x10 -> 0x06 -->  */
+               goto ov_check;
+       }
+
+       start_2wr_probe(gspca_dev, 0x08);       /* HDCS2020 */
+       i2c_write(gspca_dev, 0x1c, 0x00, 0x00);
+       i2c_write(gspca_dev, 0x15, 0xaa, 0x00);
+       retword = i2c_read(gspca_dev, 0x15);
+       if (retword != 0)
+               return 0x08;                    /* HDCS2020 */
+
+       start_2wr_probe(gspca_dev, 0x0a);       /* PB0330 */
+       i2c_write(gspca_dev, 0x07, 0xaa, 0xaa);
+       retword = i2c_read(gspca_dev, 0x07);
+       if (retword != 0)
+               return 0x0a;                    /* PB0330 */
+       retword = i2c_read(gspca_dev, 0x03);
+       if (retword != 0)
+               return 0x0a;                    /* PB0330 ?? */
+       retword = i2c_read(gspca_dev, 0x04);
+       if (retword != 0)
+               return 0x0a;                    /* PB0330 ?? */
+
+       start_2wr_probe(gspca_dev, 0x0c);       /* ICM105A */
+       i2c_write(gspca_dev, 0x01, 0x11, 0x00);
+       retword = i2c_read(gspca_dev, 0x01);
+       if (retword != 0)
+               return 0x0c;                    /* ICM105A */
+
+       start_2wr_probe(gspca_dev, 0x0e);       /* PAS202BCB */
+       reg_w(gspca_dev, 0x08, 0x008d);
+       i2c_write(gspca_dev, 0x03, 0xaa, 0x00);
+       msleep(50);
+       retword = i2c_read(gspca_dev, 0x03);
+       if (retword != 0) {
+               send_unknown(gspca_dev, SENSOR_PAS202B);
+               return 0x0e;                    /* PAS202BCB */
+       }
+
+       start_2wr_probe(gspca_dev, 0x02);       /* TAS5130C */
+       i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
+       retword = i2c_read(gspca_dev, 0x01);
+       if (retword != 0)
+               return 0x02;                    /* TAS5130C */
+ov_check:
+       reg_r(gspca_dev, 0x0010);               /* ?? */
+       reg_r(gspca_dev, 0x0010);
+
+       reg_w(gspca_dev, 0x01, 0x0000);
+       reg_w(gspca_dev, 0x01, 0x0001);
+       reg_w(gspca_dev, 0x06, 0x0010);         /* OmniVision */
+       reg_w(gspca_dev, 0xa1, 0x008b);
+       reg_w(gspca_dev, 0x08, 0x008d);
+       msleep(500);
+       reg_w(gspca_dev, 0x01, 0x0012);
+       i2c_write(gspca_dev, 0x12, 0x80, 0x00); /* sensor reset */
+       retword = i2c_read(gspca_dev, 0x0a) << 8;
+       retword |= i2c_read(gspca_dev, 0x0b);
+       PDEBUG(D_PROBE, "probe 2wr ov vga 0x%04x", retword);
+       switch (retword) {
+       case 0x7631:                            /* OV7630C */
+               reg_w(gspca_dev, 0x06, 0x0010);
+               break;
+       case 0x7620:                            /* OV7620 */
+       case 0x7648:                            /* OV7648 */
+               break;
+       default:
+               return -1;                      /* not OmniVision */
+       }
+       return retword;
+}
+
+struct sensor_by_chipset_revision {
+       u16 revision;
+       u8 internal_sensor_id;
+};
+static const struct sensor_by_chipset_revision chipset_revision_sensor[] = {
+       {0xc000, 0x12},         /* TAS5130C */
+       {0xc001, 0x13},         /* MT9V111 */
+       {0xe001, 0x13},
+       {0x8001, 0x13},
+       {0x8000, 0x14},         /* CS2102K */
+       {0x8400, 0x15},         /* MT9V111 */
+       {0xe400, 0x15},
+};
+
+static int vga_3wr_probe(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int i;
+       u16 retword;
+
+/*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/
+       reg_w(gspca_dev, 0x02, 0x0010);
+       reg_r(gspca_dev, 0x0010);
+       reg_w(gspca_dev, 0x01, 0x0000);
+       reg_w(gspca_dev, 0x00, 0x0010);
+       reg_w(gspca_dev, 0x01, 0x0001);
+       reg_w(gspca_dev, 0x91, 0x008b);
+       reg_w(gspca_dev, 0x03, 0x0012);
+       reg_w(gspca_dev, 0x01, 0x0012);
+       reg_w(gspca_dev, 0x05, 0x0012);
+       retword = i2c_read(gspca_dev, 0x14);
+       if (retword != 0)
+               return 0x11;                    /* HV7131R */
+       retword = i2c_read(gspca_dev, 0x15);
+       if (retword != 0)
+               return 0x11;                    /* HV7131R */
+       retword = i2c_read(gspca_dev, 0x16);
+       if (retword != 0)
+               return 0x11;                    /* HV7131R */
+
+       reg_w(gspca_dev, 0x02, 0x0010);
+       retword = reg_r(gspca_dev, 0x000b) << 8;
+       retword |= reg_r(gspca_dev, 0x000a);
+       PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", retword);
+       reg_r(gspca_dev, 0x0010);
+       if ((retword & 0xff00) == 0x6400)
+               return 0x02;            /* TAS5130C */
+       for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) {
+               if (chipset_revision_sensor[i].revision == retword) {
+                       sd->chip_revision = retword;
+                       send_unknown(gspca_dev, SENSOR_PB0330);
+                       return chipset_revision_sensor[i].internal_sensor_id;
+               }
+       }
+
+       reg_w(gspca_dev, 0x01, 0x0000); /* check PB0330 */
+       reg_w(gspca_dev, 0x01, 0x0001);
+       reg_w(gspca_dev, 0xdd, 0x008b);
+       reg_w(gspca_dev, 0x0a, 0x0010);
+       reg_w(gspca_dev, 0x03, 0x0012);
+       reg_w(gspca_dev, 0x01, 0x0012);
+       retword = i2c_read(gspca_dev, 0x00);
+       if (retword != 0) {
+               PDEBUG(D_PROBE, "probe 3wr vga type 0a");
+               return 0x0a;                    /* PB0330 */
+       }
+
+       /* probe gc0303 / gc0305 */
+       reg_w(gspca_dev, 0x01, 0x0000);
+       reg_w(gspca_dev, 0x01, 0x0001);
+       reg_w(gspca_dev, 0x98, 0x008b);
+       reg_w(gspca_dev, 0x01, 0x0010);
+       reg_w(gspca_dev, 0x03, 0x0012);
+       msleep(2);
+       reg_w(gspca_dev, 0x01, 0x0012);
+       retword = i2c_read(gspca_dev, 0x00);
+       if (retword != 0) {
+               PDEBUG(D_PROBE, "probe 3wr vga type %02x", retword);
+               if (retword == 0x0011)                  /* gc0303 */
+                       return 0x0303;
+               if (retword == 0x0029)                  /* gc0305 */
+                       send_unknown(gspca_dev, SENSOR_GC0305);
+               return retword;
+       }
+
+       reg_w(gspca_dev, 0x01, 0x0000); /* check OmniVision */
+       reg_w(gspca_dev, 0x01, 0x0001);
+       reg_w(gspca_dev, 0xa1, 0x008b);
+       reg_w(gspca_dev, 0x08, 0x008d);
+       reg_w(gspca_dev, 0x06, 0x0010);
+       reg_w(gspca_dev, 0x01, 0x0012);
+       reg_w(gspca_dev, 0x05, 0x0012);
+       if (i2c_read(gspca_dev, 0x1c) == 0x007f /* OV7610 - manufacturer ID */
+           && i2c_read(gspca_dev, 0x1d) == 0x00a2) {
+               send_unknown(gspca_dev, SENSOR_OV7620);
+               return 0x06;            /* OmniVision confirm ? */
+       }
+
+       reg_w(gspca_dev, 0x01, 0x0000);
+       reg_w(gspca_dev, 0x00, 0x0002);
+       reg_w(gspca_dev, 0x01, 0x0010);
+       reg_w(gspca_dev, 0x01, 0x0001);
+       reg_w(gspca_dev, 0xee, 0x008b);
+       reg_w(gspca_dev, 0x03, 0x0012);
+       reg_w(gspca_dev, 0x01, 0x0012);
+       reg_w(gspca_dev, 0x05, 0x0012);
+       retword = i2c_read(gspca_dev, 0x00) << 8;       /* ID 0 */
+       retword |= i2c_read(gspca_dev, 0x01);           /* ID 1 */
+       PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", retword);
+       if (retword == 0x2030) {
+#ifdef GSPCA_DEBUG
+               u8 retbyte;
+
+               retbyte = i2c_read(gspca_dev, 0x02);    /* revision number */
+               PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte);
+#endif
+               send_unknown(gspca_dev, SENSOR_PO2030);
+               return retword;
+       }
+
+       reg_w(gspca_dev, 0x01, 0x0000);
+       reg_w(gspca_dev, 0x0a, 0x0010);
+       reg_w(gspca_dev, 0xd3, 0x008b);
+       reg_w(gspca_dev, 0x01, 0x0001);
+       reg_w(gspca_dev, 0x03, 0x0012);
+       reg_w(gspca_dev, 0x01, 0x0012);
+       reg_w(gspca_dev, 0x05, 0x0012);
+       reg_w(gspca_dev, 0xd3, 0x008b);
+       retword = i2c_read(gspca_dev, 0x01);
+       if (retword != 0) {
+               PDEBUG(D_PROBE, "probe 3wr vga type 0a ? ret: %04x", retword);
+               return 0x16;                    /* adcm2700 (6100/6200) */
+       }
+       return -1;
+}
+
+static int zcxx_probeSensor(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int sensor;
+
+       switch (sd->sensor) {
+       case SENSOR_MC501CB:
+               return -1;              /* don't probe */
+       case SENSOR_GC0303:
+                       /* may probe but with no write in reg 0x0010 */
+               return -1;              /* don't probe */
+       case SENSOR_PAS106:
+               sensor =  sif_probe(gspca_dev);
+               if (sensor >= 0)
+                       return sensor;
+               break;
+       }
+       sensor = vga_2wr_probe(gspca_dev);
+       if (sensor >= 0)
+               return sensor;
+       return vga_3wr_probe(gspca_dev);
+}
+
+/* this function is called at probe time */
+static int sd_config(struct gspca_dev *gspca_dev,
+                       const struct usb_device_id *id)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (id->idProduct == 0x301b)
+               sd->bridge = BRIDGE_ZC301;
+       else
+               sd->bridge = BRIDGE_ZC303;
+
+       /* define some sensors from the vendor/product */
+       sd->sensor = id->driver_info;
+
+       sd->reg08 = REG08_DEF;
+
+       INIT_WORK(&sd->work, transfer_update);
+
+       return 0;
+}
+
+static int zcxx_g_volatile_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;
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUTOGAIN:
+               gspca_dev->usb_err = 0;
+               if (ctrl->val && sd->exposure && gspca_dev->streaming)
+                       sd->exposure->val = getexposure(gspca_dev);
+               return gspca_dev->usb_err;
+       }
+       return -EINVAL;
+}
+
+static int zcxx_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;
+       int i, qual;
+
+       gspca_dev->usb_err = 0;
+
+       if (ctrl->id == V4L2_CID_JPEG_COMPRESSION_QUALITY) {
+               qual = sd->reg08 >> 1;
+
+               for (i = 0; i < ARRAY_SIZE(jpeg_qual); i++) {
+                       if (ctrl->val <= jpeg_qual[i])
+                               break;
+               }
+               if (i > 0 && i == qual && ctrl->val < jpeg_qual[i])
+                       i--;
+
+               /* With high quality settings we need max bandwidth */
+               if (i >= 2 && gspca_dev->streaming &&
+                   !gspca_dev->cam.needs_full_bandwidth)
+                       return -EBUSY;
+
+               sd->reg08 = (i << 1) | 1;
+               ctrl->val = jpeg_qual[i];
+       }
+
+       if (!gspca_dev->streaming)
+               return 0;
+
+       switch (ctrl->id) {
+       /* gamma/brightness/contrast cluster */
+       case V4L2_CID_GAMMA:
+               setcontrast(gspca_dev, sd->gamma->val,
+                               sd->brightness->val, sd->contrast->val);
+               break;
+       /* autogain/exposure cluster */
+       case V4L2_CID_AUTOGAIN:
+               setautogain(gspca_dev, ctrl->val);
+               if (!gspca_dev->usb_err && !ctrl->val && sd->exposure)
+                       setexposure(gspca_dev, sd->exposure->val);
+               break;
+       case V4L2_CID_POWER_LINE_FREQUENCY:
+               setlightfreq(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_SHARPNESS:
+               setsharpness(gspca_dev, ctrl->val);
+               break;
+       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+               setquality(gspca_dev);
+               break;
+       }
+       return gspca_dev->usb_err;
+}
+
+static const struct v4l2_ctrl_ops zcxx_ctrl_ops = {
+       .g_volatile_ctrl = zcxx_g_volatile_ctrl,
+       .s_ctrl = zcxx_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;
+       static const u8 gamma[SENSOR_MAX] = {
+               [SENSOR_ADCM2700] =     4,
+               [SENSOR_CS2102] =       4,
+               [SENSOR_CS2102K] =      5,
+               [SENSOR_GC0303] =       3,
+               [SENSOR_GC0305] =       4,
+               [SENSOR_HDCS2020] =     4,
+               [SENSOR_HV7131B] =      4,
+               [SENSOR_HV7131R] =      4,
+               [SENSOR_ICM105A] =      4,
+               [SENSOR_MC501CB] =      4,
+               [SENSOR_MT9V111_1] =    4,
+               [SENSOR_MT9V111_3] =    4,
+               [SENSOR_OV7620] =       3,
+               [SENSOR_OV7630C] =      4,
+               [SENSOR_PAS106] =       4,
+               [SENSOR_PAS202B] =      4,
+               [SENSOR_PB0330] =       4,
+               [SENSOR_PO2030] =       4,
+               [SENSOR_TAS5130C] =     3,
+       };
+
+       gspca_dev->vdev.ctrl_handler = hdl;
+       v4l2_ctrl_handler_init(hdl, 8);
+       sd->brightness = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+       sd->contrast = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 255, 1, 128);
+       sd->gamma = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
+                       V4L2_CID_GAMMA, 1, 6, 1, gamma[sd->sensor]);
+       if (sd->sensor == SENSOR_HV7131R)
+               sd->exposure = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
+                       V4L2_CID_EXPOSURE, 0x30d, 0x493e, 1, 0x927);
+       sd->autogain = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
+                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+       if (sd->sensor != SENSOR_OV7630C)
+               sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &zcxx_ctrl_ops,
+                       V4L2_CID_POWER_LINE_FREQUENCY,
+                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
+                       V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
+       sd->sharpness = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
+                       V4L2_CID_SHARPNESS, 0, 3, 1,
+                       sd->sensor == SENSOR_PO2030 ? 0 : 2);
+       sd->jpegqual = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
+                       V4L2_CID_JPEG_COMPRESSION_QUALITY,
+                       jpeg_qual[0], jpeg_qual[ARRAY_SIZE(jpeg_qual) - 1], 1,
+                       jpeg_qual[REG08_DEF >> 1]);
+       if (hdl->error) {
+               pr_err("Could not initialize controls\n");
+               return hdl->error;
+       }
+       v4l2_ctrl_cluster(3, &sd->gamma);
+       if (sd->sensor == SENSOR_HV7131R)
+               v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, true);
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam;
+       int sensor;
+       static const u8 mode_tb[SENSOR_MAX] = {
+               [SENSOR_ADCM2700] =     2,
+               [SENSOR_CS2102] =       1,
+               [SENSOR_CS2102K] =      1,
+               [SENSOR_GC0303] =       1,
+               [SENSOR_GC0305] =       1,
+               [SENSOR_HDCS2020] =     1,
+               [SENSOR_HV7131B] =      1,
+               [SENSOR_HV7131R] =      1,
+               [SENSOR_ICM105A] =      1,
+               [SENSOR_MC501CB] =      2,
+               [SENSOR_MT9V111_1] =    1,
+               [SENSOR_MT9V111_3] =    1,
+               [SENSOR_OV7620] =       2,
+               [SENSOR_OV7630C] =      1,
+               [SENSOR_PAS106] =       0,
+               [SENSOR_PAS202B] =      1,
+               [SENSOR_PB0330] =       1,
+               [SENSOR_PO2030] =       1,
+               [SENSOR_TAS5130C] =     1,
+       };
+
+       sensor = zcxx_probeSensor(gspca_dev);
+       if (sensor >= 0)
+               PDEBUG(D_PROBE, "probe sensor -> %04x", sensor);
+       if ((unsigned) force_sensor < SENSOR_MAX) {
+               sd->sensor = force_sensor;
+               PDEBUG(D_PROBE, "sensor forced to %d", force_sensor);
+       } else {
+               switch (sensor) {
+               case -1:
+                       switch (sd->sensor) {
+                       case SENSOR_MC501CB:
+                               PDEBUG(D_PROBE, "Sensor MC501CB");
+                               break;
+                       case SENSOR_GC0303:
+                               PDEBUG(D_PROBE, "Sensor GC0303");
+                               break;
+                       default:
+                               pr_warn("Unknown sensor - set to TAS5130C\n");
+                               sd->sensor = SENSOR_TAS5130C;
+                       }
+                       break;
+               case 0:
+                       /* check the sensor type */
+                       sensor = i2c_read(gspca_dev, 0x00);
+                       PDEBUG(D_PROBE, "Sensor hv7131 type %d", sensor);
+                       switch (sensor) {
+                       case 0:                 /* hv7131b */
+                       case 1:                 /* hv7131e */
+                               PDEBUG(D_PROBE, "Find Sensor HV7131B");
+                               sd->sensor = SENSOR_HV7131B;
+                               break;
+                       default:
+/*                     case 2:                  * hv7131r */
+                               PDEBUG(D_PROBE, "Find Sensor HV7131R");
+                               sd->sensor = SENSOR_HV7131R;
+                               break;
+                       }
+                       break;
+               case 0x02:
+                       PDEBUG(D_PROBE, "Sensor TAS5130C");
+                       sd->sensor = SENSOR_TAS5130C;
+                       break;
+               case 0x04:
+                       PDEBUG(D_PROBE, "Find Sensor CS2102");
+                       sd->sensor = SENSOR_CS2102;
+                       break;
+               case 0x08:
+                       PDEBUG(D_PROBE, "Find Sensor HDCS2020");
+                       sd->sensor = SENSOR_HDCS2020;
+                       break;
+               case 0x0a:
+                       PDEBUG(D_PROBE,
+                               "Find Sensor PB0330. Chip revision %x",
+                               sd->chip_revision);
+                       sd->sensor = SENSOR_PB0330;
+                       break;
+               case 0x0c:
+                       PDEBUG(D_PROBE, "Find Sensor ICM105A");
+                       sd->sensor = SENSOR_ICM105A;
+                       break;
+               case 0x0e:
+                       PDEBUG(D_PROBE, "Find Sensor PAS202B");
+                       sd->sensor = SENSOR_PAS202B;
+                       break;
+               case 0x0f:
+                       PDEBUG(D_PROBE, "Find Sensor PAS106");
+                       sd->sensor = SENSOR_PAS106;
+                       break;
+               case 0x10:
+               case 0x12:
+                       PDEBUG(D_PROBE, "Find Sensor TAS5130C");
+                       sd->sensor = SENSOR_TAS5130C;
+                       break;
+               case 0x11:
+                       PDEBUG(D_PROBE, "Find Sensor HV7131R");
+                       sd->sensor = SENSOR_HV7131R;
+                       break;
+               case 0x13:
+               case 0x15:
+                       PDEBUG(D_PROBE,
+                               "Sensor MT9V111. Chip revision %04x",
+                               sd->chip_revision);
+                       sd->sensor = sd->bridge == BRIDGE_ZC301
+                                       ? SENSOR_MT9V111_1
+                                       : SENSOR_MT9V111_3;
+                       break;
+               case 0x14:
+                       PDEBUG(D_PROBE,
+                               "Find Sensor CS2102K?. Chip revision %x",
+                               sd->chip_revision);
+                       sd->sensor = SENSOR_CS2102K;
+                       break;
+               case 0x16:
+                       PDEBUG(D_PROBE, "Find Sensor ADCM2700");
+                       sd->sensor = SENSOR_ADCM2700;
+                       break;
+               case 0x29:
+                       PDEBUG(D_PROBE, "Find Sensor GC0305");
+                       sd->sensor = SENSOR_GC0305;
+                       break;
+               case 0x0303:
+                       PDEBUG(D_PROBE, "Sensor GC0303");
+                       sd->sensor =  SENSOR_GC0303;
+                       break;
+               case 0x2030:
+                       PDEBUG(D_PROBE, "Find Sensor PO2030");
+                       sd->sensor = SENSOR_PO2030;
+                       break;
+               case 0x7620:
+                       PDEBUG(D_PROBE, "Find Sensor OV7620");
+                       sd->sensor = SENSOR_OV7620;
+                       break;
+               case 0x7631:
+                       PDEBUG(D_PROBE, "Find Sensor OV7630C");
+                       sd->sensor = SENSOR_OV7630C;
+                       break;
+               case 0x7648:
+                       PDEBUG(D_PROBE, "Find Sensor OV7648");
+                       sd->sensor = SENSOR_OV7620;     /* same sensor (?) */
+                       break;
+               default:
+                       pr_err("Unknown sensor %04x\n", sensor);
+                       return -EINVAL;
+               }
+       }
+       if (sensor < 0x20) {
+               if (sensor == -1 || sensor == 0x10 || sensor == 0x12)
+                       reg_w(gspca_dev, 0x02, 0x0010);
+               reg_r(gspca_dev, 0x0010);
+       }
+
+       cam = &gspca_dev->cam;
+       switch (mode_tb[sd->sensor]) {
+       case 0:
+               cam->cam_mode = sif_mode;
+               cam->nmodes = ARRAY_SIZE(sif_mode);
+               break;
+       case 1:
+               cam->cam_mode = vga_mode;
+               cam->nmodes = ARRAY_SIZE(vga_mode);
+               break;
+       default:
+/*     case 2: */
+               cam->cam_mode = broken_vga_mode;
+               cam->nmodes = ARRAY_SIZE(broken_vga_mode);
+               break;
+       }
+
+       /* switch off the led */
+       reg_w(gspca_dev, 0x01, 0x0000);
+       return gspca_dev->usb_err;
+}
+
+static int sd_pre_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       gspca_dev->cam.needs_full_bandwidth = (sd->reg08 >= 4) ? 1 : 0;
+       return 0;
+}
+
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int mode;
+       static const struct usb_action *init_tb[SENSOR_MAX][2] = {
+       [SENSOR_ADCM2700] =
+                       {adcm2700_Initial, adcm2700_InitialScale},
+       [SENSOR_CS2102] =
+                       {cs2102_Initial, cs2102_InitialScale},
+       [SENSOR_CS2102K] =
+                       {cs2102K_Initial, cs2102K_InitialScale},
+       [SENSOR_GC0303] =
+               {gc0303_Initial, gc0303_InitialScale},
+       [SENSOR_GC0305] =
+                       {gc0305_Initial, gc0305_InitialScale},
+       [SENSOR_HDCS2020] =
+                       {hdcs2020_Initial, hdcs2020_InitialScale},
+       [SENSOR_HV7131B] =
+                       {hv7131b_Initial, hv7131b_InitialScale},
+       [SENSOR_HV7131R] =
+                       {hv7131r_Initial, hv7131r_InitialScale},
+       [SENSOR_ICM105A] =
+                       {icm105a_Initial, icm105a_InitialScale},
+       [SENSOR_MC501CB] =
+                       {mc501cb_Initial, mc501cb_InitialScale},
+       [SENSOR_MT9V111_1] =
+                       {mt9v111_1_Initial, mt9v111_1_InitialScale},
+       [SENSOR_MT9V111_3] =
+                       {mt9v111_3_Initial, mt9v111_3_InitialScale},
+       [SENSOR_OV7620] =
+                       {ov7620_Initial, ov7620_InitialScale},
+       [SENSOR_OV7630C] =
+                       {ov7630c_Initial, ov7630c_InitialScale},
+       [SENSOR_PAS106] =
+                       {pas106b_Initial, pas106b_InitialScale},
+       [SENSOR_PAS202B] =
+                       {pas202b_Initial, pas202b_InitialScale},
+       [SENSOR_PB0330] =
+                       {pb0330_Initial, pb0330_InitialScale},
+       [SENSOR_PO2030] =
+                       {po2030_Initial, po2030_InitialScale},
+       [SENSOR_TAS5130C] =
+                       {tas5130c_Initial, tas5130c_InitialScale},
+       };
+
+       /* create the JPEG header */
+       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+                       0x21);          /* JPEG 422 */
+
+       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
+       switch (sd->sensor) {
+       case SENSOR_HV7131R:
+               zcxx_probeSensor(gspca_dev);
+               break;
+       case SENSOR_PAS106:
+               usb_exchange(gspca_dev, pas106b_Initial_com);
+               break;
+       }
+       usb_exchange(gspca_dev, init_tb[sd->sensor][mode]);
+
+       switch (sd->sensor) {
+       case SENSOR_ADCM2700:
+       case SENSOR_GC0305:
+       case SENSOR_OV7620:
+       case SENSOR_PO2030:
+       case SENSOR_TAS5130C:
+       case SENSOR_GC0303:
+/*             msleep(100);                     * ?? */
+               reg_r(gspca_dev, 0x0002);       /* --> 0x40 */
+               reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
+               reg_w(gspca_dev, 0x15, 0x01ae);
+               if (sd->sensor == SENSOR_TAS5130C)
+                       break;
+               reg_w(gspca_dev, 0x0d, 0x003a);
+               reg_w(gspca_dev, 0x02, 0x003b);
+               reg_w(gspca_dev, 0x00, 0x0038);
+               break;
+       case SENSOR_HV7131R:
+       case SENSOR_PAS202B:
+               reg_w(gspca_dev, 0x03, 0x003b);
+               reg_w(gspca_dev, 0x0c, 0x003a);
+               reg_w(gspca_dev, 0x0b, 0x0039);
+               if (sd->sensor == SENSOR_HV7131R)
+                       reg_w(gspca_dev, 0x50, ZC3XX_R11D_GLOBALGAIN);
+               break;
+       }
+
+       setmatrix(gspca_dev);
+       switch (sd->sensor) {
+       case SENSOR_ADCM2700:
+       case SENSOR_OV7620:
+               reg_r(gspca_dev, 0x0008);
+               reg_w(gspca_dev, 0x00, 0x0008);
+               break;
+       case SENSOR_PAS202B:
+       case SENSOR_GC0305:
+       case SENSOR_HV7131R:
+       case SENSOR_TAS5130C:
+               reg_r(gspca_dev, 0x0008);
+               /* fall thru */
+       case SENSOR_PO2030:
+               reg_w(gspca_dev, 0x03, 0x0008);
+               break;
+       }
+       setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
+
+       /* set the gamma tables when not set */
+       switch (sd->sensor) {
+       case SENSOR_CS2102K:            /* gamma set in xxx_Initial */
+       case SENSOR_HDCS2020:
+       case SENSOR_OV7630C:
+               break;
+       default:
+               setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma),
+                               v4l2_ctrl_g_ctrl(sd->brightness),
+                               v4l2_ctrl_g_ctrl(sd->contrast));
+               break;
+       }
+       setmatrix(gspca_dev);                   /* one more time? */
+       switch (sd->sensor) {
+       case SENSOR_OV7620:
+       case SENSOR_PAS202B:
+               reg_r(gspca_dev, 0x0180);       /* from win */
+               reg_w(gspca_dev, 0x00, 0x0180);
+               break;
+       }
+       setquality(gspca_dev);
+       /* Start with BRC disabled, transfer_update will enable it if needed */
+       reg_w(gspca_dev, 0x00, 0x0007);
+       if (sd->plfreq)
+               setlightfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->plfreq));
+
+       switch (sd->sensor) {
+       case SENSOR_ADCM2700:
+               reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
+               reg_w(gspca_dev, 0x15, 0x01ae);
+               reg_w(gspca_dev, 0x02, 0x0180);
+                                               /* ms-win + */
+               reg_w(gspca_dev, 0x40, 0x0117);
+               break;
+       case SENSOR_HV7131R:
+               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
+               reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN);
+               break;
+       case SENSOR_GC0305:
+       case SENSOR_TAS5130C:
+               reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
+               reg_w(gspca_dev, 0x15, 0x01ae);
+               /* fall thru */
+       case SENSOR_PAS202B:
+       case SENSOR_PO2030:
+/*             reg_w(gspca_dev, 0x40, ZC3XX_R117_GGAIN); in win traces */
+               reg_r(gspca_dev, 0x0180);
+               break;
+       case SENSOR_OV7620:
+               reg_w(gspca_dev, 0x09, 0x01ad);
+               reg_w(gspca_dev, 0x15, 0x01ae);
+               i2c_read(gspca_dev, 0x13);      /*fixme: returns 0xa3 */
+               i2c_write(gspca_dev, 0x13, 0xa3, 0x00);
+                                       /*fixme: returned value to send? */
+               reg_w(gspca_dev, 0x40, 0x0117);
+               reg_r(gspca_dev, 0x0180);
+               break;
+       }
+
+       setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
+
+       if (gspca_dev->usb_err < 0)
+               return gspca_dev->usb_err;
+
+       /* Start the transfer parameters update thread */
+       sd->work_thread = create_singlethread_workqueue(KBUILD_MODNAME);
+       queue_work(sd->work_thread, &sd->work);
+
+       return 0;
+}
+
+/* called on streamoff with alt 0 and on disconnect */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (sd->work_thread != NULL) {
+               mutex_unlock(&gspca_dev->usb_lock);
+               destroy_workqueue(sd->work_thread);
+               mutex_lock(&gspca_dev->usb_lock);
+               sd->work_thread = NULL;
+       }
+       if (!gspca_dev->dev)
+               return;
+       send_unknown(gspca_dev, sd->sensor);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,
+                       int len)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* check the JPEG end of frame */
+       if (len >= 3
+        && data[len - 3] == 0xff && data[len - 2] == 0xd9) {
+/*fixme: what does the last byte mean?*/
+               gspca_frame_add(gspca_dev, LAST_PACKET,
+                                       data, len - 1);
+               return;
+       }
+
+       /* check the JPEG start of a frame */
+       if (data[0] == 0xff && data[1] == 0xd8) {
+               /* put the JPEG header in the new frame */
+               gspca_frame_add(gspca_dev, FIRST_PACKET,
+                       sd->jpeg_hdr, JPEG_HDR_SZ);
+
+               /* remove the webcam's header:
+                * ff d8 ff fe 00 0e 00 00 ss ss 00 01 ww ww hh hh pp pp
+                *      - 'ss ss' is the frame sequence number (BE)
+                *      - 'ww ww' and 'hh hh' are the window dimensions (BE)
+                *      - 'pp pp' is the packet sequence number (BE)
+                */
+               data += 18;
+               len -= 18;
+       }
+       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+}
+
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+                       struct v4l2_jpegcompression *jcomp)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       int ret;
+
+       ret = v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
+       if (ret)
+               return ret;
+       jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
+       return 0;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+                       struct v4l2_jpegcompression *jcomp)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       memset(jcomp, 0, sizeof *jcomp);
+       jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
+       jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+                       | V4L2_JPEG_MARKER_DQT;
+       return 0;
+}
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
+                       u8 *data,               /* interrupt packet data */
+                       int len)                /* interrput packet length */
+{
+       if (len == 8 && data[4] == 1) {
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
+               input_sync(gspca_dev->input_dev);
+               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+               input_sync(gspca_dev->input_dev);
+       }
+
+       return 0;
+}
+#endif
+
+static const struct sd_desc sd_desc = {
+       .name = KBUILD_MODNAME,
+       .config = sd_config,
+       .init = sd_init,
+       .init_controls = sd_init_controls,
+       .isoc_init = sd_pre_start,
+       .start = sd_start,
+       .stop0 = sd_stop0,
+       .pkt_scan = sd_pkt_scan,
+       .get_jcomp = sd_get_jcomp,
+       .set_jcomp = sd_set_jcomp,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+       .int_pkt_scan = sd_int_pkt_scan,
+#endif
+};
+
+static const struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x03f0, 0x1b07)},
+       {USB_DEVICE(0x041e, 0x041e)},
+       {USB_DEVICE(0x041e, 0x4017)},
+       {USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106},
+       {USB_DEVICE(0x041e, 0x401e)},
+       {USB_DEVICE(0x041e, 0x401f)},
+       {USB_DEVICE(0x041e, 0x4022)},
+       {USB_DEVICE(0x041e, 0x4029)},
+       {USB_DEVICE(0x041e, 0x4034), .driver_info = SENSOR_PAS106},
+       {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106},
+       {USB_DEVICE(0x041e, 0x4036)},
+       {USB_DEVICE(0x041e, 0x403a)},
+       {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_GC0303},
+       {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_GC0303},
+       {USB_DEVICE(0x0458, 0x7007)},
+       {USB_DEVICE(0x0458, 0x700c)},
+       {USB_DEVICE(0x0458, 0x700f)},
+       {USB_DEVICE(0x0461, 0x0a00)},
+       {USB_DEVICE(0x046d, 0x089d), .driver_info = SENSOR_MC501CB},
+       {USB_DEVICE(0x046d, 0x08a0)},
+       {USB_DEVICE(0x046d, 0x08a1)},
+       {USB_DEVICE(0x046d, 0x08a2)},
+       {USB_DEVICE(0x046d, 0x08a3)},
+       {USB_DEVICE(0x046d, 0x08a6)},
+       {USB_DEVICE(0x046d, 0x08a7)},
+       {USB_DEVICE(0x046d, 0x08a9)},
+       {USB_DEVICE(0x046d, 0x08aa)},
+       {USB_DEVICE(0x046d, 0x08ac)},
+       {USB_DEVICE(0x046d, 0x08ad)},
+       {USB_DEVICE(0x046d, 0x08ae)},
+       {USB_DEVICE(0x046d, 0x08af)},
+       {USB_DEVICE(0x046d, 0x08b9)},
+       {USB_DEVICE(0x046d, 0x08d7)},
+       {USB_DEVICE(0x046d, 0x08d8)},
+       {USB_DEVICE(0x046d, 0x08d9)},
+       {USB_DEVICE(0x046d, 0x08da)},
+       {USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB},
+       {USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106},
+       {USB_DEVICE(0x0471, 0x0326), .driver_info = SENSOR_PAS106},
+       {USB_DEVICE(0x0471, 0x032d), .driver_info = SENSOR_PAS106},
+       {USB_DEVICE(0x0471, 0x032e), .driver_info = SENSOR_PAS106},
+       {USB_DEVICE(0x055f, 0xc005)},
+       {USB_DEVICE(0x055f, 0xd003)},
+       {USB_DEVICE(0x055f, 0xd004)},
+       {USB_DEVICE(0x0698, 0x2003)},
+       {USB_DEVICE(0x0ac8, 0x0301), .driver_info = SENSOR_PAS106},
+       {USB_DEVICE(0x0ac8, 0x0302), .driver_info = SENSOR_PAS106},
+       {USB_DEVICE(0x0ac8, 0x301b)},
+       {USB_DEVICE(0x0ac8, 0x303b)},
+       {USB_DEVICE(0x0ac8, 0x305b)},
+       {USB_DEVICE(0x0ac8, 0x307b)},
+       {USB_DEVICE(0x10fd, 0x0128)},
+       {USB_DEVICE(0x10fd, 0x804d)},
+       {USB_DEVICE(0x10fd, 0x8050)},
+       {}                      /* end of entry */
+};
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* -- device connect -- */
+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);
+}
+
+/* USB driver */
+static struct usb_driver sd_driver = {
+       .name = KBUILD_MODNAME,
+       .id_table = device_table,
+       .probe = sd_probe,
+       .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+       .reset_resume = gspca_resume,
+#endif
+};
+
+module_usb_driver(sd_driver);
+
+module_param(force_sensor, int, 0644);
+MODULE_PARM_DESC(force_sensor,
+       "Force sensor. Only for experts!!!");
diff --git a/drivers/media/usb/hdpvr/Kconfig b/drivers/media/usb/hdpvr/Kconfig
new file mode 100644 (file)
index 0000000..de247f3
--- /dev/null
@@ -0,0 +1,10 @@
+
+config VIDEO_HDPVR
+       tristate "Hauppauge HD PVR support"
+       depends on VIDEO_DEV
+       ---help---
+         This is a video4linux driver for Hauppauge's HD PVR USB device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called hdpvr
+
diff --git a/drivers/media/usb/hdpvr/Makefile b/drivers/media/usb/hdpvr/Makefile
new file mode 100644 (file)
index 0000000..52f057f
--- /dev/null
@@ -0,0 +1,7 @@
+hdpvr-objs     := hdpvr-control.o hdpvr-core.o hdpvr-video.o hdpvr-i2c.o
+
+obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o
+
+ccflags-y += -Idrivers/media/video
+
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/usb/hdpvr/hdpvr-control.c b/drivers/media/usb/hdpvr/hdpvr-control.c
new file mode 100644 (file)
index 0000000..ae8f229
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Hauppauge HD PVR USB driver - video 4 linux 2 interface
+ *
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/mutex.h>
+
+#include <linux/videodev2.h>
+
+#include <media/v4l2-common.h>
+
+#include "hdpvr.h"
+
+
+int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf)
+{
+       int ret;
+       char request_type = 0x38, snd_request = 0x01;
+
+       mutex_lock(&dev->usbc_mutex);
+       dev->usbc_buf[0] = valbuf;
+       ret = usb_control_msg(dev->udev,
+                             usb_sndctrlpipe(dev->udev, 0),
+                             snd_request, 0x00 | request_type,
+                             value, CTRL_DEFAULT_INDEX,
+                             dev->usbc_buf, 1, 10000);
+
+       mutex_unlock(&dev->usbc_mutex);
+       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                "config call request for value 0x%x returned %d\n", value,
+                ret);
+
+       return ret < 0 ? ret : 0;
+}
+
+struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev)
+{
+       struct hdpvr_video_info *vidinf = NULL;
+#ifdef HDPVR_DEBUG
+       char print_buf[15];
+#endif
+       int ret;
+
+       vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL);
+       if (!vidinf) {
+               v4l2_err(&dev->v4l2_dev, "out of memory\n");
+               goto err;
+       }
+
+       mutex_lock(&dev->usbc_mutex);
+       ret = usb_control_msg(dev->udev,
+                             usb_rcvctrlpipe(dev->udev, 0),
+                             0x81, 0x80 | 0x38,
+                             0x1400, 0x0003,
+                             dev->usbc_buf, 5,
+                             1000);
+       if (ret == 5) {
+               vidinf->width   = dev->usbc_buf[1] << 8 | dev->usbc_buf[0];
+               vidinf->height  = dev->usbc_buf[3] << 8 | dev->usbc_buf[2];
+               vidinf->fps     = dev->usbc_buf[4];
+       }
+
+#ifdef HDPVR_DEBUG
+       if (hdpvr_debug & MSG_INFO) {
+               hex_dump_to_buffer(dev->usbc_buf, 5, 16, 1, print_buf,
+                                  sizeof(print_buf), 0);
+               v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                        "get video info returned: %d, %s\n", ret, print_buf);
+       }
+#endif
+       mutex_unlock(&dev->usbc_mutex);
+
+       if (!vidinf->width || !vidinf->height || !vidinf->fps) {
+               kfree(vidinf);
+               vidinf = NULL;
+       }
+err:
+       return vidinf;
+}
+
+int get_input_lines_info(struct hdpvr_device *dev)
+{
+#ifdef HDPVR_DEBUG
+       char print_buf[9];
+#endif
+       int ret, lines;
+
+       mutex_lock(&dev->usbc_mutex);
+       ret = usb_control_msg(dev->udev,
+                             usb_rcvctrlpipe(dev->udev, 0),
+                             0x81, 0x80 | 0x38,
+                             0x1800, 0x0003,
+                             dev->usbc_buf, 3,
+                             1000);
+
+#ifdef HDPVR_DEBUG
+       if (hdpvr_debug & MSG_INFO) {
+               hex_dump_to_buffer(dev->usbc_buf, 3, 16, 1, print_buf,
+                                  sizeof(print_buf), 0);
+               v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                        "get input lines info returned: %d, %s\n", ret,
+                        print_buf);
+       }
+#else
+       (void)ret;      /* suppress compiler warning */
+#endif
+       lines = dev->usbc_buf[1] << 8 | dev->usbc_buf[0];
+       mutex_unlock(&dev->usbc_mutex);
+       return lines;
+}
+
+
+int hdpvr_set_bitrate(struct hdpvr_device *dev)
+{
+       int ret;
+
+       mutex_lock(&dev->usbc_mutex);
+       memset(dev->usbc_buf, 0, 4);
+       dev->usbc_buf[0] = dev->options.bitrate;
+       dev->usbc_buf[2] = dev->options.peak_bitrate;
+
+       ret = usb_control_msg(dev->udev,
+                             usb_sndctrlpipe(dev->udev, 0),
+                             0x01, 0x38, CTRL_BITRATE_VALUE,
+                             CTRL_DEFAULT_INDEX, dev->usbc_buf, 4, 1000);
+       mutex_unlock(&dev->usbc_mutex);
+
+       return ret;
+}
+
+int hdpvr_set_audio(struct hdpvr_device *dev, u8 input,
+                   enum v4l2_mpeg_audio_encoding codec)
+{
+       int ret = 0;
+
+       if (dev->flags & HDPVR_FLAG_AC3_CAP) {
+               mutex_lock(&dev->usbc_mutex);
+               memset(dev->usbc_buf, 0, 2);
+               dev->usbc_buf[0] = input;
+               if (codec == V4L2_MPEG_AUDIO_ENCODING_AAC)
+                       dev->usbc_buf[1] = 0;
+               else if (codec == V4L2_MPEG_AUDIO_ENCODING_AC3)
+                       dev->usbc_buf[1] = 1;
+               else {
+                       mutex_unlock(&dev->usbc_mutex);
+                       v4l2_err(&dev->v4l2_dev, "invalid audio codec %d\n",
+                                codec);
+                       ret = -EINVAL;
+                       goto error;
+               }
+
+               ret = usb_control_msg(dev->udev,
+                                     usb_sndctrlpipe(dev->udev, 0),
+                                     0x01, 0x38, CTRL_AUDIO_INPUT_VALUE,
+                                     CTRL_DEFAULT_INDEX, dev->usbc_buf, 2,
+                                     1000);
+               mutex_unlock(&dev->usbc_mutex);
+               if (ret == 2)
+                       ret = 0;
+       } else
+               ret = hdpvr_config_call(dev, CTRL_AUDIO_INPUT_VALUE, input);
+error:
+       return ret;
+}
+
+int hdpvr_set_options(struct hdpvr_device *dev)
+{
+       hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, dev->options.video_std);
+
+       hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE,
+                        dev->options.video_input+1);
+
+       hdpvr_set_audio(dev, dev->options.audio_input+1,
+                      dev->options.audio_codec);
+
+       hdpvr_set_bitrate(dev);
+       hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE,
+                        dev->options.bitrate_mode);
+       hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, dev->options.gop_mode);
+
+       hdpvr_config_call(dev, CTRL_BRIGHTNESS, dev->options.brightness);
+       hdpvr_config_call(dev, CTRL_CONTRAST,   dev->options.contrast);
+       hdpvr_config_call(dev, CTRL_HUE,        dev->options.hue);
+       hdpvr_config_call(dev, CTRL_SATURATION, dev->options.saturation);
+       hdpvr_config_call(dev, CTRL_SHARPNESS,  dev->options.sharpness);
+
+       return 0;
+}
diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c
new file mode 100644 (file)
index 0000000..304f43e
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * Hauppauge HD PVR USB driver
+ *
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ * Copyright (C) 2008      John Poet
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/atomic.h>
+#include <linux/usb.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-common.h>
+
+#include "hdpvr.h"
+
+static int video_nr[HDPVR_MAX] = {[0 ... (HDPVR_MAX - 1)] = UNSET};
+module_param_array(video_nr, int, NULL, 0);
+MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)");
+
+/* holds the number of currently registered devices */
+static atomic_t dev_nr = ATOMIC_INIT(-1);
+
+int hdpvr_debug;
+module_param(hdpvr_debug, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(hdpvr_debug, "enable debugging output");
+
+static uint default_video_input = HDPVR_VIDEO_INPUTS;
+module_param(default_video_input, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / "
+                "1=S-Video / 2=Composite");
+
+static uint default_audio_input = HDPVR_AUDIO_INPUTS;
+module_param(default_audio_input, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / "
+                "1=RCA front / 2=S/PDIF");
+
+static bool boost_audio;
+module_param(boost_audio, bool, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(boost_audio, "boost the audio signal");
+
+
+/* table of devices that work with this driver */
+static struct usb_device_id hdpvr_table[] = {
+       { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID) },
+       { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID1) },
+       { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID2) },
+       { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID3) },
+       { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID4) },
+       { }                                     /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, hdpvr_table);
+
+
+void hdpvr_delete(struct hdpvr_device *dev)
+{
+       hdpvr_free_buffers(dev);
+
+       if (dev->video_dev)
+               video_device_release(dev->video_dev);
+
+       usb_put_dev(dev->udev);
+}
+
+static void challenge(u8 *bytes)
+{
+       u64 *i64P, tmp64;
+       uint i, idx;
+
+       for (idx = 0; idx < 32; ++idx) {
+
+               if (idx & 0x3)
+                       bytes[(idx >> 3) + 3] = bytes[(idx >> 2) & 0x3];
+
+               switch (idx & 0x3) {
+               case 0x3:
+                       bytes[2] += bytes[3] * 4 + bytes[4] + bytes[5];
+                       bytes[4] += bytes[(idx & 0x1) * 2] * 9 + 9;
+                       break;
+               case 0x1:
+                       bytes[0] *= 8;
+                       bytes[0] += 7*idx + 4;
+                       bytes[6] += bytes[3] * 3;
+                       break;
+               case 0x0:
+                       bytes[3 - (idx >> 3)] = bytes[idx >> 2];
+                       bytes[5] += bytes[6] * 3;
+                       for (i = 0; i < 3; i++)
+                               bytes[3] *= bytes[3] + 1;
+                       break;
+               case 0x2:
+                       for (i = 0; i < 3; i++)
+                               bytes[1] *= bytes[6] + 1;
+                       for (i = 0; i < 3; i++) {
+                               i64P = (u64 *)bytes;
+                               tmp64 = le64_to_cpup(i64P);
+                               tmp64 <<= bytes[7] & 0x0f;
+                               *i64P += cpu_to_le64(tmp64);
+                       }
+                       break;
+               }
+       }
+}
+
+/* try to init the device like the windows driver */
+static int device_authorization(struct hdpvr_device *dev)
+{
+
+       int ret, retval = -ENOMEM;
+       char request_type = 0x38, rcv_request = 0x81;
+       char *response;
+#ifdef HDPVR_DEBUG
+       size_t buf_size = 46;
+       char *print_buf = kzalloc(5*buf_size+1, GFP_KERNEL);
+       if (!print_buf) {
+               v4l2_err(&dev->v4l2_dev, "Out of memory\n");
+               return retval;
+       }
+#endif
+
+       mutex_lock(&dev->usbc_mutex);
+       ret = usb_control_msg(dev->udev,
+                             usb_rcvctrlpipe(dev->udev, 0),
+                             rcv_request, 0x80 | request_type,
+                             0x0400, 0x0003,
+                             dev->usbc_buf, 46,
+                             10000);
+       if (ret != 46) {
+               v4l2_err(&dev->v4l2_dev,
+                        "unexpected answer of status request, len %d\n", ret);
+               goto unlock;
+       }
+#ifdef HDPVR_DEBUG
+       else {
+               hex_dump_to_buffer(dev->usbc_buf, 46, 16, 1, print_buf,
+                                  5*buf_size+1, 0);
+               v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                        "Status request returned, len %d: %s\n",
+                        ret, print_buf);
+       }
+#endif
+
+       dev->fw_ver = dev->usbc_buf[1];
+
+       v4l2_info(&dev->v4l2_dev, "firmware version 0x%x dated %s\n",
+                         dev->fw_ver, &dev->usbc_buf[2]);
+
+       if (dev->fw_ver > 0x15) {
+               dev->options.brightness = 0x80;
+               dev->options.contrast   = 0x40;
+               dev->options.hue        = 0xf;
+               dev->options.saturation = 0x40;
+               dev->options.sharpness  = 0x80;
+       }
+
+       switch (dev->fw_ver) {
+       case HDPVR_FIRMWARE_VERSION:
+               dev->flags &= ~HDPVR_FLAG_AC3_CAP;
+               break;
+       case HDPVR_FIRMWARE_VERSION_AC3:
+       case HDPVR_FIRMWARE_VERSION_0X12:
+       case HDPVR_FIRMWARE_VERSION_0X15:
+               dev->flags |= HDPVR_FLAG_AC3_CAP;
+               break;
+       default:
+               v4l2_info(&dev->v4l2_dev, "untested firmware, the driver might"
+                         " not work.\n");
+               if (dev->fw_ver >= HDPVR_FIRMWARE_VERSION_AC3)
+                       dev->flags |= HDPVR_FLAG_AC3_CAP;
+               else
+                       dev->flags &= ~HDPVR_FLAG_AC3_CAP;
+       }
+
+       response = dev->usbc_buf+38;
+#ifdef HDPVR_DEBUG
+       hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0);
+       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "challenge: %s\n",
+                print_buf);
+#endif
+       challenge(response);
+#ifdef HDPVR_DEBUG
+       hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0);
+       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %s\n",
+                print_buf);
+#endif
+
+       msleep(100);
+       ret = usb_control_msg(dev->udev,
+                             usb_sndctrlpipe(dev->udev, 0),
+                             0xd1, 0x00 | request_type,
+                             0x0000, 0x0000,
+                             response, 8,
+                             10000);
+       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                "magic request returned %d\n", ret);
+
+       retval = ret != 8;
+unlock:
+       mutex_unlock(&dev->usbc_mutex);
+       return retval;
+}
+
+static int hdpvr_device_init(struct hdpvr_device *dev)
+{
+       int ret;
+       u8 *buf;
+       struct hdpvr_video_info *vidinf;
+
+       if (device_authorization(dev))
+               return -EACCES;
+
+       /* default options for init */
+       hdpvr_set_options(dev);
+
+       /* set filter options */
+       mutex_lock(&dev->usbc_mutex);
+       buf = dev->usbc_buf;
+       buf[0] = 0x03; buf[1] = 0x03; buf[2] = 0x00; buf[3] = 0x00;
+       ret = usb_control_msg(dev->udev,
+                             usb_sndctrlpipe(dev->udev, 0),
+                             0x01, 0x38,
+                             CTRL_LOW_PASS_FILTER_VALUE, CTRL_DEFAULT_INDEX,
+                             buf, 4,
+                             1000);
+       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                "control request returned %d\n", ret);
+       mutex_unlock(&dev->usbc_mutex);
+
+       vidinf = get_video_info(dev);
+       if (!vidinf)
+               v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                       "no valid video signal or device init failed\n");
+       else
+               kfree(vidinf);
+
+       /* enable fan and bling leds */
+       mutex_lock(&dev->usbc_mutex);
+       buf[0] = 0x1;
+       ret = usb_control_msg(dev->udev,
+                             usb_sndctrlpipe(dev->udev, 0),
+                             0xd4, 0x38, 0, 0, buf, 1,
+                             1000);
+       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                "control request returned %d\n", ret);
+
+       /* boost analog audio */
+       buf[0] = boost_audio;
+       ret = usb_control_msg(dev->udev,
+                             usb_sndctrlpipe(dev->udev, 0),
+                             0xd5, 0x38, 0, 0, buf, 1,
+                             1000);
+       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                "control request returned %d\n", ret);
+       mutex_unlock(&dev->usbc_mutex);
+
+       dev->status = STATUS_IDLE;
+       return 0;
+}
+
+static const struct hdpvr_options hdpvr_default_options = {
+       .video_std      = HDPVR_60HZ,
+       .video_input    = HDPVR_COMPONENT,
+       .audio_input    = HDPVR_RCA_BACK,
+       .bitrate        = 65, /* 6 mbps */
+       .peak_bitrate   = 90, /* 9 mbps */
+       .bitrate_mode   = HDPVR_CONSTANT,
+       .gop_mode       = HDPVR_SIMPLE_IDR_GOP,
+       .audio_codec    = V4L2_MPEG_AUDIO_ENCODING_AAC,
+       /* original picture controls for firmware version <= 0x15 */
+       /* updated in device_authorization() for newer firmware */
+       .brightness     = 0x86,
+       .contrast       = 0x80,
+       .hue            = 0x80,
+       .saturation     = 0x80,
+       .sharpness      = 0x80,
+};
+
+static int hdpvr_probe(struct usb_interface *interface,
+                      const struct usb_device_id *id)
+{
+       struct hdpvr_device *dev;
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       struct i2c_client *client;
+       size_t buffer_size;
+       int i;
+       int retval = -ENOMEM;
+
+       /* allocate memory for our device state and initialize it */
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev) {
+               dev_err(&interface->dev, "Out of memory\n");
+               goto error;
+       }
+
+       dev->workqueue = 0;
+
+       /* register v4l2_device early so it can be used for printks */
+       if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) {
+               dev_err(&interface->dev, "v4l2_device_register failed\n");
+               goto error;
+       }
+
+       mutex_init(&dev->io_mutex);
+       mutex_init(&dev->i2c_mutex);
+       mutex_init(&dev->usbc_mutex);
+       dev->usbc_buf = kmalloc(64, GFP_KERNEL);
+       if (!dev->usbc_buf) {
+               v4l2_err(&dev->v4l2_dev, "Out of memory\n");
+               goto error;
+       }
+
+       init_waitqueue_head(&dev->wait_buffer);
+       init_waitqueue_head(&dev->wait_data);
+
+       dev->workqueue = create_singlethread_workqueue("hdpvr_buffer");
+       if (!dev->workqueue)
+               goto error;
+
+       /* init video transfer queues */
+       INIT_LIST_HEAD(&dev->free_buff_list);
+       INIT_LIST_HEAD(&dev->rec_buff_list);
+
+       dev->options = hdpvr_default_options;
+
+       if (default_video_input < HDPVR_VIDEO_INPUTS)
+               dev->options.video_input = default_video_input;
+
+       if (default_audio_input < HDPVR_AUDIO_INPUTS) {
+               dev->options.audio_input = default_audio_input;
+               if (default_audio_input == HDPVR_SPDIF)
+                       dev->options.audio_codec =
+                               V4L2_MPEG_AUDIO_ENCODING_AC3;
+       }
+
+       dev->udev = usb_get_dev(interface_to_usbdev(interface));
+
+       /* set up the endpoint information */
+       /* use only the first bulk-in and bulk-out endpoints */
+       iface_desc = interface->cur_altsetting;
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               endpoint = &iface_desc->endpoint[i].desc;
+
+               if (!dev->bulk_in_endpointAddr &&
+                   usb_endpoint_is_bulk_in(endpoint)) {
+                       /* USB interface description is buggy, reported max
+                        * packet size is 512 bytes, windows driver uses 8192 */
+                       buffer_size = 8192;
+                       dev->bulk_in_size = buffer_size;
+                       dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
+               }
+
+       }
+       if (!dev->bulk_in_endpointAddr) {
+               v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n");
+               goto error;
+       }
+
+       /* init the device */
+       if (hdpvr_device_init(dev)) {
+               v4l2_err(&dev->v4l2_dev, "device init failed\n");
+               goto error;
+       }
+
+       mutex_lock(&dev->io_mutex);
+       if (hdpvr_alloc_buffers(dev, NUM_BUFFERS)) {
+               mutex_unlock(&dev->io_mutex);
+               v4l2_err(&dev->v4l2_dev,
+                        "allocating transfer buffers failed\n");
+               goto error;
+       }
+       mutex_unlock(&dev->io_mutex);
+
+       if (hdpvr_register_videodev(dev, &interface->dev,
+                                   video_nr[atomic_inc_return(&dev_nr)])) {
+               v4l2_err(&dev->v4l2_dev, "registering videodev failed\n");
+               goto error;
+       }
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       retval = hdpvr_register_i2c_adapter(dev);
+       if (retval < 0) {
+               v4l2_err(&dev->v4l2_dev, "i2c adapter register failed\n");
+               goto error;
+       }
+
+       client = hdpvr_register_ir_rx_i2c(dev);
+       if (!client) {
+               v4l2_err(&dev->v4l2_dev, "i2c IR RX device register failed\n");
+               goto reg_fail;
+       }
+
+       client = hdpvr_register_ir_tx_i2c(dev);
+       if (!client) {
+               v4l2_err(&dev->v4l2_dev, "i2c IR TX device register failed\n");
+               goto reg_fail;
+       }
+#endif
+
+       /* let the user know what node this device is now attached to */
+       v4l2_info(&dev->v4l2_dev, "device now attached to %s\n",
+                 video_device_node_name(dev->video_dev));
+       return 0;
+
+reg_fail:
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_adapter(&dev->i2c_adapter);
+#endif
+error:
+       if (dev) {
+               /* Destroy single thread */
+               if (dev->workqueue)
+                       destroy_workqueue(dev->workqueue);
+               /* this frees allocated memory */
+               hdpvr_delete(dev);
+       }
+       return retval;
+}
+
+static void hdpvr_disconnect(struct usb_interface *interface)
+{
+       struct hdpvr_device *dev = to_hdpvr_dev(usb_get_intfdata(interface));
+
+       v4l2_info(&dev->v4l2_dev, "device %s disconnected\n",
+                 video_device_node_name(dev->video_dev));
+       /* prevent more I/O from starting and stop any ongoing */
+       mutex_lock(&dev->io_mutex);
+       dev->status = STATUS_DISCONNECTED;
+       wake_up_interruptible(&dev->wait_data);
+       wake_up_interruptible(&dev->wait_buffer);
+       mutex_unlock(&dev->io_mutex);
+       v4l2_device_disconnect(&dev->v4l2_dev);
+       msleep(100);
+       flush_workqueue(dev->workqueue);
+       mutex_lock(&dev->io_mutex);
+       hdpvr_cancel_queue(dev);
+       mutex_unlock(&dev->io_mutex);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+       i2c_del_adapter(&dev->i2c_adapter);
+#endif
+       video_unregister_device(dev->video_dev);
+       atomic_dec(&dev_nr);
+}
+
+
+static struct usb_driver hdpvr_usb_driver = {
+       .name =         "hdpvr",
+       .probe =        hdpvr_probe,
+       .disconnect =   hdpvr_disconnect,
+       .id_table =     hdpvr_table,
+};
+
+module_usb_driver(hdpvr_usb_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.2.1");
+MODULE_AUTHOR("Janne Grunau");
+MODULE_DESCRIPTION("Hauppauge HD PVR driver");
diff --git a/drivers/media/usb/hdpvr/hdpvr-i2c.c b/drivers/media/usb/hdpvr/hdpvr-i2c.c
new file mode 100644 (file)
index 0000000..82e819f
--- /dev/null
@@ -0,0 +1,231 @@
+
+/*
+ * Hauppauge HD PVR USB driver
+ *
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ *
+ * IR device registration code is
+ * Copyright (C) 2010  Andy Walls <awalls@md.metrocast.net>
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation, version 2.
+ *
+ */
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+
+#include "hdpvr.h"
+
+#define CTRL_READ_REQUEST      0xb8
+#define CTRL_WRITE_REQUEST     0x38
+
+#define REQTYPE_I2C_READ       0xb1
+#define REQTYPE_I2C_WRITE      0xb0
+#define REQTYPE_I2C_WRITE_STATT        0xd0
+
+#define Z8F0811_IR_TX_I2C_ADDR 0x70
+#define Z8F0811_IR_RX_I2C_ADDR 0x71
+
+
+struct i2c_client *hdpvr_register_ir_tx_i2c(struct hdpvr_device *dev)
+{
+       struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data;
+       struct i2c_board_info hdpvr_ir_tx_i2c_board_info = {
+               I2C_BOARD_INFO("ir_tx_z8f0811_hdpvr", Z8F0811_IR_TX_I2C_ADDR),
+       };
+
+       init_data->name = "HD-PVR";
+       hdpvr_ir_tx_i2c_board_info.platform_data = init_data;
+
+       return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_tx_i2c_board_info);
+}
+
+struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev)
+{
+       struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data;
+       struct i2c_board_info hdpvr_ir_rx_i2c_board_info = {
+               I2C_BOARD_INFO("ir_rx_z8f0811_hdpvr", Z8F0811_IR_RX_I2C_ADDR),
+       };
+
+       /* Our default information for ir-kbd-i2c.c to use */
+       init_data->ir_codes = RC_MAP_HAUPPAUGE;
+       init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
+       init_data->type = RC_TYPE_RC5;
+       init_data->name = "HD-PVR";
+       init_data->polling_interval = 405; /* ms, duplicated from Windows */
+       hdpvr_ir_rx_i2c_board_info.platform_data = init_data;
+
+       return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_rx_i2c_board_info);
+}
+
+static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus,
+                         unsigned char addr, char *wdata, int wlen,
+                         char *data, int len)
+{
+       int ret;
+
+       if ((len > sizeof(dev->i2c_buf)) || (wlen > sizeof(dev->i2c_buf)))
+               return -EINVAL;
+
+       if (wlen) {
+               memcpy(&dev->i2c_buf, wdata, wlen);
+               ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+                                     REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
+                                     (bus << 8) | addr, 0, &dev->i2c_buf,
+                                     wlen, 1000);
+               if (ret < 0)
+                       return ret;
+       }
+
+       ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+                             REQTYPE_I2C_READ, CTRL_READ_REQUEST,
+                             (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
+
+       if (ret == len) {
+               memcpy(data, &dev->i2c_buf, len);
+               ret = 0;
+       } else if (ret >= 0)
+               ret = -EIO;
+
+       return ret;
+}
+
+static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus,
+                          unsigned char addr, char *data, int len)
+{
+       int ret;
+
+       if (len > sizeof(dev->i2c_buf))
+               return -EINVAL;
+
+       memcpy(&dev->i2c_buf, data, len);
+       ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+                             REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
+                             (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
+
+       if (ret < 0)
+               return ret;
+
+       ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+                             REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST,
+                             0, 0, &dev->i2c_buf, 2, 1000);
+
+       if ((ret == 2) && (dev->i2c_buf[1] == (len - 1)))
+               ret = 0;
+       else if (ret >= 0)
+               ret = -EIO;
+
+       return ret;
+}
+
+static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs,
+                         int num)
+{
+       struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter);
+       int retval = 0, addr;
+
+       if (num <= 0)
+               return 0;
+
+       mutex_lock(&dev->i2c_mutex);
+
+       addr = msgs[0].addr << 1;
+
+       if (num == 1) {
+               if (msgs[0].flags & I2C_M_RD)
+                       retval = hdpvr_i2c_read(dev, 1, addr, NULL, 0,
+                                               msgs[0].buf, msgs[0].len);
+               else
+                       retval = hdpvr_i2c_write(dev, 1, addr, msgs[0].buf,
+                                                msgs[0].len);
+       } else if (num == 2) {
+               if (msgs[0].addr != msgs[1].addr) {
+                       v4l2_warn(&dev->v4l2_dev, "refusing 2-phase i2c xfer "
+                                 "with conflicting target addresses\n");
+                       retval = -EINVAL;
+                       goto out;
+               }
+
+               if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD)) {
+                       v4l2_warn(&dev->v4l2_dev, "refusing complex xfer with "
+                                 "r0=%d, r1=%d\n", msgs[0].flags & I2C_M_RD,
+                                 msgs[1].flags & I2C_M_RD);
+                       retval = -EINVAL;
+                       goto out;
+               }
+
+               /*
+                * Write followed by atomic read is the only complex xfer that
+                * we actually support here.
+                */
+               retval = hdpvr_i2c_read(dev, 1, addr, msgs[0].buf, msgs[0].len,
+                                       msgs[1].buf, msgs[1].len);
+       } else {
+               v4l2_warn(&dev->v4l2_dev, "refusing %d-phase i2c xfer\n", num);
+       }
+
+out:
+       mutex_unlock(&dev->i2c_mutex);
+
+       return retval ? retval : num;
+}
+
+static u32 hdpvr_functionality(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm hdpvr_algo = {
+       .master_xfer   = hdpvr_transfer,
+       .functionality = hdpvr_functionality,
+};
+
+static struct i2c_adapter hdpvr_i2c_adapter_template = {
+       .name   = "Hauppage HD PVR I2C",
+       .owner  = THIS_MODULE,
+       .algo   = &hdpvr_algo,
+};
+
+static int hdpvr_activate_ir(struct hdpvr_device *dev)
+{
+       char buffer[2];
+
+       mutex_lock(&dev->i2c_mutex);
+
+       hdpvr_i2c_read(dev, 0, 0x54, NULL, 0, buffer, 1);
+
+       buffer[0] = 0;
+       buffer[1] = 0x8;
+       hdpvr_i2c_write(dev, 1, 0x54, buffer, 2);
+
+       buffer[1] = 0x18;
+       hdpvr_i2c_write(dev, 1, 0x54, buffer, 2);
+
+       mutex_unlock(&dev->i2c_mutex);
+
+       return 0;
+}
+
+int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
+{
+       int retval = -ENOMEM;
+
+       hdpvr_activate_ir(dev);
+
+       memcpy(&dev->i2c_adapter, &hdpvr_i2c_adapter_template,
+              sizeof(struct i2c_adapter));
+       dev->i2c_adapter.dev.parent = &dev->udev->dev;
+
+       i2c_set_adapdata(&dev->i2c_adapter, dev);
+
+       retval = i2c_add_adapter(&dev->i2c_adapter);
+
+       return retval;
+}
+
+#endif
diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c
new file mode 100644 (file)
index 0000000..0e9e156
--- /dev/null
@@ -0,0 +1,1289 @@
+/*
+ * Hauppauge HD PVR USB driver - video 4 linux 2 interface
+ *
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include "hdpvr.h"
+
+#define BULK_URB_TIMEOUT   90 /* 0.09 seconds */
+
+#define print_buffer_status() { \
+               v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,       \
+                        "%s:%d buffer stat: %d free, %d proc\n",       \
+                        __func__, __LINE__,                            \
+                        list_size(&dev->free_buff_list),               \
+                        list_size(&dev->rec_buff_list)); }
+
+struct hdpvr_fh {
+       struct hdpvr_device     *dev;
+};
+
+static uint list_size(struct list_head *list)
+{
+       struct list_head *tmp;
+       uint count = 0;
+
+       list_for_each(tmp, list) {
+               count++;
+       }
+
+       return count;
+}
+
+/*=========================================================================*/
+/* urb callback */
+static void hdpvr_read_bulk_callback(struct urb *urb)
+{
+       struct hdpvr_buffer *buf = (struct hdpvr_buffer *)urb->context;
+       struct hdpvr_device *dev = buf->dev;
+
+       /* marking buffer as received and wake waiting */
+       buf->status = BUFSTAT_READY;
+       wake_up_interruptible(&dev->wait_data);
+}
+
+/*=========================================================================*/
+/* bufffer bits */
+
+/* function expects dev->io_mutex to be hold by caller */
+int hdpvr_cancel_queue(struct hdpvr_device *dev)
+{
+       struct hdpvr_buffer *buf;
+
+       list_for_each_entry(buf, &dev->rec_buff_list, buff_list) {
+               usb_kill_urb(buf->urb);
+               buf->status = BUFSTAT_AVAILABLE;
+       }
+
+       list_splice_init(&dev->rec_buff_list, dev->free_buff_list.prev);
+
+       return 0;
+}
+
+static int hdpvr_free_queue(struct list_head *q)
+{
+       struct list_head *tmp;
+       struct list_head *p;
+       struct hdpvr_buffer *buf;
+       struct urb *urb;
+
+       for (p = q->next; p != q;) {
+               buf = list_entry(p, struct hdpvr_buffer, buff_list);
+
+               urb = buf->urb;
+               usb_free_coherent(urb->dev, urb->transfer_buffer_length,
+                                 urb->transfer_buffer, urb->transfer_dma);
+               usb_free_urb(urb);
+               tmp = p->next;
+               list_del(p);
+               kfree(buf);
+               p = tmp;
+       }
+
+       return 0;
+}
+
+/* function expects dev->io_mutex to be hold by caller */
+int hdpvr_free_buffers(struct hdpvr_device *dev)
+{
+       hdpvr_cancel_queue(dev);
+
+       hdpvr_free_queue(&dev->free_buff_list);
+       hdpvr_free_queue(&dev->rec_buff_list);
+
+       return 0;
+}
+
+/* function expects dev->io_mutex to be hold by caller */
+int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count)
+{
+       uint i;
+       int retval = -ENOMEM;
+       u8 *mem;
+       struct hdpvr_buffer *buf;
+       struct urb *urb;
+
+       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                "allocating %u buffers\n", count);
+
+       for (i = 0; i < count; i++) {
+
+               buf = kzalloc(sizeof(struct hdpvr_buffer), GFP_KERNEL);
+               if (!buf) {
+                       v4l2_err(&dev->v4l2_dev, "cannot allocate buffer\n");
+                       goto exit;
+               }
+               buf->dev = dev;
+
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!urb) {
+                       v4l2_err(&dev->v4l2_dev, "cannot allocate urb\n");
+                       goto exit_urb;
+               }
+               buf->urb = urb;
+
+               mem = usb_alloc_coherent(dev->udev, dev->bulk_in_size, GFP_KERNEL,
+                                        &urb->transfer_dma);
+               if (!mem) {
+                       v4l2_err(&dev->v4l2_dev,
+                                "cannot allocate usb transfer buffer\n");
+                       goto exit_urb_buffer;
+               }
+
+               usb_fill_bulk_urb(buf->urb, dev->udev,
+                                 usb_rcvbulkpipe(dev->udev,
+                                                 dev->bulk_in_endpointAddr),
+                                 mem, dev->bulk_in_size,
+                                 hdpvr_read_bulk_callback, buf);
+
+               buf->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+               buf->status = BUFSTAT_AVAILABLE;
+               list_add_tail(&buf->buff_list, &dev->free_buff_list);
+       }
+       return 0;
+exit_urb_buffer:
+       usb_free_urb(urb);
+exit_urb:
+       kfree(buf);
+exit:
+       hdpvr_free_buffers(dev);
+       return retval;
+}
+
+static int hdpvr_submit_buffers(struct hdpvr_device *dev)
+{
+       struct hdpvr_buffer *buf;
+       struct urb *urb;
+       int ret = 0, err_count = 0;
+
+       mutex_lock(&dev->io_mutex);
+
+       while (dev->status == STATUS_STREAMING &&
+              !list_empty(&dev->free_buff_list)) {
+
+               buf = list_entry(dev->free_buff_list.next, struct hdpvr_buffer,
+                                buff_list);
+               if (buf->status != BUFSTAT_AVAILABLE) {
+                       v4l2_err(&dev->v4l2_dev,
+                                "buffer not marked as available\n");
+                       ret = -EFAULT;
+                       goto err;
+               }
+
+               urb = buf->urb;
+               urb->status = 0;
+               urb->actual_length = 0;
+               ret = usb_submit_urb(urb, GFP_KERNEL);
+               if (ret) {
+                       v4l2_err(&dev->v4l2_dev,
+                                "usb_submit_urb in %s returned %d\n",
+                                __func__, ret);
+                       if (++err_count > 2)
+                               break;
+                       continue;
+               }
+               buf->status = BUFSTAT_INPROGRESS;
+               list_move_tail(&buf->buff_list, &dev->rec_buff_list);
+       }
+err:
+       print_buffer_status();
+       mutex_unlock(&dev->io_mutex);
+       return ret;
+}
+
+static struct hdpvr_buffer *hdpvr_get_next_buffer(struct hdpvr_device *dev)
+{
+       struct hdpvr_buffer *buf;
+
+       mutex_lock(&dev->io_mutex);
+
+       if (list_empty(&dev->rec_buff_list)) {
+               mutex_unlock(&dev->io_mutex);
+               return NULL;
+       }
+
+       buf = list_entry(dev->rec_buff_list.next, struct hdpvr_buffer,
+                        buff_list);
+       mutex_unlock(&dev->io_mutex);
+
+       return buf;
+}
+
+static void hdpvr_transmit_buffers(struct work_struct *work)
+{
+       struct hdpvr_device *dev = container_of(work, struct hdpvr_device,
+                                               worker);
+
+       while (dev->status == STATUS_STREAMING) {
+
+               if (hdpvr_submit_buffers(dev)) {
+                       v4l2_err(&dev->v4l2_dev, "couldn't submit buffers\n");
+                       goto error;
+               }
+               if (wait_event_interruptible(dev->wait_buffer,
+                               !list_empty(&dev->free_buff_list) ||
+                                            dev->status != STATUS_STREAMING))
+                       goto error;
+       }
+
+       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                "transmit worker exited\n");
+       return;
+error:
+       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                "transmit buffers errored\n");
+       dev->status = STATUS_ERROR;
+}
+
+/* function expects dev->io_mutex to be hold by caller */
+static int hdpvr_start_streaming(struct hdpvr_device *dev)
+{
+       int ret;
+       struct hdpvr_video_info *vidinf;
+
+       if (dev->status == STATUS_STREAMING)
+               return 0;
+       else if (dev->status != STATUS_IDLE)
+               return -EAGAIN;
+
+       vidinf = get_video_info(dev);
+
+       if (vidinf) {
+               v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+                        "video signal: %dx%d@%dhz\n", vidinf->width,
+                        vidinf->height, vidinf->fps);
+               kfree(vidinf);
+
+               /* start streaming 2 request */
+               ret = usb_control_msg(dev->udev,
+                                     usb_sndctrlpipe(dev->udev, 0),
+                                     0xb8, 0x38, 0x1, 0, NULL, 0, 8000);
+               v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+                        "encoder start control request returned %d\n", ret);
+
+               hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00);
+
+               dev->status = STATUS_STREAMING;
+
+               INIT_WORK(&dev->worker, hdpvr_transmit_buffers);
+               queue_work(dev->workqueue, &dev->worker);
+
+               v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+                        "streaming started\n");
+
+               return 0;
+       }
+       msleep(250);
+       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                "no video signal at input %d\n", dev->options.video_input);
+       return -EAGAIN;
+}
+
+
+/* function expects dev->io_mutex to be hold by caller */
+static int hdpvr_stop_streaming(struct hdpvr_device *dev)
+{
+       int actual_length;
+       uint c = 0;
+       u8 *buf;
+
+       if (dev->status == STATUS_IDLE)
+               return 0;
+       else if (dev->status != STATUS_STREAMING)
+               return -EAGAIN;
+
+       buf = kmalloc(dev->bulk_in_size, GFP_KERNEL);
+       if (!buf)
+               v4l2_err(&dev->v4l2_dev, "failed to allocate temporary buffer "
+                        "for emptying the internal device buffer. "
+                        "Next capture start will be slow\n");
+
+       dev->status = STATUS_SHUTTING_DOWN;
+       hdpvr_config_call(dev, CTRL_STOP_STREAMING_VALUE, 0x00);
+       mutex_unlock(&dev->io_mutex);
+
+       wake_up_interruptible(&dev->wait_buffer);
+       msleep(50);
+
+       flush_workqueue(dev->workqueue);
+
+       mutex_lock(&dev->io_mutex);
+       /* kill the still outstanding urbs */
+       hdpvr_cancel_queue(dev);
+
+       /* emptying the device buffer beforeshutting it down */
+       while (buf && ++c < 500 &&
+              !usb_bulk_msg(dev->udev,
+                            usb_rcvbulkpipe(dev->udev,
+                                            dev->bulk_in_endpointAddr),
+                            buf, dev->bulk_in_size, &actual_length,
+                            BULK_URB_TIMEOUT)) {
+               v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+                        "%2d: got %d bytes\n", c, actual_length);
+       }
+       kfree(buf);
+       v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+                "used %d urbs to empty device buffers\n", c-1);
+       msleep(10);
+
+       dev->status = STATUS_IDLE;
+
+       return 0;
+}
+
+
+/*=======================================================================*/
+/*
+ * video 4 linux 2 file operations
+ */
+
+static int hdpvr_open(struct file *file)
+{
+       struct hdpvr_device *dev;
+       struct hdpvr_fh *fh;
+       int retval = -ENOMEM;
+
+       dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file));
+       if (!dev) {
+               pr_err("open failing with with ENODEV\n");
+               retval = -ENODEV;
+               goto err;
+       }
+
+       fh = kzalloc(sizeof(struct hdpvr_fh), GFP_KERNEL);
+       if (!fh) {
+               v4l2_err(&dev->v4l2_dev, "Out of memory\n");
+               goto err;
+       }
+       /* lock the device to allow correctly handling errors
+        * in resumption */
+       mutex_lock(&dev->io_mutex);
+       dev->open_count++;
+       mutex_unlock(&dev->io_mutex);
+
+       fh->dev = dev;
+
+       /* save our object in the file's private structure */
+       file->private_data = fh;
+
+       retval = 0;
+err:
+       return retval;
+}
+
+static int hdpvr_release(struct file *file)
+{
+       struct hdpvr_fh         *fh  = file->private_data;
+       struct hdpvr_device     *dev = fh->dev;
+
+       if (!dev)
+               return -ENODEV;
+
+       mutex_lock(&dev->io_mutex);
+       if (!(--dev->open_count) && dev->status == STATUS_STREAMING)
+               hdpvr_stop_streaming(dev);
+
+       mutex_unlock(&dev->io_mutex);
+
+       return 0;
+}
+
+/*
+ * hdpvr_v4l2_read()
+ * will allocate buffers when called for the first time
+ */
+static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count,
+                         loff_t *pos)
+{
+       struct hdpvr_fh *fh = file->private_data;
+       struct hdpvr_device *dev = fh->dev;
+       struct hdpvr_buffer *buf = NULL;
+       struct urb *urb;
+       unsigned int ret = 0;
+       int rem, cnt;
+
+       if (*pos)
+               return -ESPIPE;
+
+       if (!dev)
+               return -ENODEV;
+
+       mutex_lock(&dev->io_mutex);
+       if (dev->status == STATUS_IDLE) {
+               if (hdpvr_start_streaming(dev)) {
+                       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                                "start_streaming failed\n");
+                       ret = -EIO;
+                       msleep(200);
+                       dev->status = STATUS_IDLE;
+                       mutex_unlock(&dev->io_mutex);
+                       goto err;
+               }
+               print_buffer_status();
+       }
+       mutex_unlock(&dev->io_mutex);
+
+       /* wait for the first buffer */
+       if (!(file->f_flags & O_NONBLOCK)) {
+               if (wait_event_interruptible(dev->wait_data,
+                                            hdpvr_get_next_buffer(dev)))
+                       return -ERESTARTSYS;
+       }
+
+       buf = hdpvr_get_next_buffer(dev);
+
+       while (count > 0 && buf) {
+
+               if (buf->status != BUFSTAT_READY &&
+                   dev->status != STATUS_DISCONNECTED) {
+                       /* return nonblocking */
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               goto err;
+                       }
+
+                       if (wait_event_interruptible(dev->wait_data,
+                                             buf->status == BUFSTAT_READY)) {
+                               ret = -ERESTARTSYS;
+                               goto err;
+                       }
+               }
+
+               if (buf->status != BUFSTAT_READY)
+                       break;
+
+               /* set remaining bytes to copy */
+               urb = buf->urb;
+               rem = urb->actual_length - buf->pos;
+               cnt = rem > count ? count : rem;
+
+               if (copy_to_user(buffer, urb->transfer_buffer + buf->pos,
+                                cnt)) {
+                       v4l2_err(&dev->v4l2_dev, "read: copy_to_user failed\n");
+                       if (!ret)
+                               ret = -EFAULT;
+                       goto err;
+               }
+
+               buf->pos += cnt;
+               count -= cnt;
+               buffer += cnt;
+               ret += cnt;
+
+               /* finished, take next buffer */
+               if (buf->pos == urb->actual_length) {
+                       mutex_lock(&dev->io_mutex);
+                       buf->pos = 0;
+                       buf->status = BUFSTAT_AVAILABLE;
+
+                       list_move_tail(&buf->buff_list, &dev->free_buff_list);
+
+                       print_buffer_status();
+
+                       mutex_unlock(&dev->io_mutex);
+
+                       wake_up_interruptible(&dev->wait_buffer);
+
+                       buf = hdpvr_get_next_buffer(dev);
+               }
+       }
+err:
+       if (!ret && !buf)
+               ret = -EAGAIN;
+       return ret;
+}
+
+static unsigned int hdpvr_poll(struct file *filp, poll_table *wait)
+{
+       struct hdpvr_buffer *buf = NULL;
+       struct hdpvr_fh *fh = filp->private_data;
+       struct hdpvr_device *dev = fh->dev;
+       unsigned int mask = 0;
+
+       mutex_lock(&dev->io_mutex);
+
+       if (!video_is_registered(dev->video_dev)) {
+               mutex_unlock(&dev->io_mutex);
+               return -EIO;
+       }
+
+       if (dev->status == STATUS_IDLE) {
+               if (hdpvr_start_streaming(dev)) {
+                       v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
+                                "start_streaming failed\n");
+                       dev->status = STATUS_IDLE;
+               }
+
+               print_buffer_status();
+       }
+       mutex_unlock(&dev->io_mutex);
+
+       buf = hdpvr_get_next_buffer(dev);
+       /* only wait if no data is available */
+       if (!buf || buf->status != BUFSTAT_READY) {
+               poll_wait(filp, &dev->wait_data, wait);
+               buf = hdpvr_get_next_buffer(dev);
+       }
+       if (buf && buf->status == BUFSTAT_READY)
+               mask |= POLLIN | POLLRDNORM;
+
+       return mask;
+}
+
+
+static const struct v4l2_file_operations hdpvr_fops = {
+       .owner          = THIS_MODULE,
+       .open           = hdpvr_open,
+       .release        = hdpvr_release,
+       .read           = hdpvr_read,
+       .poll           = hdpvr_poll,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+/*=======================================================================*/
+/*
+ * V4L2 ioctl handling
+ */
+
+static int vidioc_querycap(struct file *file, void  *priv,
+                          struct v4l2_capability *cap)
+{
+       struct hdpvr_device *dev = video_drvdata(file);
+
+       strcpy(cap->driver, "hdpvr");
+       strcpy(cap->card, "Hauppauge HD PVR");
+       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
+       cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
+                               V4L2_CAP_AUDIO         |
+                               V4L2_CAP_READWRITE;
+       return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *private_data,
+                       v4l2_std_id *std)
+{
+       struct hdpvr_fh *fh = file->private_data;
+       struct hdpvr_device *dev = fh->dev;
+       u8 std_type = 1;
+
+       if (*std & (V4L2_STD_NTSC | V4L2_STD_PAL_60))
+               std_type = 0;
+
+       return hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, std_type);
+}
+
+static const char *iname[] = {
+       [HDPVR_COMPONENT] = "Component",
+       [HDPVR_SVIDEO]    = "S-Video",
+       [HDPVR_COMPOSITE] = "Composite",
+};
+
+static int vidioc_enum_input(struct file *file, void *priv,
+                               struct v4l2_input *i)
+{
+       struct hdpvr_fh *fh = file->private_data;
+       struct hdpvr_device *dev = fh->dev;
+       unsigned int n;
+
+       n = i->index;
+       if (n >= HDPVR_VIDEO_INPUTS)
+               return -EINVAL;
+
+       i->type = V4L2_INPUT_TYPE_CAMERA;
+
+       strncpy(i->name, iname[n], sizeof(i->name) - 1);
+       i->name[sizeof(i->name) - 1] = '\0';
+
+       i->audioset = 1<<HDPVR_RCA_FRONT | 1<<HDPVR_RCA_BACK | 1<<HDPVR_SPDIF;
+
+       i->std = dev->video_dev->tvnorms;
+
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *private_data,
+                         unsigned int index)
+{
+       struct hdpvr_fh *fh = file->private_data;
+       struct hdpvr_device *dev = fh->dev;
+       int retval;
+
+       if (index >= HDPVR_VIDEO_INPUTS)
+               return -EINVAL;
+
+       if (dev->status != STATUS_IDLE)
+               return -EAGAIN;
+
+       retval = hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, index+1);
+       if (!retval)
+               dev->options.video_input = index;
+
+       return retval;
+}
+
+static int vidioc_g_input(struct file *file, void *private_data,
+                         unsigned int *index)
+{
+       struct hdpvr_fh *fh = file->private_data;
+       struct hdpvr_device *dev = fh->dev;
+
+       *index = dev->options.video_input;
+       return 0;
+}
+
+
+static const char *audio_iname[] = {
+       [HDPVR_RCA_FRONT] = "RCA front",
+       [HDPVR_RCA_BACK]  = "RCA back",
+       [HDPVR_SPDIF]     = "SPDIF",
+};
+
+static int vidioc_enumaudio(struct file *file, void *priv,
+                               struct v4l2_audio *audio)
+{
+       unsigned int n;
+
+       n = audio->index;
+       if (n >= HDPVR_AUDIO_INPUTS)
+               return -EINVAL;
+
+       audio->capability = V4L2_AUDCAP_STEREO;
+
+       strncpy(audio->name, audio_iname[n], sizeof(audio->name) - 1);
+       audio->name[sizeof(audio->name) - 1] = '\0';
+
+       return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *private_data,
+                         struct v4l2_audio *audio)
+{
+       struct hdpvr_fh *fh = file->private_data;
+       struct hdpvr_device *dev = fh->dev;
+       int retval;
+
+       if (audio->index >= HDPVR_AUDIO_INPUTS)
+               return -EINVAL;
+
+       if (dev->status != STATUS_IDLE)
+               return -EAGAIN;
+
+       retval = hdpvr_set_audio(dev, audio->index+1, dev->options.audio_codec);
+       if (!retval)
+               dev->options.audio_input = audio->index;
+
+       return retval;
+}
+
+static int vidioc_g_audio(struct file *file, void *private_data,
+                         struct v4l2_audio *audio)
+{
+       struct hdpvr_fh *fh = file->private_data;
+       struct hdpvr_device *dev = fh->dev;
+
+       audio->index = dev->options.audio_input;
+       audio->capability = V4L2_AUDCAP_STEREO;
+       strncpy(audio->name, audio_iname[audio->index], sizeof(audio->name));
+       audio->name[sizeof(audio->name) - 1] = '\0';
+       return 0;
+}
+
+static const s32 supported_v4l2_ctrls[] = {
+       V4L2_CID_BRIGHTNESS,
+       V4L2_CID_CONTRAST,
+       V4L2_CID_SATURATION,
+       V4L2_CID_HUE,
+       V4L2_CID_SHARPNESS,
+       V4L2_CID_MPEG_AUDIO_ENCODING,
+       V4L2_CID_MPEG_VIDEO_ENCODING,
+       V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+       V4L2_CID_MPEG_VIDEO_BITRATE,
+       V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+};
+
+static int fill_queryctrl(struct hdpvr_options *opt, struct v4l2_queryctrl *qc,
+                         int ac3, int fw_ver)
+{
+       int err;
+
+       if (fw_ver > 0x15) {
+               switch (qc->id) {
+               case V4L2_CID_BRIGHTNESS:
+                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
+               case V4L2_CID_CONTRAST:
+                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x40);
+               case V4L2_CID_SATURATION:
+                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x40);
+               case V4L2_CID_HUE:
+                       return v4l2_ctrl_query_fill(qc, 0x0, 0x1e, 1, 0xf);
+               case V4L2_CID_SHARPNESS:
+                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
+               }
+       } else {
+               switch (qc->id) {
+               case V4L2_CID_BRIGHTNESS:
+                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x86);
+               case V4L2_CID_CONTRAST:
+                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
+               case V4L2_CID_SATURATION:
+                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
+               case V4L2_CID_HUE:
+                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
+               case V4L2_CID_SHARPNESS:
+                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
+               }
+       }
+
+       switch (qc->id) {
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               return v4l2_ctrl_query_fill(
+                       qc, V4L2_MPEG_AUDIO_ENCODING_AAC,
+                       ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3
+                       : V4L2_MPEG_AUDIO_ENCODING_AAC,
+                       1, V4L2_MPEG_AUDIO_ENCODING_AAC);
+       case V4L2_CID_MPEG_VIDEO_ENCODING:
+               return v4l2_ctrl_query_fill(
+                       qc, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC,
+                       V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1,
+                       V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC);
+
+/*     case V4L2_CID_MPEG_VIDEO_? maybe keyframe interval: */
+/*             return v4l2_ctrl_query_fill(qc, 0, 128, 128, 0); */
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               return v4l2_ctrl_query_fill(
+                       qc, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+                       V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
+                       V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);
+
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               return v4l2_ctrl_query_fill(qc, 1000000, 13500000, 100000,
+                                           6500000);
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               err = v4l2_ctrl_query_fill(qc, 1100000, 20200000, 100000,
+                                          9000000);
+               if (!err && opt->bitrate_mode == HDPVR_CONSTANT)
+                       qc->flags |= V4L2_CTRL_FLAG_INACTIVE;
+               return err;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int vidioc_queryctrl(struct file *file, void *private_data,
+                           struct v4l2_queryctrl *qc)
+{
+       struct hdpvr_fh *fh = file->private_data;
+       struct hdpvr_device *dev = fh->dev;
+       int i, next;
+       u32 id = qc->id;
+
+       memset(qc, 0, sizeof(*qc));
+
+       next = !!(id &  V4L2_CTRL_FLAG_NEXT_CTRL);
+       qc->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
+
+       for (i = 0; i < ARRAY_SIZE(supported_v4l2_ctrls); i++) {
+               if (next) {
+                       if (qc->id < supported_v4l2_ctrls[i])
+                               qc->id = supported_v4l2_ctrls[i];
+                       else
+                               continue;
+               }
+
+               if (qc->id == supported_v4l2_ctrls[i])
+                       return fill_queryctrl(&dev->options, qc,
+                                             dev->flags & HDPVR_FLAG_AC3_CAP,
+                                             dev->fw_ver);
+
+               if (qc->id < supported_v4l2_ctrls[i])
+                       break;
+       }
+
+       return -EINVAL;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *private_data,
+                        struct v4l2_control *ctrl)
+{
+       struct hdpvr_fh *fh = file->private_data;
+       struct hdpvr_device *dev = fh->dev;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               ctrl->value = dev->options.brightness;
+               break;
+       case V4L2_CID_CONTRAST:
+               ctrl->value = dev->options.contrast;
+               break;
+       case V4L2_CID_SATURATION:
+               ctrl->value = dev->options.saturation;
+               break;
+       case V4L2_CID_HUE:
+               ctrl->value = dev->options.hue;
+               break;
+       case V4L2_CID_SHARPNESS:
+               ctrl->value = dev->options.sharpness;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *private_data,
+                        struct v4l2_control *ctrl)
+{
+       struct hdpvr_fh *fh = file->private_data;
+       struct hdpvr_device *dev = fh->dev;
+       int retval;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               retval = hdpvr_config_call(dev, CTRL_BRIGHTNESS, ctrl->value);
+               if (!retval)
+                       dev->options.brightness = ctrl->value;
+               break;
+       case V4L2_CID_CONTRAST:
+               retval = hdpvr_config_call(dev, CTRL_CONTRAST, ctrl->value);
+               if (!retval)
+                       dev->options.contrast = ctrl->value;
+               break;
+       case V4L2_CID_SATURATION:
+               retval = hdpvr_config_call(dev, CTRL_SATURATION, ctrl->value);
+               if (!retval)
+                       dev->options.saturation = ctrl->value;
+               break;
+       case V4L2_CID_HUE:
+               retval = hdpvr_config_call(dev, CTRL_HUE, ctrl->value);
+               if (!retval)
+                       dev->options.hue = ctrl->value;
+               break;
+       case V4L2_CID_SHARPNESS:
+               retval = hdpvr_config_call(dev, CTRL_SHARPNESS, ctrl->value);
+               if (!retval)
+                       dev->options.sharpness = ctrl->value;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return retval;
+}
+
+
+static int hdpvr_get_ctrl(struct hdpvr_options *opt,
+                         struct v4l2_ext_control *ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               ctrl->value = opt->audio_codec;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ENCODING:
+               ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC;
+               break;
+/*     case V4L2_CID_MPEG_VIDEO_B_FRAMES: */
+/*             ctrl->value = (opt->gop_mode & 0x2) ? 0 : 128; */
+/*             break; */
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               ctrl->value = opt->bitrate_mode == HDPVR_CONSTANT
+                       ? V4L2_MPEG_VIDEO_BITRATE_MODE_CBR
+                       : V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               ctrl->value = opt->bitrate * 100000;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+               ctrl->value = opt->peak_bitrate * 100000;
+               break;
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int vidioc_g_ext_ctrls(struct file *file, void *priv,
+                             struct v4l2_ext_controls *ctrls)
+{
+       struct hdpvr_fh *fh = file->private_data;
+       struct hdpvr_device *dev = fh->dev;
+       int i, err = 0;
+
+       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+               for (i = 0; i < ctrls->count; i++) {
+                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+                       err = hdpvr_get_ctrl(&dev->options, ctrl);
+                       if (err) {
+                               ctrls->error_idx = i;
+                               break;
+                       }
+               }
+               return err;
+
+       }
+
+       return -EINVAL;
+}
+
+
+static int hdpvr_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
+{
+       int ret = -EINVAL;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               if (ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AAC ||
+                   (ac3 && ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AC3))
+                       ret = 0;
+               break;
+       case V4L2_CID_MPEG_VIDEO_ENCODING:
+               if (ctrl->value == V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC)
+                       ret = 0;
+               break;
+/*     case V4L2_CID_MPEG_VIDEO_B_FRAMES: */
+/*             if (ctrl->value == 0 || ctrl->value == 128) */
+/*                     ret = 0; */
+/*             break; */
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR ||
+                   ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
+                       ret = 0;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+       {
+               uint bitrate = ctrl->value / 100000;
+               if (bitrate >= 10 && bitrate <= 135)
+                       ret = 0;
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+       {
+               uint peak_bitrate = ctrl->value / 100000;
+               if (peak_bitrate >= 10 && peak_bitrate <= 202)
+                       ret = 0;
+               break;
+       }
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               if (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)
+                       ret = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return ret;
+}
+
+static int vidioc_try_ext_ctrls(struct file *file, void *priv,
+                               struct v4l2_ext_controls *ctrls)
+{
+       struct hdpvr_fh *fh = file->private_data;
+       struct hdpvr_device *dev = fh->dev;
+       int i, err = 0;
+
+       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+               for (i = 0; i < ctrls->count; i++) {
+                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+                       err = hdpvr_try_ctrl(ctrl,
+                                            dev->flags & HDPVR_FLAG_AC3_CAP);
+                       if (err) {
+                               ctrls->error_idx = i;
+                               break;
+                       }
+               }
+               return err;
+       }
+
+       return -EINVAL;
+}
+
+
+static int hdpvr_set_ctrl(struct hdpvr_device *dev,
+                         struct v4l2_ext_control *ctrl)
+{
+       struct hdpvr_options *opt = &dev->options;
+       int ret = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_MPEG_AUDIO_ENCODING:
+               if (dev->flags & HDPVR_FLAG_AC3_CAP) {
+                       opt->audio_codec = ctrl->value;
+                       ret = hdpvr_set_audio(dev, opt->audio_input,
+                                             opt->audio_codec);
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_ENCODING:
+               break;
+/*     case V4L2_CID_MPEG_VIDEO_B_FRAMES: */
+/*             if (ctrl->value == 0 && !(opt->gop_mode & 0x2)) { */
+/*                     opt->gop_mode |= 0x2; */
+/*                     hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */
+/*                                       opt->gop_mode); */
+/*             } */
+/*             if (ctrl->value == 128 && opt->gop_mode & 0x2) { */
+/*                     opt->gop_mode &= ~0x2; */
+/*                     hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */
+/*                                       opt->gop_mode); */
+/*             } */
+/*             break; */
+       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+               if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR &&
+                   opt->bitrate_mode != HDPVR_CONSTANT) {
+                       opt->bitrate_mode = HDPVR_CONSTANT;
+                       hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE,
+                                         opt->bitrate_mode);
+               }
+               if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
+                   opt->bitrate_mode == HDPVR_CONSTANT) {
+                       opt->bitrate_mode = HDPVR_VARIABLE_AVERAGE;
+                       hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE,
+                                         opt->bitrate_mode);
+               }
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE: {
+               uint bitrate = ctrl->value / 100000;
+
+               opt->bitrate = bitrate;
+               if (bitrate >= opt->peak_bitrate)
+                       opt->peak_bitrate = bitrate+1;
+
+               hdpvr_set_bitrate(dev);
+               break;
+       }
+       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: {
+               uint peak_bitrate = ctrl->value / 100000;
+
+               if (opt->bitrate_mode == HDPVR_CONSTANT)
+                       break;
+
+               if (opt->bitrate < peak_bitrate) {
+                       opt->peak_bitrate = peak_bitrate;
+                       hdpvr_set_bitrate(dev);
+               } else
+                       ret = -EINVAL;
+               break;
+       }
+       case V4L2_CID_MPEG_STREAM_TYPE:
+               break;
+       default:
+               return -EINVAL;
+       }
+       return ret;
+}
+
+static int vidioc_s_ext_ctrls(struct file *file, void *priv,
+                             struct v4l2_ext_controls *ctrls)
+{
+       struct hdpvr_fh *fh = file->private_data;
+       struct hdpvr_device *dev = fh->dev;
+       int i, err = 0;
+
+       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
+               for (i = 0; i < ctrls->count; i++) {
+                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+                       err = hdpvr_try_ctrl(ctrl,
+                                            dev->flags & HDPVR_FLAG_AC3_CAP);
+                       if (err) {
+                               ctrls->error_idx = i;
+                               break;
+                       }
+                       err = hdpvr_set_ctrl(dev, ctrl);
+                       if (err) {
+                               ctrls->error_idx = i;
+                               break;
+                       }
+               }
+               return err;
+
+       }
+
+       return -EINVAL;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data,
+                                   struct v4l2_fmtdesc *f)
+{
+
+       if (f->index != 0 || f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       f->flags = V4L2_FMT_FLAG_COMPRESSED;
+       strncpy(f->description, "MPEG2-TS with AVC/AAC streams", 32);
+       f->pixelformat = V4L2_PIX_FMT_MPEG;
+
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data,
+                               struct v4l2_format *f)
+{
+       struct hdpvr_fh *fh = file->private_data;
+       struct hdpvr_device *dev = fh->dev;
+       struct hdpvr_video_info *vid_info;
+
+       if (!dev)
+               return -ENODEV;
+
+       vid_info = get_video_info(dev);
+       if (!vid_info)
+               return -EFAULT;
+
+       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
+       f->fmt.pix.width        = vid_info->width;
+       f->fmt.pix.height       = vid_info->height;
+       f->fmt.pix.sizeimage    = dev->bulk_in_size;
+       f->fmt.pix.colorspace   = 0;
+       f->fmt.pix.bytesperline = 0;
+       f->fmt.pix.field        = V4L2_FIELD_ANY;
+
+       kfree(vid_info);
+       return 0;
+}
+
+static int vidioc_encoder_cmd(struct file *filp, void *priv,
+                              struct v4l2_encoder_cmd *a)
+{
+       struct hdpvr_fh *fh = filp->private_data;
+       struct hdpvr_device *dev = fh->dev;
+       int res;
+
+       mutex_lock(&dev->io_mutex);
+
+       memset(&a->raw, 0, sizeof(a->raw));
+       switch (a->cmd) {
+       case V4L2_ENC_CMD_START:
+               a->flags = 0;
+               res = hdpvr_start_streaming(dev);
+               break;
+       case V4L2_ENC_CMD_STOP:
+               res = hdpvr_stop_streaming(dev);
+               break;
+       default:
+               v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
+                        "Unsupported encoder cmd %d\n", a->cmd);
+               res = -EINVAL;
+       }
+       mutex_unlock(&dev->io_mutex);
+       return res;
+}
+
+static int vidioc_try_encoder_cmd(struct file *filp, void *priv,
+                                       struct v4l2_encoder_cmd *a)
+{
+       switch (a->cmd) {
+       case V4L2_ENC_CMD_START:
+       case V4L2_ENC_CMD_STOP:
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = {
+       .vidioc_querycap        = vidioc_querycap,
+       .vidioc_s_std           = vidioc_s_std,
+       .vidioc_enum_input      = vidioc_enum_input,
+       .vidioc_g_input         = vidioc_g_input,
+       .vidioc_s_input         = vidioc_s_input,
+       .vidioc_enumaudio       = vidioc_enumaudio,
+       .vidioc_g_audio         = vidioc_g_audio,
+       .vidioc_s_audio         = vidioc_s_audio,
+       .vidioc_queryctrl       = vidioc_queryctrl,
+       .vidioc_g_ctrl          = vidioc_g_ctrl,
+       .vidioc_s_ctrl          = vidioc_s_ctrl,
+       .vidioc_g_ext_ctrls     = vidioc_g_ext_ctrls,
+       .vidioc_s_ext_ctrls     = vidioc_s_ext_ctrls,
+       .vidioc_try_ext_ctrls   = vidioc_try_ext_ctrls,
+       .vidioc_enum_fmt_vid_cap        = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap           = vidioc_g_fmt_vid_cap,
+       .vidioc_encoder_cmd     = vidioc_encoder_cmd,
+       .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd,
+};
+
+static void hdpvr_device_release(struct video_device *vdev)
+{
+       struct hdpvr_device *dev = video_get_drvdata(vdev);
+
+       hdpvr_delete(dev);
+       mutex_lock(&dev->io_mutex);
+       destroy_workqueue(dev->workqueue);
+       mutex_unlock(&dev->io_mutex);
+
+       v4l2_device_unregister(&dev->v4l2_dev);
+
+       /* deregister I2C adapter */
+#if defined(CONFIG_I2C) || (CONFIG_I2C_MODULE)
+       mutex_lock(&dev->i2c_mutex);
+       i2c_del_adapter(&dev->i2c_adapter);
+       mutex_unlock(&dev->i2c_mutex);
+#endif /* CONFIG_I2C */
+
+       kfree(dev->usbc_buf);
+       kfree(dev);
+}
+
+static const struct video_device hdpvr_video_template = {
+/*     .type                   = VFL_TYPE_GRABBER, */
+/*     .type2                  = VID_TYPE_CAPTURE | VID_TYPE_MPEG_ENCODER, */
+       .fops                   = &hdpvr_fops,
+       .release                = hdpvr_device_release,
+       .ioctl_ops              = &hdpvr_ioctl_ops,
+       .tvnorms                =
+               V4L2_STD_NTSC  | V4L2_STD_SECAM | V4L2_STD_PAL_B |
+               V4L2_STD_PAL_G | V4L2_STD_PAL_H | V4L2_STD_PAL_I |
+               V4L2_STD_PAL_D | V4L2_STD_PAL_M | V4L2_STD_PAL_N |
+               V4L2_STD_PAL_60,
+       .current_norm           = V4L2_STD_NTSC | V4L2_STD_PAL_M |
+               V4L2_STD_PAL_60,
+};
+
+int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
+                           int devnum)
+{
+       /* setup and register video device */
+       dev->video_dev = video_device_alloc();
+       if (!dev->video_dev) {
+               v4l2_err(&dev->v4l2_dev, "video_device_alloc() failed\n");
+               goto error;
+       }
+
+       *(dev->video_dev) = hdpvr_video_template;
+       strcpy(dev->video_dev->name, "Hauppauge HD PVR");
+       dev->video_dev->parent = parent;
+       video_set_drvdata(dev->video_dev, dev);
+
+       if (video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum)) {
+               v4l2_err(&dev->v4l2_dev, "video_device registration failed\n");
+               goto error;
+       }
+
+       return 0;
+error:
+       return -ENOMEM;
+}
diff --git a/drivers/media/usb/hdpvr/hdpvr.h b/drivers/media/usb/hdpvr/hdpvr.h
new file mode 100644 (file)
index 0000000..fea3c69
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * Hauppauge HD PVR USB driver
+ *
+ * Copyright (C) 2008      Janne Grunau (j@jannau.net)
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation, version 2.
+ *
+ */
+
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/workqueue.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-device.h>
+#include <media/ir-kbd-i2c.h>
+
+#define HDPVR_MAX 8
+#define HDPVR_I2C_MAX_SIZE 128
+
+/* Define these values to match your devices */
+#define HD_PVR_VENDOR_ID       0x2040
+#define HD_PVR_PRODUCT_ID      0x4900
+#define HD_PVR_PRODUCT_ID1     0x4901
+#define HD_PVR_PRODUCT_ID2     0x4902
+#define HD_PVR_PRODUCT_ID4     0x4903
+#define HD_PVR_PRODUCT_ID3     0x4982
+
+#define UNSET    (-1U)
+
+#define NUM_BUFFERS 64
+
+#define HDPVR_FIRMWARE_VERSION         0x08
+#define HDPVR_FIRMWARE_VERSION_AC3     0x0d
+#define HDPVR_FIRMWARE_VERSION_0X12    0x12
+#define HDPVR_FIRMWARE_VERSION_0X15    0x15
+
+/* #define HDPVR_DEBUG */
+
+extern int hdpvr_debug;
+
+#define MSG_INFO       1
+#define MSG_BUFFER     2
+
+struct hdpvr_options {
+       u8      video_std;
+       u8      video_input;
+       u8      audio_input;
+       u8      bitrate;        /* in 100kbps */
+       u8      peak_bitrate;   /* in 100kbps */
+       u8      bitrate_mode;
+       u8      gop_mode;
+       enum v4l2_mpeg_audio_encoding   audio_codec;
+       u8      brightness;
+       u8      contrast;
+       u8      hue;
+       u8      saturation;
+       u8      sharpness;
+};
+
+/* Structure to hold all of our device specific stuff */
+struct hdpvr_device {
+       /* the v4l device for this device */
+       struct video_device     *video_dev;
+       /* the usb device for this device */
+       struct usb_device       *udev;
+       /* v4l2-device unused */
+       struct v4l2_device      v4l2_dev;
+
+       /* the max packet size of the bulk endpoint */
+       size_t                  bulk_in_size;
+       /* the address of the bulk in endpoint */
+       __u8                    bulk_in_endpointAddr;
+
+       /* holds the current device status */
+       __u8                    status;
+       /* count the number of openers */
+       uint                    open_count;
+
+       /* holds the cureent set options */
+       struct hdpvr_options    options;
+
+       uint                    flags;
+
+       /* synchronize I/O */
+       struct mutex            io_mutex;
+       /* available buffers */
+       struct list_head        free_buff_list;
+       /* in progress buffers */
+       struct list_head        rec_buff_list;
+       /* waitqueue for buffers */
+       wait_queue_head_t       wait_buffer;
+       /* waitqueue for data */
+       wait_queue_head_t       wait_data;
+       /**/
+       struct workqueue_struct *workqueue;
+       /**/
+       struct work_struct      worker;
+
+       /* I2C adapter */
+       struct i2c_adapter      i2c_adapter;
+       /* I2C lock */
+       struct mutex            i2c_mutex;
+       /* I2C message buffer space */
+       char                    i2c_buf[HDPVR_I2C_MAX_SIZE];
+
+       /* For passing data to ir-kbd-i2c */
+       struct IR_i2c_init_data ir_i2c_init_data;
+
+       /* usb control transfer buffer and lock */
+       struct mutex            usbc_mutex;
+       u8                      *usbc_buf;
+       u8                      fw_ver;
+};
+
+static inline struct hdpvr_device *to_hdpvr_dev(struct v4l2_device *v4l2_dev)
+{
+       return container_of(v4l2_dev, struct hdpvr_device, v4l2_dev);
+}
+
+
+/* buffer one bulk urb of data */
+struct hdpvr_buffer {
+       struct list_head        buff_list;
+
+       struct urb              *urb;
+
+       struct hdpvr_device     *dev;
+
+       uint                    pos;
+
+       __u8                    status;
+};
+
+/* */
+
+struct hdpvr_video_info {
+       u16     width;
+       u16     height;
+       u8      fps;
+};
+
+enum {
+       STATUS_UNINITIALIZED    = 0,
+       STATUS_IDLE,
+       STATUS_STARTING,
+       STATUS_SHUTTING_DOWN,
+       STATUS_STREAMING,
+       STATUS_ERROR,
+       STATUS_DISCONNECTED,
+};
+
+enum {
+       HDPVR_FLAG_AC3_CAP = 1,
+};
+
+enum {
+       BUFSTAT_UNINITIALIZED = 0,
+       BUFSTAT_AVAILABLE,
+       BUFSTAT_INPROGRESS,
+       BUFSTAT_READY,
+};
+
+#define CTRL_START_STREAMING_VALUE     0x0700
+#define CTRL_STOP_STREAMING_VALUE      0x0800
+#define CTRL_BITRATE_VALUE             0x1000
+#define CTRL_BITRATE_MODE_VALUE                0x1200
+#define CTRL_GOP_MODE_VALUE            0x1300
+#define CTRL_VIDEO_INPUT_VALUE         0x1500
+#define CTRL_VIDEO_STD_TYPE            0x1700
+#define CTRL_AUDIO_INPUT_VALUE         0x2500
+#define CTRL_BRIGHTNESS                        0x2900
+#define CTRL_CONTRAST                  0x2a00
+#define CTRL_HUE                       0x2b00
+#define CTRL_SATURATION                        0x2c00
+#define CTRL_SHARPNESS                 0x2d00
+#define CTRL_LOW_PASS_FILTER_VALUE     0x3100
+
+#define CTRL_DEFAULT_INDEX             0x0003
+
+
+       /* :0 s 38 01 1000 0003 0004 4 = 0a00ca00
+        * BITRATE SETTING
+        *   1st and 2nd byte (little endian): average bitrate in 100 000 bit/s
+        *                                     min: 1 mbit/s, max: 13.5 mbit/s
+        *   3rd and 4th byte (little endian): peak bitrate in 100 000 bit/s
+        *                                     min: average + 100kbit/s,
+        *                                      max: 20.2 mbit/s
+        */
+
+       /* :0 s 38 01 1200 0003 0001 1 = 02
+        * BIT RATE MODE
+        *  constant = 1, variable (peak) = 2, variable (average) = 3
+        */
+
+       /* :0 s 38 01 1300 0003 0001 1 = 03
+        * GOP MODE (2 bit)
+        *    low bit 0/1: advanced/simple GOP
+        *   high bit 0/1: IDR(4/32/128) / no IDR (4/32/0)
+        */
+
+       /* :0 s 38 01 1700 0003 0001 1 = 00
+        * VIDEO STANDARD or FREQUNCY 0 = 60hz, 1 = 50hz
+        */
+
+       /* :0 s 38 01 3100 0003 0004 4 = 03030000
+        * FILTER CONTROL
+        *   1st byte luma low pass filter strength,
+        *   2nd byte chroma low pass filter strength,
+        *   3rd byte MF enable chroma, min=0, max=1
+        *   4th byte n
+        */
+
+
+       /* :0 s 38 b9 0001 0000 0000 0 */
+
+
+
+/* :0 s 38 d3 0000 0000 0001 1 = 00 */
+/*             ret = usb_control_msg(dev->udev, */
+/*                                   usb_sndctrlpipe(dev->udev, 0), */
+/*                                   0xd3, 0x38, */
+/*                                   0, 0, */
+/*                                   "\0", 1, */
+/*                                   1000); */
+
+/*             info("control request returned %d", ret); */
+/*             msleep(5000); */
+
+
+       /* :0 s b8 81 1400 0003 0005 5 <
+        * :0 0 5 = d0024002 19
+        * QUERY FRAME SIZE AND RATE
+        *   1st and 2nd byte (little endian): horizontal resolution
+        *   3rd and 4th byte (little endian): vertical resolution
+        *   5th byte: frame rate
+        */
+
+       /* :0 s b8 81 1800 0003 0003 3 <
+        * :0 0 3 = 030104
+        * QUERY SIGNAL AND DETECTED LINES, maybe INPUT
+        */
+
+enum hdpvr_video_std {
+       HDPVR_60HZ = 0,
+       HDPVR_50HZ,
+};
+
+enum hdpvr_video_input {
+       HDPVR_COMPONENT = 0,
+       HDPVR_SVIDEO,
+       HDPVR_COMPOSITE,
+       HDPVR_VIDEO_INPUTS
+};
+
+enum hdpvr_audio_inputs {
+       HDPVR_RCA_BACK = 0,
+       HDPVR_RCA_FRONT,
+       HDPVR_SPDIF,
+       HDPVR_AUDIO_INPUTS
+};
+
+enum hdpvr_bitrate_mode {
+       HDPVR_CONSTANT = 1,
+       HDPVR_VARIABLE_PEAK,
+       HDPVR_VARIABLE_AVERAGE,
+};
+
+enum hdpvr_gop_mode {
+       HDPVR_ADVANCED_IDR_GOP = 0,
+       HDPVR_SIMPLE_IDR_GOP,
+       HDPVR_ADVANCED_NOIDR_GOP,
+       HDPVR_SIMPLE_NOIDR_GOP,
+};
+
+void hdpvr_delete(struct hdpvr_device *dev);
+
+/*========================================================================*/
+/* hardware control functions */
+int hdpvr_set_options(struct hdpvr_device *dev);
+
+int hdpvr_set_bitrate(struct hdpvr_device *dev);
+
+int hdpvr_set_audio(struct hdpvr_device *dev, u8 input,
+                   enum v4l2_mpeg_audio_encoding codec);
+
+int hdpvr_config_call(struct hdpvr_device *dev, uint value,
+                     unsigned char valbuf);
+
+struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev);
+
+/* :0 s b8 81 1800 0003 0003 3 < */
+/* :0 0 3 = 0301ff */
+int get_input_lines_info(struct hdpvr_device *dev);
+
+
+/*========================================================================*/
+/* v4l2 registration */
+int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
+                           int devnumber);
+
+int hdpvr_cancel_queue(struct hdpvr_device *dev);
+
+/*========================================================================*/
+/* i2c adapter registration */
+int hdpvr_register_i2c_adapter(struct hdpvr_device *dev);
+
+struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev);
+struct i2c_client *hdpvr_register_ir_tx_i2c(struct hdpvr_device *dev);
+
+/*========================================================================*/
+/* buffer management */
+int hdpvr_free_buffers(struct hdpvr_device *dev);
+int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count);
diff --git a/drivers/media/usb/pvrusb2/Kconfig b/drivers/media/usb/pvrusb2/Kconfig
new file mode 100644 (file)
index 0000000..25e412e
--- /dev/null
@@ -0,0 +1,65 @@
+config VIDEO_PVRUSB2
+       tristate "Hauppauge WinTV-PVR USB2 support"
+       depends on VIDEO_V4L2 && I2C
+       select VIDEO_TUNER
+       select VIDEO_TVEEPROM
+       select VIDEO_CX2341X
+       select VIDEO_SAA711X
+       select VIDEO_CX25840
+       select VIDEO_MSP3400
+       select VIDEO_WM8775
+       select VIDEO_CS53L32A
+       ---help---
+         This is a video4linux driver for Conexant 23416 based
+         usb2 personal video recorder devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called pvrusb2
+
+config VIDEO_PVRUSB2_SYSFS
+       bool "pvrusb2 sysfs support (EXPERIMENTAL)"
+       default y
+       depends on VIDEO_PVRUSB2 && SYSFS && EXPERIMENTAL
+       ---help---
+         This option enables the operation of a sysfs based
+         interface for query and control of the pvrusb2 driver.
+
+         This is not generally needed for v4l applications,
+         although certain applications are optimized to take
+         advantage of this feature.
+
+         If you are in doubt, say Y.
+
+         Note: This feature is experimental and subject to change.
+
+config VIDEO_PVRUSB2_DVB
+       bool "pvrusb2 ATSC/DVB support (EXPERIMENTAL)"
+       default y
+       depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL
+       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
+       select DVB_S5H1409 if !DVB_FE_CUSTOMISE
+       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
+       select DVB_TDA10048 if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
+       select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
+       ---help---
+
+         This option enables a DVB interface for the pvrusb2 driver.
+         If your device does not support digital television, this
+         feature will have no affect on the driver's operation.
+
+         If you are in doubt, say Y.
+
+config VIDEO_PVRUSB2_DEBUGIFC
+       bool "pvrusb2 debug interface"
+       depends on VIDEO_PVRUSB2_SYSFS
+       ---help---
+         This option enables the inclusion of a debug interface
+         in the pvrusb2 driver, hosted through sysfs.
+
+         You do not need to select this option unless you plan
+         on debugging the driver or performing a manual firmware
+         extraction.
+
+         If you are in doubt, say N.
diff --git a/drivers/media/usb/pvrusb2/Makefile b/drivers/media/usb/pvrusb2/Makefile
new file mode 100644 (file)
index 0000000..bc716db
--- /dev/null
@@ -0,0 +1,22 @@
+obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o
+obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
+obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o
+
+pvrusb2-objs   := pvrusb2-i2c-core.o \
+                  pvrusb2-audio.o \
+                  pvrusb2-encoder.o pvrusb2-video-v4l.o \
+                  pvrusb2-eeprom.o \
+                  pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \
+                  pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \
+                  pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
+                  pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \
+                  pvrusb2-cs53l32a.o \
+                  $(obj-pvrusb2-dvb-y) \
+                  $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
+
+obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
+
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-audio.c b/drivers/media/usb/pvrusb2/pvrusb2-audio.c
new file mode 100644 (file)
index 0000000..cc06d5e
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-audio.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/msp3400.h>
+#include <media/v4l2-common.h>
+
+
+struct routing_scheme {
+       const int *def;
+       unsigned int cnt;
+};
+
+static const int routing_scheme0[] = {
+       [PVR2_CVAL_INPUT_TV]        = MSP_INPUT_DEFAULT,
+       [PVR2_CVAL_INPUT_RADIO]     = MSP_INPUT(MSP_IN_SCART2,
+                                               MSP_IN_TUNER1,
+                                               MSP_DSP_IN_SCART,
+                                               MSP_DSP_IN_SCART),
+       [PVR2_CVAL_INPUT_COMPOSITE] = MSP_INPUT(MSP_IN_SCART1,
+                                               MSP_IN_TUNER1,
+                                               MSP_DSP_IN_SCART,
+                                               MSP_DSP_IN_SCART),
+       [PVR2_CVAL_INPUT_SVIDEO]    = MSP_INPUT(MSP_IN_SCART1,
+                                               MSP_IN_TUNER1,
+                                               MSP_DSP_IN_SCART,
+                                               MSP_DSP_IN_SCART),
+};
+
+static const struct routing_scheme routing_def0 = {
+       .def = routing_scheme0,
+       .cnt = ARRAY_SIZE(routing_scheme0),
+};
+
+static const struct routing_scheme *routing_schemes[] = {
+       [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
+};
+
+void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
+{
+       if (hdw->input_dirty || hdw->force_dirty) {
+               const struct routing_scheme *sp;
+               unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
+               u32 input;
+
+               pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo");
+               sp = (sid < ARRAY_SIZE(routing_schemes)) ?
+                       routing_schemes[sid] : NULL;
+
+               if ((sp != NULL) &&
+                   (hdw->input_val >= 0) &&
+                   (hdw->input_val < sp->cnt)) {
+                       input = sp->def[hdw->input_val];
+               } else {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "*** WARNING *** subdev msp3400 set_input:"
+                                  " Invalid routing scheme (%u)"
+                                  " and/or input (%d)",
+                                  sid, hdw->input_val);
+                       return;
+               }
+               sd->ops->audio->s_routing(sd, input,
+                       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
new file mode 100644 (file)
index 0000000..e3e63d7
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_AUDIO_H
+#define __PVRUSB2_AUDIO_H
+
+#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
new file mode 100644 (file)
index 0000000..7c19ff7
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-context.h"
+#include "pvrusb2-io.h"
+#include "pvrusb2-ioread.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-debug.h"
+#include <linux/wait.h>
+#include <linux/kthread.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+static struct pvr2_context *pvr2_context_exist_first;
+static struct pvr2_context *pvr2_context_exist_last;
+static struct pvr2_context *pvr2_context_notify_first;
+static struct pvr2_context *pvr2_context_notify_last;
+static DEFINE_MUTEX(pvr2_context_mutex);
+static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_sync_data);
+static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_cleanup_data);
+static int pvr2_context_cleanup_flag;
+static int pvr2_context_cleaned_flag;
+static struct task_struct *pvr2_context_thread_ptr;
+
+
+static void pvr2_context_set_notify(struct pvr2_context *mp, int fl)
+{
+       int signal_flag = 0;
+       mutex_lock(&pvr2_context_mutex);
+       if (fl) {
+               if (!mp->notify_flag) {
+                       signal_flag = (pvr2_context_notify_first == NULL);
+                       mp->notify_prev = pvr2_context_notify_last;
+                       mp->notify_next = NULL;
+                       pvr2_context_notify_last = mp;
+                       if (mp->notify_prev) {
+                               mp->notify_prev->notify_next = mp;
+                       } else {
+                               pvr2_context_notify_first = mp;
+                       }
+                       mp->notify_flag = !0;
+               }
+       } else {
+               if (mp->notify_flag) {
+                       mp->notify_flag = 0;
+                       if (mp->notify_next) {
+                               mp->notify_next->notify_prev = mp->notify_prev;
+                       } else {
+                               pvr2_context_notify_last = mp->notify_prev;
+                       }
+                       if (mp->notify_prev) {
+                               mp->notify_prev->notify_next = mp->notify_next;
+                       } else {
+                               pvr2_context_notify_first = mp->notify_next;
+                       }
+               }
+       }
+       mutex_unlock(&pvr2_context_mutex);
+       if (signal_flag) wake_up(&pvr2_context_sync_data);
+}
+
+
+static void pvr2_context_destroy(struct pvr2_context *mp)
+{
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp);
+       if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
+       pvr2_context_set_notify(mp, 0);
+       mutex_lock(&pvr2_context_mutex);
+       if (mp->exist_next) {
+               mp->exist_next->exist_prev = mp->exist_prev;
+       } else {
+               pvr2_context_exist_last = mp->exist_prev;
+       }
+       if (mp->exist_prev) {
+               mp->exist_prev->exist_next = mp->exist_next;
+       } else {
+               pvr2_context_exist_first = mp->exist_next;
+       }
+       if (!pvr2_context_exist_first) {
+               /* Trigger wakeup on control thread in case it is waiting
+                  for an exit condition. */
+               wake_up(&pvr2_context_sync_data);
+       }
+       mutex_unlock(&pvr2_context_mutex);
+       kfree(mp);
+}
+
+
+static void pvr2_context_notify(struct pvr2_context *mp)
+{
+       pvr2_context_set_notify(mp,!0);
+}
+
+
+static void pvr2_context_check(struct pvr2_context *mp)
+{
+       struct pvr2_channel *ch1, *ch2;
+       pvr2_trace(PVR2_TRACE_CTXT,
+                  "pvr2_context %p (notify)", mp);
+       if (!mp->initialized_flag && !mp->disconnect_flag) {
+               mp->initialized_flag = !0;
+               pvr2_trace(PVR2_TRACE_CTXT,
+                          "pvr2_context %p (initialize)", mp);
+               /* Finish hardware initialization */
+               if (pvr2_hdw_initialize(mp->hdw,
+                                       (void (*)(void *))pvr2_context_notify,
+                                       mp)) {
+                       mp->video_stream.stream =
+                               pvr2_hdw_get_video_stream(mp->hdw);
+                       /* Trigger interface initialization.  By doing this
+                          here initialization runs in our own safe and
+                          cozy thread context. */
+                       if (mp->setup_func) mp->setup_func(mp);
+               } else {
+                       pvr2_trace(PVR2_TRACE_CTXT,
+                                  "pvr2_context %p (thread skipping setup)",
+                                  mp);
+                       /* Even though initialization did not succeed,
+                          we're still going to continue anyway.  We need
+                          to do this in order to await the expected
+                          disconnect (which we will detect in the normal
+                          course of operation). */
+               }
+       }
+
+       for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
+               ch2 = ch1->mc_next;
+               if (ch1->check_func) ch1->check_func(ch1);
+       }
+
+       if (mp->disconnect_flag && !mp->mc_first) {
+               /* Go away... */
+               pvr2_context_destroy(mp);
+               return;
+       }
+}
+
+
+static int pvr2_context_shutok(void)
+{
+       return pvr2_context_cleanup_flag && (pvr2_context_exist_first == NULL);
+}
+
+
+static int pvr2_context_thread_func(void *foo)
+{
+       struct pvr2_context *mp;
+
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread start");
+
+       do {
+               while ((mp = pvr2_context_notify_first) != NULL) {
+                       pvr2_context_set_notify(mp, 0);
+                       pvr2_context_check(mp);
+               }
+               wait_event_interruptible(
+                       pvr2_context_sync_data,
+                       ((pvr2_context_notify_first != NULL) ||
+                        pvr2_context_shutok()));
+       } while (!pvr2_context_shutok());
+
+       pvr2_context_cleaned_flag = !0;
+       wake_up(&pvr2_context_cleanup_data);
+
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread cleaned up");
+
+       wait_event_interruptible(
+               pvr2_context_sync_data,
+               kthread_should_stop());
+
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end");
+
+       return 0;
+}
+
+
+int pvr2_context_global_init(void)
+{
+       pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func,
+                                             NULL,
+                                             "pvrusb2-context");
+       return (pvr2_context_thread_ptr ? 0 : -ENOMEM);
+}
+
+
+void pvr2_context_global_done(void)
+{
+       pvr2_context_cleanup_flag = !0;
+       wake_up(&pvr2_context_sync_data);
+       wait_event_interruptible(
+               pvr2_context_cleanup_data,
+               pvr2_context_cleaned_flag);
+       kthread_stop(pvr2_context_thread_ptr);
+}
+
+
+struct pvr2_context *pvr2_context_create(
+       struct usb_interface *intf,
+       const struct usb_device_id *devid,
+       void (*setup_func)(struct pvr2_context *))
+{
+       struct pvr2_context *mp = NULL;
+       mp = kzalloc(sizeof(*mp),GFP_KERNEL);
+       if (!mp) goto done;
+       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp);
+       mp->setup_func = setup_func;
+       mutex_init(&mp->mutex);
+       mutex_lock(&pvr2_context_mutex);
+       mp->exist_prev = pvr2_context_exist_last;
+       mp->exist_next = NULL;
+       pvr2_context_exist_last = mp;
+       if (mp->exist_prev) {
+               mp->exist_prev->exist_next = mp;
+       } else {
+               pvr2_context_exist_first = mp;
+       }
+       mutex_unlock(&pvr2_context_mutex);
+       mp->hdw = pvr2_hdw_create(intf,devid);
+       if (!mp->hdw) {
+               pvr2_context_destroy(mp);
+               mp = NULL;
+               goto done;
+       }
+       pvr2_context_set_notify(mp, !0);
+ done:
+       return mp;
+}
+
+
+static void pvr2_context_reset_input_limits(struct pvr2_context *mp)
+{
+       unsigned int tmsk,mmsk;
+       struct pvr2_channel *cp;
+       struct pvr2_hdw *hdw = mp->hdw;
+       mmsk = pvr2_hdw_get_input_available(hdw);
+       tmsk = mmsk;
+       for (cp = mp->mc_first; cp; cp = cp->mc_next) {
+               if (!cp->input_mask) continue;
+               tmsk &= cp->input_mask;
+       }
+       pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk);
+       pvr2_hdw_commit_ctl(hdw);
+}
+
+
+static void pvr2_context_enter(struct pvr2_context *mp)
+{
+       mutex_lock(&mp->mutex);
+}
+
+
+static void pvr2_context_exit(struct pvr2_context *mp)
+{
+       int destroy_flag = 0;
+       if (!(mp->mc_first || !mp->disconnect_flag)) {
+               destroy_flag = !0;
+       }
+       mutex_unlock(&mp->mutex);
+       if (destroy_flag) pvr2_context_notify(mp);
+}
+
+
+void pvr2_context_disconnect(struct pvr2_context *mp)
+{
+       pvr2_hdw_disconnect(mp->hdw);
+       mp->disconnect_flag = !0;
+       pvr2_context_notify(mp);
+}
+
+
+void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
+{
+       pvr2_context_enter(mp);
+       cp->hdw = mp->hdw;
+       cp->mc_head = mp;
+       cp->mc_next = NULL;
+       cp->mc_prev = mp->mc_last;
+       if (mp->mc_last) {
+               mp->mc_last->mc_next = cp;
+       } else {
+               mp->mc_first = cp;
+       }
+       mp->mc_last = cp;
+       pvr2_context_exit(mp);
+}
+
+
+static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
+{
+       if (!cp->stream) return;
+       pvr2_stream_kill(cp->stream->stream);
+       cp->stream->user = NULL;
+       cp->stream = NULL;
+}
+
+
+void pvr2_channel_done(struct pvr2_channel *cp)
+{
+       struct pvr2_context *mp = cp->mc_head;
+       pvr2_context_enter(mp);
+       cp->input_mask = 0;
+       pvr2_channel_disclaim_stream(cp);
+       pvr2_context_reset_input_limits(mp);
+       if (cp->mc_next) {
+               cp->mc_next->mc_prev = cp->mc_prev;
+       } else {
+               mp->mc_last = cp->mc_prev;
+       }
+       if (cp->mc_prev) {
+               cp->mc_prev->mc_next = cp->mc_next;
+       } else {
+               mp->mc_first = cp->mc_next;
+       }
+       cp->hdw = NULL;
+       pvr2_context_exit(mp);
+}
+
+
+int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk)
+{
+       unsigned int tmsk,mmsk;
+       int ret = 0;
+       struct pvr2_channel *p2;
+       struct pvr2_hdw *hdw = cp->hdw;
+
+       mmsk = pvr2_hdw_get_input_available(hdw);
+       cmsk &= mmsk;
+       if (cmsk == cp->input_mask) {
+               /* No change; nothing to do */
+               return 0;
+       }
+
+       pvr2_context_enter(cp->mc_head);
+       do {
+               if (!cmsk) {
+                       cp->input_mask = 0;
+                       pvr2_context_reset_input_limits(cp->mc_head);
+                       break;
+               }
+               tmsk = mmsk;
+               for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) {
+                       if (p2 == cp) continue;
+                       if (!p2->input_mask) continue;
+                       tmsk &= p2->input_mask;
+               }
+               if (!(tmsk & cmsk)) {
+                       ret = -EPERM;
+                       break;
+               }
+               tmsk &= cmsk;
+               if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) {
+                       /* Internal failure changing allowed list; probably
+                          should not happen, but react if it does. */
+                       break;
+               }
+               cp->input_mask = cmsk;
+               pvr2_hdw_commit_ctl(hdw);
+       } while (0);
+       pvr2_context_exit(cp->mc_head);
+       return ret;
+}
+
+
+unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp)
+{
+       return cp->input_mask;
+}
+
+
+int pvr2_channel_claim_stream(struct pvr2_channel *cp,
+                             struct pvr2_context_stream *sp)
+{
+       int code = 0;
+       pvr2_context_enter(cp->mc_head); do {
+               if (sp == cp->stream) break;
+               if (sp && sp->user) {
+                       code = -EBUSY;
+                       break;
+               }
+               pvr2_channel_disclaim_stream(cp);
+               if (!sp) break;
+               sp->user = cp;
+               cp->stream = sp;
+       } while (0); pvr2_context_exit(cp->mc_head);
+       return code;
+}
+
+
+// This is the marker for the real beginning of a legitimate mpeg2 stream.
+static char stream_sync_key[] = {
+       0x00, 0x00, 0x01, 0xba,
+};
+
+struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
+       struct pvr2_context_stream *sp)
+{
+       struct pvr2_ioread *cp;
+       cp = pvr2_ioread_create();
+       if (!cp) return NULL;
+       pvr2_ioread_setup(cp,sp->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
new file mode 100644 (file)
index 0000000..d657e53
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_CONTEXT_H
+#define __PVRUSB2_CONTEXT_H
+
+#include <linux/mutex.h>
+#include <linux/usb.h>
+#include <linux/workqueue.h>
+
+struct pvr2_hdw;     /* hardware interface - defined elsewhere */
+struct pvr2_stream;  /* stream interface - defined elsewhere */
+
+struct pvr2_context;        /* All central state */
+struct pvr2_channel;        /* One I/O pathway to a user */
+struct pvr2_context_stream; /* Wrapper for a stream */
+struct pvr2_ioread;         /* Low level stream structure */
+
+struct pvr2_context_stream {
+       struct pvr2_channel *user;
+       struct pvr2_stream *stream;
+};
+
+struct pvr2_context {
+       struct pvr2_channel *mc_first;
+       struct pvr2_channel *mc_last;
+       struct pvr2_context *exist_next;
+       struct pvr2_context *exist_prev;
+       struct pvr2_context *notify_next;
+       struct pvr2_context *notify_prev;
+       struct pvr2_hdw *hdw;
+       struct pvr2_context_stream video_stream;
+       struct mutex mutex;
+       int notify_flag;
+       int initialized_flag;
+       int disconnect_flag;
+
+       /* Called after pvr2_context initialization is complete */
+       void (*setup_func)(struct pvr2_context *);
+
+};
+
+struct pvr2_channel {
+       struct pvr2_context *mc_head;
+       struct pvr2_channel *mc_next;
+       struct pvr2_channel *mc_prev;
+       struct pvr2_context_stream *stream;
+       struct pvr2_hdw *hdw;
+       unsigned int input_mask;
+       void (*check_func)(struct pvr2_channel *);
+};
+
+struct pvr2_context *pvr2_context_create(struct usb_interface *intf,
+                                        const struct usb_device_id *devid,
+                                        void (*setup_func)(struct pvr2_context *));
+void pvr2_context_disconnect(struct pvr2_context *);
+
+void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *);
+void pvr2_channel_done(struct pvr2_channel *);
+int pvr2_channel_limit_inputs(struct pvr2_channel *,unsigned int);
+unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *);
+int pvr2_channel_claim_stream(struct pvr2_channel *,
+                             struct pvr2_context_stream *);
+struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
+       struct pvr2_context_stream *);
+
+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
new file mode 100644 (file)
index 0000000..8832090
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+
+   This source file is specifically designed to interface with the
+   v4l-dvb cs53l32a module.
+
+*/
+
+#include "pvrusb2-cs53l32a.h"
+
+
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/errno.h>
+
+struct routing_scheme {
+       const int *def;
+       unsigned int cnt;
+};
+
+
+static const int routing_scheme1[] = {
+       [PVR2_CVAL_INPUT_TV] = 2,  /* 1 or 2 seems to work here */
+       [PVR2_CVAL_INPUT_RADIO] = 2,
+       [PVR2_CVAL_INPUT_COMPOSITE] = 0,
+       [PVR2_CVAL_INPUT_SVIDEO] =  0,
+};
+
+static const struct routing_scheme routing_def1 = {
+       .def = routing_scheme1,
+       .cnt = ARRAY_SIZE(routing_scheme1),
+};
+
+static const struct routing_scheme *routing_schemes[] = {
+       [PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1,
+};
+
+
+void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
+{
+       if (hdw->input_dirty || hdw->force_dirty) {
+               const struct routing_scheme *sp;
+               unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
+               u32 input;
+               pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)",
+                          hdw->input_val);
+               sp = (sid < ARRAY_SIZE(routing_schemes)) ?
+                       routing_schemes[sid] : NULL;
+               if ((sp == NULL) ||
+                   (hdw->input_val < 0) ||
+                   (hdw->input_val >= sp->cnt)) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "*** WARNING *** subdev v4l2 set_input:"
+                                  " Invalid routing scheme (%u)"
+                                  " and/or input (%d)",
+                                  sid, hdw->input_val);
+                       return;
+               }
+               input = sp->def[hdw->input_val];
+               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
new file mode 100644 (file)
index 0000000..53ba548
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_CS53L32A_H
+#define __PVRUSB2_CS53L32A_H
+
+/*
+
+   This module connects the pvrusb2 driver to the I2C chip level
+   driver which handles device video processing.  This interface is
+   used internally by the driver; higher level code should only
+   interact through the interface provided by pvrusb2-hdw.h.
+
+*/
+
+
+#include "pvrusb2-hdw-internal.h"
+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
new file mode 100644 (file)
index 0000000..7d5a713
--- /dev/null
@@ -0,0 +1,609 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-ctrl.h"
+#include "pvrusb2-hdw-internal.h"
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mutex.h>
+
+
+static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
+{
+       if (cptr->info->check_value) {
+               if (!cptr->info->check_value(cptr,val)) return -ERANGE;
+       } else if (cptr->info->type == pvr2_ctl_enum) {
+               if (val < 0) return -ERANGE;
+               if (val >= cptr->info->def.type_enum.count) return -ERANGE;
+       } else {
+               int lim;
+               lim = cptr->info->def.type_int.min_value;
+               if (cptr->info->get_min_value) {
+                       cptr->info->get_min_value(cptr,&lim);
+               }
+               if (val < lim) return -ERANGE;
+               lim = cptr->info->def.type_int.max_value;
+               if (cptr->info->get_max_value) {
+                       cptr->info->get_max_value(cptr,&lim);
+               }
+               if (val > lim) return -ERANGE;
+       }
+       return 0;
+}
+
+
+/* Set the given control. */
+int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
+{
+       return pvr2_ctrl_set_mask_value(cptr,~0,val);
+}
+
+
+/* Set/clear specific bits of the given control. */
+int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
+{
+       int ret = 0;
+       if (!cptr) return -EINVAL;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->set_value) {
+                       if (cptr->info->type == pvr2_ctl_bitmask) {
+                               mask &= cptr->info->def.type_bitmask.valid_bits;
+                       } else if ((cptr->info->type == pvr2_ctl_int)||
+                                  (cptr->info->type == pvr2_ctl_enum)) {
+                               ret = pvr2_ctrl_range_check(cptr,val);
+                               if (ret < 0) break;
+                       } else if (cptr->info->type != pvr2_ctl_bool) {
+                               break;
+                       }
+                       ret = cptr->info->set_value(cptr,mask,val);
+               } else {
+                       ret = -EPERM;
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Get the current value of the given control. */
+int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
+{
+       int ret = 0;
+       if (!cptr) return -EINVAL;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               ret = cptr->info->get_value(cptr,valptr);
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Retrieve control's type */
+enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
+{
+       if (!cptr) return pvr2_ctl_int;
+       return cptr->info->type;
+}
+
+
+/* Retrieve control's maximum value (int type) */
+int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
+{
+       int ret = 0;
+       if (!cptr) return 0;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->get_max_value) {
+                       cptr->info->get_max_value(cptr,&ret);
+               } else if (cptr->info->type == pvr2_ctl_int) {
+                       ret = cptr->info->def.type_int.max_value;
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Retrieve control's minimum value (int type) */
+int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
+{
+       int ret = 0;
+       if (!cptr) return 0;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->get_min_value) {
+                       cptr->info->get_min_value(cptr,&ret);
+               } else if (cptr->info->type == pvr2_ctl_int) {
+                       ret = cptr->info->def.type_int.min_value;
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Retrieve control's default value (any type) */
+int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr)
+{
+       int ret = 0;
+       if (!cptr) return -EINVAL;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->get_def_value) {
+                       ret = cptr->info->get_def_value(cptr, valptr);
+               } else {
+                       *valptr = cptr->info->default_value;
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Retrieve control's enumeration count (enum only) */
+int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
+{
+       int ret = 0;
+       if (!cptr) return 0;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->type == pvr2_ctl_enum) {
+                       ret = cptr->info->def.type_enum.count;
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Retrieve control's valid mask bits (bit mask only) */
+int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
+{
+       int ret = 0;
+       if (!cptr) return 0;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->type == pvr2_ctl_bitmask) {
+                       ret = cptr->info->def.type_bitmask.valid_bits;
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Retrieve the control's name */
+const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
+{
+       if (!cptr) return NULL;
+       return cptr->info->name;
+}
+
+
+/* Retrieve the control's desc */
+const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
+{
+       if (!cptr) return NULL;
+       return cptr->info->desc;
+}
+
+
+/* Retrieve a control enumeration or bit mask value */
+int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
+                         char *bptr,unsigned int bmax,
+                         unsigned int *blen)
+{
+       int ret = -EINVAL;
+       if (!cptr) return 0;
+       *blen = 0;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->type == pvr2_ctl_enum) {
+                       const char * const *names;
+                       names = cptr->info->def.type_enum.value_names;
+                       if (pvr2_ctrl_range_check(cptr,val) == 0) {
+                               if (names[val]) {
+                                       *blen = scnprintf(
+                                               bptr,bmax,"%s",
+                                               names[val]);
+                               } else {
+                                       *blen = 0;
+                               }
+                               ret = 0;
+                       }
+               } else if (cptr->info->type == pvr2_ctl_bitmask) {
+                       const char **names;
+                       unsigned int idx;
+                       int msk;
+                       names = cptr->info->def.type_bitmask.bit_names;
+                       val &= cptr->info->def.type_bitmask.valid_bits;
+                       for (idx = 0, msk = 1; val; idx++, msk <<= 1) {
+                               if (val & msk) {
+                                       *blen = scnprintf(bptr,bmax,"%s",
+                                                         names[idx]);
+                                       ret = 0;
+                                       break;
+                               }
+                       }
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Return V4L ID for this control or zero if none */
+int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
+{
+       if (!cptr) return 0;
+       return cptr->info->v4l_id;
+}
+
+
+unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
+{
+       unsigned int flags = 0;
+
+       if (cptr->info->get_v4lflags) {
+               flags = cptr->info->get_v4lflags(cptr);
+       }
+
+       if (cptr->info->set_value) {
+               flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
+       } else {
+               flags |= V4L2_CTRL_FLAG_READ_ONLY;
+       }
+
+       return flags;
+}
+
+
+/* Return true if control is writable */
+int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
+{
+       if (!cptr) return 0;
+       return cptr->info->set_value != NULL;
+}
+
+
+/* Return true if control has custom symbolic representation */
+int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
+{
+       if (!cptr) return 0;
+       if (!cptr->info->val_to_sym) return 0;
+       if (!cptr->info->sym_to_val) return 0;
+       return !0;
+}
+
+
+/* Convert a given mask/val to a custom symbolic value */
+int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
+                                 int mask,int val,
+                                 char *buf,unsigned int maxlen,
+                                 unsigned int *len)
+{
+       if (!cptr) return -EINVAL;
+       if (!cptr->info->val_to_sym) return -EINVAL;
+       return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len);
+}
+
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr,
+                                 const char *buf,unsigned int len,
+                                 int *maskptr,int *valptr)
+{
+       if (!cptr) return -EINVAL;
+       if (!cptr->info->sym_to_val) return -EINVAL;
+       return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr);
+}
+
+
+static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
+                                      const char **names,
+                                      char *ptr,unsigned int len)
+{
+       unsigned int idx;
+       long sm,um;
+       int spcFl;
+       unsigned int uc,cnt;
+       const char *idStr;
+
+       spcFl = 0;
+       uc = 0;
+       um = 0;
+       for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
+               if (sm & msk) {
+                       msk &= ~sm;
+                       idStr = names[idx];
+                       if (idStr) {
+                               cnt = scnprintf(ptr,len,"%s%s%s",
+                                               (spcFl ? " " : ""),
+                                               (msk_only ? "" :
+                                                ((val & sm) ? "+" : "-")),
+                                               idStr);
+                               ptr += cnt; len -= cnt; uc += cnt;
+                               spcFl = !0;
+                       } else {
+                               um |= sm;
+                       }
+               }
+       }
+       if (um) {
+               if (msk_only) {
+                       cnt = scnprintf(ptr,len,"%s0x%lx",
+                                       (spcFl ? " " : ""),
+                                       um);
+                       ptr += cnt; len -= cnt; uc += cnt;
+                       spcFl = !0;
+               } else if (um & val) {
+                       cnt = scnprintf(ptr,len,"%s+0x%lx",
+                                       (spcFl ? " " : ""),
+                                       um & val);
+                       ptr += cnt; len -= cnt; uc += cnt;
+                       spcFl = !0;
+               } else if (um & ~val) {
+                       cnt = scnprintf(ptr,len,"%s+0x%lx",
+                                       (spcFl ? " " : ""),
+                                       um & ~val);
+                       ptr += cnt; len -= cnt; uc += cnt;
+                       spcFl = !0;
+               }
+       }
+       return uc;
+}
+
+
+static const char *boolNames[] = {
+       "false",
+       "true",
+       "no",
+       "yes",
+};
+
+
+static int parse_token(const char *ptr,unsigned int len,
+                      int *valptr,
+                      const char * const *names, unsigned int namecnt)
+{
+       char buf[33];
+       unsigned int slen;
+       unsigned int idx;
+       int negfl;
+       char *p2;
+       *valptr = 0;
+       if (!names) namecnt = 0;
+       for (idx = 0; idx < namecnt; idx++) {
+               if (!names[idx]) continue;
+               slen = strlen(names[idx]);
+               if (slen != len) continue;
+               if (memcmp(names[idx],ptr,slen)) continue;
+               *valptr = idx;
+               return 0;
+       }
+       negfl = 0;
+       if ((*ptr == '-') || (*ptr == '+')) {
+               negfl = (*ptr == '-');
+               ptr++; len--;
+       }
+       if (len >= sizeof(buf)) return -EINVAL;
+       memcpy(buf,ptr,len);
+       buf[len] = 0;
+       *valptr = simple_strtol(buf,&p2,0);
+       if (negfl) *valptr = -(*valptr);
+       if (*p2) return -EINVAL;
+       return 1;
+}
+
+
+static int parse_mtoken(const char *ptr,unsigned int len,
+                       int *valptr,
+                       const char **names,int valid_bits)
+{
+       char buf[33];
+       unsigned int slen;
+       unsigned int idx;
+       char *p2;
+       int msk;
+       *valptr = 0;
+       for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
+               if (!(msk & valid_bits)) continue;
+               valid_bits &= ~msk;
+               if (!names[idx]) continue;
+               slen = strlen(names[idx]);
+               if (slen != len) continue;
+               if (memcmp(names[idx],ptr,slen)) continue;
+               *valptr = msk;
+               return 0;
+       }
+       if (len >= sizeof(buf)) return -EINVAL;
+       memcpy(buf,ptr,len);
+       buf[len] = 0;
+       *valptr = simple_strtol(buf,&p2,0);
+       if (*p2) return -EINVAL;
+       return 0;
+}
+
+
+static int parse_tlist(const char *ptr,unsigned int len,
+                      int *maskptr,int *valptr,
+                      const char **names,int valid_bits)
+{
+       unsigned int cnt;
+       int mask,val,kv,mode,ret;
+       mask = 0;
+       val = 0;
+       ret = 0;
+       while (len) {
+               cnt = 0;
+               while ((cnt < len) &&
+                      ((ptr[cnt] <= 32) ||
+                       (ptr[cnt] >= 127))) cnt++;
+               ptr += cnt;
+               len -= cnt;
+               mode = 0;
+               if ((*ptr == '-') || (*ptr == '+')) {
+                       mode = (*ptr == '-') ? -1 : 1;
+                       ptr++;
+                       len--;
+               }
+               cnt = 0;
+               while (cnt < len) {
+                       if (ptr[cnt] <= 32) break;
+                       if (ptr[cnt] >= 127) break;
+                       cnt++;
+               }
+               if (!cnt) break;
+               if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
+                       ret = -EINVAL;
+                       break;
+               }
+               ptr += cnt;
+               len -= cnt;
+               switch (mode) {
+               case 0:
+                       mask = valid_bits;
+                       val |= kv;
+                       break;
+               case -1:
+                       mask |= kv;
+                       val &= ~kv;
+                       break;
+               case 1:
+                       mask |= kv;
+                       val |= kv;
+                       break;
+               default:
+                       break;
+               }
+       }
+       *maskptr = mask;
+       *valptr = val;
+       return ret;
+}
+
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
+                          const char *ptr,unsigned int len,
+                          int *maskptr,int *valptr)
+{
+       int ret = -EINVAL;
+       unsigned int cnt;
+
+       *maskptr = 0;
+       *valptr = 0;
+
+       cnt = 0;
+       while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
+       len -= cnt; ptr += cnt;
+       cnt = 0;
+       while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
+                              (ptr[len-(cnt+1)] >= 127))) cnt++;
+       len -= cnt;
+
+       if (!len) return -EINVAL;
+
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               if (cptr->info->type == pvr2_ctl_int) {
+                       ret = parse_token(ptr,len,valptr,NULL,0);
+                       if (ret >= 0) {
+                               ret = pvr2_ctrl_range_check(cptr,*valptr);
+                       }
+                       *maskptr = ~0;
+               } else if (cptr->info->type == pvr2_ctl_bool) {
+                       ret = parse_token(ptr,len,valptr,boolNames,
+                                         ARRAY_SIZE(boolNames));
+                       if (ret == 1) {
+                               *valptr = *valptr ? !0 : 0;
+                       } else if (ret == 0) {
+                               *valptr = (*valptr & 1) ? !0 : 0;
+                       }
+                       *maskptr = 1;
+               } else if (cptr->info->type == pvr2_ctl_enum) {
+                       ret = parse_token(
+                               ptr,len,valptr,
+                               cptr->info->def.type_enum.value_names,
+                               cptr->info->def.type_enum.count);
+                       if (ret >= 0) {
+                               ret = pvr2_ctrl_range_check(cptr,*valptr);
+                       }
+                       *maskptr = ~0;
+               } else if (cptr->info->type == pvr2_ctl_bitmask) {
+                       ret = parse_tlist(
+                               ptr,len,maskptr,valptr,
+                               cptr->info->def.type_bitmask.bit_names,
+                               cptr->info->def.type_bitmask.valid_bits);
+               }
+       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
+       return ret;
+}
+
+
+/* Convert a given mask/val to a symbolic value */
+int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
+                                   int mask,int val,
+                                   char *buf,unsigned int maxlen,
+                                   unsigned int *len)
+{
+       int ret = -EINVAL;
+
+       *len = 0;
+       if (cptr->info->type == pvr2_ctl_int) {
+               *len = scnprintf(buf,maxlen,"%d",val);
+               ret = 0;
+       } else if (cptr->info->type == pvr2_ctl_bool) {
+               *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
+               ret = 0;
+       } else if (cptr->info->type == pvr2_ctl_enum) {
+               const char * const *names;
+               names = cptr->info->def.type_enum.value_names;
+               if ((val >= 0) &&
+                   (val < cptr->info->def.type_enum.count)) {
+                       if (names[val]) {
+                               *len = scnprintf(
+                                       buf,maxlen,"%s",
+                                       names[val]);
+                       } else {
+                               *len = 0;
+                       }
+                       ret = 0;
+               }
+       } else if (cptr->info->type == pvr2_ctl_bitmask) {
+               *len = gen_bitmask_string(
+                       val & mask & cptr->info->def.type_bitmask.valid_bits,
+                       ~0,!0,
+                       cptr->info->def.type_bitmask.bit_names,
+                       buf,maxlen);
+       }
+       return ret;
+}
+
+
+/* Convert a given mask/val to a symbolic value */
+int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
+                          int mask,int val,
+                          char *buf,unsigned int maxlen,
+                          unsigned int *len)
+{
+       int ret;
+       LOCK_TAKE(cptr->hdw->big_lock); do {
+               ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
+                                                     buf,maxlen,len);
+       } 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
new file mode 100644 (file)
index 0000000..794ff90
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_CTRL_H
+#define __PVRUSB2_CTRL_H
+
+struct pvr2_ctrl;
+
+enum pvr2_ctl_type {
+       pvr2_ctl_int = 0,
+       pvr2_ctl_enum = 1,
+       pvr2_ctl_bitmask = 2,
+       pvr2_ctl_bool = 3,
+};
+
+
+/* Set the given control. */
+int pvr2_ctrl_set_value(struct pvr2_ctrl *,int val);
+
+/* Set/clear specific bits of the given control. */
+int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *,int mask,int val);
+
+/* Get the current value of the given control. */
+int pvr2_ctrl_get_value(struct pvr2_ctrl *,int *valptr);
+
+/* Retrieve control's type */
+enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *);
+
+/* Retrieve control's maximum value (int type) */
+int pvr2_ctrl_get_max(struct pvr2_ctrl *);
+
+/* Retrieve control's minimum value (int type) */
+int pvr2_ctrl_get_min(struct pvr2_ctrl *);
+
+/* Retrieve control's default value (any type) */
+int pvr2_ctrl_get_def(struct pvr2_ctrl *, int *valptr);
+
+/* Retrieve control's enumeration count (enum only) */
+int pvr2_ctrl_get_cnt(struct pvr2_ctrl *);
+
+/* Retrieve control's valid mask bits (bit mask only) */
+int pvr2_ctrl_get_mask(struct pvr2_ctrl *);
+
+/* Retrieve the control's name */
+const char *pvr2_ctrl_get_name(struct pvr2_ctrl *);
+
+/* Retrieve the control's desc */
+const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *);
+
+/* Retrieve a control enumeration or bit mask value */
+int pvr2_ctrl_get_valname(struct pvr2_ctrl *,int,char *,unsigned int,
+                         unsigned int *);
+
+/* Return true if control is writable */
+int pvr2_ctrl_is_writable(struct pvr2_ctrl *);
+
+/* Return V4L flags value for control (or zero if there is no v4l control
+   actually under this control) */
+unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *);
+
+/* Return V4L ID for this control or zero if none */
+int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *);
+
+/* Return true if control has custom symbolic representation */
+int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *);
+
+/* Convert a given mask/val to a custom symbolic value */
+int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *,
+                                 int mask,int val,
+                                 char *buf,unsigned int maxlen,
+                                 unsigned int *len);
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *,
+                                 const char *buf,unsigned int len,
+                                 int *maskptr,int *valptr);
+
+/* Convert a given mask/val to a symbolic value */
+int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *,
+                          int mask,int val,
+                          char *buf,unsigned int maxlen,
+                          unsigned int *len);
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *,
+                          const char *buf,unsigned int len,
+                          int *maskptr,int *valptr);
+
+/* Convert a given mask/val to a symbolic value - must already be
+   inside of critical region. */
+int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *,
+                          int mask,int val,
+                          char *buf,unsigned int maxlen,
+                          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
new file mode 100644 (file)
index 0000000..c514d0b
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+
+   This source file is specifically designed to interface with the
+   cx2584x, in kernels 2.6.16 or newer.
+
+*/
+
+#include "pvrusb2-cx2584x-v4l.h"
+#include "pvrusb2-video-v4l.h"
+
+
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <media/cx25840.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/errno.h>
+
+
+struct routing_scheme_item {
+       int vid;
+       int aud;
+};
+
+struct routing_scheme {
+       const struct routing_scheme_item *def;
+       unsigned int cnt;
+};
+
+static const struct routing_scheme_item routing_scheme0[] = {
+       [PVR2_CVAL_INPUT_TV] = {
+               .vid = CX25840_COMPOSITE7,
+               .aud = CX25840_AUDIO8,
+       },
+       [PVR2_CVAL_INPUT_RADIO] = { /* Treat the same as composite */
+               .vid = CX25840_COMPOSITE3,
+               .aud = CX25840_AUDIO_SERIAL,
+       },
+       [PVR2_CVAL_INPUT_COMPOSITE] = {
+               .vid = CX25840_COMPOSITE3,
+               .aud = CX25840_AUDIO_SERIAL,
+       },
+       [PVR2_CVAL_INPUT_SVIDEO] = {
+               .vid = CX25840_SVIDEO1,
+               .aud = CX25840_AUDIO_SERIAL,
+       },
+};
+
+static const struct routing_scheme routing_def0 = {
+       .def = routing_scheme0,
+       .cnt = ARRAY_SIZE(routing_scheme0),
+};
+
+/* Specific to gotview device */
+static const struct routing_scheme_item routing_schemegv[] = {
+       [PVR2_CVAL_INPUT_TV] = {
+               .vid = CX25840_COMPOSITE2,
+               .aud = CX25840_AUDIO5,
+       },
+       [PVR2_CVAL_INPUT_RADIO] = {
+               /* line-in is used for radio and composite.  A GPIO is
+                  used to switch between the two choices. */
+               .vid = CX25840_COMPOSITE1,
+               .aud = CX25840_AUDIO_SERIAL,
+       },
+       [PVR2_CVAL_INPUT_COMPOSITE] = {
+               .vid = CX25840_COMPOSITE1,
+               .aud = CX25840_AUDIO_SERIAL,
+       },
+       [PVR2_CVAL_INPUT_SVIDEO] = {
+               .vid = (CX25840_SVIDEO_LUMA3|CX25840_SVIDEO_CHROMA4),
+               .aud = CX25840_AUDIO_SERIAL,
+       },
+};
+
+static const struct routing_scheme routing_defgv = {
+       .def = routing_schemegv,
+       .cnt = ARRAY_SIZE(routing_schemegv),
+};
+
+/* Specific to grabster av400 device */
+static const struct routing_scheme_item routing_schemeav400[] = {
+       [PVR2_CVAL_INPUT_COMPOSITE] = {
+               .vid = CX25840_COMPOSITE1,
+               .aud = CX25840_AUDIO_SERIAL,
+       },
+       [PVR2_CVAL_INPUT_SVIDEO] = {
+               .vid = (CX25840_SVIDEO_LUMA2|CX25840_SVIDEO_CHROMA4),
+               .aud = CX25840_AUDIO_SERIAL,
+       },
+};
+
+static const struct routing_scheme routing_defav400 = {
+       .def = routing_schemeav400,
+       .cnt = ARRAY_SIZE(routing_schemeav400),
+};
+
+static const struct routing_scheme *routing_schemes[] = {
+       [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
+       [PVR2_ROUTING_SCHEME_GOTVIEW] = &routing_defgv,
+       [PVR2_ROUTING_SCHEME_AV400] = &routing_defav400,
+};
+
+void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
+{
+       pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update...");
+       if (hdw->input_dirty || hdw->force_dirty) {
+               enum cx25840_video_input vid_input;
+               enum cx25840_audio_input aud_input;
+               const struct routing_scheme *sp;
+               unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
+
+               sp = (sid < ARRAY_SIZE(routing_schemes)) ?
+                       routing_schemes[sid] : NULL;
+               if ((sp == NULL) ||
+                   (hdw->input_val < 0) ||
+                   (hdw->input_val >= sp->cnt)) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "*** WARNING *** subdev cx2584x set_input:"
+                                  " Invalid routing scheme (%u)"
+                                  " and/or input (%d)",
+                                  sid, hdw->input_val);
+                       return;
+               }
+               vid_input = sp->def[hdw->input_val].vid;
+               aud_input = sp->def[hdw->input_val].aud;
+               pvr2_trace(PVR2_TRACE_CHIPS,
+                          "subdev cx2584x set_input vid=0x%x aud=0x%x",
+                          vid_input, aud_input);
+               sd->ops->video->s_routing(sd, (u32)vid_input, 0, 0);
+               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
new file mode 100644 (file)
index 0000000..e35c232
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_CX2584X_V4L_H
+#define __PVRUSB2_CX2584X_V4L_H
+
+/*
+
+   This module connects the pvrusb2 driver to the I2C chip level
+   driver which handles combined device audio & video processing.
+   This interface is used internally by the driver; higher level code
+   should only interact through the interface provided by
+   pvrusb2-hdw.h.
+
+*/
+
+
+
+#include "pvrusb2-hdw-internal.h"
+
+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
new file mode 100644 (file)
index 0000000..be79249
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_DEBUG_H
+#define __PVRUSB2_DEBUG_H
+
+extern int pvrusb2_debug;
+
+#define pvr2_trace(msk, fmt, arg...) do {if(msk & pvrusb2_debug) printk(KERN_INFO "pvrusb2: " fmt "\n", ##arg); } while (0)
+
+/* These are listed in *rough* order of decreasing usefulness and
+   increasing noise level. */
+#define PVR2_TRACE_INFO       (1 <<  0) /* Normal messages */
+#define PVR2_TRACE_ERROR_LEGS (1 <<  1) /* error messages */
+#define PVR2_TRACE_TOLERANCE  (1 <<  2) /* track tolerance-affected errors */
+#define PVR2_TRACE_TRAP       (1 <<  3) /* Trap & report app misbehavior */
+#define PVR2_TRACE_STD        (1 <<  4) /* Log video standard stuff */
+#define PVR2_TRACE_INIT       (1 <<  5) /* misc initialization steps */
+#define PVR2_TRACE_START_STOP (1 <<  6) /* Streaming start / stop */
+#define PVR2_TRACE_CTL        (1 <<  7) /* commit of control changes */
+#define PVR2_TRACE_STATE      (1 <<  8) /* Device state changes */
+#define PVR2_TRACE_STBITS     (1 <<  9) /* Individual bit state changes */
+#define PVR2_TRACE_EEPROM     (1 << 10) /* eeprom parsing / report */
+#define PVR2_TRACE_STRUCT     (1 << 11) /* internal struct creation */
+#define PVR2_TRACE_OPEN_CLOSE (1 << 12) /* application open / close */
+#define PVR2_TRACE_CTXT       (1 << 13) /* Main context tracking */
+#define PVR2_TRACE_SYSFS      (1 << 14) /* Sysfs driven I/O */
+#define PVR2_TRACE_FIRMWARE   (1 << 15) /* firmware upload actions */
+#define PVR2_TRACE_CHIPS      (1 << 16) /* chip broadcast operation */
+#define PVR2_TRACE_I2C        (1 << 17) /* I2C related stuff */
+#define PVR2_TRACE_I2C_CMD    (1 << 18) /* Software commands to I2C modules */
+#define PVR2_TRACE_I2C_CORE   (1 << 19) /* I2C core debugging */
+#define PVR2_TRACE_I2C_TRAF   (1 << 20) /* I2C traffic through the adapter */
+#define PVR2_TRACE_V4LIOCTL   (1 << 21) /* v4l ioctl details */
+#define PVR2_TRACE_ENCODER    (1 << 22) /* mpeg2 encoder operation */
+#define PVR2_TRACE_BUF_POOL   (1 << 23) /* Track buffer pool management */
+#define PVR2_TRACE_BUF_FLOW   (1 << 24) /* Track buffer flow in system */
+#define PVR2_TRACE_DATA_FLOW  (1 << 25) /* Track data flow */
+#define PVR2_TRACE_DEBUGIFC   (1 << 26) /* Debug interface actions */
+#define PVR2_TRACE_GPIO       (1 << 27) /* GPIO state bit changes */
+#define PVR2_TRACE_DVB_FEED   (1 << 28) /* DVB transport feed 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
new file mode 100644 (file)
index 0000000..4279ebb
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/string.h>
+#include "pvrusb2-debugifc.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-debug.h"
+
+struct debugifc_mask_item {
+       const char *name;
+       unsigned long msk;
+};
+
+
+static unsigned int debugifc_count_whitespace(const char *buf,
+                                             unsigned int count)
+{
+       unsigned int scnt;
+       char ch;
+
+       for (scnt = 0; scnt < count; scnt++) {
+               ch = buf[scnt];
+               if (ch == ' ') continue;
+               if (ch == '\t') continue;
+               if (ch == '\n') continue;
+               break;
+       }
+       return scnt;
+}
+
+
+static unsigned int debugifc_count_nonwhitespace(const char *buf,
+                                                unsigned int count)
+{
+       unsigned int scnt;
+       char ch;
+
+       for (scnt = 0; scnt < count; scnt++) {
+               ch = buf[scnt];
+               if (ch == ' ') break;
+               if (ch == '\t') break;
+               if (ch == '\n') break;
+       }
+       return scnt;
+}
+
+
+static unsigned int debugifc_isolate_word(const char *buf,unsigned int count,
+                                         const char **wstrPtr,
+                                         unsigned int *wlenPtr)
+{
+       const char *wptr;
+       unsigned int consume_cnt = 0;
+       unsigned int wlen;
+       unsigned int scnt;
+
+       wptr = NULL;
+       wlen = 0;
+       scnt = debugifc_count_whitespace(buf,count);
+       consume_cnt += scnt; count -= scnt; buf += scnt;
+       if (!count) goto done;
+
+       scnt = debugifc_count_nonwhitespace(buf,count);
+       if (!scnt) goto done;
+       wptr = buf;
+       wlen = scnt;
+       consume_cnt += scnt; count -= scnt; buf += scnt;
+
+ done:
+       *wstrPtr = wptr;
+       *wlenPtr = wlen;
+       return consume_cnt;
+}
+
+
+static int debugifc_parse_unsigned_number(const char *buf,unsigned int count,
+                                         u32 *num_ptr)
+{
+       u32 result = 0;
+       int radix = 10;
+       if ((count >= 2) && (buf[0] == '0') &&
+           ((buf[1] == 'x') || (buf[1] == 'X'))) {
+               radix = 16;
+               count -= 2;
+               buf += 2;
+       } else if ((count >= 1) && (buf[0] == '0')) {
+               radix = 8;
+       }
+
+       while (count--) {
+               int val = hex_to_bin(*buf++);
+               if (val < 0 || val >= radix)
+                       return -EINVAL;
+               result *= radix;
+               result += val;
+       }
+       *num_ptr = result;
+       return 0;
+}
+
+
+static int debugifc_match_keyword(const char *buf,unsigned int count,
+                                 const char *keyword)
+{
+       unsigned int kl;
+       if (!keyword) return 0;
+       kl = strlen(keyword);
+       if (kl != count) return 0;
+       return !memcmp(buf,keyword,kl);
+}
+
+
+int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt)
+{
+       int bcnt = 0;
+       int ccnt;
+       ccnt = scnprintf(buf, acnt, "Driver hardware description: %s\n",
+                        pvr2_hdw_get_desc(hdw));
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = scnprintf(buf,acnt,"Driver state info:\n");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       ccnt = pvr2_hdw_state_report(hdw,buf,acnt);
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+       return bcnt;
+}
+
+
+int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
+                              char *buf,unsigned int acnt)
+{
+       int bcnt = 0;
+       int ccnt;
+       int ret;
+       u32 gpio_dir,gpio_in,gpio_out;
+       struct pvr2_stream_stats stats;
+       struct pvr2_stream *sp;
+
+       ret = pvr2_hdw_is_hsm(hdw);
+       ccnt = scnprintf(buf,acnt,"USB link speed: %s\n",
+                        (ret < 0 ? "FAIL" : (ret ? "high" : "full")));
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+       gpio_dir = 0; gpio_in = 0; gpio_out = 0;
+       pvr2_hdw_gpio_get_dir(hdw,&gpio_dir);
+       pvr2_hdw_gpio_get_out(hdw,&gpio_out);
+       pvr2_hdw_gpio_get_in(hdw,&gpio_in);
+       ccnt = scnprintf(buf,acnt,"GPIO state: dir=0x%x in=0x%x out=0x%x\n",
+                        gpio_dir,gpio_in,gpio_out);
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+       ccnt = scnprintf(buf,acnt,"Streaming is %s\n",
+                        pvr2_hdw_get_streaming(hdw) ? "on" : "off");
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+
+       sp = pvr2_hdw_get_video_stream(hdw);
+       if (sp) {
+               pvr2_stream_get_stats(sp, &stats, 0);
+               ccnt = scnprintf(
+                       buf,acnt,
+                       "Bytes streamed=%u"
+                       " URBs: queued=%u idle=%u ready=%u"
+                       " processed=%u failed=%u\n",
+                       stats.bytes_processed,
+                       stats.buffers_in_queue,
+                       stats.buffers_in_idle,
+                       stats.buffers_in_ready,
+                       stats.buffers_processed,
+                       stats.buffers_failed);
+               bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       }
+
+       return bcnt;
+}
+
+
+static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
+                               unsigned int count)
+{
+       const char *wptr;
+       unsigned int wlen;
+       unsigned int scnt;
+
+       scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+       if (!scnt) return 0;
+       count -= scnt; buf += scnt;
+       if (!wptr) return 0;
+
+       pvr2_trace(PVR2_TRACE_DEBUGIFC,"debugifc cmd: \"%.*s\"",wlen,wptr);
+       if (debugifc_match_keyword(wptr,wlen,"reset")) {
+               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+               if (!scnt) return -EINVAL;
+               count -= scnt; buf += scnt;
+               if (!wptr) return -EINVAL;
+               if (debugifc_match_keyword(wptr,wlen,"cpu")) {
+                       pvr2_hdw_cpureset_assert(hdw,!0);
+                       pvr2_hdw_cpureset_assert(hdw,0);
+                       return 0;
+               } else if (debugifc_match_keyword(wptr,wlen,"bus")) {
+                       pvr2_hdw_device_reset(hdw);
+               } else if (debugifc_match_keyword(wptr,wlen,"soft")) {
+                       return pvr2_hdw_cmd_powerup(hdw);
+               } else if (debugifc_match_keyword(wptr,wlen,"deep")) {
+                       return pvr2_hdw_cmd_deep_reset(hdw);
+               } else if (debugifc_match_keyword(wptr,wlen,"firmware")) {
+                       return pvr2_upload_firmware2(hdw);
+               } else if (debugifc_match_keyword(wptr,wlen,"decoder")) {
+                       return pvr2_hdw_cmd_decoder_reset(hdw);
+               } else if (debugifc_match_keyword(wptr,wlen,"worker")) {
+                       return pvr2_hdw_untrip(hdw);
+               } else if (debugifc_match_keyword(wptr,wlen,"usbstats")) {
+                       pvr2_stream_get_stats(pvr2_hdw_get_video_stream(hdw),
+                                             NULL, !0);
+                       return 0;
+               }
+               return -EINVAL;
+       } else if (debugifc_match_keyword(wptr,wlen,"cpufw")) {
+               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+               if (!scnt) return -EINVAL;
+               count -= scnt; buf += scnt;
+               if (!wptr) return -EINVAL;
+               if (debugifc_match_keyword(wptr,wlen,"fetch")) {
+                       scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+                       if (scnt && wptr) {
+                               count -= scnt; buf += scnt;
+                               if (debugifc_match_keyword(wptr, wlen,
+                                                          "prom")) {
+                                       pvr2_hdw_cpufw_set_enabled(hdw, 2, !0);
+                               } else if (debugifc_match_keyword(wptr, wlen,
+                                                                 "ram8k")) {
+                                       pvr2_hdw_cpufw_set_enabled(hdw, 0, !0);
+                               } else if (debugifc_match_keyword(wptr, wlen,
+                                                                 "ram16k")) {
+                                       pvr2_hdw_cpufw_set_enabled(hdw, 1, !0);
+                               } else {
+                                       return -EINVAL;
+                               }
+                       }
+                       pvr2_hdw_cpufw_set_enabled(hdw,0,!0);
+                       return 0;
+               } else if (debugifc_match_keyword(wptr,wlen,"done")) {
+                       pvr2_hdw_cpufw_set_enabled(hdw,0,0);
+                       return 0;
+               } else {
+                       return -EINVAL;
+               }
+       } else if (debugifc_match_keyword(wptr,wlen,"gpio")) {
+               int dir_fl = 0;
+               int ret;
+               u32 msk,val;
+               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+               if (!scnt) return -EINVAL;
+               count -= scnt; buf += scnt;
+               if (!wptr) return -EINVAL;
+               if (debugifc_match_keyword(wptr,wlen,"dir")) {
+                       dir_fl = !0;
+               } else if (!debugifc_match_keyword(wptr,wlen,"out")) {
+                       return -EINVAL;
+               }
+               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+               if (!scnt) return -EINVAL;
+               count -= scnt; buf += scnt;
+               if (!wptr) return -EINVAL;
+               ret = debugifc_parse_unsigned_number(wptr,wlen,&msk);
+               if (ret) return ret;
+               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+               if (wptr) {
+                       ret = debugifc_parse_unsigned_number(wptr,wlen,&val);
+                       if (ret) return ret;
+               } else {
+                       val = msk;
+                       msk = 0xffffffff;
+               }
+               if (dir_fl) {
+                       ret = pvr2_hdw_gpio_chg_dir(hdw,msk,val);
+               } else {
+                       ret = pvr2_hdw_gpio_chg_out(hdw,msk,val);
+               }
+               return ret;
+       }
+       pvr2_trace(PVR2_TRACE_DEBUGIFC,
+                  "debugifc failed to recognize cmd: \"%.*s\"",wlen,wptr);
+       return -EINVAL;
+}
+
+
+int pvr2_debugifc_docmd(struct pvr2_hdw *hdw,const char *buf,
+                       unsigned int count)
+{
+       unsigned int bcnt = 0;
+       int ret;
+
+       while (count) {
+               for (bcnt = 0; bcnt < count; bcnt++) {
+                       if (buf[bcnt] == '\n') break;
+               }
+
+               ret = pvr2_debugifc_do1cmd(hdw,buf,bcnt);
+               if (ret < 0) return ret;
+               if (bcnt < count) bcnt++;
+               buf += bcnt;
+               count -= bcnt;
+       }
+
+       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
new file mode 100644 (file)
index 0000000..2f8d467
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_DEBUGIFC_H
+#define __PVRUSB2_DEBUGIFC_H
+
+struct pvr2_hdw;
+
+/* Print general status of driver.  This will also trigger a probe of
+   the USB link.  Unlike print_info(), this one synchronizes with the
+   driver so the information should be self-consistent (but it will
+   hang if the driver is wedged). */
+int pvr2_debugifc_print_info(struct pvr2_hdw *,
+                            char *buf_ptr, unsigned int buf_size);
+
+/* Non-intrusively print some useful debugging info from inside the
+   driver.  This should work even if the driver appears to be
+   wedged. */
+int pvr2_debugifc_print_status(struct pvr2_hdw *,
+                              char *buf_ptr,unsigned int buf_size);
+
+/* Parse a string command into a driver action. */
+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
new file mode 100644 (file)
index 0000000..adc501d
--- /dev/null
@@ -0,0 +1,576 @@
+/*
+ *
+ *
+ *  Copyright (C) 2007 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+
+This source file should encompass ALL per-device type information for the
+driver.  To define a new device, add elements to the pvr2_device_table and
+pvr2_device_desc structures.
+
+*/
+
+#include "pvrusb2-devattr.h"
+#include <linux/usb.h>
+#include <linux/module.h>
+/* This is needed in order to pull in tuner type ids... */
+#include <linux/i2c.h>
+#include <media/tuner.h>
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+#include "pvrusb2-hdw-internal.h"
+#include "lgdt330x.h"
+#include "s5h1409.h"
+#include "s5h1411.h"
+#include "tda10048.h"
+#include "tda18271.h"
+#include "tda8290.h"
+#include "tuner-simple.h"
+#endif
+
+
+/*------------------------------------------------------------------------*/
+/* Hauppauge PVR-USB2 Model 29xxx */
+
+static const struct pvr2_device_client_desc pvr2_cli_29xxx[] = {
+       { .module_id = PVR2_CLIENT_ID_SAA7115 },
+       { .module_id = PVR2_CLIENT_ID_MSP3400 },
+       { .module_id = PVR2_CLIENT_ID_TUNER },
+       { .module_id = PVR2_CLIENT_ID_DEMOD },
+};
+
+#define PVR2_FIRMWARE_29xxx "v4l-pvrusb2-29xxx-01.fw"
+static const char *pvr2_fw1_names_29xxx[] = {
+               PVR2_FIRMWARE_29xxx,
+};
+
+static const struct pvr2_device_desc pvr2_device_29xxx = {
+               .description = "WinTV PVR USB2 Model 29xxx",
+               .shortname = "29xxx",
+               .client_table.lst = pvr2_cli_29xxx,
+               .client_table.cnt = ARRAY_SIZE(pvr2_cli_29xxx),
+               .fx2_firmware.lst = pvr2_fw1_names_29xxx,
+               .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx),
+               .flag_has_hauppauge_rom = !0,
+               .flag_has_analogtuner = !0,
+               .flag_has_fmradio = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+               .ir_scheme = PVR2_IR_SCHEME_29XXX,
+};
+
+
+
+/*------------------------------------------------------------------------*/
+/* Hauppauge PVR-USB2 Model 24xxx */
+
+static const struct pvr2_device_client_desc pvr2_cli_24xxx[] = {
+       { .module_id = PVR2_CLIENT_ID_CX25840 },
+       { .module_id = PVR2_CLIENT_ID_TUNER },
+       { .module_id = PVR2_CLIENT_ID_WM8775 },
+       { .module_id = PVR2_CLIENT_ID_DEMOD },
+};
+
+#define PVR2_FIRMWARE_24xxx "v4l-pvrusb2-24xxx-01.fw"
+static const char *pvr2_fw1_names_24xxx[] = {
+               PVR2_FIRMWARE_24xxx,
+};
+
+static const struct pvr2_device_desc pvr2_device_24xxx = {
+               .description = "WinTV PVR USB2 Model 24xxx",
+               .shortname = "24xxx",
+               .client_table.lst = pvr2_cli_24xxx,
+               .client_table.cnt = ARRAY_SIZE(pvr2_cli_24xxx),
+               .fx2_firmware.lst = pvr2_fw1_names_24xxx,
+               .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_24xxx),
+               .flag_has_cx25840 = !0,
+               .flag_has_wm8775 = !0,
+               .flag_has_hauppauge_rom = !0,
+               .flag_has_analogtuner = !0,
+               .flag_has_fmradio = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+               .ir_scheme = PVR2_IR_SCHEME_24XXX,
+};
+
+
+
+/*------------------------------------------------------------------------*/
+/* GOTVIEW USB2.0 DVD2 */
+
+static const struct pvr2_device_client_desc pvr2_cli_gotview_2[] = {
+       { .module_id = PVR2_CLIENT_ID_CX25840 },
+       { .module_id = PVR2_CLIENT_ID_TUNER },
+       { .module_id = PVR2_CLIENT_ID_DEMOD },
+};
+
+static const struct pvr2_device_desc pvr2_device_gotview_2 = {
+               .description = "Gotview USB 2.0 DVD 2",
+               .shortname = "gv2",
+               .client_table.lst = pvr2_cli_gotview_2,
+               .client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2),
+               .flag_has_cx25840 = !0,
+               .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+               .flag_has_analogtuner = !0,
+               .flag_has_fmradio = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW,
+};
+
+
+
+/*------------------------------------------------------------------------*/
+/* GOTVIEW USB2.0 DVD Deluxe */
+
+/* (same module list as gotview_2) */
+
+static const struct pvr2_device_desc pvr2_device_gotview_2d = {
+               .description = "Gotview USB 2.0 DVD Deluxe",
+               .shortname = "gv2d",
+               .client_table.lst = pvr2_cli_gotview_2,
+               .client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2),
+               .flag_has_cx25840 = !0,
+               .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW,
+};
+
+
+
+/*------------------------------------------------------------------------*/
+/* Terratec Grabster AV400 */
+
+static const struct pvr2_device_client_desc pvr2_cli_av400[] = {
+       { .module_id = PVR2_CLIENT_ID_CX25840 },
+};
+
+static const struct pvr2_device_desc pvr2_device_av400 = {
+               .description = "Terratec Grabster AV400",
+               .shortname = "av400",
+               .flag_is_experimental = 1,
+               .client_table.lst = pvr2_cli_av400,
+               .client_table.cnt = ARRAY_SIZE(pvr2_cli_av400),
+               .flag_has_cx25840 = !0,
+               .flag_has_analogtuner = 0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .signal_routing_scheme = PVR2_ROUTING_SCHEME_AV400,
+};
+
+
+
+/*------------------------------------------------------------------------*/
+/* OnAir Creator */
+
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct lgdt330x_config pvr2_lgdt3303_config = {
+       .demod_address       = 0x0e,
+       .demod_chip          = LGDT3303,
+       .clock_polarity_flip = 1,
+};
+
+static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
+static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap)
+{
+       dvb_attach(simple_tuner_attach, adap->fe,
+                  &adap->channel.hdw->i2c_adap, 0x61,
+                  TUNER_LG_TDVS_H06XF);
+
+       return 0;
+}
+
+static const struct pvr2_dvb_props pvr2_onair_creator_fe_props = {
+       .frontend_attach = pvr2_lgdt3303_attach,
+       .tuner_attach    = pvr2_lgh06xf_attach,
+};
+#endif
+
+static const struct pvr2_device_client_desc pvr2_cli_onair_creator[] = {
+       { .module_id = PVR2_CLIENT_ID_SAA7115 },
+       { .module_id = PVR2_CLIENT_ID_CS53L32A },
+       { .module_id = PVR2_CLIENT_ID_TUNER },
+};
+
+static const struct pvr2_device_desc pvr2_device_onair_creator = {
+               .description = "OnAir Creator Hybrid USB tuner",
+               .shortname = "oac",
+               .client_table.lst = pvr2_cli_onair_creator,
+               .client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_creator),
+               .default_tuner_type = TUNER_LG_TDVS_H06XF,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .flag_digital_requires_cx23416 = !0,
+               .signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR,
+               .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
+               .default_std_mask = V4L2_STD_NTSC_M,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_onair_creator_fe_props,
+#endif
+};
+
+
+
+/*------------------------------------------------------------------------*/
+/* OnAir USB 2.0 */
+
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct lgdt330x_config pvr2_lgdt3302_config = {
+       .demod_address       = 0x0e,
+       .demod_chip          = LGDT3302,
+};
+
+static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
+static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap)
+{
+       dvb_attach(simple_tuner_attach, adap->fe,
+                  &adap->channel.hdw->i2c_adap, 0x61,
+                  TUNER_PHILIPS_FCV1236D);
+
+       return 0;
+}
+
+static const struct pvr2_dvb_props pvr2_onair_usb2_fe_props = {
+       .frontend_attach = pvr2_lgdt3302_attach,
+       .tuner_attach    = pvr2_fcv1236d_attach,
+};
+#endif
+
+static const struct pvr2_device_client_desc pvr2_cli_onair_usb2[] = {
+       { .module_id = PVR2_CLIENT_ID_SAA7115 },
+       { .module_id = PVR2_CLIENT_ID_CS53L32A },
+       { .module_id = PVR2_CLIENT_ID_TUNER },
+};
+
+static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
+               .description = "OnAir USB2 Hybrid USB tuner",
+               .shortname = "oa2",
+               .client_table.lst = pvr2_cli_onair_usb2,
+               .client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_usb2),
+               .default_tuner_type = TUNER_PHILIPS_FCV1236D,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .flag_digital_requires_cx23416 = !0,
+               .signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR,
+               .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
+               .default_std_mask = V4L2_STD_NTSC_M,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_onair_usb2_fe_props,
+#endif
+};
+
+
+
+/*------------------------------------------------------------------------*/
+/* Hauppauge PVR-USB2 Model 73xxx */
+
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct tda10048_config hauppauge_tda10048_config = {
+       .demod_address  = 0x10 >> 1,
+       .output_mode    = TDA10048_PARALLEL_OUTPUT,
+       .fwbulkwritelen = TDA10048_BULKWRITE_50,
+       .inversion      = TDA10048_INVERSION_ON,
+       .dtv6_if_freq_khz = TDA10048_IF_3300,
+       .dtv7_if_freq_khz = TDA10048_IF_3800,
+       .dtv8_if_freq_khz = TDA10048_IF_4300,
+       .clk_freq_khz   = TDA10048_CLK_16000,
+       .disable_gate_access = 1,
+};
+
+static struct tda829x_config tda829x_no_probe = {
+       .probe_tuner = TDA829X_DONT_PROBE,
+};
+
+static struct tda18271_std_map hauppauge_tda18271_dvbt_std_map = {
+        .dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
+                      .if_lvl = 1, .rfagc_top = 0x37, },
+        .dvbt_7   = { .if_freq = 3800, .agc_mode = 3, .std = 5,
+                      .if_lvl = 1, .rfagc_top = 0x37, },
+        .dvbt_8   = { .if_freq = 4300, .agc_mode = 3, .std = 6,
+                      .if_lvl = 1, .rfagc_top = 0x37, },
+};
+
+static struct tda18271_config hauppauge_tda18271_dvb_config = {
+       .std_map = &hauppauge_tda18271_dvbt_std_map,
+       .gate    = TDA18271_GATE_ANALOG,
+       .output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+static int pvr2_tda10048_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(tda10048_attach, &hauppauge_tda10048_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
+static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
+{
+       dvb_attach(tda829x_attach, adap->fe,
+                  &adap->channel.hdw->i2c_adap, 0x42,
+                  &tda829x_no_probe);
+       dvb_attach(tda18271_attach, adap->fe, 0x60,
+                  &adap->channel.hdw->i2c_adap,
+                  &hauppauge_tda18271_dvb_config);
+
+       return 0;
+}
+
+static const struct pvr2_dvb_props pvr2_73xxx_dvb_props = {
+       .frontend_attach = pvr2_tda10048_attach,
+       .tuner_attach    = pvr2_73xxx_tda18271_8295_attach,
+};
+#endif
+
+static const struct pvr2_device_client_desc pvr2_cli_73xxx[] = {
+       { .module_id = PVR2_CLIENT_ID_CX25840 },
+       { .module_id = PVR2_CLIENT_ID_TUNER,
+         .i2c_address_list = "\x42"},
+};
+
+#define PVR2_FIRMWARE_73xxx "v4l-pvrusb2-73xxx-01.fw"
+static const char *pvr2_fw1_names_73xxx[] = {
+               PVR2_FIRMWARE_73xxx,
+};
+
+static const struct pvr2_device_desc pvr2_device_73xxx = {
+               .description = "WinTV HVR-1900 Model 73xxx",
+               .shortname = "73xxx",
+               .client_table.lst = pvr2_cli_73xxx,
+               .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx),
+               .fx2_firmware.lst = pvr2_fw1_names_73xxx,
+               .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_73xxx),
+               .flag_has_cx25840 = !0,
+               .flag_has_hauppauge_rom = !0,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .flag_fx2_16kb = !0,
+               .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
+               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+               .ir_scheme = PVR2_IR_SCHEME_ZILOG,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_73xxx_dvb_props,
+#endif
+};
+
+
+
+/*------------------------------------------------------------------------*/
+/* Hauppauge PVR-USB2 Model 75xxx */
+
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+static struct s5h1409_config pvr2_s5h1409_config = {
+       .demod_address = 0x32 >> 1,
+       .output_mode   = S5H1409_PARALLEL_OUTPUT,
+       .gpio          = S5H1409_GPIO_OFF,
+       .qam_if        = 4000,
+       .inversion     = S5H1409_INVERSION_ON,
+       .status_mode   = S5H1409_DEMODLOCKING,
+};
+
+static struct s5h1411_config pvr2_s5h1411_config = {
+       .output_mode   = S5H1411_PARALLEL_OUTPUT,
+       .gpio          = S5H1411_GPIO_OFF,
+       .vsb_if        = S5H1411_IF_44000,
+       .qam_if        = S5H1411_IF_4000,
+       .inversion     = S5H1411_INVERSION_ON,
+       .status_mode   = S5H1411_DEMODLOCKING,
+};
+
+static struct tda18271_std_map hauppauge_tda18271_std_map = {
+       .atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
+                     .if_lvl = 6, .rfagc_top = 0x37, },
+       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
+                     .if_lvl = 6, .rfagc_top = 0x37, },
+};
+
+static struct tda18271_config hauppauge_tda18271_config = {
+       .std_map = &hauppauge_tda18271_std_map,
+       .gate    = TDA18271_GATE_ANALOG,
+       .output_opt = TDA18271_OUTPUT_LT_OFF,
+};
+
+static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
+static int pvr2_s5h1411_attach(struct pvr2_dvb_adapter *adap)
+{
+       adap->fe = dvb_attach(s5h1411_attach, &pvr2_s5h1411_config,
+                             &adap->channel.hdw->i2c_adap);
+       if (adap->fe)
+               return 0;
+
+       return -EIO;
+}
+
+static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
+{
+       dvb_attach(tda829x_attach, adap->fe,
+                  &adap->channel.hdw->i2c_adap, 0x42,
+                  &tda829x_no_probe);
+       dvb_attach(tda18271_attach, adap->fe, 0x60,
+                  &adap->channel.hdw->i2c_adap,
+                  &hauppauge_tda18271_config);
+
+       return 0;
+}
+
+static const struct pvr2_dvb_props pvr2_750xx_dvb_props = {
+       .frontend_attach = pvr2_s5h1409_attach,
+       .tuner_attach    = pvr2_tda18271_8295_attach,
+};
+
+static const struct pvr2_dvb_props pvr2_751xx_dvb_props = {
+       .frontend_attach = pvr2_s5h1411_attach,
+       .tuner_attach    = pvr2_tda18271_8295_attach,
+};
+#endif
+
+#define PVR2_FIRMWARE_75xxx "v4l-pvrusb2-73xxx-01.fw"
+static const char *pvr2_fw1_names_75xxx[] = {
+               PVR2_FIRMWARE_75xxx,
+};
+
+static const struct pvr2_device_desc pvr2_device_750xx = {
+               .description = "WinTV HVR-1950 Model 750xx",
+               .shortname = "750xx",
+               .client_table.lst = pvr2_cli_73xxx,
+               .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx),
+               .fx2_firmware.lst = pvr2_fw1_names_75xxx,
+               .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
+               .flag_has_cx25840 = !0,
+               .flag_has_hauppauge_rom = !0,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .flag_fx2_16kb = !0,
+               .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
+               .default_std_mask = V4L2_STD_NTSC_M,
+               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+               .ir_scheme = PVR2_IR_SCHEME_ZILOG,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_750xx_dvb_props,
+#endif
+};
+
+static const struct pvr2_device_desc pvr2_device_751xx = {
+               .description = "WinTV HVR-1950 Model 751xx",
+               .shortname = "751xx",
+               .client_table.lst = pvr2_cli_73xxx,
+               .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx),
+               .fx2_firmware.lst = pvr2_fw1_names_75xxx,
+               .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
+               .flag_has_cx25840 = !0,
+               .flag_has_hauppauge_rom = !0,
+               .flag_has_analogtuner = !0,
+               .flag_has_composite = !0,
+               .flag_has_svideo = !0,
+               .flag_fx2_16kb = !0,
+               .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
+               .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
+               .default_std_mask = V4L2_STD_NTSC_M,
+               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
+               .ir_scheme = PVR2_IR_SCHEME_ZILOG,
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+               .dvb_props = &pvr2_751xx_dvb_props,
+#endif
+};
+
+
+
+/*------------------------------------------------------------------------*/
+
+struct usb_device_id pvr2_device_table[] = {
+       { USB_DEVICE(0x2040, 0x2900),
+         .driver_info = (kernel_ulong_t)&pvr2_device_29xxx},
+       { USB_DEVICE(0x2040, 0x2950), /* Logically identical to 2900 */
+         .driver_info = (kernel_ulong_t)&pvr2_device_29xxx},
+       { USB_DEVICE(0x2040, 0x2400),
+         .driver_info = (kernel_ulong_t)&pvr2_device_24xxx},
+       { USB_DEVICE(0x1164, 0x0622),
+         .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2},
+       { USB_DEVICE(0x1164, 0x0602),
+         .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2d},
+       { USB_DEVICE(0x11ba, 0x1003),
+         .driver_info = (kernel_ulong_t)&pvr2_device_onair_creator},
+       { USB_DEVICE(0x11ba, 0x1001),
+         .driver_info = (kernel_ulong_t)&pvr2_device_onair_usb2},
+       { USB_DEVICE(0x2040, 0x7300),
+         .driver_info = (kernel_ulong_t)&pvr2_device_73xxx},
+       { USB_DEVICE(0x2040, 0x7500),
+         .driver_info = (kernel_ulong_t)&pvr2_device_750xx},
+       { USB_DEVICE(0x2040, 0x7501),
+         .driver_info = (kernel_ulong_t)&pvr2_device_751xx},
+       { USB_DEVICE(0x0ccd, 0x0039),
+         .driver_info = (kernel_ulong_t)&pvr2_device_av400},
+       { }
+};
+
+MODULE_DEVICE_TABLE(usb, pvr2_device_table);
+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
new file mode 100644 (file)
index 0000000..273c8d4
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_DEVATTR_H
+#define __PVRUSB2_DEVATTR_H
+
+#include <linux/mod_devicetable.h>
+#include <linux/videodev2.h>
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+#include "pvrusb2-dvb.h"
+#endif
+
+/*
+
+  This header defines structures used to describe attributes of a device.
+
+*/
+
+
+#define PVR2_CLIENT_ID_NULL 0
+#define PVR2_CLIENT_ID_MSP3400 1
+#define PVR2_CLIENT_ID_CX25840 2
+#define PVR2_CLIENT_ID_SAA7115 3
+#define PVR2_CLIENT_ID_TUNER 4
+#define PVR2_CLIENT_ID_CS53L32A 5
+#define PVR2_CLIENT_ID_WM8775 6
+#define PVR2_CLIENT_ID_DEMOD 7
+
+struct pvr2_device_client_desc {
+       /* One ovr PVR2_CLIENT_ID_xxxx */
+       unsigned char module_id;
+
+       /* Null-terminated array of I2C addresses to try in order
+          initialize the module.  It's safe to make this null terminated
+          since we're never going to encounter an i2c device with an
+          address of zero.  If this is a null pointer or zero-length,
+          then no I2C addresses have been specified, in which case we'll
+          try some compiled in defaults for now. */
+       unsigned char *i2c_address_list;
+};
+
+struct pvr2_device_client_table {
+       const struct pvr2_device_client_desc *lst;
+       unsigned char cnt;
+};
+
+
+struct pvr2_string_table {
+       const char **lst;
+       unsigned int cnt;
+};
+
+#define PVR2_ROUTING_SCHEME_HAUPPAUGE 0
+#define PVR2_ROUTING_SCHEME_GOTVIEW 1
+#define PVR2_ROUTING_SCHEME_ONAIR 2
+#define PVR2_ROUTING_SCHEME_AV400 3
+
+#define PVR2_DIGITAL_SCHEME_NONE 0
+#define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1
+#define PVR2_DIGITAL_SCHEME_ONAIR 2
+
+#define PVR2_LED_SCHEME_NONE 0
+#define PVR2_LED_SCHEME_HAUPPAUGE 1
+
+#define PVR2_IR_SCHEME_NONE 0
+#define PVR2_IR_SCHEME_24XXX 1 /* FX2-controlled IR */
+#define PVR2_IR_SCHEME_ZILOG 2 /* HVR-1950 style (must be taken out of reset) */
+#define PVR2_IR_SCHEME_24XXX_MCE 3 /* 24xxx MCE device */
+#define PVR2_IR_SCHEME_29XXX 4 /* Original 29xxx device */
+
+/* This describes a particular hardware type (except for the USB device ID
+   which must live in a separate structure due to environmental
+   constraints).  See the top of pvrusb2-hdw.c for where this is
+   instantiated. */
+struct pvr2_device_desc {
+       /* Single line text description of hardware */
+       const char *description;
+
+       /* Single token identifier for hardware */
+       const char *shortname;
+
+       /* List of additional client modules we need to load */
+       struct pvr2_string_table client_modules;
+
+       /* List of defined client modules we need to load */
+       struct pvr2_device_client_table client_table;
+
+       /* List of FX2 firmware file names we should search; if empty then
+          FX2 firmware check / load is skipped and we assume the device
+          was initialized from internal ROM. */
+       struct pvr2_string_table fx2_firmware;
+
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+       /* callback functions to handle attachment of digital tuner & demod */
+       const struct pvr2_dvb_props *dvb_props;
+
+#endif
+       /* Initial standard bits to use for this device, if not zero.
+          Anything set here is also implied as an available standard.
+          Note: This is ignored if overridden on the module load line via
+          the video_std module option. */
+       v4l2_std_id default_std_mask;
+
+       /* V4L tuner type ID to use with this device (only used if the
+          driver could not discover the type any other way). */
+       int default_tuner_type;
+
+       /* Signal routing scheme used by device, contains one of
+          PVR2_ROUTING_SCHEME_XXX.  Schemes have to be defined as we
+          encounter them.  This is an arbitrary integer scheme id; its
+          meaning is contained entirely within the driver and is
+          interpreted by logic which must send commands to the chip-level
+          drivers (search for things which touch this field). */
+       unsigned char signal_routing_scheme;
+
+       /* Indicates scheme for controlling device's LED (if any).  The
+          driver will turn on the LED when streaming is underway.  This
+          contains one of PVR2_LED_SCHEME_XXX. */
+       unsigned char led_scheme;
+
+       /* Control scheme to use if there is a digital tuner.  This
+          contains one of PVR2_DIGITAL_SCHEME_XXX.  This is an arbitrary
+          integer scheme id; its meaning is contained entirely within the
+          driver and is interpreted by logic which must control the
+          streaming pathway (search for things which touch this field). */
+       unsigned char digital_control_scheme;
+
+       /* If set, we don't bother trying to load cx23416 firmware. */
+       unsigned int flag_skip_cx23416_firmware:1;
+
+       /* If set, the encoder must be healthy in order for digital mode to
+          work (otherwise we assume that digital streaming will work even
+          if we fail to locate firmware for the encoder).  If the device
+          doesn't support digital streaming then this flag has no
+          effect. */
+       unsigned int flag_digital_requires_cx23416:1;
+
+       /* Device has a hauppauge eeprom which we can interrogate. */
+       unsigned int flag_has_hauppauge_rom:1;
+
+       /* Device does not require a powerup command to be issued. */
+       unsigned int flag_no_powerup:1;
+
+       /* Device has a cx25840 - this enables special additional logic to
+          handle it. */
+       unsigned int flag_has_cx25840:1;
+
+       /* Device has a wm8775 - this enables special additional logic to
+          ensure that it is found. */
+       unsigned int flag_has_wm8775:1;
+
+       /* Indicate IR scheme of hardware.  If not set, then it is assumed
+          that IR can work without any help from the driver. */
+       unsigned int ir_scheme:3;
+
+       /* These bits define which kinds of sources the device can handle.
+          Note: Digital tuner presence is inferred by the
+          digital_control_scheme enumeration. */
+       unsigned int flag_has_fmradio:1;       /* Has FM radio receiver */
+       unsigned int flag_has_analogtuner:1;   /* Has analog tuner */
+       unsigned int flag_has_composite:1;     /* Has composite input */
+       unsigned int flag_has_svideo:1;        /* Has s-video input */
+       unsigned int flag_fx2_16kb:1;          /* 16KB FX2 firmware OK here */
+
+       /* If this driver is considered experimental, i.e. not all aspects
+          are working correctly and/or it is untested, mark that fact
+          with this flag. */
+       unsigned int flag_is_experimental:1;
+};
+
+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-dvb.c b/drivers/media/usb/pvrusb2/pvrusb2-dvb.c
new file mode 100644 (file)
index 0000000..8c95793
--- /dev/null
@@ -0,0 +1,435 @@
+/*
+ *  pvrusb2-dvb.c - linux-dvb api interface to the pvrusb2 driver.
+ *
+ *  Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include "dvbdev.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-io.h"
+#include "pvrusb2-dvb.h"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap)
+{
+       int ret;
+       unsigned int count;
+       struct pvr2_buffer *bp;
+       struct pvr2_stream *stream;
+
+       pvr2_trace(PVR2_TRACE_DVB_FEED, "dvb feed thread started");
+       set_freezable();
+
+       stream = adap->channel.stream->stream;
+
+       for (;;) {
+               if (kthread_should_stop()) break;
+
+               /* Not sure about this... */
+               try_to_freeze();
+
+               bp = pvr2_stream_get_ready_buffer(stream);
+               if (bp != NULL) {
+                       count = pvr2_buffer_get_count(bp);
+                       if (count) {
+                               dvb_dmx_swfilter(
+                                       &adap->demux,
+                                       adap->buffer_storage[
+                                           pvr2_buffer_get_id(bp)],
+                                       count);
+                       } else {
+                               ret = pvr2_buffer_get_status(bp);
+                               if (ret < 0) break;
+                       }
+                       ret = pvr2_buffer_queue(bp);
+                       if (ret < 0) break;
+
+                       /* Since we know we did something to a buffer,
+                          just go back and try again.  No point in
+                          blocking unless we really ran out of
+                          buffers to process. */
+                       continue;
+               }
+
+
+               /* Wait until more buffers become available or we're
+                  told not to wait any longer. */
+               ret = wait_event_interruptible(
+                   adap->buffer_wait_data,
+                   (pvr2_stream_get_ready_count(stream) > 0) ||
+                   kthread_should_stop());
+               if (ret < 0) break;
+       }
+
+       /* If we get here and ret is < 0, then an error has occurred.
+          Probably would be a good idea to communicate that to DVB core... */
+
+       pvr2_trace(PVR2_TRACE_DVB_FEED, "dvb feed thread stopped");
+
+       return 0;
+}
+
+static int pvr2_dvb_feed_thread(void *data)
+{
+       int stat = pvr2_dvb_feed_func(data);
+       /* from videobuf-dvb.c: */
+       while (!kthread_should_stop()) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule();
+       }
+       return stat;
+}
+
+static void pvr2_dvb_notify(struct pvr2_dvb_adapter *adap)
+{
+       wake_up(&adap->buffer_wait_data);
+}
+
+static void pvr2_dvb_stream_end(struct pvr2_dvb_adapter *adap)
+{
+       unsigned int idx;
+       struct pvr2_stream *stream;
+
+       if (adap->thread) {
+               kthread_stop(adap->thread);
+               adap->thread = NULL;
+       }
+
+       if (adap->channel.stream) {
+               stream = adap->channel.stream->stream;
+       } else {
+               stream = NULL;
+       }
+       if (stream) {
+               pvr2_hdw_set_streaming(adap->channel.hdw, 0);
+               pvr2_stream_set_callback(stream, NULL, NULL);
+               pvr2_stream_kill(stream);
+               pvr2_stream_set_buffer_count(stream, 0);
+               pvr2_channel_claim_stream(&adap->channel, NULL);
+       }
+
+       if (adap->stream_run) {
+               for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
+                       if (!(adap->buffer_storage[idx])) continue;
+                       kfree(adap->buffer_storage[idx]);
+                       adap->buffer_storage[idx] = NULL;
+               }
+               adap->stream_run = 0;
+       }
+}
+
+static int pvr2_dvb_stream_do_start(struct pvr2_dvb_adapter *adap)
+{
+       struct pvr2_context *pvr = adap->channel.mc_head;
+       unsigned int idx;
+       int ret;
+       struct pvr2_buffer *bp;
+       struct pvr2_stream *stream = NULL;
+
+       if (adap->stream_run) return -EIO;
+
+       ret = pvr2_channel_claim_stream(&adap->channel, &pvr->video_stream);
+       /* somebody else already has the stream */
+       if (ret < 0) return ret;
+
+       stream = adap->channel.stream->stream;
+
+       for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
+               adap->buffer_storage[idx] = kmalloc(PVR2_DVB_BUFFER_SIZE,
+                                                   GFP_KERNEL);
+               if (!(adap->buffer_storage[idx])) return -ENOMEM;
+       }
+
+       pvr2_stream_set_callback(pvr->video_stream.stream,
+                                (pvr2_stream_callback) pvr2_dvb_notify, adap);
+
+       ret = pvr2_stream_set_buffer_count(stream, PVR2_DVB_BUFFER_COUNT);
+       if (ret < 0) return ret;
+
+       for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
+               bp = pvr2_stream_get_buffer(stream, idx);
+               pvr2_buffer_set_buffer(bp,
+                                      adap->buffer_storage[idx],
+                                      PVR2_DVB_BUFFER_SIZE);
+       }
+
+       ret = pvr2_hdw_set_streaming(adap->channel.hdw, 1);
+       if (ret < 0) return ret;
+
+       while ((bp = pvr2_stream_get_idle_buffer(stream)) != NULL) {
+               ret = pvr2_buffer_queue(bp);
+               if (ret < 0) return ret;
+       }
+
+       adap->thread = kthread_run(pvr2_dvb_feed_thread, adap, "pvrusb2-dvb");
+
+       if (IS_ERR(adap->thread)) {
+               ret = PTR_ERR(adap->thread);
+               adap->thread = NULL;
+               return ret;
+       }
+
+       adap->stream_run = !0;
+
+       return 0;
+}
+
+static int pvr2_dvb_stream_start(struct pvr2_dvb_adapter *adap)
+{
+       int ret = pvr2_dvb_stream_do_start(adap);
+       if (ret < 0) pvr2_dvb_stream_end(adap);
+       return ret;
+}
+
+static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
+{
+       struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv;
+       int ret = 0;
+
+       if (adap == NULL) return -ENODEV;
+
+       mutex_lock(&adap->lock);
+       do {
+               if (onoff) {
+                       if (!adap->feedcount) {
+                               pvr2_trace(PVR2_TRACE_DVB_FEED,
+                                          "start feeding demux");
+                               ret = pvr2_dvb_stream_start(adap);
+                               if (ret < 0) break;
+                       }
+                       (adap->feedcount)++;
+               } else if (adap->feedcount > 0) {
+                       (adap->feedcount)--;
+                       if (!adap->feedcount) {
+                               pvr2_trace(PVR2_TRACE_DVB_FEED,
+                                          "stop feeding demux");
+                               pvr2_dvb_stream_end(adap);
+                       }
+               }
+       } while (0);
+       mutex_unlock(&adap->lock);
+
+       return ret;
+}
+
+static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       pvr2_trace(PVR2_TRACE_DVB_FEED, "start pid: 0x%04x", dvbdmxfeed->pid);
+       return pvr2_dvb_ctrl_feed(dvbdmxfeed, 1);
+}
+
+static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       pvr2_trace(PVR2_TRACE_DVB_FEED, "stop pid: 0x%04x", dvbdmxfeed->pid);
+       return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0);
+}
+
+static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+       struct pvr2_dvb_adapter *adap = fe->dvb->priv;
+       return pvr2_channel_limit_inputs(
+           &adap->channel,
+           (acquire ? (1 << PVR2_CVAL_INPUT_DTV) : 0));
+}
+
+static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap)
+{
+       int ret;
+
+       ret = dvb_register_adapter(&adap->dvb_adap, "pvrusb2-dvb",
+                                  THIS_MODULE/*&hdw->usb_dev->owner*/,
+                                  &adap->channel.hdw->usb_dev->dev,
+                                  adapter_nr);
+       if (ret < 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "dvb_register_adapter failed: error %d", ret);
+               goto err;
+       }
+       adap->dvb_adap.priv = adap;
+
+       adap->demux.dmx.capabilities = DMX_TS_FILTERING |
+                                      DMX_SECTION_FILTERING |
+                                      DMX_MEMORY_BASED_FILTERING;
+       adap->demux.priv             = adap;
+       adap->demux.filternum        = 256;
+       adap->demux.feednum          = 256;
+       adap->demux.start_feed       = pvr2_dvb_start_feed;
+       adap->demux.stop_feed        = pvr2_dvb_stop_feed;
+       adap->demux.write_to_decoder = NULL;
+
+       ret = dvb_dmx_init(&adap->demux);
+       if (ret < 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "dvb_dmx_init failed: error %d", ret);
+               goto err_dmx;
+       }
+
+       adap->dmxdev.filternum       = adap->demux.filternum;
+       adap->dmxdev.demux           = &adap->demux.dmx;
+       adap->dmxdev.capabilities    = 0;
+
+       ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
+       if (ret < 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "dvb_dmxdev_init failed: error %d", ret);
+               goto err_dmx_dev;
+       }
+
+       dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
+
+       return 0;
+
+err_dmx_dev:
+       dvb_dmx_release(&adap->demux);
+err_dmx:
+       dvb_unregister_adapter(&adap->dvb_adap);
+err:
+       return ret;
+}
+
+static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap)
+{
+       pvr2_trace(PVR2_TRACE_INFO, "unregistering DVB devices");
+       dvb_net_release(&adap->dvb_net);
+       adap->demux.dmx.close(&adap->demux.dmx);
+       dvb_dmxdev_release(&adap->dmxdev);
+       dvb_dmx_release(&adap->demux);
+       dvb_unregister_adapter(&adap->dvb_adap);
+       return 0;
+}
+
+static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
+{
+       struct pvr2_hdw *hdw = adap->channel.hdw;
+       const struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props;
+       int ret = 0;
+
+       if (dvb_props == NULL) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS, "fe_props not defined!");
+               return -EINVAL;
+       }
+
+       ret = pvr2_channel_limit_inputs(
+           &adap->channel,
+           (1 << PVR2_CVAL_INPUT_DTV));
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "failed to grab control of dtv input (code=%d)",
+                   ret);
+               return ret;
+       }
+
+       if (dvb_props->frontend_attach == NULL) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "frontend_attach not defined!");
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
+
+               if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "frontend registration failed!");
+                       dvb_frontend_detach(adap->fe);
+                       adap->fe = NULL;
+                       ret = -ENODEV;
+                       goto done;
+               }
+
+               if (dvb_props->tuner_attach)
+                       dvb_props->tuner_attach(adap);
+
+               if (adap->fe->ops.analog_ops.standby)
+                       adap->fe->ops.analog_ops.standby(adap->fe);
+
+               /* Ensure all frontends negotiate bus access */
+               adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
+
+       } else {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "no frontend was attached!");
+               ret = -ENODEV;
+               return ret;
+       }
+
+ done:
+       pvr2_channel_limit_inputs(&adap->channel, 0);
+       return ret;
+}
+
+static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap)
+{
+       if (adap->fe != NULL) {
+               dvb_unregister_frontend(adap->fe);
+               dvb_frontend_detach(adap->fe);
+       }
+       return 0;
+}
+
+static void pvr2_dvb_destroy(struct pvr2_dvb_adapter *adap)
+{
+       pvr2_dvb_stream_end(adap);
+       pvr2_dvb_frontend_exit(adap);
+       pvr2_dvb_adapter_exit(adap);
+       pvr2_channel_done(&adap->channel);
+       kfree(adap);
+}
+
+static void pvr2_dvb_internal_check(struct pvr2_channel *chp)
+{
+       struct pvr2_dvb_adapter *adap;
+       adap = container_of(chp, struct pvr2_dvb_adapter, channel);
+       if (!adap->channel.mc_head->disconnect_flag) return;
+       pvr2_dvb_destroy(adap);
+}
+
+struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr)
+{
+       int ret = 0;
+       struct pvr2_dvb_adapter *adap;
+       if (!pvr->hdw->hdw_desc->dvb_props) {
+               /* Device lacks a digital interface so don't set up
+                  the DVB side of the driver either.  For now. */
+               return NULL;
+       }
+       adap = kzalloc(sizeof(*adap), GFP_KERNEL);
+       if (!adap) return adap;
+       pvr2_channel_init(&adap->channel, pvr);
+       adap->channel.check_func = pvr2_dvb_internal_check;
+       init_waitqueue_head(&adap->buffer_wait_data);
+       mutex_init(&adap->lock);
+       ret = pvr2_dvb_adapter_init(adap);
+       if (ret < 0) goto fail1;
+       ret = pvr2_dvb_frontend_init(adap);
+       if (ret < 0) goto fail2;
+       return adap;
+
+fail2:
+       pvr2_dvb_adapter_exit(adap);
+fail1:
+       pvr2_channel_done(&adap->channel);
+       return NULL;
+}
+
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-dvb.h b/drivers/media/usb/pvrusb2/pvrusb2-dvb.h
new file mode 100644 (file)
index 0000000..884ff91
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __PVRUSB2_DVB_H__
+#define __PVRUSB2_DVB_H__
+
+#include "dvb_frontend.h"
+#include "dvb_demux.h"
+#include "dvb_net.h"
+#include "dmxdev.h"
+#include "pvrusb2-context.h"
+
+#define PVR2_DVB_BUFFER_COUNT 32
+#define PVR2_DVB_BUFFER_SIZE PAGE_ALIGN(0x4000)
+
+struct pvr2_dvb_adapter {
+       struct pvr2_channel     channel;
+
+       struct dvb_adapter      dvb_adap;
+       struct dmxdev           dmxdev;
+       struct dvb_demux        demux;
+       struct dvb_net          dvb_net;
+       struct dvb_frontend     *fe;
+
+       int                     feedcount;
+       int                     max_feed_count;
+
+       struct task_struct      *thread;
+       struct mutex            lock;
+
+       unsigned int            stream_run:1;
+
+       wait_queue_head_t       buffer_wait_data;
+       char                    *buffer_storage[PVR2_DVB_BUFFER_COUNT];
+};
+
+struct pvr2_dvb_props {
+       int (*frontend_attach) (struct pvr2_dvb_adapter *);
+       int (*tuner_attach) (struct pvr2_dvb_adapter *);
+};
+
+struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr);
+
+#endif /* __PVRUSB2_DVB_H__ */
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c b/drivers/media/usb/pvrusb2/pvrusb2-eeprom.c
new file mode 100644 (file)
index 0000000..9515f3a
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/slab.h>
+#include "pvrusb2-eeprom.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+
+#define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__)
+
+
+
+/*
+
+   Read and analyze data in the eeprom.  Use tveeprom to figure out
+   the packet structure, since this is another Hauppauge device and
+   internally it has a family resemblance to ivtv-type devices
+
+*/
+
+#include <media/tveeprom.h>
+
+/* We seem to only be interested in the last 128 bytes of the EEPROM */
+#define EEPROM_SIZE 128
+
+/* Grab EEPROM contents, needed for direct method. */
+static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw)
+{
+       struct i2c_msg msg[2];
+       u8 *eeprom;
+       u8 iadd[2];
+       u8 addr;
+       u16 eepromSize;
+       unsigned int offs;
+       int ret;
+       int mode16 = 0;
+       unsigned pcnt,tcnt;
+       eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL);
+       if (!eeprom) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Failed to allocate memory"
+                          " required to read eeprom");
+               return NULL;
+       }
+
+       trace_eeprom("Value for eeprom addr from controller was 0x%x",
+                    hdw->eeprom_addr);
+       addr = hdw->eeprom_addr;
+       /* Seems that if the high bit is set, then the *real* eeprom
+          address is shifted right now bit position (noticed this in
+          newer PVR USB2 hardware) */
+       if (addr & 0x80) addr >>= 1;
+
+       /* FX2 documentation states that a 16bit-addressed eeprom is
+          expected if the I2C address is an odd number (yeah, this is
+          strange but it's what they do) */
+       mode16 = (addr & 1);
+       eepromSize = (mode16 ? 4096 : 256);
+       trace_eeprom("Examining %d byte eeprom at location 0x%x"
+                    " using %d bit addressing",eepromSize,addr,
+                    mode16 ? 16 : 8);
+
+       msg[0].addr = addr;
+       msg[0].flags = 0;
+       msg[0].len = mode16 ? 2 : 1;
+       msg[0].buf = iadd;
+       msg[1].addr = addr;
+       msg[1].flags = I2C_M_RD;
+
+       /* We have to do the actual eeprom data fetch ourselves, because
+          (1) we're only fetching part of the eeprom, and (2) if we were
+          getting the whole thing our I2C driver can't grab it in one
+          pass - which is what tveeprom is otherwise going to attempt */
+       memset(eeprom,0,EEPROM_SIZE);
+       for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) {
+               pcnt = 16;
+               if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt;
+               offs = tcnt + (eepromSize - EEPROM_SIZE);
+               if (mode16) {
+                       iadd[0] = offs >> 8;
+                       iadd[1] = offs;
+               } else {
+                       iadd[0] = offs;
+               }
+               msg[1].len = pcnt;
+               msg[1].buf = eeprom+tcnt;
+               if ((ret = i2c_transfer(&hdw->i2c_adap,
+                                       msg,ARRAY_SIZE(msg))) != 2) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "eeprom fetch set offs err=%d",ret);
+                       kfree(eeprom);
+                       return NULL;
+               }
+       }
+       return eeprom;
+}
+
+
+/* Directly call eeprom analysis function within tveeprom. */
+int pvr2_eeprom_analyze(struct pvr2_hdw *hdw)
+{
+       u8 *eeprom;
+       struct tveeprom tvdata;
+
+       memset(&tvdata,0,sizeof(tvdata));
+
+       eeprom = pvr2_eeprom_fetch(hdw);
+       if (!eeprom) return -EINVAL;
+
+       {
+               struct i2c_client fake_client;
+               /* Newer version expects a useless client interface */
+               fake_client.addr = hdw->eeprom_addr;
+               fake_client.adapter = &hdw->i2c_adap;
+               tveeprom_hauppauge_analog(&fake_client,&tvdata,eeprom);
+       }
+
+       trace_eeprom("eeprom assumed v4l tveeprom module");
+       trace_eeprom("eeprom direct call results:");
+       trace_eeprom("has_radio=%d",tvdata.has_radio);
+       trace_eeprom("tuner_type=%d",tvdata.tuner_type);
+       trace_eeprom("tuner_formats=0x%x",tvdata.tuner_formats);
+       trace_eeprom("audio_processor=%d",tvdata.audio_processor);
+       trace_eeprom("model=%d",tvdata.model);
+       trace_eeprom("revision=%d",tvdata.revision);
+       trace_eeprom("serial_number=%d",tvdata.serial_number);
+       trace_eeprom("rev_str=%s",tvdata.rev_str);
+       hdw->tuner_type = tvdata.tuner_type;
+       hdw->tuner_updated = !0;
+       hdw->serial_number = tvdata.serial_number;
+       hdw->std_mask_eeprom = tvdata.tuner_formats;
+
+       kfree(eeprom);
+
+       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
new file mode 100644 (file)
index 0000000..cca3216
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_EEPROM_H
+#define __PVRUSB2_EEPROM_H
+
+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
new file mode 100644 (file)
index 0000000..e046fda
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/device.h>   // for linux/firmware.h
+#include <linux/firmware.h>
+#include "pvrusb2-util.h"
+#include "pvrusb2-encoder.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-fx2-cmd.h"
+
+
+
+/* Firmware mailbox flags - definitions found from ivtv */
+#define IVTV_MBOX_FIRMWARE_DONE 0x00000004
+#define IVTV_MBOX_DRIVER_DONE 0x00000002
+#define IVTV_MBOX_DRIVER_BUSY 0x00000001
+
+#define MBOX_BASE 0x44
+
+
+static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
+                                   unsigned int offs,
+                                   const u32 *data, unsigned int dlen)
+{
+       unsigned int idx,addr;
+       unsigned int bAddr;
+       int ret;
+       unsigned int chunkCnt;
+
+       /*
+
+       Format: First byte must be 0x01.  Remaining 32 bit words are
+       spread out into chunks of 7 bytes each, with the first 4 bytes
+       being the data word (little endian), and the next 3 bytes
+       being the address where that data word is to be written (big
+       endian).  Repeat request for additional words, with offset
+       adjusted accordingly.
+
+       */
+       while (dlen) {
+               chunkCnt = 8;
+               if (chunkCnt > dlen) chunkCnt = dlen;
+               memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
+               bAddr = 0;
+               hdw->cmd_buffer[bAddr++] = FX2CMD_MEM_WRITE_DWORD;
+               for (idx = 0; idx < chunkCnt; idx++) {
+                       addr = idx + offs;
+                       hdw->cmd_buffer[bAddr+6] = (addr & 0xffu);
+                       hdw->cmd_buffer[bAddr+5] = ((addr>>8) & 0xffu);
+                       hdw->cmd_buffer[bAddr+4] = ((addr>>16) & 0xffu);
+                       PVR2_DECOMPOSE_LE(hdw->cmd_buffer, bAddr,data[idx]);
+                       bAddr += 7;
+               }
+               ret = pvr2_send_request(hdw,
+                                       hdw->cmd_buffer,1+(chunkCnt*7),
+                                       NULL,0);
+               if (ret) return ret;
+               data += chunkCnt;
+               dlen -= chunkCnt;
+               offs += chunkCnt;
+       }
+
+       return 0;
+}
+
+
+static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,
+                                  unsigned int offs,
+                                  u32 *data, unsigned int dlen)
+{
+       unsigned int idx;
+       int ret;
+       unsigned int chunkCnt;
+
+       /*
+
+       Format: First byte must be 0x02 (status check) or 0x28 (read
+       back block of 32 bit words).  Next 6 bytes must be zero,
+       followed by a single byte of MBOX_BASE+offset for portion to
+       be read.  Returned data is packed set of 32 bits words that
+       were read.
+
+       */
+
+       while (dlen) {
+               chunkCnt = 16;
+               if (chunkCnt > dlen) chunkCnt = dlen;
+               if (chunkCnt < 16) chunkCnt = 1;
+               hdw->cmd_buffer[0] =
+                       ((chunkCnt == 1) ?
+                        FX2CMD_MEM_READ_DWORD : FX2CMD_MEM_READ_64BYTES);
+               hdw->cmd_buffer[1] = 0;
+               hdw->cmd_buffer[2] = 0;
+               hdw->cmd_buffer[3] = 0;
+               hdw->cmd_buffer[4] = 0;
+               hdw->cmd_buffer[5] = ((offs>>16) & 0xffu);
+               hdw->cmd_buffer[6] = ((offs>>8) & 0xffu);
+               hdw->cmd_buffer[7] = (offs & 0xffu);
+               ret = pvr2_send_request(hdw,
+                                       hdw->cmd_buffer,8,
+                                       hdw->cmd_buffer,
+                                       (chunkCnt == 1 ? 4 : 16 * 4));
+               if (ret) return ret;
+
+               for (idx = 0; idx < chunkCnt; idx++) {
+                       data[idx] = PVR2_COMPOSE_LE(hdw->cmd_buffer,idx*4);
+               }
+               data += chunkCnt;
+               dlen -= chunkCnt;
+               offs += chunkCnt;
+       }
+
+       return 0;
+}
+
+
+/* This prototype is set up to be compatible with the
+   cx2341x_mbox_func prototype in cx2341x.h, which should be in
+   kernels 2.6.18 or later.  We do this so that we can enable
+   cx2341x.ko to write to our encoder (by handing it a pointer to this
+   function).  For earlier kernels this doesn't really matter. */
+static int pvr2_encoder_cmd(void *ctxt,
+                           u32 cmd,
+                           int arg_cnt_send,
+                           int arg_cnt_recv,
+                           u32 *argp)
+{
+       unsigned int poll_count;
+       unsigned int try_count = 0;
+       int retry_flag;
+       int ret = 0;
+       unsigned int idx;
+       /* These sizes look to be limited by the FX2 firmware implementation */
+       u32 wrData[16];
+       u32 rdData[16];
+       struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt;
+
+
+       /*
+
+       The encoder seems to speak entirely using blocks 32 bit words.
+       In ivtv driver terms, this is a mailbox at MBOX_BASE which we
+       populate with data and watch what the hardware does with it.
+       The first word is a set of flags used to control the
+       transaction, the second word is the command to execute, the
+       third byte is zero (ivtv driver suggests that this is some
+       kind of return value), and the fourth byte is a specified
+       timeout (windows driver always uses 0x00060000 except for one
+       case when it is zero).  All successive words are the argument
+       words for the command.
+
+       First, write out the entire set of words, with the first word
+       being zero.
+
+       Next, write out just the first word again, but set it to
+       IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which
+       probably means "go").
+
+       Next, read back the return count words.  Check the first word,
+       which should have IVTV_MBOX_FIRMWARE_DONE set.  If however
+       that bit is not set, then the command isn't done so repeat the
+       read until it is set.
+
+       Finally, write out just the first word again, but set it to
+       0x0 this time (which probably means "idle").
+
+       */
+
+       if (arg_cnt_send > (ARRAY_SIZE(wrData) - 4)) {
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "Failed to write cx23416 command"
+                       " - too many input arguments"
+                       " (was given %u limit %lu)",
+                       arg_cnt_send, (long unsigned) ARRAY_SIZE(wrData) - 4);
+               return -EINVAL;
+       }
+
+       if (arg_cnt_recv > (ARRAY_SIZE(rdData) - 4)) {
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "Failed to write cx23416 command"
+                       " - too many return arguments"
+                       " (was given %u limit %lu)",
+                       arg_cnt_recv, (long unsigned) ARRAY_SIZE(rdData) - 4);
+               return -EINVAL;
+       }
+
+
+       LOCK_TAKE(hdw->ctl_lock); do {
+
+               if (!hdw->state_encoder_ok) {
+                       ret = -EIO;
+                       break;
+               }
+
+               retry_flag = 0;
+               try_count++;
+               ret = 0;
+               wrData[0] = 0;
+               wrData[1] = cmd;
+               wrData[2] = 0;
+               wrData[3] = 0x00060000;
+               for (idx = 0; idx < arg_cnt_send; idx++) {
+                       wrData[idx+4] = argp[idx];
+               }
+               for (; idx < ARRAY_SIZE(wrData) - 4; idx++) {
+                       wrData[idx+4] = 0;
+               }
+
+               ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,idx);
+               if (ret) break;
+               wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
+               ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
+               if (ret) break;
+               poll_count = 0;
+               while (1) {
+                       poll_count++;
+                       ret = pvr2_encoder_read_words(hdw,MBOX_BASE,rdData,
+                                                     arg_cnt_recv+4);
+                       if (ret) {
+                               break;
+                       }
+                       if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
+                               break;
+                       }
+                       if (rdData[0] && (poll_count < 1000)) continue;
+                       if (!rdData[0]) {
+                               retry_flag = !0;
+                               pvr2_trace(
+                                       PVR2_TRACE_ERROR_LEGS,
+                                       "Encoder timed out waiting for us"
+                                       "; arranging to retry");
+                       } else {
+                               pvr2_trace(
+                                       PVR2_TRACE_ERROR_LEGS,
+                                       "***WARNING*** device's encoder"
+                                       " appears to be stuck"
+                                       " (status=0x%08x)",rdData[0]);
+                       }
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "Encoder command: 0x%02x",cmd);
+                       for (idx = 4; idx < arg_cnt_send; idx++) {
+                               pvr2_trace(
+                                       PVR2_TRACE_ERROR_LEGS,
+                                       "Encoder arg%d: 0x%08x",
+                                       idx-3,wrData[idx]);
+                       }
+                       ret = -EBUSY;
+                       break;
+               }
+               if (retry_flag) {
+                       if (try_count < 20) continue;
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "Too many retries...");
+                       ret = -EBUSY;
+               }
+               if (ret) {
+                       del_timer_sync(&hdw->encoder_run_timer);
+                       hdw->state_encoder_ok = 0;
+                       pvr2_trace(PVR2_TRACE_STBITS,
+                                  "State bit %s <-- %s",
+                                  "state_encoder_ok",
+                                  (hdw->state_encoder_ok ? "true" : "false"));
+                       if (hdw->state_encoder_runok) {
+                               hdw->state_encoder_runok = 0;
+                               pvr2_trace(PVR2_TRACE_STBITS,
+                                  "State bit %s <-- %s",
+                                          "state_encoder_runok",
+                                          (hdw->state_encoder_runok ?
+                                           "true" : "false"));
+                       }
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "Giving up on command."
+                               "  This is normally recovered via a firmware"
+                               " reload and re-initialization; concern"
+                               " is only warranted if this happens repeatedly"
+                               " and rapidly.");
+                       break;
+               }
+               wrData[0] = 0x7;
+               for (idx = 0; idx < arg_cnt_recv; idx++) {
+                       argp[idx] = rdData[idx+4];
+               }
+
+               wrData[0] = 0x0;
+               ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
+               if (ret) break;
+
+       } while(0); LOCK_GIVE(hdw->ctl_lock);
+
+       return ret;
+}
+
+
+static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd,
+                            int args, ...)
+{
+       va_list vl;
+       unsigned int idx;
+       u32 data[12];
+
+       if (args > ARRAY_SIZE(data)) {
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "Failed to write cx23416 command"
+                       " - too many arguments"
+                       " (was given %u limit %lu)",
+                       args, (long unsigned) ARRAY_SIZE(data));
+               return -EINVAL;
+       }
+
+       va_start(vl, args);
+       for (idx = 0; idx < args; idx++) {
+               data[idx] = va_arg(vl, u32);
+       }
+       va_end(vl);
+
+       return pvr2_encoder_cmd(hdw,cmd,args,0,data);
+}
+
+
+/* This implements some extra setup for the encoder that seems to be
+   specific to the PVR USB2 hardware. */
+static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
+{
+       int ret = 0;
+       int encMisc3Arg = 0;
+
+#if 0
+       /* This inexplicable bit happens in the Hauppauge windows
+          driver (for both 24xxx and 29xxx devices).  However I
+          currently see no difference in behavior with or without
+          this stuff.  Leave this here as a note of its existence,
+          but don't use it. */
+       LOCK_TAKE(hdw->ctl_lock); do {
+               u32 dat[1];
+               dat[0] = 0x80000640;
+               pvr2_encoder_write_words(hdw,0x01fe,dat,1);
+               pvr2_encoder_write_words(hdw,0x023e,dat,1);
+       } while(0); LOCK_GIVE(hdw->ctl_lock);
+#endif
+
+       /* Mike Isely <isely@pobox.com> 26-Jan-2006 The windows driver
+          sends the following list of ENC_MISC commands (for both
+          24xxx and 29xxx devices).  Meanings are not entirely clear,
+          however without the ENC_MISC(3,1) command then we risk
+          random perpetual video corruption whenever the video input
+          breaks up for a moment (like when switching channels). */
+
+
+#if 0
+       /* This ENC_MISC(5,0) command seems to hurt 29xxx sync
+          performance on channel changes, but is not a problem on
+          24xxx devices. */
+       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0);
+#endif
+
+       /* This ENC_MISC(3,encMisc3Arg) command is critical - without
+          it there will eventually be video corruption.  Also, the
+          saa7115 case is strange - the Windows driver is passing 1
+          regardless of device type but if we have 1 for saa7115
+          devices the video turns sluggish.  */
+       if (hdw->hdw_desc->flag_has_cx25840) {
+               encMisc3Arg = 1;
+       } else {
+               encMisc3Arg = 0;
+       }
+       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,
+                                encMisc3Arg,0,0);
+
+       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0);
+
+#if 0
+       /* This ENC_MISC(4,1) command is poisonous, so it is commented
+          out.  But I'm leaving it here anyway to document its
+          existence in the Windows driver.  The effect of this
+          command is that apps displaying the stream become sluggish
+          with stuttering video. */
+       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0);
+#endif
+
+       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0);
+       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0);
+
+       /* prevent the PTSs from slowly drifting away in the generated
+          MPEG stream */
+       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC, 2, 4, 1);
+
+       return ret;
+}
+
+int pvr2_encoder_adjust(struct pvr2_hdw *hdw)
+{
+       int ret;
+       ret = cx2341x_update(hdw,pvr2_encoder_cmd,
+                            (hdw->enc_cur_valid ? &hdw->enc_cur_state : NULL),
+                            &hdw->enc_ctl_state);
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Error from cx2341x module code=%d",ret);
+       } else {
+               memcpy(&hdw->enc_cur_state,&hdw->enc_ctl_state,
+                      sizeof(struct cx2341x_mpeg_params));
+               hdw->enc_cur_valid = !0;
+       }
+       return ret;
+}
+
+
+int pvr2_encoder_configure(struct pvr2_hdw *hdw)
+{
+       int ret;
+       int val;
+       pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure"
+                  " (cx2341x module)");
+       hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING;
+       hdw->enc_ctl_state.width = hdw->res_hor_val;
+       hdw->enc_ctl_state.height = hdw->res_ver_val;
+       hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & V4L2_STD_525_60) ?
+                                     0 : 1);
+
+       ret = 0;
+
+       ret |= pvr2_encoder_prep_config(hdw);
+
+       /* saa7115: 0xf0 */
+       val = 0xf0;
+       if (hdw->hdw_desc->flag_has_cx25840) {
+               /* ivtv cx25840: 0x140 */
+               val = 0x140;
+       }
+
+       if (!ret) ret = pvr2_encoder_vcmd(
+               hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
+               val, val);
+
+       /* setup firmware to notify us about some events (don't know why...) */
+       if (!ret) ret = pvr2_encoder_vcmd(
+               hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4,
+               0, 0, 0x10000000, 0xffffffff);
+
+       if (!ret) ret = pvr2_encoder_vcmd(
+               hdw,CX2341X_ENC_SET_VBI_LINE, 5,
+               0xffffffff,0,0,0,0);
+
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Failed to configure cx23416");
+               return ret;
+       }
+
+       ret = pvr2_encoder_adjust(hdw);
+       if (ret) return ret;
+
+       ret = pvr2_encoder_vcmd(
+               hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
+
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Failed to initialize cx23416 video input");
+               return ret;
+       }
+
+       return 0;
+}
+
+
+int pvr2_encoder_start(struct pvr2_hdw *hdw)
+{
+       int status;
+
+       /* unmask some interrupts */
+       pvr2_write_register(hdw, 0x0048, 0xbfffffff);
+
+       pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
+                         hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
+
+       switch (hdw->active_stream_type) {
+       case pvr2_config_vbi:
+               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
+                                          0x01,0x14);
+               break;
+       case pvr2_config_mpeg:
+               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
+                                          0,0x13);
+               break;
+       default: /* Unhandled cases for now */
+               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
+                                          0,0x13);
+               break;
+       }
+       return status;
+}
+
+int pvr2_encoder_stop(struct pvr2_hdw *hdw)
+{
+       int status;
+
+       /* mask all interrupts */
+       pvr2_write_register(hdw, 0x0048, 0xffffffff);
+
+       switch (hdw->active_stream_type) {
+       case pvr2_config_vbi:
+               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
+                                          0x01,0x01,0x14);
+               break;
+       case pvr2_config_mpeg:
+               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
+                                          0x01,0,0x13);
+               break;
+       default: /* Unhandled cases for now */
+               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
+                                          0x01,0,0x13);
+               break;
+       }
+
+       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
new file mode 100644 (file)
index 0000000..232fefb
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_ENCODER_H
+#define __PVRUSB2_ENCODER_H
+
+struct pvr2_hdw;
+
+int pvr2_encoder_adjust(struct pvr2_hdw *);
+int pvr2_encoder_configure(struct pvr2_hdw *);
+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
new file mode 100644 (file)
index 0000000..614755e
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *
+ *
+ *  Copyright (C) 2007 Michael Krufky <mkrufky@linuxtv.org>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _PVRUSB2_FX2_CMD_H_
+#define _PVRUSB2_FX2_CMD_H_
+
+#define FX2CMD_MEM_WRITE_DWORD  0x01u
+#define FX2CMD_MEM_READ_DWORD   0x02u
+
+#define FX2CMD_HCW_ZILOG_RESET  0x10u /* 1=reset 0=release */
+
+#define FX2CMD_MEM_READ_64BYTES 0x28u
+
+#define FX2CMD_REG_WRITE        0x04u
+#define FX2CMD_REG_READ         0x05u
+#define FX2CMD_MEMSEL           0x06u
+
+#define FX2CMD_I2C_WRITE        0x08u
+#define FX2CMD_I2C_READ         0x09u
+
+#define FX2CMD_GET_USB_SPEED    0x0bu
+
+#define FX2CMD_STREAMING_ON     0x36u
+#define FX2CMD_STREAMING_OFF    0x37u
+
+#define FX2CMD_FWPOST1          0x52u
+
+#define FX2CMD_POWER_OFF        0xdcu
+#define FX2CMD_POWER_ON         0xdeu
+
+#define FX2CMD_DEEP_RESET       0xddu
+
+#define FX2CMD_GET_EEPROM_ADDR  0xebu
+#define FX2CMD_GET_IR_CODE      0xecu
+
+#define FX2CMD_HCW_DEMOD_RESETIN       0xf0u
+#define FX2CMD_HCW_DTV_STREAMING_ON    0xf1u
+#define FX2CMD_HCW_DTV_STREAMING_OFF   0xf2u
+
+#define FX2CMD_ONAIR_DTV_STREAMING_ON  0xa0u
+#define FX2CMD_ONAIR_DTV_STREAMING_OFF 0xa1u
+#define FX2CMD_ONAIR_DTV_POWER_ON      0xa2u
+#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
new file mode 100644 (file)
index 0000000..036952f
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_HDW_INTERNAL_H
+#define __PVRUSB2_HDW_INTERNAL_H
+
+/*
+
+  This header sets up all the internal structures and definitions needed to
+  track and coordinate the driver's interaction with the hardware.  ONLY
+  source files which actually implement part of that whole circus should be
+  including this header.  Higher levels, like the external layers to the
+  various public APIs (V4L, sysfs, etc) should NOT ever include this
+  private, internal header.  This means that pvrusb2-hdw, pvrusb2-encoder,
+  etc will include this, but pvrusb2-v4l should not.
+
+*/
+
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-io.h"
+#include <media/v4l2-device.h>
+#include <media/cx2341x.h>
+#include <media/ir-kbd-i2c.h>
+#include "pvrusb2-devattr.h"
+
+/* Legal values for PVR2_CID_HSM */
+#define PVR2_CVAL_HSM_FAIL 0
+#define PVR2_CVAL_HSM_FULL 1
+#define PVR2_CVAL_HSM_HIGH 2
+
+#define PVR2_VID_ENDPOINT        0x84
+#define PVR2_UNK_ENDPOINT        0x86    /* maybe raw yuv ? */
+#define PVR2_VBI_ENDPOINT        0x88
+
+#define PVR2_CTL_BUFFSIZE        64
+
+#define FREQTABLE_SIZE 500
+
+#define LOCK_TAKE(x) do { mutex_lock(&x##_mutex); x##_held = !0; } while (0)
+#define LOCK_GIVE(x) do { x##_held = 0; mutex_unlock(&x##_mutex); } while (0)
+
+typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *);
+typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *);
+typedef int (*pvr2_ctlf_check_value)(struct pvr2_ctrl *,int);
+typedef int (*pvr2_ctlf_get_value)(struct pvr2_ctrl *,int *);
+typedef int (*pvr2_ctlf_set_value)(struct pvr2_ctrl *,int msk,int val);
+typedef int (*pvr2_ctlf_val_to_sym)(struct pvr2_ctrl *,int msk,int val,
+                                   char *,unsigned int,unsigned int *);
+typedef int (*pvr2_ctlf_sym_to_val)(struct pvr2_ctrl *,
+                                   const char *,unsigned int,
+                                   int *mskp,int *valp);
+typedef unsigned int (*pvr2_ctlf_get_v4lflags)(struct pvr2_ctrl *);
+
+/* This structure describes a specific control.  A table of these is set up
+   in pvrusb2-hdw.c. */
+struct pvr2_ctl_info {
+       /* Control's name suitable for use as an identifier */
+       const char *name;
+
+       /* Short description of control */
+       const char *desc;
+
+       /* Control's implementation */
+       pvr2_ctlf_get_value get_value;      /* Get its value */
+       pvr2_ctlf_get_value get_def_value;  /* Get its default value */
+       pvr2_ctlf_get_value get_min_value;  /* Get minimum allowed value */
+       pvr2_ctlf_get_value get_max_value;  /* Get maximum allowed value */
+       pvr2_ctlf_set_value set_value;      /* Set its value */
+       pvr2_ctlf_check_value check_value;  /* Check that value is valid */
+       pvr2_ctlf_val_to_sym val_to_sym;    /* Custom convert value->symbol */
+       pvr2_ctlf_sym_to_val sym_to_val;    /* Custom convert symbol->value */
+       pvr2_ctlf_is_dirty is_dirty;        /* Return true if dirty */
+       pvr2_ctlf_clear_dirty clear_dirty;  /* Clear dirty state */
+       pvr2_ctlf_get_v4lflags get_v4lflags;/* Retrieve v4l flags */
+
+       /* Control's type (int, enum, bitmask) */
+       enum pvr2_ctl_type type;
+
+       /* Associated V4L control ID, if any */
+       int v4l_id;
+
+       /* Associated driver internal ID, if any */
+       int internal_id;
+
+       /* Don't implicitly initialize this control's value */
+       int skip_init;
+
+       /* Starting value for this control */
+       int default_value;
+
+       /* Type-specific control information */
+       union {
+               struct { /* Integer control */
+                       long min_value; /* lower limit */
+                       long max_value; /* upper limit */
+               } type_int;
+               struct { /* enumerated control */
+                       unsigned int count;       /* enum value count */
+                       const char * const *value_names; /* symbol names */
+               } type_enum;
+               struct { /* bitmask control */
+                       unsigned int valid_bits; /* bits in use */
+                       const char **bit_names;  /* symbol name/bit */
+               } type_bitmask;
+       } def;
+};
+
+
+/* Same as pvr2_ctl_info, but includes storage for the control description */
+#define PVR2_CTLD_INFO_DESC_SIZE 32
+struct pvr2_ctld_info {
+       struct pvr2_ctl_info info;
+       char desc[PVR2_CTLD_INFO_DESC_SIZE];
+};
+
+struct pvr2_ctrl {
+       const struct pvr2_ctl_info *info;
+       struct pvr2_hdw *hdw;
+};
+
+
+
+/* Disposition of firmware1 loading situation */
+#define FW1_STATE_UNKNOWN 0
+#define FW1_STATE_MISSING 1
+#define FW1_STATE_FAILED 2
+#define FW1_STATE_RELOAD 3
+#define FW1_STATE_OK 4
+
+/* What state the device is in if it is a hybrid */
+#define PVR2_PATHWAY_UNKNOWN 0
+#define PVR2_PATHWAY_ANALOG 1
+#define PVR2_PATHWAY_DIGITAL 2
+
+typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16);
+#define PVR2_I2C_FUNC_CNT 128
+
+/* This structure contains all state data directly needed to
+   manipulate the hardware (as opposed to complying with a kernel
+   interface) */
+struct pvr2_hdw {
+       /* Underlying USB device handle */
+       struct usb_device *usb_dev;
+       struct usb_interface *usb_intf;
+
+       /* Our handle into the v4l2 sub-device architecture */
+       struct v4l2_device v4l2_dev;
+       /* Device description, anything that must adjust behavior based on
+          device specific info will use information held here. */
+       const struct pvr2_device_desc *hdw_desc;
+
+       /* Kernel worker thread handling */
+       struct workqueue_struct *workqueue;
+       struct work_struct workpoll;     /* Update driver state */
+
+       /* Video spigot */
+       struct pvr2_stream *vid_stream;
+
+       /* Mutex for all hardware state control */
+       struct mutex big_lock_mutex;
+       int big_lock_held;  /* For debugging */
+
+       /* This is a simple string which identifies the instance of this
+          driver.  It is unique within the set of existing devices, but
+          there is no attempt to keep the name consistent with the same
+          physical device each time. */
+       char name[32];
+
+       /* This is a simple string which identifies the physical device
+          instance itself - if possible.  (If not possible, then it is
+          based on the specific driver instance, similar to name above.)
+          The idea here is that userspace might hopefully be able to use
+          this recognize specific tuners.  It will encode a serial number,
+          if available. */
+       char identifier[32];
+
+       /* I2C stuff */
+       struct i2c_adapter i2c_adap;
+       struct i2c_algorithm i2c_algo;
+       pvr2_i2c_func i2c_func[PVR2_I2C_FUNC_CNT];
+       int i2c_cx25840_hack_state;
+       int i2c_linked;
+
+       /* IR related */
+       unsigned int ir_scheme_active; /* IR scheme as seen from the outside */
+       struct IR_i2c_init_data ir_init_data; /* params passed to IR modules */
+
+       /* Frequency table */
+       unsigned int freqTable[FREQTABLE_SIZE];
+       unsigned int freqProgSlot;
+
+       /* Stuff for handling low level control interaction with device */
+       struct mutex ctl_lock_mutex;
+       int ctl_lock_held;  /* For debugging */
+       struct urb *ctl_write_urb;
+       struct urb *ctl_read_urb;
+       unsigned char *ctl_write_buffer;
+       unsigned char *ctl_read_buffer;
+       int ctl_write_pend_flag;
+       int ctl_read_pend_flag;
+       int ctl_timeout_flag;
+       struct completion ctl_done;
+       unsigned char cmd_buffer[PVR2_CTL_BUFFSIZE];
+       int cmd_debug_state;               // Low level command debugging info
+       unsigned char cmd_debug_code;      //
+       unsigned int cmd_debug_write_len;  //
+       unsigned int cmd_debug_read_len;   //
+
+       /* Bits of state that describe what is going on with various parts
+          of the driver. */
+       int state_pathway_ok;         /* Pathway config is ok */
+       int state_encoder_ok;         /* Encoder is operational */
+       int state_encoder_run;        /* Encoder is running */
+       int state_encoder_config;     /* Encoder is configured */
+       int state_encoder_waitok;     /* Encoder pre-wait done */
+       int state_encoder_runok;      /* Encoder has run for >= .25 sec */
+       int state_decoder_run;        /* Decoder is running */
+       int state_decoder_ready;      /* Decoder is stabilized & streamable */
+       int state_usbstream_run;      /* FX2 is streaming */
+       int state_decoder_quiescent;  /* Decoder idle for minimal interval */
+       int state_pipeline_config;    /* Pipeline is configured */
+       int state_pipeline_req;       /* Somebody wants to stream */
+       int state_pipeline_pause;     /* Pipeline must be paused */
+       int state_pipeline_idle;      /* Pipeline not running */
+
+       /* This is the master state of the driver.  It is the combined
+          result of other bits of state.  Examining this will indicate the
+          overall state of the driver.  Values here are one of
+          PVR2_STATE_xxxx */
+       unsigned int master_state;
+
+       /* True if device led is currently on */
+       int led_on;
+
+       /* True if states must be re-evaluated */
+       int state_stale;
+
+       void (*state_func)(void *);
+       void *state_data;
+
+       /* Timer for measuring required decoder settling time before we're
+          allowed to fire it up again. */
+       struct timer_list quiescent_timer;
+
+       /* Timer for measuring decoder stabilization time, which is the
+          amount of time we need to let the decoder run before we can
+          trust its output (otherwise the encoder might see garbage and
+          then fail to start correctly). */
+       struct timer_list decoder_stabilization_timer;
+
+       /* Timer for measuring encoder pre-wait time */
+       struct timer_list encoder_wait_timer;
+
+       /* Timer for measuring encoder minimum run time */
+       struct timer_list encoder_run_timer;
+
+       /* Place to block while waiting for state changes */
+       wait_queue_head_t state_wait_data;
+
+
+       int force_dirty;        /* consider all controls dirty if true */
+       int flag_ok;            /* device in known good state */
+       int flag_modulefail;    /* true if at least one module failed to load */
+       int flag_disconnected;  /* flag_ok == 0 due to disconnect */
+       int flag_init_ok;       /* true if structure is fully initialized */
+       int fw1_state;          /* current situation with fw1 */
+       int pathway_state;      /* one of PVR2_PATHWAY_xxx */
+       int flag_decoder_missed;/* We've noticed missing decoder */
+       int flag_tripped;       /* Indicates overall failure to start */
+
+       unsigned int decoder_client_id;
+
+       // CPU firmware info (used to help find / save firmware data)
+       char *fw_buffer;
+       unsigned int fw_size;
+       int fw_cpu_flag; /* True if we are dealing with the CPU */
+
+       /* Tuner / frequency control stuff */
+       unsigned int tuner_type;
+       int tuner_updated;
+       unsigned int freqValTelevision;  /* Current freq for tv mode */
+       unsigned int freqValRadio;       /* Current freq for radio mode */
+       unsigned int freqSlotTelevision; /* Current slot for tv mode */
+       unsigned int freqSlotRadio;      /* Current slot for radio mode */
+       unsigned int freqSelector;       /* 0=radio 1=television */
+       int freqDirty;
+
+       /* Current tuner info - this information is polled from the I2C bus */
+       struct v4l2_tuner tuner_signal_info;
+       int tuner_signal_stale;
+
+       /* Cropping capability info */
+       struct v4l2_cropcap cropcap_info;
+       int cropcap_stale;
+
+       /* Video standard handling */
+       v4l2_std_id std_mask_eeprom; // Hardware supported selections
+       v4l2_std_id std_mask_avail;  // Which standards we may select from
+       v4l2_std_id std_mask_cur;    // Currently selected standard(s)
+       int std_enum_cur;            // selected standard enumeration value
+       int std_dirty;               // True if std_mask_cur has changed
+       struct pvr2_ctl_info std_info_enum;
+       struct pvr2_ctl_info std_info_avail;
+       struct pvr2_ctl_info std_info_cur;
+       struct pvr2_ctl_info std_info_detect;
+
+       // Generated string names, one per actual V4L2 standard
+       const char *std_mask_ptrs[32];
+       char std_mask_names[32][16];
+
+       int unit_number;             /* ID for driver instance */
+       unsigned long serial_number; /* ID for hardware itself */
+
+       char bus_info[32]; /* Bus location info */
+
+       /* Minor numbers used by v4l logic (yes, this is a hack, as there
+          should be no v4l junk here).  Probably a better way to do this. */
+       int v4l_minor_number_video;
+       int v4l_minor_number_vbi;
+       int v4l_minor_number_radio;
+
+       /* Bit mask of PVR2_CVAL_INPUT choices which are valid for the hardware */
+       unsigned int input_avail_mask;
+       /* Bit mask of PVR2_CVAL_INPUT choices which are currently allowed */
+       unsigned int input_allowed_mask;
+
+       /* Location of eeprom or a negative number if none */
+       int eeprom_addr;
+
+       enum pvr2_config active_stream_type;
+       enum pvr2_config desired_stream_type;
+
+       /* Control state needed for cx2341x module */
+       struct cx2341x_mpeg_params enc_cur_state;
+       struct cx2341x_mpeg_params enc_ctl_state;
+       /* True if an encoder attribute has changed */
+       int enc_stale;
+       /* True if an unsafe encoder attribute has changed */
+       int enc_unsafe_stale;
+       /* True if enc_cur_state is valid */
+       int enc_cur_valid;
+
+       /* Control state */
+#define VCREATE_DATA(lab) int lab##_val; int lab##_dirty
+       VCREATE_DATA(brightness);
+       VCREATE_DATA(contrast);
+       VCREATE_DATA(saturation);
+       VCREATE_DATA(hue);
+       VCREATE_DATA(volume);
+       VCREATE_DATA(balance);
+       VCREATE_DATA(bass);
+       VCREATE_DATA(treble);
+       VCREATE_DATA(mute);
+       VCREATE_DATA(cropl);
+       VCREATE_DATA(cropt);
+       VCREATE_DATA(cropw);
+       VCREATE_DATA(croph);
+       VCREATE_DATA(input);
+       VCREATE_DATA(audiomode);
+       VCREATE_DATA(res_hor);
+       VCREATE_DATA(res_ver);
+       VCREATE_DATA(srate);
+#undef VCREATE_DATA
+
+       struct pvr2_ctld_info *mpeg_ctrl_info;
+
+       struct pvr2_ctrl *controls;
+       unsigned int control_cnt;
+};
+
+/* This function gets the current frequency */
+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
new file mode 100644 (file)
index 0000000..fb828ba
--- /dev/null
@@ -0,0 +1,5202 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include "pvrusb2.h"
+#include "pvrusb2-std.h"
+#include "pvrusb2-util.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-i2c-core.h"
+#include "pvrusb2-eeprom.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-encoder.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-fx2-cmd.h"
+#include "pvrusb2-wm8775.h"
+#include "pvrusb2-video-v4l.h"
+#include "pvrusb2-cx2584x-v4l.h"
+#include "pvrusb2-cs53l32a.h"
+#include "pvrusb2-audio.h"
+
+#define TV_MIN_FREQ     55250000L
+#define TV_MAX_FREQ    850000000L
+
+/* This defines a minimum interval that the decoder must remain quiet
+   before we are allowed to start it running. */
+#define TIME_MSEC_DECODER_WAIT 50
+
+/* This defines a minimum interval that the decoder must be allowed to run
+   before we can safely begin using its streaming output. */
+#define TIME_MSEC_DECODER_STABILIZATION_WAIT 300
+
+/* This defines a minimum interval that the encoder must remain quiet
+   before we are allowed to configure it. */
+#define TIME_MSEC_ENCODER_WAIT 50
+
+/* This defines the minimum interval that the encoder must successfully run
+   before we consider that the encoder has run at least once since its
+   firmware has been loaded.  This measurement is in important for cases
+   where we can't do something until we know that the encoder has been run
+   at least once. */
+#define TIME_MSEC_ENCODER_OK 250
+
+static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
+static DEFINE_MUTEX(pvr2_unit_mtx);
+
+static int ctlchg;
+static int procreload;
+static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };
+static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
+static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
+static int init_pause_msec;
+
+module_param(ctlchg, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value");
+module_param(init_pause_msec, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(init_pause_msec, "hardware initialization settling delay");
+module_param(procreload, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(procreload,
+                "Attempt init failure recovery with firmware reload");
+module_param_array(tuner,    int, NULL, 0444);
+MODULE_PARM_DESC(tuner,"specify installed tuner type");
+module_param_array(video_std,    int, NULL, 0444);
+MODULE_PARM_DESC(video_std,"specify initial video standard");
+module_param_array(tolerance,    int, NULL, 0444);
+MODULE_PARM_DESC(tolerance,"specify stream error tolerance");
+
+/* US Broadcast channel 3 (61.25 MHz), to help with testing */
+static int default_tv_freq    = 61250000L;
+/* 104.3 MHz, a usable FM station for my area */
+static int default_radio_freq = 104300000L;
+
+module_param_named(tv_freq, default_tv_freq, int, 0444);
+MODULE_PARM_DESC(tv_freq, "specify initial television frequency");
+module_param_named(radio_freq, default_radio_freq, int, 0444);
+MODULE_PARM_DESC(radio_freq, "specify initial radio frequency");
+
+#define PVR2_CTL_WRITE_ENDPOINT  0x01
+#define PVR2_CTL_READ_ENDPOINT   0x81
+
+#define PVR2_GPIO_IN 0x9008
+#define PVR2_GPIO_OUT 0x900c
+#define PVR2_GPIO_DIR 0x9020
+
+#define trace_firmware(...) pvr2_trace(PVR2_TRACE_FIRMWARE,__VA_ARGS__)
+
+#define PVR2_FIRMWARE_ENDPOINT   0x02
+
+/* size of a firmware chunk */
+#define FIRMWARE_CHUNK_SIZE 0x2000
+
+typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *,
+                                       struct v4l2_subdev *);
+
+static const pvr2_subdev_update_func pvr2_module_update_functions[] = {
+       [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_subdev_update,
+       [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update,
+       [PVR2_CLIENT_ID_MSP3400] = pvr2_msp3400_subdev_update,
+       [PVR2_CLIENT_ID_CX25840] = pvr2_cx25840_subdev_update,
+       [PVR2_CLIENT_ID_CS53L32A] = pvr2_cs53l32a_subdev_update,
+};
+
+static const char *module_names[] = {
+       [PVR2_CLIENT_ID_MSP3400] = "msp3400",
+       [PVR2_CLIENT_ID_CX25840] = "cx25840",
+       [PVR2_CLIENT_ID_SAA7115] = "saa7115",
+       [PVR2_CLIENT_ID_TUNER] = "tuner",
+       [PVR2_CLIENT_ID_DEMOD] = "tuner",
+       [PVR2_CLIENT_ID_CS53L32A] = "cs53l32a",
+       [PVR2_CLIENT_ID_WM8775] = "wm8775",
+};
+
+
+static const unsigned char *module_i2c_addresses[] = {
+       [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63",
+       [PVR2_CLIENT_ID_DEMOD] = "\x43",
+       [PVR2_CLIENT_ID_MSP3400] = "\x40",
+       [PVR2_CLIENT_ID_SAA7115] = "\x21",
+       [PVR2_CLIENT_ID_WM8775] = "\x1b",
+       [PVR2_CLIENT_ID_CX25840] = "\x44",
+       [PVR2_CLIENT_ID_CS53L32A] = "\x11",
+};
+
+
+static const char *ir_scheme_names[] = {
+       [PVR2_IR_SCHEME_NONE] = "none",
+       [PVR2_IR_SCHEME_29XXX] = "29xxx",
+       [PVR2_IR_SCHEME_24XXX] = "24xxx (29xxx emulation)",
+       [PVR2_IR_SCHEME_24XXX_MCE] = "24xxx (MCE device)",
+       [PVR2_IR_SCHEME_ZILOG] = "Zilog",
+};
+
+
+/* Define the list of additional controls we'll dynamically construct based
+   on query of the cx2341x module. */
+struct pvr2_mpeg_ids {
+       const char *strid;
+       int id;
+};
+static const struct pvr2_mpeg_ids mpeg_ids[] = {
+       {
+               .strid = "audio_layer",
+               .id = V4L2_CID_MPEG_AUDIO_ENCODING,
+       },{
+               .strid = "audio_bitrate",
+               .id = V4L2_CID_MPEG_AUDIO_L2_BITRATE,
+       },{
+               /* Already using audio_mode elsewhere :-( */
+               .strid = "mpeg_audio_mode",
+               .id = V4L2_CID_MPEG_AUDIO_MODE,
+       },{
+               .strid = "mpeg_audio_mode_extension",
+               .id = V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
+       },{
+               .strid = "audio_emphasis",
+               .id = V4L2_CID_MPEG_AUDIO_EMPHASIS,
+       },{
+               .strid = "audio_crc",
+               .id = V4L2_CID_MPEG_AUDIO_CRC,
+       },{
+               .strid = "video_aspect",
+               .id = V4L2_CID_MPEG_VIDEO_ASPECT,
+       },{
+               .strid = "video_b_frames",
+               .id = V4L2_CID_MPEG_VIDEO_B_FRAMES,
+       },{
+               .strid = "video_gop_size",
+               .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+       },{
+               .strid = "video_gop_closure",
+               .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
+       },{
+               .strid = "video_bitrate_mode",
+               .id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+       },{
+               .strid = "video_bitrate",
+               .id = V4L2_CID_MPEG_VIDEO_BITRATE,
+       },{
+               .strid = "video_bitrate_peak",
+               .id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+       },{
+               .strid = "video_temporal_decimation",
+               .id = V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
+       },{
+               .strid = "stream_type",
+               .id = V4L2_CID_MPEG_STREAM_TYPE,
+       },{
+               .strid = "video_spatial_filter_mode",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
+       },{
+               .strid = "video_spatial_filter",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
+       },{
+               .strid = "video_luma_spatial_filter_type",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
+       },{
+               .strid = "video_chroma_spatial_filter_type",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
+       },{
+               .strid = "video_temporal_filter_mode",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
+       },{
+               .strid = "video_temporal_filter",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
+       },{
+               .strid = "video_median_filter_type",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
+       },{
+               .strid = "video_luma_median_filter_top",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
+       },{
+               .strid = "video_luma_median_filter_bottom",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
+       },{
+               .strid = "video_chroma_median_filter_top",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
+       },{
+               .strid = "video_chroma_median_filter_bottom",
+               .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
+       }
+};
+#define MPEGDEF_COUNT ARRAY_SIZE(mpeg_ids)
+
+
+static const char *control_values_srate[] = {
+       [V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100]   = "44.1 kHz",
+       [V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000]   = "48 kHz",
+       [V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000]   = "32 kHz",
+};
+
+
+
+static const char *control_values_input[] = {
+       [PVR2_CVAL_INPUT_TV]        = "television",  /*xawtv needs this name*/
+       [PVR2_CVAL_INPUT_DTV]       = "dtv",
+       [PVR2_CVAL_INPUT_RADIO]     = "radio",
+       [PVR2_CVAL_INPUT_SVIDEO]    = "s-video",
+       [PVR2_CVAL_INPUT_COMPOSITE] = "composite",
+};
+
+
+static const char *control_values_audiomode[] = {
+       [V4L2_TUNER_MODE_MONO]   = "Mono",
+       [V4L2_TUNER_MODE_STEREO] = "Stereo",
+       [V4L2_TUNER_MODE_LANG1]  = "Lang1",
+       [V4L2_TUNER_MODE_LANG2]  = "Lang2",
+       [V4L2_TUNER_MODE_LANG1_LANG2] = "Lang1+Lang2",
+};
+
+
+static const char *control_values_hsm[] = {
+       [PVR2_CVAL_HSM_FAIL] = "Fail",
+       [PVR2_CVAL_HSM_HIGH] = "High",
+       [PVR2_CVAL_HSM_FULL] = "Full",
+};
+
+
+static const char *pvr2_state_names[] = {
+       [PVR2_STATE_NONE] =    "none",
+       [PVR2_STATE_DEAD] =    "dead",
+       [PVR2_STATE_COLD] =    "cold",
+       [PVR2_STATE_WARM] =    "warm",
+       [PVR2_STATE_ERROR] =   "error",
+       [PVR2_STATE_READY] =   "ready",
+       [PVR2_STATE_RUN] =     "run",
+};
+
+
+struct pvr2_fx2cmd_descdef {
+       unsigned char id;
+       unsigned char *desc;
+};
+
+static const struct pvr2_fx2cmd_descdef pvr2_fx2cmd_desc[] = {
+       {FX2CMD_MEM_WRITE_DWORD, "write encoder dword"},
+       {FX2CMD_MEM_READ_DWORD, "read encoder dword"},
+       {FX2CMD_HCW_ZILOG_RESET, "zilog IR reset control"},
+       {FX2CMD_MEM_READ_64BYTES, "read encoder 64bytes"},
+       {FX2CMD_REG_WRITE, "write encoder register"},
+       {FX2CMD_REG_READ, "read encoder register"},
+       {FX2CMD_MEMSEL, "encoder memsel"},
+       {FX2CMD_I2C_WRITE, "i2c write"},
+       {FX2CMD_I2C_READ, "i2c read"},
+       {FX2CMD_GET_USB_SPEED, "get USB speed"},
+       {FX2CMD_STREAMING_ON, "stream on"},
+       {FX2CMD_STREAMING_OFF, "stream off"},
+       {FX2CMD_FWPOST1, "fwpost1"},
+       {FX2CMD_POWER_OFF, "power off"},
+       {FX2CMD_POWER_ON, "power on"},
+       {FX2CMD_DEEP_RESET, "deep reset"},
+       {FX2CMD_GET_EEPROM_ADDR, "get rom addr"},
+       {FX2CMD_GET_IR_CODE, "get IR code"},
+       {FX2CMD_HCW_DEMOD_RESETIN, "hcw demod resetin"},
+       {FX2CMD_HCW_DTV_STREAMING_ON, "hcw dtv stream on"},
+       {FX2CMD_HCW_DTV_STREAMING_OFF, "hcw dtv stream off"},
+       {FX2CMD_ONAIR_DTV_STREAMING_ON, "onair dtv stream on"},
+       {FX2CMD_ONAIR_DTV_STREAMING_OFF, "onair dtv stream off"},
+       {FX2CMD_ONAIR_DTV_POWER_ON, "onair dtv power on"},
+       {FX2CMD_ONAIR_DTV_POWER_OFF, "onair dtv power off"},
+};
+
+
+static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v);
+static void pvr2_hdw_state_sched(struct pvr2_hdw *);
+static int pvr2_hdw_state_eval(struct pvr2_hdw *);
+static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long);
+static void pvr2_hdw_worker_poll(struct work_struct *work);
+static int pvr2_hdw_wait(struct pvr2_hdw *,int state);
+static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *);
+static void pvr2_hdw_state_log_state(struct pvr2_hdw *);
+static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl);
+static int pvr2_hdw_commit_setup(struct pvr2_hdw *hdw);
+static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw);
+static void pvr2_hdw_quiescent_timeout(unsigned long);
+static void pvr2_hdw_decoder_stabilization_timeout(unsigned long);
+static void pvr2_hdw_encoder_wait_timeout(unsigned long);
+static void pvr2_hdw_encoder_run_timeout(unsigned long);
+static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32);
+static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
+                               unsigned int timeout,int probe_fl,
+                               void *write_data,unsigned int write_len,
+                               void *read_data,unsigned int read_len);
+static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw);
+static v4l2_std_id pvr2_hdw_get_detected_std(struct pvr2_hdw *hdw);
+
+static void trace_stbit(const char *name,int val)
+{
+       pvr2_trace(PVR2_TRACE_STBITS,
+                  "State bit %s <-- %s",
+                  name,(val ? "true" : "false"));
+}
+
+static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+       if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) {
+               *vp = hdw->freqTable[hdw->freqProgSlot-1];
+       } else {
+               *vp = 0;
+       }
+       return 0;
+}
+
+static int ctrl_channelfreq_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+       unsigned int slotId = hdw->freqProgSlot;
+       if ((slotId > 0) && (slotId <= FREQTABLE_SIZE)) {
+               hdw->freqTable[slotId-1] = v;
+               /* Handle side effects correctly - if we're tuned to this
+                  slot, then forgot the slot id relation since the stored
+                  frequency has been changed. */
+               if (hdw->freqSelector) {
+                       if (hdw->freqSlotRadio == slotId) {
+                               hdw->freqSlotRadio = 0;
+                       }
+               } else {
+                       if (hdw->freqSlotTelevision == slotId) {
+                               hdw->freqSlotTelevision = 0;
+                       }
+               }
+       }
+       return 0;
+}
+
+static int ctrl_channelprog_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->freqProgSlot;
+       return 0;
+}
+
+static int ctrl_channelprog_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+       if ((v >= 0) && (v <= FREQTABLE_SIZE)) {
+               hdw->freqProgSlot = v;
+       }
+       return 0;
+}
+
+static int ctrl_channel_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+       *vp = hdw->freqSelector ? hdw->freqSlotRadio : hdw->freqSlotTelevision;
+       return 0;
+}
+
+static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int slotId)
+{
+       unsigned freq = 0;
+       struct pvr2_hdw *hdw = cptr->hdw;
+       if ((slotId < 0) || (slotId > FREQTABLE_SIZE)) return 0;
+       if (slotId > 0) {
+               freq = hdw->freqTable[slotId-1];
+               if (!freq) return 0;
+               pvr2_hdw_set_cur_freq(hdw,freq);
+       }
+       if (hdw->freqSelector) {
+               hdw->freqSlotRadio = slotId;
+       } else {
+               hdw->freqSlotTelevision = slotId;
+       }
+       return 0;
+}
+
+static int ctrl_freq_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = pvr2_hdw_get_cur_freq(cptr->hdw);
+       return 0;
+}
+
+static int ctrl_freq_is_dirty(struct pvr2_ctrl *cptr)
+{
+       return cptr->hdw->freqDirty != 0;
+}
+
+static void ctrl_freq_clear_dirty(struct pvr2_ctrl *cptr)
+{
+       cptr->hdw->freqDirty = 0;
+}
+
+static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       pvr2_hdw_set_cur_freq(cptr->hdw,v);
+       return 0;
+}
+
+static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *left = cap->bounds.left;
+       return 0;
+}
+
+static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *left = cap->bounds.left;
+       if (cap->bounds.width > cptr->hdw->cropw_val) {
+               *left += cap->bounds.width - cptr->hdw->cropw_val;
+       }
+       return 0;
+}
+
+static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *top = cap->bounds.top;
+       return 0;
+}
+
+static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *top = cap->bounds.top;
+       if (cap->bounds.height > cptr->hdw->croph_val) {
+               *top += cap->bounds.height - cptr->hdw->croph_val;
+       }
+       return 0;
+}
+
+static int ctrl_cropw_max_get(struct pvr2_ctrl *cptr, int *width)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat, bleftend, cleft;
+
+       stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       bleftend = cap->bounds.left+cap->bounds.width;
+       cleft = cptr->hdw->cropl_val;
+
+       *width = cleft < bleftend ? bleftend-cleft : 0;
+       return 0;
+}
+
+static int ctrl_croph_max_get(struct pvr2_ctrl *cptr, int *height)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat, btopend, ctop;
+
+       stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       btopend = cap->bounds.top+cap->bounds.height;
+       ctop = cptr->hdw->cropt_val;
+
+       *height = ctop < btopend ? btopend-ctop : 0;
+       return 0;
+}
+
+static int ctrl_get_cropcapbl(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->bounds.left;
+       return 0;
+}
+
+static int ctrl_get_cropcapbt(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->bounds.top;
+       return 0;
+}
+
+static int ctrl_get_cropcapbw(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->bounds.width;
+       return 0;
+}
+
+static int ctrl_get_cropcapbh(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->bounds.height;
+       return 0;
+}
+
+static int ctrl_get_cropcapdl(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->defrect.left;
+       return 0;
+}
+
+static int ctrl_get_cropcapdt(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->defrect.top;
+       return 0;
+}
+
+static int ctrl_get_cropcapdw(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->defrect.width;
+       return 0;
+}
+
+static int ctrl_get_cropcapdh(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->defrect.height;
+       return 0;
+}
+
+static int ctrl_get_cropcappan(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->pixelaspect.numerator;
+       return 0;
+}
+
+static int ctrl_get_cropcappad(struct pvr2_ctrl *cptr, int *val)
+{
+       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
+       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+       if (stat != 0) {
+               return stat;
+       }
+       *val = cap->pixelaspect.denominator;
+       return 0;
+}
+
+static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       /* Actual maximum depends on the video standard in effect. */
+       if (cptr->hdw->std_mask_cur & V4L2_STD_525_60) {
+               *vp = 480;
+       } else {
+               *vp = 576;
+       }
+       return 0;
+}
+
+static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       /* Actual minimum depends on device digitizer type. */
+       if (cptr->hdw->hdw_desc->flag_has_cx25840) {
+               *vp = 75;
+       } else {
+               *vp = 17;
+       }
+       return 0;
+}
+
+static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->input_val;
+       return 0;
+}
+
+static int ctrl_check_input(struct pvr2_ctrl *cptr,int v)
+{
+       return ((1 << v) & cptr->hdw->input_allowed_mask) != 0;
+}
+
+static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v)
+{
+       return pvr2_hdw_set_input(cptr->hdw,v);
+}
+
+static int ctrl_isdirty_input(struct pvr2_ctrl *cptr)
+{
+       return cptr->hdw->input_dirty != 0;
+}
+
+static void ctrl_cleardirty_input(struct pvr2_ctrl *cptr)
+{
+       cptr->hdw->input_dirty = 0;
+}
+
+
+static int ctrl_freq_max_get(struct pvr2_ctrl *cptr, int *vp)
+{
+       unsigned long fv;
+       struct pvr2_hdw *hdw = cptr->hdw;
+       if (hdw->tuner_signal_stale) {
+               pvr2_hdw_status_poll(hdw);
+       }
+       fv = hdw->tuner_signal_info.rangehigh;
+       if (!fv) {
+               /* Safety fallback */
+               *vp = TV_MAX_FREQ;
+               return 0;
+       }
+       if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
+               fv = (fv * 125) / 2;
+       } else {
+               fv = fv * 62500;
+       }
+       *vp = fv;
+       return 0;
+}
+
+static int ctrl_freq_min_get(struct pvr2_ctrl *cptr, int *vp)
+{
+       unsigned long fv;
+       struct pvr2_hdw *hdw = cptr->hdw;
+       if (hdw->tuner_signal_stale) {
+               pvr2_hdw_status_poll(hdw);
+       }
+       fv = hdw->tuner_signal_info.rangelow;
+       if (!fv) {
+               /* Safety fallback */
+               *vp = TV_MIN_FREQ;
+               return 0;
+       }
+       if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
+               fv = (fv * 125) / 2;
+       } else {
+               fv = fv * 62500;
+       }
+       *vp = fv;
+       return 0;
+}
+
+static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr)
+{
+       return cptr->hdw->enc_stale != 0;
+}
+
+static void ctrl_cx2341x_clear_dirty(struct pvr2_ctrl *cptr)
+{
+       cptr->hdw->enc_stale = 0;
+       cptr->hdw->enc_unsafe_stale = 0;
+}
+
+static int ctrl_cx2341x_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       int ret;
+       struct v4l2_ext_controls cs;
+       struct v4l2_ext_control c1;
+       memset(&cs,0,sizeof(cs));
+       memset(&c1,0,sizeof(c1));
+       cs.controls = &c1;
+       cs.count = 1;
+       c1.id = cptr->info->v4l_id;
+       ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state, 0, &cs,
+                               VIDIOC_G_EXT_CTRLS);
+       if (ret) return ret;
+       *vp = c1.value;
+       return 0;
+}
+
+static int ctrl_cx2341x_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       int ret;
+       struct pvr2_hdw *hdw = cptr->hdw;
+       struct v4l2_ext_controls cs;
+       struct v4l2_ext_control c1;
+       memset(&cs,0,sizeof(cs));
+       memset(&c1,0,sizeof(c1));
+       cs.controls = &c1;
+       cs.count = 1;
+       c1.id = cptr->info->v4l_id;
+       c1.value = v;
+       ret = cx2341x_ext_ctrls(&hdw->enc_ctl_state,
+                               hdw->state_encoder_run, &cs,
+                               VIDIOC_S_EXT_CTRLS);
+       if (ret == -EBUSY) {
+               /* Oops.  cx2341x is telling us it's not safe to change
+                  this control while we're capturing.  Make a note of this
+                  fact so that the pipeline will be stopped the next time
+                  controls are committed.  Then go on ahead and store this
+                  change anyway. */
+               ret = cx2341x_ext_ctrls(&hdw->enc_ctl_state,
+                                       0, &cs,
+                                       VIDIOC_S_EXT_CTRLS);
+               if (!ret) hdw->enc_unsafe_stale = !0;
+       }
+       if (ret) return ret;
+       hdw->enc_stale = !0;
+       return 0;
+}
+
+static unsigned int ctrl_cx2341x_getv4lflags(struct pvr2_ctrl *cptr)
+{
+       struct v4l2_queryctrl qctrl;
+       struct pvr2_ctl_info *info;
+       qctrl.id = cptr->info->v4l_id;
+       cx2341x_ctrl_query(&cptr->hdw->enc_ctl_state,&qctrl);
+       /* Strip out the const so we can adjust a function pointer.  It's
+          OK to do this here because we know this is a dynamically created
+          control, so the underlying storage for the info pointer is (a)
+          private to us, and (b) not in read-only storage.  Either we do
+          this or we significantly complicate the underlying control
+          implementation. */
+       info = (struct pvr2_ctl_info *)(cptr->info);
+       if (qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
+               if (info->set_value) {
+                       info->set_value = NULL;
+               }
+       } else {
+               if (!(info->set_value)) {
+                       info->set_value = ctrl_cx2341x_set;
+               }
+       }
+       return qctrl.flags;
+}
+
+static int ctrl_streamingenabled_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->state_pipeline_req;
+       return 0;
+}
+
+static int ctrl_masterstate_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->master_state;
+       return 0;
+}
+
+static int ctrl_hsm_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       int result = pvr2_hdw_is_hsm(cptr->hdw);
+       *vp = PVR2_CVAL_HSM_FULL;
+       if (result < 0) *vp = PVR2_CVAL_HSM_FAIL;
+       if (result) *vp = PVR2_CVAL_HSM_HIGH;
+       return 0;
+}
+
+static int ctrl_stddetect_get(struct pvr2_ctrl *cptr, int *vp)
+{
+       *vp = pvr2_hdw_get_detected_std(cptr->hdw);
+       return 0;
+}
+
+static int ctrl_stdavail_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->std_mask_avail;
+       return 0;
+}
+
+static int ctrl_stdavail_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+       v4l2_std_id ns;
+       ns = hdw->std_mask_avail;
+       ns = (ns & ~m) | (v & m);
+       if (ns == hdw->std_mask_avail) return 0;
+       hdw->std_mask_avail = ns;
+       hdw->std_info_cur.def.type_bitmask.valid_bits = hdw->std_mask_avail;
+       return 0;
+}
+
+static int ctrl_std_val_to_sym(struct pvr2_ctrl *cptr,int msk,int val,
+                              char *bufPtr,unsigned int bufSize,
+                              unsigned int *len)
+{
+       *len = pvr2_std_id_to_str(bufPtr,bufSize,msk & val);
+       return 0;
+}
+
+static int ctrl_std_sym_to_val(struct pvr2_ctrl *cptr,
+                              const char *bufPtr,unsigned int bufSize,
+                              int *mskp,int *valp)
+{
+       int ret;
+       v4l2_std_id id;
+       ret = pvr2_std_str_to_id(&id,bufPtr,bufSize);
+       if (ret < 0) return ret;
+       if (mskp) *mskp = id;
+       if (valp) *valp = id;
+       return 0;
+}
+
+static int ctrl_stdcur_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       *vp = cptr->hdw->std_mask_cur;
+       return 0;
+}
+
+static int ctrl_stdcur_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+       v4l2_std_id ns;
+       ns = hdw->std_mask_cur;
+       ns = (ns & ~m) | (v & m);
+       if (ns == hdw->std_mask_cur) return 0;
+       hdw->std_mask_cur = ns;
+       hdw->std_dirty = !0;
+       return 0;
+}
+
+static int ctrl_stdcur_is_dirty(struct pvr2_ctrl *cptr)
+{
+       return cptr->hdw->std_dirty != 0;
+}
+
+static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr)
+{
+       cptr->hdw->std_dirty = 0;
+}
+
+static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       struct pvr2_hdw *hdw = cptr->hdw;
+       pvr2_hdw_status_poll(hdw);
+       *vp = hdw->tuner_signal_info.signal;
+       return 0;
+}
+
+static int ctrl_audio_modes_present_get(struct pvr2_ctrl *cptr,int *vp)
+{
+       int val = 0;
+       unsigned int subchan;
+       struct pvr2_hdw *hdw = cptr->hdw;
+       pvr2_hdw_status_poll(hdw);
+       subchan = hdw->tuner_signal_info.rxsubchans;
+       if (subchan & V4L2_TUNER_SUB_MONO) {
+               val |= (1 << V4L2_TUNER_MODE_MONO);
+       }
+       if (subchan & V4L2_TUNER_SUB_STEREO) {
+               val |= (1 << V4L2_TUNER_MODE_STEREO);
+       }
+       if (subchan & V4L2_TUNER_SUB_LANG1) {
+               val |= (1 << V4L2_TUNER_MODE_LANG1);
+       }
+       if (subchan & V4L2_TUNER_SUB_LANG2) {
+               val |= (1 << V4L2_TUNER_MODE_LANG2);
+       }
+       *vp = val;
+       return 0;
+}
+
+
+#define DEFINT(vmin,vmax) \
+       .type = pvr2_ctl_int, \
+       .def.type_int.min_value = vmin, \
+       .def.type_int.max_value = vmax
+
+#define DEFENUM(tab) \
+       .type = pvr2_ctl_enum, \
+       .def.type_enum.count = ARRAY_SIZE(tab), \
+       .def.type_enum.value_names = tab
+
+#define DEFBOOL \
+       .type = pvr2_ctl_bool
+
+#define DEFMASK(msk,tab) \
+       .type = pvr2_ctl_bitmask, \
+       .def.type_bitmask.valid_bits = msk, \
+       .def.type_bitmask.bit_names = tab
+
+#define DEFREF(vname) \
+       .set_value = ctrl_set_##vname, \
+       .get_value = ctrl_get_##vname, \
+       .is_dirty = ctrl_isdirty_##vname, \
+       .clear_dirty = ctrl_cleardirty_##vname
+
+
+#define VCREATE_FUNCS(vname) \
+static int ctrl_get_##vname(struct pvr2_ctrl *cptr,int *vp) \
+{*vp = cptr->hdw->vname##_val; return 0;} \
+static int ctrl_set_##vname(struct pvr2_ctrl *cptr,int m,int v) \
+{cptr->hdw->vname##_val = v; cptr->hdw->vname##_dirty = !0; return 0;} \
+static int ctrl_isdirty_##vname(struct pvr2_ctrl *cptr) \
+{return cptr->hdw->vname##_dirty != 0;} \
+static void ctrl_cleardirty_##vname(struct pvr2_ctrl *cptr) \
+{cptr->hdw->vname##_dirty = 0;}
+
+VCREATE_FUNCS(brightness)
+VCREATE_FUNCS(contrast)
+VCREATE_FUNCS(saturation)
+VCREATE_FUNCS(hue)
+VCREATE_FUNCS(volume)
+VCREATE_FUNCS(balance)
+VCREATE_FUNCS(bass)
+VCREATE_FUNCS(treble)
+VCREATE_FUNCS(mute)
+VCREATE_FUNCS(cropl)
+VCREATE_FUNCS(cropt)
+VCREATE_FUNCS(cropw)
+VCREATE_FUNCS(croph)
+VCREATE_FUNCS(audiomode)
+VCREATE_FUNCS(res_hor)
+VCREATE_FUNCS(res_ver)
+VCREATE_FUNCS(srate)
+
+/* Table definition of all controls which can be manipulated */
+static const struct pvr2_ctl_info control_defs[] = {
+       {
+               .v4l_id = V4L2_CID_BRIGHTNESS,
+               .desc = "Brightness",
+               .name = "brightness",
+               .default_value = 128,
+               DEFREF(brightness),
+               DEFINT(0,255),
+       },{
+               .v4l_id = V4L2_CID_CONTRAST,
+               .desc = "Contrast",
+               .name = "contrast",
+               .default_value = 68,
+               DEFREF(contrast),
+               DEFINT(0,127),
+       },{
+               .v4l_id = V4L2_CID_SATURATION,
+               .desc = "Saturation",
+               .name = "saturation",
+               .default_value = 64,
+               DEFREF(saturation),
+               DEFINT(0,127),
+       },{
+               .v4l_id = V4L2_CID_HUE,
+               .desc = "Hue",
+               .name = "hue",
+               .default_value = 0,
+               DEFREF(hue),
+               DEFINT(-128,127),
+       },{
+               .v4l_id = V4L2_CID_AUDIO_VOLUME,
+               .desc = "Volume",
+               .name = "volume",
+               .default_value = 62000,
+               DEFREF(volume),
+               DEFINT(0,65535),
+       },{
+               .v4l_id = V4L2_CID_AUDIO_BALANCE,
+               .desc = "Balance",
+               .name = "balance",
+               .default_value = 0,
+               DEFREF(balance),
+               DEFINT(-32768,32767),
+       },{
+               .v4l_id = V4L2_CID_AUDIO_BASS,
+               .desc = "Bass",
+               .name = "bass",
+               .default_value = 0,
+               DEFREF(bass),
+               DEFINT(-32768,32767),
+       },{
+               .v4l_id = V4L2_CID_AUDIO_TREBLE,
+               .desc = "Treble",
+               .name = "treble",
+               .default_value = 0,
+               DEFREF(treble),
+               DEFINT(-32768,32767),
+       },{
+               .v4l_id = V4L2_CID_AUDIO_MUTE,
+               .desc = "Mute",
+               .name = "mute",
+               .default_value = 0,
+               DEFREF(mute),
+               DEFBOOL,
+       }, {
+               .desc = "Capture crop left margin",
+               .name = "crop_left",
+               .internal_id = PVR2_CID_CROPL,
+               .default_value = 0,
+               DEFREF(cropl),
+               DEFINT(-129, 340),
+               .get_min_value = ctrl_cropl_min_get,
+               .get_max_value = ctrl_cropl_max_get,
+               .get_def_value = ctrl_get_cropcapdl,
+       }, {
+               .desc = "Capture crop top margin",
+               .name = "crop_top",
+               .internal_id = PVR2_CID_CROPT,
+               .default_value = 0,
+               DEFREF(cropt),
+               DEFINT(-35, 544),
+               .get_min_value = ctrl_cropt_min_get,
+               .get_max_value = ctrl_cropt_max_get,
+               .get_def_value = ctrl_get_cropcapdt,
+       }, {
+               .desc = "Capture crop width",
+               .name = "crop_width",
+               .internal_id = PVR2_CID_CROPW,
+               .default_value = 720,
+               DEFREF(cropw),
+               DEFINT(0, 864),
+               .get_max_value = ctrl_cropw_max_get,
+               .get_def_value = ctrl_get_cropcapdw,
+       }, {
+               .desc = "Capture crop height",
+               .name = "crop_height",
+               .internal_id = PVR2_CID_CROPH,
+               .default_value = 480,
+               DEFREF(croph),
+               DEFINT(0, 576),
+               .get_max_value = ctrl_croph_max_get,
+               .get_def_value = ctrl_get_cropcapdh,
+       }, {
+               .desc = "Capture capability pixel aspect numerator",
+               .name = "cropcap_pixel_numerator",
+               .internal_id = PVR2_CID_CROPCAPPAN,
+               .get_value = ctrl_get_cropcappan,
+       }, {
+               .desc = "Capture capability pixel aspect denominator",
+               .name = "cropcap_pixel_denominator",
+               .internal_id = PVR2_CID_CROPCAPPAD,
+               .get_value = ctrl_get_cropcappad,
+       }, {
+               .desc = "Capture capability bounds top",
+               .name = "cropcap_bounds_top",
+               .internal_id = PVR2_CID_CROPCAPBT,
+               .get_value = ctrl_get_cropcapbt,
+       }, {
+               .desc = "Capture capability bounds left",
+               .name = "cropcap_bounds_left",
+               .internal_id = PVR2_CID_CROPCAPBL,
+               .get_value = ctrl_get_cropcapbl,
+       }, {
+               .desc = "Capture capability bounds width",
+               .name = "cropcap_bounds_width",
+               .internal_id = PVR2_CID_CROPCAPBW,
+               .get_value = ctrl_get_cropcapbw,
+       }, {
+               .desc = "Capture capability bounds height",
+               .name = "cropcap_bounds_height",
+               .internal_id = PVR2_CID_CROPCAPBH,
+               .get_value = ctrl_get_cropcapbh,
+       },{
+               .desc = "Video Source",
+               .name = "input",
+               .internal_id = PVR2_CID_INPUT,
+               .default_value = PVR2_CVAL_INPUT_TV,
+               .check_value = ctrl_check_input,
+               DEFREF(input),
+               DEFENUM(control_values_input),
+       },{
+               .desc = "Audio Mode",
+               .name = "audio_mode",
+               .internal_id = PVR2_CID_AUDIOMODE,
+               .default_value = V4L2_TUNER_MODE_STEREO,
+               DEFREF(audiomode),
+               DEFENUM(control_values_audiomode),
+       },{
+               .desc = "Horizontal capture resolution",
+               .name = "resolution_hor",
+               .internal_id = PVR2_CID_HRES,
+               .default_value = 720,
+               DEFREF(res_hor),
+               DEFINT(19,720),
+       },{
+               .desc = "Vertical capture resolution",
+               .name = "resolution_ver",
+               .internal_id = PVR2_CID_VRES,
+               .default_value = 480,
+               DEFREF(res_ver),
+               DEFINT(17,576),
+               /* Hook in check for video standard and adjust maximum
+                  depending on the standard. */
+               .get_max_value = ctrl_vres_max_get,
+               .get_min_value = ctrl_vres_min_get,
+       },{
+               .v4l_id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
+               .default_value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
+               .desc = "Audio Sampling Frequency",
+               .name = "srate",
+               DEFREF(srate),
+               DEFENUM(control_values_srate),
+       },{
+               .desc = "Tuner Frequency (Hz)",
+               .name = "frequency",
+               .internal_id = PVR2_CID_FREQUENCY,
+               .default_value = 0,
+               .set_value = ctrl_freq_set,
+               .get_value = ctrl_freq_get,
+               .is_dirty = ctrl_freq_is_dirty,
+               .clear_dirty = ctrl_freq_clear_dirty,
+               DEFINT(0,0),
+               /* Hook in check for input value (tv/radio) and adjust
+                  max/min values accordingly */
+               .get_max_value = ctrl_freq_max_get,
+               .get_min_value = ctrl_freq_min_get,
+       },{
+               .desc = "Channel",
+               .name = "channel",
+               .set_value = ctrl_channel_set,
+               .get_value = ctrl_channel_get,
+               DEFINT(0,FREQTABLE_SIZE),
+       },{
+               .desc = "Channel Program Frequency",
+               .name = "freq_table_value",
+               .set_value = ctrl_channelfreq_set,
+               .get_value = ctrl_channelfreq_get,
+               DEFINT(0,0),
+               /* Hook in check for input value (tv/radio) and adjust
+                  max/min values accordingly */
+               .get_max_value = ctrl_freq_max_get,
+               .get_min_value = ctrl_freq_min_get,
+       },{
+               .desc = "Channel Program ID",
+               .name = "freq_table_channel",
+               .set_value = ctrl_channelprog_set,
+               .get_value = ctrl_channelprog_get,
+               DEFINT(0,FREQTABLE_SIZE),
+       },{
+               .desc = "Streaming Enabled",
+               .name = "streaming_enabled",
+               .get_value = ctrl_streamingenabled_get,
+               DEFBOOL,
+       },{
+               .desc = "USB Speed",
+               .name = "usb_speed",
+               .get_value = ctrl_hsm_get,
+               DEFENUM(control_values_hsm),
+       },{
+               .desc = "Master State",
+               .name = "master_state",
+               .get_value = ctrl_masterstate_get,
+               DEFENUM(pvr2_state_names),
+       },{
+               .desc = "Signal Present",
+               .name = "signal_present",
+               .get_value = ctrl_signal_get,
+               DEFINT(0,65535),
+       },{
+               .desc = "Audio Modes Present",
+               .name = "audio_modes_present",
+               .get_value = ctrl_audio_modes_present_get,
+               /* For this type we "borrow" the V4L2_TUNER_MODE enum from
+                  v4l.  Nothing outside of this module cares about this,
+                  but I reuse it in order to also reuse the
+                  control_values_audiomode string table. */
+               DEFMASK(((1 << V4L2_TUNER_MODE_MONO)|
+                        (1 << V4L2_TUNER_MODE_STEREO)|
+                        (1 << V4L2_TUNER_MODE_LANG1)|
+                        (1 << V4L2_TUNER_MODE_LANG2)),
+                       control_values_audiomode),
+       },{
+               .desc = "Video Standards Available Mask",
+               .name = "video_standard_mask_available",
+               .internal_id = PVR2_CID_STDAVAIL,
+               .skip_init = !0,
+               .get_value = ctrl_stdavail_get,
+               .set_value = ctrl_stdavail_set,
+               .val_to_sym = ctrl_std_val_to_sym,
+               .sym_to_val = ctrl_std_sym_to_val,
+               .type = pvr2_ctl_bitmask,
+       },{
+               .desc = "Video Standards In Use Mask",
+               .name = "video_standard_mask_active",
+               .internal_id = PVR2_CID_STDCUR,
+               .skip_init = !0,
+               .get_value = ctrl_stdcur_get,
+               .set_value = ctrl_stdcur_set,
+               .is_dirty = ctrl_stdcur_is_dirty,
+               .clear_dirty = ctrl_stdcur_clear_dirty,
+               .val_to_sym = ctrl_std_val_to_sym,
+               .sym_to_val = ctrl_std_sym_to_val,
+               .type = pvr2_ctl_bitmask,
+       },{
+               .desc = "Video Standards Detected Mask",
+               .name = "video_standard_mask_detected",
+               .internal_id = PVR2_CID_STDDETECT,
+               .skip_init = !0,
+               .get_value = ctrl_stddetect_get,
+               .val_to_sym = ctrl_std_val_to_sym,
+               .sym_to_val = ctrl_std_sym_to_val,
+               .type = pvr2_ctl_bitmask,
+       }
+};
+
+#define CTRLDEF_COUNT ARRAY_SIZE(control_defs)
+
+
+const char *pvr2_config_get_name(enum pvr2_config cfg)
+{
+       switch (cfg) {
+       case pvr2_config_empty: return "empty";
+       case pvr2_config_mpeg: return "mpeg";
+       case pvr2_config_vbi: return "vbi";
+       case pvr2_config_pcm: return "pcm";
+       case pvr2_config_rawvideo: return "raw video";
+       }
+       return "<unknown>";
+}
+
+
+struct usb_device *pvr2_hdw_get_dev(struct pvr2_hdw *hdw)
+{
+       return hdw->usb_dev;
+}
+
+
+unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *hdw)
+{
+       return hdw->serial_number;
+}
+
+
+const char *pvr2_hdw_get_bus_info(struct pvr2_hdw *hdw)
+{
+       return hdw->bus_info;
+}
+
+
+const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *hdw)
+{
+       return hdw->identifier;
+}
+
+
+unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw)
+{
+       return hdw->freqSelector ? hdw->freqValTelevision : hdw->freqValRadio;
+}
+
+/* Set the currently tuned frequency and account for all possible
+   driver-core side effects of this action. */
+static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
+{
+       if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+               if (hdw->freqSelector) {
+                       /* Swing over to radio frequency selection */
+                       hdw->freqSelector = 0;
+                       hdw->freqDirty = !0;
+               }
+               if (hdw->freqValRadio != val) {
+                       hdw->freqValRadio = val;
+                       hdw->freqSlotRadio = 0;
+                       hdw->freqDirty = !0;
+               }
+       } else {
+               if (!(hdw->freqSelector)) {
+                       /* Swing over to television frequency selection */
+                       hdw->freqSelector = 1;
+                       hdw->freqDirty = !0;
+               }
+               if (hdw->freqValTelevision != val) {
+                       hdw->freqValTelevision = val;
+                       hdw->freqSlotTelevision = 0;
+                       hdw->freqDirty = !0;
+               }
+       }
+}
+
+int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw)
+{
+       return hdw->unit_number;
+}
+
+
+/* Attempt to locate one of the given set of files.  Messages are logged
+   appropriate to what has been found.  The return value will be 0 or
+   greater on success (it will be the index of the file name found) and
+   fw_entry will be filled in.  Otherwise a negative error is returned on
+   failure.  If the return value is -ENOENT then no viable firmware file
+   could be located. */
+static int pvr2_locate_firmware(struct pvr2_hdw *hdw,
+                               const struct firmware **fw_entry,
+                               const char *fwtypename,
+                               unsigned int fwcount,
+                               const char *fwnames[])
+{
+       unsigned int idx;
+       int ret = -EINVAL;
+       for (idx = 0; idx < fwcount; idx++) {
+               ret = request_firmware(fw_entry,
+                                      fwnames[idx],
+                                      &hdw->usb_dev->dev);
+               if (!ret) {
+                       trace_firmware("Located %s firmware: %s;"
+                                      " uploading...",
+                                      fwtypename,
+                                      fwnames[idx]);
+                       return idx;
+               }
+               if (ret == -ENOENT) continue;
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "request_firmware fatal error with code=%d",ret);
+               return ret;
+       }
+       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                  "***WARNING***"
+                  " Device %s firmware"
+                  " seems to be missing.",
+                  fwtypename);
+       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                  "Did you install the pvrusb2 firmware files"
+                  " in their proper location?");
+       if (fwcount == 1) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "request_firmware unable to locate %s file %s",
+                          fwtypename,fwnames[0]);
+       } else {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "request_firmware unable to locate"
+                          " one of the following %s files:",
+                          fwtypename);
+               for (idx = 0; idx < fwcount; idx++) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "request_firmware: Failed to find %s",
+                                  fwnames[idx]);
+               }
+       }
+       return ret;
+}
+
+
+/*
+ * pvr2_upload_firmware1().
+ *
+ * Send the 8051 firmware to the device.  After the upload, arrange for
+ * device to re-enumerate.
+ *
+ * NOTE : the pointer to the firmware data given by request_firmware()
+ * is not suitable for an usb transaction.
+ *
+ */
+static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
+{
+       const struct firmware *fw_entry = NULL;
+       void  *fw_ptr;
+       unsigned int pipe;
+       unsigned int fwsize;
+       int ret;
+       u16 address;
+
+       if (!hdw->hdw_desc->fx2_firmware.cnt) {
+               hdw->fw1_state = FW1_STATE_OK;
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Connected device type defines"
+                          " no firmware to upload; ignoring firmware");
+               return -ENOTTY;
+       }
+
+       hdw->fw1_state = FW1_STATE_FAILED; // default result
+
+       trace_firmware("pvr2_upload_firmware1");
+
+       ret = pvr2_locate_firmware(hdw,&fw_entry,"fx2 controller",
+                                  hdw->hdw_desc->fx2_firmware.cnt,
+                                  hdw->hdw_desc->fx2_firmware.lst);
+       if (ret < 0) {
+               if (ret == -ENOENT) hdw->fw1_state = FW1_STATE_MISSING;
+               return ret;
+       }
+
+       usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f));
+
+       pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
+       fwsize = fw_entry->size;
+
+       if ((fwsize != 0x2000) &&
+           (!(hdw->hdw_desc->flag_fx2_16kb && (fwsize == 0x4000)))) {
+               if (hdw->hdw_desc->flag_fx2_16kb) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "Wrong fx2 firmware size"
+                                  " (expected 8192 or 16384, got %u)",
+                                  fwsize);
+               } else {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "Wrong fx2 firmware size"
+                                  " (expected 8192, got %u)",
+                                  fwsize);
+               }
+               release_firmware(fw_entry);
+               return -ENOMEM;
+       }
+
+       fw_ptr = kmalloc(0x800, GFP_KERNEL);
+       if (fw_ptr == NULL){
+               release_firmware(fw_entry);
+               return -ENOMEM;
+       }
+
+       /* We have to hold the CPU during firmware upload. */
+       pvr2_hdw_cpureset_assert(hdw,1);
+
+       /* upload the firmware to address 0000-1fff in 2048 (=0x800) bytes
+          chunk. */
+
+       ret = 0;
+       for (address = 0; address < fwsize; address += 0x800) {
+               memcpy(fw_ptr, fw_entry->data + address, 0x800);
+               ret += usb_control_msg(hdw->usb_dev, pipe, 0xa0, 0x40, address,
+                                      0, fw_ptr, 0x800, HZ);
+       }
+
+       trace_firmware("Upload done, releasing device's CPU");
+
+       /* Now release the CPU.  It will disconnect and reconnect later. */
+       pvr2_hdw_cpureset_assert(hdw,0);
+
+       kfree(fw_ptr);
+       release_firmware(fw_entry);
+
+       trace_firmware("Upload done (%d bytes sent)",ret);
+
+       /* We should have written fwsize bytes */
+       if (ret == fwsize) {
+               hdw->fw1_state = FW1_STATE_RELOAD;
+               return 0;
+       }
+
+       return -EIO;
+}
+
+
+/*
+ * pvr2_upload_firmware2()
+ *
+ * This uploads encoder firmware on endpoint 2.
+ *
+ */
+
+int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
+{
+       const struct firmware *fw_entry = NULL;
+       void  *fw_ptr;
+       unsigned int pipe, fw_len, fw_done, bcnt, icnt;
+       int actual_length;
+       int ret = 0;
+       int fwidx;
+       static const char *fw_files[] = {
+               CX2341X_FIRM_ENC_FILENAME,
+       };
+
+       if (hdw->hdw_desc->flag_skip_cx23416_firmware) {
+               return 0;
+       }
+
+       trace_firmware("pvr2_upload_firmware2");
+
+       ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder",
+                                  ARRAY_SIZE(fw_files), fw_files);
+       if (ret < 0) return ret;
+       fwidx = ret;
+       ret = 0;
+       /* Since we're about to completely reinitialize the encoder,
+          invalidate our cached copy of its configuration state.  Next
+          time we configure the encoder, then we'll fully configure it. */
+       hdw->enc_cur_valid = 0;
+
+       /* Encoder is about to be reset so note that as far as we're
+          concerned now, the encoder has never been run. */
+       del_timer_sync(&hdw->encoder_run_timer);
+       if (hdw->state_encoder_runok) {
+               hdw->state_encoder_runok = 0;
+               trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
+       }
+
+       /* First prepare firmware loading */
+       ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/
+       ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/
+       ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/
+       ret |= pvr2_hdw_cmd_deep_reset(hdw);
+       ret |= pvr2_write_register(hdw, 0xa064, 0x00000000); /*APU command*/
+       ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000408); /*gpio dir*/
+       ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/
+       ret |= pvr2_write_register(hdw, 0x9058, 0xffffffed); /*VPU ctrl*/
+       ret |= pvr2_write_register(hdw, 0x9054, 0xfffffffd); /*reset hw blocks*/
+       ret |= pvr2_write_register(hdw, 0x07f8, 0x80000800); /*encoder SDRAM refresh*/
+       ret |= pvr2_write_register(hdw, 0x07fc, 0x0000001a); /*encoder SDRAM pre-charge*/
+       ret |= pvr2_write_register(hdw, 0x0700, 0x00000000); /*I2C clock*/
+       ret |= pvr2_write_register(hdw, 0xaa00, 0x00000000); /*unknown*/
+       ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/
+       ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/
+       ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/
+       ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_FWPOST1);
+       ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
+
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "firmware2 upload prep failed, ret=%d",ret);
+               release_firmware(fw_entry);
+               goto done;
+       }
+
+       /* Now send firmware */
+
+       fw_len = fw_entry->size;
+
+       if (fw_len % sizeof(u32)) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "size of %s firmware"
+                          " must be a multiple of %zu bytes",
+                          fw_files[fwidx],sizeof(u32));
+               release_firmware(fw_entry);
+               ret = -EINVAL;
+               goto done;
+       }
+
+       fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
+       if (fw_ptr == NULL){
+               release_firmware(fw_entry);
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "failed to allocate memory for firmware2 upload");
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT);
+
+       fw_done = 0;
+       for (fw_done = 0; fw_done < fw_len;) {
+               bcnt = fw_len - fw_done;
+               if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE;
+               memcpy(fw_ptr, fw_entry->data + fw_done, bcnt);
+               /* Usbsnoop log shows that we must swap bytes... */
+               /* Some background info: The data being swapped here is a
+                  firmware image destined for the mpeg encoder chip that
+                  lives at the other end of a USB endpoint.  The encoder
+                  chip always talks in 32 bit chunks and its storage is
+                  organized into 32 bit words.  However from the file
+                  system to the encoder chip everything is purely a byte
+                  stream.  The firmware file's contents are always 32 bit
+                  swapped from what the encoder expects.  Thus the need
+                  always exists to swap the bytes regardless of the endian
+                  type of the host processor and therefore swab32() makes
+                  the most sense. */
+               for (icnt = 0; icnt < bcnt/4 ; icnt++)
+                       ((u32 *)fw_ptr)[icnt] = swab32(((u32 *)fw_ptr)[icnt]);
+
+               ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt,
+                                   &actual_length, HZ);
+               ret |= (actual_length != bcnt);
+               if (ret) break;
+               fw_done += bcnt;
+       }
+
+       trace_firmware("upload of %s : %i / %i ",
+                      fw_files[fwidx],fw_done,fw_len);
+
+       kfree(fw_ptr);
+       release_firmware(fw_entry);
+
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "firmware2 upload transfer failure");
+               goto done;
+       }
+
+       /* Finish upload */
+
+       ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/
+       ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/
+       ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
+
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "firmware2 upload post-proc failure");
+       }
+
+ done:
+       if (hdw->hdw_desc->signal_routing_scheme ==
+           PVR2_ROUTING_SCHEME_GOTVIEW) {
+               /* Ensure that GPIO 11 is set to output for GOTVIEW
+                  hardware. */
+               pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
+       }
+       return ret;
+}
+
+
+static const char *pvr2_get_state_name(unsigned int st)
+{
+       if (st < ARRAY_SIZE(pvr2_state_names)) {
+               return pvr2_state_names[st];
+       }
+       return "???";
+}
+
+static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl)
+{
+       /* Even though we really only care about the video decoder chip at
+          this point, we'll broadcast stream on/off to all sub-devices
+          anyway, just in case somebody else wants to hear the
+          command... */
+       pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 stream=%s",
+                  (enablefl ? "on" : "off"));
+       v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl);
+       v4l2_device_call_all(&hdw->v4l2_dev, 0, audio, s_stream, enablefl);
+       if (hdw->decoder_client_id) {
+               /* We get here if the encoder has been noticed.  Otherwise
+                  we'll issue a warning to the user (which should
+                  normally never happen). */
+               return 0;
+       }
+       if (!hdw->flag_decoder_missed) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "WARNING: No decoder present");
+               hdw->flag_decoder_missed = !0;
+               trace_stbit("flag_decoder_missed",
+                           hdw->flag_decoder_missed);
+       }
+       return -EIO;
+}
+
+
+int pvr2_hdw_get_state(struct pvr2_hdw *hdw)
+{
+       return hdw->master_state;
+}
+
+
+static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *hdw)
+{
+       if (!hdw->flag_tripped) return 0;
+       hdw->flag_tripped = 0;
+       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                  "Clearing driver error statuss");
+       return !0;
+}
+
+
+int pvr2_hdw_untrip(struct pvr2_hdw *hdw)
+{
+       int fl;
+       LOCK_TAKE(hdw->big_lock); do {
+               fl = pvr2_hdw_untrip_unlocked(hdw);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+       if (fl) pvr2_hdw_state_sched(hdw);
+       return 0;
+}
+
+
+
+
+int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw)
+{
+       return hdw->state_pipeline_req != 0;
+}
+
+
+int pvr2_hdw_set_streaming(struct pvr2_hdw *hdw,int enable_flag)
+{
+       int ret,st;
+       LOCK_TAKE(hdw->big_lock); do {
+               pvr2_hdw_untrip_unlocked(hdw);
+               if ((!enable_flag) != !(hdw->state_pipeline_req)) {
+                       hdw->state_pipeline_req = enable_flag != 0;
+                       pvr2_trace(PVR2_TRACE_START_STOP,
+                                  "/*--TRACE_STREAM--*/ %s",
+                                  enable_flag ? "enable" : "disable");
+               }
+               pvr2_hdw_state_sched(hdw);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+       if ((ret = pvr2_hdw_wait(hdw,0)) < 0) return ret;
+       if (enable_flag) {
+               while ((st = hdw->master_state) != PVR2_STATE_RUN) {
+                       if (st != PVR2_STATE_READY) return -EIO;
+                       if ((ret = pvr2_hdw_wait(hdw,st)) < 0) return ret;
+               }
+       }
+       return 0;
+}
+
+
+int pvr2_hdw_set_stream_type(struct pvr2_hdw *hdw,enum pvr2_config config)
+{
+       int fl;
+       LOCK_TAKE(hdw->big_lock);
+       if ((fl = (hdw->desired_stream_type != config)) != 0) {
+               hdw->desired_stream_type = config;
+               hdw->state_pipeline_config = 0;
+               trace_stbit("state_pipeline_config",
+                           hdw->state_pipeline_config);
+               pvr2_hdw_state_sched(hdw);
+       }
+       LOCK_GIVE(hdw->big_lock);
+       if (fl) return 0;
+       return pvr2_hdw_wait(hdw,0);
+}
+
+
+static int get_default_tuner_type(struct pvr2_hdw *hdw)
+{
+       int unit_number = hdw->unit_number;
+       int tp = -1;
+       if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
+               tp = tuner[unit_number];
+       }
+       if (tp < 0) return -EINVAL;
+       hdw->tuner_type = tp;
+       hdw->tuner_updated = !0;
+       return 0;
+}
+
+
+static v4l2_std_id get_default_standard(struct pvr2_hdw *hdw)
+{
+       int unit_number = hdw->unit_number;
+       int tp = 0;
+       if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
+               tp = video_std[unit_number];
+               if (tp) return tp;
+       }
+       return 0;
+}
+
+
+static unsigned int get_default_error_tolerance(struct pvr2_hdw *hdw)
+{
+       int unit_number = hdw->unit_number;
+       int tp = 0;
+       if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
+               tp = tolerance[unit_number];
+       }
+       return tp;
+}
+
+
+static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw)
+{
+       /* Try a harmless request to fetch the eeprom's address over
+          endpoint 1.  See what happens.  Only the full FX2 image can
+          respond to this.  If this probe fails then likely the FX2
+          firmware needs be loaded. */
+       int result;
+       LOCK_TAKE(hdw->ctl_lock); do {
+               hdw->cmd_buffer[0] = FX2CMD_GET_EEPROM_ADDR;
+               result = pvr2_send_request_ex(hdw,HZ*1,!0,
+                                          hdw->cmd_buffer,1,
+                                          hdw->cmd_buffer,1);
+               if (result < 0) break;
+       } while(0); LOCK_GIVE(hdw->ctl_lock);
+       if (result) {
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "Probe of device endpoint 1 result status %d",
+                          result);
+       } else {
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "Probe of device endpoint 1 succeeded");
+       }
+       return result == 0;
+}
+
+struct pvr2_std_hack {
+       v4l2_std_id pat;  /* Pattern to match */
+       v4l2_std_id msk;  /* Which bits we care about */
+       v4l2_std_id std;  /* What additional standards or default to set */
+};
+
+/* This data structure labels specific combinations of standards from
+   tveeprom that we'll try to recognize.  If we recognize one, then assume
+   a specified default standard to use.  This is here because tveeprom only
+   tells us about available standards not the intended default standard (if
+   any) for the device in question.  We guess the default based on what has
+   been reported as available.  Note that this is only for guessing a
+   default - which can always be overridden explicitly - and if the user
+   has otherwise named a default then that default will always be used in
+   place of this table. */
+static const struct pvr2_std_hack std_eeprom_maps[] = {
+       {       /* PAL(B/G) */
+               .pat = V4L2_STD_B|V4L2_STD_GH,
+               .std = V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_PAL_G,
+       },
+       {       /* NTSC(M) */
+               .pat = V4L2_STD_MN,
+               .std = V4L2_STD_NTSC_M,
+       },
+       {       /* PAL(I) */
+               .pat = V4L2_STD_PAL_I,
+               .std = V4L2_STD_PAL_I,
+       },
+       {       /* SECAM(L/L') */
+               .pat = V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC,
+               .std = V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC,
+       },
+       {       /* PAL(D/D1/K) */
+               .pat = V4L2_STD_DK,
+               .std = V4L2_STD_PAL_D|V4L2_STD_PAL_D1|V4L2_STD_PAL_K,
+       },
+};
+
+static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
+{
+       char buf[40];
+       unsigned int bcnt;
+       v4l2_std_id std1,std2,std3;
+
+       std1 = get_default_standard(hdw);
+       std3 = std1 ? 0 : hdw->hdw_desc->default_std_mask;
+
+       bcnt = pvr2_std_id_to_str(buf,sizeof(buf),hdw->std_mask_eeprom);
+       pvr2_trace(PVR2_TRACE_STD,
+                  "Supported video standard(s) reported available"
+                  " in hardware: %.*s",
+                  bcnt,buf);
+
+       hdw->std_mask_avail = hdw->std_mask_eeprom;
+
+       std2 = (std1|std3) & ~hdw->std_mask_avail;
+       if (std2) {
+               bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std2);
+               pvr2_trace(PVR2_TRACE_STD,
+                          "Expanding supported video standards"
+                          " to include: %.*s",
+                          bcnt,buf);
+               hdw->std_mask_avail |= std2;
+       }
+
+       hdw->std_info_cur.def.type_bitmask.valid_bits = hdw->std_mask_avail;
+
+       if (std1) {
+               bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std1);
+               pvr2_trace(PVR2_TRACE_STD,
+                          "Initial video standard forced to %.*s",
+                          bcnt,buf);
+               hdw->std_mask_cur = std1;
+               hdw->std_dirty = !0;
+               return;
+       }
+       if (std3) {
+               bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std3);
+               pvr2_trace(PVR2_TRACE_STD,
+                          "Initial video standard"
+                          " (determined by device type): %.*s",bcnt,buf);
+               hdw->std_mask_cur = std3;
+               hdw->std_dirty = !0;
+               return;
+       }
+
+       {
+               unsigned int idx;
+               for (idx = 0; idx < ARRAY_SIZE(std_eeprom_maps); idx++) {
+                       if (std_eeprom_maps[idx].msk ?
+                           ((std_eeprom_maps[idx].pat ^
+                            hdw->std_mask_eeprom) &
+                            std_eeprom_maps[idx].msk) :
+                           (std_eeprom_maps[idx].pat !=
+                            hdw->std_mask_eeprom)) continue;
+                       bcnt = pvr2_std_id_to_str(buf,sizeof(buf),
+                                                 std_eeprom_maps[idx].std);
+                       pvr2_trace(PVR2_TRACE_STD,
+                                  "Initial video standard guessed as %.*s",
+                                  bcnt,buf);
+                       hdw->std_mask_cur = std_eeprom_maps[idx].std;
+                       hdw->std_dirty = !0;
+                       return;
+               }
+       }
+
+}
+
+
+static unsigned int pvr2_copy_i2c_addr_list(
+       unsigned short *dst, const unsigned char *src,
+       unsigned int dst_max)
+{
+       unsigned int cnt = 0;
+       if (!src) return 0;
+       while (src[cnt] && (cnt + 1) < dst_max) {
+               dst[cnt] = src[cnt];
+               cnt++;
+       }
+       dst[cnt] = I2C_CLIENT_END;
+       return cnt;
+}
+
+
+static void pvr2_hdw_cx25840_vbi_hack(struct pvr2_hdw *hdw)
+{
+       /*
+         Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit of nuttiness
+         for cx25840 causes that module to correctly set up its video
+         scaling.  This is really a problem in the cx25840 module itself,
+         but we work around it here.  The problem has not been seen in
+         ivtv because there VBI is supported and set up.  We don't do VBI
+         here (at least not yet) and thus we never attempted to even set
+         it up.
+       */
+       struct v4l2_format fmt;
+       if (hdw->decoder_client_id != PVR2_CLIENT_ID_CX25840) {
+               /* We're not using a cx25840 so don't enable the hack */
+               return;
+       }
+
+       pvr2_trace(PVR2_TRACE_INIT,
+                  "Module ID %u:"
+                  " Executing cx25840 VBI hack",
+                  hdw->decoder_client_id);
+       memset(&fmt, 0, sizeof(fmt));
+       fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+       fmt.fmt.sliced.service_lines[0][21] = V4L2_SLICED_CAPTION_525;
+       fmt.fmt.sliced.service_lines[1][21] = V4L2_SLICED_CAPTION_525;
+       v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id,
+                            vbi, s_sliced_fmt, &fmt.fmt.sliced);
+}
+
+
+static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw,
+                               const struct pvr2_device_client_desc *cd)
+{
+       const char *fname;
+       unsigned char mid;
+       struct v4l2_subdev *sd;
+       unsigned int i2ccnt;
+       const unsigned char *p;
+       /* Arbitrary count - max # i2c addresses we will probe */
+       unsigned short i2caddr[25];
+
+       mid = cd->module_id;
+       fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL;
+       if (!fname) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Module ID %u for device %s has no name?"
+                          "  The driver might have a configuration problem.",
+                          mid,
+                          hdw->hdw_desc->description);
+               return -EINVAL;
+       }
+       pvr2_trace(PVR2_TRACE_INIT,
+                  "Module ID %u (%s) for device %s being loaded...",
+                  mid, fname,
+                  hdw->hdw_desc->description);
+
+       i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list,
+                                        ARRAY_SIZE(i2caddr));
+       if (!i2ccnt && ((p = (mid < ARRAY_SIZE(module_i2c_addresses)) ?
+                        module_i2c_addresses[mid] : NULL) != NULL)) {
+               /* Second chance: Try default i2c address list */
+               i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, p,
+                                                ARRAY_SIZE(i2caddr));
+               if (i2ccnt) {
+                       pvr2_trace(PVR2_TRACE_INIT,
+                                  "Module ID %u:"
+                                  " Using default i2c address list",
+                                  mid);
+               }
+       }
+
+       if (!i2ccnt) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Module ID %u (%s) for device %s:"
+                          " No i2c addresses."
+                          "  The driver might have a configuration problem.",
+                          mid, fname, hdw->hdw_desc->description);
+               return -EINVAL;
+       }
+
+       if (i2ccnt == 1) {
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "Module ID %u:"
+                          " Setting up with specified i2c address 0x%x",
+                          mid, i2caddr[0]);
+               sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap,
+                                        fname, i2caddr[0], NULL);
+       } else {
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "Module ID %u:"
+                          " Setting up with address probe list",
+                          mid);
+               sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap,
+                                        fname, 0, i2caddr);
+       }
+
+       if (!sd) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Module ID %u (%s) for device %s failed to load."
+                          "  Possible missing sub-device kernel module or"
+                          " initialization failure within module.",
+                          mid, fname, hdw->hdw_desc->description);
+               return -EIO;
+       }
+
+       /* Tag this sub-device instance with the module ID we know about.
+          In other places we'll use that tag to determine if the instance
+          requires special handling. */
+       sd->grp_id = mid;
+
+       pvr2_trace(PVR2_TRACE_INFO, "Attached sub-driver %s", fname);
+
+
+       /* client-specific setup... */
+       switch (mid) {
+       case PVR2_CLIENT_ID_CX25840:
+       case PVR2_CLIENT_ID_SAA7115:
+               hdw->decoder_client_id = mid;
+               break;
+       default: break;
+       }
+
+       return 0;
+}
+
+
+static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw)
+{
+       unsigned int idx;
+       const struct pvr2_string_table *cm;
+       const struct pvr2_device_client_table *ct;
+       int okFl = !0;
+
+       cm = &hdw->hdw_desc->client_modules;
+       for (idx = 0; idx < cm->cnt; idx++) {
+               request_module(cm->lst[idx]);
+       }
+
+       ct = &hdw->hdw_desc->client_table;
+       for (idx = 0; idx < ct->cnt; idx++) {
+               if (pvr2_hdw_load_subdev(hdw, &ct->lst[idx]) < 0) okFl = 0;
+       }
+       if (!okFl) {
+               hdw->flag_modulefail = !0;
+               pvr2_hdw_render_useless(hdw);
+       }
+}
+
+
+static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
+{
+       int ret;
+       unsigned int idx;
+       struct pvr2_ctrl *cptr;
+       int reloadFl = 0;
+       if (hdw->hdw_desc->fx2_firmware.cnt) {
+               if (!reloadFl) {
+                       reloadFl =
+                               (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints
+                                == 0);
+                       if (reloadFl) {
+                               pvr2_trace(PVR2_TRACE_INIT,
+                                          "USB endpoint config looks strange"
+                                          "; possibly firmware needs to be"
+                                          " loaded");
+                       }
+               }
+               if (!reloadFl) {
+                       reloadFl = !pvr2_hdw_check_firmware(hdw);
+                       if (reloadFl) {
+                               pvr2_trace(PVR2_TRACE_INIT,
+                                          "Check for FX2 firmware failed"
+                                          "; possibly firmware needs to be"
+                                          " loaded");
+                       }
+               }
+               if (reloadFl) {
+                       if (pvr2_upload_firmware1(hdw) != 0) {
+                               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                          "Failure uploading firmware1");
+                       }
+                       return;
+               }
+       }
+       hdw->fw1_state = FW1_STATE_OK;
+
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+
+       hdw->force_dirty = !0;
+
+       if (!hdw->hdw_desc->flag_no_powerup) {
+               pvr2_hdw_cmd_powerup(hdw);
+               if (!pvr2_hdw_dev_ok(hdw)) return;
+       }
+
+       /* Take the IR chip out of reset, if appropriate */
+       if (hdw->ir_scheme_active == PVR2_IR_SCHEME_ZILOG) {
+               pvr2_issue_simple_cmd(hdw,
+                                     FX2CMD_HCW_ZILOG_RESET |
+                                     (1 << 8) |
+                                     ((0) << 16));
+       }
+
+       // This step MUST happen after the earlier powerup step.
+       pvr2_i2c_core_init(hdw);
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+
+       pvr2_hdw_load_modules(hdw);
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+
+       v4l2_device_call_all(&hdw->v4l2_dev, 0, core, load_fw);
+
+       for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
+               cptr = hdw->controls + idx;
+               if (cptr->info->skip_init) continue;
+               if (!cptr->info->set_value) continue;
+               cptr->info->set_value(cptr,~0,cptr->info->default_value);
+       }
+
+       pvr2_hdw_cx25840_vbi_hack(hdw);
+
+       /* Set up special default values for the television and radio
+          frequencies here.  It's not really important what these defaults
+          are, but I set them to something usable in the Chicago area just
+          to make driver testing a little easier. */
+
+       hdw->freqValTelevision = default_tv_freq;
+       hdw->freqValRadio = default_radio_freq;
+
+       // Do not use pvr2_reset_ctl_endpoints() here.  It is not
+       // thread-safe against the normal pvr2_send_request() mechanism.
+       // (We should make it thread safe).
+
+       if (hdw->hdw_desc->flag_has_hauppauge_rom) {
+               ret = pvr2_hdw_get_eeprom_addr(hdw);
+               if (!pvr2_hdw_dev_ok(hdw)) return;
+               if (ret < 0) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "Unable to determine location of eeprom,"
+                                  " skipping");
+               } else {
+                       hdw->eeprom_addr = ret;
+                       pvr2_eeprom_analyze(hdw);
+                       if (!pvr2_hdw_dev_ok(hdw)) return;
+               }
+       } else {
+               hdw->tuner_type = hdw->hdw_desc->default_tuner_type;
+               hdw->tuner_updated = !0;
+               hdw->std_mask_eeprom = V4L2_STD_ALL;
+       }
+
+       if (hdw->serial_number) {
+               idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1,
+                               "sn-%lu", hdw->serial_number);
+       } else if (hdw->unit_number >= 0) {
+               idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1,
+                               "unit-%c",
+                               hdw->unit_number + 'a');
+       } else {
+               idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1,
+                               "unit-??");
+       }
+       hdw->identifier[idx] = 0;
+
+       pvr2_hdw_setup_std(hdw);
+
+       if (!get_default_tuner_type(hdw)) {
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "pvr2_hdw_setup: Tuner type overridden to %d",
+                          hdw->tuner_type);
+       }
+
+
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+
+       if (hdw->hdw_desc->signal_routing_scheme ==
+           PVR2_ROUTING_SCHEME_GOTVIEW) {
+               /* Ensure that GPIO 11 is set to output for GOTVIEW
+                  hardware. */
+               pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
+       }
+
+       pvr2_hdw_commit_setup(hdw);
+
+       hdw->vid_stream = pvr2_stream_create();
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+       pvr2_trace(PVR2_TRACE_INIT,
+                  "pvr2_hdw_setup: video stream is %p",hdw->vid_stream);
+       if (hdw->vid_stream) {
+               idx = get_default_error_tolerance(hdw);
+               if (idx) {
+                       pvr2_trace(PVR2_TRACE_INIT,
+                                  "pvr2_hdw_setup: video stream %p"
+                                  " setting tolerance %u",
+                                  hdw->vid_stream,idx);
+               }
+               pvr2_stream_setup(hdw->vid_stream,hdw->usb_dev,
+                                 PVR2_VID_ENDPOINT,idx);
+       }
+
+       if (!pvr2_hdw_dev_ok(hdw)) return;
+
+       hdw->flag_init_ok = !0;
+
+       pvr2_hdw_state_sched(hdw);
+}
+
+
+/* Set up the structure and attempt to put the device into a usable state.
+   This can be a time-consuming operation, which is why it is not done
+   internally as part of the create() step. */
+static void pvr2_hdw_setup(struct pvr2_hdw *hdw)
+{
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) begin",hdw);
+       do {
+               pvr2_hdw_setup_low(hdw);
+               pvr2_trace(PVR2_TRACE_INIT,
+                          "pvr2_hdw_setup(hdw=%p) done, ok=%d init_ok=%d",
+                          hdw,pvr2_hdw_dev_ok(hdw),hdw->flag_init_ok);
+               if (pvr2_hdw_dev_ok(hdw)) {
+                       if (hdw->flag_init_ok) {
+                               pvr2_trace(
+                                       PVR2_TRACE_INFO,
+                                       "Device initialization"
+                                       " completed successfully.");
+                               break;
+                       }
+                       if (hdw->fw1_state == FW1_STATE_RELOAD) {
+                               pvr2_trace(
+                                       PVR2_TRACE_INFO,
+                                       "Device microcontroller firmware"
+                                       " (re)loaded; it should now reset"
+                                       " and reconnect.");
+                               break;
+                       }
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "Device initialization was not successful.");
+                       if (hdw->fw1_state == FW1_STATE_MISSING) {
+                               pvr2_trace(
+                                       PVR2_TRACE_ERROR_LEGS,
+                                       "Giving up since device"
+                                       " microcontroller firmware"
+                                       " appears to be missing.");
+                               break;
+                       }
+               }
+               if (hdw->flag_modulefail) {
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "***WARNING*** pvrusb2 driver initialization"
+                               " failed due to the failure of one or more"
+                               " sub-device kernel modules.");
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "You need to resolve the failing condition"
+                               " before this driver can function.  There"
+                               " should be some earlier messages giving more"
+                               " information about the problem.");
+                       break;
+               }
+               if (procreload) {
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "Attempting pvrusb2 recovery by reloading"
+                               " primary firmware.");
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "If this works, device should disconnect"
+                               " and reconnect in a sane state.");
+                       hdw->fw1_state = FW1_STATE_UNKNOWN;
+                       pvr2_upload_firmware1(hdw);
+               } else {
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "***WARNING*** pvrusb2 device hardware"
+                               " appears to be jammed"
+                               " and I can't clear it.");
+                       pvr2_trace(
+                               PVR2_TRACE_ERROR_LEGS,
+                               "You might need to power cycle"
+                               " the pvrusb2 device"
+                               " in order to recover.");
+               }
+       } while (0);
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) end",hdw);
+}
+
+
+/* Perform second stage initialization.  Set callback pointer first so that
+   we can avoid a possible initialization race (if the kernel thread runs
+   before the callback has been set). */
+int pvr2_hdw_initialize(struct pvr2_hdw *hdw,
+                       void (*callback_func)(void *),
+                       void *callback_data)
+{
+       LOCK_TAKE(hdw->big_lock); do {
+               if (hdw->flag_disconnected) {
+                       /* Handle a race here: If we're already
+                          disconnected by this point, then give up.  If we
+                          get past this then we'll remain connected for
+                          the duration of initialization since the entire
+                          initialization sequence is now protected by the
+                          big_lock. */
+                       break;
+               }
+               hdw->state_data = callback_data;
+               hdw->state_func = callback_func;
+               pvr2_hdw_setup(hdw);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+       return hdw->flag_init_ok;
+}
+
+
+/* Create, set up, and return a structure for interacting with the
+   underlying hardware.  */
+struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+                                const struct usb_device_id *devid)
+{
+       unsigned int idx,cnt1,cnt2,m;
+       struct pvr2_hdw *hdw = NULL;
+       int valid_std_mask;
+       struct pvr2_ctrl *cptr;
+       struct usb_device *usb_dev;
+       const struct pvr2_device_desc *hdw_desc;
+       __u8 ifnum;
+       struct v4l2_queryctrl qctrl;
+       struct pvr2_ctl_info *ciptr;
+
+       usb_dev = interface_to_usbdev(intf);
+
+       hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info);
+
+       if (hdw_desc == NULL) {
+               pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_create:"
+                          " No device description pointer,"
+                          " unable to continue.");
+               pvr2_trace(PVR2_TRACE_INIT, "If you have a new device type,"
+                          " please contact Mike Isely <isely@pobox.com>"
+                          " to get it included in the driver\n");
+               goto fail;
+       }
+
+       hdw = kzalloc(sizeof(*hdw),GFP_KERNEL);
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"",
+                  hdw,hdw_desc->description);
+       pvr2_trace(PVR2_TRACE_INFO, "Hardware description: %s",
+               hdw_desc->description);
+       if (hdw_desc->flag_is_experimental) {
+               pvr2_trace(PVR2_TRACE_INFO, "**********");
+               pvr2_trace(PVR2_TRACE_INFO,
+                          "WARNING: Support for this device (%s) is"
+                          " experimental.", hdw_desc->description);
+               pvr2_trace(PVR2_TRACE_INFO,
+                          "Important functionality might not be"
+                          " entirely working.");
+               pvr2_trace(PVR2_TRACE_INFO,
+                          "Please consider contacting the driver author to"
+                          " help with further stabilization of the driver.");
+               pvr2_trace(PVR2_TRACE_INFO, "**********");
+       }
+       if (!hdw) goto fail;
+
+       init_timer(&hdw->quiescent_timer);
+       hdw->quiescent_timer.data = (unsigned long)hdw;
+       hdw->quiescent_timer.function = pvr2_hdw_quiescent_timeout;
+
+       init_timer(&hdw->decoder_stabilization_timer);
+       hdw->decoder_stabilization_timer.data = (unsigned long)hdw;
+       hdw->decoder_stabilization_timer.function =
+               pvr2_hdw_decoder_stabilization_timeout;
+
+       init_timer(&hdw->encoder_wait_timer);
+       hdw->encoder_wait_timer.data = (unsigned long)hdw;
+       hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout;
+
+       init_timer(&hdw->encoder_run_timer);
+       hdw->encoder_run_timer.data = (unsigned long)hdw;
+       hdw->encoder_run_timer.function = pvr2_hdw_encoder_run_timeout;
+
+       hdw->master_state = PVR2_STATE_DEAD;
+
+       init_waitqueue_head(&hdw->state_wait_data);
+
+       hdw->tuner_signal_stale = !0;
+       cx2341x_fill_defaults(&hdw->enc_ctl_state);
+
+       /* Calculate which inputs are OK */
+       m = 0;
+       if (hdw_desc->flag_has_analogtuner) m |= 1 << PVR2_CVAL_INPUT_TV;
+       if (hdw_desc->digital_control_scheme != PVR2_DIGITAL_SCHEME_NONE) {
+               m |= 1 << PVR2_CVAL_INPUT_DTV;
+       }
+       if (hdw_desc->flag_has_svideo) m |= 1 << PVR2_CVAL_INPUT_SVIDEO;
+       if (hdw_desc->flag_has_composite) m |= 1 << PVR2_CVAL_INPUT_COMPOSITE;
+       if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO;
+       hdw->input_avail_mask = m;
+       hdw->input_allowed_mask = hdw->input_avail_mask;
+
+       /* If not a hybrid device, pathway_state never changes.  So
+          initialize it here to what it should forever be. */
+       if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_DTV))) {
+               hdw->pathway_state = PVR2_PATHWAY_ANALOG;
+       } else if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_TV))) {
+               hdw->pathway_state = PVR2_PATHWAY_DIGITAL;
+       }
+
+       hdw->control_cnt = CTRLDEF_COUNT;
+       hdw->control_cnt += MPEGDEF_COUNT;
+       hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
+                               GFP_KERNEL);
+       if (!hdw->controls) goto fail;
+       hdw->hdw_desc = hdw_desc;
+       hdw->ir_scheme_active = hdw->hdw_desc->ir_scheme;
+       for (idx = 0; idx < hdw->control_cnt; idx++) {
+               cptr = hdw->controls + idx;
+               cptr->hdw = hdw;
+       }
+       for (idx = 0; idx < 32; idx++) {
+               hdw->std_mask_ptrs[idx] = hdw->std_mask_names[idx];
+       }
+       for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
+               cptr = hdw->controls + idx;
+               cptr->info = control_defs+idx;
+       }
+
+       /* Ensure that default input choice is a valid one. */
+       m = hdw->input_avail_mask;
+       if (m) for (idx = 0; idx < (sizeof(m) << 3); idx++) {
+               if (!((1 << idx) & m)) continue;
+               hdw->input_val = idx;
+               break;
+       }
+
+       /* Define and configure additional controls from cx2341x module. */
+       hdw->mpeg_ctrl_info = kcalloc(MPEGDEF_COUNT,
+                                     sizeof(*(hdw->mpeg_ctrl_info)),
+                                     GFP_KERNEL);
+       if (!hdw->mpeg_ctrl_info) goto fail;
+       for (idx = 0; idx < MPEGDEF_COUNT; idx++) {
+               cptr = hdw->controls + idx + CTRLDEF_COUNT;
+               ciptr = &(hdw->mpeg_ctrl_info[idx].info);
+               ciptr->desc = hdw->mpeg_ctrl_info[idx].desc;
+               ciptr->name = mpeg_ids[idx].strid;
+               ciptr->v4l_id = mpeg_ids[idx].id;
+               ciptr->skip_init = !0;
+               ciptr->get_value = ctrl_cx2341x_get;
+               ciptr->get_v4lflags = ctrl_cx2341x_getv4lflags;
+               ciptr->is_dirty = ctrl_cx2341x_is_dirty;
+               if (!idx) ciptr->clear_dirty = ctrl_cx2341x_clear_dirty;
+               qctrl.id = ciptr->v4l_id;
+               cx2341x_ctrl_query(&hdw->enc_ctl_state,&qctrl);
+               if (!(qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY)) {
+                       ciptr->set_value = ctrl_cx2341x_set;
+               }
+               strncpy(hdw->mpeg_ctrl_info[idx].desc,qctrl.name,
+                       PVR2_CTLD_INFO_DESC_SIZE);
+               hdw->mpeg_ctrl_info[idx].desc[PVR2_CTLD_INFO_DESC_SIZE-1] = 0;
+               ciptr->default_value = qctrl.default_value;
+               switch (qctrl.type) {
+               default:
+               case V4L2_CTRL_TYPE_INTEGER:
+                       ciptr->type = pvr2_ctl_int;
+                       ciptr->def.type_int.min_value = qctrl.minimum;
+                       ciptr->def.type_int.max_value = qctrl.maximum;
+                       break;
+               case V4L2_CTRL_TYPE_BOOLEAN:
+                       ciptr->type = pvr2_ctl_bool;
+                       break;
+               case V4L2_CTRL_TYPE_MENU:
+                       ciptr->type = pvr2_ctl_enum;
+                       ciptr->def.type_enum.value_names =
+                               cx2341x_ctrl_get_menu(&hdw->enc_ctl_state,
+                                                               ciptr->v4l_id);
+                       for (cnt1 = 0;
+                            ciptr->def.type_enum.value_names[cnt1] != NULL;
+                            cnt1++) { }
+                       ciptr->def.type_enum.count = cnt1;
+                       break;
+               }
+               cptr->info = ciptr;
+       }
+
+       // Initialize control data regarding video standard masks
+       valid_std_mask = pvr2_std_get_usable();
+       for (idx = 0; idx < 32; idx++) {
+               if (!(valid_std_mask & (1 << idx))) continue;
+               cnt1 = pvr2_std_id_to_str(
+                       hdw->std_mask_names[idx],
+                       sizeof(hdw->std_mask_names[idx])-1,
+                       1 << idx);
+               hdw->std_mask_names[idx][cnt1] = 0;
+       }
+       cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDAVAIL);
+       if (cptr) {
+               memcpy(&hdw->std_info_avail,cptr->info,
+                      sizeof(hdw->std_info_avail));
+               cptr->info = &hdw->std_info_avail;
+               hdw->std_info_avail.def.type_bitmask.bit_names =
+                       hdw->std_mask_ptrs;
+               hdw->std_info_avail.def.type_bitmask.valid_bits =
+                       valid_std_mask;
+       }
+       cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR);
+       if (cptr) {
+               memcpy(&hdw->std_info_cur,cptr->info,
+                      sizeof(hdw->std_info_cur));
+               cptr->info = &hdw->std_info_cur;
+               hdw->std_info_cur.def.type_bitmask.bit_names =
+                       hdw->std_mask_ptrs;
+               hdw->std_info_cur.def.type_bitmask.valid_bits =
+                       valid_std_mask;
+       }
+       cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDDETECT);
+       if (cptr) {
+               memcpy(&hdw->std_info_detect,cptr->info,
+                      sizeof(hdw->std_info_detect));
+               cptr->info = &hdw->std_info_detect;
+               hdw->std_info_detect.def.type_bitmask.bit_names =
+                       hdw->std_mask_ptrs;
+               hdw->std_info_detect.def.type_bitmask.valid_bits =
+                       valid_std_mask;
+       }
+
+       hdw->cropcap_stale = !0;
+       hdw->eeprom_addr = -1;
+       hdw->unit_number = -1;
+       hdw->v4l_minor_number_video = -1;
+       hdw->v4l_minor_number_vbi = -1;
+       hdw->v4l_minor_number_radio = -1;
+       hdw->ctl_write_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
+       if (!hdw->ctl_write_buffer) goto fail;
+       hdw->ctl_read_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
+       if (!hdw->ctl_read_buffer) goto fail;
+       hdw->ctl_write_urb = usb_alloc_urb(0,GFP_KERNEL);
+       if (!hdw->ctl_write_urb) goto fail;
+       hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL);
+       if (!hdw->ctl_read_urb) goto fail;
+
+       if (v4l2_device_register(&intf->dev, &hdw->v4l2_dev) != 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Error registering with v4l core, giving up");
+               goto fail;
+       }
+       mutex_lock(&pvr2_unit_mtx); do {
+               for (idx = 0; idx < PVR_NUM; idx++) {
+                       if (unit_pointers[idx]) continue;
+                       hdw->unit_number = idx;
+                       unit_pointers[idx] = hdw;
+                       break;
+               }
+       } while (0); mutex_unlock(&pvr2_unit_mtx);
+
+       cnt1 = 0;
+       cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2");
+       cnt1 += cnt2;
+       if (hdw->unit_number >= 0) {
+               cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"_%c",
+                                ('a' + hdw->unit_number));
+               cnt1 += cnt2;
+       }
+       if (cnt1 >= sizeof(hdw->name)) cnt1 = sizeof(hdw->name)-1;
+       hdw->name[cnt1] = 0;
+
+       hdw->workqueue = create_singlethread_workqueue(hdw->name);
+       INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll);
+
+       pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",
+                  hdw->unit_number,hdw->name);
+
+       hdw->tuner_type = -1;
+       hdw->flag_ok = !0;
+
+       hdw->usb_intf = intf;
+       hdw->usb_dev = usb_dev;
+
+       usb_make_path(hdw->usb_dev, hdw->bus_info, sizeof(hdw->bus_info));
+
+       ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber;
+       usb_set_interface(hdw->usb_dev,ifnum,0);
+
+       mutex_init(&hdw->ctl_lock_mutex);
+       mutex_init(&hdw->big_lock_mutex);
+
+       return hdw;
+ fail:
+       if (hdw) {
+               del_timer_sync(&hdw->quiescent_timer);
+               del_timer_sync(&hdw->decoder_stabilization_timer);
+               del_timer_sync(&hdw->encoder_run_timer);
+               del_timer_sync(&hdw->encoder_wait_timer);
+               if (hdw->workqueue) {
+                       flush_workqueue(hdw->workqueue);
+                       destroy_workqueue(hdw->workqueue);
+                       hdw->workqueue = NULL;
+               }
+               usb_free_urb(hdw->ctl_read_urb);
+               usb_free_urb(hdw->ctl_write_urb);
+               kfree(hdw->ctl_read_buffer);
+               kfree(hdw->ctl_write_buffer);
+               kfree(hdw->controls);
+               kfree(hdw->mpeg_ctrl_info);
+               kfree(hdw);
+       }
+       return NULL;
+}
+
+
+/* Remove _all_ associations between this driver and the underlying USB
+   layer. */
+static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw)
+{
+       if (hdw->flag_disconnected) return;
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_remove_usb_stuff: hdw=%p",hdw);
+       if (hdw->ctl_read_urb) {
+               usb_kill_urb(hdw->ctl_read_urb);
+               usb_free_urb(hdw->ctl_read_urb);
+               hdw->ctl_read_urb = NULL;
+       }
+       if (hdw->ctl_write_urb) {
+               usb_kill_urb(hdw->ctl_write_urb);
+               usb_free_urb(hdw->ctl_write_urb);
+               hdw->ctl_write_urb = NULL;
+       }
+       if (hdw->ctl_read_buffer) {
+               kfree(hdw->ctl_read_buffer);
+               hdw->ctl_read_buffer = NULL;
+       }
+       if (hdw->ctl_write_buffer) {
+               kfree(hdw->ctl_write_buffer);
+               hdw->ctl_write_buffer = NULL;
+       }
+       hdw->flag_disconnected = !0;
+       /* If we don't do this, then there will be a dangling struct device
+          reference to our disappearing device persisting inside the V4L
+          core... */
+       v4l2_device_disconnect(&hdw->v4l2_dev);
+       hdw->usb_dev = NULL;
+       hdw->usb_intf = NULL;
+       pvr2_hdw_render_useless(hdw);
+}
+
+
+/* Destroy hardware interaction structure */
+void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
+{
+       if (!hdw) return;
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw);
+       if (hdw->workqueue) {
+               flush_workqueue(hdw->workqueue);
+               destroy_workqueue(hdw->workqueue);
+               hdw->workqueue = NULL;
+       }
+       del_timer_sync(&hdw->quiescent_timer);
+       del_timer_sync(&hdw->decoder_stabilization_timer);
+       del_timer_sync(&hdw->encoder_run_timer);
+       del_timer_sync(&hdw->encoder_wait_timer);
+       if (hdw->fw_buffer) {
+               kfree(hdw->fw_buffer);
+               hdw->fw_buffer = NULL;
+       }
+       if (hdw->vid_stream) {
+               pvr2_stream_destroy(hdw->vid_stream);
+               hdw->vid_stream = NULL;
+       }
+       pvr2_i2c_core_done(hdw);
+       v4l2_device_unregister(&hdw->v4l2_dev);
+       pvr2_hdw_remove_usb_stuff(hdw);
+       mutex_lock(&pvr2_unit_mtx); do {
+               if ((hdw->unit_number >= 0) &&
+                   (hdw->unit_number < PVR_NUM) &&
+                   (unit_pointers[hdw->unit_number] == hdw)) {
+                       unit_pointers[hdw->unit_number] = NULL;
+               }
+       } while (0); mutex_unlock(&pvr2_unit_mtx);
+       kfree(hdw->controls);
+       kfree(hdw->mpeg_ctrl_info);
+       kfree(hdw);
+}
+
+
+int pvr2_hdw_dev_ok(struct pvr2_hdw *hdw)
+{
+       return (hdw && hdw->flag_ok);
+}
+
+
+/* Called when hardware has been unplugged */
+void pvr2_hdw_disconnect(struct pvr2_hdw *hdw)
+{
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_disconnect(hdw=%p)",hdw);
+       LOCK_TAKE(hdw->big_lock);
+       LOCK_TAKE(hdw->ctl_lock);
+       pvr2_hdw_remove_usb_stuff(hdw);
+       LOCK_GIVE(hdw->ctl_lock);
+       LOCK_GIVE(hdw->big_lock);
+}
+
+
+/* Get the number of defined controls */
+unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw)
+{
+       return hdw->control_cnt;
+}
+
+
+/* Retrieve a control handle given its index (0..count-1) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *hdw,
+                                            unsigned int idx)
+{
+       if (idx >= hdw->control_cnt) return NULL;
+       return hdw->controls + idx;
+}
+
+
+/* Retrieve a control handle given its index (0..count-1) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *hdw,
+                                         unsigned int ctl_id)
+{
+       struct pvr2_ctrl *cptr;
+       unsigned int idx;
+       int i;
+
+       /* This could be made a lot more efficient, but for now... */
+       for (idx = 0; idx < hdw->control_cnt; idx++) {
+               cptr = hdw->controls + idx;
+               i = cptr->info->internal_id;
+               if (i && (i == ctl_id)) return cptr;
+       }
+       return NULL;
+}
+
+
+/* Given a V4L ID, retrieve the control structure associated with it. */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *hdw,unsigned int ctl_id)
+{
+       struct pvr2_ctrl *cptr;
+       unsigned int idx;
+       int i;
+
+       /* This could be made a lot more efficient, but for now... */
+       for (idx = 0; idx < hdw->control_cnt; idx++) {
+               cptr = hdw->controls + idx;
+               i = cptr->info->v4l_id;
+               if (i && (i == ctl_id)) return cptr;
+       }
+       return NULL;
+}
+
+
+/* Given a V4L ID for its immediate predecessor, retrieve the control
+   structure associated with it. */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *hdw,
+                                           unsigned int ctl_id)
+{
+       struct pvr2_ctrl *cptr,*cp2;
+       unsigned int idx;
+       int i;
+
+       /* This could be made a lot more efficient, but for now... */
+       cp2 = NULL;
+       for (idx = 0; idx < hdw->control_cnt; idx++) {
+               cptr = hdw->controls + idx;
+               i = cptr->info->v4l_id;
+               if (!i) continue;
+               if (i <= ctl_id) continue;
+               if (cp2 && (cp2->info->v4l_id < i)) continue;
+               cp2 = cptr;
+       }
+       return cp2;
+       return NULL;
+}
+
+
+static const char *get_ctrl_typename(enum pvr2_ctl_type tp)
+{
+       switch (tp) {
+       case pvr2_ctl_int: return "integer";
+       case pvr2_ctl_enum: return "enum";
+       case pvr2_ctl_bool: return "boolean";
+       case pvr2_ctl_bitmask: return "bitmask";
+       }
+       return "";
+}
+
+
+static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id,
+                                   const char *name, int val)
+{
+       struct v4l2_control ctrl;
+       pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 %s=%d", name, val);
+       memset(&ctrl, 0, sizeof(ctrl));
+       ctrl.id = id;
+       ctrl.value = val;
+       v4l2_device_call_all(&hdw->v4l2_dev, 0, core, s_ctrl, &ctrl);
+}
+
+#define PVR2_SUBDEV_SET_CONTROL(hdw, id, lab) \
+       if ((hdw)->lab##_dirty || (hdw)->force_dirty) {         \
+               pvr2_subdev_set_control(hdw, id, #lab, (hdw)->lab##_val); \
+       }
+
+v4l2_std_id pvr2_hdw_get_detected_std(struct pvr2_hdw *hdw)
+{
+       v4l2_std_id std;
+       std = (v4l2_std_id)hdw->std_mask_avail;
+       v4l2_device_call_all(&hdw->v4l2_dev, 0,
+                            video, querystd, &std);
+       return std;
+}
+
+/* Execute whatever commands are required to update the state of all the
+   sub-devices so that they match our current control values. */
+static void pvr2_subdev_update(struct pvr2_hdw *hdw)
+{
+       struct v4l2_subdev *sd;
+       unsigned int id;
+       pvr2_subdev_update_func fp;
+
+       pvr2_trace(PVR2_TRACE_CHIPS, "subdev update...");
+
+       if (hdw->tuner_updated || hdw->force_dirty) {
+               struct tuner_setup setup;
+               pvr2_trace(PVR2_TRACE_CHIPS, "subdev tuner set_type(%d)",
+                          hdw->tuner_type);
+               if (((int)(hdw->tuner_type)) >= 0) {
+                       memset(&setup, 0, sizeof(setup));
+                       setup.addr = ADDR_UNSET;
+                       setup.type = hdw->tuner_type;
+                       setup.mode_mask = T_RADIO | T_ANALOG_TV;
+                       v4l2_device_call_all(&hdw->v4l2_dev, 0,
+                                            tuner, s_type_addr, &setup);
+               }
+       }
+
+       if (hdw->input_dirty || hdw->std_dirty || hdw->force_dirty) {
+               pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_standard");
+               if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+                       v4l2_device_call_all(&hdw->v4l2_dev, 0,
+                                            tuner, s_radio);
+               } else {
+                       v4l2_std_id vs;
+                       vs = hdw->std_mask_cur;
+                       v4l2_device_call_all(&hdw->v4l2_dev, 0,
+                                            core, s_std, vs);
+                       pvr2_hdw_cx25840_vbi_hack(hdw);
+               }
+               hdw->tuner_signal_stale = !0;
+               hdw->cropcap_stale = !0;
+       }
+
+       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_BRIGHTNESS, brightness);
+       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_CONTRAST, contrast);
+       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_SATURATION, saturation);
+       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_HUE, hue);
+       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_MUTE, mute);
+       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_VOLUME, volume);
+       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BALANCE, balance);
+       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BASS, bass);
+       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_TREBLE, treble);
+
+       if (hdw->input_dirty || hdw->audiomode_dirty || hdw->force_dirty) {
+               struct v4l2_tuner vt;
+               memset(&vt, 0, sizeof(vt));
+               vt.type = (hdw->input_val == PVR2_CVAL_INPUT_RADIO) ?
+                       V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+               vt.audmode = hdw->audiomode_val;
+               v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_tuner, &vt);
+       }
+
+       if (hdw->freqDirty || hdw->force_dirty) {
+               unsigned long fv;
+               struct v4l2_frequency freq;
+               fv = pvr2_hdw_get_cur_freq(hdw);
+               pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_freq(%lu)", fv);
+               if (hdw->tuner_signal_stale) pvr2_hdw_status_poll(hdw);
+               memset(&freq, 0, sizeof(freq));
+               if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
+                       /* ((fv * 1000) / 62500) */
+                       freq.frequency = (fv * 2) / 125;
+               } else {
+                       freq.frequency = fv / 62500;
+               }
+               /* tuner-core currently doesn't seem to care about this, but
+                  let's set it anyway for completeness. */
+               if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+                       freq.type = V4L2_TUNER_RADIO;
+               } else {
+                       freq.type = V4L2_TUNER_ANALOG_TV;
+               }
+               freq.tuner = 0;
+               v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner,
+                                    s_frequency, &freq);
+       }
+
+       if (hdw->res_hor_dirty || hdw->res_ver_dirty || hdw->force_dirty) {
+               struct v4l2_mbus_framefmt fmt;
+               memset(&fmt, 0, sizeof(fmt));
+               fmt.width = hdw->res_hor_val;
+               fmt.height = hdw->res_ver_val;
+               fmt.code = V4L2_MBUS_FMT_FIXED;
+               pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)",
+                          fmt.width, fmt.height);
+               v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_mbus_fmt, &fmt);
+       }
+
+       if (hdw->srate_dirty || hdw->force_dirty) {
+               u32 val;
+               pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d",
+                          hdw->srate_val);
+               switch (hdw->srate_val) {
+               default:
+               case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
+                       val = 48000;
+                       break;
+               case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
+                       val = 44100;
+                       break;
+               case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
+                       val = 32000;
+                       break;
+               }
+               v4l2_device_call_all(&hdw->v4l2_dev, 0,
+                                    audio, s_clock_freq, val);
+       }
+
+       /* Unable to set crop parameters; there is apparently no equivalent
+          for VIDIOC_S_CROP */
+
+       v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
+               id = sd->grp_id;
+               if (id >= ARRAY_SIZE(pvr2_module_update_functions)) continue;
+               fp = pvr2_module_update_functions[id];
+               if (!fp) continue;
+               (*fp)(hdw, sd);
+       }
+
+       if (hdw->tuner_signal_stale || hdw->cropcap_stale) {
+               pvr2_hdw_status_poll(hdw);
+       }
+}
+
+
+/* Figure out if we need to commit control changes.  If so, mark internal
+   state flags to indicate this fact and return true.  Otherwise do nothing
+   else and return false. */
+static int pvr2_hdw_commit_setup(struct pvr2_hdw *hdw)
+{
+       unsigned int idx;
+       struct pvr2_ctrl *cptr;
+       int value;
+       int commit_flag = hdw->force_dirty;
+       char buf[100];
+       unsigned int bcnt,ccnt;
+
+       for (idx = 0; idx < hdw->control_cnt; idx++) {
+               cptr = hdw->controls + idx;
+               if (!cptr->info->is_dirty) continue;
+               if (!cptr->info->is_dirty(cptr)) continue;
+               commit_flag = !0;
+
+               if (!(pvrusb2_debug & PVR2_TRACE_CTL)) continue;
+               bcnt = scnprintf(buf,sizeof(buf),"\"%s\" <-- ",
+                                cptr->info->name);
+               value = 0;
+               cptr->info->get_value(cptr,&value);
+               pvr2_ctrl_value_to_sym_internal(cptr,~0,value,
+                                               buf+bcnt,
+                                               sizeof(buf)-bcnt,&ccnt);
+               bcnt += ccnt;
+               bcnt += scnprintf(buf+bcnt,sizeof(buf)-bcnt," <%s>",
+                                 get_ctrl_typename(cptr->info->type));
+               pvr2_trace(PVR2_TRACE_CTL,
+                          "/*--TRACE_COMMIT--*/ %.*s",
+                          bcnt,buf);
+       }
+
+       if (!commit_flag) {
+               /* Nothing has changed */
+               return 0;
+       }
+
+       hdw->state_pipeline_config = 0;
+       trace_stbit("state_pipeline_config",hdw->state_pipeline_config);
+       pvr2_hdw_state_sched(hdw);
+
+       return !0;
+}
+
+
+/* Perform all operations needed to commit all control changes.  This must
+   be performed in synchronization with the pipeline state and is thus
+   expected to be called as part of the driver's worker thread.  Return
+   true if commit successful, otherwise return false to indicate that
+   commit isn't possible at this time. */
+static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
+{
+       unsigned int idx;
+       struct pvr2_ctrl *cptr;
+       int disruptive_change;
+
+       if (hdw->input_dirty && hdw->state_pathway_ok &&
+           (((hdw->input_val == PVR2_CVAL_INPUT_DTV) ?
+             PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG) !=
+            hdw->pathway_state)) {
+               /* Change of mode being asked for... */
+               hdw->state_pathway_ok = 0;
+               trace_stbit("state_pathway_ok", hdw->state_pathway_ok);
+       }
+       if (!hdw->state_pathway_ok) {
+               /* Can't commit anything until pathway is ok. */
+               return 0;
+       }
+
+       /* Handle some required side effects when the video standard is
+          changed.... */
+       if (hdw->std_dirty) {
+               int nvres;
+               int gop_size;
+               if (hdw->std_mask_cur & V4L2_STD_525_60) {
+                       nvres = 480;
+                       gop_size = 15;
+               } else {
+                       nvres = 576;
+                       gop_size = 12;
+               }
+               /* Rewrite the vertical resolution to be appropriate to the
+                  video standard that has been selected. */
+               if (nvres != hdw->res_ver_val) {
+                       hdw->res_ver_val = nvres;
+                       hdw->res_ver_dirty = !0;
+               }
+               /* Rewrite the GOP size to be appropriate to the video
+                  standard that has been selected. */
+               if (gop_size != hdw->enc_ctl_state.video_gop_size) {
+                       struct v4l2_ext_controls cs;
+                       struct v4l2_ext_control c1;
+                       memset(&cs, 0, sizeof(cs));
+                       memset(&c1, 0, sizeof(c1));
+                       cs.controls = &c1;
+                       cs.count = 1;
+                       c1.id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
+                       c1.value = gop_size;
+                       cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,
+                                         VIDIOC_S_EXT_CTRLS);
+               }
+       }
+
+       /* The broadcast decoder can only scale down, so if
+        * res_*_dirty && crop window < output format ==> enlarge crop.
+        *
+        * The mpeg encoder receives fields of res_hor_val dots and
+        * res_ver_val halflines.  Limits: hor<=720, ver<=576.
+        */
+       if (hdw->res_hor_dirty && hdw->cropw_val < hdw->res_hor_val) {
+               hdw->cropw_val = hdw->res_hor_val;
+               hdw->cropw_dirty = !0;
+       } else if (hdw->cropw_dirty) {
+               hdw->res_hor_dirty = !0;           /* must rescale */
+               hdw->res_hor_val = min(720, hdw->cropw_val);
+       }
+       if (hdw->res_ver_dirty && hdw->croph_val < hdw->res_ver_val) {
+               hdw->croph_val = hdw->res_ver_val;
+               hdw->croph_dirty = !0;
+       } else if (hdw->croph_dirty) {
+               int nvres = hdw->std_mask_cur & V4L2_STD_525_60 ? 480 : 576;
+               hdw->res_ver_dirty = !0;
+               hdw->res_ver_val = min(nvres, hdw->croph_val);
+       }
+
+       /* If any of the below has changed, then we can't do the update
+          while the pipeline is running.  Pipeline must be paused first
+          and decoder -> encoder connection be made quiescent before we
+          can proceed. */
+       disruptive_change =
+               (hdw->std_dirty ||
+                hdw->enc_unsafe_stale ||
+                hdw->srate_dirty ||
+                hdw->res_ver_dirty ||
+                hdw->res_hor_dirty ||
+                hdw->cropw_dirty ||
+                hdw->croph_dirty ||
+                hdw->input_dirty ||
+                (hdw->active_stream_type != hdw->desired_stream_type));
+       if (disruptive_change && !hdw->state_pipeline_idle) {
+               /* Pipeline is not idle; we can't proceed.  Arrange to
+                  cause pipeline to stop so that we can try this again
+                  later.... */
+               hdw->state_pipeline_pause = !0;
+               return 0;
+       }
+
+       if (hdw->srate_dirty) {
+               /* Write new sample rate into control structure since
+                * the master copy is stale.  We must track srate
+                * separate from the mpeg control structure because
+                * other logic also uses this value. */
+               struct v4l2_ext_controls cs;
+               struct v4l2_ext_control c1;
+               memset(&cs,0,sizeof(cs));
+               memset(&c1,0,sizeof(c1));
+               cs.controls = &c1;
+               cs.count = 1;
+               c1.id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ;
+               c1.value = hdw->srate_val;
+               cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,VIDIOC_S_EXT_CTRLS);
+       }
+
+       if (hdw->active_stream_type != hdw->desired_stream_type) {
+               /* Handle any side effects of stream config here */
+               hdw->active_stream_type = hdw->desired_stream_type;
+       }
+
+       if (hdw->hdw_desc->signal_routing_scheme ==
+           PVR2_ROUTING_SCHEME_GOTVIEW) {
+               u32 b;
+               /* Handle GOTVIEW audio switching */
+               pvr2_hdw_gpio_get_out(hdw,&b);
+               if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+                       /* Set GPIO 11 */
+                       pvr2_hdw_gpio_chg_out(hdw,(1 << 11),~0);
+               } else {
+                       /* Clear GPIO 11 */
+                       pvr2_hdw_gpio_chg_out(hdw,(1 << 11),0);
+               }
+       }
+
+       /* Check and update state for all sub-devices. */
+       pvr2_subdev_update(hdw);
+
+       hdw->tuner_updated = 0;
+       hdw->force_dirty = 0;
+       for (idx = 0; idx < hdw->control_cnt; idx++) {
+               cptr = hdw->controls + idx;
+               if (!cptr->info->clear_dirty) continue;
+               cptr->info->clear_dirty(cptr);
+       }
+
+       if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) &&
+           hdw->state_encoder_run) {
+               /* If encoder isn't running or it can't be touched, then
+                  this will get worked out later when we start the
+                  encoder. */
+               if (pvr2_encoder_adjust(hdw) < 0) return !0;
+       }
+
+       hdw->state_pipeline_config = !0;
+       /* Hardware state may have changed in a way to cause the cropping
+          capabilities to have changed.  So mark it stale, which will
+          cause a later re-fetch. */
+       trace_stbit("state_pipeline_config",hdw->state_pipeline_config);
+       return !0;
+}
+
+
+int pvr2_hdw_commit_ctl(struct pvr2_hdw *hdw)
+{
+       int fl;
+       LOCK_TAKE(hdw->big_lock);
+       fl = pvr2_hdw_commit_setup(hdw);
+       LOCK_GIVE(hdw->big_lock);
+       if (!fl) return 0;
+       return pvr2_hdw_wait(hdw,0);
+}
+
+
+static void pvr2_hdw_worker_poll(struct work_struct *work)
+{
+       int fl = 0;
+       struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,workpoll);
+       LOCK_TAKE(hdw->big_lock); do {
+               fl = pvr2_hdw_state_eval(hdw);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+       if (fl && hdw->state_func) {
+               hdw->state_func(hdw->state_data);
+       }
+}
+
+
+static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state)
+{
+       return wait_event_interruptible(
+               hdw->state_wait_data,
+               (hdw->state_stale == 0) &&
+               (!state || (hdw->master_state != state)));
+}
+
+
+/* Return name for this driver instance */
+const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
+{
+       return hdw->name;
+}
+
+
+const char *pvr2_hdw_get_desc(struct pvr2_hdw *hdw)
+{
+       return hdw->hdw_desc->description;
+}
+
+
+const char *pvr2_hdw_get_type(struct pvr2_hdw *hdw)
+{
+       return hdw->hdw_desc->shortname;
+}
+
+
+int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
+{
+       int result;
+       LOCK_TAKE(hdw->ctl_lock); do {
+               hdw->cmd_buffer[0] = FX2CMD_GET_USB_SPEED;
+               result = pvr2_send_request(hdw,
+                                          hdw->cmd_buffer,1,
+                                          hdw->cmd_buffer,1);
+               if (result < 0) break;
+               result = (hdw->cmd_buffer[0] != 0);
+       } while(0); LOCK_GIVE(hdw->ctl_lock);
+       return result;
+}
+
+
+/* Execute poll of tuner status */
+void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw)
+{
+       LOCK_TAKE(hdw->big_lock); do {
+               pvr2_hdw_status_poll(hdw);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+
+static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw)
+{
+       if (!hdw->cropcap_stale) {
+               return 0;
+       }
+       pvr2_hdw_status_poll(hdw);
+       if (hdw->cropcap_stale) {
+               return -EIO;
+       }
+       return 0;
+}
+
+
+/* Return information about cropping capabilities */
+int pvr2_hdw_get_cropcap(struct pvr2_hdw *hdw, struct v4l2_cropcap *pp)
+{
+       int stat = 0;
+       LOCK_TAKE(hdw->big_lock);
+       stat = pvr2_hdw_check_cropcap(hdw);
+       if (!stat) {
+               memcpy(pp, &hdw->cropcap_info, sizeof(hdw->cropcap_info));
+       }
+       LOCK_GIVE(hdw->big_lock);
+       return stat;
+}
+
+
+/* Return information about the tuner */
+int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp)
+{
+       LOCK_TAKE(hdw->big_lock); do {
+               if (hdw->tuner_signal_stale) {
+                       pvr2_hdw_status_poll(hdw);
+               }
+               memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner));
+       } while (0); LOCK_GIVE(hdw->big_lock);
+       return 0;
+}
+
+
+/* Get handle to video output stream */
+struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *hp)
+{
+       return hp->vid_stream;
+}
+
+
+void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw)
+{
+       int nr = pvr2_hdw_get_unit_number(hdw);
+       LOCK_TAKE(hdw->big_lock); do {
+               printk(KERN_INFO "pvrusb2: =================  START STATUS CARD #%d  =================\n", nr);
+               v4l2_device_call_all(&hdw->v4l2_dev, 0, core, log_status);
+               pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:");
+               cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2");
+               pvr2_hdw_state_log_state(hdw);
+               printk(KERN_INFO "pvrusb2: ==================  END STATUS CARD #%d  ==================\n", nr);
+       } while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+
+/* Grab EEPROM contents, needed for direct method. */
+#define EEPROM_SIZE 8192
+#define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__)
+static u8 *pvr2_full_eeprom_fetch(struct pvr2_hdw *hdw)
+{
+       struct i2c_msg msg[2];
+       u8 *eeprom;
+       u8 iadd[2];
+       u8 addr;
+       u16 eepromSize;
+       unsigned int offs;
+       int ret;
+       int mode16 = 0;
+       unsigned pcnt,tcnt;
+       eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL);
+       if (!eeprom) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Failed to allocate memory"
+                          " required to read eeprom");
+               return NULL;
+       }
+
+       trace_eeprom("Value for eeprom addr from controller was 0x%x",
+                    hdw->eeprom_addr);
+       addr = hdw->eeprom_addr;
+       /* Seems that if the high bit is set, then the *real* eeprom
+          address is shifted right now bit position (noticed this in
+          newer PVR USB2 hardware) */
+       if (addr & 0x80) addr >>= 1;
+
+       /* FX2 documentation states that a 16bit-addressed eeprom is
+          expected if the I2C address is an odd number (yeah, this is
+          strange but it's what they do) */
+       mode16 = (addr & 1);
+       eepromSize = (mode16 ? EEPROM_SIZE : 256);
+       trace_eeprom("Examining %d byte eeprom at location 0x%x"
+                    " using %d bit addressing",eepromSize,addr,
+                    mode16 ? 16 : 8);
+
+       msg[0].addr = addr;
+       msg[0].flags = 0;
+       msg[0].len = mode16 ? 2 : 1;
+       msg[0].buf = iadd;
+       msg[1].addr = addr;
+       msg[1].flags = I2C_M_RD;
+
+       /* We have to do the actual eeprom data fetch ourselves, because
+          (1) we're only fetching part of the eeprom, and (2) if we were
+          getting the whole thing our I2C driver can't grab it in one
+          pass - which is what tveeprom is otherwise going to attempt */
+       memset(eeprom,0,EEPROM_SIZE);
+       for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) {
+               pcnt = 16;
+               if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt;
+               offs = tcnt + (eepromSize - EEPROM_SIZE);
+               if (mode16) {
+                       iadd[0] = offs >> 8;
+                       iadd[1] = offs;
+               } else {
+                       iadd[0] = offs;
+               }
+               msg[1].len = pcnt;
+               msg[1].buf = eeprom+tcnt;
+               if ((ret = i2c_transfer(&hdw->i2c_adap,
+                                       msg,ARRAY_SIZE(msg))) != 2) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "eeprom fetch set offs err=%d",ret);
+                       kfree(eeprom);
+                       return NULL;
+               }
+       }
+       return eeprom;
+}
+
+
+void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw,
+                               int mode,
+                               int enable_flag)
+{
+       int ret;
+       u16 address;
+       unsigned int pipe;
+       LOCK_TAKE(hdw->big_lock); do {
+               if ((hdw->fw_buffer == NULL) == !enable_flag) break;
+
+               if (!enable_flag) {
+                       pvr2_trace(PVR2_TRACE_FIRMWARE,
+                                  "Cleaning up after CPU firmware fetch");
+                       kfree(hdw->fw_buffer);
+                       hdw->fw_buffer = NULL;
+                       hdw->fw_size = 0;
+                       if (hdw->fw_cpu_flag) {
+                               /* Now release the CPU.  It will disconnect
+                                  and reconnect later. */
+                               pvr2_hdw_cpureset_assert(hdw,0);
+                       }
+                       break;
+               }
+
+               hdw->fw_cpu_flag = (mode != 2);
+               if (hdw->fw_cpu_flag) {
+                       hdw->fw_size = (mode == 1) ? 0x4000 : 0x2000;
+                       pvr2_trace(PVR2_TRACE_FIRMWARE,
+                                  "Preparing to suck out CPU firmware"
+                                  " (size=%u)", hdw->fw_size);
+                       hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL);
+                       if (!hdw->fw_buffer) {
+                               hdw->fw_size = 0;
+                               break;
+                       }
+
+                       /* We have to hold the CPU during firmware upload. */
+                       pvr2_hdw_cpureset_assert(hdw,1);
+
+                       /* download the firmware from address 0000-1fff in 2048
+                          (=0x800) bytes chunk. */
+
+                       pvr2_trace(PVR2_TRACE_FIRMWARE,
+                                  "Grabbing CPU firmware");
+                       pipe = usb_rcvctrlpipe(hdw->usb_dev, 0);
+                       for(address = 0; address < hdw->fw_size;
+                           address += 0x800) {
+                               ret = usb_control_msg(hdw->usb_dev,pipe,
+                                                     0xa0,0xc0,
+                                                     address,0,
+                                                     hdw->fw_buffer+address,
+                                                     0x800,HZ);
+                               if (ret < 0) break;
+                       }
+
+                       pvr2_trace(PVR2_TRACE_FIRMWARE,
+                                  "Done grabbing CPU firmware");
+               } else {
+                       pvr2_trace(PVR2_TRACE_FIRMWARE,
+                                  "Sucking down EEPROM contents");
+                       hdw->fw_buffer = pvr2_full_eeprom_fetch(hdw);
+                       if (!hdw->fw_buffer) {
+                               pvr2_trace(PVR2_TRACE_FIRMWARE,
+                                          "EEPROM content suck failed.");
+                               break;
+                       }
+                       hdw->fw_size = EEPROM_SIZE;
+                       pvr2_trace(PVR2_TRACE_FIRMWARE,
+                                  "Done sucking down EEPROM contents");
+               }
+
+       } while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+
+/* Return true if we're in a mode for retrieval CPU firmware */
+int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *hdw)
+{
+       return hdw->fw_buffer != NULL;
+}
+
+
+int pvr2_hdw_cpufw_get(struct pvr2_hdw *hdw,unsigned int offs,
+                      char *buf,unsigned int cnt)
+{
+       int ret = -EINVAL;
+       LOCK_TAKE(hdw->big_lock); do {
+               if (!buf) break;
+               if (!cnt) break;
+
+               if (!hdw->fw_buffer) {
+                       ret = -EIO;
+                       break;
+               }
+
+               if (offs >= hdw->fw_size) {
+                       pvr2_trace(PVR2_TRACE_FIRMWARE,
+                                  "Read firmware data offs=%d EOF",
+                                  offs);
+                       ret = 0;
+                       break;
+               }
+
+               if (offs + cnt > hdw->fw_size) cnt = hdw->fw_size - offs;
+
+               memcpy(buf,hdw->fw_buffer+offs,cnt);
+
+               pvr2_trace(PVR2_TRACE_FIRMWARE,
+                          "Read firmware data offs=%d cnt=%d",
+                          offs,cnt);
+               ret = cnt;
+       } while (0); LOCK_GIVE(hdw->big_lock);
+
+       return ret;
+}
+
+
+int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *hdw,
+                                 enum pvr2_v4l_type index)
+{
+       switch (index) {
+       case pvr2_v4l_type_video: return hdw->v4l_minor_number_video;
+       case pvr2_v4l_type_vbi: return hdw->v4l_minor_number_vbi;
+       case pvr2_v4l_type_radio: return hdw->v4l_minor_number_radio;
+       default: return -1;
+       }
+}
+
+
+/* Store a v4l minor device number */
+void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,
+                                    enum pvr2_v4l_type index,int v)
+{
+       switch (index) {
+       case pvr2_v4l_type_video: hdw->v4l_minor_number_video = v;
+       case pvr2_v4l_type_vbi: hdw->v4l_minor_number_vbi = v;
+       case pvr2_v4l_type_radio: hdw->v4l_minor_number_radio = v;
+       default: break;
+       }
+}
+
+
+static void pvr2_ctl_write_complete(struct urb *urb)
+{
+       struct pvr2_hdw *hdw = urb->context;
+       hdw->ctl_write_pend_flag = 0;
+       if (hdw->ctl_read_pend_flag) return;
+       complete(&hdw->ctl_done);
+}
+
+
+static void pvr2_ctl_read_complete(struct urb *urb)
+{
+       struct pvr2_hdw *hdw = urb->context;
+       hdw->ctl_read_pend_flag = 0;
+       if (hdw->ctl_write_pend_flag) return;
+       complete(&hdw->ctl_done);
+}
+
+
+static void pvr2_ctl_timeout(unsigned long data)
+{
+       struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
+       if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
+               hdw->ctl_timeout_flag = !0;
+               if (hdw->ctl_write_pend_flag)
+                       usb_unlink_urb(hdw->ctl_write_urb);
+               if (hdw->ctl_read_pend_flag)
+                       usb_unlink_urb(hdw->ctl_read_urb);
+       }
+}
+
+
+/* Issue a command and get a response from the device.  This extended
+   version includes a probe flag (which if set means that device errors
+   should not be logged or treated as fatal) and a timeout in jiffies.
+   This can be used to non-lethally probe the health of endpoint 1. */
+static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
+                               unsigned int timeout,int probe_fl,
+                               void *write_data,unsigned int write_len,
+                               void *read_data,unsigned int read_len)
+{
+       unsigned int idx;
+       int status = 0;
+       struct timer_list timer;
+       if (!hdw->ctl_lock_held) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Attempted to execute control transfer"
+                          " without lock!!");
+               return -EDEADLK;
+       }
+       if (!hdw->flag_ok && !probe_fl) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Attempted to execute control transfer"
+                          " when device not ok");
+               return -EIO;
+       }
+       if (!(hdw->ctl_read_urb && hdw->ctl_write_urb)) {
+               if (!probe_fl) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "Attempted to execute control transfer"
+                                  " when USB is disconnected");
+               }
+               return -ENOTTY;
+       }
+
+       /* Ensure that we have sane parameters */
+       if (!write_data) write_len = 0;
+       if (!read_data) read_len = 0;
+       if (write_len > PVR2_CTL_BUFFSIZE) {
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "Attempted to execute %d byte"
+                       " control-write transfer (limit=%d)",
+                       write_len,PVR2_CTL_BUFFSIZE);
+               return -EINVAL;
+       }
+       if (read_len > PVR2_CTL_BUFFSIZE) {
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "Attempted to execute %d byte"
+                       " control-read transfer (limit=%d)",
+                       write_len,PVR2_CTL_BUFFSIZE);
+               return -EINVAL;
+       }
+       if ((!write_len) && (!read_len)) {
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "Attempted to execute null control transfer?");
+               return -EINVAL;
+       }
+
+
+       hdw->cmd_debug_state = 1;
+       if (write_len) {
+               hdw->cmd_debug_code = ((unsigned char *)write_data)[0];
+       } else {
+               hdw->cmd_debug_code = 0;
+       }
+       hdw->cmd_debug_write_len = write_len;
+       hdw->cmd_debug_read_len = read_len;
+
+       /* Initialize common stuff */
+       init_completion(&hdw->ctl_done);
+       hdw->ctl_timeout_flag = 0;
+       hdw->ctl_write_pend_flag = 0;
+       hdw->ctl_read_pend_flag = 0;
+       init_timer(&timer);
+       timer.expires = jiffies + timeout;
+       timer.data = (unsigned long)hdw;
+       timer.function = pvr2_ctl_timeout;
+
+       if (write_len) {
+               hdw->cmd_debug_state = 2;
+               /* Transfer write data to internal buffer */
+               for (idx = 0; idx < write_len; idx++) {
+                       hdw->ctl_write_buffer[idx] =
+                               ((unsigned char *)write_data)[idx];
+               }
+               /* Initiate a write request */
+               usb_fill_bulk_urb(hdw->ctl_write_urb,
+                                 hdw->usb_dev,
+                                 usb_sndbulkpipe(hdw->usb_dev,
+                                                 PVR2_CTL_WRITE_ENDPOINT),
+                                 hdw->ctl_write_buffer,
+                                 write_len,
+                                 pvr2_ctl_write_complete,
+                                 hdw);
+               hdw->ctl_write_urb->actual_length = 0;
+               hdw->ctl_write_pend_flag = !0;
+               status = usb_submit_urb(hdw->ctl_write_urb,GFP_KERNEL);
+               if (status < 0) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "Failed to submit write-control"
+                                  " URB status=%d",status);
+                       hdw->ctl_write_pend_flag = 0;
+                       goto done;
+               }
+       }
+
+       if (read_len) {
+               hdw->cmd_debug_state = 3;
+               memset(hdw->ctl_read_buffer,0x43,read_len);
+               /* Initiate a read request */
+               usb_fill_bulk_urb(hdw->ctl_read_urb,
+                                 hdw->usb_dev,
+                                 usb_rcvbulkpipe(hdw->usb_dev,
+                                                 PVR2_CTL_READ_ENDPOINT),
+                                 hdw->ctl_read_buffer,
+                                 read_len,
+                                 pvr2_ctl_read_complete,
+                                 hdw);
+               hdw->ctl_read_urb->actual_length = 0;
+               hdw->ctl_read_pend_flag = !0;
+               status = usb_submit_urb(hdw->ctl_read_urb,GFP_KERNEL);
+               if (status < 0) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "Failed to submit read-control"
+                                  " URB status=%d",status);
+                       hdw->ctl_read_pend_flag = 0;
+                       goto done;
+               }
+       }
+
+       /* Start timer */
+       add_timer(&timer);
+
+       /* Now wait for all I/O to complete */
+       hdw->cmd_debug_state = 4;
+       while (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
+               wait_for_completion(&hdw->ctl_done);
+       }
+       hdw->cmd_debug_state = 5;
+
+       /* Stop timer */
+       del_timer_sync(&timer);
+
+       hdw->cmd_debug_state = 6;
+       status = 0;
+
+       if (hdw->ctl_timeout_flag) {
+               status = -ETIMEDOUT;
+               if (!probe_fl) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "Timed out control-write");
+               }
+               goto done;
+       }
+
+       if (write_len) {
+               /* Validate results of write request */
+               if ((hdw->ctl_write_urb->status != 0) &&
+                   (hdw->ctl_write_urb->status != -ENOENT) &&
+                   (hdw->ctl_write_urb->status != -ESHUTDOWN) &&
+                   (hdw->ctl_write_urb->status != -ECONNRESET)) {
+                       /* USB subsystem is reporting some kind of failure
+                          on the write */
+                       status = hdw->ctl_write_urb->status;
+                       if (!probe_fl) {
+                               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                          "control-write URB failure,"
+                                          " status=%d",
+                                          status);
+                       }
+                       goto done;
+               }
+               if (hdw->ctl_write_urb->actual_length < write_len) {
+                       /* Failed to write enough data */
+                       status = -EIO;
+                       if (!probe_fl) {
+                               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                          "control-write URB short,"
+                                          " expected=%d got=%d",
+                                          write_len,
+                                          hdw->ctl_write_urb->actual_length);
+                       }
+                       goto done;
+               }
+       }
+       if (read_len) {
+               /* Validate results of read request */
+               if ((hdw->ctl_read_urb->status != 0) &&
+                   (hdw->ctl_read_urb->status != -ENOENT) &&
+                   (hdw->ctl_read_urb->status != -ESHUTDOWN) &&
+                   (hdw->ctl_read_urb->status != -ECONNRESET)) {
+                       /* USB subsystem is reporting some kind of failure
+                          on the read */
+                       status = hdw->ctl_read_urb->status;
+                       if (!probe_fl) {
+                               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                          "control-read URB failure,"
+                                          " status=%d",
+                                          status);
+                       }
+                       goto done;
+               }
+               if (hdw->ctl_read_urb->actual_length < read_len) {
+                       /* Failed to read enough data */
+                       status = -EIO;
+                       if (!probe_fl) {
+                               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                          "control-read URB short,"
+                                          " expected=%d got=%d",
+                                          read_len,
+                                          hdw->ctl_read_urb->actual_length);
+                       }
+                       goto done;
+               }
+               /* Transfer retrieved data out from internal buffer */
+               for (idx = 0; idx < read_len; idx++) {
+                       ((unsigned char *)read_data)[idx] =
+                               hdw->ctl_read_buffer[idx];
+               }
+       }
+
+ done:
+
+       hdw->cmd_debug_state = 0;
+       if ((status < 0) && (!probe_fl)) {
+               pvr2_hdw_render_useless(hdw);
+       }
+       return status;
+}
+
+
+int pvr2_send_request(struct pvr2_hdw *hdw,
+                     void *write_data,unsigned int write_len,
+                     void *read_data,unsigned int read_len)
+{
+       return pvr2_send_request_ex(hdw,HZ*4,0,
+                                   write_data,write_len,
+                                   read_data,read_len);
+}
+
+
+static int pvr2_issue_simple_cmd(struct pvr2_hdw *hdw,u32 cmdcode)
+{
+       int ret;
+       unsigned int cnt = 1;
+       unsigned int args = 0;
+       LOCK_TAKE(hdw->ctl_lock);
+       hdw->cmd_buffer[0] = cmdcode & 0xffu;
+       args = (cmdcode >> 8) & 0xffu;
+       args = (args > 2) ? 2 : args;
+       if (args) {
+               cnt += args;
+               hdw->cmd_buffer[1] = (cmdcode >> 16) & 0xffu;
+               if (args > 1) {
+                       hdw->cmd_buffer[2] = (cmdcode >> 24) & 0xffu;
+               }
+       }
+       if (pvrusb2_debug & PVR2_TRACE_INIT) {
+               unsigned int idx;
+               unsigned int ccnt,bcnt;
+               char tbuf[50];
+               cmdcode &= 0xffu;
+               bcnt = 0;
+               ccnt = scnprintf(tbuf+bcnt,
+                                sizeof(tbuf)-bcnt,
+                                "Sending FX2 command 0x%x",cmdcode);
+               bcnt += ccnt;
+               for (idx = 0; idx < ARRAY_SIZE(pvr2_fx2cmd_desc); idx++) {
+                       if (pvr2_fx2cmd_desc[idx].id == cmdcode) {
+                               ccnt = scnprintf(tbuf+bcnt,
+                                                sizeof(tbuf)-bcnt,
+                                                " \"%s\"",
+                                                pvr2_fx2cmd_desc[idx].desc);
+                               bcnt += ccnt;
+                               break;
+                       }
+               }
+               if (args) {
+                       ccnt = scnprintf(tbuf+bcnt,
+                                        sizeof(tbuf)-bcnt,
+                                        " (%u",hdw->cmd_buffer[1]);
+                       bcnt += ccnt;
+                       if (args > 1) {
+                               ccnt = scnprintf(tbuf+bcnt,
+                                                sizeof(tbuf)-bcnt,
+                                                ",%u",hdw->cmd_buffer[2]);
+                               bcnt += ccnt;
+                       }
+                       ccnt = scnprintf(tbuf+bcnt,
+                                        sizeof(tbuf)-bcnt,
+                                        ")");
+                       bcnt += ccnt;
+               }
+               pvr2_trace(PVR2_TRACE_INIT,"%.*s",bcnt,tbuf);
+       }
+       ret = pvr2_send_request(hdw,hdw->cmd_buffer,cnt,NULL,0);
+       LOCK_GIVE(hdw->ctl_lock);
+       return ret;
+}
+
+
+int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data)
+{
+       int ret;
+
+       LOCK_TAKE(hdw->ctl_lock);
+
+       hdw->cmd_buffer[0] = FX2CMD_REG_WRITE;  /* write register prefix */
+       PVR2_DECOMPOSE_LE(hdw->cmd_buffer,1,data);
+       hdw->cmd_buffer[5] = 0;
+       hdw->cmd_buffer[6] = (reg >> 8) & 0xff;
+       hdw->cmd_buffer[7] = reg & 0xff;
+
+
+       ret = pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 0);
+
+       LOCK_GIVE(hdw->ctl_lock);
+
+       return ret;
+}
+
+
+static int pvr2_read_register(struct pvr2_hdw *hdw, u16 reg, u32 *data)
+{
+       int ret = 0;
+
+       LOCK_TAKE(hdw->ctl_lock);
+
+       hdw->cmd_buffer[0] = FX2CMD_REG_READ;  /* read register prefix */
+       hdw->cmd_buffer[1] = 0;
+       hdw->cmd_buffer[2] = 0;
+       hdw->cmd_buffer[3] = 0;
+       hdw->cmd_buffer[4] = 0;
+       hdw->cmd_buffer[5] = 0;
+       hdw->cmd_buffer[6] = (reg >> 8) & 0xff;
+       hdw->cmd_buffer[7] = reg & 0xff;
+
+       ret |= pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 4);
+       *data = PVR2_COMPOSE_LE(hdw->cmd_buffer,0);
+
+       LOCK_GIVE(hdw->ctl_lock);
+
+       return ret;
+}
+
+
+void pvr2_hdw_render_useless(struct pvr2_hdw *hdw)
+{
+       if (!hdw->flag_ok) return;
+       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                  "Device being rendered inoperable");
+       if (hdw->vid_stream) {
+               pvr2_stream_setup(hdw->vid_stream,NULL,0,0);
+       }
+       hdw->flag_ok = 0;
+       trace_stbit("flag_ok",hdw->flag_ok);
+       pvr2_hdw_state_sched(hdw);
+}
+
+
+void pvr2_hdw_device_reset(struct pvr2_hdw *hdw)
+{
+       int ret;
+       pvr2_trace(PVR2_TRACE_INIT,"Performing a device reset...");
+       ret = usb_lock_device_for_reset(hdw->usb_dev,NULL);
+       if (ret == 0) {
+               ret = usb_reset_device(hdw->usb_dev);
+               usb_unlock_device(hdw->usb_dev);
+       } else {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Failed to lock USB device ret=%d",ret);
+       }
+       if (init_pause_msec) {
+               pvr2_trace(PVR2_TRACE_INFO,
+                          "Waiting %u msec for hardware to settle",
+                          init_pause_msec);
+               msleep(init_pause_msec);
+       }
+
+}
+
+
+void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
+{
+       char *da;
+       unsigned int pipe;
+       int ret;
+
+       if (!hdw->usb_dev) return;
+
+       da = kmalloc(16, GFP_KERNEL);
+
+       if (da == NULL) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Unable to allocate memory to control CPU reset");
+               return;
+       }
+
+       pvr2_trace(PVR2_TRACE_INIT,"cpureset_assert(%d)",val);
+
+       da[0] = val ? 0x01 : 0x00;
+
+       /* Write the CPUCS register on the 8051.  The lsb of the register
+          is the reset bit; a 1 asserts reset while a 0 clears it. */
+       pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
+       ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0x40,0xe600,0,da,1,HZ);
+       if (ret < 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "cpureset_assert(%d) error=%d",val,ret);
+               pvr2_hdw_render_useless(hdw);
+       }
+
+       kfree(da);
+}
+
+
+int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw)
+{
+       return pvr2_issue_simple_cmd(hdw,FX2CMD_DEEP_RESET);
+}
+
+
+int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw)
+{
+       return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_ON);
+}
+
+
+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)
+{
+       pvr2_trace(PVR2_TRACE_INIT,
+                  "Requesting decoder reset");
+       if (hdw->decoder_client_id) {
+               v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id,
+                                    core, reset, 0);
+               pvr2_hdw_cx25840_vbi_hack(hdw);
+               return 0;
+       }
+       pvr2_trace(PVR2_TRACE_INIT,
+                  "Unable to reset decoder: nothing attached");
+       return -ENOTTY;
+}
+
+
+static int pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff)
+{
+       hdw->flag_ok = !0;
+       return pvr2_issue_simple_cmd(hdw,
+                                    FX2CMD_HCW_DEMOD_RESETIN |
+                                    (1 << 8) |
+                                    ((onoff ? 1 : 0) << 16));
+}
+
+
+static int pvr2_hdw_cmd_onair_fe_power_ctrl(struct pvr2_hdw *hdw, int onoff)
+{
+       hdw->flag_ok = !0;
+       return pvr2_issue_simple_cmd(hdw,(onoff ?
+                                         FX2CMD_ONAIR_DTV_POWER_ON :
+                                         FX2CMD_ONAIR_DTV_POWER_OFF));
+}
+
+
+static int pvr2_hdw_cmd_onair_digital_path_ctrl(struct pvr2_hdw *hdw,
+                                               int onoff)
+{
+       return pvr2_issue_simple_cmd(hdw,(onoff ?
+                                         FX2CMD_ONAIR_DTV_STREAMING_ON :
+                                         FX2CMD_ONAIR_DTV_STREAMING_OFF));
+}
+
+
+static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl)
+{
+       int cmode;
+       /* Compare digital/analog desired setting with current setting.  If
+          they don't match, fix it... */
+       cmode = (digitalFl ? PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG);
+       if (cmode == hdw->pathway_state) {
+               /* They match; nothing to do */
+               return;
+       }
+
+       switch (hdw->hdw_desc->digital_control_scheme) {
+       case PVR2_DIGITAL_SCHEME_HAUPPAUGE:
+               pvr2_hdw_cmd_hcw_demod_reset(hdw,digitalFl);
+               if (cmode == PVR2_PATHWAY_ANALOG) {
+                       /* If moving to analog mode, also force the decoder
+                          to reset.  If no decoder is attached, then it's
+                          ok to ignore this because if/when the decoder
+                          attaches, it will reset itself at that time. */
+                       pvr2_hdw_cmd_decoder_reset(hdw);
+               }
+               break;
+       case PVR2_DIGITAL_SCHEME_ONAIR:
+               /* Supposedly we should always have the power on whether in
+                  digital or analog mode.  But for now do what appears to
+                  work... */
+               pvr2_hdw_cmd_onair_fe_power_ctrl(hdw,digitalFl);
+               break;
+       default: break;
+       }
+
+       pvr2_hdw_untrip_unlocked(hdw);
+       hdw->pathway_state = cmode;
+}
+
+
+static void pvr2_led_ctrl_hauppauge(struct pvr2_hdw *hdw, int onoff)
+{
+       /* change some GPIO data
+        *
+        * note: bit d7 of dir appears to control the LED,
+        * so we shut it off here.
+        *
+        */
+       if (onoff) {
+               pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000481);
+       } else {
+               pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000401);
+       }
+       pvr2_hdw_gpio_chg_out(hdw, 0xffffffff, 0x00000000);
+}
+
+
+typedef void (*led_method_func)(struct pvr2_hdw *,int);
+
+static led_method_func led_methods[] = {
+       [PVR2_LED_SCHEME_HAUPPAUGE] = pvr2_led_ctrl_hauppauge,
+};
+
+
+/* Toggle LED */
+static void pvr2_led_ctrl(struct pvr2_hdw *hdw,int onoff)
+{
+       unsigned int scheme_id;
+       led_method_func fp;
+
+       if ((!onoff) == (!hdw->led_on)) return;
+
+       hdw->led_on = onoff != 0;
+
+       scheme_id = hdw->hdw_desc->led_scheme;
+       if (scheme_id < ARRAY_SIZE(led_methods)) {
+               fp = led_methods[scheme_id];
+       } else {
+               fp = NULL;
+       }
+
+       if (fp) (*fp)(hdw,onoff);
+}
+
+
+/* Stop / start video stream transport */
+static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
+{
+       int ret;
+
+       /* If we're in analog mode, then just issue the usual analog
+          command. */
+       if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
+               return pvr2_issue_simple_cmd(hdw,
+                                            (runFl ?
+                                             FX2CMD_STREAMING_ON :
+                                             FX2CMD_STREAMING_OFF));
+               /*Note: Not reached */
+       }
+
+       if (hdw->pathway_state != PVR2_PATHWAY_DIGITAL) {
+               /* Whoops, we don't know what mode we're in... */
+               return -EINVAL;
+       }
+
+       /* To get here we have to be in digital mode.  The mechanism here
+          is unfortunately different for different vendors.  So we switch
+          on the device's digital scheme attribute in order to figure out
+          what to do. */
+       switch (hdw->hdw_desc->digital_control_scheme) {
+       case PVR2_DIGITAL_SCHEME_HAUPPAUGE:
+               return pvr2_issue_simple_cmd(hdw,
+                                            (runFl ?
+                                             FX2CMD_HCW_DTV_STREAMING_ON :
+                                             FX2CMD_HCW_DTV_STREAMING_OFF));
+       case PVR2_DIGITAL_SCHEME_ONAIR:
+               ret = pvr2_issue_simple_cmd(hdw,
+                                           (runFl ?
+                                            FX2CMD_STREAMING_ON :
+                                            FX2CMD_STREAMING_OFF));
+               if (ret) return ret;
+               return pvr2_hdw_cmd_onair_digital_path_ctrl(hdw,runFl);
+       default:
+               return -EINVAL;
+       }
+}
+
+
+/* Evaluate whether or not state_pathway_ok can change */
+static int state_eval_pathway_ok(struct pvr2_hdw *hdw)
+{
+       if (hdw->state_pathway_ok) {
+               /* Nothing to do if pathway is already ok */
+               return 0;
+       }
+       if (!hdw->state_pipeline_idle) {
+               /* Not allowed to change anything if pipeline is not idle */
+               return 0;
+       }
+       pvr2_hdw_cmd_modeswitch(hdw,hdw->input_val == PVR2_CVAL_INPUT_DTV);
+       hdw->state_pathway_ok = !0;
+       trace_stbit("state_pathway_ok",hdw->state_pathway_ok);
+       return !0;
+}
+
+
+/* Evaluate whether or not state_encoder_ok can change */
+static int state_eval_encoder_ok(struct pvr2_hdw *hdw)
+{
+       if (hdw->state_encoder_ok) return 0;
+       if (hdw->flag_tripped) return 0;
+       if (hdw->state_encoder_run) return 0;
+       if (hdw->state_encoder_config) return 0;
+       if (hdw->state_decoder_run) return 0;
+       if (hdw->state_usbstream_run) return 0;
+       if (hdw->pathway_state == PVR2_PATHWAY_DIGITAL) {
+               if (!hdw->hdw_desc->flag_digital_requires_cx23416) return 0;
+       } else if (hdw->pathway_state != PVR2_PATHWAY_ANALOG) {
+               return 0;
+       }
+
+       if (pvr2_upload_firmware2(hdw) < 0) {
+               hdw->flag_tripped = !0;
+               trace_stbit("flag_tripped",hdw->flag_tripped);
+               return !0;
+       }
+       hdw->state_encoder_ok = !0;
+       trace_stbit("state_encoder_ok",hdw->state_encoder_ok);
+       return !0;
+}
+
+
+/* Evaluate whether or not state_encoder_config can change */
+static int state_eval_encoder_config(struct pvr2_hdw *hdw)
+{
+       if (hdw->state_encoder_config) {
+               if (hdw->state_encoder_ok) {
+                       if (hdw->state_pipeline_req &&
+                           !hdw->state_pipeline_pause) return 0;
+               }
+               hdw->state_encoder_config = 0;
+               hdw->state_encoder_waitok = 0;
+               trace_stbit("state_encoder_waitok",hdw->state_encoder_waitok);
+               /* paranoia - solve race if timer just completed */
+               del_timer_sync(&hdw->encoder_wait_timer);
+       } else {
+               if (!hdw->state_pathway_ok ||
+                   (hdw->pathway_state != PVR2_PATHWAY_ANALOG) ||
+                   !hdw->state_encoder_ok ||
+                   !hdw->state_pipeline_idle ||
+                   hdw->state_pipeline_pause ||
+                   !hdw->state_pipeline_req ||
+                   !hdw->state_pipeline_config) {
+                       /* We must reset the enforced wait interval if
+                          anything has happened that might have disturbed
+                          the encoder.  This should be a rare case. */
+                       if (timer_pending(&hdw->encoder_wait_timer)) {
+                               del_timer_sync(&hdw->encoder_wait_timer);
+                       }
+                       if (hdw->state_encoder_waitok) {
+                               /* Must clear the state - therefore we did
+                                  something to a state bit and must also
+                                  return true. */
+                               hdw->state_encoder_waitok = 0;
+                               trace_stbit("state_encoder_waitok",
+                                           hdw->state_encoder_waitok);
+                               return !0;
+                       }
+                       return 0;
+               }
+               if (!hdw->state_encoder_waitok) {
+                       if (!timer_pending(&hdw->encoder_wait_timer)) {
+                               /* waitok flag wasn't set and timer isn't
+                                  running.  Check flag once more to avoid
+                                  a race then start the timer.  This is
+                                  the point when we measure out a minimal
+                                  quiet interval before doing something to
+                                  the encoder. */
+                               if (!hdw->state_encoder_waitok) {
+                                       hdw->encoder_wait_timer.expires =
+                                               jiffies +
+                                               (HZ * TIME_MSEC_ENCODER_WAIT
+                                                / 1000);
+                                       add_timer(&hdw->encoder_wait_timer);
+                               }
+                       }
+                       /* We can't continue until we know we have been
+                          quiet for the interval measured by this
+                          timer. */
+                       return 0;
+               }
+               pvr2_encoder_configure(hdw);
+               if (hdw->state_encoder_ok) hdw->state_encoder_config = !0;
+       }
+       trace_stbit("state_encoder_config",hdw->state_encoder_config);
+       return !0;
+}
+
+
+/* Return true if the encoder should not be running. */
+static int state_check_disable_encoder_run(struct pvr2_hdw *hdw)
+{
+       if (!hdw->state_encoder_ok) {
+               /* Encoder isn't healthy at the moment, so stop it. */
+               return !0;
+       }
+       if (!hdw->state_pathway_ok) {
+               /* Mode is not understood at the moment (i.e. it wants to
+                  change), so encoder must be stopped. */
+               return !0;
+       }
+
+       switch (hdw->pathway_state) {
+       case PVR2_PATHWAY_ANALOG:
+               if (!hdw->state_decoder_run) {
+                       /* We're in analog mode and the decoder is not
+                          running; thus the encoder should be stopped as
+                          well. */
+                       return !0;
+               }
+               break;
+       case PVR2_PATHWAY_DIGITAL:
+               if (hdw->state_encoder_runok) {
+                       /* This is a funny case.  We're in digital mode so
+                          really the encoder should be stopped.  However
+                          if it really is running, only kill it after
+                          runok has been set.  This gives a chance for the
+                          onair quirk to function (encoder must run
+                          briefly first, at least once, before onair
+                          digital streaming can work). */
+                       return !0;
+               }
+               break;
+       default:
+               /* Unknown mode; so encoder should be stopped. */
+               return !0;
+       }
+
+       /* If we get here, we haven't found a reason to stop the
+          encoder. */
+       return 0;
+}
+
+
+/* Return true if the encoder should be running. */
+static int state_check_enable_encoder_run(struct pvr2_hdw *hdw)
+{
+       if (!hdw->state_encoder_ok) {
+               /* Don't run the encoder if it isn't healthy... */
+               return 0;
+       }
+       if (!hdw->state_pathway_ok) {
+               /* Don't run the encoder if we don't (yet) know what mode
+                  we need to be in... */
+               return 0;
+       }
+
+       switch (hdw->pathway_state) {
+       case PVR2_PATHWAY_ANALOG:
+               if (hdw->state_decoder_run && hdw->state_decoder_ready) {
+                       /* In analog mode, if the decoder is running, then
+                          run the encoder. */
+                       return !0;
+               }
+               break;
+       case PVR2_PATHWAY_DIGITAL:
+               if ((hdw->hdw_desc->digital_control_scheme ==
+                    PVR2_DIGITAL_SCHEME_ONAIR) &&
+                   !hdw->state_encoder_runok) {
+                       /* This is a quirk.  OnAir hardware won't stream
+                          digital until the encoder has been run at least
+                          once, for a minimal period of time (empiricially
+                          measured to be 1/4 second).  So if we're on
+                          OnAir hardware and the encoder has never been
+                          run at all, then start the encoder.  Normal
+                          state machine logic in the driver will
+                          automatically handle the remaining bits. */
+                       return !0;
+               }
+               break;
+       default:
+               /* For completeness (unknown mode; encoder won't run ever) */
+               break;
+       }
+       /* If we get here, then we haven't found any reason to run the
+          encoder, so don't run it. */
+       return 0;
+}
+
+
+/* Evaluate whether or not state_encoder_run can change */
+static int state_eval_encoder_run(struct pvr2_hdw *hdw)
+{
+       if (hdw->state_encoder_run) {
+               if (!state_check_disable_encoder_run(hdw)) return 0;
+               if (hdw->state_encoder_ok) {
+                       del_timer_sync(&hdw->encoder_run_timer);
+                       if (pvr2_encoder_stop(hdw) < 0) return !0;
+               }
+               hdw->state_encoder_run = 0;
+       } else {
+               if (!state_check_enable_encoder_run(hdw)) return 0;
+               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);
+                       add_timer(&hdw->encoder_run_timer);
+               }
+       }
+       trace_stbit("state_encoder_run",hdw->state_encoder_run);
+       return !0;
+}
+
+
+/* Timeout function for quiescent timer. */
+static void pvr2_hdw_quiescent_timeout(unsigned long data)
+{
+       struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
+       hdw->state_decoder_quiescent = !0;
+       trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent);
+       hdw->state_stale = !0;
+       queue_work(hdw->workqueue,&hdw->workpoll);
+}
+
+
+/* Timeout function for decoder stabilization timer. */
+static void pvr2_hdw_decoder_stabilization_timeout(unsigned long data)
+{
+       struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
+       hdw->state_decoder_ready = !0;
+       trace_stbit("state_decoder_ready", hdw->state_decoder_ready);
+       hdw->state_stale = !0;
+       queue_work(hdw->workqueue, &hdw->workpoll);
+}
+
+
+/* Timeout function for encoder wait timer. */
+static void pvr2_hdw_encoder_wait_timeout(unsigned long data)
+{
+       struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
+       hdw->state_encoder_waitok = !0;
+       trace_stbit("state_encoder_waitok",hdw->state_encoder_waitok);
+       hdw->state_stale = !0;
+       queue_work(hdw->workqueue,&hdw->workpoll);
+}
+
+
+/* Timeout function for encoder run timer. */
+static void pvr2_hdw_encoder_run_timeout(unsigned long data)
+{
+       struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
+       if (!hdw->state_encoder_runok) {
+               hdw->state_encoder_runok = !0;
+               trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
+               hdw->state_stale = !0;
+               queue_work(hdw->workqueue,&hdw->workpoll);
+       }
+}
+
+
+/* Evaluate whether or not state_decoder_run can change */
+static int state_eval_decoder_run(struct pvr2_hdw *hdw)
+{
+       if (hdw->state_decoder_run) {
+               if (hdw->state_encoder_ok) {
+                       if (hdw->state_pipeline_req &&
+                           !hdw->state_pipeline_pause &&
+                           hdw->state_pathway_ok) return 0;
+               }
+               if (!hdw->flag_decoder_missed) {
+                       pvr2_decoder_enable(hdw,0);
+               }
+               hdw->state_decoder_quiescent = 0;
+               hdw->state_decoder_run = 0;
+               /* paranoia - solve race if timer(s) just completed */
+               del_timer_sync(&hdw->quiescent_timer);
+               /* Kill the stabilization timer, in case we're killing the
+                  encoder before the previous stabilization interval has
+                  been properly timed. */
+               del_timer_sync(&hdw->decoder_stabilization_timer);
+               hdw->state_decoder_ready = 0;
+       } else {
+               if (!hdw->state_decoder_quiescent) {
+                       if (!timer_pending(&hdw->quiescent_timer)) {
+                               /* We don't do something about the
+                                  quiescent timer until right here because
+                                  we also want to catch cases where the
+                                  decoder was already not running (like
+                                  after initialization) as opposed to
+                                  knowing that we had just stopped it.
+                                  The second flag check is here to cover a
+                                  race - the timer could have run and set
+                                  this flag just after the previous check
+                                  but before we did the pending check. */
+                               if (!hdw->state_decoder_quiescent) {
+                                       hdw->quiescent_timer.expires =
+                                               jiffies +
+                                               (HZ * TIME_MSEC_DECODER_WAIT
+                                                / 1000);
+                                       add_timer(&hdw->quiescent_timer);
+                               }
+                       }
+                       /* Don't allow decoder to start again until it has
+                          been quiesced first.  This little detail should
+                          hopefully further stabilize the encoder. */
+                       return 0;
+               }
+               if (!hdw->state_pathway_ok ||
+                   (hdw->pathway_state != PVR2_PATHWAY_ANALOG) ||
+                   !hdw->state_pipeline_req ||
+                   hdw->state_pipeline_pause ||
+                   !hdw->state_pipeline_config ||
+                   !hdw->state_encoder_config ||
+                   !hdw->state_encoder_ok) return 0;
+               del_timer_sync(&hdw->quiescent_timer);
+               if (hdw->flag_decoder_missed) return 0;
+               if (pvr2_decoder_enable(hdw,!0) < 0) return 0;
+               hdw->state_decoder_quiescent = 0;
+               hdw->state_decoder_ready = 0;
+               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);
+                       add_timer(&hdw->decoder_stabilization_timer);
+               } else {
+                       hdw->state_decoder_ready = !0;
+               }
+       }
+       trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent);
+       trace_stbit("state_decoder_run",hdw->state_decoder_run);
+       trace_stbit("state_decoder_ready", hdw->state_decoder_ready);
+       return !0;
+}
+
+
+/* Evaluate whether or not state_usbstream_run can change */
+static int state_eval_usbstream_run(struct pvr2_hdw *hdw)
+{
+       if (hdw->state_usbstream_run) {
+               int fl = !0;
+               if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
+                       fl = (hdw->state_encoder_ok &&
+                             hdw->state_encoder_run);
+               } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
+                          (hdw->hdw_desc->flag_digital_requires_cx23416)) {
+                       fl = hdw->state_encoder_ok;
+               }
+               if (fl &&
+                   hdw->state_pipeline_req &&
+                   !hdw->state_pipeline_pause &&
+                   hdw->state_pathway_ok) {
+                       return 0;
+               }
+               pvr2_hdw_cmd_usbstream(hdw,0);
+               hdw->state_usbstream_run = 0;
+       } else {
+               if (!hdw->state_pipeline_req ||
+                   hdw->state_pipeline_pause ||
+                   !hdw->state_pathway_ok) return 0;
+               if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
+                       if (!hdw->state_encoder_ok ||
+                           !hdw->state_encoder_run) return 0;
+               } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
+                          (hdw->hdw_desc->flag_digital_requires_cx23416)) {
+                       if (!hdw->state_encoder_ok) return 0;
+                       if (hdw->state_encoder_run) return 0;
+                       if (hdw->hdw_desc->digital_control_scheme ==
+                           PVR2_DIGITAL_SCHEME_ONAIR) {
+                               /* OnAir digital receivers won't stream
+                                  unless the analog encoder has run first.
+                                  Why?  I have no idea.  But don't even
+                                  try until we know the analog side is
+                                  known to have run. */
+                               if (!hdw->state_encoder_runok) return 0;
+                       }
+               }
+               if (pvr2_hdw_cmd_usbstream(hdw,!0) < 0) return 0;
+               hdw->state_usbstream_run = !0;
+       }
+       trace_stbit("state_usbstream_run",hdw->state_usbstream_run);
+       return !0;
+}
+
+
+/* Attempt to configure pipeline, if needed */
+static int state_eval_pipeline_config(struct pvr2_hdw *hdw)
+{
+       if (hdw->state_pipeline_config ||
+           hdw->state_pipeline_pause) return 0;
+       pvr2_hdw_commit_execute(hdw);
+       return !0;
+}
+
+
+/* Update pipeline idle and pipeline pause tracking states based on other
+   inputs.  This must be called whenever the other relevant inputs have
+   changed. */
+static int state_update_pipeline_state(struct pvr2_hdw *hdw)
+{
+       unsigned int st;
+       int updatedFl = 0;
+       /* Update pipeline state */
+       st = !(hdw->state_encoder_run ||
+              hdw->state_decoder_run ||
+              hdw->state_usbstream_run ||
+              (!hdw->state_decoder_quiescent));
+       if (!st != !hdw->state_pipeline_idle) {
+               hdw->state_pipeline_idle = st;
+               updatedFl = !0;
+       }
+       if (hdw->state_pipeline_idle && hdw->state_pipeline_pause) {
+               hdw->state_pipeline_pause = 0;
+               updatedFl = !0;
+       }
+       return updatedFl;
+}
+
+
+typedef int (*state_eval_func)(struct pvr2_hdw *);
+
+/* Set of functions to be run to evaluate various states in the driver. */
+static const state_eval_func eval_funcs[] = {
+       state_eval_pathway_ok,
+       state_eval_pipeline_config,
+       state_eval_encoder_ok,
+       state_eval_encoder_config,
+       state_eval_decoder_run,
+       state_eval_encoder_run,
+       state_eval_usbstream_run,
+};
+
+
+/* Process various states and return true if we did anything interesting. */
+static int pvr2_hdw_state_update(struct pvr2_hdw *hdw)
+{
+       unsigned int i;
+       int state_updated = 0;
+       int check_flag;
+
+       if (!hdw->state_stale) return 0;
+       if ((hdw->fw1_state != FW1_STATE_OK) ||
+           !hdw->flag_ok) {
+               hdw->state_stale = 0;
+               return !0;
+       }
+       /* This loop is the heart of the entire driver.  It keeps trying to
+          evaluate various bits of driver state until nothing changes for
+          one full iteration.  Each "bit of state" tracks some global
+          aspect of the driver, e.g. whether decoder should run, if
+          pipeline is configured, usb streaming is on, etc.  We separately
+          evaluate each of those questions based on other driver state to
+          arrive at the correct running configuration. */
+       do {
+               check_flag = 0;
+               state_update_pipeline_state(hdw);
+               /* Iterate over each bit of state */
+               for (i = 0; (i<ARRAY_SIZE(eval_funcs)) && hdw->flag_ok; i++) {
+                       if ((*eval_funcs[i])(hdw)) {
+                               check_flag = !0;
+                               state_updated = !0;
+                               state_update_pipeline_state(hdw);
+                       }
+               }
+       } while (check_flag && hdw->flag_ok);
+       hdw->state_stale = 0;
+       trace_stbit("state_stale",hdw->state_stale);
+       return state_updated;
+}
+
+
+static unsigned int print_input_mask(unsigned int msk,
+                                    char *buf,unsigned int acnt)
+{
+       unsigned int idx,ccnt;
+       unsigned int tcnt = 0;
+       for (idx = 0; idx < ARRAY_SIZE(control_values_input); idx++) {
+               if (!((1 << idx) & msk)) continue;
+               ccnt = scnprintf(buf+tcnt,
+                                acnt-tcnt,
+                                "%s%s",
+                                (tcnt ? ", " : ""),
+                                control_values_input[idx]);
+               tcnt += ccnt;
+       }
+       return tcnt;
+}
+
+
+static const char *pvr2_pathway_state_name(int id)
+{
+       switch (id) {
+       case PVR2_PATHWAY_ANALOG: return "analog";
+       case PVR2_PATHWAY_DIGITAL: return "digital";
+       default: return "unknown";
+       }
+}
+
+
+static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
+                                            char *buf,unsigned int acnt)
+{
+       switch (which) {
+       case 0:
+               return scnprintf(
+                       buf,acnt,
+                       "driver:%s%s%s%s%s <mode=%s>",
+                       (hdw->flag_ok ? " <ok>" : " <fail>"),
+                       (hdw->flag_init_ok ? " <init>" : " <uninitialized>"),
+                       (hdw->flag_disconnected ? " <disconnected>" :
+                        " <connected>"),
+                       (hdw->flag_tripped ? " <tripped>" : ""),
+                       (hdw->flag_decoder_missed ? " <no decoder>" : ""),
+                       pvr2_pathway_state_name(hdw->pathway_state));
+
+       case 1:
+               return scnprintf(
+                       buf,acnt,
+                       "pipeline:%s%s%s%s",
+                       (hdw->state_pipeline_idle ? " <idle>" : ""),
+                       (hdw->state_pipeline_config ?
+                        " <configok>" : " <stale>"),
+                       (hdw->state_pipeline_req ? " <req>" : ""),
+                       (hdw->state_pipeline_pause ? " <pause>" : ""));
+       case 2:
+               return scnprintf(
+                       buf,acnt,
+                       "worker:%s%s%s%s%s%s%s",
+                       (hdw->state_decoder_run ?
+                        (hdw->state_decoder_ready ?
+                         "<decode:run>" : " <decode:start>") :
+                        (hdw->state_decoder_quiescent ?
+                         "" : " <decode:stop>")),
+                       (hdw->state_decoder_quiescent ?
+                        " <decode:quiescent>" : ""),
+                       (hdw->state_encoder_ok ?
+                        "" : " <encode:init>"),
+                       (hdw->state_encoder_run ?
+                        (hdw->state_encoder_runok ?
+                         " <encode:run>" :
+                         " <encode:firstrun>") :
+                        (hdw->state_encoder_runok ?
+                         " <encode:stop>" :
+                         " <encode:virgin>")),
+                       (hdw->state_encoder_config ?
+                        " <encode:configok>" :
+                        (hdw->state_encoder_waitok ?
+                         "" : " <encode:waitok>")),
+                       (hdw->state_usbstream_run ?
+                        " <usb:run>" : " <usb:stop>"),
+                       (hdw->state_pathway_ok ?
+                        " <pathway:ok>" : ""));
+       case 3:
+               return scnprintf(
+                       buf,acnt,
+                       "state: %s",
+                       pvr2_get_state_name(hdw->master_state));
+       case 4: {
+               unsigned int tcnt = 0;
+               unsigned int ccnt;
+
+               ccnt = scnprintf(buf,
+                                acnt,
+                                "Hardware supported inputs: ");
+               tcnt += ccnt;
+               tcnt += print_input_mask(hdw->input_avail_mask,
+                                        buf+tcnt,
+                                        acnt-tcnt);
+               if (hdw->input_avail_mask != hdw->input_allowed_mask) {
+                       ccnt = scnprintf(buf+tcnt,
+                                        acnt-tcnt,
+                                        "; allowed inputs: ");
+                       tcnt += ccnt;
+                       tcnt += print_input_mask(hdw->input_allowed_mask,
+                                                buf+tcnt,
+                                                acnt-tcnt);
+               }
+               return tcnt;
+       }
+       case 5: {
+               struct pvr2_stream_stats stats;
+               if (!hdw->vid_stream) break;
+               pvr2_stream_get_stats(hdw->vid_stream,
+                                     &stats,
+                                     0);
+               return scnprintf(
+                       buf,acnt,
+                       "Bytes streamed=%u"
+                       " URBs: queued=%u idle=%u ready=%u"
+                       " processed=%u failed=%u",
+                       stats.bytes_processed,
+                       stats.buffers_in_queue,
+                       stats.buffers_in_idle,
+                       stats.buffers_in_ready,
+                       stats.buffers_processed,
+                       stats.buffers_failed);
+       }
+       case 6: {
+               unsigned int id = hdw->ir_scheme_active;
+               return scnprintf(buf, acnt, "ir scheme: id=%d %s", id,
+                                (id >= ARRAY_SIZE(ir_scheme_names) ?
+                                 "?" : ir_scheme_names[id]));
+       }
+       default: break;
+       }
+       return 0;
+}
+
+
+/* Generate report containing info about attached sub-devices and attached
+   i2c clients, including an indication of which attached i2c clients are
+   actually sub-devices. */
+static unsigned int pvr2_hdw_report_clients(struct pvr2_hdw *hdw,
+                                           char *buf, unsigned int acnt)
+{
+       struct v4l2_subdev *sd;
+       unsigned int tcnt = 0;
+       unsigned int ccnt;
+       struct i2c_client *client;
+       const char *p;
+       unsigned int id;
+
+       ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers and I2C clients:\n");
+       tcnt += ccnt;
+       v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
+               id = sd->grp_id;
+               p = NULL;
+               if (id < ARRAY_SIZE(module_names)) p = module_names[id];
+               if (p) {
+                       ccnt = scnprintf(buf + tcnt, acnt - tcnt, "  %s:", p);
+                       tcnt += ccnt;
+               } else {
+                       ccnt = scnprintf(buf + tcnt, acnt - tcnt,
+                                        "  (unknown id=%u):", id);
+                       tcnt += ccnt;
+               }
+               client = v4l2_get_subdevdata(sd);
+               if (client) {
+                       ccnt = scnprintf(buf + tcnt, acnt - tcnt,
+                                        " %s @ %02x\n", client->name,
+                                        client->addr);
+                       tcnt += ccnt;
+               } else {
+                       ccnt = scnprintf(buf + tcnt, acnt - tcnt,
+                                        " no i2c client\n");
+                       tcnt += ccnt;
+               }
+       }
+       return tcnt;
+}
+
+
+unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw,
+                                  char *buf,unsigned int acnt)
+{
+       unsigned int bcnt,ccnt,idx;
+       bcnt = 0;
+       LOCK_TAKE(hdw->big_lock);
+       for (idx = 0; ; idx++) {
+               ccnt = pvr2_hdw_report_unlocked(hdw,idx,buf,acnt);
+               if (!ccnt) break;
+               bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+               if (!acnt) break;
+               buf[0] = '\n'; ccnt = 1;
+               bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       }
+       ccnt = pvr2_hdw_report_clients(hdw, buf, acnt);
+       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+       LOCK_GIVE(hdw->big_lock);
+       return bcnt;
+}
+
+
+static void pvr2_hdw_state_log_state(struct pvr2_hdw *hdw)
+{
+       char buf[256];
+       unsigned int idx, ccnt;
+       unsigned int lcnt, ucnt;
+
+       for (idx = 0; ; idx++) {
+               ccnt = pvr2_hdw_report_unlocked(hdw,idx,buf,sizeof(buf));
+               if (!ccnt) break;
+               printk(KERN_INFO "%s %.*s\n",hdw->name,ccnt,buf);
+       }
+       ccnt = pvr2_hdw_report_clients(hdw, buf, sizeof(buf));
+       ucnt = 0;
+       while (ucnt < ccnt) {
+               lcnt = 0;
+               while ((lcnt + ucnt < ccnt) && (buf[lcnt + ucnt] != '\n')) {
+                       lcnt++;
+               }
+               printk(KERN_INFO "%s %.*s\n", hdw->name, lcnt, buf + ucnt);
+               ucnt += lcnt + 1;
+       }
+}
+
+
+/* Evaluate and update the driver's current state, taking various actions
+   as appropriate for the update. */
+static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
+{
+       unsigned int st;
+       int state_updated = 0;
+       int callback_flag = 0;
+       int analog_mode;
+
+       pvr2_trace(PVR2_TRACE_STBITS,
+                  "Drive state check START");
+       if (pvrusb2_debug & PVR2_TRACE_STBITS) {
+               pvr2_hdw_state_log_state(hdw);
+       }
+
+       /* Process all state and get back over disposition */
+       state_updated = pvr2_hdw_state_update(hdw);
+
+       analog_mode = (hdw->pathway_state != PVR2_PATHWAY_DIGITAL);
+
+       /* Update master state based upon all other states. */
+       if (!hdw->flag_ok) {
+               st = PVR2_STATE_DEAD;
+       } else if (hdw->fw1_state != FW1_STATE_OK) {
+               st = PVR2_STATE_COLD;
+       } else if ((analog_mode ||
+                   hdw->hdw_desc->flag_digital_requires_cx23416) &&
+                  !hdw->state_encoder_ok) {
+               st = PVR2_STATE_WARM;
+       } else if (hdw->flag_tripped ||
+                  (analog_mode && hdw->flag_decoder_missed)) {
+               st = PVR2_STATE_ERROR;
+       } else if (hdw->state_usbstream_run &&
+                  (!analog_mode ||
+                   (hdw->state_encoder_run && hdw->state_decoder_run))) {
+               st = PVR2_STATE_RUN;
+       } else {
+               st = PVR2_STATE_READY;
+       }
+       if (hdw->master_state != st) {
+               pvr2_trace(PVR2_TRACE_STATE,
+                          "Device state change from %s to %s",
+                          pvr2_get_state_name(hdw->master_state),
+                          pvr2_get_state_name(st));
+               pvr2_led_ctrl(hdw,st == PVR2_STATE_RUN);
+               hdw->master_state = st;
+               state_updated = !0;
+               callback_flag = !0;
+       }
+       if (state_updated) {
+               /* Trigger anyone waiting on any state changes here. */
+               wake_up(&hdw->state_wait_data);
+       }
+
+       if (pvrusb2_debug & PVR2_TRACE_STBITS) {
+               pvr2_hdw_state_log_state(hdw);
+       }
+       pvr2_trace(PVR2_TRACE_STBITS,
+                  "Drive state check DONE callback=%d",callback_flag);
+
+       return callback_flag;
+}
+
+
+/* Cause kernel thread to check / update driver state */
+static void pvr2_hdw_state_sched(struct pvr2_hdw *hdw)
+{
+       if (hdw->state_stale) return;
+       hdw->state_stale = !0;
+       trace_stbit("state_stale",hdw->state_stale);
+       queue_work(hdw->workqueue,&hdw->workpoll);
+}
+
+
+int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *dp)
+{
+       return pvr2_read_register(hdw,PVR2_GPIO_DIR,dp);
+}
+
+
+int pvr2_hdw_gpio_get_out(struct pvr2_hdw *hdw,u32 *dp)
+{
+       return pvr2_read_register(hdw,PVR2_GPIO_OUT,dp);
+}
+
+
+int pvr2_hdw_gpio_get_in(struct pvr2_hdw *hdw,u32 *dp)
+{
+       return pvr2_read_register(hdw,PVR2_GPIO_IN,dp);
+}
+
+
+int pvr2_hdw_gpio_chg_dir(struct pvr2_hdw *hdw,u32 msk,u32 val)
+{
+       u32 cval,nval;
+       int ret;
+       if (~msk) {
+               ret = pvr2_read_register(hdw,PVR2_GPIO_DIR,&cval);
+               if (ret) return ret;
+               nval = (cval & ~msk) | (val & msk);
+               pvr2_trace(PVR2_TRACE_GPIO,
+                          "GPIO direction changing 0x%x:0x%x"
+                          " from 0x%x to 0x%x",
+                          msk,val,cval,nval);
+       } else {
+               nval = val;
+               pvr2_trace(PVR2_TRACE_GPIO,
+                          "GPIO direction changing to 0x%x",nval);
+       }
+       return pvr2_write_register(hdw,PVR2_GPIO_DIR,nval);
+}
+
+
+int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val)
+{
+       u32 cval,nval;
+       int ret;
+       if (~msk) {
+               ret = pvr2_read_register(hdw,PVR2_GPIO_OUT,&cval);
+               if (ret) return ret;
+               nval = (cval & ~msk) | (val & msk);
+               pvr2_trace(PVR2_TRACE_GPIO,
+                          "GPIO output changing 0x%x:0x%x from 0x%x to 0x%x",
+                          msk,val,cval,nval);
+       } else {
+               nval = val;
+               pvr2_trace(PVR2_TRACE_GPIO,
+                          "GPIO output changing to 0x%x",nval);
+       }
+       return pvr2_write_register(hdw,PVR2_GPIO_OUT,nval);
+}
+
+
+void pvr2_hdw_status_poll(struct pvr2_hdw *hdw)
+{
+       struct v4l2_tuner *vtp = &hdw->tuner_signal_info;
+       memset(vtp, 0, sizeof(*vtp));
+       vtp->type = (hdw->input_val == PVR2_CVAL_INPUT_RADIO) ?
+               V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+       hdw->tuner_signal_stale = 0;
+       /* Note: There apparently is no replacement for VIDIOC_CROPCAP
+          using v4l2-subdev - therefore we can't support that AT ALL right
+          now.  (Of course, no sub-drivers seem to implement it either.
+          But now it's a a chicken and egg problem...) */
+       v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, g_tuner, vtp);
+       pvr2_trace(PVR2_TRACE_CHIPS, "subdev status poll"
+                  " type=%u strength=%u audio=0x%x cap=0x%x"
+                  " low=%u hi=%u",
+                  vtp->type,
+                  vtp->signal, vtp->rxsubchans, vtp->capability,
+                  vtp->rangelow, vtp->rangehigh);
+
+       /* We have to do this to avoid getting into constant polling if
+          there's nobody to answer a poll of cropcap info. */
+       hdw->cropcap_stale = 0;
+}
+
+
+unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw)
+{
+       return hdw->input_avail_mask;
+}
+
+
+unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *hdw)
+{
+       return hdw->input_allowed_mask;
+}
+
+
+static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v)
+{
+       if (hdw->input_val != v) {
+               hdw->input_val = v;
+               hdw->input_dirty = !0;
+       }
+
+       /* Handle side effects - if we switch to a mode that needs the RF
+          tuner, then select the right frequency choice as well and mark
+          it dirty. */
+       if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
+               hdw->freqSelector = 0;
+               hdw->freqDirty = !0;
+       } else if ((hdw->input_val == PVR2_CVAL_INPUT_TV) ||
+                  (hdw->input_val == PVR2_CVAL_INPUT_DTV)) {
+               hdw->freqSelector = 1;
+               hdw->freqDirty = !0;
+       }
+       return 0;
+}
+
+
+int pvr2_hdw_set_input_allowed(struct pvr2_hdw *hdw,
+                              unsigned int change_mask,
+                              unsigned int change_val)
+{
+       int ret = 0;
+       unsigned int nv,m,idx;
+       LOCK_TAKE(hdw->big_lock);
+       do {
+               nv = hdw->input_allowed_mask & ~change_mask;
+               nv |= (change_val & change_mask);
+               nv &= hdw->input_avail_mask;
+               if (!nv) {
+                       /* No legal modes left; return error instead. */
+                       ret = -EPERM;
+                       break;
+               }
+               hdw->input_allowed_mask = nv;
+               if ((1 << hdw->input_val) & hdw->input_allowed_mask) {
+                       /* Current mode is still in the allowed mask, so
+                          we're done. */
+                       break;
+               }
+               /* Select and switch to a mode that is still in the allowed
+                  mask */
+               if (!hdw->input_allowed_mask) {
+                       /* Nothing legal; give up */
+                       break;
+               }
+               m = hdw->input_allowed_mask;
+               for (idx = 0; idx < (sizeof(m) << 3); idx++) {
+                       if (!((1 << idx) & m)) continue;
+                       pvr2_hdw_set_input(hdw,idx);
+                       break;
+               }
+       } while (0);
+       LOCK_GIVE(hdw->big_lock);
+       return ret;
+}
+
+
+/* Find I2C address of eeprom */
+static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
+{
+       int result;
+       LOCK_TAKE(hdw->ctl_lock); do {
+               hdw->cmd_buffer[0] = FX2CMD_GET_EEPROM_ADDR;
+               result = pvr2_send_request(hdw,
+                                          hdw->cmd_buffer,1,
+                                          hdw->cmd_buffer,1);
+               if (result < 0) break;
+               result = hdw->cmd_buffer[0];
+       } while(0); LOCK_GIVE(hdw->ctl_lock);
+       return result;
+}
+
+
+int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
+                            struct v4l2_dbg_match *match, u64 reg_id,
+                            int setFl, u64 *val_ptr)
+{
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       struct v4l2_dbg_register req;
+       int stat = 0;
+       int okFl = 0;
+
+       if (!capable(CAP_SYS_ADMIN)) return -EPERM;
+
+       req.match = *match;
+       req.reg = reg_id;
+       if (setFl) req.val = *val_ptr;
+       /* It would be nice to know if a sub-device answered the request */
+       v4l2_device_call_all(&hdw->v4l2_dev, 0, core, g_register, &req);
+       if (!setFl) *val_ptr = req.val;
+       if (okFl) {
+               return stat;
+       }
+       return -EINVAL;
+#else
+       return -ENOSYS;
+#endif
+}
+
+
+/*
+  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.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h
new file mode 100644 (file)
index 0000000..8060fc6
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_HDW_H
+#define __PVRUSB2_HDW_H
+
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include "pvrusb2-io.h"
+#include "pvrusb2-ctrl.h"
+
+
+/* Private internal control ids, look these up with
+   pvr2_hdw_get_ctrl_by_id() - these are NOT visible in V4L */
+#define PVR2_CID_STDCUR 2
+#define PVR2_CID_STDAVAIL 3
+#define PVR2_CID_INPUT 4
+#define PVR2_CID_AUDIOMODE 5
+#define PVR2_CID_FREQUENCY 6
+#define PVR2_CID_HRES 7
+#define PVR2_CID_VRES 8
+#define PVR2_CID_CROPL 9
+#define PVR2_CID_CROPT 10
+#define PVR2_CID_CROPW 11
+#define PVR2_CID_CROPH 12
+#define PVR2_CID_CROPCAPPAN 13
+#define PVR2_CID_CROPCAPPAD 14
+#define PVR2_CID_CROPCAPBL 15
+#define PVR2_CID_CROPCAPBT 16
+#define PVR2_CID_CROPCAPBW 17
+#define PVR2_CID_CROPCAPBH 18
+#define PVR2_CID_STDDETECT 19
+
+/* Legal values for the INPUT state variable */
+#define PVR2_CVAL_INPUT_TV 0
+#define PVR2_CVAL_INPUT_DTV 1
+#define PVR2_CVAL_INPUT_COMPOSITE 2
+#define PVR2_CVAL_INPUT_SVIDEO 3
+#define PVR2_CVAL_INPUT_RADIO 4
+
+enum pvr2_config {
+       pvr2_config_empty,    /* No configuration */
+       pvr2_config_mpeg,     /* Encoded / compressed video */
+       pvr2_config_vbi,      /* Standard vbi info */
+       pvr2_config_pcm,      /* Audio raw pcm stream */
+       pvr2_config_rawvideo, /* Video raw frames */
+};
+
+enum pvr2_v4l_type {
+       pvr2_v4l_type_video,
+       pvr2_v4l_type_vbi,
+       pvr2_v4l_type_radio,
+};
+
+/* Major states that we can be in:
+ *
+ *  DEAD - Device is in an unusable state and cannot be recovered.  This
+ *  can happen if we completely lose the ability to communicate with it
+ *  (but it might still on the bus).  In this state there's nothing we can
+ *  do; it must be replugged in order to recover.
+ *
+ *  COLD - Device is in an unusable state, needs microcontroller firmware.
+ *
+ *  WARM - We can communicate with the device and the proper
+ *  microcontroller firmware is running, but other device initialization is
+ *  still needed (e.g. encoder firmware).
+ *
+ *  ERROR - A problem prevents capture operation (e.g. encoder firmware
+ *  missing).
+ *
+ *  READY - Device is operational, but not streaming.
+ *
+ *  RUN - Device is streaming.
+ *
+ */
+#define PVR2_STATE_NONE 0
+#define PVR2_STATE_DEAD 1
+#define PVR2_STATE_COLD 2
+#define PVR2_STATE_WARM 3
+#define PVR2_STATE_ERROR 4
+#define PVR2_STATE_READY 5
+#define PVR2_STATE_RUN 6
+
+/* Translate configuration enum to a string label */
+const char *pvr2_config_get_name(enum pvr2_config);
+
+struct pvr2_hdw;
+
+/* Create and return a structure for interacting with the underlying
+   hardware */
+struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+                                const struct usb_device_id *devid);
+
+/* Perform second stage initialization, passing in a notification callback
+   for when the master state changes. */
+int pvr2_hdw_initialize(struct pvr2_hdw *,
+                       void (*callback_func)(void *),
+                       void *callback_data);
+
+/* Destroy hardware interaction structure */
+void pvr2_hdw_destroy(struct pvr2_hdw *);
+
+/* Return true if in the ready (normal) state */
+int pvr2_hdw_dev_ok(struct pvr2_hdw *);
+
+/* Return small integer number [1..N] for logical instance number of this
+   device.  This is useful for indexing array-valued module parameters. */
+int pvr2_hdw_get_unit_number(struct pvr2_hdw *);
+
+/* Get pointer to underlying USB device */
+struct usb_device *pvr2_hdw_get_dev(struct pvr2_hdw *);
+
+/* Retrieve serial number of device */
+unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *);
+
+/* Retrieve bus location info of device */
+const char *pvr2_hdw_get_bus_info(struct pvr2_hdw *);
+
+/* Retrieve per-instance string identifier for this specific device */
+const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *);
+
+/* Called when hardware has been unplugged */
+void pvr2_hdw_disconnect(struct pvr2_hdw *);
+
+/* Get the number of defined controls */
+unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *);
+
+/* Retrieve a control handle given its index (0..count-1) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *,unsigned int);
+
+/* Retrieve a control handle given its internal ID (if any) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *,unsigned int);
+
+/* Retrieve a control handle given its V4L ID (if any) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *,unsigned int ctl_id);
+
+/* Retrieve a control handle given its immediate predecessor V4L ID (if any) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *,
+                                           unsigned int ctl_id);
+
+/* Commit all control changes made up to this point */
+int pvr2_hdw_commit_ctl(struct pvr2_hdw *);
+
+/* Return a bit mask of valid input selections for this device.  Mask bits
+ * will be according to PVR_CVAL_INPUT_xxxx definitions. */
+unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *);
+
+/* Return a bit mask of allowed input selections for this device.  Mask bits
+ * will be according to PVR_CVAL_INPUT_xxxx definitions. */
+unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *);
+
+/* Change the set of allowed input selections for this device.  Both
+   change_mask and change_valu are mask bits according to
+   PVR_CVAL_INPUT_xxxx definitions.  The change_mask parameter indicate
+   which settings are being changed and the change_val parameter indicates
+   whether corresponding settings are being set or cleared. */
+int pvr2_hdw_set_input_allowed(struct pvr2_hdw *,
+                              unsigned int change_mask,
+                              unsigned int change_val);
+
+/* Return name for this driver instance */
+const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *);
+
+/* Mark tuner status stale so that it will be re-fetched */
+void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *);
+
+/* Return information about the tuner */
+int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *);
+
+/* Return information about cropping capabilities */
+int pvr2_hdw_get_cropcap(struct pvr2_hdw *, struct v4l2_cropcap *);
+
+/* Query device and see if it thinks it is on a high-speed USB link */
+int pvr2_hdw_is_hsm(struct pvr2_hdw *);
+
+/* Return a string token representative of the hardware type */
+const char *pvr2_hdw_get_type(struct pvr2_hdw *);
+
+/* Return a single line description of the hardware type */
+const char *pvr2_hdw_get_desc(struct pvr2_hdw *);
+
+/* Turn streaming on/off */
+int pvr2_hdw_set_streaming(struct pvr2_hdw *,int);
+
+/* Find out if streaming is on */
+int pvr2_hdw_get_streaming(struct pvr2_hdw *);
+
+/* Retrieve driver overall state */
+int pvr2_hdw_get_state(struct pvr2_hdw *);
+
+/* Configure the type of stream to generate */
+int pvr2_hdw_set_stream_type(struct pvr2_hdw *, enum pvr2_config);
+
+/* Get handle to video output stream */
+struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *);
+
+/* Enable / disable retrieval of CPU firmware or prom contents.  This must
+   be enabled before pvr2_hdw_cpufw_get() will function.  Note that doing
+   this may prevent the device from running (and leaving this mode may
+   imply a device reset). */
+void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *,
+                               int mode, /* 0=8KB FX2, 1=16KB FX2, 2=PROM */
+                               int enable_flag);
+
+/* Return true if we're in a mode for retrieval CPU firmware */
+int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *);
+
+/* Retrieve a piece of the CPU's firmware at the given offset.  Return
+   value is the number of bytes retrieved or zero if we're past the end or
+   an error otherwise (e.g. if firmware retrieval is not enabled). */
+int pvr2_hdw_cpufw_get(struct pvr2_hdw *,unsigned int offs,
+                      char *buf,unsigned int cnt);
+
+/* Retrieve a previously stored v4l minor device number */
+int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *,enum pvr2_v4l_type index);
+
+/* Store a v4l minor device number */
+void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,
+                                    enum pvr2_v4l_type index,int);
+
+/* Direct read/write access to chip's registers:
+   match - specify criteria to identify target chip (this is a v4l dbg struct)
+   reg_id  - register number to access
+   setFl   - true to set the register, false to read it
+   val_ptr - storage location for source / result. */
+int pvr2_hdw_register_access(struct pvr2_hdw *,
+                            struct v4l2_dbg_match *match, u64 reg_id,
+                            int setFl, u64 *val_ptr);
+
+/* The following entry points are all lower level things you normally don't
+   want to worry about. */
+
+/* Issue a command and get a response from the device.  LOTS of higher
+   level stuff is built on this. */
+int pvr2_send_request(struct pvr2_hdw *,
+                     void *write_ptr,unsigned int write_len,
+                     void *read_ptr,unsigned int read_len);
+
+/* Slightly higher level device communication functions. */
+int pvr2_write_register(struct pvr2_hdw *, u16, u32);
+
+/* Call if for any reason we can't talk to the hardware anymore - this will
+   cause the driver to stop flailing on the device. */
+void pvr2_hdw_render_useless(struct pvr2_hdw *);
+
+/* Set / clear 8051's reset bit */
+void pvr2_hdw_cpureset_assert(struct pvr2_hdw *,int);
+
+/* Execute a USB-commanded device reset */
+void pvr2_hdw_device_reset(struct pvr2_hdw *);
+
+/* Reset worker's error trapping circuit breaker */
+int pvr2_hdw_untrip(struct pvr2_hdw *);
+
+/* Execute hard reset command (after this point it's likely that the
+   encoder will have to be reconfigured).  This also clears the "useless"
+   state. */
+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 *);
+
+/* Direct manipulation of GPIO bits */
+int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *);
+int pvr2_hdw_gpio_get_out(struct pvr2_hdw *hdw,u32 *);
+int pvr2_hdw_gpio_get_in(struct pvr2_hdw *hdw,u32 *);
+int pvr2_hdw_gpio_chg_dir(struct pvr2_hdw *hdw,u32 msk,u32 val);
+int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val);
+
+/* This data structure is specifically for the next function... */
+struct pvr2_hdw_debug_info {
+       int big_lock_held;
+       int ctl_lock_held;
+       int flag_disconnected;
+       int flag_init_ok;
+       int flag_ok;
+       int fw1_state;
+       int flag_decoder_missed;
+       int flag_tripped;
+       int state_encoder_ok;
+       int state_encoder_run;
+       int state_decoder_run;
+       int state_decoder_ready;
+       int state_usbstream_run;
+       int state_decoder_quiescent;
+       int state_pipeline_config;
+       int state_pipeline_req;
+       int state_pipeline_pause;
+       int state_pipeline_idle;
+       int cmd_debug_state;
+       int cmd_debug_write_len;
+       int cmd_debug_read_len;
+       int cmd_debug_write_pend;
+       int cmd_debug_read_pend;
+       int cmd_debug_timeout;
+       int cmd_debug_rstatus;
+       int cmd_debug_wstatus;
+       unsigned char cmd_code;
+};
+
+/* Non-intrusively retrieve internal state info - this is useful for
+   diagnosing lockups.  Note that this operation is completed without any
+   kind of locking and so it is not atomic and may yield inconsistent
+   results.  This is *purely* a debugging aid. */
+void pvr2_hdw_get_debug_info_unlocked(const struct pvr2_hdw *hdw,
+                                     struct pvr2_hdw_debug_info *);
+
+/* Intrusively retrieve internal state info - this is useful for
+   diagnosing overall driver state.  This operation synchronizes against
+   the overall driver mutex - so if there are locking problems this will
+   likely hang!  This is *purely* a debugging aid. */
+void pvr2_hdw_get_debug_info_locked(struct pvr2_hdw *hdw,
+                                   struct pvr2_hdw_debug_info *);
+
+/* Report out several lines of text that describes driver internal state.
+   Results are written into the passed-in buffer. */
+unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw,
+                                  char *buf_ptr,unsigned int buf_size);
+
+/* Cause modules to log their state once */
+void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw);
+
+/* Cause encoder firmware to be uploaded into the device.  This is normally
+   done autonomously, but the interface is exported here because it is also
+   a debugging aid. */
+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
new file mode 100644 (file)
index 0000000..885ce11
--- /dev/null
@@ -0,0 +1,698 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <media/ir-kbd-i2c.h>
+#include "pvrusb2-i2c-core.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-fx2-cmd.h"
+#include "pvrusb2.h"
+
+#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
+
+/*
+
+  This module attempts to implement a compliant I2C adapter for the pvrusb2
+  device.
+
+*/
+
+static unsigned int i2c_scan;
+module_param(i2c_scan, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+
+static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 };
+module_param_array(ir_mode, int, NULL, 0444);
+MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR");
+
+static int pvr2_disable_ir_video;
+module_param_named(disable_autoload_ir_video, pvr2_disable_ir_video,
+                  int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(disable_autoload_ir_video,
+                "1=do not try to autoload ir_video IR receiver");
+
+static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */
+                         u8 i2c_addr,      /* I2C address we're talking to */
+                         u8 *data,         /* Data to write */
+                         u16 length)       /* Size of data to write */
+{
+       /* Return value - default 0 means success */
+       int ret;
+
+
+       if (!data) length = 0;
+       if (length > (sizeof(hdw->cmd_buffer) - 3)) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Killing an I2C write to %u that is too large"
+                          " (desired=%u limit=%u)",
+                          i2c_addr,
+                          length,(unsigned int)(sizeof(hdw->cmd_buffer) - 3));
+               return -ENOTSUPP;
+       }
+
+       LOCK_TAKE(hdw->ctl_lock);
+
+       /* Clear the command buffer (likely to be paranoia) */
+       memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer));
+
+       /* Set up command buffer for an I2C write */
+       hdw->cmd_buffer[0] = FX2CMD_I2C_WRITE;      /* write prefix */
+       hdw->cmd_buffer[1] = i2c_addr;  /* i2c addr of chip */
+       hdw->cmd_buffer[2] = length;    /* length of what follows */
+       if (length) memcpy(hdw->cmd_buffer + 3, data, length);
+
+       /* Do the operation */
+       ret = pvr2_send_request(hdw,
+                               hdw->cmd_buffer,
+                               length + 3,
+                               hdw->cmd_buffer,
+                               1);
+       if (!ret) {
+               if (hdw->cmd_buffer[0] != 8) {
+                       ret = -EIO;
+                       if (hdw->cmd_buffer[0] != 7) {
+                               trace_i2c("unexpected status"
+                                         " from i2_write[%d]: %d",
+                                         i2c_addr,hdw->cmd_buffer[0]);
+                       }
+               }
+       }
+
+       LOCK_GIVE(hdw->ctl_lock);
+
+       return ret;
+}
+
+static int pvr2_i2c_read(struct pvr2_hdw *hdw, /* Context */
+                        u8 i2c_addr,       /* I2C address we're talking to */
+                        u8 *data,          /* Data to write */
+                        u16 dlen,          /* Size of data to write */
+                        u8 *res,           /* Where to put data we read */
+                        u16 rlen)          /* Amount of data to read */
+{
+       /* Return value - default 0 means success */
+       int ret;
+
+
+       if (!data) dlen = 0;
+       if (dlen > (sizeof(hdw->cmd_buffer) - 4)) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Killing an I2C read to %u that has wlen too large"
+                          " (desired=%u limit=%u)",
+                          i2c_addr,
+                          dlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 4));
+               return -ENOTSUPP;
+       }
+       if (res && (rlen > (sizeof(hdw->cmd_buffer) - 1))) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Killing an I2C read to %u that has rlen too large"
+                          " (desired=%u limit=%u)",
+                          i2c_addr,
+                          rlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 1));
+               return -ENOTSUPP;
+       }
+
+       LOCK_TAKE(hdw->ctl_lock);
+
+       /* Clear the command buffer (likely to be paranoia) */
+       memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer));
+
+       /* Set up command buffer for an I2C write followed by a read */
+       hdw->cmd_buffer[0] = FX2CMD_I2C_READ;  /* read prefix */
+       hdw->cmd_buffer[1] = dlen;  /* arg length */
+       hdw->cmd_buffer[2] = rlen;  /* answer length. Device will send one
+                                      more byte (status). */
+       hdw->cmd_buffer[3] = i2c_addr;  /* i2c addr of chip */
+       if (dlen) memcpy(hdw->cmd_buffer + 4, data, dlen);
+
+       /* Do the operation */
+       ret = pvr2_send_request(hdw,
+                               hdw->cmd_buffer,
+                               4 + dlen,
+                               hdw->cmd_buffer,
+                               rlen + 1);
+       if (!ret) {
+               if (hdw->cmd_buffer[0] != 8) {
+                       ret = -EIO;
+                       if (hdw->cmd_buffer[0] != 7) {
+                               trace_i2c("unexpected status"
+                                         " from i2_read[%d]: %d",
+                                         i2c_addr,hdw->cmd_buffer[0]);
+                       }
+               }
+       }
+
+       /* Copy back the result */
+       if (res && rlen) {
+               if (ret) {
+                       /* Error, just blank out the return buffer */
+                       memset(res, 0, rlen);
+               } else {
+                       memcpy(res, hdw->cmd_buffer + 1, rlen);
+               }
+       }
+
+       LOCK_GIVE(hdw->ctl_lock);
+
+       return ret;
+}
+
+/* This is the common low level entry point for doing I2C operations to the
+   hardware. */
+static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw,
+                            u8 i2c_addr,
+                            u8 *wdata,
+                            u16 wlen,
+                            u8 *rdata,
+                            u16 rlen)
+{
+       if (!rdata) rlen = 0;
+       if (!wdata) wlen = 0;
+       if (rlen || !wlen) {
+               return pvr2_i2c_read(hdw,i2c_addr,wdata,wlen,rdata,rlen);
+       } else {
+               return pvr2_i2c_write(hdw,i2c_addr,wdata,wlen);
+       }
+}
+
+
+/* This is a special entry point for cases of I2C transaction attempts to
+   the IR receiver.  The implementation here simulates the IR receiver by
+   issuing a command to the FX2 firmware and using that response to return
+   what the real I2C receiver would have returned.  We use this for 24xxx
+   devices, where the IR receiver chip has been removed and replaced with
+   FX2 related logic. */
+static int i2c_24xxx_ir(struct pvr2_hdw *hdw,
+                       u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
+{
+       u8 dat[4];
+       unsigned int stat;
+
+       if (!(rlen || wlen)) {
+               /* This is a probe attempt.  Just let it succeed. */
+               return 0;
+       }
+
+       /* We don't understand this kind of transaction */
+       if ((wlen != 0) || (rlen == 0)) return -EIO;
+
+       if (rlen < 3) {
+               /* Mike Isely <isely@pobox.com> Appears to be a probe
+                  attempt from lirc.  Just fill in zeroes and return.  If
+                  we try instead to do the full transaction here, then bad
+                  things seem to happen within the lirc driver module
+                  (version 0.8.0-7 sources from Debian, when run under
+                  vanilla 2.6.17.6 kernel) - and I don't have the patience
+                  to chase it down. */
+               if (rlen > 0) rdata[0] = 0;
+               if (rlen > 1) rdata[1] = 0;
+               return 0;
+       }
+
+       /* Issue a command to the FX2 to read the IR receiver. */
+       LOCK_TAKE(hdw->ctl_lock); do {
+               hdw->cmd_buffer[0] = FX2CMD_GET_IR_CODE;
+               stat = pvr2_send_request(hdw,
+                                        hdw->cmd_buffer,1,
+                                        hdw->cmd_buffer,4);
+               dat[0] = hdw->cmd_buffer[0];
+               dat[1] = hdw->cmd_buffer[1];
+               dat[2] = hdw->cmd_buffer[2];
+               dat[3] = hdw->cmd_buffer[3];
+       } while (0); LOCK_GIVE(hdw->ctl_lock);
+
+       /* Give up if that operation failed. */
+       if (stat != 0) return stat;
+
+       /* Mangle the results into something that looks like the real IR
+          receiver. */
+       rdata[2] = 0xc1;
+       if (dat[0] != 1) {
+               /* No code received. */
+               rdata[0] = 0;
+               rdata[1] = 0;
+       } else {
+               u16 val;
+               /* Mash the FX2 firmware-provided IR code into something
+                  that the normal i2c chip-level driver expects. */
+               val = dat[1];
+               val <<= 8;
+               val |= dat[2];
+               val >>= 1;
+               val &= ~0x0003;
+               val |= 0x8000;
+               rdata[0] = (val >> 8) & 0xffu;
+               rdata[1] = val & 0xffu;
+       }
+
+       return 0;
+}
+
+/* This is a special entry point that is entered if an I2C operation is
+   attempted to a wm8775 chip on model 24xxx hardware.  Autodetect of this
+   part doesn't work, but we know it is really there.  So let's look for
+   the autodetect attempt and just return success if we see that. */
+static int i2c_hack_wm8775(struct pvr2_hdw *hdw,
+                          u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
+{
+       if (!(rlen || wlen)) {
+               // This is a probe attempt.  Just let it succeed.
+               return 0;
+       }
+       return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen);
+}
+
+/* This is an entry point designed to always fail any attempt to perform a
+   transfer.  We use this to cause certain I2C addresses to not be
+   probed. */
+static int i2c_black_hole(struct pvr2_hdw *hdw,
+                          u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
+{
+       return -EIO;
+}
+
+/* This is a special entry point that is entered if an I2C operation is
+   attempted to a cx25840 chip on model 24xxx hardware.  This chip can
+   sometimes wedge itself.  Worse still, when this happens msp3400 can
+   falsely detect this part and then the system gets hosed up after msp3400
+   gets confused and dies.  What we want to do here is try to keep msp3400
+   away and also try to notice if the chip is wedged and send a warning to
+   the system log. */
+static int i2c_hack_cx25840(struct pvr2_hdw *hdw,
+                           u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
+{
+       int ret;
+       unsigned int subaddr;
+       u8 wbuf[2];
+       int state = hdw->i2c_cx25840_hack_state;
+
+       if (!(rlen || wlen)) {
+               // Probe attempt - always just succeed and don't bother the
+               // hardware (this helps to make the state machine further
+               // down somewhat easier).
+               return 0;
+       }
+
+       if (state == 3) {
+               return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen);
+       }
+
+       /* We're looking for the exact pattern where the revision register
+          is being read.  The cx25840 module will always look at the
+          revision register first.  Any other pattern of access therefore
+          has to be a probe attempt from somebody else so we'll reject it.
+          Normally we could just let each client just probe the part
+          anyway, but when the cx25840 is wedged, msp3400 will get a false
+          positive and that just screws things up... */
+
+       if (wlen == 0) {
+               switch (state) {
+               case 1: subaddr = 0x0100; break;
+               case 2: subaddr = 0x0101; break;
+               default: goto fail;
+               }
+       } else if (wlen == 2) {
+               subaddr = (wdata[0] << 8) | wdata[1];
+               switch (subaddr) {
+               case 0x0100: state = 1; break;
+               case 0x0101: state = 2; break;
+               default: goto fail;
+               }
+       } else {
+               goto fail;
+       }
+       if (!rlen) goto success;
+       state = 0;
+       if (rlen != 1) goto fail;
+
+       /* If we get to here then we have a legitimate read for one of the
+          two revision bytes, so pass it through. */
+       wbuf[0] = subaddr >> 8;
+       wbuf[1] = subaddr;
+       ret = pvr2_i2c_basic_op(hdw,i2c_addr,wbuf,2,rdata,rlen);
+
+       if ((ret != 0) || (*rdata == 0x04) || (*rdata == 0x0a)) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "WARNING: Detected a wedged cx25840 chip;"
+                          " the device will not work.");
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "WARNING: Try power cycling the pvrusb2 device.");
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "WARNING: Disabling further access to the device"
+                          " to prevent other foul-ups.");
+               // This blocks all further communication with the part.
+               hdw->i2c_func[0x44] = NULL;
+               pvr2_hdw_render_useless(hdw);
+               goto fail;
+       }
+
+       /* Success! */
+       pvr2_trace(PVR2_TRACE_CHIPS,"cx25840 appears to be OK.");
+       state = 3;
+
+ success:
+       hdw->i2c_cx25840_hack_state = state;
+       return 0;
+
+ fail:
+       hdw->i2c_cx25840_hack_state = state;
+       return -EIO;
+}
+
+/* This is a very, very limited I2C adapter implementation.  We can only
+   support what we actually know will work on the device... */
+static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
+                        struct i2c_msg msgs[],
+                        int num)
+{
+       int ret = -ENOTSUPP;
+       pvr2_i2c_func funcp = NULL;
+       struct pvr2_hdw *hdw = (struct pvr2_hdw *)(i2c_adap->algo_data);
+
+       if (!num) {
+               ret = -EINVAL;
+               goto done;
+       }
+       if (msgs[0].addr < PVR2_I2C_FUNC_CNT) {
+               funcp = hdw->i2c_func[msgs[0].addr];
+       }
+       if (!funcp) {
+               ret = -EIO;
+               goto done;
+       }
+
+       if (num == 1) {
+               if (msgs[0].flags & I2C_M_RD) {
+                       /* Simple read */
+                       u16 tcnt,bcnt,offs;
+                       if (!msgs[0].len) {
+                               /* Length == 0 read.  This is a probe. */
+                               if (funcp(hdw,msgs[0].addr,NULL,0,NULL,0)) {
+                                       ret = -EIO;
+                                       goto done;
+                               }
+                               ret = 1;
+                               goto done;
+                       }
+                       /* If the read is short enough we'll do the whole
+                          thing atomically.  Otherwise we have no choice
+                          but to break apart the reads. */
+                       tcnt = msgs[0].len;
+                       offs = 0;
+                       while (tcnt) {
+                               bcnt = tcnt;
+                               if (bcnt > sizeof(hdw->cmd_buffer)-1) {
+                                       bcnt = sizeof(hdw->cmd_buffer)-1;
+                               }
+                               if (funcp(hdw,msgs[0].addr,NULL,0,
+                                         msgs[0].buf+offs,bcnt)) {
+                                       ret = -EIO;
+                                       goto done;
+                               }
+                               offs += bcnt;
+                               tcnt -= bcnt;
+                       }
+                       ret = 1;
+                       goto done;
+               } else {
+                       /* Simple write */
+                       ret = 1;
+                       if (funcp(hdw,msgs[0].addr,
+                                 msgs[0].buf,msgs[0].len,NULL,0)) {
+                               ret = -EIO;
+                       }
+                       goto done;
+               }
+       } else if (num == 2) {
+               if (msgs[0].addr != msgs[1].addr) {
+                       trace_i2c("i2c refusing 2 phase transfer with"
+                                 " conflicting target addresses");
+                       ret = -ENOTSUPP;
+                       goto done;
+               }
+               if ((!((msgs[0].flags & I2C_M_RD))) &&
+                   (msgs[1].flags & I2C_M_RD)) {
+                       u16 tcnt,bcnt,wcnt,offs;
+                       /* Write followed by atomic read.  If the read
+                          portion is short enough we'll do the whole thing
+                          atomically.  Otherwise we have no choice but to
+                          break apart the reads. */
+                       tcnt = msgs[1].len;
+                       wcnt = msgs[0].len;
+                       offs = 0;
+                       while (tcnt || wcnt) {
+                               bcnt = tcnt;
+                               if (bcnt > sizeof(hdw->cmd_buffer)-1) {
+                                       bcnt = sizeof(hdw->cmd_buffer)-1;
+                               }
+                               if (funcp(hdw,msgs[0].addr,
+                                         msgs[0].buf,wcnt,
+                                         msgs[1].buf+offs,bcnt)) {
+                                       ret = -EIO;
+                                       goto done;
+                               }
+                               offs += bcnt;
+                               tcnt -= bcnt;
+                               wcnt = 0;
+                       }
+                       ret = 2;
+                       goto done;
+               } else {
+                       trace_i2c("i2c refusing complex transfer"
+                                 " read0=%d read1=%d",
+                                 (msgs[0].flags & I2C_M_RD),
+                                 (msgs[1].flags & I2C_M_RD));
+               }
+       } else {
+               trace_i2c("i2c refusing %d phase transfer",num);
+       }
+
+ done:
+       if (pvrusb2_debug & PVR2_TRACE_I2C_TRAF) {
+               unsigned int idx,offs,cnt;
+               for (idx = 0; idx < num; idx++) {
+                       cnt = msgs[idx].len;
+                       printk(KERN_INFO
+                              "pvrusb2 i2c xfer %u/%u:"
+                              " addr=0x%x len=%d %s",
+                              idx+1,num,
+                              msgs[idx].addr,
+                              cnt,
+                              (msgs[idx].flags & I2C_M_RD ?
+                               "read" : "write"));
+                       if ((ret > 0) || !(msgs[idx].flags & I2C_M_RD)) {
+                               if (cnt > 8) cnt = 8;
+                               printk(" [");
+                               for (offs = 0; offs < (cnt>8?8:cnt); offs++) {
+                                       if (offs) printk(" ");
+                                       printk("%02x",msgs[idx].buf[offs]);
+                               }
+                               if (offs < cnt) printk(" ...");
+                               printk("]");
+                       }
+                       if (idx+1 == num) {
+                               printk(" result=%d",ret);
+                       }
+                       printk("\n");
+               }
+               if (!num) {
+                       printk(KERN_INFO
+                              "pvrusb2 i2c xfer null transfer result=%d\n",
+                              ret);
+               }
+       }
+       return ret;
+}
+
+static u32 pvr2_i2c_functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm pvr2_i2c_algo_template = {
+       .master_xfer   = pvr2_i2c_xfer,
+       .functionality = pvr2_i2c_functionality,
+};
+
+static struct i2c_adapter pvr2_i2c_adap_template = {
+       .owner         = THIS_MODULE,
+       .class         = 0,
+};
+
+
+/* Return true if device exists at given address */
+static int do_i2c_probe(struct pvr2_hdw *hdw, int addr)
+{
+       struct i2c_msg msg[1];
+       int rc;
+       msg[0].addr = 0;
+       msg[0].flags = I2C_M_RD;
+       msg[0].len = 0;
+       msg[0].buf = NULL;
+       msg[0].addr = addr;
+       rc = i2c_transfer(&hdw->i2c_adap, msg, ARRAY_SIZE(msg));
+       return rc == 1;
+}
+
+static void do_i2c_scan(struct pvr2_hdw *hdw)
+{
+       int i;
+       printk(KERN_INFO "%s: i2c scan beginning\n", hdw->name);
+       for (i = 0; i < 128; i++) {
+               if (do_i2c_probe(hdw, i)) {
+                       printk(KERN_INFO "%s: i2c scan: found device @ 0x%x\n",
+                              hdw->name, i);
+               }
+       }
+       printk(KERN_INFO "%s: i2c scan done.\n", hdw->name);
+}
+
+static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
+{
+       struct i2c_board_info info;
+       struct IR_i2c_init_data *init_data = &hdw->ir_init_data;
+       if (pvr2_disable_ir_video) {
+               pvr2_trace(PVR2_TRACE_INFO,
+                          "Automatic binding of ir_video has been disabled.");
+               return;
+       }
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       switch (hdw->ir_scheme_active) {
+       case PVR2_IR_SCHEME_24XXX: /* FX2-controlled IR */
+       case PVR2_IR_SCHEME_29XXX: /* Original 29xxx device */
+               init_data->ir_codes              = RC_MAP_HAUPPAUGE;
+               init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
+               init_data->type                  = RC_TYPE_RC5;
+               init_data->name                  = hdw->hdw_desc->description;
+               init_data->polling_interval      = 100; /* ms From ir-kbd-i2c */
+               /* IR Receiver */
+               info.addr          = 0x18;
+               info.platform_data = init_data;
+               strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
+               pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.",
+                          info.type, info.addr);
+               i2c_new_device(&hdw->i2c_adap, &info);
+               break;
+       case PVR2_IR_SCHEME_ZILOG:     /* HVR-1950 style */
+       case PVR2_IR_SCHEME_24XXX_MCE: /* 24xxx MCE device */
+               init_data->ir_codes              = RC_MAP_HAUPPAUGE;
+               init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
+               init_data->type                  = RC_TYPE_RC5;
+               init_data->name                  = hdw->hdw_desc->description;
+               /* IR Receiver */
+               info.addr          = 0x71;
+               info.platform_data = init_data;
+               strlcpy(info.type, "ir_rx_z8f0811_haup", I2C_NAME_SIZE);
+               pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.",
+                          info.type, info.addr);
+               i2c_new_device(&hdw->i2c_adap, &info);
+               /* IR Trasmitter */
+               info.addr          = 0x70;
+               info.platform_data = init_data;
+               strlcpy(info.type, "ir_tx_z8f0811_haup", I2C_NAME_SIZE);
+               pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.",
+                          info.type, info.addr);
+               i2c_new_device(&hdw->i2c_adap, &info);
+               break;
+       default:
+               /* The device either doesn't support I2C-based IR or we
+                  don't know (yet) how to operate IR on the device. */
+               break;
+       }
+}
+
+void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
+{
+       unsigned int idx;
+
+       /* The default action for all possible I2C addresses is just to do
+          the transfer normally. */
+       for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) {
+               hdw->i2c_func[idx] = pvr2_i2c_basic_op;
+       }
+
+       /* However, deal with various special cases for 24xxx hardware. */
+       if (ir_mode[hdw->unit_number] == 0) {
+               printk(KERN_INFO "%s: IR disabled\n",hdw->name);
+               hdw->i2c_func[0x18] = i2c_black_hole;
+       } else if (ir_mode[hdw->unit_number] == 1) {
+               if (hdw->ir_scheme_active == PVR2_IR_SCHEME_24XXX) {
+                       /* Set up translation so that our IR looks like a
+                          29xxx device */
+                       hdw->i2c_func[0x18] = i2c_24xxx_ir;
+               }
+       }
+       if (hdw->hdw_desc->flag_has_cx25840) {
+               hdw->i2c_func[0x44] = i2c_hack_cx25840;
+       }
+       if (hdw->hdw_desc->flag_has_wm8775) {
+               hdw->i2c_func[0x1b] = i2c_hack_wm8775;
+       }
+
+       // Configure the adapter and set up everything else related to it.
+       memcpy(&hdw->i2c_adap,&pvr2_i2c_adap_template,sizeof(hdw->i2c_adap));
+       memcpy(&hdw->i2c_algo,&pvr2_i2c_algo_template,sizeof(hdw->i2c_algo));
+       strlcpy(hdw->i2c_adap.name,hdw->name,sizeof(hdw->i2c_adap.name));
+       hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev;
+       hdw->i2c_adap.algo = &hdw->i2c_algo;
+       hdw->i2c_adap.algo_data = hdw;
+       hdw->i2c_linked = !0;
+       i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev);
+       i2c_add_adapter(&hdw->i2c_adap);
+       if (hdw->i2c_func[0x18] == i2c_24xxx_ir) {
+               /* Probe for a different type of IR receiver on this
+                  device.  This is really the only way to differentiate
+                  older 24xxx devices from 24xxx variants that include an
+                  IR blaster.  If the IR blaster is present, the IR
+                  receiver is part of that chip and thus we must disable
+                  the emulated IR receiver. */
+               if (do_i2c_probe(hdw, 0x71)) {
+                       pvr2_trace(PVR2_TRACE_INFO,
+                                  "Device has newer IR hardware;"
+                                  " disabling unneeded virtual IR device");
+                       hdw->i2c_func[0x18] = NULL;
+                       /* Remember that this is a different device... */
+                       hdw->ir_scheme_active = PVR2_IR_SCHEME_24XXX_MCE;
+               }
+       }
+       if (i2c_scan) do_i2c_scan(hdw);
+
+       pvr2_i2c_register_ir(hdw);
+}
+
+void pvr2_i2c_core_done(struct pvr2_hdw *hdw)
+{
+       if (hdw->i2c_linked) {
+               i2c_del_adapter(&hdw->i2c_adap);
+               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
new file mode 100644 (file)
index 0000000..6a75769
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_I2C_CORE_H
+#define __PVRUSB2_I2C_CORE_H
+
+struct pvr2_hdw;
+
+void pvr2_i2c_core_init(struct pvr2_hdw *);
+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
new file mode 100644 (file)
index 0000000..20b6ae0
--- /dev/null
@@ -0,0 +1,695 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-io.h"
+#include "pvrusb2-debug.h"
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+
+static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state);
+
+#define BUFFER_SIG 0x47653271
+
+// #define SANITY_CHECK_BUFFERS
+
+
+#ifdef SANITY_CHECK_BUFFERS
+#define BUFFER_CHECK(bp) do { \
+       if ((bp)->signature != BUFFER_SIG) { \
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS, \
+               "Buffer %p is bad at %s:%d", \
+               (bp),__FILE__,__LINE__); \
+               pvr2_buffer_describe(bp,"BadSig"); \
+               BUG(); \
+       } \
+} while (0)
+#else
+#define BUFFER_CHECK(bp) do {} while(0)
+#endif
+
+struct pvr2_stream {
+       /* Buffers queued for reading */
+       struct list_head queued_list;
+       unsigned int q_count;
+       unsigned int q_bcount;
+       /* Buffers with retrieved data */
+       struct list_head ready_list;
+       unsigned int r_count;
+       unsigned int r_bcount;
+       /* Buffers available for use */
+       struct list_head idle_list;
+       unsigned int i_count;
+       unsigned int i_bcount;
+       /* Pointers to all buffers */
+       struct pvr2_buffer **buffers;
+       /* Array size of buffers */
+       unsigned int buffer_slot_count;
+       /* Total buffers actually in circulation */
+       unsigned int buffer_total_count;
+       /* Designed number of buffers to be in circulation */
+       unsigned int buffer_target_count;
+       /* Executed when ready list become non-empty */
+       pvr2_stream_callback callback_func;
+       void *callback_data;
+       /* Context for transfer endpoint */
+       struct usb_device *dev;
+       int endpoint;
+       /* Overhead for mutex enforcement */
+       spinlock_t list_lock;
+       struct mutex mutex;
+       /* Tracking state for tolerating errors */
+       unsigned int fail_count;
+       unsigned int fail_tolerance;
+
+       unsigned int buffers_processed;
+       unsigned int buffers_failed;
+       unsigned int bytes_processed;
+};
+
+struct pvr2_buffer {
+       int id;
+       int signature;
+       enum pvr2_buffer_state state;
+       void *ptr;               /* Pointer to storage area */
+       unsigned int max_count;  /* Size of storage area */
+       unsigned int used_count; /* Amount of valid data in storage area */
+       int status;              /* Transfer result status */
+       struct pvr2_stream *stream;
+       struct list_head list_overhead;
+       struct urb *purb;
+};
+
+static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state st)
+{
+       switch (st) {
+       case pvr2_buffer_state_none: return "none";
+       case pvr2_buffer_state_idle: return "idle";
+       case pvr2_buffer_state_queued: return "queued";
+       case pvr2_buffer_state_ready: return "ready";
+       }
+       return "unknown";
+}
+
+#ifdef SANITY_CHECK_BUFFERS
+static void pvr2_buffer_describe(struct pvr2_buffer *bp,const char *msg)
+{
+       pvr2_trace(PVR2_TRACE_INFO,
+                  "buffer%s%s %p state=%s id=%d status=%d"
+                  " stream=%p purb=%p sig=0x%x",
+                  (msg ? " " : ""),
+                  (msg ? msg : ""),
+                  bp,
+                  (bp ? pvr2_buffer_state_decode(bp->state) : "(invalid)"),
+                  (bp ? bp->id : 0),
+                  (bp ? bp->status : 0),
+                  (bp ? bp->stream : NULL),
+                  (bp ? bp->purb : NULL),
+                  (bp ? bp->signature : 0));
+}
+#endif  /*  SANITY_CHECK_BUFFERS  */
+
+static void pvr2_buffer_remove(struct pvr2_buffer *bp)
+{
+       unsigned int *cnt;
+       unsigned int *bcnt;
+       unsigned int ccnt;
+       struct pvr2_stream *sp = bp->stream;
+       switch (bp->state) {
+       case pvr2_buffer_state_idle:
+               cnt = &sp->i_count;
+               bcnt = &sp->i_bcount;
+               ccnt = bp->max_count;
+               break;
+       case pvr2_buffer_state_queued:
+               cnt = &sp->q_count;
+               bcnt = &sp->q_bcount;
+               ccnt = bp->max_count;
+               break;
+       case pvr2_buffer_state_ready:
+               cnt = &sp->r_count;
+               bcnt = &sp->r_bcount;
+               ccnt = bp->used_count;
+               break;
+       default:
+               return;
+       }
+       list_del_init(&bp->list_overhead);
+       (*cnt)--;
+       (*bcnt) -= ccnt;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/"
+                  " bufferPool     %8s dec cap=%07d cnt=%02d",
+                  pvr2_buffer_state_decode(bp->state),*bcnt,*cnt);
+       bp->state = pvr2_buffer_state_none;
+}
+
+static void pvr2_buffer_set_none(struct pvr2_buffer *bp)
+{
+       unsigned long irq_flags;
+       struct pvr2_stream *sp;
+       BUFFER_CHECK(bp);
+       sp = bp->stream;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
+                  bp,
+                  pvr2_buffer_state_decode(bp->state),
+                  pvr2_buffer_state_decode(pvr2_buffer_state_none));
+       spin_lock_irqsave(&sp->list_lock,irq_flags);
+       pvr2_buffer_remove(bp);
+       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+}
+
+static int pvr2_buffer_set_ready(struct pvr2_buffer *bp)
+{
+       int fl;
+       unsigned long irq_flags;
+       struct pvr2_stream *sp;
+       BUFFER_CHECK(bp);
+       sp = bp->stream;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
+                  bp,
+                  pvr2_buffer_state_decode(bp->state),
+                  pvr2_buffer_state_decode(pvr2_buffer_state_ready));
+       spin_lock_irqsave(&sp->list_lock,irq_flags);
+       fl = (sp->r_count == 0);
+       pvr2_buffer_remove(bp);
+       list_add_tail(&bp->list_overhead,&sp->ready_list);
+       bp->state = pvr2_buffer_state_ready;
+       (sp->r_count)++;
+       sp->r_bcount += bp->used_count;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/"
+                  " bufferPool     %8s inc cap=%07d cnt=%02d",
+                  pvr2_buffer_state_decode(bp->state),
+                  sp->r_bcount,sp->r_count);
+       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+       return fl;
+}
+
+static void pvr2_buffer_set_idle(struct pvr2_buffer *bp)
+{
+       unsigned long irq_flags;
+       struct pvr2_stream *sp;
+       BUFFER_CHECK(bp);
+       sp = bp->stream;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
+                  bp,
+                  pvr2_buffer_state_decode(bp->state),
+                  pvr2_buffer_state_decode(pvr2_buffer_state_idle));
+       spin_lock_irqsave(&sp->list_lock,irq_flags);
+       pvr2_buffer_remove(bp);
+       list_add_tail(&bp->list_overhead,&sp->idle_list);
+       bp->state = pvr2_buffer_state_idle;
+       (sp->i_count)++;
+       sp->i_bcount += bp->max_count;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/"
+                  " bufferPool     %8s inc cap=%07d cnt=%02d",
+                  pvr2_buffer_state_decode(bp->state),
+                  sp->i_bcount,sp->i_count);
+       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+}
+
+static void pvr2_buffer_set_queued(struct pvr2_buffer *bp)
+{
+       unsigned long irq_flags;
+       struct pvr2_stream *sp;
+       BUFFER_CHECK(bp);
+       sp = bp->stream;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
+                  bp,
+                  pvr2_buffer_state_decode(bp->state),
+                  pvr2_buffer_state_decode(pvr2_buffer_state_queued));
+       spin_lock_irqsave(&sp->list_lock,irq_flags);
+       pvr2_buffer_remove(bp);
+       list_add_tail(&bp->list_overhead,&sp->queued_list);
+       bp->state = pvr2_buffer_state_queued;
+       (sp->q_count)++;
+       sp->q_bcount += bp->max_count;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/"
+                  " bufferPool     %8s inc cap=%07d cnt=%02d",
+                  pvr2_buffer_state_decode(bp->state),
+                  sp->q_bcount,sp->q_count);
+       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+}
+
+static void pvr2_buffer_wipe(struct pvr2_buffer *bp)
+{
+       if (bp->state == pvr2_buffer_state_queued) {
+               usb_kill_urb(bp->purb);
+       }
+}
+
+static int pvr2_buffer_init(struct pvr2_buffer *bp,
+                           struct pvr2_stream *sp,
+                           unsigned int id)
+{
+       memset(bp,0,sizeof(*bp));
+       bp->signature = BUFFER_SIG;
+       bp->id = id;
+       pvr2_trace(PVR2_TRACE_BUF_POOL,
+                  "/*---TRACE_FLOW---*/ bufferInit     %p stream=%p",bp,sp);
+       bp->stream = sp;
+       bp->state = pvr2_buffer_state_none;
+       INIT_LIST_HEAD(&bp->list_overhead);
+       bp->purb = usb_alloc_urb(0,GFP_KERNEL);
+       if (! bp->purb) return -ENOMEM;
+#ifdef SANITY_CHECK_BUFFERS
+       pvr2_buffer_describe(bp,"create");
+#endif
+       return 0;
+}
+
+static void pvr2_buffer_done(struct pvr2_buffer *bp)
+{
+#ifdef SANITY_CHECK_BUFFERS
+       pvr2_buffer_describe(bp,"delete");
+#endif
+       pvr2_buffer_wipe(bp);
+       pvr2_buffer_set_none(bp);
+       bp->signature = 0;
+       bp->stream = NULL;
+       usb_free_urb(bp->purb);
+       pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/"
+                  " bufferDone     %p",bp);
+}
+
+static int pvr2_stream_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
+{
+       int ret;
+       unsigned int scnt;
+
+       /* Allocate buffers pointer array in multiples of 32 entries */
+       if (cnt == sp->buffer_total_count) return 0;
+
+       pvr2_trace(PVR2_TRACE_BUF_POOL,
+                  "/*---TRACE_FLOW---*/ poolResize    "
+                  " stream=%p cur=%d adj=%+d",
+                  sp,
+                  sp->buffer_total_count,
+                  cnt-sp->buffer_total_count);
+
+       scnt = cnt & ~0x1f;
+       if (cnt > scnt) scnt += 0x20;
+
+       if (cnt > sp->buffer_total_count) {
+               if (scnt > sp->buffer_slot_count) {
+                       struct pvr2_buffer **nb;
+                       nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL);
+                       if (!nb) return -ENOMEM;
+                       if (sp->buffer_slot_count) {
+                               memcpy(nb,sp->buffers,
+                                      sp->buffer_slot_count * sizeof(*nb));
+                               kfree(sp->buffers);
+                       }
+                       sp->buffers = nb;
+                       sp->buffer_slot_count = scnt;
+               }
+               while (sp->buffer_total_count < cnt) {
+                       struct pvr2_buffer *bp;
+                       bp = kmalloc(sizeof(*bp),GFP_KERNEL);
+                       if (!bp) return -ENOMEM;
+                       ret = pvr2_buffer_init(bp,sp,sp->buffer_total_count);
+                       if (ret) {
+                               kfree(bp);
+                               return -ENOMEM;
+                       }
+                       sp->buffers[sp->buffer_total_count] = bp;
+                       (sp->buffer_total_count)++;
+                       pvr2_buffer_set_idle(bp);
+               }
+       } else {
+               while (sp->buffer_total_count > cnt) {
+                       struct pvr2_buffer *bp;
+                       bp = sp->buffers[sp->buffer_total_count - 1];
+                       /* Paranoia */
+                       sp->buffers[sp->buffer_total_count - 1] = NULL;
+                       (sp->buffer_total_count)--;
+                       pvr2_buffer_done(bp);
+                       kfree(bp);
+               }
+               if (scnt < sp->buffer_slot_count) {
+                       struct pvr2_buffer **nb = NULL;
+                       if (scnt) {
+                               nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL);
+                               if (!nb) return -ENOMEM;
+                               memcpy(nb,sp->buffers,scnt * sizeof(*nb));
+                       }
+                       kfree(sp->buffers);
+                       sp->buffers = nb;
+                       sp->buffer_slot_count = scnt;
+               }
+       }
+       return 0;
+}
+
+static int pvr2_stream_achieve_buffer_count(struct pvr2_stream *sp)
+{
+       struct pvr2_buffer *bp;
+       unsigned int cnt;
+
+       if (sp->buffer_total_count == sp->buffer_target_count) return 0;
+
+       pvr2_trace(PVR2_TRACE_BUF_POOL,
+                  "/*---TRACE_FLOW---*/"
+                  " poolCheck      stream=%p cur=%d tgt=%d",
+                  sp,sp->buffer_total_count,sp->buffer_target_count);
+
+       if (sp->buffer_total_count < sp->buffer_target_count) {
+               return pvr2_stream_buffer_count(sp,sp->buffer_target_count);
+       }
+
+       cnt = 0;
+       while ((sp->buffer_total_count - cnt) > sp->buffer_target_count) {
+               bp = sp->buffers[sp->buffer_total_count - (cnt + 1)];
+               if (bp->state != pvr2_buffer_state_idle) break;
+               cnt++;
+       }
+       if (cnt) {
+               pvr2_stream_buffer_count(sp,sp->buffer_total_count - cnt);
+       }
+
+       return 0;
+}
+
+static void pvr2_stream_internal_flush(struct pvr2_stream *sp)
+{
+       struct list_head *lp;
+       struct pvr2_buffer *bp1;
+       while ((lp = sp->queued_list.next) != &sp->queued_list) {
+               bp1 = list_entry(lp,struct pvr2_buffer,list_overhead);
+               pvr2_buffer_wipe(bp1);
+               /* At this point, we should be guaranteed that no
+                  completion callback may happen on this buffer.  But it's
+                  possible that it might have completed after we noticed
+                  it but before we wiped it.  So double check its status
+                  here first. */
+               if (bp1->state != pvr2_buffer_state_queued) continue;
+               pvr2_buffer_set_idle(bp1);
+       }
+       if (sp->buffer_total_count != sp->buffer_target_count) {
+               pvr2_stream_achieve_buffer_count(sp);
+       }
+}
+
+static void pvr2_stream_init(struct pvr2_stream *sp)
+{
+       spin_lock_init(&sp->list_lock);
+       mutex_init(&sp->mutex);
+       INIT_LIST_HEAD(&sp->queued_list);
+       INIT_LIST_HEAD(&sp->ready_list);
+       INIT_LIST_HEAD(&sp->idle_list);
+}
+
+static void pvr2_stream_done(struct pvr2_stream *sp)
+{
+       mutex_lock(&sp->mutex); do {
+               pvr2_stream_internal_flush(sp);
+               pvr2_stream_buffer_count(sp,0);
+       } while (0); mutex_unlock(&sp->mutex);
+}
+
+static void buffer_complete(struct urb *urb)
+{
+       struct pvr2_buffer *bp = urb->context;
+       struct pvr2_stream *sp;
+       unsigned long irq_flags;
+       BUFFER_CHECK(bp);
+       sp = bp->stream;
+       bp->used_count = 0;
+       bp->status = 0;
+       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                  "/*---TRACE_FLOW---*/ bufferComplete %p stat=%d cnt=%d",
+                  bp,urb->status,urb->actual_length);
+       spin_lock_irqsave(&sp->list_lock,irq_flags);
+       if ((!(urb->status)) ||
+           (urb->status == -ENOENT) ||
+           (urb->status == -ECONNRESET) ||
+           (urb->status == -ESHUTDOWN)) {
+               (sp->buffers_processed)++;
+               sp->bytes_processed += urb->actual_length;
+               bp->used_count = urb->actual_length;
+               if (sp->fail_count) {
+                       pvr2_trace(PVR2_TRACE_TOLERANCE,
+                                  "stream %p transfer ok"
+                                  " - fail count reset",sp);
+                       sp->fail_count = 0;
+               }
+       } else if (sp->fail_count < sp->fail_tolerance) {
+               // We can tolerate this error, because we're below the
+               // threshold...
+               (sp->fail_count)++;
+               (sp->buffers_failed)++;
+               pvr2_trace(PVR2_TRACE_TOLERANCE,
+                          "stream %p ignoring error %d"
+                          " - fail count increased to %u",
+                          sp,urb->status,sp->fail_count);
+       } else {
+               (sp->buffers_failed)++;
+               bp->status = urb->status;
+       }
+       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+       pvr2_buffer_set_ready(bp);
+       if (sp && sp->callback_func) {
+               sp->callback_func(sp->callback_data);
+       }
+}
+
+struct pvr2_stream *pvr2_stream_create(void)
+{
+       struct pvr2_stream *sp;
+       sp = kzalloc(sizeof(*sp),GFP_KERNEL);
+       if (!sp) return sp;
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_create: sp=%p",sp);
+       pvr2_stream_init(sp);
+       return sp;
+}
+
+void pvr2_stream_destroy(struct pvr2_stream *sp)
+{
+       if (!sp) return;
+       pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_destroy: sp=%p",sp);
+       pvr2_stream_done(sp);
+       kfree(sp);
+}
+
+void pvr2_stream_setup(struct pvr2_stream *sp,
+                      struct usb_device *dev,
+                      int endpoint,
+                      unsigned int tolerance)
+{
+       mutex_lock(&sp->mutex); do {
+               pvr2_stream_internal_flush(sp);
+               sp->dev = dev;
+               sp->endpoint = endpoint;
+               sp->fail_tolerance = tolerance;
+       } while(0); mutex_unlock(&sp->mutex);
+}
+
+void pvr2_stream_set_callback(struct pvr2_stream *sp,
+                             pvr2_stream_callback func,
+                             void *data)
+{
+       unsigned long irq_flags;
+       mutex_lock(&sp->mutex); do {
+               spin_lock_irqsave(&sp->list_lock,irq_flags);
+               sp->callback_data = data;
+               sp->callback_func = func;
+               spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+       } while(0); mutex_unlock(&sp->mutex);
+}
+
+void pvr2_stream_get_stats(struct pvr2_stream *sp,
+                          struct pvr2_stream_stats *stats,
+                          int zero_counts)
+{
+       unsigned long irq_flags;
+       spin_lock_irqsave(&sp->list_lock,irq_flags);
+       if (stats) {
+               stats->buffers_in_queue = sp->q_count;
+               stats->buffers_in_idle = sp->i_count;
+               stats->buffers_in_ready = sp->r_count;
+               stats->buffers_processed = sp->buffers_processed;
+               stats->buffers_failed = sp->buffers_failed;
+               stats->bytes_processed = sp->bytes_processed;
+       }
+       if (zero_counts) {
+               sp->buffers_processed = 0;
+               sp->buffers_failed = 0;
+               sp->bytes_processed = 0;
+       }
+       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+}
+
+/* Query / set the nominal buffer count */
+int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
+{
+       return sp->buffer_target_count;
+}
+
+int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
+{
+       int ret;
+       if (sp->buffer_target_count == cnt) return 0;
+       mutex_lock(&sp->mutex); do {
+               sp->buffer_target_count = cnt;
+               ret = pvr2_stream_achieve_buffer_count(sp);
+       } while(0); mutex_unlock(&sp->mutex);
+       return ret;
+}
+
+struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *sp)
+{
+       struct list_head *lp = sp->idle_list.next;
+       if (lp == &sp->idle_list) return NULL;
+       return list_entry(lp,struct pvr2_buffer,list_overhead);
+}
+
+struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *sp)
+{
+       struct list_head *lp = sp->ready_list.next;
+       if (lp == &sp->ready_list) return NULL;
+       return list_entry(lp,struct pvr2_buffer,list_overhead);
+}
+
+struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id)
+{
+       if (id < 0) return NULL;
+       if (id >= sp->buffer_total_count) return NULL;
+       return sp->buffers[id];
+}
+
+int pvr2_stream_get_ready_count(struct pvr2_stream *sp)
+{
+       return sp->r_count;
+}
+
+void pvr2_stream_kill(struct pvr2_stream *sp)
+{
+       struct pvr2_buffer *bp;
+       mutex_lock(&sp->mutex); do {
+               pvr2_stream_internal_flush(sp);
+               while ((bp = pvr2_stream_get_ready_buffer(sp)) != NULL) {
+                       pvr2_buffer_set_idle(bp);
+               }
+               if (sp->buffer_total_count != sp->buffer_target_count) {
+                       pvr2_stream_achieve_buffer_count(sp);
+               }
+       } while(0); mutex_unlock(&sp->mutex);
+}
+
+int pvr2_buffer_queue(struct pvr2_buffer *bp)
+{
+#undef SEED_BUFFER
+#ifdef SEED_BUFFER
+       unsigned int idx;
+       unsigned int val;
+#endif
+       int ret = 0;
+       struct pvr2_stream *sp;
+       if (!bp) return -EINVAL;
+       sp = bp->stream;
+       mutex_lock(&sp->mutex); do {
+               pvr2_buffer_wipe(bp);
+               if (!sp->dev) {
+                       ret = -EIO;
+                       break;
+               }
+               pvr2_buffer_set_queued(bp);
+#ifdef SEED_BUFFER
+               for (idx = 0; idx < (bp->max_count) / 4; idx++) {
+                       val = bp->id << 24;
+                       val |= idx;
+                       ((unsigned int *)(bp->ptr))[idx] = val;
+               }
+#endif
+               bp->status = -EINPROGRESS;
+               usb_fill_bulk_urb(bp->purb,      // struct urb *urb
+                                 sp->dev,       // struct usb_device *dev
+                                 // endpoint (below)
+                                 usb_rcvbulkpipe(sp->dev,sp->endpoint),
+                                 bp->ptr,       // void *transfer_buffer
+                                 bp->max_count, // int buffer_length
+                                 buffer_complete,
+                                 bp);
+               usb_submit_urb(bp->purb,GFP_KERNEL);
+       } while(0); mutex_unlock(&sp->mutex);
+       return ret;
+}
+
+int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt)
+{
+       int ret = 0;
+       unsigned long irq_flags;
+       struct pvr2_stream *sp;
+       if (!bp) return -EINVAL;
+       sp = bp->stream;
+       mutex_lock(&sp->mutex); do {
+               spin_lock_irqsave(&sp->list_lock,irq_flags);
+               if (bp->state != pvr2_buffer_state_idle) {
+                       ret = -EPERM;
+               } else {
+                       bp->ptr = ptr;
+                       bp->stream->i_bcount -= bp->max_count;
+                       bp->max_count = cnt;
+                       bp->stream->i_bcount += bp->max_count;
+                       pvr2_trace(PVR2_TRACE_BUF_FLOW,
+                                  "/*---TRACE_FLOW---*/ bufferPool    "
+                                  " %8s cap cap=%07d cnt=%02d",
+                                  pvr2_buffer_state_decode(
+                                          pvr2_buffer_state_idle),
+                                  bp->stream->i_bcount,bp->stream->i_count);
+               }
+               spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+       } while(0); mutex_unlock(&sp->mutex);
+       return ret;
+}
+
+unsigned int pvr2_buffer_get_count(struct pvr2_buffer *bp)
+{
+       return bp->used_count;
+}
+
+int pvr2_buffer_get_status(struct pvr2_buffer *bp)
+{
+       return bp->status;
+}
+
+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
new file mode 100644 (file)
index 0000000..afb7e87
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_IO_H
+#define __PVRUSB2_IO_H
+
+#include <linux/usb.h>
+#include <linux/list.h>
+
+typedef void (*pvr2_stream_callback)(void *);
+
+enum pvr2_buffer_state {
+       pvr2_buffer_state_none = 0,   // Not on any list
+       pvr2_buffer_state_idle = 1,   // Buffer is ready to be used again
+       pvr2_buffer_state_queued = 2, // Buffer has been queued for filling
+       pvr2_buffer_state_ready = 3,  // Buffer has data available
+};
+
+struct pvr2_stream;
+struct pvr2_buffer;
+
+struct pvr2_stream_stats {
+       unsigned int buffers_in_queue;
+       unsigned int buffers_in_idle;
+       unsigned int buffers_in_ready;
+       unsigned int buffers_processed;
+       unsigned int buffers_failed;
+       unsigned int bytes_processed;
+};
+
+/* Initialize / tear down stream structure */
+struct pvr2_stream *pvr2_stream_create(void);
+void pvr2_stream_destroy(struct pvr2_stream *);
+void pvr2_stream_setup(struct pvr2_stream *,
+                      struct usb_device *dev,int endpoint,
+                      unsigned int tolerance);
+void pvr2_stream_set_callback(struct pvr2_stream *,
+                             pvr2_stream_callback func,
+                             void *data);
+void pvr2_stream_get_stats(struct pvr2_stream *,
+                          struct pvr2_stream_stats *,
+                          int zero_counts);
+
+/* Query / set the nominal buffer count */
+int pvr2_stream_get_buffer_count(struct pvr2_stream *);
+int pvr2_stream_set_buffer_count(struct pvr2_stream *,unsigned int);
+
+/* Get a pointer to a buffer that is either idle, ready, or is specified
+   named. */
+struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *);
+struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *);
+struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id);
+
+/* Find out how many buffers are idle or ready */
+int pvr2_stream_get_ready_count(struct pvr2_stream *);
+
+
+/* Kill all pending buffers and throw away any ready buffers as well */
+void pvr2_stream_kill(struct pvr2_stream *);
+
+/* Set up the actual storage for a buffer */
+int pvr2_buffer_set_buffer(struct pvr2_buffer *,void *ptr,unsigned int cnt);
+
+/* Find out size of data in the given ready buffer */
+unsigned int pvr2_buffer_get_count(struct pvr2_buffer *);
+
+/* Retrieve completion code for given ready buffer */
+int pvr2_buffer_get_status(struct pvr2_buffer *);
+
+/* Retrieve ID of given buffer */
+int pvr2_buffer_get_id(struct pvr2_buffer *);
+
+/* Start reading into given buffer (kill it if needed) */
+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
new file mode 100644 (file)
index 0000000..bba6115
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-ioread.h"
+#include "pvrusb2-debug.h"
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <asm/uaccess.h>
+
+#define BUFFER_COUNT 32
+#define BUFFER_SIZE PAGE_ALIGN(0x4000)
+
+struct pvr2_ioread {
+       struct pvr2_stream *stream;
+       char *buffer_storage[BUFFER_COUNT];
+       char *sync_key_ptr;
+       unsigned int sync_key_len;
+       unsigned int sync_buf_offs;
+       unsigned int sync_state;
+       unsigned int sync_trashed_count;
+       int enabled;         // Streaming is on
+       int spigot_open;     // OK to pass data to client
+       int stream_running;  // Passing data to client now
+
+       /* State relevant to current buffer being read */
+       struct pvr2_buffer *c_buf;
+       char *c_data_ptr;
+       unsigned int c_data_len;
+       unsigned int c_data_offs;
+       struct mutex mutex;
+};
+
+static int pvr2_ioread_init(struct pvr2_ioread *cp)
+{
+       unsigned int idx;
+
+       cp->stream = NULL;
+       mutex_init(&cp->mutex);
+
+       for (idx = 0; idx < BUFFER_COUNT; idx++) {
+               cp->buffer_storage[idx] = kmalloc(BUFFER_SIZE,GFP_KERNEL);
+               if (!(cp->buffer_storage[idx])) break;
+       }
+
+       if (idx < BUFFER_COUNT) {
+               // An allocation appears to have failed
+               for (idx = 0; idx < BUFFER_COUNT; idx++) {
+                       if (!(cp->buffer_storage[idx])) continue;
+                       kfree(cp->buffer_storage[idx]);
+               }
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+static void pvr2_ioread_done(struct pvr2_ioread *cp)
+{
+       unsigned int idx;
+
+       pvr2_ioread_setup(cp,NULL);
+       for (idx = 0; idx < BUFFER_COUNT; idx++) {
+               if (!(cp->buffer_storage[idx])) continue;
+               kfree(cp->buffer_storage[idx]);
+       }
+}
+
+struct pvr2_ioread *pvr2_ioread_create(void)
+{
+       struct pvr2_ioread *cp;
+       cp = kzalloc(sizeof(*cp),GFP_KERNEL);
+       if (!cp) return NULL;
+       pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_create id=%p",cp);
+       if (pvr2_ioread_init(cp) < 0) {
+               kfree(cp);
+               return NULL;
+       }
+       return cp;
+}
+
+void pvr2_ioread_destroy(struct pvr2_ioread *cp)
+{
+       if (!cp) return;
+       pvr2_ioread_done(cp);
+       pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_destroy id=%p",cp);
+       if (cp->sync_key_ptr) {
+               kfree(cp->sync_key_ptr);
+               cp->sync_key_ptr = NULL;
+       }
+       kfree(cp);
+}
+
+void pvr2_ioread_set_sync_key(struct pvr2_ioread *cp,
+                             const char *sync_key_ptr,
+                             unsigned int sync_key_len)
+{
+       if (!cp) return;
+
+       if (!sync_key_ptr) sync_key_len = 0;
+       if ((sync_key_len == cp->sync_key_len) &&
+           ((!sync_key_len) ||
+            (!memcmp(sync_key_ptr,cp->sync_key_ptr,sync_key_len)))) return;
+
+       if (sync_key_len != cp->sync_key_len) {
+               if (cp->sync_key_ptr) {
+                       kfree(cp->sync_key_ptr);
+                       cp->sync_key_ptr = NULL;
+               }
+               cp->sync_key_len = 0;
+               if (sync_key_len) {
+                       cp->sync_key_ptr = kmalloc(sync_key_len,GFP_KERNEL);
+                       if (cp->sync_key_ptr) {
+                               cp->sync_key_len = sync_key_len;
+                       }
+               }
+       }
+       if (!cp->sync_key_len) return;
+       memcpy(cp->sync_key_ptr,sync_key_ptr,cp->sync_key_len);
+}
+
+static void pvr2_ioread_stop(struct pvr2_ioread *cp)
+{
+       if (!(cp->enabled)) return;
+       pvr2_trace(PVR2_TRACE_START_STOP,
+                  "/*---TRACE_READ---*/ pvr2_ioread_stop id=%p",cp);
+       pvr2_stream_kill(cp->stream);
+       cp->c_buf = NULL;
+       cp->c_data_ptr = NULL;
+       cp->c_data_len = 0;
+       cp->c_data_offs = 0;
+       cp->enabled = 0;
+       cp->stream_running = 0;
+       cp->spigot_open = 0;
+       if (cp->sync_state) {
+               pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                          "/*---TRACE_READ---*/ sync_state <== 0");
+               cp->sync_state = 0;
+       }
+}
+
+static int pvr2_ioread_start(struct pvr2_ioread *cp)
+{
+       int stat;
+       struct pvr2_buffer *bp;
+       if (cp->enabled) return 0;
+       if (!(cp->stream)) return 0;
+       pvr2_trace(PVR2_TRACE_START_STOP,
+                  "/*---TRACE_READ---*/ pvr2_ioread_start id=%p",cp);
+       while ((bp = pvr2_stream_get_idle_buffer(cp->stream)) != NULL) {
+               stat = pvr2_buffer_queue(bp);
+               if (stat < 0) {
+                       pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                                  "/*---TRACE_READ---*/"
+                                  " pvr2_ioread_start id=%p"
+                                  " error=%d",
+                                  cp,stat);
+                       pvr2_ioread_stop(cp);
+                       return stat;
+               }
+       }
+       cp->enabled = !0;
+       cp->c_buf = NULL;
+       cp->c_data_ptr = NULL;
+       cp->c_data_len = 0;
+       cp->c_data_offs = 0;
+       cp->stream_running = 0;
+       if (cp->sync_key_len) {
+               pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                          "/*---TRACE_READ---*/ sync_state <== 1");
+               cp->sync_state = 1;
+               cp->sync_trashed_count = 0;
+               cp->sync_buf_offs = 0;
+       }
+       cp->spigot_open = 0;
+       return 0;
+}
+
+struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *cp)
+{
+       return cp->stream;
+}
+
+int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp)
+{
+       int ret;
+       unsigned int idx;
+       struct pvr2_buffer *bp;
+
+       mutex_lock(&cp->mutex); do {
+               if (cp->stream) {
+                       pvr2_trace(PVR2_TRACE_START_STOP,
+                                  "/*---TRACE_READ---*/"
+                                  " pvr2_ioread_setup (tear-down) id=%p",cp);
+                       pvr2_ioread_stop(cp);
+                       pvr2_stream_kill(cp->stream);
+                       if (pvr2_stream_get_buffer_count(cp->stream)) {
+                               pvr2_stream_set_buffer_count(cp->stream,0);
+                       }
+                       cp->stream = NULL;
+               }
+               if (sp) {
+                       pvr2_trace(PVR2_TRACE_START_STOP,
+                                  "/*---TRACE_READ---*/"
+                                  " pvr2_ioread_setup (setup) id=%p",cp);
+                       pvr2_stream_kill(sp);
+                       ret = pvr2_stream_set_buffer_count(sp,BUFFER_COUNT);
+                       if (ret < 0) {
+                               mutex_unlock(&cp->mutex);
+                               return ret;
+                       }
+                       for (idx = 0; idx < BUFFER_COUNT; idx++) {
+                               bp = pvr2_stream_get_buffer(sp,idx);
+                               pvr2_buffer_set_buffer(bp,
+                                                      cp->buffer_storage[idx],
+                                                      BUFFER_SIZE);
+                       }
+                       cp->stream = sp;
+               }
+       } while (0); mutex_unlock(&cp->mutex);
+
+       return 0;
+}
+
+int pvr2_ioread_set_enabled(struct pvr2_ioread *cp,int fl)
+{
+       int ret = 0;
+       if ((!fl) == (!(cp->enabled))) return ret;
+
+       mutex_lock(&cp->mutex); do {
+               if (fl) {
+                       ret = pvr2_ioread_start(cp);
+               } else {
+                       pvr2_ioread_stop(cp);
+               }
+       } while (0); mutex_unlock(&cp->mutex);
+       return ret;
+}
+
+static int pvr2_ioread_get_buffer(struct pvr2_ioread *cp)
+{
+       int stat;
+
+       while (cp->c_data_len <= cp->c_data_offs) {
+               if (cp->c_buf) {
+                       // Flush out current buffer first.
+                       stat = pvr2_buffer_queue(cp->c_buf);
+                       if (stat < 0) {
+                               // Streaming error...
+                               pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                                          "/*---TRACE_READ---*/"
+                                          " pvr2_ioread_read id=%p"
+                                          " queue_error=%d",
+                                          cp,stat);
+                               pvr2_ioread_stop(cp);
+                               return 0;
+                       }
+                       cp->c_buf = NULL;
+                       cp->c_data_ptr = NULL;
+                       cp->c_data_len = 0;
+                       cp->c_data_offs = 0;
+               }
+               // Now get a freshly filled buffer.
+               cp->c_buf = pvr2_stream_get_ready_buffer(cp->stream);
+               if (!cp->c_buf) break; // Nothing ready; done.
+               cp->c_data_len = pvr2_buffer_get_count(cp->c_buf);
+               if (!cp->c_data_len) {
+                       // Nothing transferred.  Was there an error?
+                       stat = pvr2_buffer_get_status(cp->c_buf);
+                       if (stat < 0) {
+                               // Streaming error...
+                               pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                                          "/*---TRACE_READ---*/"
+                                          " pvr2_ioread_read id=%p"
+                                          " buffer_error=%d",
+                                          cp,stat);
+                               pvr2_ioread_stop(cp);
+                               // Give up.
+                               return 0;
+                       }
+                       // Start over...
+                       continue;
+               }
+               cp->c_data_offs = 0;
+               cp->c_data_ptr = cp->buffer_storage[
+                       pvr2_buffer_get_id(cp->c_buf)];
+       }
+       return !0;
+}
+
+static void pvr2_ioread_filter(struct pvr2_ioread *cp)
+{
+       unsigned int idx;
+       if (!cp->enabled) return;
+       if (cp->sync_state != 1) return;
+
+       // Search the stream for our synchronization key.  This is made
+       // complicated by the fact that in order to be honest with
+       // ourselves here we must search across buffer boundaries...
+       mutex_lock(&cp->mutex); while (1) {
+               // Ensure we have a buffer
+               if (!pvr2_ioread_get_buffer(cp)) break;
+               if (!cp->c_data_len) break;
+
+               // Now walk the buffer contents until we match the key or
+               // run out of buffer data.
+               for (idx = cp->c_data_offs; idx < cp->c_data_len; idx++) {
+                       if (cp->sync_buf_offs >= cp->sync_key_len) break;
+                       if (cp->c_data_ptr[idx] ==
+                           cp->sync_key_ptr[cp->sync_buf_offs]) {
+                               // Found the next key byte
+                               (cp->sync_buf_offs)++;
+                       } else {
+                               // Whoops, mismatched.  Start key over...
+                               cp->sync_buf_offs = 0;
+                       }
+               }
+
+               // Consume what we've walked through
+               cp->c_data_offs += idx;
+               cp->sync_trashed_count += idx;
+
+               // If we've found the key, then update state and get out.
+               if (cp->sync_buf_offs >= cp->sync_key_len) {
+                       cp->sync_trashed_count -= cp->sync_key_len;
+                       pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                                  "/*---TRACE_READ---*/"
+                                  " sync_state <== 2 (skipped %u bytes)",
+                                  cp->sync_trashed_count);
+                       cp->sync_state = 2;
+                       cp->sync_buf_offs = 0;
+                       break;
+               }
+
+               if (cp->c_data_offs < cp->c_data_len) {
+                       // Sanity check - should NEVER get here
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "ERROR: pvr2_ioread filter sync problem"
+                                  " len=%u offs=%u",
+                                  cp->c_data_len,cp->c_data_offs);
+                       // Get out so we don't get stuck in an infinite
+                       // loop.
+                       break;
+               }
+
+               continue; // (for clarity)
+       } mutex_unlock(&cp->mutex);
+}
+
+int pvr2_ioread_avail(struct pvr2_ioread *cp)
+{
+       int ret;
+       if (!(cp->enabled)) {
+               // Stream is not enabled; so this is an I/O error
+               return -EIO;
+       }
+
+       if (cp->sync_state == 1) {
+               pvr2_ioread_filter(cp);
+               if (cp->sync_state == 1) return -EAGAIN;
+       }
+
+       ret = 0;
+       if (cp->stream_running) {
+               if (!pvr2_stream_get_ready_count(cp->stream)) {
+                       // No data available at all right now.
+                       ret = -EAGAIN;
+               }
+       } else {
+               if (pvr2_stream_get_ready_count(cp->stream) < BUFFER_COUNT/2) {
+                       // Haven't buffered up enough yet; try again later
+                       ret = -EAGAIN;
+               }
+       }
+
+       if ((!(cp->spigot_open)) != (!(ret == 0))) {
+               cp->spigot_open = (ret == 0);
+               pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                          "/*---TRACE_READ---*/ data is %s",
+                          cp->spigot_open ? "available" : "pending");
+       }
+
+       return ret;
+}
+
+int pvr2_ioread_read(struct pvr2_ioread *cp,void __user *buf,unsigned int cnt)
+{
+       unsigned int copied_cnt;
+       unsigned int bcnt;
+       const char *src;
+       int stat;
+       int ret = 0;
+       unsigned int req_cnt = cnt;
+
+       if (!cnt) {
+               pvr2_trace(PVR2_TRACE_TRAP,
+                          "/*---TRACE_READ---*/ pvr2_ioread_read id=%p"
+                          " ZERO Request? Returning zero.",cp);
+               return 0;
+       }
+
+       stat = pvr2_ioread_avail(cp);
+       if (stat < 0) return stat;
+
+       cp->stream_running = !0;
+
+       mutex_lock(&cp->mutex); do {
+
+               // Suck data out of the buffers and copy to the user
+               copied_cnt = 0;
+               if (!buf) cnt = 0;
+               while (1) {
+                       if (!pvr2_ioread_get_buffer(cp)) {
+                               ret = -EIO;
+                               break;
+                       }
+
+                       if (!cnt) break;
+
+                       if (cp->sync_state == 2) {
+                               // We're repeating the sync key data into
+                               // the stream.
+                               src = cp->sync_key_ptr + cp->sync_buf_offs;
+                               bcnt = cp->sync_key_len - cp->sync_buf_offs;
+                       } else {
+                               // Normal buffer copy
+                               src = cp->c_data_ptr + cp->c_data_offs;
+                               bcnt = cp->c_data_len - cp->c_data_offs;
+                       }
+
+                       if (!bcnt) break;
+
+                       // Don't run past user's buffer
+                       if (bcnt > cnt) bcnt = cnt;
+
+                       if (copy_to_user(buf,src,bcnt)) {
+                               // User supplied a bad pointer?
+                               // Give up - this *will* cause data
+                               // to be lost.
+                               ret = -EFAULT;
+                               break;
+                       }
+                       cnt -= bcnt;
+                       buf += bcnt;
+                       copied_cnt += bcnt;
+
+                       if (cp->sync_state == 2) {
+                               // Update offset inside sync key that we're
+                               // repeating back out.
+                               cp->sync_buf_offs += bcnt;
+                               if (cp->sync_buf_offs >= cp->sync_key_len) {
+                                       // Consumed entire key; switch mode
+                                       // to normal.
+                                       pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                                                  "/*---TRACE_READ---*/"
+                                                  " sync_state <== 0");
+                                       cp->sync_state = 0;
+                               }
+                       } else {
+                               // Update buffer offset.
+                               cp->c_data_offs += bcnt;
+                       }
+               }
+
+       } while (0); mutex_unlock(&cp->mutex);
+
+       if (!ret) {
+               if (copied_cnt) {
+                       // If anything was copied, return that count
+                       ret = copied_cnt;
+               } else {
+                       // Nothing copied; suggest to caller that another
+                       // attempt should be tried again later
+                       ret = -EAGAIN;
+               }
+       }
+
+       pvr2_trace(PVR2_TRACE_DATA_FLOW,
+                  "/*---TRACE_READ---*/ pvr2_ioread_read"
+                  " id=%p request=%d result=%d",
+                  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
new file mode 100644 (file)
index 0000000..100e078
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_IOREAD_H
+#define __PVRUSB2_IOREAD_H
+
+#include "pvrusb2-io.h"
+
+struct pvr2_ioread;
+
+struct pvr2_ioread *pvr2_ioread_create(void);
+void pvr2_ioread_destroy(struct pvr2_ioread *);
+int pvr2_ioread_setup(struct pvr2_ioread *,struct pvr2_stream *);
+struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *);
+void pvr2_ioread_set_sync_key(struct pvr2_ioread *,
+                             const char *sync_key_ptr,
+                             unsigned int sync_key_len);
+int pvr2_ioread_set_enabled(struct pvr2_ioread *,int fl);
+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
new file mode 100644 (file)
index 0000000..c1d9bb6
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-devattr.h"
+#include "pvrusb2-context.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-v4l2.h"
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+#include "pvrusb2-sysfs.h"
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+#define DRIVER_AUTHOR "Mike Isely <isely@pobox.com>"
+#define DRIVER_DESC "Hauppauge WinTV-PVR-USB2 MPEG2 Encoder/Tuner"
+#define DRIVER_VERSION "V4L in-tree version"
+
+#define DEFAULT_DEBUG_MASK (PVR2_TRACE_ERROR_LEGS| \
+                           PVR2_TRACE_INFO| \
+                           PVR2_TRACE_STD| \
+                           PVR2_TRACE_TOLERANCE| \
+                           PVR2_TRACE_TRAP| \
+                           0)
+
+int pvrusb2_debug = DEFAULT_DEBUG_MASK;
+
+module_param_named(debug,pvrusb2_debug,int,S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug trace mask");
+
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+static struct pvr2_sysfs_class *class_ptr = NULL;
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+static void pvr_setup_attach(struct pvr2_context *pvr)
+{
+       /* Create association with v4l layer */
+       pvr2_v4l2_create(pvr);
+#ifdef CONFIG_VIDEO_PVRUSB2_DVB
+       /* Create association with dvb layer */
+       pvr2_dvb_create(pvr);
+#endif
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+       pvr2_sysfs_create(pvr,class_ptr);
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+}
+
+static int pvr_probe(struct usb_interface *intf,
+                    const struct usb_device_id *devid)
+{
+       struct pvr2_context *pvr;
+
+       /* Create underlying hardware interface */
+       pvr = pvr2_context_create(intf,devid,pvr_setup_attach);
+       if (!pvr) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "Failed to create hdw handler");
+               return -ENOMEM;
+       }
+
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_probe(pvr=%p)",pvr);
+
+       usb_set_intfdata(intf, pvr);
+
+       return 0;
+}
+
+/*
+ * pvr_disconnect()
+ *
+ */
+static void pvr_disconnect(struct usb_interface *intf)
+{
+       struct pvr2_context *pvr = usb_get_intfdata(intf);
+
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) BEGIN",pvr);
+
+       usb_set_intfdata (intf, NULL);
+       pvr2_context_disconnect(pvr);
+
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) DONE",pvr);
+
+}
+
+static struct usb_driver pvr_driver = {
+       .name =         "pvrusb2",
+       .id_table =     pvr2_device_table,
+       .probe =        pvr_probe,
+       .disconnect =   pvr_disconnect
+};
+
+/*
+ * pvr_init() / pvr_exit()
+ *
+ * This code is run to initialize/exit the driver.
+ *
+ */
+static int __init pvr_init(void)
+{
+       int ret;
+
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_init");
+
+       ret = pvr2_context_global_init();
+       if (ret != 0) {
+               pvr2_trace(PVR2_TRACE_INIT,"pvr_init failure code=%d",ret);
+               return ret;
+       }
+
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+       class_ptr = pvr2_sysfs_class_create();
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+       ret = usb_register(&pvr_driver);
+
+       if (ret == 0)
+               printk(KERN_INFO "pvrusb2: " DRIVER_VERSION ":"
+                      DRIVER_DESC "\n");
+       if (pvrusb2_debug)
+               printk(KERN_INFO "pvrusb2: Debug mask is %d (0x%x)\n",
+                      pvrusb2_debug,pvrusb2_debug);
+
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete");
+
+       return ret;
+}
+
+static void __exit pvr_exit(void)
+{
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_exit");
+
+       usb_deregister(&pvr_driver);
+
+       pvr2_context_global_done();
+
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+       pvr2_sysfs_class_destroy(class_ptr);
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+       pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete");
+}
+
+module_init(pvr_init);
+module_exit(pvr_exit);
+
+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
new file mode 100644 (file)
index 0000000..453627b
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-std.h"
+#include "pvrusb2-debug.h"
+#include <asm/string.h>
+#include <linux/slab.h>
+
+struct std_name {
+       const char *name;
+       v4l2_std_id id;
+};
+
+
+#define CSTD_PAL \
+       (V4L2_STD_PAL_B| \
+        V4L2_STD_PAL_B1| \
+        V4L2_STD_PAL_G| \
+        V4L2_STD_PAL_H| \
+        V4L2_STD_PAL_I| \
+        V4L2_STD_PAL_D| \
+        V4L2_STD_PAL_D1| \
+        V4L2_STD_PAL_K| \
+        V4L2_STD_PAL_M| \
+        V4L2_STD_PAL_N| \
+        V4L2_STD_PAL_Nc| \
+        V4L2_STD_PAL_60)
+
+#define CSTD_NTSC \
+       (V4L2_STD_NTSC_M| \
+        V4L2_STD_NTSC_M_JP| \
+        V4L2_STD_NTSC_M_KR| \
+        V4L2_STD_NTSC_443)
+
+#define CSTD_ATSC \
+       (V4L2_STD_ATSC_8_VSB| \
+        V4L2_STD_ATSC_16_VSB)
+
+#define CSTD_SECAM \
+       (V4L2_STD_SECAM_B| \
+        V4L2_STD_SECAM_D| \
+        V4L2_STD_SECAM_G| \
+        V4L2_STD_SECAM_H| \
+        V4L2_STD_SECAM_K| \
+        V4L2_STD_SECAM_K1| \
+        V4L2_STD_SECAM_L| \
+        V4L2_STD_SECAM_LC)
+
+#define TSTD_B   (V4L2_STD_PAL_B|V4L2_STD_SECAM_B)
+#define TSTD_B1  (V4L2_STD_PAL_B1)
+#define TSTD_D   (V4L2_STD_PAL_D|V4L2_STD_SECAM_D)
+#define TSTD_D1  (V4L2_STD_PAL_D1)
+#define TSTD_G   (V4L2_STD_PAL_G|V4L2_STD_SECAM_G)
+#define TSTD_H   (V4L2_STD_PAL_H|V4L2_STD_SECAM_H)
+#define TSTD_I   (V4L2_STD_PAL_I)
+#define TSTD_K   (V4L2_STD_PAL_K|V4L2_STD_SECAM_K)
+#define TSTD_K1  (V4L2_STD_SECAM_K1)
+#define TSTD_L   (V4L2_STD_SECAM_L)
+#define TSTD_M   (V4L2_STD_PAL_M|V4L2_STD_NTSC_M)
+#define TSTD_N   (V4L2_STD_PAL_N)
+#define TSTD_Nc  (V4L2_STD_PAL_Nc)
+#define TSTD_60  (V4L2_STD_PAL_60)
+
+#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_ATSC|CSTD_SECAM)
+
+/* Mapping of standard bits to color system */
+static const struct std_name std_groups[] = {
+       {"PAL",CSTD_PAL},
+       {"NTSC",CSTD_NTSC},
+       {"SECAM",CSTD_SECAM},
+       {"ATSC",CSTD_ATSC},
+};
+
+/* Mapping of standard bits to modulation system */
+static const struct std_name std_items[] = {
+       {"B",TSTD_B},
+       {"B1",TSTD_B1},
+       {"D",TSTD_D},
+       {"D1",TSTD_D1},
+       {"G",TSTD_G},
+       {"H",TSTD_H},
+       {"I",TSTD_I},
+       {"K",TSTD_K},
+       {"K1",TSTD_K1},
+       {"L",TSTD_L},
+       {"LC",V4L2_STD_SECAM_LC},
+       {"M",TSTD_M},
+       {"Mj",V4L2_STD_NTSC_M_JP},
+       {"443",V4L2_STD_NTSC_443},
+       {"Mk",V4L2_STD_NTSC_M_KR},
+       {"N",TSTD_N},
+       {"Nc",TSTD_Nc},
+       {"60",TSTD_60},
+       {"8VSB",V4L2_STD_ATSC_8_VSB},
+       {"16VSB",V4L2_STD_ATSC_16_VSB},
+};
+
+
+// Search an array of std_name structures and return a pointer to the
+// element with the matching name.
+static const struct std_name *find_std_name(const struct std_name *arrPtr,
+                                           unsigned int arrSize,
+                                           const char *bufPtr,
+                                           unsigned int bufSize)
+{
+       unsigned int idx;
+       const struct std_name *p;
+       for (idx = 0; idx < arrSize; idx++) {
+               p = arrPtr + idx;
+               if (strlen(p->name) != bufSize) continue;
+               if (!memcmp(bufPtr,p->name,bufSize)) return p;
+       }
+       return NULL;
+}
+
+
+int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
+                      unsigned int bufSize)
+{
+       v4l2_std_id id = 0;
+       v4l2_std_id cmsk = 0;
+       v4l2_std_id t;
+       int mMode = 0;
+       unsigned int cnt;
+       char ch;
+       const struct std_name *sp;
+
+       while (bufSize) {
+               if (!mMode) {
+                       cnt = 0;
+                       while ((cnt < bufSize) && (bufPtr[cnt] != '-')) cnt++;
+                       if (cnt >= bufSize) return 0; // No more characters
+                       sp = find_std_name(std_groups, ARRAY_SIZE(std_groups),
+                                          bufPtr,cnt);
+                       if (!sp) return 0; // Illegal color system name
+                       cnt++;
+                       bufPtr += cnt;
+                       bufSize -= cnt;
+                       mMode = !0;
+                       cmsk = sp->id;
+                       continue;
+               }
+               cnt = 0;
+               while (cnt < bufSize) {
+                       ch = bufPtr[cnt];
+                       if (ch == ';') {
+                               mMode = 0;
+                               break;
+                       }
+                       if (ch == '/') break;
+                       cnt++;
+               }
+               sp = find_std_name(std_items, ARRAY_SIZE(std_items),
+                                  bufPtr,cnt);
+               if (!sp) return 0; // Illegal modulation system ID
+               t = sp->id & cmsk;
+               if (!t) return 0; // Specific color + modulation system illegal
+               id |= t;
+               if (cnt < bufSize) cnt++;
+               bufPtr += cnt;
+               bufSize -= cnt;
+       }
+
+       if (idPtr) *idPtr = id;
+       return !0;
+}
+
+
+unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize,
+                               v4l2_std_id id)
+{
+       unsigned int idx1,idx2;
+       const struct std_name *ip,*gp;
+       int gfl,cfl;
+       unsigned int c1,c2;
+       cfl = 0;
+       c1 = 0;
+       for (idx1 = 0; idx1 < ARRAY_SIZE(std_groups); idx1++) {
+               gp = std_groups + idx1;
+               gfl = 0;
+               for (idx2 = 0; idx2 < ARRAY_SIZE(std_items); idx2++) {
+                       ip = std_items + idx2;
+                       if (!(gp->id & ip->id & id)) continue;
+                       if (!gfl) {
+                               if (cfl) {
+                                       c2 = scnprintf(bufPtr,bufSize,";");
+                                       c1 += c2;
+                                       bufSize -= c2;
+                                       bufPtr += c2;
+                               }
+                               cfl = !0;
+                               c2 = scnprintf(bufPtr,bufSize,
+                                              "%s-",gp->name);
+                               gfl = !0;
+                       } else {
+                               c2 = scnprintf(bufPtr,bufSize,"/");
+                       }
+                       c1 += c2;
+                       bufSize -= c2;
+                       bufPtr += c2;
+                       c2 = scnprintf(bufPtr,bufSize,
+                                      ip->name);
+                       c1 += c2;
+                       bufSize -= c2;
+                       bufPtr += c2;
+               }
+       }
+       return c1;
+}
+
+
+// Template data for possible enumerated video standards.  Here we group
+// standards which share common frame rates and resolution.
+static struct v4l2_standard generic_standards[] = {
+       {
+               .id             = (TSTD_B|TSTD_B1|
+                                  TSTD_D|TSTD_D1|
+                                  TSTD_G|
+                                  TSTD_H|
+                                  TSTD_I|
+                                  TSTD_K|TSTD_K1|
+                                  TSTD_L|
+                                  V4L2_STD_SECAM_LC |
+                                  TSTD_N|TSTD_Nc),
+               .frameperiod    =
+               {
+                       .numerator  = 1,
+                       .denominator= 25
+               },
+               .framelines     = 625,
+               .reserved       = {0,0,0,0}
+       }, {
+               .id             = (TSTD_M|
+                                  V4L2_STD_NTSC_M_JP|
+                                  V4L2_STD_NTSC_M_KR),
+               .frameperiod    =
+               {
+                       .numerator  = 1001,
+                       .denominator= 30000
+               },
+               .framelines     = 525,
+               .reserved       = {0,0,0,0}
+       }, { // This is a total wild guess
+               .id             = (TSTD_60),
+               .frameperiod    =
+               {
+                       .numerator  = 1001,
+                       .denominator= 30000
+               },
+               .framelines     = 525,
+               .reserved       = {0,0,0,0}
+       }, { // This is total wild guess
+               .id             = V4L2_STD_NTSC_443,
+               .frameperiod    =
+               {
+                       .numerator  = 1001,
+                       .denominator= 30000
+               },
+               .framelines     = 525,
+               .reserved       = {0,0,0,0}
+       }
+};
+
+static struct v4l2_standard *match_std(v4l2_std_id id)
+{
+       unsigned int idx;
+       for (idx = 0; idx < ARRAY_SIZE(generic_standards); idx++) {
+               if (generic_standards[idx].id & id) {
+                       return generic_standards + idx;
+               }
+       }
+       return NULL;
+}
+
+static int pvr2_std_fill(struct v4l2_standard *std,v4l2_std_id id)
+{
+       struct v4l2_standard *template;
+       int idx;
+       unsigned int bcnt;
+       template = match_std(id);
+       if (!template) return 0;
+       idx = std->index;
+       memcpy(std,template,sizeof(*template));
+       std->index = idx;
+       std->id = id;
+       bcnt = pvr2_std_id_to_str(std->name,sizeof(std->name)-1,id);
+       std->name[bcnt] = 0;
+       pvr2_trace(PVR2_TRACE_STD,"Set up standard idx=%u name=%s",
+                  std->index,std->name);
+       return !0;
+}
+
+/* These are special cases of combined standards that we should enumerate
+   separately if the component pieces are present. */
+static v4l2_std_id std_mixes[] = {
+       V4L2_STD_PAL_B | V4L2_STD_PAL_G,
+       V4L2_STD_PAL_D | V4L2_STD_PAL_K,
+       V4L2_STD_SECAM_B | V4L2_STD_SECAM_G,
+       V4L2_STD_SECAM_D | V4L2_STD_SECAM_K,
+};
+
+struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
+                                          v4l2_std_id id)
+{
+       unsigned int std_cnt = 0;
+       unsigned int idx,bcnt,idx2;
+       v4l2_std_id idmsk,cmsk,fmsk;
+       struct v4l2_standard *stddefs;
+
+       if (pvrusb2_debug & PVR2_TRACE_STD) {
+               char buf[100];
+               bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id);
+               pvr2_trace(
+                       PVR2_TRACE_STD,"Mapping standards mask=0x%x (%.*s)",
+                       (int)id,bcnt,buf);
+       }
+
+       *countptr = 0;
+       std_cnt = 0;
+       fmsk = 0;
+       for (idmsk = 1, cmsk = id; cmsk; idmsk <<= 1) {
+               if (!(idmsk & cmsk)) continue;
+               cmsk &= ~idmsk;
+               if (match_std(idmsk)) {
+                       std_cnt++;
+                       continue;
+               }
+               fmsk |= idmsk;
+       }
+
+       for (idx2 = 0; idx2 < ARRAY_SIZE(std_mixes); idx2++) {
+               if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++;
+       }
+
+       /* Don't complain about ATSC standard values */
+       fmsk &= ~CSTD_ATSC;
+
+       if (fmsk) {
+               char buf[100];
+               bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk);
+               pvr2_trace(
+                       PVR2_TRACE_ERROR_LEGS,
+                       "WARNING:"
+                       " Failed to classify the following standard(s): %.*s",
+                       bcnt,buf);
+       }
+
+       pvr2_trace(PVR2_TRACE_STD,"Setting up %u unique standard(s)",
+                  std_cnt);
+       if (!std_cnt) return NULL; // paranoia
+
+       stddefs = kzalloc(sizeof(struct v4l2_standard) * std_cnt,
+                         GFP_KERNEL);
+       if (!stddefs)
+               return NULL;
+
+       for (idx = 0; idx < std_cnt; idx++)
+               stddefs[idx].index = idx;
+
+       idx = 0;
+
+       /* Enumerate potential special cases */
+       for (idx2 = 0; (idx2 < ARRAY_SIZE(std_mixes)) && (idx < std_cnt);
+            idx2++) {
+               if (!(id & std_mixes[idx2])) continue;
+               if (pvr2_std_fill(stddefs+idx,std_mixes[idx2])) idx++;
+       }
+       /* Now enumerate individual pieces */
+       for (idmsk = 1, cmsk = id; cmsk && (idx < std_cnt); idmsk <<= 1) {
+               if (!(idmsk & cmsk)) continue;
+               cmsk &= ~idmsk;
+               if (!pvr2_std_fill(stddefs+idx,idmsk)) continue;
+               idx++;
+       }
+
+       *countptr = std_cnt;
+       return stddefs;
+}
+
+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
new file mode 100644 (file)
index 0000000..a35c53d
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_STD_H
+#define __PVRUSB2_STD_H
+
+#include <linux/videodev2.h>
+
+// Convert string describing one or more video standards into a mask of V4L
+// standard bits.  Return true if conversion succeeds otherwise return
+// false.  String is expected to be of the form: C1-x/y;C2-a/b where C1 and
+// C2 are color system names (e.g. "PAL", "NTSC") and x, y, a, and b are
+// modulation schemes (e.g. "M", "B", "G", etc).
+int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
+                      unsigned int bufSize);
+
+// Convert any arbitrary set of video standard bits into an unambiguous
+// readable string.  Return value is the number of bytes consumed in the
+// buffer.  The formatted string is of a form that can be parsed by our
+// sibling std_std_to_id() function.
+unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize,
+                               v4l2_std_id id);
+
+// Create an array of suitable v4l2_standard structures given a bit mask of
+// video standards to support.  The array is allocated from the heap, and
+// the number of elements is returned in the first argument.
+struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
+                                          v4l2_std_id id);
+
+// Return mask of which video standard bits are valid
+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
new file mode 100644 (file)
index 0000000..6ef1335
--- /dev/null
@@ -0,0 +1,861 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include "pvrusb2-sysfs.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-debug.h"
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+#include "pvrusb2-debugifc.h"
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+
+#define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__)
+
+struct pvr2_sysfs {
+       struct pvr2_channel channel;
+       struct device *class_dev;
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+       struct pvr2_sysfs_debugifc *debugifc;
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+       struct pvr2_sysfs_ctl_item *item_first;
+       struct pvr2_sysfs_ctl_item *item_last;
+       struct device_attribute attr_v4l_minor_number;
+       struct device_attribute attr_v4l_radio_minor_number;
+       struct device_attribute attr_unit_number;
+       struct device_attribute attr_bus_info;
+       struct device_attribute attr_hdw_name;
+       struct device_attribute attr_hdw_desc;
+       int v4l_minor_number_created_ok;
+       int v4l_radio_minor_number_created_ok;
+       int unit_number_created_ok;
+       int bus_info_created_ok;
+       int hdw_name_created_ok;
+       int hdw_desc_created_ok;
+};
+
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+struct pvr2_sysfs_debugifc {
+       struct device_attribute attr_debugcmd;
+       struct device_attribute attr_debuginfo;
+       int debugcmd_created_ok;
+       int debuginfo_created_ok;
+};
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+
+struct pvr2_sysfs_ctl_item {
+       struct device_attribute attr_name;
+       struct device_attribute attr_type;
+       struct device_attribute attr_min;
+       struct device_attribute attr_max;
+       struct device_attribute attr_def;
+       struct device_attribute attr_enum;
+       struct device_attribute attr_bits;
+       struct device_attribute attr_val;
+       struct device_attribute attr_custom;
+       struct pvr2_ctrl *cptr;
+       int ctl_id;
+       struct pvr2_sysfs *chptr;
+       struct pvr2_sysfs_ctl_item *item_next;
+       struct attribute *attr_gen[8];
+       struct attribute_group grp;
+       int created_ok;
+       char name[80];
+};
+
+struct pvr2_sysfs_class {
+       struct class class;
+};
+
+static ssize_t show_name(struct device *class_dev,
+                        struct device_attribute *attr,
+                        char *buf)
+{
+       struct pvr2_sysfs_ctl_item *cip;
+       const char *name;
+       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_name);
+       name = pvr2_ctrl_get_desc(cip->cptr);
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",
+                        cip->chptr, cip->ctl_id, name);
+       if (!name) return -EINVAL;
+       return scnprintf(buf, PAGE_SIZE, "%s\n", name);
+}
+
+static ssize_t show_type(struct device *class_dev,
+                        struct device_attribute *attr,
+                        char *buf)
+{
+       struct pvr2_sysfs_ctl_item *cip;
+       const char *name;
+       enum pvr2_ctl_type tp;
+       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_type);
+       tp = pvr2_ctrl_get_type(cip->cptr);
+       switch (tp) {
+       case pvr2_ctl_int: name = "integer"; break;
+       case pvr2_ctl_enum: name = "enum"; break;
+       case pvr2_ctl_bitmask: name = "bitmask"; break;
+       case pvr2_ctl_bool: name = "boolean"; break;
+       default: name = "?"; break;
+       }
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",
+                        cip->chptr, cip->ctl_id, name);
+       if (!name) return -EINVAL;
+       return scnprintf(buf, PAGE_SIZE, "%s\n", name);
+}
+
+static ssize_t show_min(struct device *class_dev,
+                       struct device_attribute *attr,
+                       char *buf)
+{
+       struct pvr2_sysfs_ctl_item *cip;
+       long val;
+       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_min);
+       val = pvr2_ctrl_get_min(cip->cptr);
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",
+                        cip->chptr, cip->ctl_id, val);
+       return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
+}
+
+static ssize_t show_max(struct device *class_dev,
+                       struct device_attribute *attr,
+                       char *buf)
+{
+       struct pvr2_sysfs_ctl_item *cip;
+       long val;
+       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_max);
+       val = pvr2_ctrl_get_max(cip->cptr);
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",
+                        cip->chptr, cip->ctl_id, val);
+       return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
+}
+
+static ssize_t show_def(struct device *class_dev,
+                       struct device_attribute *attr,
+                       char *buf)
+{
+       struct pvr2_sysfs_ctl_item *cip;
+       int val;
+       int ret;
+       unsigned int cnt = 0;
+       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_def);
+       ret = pvr2_ctrl_get_def(cip->cptr, &val);
+       if (ret < 0) return ret;
+       ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
+                                    buf, PAGE_SIZE - 1, &cnt);
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %.*s (%d)",
+                        cip->chptr, cip->ctl_id, cnt, buf, val);
+       buf[cnt] = '\n';
+       return cnt + 1;
+}
+
+static ssize_t show_val_norm(struct device *class_dev,
+                            struct device_attribute *attr,
+                            char *buf)
+{
+       struct pvr2_sysfs_ctl_item *cip;
+       int val;
+       int ret;
+       unsigned int cnt = 0;
+       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
+       ret = pvr2_ctrl_get_value(cip->cptr, &val);
+       if (ret < 0) return ret;
+       ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
+                                    buf, PAGE_SIZE - 1, &cnt);
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
+                        cip->chptr, cip->ctl_id, cnt, buf, val);
+       buf[cnt] = '\n';
+       return cnt+1;
+}
+
+static ssize_t show_val_custom(struct device *class_dev,
+                              struct device_attribute *attr,
+                              char *buf)
+{
+       struct pvr2_sysfs_ctl_item *cip;
+       int val;
+       int ret;
+       unsigned int cnt = 0;
+       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
+       ret = pvr2_ctrl_get_value(cip->cptr, &val);
+       if (ret < 0) return ret;
+       ret = pvr2_ctrl_custom_value_to_sym(cip->cptr, ~0, val,
+                                           buf, PAGE_SIZE - 1, &cnt);
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
+                        cip->chptr, cip->ctl_id, cnt, buf, val);
+       buf[cnt] = '\n';
+       return cnt+1;
+}
+
+static ssize_t show_enum(struct device *class_dev,
+                        struct device_attribute *attr,
+                        char *buf)
+{
+       struct pvr2_sysfs_ctl_item *cip;
+       long val;
+       unsigned int bcnt, ccnt, ecnt;
+       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_enum);
+       ecnt = pvr2_ctrl_get_cnt(cip->cptr);
+       bcnt = 0;
+       for (val = 0; val < ecnt; val++) {
+               pvr2_ctrl_get_valname(cip->cptr, val, buf + bcnt,
+                                     PAGE_SIZE - bcnt, &ccnt);
+               if (!ccnt) continue;
+               bcnt += ccnt;
+               if (bcnt >= PAGE_SIZE) break;
+               buf[bcnt] = '\n';
+               bcnt++;
+       }
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",
+                        cip->chptr, cip->ctl_id);
+       return bcnt;
+}
+
+static ssize_t show_bits(struct device *class_dev,
+                        struct device_attribute *attr,
+                        char *buf)
+{
+       struct pvr2_sysfs_ctl_item *cip;
+       int valid_bits, msk;
+       unsigned int bcnt, ccnt;
+       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_bits);
+       valid_bits = pvr2_ctrl_get_mask(cip->cptr);
+       bcnt = 0;
+       for (msk = 1; valid_bits; msk <<= 1) {
+               if (!(msk & valid_bits)) continue;
+               valid_bits &= ~msk;
+               pvr2_ctrl_get_valname(cip->cptr, msk, buf + bcnt,
+                                     PAGE_SIZE - bcnt, &ccnt);
+               bcnt += ccnt;
+               if (bcnt >= PAGE_SIZE) break;
+               buf[bcnt] = '\n';
+               bcnt++;
+       }
+       pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",
+                        cip->chptr, cip->ctl_id);
+       return bcnt;
+}
+
+static int store_val_any(struct pvr2_sysfs_ctl_item *cip, int customfl,
+                        const char *buf,unsigned int count)
+{
+       int ret;
+       int mask,val;
+       if (customfl) {
+               ret = pvr2_ctrl_custom_sym_to_value(cip->cptr, buf, count,
+                                                   &mask, &val);
+       } else {
+               ret = pvr2_ctrl_sym_to_value(cip->cptr, buf, count,
+                                            &mask, &val);
+       }
+       if (ret < 0) return ret;
+       ret = pvr2_ctrl_set_mask_value(cip->cptr, mask, val);
+       pvr2_hdw_commit_ctl(cip->chptr->channel.hdw);
+       return ret;
+}
+
+static ssize_t store_val_norm(struct device *class_dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct pvr2_sysfs_ctl_item *cip;
+       int ret;
+       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
+       pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"",
+                        cip->chptr, cip->ctl_id, (int)count, buf);
+       ret = store_val_any(cip, 0, buf, count);
+       if (!ret) ret = count;
+       return ret;
+}
+
+static ssize_t store_val_custom(struct device *class_dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct pvr2_sysfs_ctl_item *cip;
+       int ret;
+       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
+       pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"",
+                        cip->chptr, cip->ctl_id, (int)count, buf);
+       ret = store_val_any(cip, 1, buf, count);
+       if (!ret) ret = count;
+       return ret;
+}
+
+static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
+{
+       struct pvr2_sysfs_ctl_item *cip;
+       struct pvr2_ctrl *cptr;
+       unsigned int cnt,acnt;
+       int ret;
+
+       cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id);
+       if (!cptr) return;
+
+       cip = kzalloc(sizeof(*cip),GFP_KERNEL);
+       if (!cip) return;
+       pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip);
+
+       cip->cptr = cptr;
+       cip->ctl_id = ctl_id;
+
+       cip->chptr = sfp;
+       cip->item_next = NULL;
+       if (sfp->item_last) {
+               sfp->item_last->item_next = cip;
+       } else {
+               sfp->item_first = cip;
+       }
+       sfp->item_last = cip;
+
+       sysfs_attr_init(&cip->attr_name.attr);
+       cip->attr_name.attr.name = "name";
+       cip->attr_name.attr.mode = S_IRUGO;
+       cip->attr_name.show = show_name;
+
+       sysfs_attr_init(&cip->attr_type.attr);
+       cip->attr_type.attr.name = "type";
+       cip->attr_type.attr.mode = S_IRUGO;
+       cip->attr_type.show = show_type;
+
+       sysfs_attr_init(&cip->attr_min.attr);
+       cip->attr_min.attr.name = "min_val";
+       cip->attr_min.attr.mode = S_IRUGO;
+       cip->attr_min.show = show_min;
+
+       sysfs_attr_init(&cip->attr_max.attr);
+       cip->attr_max.attr.name = "max_val";
+       cip->attr_max.attr.mode = S_IRUGO;
+       cip->attr_max.show = show_max;
+
+       sysfs_attr_init(&cip->attr_def.attr);
+       cip->attr_def.attr.name = "def_val";
+       cip->attr_def.attr.mode = S_IRUGO;
+       cip->attr_def.show = show_def;
+
+       sysfs_attr_init(&cip->attr_val.attr);
+       cip->attr_val.attr.name = "cur_val";
+       cip->attr_val.attr.mode = S_IRUGO;
+
+       sysfs_attr_init(&cip->attr_custom.attr);
+       cip->attr_custom.attr.name = "custom_val";
+       cip->attr_custom.attr.mode = S_IRUGO;
+
+       sysfs_attr_init(&cip->attr_enum.attr);
+       cip->attr_enum.attr.name = "enum_val";
+       cip->attr_enum.attr.mode = S_IRUGO;
+       cip->attr_enum.show = show_enum;
+
+       sysfs_attr_init(&cip->attr_bits.attr);
+       cip->attr_bits.attr.name = "bit_val";
+       cip->attr_bits.attr.mode = S_IRUGO;
+       cip->attr_bits.show = show_bits;
+
+       if (pvr2_ctrl_is_writable(cptr)) {
+               cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP;
+               cip->attr_custom.attr.mode |= S_IWUSR|S_IWGRP;
+       }
+
+       acnt = 0;
+       cip->attr_gen[acnt++] = &cip->attr_name.attr;
+       cip->attr_gen[acnt++] = &cip->attr_type.attr;
+       cip->attr_gen[acnt++] = &cip->attr_val.attr;
+       cip->attr_gen[acnt++] = &cip->attr_def.attr;
+       cip->attr_val.show = show_val_norm;
+       cip->attr_val.store = store_val_norm;
+       if (pvr2_ctrl_has_custom_symbols(cptr)) {
+               cip->attr_gen[acnt++] = &cip->attr_custom.attr;
+               cip->attr_custom.show = show_val_custom;
+               cip->attr_custom.store = store_val_custom;
+       }
+       switch (pvr2_ctrl_get_type(cptr)) {
+       case pvr2_ctl_enum:
+               // Control is an enumeration
+               cip->attr_gen[acnt++] = &cip->attr_enum.attr;
+               break;
+       case pvr2_ctl_int:
+               // Control is an integer
+               cip->attr_gen[acnt++] = &cip->attr_min.attr;
+               cip->attr_gen[acnt++] = &cip->attr_max.attr;
+               break;
+       case pvr2_ctl_bitmask:
+               // Control is an bitmask
+               cip->attr_gen[acnt++] = &cip->attr_bits.attr;
+               break;
+       default: break;
+       }
+
+       cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s",
+                       pvr2_ctrl_get_name(cptr));
+       cip->name[cnt] = 0;
+       cip->grp.name = cip->name;
+       cip->grp.attrs = cip->attr_gen;
+
+       ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "sysfs_create_group error: %d",
+                          ret);
+               return;
+       }
+       cip->created_ok = !0;
+}
+
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+static ssize_t debuginfo_show(struct device *, struct device_attribute *,
+                             char *);
+static ssize_t debugcmd_show(struct device *, struct device_attribute *,
+                            char *);
+static ssize_t debugcmd_store(struct device *, struct device_attribute *,
+                             const char *, size_t count);
+
+static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
+{
+       struct pvr2_sysfs_debugifc *dip;
+       int ret;
+
+       dip = kzalloc(sizeof(*dip),GFP_KERNEL);
+       if (!dip) return;
+       sysfs_attr_init(&dip->attr_debugcmd.attr);
+       dip->attr_debugcmd.attr.name = "debugcmd";
+       dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP;
+       dip->attr_debugcmd.show = debugcmd_show;
+       dip->attr_debugcmd.store = debugcmd_store;
+       sysfs_attr_init(&dip->attr_debuginfo.attr);
+       dip->attr_debuginfo.attr.name = "debuginfo";
+       dip->attr_debuginfo.attr.mode = S_IRUGO;
+       dip->attr_debuginfo.show = debuginfo_show;
+       sfp->debugifc = dip;
+       ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd);
+       if (ret < 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
+       } else {
+               dip->debugcmd_created_ok = !0;
+       }
+       ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo);
+       if (ret < 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
+       } else {
+               dip->debuginfo_created_ok = !0;
+       }
+}
+
+
+static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
+{
+       if (!sfp->debugifc) return;
+       if (sfp->debugifc->debuginfo_created_ok) {
+               device_remove_file(sfp->class_dev,
+                                        &sfp->debugifc->attr_debuginfo);
+       }
+       if (sfp->debugifc->debugcmd_created_ok) {
+               device_remove_file(sfp->class_dev,
+                                        &sfp->debugifc->attr_debugcmd);
+       }
+       kfree(sfp->debugifc);
+       sfp->debugifc = NULL;
+}
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+
+
+static void pvr2_sysfs_add_controls(struct pvr2_sysfs *sfp)
+{
+       unsigned int idx,cnt;
+       cnt = pvr2_hdw_get_ctrl_count(sfp->channel.hdw);
+       for (idx = 0; idx < cnt; idx++) {
+               pvr2_sysfs_add_control(sfp,idx);
+       }
+}
+
+
+static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp)
+{
+       struct pvr2_sysfs_ctl_item *cip1,*cip2;
+       for (cip1 = sfp->item_first; cip1; cip1 = cip2) {
+               cip2 = cip1->item_next;
+               if (cip1->created_ok) {
+                       sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
+               }
+               pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1);
+               kfree(cip1);
+       }
+}
+
+
+static void pvr2_sysfs_class_release(struct class *class)
+{
+       struct pvr2_sysfs_class *clp;
+       clp = container_of(class,struct pvr2_sysfs_class,class);
+       pvr2_sysfs_trace("Destroying pvr2_sysfs_class id=%p",clp);
+       kfree(clp);
+}
+
+
+static void pvr2_sysfs_release(struct device *class_dev)
+{
+       pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev);
+       kfree(class_dev);
+}
+
+
+static void class_dev_destroy(struct pvr2_sysfs *sfp)
+{
+       struct device *dev;
+       if (!sfp->class_dev) return;
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+       pvr2_sysfs_tear_down_debugifc(sfp);
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+       pvr2_sysfs_tear_down_controls(sfp);
+       if (sfp->hdw_desc_created_ok) {
+               device_remove_file(sfp->class_dev,
+                                  &sfp->attr_hdw_desc);
+       }
+       if (sfp->hdw_name_created_ok) {
+               device_remove_file(sfp->class_dev,
+                                  &sfp->attr_hdw_name);
+       }
+       if (sfp->bus_info_created_ok) {
+               device_remove_file(sfp->class_dev,
+                                        &sfp->attr_bus_info);
+       }
+       if (sfp->v4l_minor_number_created_ok) {
+               device_remove_file(sfp->class_dev,
+                                        &sfp->attr_v4l_minor_number);
+       }
+       if (sfp->v4l_radio_minor_number_created_ok) {
+               device_remove_file(sfp->class_dev,
+                                        &sfp->attr_v4l_radio_minor_number);
+       }
+       if (sfp->unit_number_created_ok) {
+               device_remove_file(sfp->class_dev,
+                                        &sfp->attr_unit_number);
+       }
+       pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
+       dev_set_drvdata(sfp->class_dev, NULL);
+       dev = sfp->class_dev->parent;
+       sfp->class_dev->parent = NULL;
+       put_device(dev);
+       device_unregister(sfp->class_dev);
+       sfp->class_dev = NULL;
+}
+
+
+static ssize_t v4l_minor_number_show(struct device *class_dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = dev_get_drvdata(class_dev);
+       if (!sfp) return -EINVAL;
+       return scnprintf(buf,PAGE_SIZE,"%d\n",
+                        pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
+                                                      pvr2_v4l_type_video));
+}
+
+
+static ssize_t bus_info_show(struct device *class_dev,
+                            struct device_attribute *attr, char *buf)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = dev_get_drvdata(class_dev);
+       if (!sfp) return -EINVAL;
+       return scnprintf(buf,PAGE_SIZE,"%s\n",
+                        pvr2_hdw_get_bus_info(sfp->channel.hdw));
+}
+
+
+static ssize_t hdw_name_show(struct device *class_dev,
+                            struct device_attribute *attr, char *buf)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = dev_get_drvdata(class_dev);
+       if (!sfp) return -EINVAL;
+       return scnprintf(buf,PAGE_SIZE,"%s\n",
+                        pvr2_hdw_get_type(sfp->channel.hdw));
+}
+
+
+static ssize_t hdw_desc_show(struct device *class_dev,
+                            struct device_attribute *attr, char *buf)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = dev_get_drvdata(class_dev);
+       if (!sfp) return -EINVAL;
+       return scnprintf(buf,PAGE_SIZE,"%s\n",
+                        pvr2_hdw_get_desc(sfp->channel.hdw));
+}
+
+
+static ssize_t v4l_radio_minor_number_show(struct device *class_dev,
+                                          struct device_attribute *attr,
+                                          char *buf)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = dev_get_drvdata(class_dev);
+       if (!sfp) return -EINVAL;
+       return scnprintf(buf,PAGE_SIZE,"%d\n",
+                        pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
+                                                      pvr2_v4l_type_radio));
+}
+
+
+static ssize_t unit_number_show(struct device *class_dev,
+                               struct device_attribute *attr, char *buf)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = dev_get_drvdata(class_dev);
+       if (!sfp) return -EINVAL;
+       return scnprintf(buf,PAGE_SIZE,"%d\n",
+                        pvr2_hdw_get_unit_number(sfp->channel.hdw));
+}
+
+
+static void class_dev_create(struct pvr2_sysfs *sfp,
+                            struct pvr2_sysfs_class *class_ptr)
+{
+       struct usb_device *usb_dev;
+       struct device *class_dev;
+       int ret;
+
+       usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
+       if (!usb_dev) return;
+       class_dev = kzalloc(sizeof(*class_dev),GFP_KERNEL);
+       if (!class_dev) return;
+
+       pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
+
+       class_dev->class = &class_ptr->class;
+
+       dev_set_name(class_dev, "%s",
+                    pvr2_hdw_get_device_identifier(sfp->channel.hdw));
+
+       class_dev->parent = get_device(&usb_dev->dev);
+
+       sfp->class_dev = class_dev;
+       dev_set_drvdata(class_dev, sfp);
+       ret = device_register(class_dev);
+       if (ret) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_register failed");
+               put_device(class_dev);
+               return;
+       }
+
+       sysfs_attr_init(&sfp->attr_v4l_minor_number.attr);
+       sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
+       sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
+       sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
+       sfp->attr_v4l_minor_number.store = NULL;
+       ret = device_create_file(sfp->class_dev,
+                                      &sfp->attr_v4l_minor_number);
+       if (ret < 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
+       } else {
+               sfp->v4l_minor_number_created_ok = !0;
+       }
+
+       sysfs_attr_init(&sfp->attr_v4l_radio_minor_number.attr);
+       sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number";
+       sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO;
+       sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show;
+       sfp->attr_v4l_radio_minor_number.store = NULL;
+       ret = device_create_file(sfp->class_dev,
+                                      &sfp->attr_v4l_radio_minor_number);
+       if (ret < 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
+       } else {
+               sfp->v4l_radio_minor_number_created_ok = !0;
+       }
+
+       sysfs_attr_init(&sfp->attr_unit_number.attr);
+       sfp->attr_unit_number.attr.name = "unit_number";
+       sfp->attr_unit_number.attr.mode = S_IRUGO;
+       sfp->attr_unit_number.show = unit_number_show;
+       sfp->attr_unit_number.store = NULL;
+       ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number);
+       if (ret < 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
+       } else {
+               sfp->unit_number_created_ok = !0;
+       }
+
+       sysfs_attr_init(&sfp->attr_bus_info.attr);
+       sfp->attr_bus_info.attr.name = "bus_info_str";
+       sfp->attr_bus_info.attr.mode = S_IRUGO;
+       sfp->attr_bus_info.show = bus_info_show;
+       sfp->attr_bus_info.store = NULL;
+       ret = device_create_file(sfp->class_dev,
+                                      &sfp->attr_bus_info);
+       if (ret < 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
+       } else {
+               sfp->bus_info_created_ok = !0;
+       }
+
+       sysfs_attr_init(&sfp->attr_hdw_name.attr);
+       sfp->attr_hdw_name.attr.name = "device_hardware_type";
+       sfp->attr_hdw_name.attr.mode = S_IRUGO;
+       sfp->attr_hdw_name.show = hdw_name_show;
+       sfp->attr_hdw_name.store = NULL;
+       ret = device_create_file(sfp->class_dev,
+                                &sfp->attr_hdw_name);
+       if (ret < 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
+       } else {
+               sfp->hdw_name_created_ok = !0;
+       }
+
+       sysfs_attr_init(&sfp->attr_hdw_desc.attr);
+       sfp->attr_hdw_desc.attr.name = "device_hardware_description";
+       sfp->attr_hdw_desc.attr.mode = S_IRUGO;
+       sfp->attr_hdw_desc.show = hdw_desc_show;
+       sfp->attr_hdw_desc.store = NULL;
+       ret = device_create_file(sfp->class_dev,
+                                &sfp->attr_hdw_desc);
+       if (ret < 0) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "device_create_file error: %d",
+                          ret);
+       } else {
+               sfp->hdw_desc_created_ok = !0;
+       }
+
+       pvr2_sysfs_add_controls(sfp);
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+       pvr2_sysfs_add_debugifc(sfp);
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+}
+
+
+static void pvr2_sysfs_internal_check(struct pvr2_channel *chp)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = container_of(chp,struct pvr2_sysfs,channel);
+       if (!sfp->channel.mc_head->disconnect_flag) return;
+       pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_sysfs id=%p",sfp);
+       class_dev_destroy(sfp);
+       pvr2_channel_done(&sfp->channel);
+       kfree(sfp);
+}
+
+
+struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp,
+                                    struct pvr2_sysfs_class *class_ptr)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = kzalloc(sizeof(*sfp),GFP_KERNEL);
+       if (!sfp) return sfp;
+       pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp);
+       pvr2_channel_init(&sfp->channel,mp);
+       sfp->channel.check_func = pvr2_sysfs_internal_check;
+
+       class_dev_create(sfp,class_ptr);
+       return sfp;
+}
+
+
+
+struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
+{
+       struct pvr2_sysfs_class *clp;
+       clp = kzalloc(sizeof(*clp),GFP_KERNEL);
+       if (!clp) return clp;
+       pvr2_sysfs_trace("Creating and registering pvr2_sysfs_class id=%p",
+                        clp);
+       clp->class.name = "pvrusb2";
+       clp->class.class_release = pvr2_sysfs_class_release;
+       clp->class.dev_release = pvr2_sysfs_release;
+       if (class_register(&clp->class)) {
+               pvr2_sysfs_trace(
+                       "Registration failed for pvr2_sysfs_class id=%p",clp);
+               kfree(clp);
+               clp = NULL;
+       }
+       return clp;
+}
+
+
+void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp)
+{
+       pvr2_sysfs_trace("Unregistering pvr2_sysfs_class id=%p", clp);
+       class_unregister(&clp->class);
+}
+
+
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+static ssize_t debuginfo_show(struct device *class_dev,
+                             struct device_attribute *attr, char *buf)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = dev_get_drvdata(class_dev);
+       if (!sfp) return -EINVAL;
+       pvr2_hdw_trigger_module_log(sfp->channel.hdw);
+       return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE);
+}
+
+
+static ssize_t debugcmd_show(struct device *class_dev,
+                            struct device_attribute *attr, char *buf)
+{
+       struct pvr2_sysfs *sfp;
+       sfp = dev_get_drvdata(class_dev);
+       if (!sfp) return -EINVAL;
+       return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE);
+}
+
+
+static ssize_t debugcmd_store(struct device *class_dev,
+                             struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct pvr2_sysfs *sfp;
+       int ret;
+
+       sfp = dev_get_drvdata(class_dev);
+       if (!sfp) return -EINVAL;
+
+       ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count);
+       if (ret < 0) return ret;
+       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
new file mode 100644 (file)
index 0000000..6d875bf
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_SYSFS_H
+#define __PVRUSB2_SYSFS_H
+
+#include <linux/list.h>
+#include <linux/sysfs.h>
+#include "pvrusb2-context.h"
+
+struct pvr2_sysfs;
+struct pvr2_sysfs_class;
+
+struct pvr2_sysfs_class *pvr2_sysfs_class_create(void);
+void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *);
+
+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
new file mode 100644 (file)
index 0000000..92b7554
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_UTIL_H
+#define __PVRUSB2_UTIL_H
+
+#define PVR2_DECOMPOSE_LE(t,i,d) \
+    do {    \
+       (t)[i] = (d) & 0xff;\
+       (t)[i+1] = ((d) >> 8) & 0xff;\
+       (t)[i+2] = ((d) >> 16) & 0xff;\
+       (t)[i+3] = ((d) >> 24) & 0xff;\
+    } while(0)
+
+#define PVR2_DECOMPOSE_BE(t,i,d) \
+    do {    \
+       (t)[i+3] = (d) & 0xff;\
+       (t)[i+2] = ((d) >> 8) & 0xff;\
+       (t)[i+1] = ((d) >> 16) & 0xff;\
+       (t)[i] = ((d) >> 24) & 0xff;\
+    } while(0)
+
+#define PVR2_COMPOSE_LE(t,i) \
+    ((((u32)((t)[i+3])) << 24) | \
+     (((u32)((t)[i+2])) << 16) | \
+     (((u32)((t)[i+1])) << 8) | \
+     ((u32)((t)[i])))
+
+#define PVR2_COMPOSE_BE(t,i) \
+    ((((u32)((t)[i])) << 24) | \
+     (((u32)((t)[i+1])) << 16) | \
+     (((u32)((t)[i+2])) << 8) | \
+     ((u32)((t)[i+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
new file mode 100644 (file)
index 0000000..f344aed
--- /dev/null
@@ -0,0 +1,1413 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include "pvrusb2-context.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-v4l2.h"
+#include "pvrusb2-ioread.h"
+#include <linux/videodev2.h>
+#include <linux/module.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+
+struct pvr2_v4l2_dev;
+struct pvr2_v4l2_fh;
+struct pvr2_v4l2;
+
+struct pvr2_v4l2_dev {
+       struct video_device devbase; /* MUST be first! */
+       struct pvr2_v4l2 *v4lp;
+       struct pvr2_context_stream *stream;
+       /* Information about this device: */
+       enum pvr2_config config; /* Expected stream format */
+       int v4l_type; /* V4L defined type for this device node */
+       enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
+};
+
+struct pvr2_v4l2_fh {
+       struct pvr2_channel channel;
+       struct pvr2_v4l2_dev *pdi;
+       enum v4l2_priority prio;
+       struct pvr2_ioread *rhp;
+       struct file *file;
+       struct pvr2_v4l2 *vhead;
+       struct pvr2_v4l2_fh *vnext;
+       struct pvr2_v4l2_fh *vprev;
+       wait_queue_head_t wait_data;
+       int fw_mode_flag;
+       /* Map contiguous ordinal value to input id */
+       unsigned char *input_map;
+       unsigned int input_cnt;
+};
+
+struct pvr2_v4l2 {
+       struct pvr2_channel channel;
+       struct pvr2_v4l2_fh *vfirst;
+       struct pvr2_v4l2_fh *vlast;
+
+       struct v4l2_prio_state prio;
+
+       /* streams - Note that these must be separately, individually,
+        * allocated pointers.  This is because the v4l core is going to
+        * manage their deletion - separately, individually...  */
+       struct pvr2_v4l2_dev *dev_video;
+       struct pvr2_v4l2_dev *dev_radio;
+};
+
+static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
+module_param_array(video_nr, int, NULL, 0444);
+MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
+static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
+module_param_array(radio_nr, int, NULL, 0444);
+MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
+static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
+module_param_array(vbi_nr, int, NULL, 0444);
+MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
+
+static struct v4l2_capability pvr_capability ={
+       .driver         = "pvrusb2",
+       .card           = "Hauppauge WinTV pvr-usb2",
+       .bus_info       = "usb",
+       .version        = LINUX_VERSION_CODE,
+       .capabilities   = (V4L2_CAP_VIDEO_CAPTURE |
+                          V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
+                          V4L2_CAP_READWRITE),
+};
+
+static struct v4l2_fmtdesc pvr_fmtdesc [] = {
+       {
+               .index          = 0,
+               .type           = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               .flags          = V4L2_FMT_FLAG_COMPRESSED,
+               .description    = "MPEG1/2",
+               // This should really be V4L2_PIX_FMT_MPEG, but xawtv
+               // breaks when I do that.
+               .pixelformat    = 0, // V4L2_PIX_FMT_MPEG,
+       }
+};
+
+#define PVR_FORMAT_PIX  0
+#define PVR_FORMAT_VBI  1
+
+static struct v4l2_format pvr_format [] = {
+       [PVR_FORMAT_PIX] = {
+               .type   = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               .fmt    = {
+                       .pix        = {
+                               .width          = 720,
+                               .height             = 576,
+                               // This should really be V4L2_PIX_FMT_MPEG,
+                               // but xawtv breaks when I do that.
+                               .pixelformat    = 0, // V4L2_PIX_FMT_MPEG,
+                               .field          = V4L2_FIELD_INTERLACED,
+                               .bytesperline   = 0,  // doesn't make sense
+                                                     // here
+                               //FIXME : Don't know what to put here...
+                               .sizeimage          = (32*1024),
+                               .colorspace     = 0, // doesn't make sense here
+                               .priv           = 0
+                       }
+               }
+       },
+       [PVR_FORMAT_VBI] = {
+               .type   = V4L2_BUF_TYPE_VBI_CAPTURE,
+               .fmt    = {
+                       .vbi        = {
+                               .sampling_rate = 27000000,
+                               .offset = 248,
+                               .samples_per_line = 1443,
+                               .sample_format = V4L2_PIX_FMT_GREY,
+                               .start = { 0, 0 },
+                               .count = { 0, 0 },
+                               .flags = 0,
+                       }
+               }
+       }
+};
+
+
+
+/*
+ * This is part of Video 4 Linux API. These procedures handle ioctl() calls.
+ */
+static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+
+       memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
+       strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
+                       sizeof(cap->bus_info));
+       strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
+       return 0;
+}
+
+static int pvr2_g_priority(struct file *file, void *priv, enum v4l2_priority *p)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_v4l2 *vp = fh->vhead;
+
+       *p = v4l2_prio_max(&vp->prio);
+       return 0;
+}
+
+static int pvr2_s_priority(struct file *file, void *priv, enum v4l2_priority prio)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_v4l2 *vp = fh->vhead;
+
+       return v4l2_prio_change(&vp->prio, &fh->prio, prio);
+}
+
+static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       int val = 0;
+       int ret;
+
+       ret = pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), &val);
+       *std = val;
+       return ret;
+}
+
+int pvr2_s_std(struct file *file, void *priv, v4l2_std_id *std)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+
+       return pvr2_ctrl_set_value(
+               pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), *std);
+}
+
+static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       int val = 0;
+       int ret;
+
+       ret = pvr2_ctrl_get_value(
+               pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDDETECT), &val);
+       *std = val;
+       return ret;
+}
+
+static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       struct pvr2_ctrl *cptr;
+       struct v4l2_input tmp;
+       unsigned int cnt;
+       int val;
+
+       cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
+
+       memset(&tmp, 0, sizeof(tmp));
+       tmp.index = vi->index;
+       if (vi->index >= fh->input_cnt)
+               return -EINVAL;
+       val = fh->input_map[vi->index];
+       switch (val) {
+       case PVR2_CVAL_INPUT_TV:
+       case PVR2_CVAL_INPUT_DTV:
+       case PVR2_CVAL_INPUT_RADIO:
+               tmp.type = V4L2_INPUT_TYPE_TUNER;
+               break;
+       case PVR2_CVAL_INPUT_SVIDEO:
+       case PVR2_CVAL_INPUT_COMPOSITE:
+               tmp.type = V4L2_INPUT_TYPE_CAMERA;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       cnt = 0;
+       pvr2_ctrl_get_valname(cptr, val,
+                       tmp.name, sizeof(tmp.name) - 1, &cnt);
+       tmp.name[cnt] = 0;
+
+       /* Don't bother with audioset, since this driver currently
+          always switches the audio whenever the video is
+          switched. */
+
+       /* Handling std is a tougher problem.  It doesn't make
+          sense in cases where a device might be multi-standard.
+          We could just copy out the current value for the
+          standard, but it can change over time.  For now just
+          leave it zero. */
+       *vi = tmp;
+       return 0;
+}
+
+static int pvr2_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       unsigned int idx;
+       struct pvr2_ctrl *cptr;
+       int val;
+       int ret;
+
+       cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
+       val = 0;
+       ret = pvr2_ctrl_get_value(cptr, &val);
+       *i = 0;
+       for (idx = 0; idx < fh->input_cnt; idx++) {
+               if (fh->input_map[idx] == val) {
+                       *i = idx;
+                       break;
+               }
+       }
+       return ret;
+}
+
+static int pvr2_s_input(struct file *file, void *priv, unsigned int inp)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+
+       if (inp >= fh->input_cnt)
+               return -EINVAL;
+       return pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
+                       fh->input_map[inp]);
+}
+
+static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin)
+{
+       /* pkt: FIXME: We are returning one "fake" input here
+          which could very well be called "whatever_we_like".
+          This is for apps that want to see an audio input
+          just to feel comfortable, as well as to test if
+          it can do stereo or sth. There is actually no guarantee
+          that the actual audio input cannot change behind the app's
+          back, but most applications should not mind that either.
+
+          Hopefully, mplayer people will work with us on this (this
+          whole mess is to support mplayer pvr://), or Hans will come
+          up with a more standard way to say "we have inputs but we
+          don 't want you to change them independent of video" which
+          will sort this mess.
+        */
+
+       if (vin->index > 0)
+               return -EINVAL;
+       strncpy(vin->name, "PVRUSB2 Audio", 14);
+       vin->capability = V4L2_AUDCAP_STEREO;
+       return 0;
+}
+
+static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin)
+{
+       /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
+       vin->index = 0;
+       strncpy(vin->name, "PVRUSB2 Audio", 14);
+       vin->capability = V4L2_AUDCAP_STEREO;
+       return 0;
+}
+
+static int pvr2_s_audio(struct file *file, void *priv, struct v4l2_audio *vout)
+{
+       if (vout->index)
+               return -EINVAL;
+       return 0;
+}
+
+static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+
+       if (vt->index != 0)
+               return -EINVAL; /* Only answer for the 1st tuner */
+
+       pvr2_hdw_execute_tuner_poll(hdw);
+       return pvr2_hdw_get_tuner_status(hdw, vt);
+}
+
+static int pvr2_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+
+       if (vt->index != 0)
+               return -EINVAL;
+
+       return pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE),
+                       vt->audmode);
+}
+
+int pvr2_s_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       unsigned long fv;
+       struct v4l2_tuner vt;
+       int cur_input;
+       struct pvr2_ctrl *ctrlp;
+       int ret;
+
+       ret = pvr2_hdw_get_tuner_status(hdw, &vt);
+       if (ret != 0)
+               return ret;
+       ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
+       ret = pvr2_ctrl_get_value(ctrlp, &cur_input);
+       if (ret != 0)
+               return ret;
+       if (vf->type == V4L2_TUNER_RADIO) {
+               if (cur_input != PVR2_CVAL_INPUT_RADIO)
+                       pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO);
+       } else {
+               if (cur_input == PVR2_CVAL_INPUT_RADIO)
+                       pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_TV);
+       }
+       fv = vf->frequency;
+       if (vt.capability & V4L2_TUNER_CAP_LOW)
+               fv = (fv * 125) / 2;
+       else
+               fv = fv * 62500;
+       return pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
+}
+
+static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       int val = 0;
+       int cur_input;
+       struct v4l2_tuner vt;
+       int ret;
+
+       ret = pvr2_hdw_get_tuner_status(hdw, &vt);
+       if (ret != 0)
+               return ret;
+       ret = pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY),
+                       &val);
+       if (ret != 0)
+               return ret;
+       pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
+                       &cur_input);
+       if (cur_input == PVR2_CVAL_INPUT_RADIO)
+               vf->type = V4L2_TUNER_RADIO;
+       else
+               vf->type = V4L2_TUNER_ANALOG_TV;
+       if (vt.capability & V4L2_TUNER_CAP_LOW)
+               val = (val * 2) / 125;
+       else
+               val /= 62500;
+       vf->frequency = val;
+       return 0;
+}
+
+static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd)
+{
+       /* Only one format is supported : mpeg.*/
+       if (fd->index != 0)
+               return -EINVAL;
+
+       memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
+       return 0;
+}
+
+static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       int val;
+
+       memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format));
+       val = 0;
+       pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES),
+                       &val);
+       vf->fmt.pix.width = val;
+       val = 0;
+       pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES),
+                       &val);
+       vf->fmt.pix.height = val;
+       return 0;
+}
+
+static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       int lmin, lmax, ldef;
+       struct pvr2_ctrl *hcp, *vcp;
+       int h = vf->fmt.pix.height;
+       int w = vf->fmt.pix.width;
+
+       hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
+       vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
+
+       lmin = pvr2_ctrl_get_min(hcp);
+       lmax = pvr2_ctrl_get_max(hcp);
+       pvr2_ctrl_get_def(hcp, &ldef);
+       if (w == -1)
+               w = ldef;
+       else if (w < lmin)
+               w = lmin;
+       else if (w > lmax)
+               w = lmax;
+       lmin = pvr2_ctrl_get_min(vcp);
+       lmax = pvr2_ctrl_get_max(vcp);
+       pvr2_ctrl_get_def(vcp, &ldef);
+       if (h == -1)
+               h = ldef;
+       else if (h < lmin)
+               h = lmin;
+       else if (h > lmax)
+               h = lmax;
+
+       memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
+                       sizeof(struct v4l2_format));
+       vf->fmt.pix.width = w;
+       vf->fmt.pix.height = h;
+       return 0;
+}
+
+static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       struct pvr2_ctrl *hcp, *vcp;
+       int ret = pvr2_try_fmt_vid_cap(file, fh, vf);
+
+       if (ret)
+               return ret;
+       hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
+       vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
+       pvr2_ctrl_set_value(hcp, vf->fmt.pix.width);
+       pvr2_ctrl_set_value(vcp, vf->fmt.pix.height);
+       return 0;
+}
+
+static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       struct pvr2_v4l2_dev *pdi = fh->pdi;
+       int ret;
+
+       if (!fh->pdi->stream) {
+               /* No stream defined for this node.  This means
+                  that we're not currently allowed to stream from
+                  this node. */
+               return -EPERM;
+       }
+       ret = pvr2_hdw_set_stream_type(hdw, pdi->config);
+       if (ret < 0)
+               return ret;
+       return pvr2_hdw_set_streaming(hdw, !0);
+}
+
+static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+
+       if (!fh->pdi->stream) {
+               /* No stream defined for this node.  This means
+                  that we're not currently allowed to stream from
+                  this node. */
+               return -EPERM;
+       }
+       return pvr2_hdw_set_streaming(hdw, 0);
+}
+
+static int pvr2_queryctrl(struct file *file, void *priv,
+               struct v4l2_queryctrl *vc)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       struct pvr2_ctrl *cptr;
+       int val;
+
+       if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
+               cptr = pvr2_hdw_get_ctrl_nextv4l(
+                               hdw, (vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
+               if (cptr)
+                       vc->id = pvr2_ctrl_get_v4lid(cptr);
+       } else {
+               cptr = pvr2_hdw_get_ctrl_v4l(hdw, vc->id);
+       }
+       if (!cptr) {
+               pvr2_trace(PVR2_TRACE_V4LIOCTL,
+                               "QUERYCTRL id=0x%x not implemented here",
+                               vc->id);
+               return -EINVAL;
+       }
+
+       pvr2_trace(PVR2_TRACE_V4LIOCTL,
+                       "QUERYCTRL id=0x%x mapping name=%s (%s)",
+                       vc->id, pvr2_ctrl_get_name(cptr),
+                       pvr2_ctrl_get_desc(cptr));
+       strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
+       vc->flags = pvr2_ctrl_get_v4lflags(cptr);
+       pvr2_ctrl_get_def(cptr, &val);
+       vc->default_value = val;
+       switch (pvr2_ctrl_get_type(cptr)) {
+       case pvr2_ctl_enum:
+               vc->type = V4L2_CTRL_TYPE_MENU;
+               vc->minimum = 0;
+               vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
+               vc->step = 1;
+               break;
+       case pvr2_ctl_bool:
+               vc->type = V4L2_CTRL_TYPE_BOOLEAN;
+               vc->minimum = 0;
+               vc->maximum = 1;
+               vc->step = 1;
+               break;
+       case pvr2_ctl_int:
+               vc->type = V4L2_CTRL_TYPE_INTEGER;
+               vc->minimum = pvr2_ctrl_get_min(cptr);
+               vc->maximum = pvr2_ctrl_get_max(cptr);
+               vc->step = 1;
+               break;
+       default:
+               pvr2_trace(PVR2_TRACE_V4LIOCTL,
+                               "QUERYCTRL id=0x%x name=%s not mappable",
+                               vc->id, pvr2_ctrl_get_name(cptr));
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       unsigned int cnt = 0;
+       int ret;
+
+       ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw, vm->id),
+                       vm->index,
+                       vm->name, sizeof(vm->name) - 1,
+                       &cnt);
+       vm->name[cnt] = 0;
+       return ret;
+}
+
+static int pvr2_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       int val = 0;
+       int ret;
+
+       ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
+                       &val);
+       vc->value = val;
+       return ret;
+}
+
+static int pvr2_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+
+       return pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
+                       vc->value);
+}
+
+static int pvr2_g_ext_ctrls(struct file *file, void *priv,
+                                       struct v4l2_ext_controls *ctls)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       struct v4l2_ext_control *ctrl;
+       unsigned int idx;
+       int val;
+       int ret;
+
+       ret = 0;
+       for (idx = 0; idx < ctls->count; idx++) {
+               ctrl = ctls->controls + idx;
+               ret = pvr2_ctrl_get_value(
+                               pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id), &val);
+               if (ret) {
+                       ctls->error_idx = idx;
+                       return ret;
+               }
+               /* Ensure that if read as a 64 bit value, the user
+                  will still get a hopefully sane value */
+               ctrl->value64 = 0;
+               ctrl->value = val;
+       }
+       return 0;
+}
+
+static int pvr2_s_ext_ctrls(struct file *file, void *priv,
+               struct v4l2_ext_controls *ctls)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       struct v4l2_ext_control *ctrl;
+       unsigned int idx;
+       int ret;
+
+       ret = 0;
+       for (idx = 0; idx < ctls->count; idx++) {
+               ctrl = ctls->controls + idx;
+               ret = pvr2_ctrl_set_value(
+                               pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id),
+                               ctrl->value);
+               if (ret) {
+                       ctls->error_idx = idx;
+                       return ret;
+               }
+       }
+       return 0;
+}
+
+static int pvr2_try_ext_ctrls(struct file *file, void *priv,
+               struct v4l2_ext_controls *ctls)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       struct v4l2_ext_control *ctrl;
+       struct pvr2_ctrl *pctl;
+       unsigned int idx;
+
+       /* For the moment just validate that the requested control
+          actually exists. */
+       for (idx = 0; idx < ctls->count; idx++) {
+               ctrl = ctls->controls + idx;
+               pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
+               if (!pctl) {
+                       ctls->error_idx = idx;
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
+static int pvr2_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       int ret;
+
+       if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       ret = pvr2_hdw_get_cropcap(hdw, cap);
+       cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
+       return ret;
+}
+
+static int pvr2_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       int val = 0;
+       int ret;
+
+       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       ret = pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
+       if (ret != 0)
+               return -EINVAL;
+       crop->c.left = val;
+       ret = pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
+       if (ret != 0)
+               return -EINVAL;
+       crop->c.top = val;
+       ret = pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
+       if (ret != 0)
+               return -EINVAL;
+       crop->c.width = val;
+       ret = pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
+       if (ret != 0)
+               return -EINVAL;
+       crop->c.height = val;
+       return 0;
+}
+
+static int pvr2_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       int ret;
+
+       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       ret = pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
+                       crop->c.left);
+       if (ret != 0)
+               return -EINVAL;
+       ret = pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
+                       crop->c.top);
+       if (ret != 0)
+               return -EINVAL;
+       ret = pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
+                       crop->c.width);
+       if (ret != 0)
+               return -EINVAL;
+       ret = pvr2_ctrl_set_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
+                       crop->c.height);
+       if (ret != 0)
+               return -EINVAL;
+       return 0;
+}
+
+static int pvr2_log_status(struct file *file, void *priv)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+
+       pvr2_hdw_trigger_module_log(hdw);
+       return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int pvr2_g_register(struct file *file, void *priv, struct v4l2_dbg_register *req)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       u64 val;
+       int ret;
+
+       ret = pvr2_hdw_register_access(
+                       hdw, &req->match, req->reg,
+                       0, &val);
+       req->val = val;
+       return ret;
+}
+
+static int pvr2_s_register(struct file *file, void *priv, struct v4l2_dbg_register *req)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       u64 val;
+       int ret;
+
+       val = req->val;
+       ret = pvr2_hdw_register_access(
+                       hdw, &req->match, req->reg,
+                       1, &val);
+       return ret;
+}
+#endif
+
+static const struct v4l2_ioctl_ops pvr2_ioctl_ops = {
+       .vidioc_querycap                    = pvr2_querycap,
+       .vidioc_g_priority                  = pvr2_g_priority,
+       .vidioc_s_priority                  = pvr2_s_priority,
+       .vidioc_s_audio                     = pvr2_s_audio,
+       .vidioc_g_audio                     = pvr2_g_audio,
+       .vidioc_enumaudio                   = pvr2_enumaudio,
+       .vidioc_enum_input                  = pvr2_enum_input,
+       .vidioc_cropcap                     = pvr2_cropcap,
+       .vidioc_s_crop                      = pvr2_s_crop,
+       .vidioc_g_crop                      = pvr2_g_crop,
+       .vidioc_g_input                     = pvr2_g_input,
+       .vidioc_s_input                     = pvr2_s_input,
+       .vidioc_g_frequency                 = pvr2_g_frequency,
+       .vidioc_s_frequency                 = pvr2_s_frequency,
+       .vidioc_s_tuner                     = pvr2_s_tuner,
+       .vidioc_g_tuner                     = pvr2_g_tuner,
+       .vidioc_g_std                       = pvr2_g_std,
+       .vidioc_s_std                       = pvr2_s_std,
+       .vidioc_querystd                    = pvr2_querystd,
+       .vidioc_log_status                  = pvr2_log_status,
+       .vidioc_enum_fmt_vid_cap            = pvr2_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap               = pvr2_g_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap               = pvr2_s_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap             = pvr2_try_fmt_vid_cap,
+       .vidioc_streamon                    = pvr2_streamon,
+       .vidioc_streamoff                   = pvr2_streamoff,
+       .vidioc_queryctrl                   = pvr2_queryctrl,
+       .vidioc_querymenu                   = pvr2_querymenu,
+       .vidioc_g_ctrl                      = pvr2_g_ctrl,
+       .vidioc_s_ctrl                      = pvr2_s_ctrl,
+       .vidioc_g_ext_ctrls                 = pvr2_g_ext_ctrls,
+       .vidioc_s_ext_ctrls                 = pvr2_s_ext_ctrls,
+       .vidioc_try_ext_ctrls               = pvr2_try_ext_ctrls,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register                  = pvr2_g_register,
+       .vidioc_s_register                  = pvr2_s_register,
+#endif
+};
+
+static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
+{
+       struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
+       enum pvr2_config cfg = dip->config;
+       char msg[80];
+       unsigned int mcnt;
+
+       /* Construct the unregistration message *before* we actually
+          perform the unregistration step.  By doing it this way we don't
+          have to worry about potentially touching deleted resources. */
+       mcnt = scnprintf(msg, sizeof(msg) - 1,
+                        "pvrusb2: unregistered device %s [%s]",
+                        video_device_node_name(&dip->devbase),
+                        pvr2_config_get_name(cfg));
+       msg[mcnt] = 0;
+
+       pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
+
+       /* Paranoia */
+       dip->v4lp = NULL;
+       dip->stream = NULL;
+
+       /* Actual deallocation happens later when all internal references
+          are gone. */
+       video_unregister_device(&dip->devbase);
+
+       printk(KERN_INFO "%s\n", msg);
+
+}
+
+
+static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
+{
+       if (!dip) return;
+       if (!dip->devbase.parent) return;
+       dip->devbase.parent = NULL;
+       device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
+}
+
+
+static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
+{
+       if (vp->dev_video) {
+               pvr2_v4l2_dev_destroy(vp->dev_video);
+               vp->dev_video = NULL;
+       }
+       if (vp->dev_radio) {
+               pvr2_v4l2_dev_destroy(vp->dev_radio);
+               vp->dev_radio = NULL;
+       }
+
+       pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
+       pvr2_channel_done(&vp->channel);
+       kfree(vp);
+}
+
+
+static void pvr2_video_device_release(struct video_device *vdev)
+{
+       struct pvr2_v4l2_dev *dev;
+       dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
+       kfree(dev);
+}
+
+
+static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
+{
+       struct pvr2_v4l2 *vp;
+       vp = container_of(chp,struct pvr2_v4l2,channel);
+       if (!vp->channel.mc_head->disconnect_flag) return;
+       pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
+       pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
+       if (vp->vfirst) return;
+       pvr2_v4l2_destroy_no_lock(vp);
+}
+
+
+static long pvr2_v4l2_ioctl(struct file *file,
+                          unsigned int cmd, unsigned long arg)
+{
+
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       struct pvr2_v4l2 *vp = fh->vhead;
+       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+       long ret = -EINVAL;
+
+       if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL)
+               v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
+
+       if (!pvr2_hdw_dev_ok(hdw)) {
+               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                          "ioctl failed - bad or no context");
+               return -EFAULT;
+       }
+
+       /* check priority */
+       switch (cmd) {
+       case VIDIOC_S_CTRL:
+       case VIDIOC_S_STD:
+       case VIDIOC_S_INPUT:
+       case VIDIOC_S_TUNER:
+       case VIDIOC_S_FREQUENCY:
+               ret = v4l2_prio_check(&vp->prio, fh->prio);
+               if (ret)
+                       return ret;
+       }
+
+       ret = video_ioctl2(file, cmd, arg);
+
+       pvr2_hdw_commit_ctl(hdw);
+
+       if (ret < 0) {
+               if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
+                       pvr2_trace(PVR2_TRACE_V4LIOCTL,
+                                  "pvr2_v4l2_do_ioctl failure, ret=%ld", ret);
+               } else {
+                       if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
+                               pvr2_trace(PVR2_TRACE_V4LIOCTL,
+                                          "pvr2_v4l2_do_ioctl failure, ret=%ld"
+                                          " command was:", ret);
+                               v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw),
+                                               cmd);
+                       }
+               }
+       } else {
+               pvr2_trace(PVR2_TRACE_V4LIOCTL,
+                          "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
+                          ret, ret);
+       }
+       return ret;
+
+}
+
+
+static int pvr2_v4l2_release(struct file *file)
+{
+       struct pvr2_v4l2_fh *fhp = file->private_data;
+       struct pvr2_v4l2 *vp = fhp->vhead;
+       struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
+
+       pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
+
+       if (fhp->rhp) {
+               struct pvr2_stream *sp;
+               pvr2_hdw_set_streaming(hdw,0);
+               sp = pvr2_ioread_get_stream(fhp->rhp);
+               if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
+               pvr2_ioread_destroy(fhp->rhp);
+               fhp->rhp = NULL;
+       }
+
+       v4l2_prio_close(&vp->prio, fhp->prio);
+       file->private_data = NULL;
+
+       if (fhp->vnext) {
+               fhp->vnext->vprev = fhp->vprev;
+       } else {
+               vp->vlast = fhp->vprev;
+       }
+       if (fhp->vprev) {
+               fhp->vprev->vnext = fhp->vnext;
+       } else {
+               vp->vfirst = fhp->vnext;
+       }
+       fhp->vnext = NULL;
+       fhp->vprev = NULL;
+       fhp->vhead = NULL;
+       pvr2_channel_done(&fhp->channel);
+       pvr2_trace(PVR2_TRACE_STRUCT,
+                  "Destroying pvr_v4l2_fh id=%p",fhp);
+       if (fhp->input_map) {
+               kfree(fhp->input_map);
+               fhp->input_map = NULL;
+       }
+       kfree(fhp);
+       if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
+               pvr2_v4l2_destroy_no_lock(vp);
+       }
+       return 0;
+}
+
+
+static int pvr2_v4l2_open(struct file *file)
+{
+       struct pvr2_v4l2_dev *dip; /* Our own context pointer */
+       struct pvr2_v4l2_fh *fhp;
+       struct pvr2_v4l2 *vp;
+       struct pvr2_hdw *hdw;
+       unsigned int input_mask = 0;
+       unsigned int input_cnt,idx;
+       int ret = 0;
+
+       dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
+
+       vp = dip->v4lp;
+       hdw = vp->channel.hdw;
+
+       pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
+
+       if (!pvr2_hdw_dev_ok(hdw)) {
+               pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
+                          "pvr2_v4l2_open: hardware not ready");
+               return -EIO;
+       }
+
+       fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
+       if (!fhp) {
+               return -ENOMEM;
+       }
+
+       init_waitqueue_head(&fhp->wait_data);
+       fhp->pdi = dip;
+
+       pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
+       pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
+
+       if (dip->v4l_type == VFL_TYPE_RADIO) {
+               /* Opening device as a radio, legal input selection subset
+                  is just the radio. */
+               input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
+       } else {
+               /* Opening the main V4L device, legal input selection
+                  subset includes all analog inputs. */
+               input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
+                             (1 << PVR2_CVAL_INPUT_TV) |
+                             (1 << PVR2_CVAL_INPUT_COMPOSITE) |
+                             (1 << PVR2_CVAL_INPUT_SVIDEO));
+       }
+       ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
+       if (ret) {
+               pvr2_channel_done(&fhp->channel);
+               pvr2_trace(PVR2_TRACE_STRUCT,
+                          "Destroying pvr_v4l2_fh id=%p (input mask error)",
+                          fhp);
+
+               kfree(fhp);
+               return ret;
+       }
+
+       input_mask &= pvr2_hdw_get_input_available(hdw);
+       input_cnt = 0;
+       for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
+               if (input_mask & (1 << idx)) input_cnt++;
+       }
+       fhp->input_cnt = input_cnt;
+       fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
+       if (!fhp->input_map) {
+               pvr2_channel_done(&fhp->channel);
+               pvr2_trace(PVR2_TRACE_STRUCT,
+                          "Destroying pvr_v4l2_fh id=%p (input map failure)",
+                          fhp);
+               kfree(fhp);
+               return -ENOMEM;
+       }
+       input_cnt = 0;
+       for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
+               if (!(input_mask & (1 << idx))) continue;
+               fhp->input_map[input_cnt++] = idx;
+       }
+
+       fhp->vnext = NULL;
+       fhp->vprev = vp->vlast;
+       if (vp->vlast) {
+               vp->vlast->vnext = fhp;
+       } else {
+               vp->vfirst = fhp;
+       }
+       vp->vlast = fhp;
+       fhp->vhead = vp;
+
+       fhp->file = file;
+       file->private_data = fhp;
+       v4l2_prio_open(&vp->prio, &fhp->prio);
+
+       fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
+
+       return 0;
+}
+
+
+static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
+{
+       wake_up(&fhp->wait_data);
+}
+
+static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
+{
+       int ret;
+       struct pvr2_stream *sp;
+       struct pvr2_hdw *hdw;
+       if (fh->rhp) return 0;
+
+       if (!fh->pdi->stream) {
+               /* No stream defined for this node.  This means that we're
+                  not currently allowed to stream from this node. */
+               return -EPERM;
+       }
+
+       /* First read() attempt.  Try to claim the stream and start
+          it... */
+       if ((ret = pvr2_channel_claim_stream(&fh->channel,
+                                            fh->pdi->stream)) != 0) {
+               /* Someone else must already have it */
+               return ret;
+       }
+
+       fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
+       if (!fh->rhp) {
+               pvr2_channel_claim_stream(&fh->channel,NULL);
+               return -ENOMEM;
+       }
+
+       hdw = fh->channel.mc_head->hdw;
+       sp = fh->pdi->stream->stream;
+       pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
+       pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
+       if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
+       return pvr2_ioread_set_enabled(fh->rhp,!0);
+}
+
+
+static ssize_t pvr2_v4l2_read(struct file *file,
+                             char __user *buff, size_t count, loff_t *ppos)
+{
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       int ret;
+
+       if (fh->fw_mode_flag) {
+               struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+               char *tbuf;
+               int c1,c2;
+               int tcnt = 0;
+               unsigned int offs = *ppos;
+
+               tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
+               if (!tbuf) return -ENOMEM;
+
+               while (count) {
+                       c1 = count;
+                       if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
+                       c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
+                       if (c2 < 0) {
+                               tcnt = c2;
+                               break;
+                       }
+                       if (!c2) break;
+                       if (copy_to_user(buff,tbuf,c2)) {
+                               tcnt = -EFAULT;
+                               break;
+                       }
+                       offs += c2;
+                       tcnt += c2;
+                       buff += c2;
+                       count -= c2;
+                       *ppos += c2;
+               }
+               kfree(tbuf);
+               return tcnt;
+       }
+
+       if (!fh->rhp) {
+               ret = pvr2_v4l2_iosetup(fh);
+               if (ret) {
+                       return ret;
+               }
+       }
+
+       for (;;) {
+               ret = pvr2_ioread_read(fh->rhp,buff,count);
+               if (ret >= 0) break;
+               if (ret != -EAGAIN) break;
+               if (file->f_flags & O_NONBLOCK) break;
+               /* Doing blocking I/O.  Wait here. */
+               ret = wait_event_interruptible(
+                       fh->wait_data,
+                       pvr2_ioread_avail(fh->rhp) >= 0);
+               if (ret < 0) break;
+       }
+
+       return ret;
+}
+
+
+static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
+{
+       unsigned int mask = 0;
+       struct pvr2_v4l2_fh *fh = file->private_data;
+       int ret;
+
+       if (fh->fw_mode_flag) {
+               mask |= POLLIN | POLLRDNORM;
+               return mask;
+       }
+
+       if (!fh->rhp) {
+               ret = pvr2_v4l2_iosetup(fh);
+               if (ret) return POLLERR;
+       }
+
+       poll_wait(file,&fh->wait_data,wait);
+
+       if (pvr2_ioread_avail(fh->rhp) >= 0) {
+               mask |= POLLIN | POLLRDNORM;
+       }
+
+       return mask;
+}
+
+
+static const struct v4l2_file_operations vdev_fops = {
+       .owner      = THIS_MODULE,
+       .open       = pvr2_v4l2_open,
+       .release    = pvr2_v4l2_release,
+       .read       = pvr2_v4l2_read,
+       .ioctl      = pvr2_v4l2_ioctl,
+       .poll       = pvr2_v4l2_poll,
+};
+
+
+static struct video_device vdev_template = {
+       .fops       = &vdev_fops,
+};
+
+
+static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
+                              struct pvr2_v4l2 *vp,
+                              int v4l_type)
+{
+       struct usb_device *usbdev;
+       int mindevnum;
+       int unit_number;
+       struct pvr2_hdw *hdw;
+       int *nr_ptr = NULL;
+       dip->v4lp = vp;
+
+       hdw = vp->channel.mc_head->hdw;
+       usbdev = pvr2_hdw_get_dev(hdw);
+       dip->v4l_type = v4l_type;
+       switch (v4l_type) {
+       case VFL_TYPE_GRABBER:
+               dip->stream = &vp->channel.mc_head->video_stream;
+               dip->config = pvr2_config_mpeg;
+               dip->minor_type = pvr2_v4l_type_video;
+               nr_ptr = video_nr;
+               if (!dip->stream) {
+                       pr_err(KBUILD_MODNAME
+                               ": Failed to set up pvrusb2 v4l video dev"
+                               " due to missing stream instance\n");
+                       return;
+               }
+               break;
+       case VFL_TYPE_VBI:
+               dip->config = pvr2_config_vbi;
+               dip->minor_type = pvr2_v4l_type_vbi;
+               nr_ptr = vbi_nr;
+               break;
+       case VFL_TYPE_RADIO:
+               dip->stream = &vp->channel.mc_head->video_stream;
+               dip->config = pvr2_config_mpeg;
+               dip->minor_type = pvr2_v4l_type_radio;
+               nr_ptr = radio_nr;
+               break;
+       default:
+               /* Bail out (this should be impossible) */
+               pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
+                   " due to unrecognized config\n");
+               return;
+       }
+
+       memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
+       dip->devbase.release = pvr2_video_device_release;
+       dip->devbase.ioctl_ops = &pvr2_ioctl_ops;
+       {
+               int val;
+               pvr2_ctrl_get_value(
+                       pvr2_hdw_get_ctrl_by_id(hdw,
+                                               PVR2_CID_STDAVAIL), &val);
+               dip->devbase.tvnorms = (v4l2_std_id)val;
+       }
+
+       mindevnum = -1;
+       unit_number = pvr2_hdw_get_unit_number(hdw);
+       if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
+               mindevnum = nr_ptr[unit_number];
+       }
+       dip->devbase.parent = &usbdev->dev;
+       if ((video_register_device(&dip->devbase,
+                                  dip->v4l_type, mindevnum) < 0) &&
+           (video_register_device(&dip->devbase,
+                                  dip->v4l_type, -1) < 0)) {
+               pr_err(KBUILD_MODNAME
+                       ": Failed to register pvrusb2 v4l device\n");
+       }
+
+       printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
+              video_device_node_name(&dip->devbase),
+              pvr2_config_get_name(dip->config));
+
+       pvr2_hdw_v4l_store_minor_number(hdw,
+                                       dip->minor_type,dip->devbase.minor);
+}
+
+
+struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
+{
+       struct pvr2_v4l2 *vp;
+
+       vp = kzalloc(sizeof(*vp),GFP_KERNEL);
+       if (!vp) return vp;
+       pvr2_channel_init(&vp->channel,mnp);
+       pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
+
+       vp->channel.check_func = pvr2_v4l2_internal_check;
+
+       /* register streams */
+       vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
+       if (!vp->dev_video) goto fail;
+       pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
+       if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
+           (1 << PVR2_CVAL_INPUT_RADIO)) {
+               vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
+               if (!vp->dev_radio) goto fail;
+               pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
+       }
+
+       return vp;
+ fail:
+       pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
+       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
new file mode 100644 (file)
index 0000000..34c011a
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_V4L2_H
+#define __PVRUSB2_V4L2_H
+
+#include "pvrusb2-context.h"
+
+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
new file mode 100644 (file)
index 0000000..2e205c9
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+
+   This source file is specifically designed to interface with the
+   saa711x support that is available in the v4l available starting
+   with linux 2.6.15.
+
+*/
+
+#include "pvrusb2-video-v4l.h"
+
+
+
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/saa7115.h>
+#include <linux/errno.h>
+
+struct routing_scheme {
+       const int *def;
+       unsigned int cnt;
+};
+
+
+static const int routing_scheme0[] = {
+       [PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4,
+       /* In radio mode, we mute the video, but point at one
+          spot just to stay consistent */
+       [PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5,
+       [PVR2_CVAL_INPUT_COMPOSITE] = SAA7115_COMPOSITE5,
+       [PVR2_CVAL_INPUT_SVIDEO] =  SAA7115_SVIDEO2,
+};
+
+static const struct routing_scheme routing_def0 = {
+       .def = routing_scheme0,
+       .cnt = ARRAY_SIZE(routing_scheme0),
+};
+
+static const int routing_scheme1[] = {
+       [PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4,
+       [PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5,
+       [PVR2_CVAL_INPUT_COMPOSITE] = SAA7115_COMPOSITE3,
+       [PVR2_CVAL_INPUT_SVIDEO] =  SAA7115_SVIDEO2, /* or SVIDEO0, it seems */
+};
+
+static const struct routing_scheme routing_def1 = {
+       .def = routing_scheme1,
+       .cnt = ARRAY_SIZE(routing_scheme1),
+};
+
+static const struct routing_scheme *routing_schemes[] = {
+       [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
+       [PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1,
+};
+
+void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
+{
+       if (hdw->input_dirty || hdw->force_dirty) {
+               const struct routing_scheme *sp;
+               unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
+               u32 input;
+
+               pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)",
+                          hdw->input_val);
+
+               sp = (sid < ARRAY_SIZE(routing_schemes)) ?
+                       routing_schemes[sid] : NULL;
+               if ((sp == NULL) ||
+                   (hdw->input_val < 0) ||
+                   (hdw->input_val >= sp->cnt)) {
+                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+                                  "*** WARNING *** subdev v4l2 set_input:"
+                                  " Invalid routing scheme (%u)"
+                                  " and/or input (%d)",
+                                  sid, hdw->input_val);
+                       return;
+               }
+               input = sp->def[hdw->input_val];
+               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
new file mode 100644 (file)
index 0000000..3b0bd5d
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_VIDEO_V4L_H
+#define __PVRUSB2_VIDEO_V4L_H
+
+/*
+
+   This module connects the pvrusb2 driver to the I2C chip level
+   driver which handles device video processing.  This interface is
+   used internally by the driver; higher level code should only
+   interact through the interface provided by pvrusb2-hdw.h.
+
+*/
+
+
+#include "pvrusb2-hdw-internal.h"
+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
new file mode 100644 (file)
index 0000000..3ac8d75
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+
+   This source file is specifically designed to interface with the
+   wm8775.
+
+*/
+
+#include "pvrusb2-wm8775.h"
+
+
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/errno.h>
+
+void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
+{
+       if (hdw->input_dirty || hdw->force_dirty) {
+               u32 input;
+
+               switch (hdw->input_val) {
+               case PVR2_CVAL_INPUT_RADIO:
+                       input = 1;
+                       break;
+               default:
+                       /* All other cases just use the second input */
+                       input = 2;
+                       break;
+               }
+               pvr2_trace(PVR2_TRACE_CHIPS, "subdev wm8775"
+                          " set_input(val=%d route=0x%x)",
+                          hdw->input_val, input);
+
+               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
new file mode 100644 (file)
index 0000000..0577bc7
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_WM8775_H
+#define __PVRUSB2_WM8775_H
+
+/*
+
+   This module connects the pvrusb2 driver to the I2C chip level
+   driver which performs analog -> digital audio conversion for
+   external audio inputs.  This interface is used internally by the
+   driver; higher level code should only interact through the
+   interface provided by pvrusb2-hdw.h.
+
+*/
+
+
+
+#include "pvrusb2-hdw-internal.h"
+
+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
new file mode 100644 (file)
index 0000000..240de9b
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  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
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_H
+#define __PVRUSB2_H
+
+/* Maximum number of pvrusb2 instances we can track at once.  You
+   might want to increase this - however the driver operation will not
+   be impaired if it is too small.  Instead additional units just
+   won't have an ID assigned and it might not be possible to specify
+   module parameters for those extra units. */
+#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/Kconfig b/drivers/media/usb/pwc/Kconfig
new file mode 100644 (file)
index 0000000..d63d0a8
--- /dev/null
@@ -0,0 +1,48 @@
+config USB_PWC
+       tristate "USB Philips Cameras"
+       depends on VIDEO_V4L2
+       select VIDEOBUF2_VMALLOC
+       ---help---
+         Say Y or M here if you want to use one of these Philips & OEM
+         webcams:
+          * Philips PCA645, PCA646
+          * Philips PCVC675, PCVC680, PCVC690
+          * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
+          * Philips SPC900NC
+          * Askey VC010
+          * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
+            and 'Orbit'/'Sphere'
+          * Samsung MPC-C10, MPC-C30
+          * Creative Webcam 5, Pro Ex
+          * SOTEC Afina Eye
+          * Visionite VCS-UC300, VCS-UM100
+
+         The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
+         and never will be, but the 665 and 720/20 are supported by other
+         drivers.
+
+         Some newer logitech webcams are not handled by this driver but by the
+         Usb Video Class driver (linux-uvc).
+
+         The built-in microphone is enabled by selecting USB Audio support.
+
+         To compile this driver as a module, choose M here: the
+         module will be called pwc.
+
+config USB_PWC_DEBUG
+       bool "USB Philips Cameras verbose debug"
+       depends on USB_PWC
+       help
+         Say Y here in order to have the pwc driver generate verbose debugging
+         messages.
+         A special module options 'trace' is used to control the verbosity.
+
+config USB_PWC_INPUT_EVDEV
+       bool "USB Philips Cameras input events device support"
+       default y
+       depends on USB_PWC && (USB_PWC=INPUT || INPUT=y)
+       ---help---
+         This option makes USB Philips cameras register the snapshot button as
+         an input device to report button events.
+
+         If you are in doubt, say Y.
diff --git a/drivers/media/usb/pwc/Makefile b/drivers/media/usb/pwc/Makefile
new file mode 100644 (file)
index 0000000..f5c8ec2
--- /dev/null
@@ -0,0 +1,4 @@
+pwc-objs       := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o
+pwc-objs       += pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o
+
+obj-$(CONFIG_USB_PWC) += pwc.o
diff --git a/drivers/media/usb/pwc/philips.txt b/drivers/media/usb/pwc/philips.txt
new file mode 100644 (file)
index 0000000..d38dd79
--- /dev/null
@@ -0,0 +1,236 @@
+This file contains some additional information for the Philips and OEM webcams.
+E-mail: webcam@smcc.demon.nl                        Last updated: 2004-01-19
+Site: http://www.smcc.demon.nl/webcam/
+
+As of this moment, the following cameras are supported:
+ * Philips PCA645
+ * Philips PCA646
+ * Philips PCVC675
+ * Philips PCVC680
+ * Philips PCVC690
+ * Philips PCVC720/40
+ * Philips PCVC730
+ * Philips PCVC740
+ * Philips PCVC750
+ * Askey VC010
+ * Creative Labs Webcam 5
+ * Creative Labs Webcam Pro Ex
+ * Logitech QuickCam 3000 Pro
+ * Logitech QuickCam 4000 Pro
+ * Logitech QuickCam Notebook Pro
+ * Logitech QuickCam Zoom
+ * Logitech QuickCam Orbit
+ * Logitech QuickCam Sphere
+ * Samsung MPC-C10
+ * Samsung MPC-C30
+ * Sotec Afina Eye
+ * AME CU-001
+ * Visionite VCS-UM100
+ * Visionite VCS-UC300
+
+The main webpage for the Philips driver is at the address above. It contains
+a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin
+contains decompression routines that allow you to use higher image sizes and
+framerates; in addition the webcam uses less bandwidth on the USB bus (handy
+if you want to run more than 1 camera simultaneously). These routines fall
+under a NDA, and may therefore not be distributed as source; however, its use
+is completely optional.
+
+You can build this code either into your kernel, or as a module. I recommend
+the latter, since it makes troubleshooting a lot easier. The built-in
+microphone is supported through the USB Audio class.
+
+When you load the module you can set some default settings for the
+camera; some programs depend on a particular image-size or -format and
+don't know how to set it properly in the driver. The options are:
+
+size
+   Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
+   'vga', for an image size of resp. 128x96, 160x120, 176x144,
+   320x240, 352x288 and 640x480 (of course, only for those cameras that
+   support these resolutions).
+
+fps
+   Specifies the desired framerate. Is an integer in the range of 4-30.
+
+fbufs
+   This parameter specifies the number of internal buffers to use for storing
+   frames from the cam. This will help if the process that reads images from
+   the cam is a bit slow or momentarily busy. However, on slow machines it
+   only introduces lag, so choose carefully. The default is 3, which is
+   reasonable. You can set it between 2 and 5.
+
+mbufs
+   This is an integer between 1 and 10. It will tell the module the number of
+   buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
+   The default is 2, which is adequate for most applications (double
+   buffering).
+
+   Should you experience a lot of 'Dumping frame...' messages during
+   grabbing with a tool that uses mmap(), you might want to increase if.
+   However, it doesn't really buffer images, it just gives you a bit more
+   slack when your program is behind. But you need a multi-threaded or
+   forked program to really take advantage of these buffers.
+
+   The absolute maximum is 10, but don't set it too high!  Every buffer takes
+   up 460 KB of RAM, so unless you have a lot of memory setting this to
+   something more than 4 is an absolute waste.  This memory is only
+   allocated during open(), so nothing is wasted when the camera is not in
+   use.
+
+power_save
+   When power_save is enabled (set to 1), the module will try to shut down
+   the cam on close() and re-activate on open(). This will save power and
+   turn off the LED. Not all cameras support this though (the 645 and 646
+   don't have power saving at all), and some models don't work either (they
+   will shut down, but never wake up). Consider this experimental. By
+   default this option is disabled.
+
+compression (only useful with the plugin)
+   With this option you can control the compression factor that the camera
+   uses to squeeze the image through the USB bus. You can set the
+   parameter between 0 and 3:
+     0 = prefer uncompressed images; if the requested mode is not available
+        in an uncompressed format, the driver will silently switch to low
+        compression.
+     1 = low compression.
+     2 = medium compression.
+     3 = high compression.
+
+   High compression takes less bandwidth of course, but it could also
+   introduce some unwanted artefacts. The default is 2, medium compression.
+   See the FAQ on the website for an overview of which modes require
+   compression.
+
+   The compression parameter does not apply to the 645 and 646 cameras
+   and OEM models derived from those (only a few). Most cams honour this
+   parameter.
+
+leds
+   This settings takes 2 integers, that define the on/off time for the LED
+   (in milliseconds). One of the interesting things that you can do with
+   this is let the LED blink while the camera is in use. This:
+
+     leds=500,500
+
+   will blink the LED once every second. But with:
+
+     leds=0,0
+
+   the LED never goes on, making it suitable for silent surveillance.
+
+   By default the camera's LED is on solid while in use, and turned off
+   when the camera is not used anymore.
+
+   This parameter works only with the ToUCam range of cameras (720, 730, 740,
+   750) and OEMs. For other cameras this command is silently ignored, and
+   the LED cannot be controlled.
+
+   Finally: this parameters does not take effect UNTIL the first time you
+   open the camera device. Until then, the LED remains on.
+
+dev_hint
+   A long standing problem with USB devices is their dynamic nature: you
+   never know what device a camera gets assigned; it depends on module load
+   order, the hub configuration, the order in which devices are plugged in,
+   and the phase of the moon (i.e. it can be random). With this option you
+   can give the driver a hint as to what video device node (/dev/videoX) it
+   should use with a specific camera. This is also handy if you have two
+   cameras of the same model.
+
+   A camera is specified by its type (the number from the camera model,
+   like PCA645, PCVC750VC, etc) and optionally the serial number (visible
+   in /proc/bus/usb/devices). A hint consists of a string with the following
+   format:
+
+      [type[.serialnumber]:]node
+
+   The square brackets mean that both the type and the serialnumber are
+   optional, but a serialnumber cannot be specified without a type (which
+   would be rather pointless). The serialnumber is separated from the type
+   by a '.'; the node number by a ':'.
+
+   This somewhat cryptic syntax is best explained by a few examples:
+
+     dev_hint=3,5              The first detected cam gets assigned
+                              /dev/video3, the second /dev/video5. Any
+                              other cameras will get the first free
+                              available slot (see below).
+
+     dev_hint=645:1,680:2      The PCA645 camera will get /dev/video1,
+                              and a PCVC680 /dev/video2.
+
+     dev_hint=645.0123:3,645.4567:0    The PCA645 camera with serialnumber
+                                       0123 goes to /dev/video3, the same
+                                       camera model with the 4567 serial
+                                       gets /dev/video0.
+
+     dev_hint=750:1,4,5,6       The PCVC750 camera will get /dev/video1, the
+                               next 3 Philips cams will use /dev/video4
+                               through /dev/video6.
+
+   Some points worth knowing:
+   - Serialnumbers are case sensitive and must be written full, including
+     leading zeroes (it's treated as a string).
+   - If a device node is already occupied, registration will fail and
+     the webcam is not available.
+   - You can have up to 64 video devices; be sure to make enough device
+     nodes in /dev if you want to spread the numbers.
+     After /dev/video9 comes /dev/video10 (not /dev/videoA).
+   - If a camera does not match any dev_hint, it will simply get assigned
+     the first available device node, just as it used to be.
+
+trace
+   In order to better detect problems, it is now possible to turn on a
+   'trace' of some of the calls the module makes; it logs all items in your
+   kernel log at debug level.
+
+   The trace variable is a bitmask; each bit represents a certain feature.
+   If you want to trace something, look up the bit value(s) in the table
+   below, add the values together and supply that to the trace variable.
+
+   Value  Value   Description                                     Default
+   (dec)  (hex)
+       1    0x1   Module initialization; this will log messages       On
+                 while loading and unloading the module
+
+       2    0x2   probe() and disconnect() traces                     On
+
+       4    0x4   Trace open() and close() calls                      Off
+
+       8    0x8   read(), mmap() and associated ioctl() calls         Off
+
+      16   0x10   Memory allocation of buffers, etc.                  Off
+
+      32   0x20   Showing underflow, overflow and Dumping frame       On
+                 messages
+
+      64   0x40   Show viewport and image sizes                       Off
+
+     128   0x80   PWCX debugging                                      Off
+
+   For example, to trace the open() & read() functions, sum 8 + 4 = 12,
+   so you would supply trace=12 during insmod or modprobe. If
+   you want to turn the initialization and probing tracing off, set trace=0.
+   The default value for trace is 35 (0x23).
+
+
+
+Example:
+
+     # modprobe pwc size=cif fps=15 power_save=1
+
+The fbufs, mbufs and trace parameters are global and apply to all connected
+cameras. Each camera has its own set of buffers.
+
+size and fps only specify defaults when you open() the device; this is to
+accommodate some tools that don't set the size. You can change these
+settings after open() with the Video4Linux ioctl() calls. The default of
+defaults is QCIF size at 10 fps.
+
+The compression parameter is semiglobal; it sets the initial compression
+preference for all camera's, but this parameter can be set per camera with
+the VIDIOCPWCSCQUAL ioctl() call.
+
+All parameters are optional.
+
diff --git a/drivers/media/usb/pwc/pwc-ctrl.c b/drivers/media/usb/pwc/pwc-ctrl.c
new file mode 100644 (file)
index 0000000..1f506fd
--- /dev/null
@@ -0,0 +1,553 @@
+/* Driver for Philips webcam
+   Functions that send various control messages to the webcam, including
+   video modes.
+   (C) 1999-2003 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+   (C) 2011 Hans de Goede <hdegoede@redhat.com>
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/*
+   Changes
+   2001/08/03  Alvarado   Added methods for changing white balance and
+                         red/green gains
+ */
+
+/* Control functions for the cam; brightness, contrast, video mode, etc. */
+
+#ifdef __KERNEL__
+#include <asm/uaccess.h>
+#endif
+#include <asm/errno.h>
+
+#include "pwc.h"
+#include "pwc-kiara.h"
+#include "pwc-timon.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
+
+/* Selectors for status controls used only in this file */
+#define GET_STATUS_B00                         0x0B00
+#define SENSOR_TYPE_FORMATTER1                 0x0C00
+#define GET_STATUS_3000                                0x3000
+#define READ_RAW_Y_MEAN_FORMATTER              0x3100
+#define SET_POWER_SAVE_MODE_FORMATTER          0x3200
+#define MIRROR_IMAGE_FORMATTER                 0x3300
+#define LED_FORMATTER                          0x3400
+#define LOWLIGHT                               0x3500
+#define GET_STATUS_3600                                0x3600
+#define SENSOR_TYPE_FORMATTER2                 0x3700
+#define GET_STATUS_3800                                0x3800
+#define GET_STATUS_4000                                0x4000
+#define GET_STATUS_4100                                0x4100  /* Get */
+#define CTL_STATUS_4200                                0x4200  /* [GS] 1 */
+
+/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
+#define VIDEO_OUTPUT_CONTROL_FORMATTER         0x0100
+
+static const char *size2name[PSZ_MAX] =
+{
+       "subQCIF",
+       "QSIF",
+       "QCIF",
+       "SIF",
+       "CIF",
+       "VGA",
+};
+
+/********/
+
+/* Entries for the Nala (645/646) camera; the Nala doesn't have compression
+   preferences, so you either get compressed or non-compressed streams.
+
+   An alternate value of 0 means this mode is not available at all.
+ */
+
+#define PWC_FPS_MAX_NALA 8
+
+struct Nala_table_entry {
+       char alternate;                 /* USB alternate setting */
+       int compressed;                 /* Compressed yes/no */
+
+       unsigned char mode[3];          /* precomputed mode table */
+};
+
+static unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15, 20, 24 };
+
+static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
+{
+#include "pwc-nala.h"
+};
+
+/****************************************************************************/
+
+static int recv_control_msg(struct pwc_device *pdev,
+       u8 request, u16 value, int recv_count)
+{
+       int rc;
+
+       rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
+               request,
+               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+               value, pdev->vcinterface,
+               pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT);
+       if (rc < 0)
+               PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
+                         rc, request, value);
+       return rc;
+}
+
+static inline int send_video_command(struct pwc_device *pdev,
+       int index, const unsigned char *buf, int buflen)
+{
+       int rc;
+
+       memcpy(pdev->ctrl_buf, buf, buflen);
+
+       rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+                       SET_EP_STREAM_CTL,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       VIDEO_OUTPUT_CONTROL_FORMATTER, index,
+                       pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT);
+       if (rc >= 0)
+               memcpy(pdev->cmd_buf, buf, buflen);
+       else
+               PWC_ERROR("send_video_command error %d\n", rc);
+
+       return rc;
+}
+
+int send_control_msg(struct pwc_device *pdev,
+       u8 request, u16 value, void *buf, int buflen)
+{
+       return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
+                       request,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, pdev->vcinterface,
+                       buf, buflen, USB_CTRL_SET_TIMEOUT);
+}
+
+static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt,
+                              int frames, int *compression, int send_to_cam)
+{
+       int fps, ret = 0;
+       struct Nala_table_entry *pEntry;
+       int frames2frames[31] =
+       { /* closest match of framerate */
+          0,  0,  0,  0,  4,  /*  0-4  */
+          5,  5,  7,  7, 10,  /*  5-9  */
+         10, 10, 12, 12, 15,  /* 10-14 */
+         15, 15, 15, 20, 20,  /* 15-19 */
+         20, 20, 20, 24, 24,  /* 20-24 */
+         24, 24, 24, 24, 24,  /* 25-29 */
+         24                   /* 30    */
+       };
+       int frames2table[31] =
+       { 0, 0, 0, 0, 0, /*  0-4  */
+         1, 1, 1, 2, 2, /*  5-9  */
+         3, 3, 4, 4, 4, /* 10-14 */
+         5, 5, 5, 5, 5, /* 15-19 */
+         6, 6, 6, 6, 7, /* 20-24 */
+         7, 7, 7, 7, 7, /* 25-29 */
+         7              /* 30    */
+       };
+
+       if (size < 0 || size > PSZ_CIF)
+               return -EINVAL;
+       if (frames < 4)
+               frames = 4;
+       else if (frames > 25)
+               frames = 25;
+       frames = frames2frames[frames];
+       fps = frames2table[frames];
+       pEntry = &Nala_table[size][fps];
+       if (pEntry->alternate == 0)
+               return -EINVAL;
+
+       if (send_to_cam)
+               ret = send_video_command(pdev, pdev->vendpoint,
+                                        pEntry->mode, 3);
+       if (ret < 0)
+               return ret;
+
+       if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420)
+               pwc_dec1_init(pdev, pEntry->mode);
+
+       /* Set various parameters */
+       pdev->pixfmt = pixfmt;
+       pdev->vframes = frames;
+       pdev->valternate = pEntry->alternate;
+       pdev->width  = pwc_image_sizes[size][0];
+       pdev->height = pwc_image_sizes[size][1];
+       pdev->frame_size = (pdev->width * pdev->height * 3) / 2;
+       if (pEntry->compressed) {
+               if (pdev->release < 5) { /* 4 fold compression */
+                       pdev->vbandlength = 528;
+                       pdev->frame_size /= 4;
+               }
+               else {
+                       pdev->vbandlength = 704;
+                       pdev->frame_size /= 3;
+               }
+       }
+       else
+               pdev->vbandlength = 0;
+
+       /* Let pwc-if.c:isoc_init know we don't support higher compression */
+       *compression = 3;
+
+       return 0;
+}
+
+
+static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt,
+                               int frames, int *compression, int send_to_cam)
+{
+       const struct Timon_table_entry *pChoose;
+       int fps, ret = 0;
+
+       if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
+               return -EINVAL;
+       if (frames < 5)
+               frames = 5;
+       else if (size == PSZ_VGA && frames > 15)
+               frames = 15;
+       else if (frames > 30)
+               frames = 30;
+       fps = (frames / 5) - 1;
+
+       /* Find a supported framerate with progressively higher compression */
+       pChoose = NULL;
+       while (*compression <= 3) {
+               pChoose = &Timon_table[size][fps][*compression];
+               if (pChoose->alternate != 0)
+                       break;
+               (*compression)++;
+       }
+       if (pChoose == NULL || pChoose->alternate == 0)
+               return -ENOENT; /* Not supported. */
+
+       if (send_to_cam)
+               ret = send_video_command(pdev, pdev->vendpoint,
+                                        pChoose->mode, 13);
+       if (ret < 0)
+               return ret;
+
+       if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
+               pwc_dec23_init(pdev, pChoose->mode);
+
+       /* Set various parameters */
+       pdev->pixfmt = pixfmt;
+       pdev->vframes = (fps + 1) * 5;
+       pdev->valternate = pChoose->alternate;
+       pdev->width  = pwc_image_sizes[size][0];
+       pdev->height = pwc_image_sizes[size][1];
+       pdev->vbandlength = pChoose->bandlength;
+       if (pChoose->bandlength > 0)
+               pdev->frame_size = (pChoose->bandlength * pdev->height) / 4;
+       else
+               pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
+       return 0;
+}
+
+
+static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt,
+                               int frames, int *compression, int send_to_cam)
+{
+       const struct Kiara_table_entry *pChoose = NULL;
+       int fps, ret = 0;
+
+       if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
+               return -EINVAL;
+       if (frames < 5)
+               frames = 5;
+       else if (size == PSZ_VGA && frames > 15)
+               frames = 15;
+       else if (frames > 30)
+               frames = 30;
+       fps = (frames / 5) - 1;
+
+       /* Find a supported framerate with progressively higher compression */
+       while (*compression <= 3) {
+               pChoose = &Kiara_table[size][fps][*compression];
+               if (pChoose->alternate != 0)
+                       break;
+               (*compression)++;
+       }
+       if (pChoose == NULL || pChoose->alternate == 0)
+               return -ENOENT; /* Not supported. */
+
+       /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
+       if (send_to_cam)
+               ret = send_video_command(pdev, 4, pChoose->mode, 12);
+       if (ret < 0)
+               return ret;
+
+       if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
+               pwc_dec23_init(pdev, pChoose->mode);
+
+       /* All set and go */
+       pdev->pixfmt = pixfmt;
+       pdev->vframes = (fps + 1) * 5;
+       pdev->valternate = pChoose->alternate;
+       pdev->width  = pwc_image_sizes[size][0];
+       pdev->height = pwc_image_sizes[size][1];
+       pdev->vbandlength = pChoose->bandlength;
+       if (pdev->vbandlength > 0)
+               pdev->frame_size = (pdev->vbandlength * pdev->height) / 4;
+       else
+               pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
+       PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n",
+           pdev->frame_size, pdev->vframes, size, pdev->vbandlength);
+       return 0;
+}
+
+int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
+       int pixfmt, int frames, int *compression, int send_to_cam)
+{
+       int ret, size;
+
+       PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n",
+                      width, height, frames, pixfmt);
+       size = pwc_get_size(pdev, width, height);
+       PWC_TRACE("decode_size = %d.\n", size);
+
+       if (DEVICE_USE_CODEC1(pdev->type)) {
+               ret = set_video_mode_Nala(pdev, size, pixfmt, frames,
+                                         compression, send_to_cam);
+       } else if (DEVICE_USE_CODEC3(pdev->type)) {
+               ret = set_video_mode_Kiara(pdev, size, pixfmt, frames,
+                                          compression, send_to_cam);
+       } else {
+               ret = set_video_mode_Timon(pdev, size, pixfmt, frames,
+                                          compression, send_to_cam);
+       }
+       if (ret < 0) {
+               PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
+               return ret;
+       }
+       pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
+       PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height);
+       return 0;
+}
+
+static unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int index, unsigned int size)
+{
+       unsigned int i;
+
+       for (i = 0; i < PWC_FPS_MAX_NALA; i++) {
+               if (Nala_table[size][i].alternate) {
+                       if (index--==0) return Nala_fps_vector[i];
+               }
+       }
+       return 0;
+}
+
+static unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int index, unsigned int size)
+{
+       unsigned int i;
+
+       for (i = 0; i < PWC_FPS_MAX_KIARA; i++) {
+               if (Kiara_table[size][i][3].alternate) {
+                       if (index--==0) return Kiara_fps_vector[i];
+               }
+       }
+       return 0;
+}
+
+static unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int index, unsigned int size)
+{
+       unsigned int i;
+
+       for (i=0; i < PWC_FPS_MAX_TIMON; i++) {
+               if (Timon_table[size][i][3].alternate) {
+                       if (index--==0) return Timon_fps_vector[i];
+               }
+       }
+       return 0;
+}
+
+unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size)
+{
+       unsigned int ret;
+
+       if (DEVICE_USE_CODEC1(pdev->type)) {
+               ret = pwc_get_fps_Nala(pdev, index, size);
+
+       } else if (DEVICE_USE_CODEC3(pdev->type)) {
+               ret = pwc_get_fps_Kiara(pdev, index, size);
+
+       } else {
+               ret = pwc_get_fps_Timon(pdev, index, size);
+       }
+
+       return ret;
+}
+
+int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
+{
+       int ret;
+
+       ret = recv_control_msg(pdev, request, value, 1);
+       if (ret < 0)
+               return ret;
+
+       *data = pdev->ctrl_buf[0];
+       return 0;
+}
+
+int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
+{
+       int ret;
+
+       pdev->ctrl_buf[0] = data;
+       ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
+{
+       int ret;
+
+       ret = recv_control_msg(pdev, request, value, 1);
+       if (ret < 0)
+               return ret;
+
+       *data = ((s8 *)pdev->ctrl_buf)[0];
+       return 0;
+}
+
+int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
+{
+       int ret;
+
+       ret = recv_control_msg(pdev, request, value, 2);
+       if (ret < 0)
+               return ret;
+
+       *data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0];
+       return 0;
+}
+
+int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
+{
+       int ret;
+
+       pdev->ctrl_buf[0] = data & 0xff;
+       pdev->ctrl_buf[1] = data >> 8;
+       ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
+{
+       int ret;
+
+       ret = send_control_msg(pdev, SET_STATUS_CTL, value, NULL, 0);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+/* POWER */
+void pwc_camera_power(struct pwc_device *pdev, int power)
+{
+       int r;
+
+       if (!pdev->power_save)
+               return;
+
+       if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
+               return; /* Not supported by Nala or Timon < release 6 */
+
+       if (power)
+               pdev->ctrl_buf[0] = 0x00; /* active */
+       else
+               pdev->ctrl_buf[0] = 0xFF; /* power save */
+       r = send_control_msg(pdev, SET_STATUS_CTL,
+               SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1);
+       if (r < 0)
+               PWC_ERROR("Failed to power %s camera (%d)\n",
+                         power ? "on" : "off", r);
+}
+
+int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
+{
+       int r;
+
+       if (pdev->type < 730)
+               return 0;
+       on_value /= 100;
+       off_value /= 100;
+       if (on_value < 0)
+               on_value = 0;
+       if (on_value > 0xff)
+               on_value = 0xff;
+       if (off_value < 0)
+               off_value = 0;
+       if (off_value > 0xff)
+               off_value = 0xff;
+
+       pdev->ctrl_buf[0] = on_value;
+       pdev->ctrl_buf[1] = off_value;
+
+       r = send_control_msg(pdev,
+               SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2);
+       if (r < 0)
+               PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
+
+       return r;
+}
+
+#ifdef CONFIG_USB_PWC_DEBUG
+int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
+{
+       int ret = -1, request;
+
+       if (pdev->type < 675)
+               request = SENSOR_TYPE_FORMATTER1;
+       else if (pdev->type < 730)
+               return -1; /* The Vesta series doesn't have this call */
+       else
+               request = SENSOR_TYPE_FORMATTER2;
+
+       ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1);
+       if (ret < 0)
+               return ret;
+       if (pdev->type < 675)
+               *sensor = pdev->ctrl_buf[0] | 0x100;
+       else
+               *sensor = pdev->ctrl_buf[0];
+       return 0;
+}
+#endif
diff --git a/drivers/media/usb/pwc/pwc-dec1.c b/drivers/media/usb/pwc/pwc-dec1.c
new file mode 100644 (file)
index 0000000..e899036
--- /dev/null
@@ -0,0 +1,32 @@
+/* Linux driver for Philips webcam
+   Decompression for chipset version 1
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#include "pwc.h"
+
+void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd)
+{
+       struct pwc_dec1_private *pdec = &pdev->dec1;
+
+       pdec->version = pdev->release;
+}
diff --git a/drivers/media/usb/pwc/pwc-dec1.h b/drivers/media/usb/pwc/pwc-dec1.h
new file mode 100644 (file)
index 0000000..c565ef8
--- /dev/null
@@ -0,0 +1,39 @@
+/* Linux driver for Philips webcam
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef PWC_DEC1_H
+#define PWC_DEC1_H
+
+#include <linux/mutex.h>
+
+struct pwc_device;
+
+struct pwc_dec1_private
+{
+       int version;
+};
+
+void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd);
+
+#endif
diff --git a/drivers/media/usb/pwc/pwc-dec23.c b/drivers/media/usb/pwc/pwc-dec23.c
new file mode 100644 (file)
index 0000000..3792fed
--- /dev/null
@@ -0,0 +1,691 @@
+/* Linux driver for Philips webcam
+   Decompression for chipset version 2 et 3
+   (C) 2004-2006  Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+#include "pwc-timon.h"
+#include "pwc-kiara.h"
+#include "pwc-dec23.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+
+/*
+ * USE_LOOKUP_TABLE_TO_CLAMP
+ *   0: use a C version of this tests:  {  a<0?0:(a>255?255:a) }
+ *   1: use a faster lookup table for cpu with a big cache (intel)
+ */
+#define USE_LOOKUP_TABLE_TO_CLAMP      1
+/*
+ * UNROLL_LOOP_FOR_COPYING_BLOCK
+ *   0: use a loop for a smaller code (but little slower)
+ *   1: when unrolling the loop, gcc produces some faster code (perhaps only
+ *   valid for intel processor class). Activating this option, automaticaly
+ *   activate USE_LOOKUP_TABLE_TO_CLAMP
+ */
+#define UNROLL_LOOP_FOR_COPY           1
+#if UNROLL_LOOP_FOR_COPY
+# undef USE_LOOKUP_TABLE_TO_CLAMP
+# define USE_LOOKUP_TABLE_TO_CLAMP 1
+#endif
+
+static void build_subblock_pattern(struct pwc_dec23_private *pdec)
+{
+       static const unsigned int initial_values[12] = {
+               -0x526500, -0x221200, 0x221200, 0x526500,
+                          -0x3de200, 0x3de200,
+               -0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480,
+                          -0x12c200, 0x12c200
+
+       };
+       static const unsigned int values_derivated[12] = {
+               0xa4ca, 0x4424, -0x4424, -0xa4ca,
+                       0x7bc4, -0x7bc4,
+               0xdb69, 0x5aba, -0x5aba, -0xdb69,
+                       0x2584, -0x2584
+       };
+       unsigned int temp_values[12];
+       int i, j;
+
+       memcpy(temp_values, initial_values, sizeof(initial_values));
+       for (i = 0; i < 256; i++) {
+               for (j = 0; j < 12; j++) {
+                       pdec->table_subblock[i][j] = temp_values[j];
+                       temp_values[j] += values_derivated[j];
+               }
+       }
+}
+
+static void build_bit_powermask_table(struct pwc_dec23_private *pdec)
+{
+       unsigned char *p;
+       unsigned int bit, byte, mask, val;
+       unsigned int bitpower = 1;
+
+       for (bit = 0; bit < 8; bit++) {
+               mask = bitpower - 1;
+               p = pdec->table_bitpowermask[bit];
+               for (byte = 0; byte < 256; byte++) {
+                       val = (byte & mask);
+                       if (byte & bitpower)
+                               val = -val;
+                       *p++ = val;
+               }
+               bitpower<<=1;
+       }
+}
+
+
+static void build_table_color(const unsigned int romtable[16][8],
+                             unsigned char p0004[16][1024],
+                             unsigned char p8004[16][256])
+{
+       int compression_mode, j, k, bit, pw;
+       unsigned char *p0, *p8;
+       const unsigned int *r;
+
+       /* We have 16 compressions tables */
+       for (compression_mode = 0; compression_mode < 16; compression_mode++) {
+               p0 = p0004[compression_mode];
+               p8 = p8004[compression_mode];
+               r  = romtable[compression_mode];
+
+               for (j = 0; j < 8; j++, r++, p0 += 128) {
+
+                       for (k = 0; k < 16; k++) {
+                               if (k == 0)
+                                       bit = 1;
+                               else if (k >= 1 && k < 3)
+                                       bit = (r[0] >> 15) & 7;
+                               else if (k >= 3 && k < 6)
+                                       bit = (r[0] >> 12) & 7;
+                               else if (k >= 6 && k < 10)
+                                       bit = (r[0] >> 9) & 7;
+                               else if (k >= 10 && k < 13)
+                                       bit = (r[0] >> 6) & 7;
+                               else if (k >= 13 && k < 15)
+                                       bit = (r[0] >> 3) & 7;
+                               else
+                                       bit = (r[0]) & 7;
+                               if (k == 0)
+                                       *p8++ = 8;
+                               else
+                                       *p8++ = j - bit;
+                               *p8++ = bit;
+
+                               pw = 1 << bit;
+                               p0[k + 0x00] = (1 * pw) + 0x80;
+                               p0[k + 0x10] = (2 * pw) + 0x80;
+                               p0[k + 0x20] = (3 * pw) + 0x80;
+                               p0[k + 0x30] = (4 * pw) + 0x80;
+                               p0[k + 0x40] = (-1 * pw) + 0x80;
+                               p0[k + 0x50] = (-2 * pw) + 0x80;
+                               p0[k + 0x60] = (-3 * pw) + 0x80;
+                               p0[k + 0x70] = (-4 * pw) + 0x80;
+                       }       /* end of for (k=0; k<16; k++, p8++) */
+               }       /* end of for (j=0; j<8; j++ , table++) */
+       } /* end of foreach compression_mode */
+}
+
+/*
+ *
+ */
+static void fill_table_dc00_d800(struct pwc_dec23_private *pdec)
+{
+#define SCALEBITS 15
+#define ONE_HALF  (1UL << (SCALEBITS - 1))
+       int i;
+       unsigned int offset1 = ONE_HALF;
+       unsigned int offset2 = 0x0000;
+
+       for (i=0; i<256; i++) {
+               pdec->table_dc00[i] = offset1 & ~(ONE_HALF);
+               pdec->table_d800[i] = offset2;
+
+               offset1 += 0x7bc4;
+               offset2 += 0x7bc4;
+       }
+}
+
+/*
+ * To decode the stream:
+ *   if look_bits(2) == 0:     # op == 2 in the lookup table
+ *      skip_bits(2)
+ *      end of the stream
+ *   elif look_bits(3) == 7:   # op == 1 in the lookup table
+ *      skip_bits(3)
+ *      yyyy = get_bits(4)
+ *      xxxx = get_bits(8)
+ *   else:                     # op == 0 in the lookup table
+ *      skip_bits(x)
+ *
+ * For speedup processing, we build a lookup table and we takes the first 6 bits.
+ *
+ * struct {
+ *   unsigned char op;     // operation to execute
+ *   unsigned char bits;    // bits use to perform operation
+ *   unsigned char offset1; // offset to add to access in the table_0004 % 16
+ *   unsigned char offset2; // offset to add to access in the table_0004
+ * }
+ *
+ * How to build this table ?
+ *   op == 2 when (i%4)==0
+ *   op == 1 when (i%8)==7
+ *   op == 0 otherwise
+ *
+ */
+static const unsigned char hash_table_ops[64*4] = {
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x10,
+       0x00, 0x06, 0x01, 0x30,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x01, 0x20,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x50,
+       0x00, 0x05, 0x02, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x03, 0x00,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x10,
+       0x00, 0x06, 0x02, 0x10,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x01, 0x60,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x50,
+       0x00, 0x05, 0x02, 0x40,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x03, 0x40,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x10,
+       0x00, 0x06, 0x01, 0x70,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x01, 0x20,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x50,
+       0x00, 0x05, 0x02, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x03, 0x00,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x10,
+       0x00, 0x06, 0x02, 0x50,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x01, 0x60,
+       0x01, 0x00, 0x00, 0x00,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x00,
+       0x00, 0x04, 0x01, 0x50,
+       0x00, 0x05, 0x02, 0x40,
+       0x02, 0x00, 0x00, 0x00,
+       0x00, 0x03, 0x01, 0x40,
+       0x00, 0x05, 0x03, 0x40,
+       0x01, 0x00, 0x00, 0x00
+};
+
+/*
+ *
+ */
+static const unsigned int MulIdx[16][16] = {
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+       {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,},
+       {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,},
+       {4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,},
+       {6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,},
+       {4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,},
+       {1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,},
+       {0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,},
+       {0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,},
+       {1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,},
+       {7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,},
+       {4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,},
+       {7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,},
+       {1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,},
+       {1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,},
+       {10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10}
+};
+
+#if USE_LOOKUP_TABLE_TO_CLAMP
+#define MAX_OUTER_CROP_VALUE   (512)
+static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];
+#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)])
+#else
+#define CLAMP(x) ((x)>255?255:((x)<0?0:x))
+#endif
+
+
+/* If the type or the command change, we rebuild the lookup table */
+void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd)
+{
+       int flags, version, shift, i;
+       struct pwc_dec23_private *pdec = &pdev->dec23;
+
+       mutex_init(&pdec->lock);
+
+       if (pdec->last_cmd_valid && pdec->last_cmd == cmd[2])
+               return;
+
+       if (DEVICE_USE_CODEC3(pdev->type)) {
+               flags = cmd[2] & 0x18;
+               if (flags == 8)
+                       pdec->nbits = 7;        /* More bits, mean more bits to encode the stream, but better quality */
+               else if (flags == 0x10)
+                       pdec->nbits = 8;
+               else
+                       pdec->nbits = 6;
+
+               version = cmd[2] >> 5;
+               build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
+               build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
+
+       } else {
+
+               flags = cmd[2] & 6;
+               if (flags == 2)
+                       pdec->nbits = 7;
+               else if (flags == 4)
+                       pdec->nbits = 8;
+               else
+                       pdec->nbits = 6;
+
+               version = cmd[2] >> 3;
+               build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
+               build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
+       }
+
+       /* Informations can be coded on a variable number of bits but never less than 8 */
+       shift = 8 - pdec->nbits;
+       pdec->scalebits = SCALEBITS - shift;
+       pdec->nbitsmask = 0xFF >> shift;
+
+       fill_table_dc00_d800(pdec);
+       build_subblock_pattern(pdec);
+       build_bit_powermask_table(pdec);
+
+#if USE_LOOKUP_TABLE_TO_CLAMP
+       /* Build the static table to clamp value [0-255] */
+       for (i=0;i<MAX_OUTER_CROP_VALUE;i++)
+               pwc_crop_table[i] = 0;
+       for (i=0; i<256; i++)
+               pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i;
+       for (i=0; i<MAX_OUTER_CROP_VALUE; i++)
+               pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255;
+#endif
+
+       pdec->last_cmd = cmd[2];
+       pdec->last_cmd_valid = 1;
+}
+
+/*
+ * Copy the 4x4 image block to Y plane buffer
+ */
+static void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+       const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+       const int *c = src;
+       unsigned char *d = dst;
+
+       *d++ = cm[c[0] >> scalebits];
+       *d++ = cm[c[1] >> scalebits];
+       *d++ = cm[c[2] >> scalebits];
+       *d++ = cm[c[3] >> scalebits];
+
+       d = dst + bytes_per_line;
+       *d++ = cm[c[4] >> scalebits];
+       *d++ = cm[c[5] >> scalebits];
+       *d++ = cm[c[6] >> scalebits];
+       *d++ = cm[c[7] >> scalebits];
+
+       d = dst + bytes_per_line*2;
+       *d++ = cm[c[8] >> scalebits];
+       *d++ = cm[c[9] >> scalebits];
+       *d++ = cm[c[10] >> scalebits];
+       *d++ = cm[c[11] >> scalebits];
+
+       d = dst + bytes_per_line*3;
+       *d++ = cm[c[12] >> scalebits];
+       *d++ = cm[c[13] >> scalebits];
+       *d++ = cm[c[14] >> scalebits];
+       *d++ = cm[c[15] >> scalebits];
+#else
+       int i;
+       const int *c = src;
+       unsigned char *d = dst;
+       for (i = 0; i < 4; i++, c++)
+               *d++ = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line;
+       for (i = 0; i < 4; i++, c++)
+               *d++ = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line*2;
+       for (i = 0; i < 4; i++, c++)
+               *d++ = CLAMP((*c) >> scalebits);
+
+       d = dst + bytes_per_line*3;
+       for (i = 0; i < 4; i++, c++)
+               *d++ = CLAMP((*c) >> scalebits);
+#endif
+}
+
+/*
+ * Copy the 4x4 image block to a CrCb plane buffer
+ *
+ */
+static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+       /* Unroll all loops */
+       const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+       const int *c = src;
+       unsigned char *d = dst;
+
+       *d++ = cm[c[0] >> scalebits];
+       *d++ = cm[c[4] >> scalebits];
+       *d++ = cm[c[1] >> scalebits];
+       *d++ = cm[c[5] >> scalebits];
+       *d++ = cm[c[2] >> scalebits];
+       *d++ = cm[c[6] >> scalebits];
+       *d++ = cm[c[3] >> scalebits];
+       *d++ = cm[c[7] >> scalebits];
+
+       d = dst + bytes_per_line;
+       *d++ = cm[c[12] >> scalebits];
+       *d++ = cm[c[8] >> scalebits];
+       *d++ = cm[c[13] >> scalebits];
+       *d++ = cm[c[9] >> scalebits];
+       *d++ = cm[c[14] >> scalebits];
+       *d++ = cm[c[10] >> scalebits];
+       *d++ = cm[c[15] >> scalebits];
+       *d++ = cm[c[11] >> scalebits];
+#else
+       int i;
+       const int *c1 = src;
+       const int *c2 = src + 4;
+       unsigned char *d = dst;
+
+       for (i = 0; i < 4; i++, c1++, c2++) {
+               *d++ = CLAMP((*c1) >> scalebits);
+               *d++ = CLAMP((*c2) >> scalebits);
+       }
+       c1 = src + 12;
+       d = dst + bytes_per_line;
+       for (i = 0; i < 4; i++, c1++, c2++) {
+               *d++ = CLAMP((*c1) >> scalebits);
+               *d++ = CLAMP((*c2) >> scalebits);
+       }
+#endif
+}
+
+/*
+ * To manage the stream, we keep bits in a 32 bits register.
+ * fill_nbits(n): fill the reservoir with at least n bits
+ * skip_bits(n): discard n bits from the reservoir
+ * get_bits(n): fill the reservoir, returns the first n bits and discard the
+ *              bits from the reservoir.
+ * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir
+ *                 contains at least n bits. bits returned is discarded.
+ */
+#define fill_nbits(pdec, nbits_wanted) do { \
+   while (pdec->nbits_in_reservoir<(nbits_wanted)) \
+    { \
+      pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \
+      pdec->nbits_in_reservoir += 8; \
+    } \
+}  while(0);
+
+#define skip_nbits(pdec, nbits_to_skip) do { \
+   pdec->reservoir >>= (nbits_to_skip); \
+   pdec->nbits_in_reservoir -= (nbits_to_skip); \
+}  while(0);
+
+#define get_nbits(pdec, nbits_wanted, result) do { \
+   fill_nbits(pdec, nbits_wanted); \
+   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
+   skip_nbits(pdec, nbits_wanted); \
+}  while(0);
+
+#define __get_nbits(pdec, nbits_wanted, result) do { \
+   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
+   skip_nbits(pdec, nbits_wanted); \
+}  while(0);
+
+#define look_nbits(pdec, nbits_wanted) \
+   ((pdec->reservoir) & ((1U<<(nbits_wanted))-1))
+
+/*
+ * Decode a 4x4 pixel block
+ */
+static void decode_block(struct pwc_dec23_private *pdec,
+                        const unsigned char *ptable0004,
+                        const unsigned char *ptable8004)
+{
+       unsigned int primary_color;
+       unsigned int channel_v, offset1, op;
+       int i;
+
+       fill_nbits(pdec, 16);
+       __get_nbits(pdec, pdec->nbits, primary_color);
+
+       if (look_nbits(pdec,2) == 0) {
+               skip_nbits(pdec, 2);
+               /* Very simple, the color is the same for all pixels of the square */
+               for (i = 0; i < 16; i++)
+                       pdec->temp_colors[i] = pdec->table_dc00[primary_color];
+
+               return;
+       }
+
+       /* This block is encoded with small pattern */
+       for (i = 0; i < 16; i++)
+               pdec->temp_colors[i] = pdec->table_d800[primary_color];
+
+       __get_nbits(pdec, 3, channel_v);
+       channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2);
+
+       ptable0004 += (channel_v * 128);
+       ptable8004 += (channel_v * 32);
+
+       offset1 = 0;
+       do
+       {
+               unsigned int htable_idx, rows = 0;
+               const unsigned int *block;
+
+               /* [  zzzz y x x ]
+                *     xx == 00 :=> end of the block def, remove the two bits from the stream
+                *    yxx == 111
+                *    yxx == any other value
+                *
+                */
+               fill_nbits(pdec, 16);
+               htable_idx = look_nbits(pdec, 6);
+               op = hash_table_ops[htable_idx * 4];
+
+               if (op == 2) {
+                       skip_nbits(pdec, 2);
+
+               } else if (op == 1) {
+                       /* 15bits [ xxxx xxxx yyyy 111 ]
+                        * yyy => offset in the table8004
+                        * xxx => offset in the tabled004 (tree)
+                        */
+                       unsigned int mask, shift;
+                       unsigned int nbits, col1;
+                       unsigned int yyyy;
+
+                       skip_nbits(pdec, 3);
+                       /* offset1 += yyyy */
+                       __get_nbits(pdec, 4, yyyy);
+                       offset1 += 1 + yyyy;
+                       offset1 &= 0x0F;
+                       nbits = ptable8004[offset1 * 2];
+
+                       /* col1 = xxxx xxxx */
+                       __get_nbits(pdec, nbits+1, col1);
+
+                       /* Bit mask table */
+                       mask = pdec->table_bitpowermask[nbits][col1];
+                       shift = ptable8004[offset1 * 2 + 1];
+                       rows = ((mask << shift) + 0x80) & 0xFF;
+
+                       block = pdec->table_subblock[rows];
+                       for (i = 0; i < 16; i++)
+                               pdec->temp_colors[i] += block[MulIdx[offset1][i]];
+
+               } else {
+                       /* op == 0
+                        * offset1 is coded on 3 bits
+                        */
+                       unsigned int shift;
+
+                       offset1 += hash_table_ops [htable_idx * 4 + 2];
+                       offset1 &= 0x0F;
+
+                       rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3]];
+                       block = pdec->table_subblock[rows];
+                       for (i = 0; i < 16; i++)
+                               pdec->temp_colors[i] += block[MulIdx[offset1][i]];
+
+                       shift = hash_table_ops[htable_idx * 4 + 1];
+                       skip_nbits(pdec, shift);
+               }
+
+       } while (op != 2);
+
+}
+
+static void DecompressBand23(struct pwc_dec23_private *pdec,
+                            const unsigned char *rawyuv,
+                            unsigned char *planar_y,
+                            unsigned char *planar_u,
+                            unsigned char *planar_v,
+                            unsigned int   compressed_image_width,
+                            unsigned int   real_image_width)
+{
+       int compression_index, nblocks;
+       const unsigned char *ptable0004;
+       const unsigned char *ptable8004;
+
+       pdec->reservoir = 0;
+       pdec->nbits_in_reservoir = 0;
+       pdec->stream = rawyuv + 1;      /* The first byte of the stream is skipped */
+
+       get_nbits(pdec, 4, compression_index);
+
+       /* pass 1: uncompress Y component */
+       nblocks = compressed_image_width / 4;
+
+       ptable0004 = pdec->table_0004_pass1[compression_index];
+       ptable8004 = pdec->table_8004_pass1[compression_index];
+
+       /* Each block decode a square of 4x4 */
+       while (nblocks) {
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits);
+               planar_y += 4;
+               nblocks--;
+       }
+
+       /* pass 2: uncompress UV component */
+       nblocks = compressed_image_width / 8;
+
+       ptable0004 = pdec->table_0004_pass2[compression_index];
+       ptable8004 = pdec->table_8004_pass2[compression_index];
+
+       /* Each block decode a square of 4x4 */
+       while (nblocks) {
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits);
+
+               decode_block(pdec, ptable0004, ptable8004);
+               copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits);
+
+               planar_v += 8;
+               planar_u += 8;
+               nblocks -= 2;
+       }
+
+}
+
+/**
+ *
+ * Uncompress a pwc23 buffer.
+ *
+ * src: raw data
+ * dst: image output
+ */
+void pwc_dec23_decompress(struct pwc_device *pdev,
+                         const void *src,
+                         void *dst)
+{
+       int bandlines_left, bytes_per_block;
+       struct pwc_dec23_private *pdec = &pdev->dec23;
+
+       /* YUV420P image format */
+       unsigned char *pout_planar_y;
+       unsigned char *pout_planar_u;
+       unsigned char *pout_planar_v;
+       unsigned int   plane_size;
+
+       mutex_lock(&pdec->lock);
+
+       bandlines_left = pdev->height / 4;
+       bytes_per_block = pdev->width * 4;
+       plane_size = pdev->height * pdev->width;
+
+       pout_planar_y = dst;
+       pout_planar_u = dst + plane_size;
+       pout_planar_v = dst + plane_size + plane_size / 4;
+
+       while (bandlines_left--) {
+               DecompressBand23(pdec, src,
+                                pout_planar_y, pout_planar_u, pout_planar_v,
+                                pdev->width, pdev->width);
+               src += pdev->vbandlength;
+               pout_planar_y += bytes_per_block;
+               pout_planar_u += pdev->width;
+               pout_planar_v += pdev->width;
+       }
+       mutex_unlock(&pdec->lock);
+}
diff --git a/drivers/media/usb/pwc/pwc-dec23.h b/drivers/media/usb/pwc/pwc-dec23.h
new file mode 100644 (file)
index 0000000..c655b1c
--- /dev/null
@@ -0,0 +1,61 @@
+/* Linux driver for Philips webcam
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef PWC_DEC23_H
+#define PWC_DEC23_H
+
+struct pwc_device;
+
+struct pwc_dec23_private
+{
+       struct mutex lock;
+
+       unsigned char last_cmd, last_cmd_valid;
+
+  unsigned int scalebits;
+  unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */
+
+  unsigned int reservoir;
+  unsigned int nbits_in_reservoir;
+
+  const unsigned char *stream;
+  int temp_colors[16];
+
+  unsigned char table_0004_pass1[16][1024];
+  unsigned char table_0004_pass2[16][1024];
+  unsigned char table_8004_pass1[16][256];
+  unsigned char table_8004_pass2[16][256];
+  unsigned int  table_subblock[256][12];
+
+  unsigned char table_bitpowermask[8][256];
+  unsigned int  table_d800[256];
+  unsigned int  table_dc00[256];
+
+};
+
+void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd);
+void pwc_dec23_decompress(struct pwc_device *pdev,
+                         const void *src,
+                         void *dst);
+#endif
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
new file mode 100644 (file)
index 0000000..de7c7ba
--- /dev/null
@@ -0,0 +1,1165 @@
+/* Linux driver for Philips webcam
+   USB and Video4Linux interface part.
+   (C) 1999-2004 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+   (C) 2011 Hans de Goede <hdegoede@redhat.com>
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+/*
+   This code forms the interface between the USB layers and the Philips
+   specific stuff. Some adanved stuff of the driver falls under an
+   NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
+   is thus not distributed in source form. The binary pwcx.o module
+   contains the code that falls under the NDA.
+
+   In case you're wondering: 'pwc' stands for "Philips WebCam", but
+   I really didn't want to type 'philips_web_cam' every time (I'm lazy as
+   any Linux kernel hacker, but I don't like uncomprehensible abbreviations
+   without explanation).
+
+   Oh yes, convention: to disctinguish between all the various pointers to
+   device-structures, I use these names for the pointer variables:
+   udev: struct usb_device *
+   vdev: struct video_device (member of pwc_dev)
+   pdev: struct pwc_devive *
+*/
+
+/* Contributors:
+   - Alvarado: adding whitebalance code
+   - Alistar Moire: QuickCam 3000 Pro device/product ID
+   - Tony Hoyle: Creative Labs Webcam 5 device/product ID
+   - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
+   - Jk Fang: Sotec Afina Eye ID
+   - Xavier Roche: QuickCam Pro 4000 ID
+   - Jens Knudsen: QuickCam Zoom ID
+   - J. Debert: QuickCam for Notebooks ID
+   - Pham Thanh Nam: webcam snapshot button as an event input device
+*/
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+#include <linux/usb/input.h>
+#endif
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <linux/kernel.h>              /* simple_strtol() */
+
+#include "pwc.h"
+#include "pwc-kiara.h"
+#include "pwc-timon.h"
+#include "pwc-dec23.h"
+#include "pwc-dec1.h"
+
+/* Function prototypes and driver templates */
+
+/* hotplug device table support */
+static const struct usb_device_id pwc_device_table [] = {
+       { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */
+       { USB_DEVICE(0x0471, 0x0303) },
+       { USB_DEVICE(0x0471, 0x0304) },
+       { USB_DEVICE(0x0471, 0x0307) },
+       { USB_DEVICE(0x0471, 0x0308) },
+       { USB_DEVICE(0x0471, 0x030C) },
+       { USB_DEVICE(0x0471, 0x0310) },
+       { USB_DEVICE(0x0471, 0x0311) }, /* Philips ToUcam PRO II */
+       { USB_DEVICE(0x0471, 0x0312) },
+       { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */
+       { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */
+       { USB_DEVICE(0x069A, 0x0001) }, /* Askey */
+       { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */
+       { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */
+       { USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */
+       { USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom (old model) */
+       { USB_DEVICE(0x046D, 0x08B4) }, /* Logitech QuickCam Zoom (new model) */
+       { USB_DEVICE(0x046D, 0x08B5) }, /* Logitech QuickCam Orbit/Sphere */
+       { USB_DEVICE(0x046D, 0x08B6) }, /* Cisco VT Camera */
+       { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech ViewPort AV 100 */
+       { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */
+       { USB_DEVICE(0x055D, 0x9000) }, /* Samsung MPC-C10 */
+       { USB_DEVICE(0x055D, 0x9001) }, /* Samsung MPC-C30 */
+       { USB_DEVICE(0x055D, 0x9002) }, /* Samsung SNC-35E (Ver3.0) */
+       { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */
+       { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */
+       { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */
+       { USB_DEVICE(0x06BE, 0x8116) }, /* new Afina Eye */
+       { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */
+       { USB_DEVICE(0x0d81, 0x1900) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, pwc_device_table);
+
+static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id);
+static void usb_pwc_disconnect(struct usb_interface *intf);
+static void pwc_isoc_cleanup(struct pwc_device *pdev);
+
+static struct usb_driver pwc_driver = {
+       .name =                 "Philips webcam",       /* name */
+       .id_table =             pwc_device_table,
+       .probe =                usb_pwc_probe,          /* probe() */
+       .disconnect =           usb_pwc_disconnect,     /* disconnect() */
+};
+
+#define MAX_DEV_HINTS  20
+#define MAX_ISOC_ERRORS        20
+
+#ifdef CONFIG_USB_PWC_DEBUG
+       int pwc_trace = PWC_DEBUG_LEVEL;
+#endif
+static int power_save = -1;
+static int leds[2] = { 100, 0 };
+
+/***/
+
+static const struct v4l2_file_operations pwc_fops = {
+       .owner =        THIS_MODULE,
+       .open =         v4l2_fh_open,
+       .release =      vb2_fop_release,
+       .read =         vb2_fop_read,
+       .poll =         vb2_fop_poll,
+       .mmap =         vb2_fop_mmap,
+       .unlocked_ioctl = video_ioctl2,
+};
+static struct video_device pwc_template = {
+       .name =         "Philips Webcam",       /* Filled in later */
+       .release =      video_device_release_empty,
+       .fops =         &pwc_fops,
+       .ioctl_ops =    &pwc_ioctl_ops,
+};
+
+/***************************************************************************/
+/* Private functions */
+
+struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev)
+{
+       unsigned long flags = 0;
+       struct pwc_frame_buf *buf = NULL;
+
+       spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
+       if (list_empty(&pdev->queued_bufs))
+               goto leave;
+
+       buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf, list);
+       list_del(&buf->list);
+leave:
+       spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
+       return buf;
+}
+
+static void pwc_snapshot_button(struct pwc_device *pdev, int down)
+{
+       if (down) {
+               PWC_TRACE("Snapshot button pressed.\n");
+       } else {
+               PWC_TRACE("Snapshot button released.\n");
+       }
+
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+       if (pdev->button_dev) {
+               input_report_key(pdev->button_dev, KEY_CAMERA, down);
+               input_sync(pdev->button_dev);
+       }
+#endif
+}
+
+static void pwc_frame_complete(struct pwc_device *pdev)
+{
+       struct pwc_frame_buf *fbuf = pdev->fill_buf;
+
+       /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
+          frames on the USB wire after an exposure change. This conditition is
+          however detected  in the cam and a bit is set in the header.
+          */
+       if (pdev->type == 730) {
+               unsigned char *ptr = (unsigned char *)fbuf->data;
+
+               if (ptr[1] == 1 && ptr[0] & 0x10) {
+                       PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n");
+                       pdev->drop_frames += 2;
+               }
+               if ((ptr[0] ^ pdev->vmirror) & 0x01) {
+                       pwc_snapshot_button(pdev, ptr[0] & 0x01);
+               }
+               if ((ptr[0] ^ pdev->vmirror) & 0x02) {
+                       if (ptr[0] & 0x02)
+                               PWC_TRACE("Image is mirrored.\n");
+                       else
+                               PWC_TRACE("Image is normal.\n");
+               }
+               pdev->vmirror = ptr[0] & 0x03;
+               /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
+                  after a short frame; this condition is filtered out specifically. A 4 byte
+                  frame doesn't make sense anyway.
+                  So we get either this sequence:
+                  drop_bit set -> 4 byte frame -> short frame -> good frame
+                  Or this one:
+                  drop_bit set -> short frame -> good frame
+                  So we drop either 3 or 2 frames in all!
+                  */
+               if (fbuf->filled == 4)
+                       pdev->drop_frames++;
+       } else if (pdev->type == 740 || pdev->type == 720) {
+               unsigned char *ptr = (unsigned char *)fbuf->data;
+               if ((ptr[0] ^ pdev->vmirror) & 0x01) {
+                       pwc_snapshot_button(pdev, ptr[0] & 0x01);
+               }
+               pdev->vmirror = ptr[0] & 0x03;
+       }
+
+       /* In case we were instructed to drop the frame, do so silently. */
+       if (pdev->drop_frames > 0) {
+               pdev->drop_frames--;
+       } else {
+               /* Check for underflow first */
+               if (fbuf->filled < pdev->frame_total_size) {
+                       PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
+                                      " discarded.\n", fbuf->filled);
+               } else {
+                       fbuf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
+                       fbuf->vb.v4l2_buf.sequence = pdev->vframe_count;
+                       vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+                       pdev->fill_buf = NULL;
+                       pdev->vsync = 0;
+               }
+       } /* !drop_frames */
+       pdev->vframe_count++;
+}
+
+/* This gets called for the Isochronous pipe (video). This is done in
+ * interrupt time, so it has to be fast, not crash, and not stall. Neat.
+ */
+static void pwc_isoc_handler(struct urb *urb)
+{
+       struct pwc_device *pdev = (struct pwc_device *)urb->context;
+       int i, fst, flen;
+       unsigned char *iso_buf = NULL;
+
+       if (urb->status == -ENOENT || urb->status == -ECONNRESET ||
+           urb->status == -ESHUTDOWN) {
+               PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
+               return;
+       }
+
+       if (pdev->fill_buf == NULL)
+               pdev->fill_buf = pwc_get_next_fill_buf(pdev);
+
+       if (urb->status != 0) {
+               const char *errmsg;
+
+               errmsg = "Unknown";
+               switch(urb->status) {
+                       case -ENOSR:            errmsg = "Buffer error (overrun)"; break;
+                       case -EPIPE:            errmsg = "Stalled (device not responding)"; break;
+                       case -EOVERFLOW:        errmsg = "Babble (bad cable?)"; break;
+                       case -EPROTO:           errmsg = "Bit-stuff error (bad cable?)"; break;
+                       case -EILSEQ:           errmsg = "CRC/Timeout (could be anything)"; break;
+                       case -ETIME:            errmsg = "Device does not respond"; break;
+               }
+               PWC_ERROR("pwc_isoc_handler() called with status %d [%s].\n",
+                         urb->status, errmsg);
+               /* Give up after a number of contiguous errors */
+               if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
+               {
+                       PWC_ERROR("Too many ISOC errors, bailing out.\n");
+                       if (pdev->fill_buf) {
+                               vb2_buffer_done(&pdev->fill_buf->vb,
+                                               VB2_BUF_STATE_ERROR);
+                               pdev->fill_buf = NULL;
+                       }
+               }
+               pdev->vsync = 0; /* Drop the current frame */
+               goto handler_end;
+       }
+
+       /* Reset ISOC error counter. We did get here, after all. */
+       pdev->visoc_errors = 0;
+
+       /* vsync: 0 = don't copy data
+                 1 = sync-hunt
+                 2 = synched
+        */
+       /* Compact data */
+       for (i = 0; i < urb->number_of_packets; i++) {
+               fst  = urb->iso_frame_desc[i].status;
+               flen = urb->iso_frame_desc[i].actual_length;
+               iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+               if (fst != 0) {
+                       PWC_ERROR("Iso frame %d has error %d\n", i, fst);
+                       continue;
+               }
+               if (flen > 0 && pdev->vsync) {
+                       struct pwc_frame_buf *fbuf = pdev->fill_buf;
+
+                       if (pdev->vsync == 1) {
+                               do_gettimeofday(&fbuf->vb.v4l2_buf.timestamp);
+                               pdev->vsync = 2;
+                       }
+
+                       if (flen + fbuf->filled > pdev->frame_total_size) {
+                               PWC_ERROR("Frame overflow (%d > %d)\n",
+                                         flen + fbuf->filled,
+                                         pdev->frame_total_size);
+                               pdev->vsync = 0; /* Let's wait for an EOF */
+                       } else {
+                               memcpy(fbuf->data + fbuf->filled, iso_buf,
+                                      flen);
+                               fbuf->filled += flen;
+                       }
+               }
+               if (flen < pdev->vlast_packet_size) {
+                       /* Shorter packet... end of frame */
+                       if (pdev->vsync == 2)
+                               pwc_frame_complete(pdev);
+                       if (pdev->fill_buf == NULL)
+                               pdev->fill_buf = pwc_get_next_fill_buf(pdev);
+                       if (pdev->fill_buf) {
+                               pdev->fill_buf->filled = 0;
+                               pdev->vsync = 1;
+                       }
+               }
+               pdev->vlast_packet_size = flen;
+       }
+
+handler_end:
+       i = usb_submit_urb(urb, GFP_ATOMIC);
+       if (i != 0)
+               PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
+}
+
+/* Both v4l2_lock and vb_queue_lock should be locked when calling this */
+static int pwc_isoc_init(struct pwc_device *pdev)
+{
+       struct usb_device *udev;
+       struct urb *urb;
+       int i, j, ret;
+       struct usb_interface *intf;
+       struct usb_host_interface *idesc = NULL;
+       int compression = 0; /* 0..3 = uncompressed..high */
+
+       pdev->vsync = 0;
+       pdev->vlast_packet_size = 0;
+       pdev->fill_buf = NULL;
+       pdev->vframe_count = 0;
+       pdev->visoc_errors = 0;
+       udev = pdev->udev;
+
+retry:
+       /* We first try with low compression and then retry with a higher
+          compression setting if there is not enough bandwidth. */
+       ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
+                                pdev->vframes, &compression, 1);
+
+       /* Get the current alternate interface, adjust packet size */
+       intf = usb_ifnum_to_if(udev, 0);
+       if (intf)
+               idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
+       if (!idesc)
+               return -EIO;
+
+       /* Search video endpoint */
+       pdev->vmax_packet_size = -1;
+       for (i = 0; i < idesc->desc.bNumEndpoints; i++) {
+               if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
+                       pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
+                       break;
+               }
+       }
+
+       if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
+               PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n");
+               return -ENFILE; /* Odd error, that should be noticeable */
+       }
+
+       /* Set alternate interface */
+       PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
+       ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
+       if (ret == -ENOSPC && compression < 3) {
+               compression++;
+               goto retry;
+       }
+       if (ret < 0)
+               return ret;
+
+       /* Allocate and init Isochronuous urbs */
+       for (i = 0; i < MAX_ISO_BUFS; i++) {
+               urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
+               if (urb == NULL) {
+                       PWC_ERROR("Failed to allocate urb %d\n", i);
+                       pwc_isoc_cleanup(pdev);
+                       return -ENOMEM;
+               }
+               pdev->urbs[i] = urb;
+               PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
+
+               urb->interval = 1; // devik
+               urb->dev = udev;
+               urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+               urb->transfer_buffer = usb_alloc_coherent(udev,
+                                                         ISO_BUFFER_SIZE,
+                                                         GFP_KERNEL,
+                                                         &urb->transfer_dma);
+               if (urb->transfer_buffer == NULL) {
+                       PWC_ERROR("Failed to allocate urb buffer %d\n", i);
+                       pwc_isoc_cleanup(pdev);
+                       return -ENOMEM;
+               }
+               urb->transfer_buffer_length = ISO_BUFFER_SIZE;
+               urb->complete = pwc_isoc_handler;
+               urb->context = pdev;
+               urb->start_frame = 0;
+               urb->number_of_packets = ISO_FRAMES_PER_DESC;
+               for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
+                       urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
+                       urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
+               }
+       }
+
+       /* link */
+       for (i = 0; i < MAX_ISO_BUFS; i++) {
+               ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL);
+               if (ret == -ENOSPC && compression < 3) {
+                       compression++;
+                       pwc_isoc_cleanup(pdev);
+                       goto retry;
+               }
+               if (ret) {
+                       PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
+                       pwc_isoc_cleanup(pdev);
+                       return ret;
+               }
+               PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->urbs[i]);
+       }
+
+       /* All is done... */
+       PWC_DEBUG_OPEN("<< pwc_isoc_init()\n");
+       return 0;
+}
+
+static void pwc_iso_stop(struct pwc_device *pdev)
+{
+       int i;
+
+       /* Unlinking ISOC buffers one by one */
+       for (i = 0; i < MAX_ISO_BUFS; i++) {
+               if (pdev->urbs[i]) {
+                       PWC_DEBUG_MEMORY("Unlinking URB %p\n", pdev->urbs[i]);
+                       usb_kill_urb(pdev->urbs[i]);
+               }
+       }
+}
+
+static void pwc_iso_free(struct pwc_device *pdev)
+{
+       int i;
+
+       /* Freeing ISOC buffers one by one */
+       for (i = 0; i < MAX_ISO_BUFS; i++) {
+               if (pdev->urbs[i]) {
+                       PWC_DEBUG_MEMORY("Freeing URB\n");
+                       if (pdev->urbs[i]->transfer_buffer) {
+                               usb_free_coherent(pdev->udev,
+                                       pdev->urbs[i]->transfer_buffer_length,
+                                       pdev->urbs[i]->transfer_buffer,
+                                       pdev->urbs[i]->transfer_dma);
+                       }
+                       usb_free_urb(pdev->urbs[i]);
+                       pdev->urbs[i] = NULL;
+               }
+       }
+}
+
+/* Both v4l2_lock and vb_queue_lock should be locked when calling this */
+static void pwc_isoc_cleanup(struct pwc_device *pdev)
+{
+       PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
+
+       pwc_iso_stop(pdev);
+       pwc_iso_free(pdev);
+       usb_set_interface(pdev->udev, 0, 0);
+
+       PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
+}
+
+/* Must be called with vb_queue_lock hold */
+static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
+{
+       unsigned long flags = 0;
+
+       spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
+       while (!list_empty(&pdev->queued_bufs)) {
+               struct pwc_frame_buf *buf;
+
+               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);
+       }
+       spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
+}
+
+#ifdef CONFIG_USB_PWC_DEBUG
+static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
+{
+       switch(sensor_type) {
+               case 0x00:
+                       return "Hyundai CMOS sensor";
+               case 0x20:
+                       return "Sony CCD sensor + TDA8787";
+               case 0x2E:
+                       return "Sony CCD sensor + Exas 98L59";
+               case 0x2F:
+                       return "Sony CCD sensor + ADI 9804";
+               case 0x30:
+                       return "Sharp CCD sensor + TDA8787";
+               case 0x3E:
+                       return "Sharp CCD sensor + Exas 98L59";
+               case 0x3F:
+                       return "Sharp CCD sensor + ADI 9804";
+               case 0x40:
+                       return "UPA 1021 sensor";
+               case 0x100:
+                       return "VGA sensor";
+               case 0x101:
+                       return "PAL MR sensor";
+               default:
+                       return "unknown type of sensor";
+       }
+}
+#endif
+
+/***************************************************************************/
+/* Video4Linux functions */
+
+static void pwc_video_release(struct v4l2_device *v)
+{
+       struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
+
+       v4l2_ctrl_handler_free(&pdev->ctrl_handler);
+       v4l2_device_unregister(&pdev->v4l2_dev);
+       kfree(pdev->ctrl_buf);
+       kfree(pdev);
+}
+
+/***************************************************************************/
+/* Videobuf2 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 pwc_device *pdev = vb2_get_drv_priv(vq);
+       int size;
+
+       if (*nbuffers < MIN_FRAMES)
+               *nbuffers = MIN_FRAMES;
+       else if (*nbuffers > MAX_FRAMES)
+               *nbuffers = MAX_FRAMES;
+
+       *nplanes = 1;
+
+       size = pwc_get_size(pdev, MAX_WIDTH, MAX_HEIGHT);
+       sizes[0] = PAGE_ALIGN(pwc_image_sizes[size][0] *
+                             pwc_image_sizes[size][1] * 3 / 2);
+
+       return 0;
+}
+
+static int buffer_init(struct vb2_buffer *vb)
+{
+       struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+
+       /* need vmalloc since frame buffer > 128K */
+       buf->data = vzalloc(PWC_FRAME_SIZE);
+       if (buf->data == NULL)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static int buffer_prepare(struct vb2_buffer *vb)
+{
+       struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
+
+       /* Don't allow queing new buffers after device disconnection */
+       if (!pdev->udev)
+               return -ENODEV;
+
+       return 0;
+}
+
+static int buffer_finish(struct vb2_buffer *vb)
+{
+       struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
+       struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+
+       /*
+        * Application has called dqbuf and is getting back a buffer we've
+        * filled, take the pwc data we've stored in buf->data and decompress
+        * it into a usable format, storing the result in the vb2_buffer
+        */
+       return pwc_decompress(pdev, buf);
+}
+
+static void buffer_cleanup(struct vb2_buffer *vb)
+{
+       struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+
+       vfree(buf->data);
+}
+
+static void buffer_queue(struct vb2_buffer *vb)
+{
+       struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
+       struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
+       unsigned long flags = 0;
+
+       /* Check the device has not disconnected between prep and queuing */
+       if (!pdev->udev) {
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+               return;
+       }
+
+       spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
+       list_add_tail(&buf->list, &pdev->queued_bufs);
+       spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
+}
+
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+       struct pwc_device *pdev = vb2_get_drv_priv(vq);
+       int r;
+
+       if (!pdev->udev)
+               return -ENODEV;
+
+       if (mutex_lock_interruptible(&pdev->v4l2_lock))
+               return -ERESTARTSYS;
+       /* Turn on camera and set LEDS on */
+       pwc_camera_power(pdev, 1);
+       pwc_set_leds(pdev, leds[0], leds[1]);
+
+       r = pwc_isoc_init(pdev);
+       if (r) {
+               /* If we failed turn camera and LEDS back off */
+               pwc_set_leds(pdev, 0, 0);
+               pwc_camera_power(pdev, 0);
+               /* And cleanup any queued bufs!! */
+               pwc_cleanup_queued_bufs(pdev);
+       }
+       mutex_unlock(&pdev->v4l2_lock);
+
+       return r;
+}
+
+static int stop_streaming(struct vb2_queue *vq)
+{
+       struct pwc_device *pdev = vb2_get_drv_priv(vq);
+
+       if (mutex_lock_interruptible(&pdev->v4l2_lock))
+               return -ERESTARTSYS;
+       if (pdev->udev) {
+               pwc_set_leds(pdev, 0, 0);
+               pwc_camera_power(pdev, 0);
+               pwc_isoc_cleanup(pdev);
+       }
+
+       pwc_cleanup_queued_bufs(pdev);
+       mutex_unlock(&pdev->v4l2_lock);
+
+       return 0;
+}
+
+static struct vb2_ops pwc_vb_queue_ops = {
+       .queue_setup            = queue_setup,
+       .buf_init               = buffer_init,
+       .buf_prepare            = buffer_prepare,
+       .buf_finish             = buffer_finish,
+       .buf_cleanup            = buffer_cleanup,
+       .buf_queue              = buffer_queue,
+       .start_streaming        = start_streaming,
+       .stop_streaming         = stop_streaming,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
+};
+
+/***************************************************************************/
+/* USB functions */
+
+/* This function gets called when a new device is plugged in or the usb core
+ * is loaded.
+ */
+
+static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct pwc_device *pdev = NULL;
+       int vendor_id, product_id, type_id;
+       int rc;
+       int features = 0;
+       int compression = 0;
+       int my_power_save = power_save;
+       char serial_number[30], *name;
+
+       vendor_id = le16_to_cpu(udev->descriptor.idVendor);
+       product_id = le16_to_cpu(udev->descriptor.idProduct);
+
+       /* Check if we can handle this device */
+       PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n",
+               vendor_id, product_id,
+               intf->altsetting->desc.bInterfaceNumber);
+
+       /* the interfaces are probed one by one. We are only interested in the
+          video interface (0) now.
+          Interface 1 is the Audio Control, and interface 2 Audio itself.
+        */
+       if (intf->altsetting->desc.bInterfaceNumber > 0)
+               return -ENODEV;
+
+       if (vendor_id == 0x0471) {
+               switch (product_id) {
+               case 0x0302:
+                       PWC_INFO("Philips PCA645VC USB webcam detected.\n");
+                       name = "Philips 645 webcam";
+                       type_id = 645;
+                       break;
+               case 0x0303:
+                       PWC_INFO("Philips PCA646VC USB webcam detected.\n");
+                       name = "Philips 646 webcam";
+                       type_id = 646;
+                       break;
+               case 0x0304:
+                       PWC_INFO("Askey VC010 type 2 USB webcam detected.\n");
+                       name = "Askey VC010 webcam";
+                       type_id = 646;
+                       break;
+               case 0x0307:
+                       PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n");
+                       name = "Philips 675 webcam";
+                       type_id = 675;
+                       break;
+               case 0x0308:
+                       PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
+                       name = "Philips 680 webcam";
+                       type_id = 680;
+                       break;
+               case 0x030C:
+                       PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
+                       name = "Philips 690 webcam";
+                       type_id = 690;
+                       break;
+               case 0x0310:
+                       PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
+                       name = "Philips 730 webcam";
+                       type_id = 730;
+                       break;
+               case 0x0311:
+                       PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
+                       name = "Philips 740 webcam";
+                       type_id = 740;
+                       break;
+               case 0x0312:
+                       PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
+                       name = "Philips 750 webcam";
+                       type_id = 750;
+                       break;
+               case 0x0313:
+                       PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
+                       name = "Philips 720K/40 webcam";
+                       type_id = 720;
+                       break;
+               case 0x0329:
+                       PWC_INFO("Philips SPC 900NC USB webcam detected.\n");
+                       name = "Philips SPC 900NC webcam";
+                       type_id = 740;
+                       break;
+               default:
+                       return -ENODEV;
+                       break;
+               }
+       }
+       else if (vendor_id == 0x069A) {
+               switch(product_id) {
+               case 0x0001:
+                       PWC_INFO("Askey VC010 type 1 USB webcam detected.\n");
+                       name = "Askey VC010 webcam";
+                       type_id = 645;
+                       break;
+               default:
+                       return -ENODEV;
+                       break;
+               }
+       }
+       else if (vendor_id == 0x046d) {
+               switch(product_id) {
+               case 0x08b0:
+                       PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n");
+                       name = "Logitech QuickCam Pro 3000";
+                       type_id = 740; /* CCD sensor */
+                       break;
+               case 0x08b1:
+                       PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n");
+                       name = "Logitech QuickCam Notebook Pro";
+                       type_id = 740; /* CCD sensor */
+                       break;
+               case 0x08b2:
+                       PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n");
+                       name = "Logitech QuickCam Pro 4000";
+                       type_id = 740; /* CCD sensor */
+                       if (my_power_save == -1)
+                               my_power_save = 1;
+                       break;
+               case 0x08b3:
+                       PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n");
+                       name = "Logitech QuickCam Zoom";
+                       type_id = 740; /* CCD sensor */
+                       break;
+               case 0x08B4:
+                       PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
+                       name = "Logitech QuickCam Zoom";
+                       type_id = 740; /* CCD sensor */
+                       if (my_power_save == -1)
+                               my_power_save = 1;
+                       break;
+               case 0x08b5:
+                       PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
+                       name = "Logitech QuickCam Orbit";
+                       type_id = 740; /* CCD sensor */
+                       if (my_power_save == -1)
+                               my_power_save = 1;
+                       features |= FEATURE_MOTOR_PANTILT;
+                       break;
+               case 0x08b6:
+                       PWC_INFO("Logitech/Cisco VT Camera webcam detected.\n");
+                       name = "Cisco VT Camera";
+                       type_id = 740; /* CCD sensor */
+                       break;
+               case 0x08b7:
+                       PWC_INFO("Logitech ViewPort AV 100 webcam detected.\n");
+                       name = "Logitech ViewPort AV 100";
+                       type_id = 740; /* CCD sensor */
+                       break;
+               case 0x08b8: /* Where this released? */
+                       PWC_INFO("Logitech QuickCam detected (reserved ID).\n");
+                       name = "Logitech QuickCam (res.)";
+                       type_id = 730; /* Assuming CMOS */
+                       break;
+               default:
+                       return -ENODEV;
+                       break;
+               }
+       }
+       else if (vendor_id == 0x055d) {
+               /* I don't know the difference between the C10 and the C30;
+                  I suppose the difference is the sensor, but both cameras
+                  work equally well with a type_id of 675
+                */
+               switch(product_id) {
+               case 0x9000:
+                       PWC_INFO("Samsung MPC-C10 USB webcam detected.\n");
+                       name = "Samsung MPC-C10";
+                       type_id = 675;
+                       break;
+               case 0x9001:
+                       PWC_INFO("Samsung MPC-C30 USB webcam detected.\n");
+                       name = "Samsung MPC-C30";
+                       type_id = 675;
+                       break;
+               case 0x9002:
+                       PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n");
+                       name = "Samsung MPC-C30";
+                       type_id = 740;
+                       break;
+               default:
+                       return -ENODEV;
+                       break;
+               }
+       }
+       else if (vendor_id == 0x041e) {
+               switch(product_id) {
+               case 0x400c:
+                       PWC_INFO("Creative Labs Webcam 5 detected.\n");
+                       name = "Creative Labs Webcam 5";
+                       type_id = 730;
+                       if (my_power_save == -1)
+                               my_power_save = 1;
+                       break;
+               case 0x4011:
+                       PWC_INFO("Creative Labs Webcam Pro Ex detected.\n");
+                       name = "Creative Labs Webcam Pro Ex";
+                       type_id = 740;
+                       break;
+               default:
+                       return -ENODEV;
+                       break;
+               }
+       }
+       else if (vendor_id == 0x04cc) {
+               switch(product_id) {
+               case 0x8116:
+                       PWC_INFO("Sotec Afina Eye USB webcam detected.\n");
+                       name = "Sotec Afina Eye";
+                       type_id = 730;
+                       break;
+               default:
+                       return -ENODEV;
+                       break;
+               }
+       }
+       else if (vendor_id == 0x06be) {
+               switch(product_id) {
+               case 0x8116:
+                       /* This is essentially the same cam as the Sotec Afina Eye */
+                       PWC_INFO("AME Co. Afina Eye USB webcam detected.\n");
+                       name = "AME Co. Afina Eye";
+                       type_id = 750;
+                       break;
+               default:
+                       return -ENODEV;
+                       break;
+               }
+
+       }
+       else if (vendor_id == 0x0d81) {
+               switch(product_id) {
+               case 0x1900:
+                       PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n");
+                       name = "Visionite VCS-UC300";
+                       type_id = 740; /* CCD sensor */
+                       break;
+               case 0x1910:
+                       PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n");
+                       name = "Visionite VCS-UM100";
+                       type_id = 730; /* CMOS sensor */
+                       break;
+               default:
+                       return -ENODEV;
+                       break;
+               }
+       }
+       else
+               return -ENODEV; /* Not any of the know types; but the list keeps growing. */
+
+       if (my_power_save == -1)
+               my_power_save = 0;
+
+       memset(serial_number, 0, 30);
+       usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
+       PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
+
+       if (udev->descriptor.bNumConfigurations > 1)
+               PWC_WARNING("Warning: more than 1 configuration available.\n");
+
+       /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
+       pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL);
+       if (pdev == NULL) {
+               PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
+               return -ENOMEM;
+       }
+       pdev->type = type_id;
+       pdev->features = features;
+       pwc_construct(pdev); /* set min/max sizes correct */
+
+       mutex_init(&pdev->v4l2_lock);
+       mutex_init(&pdev->vb_queue_lock);
+       spin_lock_init(&pdev->queued_bufs_lock);
+       INIT_LIST_HEAD(&pdev->queued_bufs);
+
+       pdev->udev = udev;
+       pdev->power_save = my_power_save;
+
+       /* Init videobuf2 queue structure */
+       memset(&pdev->vb_queue, 0, sizeof(pdev->vb_queue));
+       pdev->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       pdev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+       pdev->vb_queue.drv_priv = pdev;
+       pdev->vb_queue.buf_struct_size = sizeof(struct pwc_frame_buf);
+       pdev->vb_queue.ops = &pwc_vb_queue_ops;
+       pdev->vb_queue.mem_ops = &vb2_vmalloc_memops;
+       vb2_queue_init(&pdev->vb_queue);
+
+       /* Init video_device structure */
+       memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
+       strcpy(pdev->vdev.name, name);
+       pdev->vdev.queue = &pdev->vb_queue;
+       pdev->vdev.queue->lock = &pdev->vb_queue_lock;
+       set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags);
+       video_set_drvdata(&pdev->vdev, pdev);
+
+       pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
+       PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
+
+       /* Allocate USB command buffers */
+       pdev->ctrl_buf = kmalloc(sizeof(pdev->cmd_buf), GFP_KERNEL);
+       if (!pdev->ctrl_buf) {
+               PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
+               rc = -ENOMEM;
+               goto err_free_mem;
+       }
+
+#ifdef CONFIG_USB_PWC_DEBUG
+       /* Query sensor type */
+       if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
+               PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
+                               pdev->vdev.name,
+                               pwc_sensor_type_to_string(rc), rc);
+       }
+#endif
+
+       /* Set the leds off */
+       pwc_set_leds(pdev, 0, 0);
+
+       /* Setup intial videomode */
+       rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT,
+                               V4L2_PIX_FMT_YUV420, 30, &compression, 1);
+       if (rc)
+               goto err_free_mem;
+
+       /* Register controls (and read default values from camera */
+       rc = pwc_init_controls(pdev);
+       if (rc) {
+               PWC_ERROR("Failed to register v4l2 controls (%d).\n", rc);
+               goto err_free_mem;
+       }
+
+       /* And powerdown the camera until streaming starts */
+       pwc_camera_power(pdev, 0);
+
+       /* Register the v4l2_device structure */
+       pdev->v4l2_dev.release = pwc_video_release;
+       rc = v4l2_device_register(&intf->dev, &pdev->v4l2_dev);
+       if (rc) {
+               PWC_ERROR("Failed to register v4l2-device (%d).\n", rc);
+               goto err_free_controls;
+       }
+
+       pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
+       pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
+       pdev->vdev.lock = &pdev->v4l2_lock;
+
+       rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, -1);
+       if (rc < 0) {
+               PWC_ERROR("Failed to register as video device (%d).\n", rc);
+               goto err_unregister_v4l2_dev;
+       }
+       PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
+
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+       /* register webcam snapshot button input device */
+       pdev->button_dev = input_allocate_device();
+       if (!pdev->button_dev) {
+               PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
+               rc = -ENOMEM;
+               goto err_video_unreg;
+       }
+
+       usb_make_path(udev, pdev->button_phys, sizeof(pdev->button_phys));
+       strlcat(pdev->button_phys, "/input0", sizeof(pdev->button_phys));
+
+       pdev->button_dev->name = "PWC snapshot button";
+       pdev->button_dev->phys = pdev->button_phys;
+       usb_to_input_id(pdev->udev, &pdev->button_dev->id);
+       pdev->button_dev->dev.parent = &pdev->udev->dev;
+       pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY);
+       pdev->button_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
+
+       rc = input_register_device(pdev->button_dev);
+       if (rc) {
+               input_free_device(pdev->button_dev);
+               pdev->button_dev = NULL;
+               goto err_video_unreg;
+       }
+#endif
+
+       return 0;
+
+err_video_unreg:
+       video_unregister_device(&pdev->vdev);
+err_unregister_v4l2_dev:
+       v4l2_device_unregister(&pdev->v4l2_dev);
+err_free_controls:
+       v4l2_ctrl_handler_free(&pdev->ctrl_handler);
+err_free_mem:
+       kfree(pdev->ctrl_buf);
+       kfree(pdev);
+       return rc;
+}
+
+/* The user yanked out the cable... */
+static void usb_pwc_disconnect(struct usb_interface *intf)
+{
+       struct v4l2_device *v = usb_get_intfdata(intf);
+       struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
+
+       mutex_lock(&pdev->vb_queue_lock);
+       mutex_lock(&pdev->v4l2_lock);
+       /* No need to keep the urbs around after disconnection */
+       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);
+       mutex_unlock(&pdev->v4l2_lock);
+       mutex_unlock(pdev->vb_queue.lock);
+
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+       if (pdev->button_dev)
+               input_unregister_device(pdev->button_dev);
+#endif
+
+       v4l2_device_put(&pdev->v4l2_dev);
+}
+
+
+/*
+ * Initialization code & module stuff
+ */
+
+static unsigned int leds_nargs;
+
+#ifdef CONFIG_USB_PWC_DEBUG
+module_param_named(trace, pwc_trace, int, 0644);
+#endif
+module_param(power_save, int, 0644);
+module_param_array(leds, int, &leds_nargs, 0444);
+
+#ifdef CONFIG_USB_PWC_DEBUG
+MODULE_PARM_DESC(trace, "For debugging purposes");
+#endif
+MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
+MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
+
+MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
+MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("pwcx");
+MODULE_VERSION( PWC_VERSION );
+
+module_usb_driver(pwc_driver);
diff --git a/drivers/media/usb/pwc/pwc-kiara.c b/drivers/media/usb/pwc/pwc-kiara.c
new file mode 100644 (file)
index 0000000..e5f4fd8
--- /dev/null
@@ -0,0 +1,892 @@
+/* Linux driver for Philips webcam
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+/* This tables contains entries for the 730/740/750 (Kiara) camera, with
+   4 different qualities (no compression, low, medium, high).
+   It lists the bandwidth requirements for said mode by its alternate interface
+   number. An alternate of 0 means that the mode is unavailable.
+
+   There are 6 * 4 * 4 entries:
+     6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+     6 framerates: 5, 10, 15, 20, 25, 30
+     4 compression modi: none, low, medium, high
+
+   When an uncompressed mode is not available, the next available compressed mode
+   will be chosen (unless the decompressor is absent). Sometimes there are only
+   1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+
+
+#include "pwc-kiara.h"
+
+const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA] = { 5, 10, 15, 20, 25, 30 };
+
+const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
+{
+   /* SQCIF */
+   {
+      /* 5 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 10 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 15 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 20 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 25 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 30 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+   },
+   /* QSIF */
+   {
+      /* 5 fps */
+      {
+        {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+        {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+        {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+        {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+      },
+      /* 10 fps */
+      {
+        {2, 291,    0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}},
+        {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+        {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+        {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+      },
+      /* 15 fps */
+      {
+        {3, 437,    0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}},
+        {2, 292,  640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+        {2, 292,  640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+        {1, 192,  420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+      },
+      /* 20 fps */
+      {
+        {4, 589,    0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}},
+        {3, 448,  730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}},
+        {2, 292,  476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}},
+        {1, 192,  312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+      },
+      /* 25 fps */
+      {
+        {5, 703,    0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}},
+        {3, 447,  610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}},
+        {2, 292,  398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+        {1, 193,  262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}},
+      },
+      /* 30 fps */
+      {
+        {8, 874,    0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}},
+        {5, 704,  730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}},
+        {3, 448,  492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}},
+        {2, 292,  320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+      },
+   },
+   /* QCIF */
+   {
+      /* 5 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 10 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 15 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 20 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 25 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 30 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+   },
+   /* SIF */
+   {
+      /* 5 fps */
+      {
+        {4, 582,    0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}},
+        {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}},
+        {2, 291,  960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}},
+        {1, 191,  630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}},
+      },
+      /* 10 fps */
+      {
+        {0, },
+        {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}},
+        {3, 447,  736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}},
+        {2, 292,  480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}},
+      },
+      /* 15 fps */
+      {
+        {0, },
+        {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}},
+        {4, 592,  650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}},
+        {3, 448,  492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}},
+      },
+      /* 20 fps */
+      {
+        {0, },
+        {9, 958,  782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}},
+        {5, 703,  574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}},
+        {3, 446,  364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}},
+      },
+      /* 25 fps */
+      {
+        {0, },
+        {9, 958,  654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}},
+        {6, 776,  530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}},
+        {4, 592,  404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}},
+      },
+      /* 30 fps */
+      {
+        {0, },
+        {9, 957,  526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}},
+        {6, 775,  426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}},
+        {4, 590,  324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}},
+      },
+   },
+   /* CIF */
+   {
+      /* 5 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 10 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 15 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 20 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 25 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 30 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+   },
+   /* VGA */
+   {
+      /* 5 fps */
+      {
+        {0, },
+        {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}},
+        {4, 592,  976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}},
+        {3, 448,  738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}},
+      },
+      /* 10 fps */
+      {
+        {0, },
+        {9, 956,  788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}},
+        {6, 776,  640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}},
+        {4, 592,  488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}},
+      },
+      /* 15 fps */
+      {
+        {0, },
+        {9, 957,  526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+        {9, 957,  526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+        {8, 895,  492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}},
+      },
+      /* 20 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 25 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 30 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+   },
+};
+
+
+/*
+ * Rom table for kiara chips
+ *
+ * 32 roms tables (one for each resolution ?)
+ *  2 tables per roms (one for each passes) (Y, and U&V)
+ * 128 bytes per passes
+ */
+
+const unsigned int KiaraRomTable [8][2][16][8] =
+{
+ { /* version 0 */
+  { /* version 0, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009292,0x00009292,0x00009493,0x000124db},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x0000a493,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x000124db,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 0, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000001,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009292,
+    0x00009492,0x00009493,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000126dc,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 1 */
+  { /* version 1, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009492,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 1, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000049,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 2 */
+  { /* version 2, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x0000a49b},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 2, passes 1 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x0000a49b,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x0001249b,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 3 */
+  { /* version 3, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 3, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 4 */
+  { /* version 4, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 4, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 5 */
+  { /* version 5, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 5, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x00009252,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 6 */
+  { /* version 6, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 6, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 7 */
+  { /* version 7, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 7, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ }
+};
+
diff --git a/drivers/media/usb/pwc/pwc-kiara.h b/drivers/media/usb/pwc/pwc-kiara.h
new file mode 100644 (file)
index 0000000..8e02b7a
--- /dev/null
@@ -0,0 +1,48 @@
+/* Linux driver for Philips webcam
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* Entries for the Kiara (730/740/750) camera */
+
+#ifndef PWC_KIARA_H
+#define PWC_KIARA_H
+
+#include "pwc.h"
+
+#define PWC_FPS_MAX_KIARA 6
+
+struct Kiara_table_entry
+{
+       char alternate;                 /* USB alternate interface */
+       unsigned short packetsize;      /* Normal packet size */
+       unsigned short bandlength;      /* Bandlength when decompressing */
+       unsigned char mode[12];         /* precomputed mode settings for cam */
+};
+
+extern const struct Kiara_table_entry Kiara_table[PSZ_MAX][PWC_FPS_MAX_KIARA][4];
+extern const unsigned int KiaraRomTable[8][2][16][8];
+extern const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA];
+
+#endif
+
+
diff --git a/drivers/media/usb/pwc/pwc-misc.c b/drivers/media/usb/pwc/pwc-misc.c
new file mode 100644 (file)
index 0000000..9be5adf
--- /dev/null
@@ -0,0 +1,93 @@
+/* Linux driver for Philips webcam
+   Various miscellaneous functions and tables.
+   (C) 1999-2003 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+#include "pwc.h"
+
+const int pwc_image_sizes[PSZ_MAX][2] =
+{
+       { 128,  96 }, /* sqcif */
+       { 160, 120 }, /* qsif */
+       { 176, 144 }, /* qcif */
+       { 320, 240 }, /* sif */
+       { 352, 288 }, /* cif */
+       { 640, 480 }, /* vga */
+};
+
+/* x,y -> PSZ_ */
+int pwc_get_size(struct pwc_device *pdev, int width, int height)
+{
+       int i;
+
+       /* Find the largest size supported by the camera that fits into the
+          requested size. */
+       for (i = PSZ_MAX - 1; i >= 0; i--) {
+               if (!(pdev->image_mask & (1 << i)))
+                       continue;
+
+               if (pwc_image_sizes[i][0] <= width &&
+                   pwc_image_sizes[i][1] <= height)
+                       return i;
+       }
+
+       /* No mode found, return the smallest mode we have */
+       for (i = 0; i < PSZ_MAX; i++) {
+               if (pdev->image_mask & (1 << i))
+                       return i;
+       }
+
+       /* Never reached there always is atleast one supported mode */
+       return 0;
+}
+
+/* initialize variables depending on type and decompressor */
+void pwc_construct(struct pwc_device *pdev)
+{
+       if (DEVICE_USE_CODEC1(pdev->type)) {
+
+               pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
+               pdev->vcinterface = 2;
+               pdev->vendpoint = 4;
+               pdev->frame_header_size = 0;
+               pdev->frame_trailer_size = 0;
+
+       } else if (DEVICE_USE_CODEC3(pdev->type)) {
+
+               pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
+               pdev->vcinterface = 3;
+               pdev->vendpoint = 5;
+               pdev->frame_header_size = TOUCAM_HEADER_SIZE;
+               pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
+
+       } else /* if (DEVICE_USE_CODEC2(pdev->type)) */ {
+
+               pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
+               pdev->vcinterface = 3;
+               pdev->vendpoint = 4;
+               pdev->frame_header_size = 0;
+               pdev->frame_trailer_size = 0;
+       }
+}
diff --git a/drivers/media/usb/pwc/pwc-nala.h b/drivers/media/usb/pwc/pwc-nala.h
new file mode 100644 (file)
index 0000000..168c73e
--- /dev/null
@@ -0,0 +1,66 @@
+   /* SQCIF */
+   {
+      {0, 0, {0x04, 0x01, 0x03}},
+      {8, 0, {0x05, 0x01, 0x03}},
+      {7, 0, {0x08, 0x01, 0x03}},
+      {7, 0, {0x0A, 0x01, 0x03}},
+      {6, 0, {0x0C, 0x01, 0x03}},
+      {5, 0, {0x0F, 0x01, 0x03}},
+      {4, 0, {0x14, 0x01, 0x03}},
+      {3, 0, {0x18, 0x01, 0x03}},
+   },
+   /* QSIF */
+   {
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+   },
+   /* QCIF */
+   {
+      {0, 0, {0x04, 0x01, 0x02}},
+      {8, 0, {0x05, 0x01, 0x02}},
+      {7, 0, {0x08, 0x01, 0x02}},
+      {6, 0, {0x0A, 0x01, 0x02}},
+      {5, 0, {0x0C, 0x01, 0x02}},
+      {4, 0, {0x0F, 0x01, 0x02}},
+      {1, 0, {0x14, 0x01, 0x02}},
+      {1, 0, {0x18, 0x01, 0x02}},
+   },
+   /* SIF */
+   {
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+   },
+   /* CIF */
+   {
+      {4, 0, {0x04, 0x01, 0x01}},
+      {7, 1, {0x05, 0x03, 0x01}},
+      {6, 1, {0x08, 0x03, 0x01}},
+      {4, 1, {0x0A, 0x03, 0x01}},
+      {3, 1, {0x0C, 0x03, 0x01}},
+      {2, 1, {0x0F, 0x03, 0x01}},
+      {0},
+      {0},
+   },
+   /* VGA */
+   {
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+   },
diff --git a/drivers/media/usb/pwc/pwc-timon.c b/drivers/media/usb/pwc/pwc-timon.c
new file mode 100644 (file)
index 0000000..c56c174
--- /dev/null
@@ -0,0 +1,1448 @@
+/* Linux driver for Philips webcam
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+/* This tables contains entries for the 675/680/690 (Timon) camera, with
+   4 different qualities (no compression, low, medium, high).
+   It lists the bandwidth requirements for said mode by its alternate interface
+   number. An alternate of 0 means that the mode is unavailable.
+
+   There are 6 * 4 * 4 entries:
+     6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+     6 framerates: 5, 10, 15, 20, 25, 30
+     4 compression modi: none, low, medium, high
+
+   When an uncompressed mode is not available, the next available compressed mode
+   will be chosen (unless the decompressor is absent). Sometimes there are only
+   1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+
+#include "pwc-timon.h"
+
+const unsigned int Timon_fps_vector[PWC_FPS_MAX_TIMON] = { 5, 10, 15, 20, 25, 30 };
+
+const struct Timon_table_entry Timon_table[PSZ_MAX][PWC_FPS_MAX_TIMON][4] =
+{
+   /* SQCIF */
+   {
+      /* 5 fps */
+      {
+        {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+        {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+        {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+        {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+      },
+      /* 10 fps */
+      {
+        {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+        {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+        {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+        {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+      },
+      /* 15 fps */
+      {
+        {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+        {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+        {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+        {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+      },
+      /* 20 fps */
+      {
+        {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+        {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+        {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+        {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+      },
+      /* 25 fps */
+      {
+        {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+        {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+        {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+        {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+      },
+      /* 30 fps */
+      {
+        {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+        {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+        {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+        {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+      },
+   },
+   /* QSIF */
+   {
+      /* 5 fps */
+      {
+        {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+        {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+        {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+        {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+      },
+      /* 10 fps */
+      {
+        {2, 291,    0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}},
+        {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+        {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+        {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+      },
+      /* 15 fps */
+      {
+        {3, 437,    0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}},
+        {2, 291,  640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+        {2, 291,  640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+        {1, 191,  420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+      },
+      /* 20 fps */
+      {
+        {4, 588,    0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}},
+        {3, 447,  730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+        {2, 292,  476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+        {1, 192,  312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+      },
+      /* 25 fps */
+      {
+        {5, 703,    0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}},
+        {3, 447,  610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+        {2, 292,  398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+        {1, 192,  262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+      },
+      /* 30 fps */
+      {
+        {8, 873,    0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}},
+        {5, 704,  774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}},
+        {3, 448,  492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}},
+        {2, 291,  320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+      },
+   },
+   /* QCIF */
+   {
+      /* 5 fps */
+      {
+        {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+        {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+        {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+        {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+      },
+      /* 10 fps */
+      {
+        {3, 385,    0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}},
+        {2, 291,  800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+        {2, 291,  800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+        {1, 194,  532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}},
+      },
+      /* 15 fps */
+      {
+        {4, 577,    0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}},
+        {3, 447,  818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}},
+        {2, 292,  534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}},
+        {1, 195,  356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}},
+      },
+      /* 20 fps */
+      {
+        {6, 776,    0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}},
+        {4, 591,  804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}},
+        {3, 447,  608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+        {2, 291,  396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+      },
+      /* 25 fps */
+      {
+        {9, 928,    0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}},
+        {5, 703,  800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}},
+        {3, 447,  508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+        {2, 292,  332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+      },
+      /* 30 fps */
+      {
+        {0, },
+        {9, 956,  876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}},
+        {4, 592,  542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}},
+        {2, 291,  266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}},
+      },
+   },
+   /* SIF */
+   {
+      /* 5 fps */
+      {
+        {4, 582,    0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}},
+        {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}},
+        {2, 291,  960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}},
+        {1, 191,  630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}},
+      },
+      /* 10 fps */
+      {
+        {0, },
+        {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}},
+        {3, 447,  736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}},
+        {2, 291,  480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}},
+      },
+      /* 15 fps */
+      {
+        {0, },
+        {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}},
+        {4, 591,  650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}},
+        {3, 448,  492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}},
+      },
+      /* 20 fps */
+      {
+        {0, },
+        {9, 958,  782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}},
+        {5, 703,  574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}},
+        {3, 446,  364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}},
+      },
+      /* 25 fps */
+      {
+        {0, },
+        {9, 958,  654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}},
+        {6, 776,  530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}},
+        {4, 592,  404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}},
+      },
+      /* 30 fps */
+      {
+        {0, },
+        {9, 957,  526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}},
+        {6, 775,  426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}},
+        {4, 590,  324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}},
+      },
+   },
+   /* CIF */
+   {
+      /* 5 fps */
+      {
+        {6, 771,    0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}},
+        {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}},
+        {2, 291,  800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}},
+        {1, 193,  528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}},
+      },
+      /* 10 fps */
+      {
+        {0, },
+        {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}},
+        {4, 591,  812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}},
+        {2, 291,  400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}},
+      },
+      /* 15 fps */
+      {
+        {0, },
+        {9, 956,  876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}},
+        {5, 703,  644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}},
+        {3, 448,  410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}},
+      },
+      /* 20 fps */
+      {
+        {0, },
+        {9, 956,  650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}},
+        {6, 776,  528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}},
+        {4, 591,  402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}},
+      },
+      /* 25 fps */
+      {
+        {0, },
+        {9, 956,  544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}},
+        {7, 840,  478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}},
+        {5, 703,  400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}},
+      },
+      /* 30 fps */
+      {
+        {0, },
+        {9, 956,  438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}},
+        {7, 838,  384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}},
+        {6, 773,  354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}},
+      },
+   },
+   /* VGA */
+   {
+      /* 5 fps */
+      {
+        {0, },
+        {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}},
+        {4, 592,  976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}},
+        {3, 448,  738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}},
+      },
+      /* 10 fps */
+      {
+        {0, },
+        {9, 956,  788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}},
+        {6, 776,  640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}},
+        {4, 592,  488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}},
+      },
+      /* 15 fps */
+      {
+        {0, },
+        {9, 957,  526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+        {9, 957,  526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+        {8, 895,  492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}},
+      },
+      /* 20 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 25 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+      /* 30 fps */
+      {
+        {0, },
+        {0, },
+        {0, },
+        {0, },
+      },
+   },
+};
+
+/*
+ * 16 versions:
+ *   2 tables  (one for Y, and one for U&V)
+ *   16 levels of details per tables
+ *   8 blocs
+ */
+
+const unsigned int TimonRomTable [16][2][16][8] =
+{
+ { /* version 0 */
+  { /* version 0, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000001,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000001,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 0, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000001,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000001,
+    0x00000001,0x00000009,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000009,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000009,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 1 */
+  { /* version 1, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 1, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000001,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000049,0x00000249,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 2 */
+  { /* version 2, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009492,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 2, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000049,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 3 */
+  { /* version 3, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009292,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 3, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00000049,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009292,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 4 */
+  { /* version 4, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x0000a49b},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 4, passes 1 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x0000a49b,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x0001249b,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 5 */
+  { /* version 5, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 5, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x000124db,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009493,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 6 */
+  { /* version 6, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 6, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 7 */
+  { /* version 7, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x0002496e},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0002496d,0x00025bb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 7, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001b724,0x0001b925,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 8 */
+  { /* version 8, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x00024b76,0x00024b77},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x00024b76,0x00025bbf},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001c92d,0x00024b76,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001b724,0x00024b6d,0x0002ddb6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 8, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0002496d,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 9 */
+  { /* version 9, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 9, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 10 */
+  { /* version 10, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0002496d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 10, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x00009493,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009493,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 11 */
+  { /* version 11, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 11, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x00009252,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 12 */
+  { /* version 12, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 12, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 13 */
+  { /* version 13, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 13, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 14 */
+  { /* version 14, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0002496d,0x00024b76,0x00024b77},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002db6d,0x00036db6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 14, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000136e4,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 15 */
+  { /* version 15, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0002496d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x00024b6d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002db6d,0x00036db6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 15, passes 1 */
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009292,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000124db,0x0001b724,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x0001b724,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x0001b724,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x0001b724,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001c924,0x0001b724,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001c924,0x0001b724,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001c924,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002496d,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ }
+};
diff --git a/drivers/media/usb/pwc/pwc-timon.h b/drivers/media/usb/pwc/pwc-timon.h
new file mode 100644 (file)
index 0000000..270c5b9
--- /dev/null
@@ -0,0 +1,63 @@
+/* Linux driver for Philips webcam
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+
+/* This tables contains entries for the 675/680/690 (Timon) camera, with
+   4 different qualities (no compression, low, medium, high).
+   It lists the bandwidth requirements for said mode by its alternate interface
+   number. An alternate of 0 means that the mode is unavailable.
+
+   There are 6 * 4 * 4 entries:
+     6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+     6 framerates: 5, 10, 15, 20, 25, 30
+     4 compression modi: none, low, medium, high
+
+   When an uncompressed mode is not available, the next available compressed mode
+   will be chosen (unless the decompressor is absent). Sometimes there are only
+   1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+
+#ifndef PWC_TIMON_H
+#define PWC_TIMON_H
+
+#include "pwc.h"
+
+#define PWC_FPS_MAX_TIMON 6
+
+struct Timon_table_entry
+{
+       char alternate;                 /* USB alternate interface */
+       unsigned short packetsize;      /* Normal packet size */
+       unsigned short bandlength;      /* Bandlength when decompressing */
+       unsigned char mode[13];         /* precomputed mode settings for cam */
+};
+
+extern const struct Timon_table_entry Timon_table[PSZ_MAX][PWC_FPS_MAX_TIMON][4];
+extern const unsigned int TimonRomTable [16][2][16][8];
+extern const unsigned int Timon_fps_vector[PWC_FPS_MAX_TIMON];
+
+#endif
+
+
diff --git a/drivers/media/usb/pwc/pwc-uncompress.c b/drivers/media/usb/pwc/pwc-uncompress.c
new file mode 100644 (file)
index 0000000..b65903f
--- /dev/null
@@ -0,0 +1,107 @@
+/* Linux driver for Philips webcam
+   Decompression frontend.
+   (C) 1999-2003 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+   vim: set ts=8:
+*/
+
+#include <asm/current.h>
+#include <asm/types.h>
+
+#include "pwc.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
+
+int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
+{
+       int n, line, col;
+       void *yuv, *image;
+       u16 *src;
+       u16 *dsty, *dstu, *dstv;
+
+       image = vb2_plane_vaddr(&fbuf->vb, 0);
+
+       yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
+
+       /* Raw format; that's easy... */
+       if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
+       {
+               struct pwc_raw_frame *raw_frame = image;
+               raw_frame->type = cpu_to_le16(pdev->type);
+               raw_frame->vbandlength = cpu_to_le16(pdev->vbandlength);
+                       /* cmd_buf is always 4 bytes, but sometimes, only the
+                        * first 3 bytes is filled (Nala case). We can
+                        * determine this using the type of the webcam */
+               memcpy(raw_frame->cmd, pdev->cmd_buf, 4);
+               memcpy(raw_frame+1, yuv, pdev->frame_size);
+               vb2_set_plane_payload(&fbuf->vb, 0,
+                       pdev->frame_size + sizeof(struct pwc_raw_frame));
+               return 0;
+       }
+
+       vb2_set_plane_payload(&fbuf->vb, 0,
+                             pdev->width * pdev->height * 3 / 2);
+
+       if (pdev->vbandlength == 0) {
+               /* Uncompressed mode.
+                *
+                * We do some byte shuffling here to go from the
+                * native format to YUV420P.
+                */
+               src = (u16 *)yuv;
+               n = pdev->width * pdev->height;
+               dsty = (u16 *)(image);
+               dstu = (u16 *)(image + n);
+               dstv = (u16 *)(image + n + n / 4);
+
+               for (line = 0; line < pdev->height; line++) {
+                       for (col = 0; col < pdev->width; col += 4) {
+                               *dsty++ = *src++;
+                               *dsty++ = *src++;
+                               if (line & 1)
+                                       *dstv++ = *src++;
+                               else
+                                       *dstu++ = *src++;
+                       }
+               }
+
+               return 0;
+       }
+
+       /*
+        * Compressed;
+        * the decompressor routines will write the data in planar format
+        * immediately.
+        */
+       if (DEVICE_USE_CODEC1(pdev->type)) {
+
+               /* TODO & FIXME */
+               PWC_ERROR("This chipset is not supported for now\n");
+               return -ENXIO; /* No such device or address: missing decompressor */
+
+       } else {
+               pwc_dec23_decompress(pdev, yuv, image);
+       }
+       return 0;
+}
diff --git a/drivers/media/usb/pwc/pwc-v4l.c b/drivers/media/usb/pwc/pwc-v4l.c
new file mode 100644 (file)
index 0000000..545e9bb
--- /dev/null
@@ -0,0 +1,1053 @@
+/* Linux driver for Philips webcam
+   USB and Video4Linux interface part.
+   (C) 1999-2004 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+   (C) 2011 Hans de Goede <hdegoede@redhat.com>
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/vmalloc.h>
+#include <linux/jiffies.h>
+#include <asm/io.h>
+
+#include "pwc.h"
+
+#define PWC_CID_CUSTOM(ctrl) ((V4L2_CID_USER_BASE | 0xf000) + custom_ ## ctrl)
+
+static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl);
+static int pwc_s_ctrl(struct v4l2_ctrl *ctrl);
+
+static const struct v4l2_ctrl_ops pwc_ctrl_ops = {
+       .g_volatile_ctrl = pwc_g_volatile_ctrl,
+       .s_ctrl = pwc_s_ctrl,
+};
+
+enum { awb_indoor, awb_outdoor, awb_fl, awb_manual, awb_auto };
+enum { custom_autocontour, custom_contour, custom_noise_reduction,
+       custom_awb_speed, custom_awb_delay,
+       custom_save_user, custom_restore_user, custom_restore_factory };
+
+const char * const pwc_auto_whitebal_qmenu[] = {
+       "Indoor (Incandescant Lighting) Mode",
+       "Outdoor (Sunlight) Mode",
+       "Indoor (Fluorescent Lighting) Mode",
+       "Manual Mode",
+       "Auto Mode",
+       NULL
+};
+
+static const struct v4l2_ctrl_config pwc_auto_white_balance_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = V4L2_CID_AUTO_WHITE_BALANCE,
+       .type   = V4L2_CTRL_TYPE_MENU,
+       .max    = awb_auto,
+       .qmenu  = pwc_auto_whitebal_qmenu,
+};
+
+static const struct v4l2_ctrl_config pwc_autocontour_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(autocontour),
+       .type   = V4L2_CTRL_TYPE_BOOLEAN,
+       .name   = "Auto contour",
+       .min    = 0,
+       .max    = 1,
+       .step   = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_contour_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(contour),
+       .type   = V4L2_CTRL_TYPE_INTEGER,
+       .name   = "Contour",
+       .flags  = V4L2_CTRL_FLAG_SLIDER,
+       .min    = 0,
+       .max    = 63,
+       .step   = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_backlight_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = V4L2_CID_BACKLIGHT_COMPENSATION,
+       .type   = V4L2_CTRL_TYPE_BOOLEAN,
+       .min    = 0,
+       .max    = 1,
+       .step   = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_flicker_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = V4L2_CID_BAND_STOP_FILTER,
+       .type   = V4L2_CTRL_TYPE_BOOLEAN,
+       .min    = 0,
+       .max    = 1,
+       .step   = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_noise_reduction_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(noise_reduction),
+       .type   = V4L2_CTRL_TYPE_INTEGER,
+       .name   = "Dynamic Noise Reduction",
+       .min    = 0,
+       .max    = 3,
+       .step   = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_save_user_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(save_user),
+       .type   = V4L2_CTRL_TYPE_BUTTON,
+       .name    = "Save User Settings",
+};
+
+static const struct v4l2_ctrl_config pwc_restore_user_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(restore_user),
+       .type   = V4L2_CTRL_TYPE_BUTTON,
+       .name    = "Restore User Settings",
+};
+
+static const struct v4l2_ctrl_config pwc_restore_factory_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(restore_factory),
+       .type   = V4L2_CTRL_TYPE_BUTTON,
+       .name    = "Restore Factory Settings",
+};
+
+static const struct v4l2_ctrl_config pwc_awb_speed_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(awb_speed),
+       .type   = V4L2_CTRL_TYPE_INTEGER,
+       .name   = "Auto White Balance Speed",
+       .min    = 1,
+       .max    = 32,
+       .step   = 1,
+};
+
+static const struct v4l2_ctrl_config pwc_awb_delay_cfg = {
+       .ops    = &pwc_ctrl_ops,
+       .id     = PWC_CID_CUSTOM(awb_delay),
+       .type   = V4L2_CTRL_TYPE_INTEGER,
+       .name   = "Auto White Balance Delay",
+       .min    = 0,
+       .max    = 63,
+       .step   = 1,
+};
+
+int pwc_init_controls(struct pwc_device *pdev)
+{
+       struct v4l2_ctrl_handler *hdl;
+       struct v4l2_ctrl_config cfg;
+       int r, def;
+
+       hdl = &pdev->ctrl_handler;
+       r = v4l2_ctrl_handler_init(hdl, 20);
+       if (r)
+               return r;
+
+       /* Brightness, contrast, saturation, gamma */
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, BRIGHTNESS_FORMATTER, &def);
+       if (r || def > 127)
+               def = 63;
+       pdev->brightness = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_BRIGHTNESS, 0, 127, 1, def);
+
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, CONTRAST_FORMATTER, &def);
+       if (r || def > 63)
+               def = 31;
+       pdev->contrast = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_CONTRAST, 0, 63, 1, def);
+
+       if (pdev->type >= 675) {
+               if (pdev->type < 730)
+                       pdev->saturation_fmt = SATURATION_MODE_FORMATTER2;
+               else
+                       pdev->saturation_fmt = SATURATION_MODE_FORMATTER1;
+               r = pwc_get_s8_ctrl(pdev, GET_CHROM_CTL, pdev->saturation_fmt,
+                                   &def);
+               if (r || def < -100 || def > 100)
+                       def = 0;
+               pdev->saturation = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                                     V4L2_CID_SATURATION, -100, 100, 1, def);
+       }
+
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, GAMMA_FORMATTER, &def);
+       if (r || def > 31)
+               def = 15;
+       pdev->gamma = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_GAMMA, 0, 31, 1, def);
+
+       /* auto white balance, red gain, blue gain */
+       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, WB_MODE_FORMATTER, &def);
+       if (r || def > awb_auto)
+               def = awb_auto;
+       cfg = pwc_auto_white_balance_cfg;
+       cfg.name = v4l2_ctrl_get_name(cfg.id);
+       cfg.def = def;
+       pdev->auto_white_balance = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+       /* check auto controls to avoid NULL deref in v4l2_ctrl_auto_cluster */
+       if (!pdev->auto_white_balance)
+               return hdl->error;
+
+       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
+                           PRESET_MANUAL_RED_GAIN_FORMATTER, &def);
+       if (r)
+               def = 127;
+       pdev->red_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_RED_BALANCE, 0, 255, 1, def);
+
+       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
+                           PRESET_MANUAL_BLUE_GAIN_FORMATTER, &def);
+       if (r)
+               def = 127;
+       pdev->blue_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_BLUE_BALANCE, 0, 255, 1, def);
+
+       v4l2_ctrl_auto_cluster(3, &pdev->auto_white_balance, awb_manual, true);
+
+       /* autogain, gain */
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AGC_MODE_FORMATTER, &def);
+       if (r || (def != 0 && def != 0xff))
+               def = 0;
+       /* Note a register value if 0 means auto gain is on */
+       pdev->autogain = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_AUTOGAIN, 0, 1, 1, def == 0);
+       if (!pdev->autogain)
+               return hdl->error;
+
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, PRESET_AGC_FORMATTER, &def);
+       if (r || def > 63)
+               def = 31;
+       pdev->gain = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_GAIN, 0, 63, 1, def);
+
+       /* auto exposure, exposure */
+       if (DEVICE_USE_CODEC2(pdev->type)) {
+               r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, SHUTTER_MODE_FORMATTER,
+                                   &def);
+               if (r || (def != 0 && def != 0xff))
+                       def = 0;
+               /*
+                * def = 0 auto, def = ff manual
+                * menu idx 0 = auto, idx 1 = manual
+                */
+               pdev->exposure_auto = v4l2_ctrl_new_std_menu(hdl,
+                                       &pwc_ctrl_ops,
+                                       V4L2_CID_EXPOSURE_AUTO,
+                                       1, 0, def != 0);
+               if (!pdev->exposure_auto)
+                       return hdl->error;
+
+               /* GET_LUM_CTL, PRESET_SHUTTER_FORMATTER is unreliable */
+               r = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
+                                    READ_SHUTTER_FORMATTER, &def);
+               if (r || def > 655)
+                       def = 655;
+               pdev->exposure = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                                       V4L2_CID_EXPOSURE, 0, 655, 1, def);
+               /* CODEC2: separate auto gain & auto exposure */
+               v4l2_ctrl_auto_cluster(2, &pdev->autogain, 0, true);
+               v4l2_ctrl_auto_cluster(2, &pdev->exposure_auto,
+                                      V4L2_EXPOSURE_MANUAL, true);
+       } else if (DEVICE_USE_CODEC3(pdev->type)) {
+               /* GET_LUM_CTL, PRESET_SHUTTER_FORMATTER is unreliable */
+               r = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
+                                    READ_SHUTTER_FORMATTER, &def);
+               if (r || def > 255)
+                       def = 255;
+               pdev->exposure = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                                       V4L2_CID_EXPOSURE, 0, 255, 1, def);
+               /* CODEC3: both gain and exposure controlled by autogain */
+               pdev->autogain_expo_cluster[0] = pdev->autogain;
+               pdev->autogain_expo_cluster[1] = pdev->gain;
+               pdev->autogain_expo_cluster[2] = pdev->exposure;
+               v4l2_ctrl_auto_cluster(3, pdev->autogain_expo_cluster,
+                                      0, true);
+       }
+
+       /* color / bw setting */
+       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, COLOUR_MODE_FORMATTER,
+                        &def);
+       if (r || (def != 0 && def != 0xff))
+               def = 0xff;
+       /* def = 0 bw, def = ff color, menu idx 0 = color, idx 1 = bw */
+       pdev->colorfx = v4l2_ctrl_new_std_menu(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_COLORFX, 1, 0, def == 0);
+
+       /* autocontour, contour */
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &def);
+       if (r || (def != 0 && def != 0xff))
+               def = 0;
+       cfg = pwc_autocontour_cfg;
+       cfg.def = def == 0;
+       pdev->autocontour = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+       if (!pdev->autocontour)
+               return hdl->error;
+
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, &def);
+       if (r || def > 63)
+               def = 31;
+       cfg = pwc_contour_cfg;
+       cfg.def = def;
+       pdev->contour = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+       v4l2_ctrl_auto_cluster(2, &pdev->autocontour, 0, false);
+
+       /* backlight */
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
+                           BACK_LIGHT_COMPENSATION_FORMATTER, &def);
+       if (r || (def != 0 && def != 0xff))
+               def = 0;
+       cfg = pwc_backlight_cfg;
+       cfg.name = v4l2_ctrl_get_name(cfg.id);
+       cfg.def = def == 0;
+       pdev->backlight = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+       /* flikker rediction */
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
+                           FLICKERLESS_MODE_FORMATTER, &def);
+       if (r || (def != 0 && def != 0xff))
+               def = 0;
+       cfg = pwc_flicker_cfg;
+       cfg.name = v4l2_ctrl_get_name(cfg.id);
+       cfg.def = def == 0;
+       pdev->flicker = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+       /* Dynamic noise reduction */
+       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
+                           DYNAMIC_NOISE_CONTROL_FORMATTER, &def);
+       if (r || def > 3)
+               def = 2;
+       cfg = pwc_noise_reduction_cfg;
+       cfg.def = def;
+       pdev->noise_reduction = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+       /* Save / Restore User / Factory Settings */
+       pdev->save_user = v4l2_ctrl_new_custom(hdl, &pwc_save_user_cfg, NULL);
+       pdev->restore_user = v4l2_ctrl_new_custom(hdl, &pwc_restore_user_cfg,
+                                                 NULL);
+       if (pdev->restore_user)
+               pdev->restore_user->flags |= V4L2_CTRL_FLAG_UPDATE;
+       pdev->restore_factory = v4l2_ctrl_new_custom(hdl,
+                                                    &pwc_restore_factory_cfg,
+                                                    NULL);
+       if (pdev->restore_factory)
+               pdev->restore_factory->flags |= V4L2_CTRL_FLAG_UPDATE;
+
+       /* Auto White Balance speed & delay */
+       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
+                           AWB_CONTROL_SPEED_FORMATTER, &def);
+       if (r || def < 1 || def > 32)
+               def = 1;
+       cfg = pwc_awb_speed_cfg;
+       cfg.def = def;
+       pdev->awb_speed = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
+                           AWB_CONTROL_DELAY_FORMATTER, &def);
+       if (r || def > 63)
+               def = 0;
+       cfg = pwc_awb_delay_cfg;
+       cfg.def = def;
+       pdev->awb_delay = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
+
+       if (!(pdev->features & FEATURE_MOTOR_PANTILT))
+               return hdl->error;
+
+       /* Motor pan / tilt / reset */
+       pdev->motor_pan = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_PAN_RELATIVE, -4480, 4480, 64, 0);
+       if (!pdev->motor_pan)
+               return hdl->error;
+       pdev->motor_tilt = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_TILT_RELATIVE, -1920, 1920, 64, 0);
+       pdev->motor_pan_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_PAN_RESET, 0, 0, 0, 0);
+       pdev->motor_tilt_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
+                               V4L2_CID_TILT_RESET, 0, 0, 0, 0);
+       v4l2_ctrl_cluster(4, &pdev->motor_pan);
+
+       return hdl->error;
+}
+
+static void pwc_vidioc_fill_fmt(struct v4l2_format *f,
+       int width, int height, u32 pixfmt)
+{
+       memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
+       f->fmt.pix.width        = width;
+       f->fmt.pix.height       = height;
+       f->fmt.pix.field        = V4L2_FIELD_NONE;
+       f->fmt.pix.pixelformat  = pixfmt;
+       f->fmt.pix.bytesperline = f->fmt.pix.width;
+       f->fmt.pix.sizeimage    = f->fmt.pix.height * f->fmt.pix.width * 3 / 2;
+       f->fmt.pix.colorspace   = V4L2_COLORSPACE_SRGB;
+       PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() "
+                       "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n",
+                       f->fmt.pix.width,
+                       f->fmt.pix.height,
+                       f->fmt.pix.bytesperline,
+                       f->fmt.pix.sizeimage,
+                       (f->fmt.pix.pixelformat)&255,
+                       (f->fmt.pix.pixelformat>>8)&255,
+                       (f->fmt.pix.pixelformat>>16)&255,
+                       (f->fmt.pix.pixelformat>>24)&255);
+}
+
+/* ioctl(VIDIOC_TRY_FMT) */
+static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
+{
+       int size;
+
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+               return -EINVAL;
+       }
+
+       switch (f->fmt.pix.pixelformat) {
+               case V4L2_PIX_FMT_YUV420:
+                       break;
+               case V4L2_PIX_FMT_PWC1:
+                       if (DEVICE_USE_CODEC23(pdev->type)) {
+                               PWC_DEBUG_IOCTL("codec1 is only supported for old pwc webcam\n");
+                               return -EINVAL;
+                       }
+                       break;
+               case V4L2_PIX_FMT_PWC2:
+                       if (DEVICE_USE_CODEC1(pdev->type)) {
+                               PWC_DEBUG_IOCTL("codec23 is only supported for new pwc webcam\n");
+                               return -EINVAL;
+                       }
+                       break;
+               default:
+                       PWC_DEBUG_IOCTL("Unsupported pixel format\n");
+                       return -EINVAL;
+
+       }
+
+       size = pwc_get_size(pdev, f->fmt.pix.width, f->fmt.pix.height);
+       pwc_vidioc_fill_fmt(f,
+                           pwc_image_sizes[size][0],
+                           pwc_image_sizes[size][1],
+                           f->fmt.pix.pixelformat);
+
+       return 0;
+}
+
+/* ioctl(VIDIOC_SET_FMT) */
+
+static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+       int ret, pixelformat, compression = 0;
+
+       ret = pwc_vidioc_try_fmt(pdev, f);
+       if (ret < 0)
+               return ret;
+
+       if (vb2_is_busy(&pdev->vb_queue))
+               return -EBUSY;
+
+       pixelformat = f->fmt.pix.pixelformat;
+
+       PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d "
+                       "format=%c%c%c%c\n",
+                       f->fmt.pix.width, f->fmt.pix.height, pdev->vframes,
+                       (pixelformat)&255,
+                       (pixelformat>>8)&255,
+                       (pixelformat>>16)&255,
+                       (pixelformat>>24)&255);
+
+       ret = pwc_set_video_mode(pdev, f->fmt.pix.width, f->fmt.pix.height,
+                                pixelformat, 30, &compression, 0);
+
+       PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret);
+
+       pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
+       return ret;
+}
+
+static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+
+       strcpy(cap->driver, PWC_NAME);
+       strlcpy(cap->card, pdev->vdev.name, sizeof(cap->card));
+       usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info));
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+                                       V4L2_CAP_READWRITE;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       return 0;
+}
+
+static int pwc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+       if (i->index)   /* Only one INPUT is supported */
+               return -EINVAL;
+
+       strlcpy(i->name, "Camera", sizeof(i->name));
+       i->type = V4L2_INPUT_TYPE_CAMERA;
+       return 0;
+}
+
+static int pwc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+       *i = 0;
+       return 0;
+}
+
+static int pwc_s_input(struct file *file, void *fh, unsigned int i)
+{
+       return i ? -EINVAL : 0;
+}
+
+static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct pwc_device *pdev =
+               container_of(ctrl->handler, struct pwc_device, ctrl_handler);
+       int ret = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               if (pdev->color_bal_valid &&
+                       (pdev->auto_white_balance->val != awb_auto ||
+                        time_before(jiffies,
+                               pdev->last_color_bal_update + HZ / 4))) {
+                       pdev->red_balance->val  = pdev->last_red_balance;
+                       pdev->blue_balance->val = pdev->last_blue_balance;
+                       break;
+               }
+               ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
+                                     READ_RED_GAIN_FORMATTER,
+                                     &pdev->red_balance->val);
+               if (ret)
+                       break;
+               ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
+                                     READ_BLUE_GAIN_FORMATTER,
+                                     &pdev->blue_balance->val);
+               if (ret)
+                       break;
+               pdev->last_red_balance  = pdev->red_balance->val;
+               pdev->last_blue_balance = pdev->blue_balance->val;
+               pdev->last_color_bal_update = jiffies;
+               pdev->color_bal_valid = true;
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if (pdev->gain_valid && time_before(jiffies,
+                               pdev->last_gain_update + HZ / 4)) {
+                       pdev->gain->val = pdev->last_gain;
+                       break;
+               }
+               ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
+                                     READ_AGC_FORMATTER, &pdev->gain->val);
+               if (ret)
+                       break;
+               pdev->last_gain = pdev->gain->val;
+               pdev->last_gain_update = jiffies;
+               pdev->gain_valid = true;
+               if (!DEVICE_USE_CODEC3(pdev->type))
+                       break;
+               /* Fall through for CODEC3 where autogain also controls expo */
+       case V4L2_CID_EXPOSURE_AUTO:
+               if (pdev->exposure_valid && time_before(jiffies,
+                               pdev->last_exposure_update + HZ / 4)) {
+                       pdev->exposure->val = pdev->last_exposure;
+                       break;
+               }
+               ret = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
+                                      READ_SHUTTER_FORMATTER,
+                                      &pdev->exposure->val);
+               if (ret)
+                       break;
+               pdev->last_exposure = pdev->exposure->val;
+               pdev->last_exposure_update = jiffies;
+               pdev->exposure_valid = true;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       if (ret)
+               PWC_ERROR("g_ctrl %s error %d\n", ctrl->name, ret);
+
+       return ret;
+}
+
+static int pwc_set_awb(struct pwc_device *pdev)
+{
+       int ret;
+
+       if (pdev->auto_white_balance->is_new) {
+               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+                                     WB_MODE_FORMATTER,
+                                     pdev->auto_white_balance->val);
+               if (ret)
+                       return ret;
+
+               if (pdev->auto_white_balance->val != awb_manual)
+                       pdev->color_bal_valid = false; /* Force cache update */
+
+               /*
+                * If this is a preset, update our red / blue balance values
+                * so that events get generated for the new preset values
+                */
+               if (pdev->auto_white_balance->val == awb_indoor ||
+                   pdev->auto_white_balance->val == awb_outdoor ||
+                   pdev->auto_white_balance->val == awb_fl)
+                       pwc_g_volatile_ctrl(pdev->auto_white_balance);
+       }
+       if (pdev->auto_white_balance->val != awb_manual)
+               return 0;
+
+       if (pdev->red_balance->is_new) {
+               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+                                     PRESET_MANUAL_RED_GAIN_FORMATTER,
+                                     pdev->red_balance->val);
+               if (ret)
+                       return ret;
+       }
+
+       if (pdev->blue_balance->is_new) {
+               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+                                     PRESET_MANUAL_BLUE_GAIN_FORMATTER,
+                                     pdev->blue_balance->val);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+/* For CODEC2 models which have separate autogain and auto exposure */
+static int pwc_set_autogain(struct pwc_device *pdev)
+{
+       int ret;
+
+       if (pdev->autogain->is_new) {
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     AGC_MODE_FORMATTER,
+                                     pdev->autogain->val ? 0 : 0xff);
+               if (ret)
+                       return ret;
+
+               if (pdev->autogain->val)
+                       pdev->gain_valid = false; /* Force cache update */
+       }
+
+       if (pdev->autogain->val)
+               return 0;
+
+       if (pdev->gain->is_new) {
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     PRESET_AGC_FORMATTER,
+                                     pdev->gain->val);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+/* For CODEC2 models which have separate autogain and auto exposure */
+static int pwc_set_exposure_auto(struct pwc_device *pdev)
+{
+       int ret;
+       int is_auto = pdev->exposure_auto->val == V4L2_EXPOSURE_AUTO;
+
+       if (pdev->exposure_auto->is_new) {
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     SHUTTER_MODE_FORMATTER,
+                                     is_auto ? 0 : 0xff);
+               if (ret)
+                       return ret;
+
+               if (is_auto)
+                       pdev->exposure_valid = false; /* Force cache update */
+       }
+
+       if (is_auto)
+               return 0;
+
+       if (pdev->exposure->is_new) {
+               ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
+                                      PRESET_SHUTTER_FORMATTER,
+                                      pdev->exposure->val);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+/* For CODEC3 models which have autogain controlling both gain and exposure */
+static int pwc_set_autogain_expo(struct pwc_device *pdev)
+{
+       int ret;
+
+       if (pdev->autogain->is_new) {
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     AGC_MODE_FORMATTER,
+                                     pdev->autogain->val ? 0 : 0xff);
+               if (ret)
+                       return ret;
+
+               if (pdev->autogain->val) {
+                       pdev->gain_valid     = false; /* Force cache update */
+                       pdev->exposure_valid = false; /* Force cache update */
+               }
+       }
+
+       if (pdev->autogain->val)
+               return 0;
+
+       if (pdev->gain->is_new) {
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     PRESET_AGC_FORMATTER,
+                                     pdev->gain->val);
+               if (ret)
+                       return ret;
+       }
+
+       if (pdev->exposure->is_new) {
+               ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
+                                      PRESET_SHUTTER_FORMATTER,
+                                      pdev->exposure->val);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+static int pwc_set_motor(struct pwc_device *pdev)
+{
+       int ret;
+
+       pdev->ctrl_buf[0] = 0;
+       if (pdev->motor_pan_reset->is_new)
+               pdev->ctrl_buf[0] |= 0x01;
+       if (pdev->motor_tilt_reset->is_new)
+               pdev->ctrl_buf[0] |= 0x02;
+       if (pdev->motor_pan_reset->is_new || pdev->motor_tilt_reset->is_new) {
+               ret = send_control_msg(pdev, SET_MPT_CTL,
+                                      PT_RESET_CONTROL_FORMATTER,
+                                      pdev->ctrl_buf, 1);
+               if (ret < 0)
+                       return ret;
+       }
+
+       memset(pdev->ctrl_buf, 0, 4);
+       if (pdev->motor_pan->is_new) {
+               pdev->ctrl_buf[0] = pdev->motor_pan->val & 0xFF;
+               pdev->ctrl_buf[1] = (pdev->motor_pan->val >> 8);
+       }
+       if (pdev->motor_tilt->is_new) {
+               pdev->ctrl_buf[2] = pdev->motor_tilt->val & 0xFF;
+               pdev->ctrl_buf[3] = (pdev->motor_tilt->val >> 8);
+       }
+       if (pdev->motor_pan->is_new || pdev->motor_tilt->is_new) {
+               ret = send_control_msg(pdev, SET_MPT_CTL,
+                                      PT_RELATIVE_CONTROL_FORMATTER,
+                                      pdev->ctrl_buf, 4);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct pwc_device *pdev =
+               container_of(ctrl->handler, struct pwc_device, ctrl_handler);
+       int ret = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     BRIGHTNESS_FORMATTER, ctrl->val);
+               break;
+       case V4L2_CID_CONTRAST:
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     CONTRAST_FORMATTER, ctrl->val);
+               break;
+       case V4L2_CID_SATURATION:
+               ret = pwc_set_s8_ctrl(pdev, SET_CHROM_CTL,
+                                     pdev->saturation_fmt, ctrl->val);
+               break;
+       case V4L2_CID_GAMMA:
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     GAMMA_FORMATTER, ctrl->val);
+               break;
+       case V4L2_CID_AUTO_WHITE_BALANCE:
+               ret = pwc_set_awb(pdev);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if (DEVICE_USE_CODEC2(pdev->type))
+                       ret = pwc_set_autogain(pdev);
+               else if (DEVICE_USE_CODEC3(pdev->type))
+                       ret = pwc_set_autogain_expo(pdev);
+               else
+                       ret = -EINVAL;
+               break;
+       case V4L2_CID_EXPOSURE_AUTO:
+               if (DEVICE_USE_CODEC2(pdev->type))
+                       ret = pwc_set_exposure_auto(pdev);
+               else
+                       ret = -EINVAL;
+               break;
+       case V4L2_CID_COLORFX:
+               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+                                     COLOUR_MODE_FORMATTER,
+                                     ctrl->val ? 0 : 0xff);
+               break;
+       case PWC_CID_CUSTOM(autocontour):
+               if (pdev->autocontour->is_new) {
+                       ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                       AUTO_CONTOUR_FORMATTER,
+                                       pdev->autocontour->val ? 0 : 0xff);
+               }
+               if (ret == 0 && pdev->contour->is_new) {
+                       ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                             PRESET_CONTOUR_FORMATTER,
+                                             pdev->contour->val);
+               }
+               break;
+       case V4L2_CID_BACKLIGHT_COMPENSATION:
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     BACK_LIGHT_COMPENSATION_FORMATTER,
+                                     ctrl->val ? 0 : 0xff);
+               break;
+       case V4L2_CID_BAND_STOP_FILTER:
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     FLICKERLESS_MODE_FORMATTER,
+                                     ctrl->val ? 0 : 0xff);
+               break;
+       case PWC_CID_CUSTOM(noise_reduction):
+               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
+                                     DYNAMIC_NOISE_CONTROL_FORMATTER,
+                                     ctrl->val);
+               break;
+       case PWC_CID_CUSTOM(save_user):
+               ret = pwc_button_ctrl(pdev, SAVE_USER_DEFAULTS_FORMATTER);
+               break;
+       case PWC_CID_CUSTOM(restore_user):
+               ret = pwc_button_ctrl(pdev, RESTORE_USER_DEFAULTS_FORMATTER);
+               break;
+       case PWC_CID_CUSTOM(restore_factory):
+               ret = pwc_button_ctrl(pdev,
+                                     RESTORE_FACTORY_DEFAULTS_FORMATTER);
+               break;
+       case PWC_CID_CUSTOM(awb_speed):
+               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+                                     AWB_CONTROL_SPEED_FORMATTER,
+                                     ctrl->val);
+               break;
+       case PWC_CID_CUSTOM(awb_delay):
+               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
+                                     AWB_CONTROL_DELAY_FORMATTER,
+                                     ctrl->val);
+               break;
+       case V4L2_CID_PAN_RELATIVE:
+               ret = pwc_set_motor(pdev);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+
+       if (ret)
+               PWC_ERROR("s_ctrl %s error %d\n", ctrl->name, ret);
+
+       return ret;
+}
+
+static int pwc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+
+       /* We only support two format: the raw format, and YUV */
+       switch (f->index) {
+       case 0:
+               /* RAW format */
+               f->pixelformat = pdev->type <= 646 ? V4L2_PIX_FMT_PWC1 : V4L2_PIX_FMT_PWC2;
+               f->flags = V4L2_FMT_FLAG_COMPRESSED;
+               strlcpy(f->description, "Raw Philips Webcam", sizeof(f->description));
+               break;
+       case 1:
+               f->pixelformat = V4L2_PIX_FMT_YUV420;
+               strlcpy(f->description, "4:2:0, planar, Y-Cb-Cr", sizeof(f->description));
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+
+       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",
+                       pdev->width, pdev->height);
+       pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
+       return 0;
+}
+
+static int pwc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+
+       return pwc_vidioc_try_fmt(pdev, f);
+}
+
+static int pwc_enum_framesizes(struct file *file, void *fh,
+                                        struct v4l2_frmsizeenum *fsize)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+       unsigned int i = 0, index = fsize->index;
+
+       if (fsize->pixel_format == V4L2_PIX_FMT_YUV420 ||
+           (fsize->pixel_format == V4L2_PIX_FMT_PWC1 &&
+                       DEVICE_USE_CODEC1(pdev->type)) ||
+           (fsize->pixel_format == V4L2_PIX_FMT_PWC2 &&
+                       DEVICE_USE_CODEC23(pdev->type))) {
+               for (i = 0; i < PSZ_MAX; i++) {
+                       if (!(pdev->image_mask & (1UL << i)))
+                               continue;
+                       if (!index--) {
+                               fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+                               fsize->discrete.width = pwc_image_sizes[i][0];
+                               fsize->discrete.height = pwc_image_sizes[i][1];
+                               return 0;
+                       }
+               }
+       }
+       return -EINVAL;
+}
+
+static int pwc_enum_frameintervals(struct file *file, void *fh,
+                                          struct v4l2_frmivalenum *fival)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+       int size = -1;
+       unsigned int i;
+
+       for (i = 0; i < PSZ_MAX; i++) {
+               if (pwc_image_sizes[i][0] == fival->width &&
+                               pwc_image_sizes[i][1] == fival->height) {
+                       size = i;
+                       break;
+               }
+       }
+
+       /* TODO: Support raw format */
+       if (size < 0 || fival->pixel_format != V4L2_PIX_FMT_YUV420)
+               return -EINVAL;
+
+       i = pwc_get_fps(pdev, fival->index, size);
+       if (!i)
+               return -EINVAL;
+
+       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+       fival->discrete.numerator = 1;
+       fival->discrete.denominator = i;
+
+       return 0;
+}
+
+static int pwc_g_parm(struct file *file, void *fh,
+                     struct v4l2_streamparm *parm)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       memset(parm, 0, sizeof(*parm));
+
+       parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       parm->parm.capture.readbuffers = MIN_FRAMES;
+       parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME;
+       parm->parm.capture.timeperframe.denominator = pdev->vframes;
+       parm->parm.capture.timeperframe.numerator = 1;
+
+       return 0;
+}
+
+static int pwc_s_parm(struct file *file, void *fh,
+                     struct v4l2_streamparm *parm)
+{
+       struct pwc_device *pdev = video_drvdata(file);
+       int compression = 0;
+       int ret, fps;
+
+       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       /* If timeperframe == 0, then reset the framerate to the nominal value.
+          We pick a high framerate here, and let pwc_set_video_mode() figure
+          out the best match. */
+       if (parm->parm.capture.timeperframe.numerator == 0 ||
+           parm->parm.capture.timeperframe.denominator == 0)
+               fps = 30;
+       else
+               fps = parm->parm.capture.timeperframe.denominator /
+                     parm->parm.capture.timeperframe.numerator;
+
+       if (vb2_is_busy(&pdev->vb_queue))
+               return -EBUSY;
+
+       ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
+                                fps, &compression, 0);
+
+       pwc_g_parm(file, fh, parm);
+
+       return ret;
+}
+
+const struct v4l2_ioctl_ops pwc_ioctl_ops = {
+       .vidioc_querycap                    = pwc_querycap,
+       .vidioc_enum_input                  = pwc_enum_input,
+       .vidioc_g_input                     = pwc_g_input,
+       .vidioc_s_input                     = pwc_s_input,
+       .vidioc_enum_fmt_vid_cap            = pwc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap               = pwc_g_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap               = pwc_s_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap             = pwc_try_fmt_vid_cap,
+       .vidioc_reqbufs                     = vb2_ioctl_reqbufs,
+       .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_enum_framesizes             = pwc_enum_framesizes,
+       .vidioc_enum_frameintervals         = pwc_enum_frameintervals,
+       .vidioc_g_parm                      = pwc_g_parm,
+       .vidioc_s_parm                      = pwc_s_parm,
+       .vidioc_subscribe_event             = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event           = v4l2_event_unsubscribe,
+};
diff --git a/drivers/media/usb/pwc/pwc.h b/drivers/media/usb/pwc/pwc.h
new file mode 100644 (file)
index 0000000..7a6a0d3
--- /dev/null
@@ -0,0 +1,393 @@
+/* (C) 1999-2003 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef PWC_H
+#define PWC_H
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/errno.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-vmalloc.h>
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+#include <linux/input.h>
+#endif
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
+
+/* Version block */
+#define PWC_VERSION    "10.0.15"
+#define PWC_NAME       "pwc"
+#define PFX            PWC_NAME ": "
+
+
+/* Trace certain actions in the driver */
+#define PWC_DEBUG_LEVEL_MODULE (1<<0)
+#define PWC_DEBUG_LEVEL_PROBE  (1<<1)
+#define PWC_DEBUG_LEVEL_OPEN   (1<<2)
+#define PWC_DEBUG_LEVEL_READ   (1<<3)
+#define PWC_DEBUG_LEVEL_MEMORY (1<<4)
+#define PWC_DEBUG_LEVEL_FLOW   (1<<5)
+#define PWC_DEBUG_LEVEL_SIZE   (1<<6)
+#define PWC_DEBUG_LEVEL_IOCTL  (1<<7)
+#define PWC_DEBUG_LEVEL_TRACE  (1<<8)
+
+#define PWC_DEBUG_MODULE(fmt, args...) PWC_DEBUG(MODULE, fmt, ##args)
+#define PWC_DEBUG_PROBE(fmt, args...) PWC_DEBUG(PROBE, fmt, ##args)
+#define PWC_DEBUG_OPEN(fmt, args...) PWC_DEBUG(OPEN, fmt, ##args)
+#define PWC_DEBUG_READ(fmt, args...) PWC_DEBUG(READ, fmt, ##args)
+#define PWC_DEBUG_MEMORY(fmt, args...) PWC_DEBUG(MEMORY, fmt, ##args)
+#define PWC_DEBUG_FLOW(fmt, args...) PWC_DEBUG(FLOW, fmt, ##args)
+#define PWC_DEBUG_SIZE(fmt, args...) PWC_DEBUG(SIZE, fmt, ##args)
+#define PWC_DEBUG_IOCTL(fmt, args...) PWC_DEBUG(IOCTL, fmt, ##args)
+#define PWC_DEBUG_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
+
+
+#ifdef CONFIG_USB_PWC_DEBUG
+
+#define PWC_DEBUG_LEVEL        (PWC_DEBUG_LEVEL_MODULE)
+
+#define PWC_DEBUG(level, fmt, args...) do {\
+       if ((PWC_DEBUG_LEVEL_ ##level) & pwc_trace) \
+               printk(KERN_DEBUG PFX fmt, ##args); \
+       } while (0)
+
+#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
+#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
+#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
+#define PWC_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
+
+#else /* if ! CONFIG_USB_PWC_DEBUG */
+
+#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
+#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
+#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
+#define PWC_TRACE(fmt, args...) do { } while(0)
+#define PWC_DEBUG(level, fmt, args...) do { } while(0)
+
+#define pwc_trace 0
+
+#endif
+
+/* Defines for ToUCam cameras */
+#define TOUCAM_HEADER_SIZE             8
+#define TOUCAM_TRAILER_SIZE            4
+
+#define FEATURE_MOTOR_PANTILT          0x0001
+#define FEATURE_CODEC1                 0x0002
+#define FEATURE_CODEC2                 0x0004
+
+#define MAX_WIDTH              640
+#define MAX_HEIGHT             480
+
+/* Ignore errors in the first N frames, to allow for startup delays */
+#define FRAME_LOWMARK 5
+
+/* Size and number of buffers for the ISO pipe. */
+#define MAX_ISO_BUFS           3
+#define ISO_FRAMES_PER_DESC    10
+#define ISO_MAX_FRAME_SIZE     960
+#define ISO_BUFFER_SIZE        (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
+
+/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */
+#define PWC_FRAME_SIZE                 (460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE)
+
+/* Absolute minimum and maximum number of buffers available for mmap() */
+#define MIN_FRAMES             2
+#define MAX_FRAMES             16
+
+/* Some macros to quickly find the type of a webcam */
+#define DEVICE_USE_CODEC1(x) ((x)<675)
+#define DEVICE_USE_CODEC2(x) ((x)>=675 && (x)<700)
+#define DEVICE_USE_CODEC3(x) ((x)>=700)
+#define DEVICE_USE_CODEC23(x) ((x)>=675)
+
+/* Request types: video */
+#define SET_LUM_CTL                    0x01
+#define GET_LUM_CTL                    0x02
+#define SET_CHROM_CTL                  0x03
+#define GET_CHROM_CTL                  0x04
+#define SET_STATUS_CTL                 0x05
+#define GET_STATUS_CTL                 0x06
+#define SET_EP_STREAM_CTL              0x07
+#define GET_EP_STREAM_CTL              0x08
+#define GET_XX_CTL                     0x09
+#define SET_XX_CTL                     0x0A
+#define GET_XY_CTL                     0x0B
+#define SET_XY_CTL                     0x0C
+#define SET_MPT_CTL                    0x0D
+#define GET_MPT_CTL                    0x0E
+
+/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
+#define AGC_MODE_FORMATTER                     0x2000
+#define PRESET_AGC_FORMATTER                   0x2100
+#define SHUTTER_MODE_FORMATTER                 0x2200
+#define PRESET_SHUTTER_FORMATTER               0x2300
+#define PRESET_CONTOUR_FORMATTER               0x2400
+#define AUTO_CONTOUR_FORMATTER                 0x2500
+#define BACK_LIGHT_COMPENSATION_FORMATTER      0x2600
+#define CONTRAST_FORMATTER                     0x2700
+#define DYNAMIC_NOISE_CONTROL_FORMATTER                0x2800
+#define FLICKERLESS_MODE_FORMATTER             0x2900
+#define AE_CONTROL_SPEED                       0x2A00
+#define BRIGHTNESS_FORMATTER                   0x2B00
+#define GAMMA_FORMATTER                                0x2C00
+
+/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
+#define WB_MODE_FORMATTER                      0x1000
+#define AWB_CONTROL_SPEED_FORMATTER            0x1100
+#define AWB_CONTROL_DELAY_FORMATTER            0x1200
+#define PRESET_MANUAL_RED_GAIN_FORMATTER       0x1300
+#define PRESET_MANUAL_BLUE_GAIN_FORMATTER      0x1400
+#define COLOUR_MODE_FORMATTER                  0x1500
+#define SATURATION_MODE_FORMATTER1             0x1600
+#define SATURATION_MODE_FORMATTER2             0x1700
+
+/* Selectors for the Status controls [GS]ET_STATUS_CTL */
+#define SAVE_USER_DEFAULTS_FORMATTER           0x0200
+#define RESTORE_USER_DEFAULTS_FORMATTER                0x0300
+#define RESTORE_FACTORY_DEFAULTS_FORMATTER     0x0400
+#define READ_AGC_FORMATTER                     0x0500
+#define READ_SHUTTER_FORMATTER                 0x0600
+#define READ_RED_GAIN_FORMATTER                        0x0700
+#define READ_BLUE_GAIN_FORMATTER               0x0800
+
+/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */
+#define PT_RELATIVE_CONTROL_FORMATTER          0x01
+#define PT_RESET_CONTROL_FORMATTER             0x02
+#define PT_STATUS_FORMATTER                    0x03
+
+/* Enumeration of image sizes */
+#define PSZ_SQCIF      0x00
+#define PSZ_QSIF       0x01
+#define PSZ_QCIF       0x02
+#define PSZ_SIF                0x03
+#define PSZ_CIF                0x04
+#define PSZ_VGA                0x05
+#define PSZ_MAX                6
+
+struct pwc_raw_frame {
+       __le16 type;            /* type of the webcam */
+       __le16 vbandlength;     /* Size of 4 lines compressed (used by the
+                                  decompressor) */
+       __u8   cmd[4];          /* the four byte of the command (in case of
+                                  nala, only the first 3 bytes is filled) */
+       __u8   rawframe[0];     /* frame_size = H / 4 * vbandlength */
+} __packed;
+
+/* intermediate buffers with raw data from the USB cam */
+struct pwc_frame_buf
+{
+       struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
+       struct list_head list;
+       void *data;
+       int filled;             /* number of bytes filled */
+};
+
+struct pwc_device
+{
+       struct video_device vdev;
+       struct v4l2_device v4l2_dev;
+
+       /* videobuf2 queue and queued buffers list */
+       struct vb2_queue vb_queue;
+       struct list_head queued_bufs;
+       spinlock_t queued_bufs_lock; /* Protects queued_bufs */
+
+       /* Note if taking both locks v4l2_lock must always be locked first! */
+       struct mutex v4l2_lock;      /* Protects everything else */
+       struct mutex vb_queue_lock;  /* Protects vb_queue and capt_file */
+
+       /* Pointer to our usb_device, will be NULL after unplug */
+       struct usb_device *udev; /* Both mutexes most be hold when setting! */
+
+       /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
+       int type;
+       int release;            /* release number */
+       int features;           /* feature bits */
+
+       /*** Video data ***/
+       int vendpoint;          /* video isoc endpoint */
+       int vcinterface;        /* video control interface */
+       int valternate;         /* alternate interface needed */
+       int vframes;            /* frames-per-second */
+       int pixfmt;             /* pixelformat: V4L2_PIX_FMT_YUV420 or _PWCX */
+       int vframe_count;       /* received frames */
+       int vmax_packet_size;   /* USB maxpacket size */
+       int vlast_packet_size;  /* for frame synchronisation */
+       int visoc_errors;       /* number of contiguous ISOC errors */
+       int vbandlength;        /* compressed band length; 0 is uncompressed */
+       char vsync;             /* used by isoc handler */
+       char vmirror;           /* for ToUCaM series */
+       char power_save;        /* Do powersaving for this cam */
+
+       unsigned char cmd_buf[13];
+       unsigned char *ctrl_buf;
+
+       struct urb *urbs[MAX_ISO_BUFS];
+
+       /*
+        * Frame currently being filled, this only gets touched by the
+        * isoc urb complete handler, and by stream start / stop since
+        * start / stop touch it before / after starting / killing the urbs
+        * no locking is needed around this
+        */
+       struct pwc_frame_buf *fill_buf;
+
+       int frame_header_size, frame_trailer_size;
+       int frame_size;
+       int frame_total_size;   /* including header & trailer */
+       int drop_frames;
+
+       union { /* private data for decompression engine */
+               struct pwc_dec1_private dec1;
+               struct pwc_dec23_private dec23;
+       };
+
+       /*
+        * We have an 'image' and a 'view', where 'image' is the fixed-size img
+        * as delivered by the camera, and 'view' is the size requested by the
+        * program. The camera image is centered in this viewport, laced with
+        * a gray or black border. view_min <= image <= view <= view_max;
+        */
+       int image_mask;                         /* supported sizes */
+       int width, height;                      /* current resolution */
+
+#ifdef CONFIG_USB_PWC_INPUT_EVDEV
+       struct input_dev *button_dev;   /* webcam snapshot button input */
+       char button_phys[64];
+#endif
+
+       /* controls */
+       struct v4l2_ctrl_handler        ctrl_handler;
+       u16                             saturation_fmt;
+       struct v4l2_ctrl                *brightness;
+       struct v4l2_ctrl                *contrast;
+       struct v4l2_ctrl                *saturation;
+       struct v4l2_ctrl                *gamma;
+       struct {
+               /* awb / red-blue balance cluster */
+               struct v4l2_ctrl        *auto_white_balance;
+               struct v4l2_ctrl        *red_balance;
+               struct v4l2_ctrl        *blue_balance;
+               /* usb ctrl transfers are slow, so we cache things */
+               int                     color_bal_valid;
+               unsigned long           last_color_bal_update; /* In jiffies */
+               s32                     last_red_balance;
+               s32                     last_blue_balance;
+       };
+       struct {
+               /* autogain / gain cluster */
+               struct v4l2_ctrl        *autogain;
+               struct v4l2_ctrl        *gain;
+               int                     gain_valid;
+               unsigned long           last_gain_update; /* In jiffies */
+               s32                     last_gain;
+       };
+       struct {
+               /* exposure_auto / exposure cluster */
+               struct v4l2_ctrl        *exposure_auto;
+               struct v4l2_ctrl        *exposure;
+               int                     exposure_valid;
+               unsigned long           last_exposure_update; /* In jiffies */
+               s32                     last_exposure;
+       };
+       struct v4l2_ctrl                *colorfx;
+       struct {
+               /* autocontour/contour cluster */
+               struct v4l2_ctrl        *autocontour;
+               struct v4l2_ctrl        *contour;
+       };
+       struct v4l2_ctrl                *backlight;
+       struct v4l2_ctrl                *flicker;
+       struct v4l2_ctrl                *noise_reduction;
+       struct v4l2_ctrl                *save_user;
+       struct v4l2_ctrl                *restore_user;
+       struct v4l2_ctrl                *restore_factory;
+       struct v4l2_ctrl                *awb_speed;
+       struct v4l2_ctrl                *awb_delay;
+       struct {
+               /* motor control cluster */
+               struct v4l2_ctrl        *motor_pan;
+               struct v4l2_ctrl        *motor_tilt;
+               struct v4l2_ctrl        *motor_pan_reset;
+               struct v4l2_ctrl        *motor_tilt_reset;
+       };
+       /* CODEC3 models have both gain and exposure controlled by autogain */
+       struct v4l2_ctrl                *autogain_expo_cluster[3];
+};
+
+/* Global variables */
+#ifdef CONFIG_USB_PWC_DEBUG
+extern int pwc_trace;
+#endif
+
+/** Functions in pwc-misc.c */
+/* sizes in pixels */
+extern const int pwc_image_sizes[PSZ_MAX][2];
+
+int pwc_get_size(struct pwc_device *pdev, int width, int height);
+void pwc_construct(struct pwc_device *pdev);
+
+/** Functions in pwc-ctrl.c */
+/* Request a certain video mode. Returns < 0 if not possible */
+extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
+       int pixfmt, int frames, int *compression, int send_to_cam);
+extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size);
+extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
+extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
+extern int send_control_msg(struct pwc_device *pdev,
+                           u8 request, u16 value, void *buf, int buflen);
+
+/* Control get / set helpers */
+int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data);
+int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data);
+int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data);
+#define pwc_set_s8_ctrl pwc_set_u8_ctrl
+int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *dat);
+int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data);
+int pwc_button_ctrl(struct pwc_device *pdev, u16 value);
+int pwc_init_controls(struct pwc_device *pdev);
+
+/* Power down or up the camera; not supported by all models */
+extern void pwc_camera_power(struct pwc_device *pdev, int power);
+
+extern const struct v4l2_ioctl_ops pwc_ioctl_ops;
+
+/** pwc-uncompress.c */
+/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
+int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf);
+
+#endif
diff --git a/drivers/media/usb/sn9c102/Kconfig b/drivers/media/usb/sn9c102/Kconfig
new file mode 100644 (file)
index 0000000..6ebaf29
--- /dev/null
@@ -0,0 +1,14 @@
+config USB_SN9C102
+       tristate "USB SN9C1xx PC Camera Controller support (DEPRECATED)"
+       depends on VIDEO_V4L2
+       ---help---
+         This driver is DEPRECATED please use the gspca sonixb and
+         sonixj modules instead.
+
+         Say Y here if you want support for cameras based on SONiX SN9C101,
+         SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers.
+
+         See <file:Documentation/video4linux/sn9c102.txt> for more info.
+
+         To compile this driver as a module, choose M here: the
+         module will be called sn9c102.
diff --git a/drivers/media/usb/sn9c102/Makefile b/drivers/media/usb/sn9c102/Makefile
new file mode 100644 (file)
index 0000000..7ecd5a9
--- /dev/null
@@ -0,0 +1,15 @@
+sn9c102-objs := sn9c102_core.o \
+               sn9c102_hv7131d.o \
+               sn9c102_hv7131r.o \
+               sn9c102_mi0343.o \
+               sn9c102_mi0360.o \
+               sn9c102_mt9v111.o \
+               sn9c102_ov7630.o \
+               sn9c102_ov7660.o \
+               sn9c102_pas106b.o \
+               sn9c102_pas202bcb.o \
+               sn9c102_tas5110c1b.o \
+               sn9c102_tas5110d.o \
+               sn9c102_tas5130d1b.o
+
+obj-$(CONFIG_USB_SN9C102)       += sn9c102.o
diff --git a/drivers/media/usb/sn9c102/sn9c102.h b/drivers/media/usb/sn9c102/sn9c102.h
new file mode 100644 (file)
index 0000000..2bc153e
--- /dev/null
@@ -0,0 +1,211 @@
+/***************************************************************************
+ * V4L2 driver for SN9C1xx PC Camera Controllers                           *
+ *                                                                         *
+ * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ *                                                                         *
+ * 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.               *
+ ***************************************************************************/
+
+#ifndef _SN9C102_H_
+#define _SN9C102_H_
+
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/types.h>
+#include <linux/param.h>
+#include <linux/rwsem.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+#include <linux/stddef.h>
+#include <linux/kref.h>
+
+#include "sn9c102_config.h"
+#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
+
+
+enum sn9c102_frame_state {
+       F_UNUSED,
+       F_QUEUED,
+       F_GRABBING,
+       F_DONE,
+       F_ERROR,
+};
+
+struct sn9c102_frame_t {
+       void* bufmem;
+       struct v4l2_buffer buf;
+       enum sn9c102_frame_state state;
+       struct list_head frame;
+       unsigned long vma_use_count;
+};
+
+enum sn9c102_dev_state {
+       DEV_INITIALIZED = 0x01,
+       DEV_DISCONNECTED = 0x02,
+       DEV_MISCONFIGURED = 0x04,
+};
+
+enum sn9c102_io_method {
+       IO_NONE,
+       IO_READ,
+       IO_MMAP,
+};
+
+enum sn9c102_stream_state {
+       STREAM_OFF,
+       STREAM_INTERRUPT,
+       STREAM_ON,
+};
+
+typedef char sn9c102_sof_header_t[62];
+
+struct sn9c102_sof_t {
+       sn9c102_sof_header_t header;
+       u16 bytesread;
+};
+
+struct sn9c102_sysfs_attr {
+       u16 reg, i2c_reg;
+       sn9c102_sof_header_t frame_header;
+};
+
+struct sn9c102_module_param {
+       u8 force_munmap;
+       u16 frame_timeout;
+};
+
+static DEFINE_MUTEX(sn9c102_sysfs_lock);
+static DECLARE_RWSEM(sn9c102_dev_lock);
+
+struct sn9c102_device {
+       struct video_device* v4ldev;
+
+       enum sn9c102_bridge bridge;
+       struct sn9c102_sensor sensor;
+
+       struct usb_device* usbdev;
+       struct urb* urb[SN9C102_URBS];
+       void* transfer_buffer[SN9C102_URBS];
+       u8* control_buffer;
+
+       struct sn9c102_frame_t *frame_current, frame[SN9C102_MAX_FRAMES];
+       struct list_head inqueue, outqueue;
+       u32 frame_count, nbuffers, nreadbuffers;
+
+       enum sn9c102_io_method io;
+       enum sn9c102_stream_state stream;
+
+       struct v4l2_jpegcompression compression;
+
+       struct sn9c102_sysfs_attr sysfs;
+       struct sn9c102_sof_t sof;
+       u16 reg[384];
+
+       struct sn9c102_module_param module_param;
+
+       struct kref kref;
+       enum sn9c102_dev_state state;
+       u8 users;
+
+       struct completion probe;
+       struct mutex open_mutex, fileop_mutex;
+       spinlock_t queue_lock;
+       wait_queue_head_t wait_open, wait_frame, wait_stream;
+};
+
+/*****************************************************************************/
+
+struct sn9c102_device*
+sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id)
+{
+       return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL;
+}
+
+
+void
+sn9c102_attach_sensor(struct sn9c102_device* cam,
+                     const struct sn9c102_sensor* sensor)
+{
+       memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
+}
+
+
+enum sn9c102_bridge
+sn9c102_get_bridge(struct sn9c102_device* cam)
+{
+       return cam->bridge;
+}
+
+
+struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam)
+{
+       return &cam->sensor;
+}
+
+/*****************************************************************************/
+
+#undef DBG
+#undef KDBG
+#ifdef SN9C102_DEBUG
+#      define DBG(level, fmt, args...)                                       \
+do {                                                                          \
+       if (debug >= (level)) {                                               \
+               if ((level) == 1)                                             \
+                       dev_err(&cam->usbdev->dev, fmt "\n", ## args);        \
+               else if ((level) == 2)                                        \
+                       dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
+               else if ((level) >= 3)                                        \
+                       dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n",      \
+                                __func__, __LINE__ , ## args);           \
+       }                                                                     \
+} while (0)
+#      define V4LDBG(level, name, cmd)                                       \
+do {                                                                          \
+       if (debug >= (level))                                                 \
+               v4l_printk_ioctl(name, cmd);                                  \
+} while (0)
+#      define KDBG(level, fmt, args...)                                      \
+do {                                                                          \
+       if (debug >= (level)) {                                               \
+               if ((level) == 1 || (level) == 2)                             \
+                       pr_info("sn9c102: " fmt "\n", ## args);               \
+               else if ((level) == 3)                                        \
+                       pr_debug("sn9c102: [%s:%d] " fmt "\n",                \
+                                __func__, __LINE__ , ## args);           \
+       }                                                                     \
+} while (0)
+#else
+#      define DBG(level, fmt, args...) do {;} while(0)
+#      define V4LDBG(level, name, cmd) do {;} while(0)
+#      define KDBG(level, fmt, args...) do {;} while(0)
+#endif
+
+#undef PDBG
+#define PDBG(fmt, args...)                                                    \
+dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \
+        __LINE__ , ## args)
+
+#undef PDBGG
+#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
+
+#endif /* _SN9C102_H_ */
diff --git a/drivers/media/usb/sn9c102/sn9c102_config.h b/drivers/media/usb/sn9c102/sn9c102_config.h
new file mode 100644 (file)
index 0000000..0f4e037
--- /dev/null
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * Global parameters for the V4L2 driver for SN9C1xx PC Camera Controllers *
+ *                                                                         *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * 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.               *
+ ***************************************************************************/
+
+#ifndef _SN9C102_CONFIG_H_
+#define _SN9C102_CONFIG_H_
+
+#include <linux/types.h>
+#include <linux/jiffies.h>
+
+#define SN9C102_DEBUG
+#define SN9C102_DEBUG_LEVEL       2
+#define SN9C102_MAX_DEVICES       64
+#define SN9C102_PRESERVE_IMGSCALE 0
+#define SN9C102_FORCE_MUNMAP      0
+#define SN9C102_MAX_FRAMES        32
+#define SN9C102_URBS              2
+#define SN9C102_ISO_PACKETS       7
+#define SN9C102_ALTERNATE_SETTING 8
+#define SN9C102_URB_TIMEOUT       msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
+#define SN9C102_CTRL_TIMEOUT      300
+#define SN9C102_FRAME_TIMEOUT     0
+
+/*****************************************************************************/
+
+static const u8 SN9C102_Y_QTABLE0[64] = {
+        8,   5,   5,   8,  12,  20,  25,  30,
+        6,   6,   7,   9,  13,  29,  30,  27,
+        7,   6,   8,  12,  20,  28,  34,  28,
+        7,   8,  11,  14,  25,  43,  40,  31,
+        9,  11,  18,  28,  34,  54,  51,  38,
+       12,  17,  27,  32,  40,  52,  56,  46,
+       24,  32,  39,  43,  51,  60,  60,  50,
+       36,  46,  47,  49,  56,  50,  51,  49
+};
+
+static const u8 SN9C102_UV_QTABLE0[64] = {
+        8,   9,  12,  23,  49,  49,  49,  49,
+        9,  10,  13,  33,  49,  49,  49,  49,
+       12,  13,  28,  49,  49,  49,  49,  49,
+       23,  33,  49,  49,  49,  49,  49,  49,
+       49,  49,  49,  49,  49,  49,  49,  49,
+       49,  49,  49,  49,  49,  49,  49,  49,
+       49,  49,  49,  49,  49,  49,  49,  49,
+       49,  49,  49,  49,  49,  49,  49,  49
+};
+
+static const u8 SN9C102_Y_QTABLE1[64] = {
+       16,  11,  10,  16,  24,  40,  51,  61,
+       12,  12,  14,  19,  26,  58,  60,  55,
+       14,  13,  16,  24,  40,  57,  69,  56,
+       14,  17,  22,  29,  51,  87,  80,  62,
+       18,  22,  37,  56,  68, 109, 103,  77,
+       24,  35,  55,  64,  81, 104, 113,  92,
+       49,  64,  78,  87, 103, 121, 120, 101,
+       72,  92,  95,  98, 112, 100, 103,  99
+};
+
+static const u8 SN9C102_UV_QTABLE1[64] = {
+       17,  18,  24,  47,  99,  99,  99,  99,
+       18,  21,  26,  66,  99,  99,  99,  99,
+       24,  26,  56,  99,  99,  99,  99,  99,
+       47,  66,  99,  99,  99,  99,  99,  99,
+       99,  99,  99,  99,  99,  99,  99,  99,
+       99,  99,  99,  99,  99,  99,  99,  99,
+       99,  99,  99,  99,  99,  99,  99,  99,
+       99,  99,  99,  99,  99,  99,  99,  99
+};
+
+#endif /* _SN9C102_CONFIG_H_ */
diff --git a/drivers/media/usb/sn9c102/sn9c102_core.c b/drivers/media/usb/sn9c102/sn9c102_core.c
new file mode 100644 (file)
index 0000000..19ea780
--- /dev/null
@@ -0,0 +1,3421 @@
+/***************************************************************************
+ * V4L2 driver for SN9C1xx PC Camera Controllers                           *
+ *                                                                         *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ *                                                                         *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/compiler.h>
+#include <linux/ioctl.h>
+#include <linux/poll.h>
+#include <linux/stat.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/version.h>
+#include <linux/page-flags.h>
+#include <asm/byteorder.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+
+#include "sn9c102.h"
+
+/*****************************************************************************/
+
+#define SN9C102_MODULE_NAME     "V4L2 driver for SN9C1xx PC Camera Controllers"
+#define SN9C102_MODULE_ALIAS    "sn9c1xx"
+#define SN9C102_MODULE_AUTHOR   "(C) 2004-2007 Luca Risolia"
+#define SN9C102_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
+#define SN9C102_MODULE_LICENSE  "GPL"
+#define SN9C102_MODULE_VERSION  "1:1.48"
+
+/*****************************************************************************/
+
+MODULE_DEVICE_TABLE(usb, sn9c102_id_table);
+
+MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);
+MODULE_DESCRIPTION(SN9C102_MODULE_NAME);
+MODULE_ALIAS(SN9C102_MODULE_ALIAS);
+MODULE_VERSION(SN9C102_MODULE_VERSION);
+MODULE_LICENSE(SN9C102_MODULE_LICENSE);
+
+static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1};
+module_param_array(video_nr, short, NULL, 0444);
+MODULE_PARM_DESC(video_nr,
+                " <-1|n[,...]>"
+                "\nSpecify V4L2 minor mode number."
+                "\n-1 = use next available (default)"
+                "\n n = use minor number n (integer >= 0)"
+                "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES)
+                " cameras this way."
+                "\nFor example:"
+                "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
+                "\nthe second camera and use auto for the first"
+                "\none and for every other camera."
+                "\n");
+
+static bool force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
+                             SN9C102_FORCE_MUNMAP};
+module_param_array(force_munmap, bool, NULL, 0444);
+MODULE_PARM_DESC(force_munmap,
+                " <0|1[,...]>"
+                "\nForce the application to unmap previously"
+                "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
+                "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
+                "\nthis feature. This parameter is specific for each"
+                "\ndetected camera."
+                "\n0 = do not force memory unmapping"
+                "\n1 = force memory unmapping (save memory)"
+                "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
+                "\n");
+
+static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] =
+                                      SN9C102_FRAME_TIMEOUT};
+module_param_array(frame_timeout, uint, NULL, 0644);
+MODULE_PARM_DESC(frame_timeout,
+                " <0|n[,...]>"
+                "\nTimeout for a video frame in seconds before"
+                "\nreturning an I/O error; 0 for infinity."
+                "\nThis parameter is specific for each detected camera."
+                "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
+                "\n");
+
+#ifdef SN9C102_DEBUG
+static unsigned short debug = SN9C102_DEBUG_LEVEL;
+module_param(debug, ushort, 0644);
+MODULE_PARM_DESC(debug,
+                " <n>"
+                "\nDebugging information level, from 0 to 3:"
+                "\n0 = none (use carefully)"
+                "\n1 = critical errors"
+                "\n2 = significant informations"
+                "\n3 = more verbose messages"
+                "\nLevel 3 is useful for testing only."
+                "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
+                "\n");
+#endif
+
+/*
+   Add the probe entries to this table. Be sure to add the entry in the right
+   place, since, on failure, the next probing routine is called according to
+   the order of the list below, from top to bottom.
+*/
+static int (*sn9c102_sensor_table[])(struct sn9c102_device *) = {
+       &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
+       &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
+       &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
+       &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
+};
+
+/*****************************************************************************/
+
+static u32
+sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
+                       enum sn9c102_io_method io)
+{
+       struct v4l2_pix_format* p = &(cam->sensor.pix_format);
+       struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
+       size_t imagesize = cam->module_param.force_munmap || io == IO_READ ?
+                          (p->width * p->height * p->priv) / 8 :
+                          (r->width * r->height * p->priv) / 8;
+       void* buff = NULL;
+       u32 i;
+
+       if (count > SN9C102_MAX_FRAMES)
+               count = SN9C102_MAX_FRAMES;
+
+       if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120)
+               imagesize += 589 + 2; /* length of JPEG header + EOI marker */
+
+       cam->nbuffers = count;
+       while (cam->nbuffers > 0) {
+               if ((buff = vmalloc_32_user(cam->nbuffers *
+                                           PAGE_ALIGN(imagesize))))
+                       break;
+               cam->nbuffers--;
+       }
+
+       for (i = 0; i < cam->nbuffers; i++) {
+               cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize);
+               cam->frame[i].buf.index = i;
+               cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize);
+               cam->frame[i].buf.length = imagesize;
+               cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               cam->frame[i].buf.sequence = 0;
+               cam->frame[i].buf.field = V4L2_FIELD_NONE;
+               cam->frame[i].buf.memory = V4L2_MEMORY_MMAP;
+               cam->frame[i].buf.flags = 0;
+       }
+
+       return cam->nbuffers;
+}
+
+
+static void sn9c102_release_buffers(struct sn9c102_device* cam)
+{
+       if (cam->nbuffers) {
+               vfree(cam->frame[0].bufmem);
+               cam->nbuffers = 0;
+       }
+       cam->frame_current = NULL;
+}
+
+
+static void sn9c102_empty_framequeues(struct sn9c102_device* cam)
+{
+       u32 i;
+
+       INIT_LIST_HEAD(&cam->inqueue);
+       INIT_LIST_HEAD(&cam->outqueue);
+
+       for (i = 0; i < SN9C102_MAX_FRAMES; i++) {
+               cam->frame[i].state = F_UNUSED;
+               cam->frame[i].buf.bytesused = 0;
+       }
+}
+
+
+static void sn9c102_requeue_outqueue(struct sn9c102_device* cam)
+{
+       struct sn9c102_frame_t *i;
+
+       list_for_each_entry(i, &cam->outqueue, frame) {
+               i->state = F_QUEUED;
+               list_add(&i->frame, &cam->inqueue);
+       }
+
+       INIT_LIST_HEAD(&cam->outqueue);
+}
+
+
+static void sn9c102_queue_unusedframes(struct sn9c102_device* cam)
+{
+       unsigned long lock_flags;
+       u32 i;
+
+       for (i = 0; i < cam->nbuffers; i++)
+               if (cam->frame[i].state == F_UNUSED) {
+                       cam->frame[i].state = F_QUEUED;
+                       spin_lock_irqsave(&cam->queue_lock, lock_flags);
+                       list_add_tail(&cam->frame[i].frame, &cam->inqueue);
+                       spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+               }
+}
+
+/*****************************************************************************/
+
+/*
+   Write a sequence of count value/register pairs. Returns -1 after the first
+   failed write, or 0 for no errors.
+*/
+int sn9c102_write_regs(struct sn9c102_device* cam, const u8 valreg[][2],
+                      int count)
+{
+       struct usb_device* udev = cam->usbdev;
+       u8* buff = cam->control_buffer;
+       int i, res;
+
+       for (i = 0; i < count; i++) {
+               u8 index = valreg[i][1];
+
+               /*
+                  index is a u8, so it must be <256 and can't be out of range.
+                  If we put in a check anyway, gcc annoys us with a warning
+                  hat our check is useless. People get all uppity when they
+                  see warnings in the kernel compile.
+               */
+
+               *buff = valreg[i][0];
+
+               res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08,
+                                     0x41, index, 0, buff, 1,
+                                     SN9C102_CTRL_TIMEOUT);
+
+               if (res < 0) {
+                       DBG(3, "Failed to write a register (value 0x%02X, "
+                              "index 0x%02X, error %d)", *buff, index, res);
+                       return -1;
+               }
+
+               cam->reg[index] = *buff;
+       }
+
+       return 0;
+}
+
+
+int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index)
+{
+       struct usb_device* udev = cam->usbdev;
+       u8* buff = cam->control_buffer;
+       int res;
+
+       if (index >= ARRAY_SIZE(cam->reg))
+               return -1;
+
+       *buff = value;
+
+       res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
+                             index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
+       if (res < 0) {
+               DBG(3, "Failed to write a register (value 0x%02X, index "
+                      "0x%02X, error %d)", value, index, res);
+               return -1;
+       }
+
+       cam->reg[index] = value;
+
+       return 0;
+}
+
+
+/* NOTE: with the SN9C10[123] reading some registers always returns 0 */
+int sn9c102_read_reg(struct sn9c102_device* cam, u16 index)
+{
+       struct usb_device* udev = cam->usbdev;
+       u8* buff = cam->control_buffer;
+       int res;
+
+       res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
+                             index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
+       if (res < 0)
+               DBG(3, "Failed to read a register (index 0x%02X, error %d)",
+                   index, res);
+
+       return (res >= 0) ? (int)(*buff) : -1;
+}
+
+
+int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index)
+{
+       if (index >= ARRAY_SIZE(cam->reg))
+               return -1;
+
+       return cam->reg[index];
+}
+
+
+static int
+sn9c102_i2c_wait(struct sn9c102_device* cam,
+                const struct sn9c102_sensor* sensor)
+{
+       int i, r;
+
+       for (i = 1; i <= 5; i++) {
+               r = sn9c102_read_reg(cam, 0x08);
+               if (r < 0)
+                       return -EIO;
+               if (r & 0x04)
+                       return 0;
+               if (sensor->frequency & SN9C102_I2C_400KHZ)
+                       udelay(5*16);
+               else
+                       udelay(16*16);
+       }
+       return -EBUSY;
+}
+
+
+static int
+sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
+                             const struct sn9c102_sensor* sensor)
+{
+       int r , err = 0;
+
+       r = sn9c102_read_reg(cam, 0x08);
+       if (r < 0)
+               err += r;
+
+       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
+               if (!(r & 0x08))
+                       err += -1;
+       } else {
+               if (r & 0x08)
+                       err += -1;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int
+sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
+                              const struct sn9c102_sensor* sensor)
+{
+       int r;
+       r = sn9c102_read_reg(cam, 0x08);
+       return (r < 0 || (r >= 0 && (r & 0x08))) ? -EIO : 0;
+}
+
+
+int
+sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
+                        const struct sn9c102_sensor* sensor, u8 data0,
+                        u8 data1, u8 n, u8 buffer[])
+{
+       struct usb_device* udev = cam->usbdev;
+       u8* data = cam->control_buffer;
+       int i = 0, err = 0, res;
+
+       /* Write cycle */
+       data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
+                 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10;
+       data[1] = data0; /* I2C slave id */
+       data[2] = data1; /* address */
+       data[7] = 0x10;
+       res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
+                             0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
+       if (res < 0)
+               err += res;
+
+       err += sn9c102_i2c_wait(cam, sensor);
+
+       /* Read cycle - n bytes */
+       data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
+                 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) |
+                 (n << 4) | 0x02;
+       data[1] = data0;
+       data[7] = 0x10;
+       res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
+                             0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
+       if (res < 0)
+               err += res;
+
+       err += sn9c102_i2c_wait(cam, sensor);
+
+       /* The first read byte will be placed in data[4] */
+       res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
+                             0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT);
+       if (res < 0)
+               err += res;
+
+       err += sn9c102_i2c_detect_read_error(cam, sensor);
+
+       PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1,
+             data[4]);
+
+       if (err) {
+               DBG(3, "I2C read failed for %s image sensor", sensor->name);
+               return -1;
+       }
+
+       if (buffer)
+               for (i = 0; i < n && i < 5; i++)
+                       buffer[n-i-1] = data[4-i];
+
+       return (int)data[4];
+}
+
+
+int
+sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
+                         const struct sn9c102_sensor* sensor, u8 n, u8 data0,
+                         u8 data1, u8 data2, u8 data3, u8 data4, u8 data5)
+{
+       struct usb_device* udev = cam->usbdev;
+       u8* data = cam->control_buffer;
+       int err = 0, res;
+
+       /* Write cycle. It usually is address + value */
+       data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
+                 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0)
+                 | ((n - 1) << 4);
+       data[1] = data0;
+       data[2] = data1;
+       data[3] = data2;
+       data[4] = data3;
+       data[5] = data4;
+       data[6] = data5;
+       data[7] = 0x17;
+       res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
+                             0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
+       if (res < 0)
+               err += res;
+
+       err += sn9c102_i2c_wait(cam, sensor);
+       err += sn9c102_i2c_detect_write_error(cam, sensor);
+
+       if (err)
+               DBG(3, "I2C write failed for %s image sensor", sensor->name);
+
+       PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, "
+             "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X",
+             n, data0, data1, data2, data3, data4, data5);
+
+       return err ? -1 : 0;
+}
+
+
+int
+sn9c102_i2c_try_read(struct sn9c102_device* cam,
+                    const struct sn9c102_sensor* sensor, u8 address)
+{
+       return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id,
+                                       address, 1, NULL);
+}
+
+
+static int sn9c102_i2c_try_write(struct sn9c102_device* cam,
+                                const struct sn9c102_sensor* sensor,
+                                u8 address, u8 value)
+{
+       return sn9c102_i2c_try_raw_write(cam, sensor, 3,
+                                        sensor->i2c_slave_id, address,
+                                        value, 0, 0, 0);
+}
+
+
+int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address)
+{
+       return sn9c102_i2c_try_read(cam, &cam->sensor, address);
+}
+
+
+int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value)
+{
+       return sn9c102_i2c_try_write(cam, &cam->sensor, address, value);
+}
+
+/*****************************************************************************/
+
+static size_t sn9c102_sof_length(struct sn9c102_device* cam)
+{
+       switch (cam->bridge) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+               return 12;
+       case BRIDGE_SN9C103:
+               return 18;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               return 62;
+       }
+
+       return 0;
+}
+
+
+static void*
+sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
+{
+       static const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
+       const char *m = mem;
+       size_t soflen = 0, i, j;
+
+       soflen = sn9c102_sof_length(cam);
+
+       for (i = 0; i < len; i++) {
+               size_t b;
+
+               /* Read the variable part of the header */
+               if (unlikely(cam->sof.bytesread >= sizeof(marker))) {
+                       cam->sof.header[cam->sof.bytesread] = *(m+i);
+                       if (++cam->sof.bytesread == soflen) {
+                               cam->sof.bytesread = 0;
+                               return mem + i;
+                       }
+                       continue;
+               }
+
+               /* Search for the SOF marker (fixed part) in the header */
+               for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) {
+                       if (unlikely(i+j == len))
+                               return NULL;
+                       if (*(m+i+j) == marker[cam->sof.bytesread]) {
+                               cam->sof.header[cam->sof.bytesread] = *(m+i+j);
+                               if (++cam->sof.bytesread == sizeof(marker)) {
+                                       PDBGG("Bytes to analyze: %zd. SOF "
+                                             "starts at byte #%zd", len, i);
+                                       i += j+1;
+                                       break;
+                               }
+                       } else {
+                               cam->sof.bytesread = 0;
+                               break;
+                       }
+               }
+       }
+
+       return NULL;
+}
+
+
+static void*
+sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
+{
+       static const u8 eof_header[4][4] = {
+               {0x00, 0x00, 0x00, 0x00},
+               {0x40, 0x00, 0x00, 0x00},
+               {0x80, 0x00, 0x00, 0x00},
+               {0xc0, 0x00, 0x00, 0x00},
+       };
+       size_t i, j;
+
+       /* The EOF header does not exist in compressed data */
+       if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
+           cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
+               return NULL;
+
+       /*
+          The EOF header might cross the packet boundary, but this is not a
+          problem, since the end of a frame is determined by checking its size
+          in the first place.
+       */
+       for (i = 0; (len >= 4) && (i <= len - 4); i++)
+               for (j = 0; j < ARRAY_SIZE(eof_header); j++)
+                       if (!memcmp(mem + i, eof_header[j], 4))
+                               return mem + i;
+
+       return NULL;
+}
+
+
+static void
+sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
+{
+       static const u8 jpeg_header[589] = {
+               0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05,
+               0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06,
+               0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e,
+               0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16,
+               0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16,
+               0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29,
+               0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29,
+               0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a,
+               0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28,
+               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2,
+               0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+               0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01,
+               0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+               0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
+               0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00,
+               0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
+               0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
+               0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
+               0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,
+               0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
+               0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
+               0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38,
+               0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
+               0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
+               0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
+               0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+               0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+               0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
+               0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
+               0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3,
+               0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3,
+               0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
+               0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
+               0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
+               0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
+               0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+               0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
+               0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1,
+               0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19,
+               0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+               0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
+               0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
+               0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
+               0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+               0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+               0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
+               0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
+               0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+               0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
+               0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
+               0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11,
+               0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02,
+               0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03,
+               0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
+       };
+       u8 *pos = f->bufmem;
+
+       memcpy(pos, jpeg_header, sizeof(jpeg_header));
+       *(pos + 6) = 0x00;
+       *(pos + 7 + 64) = 0x01;
+       if (cam->compression.quality == 0) {
+               memcpy(pos + 7, SN9C102_Y_QTABLE0, 64);
+               memcpy(pos + 8 + 64, SN9C102_UV_QTABLE0, 64);
+       } else if (cam->compression.quality == 1) {
+               memcpy(pos + 7, SN9C102_Y_QTABLE1, 64);
+               memcpy(pos + 8 + 64, SN9C102_UV_QTABLE1, 64);
+       }
+       *(pos + 564) = cam->sensor.pix_format.width & 0xFF;
+       *(pos + 563) = (cam->sensor.pix_format.width >> 8) & 0xFF;
+       *(pos + 562) = cam->sensor.pix_format.height & 0xFF;
+       *(pos + 561) = (cam->sensor.pix_format.height >> 8) & 0xFF;
+       *(pos + 567) = 0x21;
+
+       f->buf.bytesused += sizeof(jpeg_header);
+}
+
+
+static void sn9c102_urb_complete(struct urb *urb)
+{
+       struct sn9c102_device* cam = urb->context;
+       struct sn9c102_frame_t** f;
+       size_t imagesize, soflen;
+       u8 i;
+       int err = 0;
+
+       if (urb->status == -ENOENT)
+               return;
+
+       f = &cam->frame_current;
+
+       if (cam->stream == STREAM_INTERRUPT) {
+               cam->stream = STREAM_OFF;
+               if ((*f))
+                       (*f)->state = F_QUEUED;
+               cam->sof.bytesread = 0;
+               DBG(3, "Stream interrupted by application");
+               wake_up(&cam->wait_stream);
+       }
+
+       if (cam->state & DEV_DISCONNECTED)
+               return;
+
+       if (cam->state & DEV_MISCONFIGURED) {
+               wake_up_interruptible(&cam->wait_frame);
+               return;
+       }
+
+       if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue))
+               goto resubmit_urb;
+
+       if (!(*f))
+               (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t,
+                                 frame);
+
+       imagesize = (cam->sensor.pix_format.width *
+                    cam->sensor.pix_format.height *
+                    cam->sensor.pix_format.priv) / 8;
+       if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
+               imagesize += 589; /* length of jpeg header */
+       soflen = sn9c102_sof_length(cam);
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               unsigned int img, len, status;
+               void *pos, *sof, *eof;
+
+               len = urb->iso_frame_desc[i].actual_length;
+               status = urb->iso_frame_desc[i].status;
+               pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer;
+
+               if (status) {
+                       DBG(3, "Error in isochronous frame");
+                       (*f)->state = F_ERROR;
+                       cam->sof.bytesread = 0;
+                       continue;
+               }
+
+               PDBGG("Isochrnous frame: length %u, #%u i", len, i);
+
+redo:
+               sof = sn9c102_find_sof_header(cam, pos, len);
+               if (likely(!sof)) {
+                       eof = sn9c102_find_eof_header(cam, pos, len);
+                       if ((*f)->state == F_GRABBING) {
+end_of_frame:
+                               img = len;
+
+                               if (eof)
+                                       img = (eof > pos) ? eof - pos - 1 : 0;
+
+                               if ((*f)->buf.bytesused + img > imagesize) {
+                                       u32 b;
+                                       b = (*f)->buf.bytesused + img -
+                                           imagesize;
+                                       img = imagesize - (*f)->buf.bytesused;
+                                       PDBGG("Expected EOF not found: video "
+                                             "frame cut");
+                                       if (eof)
+                                               DBG(3, "Exceeded limit: +%u "
+                                                      "bytes", (unsigned)(b));
+                               }
+
+                               memcpy((*f)->bufmem + (*f)->buf.bytesused, pos,
+                                      img);
+
+                               if ((*f)->buf.bytesused == 0)
+                                       do_gettimeofday(&(*f)->buf.timestamp);
+
+                               (*f)->buf.bytesused += img;
+
+                               if ((*f)->buf.bytesused == imagesize ||
+                                   ((cam->sensor.pix_format.pixelformat ==
+                                     V4L2_PIX_FMT_SN9C10X ||
+                                     cam->sensor.pix_format.pixelformat ==
+                                     V4L2_PIX_FMT_JPEG) && eof)) {
+                                       u32 b;
+
+                                       b = (*f)->buf.bytesused;
+                                       (*f)->state = F_DONE;
+                                       (*f)->buf.sequence= ++cam->frame_count;
+
+                                       spin_lock(&cam->queue_lock);
+                                       list_move_tail(&(*f)->frame,
+                                                      &cam->outqueue);
+                                       if (!list_empty(&cam->inqueue))
+                                               (*f) = list_entry(
+                                                       cam->inqueue.next,
+                                                       struct sn9c102_frame_t,
+                                                       frame );
+                                       else
+                                               (*f) = NULL;
+                                       spin_unlock(&cam->queue_lock);
+
+                                       memcpy(cam->sysfs.frame_header,
+                                              cam->sof.header, soflen);
+
+                                       DBG(3, "Video frame captured: %lu "
+                                              "bytes", (unsigned long)(b));
+
+                                       if (!(*f))
+                                               goto resubmit_urb;
+
+                               } else if (eof) {
+                                       (*f)->state = F_ERROR;
+                                       DBG(3, "Not expected EOF after %lu "
+                                              "bytes of image data",
+                                           (unsigned long)
+                                           ((*f)->buf.bytesused));
+                               }
+
+                               if (sof) /* (1) */
+                                       goto start_of_frame;
+
+                       } else if (eof) {
+                               DBG(3, "EOF without SOF");
+                               continue;
+
+                       } else {
+                               PDBGG("Ignoring pointless isochronous frame");
+                               continue;
+                       }
+
+               } else if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) {
+start_of_frame:
+                       (*f)->state = F_GRABBING;
+                       (*f)->buf.bytesused = 0;
+                       len -= (sof - pos);
+                       pos = sof;
+                       if (cam->sensor.pix_format.pixelformat ==
+                           V4L2_PIX_FMT_JPEG)
+                               sn9c102_write_jpegheader(cam, (*f));
+                       DBG(3, "SOF detected: new video frame");
+                       if (len)
+                               goto redo;
+
+               } else if ((*f)->state == F_GRABBING) {
+                       eof = sn9c102_find_eof_header(cam, pos, len);
+                       if (eof && eof < sof)
+                               goto end_of_frame; /* (1) */
+                       else {
+                               if (cam->sensor.pix_format.pixelformat ==
+                                   V4L2_PIX_FMT_SN9C10X ||
+                                   cam->sensor.pix_format.pixelformat ==
+                                   V4L2_PIX_FMT_JPEG) {
+                                       if (sof - pos >= soflen) {
+                                               eof = sof - soflen;
+                                       } else { /* remove header */
+                                               eof = pos;
+                                               (*f)->buf.bytesused -=
+                                                       (soflen - (sof - pos));
+                                       }
+                                       goto end_of_frame;
+                               } else {
+                                       DBG(3, "SOF before expected EOF after "
+                                              "%lu bytes of image data",
+                                           (unsigned long)
+                                           ((*f)->buf.bytesused));
+                                       goto start_of_frame;
+                               }
+                       }
+               }
+       }
+
+resubmit_urb:
+       urb->dev = cam->usbdev;
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+       if (err < 0 && err != -EPERM) {
+               cam->state |= DEV_MISCONFIGURED;
+               DBG(1, "usb_submit_urb() failed");
+       }
+
+       wake_up_interruptible(&cam->wait_frame);
+}
+
+
+static int sn9c102_start_transfer(struct sn9c102_device* cam)
+{
+       struct usb_device *udev = cam->usbdev;
+       struct urb* urb;
+       struct usb_host_interface* altsetting = usb_altnum_to_altsetting(
+                                                   usb_ifnum_to_if(udev, 0),
+                                                   SN9C102_ALTERNATE_SETTING);
+       const unsigned int psz = le16_to_cpu(altsetting->
+                                            endpoint[0].desc.wMaxPacketSize);
+       s8 i, j;
+       int err = 0;
+
+       for (i = 0; i < SN9C102_URBS; i++) {
+               cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz,
+                                                 GFP_KERNEL);
+               if (!cam->transfer_buffer[i]) {
+                       err = -ENOMEM;
+                       DBG(1, "Not enough memory");
+                       goto free_buffers;
+               }
+       }
+
+       for (i = 0; i < SN9C102_URBS; i++) {
+               urb = usb_alloc_urb(SN9C102_ISO_PACKETS, GFP_KERNEL);
+               cam->urb[i] = urb;
+               if (!urb) {
+                       err = -ENOMEM;
+                       DBG(1, "usb_alloc_urb() failed");
+                       goto free_urbs;
+               }
+               urb->dev = udev;
+               urb->context = cam;
+               urb->pipe = usb_rcvisocpipe(udev, 1);
+               urb->transfer_flags = URB_ISO_ASAP;
+               urb->number_of_packets = SN9C102_ISO_PACKETS;
+               urb->complete = sn9c102_urb_complete;
+               urb->transfer_buffer = cam->transfer_buffer[i];
+               urb->transfer_buffer_length = psz * SN9C102_ISO_PACKETS;
+               urb->interval = 1;
+               for (j = 0; j < SN9C102_ISO_PACKETS; j++) {
+                       urb->iso_frame_desc[j].offset = psz * j;
+                       urb->iso_frame_desc[j].length = psz;
+               }
+       }
+
+       /* Enable video */
+       if (!(cam->reg[0x01] & 0x04)) {
+               err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01);
+               if (err) {
+                       err = -EIO;
+                       DBG(1, "I/O hardware error");
+                       goto free_urbs;
+               }
+       }
+
+       err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING);
+       if (err) {
+               DBG(1, "usb_set_interface() failed");
+               goto free_urbs;
+       }
+
+       cam->frame_current = NULL;
+       cam->sof.bytesread = 0;
+
+       for (i = 0; i < SN9C102_URBS; i++) {
+               err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
+               if (err) {
+                       for (j = i-1; j >= 0; j--)
+                               usb_kill_urb(cam->urb[j]);
+                       DBG(1, "usb_submit_urb() failed, error %d", err);
+                       goto free_urbs;
+               }
+       }
+
+       return 0;
+
+free_urbs:
+       for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++)
+               usb_free_urb(cam->urb[i]);
+
+free_buffers:
+       for (i = 0; (i < SN9C102_URBS) && cam->transfer_buffer[i]; i++)
+               kfree(cam->transfer_buffer[i]);
+
+       return err;
+}
+
+
+static int sn9c102_stop_transfer(struct sn9c102_device* cam)
+{
+       struct usb_device *udev = cam->usbdev;
+       s8 i;
+       int err = 0;
+
+       if (cam->state & DEV_DISCONNECTED)
+               return 0;
+
+       for (i = SN9C102_URBS-1; i >= 0; i--) {
+               usb_kill_urb(cam->urb[i]);
+               usb_free_urb(cam->urb[i]);
+               kfree(cam->transfer_buffer[i]);
+       }
+
+       err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */
+       if (err)
+               DBG(3, "usb_set_interface() failed");
+
+       return err;
+}
+
+
+static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
+{
+       cam->stream = STREAM_INTERRUPT;
+       wait_event_timeout(cam->wait_stream,
+                                    (cam->stream == STREAM_OFF) ||
+                                    (cam->state & DEV_DISCONNECTED),
+                                    SN9C102_URB_TIMEOUT);
+       if (cam->state & DEV_DISCONNECTED)
+               return -ENODEV;
+       else if (cam->stream != STREAM_OFF) {
+               cam->state |= DEV_MISCONFIGURED;
+               DBG(1, "URB timeout reached. The camera is misconfigured. "
+                      "To use it, close and open %s again.",
+                   video_device_node_name(cam->v4ldev));
+               return -EIO;
+       }
+
+       return 0;
+}
+
+/*****************************************************************************/
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count)
+{
+       char str[7];
+       char* endp;
+       unsigned long val;
+
+       if (len < 6) {
+               strncpy(str, buff, len);
+               str[len] = '\0';
+       } else {
+               strncpy(str, buff, 6);
+               str[6] = '\0';
+       }
+
+       val = simple_strtoul(str, &endp, 0);
+
+       *count = 0;
+       if (val <= 0xffff)
+               *count = (ssize_t)(endp - str);
+       if ((*count) && (len == *count+1) && (buff[*count] == '\n'))
+               *count += 1;
+
+       return (u16)val;
+}
+
+/*
+   NOTE 1: being inside one of the following methods implies that the v4l
+          device exists for sure (see kobjects and reference counters)
+   NOTE 2: buffers are PAGE_SIZE long
+*/
+
+static ssize_t sn9c102_show_reg(struct device* cd,
+                               struct device_attribute *attr, char* buf)
+{
+       struct sn9c102_device* cam;
+       ssize_t count;
+
+       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+               return -ERESTARTSYS;
+
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
+       if (!cam) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -ENODEV;
+       }
+
+       count = sprintf(buf, "%u\n", cam->sysfs.reg);
+
+       mutex_unlock(&sn9c102_sysfs_lock);
+
+       return count;
+}
+
+
+static ssize_t
+sn9c102_store_reg(struct device* cd, struct device_attribute *attr,
+                 const char* buf, size_t len)
+{
+       struct sn9c102_device* cam;
+       u16 index;
+       ssize_t count;
+
+       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+               return -ERESTARTSYS;
+
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
+       if (!cam) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -ENODEV;
+       }
+
+       index = sn9c102_strtou16(buf, len, &count);
+       if (index >= ARRAY_SIZE(cam->reg) || !count) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -EINVAL;
+       }
+
+       cam->sysfs.reg = index;
+
+       DBG(2, "Moved SN9C1XX register index to 0x%02X", cam->sysfs.reg);
+       DBG(3, "Written bytes: %zd", count);
+
+       mutex_unlock(&sn9c102_sysfs_lock);
+
+       return count;
+}
+
+
+static ssize_t sn9c102_show_val(struct device* cd,
+                               struct device_attribute *attr, char* buf)
+{
+       struct sn9c102_device* cam;
+       ssize_t count;
+       int val;
+
+       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+               return -ERESTARTSYS;
+
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
+       if (!cam) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -ENODEV;
+       }
+
+       if ((val = sn9c102_read_reg(cam, cam->sysfs.reg)) < 0) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -EIO;
+       }
+
+       count = sprintf(buf, "%d\n", val);
+
+       DBG(3, "Read bytes: %zd, value: %d", count, val);
+
+       mutex_unlock(&sn9c102_sysfs_lock);
+
+       return count;
+}
+
+
+static ssize_t
+sn9c102_store_val(struct device* cd, struct device_attribute *attr,
+                 const char* buf, size_t len)
+{
+       struct sn9c102_device* cam;
+       u16 value;
+       ssize_t count;
+       int err;
+
+       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+               return -ERESTARTSYS;
+
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
+       if (!cam) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -ENODEV;
+       }
+
+       value = sn9c102_strtou16(buf, len, &count);
+       if (!count) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -EINVAL;
+       }
+
+       err = sn9c102_write_reg(cam, value, cam->sysfs.reg);
+       if (err) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -EIO;
+       }
+
+       DBG(2, "Written SN9C1XX reg. 0x%02X, val. 0x%02X",
+           cam->sysfs.reg, value);
+       DBG(3, "Written bytes: %zd", count);
+
+       mutex_unlock(&sn9c102_sysfs_lock);
+
+       return count;
+}
+
+
+static ssize_t sn9c102_show_i2c_reg(struct device* cd,
+                                   struct device_attribute *attr, char* buf)
+{
+       struct sn9c102_device* cam;
+       ssize_t count;
+
+       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+               return -ERESTARTSYS;
+
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
+       if (!cam) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -ENODEV;
+       }
+
+       count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg);
+
+       DBG(3, "Read bytes: %zd", count);
+
+       mutex_unlock(&sn9c102_sysfs_lock);
+
+       return count;
+}
+
+
+static ssize_t
+sn9c102_store_i2c_reg(struct device* cd, struct device_attribute *attr,
+                     const char* buf, size_t len)
+{
+       struct sn9c102_device* cam;
+       u16 index;
+       ssize_t count;
+
+       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+               return -ERESTARTSYS;
+
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
+       if (!cam) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -ENODEV;
+       }
+
+       index = sn9c102_strtou16(buf, len, &count);
+       if (!count) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -EINVAL;
+       }
+
+       cam->sysfs.i2c_reg = index;
+
+       DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg);
+       DBG(3, "Written bytes: %zd", count);
+
+       mutex_unlock(&sn9c102_sysfs_lock);
+
+       return count;
+}
+
+
+static ssize_t sn9c102_show_i2c_val(struct device* cd,
+                                   struct device_attribute *attr, char* buf)
+{
+       struct sn9c102_device* cam;
+       ssize_t count;
+       int val;
+
+       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+               return -ERESTARTSYS;
+
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
+       if (!cam) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -ENODEV;
+       }
+
+       if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -ENOSYS;
+       }
+
+       if ((val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -EIO;
+       }
+
+       count = sprintf(buf, "%d\n", val);
+
+       DBG(3, "Read bytes: %zd, value: %d", count, val);
+
+       mutex_unlock(&sn9c102_sysfs_lock);
+
+       return count;
+}
+
+
+static ssize_t
+sn9c102_store_i2c_val(struct device* cd, struct device_attribute *attr,
+                     const char* buf, size_t len)
+{
+       struct sn9c102_device* cam;
+       u16 value;
+       ssize_t count;
+       int err;
+
+       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+               return -ERESTARTSYS;
+
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
+       if (!cam) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -ENODEV;
+       }
+
+       if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -ENOSYS;
+       }
+
+       value = sn9c102_strtou16(buf, len, &count);
+       if (!count) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -EINVAL;
+       }
+
+       err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value);
+       if (err) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -EIO;
+       }
+
+       DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X",
+           cam->sysfs.i2c_reg, value);
+       DBG(3, "Written bytes: %zd", count);
+
+       mutex_unlock(&sn9c102_sysfs_lock);
+
+       return count;
+}
+
+
+static ssize_t
+sn9c102_store_green(struct device* cd, struct device_attribute *attr,
+                   const char* buf, size_t len)
+{
+       struct sn9c102_device* cam;
+       enum sn9c102_bridge bridge;
+       ssize_t res = 0;
+       u16 value;
+       ssize_t count;
+
+       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
+               return -ERESTARTSYS;
+
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
+       if (!cam) {
+               mutex_unlock(&sn9c102_sysfs_lock);
+               return -ENODEV;
+       }
+
+       bridge = cam->bridge;
+
+       mutex_unlock(&sn9c102_sysfs_lock);
+
+       value = sn9c102_strtou16(buf, len, &count);
+       if (!count)
+               return -EINVAL;
+
+       switch (bridge) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+               if (value > 0x0f)
+                       return -EINVAL;
+               if ((res = sn9c102_store_reg(cd, attr, "0x11", 4)) >= 0)
+                       res = sn9c102_store_val(cd, attr, buf, len);
+               break;
+       case BRIDGE_SN9C103:
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               if (value > 0x7f)
+                       return -EINVAL;
+               if ((res = sn9c102_store_reg(cd, attr, "0x07", 4)) >= 0)
+                       res = sn9c102_store_val(cd, attr, buf, len);
+               break;
+       }
+
+       return res;
+}
+
+
+static ssize_t
+sn9c102_store_blue(struct device* cd, struct device_attribute *attr,
+                  const char* buf, size_t len)
+{
+       ssize_t res = 0;
+       u16 value;
+       ssize_t count;
+
+       value = sn9c102_strtou16(buf, len, &count);
+       if (!count || value > 0x7f)
+               return -EINVAL;
+
+       if ((res = sn9c102_store_reg(cd, attr, "0x06", 4)) >= 0)
+               res = sn9c102_store_val(cd, attr, buf, len);
+
+       return res;
+}
+
+
+static ssize_t
+sn9c102_store_red(struct device* cd, struct device_attribute *attr,
+                 const char* buf, size_t len)
+{
+       ssize_t res = 0;
+       u16 value;
+       ssize_t count;
+
+       value = sn9c102_strtou16(buf, len, &count);
+       if (!count || value > 0x7f)
+               return -EINVAL;
+
+       if ((res = sn9c102_store_reg(cd, attr, "0x05", 4)) >= 0)
+               res = sn9c102_store_val(cd, attr, buf, len);
+
+       return res;
+}
+
+
+static ssize_t sn9c102_show_frame_header(struct device* cd,
+                                        struct device_attribute *attr,
+                                        char* buf)
+{
+       struct sn9c102_device* cam;
+       ssize_t count;
+
+       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
+       if (!cam)
+               return -ENODEV;
+
+       count = sizeof(cam->sysfs.frame_header);
+       memcpy(buf, cam->sysfs.frame_header, count);
+
+       DBG(3, "Frame header, read bytes: %zd", count);
+
+       return count;
+}
+
+
+static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, sn9c102_show_reg, sn9c102_store_reg);
+static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, sn9c102_show_val, sn9c102_store_val);
+static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
+                  sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
+static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
+                  sn9c102_show_i2c_val, sn9c102_store_i2c_val);
+static DEVICE_ATTR(green, S_IWUSR, NULL, sn9c102_store_green);
+static DEVICE_ATTR(blue, S_IWUSR, NULL, sn9c102_store_blue);
+static DEVICE_ATTR(red, S_IWUSR, NULL, sn9c102_store_red);
+static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL);
+
+
+static int sn9c102_create_sysfs(struct sn9c102_device* cam)
+{
+       struct device *dev = &(cam->v4ldev->dev);
+       int err = 0;
+
+       if ((err = device_create_file(dev, &dev_attr_reg)))
+               goto err_out;
+       if ((err = device_create_file(dev, &dev_attr_val)))
+               goto err_reg;
+       if ((err = device_create_file(dev, &dev_attr_frame_header)))
+               goto err_val;
+
+       if (cam->sensor.sysfs_ops) {
+               if ((err = device_create_file(dev, &dev_attr_i2c_reg)))
+                       goto err_frame_header;
+               if ((err = device_create_file(dev, &dev_attr_i2c_val)))
+                       goto err_i2c_reg;
+       }
+
+       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
+               if ((err = device_create_file(dev, &dev_attr_green)))
+                       goto err_i2c_val;
+       } else {
+               if ((err = device_create_file(dev, &dev_attr_blue)))
+                       goto err_i2c_val;
+               if ((err = device_create_file(dev, &dev_attr_red)))
+                       goto err_blue;
+       }
+
+       return 0;
+
+err_blue:
+       device_remove_file(dev, &dev_attr_blue);
+err_i2c_val:
+       if (cam->sensor.sysfs_ops)
+               device_remove_file(dev, &dev_attr_i2c_val);
+err_i2c_reg:
+       if (cam->sensor.sysfs_ops)
+               device_remove_file(dev, &dev_attr_i2c_reg);
+err_frame_header:
+       device_remove_file(dev, &dev_attr_frame_header);
+err_val:
+       device_remove_file(dev, &dev_attr_val);
+err_reg:
+       device_remove_file(dev, &dev_attr_reg);
+err_out:
+       return err;
+}
+#endif /* CONFIG_VIDEO_ADV_DEBUG */
+
+/*****************************************************************************/
+
+static int
+sn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix)
+{
+       int err = 0;
+
+       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
+           pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+               switch (cam->bridge) {
+               case BRIDGE_SN9C101:
+               case BRIDGE_SN9C102:
+               case BRIDGE_SN9C103:
+                       err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
+                                                0x18);
+                       break;
+               case BRIDGE_SN9C105:
+               case BRIDGE_SN9C120:
+                       err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
+                                                0x18);
+                       break;
+               }
+       } else {
+               switch (cam->bridge) {
+               case BRIDGE_SN9C101:
+               case BRIDGE_SN9C102:
+               case BRIDGE_SN9C103:
+                       err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
+                                                0x18);
+                       break;
+               case BRIDGE_SN9C105:
+               case BRIDGE_SN9C120:
+                       err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
+                                                0x18);
+                       break;
+               }
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int
+sn9c102_set_compression(struct sn9c102_device* cam,
+                       struct v4l2_jpegcompression* compression)
+{
+       int i, err = 0;
+
+       switch (cam->bridge) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+       case BRIDGE_SN9C103:
+               if (compression->quality == 0)
+                       err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01,
+                                                0x17);
+               else if (compression->quality == 1)
+                       err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe,
+                                                0x17);
+               break;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               if (compression->quality == 0) {
+                       for (i = 0; i <= 63; i++) {
+                               err += sn9c102_write_reg(cam,
+                                                        SN9C102_Y_QTABLE1[i],
+                                                        0x100 + i);
+                               err += sn9c102_write_reg(cam,
+                                                        SN9C102_UV_QTABLE1[i],
+                                                        0x140 + i);
+                       }
+                       err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf,
+                                                0x18);
+               } else if (compression->quality == 1) {
+                       for (i = 0; i <= 63; i++) {
+                               err += sn9c102_write_reg(cam,
+                                                        SN9C102_Y_QTABLE1[i],
+                                                        0x100 + i);
+                               err += sn9c102_write_reg(cam,
+                                                        SN9C102_UV_QTABLE1[i],
+                                                        0x140 + i);
+                       }
+                       err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x40,
+                                                0x18);
+               }
+               break;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale)
+{
+       u8 r = 0;
+       int err = 0;
+
+       if (scale == 1)
+               r = cam->reg[0x18] & 0xcf;
+       else if (scale == 2) {
+               r = cam->reg[0x18] & 0xcf;
+               r |= 0x10;
+       } else if (scale == 4)
+               r = cam->reg[0x18] | 0x20;
+
+       err += sn9c102_write_reg(cam, r, 0x18);
+       if (err)
+               return -EIO;
+
+       PDBGG("Scaling factor: %u", scale);
+
+       return 0;
+}
+
+
+static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect)
+{
+       struct sn9c102_sensor* s = &cam->sensor;
+       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left),
+          v_start = (u8)(rect->top - s->cropcap.bounds.top),
+          h_size = (u8)(rect->width / 16),
+          v_size = (u8)(rect->height / 16);
+       int err = 0;
+
+       err += sn9c102_write_reg(cam, h_start, 0x12);
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+       err += sn9c102_write_reg(cam, h_size, 0x15);
+       err += sn9c102_write_reg(cam, v_size, 0x16);
+       if (err)
+               return -EIO;
+
+       PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size "
+             "%u %u %u %u", h_start, v_start, h_size, v_size);
+
+       return 0;
+}
+
+
+static int sn9c102_init(struct sn9c102_device* cam)
+{
+       struct sn9c102_sensor* s = &cam->sensor;
+       struct v4l2_control ctrl;
+       struct v4l2_queryctrl *qctrl;
+       struct v4l2_rect* rect;
+       u8 i = 0;
+       int err = 0;
+
+       if (!(cam->state & DEV_INITIALIZED)) {
+               mutex_init(&cam->open_mutex);
+               init_waitqueue_head(&cam->wait_open);
+               qctrl = s->qctrl;
+               rect = &(s->cropcap.defrect);
+       } else { /* use current values */
+               qctrl = s->_qctrl;
+               rect = &(s->_rect);
+       }
+
+       err += sn9c102_set_scale(cam, rect->width / s->pix_format.width);
+       err += sn9c102_set_crop(cam, rect);
+       if (err)
+               return err;
+
+       if (s->init) {
+               err = s->init(cam);
+               if (err) {
+                       DBG(3, "Sensor initialization failed");
+                       return err;
+               }
+       }
+
+       if (!(cam->state & DEV_INITIALIZED))
+               if (cam->bridge == BRIDGE_SN9C101 ||
+                   cam->bridge == BRIDGE_SN9C102 ||
+                   cam->bridge == BRIDGE_SN9C103) {
+                       if (s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
+                               s->pix_format.pixelformat= V4L2_PIX_FMT_SBGGR8;
+                       cam->compression.quality =  cam->reg[0x17] & 0x01 ?
+                                                   0 : 1;
+               } else {
+                       if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
+                               s->pix_format.pixelformat = V4L2_PIX_FMT_JPEG;
+                       cam->compression.quality =  cam->reg[0x18] & 0x40 ?
+                                                   0 : 1;
+                       err += sn9c102_set_compression(cam, &cam->compression);
+               }
+       else
+               err += sn9c102_set_compression(cam, &cam->compression);
+       err += sn9c102_set_pix_format(cam, &s->pix_format);
+       if (s->set_pix_format)
+               err += s->set_pix_format(cam, &s->pix_format);
+       if (err)
+               return err;
+
+       if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
+           s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
+               DBG(3, "Compressed video format is active, quality %d",
+                   cam->compression.quality);
+       else
+               DBG(3, "Uncompressed video format is active");
+
+       if (s->set_crop)
+               if ((err = s->set_crop(cam, rect))) {
+                       DBG(3, "set_crop() failed");
+                       return err;
+               }
+
+       if (s->set_ctrl) {
+               for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+                       if (s->qctrl[i].id != 0 &&
+                           !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) {
+                               ctrl.id = s->qctrl[i].id;
+                               ctrl.value = qctrl[i].default_value;
+                               err = s->set_ctrl(cam, &ctrl);
+                               if (err) {
+                                       DBG(3, "Set %s control failed",
+                                           s->qctrl[i].name);
+                                       return err;
+                               }
+                               DBG(3, "Image sensor supports '%s' control",
+                                   s->qctrl[i].name);
+                       }
+       }
+
+       if (!(cam->state & DEV_INITIALIZED)) {
+               mutex_init(&cam->fileop_mutex);
+               spin_lock_init(&cam->queue_lock);
+               init_waitqueue_head(&cam->wait_frame);
+               init_waitqueue_head(&cam->wait_stream);
+               cam->nreadbuffers = 2;
+               memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl));
+               memcpy(&(s->_rect), &(s->cropcap.defrect),
+                      sizeof(struct v4l2_rect));
+               cam->state |= DEV_INITIALIZED;
+       }
+
+       DBG(2, "Initialization succeeded");
+       return 0;
+}
+
+/*****************************************************************************/
+
+static void sn9c102_release_resources(struct kref *kref)
+{
+       struct sn9c102_device *cam;
+
+       mutex_lock(&sn9c102_sysfs_lock);
+
+       cam = container_of(kref, struct sn9c102_device, kref);
+
+       DBG(2, "V4L2 device %s deregistered",
+           video_device_node_name(cam->v4ldev));
+       video_set_drvdata(cam->v4ldev, NULL);
+       video_unregister_device(cam->v4ldev);
+       usb_put_dev(cam->usbdev);
+       kfree(cam->control_buffer);
+       kfree(cam);
+
+       mutex_unlock(&sn9c102_sysfs_lock);
+
+}
+
+
+static int sn9c102_open(struct file *filp)
+{
+       struct sn9c102_device* cam;
+       int err = 0;
+
+       /*
+          A read_trylock() in open() is the only safe way to prevent race
+          conditions with disconnect(), one close() and multiple (not
+          necessarily simultaneous) attempts to open(). For example, it
+          prevents from waiting for a second access, while the device
+          structure is being deallocated, after a possible disconnect() and
+          during a following close() holding the write lock: given that, after
+          this deallocation, no access will be possible anymore, using the
+          non-trylock version would have let open() gain the access to the
+          device structure improperly.
+          For this reason the lock must also not be per-device.
+       */
+       if (!down_read_trylock(&sn9c102_dev_lock))
+               return -ERESTARTSYS;
+
+       cam = video_drvdata(filp);
+
+       if (wait_for_completion_interruptible(&cam->probe)) {
+               up_read(&sn9c102_dev_lock);
+               return -ERESTARTSYS;
+       }
+
+       kref_get(&cam->kref);
+
+       /*
+           Make sure to isolate all the simultaneous opens.
+       */
+       if (mutex_lock_interruptible(&cam->open_mutex)) {
+               kref_put(&cam->kref, sn9c102_release_resources);
+               up_read(&sn9c102_dev_lock);
+               return -ERESTARTSYS;
+       }
+
+       if (cam->state & DEV_DISCONNECTED) {
+               DBG(1, "Device not present");
+               err = -ENODEV;
+               goto out;
+       }
+
+       if (cam->users) {
+               DBG(2, "Device %s is already in use",
+                   video_device_node_name(cam->v4ldev));
+               DBG(3, "Simultaneous opens are not supported");
+               /*
+                  open() must follow the open flags and should block
+                  eventually while the device is in use.
+               */
+               if ((filp->f_flags & O_NONBLOCK) ||
+                   (filp->f_flags & O_NDELAY)) {
+                       err = -EWOULDBLOCK;
+                       goto out;
+               }
+               DBG(2, "A blocking open() has been requested. Wait for the "
+                      "device to be released...");
+               up_read(&sn9c102_dev_lock);
+               /*
+                  We will not release the "open_mutex" lock, so that only one
+                  process can be in the wait queue below. This way the process
+                  will be sleeping while holding the lock, without losing its
+                  priority after any wake_up().
+               */
+               err = wait_event_interruptible_exclusive(cam->wait_open,
+                                               (cam->state & DEV_DISCONNECTED)
+                                                        || !cam->users);
+               down_read(&sn9c102_dev_lock);
+               if (err)
+                       goto out;
+               if (cam->state & DEV_DISCONNECTED) {
+                       err = -ENODEV;
+                       goto out;
+               }
+       }
+
+       if (cam->state & DEV_MISCONFIGURED) {
+               err = sn9c102_init(cam);
+               if (err) {
+                       DBG(1, "Initialization failed again. "
+                              "I will retry on next open().");
+                       goto out;
+               }
+               cam->state &= ~DEV_MISCONFIGURED;
+       }
+
+       if ((err = sn9c102_start_transfer(cam)))
+               goto out;
+
+       filp->private_data = cam;
+       cam->users++;
+       cam->io = IO_NONE;
+       cam->stream = STREAM_OFF;
+       cam->nbuffers = 0;
+       cam->frame_count = 0;
+       sn9c102_empty_framequeues(cam);
+
+       DBG(3, "Video device %s is open", video_device_node_name(cam->v4ldev));
+
+out:
+       mutex_unlock(&cam->open_mutex);
+       if (err)
+               kref_put(&cam->kref, sn9c102_release_resources);
+
+       up_read(&sn9c102_dev_lock);
+       return err;
+}
+
+
+static int sn9c102_release(struct file *filp)
+{
+       struct sn9c102_device* cam;
+
+       down_write(&sn9c102_dev_lock);
+
+       cam = video_drvdata(filp);
+
+       sn9c102_stop_transfer(cam);
+       sn9c102_release_buffers(cam);
+       cam->users--;
+       wake_up_interruptible_nr(&cam->wait_open, 1);
+
+       DBG(3, "Video device %s closed", video_device_node_name(cam->v4ldev));
+
+       kref_put(&cam->kref, sn9c102_release_resources);
+
+       up_write(&sn9c102_dev_lock);
+
+       return 0;
+}
+
+
+static ssize_t
+sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
+{
+       struct sn9c102_device *cam = video_drvdata(filp);
+       struct sn9c102_frame_t* f, * i;
+       unsigned long lock_flags;
+       long timeout;
+       int err = 0;
+
+       if (mutex_lock_interruptible(&cam->fileop_mutex))
+               return -ERESTARTSYS;
+
+       if (cam->state & DEV_DISCONNECTED) {
+               DBG(1, "Device not present");
+               mutex_unlock(&cam->fileop_mutex);
+               return -ENODEV;
+       }
+
+       if (cam->state & DEV_MISCONFIGURED) {
+               DBG(1, "The camera is misconfigured. Close and open it "
+                      "again.");
+               mutex_unlock(&cam->fileop_mutex);
+               return -EIO;
+       }
+
+       if (cam->io == IO_MMAP) {
+               DBG(3, "Close and open the device again to choose "
+                      "the read method");
+               mutex_unlock(&cam->fileop_mutex);
+               return -EBUSY;
+       }
+
+       if (cam->io == IO_NONE) {
+               if (!sn9c102_request_buffers(cam,cam->nreadbuffers, IO_READ)) {
+                       DBG(1, "read() failed, not enough memory");
+                       mutex_unlock(&cam->fileop_mutex);
+                       return -ENOMEM;
+               }
+               cam->io = IO_READ;
+               cam->stream = STREAM_ON;
+       }
+
+       if (list_empty(&cam->inqueue)) {
+               if (!list_empty(&cam->outqueue))
+                       sn9c102_empty_framequeues(cam);
+               sn9c102_queue_unusedframes(cam);
+       }
+
+       if (!count) {
+               mutex_unlock(&cam->fileop_mutex);
+               return 0;
+       }
+
+       if (list_empty(&cam->outqueue)) {
+               if (filp->f_flags & O_NONBLOCK) {
+                       mutex_unlock(&cam->fileop_mutex);
+                       return -EAGAIN;
+               }
+               if (!cam->module_param.frame_timeout) {
+                       err = wait_event_interruptible
+                             ( cam->wait_frame,
+                               (!list_empty(&cam->outqueue)) ||
+                               (cam->state & DEV_DISCONNECTED) ||
+                               (cam->state & DEV_MISCONFIGURED) );
+                       if (err) {
+                               mutex_unlock(&cam->fileop_mutex);
+                               return err;
+                       }
+               } else {
+                       timeout = wait_event_interruptible_timeout
+                                 ( cam->wait_frame,
+                                   (!list_empty(&cam->outqueue)) ||
+                                   (cam->state & DEV_DISCONNECTED) ||
+                                   (cam->state & DEV_MISCONFIGURED),
+                                   msecs_to_jiffies(
+                                       cam->module_param.frame_timeout * 1000
+                                   )
+                                 );
+                       if (timeout < 0) {
+                               mutex_unlock(&cam->fileop_mutex);
+                               return timeout;
+                       } else if (timeout == 0 &&
+                                  !(cam->state & DEV_DISCONNECTED)) {
+                               DBG(1, "Video frame timeout elapsed");
+                               mutex_unlock(&cam->fileop_mutex);
+                               return -EIO;
+                       }
+               }
+               if (cam->state & DEV_DISCONNECTED) {
+                       mutex_unlock(&cam->fileop_mutex);
+                       return -ENODEV;
+               }
+               if (cam->state & DEV_MISCONFIGURED) {
+                       mutex_unlock(&cam->fileop_mutex);
+                       return -EIO;
+               }
+       }
+
+       f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame);
+
+       if (count > f->buf.bytesused)
+               count = f->buf.bytesused;
+
+       if (copy_to_user(buf, f->bufmem, count)) {
+               err = -EFAULT;
+               goto exit;
+       }
+       *f_pos += count;
+
+exit:
+       spin_lock_irqsave(&cam->queue_lock, lock_flags);
+       list_for_each_entry(i, &cam->outqueue, frame)
+               i->state = F_UNUSED;
+       INIT_LIST_HEAD(&cam->outqueue);
+       spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+
+       sn9c102_queue_unusedframes(cam);
+
+       PDBGG("Frame #%lu, bytes read: %zu",
+             (unsigned long)f->buf.index, count);
+
+       mutex_unlock(&cam->fileop_mutex);
+
+       return count;
+}
+
+
+static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
+{
+       struct sn9c102_device *cam = video_drvdata(filp);
+       struct sn9c102_frame_t* f;
+       unsigned long lock_flags;
+       unsigned int mask = 0;
+
+       if (mutex_lock_interruptible(&cam->fileop_mutex))
+               return POLLERR;
+
+       if (cam->state & DEV_DISCONNECTED) {
+               DBG(1, "Device not present");
+               goto error;
+       }
+
+       if (cam->state & DEV_MISCONFIGURED) {
+               DBG(1, "The camera is misconfigured. Close and open it "
+                      "again.");
+               goto error;
+       }
+
+       if (cam->io == IO_NONE) {
+               if (!sn9c102_request_buffers(cam, cam->nreadbuffers,
+                                            IO_READ)) {
+                       DBG(1, "poll() failed, not enough memory");
+                       goto error;
+               }
+               cam->io = IO_READ;
+               cam->stream = STREAM_ON;
+       }
+
+       if (cam->io == IO_READ) {
+               spin_lock_irqsave(&cam->queue_lock, lock_flags);
+               list_for_each_entry(f, &cam->outqueue, frame)
+                       f->state = F_UNUSED;
+               INIT_LIST_HEAD(&cam->outqueue);
+               spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+               sn9c102_queue_unusedframes(cam);
+       }
+
+       poll_wait(filp, &cam->wait_frame, wait);
+
+       if (!list_empty(&cam->outqueue))
+               mask |= POLLIN | POLLRDNORM;
+
+       mutex_unlock(&cam->fileop_mutex);
+
+       return mask;
+
+error:
+       mutex_unlock(&cam->fileop_mutex);
+       return POLLERR;
+}
+
+
+static void sn9c102_vm_open(struct vm_area_struct* vma)
+{
+       struct sn9c102_frame_t* f = vma->vm_private_data;
+       f->vma_use_count++;
+}
+
+
+static void sn9c102_vm_close(struct vm_area_struct* vma)
+{
+       /* NOTE: buffers are not freed here */
+       struct sn9c102_frame_t* f = vma->vm_private_data;
+       f->vma_use_count--;
+}
+
+
+static const struct vm_operations_struct sn9c102_vm_ops = {
+       .open = sn9c102_vm_open,
+       .close = sn9c102_vm_close,
+};
+
+
+static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
+{
+       struct sn9c102_device *cam = video_drvdata(filp);
+       unsigned long size = vma->vm_end - vma->vm_start,
+                     start = vma->vm_start;
+       void *pos;
+       u32 i;
+
+       if (mutex_lock_interruptible(&cam->fileop_mutex))
+               return -ERESTARTSYS;
+
+       if (cam->state & DEV_DISCONNECTED) {
+               DBG(1, "Device not present");
+               mutex_unlock(&cam->fileop_mutex);
+               return -ENODEV;
+       }
+
+       if (cam->state & DEV_MISCONFIGURED) {
+               DBG(1, "The camera is misconfigured. Close and open it "
+                      "again.");
+               mutex_unlock(&cam->fileop_mutex);
+               return -EIO;
+       }
+
+       if (!(vma->vm_flags & (VM_WRITE | VM_READ))) {
+               mutex_unlock(&cam->fileop_mutex);
+               return -EACCES;
+       }
+
+       if (cam->io != IO_MMAP ||
+           size != PAGE_ALIGN(cam->frame[0].buf.length)) {
+               mutex_unlock(&cam->fileop_mutex);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < cam->nbuffers; i++) {
+               if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff)
+                       break;
+       }
+       if (i == cam->nbuffers) {
+               mutex_unlock(&cam->fileop_mutex);
+               return -EINVAL;
+       }
+
+       vma->vm_flags |= VM_IO;
+       vma->vm_flags |= VM_RESERVED;
+
+       pos = cam->frame[i].bufmem;
+       while (size > 0) { /* size is page-aligned */
+               if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
+                       mutex_unlock(&cam->fileop_mutex);
+                       return -EAGAIN;
+               }
+               start += PAGE_SIZE;
+               pos += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       vma->vm_ops = &sn9c102_vm_ops;
+       vma->vm_private_data = &cam->frame[i];
+       sn9c102_vm_open(vma);
+
+       mutex_unlock(&cam->fileop_mutex);
+
+       return 0;
+}
+
+/*****************************************************************************/
+
+static int
+sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_capability cap = {
+               .driver = "sn9c102",
+               .version = LINUX_VERSION_CODE,
+               .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+                               V4L2_CAP_STREAMING,
+       };
+
+       strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
+       if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
+               strlcpy(cap.bus_info, dev_name(&cam->usbdev->dev),
+                       sizeof(cap.bus_info));
+
+       if (copy_to_user(arg, &cap, sizeof(cap)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_input i;
+
+       if (copy_from_user(&i, arg, sizeof(i)))
+               return -EFAULT;
+
+       if (i.index)
+               return -EINVAL;
+
+       memset(&i, 0, sizeof(i));
+       strcpy(i.name, "Camera");
+       i.type = V4L2_INPUT_TYPE_CAMERA;
+       i.capabilities = V4L2_IN_CAP_STD;
+
+       if (copy_to_user(arg, &i, sizeof(i)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_g_input(struct sn9c102_device* cam, void __user * arg)
+{
+       int index = 0;
+
+       if (copy_to_user(arg, &index, sizeof(index)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_s_input(struct sn9c102_device* cam, void __user * arg)
+{
+       int index;
+
+       if (copy_from_user(&index, arg, sizeof(index)))
+               return -EFAULT;
+
+       if (index != 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg)
+{
+       struct sn9c102_sensor* s = &cam->sensor;
+       struct v4l2_queryctrl qc;
+       u8 i;
+
+       if (copy_from_user(&qc, arg, sizeof(qc)))
+               return -EFAULT;
+
+       for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+               if (qc.id && qc.id == s->qctrl[i].id) {
+                       memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
+                       if (copy_to_user(arg, &qc, sizeof(qc)))
+                               return -EFAULT;
+                       return 0;
+               }
+
+       return -EINVAL;
+}
+
+
+static int
+sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg)
+{
+       struct sn9c102_sensor* s = &cam->sensor;
+       struct v4l2_control ctrl;
+       int err = 0;
+       u8 i;
+
+       if (!s->get_ctrl && !s->set_ctrl)
+               return -EINVAL;
+
+       if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+               return -EFAULT;
+
+       if (!s->get_ctrl) {
+               for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
+                       if (ctrl.id && ctrl.id == s->qctrl[i].id) {
+                               ctrl.value = s->_qctrl[i].default_value;
+                               goto exit;
+                       }
+               return -EINVAL;
+       } else
+               err = s->get_ctrl(cam, &ctrl);
+
+exit:
+       if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
+               return -EFAULT;
+
+       PDBGG("VIDIOC_G_CTRL: id %lu, value %lu",
+             (unsigned long)ctrl.id, (unsigned long)ctrl.value);
+
+       return err;
+}
+
+
+static int
+sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg)
+{
+       struct sn9c102_sensor* s = &cam->sensor;
+       struct v4l2_control ctrl;
+       u8 i;
+       int err = 0;
+
+       if (!s->set_ctrl)
+               return -EINVAL;
+
+       if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
+               return -EFAULT;
+
+       for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) {
+               if (ctrl.id == s->qctrl[i].id) {
+                       if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)
+                               return -EINVAL;
+                       if (ctrl.value < s->qctrl[i].minimum ||
+                           ctrl.value > s->qctrl[i].maximum)
+                               return -ERANGE;
+                       ctrl.value -= ctrl.value % s->qctrl[i].step;
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(s->qctrl))
+               return -EINVAL;
+       if ((err = s->set_ctrl(cam, &ctrl)))
+               return err;
+
+       s->_qctrl[i].default_value = ctrl.value;
+
+       PDBGG("VIDIOC_S_CTRL: id %lu, value %lu",
+             (unsigned long)ctrl.id, (unsigned long)ctrl.value);
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_cropcap* cc = &(cam->sensor.cropcap);
+
+       cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       cc->pixelaspect.numerator = 1;
+       cc->pixelaspect.denominator = 1;
+
+       if (copy_to_user(arg, cc, sizeof(*cc)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg)
+{
+       struct sn9c102_sensor* s = &cam->sensor;
+       struct v4l2_crop crop = {
+               .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+       };
+
+       memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
+
+       if (copy_to_user(arg, &crop, sizeof(crop)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
+{
+       struct sn9c102_sensor* s = &cam->sensor;
+       struct v4l2_crop crop;
+       struct v4l2_rect* rect;
+       struct v4l2_rect* bounds = &(s->cropcap.bounds);
+       struct v4l2_pix_format* pix_format = &(s->pix_format);
+       u8 scale;
+       const enum sn9c102_stream_state stream = cam->stream;
+       const u32 nbuffers = cam->nbuffers;
+       u32 i;
+       int err = 0;
+
+       if (copy_from_user(&crop, arg, sizeof(crop)))
+               return -EFAULT;
+
+       rect = &(crop.c);
+
+       if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (cam->module_param.force_munmap)
+               for (i = 0; i < cam->nbuffers; i++)
+                       if (cam->frame[i].vma_use_count) {
+                               DBG(3, "VIDIOC_S_CROP failed. "
+                                      "Unmap the buffers first.");
+                               return -EBUSY;
+                       }
+
+       /* Preserve R,G or B origin */
+       rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;
+       rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;
+
+       if (rect->width < 16)
+               rect->width = 16;
+       if (rect->height < 16)
+               rect->height = 16;
+       if (rect->width > bounds->width)
+               rect->width = bounds->width;
+       if (rect->height > bounds->height)
+               rect->height = bounds->height;
+       if (rect->left < bounds->left)
+               rect->left = bounds->left;
+       if (rect->top < bounds->top)
+               rect->top = bounds->top;
+       if (rect->left + rect->width > bounds->left + bounds->width)
+               rect->left = bounds->left+bounds->width - rect->width;
+       if (rect->top + rect->height > bounds->top + bounds->height)
+               rect->top = bounds->top+bounds->height - rect->height;
+
+       rect->width &= ~15L;
+       rect->height &= ~15L;
+
+       if (SN9C102_PRESERVE_IMGSCALE) {
+               /* Calculate the actual scaling factor */
+               u32 a, b;
+               a = rect->width * rect->height;
+               b = pix_format->width * pix_format->height;
+               scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
+       } else
+               scale = 1;
+
+       if (cam->stream == STREAM_ON)
+               if ((err = sn9c102_stream_interrupt(cam)))
+                       return err;
+
+       if (copy_to_user(arg, &crop, sizeof(crop))) {
+               cam->stream = stream;
+               return -EFAULT;
+       }
+
+       if (cam->module_param.force_munmap || cam->io == IO_READ)
+               sn9c102_release_buffers(cam);
+
+       err = sn9c102_set_crop(cam, rect);
+       if (s->set_crop)
+               err += s->set_crop(cam, rect);
+       err += sn9c102_set_scale(cam, scale);
+
+       if (err) { /* atomic, no rollback in ioctl() */
+               cam->state |= DEV_MISCONFIGURED;
+               DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
+                      "use the camera, close and open %s again.",
+                   video_device_node_name(cam->v4ldev));
+               return -EIO;
+       }
+
+       s->pix_format.width = rect->width/scale;
+       s->pix_format.height = rect->height/scale;
+       memcpy(&(s->_rect), rect, sizeof(*rect));
+
+       if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
+           nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
+               cam->state |= DEV_MISCONFIGURED;
+               DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
+                      "use the camera, close and open %s again.",
+                   video_device_node_name(cam->v4ldev));
+               return -ENOMEM;
+       }
+
+       if (cam->io == IO_READ)
+               sn9c102_empty_framequeues(cam);
+       else if (cam->module_param.force_munmap)
+               sn9c102_requeue_outqueue(cam);
+
+       cam->stream = stream;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_enum_framesizes(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_frmsizeenum frmsize;
+
+       if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
+               return -EFAULT;
+
+       if (frmsize.index != 0)
+               return -EINVAL;
+
+       switch (cam->bridge) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+       case BRIDGE_SN9C103:
+               if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X &&
+                   frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
+                       return -EINVAL;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG &&
+                   frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
+                       return -EINVAL;
+       }
+
+       frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE;
+       frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16;
+       frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16;
+       frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width;
+       frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height;
+       memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
+
+       if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_fmtdesc fmtd;
+
+       if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
+               return -EFAULT;
+
+       if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (fmtd.index == 0) {
+               strcpy(fmtd.description, "bayer rgb");
+               fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
+       } else if (fmtd.index == 1) {
+               switch (cam->bridge) {
+               case BRIDGE_SN9C101:
+               case BRIDGE_SN9C102:
+               case BRIDGE_SN9C103:
+                       strcpy(fmtd.description, "compressed");
+                       fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
+                       break;
+               case BRIDGE_SN9C105:
+               case BRIDGE_SN9C120:
+                       strcpy(fmtd.description, "JPEG");
+                       fmtd.pixelformat = V4L2_PIX_FMT_JPEG;
+                       break;
+               }
+               fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
+       } else
+               return -EINVAL;
+
+       fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
+
+       if (copy_to_user(arg, &fmtd, sizeof(fmtd)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_format format;
+       struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format);
+
+       if (copy_from_user(&format, arg, sizeof(format)))
+               return -EFAULT;
+
+       if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ?
+                          V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
+       pfmt->bytesperline = (pfmt->pixelformat == V4L2_PIX_FMT_SN9C10X ||
+                             pfmt->pixelformat == V4L2_PIX_FMT_JPEG)
+                            ? 0 : (pfmt->width * pfmt->priv) / 8;
+       pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
+       pfmt->field = V4L2_FIELD_NONE;
+       memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
+
+       if (copy_to_user(arg, &format, sizeof(format)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
+                        void __user * arg)
+{
+       struct sn9c102_sensor* s = &cam->sensor;
+       struct v4l2_format format;
+       struct v4l2_pix_format* pix;
+       struct v4l2_pix_format* pfmt = &(s->pix_format);
+       struct v4l2_rect* bounds = &(s->cropcap.bounds);
+       struct v4l2_rect rect;
+       u8 scale;
+       const enum sn9c102_stream_state stream = cam->stream;
+       const u32 nbuffers = cam->nbuffers;
+       u32 i;
+       int err = 0;
+
+       if (copy_from_user(&format, arg, sizeof(format)))
+               return -EFAULT;
+
+       pix = &(format.fmt.pix);
+
+       if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       memcpy(&rect, &(s->_rect), sizeof(rect));
+
+       { /* calculate the actual scaling factor */
+               u32 a, b;
+               a = rect.width * rect.height;
+               b = pix->width * pix->height;
+               scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
+       }
+
+       rect.width = scale * pix->width;
+       rect.height = scale * pix->height;
+
+       if (rect.width < 16)
+               rect.width = 16;
+       if (rect.height < 16)
+               rect.height = 16;
+       if (rect.width > bounds->left + bounds->width - rect.left)
+               rect.width = bounds->left + bounds->width - rect.left;
+       if (rect.height > bounds->top + bounds->height - rect.top)
+               rect.height = bounds->top + bounds->height - rect.top;
+
+       rect.width &= ~15L;
+       rect.height &= ~15L;
+
+       { /* adjust the scaling factor */
+               u32 a, b;
+               a = rect.width * rect.height;
+               b = pix->width * pix->height;
+               scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
+       }
+
+       pix->width = rect.width / scale;
+       pix->height = rect.height / scale;
+
+       switch (cam->bridge) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+       case BRIDGE_SN9C103:
+               if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
+                   pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
+                       pix->pixelformat = pfmt->pixelformat;
+               break;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               if (pix->pixelformat != V4L2_PIX_FMT_JPEG &&
+                   pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
+                       pix->pixelformat = pfmt->pixelformat;
+               break;
+       }
+       pix->priv = pfmt->priv; /* bpp */
+       pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_JPEG) ?
+                         V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
+       pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
+                            pix->pixelformat == V4L2_PIX_FMT_JPEG)
+                           ? 0 : (pix->width * pix->priv) / 8;
+       pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
+       pix->field = V4L2_FIELD_NONE;
+
+       if (cmd == VIDIOC_TRY_FMT) {
+               if (copy_to_user(arg, &format, sizeof(format)))
+                       return -EFAULT;
+               return 0;
+       }
+
+       if (cam->module_param.force_munmap)
+               for (i = 0; i < cam->nbuffers; i++)
+                       if (cam->frame[i].vma_use_count) {
+                               DBG(3, "VIDIOC_S_FMT failed. Unmap the "
+                                      "buffers first.");
+                               return -EBUSY;
+                       }
+
+       if (cam->stream == STREAM_ON)
+               if ((err = sn9c102_stream_interrupt(cam)))
+                       return err;
+
+       if (copy_to_user(arg, &format, sizeof(format))) {
+               cam->stream = stream;
+               return -EFAULT;
+       }
+
+       if (cam->module_param.force_munmap  || cam->io == IO_READ)
+               sn9c102_release_buffers(cam);
+
+       err += sn9c102_set_pix_format(cam, pix);
+       err += sn9c102_set_crop(cam, &rect);
+       if (s->set_pix_format)
+               err += s->set_pix_format(cam, pix);
+       if (s->set_crop)
+               err += s->set_crop(cam, &rect);
+       err += sn9c102_set_scale(cam, scale);
+
+       if (err) { /* atomic, no rollback in ioctl() */
+               cam->state |= DEV_MISCONFIGURED;
+               DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
+                      "use the camera, close and open %s again.",
+                   video_device_node_name(cam->v4ldev));
+               return -EIO;
+       }
+
+       memcpy(pfmt, pix, sizeof(*pix));
+       memcpy(&(s->_rect), &rect, sizeof(rect));
+
+       if ((cam->module_param.force_munmap  || cam->io == IO_READ) &&
+           nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
+               cam->state |= DEV_MISCONFIGURED;
+               DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
+                      "use the camera, close and open %s again.",
+                   video_device_node_name(cam->v4ldev));
+               return -ENOMEM;
+       }
+
+       if (cam->io == IO_READ)
+               sn9c102_empty_framequeues(cam);
+       else if (cam->module_param.force_munmap)
+               sn9c102_requeue_outqueue(cam);
+
+       cam->stream = stream;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg)
+{
+       if (copy_to_user(arg, &cam->compression, sizeof(cam->compression)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_jpegcompression jc;
+       const enum sn9c102_stream_state stream = cam->stream;
+       int err = 0;
+
+       if (copy_from_user(&jc, arg, sizeof(jc)))
+               return -EFAULT;
+
+       if (jc.quality != 0 && jc.quality != 1)
+               return -EINVAL;
+
+       if (cam->stream == STREAM_ON)
+               if ((err = sn9c102_stream_interrupt(cam)))
+                       return err;
+
+       err += sn9c102_set_compression(cam, &jc);
+       if (err) { /* atomic, no rollback in ioctl() */
+               cam->state |= DEV_MISCONFIGURED;
+               DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware problems. "
+                      "To use the camera, close and open %s again.",
+                   video_device_node_name(cam->v4ldev));
+               return -EIO;
+       }
+
+       cam->compression.quality = jc.quality;
+
+       cam->stream = stream;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_requestbuffers rb;
+       u32 i;
+       int err;
+
+       if (copy_from_user(&rb, arg, sizeof(rb)))
+               return -EFAULT;
+
+       if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           rb.memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
+
+       if (cam->io == IO_READ) {
+               DBG(3, "Close and open the device again to choose the mmap "
+                      "I/O method");
+               return -EBUSY;
+       }
+
+       for (i = 0; i < cam->nbuffers; i++)
+               if (cam->frame[i].vma_use_count) {
+                       DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are "
+                              "still mapped.");
+                       return -EBUSY;
+               }
+
+       if (cam->stream == STREAM_ON)
+               if ((err = sn9c102_stream_interrupt(cam)))
+                       return err;
+
+       sn9c102_empty_framequeues(cam);
+
+       sn9c102_release_buffers(cam);
+       if (rb.count)
+               rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP);
+
+       if (copy_to_user(arg, &rb, sizeof(rb))) {
+               sn9c102_release_buffers(cam);
+               cam->io = IO_NONE;
+               return -EFAULT;
+       }
+
+       cam->io = rb.count ? IO_MMAP : IO_NONE;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_querybuf(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_buffer b;
+
+       if (copy_from_user(&b, arg, sizeof(b)))
+               return -EFAULT;
+
+       if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           b.index >= cam->nbuffers || cam->io != IO_MMAP)
+               return -EINVAL;
+
+       memcpy(&b, &cam->frame[b.index].buf, sizeof(b));
+
+       if (cam->frame[b.index].vma_use_count)
+               b.flags |= V4L2_BUF_FLAG_MAPPED;
+
+       if (cam->frame[b.index].state == F_DONE)
+               b.flags |= V4L2_BUF_FLAG_DONE;
+       else if (cam->frame[b.index].state != F_UNUSED)
+               b.flags |= V4L2_BUF_FLAG_QUEUED;
+
+       if (copy_to_user(arg, &b, sizeof(b)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_qbuf(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_buffer b;
+       unsigned long lock_flags;
+
+       if (copy_from_user(&b, arg, sizeof(b)))
+               return -EFAULT;
+
+       if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           b.index >= cam->nbuffers || cam->io != IO_MMAP)
+               return -EINVAL;
+
+       if (cam->frame[b.index].state != F_UNUSED)
+               return -EINVAL;
+
+       cam->frame[b.index].state = F_QUEUED;
+
+       spin_lock_irqsave(&cam->queue_lock, lock_flags);
+       list_add_tail(&cam->frame[b.index].frame, &cam->inqueue);
+       spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+
+       PDBGG("Frame #%lu queued", (unsigned long)b.index);
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
+                    void __user * arg)
+{
+       struct v4l2_buffer b;
+       struct sn9c102_frame_t *f;
+       unsigned long lock_flags;
+       long timeout;
+       int err = 0;
+
+       if (copy_from_user(&b, arg, sizeof(b)))
+               return -EFAULT;
+
+       if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
+               return -EINVAL;
+
+       if (list_empty(&cam->outqueue)) {
+               if (cam->stream == STREAM_OFF)
+                       return -EINVAL;
+               if (filp->f_flags & O_NONBLOCK)
+                       return -EAGAIN;
+               if (!cam->module_param.frame_timeout) {
+                       err = wait_event_interruptible
+                             ( cam->wait_frame,
+                               (!list_empty(&cam->outqueue)) ||
+                               (cam->state & DEV_DISCONNECTED) ||
+                               (cam->state & DEV_MISCONFIGURED) );
+                       if (err)
+                               return err;
+               } else {
+                       timeout = wait_event_interruptible_timeout
+                                 ( cam->wait_frame,
+                                   (!list_empty(&cam->outqueue)) ||
+                                   (cam->state & DEV_DISCONNECTED) ||
+                                   (cam->state & DEV_MISCONFIGURED),
+                                   cam->module_param.frame_timeout *
+                                   1000 * msecs_to_jiffies(1) );
+                       if (timeout < 0)
+                               return timeout;
+                       else if (timeout == 0 &&
+                                !(cam->state & DEV_DISCONNECTED)) {
+                               DBG(1, "Video frame timeout elapsed");
+                               return -EIO;
+                       }
+               }
+               if (cam->state & DEV_DISCONNECTED)
+                       return -ENODEV;
+               if (cam->state & DEV_MISCONFIGURED)
+                       return -EIO;
+       }
+
+       spin_lock_irqsave(&cam->queue_lock, lock_flags);
+       f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame);
+       list_del(cam->outqueue.next);
+       spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
+
+       f->state = F_UNUSED;
+
+       memcpy(&b, &f->buf, sizeof(b));
+       if (f->vma_use_count)
+               b.flags |= V4L2_BUF_FLAG_MAPPED;
+
+       if (copy_to_user(arg, &b, sizeof(b)))
+               return -EFAULT;
+
+       PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index);
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg)
+{
+       int type;
+
+       if (copy_from_user(&type, arg, sizeof(type)))
+               return -EFAULT;
+
+       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
+               return -EINVAL;
+
+       cam->stream = STREAM_ON;
+
+       DBG(3, "Stream on");
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_streamoff(struct sn9c102_device* cam, void __user * arg)
+{
+       int type, err;
+
+       if (copy_from_user(&type, arg, sizeof(type)))
+               return -EFAULT;
+
+       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
+               return -EINVAL;
+
+       if (cam->stream == STREAM_ON)
+               if ((err = sn9c102_stream_interrupt(cam)))
+                       return err;
+
+       sn9c102_empty_framequeues(cam);
+
+       DBG(3, "Stream off");
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_g_parm(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_streamparm sp;
+
+       if (copy_from_user(&sp, arg, sizeof(sp)))
+               return -EFAULT;
+
+       if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       sp.parm.capture.extendedmode = 0;
+       sp.parm.capture.readbuffers = cam->nreadbuffers;
+
+       if (copy_to_user(arg, &sp, sizeof(sp)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_streamparm sp;
+
+       if (copy_from_user(&sp, arg, sizeof(sp)))
+               return -EFAULT;
+
+       if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       sp.parm.capture.extendedmode = 0;
+
+       if (sp.parm.capture.readbuffers == 0)
+               sp.parm.capture.readbuffers = cam->nreadbuffers;
+
+       if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES)
+               sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES;
+
+       if (copy_to_user(arg, &sp, sizeof(sp)))
+               return -EFAULT;
+
+       cam->nreadbuffers = sp.parm.capture.readbuffers;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_enumaudio(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_audio audio;
+
+       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
+               return -EINVAL;
+
+       if (copy_from_user(&audio, arg, sizeof(audio)))
+               return -EFAULT;
+
+       if (audio.index != 0)
+               return -EINVAL;
+
+       strcpy(audio.name, "Microphone");
+       audio.capability = 0;
+       audio.mode = 0;
+
+       if (copy_to_user(arg, &audio, sizeof(audio)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_g_audio(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_audio audio;
+
+       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
+               return -EINVAL;
+
+       if (copy_from_user(&audio, arg, sizeof(audio)))
+               return -EFAULT;
+
+       memset(&audio, 0, sizeof(audio));
+       strcpy(audio.name, "Microphone");
+
+       if (copy_to_user(arg, &audio, sizeof(audio)))
+               return -EFAULT;
+
+       return 0;
+}
+
+
+static int
+sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg)
+{
+       struct v4l2_audio audio;
+
+       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
+               return -EINVAL;
+
+       if (copy_from_user(&audio, arg, sizeof(audio)))
+               return -EFAULT;
+
+       if (audio.index != 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+
+static long sn9c102_ioctl_v4l2(struct file *filp,
+                             unsigned int cmd, void __user *arg)
+{
+       struct sn9c102_device *cam = video_drvdata(filp);
+
+       switch (cmd) {
+
+       case VIDIOC_QUERYCAP:
+               return sn9c102_vidioc_querycap(cam, arg);
+
+       case VIDIOC_ENUMINPUT:
+               return sn9c102_vidioc_enuminput(cam, arg);
+
+       case VIDIOC_G_INPUT:
+               return sn9c102_vidioc_g_input(cam, arg);
+
+       case VIDIOC_S_INPUT:
+               return sn9c102_vidioc_s_input(cam, arg);
+
+       case VIDIOC_QUERYCTRL:
+               return sn9c102_vidioc_query_ctrl(cam, arg);
+
+       case VIDIOC_G_CTRL:
+               return sn9c102_vidioc_g_ctrl(cam, arg);
+
+       case VIDIOC_S_CTRL:
+               return sn9c102_vidioc_s_ctrl(cam, arg);
+
+       case VIDIOC_CROPCAP:
+               return sn9c102_vidioc_cropcap(cam, arg);
+
+       case VIDIOC_G_CROP:
+               return sn9c102_vidioc_g_crop(cam, arg);
+
+       case VIDIOC_S_CROP:
+               return sn9c102_vidioc_s_crop(cam, arg);
+
+       case VIDIOC_ENUM_FRAMESIZES:
+               return sn9c102_vidioc_enum_framesizes(cam, arg);
+
+       case VIDIOC_ENUM_FMT:
+               return sn9c102_vidioc_enum_fmt(cam, arg);
+
+       case VIDIOC_G_FMT:
+               return sn9c102_vidioc_g_fmt(cam, arg);
+
+       case VIDIOC_TRY_FMT:
+       case VIDIOC_S_FMT:
+               return sn9c102_vidioc_try_s_fmt(cam, cmd, arg);
+
+       case VIDIOC_G_JPEGCOMP:
+               return sn9c102_vidioc_g_jpegcomp(cam, arg);
+
+       case VIDIOC_S_JPEGCOMP:
+               return sn9c102_vidioc_s_jpegcomp(cam, arg);
+
+       case VIDIOC_REQBUFS:
+               return sn9c102_vidioc_reqbufs(cam, arg);
+
+       case VIDIOC_QUERYBUF:
+               return sn9c102_vidioc_querybuf(cam, arg);
+
+       case VIDIOC_QBUF:
+               return sn9c102_vidioc_qbuf(cam, arg);
+
+       case VIDIOC_DQBUF:
+               return sn9c102_vidioc_dqbuf(cam, filp, arg);
+
+       case VIDIOC_STREAMON:
+               return sn9c102_vidioc_streamon(cam, arg);
+
+       case VIDIOC_STREAMOFF:
+               return sn9c102_vidioc_streamoff(cam, arg);
+
+       case VIDIOC_G_PARM:
+               return sn9c102_vidioc_g_parm(cam, arg);
+
+       case VIDIOC_S_PARM:
+               return sn9c102_vidioc_s_parm(cam, arg);
+
+       case VIDIOC_ENUMAUDIO:
+               return sn9c102_vidioc_enumaudio(cam, arg);
+
+       case VIDIOC_G_AUDIO:
+               return sn9c102_vidioc_g_audio(cam, arg);
+
+       case VIDIOC_S_AUDIO:
+               return sn9c102_vidioc_s_audio(cam, arg);
+
+       default:
+               return -ENOTTY;
+
+       }
+}
+
+
+static long sn9c102_ioctl(struct file *filp,
+                        unsigned int cmd, unsigned long arg)
+{
+       struct sn9c102_device *cam = video_drvdata(filp);
+       int err = 0;
+
+       if (mutex_lock_interruptible(&cam->fileop_mutex))
+               return -ERESTARTSYS;
+
+       if (cam->state & DEV_DISCONNECTED) {
+               DBG(1, "Device not present");
+               mutex_unlock(&cam->fileop_mutex);
+               return -ENODEV;
+       }
+
+       if (cam->state & DEV_MISCONFIGURED) {
+               DBG(1, "The camera is misconfigured. Close and open it "
+                      "again.");
+               mutex_unlock(&cam->fileop_mutex);
+               return -EIO;
+       }
+
+       V4LDBG(3, "sn9c102", cmd);
+
+       err = sn9c102_ioctl_v4l2(filp, cmd, (void __user *)arg);
+
+       mutex_unlock(&cam->fileop_mutex);
+
+       return err;
+}
+
+/*****************************************************************************/
+
+static const struct v4l2_file_operations sn9c102_fops = {
+       .owner = THIS_MODULE,
+       .open = sn9c102_open,
+       .release = sn9c102_release,
+       .unlocked_ioctl = sn9c102_ioctl,
+       .read = sn9c102_read,
+       .poll = sn9c102_poll,
+       .mmap = sn9c102_mmap,
+};
+
+/*****************************************************************************/
+
+/* It exists a single interface only. We do not need to validate anything. */
+static int
+sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct sn9c102_device* cam;
+       static unsigned int dev_nr;
+       unsigned int i;
+       int err = 0, r;
+
+       if (!(cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL)))
+               return -ENOMEM;
+
+       cam->usbdev = udev;
+
+       if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) {
+               DBG(1, "kzalloc() failed");
+               err = -ENOMEM;
+               goto fail;
+       }
+
+       if (!(cam->v4ldev = video_device_alloc())) {
+               DBG(1, "video_device_alloc() failed");
+               err = -ENOMEM;
+               goto fail;
+       }
+
+       r = sn9c102_read_reg(cam, 0x00);
+       if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
+               DBG(1, "Sorry, this is not a SN9C1xx-based camera "
+                      "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+               err = -ENODEV;
+               goto fail;
+       }
+
+       cam->bridge = id->driver_info;
+       switch (cam->bridge) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+               DBG(2, "SN9C10[12] PC Camera Controller detected "
+                      "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+               break;
+       case BRIDGE_SN9C103:
+               DBG(2, "SN9C103 PC Camera Controller detected "
+                      "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+               break;
+       case BRIDGE_SN9C105:
+               DBG(2, "SN9C105 PC Camera Controller detected "
+                      "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+               break;
+       case BRIDGE_SN9C120:
+               DBG(2, "SN9C120 PC Camera Controller detected "
+                      "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
+               break;
+       }
+
+       for  (i = 0; i < ARRAY_SIZE(sn9c102_sensor_table); i++) {
+               err = sn9c102_sensor_table[i](cam);
+               if (!err)
+                       break;
+       }
+
+       if (!err) {
+               DBG(2, "%s image sensor detected", cam->sensor.name);
+               DBG(3, "Support for %s maintained by %s",
+                   cam->sensor.name, cam->sensor.maintainer);
+       } else {
+               DBG(1, "No supported image sensor detected for this bridge");
+               err = -ENODEV;
+               goto fail;
+       }
+
+       if (!(cam->bridge & cam->sensor.supported_bridge)) {
+               DBG(1, "Bridge not supported");
+               err = -ENODEV;
+               goto fail;
+       }
+
+       if (sn9c102_init(cam)) {
+               DBG(1, "Initialization failed. I will retry on open().");
+               cam->state |= DEV_MISCONFIGURED;
+       }
+
+       strcpy(cam->v4ldev->name, "SN9C1xx PC Camera");
+       cam->v4ldev->fops = &sn9c102_fops;
+       cam->v4ldev->release = video_device_release;
+       cam->v4ldev->parent = &udev->dev;
+
+       init_completion(&cam->probe);
+
+       err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
+                                   video_nr[dev_nr]);
+       if (err) {
+               DBG(1, "V4L2 device registration failed");
+               if (err == -ENFILE && video_nr[dev_nr] == -1)
+                       DBG(1, "Free /dev/videoX node not found");
+               video_nr[dev_nr] = -1;
+               dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
+               complete_all(&cam->probe);
+               goto fail;
+       }
+
+       DBG(2, "V4L2 device registered as %s",
+           video_device_node_name(cam->v4ldev));
+
+       video_set_drvdata(cam->v4ldev, cam);
+       cam->module_param.force_munmap = force_munmap[dev_nr];
+       cam->module_param.frame_timeout = frame_timeout[dev_nr];
+
+       dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       err = sn9c102_create_sysfs(cam);
+       if (!err)
+               DBG(2, "Optional device control through 'sysfs' "
+                      "interface ready");
+       else
+               DBG(2, "Failed to create optional 'sysfs' interface for "
+                      "device controlling. Error #%d", err);
+#else
+       DBG(2, "Optional device control through 'sysfs' interface disabled");
+       DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' "
+              "configuration option to enable it.");
+#endif
+
+       usb_set_intfdata(intf, cam);
+       kref_init(&cam->kref);
+       usb_get_dev(cam->usbdev);
+
+       complete_all(&cam->probe);
+
+       return 0;
+
+fail:
+       if (cam) {
+               kfree(cam->control_buffer);
+               if (cam->v4ldev)
+                       video_device_release(cam->v4ldev);
+               kfree(cam);
+       }
+       return err;
+}
+
+
+static void sn9c102_usb_disconnect(struct usb_interface* intf)
+{
+       struct sn9c102_device* cam;
+
+       down_write(&sn9c102_dev_lock);
+
+       cam = usb_get_intfdata(intf);
+
+       DBG(2, "Disconnecting %s...", cam->v4ldev->name);
+
+       if (cam->users) {
+               DBG(2, "Device %s is open! Deregistration and memory "
+                      "deallocation are deferred.",
+                   video_device_node_name(cam->v4ldev));
+               cam->state |= DEV_MISCONFIGURED;
+               sn9c102_stop_transfer(cam);
+               cam->state |= DEV_DISCONNECTED;
+               wake_up_interruptible(&cam->wait_frame);
+               wake_up(&cam->wait_stream);
+       } else
+               cam->state |= DEV_DISCONNECTED;
+
+       wake_up_interruptible_all(&cam->wait_open);
+
+       kref_put(&cam->kref, sn9c102_release_resources);
+
+       up_write(&sn9c102_dev_lock);
+}
+
+
+static struct usb_driver sn9c102_usb_driver = {
+       .name =       "sn9c102",
+       .id_table =   sn9c102_id_table,
+       .probe =      sn9c102_usb_probe,
+       .disconnect = sn9c102_usb_disconnect,
+};
+
+module_usb_driver(sn9c102_usb_driver);
diff --git a/drivers/media/usb/sn9c102/sn9c102_devtable.h b/drivers/media/usb/sn9c102/sn9c102_devtable.h
new file mode 100644 (file)
index 0000000..b3d2cc7
--- /dev/null
@@ -0,0 +1,147 @@
+/***************************************************************************
+ * Table of device identifiers of the SN9C1xx PC Camera Controllers        *
+ *                                                                         *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * 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.               *
+ ***************************************************************************/
+
+#ifndef _SN9C102_DEVTABLE_H_
+#define _SN9C102_DEVTABLE_H_
+
+#include <linux/usb.h>
+
+struct sn9c102_device;
+
+/*
+   Each SN9C1xx camera has proper PID/VID identifiers.
+   SN9C103, SN9C105, SN9C120 support multiple interfaces, but we only have to
+   handle the video class interface.
+*/
+#define SN9C102_USB_DEVICE(vend, prod, bridge)                                \
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE |                           \
+                      USB_DEVICE_ID_MATCH_INT_CLASS,                         \
+       .idVendor = (vend),                                                   \
+       .idProduct = (prod),                                                  \
+       .bInterfaceClass = 0xff,                                              \
+       .driver_info = (bridge)
+
+static const struct usb_device_id sn9c102_id_table[] = {
+       /* SN9C101 and SN9C102 */
+#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
+       { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), },
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */
+       { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), },
+#endif
+       { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), },
+#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
+       { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), },
+#endif
+       { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, /* not in sonixb */
+#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
+       { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */
+       { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
+#endif
+       { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, /* not in sonixb */
+       /* SN9C103 */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, non existent ? */
+       { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), }, /* not in sonixb */
+#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, HY7131D/E */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), }, non existent ? */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), }, non existent ? */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, non existent ? */
+       { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), },
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */
+       { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), },
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, non existent ? */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), }, non existent ? */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, non existent ? */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, PAS106 */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, TAS5130 */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, TAS5110, non existent */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, non existent ? */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, non existent ? */
+       { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), },
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, non existent ? */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), }, non existent ? */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), }, non existent ? */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), }, non existent ? */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), }, non existent ? */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, non existent ? */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, non existent ? */
+#endif
+       /* SN9C105 */
+#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE
+       { SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), }, PO1030 */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, OM6801 */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, HV7131GP */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, non existent ? */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, MO4000 */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), }, ICM105C */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, OV7648 */
+       { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
+       /* SN9C120 */
+       { SN9C102_USB_DEVICE(0x0458, 0x7025, BRIDGE_SN9C120), },
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), }, po2030 */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, om6801 */
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, S5K53BEB */
+       { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
+/*     { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */
+       { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
+       { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), },
+#endif
+       { }
+};
+
+/*
+   Probing functions: on success, you must attach the sensor to the camera
+   by calling sn9c102_attach_sensor().
+   To enable the I2C communication, you might need to perform a really basic
+   initialization of the SN9C1XX chip.
+   Functions must return 0 on success, the appropriate error otherwise.
+*/
+extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
+extern int sn9c102_probe_hv7131r(struct sn9c102_device* cam);
+extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
+extern int sn9c102_probe_mi0360(struct sn9c102_device* cam);
+extern int sn9c102_probe_mt9v111(struct sn9c102_device *cam);
+extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
+extern int sn9c102_probe_ov7660(struct sn9c102_device* cam);
+extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
+extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
+extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
+extern int sn9c102_probe_tas5110d(struct sn9c102_device* cam);
+extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
+
+#endif /* _SN9C102_DEVTABLE_H_ */
diff --git a/drivers/media/usb/sn9c102/sn9c102_hv7131d.c b/drivers/media/usb/sn9c102/sn9c102_hv7131d.c
new file mode 100644 (file)
index 0000000..2dce5c9
--- /dev/null
@@ -0,0 +1,264 @@
+/***************************************************************************
+ * Plug-in for HV7131D image sensor connected to the SN9C1xx PC Camera     *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ *                                                                         *
+ * 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 "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
+
+
+static int hv7131d_init(struct sn9c102_device* cam)
+{
+       int err;
+
+       err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
+                                      {0x00, 0x14}, {0x60, 0x17},
+                                      {0x0e, 0x18}, {0xf2, 0x19});
+
+       err += sn9c102_i2c_write(cam, 0x01, 0x04);
+       err += sn9c102_i2c_write(cam, 0x02, 0x00);
+       err += sn9c102_i2c_write(cam, 0x28, 0x00);
+
+       return err;
+}
+
+
+static int hv7131d_get_ctrl(struct sn9c102_device* cam,
+                           struct v4l2_control* ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               {
+                       int r1 = sn9c102_i2c_read(cam, 0x26),
+                           r2 = sn9c102_i2c_read(cam, 0x27);
+                       if (r1 < 0 || r2 < 0)
+                               return -EIO;
+                       ctrl->value = (r1 << 8) | (r2 & 0xff);
+               }
+               return 0;
+       case V4L2_CID_RED_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0)
+                       return -EIO;
+               ctrl->value = 0x3f - (ctrl->value & 0x3f);
+               return 0;
+       case V4L2_CID_BLUE_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0)
+                       return -EIO;
+               ctrl->value = 0x3f - (ctrl->value & 0x3f);
+               return 0;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0)
+                       return -EIO;
+               ctrl->value = 0x3f - (ctrl->value & 0x3f);
+               return 0;
+       case SN9C102_V4L2_CID_RESET_LEVEL:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x3f;
+               return 0;
+       case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x34)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x07;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+
+static int hv7131d_set_ctrl(struct sn9c102_device* cam,
+                           const struct v4l2_control* ctrl)
+{
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               err += sn9c102_i2c_write(cam, 0x26, ctrl->value >> 8);
+               err += sn9c102_i2c_write(cam, 0x27, ctrl->value & 0xff);
+               break;
+       case V4L2_CID_RED_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x31, 0x3f - ctrl->value);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x33, 0x3f - ctrl->value);
+               break;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x32, 0x3f - ctrl->value);
+               break;
+       case SN9C102_V4L2_CID_RESET_LEVEL:
+               err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
+               break;
+       case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE:
+               err += sn9c102_i2c_write(cam, 0x34, ctrl->value);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int hv7131d_set_crop(struct sn9c102_device* cam,
+                           const struct v4l2_rect* rect)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2,
+          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
+
+       err += sn9c102_write_reg(cam, h_start, 0x12);
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+
+       return err;
+}
+
+
+static int hv7131d_set_pix_format(struct sn9c102_device* cam,
+                                 const struct v4l2_pix_format* pix)
+{
+       int err = 0;
+
+       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+               err += sn9c102_write_reg(cam, 0x42, 0x19);
+       else
+               err += sn9c102_write_reg(cam, 0xf2, 0x19);
+
+       return err;
+}
+
+
+static const struct sn9c102_sensor hv7131d = {
+       .name = "HV7131D",
+       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
+       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
+       .frequency = SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_2WIRES,
+       .i2c_slave_id = 0x11,
+       .init = &hv7131d_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_EXPOSURE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "exposure",
+                       .minimum = 0x0250,
+                       .maximum = 0xffff,
+                       .step = 0x0001,
+                       .default_value = 0x0250,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_RED_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "red balance",
+                       .minimum = 0x00,
+                       .maximum = 0x3f,
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_BLUE_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "blue balance",
+                       .minimum = 0x00,
+                       .maximum = 0x3f,
+                       .step = 0x01,
+                       .default_value = 0x20,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "green balance",
+                       .minimum = 0x00,
+                       .maximum = 0x3f,
+                       .step = 0x01,
+                       .default_value = 0x1e,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_RESET_LEVEL,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "reset level",
+                       .minimum = 0x19,
+                       .maximum = 0x3f,
+                       .step = 0x01,
+                       .default_value = 0x30,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "pixel bias voltage",
+                       .minimum = 0x00,
+                       .maximum = 0x07,
+                       .step = 0x01,
+                       .default_value = 0x02,
+                       .flags = 0,
+               },
+       },
+       .get_ctrl = &hv7131d_get_ctrl,
+       .set_ctrl = &hv7131d_set_ctrl,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+       },
+       .set_crop = &hv7131d_set_crop,
+       .pix_format = {
+               .width = 640,
+               .height = 480,
+               .pixelformat = V4L2_PIX_FMT_SBGGR8,
+               .priv = 8,
+       },
+       .set_pix_format = &hv7131d_set_pix_format
+};
+
+
+int sn9c102_probe_hv7131d(struct sn9c102_device* cam)
+{
+       int r0 = 0, r1 = 0, err;
+
+       err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
+                                      {0x28, 0x17});
+
+       r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00);
+       r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01);
+       if (err || r0 < 0 || r1 < 0)
+               return -EIO;
+
+       if ((r0 != 0x00 && r0 != 0x01) || r1 != 0x04)
+               return -ENODEV;
+
+       sn9c102_attach_sensor(cam, &hv7131d);
+
+       return 0;
+}
diff --git a/drivers/media/usb/sn9c102/sn9c102_hv7131r.c b/drivers/media/usb/sn9c102/sn9c102_hv7131r.c
new file mode 100644 (file)
index 0000000..4295887
--- /dev/null
@@ -0,0 +1,363 @@
+/***************************************************************************
+ * Plug-in for HV7131R image sensor connected to the SN9C1xx PC Camera     *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * 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 "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
+
+
+static int hv7131r_init(struct sn9c102_device* cam)
+{
+       int err = 0;
+
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C103:
+               err = sn9c102_write_const_regs(cam, {0x00, 0x03}, {0x1a, 0x04},
+                                              {0x20, 0x05}, {0x20, 0x06},
+                                              {0x03, 0x10}, {0x00, 0x14},
+                                              {0x60, 0x17}, {0x0a, 0x18},
+                                              {0xf0, 0x19}, {0x1d, 0x1a},
+                                              {0x10, 0x1b}, {0x02, 0x1c},
+                                              {0x03, 0x1d}, {0x0f, 0x1e},
+                                              {0x0c, 0x1f}, {0x00, 0x20},
+                                              {0x10, 0x21}, {0x20, 0x22},
+                                              {0x30, 0x23}, {0x40, 0x24},
+                                              {0x50, 0x25}, {0x60, 0x26},
+                                              {0x70, 0x27}, {0x80, 0x28},
+                                              {0x90, 0x29}, {0xa0, 0x2a},
+                                              {0xb0, 0x2b}, {0xc0, 0x2c},
+                                              {0xd0, 0x2d}, {0xe0, 0x2e},
+                                              {0xf0, 0x2f}, {0xff, 0x30});
+               break;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
+                                              {0x00, 0x03}, {0x1a, 0x04},
+                                              {0x44, 0x05}, {0x3e, 0x06},
+                                              {0x1a, 0x07}, {0x03, 0x10},
+                                              {0x08, 0x14}, {0xa3, 0x17},
+                                              {0x4b, 0x18}, {0x00, 0x19},
+                                              {0x1d, 0x1a}, {0x10, 0x1b},
+                                              {0x02, 0x1c}, {0x03, 0x1d},
+                                              {0x0f, 0x1e}, {0x0c, 0x1f},
+                                              {0x00, 0x20}, {0x29, 0x21},
+                                              {0x40, 0x22}, {0x54, 0x23},
+                                              {0x66, 0x24}, {0x76, 0x25},
+                                              {0x85, 0x26}, {0x94, 0x27},
+                                              {0xa1, 0x28}, {0xae, 0x29},
+                                              {0xbb, 0x2a}, {0xc7, 0x2b},
+                                              {0xd3, 0x2c}, {0xde, 0x2d},
+                                              {0xea, 0x2e}, {0xf4, 0x2f},
+                                              {0xff, 0x30}, {0x00, 0x3F},
+                                              {0xC7, 0x40}, {0x01, 0x41},
+                                              {0x44, 0x42}, {0x00, 0x43},
+                                              {0x44, 0x44}, {0x00, 0x45},
+                                              {0x44, 0x46}, {0x00, 0x47},
+                                              {0xC7, 0x48}, {0x01, 0x49},
+                                              {0xC7, 0x4A}, {0x01, 0x4B},
+                                              {0xC7, 0x4C}, {0x01, 0x4D},
+                                              {0x44, 0x4E}, {0x00, 0x4F},
+                                              {0x44, 0x50}, {0x00, 0x51},
+                                              {0x44, 0x52}, {0x00, 0x53},
+                                              {0xC7, 0x54}, {0x01, 0x55},
+                                              {0xC7, 0x56}, {0x01, 0x57},
+                                              {0xC7, 0x58}, {0x01, 0x59},
+                                              {0x44, 0x5A}, {0x00, 0x5B},
+                                              {0x44, 0x5C}, {0x00, 0x5D},
+                                              {0x44, 0x5E}, {0x00, 0x5F},
+                                              {0xC7, 0x60}, {0x01, 0x61},
+                                              {0xC7, 0x62}, {0x01, 0x63},
+                                              {0xC7, 0x64}, {0x01, 0x65},
+                                              {0x44, 0x66}, {0x00, 0x67},
+                                              {0x44, 0x68}, {0x00, 0x69},
+                                              {0x44, 0x6A}, {0x00, 0x6B},
+                                              {0xC7, 0x6C}, {0x01, 0x6D},
+                                              {0xC7, 0x6E}, {0x01, 0x6F},
+                                              {0xC7, 0x70}, {0x01, 0x71},
+                                              {0x44, 0x72}, {0x00, 0x73},
+                                              {0x44, 0x74}, {0x00, 0x75},
+                                              {0x44, 0x76}, {0x00, 0x77},
+                                              {0xC7, 0x78}, {0x01, 0x79},
+                                              {0xC7, 0x7A}, {0x01, 0x7B},
+                                              {0xC7, 0x7C}, {0x01, 0x7D},
+                                              {0x44, 0x7E}, {0x00, 0x7F},
+                                              {0x14, 0x84}, {0x00, 0x85},
+                                              {0x27, 0x86}, {0x00, 0x87},
+                                              {0x07, 0x88}, {0x00, 0x89},
+                                              {0xEC, 0x8A}, {0x0f, 0x8B},
+                                              {0xD8, 0x8C}, {0x0f, 0x8D},
+                                              {0x3D, 0x8E}, {0x00, 0x8F},
+                                              {0x3D, 0x90}, {0x00, 0x91},
+                                              {0xCD, 0x92}, {0x0f, 0x93},
+                                              {0xf7, 0x94}, {0x0f, 0x95},
+                                              {0x0C, 0x96}, {0x00, 0x97},
+                                              {0x00, 0x98}, {0x66, 0x99},
+                                              {0x05, 0x9A}, {0x00, 0x9B},
+                                              {0x04, 0x9C}, {0x00, 0x9D},
+                                              {0x08, 0x9E}, {0x00, 0x9F},
+                                              {0x2D, 0xC0}, {0x2D, 0xC1},
+                                              {0x3A, 0xC2}, {0x05, 0xC3},
+                                              {0x04, 0xC4}, {0x3F, 0xC5},
+                                              {0x00, 0xC6}, {0x00, 0xC7},
+                                              {0x50, 0xC8}, {0x3C, 0xC9},
+                                              {0x28, 0xCA}, {0xD8, 0xCB},
+                                              {0x14, 0xCC}, {0xEC, 0xCD},
+                                              {0x32, 0xCE}, {0xDD, 0xCF},
+                                              {0x32, 0xD0}, {0xDD, 0xD1},
+                                              {0x6A, 0xD2}, {0x50, 0xD3},
+                                              {0x00, 0xD4}, {0x00, 0xD5},
+                                              {0x00, 0xD6});
+               break;
+       default:
+               break;
+       }
+
+       err += sn9c102_i2c_write(cam, 0x20, 0x00);
+       err += sn9c102_i2c_write(cam, 0x21, 0xd6);
+       err += sn9c102_i2c_write(cam, 0x25, 0x06);
+
+       return err;
+}
+
+
+static int hv7131r_get_ctrl(struct sn9c102_device* cam,
+                           struct v4l2_control* ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0)
+                       return -EIO;
+               return 0;
+       case V4L2_CID_RED_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0)
+                       return -EIO;
+               ctrl->value = ctrl->value & 0x3f;
+               return 0;
+       case V4L2_CID_BLUE_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0)
+                       return -EIO;
+               ctrl->value = ctrl->value & 0x3f;
+               return 0;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0)
+                       return -EIO;
+               ctrl->value = ctrl->value & 0x3f;
+               return 0;
+       case V4L2_CID_BLACK_LEVEL:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x01)) < 0)
+                       return -EIO;
+               ctrl->value = (ctrl->value & 0x08) ? 1 : 0;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+
+static int hv7131r_set_ctrl(struct sn9c102_device* cam,
+                           const struct v4l2_control* ctrl)
+{
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+               err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
+               break;
+       case V4L2_CID_RED_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x31, ctrl->value);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x33, ctrl->value);
+               break;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x32, ctrl->value);
+               break;
+       case V4L2_CID_BLACK_LEVEL:
+               {
+                       int r = sn9c102_i2c_read(cam, 0x01);
+                       if (r < 0)
+                               return -EIO;
+                       err += sn9c102_i2c_write(cam, 0x01,
+                                                (ctrl->value<<3) | (r&0xf7));
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int hv7131r_set_crop(struct sn9c102_device* cam,
+                           const struct v4l2_rect* rect)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
+          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+
+       err += sn9c102_write_reg(cam, h_start, 0x12);
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+
+       return err;
+}
+
+
+static int hv7131r_set_pix_format(struct sn9c102_device* cam,
+                                 const struct v4l2_pix_format* pix)
+{
+       int err = 0;
+
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C103:
+               if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
+                       err += sn9c102_write_reg(cam, 0xa0, 0x19);
+                       err += sn9c102_i2c_write(cam, 0x01, 0x04);
+               } else {
+                       err += sn9c102_write_reg(cam, 0x30, 0x19);
+                       err += sn9c102_i2c_write(cam, 0x01, 0x04);
+               }
+               break;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
+                       err += sn9c102_write_reg(cam, 0xa5, 0x17);
+                       err += sn9c102_i2c_write(cam, 0x01, 0x24);
+               } else {
+                       err += sn9c102_write_reg(cam, 0xa3, 0x17);
+                       err += sn9c102_i2c_write(cam, 0x01, 0x04);
+               }
+               break;
+       default:
+               break;
+       }
+
+       return err;
+}
+
+
+static const struct sn9c102_sensor hv7131r = {
+       .name = "HV7131R",
+       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
+       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
+       .frequency = SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_2WIRES,
+       .i2c_slave_id = 0x11,
+       .init = &hv7131r_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "global gain",
+                       .minimum = 0x00,
+                       .maximum = 0xff,
+                       .step = 0x01,
+                       .default_value = 0x40,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_RED_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "red balance",
+                       .minimum = 0x00,
+                       .maximum = 0x3f,
+                       .step = 0x01,
+                       .default_value = 0x08,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_BLUE_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "blue balance",
+                       .minimum = 0x00,
+                       .maximum = 0x3f,
+                       .step = 0x01,
+                       .default_value = 0x1a,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "green balance",
+                       .minimum = 0x00,
+                       .maximum = 0x3f,
+                       .step = 0x01,
+                       .default_value = 0x2f,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_BLACK_LEVEL,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "auto black level compensation",
+                       .minimum = 0x00,
+                       .maximum = 0x01,
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+       },
+       .get_ctrl = &hv7131r_get_ctrl,
+       .set_ctrl = &hv7131r_set_ctrl,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+       },
+       .set_crop = &hv7131r_set_crop,
+       .pix_format = {
+               .width = 640,
+               .height = 480,
+               .pixelformat = V4L2_PIX_FMT_SBGGR8,
+               .priv = 8,
+       },
+       .set_pix_format = &hv7131r_set_pix_format
+};
+
+
+int sn9c102_probe_hv7131r(struct sn9c102_device* cam)
+{
+       int devid, err;
+
+       err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x02},
+                                      {0x34, 0x01}, {0x20, 0x17},
+                                      {0x34, 0x01}, {0x46, 0x01});
+
+       devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00);
+       if (err || devid < 0)
+               return -EIO;
+
+       if (devid != 0x02)
+               return -ENODEV;
+
+       sn9c102_attach_sensor(cam, &hv7131r);
+
+       return 0;
+}
diff --git a/drivers/media/usb/sn9c102/sn9c102_mi0343.c b/drivers/media/usb/sn9c102/sn9c102_mi0343.c
new file mode 100644 (file)
index 0000000..1f5b09b
--- /dev/null
@@ -0,0 +1,352 @@
+/***************************************************************************
+ * Plug-in for MI-0343 image sensor connected to the SN9C1xx PC Camera     *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ *                                                                         *
+ * 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 "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
+
+
+static int mi0343_init(struct sn9c102_device* cam)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+
+       err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
+                                      {0x0a, 0x14}, {0x40, 0x01},
+                                      {0x20, 0x17}, {0x07, 0x18},
+                                      {0xa0, 0x19});
+
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
+                                        0x00, 0x01, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
+                                        0x00, 0x00, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
+                                        0x01, 0xe1, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
+                                        0x02, 0x81, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
+                                        0x00, 0x17, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
+                                        0x00, 0x11, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
+                                        0x04, 0x9a, 0, 0);
+
+       return err;
+}
+
+
+static int mi0343_get_ctrl(struct sn9c102_device* cam,
+                          struct v4l2_control* ctrl)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       u8 data[2];
+
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
+                                            data) < 0)
+                       return -EIO;
+               ctrl->value = data[0];
+               return 0;
+       case V4L2_CID_GAIN:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
+                                            data) < 0)
+                       return -EIO;
+               break;
+       case V4L2_CID_HFLIP:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
+                                            data) < 0)
+                       return -EIO;
+               ctrl->value = data[1] & 0x20 ? 1 : 0;
+               return 0;
+       case V4L2_CID_VFLIP:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
+                                            data) < 0)
+                       return -EIO;
+               ctrl->value = data[1] & 0x80 ? 1 : 0;
+               return 0;
+       case V4L2_CID_RED_BALANCE:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
+                                            data) < 0)
+                       return -EIO;
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
+                                            data) < 0)
+                       return -EIO;
+               break;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
+                                            data) < 0)
+                       return -EIO;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+       case V4L2_CID_RED_BALANCE:
+       case V4L2_CID_BLUE_BALANCE:
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               ctrl->value = data[1] | (data[0] << 8);
+               if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
+                       ctrl->value -= 0x10;
+               else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
+                       ctrl->value -= 0x60;
+               else if (ctrl->value >= 0xe0 && ctrl->value <= 0xff)
+                       ctrl->value -= 0xe0;
+       }
+
+       return 0;
+}
+
+
+static int mi0343_set_ctrl(struct sn9c102_device* cam,
+                          const struct v4l2_control* ctrl)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       u16 reg = 0;
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+       case V4L2_CID_RED_BALANCE:
+       case V4L2_CID_BLUE_BALANCE:
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               if (ctrl->value <= (0x3f-0x10))
+                       reg = 0x10 + ctrl->value;
+               else if (ctrl->value <= ((0x3f-0x10) + (0x7f-0x60)))
+                       reg = 0x60 + (ctrl->value - (0x3f-0x10));
+               else
+                       reg = 0xe0 + (ctrl->value - (0x3f-0x10) - (0x7f-0x60));
+               break;
+       }
+
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x09, ctrl->value, 0x00,
+                                                0, 0);
+               break;
+       case V4L2_CID_GAIN:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x35, reg >> 8, reg & 0xff,
+                                                0, 0);
+               break;
+       case V4L2_CID_HFLIP:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x20, ctrl->value ? 0x40:0x00,
+                                                ctrl->value ? 0x20:0x00,
+                                                0, 0);
+               break;
+       case V4L2_CID_VFLIP:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x20, ctrl->value ? 0x80:0x00,
+                                                ctrl->value ? 0x80:0x00,
+                                                0, 0);
+               break;
+       case V4L2_CID_RED_BALANCE:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x2d, reg >> 8, reg & 0xff,
+                                                0, 0);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x2c, reg >> 8, reg & 0xff,
+                                                0, 0);
+               break;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x2b, reg >> 8, reg & 0xff,
+                                                0, 0);
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x2e, reg >> 8, reg & 0xff,
+                                                0, 0);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int mi0343_set_crop(struct sn9c102_device* cam,
+                           const struct v4l2_rect* rect)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
+          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
+
+       err += sn9c102_write_reg(cam, h_start, 0x12);
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+
+       return err;
+}
+
+
+static int mi0343_set_pix_format(struct sn9c102_device* cam,
+                                const struct v4l2_pix_format* pix)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+
+       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x0a, 0x00, 0x03, 0, 0);
+               err += sn9c102_write_reg(cam, 0x20, 0x19);
+       } else {
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x0a, 0x00, 0x05, 0, 0);
+               err += sn9c102_write_reg(cam, 0xa0, 0x19);
+       }
+
+       return err;
+}
+
+
+static const struct sn9c102_sensor mi0343 = {
+       .name = "MI-0343",
+       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
+       .frequency = SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_2WIRES,
+       .i2c_slave_id = 0x5d,
+       .init = &mi0343_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_EXPOSURE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "exposure",
+                       .minimum = 0x00,
+                       .maximum = 0x0f,
+                       .step = 0x01,
+                       .default_value = 0x06,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "global gain",
+                       .minimum = 0x00,
+                       .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),/*0x6d*/
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_HFLIP,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "horizontal mirror",
+                       .minimum = 0,
+                       .maximum = 1,
+                       .step = 1,
+                       .default_value = 0,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_VFLIP,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "vertical mirror",
+                       .minimum = 0,
+                       .maximum = 1,
+                       .step = 1,
+                       .default_value = 0,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_RED_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "red balance",
+                       .minimum = 0x00,
+                       .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_BLUE_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "blue balance",
+                       .minimum = 0x00,
+                       .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "green balance",
+                       .minimum = 0x00,
+                       .maximum = ((0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0)),
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+       },
+       .get_ctrl = &mi0343_get_ctrl,
+       .set_ctrl = &mi0343_set_ctrl,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+       },
+       .set_crop = &mi0343_set_crop,
+       .pix_format = {
+               .width = 640,
+               .height = 480,
+               .pixelformat = V4L2_PIX_FMT_SBGGR8,
+               .priv = 8,
+       },
+       .set_pix_format = &mi0343_set_pix_format
+};
+
+
+int sn9c102_probe_mi0343(struct sn9c102_device* cam)
+{
+       u8 data[2];
+
+       if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
+                                    {0x28, 0x17}))
+               return -EIO;
+
+       if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
+                                    2, data) < 0)
+               return -EIO;
+
+       if (data[1] != 0x42 || data[0] != 0xe3)
+               return -ENODEV;
+
+       sn9c102_attach_sensor(cam, &mi0343);
+
+       return 0;
+}
diff --git a/drivers/media/usb/sn9c102/sn9c102_mi0360.c b/drivers/media/usb/sn9c102/sn9c102_mi0360.c
new file mode 100644 (file)
index 0000000..d973fc1
--- /dev/null
@@ -0,0 +1,453 @@
+/***************************************************************************
+ * Plug-in for MI-0360 image sensor connected to the SN9C1xx PC Camera     *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * 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 "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
+
+
+static int mi0360_init(struct sn9c102_device* cam)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C103:
+               err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
+                                              {0x0a, 0x14}, {0x40, 0x01},
+                                              {0x20, 0x17}, {0x07, 0x18},
+                                              {0xa0, 0x19}, {0x02, 0x1c},
+                                              {0x03, 0x1d}, {0x0f, 0x1e},
+                                              {0x0c, 0x1f}, {0x00, 0x20},
+                                              {0x10, 0x21}, {0x20, 0x22},
+                                              {0x30, 0x23}, {0x40, 0x24},
+                                              {0x50, 0x25}, {0x60, 0x26},
+                                              {0x70, 0x27}, {0x80, 0x28},
+                                              {0x90, 0x29}, {0xa0, 0x2a},
+                                              {0xb0, 0x2b}, {0xc0, 0x2c},
+                                              {0xd0, 0x2d}, {0xe0, 0x2e},
+                                              {0xf0, 0x2f}, {0xff, 0x30});
+               break;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
+                                              {0x00, 0x03}, {0x1a, 0x04},
+                                              {0x50, 0x05}, {0x20, 0x06},
+                                              {0x10, 0x07}, {0x03, 0x10},
+                                              {0x08, 0x14}, {0xa2, 0x17},
+                                              {0x47, 0x18}, {0x00, 0x19},
+                                              {0x1d, 0x1a}, {0x10, 0x1b},
+                                              {0x02, 0x1c}, {0x03, 0x1d},
+                                              {0x0f, 0x1e}, {0x0c, 0x1f},
+                                              {0x00, 0x20}, {0x29, 0x21},
+                                              {0x40, 0x22}, {0x54, 0x23},
+                                              {0x66, 0x24}, {0x76, 0x25},
+                                              {0x85, 0x26}, {0x94, 0x27},
+                                              {0xa1, 0x28}, {0xae, 0x29},
+                                              {0xbb, 0x2a}, {0xc7, 0x2b},
+                                              {0xd3, 0x2c}, {0xde, 0x2d},
+                                              {0xea, 0x2e}, {0xf4, 0x2f},
+                                              {0xff, 0x30}, {0x00, 0x3F},
+                                              {0xC7, 0x40}, {0x01, 0x41},
+                                              {0x44, 0x42}, {0x00, 0x43},
+                                              {0x44, 0x44}, {0x00, 0x45},
+                                              {0x44, 0x46}, {0x00, 0x47},
+                                              {0xC7, 0x48}, {0x01, 0x49},
+                                              {0xC7, 0x4A}, {0x01, 0x4B},
+                                              {0xC7, 0x4C}, {0x01, 0x4D},
+                                              {0x44, 0x4E}, {0x00, 0x4F},
+                                              {0x44, 0x50}, {0x00, 0x51},
+                                              {0x44, 0x52}, {0x00, 0x53},
+                                              {0xC7, 0x54}, {0x01, 0x55},
+                                              {0xC7, 0x56}, {0x01, 0x57},
+                                              {0xC7, 0x58}, {0x01, 0x59},
+                                              {0x44, 0x5A}, {0x00, 0x5B},
+                                              {0x44, 0x5C}, {0x00, 0x5D},
+                                              {0x44, 0x5E}, {0x00, 0x5F},
+                                              {0xC7, 0x60}, {0x01, 0x61},
+                                              {0xC7, 0x62}, {0x01, 0x63},
+                                              {0xC7, 0x64}, {0x01, 0x65},
+                                              {0x44, 0x66}, {0x00, 0x67},
+                                              {0x44, 0x68}, {0x00, 0x69},
+                                              {0x44, 0x6A}, {0x00, 0x6B},
+                                              {0xC7, 0x6C}, {0x01, 0x6D},
+                                              {0xC7, 0x6E}, {0x01, 0x6F},
+                                              {0xC7, 0x70}, {0x01, 0x71},
+                                              {0x44, 0x72}, {0x00, 0x73},
+                                              {0x44, 0x74}, {0x00, 0x75},
+                                              {0x44, 0x76}, {0x00, 0x77},
+                                              {0xC7, 0x78}, {0x01, 0x79},
+                                              {0xC7, 0x7A}, {0x01, 0x7B},
+                                              {0xC7, 0x7C}, {0x01, 0x7D},
+                                              {0x44, 0x7E}, {0x00, 0x7F},
+                                              {0x14, 0x84}, {0x00, 0x85},
+                                              {0x27, 0x86}, {0x00, 0x87},
+                                              {0x07, 0x88}, {0x00, 0x89},
+                                              {0xEC, 0x8A}, {0x0f, 0x8B},
+                                              {0xD8, 0x8C}, {0x0f, 0x8D},
+                                              {0x3D, 0x8E}, {0x00, 0x8F},
+                                              {0x3D, 0x90}, {0x00, 0x91},
+                                              {0xCD, 0x92}, {0x0f, 0x93},
+                                              {0xf7, 0x94}, {0x0f, 0x95},
+                                              {0x0C, 0x96}, {0x00, 0x97},
+                                              {0x00, 0x98}, {0x66, 0x99},
+                                              {0x05, 0x9A}, {0x00, 0x9B},
+                                              {0x04, 0x9C}, {0x00, 0x9D},
+                                              {0x08, 0x9E}, {0x00, 0x9F},
+                                              {0x2D, 0xC0}, {0x2D, 0xC1},
+                                              {0x3A, 0xC2}, {0x05, 0xC3},
+                                              {0x04, 0xC4}, {0x3F, 0xC5},
+                                              {0x00, 0xC6}, {0x00, 0xC7},
+                                              {0x50, 0xC8}, {0x3C, 0xC9},
+                                              {0x28, 0xCA}, {0xD8, 0xCB},
+                                              {0x14, 0xCC}, {0xEC, 0xCD},
+                                              {0x32, 0xCE}, {0xDD, 0xCF},
+                                              {0x32, 0xD0}, {0xDD, 0xD1},
+                                              {0x6A, 0xD2}, {0x50, 0xD3},
+                                              {0x00, 0xD4}, {0x00, 0xD5},
+                                              {0x00, 0xD6});
+               break;
+       default:
+               break;
+       }
+
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
+                                        0x00, 0x01, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
+                                        0x00, 0x00, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
+                                        0x01, 0xe1, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
+                                        0x02, 0x81, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
+                                        0x00, 0x17, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
+                                        0x00, 0x11, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
+                                        0x04, 0x9a, 0, 0);
+
+       return err;
+}
+
+
+static int mi0360_get_ctrl(struct sn9c102_device* cam,
+                          struct v4l2_control* ctrl)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       u8 data[2];
+
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
+                                            data) < 0)
+                       return -EIO;
+               ctrl->value = data[0];
+               return 0;
+       case V4L2_CID_GAIN:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
+                                            data) < 0)
+                       return -EIO;
+               ctrl->value = data[1];
+               return 0;
+       case V4L2_CID_RED_BALANCE:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
+                                            data) < 0)
+                       return -EIO;
+               ctrl->value = data[1];
+               return 0;
+       case V4L2_CID_BLUE_BALANCE:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
+                                            data) < 0)
+                       return -EIO;
+               ctrl->value = data[1];
+               return 0;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
+                                            data) < 0)
+                       return -EIO;
+               ctrl->value = data[1];
+               return 0;
+       case V4L2_CID_HFLIP:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
+                                            data) < 0)
+                       return -EIO;
+               ctrl->value = data[1] & 0x20 ? 1 : 0;
+               return 0;
+       case V4L2_CID_VFLIP:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
+                                            data) < 0)
+                       return -EIO;
+               ctrl->value = data[1] & 0x80 ? 1 : 0;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+
+static int mi0360_set_ctrl(struct sn9c102_device* cam,
+                          const struct v4l2_control* ctrl)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x09, ctrl->value, 0x00,
+                                                0, 0);
+               break;
+       case V4L2_CID_GAIN:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x35, 0x03, ctrl->value,
+                                                0, 0);
+               break;
+       case V4L2_CID_RED_BALANCE:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x2c, 0x03, ctrl->value,
+                                                0, 0);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x2d, 0x03, ctrl->value,
+                                                0, 0);
+               break;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x2b, 0x03, ctrl->value,
+                                                0, 0);
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x2e, 0x03, ctrl->value,
+                                                0, 0);
+               break;
+       case V4L2_CID_HFLIP:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x20, ctrl->value ? 0x40:0x00,
+                                                ctrl->value ? 0x20:0x00,
+                                                0, 0);
+               break;
+       case V4L2_CID_VFLIP:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x20, ctrl->value ? 0x80:0x00,
+                                                ctrl->value ? 0x80:0x00,
+                                                0, 0);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int mi0360_set_crop(struct sn9c102_device* cam,
+                           const struct v4l2_rect* rect)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+       u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C103:
+               h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0;
+               break;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
+               break;
+       default:
+               break;
+       }
+
+       err += sn9c102_write_reg(cam, h_start, 0x12);
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+
+       return err;
+}
+
+
+static int mi0360_set_pix_format(struct sn9c102_device* cam,
+                                const struct v4l2_pix_format* pix)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+
+       if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x0a, 0x00, 0x05, 0, 0);
+               err += sn9c102_write_reg(cam, 0x60, 0x19);
+               if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
+                   sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
+                       err += sn9c102_write_reg(cam, 0xa6, 0x17);
+       } else {
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x0a, 0x00, 0x02, 0, 0);
+               err += sn9c102_write_reg(cam, 0x20, 0x19);
+               if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
+                   sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
+                       err += sn9c102_write_reg(cam, 0xa2, 0x17);
+       }
+
+       return err;
+}
+
+
+static const struct sn9c102_sensor mi0360 = {
+       .name = "MI-0360",
+       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
+       .frequency = SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_2WIRES,
+       .i2c_slave_id = 0x5d,
+       .init = &mi0360_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_EXPOSURE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "exposure",
+                       .minimum = 0x00,
+                       .maximum = 0x0f,
+                       .step = 0x01,
+                       .default_value = 0x05,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "global gain",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
+                       .step = 0x01,
+                       .default_value = 0x25,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_HFLIP,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "horizontal mirror",
+                       .minimum = 0,
+                       .maximum = 1,
+                       .step = 1,
+                       .default_value = 0,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_VFLIP,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "vertical mirror",
+                       .minimum = 0,
+                       .maximum = 1,
+                       .step = 1,
+                       .default_value = 0,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_BLUE_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "blue balance",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
+                       .step = 0x01,
+                       .default_value = 0x0f,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_RED_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "red balance",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
+                       .step = 0x01,
+                       .default_value = 0x32,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "green balance",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
+                       .step = 0x01,
+                       .default_value = 0x25,
+                       .flags = 0,
+               },
+       },
+       .get_ctrl = &mi0360_get_ctrl,
+       .set_ctrl = &mi0360_set_ctrl,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+       },
+       .set_crop = &mi0360_set_crop,
+       .pix_format = {
+               .width = 640,
+               .height = 480,
+               .pixelformat = V4L2_PIX_FMT_SBGGR8,
+               .priv = 8,
+       },
+       .set_pix_format = &mi0360_set_pix_format
+};
+
+
+int sn9c102_probe_mi0360(struct sn9c102_device* cam)
+{
+
+       u8 data[2];
+
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C103:
+               if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
+                                            {0x28, 0x17}))
+                       return -EIO;
+               break;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               if (sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
+                                            {0x01, 0x01}, {0x00, 0x01},
+                                            {0x28, 0x17}))
+                       return -EIO;
+               break;
+       default:
+               break;
+       }
+
+       if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00,
+                                    2, data) < 0)
+               return -EIO;
+
+       if (data[0] != 0x82 || data[1] != 0x43)
+               return -ENODEV;
+
+       sn9c102_attach_sensor(cam, &mi0360);
+
+       return 0;
+}
diff --git a/drivers/media/usb/sn9c102/sn9c102_mt9v111.c b/drivers/media/usb/sn9c102/sn9c102_mt9v111.c
new file mode 100644 (file)
index 0000000..95986eb
--- /dev/null
@@ -0,0 +1,260 @@
+/***************************************************************************
+ * Plug-in for MT9V111 image sensor connected to the SN9C1xx PC Camera     *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * 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 "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
+
+
+static int mt9v111_init(struct sn9c102_device *cam)
+{
+       struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
+       int err = 0;
+
+       err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
+                                      {0x00, 0x03}, {0x1a, 0x04},
+                                      {0x1f, 0x05}, {0x20, 0x06},
+                                      {0x1f, 0x07}, {0x81, 0x08},
+                                      {0x5c, 0x09}, {0x00, 0x0a},
+                                      {0x00, 0x0b}, {0x00, 0x0c},
+                                      {0x00, 0x0d}, {0x00, 0x0e},
+                                      {0x00, 0x0f}, {0x03, 0x10},
+                                      {0x00, 0x11}, {0x00, 0x12},
+                                      {0x02, 0x13}, {0x14, 0x14},
+                                      {0x28, 0x15}, {0x1e, 0x16},
+                                      {0xe2, 0x17}, {0x06, 0x18},
+                                      {0x00, 0x19}, {0x00, 0x1a},
+                                      {0x00, 0x1b}, {0x08, 0x20},
+                                      {0x39, 0x21}, {0x51, 0x22},
+                                      {0x63, 0x23}, {0x73, 0x24},
+                                      {0x82, 0x25}, {0x8f, 0x26},
+                                      {0x9b, 0x27}, {0xa7, 0x28},
+                                      {0xb1, 0x29}, {0xbc, 0x2a},
+                                      {0xc6, 0x2b}, {0xcf, 0x2c},
+                                      {0xd8, 0x2d}, {0xe1, 0x2e},
+                                      {0xea, 0x2f}, {0xf2, 0x30},
+                                      {0x13, 0x84}, {0x00, 0x85},
+                                      {0x25, 0x86}, {0x00, 0x87},
+                                      {0x07, 0x88}, {0x00, 0x89},
+                                      {0xee, 0x8a}, {0x0f, 0x8b},
+                                      {0xe5, 0x8c}, {0x0f, 0x8d},
+                                      {0x2e, 0x8e}, {0x00, 0x8f},
+                                      {0x30, 0x90}, {0x00, 0x91},
+                                      {0xd4, 0x92}, {0x0f, 0x93},
+                                      {0xfc, 0x94}, {0x0f, 0x95},
+                                      {0x14, 0x96}, {0x00, 0x97},
+                                      {0x00, 0x98}, {0x60, 0x99},
+                                      {0x07, 0x9a}, {0x40, 0x9b},
+                                      {0x20, 0x9c}, {0x00, 0x9d},
+                                      {0x00, 0x9e}, {0x00, 0x9f},
+                                      {0x2d, 0xc0}, {0x2d, 0xc1},
+                                      {0x3a, 0xc2}, {0x05, 0xc3},
+                                      {0x04, 0xc4}, {0x3f, 0xc5},
+                                      {0x00, 0xc6}, {0x00, 0xc7},
+                                      {0x50, 0xc8}, {0x3c, 0xc9},
+                                      {0x28, 0xca}, {0xd8, 0xcb},
+                                      {0x14, 0xcc}, {0xec, 0xcd},
+                                      {0x32, 0xce}, {0xdd, 0xcf},
+                                      {0x2d, 0xd0}, {0xdd, 0xd1},
+                                      {0x6a, 0xd2}, {0x50, 0xd3},
+                                      {0x60, 0xd4}, {0x00, 0xd5},
+                                      {0x00, 0xd6});
+
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
+                                        0x00, 0x01, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
+                                        0x00, 0x01, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
+                                        0x00, 0x00, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08,
+                                        0x04, 0x80, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
+                                        0x00, 0x04, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08,
+                                        0x00, 0x08, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x02,
+                                        0x00, 0x16, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
+                                        0x01, 0xe7, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
+                                        0x02, 0x87, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
+                                        0x00, 0x40, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
+                                        0x00, 0x09, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x07,
+                                        0x30, 0x02, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0c,
+                                        0x00, 0x00, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x12,
+                                        0x00, 0xb0, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x13,
+                                        0x00, 0x7c, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x1e,
+                                        0x00, 0x00, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20,
+                                        0x00, 0x00, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20,
+                                        0x00, 0x00, 0, 0);
+       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
+                                        0x00, 0x04, 0, 0);
+
+       return err;
+}
+
+static int mt9v111_get_ctrl(struct sn9c102_device *cam,
+                           struct v4l2_control *ctrl)
+{
+       struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
+       u8 data[2];
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
+                                            data) < 0)
+                       return -EIO;
+               ctrl->value = data[1] & 0x80 ? 1 : 0;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+static int mt9v111_set_ctrl(struct sn9c102_device *cam,
+                           const struct v4l2_control *ctrl)
+{
+       struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_VFLIP:
+               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
+                                                0x20,
+                                                ctrl->value ? 0x80 : 0x00,
+                                                ctrl->value ? 0x80 : 0x00, 0,
+                                                0);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+static int mt9v111_set_crop(struct sn9c102_device *cam,
+                           const struct v4l2_rect *rect)
+{
+       struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
+       int err = 0;
+       u8 v_start = (u8) (rect->top - s->cropcap.bounds.top) + 2;
+
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+
+       return err;
+}
+
+static int mt9v111_set_pix_format(struct sn9c102_device *cam,
+                                 const struct v4l2_pix_format *pix)
+{
+       int err = 0;
+
+       if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
+               err += sn9c102_write_reg(cam, 0xb4, 0x17);
+       } else {
+               err += sn9c102_write_reg(cam, 0xe2, 0x17);
+       }
+
+       return err;
+}
+
+
+static const struct sn9c102_sensor mt9v111 = {
+       .name = "MT9V111",
+       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
+       .frequency = SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_2WIRES,
+       .i2c_slave_id = 0x5c,
+       .init = &mt9v111_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_VFLIP,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "vertical mirror",
+                       .minimum = 0,
+                       .maximum = 1,
+                       .step = 1,
+                       .default_value = 0,
+                       .flags = 0,
+               },
+       },
+       .get_ctrl = &mt9v111_get_ctrl,
+       .set_ctrl = &mt9v111_set_ctrl,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+       },
+       .set_crop = &mt9v111_set_crop,
+       .pix_format = {
+               .width = 640,
+               .height = 480,
+               .pixelformat = V4L2_PIX_FMT_SBGGR8,
+               .priv = 8,
+       },
+       .set_pix_format = &mt9v111_set_pix_format
+};
+
+
+int sn9c102_probe_mt9v111(struct sn9c102_device *cam)
+{
+       u8 data[2];
+       int err = 0;
+
+       err += sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
+                                       {0x29, 0x01}, {0x42, 0x17},
+                                       {0x62, 0x17}, {0x08, 0x01});
+       err += sn9c102_i2c_try_raw_write(cam, &mt9v111, 4,
+                                        mt9v111.i2c_slave_id, 0x01, 0x00,
+                                        0x04, 0, 0);
+       if (err || sn9c102_i2c_try_raw_read(cam, &mt9v111,
+                                           mt9v111.i2c_slave_id, 0x36, 2,
+                                           data) < 0)
+               return -EIO;
+
+       if (data[0] != 0x82 || data[1] != 0x3a)
+               return -ENODEV;
+
+       sn9c102_attach_sensor(cam, &mt9v111);
+
+       return 0;
+}
diff --git a/drivers/media/usb/sn9c102/sn9c102_ov7630.c b/drivers/media/usb/sn9c102/sn9c102_ov7630.c
new file mode 100644 (file)
index 0000000..803712c
--- /dev/null
@@ -0,0 +1,626 @@
+/***************************************************************************
+ * Plug-in for OV7630 image sensor connected to the SN9C1xx PC Camera      *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ *                                                                         *
+ * 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 "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
+
+
+static int ov7630_init(struct sn9c102_device* cam)
+{
+       int err = 0;
+
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+               err = sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17},
+                                              {0x0f, 0x18}, {0x50, 0x19});
+
+               err += sn9c102_i2c_write(cam, 0x12, 0x8d);
+               err += sn9c102_i2c_write(cam, 0x12, 0x0d);
+               err += sn9c102_i2c_write(cam, 0x11, 0x00);
+               err += sn9c102_i2c_write(cam, 0x15, 0x35);
+               err += sn9c102_i2c_write(cam, 0x16, 0x03);
+               err += sn9c102_i2c_write(cam, 0x17, 0x1c);
+               err += sn9c102_i2c_write(cam, 0x18, 0xbd);
+               err += sn9c102_i2c_write(cam, 0x19, 0x06);
+               err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
+               err += sn9c102_i2c_write(cam, 0x1b, 0x04);
+               err += sn9c102_i2c_write(cam, 0x20, 0x44);
+               err += sn9c102_i2c_write(cam, 0x23, 0xee);
+               err += sn9c102_i2c_write(cam, 0x26, 0xa0);
+               err += sn9c102_i2c_write(cam, 0x27, 0x9a);
+               err += sn9c102_i2c_write(cam, 0x28, 0x20);
+               err += sn9c102_i2c_write(cam, 0x29, 0x30);
+               err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
+               err += sn9c102_i2c_write(cam, 0x30, 0x24);
+               err += sn9c102_i2c_write(cam, 0x32, 0x86);
+               err += sn9c102_i2c_write(cam, 0x60, 0xa9);
+               err += sn9c102_i2c_write(cam, 0x61, 0x42);
+               err += sn9c102_i2c_write(cam, 0x65, 0x00);
+               err += sn9c102_i2c_write(cam, 0x69, 0x38);
+               err += sn9c102_i2c_write(cam, 0x6f, 0x88);
+               err += sn9c102_i2c_write(cam, 0x70, 0x0b);
+               err += sn9c102_i2c_write(cam, 0x71, 0x00);
+               err += sn9c102_i2c_write(cam, 0x74, 0x21);
+               err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
+               break;
+       case BRIDGE_SN9C103:
+               err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
+                                              {0x1a, 0x04}, {0x20, 0x05},
+                                              {0x20, 0x06}, {0x20, 0x07},
+                                              {0x03, 0x10}, {0x0a, 0x14},
+                                              {0x60, 0x17}, {0x0f, 0x18},
+                                              {0x50, 0x19}, {0x1d, 0x1a},
+                                              {0x10, 0x1b}, {0x02, 0x1c},
+                                              {0x03, 0x1d}, {0x0f, 0x1e},
+                                              {0x0c, 0x1f}, {0x00, 0x20},
+                                              {0x10, 0x21}, {0x20, 0x22},
+                                              {0x30, 0x23}, {0x40, 0x24},
+                                              {0x50, 0x25}, {0x60, 0x26},
+                                              {0x70, 0x27}, {0x80, 0x28},
+                                              {0x90, 0x29}, {0xa0, 0x2a},
+                                              {0xb0, 0x2b}, {0xc0, 0x2c},
+                                              {0xd0, 0x2d}, {0xe0, 0x2e},
+                                              {0xf0, 0x2f}, {0xff, 0x30});
+
+               err += sn9c102_i2c_write(cam, 0x12, 0x8d);
+               err += sn9c102_i2c_write(cam, 0x12, 0x0d);
+               err += sn9c102_i2c_write(cam, 0x15, 0x34);
+               err += sn9c102_i2c_write(cam, 0x11, 0x01);
+               err += sn9c102_i2c_write(cam, 0x1b, 0x04);
+               err += sn9c102_i2c_write(cam, 0x20, 0x44);
+               err += sn9c102_i2c_write(cam, 0x23, 0xee);
+               err += sn9c102_i2c_write(cam, 0x26, 0xa0);
+               err += sn9c102_i2c_write(cam, 0x27, 0x9a);
+               err += sn9c102_i2c_write(cam, 0x28, 0x20);
+               err += sn9c102_i2c_write(cam, 0x29, 0x30);
+               err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
+               err += sn9c102_i2c_write(cam, 0x30, 0x24);
+               err += sn9c102_i2c_write(cam, 0x32, 0x86);
+               err += sn9c102_i2c_write(cam, 0x60, 0xa9);
+               err += sn9c102_i2c_write(cam, 0x61, 0x42);
+               err += sn9c102_i2c_write(cam, 0x65, 0x00);
+               err += sn9c102_i2c_write(cam, 0x69, 0x38);
+               err += sn9c102_i2c_write(cam, 0x6f, 0x88);
+               err += sn9c102_i2c_write(cam, 0x70, 0x0b);
+               err += sn9c102_i2c_write(cam, 0x71, 0x00);
+               err += sn9c102_i2c_write(cam, 0x74, 0x21);
+               err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
+               break;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+       err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
+                                      {0x1a, 0x04}, {0x03, 0x10},
+                                      {0x0a, 0x14}, {0xe2, 0x17},
+                                      {0x0b, 0x18}, {0x00, 0x19},
+                                      {0x1d, 0x1a}, {0x10, 0x1b},
+                                      {0x02, 0x1c}, {0x03, 0x1d},
+                                      {0x0f, 0x1e}, {0x0c, 0x1f},
+                                      {0x00, 0x20}, {0x24, 0x21},
+                                      {0x3b, 0x22}, {0x47, 0x23},
+                                      {0x60, 0x24}, {0x71, 0x25},
+                                      {0x80, 0x26}, {0x8f, 0x27},
+                                      {0x9d, 0x28}, {0xaa, 0x29},
+                                      {0xb8, 0x2a}, {0xc4, 0x2b},
+                                      {0xd1, 0x2c}, {0xdd, 0x2d},
+                                      {0xe8, 0x2e}, {0xf4, 0x2f},
+                                      {0xff, 0x30}, {0x00, 0x3f},
+                                      {0xc7, 0x40}, {0x01, 0x41},
+                                      {0x44, 0x42}, {0x00, 0x43},
+                                      {0x44, 0x44}, {0x00, 0x45},
+                                      {0x44, 0x46}, {0x00, 0x47},
+                                      {0xc7, 0x48}, {0x01, 0x49},
+                                      {0xc7, 0x4a}, {0x01, 0x4b},
+                                      {0xc7, 0x4c}, {0x01, 0x4d},
+                                      {0x44, 0x4e}, {0x00, 0x4f},
+                                      {0x44, 0x50}, {0x00, 0x51},
+                                      {0x44, 0x52}, {0x00, 0x53},
+                                      {0xc7, 0x54}, {0x01, 0x55},
+                                      {0xc7, 0x56}, {0x01, 0x57},
+                                      {0xc7, 0x58}, {0x01, 0x59},
+                                      {0x44, 0x5a}, {0x00, 0x5b},
+                                      {0x44, 0x5c}, {0x00, 0x5d},
+                                      {0x44, 0x5e}, {0x00, 0x5f},
+                                      {0xc7, 0x60}, {0x01, 0x61},
+                                      {0xc7, 0x62}, {0x01, 0x63},
+                                      {0xc7, 0x64}, {0x01, 0x65},
+                                      {0x44, 0x66}, {0x00, 0x67},
+                                      {0x44, 0x68}, {0x00, 0x69},
+                                      {0x44, 0x6a}, {0x00, 0x6b},
+                                      {0xc7, 0x6c}, {0x01, 0x6d},
+                                      {0xc7, 0x6e}, {0x01, 0x6f},
+                                      {0xc7, 0x70}, {0x01, 0x71},
+                                      {0x44, 0x72}, {0x00, 0x73},
+                                      {0x44, 0x74}, {0x00, 0x75},
+                                      {0x44, 0x76}, {0x00, 0x77},
+                                      {0xc7, 0x78}, {0x01, 0x79},
+                                      {0xc7, 0x7a}, {0x01, 0x7b},
+                                      {0xc7, 0x7c}, {0x01, 0x7d},
+                                      {0x44, 0x7e}, {0x00, 0x7f},
+                                      {0x17, 0x84}, {0x00, 0x85},
+                                      {0x2e, 0x86}, {0x00, 0x87},
+                                      {0x09, 0x88}, {0x00, 0x89},
+                                      {0xe8, 0x8a}, {0x0f, 0x8b},
+                                      {0xda, 0x8c}, {0x0f, 0x8d},
+                                      {0x40, 0x8e}, {0x00, 0x8f},
+                                      {0x37, 0x90}, {0x00, 0x91},
+                                      {0xcf, 0x92}, {0x0f, 0x93},
+                                      {0xfa, 0x94}, {0x0f, 0x95},
+                                      {0x00, 0x96}, {0x00, 0x97},
+                                      {0x00, 0x98}, {0x66, 0x99},
+                                      {0x00, 0x9a}, {0x40, 0x9b},
+                                      {0x20, 0x9c}, {0x00, 0x9d},
+                                      {0x00, 0x9e}, {0x00, 0x9f},
+                                      {0x2d, 0xc0}, {0x2d, 0xc1},
+                                      {0x3a, 0xc2}, {0x00, 0xc3},
+                                      {0x04, 0xc4}, {0x3f, 0xc5},
+                                      {0x00, 0xc6}, {0x00, 0xc7},
+                                      {0x50, 0xc8}, {0x3c, 0xc9},
+                                      {0x28, 0xca}, {0xd8, 0xcb},
+                                      {0x14, 0xcc}, {0xec, 0xcd},
+                                      {0x32, 0xce}, {0xdd, 0xcf},
+                                      {0x32, 0xd0}, {0xdd, 0xd1},
+                                      {0x6a, 0xd2}, {0x50, 0xd3},
+                                      {0x60, 0xd4}, {0x00, 0xd5},
+                                      {0x00, 0xd6});
+
+               err += sn9c102_i2c_write(cam, 0x12, 0x80);
+               err += sn9c102_i2c_write(cam, 0x12, 0x48);
+               err += sn9c102_i2c_write(cam, 0x01, 0x80);
+               err += sn9c102_i2c_write(cam, 0x02, 0x80);
+               err += sn9c102_i2c_write(cam, 0x03, 0x80);
+               err += sn9c102_i2c_write(cam, 0x04, 0x10);
+               err += sn9c102_i2c_write(cam, 0x05, 0x20);
+               err += sn9c102_i2c_write(cam, 0x06, 0x80);
+               err += sn9c102_i2c_write(cam, 0x11, 0x00);
+               err += sn9c102_i2c_write(cam, 0x0c, 0x20);
+               err += sn9c102_i2c_write(cam, 0x0d, 0x20);
+               err += sn9c102_i2c_write(cam, 0x15, 0x80);
+               err += sn9c102_i2c_write(cam, 0x16, 0x03);
+               err += sn9c102_i2c_write(cam, 0x17, 0x1b);
+               err += sn9c102_i2c_write(cam, 0x18, 0xbd);
+               err += sn9c102_i2c_write(cam, 0x19, 0x05);
+               err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
+               err += sn9c102_i2c_write(cam, 0x1b, 0x04);
+               err += sn9c102_i2c_write(cam, 0x21, 0x1b);
+               err += sn9c102_i2c_write(cam, 0x22, 0x00);
+               err += sn9c102_i2c_write(cam, 0x23, 0xde);
+               err += sn9c102_i2c_write(cam, 0x24, 0x10);
+               err += sn9c102_i2c_write(cam, 0x25, 0x8a);
+               err += sn9c102_i2c_write(cam, 0x26, 0xa0);
+               err += sn9c102_i2c_write(cam, 0x27, 0xca);
+               err += sn9c102_i2c_write(cam, 0x28, 0xa2);
+               err += sn9c102_i2c_write(cam, 0x29, 0x74);
+               err += sn9c102_i2c_write(cam, 0x2a, 0x88);
+               err += sn9c102_i2c_write(cam, 0x2b, 0x34);
+               err += sn9c102_i2c_write(cam, 0x2c, 0x88);
+               err += sn9c102_i2c_write(cam, 0x2e, 0x00);
+               err += sn9c102_i2c_write(cam, 0x2f, 0x00);
+               err += sn9c102_i2c_write(cam, 0x30, 0x00);
+               err += sn9c102_i2c_write(cam, 0x32, 0xc2);
+               err += sn9c102_i2c_write(cam, 0x33, 0x08);
+               err += sn9c102_i2c_write(cam, 0x4c, 0x40);
+               err += sn9c102_i2c_write(cam, 0x4d, 0xf3);
+               err += sn9c102_i2c_write(cam, 0x60, 0x05);
+               err += sn9c102_i2c_write(cam, 0x61, 0x40);
+               err += sn9c102_i2c_write(cam, 0x62, 0x12);
+               err += sn9c102_i2c_write(cam, 0x63, 0x57);
+               err += sn9c102_i2c_write(cam, 0x64, 0x73);
+               err += sn9c102_i2c_write(cam, 0x65, 0x00);
+               err += sn9c102_i2c_write(cam, 0x66, 0x55);
+               err += sn9c102_i2c_write(cam, 0x67, 0x01);
+               err += sn9c102_i2c_write(cam, 0x68, 0xac);
+               err += sn9c102_i2c_write(cam, 0x69, 0x38);
+               err += sn9c102_i2c_write(cam, 0x6f, 0x1f);
+               err += sn9c102_i2c_write(cam, 0x70, 0x01);
+               err += sn9c102_i2c_write(cam, 0x71, 0x00);
+               err += sn9c102_i2c_write(cam, 0x72, 0x10);
+               err += sn9c102_i2c_write(cam, 0x73, 0x50);
+               err += sn9c102_i2c_write(cam, 0x74, 0x20);
+               err += sn9c102_i2c_write(cam, 0x76, 0x01);
+               err += sn9c102_i2c_write(cam, 0x77, 0xf3);
+               err += sn9c102_i2c_write(cam, 0x78, 0x90);
+               err += sn9c102_i2c_write(cam, 0x79, 0x98);
+               err += sn9c102_i2c_write(cam, 0x7a, 0x98);
+               err += sn9c102_i2c_write(cam, 0x7b, 0x00);
+               err += sn9c102_i2c_write(cam, 0x7c, 0x38);
+               err += sn9c102_i2c_write(cam, 0x7d, 0xff);
+               break;
+       default:
+               break;
+       }
+
+       return err;
+}
+
+
+static int ov7630_get_ctrl(struct sn9c102_device* cam,
+                          struct v4l2_control* ctrl)
+{
+       enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
+                       return -EIO;
+               break;
+       case V4L2_CID_RED_BALANCE:
+               if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
+                       ctrl->value = sn9c102_pread_reg(cam, 0x05);
+               else
+                       ctrl->value = sn9c102_pread_reg(cam, 0x07);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               ctrl->value = sn9c102_pread_reg(cam, 0x06);
+               break;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
+                       ctrl->value = sn9c102_pread_reg(cam, 0x07);
+               else
+                       ctrl->value = sn9c102_pread_reg(cam, 0x05);
+               break;
+               break;
+       case V4L2_CID_GAIN:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x3f;
+               break;
+       case V4L2_CID_DO_WHITE_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x3f;
+               break;
+       case V4L2_CID_WHITENESS:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0d)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x3f;
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x01;
+               break;
+       case V4L2_CID_VFLIP:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x75)) < 0)
+                       return -EIO;
+               ctrl->value = (ctrl->value & 0x80) ? 1 : 0;
+               break;
+       case SN9C102_V4L2_CID_GAMMA:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x14)) < 0)
+                       return -EIO;
+               ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
+               break;
+       case SN9C102_V4L2_CID_BAND_FILTER:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x2d)) < 0)
+                       return -EIO;
+               ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int ov7630_set_ctrl(struct sn9c102_device* cam,
+                          const struct v4l2_control* ctrl)
+{
+       enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
+               break;
+       case V4L2_CID_RED_BALANCE:
+               if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
+                       err += sn9c102_write_reg(cam, ctrl->value, 0x05);
+               else
+                       err += sn9c102_write_reg(cam, ctrl->value, 0x07);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               err += sn9c102_write_reg(cam, ctrl->value, 0x06);
+               break;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
+                       err += sn9c102_write_reg(cam, ctrl->value, 0x07);
+               else
+                       err += sn9c102_write_reg(cam, ctrl->value, 0x05);
+               break;
+       case V4L2_CID_GAIN:
+               err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
+               break;
+       case V4L2_CID_DO_WHITE_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
+               break;
+       case V4L2_CID_WHITENESS:
+               err += sn9c102_i2c_write(cam, 0x0d, ctrl->value);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               err += sn9c102_i2c_write(cam, 0x13, ctrl->value |
+                                                   (ctrl->value << 1));
+               break;
+       case V4L2_CID_VFLIP:
+               err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7));
+               break;
+       case SN9C102_V4L2_CID_GAMMA:
+               err += sn9c102_i2c_write(cam, 0x14, ctrl->value << 2);
+               break;
+       case SN9C102_V4L2_CID_BAND_FILTER:
+               err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int ov7630_set_crop(struct sn9c102_device* cam,
+                          const struct v4l2_rect* rect)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+       u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+       case BRIDGE_SN9C103:
+               h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
+               break;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
+               break;
+       default:
+               break;
+       }
+
+       err += sn9c102_write_reg(cam, h_start, 0x12);
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+
+       return err;
+}
+
+
+static int ov7630_set_pix_format(struct sn9c102_device* cam,
+                                const struct v4l2_pix_format* pix)
+{
+       int err = 0;
+
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+       case BRIDGE_SN9C103:
+               if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8)
+                       err += sn9c102_write_reg(cam, 0x50, 0x19);
+               else
+                       err += sn9c102_write_reg(cam, 0x20, 0x19);
+               break;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
+                       err += sn9c102_write_reg(cam, 0xe5, 0x17);
+                       err += sn9c102_i2c_write(cam, 0x11, 0x04);
+               } else {
+                       err += sn9c102_write_reg(cam, 0xe2, 0x17);
+                       err += sn9c102_i2c_write(cam, 0x11, 0x02);
+               }
+               break;
+       default:
+               break;
+       }
+
+       return err;
+}
+
+
+static const struct sn9c102_sensor ov7630 = {
+       .name = "OV7630",
+       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103 |
+                           BRIDGE_SN9C105 | BRIDGE_SN9C120,
+       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
+       .frequency = SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_2WIRES,
+       .i2c_slave_id = 0x21,
+       .init = &ov7630_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "global gain",
+                       .minimum = 0x00,
+                       .maximum = 0x3f,
+                       .step = 0x01,
+                       .default_value = 0x14,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_EXPOSURE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "exposure",
+                       .minimum = 0x00,
+                       .maximum = 0xff,
+                       .step = 0x01,
+                       .default_value = 0x60,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_WHITENESS,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "white balance background: red",
+                       .minimum = 0x00,
+                       .maximum = 0x3f,
+                       .step = 0x01,
+                       .default_value = 0x20,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_DO_WHITE_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "white balance background: blue",
+                       .minimum = 0x00,
+                       .maximum = 0x3f,
+                       .step = 0x01,
+                       .default_value = 0x20,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_RED_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "red balance",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
+                       .step = 0x01,
+                       .default_value = 0x20,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_BLUE_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "blue balance",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
+                       .step = 0x01,
+                       .default_value = 0x20,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_AUTOGAIN,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "auto adjust",
+                       .minimum = 0x00,
+                       .maximum = 0x01,
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_VFLIP,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "vertical flip",
+                       .minimum = 0x00,
+                       .maximum = 0x01,
+                       .step = 0x01,
+                       .default_value = 0x01,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "green balance",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
+                       .step = 0x01,
+                       .default_value = 0x20,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_BAND_FILTER,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "band filter",
+                       .minimum = 0x00,
+                       .maximum = 0x01,
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_GAMMA,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "rgb gamma",
+                       .minimum = 0x00,
+                       .maximum = 0x01,
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+       },
+       .get_ctrl = &ov7630_get_ctrl,
+       .set_ctrl = &ov7630_set_ctrl,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+       },
+       .set_crop = &ov7630_set_crop,
+       .pix_format = {
+               .width = 640,
+               .height = 480,
+               .pixelformat = V4L2_PIX_FMT_SN9C10X,
+               .priv = 8,
+       },
+       .set_pix_format = &ov7630_set_pix_format
+};
+
+
+int sn9c102_probe_ov7630(struct sn9c102_device* cam)
+{
+       int pid, ver, err = 0;
+
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+               err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
+                                              {0x28, 0x17});
+               break;
+       case BRIDGE_SN9C103: /* do _not_ change anything! */
+               err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x42, 0x01},
+                                              {0x28, 0x17}, {0x44, 0x02});
+               pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
+               if (err || pid < 0) /* try a different initialization */
+                       err += sn9c102_write_const_regs(cam, {0x01, 0x01},
+                                                       {0x00, 0x01});
+               break;
+       case BRIDGE_SN9C105:
+       case BRIDGE_SN9C120:
+               err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
+                                              {0x29, 0x01}, {0x74, 0x02},
+                                              {0x0e, 0x01}, {0x44, 0x01});
+               break;
+       default:
+               break;
+       }
+
+       pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
+       ver = sn9c102_i2c_try_read(cam, &ov7630, 0x0b);
+       if (err || pid < 0 || ver < 0)
+               return -EIO;
+       if (pid != 0x76 || ver != 0x31)
+               return -ENODEV;
+       sn9c102_attach_sensor(cam, &ov7630);
+
+       return 0;
+}
diff --git a/drivers/media/usb/sn9c102/sn9c102_ov7660.c b/drivers/media/usb/sn9c102/sn9c102_ov7660.c
new file mode 100644 (file)
index 0000000..7977795
--- /dev/null
@@ -0,0 +1,538 @@
+/***************************************************************************
+ * Plug-in for OV7660 image sensor connected to the SN9C1xx PC Camera      *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * 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 "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
+
+
+static int ov7660_init(struct sn9c102_device* cam)
+{
+       int err = 0;
+
+       err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
+                                      {0x1a, 0x04}, {0x03, 0x10},
+                                      {0x08, 0x14}, {0x20, 0x17},
+                                      {0x8b, 0x18}, {0x00, 0x19},
+                                      {0x1d, 0x1a}, {0x10, 0x1b},
+                                      {0x02, 0x1c}, {0x03, 0x1d},
+                                      {0x0f, 0x1e}, {0x0c, 0x1f},
+                                      {0x00, 0x20}, {0x29, 0x21},
+                                      {0x40, 0x22}, {0x54, 0x23},
+                                      {0x66, 0x24}, {0x76, 0x25},
+                                      {0x85, 0x26}, {0x94, 0x27},
+                                      {0xa1, 0x28}, {0xae, 0x29},
+                                      {0xbb, 0x2a}, {0xc7, 0x2b},
+                                      {0xd3, 0x2c}, {0xde, 0x2d},
+                                      {0xea, 0x2e}, {0xf4, 0x2f},
+                                      {0xff, 0x30}, {0x00, 0x3f},
+                                      {0xc7, 0x40}, {0x01, 0x41},
+                                      {0x44, 0x42}, {0x00, 0x43},
+                                      {0x44, 0x44}, {0x00, 0x45},
+                                      {0x44, 0x46}, {0x00, 0x47},
+                                      {0xc7, 0x48}, {0x01, 0x49},
+                                      {0xc7, 0x4a}, {0x01, 0x4b},
+                                      {0xc7, 0x4c}, {0x01, 0x4d},
+                                      {0x44, 0x4e}, {0x00, 0x4f},
+                                      {0x44, 0x50}, {0x00, 0x51},
+                                      {0x44, 0x52}, {0x00, 0x53},
+                                      {0xc7, 0x54}, {0x01, 0x55},
+                                      {0xc7, 0x56}, {0x01, 0x57},
+                                      {0xc7, 0x58}, {0x01, 0x59},
+                                      {0x44, 0x5a}, {0x00, 0x5b},
+                                      {0x44, 0x5c}, {0x00, 0x5d},
+                                      {0x44, 0x5e}, {0x00, 0x5f},
+                                      {0xc7, 0x60}, {0x01, 0x61},
+                                      {0xc7, 0x62}, {0x01, 0x63},
+                                      {0xc7, 0x64}, {0x01, 0x65},
+                                      {0x44, 0x66}, {0x00, 0x67},
+                                      {0x44, 0x68}, {0x00, 0x69},
+                                      {0x44, 0x6a}, {0x00, 0x6b},
+                                      {0xc7, 0x6c}, {0x01, 0x6d},
+                                      {0xc7, 0x6e}, {0x01, 0x6f},
+                                      {0xc7, 0x70}, {0x01, 0x71},
+                                      {0x44, 0x72}, {0x00, 0x73},
+                                      {0x44, 0x74}, {0x00, 0x75},
+                                      {0x44, 0x76}, {0x00, 0x77},
+                                      {0xc7, 0x78}, {0x01, 0x79},
+                                      {0xc7, 0x7a}, {0x01, 0x7b},
+                                      {0xc7, 0x7c}, {0x01, 0x7d},
+                                      {0x44, 0x7e}, {0x00, 0x7f},
+                                      {0x14, 0x84}, {0x00, 0x85},
+                                      {0x27, 0x86}, {0x00, 0x87},
+                                      {0x07, 0x88}, {0x00, 0x89},
+                                      {0xec, 0x8a}, {0x0f, 0x8b},
+                                      {0xd8, 0x8c}, {0x0f, 0x8d},
+                                      {0x3d, 0x8e}, {0x00, 0x8f},
+                                      {0x3d, 0x90}, {0x00, 0x91},
+                                      {0xcd, 0x92}, {0x0f, 0x93},
+                                      {0xf7, 0x94}, {0x0f, 0x95},
+                                      {0x0c, 0x96}, {0x00, 0x97},
+                                      {0x00, 0x98}, {0x66, 0x99},
+                                      {0x05, 0x9a}, {0x00, 0x9b},
+                                      {0x04, 0x9c}, {0x00, 0x9d},
+                                      {0x08, 0x9e}, {0x00, 0x9f},
+                                      {0x2d, 0xc0}, {0x2d, 0xc1},
+                                      {0x3a, 0xc2}, {0x05, 0xc3},
+                                      {0x04, 0xc4}, {0x3f, 0xc5},
+                                      {0x00, 0xc6}, {0x00, 0xc7},
+                                      {0x50, 0xc8}, {0x3C, 0xc9},
+                                      {0x28, 0xca}, {0xd8, 0xcb},
+                                      {0x14, 0xcc}, {0xec, 0xcd},
+                                      {0x32, 0xce}, {0xdd, 0xcf},
+                                      {0x32, 0xd0}, {0xdd, 0xd1},
+                                      {0x6a, 0xd2}, {0x50, 0xd3},
+                                      {0x00, 0xd4}, {0x00, 0xd5},
+                                      {0x00, 0xd6});
+
+       err += sn9c102_i2c_write(cam, 0x12, 0x80);
+       err += sn9c102_i2c_write(cam, 0x11, 0x09);
+       err += sn9c102_i2c_write(cam, 0x00, 0x0A);
+       err += sn9c102_i2c_write(cam, 0x01, 0x80);
+       err += sn9c102_i2c_write(cam, 0x02, 0x80);
+       err += sn9c102_i2c_write(cam, 0x03, 0x00);
+       err += sn9c102_i2c_write(cam, 0x04, 0x00);
+       err += sn9c102_i2c_write(cam, 0x05, 0x08);
+       err += sn9c102_i2c_write(cam, 0x06, 0x0B);
+       err += sn9c102_i2c_write(cam, 0x07, 0x00);
+       err += sn9c102_i2c_write(cam, 0x08, 0x1C);
+       err += sn9c102_i2c_write(cam, 0x09, 0x01);
+       err += sn9c102_i2c_write(cam, 0x0A, 0x76);
+       err += sn9c102_i2c_write(cam, 0x0B, 0x60);
+       err += sn9c102_i2c_write(cam, 0x0C, 0x00);
+       err += sn9c102_i2c_write(cam, 0x0D, 0x08);
+       err += sn9c102_i2c_write(cam, 0x0E, 0x04);
+       err += sn9c102_i2c_write(cam, 0x0F, 0x6F);
+       err += sn9c102_i2c_write(cam, 0x10, 0x20);
+       err += sn9c102_i2c_write(cam, 0x11, 0x03);
+       err += sn9c102_i2c_write(cam, 0x12, 0x05);
+       err += sn9c102_i2c_write(cam, 0x13, 0xC7);
+       err += sn9c102_i2c_write(cam, 0x14, 0x2C);
+       err += sn9c102_i2c_write(cam, 0x15, 0x00);
+       err += sn9c102_i2c_write(cam, 0x16, 0x02);
+       err += sn9c102_i2c_write(cam, 0x17, 0x10);
+       err += sn9c102_i2c_write(cam, 0x18, 0x60);
+       err += sn9c102_i2c_write(cam, 0x19, 0x02);
+       err += sn9c102_i2c_write(cam, 0x1A, 0x7B);
+       err += sn9c102_i2c_write(cam, 0x1B, 0x02);
+       err += sn9c102_i2c_write(cam, 0x1C, 0x7F);
+       err += sn9c102_i2c_write(cam, 0x1D, 0xA2);
+       err += sn9c102_i2c_write(cam, 0x1E, 0x01);
+       err += sn9c102_i2c_write(cam, 0x1F, 0x0E);
+       err += sn9c102_i2c_write(cam, 0x20, 0x05);
+       err += sn9c102_i2c_write(cam, 0x21, 0x05);
+       err += sn9c102_i2c_write(cam, 0x22, 0x05);
+       err += sn9c102_i2c_write(cam, 0x23, 0x05);
+       err += sn9c102_i2c_write(cam, 0x24, 0x68);
+       err += sn9c102_i2c_write(cam, 0x25, 0x58);
+       err += sn9c102_i2c_write(cam, 0x26, 0xD4);
+       err += sn9c102_i2c_write(cam, 0x27, 0x80);
+       err += sn9c102_i2c_write(cam, 0x28, 0x80);
+       err += sn9c102_i2c_write(cam, 0x29, 0x30);
+       err += sn9c102_i2c_write(cam, 0x2A, 0x00);
+       err += sn9c102_i2c_write(cam, 0x2B, 0x00);
+       err += sn9c102_i2c_write(cam, 0x2C, 0x80);
+       err += sn9c102_i2c_write(cam, 0x2D, 0x00);
+       err += sn9c102_i2c_write(cam, 0x2E, 0x00);
+       err += sn9c102_i2c_write(cam, 0x2F, 0x0E);
+       err += sn9c102_i2c_write(cam, 0x30, 0x08);
+       err += sn9c102_i2c_write(cam, 0x31, 0x30);
+       err += sn9c102_i2c_write(cam, 0x32, 0xB4);
+       err += sn9c102_i2c_write(cam, 0x33, 0x00);
+       err += sn9c102_i2c_write(cam, 0x34, 0x07);
+       err += sn9c102_i2c_write(cam, 0x35, 0x84);
+       err += sn9c102_i2c_write(cam, 0x36, 0x00);
+       err += sn9c102_i2c_write(cam, 0x37, 0x0C);
+       err += sn9c102_i2c_write(cam, 0x38, 0x02);
+       err += sn9c102_i2c_write(cam, 0x39, 0x43);
+       err += sn9c102_i2c_write(cam, 0x3A, 0x00);
+       err += sn9c102_i2c_write(cam, 0x3B, 0x0A);
+       err += sn9c102_i2c_write(cam, 0x3C, 0x6C);
+       err += sn9c102_i2c_write(cam, 0x3D, 0x99);
+       err += sn9c102_i2c_write(cam, 0x3E, 0x0E);
+       err += sn9c102_i2c_write(cam, 0x3F, 0x41);
+       err += sn9c102_i2c_write(cam, 0x40, 0xC1);
+       err += sn9c102_i2c_write(cam, 0x41, 0x22);
+       err += sn9c102_i2c_write(cam, 0x42, 0x08);
+       err += sn9c102_i2c_write(cam, 0x43, 0xF0);
+       err += sn9c102_i2c_write(cam, 0x44, 0x10);
+       err += sn9c102_i2c_write(cam, 0x45, 0x78);
+       err += sn9c102_i2c_write(cam, 0x46, 0xA8);
+       err += sn9c102_i2c_write(cam, 0x47, 0x60);
+       err += sn9c102_i2c_write(cam, 0x48, 0x80);
+       err += sn9c102_i2c_write(cam, 0x49, 0x00);
+       err += sn9c102_i2c_write(cam, 0x4A, 0x00);
+       err += sn9c102_i2c_write(cam, 0x4B, 0x00);
+       err += sn9c102_i2c_write(cam, 0x4C, 0x00);
+       err += sn9c102_i2c_write(cam, 0x4D, 0x00);
+       err += sn9c102_i2c_write(cam, 0x4E, 0x00);
+       err += sn9c102_i2c_write(cam, 0x4F, 0x46);
+       err += sn9c102_i2c_write(cam, 0x50, 0x36);
+       err += sn9c102_i2c_write(cam, 0x51, 0x0F);
+       err += sn9c102_i2c_write(cam, 0x52, 0x17);
+       err += sn9c102_i2c_write(cam, 0x53, 0x7F);
+       err += sn9c102_i2c_write(cam, 0x54, 0x96);
+       err += sn9c102_i2c_write(cam, 0x55, 0x40);
+       err += sn9c102_i2c_write(cam, 0x56, 0x40);
+       err += sn9c102_i2c_write(cam, 0x57, 0x40);
+       err += sn9c102_i2c_write(cam, 0x58, 0x0F);
+       err += sn9c102_i2c_write(cam, 0x59, 0xBA);
+       err += sn9c102_i2c_write(cam, 0x5A, 0x9A);
+       err += sn9c102_i2c_write(cam, 0x5B, 0x22);
+       err += sn9c102_i2c_write(cam, 0x5C, 0xB9);
+       err += sn9c102_i2c_write(cam, 0x5D, 0x9B);
+       err += sn9c102_i2c_write(cam, 0x5E, 0x10);
+       err += sn9c102_i2c_write(cam, 0x5F, 0xF0);
+       err += sn9c102_i2c_write(cam, 0x60, 0x05);
+       err += sn9c102_i2c_write(cam, 0x61, 0x60);
+       err += sn9c102_i2c_write(cam, 0x62, 0x00);
+       err += sn9c102_i2c_write(cam, 0x63, 0x00);
+       err += sn9c102_i2c_write(cam, 0x64, 0x50);
+       err += sn9c102_i2c_write(cam, 0x65, 0x30);
+       err += sn9c102_i2c_write(cam, 0x66, 0x00);
+       err += sn9c102_i2c_write(cam, 0x67, 0x80);
+       err += sn9c102_i2c_write(cam, 0x68, 0x7A);
+       err += sn9c102_i2c_write(cam, 0x69, 0x90);
+       err += sn9c102_i2c_write(cam, 0x6A, 0x80);
+       err += sn9c102_i2c_write(cam, 0x6B, 0x0A);
+       err += sn9c102_i2c_write(cam, 0x6C, 0x30);
+       err += sn9c102_i2c_write(cam, 0x6D, 0x48);
+       err += sn9c102_i2c_write(cam, 0x6E, 0x80);
+       err += sn9c102_i2c_write(cam, 0x6F, 0x74);
+       err += sn9c102_i2c_write(cam, 0x70, 0x64);
+       err += sn9c102_i2c_write(cam, 0x71, 0x60);
+       err += sn9c102_i2c_write(cam, 0x72, 0x5C);
+       err += sn9c102_i2c_write(cam, 0x73, 0x58);
+       err += sn9c102_i2c_write(cam, 0x74, 0x54);
+       err += sn9c102_i2c_write(cam, 0x75, 0x4C);
+       err += sn9c102_i2c_write(cam, 0x76, 0x40);
+       err += sn9c102_i2c_write(cam, 0x77, 0x38);
+       err += sn9c102_i2c_write(cam, 0x78, 0x34);
+       err += sn9c102_i2c_write(cam, 0x79, 0x30);
+       err += sn9c102_i2c_write(cam, 0x7A, 0x2F);
+       err += sn9c102_i2c_write(cam, 0x7B, 0x2B);
+       err += sn9c102_i2c_write(cam, 0x7C, 0x03);
+       err += sn9c102_i2c_write(cam, 0x7D, 0x07);
+       err += sn9c102_i2c_write(cam, 0x7E, 0x17);
+       err += sn9c102_i2c_write(cam, 0x7F, 0x34);
+       err += sn9c102_i2c_write(cam, 0x80, 0x41);
+       err += sn9c102_i2c_write(cam, 0x81, 0x4D);
+       err += sn9c102_i2c_write(cam, 0x82, 0x58);
+       err += sn9c102_i2c_write(cam, 0x83, 0x63);
+       err += sn9c102_i2c_write(cam, 0x84, 0x6E);
+       err += sn9c102_i2c_write(cam, 0x85, 0x77);
+       err += sn9c102_i2c_write(cam, 0x86, 0x87);
+       err += sn9c102_i2c_write(cam, 0x87, 0x95);
+       err += sn9c102_i2c_write(cam, 0x88, 0xAF);
+       err += sn9c102_i2c_write(cam, 0x89, 0xC7);
+       err += sn9c102_i2c_write(cam, 0x8A, 0xDF);
+       err += sn9c102_i2c_write(cam, 0x8B, 0x99);
+       err += sn9c102_i2c_write(cam, 0x8C, 0x99);
+       err += sn9c102_i2c_write(cam, 0x8D, 0xCF);
+       err += sn9c102_i2c_write(cam, 0x8E, 0x20);
+       err += sn9c102_i2c_write(cam, 0x8F, 0x26);
+       err += sn9c102_i2c_write(cam, 0x90, 0x10);
+       err += sn9c102_i2c_write(cam, 0x91, 0x0C);
+       err += sn9c102_i2c_write(cam, 0x92, 0x25);
+       err += sn9c102_i2c_write(cam, 0x93, 0x00);
+       err += sn9c102_i2c_write(cam, 0x94, 0x50);
+       err += sn9c102_i2c_write(cam, 0x95, 0x50);
+       err += sn9c102_i2c_write(cam, 0x96, 0x00);
+       err += sn9c102_i2c_write(cam, 0x97, 0x01);
+       err += sn9c102_i2c_write(cam, 0x98, 0x10);
+       err += sn9c102_i2c_write(cam, 0x99, 0x40);
+       err += sn9c102_i2c_write(cam, 0x9A, 0x40);
+       err += sn9c102_i2c_write(cam, 0x9B, 0x20);
+       err += sn9c102_i2c_write(cam, 0x9C, 0x00);
+       err += sn9c102_i2c_write(cam, 0x9D, 0x99);
+       err += sn9c102_i2c_write(cam, 0x9E, 0x7F);
+       err += sn9c102_i2c_write(cam, 0x9F, 0x00);
+       err += sn9c102_i2c_write(cam, 0xA0, 0x00);
+       err += sn9c102_i2c_write(cam, 0xA1, 0x00);
+
+       return err;
+}
+
+
+static int ov7660_get_ctrl(struct sn9c102_device* cam,
+                          struct v4l2_control* ctrl)
+{
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
+                       return -EIO;
+               break;
+       case V4L2_CID_DO_WHITE_BALANCE:
+               if ((ctrl->value = sn9c102_read_reg(cam, 0x02)) < 0)
+                       return -EIO;
+               ctrl->value = (ctrl->value & 0x04) ? 1 : 0;
+               break;
+       case V4L2_CID_RED_BALANCE:
+               if ((ctrl->value = sn9c102_read_reg(cam, 0x05)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x7f;
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               if ((ctrl->value = sn9c102_read_reg(cam, 0x06)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x7f;
+               break;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               if ((ctrl->value = sn9c102_read_reg(cam, 0x07)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x7f;
+               break;
+       case SN9C102_V4L2_CID_BAND_FILTER:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x3b)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x08;
+               break;
+       case V4L2_CID_GAIN:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x1f;
+               break;
+       case V4L2_CID_AUTOGAIN:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x01;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int ov7660_set_ctrl(struct sn9c102_device* cam,
+                          const struct v4l2_control* ctrl)
+{
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
+               break;
+       case V4L2_CID_DO_WHITE_BALANCE:
+               err += sn9c102_write_reg(cam, 0x43 | (ctrl->value << 2), 0x02);
+               break;
+       case V4L2_CID_RED_BALANCE:
+               err += sn9c102_write_reg(cam, ctrl->value, 0x05);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               err += sn9c102_write_reg(cam, ctrl->value, 0x06);
+               break;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               err += sn9c102_write_reg(cam, ctrl->value, 0x07);
+               break;
+       case SN9C102_V4L2_CID_BAND_FILTER:
+               err += sn9c102_i2c_write(cam, ctrl->value << 3, 0x3b);
+               break;
+       case V4L2_CID_GAIN:
+               err += sn9c102_i2c_write(cam, 0x00, 0x60 + ctrl->value);
+               break;
+       case V4L2_CID_AUTOGAIN:
+               err += sn9c102_i2c_write(cam, 0x13, 0xc0 |
+                                                   (ctrl->value * 0x07));
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int ov7660_set_crop(struct sn9c102_device* cam,
+                          const struct v4l2_rect* rect)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
+          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
+
+       err += sn9c102_write_reg(cam, h_start, 0x12);
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+
+       return err;
+}
+
+
+static int ov7660_set_pix_format(struct sn9c102_device* cam,
+                                const struct v4l2_pix_format* pix)
+{
+       int r0, err = 0;
+
+       r0 = sn9c102_pread_reg(cam, 0x01);
+
+       if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+               err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
+               err += sn9c102_write_reg(cam, 0xa2, 0x17);
+               err += sn9c102_i2c_write(cam, 0x11, 0x00);
+       } else {
+               err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
+               err += sn9c102_write_reg(cam, 0xa2, 0x17);
+               err += sn9c102_i2c_write(cam, 0x11, 0x0d);
+       }
+
+       return err;
+}
+
+
+static const struct sn9c102_sensor ov7660 = {
+       .name = "OV7660",
+       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
+       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
+       .frequency = SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_2WIRES,
+       .i2c_slave_id = 0x21,
+       .init = &ov7660_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "global gain",
+                       .minimum = 0x00,
+                       .maximum = 0x1f,
+                       .step = 0x01,
+                       .default_value = 0x09,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_EXPOSURE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "exposure",
+                       .minimum = 0x00,
+                       .maximum = 0xff,
+                       .step = 0x01,
+                       .default_value = 0x27,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_DO_WHITE_BALANCE,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "night mode",
+                       .minimum = 0x00,
+                       .maximum = 0x01,
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_RED_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "red balance",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
+                       .step = 0x01,
+                       .default_value = 0x14,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_BLUE_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "blue balance",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
+                       .step = 0x01,
+                       .default_value = 0x14,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_AUTOGAIN,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "auto adjust",
+                       .minimum = 0x00,
+                       .maximum = 0x01,
+                       .step = 0x01,
+                       .default_value = 0x01,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "green balance",
+                       .minimum = 0x00,
+                       .maximum = 0x7f,
+                       .step = 0x01,
+                       .default_value = 0x14,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_BAND_FILTER,
+                       .type = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name = "band filter",
+                       .minimum = 0x00,
+                       .maximum = 0x01,
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+       },
+       .get_ctrl = &ov7660_get_ctrl,
+       .set_ctrl = &ov7660_set_ctrl,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+       },
+       .set_crop = &ov7660_set_crop,
+       .pix_format = {
+               .width = 640,
+               .height = 480,
+               .pixelformat = V4L2_PIX_FMT_JPEG,
+               .priv = 8,
+       },
+       .set_pix_format = &ov7660_set_pix_format
+};
+
+
+int sn9c102_probe_ov7660(struct sn9c102_device* cam)
+{
+       int pid, ver, err;
+
+       err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
+                                      {0x01, 0x01}, {0x00, 0x01},
+                                      {0x28, 0x17});
+
+       pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a);
+       ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b);
+       if (err || pid < 0 || ver < 0)
+               return -EIO;
+       if (pid != 0x76 || ver != 0x60)
+               return -ENODEV;
+
+       sn9c102_attach_sensor(cam, &ov7660);
+
+       return 0;
+}
diff --git a/drivers/media/usb/sn9c102/sn9c102_pas106b.c b/drivers/media/usb/sn9c102/sn9c102_pas106b.c
new file mode 100644 (file)
index 0000000..81cd969
--- /dev/null
@@ -0,0 +1,302 @@
+/***************************************************************************
+ * Plug-in for PAS106B image sensor connected to the SN9C1xx PC Camera     *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ *                                                                         *
+ * 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/delay.h>
+#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
+
+
+static int pas106b_init(struct sn9c102_device* cam)
+{
+       int err = 0;
+
+       err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
+                                      {0x00, 0x14}, {0x20, 0x17},
+                                      {0x20, 0x19}, {0x09, 0x18});
+
+       err += sn9c102_i2c_write(cam, 0x02, 0x0c);
+       err += sn9c102_i2c_write(cam, 0x05, 0x5a);
+       err += sn9c102_i2c_write(cam, 0x06, 0x88);
+       err += sn9c102_i2c_write(cam, 0x07, 0x80);
+       err += sn9c102_i2c_write(cam, 0x10, 0x06);
+       err += sn9c102_i2c_write(cam, 0x11, 0x06);
+       err += sn9c102_i2c_write(cam, 0x12, 0x00);
+       err += sn9c102_i2c_write(cam, 0x14, 0x02);
+       err += sn9c102_i2c_write(cam, 0x13, 0x01);
+
+       msleep(400);
+
+       return err;
+}
+
+
+static int pas106b_get_ctrl(struct sn9c102_device* cam,
+                           struct v4l2_control* ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               {
+                       int r1 = sn9c102_i2c_read(cam, 0x03),
+                           r2 = sn9c102_i2c_read(cam, 0x04);
+                       if (r1 < 0 || r2 < 0)
+                               return -EIO;
+                       ctrl->value = (r1 << 4) | (r2 & 0x0f);
+               }
+               return 0;
+       case V4L2_CID_RED_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x1f;
+               return 0;
+       case V4L2_CID_BLUE_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x1f;
+               return 0;
+       case V4L2_CID_GAIN:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0e)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x1f;
+               return 0;
+       case V4L2_CID_CONTRAST:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0f)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x07;
+               return 0;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0a)) < 0)
+                       return -EIO;
+               ctrl->value = (ctrl->value & 0x1f) << 1;
+               return 0;
+       case SN9C102_V4L2_CID_DAC_MAGNITUDE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0)
+                       return -EIO;
+               ctrl->value &= 0xf8;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+
+static int pas106b_set_ctrl(struct sn9c102_device* cam,
+                           const struct v4l2_control* ctrl)
+{
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               err += sn9c102_i2c_write(cam, 0x03, ctrl->value >> 4);
+               err += sn9c102_i2c_write(cam, 0x04, ctrl->value & 0x0f);
+               break;
+       case V4L2_CID_RED_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
+               break;
+       case V4L2_CID_GAIN:
+               err += sn9c102_i2c_write(cam, 0x0e, ctrl->value);
+               break;
+       case V4L2_CID_CONTRAST:
+               err += sn9c102_i2c_write(cam, 0x0f, ctrl->value);
+               break;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x0a, ctrl->value >> 1);
+               err += sn9c102_i2c_write(cam, 0x0b, ctrl->value >> 1);
+               break;
+       case SN9C102_V4L2_CID_DAC_MAGNITUDE:
+               err += sn9c102_i2c_write(cam, 0x08, ctrl->value << 3);
+               break;
+       default:
+               return -EINVAL;
+       }
+       err += sn9c102_i2c_write(cam, 0x13, 0x01);
+
+       return err ? -EIO : 0;
+}
+
+
+static int pas106b_set_crop(struct sn9c102_device* cam,
+                           const struct v4l2_rect* rect)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
+          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
+
+       err += sn9c102_write_reg(cam, h_start, 0x12);
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+
+       return err;
+}
+
+
+static int pas106b_set_pix_format(struct sn9c102_device* cam,
+                                 const struct v4l2_pix_format* pix)
+{
+       int err = 0;
+
+       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+               err += sn9c102_write_reg(cam, 0x2c, 0x17);
+       else
+               err += sn9c102_write_reg(cam, 0x20, 0x17);
+
+       return err;
+}
+
+
+static const struct sn9c102_sensor pas106b = {
+       .name = "PAS106B",
+       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
+       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
+       .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_2WIRES,
+       .i2c_slave_id = 0x40,
+       .init = &pas106b_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_EXPOSURE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "exposure",
+                       .minimum = 0x125,
+                       .maximum = 0xfff,
+                       .step = 0x001,
+                       .default_value = 0x140,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "global gain",
+                       .minimum = 0x00,
+                       .maximum = 0x1f,
+                       .step = 0x01,
+                       .default_value = 0x0d,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_CONTRAST,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "contrast",
+                       .minimum = 0x00,
+                       .maximum = 0x07,
+                       .step = 0x01,
+                       .default_value = 0x00, /* 0x00~0x03 have same effect */
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_RED_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "red balance",
+                       .minimum = 0x00,
+                       .maximum = 0x1f,
+                       .step = 0x01,
+                       .default_value = 0x04,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_BLUE_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "blue balance",
+                       .minimum = 0x00,
+                       .maximum = 0x1f,
+                       .step = 0x01,
+                       .default_value = 0x06,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "green balance",
+                       .minimum = 0x00,
+                       .maximum = 0x3e,
+                       .step = 0x02,
+                       .default_value = 0x02,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "DAC magnitude",
+                       .minimum = 0x00,
+                       .maximum = 0x1f,
+                       .step = 0x01,
+                       .default_value = 0x01,
+                       .flags = 0,
+               },
+       },
+       .get_ctrl = &pas106b_get_ctrl,
+       .set_ctrl = &pas106b_set_ctrl,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 352,
+                       .height = 288,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 352,
+                       .height = 288,
+               },
+       },
+       .set_crop = &pas106b_set_crop,
+       .pix_format = {
+               .width = 352,
+               .height = 288,
+               .pixelformat = V4L2_PIX_FMT_SBGGR8,
+               .priv = 8, /* we use this field as 'bits per pixel' */
+       },
+       .set_pix_format = &pas106b_set_pix_format
+};
+
+
+int sn9c102_probe_pas106b(struct sn9c102_device* cam)
+{
+       int r0 = 0, r1 = 0;
+       unsigned int pid = 0;
+
+       /*
+          Minimal initialization to enable the I2C communication
+          NOTE: do NOT change the values!
+       */
+       if (sn9c102_write_const_regs(cam,
+                                    {0x01, 0x01}, /* sensor power down */
+                                    {0x00, 0x01}, /* sensor power on */
+                                   {0x28, 0x17})) /* sensor clock at 24 MHz */
+               return -EIO;
+
+       r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00);
+       r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01);
+       if (r0 < 0 || r1 < 0)
+               return -EIO;
+
+       pid = (r0 << 11) | ((r1 & 0xf0) >> 4);
+       if (pid != 0x007)
+               return -ENODEV;
+
+       sn9c102_attach_sensor(cam, &pas106b);
+
+       return 0;
+}
diff --git a/drivers/media/usb/sn9c102/sn9c102_pas202bcb.c b/drivers/media/usb/sn9c102/sn9c102_pas202bcb.c
new file mode 100644 (file)
index 0000000..2e86fdc
--- /dev/null
@@ -0,0 +1,335 @@
+/***************************************************************************
+ * Plug-in for PAS202BCB image sensor connected to the SN9C1xx PC Camera   *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio                  *
+ *                       <medaglia@undl.org.br>                            *
+ *                                                                         *
+ * Support for SN9C103, DAC Magnitude, exposure and green gain controls    *
+ * added by Luca Risolia <luca.risolia@studio.unibo.it>                    *
+ *                                                                         *
+ * 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/delay.h>
+#include "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
+
+
+static int pas202bcb_init(struct sn9c102_device* cam)
+{
+       int err = 0;
+
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+               err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
+                                              {0x00, 0x14}, {0x20, 0x17},
+                                              {0x30, 0x19}, {0x09, 0x18});
+               break;
+       case BRIDGE_SN9C103:
+               err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
+                                              {0x1a, 0x04}, {0x20, 0x05},
+                                              {0x20, 0x06}, {0x20, 0x07},
+                                              {0x00, 0x10}, {0x00, 0x11},
+                                              {0x00, 0x14}, {0x20, 0x17},
+                                              {0x30, 0x19}, {0x09, 0x18},
+                                              {0x02, 0x1c}, {0x03, 0x1d},
+                                              {0x0f, 0x1e}, {0x0c, 0x1f},
+                                              {0x00, 0x20}, {0x10, 0x21},
+                                              {0x20, 0x22}, {0x30, 0x23},
+                                              {0x40, 0x24}, {0x50, 0x25},
+                                              {0x60, 0x26}, {0x70, 0x27},
+                                              {0x80, 0x28}, {0x90, 0x29},
+                                              {0xa0, 0x2a}, {0xb0, 0x2b},
+                                              {0xc0, 0x2c}, {0xd0, 0x2d},
+                                              {0xe0, 0x2e}, {0xf0, 0x2f},
+                                              {0xff, 0x30});
+               break;
+       default:
+               break;
+       }
+
+       err += sn9c102_i2c_write(cam, 0x02, 0x14);
+       err += sn9c102_i2c_write(cam, 0x03, 0x40);
+       err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
+       err += sn9c102_i2c_write(cam, 0x0e, 0x01);
+       err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
+       err += sn9c102_i2c_write(cam, 0x10, 0x08);
+       err += sn9c102_i2c_write(cam, 0x13, 0x63);
+       err += sn9c102_i2c_write(cam, 0x15, 0x70);
+       err += sn9c102_i2c_write(cam, 0x11, 0x01);
+
+       msleep(400);
+
+       return err;
+}
+
+
+static int pas202bcb_get_ctrl(struct sn9c102_device* cam,
+                             struct v4l2_control* ctrl)
+{
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               {
+                       int r1 = sn9c102_i2c_read(cam, 0x04),
+                           r2 = sn9c102_i2c_read(cam, 0x05);
+                       if (r1 < 0 || r2 < 0)
+                               return -EIO;
+                       ctrl->value = (r1 << 6) | (r2 & 0x3f);
+               }
+               return 0;
+       case V4L2_CID_RED_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x0f;
+               return 0;
+       case V4L2_CID_BLUE_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x0f;
+               return 0;
+       case V4L2_CID_GAIN:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x1f;
+               return 0;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0)
+                       return -EIO;
+               ctrl->value &= 0x0f;
+               return 0;
+       case SN9C102_V4L2_CID_DAC_MAGNITUDE:
+               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
+                       return -EIO;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+
+static int pas202bcb_set_pix_format(struct sn9c102_device* cam,
+                                   const struct v4l2_pix_format* pix)
+{
+       int err = 0;
+
+       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+               err += sn9c102_write_reg(cam, 0x28, 0x17);
+       else
+               err += sn9c102_write_reg(cam, 0x20, 0x17);
+
+       return err;
+}
+
+
+static int pas202bcb_set_ctrl(struct sn9c102_device* cam,
+                             const struct v4l2_control* ctrl)
+{
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_EXPOSURE:
+               err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6);
+               err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f);
+               break;
+       case V4L2_CID_RED_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
+               break;
+       case V4L2_CID_BLUE_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x07, ctrl->value);
+               break;
+       case V4L2_CID_GAIN:
+               err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
+               break;
+       case SN9C102_V4L2_CID_GREEN_BALANCE:
+               err += sn9c102_i2c_write(cam, 0x08, ctrl->value);
+               break;
+       case SN9C102_V4L2_CID_DAC_MAGNITUDE:
+               err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
+               break;
+       default:
+               return -EINVAL;
+       }
+       err += sn9c102_i2c_write(cam, 0x11, 0x01);
+
+       return err ? -EIO : 0;
+}
+
+
+static int pas202bcb_set_crop(struct sn9c102_device* cam,
+                             const struct v4l2_rect* rect)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+       u8 h_start = 0,
+          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
+
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+               h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
+               break;
+       case BRIDGE_SN9C103:
+               h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3;
+               break;
+       default:
+               break;
+       }
+
+       err += sn9c102_write_reg(cam, h_start, 0x12);
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+
+       return err;
+}
+
+
+static const struct sn9c102_sensor pas202bcb = {
+       .name = "PAS202BCB",
+       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
+       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
+       .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_2WIRES,
+       .i2c_slave_id = 0x40,
+       .init = &pas202bcb_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_EXPOSURE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "exposure",
+                       .minimum = 0x01e5,
+                       .maximum = 0x3fff,
+                       .step = 0x0001,
+                       .default_value = 0x01e5,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "global gain",
+                       .minimum = 0x00,
+                       .maximum = 0x1f,
+                       .step = 0x01,
+                       .default_value = 0x0b,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_RED_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "red balance",
+                       .minimum = 0x00,
+                       .maximum = 0x0f,
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_BLUE_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "blue balance",
+                       .minimum = 0x00,
+                       .maximum = 0x0f,
+                       .step = 0x01,
+                       .default_value = 0x05,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "green balance",
+                       .minimum = 0x00,
+                       .maximum = 0x0f,
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+               {
+                       .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "DAC magnitude",
+                       .minimum = 0x00,
+                       .maximum = 0xff,
+                       .step = 0x01,
+                       .default_value = 0x04,
+                       .flags = 0,
+               },
+       },
+       .get_ctrl = &pas202bcb_get_ctrl,
+       .set_ctrl = &pas202bcb_set_ctrl,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+       },
+       .set_crop = &pas202bcb_set_crop,
+       .pix_format = {
+               .width = 640,
+               .height = 480,
+               .pixelformat = V4L2_PIX_FMT_SBGGR8,
+               .priv = 8,
+       },
+       .set_pix_format = &pas202bcb_set_pix_format
+};
+
+
+int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
+{
+       int r0 = 0, r1 = 0, err = 0;
+       unsigned int pid = 0;
+
+       /*
+        *  Minimal initialization to enable the I2C communication
+        *  NOTE: do NOT change the values!
+        */
+       switch (sn9c102_get_bridge(cam)) {
+       case BRIDGE_SN9C101:
+       case BRIDGE_SN9C102:
+               err = sn9c102_write_const_regs(cam,
+                                              {0x01, 0x01}, /* power down */
+                                              {0x40, 0x01}, /* power on */
+                                              {0x28, 0x17});/* clock 24 MHz */
+               break;
+       case BRIDGE_SN9C103: /* do _not_ change anything! */
+               err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x01},
+                                              {0x44, 0x02}, {0x29, 0x17});
+               break;
+       default:
+               break;
+       }
+
+       r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00);
+       r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01);
+
+       if (err || r0 < 0 || r1 < 0)
+               return -EIO;
+
+       pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
+       if (pid != 0x017)
+               return -ENODEV;
+
+       sn9c102_attach_sensor(cam, &pas202bcb);
+
+       return 0;
+}
diff --git a/drivers/media/usb/sn9c102/sn9c102_sensor.h b/drivers/media/usb/sn9c102/sn9c102_sensor.h
new file mode 100644 (file)
index 0000000..3679970
--- /dev/null
@@ -0,0 +1,307 @@
+/***************************************************************************
+ * API for image sensors connected to the SN9C1xx PC Camera Controllers    *
+ *                                                                         *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ *                                                                         *
+ * 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.               *
+ ***************************************************************************/
+
+#ifndef _SN9C102_SENSOR_H_
+#define _SN9C102_SENSOR_H_
+
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <linux/device.h>
+#include <linux/stddef.h>
+#include <linux/errno.h>
+#include <asm/types.h>
+
+struct sn9c102_device;
+struct sn9c102_sensor;
+
+/*****************************************************************************/
+
+/*
+   OVERVIEW.
+   This is a small interface that allows you to add support for any CCD/CMOS
+   image sensors connected to the SN9C1XX bridges. The entire API is documented
+   below. In the most general case, to support a sensor there are three steps
+   you have to follow:
+   1) define the main "sn9c102_sensor" structure by setting the basic fields;
+   2) write a probing function to be called by the core module when the USB
+      camera is recognized, then add both the USB ids and the name of that
+      function to the two corresponding tables in sn9c102_devtable.h;
+   3) implement the methods that you want/need (and fill the rest of the main
+      structure accordingly).
+   "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do
+   NOT need to touch the source code of the core module for the things to work
+   properly, unless you find bugs or flaws in it. Finally, do not forget to
+   read the V4L2 API for completeness.
+*/
+
+/*****************************************************************************/
+
+enum sn9c102_bridge {
+       BRIDGE_SN9C101 = 0x01,
+       BRIDGE_SN9C102 = 0x02,
+       BRIDGE_SN9C103 = 0x04,
+       BRIDGE_SN9C105 = 0x08,
+       BRIDGE_SN9C120 = 0x10,
+};
+
+/* Return the bridge name */
+enum sn9c102_bridge sn9c102_get_bridge(struct sn9c102_device* cam);
+
+/* Return a pointer the sensor struct attached to the camera */
+struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam);
+
+/* Identify a device */
+extern struct sn9c102_device*
+sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id);
+
+/* Attach a probed sensor to the camera. */
+extern void
+sn9c102_attach_sensor(struct sn9c102_device* cam,
+                     const struct sn9c102_sensor* sensor);
+
+/*
+   Read/write routines: they always return -1 on error, 0 or the read value
+   otherwise. NOTE that a real read operation is not supported by the SN9C1XX
+   chip for some of its registers. To work around this problem, a pseudo-read
+   call is provided instead: it returns the last successfully written value
+   on the register (0 if it has never been written), the usual -1 on error.
+*/
+
+/* The "try" I2C I/O versions are used when probing the sensor */
+extern int sn9c102_i2c_try_read(struct sn9c102_device*,
+                               const struct sn9c102_sensor*, u8 address);
+
+/*
+   These must be used if and only if the sensor doesn't implement the standard
+   I2C protocol. There are a number of good reasons why you must use the
+   single-byte versions of these functions: do not abuse. The first function
+   writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C1XX
+   chip. The second one programs the registers 0x09 and 0x10 with data0 and
+   data1, and places the n bytes read from the sensor register table in the
+   buffer pointed by 'buffer'. Both the functions return -1 on error; the write
+   version returns 0 on success, while the read version returns the first read
+   byte.
+*/
+extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
+                                    const struct sn9c102_sensor* sensor, u8 n,
+                                    u8 data0, u8 data1, u8 data2, u8 data3,
+                                    u8 data4, u8 data5);
+extern int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
+                                   const struct sn9c102_sensor* sensor,
+                                   u8 data0, u8 data1, u8 n, u8 buffer[]);
+
+/* To be used after the sensor struct has been attached to the camera struct */
+extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value);
+extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address);
+
+/* I/O on registers in the bridge. Could be used by the sensor methods too */
+extern int sn9c102_read_reg(struct sn9c102_device*, u16 index);
+extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
+extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
+extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2],
+                             int count);
+/*
+   Write multiple registers with constant values. For example:
+   sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18});
+   Register addresses must be < 256.
+*/
+#define sn9c102_write_const_regs(sn9c102_device, data...)                     \
+       ({ static const u8 _valreg[][2] = {data};                             \
+       sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); })
+
+/*****************************************************************************/
+
+enum sn9c102_i2c_sysfs_ops {
+       SN9C102_I2C_READ = 0x01,
+       SN9C102_I2C_WRITE = 0x02,
+};
+
+enum sn9c102_i2c_frequency { /* sensors may support both the frequencies */
+       SN9C102_I2C_100KHZ = 0x01,
+       SN9C102_I2C_400KHZ = 0x02,
+};
+
+enum sn9c102_i2c_interface {
+       SN9C102_I2C_2WIRES,
+       SN9C102_I2C_3WIRES,
+};
+
+#define SN9C102_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10)
+
+struct sn9c102_sensor {
+       char name[32], /* sensor name */
+            maintainer[64]; /* name of the maintainer <email> */
+
+       enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */
+
+       /* Supported operations through the 'sysfs' interface */
+       enum sn9c102_i2c_sysfs_ops sysfs_ops;
+
+       /*
+          These sensor capabilities must be provided if the SN9C1XX controller
+          needs to communicate through the sensor serial interface by using
+          at least one of the i2c functions available.
+       */
+       enum sn9c102_i2c_frequency frequency;
+       enum sn9c102_i2c_interface interface;
+
+       /*
+          This identifier must be provided if the image sensor implements
+          the standard I2C protocol.
+       */
+       u8 i2c_slave_id; /* reg. 0x09 */
+
+       /*
+          NOTE: Where not noted,most of the functions below are not mandatory.
+                Set to null if you do not implement them. If implemented,
+                they must return 0 on success, the proper error otherwise.
+       */
+
+       int (*init)(struct sn9c102_device* cam);
+       /*
+          This function will be called after the sensor has been attached.
+          It should be used to initialize the sensor only, but may also
+          configure part of the SN9C1XX chip if necessary. You don't need to
+          setup picture settings like brightness, contrast, etc.. here, if
+          the corresponding controls are implemented (see below), since
+          they are adjusted in the core driver by calling the set_ctrl()
+          method after init(), where the arguments are the default values
+          specified in the v4l2_queryctrl list of supported controls;
+          Same suggestions apply for other settings, _if_ the corresponding
+          methods are present; if not, the initialization must configure the
+          sensor according to the default configuration structures below.
+       */
+
+       struct v4l2_queryctrl qctrl[SN9C102_MAX_CTRLS];
+       /*
+          Optional list of default controls, defined as indicated in the
+          V4L2 API. Menu type controls are not handled by this interface.
+       */
+
+       int (*get_ctrl)(struct sn9c102_device* cam, struct v4l2_control* ctrl);
+       int (*set_ctrl)(struct sn9c102_device* cam,
+                       const struct v4l2_control* ctrl);
+       /*
+          You must implement at least the set_ctrl method if you have defined
+          the list above. The returned value must follow the V4L2
+          specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER
+          are not supported by this driver, so do not implement them. Also,
+          you don't have to check whether the passed values are out of bounds,
+          given that this is done by the core module.
+       */
+
+       struct v4l2_cropcap cropcap;
+       /*
+          Think the image sensor as a grid of R,G,B monochromatic pixels
+          disposed according to a particular Bayer pattern, which describes
+          the complete array of pixels, from (0,0) to (xmax, ymax). We will
+          use this coordinate system from now on. It is assumed the sensor
+          chip can be programmed to capture/transmit a subsection of that
+          array of pixels: we will call this subsection "active window".
+          It is not always true that the largest achievable active window can
+          cover the whole array of pixels. The V4L2 API defines another
+          area called "source rectangle", which, in turn, is a subrectangle of
+          the active window. The SN9C1XX chip is always programmed to read the
+          source rectangle.
+          The bounds of both the active window and the source rectangle are
+          specified in the cropcap substructures 'bounds' and 'defrect'.
+          By default, the source rectangle should cover the largest possible
+          area. Again, it is not always true that the largest source rectangle
+          can cover the entire active window, although it is a rare case for
+          the hardware we have. The bounds of the source rectangle _must_ be
+          multiple of 16 and must use the same coordinate system as indicated
+          before; their centers shall align initially.
+          If necessary, the sensor chip must be initialized during init() to
+          set the bounds of the active sensor window; however, by default, it
+          usually covers the largest achievable area (maxwidth x maxheight)
+          of pixels, so no particular initialization is needed, if you have
+          defined the correct default bounds in the structures.
+          See the V4L2 API for further details.
+          NOTE: once you have defined the bounds of the active window
+                (struct cropcap.bounds) you must not change them.anymore.
+          Only 'bounds' and 'defrect' fields are mandatory, other fields
+          will be ignored.
+       */
+
+       int (*set_crop)(struct sn9c102_device* cam,
+                       const struct v4l2_rect* rect);
+       /*
+          To be called on VIDIOC_C_SETCROP. The core module always calls a
+          default routine which configures the appropriate SN9C1XX regs (also
+          scaling), but you may need to override/adjust specific stuff.
+          'rect' contains width and height values that are multiple of 16: in
+          case you override the default function, you always have to program
+          the chip to match those values; on error return the corresponding
+          error code without rolling back.
+          NOTE: in case, you must program the SN9C1XX chip to get rid of
+                blank pixels or blank lines at the _start_ of each line or
+                frame after each HSYNC or VSYNC, so that the image starts with
+                real RGB data (see regs 0x12, 0x13) (having set H_SIZE and,
+                V_SIZE you don't have to care about blank pixels or blank
+                lines at the end of each line or frame).
+       */
+
+       struct v4l2_pix_format pix_format;
+       /*
+          What you have to define here are: 1) initial 'width' and 'height' of
+          the target rectangle 2) the initial 'pixelformat', which can be
+          either V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_JPEG (for ompressed video)
+          or V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate
+          the number of bits per pixel for uncompressed video, 8 or 9 (despite
+          the current value of 'pixelformat').
+          NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4
+                  of cropcap.defrect.width and cropcap.defrect.height. I
+                  suggest 1/1.
+          NOTE 2: The initial compression quality is defined by the first bit
+                  of reg 0x17 during the initialization of the image sensor.
+          NOTE 3: as said above, you have to program the SN9C1XX chip to get
+                  rid of any blank pixels, so that the output of the sensor
+                  matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
+       */
+
+       int (*set_pix_format)(struct sn9c102_device* cam,
+                             const struct v4l2_pix_format* pix);
+       /*
+          To be called on VIDIOC_S_FMT, when switching from the SBGGR8 to
+          SN9C10X pixel format or viceversa. On error return the corresponding
+          error code without rolling back.
+       */
+
+       /*
+          Do NOT write to the data below, it's READ ONLY. It is used by the
+          core module to store successfully updated values of the above
+          settings, for rollbacks..etc..in case of errors during atomic I/O
+       */
+       struct v4l2_queryctrl _qctrl[SN9C102_MAX_CTRLS];
+       struct v4l2_rect _rect;
+};
+
+/*****************************************************************************/
+
+/* Private ioctl's for control settings supported by some image sensors */
+#define SN9C102_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0)
+#define SN9C102_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1)
+#define SN9C102_V4L2_CID_RESET_LEVEL (V4L2_CID_PRIVATE_BASE + 2)
+#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE (V4L2_CID_PRIVATE_BASE + 3)
+#define SN9C102_V4L2_CID_GAMMA (V4L2_CID_PRIVATE_BASE + 4)
+#define SN9C102_V4L2_CID_BAND_FILTER (V4L2_CID_PRIVATE_BASE + 5)
+#define SN9C102_V4L2_CID_BRIGHT_LEVEL (V4L2_CID_PRIVATE_BASE + 6)
+
+#endif /* _SN9C102_SENSOR_H_ */
diff --git a/drivers/media/usb/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/usb/sn9c102/sn9c102_tas5110c1b.c
new file mode 100644 (file)
index 0000000..04cdfdd
--- /dev/null
@@ -0,0 +1,154 @@
+/***************************************************************************
+ * Plug-in for TAS5110C1B image sensor connected to the SN9C1xx PC Camera  *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ *                                                                         *
+ * 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 "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
+
+
+static int tas5110c1b_init(struct sn9c102_device* cam)
+{
+       int err = 0;
+
+       err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x44, 0x01},
+                                      {0x00, 0x10}, {0x00, 0x11},
+                                      {0x0a, 0x14}, {0x60, 0x17},
+                                      {0x06, 0x18}, {0xfb, 0x19});
+
+       err += sn9c102_i2c_write(cam, 0xc0, 0x80);
+
+       return err;
+}
+
+
+static int tas5110c1b_set_ctrl(struct sn9c102_device* cam,
+                              const struct v4l2_control* ctrl)
+{
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+               err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int tas5110c1b_set_crop(struct sn9c102_device* cam,
+                              const struct v4l2_rect* rect)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
+          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
+
+       err += sn9c102_write_reg(cam, h_start, 0x12);
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+
+       /* Don't change ! */
+       err += sn9c102_write_reg(cam, 0x14, 0x1a);
+       err += sn9c102_write_reg(cam, 0x0a, 0x1b);
+       err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19);
+
+       return err;
+}
+
+
+static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
+                                    const struct v4l2_pix_format* pix)
+{
+       int err = 0;
+
+       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+               err += sn9c102_write_reg(cam, 0x2b, 0x19);
+       else
+               err += sn9c102_write_reg(cam, 0xfb, 0x19);
+
+       return err;
+}
+
+
+static const struct sn9c102_sensor tas5110c1b = {
+       .name = "TAS5110C1B",
+       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
+       .sysfs_ops = SN9C102_I2C_WRITE,
+       .frequency = SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_3WIRES,
+       .init = &tas5110c1b_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "global gain",
+                       .minimum = 0x00,
+                       .maximum = 0xf6,
+                       .step = 0x01,
+                       .default_value = 0x40,
+                       .flags = 0,
+               },
+       },
+       .set_ctrl = &tas5110c1b_set_ctrl,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 352,
+                       .height = 288,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 352,
+                       .height = 288,
+               },
+       },
+       .set_crop = &tas5110c1b_set_crop,
+       .pix_format = {
+               .width = 352,
+               .height = 288,
+               .pixelformat = V4L2_PIX_FMT_SBGGR8,
+               .priv = 8,
+       },
+       .set_pix_format = &tas5110c1b_set_pix_format
+};
+
+
+int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
+{
+       const struct usb_device_id tas5110c1b_id_table[] = {
+               { USB_DEVICE(0x0c45, 0x6001), },
+               { USB_DEVICE(0x0c45, 0x6005), },
+               { USB_DEVICE(0x0c45, 0x60ab), },
+               { }
+       };
+
+       /* Sensor detection is based on USB pid/vid */
+       if (!sn9c102_match_id(cam, tas5110c1b_id_table))
+               return -ENODEV;
+
+       sn9c102_attach_sensor(cam, &tas5110c1b);
+
+       return 0;
+}
diff --git a/drivers/media/usb/sn9c102/sn9c102_tas5110d.c b/drivers/media/usb/sn9c102/sn9c102_tas5110d.c
new file mode 100644 (file)
index 0000000..9372e6f
--- /dev/null
@@ -0,0 +1,119 @@
+/***************************************************************************
+ * Plug-in for TAS5110D image sensor connected to the SN9C1xx PC Camera    *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * 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 "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
+
+
+static int tas5110d_init(struct sn9c102_device* cam)
+{
+       int err;
+
+       err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x04, 0x01},
+                                      {0x0a, 0x14}, {0x60, 0x17},
+                                      {0x06, 0x18}, {0xfb, 0x19});
+
+       err += sn9c102_i2c_write(cam, 0x9a, 0xca);
+
+       return err;
+}
+
+
+static int tas5110d_set_crop(struct sn9c102_device* cam,
+                            const struct v4l2_rect* rect)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       int err = 0;
+       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
+          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
+
+       err += sn9c102_write_reg(cam, h_start, 0x12);
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+
+       err += sn9c102_write_reg(cam, 0x14, 0x1a);
+       err += sn9c102_write_reg(cam, 0x0a, 0x1b);
+
+       return err;
+}
+
+
+static int tas5110d_set_pix_format(struct sn9c102_device* cam,
+                                    const struct v4l2_pix_format* pix)
+{
+       int err = 0;
+
+       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+               err += sn9c102_write_reg(cam, 0x3b, 0x19);
+       else
+               err += sn9c102_write_reg(cam, 0xfb, 0x19);
+
+       return err;
+}
+
+
+static const struct sn9c102_sensor tas5110d = {
+       .name = "TAS5110D",
+       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
+       .sysfs_ops = SN9C102_I2C_WRITE,
+       .frequency = SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_2WIRES,
+       .i2c_slave_id = 0x61,
+       .init = &tas5110d_init,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 352,
+                       .height = 288,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 352,
+                       .height = 288,
+               },
+       },
+       .set_crop = &tas5110d_set_crop,
+       .pix_format = {
+               .width = 352,
+               .height = 288,
+               .pixelformat = V4L2_PIX_FMT_SBGGR8,
+               .priv = 8,
+       },
+       .set_pix_format = &tas5110d_set_pix_format
+};
+
+
+int sn9c102_probe_tas5110d(struct sn9c102_device* cam)
+{
+       const struct usb_device_id tas5110d_id_table[] = {
+               { USB_DEVICE(0x0c45, 0x6007), },
+               { }
+       };
+
+       if (!sn9c102_match_id(cam, tas5110d_id_table))
+               return -ENODEV;
+
+       sn9c102_attach_sensor(cam, &tas5110d);
+
+       return 0;
+}
diff --git a/drivers/media/usb/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/usb/sn9c102/sn9c102_tas5130d1b.c
new file mode 100644 (file)
index 0000000..a30bbc4
--- /dev/null
@@ -0,0 +1,165 @@
+/***************************************************************************
+ * Plug-in for TAS5130D1B image sensor connected to the SN9C1xx PC Camera  *
+ * Controllers                                                             *
+ *                                                                         *
+ * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
+ *                                                                         *
+ * 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 "sn9c102_sensor.h"
+#include "sn9c102_devtable.h"
+
+
+static int tas5130d1b_init(struct sn9c102_device* cam)
+{
+       int err;
+
+       err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x20, 0x17},
+                                      {0x04, 0x01}, {0x01, 0x10},
+                                      {0x00, 0x11}, {0x00, 0x14},
+                                      {0x60, 0x17}, {0x07, 0x18});
+
+       return err;
+}
+
+
+static int tas5130d1b_set_ctrl(struct sn9c102_device* cam,
+                              const struct v4l2_control* ctrl)
+{
+       int err = 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_GAIN:
+               err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
+               break;
+       case V4L2_CID_EXPOSURE:
+               err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return err ? -EIO : 0;
+}
+
+
+static int tas5130d1b_set_crop(struct sn9c102_device* cam,
+                              const struct v4l2_rect* rect)
+{
+       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
+       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104,
+          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12;
+       int err = 0;
+
+       err += sn9c102_write_reg(cam, h_start, 0x12);
+       err += sn9c102_write_reg(cam, v_start, 0x13);
+
+       /* Do NOT change! */
+       err += sn9c102_write_reg(cam, 0x1f, 0x1a);
+       err += sn9c102_write_reg(cam, 0x1a, 0x1b);
+       err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19);
+
+       return err;
+}
+
+
+static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
+                                    const struct v4l2_pix_format* pix)
+{
+       int err = 0;
+
+       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+               err += sn9c102_write_reg(cam, 0x63, 0x19);
+       else
+               err += sn9c102_write_reg(cam, 0xf3, 0x19);
+
+       return err;
+}
+
+
+static const struct sn9c102_sensor tas5130d1b = {
+       .name = "TAS5130D1B",
+       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
+       .sysfs_ops = SN9C102_I2C_WRITE,
+       .frequency = SN9C102_I2C_100KHZ,
+       .interface = SN9C102_I2C_3WIRES,
+       .init = &tas5130d1b_init,
+       .qctrl = {
+               {
+                       .id = V4L2_CID_GAIN,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "global gain",
+                       .minimum = 0x00,
+                       .maximum = 0xf6,
+                       .step = 0x02,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+               {
+                       .id = V4L2_CID_EXPOSURE,
+                       .type = V4L2_CTRL_TYPE_INTEGER,
+                       .name = "exposure",
+                       .minimum = 0x00,
+                       .maximum = 0x47,
+                       .step = 0x01,
+                       .default_value = 0x00,
+                       .flags = 0,
+               },
+       },
+       .set_ctrl = &tas5130d1b_set_ctrl,
+       .cropcap = {
+               .bounds = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+               .defrect = {
+                       .left = 0,
+                       .top = 0,
+                       .width = 640,
+                       .height = 480,
+               },
+       },
+       .set_crop = &tas5130d1b_set_crop,
+       .pix_format = {
+               .width = 640,
+               .height = 480,
+               .pixelformat = V4L2_PIX_FMT_SBGGR8,
+               .priv = 8,
+       },
+       .set_pix_format = &tas5130d1b_set_pix_format
+};
+
+
+int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam)
+{
+       const struct usb_device_id tas5130d1b_id_table[] = {
+               { USB_DEVICE(0x0c45, 0x6024), },
+               { USB_DEVICE(0x0c45, 0x6025), },
+               { USB_DEVICE(0x0c45, 0x60aa), },
+               { }
+       };
+
+       /* Sensor detection is based on USB pid/vid */
+       if (!sn9c102_match_id(cam, tas5130d1b_id_table))
+               return -ENODEV;
+
+       sn9c102_attach_sensor(cam, &tas5130d1b);
+
+       return 0;
+}
diff --git a/drivers/media/usb/stk1160/Kconfig b/drivers/media/usb/stk1160/Kconfig
new file mode 100644 (file)
index 0000000..1c3a1ec
--- /dev/null
@@ -0,0 +1,20 @@
+config VIDEO_STK1160
+       tristate "STK1160 USB video capture support"
+       depends on VIDEO_DEV && I2C
+       select VIDEOBUF2_VMALLOC
+       select VIDEO_SAA711X
+
+       ---help---
+         This is a video4linux driver for STK1160 based video capture devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called stk1160
+
+config VIDEO_STK1160_AC97
+       bool "STK1160 AC97 codec support"
+       depends on VIDEO_STK1160 && SND
+       select SND_AC97_CODEC
+
+       ---help---
+         Enables AC97 codec support for stk1160 driver.
+.
diff --git a/drivers/media/usb/stk1160/Makefile b/drivers/media/usb/stk1160/Makefile
new file mode 100644 (file)
index 0000000..8a3c784
--- /dev/null
@@ -0,0 +1,11 @@
+obj-stk1160-ac97-$(CONFIG_VIDEO_STK1160_AC97) := stk1160-ac97.o
+
+stk1160-y :=   stk1160-core.o \
+               stk1160-v4l.o \
+               stk1160-video.o \
+               stk1160-i2c.o \
+               $(obj-stk1160-ac97-y)
+
+obj-$(CONFIG_VIDEO_STK1160) += stk1160.o
+
+ccflags-y += -Idrivers/media/video
diff --git a/drivers/media/usb/stk1160/stk1160-ac97.c b/drivers/media/usb/stk1160/stk1160-ac97.c
new file mode 100644 (file)
index 0000000..8d325f5
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * STK1160 driver
+ *
+ * Copyright (C) 2012 Ezequiel Garcia
+ * <elezegarcia--a.t--gmail.com>
+ *
+ * Based on Easycap driver by R.M. Thomas
+ *     Copyright (C) 2010 R.M. Thomas
+ *     <rmthomas--a.t--sciolus.org>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/ac97_codec.h>
+
+#include "stk1160.h"
+#include "stk1160-reg.h"
+
+static struct snd_ac97 *stk1160_ac97;
+
+static void stk1160_write_ac97(struct snd_ac97 *ac97, u16 reg, u16 value)
+{
+       struct stk1160 *dev = ac97->private_data;
+
+       /* Set codec register address */
+       stk1160_write_reg(dev, STK1160_AC97_ADDR, reg);
+
+       /* Set codec command */
+       stk1160_write_reg(dev, STK1160_AC97_CMD, value & 0xff);
+       stk1160_write_reg(dev, STK1160_AC97_CMD + 1, (value & 0xff00) >> 8);
+
+       /*
+        * Set command write bit to initiate write operation.
+        * The bit will be cleared when transfer is done.
+        */
+       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8c);
+}
+
+static u16 stk1160_read_ac97(struct snd_ac97 *ac97, u16 reg)
+{
+       struct stk1160 *dev = ac97->private_data;
+       u8 vall = 0;
+       u8 valh = 0;
+
+       /* Set codec register address */
+       stk1160_write_reg(dev, STK1160_AC97_ADDR, reg);
+
+       /*
+        * Set command read bit to initiate read operation.
+        * The bit will be cleared when transfer is done.
+        */
+       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8b);
+
+       /* Retrieve register value */
+       stk1160_read_reg(dev, STK1160_AC97_CMD, &vall);
+       stk1160_read_reg(dev, STK1160_AC97_CMD + 1, &valh);
+
+       return (valh << 8) | vall;
+}
+
+static void stk1160_reset_ac97(struct snd_ac97 *ac97)
+{
+       struct stk1160 *dev = ac97->private_data;
+       /* Two-step reset AC97 interface and hardware codec */
+       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x94);
+       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x88);
+
+       /* Set 16-bit audio data and choose L&R channel*/
+       stk1160_write_reg(dev, STK1160_AC97CTL_1 + 2, 0x01);
+}
+
+static struct snd_ac97_bus_ops stk1160_ac97_ops = {
+       .read   = stk1160_read_ac97,
+       .write  = stk1160_write_ac97,
+       .reset  = stk1160_reset_ac97,
+};
+
+int stk1160_ac97_register(struct stk1160 *dev)
+{
+       struct snd_card *card = NULL;
+       struct snd_ac97_bus *ac97_bus;
+       struct snd_ac97_template ac97_template;
+       int rc;
+
+       /*
+        * Just want a card to access ac96 controls,
+        * the actual capture interface will be handled by snd-usb-audio
+        */
+       rc = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+                             THIS_MODULE, 0, &card);
+       if (rc < 0)
+               return rc;
+
+       snd_card_set_dev(card, dev->dev);
+
+       /* TODO: I'm not sure where should I get these names :-( */
+       snprintf(card->shortname, sizeof(card->shortname),
+                "stk1160-mixer");
+       snprintf(card->longname, sizeof(card->longname),
+                "stk1160 ac97 codec mixer control");
+       strncpy(card->driver, dev->dev->driver->name, sizeof(card->driver));
+
+       rc = snd_ac97_bus(card, 0, &stk1160_ac97_ops, NULL, &ac97_bus);
+       if (rc)
+               goto err;
+
+       /* We must set private_data before calling snd_ac97_mixer */
+       memset(&ac97_template, 0, sizeof(ac97_template));
+       ac97_template.private_data = dev;
+       ac97_template.scaps = AC97_SCAP_SKIP_MODEM;
+       rc = snd_ac97_mixer(ac97_bus, &ac97_template, &stk1160_ac97);
+       if (rc)
+               goto err;
+
+       dev->snd_card = card;
+       rc = snd_card_register(card);
+       if (rc)
+               goto err;
+
+       return 0;
+
+err:
+       dev->snd_card = NULL;
+       if (card)
+               snd_card_free(card);
+       return rc;
+}
+
+int stk1160_ac97_unregister(struct stk1160 *dev)
+{
+       struct snd_card *card = dev->snd_card;
+
+       /*
+        * We need to check usb_device,
+        * because ac97 release attempts to communicate with codec
+        */
+       if (card && dev->udev)
+               snd_card_free(card);
+
+       return 0;
+}
diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c
new file mode 100644 (file)
index 0000000..74236fd
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * STK1160 driver
+ *
+ * Copyright (C) 2012 Ezequiel Garcia
+ * <elezegarcia--a.t--gmail.com>
+ *
+ * Based on Easycap driver by R.M. Thomas
+ *     Copyright (C) 2010 R.M. Thomas
+ *     <rmthomas--a.t--sciolus.org>
+ *
+ * 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.
+ *
+ * TODO:
+ *
+ * 1. (Try to) detect if we must register ac97 mixer
+ * 2. Support stream at lower speed: lower frame rate or lower frame size.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <linux/usb.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <media/saa7115.h>
+
+#include "stk1160.h"
+#include "stk1160-reg.h"
+
+static unsigned int input;
+module_param(input, int, 0644);
+MODULE_PARM_DESC(input, "Set default input");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ezequiel Garcia");
+MODULE_DESCRIPTION("STK1160 driver");
+
+/* Devices supported by this driver */
+static struct usb_device_id stk1160_id_table[] = {
+       { USB_DEVICE(0x05e1, 0x0408) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, stk1160_id_table);
+
+/* saa7113 I2C address */
+static unsigned short saa7113_addrs[] = {
+       0x4a >> 1,
+       I2C_CLIENT_END
+};
+
+/*
+ * Read/Write stk registers
+ */
+int stk1160_read_reg(struct stk1160 *dev, u16 reg, u8 *value)
+{
+       int ret;
+       int pipe = usb_rcvctrlpipe(dev->udev, 0);
+
+       *value = 0;
+       ret = usb_control_msg(dev->udev, pipe, 0x00,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0x00, reg, value, sizeof(u8), HZ);
+       if (ret < 0) {
+               stk1160_err("read failed on reg 0x%x (%d)\n",
+                       reg, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value)
+{
+       int ret;
+       int pipe = usb_sndctrlpipe(dev->udev, 0);
+
+       ret =  usb_control_msg(dev->udev, pipe, 0x01,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, reg, NULL, 0, HZ);
+       if (ret < 0) {
+               stk1160_err("write failed on reg 0x%x (%d)\n",
+                       reg, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+void stk1160_select_input(struct stk1160 *dev)
+{
+       static const u8 gctrl[] = {
+               0x98, 0x90, 0x88, 0x80
+       };
+
+       if (dev->ctl_input < ARRAY_SIZE(gctrl))
+               stk1160_write_reg(dev, STK1160_GCTRL, gctrl[dev->ctl_input]);
+}
+
+/* TODO: We should break this into pieces */
+static void stk1160_reg_reset(struct stk1160 *dev)
+{
+       int i;
+
+       static const struct regval ctl[] = {
+               {STK1160_GCTRL+2, 0x0078},
+
+               {STK1160_RMCTL+1, 0x0000},
+               {STK1160_RMCTL+3, 0x0002},
+
+               {STK1160_PLLSO,   0x0010},
+               {STK1160_PLLSO+1, 0x0000},
+               {STK1160_PLLSO+2, 0x0014},
+               {STK1160_PLLSO+3, 0x000E},
+
+               {STK1160_PLLFD,   0x0046},
+
+               /* Timing generator setup */
+               {STK1160_TIGEN,   0x0012},
+               {STK1160_TICTL,   0x002D},
+               {STK1160_TICTL+1, 0x0001},
+               {STK1160_TICTL+2, 0x0000},
+               {STK1160_TICTL+3, 0x0000},
+               {STK1160_TIGEN,   0x0080},
+
+               {0xffff, 0xffff}
+       };
+
+       for (i = 0; ctl[i].reg != 0xffff; i++)
+               stk1160_write_reg(dev, ctl[i].reg, ctl[i].val);
+}
+
+static void stk1160_release(struct v4l2_device *v4l2_dev)
+{
+       struct stk1160 *dev = container_of(v4l2_dev, struct stk1160, v4l2_dev);
+
+       stk1160_info("releasing all resources\n");
+
+       stk1160_i2c_unregister(dev);
+
+       v4l2_ctrl_handler_free(&dev->ctrl_handler);
+       v4l2_device_unregister(&dev->v4l2_dev);
+       kfree(dev->alt_max_pkt_size);
+       kfree(dev);
+}
+
+/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
+#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
+
+/*
+ * Scan usb interface and populate max_pkt_size array
+ * with information on each alternate setting.
+ * The array should be allocated by the caller.
+ */
+static int stk1160_scan_usb(struct usb_interface *intf, struct usb_device *udev,
+               unsigned int *max_pkt_size)
+{
+       int i, e, sizedescr, size, ifnum;
+       const struct usb_endpoint_descriptor *desc;
+
+       bool has_video = false, has_audio = false;
+       const char *speed;
+
+       ifnum = intf->altsetting[0].desc.bInterfaceNumber;
+
+       /* Get endpoints */
+       for (i = 0; i < intf->num_altsetting; i++) {
+
+               for (e = 0; e < intf->altsetting[i].desc.bNumEndpoints; e++) {
+
+                       /* This isn't clear enough, at least to me */
+                       desc = &intf->altsetting[i].endpoint[e].desc;
+                       sizedescr = le16_to_cpu(desc->wMaxPacketSize);
+                       size = sizedescr & 0x7ff;
+
+                       if (udev->speed == USB_SPEED_HIGH)
+                               size = size * hb_mult(sizedescr);
+
+                       if (usb_endpoint_xfer_isoc(desc) &&
+                           usb_endpoint_dir_in(desc)) {
+                               switch (desc->bEndpointAddress) {
+                               case STK1160_EP_AUDIO:
+                                       has_audio = true;
+                                       break;
+                               case STK1160_EP_VIDEO:
+                                       has_video = true;
+                                       max_pkt_size[i] = size;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       /* Is this even possible? */
+       if (!(has_audio || has_video)) {
+               dev_err(&udev->dev, "no audio or video endpoints found\n");
+               return -ENODEV;
+       }
+
+       switch (udev->speed) {
+       case USB_SPEED_LOW:
+               speed = "1.5";
+               break;
+       case USB_SPEED_FULL:
+               speed = "12";
+               break;
+       case USB_SPEED_HIGH:
+               speed = "480";
+               break;
+       default:
+               speed = "unknown";
+       }
+
+       dev_info(&udev->dev, "New device %s %s @ %s Mbps (%04x:%04x, interface %d, class %d)\n",
+               udev->manufacturer ? udev->manufacturer : "",
+               udev->product ? udev->product : "",
+               speed,
+               le16_to_cpu(udev->descriptor.idVendor),
+               le16_to_cpu(udev->descriptor.idProduct),
+               ifnum,
+               intf->altsetting->desc.bInterfaceNumber);
+
+       /* This should never happen, since we rejected audio interfaces */
+       if (has_audio)
+               dev_warn(&udev->dev, "audio interface %d found.\n\
+                               This is not implemented by this driver,\
+                               you should use snd-usb-audio instead\n", ifnum);
+
+       if (has_video)
+               dev_info(&udev->dev, "video interface %d found\n",
+                               ifnum);
+
+       /*
+        * Make sure we have 480 Mbps of bandwidth, otherwise things like
+        * video stream wouldn't likely work, since 12 Mbps is generally
+        * not enough even for most streams.
+        */
+       if (udev->speed != USB_SPEED_HIGH)
+               dev_warn(&udev->dev, "must be connected to a high-speed USB 2.0 port\n\
+                               You may not be able to stream video smoothly\n");
+
+       return 0;
+}
+
+static int stk1160_probe(struct usb_interface *interface,
+               const struct usb_device_id *id)
+{
+       int ifnum;
+       int rc = 0;
+
+       unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
+       struct usb_device *udev;
+       struct stk1160 *dev;
+
+       ifnum = interface->altsetting[0].desc.bInterfaceNumber;
+       udev = interface_to_usbdev(interface);
+
+       /*
+        * Since usb audio class is supported by snd-usb-audio,
+        * we reject audio interface.
+        */
+       if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO)
+               return -ENODEV;
+
+       /* Alloc an array for all possible max_pkt_size */
+       alt_max_pkt_size = kmalloc(sizeof(alt_max_pkt_size[0]) *
+                       interface->num_altsetting, GFP_KERNEL);
+       if (alt_max_pkt_size == NULL)
+               return -ENOMEM;
+
+       /*
+        * Scan usb posibilities and populate alt_max_pkt_size array.
+        * Also, check if device speed is fast enough.
+        */
+       rc = stk1160_scan_usb(interface, udev, alt_max_pkt_size);
+       if (rc < 0) {
+               kfree(alt_max_pkt_size);
+               return rc;
+       }
+
+       dev = kzalloc(sizeof(struct stk1160), GFP_KERNEL);
+       if (dev == NULL) {
+               kfree(alt_max_pkt_size);
+               return -ENOMEM;
+       }
+
+       dev->alt_max_pkt_size = alt_max_pkt_size;
+       dev->udev = udev;
+       dev->num_alt = interface->num_altsetting;
+       dev->ctl_input = input;
+
+       /* We save struct device for debug purposes only */
+       dev->dev = &interface->dev;
+
+       usb_set_intfdata(interface, dev);
+
+       /* initialize videobuf2 stuff */
+       rc = stk1160_vb2_setup(dev);
+       if (rc < 0)
+               goto free_err;
+
+       /*
+        * There is no need to take any locks here in probe
+        * because we register the device node as the *last* thing.
+        */
+       spin_lock_init(&dev->buf_lock);
+       mutex_init(&dev->v4l_lock);
+       mutex_init(&dev->vb_queue_lock);
+
+       rc = v4l2_ctrl_handler_init(&dev->ctrl_handler, 0);
+       if (rc) {
+               stk1160_err("v4l2_ctrl_handler_init failed (%d)\n", rc);
+               goto free_err;
+       }
+
+       /*
+        * We obtain a v4l2_dev but defer
+        * registration of video device node as the last thing.
+        * There is no need to set the name if we give a device struct
+        */
+       dev->v4l2_dev.release = stk1160_release;
+       dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler;
+       rc = v4l2_device_register(dev->dev, &dev->v4l2_dev);
+       if (rc) {
+               stk1160_err("v4l2_device_register failed (%d)\n", rc);
+               goto free_ctrl;
+       }
+
+       rc = stk1160_i2c_register(dev);
+       if (rc < 0)
+               goto unreg_v4l2;
+
+       /*
+        * To the best of my knowledge stk1160 boards only have
+        * saa7113, but it doesn't hurt to support them all.
+        */
+       dev->sd_saa7115 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+               "saa7115_auto", 0, saa7113_addrs);
+
+       stk1160_info("driver ver %s successfully loaded\n",
+               STK1160_VERSION);
+
+       /* i2c reset saa711x */
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0);
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
+                               0, 0, 0);
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
+
+       /* reset stk1160 to default values */
+       stk1160_reg_reset(dev);
+
+       /* select default input */
+       stk1160_select_input(dev);
+
+       stk1160_ac97_register(dev);
+
+       rc = stk1160_video_register(dev);
+       if (rc < 0)
+               goto unreg_i2c;
+
+       return 0;
+
+unreg_i2c:
+       stk1160_i2c_unregister(dev);
+unreg_v4l2:
+       v4l2_device_unregister(&dev->v4l2_dev);
+free_ctrl:
+       v4l2_ctrl_handler_free(&dev->ctrl_handler);
+free_err:
+       kfree(alt_max_pkt_size);
+       kfree(dev);
+
+       return rc;
+}
+
+static void stk1160_disconnect(struct usb_interface *interface)
+{
+       struct stk1160 *dev;
+
+       dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+
+       /*
+        * Wait until all current v4l2 operation are finished
+        * then deallocate resources
+        */
+       mutex_lock(&dev->vb_queue_lock);
+       mutex_lock(&dev->v4l_lock);
+
+       /* Here is the only place where isoc get released */
+       stk1160_uninit_isoc(dev);
+
+       /* ac97 unregister needs to be done before usb_device is cleared */
+       stk1160_ac97_unregister(dev);
+
+       stk1160_clear_queue(dev);
+
+       video_unregister_device(&dev->vdev);
+       v4l2_device_disconnect(&dev->v4l2_dev);
+
+       /* This way current users can detect device is gone */
+       dev->udev = NULL;
+
+       mutex_unlock(&dev->v4l_lock);
+       mutex_unlock(&dev->vb_queue_lock);
+
+       /*
+        * This calls stk1160_release if it's the last reference.
+        * therwise, release is posponed until there are no users left.
+        */
+       v4l2_device_put(&dev->v4l2_dev);
+}
+
+static struct usb_driver stk1160_usb_driver = {
+       .name = "stk1160",
+       .id_table = stk1160_id_table,
+       .probe = stk1160_probe,
+       .disconnect = stk1160_disconnect,
+};
+
+module_usb_driver(stk1160_usb_driver);
diff --git a/drivers/media/usb/stk1160/stk1160-i2c.c b/drivers/media/usb/stk1160/stk1160-i2c.c
new file mode 100644 (file)
index 0000000..176ac93
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * STK1160 driver
+ *
+ * Copyright (C) 2012 Ezequiel Garcia
+ * <elezegarcia--a.t--gmail.com>
+ *
+ * Based on Easycap driver by R.M. Thomas
+ *     Copyright (C) 2010 R.M. Thomas
+ *     <rmthomas--a.t--sciolus.org>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+
+#include "stk1160.h"
+#include "stk1160-reg.h"
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+#define dprintk_i2c(fmt, args...)                              \
+do {                                                           \
+       if (i2c_debug)                                          \
+               printk(KERN_DEBUG fmt, ##args);                 \
+} while (0)
+
+static int stk1160_i2c_busy_wait(struct stk1160 *dev, u8 wait_bit_mask)
+{
+       unsigned long end;
+       u8 flag;
+
+       /* Wait until read/write finish bit is set */
+       end = jiffies + msecs_to_jiffies(STK1160_I2C_TIMEOUT);
+       while (time_is_after_jiffies(end)) {
+
+               stk1160_read_reg(dev, STK1160_SICTL+1, &flag);
+               /* read/write done? */
+               if (flag & wait_bit_mask)
+                       goto done;
+
+               usleep_range(10 * USEC_PER_MSEC, 20 * USEC_PER_MSEC);
+       }
+
+       return -ETIMEDOUT;
+
+done:
+       return 0;
+}
+
+static int stk1160_i2c_write_reg(struct stk1160 *dev, u8 addr,
+               u8 reg, u8 value)
+{
+       int rc;
+
+       /* Set serial device address */
+       rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
+       if (rc < 0)
+               return rc;
+
+       /* Set i2c device register sub-address */
+       rc = stk1160_write_reg(dev, STK1160_SBUSW_WA, reg);
+       if (rc < 0)
+               return rc;
+
+       /* Set i2c device register value */
+       rc = stk1160_write_reg(dev, STK1160_SBUSW_WD, value);
+       if (rc < 0)
+               return rc;
+
+       /* Start write now */
+       rc = stk1160_write_reg(dev, STK1160_SICTL, 0x01);
+       if (rc < 0)
+               return rc;
+
+       rc = stk1160_i2c_busy_wait(dev, 0x04);
+       if (rc < 0)
+               return rc;
+
+       return 0;
+}
+
+static int stk1160_i2c_read_reg(struct stk1160 *dev, u8 addr,
+               u8 reg, u8 *value)
+{
+       int rc;
+
+       /* Set serial device address */
+       rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
+       if (rc < 0)
+               return rc;
+
+       /* Set i2c device register sub-address */
+       rc = stk1160_write_reg(dev, STK1160_SBUSR_RA, reg);
+       if (rc < 0)
+               return rc;
+
+       /* Start read now */
+       rc = stk1160_write_reg(dev, STK1160_SICTL, 0x20);
+       if (rc < 0)
+               return rc;
+
+       rc = stk1160_i2c_busy_wait(dev, 0x01);
+       if (rc < 0)
+               return rc;
+
+       stk1160_read_reg(dev, STK1160_SBUSR_RD, value);
+       if (rc < 0)
+               return rc;
+
+       return 0;
+}
+
+/*
+ * stk1160_i2c_check_for_device()
+ * check if there is a i2c_device at the supplied address
+ */
+static int stk1160_i2c_check_for_device(struct stk1160 *dev,
+               unsigned char addr)
+{
+       int rc;
+
+       /* Set serial device address */
+       rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
+       if (rc < 0)
+               return rc;
+
+       /* Set device sub-address, we'll chip version reg */
+       rc = stk1160_write_reg(dev, STK1160_SBUSR_RA, 0x00);
+       if (rc < 0)
+               return rc;
+
+       /* Start read now */
+       rc = stk1160_write_reg(dev, STK1160_SICTL, 0x20);
+       if (rc < 0)
+               return rc;
+
+       rc = stk1160_i2c_busy_wait(dev, 0x01);
+       if (rc < 0)
+               return -ENODEV;
+
+       return 0;
+}
+
+/*
+ * stk1160_i2c_xfer()
+ * the main i2c transfer function
+ */
+static int stk1160_i2c_xfer(struct i2c_adapter *i2c_adap,
+                          struct i2c_msg msgs[], int num)
+{
+       struct stk1160 *dev = i2c_adap->algo_data;
+       int addr, rc, i;
+
+       for (i = 0; i < num; i++) {
+               addr = msgs[i].addr << 1;
+               dprintk_i2c("%s: addr=%x", __func__, addr);
+
+               if (!msgs[i].len) {
+                       /* no len: check only for device presence */
+                       rc = stk1160_i2c_check_for_device(dev, addr);
+                       if (rc < 0) {
+                               dprintk_i2c(" no device\n");
+                               return rc;
+                       }
+
+               } else if (msgs[i].flags & I2C_M_RD) {
+                       /* read request without preceding register selection */
+                       dprintk_i2c(" subaddr not selected");
+                       rc = -EOPNOTSUPP;
+                       goto err;
+
+               } else if (i + 1 < num && msgs[i].len <= 2 &&
+                          (msgs[i + 1].flags & I2C_M_RD) &&
+                          msgs[i].addr == msgs[i + 1].addr) {
+
+                       if (msgs[i].len != 1 || msgs[i + 1].len != 1) {
+                               dprintk_i2c(" len not supported");
+                               rc = -EOPNOTSUPP;
+                               goto err;
+                       }
+
+                       dprintk_i2c(" subaddr=%x", msgs[i].buf[0]);
+
+                       rc = stk1160_i2c_read_reg(dev, addr, msgs[i].buf[0],
+                               msgs[i + 1].buf);
+
+                       dprintk_i2c(" read=%x", *msgs[i + 1].buf);
+
+                       /* consumed two msgs, so we skip one of them */
+                       i++;
+
+               } else {
+                       if (msgs[i].len != 2) {
+                               dprintk_i2c(" len not supported");
+                               rc = -EOPNOTSUPP;
+                               goto err;
+                       }
+
+                       dprintk_i2c(" subaddr=%x write=%x",
+                               msgs[i].buf[0],  msgs[i].buf[1]);
+
+                       rc = stk1160_i2c_write_reg(dev, addr, msgs[i].buf[0],
+                               msgs[i].buf[1]);
+               }
+
+               if (rc < 0)
+                       goto err;
+               dprintk_i2c(" OK\n");
+       }
+
+       return num;
+err:
+       dprintk_i2c(" ERROR: %d\n", rc);
+       return num;
+}
+
+/*
+ * functionality(), what da heck is this?
+ */
+static u32 functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm algo = {
+       .master_xfer   = stk1160_i2c_xfer,
+       .functionality = functionality,
+};
+
+static struct i2c_adapter adap_template = {
+       .owner = THIS_MODULE,
+       .name = "stk1160",
+       .algo = &algo,
+};
+
+static struct i2c_client client_template = {
+       .name = "stk1160 internal",
+};
+
+/*
+ * stk1160_i2c_register()
+ * register i2c bus
+ */
+int stk1160_i2c_register(struct stk1160 *dev)
+{
+       int rc;
+
+       dev->i2c_adap = adap_template;
+       dev->i2c_adap.dev.parent = dev->dev;
+       strcpy(dev->i2c_adap.name, "stk1160");
+       dev->i2c_adap.algo_data = dev;
+
+       i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
+
+       rc = i2c_add_adapter(&dev->i2c_adap);
+       if (rc < 0) {
+               stk1160_err("cannot add i2c adapter (%d)\n", rc);
+               return rc;
+       }
+
+       dev->i2c_client = client_template;
+       dev->i2c_client.adapter = &dev->i2c_adap;
+
+       /* Set i2c clock divider device address */
+       stk1160_write_reg(dev, STK1160_SICTL_CD,  0x0f);
+
+       /* ??? */
+       stk1160_write_reg(dev, STK1160_ASIC + 3,  0x00);
+
+       return 0;
+}
+
+/*
+ * stk1160_i2c_unregister()
+ * unregister i2c_bus
+ */
+int stk1160_i2c_unregister(struct stk1160 *dev)
+{
+       i2c_del_adapter(&dev->i2c_adap);
+       return 0;
+}
diff --git a/drivers/media/usb/stk1160/stk1160-reg.h b/drivers/media/usb/stk1160/stk1160-reg.h
new file mode 100644 (file)
index 0000000..3e49da6
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * STK1160 driver
+ *
+ * Copyright (C) 2012 Ezequiel Garcia
+ * <elezegarcia--a.t--gmail.com>
+ *
+ * Based on Easycap driver by R.M. Thomas
+ *     Copyright (C) 2010 R.M. Thomas
+ *     <rmthomas--a.t--sciolus.org>
+ *
+ * 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.
+ *
+ */
+
+/* GPIO Control */
+#define STK1160_GCTRL                  0x000
+
+/* Remote Wakup Control */
+#define STK1160_RMCTL                  0x00c
+
+/*
+ * Decoder Control Register:
+ * This byte controls capture start/stop
+ * with bit #7 (0x?? OR 0x80 to activate).
+ */
+#define STK1160_DCTRL                  0x100
+
+/* Capture Frame Start Position */
+#define STK116_CFSPO                   0x110
+#define STK116_CFSPO_STX_L             0x110
+#define STK116_CFSPO_STX_H             0x111
+#define STK116_CFSPO_STY_L             0x112
+#define STK116_CFSPO_STY_H             0x113
+
+/* Capture Frame End Position */
+#define STK116_CFEPO                   0x114
+#define STK116_CFEPO_ENX_L             0x114
+#define STK116_CFEPO_ENX_H             0x115
+#define STK116_CFEPO_ENY_L             0x116
+#define STK116_CFEPO_ENY_H             0x117
+
+/* Serial Interface Control  */
+#define STK1160_SICTL                  0x200
+#define STK1160_SICTL_CD               0x202
+#define STK1160_SICTL_SDA              0x203
+
+/* Serial Bus Write */
+#define STK1160_SBUSW                  0x204
+#define STK1160_SBUSW_WA               0x204
+#define STK1160_SBUSW_WD               0x205
+
+/* Serial Bus Read */
+#define STK1160_SBUSR                  0x208
+#define STK1160_SBUSR_RA               0x208
+#define STK1160_SBUSR_RD               0x209
+
+/* Alternate Serial Inteface Control */
+#define STK1160_ASIC                   0x2fc
+
+/* PLL Select Options */
+#define STK1160_PLLSO                  0x018
+
+/* PLL Frequency Divider */
+#define STK1160_PLLFD                  0x01c
+
+/* Timing Generator */
+#define STK1160_TIGEN                  0x300
+
+/* Timing Control Parameter */
+#define STK1160_TICTL                  0x350
+
+/* AC97 Audio Control */
+#define STK1160_AC97CTL_0              0x500
+#define STK1160_AC97CTL_1              0x504
+
+/* Use [0:6] bits of register 0x504 to set codec command address */
+#define STK1160_AC97_ADDR              0x504
+/* Use [16:31] bits of register 0x500 to set codec command data */
+#define STK1160_AC97_CMD               0x502
+
+/* Audio I2S Interface */
+#define STK1160_I2SCTL                 0x50c
+
+/* EEPROM Interface */
+#define STK1160_EEPROM_SZ              0x5f0
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
new file mode 100644 (file)
index 0000000..360bdbe
--- /dev/null
@@ -0,0 +1,738 @@
+/*
+ * STK1160 driver
+ *
+ * Copyright (C) 2012 Ezequiel Garcia
+ * <elezegarcia--a.t--gmail.com>
+ *
+ * Based on Easycap driver by R.M. Thomas
+ *     Copyright (C) 2010 R.M. Thomas
+ *     <rmthomas--a.t--sciolus.org>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/videobuf2-vmalloc.h>
+
+#include <media/saa7115.h>
+
+#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");
+
+/* supported video standards */
+static struct stk1160_fmt format[] = {
+       {
+               .name     = "16 bpp YUY2, 4:2:2, packed",
+               .fourcc   = V4L2_PIX_FMT_UYVY,
+               .depth    = 16,
+       }
+};
+
+static void stk1160_set_std(struct stk1160 *dev)
+{
+       int i;
+
+       static struct regval std525[] = {
+
+               /* 720x480 */
+
+               /* Frame start */
+               {STK116_CFSPO_STX_L, 0x0000},
+               {STK116_CFSPO_STX_H, 0x0000},
+               {STK116_CFSPO_STY_L, 0x0003},
+               {STK116_CFSPO_STY_H, 0x0000},
+
+               /* Frame end */
+               {STK116_CFEPO_ENX_L, 0x05a0},
+               {STK116_CFEPO_ENX_H, 0x0005},
+               {STK116_CFEPO_ENY_L, 0x00f3},
+               {STK116_CFEPO_ENY_H, 0x0000},
+
+               {0xffff, 0xffff}
+       };
+
+       static struct regval std625[] = {
+
+               /* 720x576 */
+
+               /* TODO: Each line of frame has some junk at the end */
+               /* Frame start */
+               {STK116_CFSPO,   0x0000},
+               {STK116_CFSPO+1, 0x0000},
+               {STK116_CFSPO+2, 0x0001},
+               {STK116_CFSPO+3, 0x0000},
+
+               /* Frame end */
+               {STK116_CFEPO,   0x05a0},
+               {STK116_CFEPO+1, 0x0005},
+               {STK116_CFEPO+2, 0x0121},
+               {STK116_CFEPO+3, 0x0001},
+
+               {0xffff, 0xffff}
+       };
+
+       if (dev->norm & V4L2_STD_525_60) {
+               stk1160_dbg("registers to NTSC like standard\n");
+               for (i = 0; std525[i].reg != 0xffff; i++)
+                       stk1160_write_reg(dev, std525[i].reg, std525[i].val);
+       } else {
+               stk1160_dbg("registers to PAL like standard\n");
+               for (i = 0; std625[i].reg != 0xffff; i++)
+                       stk1160_write_reg(dev, std625[i].reg, std625[i].val);
+       }
+
+}
+
+/*
+ * Set a new alternate setting.
+ * Returns true is dev->max_pkt_size has changed, false otherwise.
+ */
+static bool stk1160_set_alternate(struct stk1160 *dev)
+{
+       int i, prev_alt = dev->alt;
+       unsigned int min_pkt_size;
+       bool new_pkt_size;
+
+       /*
+        * If we don't set right alternate,
+        * then we will get a green screen with junk.
+        */
+       min_pkt_size = STK1160_MIN_PKT_SIZE;
+
+       for (i = 0; i < dev->num_alt; i++) {
+               /* stop when the selected alt setting offers enough bandwidth */
+               if (dev->alt_max_pkt_size[i] >= min_pkt_size) {
+                       dev->alt = i;
+                       break;
+               /*
+                * otherwise make sure that we end up with the maximum bandwidth
+                * because the min_pkt_size equation might be wrong...
+                */
+               } else if (dev->alt_max_pkt_size[i] >
+                          dev->alt_max_pkt_size[dev->alt])
+                       dev->alt = i;
+       }
+
+       stk1160_info("setting alternate %d\n", dev->alt);
+
+       if (dev->alt != prev_alt) {
+               stk1160_dbg("minimum isoc packet size: %u (alt=%d)\n",
+                               min_pkt_size, dev->alt);
+               stk1160_dbg("setting alt %d with wMaxPacketSize=%u\n",
+                              dev->alt, dev->alt_max_pkt_size[dev->alt]);
+               usb_set_interface(dev->udev, 0, dev->alt);
+       }
+
+       new_pkt_size = dev->max_pkt_size != dev->alt_max_pkt_size[dev->alt];
+       dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
+
+       return new_pkt_size;
+}
+
+static int stk1160_start_streaming(struct stk1160 *dev)
+{
+       int i, rc;
+       bool new_pkt_size;
+
+       /* Check device presence */
+       if (!dev->udev)
+               return -ENODEV;
+
+       if (mutex_lock_interruptible(&dev->v4l_lock))
+               return -ERESTARTSYS;
+       /*
+        * For some reason it is mandatory to set alternate *first*
+        * and only *then* initialize isoc urbs.
+        * Someone please explain me why ;)
+        */
+       new_pkt_size = stk1160_set_alternate(dev);
+
+       /*
+        * We (re)allocate isoc urbs if:
+        * there is no allocated isoc urbs, OR
+        * a new dev->max_pkt_size is detected
+        */
+       if (!dev->isoc_ctl.num_bufs || new_pkt_size) {
+               rc = stk1160_alloc_isoc(dev);
+               if (rc < 0)
+                       return rc;
+       }
+
+       /* 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_KERNEL);
+               if (rc) {
+                       stk1160_err("cannot submit urb[%d] (%d)\n", i, rc);
+                       stk1160_uninit_isoc(dev);
+                       return rc;
+               }
+       }
+
+       /* Start saa711x */
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
+
+       /* Start stk1160 */
+       stk1160_write_reg(dev, STK1160_DCTRL, 0xb3);
+       stk1160_write_reg(dev, STK1160_DCTRL+3, 0x00);
+
+       stk1160_dbg("streaming started\n");
+
+       mutex_unlock(&dev->v4l_lock);
+
+       return 0;
+}
+
+/* Must be called with v4l_lock hold */
+static void stk1160_stop_hw(struct stk1160 *dev)
+{
+       /* If the device is not physically present, there is nothing to do */
+       if (!dev->udev)
+               return;
+
+       /* set alternate 0 */
+       dev->alt = 0;
+       stk1160_info("setting alternate %d\n", dev->alt);
+       usb_set_interface(dev->udev, 0, 0);
+
+       /* Stop stk1160 */
+       stk1160_write_reg(dev, STK1160_DCTRL, 0x00);
+       stk1160_write_reg(dev, STK1160_DCTRL+3, 0x00);
+
+       /* Stop saa711x */
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
+}
+
+static int stk1160_stop_streaming(struct stk1160 *dev)
+{
+       if (mutex_lock_interruptible(&dev->v4l_lock))
+               return -ERESTARTSYS;
+
+       stk1160_cancel_isoc(dev);
+
+       /*
+        * It is possible to keep buffers around using a module parameter.
+        * This is intended to avoid memory fragmentation.
+        */
+       if (!keep_buffers)
+               stk1160_free_isoc(dev);
+
+       stk1160_stop_hw(dev);
+
+       stk1160_clear_queue(dev);
+
+       stk1160_dbg("streaming stopped\n");
+
+       mutex_unlock(&dev->v4l_lock);
+
+       return 0;
+}
+
+static struct v4l2_file_operations stk1160_fops = {
+       .owner = THIS_MODULE,
+       .open = v4l2_fh_open,
+       .release = vb2_fop_release,
+       .read = vb2_fop_read,
+       .poll = vb2_fop_poll,
+       .mmap = vb2_fop_mmap,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+/*
+ * vidioc ioctls
+ */
+static int vidioc_querycap(struct file *file,
+               void *priv, struct v4l2_capability *cap)
+{
+       struct stk1160 *dev = video_drvdata(file);
+
+       strcpy(cap->driver, "stk1160");
+       strcpy(cap->card, "stk1160");
+       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
+       cap->device_caps =
+               V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_STREAMING |
+               V4L2_CAP_READWRITE;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+               struct v4l2_fmtdesc *f)
+{
+       if (f->index != 0)
+               return -EINVAL;
+
+       strlcpy(f->description, format[f->index].name, sizeof(f->description));
+       f->pixelformat = format[f->index].fourcc;
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct stk1160 *dev = video_drvdata(file);
+
+       f->fmt.pix.width = dev->width;
+       f->fmt.pix.height = dev->height;
+       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+       f->fmt.pix.pixelformat = dev->fmt->fourcc;
+       f->fmt.pix.bytesperline = dev->width * 2;
+       f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                       struct v4l2_format *f)
+{
+       struct stk1160 *dev = video_drvdata(file);
+
+       if (f->fmt.pix.pixelformat != format[0].fourcc) {
+               stk1160_err("fourcc format 0x%08x invalid\n",
+                       f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       /*
+        * User can't choose size at his own will,
+        * so we just return him the current size chosen
+        * at standard selection.
+        * TODO: Implement frame scaling?
+        */
+
+       f->fmt.pix.width = dev->width;
+       f->fmt.pix.height = dev->height;
+       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+       f->fmt.pix.bytesperline = dev->width * 2;
+       f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct stk1160 *dev = video_drvdata(file);
+       struct vb2_queue *q = &dev->vb_vidq;
+       int rc;
+
+       if (vb2_is_busy(q))
+               return -EBUSY;
+
+       rc = vidioc_try_fmt_vid_cap(file, priv, f);
+       if (rc < 0)
+               return rc;
+
+       /* We don't support any format changes */
+
+       return 0;
+}
+
+static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       struct stk1160 *dev = video_drvdata(file);
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm);
+       return 0;
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       struct stk1160 *dev = video_drvdata(file);
+
+       *norm = dev->norm;
+       return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       struct stk1160 *dev = video_drvdata(file);
+       struct vb2_queue *q = &dev->vb_vidq;
+
+       if (vb2_is_busy(q))
+               return -EBUSY;
+
+       /* Check device presence */
+       if (!dev->udev)
+               return -ENODEV;
+
+       /* We need to set this now, before we call stk1160_set_std */
+       dev->norm = *norm;
+
+       /* This is taken from saa7115 video decoder */
+       if (dev->norm & V4L2_STD_525_60) {
+               dev->width = 720;
+               dev->height = 480;
+       } else if (dev->norm & V4L2_STD_625_50) {
+               dev->width = 720;
+               dev->height = 576;
+       } else {
+               stk1160_err("invalid standard\n");
+               return -EINVAL;
+       }
+
+       stk1160_set_std(dev);
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std,
+                       dev->norm);
+
+       return 0;
+}
+
+
+static int vidioc_enum_input(struct file *file, void *priv,
+                               struct v4l2_input *i)
+{
+       struct stk1160 *dev = video_drvdata(file);
+
+       if (i->index > STK1160_MAX_INPUT)
+               return -EINVAL;
+
+       sprintf(i->name, "Composite%d", i->index);
+       i->type = V4L2_INPUT_TYPE_CAMERA;
+       i->std = dev->vdev.tvnorms;
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct stk1160 *dev = video_drvdata(file);
+       *i = dev->ctl_input;
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       struct stk1160 *dev = video_drvdata(file);
+
+       if (vb2_is_busy(&dev->vb_vidq))
+               return -EBUSY;
+
+       if (i > STK1160_MAX_INPUT)
+               return -EINVAL;
+
+       dev->ctl_input = i;
+
+       stk1160_select_input(dev);
+
+       return 0;
+}
+
+static int vidioc_g_chip_ident(struct file *file, void *priv,
+              struct v4l2_dbg_chip_ident *chip)
+{
+       switch (chip->match.type) {
+       case V4L2_CHIP_MATCH_HOST:
+               chip->ident = V4L2_IDENT_NONE;
+               chip->revision = 0;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register(struct file *file, void *priv,
+                            struct v4l2_dbg_register *reg)
+{
+       struct stk1160 *dev = video_drvdata(file);
+       int rc;
+       u8 val;
+
+       switch (reg->match.type) {
+       case V4L2_CHIP_MATCH_AC97:
+               /* TODO: Support me please :-( */
+               return -EINVAL;
+       case V4L2_CHIP_MATCH_I2C_DRIVER:
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
+               return 0;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               /* TODO: is this correct? */
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
+               return 0;
+       default:
+               if (!v4l2_chip_match_host(&reg->match))
+                       return -EINVAL;
+       }
+
+       /* Match host */
+       rc = stk1160_read_reg(dev, reg->reg, &val);
+       reg->val = val;
+       reg->size = 1;
+
+       return rc;
+}
+
+static int vidioc_s_register(struct file *file, void *priv,
+                            struct v4l2_dbg_register *reg)
+{
+       struct stk1160 *dev = video_drvdata(file);
+
+       switch (reg->match.type) {
+       case V4L2_CHIP_MATCH_AC97:
+               return -EINVAL;
+       case V4L2_CHIP_MATCH_I2C_DRIVER:
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
+               return 0;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               /* TODO: is this correct? */
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
+               return 0;
+       default:
+               if (!v4l2_chip_match_host(&reg->match))
+                       return -EINVAL;
+       }
+
+       /* Match host */
+       return stk1160_write_reg(dev, reg->reg, cpu_to_le16(reg->val));
+}
+#endif
+
+static const struct v4l2_ioctl_ops stk1160_ioctl_ops = {
+       .vidioc_querycap      = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
+       .vidioc_querystd      = vidioc_querystd,
+       .vidioc_g_std         = vidioc_g_std,
+       .vidioc_s_std         = vidioc_s_std,
+       .vidioc_enum_input    = vidioc_enum_input,
+       .vidioc_g_input       = vidioc_g_input,
+       .vidioc_s_input       = vidioc_s_input,
+
+       /* vb2 takes care of these */
+       .vidioc_reqbufs       = vb2_ioctl_reqbufs,
+       .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,
+       .vidioc_g_chip_ident = vidioc_g_chip_ident,
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register = vidioc_g_register,
+       .vidioc_s_register = vidioc_s_register,
+#endif
+};
+
+/********************************************************************/
+
+/*
+ * Videobuf2 operations
+ */
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *v4l_fmt,
+                               unsigned int *nbuffers, unsigned int *nplanes,
+                               unsigned int sizes[], void *alloc_ctxs[])
+{
+       struct stk1160 *dev = vb2_get_drv_priv(vq);
+       unsigned long size;
+
+       size = dev->width * dev->height * 2;
+
+       /*
+        * Here we can change the number of buffers being requested.
+        * So, we set a minimum and a maximum like this:
+        */
+       *nbuffers = clamp_t(unsigned int, *nbuffers,
+                       STK1160_MIN_VIDEO_BUFFERS, STK1160_MAX_VIDEO_BUFFERS);
+
+       /* This means a packed colorformat */
+       *nplanes = 1;
+
+       sizes[0] = size;
+
+       stk1160_info("%s: buffer count %d, each %ld bytes\n",
+                       __func__, *nbuffers, size);
+
+       return 0;
+}
+
+static void buffer_queue(struct vb2_buffer *vb)
+{
+       unsigned long flags;
+       struct stk1160 *dev = vb2_get_drv_priv(vb->vb2_queue);
+       struct stk1160_buffer *buf =
+               container_of(vb, struct stk1160_buffer, vb);
+
+       spin_lock_irqsave(&dev->buf_lock, flags);
+       if (!dev->udev) {
+               /*
+                * If the device is disconnected return the buffer to userspace
+                * directly. The next QBUF call will fail with -ENODEV.
+                */
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+       } else {
+
+               buf->mem = vb2_plane_vaddr(vb, 0);
+               buf->length = vb2_plane_size(vb, 0);
+               buf->bytesused = 0;
+               buf->pos = 0;
+
+               /*
+                * If buffer length is less from expected then we return
+                * the buffer to userspace directly.
+                */
+               if (buf->length < dev->width * dev->height * 2)
+                       vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+               else
+                       list_add_tail(&buf->list, &dev->avail_bufs);
+
+       }
+       spin_unlock_irqrestore(&dev->buf_lock, flags);
+}
+
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+       struct stk1160 *dev = vb2_get_drv_priv(vq);
+       return stk1160_start_streaming(dev);
+}
+
+/* abort streaming and wait for last buffer */
+static int stop_streaming(struct vb2_queue *vq)
+{
+       struct stk1160 *dev = vb2_get_drv_priv(vq);
+       return stk1160_stop_streaming(dev);
+}
+
+static struct vb2_ops stk1160_video_qops = {
+       .queue_setup            = queue_setup,
+       .buf_queue              = buffer_queue,
+       .start_streaming        = start_streaming,
+       .stop_streaming         = stop_streaming,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
+};
+
+static struct video_device v4l_template = {
+       .name = "stk1160",
+       .tvnorms = V4L2_STD_525_60 | V4L2_STD_625_50,
+       .fops = &stk1160_fops,
+       .ioctl_ops = &stk1160_ioctl_ops,
+       .release = video_device_release_empty,
+};
+
+/********************************************************************/
+
+/* Must be called with both v4l_lock and vb_queue_lock hold */
+void stk1160_clear_queue(struct stk1160 *dev)
+{
+       struct stk1160_buffer *buf;
+       unsigned long flags;
+
+       /* Release all active buffers */
+       spin_lock_irqsave(&dev->buf_lock, flags);
+       while (!list_empty(&dev->avail_bufs)) {
+               buf = list_first_entry(&dev->avail_bufs,
+                       struct stk1160_buffer, list);
+               list_del(&buf->list);
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+               stk1160_info("buffer [%p/%d] aborted\n",
+                               buf, buf->vb.v4l2_buf.index);
+       }
+       /* It's important to clear current buffer */
+       dev->isoc_ctl.buf = NULL;
+       spin_unlock_irqrestore(&dev->buf_lock, flags);
+}
+
+int stk1160_vb2_setup(struct stk1160 *dev)
+{
+       int rc;
+       struct vb2_queue *q;
+
+       q = &dev->vb_vidq;
+       memset(q, 0, sizeof(dev->vb_vidq));
+       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
+       q->drv_priv = dev;
+       q->buf_struct_size = sizeof(struct stk1160_buffer);
+       q->ops = &stk1160_video_qops;
+       q->mem_ops = &vb2_vmalloc_memops;
+
+       rc = vb2_queue_init(q);
+       if (rc < 0)
+               return rc;
+
+       /* initialize video dma queue */
+       INIT_LIST_HEAD(&dev->avail_bufs);
+
+       return 0;
+}
+
+int stk1160_video_register(struct stk1160 *dev)
+{
+       int rc;
+
+       /* Initialize video_device with a template structure */
+       dev->vdev = v4l_template;
+       dev->vdev.debug = vidioc_debug;
+       dev->vdev.queue = &dev->vb_vidq;
+
+       /*
+        * Provide mutexes for v4l2 core and for videobuf2 queue.
+        * It will be used to protect *only* v4l2 ioctls.
+        */
+       dev->vdev.lock = &dev->v4l_lock;
+       dev->vdev.queue->lock = &dev->vb_queue_lock;
+
+       /* This will be used to set video_device parent */
+       dev->vdev.v4l2_dev = &dev->v4l2_dev;
+       set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
+
+       /* NTSC is default */
+       dev->norm = V4L2_STD_NTSC_M;
+       dev->width = 720;
+       dev->height = 480;
+
+       /* set default format */
+       dev->fmt = &format[0];
+       stk1160_set_std(dev);
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std,
+                       dev->norm);
+
+       video_set_drvdata(&dev->vdev, dev);
+       rc = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
+       if (rc < 0) {
+               stk1160_err("video_register_device failed (%d)\n", rc);
+               return rc;
+       }
+
+       v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
+                 video_device_node_name(&dev->vdev));
+
+       return 0;
+}
diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c
new file mode 100644 (file)
index 0000000..3785269
--- /dev/null
@@ -0,0 +1,518 @@
+/*
+ * STK1160 driver
+ *
+ * Copyright (C) 2012 Ezequiel Garcia
+ * <elezegarcia--a.t--gmail.com>
+ *
+ * Based on Easycap driver by R.M. Thomas
+ *     Copyright (C) 2010 R.M. Thomas
+ *     <rmthomas--a.t--sciolus.org>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <linux/ratelimit.h>
+
+#include "stk1160.h"
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+static inline void print_err_status(struct stk1160 *dev,
+                                    int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+
+       if (packet < 0)
+               printk_ratelimited(KERN_WARNING "URB status %d [%s].\n",
+                               status, errmsg);
+       else
+               printk_ratelimited(KERN_INFO "URB packet %d, status %d [%s].\n",
+                              packet, status, errmsg);
+}
+
+static inline
+struct stk1160_buffer *stk1160_next_buffer(struct stk1160 *dev)
+{
+       struct stk1160_buffer *buf = NULL;
+       unsigned long flags = 0;
+
+       /* Current buffer must be NULL when this functions gets called */
+       BUG_ON(dev->isoc_ctl.buf);
+
+       spin_lock_irqsave(&dev->buf_lock, flags);
+       if (!list_empty(&dev->avail_bufs)) {
+               buf = list_first_entry(&dev->avail_bufs,
+                               struct stk1160_buffer, list);
+               list_del(&buf->list);
+       }
+       spin_unlock_irqrestore(&dev->buf_lock, flags);
+
+       return buf;
+}
+
+static inline
+void stk1160_buffer_done(struct stk1160 *dev)
+{
+       struct stk1160_buffer *buf = dev->isoc_ctl.buf;
+
+       dev->field_count++;
+
+       buf->vb.v4l2_buf.sequence = dev->field_count >> 1;
+       buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
+       buf->vb.v4l2_buf.bytesused = buf->bytesused;
+       do_gettimeofday(&buf->vb.v4l2_buf.timestamp);
+
+       vb2_set_plane_payload(&buf->vb, 0, buf->bytesused);
+       vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+
+       dev->isoc_ctl.buf = NULL;
+}
+
+static inline
+void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len)
+{
+       int linesdone, lineoff, lencopy;
+       int bytesperline = dev->width * 2;
+       struct stk1160_buffer *buf = dev->isoc_ctl.buf;
+       u8 *dst = buf->mem;
+       int remain;
+
+       /*
+        * TODO: These stk1160_dbg are very spammy!
+        * We should 1) check why we are getting them
+        * and 2) add ratelimit.
+        *
+        * UPDATE: One of the reasons (the only one?) for getting these
+        * is incorrect standard (mismatch between expected and configured).
+        * So perhaps, we could add a counter for errors. When the counter
+        * reaches some value, we simply stop streaming.
+        */
+
+       len -= 4;
+       src += 4;
+
+       remain = len;
+
+       linesdone = buf->pos / bytesperline;
+       lineoff = buf->pos % bytesperline; /* offset in current line */
+
+       if (!buf->odd)
+               dst += bytesperline;
+
+       /* Multiply linesdone by two, to take account of the other field */
+       dst += linesdone * bytesperline * 2 + lineoff;
+
+       /* Copy the remaining of current line */
+       if (remain < (bytesperline - lineoff))
+               lencopy = remain;
+       else
+               lencopy = bytesperline - lineoff;
+
+       /*
+        * Check if we have enough space left in the buffer.
+        * In that case, we force loop exit after copy.
+        */
+       if (lencopy > buf->bytesused - buf->length) {
+               lencopy = buf->bytesused - buf->length;
+               remain = lencopy;
+       }
+
+       /* Check if the copy is done */
+       if (lencopy == 0 || remain == 0)
+               return;
+
+       /* Let the bug hunt begin! sanity checks! */
+       if (lencopy < 0) {
+               stk1160_dbg("copy skipped: negative lencopy\n");
+               return;
+       }
+
+       if ((unsigned long)dst + lencopy >
+               (unsigned long)buf->mem + buf->length) {
+               printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n");
+               return;
+       }
+
+       memcpy(dst, src, lencopy);
+
+       buf->bytesused += lencopy;
+       buf->pos += lencopy;
+       remain -= lencopy;
+
+       /* Copy current field line by line, interlacing with the other field */
+       while (remain > 0) {
+
+               dst += lencopy + bytesperline;
+               src += lencopy;
+
+               /* Copy one line at a time */
+               if (remain < bytesperline)
+                       lencopy = remain;
+               else
+                       lencopy = bytesperline;
+
+               /*
+                * Check if we have enough space left in the buffer.
+                * In that case, we force loop exit after copy.
+                */
+               if (lencopy > buf->bytesused - buf->length) {
+                       lencopy = buf->bytesused - buf->length;
+                       remain = lencopy;
+               }
+
+               /* Check if the copy is done */
+               if (lencopy == 0 || remain == 0)
+                       return;
+
+               if (lencopy < 0) {
+                       printk_ratelimited(KERN_WARNING "stk1160: negative lencopy detected\n");
+                       return;
+               }
+
+               if ((unsigned long)dst + lencopy >
+                       (unsigned long)buf->mem + buf->length) {
+                       printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n");
+                       return;
+               }
+
+               memcpy(dst, src, lencopy);
+               remain -= lencopy;
+
+               buf->bytesused += lencopy;
+               buf->pos += lencopy;
+       }
+}
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static void stk1160_process_isoc(struct stk1160 *dev, struct urb *urb)
+{
+       int i, len, status;
+       u8 *p;
+
+       if (!dev) {
+               stk1160_warn("%s called with null device\n", __func__);
+               return;
+       }
+
+       if (urb->status < 0) {
+               /* Print status and drop current packet (or field?) */
+               print_err_status(dev, -1, urb->status);
+               return;
+       }
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               status = urb->iso_frame_desc[i].status;
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       continue;
+               }
+
+               /* Get packet actual length and pointer to data */
+               p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+               len = urb->iso_frame_desc[i].actual_length;
+
+               /* Empty packet */
+               if (len <= 4)
+                       continue;
+
+               /*
+                * An 8-byte packet sequence means end of field.
+                * So if we don't have any packet, we start receiving one now
+                * and if we do have a packet, then we are done with it.
+                *
+                * These end of field packets are always 0xc0 or 0x80,
+                * but not always 8-byte long so we don't check packet length.
+                */
+               if (p[0] == 0xc0) {
+
+                       /*
+                        * If first byte is 0xc0 then we received
+                        * second field, and frame has ended.
+                        */
+                       if (dev->isoc_ctl.buf != NULL)
+                               stk1160_buffer_done(dev);
+
+                       dev->isoc_ctl.buf = stk1160_next_buffer(dev);
+                       if (dev->isoc_ctl.buf == NULL)
+                               return;
+               }
+
+               /*
+                * If we don't have a buffer here, then it means we
+                * haven't found the start mark sequence.
+                */
+               if (dev->isoc_ctl.buf == NULL)
+                       continue;
+
+               if (p[0] == 0xc0 || p[0] == 0x80) {
+
+                       /* We set next packet parity and
+                        * continue to get next one
+                        */
+                       dev->isoc_ctl.buf->odd = *p & 0x40;
+                       dev->isoc_ctl.buf->pos = 0;
+                       continue;
+               }
+
+               stk1160_copy_video(dev, p, len);
+       }
+}
+
+
+/*
+ * IRQ callback, called by URB callback
+ */
+static void stk1160_isoc_irq(struct urb *urb)
+{
+       int i, rc;
+       struct stk1160 *dev = urb->context;
+
+       switch (urb->status) {
+       case 0:
+               break;
+       case -ECONNRESET:   /* kill */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* TODO: check uvc driver: he frees the queue here */
+               return;
+       default:
+               stk1160_err("urb error! status %d\n", urb->status);
+               return;
+       }
+
+       stk1160_process_isoc(dev, urb);
+
+       /* Reset urb buffers */
+       for (i = 0; i < urb->number_of_packets; i++) {
+               urb->iso_frame_desc[i].status = 0;
+               urb->iso_frame_desc[i].actual_length = 0;
+       }
+
+       rc = usb_submit_urb(urb, GFP_ATOMIC);
+       if (rc)
+               stk1160_err("urb re-submit failed (%d)\n", rc);
+}
+
+/*
+ * Cancel urbs
+ * This function can't be called in atomic context
+ */
+void stk1160_cancel_isoc(struct stk1160 *dev)
+{
+       int i;
+
+       /*
+        * This check is not necessary, but we add it
+        * to avoid a spurious debug message
+        */
+       if (!dev->isoc_ctl.num_bufs)
+               return;
+
+       stk1160_dbg("killing urbs...\n");
+
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+
+               /*
+                * To kill urbs we can't be in atomic context.
+                * We don't care for NULL pointer since
+                * usb_kill_urb allows it.
+                */
+               usb_kill_urb(dev->isoc_ctl.urb[i]);
+       }
+
+       stk1160_dbg("all urbs killed\n");
+}
+
+/*
+ * Releases urb and transfer buffers
+ * Obviusly, associated urb must be killed before releasing it.
+ */
+void stk1160_free_isoc(struct stk1160 *dev)
+{
+       struct urb *urb;
+       int i;
+
+       stk1160_dbg("freeing urb buffers...\n");
+
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+
+               urb = dev->isoc_ctl.urb[i];
+               if (urb) {
+
+                       if (dev->isoc_ctl.transfer_buffer[i]) {
+#ifndef CONFIG_DMA_NONCOHERENT
+                               usb_free_coherent(dev->udev,
+                                       urb->transfer_buffer_length,
+                                       dev->isoc_ctl.transfer_buffer[i],
+                                       urb->transfer_dma);
+#else
+                               kfree(dev->isoc_ctl.transfer_buffer[i]);
+#endif
+                       }
+                       usb_free_urb(urb);
+                       dev->isoc_ctl.urb[i] = NULL;
+               }
+               dev->isoc_ctl.transfer_buffer[i] = NULL;
+       }
+
+       kfree(dev->isoc_ctl.urb);
+       kfree(dev->isoc_ctl.transfer_buffer);
+
+       dev->isoc_ctl.urb = NULL;
+       dev->isoc_ctl.transfer_buffer = NULL;
+       dev->isoc_ctl.num_bufs = 0;
+
+       stk1160_dbg("all urb buffers freed\n");
+}
+
+/*
+ * Helper for cancelling and freeing urbs
+ * This function can't be called in atomic context
+ */
+void stk1160_uninit_isoc(struct stk1160 *dev)
+{
+       stk1160_cancel_isoc(dev);
+       stk1160_free_isoc(dev);
+}
+
+/*
+ * Allocate URBs
+ */
+int stk1160_alloc_isoc(struct stk1160 *dev)
+{
+       struct urb *urb;
+       int i, j, k, sb_size, max_packets, num_bufs;
+
+       /*
+        * It may be necessary to release isoc here,
+        * since isoc are only released on disconnection.
+        * (see new_pkt_size flag)
+        */
+       if (dev->isoc_ctl.num_bufs)
+               stk1160_uninit_isoc(dev);
+
+       stk1160_dbg("allocating urbs...\n");
+
+       num_bufs = STK1160_NUM_BUFS;
+       max_packets = STK1160_NUM_PACKETS;
+       sb_size = max_packets * dev->max_pkt_size;
+
+       dev->isoc_ctl.buf = NULL;
+       dev->isoc_ctl.max_pkt_size = dev->max_pkt_size;
+       dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
+       if (!dev->isoc_ctl.urb) {
+               stk1160_err("out of memory for urb array\n");
+               return -ENOMEM;
+       }
+
+       dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
+                                             GFP_KERNEL);
+       if (!dev->isoc_ctl.transfer_buffer) {
+               stk1160_err("out of memory for usb transfers\n");
+               kfree(dev->isoc_ctl.urb);
+               return -ENOMEM;
+       }
+
+       /* allocate urbs and transfer buffers */
+       for (i = 0; i < num_bufs; i++) {
+
+               urb = usb_alloc_urb(max_packets, GFP_KERNEL);
+               if (!urb) {
+                       stk1160_err("cannot alloc urb[%d]\n", i);
+                       stk1160_uninit_isoc(dev);
+                       return -ENOMEM;
+               }
+               dev->isoc_ctl.urb[i] = urb;
+
+#ifndef CONFIG_DMA_NONCOHERENT
+               dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev,
+                       sb_size, GFP_KERNEL, &urb->transfer_dma);
+#else
+               dev->isoc_ctl.transfer_buffer[i] = kmalloc(sb_size, GFP_KERNEL);
+#endif
+               if (!dev->isoc_ctl.transfer_buffer[i]) {
+                       stk1160_err("cannot alloc %d bytes for tx buffer\n",
+                               sb_size);
+                       stk1160_uninit_isoc(dev);
+                       return -ENOMEM;
+               }
+               memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
+
+               /*
+                * FIXME: Where can I get the endpoint?
+                */
+               urb->dev = dev->udev;
+               urb->pipe = usb_rcvisocpipe(dev->udev, STK1160_EP_VIDEO);
+               urb->transfer_buffer = dev->isoc_ctl.transfer_buffer[i];
+               urb->transfer_buffer_length = sb_size;
+               urb->complete = stk1160_isoc_irq;
+               urb->context = dev;
+               urb->interval = 1;
+               urb->start_frame = 0;
+               urb->number_of_packets = max_packets;
+#ifndef CONFIG_DMA_NONCOHERENT
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+#else
+               urb->transfer_flags = URB_ISO_ASAP;
+#endif
+
+               k = 0;
+               for (j = 0; j < max_packets; j++) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length =
+                                       dev->isoc_ctl.max_pkt_size;
+                       k += dev->isoc_ctl.max_pkt_size;
+               }
+       }
+
+       stk1160_dbg("urbs allocated\n");
+
+       /* At last we can say we have some buffers */
+       dev->isoc_ctl.num_bufs = num_bufs;
+
+       return 0;
+}
+
diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h
new file mode 100644 (file)
index 0000000..3feba00
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * STK1160 driver
+ *
+ * Copyright (C) 2012 Ezequiel Garcia
+ * <elezegarcia--a.t--gmail.com>
+ *
+ * Based on Easycap driver by R.M. Thomas
+ *     Copyright (C) 2010 R.M. Thomas
+ *     <rmthomas--a.t--sciolus.org>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <sound/core.h>
+#include <sound/ac97_codec.h>
+#include <media/videobuf2-core.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#define STK1160_VERSION                "0.9.5"
+#define STK1160_VERSION_NUM    0x000905
+
+/* TODO: Decide on number of packets for each buffer */
+#define STK1160_NUM_PACKETS 64
+
+/* Number of buffers for isoc transfers */
+#define STK1160_NUM_BUFS 16 /* TODO */
+
+/* TODO: This endpoint address should be retrieved */
+#define STK1160_EP_VIDEO 0x82
+#define STK1160_EP_AUDIO 0x81
+
+/* Max and min video buffers */
+#define STK1160_MIN_VIDEO_BUFFERS 8
+#define STK1160_MAX_VIDEO_BUFFERS 32
+
+#define STK1160_MIN_PKT_SIZE 3072
+
+#define STK1160_MAX_INPUT 3
+
+#define STK1160_I2C_TIMEOUT 100
+
+/* TODO: Print helpers
+ * I could use dev_xxx, pr_xxx, v4l2_xxx or printk.
+ * However, there isn't a solid consensus on which
+ * new drivers should use.
+ *
+ */
+#define DEBUG
+#ifdef DEBUG
+#define stk1160_dbg(fmt, args...) \
+       printk(KERN_DEBUG "stk1160: " fmt,  ## args)
+#else
+#define stk1160_dbg(fmt, args...)
+#endif
+
+#define stk1160_info(fmt, args...) \
+       pr_info("stk1160: " fmt, ## args)
+
+#define stk1160_warn(fmt, args...) \
+       pr_warn("stk1160: " fmt, ## args)
+
+#define stk1160_err(fmt, args...) \
+       pr_err("stk1160: " fmt, ## args)
+
+/* Buffer for one video frame */
+struct stk1160_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct vb2_buffer vb;
+       struct list_head list;
+
+       void *mem;
+       unsigned int length;            /* buffer length */
+       unsigned int bytesused;         /* bytes written */
+       int odd;                        /* current oddity */
+
+       /*
+        * Since we interlace two fields per frame,
+        * this is different from bytesused.
+        */
+       unsigned int pos;               /* current pos inside buffer */
+};
+
+struct stk1160_isoc_ctl {
+       /* max packet size of isoc transaction */
+       int max_pkt_size;
+
+       /* number of allocated urbs */
+       int num_bufs;
+
+       /* urb for isoc transfers */
+       struct urb **urb;
+
+       /* transfer buffers for isoc transfer */
+       char **transfer_buffer;
+
+       /* current buffer */
+       struct stk1160_buffer *buf;
+};
+
+struct stk1160_fmt {
+       char  *name;
+       u32   fourcc;          /* v4l2 format id */
+       int   depth;
+};
+
+struct stk1160 {
+       struct v4l2_device v4l2_dev;
+       struct video_device vdev;
+       struct v4l2_ctrl_handler ctrl_handler;
+
+       struct device *dev;
+       struct usb_device *udev;
+
+       /* saa7115 subdev */
+       struct v4l2_subdev *sd_saa7115;
+
+       /* isoc control struct */
+       struct list_head avail_bufs;
+
+       /* video capture */
+       struct vb2_queue vb_vidq;
+
+       /* max packet size of isoc transaction */
+       int max_pkt_size;
+       /* array of wMaxPacketSize */
+       unsigned int *alt_max_pkt_size;
+       /* alternate */
+       int alt;
+       /* Number of alternative settings */
+       int num_alt;
+
+       struct stk1160_isoc_ctl isoc_ctl;
+       char urb_buf[255];       /* urb control msg buffer */
+
+       /* frame properties */
+       int width;                /* current frame width */
+       int height;               /* current frame height */
+       unsigned int ctl_input;   /* selected input */
+       v4l2_std_id norm;         /* current norm */
+       struct stk1160_fmt *fmt;  /* selected format */
+
+       unsigned int field_count; /* not sure ??? */
+       enum v4l2_field field;    /* also not sure :/ */
+
+       /* i2c i/o */
+       struct i2c_adapter i2c_adap;
+       struct i2c_client i2c_client;
+
+       struct mutex v4l_lock;
+       struct mutex vb_queue_lock;
+       spinlock_t buf_lock;
+
+       struct file *fh_owner;  /* filehandle ownership */
+
+       /* EXPERIMENTAL */
+       struct snd_card *snd_card;
+};
+
+struct regval {
+       u16 reg;
+       u16 val;
+};
+
+/* Provided by stk1160-v4l.c */
+int stk1160_vb2_setup(struct stk1160 *dev);
+int stk1160_video_register(struct stk1160 *dev);
+void stk1160_video_unregister(struct stk1160 *dev);
+void stk1160_clear_queue(struct stk1160 *dev);
+
+/* Provided by stk1160-video.c */
+int stk1160_alloc_isoc(struct stk1160 *dev);
+void stk1160_free_isoc(struct stk1160 *dev);
+void stk1160_cancel_isoc(struct stk1160 *dev);
+void stk1160_uninit_isoc(struct stk1160 *dev);
+
+/* Provided by stk1160-i2c.c */
+int stk1160_i2c_register(struct stk1160 *dev);
+int stk1160_i2c_unregister(struct stk1160 *dev);
+
+/* Provided by stk1160-core.c */
+int stk1160_read_reg(struct stk1160 *dev, u16 reg, u8 *value);
+int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value);
+int stk1160_write_regs_req(struct stk1160 *dev, u8 req, u16 reg,
+               char *buf, int len);
+int stk1160_read_reg_req_len(struct stk1160 *dev, u8 req, u16 reg,
+               char *buf, int len);
+void stk1160_select_input(struct stk1160 *dev);
+
+/* Provided by stk1160-ac97.c */
+#ifdef CONFIG_VIDEO_STK1160_AC97
+int stk1160_ac97_register(struct stk1160 *dev);
+int stk1160_ac97_unregister(struct stk1160 *dev);
+#else
+static inline int stk1160_ac97_register(struct stk1160 *dev) { return 0; }
+static inline int stk1160_ac97_unregister(struct stk1160 *dev) { return 0; }
+#endif
+
diff --git a/drivers/media/usb/tlg2300/Kconfig b/drivers/media/usb/tlg2300/Kconfig
new file mode 100644 (file)
index 0000000..645d915
--- /dev/null
@@ -0,0 +1,16 @@
+config VIDEO_TLG2300
+       tristate "Telegent TLG2300 USB video capture support"
+       depends on VIDEO_DEV && I2C && SND && DVB_CORE
+       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.
+
+         To compile this driver as a module, choose M here: the
+         module will be called poseidon
diff --git a/drivers/media/usb/tlg2300/Makefile b/drivers/media/usb/tlg2300/Makefile
new file mode 100644 (file)
index 0000000..4d66087
--- /dev/null
@@ -0,0 +1,9 @@
+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/video
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
+
diff --git a/drivers/media/usb/tlg2300/pd-alsa.c b/drivers/media/usb/tlg2300/pd-alsa.c
new file mode 100644 (file)
index 0000000..9f8b7da
--- /dev/null
@@ -0,0 +1,332 @@
+#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_create(-1, "Telegent", THIS_MODULE, 0, &card);
+       if (ret != 0)
+               return ret;
+
+       ret = snd_pcm_new(card, "poseidon audio", 0, 0, 1, &pcm);
+       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/media/usb/tlg2300/pd-common.h b/drivers/media/usb/tlg2300/pd-common.h
new file mode 100644 (file)
index 0000000..5dd73b7
--- /dev/null
@@ -0,0 +1,281 @@
+#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 "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_VBI             (0x0008)
+#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         (45000000)
+#define TUNER_FREQ_MAX         (862000000)
+
+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;
+
+       /* 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;
+       int             users;
+       unsigned int    is_radio_streaming;
+       int             pre_emphasis;
+       struct video_device *fm_dev;
+};
+
+#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 *);
+struct video_device *vdev_init(struct poseidon *, struct video_device *);
+
+/* 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);
+void destroy_video_device(struct video_device **v_dev);
+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)
+
+#define logs(f) do { \
+                       if ((debug_mode & 0x4) && \
+                               (f)->type == V4L2_BUF_TYPE_VBI_CAPTURE) \
+                                       log("type : VBI");\
+                                                               \
+                       if ((debug_mode & 0x8) && \
+                               (f)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) \
+                                       log("type : VIDEO");\
+               } while (0)
+#endif
diff --git a/drivers/media/usb/tlg2300/pd-dvb.c b/drivers/media/usb/tlg2300/pd-dvb.c
new file mode 100644 (file)
index 0000000..30fcb11
--- /dev/null
@@ -0,0 +1,596 @@
+#include "pd-common.h"
+#include <linux/kernel.h>
+#include <linux/usb.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/media/usb/tlg2300/pd-main.c b/drivers/media/usb/tlg2300/pd-main.c
new file mode 100644 (file)
index 0000000..7b1f6eb
--- /dev/null
@@ -0,0 +1,536 @@
+/*
+ * 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 struct usb_driver poseidon_driver;
+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 = 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) + pd->radio_data.users;
+}
+
+/* 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 "\n\t+ TLG2300 auto suspend +\n\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 "\n\t ++ TLG2300 resume ++\n\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, int *down_firmware)
+{
+       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) {
+               *down_firmware = 1;
+               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 */
+       check_firmware(udev, &ret);
+       if (ret)
+               return 0;
+
+       /* 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) {
+               struct device *dev = &interface->dev;
+
+               logpm(pd);
+               mutex_init(&pd->lock);
+
+               /* register v4l2 device */
+               snprintf(pd->v4l2_dev.name, sizeof(pd->v4l2_dev.name), "%s %s",
+                       dev->driver->name, dev_name(dev));
+               ret = v4l2_device_register(NULL, &pd->v4l2_dev);
+
+               /* register devices in directory /dev */
+               ret = pd_video_init(pd);
+               poseidon_audio_init(pd);
+               poseidon_fm_init(pd);
+               pd_dvb_usb_device_init(pd);
+
+               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;
+}
+
+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/media/usb/tlg2300/pd-radio.c b/drivers/media/usb/tlg2300/pd-radio.c
new file mode 100644 (file)
index 0000000..4fad1df
--- /dev/null
@@ -0,0 +1,421 @@
+#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 <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 76000000
+#define TUNER_FREQ_MAX_FM 108000000
+
+#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 video_device *vfd = video_devdata(filp);
+       struct poseidon *p = video_get_drvdata(vfd);
+       int ret = 0;
+
+       if (!p)
+               return -1;
+
+       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;
+       }
+
+       usb_autopm_get_interface(p->interface);
+       if (0 == p->state) {
+               /* 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;
+       }
+       p->radio_data.users++;
+       kref_get(&p->kref);
+       filp->private_data = p;
+out:
+       mutex_unlock(&p->lock);
+       return ret;
+}
+
+static int poseidon_fm_close(struct file *filp)
+{
+       struct poseidon *p = filp->private_data;
+       struct radio_data *fm = &p->radio_data;
+       uint32_t status;
+
+       mutex_lock(&p->lock);
+       fm->users--;
+       if (0 == fm->users)
+               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);
+       filp->private_data = NULL;
+       return 0;
+}
+
+static int vidioc_querycap(struct file *file, void *priv,
+                       struct v4l2_capability *v)
+{
+       struct poseidon *p = file->private_data;
+
+       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->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+       return 0;
+}
+
+static const struct v4l2_file_operations poseidon_fm_fops = {
+       .owner         = THIS_MODULE,
+       .open          = poseidon_fm_open,
+       .release       = poseidon_fm_close,
+       .ioctl         = video_ioctl2,
+};
+
+static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv,
+                                struct v4l2_tuner *vt)
+{
+       struct tuner_fm_sig_stat_s fm_stat = {};
+       int ret, status, count = 5;
+       struct poseidon *p = file->private_data;
+
+       if (vt->index != 0)
+               return -EINVAL;
+
+       vt->type        = V4L2_TUNER_RADIO;
+       vt->capability  = V4L2_TUNER_CAP_STEREO;
+       vt->rangelow    = TUNER_FREQ_MIN_FM / 62500;
+       vt->rangehigh   = TUNER_FREQ_MAX_FM / 62500;
+       vt->rxsubchans  = V4L2_TUNER_SUB_STEREO;
+       vt->audmode     = V4L2_TUNER_MODE_STEREO;
+       vt->signal      = 0;
+       vt->afc         = 0;
+
+       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 = file->private_data;
+
+       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) * 500 / 1000;/* kHZ */
+       if (freq < TUNER_FREQ_MIN_FM/1000 || freq > TUNER_FREQ_MAX_FM/1000) {
+               ret = -EINVAL;
+               goto error;
+       }
+
+       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 = frequency;
+error:
+       mutex_unlock(&p->lock);
+       return ret;
+}
+
+static int fm_set_freq(struct file *file, void *priv,
+                      struct v4l2_frequency *argp)
+{
+       struct poseidon *p = file->private_data;
+
+       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_vidioc_g_ctrl(struct file *file, void *priv,
+               struct v4l2_control *arg)
+{
+       return 0;
+}
+
+static int tlg_fm_vidioc_g_exts_ctrl(struct file *file, void *fh,
+                               struct v4l2_ext_controls *ctrls)
+{
+       struct poseidon *p = file->private_data;
+       int i;
+
+       if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX)
+               return -EINVAL;
+
+       for (i = 0; i < ctrls->count; i++) {
+               struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+               if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS)
+                       continue;
+
+               if (i < MAX_PREEMPHASIS)
+                       ctrl->value = p->radio_data.pre_emphasis;
+       }
+       return 0;
+}
+
+static int tlg_fm_vidioc_s_exts_ctrl(struct file *file, void *fh,
+                       struct v4l2_ext_controls *ctrls)
+{
+       int i;
+
+       if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX)
+               return -EINVAL;
+
+       for (i = 0; i < ctrls->count; i++) {
+               struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+               if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS)
+                       continue;
+
+               if (ctrl->value >= 0 && ctrl->value < MAX_PREEMPHASIS) {
+                       struct poseidon *p = file->private_data;
+                       int pre_emphasis = preemphasis[ctrl->value];
+                       u32 status;
+
+                       send_set_req(p, TUNER_AUD_ANA_STD,
+                                               pre_emphasis, &status);
+                       p->radio_data.pre_emphasis = pre_emphasis;
+               }
+       }
+       return 0;
+}
+
+static int tlg_fm_vidioc_s_ctrl(struct file *file, void *priv,
+               struct v4l2_control *ctrl)
+{
+       return 0;
+}
+
+static int tlg_fm_vidioc_queryctrl(struct file *file, void *priv,
+               struct v4l2_queryctrl *ctrl)
+{
+       if (!(ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL))
+               return -EINVAL;
+
+       ctrl->id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
+       if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS) {
+               /* return the next supported control */
+               ctrl->id = V4L2_CID_TUNE_PREEMPHASIS;
+               v4l2_ctrl_query_fill(ctrl, V4L2_PREEMPHASIS_DISABLED,
+                                       V4L2_PREEMPHASIS_75_uS, 1,
+                                       V4L2_PREEMPHASIS_50_uS);
+               ctrl->flags = V4L2_CTRL_FLAG_UPDATE;
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int tlg_fm_vidioc_querymenu(struct file *file, void *fh,
+                               struct v4l2_querymenu *qmenu)
+{
+       return v4l2_ctrl_query_menu(qmenu, NULL, NULL);
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
+{
+       return vt->index > 0 ? -EINVAL : 0;
+}
+static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *va)
+{
+       return (va->index != 0) ? -EINVAL : 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+       a->index    = 0;
+       a->mode    = 0;
+       a->capability = V4L2_AUDCAP_STEREO;
+       strcpy(a->name, "Radio");
+       return 0;
+}
+
+static int vidioc_s_input(struct file *filp, void *priv, u32 i)
+{
+       return (i != 0) ? -EINVAL : 0;
+}
+
+static int vidioc_g_input(struct file *filp, void *priv, u32 *i)
+{
+       return (*i != 0) ? -EINVAL : 0;
+}
+
+static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = {
+       .vidioc_querycap    = vidioc_querycap,
+       .vidioc_g_audio     = vidioc_g_audio,
+       .vidioc_s_audio     = vidioc_s_audio,
+       .vidioc_g_input     = vidioc_g_input,
+       .vidioc_s_input     = vidioc_s_input,
+       .vidioc_queryctrl   = tlg_fm_vidioc_queryctrl,
+       .vidioc_querymenu   = tlg_fm_vidioc_querymenu,
+       .vidioc_g_ctrl      = tlg_fm_vidioc_g_ctrl,
+       .vidioc_s_ctrl      = tlg_fm_vidioc_s_ctrl,
+       .vidioc_s_ext_ctrls = tlg_fm_vidioc_s_exts_ctrl,
+       .vidioc_g_ext_ctrls = tlg_fm_vidioc_g_exts_ctrl,
+       .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,
+};
+
+static struct video_device poseidon_fm_template = {
+       .name       = "Telegent-Radio",
+       .fops       = &poseidon_fm_fops,
+       .minor      = -1,
+       .release    = video_device_release,
+       .ioctl_ops  = &poseidon_fm_ioctl_ops,
+};
+
+int poseidon_fm_init(struct poseidon *p)
+{
+       struct video_device *fm_dev;
+
+       fm_dev = vdev_init(p, &poseidon_fm_template);
+       if (fm_dev == NULL)
+               return -1;
+
+       if (video_register_device(fm_dev, VFL_TYPE_RADIO, -1) < 0) {
+               video_device_release(fm_dev);
+               return -1;
+       }
+       p->radio_data.fm_dev = fm_dev;
+       return 0;
+}
+
+int poseidon_fm_exit(struct poseidon *p)
+{
+       destroy_video_device(&p->radio_data.fm_dev);
+       return 0;
+}
diff --git a/drivers/media/usb/tlg2300/pd-video.c b/drivers/media/usb/tlg2300/pd-video.c
new file mode 100644 (file)
index 0000000..bfbf9e5
--- /dev/null
@@ -0,0 +1,1668 @@
+#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 "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 poseidon_control {
+       struct v4l2_queryctrl v4l2_ctrl;
+       enum cmd_custom_param_id vc_id;
+};
+
+static struct poseidon_control controls[] = {
+       {
+               { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER,
+                       "brightness", 0, 10000, 1, 100, 0, },
+               CUST_PARM_ID_BRIGHTNESS_CTRL
+       }, {
+               { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER,
+                       "contrast", 0, 10000, 1, 100, 0, },
+               CUST_PARM_ID_CONTRAST_CTRL,
+       }, {
+               { V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER,
+                       "hue", 0, 10000, 1, 100, 0, },
+               CUST_PARM_ID_HUE_CTRL,
+       }, {
+               { V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER,
+                       "saturation", 0, 10000, 1, 100, 0, },
+               CUST_PARM_ID_SATURATION_CTRL,
+       },
+};
+
+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 front_face *front = fh;
+       struct poseidon *p = front->pd;
+
+       logs(front);
+
+       strcpy(cap->driver, "tele-video");
+       strcpy(cap->card, "Telegent Poseidon");
+       usb_make_path(p->udev, cap->bus_info, sizeof(cap->bus_info));
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
+                               V4L2_CAP_AUDIO | V4L2_CAP_STREAMING |
+                               V4L2_CAP_READWRITE | V4L2_CAP_VBI_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++;
+       do_gettimeofday(&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)
+{
+       /* logs(video->front); */
+       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;
+
+       logs(front);
+       f->fmt.pix = pd->video_data.context.pix;
+       return 0;
+}
+
+static int vidioc_try_fmt(struct file *file, void *fh,
+               struct v4l2_format *f)
+{
+       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;
+
+       logs(front);
+       /* 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;
+       logs(front);
+       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;
+       logs(front);
+       return set_std(front->pd, norm);
+}
+
+static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in)
+{
+       struct front_face *front = fh;
+
+       if (in->index < 0 || 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    = 0;
+       in->tuner       = 0;
+       in->std         = V4L2_STD_ALL;
+       in->status      = 0;
+       logs(front);
+       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;
+
+       logs(front);
+       *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 < 0 || 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 struct poseidon_control *check_control_id(__u32 id)
+{
+       struct poseidon_control *control = &controls[0];
+       int array_size = ARRAY_SIZE(controls);
+
+       for (; control < &controls[array_size]; control++)
+               if (control->v4l2_ctrl.id  == id)
+                       return control;
+       return NULL;
+}
+
+static int vidioc_queryctrl(struct file *file, void *fh,
+                       struct v4l2_queryctrl *a)
+{
+       struct poseidon_control *control = NULL;
+
+       control = check_control_id(a->id);
+       if (!control)
+               return -EINVAL;
+
+       *a = control->v4l2_ctrl;
+       return 0;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *ctrl)
+{
+       struct front_face *front = fh;
+       struct poseidon *pd = front->pd;
+       struct poseidon_control *control = NULL;
+       struct tuner_custom_parameter_s tuner_param;
+       s32 ret = 0, cmd_status;
+
+       control = check_control_id(ctrl->id);
+       if (!control)
+               return -EINVAL;
+
+       mutex_lock(&pd->lock);
+       ret = send_get_req(pd, TUNER_CUSTOM_PARAMETER, control->vc_id,
+                       &tuner_param, &cmd_status, sizeof(tuner_param));
+       mutex_unlock(&pd->lock);
+
+       if (ret || cmd_status)
+               return -1;
+
+       ctrl->value = tuner_param.param_value;
+       return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a)
+{
+       struct tuner_custom_parameter_s param = {0};
+       struct poseidon_control *control = NULL;
+       struct front_face *front        = fh;
+       struct poseidon *pd             = front->pd;
+       s32 ret = 0, cmd_status, params;
+
+       control = check_control_id(a->id);
+       if (!control)
+               return -EINVAL;
+
+       param.param_value = a->value;
+       param.param_id  = control->vc_id;
+       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, 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;
+       logs(front);
+       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, struct v4l2_tuner *a)
+{
+       struct front_face *front        = fh;
+       struct poseidon *pd             = front->pd;
+       int index;
+
+       if (0 != a->index)
+               return -EINVAL;
+       logs(front);
+       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;
+
+       param = frequency * 62500 / 1000;
+       if (param < TUNER_FREQ_MIN/1000 || param > TUNER_FREQ_MAX / 1000)
+               return -EINVAL;
+
+       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,
+                               struct v4l2_frequency *freq)
+{
+       struct front_face *front = fh;
+       struct poseidon *pd = front->pd;
+
+       logs(front);
+#ifdef CONFIG_PM
+       pd->pm_suspend = pm_video_suspend;
+       pd->pm_resume = pm_video_resume;
+#endif
+       return set_frequency(pd, freq->frequency);
+}
+
+static int vidioc_reqbufs(struct file *file, void *fh,
+                               struct v4l2_requestbuffers *b)
+{
+       struct front_face *front = file->private_data;
+       logs(front);
+       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;
+       logs(front);
+       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;
+
+       logs(front);
+       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;
+
+       logs(front);
+       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,
+                               .priv           = 0
+                       };
+}
+
+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 (vfd->vfl_type == VFL_TYPE_GRABBER
+               && !(pd->state & POSEIDON_STATE_ANALOG)) {
+               front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
+               if (!front)
+                       goto out;
+
+               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;
+               }
+
+               pd->state               |= POSEIDON_STATE_ANALOG;
+               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 if (vfd->vfl_type == VFL_TYPE_VBI
+               && !(pd->state & POSEIDON_STATE_VBI)) {
+               front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
+               if (!front)
+                       goto out;
+
+               pd->state       |= POSEIDON_STATE_VBI;
+               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);
+       } else {
+               /* maybe add FM support here */
+               log("other ");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       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;
+
+       logs(front);
+       mutex_lock(&pd->lock);
+
+       if (front->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               pd->state &= ~POSEIDON_STATE_ANALOG;
+
+               /* 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->state &= ~POSEIDON_STATE_VBI;
+               pd->vbi_data.front = NULL;
+               pd->vbi_data.users--;
+       }
+       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 */
+       .vidioc_try_fmt_vid_cap = vidioc_try_fmt,
+
+       /* 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_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,
+
+       /* Control handling */
+       .vidioc_queryctrl       = vidioc_queryctrl,
+       .vidioc_g_ctrl          = vidioc_g_ctrl,
+       .vidioc_s_ctrl          = vidioc_s_ctrl,
+};
+
+static struct video_device pd_video_template = {
+       .name = "Telegent-Video",
+       .fops = &pd_video_fops,
+       .minor = -1,
+       .release = video_device_release,
+       .tvnorms = V4L2_STD_ALL,
+       .ioctl_ops = &pd_video_ioctl_ops,
+};
+
+struct video_device *vdev_init(struct poseidon *pd, struct video_device *tmp)
+{
+       struct video_device *vfd;
+
+       vfd = video_device_alloc();
+       if (vfd == NULL)
+               return NULL;
+       *vfd            = *tmp;
+       vfd->minor      = -1;
+       vfd->v4l2_dev   = &pd->v4l2_dev;
+       /*vfd->parent   = &(pd->udev->dev); */
+       vfd->release    = video_device_release;
+       video_set_drvdata(vfd, pd);
+       return vfd;
+}
+
+void destroy_video_device(struct video_device **v_dev)
+{
+       struct video_device *dev = *v_dev;
+
+       if (dev == NULL)
+               return;
+
+       if (video_is_registered(dev))
+               video_unregister_device(dev);
+       else
+               video_device_release(dev);
+       *v_dev = NULL;
+}
+
+void pd_video_exit(struct poseidon *pd)
+{
+       struct video_data *video = &pd->video_data;
+       struct vbi_data *vbi = &pd->vbi_data;
+
+       destroy_video_device(&video->v_dev);
+       destroy_video_device(&vbi->v_dev);
+       log();
+}
+
+int pd_video_init(struct poseidon *pd)
+{
+       struct video_data *video = &pd->video_data;
+       struct vbi_data *vbi    = &pd->vbi_data;
+       int ret = -ENOMEM;
+
+       video->v_dev = vdev_init(pd, &pd_video_template);
+       if (video->v_dev == NULL)
+               goto out;
+
+       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 = vdev_init(pd, &pd_video_template);
+       if (vbi->v_dev == NULL) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       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/media/usb/tlg2300/vendorcmds.h b/drivers/media/usb/tlg2300/vendorcmds.h
new file mode 100644 (file)
index 0000000..ba6f4ae
--- /dev/null
@@ -0,0 +1,243 @@
+#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/media/usb/tm6000/Kconfig b/drivers/media/usb/tm6000/Kconfig
new file mode 100644 (file)
index 0000000..a43b77a
--- /dev/null
@@ -0,0 +1,33 @@
+config VIDEO_TM6000
+       tristate "TV Master TM5600/6000/6010 driver"
+       depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB
+       select VIDEO_TUNER
+       select MEDIA_TUNER_XC2028
+       select MEDIA_TUNER_XC5000
+       select VIDEOBUF_VMALLOC
+       help
+         Support for TM5600/TM6000/TM6010 USB Device
+
+         Since these cards have no MPEG decoder onboard, they transmit
+         only compressed MPEG data over the usb bus, so you need
+         an external software decoder to watch TV on your computer.
+
+         Say Y if you own such a device and want to use it.
+
+config VIDEO_TM6000_ALSA
+       tristate "TV Master TM5600/6000/6010 audio support"
+       depends on VIDEO_TM6000 && SND
+       select SND_PCM
+       ---help---
+         This is a video4linux driver for direct (DMA) audio for
+         TM5600/TM6000/TM6010 USB Devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tm6000-alsa.
+
+config VIDEO_TM6000_DVB
+       tristate "DVB Support for tm6000 based TV cards"
+       depends on VIDEO_TM6000 && DVB_CORE && USB
+       select DVB_ZL10353
+       ---help---
+         This adds support for DVB cards based on the tm5600/tm6000 chip.
diff --git a/drivers/media/usb/tm6000/Makefile b/drivers/media/usb/tm6000/Makefile
new file mode 100644 (file)
index 0000000..1feb8c9
--- /dev/null
@@ -0,0 +1,15 @@
+tm6000-y := tm6000-cards.o \
+                  tm6000-core.o  \
+                  tm6000-i2c.o   \
+                  tm6000-video.o \
+                  tm6000-stds.o \
+                  tm6000-input.o
+
+obj-$(CONFIG_VIDEO_TM6000) += tm6000.o
+obj-$(CONFIG_VIDEO_TM6000_ALSA) += tm6000-alsa.o
+obj-$(CONFIG_VIDEO_TM6000_DVB) += tm6000-dvb.o
+
+ccflags-y := -Idrivers/media/video
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/drivers/media/usb/tm6000/tm6000-alsa.c b/drivers/media/usb/tm6000/tm6000-alsa.c
new file mode 100644 (file)
index 0000000..bd07ec7
--- /dev/null
@@ -0,0 +1,528 @@
+/*
+ *
+ *  Support for audio capture for tm5600/6000/6010
+ *    (c) 2007-2008 Mauro Carvalho Chehab <mchehab@redhat.com>
+ *
+ *  Based on cx88-alsa.c
+ *
+ *  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/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+
+#undef dprintk
+
+#define dprintk(level, fmt, arg...) do {                                  \
+       if (debug >= level)                                                \
+               printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg); \
+       } while (0)
+
+/****************************************************************************
+                       Module global static vars
+ ****************************************************************************/
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
+
+static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable tm6000x soundcard. default enabled.");
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for tm6000x capture interface(s).");
+
+
+/****************************************************************************
+                               Module macros
+ ****************************************************************************/
+
+MODULE_DESCRIPTION("ALSA driver module for tm5600/tm6000/tm6010 based TV cards");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Trident,tm5600},"
+                       "{{Trident,tm6000},"
+                       "{{Trident,tm6010}");
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+/****************************************************************************
+                       Module specific funtions
+ ****************************************************************************/
+
+/*
+ * BOARD Specific: Sets audio DMA
+ */
+
+static int _tm6000_start_audio_dma(struct snd_tm6000_card *chip)
+{
+       struct tm6000_core *core = chip->core;
+
+       dprintk(1, "Starting audio DMA\n");
+
+       /* Enables audio */
+       tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x40, 0x40);
+
+       tm6000_set_audio_bitrate(core, 48000);
+
+       return 0;
+}
+
+/*
+ * BOARD Specific: Resets audio DMA
+ */
+static int _tm6000_stop_audio_dma(struct snd_tm6000_card *chip)
+{
+       struct tm6000_core *core = chip->core;
+
+       dprintk(1, "Stopping audio DMA\n");
+
+       /* Disables audio */
+       tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x00, 0x40);
+
+       return 0;
+}
+
+static void dsp_buffer_free(struct snd_pcm_substream *substream)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+
+       dprintk(2, "Freeing buffer\n");
+
+       vfree(substream->runtime->dma_area);
+       substream->runtime->dma_area = NULL;
+       substream->runtime->dma_bytes = 0;
+}
+
+static int dsp_buffer_alloc(struct snd_pcm_substream *substream, int size)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+
+       dprintk(2, "Allocating buffer\n");
+
+       if (substream->runtime->dma_area) {
+               if (substream->runtime->dma_bytes > size)
+                       return 0;
+
+               dsp_buffer_free(substream);
+       }
+
+       substream->runtime->dma_area = vmalloc(size);
+       if (!substream->runtime->dma_area)
+               return -ENOMEM;
+
+       substream->runtime->dma_bytes = size;
+
+       return 0;
+}
+
+
+/****************************************************************************
+                               ALSA PCM Interface
+ ****************************************************************************/
+
+/*
+ * Digital hardware definition
+ */
+#define DEFAULT_FIFO_SIZE      4096
+
+static struct snd_pcm_hardware snd_tm6000_digital_hw = {
+       .info = SNDRV_PCM_INFO_BATCH |
+               SNDRV_PCM_INFO_MMAP |
+               SNDRV_PCM_INFO_INTERLEAVED |
+               SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP_VALID,
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT,
+       .rate_min = 48000,
+       .rate_max = 48000,
+       .channels_min = 2,
+       .channels_max = 2,
+       .period_bytes_min = 64,
+       .period_bytes_max = 12544,
+       .periods_min = 2,
+       .periods_max = 98,
+       .buffer_bytes_max = 62720 * 8,
+};
+
+/*
+ * audio pcm capture open callback
+ */
+static int snd_tm6000_pcm_open(struct snd_pcm_substream *substream)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       int err;
+
+       err = snd_pcm_hw_constraint_pow2(runtime, 0,
+                                        SNDRV_PCM_HW_PARAM_PERIODS);
+       if (err < 0)
+               goto _error;
+
+       chip->substream = substream;
+
+       runtime->hw = snd_tm6000_digital_hw;
+       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+
+       return 0;
+_error:
+       dprintk(1, "Error opening PCM!\n");
+       return err;
+}
+
+/*
+ * audio close callback
+ */
+static int snd_tm6000_close(struct snd_pcm_substream *substream)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+       struct tm6000_core *core = chip->core;
+
+       if (atomic_read(&core->stream_started) > 0) {
+               atomic_set(&core->stream_started, 0);
+               schedule_work(&core->wq_trigger);
+       }
+
+       return 0;
+}
+
+static int tm6000_fillbuf(struct tm6000_core *core, char *buf, int size)
+{
+       struct snd_tm6000_card *chip = core->adev;
+       struct snd_pcm_substream *substream = chip->substream;
+       struct snd_pcm_runtime *runtime;
+       int period_elapsed = 0;
+       unsigned int stride, buf_pos;
+       int length;
+
+       if (atomic_read(&core->stream_started) == 0)
+               return 0;
+
+       if (!size || !substream) {
+               dprintk(1, "substream was NULL\n");
+               return -EINVAL;
+       }
+
+       runtime = substream->runtime;
+       if (!runtime || !runtime->dma_area) {
+               dprintk(1, "runtime was NULL\n");
+               return -EINVAL;
+       }
+
+       buf_pos = chip->buf_pos;
+       stride = runtime->frame_bits >> 3;
+
+       if (stride == 0) {
+               dprintk(1, "stride is zero\n");
+               return -EINVAL;
+       }
+
+       length = size / stride;
+       if (length == 0) {
+               dprintk(1, "%s: length was zero\n", __func__);
+               return -EINVAL;
+       }
+
+       dprintk(1, "Copying %d bytes at %p[%d] - buf size=%d x %d\n", size,
+               runtime->dma_area, buf_pos,
+               (unsigned int)runtime->buffer_size, stride);
+
+       if (buf_pos + length >= runtime->buffer_size) {
+               unsigned int cnt = runtime->buffer_size - buf_pos;
+               memcpy(runtime->dma_area + buf_pos * stride, buf, cnt * stride);
+               memcpy(runtime->dma_area, buf + cnt * stride,
+                       length * stride - cnt * stride);
+       } else
+               memcpy(runtime->dma_area + buf_pos * stride, buf,
+                       length * stride);
+
+       snd_pcm_stream_lock(substream);
+
+       chip->buf_pos += length;
+       if (chip->buf_pos >= runtime->buffer_size)
+               chip->buf_pos -= runtime->buffer_size;
+
+       chip->period_pos += length;
+       if (chip->period_pos >= runtime->period_size) {
+               chip->period_pos -= runtime->period_size;
+               period_elapsed = 1;
+       }
+
+       snd_pcm_stream_unlock(substream);
+
+       if (period_elapsed)
+               snd_pcm_period_elapsed(substream);
+
+       return 0;
+}
+
+/*
+ * hw_params callback
+ */
+static int snd_tm6000_hw_params(struct snd_pcm_substream *substream,
+                             struct snd_pcm_hw_params *hw_params)
+{
+       int size, rc;
+
+       size = params_period_bytes(hw_params) * params_periods(hw_params);
+
+       rc = dsp_buffer_alloc(substream, size);
+       if (rc < 0)
+               return rc;
+
+       return 0;
+}
+
+/*
+ * hw free callback
+ */
+static int snd_tm6000_hw_free(struct snd_pcm_substream *substream)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+       struct tm6000_core *core = chip->core;
+
+       if (atomic_read(&core->stream_started) > 0) {
+               atomic_set(&core->stream_started, 0);
+               schedule_work(&core->wq_trigger);
+       }
+
+       dsp_buffer_free(substream);
+       return 0;
+}
+
+/*
+ * prepare callback
+ */
+static int snd_tm6000_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+
+       chip->buf_pos = 0;
+       chip->period_pos = 0;
+
+       return 0;
+}
+
+
+/*
+ * trigger callback
+ */
+static void audio_trigger(struct work_struct *work)
+{
+       struct tm6000_core *core = container_of(work, struct tm6000_core,
+                                               wq_trigger);
+       struct snd_tm6000_card *chip = core->adev;
+
+       if (atomic_read(&core->stream_started)) {
+               dprintk(1, "starting capture");
+               _tm6000_start_audio_dma(chip);
+       } else {
+               dprintk(1, "stopping capture");
+               _tm6000_stop_audio_dma(chip);
+       }
+}
+
+static int snd_tm6000_card_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+       struct tm6000_core *core = chip->core;
+       int err = 0;
+
+       switch (cmd) {
+       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
+       case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
+       case SNDRV_PCM_TRIGGER_START:
+               atomic_set(&core->stream_started, 1);
+               break;
+       case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
+       case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
+       case SNDRV_PCM_TRIGGER_STOP:
+               atomic_set(&core->stream_started, 0);
+               break;
+       default:
+               err = -EINVAL;
+               break;
+       }
+       schedule_work(&core->wq_trigger);
+
+       return err;
+}
+/*
+ * pointer callback
+ */
+static snd_pcm_uframes_t snd_tm6000_pointer(struct snd_pcm_substream *substream)
+{
+       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
+
+       return chip->buf_pos;
+}
+
+static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
+                                            unsigned long offset)
+{
+       void *pageptr = subs->runtime->dma_area + offset;
+
+       return vmalloc_to_page(pageptr);
+}
+
+/*
+ * operators
+ */
+static struct snd_pcm_ops snd_tm6000_pcm_ops = {
+       .open = snd_tm6000_pcm_open,
+       .close = snd_tm6000_close,
+       .ioctl = snd_pcm_lib_ioctl,
+       .hw_params = snd_tm6000_hw_params,
+       .hw_free = snd_tm6000_hw_free,
+       .prepare = snd_tm6000_prepare,
+       .trigger = snd_tm6000_card_trigger,
+       .pointer = snd_tm6000_pointer,
+       .page = snd_pcm_get_vmalloc_page,
+};
+
+/*
+ * create a PCM device
+ */
+
+/* FIXME: Control interface - How to control volume/mute? */
+
+/****************************************************************************
+                       Basic Flow for Sound Devices
+ ****************************************************************************/
+
+/*
+ * Alsa Constructor - Component probe
+ */
+static int tm6000_audio_init(struct tm6000_core *dev)
+{
+       struct snd_card         *card;
+       struct snd_tm6000_card  *chip;
+       int                     rc;
+       static int              devnr;
+       char                    component[14];
+       struct snd_pcm          *pcm;
+
+       if (!dev)
+               return 0;
+
+       if (devnr >= SNDRV_CARDS)
+               return -ENODEV;
+
+       if (!enable[devnr])
+               return -ENOENT;
+
+       rc = snd_card_create(index[devnr], "tm6000", THIS_MODULE, 0, &card);
+       if (rc < 0) {
+               snd_printk(KERN_ERR "cannot create card instance %d\n", devnr);
+               return rc;
+       }
+       strcpy(card->driver, "tm6000-alsa");
+       strcpy(card->shortname, "TM5600/60x0");
+       sprintf(card->longname, "TM5600/60x0 Audio at bus %d device %d",
+               dev->udev->bus->busnum, dev->udev->devnum);
+
+       sprintf(component, "USB%04x:%04x",
+               le16_to_cpu(dev->udev->descriptor.idVendor),
+               le16_to_cpu(dev->udev->descriptor.idProduct));
+       snd_component_add(card, component);
+       snd_card_set_dev(card, &dev->udev->dev);
+
+       chip = kzalloc(sizeof(struct snd_tm6000_card), GFP_KERNEL);
+       if (!chip) {
+               rc = -ENOMEM;
+               goto error;
+       }
+
+       chip->core = dev;
+       chip->card = card;
+       dev->adev = chip;
+       spin_lock_init(&chip->reg_lock);
+
+       rc = snd_pcm_new(card, "TM6000 Audio", 0, 0, 1, &pcm);
+       if (rc < 0)
+               goto error_chip;
+
+       pcm->info_flags = 0;
+       pcm->private_data = chip;
+       strcpy(pcm->name, "Trident TM5600/60x0");
+
+       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops);
+
+       INIT_WORK(&dev->wq_trigger, audio_trigger);
+       rc = snd_card_register(card);
+       if (rc < 0)
+               goto error_chip;
+
+       dprintk(1, "Registered audio driver for %s\n", card->longname);
+
+       return 0;
+
+error_chip:
+       kfree(chip);
+       dev->adev = NULL;
+error:
+       snd_card_free(card);
+       return rc;
+}
+
+static int tm6000_audio_fini(struct tm6000_core *dev)
+{
+       struct snd_tm6000_card  *chip = dev->adev;
+
+       if (!dev)
+               return 0;
+
+       if (!chip)
+               return 0;
+
+       if (!chip->card)
+               return 0;
+
+       snd_card_free(chip->card);
+       chip->card = NULL;
+       kfree(chip);
+       dev->adev = NULL;
+
+       return 0;
+}
+
+static struct tm6000_ops audio_ops = {
+       .type   = TM6000_AUDIO,
+       .name   = "TM6000 Audio Extension",
+       .init   = tm6000_audio_init,
+       .fini   = tm6000_audio_fini,
+       .fillbuf = tm6000_fillbuf,
+};
+
+static int __init tm6000_alsa_register(void)
+{
+       return tm6000_register_extension(&audio_ops);
+}
+
+static void __exit tm6000_alsa_unregister(void)
+{
+       tm6000_unregister_extension(&audio_ops);
+}
+
+module_init(tm6000_alsa_register);
+module_exit(tm6000_alsa_unregister);
diff --git a/drivers/media/usb/tm6000/tm6000-cards.c b/drivers/media/usb/tm6000/tm6000-cards.c
new file mode 100644 (file)
index 0000000..034659b
--- /dev/null
@@ -0,0 +1,1413 @@
+/*
+ *  tm6000-cards.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation version 2
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include <media/tvaudio.h>
+#include <media/i2c-addr.h>
+#include <media/rc-map.h>
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+#include "tuner-xc2028.h"
+#include "xc5000.h"
+
+#define TM6000_BOARD_UNKNOWN                   0
+#define TM5600_BOARD_GENERIC                   1
+#define TM6000_BOARD_GENERIC                   2
+#define TM6010_BOARD_GENERIC                   3
+#define TM5600_BOARD_10MOONS_UT821             4
+#define TM5600_BOARD_10MOONS_UT330             5
+#define TM6000_BOARD_ADSTECH_DUAL_TV           6
+#define TM6000_BOARD_FREECOM_AND_SIMILAR       7
+#define TM6000_BOARD_ADSTECH_MINI_DUAL_TV      8
+#define TM6010_BOARD_HAUPPAUGE_900H            9
+#define TM6010_BOARD_BEHOLD_WANDER             10
+#define TM6010_BOARD_BEHOLD_VOYAGER            11
+#define TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE        12
+#define TM6010_BOARD_TWINHAN_TU501             13
+#define TM6010_BOARD_BEHOLD_WANDER_LITE                14
+#define TM6010_BOARD_BEHOLD_VOYAGER_LITE       15
+#define TM5600_BOARD_TERRATEC_GRABSTER         16
+
+#define is_generic(model) ((model == TM6000_BOARD_UNKNOWN) || \
+                          (model == TM5600_BOARD_GENERIC) || \
+                          (model == TM6000_BOARD_GENERIC) || \
+                          (model == TM6010_BOARD_GENERIC))
+
+#define TM6000_MAXBOARDS        16
+static unsigned int card[]     = {[0 ... (TM6000_MAXBOARDS - 1)] = UNSET };
+
+module_param_array(card,  int, NULL, 0444);
+
+static unsigned long tm6000_devused;
+
+
+struct tm6000_board {
+       char            *name;
+       char            eename[16];             /* EEPROM name */
+       unsigned        eename_size;            /* size of EEPROM name */
+       unsigned        eename_pos;             /* Position where it appears at ROM */
+
+       struct tm6000_capabilities caps;
+
+       enum            tm6000_devtype type;    /* variant of the chipset */
+       int             tuner_type;     /* type of the tuner */
+       int             tuner_addr;     /* tuner address */
+       int             demod_addr;     /* demodulator address */
+
+       struct tm6000_gpio gpio;
+
+       struct tm6000_input     vinput[3];
+       struct tm6000_input     rinput;
+
+       char            *ir_codes;
+};
+
+static struct tm6000_board tm6000_boards[] = {
+       [TM6000_BOARD_UNKNOWN] = {
+               .name         = "Unknown tm6000 video grabber",
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_eeprom     = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6000_GPIO_1,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM5600_BOARD_GENERIC] = {
+               .name         = "Generic tm5600 board",
+               .type         = TM5600,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_addr   = 0xc2 >> 1,
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_eeprom     = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6000_GPIO_1,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6000_BOARD_GENERIC] = {
+               .name         = "Generic tm6000 board",
+               .tuner_type   = TUNER_XC2028,
+               .tuner_addr   = 0xc2 >> 1,
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_eeprom     = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6000_GPIO_1,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6010_BOARD_GENERIC] = {
+               .name         = "Generic tm6010 board",
+               .type         = TM6010,
+               .tuner_type   = TUNER_XC2028,
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_dvb        = 1,
+                       .has_zl10353    = 1,
+                       .has_eeprom     = 1,
+                       .has_remote     = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_2,
+                       .tuner_on       = TM6010_GPIO_3,
+                       .demod_reset    = TM6010_GPIO_1,
+                       .demod_on       = TM6010_GPIO_4,
+                       .power_led      = TM6010_GPIO_7,
+                       .dvb_led        = TM6010_GPIO_5,
+                       .ir             = TM6010_GPIO_0,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM5600_BOARD_10MOONS_UT821] = {
+               .name         = "10Moons UT 821",
+               .tuner_type   = TUNER_XC2028,
+               .eename       = { '1', '0', 'M', 'O', 'O', 'N', 'S', '5', '6', '0', '0', 0xff, 0x45, 0x5b},
+               .eename_size  = 14,
+               .eename_pos   = 0x14,
+               .type         = TM5600,
+               .tuner_addr   = 0xc2 >> 1,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_eeprom   = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6000_GPIO_1,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM5600_BOARD_10MOONS_UT330] = {
+               .name         = "10Moons UT 330",
+               .tuner_type   = TUNER_PHILIPS_FQ1216AME_MK4,
+               .tuner_addr   = 0xc8 >> 1,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_dvb      = 0,
+                       .has_zl10353  = 0,
+                       .has_eeprom   = 1,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6000_BOARD_ADSTECH_DUAL_TV] = {
+               .name         = "ADSTECH Dual TV USB",
+               .tuner_type   = TUNER_XC2028,
+               .tuner_addr   = 0xc8 >> 1,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_tda9874  = 1,
+                       .has_dvb      = 1,
+                       .has_zl10353  = 1,
+                       .has_eeprom   = 1,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6000_BOARD_FREECOM_AND_SIMILAR] = {
+               .name         = "Freecom Hybrid Stick / Moka DVB-T Receiver Dual",
+               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_dvb      = 1,
+                       .has_zl10353  = 1,
+                       .has_eeprom   = 0,
+                       .has_remote   = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6000_GPIO_4,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6000_BOARD_ADSTECH_MINI_DUAL_TV] = {
+               .name         = "ADSTECH Mini Dual TV USB",
+               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
+               .tuner_addr   = 0xc8 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_dvb      = 1,
+                       .has_zl10353  = 1,
+                       .has_eeprom   = 0,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6000_GPIO_4,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6010_BOARD_HAUPPAUGE_900H] = {
+               .name         = "Hauppauge WinTV HVR-900H / WinTV USB2-Stick",
+               .eename       = { 'H', 0, 'V', 0, 'R', 0, '9', 0, '0', 0, '0', 0, 'H', 0 },
+               .eename_size  = 14,
+               .eename_pos   = 0x42,
+               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .type         = TM6010,
+               .ir_codes = RC_MAP_HAUPPAUGE,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_dvb      = 1,
+                       .has_zl10353  = 1,
+                       .has_eeprom   = 1,
+                       .has_remote   = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_2,
+                       .tuner_on       = TM6010_GPIO_3,
+                       .demod_reset    = TM6010_GPIO_1,
+                       .demod_on       = TM6010_GPIO_4,
+                       .power_led      = TM6010_GPIO_7,
+                       .dvb_led        = TM6010_GPIO_5,
+                       .ir             = TM6010_GPIO_0,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6010_BOARD_BEHOLD_WANDER] = {
+               .name         = "Beholder Wander DVB-T/TV/FM USB2.0",
+               .tuner_type   = TUNER_XC5000,
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .type         = TM6010,
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_dvb        = 1,
+                       .has_zl10353    = 1,
+                       .has_eeprom     = 1,
+                       .has_remote     = 1,
+                       .has_radio      = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_0,
+                       .demod_reset    = TM6010_GPIO_1,
+                       .power_led      = TM6010_GPIO_6,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+               .rinput = {
+                       .type   = TM6000_INPUT_RADIO,
+                       .amux   = TM6000_AMUX_ADC1,
+               },
+       },
+       [TM6010_BOARD_BEHOLD_VOYAGER] = {
+               .name         = "Beholder Voyager TV/FM USB2.0",
+               .tuner_type   = TUNER_XC5000,
+               .tuner_addr   = 0xc2 >> 1,
+               .type         = TM6010,
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_dvb        = 0,
+                       .has_zl10353    = 0,
+                       .has_eeprom     = 1,
+                       .has_remote     = 1,
+                       .has_radio      = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_0,
+                       .power_led      = TM6010_GPIO_6,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+               .rinput = {
+                       .type   = TM6000_INPUT_RADIO,
+                       .amux   = TM6000_AMUX_ADC1,
+               },
+       },
+       [TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE] = {
+               .name         = "Terratec Cinergy Hybrid XE / Cinergy Hybrid-Stick",
+               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .type         = TM6010,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_dvb      = 1,
+                       .has_zl10353  = 1,
+                       .has_eeprom   = 1,
+                       .has_remote   = 1,
+                       .has_radio    = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_2,
+                       .tuner_on       = TM6010_GPIO_3,
+                       .demod_reset    = TM6010_GPIO_1,
+                       .demod_on       = TM6010_GPIO_4,
+                       .power_led      = TM6010_GPIO_7,
+                       .dvb_led        = TM6010_GPIO_5,
+                       .ir             = TM6010_GPIO_0,
+               },
+               .ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS,
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+               .rinput = {
+                       .type = TM6000_INPUT_RADIO,
+                       .amux = TM6000_AMUX_SIF1,
+               },
+       },
+       [TM5600_BOARD_TERRATEC_GRABSTER] = {
+               .name         = "Terratec Grabster AV 150/250 MX",
+               .type         = TM5600,
+               .tuner_type   = TUNER_ABSENT,
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_ADC1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6010_BOARD_TWINHAN_TU501] = {
+               .name         = "Twinhan TU501(704D1)",
+               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .type         = TM6010,
+               .caps = {
+                       .has_tuner    = 1,
+                       .has_dvb      = 1,
+                       .has_zl10353  = 1,
+                       .has_eeprom   = 1,
+                       .has_remote   = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_2,
+                       .tuner_on       = TM6010_GPIO_3,
+                       .demod_reset    = TM6010_GPIO_1,
+                       .demod_on       = TM6010_GPIO_4,
+                       .power_led      = TM6010_GPIO_7,
+                       .dvb_led        = TM6010_GPIO_5,
+                       .ir             = TM6010_GPIO_0,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       }, {
+                       .type   = TM6000_INPUT_COMPOSITE1,
+                       .vmux   = TM6000_VMUX_VIDEO_A,
+                       .amux   = TM6000_AMUX_ADC2,
+                       }, {
+                       .type   = TM6000_INPUT_SVIDEO,
+                       .vmux   = TM6000_VMUX_VIDEO_AB,
+                       .amux   = TM6000_AMUX_ADC2,
+                       },
+               },
+       },
+       [TM6010_BOARD_BEHOLD_WANDER_LITE] = {
+               .name         = "Beholder Wander Lite DVB-T/TV/FM USB2.0",
+               .tuner_type   = TUNER_XC5000,
+               .tuner_addr   = 0xc2 >> 1,
+               .demod_addr   = 0x1e >> 1,
+               .type         = TM6010,
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_dvb        = 1,
+                       .has_zl10353    = 1,
+                       .has_eeprom     = 1,
+                       .has_remote     = 0,
+                       .has_radio      = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_0,
+                       .demod_reset    = TM6010_GPIO_1,
+                       .power_led      = TM6010_GPIO_6,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       },
+               },
+               .rinput = {
+                       .type   = TM6000_INPUT_RADIO,
+                       .amux   = TM6000_AMUX_ADC1,
+               },
+       },
+       [TM6010_BOARD_BEHOLD_VOYAGER_LITE] = {
+               .name         = "Beholder Voyager Lite TV/FM USB2.0",
+               .tuner_type   = TUNER_XC5000,
+               .tuner_addr   = 0xc2 >> 1,
+               .type         = TM6010,
+               .caps = {
+                       .has_tuner      = 1,
+                       .has_dvb        = 0,
+                       .has_zl10353    = 0,
+                       .has_eeprom     = 1,
+                       .has_remote     = 0,
+                       .has_radio      = 1,
+               },
+               .gpio = {
+                       .tuner_reset    = TM6010_GPIO_0,
+                       .power_led      = TM6010_GPIO_6,
+               },
+               .vinput = { {
+                       .type   = TM6000_INPUT_TV,
+                       .vmux   = TM6000_VMUX_VIDEO_B,
+                       .amux   = TM6000_AMUX_SIF1,
+                       },
+               },
+               .rinput = {
+                       .type   = TM6000_INPUT_RADIO,
+                       .amux   = TM6000_AMUX_ADC1,
+               },
+       },
+};
+
+/* table of devices that work with this driver */
+static struct usb_device_id tm6000_id_table[] = {
+       { USB_DEVICE(0x6000, 0x0001), .driver_info = TM5600_BOARD_GENERIC },
+       { USB_DEVICE(0x6000, 0x0002), .driver_info = TM6010_BOARD_GENERIC },
+       { USB_DEVICE(0x06e1, 0xf332), .driver_info = TM6000_BOARD_ADSTECH_DUAL_TV },
+       { USB_DEVICE(0x14aa, 0x0620), .driver_info = TM6000_BOARD_FREECOM_AND_SIMILAR },
+       { USB_DEVICE(0x06e1, 0xb339), .driver_info = TM6000_BOARD_ADSTECH_MINI_DUAL_TV },
+       { USB_DEVICE(0x2040, 0x6600), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
+       { USB_DEVICE(0x2040, 0x6601), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
+       { USB_DEVICE(0x2040, 0x6610), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
+       { USB_DEVICE(0x2040, 0x6611), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
+       { USB_DEVICE(0x6000, 0xdec0), .driver_info = TM6010_BOARD_BEHOLD_WANDER },
+       { USB_DEVICE(0x6000, 0xdec1), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER },
+       { USB_DEVICE(0x0ccd, 0x0086), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE },
+       { USB_DEVICE(0x0ccd, 0x00A5), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE },
+       { USB_DEVICE(0x0ccd, 0x0079), .driver_info = TM5600_BOARD_TERRATEC_GRABSTER },
+       { USB_DEVICE(0x13d3, 0x3240), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
+       { USB_DEVICE(0x13d3, 0x3241), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
+       { USB_DEVICE(0x13d3, 0x3243), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
+       { USB_DEVICE(0x13d3, 0x3264), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
+       { USB_DEVICE(0x6000, 0xdec2), .driver_info = TM6010_BOARD_BEHOLD_WANDER_LITE },
+       { USB_DEVICE(0x6000, 0xdec3), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER_LITE },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, tm6000_id_table);
+
+/* Control power led for show some activity */
+void tm6000_flash_led(struct tm6000_core *dev, u8 state)
+{
+       /* Power LED unconfigured */
+       if (!dev->gpio.power_led)
+               return;
+
+       /* ON Power LED */
+       if (state) {
+               switch (dev->model) {
+               case TM6010_BOARD_HAUPPAUGE_900H:
+               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+               case TM6010_BOARD_TWINHAN_TU501:
+                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                               dev->gpio.power_led, 0x00);
+                       break;
+               case TM6010_BOARD_BEHOLD_WANDER:
+               case TM6010_BOARD_BEHOLD_VOYAGER:
+               case TM6010_BOARD_BEHOLD_WANDER_LITE:
+               case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
+                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                               dev->gpio.power_led, 0x01);
+                       break;
+               }
+       }
+       /* OFF Power LED */
+       else {
+               switch (dev->model) {
+               case TM6010_BOARD_HAUPPAUGE_900H:
+               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+               case TM6010_BOARD_TWINHAN_TU501:
+                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                               dev->gpio.power_led, 0x01);
+                       break;
+               case TM6010_BOARD_BEHOLD_WANDER:
+               case TM6010_BOARD_BEHOLD_VOYAGER:
+               case TM6010_BOARD_BEHOLD_WANDER_LITE:
+               case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
+                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                               dev->gpio.power_led, 0x00);
+                       break;
+               }
+       }
+}
+
+/* Tuner callback to provide the proper gpio changes needed for xc5000 */
+int tm6000_xc5000_callback(void *ptr, int component, int command, int arg)
+{
+       int rc = 0;
+       struct tm6000_core *dev = ptr;
+
+       if (dev->tuner_type != TUNER_XC5000)
+               return 0;
+
+       switch (command) {
+       case XC5000_TUNER_RESET:
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                              dev->gpio.tuner_reset, 0x01);
+               msleep(15);
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                              dev->gpio.tuner_reset, 0x00);
+               msleep(15);
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                              dev->gpio.tuner_reset, 0x01);
+               break;
+       }
+       return rc;
+}
+EXPORT_SYMBOL_GPL(tm6000_xc5000_callback);
+
+/* Tuner callback to provide the proper gpio changes needed for xc2028 */
+
+int tm6000_tuner_callback(void *ptr, int component, int command, int arg)
+{
+       int rc = 0;
+       struct tm6000_core *dev = ptr;
+
+       if (dev->tuner_type != TUNER_XC2028)
+               return 0;
+
+       switch (command) {
+       case XC2028_RESET_CLK:
+               tm6000_ir_wait(dev, 0);
+
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT,
+                                       0x02, arg);
+               msleep(10);
+               rc = tm6000_i2c_reset(dev, 10);
+               break;
+       case XC2028_TUNER_RESET:
+               /* Reset codes during load firmware */
+               switch (arg) {
+               case 0:
+                       /* newer tuner can faster reset */
+                       switch (dev->model) {
+                       case TM5600_BOARD_10MOONS_UT821:
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x01);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              0x300, 0x01);
+                               msleep(10);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x00);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              0x300, 0x00);
+                               msleep(10);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x01);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              0x300, 0x01);
+                               break;
+                       case TM6010_BOARD_HAUPPAUGE_900H:
+                       case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+                       case TM6010_BOARD_TWINHAN_TU501:
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x01);
+                               msleep(60);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x00);
+                               msleep(75);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x01);
+                               msleep(60);
+                               break;
+                       default:
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x00);
+                               msleep(130);
+                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                              dev->gpio.tuner_reset, 0x01);
+                               msleep(130);
+                               break;
+                       }
+
+                       tm6000_ir_wait(dev, 1);
+                       break;
+               case 1:
+                       tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT,
+                                               0x02, 0x01);
+                       msleep(10);
+                       break;
+               case 2:
+                       rc = tm6000_i2c_reset(dev, 100);
+                       break;
+               }
+               break;
+       case XC2028_I2C_FLUSH:
+               tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
+               tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
+               break;
+       }
+       return rc;
+}
+EXPORT_SYMBOL_GPL(tm6000_tuner_callback);
+
+int tm6000_cards_setup(struct tm6000_core *dev)
+{
+       /*
+        * Board-specific initialization sequence. Handles all GPIO
+        * initialization sequences that are board-specific.
+        * Up to now, all found devices use GPIO1 and GPIO4 at the same way.
+        * Probably, they're all based on some reference device. Due to that,
+        * there's a common routine at the end to handle those GPIO's. Devices
+        * that use different pinups or init sequences can just return at
+        * the board-specific session.
+        */
+       switch (dev->model) {
+       case TM6010_BOARD_HAUPPAUGE_900H:
+       case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+       case TM6010_BOARD_TWINHAN_TU501:
+       case TM6010_BOARD_GENERIC:
+               /* Turn xceive 3028 on */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.tuner_on, 0x01);
+               msleep(15);
+               /* Turn zarlink zl10353 on */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00);
+               msleep(15);
+               /* Reset zarlink zl10353 */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00);
+               msleep(50);
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01);
+               msleep(15);
+               /* Turn zarlink zl10353 off */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x01);
+               msleep(15);
+               /* ir ? */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.ir, 0x01);
+               msleep(15);
+               /* Power led on (blue) */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x00);
+               msleep(15);
+               /* DVB led off (orange) */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.dvb_led, 0x01);
+               msleep(15);
+               /* Turn zarlink zl10353 on */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00);
+               msleep(15);
+               break;
+       case TM6010_BOARD_BEHOLD_WANDER:
+       case TM6010_BOARD_BEHOLD_WANDER_LITE:
+               /* Power led on (blue) */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01);
+               msleep(15);
+               /* Reset zarlink zl10353 */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00);
+               msleep(50);
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01);
+               msleep(15);
+               break;
+       case TM6010_BOARD_BEHOLD_VOYAGER:
+       case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
+               /* Power led on (blue) */
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01);
+               msleep(15);
+               break;
+       default:
+               break;
+       }
+
+       /*
+        * Default initialization. Most of the devices seem to use GPIO1
+        * and GPIO4.on the same way, so, this handles the common sequence
+        * used by most devices.
+        * If a device uses a different sequence or different GPIO pins for
+        * reset, just add the code at the board-specific part
+        */
+
+       if (dev->gpio.tuner_reset) {
+               int rc;
+               int i;
+
+               for (i = 0; i < 2; i++) {
+                       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                               dev->gpio.tuner_reset, 0x00);
+                       if (rc < 0) {
+                               printk(KERN_ERR "Error %i doing tuner reset\n", rc);
+                               return rc;
+                       }
+
+                       msleep(10); /* Just to be conservative */
+                       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                                               dev->gpio.tuner_reset, 0x01);
+                       if (rc < 0) {
+                               printk(KERN_ERR "Error %i doing tuner reset\n", rc);
+                               return rc;
+                       }
+               }
+       } else {
+               printk(KERN_ERR "Tuner reset is not configured\n");
+               return -1;
+       }
+
+       msleep(50);
+
+       return 0;
+};
+
+static void tm6000_config_tuner(struct tm6000_core *dev)
+{
+       struct tuner_setup tun_setup;
+
+       /* Load tuner module */
+       v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+               "tuner", dev->tuner_addr, NULL);
+
+       memset(&tun_setup, 0, sizeof(tun_setup));
+       tun_setup.type = dev->tuner_type;
+       tun_setup.addr = dev->tuner_addr;
+
+       tun_setup.mode_mask = 0;
+       if (dev->caps.has_tuner)
+               tun_setup.mode_mask |= (T_ANALOG_TV | T_RADIO);
+
+       switch (dev->tuner_type) {
+       case TUNER_XC2028:
+               tun_setup.tuner_callback = tm6000_tuner_callback;
+               break;
+       case TUNER_XC5000:
+               tun_setup.tuner_callback = tm6000_xc5000_callback;
+               break;
+       }
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
+
+       switch (dev->tuner_type) {
+       case TUNER_XC2028: {
+               struct v4l2_priv_tun_config xc2028_cfg;
+               struct xc2028_ctrl ctl;
+
+               memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
+               memset(&ctl, 0, sizeof(ctl));
+
+               ctl.demod = XC3028_FE_ZARLINK456;
+
+               xc2028_cfg.tuner = TUNER_XC2028;
+               xc2028_cfg.priv  = &ctl;
+
+               switch (dev->model) {
+               case TM6010_BOARD_HAUPPAUGE_900H:
+               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+               case TM6010_BOARD_TWINHAN_TU501:
+                       ctl.max_len = 80;
+                       ctl.fname = "xc3028L-v36.fw";
+                       break;
+               default:
+                       if (dev->dev_type == TM6010)
+                               ctl.fname = "xc3028-v27.fw";
+                       else
+                               ctl.fname = "xc3028-v24.fw";
+               }
+
+               printk(KERN_INFO "Setting firmware parameters for xc2028\n");
+               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config,
+                                    &xc2028_cfg);
+
+               }
+               break;
+       case TUNER_XC5000:
+               {
+               struct v4l2_priv_tun_config  xc5000_cfg;
+               struct xc5000_config ctl = {
+                       .i2c_address = dev->tuner_addr,
+                       .if_khz      = 4570,
+                       .radio_input = XC5000_RADIO_FM1_MONO,
+                       };
+
+               xc5000_cfg.tuner = TUNER_XC5000;
+               xc5000_cfg.priv  = &ctl;
+
+               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config,
+                                    &xc5000_cfg);
+               }
+               break;
+       default:
+               printk(KERN_INFO "Unknown tuner type. Tuner is not configured.\n");
+               break;
+       }
+}
+
+static int fill_board_specific_data(struct tm6000_core *dev)
+{
+       int rc;
+
+       dev->dev_type   = tm6000_boards[dev->model].type;
+       dev->tuner_type = tm6000_boards[dev->model].tuner_type;
+       dev->tuner_addr = tm6000_boards[dev->model].tuner_addr;
+
+       dev->gpio = tm6000_boards[dev->model].gpio;
+
+       dev->ir_codes = tm6000_boards[dev->model].ir_codes;
+
+       dev->demod_addr = tm6000_boards[dev->model].demod_addr;
+
+       dev->caps = tm6000_boards[dev->model].caps;
+
+       dev->vinput[0] = tm6000_boards[dev->model].vinput[0];
+       dev->vinput[1] = tm6000_boards[dev->model].vinput[1];
+       dev->vinput[2] = tm6000_boards[dev->model].vinput[2];
+       dev->rinput = tm6000_boards[dev->model].rinput;
+
+       /* setup per-model quirks */
+       switch (dev->model) {
+       case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+       case TM6010_BOARD_HAUPPAUGE_900H:
+               dev->quirks |= TM6000_QUIRK_NO_USB_DELAY;
+               break;
+
+       default:
+               break;
+       }
+
+       /* initialize hardware */
+       rc = tm6000_init(dev);
+       if (rc < 0)
+               return rc;
+
+       return v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev);
+}
+
+
+static void use_alternative_detection_method(struct tm6000_core *dev)
+{
+       int i, model = -1;
+
+       if (!dev->eedata_size)
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(tm6000_boards); i++) {
+               if (!tm6000_boards[i].eename_size)
+                       continue;
+               if (dev->eedata_size < tm6000_boards[i].eename_pos +
+                                      tm6000_boards[i].eename_size)
+                       continue;
+
+               if (!memcmp(&dev->eedata[tm6000_boards[i].eename_pos],
+                           tm6000_boards[i].eename,
+                           tm6000_boards[i].eename_size)) {
+                       model = i;
+                       break;
+               }
+       }
+       if (model < 0) {
+               printk(KERN_INFO "Device has eeprom but is currently unknown\n");
+               return;
+       }
+
+       dev->model = model;
+
+       printk(KERN_INFO "Device identified via eeprom as %s (type = %d)\n",
+              tm6000_boards[model].name, model);
+}
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
+static void request_module_async(struct work_struct *work)
+{
+       struct tm6000_core *dev = container_of(work, struct tm6000_core,
+                                              request_module_wk);
+
+       request_module("tm6000-alsa");
+
+       if (dev->caps.has_dvb)
+               request_module("tm6000-dvb");
+}
+
+static void request_modules(struct tm6000_core *dev)
+{
+       INIT_WORK(&dev->request_module_wk, request_module_async);
+       schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_modules(struct tm6000_core *dev)
+{
+       flush_work_sync(&dev->request_module_wk);
+}
+#else
+#define request_modules(dev)
+#define flush_request_modules(dev)
+#endif /* CONFIG_MODULES */
+
+static int tm6000_init_dev(struct tm6000_core *dev)
+{
+       struct v4l2_frequency f;
+       int rc = 0;
+
+       mutex_init(&dev->lock);
+       mutex_lock(&dev->lock);
+
+       if (!is_generic(dev->model)) {
+               rc = fill_board_specific_data(dev);
+               if (rc < 0)
+                       goto err;
+
+               /* register i2c bus */
+               rc = tm6000_i2c_register(dev);
+               if (rc < 0)
+                       goto err;
+       } else {
+               /* register i2c bus */
+               rc = tm6000_i2c_register(dev);
+               if (rc < 0)
+                       goto err;
+
+               use_alternative_detection_method(dev);
+
+               rc = fill_board_specific_data(dev);
+               if (rc < 0)
+                       goto err;
+       }
+
+       /* Default values for STD and resolutions */
+       dev->width = 720;
+       dev->height = 480;
+       dev->norm = V4L2_STD_PAL_M;
+
+       /* Configure tuner */
+       tm6000_config_tuner(dev);
+
+       /* Set video standard */
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
+
+       /* Set tuner frequency - also loads firmware on xc2028/xc3028 */
+       f.tuner = 0;
+       f.type = V4L2_TUNER_ANALOG_TV;
+       f.frequency = 3092;     /* 193.25 MHz */
+       dev->freq = f.frequency;
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
+
+       if (dev->caps.has_tda9874)
+               v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+                       "tvaudio", I2C_ADDR_TDA9874, NULL);
+
+       /* register and initialize V4L2 */
+       rc = tm6000_v4l2_register(dev);
+       if (rc < 0)
+               goto err;
+
+       tm6000_add_into_devlist(dev);
+       tm6000_init_extension(dev);
+
+       tm6000_ir_init(dev);
+
+       request_modules(dev);
+
+       mutex_unlock(&dev->lock);
+       return 0;
+
+err:
+       mutex_unlock(&dev->lock);
+       return rc;
+}
+
+/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
+#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
+
+static void get_max_endpoint(struct usb_device *udev,
+                            struct usb_host_interface *alt,
+                            char *msgtype,
+                            struct usb_host_endpoint *curr_e,
+                            struct tm6000_endpoint *tm_ep)
+{
+       u16 tmp = le16_to_cpu(curr_e->desc.wMaxPacketSize);
+       unsigned int size = tmp & 0x7ff;
+
+       if (udev->speed == USB_SPEED_HIGH)
+               size = size * hb_mult(tmp);
+
+       if (size > tm_ep->maxsize) {
+               tm_ep->endp = curr_e;
+               tm_ep->maxsize = size;
+               tm_ep->bInterfaceNumber = alt->desc.bInterfaceNumber;
+               tm_ep->bAlternateSetting = alt->desc.bAlternateSetting;
+
+               printk(KERN_INFO "tm6000: %s endpoint: 0x%02x (max size=%u bytes)\n",
+                                       msgtype, curr_e->desc.bEndpointAddress,
+                                       size);
+       }
+}
+
+/*
+ * tm6000_usb_probe()
+ * checks for supported devices
+ */
+static int tm6000_usb_probe(struct usb_interface *interface,
+                           const struct usb_device_id *id)
+{
+       struct usb_device *usbdev;
+       struct tm6000_core *dev = NULL;
+       int i, rc = 0;
+       int nr = 0;
+       char *speed;
+
+       usbdev = usb_get_dev(interface_to_usbdev(interface));
+
+       /* Selects the proper interface */
+       rc = usb_set_interface(usbdev, 0, 1);
+       if (rc < 0)
+               goto err;
+
+       /* Check to see next free device and mark as used */
+       nr = find_first_zero_bit(&tm6000_devused, TM6000_MAXBOARDS);
+       if (nr >= TM6000_MAXBOARDS) {
+               printk(KERN_ERR "tm6000: Supports only %i tm60xx boards.\n", TM6000_MAXBOARDS);
+               usb_put_dev(usbdev);
+               return -ENOMEM;
+       }
+
+       /* Create and initialize dev struct */
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (dev == NULL) {
+               printk(KERN_ERR "tm6000" ": out of memory!\n");
+               usb_put_dev(usbdev);
+               return -ENOMEM;
+       }
+       spin_lock_init(&dev->slock);
+       mutex_init(&dev->usb_lock);
+
+       /* Increment usage count */
+       set_bit(nr, &tm6000_devused);
+       snprintf(dev->name, 29, "tm6000 #%d", nr);
+
+       dev->model = id->driver_info;
+       if (card[nr] < ARRAY_SIZE(tm6000_boards))
+               dev->model = card[nr];
+
+       dev->udev = usbdev;
+       dev->devno = nr;
+
+       switch (usbdev->speed) {
+       case USB_SPEED_LOW:
+               speed = "1.5";
+               break;
+       case USB_SPEED_UNKNOWN:
+       case USB_SPEED_FULL:
+               speed = "12";
+               break;
+       case USB_SPEED_HIGH:
+               speed = "480";
+               break;
+       default:
+               speed = "unknown";
+       }
+
+       /* Get endpoints */
+       for (i = 0; i < interface->num_altsetting; i++) {
+               int ep;
+
+               for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) {
+                       struct usb_host_endpoint        *e;
+                       int dir_out;
+
+                       e = &interface->altsetting[i].endpoint[ep];
+
+                       dir_out = ((e->desc.bEndpointAddress &
+                                       USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+
+                       printk(KERN_INFO "tm6000: alt %d, interface %i, class %i\n",
+                              i,
+                              interface->altsetting[i].desc.bInterfaceNumber,
+                              interface->altsetting[i].desc.bInterfaceClass);
+
+                       switch (e->desc.bmAttributes) {
+                       case USB_ENDPOINT_XFER_BULK:
+                               if (!dir_out) {
+                                       get_max_endpoint(usbdev,
+                                                        &interface->altsetting[i],
+                                                        "Bulk IN", e,
+                                                        &dev->bulk_in);
+                               } else {
+                                       get_max_endpoint(usbdev,
+                                                        &interface->altsetting[i],
+                                                        "Bulk OUT", e,
+                                                        &dev->bulk_out);
+                               }
+                               break;
+                       case USB_ENDPOINT_XFER_ISOC:
+                               if (!dir_out) {
+                                       get_max_endpoint(usbdev,
+                                                        &interface->altsetting[i],
+                                                        "ISOC IN", e,
+                                                        &dev->isoc_in);
+                               } else {
+                                       get_max_endpoint(usbdev,
+                                                        &interface->altsetting[i],
+                                                        "ISOC OUT", e,
+                                                        &dev->isoc_out);
+                               }
+                               break;
+                       case USB_ENDPOINT_XFER_INT:
+                               if (!dir_out) {
+                                       get_max_endpoint(usbdev,
+                                                       &interface->altsetting[i],
+                                                       "INT IN", e,
+                                                       &dev->int_in);
+                               } else {
+                                       get_max_endpoint(usbdev,
+                                                       &interface->altsetting[i],
+                                                       "INT OUT", e,
+                                                       &dev->int_out);
+                               }
+                               break;
+                       }
+               }
+       }
+
+
+       printk(KERN_INFO "tm6000: New video device @ %s Mbps (%04x:%04x, ifnum %d)\n",
+               speed,
+               le16_to_cpu(dev->udev->descriptor.idVendor),
+               le16_to_cpu(dev->udev->descriptor.idProduct),
+               interface->altsetting->desc.bInterfaceNumber);
+
+/* check if the the device has the iso in endpoint at the correct place */
+       if (!dev->isoc_in.endp) {
+               printk(KERN_ERR "tm6000: probing error: no IN ISOC endpoint!\n");
+               rc = -ENODEV;
+
+               goto err;
+       }
+
+       /* save our data pointer in this interface device */
+       usb_set_intfdata(interface, dev);
+
+       printk(KERN_INFO "tm6000: Found %s\n", tm6000_boards[dev->model].name);
+
+       rc = tm6000_init_dev(dev);
+       if (rc < 0)
+               goto err;
+
+       return 0;
+
+err:
+       printk(KERN_ERR "tm6000: Error %d while registering\n", rc);
+
+       clear_bit(nr, &tm6000_devused);
+       usb_put_dev(usbdev);
+
+       kfree(dev);
+       return rc;
+}
+
+/*
+ * tm6000_usb_disconnect()
+ * called when the device gets diconencted
+ * video device will be unregistered on v4l2_close in case it is still open
+ */
+static void tm6000_usb_disconnect(struct usb_interface *interface)
+{
+       struct tm6000_core *dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+
+       if (!dev)
+               return;
+
+       printk(KERN_INFO "tm6000: disconnecting %s\n", dev->name);
+
+       flush_request_modules(dev);
+
+       tm6000_ir_fini(dev);
+
+       if (dev->gpio.power_led) {
+               switch (dev->model) {
+               case TM6010_BOARD_HAUPPAUGE_900H:
+               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
+               case TM6010_BOARD_TWINHAN_TU501:
+                       /* Power led off */
+                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                               dev->gpio.power_led, 0x01);
+                       msleep(15);
+                       break;
+               case TM6010_BOARD_BEHOLD_WANDER:
+               case TM6010_BOARD_BEHOLD_VOYAGER:
+               case TM6010_BOARD_BEHOLD_WANDER_LITE:
+               case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
+                       /* Power led off */
+                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                               dev->gpio.power_led, 0x00);
+                       msleep(15);
+                       break;
+               }
+       }
+       tm6000_v4l2_unregister(dev);
+
+       tm6000_i2c_unregister(dev);
+
+       v4l2_device_unregister(&dev->v4l2_dev);
+
+       dev->state |= DEV_DISCONNECTED;
+
+       usb_put_dev(dev->udev);
+
+       tm6000_close_extension(dev);
+       tm6000_remove_from_devlist(dev);
+
+       clear_bit(dev->devno, &tm6000_devused);
+       kfree(dev);
+}
+
+static struct usb_driver tm6000_usb_driver = {
+               .name = "tm6000",
+               .probe = tm6000_usb_probe,
+               .disconnect = tm6000_usb_disconnect,
+               .id_table = tm6000_id_table,
+};
+
+module_usb_driver(tm6000_usb_driver);
+
+MODULE_DESCRIPTION("Trident TVMaster TM5600/TM6000/TM6010 USB2 adapter");
+MODULE_AUTHOR("Mauro Carvalho Chehab");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/usb/tm6000/tm6000-core.c b/drivers/media/usb/tm6000/tm6000-core.c
new file mode 100644 (file)
index 0000000..22cc011
--- /dev/null
@@ -0,0 +1,935 @@
+/*
+ *  tm6000-core.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *      - DVB-T support
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation version 2
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include "tm6000.h"
+#include "tm6000-regs.h"
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+
+#define USB_TIMEOUT    (5 * HZ) /* ms */
+
+int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
+                         u16 value, u16 index, u8 *buf, u16 len)
+{
+       int          ret, i;
+       unsigned int pipe;
+       u8           *data = NULL;
+       int delay = 5000;
+
+       mutex_lock(&dev->usb_lock);
+
+       if (len)
+               data = kzalloc(len, GFP_KERNEL);
+
+       if (req_type & USB_DIR_IN)
+               pipe = usb_rcvctrlpipe(dev->udev, 0);
+       else {
+               pipe = usb_sndctrlpipe(dev->udev, 0);
+               memcpy(data, buf, len);
+       }
+
+       if (tm6000_debug & V4L2_DEBUG_I2C) {
+               printk(KERN_DEBUG "(dev %p, pipe %08x): ", dev->udev, pipe);
+
+               printk(KERN_CONT "%s: %02x %02x %02x %02x %02x %02x %02x %02x ",
+                       (req_type & USB_DIR_IN) ? " IN" : "OUT",
+                       req_type, req, value&0xff, value>>8, index&0xff,
+                       index>>8, len&0xff, len>>8);
+
+               if (!(req_type & USB_DIR_IN)) {
+                       printk(KERN_CONT ">>> ");
+                       for (i = 0; i < len; i++)
+                               printk(KERN_CONT " %02x", buf[i]);
+                       printk(KERN_CONT "\n");
+               }
+       }
+
+       ret = usb_control_msg(dev->udev, pipe, req, req_type, value, index,
+                             data, len, USB_TIMEOUT);
+
+       if (req_type &  USB_DIR_IN)
+               memcpy(buf, data, len);
+
+       if (tm6000_debug & V4L2_DEBUG_I2C) {
+               if (ret < 0) {
+                       if (req_type &  USB_DIR_IN)
+                               printk(KERN_DEBUG "<<< (len=%d)\n", len);
+
+                       printk(KERN_CONT "%s: Error #%d\n", __func__, ret);
+               } else if (req_type &  USB_DIR_IN) {
+                       printk(KERN_CONT "<<< ");
+                       for (i = 0; i < len; i++)
+                               printk(KERN_CONT " %02x", buf[i]);
+                       printk(KERN_CONT "\n");
+               }
+       }
+
+       kfree(data);
+
+       if (dev->quirks & TM6000_QUIRK_NO_USB_DELAY)
+               delay = 0;
+
+       if (req == REQ_16_SET_GET_I2C_WR1_RDN && !(req_type & USB_DIR_IN)) {
+               unsigned int tsleep;
+               /* Calculate delay time, 14000us for 64 bytes */
+               tsleep = (len * 200) + 200;
+               if (tsleep < delay)
+                       tsleep = delay;
+               usleep_range(tsleep, tsleep + 1000);
+       }
+       else if (delay)
+               usleep_range(delay, delay + 1000);
+
+       mutex_unlock(&dev->usb_lock);
+       return ret;
+}
+
+int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index)
+{
+       return
+               tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
+                                     req, value, index, NULL, 0);
+}
+EXPORT_SYMBOL_GPL(tm6000_set_reg);
+
+int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index)
+{
+       int rc;
+       u8 buf[1];
+
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
+                                       value, index, buf, 1);
+
+       if (rc < 0)
+               return rc;
+
+       return *buf;
+}
+EXPORT_SYMBOL_GPL(tm6000_get_reg);
+
+int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
+                                               u16 index, u16 mask)
+{
+       int rc;
+       u8 buf[1];
+       u8 new_index;
+
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
+                                       value, 0, buf, 1);
+
+       if (rc < 0)
+               return rc;
+
+       new_index = (buf[0] & ~mask) | (index & mask);
+
+       if (new_index == buf[0])
+               return 0;
+
+       return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
+                                     req, value, new_index, NULL, 0);
+}
+EXPORT_SYMBOL_GPL(tm6000_set_reg_mask);
+
+int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index)
+{
+       int rc;
+       u8 buf[2];
+
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
+                                       value, index, buf, 2);
+
+       if (rc < 0)
+               return rc;
+
+       return buf[1]|buf[0]<<8;
+}
+
+int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index)
+{
+       int rc;
+       u8 buf[4];
+
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
+                                       value, index, buf, 4);
+
+       if (rc < 0)
+               return rc;
+
+       return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24;
+}
+
+int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep)
+{
+       int rc;
+
+       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
+       if (rc < 0)
+               return rc;
+
+       msleep(tsleep);
+
+       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
+       msleep(tsleep);
+
+       return rc;
+}
+
+void tm6000_set_fourcc_format(struct tm6000_core *dev)
+{
+       if (dev->dev_type == TM6010) {
+               int val;
+
+               val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, 0) & 0xfc;
+               if (dev->fourcc == V4L2_PIX_FMT_UYVY)
+                       tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val);
+               else
+                       tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val | 1);
+       } else {
+               if (dev->fourcc == V4L2_PIX_FMT_UYVY)
+                       tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
+               else
+                       tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0x90);
+       }
+}
+
+static void tm6000_set_vbi(struct tm6000_core *dev)
+{
+       /*
+        * FIXME:
+        * VBI lines and start/end are different between 60Hz and 50Hz
+        * So, it is very likely that we need to change the config to
+        * something that takes it into account, doing something different
+        * if (dev->norm & V4L2_STD_525_60)
+        */
+
+       if (dev->dev_type == TM6010) {
+               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
+               tm6000_set_reg(dev, TM6010_REQ07_R41_TELETEXT_VBI_CODE1, 0x27);
+               tm6000_set_reg(dev, TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55);
+               tm6000_set_reg(dev, TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7, 0x66);
+               tm6000_set_reg(dev, TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8, 0x66);
+               tm6000_set_reg(dev, TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22, 0x66);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23, 0x00);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES, 0x00);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN, 0x00);
+               tm6000_set_reg(dev,
+                       TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02);
+               tm6000_set_reg(dev, TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35);
+               tm6000_set_reg(dev, TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0);
+               tm6000_set_reg(dev, TM6010_REQ07_R5A_VBI_TELETEXT_DTO1, 0x11);
+               tm6000_set_reg(dev, TM6010_REQ07_R5B_VBI_TELETEXT_DTO0, 0x4c);
+               tm6000_set_reg(dev, TM6010_REQ07_R40_TELETEXT_VBI_CODE0, 0x01);
+               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00);
+       }
+}
+
+int tm6000_init_analog_mode(struct tm6000_core *dev)
+{
+       struct v4l2_frequency f;
+
+       if (dev->dev_type == TM6010) {
+               u8 active = TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE;
+
+               if (!dev->radio)
+                       active |= TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE;
+
+               /* Enable video and audio */
+               tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
+                                                       active, 0x60);
+               /* Disable TS input */
+               tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
+                                                       0x00, 0x40);
+       } else {
+               /* Enables soft reset */
+               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
+
+               if (dev->scaler)
+                       /* Disable Hfilter and Enable TS Drop err */
+                       tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x20);
+               else    /* Enable Hfilter and disable TS Drop err */
+                       tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x80);
+
+               tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x88);
+               tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x23);
+               tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xc0);
+               tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xd8);
+               tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x06);
+               tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f);
+
+               /* AP Software reset */
+               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08);
+               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00);
+
+               tm6000_set_fourcc_format(dev);
+
+               /* Disables soft reset */
+               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00);
+       }
+       msleep(20);
+
+       /* Tuner firmware can now be loaded */
+
+       /*
+        * FIXME: This is a hack! xc3028 "sleeps" when no channel is detected
+        * for more than a few seconds. Not sure why, as this behavior does
+        * not happen on other devices with xc3028. So, I suspect that it
+        * is yet another bug at tm6000. After start sleeping, decoding
+        * doesn't start automatically. Instead, it requires some
+        * I2C commands to wake it up. As we want to have image at the
+        * beginning, we needed to add this hack. The better would be to
+        * discover some way to make tm6000 to wake up without this hack.
+        */
+       f.frequency = dev->freq;
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
+
+       msleep(100);
+       tm6000_set_standard(dev);
+       tm6000_set_vbi(dev);
+       tm6000_set_audio_bitrate(dev, 48000);
+
+       /* switch dvb led off */
+       if (dev->gpio.dvb_led) {
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                       dev->gpio.dvb_led, 0x01);
+       }
+
+       return 0;
+}
+
+int tm6000_init_digital_mode(struct tm6000_core *dev)
+{
+       if (dev->dev_type == TM6010) {
+               /* Disable video and audio */
+               tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
+                               0x00, 0x60);
+               /* Enable TS input */
+               tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
+                               0x40, 0x40);
+               /* all power down, but not the digital data port */
+               tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0x28);
+               tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xfc);
+               tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0xff);
+       } else  {
+               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08);
+               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00);
+               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
+               tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x08);
+               tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c);
+               tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff);
+               tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0xd8);
+               tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x40);
+               tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
+               tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x09);
+               tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x37);
+               tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xd8);
+               tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xc0);
+               tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x60);
+
+               tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c);
+               tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff);
+               tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0x08);
+               msleep(50);
+
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
+               msleep(50);
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x01);
+               msleep(50);
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
+               msleep(100);
+       }
+
+       /* switch dvb led on */
+       if (dev->gpio.dvb_led) {
+               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
+                       dev->gpio.dvb_led, 0x00);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(tm6000_init_digital_mode);
+
+struct reg_init {
+       u8 req;
+       u8 reg;
+       u8 val;
+};
+
+/* The meaning of those initializations are unknown */
+static struct reg_init tm6000_init_tab[] = {
+       /* REG  VALUE */
+       { TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f },
+       { TM6010_REQ07_RFF_SOFT_RESET, 0x08 },
+       { TM6010_REQ07_RFF_SOFT_RESET, 0x00 },
+       { TM6010_REQ07_RD5_POWERSAVE, 0x4f },
+       { TM6000_REQ07_RDA_CLK_SEL, 0x23 },
+       { TM6000_REQ07_RDB_OUT_SEL, 0x08 },
+       { TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x00 },
+       { TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10 },
+       { TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00 },
+       { TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00 },
+       { TM6000_REQ07_REB_VADC_AADC_MODE, 0x64 },      /* 48000 bits/sample, external input */
+       { TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL, 0xc2 },
+
+       { TM6010_REQ07_R3F_RESET, 0x01 },               /* Start of soft reset */
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
+       { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 },
+       { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 },
+       { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 },
+       { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 },
+       { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a },
+       { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 },
+       { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 },
+       { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b },
+       { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 },
+       { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f },
+       { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c },
+       { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c },
+       { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+       { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
+       { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a },
+       { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 },
+       { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 },
+       { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a },
+       { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 },
+       { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 },
+       { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 },
+       { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 },
+       { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 },
+       { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 },
+       { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+       { TM6010_REQ07_RC1_TRESHOLD, 0xd0 },
+       { TM6010_REQ07_RC3_HSTART1, 0x88 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },               /* End of the soft reset */
+       { TM6010_REQ05_R18_IMASK7, 0x00 },
+};
+
+static struct reg_init tm6010_init_tab[] = {
+       { TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x00 },
+       { TM6010_REQ07_RC4_HSTART0, 0xa0 },
+       { TM6010_REQ07_RC6_HEND0, 0x40 },
+       { TM6010_REQ07_RCA_VEND0, 0x31 },
+       { TM6010_REQ07_RCC_ACTIVE_IF, 0xe1 },
+       { TM6010_REQ07_RE0_DVIDEO_SOURCE, 0x03 },
+       { TM6010_REQ07_RFE_POWER_DOWN, 0x7f },
+
+       { TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0 },
+       { TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4 },
+       { TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8 },
+       { TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00 },
+       { TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2 },
+       { TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0 },
+       { TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2 },
+       { TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60 },
+       { TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc },
+
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
+       { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 },
+       { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 },
+       { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 },
+       { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 },
+       { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a },
+       { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 },
+       { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 },
+       { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b },
+       { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 },
+       { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f },
+       { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c },
+       { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c },
+       { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+       { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
+       { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a },
+       { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 },
+       { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 },
+       { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a },
+       { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 },
+       { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 },
+       { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 },
+       { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 },
+       { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 },
+       { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 },
+       { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+       { TM6010_REQ07_RC1_TRESHOLD, 0xd0 },
+       { TM6010_REQ07_RC3_HSTART1, 0x88 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+
+       { TM6010_REQ05_R18_IMASK7, 0x00 },
+
+       { TM6010_REQ07_RDC_IR_LEADER1, 0xaa },
+       { TM6010_REQ07_RDD_IR_LEADER0, 0x30 },
+       { TM6010_REQ07_RDE_IR_PULSE_CNT1, 0x20 },
+       { TM6010_REQ07_RDF_IR_PULSE_CNT0, 0xd0 },
+       { REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 },
+       { TM6010_REQ07_RD8_IR, 0x0f },
+
+       /* set remote wakeup key:any key wakeup */
+       { TM6010_REQ07_RE5_REMOTE_WAKEUP,  0xfe },
+       { TM6010_REQ07_RDA_IR_WAKEUP_SEL,  0xff },
+};
+
+int tm6000_init(struct tm6000_core *dev)
+{
+       int board, rc = 0, i, size;
+       struct reg_init *tab;
+
+       /* Check board revision */
+       board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0);
+       if (board >= 0) {
+               switch (board & 0xff) {
+               case 0xf3:
+                       printk(KERN_INFO "Found tm6000\n");
+                       if (dev->dev_type != TM6000)
+                               dev->dev_type = TM6000;
+                       break;
+               case 0xf4:
+                       printk(KERN_INFO "Found tm6010\n");
+                       if (dev->dev_type != TM6010)
+                               dev->dev_type = TM6010;
+                       break;
+               default:
+                       printk(KERN_INFO "Unknown board version = 0x%08x\n", board);
+               }
+       } else
+               printk(KERN_ERR "Error %i while retrieving board version\n", board);
+
+       if (dev->dev_type == TM6010) {
+               tab = tm6010_init_tab;
+               size = ARRAY_SIZE(tm6010_init_tab);
+       } else {
+               tab = tm6000_init_tab;
+               size = ARRAY_SIZE(tm6000_init_tab);
+       }
+
+       /* Load board's initialization table */
+       for (i = 0; i < size; i++) {
+               rc = tm6000_set_reg(dev, tab[i].req, tab[i].reg, tab[i].val);
+               if (rc < 0) {
+                       printk(KERN_ERR "Error %i while setting req %d, "
+                                       "reg %d to value %d\n", rc,
+                                       tab[i].req, tab[i].reg, tab[i].val);
+                       return rc;
+               }
+       }
+
+       msleep(5); /* Just to be conservative */
+
+       rc = tm6000_cards_setup(dev);
+
+       return rc;
+}
+
+
+int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate)
+{
+       int val = 0;
+       u8 areg_f0 = 0x60; /* ADC MCLK = 250 Fs */
+       u8 areg_0a = 0x91; /* SIF 48KHz */
+
+       switch (bitrate) {
+       case 48000:
+               areg_f0 = 0x60; /* ADC MCLK = 250 Fs */
+               areg_0a = 0x91; /* SIF 48KHz */
+               dev->audio_bitrate = bitrate;
+               break;
+       case 32000:
+               areg_f0 = 0x00; /* ADC MCLK = 375 Fs */
+               areg_0a = 0x90; /* SIF 32KHz */
+               dev->audio_bitrate = bitrate;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+
+       /* enable I2S, if we use sif or external I2S device */
+       if (dev->dev_type == TM6010) {
+               val = tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, areg_0a);
+               if (val < 0)
+                       return val;
+
+               val = tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+                                                       areg_f0, 0xf0);
+               if (val < 0)
+                       return val;
+       } else {
+               val = tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
+                                                       areg_f0, 0xf0);
+               if (val < 0)
+                       return val;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate);
+
+int tm6000_set_audio_rinput(struct tm6000_core *dev)
+{
+       if (dev->dev_type == TM6010) {
+               /* Audio crossbar setting, default SIF1 */
+               u8 areg_f0;
+               u8 areg_07 = 0x10;
+
+               switch (dev->rinput.amux) {
+               case TM6000_AMUX_SIF1:
+               case TM6000_AMUX_SIF2:
+                       areg_f0 = 0x03;
+                       areg_07 = 0x30;
+                       break;
+               case TM6000_AMUX_ADC1:
+                       areg_f0 = 0x00;
+                       break;
+               case TM6000_AMUX_ADC2:
+                       areg_f0 = 0x08;
+                       break;
+               case TM6000_AMUX_I2S:
+                       areg_f0 = 0x04;
+                       break;
+               default:
+                       printk(KERN_INFO "%s: audio input dosn't support\n",
+                               dev->name);
+                       return 0;
+                       break;
+               }
+               /* Set audio input crossbar */
+               tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+                                                       areg_f0, 0x0f);
+               /* Mux overflow workaround */
+               tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+                       areg_07, 0xf0);
+       } else {
+               u8 areg_eb;
+               /* Audio setting, default LINE1 */
+               switch (dev->rinput.amux) {
+               case TM6000_AMUX_ADC1:
+                       areg_eb = 0x00;
+                       break;
+               case TM6000_AMUX_ADC2:
+                       areg_eb = 0x04;
+                       break;
+               default:
+                       printk(KERN_INFO "%s: audio input dosn't support\n",
+                               dev->name);
+                       return 0;
+                       break;
+               }
+               /* Set audio input */
+               tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
+                                                       areg_eb, 0x0f);
+       }
+       return 0;
+}
+
+static void tm6010_set_mute_sif(struct tm6000_core *dev, u8 mute)
+{
+       u8 mute_reg = 0;
+
+       if (mute)
+               mute_reg = 0x08;
+
+       tm6000_set_reg_mask(dev, TM6010_REQ08_R0A_A_I2S_MOD, mute_reg, 0x08);
+}
+
+static void tm6010_set_mute_adc(struct tm6000_core *dev, u8 mute)
+{
+       u8 mute_reg = 0;
+
+       if (mute)
+               mute_reg = 0x20;
+
+       if (dev->dev_type == TM6010) {
+               tm6000_set_reg_mask(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL,
+                                                       mute_reg, 0x20);
+               tm6000_set_reg_mask(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL,
+                                                       mute_reg, 0x20);
+       } else {
+               tm6000_set_reg_mask(dev, TM6000_REQ07_REC_VADC_AADC_LVOL,
+                                                       mute_reg, 0x20);
+               tm6000_set_reg_mask(dev, TM6000_REQ07_RED_VADC_AADC_RVOL,
+                                                       mute_reg, 0x20);
+       }
+}
+
+int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute)
+{
+       enum tm6000_mux mux;
+
+       if (dev->radio)
+               mux = dev->rinput.amux;
+       else
+               mux = dev->vinput[dev->input].amux;
+
+       switch (mux) {
+       case TM6000_AMUX_SIF1:
+       case TM6000_AMUX_SIF2:
+               if (dev->dev_type == TM6010)
+                       tm6010_set_mute_sif(dev, mute);
+               else {
+                       printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has"
+                                       " SIF audio inputs. Please check the %s"
+                                       " configuration.\n", dev->name);
+                       return -EINVAL;
+               }
+               break;
+       case TM6000_AMUX_ADC1:
+       case TM6000_AMUX_ADC2:
+               tm6010_set_mute_adc(dev, mute);
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
+       return 0;
+}
+
+static void tm6010_set_volume_sif(struct tm6000_core *dev, int vol)
+{
+       u8 vol_reg;
+
+       vol_reg = vol & 0x0F;
+
+       if (vol < 0)
+               vol_reg |= 0x40;
+
+       tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, vol_reg);
+       tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, vol_reg);
+}
+
+static void tm6010_set_volume_adc(struct tm6000_core *dev, int vol)
+{
+       u8 vol_reg;
+
+       vol_reg = (vol + 0x10) & 0x1f;
+
+       if (dev->dev_type == TM6010) {
+               tm6000_set_reg(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL, vol_reg);
+               tm6000_set_reg(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL, vol_reg);
+       } else {
+               tm6000_set_reg(dev, TM6000_REQ07_REC_VADC_AADC_LVOL, vol_reg);
+               tm6000_set_reg(dev, TM6000_REQ07_RED_VADC_AADC_RVOL, vol_reg);
+       }
+}
+
+void tm6000_set_volume(struct tm6000_core *dev, int vol)
+{
+       enum tm6000_mux mux;
+
+       if (dev->radio) {
+               mux = dev->rinput.amux;
+               vol += 8; /* Offset to 0 dB */
+       } else
+               mux = dev->vinput[dev->input].amux;
+
+       switch (mux) {
+       case TM6000_AMUX_SIF1:
+       case TM6000_AMUX_SIF2:
+               if (dev->dev_type == TM6010)
+                       tm6010_set_volume_sif(dev, vol);
+               else
+                       printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has"
+                                       " SIF audio inputs. Please check the %s"
+                                       " configuration.\n", dev->name);
+               break;
+       case TM6000_AMUX_ADC1:
+       case TM6000_AMUX_ADC2:
+               tm6010_set_volume_adc(dev, vol);
+               break;
+       default:
+               break;
+       }
+}
+
+static LIST_HEAD(tm6000_devlist);
+static DEFINE_MUTEX(tm6000_devlist_mutex);
+
+/*
+ * tm6000_realease_resource()
+ */
+
+void tm6000_remove_from_devlist(struct tm6000_core *dev)
+{
+       mutex_lock(&tm6000_devlist_mutex);
+       list_del(&dev->devlist);
+       mutex_unlock(&tm6000_devlist_mutex);
+};
+
+void tm6000_add_into_devlist(struct tm6000_core *dev)
+{
+       mutex_lock(&tm6000_devlist_mutex);
+       list_add_tail(&dev->devlist, &tm6000_devlist);
+       mutex_unlock(&tm6000_devlist_mutex);
+};
+
+/*
+ * Extension interface
+ */
+
+static LIST_HEAD(tm6000_extension_devlist);
+
+int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
+                       char *buf, int size)
+{
+       struct tm6000_ops *ops = NULL;
+
+       /* FIXME: tm6000_extension_devlist_lock should be a spinlock */
+
+       if (!list_empty(&tm6000_extension_devlist)) {
+               list_for_each_entry(ops, &tm6000_extension_devlist, next) {
+                       if (ops->fillbuf && ops->type == type)
+                               ops->fillbuf(dev, buf, size);
+               }
+       }
+
+       return 0;
+}
+
+int tm6000_register_extension(struct tm6000_ops *ops)
+{
+       struct tm6000_core *dev = NULL;
+
+       mutex_lock(&tm6000_devlist_mutex);
+       list_add_tail(&ops->next, &tm6000_extension_devlist);
+       list_for_each_entry(dev, &tm6000_devlist, devlist) {
+               ops->init(dev);
+               printk(KERN_INFO "%s: Initialized (%s) extension\n",
+                      dev->name, ops->name);
+       }
+       mutex_unlock(&tm6000_devlist_mutex);
+       return 0;
+}
+EXPORT_SYMBOL(tm6000_register_extension);
+
+void tm6000_unregister_extension(struct tm6000_ops *ops)
+{
+       struct tm6000_core *dev = NULL;
+
+       mutex_lock(&tm6000_devlist_mutex);
+       list_for_each_entry(dev, &tm6000_devlist, devlist)
+               ops->fini(dev);
+
+       printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name);
+       list_del(&ops->next);
+       mutex_unlock(&tm6000_devlist_mutex);
+}
+EXPORT_SYMBOL(tm6000_unregister_extension);
+
+void tm6000_init_extension(struct tm6000_core *dev)
+{
+       struct tm6000_ops *ops = NULL;
+
+       mutex_lock(&tm6000_devlist_mutex);
+       if (!list_empty(&tm6000_extension_devlist)) {
+               list_for_each_entry(ops, &tm6000_extension_devlist, next) {
+                       if (ops->init)
+                               ops->init(dev);
+               }
+       }
+       mutex_unlock(&tm6000_devlist_mutex);
+}
+
+void tm6000_close_extension(struct tm6000_core *dev)
+{
+       struct tm6000_ops *ops = NULL;
+
+       mutex_lock(&tm6000_devlist_mutex);
+       if (!list_empty(&tm6000_extension_devlist)) {
+               list_for_each_entry(ops, &tm6000_extension_devlist, next) {
+                       if (ops->fini)
+                               ops->fini(dev);
+               }
+       }
+       mutex_unlock(&tm6000_devlist_mutex);
+}
diff --git a/drivers/media/usb/tm6000/tm6000-dvb.c b/drivers/media/usb/tm6000/tm6000-dvb.c
new file mode 100644 (file)
index 0000000..e1f3f66
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+ *  tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.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 version 2
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+
+#include "zl10353.h"
+
+#include <media/tuner.h>
+
+#include "tuner-xc2028.h"
+#include "xc5000.h"
+
+MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV cards");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
+MODULE_LICENSE("GPL");
+
+MODULE_SUPPORTED_DEVICE("{{Trident, tm5600},"
+                       "{{Trident, tm6000},"
+                       "{{Trident, tm6010}");
+
+static int debug;
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug message");
+
+static inline void print_err_status(struct tm6000_core *dev,
+                                   int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+       if (packet < 0) {
+               dprintk(dev, 1, "URB status %d [%s].\n",
+                       status, errmsg);
+       } else {
+               dprintk(dev, 1, "URB packet %d, status %d [%s].\n",
+                       packet, status, errmsg);
+       }
+}
+
+static void tm6000_urb_received(struct urb *urb)
+{
+       int ret;
+       struct tm6000_core *dev = urb->context;
+
+       switch (urb->status) {
+       case 0:
+       case -ETIMEDOUT:
+               break;
+       case -ENOENT:
+       case -ECONNRESET:
+       case -ESHUTDOWN:
+               return;
+       default:
+               print_err_status(dev, 0, urb->status);
+       }
+
+       if (urb->actual_length > 0)
+               dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
+                                                  urb->actual_length);
+
+       if (dev->dvb->streams > 0) {
+               ret = usb_submit_urb(urb, GFP_ATOMIC);
+               if (ret < 0) {
+                       printk(KERN_ERR "tm6000:  error %s\n", __func__);
+                       kfree(urb->transfer_buffer);
+                       usb_free_urb(urb);
+               }
+       }
+}
+
+static int tm6000_start_stream(struct tm6000_core *dev)
+{
+       int ret;
+       unsigned int pipe, size;
+       struct tm6000_dvb *dvb = dev->dvb;
+
+       printk(KERN_INFO "tm6000: got start stream request %s\n", __func__);
+
+       if (dev->mode != TM6000_MODE_DIGITAL) {
+               tm6000_init_digital_mode(dev);
+               dev->mode = TM6000_MODE_DIGITAL;
+       }
+
+       dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (dvb->bulk_urb == NULL) {
+               printk(KERN_ERR "tm6000: couldn't allocate urb\n");
+               return -ENOMEM;
+       }
+
+       pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress
+                                                         & USB_ENDPOINT_NUMBER_MASK);
+
+       size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
+       size = size * 15; /* 512 x 8 or 12 or 15 */
+
+       dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
+       if (dvb->bulk_urb->transfer_buffer == NULL) {
+               usb_free_urb(dvb->bulk_urb);
+               printk(KERN_ERR "tm6000: couldn't allocate transfer buffer!\n");
+               return -ENOMEM;
+       }
+
+       usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe,
+                                                dvb->bulk_urb->transfer_buffer,
+                                                size,
+                                                tm6000_urb_received, dev);
+
+       ret = usb_clear_halt(dev->udev, pipe);
+       if (ret < 0) {
+               printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",
+                                                       ret, __func__);
+               return ret;
+       } else
+               printk(KERN_ERR "tm6000: pipe resetted\n");
+
+/*     mutex_lock(&tm6000_driver.open_close_mutex); */
+       ret = usb_submit_urb(dvb->bulk_urb, GFP_ATOMIC);
+
+/*     mutex_unlock(&tm6000_driver.open_close_mutex); */
+       if (ret) {
+               printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n",
+                                                                       ret);
+
+               kfree(dvb->bulk_urb->transfer_buffer);
+               usb_free_urb(dvb->bulk_urb);
+               return ret;
+       }
+
+       return 0;
+}
+
+static void tm6000_stop_stream(struct tm6000_core *dev)
+{
+       struct tm6000_dvb *dvb = dev->dvb;
+
+       if (dvb->bulk_urb) {
+               printk(KERN_INFO "urb killing\n");
+               usb_kill_urb(dvb->bulk_urb);
+               printk(KERN_INFO "urb buffer free\n");
+               kfree(dvb->bulk_urb->transfer_buffer);
+               usb_free_urb(dvb->bulk_urb);
+               dvb->bulk_urb = NULL;
+       }
+}
+
+static int tm6000_start_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct tm6000_core *dev = demux->priv;
+       struct tm6000_dvb *dvb = dev->dvb;
+       printk(KERN_INFO "tm6000: got start feed request %s\n", __func__);
+
+       mutex_lock(&dvb->mutex);
+       if (dvb->streams == 0) {
+               dvb->streams = 1;
+/*             mutex_init(&tm6000_dev->streming_mutex); */
+               tm6000_start_stream(dev);
+       } else
+               ++(dvb->streams);
+       mutex_unlock(&dvb->mutex);
+
+       return 0;
+}
+
+static int tm6000_stop_feed(struct dvb_demux_feed *feed)
+{
+       struct dvb_demux *demux = feed->demux;
+       struct tm6000_core *dev = demux->priv;
+       struct tm6000_dvb *dvb = dev->dvb;
+
+       printk(KERN_INFO "tm6000: got stop feed request %s\n", __func__);
+
+       mutex_lock(&dvb->mutex);
+
+       printk(KERN_INFO "stream %#x\n", dvb->streams);
+       --(dvb->streams);
+       if (dvb->streams == 0) {
+               printk(KERN_INFO "stop stream\n");
+               tm6000_stop_stream(dev);
+/*             mutex_destroy(&tm6000_dev->streaming_mutex); */
+       }
+       mutex_unlock(&dvb->mutex);
+/*     mutex_destroy(&tm6000_dev->streaming_mutex); */
+
+       return 0;
+}
+
+static int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
+{
+       struct tm6000_dvb *dvb = dev->dvb;
+
+       if (dev->caps.has_zl10353) {
+               struct zl10353_config config = {
+                                    .demod_address = dev->demod_addr,
+                                    .no_tuner = 1,
+                                    .parallel_ts = 1,
+                                    .if2 = 45700,
+                                    .disable_i2c_gate_ctrl = 1,
+                                   };
+
+               dvb->frontend = dvb_attach(zl10353_attach, &config,
+                                                          &dev->i2c_adap);
+       } else {
+               printk(KERN_ERR "tm6000: no frontend defined for the device!\n");
+               return -1;
+       }
+
+       return (!dvb->frontend) ? -1 : 0;
+}
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int register_dvb(struct tm6000_core *dev)
+{
+       int ret = -1;
+       struct tm6000_dvb *dvb = dev->dvb;
+
+       mutex_init(&dvb->mutex);
+
+       dvb->streams = 0;
+
+       /* attach the frontend */
+       ret = tm6000_dvb_attach_frontend(dev);
+       if (ret < 0) {
+               printk(KERN_ERR "tm6000: couldn't attach the frontend!\n");
+               goto err;
+       }
+
+       ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T",
+                                       THIS_MODULE, &dev->udev->dev, adapter_nr);
+       dvb->adapter.priv = dev;
+
+       if (dvb->frontend) {
+               switch (dev->tuner_type) {
+               case TUNER_XC2028: {
+                       struct xc2028_config cfg = {
+                               .i2c_adap = &dev->i2c_adap,
+                               .i2c_addr = dev->tuner_addr,
+                       };
+
+                       dvb->frontend->callback = tm6000_tuner_callback;
+                       ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+                       if (ret < 0) {
+                               printk(KERN_ERR
+                                       "tm6000: couldn't register frontend\n");
+                               goto adapter_err;
+                       }
+
+                       if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
+                               printk(KERN_ERR "tm6000: couldn't register "
+                                               "frontend (xc3028)\n");
+                               ret = -EINVAL;
+                               goto frontend_err;
+                       }
+                       printk(KERN_INFO "tm6000: XC2028/3028 asked to be "
+                                        "attached to frontend!\n");
+                       break;
+                       }
+               case TUNER_XC5000: {
+                       struct xc5000_config cfg = {
+                               .i2c_address = dev->tuner_addr,
+                       };
+
+                       dvb->frontend->callback = tm6000_xc5000_callback;
+                       ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
+                       if (ret < 0) {
+                               printk(KERN_ERR
+                                       "tm6000: couldn't register frontend\n");
+                               goto adapter_err;
+                       }
+
+                       if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) {
+                               printk(KERN_ERR "tm6000: couldn't register "
+                                               "frontend (xc5000)\n");
+                               ret = -EINVAL;
+                               goto frontend_err;
+                       }
+                       printk(KERN_INFO "tm6000: XC5000 asked to be "
+                                        "attached to frontend!\n");
+                       break;
+                       }
+               }
+       } else
+               printk(KERN_ERR "tm6000: no frontend found\n");
+
+       dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING
+                                                           | DMX_MEMORY_BASED_FILTERING;
+       dvb->demux.priv = dev;
+       dvb->demux.filternum = 8;
+       dvb->demux.feednum = 8;
+       dvb->demux.start_feed = tm6000_start_feed;
+       dvb->demux.stop_feed = tm6000_stop_feed;
+       dvb->demux.write_to_decoder = NULL;
+       ret = dvb_dmx_init(&dvb->demux);
+       if (ret < 0) {
+               printk(KERN_ERR "tm6000: dvb_dmx_init failed (errno = %d)\n", ret);
+               goto frontend_err;
+       }
+
+       dvb->dmxdev.filternum = dev->dvb->demux.filternum;
+       dvb->dmxdev.demux = &dev->dvb->demux.dmx;
+       dvb->dmxdev.capabilities = 0;
+
+       ret =  dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
+       if (ret < 0) {
+               printk(KERN_ERR "tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret);
+               goto dvb_dmx_err;
+       }
+
+       return 0;
+
+dvb_dmx_err:
+       dvb_dmx_release(&dvb->demux);
+frontend_err:
+       if (dvb->frontend) {
+               dvb_frontend_detach(dvb->frontend);
+               dvb_unregister_frontend(dvb->frontend);
+       }
+adapter_err:
+       dvb_unregister_adapter(&dvb->adapter);
+err:
+       return ret;
+}
+
+static void unregister_dvb(struct tm6000_core *dev)
+{
+       struct tm6000_dvb *dvb = dev->dvb;
+
+       if (dvb->bulk_urb != NULL) {
+               struct urb *bulk_urb = dvb->bulk_urb;
+
+               kfree(bulk_urb->transfer_buffer);
+               bulk_urb->transfer_buffer = NULL;
+               usb_unlink_urb(bulk_urb);
+               usb_free_urb(bulk_urb);
+       }
+
+/*     mutex_lock(&tm6000_driver.open_close_mutex); */
+       if (dvb->frontend) {
+               dvb_frontend_detach(dvb->frontend);
+               dvb_unregister_frontend(dvb->frontend);
+       }
+
+       dvb_dmxdev_release(&dvb->dmxdev);
+       dvb_dmx_release(&dvb->demux);
+       dvb_unregister_adapter(&dvb->adapter);
+       mutex_destroy(&dvb->mutex);
+/*     mutex_unlock(&tm6000_driver.open_close_mutex); */
+}
+
+static int dvb_init(struct tm6000_core *dev)
+{
+       struct tm6000_dvb *dvb;
+       int rc;
+
+       if (!dev)
+               return 0;
+
+       if (!dev->caps.has_dvb)
+               return 0;
+
+       if (dev->udev->speed == USB_SPEED_FULL) {
+               printk(KERN_INFO "This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)\n");
+               return 0;
+       }
+
+       dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL);
+       if (!dvb) {
+               printk(KERN_INFO "Cannot allocate memory\n");
+               return -ENOMEM;
+       }
+
+       dev->dvb = dvb;
+
+       rc = register_dvb(dev);
+       if (rc < 0) {
+               kfree(dvb);
+               dev->dvb = NULL;
+               return 0;
+       }
+
+       return 0;
+}
+
+static int dvb_fini(struct tm6000_core *dev)
+{
+       if (!dev)
+               return 0;
+
+       if (!dev->caps.has_dvb)
+               return 0;
+
+       if (dev->dvb) {
+               unregister_dvb(dev);
+               kfree(dev->dvb);
+               dev->dvb = NULL;
+       }
+
+       return 0;
+}
+
+static struct tm6000_ops dvb_ops = {
+       .type   = TM6000_DVB,
+       .name   = "TM6000 dvb Extension",
+       .init   = dvb_init,
+       .fini   = dvb_fini,
+};
+
+static int __init tm6000_dvb_register(void)
+{
+       return tm6000_register_extension(&dvb_ops);
+}
+
+static void __exit tm6000_dvb_unregister(void)
+{
+       tm6000_unregister_extension(&dvb_ops);
+}
+
+module_init(tm6000_dvb_register);
+module_exit(tm6000_dvb_unregister);
diff --git a/drivers/media/usb/tm6000/tm6000-i2c.c b/drivers/media/usb/tm6000/tm6000-i2c.c
new file mode 100644 (file)
index 0000000..c7e23e3
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ *  tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *     - Fix SMBus Read Byte command
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation version 2
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+#include "tuner-xc2028.h"
+
+
+/* ----------------------------------------------------------- */
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+#define i2c_dprintk(lvl, fmt, args...) if (i2c_debug >= lvl) do { \
+                       printk(KERN_DEBUG "%s at %s: " fmt, \
+                       dev->name, __func__, ##args); } while (0)
+
+static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
+                               __u8 reg, char *buf, int len)
+{
+       int rc;
+       unsigned int i2c_packet_limit = 16;
+
+       if (dev->dev_type == TM6010)
+               i2c_packet_limit = 80;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > i2c_packet_limit) {
+               printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
+                       len, i2c_packet_limit);
+               return -1;
+       }
+
+       /* capture mutex */
+       rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
+               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+               addr | reg << 8, 0, buf, len);
+
+       if (rc < 0) {
+               /* release mutex */
+               return rc;
+       }
+
+       /* release mutex */
+       return rc;
+}
+
+/* Generic read - doesn't work fine with 16bit registers */
+static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr,
+                               __u8 reg, char *buf, int len)
+{
+       int rc;
+       u8 b[2];
+       unsigned int i2c_packet_limit = 16;
+
+       if (dev->dev_type == TM6010)
+               i2c_packet_limit = 64;
+
+       if (!buf)
+               return -1;
+
+       if (len < 1 || len > i2c_packet_limit) {
+               printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
+                       len, i2c_packet_limit);
+               return -1;
+       }
+
+       /* capture mutex */
+       if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
+               /*
+                * Workaround an I2C bug when reading from zl10353
+                */
+               reg -= 1;
+               len += 1;
+
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);
+
+               *buf = b[1];
+       } else {
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
+       }
+
+       /* release mutex */
+       return rc;
+}
+
+/*
+ * read from a 16bit register
+ * for example xc2028, xc3028 or xc3028L
+ */
+static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr,
+                                 __u16 reg, char *buf, int len)
+{
+       int rc;
+       unsigned char ureg;
+
+       if (!buf || len != 2)
+               return -1;
+
+       /* capture mutex */
+       if (dev->dev_type == TM6010) {
+               ureg = reg & 0xFF;
+               rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
+                       USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
+                       addr | (reg & 0xFF00), 0, &ureg, 1);
+
+               if (rc < 0) {
+                       /* release mutex */
+                       return rc;
+               }
+
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+                       USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
+                       reg, 0, buf, len);
+       } else {
+               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
+                       USB_RECIP_DEVICE, REQ_14_SET_GET_I2C_WR2_RDN,
+                       addr, reg, buf, len);
+       }
+
+       /* release mutex */
+       return rc;
+}
+
+static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
+                          struct i2c_msg msgs[], int num)
+{
+       struct tm6000_core *dev = i2c_adap->algo_data;
+       int addr, rc, i, byte;
+
+       if (num <= 0)
+               return 0;
+       for (i = 0; i < num; i++) {
+               addr = (msgs[i].addr << 1) & 0xff;
+               i2c_dprintk(2, "%s %s addr=0x%x len=%d:",
+                        (msgs[i].flags & I2C_M_RD) ? "read" : "write",
+                        i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
+               if (msgs[i].flags & I2C_M_RD) {
+                       /* read request without preceding register selection */
+                       /*
+                        * The TM6000 only supports a read transaction
+                        * immediately after a 1 or 2 byte write to select
+                        * a register.  We cannot fulfil this request.
+                        */
+                       i2c_dprintk(2, " read without preceding write not"
+                                      " supported");
+                       rc = -EOPNOTSUPP;
+                       goto err;
+               } else if (i + 1 < num && msgs[i].len <= 2 &&
+                          (msgs[i + 1].flags & I2C_M_RD) &&
+                          msgs[i].addr == msgs[i + 1].addr) {
+                       /* 1 or 2 byte write followed by a read */
+                       if (i2c_debug >= 2)
+                               for (byte = 0; byte < msgs[i].len; byte++)
+                                       printk(KERN_CONT " %02x", msgs[i].buf[byte]);
+                       i2c_dprintk(2, "; joined to read %s len=%d:",
+                                   i == num - 2 ? "stop" : "nonstop",
+                                   msgs[i + 1].len);
+
+                       if (msgs[i].len == 2) {
+                               rc = tm6000_i2c_recv_regs16(dev, addr,
+                                       msgs[i].buf[0] << 8 | msgs[i].buf[1],
+                                       msgs[i + 1].buf, msgs[i + 1].len);
+                       } else {
+                               rc = tm6000_i2c_recv_regs(dev, addr, msgs[i].buf[0],
+                                       msgs[i + 1].buf, msgs[i + 1].len);
+                       }
+
+                       i++;
+
+                       if (addr == dev->tuner_addr << 1) {
+                               tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
+                               tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
+                       }
+                       if (i2c_debug >= 2)
+                               for (byte = 0; byte < msgs[i].len; byte++)
+                                       printk(KERN_CONT " %02x", msgs[i].buf[byte]);
+               } else {
+                       /* write bytes */
+                       if (i2c_debug >= 2)
+                               for (byte = 0; byte < msgs[i].len; byte++)
+                                       printk(KERN_CONT " %02x", msgs[i].buf[byte]);
+                       rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0],
+                               msgs[i].buf + 1, msgs[i].len - 1);
+               }
+               if (i2c_debug >= 2)
+                       printk(KERN_CONT "\n");
+               if (rc < 0)
+                       goto err;
+       }
+
+       return num;
+err:
+       i2c_dprintk(2, " ERROR: %i\n", rc);
+       return rc;
+}
+
+static int tm6000_i2c_eeprom(struct tm6000_core *dev)
+{
+       int i, rc;
+       unsigned char *p = dev->eedata;
+       unsigned char bytes[17];
+
+       dev->i2c_client.addr = 0xa0 >> 1;
+       dev->eedata_size = 0;
+
+       bytes[16] = '\0';
+       for (i = 0; i < sizeof(dev->eedata); ) {
+               *p = i;
+               rc = tm6000_i2c_recv_regs(dev, 0xa0, i, p, 1);
+               if (rc < 1) {
+                       if (p == dev->eedata)
+                               goto noeeprom;
+                       else {
+                               printk(KERN_WARNING
+                               "%s: i2c eeprom read error (err=%d)\n",
+                               dev->name, rc);
+                       }
+                       return -EINVAL;
+               }
+               dev->eedata_size++;
+               p++;
+               if (0 == (i % 16))
+                       printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
+               printk(KERN_CONT " %02x", dev->eedata[i]);
+               if ((dev->eedata[i] >= ' ') && (dev->eedata[i] <= 'z'))
+                       bytes[i%16] = dev->eedata[i];
+               else
+                       bytes[i%16] = '.';
+
+               i++;
+
+               if (0 == (i % 16)) {
+                       bytes[16] = '\0';
+                       printk(KERN_CONT "  %s\n", bytes);
+               }
+       }
+       if (0 != (i%16)) {
+               bytes[i%16] = '\0';
+               for (i %= 16; i < 16; i++)
+                       printk(KERN_CONT "   ");
+               printk(KERN_CONT "  %s\n", bytes);
+       }
+
+       return 0;
+
+noeeprom:
+       printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
+              dev->name, rc);
+       return -EINVAL;
+}
+
+/* ----------------------------------------------------------- */
+
+/*
+ * functionality()
+ */
+static u32 functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm tm6000_algo = {
+       .master_xfer   = tm6000_i2c_xfer,
+       .functionality = functionality,
+};
+
+/* ----------------------------------------------------------- */
+
+/*
+ * tm6000_i2c_register()
+ * register i2c bus
+ */
+int tm6000_i2c_register(struct tm6000_core *dev)
+{
+       int rc;
+
+       dev->i2c_adap.owner = THIS_MODULE;
+       dev->i2c_adap.algo = &tm6000_algo;
+       dev->i2c_adap.dev.parent = &dev->udev->dev;
+       strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name));
+       dev->i2c_adap.algo_data = dev;
+       i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
+       rc = i2c_add_adapter(&dev->i2c_adap);
+       if (rc)
+               return rc;
+
+       dev->i2c_client.adapter = &dev->i2c_adap;
+       strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE);
+       tm6000_i2c_eeprom(dev);
+
+       return 0;
+}
+
+/*
+ * tm6000_i2c_unregister()
+ * unregister i2c_bus
+ */
+int tm6000_i2c_unregister(struct tm6000_core *dev)
+{
+       i2c_del_adapter(&dev->i2c_adap);
+       return 0;
+}
diff --git a/drivers/media/usb/tm6000/tm6000-input.c b/drivers/media/usb/tm6000/tm6000-input.c
new file mode 100644 (file)
index 0000000..e80b7e1
--- /dev/null
@@ -0,0 +1,498 @@
+/*
+ *  tm6000-input.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2010 Stefan Ringel <stefan.ringel@arcor.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation version 2
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <linux/input.h>
+#include <linux/usb.h>
+
+#include <media/rc-core.h>
+
+#include "tm6000.h"
+#include "tm6000-regs.h"
+
+static unsigned int ir_debug;
+module_param(ir_debug, int, 0644);
+MODULE_PARM_DESC(ir_debug, "debug message level");
+
+static unsigned int enable_ir = 1;
+module_param(enable_ir, int, 0644);
+MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)");
+
+static unsigned int ir_clock_mhz = 12;
+module_param(ir_clock_mhz, int, 0644);
+MODULE_PARM_DESC(enable_ir, "ir clock, in MHz");
+
+#define URB_SUBMIT_DELAY       100     /* ms - Delay to submit an URB request on retrial and init */
+#define URB_INT_LED_DELAY      100     /* ms - Delay to turn led on again on int mode */
+
+#undef dprintk
+
+#define dprintk(level, fmt, arg...) do {\
+       if (ir_debug >= level) \
+               printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
+       } while (0)
+
+struct tm6000_ir_poll_result {
+       u16 rc_data;
+};
+
+struct tm6000_IR {
+       struct tm6000_core      *dev;
+       struct rc_dev           *rc;
+       char                    name[32];
+       char                    phys[32];
+
+       /* poll expernal decoder */
+       int                     polling;
+       struct delayed_work     work;
+       u8                      wait:1;
+       u8                      pwled:2;
+       u8                      submit_urb:1;
+       u16                     key_addr;
+       struct urb              *int_urb;
+
+       /* IR device properties */
+       u64                     rc_type;
+};
+
+void tm6000_ir_wait(struct tm6000_core *dev, u8 state)
+{
+       struct tm6000_IR *ir = dev->ir;
+
+       if (!dev->ir)
+               return;
+
+       dprintk(2, "%s: %i\n",__func__, ir->wait);
+
+       if (state)
+               ir->wait = 1;
+       else
+               ir->wait = 0;
+}
+
+static int tm6000_ir_config(struct tm6000_IR *ir)
+{
+       struct tm6000_core *dev = ir->dev;
+       u32 pulse = 0, leader = 0;
+
+       dprintk(2, "%s\n",__func__);
+
+       /*
+        * The IR decoder supports RC-5 or NEC, with a configurable timing.
+        * The timing configuration there is not that accurate, as it uses
+        * approximate values. The NEC spec mentions a 562.5 unit period,
+        * and RC-5 uses a 888.8 period.
+        * Currently, driver assumes a clock provided by a 12 MHz XTAL, but
+        * a modprobe parameter can adjust it.
+        * Adjustments are required for other timings.
+        * It seems that the 900ms timing for NEC is used to detect a RC-5
+        * IR, in order to discard such decoding
+        */
+
+       switch (ir->rc_type) {
+       case RC_TYPE_NEC:
+               leader = 900;   /* ms */
+               pulse  = 700;   /* ms - the actual value would be 562 */
+               break;
+       default:
+       case RC_TYPE_RC5:
+               leader = 900;   /* ms - from the NEC decoding */
+               pulse  = 1780;  /* ms - The actual value would be 1776 */
+               break;
+       }
+
+       pulse = ir_clock_mhz * pulse;
+       leader = ir_clock_mhz * leader;
+       if (ir->rc_type == RC_TYPE_NEC)
+               leader = leader | 0x8000;
+
+       dprintk(2, "%s: %s, %d MHz, leader = 0x%04x, pulse = 0x%06x \n",
+               __func__,
+               (ir->rc_type == RC_TYPE_NEC) ? "NEC" : "RC-5",
+               ir_clock_mhz, leader, pulse);
+
+       /* Remote WAKEUP = enable, normal mode, from IR decoder output */
+       tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe);
+
+       /* Enable IR reception on non-busrt mode */
+       tm6000_set_reg(dev, TM6010_REQ07_RD8_IR, 0x2f);
+
+       /* IR_WKUP_SEL = Low byte in decoded IR data */
+       tm6000_set_reg(dev, TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff);
+       /* IR_WKU_ADD code */
+       tm6000_set_reg(dev, TM6010_REQ07_RDB_IR_WAKEUP_ADD, 0xff);
+
+       tm6000_set_reg(dev, TM6010_REQ07_RDC_IR_LEADER1, leader >> 8);
+       tm6000_set_reg(dev, TM6010_REQ07_RDD_IR_LEADER0, leader);
+
+       tm6000_set_reg(dev, TM6010_REQ07_RDE_IR_PULSE_CNT1, pulse >> 8);
+       tm6000_set_reg(dev, TM6010_REQ07_RDF_IR_PULSE_CNT0, pulse);
+
+       if (!ir->polling)
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
+       else
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
+       msleep(10);
+
+       /* Shows that IR is working via the LED */
+       tm6000_flash_led(dev, 0);
+       msleep(100);
+       tm6000_flash_led(dev, 1);
+       ir->pwled = 1;
+
+       return 0;
+}
+
+static void tm6000_ir_urb_received(struct urb *urb)
+{
+       struct tm6000_core *dev = urb->context;
+       struct tm6000_IR *ir = dev->ir;
+       struct tm6000_ir_poll_result poll_result;
+       char *buf;
+
+       dprintk(2, "%s\n",__func__);
+       if (urb->status < 0 || urb->actual_length <= 0) {
+               printk(KERN_INFO "tm6000: IR URB failure: status: %i, length %i\n",
+                      urb->status, urb->actual_length);
+               ir->submit_urb = 1;
+               schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
+               return;
+       }
+       buf = urb->transfer_buffer;
+
+       if (ir_debug)
+               print_hex_dump(KERN_DEBUG, "tm6000: IR data: ",
+                              DUMP_PREFIX_OFFSET,16, 1,
+                              buf, urb->actual_length, false);
+
+       poll_result.rc_data = buf[0];
+       if (urb->actual_length > 1)
+               poll_result.rc_data |= buf[1] << 8;
+
+       dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
+       rc_keydown(ir->rc, poll_result.rc_data, 0);
+
+       usb_submit_urb(urb, GFP_ATOMIC);
+       /*
+        * Flash the led. We can't do it here, as it is running on IRQ context.
+        * So, use the scheduler to do it, in a few ms.
+        */
+       ir->pwled = 2;
+       schedule_delayed_work(&ir->work, msecs_to_jiffies(10));
+}
+
+static void tm6000_ir_handle_key(struct work_struct *work)
+{
+       struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
+       struct tm6000_core *dev = ir->dev;
+       struct tm6000_ir_poll_result poll_result;
+       int rc;
+       u8 buf[2];
+
+       if (ir->wait)
+               return;
+
+       dprintk(3, "%s\n",__func__);
+
+       rc = tm6000_read_write_usb(dev, USB_DIR_IN |
+               USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+               REQ_02_GET_IR_CODE, 0, 0, buf, 2);
+       if (rc < 0)
+               return;
+
+       if (rc > 1)
+               poll_result.rc_data = buf[0] | buf[1] << 8;
+       else
+               poll_result.rc_data = buf[0];
+
+       /* Check if something was read */
+       if ((poll_result.rc_data & 0xff) == 0xff) {
+               if (!ir->pwled) {
+                       tm6000_flash_led(dev, 1);
+                       ir->pwled = 1;
+               }
+               return;
+       }
+
+       dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
+       rc_keydown(ir->rc, poll_result.rc_data, 0);
+       tm6000_flash_led(dev, 0);
+       ir->pwled = 0;
+
+       /* Re-schedule polling */
+       schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
+}
+
+static void tm6000_ir_int_work(struct work_struct *work)
+{
+       struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
+       struct tm6000_core *dev = ir->dev;
+       int rc;
+
+       dprintk(3, "%s, submit_urb = %d, pwled = %d\n",__func__, ir->submit_urb,
+               ir->pwled);
+
+       if (ir->submit_urb) {
+               dprintk(3, "Resubmit urb\n");
+               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
+
+               rc = usb_submit_urb(ir->int_urb, GFP_ATOMIC);
+               if (rc < 0) {
+                       printk(KERN_ERR "tm6000: Can't submit an IR interrupt. Error %i\n",
+                              rc);
+                       /* Retry in 100 ms */
+                       schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
+                       return;
+               }
+               ir->submit_urb = 0;
+       }
+
+       /* Led is enabled only if USB submit doesn't fail */
+       if (ir->pwled == 2) {
+               tm6000_flash_led(dev, 0);
+               ir->pwled = 0;
+               schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_INT_LED_DELAY));
+       } else if (!ir->pwled) {
+               tm6000_flash_led(dev, 1);
+               ir->pwled = 1;
+       }
+}
+
+static int tm6000_ir_start(struct rc_dev *rc)
+{
+       struct tm6000_IR *ir = rc->priv;
+
+       dprintk(2, "%s\n",__func__);
+
+       schedule_delayed_work(&ir->work, 0);
+
+       return 0;
+}
+
+static void tm6000_ir_stop(struct rc_dev *rc)
+{
+       struct tm6000_IR *ir = rc->priv;
+
+       dprintk(2, "%s\n",__func__);
+
+       cancel_delayed_work_sync(&ir->work);
+}
+
+static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
+{
+       struct tm6000_IR *ir = rc->priv;
+
+       if (!ir)
+               return 0;
+
+       dprintk(2, "%s\n",__func__);
+
+       if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC))
+               ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff);
+
+       ir->rc_type = rc_type;
+
+       tm6000_ir_config(ir);
+       /* TODO */
+       return 0;
+}
+
+static int __tm6000_ir_int_start(struct rc_dev *rc)
+{
+       struct tm6000_IR *ir = rc->priv;
+       struct tm6000_core *dev = ir->dev;
+       int pipe, size;
+       int err = -ENOMEM;
+
+       if (!ir)
+               return -ENODEV;
+
+       dprintk(2, "%s\n",__func__);
+
+       ir->int_urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!ir->int_urb)
+               return -ENOMEM;
+
+       pipe = usb_rcvintpipe(dev->udev,
+               dev->int_in.endp->desc.bEndpointAddress
+               & USB_ENDPOINT_NUMBER_MASK);
+
+       size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
+       dprintk(1, "IR max size: %d\n", size);
+
+       ir->int_urb->transfer_buffer = kzalloc(size, GFP_ATOMIC);
+       if (ir->int_urb->transfer_buffer == NULL) {
+               usb_free_urb(ir->int_urb);
+               return err;
+       }
+       dprintk(1, "int interval: %d\n", dev->int_in.endp->desc.bInterval);
+
+       usb_fill_int_urb(ir->int_urb, dev->udev, pipe,
+               ir->int_urb->transfer_buffer, size,
+               tm6000_ir_urb_received, dev,
+               dev->int_in.endp->desc.bInterval);
+
+       ir->submit_urb = 1;
+       schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
+
+       return 0;
+}
+
+static void __tm6000_ir_int_stop(struct rc_dev *rc)
+{
+       struct tm6000_IR *ir = rc->priv;
+
+       if (!ir || !ir->int_urb)
+               return;
+
+       dprintk(2, "%s\n",__func__);
+
+       usb_kill_urb(ir->int_urb);
+       kfree(ir->int_urb->transfer_buffer);
+       usb_free_urb(ir->int_urb);
+       ir->int_urb = NULL;
+}
+
+int tm6000_ir_int_start(struct tm6000_core *dev)
+{
+       struct tm6000_IR *ir = dev->ir;
+
+       if (!ir)
+               return 0;
+
+       return __tm6000_ir_int_start(ir->rc);
+}
+
+void tm6000_ir_int_stop(struct tm6000_core *dev)
+{
+       struct tm6000_IR *ir = dev->ir;
+
+       if (!ir || !ir->rc)
+               return;
+
+       __tm6000_ir_int_stop(ir->rc);
+}
+
+int tm6000_ir_init(struct tm6000_core *dev)
+{
+       struct tm6000_IR *ir;
+       struct rc_dev *rc;
+       int err = -ENOMEM;
+
+       if (!enable_ir)
+               return -ENODEV;
+
+       if (!dev->caps.has_remote)
+               return 0;
+
+       if (!dev->ir_codes)
+               return 0;
+
+       ir = kzalloc(sizeof(*ir), GFP_ATOMIC);
+       rc = rc_allocate_device();
+       if (!ir || !rc)
+               goto out;
+
+       dprintk(2, "%s\n", __func__);
+
+       /* record handles to ourself */
+       ir->dev = dev;
+       dev->ir = ir;
+       ir->rc = rc;
+
+       /* input setup */
+       rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
+       /* Neded, in order to support NEC remotes with 24 or 32 bits */
+       rc->scanmask = 0xffff;
+       rc->priv = ir;
+       rc->change_protocol = tm6000_ir_change_protocol;
+       if (dev->int_in.endp) {
+               rc->open    = __tm6000_ir_int_start;
+               rc->close   = __tm6000_ir_int_stop;
+               INIT_DELAYED_WORK(&ir->work, tm6000_ir_int_work);
+       } else {
+               rc->open  = tm6000_ir_start;
+               rc->close = tm6000_ir_stop;
+               ir->polling = 50;
+               INIT_DELAYED_WORK(&ir->work, tm6000_ir_handle_key);
+       }
+       rc->driver_type = RC_DRIVER_SCANCODE;
+
+       snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)",
+                                               dev->name);
+
+       usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
+       strlcat(ir->phys, "/input0", sizeof(ir->phys));
+
+       tm6000_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
+
+       rc->input_name = ir->name;
+       rc->input_phys = ir->phys;
+       rc->input_id.bustype = BUS_USB;
+       rc->input_id.version = 1;
+       rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
+       rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
+       rc->map_name = dev->ir_codes;
+       rc->driver_name = "tm6000";
+       rc->dev.parent = &dev->udev->dev;
+
+       /* ir register */
+       err = rc_register_device(rc);
+       if (err)
+               goto out;
+
+       return 0;
+
+out:
+       dev->ir = NULL;
+       rc_free_device(rc);
+       kfree(ir);
+       return err;
+}
+
+int tm6000_ir_fini(struct tm6000_core *dev)
+{
+       struct tm6000_IR *ir = dev->ir;
+
+       /* skip detach on non attached board */
+
+       if (!ir)
+               return 0;
+
+       dprintk(2, "%s\n",__func__);
+
+       if (!ir->polling)
+               __tm6000_ir_int_stop(ir->rc);
+
+       tm6000_ir_stop(ir->rc);
+
+       /* Turn off the led */
+       tm6000_flash_led(dev, 0);
+       ir->pwled = 0;
+
+       rc_unregister_device(ir->rc);
+
+       kfree(ir);
+       dev->ir = NULL;
+
+       return 0;
+}
diff --git a/drivers/media/usb/tm6000/tm6000-regs.h b/drivers/media/usb/tm6000/tm6000-regs.h
new file mode 100644 (file)
index 0000000..a38c251
--- /dev/null
@@ -0,0 +1,600 @@
+/*
+ *  tm6000-regs.h - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation version 2
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Define TV Master TM5600/TM6000/TM6010 Request codes
+ */
+#define REQ_00_SET_IR_VALUE            0
+#define REQ_01_SET_WAKEUP_IRCODE       1
+#define REQ_02_GET_IR_CODE             2
+#define REQ_03_SET_GET_MCU_PIN         3
+#define REQ_04_EN_DISABLE_MCU_INT      4
+#define REQ_05_SET_GET_USBREG          5
+       /* Write: RegNum, Value, 0 */
+       /* Read : RegNum, Value, 1, RegStatus */
+#define REQ_06_SET_GET_USBREG_BIT      6
+#define REQ_07_SET_GET_AVREG           7
+       /* Write: RegNum, Value, 0 */
+       /* Read : RegNum, Value, 1, RegStatus */
+#define REQ_08_SET_GET_AVREG_BIT       8
+#define REQ_09_SET_GET_TUNER_FQ                9
+#define REQ_10_SET_TUNER_SYSTEM                10
+#define REQ_11_SET_EEPROM_ADDR         11
+#define REQ_12_SET_GET_EEPROMBYTE      12
+#define REQ_13_GET_EEPROM_SEQREAD      13
+#define REQ_14_SET_GET_I2C_WR2_RDN     14
+#define REQ_15_SET_GET_I2CBYTE         15
+       /* Write: Subaddr, Slave Addr, value, 0 */
+       /* Read : Subaddr, Slave Addr, value, 1 */
+#define REQ_16_SET_GET_I2C_WR1_RDN     16
+       /* Subaddr, Slave Addr, 0, length */
+#define REQ_17_SET_GET_I2CFP           17
+       /* Write: Slave Addr, register, value */
+       /* Read : Slave Addr, register, 2, data */
+#define REQ_20_DATA_TRANSFER           20
+#define REQ_30_I2C_WRITE               30
+#define REQ_31_I2C_READ                        31
+#define REQ_35_AFTEK_TUNER_READ                35
+#define REQ_40_GET_VERSION             40
+#define REQ_50_SET_START               50
+#define REQ_51_SET_STOP                        51
+#define REQ_52_TRANSMIT_DATA           52
+#define REQ_53_SPI_INITIAL             53
+#define REQ_54_SPI_SETSTART            54
+#define REQ_55_SPI_INOUTDATA           55
+#define REQ_56_SPI_SETSTOP             56
+
+/*
+ * Define TV Master TM5600/TM6000/TM6010 GPIO lines
+ */
+
+#define TM6000_GPIO_CLK                0x101
+#define TM6000_GPIO_DATA       0x100
+
+#define TM6000_GPIO_1          0x102
+#define TM6000_GPIO_2          0x103
+#define TM6000_GPIO_3          0x104
+#define TM6000_GPIO_4          0x300
+#define TM6000_GPIO_5          0x301
+#define TM6000_GPIO_6          0x304
+#define TM6000_GPIO_7          0x305
+
+/* tm6010 defines GPIO with different values */
+#define TM6010_GPIO_0      0x0102
+#define TM6010_GPIO_1      0x0103
+#define TM6010_GPIO_2      0x0104
+#define TM6010_GPIO_3      0x0105
+#define TM6010_GPIO_4      0x0106
+#define TM6010_GPIO_5      0x0107
+#define TM6010_GPIO_6      0x0300
+#define TM6010_GPIO_7      0x0301
+#define TM6010_GPIO_9      0x0305
+/*
+ * Define TV Master TM5600/TM6000/TM6010 URB message codes and length
+ */
+
+enum {
+       TM6000_URB_MSG_VIDEO = 1,
+       TM6000_URB_MSG_AUDIO,
+       TM6000_URB_MSG_VBI,
+       TM6000_URB_MSG_PTS,
+       TM6000_URB_MSG_ERR,
+};
+
+/* Define specific TM6000 Video decoder registers */
+#define TM6000_REQ07_RD8_TEST_SEL                      0x07, 0xd8
+#define TM6000_REQ07_RD9_A_SIM_SEL                     0x07, 0xd9
+#define TM6000_REQ07_RDA_CLK_SEL                       0x07, 0xda
+#define TM6000_REQ07_RDB_OUT_SEL                       0x07, 0xdb
+#define TM6000_REQ07_RDC_NSEL_I2S                      0x07, 0xdc
+#define TM6000_REQ07_RDD_GPIO2_MDRV                    0x07, 0xdd
+#define TM6000_REQ07_RDE_GPIO1_MDRV                    0x07, 0xde
+#define TM6000_REQ07_RDF_PWDOWN_ACLK                   0x07, 0xdf
+#define TM6000_REQ07_RE0_VADC_REF_CTL                  0x07, 0xe0
+#define TM6000_REQ07_RE1_VADC_DACLIMP                  0x07, 0xe1
+#define TM6000_REQ07_RE2_VADC_STATUS_CTL               0x07, 0xe2
+#define TM6000_REQ07_RE3_VADC_INP_LPF_SEL1             0x07, 0xe3
+#define TM6000_REQ07_RE4_VADC_TARGET1                  0x07, 0xe4
+#define TM6000_REQ07_RE5_VADC_INP_LPF_SEL2             0x07, 0xe5
+#define TM6000_REQ07_RE6_VADC_TARGET2                  0x07, 0xe6
+#define TM6000_REQ07_RE7_VADC_AGAIN_CTL                        0x07, 0xe7
+#define TM6000_REQ07_RE8_VADC_PWDOWN_CTL               0x07, 0xe8
+#define TM6000_REQ07_RE9_VADC_INPUT_CTL1               0x07, 0xe9
+#define TM6000_REQ07_REA_VADC_INPUT_CTL2               0x07, 0xea
+#define TM6000_REQ07_REB_VADC_AADC_MODE                        0x07, 0xeb
+#define TM6000_REQ07_REC_VADC_AADC_LVOL                        0x07, 0xec
+#define TM6000_REQ07_RED_VADC_AADC_RVOL                        0x07, 0xed
+#define TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL         0x07, 0xee
+#define TM6000_REQ07_REF_VADC_GAIN_MAP_CTL             0x07, 0xef
+#define TM6000_REQ07_RFD_BIST_ERR_VST_LOW              0x07, 0xfd
+#define TM6000_REQ07_RFE_BIST_ERR_VST_HIGH             0x07, 0xfe
+
+/* Define TM6000/TM6010 Video decoder registers */
+#define TM6010_REQ07_R00_VIDEO_CONTROL0                        0x07, 0x00
+#define TM6010_REQ07_R01_VIDEO_CONTROL1                        0x07, 0x01
+#define TM6010_REQ07_R02_VIDEO_CONTROL2                        0x07, 0x02
+#define TM6010_REQ07_R03_YC_SEP_CONTROL                        0x07, 0x03
+#define TM6010_REQ07_R04_LUMA_HAGC_CONTROL             0x07, 0x04
+#define TM6010_REQ07_R05_NOISE_THRESHOLD               0x07, 0x05
+#define TM6010_REQ07_R06_AGC_GATE_THRESHOLD            0x07, 0x06
+#define TM6010_REQ07_R07_OUTPUT_CONTROL                        0x07, 0x07
+#define TM6010_REQ07_R08_LUMA_CONTRAST_ADJ             0x07, 0x08
+#define TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ           0x07, 0x09
+#define TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ         0x07, 0x0a
+#define TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ          0x07, 0x0b
+#define TM6010_REQ07_R0C_CHROMA_AGC_CONTROL            0x07, 0x0c
+#define TM6010_REQ07_R0D_CHROMA_KILL_LEVEL             0x07, 0x0d
+#define TM6010_REQ07_R0F_CHROMA_AUTO_POSITION          0x07, 0x0f
+#define TM6010_REQ07_R10_AGC_PEAK_NOMINAL              0x07, 0x10
+#define TM6010_REQ07_R11_AGC_PEAK_CONTROL              0x07, 0x11
+#define TM6010_REQ07_R12_AGC_GATE_STARTH               0x07, 0x12
+#define TM6010_REQ07_R13_AGC_GATE_STARTL               0x07, 0x13
+#define TM6010_REQ07_R14_AGC_GATE_WIDTH                        0x07, 0x14
+#define TM6010_REQ07_R15_AGC_BP_DELAY                  0x07, 0x15
+#define TM6010_REQ07_R16_LOCK_COUNT                    0x07, 0x16
+#define TM6010_REQ07_R17_HLOOP_MAXSTATE                        0x07, 0x17
+#define TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3         0x07, 0x18
+#define TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2         0x07, 0x19
+#define TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1         0x07, 0x1a
+#define TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0         0x07, 0x1b
+#define TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3          0x07, 0x1c
+#define TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2          0x07, 0x1d
+#define TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1          0x07, 0x1e
+#define TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0          0x07, 0x1f
+#define TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME                0x07, 0x20
+#define TM6010_REQ07_R21_HSYNC_PHASE_OFFSET            0x07, 0x21
+#define TM6010_REQ07_R22_HSYNC_PLL_START_TIME          0x07, 0x22
+#define TM6010_REQ07_R23_HSYNC_PLL_END_TIME            0x07, 0x23
+#define TM6010_REQ07_R24_HSYNC_TIP_START_TIME          0x07, 0x24
+#define TM6010_REQ07_R25_HSYNC_TIP_END_TIME            0x07, 0x25
+#define TM6010_REQ07_R26_HSYNC_RISING_EDGE_START       0x07, 0x26
+#define TM6010_REQ07_R27_HSYNC_RISING_EDGE_END         0x07, 0x27
+#define TM6010_REQ07_R28_BACKPORCH_START               0x07, 0x28
+#define TM6010_REQ07_R29_BACKPORCH_END                 0x07, 0x29
+#define TM6010_REQ07_R2A_HSYNC_FILTER_START            0x07, 0x2a
+#define TM6010_REQ07_R2B_HSYNC_FILTER_END              0x07, 0x2b
+#define TM6010_REQ07_R2C_CHROMA_BURST_START            0x07, 0x2c
+#define TM6010_REQ07_R2D_CHROMA_BURST_END              0x07, 0x2d
+#define TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART           0x07, 0x2e
+#define TM6010_REQ07_R2F_ACTIVE_VIDEO_HWIDTH           0x07, 0x2f
+#define TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART           0x07, 0x30
+#define TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT           0x07, 0x31
+#define TM6010_REQ07_R32_VSYNC_HLOCK_MIN               0x07, 0x32
+#define TM6010_REQ07_R33_VSYNC_HLOCK_MAX               0x07, 0x33
+#define TM6010_REQ07_R34_VSYNC_AGC_MIN                 0x07, 0x34
+#define TM6010_REQ07_R35_VSYNC_AGC_MAX                 0x07, 0x35
+#define TM6010_REQ07_R36_VSYNC_VBI_MIN                 0x07, 0x36
+#define TM6010_REQ07_R37_VSYNC_VBI_MAX                 0x07, 0x37
+#define TM6010_REQ07_R38_VSYNC_THRESHOLD               0x07, 0x38
+#define TM6010_REQ07_R39_VSYNC_TIME_CONSTANT           0x07, 0x39
+#define TM6010_REQ07_R3A_STATUS1                       0x07, 0x3a
+#define TM6010_REQ07_R3B_STATUS2                       0x07, 0x3b
+#define TM6010_REQ07_R3C_STATUS3                       0x07, 0x3c
+#define TM6010_REQ07_R3F_RESET                         0x07, 0x3f
+#define TM6010_REQ07_R40_TELETEXT_VBI_CODE0            0x07, 0x40
+#define TM6010_REQ07_R41_TELETEXT_VBI_CODE1            0x07, 0x41
+#define TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL           0x07, 0x42
+#define TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7           0x07, 0x43
+#define TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8           0x07, 0x44
+#define TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9           0x07, 0x45
+#define TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10          0x07, 0x46
+#define TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11          0x07, 0x47
+#define TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12          0x07, 0x48
+#define TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13          0x07, 0x49
+#define TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14          0x07, 0x4a
+#define TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15          0x07, 0x4b
+#define TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16          0x07, 0x4c
+#define TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17          0x07, 0x4d
+#define TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18          0x07, 0x4e
+#define TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19          0x07, 0x4f
+#define TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20          0x07, 0x50
+#define TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21          0x07, 0x51
+#define TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22          0x07, 0x52
+#define TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23          0x07, 0x53
+#define TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES          0x07, 0x54
+#define TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN          0x07, 0x55
+#define TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN                0x07, 0x56
+#define TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN                0x07, 0x57
+#define TM6010_REQ07_R58_VBI_CAPTION_DTO1              0x07, 0x58
+#define TM6010_REQ07_R59_VBI_CAPTION_DTO0              0x07, 0x59
+#define TM6010_REQ07_R5A_VBI_TELETEXT_DTO1             0x07, 0x5a
+#define TM6010_REQ07_R5B_VBI_TELETEXT_DTO0             0x07, 0x5b
+#define TM6010_REQ07_R5C_VBI_WSS625_DTO1               0x07, 0x5c
+#define TM6010_REQ07_R5D_VBI_WSS625_DTO0               0x07, 0x5d
+#define TM6010_REQ07_R5E_VBI_CAPTION_FRAME_START       0x07, 0x5e
+#define TM6010_REQ07_R5F_VBI_WSS625_FRAME_START                0x07, 0x5f
+#define TM6010_REQ07_R60_TELETEXT_FRAME_START          0x07, 0x60
+#define TM6010_REQ07_R61_VBI_CCDATA1                   0x07, 0x61
+#define TM6010_REQ07_R62_VBI_CCDATA2                   0x07, 0x62
+#define TM6010_REQ07_R63_VBI_WSS625_DATA1              0x07, 0x63
+#define TM6010_REQ07_R64_VBI_WSS625_DATA2              0x07, 0x64
+#define TM6010_REQ07_R65_VBI_DATA_STATUS               0x07, 0x65
+#define TM6010_REQ07_R66_VBI_CAPTION_START             0x07, 0x66
+#define TM6010_REQ07_R67_VBI_WSS625_START              0x07, 0x67
+#define TM6010_REQ07_R68_VBI_TELETEXT_START            0x07, 0x68
+#define TM6010_REQ07_R70_HSYNC_DTO_INC_STATUS3         0x07, 0x70
+#define TM6010_REQ07_R71_HSYNC_DTO_INC_STATUS2         0x07, 0x71
+#define TM6010_REQ07_R72_HSYNC_DTO_INC_STATUS1         0x07, 0x72
+#define TM6010_REQ07_R73_HSYNC_DTO_INC_STATUS0         0x07, 0x73
+#define TM6010_REQ07_R74_CHROMA_DTO_INC_STATUS3                0x07, 0x74
+#define TM6010_REQ07_R75_CHROMA_DTO_INC_STATUS2                0x07, 0x75
+#define TM6010_REQ07_R76_CHROMA_DTO_INC_STATUS1                0x07, 0x76
+#define TM6010_REQ07_R77_CHROMA_DTO_INC_STATUS0                0x07, 0x77
+#define TM6010_REQ07_R78_AGC_AGAIN_STATUS              0x07, 0x78
+#define TM6010_REQ07_R79_AGC_DGAIN_STATUS              0x07, 0x79
+#define TM6010_REQ07_R7A_CHROMA_MAG_STATUS             0x07, 0x7a
+#define TM6010_REQ07_R7B_CHROMA_GAIN_STATUS1           0x07, 0x7b
+#define TM6010_REQ07_R7C_CHROMA_GAIN_STATUS0           0x07, 0x7c
+#define TM6010_REQ07_R7D_CORDIC_FREQ_STATUS            0x07, 0x7d
+#define TM6010_REQ07_R7F_STATUS_NOISE                  0x07, 0x7f
+#define TM6010_REQ07_R80_COMB_FILTER_TRESHOLD          0x07, 0x80
+#define TM6010_REQ07_R82_COMB_FILTER_CONFIG            0x07, 0x82
+#define TM6010_REQ07_R83_CHROMA_LOCK_CONFIG            0x07, 0x83
+#define TM6010_REQ07_R84_NOISE_NTSC_C                  0x07, 0x84
+#define TM6010_REQ07_R85_NOISE_PAL_C                   0x07, 0x85
+#define TM6010_REQ07_R86_NOISE_PHASE_C                 0x07, 0x86
+#define TM6010_REQ07_R87_NOISE_PHASE_Y                 0x07, 0x87
+#define TM6010_REQ07_R8A_CHROMA_LOOPFILTER_STATE       0x07, 0x8a
+#define TM6010_REQ07_R8B_CHROMA_HRESAMPLER             0x07, 0x8b
+#define TM6010_REQ07_R8D_CPUMP_DELAY_ADJ               0x07, 0x8d
+#define TM6010_REQ07_R8E_CPUMP_ADJ                     0x07, 0x8e
+#define TM6010_REQ07_R8F_CPUMP_DELAY                   0x07, 0x8f
+
+/* Define TM6000/TM6010 Miscellaneous registers */
+#define TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE           0x07, 0xc0
+#define TM6010_REQ07_RC1_TRESHOLD                      0x07, 0xc1
+#define TM6010_REQ07_RC2_HSYNC_WIDTH                   0x07, 0xc2
+#define TM6010_REQ07_RC3_HSTART1                       0x07, 0xc3
+#define TM6010_REQ07_RC4_HSTART0                       0x07, 0xc4
+#define TM6010_REQ07_RC5_HEND1                         0x07, 0xc5
+#define TM6010_REQ07_RC6_HEND0                         0x07, 0xc6
+#define TM6010_REQ07_RC7_VSTART1                       0x07, 0xc7
+#define TM6010_REQ07_RC8_VSTART0                       0x07, 0xc8
+#define TM6010_REQ07_RC9_VEND1                         0x07, 0xc9
+#define TM6010_REQ07_RCA_VEND0                         0x07, 0xca
+#define TM6010_REQ07_RCB_DELAY                         0x07, 0xcb
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RCC_ACTIVE_IF                     0x07, 0xcc
+#define TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE (1 << 5)
+#define TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE (1 << 6)
+#define TM6010_REQ07_RD0_USB_PERIPHERY_CONTROL         0x07, 0xd0
+#define TM6010_REQ07_RD1_ADDR_FOR_REQ1                 0x07, 0xd1
+#define TM6010_REQ07_RD2_ADDR_FOR_REQ2                 0x07, 0xd2
+#define TM6010_REQ07_RD3_ADDR_FOR_REQ3                 0x07, 0xd3
+#define TM6010_REQ07_RD4_ADDR_FOR_REQ4                 0x07, 0xd4
+#define TM6010_REQ07_RD5_POWERSAVE                     0x07, 0xd5
+#define TM6010_REQ07_RD6_ENDP_REQ1_REQ2                        0x07, 0xd6
+#define TM6010_REQ07_RD7_ENDP_REQ3_REQ4                        0x07, 0xd7
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD8_IR                            0x07, 0xd8
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RD9_IR_BSIZE                      0x07, 0xd9
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RDA_IR_WAKEUP_SEL                 0x07, 0xda
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RDB_IR_WAKEUP_ADD                 0x07, 0xdb
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RDC_IR_LEADER1                    0x07, 0xdc
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RDD_IR_LEADER0                    0x07, 0xdd
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RDE_IR_PULSE_CNT1                 0x07, 0xde
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RDF_IR_PULSE_CNT0                 0x07, 0xdf
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE0_DVIDEO_SOURCE                 0x07, 0xe0
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE0_DVIDEO_SOURCE_IF              0x07, 0xe1
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE2_OUT_SEL2                      0x07, 0xe2
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE3_OUT_SEL1                      0x07, 0xe3
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE4_OUT_SEL0                      0x07, 0xe4
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE5_REMOTE_WAKEUP                 0x07, 0xe5
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE7_PUB_GPIO                      0x07, 0xe7
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE8_TYPESEL_MOS_I2S               0x07, 0xe8
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RE9_TYPESEL_MOS_TS                        0x07, 0xe9
+/* ONLY for TM6010 */
+#define TM6010_REQ07_REA_TYPESEL_MOS_CCIR              0x07, 0xea
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF0_BIST_CRC_RESULT0              0x07, 0xf0
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF1_BIST_CRC_RESULT1              0x07, 0xf1
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF2_BIST_CRC_RESULT2              0x07, 0xf2
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF3_BIST_CRC_RESULT3              0x07, 0xf3
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF4_BIST_ERR_VST2                 0x07, 0xf4
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF5_BIST_ERR_VST1                 0x07, 0xf5
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF6_BIST_ERR_VST0                 0x07, 0xf6
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RF7_BIST                          0x07, 0xf7
+/* ONLY for TM6010 */
+#define TM6010_REQ07_RFE_POWER_DOWN                    0x07, 0xfe
+#define TM6010_REQ07_RFF_SOFT_RESET                    0x07, 0xff
+
+/* Define TM6000/TM6010 USB registers */
+#define TM6010_REQ05_R00_MAIN_CTRL             0x05, 0x00
+#define TM6010_REQ05_R01_DEVADDR               0x05, 0x01
+#define TM6010_REQ05_R02_TEST                  0x05, 0x02
+#define TM6010_REQ05_R04_SOFN0                 0x05, 0x04
+#define TM6010_REQ05_R05_SOFN1                 0x05, 0x05
+#define TM6010_REQ05_R06_SOFTM0                        0x05, 0x06
+#define TM6010_REQ05_R07_SOFTM1                        0x05, 0x07
+#define TM6010_REQ05_R08_PHY_TEST              0x05, 0x08
+#define TM6010_REQ05_R09_VCTL                  0x05, 0x09
+#define TM6010_REQ05_R0A_VSTA                  0x05, 0x0a
+#define TM6010_REQ05_R0B_CX_CFG                        0x05, 0x0b
+#define TM6010_REQ05_R0C_ENDP0_REG0            0x05, 0x0c
+#define TM6010_REQ05_R10_GMASK                 0x05, 0x10
+#define TM6010_REQ05_R11_IMASK0                        0x05, 0x11
+#define TM6010_REQ05_R12_IMASK1                        0x05, 0x12
+#define TM6010_REQ05_R13_IMASK2                        0x05, 0x13
+#define TM6010_REQ05_R14_IMASK3                        0x05, 0x14
+#define TM6010_REQ05_R15_IMASK4                        0x05, 0x15
+#define TM6010_REQ05_R16_IMASK5                        0x05, 0x16
+#define TM6010_REQ05_R17_IMASK6                        0x05, 0x17
+#define TM6010_REQ05_R18_IMASK7                        0x05, 0x18
+#define TM6010_REQ05_R19_ZEROP0                        0x05, 0x19
+#define TM6010_REQ05_R1A_ZEROP1                        0x05, 0x1a
+#define TM6010_REQ05_R1C_FIFO_EMP0             0x05, 0x1c
+#define TM6010_REQ05_R1D_FIFO_EMP1             0x05, 0x1d
+#define TM6010_REQ05_R20_IRQ_GROUP             0x05, 0x20
+#define TM6010_REQ05_R21_IRQ_SOURCE0           0x05, 0x21
+#define TM6010_REQ05_R22_IRQ_SOURCE1           0x05, 0x22
+#define TM6010_REQ05_R23_IRQ_SOURCE2           0x05, 0x23
+#define TM6010_REQ05_R24_IRQ_SOURCE3           0x05, 0x24
+#define TM6010_REQ05_R25_IRQ_SOURCE4           0x05, 0x25
+#define TM6010_REQ05_R26_IRQ_SOURCE5           0x05, 0x26
+#define TM6010_REQ05_R27_IRQ_SOURCE6           0x05, 0x27
+#define TM6010_REQ05_R28_IRQ_SOURCE7           0x05, 0x28
+#define TM6010_REQ05_R29_SEQ_ERR0              0x05, 0x29
+#define TM6010_REQ05_R2A_SEQ_ERR1              0x05, 0x2a
+#define TM6010_REQ05_R2B_SEQ_ABORT0            0x05, 0x2b
+#define TM6010_REQ05_R2C_SEQ_ABORT1            0x05, 0x2c
+#define TM6010_REQ05_R2D_TX_ZERO0              0x05, 0x2d
+#define TM6010_REQ05_R2E_TX_ZERO1              0x05, 0x2e
+#define TM6010_REQ05_R2F_IDLE_CNT              0x05, 0x2f
+#define TM6010_REQ05_R30_FNO_P1                        0x05, 0x30
+#define TM6010_REQ05_R31_FNO_P2                        0x05, 0x31
+#define TM6010_REQ05_R32_FNO_P3                        0x05, 0x32
+#define TM6010_REQ05_R33_FNO_P4                        0x05, 0x33
+#define TM6010_REQ05_R34_FNO_P5                        0x05, 0x34
+#define TM6010_REQ05_R35_FNO_P6                        0x05, 0x35
+#define TM6010_REQ05_R36_FNO_P7                        0x05, 0x36
+#define TM6010_REQ05_R37_FNO_P8                        0x05, 0x37
+#define TM6010_REQ05_R38_FNO_P9                        0x05, 0x38
+#define TM6010_REQ05_R30_FNO_P10               0x05, 0x39
+#define TM6010_REQ05_R30_FNO_P11               0x05, 0x3a
+#define TM6010_REQ05_R30_FNO_P12               0x05, 0x3b
+#define TM6010_REQ05_R30_FNO_P13               0x05, 0x3c
+#define TM6010_REQ05_R30_FNO_P14               0x05, 0x3d
+#define TM6010_REQ05_R30_FNO_P15               0x05, 0x3e
+#define TM6010_REQ05_R40_IN_MAXPS_LOW1         0x05, 0x40
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH1                0x05, 0x41
+#define TM6010_REQ05_R42_IN_MAXPS_LOW2         0x05, 0x42
+#define TM6010_REQ05_R43_IN_MAXPS_HIGH2                0x05, 0x43
+#define TM6010_REQ05_R44_IN_MAXPS_LOW3         0x05, 0x44
+#define TM6010_REQ05_R45_IN_MAXPS_HIGH3                0x05, 0x45
+#define TM6010_REQ05_R46_IN_MAXPS_LOW4         0x05, 0x46
+#define TM6010_REQ05_R47_IN_MAXPS_HIGH4                0x05, 0x47
+#define TM6010_REQ05_R48_IN_MAXPS_LOW5         0x05, 0x48
+#define TM6010_REQ05_R49_IN_MAXPS_HIGH5                0x05, 0x49
+#define TM6010_REQ05_R4A_IN_MAXPS_LOW6         0x05, 0x4a
+#define TM6010_REQ05_R4B_IN_MAXPS_HIGH6                0x05, 0x4b
+#define TM6010_REQ05_R4C_IN_MAXPS_LOW7         0x05, 0x4c
+#define TM6010_REQ05_R4D_IN_MAXPS_HIGH7                0x05, 0x4d
+#define TM6010_REQ05_R4E_IN_MAXPS_LOW8         0x05, 0x4e
+#define TM6010_REQ05_R4F_IN_MAXPS_HIGH8                0x05, 0x4f
+#define TM6010_REQ05_R50_IN_MAXPS_LOW9         0x05, 0x50
+#define TM6010_REQ05_R51_IN_MAXPS_HIGH9                0x05, 0x51
+#define TM6010_REQ05_R40_IN_MAXPS_LOW10                0x05, 0x52
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH10       0x05, 0x53
+#define TM6010_REQ05_R40_IN_MAXPS_LOW11                0x05, 0x54
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH11       0x05, 0x55
+#define TM6010_REQ05_R40_IN_MAXPS_LOW12                0x05, 0x56
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH12       0x05, 0x57
+#define TM6010_REQ05_R40_IN_MAXPS_LOW13                0x05, 0x58
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH13       0x05, 0x59
+#define TM6010_REQ05_R40_IN_MAXPS_LOW14                0x05, 0x5a
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH14       0x05, 0x5b
+#define TM6010_REQ05_R40_IN_MAXPS_LOW15                0x05, 0x5c
+#define TM6010_REQ05_R41_IN_MAXPS_HIGH15       0x05, 0x5d
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW1                0x05, 0x60
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH1       0x05, 0x61
+#define TM6010_REQ05_R62_OUT_MAXPS_LOW2                0x05, 0x62
+#define TM6010_REQ05_R63_OUT_MAXPS_HIGH2       0x05, 0x63
+#define TM6010_REQ05_R64_OUT_MAXPS_LOW3                0x05, 0x64
+#define TM6010_REQ05_R65_OUT_MAXPS_HIGH3       0x05, 0x65
+#define TM6010_REQ05_R66_OUT_MAXPS_LOW4                0x05, 0x66
+#define TM6010_REQ05_R67_OUT_MAXPS_HIGH4       0x05, 0x67
+#define TM6010_REQ05_R68_OUT_MAXPS_LOW5                0x05, 0x68
+#define TM6010_REQ05_R69_OUT_MAXPS_HIGH5       0x05, 0x69
+#define TM6010_REQ05_R6A_OUT_MAXPS_LOW6                0x05, 0x6a
+#define TM6010_REQ05_R6B_OUT_MAXPS_HIGH6       0x05, 0x6b
+#define TM6010_REQ05_R6C_OUT_MAXPS_LOW7                0x05, 0x6c
+#define TM6010_REQ05_R6D_OUT_MAXPS_HIGH7       0x05, 0x6d
+#define TM6010_REQ05_R6E_OUT_MAXPS_LOW8                0x05, 0x6e
+#define TM6010_REQ05_R6F_OUT_MAXPS_HIGH8       0x05, 0x6f
+#define TM6010_REQ05_R70_OUT_MAXPS_LOW9                0x05, 0x70
+#define TM6010_REQ05_R71_OUT_MAXPS_HIGH9       0x05, 0x71
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW10       0x05, 0x72
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH10      0x05, 0x73
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW11       0x05, 0x74
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH11      0x05, 0x75
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW12       0x05, 0x76
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH12      0x05, 0x77
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW13       0x05, 0x78
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH13      0x05, 0x79
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW14       0x05, 0x7a
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH14      0x05, 0x7b
+#define TM6010_REQ05_R60_OUT_MAXPS_LOW15       0x05, 0x7c
+#define TM6010_REQ05_R61_OUT_MAXPS_HIGH15      0x05, 0x7d
+#define TM6010_REQ05_R80_FIFO0                 0x05, 0x80
+#define TM6010_REQ05_R81_FIFO1                 0x05, 0x81
+#define TM6010_REQ05_R82_FIFO2                 0x05, 0x82
+#define TM6010_REQ05_R83_FIFO3                 0x05, 0x83
+#define TM6010_REQ05_R84_FIFO4                 0x05, 0x84
+#define TM6010_REQ05_R85_FIFO5                 0x05, 0x85
+#define TM6010_REQ05_R86_FIFO6                 0x05, 0x86
+#define TM6010_REQ05_R87_FIFO7                 0x05, 0x87
+#define TM6010_REQ05_R88_FIFO8                 0x05, 0x88
+#define TM6010_REQ05_R89_FIFO9                 0x05, 0x89
+#define TM6010_REQ05_R81_FIFO10                        0x05, 0x8a
+#define TM6010_REQ05_R81_FIFO11                        0x05, 0x8b
+#define TM6010_REQ05_R81_FIFO12                        0x05, 0x8c
+#define TM6010_REQ05_R81_FIFO13                        0x05, 0x8d
+#define TM6010_REQ05_R81_FIFO14                        0x05, 0x8e
+#define TM6010_REQ05_R81_FIFO15                        0x05, 0x8f
+#define TM6010_REQ05_R90_CFG_FIFO0             0x05, 0x90
+#define TM6010_REQ05_R91_CFG_FIFO1             0x05, 0x91
+#define TM6010_REQ05_R92_CFG_FIFO2             0x05, 0x92
+#define TM6010_REQ05_R93_CFG_FIFO3             0x05, 0x93
+#define TM6010_REQ05_R94_CFG_FIFO4             0x05, 0x94
+#define TM6010_REQ05_R95_CFG_FIFO5             0x05, 0x95
+#define TM6010_REQ05_R96_CFG_FIFO6             0x05, 0x96
+#define TM6010_REQ05_R97_CFG_FIFO7             0x05, 0x97
+#define TM6010_REQ05_R98_CFG_FIFO8             0x05, 0x98
+#define TM6010_REQ05_R99_CFG_FIFO9             0x05, 0x99
+#define TM6010_REQ05_R91_CFG_FIFO10            0x05, 0x9a
+#define TM6010_REQ05_R91_CFG_FIFO11            0x05, 0x9b
+#define TM6010_REQ05_R91_CFG_FIFO12            0x05, 0x9c
+#define TM6010_REQ05_R91_CFG_FIFO13            0x05, 0x9d
+#define TM6010_REQ05_R91_CFG_FIFO14            0x05, 0x9e
+#define TM6010_REQ05_R91_CFG_FIFO15            0x05, 0x9f
+#define TM6010_REQ05_RA0_CTL_FIFO0             0x05, 0xa0
+#define TM6010_REQ05_RA1_CTL_FIFO1             0x05, 0xa1
+#define TM6010_REQ05_RA2_CTL_FIFO2             0x05, 0xa2
+#define TM6010_REQ05_RA3_CTL_FIFO3             0x05, 0xa3
+#define TM6010_REQ05_RA4_CTL_FIFO4             0x05, 0xa4
+#define TM6010_REQ05_RA5_CTL_FIFO5             0x05, 0xa5
+#define TM6010_REQ05_RA6_CTL_FIFO6             0x05, 0xa6
+#define TM6010_REQ05_RA7_CTL_FIFO7             0x05, 0xa7
+#define TM6010_REQ05_RA8_CTL_FIFO8             0x05, 0xa8
+#define TM6010_REQ05_RA9_CTL_FIFO9             0x05, 0xa9
+#define TM6010_REQ05_RA1_CTL_FIFO10            0x05, 0xaa
+#define TM6010_REQ05_RA1_CTL_FIFO11            0x05, 0xab
+#define TM6010_REQ05_RA1_CTL_FIFO12            0x05, 0xac
+#define TM6010_REQ05_RA1_CTL_FIFO13            0x05, 0xad
+#define TM6010_REQ05_RA1_CTL_FIFO14            0x05, 0xae
+#define TM6010_REQ05_RA1_CTL_FIFO15            0x05, 0xaf
+#define TM6010_REQ05_RB0_BC_LOW_FIFO0          0x05, 0xb0
+#define TM6010_REQ05_RB1_BC_LOW_FIFO1          0x05, 0xb1
+#define TM6010_REQ05_RB2_BC_LOW_FIFO2          0x05, 0xb2
+#define TM6010_REQ05_RB3_BC_LOW_FIFO3          0x05, 0xb3
+#define TM6010_REQ05_RB4_BC_LOW_FIFO4          0x05, 0xb4
+#define TM6010_REQ05_RB5_BC_LOW_FIFO5          0x05, 0xb5
+#define TM6010_REQ05_RB6_BC_LOW_FIFO6          0x05, 0xb6
+#define TM6010_REQ05_RB7_BC_LOW_FIFO7          0x05, 0xb7
+#define TM6010_REQ05_RB8_BC_LOW_FIFO8          0x05, 0xb8
+#define TM6010_REQ05_RB9_BC_LOW_FIFO9          0x05, 0xb9
+#define TM6010_REQ05_RB1_BC_LOW_FIFO10         0x05, 0xba
+#define TM6010_REQ05_RB1_BC_LOW_FIFO11         0x05, 0xbb
+#define TM6010_REQ05_RB1_BC_LOW_FIFO12         0x05, 0xbc
+#define TM6010_REQ05_RB1_BC_LOW_FIFO13         0x05, 0xbd
+#define TM6010_REQ05_RB1_BC_LOW_FIFO14         0x05, 0xbe
+#define TM6010_REQ05_RB1_BC_LOW_FIFO15         0x05, 0xbf
+#define TM6010_REQ05_RC0_DATA_FIFO0            0x05, 0xc0
+#define TM6010_REQ05_RC4_DATA_FIFO1            0x05, 0xc4
+#define TM6010_REQ05_RC8_DATA_FIFO2            0x05, 0xc8
+#define TM6010_REQ05_RCC_DATA_FIFO3            0x05, 0xcc
+#define TM6010_REQ05_RD0_DATA_FIFO4            0x05, 0xd0
+#define TM6010_REQ05_RD4_DATA_FIFO5            0x05, 0xd4
+#define TM6010_REQ05_RD8_DATA_FIFO6            0x05, 0xd8
+#define TM6010_REQ05_RDC_DATA_FIFO7            0x05, 0xdc
+#define TM6010_REQ05_RE0_DATA_FIFO8            0x05, 0xe0
+#define TM6010_REQ05_RE4_DATA_FIFO9            0x05, 0xe4
+#define TM6010_REQ05_RC4_DATA_FIFO10           0x05, 0xe8
+#define TM6010_REQ05_RC4_DATA_FIFO11           0x05, 0xec
+#define TM6010_REQ05_RC4_DATA_FIFO12           0x05, 0xf0
+#define TM6010_REQ05_RC4_DATA_FIFO13           0x05, 0xf4
+#define TM6010_REQ05_RC4_DATA_FIFO14           0x05, 0xf8
+#define TM6010_REQ05_RC4_DATA_FIFO15           0x05, 0xfc
+
+/* Define TM6010 Audio decoder registers */
+/* This core available only in TM6010 */
+#define TM6010_REQ08_R00_A_VERSION             0x08, 0x00
+#define TM6010_REQ08_R01_A_INIT                        0x08, 0x01
+#define TM6010_REQ08_R02_A_FIX_GAIN_CTRL       0x08, 0x02
+#define TM6010_REQ08_R03_A_AUTO_GAIN_CTRL      0x08, 0x03
+#define TM6010_REQ08_R04_A_SIF_AMP_CTRL                0x08, 0x04
+#define TM6010_REQ08_R05_A_STANDARD_MOD                0x08, 0x05
+#define TM6010_REQ08_R06_A_SOUND_MOD           0x08, 0x06
+#define TM6010_REQ08_R07_A_LEFT_VOL            0x08, 0x07
+#define TM6010_REQ08_R08_A_RIGHT_VOL           0x08, 0x08
+#define TM6010_REQ08_R09_A_MAIN_VOL            0x08, 0x09
+#define TM6010_REQ08_R0A_A_I2S_MOD             0x08, 0x0a
+#define TM6010_REQ08_R0B_A_ASD_THRES1          0x08, 0x0b
+#define TM6010_REQ08_R0C_A_ASD_THRES2          0x08, 0x0c
+#define TM6010_REQ08_R0D_A_AMD_THRES           0x08, 0x0d
+#define TM6010_REQ08_R0E_A_MONO_THRES1         0x08, 0x0e
+#define TM6010_REQ08_R0F_A_MONO_THRES2         0x08, 0x0f
+#define TM6010_REQ08_R10_A_MUTE_THRES1         0x08, 0x10
+#define TM6010_REQ08_R11_A_MUTE_THRES2         0x08, 0x11
+#define TM6010_REQ08_R12_A_AGC_U               0x08, 0x12
+#define TM6010_REQ08_R13_A_AGC_ERR_T           0x08, 0x13
+#define TM6010_REQ08_R14_A_AGC_GAIN_INIT       0x08, 0x14
+#define TM6010_REQ08_R15_A_AGC_STEP_THR                0x08, 0x15
+#define TM6010_REQ08_R16_A_AGC_GAIN_MAX                0x08, 0x16
+#define TM6010_REQ08_R17_A_AGC_GAIN_MIN                0x08, 0x17
+#define TM6010_REQ08_R18_A_TR_CTRL             0x08, 0x18
+#define TM6010_REQ08_R19_A_FH_2FH_GAIN         0x08, 0x19
+#define TM6010_REQ08_R1A_A_NICAM_SER_MAX       0x08, 0x1a
+#define TM6010_REQ08_R1B_A_NICAM_SER_MIN       0x08, 0x1b
+#define TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT     0x08, 0x1e
+#define TM6010_REQ08_R1F_A_TEST_INTF_SEL       0x08, 0x1f
+#define TM6010_REQ08_R20_A_TEST_PIN_SEL                0x08, 0x20
+#define TM6010_REQ08_R21_A_AGC_ERR             0x08, 0x21
+#define TM6010_REQ08_R22_A_AGC_GAIN            0x08, 0x22
+#define TM6010_REQ08_R23_A_NICAM_INFO          0x08, 0x23
+#define TM6010_REQ08_R24_A_SER                 0x08, 0x24
+#define TM6010_REQ08_R25_A_C1_AMP              0x08, 0x25
+#define TM6010_REQ08_R26_A_C2_AMP              0x08, 0x26
+#define TM6010_REQ08_R27_A_NOISE_AMP           0x08, 0x27
+#define TM6010_REQ08_R28_A_AUDIO_MODE_RES      0x08, 0x28
+
+/* Define TM6010 Video ADC registers */
+#define TM6010_REQ08_RE0_ADC_REF               0x08, 0xe0
+#define TM6010_REQ08_RE1_DAC_CLMP              0x08, 0xe1
+#define TM6010_REQ08_RE2_POWER_DOWN_CTRL1      0x08, 0xe2
+#define TM6010_REQ08_RE3_ADC_IN1_SEL           0x08, 0xe3
+#define TM6010_REQ08_RE4_ADC_IN2_SEL           0x08, 0xe4
+#define TM6010_REQ08_RE5_GAIN_PARAM            0x08, 0xe5
+#define TM6010_REQ08_RE6_POWER_DOWN_CTRL2      0x08, 0xe6
+#define TM6010_REQ08_RE7_REG_GAIN_Y            0x08, 0xe7
+#define TM6010_REQ08_RE8_REG_GAIN_C            0x08, 0xe8
+#define TM6010_REQ08_RE9_BIAS_CTRL             0x08, 0xe9
+#define TM6010_REQ08_REA_BUFF_DRV_CTRL         0x08, 0xea
+#define TM6010_REQ08_REB_SIF_GAIN_CTRL         0x08, 0xeb
+#define TM6010_REQ08_REC_REVERSE_YC_CTRL       0x08, 0xec
+#define TM6010_REQ08_RED_GAIN_SEL              0x08, 0xed
+
+/* Define TM6010 Audio ADC registers */
+#define TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG   0x08, 0xf0
+#define TM6010_REQ08_RF1_AADC_POWER_DOWN       0x08, 0xf1
+#define TM6010_REQ08_RF2_LEFT_CHANNEL_VOL      0x08, 0xf2
+#define TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL     0x08, 0xf3
diff --git a/drivers/media/usb/tm6000/tm6000-stds.c b/drivers/media/usb/tm6000/tm6000-stds.c
new file mode 100644 (file)
index 0000000..5e28d6a
--- /dev/null
@@ -0,0 +1,638 @@
+/*
+ *  tm6000-stds.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@redhat.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 version 2
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include "tm6000.h"
+#include "tm6000-regs.h"
+
+static unsigned int tm6010_a_mode;
+module_param(tm6010_a_mode, int, 0644);
+MODULE_PARM_DESC(tm6010_a_mode, "set tm6010 sif audio mode");
+
+struct tm6000_reg_settings {
+       unsigned char req;
+       unsigned char reg;
+       unsigned char value;
+};
+
+
+struct tm6000_std_settings {
+       v4l2_std_id id;
+       struct tm6000_reg_settings *common;
+};
+
+static struct tm6000_reg_settings composite_pal_m[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x04 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x20 },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_pal_nc[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x36 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_pal[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x32 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_secam[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x38 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings composite_ntsc[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_std_settings composite_stds[] = {
+       { .id = V4L2_STD_PAL_M, .common = composite_pal_m, },
+       { .id = V4L2_STD_PAL_Nc, .common = composite_pal_nc, },
+       { .id = V4L2_STD_PAL, .common = composite_pal, },
+       { .id = V4L2_STD_SECAM, .common = composite_secam, },
+       { .id = V4L2_STD_NTSC, .common = composite_ntsc, },
+};
+
+static struct tm6000_reg_settings svideo_pal_m[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x05 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_pal_nc[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x37 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_pal[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x33 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_secam[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x39 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_reg_settings svideo_ntsc[] = {
+       { TM6010_REQ07_R3F_RESET, 0x01 },
+       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x01 },
+       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f },
+       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
+       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 },
+       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 },
+       { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0x8b },
+       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
+       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
+       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
+       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
+       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
+       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
+       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
+       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
+       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
+       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
+       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
+       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
+       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
+       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
+       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
+       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd },
+       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
+       { TM6010_REQ07_R3F_RESET, 0x00 },
+       { 0, 0, 0 }
+};
+
+static struct tm6000_std_settings svideo_stds[] = {
+       { .id = V4L2_STD_PAL_M, .common = svideo_pal_m, },
+       { .id = V4L2_STD_PAL_Nc, .common = svideo_pal_nc, },
+       { .id = V4L2_STD_PAL, .common = svideo_pal, },
+       { .id = V4L2_STD_SECAM, .common = svideo_secam, },
+       { .id = V4L2_STD_NTSC, .common = svideo_ntsc, },
+};
+
+static int tm6000_set_audio_std(struct tm6000_core *dev)
+{
+       uint8_t areg_02 = 0x04; /* GC1 Fixed gain 0dB */
+       uint8_t areg_05 = 0x01; /* Auto 4.5 = M Japan, Auto 6.5 = DK */
+       uint8_t areg_06 = 0x02; /* Auto de-emphasis, mannual channel mode */
+
+       if (dev->radio) {
+               tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00);
+               tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, 0x04);
+               tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00);
+               tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0x80);
+               tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, 0x0c);
+               /* set mono or stereo */
+               if (dev->amode == V4L2_TUNER_MODE_MONO)
+                       tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x00);
+               else if (dev->amode == V4L2_TUNER_MODE_STEREO)
+                       tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x02);
+               tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x18);
+               tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x0a);
+               tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x40);
+               tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe);
+               tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13);
+               tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80);
+               tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0xff);
+               return 0;
+       }
+
+       /*
+        * STD/MN shouldn't be affected by tm6010_a_mode, as there's just one
+        * audio standard for each V4L2_STD type.
+        */
+       if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_KR) {
+               areg_05 |= 0x04;
+       } else if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_JP) {
+               areg_05 |= 0x43;
+       } else if (dev->norm & V4L2_STD_MN) {
+               areg_05 |= 0x22;
+       } else switch (tm6010_a_mode) {
+       /* auto */
+       case 0:
+               if ((dev->norm & V4L2_STD_SECAM) == V4L2_STD_SECAM_L)
+                       areg_05 |= 0x00;
+               else    /* Other PAL/SECAM standards */
+                       areg_05 |= 0x10;
+               break;
+       /* A2 */
+       case 1:
+               if (dev->norm & V4L2_STD_DK)
+                       areg_05 = 0x09;
+               else
+                       areg_05 = 0x05;
+               break;
+       /* NICAM */
+       case 2:
+               if (dev->norm & V4L2_STD_DK) {
+                       areg_05 = 0x06;
+               } else if (dev->norm & V4L2_STD_PAL_I) {
+                       areg_05 = 0x08;
+               } else if (dev->norm & V4L2_STD_SECAM_L) {
+                       areg_05 = 0x0a;
+                       areg_02 = 0x02;
+               } else {
+                       areg_05 = 0x07;
+               }
+               break;
+       /* other */
+       case 3:
+               if (dev->norm & V4L2_STD_DK) {
+                       areg_05 = 0x0b;
+               } else {
+                       areg_05 = 0x02;
+               }
+               break;
+       }
+
+       tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00);
+       tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, areg_02);
+       tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00);
+       tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0xa0);
+       tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, areg_05);
+       tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, areg_06);
+       tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, 0x00);
+       tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, 0x00);
+       tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x08);
+       tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, 0x91);
+       tm6000_set_reg(dev, TM6010_REQ08_R0B_A_ASD_THRES1, 0x20);
+       tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x12);
+       tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x20);
+       tm6000_set_reg(dev, TM6010_REQ08_R0E_A_MONO_THRES1, 0xf0);
+       tm6000_set_reg(dev, TM6010_REQ08_R0F_A_MONO_THRES2, 0x80);
+       tm6000_set_reg(dev, TM6010_REQ08_R10_A_MUTE_THRES1, 0xc0);
+       tm6000_set_reg(dev, TM6010_REQ08_R11_A_MUTE_THRES2, 0x80);
+       tm6000_set_reg(dev, TM6010_REQ08_R12_A_AGC_U, 0x12);
+       tm6000_set_reg(dev, TM6010_REQ08_R13_A_AGC_ERR_T, 0xfe);
+       tm6000_set_reg(dev, TM6010_REQ08_R14_A_AGC_GAIN_INIT, 0x20);
+       tm6000_set_reg(dev, TM6010_REQ08_R15_A_AGC_STEP_THR, 0x14);
+       tm6000_set_reg(dev, TM6010_REQ08_R16_A_AGC_GAIN_MAX, 0xfe);
+       tm6000_set_reg(dev, TM6010_REQ08_R17_A_AGC_GAIN_MIN, 0x01);
+       tm6000_set_reg(dev, TM6010_REQ08_R18_A_TR_CTRL, 0xa0);
+       tm6000_set_reg(dev, TM6010_REQ08_R19_A_FH_2FH_GAIN, 0x32);
+       tm6000_set_reg(dev, TM6010_REQ08_R1A_A_NICAM_SER_MAX, 0x64);
+       tm6000_set_reg(dev, TM6010_REQ08_R1B_A_NICAM_SER_MIN, 0x20);
+       tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1c, 0x00);
+       tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1d, 0x00);
+       tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13);
+       tm6000_set_reg(dev, TM6010_REQ08_R1F_A_TEST_INTF_SEL, 0x00);
+       tm6000_set_reg(dev, TM6010_REQ08_R20_A_TEST_PIN_SEL, 0x00);
+       tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80);
+
+       return 0;
+}
+
+void tm6000_get_std_res(struct tm6000_core *dev)
+{
+       /* Currently, those are the only supported resoltions */
+       if (dev->norm & V4L2_STD_525_60)
+               dev->height = 480;
+       else
+               dev->height = 576;
+
+       dev->width = 720;
+}
+
+static int tm6000_load_std(struct tm6000_core *dev, struct tm6000_reg_settings *set)
+{
+       int i, rc;
+
+       /* Load board's initialization table */
+       for (i = 0; set[i].req; i++) {
+               rc = tm6000_set_reg(dev, set[i].req, set[i].reg, set[i].value);
+               if (rc < 0) {
+                       printk(KERN_ERR "Error %i while setting "
+                              "req %d, reg %d to value %d\n",
+                              rc, set[i].req, set[i].reg, set[i].value);
+                       return rc;
+               }
+       }
+
+       return 0;
+}
+
+int tm6000_set_standard(struct tm6000_core *dev)
+{
+       struct tm6000_input *input;
+       int i, rc = 0;
+       u8 reg_07_fe = 0x8a;
+       u8 reg_08_f1 = 0xfc;
+       u8 reg_08_e2 = 0xf0;
+       u8 reg_08_e6 = 0x0f;
+
+       tm6000_get_std_res(dev);
+
+       if (!dev->radio)
+               input = &dev->vinput[dev->input];
+       else
+               input = &dev->rinput;
+
+       if (dev->dev_type == TM6010) {
+               switch (input->vmux) {
+               case TM6000_VMUX_VIDEO_A:
+                       tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4);
+                       tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1);
+                       tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0);
+                       tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
+                       tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8);
+                       reg_07_fe |= 0x01;
+                       break;
+               case TM6000_VMUX_VIDEO_B:
+                       tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8);
+                       tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1);
+                       tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0);
+                       tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
+                       tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8);
+                       reg_07_fe |= 0x01;
+                       break;
+               case TM6000_VMUX_VIDEO_AB:
+                       tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc);
+                       tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8);
+                       reg_08_e6 = 0x00;
+                       tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2);
+                       tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0);
+                       tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
+                       tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe0);
+                       break;
+               default:
+                       break;
+               }
+               switch (input->amux) {
+               case TM6000_AMUX_ADC1:
+                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+                               0x00, 0x0f);
+                       /* Mux overflow workaround */
+                       tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+                               0x10, 0xf0);
+                       break;
+               case TM6000_AMUX_ADC2:
+                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+                               0x08, 0x0f);
+                       /* Mux overflow workaround */
+                       tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+                               0x10, 0xf0);
+                       break;
+               case TM6000_AMUX_SIF1:
+                       reg_08_e2 |= 0x02;
+                       reg_08_e6 = 0x08;
+                       reg_07_fe |= 0x40;
+                       reg_08_f1 |= 0x02;
+                       tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3);
+                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+                               0x02, 0x0f);
+                       /* Mux overflow workaround */
+                       tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+                               0x30, 0xf0);
+                       break;
+               case TM6000_AMUX_SIF2:
+                       reg_08_e2 |= 0x02;
+                       reg_08_e6 = 0x08;
+                       reg_07_fe |= 0x40;
+                       reg_08_f1 |= 0x02;
+                       tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf7);
+                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
+                               0x02, 0x0f);
+                       /* Mux overflow workaround */
+                       tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
+                               0x30, 0xf0);
+                       break;
+               default:
+                       break;
+               }
+               tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, reg_08_e2);
+               tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, reg_08_e6);
+               tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, reg_08_f1);
+               tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, reg_07_fe);
+       } else {
+               switch (input->vmux) {
+               case TM6000_VMUX_VIDEO_A:
+                       tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10);
+                       tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00);
+                       tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f);
+                       tm6000_set_reg(dev,
+                           REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0);
+                       break;
+               case TM6000_VMUX_VIDEO_B:
+                       tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x00);
+                       tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00);
+                       tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f);
+                       tm6000_set_reg(dev,
+                           REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0);
+                       break;
+               case TM6000_VMUX_VIDEO_AB:
+                       tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10);
+                       tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x10);
+                       tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00);
+                       tm6000_set_reg(dev,
+                           REQ_03_SET_GET_MCU_PIN, input->v_gpio, 1);
+                       break;
+               default:
+                       break;
+               }
+               switch (input->amux) {
+               case TM6000_AMUX_ADC1:
+                       tm6000_set_reg_mask(dev,
+                               TM6000_REQ07_REB_VADC_AADC_MODE, 0x00, 0x0f);
+                       break;
+               case TM6000_AMUX_ADC2:
+                       tm6000_set_reg_mask(dev,
+                               TM6000_REQ07_REB_VADC_AADC_MODE, 0x04, 0x0f);
+                       break;
+               default:
+                       break;
+               }
+       }
+       if (input->type == TM6000_INPUT_SVIDEO) {
+               for (i = 0; i < ARRAY_SIZE(svideo_stds); i++) {
+                       if (dev->norm & svideo_stds[i].id) {
+                               rc = tm6000_load_std(dev, svideo_stds[i].common);
+                               goto ret;
+                       }
+               }
+               return -EINVAL;
+       } else {
+               for (i = 0; i < ARRAY_SIZE(composite_stds); i++) {
+                       if (dev->norm & composite_stds[i].id) {
+                               rc = tm6000_load_std(dev, composite_stds[i].common);
+                               goto ret;
+                       }
+               }
+               return -EINVAL;
+       }
+
+ret:
+       if (rc < 0)
+               return rc;
+
+       if ((dev->dev_type == TM6010) &&
+           ((input->amux == TM6000_AMUX_SIF1) ||
+           (input->amux == TM6000_AMUX_SIF2)))
+               tm6000_set_audio_std(dev);
+
+       msleep(40);
+
+       return 0;
+}
diff --git a/drivers/media/usb/tm6000/tm6000-usb-isoc.h b/drivers/media/usb/tm6000/tm6000-usb-isoc.h
new file mode 100644 (file)
index 0000000..99d15a5
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  tm6000-buf.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation version 2
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/videodev2.h>
+
+#define TM6000_URB_MSG_LEN 180
+
+struct usb_isoc_ctl {
+               /* max packet size of isoc transaction */
+       int                             max_pkt_size;
+
+               /* number of allocated urbs */
+       int                             num_bufs;
+
+               /* urb for isoc transfers */
+       struct urb                      **urb;
+
+               /* transfer buffers for isoc transfer */
+       char                            **transfer_buffer;
+
+               /* Last buffer command and region */
+       u8                              cmd;
+       int                             pos, size, pktsize;
+
+               /* Last field: ODD or EVEN? */
+       int                             vfield, field;
+
+               /* Stores incomplete commands */
+       u32                             tmp_buf;
+       int                             tmp_buf_len;
+
+               /* Stores already requested buffers */
+       struct tm6000_buffer            *buf;
+};
diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c
new file mode 100644 (file)
index 0000000..45ed59c
--- /dev/null
@@ -0,0 +1,1852 @@
+/*
+ *   tm6000-video.c - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *     - Fixed module load/unload
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation version 2
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#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/ioport.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/random.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ioctl.h>
+#include <media/tuner.h>
+#include <linux/interrupt.h>
+#include <linux/kthread.h>
+#include <linux/highmem.h>
+#include <linux/freezer.h>
+
+#include "tm6000-regs.h"
+#include "tm6000.h"
+
+#define BUFFER_TIMEOUT     msecs_to_jiffies(2000)  /* 2 seconds */
+
+/* Limits minimum and default number of buffers */
+#define TM6000_MIN_BUF 4
+#define TM6000_DEF_BUF 8
+
+#define TM6000_MAX_ISO_PACKETS 46      /* Max number of ISO packets */
+
+/* Declare static vars that will be used as parameters */
+static unsigned int vid_limit = 16;    /* Video memory limit, in Mb */
+static int video_nr = -1;              /* /dev/videoN, -1 for autodetect */
+static int radio_nr = -1;              /* /dev/radioN, -1 for autodetect */
+
+/* Debug level */
+int tm6000_debug;
+EXPORT_SYMBOL_GPL(tm6000_debug);
+
+static const struct v4l2_queryctrl no_ctrl = {
+       .name  = "42",
+       .flags = V4L2_CTRL_FLAG_DISABLED,
+};
+
+/* supported controls */
+static struct v4l2_queryctrl tm6000_qctrl[] = {
+       {
+               .id            = V4L2_CID_BRIGHTNESS,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Brightness",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 1,
+               .default_value = 54,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_CONTRAST,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Contrast",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 0x1,
+               .default_value = 119,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_SATURATION,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Saturation",
+               .minimum       = 0,
+               .maximum       = 255,
+               .step          = 0x1,
+               .default_value = 112,
+               .flags         = 0,
+       }, {
+               .id            = V4L2_CID_HUE,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+               .name          = "Hue",
+               .minimum       = -128,
+               .maximum       = 127,
+               .step          = 0x1,
+               .default_value = 0,
+               .flags         = 0,
+       },
+               /* --- audio --- */
+       {
+               .id            = V4L2_CID_AUDIO_MUTE,
+               .name          = "Mute",
+               .minimum       = 0,
+               .maximum       = 1,
+               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+       }, {
+               .id            = V4L2_CID_AUDIO_VOLUME,
+               .name          = "Volume",
+               .minimum       = -15,
+               .maximum       = 15,
+               .step          = 1,
+               .default_value = 0,
+               .type          = V4L2_CTRL_TYPE_INTEGER,
+       }
+};
+
+static const unsigned int CTRLS = ARRAY_SIZE(tm6000_qctrl);
+static int qctl_regs[ARRAY_SIZE(tm6000_qctrl)];
+
+static struct tm6000_fmt format[] = {
+       {
+               .name     = "4:2:2, packed, YVY2",
+               .fourcc   = V4L2_PIX_FMT_YUYV,
+               .depth    = 16,
+       }, {
+               .name     = "4:2:2, packed, UYVY",
+               .fourcc   = V4L2_PIX_FMT_UYVY,
+               .depth    = 16,
+       }, {
+               .name     = "A/V + VBI mux packet",
+               .fourcc   = V4L2_PIX_FMT_TM6000,
+               .depth    = 16,
+       }
+};
+
+static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id)
+{
+       unsigned int i;
+
+       for (i = 0; i < CTRLS; i++)
+               if (tm6000_qctrl[i].id == id)
+                       return tm6000_qctrl+i;
+       return NULL;
+}
+
+/* ------------------------------------------------------------------
+ *     DMA and thread functions
+ * ------------------------------------------------------------------
+ */
+
+#define norm_maxw(a) 720
+#define norm_maxh(a) 576
+
+#define norm_minw(a) norm_maxw(a)
+#define norm_minh(a) norm_maxh(a)
+
+/*
+ * video-buf generic routine to get the next available buffer
+ */
+static inline void get_next_buf(struct tm6000_dmaqueue *dma_q,
+                              struct tm6000_buffer   **buf)
+{
+       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+
+       if (list_empty(&dma_q->active)) {
+               dprintk(dev, V4L2_DEBUG_QUEUE, "No active queue to serve\n");
+               *buf = NULL;
+               return;
+       }
+
+       *buf = list_entry(dma_q->active.next,
+                       struct tm6000_buffer, vb.queue);
+}
+
+/*
+ * Announces that a buffer were filled and request the next
+ */
+static inline void buffer_filled(struct tm6000_core *dev,
+                                struct tm6000_dmaqueue *dma_q,
+                                struct tm6000_buffer *buf)
+{
+       /* Advice that buffer was filled */
+       dprintk(dev, V4L2_DEBUG_ISOC, "[%p/%d] wakeup\n", buf, buf->vb.i);
+       buf->vb.state = VIDEOBUF_DONE;
+       buf->vb.field_count++;
+       do_gettimeofday(&buf->vb.ts);
+
+       list_del(&buf->vb.queue);
+       wake_up(&buf->vb.done);
+}
+
+/*
+ * Identify the tm5600/6000 buffer header type and properly handles
+ */
+static int copy_streams(u8 *data, unsigned long len,
+                       struct urb *urb)
+{
+       struct tm6000_dmaqueue  *dma_q = urb->context;
+       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+       u8 *ptr = data, *endp = data+len;
+       unsigned long header = 0;
+       int rc = 0;
+       unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0;
+       struct tm6000_buffer *vbuf = NULL;
+       char *voutp = NULL;
+       unsigned int linewidth;
+
+       if (!dev->radio) {
+               /* get video buffer */
+               get_next_buf(dma_q, &vbuf);
+
+               if (!vbuf)
+                       return rc;
+               voutp = videobuf_to_vmalloc(&vbuf->vb);
+
+               if (!voutp)
+                       return 0;
+       }
+
+       for (ptr = data; ptr < endp;) {
+               if (!dev->isoc_ctl.cmd) {
+                       /* Header */
+                       if (dev->isoc_ctl.tmp_buf_len > 0) {
+                               /* from last urb or packet */
+                               header = dev->isoc_ctl.tmp_buf;
+                               if (4 - dev->isoc_ctl.tmp_buf_len > 0) {
+                                       memcpy((u8 *)&header +
+                                               dev->isoc_ctl.tmp_buf_len,
+                                               ptr,
+                                               4 - dev->isoc_ctl.tmp_buf_len);
+                                       ptr += 4 - dev->isoc_ctl.tmp_buf_len;
+                               }
+                               dev->isoc_ctl.tmp_buf_len = 0;
+                       } else {
+                               if (ptr + 3 >= endp) {
+                                       /* have incomplete header */
+                                       dev->isoc_ctl.tmp_buf_len = endp - ptr;
+                                       memcpy(&dev->isoc_ctl.tmp_buf, ptr,
+                                               dev->isoc_ctl.tmp_buf_len);
+                                       return rc;
+                               }
+                               /* Seek for sync */
+                               for (; ptr < endp - 3; ptr++) {
+                                       if (*(ptr + 3) == 0x47)
+                                               break;
+                               }
+                               /* Get message header */
+                               header = *(unsigned long *)ptr;
+                               ptr += 4;
+                       }
+
+                       /* split the header fields */
+                       size = ((header & 0x7e) << 1);
+                       if (size > 0)
+                               size -= 4;
+                       block = (header >> 7) & 0xf;
+                       field = (header >> 11) & 0x1;
+                       line  = (header >> 12) & 0x1ff;
+                       cmd   = (header >> 21) & 0x7;
+                       /* Validates haeder fields */
+                       if (size > TM6000_URB_MSG_LEN)
+                               size = TM6000_URB_MSG_LEN;
+                       pktsize = TM6000_URB_MSG_LEN;
+                       /*
+                        * calculate position in buffer and change the buffer
+                        */
+                       switch (cmd) {
+                       case TM6000_URB_MSG_VIDEO:
+                               if (!dev->radio) {
+                                       if ((dev->isoc_ctl.vfield != field) &&
+                                               (field == 1)) {
+                                               /*
+                                                * Announces that a new buffer
+                                                * were filled
+                                                */
+                                               buffer_filled(dev, dma_q, vbuf);
+                                               dprintk(dev, V4L2_DEBUG_ISOC,
+                                                       "new buffer filled\n");
+                                               get_next_buf(dma_q, &vbuf);
+                                               if (!vbuf)
+                                                       return rc;
+                                               voutp = videobuf_to_vmalloc(&vbuf->vb);
+                                               if (!voutp)
+                                                       return rc;
+                                               memset(voutp, 0, vbuf->vb.size);
+                                       }
+                                       linewidth = vbuf->vb.width << 1;
+                                       pos = ((line << 1) - field - 1) *
+                                       linewidth + block * TM6000_URB_MSG_LEN;
+                                       /* Don't allow to write out of the buffer */
+                                       if (pos + size > vbuf->vb.size)
+                                               cmd = TM6000_URB_MSG_ERR;
+                                       dev->isoc_ctl.vfield = field;
+                               }
+                               break;
+                       case TM6000_URB_MSG_VBI:
+                               break;
+                       case TM6000_URB_MSG_AUDIO:
+                       case TM6000_URB_MSG_PTS:
+                               size = pktsize; /* Size is always 180 bytes */
+                               break;
+                       }
+               } else {
+                       /* Continue the last copy */
+                       cmd = dev->isoc_ctl.cmd;
+                       size = dev->isoc_ctl.size;
+                       pos = dev->isoc_ctl.pos;
+                       pktsize = dev->isoc_ctl.pktsize;
+                       field = dev->isoc_ctl.field;
+               }
+               cpysize = (endp - ptr > size) ? size : endp - ptr;
+               if (cpysize) {
+                       /* copy data in different buffers */
+                       switch (cmd) {
+                       case TM6000_URB_MSG_VIDEO:
+                               /* Fills video buffer */
+                               if (vbuf)
+                                       memcpy(&voutp[pos], ptr, cpysize);
+                               break;
+                       case TM6000_URB_MSG_AUDIO: {
+                               int i;
+                               for (i = 0; i < cpysize; i += 2)
+                                       swab16s((u16 *)(ptr + i));
+
+                               tm6000_call_fillbuf(dev, TM6000_AUDIO, ptr, cpysize);
+                               break;
+                       }
+                       case TM6000_URB_MSG_VBI:
+                               /* Need some code to copy vbi buffer */
+                               break;
+                       case TM6000_URB_MSG_PTS: {
+                               /* Need some code to copy pts */
+                               u32 pts;
+                               pts = *(u32 *)ptr;
+                               dprintk(dev, V4L2_DEBUG_ISOC, "field %d, PTS %x",
+                                       field, pts);
+                               break;
+                       }
+                       }
+               }
+               if (ptr + pktsize > endp) {
+                       /*
+                        * End of URB packet, but cmd processing is not
+                        * complete. Preserve the state for a next packet
+                        */
+                       dev->isoc_ctl.pos = pos + cpysize;
+                       dev->isoc_ctl.size = size - cpysize;
+                       dev->isoc_ctl.cmd = cmd;
+                       dev->isoc_ctl.field = field;
+                       dev->isoc_ctl.pktsize = pktsize - (endp - ptr);
+                       ptr += endp - ptr;
+               } else {
+                       dev->isoc_ctl.cmd = 0;
+                       ptr += pktsize;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Identify the tm5600/6000 buffer header type and properly handles
+ */
+static int copy_multiplexed(u8 *ptr, unsigned long len,
+                       struct urb *urb)
+{
+       struct tm6000_dmaqueue  *dma_q = urb->context;
+       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+       unsigned int pos = dev->isoc_ctl.pos, cpysize;
+       int rc = 1;
+       struct tm6000_buffer *buf;
+       char *outp = NULL;
+
+       get_next_buf(dma_q, &buf);
+       if (buf)
+               outp = videobuf_to_vmalloc(&buf->vb);
+
+       if (!outp)
+               return 0;
+
+       while (len > 0) {
+               cpysize = min(len, buf->vb.size-pos);
+               memcpy(&outp[pos], ptr, cpysize);
+               pos += cpysize;
+               ptr += cpysize;
+               len -= cpysize;
+               if (pos >= buf->vb.size) {
+                       pos = 0;
+                       /* Announces that a new buffer were filled */
+                       buffer_filled(dev, dma_q, buf);
+                       dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n");
+                       get_next_buf(dma_q, &buf);
+                       if (!buf)
+                               break;
+                       outp = videobuf_to_vmalloc(&(buf->vb));
+                       if (!outp)
+                               return rc;
+                       pos = 0;
+               }
+       }
+
+       dev->isoc_ctl.pos = pos;
+       return rc;
+}
+
+static inline void print_err_status(struct tm6000_core *dev,
+                                    int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+       if (packet < 0) {
+               dprintk(dev, V4L2_DEBUG_QUEUE, "URB status %d [%s].\n",
+                       status, errmsg);
+       } else {
+               dprintk(dev, V4L2_DEBUG_QUEUE, "URB packet %d, status %d [%s].\n",
+                       packet, status, errmsg);
+       }
+}
+
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static inline int tm6000_isoc_copy(struct urb *urb)
+{
+       struct tm6000_dmaqueue  *dma_q = urb->context;
+       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+       int i, len = 0, rc = 1, status;
+       char *p;
+
+       if (urb->status < 0) {
+               print_err_status(dev, -1, urb->status);
+               return 0;
+       }
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               status = urb->iso_frame_desc[i].status;
+
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       continue;
+               }
+
+               len = urb->iso_frame_desc[i].actual_length;
+
+               if (len > 0) {
+                       p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+                       if (!urb->iso_frame_desc[i].status) {
+                               if ((dev->fourcc) == V4L2_PIX_FMT_TM6000) {
+                                       rc = copy_multiplexed(p, len, urb);
+                                       if (rc <= 0)
+                                               return rc;
+                               } else {
+                                       copy_streams(p, len, urb);
+                               }
+                       }
+               }
+       }
+       return rc;
+}
+
+/* ------------------------------------------------------------------
+ *     URB control
+ * ------------------------------------------------------------------
+ */
+
+/*
+ * IRQ callback, called by URB callback
+ */
+static void tm6000_irq_callback(struct urb *urb)
+{
+       struct tm6000_dmaqueue  *dma_q = urb->context;
+       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
+       int i;
+
+       switch (urb->status) {
+       case 0:
+       case -ETIMEDOUT:
+               break;
+
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+
+       default:
+               tm6000_err("urb completion error %d.\n", urb->status);
+               break;
+       }
+
+       spin_lock(&dev->slock);
+       tm6000_isoc_copy(urb);
+       spin_unlock(&dev->slock);
+
+       /* Reset urb buffers */
+       for (i = 0; i < urb->number_of_packets; i++) {
+               urb->iso_frame_desc[i].status = 0;
+               urb->iso_frame_desc[i].actual_length = 0;
+       }
+
+       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (urb->status)
+               tm6000_err("urb resubmit failed (error=%i)\n",
+                       urb->status);
+}
+
+/*
+ * Stop and Deallocate URBs
+ */
+static void tm6000_uninit_isoc(struct tm6000_core *dev)
+{
+       struct urb *urb;
+       int i;
+
+       dev->isoc_ctl.buf = NULL;
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               urb = dev->isoc_ctl.urb[i];
+               if (urb) {
+                       usb_kill_urb(urb);
+                       usb_unlink_urb(urb);
+                       if (dev->isoc_ctl.transfer_buffer[i]) {
+                               usb_free_coherent(dev->udev,
+                                               urb->transfer_buffer_length,
+                                               dev->isoc_ctl.transfer_buffer[i],
+                                               urb->transfer_dma);
+                       }
+                       usb_free_urb(urb);
+                       dev->isoc_ctl.urb[i] = NULL;
+               }
+               dev->isoc_ctl.transfer_buffer[i] = NULL;
+       }
+
+       kfree(dev->isoc_ctl.urb);
+       kfree(dev->isoc_ctl.transfer_buffer);
+
+       dev->isoc_ctl.urb = NULL;
+       dev->isoc_ctl.transfer_buffer = NULL;
+       dev->isoc_ctl.num_bufs = 0;
+}
+
+/*
+ * Allocate URBs and start IRQ
+ */
+static int tm6000_prepare_isoc(struct tm6000_core *dev)
+{
+       struct tm6000_dmaqueue *dma_q = &dev->vidq;
+       int i, j, sb_size, pipe, size, max_packets, num_bufs = 8;
+       struct urb *urb;
+
+       /* De-allocates all pending stuff */
+       tm6000_uninit_isoc(dev);
+       /* Stop interrupt USB pipe */
+       tm6000_ir_int_stop(dev);
+
+       usb_set_interface(dev->udev,
+                         dev->isoc_in.bInterfaceNumber,
+                         dev->isoc_in.bAlternateSetting);
+
+       /* Start interrupt USB pipe */
+       tm6000_ir_int_start(dev);
+
+       pipe = usb_rcvisocpipe(dev->udev,
+                              dev->isoc_in.endp->desc.bEndpointAddress &
+                              USB_ENDPOINT_NUMBER_MASK);
+
+       size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
+
+       if (size > dev->isoc_in.maxsize)
+               size = dev->isoc_in.maxsize;
+
+       dev->isoc_ctl.max_pkt_size = size;
+
+       max_packets = TM6000_MAX_ISO_PACKETS;
+       sb_size = max_packets * size;
+
+       dev->isoc_ctl.num_bufs = num_bufs;
+
+       dev->isoc_ctl.urb = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
+       if (!dev->isoc_ctl.urb) {
+               tm6000_err("cannot alloc memory for usb buffers\n");
+               return -ENOMEM;
+       }
+
+       dev->isoc_ctl.transfer_buffer = kmalloc(sizeof(void *)*num_bufs,
+                                  GFP_KERNEL);
+       if (!dev->isoc_ctl.transfer_buffer) {
+               tm6000_err("cannot allocate memory for usbtransfer\n");
+               kfree(dev->isoc_ctl.urb);
+               return -ENOMEM;
+       }
+
+       dprintk(dev, V4L2_DEBUG_QUEUE, "Allocating %d x %d packets"
+                   " (%d bytes) of %d bytes each to handle %u size\n",
+                   max_packets, num_bufs, sb_size,
+                   dev->isoc_in.maxsize, size);
+
+       /* allocate urbs and transfer buffers */
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               urb = usb_alloc_urb(max_packets, GFP_KERNEL);
+               if (!urb) {
+                       tm6000_err("cannot alloc isoc_ctl.urb %i\n", i);
+                       tm6000_uninit_isoc(dev);
+                       usb_free_urb(urb);
+                       return -ENOMEM;
+               }
+               dev->isoc_ctl.urb[i] = urb;
+
+               dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev,
+                       sb_size, GFP_KERNEL, &urb->transfer_dma);
+               if (!dev->isoc_ctl.transfer_buffer[i]) {
+                       tm6000_err("unable to allocate %i bytes for transfer"
+                                       " buffer %i%s\n",
+                                       sb_size, i,
+                                       in_interrupt() ? " while in int" : "");
+                       tm6000_uninit_isoc(dev);
+                       return -ENOMEM;
+               }
+               memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
+
+               usb_fill_bulk_urb(urb, dev->udev, pipe,
+                                 dev->isoc_ctl.transfer_buffer[i], sb_size,
+                                 tm6000_irq_callback, dma_q);
+               urb->interval = dev->isoc_in.endp->desc.bInterval;
+               urb->number_of_packets = max_packets;
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+
+               for (j = 0; j < max_packets; j++) {
+                       urb->iso_frame_desc[j].offset = size * j;
+                       urb->iso_frame_desc[j].length = size;
+               }
+       }
+
+       return 0;
+}
+
+static int tm6000_start_thread(struct tm6000_core *dev)
+{
+       struct tm6000_dmaqueue *dma_q = &dev->vidq;
+       int i;
+
+       dma_q->frame = 0;
+       dma_q->ini_jiffies = jiffies;
+
+       init_waitqueue_head(&dma_q->wq);
+
+       /* submit urbs and enables IRQ */
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               int rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
+               if (rc) {
+                       tm6000_err("submit of urb %i failed (error=%i)\n", i,
+                                  rc);
+                       tm6000_uninit_isoc(dev);
+                       return rc;
+               }
+       }
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------
+ *     Videobuf operations
+ * ------------------------------------------------------------------
+ */
+
+static int
+buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
+{
+       struct tm6000_fh *fh = vq->priv_data;
+
+       *size = fh->fmt->depth * fh->width * fh->height >> 3;
+       if (0 == *count)
+               *count = TM6000_DEF_BUF;
+
+       if (*count < TM6000_MIN_BUF)
+               *count = TM6000_MIN_BUF;
+
+       while (*size * *count > vid_limit * 1024 * 1024)
+               (*count)--;
+
+       return 0;
+}
+
+static void free_buffer(struct videobuf_queue *vq, struct tm6000_buffer *buf)
+{
+       struct tm6000_fh *fh = vq->priv_data;
+       struct tm6000_core   *dev = fh->dev;
+       unsigned long flags;
+
+       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;
+}
+
+static int
+buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
+                                               enum v4l2_field field)
+{
+       struct tm6000_fh     *fh  = vq->priv_data;
+       struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb);
+       struct tm6000_core   *dev = fh->dev;
+       int rc = 0;
+
+       BUG_ON(NULL == fh->fmt);
+
+
+       /* FIXME: It assumes depth=2 */
+       /* The only currently supported format is 16 bits/pixel */
+       buf->vb.size = fh->fmt->depth*fh->width*fh->height >> 3;
+       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
+               return -EINVAL;
+
+       if (buf->fmt       != fh->fmt    ||
+           buf->vb.width  != fh->width  ||
+           buf->vb.height != fh->height ||
+           buf->vb.field  != field) {
+               buf->fmt       = fh->fmt;
+               buf->vb.width  = fh->width;
+               buf->vb.height = fh->height;
+               buf->vb.field  = field;
+               buf->vb.state = VIDEOBUF_NEEDS_INIT;
+       }
+
+       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+               rc = videobuf_iolock(vq, &buf->vb, NULL);
+               if (rc != 0)
+                       goto fail;
+       }
+
+       if (!dev->isoc_ctl.num_bufs) {
+               rc = tm6000_prepare_isoc(dev);
+               if (rc < 0)
+                       goto fail;
+
+               rc = tm6000_start_thread(dev);
+               if (rc < 0)
+                       goto fail;
+
+       }
+
+       buf->vb.state = VIDEOBUF_PREPARED;
+       return 0;
+
+fail:
+       free_buffer(vq, buf);
+       return rc;
+}
+
+static void
+buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+{
+       struct tm6000_buffer    *buf     = container_of(vb, struct tm6000_buffer, vb);
+       struct tm6000_fh        *fh      = vq->priv_data;
+       struct tm6000_core      *dev     = fh->dev;
+       struct tm6000_dmaqueue  *vidq    = &dev->vidq;
+
+       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 tm6000_buffer   *buf  = container_of(vb, struct tm6000_buffer, vb);
+
+       free_buffer(vq, buf);
+}
+
+static struct videobuf_queue_ops tm6000_video_qops = {
+       .buf_setup      = buffer_setup,
+       .buf_prepare    = buffer_prepare,
+       .buf_queue      = buffer_queue,
+       .buf_release    = buffer_release,
+};
+
+/* ------------------------------------------------------------------
+ *     IOCTL handling
+ * ------------------------------------------------------------------
+ */
+
+static bool is_res_read(struct tm6000_core *dev, struct tm6000_fh *fh)
+{
+       /* Is the current fh handling it? if so, that's OK */
+       if (dev->resources == fh && dev->is_res_read)
+               return true;
+
+       return false;
+}
+
+static bool is_res_streaming(struct tm6000_core *dev, struct tm6000_fh *fh)
+{
+       /* Is the current fh handling it? if so, that's OK */
+       if (dev->resources == fh)
+               return true;
+
+       return false;
+}
+
+static bool res_get(struct tm6000_core *dev, struct tm6000_fh *fh,
+                  bool is_res_read)
+{
+       /* Is the current fh handling it? if so, that's OK */
+       if (dev->resources == fh && dev->is_res_read == is_res_read)
+               return true;
+
+       /* is it free? */
+       if (dev->resources)
+               return false;
+
+       /* grab it */
+       dev->resources = fh;
+       dev->is_res_read = is_res_read;
+       dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n");
+       return true;
+}
+
+static void res_free(struct tm6000_core *dev, struct tm6000_fh *fh)
+{
+       /* Is the current fh handling it? if so, that's OK */
+       if (dev->resources != fh)
+               return;
+
+       dev->resources = NULL;
+       dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: put\n");
+}
+
+/* ------------------------------------------------------------------
+ *     IOCTL vidioc handling
+ * ------------------------------------------------------------------
+ */
+static int vidioc_querycap(struct file *file, void  *priv,
+                                       struct v4l2_capability *cap)
+{
+       struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
+
+       strlcpy(cap->driver, "tm6000", sizeof(cap->driver));
+       strlcpy(cap->card, "Trident TVMaster TM5600/6000/6010", sizeof(cap->card));
+       cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
+                               V4L2_CAP_STREAMING     |
+                               V4L2_CAP_AUDIO         |
+                               V4L2_CAP_READWRITE;
+
+       if (dev->tuner_type != TUNER_ABSENT)
+               cap->capabilities |= V4L2_CAP_TUNER;
+
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *f)
+{
+       if (unlikely(f->index >= ARRAY_SIZE(format)))
+               return -EINVAL;
+
+       strlcpy(f->description, format[f->index].name, sizeof(f->description));
+       f->pixelformat = format[f->index].fourcc;
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct tm6000_fh  *fh = priv;
+
+       f->fmt.pix.width        = fh->width;
+       f->fmt.pix.height       = fh->height;
+       f->fmt.pix.field        = fh->vb_vidq.field;
+       f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fh->fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return 0;
+}
+
+static struct tm6000_fmt *format_by_fourcc(unsigned int fourcc)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(format); i++)
+               if (format[i].fourcc == fourcc)
+                       return format+i;
+       return NULL;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                       struct v4l2_format *f)
+{
+       struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
+       struct tm6000_fmt *fmt;
+       enum v4l2_field field;
+
+       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       if (NULL == fmt) {
+               dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Fourcc format (0x%08x)"
+                               " invalid.\n", f->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       field = f->fmt.pix.field;
+
+       if (field == V4L2_FIELD_ANY)
+               field = V4L2_FIELD_SEQ_TB;
+       else if (V4L2_FIELD_INTERLACED != field) {
+               dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Field type invalid.\n");
+               return -EINVAL;
+       }
+
+       tm6000_get_std_res(dev);
+
+       f->fmt.pix.width  = dev->width;
+       f->fmt.pix.height = dev->height;
+
+       f->fmt.pix.width &= ~0x01;
+
+       f->fmt.pix.field = field;
+
+       f->fmt.pix.bytesperline =
+               (f->fmt.pix.width * fmt->depth) >> 3;
+       f->fmt.pix.sizeimage =
+               f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return 0;
+}
+
+/*FIXME: This seems to be generic enough to be at videodev2 */
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct tm6000_fh  *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+       int ret = vidioc_try_fmt_vid_cap(file, fh, f);
+       if (ret < 0)
+               return ret;
+
+       fh->fmt           = format_by_fourcc(f->fmt.pix.pixelformat);
+       fh->width         = f->fmt.pix.width;
+       fh->height        = f->fmt.pix.height;
+       fh->vb_vidq.field = f->fmt.pix.field;
+       fh->type          = f->type;
+
+       dev->fourcc       = f->fmt.pix.pixelformat;
+
+       tm6000_set_fourcc_format(dev);
+
+       return 0;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                          struct v4l2_requestbuffers *p)
+{
+       struct tm6000_fh  *fh = priv;
+
+       return videobuf_reqbufs(&fh->vb_vidq, p);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+                           struct v4l2_buffer *p)
+{
+       struct tm6000_fh  *fh = priv;
+
+       return videobuf_querybuf(&fh->vb_vidq, p);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct tm6000_fh  *fh = priv;
+
+       return videobuf_qbuf(&fh->vb_vidq, p);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+       struct tm6000_fh  *fh = priv;
+
+       return videobuf_dqbuf(&fh->vb_vidq, p,
+                               file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct tm6000_fh *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+       if (i != fh->type)
+               return -EINVAL;
+
+       if (!res_get(dev, fh, false))
+               return -EBUSY;
+       return videobuf_streamon(&fh->vb_vidq);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct tm6000_fh *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (i != fh->type)
+               return -EINVAL;
+
+       videobuf_streamoff(&fh->vb_vidq);
+       res_free(dev, fh);
+
+       return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       int rc = 0;
+       struct tm6000_fh *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       dev->norm = *norm;
+       rc = tm6000_init_analog_mode(dev);
+
+       fh->width  = dev->width;
+       fh->height = dev->height;
+
+       if (rc < 0)
+               return rc;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
+
+       return 0;
+}
+
+static const char *iname[] = {
+       [TM6000_INPUT_TV] = "Television",
+       [TM6000_INPUT_COMPOSITE1] = "Composite 1",
+       [TM6000_INPUT_COMPOSITE2] = "Composite 2",
+       [TM6000_INPUT_SVIDEO] = "S-Video",
+};
+
+static int vidioc_enum_input(struct file *file, void *priv,
+                               struct v4l2_input *i)
+{
+       struct tm6000_fh   *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+       unsigned int n;
+
+       n = i->index;
+       if (n >= 3)
+               return -EINVAL;
+
+       if (!dev->vinput[n].type)
+               return -EINVAL;
+
+       i->index = n;
+
+       if (dev->vinput[n].type == TM6000_INPUT_TV)
+               i->type = V4L2_INPUT_TYPE_TUNER;
+       else
+               i->type = V4L2_INPUT_TYPE_CAMERA;
+
+       strcpy(i->name, iname[dev->vinput[n].type]);
+
+       i->std = TM6000_STD;
+
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct tm6000_fh   *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       *i = dev->input;
+
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       struct tm6000_fh   *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+       int rc = 0;
+
+       if (i >= 3)
+               return -EINVAL;
+       if (!dev->vinput[i].type)
+               return -EINVAL;
+
+       dev->input = i;
+
+       rc = vidioc_s_std(file, priv, &dev->vfd->current_norm);
+
+       return rc;
+}
+
+/* --- controls ---------------------------------------------- */
+static int vidioc_queryctrl(struct file *file, void *priv,
+                               struct v4l2_queryctrl *qc)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)
+               if (qc->id && qc->id == tm6000_qctrl[i].id) {
+                       memcpy(qc, &(tm6000_qctrl[i]),
+                               sizeof(*qc));
+                       return 0;
+               }
+
+       return -EINVAL;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctrl)
+{
+       struct tm6000_fh  *fh = priv;
+       struct tm6000_core *dev    = fh->dev;
+       int  val;
+
+       /* FIXME: Probably, those won't work! Maybe we need shadow regs */
+       switch (ctrl->id) {
+       case V4L2_CID_CONTRAST:
+               val = tm6000_get_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0);
+               break;
+       case V4L2_CID_BRIGHTNESS:
+               val = tm6000_get_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0);
+               return 0;
+       case V4L2_CID_SATURATION:
+               val = tm6000_get_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0);
+               return 0;
+       case V4L2_CID_HUE:
+               val = tm6000_get_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, 0);
+               return 0;
+       case V4L2_CID_AUDIO_MUTE:
+               val = dev->ctl_mute;
+               return 0;
+       case V4L2_CID_AUDIO_VOLUME:
+               val = dev->ctl_volume;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+
+       if (val < 0)
+               return val;
+
+       ctrl->value = val;
+
+       return 0;
+}
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctrl)
+{
+       struct tm6000_fh   *fh  = priv;
+       struct tm6000_core *dev = fh->dev;
+       u8  val = ctrl->value;
+
+       switch (ctrl->id) {
+       case V4L2_CID_CONTRAST:
+               tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val);
+               return 0;
+       case V4L2_CID_BRIGHTNESS:
+               tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val);
+               return 0;
+       case V4L2_CID_SATURATION:
+               tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val);
+               return 0;
+       case V4L2_CID_HUE:
+               tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val);
+               return 0;
+       case V4L2_CID_AUDIO_MUTE:
+               dev->ctl_mute = val;
+               tm6000_tvaudio_set_mute(dev, val);
+               return 0;
+       case V4L2_CID_AUDIO_VOLUME:
+               dev->ctl_volume = val;
+               tm6000_set_volume(dev, val);
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct tm6000_fh   *fh  = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (unlikely(UNSET == dev->tuner_type))
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+
+       strcpy(t->name, "Television");
+       t->type       = V4L2_TUNER_ANALOG_TV;
+       t->capability = V4L2_TUNER_CAP_NORM;
+       t->rangehigh  = 0xffffffffUL;
+       t->rxsubchans = V4L2_TUNER_SUB_STEREO;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
+
+       t->audmode = dev->amode;
+
+       return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *t)
+{
+       struct tm6000_fh   *fh  = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (UNSET == dev->tuner_type)
+               return -EINVAL;
+       if (0 != t->index)
+               return -EINVAL;
+
+       dev->amode = t->audmode;
+       dprintk(dev, 3, "audio mode: %x\n", t->audmode);
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
+
+       return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct tm6000_fh   *fh  = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (unlikely(UNSET == dev->tuner_type))
+               return -EINVAL;
+
+       f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+       f->frequency = dev->freq;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, f);
+
+       return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *f)
+{
+       struct tm6000_fh   *fh  = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (unlikely(UNSET == dev->tuner_type))
+               return -EINVAL;
+       if (unlikely(f->tuner != 0))
+               return -EINVAL;
+       if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type)
+               return -EINVAL;
+       if (1 == fh->radio && V4L2_TUNER_RADIO != f->type)
+               return -EINVAL;
+
+       dev->freq = f->frequency;
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f);
+
+       return 0;
+}
+
+static int radio_querycap(struct file *file, void *priv,
+                                       struct v4l2_capability *cap)
+{
+       struct tm6000_fh *fh = file->private_data;
+       struct tm6000_core *dev = fh->dev;
+
+       strcpy(cap->driver, "tm6000");
+       strlcpy(cap->card, dev->name, sizeof(dev->name));
+       sprintf(cap->bus_info, "USB%04x:%04x",
+               le16_to_cpu(dev->udev->descriptor.idVendor),
+               le16_to_cpu(dev->udev->descriptor.idProduct));
+       cap->version = dev->dev_type;
+       cap->capabilities = V4L2_CAP_TUNER |
+                       V4L2_CAP_AUDIO     |
+                       V4L2_CAP_RADIO     |
+                       V4L2_CAP_READWRITE |
+                       V4L2_CAP_STREAMING;
+
+       return 0;
+}
+
+static int radio_g_tuner(struct file *file, void *priv,
+                                       struct v4l2_tuner *t)
+{
+       struct tm6000_fh *fh = file->private_data;
+       struct tm6000_core *dev = fh->dev;
+
+       if (0 != t->index)
+               return -EINVAL;
+
+       memset(t, 0, sizeof(*t));
+       strcpy(t->name, "Radio");
+       t->type = V4L2_TUNER_RADIO;
+       t->rxsubchans = V4L2_TUNER_SUB_STEREO;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
+
+       return 0;
+}
+
+static int radio_s_tuner(struct file *file, void *priv,
+                                       struct v4l2_tuner *t)
+{
+       struct tm6000_fh *fh = file->private_data;
+       struct tm6000_core *dev = fh->dev;
+
+       if (0 != t->index)
+               return -EINVAL;
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
+
+       return 0;
+}
+
+static int radio_enum_input(struct file *file, void *priv,
+                                       struct v4l2_input *i)
+{
+       struct tm6000_fh *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (i->index != 0)
+               return -EINVAL;
+
+       if (!dev->rinput.type)
+               return -EINVAL;
+
+       strcpy(i->name, "Radio");
+       i->type = V4L2_INPUT_TYPE_TUNER;
+
+       return 0;
+}
+
+static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
+{
+       struct tm6000_fh *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (dev->input != 5)
+               return -EINVAL;
+
+       *i = dev->input - 5;
+
+       return 0;
+}
+
+static int radio_g_audio(struct file *file, void *priv,
+                                       struct v4l2_audio *a)
+{
+       memset(a, 0, sizeof(*a));
+       strcpy(a->name, "Radio");
+       return 0;
+}
+
+static int radio_s_audio(struct file *file, void *priv,
+                                       struct v4l2_audio *a)
+{
+       return 0;
+}
+
+static int radio_s_input(struct file *filp, void *priv, unsigned int i)
+{
+       struct tm6000_fh *fh = priv;
+       struct tm6000_core *dev = fh->dev;
+
+       if (i)
+               return -EINVAL;
+
+       if (!dev->rinput.type)
+               return -EINVAL;
+
+       dev->input = i + 5;
+
+       return 0;
+}
+
+static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+       return 0;
+}
+
+static int radio_queryctrl(struct file *file, void *priv,
+                                       struct v4l2_queryctrl *c)
+{
+       const struct v4l2_queryctrl *ctrl;
+
+       if (c->id <  V4L2_CID_BASE ||
+           c->id >= V4L2_CID_LASTP1)
+               return -EINVAL;
+       if (c->id == V4L2_CID_AUDIO_MUTE) {
+               ctrl = ctrl_by_id(c->id);
+               *c = *ctrl;
+       } else
+               *c = no_ctrl;
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------
+       File operations for the device
+   ------------------------------------------------------------------*/
+
+static int __tm6000_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct tm6000_core *dev = video_drvdata(file);
+       struct tm6000_fh *fh;
+       enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       int i, rc;
+       int radio = 0;
+
+       dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n",
+               video_device_node_name(vdev));
+
+       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;
+       case VFL_TYPE_RADIO:
+               radio = 1;
+               break;
+       }
+
+       /* If more than one user, mutex should be added */
+       dev->users++;
+
+       dprintk(dev, V4L2_DEBUG_OPEN, "open dev=%s type=%s users=%d\n",
+               video_device_node_name(vdev), v4l2_type_names[type],
+               dev->users);
+
+       /* allocate + initialize per filehandle data */
+       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+       if (NULL == fh) {
+               dev->users--;
+               return -ENOMEM;
+       }
+
+       file->private_data = fh;
+       fh->dev      = dev;
+       fh->radio    = radio;
+       dev->radio   = radio;
+       fh->type     = type;
+       dev->fourcc  = format[0].fourcc;
+
+       fh->fmt      = format_by_fourcc(dev->fourcc);
+
+       tm6000_get_std_res(dev);
+
+       fh->width = dev->width;
+       fh->height = dev->height;
+
+       dprintk(dev, V4L2_DEBUG_OPEN, "Open: fh=0x%08lx, dev=0x%08lx, "
+                                               "dev->vidq=0x%08lx\n",
+                       (unsigned long)fh, (unsigned long)dev,
+                       (unsigned long)&dev->vidq);
+       dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "
+                               "queued=%d\n", list_empty(&dev->vidq.queued));
+       dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "
+                               "active=%d\n", list_empty(&dev->vidq.active));
+
+       /* initialize hardware on analog mode */
+       rc = tm6000_init_analog_mode(dev);
+       if (rc < 0)
+               return rc;
+
+       if (dev->mode != TM6000_MODE_ANALOG) {
+               /* Put all controls at a sane state */
+               for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)
+                       qctl_regs[i] = tm6000_qctrl[i].default_value;
+
+               dev->mode = TM6000_MODE_ANALOG;
+       }
+
+       if (!fh->radio) {
+               videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops,
+                               NULL, &dev->slock,
+                               fh->type,
+                               V4L2_FIELD_INTERLACED,
+                               sizeof(struct tm6000_buffer), fh, &dev->lock);
+       } else {
+               dprintk(dev, V4L2_DEBUG_OPEN, "video_open: setting radio device\n");
+               dev->input = 5;
+               tm6000_set_audio_rinput(dev);
+               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio);
+               tm6000_prepare_isoc(dev);
+               tm6000_start_thread(dev);
+       }
+
+       return 0;
+}
+
+static int tm6000_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       int res;
+
+       mutex_lock(vdev->lock);
+       res = __tm6000_open(file);
+       mutex_unlock(vdev->lock);
+       return res;
+}
+
+static ssize_t
+tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos)
+{
+       struct tm6000_fh *fh = file->private_data;
+       struct tm6000_core *dev = fh->dev;
+
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               int res;
+
+               if (!res_get(fh->dev, fh, true))
+                       return -EBUSY;
+
+               if (mutex_lock_interruptible(&dev->lock))
+                       return -ERESTARTSYS;
+               res = videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0,
+                                       file->f_flags & O_NONBLOCK);
+               mutex_unlock(&dev->lock);
+               return res;
+       }
+       return 0;
+}
+
+static unsigned int
+__tm6000_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct tm6000_fh        *fh = file->private_data;
+       struct tm6000_buffer    *buf;
+
+       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
+               return POLLERR;
+
+       if (!!is_res_streaming(fh->dev, fh))
+               return POLLERR;
+
+       if (!is_res_read(fh->dev, fh)) {
+               /* streaming capture */
+               if (list_empty(&fh->vb_vidq.stream))
+                       return POLLERR;
+               buf = list_entry(fh->vb_vidq.stream.next, struct tm6000_buffer, vb.stream);
+       } else {
+               /* read() capture */
+               return videobuf_poll_stream(file, &fh->vb_vidq, wait);
+       }
+       poll_wait(file, &buf->vb.done, wait);
+       if (buf->vb.state == VIDEOBUF_DONE ||
+           buf->vb.state == VIDEOBUF_ERROR)
+               return POLLIN | POLLRDNORM;
+       return 0;
+}
+
+static unsigned int tm6000_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct tm6000_fh *fh = file->private_data;
+       struct tm6000_core *dev = fh->dev;
+       unsigned int res;
+
+       mutex_lock(&dev->lock);
+       res = __tm6000_poll(file, wait);
+       mutex_unlock(&dev->lock);
+       return res;
+}
+
+static int tm6000_release(struct file *file)
+{
+       struct tm6000_fh         *fh = file->private_data;
+       struct tm6000_core      *dev = fh->dev;
+       struct video_device    *vdev = video_devdata(file);
+
+       dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: close called (dev=%s, users=%d)\n",
+               video_device_node_name(vdev), dev->users);
+
+       mutex_lock(&dev->lock);
+       dev->users--;
+
+       res_free(dev, fh);
+
+       if (!dev->users) {
+               tm6000_uninit_isoc(dev);
+
+               /* Stop interrupt USB pipe */
+               tm6000_ir_int_stop(dev);
+
+               usb_reset_configuration(dev->udev);
+
+               if (dev->int_in.endp)
+                       usb_set_interface(dev->udev,
+                                       dev->isoc_in.bInterfaceNumber, 2);
+               else
+                       usb_set_interface(dev->udev,
+                                       dev->isoc_in.bInterfaceNumber, 0);
+
+               /* Start interrupt USB pipe */
+               tm6000_ir_int_start(dev);
+
+               if (!fh->radio)
+                       videobuf_mmap_free(&fh->vb_vidq);
+       }
+
+       kfree(fh);
+       mutex_unlock(&dev->lock);
+
+       return 0;
+}
+
+static int tm6000_mmap(struct file *file, struct vm_area_struct * vma)
+{
+       struct tm6000_fh *fh = file->private_data;
+       struct tm6000_core *dev = fh->dev;
+       int res;
+
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
+       res = videobuf_mmap_mapper(&fh->vb_vidq, vma);
+       mutex_unlock(&dev->lock);
+       return res;
+}
+
+static struct v4l2_file_operations tm6000_fops = {
+       .owner = THIS_MODULE,
+       .open = tm6000_open,
+       .release = tm6000_release,
+       .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
+       .read = tm6000_read,
+       .poll = tm6000_poll,
+       .mmap = tm6000_mmap,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+       .vidioc_querycap          = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
+       .vidioc_s_std             = vidioc_s_std,
+       .vidioc_enum_input        = vidioc_enum_input,
+       .vidioc_g_input           = vidioc_g_input,
+       .vidioc_s_input           = vidioc_s_input,
+       .vidioc_queryctrl         = vidioc_queryctrl,
+       .vidioc_g_ctrl            = vidioc_g_ctrl,
+       .vidioc_s_ctrl            = vidioc_s_ctrl,
+       .vidioc_g_tuner           = vidioc_g_tuner,
+       .vidioc_s_tuner           = vidioc_s_tuner,
+       .vidioc_g_frequency       = vidioc_g_frequency,
+       .vidioc_s_frequency       = vidioc_s_frequency,
+       .vidioc_streamon          = vidioc_streamon,
+       .vidioc_streamoff         = vidioc_streamoff,
+       .vidioc_reqbufs           = vidioc_reqbufs,
+       .vidioc_querybuf          = vidioc_querybuf,
+       .vidioc_qbuf              = vidioc_qbuf,
+       .vidioc_dqbuf             = vidioc_dqbuf,
+};
+
+static struct video_device tm6000_template = {
+       .name           = "tm6000",
+       .fops           = &tm6000_fops,
+       .ioctl_ops      = &video_ioctl_ops,
+       .release        = video_device_release,
+       .tvnorms        = TM6000_STD,
+       .current_norm   = V4L2_STD_NTSC_M,
+};
+
+static const struct v4l2_file_operations radio_fops = {
+       .owner          = THIS_MODULE,
+       .open           = tm6000_open,
+       .release        = tm6000_release,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops radio_ioctl_ops = {
+       .vidioc_querycap        = radio_querycap,
+       .vidioc_g_tuner         = radio_g_tuner,
+       .vidioc_enum_input      = radio_enum_input,
+       .vidioc_g_audio         = radio_g_audio,
+       .vidioc_s_tuner         = radio_s_tuner,
+       .vidioc_s_audio         = radio_s_audio,
+       .vidioc_s_input         = radio_s_input,
+       .vidioc_s_std           = radio_s_std,
+       .vidioc_queryctrl       = radio_queryctrl,
+       .vidioc_g_input         = radio_g_input,
+       .vidioc_g_ctrl          = vidioc_g_ctrl,
+       .vidioc_s_ctrl          = vidioc_s_ctrl,
+       .vidioc_g_frequency     = vidioc_g_frequency,
+       .vidioc_s_frequency     = vidioc_s_frequency,
+};
+
+static struct video_device tm6000_radio_template = {
+       .name                   = "tm6000",
+       .fops                   = &radio_fops,
+       .ioctl_ops              = &radio_ioctl_ops,
+};
+
+/* -----------------------------------------------------------------
+ *     Initialization and module stuff
+ * ------------------------------------------------------------------
+ */
+
+static struct video_device *vdev_init(struct tm6000_core *dev,
+               const struct video_device
+               *template, const char *type_name)
+{
+       struct video_device *vfd;
+
+       vfd = video_device_alloc();
+       if (NULL == vfd)
+               return NULL;
+
+       *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);
+
+       video_set_drvdata(vfd, dev);
+       return vfd;
+}
+
+int tm6000_v4l2_register(struct tm6000_core *dev)
+{
+       int ret = -1;
+
+       dev->vfd = vdev_init(dev, &tm6000_template, "video");
+
+       if (!dev->vfd) {
+               printk(KERN_INFO "%s: can't register video device\n",
+                      dev->name);
+               return -ENOMEM;
+       }
+
+       /* init video dma queues */
+       INIT_LIST_HEAD(&dev->vidq.active);
+       INIT_LIST_HEAD(&dev->vidq.queued);
+
+       ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr);
+
+       if (ret < 0) {
+               printk(KERN_INFO "%s: can't register video device\n",
+                      dev->name);
+               return ret;
+       }
+
+       printk(KERN_INFO "%s: registered device %s\n",
+              dev->name, video_device_node_name(dev->vfd));
+
+       if (dev->caps.has_radio) {
+               dev->radio_dev = vdev_init(dev, &tm6000_radio_template,
+                                                          "radio");
+               if (!dev->radio_dev) {
+                       printk(KERN_INFO "%s: can't register radio device\n",
+                              dev->name);
+                       return ret; /* FIXME release resource */
+               }
+
+               ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
+                                           radio_nr);
+               if (ret < 0) {
+                       printk(KERN_INFO "%s: can't register radio device\n",
+                              dev->name);
+                       return ret; /* FIXME release resource */
+               }
+
+               printk(KERN_INFO "%s: registered device %s\n",
+                      dev->name, video_device_node_name(dev->radio_dev));
+       }
+
+       printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret);
+       return ret;
+}
+
+int tm6000_v4l2_unregister(struct tm6000_core *dev)
+{
+       video_unregister_device(dev->vfd);
+
+       if (dev->radio_dev) {
+               if (video_is_registered(dev->radio_dev))
+                       video_unregister_device(dev->radio_dev);
+               else
+                       video_device_release(dev->radio_dev);
+               dev->radio_dev = NULL;
+       }
+
+       return 0;
+}
+
+int tm6000_v4l2_exit(void)
+{
+       return 0;
+}
+
+module_param(video_nr, int, 0);
+MODULE_PARM_DESC(video_nr, "Allow changing video device number");
+
+module_param_named(debug, tm6000_debug, int, 0444);
+MODULE_PARM_DESC(debug, "activates debug info");
+
+module_param(vid_limit, int, 0644);
+MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
+
diff --git a/drivers/media/usb/tm6000/tm6000.h b/drivers/media/usb/tm6000/tm6000.h
new file mode 100644 (file)
index 0000000..6df4186
--- /dev/null
@@ -0,0 +1,399 @@
+/*
+ *  tm6000.h - driver for TM5600/TM6000/TM6010 USB video capture devices
+ *
+ *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
+ *
+ *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
+ *     - DVB-T support
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation version 2
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/videobuf-vmalloc.h>
+#include "tm6000-usb-isoc.h"
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <media/v4l2-device.h>
+
+#include <linux/dvb/frontend.h>
+#include "dvb_demux.h"
+#include "dvb_frontend.h"
+#include "dmxdev.h"
+
+/* Inputs */
+enum tm6000_itype {
+       TM6000_INPUT_TV = 1,
+       TM6000_INPUT_COMPOSITE1,
+       TM6000_INPUT_COMPOSITE2,
+       TM6000_INPUT_SVIDEO,
+       TM6000_INPUT_DVB,
+       TM6000_INPUT_RADIO,
+};
+
+enum tm6000_mux {
+       TM6000_VMUX_VIDEO_A = 1,
+       TM6000_VMUX_VIDEO_B,
+       TM6000_VMUX_VIDEO_AB,
+       TM6000_AMUX_ADC1,
+       TM6000_AMUX_ADC2,
+       TM6000_AMUX_SIF1,
+       TM6000_AMUX_SIF2,
+       TM6000_AMUX_I2S,
+};
+
+enum tm6000_devtype {
+       TM6000 = 0,
+       TM5600,
+       TM6010,
+};
+
+struct tm6000_input {
+       enum tm6000_itype       type;
+       enum tm6000_mux         vmux;
+       enum tm6000_mux         amux;
+       unsigned int            v_gpio;
+       unsigned int            a_gpio;
+};
+
+/* ------------------------------------------------------------------
+ *     Basic structures
+ * ------------------------------------------------------------------
+ */
+
+struct tm6000_fmt {
+       char  *name;
+       u32   fourcc;          /* v4l2 format id */
+       int   depth;
+};
+
+/* buffer for one video frame */
+struct tm6000_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct videobuf_buffer vb;
+
+       struct tm6000_fmt      *fmt;
+};
+
+struct tm6000_dmaqueue {
+       struct list_head       active;
+       struct list_head       queued;
+
+       /* thread for generating video stream*/
+       struct task_struct         *kthread;
+       wait_queue_head_t          wq;
+       /* Counters to control fps rate */
+       int                        frame;
+       int                        ini_jiffies;
+};
+
+/* device states */
+enum tm6000_core_state {
+       DEV_INITIALIZED   = 0x01,
+       DEV_DISCONNECTED  = 0x02,
+       DEV_MISCONFIGURED = 0x04,
+};
+
+/* io methods */
+enum tm6000_io_method {
+       IO_NONE,
+       IO_READ,
+       IO_MMAP,
+};
+
+enum tm6000_mode {
+       TM6000_MODE_UNKNOWN = 0,
+       TM6000_MODE_ANALOG,
+       TM6000_MODE_DIGITAL,
+};
+
+struct tm6000_gpio {
+       int             tuner_reset;
+       int             tuner_on;
+       int             demod_reset;
+       int             demod_on;
+       int             power_led;
+       int             dvb_led;
+       int             ir;
+};
+
+struct tm6000_capabilities {
+       unsigned int    has_tuner:1;
+       unsigned int    has_tda9874:1;
+       unsigned int    has_dvb:1;
+       unsigned int    has_zl10353:1;
+       unsigned int    has_eeprom:1;
+       unsigned int    has_remote:1;
+       unsigned int    has_radio:1;
+};
+
+struct tm6000_dvb {
+       struct dvb_adapter      adapter;
+       struct dvb_demux        demux;
+       struct dvb_frontend     *frontend;
+       struct dmxdev           dmxdev;
+       unsigned int            streams;
+       struct urb              *bulk_urb;
+       struct mutex            mutex;
+};
+
+struct snd_tm6000_card {
+       struct snd_card                 *card;
+       spinlock_t                      reg_lock;
+       struct tm6000_core              *core;
+       struct snd_pcm_substream        *substream;
+
+       /* temporary data for buffer fill processing */
+       unsigned                        buf_pos;
+       unsigned                        period_pos;
+};
+
+struct tm6000_endpoint {
+       struct usb_host_endpoint        *endp;
+       __u8                            bInterfaceNumber;
+       __u8                            bAlternateSetting;
+       unsigned                        maxsize;
+};
+
+#define TM6000_QUIRK_NO_USB_DELAY (1 << 0)
+
+struct tm6000_core {
+       /* generic device properties */
+       char                            name[30];       /* name (including minor) of the device */
+       int                             model;          /* index in the device_data struct */
+       int                             devno;          /* marks the number of this device */
+       enum tm6000_devtype             dev_type;       /* type of device */
+       unsigned char                   eedata[256];    /* Eeprom data */
+       unsigned                        eedata_size;    /* Size of the eeprom info */
+
+       v4l2_std_id                     norm;           /* Current norm */
+       int                             width, height;  /* Selected resolution */
+
+       enum tm6000_core_state          state;
+
+       /* Device Capabilities*/
+       struct tm6000_capabilities      caps;
+
+       /* Used to load alsa/dvb */
+        struct work_struct             request_module_wk;
+
+       /* Tuner configuration */
+       int                             tuner_type;             /* type of the tuner */
+       int                             tuner_addr;             /* tuner address */
+
+       struct tm6000_gpio              gpio;
+
+       char                            *ir_codes;
+
+       __u8                            radio;
+
+       /* Demodulator configuration */
+       int                             demod_addr;     /* demodulator address */
+
+       int                             audio_bitrate;
+       /* i2c i/o */
+       struct i2c_adapter              i2c_adap;
+       struct i2c_client               i2c_client;
+
+
+       /* extension */
+       struct list_head                devlist;
+
+       /* video for linux */
+       int                             users;
+
+       /* various device info */
+       struct tm6000_fh                *resources;     /* Points to fh that is streaming */
+       bool                            is_res_read;
+
+       struct video_device             *vfd;
+       struct video_device             *radio_dev;
+       struct tm6000_dmaqueue          vidq;
+       struct v4l2_device              v4l2_dev;
+
+       int                             input;
+       struct tm6000_input             vinput[3];      /* video input */
+       struct tm6000_input             rinput;         /* radio input */
+
+       int                             freq;
+       unsigned int                    fourcc;
+
+       enum tm6000_mode                mode;
+
+       int                             ctl_mute;             /* audio */
+       int                             ctl_volume;
+       int                             amode;
+
+       /* DVB-T support */
+       struct tm6000_dvb               *dvb;
+
+       /* audio support */
+       struct snd_tm6000_card          *adev;
+       struct work_struct              wq_trigger;   /* Trigger to start/stop audio for alsa module */
+       atomic_t                        stream_started;  /* stream should be running if true */
+
+       struct tm6000_IR                *ir;
+
+       /* locks */
+       struct mutex                    lock;
+       struct mutex                    usb_lock;
+
+       /* usb transfer */
+       struct usb_device               *udev;          /* the usb device */
+
+       struct tm6000_endpoint          bulk_in, bulk_out, isoc_in, isoc_out;
+       struct tm6000_endpoint          int_in, int_out;
+
+       /* scaler!=0 if scaler is active*/
+       int                             scaler;
+
+               /* Isoc control struct */
+       struct usb_isoc_ctl          isoc_ctl;
+
+       spinlock_t                   slock;
+
+       unsigned long quirks;
+};
+
+enum tm6000_ops_type {
+       TM6000_AUDIO = 0x10,
+       TM6000_DVB = 0x20,
+};
+
+struct tm6000_ops {
+       struct list_head        next;
+       char                    *name;
+       enum tm6000_ops_type    type;
+       int (*init)(struct tm6000_core *);
+       int (*fini)(struct tm6000_core *);
+       int (*fillbuf)(struct tm6000_core *, char *buf, int size);
+};
+
+struct tm6000_fh {
+       struct tm6000_core           *dev;
+       unsigned int                 radio;
+
+       /* video capture */
+       struct tm6000_fmt            *fmt;
+       unsigned int                 width, height;
+       struct videobuf_queue        vb_vidq;
+
+       enum v4l2_buf_type           type;
+};
+
+#define TM6000_STD     (V4L2_STD_PAL|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|    \
+                       V4L2_STD_PAL_M|V4L2_STD_PAL_60|V4L2_STD_NTSC_M| \
+                       V4L2_STD_NTSC_M_JP|V4L2_STD_SECAM)
+
+/* In tm6000-cards.c */
+
+int tm6000_tuner_callback(void *ptr, int component, int command, int arg);
+int tm6000_xc5000_callback(void *ptr, int component, int command, int arg);
+int tm6000_cards_setup(struct tm6000_core *dev);
+void tm6000_flash_led(struct tm6000_core *dev, u8 state);
+
+/* In tm6000-core.c */
+
+int tm6000_read_write_usb(struct tm6000_core *dev, u8 reqtype, u8 req,
+                          u16 value, u16 index, u8 *buf, u16 len);
+int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index);
+int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index);
+int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index);
+int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index);
+int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
+                                               u16 index, u16 mask);
+int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep);
+int tm6000_init(struct tm6000_core *dev);
+int tm6000_reset(struct tm6000_core *dev);
+
+int tm6000_init_analog_mode(struct tm6000_core *dev);
+int tm6000_init_digital_mode(struct tm6000_core *dev);
+int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate);
+int tm6000_set_audio_rinput(struct tm6000_core *dev);
+int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute);
+void tm6000_set_volume(struct tm6000_core *dev, int vol);
+
+int tm6000_v4l2_register(struct tm6000_core *dev);
+int tm6000_v4l2_unregister(struct tm6000_core *dev);
+int tm6000_v4l2_exit(void);
+void tm6000_set_fourcc_format(struct tm6000_core *dev);
+
+void tm6000_remove_from_devlist(struct tm6000_core *dev);
+void tm6000_add_into_devlist(struct tm6000_core *dev);
+int tm6000_register_extension(struct tm6000_ops *ops);
+void tm6000_unregister_extension(struct tm6000_ops *ops);
+void tm6000_init_extension(struct tm6000_core *dev);
+void tm6000_close_extension(struct tm6000_core *dev);
+int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
+                       char *buf, int size);
+
+
+/* In tm6000-stds.c */
+void tm6000_get_std_res(struct tm6000_core *dev);
+int tm6000_set_standard(struct tm6000_core *dev);
+
+/* In tm6000-i2c.c */
+int tm6000_i2c_register(struct tm6000_core *dev);
+int tm6000_i2c_unregister(struct tm6000_core *dev);
+
+/* In tm6000-queue.c */
+
+int tm6000_v4l2_mmap(struct file *filp, struct vm_area_struct *vma);
+
+int tm6000_vidioc_streamon(struct file *file, void *priv,
+                          enum v4l2_buf_type i);
+int tm6000_vidioc_streamoff(struct file *file, void *priv,
+                           enum v4l2_buf_type i);
+int tm6000_vidioc_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *rb);
+int tm6000_vidioc_querybuf(struct file *file, void *priv,
+                          struct v4l2_buffer *b);
+int tm6000_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b);
+int tm6000_vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b);
+ssize_t tm6000_v4l2_read(struct file *filp, char __user * buf, size_t count,
+                        loff_t *f_pos);
+unsigned int tm6000_v4l2_poll(struct file *file,
+                             struct poll_table_struct *wait);
+int tm6000_queue_init(struct tm6000_core *dev);
+
+/* In tm6000-alsa.c */
+/*int tm6000_audio_init(struct tm6000_core *dev, int idx);*/
+
+/* In tm6000-input.c */
+int tm6000_ir_init(struct tm6000_core *dev);
+int tm6000_ir_fini(struct tm6000_core *dev);
+void tm6000_ir_wait(struct tm6000_core *dev, u8 state);
+int tm6000_ir_int_start(struct tm6000_core *dev);
+void tm6000_ir_int_stop(struct tm6000_core *dev);
+
+/* Debug stuff */
+
+extern int tm6000_debug;
+
+#define dprintk(dev, level, fmt, arg...) do {\
+       if (tm6000_debug & level) \
+               printk(KERN_INFO "(%lu) %s %s :"fmt, jiffies, \
+                        dev->name, __func__ , ##arg); } while (0)
+
+#define V4L2_DEBUG_REG         0x0004
+#define V4L2_DEBUG_I2C         0x0008
+#define V4L2_DEBUG_QUEUE       0x0010
+#define V4L2_DEBUG_ISOC                0x0020
+#define V4L2_DEBUG_RES_LOCK    0x0040  /* Resource locking */
+#define V4L2_DEBUG_OPEN                0x0080  /* video open/close debug */
+
+#define tm6000_err(fmt, arg...) do {\
+       printk(KERN_ERR "tm6000 %s :"fmt, \
+               __func__ , ##arg); } while (0)
diff --git a/drivers/media/usb/usbvision/Kconfig b/drivers/media/usb/usbvision/Kconfig
new file mode 100644 (file)
index 0000000..fc24ef0
--- /dev/null
@@ -0,0 +1,12 @@
+config VIDEO_USBVISION
+       tristate "USB video devices based on Nogatech NT1003/1004/1005"
+       depends on I2C && VIDEO_V4L2
+       select VIDEO_TUNER
+       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
+       ---help---
+         There are more than 50 different USB video devices based on
+         NT1003/1004/1005 USB Bridges. This driver enables using those
+         devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called usbvision.
diff --git a/drivers/media/usb/usbvision/Makefile b/drivers/media/usb/usbvision/Makefile
new file mode 100644 (file)
index 0000000..d55c6bd
--- /dev/null
@@ -0,0 +1,6 @@
+usbvision-objs  := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-cards.o
+
+obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o
+
+ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/tuners
diff --git a/drivers/media/usb/usbvision/usbvision-cards.c b/drivers/media/usb/usbvision/usbvision-cards.c
new file mode 100644 (file)
index 0000000..3103d0d
--- /dev/null
@@ -0,0 +1,1133 @@
+/*
+ *  usbvision-cards.c
+ *  usbvision cards definition file
+ *
+ * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ *
+ * This module is part of usbvision driver project.
+ * Updates to driver completed by Dwaine P. Garden
+ *
+ * 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/list.h>
+#include <linux/module.h>
+#include <media/v4l2-dev.h>
+#include <media/tuner.h>
+#include "usbvision.h"
+#include "usbvision-cards.h"
+
+/* Supported Devices: A table for usbvision.c*/
+struct usbvision_device_data_st  usbvision_device_data[] = {
+       [XANBOO] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 4,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Xanboo",
+       },
+       [BELKIN_VIDEOBUS_II] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Belkin USB VideoBus II Adapter",
+       },
+       [BELKIN_VIDEOBUS] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Belkin Components USB VideoBus",
+       },
+       [BELKIN_USB_VIDEOBUS_II] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Belkin USB VideoBus II",
+       },
+       [ECHOFX_INTERVIEW_LITE] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 0,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "echoFX InterView Lite",
+       },
+       [USBGEAR_USBG_V1] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "USBGear USBG-V1 resp. HAMA USB",
+       },
+       [D_LINK_V100] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 4,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 0,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "D-Link V100",
+       },
+       [X10_USB_CAMERA] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "X10 USB Camera",
+       },
+       [HPG_WINTV_LIVE_PAL_BG] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = -1,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Live (PAL B/G)",
+       },
+       [HPG_WINTV_LIVE_PRO_NTSC_MN] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 0,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Live Pro (NTSC M/N)",
+       },
+       [ZORAN_PMD_NOGATECH] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 2,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Zoran Co. PMD (Nogatech) AV-grabber Manhattan",
+       },
+       [NOGATECH_USB_TV_NTSC_FM] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .x_offset       = -1,
+               .y_offset       = 20,
+               .model_string   = "Nogatech USB-TV (NTSC) FM",
+       },
+       [PNY_USB_TV_NTSC_FM] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .x_offset       = -1,
+               .y_offset       = 20,
+               .model_string   = "PNY USB-TV (NTSC) FM",
+       },
+       [PV_PLAYTV_USB_PRO_PAL_FM] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "PixelView PlayTv-USB PRO (PAL) FM",
+       },
+       [ZT_721] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "ZTV ZT-721 2.4GHz USB A/V Receiver",
+       },
+       [HPG_WINTV_NTSC_MN] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .x_offset       = -1,
+               .y_offset       = 20,
+               .model_string   = "Hauppauge WinTV USB (NTSC M/N)",
+       },
+       [HPG_WINTV_PAL_BG] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Hauppauge WinTV USB (PAL B/G)",
+       },
+       [HPG_WINTV_PAL_I] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Hauppauge WinTV USB (PAL I)",
+       },
+       [HPG_WINTV_PAL_SECAM_L] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_SECAM,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_SECAM,
+               .x_offset       = 0x80,
+               .y_offset       = 0x16,
+               .model_string   = "Hauppauge WinTV USB (PAL/SECAM L)",
+       },
+       [HPG_WINTV_PAL_D_K] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Hauppauge WinTV USB (PAL D/K)",
+       },
+       [HPG_WINTV_NTSC_FM] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Hauppauge WinTV USB (NTSC FM)",
+       },
+       [HPG_WINTV_PAL_BG_FM] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Hauppauge WinTV USB (PAL B/G FM)",
+       },
+       [HPG_WINTV_PAL_I_FM] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Hauppauge WinTV USB (PAL I FM)",
+       },
+       [HPG_WINTV_PAL_D_K_FM] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Hauppauge WinTV USB (PAL D/K FM)",
+       },
+       [HPG_WINTV_PRO_NTSC_MN] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_MICROTUNE_4049FM5,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (NTSC M/N)",
+       },
+       [HPG_WINTV_PRO_NTSC_MN_V2] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_MICROTUNE_4049FM5,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (NTSC M/N) V2",
+       },
+       [HPG_WINTV_PRO_PAL] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L)",
+       },
+       [HPG_WINTV_PRO_NTSC_MN_V3] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (NTSC M/N) V3",
+       },
+       [HPG_WINTV_PRO_PAL_BG] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (PAL B/G)",
+       },
+       [HPG_WINTV_PRO_PAL_I] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (PAL I)",
+       },
+       [HPG_WINTV_PRO_PAL_SECAM_L] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_SECAM,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_SECAM,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM L)",
+       },
+       [HPG_WINTV_PRO_PAL_D_K] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (PAL D/K)",
+       },
+       [HPG_WINTV_PRO_PAL_SECAM] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_SECAM,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_SECAM,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L)",
+       },
+       [HPG_WINTV_PRO_PAL_SECAM_V2] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_SECAM,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_SECAM,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L) V2",
+       },
+       [HPG_WINTV_PRO_PAL_BG_V2] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_ALPS_TSBE1_PAL,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (PAL B/G) V2",
+       },
+       [HPG_WINTV_PRO_PAL_BG_D_K] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_ALPS_TSBE1_PAL,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (PAL B/G,D/K)",
+       },
+       [HPG_WINTV_PRO_PAL_I_D_K] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (PAL I,D/K)",
+       },
+       [HPG_WINTV_PRO_NTSC_MN_FM] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (NTSC M/N FM)",
+       },
+       [HPG_WINTV_PRO_PAL_BG_FM] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (PAL B/G FM)",
+       },
+       [HPG_WINTV_PRO_PAL_I_FM] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (PAL I FM)",
+       },
+       [HPG_WINTV_PRO_PAL_D_K_FM] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (PAL D/K FM)",
+       },
+       [HPG_WINTV_PRO_TEMIC_PAL_FM] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_MICROTUNE_4049FM5,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (Temic PAL/SECAM B/G/I/D/K/L FM)",
+       },
+       [HPG_WINTV_PRO_TEMIC_PAL_BG_FM] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_MICROTUNE_4049FM5,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (Temic PAL B/G FM)",
+       },
+       [HPG_WINTV_PRO_PAL_FM] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L FM)",
+       },
+       [HPG_WINTV_PRO_NTSC_MN_FM_V2] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Hauppauge WinTV USB Pro (NTSC M/N FM) V2",
+       },
+       [CAMTEL_TVB330] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .x_offset       = 5,
+               .y_offset       = 5,
+               .model_string   = "Camtel Technology USB TV Genie Pro FM Model TVB330",
+       },
+       [DIGITAL_VIDEO_CREATOR_I] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 0,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Digital Video Creator I",
+       },
+       [GLOBAL_VILLAGE_GV_007_NTSC] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 0,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = 82,
+               .y_offset       = 20,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Global Village GV-007 (NTSC)",
+       },
+       [DAZZLE_DVC_50_REV_1_NTSC] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 0,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)",
+       },
+       [DAZZLE_DVC_80_REV_1_PAL] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 0,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Dazzle Fusion Model DVC-80 Rev 1 (PAL)",
+       },
+       [DAZZLE_DVC_90_REV_1_SECAM] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_SECAM,
+               .audio_channels = 0,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)",
+       },
+       [ESKAPE_LABS_MYTV2GO] = {
+               .interface      = 0,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Eskape Labs MyTV2Go",
+       },
+       [PINNA_PCTV_USB_PAL] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 0,
+               .tuner          = 1,
+               .tuner_type     = TUNER_TEMIC_4066FY5_PAL_I,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Pinnacle Studio PCTV USB (PAL)",
+       },
+       [PINNA_PCTV_USB_SECAM] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_SECAM,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_SECAM,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Pinnacle Studio PCTV USB (SECAM)",
+       },
+       [PINNA_PCTV_USB_PAL_FM] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = 128,
+               .y_offset       = 23,
+               .model_string   = "Pinnacle Studio PCTV USB (PAL) FM",
+       },
+       [MIRO_PCTV_USB] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_PAL,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Miro PCTV USB",
+       },
+       [PINNA_PCTV_USB_NTSC_FM] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Pinnacle Studio PCTV USB (NTSC) FM",
+       },
+       [PINNA_PCTV_USB_NTSC_FM_V3] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Pinnacle Studio PCTV USB (NTSC) FM V3",
+       },
+       [PINNA_PCTV_USB_PAL_FM_V2] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_TEMIC_4009FR5_PAL,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Pinnacle Studio PCTV USB (PAL) FM V2",
+       },
+       [PINNA_PCTV_USB_NTSC_FM_V2] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_TEMIC_4039FR5_NTSC,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Pinnacle Studio PCTV USB (NTSC) FM V2",
+       },
+       [PINNA_PCTV_USB_PAL_FM_V3] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_TEMIC_4009FR5_PAL,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Pinnacle Studio PCTV USB (PAL) FM V3",
+       },
+       [PINNA_LINX_VD_IN_CAB_NTSC] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Pinnacle Studio Linx Video input cable (NTSC)",
+       },
+       [PINNA_LINX_VD_IN_CAB_PAL] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 2,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Pinnacle Studio Linx Video input cable (PAL)",
+       },
+       [PINNA_PCTV_BUNGEE_PAL_FM] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7113,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 1,
+               .radio          = 1,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_TEMIC_4009FR5_PAL,
+               .x_offset       = 0,
+               .y_offset       = 3,
+               .dvi_yuv_override = 1,
+               .dvi_yuv        = 7,
+               .model_string   = "Pinnacle PCTV Bungee USB (PAL) FM",
+       },
+       [HPG_WINTV] = {
+               .interface      = -1,
+               .codec          = CODEC_SAA7111,
+               .video_channels = 3,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 1,
+               .radio          = 0,
+               .vbi            = 1,
+               .tuner          = 1,
+               .tuner_type     = TUNER_PHILIPS_NTSC_M,
+               .x_offset       = -1,
+               .y_offset       = -1,
+               .model_string   = "Hauppauge WinTv-USB",
+       },
+       [MICROCAM_NTSC] = {
+               .interface      = -1,
+               .codec          = CODEC_WEBCAM,
+               .video_channels = 1,
+               .video_norm     = V4L2_STD_NTSC,
+               .audio_channels = 0,
+               .radio          = 0,
+               .vbi            = 0,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = 71,
+               .y_offset       = 15,
+               .model_string   = "Nogatech USB MicroCam NTSC (NV3000N)",
+       },
+       [MICROCAM_PAL] = {
+               .interface      = -1,
+               .codec          = CODEC_WEBCAM,
+               .video_channels = 1,
+               .video_norm     = V4L2_STD_PAL,
+               .audio_channels = 0,
+               .radio          = 0,
+               .vbi            = 0,
+               .tuner          = 0,
+               .tuner_type     = 0,
+               .x_offset       = 71,
+               .y_offset       = 18,
+               .model_string   = "Nogatech USB MicroCam PAL (NV3001P)",
+       },
+};
+const int usbvision_device_data_size = ARRAY_SIZE(usbvision_device_data);
+
+/* Supported Devices */
+
+struct usb_device_id usbvision_table[] = {
+       { USB_DEVICE(0x0a6f, 0x0400), .driver_info = XANBOO },
+       { USB_DEVICE(0x050d, 0x0106), .driver_info = BELKIN_VIDEOBUS_II },
+       { USB_DEVICE(0x050d, 0x0207), .driver_info = BELKIN_VIDEOBUS },
+       { USB_DEVICE(0x050d, 0x0208), .driver_info = BELKIN_USB_VIDEOBUS_II },
+       { USB_DEVICE(0x0571, 0x0002), .driver_info = ECHOFX_INTERVIEW_LITE },
+       { USB_DEVICE(0x0573, 0x0003), .driver_info = USBGEAR_USBG_V1 },
+       { USB_DEVICE(0x0573, 0x0400), .driver_info = D_LINK_V100 },
+       { USB_DEVICE(0x0573, 0x2000), .driver_info = X10_USB_CAMERA },
+       { USB_DEVICE(0x0573, 0x2d00), .driver_info = HPG_WINTV_LIVE_PAL_BG },
+       { USB_DEVICE(0x0573, 0x2d01), .driver_info = HPG_WINTV_LIVE_PRO_NTSC_MN },
+       { USB_DEVICE(0x0573, 0x2101), .driver_info = ZORAN_PMD_NOGATECH },
+       { USB_DEVICE(0x0573, 0x3000), .driver_info = MICROCAM_NTSC },
+       { USB_DEVICE(0x0573, 0x3001), .driver_info = MICROCAM_PAL },
+       { USB_DEVICE(0x0573, 0x4100), .driver_info = NOGATECH_USB_TV_NTSC_FM },
+       { USB_DEVICE(0x0573, 0x4110), .driver_info = PNY_USB_TV_NTSC_FM },
+       { USB_DEVICE(0x0573, 0x4450), .driver_info = PV_PLAYTV_USB_PRO_PAL_FM },
+       { USB_DEVICE(0x0573, 0x4550), .driver_info = ZT_721 },
+       { USB_DEVICE(0x0573, 0x4d00), .driver_info = HPG_WINTV_NTSC_MN },
+       { USB_DEVICE(0x0573, 0x4d01), .driver_info = HPG_WINTV_PAL_BG },
+       { USB_DEVICE(0x0573, 0x4d02), .driver_info = HPG_WINTV_PAL_I },
+       { USB_DEVICE(0x0573, 0x4d03), .driver_info = HPG_WINTV_PAL_SECAM_L },
+       { USB_DEVICE(0x0573, 0x4d04), .driver_info = HPG_WINTV_PAL_D_K },
+       { USB_DEVICE(0x0573, 0x4d10), .driver_info = HPG_WINTV_NTSC_FM },
+       { USB_DEVICE(0x0573, 0x4d11), .driver_info = HPG_WINTV_PAL_BG_FM },
+       { USB_DEVICE(0x0573, 0x4d12), .driver_info = HPG_WINTV_PAL_I_FM },
+       { USB_DEVICE(0x0573, 0x4d14), .driver_info = HPG_WINTV_PAL_D_K_FM },
+       { USB_DEVICE(0x0573, 0x4d2a), .driver_info = HPG_WINTV_PRO_NTSC_MN },
+       { USB_DEVICE(0x0573, 0x4d2b), .driver_info = HPG_WINTV_PRO_NTSC_MN_V2 },
+       { USB_DEVICE(0x0573, 0x4d2c), .driver_info = HPG_WINTV_PRO_PAL },
+       { USB_DEVICE(0x0573, 0x4d20), .driver_info = HPG_WINTV_PRO_NTSC_MN_V3 },
+       { USB_DEVICE(0x0573, 0x4d21), .driver_info = HPG_WINTV_PRO_PAL_BG },
+       { USB_DEVICE(0x0573, 0x4d22), .driver_info = HPG_WINTV_PRO_PAL_I },
+       { USB_DEVICE(0x0573, 0x4d23), .driver_info = HPG_WINTV_PRO_PAL_SECAM_L },
+       { USB_DEVICE(0x0573, 0x4d24), .driver_info = HPG_WINTV_PRO_PAL_D_K },
+       { USB_DEVICE(0x0573, 0x4d25), .driver_info = HPG_WINTV_PRO_PAL_SECAM },
+       { USB_DEVICE(0x0573, 0x4d26), .driver_info = HPG_WINTV_PRO_PAL_SECAM_V2 },
+       { USB_DEVICE(0x0573, 0x4d27), .driver_info = HPG_WINTV_PRO_PAL_BG_V2 },
+       { USB_DEVICE(0x0573, 0x4d28), .driver_info = HPG_WINTV_PRO_PAL_BG_D_K },
+       { USB_DEVICE(0x0573, 0x4d29), .driver_info = HPG_WINTV_PRO_PAL_I_D_K },
+       { USB_DEVICE(0x0573, 0x4d30), .driver_info = HPG_WINTV_PRO_NTSC_MN_FM },
+       { USB_DEVICE(0x0573, 0x4d31), .driver_info = HPG_WINTV_PRO_PAL_BG_FM },
+       { USB_DEVICE(0x0573, 0x4d32), .driver_info = HPG_WINTV_PRO_PAL_I_FM },
+       { USB_DEVICE(0x0573, 0x4d34), .driver_info = HPG_WINTV_PRO_PAL_D_K_FM },
+       { USB_DEVICE(0x0573, 0x4d35), .driver_info = HPG_WINTV_PRO_TEMIC_PAL_FM },
+       { USB_DEVICE(0x0573, 0x4d36), .driver_info = HPG_WINTV_PRO_TEMIC_PAL_BG_FM },
+       { USB_DEVICE(0x0573, 0x4d37), .driver_info = HPG_WINTV_PRO_PAL_FM },
+       { USB_DEVICE(0x0573, 0x4d38), .driver_info = HPG_WINTV_PRO_NTSC_MN_FM_V2 },
+       { USB_DEVICE(0x0768, 0x0006), .driver_info = CAMTEL_TVB330 },
+       { USB_DEVICE(0x07d0, 0x0001), .driver_info = DIGITAL_VIDEO_CREATOR_I },
+       { USB_DEVICE(0x07d0, 0x0002), .driver_info = GLOBAL_VILLAGE_GV_007_NTSC },
+       { USB_DEVICE(0x07d0, 0x0003), .driver_info = DAZZLE_DVC_50_REV_1_NTSC },
+       { USB_DEVICE(0x07d0, 0x0004), .driver_info = DAZZLE_DVC_80_REV_1_PAL },
+       { USB_DEVICE(0x07d0, 0x0005), .driver_info = DAZZLE_DVC_90_REV_1_SECAM },
+       { USB_DEVICE(0x07f8, 0x9104), .driver_info = ESKAPE_LABS_MYTV2GO },
+       { USB_DEVICE(0x2304, 0x010d), .driver_info = PINNA_PCTV_USB_PAL },
+       { USB_DEVICE(0x2304, 0x0109), .driver_info = PINNA_PCTV_USB_SECAM },
+       { USB_DEVICE(0x2304, 0x0110), .driver_info = PINNA_PCTV_USB_PAL_FM },
+       { USB_DEVICE(0x2304, 0x0111), .driver_info = MIRO_PCTV_USB },
+       { USB_DEVICE(0x2304, 0x0112), .driver_info = PINNA_PCTV_USB_NTSC_FM },
+       { USB_DEVICE(0x2304, 0x0113), .driver_info = PINNA_PCTV_USB_NTSC_FM_V3 },
+       { USB_DEVICE(0x2304, 0x0210), .driver_info = PINNA_PCTV_USB_PAL_FM_V2 },
+       { USB_DEVICE(0x2304, 0x0212), .driver_info = PINNA_PCTV_USB_NTSC_FM_V2 },
+       { USB_DEVICE(0x2304, 0x0214), .driver_info = PINNA_PCTV_USB_PAL_FM_V3 },
+       { USB_DEVICE(0x2304, 0x0300), .driver_info = PINNA_LINX_VD_IN_CAB_NTSC },
+       { USB_DEVICE(0x2304, 0x0301), .driver_info = PINNA_LINX_VD_IN_CAB_PAL },
+       { USB_DEVICE(0x2304, 0x0419), .driver_info = PINNA_PCTV_BUNGEE_PAL_FM },
+       { USB_DEVICE(0x2400, 0x4200), .driver_info = HPG_WINTV },
+       { },    /* terminate list */
+};
+
+MODULE_DEVICE_TABLE(usb, usbvision_table);
diff --git a/drivers/media/usb/usbvision/usbvision-cards.h b/drivers/media/usb/usbvision/usbvision-cards.h
new file mode 100644 (file)
index 0000000..a51cc11
--- /dev/null
@@ -0,0 +1,69 @@
+#define XANBOO                                   0
+#define BELKIN_VIDEOBUS_II                       1
+#define BELKIN_VIDEOBUS                          2
+#define BELKIN_USB_VIDEOBUS_II                   3
+#define ECHOFX_INTERVIEW_LITE                    4
+#define USBGEAR_USBG_V1                          5
+#define D_LINK_V100                              6
+#define X10_USB_CAMERA                           7
+#define HPG_WINTV_LIVE_PAL_BG                    8
+#define HPG_WINTV_LIVE_PRO_NTSC_MN               9
+#define ZORAN_PMD_NOGATECH                       10
+#define NOGATECH_USB_TV_NTSC_FM                  11
+#define PNY_USB_TV_NTSC_FM                       12
+#define PV_PLAYTV_USB_PRO_PAL_FM                 13
+#define ZT_721                                   14
+#define HPG_WINTV_NTSC_MN                        15
+#define HPG_WINTV_PAL_BG                         16
+#define HPG_WINTV_PAL_I                          17
+#define HPG_WINTV_PAL_SECAM_L                    18
+#define HPG_WINTV_PAL_D_K                        19
+#define HPG_WINTV_NTSC_FM                        20
+#define HPG_WINTV_PAL_BG_FM                      21
+#define HPG_WINTV_PAL_I_FM                       22
+#define HPG_WINTV_PAL_D_K_FM                     23
+#define HPG_WINTV_PRO_NTSC_MN                    24
+#define HPG_WINTV_PRO_NTSC_MN_V2                 25
+#define HPG_WINTV_PRO_PAL                        26
+#define HPG_WINTV_PRO_NTSC_MN_V3                 27
+#define HPG_WINTV_PRO_PAL_BG                     28
+#define HPG_WINTV_PRO_PAL_I                      29
+#define HPG_WINTV_PRO_PAL_SECAM_L                30
+#define HPG_WINTV_PRO_PAL_D_K                    31
+#define HPG_WINTV_PRO_PAL_SECAM                  32
+#define HPG_WINTV_PRO_PAL_SECAM_V2               33
+#define HPG_WINTV_PRO_PAL_BG_V2                  34
+#define HPG_WINTV_PRO_PAL_BG_D_K                 35
+#define HPG_WINTV_PRO_PAL_I_D_K                  36
+#define HPG_WINTV_PRO_NTSC_MN_FM                 37
+#define HPG_WINTV_PRO_PAL_BG_FM                  38
+#define HPG_WINTV_PRO_PAL_I_FM                   39
+#define HPG_WINTV_PRO_PAL_D_K_FM                 40
+#define HPG_WINTV_PRO_TEMIC_PAL_FM               41
+#define HPG_WINTV_PRO_TEMIC_PAL_BG_FM            42
+#define HPG_WINTV_PRO_PAL_FM                     43
+#define HPG_WINTV_PRO_NTSC_MN_FM_V2              44
+#define CAMTEL_TVB330                            45
+#define DIGITAL_VIDEO_CREATOR_I                  46
+#define GLOBAL_VILLAGE_GV_007_NTSC               47
+#define DAZZLE_DVC_50_REV_1_NTSC                 48
+#define DAZZLE_DVC_80_REV_1_PAL                  49
+#define DAZZLE_DVC_90_REV_1_SECAM                50
+#define ESKAPE_LABS_MYTV2GO                      51
+#define PINNA_PCTV_USB_PAL                       52
+#define PINNA_PCTV_USB_SECAM                     53
+#define PINNA_PCTV_USB_PAL_FM                    54
+#define MIRO_PCTV_USB                            55
+#define PINNA_PCTV_USB_NTSC_FM                   56
+#define PINNA_PCTV_USB_PAL_FM_V2                 57
+#define PINNA_PCTV_USB_NTSC_FM_V2                58
+#define PINNA_PCTV_USB_PAL_FM_V3                 59
+#define PINNA_LINX_VD_IN_CAB_NTSC                60
+#define PINNA_LINX_VD_IN_CAB_PAL                 61
+#define PINNA_PCTV_BUNGEE_PAL_FM                 62
+#define HPG_WINTV                                63
+#define PINNA_PCTV_USB_NTSC_FM_V3                64
+#define MICROCAM_NTSC                            65
+#define MICROCAM_PAL                             66
+
+extern const int usbvision_device_data_size;
diff --git a/drivers/media/usb/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c
new file mode 100644 (file)
index 0000000..c9b2042
--- /dev/null
@@ -0,0 +1,2518 @@
+/*
+ * usbvision-core.c - driver for NT100x USB video capture devices
+ *
+ *
+ * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ *                         Dwaine Garden <dwainegarden@rogers.com>
+ *
+ * This module is part of usbvision driver project.
+ * Updates to driver completed by Dwaine P. Garden
+ *
+ * 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/list.h>
+#include <linux/timer.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+
+#include <media/saa7115.h>
+#include <media/v4l2-common.h>
+#include <media/tuner.h>
+
+#include <linux/workqueue.h>
+
+#include "usbvision.h"
+
+static unsigned int core_debug;
+module_param(core_debug, int, 0644);
+MODULE_PARM_DESC(core_debug, "enable debug messages [core]");
+
+static int adjust_compression = 1;     /* Set the compression to be adaptive */
+module_param(adjust_compression, int, 0444);
+MODULE_PARM_DESC(adjust_compression, " Set the ADPCM compression for the device.  Default: 1 (On)");
+
+/* To help people with Black and White output with using s-video input.
+ * Some cables and input device are wired differently. */
+static int switch_svideo_input;
+module_param(switch_svideo_input, int, 0444);
+MODULE_PARM_DESC(switch_svideo_input, " Set the S-Video input.  Some cables and input device are wired differently. Default: 0 (Off)");
+
+static unsigned int adjust_x_offset = -1;
+module_param(adjust_x_offset, int, 0644);
+MODULE_PARM_DESC(adjust_x_offset, "adjust X offset display [core]");
+
+static unsigned int adjust_y_offset = -1;
+module_param(adjust_y_offset, int, 0644);
+MODULE_PARM_DESC(adjust_y_offset, "adjust Y offset display [core]");
+
+
+#define        ENABLE_HEXDUMP  0       /* Enable if you need it */
+
+
+#ifdef USBVISION_DEBUG
+       #define PDEBUG(level, fmt, args...) { \
+               if (core_debug & (level)) \
+                       printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \
+                               __func__, __LINE__ , ## args); \
+       }
+#else
+       #define PDEBUG(level, fmt, args...) do {} while (0)
+#endif
+
+#define DBG_HEADER     (1 << 0)
+#define DBG_IRQ                (1 << 1)
+#define DBG_ISOC       (1 << 2)
+#define DBG_PARSE      (1 << 3)
+#define DBG_SCRATCH    (1 << 4)
+#define DBG_FUNC       (1 << 5)
+
+static const int max_imgwidth = MAX_FRAME_WIDTH;
+static const int max_imgheight = MAX_FRAME_HEIGHT;
+static const int min_imgwidth = MIN_FRAME_WIDTH;
+static const int min_imgheight = MIN_FRAME_HEIGHT;
+
+/* The value of 'scratch_buf_size' affects quality of the picture
+ * in many ways. Shorter buffers may cause loss of data when client
+ * is too slow. Larger buffers are memory-consuming and take longer
+ * to work with. This setting can be adjusted, but the default value
+ * should be OK for most desktop users.
+ */
+#define DEFAULT_SCRATCH_BUF_SIZE       (0x20000)               /* 128kB memory scratch buffer */
+static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE;
+
+/* Function prototypes */
+static int usbvision_request_intra(struct usb_usbvision *usbvision);
+static int usbvision_unrequest_intra(struct usb_usbvision *usbvision);
+static int usbvision_adjust_compression(struct usb_usbvision *usbvision);
+static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision);
+
+/*******************************/
+/* Memory management functions */
+/*******************************/
+
+/*
+ * Here we want the physical address of the memory.
+ * This is used when initializing the contents of the area.
+ */
+
+static void *usbvision_rvmalloc(unsigned long size)
+{
+       void *mem;
+       unsigned long adr;
+
+       size = PAGE_ALIGN(size);
+       mem = vmalloc_32(size);
+       if (!mem)
+               return NULL;
+
+       memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+       adr = (unsigned long) mem;
+       while (size > 0) {
+               SetPageReserved(vmalloc_to_page((void *)adr));
+               adr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       return mem;
+}
+
+static void usbvision_rvfree(void *mem, unsigned long size)
+{
+       unsigned long adr;
+
+       if (!mem)
+               return;
+
+       size = PAGE_ALIGN(size);
+
+       adr = (unsigned long) mem;
+       while ((long) size > 0) {
+               ClearPageReserved(vmalloc_to_page((void *)adr));
+               adr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       vfree(mem);
+}
+
+
+#if ENABLE_HEXDUMP
+static void usbvision_hexdump(const unsigned char *data, int len)
+{
+       char tmp[80];
+       int i, k;
+
+       for (i = k = 0; len > 0; i++, len--) {
+               if (i > 0 && (i % 16 == 0)) {
+                       printk("%s\n", tmp);
+                       k = 0;
+               }
+               k += sprintf(&tmp[k], "%02x ", data[i]);
+       }
+       if (k > 0)
+               printk(KERN_CONT "%s\n", tmp);
+}
+#endif
+
+/********************************
+ * scratch ring buffer handling
+ ********************************/
+static int scratch_len(struct usb_usbvision *usbvision)    /* This returns the amount of data actually in the buffer */
+{
+       int len = usbvision->scratch_write_ptr - usbvision->scratch_read_ptr;
+
+       if (len < 0)
+               len += scratch_buf_size;
+       PDEBUG(DBG_SCRATCH, "scratch_len() = %d\n", len);
+
+       return len;
+}
+
+
+/* This returns the free space left in the buffer */
+static int scratch_free(struct usb_usbvision *usbvision)
+{
+       int free = usbvision->scratch_read_ptr - usbvision->scratch_write_ptr;
+       if (free <= 0)
+               free += scratch_buf_size;
+       if (free) {
+               free -= 1;                                                      /* at least one byte in the buffer must */
+                                                                               /* left blank, otherwise there is no chance to differ between full and empty */
+       }
+       PDEBUG(DBG_SCRATCH, "return %d\n", free);
+
+       return free;
+}
+
+
+/* This puts data into the buffer */
+static int scratch_put(struct usb_usbvision *usbvision, unsigned char *data,
+                      int len)
+{
+       int len_part;
+
+       if (usbvision->scratch_write_ptr + len < scratch_buf_size) {
+               memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len);
+               usbvision->scratch_write_ptr += len;
+       } else {
+               len_part = scratch_buf_size - usbvision->scratch_write_ptr;
+               memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len_part);
+               if (len == len_part) {
+                       usbvision->scratch_write_ptr = 0;                       /* just set write_ptr to zero */
+               } else {
+                       memcpy(usbvision->scratch, data + len_part, len - len_part);
+                       usbvision->scratch_write_ptr = len - len_part;
+               }
+       }
+
+       PDEBUG(DBG_SCRATCH, "len=%d, new write_ptr=%d\n", len, usbvision->scratch_write_ptr);
+
+       return len;
+}
+
+/* This marks the write_ptr as position of new frame header */
+static void scratch_mark_header(struct usb_usbvision *usbvision)
+{
+       PDEBUG(DBG_SCRATCH, "header at write_ptr=%d\n", usbvision->scratch_headermarker_write_ptr);
+
+       usbvision->scratch_headermarker[usbvision->scratch_headermarker_write_ptr] =
+                               usbvision->scratch_write_ptr;
+       usbvision->scratch_headermarker_write_ptr += 1;
+       usbvision->scratch_headermarker_write_ptr %= USBVISION_NUM_HEADERMARKER;
+}
+
+/* This gets data from the buffer at the given "ptr" position */
+static int scratch_get_extra(struct usb_usbvision *usbvision,
+                            unsigned char *data, int *ptr, int len)
+{
+       int len_part;
+
+       if (*ptr + len < scratch_buf_size) {
+               memcpy(data, usbvision->scratch + *ptr, len);
+               *ptr += len;
+       } else {
+               len_part = scratch_buf_size - *ptr;
+               memcpy(data, usbvision->scratch + *ptr, len_part);
+               if (len == len_part) {
+                       *ptr = 0;                                                       /* just set the y_ptr to zero */
+               } else {
+                       memcpy(data + len_part, usbvision->scratch, len - len_part);
+                       *ptr = len - len_part;
+               }
+       }
+
+       PDEBUG(DBG_SCRATCH, "len=%d, new ptr=%d\n", len, *ptr);
+
+       return len;
+}
+
+
+/* This sets the scratch extra read pointer */
+static void scratch_set_extra_ptr(struct usb_usbvision *usbvision, int *ptr,
+                                 int len)
+{
+       *ptr = (usbvision->scratch_read_ptr + len) % scratch_buf_size;
+
+       PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr);
+}
+
+
+/* This increments the scratch extra read pointer */
+static void scratch_inc_extra_ptr(int *ptr, int len)
+{
+       *ptr = (*ptr + len) % scratch_buf_size;
+
+       PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr);
+}
+
+
+/* This gets data from the buffer */
+static int scratch_get(struct usb_usbvision *usbvision, unsigned char *data,
+                      int len)
+{
+       int len_part;
+
+       if (usbvision->scratch_read_ptr + len < scratch_buf_size) {
+               memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len);
+               usbvision->scratch_read_ptr += len;
+       } else {
+               len_part = scratch_buf_size - usbvision->scratch_read_ptr;
+               memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len_part);
+               if (len == len_part) {
+                       usbvision->scratch_read_ptr = 0;                                /* just set the read_ptr to zero */
+               } else {
+                       memcpy(data + len_part, usbvision->scratch, len - len_part);
+                       usbvision->scratch_read_ptr = len - len_part;
+               }
+       }
+
+       PDEBUG(DBG_SCRATCH, "len=%d, new read_ptr=%d\n", len, usbvision->scratch_read_ptr);
+
+       return len;
+}
+
+
+/* This sets read pointer to next header and returns it */
+static int scratch_get_header(struct usb_usbvision *usbvision,
+                             struct usbvision_frame_header *header)
+{
+       int err_code = 0;
+
+       PDEBUG(DBG_SCRATCH, "from read_ptr=%d", usbvision->scratch_headermarker_read_ptr);
+
+       while (usbvision->scratch_headermarker_write_ptr -
+               usbvision->scratch_headermarker_read_ptr != 0) {
+               usbvision->scratch_read_ptr =
+                       usbvision->scratch_headermarker[usbvision->scratch_headermarker_read_ptr];
+               usbvision->scratch_headermarker_read_ptr += 1;
+               usbvision->scratch_headermarker_read_ptr %= USBVISION_NUM_HEADERMARKER;
+               scratch_get(usbvision, (unsigned char *)header, USBVISION_HEADER_LENGTH);
+               if ((header->magic_1 == USBVISION_MAGIC_1)
+                        && (header->magic_2 == USBVISION_MAGIC_2)
+                        && (header->header_length == USBVISION_HEADER_LENGTH)) {
+                       err_code = USBVISION_HEADER_LENGTH;
+                       header->frame_width  = header->frame_width_lo  + (header->frame_width_hi << 8);
+                       header->frame_height = header->frame_height_lo + (header->frame_height_hi << 8);
+                       break;
+               }
+       }
+
+       return err_code;
+}
+
+
+/* This removes len bytes of old data from the buffer */
+static void scratch_rm_old(struct usb_usbvision *usbvision, int len)
+{
+       usbvision->scratch_read_ptr += len;
+       usbvision->scratch_read_ptr %= scratch_buf_size;
+       PDEBUG(DBG_SCRATCH, "read_ptr is now %d\n", usbvision->scratch_read_ptr);
+}
+
+
+/* This resets the buffer - kills all data in it too */
+static void scratch_reset(struct usb_usbvision *usbvision)
+{
+       PDEBUG(DBG_SCRATCH, "\n");
+
+       usbvision->scratch_read_ptr = 0;
+       usbvision->scratch_write_ptr = 0;
+       usbvision->scratch_headermarker_read_ptr = 0;
+       usbvision->scratch_headermarker_write_ptr = 0;
+       usbvision->isocstate = isoc_state_no_frame;
+}
+
+int usbvision_scratch_alloc(struct usb_usbvision *usbvision)
+{
+       usbvision->scratch = vmalloc_32(scratch_buf_size);
+       scratch_reset(usbvision);
+       if (usbvision->scratch == NULL) {
+               dev_err(&usbvision->dev->dev,
+                       "%s: unable to allocate %d bytes for scratch\n",
+                               __func__, scratch_buf_size);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+void usbvision_scratch_free(struct usb_usbvision *usbvision)
+{
+       vfree(usbvision->scratch);
+       usbvision->scratch = NULL;
+}
+
+/*
+ * usbvision_decompress_alloc()
+ *
+ * allocates intermediate buffer for decompression
+ */
+int usbvision_decompress_alloc(struct usb_usbvision *usbvision)
+{
+       int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2;
+
+       usbvision->intra_frame_buffer = vmalloc_32(IFB_size);
+       if (usbvision->intra_frame_buffer == NULL) {
+               dev_err(&usbvision->dev->dev,
+                       "%s: unable to allocate %d for compr. frame buffer\n",
+                               __func__, IFB_size);
+               return -ENOMEM;
+       }
+       return 0;
+}
+
+/*
+ * usbvision_decompress_free()
+ *
+ * frees intermediate buffer for decompression
+ */
+void usbvision_decompress_free(struct usb_usbvision *usbvision)
+{
+       vfree(usbvision->intra_frame_buffer);
+       usbvision->intra_frame_buffer = NULL;
+
+}
+
+/************************************************************
+ * Here comes the data parsing stuff that is run as interrupt
+ ************************************************************/
+/*
+ * usbvision_find_header()
+ *
+ * Locate one of supported header markers in the scratch buffer.
+ */
+static enum parse_state usbvision_find_header(struct usb_usbvision *usbvision)
+{
+       struct usbvision_frame *frame;
+       int found_header = 0;
+
+       frame = usbvision->cur_frame;
+
+       while (scratch_get_header(usbvision, &frame->isoc_header) == USBVISION_HEADER_LENGTH) {
+               /* found header in scratch */
+               PDEBUG(DBG_HEADER, "found header: 0x%02x%02x %d %d %d %d %#x 0x%02x %u %u",
+                               frame->isoc_header.magic_2,
+                               frame->isoc_header.magic_1,
+                               frame->isoc_header.header_length,
+                               frame->isoc_header.frame_num,
+                               frame->isoc_header.frame_phase,
+                               frame->isoc_header.frame_latency,
+                               frame->isoc_header.data_format,
+                               frame->isoc_header.format_param,
+                               frame->isoc_header.frame_width,
+                               frame->isoc_header.frame_height);
+
+               if (usbvision->request_intra) {
+                       if (frame->isoc_header.format_param & 0x80) {
+                               found_header = 1;
+                               usbvision->last_isoc_frame_num = -1; /* do not check for lost frames this time */
+                               usbvision_unrequest_intra(usbvision);
+                               break;
+                       }
+               } else {
+                       found_header = 1;
+                       break;
+               }
+       }
+
+       if (found_header) {
+               frame->frmwidth = frame->isoc_header.frame_width * usbvision->stretch_width;
+               frame->frmheight = frame->isoc_header.frame_height * usbvision->stretch_height;
+               frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth) >> 3;
+       } else { /* no header found */
+               PDEBUG(DBG_HEADER, "skipping scratch data, no header");
+               scratch_reset(usbvision);
+               return parse_state_end_parse;
+       }
+
+       /* found header */
+       if (frame->isoc_header.data_format == ISOC_MODE_COMPRESS) {
+               /* check isoc_header.frame_num for lost frames */
+               if (usbvision->last_isoc_frame_num >= 0) {
+                       if (((usbvision->last_isoc_frame_num + 1) % 32) != frame->isoc_header.frame_num) {
+                               /* unexpected frame drop: need to request new intra frame */
+                               PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isoc_header.frame_num);
+                               usbvision_request_intra(usbvision);
+                               return parse_state_next_frame;
+                       }
+               }
+               usbvision->last_isoc_frame_num = frame->isoc_header.frame_num;
+       }
+       usbvision->header_count++;
+       frame->scanstate = scan_state_lines;
+       frame->curline = 0;
+
+       return parse_state_continue;
+}
+
+static enum parse_state usbvision_parse_lines_422(struct usb_usbvision *usbvision,
+                                          long *pcopylen)
+{
+       volatile struct usbvision_frame *frame;
+       unsigned char *f;
+       int len;
+       int i;
+       unsigned char yuyv[4] = { 180, 128, 10, 128 }; /* YUV components */
+       unsigned char rv, gv, bv;       /* RGB components */
+       int clipmask_index, bytes_per_pixel;
+       int stretch_bytes, clipmask_add;
+
+       frame  = usbvision->cur_frame;
+       f = frame->data + (frame->v4l2_linesize * frame->curline);
+
+       /* Make sure there's enough data for the entire line */
+       len = (frame->isoc_header.frame_width * 2) + 5;
+       if (scratch_len(usbvision) < len) {
+               PDEBUG(DBG_PARSE, "out of data in line %d, need %u.\n", frame->curline, len);
+               return parse_state_out;
+       }
+
+       if ((frame->curline + 1) >= frame->frmheight)
+               return parse_state_next_frame;
+
+       bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
+       stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel;
+       clipmask_index = frame->curline * MAX_FRAME_WIDTH;
+       clipmask_add = usbvision->stretch_width;
+
+       for (i = 0; i < frame->frmwidth; i += (2 * usbvision->stretch_width)) {
+               scratch_get(usbvision, &yuyv[0], 4);
+
+               if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+                       *f++ = yuyv[0]; /* Y */
+                       *f++ = yuyv[3]; /* U */
+               } else {
+                       YUV_TO_RGB_BY_THE_BOOK(yuyv[0], yuyv[1], yuyv[3], rv, gv, bv);
+                       switch (frame->v4l2_format.format) {
+                       case V4L2_PIX_FMT_RGB565:
+                               *f++ = (0x1F & rv) |
+                                       (0xE0 & (gv << 5));
+                               *f++ = (0x07 & (gv >> 3)) |
+                                       (0xF8 &  bv);
+                               break;
+                       case V4L2_PIX_FMT_RGB24:
+                               *f++ = rv;
+                               *f++ = gv;
+                               *f++ = bv;
+                               break;
+                       case V4L2_PIX_FMT_RGB32:
+                               *f++ = rv;
+                               *f++ = gv;
+                               *f++ = bv;
+                               f++;
+                               break;
+                       case V4L2_PIX_FMT_RGB555:
+                               *f++ = (0x1F & rv) |
+                                       (0xE0 & (gv << 5));
+                               *f++ = (0x03 & (gv >> 3)) |
+                                       (0x7C & (bv << 2));
+                               break;
+                       }
+               }
+               clipmask_index += clipmask_add;
+               f += stretch_bytes;
+
+               if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+                       *f++ = yuyv[2]; /* Y */
+                       *f++ = yuyv[1]; /* V */
+               } else {
+                       YUV_TO_RGB_BY_THE_BOOK(yuyv[2], yuyv[1], yuyv[3], rv, gv, bv);
+                       switch (frame->v4l2_format.format) {
+                       case V4L2_PIX_FMT_RGB565:
+                               *f++ = (0x1F & rv) |
+                                       (0xE0 & (gv << 5));
+                               *f++ = (0x07 & (gv >> 3)) |
+                                       (0xF8 &  bv);
+                               break;
+                       case V4L2_PIX_FMT_RGB24:
+                               *f++ = rv;
+                               *f++ = gv;
+                               *f++ = bv;
+                               break;
+                       case V4L2_PIX_FMT_RGB32:
+                               *f++ = rv;
+                               *f++ = gv;
+                               *f++ = bv;
+                               f++;
+                               break;
+                       case V4L2_PIX_FMT_RGB555:
+                               *f++ = (0x1F & rv) |
+                                       (0xE0 & (gv << 5));
+                               *f++ = (0x03 & (gv >> 3)) |
+                                       (0x7C & (bv << 2));
+                               break;
+                       }
+               }
+               clipmask_index += clipmask_add;
+               f += stretch_bytes;
+       }
+
+       frame->curline += usbvision->stretch_height;
+       *pcopylen += frame->v4l2_linesize * usbvision->stretch_height;
+
+       if (frame->curline >= frame->frmheight)
+               return parse_state_next_frame;
+       return parse_state_continue;
+}
+
+/* The decompression routine  */
+static int usbvision_decompress(struct usb_usbvision *usbvision, unsigned char *compressed,
+                                                               unsigned char *decompressed, int *start_pos,
+                                                               int *block_typestart_pos, int len)
+{
+       int rest_pixel, idx, pos, extra_pos, block_len, block_type_pos, block_type_len;
+       unsigned char block_byte, block_code, block_type, block_type_byte, integrator;
+
+       integrator = 0;
+       pos = *start_pos;
+       block_type_pos = *block_typestart_pos;
+       extra_pos = pos;
+       block_len = 0;
+       block_byte = 0;
+       block_code = 0;
+       block_type = 0;
+       block_type_byte = 0;
+       block_type_len = 0;
+       rest_pixel = len;
+
+       for (idx = 0; idx < len; idx++) {
+               if (block_len == 0) {
+                       if (block_type_len == 0) {
+                               block_type_byte = compressed[block_type_pos];
+                               block_type_pos++;
+                               block_type_len = 4;
+                       }
+                       block_type = (block_type_byte & 0xC0) >> 6;
+
+                       /* statistic: */
+                       usbvision->compr_block_types[block_type]++;
+
+                       pos = extra_pos;
+                       if (block_type == 0) {
+                               if (rest_pixel >= 24) {
+                                       idx += 23;
+                                       rest_pixel -= 24;
+                                       integrator = decompressed[idx];
+                               } else {
+                                       idx += rest_pixel - 1;
+                                       rest_pixel = 0;
+                               }
+                       } else {
+                               block_code = compressed[pos];
+                               pos++;
+                               if (rest_pixel >= 24)
+                                       block_len  = 24;
+                               else
+                                       block_len = rest_pixel;
+                               rest_pixel -= block_len;
+                               extra_pos = pos + (block_len / 4);
+                       }
+                       block_type_byte <<= 2;
+                       block_type_len -= 1;
+               }
+               if (block_len > 0) {
+                       if ((block_len % 4) == 0) {
+                               block_byte = compressed[pos];
+                               pos++;
+                       }
+                       if (block_type == 1) /* inter Block */
+                               integrator = decompressed[idx];
+                       switch (block_byte & 0xC0) {
+                       case 0x03 << 6:
+                               integrator += compressed[extra_pos];
+                               extra_pos++;
+                               break;
+                       case 0x02 << 6:
+                               integrator += block_code;
+                               break;
+                       case 0x00:
+                               integrator -= block_code;
+                               break;
+                       }
+                       decompressed[idx] = integrator;
+                       block_byte <<= 2;
+                       block_len -= 1;
+               }
+       }
+       *start_pos = extra_pos;
+       *block_typestart_pos = block_type_pos;
+       return idx;
+}
+
+
+/*
+ * usbvision_parse_compress()
+ *
+ * Parse compressed frame from the scratch buffer, put
+ * decoded RGB value into the current frame buffer and add the written
+ * number of bytes (RGB) to the *pcopylen.
+ *
+ */
+static enum parse_state usbvision_parse_compress(struct usb_usbvision *usbvision,
+                                          long *pcopylen)
+{
+#define USBVISION_STRIP_MAGIC          0x5A
+#define USBVISION_STRIP_LEN_MAX                400
+#define USBVISION_STRIP_HEADER_LEN     3
+
+       struct usbvision_frame *frame;
+       unsigned char *f, *u = NULL, *v = NULL;
+       unsigned char strip_data[USBVISION_STRIP_LEN_MAX];
+       unsigned char strip_header[USBVISION_STRIP_HEADER_LEN];
+       int idx, idx_end, strip_len, strip_ptr, startblock_pos, block_pos, block_type_pos;
+       int clipmask_index;
+       int image_size;
+       unsigned char rv, gv, bv;
+       static unsigned char *Y, *U, *V;
+
+       frame = usbvision->cur_frame;
+       image_size = frame->frmwidth * frame->frmheight;
+       if ((frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) ||
+           (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420)) {       /* this is a planar format */
+               /* ... v4l2_linesize not used here. */
+               f = frame->data + (frame->width * frame->curline);
+       } else
+               f = frame->data + (frame->v4l2_linesize * frame->curline);
+
+       if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { /* initialise u and v pointers */
+               /* get base of u and b planes add halfoffset */
+               u = frame->data
+                       + image_size
+                       + (frame->frmwidth >> 1) * frame->curline;
+               v = u + (image_size >> 1);
+       } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) {
+               v = frame->data + image_size + ((frame->curline * (frame->width)) >> 2);
+               u = v + (image_size >> 2);
+       }
+
+       if (frame->curline == 0)
+               usbvision_adjust_compression(usbvision);
+
+       if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN)
+               return parse_state_out;
+
+       /* get strip header without changing the scratch_read_ptr */
+       scratch_set_extra_ptr(usbvision, &strip_ptr, 0);
+       scratch_get_extra(usbvision, &strip_header[0], &strip_ptr,
+                               USBVISION_STRIP_HEADER_LEN);
+
+       if (strip_header[0] != USBVISION_STRIP_MAGIC) {
+               /* wrong strip magic */
+               usbvision->strip_magic_errors++;
+               return parse_state_next_frame;
+       }
+
+       if (frame->curline != (int)strip_header[2]) {
+               /* line number mismatch error */
+               usbvision->strip_line_number_errors++;
+       }
+
+       strip_len = 2 * (unsigned int)strip_header[1];
+       if (strip_len > USBVISION_STRIP_LEN_MAX) {
+               /* strip overrun */
+               /* I think this never happens */
+               usbvision_request_intra(usbvision);
+       }
+
+       if (scratch_len(usbvision) < strip_len) {
+               /* there is not enough data for the strip */
+               return parse_state_out;
+       }
+
+       if (usbvision->intra_frame_buffer) {
+               Y = usbvision->intra_frame_buffer + frame->frmwidth * frame->curline;
+               U = usbvision->intra_frame_buffer + image_size + (frame->frmwidth / 2) * (frame->curline / 2);
+               V = usbvision->intra_frame_buffer + image_size / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2);
+       } else {
+               return parse_state_next_frame;
+       }
+
+       clipmask_index = frame->curline * MAX_FRAME_WIDTH;
+
+       scratch_get(usbvision, strip_data, strip_len);
+
+       idx_end = frame->frmwidth;
+       block_type_pos = USBVISION_STRIP_HEADER_LEN;
+       startblock_pos = block_type_pos + (idx_end - 1) / 96 + (idx_end / 2 - 1) / 96 + 2;
+       block_pos = startblock_pos;
+
+       usbvision->block_pos = block_pos;
+
+       usbvision_decompress(usbvision, strip_data, Y, &block_pos, &block_type_pos, idx_end);
+       if (strip_len > usbvision->max_strip_len)
+               usbvision->max_strip_len = strip_len;
+
+       if (frame->curline % 2)
+               usbvision_decompress(usbvision, strip_data, V, &block_pos, &block_type_pos, idx_end / 2);
+       else
+               usbvision_decompress(usbvision, strip_data, U, &block_pos, &block_type_pos, idx_end / 2);
+
+       if (block_pos > usbvision->comprblock_pos)
+               usbvision->comprblock_pos = block_pos;
+       if (block_pos > strip_len)
+               usbvision->strip_len_errors++;
+
+       for (idx = 0; idx < idx_end; idx++) {
+               if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+                       *f++ = Y[idx];
+                       *f++ = idx & 0x01 ? U[idx / 2] : V[idx / 2];
+               } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) {
+                       *f++ = Y[idx];
+                       if (idx & 0x01)
+                               *u++ = U[idx >> 1];
+                       else
+                               *v++ = V[idx >> 1];
+               } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) {
+                       *f++ = Y[idx];
+                       if (!((idx & 0x01) | (frame->curline & 0x01))) {
+                               /* only need do this for 1 in 4 pixels */
+                               /* intraframe buffer is YUV420 format */
+                               *u++ = U[idx >> 1];
+                               *v++ = V[idx >> 1];
+                       }
+               } else {
+                       YUV_TO_RGB_BY_THE_BOOK(Y[idx], U[idx / 2], V[idx / 2], rv, gv, bv);
+                       switch (frame->v4l2_format.format) {
+                       case V4L2_PIX_FMT_GREY:
+                               *f++ = Y[idx];
+                               break;
+                       case V4L2_PIX_FMT_RGB555:
+                               *f++ = (0x1F & rv) |
+                                       (0xE0 & (gv << 5));
+                               *f++ = (0x03 & (gv >> 3)) |
+                                       (0x7C & (bv << 2));
+                               break;
+                       case V4L2_PIX_FMT_RGB565:
+                               *f++ = (0x1F & rv) |
+                                       (0xE0 & (gv << 5));
+                               *f++ = (0x07 & (gv >> 3)) |
+                                       (0xF8 & bv);
+                               break;
+                       case V4L2_PIX_FMT_RGB24:
+                               *f++ = rv;
+                               *f++ = gv;
+                               *f++ = bv;
+                               break;
+                       case V4L2_PIX_FMT_RGB32:
+                               *f++ = rv;
+                               *f++ = gv;
+                               *f++ = bv;
+                               f++;
+                               break;
+                       }
+               }
+               clipmask_index++;
+       }
+       /* Deal with non-integer no. of bytes for YUV420P */
+       if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420)
+               *pcopylen += frame->v4l2_linesize;
+       else
+               *pcopylen += frame->curline & 0x01 ? frame->v4l2_linesize : frame->v4l2_linesize << 1;
+
+       frame->curline += 1;
+
+       if (frame->curline >= frame->frmheight)
+               return parse_state_next_frame;
+       return parse_state_continue;
+
+}
+
+
+/*
+ * usbvision_parse_lines_420()
+ *
+ * Parse two lines from the scratch buffer, put
+ * decoded RGB value into the current frame buffer and add the written
+ * number of bytes (RGB) to the *pcopylen.
+ *
+ */
+static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvision,
+                                          long *pcopylen)
+{
+       struct usbvision_frame *frame;
+       unsigned char *f_even = NULL, *f_odd = NULL;
+       unsigned int pixel_per_line, block;
+       int pixel, block_split;
+       int y_ptr, u_ptr, v_ptr, y_odd_offset;
+       const int y_block_size = 128;
+       const int uv_block_size = 64;
+       const int sub_block_size = 32;
+       const int y_step[] = { 0, 0, 0, 2 }, y_step_size = 4;
+       const int uv_step[] = { 0, 0, 0, 4 }, uv_step_size = 4;
+       unsigned char y[2], u, v;       /* YUV components */
+       int y_, u_, v_, vb, uvg, ur;
+       int r_, g_, b_;                 /* RGB components */
+       unsigned char g;
+       int clipmask_even_index, clipmask_odd_index, bytes_per_pixel;
+       int clipmask_add, stretch_bytes;
+
+       frame  = usbvision->cur_frame;
+       f_even = frame->data + (frame->v4l2_linesize * frame->curline);
+       f_odd  = f_even + frame->v4l2_linesize * usbvision->stretch_height;
+
+       /* Make sure there's enough data for the entire line */
+       /* In this mode usbvision transfer 3 bytes for every 2 pixels */
+       /* I need two lines to decode the color */
+       bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
+       stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel;
+       clipmask_even_index = frame->curline * MAX_FRAME_WIDTH;
+       clipmask_odd_index  = clipmask_even_index + MAX_FRAME_WIDTH;
+       clipmask_add = usbvision->stretch_width;
+       pixel_per_line = frame->isoc_header.frame_width;
+
+       if (scratch_len(usbvision) < (int)pixel_per_line * 3) {
+               /* printk(KERN_DEBUG "out of data, need %d\n", len); */
+               return parse_state_out;
+       }
+
+       if ((frame->curline + 1) >= frame->frmheight)
+               return parse_state_next_frame;
+
+       block_split = (pixel_per_line%y_block_size) ? 1 : 0;    /* are some blocks splitted into different lines? */
+
+       y_odd_offset = (pixel_per_line / y_block_size) * (y_block_size + uv_block_size)
+                       + block_split * uv_block_size;
+
+       scratch_set_extra_ptr(usbvision, &y_ptr, y_odd_offset);
+       scratch_set_extra_ptr(usbvision, &u_ptr, y_block_size);
+       scratch_set_extra_ptr(usbvision, &v_ptr, y_odd_offset
+                       + (4 - block_split) * sub_block_size);
+
+       for (block = 0; block < (pixel_per_line / sub_block_size); block++) {
+               for (pixel = 0; pixel < sub_block_size; pixel += 2) {
+                       scratch_get(usbvision, &y[0], 2);
+                       scratch_get_extra(usbvision, &u, &u_ptr, 1);
+                       scratch_get_extra(usbvision, &v, &v_ptr, 1);
+
+                       /* I don't use the YUV_TO_RGB macro for better performance */
+                       v_ = v - 128;
+                       u_ = u - 128;
+                       vb = 132252 * v_;
+                       uvg = -53281 * u_ - 25625 * v_;
+                       ur = 104595 * u_;
+
+                       if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+                               *f_even++ = y[0];
+                               *f_even++ = v;
+                       } else {
+                               y_ = 76284 * (y[0] - 16);
+
+                               b_ = (y_ + vb) >> 16;
+                               g_ = (y_ + uvg) >> 16;
+                               r_ = (y_ + ur) >> 16;
+
+                               switch (frame->v4l2_format.format) {
+                               case V4L2_PIX_FMT_RGB565:
+                                       g = LIMIT_RGB(g_);
+                                       *f_even++ =
+                                               (0x1F & LIMIT_RGB(r_)) |
+                                               (0xE0 & (g << 5));
+                                       *f_even++ =
+                                               (0x07 & (g >> 3)) |
+                                               (0xF8 &  LIMIT_RGB(b_));
+                                       break;
+                               case V4L2_PIX_FMT_RGB24:
+                                       *f_even++ = LIMIT_RGB(r_);
+                                       *f_even++ = LIMIT_RGB(g_);
+                                       *f_even++ = LIMIT_RGB(b_);
+                                       break;
+                               case V4L2_PIX_FMT_RGB32:
+                                       *f_even++ = LIMIT_RGB(r_);
+                                       *f_even++ = LIMIT_RGB(g_);
+                                       *f_even++ = LIMIT_RGB(b_);
+                                       f_even++;
+                                       break;
+                               case V4L2_PIX_FMT_RGB555:
+                                       g = LIMIT_RGB(g_);
+                                       *f_even++ = (0x1F & LIMIT_RGB(r_)) |
+                                               (0xE0 & (g << 5));
+                                       *f_even++ = (0x03 & (g >> 3)) |
+                                               (0x7C & (LIMIT_RGB(b_) << 2));
+                                       break;
+                               }
+                       }
+                       clipmask_even_index += clipmask_add;
+                       f_even += stretch_bytes;
+
+                       if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+                               *f_even++ = y[1];
+                               *f_even++ = u;
+                       } else {
+                               y_ = 76284 * (y[1] - 16);
+
+                               b_ = (y_ + vb) >> 16;
+                               g_ = (y_ + uvg) >> 16;
+                               r_ = (y_ + ur) >> 16;
+
+                               switch (frame->v4l2_format.format) {
+                               case V4L2_PIX_FMT_RGB565:
+                                       g = LIMIT_RGB(g_);
+                                       *f_even++ =
+                                               (0x1F & LIMIT_RGB(r_)) |
+                                               (0xE0 & (g << 5));
+                                       *f_even++ =
+                                               (0x07 & (g >> 3)) |
+                                               (0xF8 &  LIMIT_RGB(b_));
+                                       break;
+                               case V4L2_PIX_FMT_RGB24:
+                                       *f_even++ = LIMIT_RGB(r_);
+                                       *f_even++ = LIMIT_RGB(g_);
+                                       *f_even++ = LIMIT_RGB(b_);
+                                       break;
+                               case V4L2_PIX_FMT_RGB32:
+                                       *f_even++ = LIMIT_RGB(r_);
+                                       *f_even++ = LIMIT_RGB(g_);
+                                       *f_even++ = LIMIT_RGB(b_);
+                                       f_even++;
+                                       break;
+                               case V4L2_PIX_FMT_RGB555:
+                                       g = LIMIT_RGB(g_);
+                                       *f_even++ = (0x1F & LIMIT_RGB(r_)) |
+                                               (0xE0 & (g << 5));
+                                       *f_even++ = (0x03 & (g >> 3)) |
+                                               (0x7C & (LIMIT_RGB(b_) << 2));
+                                       break;
+                               }
+                       }
+                       clipmask_even_index += clipmask_add;
+                       f_even += stretch_bytes;
+
+                       scratch_get_extra(usbvision, &y[0], &y_ptr, 2);
+
+                       if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+                               *f_odd++ = y[0];
+                               *f_odd++ = v;
+                       } else {
+                               y_ = 76284 * (y[0] - 16);
+
+                               b_ = (y_ + vb) >> 16;
+                               g_ = (y_ + uvg) >> 16;
+                               r_ = (y_ + ur) >> 16;
+
+                               switch (frame->v4l2_format.format) {
+                               case V4L2_PIX_FMT_RGB565:
+                                       g = LIMIT_RGB(g_);
+                                       *f_odd++ =
+                                               (0x1F & LIMIT_RGB(r_)) |
+                                               (0xE0 & (g << 5));
+                                       *f_odd++ =
+                                               (0x07 & (g >> 3)) |
+                                               (0xF8 &  LIMIT_RGB(b_));
+                                       break;
+                               case V4L2_PIX_FMT_RGB24:
+                                       *f_odd++ = LIMIT_RGB(r_);
+                                       *f_odd++ = LIMIT_RGB(g_);
+                                       *f_odd++ = LIMIT_RGB(b_);
+                                       break;
+                               case V4L2_PIX_FMT_RGB32:
+                                       *f_odd++ = LIMIT_RGB(r_);
+                                       *f_odd++ = LIMIT_RGB(g_);
+                                       *f_odd++ = LIMIT_RGB(b_);
+                                       f_odd++;
+                                       break;
+                               case V4L2_PIX_FMT_RGB555:
+                                       g = LIMIT_RGB(g_);
+                                       *f_odd++ = (0x1F & LIMIT_RGB(r_)) |
+                                               (0xE0 & (g << 5));
+                                       *f_odd++ = (0x03 & (g >> 3)) |
+                                               (0x7C & (LIMIT_RGB(b_) << 2));
+                                       break;
+                               }
+                       }
+                       clipmask_odd_index += clipmask_add;
+                       f_odd += stretch_bytes;
+
+                       if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
+                               *f_odd++ = y[1];
+                               *f_odd++ = u;
+                       } else {
+                               y_ = 76284 * (y[1] - 16);
+
+                               b_ = (y_ + vb) >> 16;
+                               g_ = (y_ + uvg) >> 16;
+                               r_ = (y_ + ur) >> 16;
+
+                               switch (frame->v4l2_format.format) {
+                               case V4L2_PIX_FMT_RGB565:
+                                       g = LIMIT_RGB(g_);
+                                       *f_odd++ =
+                                               (0x1F & LIMIT_RGB(r_)) |
+                                               (0xE0 & (g << 5));
+                                       *f_odd++ =
+                                               (0x07 & (g >> 3)) |
+                                               (0xF8 &  LIMIT_RGB(b_));
+                                       break;
+                               case V4L2_PIX_FMT_RGB24:
+                                       *f_odd++ = LIMIT_RGB(r_);
+                                       *f_odd++ = LIMIT_RGB(g_);
+                                       *f_odd++ = LIMIT_RGB(b_);
+                                       break;
+                               case V4L2_PIX_FMT_RGB32:
+                                       *f_odd++ = LIMIT_RGB(r_);
+                                       *f_odd++ = LIMIT_RGB(g_);
+                                       *f_odd++ = LIMIT_RGB(b_);
+                                       f_odd++;
+                                       break;
+                               case V4L2_PIX_FMT_RGB555:
+                                       g = LIMIT_RGB(g_);
+                                       *f_odd++ = (0x1F & LIMIT_RGB(r_)) |
+                                               (0xE0 & (g << 5));
+                                       *f_odd++ = (0x03 & (g >> 3)) |
+                                               (0x7C & (LIMIT_RGB(b_) << 2));
+                                       break;
+                               }
+                       }
+                       clipmask_odd_index += clipmask_add;
+                       f_odd += stretch_bytes;
+               }
+
+               scratch_rm_old(usbvision, y_step[block % y_step_size] * sub_block_size);
+               scratch_inc_extra_ptr(&y_ptr, y_step[(block + 2 * block_split) % y_step_size]
+                               * sub_block_size);
+               scratch_inc_extra_ptr(&u_ptr, uv_step[block % uv_step_size]
+                               * sub_block_size);
+               scratch_inc_extra_ptr(&v_ptr, uv_step[(block + 2 * block_split) % uv_step_size]
+                               * sub_block_size);
+       }
+
+       scratch_rm_old(usbvision, pixel_per_line * 3 / 2
+                       + block_split * sub_block_size);
+
+       frame->curline += 2 * usbvision->stretch_height;
+       *pcopylen += frame->v4l2_linesize * 2 * usbvision->stretch_height;
+
+       if (frame->curline >= frame->frmheight)
+               return parse_state_next_frame;
+       return parse_state_continue;
+}
+
+/*
+ * usbvision_parse_data()
+ *
+ * Generic routine to parse the scratch buffer. It employs either
+ * usbvision_find_header() or usbvision_parse_lines() to do most
+ * of work.
+ *
+ */
+static void usbvision_parse_data(struct usb_usbvision *usbvision)
+{
+       struct usbvision_frame *frame;
+       enum parse_state newstate;
+       long copylen = 0;
+       unsigned long lock_flags;
+
+       frame = usbvision->cur_frame;
+
+       PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision));
+
+       while (1) {
+               newstate = parse_state_out;
+               if (scratch_len(usbvision)) {
+                       if (frame->scanstate == scan_state_scanning) {
+                               newstate = usbvision_find_header(usbvision);
+                       } else if (frame->scanstate == scan_state_lines) {
+                               if (usbvision->isoc_mode == ISOC_MODE_YUV420)
+                                       newstate = usbvision_parse_lines_420(usbvision, &copylen);
+                               else if (usbvision->isoc_mode == ISOC_MODE_YUV422)
+                                       newstate = usbvision_parse_lines_422(usbvision, &copylen);
+                               else if (usbvision->isoc_mode == ISOC_MODE_COMPRESS)
+                                       newstate = usbvision_parse_compress(usbvision, &copylen);
+                       }
+               }
+               if (newstate == parse_state_continue)
+                       continue;
+               if ((newstate == parse_state_next_frame) || (newstate == parse_state_out))
+                       break;
+               return; /* parse_state_end_parse */
+       }
+
+       if (newstate == parse_state_next_frame) {
+               frame->grabstate = frame_state_done;
+               do_gettimeofday(&(frame->timestamp));
+               frame->sequence = usbvision->frame_num;
+
+               spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+               list_move_tail(&(frame->frame), &usbvision->outqueue);
+               usbvision->cur_frame = NULL;
+               spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+               usbvision->frame_num++;
+
+               /* This will cause the process to request another frame. */
+               if (waitqueue_active(&usbvision->wait_frame)) {
+                       PDEBUG(DBG_PARSE, "Wake up !");
+                       wake_up_interruptible(&usbvision->wait_frame);
+               }
+       } else {
+               frame->grabstate = frame_state_grabbing;
+       }
+
+       /* Update the frame's uncompressed length. */
+       frame->scanlength += copylen;
+}
+
+
+/*
+ * Make all of the blocks of data contiguous
+ */
+static int usbvision_compress_isochronous(struct usb_usbvision *usbvision,
+                                         struct urb *urb)
+{
+       unsigned char *packet_data;
+       int i, totlen = 0;
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               int packet_len = urb->iso_frame_desc[i].actual_length;
+               int packet_stat = urb->iso_frame_desc[i].status;
+
+               packet_data = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+
+               /* Detect and ignore errored packets */
+               if (packet_stat) {      /* packet_stat != 0 ????????????? */
+                       PDEBUG(DBG_ISOC, "data error: [%d] len=%d, status=%X", i, packet_len, packet_stat);
+                       usbvision->isoc_err_count++;
+                       continue;
+               }
+
+               /* Detect and ignore empty packets */
+               if (packet_len < 0) {
+                       PDEBUG(DBG_ISOC, "error packet [%d]", i);
+                       usbvision->isoc_skip_count++;
+                       continue;
+               } else if (packet_len == 0) {   /* Frame end ????? */
+                       PDEBUG(DBG_ISOC, "null packet [%d]", i);
+                       usbvision->isocstate = isoc_state_no_frame;
+                       usbvision->isoc_skip_count++;
+                       continue;
+               } else if (packet_len > usbvision->isoc_packet_size) {
+                       PDEBUG(DBG_ISOC, "packet[%d] > isoc_packet_size", i);
+                       usbvision->isoc_skip_count++;
+                       continue;
+               }
+
+               PDEBUG(DBG_ISOC, "packet ok [%d] len=%d", i, packet_len);
+
+               if (usbvision->isocstate == isoc_state_no_frame) { /* new frame begins */
+                       usbvision->isocstate = isoc_state_in_frame;
+                       scratch_mark_header(usbvision);
+                       usbvision_measure_bandwidth(usbvision);
+                       PDEBUG(DBG_ISOC, "packet with header");
+               }
+
+               /*
+                * If usbvision continues to feed us with data but there is no
+                * consumption (if, for example, V4L client fell asleep) we
+                * may overflow the buffer. We have to move old data over to
+                * free room for new data. This is bad for old data. If we
+                * just drop new data then it's bad for new data... choose
+                * your favorite evil here.
+                */
+               if (scratch_free(usbvision) < packet_len) {
+                       usbvision->scratch_ovf_count++;
+                       PDEBUG(DBG_ISOC, "scratch buf overflow! scr_len: %d, n: %d",
+                              scratch_len(usbvision), packet_len);
+                       scratch_rm_old(usbvision, packet_len - scratch_free(usbvision));
+               }
+
+               /* Now we know that there is enough room in scratch buffer */
+               scratch_put(usbvision, packet_data, packet_len);
+               totlen += packet_len;
+               usbvision->isoc_data_count += packet_len;
+               usbvision->isoc_packet_count++;
+       }
+#if ENABLE_HEXDUMP
+       if (totlen > 0) {
+               static int foo;
+
+               if (foo < 1) {
+                       printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen);
+                       usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen);
+                       ++foo;
+               }
+       }
+#endif
+       return totlen;
+}
+
+static void usbvision_isoc_irq(struct urb *urb)
+{
+       int err_code = 0;
+       int len;
+       struct usb_usbvision *usbvision = urb->context;
+       int i;
+       unsigned long start_time = jiffies;
+       struct usbvision_frame **f;
+
+       /* We don't want to do anything if we are about to be removed! */
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return;
+
+       /* any urb with wrong status is ignored without acknowledgement */
+       if (urb->status == -ENOENT)
+               return;
+
+       f = &usbvision->cur_frame;
+
+       /* Manage streaming interruption */
+       if (usbvision->streaming == stream_interrupt) {
+               usbvision->streaming = stream_idle;
+               if ((*f)) {
+                       (*f)->grabstate = frame_state_ready;
+                       (*f)->scanstate = scan_state_scanning;
+               }
+               PDEBUG(DBG_IRQ, "stream interrupted");
+               wake_up_interruptible(&usbvision->wait_stream);
+       }
+
+       /* Copy the data received into our scratch buffer */
+       len = usbvision_compress_isochronous(usbvision, urb);
+
+       usbvision->isoc_urb_count++;
+       usbvision->urb_length = len;
+
+       if (usbvision->streaming == stream_on) {
+               /* If we collected enough data let's parse! */
+               if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH &&
+                   !list_empty(&(usbvision->inqueue))) {
+                       if (!(*f)) {
+                               (*f) = list_entry(usbvision->inqueue.next,
+                                                 struct usbvision_frame,
+                                                 frame);
+                       }
+                       usbvision_parse_data(usbvision);
+               } else {
+                       /* If we don't have a frame
+                         we're current working on, complain */
+                       PDEBUG(DBG_IRQ,
+                              "received data, but no one needs it");
+                       scratch_reset(usbvision);
+               }
+       } else {
+               PDEBUG(DBG_IRQ, "received data, but no one needs it");
+               scratch_reset(usbvision);
+       }
+
+       usbvision->time_in_irq += jiffies - start_time;
+
+       for (i = 0; i < USBVISION_URB_FRAMES; i++) {
+               urb->iso_frame_desc[i].status = 0;
+               urb->iso_frame_desc[i].actual_length = 0;
+       }
+
+       urb->status = 0;
+       urb->dev = usbvision->dev;
+       err_code = usb_submit_urb(urb, GFP_ATOMIC);
+
+       if (err_code) {
+               dev_err(&usbvision->dev->dev,
+                       "%s: usb_submit_urb failed: error %d\n",
+                               __func__, err_code);
+       }
+
+       return;
+}
+
+/*************************************/
+/* Low level usbvision access functions */
+/*************************************/
+
+/*
+ * usbvision_read_reg()
+ *
+ * return  < 0 -> Error
+ *        >= 0 -> Data
+ */
+
+int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg)
+{
+       int err_code = 0;
+       unsigned char buffer[1];
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return -1;
+
+       err_code = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1),
+                               USBVISION_OP_CODE,
+                               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
+                               0, (__u16) reg, buffer, 1, HZ);
+
+       if (err_code < 0) {
+               dev_err(&usbvision->dev->dev,
+                       "%s: failed: error %d\n", __func__, err_code);
+               return err_code;
+       }
+       return buffer[0];
+}
+
+/*
+ * usbvision_write_reg()
+ *
+ * return 1 -> Reg written
+ *        0 -> usbvision is not yet ready
+ *       -1 -> Something went wrong
+ */
+
+int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
+                           unsigned char value)
+{
+       int err_code = 0;
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return 0;
+
+       err_code = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+                               USBVISION_OP_CODE,
+                               USB_DIR_OUT | USB_TYPE_VENDOR |
+                               USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ);
+
+       if (err_code < 0) {
+               dev_err(&usbvision->dev->dev,
+                       "%s: failed: error %d\n", __func__, err_code);
+       }
+       return err_code;
+}
+
+
+static void usbvision_ctrl_urb_complete(struct urb *urb)
+{
+       struct usb_usbvision *usbvision = (struct usb_usbvision *)urb->context;
+
+       PDEBUG(DBG_IRQ, "");
+       usbvision->ctrl_urb_busy = 0;
+       if (waitqueue_active(&usbvision->ctrl_urb_wq))
+               wake_up_interruptible(&usbvision->ctrl_urb_wq);
+}
+
+
+static int usbvision_write_reg_irq(struct usb_usbvision *usbvision, int address,
+                               unsigned char *data, int len)
+{
+       int err_code = 0;
+
+       PDEBUG(DBG_IRQ, "");
+       if (len > 8)
+               return -EFAULT;
+       if (usbvision->ctrl_urb_busy)
+               return -EBUSY;
+       usbvision->ctrl_urb_busy = 1;
+
+       usbvision->ctrl_urb_setup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
+       usbvision->ctrl_urb_setup.bRequest     = USBVISION_OP_CODE;
+       usbvision->ctrl_urb_setup.wValue       = 0;
+       usbvision->ctrl_urb_setup.wIndex       = cpu_to_le16(address);
+       usbvision->ctrl_urb_setup.wLength      = cpu_to_le16(len);
+       usb_fill_control_urb(usbvision->ctrl_urb, usbvision->dev,
+                                                       usb_sndctrlpipe(usbvision->dev, 1),
+                                                       (unsigned char *)&usbvision->ctrl_urb_setup,
+                                                       (void *)usbvision->ctrl_urb_buffer, len,
+                                                       usbvision_ctrl_urb_complete,
+                                                       (void *)usbvision);
+
+       memcpy(usbvision->ctrl_urb_buffer, data, len);
+
+       err_code = usb_submit_urb(usbvision->ctrl_urb, GFP_ATOMIC);
+       if (err_code < 0) {
+               /* error in usb_submit_urb() */
+               usbvision->ctrl_urb_busy = 0;
+       }
+       PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, err_code);
+       return err_code;
+}
+
+
+static int usbvision_init_compression(struct usb_usbvision *usbvision)
+{
+       int err_code = 0;
+
+       usbvision->last_isoc_frame_num = -1;
+       usbvision->isoc_data_count = 0;
+       usbvision->isoc_packet_count = 0;
+       usbvision->isoc_skip_count = 0;
+       usbvision->compr_level = 50;
+       usbvision->last_compr_level = -1;
+       usbvision->isoc_urb_count = 0;
+       usbvision->request_intra = 1;
+       usbvision->isoc_measure_bandwidth_count = 0;
+
+       return err_code;
+}
+
+/* this function measures the used bandwidth since last call
+ * return:    0 : no error
+ * sets used_bandwidth to 1-100 : 1-100% of full bandwidth resp. to isoc_packet_size
+ */
+static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision)
+{
+       int err_code = 0;
+
+       if (usbvision->isoc_measure_bandwidth_count < 2) { /* this gives an average bandwidth of 3 frames */
+               usbvision->isoc_measure_bandwidth_count++;
+               return err_code;
+       }
+       if ((usbvision->isoc_packet_size > 0) && (usbvision->isoc_packet_count > 0)) {
+               usbvision->used_bandwidth = usbvision->isoc_data_count /
+                                       (usbvision->isoc_packet_count + usbvision->isoc_skip_count) *
+                                       100 / usbvision->isoc_packet_size;
+       }
+       usbvision->isoc_measure_bandwidth_count = 0;
+       usbvision->isoc_data_count = 0;
+       usbvision->isoc_packet_count = 0;
+       usbvision->isoc_skip_count = 0;
+       return err_code;
+}
+
+static int usbvision_adjust_compression(struct usb_usbvision *usbvision)
+{
+       int err_code = 0;
+       unsigned char buffer[6];
+
+       PDEBUG(DBG_IRQ, "");
+       if ((adjust_compression) && (usbvision->used_bandwidth > 0)) {
+               usbvision->compr_level += (usbvision->used_bandwidth - 90) / 2;
+               RESTRICT_TO_RANGE(usbvision->compr_level, 0, 100);
+               if (usbvision->compr_level != usbvision->last_compr_level) {
+                       int distortion;
+
+                       if (usbvision->bridge_type == BRIDGE_NT1004 || usbvision->bridge_type == BRIDGE_NT1005) {
+                               buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100);     /* PCM Threshold 1 */
+                               buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100);      /* PCM Threshold 2 */
+                               distortion = 7 + 248 * usbvision->compr_level / 100;
+                               buffer[2] = (unsigned char)(distortion & 0xFF);                         /* Average distortion Threshold (inter) */
+                               buffer[3] = (unsigned char)(distortion & 0xFF);                         /* Average distortion Threshold (intra) */
+                               distortion = 1 + 42 * usbvision->compr_level / 100;
+                               buffer[4] = (unsigned char)(distortion & 0xFF);                         /* Maximum distortion Threshold (inter) */
+                               buffer[5] = (unsigned char)(distortion & 0xFF);                         /* Maximum distortion Threshold (intra) */
+                       } else { /* BRIDGE_NT1003 */
+                               buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100);     /* PCM threshold 1 */
+                               buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100);      /* PCM threshold 2 */
+                               distortion = 2 + 253 * usbvision->compr_level / 100;
+                               buffer[2] = (unsigned char)(distortion & 0xFF);                         /* distortion threshold bit0-7 */
+                               buffer[3] = 0;  /* (unsigned char)((distortion >> 8) & 0x0F);           distortion threshold bit 8-11 */
+                               distortion = 0 + 43 * usbvision->compr_level / 100;
+                               buffer[4] = (unsigned char)(distortion & 0xFF);                         /* maximum distortion bit0-7 */
+                               buffer[5] = 0; /* (unsigned char)((distortion >> 8) & 0x01);            maximum distortion bit 8 */
+                       }
+                       err_code = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6);
+                       if (err_code == 0) {
+                               PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0],
+                                                               buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
+                               usbvision->last_compr_level = usbvision->compr_level;
+                       }
+               }
+       }
+       return err_code;
+}
+
+static int usbvision_request_intra(struct usb_usbvision *usbvision)
+{
+       int err_code = 0;
+       unsigned char buffer[1];
+
+       PDEBUG(DBG_IRQ, "");
+       usbvision->request_intra = 1;
+       buffer[0] = 1;
+       usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
+       return err_code;
+}
+
+static int usbvision_unrequest_intra(struct usb_usbvision *usbvision)
+{
+       int err_code = 0;
+       unsigned char buffer[1];
+
+       PDEBUG(DBG_IRQ, "");
+       usbvision->request_intra = 0;
+       buffer[0] = 0;
+       usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
+       return err_code;
+}
+
+/*******************************
+ * usbvision utility functions
+ *******************************/
+
+int usbvision_power_off(struct usb_usbvision *usbvision)
+{
+       int err_code = 0;
+
+       PDEBUG(DBG_FUNC, "");
+
+       err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN);
+       if (err_code == 1)
+               usbvision->power = 0;
+       PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code != 1) ? "ERROR" : "power is off", err_code);
+       return err_code;
+}
+
+/* configure webcam image sensor using the serial port */
+static int usbvision_init_webcam(struct usb_usbvision *usbvision)
+{
+       int rc;
+       int i;
+       static char init_values[38][3] = {
+               { 0x04, 0x12, 0x08 }, { 0x05, 0xff, 0xc8 }, { 0x06, 0x18, 0x07 }, { 0x07, 0x90, 0x00 },
+               { 0x09, 0x00, 0x00 }, { 0x0a, 0x00, 0x00 }, { 0x0b, 0x08, 0x00 }, { 0x0d, 0xcc, 0xcc },
+               { 0x0e, 0x13, 0x14 }, { 0x10, 0x9b, 0x83 }, { 0x11, 0x5a, 0x3f }, { 0x12, 0xe4, 0x73 },
+               { 0x13, 0x88, 0x84 }, { 0x14, 0x89, 0x80 }, { 0x15, 0x00, 0x20 }, { 0x16, 0x00, 0x00 },
+               { 0x17, 0xff, 0xa0 }, { 0x18, 0x6b, 0x20 }, { 0x19, 0x22, 0x40 }, { 0x1a, 0x10, 0x07 },
+               { 0x1b, 0x00, 0x47 }, { 0x1c, 0x03, 0xe0 }, { 0x1d, 0x00, 0x00 }, { 0x1e, 0x00, 0x00 },
+               { 0x1f, 0x00, 0x00 }, { 0x20, 0x00, 0x00 }, { 0x21, 0x00, 0x00 }, { 0x22, 0x00, 0x00 },
+               { 0x23, 0x00, 0x00 }, { 0x24, 0x00, 0x00 }, { 0x25, 0x00, 0x00 }, { 0x26, 0x00, 0x00 },
+               { 0x27, 0x00, 0x00 }, { 0x28, 0x00, 0x00 }, { 0x29, 0x00, 0x00 }, { 0x08, 0x80, 0x60 },
+               { 0x0f, 0x2d, 0x24 }, { 0x0c, 0x80, 0x80 }
+       };
+       char value[3];
+
+       /* the only difference between PAL and NTSC init_values */
+       if (usbvision_device_data[usbvision->dev_model].video_norm == V4L2_STD_NTSC)
+               init_values[4][1] = 0x34;
+
+       for (i = 0; i < sizeof(init_values) / 3; i++) {
+               usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT);
+               memcpy(value, init_values[i], 3);
+               rc = usb_control_msg(usbvision->dev,
+                                    usb_sndctrlpipe(usbvision->dev, 1),
+                                    USBVISION_OP_CODE,
+                                    USB_DIR_OUT | USB_TYPE_VENDOR |
+                                    USB_RECIP_ENDPOINT, 0,
+                                    (__u16) USBVISION_SER_DAT1, value,
+                                    3, HZ);
+               if (rc < 0)
+                       return rc;
+               usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SIO);
+               /* write 3 bytes to the serial port using SIO mode */
+               usbvision_write_reg(usbvision, USBVISION_SER_CONT, 3 | 0x10);
+               usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, 0);
+               usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT);
+               usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_IO_2);
+               usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_CLK_OUT);
+               usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_DAT_IO);
+               usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_CLK_OUT | USBVISION_DAT_IO);
+       }
+
+       return 0;
+}
+
+/*
+ * usbvision_set_video_format()
+ *
+ */
+static int usbvision_set_video_format(struct usb_usbvision *usbvision, int format)
+{
+       static const char proc[] = "usbvision_set_video_format";
+       int rc;
+       unsigned char value[2];
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return 0;
+
+       PDEBUG(DBG_FUNC, "isoc_mode %#02x", format);
+
+       if ((format != ISOC_MODE_YUV422)
+           && (format != ISOC_MODE_YUV420)
+           && (format != ISOC_MODE_COMPRESS)) {
+               printk(KERN_ERR "usbvision: unknown video format %02x, using default YUV420",
+                      format);
+               format = ISOC_MODE_YUV420;
+       }
+       value[0] = 0x0A;  /* TODO: See the effect of the filter */
+       value[1] = format; /* Sets the VO_MODE register which follows FILT_CONT */
+       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+                            USBVISION_OP_CODE,
+                            USB_DIR_OUT | USB_TYPE_VENDOR |
+                            USB_RECIP_ENDPOINT, 0,
+                            (__u16) USBVISION_FILT_CONT, value, 2, HZ);
+
+       if (rc < 0) {
+               printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - "
+                      "reconnect or reload driver.\n", proc, rc);
+       }
+       usbvision->isoc_mode = format;
+       return rc;
+}
+
+/*
+ * usbvision_set_output()
+ *
+ */
+
+int usbvision_set_output(struct usb_usbvision *usbvision, int width,
+                        int height)
+{
+       int err_code = 0;
+       int usb_width, usb_height;
+       unsigned int frame_rate = 0, frame_drop = 0;
+       unsigned char value[4];
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return 0;
+
+       if (width > MAX_USB_WIDTH) {
+               usb_width = width / 2;
+               usbvision->stretch_width = 2;
+       } else {
+               usb_width = width;
+               usbvision->stretch_width = 1;
+       }
+
+       if (height > MAX_USB_HEIGHT) {
+               usb_height = height / 2;
+               usbvision->stretch_height = 2;
+       } else {
+               usb_height = height;
+               usbvision->stretch_height = 1;
+       }
+
+       RESTRICT_TO_RANGE(usb_width, MIN_FRAME_WIDTH, MAX_USB_WIDTH);
+       usb_width &= ~(MIN_FRAME_WIDTH-1);
+       RESTRICT_TO_RANGE(usb_height, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT);
+       usb_height &= ~(1);
+
+       PDEBUG(DBG_FUNC, "usb %dx%d; screen %dx%d; stretch %dx%d",
+                                               usb_width, usb_height, width, height,
+                                               usbvision->stretch_width, usbvision->stretch_height);
+
+       /* I'll not rewrite the same values */
+       if ((usb_width != usbvision->curwidth) || (usb_height != usbvision->curheight)) {
+               value[0] = usb_width & 0xff;            /* LSB */
+               value[1] = (usb_width >> 8) & 0x03;     /* MSB */
+               value[2] = usb_height & 0xff;           /* LSB */
+               value[3] = (usb_height >> 8) & 0x03;    /* MSB */
+
+               err_code = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+                            USBVISION_OP_CODE,
+                            USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
+                                0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ);
+
+               if (err_code < 0) {
+                       dev_err(&usbvision->dev->dev,
+                               "%s failed: error %d\n", __func__, err_code);
+                       return err_code;
+               }
+               usbvision->curwidth = usbvision->stretch_width * usb_width;
+               usbvision->curheight = usbvision->stretch_height * usb_height;
+       }
+
+       if (usbvision->isoc_mode == ISOC_MODE_YUV422)
+               frame_rate = (usbvision->isoc_packet_size * 1000) / (usb_width * usb_height * 2);
+       else if (usbvision->isoc_mode == ISOC_MODE_YUV420)
+               frame_rate = (usbvision->isoc_packet_size * 1000) / ((usb_width * usb_height * 12) / 8);
+       else
+               frame_rate = FRAMERATE_MAX;
+
+       if (usbvision->tvnorm_id & V4L2_STD_625_50)
+               frame_drop = frame_rate * 32 / 25 - 1;
+       else if (usbvision->tvnorm_id & V4L2_STD_525_60)
+               frame_drop = frame_rate * 32 / 30 - 1;
+
+       RESTRICT_TO_RANGE(frame_drop, FRAMERATE_MIN, FRAMERATE_MAX);
+
+       PDEBUG(DBG_FUNC, "frame_rate %d fps, frame_drop %d", frame_rate, frame_drop);
+
+       frame_drop = FRAMERATE_MAX;     /* We can allow the maximum here, because dropping is controlled */
+
+       if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) {
+               if (usbvision_device_data[usbvision->dev_model].video_norm == V4L2_STD_PAL)
+                       frame_drop = 25;
+               else
+                       frame_drop = 30;
+       }
+
+       /* frame_drop = 7; => frame_phase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ...
+               => frame_skip = 4;
+               => frame_rate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25;
+
+          frame_drop = 9; => frame_phase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ...
+           => frame_skip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ...
+               => frame_rate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125;
+       */
+       err_code = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frame_drop);
+       return err_code;
+}
+
+
+/*
+ * usbvision_frames_alloc
+ * allocate the required frames
+ */
+int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames)
+{
+       int i;
+
+       /* needs to be page aligned cause the buffers can be mapped individually! */
+       usbvision->max_frame_size = PAGE_ALIGN(usbvision->curwidth *
+                                               usbvision->curheight *
+                                               usbvision->palette.bytes_per_pixel);
+
+       /* Try to do my best to allocate the frames the user want in the remaining memory */
+       usbvision->num_frames = number_of_frames;
+       while (usbvision->num_frames > 0) {
+               usbvision->fbuf_size = usbvision->num_frames * usbvision->max_frame_size;
+               usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size);
+               if (usbvision->fbuf)
+                       break;
+               usbvision->num_frames--;
+       }
+
+       spin_lock_init(&usbvision->queue_lock);
+       init_waitqueue_head(&usbvision->wait_frame);
+       init_waitqueue_head(&usbvision->wait_stream);
+
+       /* Allocate all buffers */
+       for (i = 0; i < usbvision->num_frames; i++) {
+               usbvision->frame[i].index = i;
+               usbvision->frame[i].grabstate = frame_state_unused;
+               usbvision->frame[i].data = usbvision->fbuf +
+                       i * usbvision->max_frame_size;
+               /*
+                * Set default sizes for read operation.
+                */
+               usbvision->stretch_width = 1;
+               usbvision->stretch_height = 1;
+               usbvision->frame[i].width = usbvision->curwidth;
+               usbvision->frame[i].height = usbvision->curheight;
+               usbvision->frame[i].bytes_read = 0;
+       }
+       PDEBUG(DBG_FUNC, "allocated %d frames (%d bytes per frame)",
+                       usbvision->num_frames, usbvision->max_frame_size);
+       return usbvision->num_frames;
+}
+
+/*
+ * usbvision_frames_free
+ * frees memory allocated for the frames
+ */
+void usbvision_frames_free(struct usb_usbvision *usbvision)
+{
+       /* Have to free all that memory */
+       PDEBUG(DBG_FUNC, "free %d frames", usbvision->num_frames);
+
+       if (usbvision->fbuf != NULL) {
+               usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size);
+               usbvision->fbuf = NULL;
+
+               usbvision->num_frames = 0;
+       }
+}
+/*
+ * usbvision_empty_framequeues()
+ * prepare queues for incoming and outgoing frames
+ */
+void usbvision_empty_framequeues(struct usb_usbvision *usbvision)
+{
+       u32 i;
+
+       INIT_LIST_HEAD(&(usbvision->inqueue));
+       INIT_LIST_HEAD(&(usbvision->outqueue));
+
+       for (i = 0; i < USBVISION_NUMFRAMES; i++) {
+               usbvision->frame[i].grabstate = frame_state_unused;
+               usbvision->frame[i].bytes_read = 0;
+       }
+}
+
+/*
+ * usbvision_stream_interrupt()
+ * stops streaming
+ */
+int usbvision_stream_interrupt(struct usb_usbvision *usbvision)
+{
+       int ret = 0;
+
+       /* stop reading from the device */
+
+       usbvision->streaming = stream_interrupt;
+       ret = wait_event_timeout(usbvision->wait_stream,
+                                (usbvision->streaming == stream_idle),
+                                msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES));
+       return ret;
+}
+
+/*
+ * usbvision_set_compress_params()
+ *
+ */
+
+static int usbvision_set_compress_params(struct usb_usbvision *usbvision)
+{
+       static const char proc[] = "usbvision_set_compresion_params: ";
+       int rc;
+       unsigned char value[6];
+
+       value[0] = 0x0F;    /* Intra-Compression cycle */
+       value[1] = 0x01;    /* Reg.45 one line per strip */
+       value[2] = 0x00;    /* Reg.46 Force intra mode on all new frames */
+       value[3] = 0x00;    /* Reg.47 FORCE_UP <- 0 normal operation (not force) */
+       value[4] = 0xA2;    /* Reg.48 BUF_THR I'm not sure if this does something in not compressed mode. */
+       value[5] = 0x00;    /* Reg.49 DVI_YUV This has nothing to do with compression */
+
+       /* catched values for NT1004 */
+       /* value[0] = 0xFF; Never apply intra mode automatically */
+       /* value[1] = 0xF1; Use full frame height for virtual strip width; One line per strip */
+       /* value[2] = 0x01; Force intra mode on all new frames */
+       /* value[3] = 0x00; Strip size 400 Bytes; do not force up */
+       /* value[4] = 0xA2; */
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return 0;
+
+       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+                            USBVISION_OP_CODE,
+                            USB_DIR_OUT | USB_TYPE_VENDOR |
+                            USB_RECIP_ENDPOINT, 0,
+                            (__u16) USBVISION_INTRA_CYC, value, 5, HZ);
+
+       if (rc < 0) {
+               printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
+                      "reconnect or reload driver.\n", proc, rc);
+               return rc;
+       }
+
+       if (usbvision->bridge_type == BRIDGE_NT1004) {
+               value[0] =  20; /* PCM Threshold 1 */
+               value[1] =  12; /* PCM Threshold 2 */
+               value[2] = 255; /* Distortion Threshold inter */
+               value[3] = 255; /* Distortion Threshold intra */
+               value[4] =  43; /* Max Distortion inter */
+               value[5] =  43; /* Max Distortion intra */
+       } else {
+               value[0] =  20; /* PCM Threshold 1 */
+               value[1] =  12; /* PCM Threshold 2 */
+               value[2] = 255; /* Distortion Threshold d7-d0 */
+               value[3] =   0; /* Distortion Threshold d11-d8 */
+               value[4] =  43; /* Max Distortion d7-d0 */
+               value[5] =   0; /* Max Distortion d8 */
+       }
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return 0;
+
+       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+                            USBVISION_OP_CODE,
+                            USB_DIR_OUT | USB_TYPE_VENDOR |
+                            USB_RECIP_ENDPOINT, 0,
+                            (__u16) USBVISION_PCM_THR1, value, 6, HZ);
+
+       if (rc < 0) {
+               printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
+                      "reconnect or reload driver.\n", proc, rc);
+       }
+       return rc;
+}
+
+
+/*
+ * usbvision_set_input()
+ *
+ * Set the input (saa711x, ...) size x y and other misc input params
+ * I've no idea if this parameters are right
+ *
+ */
+int usbvision_set_input(struct usb_usbvision *usbvision)
+{
+       static const char proc[] = "usbvision_set_input: ";
+       int rc;
+       unsigned char value[8];
+       unsigned char dvi_yuv_value;
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return 0;
+
+       /* Set input format expected from decoder*/
+       if (usbvision_device_data[usbvision->dev_model].vin_reg1_override) {
+               value[0] = usbvision_device_data[usbvision->dev_model].vin_reg1;
+       } else if (usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) {
+               /* SAA7113 uses 8 bit output */
+               value[0] = USBVISION_8_422_SYNC;
+       } else {
+               /* I'm sure only about d2-d0 [010] 16 bit 4:2:2 usin sync pulses
+                * as that is how saa7111 is configured */
+               value[0] = USBVISION_16_422_SYNC;
+               /* | USBVISION_VSNC_POL | USBVISION_VCLK_POL);*/
+       }
+
+       rc = usbvision_write_reg(usbvision, USBVISION_VIN_REG1, value[0]);
+       if (rc < 0) {
+               printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
+                      "reconnect or reload driver.\n", proc, rc);
+               return rc;
+       }
+
+
+       if (usbvision->tvnorm_id & V4L2_STD_PAL) {
+               value[0] = 0xC0;
+               value[1] = 0x02;        /* 0x02C0 -> 704 Input video line length */
+               value[2] = 0x20;
+               value[3] = 0x01;        /* 0x0120 -> 288 Input video n. of lines */
+               value[4] = 0x60;
+               value[5] = 0x00;        /* 0x0060 -> 96 Input video h offset */
+               value[6] = 0x16;
+               value[7] = 0x00;        /* 0x0016 -> 22 Input video v offset */
+       } else if (usbvision->tvnorm_id & V4L2_STD_SECAM) {
+               value[0] = 0xC0;
+               value[1] = 0x02;        /* 0x02C0 -> 704 Input video line length */
+               value[2] = 0x20;
+               value[3] = 0x01;        /* 0x0120 -> 288 Input video n. of lines */
+               value[4] = 0x01;
+               value[5] = 0x00;        /* 0x0001 -> 01 Input video h offset */
+               value[6] = 0x01;
+               value[7] = 0x00;        /* 0x0001 -> 01 Input video v offset */
+       } else {        /* V4L2_STD_NTSC */
+               value[0] = 0xD0;
+               value[1] = 0x02;        /* 0x02D0 -> 720 Input video line length */
+               value[2] = 0xF0;
+               value[3] = 0x00;        /* 0x00F0 -> 240 Input video number of lines */
+               value[4] = 0x50;
+               value[5] = 0x00;        /* 0x0050 -> 80 Input video h offset */
+               value[6] = 0x10;
+               value[7] = 0x00;        /* 0x0010 -> 16 Input video v offset */
+       }
+
+       /* webcam is only 480 pixels wide, both PAL and NTSC version */
+       if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) {
+               value[0] = 0xe0;
+               value[1] = 0x01;        /* 0x01E0 -> 480 Input video line length */
+       }
+
+       if (usbvision_device_data[usbvision->dev_model].x_offset >= 0) {
+               value[4] = usbvision_device_data[usbvision->dev_model].x_offset & 0xff;
+               value[5] = (usbvision_device_data[usbvision->dev_model].x_offset & 0x0300) >> 8;
+       }
+
+       if (adjust_x_offset != -1) {
+               value[4] = adjust_x_offset & 0xff;
+               value[5] = (adjust_x_offset & 0x0300) >> 8;
+       }
+
+       if (usbvision_device_data[usbvision->dev_model].y_offset >= 0) {
+               value[6] = usbvision_device_data[usbvision->dev_model].y_offset & 0xff;
+               value[7] = (usbvision_device_data[usbvision->dev_model].y_offset & 0x0300) >> 8;
+       }
+
+       if (adjust_y_offset != -1) {
+               value[6] = adjust_y_offset & 0xff;
+               value[7] = (adjust_y_offset & 0x0300) >> 8;
+       }
+
+       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+                            USBVISION_OP_CODE, /* USBVISION specific code */
+                            USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0,
+                            (__u16) USBVISION_LXSIZE_I, value, 8, HZ);
+       if (rc < 0) {
+               printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
+                      "reconnect or reload driver.\n", proc, rc);
+               return rc;
+       }
+
+
+       dvi_yuv_value = 0x00;   /* U comes after V, Ya comes after U/V, Yb comes after Yb */
+
+       if (usbvision_device_data[usbvision->dev_model].dvi_yuv_override) {
+               dvi_yuv_value = usbvision_device_data[usbvision->dev_model].dvi_yuv;
+       } else if (usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) {
+               /* This changes as the fine sync control changes. Further investigation necessary */
+               dvi_yuv_value = 0x06;
+       }
+
+       return usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value);
+}
+
+
+/*
+ * usbvision_set_dram_settings()
+ *
+ * Set the buffer address needed by the usbvision dram to operate
+ * This values has been taken with usbsnoop.
+ *
+ */
+
+static int usbvision_set_dram_settings(struct usb_usbvision *usbvision)
+{
+       int rc;
+       unsigned char value[8];
+
+       if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) {
+               value[0] = 0x42;
+               value[1] = 0x71;
+               value[2] = 0xff;
+               value[3] = 0x00;
+               value[4] = 0x98;
+               value[5] = 0xe0;
+               value[6] = 0x71;
+               value[7] = 0xff;
+               /* UR:  0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte) */
+               /* FDL: 0x00000-0x0E099 =  57498 Words */
+               /* VDW: 0x0E3FF-0x3FFFF */
+       } else {
+               value[0] = 0x42;
+               value[1] = 0x00;
+               value[2] = 0xff;
+               value[3] = 0x00;
+               value[4] = 0x00;
+               value[5] = 0x00;
+               value[6] = 0x00;
+               value[7] = 0xff;
+       }
+       /* These are the values of the address of the video buffer,
+        * they have to be loaded into the USBVISION_DRM_PRM1-8
+        *
+        * Start address of video output buffer for read:       drm_prm1-2 -> 0x00000
+        * End address of video output buffer for read:         drm_prm1-3 -> 0x1ffff
+        * Start address of video frame delay buffer:           drm_prm1-4 -> 0x20000
+        *    Only used in compressed mode
+        * End address of video frame delay buffer:             drm_prm1-5-6 -> 0x3ffff
+        *    Only used in compressed mode
+        * Start address of video output buffer for write:      drm_prm1-7 -> 0x00000
+        * End address of video output buffer for write:        drm_prm1-8 -> 0x1ffff
+        */
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return 0;
+
+       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
+                            USBVISION_OP_CODE, /* USBVISION specific code */
+                            USB_DIR_OUT | USB_TYPE_VENDOR |
+                            USB_RECIP_ENDPOINT, 0,
+                            (__u16) USBVISION_DRM_PRM1, value, 8, HZ);
+
+       if (rc < 0) {
+               dev_err(&usbvision->dev->dev, "%s: ERROR=%d\n", __func__, rc);
+               return rc;
+       }
+
+       /* Restart the video buffer logic */
+       rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR |
+                                  USBVISION_RES_FDL | USBVISION_RES_VDW);
+       if (rc < 0)
+               return rc;
+       rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, 0x00);
+
+       return rc;
+}
+
+/*
+ * ()
+ *
+ * Power on the device, enables suspend-resume logic
+ * &  reset the isoc End-Point
+ *
+ */
+
+int usbvision_power_on(struct usb_usbvision *usbvision)
+{
+       int err_code = 0;
+
+       PDEBUG(DBG_FUNC, "");
+
+       usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN);
+       usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+                       USBVISION_SSPND_EN | USBVISION_RES2);
+
+       if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) {
+               usbvision_write_reg(usbvision, USBVISION_VIN_REG1,
+                               USBVISION_16_422_SYNC | USBVISION_HVALID_PO);
+               usbvision_write_reg(usbvision, USBVISION_VIN_REG2,
+                               USBVISION_NOHVALID | USBVISION_KEEP_BLANK);
+       }
+       usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+                       USBVISION_SSPND_EN | USBVISION_PWR_VID);
+       mdelay(10);
+       err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+                       USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2);
+       if (err_code == 1)
+               usbvision->power = 1;
+       PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code < 0) ? "ERROR" : "power is on", err_code);
+       return err_code;
+}
+
+
+/*
+ * usbvision timer stuff
+ */
+
+/* to call usbvision_power_off from task queue */
+static void call_usbvision_power_off(struct work_struct *work)
+{
+       struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, power_off_work);
+
+       PDEBUG(DBG_FUNC, "");
+       if (mutex_lock_interruptible(&usbvision->v4l2_lock))
+               return;
+
+       if (usbvision->user == 0) {
+               usbvision_i2c_unregister(usbvision);
+
+               usbvision_power_off(usbvision);
+               usbvision->initialized = 0;
+       }
+       mutex_unlock(&usbvision->v4l2_lock);
+}
+
+static void usbvision_power_off_timer(unsigned long data)
+{
+       struct usb_usbvision *usbvision = (void *)data;
+
+       PDEBUG(DBG_FUNC, "");
+       del_timer(&usbvision->power_off_timer);
+       INIT_WORK(&usbvision->power_off_work, call_usbvision_power_off);
+       (void) schedule_work(&usbvision->power_off_work);
+}
+
+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;
+}
+
+void usbvision_set_power_off_timer(struct usb_usbvision *usbvision)
+{
+       mod_timer(&usbvision->power_off_timer, jiffies + USBVISION_POWEROFF_TIME);
+}
+
+void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision)
+{
+       if (timer_pending(&usbvision->power_off_timer))
+               del_timer(&usbvision->power_off_timer);
+}
+
+/*
+ * usbvision_begin_streaming()
+ * Sure you have to put bit 7 to 0, if not incoming frames are droped, but no
+ * idea about the rest
+ */
+int usbvision_begin_streaming(struct usb_usbvision *usbvision)
+{
+       if (usbvision->isoc_mode == ISOC_MODE_COMPRESS)
+               usbvision_init_compression(usbvision);
+       return usbvision_write_reg(usbvision, USBVISION_VIN_REG2,
+               USBVISION_NOHVALID | usbvision->vin_reg2_preset);
+}
+
+/*
+ * usbvision_restart_isoc()
+ * Not sure yet if touching here PWR_REG make loose the config
+ */
+
+int usbvision_restart_isoc(struct usb_usbvision *usbvision)
+{
+       int ret;
+
+       ret = usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+                             USBVISION_SSPND_EN | USBVISION_PWR_VID);
+       if (ret < 0)
+               return ret;
+       ret = usbvision_write_reg(usbvision, USBVISION_PWR_REG,
+                             USBVISION_SSPND_EN | USBVISION_PWR_VID |
+                             USBVISION_RES2);
+       if (ret < 0)
+               return ret;
+       ret = usbvision_write_reg(usbvision, USBVISION_VIN_REG2,
+                             USBVISION_KEEP_BLANK | USBVISION_NOHVALID |
+                                 usbvision->vin_reg2_preset);
+       if (ret < 0)
+               return ret;
+
+       /* TODO: schedule timeout */
+       while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) & 0x01) != 1)
+               ;
+
+       return 0;
+}
+
+int usbvision_audio_off(struct usb_usbvision *usbvision)
+{
+       if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_AUDIO_MUTE) < 0) {
+               printk(KERN_ERR "usbvision_audio_off: can't write reg\n");
+               return -1;
+       }
+       usbvision->audio_mute = 0;
+       usbvision->audio_channel = USBVISION_AUDIO_MUTE;
+       return 0;
+}
+
+int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel)
+{
+       if (!usbvision->audio_mute) {
+               if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, audio_channel) < 0) {
+                       printk(KERN_ERR "usbvision_set_audio: can't write iopin register for audio switching\n");
+                       return -1;
+               }
+       }
+       usbvision->audio_channel = audio_channel;
+       return 0;
+}
+
+int usbvision_setup(struct usb_usbvision *usbvision, int format)
+{
+       if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM)
+               usbvision_init_webcam(usbvision);
+       usbvision_set_video_format(usbvision, format);
+       usbvision_set_dram_settings(usbvision);
+       usbvision_set_compress_params(usbvision);
+       usbvision_set_input(usbvision);
+       usbvision_set_output(usbvision, MAX_USB_WIDTH, MAX_USB_HEIGHT);
+       usbvision_restart_isoc(usbvision);
+
+       /* cosas del PCM */
+       return USBVISION_IS_OPERATIONAL(usbvision);
+}
+
+int usbvision_set_alternate(struct usb_usbvision *dev)
+{
+       int err_code, prev_alt = dev->iface_alt;
+       int i;
+
+       dev->iface_alt = 0;
+       for (i = 0; i < dev->num_alt; i++)
+               if (dev->alt_max_pkt_size[i] > dev->alt_max_pkt_size[dev->iface_alt])
+                       dev->iface_alt = i;
+
+       if (dev->iface_alt != prev_alt) {
+               dev->isoc_packet_size = dev->alt_max_pkt_size[dev->iface_alt];
+               PDEBUG(DBG_FUNC, "setting alternate %d with max_packet_size=%u",
+                               dev->iface_alt, dev->isoc_packet_size);
+               err_code = usb_set_interface(dev->dev, dev->iface, dev->iface_alt);
+               if (err_code < 0) {
+                       dev_err(&dev->dev->dev,
+                               "cannot change alternate number to %d (error=%i)\n",
+                                       dev->iface_alt, err_code);
+                       return err_code;
+               }
+       }
+
+       PDEBUG(DBG_ISOC, "ISO Packet Length:%d", dev->isoc_packet_size);
+
+       return 0;
+}
+
+/*
+ * usbvision_init_isoc()
+ *
+ */
+int usbvision_init_isoc(struct usb_usbvision *usbvision)
+{
+       struct usb_device *dev = usbvision->dev;
+       int buf_idx, err_code, reg_value;
+       int sb_size;
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return -EFAULT;
+
+       usbvision->cur_frame = NULL;
+       scratch_reset(usbvision);
+
+       /* Alternate interface 1 is is the biggest frame size */
+       err_code = usbvision_set_alternate(usbvision);
+       if (err_code < 0) {
+               usbvision->last_error = err_code;
+               return -EBUSY;
+       }
+       sb_size = USBVISION_URB_FRAMES * usbvision->isoc_packet_size;
+
+       reg_value = (16 - usbvision_read_reg(usbvision,
+                                           USBVISION_ALTER_REG)) & 0x0F;
+
+       usbvision->usb_bandwidth = reg_value >> 1;
+       PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
+              usbvision->usb_bandwidth);
+
+
+
+       /* We double buffer the Iso lists */
+
+       for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) {
+               int j, k;
+               struct urb *urb;
+
+               urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
+               if (urb == NULL) {
+                       dev_err(&usbvision->dev->dev,
+                               "%s: usb_alloc_urb() failed\n", __func__);
+                       return -ENOMEM;
+               }
+               usbvision->sbuf[buf_idx].urb = urb;
+               usbvision->sbuf[buf_idx].data =
+                       usb_alloc_coherent(usbvision->dev,
+                                          sb_size,
+                                          GFP_KERNEL,
+                                          &urb->transfer_dma);
+               urb->dev = dev;
+               urb->context = usbvision;
+               urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp);
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+               urb->interval = 1;
+               urb->transfer_buffer = usbvision->sbuf[buf_idx].data;
+               urb->complete = usbvision_isoc_irq;
+               urb->number_of_packets = USBVISION_URB_FRAMES;
+               urb->transfer_buffer_length =
+                   usbvision->isoc_packet_size * USBVISION_URB_FRAMES;
+               for (j = k = 0; j < USBVISION_URB_FRAMES; j++,
+                    k += usbvision->isoc_packet_size) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length =
+                               usbvision->isoc_packet_size;
+               }
+       }
+
+       /* Submit all URBs */
+       for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) {
+                       err_code = usb_submit_urb(usbvision->sbuf[buf_idx].urb,
+                                                GFP_KERNEL);
+               if (err_code) {
+                       dev_err(&usbvision->dev->dev,
+                               "%s: usb_submit_urb(%d) failed: error %d\n",
+                                       __func__, buf_idx, err_code);
+               }
+       }
+
+       usbvision->streaming = stream_idle;
+       PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x",
+              __func__,
+              usbvision->video_endp);
+       return 0;
+}
+
+/*
+ * usbvision_stop_isoc()
+ *
+ * This procedure stops streaming and deallocates URBs. Then it
+ * activates zero-bandwidth alt. setting of the video interface.
+ *
+ */
+void usbvision_stop_isoc(struct usb_usbvision *usbvision)
+{
+       int buf_idx, err_code, reg_value;
+       int sb_size = USBVISION_URB_FRAMES * usbvision->isoc_packet_size;
+
+       if ((usbvision->streaming == stream_off) || (usbvision->dev == NULL))
+               return;
+
+       /* Unschedule all of the iso td's */
+       for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) {
+               usb_kill_urb(usbvision->sbuf[buf_idx].urb);
+               if (usbvision->sbuf[buf_idx].data) {
+                       usb_free_coherent(usbvision->dev,
+                                         sb_size,
+                                         usbvision->sbuf[buf_idx].data,
+                                         usbvision->sbuf[buf_idx].urb->transfer_dma);
+               }
+               usb_free_urb(usbvision->sbuf[buf_idx].urb);
+               usbvision->sbuf[buf_idx].urb = NULL;
+       }
+
+       PDEBUG(DBG_ISOC, "%s: streaming=stream_off\n", __func__);
+       usbvision->streaming = stream_off;
+
+       if (!usbvision->remove_pending) {
+               /* Set packet size to 0 */
+               usbvision->iface_alt = 0;
+               err_code = usb_set_interface(usbvision->dev, usbvision->iface,
+                                           usbvision->iface_alt);
+               if (err_code < 0) {
+                       dev_err(&usbvision->dev->dev,
+                               "%s: usb_set_interface() failed: error %d\n",
+                                       __func__, err_code);
+                       usbvision->last_error = err_code;
+               }
+               reg_value = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
+               usbvision->isoc_packet_size =
+                       (reg_value == 0) ? 0 : (reg_value * 64) - 1;
+               PDEBUG(DBG_ISOC, "ISO Packet Length:%d",
+                      usbvision->isoc_packet_size);
+
+               usbvision->usb_bandwidth = reg_value >> 1;
+               PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
+                      usbvision->usb_bandwidth);
+       }
+}
+
+int usbvision_muxsel(struct usb_usbvision *usbvision, int channel)
+{
+       /* inputs #0 and #3 are constant for every SAA711x. */
+       /* inputs #1 and #2 are variable for SAA7111 and SAA7113 */
+       int mode[4] = { SAA7115_COMPOSITE0, 0, 0, SAA7115_COMPOSITE3 };
+       int audio[] = { 1, 0, 0, 0 };
+       /* channel 0 is TV with audiochannel 1 (tuner mono) */
+       /* channel 1 is Composite with audio channel 0 (line in) */
+       /* channel 2 is S-Video with audio channel 0 (line in) */
+       /* channel 3 is additional video inputs to the device with audio channel 0 (line in) */
+
+       RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs);
+       usbvision->ctl_input = channel;
+
+       /* set the new channel */
+       /* Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video */
+       /* Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red */
+
+       switch (usbvision_device_data[usbvision->dev_model].codec) {
+       case CODEC_SAA7113:
+               mode[1] = SAA7115_COMPOSITE2;
+               if (switch_svideo_input) {
+                       /* To handle problems with S-Video Input for
+                        * some devices.  Use switch_svideo_input
+                        * parameter when loading the module.*/
+                       mode[2] = SAA7115_COMPOSITE1;
+               } else {
+                       mode[2] = SAA7115_SVIDEO1;
+               }
+               break;
+       case CODEC_SAA7111:
+       default:
+               /* modes for saa7111 */
+               mode[1] = SAA7115_COMPOSITE1;
+               mode[2] = SAA7115_SVIDEO1;
+               break;
+       }
+       call_all(usbvision, video, s_routing, mode[channel], 0, 0);
+       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
new file mode 100644 (file)
index 0000000..89fec02
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * usbvision_i2c.c
+ *  i2c algorithm for USB-I2C Bridges
+ *
+ * Copyright (c) 1999-2007 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ *                         Dwaine Garden <dwainegarden@rogers.com>
+ *
+ * This module is part of usbvision driver project.
+ * Updates to driver completed by Dwaine P. Garden
+ *
+ * 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/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include "usbvision.h"
+
+#define DBG_I2C                (1 << 0)
+
+static int i2c_debug;
+
+module_param(i2c_debug, int, 0644);                    /* debug_i2c_usb mode of the device driver */
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+#define PDEBUG(level, fmt, args...) { \
+               if (i2c_debug & (level)) \
+                       printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \
+                               __func__, __LINE__ , ## args); \
+       }
+
+static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
+                           short len);
+static int usbvision_i2c_read(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
+                          short len);
+
+static inline int try_write_address(struct i2c_adapter *i2c_adap,
+                                   unsigned char addr, int retries)
+{
+       struct usb_usbvision *usbvision;
+       int i, ret = -1;
+       char buf[4];
+
+       usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap);
+       buf[0] = 0x00;
+       for (i = 0; i <= retries; i++) {
+               ret = (usbvision_i2c_write(usbvision, addr, buf, 1));
+               if (ret == 1)
+                       break;  /* success! */
+               udelay(5);
+               if (i == retries)       /* no success */
+                       break;
+               udelay(10);
+       }
+       if (i) {
+               PDEBUG(DBG_I2C, "Needed %d retries for address %#2x", i, addr);
+               PDEBUG(DBG_I2C, "Maybe there's no device at this address");
+       }
+       return ret;
+}
+
+static inline int try_read_address(struct i2c_adapter *i2c_adap,
+                                  unsigned char addr, int retries)
+{
+       struct usb_usbvision *usbvision;
+       int i, ret = -1;
+       char buf[4];
+
+       usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap);
+       for (i = 0; i <= retries; i++) {
+               ret = (usbvision_i2c_read(usbvision, addr, buf, 1));
+               if (ret == 1)
+                       break;  /* success! */
+               udelay(5);
+               if (i == retries)       /* no success */
+                       break;
+               udelay(10);
+       }
+       if (i) {
+               PDEBUG(DBG_I2C, "Needed %d retries for address %#2x", i, addr);
+               PDEBUG(DBG_I2C, "Maybe there's no device at this address");
+       }
+       return ret;
+}
+
+static inline int usb_find_address(struct i2c_adapter *i2c_adap,
+                                  struct i2c_msg *msg, int retries,
+                                  unsigned char *add)
+{
+       unsigned short flags = msg->flags;
+
+       unsigned char addr;
+       int ret;
+
+       addr = (msg->addr << 1);
+       if (flags & I2C_M_RD)
+               addr |= 1;
+
+       add[0] = addr;
+       if (flags & I2C_M_RD)
+               ret = try_read_address(i2c_adap, addr, retries);
+       else
+               ret = try_write_address(i2c_adap, addr, retries);
+
+       if (ret != 1)
+               return -EREMOTEIO;
+
+       return 0;
+}
+
+static int
+usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+{
+       struct i2c_msg *pmsg;
+       struct usb_usbvision *usbvision;
+       int i, ret;
+       unsigned char addr = 0;
+
+       usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap);
+
+       for (i = 0; i < num; i++) {
+               pmsg = &msgs[i];
+               ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr);
+               if (ret != 0) {
+                       PDEBUG(DBG_I2C, "got NAK from device, message #%d", i);
+                       return (ret < 0) ? ret : -EREMOTEIO;
+               }
+
+               if (pmsg->flags & I2C_M_RD) {
+                       /* read bytes into buffer */
+                       ret = (usbvision_i2c_read(usbvision, addr, pmsg->buf, pmsg->len));
+                       if (ret < pmsg->len)
+                               return (ret < 0) ? ret : -EREMOTEIO;
+               } else {
+                       /* write bytes from buffer */
+                       ret = (usbvision_i2c_write(usbvision, addr, pmsg->buf, pmsg->len));
+                       if (ret < pmsg->len)
+                               return (ret < 0) ? ret : -EREMOTEIO;
+               }
+       }
+       return num;
+}
+
+static u32 functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+/* -----exported algorithm data: ------------------------------------- */
+
+static struct i2c_algorithm usbvision_algo = {
+       .master_xfer   = usbvision_i2c_xfer,
+       .smbus_xfer    = NULL,
+       .functionality = functionality,
+};
+
+
+/* ----------------------------------------------------------------------- */
+/* usbvision specific I2C functions                                        */
+/* ----------------------------------------------------------------------- */
+static struct i2c_adapter i2c_adap_template;
+
+int usbvision_i2c_register(struct usb_usbvision *usbvision)
+{
+       static unsigned short saa711x_addrs[] = {
+               0x4a >> 1, 0x48 >> 1,   /* SAA7111, SAA7111A and SAA7113 */
+               0x42 >> 1, 0x40 >> 1,   /* SAA7114, SAA7115 and SAA7118 */
+               I2C_CLIENT_END };
+
+       if (usbvision->registered_i2c)
+               return 0;
+
+       memcpy(&usbvision->i2c_adap, &i2c_adap_template,
+              sizeof(struct i2c_adapter));
+
+       sprintf(usbvision->i2c_adap.name, "%s-%d-%s", i2c_adap_template.name,
+               usbvision->dev->bus->busnum, usbvision->dev->devpath);
+       PDEBUG(DBG_I2C, "Adaptername: %s", usbvision->i2c_adap.name);
+       usbvision->i2c_adap.dev.parent = &usbvision->dev->dev;
+
+       i2c_set_adapdata(&usbvision->i2c_adap, &usbvision->v4l2_dev);
+
+       if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) {
+               printk(KERN_ERR "usbvision_i2c_register: can't write reg\n");
+               return -EBUSY;
+       }
+
+       PDEBUG(DBG_I2C, "I2C   debugging is enabled [i2c]");
+       PDEBUG(DBG_I2C, "ALGO   debugging is enabled [i2c]");
+
+       /* register new adapter to i2c module... */
+
+       usbvision->i2c_adap.algo = &usbvision_algo;
+
+       usbvision->i2c_adap.timeout = 100;      /* default values, should       */
+       usbvision->i2c_adap.retries = 3;        /* be replaced by defines       */
+
+       i2c_add_adapter(&usbvision->i2c_adap);
+
+       PDEBUG(DBG_I2C, "i2c bus for %s registered", usbvision->i2c_adap.name);
+
+       /* Request the load of the i2c modules we need */
+       switch (usbvision_device_data[usbvision->dev_model].codec) {
+       case CODEC_SAA7113:
+       case CODEC_SAA7111:
+               /* Without this delay the detection of the saa711x is
+                  hit-and-miss. */
+               mdelay(10);
+               v4l2_i2c_new_subdev(&usbvision->v4l2_dev,
+                               &usbvision->i2c_adap,
+                               "saa7115_auto", 0, saa711x_addrs);
+               break;
+       }
+       if (usbvision_device_data[usbvision->dev_model].tuner == 1) {
+               struct v4l2_subdev *sd;
+               enum v4l2_i2c_tuner_type type;
+               struct tuner_setup tun_setup;
+
+               sd = v4l2_i2c_new_subdev(&usbvision->v4l2_dev,
+                               &usbvision->i2c_adap,
+                               "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+               /* depending on whether we found a demod or not, select
+                  the tuner type. */
+               type = sd ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
+
+               sd = v4l2_i2c_new_subdev(&usbvision->v4l2_dev,
+                               &usbvision->i2c_adap,
+                               "tuner", 0, v4l2_i2c_tuner_addrs(type));
+
+               if (sd == NULL)
+                       return -ENODEV;
+               if (usbvision->tuner_type != -1) {
+                       tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+                       tun_setup.type = usbvision->tuner_type;
+                       tun_setup.addr = v4l2_i2c_subdev_addr(sd);
+                       call_all(usbvision, tuner, s_type_addr, &tun_setup);
+               }
+       }
+       usbvision->registered_i2c = 1;
+
+       return 0;
+}
+
+int usbvision_i2c_unregister(struct usb_usbvision *usbvision)
+{
+       if (!usbvision->registered_i2c)
+               return 0;
+
+       i2c_del_adapter(&(usbvision->i2c_adap));
+       usbvision->registered_i2c = 0;
+
+       PDEBUG(DBG_I2C, "i2c bus for %s unregistered", usbvision->i2c_adap.name);
+
+       return 0;
+}
+
+static int
+usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr,
+                    char *buf, short len)
+{
+       int rc, retries;
+
+       for (retries = 5;;) {
+               rc = usbvision_write_reg(usbvision, USBVISION_SER_ADRS, addr);
+               if (rc < 0)
+                       return rc;
+
+               /* Initiate byte read cycle                    */
+               /* USBVISION_SER_CONT <- d0-d2 n. of bytes to r/w */
+               /*                    d3 0=Wr 1=Rd             */
+               rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT,
+                                     (len & 0x07) | 0x18);
+               if (rc < 0)
+                       return rc;
+
+               /* Test for Busy and ACK */
+               do {
+                       /* USBVISION_SER_CONT -> d4 == 0 busy */
+                       rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT);
+               } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */
+               if (rc < 0)
+                       return rc;
+
+               /* USBVISION_SER_CONT -> d5 == 1 Not ack */
+               if ((rc & 0x20) == 0)   /* Ack? */
+                       break;
+
+               /* I2C abort */
+               rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00);
+               if (rc < 0)
+                       return rc;
+
+               if (--retries < 0)
+                       return -1;
+       }
+
+       switch (len) {
+       case 4:
+               buf[3] = usbvision_read_reg(usbvision, USBVISION_SER_DAT4);
+       case 3:
+               buf[2] = usbvision_read_reg(usbvision, USBVISION_SER_DAT3);
+       case 2:
+               buf[1] = usbvision_read_reg(usbvision, USBVISION_SER_DAT2);
+       case 1:
+               buf[0] = usbvision_read_reg(usbvision, USBVISION_SER_DAT1);
+               break;
+       default:
+               printk(KERN_ERR
+                      "usbvision_i2c_read_max4: buffer length > 4\n");
+       }
+
+       if (i2c_debug & DBG_I2C) {
+               int idx;
+
+               for (idx = 0; idx < len; idx++)
+                       PDEBUG(DBG_I2C, "read %x from address %x", (unsigned char)buf[idx], addr);
+       }
+       return len;
+}
+
+
+static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision,
+                                unsigned char addr, const char *buf,
+                                short len)
+{
+       int rc, retries;
+       int i;
+       unsigned char value[6];
+       unsigned char ser_cont;
+
+       ser_cont = (len & 0x07) | 0x10;
+
+       value[0] = addr;
+       value[1] = ser_cont;
+       for (i = 0; i < len; i++)
+               value[i + 2] = buf[i];
+
+       for (retries = 5;;) {
+               rc = usb_control_msg(usbvision->dev,
+                                    usb_sndctrlpipe(usbvision->dev, 1),
+                                    USBVISION_OP_CODE,
+                                    USB_DIR_OUT | USB_TYPE_VENDOR |
+                                    USB_RECIP_ENDPOINT, 0,
+                                    (__u16) USBVISION_SER_ADRS, value,
+                                    len + 2, HZ);
+
+               if (rc < 0)
+                       return rc;
+
+               rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT,
+                                     (len & 0x07) | 0x10);
+               if (rc < 0)
+                       return rc;
+
+               /* Test for Busy and ACK */
+               do {
+                       rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT);
+               } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */
+               if (rc < 0)
+                       return rc;
+
+               if ((rc & 0x20) == 0)   /* Ack? */
+                       break;
+
+               /* I2C abort */
+               usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00);
+
+               if (--retries < 0)
+                       return -1;
+
+       }
+
+       if (i2c_debug & DBG_I2C) {
+               int idx;
+
+               for (idx = 0; idx < len; idx++)
+                       PDEBUG(DBG_I2C, "wrote %x at address %x", (unsigned char)buf[idx], addr);
+       }
+       return len;
+}
+
+static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
+                           short len)
+{
+       char *buf_ptr = buf;
+       int retval;
+       int wrcount = 0;
+       int count;
+       int max_len = 4;
+
+       while (len > 0) {
+               count = (len > max_len) ? max_len : len;
+               retval = usbvision_i2c_write_max4(usbvision, addr, buf_ptr, count);
+               if (retval > 0) {
+                       len -= count;
+                       buf_ptr += count;
+                       wrcount += count;
+               } else
+                       return (retval < 0) ? retval : -EFAULT;
+       }
+       return wrcount;
+}
+
+static int usbvision_i2c_read(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
+                          short len)
+{
+       char temp[4];
+       int retval, i;
+       int rdcount = 0;
+       int count;
+
+       while (len > 0) {
+               count = (len > 3) ? 4 : len;
+               retval = usbvision_i2c_read_max4(usbvision, addr, temp, count);
+               if (retval > 0) {
+                       for (i = 0; i < len; i++)
+                               buf[rdcount + i] = temp[i];
+                       len -= count;
+                       rdcount += count;
+               } else
+                       return (retval < 0) ? retval : -EFAULT;
+       }
+       return rdcount;
+}
+
+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
new file mode 100644 (file)
index 0000000..8a43179
--- /dev/null
@@ -0,0 +1,1720 @@
+/*
+ * USB USBVISION Video device driver 0.9.10
+ *
+ *
+ *
+ * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ *
+ * This module is part of usbvision driver project.
+ *
+ * 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.
+ *
+ * Let's call the version 0.... until compression decoding is completely
+ * implemented.
+ *
+ * This driver is written by Jose Ignacio Gijon and Joerg Heckenbach.
+ * It was based on USB CPiA driver written by Peter Pregler,
+ * Scott J. Bertin and Johannes Erdfelt
+ * Ideas are taken from bttv driver by Ralph Metzler, Marcus Metzler &
+ * Gerd Knorr and zoran 36120/36125 driver by Pauline Middelink
+ * Updates to driver completed by Dwaine P. Garden
+ *
+ *
+ * TODO:
+ *     - use submit_urb for all setup packets
+ *     - Fix memory settings for nt1004. It is 4 times as big as the
+ *       nt1003 memory.
+ *     - Add audio on endpoint 3 for nt1004 chip.
+ *         Seems impossible, needs a codec interface.  Which one?
+ *     - Clean up the driver.
+ *     - optimization for performance.
+ *     - Add Videotext capability (VBI).  Working on it.....
+ *     - Check audio for other devices
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+
+#include <media/saa7115.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/tuner.h>
+
+#include <linux/workqueue.h>
+
+#include "usbvision.h"
+#include "usbvision-cards.h"
+
+#define DRIVER_AUTHOR                                  \
+       "Joerg Heckenbach <joerg@heckenbach-aw.de>, "   \
+       "Dwaine Garden <DwaineGarden@rogers.com>"
+#define DRIVER_NAME "usbvision"
+#define DRIVER_ALIAS "USBVision"
+#define DRIVER_DESC "USBVision USB Video Device Driver for Linux"
+#define DRIVER_LICENSE "GPL"
+#define USBVISION_VERSION_STRING "0.9.11"
+
+#define        ENABLE_HEXDUMP  0       /* Enable if you need it */
+
+
+#ifdef USBVISION_DEBUG
+       #define PDEBUG(level, fmt, args...) { \
+               if (video_debug & (level)) \
+                       printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \
+                               __func__, __LINE__ , ## args); \
+       }
+#else
+       #define PDEBUG(level, fmt, args...) do {} while (0)
+#endif
+
+#define DBG_IO         (1 << 1)
+#define DBG_PROBE      (1 << 2)
+#define DBG_MMAP       (1 << 3)
+
+/* String operations */
+#define rmspace(str)   while (*str == ' ') str++;
+#define goto2next(str) while (*str != ' ') str++; while (*str == ' ') str++;
+
+
+/* sequential number of usbvision device */
+static int usbvision_nr;
+
+static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = {
+       { 1, 1,  8, V4L2_PIX_FMT_GREY    , "GREY" },
+       { 1, 2, 16, V4L2_PIX_FMT_RGB565  , "RGB565" },
+       { 1, 3, 24, V4L2_PIX_FMT_RGB24   , "RGB24" },
+       { 1, 4, 32, V4L2_PIX_FMT_RGB32   , "RGB32" },
+       { 1, 2, 16, V4L2_PIX_FMT_RGB555  , "RGB555" },
+       { 1, 2, 16, V4L2_PIX_FMT_YUYV    , "YUV422" },
+       { 1, 2, 12, V4L2_PIX_FMT_YVU420  , "YUV420P" }, /* 1.5 ! */
+       { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" }
+};
+
+/* Function prototypes */
+static void usbvision_release(struct usb_usbvision *usbvision);
+
+/* Default initialization of device driver parameters */
+/* Set the default format for ISOC endpoint */
+static int isoc_mode = ISOC_MODE_COMPRESS;
+/* Set the default Debug Mode of the device driver */
+static int video_debug;
+/* Set the default device to power on at startup */
+static int power_on_at_open = 1;
+/* Sequential Number of Video Device */
+static int video_nr = -1;
+/* Sequential Number of Radio Device */
+static int radio_nr = -1;
+
+/* Grab parameters for the device driver */
+
+/* Showing parameters under SYSFS */
+module_param(isoc_mode, int, 0444);
+module_param(video_debug, int, 0444);
+module_param(power_on_at_open, int, 0444);
+module_param(video_nr, int, 0444);
+module_param(radio_nr, int, 0444);
+
+MODULE_PARM_DESC(isoc_mode, " Set the default format for ISOC endpoint.  Default: 0x60 (Compression On)");
+MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver.  Default: 0 (Off)");
+MODULE_PARM_DESC(power_on_at_open, " Set the default device to power on when device is opened.  Default: 1 (On)");
+MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX).  Default: -1 (autodetect)");
+MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX).  Default: -1 (autodetect)");
+
+
+/* Misc stuff */
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+MODULE_VERSION(USBVISION_VERSION_STRING);
+MODULE_ALIAS(DRIVER_ALIAS);
+
+
+/*****************************************************************************/
+/* SYSFS Code - Copied from the stv680.c usb module.                        */
+/* Device information is located at /sys/class/video4linux/video0            */
+/* Device parameters information is located at /sys/module/usbvision         */
+/* Device USB Information is located at                                      */
+/*   /sys/bus/usb/drivers/USBVision Video Grabber                            */
+/*****************************************************************************/
+
+#define YES_NO(x) ((x) ? "Yes" : "No")
+
+static inline struct usb_usbvision *cd_to_usbvision(struct device *cd)
+{
+       struct video_device *vdev =
+               container_of(cd, struct video_device, dev);
+       return video_get_drvdata(vdev);
+}
+
+static ssize_t show_version(struct device *cd,
+                           struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%s\n", USBVISION_VERSION_STRING);
+}
+static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
+
+static ssize_t show_model(struct device *cd,
+                         struct device_attribute *attr, char *buf)
+{
+       struct video_device *vdev =
+               container_of(cd, struct video_device, dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       return sprintf(buf, "%s\n",
+                      usbvision_device_data[usbvision->dev_model].model_string);
+}
+static DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
+
+static ssize_t show_hue(struct device *cd,
+                       struct device_attribute *attr, char *buf)
+{
+       struct video_device *vdev =
+               container_of(cd, struct video_device, dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       struct v4l2_control ctrl;
+       ctrl.id = V4L2_CID_HUE;
+       ctrl.value = 0;
+       if (usbvision->user)
+               call_all(usbvision, core, g_ctrl, &ctrl);
+       return sprintf(buf, "%d\n", ctrl.value);
+}
+static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
+
+static ssize_t show_contrast(struct device *cd,
+                            struct device_attribute *attr, char *buf)
+{
+       struct video_device *vdev =
+               container_of(cd, struct video_device, dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       struct v4l2_control ctrl;
+       ctrl.id = V4L2_CID_CONTRAST;
+       ctrl.value = 0;
+       if (usbvision->user)
+               call_all(usbvision, core, g_ctrl, &ctrl);
+       return sprintf(buf, "%d\n", ctrl.value);
+}
+static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
+
+static ssize_t show_brightness(struct device *cd,
+                              struct device_attribute *attr, char *buf)
+{
+       struct video_device *vdev =
+               container_of(cd, struct video_device, dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       struct v4l2_control ctrl;
+       ctrl.id = V4L2_CID_BRIGHTNESS;
+       ctrl.value = 0;
+       if (usbvision->user)
+               call_all(usbvision, core, g_ctrl, &ctrl);
+       return sprintf(buf, "%d\n", ctrl.value);
+}
+static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
+
+static ssize_t show_saturation(struct device *cd,
+                              struct device_attribute *attr, char *buf)
+{
+       struct video_device *vdev =
+               container_of(cd, struct video_device, dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       struct v4l2_control ctrl;
+       ctrl.id = V4L2_CID_SATURATION;
+       ctrl.value = 0;
+       if (usbvision->user)
+               call_all(usbvision, core, g_ctrl, &ctrl);
+       return sprintf(buf, "%d\n", ctrl.value);
+}
+static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
+
+static ssize_t show_streaming(struct device *cd,
+                             struct device_attribute *attr, char *buf)
+{
+       struct video_device *vdev =
+               container_of(cd, struct video_device, dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       return sprintf(buf, "%s\n",
+                      YES_NO(usbvision->streaming == stream_on ? 1 : 0));
+}
+static DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL);
+
+static ssize_t show_compression(struct device *cd,
+                               struct device_attribute *attr, char *buf)
+{
+       struct video_device *vdev =
+               container_of(cd, struct video_device, dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       return sprintf(buf, "%s\n",
+                      YES_NO(usbvision->isoc_mode == ISOC_MODE_COMPRESS));
+}
+static DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL);
+
+static ssize_t show_device_bridge(struct device *cd,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct video_device *vdev =
+               container_of(cd, struct video_device, dev);
+       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
+       return sprintf(buf, "%d\n", usbvision->bridge_type);
+}
+static DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL);
+
+static void usbvision_create_sysfs(struct video_device *vdev)
+{
+       int res;
+
+       if (!vdev)
+               return;
+       do {
+               res = device_create_file(&vdev->dev, &dev_attr_version);
+               if (res < 0)
+                       break;
+               res = device_create_file(&vdev->dev, &dev_attr_model);
+               if (res < 0)
+                       break;
+               res = device_create_file(&vdev->dev, &dev_attr_hue);
+               if (res < 0)
+                       break;
+               res = device_create_file(&vdev->dev, &dev_attr_contrast);
+               if (res < 0)
+                       break;
+               res = device_create_file(&vdev->dev, &dev_attr_brightness);
+               if (res < 0)
+                       break;
+               res = device_create_file(&vdev->dev, &dev_attr_saturation);
+               if (res < 0)
+                       break;
+               res = device_create_file(&vdev->dev, &dev_attr_streaming);
+               if (res < 0)
+                       break;
+               res = device_create_file(&vdev->dev, &dev_attr_compression);
+               if (res < 0)
+                       break;
+               res = device_create_file(&vdev->dev, &dev_attr_bridge);
+               if (res >= 0)
+                       return;
+       } while (0);
+
+       dev_err(&vdev->dev, "%s error: %d\n", __func__, res);
+}
+
+static void usbvision_remove_sysfs(struct video_device *vdev)
+{
+       if (vdev) {
+               device_remove_file(&vdev->dev, &dev_attr_version);
+               device_remove_file(&vdev->dev, &dev_attr_model);
+               device_remove_file(&vdev->dev, &dev_attr_hue);
+               device_remove_file(&vdev->dev, &dev_attr_contrast);
+               device_remove_file(&vdev->dev, &dev_attr_brightness);
+               device_remove_file(&vdev->dev, &dev_attr_saturation);
+               device_remove_file(&vdev->dev, &dev_attr_streaming);
+               device_remove_file(&vdev->dev, &dev_attr_compression);
+               device_remove_file(&vdev->dev, &dev_attr_bridge);
+       }
+}
+
+/*
+ * usbvision_open()
+ *
+ * This is part of Video 4 Linux API. The driver can be opened by one
+ * client only (checks internal counter 'usbvision->user'). The procedure
+ * then allocates buffers needed for video processing.
+ *
+ */
+static int usbvision_v4l2_open(struct file *file)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int err_code = 0;
+
+       PDEBUG(DBG_IO, "open");
+
+       if (mutex_lock_interruptible(&usbvision->v4l2_lock))
+               return -ERESTARTSYS;
+       usbvision_reset_power_off_timer(usbvision);
+
+       if (usbvision->user)
+               err_code = -EBUSY;
+       else {
+               /* Allocate memory for the scratch ring buffer */
+               err_code = usbvision_scratch_alloc(usbvision);
+               if (isoc_mode == ISOC_MODE_COMPRESS) {
+                       /* Allocate intermediate decompression buffers
+                          only if needed */
+                       err_code = usbvision_decompress_alloc(usbvision);
+               }
+               if (err_code) {
+                       /* Deallocate all buffers if trouble */
+                       usbvision_scratch_free(usbvision);
+                       usbvision_decompress_free(usbvision);
+               }
+       }
+
+       /* If so far no errors then we shall start the camera */
+       if (!err_code) {
+               if (usbvision->power == 0) {
+                       usbvision_power_on(usbvision);
+                       usbvision_i2c_register(usbvision);
+               }
+
+               /* Send init sequence only once, it's large! */
+               if (!usbvision->initialized) {
+                       int setup_ok = 0;
+                       setup_ok = usbvision_setup(usbvision, isoc_mode);
+                       if (setup_ok)
+                               usbvision->initialized = 1;
+                       else
+                               err_code = -EBUSY;
+               }
+
+               if (!err_code) {
+                       usbvision_begin_streaming(usbvision);
+                       err_code = usbvision_init_isoc(usbvision);
+                       /* device must be initialized before isoc transfer */
+                       usbvision_muxsel(usbvision, 0);
+                       usbvision->user++;
+               } else {
+                       if (power_on_at_open) {
+                               usbvision_i2c_unregister(usbvision);
+                               usbvision_power_off(usbvision);
+                               usbvision->initialized = 0;
+                       }
+               }
+       }
+
+       /* prepare queues */
+       usbvision_empty_framequeues(usbvision);
+       mutex_unlock(&usbvision->v4l2_lock);
+
+       PDEBUG(DBG_IO, "success");
+       return err_code;
+}
+
+/*
+ * usbvision_v4l2_close()
+ *
+ * This is part of Video 4 Linux API. The procedure
+ * stops streaming and deallocates all buffers that were earlier
+ * allocated in usbvision_v4l2_open().
+ *
+ */
+static int usbvision_v4l2_close(struct file *file)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       PDEBUG(DBG_IO, "close");
+
+       mutex_lock(&usbvision->v4l2_lock);
+       usbvision_audio_off(usbvision);
+       usbvision_restart_isoc(usbvision);
+       usbvision_stop_isoc(usbvision);
+
+       usbvision_decompress_free(usbvision);
+       usbvision_frames_free(usbvision);
+       usbvision_empty_framequeues(usbvision);
+       usbvision_scratch_free(usbvision);
+
+       usbvision->user--;
+
+       if (power_on_at_open) {
+               /* power off in a little while
+                  to avoid off/on every close/open short sequences */
+               usbvision_set_power_off_timer(usbvision);
+               usbvision->initialized = 0;
+       }
+
+       if (usbvision->remove_pending) {
+               printk(KERN_INFO "%s: Final disconnect\n", __func__);
+               usbvision_release(usbvision);
+       }
+       mutex_unlock(&usbvision->v4l2_lock);
+
+       PDEBUG(DBG_IO, "success");
+       return 0;
+}
+
+
+/*
+ * usbvision_ioctl()
+ *
+ * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
+ *
+ */
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register(struct file *file, void *priv,
+                               struct v4l2_dbg_register *reg)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int err_code;
+
+       if (!v4l2_chip_match_host(&reg->match))
+               return -EINVAL;
+       /* NT100x has a 8-bit register space */
+       err_code = usbvision_read_reg(usbvision, reg->reg&0xff);
+       if (err_code < 0) {
+               dev_err(&usbvision->vdev->dev,
+                       "%s: VIDIOC_DBG_G_REGISTER failed: error %d\n",
+                               __func__, err_code);
+               return err_code;
+       }
+       reg->val = err_code;
+       reg->size = 1;
+       return 0;
+}
+
+static int vidioc_s_register(struct file *file, void *priv,
+                               struct v4l2_dbg_register *reg)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int err_code;
+
+       if (!v4l2_chip_match_host(&reg->match))
+               return -EINVAL;
+       /* NT100x has a 8-bit register space */
+       err_code = usbvision_write_reg(usbvision, reg->reg & 0xff, reg->val);
+       if (err_code < 0) {
+               dev_err(&usbvision->vdev->dev,
+                       "%s: VIDIOC_DBG_S_REGISTER failed: error %d\n",
+                               __func__, err_code);
+               return err_code;
+       }
+       return 0;
+}
+#endif
+
+static int vidioc_querycap(struct file *file, void  *priv,
+                                       struct v4l2_capability *vc)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
+       strlcpy(vc->card,
+               usbvision_device_data[usbvision->dev_model].model_string,
+               sizeof(vc->card));
+       usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info));
+       vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_AUDIO |
+               V4L2_CAP_READWRITE |
+               V4L2_CAP_STREAMING |
+               (usbvision->have_tuner ? V4L2_CAP_TUNER : 0);
+       return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+                               struct v4l2_input *vi)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int chan;
+
+       if (vi->index >= usbvision->video_inputs)
+               return -EINVAL;
+       if (usbvision->have_tuner)
+               chan = vi->index;
+       else
+               chan = vi->index + 1; /* skip Television string*/
+
+       /* Determine the requested input characteristics
+          specific for each usbvision card model */
+       switch (chan) {
+       case 0:
+               if (usbvision_device_data[usbvision->dev_model].video_channels == 4) {
+                       strcpy(vi->name, "White Video Input");
+               } else {
+                       strcpy(vi->name, "Television");
+                       vi->type = V4L2_INPUT_TYPE_TUNER;
+                       vi->audioset = 1;
+                       vi->tuner = chan;
+                       vi->std = USBVISION_NORMS;
+               }
+               break;
+       case 1:
+               vi->type = V4L2_INPUT_TYPE_CAMERA;
+               if (usbvision_device_data[usbvision->dev_model].video_channels == 4)
+                       strcpy(vi->name, "Green Video Input");
+               else
+                       strcpy(vi->name, "Composite Video Input");
+               vi->std = V4L2_STD_PAL;
+               break;
+       case 2:
+               vi->type = V4L2_INPUT_TYPE_CAMERA;
+               if (usbvision_device_data[usbvision->dev_model].video_channels == 4)
+                       strcpy(vi->name, "Yellow Video Input");
+               else
+                       strcpy(vi->name, "S-Video Input");
+               vi->std = V4L2_STD_PAL;
+               break;
+       case 3:
+               vi->type = V4L2_INPUT_TYPE_CAMERA;
+               strcpy(vi->name, "Red Video Input");
+               vi->std = V4L2_STD_PAL;
+               break;
+       }
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *input)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       *input = usbvision->ctl_input;
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       if (input >= usbvision->video_inputs)
+               return -EINVAL;
+
+       usbvision_muxsel(usbvision, input);
+       usbvision_set_input(usbvision);
+       usbvision_set_output(usbvision,
+                            usbvision->curwidth,
+                            usbvision->curheight);
+       return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       usbvision->tvnorm_id = *id;
+
+       call_all(usbvision, core, s_std, usbvision->tvnorm_id);
+       /* propagate the change to the decoder */
+       usbvision_muxsel(usbvision, usbvision->ctl_input);
+
+       return 0;
+}
+
+static int vidioc_g_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *vt)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       if (!usbvision->have_tuner || vt->index)        /* Only tuner 0 */
+               return -EINVAL;
+       if (usbvision->radio) {
+               strcpy(vt->name, "Radio");
+               vt->type = V4L2_TUNER_RADIO;
+       } else {
+               strcpy(vt->name, "Television");
+       }
+       /* Let clients fill in the remainder of this struct */
+       call_all(usbvision, tuner, g_tuner, vt);
+
+       return 0;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv,
+                               struct v4l2_tuner *vt)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       /* Only no or one tuner for now */
+       if (!usbvision->have_tuner || vt->index)
+               return -EINVAL;
+       /* let clients handle this */
+       call_all(usbvision, tuner, s_tuner, vt);
+
+       return 0;
+}
+
+static int vidioc_g_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *freq)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       freq->tuner = 0; /* Only one tuner */
+       if (usbvision->radio)
+               freq->type = V4L2_TUNER_RADIO;
+       else
+               freq->type = V4L2_TUNER_ANALOG_TV;
+       freq->frequency = usbvision->freq;
+
+       return 0;
+}
+
+static int vidioc_s_frequency(struct file *file, void *priv,
+                               struct v4l2_frequency *freq)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       /* Only no or one tuner for now */
+       if (!usbvision->have_tuner || freq->tuner)
+               return -EINVAL;
+
+       usbvision->freq = freq->frequency;
+       call_all(usbvision, tuner, s_frequency, freq);
+
+       return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       if (usbvision->radio)
+               strcpy(a->name, "Radio");
+       else
+               strcpy(a->name, "TV");
+
+       return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *fh,
+                         struct v4l2_audio *a)
+{
+       if (a->index)
+               return -EINVAL;
+       return 0;
+}
+
+static int vidioc_queryctrl(struct file *file, void *priv,
+                           struct v4l2_queryctrl *ctrl)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       call_all(usbvision, core, queryctrl, ctrl);
+
+       if (!ctrl->type)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int vidioc_g_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctrl)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       call_all(usbvision, core, g_ctrl, ctrl);
+       return 0;
+}
+
+static int vidioc_s_ctrl(struct file *file, void *priv,
+                               struct v4l2_control *ctrl)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       call_all(usbvision, core, s_ctrl, ctrl);
+       return 0;
+}
+
+static int vidioc_reqbufs(struct file *file,
+                          void *priv, struct v4l2_requestbuffers *vr)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int ret;
+
+       RESTRICT_TO_RANGE(vr->count, 1, USBVISION_NUMFRAMES);
+
+       /* Check input validity:
+          the user must do a VIDEO CAPTURE and MMAP method. */
+       if (vr->memory != V4L2_MEMORY_MMAP)
+               return -EINVAL;
+
+       if (usbvision->streaming == stream_on) {
+               ret = usbvision_stream_interrupt(usbvision);
+               if (ret)
+                       return ret;
+       }
+
+       usbvision_frames_free(usbvision);
+       usbvision_empty_framequeues(usbvision);
+       vr->count = usbvision_frames_alloc(usbvision, vr->count);
+
+       usbvision->cur_frame = NULL;
+
+       return 0;
+}
+
+static int vidioc_querybuf(struct file *file,
+                           void *priv, struct v4l2_buffer *vb)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       struct usbvision_frame *frame;
+
+       /* FIXME : must control
+          that buffers are mapped (VIDIOC_REQBUFS has been called) */
+       if (vb->index >= usbvision->num_frames)
+               return -EINVAL;
+       /* Updating the corresponding frame state */
+       vb->flags = 0;
+       frame = &usbvision->frame[vb->index];
+       if (frame->grabstate >= frame_state_ready)
+               vb->flags |= V4L2_BUF_FLAG_QUEUED;
+       if (frame->grabstate >= frame_state_done)
+               vb->flags |= V4L2_BUF_FLAG_DONE;
+       if (frame->grabstate == frame_state_unused)
+               vb->flags |= V4L2_BUF_FLAG_MAPPED;
+       vb->memory = V4L2_MEMORY_MMAP;
+
+       vb->m.offset = vb->index * PAGE_ALIGN(usbvision->max_frame_size);
+
+       vb->memory = V4L2_MEMORY_MMAP;
+       vb->field = V4L2_FIELD_NONE;
+       vb->length = usbvision->curwidth *
+               usbvision->curheight *
+               usbvision->palette.bytes_per_pixel;
+       vb->timestamp = usbvision->frame[vb->index].timestamp;
+       vb->sequence = usbvision->frame[vb->index].sequence;
+       return 0;
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *vb)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       struct usbvision_frame *frame;
+       unsigned long lock_flags;
+
+       /* FIXME : works only on VIDEO_CAPTURE MODE, MMAP. */
+       if (vb->index >= usbvision->num_frames)
+               return -EINVAL;
+
+       frame = &usbvision->frame[vb->index];
+
+       if (frame->grabstate != frame_state_unused)
+               return -EAGAIN;
+
+       /* Mark it as ready and enqueue frame */
+       frame->grabstate = frame_state_ready;
+       frame->scanstate = scan_state_scanning;
+       frame->scanlength = 0;  /* Accumulated in usbvision_parse_data() */
+
+       vb->flags &= ~V4L2_BUF_FLAG_DONE;
+
+       /* set v4l2_format index */
+       frame->v4l2_format = usbvision->palette;
+
+       spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+       list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue);
+       spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+       return 0;
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *vb)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int ret;
+       struct usbvision_frame *f;
+       unsigned long lock_flags;
+
+       if (list_empty(&(usbvision->outqueue))) {
+               if (usbvision->streaming == stream_idle)
+                       return -EINVAL;
+               ret = wait_event_interruptible
+                       (usbvision->wait_frame,
+                        !list_empty(&(usbvision->outqueue)));
+               if (ret)
+                       return ret;
+       }
+
+       spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+       f = list_entry(usbvision->outqueue.next,
+                      struct usbvision_frame, frame);
+       list_del(usbvision->outqueue.next);
+       spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+       f->grabstate = frame_state_unused;
+
+       vb->memory = V4L2_MEMORY_MMAP;
+       vb->flags = V4L2_BUF_FLAG_MAPPED |
+               V4L2_BUF_FLAG_QUEUED |
+               V4L2_BUF_FLAG_DONE;
+       vb->index = f->index;
+       vb->sequence = f->sequence;
+       vb->timestamp = f->timestamp;
+       vb->field = V4L2_FIELD_NONE;
+       vb->bytesused = f->scanlength;
+
+       return 0;
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       usbvision->streaming = stream_on;
+       call_all(usbvision, video, s_stream, 1);
+
+       return 0;
+}
+
+static int vidioc_streamoff(struct file *file,
+                           void *priv, enum v4l2_buf_type type)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (usbvision->streaming == stream_on) {
+               usbvision_stream_interrupt(usbvision);
+               /* Stop all video streamings */
+               call_all(usbvision, video, s_stream, 0);
+       }
+       usbvision_empty_framequeues(usbvision);
+
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+                                       struct v4l2_fmtdesc *vfd)
+{
+       if (vfd->index >= USBVISION_SUPPORTED_PALETTES - 1)
+               return -EINVAL;
+       strcpy(vfd->description, usbvision_v4l2_format[vfd->index].desc);
+       vfd->pixelformat = usbvision_v4l2_format[vfd->index].format;
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *vf)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       vf->fmt.pix.width = usbvision->curwidth;
+       vf->fmt.pix.height = usbvision->curheight;
+       vf->fmt.pix.pixelformat = usbvision->palette.format;
+       vf->fmt.pix.bytesperline =
+               usbvision->curwidth * usbvision->palette.bytes_per_pixel;
+       vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline * usbvision->curheight;
+       vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+       vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */
+
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                              struct v4l2_format *vf)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int format_idx;
+
+       /* Find requested format in available ones */
+       for (format_idx = 0; format_idx < USBVISION_SUPPORTED_PALETTES; format_idx++) {
+               if (vf->fmt.pix.pixelformat ==
+                  usbvision_v4l2_format[format_idx].format) {
+                       usbvision->palette = usbvision_v4l2_format[format_idx];
+                       break;
+               }
+       }
+       /* robustness */
+       if (format_idx == USBVISION_SUPPORTED_PALETTES)
+               return -EINVAL;
+       RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
+       RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT);
+
+       vf->fmt.pix.bytesperline = vf->fmt.pix.width*
+               usbvision->palette.bytes_per_pixel;
+       vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height;
+
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                              struct v4l2_format *vf)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int ret;
+
+       ret = vidioc_try_fmt_vid_cap(file, priv, vf);
+       if (ret)
+               return ret;
+
+       /* stop io in case it is already in progress */
+       if (usbvision->streaming == stream_on) {
+               ret = usbvision_stream_interrupt(usbvision);
+               if (ret)
+                       return ret;
+       }
+       usbvision_frames_free(usbvision);
+       usbvision_empty_framequeues(usbvision);
+
+       usbvision->cur_frame = NULL;
+
+       /* by now we are committed to the new data... */
+       usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height);
+
+       return 0;
+}
+
+static ssize_t usbvision_read(struct file *file, char __user *buf,
+                     size_t count, loff_t *ppos)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int noblock = file->f_flags & O_NONBLOCK;
+       unsigned long lock_flags;
+       int ret, i;
+       struct usbvision_frame *frame;
+
+       PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __func__,
+              (unsigned long)count, noblock);
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL))
+               return -EFAULT;
+
+       /* This entry point is compatible with the mmap routines
+          so that a user can do either VIDIOC_QBUF/VIDIOC_DQBUF
+          to get frames or call read on the device. */
+       if (!usbvision->num_frames) {
+               /* First, allocate some frames to work with
+                  if this has not been done with VIDIOC_REQBUF */
+               usbvision_frames_free(usbvision);
+               usbvision_empty_framequeues(usbvision);
+               usbvision_frames_alloc(usbvision, USBVISION_NUMFRAMES);
+       }
+
+       if (usbvision->streaming != stream_on) {
+               /* no stream is running, make it running ! */
+               usbvision->streaming = stream_on;
+               call_all(usbvision, video, s_stream, 1);
+       }
+
+       /* Then, enqueue as many frames as possible
+          (like a user of VIDIOC_QBUF would do) */
+       for (i = 0; i < usbvision->num_frames; i++) {
+               frame = &usbvision->frame[i];
+               if (frame->grabstate == frame_state_unused) {
+                       /* Mark it as ready and enqueue frame */
+                       frame->grabstate = frame_state_ready;
+                       frame->scanstate = scan_state_scanning;
+                       /* Accumulated in usbvision_parse_data() */
+                       frame->scanlength = 0;
+
+                       /* set v4l2_format index */
+                       frame->v4l2_format = usbvision->palette;
+
+                       spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+                       list_add_tail(&frame->frame, &usbvision->inqueue);
+                       spin_unlock_irqrestore(&usbvision->queue_lock,
+                                              lock_flags);
+               }
+       }
+
+       /* Then try to steal a frame (like a VIDIOC_DQBUF would do) */
+       if (list_empty(&(usbvision->outqueue))) {
+               if (noblock)
+                       return -EAGAIN;
+
+               ret = wait_event_interruptible
+                       (usbvision->wait_frame,
+                        !list_empty(&(usbvision->outqueue)));
+               if (ret)
+                       return ret;
+       }
+
+       spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
+       frame = list_entry(usbvision->outqueue.next,
+                          struct usbvision_frame, frame);
+       list_del(usbvision->outqueue.next);
+       spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
+
+       /* An error returns an empty frame */
+       if (frame->grabstate == frame_state_error) {
+               frame->bytes_read = 0;
+               return 0;
+       }
+
+       PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld",
+              __func__,
+              frame->index, frame->bytes_read, frame->scanlength);
+
+       /* copy bytes to user space; we allow for partials reads */
+       if ((count + frame->bytes_read) > (unsigned long)frame->scanlength)
+               count = frame->scanlength - frame->bytes_read;
+
+       if (copy_to_user(buf, frame->data + frame->bytes_read, count))
+               return -EFAULT;
+
+       frame->bytes_read += count;
+       PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld",
+              __func__,
+              (unsigned long)count, frame->bytes_read);
+
+       /* For now, forget the frame if it has not been read in one shot. */
+/*     if (frame->bytes_read >= frame->scanlength) {*/ /* All data has been read */
+               frame->bytes_read = 0;
+
+               /* Mark it as available to be used again. */
+               frame->grabstate = frame_state_unused;
+/*     } */
+
+       return count;
+}
+
+static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
+                     size_t count, loff_t *ppos)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int res;
+
+       if (mutex_lock_interruptible(&usbvision->v4l2_lock))
+               return -ERESTARTSYS;
+       res = usbvision_read(file, buf, count, ppos);
+       mutex_unlock(&usbvision->v4l2_lock);
+       return res;
+}
+
+static int usbvision_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       unsigned long size = vma->vm_end - vma->vm_start,
+               start = vma->vm_start;
+       void *pos;
+       u32 i;
+       struct usb_usbvision *usbvision = video_drvdata(file);
+
+       PDEBUG(DBG_MMAP, "mmap");
+
+       if (!USBVISION_IS_OPERATIONAL(usbvision))
+               return -EFAULT;
+
+       if (!(vma->vm_flags & VM_WRITE) ||
+           size != PAGE_ALIGN(usbvision->max_frame_size)) {
+               return -EINVAL;
+       }
+
+       for (i = 0; i < usbvision->num_frames; i++) {
+               if (((PAGE_ALIGN(usbvision->max_frame_size)*i) >> PAGE_SHIFT) ==
+                   vma->vm_pgoff)
+                       break;
+       }
+       if (i == usbvision->num_frames) {
+               PDEBUG(DBG_MMAP,
+                      "mmap: user supplied mapping address is out of range");
+               return -EINVAL;
+       }
+
+       /* VM_IO is eventually going to replace PageReserved altogether */
+       vma->vm_flags |= VM_IO;
+       vma->vm_flags |= VM_RESERVED;   /* avoid to swap out this VMA */
+
+       pos = usbvision->frame[i].data;
+       while (size > 0) {
+               if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
+                       PDEBUG(DBG_MMAP, "mmap: vm_insert_page failed");
+                       return -EAGAIN;
+               }
+               start += PAGE_SIZE;
+               pos += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       return 0;
+}
+
+static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int res;
+
+       if (mutex_lock_interruptible(&usbvision->v4l2_lock))
+               return -ERESTARTSYS;
+       res = usbvision_mmap(file, vma);
+       mutex_unlock(&usbvision->v4l2_lock);
+       return res;
+}
+
+/*
+ * Here comes the stuff for radio on usbvision based devices
+ *
+ */
+static int usbvision_radio_open(struct file *file)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int err_code = 0;
+
+       PDEBUG(DBG_IO, "%s:", __func__);
+
+       if (mutex_lock_interruptible(&usbvision->v4l2_lock))
+               return -ERESTARTSYS;
+       if (usbvision->user) {
+               dev_err(&usbvision->rdev->dev,
+                       "%s: Someone tried to open an already opened USBVision Radio!\n",
+                               __func__);
+               err_code = -EBUSY;
+       } else {
+               if (power_on_at_open) {
+                       usbvision_reset_power_off_timer(usbvision);
+                       if (usbvision->power == 0) {
+                               usbvision_power_on(usbvision);
+                               usbvision_i2c_register(usbvision);
+                       }
+               }
+
+               /* Alternate interface 1 is is the biggest frame size */
+               err_code = usbvision_set_alternate(usbvision);
+               if (err_code < 0) {
+                       usbvision->last_error = err_code;
+                       err_code = -EBUSY;
+                       goto out;
+               }
+
+               /* If so far no errors then we shall start the radio */
+               usbvision->radio = 1;
+               call_all(usbvision, tuner, s_radio);
+               usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO);
+               usbvision->user++;
+       }
+
+       if (err_code) {
+               if (power_on_at_open) {
+                       usbvision_i2c_unregister(usbvision);
+                       usbvision_power_off(usbvision);
+                       usbvision->initialized = 0;
+               }
+       }
+out:
+       mutex_unlock(&usbvision->v4l2_lock);
+       return err_code;
+}
+
+
+static int usbvision_radio_close(struct file *file)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int err_code = 0;
+
+       PDEBUG(DBG_IO, "");
+
+       mutex_lock(&usbvision->v4l2_lock);
+       /* Set packet size to 0 */
+       usbvision->iface_alt = 0;
+       err_code = usb_set_interface(usbvision->dev, usbvision->iface,
+                                   usbvision->iface_alt);
+
+       usbvision_audio_off(usbvision);
+       usbvision->radio = 0;
+       usbvision->user--;
+
+       if (power_on_at_open) {
+               usbvision_set_power_off_timer(usbvision);
+               usbvision->initialized = 0;
+       }
+
+       if (usbvision->remove_pending) {
+               printk(KERN_INFO "%s: Final disconnect\n", __func__);
+               usbvision_release(usbvision);
+       }
+
+       mutex_unlock(&usbvision->v4l2_lock);
+       PDEBUG(DBG_IO, "success");
+       return err_code;
+}
+
+/* Video registration stuff */
+
+/* Video template */
+static const struct v4l2_file_operations usbvision_fops = {
+       .owner             = THIS_MODULE,
+       .open           = usbvision_v4l2_open,
+       .release        = usbvision_v4l2_close,
+       .read           = usbvision_v4l2_read,
+       .mmap           = usbvision_v4l2_mmap,
+       .unlocked_ioctl = video_ioctl2,
+/*     .poll           = video_poll, */
+};
+
+static const struct v4l2_ioctl_ops usbvision_ioctl_ops = {
+       .vidioc_querycap      = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
+       .vidioc_reqbufs       = vidioc_reqbufs,
+       .vidioc_querybuf      = vidioc_querybuf,
+       .vidioc_qbuf          = vidioc_qbuf,
+       .vidioc_dqbuf         = vidioc_dqbuf,
+       .vidioc_s_std         = vidioc_s_std,
+       .vidioc_enum_input    = vidioc_enum_input,
+       .vidioc_g_input       = vidioc_g_input,
+       .vidioc_s_input       = vidioc_s_input,
+       .vidioc_queryctrl     = vidioc_queryctrl,
+       .vidioc_g_audio       = vidioc_g_audio,
+       .vidioc_s_audio       = vidioc_s_audio,
+       .vidioc_g_ctrl        = vidioc_g_ctrl,
+       .vidioc_s_ctrl        = vidioc_s_ctrl,
+       .vidioc_streamon      = vidioc_streamon,
+       .vidioc_streamoff     = vidioc_streamoff,
+       .vidioc_g_tuner       = vidioc_g_tuner,
+       .vidioc_s_tuner       = vidioc_s_tuner,
+       .vidioc_g_frequency   = vidioc_g_frequency,
+       .vidioc_s_frequency   = vidioc_s_frequency,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register    = vidioc_g_register,
+       .vidioc_s_register    = vidioc_s_register,
+#endif
+};
+
+static struct video_device usbvision_video_template = {
+       .fops           = &usbvision_fops,
+       .ioctl_ops      = &usbvision_ioctl_ops,
+       .name           = "usbvision-video",
+       .release        = video_device_release,
+       .tvnorms        = USBVISION_NORMS,
+       .current_norm   = V4L2_STD_PAL
+};
+
+
+/* Radio template */
+static const struct v4l2_file_operations usbvision_radio_fops = {
+       .owner             = THIS_MODULE,
+       .open           = usbvision_radio_open,
+       .release        = usbvision_radio_close,
+       .unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = {
+       .vidioc_querycap      = vidioc_querycap,
+       .vidioc_enum_input    = vidioc_enum_input,
+       .vidioc_g_input       = vidioc_g_input,
+       .vidioc_s_input       = vidioc_s_input,
+       .vidioc_queryctrl     = vidioc_queryctrl,
+       .vidioc_g_audio       = vidioc_g_audio,
+       .vidioc_s_audio       = vidioc_s_audio,
+       .vidioc_g_ctrl        = vidioc_g_ctrl,
+       .vidioc_s_ctrl        = vidioc_s_ctrl,
+       .vidioc_g_tuner       = vidioc_g_tuner,
+       .vidioc_s_tuner       = vidioc_s_tuner,
+       .vidioc_g_frequency   = vidioc_g_frequency,
+       .vidioc_s_frequency   = vidioc_s_frequency,
+};
+
+static struct video_device usbvision_radio_template = {
+       .fops           = &usbvision_radio_fops,
+       .name           = "usbvision-radio",
+       .release        = video_device_release,
+       .ioctl_ops      = &usbvision_radio_ioctl_ops,
+
+       .tvnorms              = USBVISION_NORMS,
+       .current_norm         = V4L2_STD_PAL
+};
+
+
+static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision,
+                                       struct video_device *vdev_template,
+                                       char *name)
+{
+       struct usb_device *usb_dev = usbvision->dev;
+       struct video_device *vdev;
+
+       if (usb_dev == NULL) {
+               dev_err(&usbvision->dev->dev,
+                       "%s: usbvision->dev is not set\n", __func__);
+               return NULL;
+       }
+
+       vdev = video_device_alloc();
+       if (NULL == vdev)
+               return NULL;
+       *vdev = *vdev_template;
+       vdev->lock = &usbvision->v4l2_lock;
+       vdev->v4l2_dev = &usbvision->v4l2_dev;
+       snprintf(vdev->name, sizeof(vdev->name), "%s", name);
+       video_set_drvdata(vdev, usbvision);
+       return vdev;
+}
+
+/* unregister video4linux devices */
+static void usbvision_unregister_video(struct usb_usbvision *usbvision)
+{
+       /* Radio Device: */
+       if (usbvision->rdev) {
+               PDEBUG(DBG_PROBE, "unregister %s [v4l2]",
+                      video_device_node_name(usbvision->rdev));
+               if (video_is_registered(usbvision->rdev))
+                       video_unregister_device(usbvision->rdev);
+               else
+                       video_device_release(usbvision->rdev);
+               usbvision->rdev = NULL;
+       }
+
+       /* Video Device: */
+       if (usbvision->vdev) {
+               PDEBUG(DBG_PROBE, "unregister %s [v4l2]",
+                      video_device_node_name(usbvision->vdev));
+               if (video_is_registered(usbvision->vdev))
+                       video_unregister_device(usbvision->vdev);
+               else
+                       video_device_release(usbvision->vdev);
+               usbvision->vdev = NULL;
+       }
+}
+
+/* register video4linux devices */
+static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
+{
+       /* Video Device: */
+       usbvision->vdev = usbvision_vdev_init(usbvision,
+                                             &usbvision_video_template,
+                                             "USBVision Video");
+       if (usbvision->vdev == NULL)
+               goto err_exit;
+       if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
+               goto err_exit;
+       printk(KERN_INFO "USBVision[%d]: registered USBVision Video device %s [v4l2]\n",
+              usbvision->nr, video_device_node_name(usbvision->vdev));
+
+       /* Radio Device: */
+       if (usbvision_device_data[usbvision->dev_model].radio) {
+               /* usbvision has radio */
+               usbvision->rdev = usbvision_vdev_init(usbvision,
+                                                     &usbvision_radio_template,
+                                                     "USBVision Radio");
+               if (usbvision->rdev == NULL)
+                       goto err_exit;
+               if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr) < 0)
+                       goto err_exit;
+               printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device %s [v4l2]\n",
+                      usbvision->nr, video_device_node_name(usbvision->rdev));
+       }
+       /* all done */
+       return 0;
+
+ err_exit:
+       dev_err(&usbvision->dev->dev,
+               "USBVision[%d]: video_register_device() failed\n",
+                       usbvision->nr);
+       usbvision_unregister_video(usbvision);
+       return -1;
+}
+
+/*
+ * usbvision_alloc()
+ *
+ * This code allocates the struct usb_usbvision.
+ * It is filled with default values.
+ *
+ * Returns NULL on error, a pointer to usb_usbvision else.
+ *
+ */
+static struct usb_usbvision *usbvision_alloc(struct usb_device *dev,
+                                            struct usb_interface *intf)
+{
+       struct usb_usbvision *usbvision;
+
+       usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL);
+       if (usbvision == NULL)
+               return NULL;
+
+       usbvision->dev = dev;
+       if (v4l2_device_register(&intf->dev, &usbvision->v4l2_dev))
+               goto err_free;
+
+       mutex_init(&usbvision->v4l2_lock);
+
+       /* prepare control urb for control messages during interrupts */
+       usbvision->ctrl_urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
+       if (usbvision->ctrl_urb == NULL)
+               goto err_unreg;
+       init_waitqueue_head(&usbvision->ctrl_urb_wq);
+
+       usbvision_init_power_off_timer(usbvision);
+
+       return usbvision;
+
+err_unreg:
+       v4l2_device_unregister(&usbvision->v4l2_dev);
+err_free:
+       kfree(usbvision);
+       return NULL;
+}
+
+/*
+ * usbvision_release()
+ *
+ * This code does final release of struct usb_usbvision. This happens
+ * after the device is disconnected -and- all clients closed their files.
+ *
+ */
+static void usbvision_release(struct usb_usbvision *usbvision)
+{
+       PDEBUG(DBG_PROBE, "");
+
+       usbvision_reset_power_off_timer(usbvision);
+
+       usbvision->initialized = 0;
+
+       usbvision_remove_sysfs(usbvision->vdev);
+       usbvision_unregister_video(usbvision);
+
+       usb_free_urb(usbvision->ctrl_urb);
+
+       v4l2_device_unregister(&usbvision->v4l2_dev);
+       kfree(usbvision);
+
+       PDEBUG(DBG_PROBE, "success");
+}
+
+
+/*********************** usb interface **********************************/
+
+static void usbvision_configure_video(struct usb_usbvision *usbvision)
+{
+       int model;
+
+       if (usbvision == NULL)
+               return;
+
+       model = usbvision->dev_model;
+       usbvision->palette = usbvision_v4l2_format[2]; /* V4L2_PIX_FMT_RGB24; */
+
+       if (usbvision_device_data[usbvision->dev_model].vin_reg2_override) {
+               usbvision->vin_reg2_preset =
+                       usbvision_device_data[usbvision->dev_model].vin_reg2;
+       } else {
+               usbvision->vin_reg2_preset = 0;
+       }
+
+       usbvision->tvnorm_id = usbvision_device_data[model].video_norm;
+
+       usbvision->video_inputs = usbvision_device_data[model].video_channels;
+       usbvision->ctl_input = 0;
+
+       /* This should be here to make i2c clients to be able to register */
+       /* first switch off audio */
+       if (usbvision_device_data[model].audio_channels > 0)
+               usbvision_audio_off(usbvision);
+       if (!power_on_at_open) {
+               /* and then power up the noisy tuner */
+               usbvision_power_on(usbvision);
+               usbvision_i2c_register(usbvision);
+       }
+}
+
+/*
+ * usbvision_probe()
+ *
+ * This procedure queries device descriptor and accepts the interface
+ * if it looks like USBVISION video device
+ *
+ */
+static int __devinit usbvision_probe(struct usb_interface *intf,
+                                    const struct usb_device_id *devid)
+{
+       struct usb_device *dev = usb_get_dev(interface_to_usbdev(intf));
+       struct usb_interface *uif;
+       __u8 ifnum = intf->altsetting->desc.bInterfaceNumber;
+       const struct usb_host_interface *interface;
+       struct usb_usbvision *usbvision = NULL;
+       const struct usb_endpoint_descriptor *endpoint;
+       int model, i;
+
+       PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u",
+                               dev->descriptor.idVendor,
+                               dev->descriptor.idProduct, ifnum);
+
+       model = devid->driver_info;
+       if (model < 0 || model >= usbvision_device_data_size) {
+               PDEBUG(DBG_PROBE, "model out of bounds %d", model);
+               return -ENODEV;
+       }
+       printk(KERN_INFO "%s: %s found\n", __func__,
+                               usbvision_device_data[model].model_string);
+
+       if (usbvision_device_data[model].interface >= 0)
+               interface = &dev->actconfig->interface[usbvision_device_data[model].interface]->altsetting[0];
+       else
+               interface = &dev->actconfig->interface[ifnum]->altsetting[0];
+       endpoint = &interface->endpoint[1].desc;
+       if (!usb_endpoint_xfer_isoc(endpoint)) {
+               dev_err(&intf->dev, "%s: interface %d. has non-ISO endpoint!\n",
+                   __func__, ifnum);
+               dev_err(&intf->dev, "%s: Endpoint attributes %d",
+                   __func__, endpoint->bmAttributes);
+               return -ENODEV;
+       }
+       if (usb_endpoint_dir_out(endpoint)) {
+               dev_err(&intf->dev, "%s: interface %d. has ISO OUT endpoint!\n",
+                   __func__, ifnum);
+               return -ENODEV;
+       }
+
+       usbvision = usbvision_alloc(dev, intf);
+       if (usbvision == NULL) {
+               dev_err(&intf->dev, "%s: couldn't allocate USBVision struct\n", __func__);
+               return -ENOMEM;
+       }
+
+       if (dev->descriptor.bNumConfigurations > 1)
+               usbvision->bridge_type = BRIDGE_NT1004;
+       else if (model == DAZZLE_DVC_90_REV_1_SECAM)
+               usbvision->bridge_type = BRIDGE_NT1005;
+       else
+               usbvision->bridge_type = BRIDGE_NT1003;
+       PDEBUG(DBG_PROBE, "bridge_type %d", usbvision->bridge_type);
+
+       /* compute alternate max packet sizes */
+       uif = dev->actconfig->interface[0];
+
+       usbvision->num_alt = uif->num_altsetting;
+       PDEBUG(DBG_PROBE, "Alternate settings: %i", usbvision->num_alt);
+       usbvision->alt_max_pkt_size = kmalloc(32 * usbvision->num_alt, GFP_KERNEL);
+       if (usbvision->alt_max_pkt_size == NULL) {
+               dev_err(&intf->dev, "usbvision: out of memory!\n");
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < usbvision->num_alt; i++) {
+               u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc.
+                                     wMaxPacketSize);
+               usbvision->alt_max_pkt_size[i] =
+                       (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
+               PDEBUG(DBG_PROBE, "Alternate setting %i, max size= %i", i,
+                      usbvision->alt_max_pkt_size[i]);
+       }
+
+
+       usbvision->nr = usbvision_nr++;
+
+       usbvision->have_tuner = usbvision_device_data[model].tuner;
+       if (usbvision->have_tuner)
+               usbvision->tuner_type = usbvision_device_data[model].tuner_type;
+
+       usbvision->dev_model = model;
+       usbvision->remove_pending = 0;
+       usbvision->iface = ifnum;
+       usbvision->iface_alt = 0;
+       usbvision->video_endp = endpoint->bEndpointAddress;
+       usbvision->isoc_packet_size = 0;
+       usbvision->usb_bandwidth = 0;
+       usbvision->user = 0;
+       usbvision->streaming = stream_off;
+       usbvision_configure_video(usbvision);
+       usbvision_register_video(usbvision);
+
+       usbvision_create_sysfs(usbvision->vdev);
+
+       PDEBUG(DBG_PROBE, "success");
+       return 0;
+}
+
+
+/*
+ * usbvision_disconnect()
+ *
+ * This procedure stops all driver activity, deallocates interface-private
+ * structure (pointed by 'ptr') and after that driver should be removable
+ * with no ill consequences.
+ *
+ */
+static void __devexit usbvision_disconnect(struct usb_interface *intf)
+{
+       struct usb_usbvision *usbvision = to_usbvision(usb_get_intfdata(intf));
+
+       PDEBUG(DBG_PROBE, "");
+
+       if (usbvision == NULL) {
+               pr_err("%s: usb_get_intfdata() failed\n", __func__);
+               return;
+       }
+
+       mutex_lock(&usbvision->v4l2_lock);
+
+       /* At this time we ask to cancel outstanding URBs */
+       usbvision_stop_isoc(usbvision);
+
+       v4l2_device_disconnect(&usbvision->v4l2_dev);
+
+       if (usbvision->power) {
+               usbvision_i2c_unregister(usbvision);
+               usbvision_power_off(usbvision);
+       }
+       usbvision->remove_pending = 1;  /* Now all ISO data will be ignored */
+
+       usb_put_dev(usbvision->dev);
+       usbvision->dev = NULL;  /* USB device is no more */
+
+       mutex_unlock(&usbvision->v4l2_lock);
+
+       if (usbvision->user) {
+               printk(KERN_INFO "%s: In use, disconnect pending\n",
+                      __func__);
+               wake_up_interruptible(&usbvision->wait_frame);
+               wake_up_interruptible(&usbvision->wait_stream);
+       } else {
+               usbvision_release(usbvision);
+       }
+
+       PDEBUG(DBG_PROBE, "success");
+}
+
+static struct usb_driver usbvision_driver = {
+       .name           = "usbvision",
+       .id_table       = usbvision_table,
+       .probe          = usbvision_probe,
+       .disconnect     = __devexit_p(usbvision_disconnect),
+};
+
+/*
+ * usbvision_init()
+ *
+ * This code is run to initialize the driver.
+ *
+ */
+static int __init usbvision_init(void)
+{
+       int err_code;
+
+       PDEBUG(DBG_PROBE, "");
+
+       PDEBUG(DBG_IO,  "IO      debugging is enabled [video]");
+       PDEBUG(DBG_PROBE, "PROBE   debugging is enabled [video]");
+       PDEBUG(DBG_MMAP, "MMAP    debugging is enabled [video]");
+
+       /* disable planar mode support unless compression enabled */
+       if (isoc_mode != ISOC_MODE_COMPRESS) {
+               /* FIXME : not the right way to set supported flag */
+               usbvision_v4l2_format[6].supported = 0; /* V4L2_PIX_FMT_YVU420 */
+               usbvision_v4l2_format[7].supported = 0; /* V4L2_PIX_FMT_YUV422P */
+       }
+
+       err_code = usb_register(&usbvision_driver);
+
+       if (err_code == 0) {
+               printk(KERN_INFO DRIVER_DESC " : " USBVISION_VERSION_STRING "\n");
+               PDEBUG(DBG_PROBE, "success");
+       }
+       return err_code;
+}
+
+static void __exit usbvision_exit(void)
+{
+       PDEBUG(DBG_PROBE, "");
+
+       usb_deregister(&usbvision_driver);
+       PDEBUG(DBG_PROBE, "success");
+}
+
+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
new file mode 100644 (file)
index 0000000..43cf61f
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+ * USBVISION.H
+ *  usbvision header file
+ *
+ * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
+ *                         Dwaine Garden <dwainegarden@rogers.com>
+ *
+ *
+ * Report problems to v4l MailingList: linux-media@vger.kernel.org
+ *
+ * This module is part of usbvision driver project.
+ * Updates to driver completed by Dwaine P. Garden
+ * v4l2 conversion by Thierry Merle <thierry.merle@free.fr>
+ *
+ * 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.
+ */
+
+
+#ifndef __LINUX_USBVISION_H
+#define __LINUX_USBVISION_H
+
+#include <linux/list.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <media/v4l2-device.h>
+#include <media/tuner.h>
+#include <linux/videodev2.h>
+
+#define USBVISION_DEBUG                /* Turn on debug messages */
+
+#define USBVISION_PWR_REG              0x00
+       #define USBVISION_SSPND_EN              (1 << 1)
+       #define USBVISION_RES2                  (1 << 2)
+       #define USBVISION_PWR_VID               (1 << 5)
+       #define USBVISION_E2_EN                 (1 << 7)
+#define USBVISION_CONFIG_REG           0x01
+#define USBVISION_ADRS_REG             0x02
+#define USBVISION_ALTER_REG            0x03
+#define USBVISION_FORCE_ALTER_REG      0x04
+#define USBVISION_STATUS_REG           0x05
+#define USBVISION_IOPIN_REG            0x06
+       #define USBVISION_IO_1                  (1 << 0)
+       #define USBVISION_IO_2                  (1 << 1)
+       #define USBVISION_AUDIO_IN              0
+       #define USBVISION_AUDIO_TV              1
+       #define USBVISION_AUDIO_RADIO           2
+       #define USBVISION_AUDIO_MUTE            3
+#define USBVISION_SER_MODE             0x07
+       #define USBVISION_CLK_OUT               (1 << 0)
+       #define USBVISION_DAT_IO                (1 << 1)
+       #define USBVISION_SENS_OUT              (1 << 2)
+       #define USBVISION_SER_MODE_SOFT         (0 << 4)
+       #define USBVISION_SER_MODE_SIO          (1 << 4)
+#define USBVISION_SER_ADRS             0x08
+#define USBVISION_SER_CONT             0x09
+#define USBVISION_SER_DAT1             0x0A
+#define USBVISION_SER_DAT2             0x0B
+#define USBVISION_SER_DAT3             0x0C
+#define USBVISION_SER_DAT4             0x0D
+#define USBVISION_EE_DATA              0x0E
+#define USBVISION_EE_LSBAD             0x0F
+#define USBVISION_EE_CONT              0x10
+#define USBVISION_DRM_CONT                     0x12
+       #define USBVISION_REF                   (1 << 0)
+       #define USBVISION_RES_UR                (1 << 2)
+       #define USBVISION_RES_FDL               (1 << 3)
+       #define USBVISION_RES_VDW               (1 << 4)
+#define USBVISION_DRM_PRM1             0x13
+#define USBVISION_DRM_PRM2             0x14
+#define USBVISION_DRM_PRM3             0x15
+#define USBVISION_DRM_PRM4             0x16
+#define USBVISION_DRM_PRM5             0x17
+#define USBVISION_DRM_PRM6             0x18
+#define USBVISION_DRM_PRM7             0x19
+#define USBVISION_DRM_PRM8             0x1A
+#define USBVISION_VIN_REG1             0x1B
+       #define USBVISION_8_422_SYNC            0x01
+       #define USBVISION_16_422_SYNC           0x02
+       #define USBVISION_VSNC_POL              (1 << 3)
+       #define USBVISION_HSNC_POL              (1 << 4)
+       #define USBVISION_FID_POL               (1 << 5)
+       #define USBVISION_HVALID_PO             (1 << 6)
+       #define USBVISION_VCLK_POL              (1 << 7)
+#define USBVISION_VIN_REG2             0x1C
+       #define USBVISION_AUTO_FID              (1 << 0)
+       #define USBVISION_NONE_INTER            (1 << 1)
+       #define USBVISION_NOHVALID              (1 << 2)
+       #define USBVISION_UV_ID                 (1 << 3)
+       #define USBVISION_FIX_2C                (1 << 4)
+       #define USBVISION_SEND_FID              (1 << 5)
+       #define USBVISION_KEEP_BLANK            (1 << 7)
+#define USBVISION_LXSIZE_I             0x1D
+#define USBVISION_MXSIZE_I             0x1E
+#define USBVISION_LYSIZE_I             0x1F
+#define USBVISION_MYSIZE_I             0x20
+#define USBVISION_LX_OFFST             0x21
+#define USBVISION_MX_OFFST             0x22
+#define USBVISION_LY_OFFST             0x23
+#define USBVISION_MY_OFFST             0x24
+#define USBVISION_FRM_RATE             0x25
+#define USBVISION_LXSIZE_O             0x26
+#define USBVISION_MXSIZE_O             0x27
+#define USBVISION_LYSIZE_O             0x28
+#define USBVISION_MYSIZE_O             0x29
+#define USBVISION_FILT_CONT            0x2A
+#define USBVISION_VO_MODE              0x2B
+#define USBVISION_INTRA_CYC            0x2C
+#define USBVISION_STRIP_SZ             0x2D
+#define USBVISION_FORCE_INTRA          0x2E
+#define USBVISION_FORCE_UP             0x2F
+#define USBVISION_BUF_THR              0x30
+#define USBVISION_DVI_YUV              0x31
+#define USBVISION_AUDIO_CONT           0x32
+#define USBVISION_AUD_PK_LEN           0x33
+#define USBVISION_BLK_PK_LEN           0x34
+#define USBVISION_PCM_THR1             0x38
+#define USBVISION_PCM_THR2             0x39
+#define USBVISION_DIST_THR_L           0x3A
+#define USBVISION_DIST_THR_H           0x3B
+#define USBVISION_MAX_DIST_L           0x3C
+#define USBVISION_MAX_DIST_H           0x3D
+#define USBVISION_OP_CODE              0x33
+
+#define MAX_BYTES_PER_PIXEL            4
+
+#define MIN_FRAME_WIDTH                        64
+#define MAX_USB_WIDTH                  320  /* 384 */
+#define MAX_FRAME_WIDTH                        320  /* 384 */                  /* streching sometimes causes crashes*/
+
+#define MIN_FRAME_HEIGHT               48
+#define MAX_USB_HEIGHT                 240  /* 288 */
+#define MAX_FRAME_HEIGHT               240  /* 288 */                  /* Streching sometimes causes crashes*/
+
+#define MAX_FRAME_SIZE                 (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL)
+#define USBVISION_CLIPMASK_SIZE                (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) /* bytesize of clipmask */
+
+#define USBVISION_URB_FRAMES           32
+
+#define USBVISION_NUM_HEADERMARKER     20
+#define USBVISION_NUMFRAMES            3  /* Maximum number of frames an application can get */
+#define USBVISION_NUMSBUF              2 /* Dimensioning the USB S buffering */
+
+#define USBVISION_POWEROFF_TIME                (3 * HZ)                /* 3 seconds */
+
+
+#define FRAMERATE_MIN  0
+#define FRAMERATE_MAX  31
+
+enum {
+       ISOC_MODE_YUV422 = 0x03,
+       ISOC_MODE_YUV420 = 0x14,
+       ISOC_MODE_COMPRESS = 0x60,
+};
+
+/* This macro restricts an int variable to an inclusive range */
+#define RESTRICT_TO_RANGE(v, mi, ma) \
+       { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
+
+/*
+ * We use macros to do YUV -> RGB conversion because this is
+ * very important for speed and totally unimportant for size.
+ *
+ * YUV -> RGB Conversion
+ * ---------------------
+ *
+ * B = 1.164*(Y-16)                + 2.018*(V-128)
+ * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128)
+ * R = 1.164*(Y-16) + 1.596*(U-128)
+ *
+ * If you fancy integer arithmetics (as you should), hear this:
+ *
+ * 65536*B = 76284*(Y-16)                + 132252*(V-128)
+ * 65536*G = 76284*(Y-16) -  53281*(U-128) -  25625*(V-128)
+ * 65536*R = 76284*(Y-16) + 104595*(U-128)
+ *
+ * Make sure the output values are within [0..255] range.
+ */
+#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x)))
+#define YUV_TO_RGB_BY_THE_BOOK(my, mu, mv, mr, mg, mb) { \
+       int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \
+       mm_y = (my) - 16; \
+       mm_u = (mu) - 128; \
+       mm_v = (mv) - 128; \
+       mm_yc = mm_y * 76284; \
+       mm_b = (mm_yc + 132252 * mm_v) >> 16; \
+       mm_g = (mm_yc - 53281 * mm_u - 25625 * mm_v) >> 16; \
+       mm_r = (mm_yc + 104595 * mm_u) >> 16; \
+       mb = LIMIT_RGB(mm_b); \
+       mg = LIMIT_RGB(mm_g); \
+       mr = LIMIT_RGB(mm_r); \
+}
+
+/* Debugging aid */
+#define USBVISION_SAY_AND_WAIT(what) { \
+       wait_queue_head_t wq; \
+       init_waitqueue_head(&wq); \
+       printk(KERN_INFO "Say: %s\n", what); \
+       interruptible_sleep_on_timeout(&wq, HZ * 3); \
+}
+
+/*
+ * This macro checks if usbvision is still operational. The 'usbvision'
+ * pointer must be valid, usbvision->dev must be valid, we are not
+ * removing the device and the device has not erred on us.
+ */
+#define USBVISION_IS_OPERATIONAL(udevice) (\
+       (udevice != NULL) && \
+       ((udevice)->dev != NULL) && \
+       ((udevice)->last_error == 0) && \
+       (!(udevice)->remove_pending))
+
+#define I2C_USB_ADAP_MAX       16
+
+#define USBVISION_NORMS (V4L2_STD_PAL | V4L2_STD_NTSC | V4L2_STD_SECAM | V4L2_STD_PAL_M)
+
+/* ----------------------------------------------------------------- */
+/* usbvision video structures                                        */
+/* ----------------------------------------------------------------- */
+enum scan_state {
+       scan_state_scanning,    /* Scanning for header */
+       scan_state_lines        /* Parsing lines */
+};
+
+/* Completion states of the data parser */
+enum parse_state {
+       parse_state_continue,   /* Just parse next item */
+       parse_state_next_frame, /* Frame done, send it to V4L */
+       parse_state_out,        /* Not enough data for frame */
+       parse_state_end_parse   /* End parsing */
+};
+
+enum frame_state {
+       frame_state_unused,     /* Unused (no MCAPTURE) */
+       frame_state_ready,      /* Ready to start grabbing */
+       frame_state_grabbing,   /* In the process of being grabbed into */
+       frame_state_done,       /* Finished grabbing, but not been synced yet */
+       frame_state_done_hold,  /* Are syncing or reading */
+       frame_state_error,      /* Something bad happened while processing */
+};
+
+/* stream states */
+enum stream_state {
+       stream_off,             /* Driver streaming is completely OFF */
+       stream_idle,            /* Driver streaming is ready to be put ON by the application */
+       stream_interrupt,       /* Driver streaming must be interrupted */
+       stream_on,              /* Driver streaming is put ON by the application */
+};
+
+enum isoc_state {
+       isoc_state_in_frame,    /* Isoc packet is member of frame */
+       isoc_state_no_frame,    /* Isoc packet is not member of any frame */
+};
+
+struct usb_device;
+
+struct usbvision_sbuf {
+       char *data;
+       struct urb *urb;
+};
+
+#define USBVISION_MAGIC_1                      0x55
+#define USBVISION_MAGIC_2                      0xAA
+#define USBVISION_HEADER_LENGTH                        0x0c
+#define USBVISION_SAA7111_ADDR                 0x48
+#define USBVISION_SAA7113_ADDR                 0x4a
+#define USBVISION_IIC_LRACK                    0x20
+#define USBVISION_IIC_LRNACK                   0x30
+#define USBVISION_FRAME_FORMAT_PARAM_INTRA     (1<<7)
+
+struct usbvision_v4l2_format_st {
+       int             supported;
+       int             bytes_per_pixel;
+       int             depth;
+       int             format;
+       char            *desc;
+};
+#define USBVISION_SUPPORTED_PALETTES ARRAY_SIZE(usbvision_v4l2_format)
+
+struct usbvision_frame_header {
+       unsigned char magic_1;                          /* 0 magic */
+       unsigned char magic_2;                          /* 1  magic */
+       unsigned char header_length;                    /* 2 */
+       unsigned char frame_num;                        /* 3 */
+       unsigned char frame_phase;                      /* 4 */
+       unsigned char frame_latency;                    /* 5 */
+       unsigned char data_format;                      /* 6 */
+       unsigned char format_param;                     /* 7 */
+       unsigned char frame_width_lo;                   /* 8 */
+       unsigned char frame_width_hi;                   /* 9 */
+       unsigned char frame_height_lo;                  /* 10 */
+       unsigned char frame_height_hi;                  /* 11 */
+       __u16 frame_width;                              /* 8 - 9 after endian correction*/
+       __u16 frame_height;                             /* 10 - 11 after endian correction*/
+};
+
+struct usbvision_frame {
+       char *data;                                     /* Frame buffer */
+       struct usbvision_frame_header isoc_header;      /* Header from stream */
+
+       int width;                                      /* Width application is expecting */
+       int height;                                     /* Height */
+       int index;                                      /* Frame index */
+       int frmwidth;                                   /* Width the frame actually is */
+       int frmheight;                                  /* Height */
+
+       volatile int grabstate;                         /* State of grabbing */
+       int scanstate;                                  /* State of scanning */
+
+       struct list_head frame;
+
+       int curline;                                    /* Line of frame we're working on */
+
+       long scanlength;                                /* uncompressed, raw data length of frame */
+       long bytes_read;                                /* amount of scanlength that has been read from data */
+       struct usbvision_v4l2_format_st v4l2_format;    /* format the user needs*/
+       int v4l2_linesize;                              /* bytes for one videoline*/
+       struct timeval timestamp;
+       int sequence;                                   /* How many video frames we send to user */
+};
+
+#define CODEC_SAA7113  7113
+#define CODEC_SAA7111  7111
+#define CODEC_WEBCAM   3000
+#define BRIDGE_NT1003  1003
+#define BRIDGE_NT1004  1004
+#define BRIDGE_NT1005   1005
+
+struct usbvision_device_data_st {
+       __u64 video_norm;
+       const char *model_string;
+       int interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */
+       __u16 codec;
+       unsigned video_channels:3;
+       unsigned audio_channels:2;
+       unsigned radio:1;
+       unsigned vbi:1;
+       unsigned tuner:1;
+       unsigned vin_reg1_override:1;   /* Override default value with */
+       unsigned vin_reg2_override:1;   /* vin_reg1, vin_reg2, etc. */
+       unsigned dvi_yuv_override:1;
+       __u8 vin_reg1;
+       __u8 vin_reg2;
+       __u8 dvi_yuv;
+       __u8 tuner_type;
+       __s16 x_offset;
+       __s16 y_offset;
+};
+
+/* Declared on usbvision-cards.c */
+extern struct usbvision_device_data_st usbvision_device_data[];
+extern struct usb_device_id usbvision_table[];
+
+struct usb_usbvision {
+       struct v4l2_device v4l2_dev;
+       struct video_device *vdev;                                      /* Video Device */
+       struct video_device *rdev;                                      /* Radio Device */
+
+       /* i2c Declaration Section*/
+       struct i2c_adapter i2c_adap;
+       int registered_i2c;
+
+       struct urb *ctrl_urb;
+       unsigned char ctrl_urb_buffer[8];
+       int ctrl_urb_busy;
+       struct usb_ctrlrequest ctrl_urb_setup;
+       wait_queue_head_t ctrl_urb_wq;                                  /* Processes waiting */
+
+       /* configuration part */
+       int have_tuner;
+       int tuner_type;
+       int bridge_type;                                                /* NT1003, NT1004, NT1005 */
+       int radio;
+       int video_inputs;                                               /* # of inputs */
+       unsigned long freq;
+       int audio_mute;
+       int audio_channel;
+       int isoc_mode;                                                  /* format of video data for the usb isoc-transfer */
+       unsigned int nr;                                                /* Number of the device */
+
+       /* Device structure */
+       struct usb_device *dev;
+       /* usb transfer */
+       int num_alt;            /* Number of alternative settings */
+       unsigned int *alt_max_pkt_size; /* array of max_packet_size */
+       unsigned char iface;                                            /* Video interface number */
+       unsigned char iface_alt;                                        /* Alt settings */
+       unsigned char vin_reg2_preset;
+       struct mutex v4l2_lock;
+       struct timer_list power_off_timer;
+       struct work_struct power_off_work;
+       int power;                                                      /* is the device powered on? */
+       int user;                                                       /* user count for exclusive use */
+       int initialized;                                                /* Had we already sent init sequence? */
+       int dev_model;                                                  /* What type of USBVISION device we got? */
+       enum stream_state streaming;                                    /* Are we streaming Isochronous? */
+       int last_error;                                                 /* What calamity struck us? */
+       int curwidth;                                                   /* width of the frame the device is currently set to*/
+       int curheight;                                                  /* height of the frame the device is currently set to*/
+       int stretch_width;                                              /* stretch-factor for frame width (from usb to screen)*/
+       int stretch_height;                                             /* stretch-factor for frame height (from usb to screen)*/
+       char *fbuf;                                                     /* Videodev buffer area for mmap*/
+       int max_frame_size;                                             /* Bytes in one video frame */
+       int fbuf_size;                                                  /* Videodev buffer size */
+       spinlock_t queue_lock;                                          /* spinlock for protecting mods on inqueue and outqueue */
+       struct list_head inqueue, outqueue;                             /* queued frame list and ready to dequeue frame list */
+       wait_queue_head_t wait_frame;                                   /* Processes waiting */
+       wait_queue_head_t wait_stream;                                  /* Processes waiting */
+       struct usbvision_frame *cur_frame;                              /* pointer to current frame, set by usbvision_find_header */
+       struct usbvision_frame frame[USBVISION_NUMFRAMES];              /* frame buffer */
+       int num_frames;                                                 /* number of frames allocated */
+       struct usbvision_sbuf sbuf[USBVISION_NUMSBUF];                  /* S buffering */
+       volatile int remove_pending;                                    /* If set then about to exit */
+
+       /* Scratch space from the Isochronous Pipe.*/
+       unsigned char *scratch;
+       int scratch_read_ptr;
+       int scratch_write_ptr;
+       int scratch_headermarker[USBVISION_NUM_HEADERMARKER];
+       int scratch_headermarker_read_ptr;
+       int scratch_headermarker_write_ptr;
+       enum isoc_state isocstate;
+       struct usbvision_v4l2_format_st palette;
+
+       struct v4l2_capability vcap;                                    /* Video capabilities */
+       unsigned int ctl_input;                                         /* selected input */
+       v4l2_std_id tvnorm_id;                                          /* selected tv norm */
+       unsigned char video_endp;                                       /* 0x82 for USBVISION devices based */
+
+       /* Decompression stuff: */
+       unsigned char *intra_frame_buffer;                              /* Buffer for reference frame */
+       int block_pos;                                                  /* for test only */
+       int request_intra;                                              /* 0 = normal; 1 = intra frame is requested; */
+       int last_isoc_frame_num;                                        /* check for lost isoc frames */
+       int isoc_packet_size;                                           /* need to calculate used_bandwidth */
+       int used_bandwidth;                                             /* used bandwidth 0-100%, need to set compr_level */
+       int compr_level;                                                /* How strong (100) or weak (0) is compression */
+       int last_compr_level;                                           /* How strong (100) or weak (0) was compression */
+       int usb_bandwidth;                                              /* Mbit/s */
+
+       /* Statistics that can be overlayed on the screen */
+       unsigned long isoc_urb_count;                   /* How many URBs we received so far */
+       unsigned long urb_length;                       /* Length of last URB */
+       unsigned long isoc_data_count;                  /* How many bytes we received */
+       unsigned long header_count;                     /* How many frame headers we found */
+       unsigned long scratch_ovf_count;                /* How many times we overflowed scratch */
+       unsigned long isoc_skip_count;                  /* How many empty ISO packets received */
+       unsigned long isoc_err_count;                   /* How many bad ISO packets received */
+       unsigned long isoc_packet_count;                /* How many packets we totally got */
+       unsigned long time_in_irq;                      /* How long do we need for interrupt */
+       int isoc_measure_bandwidth_count;
+       int frame_num;                                  /* How many video frames we send to user */
+       int max_strip_len;                              /* How big is the biggest strip */
+       int comprblock_pos;
+       int strip_len_errors;                           /* How many times was block_pos greater than strip_len */
+       int strip_magic_errors;
+       int strip_line_number_errors;
+       int compr_block_types[4];
+};
+
+static inline struct usb_usbvision *to_usbvision(struct v4l2_device *v4l2_dev)
+{
+       return container_of(v4l2_dev, struct usb_usbvision, v4l2_dev);
+}
+
+#define call_all(usbvision, o, f, args...) \
+       v4l2_device_call_all(&usbvision->v4l2_dev, 0, o, f, ##args)
+
+/* --------------------------------------------------------------- */
+/* defined in usbvision-i2c.c                                      */
+/* i2c-algo-usb declaration                                        */
+/* --------------------------------------------------------------- */
+
+/* ----------------------------------------------------------------------- */
+/* usbvision specific I2C functions                                        */
+/* ----------------------------------------------------------------------- */
+int usbvision_i2c_register(struct usb_usbvision *usbvision);
+int usbvision_i2c_unregister(struct usb_usbvision *usbvision);
+
+/* defined in usbvision-core.c                                      */
+int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg);
+int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
+                       unsigned char value);
+
+int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames);
+void usbvision_frames_free(struct usb_usbvision *usbvision);
+int usbvision_scratch_alloc(struct usb_usbvision *usbvision);
+void usbvision_scratch_free(struct usb_usbvision *usbvision);
+int usbvision_decompress_alloc(struct usb_usbvision *usbvision);
+void usbvision_decompress_free(struct usb_usbvision *usbvision);
+
+int usbvision_setup(struct usb_usbvision *usbvision, int format);
+int usbvision_init_isoc(struct usb_usbvision *usbvision);
+int usbvision_restart_isoc(struct usb_usbvision *usbvision);
+void usbvision_stop_isoc(struct usb_usbvision *usbvision);
+int usbvision_set_alternate(struct usb_usbvision *dev);
+
+int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel);
+int usbvision_audio_off(struct usb_usbvision *usbvision);
+
+int usbvision_begin_streaming(struct usb_usbvision *usbvision);
+void usbvision_empty_framequeues(struct usb_usbvision *dev);
+int usbvision_stream_interrupt(struct usb_usbvision *dev);
+
+int usbvision_muxsel(struct usb_usbvision *usbvision, int channel);
+int usbvision_set_input(struct usb_usbvision *usbvision);
+int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height);
+
+void usbvision_init_power_off_timer(struct usb_usbvision *usbvision);
+void usbvision_set_power_off_timer(struct usb_usbvision *usbvision);
+void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision);
+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/Kconfig b/drivers/media/usb/uvc/Kconfig
new file mode 100644 (file)
index 0000000..541c9f1
--- /dev/null
@@ -0,0 +1,19 @@
+config USB_VIDEO_CLASS
+       tristate "USB Video Class (UVC)"
+       select VIDEOBUF2_VMALLOC
+       ---help---
+         Support for the USB Video Class (UVC).  Currently only video
+         input devices, such as webcams, are supported.
+
+         For more information see: <http://linux-uvc.berlios.de/>
+
+config USB_VIDEO_CLASS_INPUT_EVDEV
+       bool "UVC input events device support"
+       default y
+       depends on USB_VIDEO_CLASS
+       depends on USB_VIDEO_CLASS=INPUT || INPUT=y
+       ---help---
+         This option makes USB Video Class devices register an input device
+         to report button events.
+
+         If you are in doubt, say Y.
diff --git a/drivers/media/usb/uvc/Makefile b/drivers/media/usb/uvc/Makefile
new file mode 100644 (file)
index 0000000..c26d12f
--- /dev/null
@@ -0,0 +1,6 @@
+uvcvideo-objs  := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \
+                 uvc_status.o uvc_isight.o uvc_debugfs.o
+ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
+uvcvideo-objs  += uvc_entity.o
+endif
+obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
new file mode 100644 (file)
index 0000000..f7061a5
--- /dev/null
@@ -0,0 +1,2165 @@
+/*
+ *      uvc_ctrl.c  --  USB Video Class driver - Controls
+ *
+ *      Copyright (C) 2005-2010
+ *          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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+#include <linux/atomic.h>
+#include <media/v4l2-ctrls.h>
+
+#include "uvcvideo.h"
+
+#define UVC_CTRL_DATA_CURRENT  0
+#define UVC_CTRL_DATA_BACKUP   1
+#define UVC_CTRL_DATA_MIN      2
+#define UVC_CTRL_DATA_MAX      3
+#define UVC_CTRL_DATA_RES      4
+#define UVC_CTRL_DATA_DEF      5
+#define UVC_CTRL_DATA_LAST     6
+
+/* ------------------------------------------------------------------------
+ * Controls
+ */
+
+static struct uvc_control_info uvc_ctrls[] = {
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_BRIGHTNESS_CONTROL,
+               .index          = 0,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_CONTRAST_CONTROL,
+               .index          = 1,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_HUE_CONTROL,
+               .index          = 2,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE
+                               | UVC_CTRL_FLAG_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_SATURATION_CONTROL,
+               .index          = 3,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_SHARPNESS_CONTROL,
+               .index          = 4,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_GAMMA_CONTROL,
+               .index          = 5,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
+               .index          = 6,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE
+                               | UVC_CTRL_FLAG_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
+               .index          = 7,
+               .size           = 4,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE
+                               | UVC_CTRL_FLAG_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL,
+               .index          = 8,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_GAIN_CONTROL,
+               .index          = 9,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
+               .index          = 10,
+               .size           = 1,
+               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
+                               | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_HUE_AUTO_CONTROL,
+               .index          = 11,
+               .size           = 1,
+               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
+                               | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
+               .index          = 12,
+               .size           = 1,
+               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
+                               | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
+               .index          = 13,
+               .size           = 1,
+               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
+                               | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_DIGITAL_MULTIPLIER_CONTROL,
+               .index          = 14,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL,
+               .index          = 15,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL,
+               .index          = 16,
+               .size           = 1,
+               .flags          = UVC_CTRL_FLAG_GET_CUR,
+       },
+       {
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_ANALOG_LOCK_STATUS_CONTROL,
+               .index          = 17,
+               .size           = 1,
+               .flags          = UVC_CTRL_FLAG_GET_CUR,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_SCANNING_MODE_CONTROL,
+               .index          = 0,
+               .size           = 1,
+               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
+                               | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_AE_MODE_CONTROL,
+               .index          = 1,
+               .size           = 1,
+               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
+                               | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_GET_RES
+                               | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_AE_PRIORITY_CONTROL,
+               .index          = 2,
+               .size           = 1,
+               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
+                               | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
+               .index          = 3,
+               .size           = 4,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL,
+               .index          = 4,
+               .size           = 1,
+               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_FOCUS_ABSOLUTE_CONTROL,
+               .index          = 5,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE
+                               | UVC_CTRL_FLAG_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_FOCUS_RELATIVE_CONTROL,
+               .index          = 6,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN
+                               | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES
+                               | UVC_CTRL_FLAG_GET_DEF
+                               | UVC_CTRL_FLAG_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_IRIS_ABSOLUTE_CONTROL,
+               .index          = 7,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE
+                               | UVC_CTRL_FLAG_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_IRIS_RELATIVE_CONTROL,
+               .index          = 8,
+               .size           = 1,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_ZOOM_ABSOLUTE_CONTROL,
+               .index          = 9,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE
+                               | UVC_CTRL_FLAG_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_ZOOM_RELATIVE_CONTROL,
+               .index          = 10,
+               .size           = 3,
+               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN
+                               | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES
+                               | UVC_CTRL_FLAG_GET_DEF
+                               | UVC_CTRL_FLAG_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_PANTILT_ABSOLUTE_CONTROL,
+               .index          = 11,
+               .size           = 8,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE
+                               | UVC_CTRL_FLAG_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_PANTILT_RELATIVE_CONTROL,
+               .index          = 12,
+               .size           = 4,
+               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN
+                               | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES
+                               | UVC_CTRL_FLAG_GET_DEF
+                               | UVC_CTRL_FLAG_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_ROLL_ABSOLUTE_CONTROL,
+               .index          = 13,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR
+                               | UVC_CTRL_FLAG_GET_RANGE
+                               | UVC_CTRL_FLAG_RESTORE
+                               | UVC_CTRL_FLAG_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_ROLL_RELATIVE_CONTROL,
+               .index          = 14,
+               .size           = 2,
+               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN
+                               | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES
+                               | UVC_CTRL_FLAG_GET_DEF
+                               | UVC_CTRL_FLAG_AUTO_UPDATE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_FOCUS_AUTO_CONTROL,
+               .index          = 17,
+               .size           = 1,
+               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
+                               | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
+       },
+       {
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_PRIVACY_CONTROL,
+               .index          = 18,
+               .size           = 1,
+               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
+                               | UVC_CTRL_FLAG_RESTORE
+                               | UVC_CTRL_FLAG_AUTO_UPDATE,
+       },
+};
+
+static struct uvc_menu_info power_line_frequency_controls[] = {
+       { 0, "Disabled" },
+       { 1, "50 Hz" },
+       { 2, "60 Hz" },
+};
+
+static struct uvc_menu_info exposure_auto_controls[] = {
+       { 2, "Auto Mode" },
+       { 1, "Manual Mode" },
+       { 4, "Shutter Priority Mode" },
+       { 8, "Aperture Priority Mode" },
+};
+
+static __s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping,
+       __u8 query, const __u8 *data)
+{
+       __s8 zoom = (__s8)data[0];
+
+       switch (query) {
+       case UVC_GET_CUR:
+               return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]);
+
+       case UVC_GET_MIN:
+       case UVC_GET_MAX:
+       case UVC_GET_RES:
+       case UVC_GET_DEF:
+       default:
+               return data[2];
+       }
+}
+
+static void uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping,
+       __s32 value, __u8 *data)
+{
+       data[0] = value == 0 ? 0 : (value > 0) ? 1 : 0xff;
+       data[2] = min((int)abs(value), 0xff);
+}
+
+static struct uvc_control_mapping uvc_ctrl_mappings[] = {
+       {
+               .id             = V4L2_CID_BRIGHTNESS,
+               .name           = "Brightness",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_BRIGHTNESS_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
+       },
+       {
+               .id             = V4L2_CID_CONTRAST,
+               .name           = "Contrast",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_CONTRAST_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_HUE,
+               .name           = "Hue",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_HUE_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
+               .master_id      = V4L2_CID_HUE_AUTO,
+               .master_manual  = 0,
+       },
+       {
+               .id             = V4L2_CID_SATURATION,
+               .name           = "Saturation",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_SATURATION_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_SHARPNESS,
+               .name           = "Sharpness",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_SHARPNESS_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_GAMMA,
+               .name           = "Gamma",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_GAMMA_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_BACKLIGHT_COMPENSATION,
+               .name           = "Backlight Compensation",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_GAIN,
+               .name           = "Gain",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_GAIN_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_POWER_LINE_FREQUENCY,
+               .name           = "Power Line Frequency",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
+               .size           = 2,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_MENU,
+               .data_type      = UVC_CTRL_DATA_TYPE_ENUM,
+               .menu_info      = power_line_frequency_controls,
+               .menu_count     = ARRAY_SIZE(power_line_frequency_controls),
+       },
+       {
+               .id             = V4L2_CID_HUE_AUTO,
+               .name           = "Hue, Auto",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_HUE_AUTO_CONTROL,
+               .size           = 1,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
+               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
+               .slave_ids      = { V4L2_CID_HUE, },
+       },
+       {
+               .id             = V4L2_CID_EXPOSURE_AUTO,
+               .name           = "Exposure, Auto",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_AE_MODE_CONTROL,
+               .size           = 4,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_MENU,
+               .data_type      = UVC_CTRL_DATA_TYPE_BITMASK,
+               .menu_info      = exposure_auto_controls,
+               .menu_count     = ARRAY_SIZE(exposure_auto_controls),
+               .slave_ids      = { V4L2_CID_EXPOSURE_ABSOLUTE, },
+       },
+       {
+               .id             = V4L2_CID_EXPOSURE_AUTO_PRIORITY,
+               .name           = "Exposure, Auto Priority",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_AE_PRIORITY_CONTROL,
+               .size           = 1,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
+               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
+       },
+       {
+               .id             = V4L2_CID_EXPOSURE_ABSOLUTE,
+               .name           = "Exposure (Absolute)",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
+               .size           = 32,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+               .master_id      = V4L2_CID_EXPOSURE_AUTO,
+               .master_manual  = V4L2_EXPOSURE_MANUAL,
+       },
+       {
+               .id             = V4L2_CID_AUTO_WHITE_BALANCE,
+               .name           = "White Balance Temperature, Auto",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
+               .size           = 1,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
+               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
+               .slave_ids      = { V4L2_CID_WHITE_BALANCE_TEMPERATURE, },
+       },
+       {
+               .id             = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
+               .name           = "White Balance Temperature",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+               .master_id      = V4L2_CID_AUTO_WHITE_BALANCE,
+               .master_manual  = 0,
+       },
+       {
+               .id             = V4L2_CID_AUTO_WHITE_BALANCE,
+               .name           = "White Balance Component, Auto",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
+               .size           = 1,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
+               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
+               .slave_ids      = { V4L2_CID_BLUE_BALANCE,
+                                   V4L2_CID_RED_BALANCE },
+       },
+       {
+               .id             = V4L2_CID_BLUE_BALANCE,
+               .name           = "White Balance Blue Component",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
+               .master_id      = V4L2_CID_AUTO_WHITE_BALANCE,
+               .master_manual  = 0,
+       },
+       {
+               .id             = V4L2_CID_RED_BALANCE,
+               .name           = "White Balance Red Component",
+               .entity         = UVC_GUID_UVC_PROCESSING,
+               .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
+               .size           = 16,
+               .offset         = 16,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
+               .master_id      = V4L2_CID_AUTO_WHITE_BALANCE,
+               .master_manual  = 0,
+       },
+       {
+               .id             = V4L2_CID_FOCUS_ABSOLUTE,
+               .name           = "Focus (absolute)",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_FOCUS_ABSOLUTE_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+               .master_id      = V4L2_CID_FOCUS_AUTO,
+               .master_manual  = 0,
+       },
+       {
+               .id             = V4L2_CID_FOCUS_AUTO,
+               .name           = "Focus, Auto",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_FOCUS_AUTO_CONTROL,
+               .size           = 1,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
+               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
+               .slave_ids      = { V4L2_CID_FOCUS_ABSOLUTE, },
+       },
+       {
+               .id             = V4L2_CID_IRIS_ABSOLUTE,
+               .name           = "Iris, Absolute",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_IRIS_ABSOLUTE_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_IRIS_RELATIVE,
+               .name           = "Iris, Relative",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_IRIS_RELATIVE_CONTROL,
+               .size           = 8,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
+       },
+       {
+               .id             = V4L2_CID_ZOOM_ABSOLUTE,
+               .name           = "Zoom, Absolute",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_ZOOM_ABSOLUTE_CONTROL,
+               .size           = 16,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_ZOOM_CONTINUOUS,
+               .name           = "Zoom, Continuous",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_ZOOM_RELATIVE_CONTROL,
+               .size           = 0,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
+               .get            = uvc_ctrl_get_zoom,
+               .set            = uvc_ctrl_set_zoom,
+       },
+       {
+               .id             = V4L2_CID_PAN_ABSOLUTE,
+               .name           = "Pan (Absolute)",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_PANTILT_ABSOLUTE_CONTROL,
+               .size           = 32,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_TILT_ABSOLUTE,
+               .name           = "Tilt (Absolute)",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_PANTILT_ABSOLUTE_CONTROL,
+               .size           = 32,
+               .offset         = 32,
+               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
+               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
+       },
+       {
+               .id             = V4L2_CID_PRIVACY,
+               .name           = "Privacy",
+               .entity         = UVC_GUID_UVC_CAMERA,
+               .selector       = UVC_CT_PRIVACY_CONTROL,
+               .size           = 1,
+               .offset         = 0,
+               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
+               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
+       },
+};
+
+/* ------------------------------------------------------------------------
+ * Utility functions
+ */
+
+static inline __u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id)
+{
+       return ctrl->uvc_data + id * ctrl->info.size;
+}
+
+static inline int uvc_test_bit(const __u8 *data, int bit)
+{
+       return (data[bit >> 3] >> (bit & 7)) & 1;
+}
+
+static inline void uvc_clear_bit(__u8 *data, int bit)
+{
+       data[bit >> 3] &= ~(1 << (bit & 7));
+}
+
+/* Extract the bit string specified by mapping->offset and mapping->size
+ * from the little-endian data stored at 'data' and return the result as
+ * a signed 32bit integer. Sign extension will be performed if the mapping
+ * references a signed data type.
+ */
+static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
+       __u8 query, const __u8 *data)
+{
+       int bits = mapping->size;
+       int offset = mapping->offset;
+       __s32 value = 0;
+       __u8 mask;
+
+       data += offset / 8;
+       offset &= 7;
+       mask = ((1LL << bits) - 1) << offset;
+
+       for (; bits > 0; data++) {
+               __u8 byte = *data & mask;
+               value |= offset > 0 ? (byte >> offset) : (byte << (-offset));
+               bits -= 8 - (offset > 0 ? offset : 0);
+               offset -= 8;
+               mask = (1 << bits) - 1;
+       }
+
+       /* Sign-extend the value if needed. */
+       if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED)
+               value |= -(value & (1 << (mapping->size - 1)));
+
+       return value;
+}
+
+/* Set the bit string specified by mapping->offset and mapping->size
+ * in the little-endian data stored at 'data' to the value 'value'.
+ */
+static void uvc_set_le_value(struct uvc_control_mapping *mapping,
+       __s32 value, __u8 *data)
+{
+       int bits = mapping->size;
+       int offset = mapping->offset;
+       __u8 mask;
+
+       /* According to the v4l2 spec, writing any value to a button control
+        * should result in the action belonging to the button control being
+        * triggered. UVC devices however want to see a 1 written -> override
+        * value.
+        */
+       if (mapping->v4l2_type == V4L2_CTRL_TYPE_BUTTON)
+               value = -1;
+
+       data += offset / 8;
+       offset &= 7;
+
+       for (; bits > 0; data++) {
+               mask = ((1LL << bits) - 1) << offset;
+               *data = (*data & ~mask) | ((value << offset) & mask);
+               value >>= offset ? offset : 8;
+               bits -= 8 - offset;
+               offset = 0;
+       }
+}
+
+/* ------------------------------------------------------------------------
+ * Terminal and unit management
+ */
+
+static const __u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING;
+static const __u8 uvc_camera_guid[16] = UVC_GUID_UVC_CAMERA;
+static const __u8 uvc_media_transport_input_guid[16] =
+       UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT;
+
+static int uvc_entity_match_guid(const struct uvc_entity *entity,
+       const __u8 guid[16])
+{
+       switch (UVC_ENTITY_TYPE(entity)) {
+       case UVC_ITT_CAMERA:
+               return memcmp(uvc_camera_guid, guid, 16) == 0;
+
+       case UVC_ITT_MEDIA_TRANSPORT_INPUT:
+               return memcmp(uvc_media_transport_input_guid, guid, 16) == 0;
+
+       case UVC_VC_PROCESSING_UNIT:
+               return memcmp(uvc_processing_guid, guid, 16) == 0;
+
+       case UVC_VC_EXTENSION_UNIT:
+               return memcmp(entity->extension.guidExtensionCode,
+                             guid, 16) == 0;
+
+       default:
+               return 0;
+       }
+}
+
+/* ------------------------------------------------------------------------
+ * UVC Controls
+ */
+
+static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id,
+       struct uvc_control_mapping **mapping, struct uvc_control **control,
+       int next)
+{
+       struct uvc_control *ctrl;
+       struct uvc_control_mapping *map;
+       unsigned int i;
+
+       if (entity == NULL)
+               return;
+
+       for (i = 0; i < entity->ncontrols; ++i) {
+               ctrl = &entity->controls[i];
+               if (!ctrl->initialized)
+                       continue;
+
+               list_for_each_entry(map, &ctrl->info.mappings, list) {
+                       if ((map->id == v4l2_id) && !next) {
+                               *control = ctrl;
+                               *mapping = map;
+                               return;
+                       }
+
+                       if ((*mapping == NULL || (*mapping)->id > map->id) &&
+                           (map->id > v4l2_id) && next) {
+                               *control = ctrl;
+                               *mapping = map;
+                       }
+               }
+       }
+}
+
+static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
+       __u32 v4l2_id, struct uvc_control_mapping **mapping)
+{
+       struct uvc_control *ctrl = NULL;
+       struct uvc_entity *entity;
+       int next = v4l2_id & V4L2_CTRL_FLAG_NEXT_CTRL;
+
+       *mapping = NULL;
+
+       /* Mask the query flags. */
+       v4l2_id &= V4L2_CTRL_ID_MASK;
+
+       /* Find the control. */
+       list_for_each_entry(entity, &chain->entities, chain) {
+               __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next);
+               if (ctrl && !next)
+                       return ctrl;
+       }
+
+       if (ctrl == NULL && !next)
+               uvc_trace(UVC_TRACE_CONTROL, "Control 0x%08x not found.\n",
+                               v4l2_id);
+
+       return ctrl;
+}
+
+static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain,
+       struct uvc_control *ctrl)
+{
+       int ret;
+
+       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) {
+               ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id,
+                                    chain->dev->intfnum, ctrl->info.selector,
+                                    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF),
+                                    ctrl->info.size);
+               if (ret < 0)
+                       return ret;
+       }
+
+       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) {
+               ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id,
+                                    chain->dev->intfnum, ctrl->info.selector,
+                                    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN),
+                                    ctrl->info.size);
+               if (ret < 0)
+                       return ret;
+       }
+       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) {
+               ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id,
+                                    chain->dev->intfnum, ctrl->info.selector,
+                                    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX),
+                                    ctrl->info.size);
+               if (ret < 0)
+                       return ret;
+       }
+       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) {
+               ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id,
+                                    chain->dev->intfnum, ctrl->info.selector,
+                                    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES),
+                                    ctrl->info.size);
+               if (ret < 0) {
+                       if (UVC_ENTITY_TYPE(ctrl->entity) !=
+                           UVC_VC_EXTENSION_UNIT)
+                               return ret;
+
+                       /* GET_RES is mandatory for XU controls, but some
+                        * cameras still choke on it. Ignore errors and set the
+                        * resolution value to zero.
+                        */
+                       uvc_warn_once(chain->dev, UVC_WARN_XU_GET_RES,
+                                     "UVC non compliance - GET_RES failed on "
+                                     "an XU control. Enabling workaround.\n");
+                       memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), 0,
+                              ctrl->info.size);
+               }
+       }
+
+       ctrl->cached = 1;
+       return 0;
+}
+
+static int __uvc_ctrl_get(struct uvc_video_chain *chain,
+       struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
+       s32 *value)
+{
+       struct uvc_menu_info *menu;
+       unsigned int i;
+       int ret;
+
+       if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
+               return -EINVAL;
+
+       if (!ctrl->loaded) {
+               ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id,
+                               chain->dev->intfnum, ctrl->info.selector,
+                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+                               ctrl->info.size);
+               if (ret < 0)
+                       return ret;
+
+               ctrl->loaded = 1;
+       }
+
+       *value = mapping->get(mapping, UVC_GET_CUR,
+               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
+
+       if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
+               menu = mapping->menu_info;
+               for (i = 0; i < mapping->menu_count; ++i, ++menu) {
+                       if (menu->value == *value) {
+                               *value = i;
+                               break;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
+       struct uvc_control *ctrl,
+       struct uvc_control_mapping *mapping,
+       struct v4l2_queryctrl *v4l2_ctrl)
+{
+       struct uvc_control_mapping *master_map = NULL;
+       struct uvc_control *master_ctrl = NULL;
+       struct uvc_menu_info *menu;
+       unsigned int i;
+
+       memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl);
+       v4l2_ctrl->id = mapping->id;
+       v4l2_ctrl->type = mapping->v4l2_type;
+       strlcpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name);
+       v4l2_ctrl->flags = 0;
+
+       if (!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR))
+               v4l2_ctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
+       if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR))
+               v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+       if (mapping->master_id)
+               __uvc_find_control(ctrl->entity, mapping->master_id,
+                                  &master_map, &master_ctrl, 0);
+       if (master_ctrl && (master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) {
+               s32 val;
+               int ret = __uvc_ctrl_get(chain, master_ctrl, master_map, &val);
+               if (ret < 0)
+                       return ret;
+
+               if (val != mapping->master_manual)
+                               v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+       }
+
+       if (!ctrl->cached) {
+               int ret = uvc_ctrl_populate_cache(chain, ctrl);
+               if (ret < 0)
+                       return ret;
+       }
+
+       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) {
+               v4l2_ctrl->default_value = mapping->get(mapping, UVC_GET_DEF,
+                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF));
+       }
+
+       switch (mapping->v4l2_type) {
+       case V4L2_CTRL_TYPE_MENU:
+               v4l2_ctrl->minimum = 0;
+               v4l2_ctrl->maximum = mapping->menu_count - 1;
+               v4l2_ctrl->step = 1;
+
+               menu = mapping->menu_info;
+               for (i = 0; i < mapping->menu_count; ++i, ++menu) {
+                       if (menu->value == v4l2_ctrl->default_value) {
+                               v4l2_ctrl->default_value = i;
+                               break;
+                       }
+               }
+
+               return 0;
+
+       case V4L2_CTRL_TYPE_BOOLEAN:
+               v4l2_ctrl->minimum = 0;
+               v4l2_ctrl->maximum = 1;
+               v4l2_ctrl->step = 1;
+               return 0;
+
+       case V4L2_CTRL_TYPE_BUTTON:
+               v4l2_ctrl->minimum = 0;
+               v4l2_ctrl->maximum = 0;
+               v4l2_ctrl->step = 0;
+               return 0;
+
+       default:
+               break;
+       }
+
+       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN)
+               v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN,
+                                    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
+
+       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX)
+               v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX,
+                                    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
+
+       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)
+               v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES,
+                                 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
+
+       return 0;
+}
+
+int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
+       struct v4l2_queryctrl *v4l2_ctrl)
+{
+       struct uvc_control *ctrl;
+       struct uvc_control_mapping *mapping;
+       int ret;
+
+       ret = mutex_lock_interruptible(&chain->ctrl_mutex);
+       if (ret < 0)
+               return -ERESTARTSYS;
+
+       ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping);
+       if (ctrl == NULL) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       ret = __uvc_query_v4l2_ctrl(chain, ctrl, mapping, v4l2_ctrl);
+done:
+       mutex_unlock(&chain->ctrl_mutex);
+       return ret;
+}
+
+/*
+ * Mapping V4L2 controls to UVC controls can be straighforward if done well.
+ * Most of the UVC controls exist in V4L2, and can be mapped directly. Some
+ * must be grouped (for instance the Red Balance, Blue Balance and Do White
+ * Balance V4L2 controls use the White Balance Component UVC control) or
+ * otherwise translated. The approach we take here is to use a translation
+ * table for the controls that can be mapped directly, and handle the others
+ * manually.
+ */
+int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
+       struct v4l2_querymenu *query_menu)
+{
+       struct uvc_menu_info *menu_info;
+       struct uvc_control_mapping *mapping;
+       struct uvc_control *ctrl;
+       u32 index = query_menu->index;
+       u32 id = query_menu->id;
+       int ret;
+
+       memset(query_menu, 0, sizeof(*query_menu));
+       query_menu->id = id;
+       query_menu->index = index;
+
+       ret = mutex_lock_interruptible(&chain->ctrl_mutex);
+       if (ret < 0)
+               return -ERESTARTSYS;
+
+       ctrl = uvc_find_control(chain, query_menu->id, &mapping);
+       if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if (query_menu->index >= mapping->menu_count) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       menu_info = &mapping->menu_info[query_menu->index];
+
+       if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK &&
+           (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) {
+               s32 bitmap;
+
+               if (!ctrl->cached) {
+                       ret = uvc_ctrl_populate_cache(chain, ctrl);
+                       if (ret < 0)
+                               goto done;
+               }
+
+               bitmap = mapping->get(mapping, UVC_GET_RES,
+                                     uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
+               if (!(bitmap & menu_info->value)) {
+                       ret = -EINVAL;
+                       goto done;
+               }
+       }
+
+       strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
+
+done:
+       mutex_unlock(&chain->ctrl_mutex);
+       return ret;
+}
+
+/* --------------------------------------------------------------------------
+ * Ctrl event handling
+ */
+
+static void uvc_ctrl_fill_event(struct uvc_video_chain *chain,
+       struct v4l2_event *ev,
+       struct uvc_control *ctrl,
+       struct uvc_control_mapping *mapping,
+       s32 value, u32 changes)
+{
+       struct v4l2_queryctrl v4l2_ctrl;
+
+       __uvc_query_v4l2_ctrl(chain, ctrl, mapping, &v4l2_ctrl);
+
+       memset(ev->reserved, 0, sizeof(ev->reserved));
+       ev->type = V4L2_EVENT_CTRL;
+       ev->id = v4l2_ctrl.id;
+       ev->u.ctrl.value = value;
+       ev->u.ctrl.changes = changes;
+       ev->u.ctrl.type = v4l2_ctrl.type;
+       ev->u.ctrl.flags = v4l2_ctrl.flags;
+       ev->u.ctrl.minimum = v4l2_ctrl.minimum;
+       ev->u.ctrl.maximum = v4l2_ctrl.maximum;
+       ev->u.ctrl.step = v4l2_ctrl.step;
+       ev->u.ctrl.default_value = v4l2_ctrl.default_value;
+}
+
+static void uvc_ctrl_send_event(struct uvc_fh *handle,
+       struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
+       s32 value, u32 changes)
+{
+       struct v4l2_subscribed_event *sev;
+       struct v4l2_event ev;
+
+       if (list_empty(&mapping->ev_subs))
+               return;
+
+       uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, value, changes);
+
+       list_for_each_entry(sev, &mapping->ev_subs, node) {
+               if (sev->fh && (sev->fh != &handle->vfh ||
+                   (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK) ||
+                   (changes & V4L2_EVENT_CTRL_CH_FLAGS)))
+                       v4l2_event_queue_fh(sev->fh, &ev);
+       }
+}
+
+static void uvc_ctrl_send_slave_event(struct uvc_fh *handle,
+       struct uvc_control *master, u32 slave_id,
+       const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
+{
+       struct uvc_control_mapping *mapping = NULL;
+       struct uvc_control *ctrl = NULL;
+       u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
+       unsigned int i;
+       s32 val = 0;
+
+       /*
+        * We can skip sending an event for the slave if the slave
+        * is being modified in the same transaction.
+        */
+       for (i = 0; i < xctrls_count; i++) {
+               if (xctrls[i].id == slave_id)
+                       return;
+       }
+
+       __uvc_find_control(master->entity, slave_id, &mapping, &ctrl, 0);
+       if (ctrl == NULL)
+               return;
+
+       if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0)
+               changes |= V4L2_EVENT_CTRL_CH_VALUE;
+
+       uvc_ctrl_send_event(handle, ctrl, mapping, val, changes);
+}
+
+static void uvc_ctrl_send_events(struct uvc_fh *handle,
+       const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
+{
+       struct uvc_control_mapping *mapping;
+       struct uvc_control *ctrl;
+       u32 changes = V4L2_EVENT_CTRL_CH_VALUE;
+       unsigned int i;
+       unsigned int j;
+
+       for (i = 0; i < xctrls_count; ++i) {
+               ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping);
+
+               for (j = 0; j < ARRAY_SIZE(mapping->slave_ids); ++j) {
+                       if (!mapping->slave_ids[j])
+                               break;
+                       uvc_ctrl_send_slave_event(handle, ctrl,
+                                                 mapping->slave_ids[j],
+                                                 xctrls, xctrls_count);
+               }
+
+               /*
+                * If the master is being modified in the same transaction
+                * flags may change too.
+                */
+               if (mapping->master_id) {
+                       for (j = 0; j < xctrls_count; j++) {
+                               if (xctrls[j].id == mapping->master_id) {
+                                       changes |= V4L2_EVENT_CTRL_CH_FLAGS;
+                                       break;
+                               }
+                       }
+               }
+
+               uvc_ctrl_send_event(handle, ctrl, mapping, xctrls[i].value,
+                                   changes);
+       }
+}
+
+static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
+{
+       struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh);
+       struct uvc_control_mapping *mapping;
+       struct uvc_control *ctrl;
+       int ret;
+
+       ret = mutex_lock_interruptible(&handle->chain->ctrl_mutex);
+       if (ret < 0)
+               return -ERESTARTSYS;
+
+       ctrl = uvc_find_control(handle->chain, sev->id, &mapping);
+       if (ctrl == NULL) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       list_add_tail(&sev->node, &mapping->ev_subs);
+       if (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL) {
+               struct v4l2_event ev;
+               u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
+               s32 val = 0;
+
+               if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0)
+                       changes |= V4L2_EVENT_CTRL_CH_VALUE;
+
+               uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val,
+                                   changes);
+               /* Mark the queue as active, allowing this initial
+                  event to be accepted. */
+               sev->elems = elems;
+               v4l2_event_queue_fh(sev->fh, &ev);
+       }
+
+done:
+       mutex_unlock(&handle->chain->ctrl_mutex);
+       return ret;
+}
+
+static void uvc_ctrl_del_event(struct v4l2_subscribed_event *sev)
+{
+       struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh);
+
+       mutex_lock(&handle->chain->ctrl_mutex);
+       list_del(&sev->node);
+       mutex_unlock(&handle->chain->ctrl_mutex);
+}
+
+const struct v4l2_subscribed_event_ops uvc_ctrl_sub_ev_ops = {
+       .add = uvc_ctrl_add_event,
+       .del = uvc_ctrl_del_event,
+       .replace = v4l2_ctrl_replace,
+       .merge = v4l2_ctrl_merge,
+};
+
+/* --------------------------------------------------------------------------
+ * Control transactions
+ *
+ * To make extended set operations as atomic as the hardware allows, controls
+ * are handled using begin/commit/rollback operations.
+ *
+ * At the beginning of a set request, uvc_ctrl_begin should be called to
+ * initialize the request. This function acquires the control lock.
+ *
+ * When setting a control, the new value is stored in the control data field
+ * at position UVC_CTRL_DATA_CURRENT. The control is then marked as dirty for
+ * later processing. If the UVC and V4L2 control sizes differ, the current
+ * value is loaded from the hardware before storing the new value in the data
+ * field.
+ *
+ * After processing all controls in the transaction, uvc_ctrl_commit or
+ * uvc_ctrl_rollback must be called to apply the pending changes to the
+ * hardware or revert them. When applying changes, all controls marked as
+ * dirty will be modified in the UVC device, and the dirty flag will be
+ * cleared. When reverting controls, the control data field
+ * UVC_CTRL_DATA_CURRENT is reverted to its previous value
+ * (UVC_CTRL_DATA_BACKUP) for all dirty controls. Both functions release the
+ * control lock.
+ */
+int uvc_ctrl_begin(struct uvc_video_chain *chain)
+{
+       return mutex_lock_interruptible(&chain->ctrl_mutex) ? -ERESTARTSYS : 0;
+}
+
+static int uvc_ctrl_commit_entity(struct uvc_device *dev,
+       struct uvc_entity *entity, int rollback)
+{
+       struct uvc_control *ctrl;
+       unsigned int i;
+       int ret;
+
+       if (entity == NULL)
+               return 0;
+
+       for (i = 0; i < entity->ncontrols; ++i) {
+               ctrl = &entity->controls[i];
+               if (!ctrl->initialized)
+                       continue;
+
+               /* Reset the loaded flag for auto-update controls that were
+                * marked as loaded in uvc_ctrl_get/uvc_ctrl_set to prevent
+                * uvc_ctrl_get from using the cached value, and for write-only
+                * controls to prevent uvc_ctrl_set from setting bits not
+                * explicitly set by the user.
+                */
+               if (ctrl->info.flags & UVC_CTRL_FLAG_AUTO_UPDATE ||
+                   !(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR))
+                       ctrl->loaded = 0;
+
+               if (!ctrl->dirty)
+                       continue;
+
+               if (!rollback)
+                       ret = uvc_query_ctrl(dev, UVC_SET_CUR, ctrl->entity->id,
+                               dev->intfnum, ctrl->info.selector,
+                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+                               ctrl->info.size);
+               else
+                       ret = 0;
+
+               if (rollback || ret < 0)
+                       memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+                              uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
+                              ctrl->info.size);
+
+               ctrl->dirty = 0;
+
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback,
+                     const struct v4l2_ext_control *xctrls,
+                     unsigned int xctrls_count)
+{
+       struct uvc_video_chain *chain = handle->chain;
+       struct uvc_entity *entity;
+       int ret = 0;
+
+       /* Find the control. */
+       list_for_each_entry(entity, &chain->entities, chain) {
+               ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback);
+               if (ret < 0)
+                       goto done;
+       }
+
+       if (!rollback)
+               uvc_ctrl_send_events(handle, xctrls, xctrls_count);
+done:
+       mutex_unlock(&chain->ctrl_mutex);
+       return ret;
+}
+
+int uvc_ctrl_get(struct uvc_video_chain *chain,
+       struct v4l2_ext_control *xctrl)
+{
+       struct uvc_control *ctrl;
+       struct uvc_control_mapping *mapping;
+
+       ctrl = uvc_find_control(chain, xctrl->id, &mapping);
+       if (ctrl == NULL)
+               return -EINVAL;
+
+       return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value);
+}
+
+int uvc_ctrl_set(struct uvc_video_chain *chain,
+       struct v4l2_ext_control *xctrl)
+{
+       struct uvc_control *ctrl;
+       struct uvc_control_mapping *mapping;
+       s32 value;
+       u32 step;
+       s32 min;
+       s32 max;
+       int ret;
+
+       ctrl = uvc_find_control(chain, xctrl->id, &mapping);
+       if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) == 0)
+               return -EINVAL;
+
+       /* Clamp out of range values. */
+       switch (mapping->v4l2_type) {
+       case V4L2_CTRL_TYPE_INTEGER:
+               if (!ctrl->cached) {
+                       ret = uvc_ctrl_populate_cache(chain, ctrl);
+                       if (ret < 0)
+                               return ret;
+               }
+
+               min = mapping->get(mapping, UVC_GET_MIN,
+                                  uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
+               max = mapping->get(mapping, UVC_GET_MAX,
+                                  uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
+               step = mapping->get(mapping, UVC_GET_RES,
+                                   uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
+               if (step == 0)
+                       step = 1;
+
+               xctrl->value = min + (xctrl->value - min + step/2) / step * step;
+               xctrl->value = clamp(xctrl->value, min, max);
+               value = xctrl->value;
+               break;
+
+       case V4L2_CTRL_TYPE_BOOLEAN:
+               xctrl->value = clamp(xctrl->value, 0, 1);
+               value = xctrl->value;
+               break;
+
+       case V4L2_CTRL_TYPE_MENU:
+               if (xctrl->value < 0 || xctrl->value >= mapping->menu_count)
+                       return -ERANGE;
+               value = mapping->menu_info[xctrl->value].value;
+
+               /* Valid menu indices are reported by the GET_RES request for
+                * UVC controls that support it.
+                */
+               if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK &&
+                   (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) {
+                       if (!ctrl->cached) {
+                               ret = uvc_ctrl_populate_cache(chain, ctrl);
+                               if (ret < 0)
+                                       return ret;
+                       }
+
+                       step = mapping->get(mapping, UVC_GET_RES,
+                                       uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
+                       if (!(step & value))
+                               return -ERANGE;
+               }
+
+               break;
+
+       default:
+               value = xctrl->value;
+               break;
+       }
+
+       /* If the mapping doesn't span the whole UVC control, the current value
+        * needs to be loaded from the device to perform the read-modify-write
+        * operation.
+        */
+       if (!ctrl->loaded && (ctrl->info.size * 8) != mapping->size) {
+               if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) {
+                       memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+                               0, ctrl->info.size);
+               } else {
+                       ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
+                               ctrl->entity->id, chain->dev->intfnum,
+                               ctrl->info.selector,
+                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+                               ctrl->info.size);
+                       if (ret < 0)
+                               return ret;
+               }
+
+               ctrl->loaded = 1;
+       }
+
+       /* Backup the current value in case we need to rollback later. */
+       if (!ctrl->dirty) {
+               memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
+                      uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
+                      ctrl->info.size);
+       }
+
+       mapping->set(mapping, value,
+               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
+
+       ctrl->dirty = 1;
+       ctrl->modified = 1;
+       return 0;
+}
+
+/* --------------------------------------------------------------------------
+ * Dynamic controls
+ */
+
+static void uvc_ctrl_fixup_xu_info(struct uvc_device *dev,
+       const struct uvc_control *ctrl, struct uvc_control_info *info)
+{
+       struct uvc_ctrl_fixup {
+               struct usb_device_id id;
+               u8 entity;
+               u8 selector;
+               u8 flags;
+       };
+
+       static const struct uvc_ctrl_fixup fixups[] = {
+               { { USB_DEVICE(0x046d, 0x08c2) }, 9, 1,
+                       UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
+                       UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
+                       UVC_CTRL_FLAG_AUTO_UPDATE },
+               { { USB_DEVICE(0x046d, 0x08cc) }, 9, 1,
+                       UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
+                       UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
+                       UVC_CTRL_FLAG_AUTO_UPDATE },
+               { { USB_DEVICE(0x046d, 0x0994) }, 9, 1,
+                       UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
+                       UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
+                       UVC_CTRL_FLAG_AUTO_UPDATE },
+       };
+
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(fixups); ++i) {
+               if (!usb_match_one_id(dev->intf, &fixups[i].id))
+                       continue;
+
+               if (fixups[i].entity == ctrl->entity->id &&
+                   fixups[i].selector == info->selector) {
+                       info->flags = fixups[i].flags;
+                       return;
+               }
+       }
+}
+
+/*
+ * Query control information (size and flags) for XU controls.
+ */
+static int uvc_ctrl_fill_xu_info(struct uvc_device *dev,
+       const struct uvc_control *ctrl, struct uvc_control_info *info)
+{
+       u8 *data;
+       int ret;
+
+       data = kmalloc(2, GFP_KERNEL);
+       if (data == NULL)
+               return -ENOMEM;
+
+       memcpy(info->entity, ctrl->entity->extension.guidExtensionCode,
+              sizeof(info->entity));
+       info->index = ctrl->index;
+       info->selector = ctrl->index + 1;
+
+       /* Query and verify the control length (GET_LEN) */
+       ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, dev->intfnum,
+                            info->selector, data, 2);
+       if (ret < 0) {
+               uvc_trace(UVC_TRACE_CONTROL,
+                         "GET_LEN failed on control %pUl/%u (%d).\n",
+                          info->entity, info->selector, ret);
+               goto done;
+       }
+
+       info->size = le16_to_cpup((__le16 *)data);
+
+       /* Query the control information (GET_INFO) */
+       ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, dev->intfnum,
+                            info->selector, data, 1);
+       if (ret < 0) {
+               uvc_trace(UVC_TRACE_CONTROL,
+                         "GET_INFO failed on control %pUl/%u (%d).\n",
+                         info->entity, info->selector, ret);
+               goto done;
+       }
+
+       info->flags = UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX
+                   | UVC_CTRL_FLAG_GET_RES | UVC_CTRL_FLAG_GET_DEF
+                   | (data[0] & UVC_CONTROL_CAP_GET ?
+                      UVC_CTRL_FLAG_GET_CUR : 0)
+                   | (data[0] & UVC_CONTROL_CAP_SET ?
+                      UVC_CTRL_FLAG_SET_CUR : 0)
+                   | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ?
+                      UVC_CTRL_FLAG_AUTO_UPDATE : 0);
+
+       uvc_ctrl_fixup_xu_info(dev, ctrl, info);
+
+       uvc_trace(UVC_TRACE_CONTROL, "XU control %pUl/%u queried: len %u, "
+                 "flags { get %u set %u auto %u }.\n",
+                 info->entity, info->selector, info->size,
+                 (info->flags & UVC_CTRL_FLAG_GET_CUR) ? 1 : 0,
+                 (info->flags & UVC_CTRL_FLAG_SET_CUR) ? 1 : 0,
+                 (info->flags & UVC_CTRL_FLAG_AUTO_UPDATE) ? 1 : 0);
+
+done:
+       kfree(data);
+       return ret;
+}
+
+static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl,
+       const struct uvc_control_info *info);
+
+static int uvc_ctrl_init_xu_ctrl(struct uvc_device *dev,
+       struct uvc_control *ctrl)
+{
+       struct uvc_control_info info;
+       int ret;
+
+       if (ctrl->initialized)
+               return 0;
+
+       ret = uvc_ctrl_fill_xu_info(dev, ctrl, &info);
+       if (ret < 0)
+               return ret;
+
+       ret = uvc_ctrl_add_info(dev, ctrl, &info);
+       if (ret < 0)
+               uvc_trace(UVC_TRACE_CONTROL, "Failed to initialize control "
+                         "%pUl/%u on device %s entity %u\n", info.entity,
+                         info.selector, dev->udev->devpath, ctrl->entity->id);
+
+       return ret;
+}
+
+int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
+       struct uvc_xu_control_query *xqry)
+{
+       struct uvc_entity *entity;
+       struct uvc_control *ctrl;
+       unsigned int i, found = 0;
+       __u32 reqflags;
+       __u16 size;
+       __u8 *data = NULL;
+       int ret;
+
+       /* Find the extension unit. */
+       list_for_each_entry(entity, &chain->entities, chain) {
+               if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT &&
+                   entity->id == xqry->unit)
+                       break;
+       }
+
+       if (entity->id != xqry->unit) {
+               uvc_trace(UVC_TRACE_CONTROL, "Extension unit %u not found.\n",
+                       xqry->unit);
+               return -ENOENT;
+       }
+
+       /* Find the control and perform delayed initialization if needed. */
+       for (i = 0; i < entity->ncontrols; ++i) {
+               ctrl = &entity->controls[i];
+               if (ctrl->index == xqry->selector - 1) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (!found) {
+               uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u not found.\n",
+                       entity->extension.guidExtensionCode, xqry->selector);
+               return -ENOENT;
+       }
+
+       if (mutex_lock_interruptible(&chain->ctrl_mutex))
+               return -ERESTARTSYS;
+
+       ret = uvc_ctrl_init_xu_ctrl(chain->dev, ctrl);
+       if (ret < 0) {
+               ret = -ENOENT;
+               goto done;
+       }
+
+       /* Validate the required buffer size and flags for the request */
+       reqflags = 0;
+       size = ctrl->info.size;
+
+       switch (xqry->query) {
+       case UVC_GET_CUR:
+               reqflags = UVC_CTRL_FLAG_GET_CUR;
+               break;
+       case UVC_GET_MIN:
+               reqflags = UVC_CTRL_FLAG_GET_MIN;
+               break;
+       case UVC_GET_MAX:
+               reqflags = UVC_CTRL_FLAG_GET_MAX;
+               break;
+       case UVC_GET_DEF:
+               reqflags = UVC_CTRL_FLAG_GET_DEF;
+               break;
+       case UVC_GET_RES:
+               reqflags = UVC_CTRL_FLAG_GET_RES;
+               break;
+       case UVC_SET_CUR:
+               reqflags = UVC_CTRL_FLAG_SET_CUR;
+               break;
+       case UVC_GET_LEN:
+               size = 2;
+               break;
+       case UVC_GET_INFO:
+               size = 1;
+               break;
+       default:
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if (size != xqry->size) {
+               ret = -ENOBUFS;
+               goto done;
+       }
+
+       if (reqflags && !(ctrl->info.flags & reqflags)) {
+               ret = -EBADRQC;
+               goto done;
+       }
+
+       data = kmalloc(size, GFP_KERNEL);
+       if (data == NULL) {
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       if (xqry->query == UVC_SET_CUR &&
+           copy_from_user(data, xqry->data, size)) {
+               ret = -EFAULT;
+               goto done;
+       }
+
+       ret = uvc_query_ctrl(chain->dev, xqry->query, xqry->unit,
+                            chain->dev->intfnum, xqry->selector, data, size);
+       if (ret < 0)
+               goto done;
+
+       if (xqry->query != UVC_SET_CUR &&
+           copy_to_user(xqry->data, data, size))
+               ret = -EFAULT;
+done:
+       kfree(data);
+       mutex_unlock(&chain->ctrl_mutex);
+       return ret;
+}
+
+/* --------------------------------------------------------------------------
+ * Suspend/resume
+ */
+
+/*
+ * Restore control values after resume, skipping controls that haven't been
+ * changed.
+ *
+ * TODO
+ * - Don't restore modified controls that are back to their default value.
+ * - Handle restore order (Auto-Exposure Mode should be restored before
+ *   Exposure Time).
+ */
+int uvc_ctrl_resume_device(struct uvc_device *dev)
+{
+       struct uvc_control *ctrl;
+       struct uvc_entity *entity;
+       unsigned int i;
+       int ret;
+
+       /* Walk the entities list and restore controls when possible. */
+       list_for_each_entry(entity, &dev->entities, list) {
+
+               for (i = 0; i < entity->ncontrols; ++i) {
+                       ctrl = &entity->controls[i];
+
+                       if (!ctrl->initialized || !ctrl->modified ||
+                           (ctrl->info.flags & UVC_CTRL_FLAG_RESTORE) == 0)
+                               continue;
+
+                       printk(KERN_INFO "restoring control %pUl/%u/%u\n",
+                               ctrl->info.entity, ctrl->info.index,
+                               ctrl->info.selector);
+                       ctrl->dirty = 1;
+               }
+
+               ret = uvc_ctrl_commit_entity(dev, entity, 0);
+               if (ret < 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+/* --------------------------------------------------------------------------
+ * Control and mapping handling
+ */
+
+/*
+ * Add control information to a given control.
+ */
+static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl,
+       const struct uvc_control_info *info)
+{
+       int ret = 0;
+
+       memcpy(&ctrl->info, info, sizeof(*info));
+       INIT_LIST_HEAD(&ctrl->info.mappings);
+
+       /* Allocate an array to save control values (cur, def, max, etc.) */
+       ctrl->uvc_data = kzalloc(ctrl->info.size * UVC_CTRL_DATA_LAST + 1,
+                                GFP_KERNEL);
+       if (ctrl->uvc_data == NULL) {
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       ctrl->initialized = 1;
+
+       uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s "
+               "entity %u\n", ctrl->info.entity, ctrl->info.selector,
+               dev->udev->devpath, ctrl->entity->id);
+
+done:
+       if (ret < 0)
+               kfree(ctrl->uvc_data);
+       return ret;
+}
+
+/*
+ * Add a control mapping to a given control.
+ */
+static int __uvc_ctrl_add_mapping(struct uvc_device *dev,
+       struct uvc_control *ctrl, const struct uvc_control_mapping *mapping)
+{
+       struct uvc_control_mapping *map;
+       unsigned int size;
+
+       /* Most mappings come from static kernel data and need to be duplicated.
+        * Mappings that come from userspace will be unnecessarily duplicated,
+        * this could be optimized.
+        */
+       map = kmemdup(mapping, sizeof(*mapping), GFP_KERNEL);
+       if (map == NULL)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&map->ev_subs);
+
+       size = sizeof(*mapping->menu_info) * mapping->menu_count;
+       map->menu_info = kmemdup(mapping->menu_info, size, GFP_KERNEL);
+       if (map->menu_info == NULL) {
+               kfree(map);
+               return -ENOMEM;
+       }
+
+       if (map->get == NULL)
+               map->get = uvc_get_le_value;
+       if (map->set == NULL)
+               map->set = uvc_set_le_value;
+
+       list_add_tail(&map->list, &ctrl->info.mappings);
+       uvc_trace(UVC_TRACE_CONTROL,
+               "Adding mapping '%s' to control %pUl/%u.\n",
+               map->name, ctrl->info.entity, ctrl->info.selector);
+
+       return 0;
+}
+
+int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
+       const struct uvc_control_mapping *mapping)
+{
+       struct uvc_device *dev = chain->dev;
+       struct uvc_control_mapping *map;
+       struct uvc_entity *entity;
+       struct uvc_control *ctrl;
+       int found = 0;
+       int ret;
+
+       if (mapping->id & ~V4L2_CTRL_ID_MASK) {
+               uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', control "
+                       "id 0x%08x is invalid.\n", mapping->name,
+                       mapping->id);
+               return -EINVAL;
+       }
+
+       /* Search for the matching (GUID/CS) control on the current chain */
+       list_for_each_entry(entity, &chain->entities, chain) {
+               unsigned int i;
+
+               if (UVC_ENTITY_TYPE(entity) != UVC_VC_EXTENSION_UNIT ||
+                   !uvc_entity_match_guid(entity, mapping->entity))
+                       continue;
+
+               for (i = 0; i < entity->ncontrols; ++i) {
+                       ctrl = &entity->controls[i];
+                       if (ctrl->index == mapping->selector - 1) {
+                               found = 1;
+                               break;
+                       }
+               }
+
+               if (found)
+                       break;
+       }
+       if (!found)
+               return -ENOENT;
+
+       if (mutex_lock_interruptible(&chain->ctrl_mutex))
+               return -ERESTARTSYS;
+
+       /* Perform delayed initialization of XU controls */
+       ret = uvc_ctrl_init_xu_ctrl(dev, ctrl);
+       if (ret < 0) {
+               ret = -ENOENT;
+               goto done;
+       }
+
+       list_for_each_entry(map, &ctrl->info.mappings, list) {
+               if (mapping->id == map->id) {
+                       uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', "
+                               "control id 0x%08x already exists.\n",
+                               mapping->name, mapping->id);
+                       ret = -EEXIST;
+                       goto done;
+               }
+       }
+
+       /* Prevent excess memory consumption */
+       if (atomic_inc_return(&dev->nmappings) > UVC_MAX_CONTROL_MAPPINGS) {
+               atomic_dec(&dev->nmappings);
+               uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', maximum "
+                       "mappings count (%u) exceeded.\n", mapping->name,
+                       UVC_MAX_CONTROL_MAPPINGS);
+               ret = -ENOMEM;
+               goto done;
+       }
+
+       ret = __uvc_ctrl_add_mapping(dev, ctrl, mapping);
+       if (ret < 0)
+               atomic_dec(&dev->nmappings);
+
+done:
+       mutex_unlock(&chain->ctrl_mutex);
+       return ret;
+}
+
+/*
+ * Prune an entity of its bogus controls using a blacklist. Bogus controls
+ * are currently the ones that crash the camera or unconditionally return an
+ * error when queried.
+ */
+static void uvc_ctrl_prune_entity(struct uvc_device *dev,
+       struct uvc_entity *entity)
+{
+       struct uvc_ctrl_blacklist {
+               struct usb_device_id id;
+               u8 index;
+       };
+
+       static const struct uvc_ctrl_blacklist processing_blacklist[] = {
+               { { USB_DEVICE(0x13d3, 0x509b) }, 9 }, /* Gain */
+               { { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */
+               { { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */
+       };
+       static const struct uvc_ctrl_blacklist camera_blacklist[] = {
+               { { USB_DEVICE(0x06f8, 0x3005) }, 9 }, /* Zoom, Absolute */
+       };
+
+       const struct uvc_ctrl_blacklist *blacklist;
+       unsigned int size;
+       unsigned int count;
+       unsigned int i;
+       u8 *controls;
+
+       switch (UVC_ENTITY_TYPE(entity)) {
+       case UVC_VC_PROCESSING_UNIT:
+               blacklist = processing_blacklist;
+               count = ARRAY_SIZE(processing_blacklist);
+               controls = entity->processing.bmControls;
+               size = entity->processing.bControlSize;
+               break;
+
+       case UVC_ITT_CAMERA:
+               blacklist = camera_blacklist;
+               count = ARRAY_SIZE(camera_blacklist);
+               controls = entity->camera.bmControls;
+               size = entity->camera.bControlSize;
+               break;
+
+       default:
+               return;
+       }
+
+       for (i = 0; i < count; ++i) {
+               if (!usb_match_one_id(dev->intf, &blacklist[i].id))
+                       continue;
+
+               if (blacklist[i].index >= 8 * size ||
+                   !uvc_test_bit(controls, blacklist[i].index))
+                       continue;
+
+               uvc_trace(UVC_TRACE_CONTROL, "%u/%u control is black listed, "
+                       "removing it.\n", entity->id, blacklist[i].index);
+
+               uvc_clear_bit(controls, blacklist[i].index);
+       }
+}
+
+/*
+ * Add control information and hardcoded stock control mappings to the given
+ * device.
+ */
+static void uvc_ctrl_init_ctrl(struct uvc_device *dev, struct uvc_control *ctrl)
+{
+       const struct uvc_control_info *info = uvc_ctrls;
+       const struct uvc_control_info *iend = info + ARRAY_SIZE(uvc_ctrls);
+       const struct uvc_control_mapping *mapping = uvc_ctrl_mappings;
+       const struct uvc_control_mapping *mend =
+               mapping + ARRAY_SIZE(uvc_ctrl_mappings);
+
+       /* XU controls initialization requires querying the device for control
+        * information. As some buggy UVC devices will crash when queried
+        * repeatedly in a tight loop, delay XU controls initialization until
+        * first use.
+        */
+       if (UVC_ENTITY_TYPE(ctrl->entity) == UVC_VC_EXTENSION_UNIT)
+               return;
+
+       for (; info < iend; ++info) {
+               if (uvc_entity_match_guid(ctrl->entity, info->entity) &&
+                   ctrl->index == info->index) {
+                       uvc_ctrl_add_info(dev, ctrl, info);
+                       break;
+                }
+       }
+
+       if (!ctrl->initialized)
+               return;
+
+       for (; mapping < mend; ++mapping) {
+               if (uvc_entity_match_guid(ctrl->entity, mapping->entity) &&
+                   ctrl->info.selector == mapping->selector)
+                       __uvc_ctrl_add_mapping(dev, ctrl, mapping);
+       }
+}
+
+/*
+ * Initialize device controls.
+ */
+int uvc_ctrl_init_device(struct uvc_device *dev)
+{
+       struct uvc_entity *entity;
+       unsigned int i;
+
+       /* Walk the entities list and instantiate controls */
+       list_for_each_entry(entity, &dev->entities, list) {
+               struct uvc_control *ctrl;
+               unsigned int bControlSize = 0, ncontrols;
+               __u8 *bmControls = NULL;
+
+               if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) {
+                       bmControls = entity->extension.bmControls;
+                       bControlSize = entity->extension.bControlSize;
+               } else if (UVC_ENTITY_TYPE(entity) == UVC_VC_PROCESSING_UNIT) {
+                       bmControls = entity->processing.bmControls;
+                       bControlSize = entity->processing.bControlSize;
+               } else if (UVC_ENTITY_TYPE(entity) == UVC_ITT_CAMERA) {
+                       bmControls = entity->camera.bmControls;
+                       bControlSize = entity->camera.bControlSize;
+               }
+
+               /* Remove bogus/blacklisted controls */
+               uvc_ctrl_prune_entity(dev, entity);
+
+               /* Count supported controls and allocate the controls array */
+               ncontrols = memweight(bmControls, bControlSize);
+               if (ncontrols == 0)
+                       continue;
+
+               entity->controls = kcalloc(ncontrols, sizeof(*ctrl),
+                                          GFP_KERNEL);
+               if (entity->controls == NULL)
+                       return -ENOMEM;
+               entity->ncontrols = ncontrols;
+
+               /* Initialize all supported controls */
+               ctrl = entity->controls;
+               for (i = 0; i < bControlSize * 8; ++i) {
+                       if (uvc_test_bit(bmControls, i) == 0)
+                               continue;
+
+                       ctrl->entity = entity;
+                       ctrl->index = i;
+
+                       uvc_ctrl_init_ctrl(dev, ctrl);
+                       ctrl++;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Cleanup device controls.
+ */
+static void uvc_ctrl_cleanup_mappings(struct uvc_device *dev,
+       struct uvc_control *ctrl)
+{
+       struct uvc_control_mapping *mapping, *nm;
+
+       list_for_each_entry_safe(mapping, nm, &ctrl->info.mappings, list) {
+               list_del(&mapping->list);
+               kfree(mapping->menu_info);
+               kfree(mapping);
+       }
+}
+
+void uvc_ctrl_cleanup_device(struct uvc_device *dev)
+{
+       struct uvc_entity *entity;
+       unsigned int i;
+
+       /* Free controls and control mappings for all entities. */
+       list_for_each_entry(entity, &dev->entities, list) {
+               for (i = 0; i < entity->ncontrols; ++i) {
+                       struct uvc_control *ctrl = &entity->controls[i];
+
+                       if (!ctrl->initialized)
+                               continue;
+
+                       uvc_ctrl_cleanup_mappings(dev, ctrl);
+                       kfree(ctrl->uvc_data);
+               }
+
+               kfree(entity->controls);
+       }
+}
diff --git a/drivers/media/usb/uvc/uvc_debugfs.c b/drivers/media/usb/uvc/uvc_debugfs.c
new file mode 100644 (file)
index 0000000..14561a5
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ *      uvc_debugfs.c --  USB Video Class driver - Debugging support
+ *
+ *      Copyright (C) 2011
+ *          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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+
+#include "uvcvideo.h"
+
+/* -----------------------------------------------------------------------------
+ * Statistics
+ */
+
+#define UVC_DEBUGFS_BUF_SIZE   1024
+
+struct uvc_debugfs_buffer {
+       size_t count;
+       char data[UVC_DEBUGFS_BUF_SIZE];
+};
+
+static int uvc_debugfs_stats_open(struct inode *inode, struct file *file)
+{
+       struct uvc_streaming *stream = inode->i_private;
+       struct uvc_debugfs_buffer *buf;
+
+       buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+       if (buf == NULL)
+               return -ENOMEM;
+
+       buf->count = uvc_video_stats_dump(stream, buf->data, sizeof(buf->data));
+
+       file->private_data = buf;
+       return 0;
+}
+
+static ssize_t uvc_debugfs_stats_read(struct file *file, char __user *user_buf,
+                                     size_t nbytes, loff_t *ppos)
+{
+       struct uvc_debugfs_buffer *buf = file->private_data;
+
+       return simple_read_from_buffer(user_buf, nbytes, ppos, buf->data,
+                                      buf->count);
+}
+
+static int uvc_debugfs_stats_release(struct inode *inode, struct file *file)
+{
+       kfree(file->private_data);
+       file->private_data = NULL;
+
+       return 0;
+}
+
+static const struct file_operations uvc_debugfs_stats_fops = {
+       .owner = THIS_MODULE,
+       .open = uvc_debugfs_stats_open,
+       .llseek = no_llseek,
+       .read = uvc_debugfs_stats_read,
+       .release = uvc_debugfs_stats_release,
+};
+
+/* -----------------------------------------------------------------------------
+ * Global and stream initialization/cleanup
+ */
+
+static struct dentry *uvc_debugfs_root_dir;
+
+int uvc_debugfs_init_stream(struct uvc_streaming *stream)
+{
+       struct usb_device *udev = stream->dev->udev;
+       struct dentry *dent;
+       char dir_name[32];
+
+       if (uvc_debugfs_root_dir == NULL)
+               return -ENODEV;
+
+       sprintf(dir_name, "%u-%u", udev->bus->busnum, udev->devnum);
+
+       dent = debugfs_create_dir(dir_name, uvc_debugfs_root_dir);
+       if (IS_ERR_OR_NULL(dent)) {
+               uvc_printk(KERN_INFO, "Unable to create debugfs %s "
+                          "directory.\n", dir_name);
+               return -ENODEV;
+       }
+
+       stream->debugfs_dir = dent;
+
+       dent = debugfs_create_file("stats", 0444, stream->debugfs_dir,
+                                  stream, &uvc_debugfs_stats_fops);
+       if (IS_ERR_OR_NULL(dent)) {
+               uvc_printk(KERN_INFO, "Unable to create debugfs stats file.\n");
+               uvc_debugfs_cleanup_stream(stream);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream)
+{
+       if (stream->debugfs_dir == NULL)
+               return;
+
+       debugfs_remove_recursive(stream->debugfs_dir);
+       stream->debugfs_dir = NULL;
+}
+
+int uvc_debugfs_init(void)
+{
+       struct dentry *dir;
+
+       dir = debugfs_create_dir("uvcvideo", usb_debug_root);
+       if (IS_ERR_OR_NULL(dir)) {
+               uvc_printk(KERN_INFO, "Unable to create debugfs directory\n");
+               return -ENODATA;
+       }
+
+       uvc_debugfs_root_dir = dir;
+       return 0;
+}
+
+void uvc_debugfs_cleanup(void)
+{
+       if (uvc_debugfs_root_dir != NULL)
+               debugfs_remove_recursive(uvc_debugfs_root_dir);
+}
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
new file mode 100644 (file)
index 0000000..45d7aa1
--- /dev/null
@@ -0,0 +1,2472 @@
+/*
+ *      uvc_driver.c  --  USB Video Class driver
+ *
+ *      Copyright (C) 2005-2010
+ *          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.
+ *
+ */
+
+/*
+ * This driver aims to support video input and ouput devices compliant with the
+ * 'USB Video Class' specification.
+ *
+ * The driver doesn't support the deprecated v4l1 interface. It implements the
+ * mmap capture method only, and doesn't do any image format conversion in
+ * software. If your user-space application doesn't support YUYV or MJPEG, fix
+ * it :-). Please note that the MJPEG data have been stripped from their
+ * Huffman tables (DHT marker), you will need to add it back if your JPEG
+ * codec can't handle MJPEG data.
+ */
+
+#include <linux/atomic.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+#include <linux/version.h>
+#include <asm/unaligned.h>
+
+#include <media/v4l2-common.h>
+
+#include "uvcvideo.h"
+
+#define DRIVER_AUTHOR          "Laurent Pinchart " \
+                               "<laurent.pinchart@ideasonboard.com>"
+#define DRIVER_DESC            "USB Video Class driver"
+
+unsigned int uvc_clock_param = CLOCK_MONOTONIC;
+unsigned int uvc_no_drop_param;
+static unsigned int uvc_quirks_param = -1;
+unsigned int uvc_trace_param;
+unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT;
+
+/* ------------------------------------------------------------------------
+ * Video formats
+ */
+
+static struct uvc_format_desc uvc_fmts[] = {
+       {
+               .name           = "YUV 4:2:2 (YUYV)",
+               .guid           = UVC_GUID_FORMAT_YUY2,
+               .fcc            = V4L2_PIX_FMT_YUYV,
+       },
+       {
+               .name           = "YUV 4:2:2 (YUYV)",
+               .guid           = UVC_GUID_FORMAT_YUY2_ISIGHT,
+               .fcc            = V4L2_PIX_FMT_YUYV,
+       },
+       {
+               .name           = "YUV 4:2:0 (NV12)",
+               .guid           = UVC_GUID_FORMAT_NV12,
+               .fcc            = V4L2_PIX_FMT_NV12,
+       },
+       {
+               .name           = "MJPEG",
+               .guid           = UVC_GUID_FORMAT_MJPEG,
+               .fcc            = V4L2_PIX_FMT_MJPEG,
+       },
+       {
+               .name           = "YVU 4:2:0 (YV12)",
+               .guid           = UVC_GUID_FORMAT_YV12,
+               .fcc            = V4L2_PIX_FMT_YVU420,
+       },
+       {
+               .name           = "YUV 4:2:0 (I420)",
+               .guid           = UVC_GUID_FORMAT_I420,
+               .fcc            = V4L2_PIX_FMT_YUV420,
+       },
+       {
+               .name           = "YUV 4:2:0 (M420)",
+               .guid           = UVC_GUID_FORMAT_M420,
+               .fcc            = V4L2_PIX_FMT_M420,
+       },
+       {
+               .name           = "YUV 4:2:2 (UYVY)",
+               .guid           = UVC_GUID_FORMAT_UYVY,
+               .fcc            = V4L2_PIX_FMT_UYVY,
+       },
+       {
+               .name           = "Greyscale 8-bit (Y800)",
+               .guid           = UVC_GUID_FORMAT_Y800,
+               .fcc            = V4L2_PIX_FMT_GREY,
+       },
+       {
+               .name           = "Greyscale 8-bit (Y8  )",
+               .guid           = UVC_GUID_FORMAT_Y8,
+               .fcc            = V4L2_PIX_FMT_GREY,
+       },
+       {
+               .name           = "Greyscale 10-bit (Y10 )",
+               .guid           = UVC_GUID_FORMAT_Y10,
+               .fcc            = V4L2_PIX_FMT_Y10,
+       },
+       {
+               .name           = "Greyscale 12-bit (Y12 )",
+               .guid           = UVC_GUID_FORMAT_Y12,
+               .fcc            = V4L2_PIX_FMT_Y12,
+       },
+       {
+               .name           = "Greyscale 16-bit (Y16 )",
+               .guid           = UVC_GUID_FORMAT_Y16,
+               .fcc            = V4L2_PIX_FMT_Y16,
+       },
+       {
+               .name           = "RGB Bayer",
+               .guid           = UVC_GUID_FORMAT_BY8,
+               .fcc            = V4L2_PIX_FMT_SBGGR8,
+       },
+       {
+               .name           = "RGB565",
+               .guid           = UVC_GUID_FORMAT_RGBP,
+               .fcc            = V4L2_PIX_FMT_RGB565,
+       },
+       {
+               .name           = "H.264",
+               .guid           = UVC_GUID_FORMAT_H264,
+               .fcc            = V4L2_PIX_FMT_H264,
+       },
+};
+
+/* ------------------------------------------------------------------------
+ * Utility functions
+ */
+
+struct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts,
+               __u8 epaddr)
+{
+       struct usb_host_endpoint *ep;
+       unsigned int i;
+
+       for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
+               ep = &alts->endpoint[i];
+               if (ep->desc.bEndpointAddress == epaddr)
+                       return ep;
+       }
+
+       return NULL;
+}
+
+static struct uvc_format_desc *uvc_format_by_guid(const __u8 guid[16])
+{
+       unsigned int len = ARRAY_SIZE(uvc_fmts);
+       unsigned int i;
+
+       for (i = 0; i < len; ++i) {
+               if (memcmp(guid, uvc_fmts[i].guid, 16) == 0)
+                       return &uvc_fmts[i];
+       }
+
+       return NULL;
+}
+
+static __u32 uvc_colorspace(const __u8 primaries)
+{
+       static const __u8 colorprimaries[] = {
+               0,
+               V4L2_COLORSPACE_SRGB,
+               V4L2_COLORSPACE_470_SYSTEM_M,
+               V4L2_COLORSPACE_470_SYSTEM_BG,
+               V4L2_COLORSPACE_SMPTE170M,
+               V4L2_COLORSPACE_SMPTE240M,
+       };
+
+       if (primaries < ARRAY_SIZE(colorprimaries))
+               return colorprimaries[primaries];
+
+       return 0;
+}
+
+/* Simplify a fraction using a simple continued fraction decomposition. The
+ * idea here is to convert fractions such as 333333/10000000 to 1/30 using
+ * 32 bit arithmetic only. The algorithm is not perfect and relies upon two
+ * arbitrary parameters to remove non-significative terms from the simple
+ * continued fraction decomposition. Using 8 and 333 for n_terms and threshold
+ * respectively seems to give nice results.
+ */
+void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator,
+               unsigned int n_terms, unsigned int threshold)
+{
+       uint32_t *an;
+       uint32_t x, y, r;
+       unsigned int i, n;
+
+       an = kmalloc(n_terms * sizeof *an, GFP_KERNEL);
+       if (an == NULL)
+               return;
+
+       /* Convert the fraction to a simple continued fraction. See
+        * http://mathforum.org/dr.math/faq/faq.fractions.html
+        * Stop if the current term is bigger than or equal to the given
+        * threshold.
+        */
+       x = *numerator;
+       y = *denominator;
+
+       for (n = 0; n < n_terms && y != 0; ++n) {
+               an[n] = x / y;
+               if (an[n] >= threshold) {
+                       if (n < 2)
+                               n++;
+                       break;
+               }
+
+               r = x - an[n] * y;
+               x = y;
+               y = r;
+       }
+
+       /* Expand the simple continued fraction back to an integer fraction. */
+       x = 0;
+       y = 1;
+
+       for (i = n; i > 0; --i) {
+               r = y;
+               y = an[i-1] * y + x;
+               x = r;
+       }
+
+       *numerator = y;
+       *denominator = x;
+       kfree(an);
+}
+
+/* Convert a fraction to a frame interval in 100ns multiples. The idea here is
+ * to compute numerator / denominator * 10000000 using 32 bit fixed point
+ * arithmetic only.
+ */
+uint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator)
+{
+       uint32_t multiplier;
+
+       /* Saturate the result if the operation would overflow. */
+       if (denominator == 0 ||
+           numerator/denominator >= ((uint32_t)-1)/10000000)
+               return (uint32_t)-1;
+
+       /* Divide both the denominator and the multiplier by two until
+        * numerator * multiplier doesn't overflow. If anyone knows a better
+        * algorithm please let me know.
+        */
+       multiplier = 10000000;
+       while (numerator > ((uint32_t)-1)/multiplier) {
+               multiplier /= 2;
+               denominator /= 2;
+       }
+
+       return denominator ? numerator * multiplier / denominator : 0;
+}
+
+/* ------------------------------------------------------------------------
+ * Terminal and unit management
+ */
+
+struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id)
+{
+       struct uvc_entity *entity;
+
+       list_for_each_entry(entity, &dev->entities, list) {
+               if (entity->id == id)
+                       return entity;
+       }
+
+       return NULL;
+}
+
+static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev,
+       int id, struct uvc_entity *entity)
+{
+       unsigned int i;
+
+       if (entity == NULL)
+               entity = list_entry(&dev->entities, struct uvc_entity, list);
+
+       list_for_each_entry_continue(entity, &dev->entities, list) {
+               for (i = 0; i < entity->bNrInPins; ++i)
+                       if (entity->baSourceID[i] == id)
+                               return entity;
+       }
+
+       return NULL;
+}
+
+static struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id)
+{
+       struct uvc_streaming *stream;
+
+       list_for_each_entry(stream, &dev->streams, list) {
+               if (stream->header.bTerminalLink == id)
+                       return stream;
+       }
+
+       return NULL;
+}
+
+/* ------------------------------------------------------------------------
+ * Descriptors parsing
+ */
+
+static int uvc_parse_format(struct uvc_device *dev,
+       struct uvc_streaming *streaming, struct uvc_format *format,
+       __u32 **intervals, unsigned char *buffer, int buflen)
+{
+       struct usb_interface *intf = streaming->intf;
+       struct usb_host_interface *alts = intf->cur_altsetting;
+       struct uvc_format_desc *fmtdesc;
+       struct uvc_frame *frame;
+       const unsigned char *start = buffer;
+       unsigned int interval;
+       unsigned int i, n;
+       __u8 ftype;
+
+       format->type = buffer[2];
+       format->index = buffer[3];
+
+       switch (buffer[2]) {
+       case UVC_VS_FORMAT_UNCOMPRESSED:
+       case UVC_VS_FORMAT_FRAME_BASED:
+               n = buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED ? 27 : 28;
+               if (buflen < n) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
+                              "interface %d FORMAT error\n",
+                              dev->udev->devnum,
+                              alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               /* Find the format descriptor from its GUID. */
+               fmtdesc = uvc_format_by_guid(&buffer[5]);
+
+               if (fmtdesc != NULL) {
+                       strlcpy(format->name, fmtdesc->name,
+                               sizeof format->name);
+                       format->fcc = fmtdesc->fcc;
+               } else {
+                       uvc_printk(KERN_INFO, "Unknown video format %pUl\n",
+                               &buffer[5]);
+                       snprintf(format->name, sizeof(format->name), "%pUl\n",
+                               &buffer[5]);
+                       format->fcc = 0;
+               }
+
+               format->bpp = buffer[21];
+               if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) {
+                       ftype = UVC_VS_FRAME_UNCOMPRESSED;
+               } else {
+                       ftype = UVC_VS_FRAME_FRAME_BASED;
+                       if (buffer[27])
+                               format->flags = UVC_FMT_FLAG_COMPRESSED;
+               }
+               break;
+
+       case UVC_VS_FORMAT_MJPEG:
+               if (buflen < 11) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
+                              "interface %d FORMAT error\n",
+                              dev->udev->devnum,
+                              alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               strlcpy(format->name, "MJPEG", sizeof format->name);
+               format->fcc = V4L2_PIX_FMT_MJPEG;
+               format->flags = UVC_FMT_FLAG_COMPRESSED;
+               format->bpp = 0;
+               ftype = UVC_VS_FRAME_MJPEG;
+               break;
+
+       case UVC_VS_FORMAT_DV:
+               if (buflen < 9) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
+                              "interface %d FORMAT error\n",
+                              dev->udev->devnum,
+                              alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               switch (buffer[8] & 0x7f) {
+               case 0:
+                       strlcpy(format->name, "SD-DV", sizeof format->name);
+                       break;
+               case 1:
+                       strlcpy(format->name, "SDL-DV", sizeof format->name);
+                       break;
+               case 2:
+                       strlcpy(format->name, "HD-DV", sizeof format->name);
+                       break;
+               default:
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
+                              "interface %d: unknown DV format %u\n",
+                              dev->udev->devnum,
+                              alts->desc.bInterfaceNumber, buffer[8]);
+                       return -EINVAL;
+               }
+
+               strlcat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",
+                       sizeof format->name);
+
+               format->fcc = V4L2_PIX_FMT_DV;
+               format->flags = UVC_FMT_FLAG_COMPRESSED | UVC_FMT_FLAG_STREAM;
+               format->bpp = 0;
+               ftype = 0;
+
+               /* Create a dummy frame descriptor. */
+               frame = &format->frame[0];
+               memset(&format->frame[0], 0, sizeof format->frame[0]);
+               frame->bFrameIntervalType = 1;
+               frame->dwDefaultFrameInterval = 1;
+               frame->dwFrameInterval = *intervals;
+               *(*intervals)++ = 1;
+               format->nframes = 1;
+               break;
+
+       case UVC_VS_FORMAT_MPEG2TS:
+       case UVC_VS_FORMAT_STREAM_BASED:
+               /* Not supported yet. */
+       default:
+               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
+                      "interface %d unsupported format %u\n",
+                      dev->udev->devnum, alts->desc.bInterfaceNumber,
+                      buffer[2]);
+               return -EINVAL;
+       }
+
+       uvc_trace(UVC_TRACE_DESCR, "Found format %s.\n", format->name);
+
+       buflen -= buffer[0];
+       buffer += buffer[0];
+
+       /* Parse the frame descriptors. Only uncompressed, MJPEG and frame
+        * based formats have frame descriptors.
+        */
+       while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
+              buffer[2] == ftype) {
+               frame = &format->frame[format->nframes];
+               if (ftype != UVC_VS_FRAME_FRAME_BASED)
+                       n = buflen > 25 ? buffer[25] : 0;
+               else
+                       n = buflen > 21 ? buffer[21] : 0;
+
+               n = n ? n : 3;
+
+               if (buflen < 26 + 4*n) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
+                              "interface %d FRAME error\n", dev->udev->devnum,
+                              alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               frame->bFrameIndex = buffer[3];
+               frame->bmCapabilities = buffer[4];
+               frame->wWidth = get_unaligned_le16(&buffer[5]);
+               frame->wHeight = get_unaligned_le16(&buffer[7]);
+               frame->dwMinBitRate = get_unaligned_le32(&buffer[9]);
+               frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]);
+               if (ftype != UVC_VS_FRAME_FRAME_BASED) {
+                       frame->dwMaxVideoFrameBufferSize =
+                               get_unaligned_le32(&buffer[17]);
+                       frame->dwDefaultFrameInterval =
+                               get_unaligned_le32(&buffer[21]);
+                       frame->bFrameIntervalType = buffer[25];
+               } else {
+                       frame->dwMaxVideoFrameBufferSize = 0;
+                       frame->dwDefaultFrameInterval =
+                               get_unaligned_le32(&buffer[17]);
+                       frame->bFrameIntervalType = buffer[21];
+               }
+               frame->dwFrameInterval = *intervals;
+
+               /* Several UVC chipsets screw up dwMaxVideoFrameBufferSize
+                * completely. Observed behaviours range from setting the
+                * value to 1.1x the actual frame size to hardwiring the
+                * 16 low bits to 0. This results in a higher than necessary
+                * memory usage as well as a wrong image size information. For
+                * uncompressed formats this can be fixed by computing the
+                * value from the frame size.
+                */
+               if (!(format->flags & UVC_FMT_FLAG_COMPRESSED))
+                       frame->dwMaxVideoFrameBufferSize = format->bpp
+                               * frame->wWidth * frame->wHeight / 8;
+
+               /* Some bogus devices report dwMinFrameInterval equal to
+                * dwMaxFrameInterval and have dwFrameIntervalStep set to
+                * zero. Setting all null intervals to 1 fixes the problem and
+                * some other divisions by zero that could happen.
+                */
+               for (i = 0; i < n; ++i) {
+                       interval = get_unaligned_le32(&buffer[26+4*i]);
+                       *(*intervals)++ = interval ? interval : 1;
+               }
+
+               /* Make sure that the default frame interval stays between
+                * the boundaries.
+                */
+               n -= frame->bFrameIntervalType ? 1 : 2;
+               frame->dwDefaultFrameInterval =
+                       min(frame->dwFrameInterval[n],
+                           max(frame->dwFrameInterval[0],
+                               frame->dwDefaultFrameInterval));
+
+               if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) {
+                       frame->bFrameIntervalType = 1;
+                       frame->dwFrameInterval[0] =
+                               frame->dwDefaultFrameInterval;
+               }
+
+               uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n",
+                       frame->wWidth, frame->wHeight,
+                       10000000/frame->dwDefaultFrameInterval,
+                       (100000000/frame->dwDefaultFrameInterval)%10);
+
+               format->nframes++;
+               buflen -= buffer[0];
+               buffer += buffer[0];
+       }
+
+       if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
+           buffer[2] == UVC_VS_STILL_IMAGE_FRAME) {
+               buflen -= buffer[0];
+               buffer += buffer[0];
+       }
+
+       if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
+           buffer[2] == UVC_VS_COLORFORMAT) {
+               if (buflen < 6) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
+                              "interface %d COLORFORMAT error\n",
+                              dev->udev->devnum,
+                              alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               format->colorspace = uvc_colorspace(buffer[3]);
+
+               buflen -= buffer[0];
+               buffer += buffer[0];
+       }
+
+       return buffer - start;
+}
+
+static int uvc_parse_streaming(struct uvc_device *dev,
+       struct usb_interface *intf)
+{
+       struct uvc_streaming *streaming = NULL;
+       struct uvc_format *format;
+       struct uvc_frame *frame;
+       struct usb_host_interface *alts = &intf->altsetting[0];
+       unsigned char *_buffer, *buffer = alts->extra;
+       int _buflen, buflen = alts->extralen;
+       unsigned int nformats = 0, nframes = 0, nintervals = 0;
+       unsigned int size, i, n, p;
+       __u32 *interval;
+       __u16 psize;
+       int ret = -EINVAL;
+
+       if (intf->cur_altsetting->desc.bInterfaceSubClass
+               != UVC_SC_VIDEOSTREAMING) {
+               uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a "
+                       "video streaming interface\n", dev->udev->devnum,
+                       intf->altsetting[0].desc.bInterfaceNumber);
+               return -EINVAL;
+       }
+
+       if (usb_driver_claim_interface(&uvc_driver.driver, intf, dev)) {
+               uvc_trace(UVC_TRACE_DESCR, "device %d interface %d is already "
+                       "claimed\n", dev->udev->devnum,
+                       intf->altsetting[0].desc.bInterfaceNumber);
+               return -EINVAL;
+       }
+
+       streaming = kzalloc(sizeof *streaming, GFP_KERNEL);
+       if (streaming == NULL) {
+               usb_driver_release_interface(&uvc_driver.driver, intf);
+               return -EINVAL;
+       }
+
+       mutex_init(&streaming->mutex);
+       streaming->dev = dev;
+       streaming->intf = usb_get_intf(intf);
+       streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
+       /* The Pico iMage webcam has its class-specific interface descriptors
+        * after the endpoint descriptors.
+        */
+       if (buflen == 0) {
+               for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
+                       struct usb_host_endpoint *ep = &alts->endpoint[i];
+
+                       if (ep->extralen == 0)
+                               continue;
+
+                       if (ep->extralen > 2 &&
+                           ep->extra[1] == USB_DT_CS_INTERFACE) {
+                               uvc_trace(UVC_TRACE_DESCR, "trying extra data "
+                                       "from endpoint %u.\n", i);
+                               buffer = alts->endpoint[i].extra;
+                               buflen = alts->endpoint[i].extralen;
+                               break;
+                       }
+               }
+       }
+
+       /* Skip the standard interface descriptors. */
+       while (buflen > 2 && buffer[1] != USB_DT_CS_INTERFACE) {
+               buflen -= buffer[0];
+               buffer += buffer[0];
+       }
+
+       if (buflen <= 2) {
+               uvc_trace(UVC_TRACE_DESCR, "no class-specific streaming "
+                       "interface descriptors found.\n");
+               goto error;
+       }
+
+       /* Parse the header descriptor. */
+       switch (buffer[2]) {
+       case UVC_VS_OUTPUT_HEADER:
+               streaming->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+               size = 9;
+               break;
+
+       case UVC_VS_INPUT_HEADER:
+               streaming->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+               size = 13;
+               break;
+
+       default:
+               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
+                       "%d HEADER descriptor not found.\n", dev->udev->devnum,
+                       alts->desc.bInterfaceNumber);
+               goto error;
+       }
+
+       p = buflen >= 4 ? buffer[3] : 0;
+       n = buflen >= size ? buffer[size-1] : 0;
+
+       if (buflen < size + p*n) {
+               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
+                       "interface %d HEADER descriptor is invalid.\n",
+                       dev->udev->devnum, alts->desc.bInterfaceNumber);
+               goto error;
+       }
+
+       streaming->header.bNumFormats = p;
+       streaming->header.bEndpointAddress = buffer[6];
+       if (buffer[2] == UVC_VS_INPUT_HEADER) {
+               streaming->header.bmInfo = buffer[7];
+               streaming->header.bTerminalLink = buffer[8];
+               streaming->header.bStillCaptureMethod = buffer[9];
+               streaming->header.bTriggerSupport = buffer[10];
+               streaming->header.bTriggerUsage = buffer[11];
+       } else {
+               streaming->header.bTerminalLink = buffer[7];
+       }
+       streaming->header.bControlSize = n;
+
+       streaming->header.bmaControls = kmemdup(&buffer[size], p * n,
+                                               GFP_KERNEL);
+       if (streaming->header.bmaControls == NULL) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       buflen -= buffer[0];
+       buffer += buffer[0];
+
+       _buffer = buffer;
+       _buflen = buflen;
+
+       /* Count the format and frame descriptors. */
+       while (_buflen > 2 && _buffer[1] == USB_DT_CS_INTERFACE) {
+               switch (_buffer[2]) {
+               case UVC_VS_FORMAT_UNCOMPRESSED:
+               case UVC_VS_FORMAT_MJPEG:
+               case UVC_VS_FORMAT_FRAME_BASED:
+                       nformats++;
+                       break;
+
+               case UVC_VS_FORMAT_DV:
+                       /* DV format has no frame descriptor. We will create a
+                        * dummy frame descriptor with a dummy frame interval.
+                        */
+                       nformats++;
+                       nframes++;
+                       nintervals++;
+                       break;
+
+               case UVC_VS_FORMAT_MPEG2TS:
+               case UVC_VS_FORMAT_STREAM_BASED:
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
+                               "interface %d FORMAT %u is not supported.\n",
+                               dev->udev->devnum,
+                               alts->desc.bInterfaceNumber, _buffer[2]);
+                       break;
+
+               case UVC_VS_FRAME_UNCOMPRESSED:
+               case UVC_VS_FRAME_MJPEG:
+                       nframes++;
+                       if (_buflen > 25)
+                               nintervals += _buffer[25] ? _buffer[25] : 3;
+                       break;
+
+               case UVC_VS_FRAME_FRAME_BASED:
+                       nframes++;
+                       if (_buflen > 21)
+                               nintervals += _buffer[21] ? _buffer[21] : 3;
+                       break;
+               }
+
+               _buflen -= _buffer[0];
+               _buffer += _buffer[0];
+       }
+
+       if (nformats == 0) {
+               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
+                       "%d has no supported formats defined.\n",
+                       dev->udev->devnum, alts->desc.bInterfaceNumber);
+               goto error;
+       }
+
+       size = nformats * sizeof *format + nframes * sizeof *frame
+            + nintervals * sizeof *interval;
+       format = kzalloc(size, GFP_KERNEL);
+       if (format == NULL) {
+               ret = -ENOMEM;
+               goto error;
+       }
+
+       frame = (struct uvc_frame *)&format[nformats];
+       interval = (__u32 *)&frame[nframes];
+
+       streaming->format = format;
+       streaming->nformats = nformats;
+
+       /* Parse the format descriptors. */
+       while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) {
+               switch (buffer[2]) {
+               case UVC_VS_FORMAT_UNCOMPRESSED:
+               case UVC_VS_FORMAT_MJPEG:
+               case UVC_VS_FORMAT_DV:
+               case UVC_VS_FORMAT_FRAME_BASED:
+                       format->frame = frame;
+                       ret = uvc_parse_format(dev, streaming, format,
+                               &interval, buffer, buflen);
+                       if (ret < 0)
+                               goto error;
+
+                       frame += format->nframes;
+                       format++;
+
+                       buflen -= ret;
+                       buffer += ret;
+                       continue;
+
+               default:
+                       break;
+               }
+
+               buflen -= buffer[0];
+               buffer += buffer[0];
+       }
+
+       if (buflen)
+               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
+                       "%d has %u bytes of trailing descriptor garbage.\n",
+                       dev->udev->devnum, alts->desc.bInterfaceNumber, buflen);
+
+       /* Parse the alternate settings to find the maximum bandwidth. */
+       for (i = 0; i < intf->num_altsetting; ++i) {
+               struct usb_host_endpoint *ep;
+               alts = &intf->altsetting[i];
+               ep = uvc_find_endpoint(alts,
+                               streaming->header.bEndpointAddress);
+               if (ep == NULL)
+                       continue;
+
+               psize = le16_to_cpu(ep->desc.wMaxPacketSize);
+               psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+               if (psize > streaming->maxpsize)
+                       streaming->maxpsize = psize;
+       }
+
+       list_add_tail(&streaming->list, &dev->streams);
+       return 0;
+
+error:
+       usb_driver_release_interface(&uvc_driver.driver, intf);
+       usb_put_intf(intf);
+       kfree(streaming->format);
+       kfree(streaming->header.bmaControls);
+       kfree(streaming);
+       return ret;
+}
+
+static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,
+               unsigned int num_pads, unsigned int extra_size)
+{
+       struct uvc_entity *entity;
+       unsigned int num_inputs;
+       unsigned int size;
+       unsigned int i;
+
+       extra_size = ALIGN(extra_size, sizeof(*entity->pads));
+       num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1;
+       size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads
+            + num_inputs;
+       entity = kzalloc(size, GFP_KERNEL);
+       if (entity == NULL)
+               return NULL;
+
+       entity->id = id;
+       entity->type = type;
+
+       entity->num_links = 0;
+       entity->num_pads = num_pads;
+       entity->pads = ((void *)(entity + 1)) + extra_size;
+
+       for (i = 0; i < num_inputs; ++i)
+               entity->pads[i].flags = MEDIA_PAD_FL_SINK;
+       if (!UVC_ENTITY_IS_OTERM(entity))
+               entity->pads[num_pads-1].flags = MEDIA_PAD_FL_SOURCE;
+
+       entity->bNrInPins = num_inputs;
+       entity->baSourceID = (__u8 *)(&entity->pads[num_pads]);
+
+       return entity;
+}
+
+/* Parse vendor-specific extensions. */
+static int uvc_parse_vendor_control(struct uvc_device *dev,
+       const unsigned char *buffer, int buflen)
+{
+       struct usb_device *udev = dev->udev;
+       struct usb_host_interface *alts = dev->intf->cur_altsetting;
+       struct uvc_entity *unit;
+       unsigned int n, p;
+       int handled = 0;
+
+       switch (le16_to_cpu(dev->udev->descriptor.idVendor)) {
+       case 0x046d:            /* Logitech */
+               if (buffer[1] != 0x41 || buffer[2] != 0x01)
+                       break;
+
+               /* Logitech implements several vendor specific functions
+                * through vendor specific extension units (LXU).
+                *
+                * The LXU descriptors are similar to XU descriptors
+                * (see "USB Device Video Class for Video Devices", section
+                * 3.7.2.6 "Extension Unit Descriptor") with the following
+                * differences:
+                *
+                * ----------------------------------------------------------
+                * 0            bLength         1        Number
+                *      Size of this descriptor, in bytes: 24+p+n*2
+                * ----------------------------------------------------------
+                * 23+p+n       bmControlsType  N       Bitmap
+                *      Individual bits in the set are defined:
+                *      0: Absolute
+                *      1: Relative
+                *
+                *      This bitset is mapped exactly the same as bmControls.
+                * ----------------------------------------------------------
+                * 23+p+n*2     bReserved       1       Boolean
+                * ----------------------------------------------------------
+                * 24+p+n*2     iExtension      1       Index
+                *      Index of a string descriptor that describes this
+                *      extension unit.
+                * ----------------------------------------------------------
+                */
+               p = buflen >= 22 ? buffer[21] : 0;
+               n = buflen >= 25 + p ? buffer[22+p] : 0;
+
+               if (buflen < 25 + p + 2*n) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d EXTENSION_UNIT error\n",
+                               udev->devnum, alts->desc.bInterfaceNumber);
+                       break;
+               }
+
+               unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3],
+                                       p + 1, 2*n);
+               if (unit == NULL)
+                       return -ENOMEM;
+
+               memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
+               unit->extension.bNumControls = buffer[20];
+               memcpy(unit->baSourceID, &buffer[22], p);
+               unit->extension.bControlSize = buffer[22+p];
+               unit->extension.bmControls = (__u8 *)unit + sizeof(*unit);
+               unit->extension.bmControlsType = (__u8 *)unit + sizeof(*unit)
+                                              + n;
+               memcpy(unit->extension.bmControls, &buffer[23+p], 2*n);
+
+               if (buffer[24+p+2*n] != 0)
+                       usb_string(udev, buffer[24+p+2*n], unit->name,
+                                  sizeof unit->name);
+               else
+                       sprintf(unit->name, "Extension %u", buffer[3]);
+
+               list_add_tail(&unit->list, &dev->entities);
+               handled = 1;
+               break;
+       }
+
+       return handled;
+}
+
+static int uvc_parse_standard_control(struct uvc_device *dev,
+       const unsigned char *buffer, int buflen)
+{
+       struct usb_device *udev = dev->udev;
+       struct uvc_entity *unit, *term;
+       struct usb_interface *intf;
+       struct usb_host_interface *alts = dev->intf->cur_altsetting;
+       unsigned int i, n, p, len;
+       __u16 type;
+
+       switch (buffer[2]) {
+       case UVC_VC_HEADER:
+               n = buflen >= 12 ? buffer[11] : 0;
+
+               if (buflen < 12 || buflen < 12 + n) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d HEADER error\n", udev->devnum,
+                               alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               dev->uvc_version = get_unaligned_le16(&buffer[3]);
+               dev->clock_frequency = get_unaligned_le32(&buffer[7]);
+
+               /* Parse all USB Video Streaming interfaces. */
+               for (i = 0; i < n; ++i) {
+                       intf = usb_ifnum_to_if(udev, buffer[12+i]);
+                       if (intf == NULL) {
+                               uvc_trace(UVC_TRACE_DESCR, "device %d "
+                                       "interface %d doesn't exists\n",
+                                       udev->devnum, i);
+                               continue;
+                       }
+
+                       uvc_parse_streaming(dev, intf);
+               }
+               break;
+
+       case UVC_VC_INPUT_TERMINAL:
+               if (buflen < 8) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d INPUT_TERMINAL error\n",
+                               udev->devnum, alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               /* Make sure the terminal type MSB is not null, otherwise it
+                * could be confused with a unit.
+                */
+               type = get_unaligned_le16(&buffer[4]);
+               if ((type & 0xff00) == 0) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d INPUT_TERMINAL %d has invalid "
+                               "type 0x%04x, skipping\n", udev->devnum,
+                               alts->desc.bInterfaceNumber,
+                               buffer[3], type);
+                       return 0;
+               }
+
+               n = 0;
+               p = 0;
+               len = 8;
+
+               if (type == UVC_ITT_CAMERA) {
+                       n = buflen >= 15 ? buffer[14] : 0;
+                       len = 15;
+
+               } else if (type == UVC_ITT_MEDIA_TRANSPORT_INPUT) {
+                       n = buflen >= 9 ? buffer[8] : 0;
+                       p = buflen >= 10 + n ? buffer[9+n] : 0;
+                       len = 10;
+               }
+
+               if (buflen < len + n + p) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d INPUT_TERMINAL error\n",
+                               udev->devnum, alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3],
+                                       1, n + p);
+               if (term == NULL)
+                       return -ENOMEM;
+
+               if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) {
+                       term->camera.bControlSize = n;
+                       term->camera.bmControls = (__u8 *)term + sizeof *term;
+                       term->camera.wObjectiveFocalLengthMin =
+                               get_unaligned_le16(&buffer[8]);
+                       term->camera.wObjectiveFocalLengthMax =
+                               get_unaligned_le16(&buffer[10]);
+                       term->camera.wOcularFocalLength =
+                               get_unaligned_le16(&buffer[12]);
+                       memcpy(term->camera.bmControls, &buffer[15], n);
+               } else if (UVC_ENTITY_TYPE(term) ==
+                          UVC_ITT_MEDIA_TRANSPORT_INPUT) {
+                       term->media.bControlSize = n;
+                       term->media.bmControls = (__u8 *)term + sizeof *term;
+                       term->media.bTransportModeSize = p;
+                       term->media.bmTransportModes = (__u8 *)term
+                                                    + sizeof *term + n;
+                       memcpy(term->media.bmControls, &buffer[9], n);
+                       memcpy(term->media.bmTransportModes, &buffer[10+n], p);
+               }
+
+               if (buffer[7] != 0)
+                       usb_string(udev, buffer[7], term->name,
+                                  sizeof term->name);
+               else if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA)
+                       sprintf(term->name, "Camera %u", buffer[3]);
+               else if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT)
+                       sprintf(term->name, "Media %u", buffer[3]);
+               else
+                       sprintf(term->name, "Input %u", buffer[3]);
+
+               list_add_tail(&term->list, &dev->entities);
+               break;
+
+       case UVC_VC_OUTPUT_TERMINAL:
+               if (buflen < 9) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d OUTPUT_TERMINAL error\n",
+                               udev->devnum, alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               /* Make sure the terminal type MSB is not null, otherwise it
+                * could be confused with a unit.
+                */
+               type = get_unaligned_le16(&buffer[4]);
+               if ((type & 0xff00) == 0) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d OUTPUT_TERMINAL %d has invalid "
+                               "type 0x%04x, skipping\n", udev->devnum,
+                               alts->desc.bInterfaceNumber, buffer[3], type);
+                       return 0;
+               }
+
+               term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3],
+                                       1, 0);
+               if (term == NULL)
+                       return -ENOMEM;
+
+               memcpy(term->baSourceID, &buffer[7], 1);
+
+               if (buffer[8] != 0)
+                       usb_string(udev, buffer[8], term->name,
+                                  sizeof term->name);
+               else
+                       sprintf(term->name, "Output %u", buffer[3]);
+
+               list_add_tail(&term->list, &dev->entities);
+               break;
+
+       case UVC_VC_SELECTOR_UNIT:
+               p = buflen >= 5 ? buffer[4] : 0;
+
+               if (buflen < 5 || buflen < 6 + p) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d SELECTOR_UNIT error\n",
+                               udev->devnum, alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0);
+               if (unit == NULL)
+                       return -ENOMEM;
+
+               memcpy(unit->baSourceID, &buffer[5], p);
+
+               if (buffer[5+p] != 0)
+                       usb_string(udev, buffer[5+p], unit->name,
+                                  sizeof unit->name);
+               else
+                       sprintf(unit->name, "Selector %u", buffer[3]);
+
+               list_add_tail(&unit->list, &dev->entities);
+               break;
+
+       case UVC_VC_PROCESSING_UNIT:
+               n = buflen >= 8 ? buffer[7] : 0;
+               p = dev->uvc_version >= 0x0110 ? 10 : 9;
+
+               if (buflen < p + n) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d PROCESSING_UNIT error\n",
+                               udev->devnum, alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n);
+               if (unit == NULL)
+                       return -ENOMEM;
+
+               memcpy(unit->baSourceID, &buffer[4], 1);
+               unit->processing.wMaxMultiplier =
+                       get_unaligned_le16(&buffer[5]);
+               unit->processing.bControlSize = buffer[7];
+               unit->processing.bmControls = (__u8 *)unit + sizeof *unit;
+               memcpy(unit->processing.bmControls, &buffer[8], n);
+               if (dev->uvc_version >= 0x0110)
+                       unit->processing.bmVideoStandards = buffer[9+n];
+
+               if (buffer[8+n] != 0)
+                       usb_string(udev, buffer[8+n], unit->name,
+                                  sizeof unit->name);
+               else
+                       sprintf(unit->name, "Processing %u", buffer[3]);
+
+               list_add_tail(&unit->list, &dev->entities);
+               break;
+
+       case UVC_VC_EXTENSION_UNIT:
+               p = buflen >= 22 ? buffer[21] : 0;
+               n = buflen >= 24 + p ? buffer[22+p] : 0;
+
+               if (buflen < 24 + p + n) {
+                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
+                               "interface %d EXTENSION_UNIT error\n",
+                               udev->devnum, alts->desc.bInterfaceNumber);
+                       return -EINVAL;
+               }
+
+               unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n);
+               if (unit == NULL)
+                       return -ENOMEM;
+
+               memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
+               unit->extension.bNumControls = buffer[20];
+               memcpy(unit->baSourceID, &buffer[22], p);
+               unit->extension.bControlSize = buffer[22+p];
+               unit->extension.bmControls = (__u8 *)unit + sizeof *unit;
+               memcpy(unit->extension.bmControls, &buffer[23+p], n);
+
+               if (buffer[23+p+n] != 0)
+                       usb_string(udev, buffer[23+p+n], unit->name,
+                                  sizeof unit->name);
+               else
+                       sprintf(unit->name, "Extension %u", buffer[3]);
+
+               list_add_tail(&unit->list, &dev->entities);
+               break;
+
+       default:
+               uvc_trace(UVC_TRACE_DESCR, "Found an unknown CS_INTERFACE "
+                       "descriptor (%u)\n", buffer[2]);
+               break;
+       }
+
+       return 0;
+}
+
+static int uvc_parse_control(struct uvc_device *dev)
+{
+       struct usb_host_interface *alts = dev->intf->cur_altsetting;
+       unsigned char *buffer = alts->extra;
+       int buflen = alts->extralen;
+       int ret;
+
+       /* Parse the default alternate setting only, as the UVC specification
+        * defines a single alternate setting, the default alternate setting
+        * zero.
+        */
+
+       while (buflen > 2) {
+               if (uvc_parse_vendor_control(dev, buffer, buflen) ||
+                   buffer[1] != USB_DT_CS_INTERFACE)
+                       goto next_descriptor;
+
+               if ((ret = uvc_parse_standard_control(dev, buffer, buflen)) < 0)
+                       return ret;
+
+next_descriptor:
+               buflen -= buffer[0];
+               buffer += buffer[0];
+       }
+
+       /* Check if the optional status endpoint is present. Built-in iSight
+        * webcams have an interrupt endpoint but spit proprietary data that
+        * don't conform to the UVC status endpoint messages. Don't try to
+        * handle the interrupt endpoint for those cameras.
+        */
+       if (alts->desc.bNumEndpoints == 1 &&
+           !(dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)) {
+               struct usb_host_endpoint *ep = &alts->endpoint[0];
+               struct usb_endpoint_descriptor *desc = &ep->desc;
+
+               if (usb_endpoint_is_int_in(desc) &&
+                   le16_to_cpu(desc->wMaxPacketSize) >= 8 &&
+                   desc->bInterval != 0) {
+                       uvc_trace(UVC_TRACE_DESCR, "Found a Status endpoint "
+                               "(addr %02x).\n", desc->bEndpointAddress);
+                       dev->int_ep = ep;
+               }
+       }
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------------
+ * UVC device scan
+ */
+
+/*
+ * Scan the UVC descriptors to locate a chain starting at an Output Terminal
+ * and containing the following units:
+ *
+ * - one or more Output Terminals (USB Streaming or Display)
+ * - zero or one Processing Unit
+ * - zero, one or more single-input Selector Units
+ * - zero or one multiple-input Selector Units, provided all inputs are
+ *   connected to input terminals
+ * - zero, one or mode single-input Extension Units
+ * - one or more Input Terminals (Camera, External or USB Streaming)
+ *
+ * The terminal and units must match on of the following structures:
+ *
+ * ITT_*(0) -> +---------+    +---------+    +---------+ -> TT_STREAMING(0)
+ * ...         | SU{0,1} | -> | PU{0,1} | -> | XU{0,n} |    ...
+ * ITT_*(n) -> +---------+    +---------+    +---------+ -> TT_STREAMING(n)
+ *
+ *                 +---------+    +---------+ -> OTT_*(0)
+ * TT_STREAMING -> | PU{0,1} | -> | XU{0,n} |    ...
+ *                 +---------+    +---------+ -> OTT_*(n)
+ *
+ * The Processing Unit and Extension Units can be in any order. Additional
+ * Extension Units connected to the main chain as single-unit branches are
+ * also supported. Single-input Selector Units are ignored.
+ */
+static int uvc_scan_chain_entity(struct uvc_video_chain *chain,
+       struct uvc_entity *entity)
+{
+       switch (UVC_ENTITY_TYPE(entity)) {
+       case UVC_VC_EXTENSION_UNIT:
+               if (uvc_trace_param & UVC_TRACE_PROBE)
+                       printk(" <- XU %d", entity->id);
+
+               if (entity->bNrInPins != 1) {
+                       uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more "
+                               "than 1 input pin.\n", entity->id);
+                       return -1;
+               }
+
+               break;
+
+       case UVC_VC_PROCESSING_UNIT:
+               if (uvc_trace_param & UVC_TRACE_PROBE)
+                       printk(" <- PU %d", entity->id);
+
+               if (chain->processing != NULL) {
+                       uvc_trace(UVC_TRACE_DESCR, "Found multiple "
+                               "Processing Units in chain.\n");
+                       return -1;
+               }
+
+               chain->processing = entity;
+               break;
+
+       case UVC_VC_SELECTOR_UNIT:
+               if (uvc_trace_param & UVC_TRACE_PROBE)
+                       printk(" <- SU %d", entity->id);
+
+               /* Single-input selector units are ignored. */
+               if (entity->bNrInPins == 1)
+                       break;
+
+               if (chain->selector != NULL) {
+                       uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector "
+                               "Units in chain.\n");
+                       return -1;
+               }
+
+               chain->selector = entity;
+               break;
+
+       case UVC_ITT_VENDOR_SPECIFIC:
+       case UVC_ITT_CAMERA:
+       case UVC_ITT_MEDIA_TRANSPORT_INPUT:
+               if (uvc_trace_param & UVC_TRACE_PROBE)
+                       printk(" <- IT %d\n", entity->id);
+
+               break;
+
+       case UVC_OTT_VENDOR_SPECIFIC:
+       case UVC_OTT_DISPLAY:
+       case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
+               if (uvc_trace_param & UVC_TRACE_PROBE)
+                       printk(" OT %d", entity->id);
+
+               break;
+
+       case UVC_TT_STREAMING:
+               if (UVC_ENTITY_IS_ITERM(entity)) {
+                       if (uvc_trace_param & UVC_TRACE_PROBE)
+                               printk(" <- IT %d\n", entity->id);
+               } else {
+                       if (uvc_trace_param & UVC_TRACE_PROBE)
+                               printk(" OT %d", entity->id);
+               }
+
+               break;
+
+       default:
+               uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type "
+                       "0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity));
+               return -1;
+       }
+
+       list_add_tail(&entity->chain, &chain->entities);
+       return 0;
+}
+
+static int uvc_scan_chain_forward(struct uvc_video_chain *chain,
+       struct uvc_entity *entity, struct uvc_entity *prev)
+{
+       struct uvc_entity *forward;
+       int found;
+
+       /* Forward scan */
+       forward = NULL;
+       found = 0;
+
+       while (1) {
+               forward = uvc_entity_by_reference(chain->dev, entity->id,
+                       forward);
+               if (forward == NULL)
+                       break;
+               if (forward == prev)
+                       continue;
+
+               switch (UVC_ENTITY_TYPE(forward)) {
+               case UVC_VC_EXTENSION_UNIT:
+                       if (forward->bNrInPins != 1) {
+                               uvc_trace(UVC_TRACE_DESCR, "Extension unit %d "
+                                         "has more than 1 input pin.\n",
+                                         entity->id);
+                               return -EINVAL;
+                       }
+
+                       list_add_tail(&forward->chain, &chain->entities);
+                       if (uvc_trace_param & UVC_TRACE_PROBE) {
+                               if (!found)
+                                       printk(" (->");
+
+                               printk(" XU %d", forward->id);
+                               found = 1;
+                       }
+                       break;
+
+               case UVC_OTT_VENDOR_SPECIFIC:
+               case UVC_OTT_DISPLAY:
+               case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
+               case UVC_TT_STREAMING:
+                       if (UVC_ENTITY_IS_ITERM(forward)) {
+                               uvc_trace(UVC_TRACE_DESCR, "Unsupported input "
+                                       "terminal %u.\n", forward->id);
+                               return -EINVAL;
+                       }
+
+                       list_add_tail(&forward->chain, &chain->entities);
+                       if (uvc_trace_param & UVC_TRACE_PROBE) {
+                               if (!found)
+                                       printk(" (->");
+
+                               printk(" OT %d", forward->id);
+                               found = 1;
+                       }
+                       break;
+               }
+       }
+       if (found)
+               printk(")");
+
+       return 0;
+}
+
+static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
+       struct uvc_entity **_entity)
+{
+       struct uvc_entity *entity = *_entity;
+       struct uvc_entity *term;
+       int id = -EINVAL, i;
+
+       switch (UVC_ENTITY_TYPE(entity)) {
+       case UVC_VC_EXTENSION_UNIT:
+       case UVC_VC_PROCESSING_UNIT:
+               id = entity->baSourceID[0];
+               break;
+
+       case UVC_VC_SELECTOR_UNIT:
+               /* Single-input selector units are ignored. */
+               if (entity->bNrInPins == 1) {
+                       id = entity->baSourceID[0];
+                       break;
+               }
+
+               if (uvc_trace_param & UVC_TRACE_PROBE)
+                       printk(" <- IT");
+
+               chain->selector = entity;
+               for (i = 0; i < entity->bNrInPins; ++i) {
+                       id = entity->baSourceID[i];
+                       term = uvc_entity_by_id(chain->dev, id);
+                       if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) {
+                               uvc_trace(UVC_TRACE_DESCR, "Selector unit %d "
+                                       "input %d isn't connected to an "
+                                       "input terminal\n", entity->id, i);
+                               return -1;
+                       }
+
+                       if (uvc_trace_param & UVC_TRACE_PROBE)
+                               printk(" %d", term->id);
+
+                       list_add_tail(&term->chain, &chain->entities);
+                       uvc_scan_chain_forward(chain, term, entity);
+               }
+
+               if (uvc_trace_param & UVC_TRACE_PROBE)
+                       printk("\n");
+
+               id = 0;
+               break;
+
+       case UVC_ITT_VENDOR_SPECIFIC:
+       case UVC_ITT_CAMERA:
+       case UVC_ITT_MEDIA_TRANSPORT_INPUT:
+       case UVC_OTT_VENDOR_SPECIFIC:
+       case UVC_OTT_DISPLAY:
+       case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
+       case UVC_TT_STREAMING:
+               id = UVC_ENTITY_IS_OTERM(entity) ? entity->baSourceID[0] : 0;
+               break;
+       }
+
+       if (id <= 0) {
+               *_entity = NULL;
+               return id;
+       }
+
+       entity = uvc_entity_by_id(chain->dev, id);
+       if (entity == NULL) {
+               uvc_trace(UVC_TRACE_DESCR, "Found reference to "
+                       "unknown entity %d.\n", id);
+               return -EINVAL;
+       }
+
+       *_entity = entity;
+       return 0;
+}
+
+static int uvc_scan_chain(struct uvc_video_chain *chain,
+                         struct uvc_entity *term)
+{
+       struct uvc_entity *entity, *prev;
+
+       uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain:");
+
+       entity = term;
+       prev = NULL;
+
+       while (entity != NULL) {
+               /* Entity must not be part of an existing chain */
+               if (entity->chain.next || entity->chain.prev) {
+                       uvc_trace(UVC_TRACE_DESCR, "Found reference to "
+                               "entity %d already in chain.\n", entity->id);
+                       return -EINVAL;
+               }
+
+               /* Process entity */
+               if (uvc_scan_chain_entity(chain, entity) < 0)
+                       return -EINVAL;
+
+               /* Forward scan */
+               if (uvc_scan_chain_forward(chain, entity, prev) < 0)
+                       return -EINVAL;
+
+               /* Backward scan */
+               prev = entity;
+               if (uvc_scan_chain_backward(chain, &entity) < 0)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
+static unsigned int uvc_print_terms(struct list_head *terms, u16 dir,
+               char *buffer)
+{
+       struct uvc_entity *term;
+       unsigned int nterms = 0;
+       char *p = buffer;
+
+       list_for_each_entry(term, terms, chain) {
+               if (!UVC_ENTITY_IS_TERM(term) ||
+                   UVC_TERM_DIRECTION(term) != dir)
+                       continue;
+
+               if (nterms)
+                       p += sprintf(p, ",");
+               if (++nterms >= 4) {
+                       p += sprintf(p, "...");
+                       break;
+               }
+               p += sprintf(p, "%u", term->id);
+       }
+
+       return p - buffer;
+}
+
+static const char *uvc_print_chain(struct uvc_video_chain *chain)
+{
+       static char buffer[43];
+       char *p = buffer;
+
+       p += uvc_print_terms(&chain->entities, UVC_TERM_INPUT, p);
+       p += sprintf(p, " -> ");
+       uvc_print_terms(&chain->entities, UVC_TERM_OUTPUT, p);
+
+       return buffer;
+}
+
+/*
+ * Scan the device for video chains and register video devices.
+ *
+ * Chains are scanned starting at their output terminals and walked backwards.
+ */
+static int uvc_scan_device(struct uvc_device *dev)
+{
+       struct uvc_video_chain *chain;
+       struct uvc_entity *term;
+
+       list_for_each_entry(term, &dev->entities, list) {
+               if (!UVC_ENTITY_IS_OTERM(term))
+                       continue;
+
+               /* If the terminal is already included in a chain, skip it.
+                * This can happen for chains that have multiple output
+                * terminals, where all output terminals beside the first one
+                * will be inserted in the chain in forward scans.
+                */
+               if (term->chain.next || term->chain.prev)
+                       continue;
+
+               chain = kzalloc(sizeof(*chain), GFP_KERNEL);
+               if (chain == NULL)
+                       return -ENOMEM;
+
+               INIT_LIST_HEAD(&chain->entities);
+               mutex_init(&chain->ctrl_mutex);
+               chain->dev = dev;
+
+               if (uvc_scan_chain(chain, term) < 0) {
+                       kfree(chain);
+                       continue;
+               }
+
+               uvc_trace(UVC_TRACE_PROBE, "Found a valid video chain (%s).\n",
+                         uvc_print_chain(chain));
+
+               list_add_tail(&chain->list, &dev->chains);
+       }
+
+       if (list_empty(&dev->chains)) {
+               uvc_printk(KERN_INFO, "No valid video chain found.\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------------
+ * Video device registration and unregistration
+ */
+
+/*
+ * Delete the UVC device.
+ *
+ * Called by the kernel when the last reference to the uvc_device structure
+ * is released.
+ *
+ * As this function is called after or during disconnect(), all URBs have
+ * already been canceled by the USB core. There is no need to kill the
+ * interrupt URB manually.
+ */
+static void uvc_delete(struct uvc_device *dev)
+{
+       struct list_head *p, *n;
+
+       usb_put_intf(dev->intf);
+       usb_put_dev(dev->udev);
+
+       uvc_status_cleanup(dev);
+       uvc_ctrl_cleanup_device(dev);
+
+       if (dev->vdev.dev)
+               v4l2_device_unregister(&dev->vdev);
+#ifdef CONFIG_MEDIA_CONTROLLER
+       if (media_devnode_is_registered(&dev->mdev.devnode))
+               media_device_unregister(&dev->mdev);
+#endif
+
+       list_for_each_safe(p, n, &dev->chains) {
+               struct uvc_video_chain *chain;
+               chain = list_entry(p, struct uvc_video_chain, list);
+               kfree(chain);
+       }
+
+       list_for_each_safe(p, n, &dev->entities) {
+               struct uvc_entity *entity;
+               entity = list_entry(p, struct uvc_entity, list);
+#ifdef CONFIG_MEDIA_CONTROLLER
+               uvc_mc_cleanup_entity(entity);
+#endif
+               if (entity->vdev) {
+                       video_device_release(entity->vdev);
+                       entity->vdev = NULL;
+               }
+               kfree(entity);
+       }
+
+       list_for_each_safe(p, n, &dev->streams) {
+               struct uvc_streaming *streaming;
+               streaming = list_entry(p, struct uvc_streaming, list);
+               usb_driver_release_interface(&uvc_driver.driver,
+                       streaming->intf);
+               usb_put_intf(streaming->intf);
+               kfree(streaming->format);
+               kfree(streaming->header.bmaControls);
+               kfree(streaming);
+       }
+
+       kfree(dev);
+}
+
+static void uvc_release(struct video_device *vdev)
+{
+       struct uvc_streaming *stream = video_get_drvdata(vdev);
+       struct uvc_device *dev = stream->dev;
+
+       /* Decrement the registered streams count and delete the device when it
+        * reaches zero.
+        */
+       if (atomic_dec_and_test(&dev->nstreams))
+               uvc_delete(dev);
+}
+
+/*
+ * Unregister the video devices.
+ */
+static void uvc_unregister_video(struct uvc_device *dev)
+{
+       struct uvc_streaming *stream;
+
+       /* Unregistering all video devices might result in uvc_delete() being
+        * called from inside the loop if there's no open file handle. To avoid
+        * that, increment the stream count before iterating over the streams
+        * and decrement it when done.
+        */
+       atomic_inc(&dev->nstreams);
+
+       list_for_each_entry(stream, &dev->streams, list) {
+               if (stream->vdev == NULL)
+                       continue;
+
+               video_unregister_device(stream->vdev);
+               stream->vdev = NULL;
+
+               uvc_debugfs_cleanup_stream(stream);
+       }
+
+       /* Decrement the stream count and call uvc_delete explicitly if there
+        * are no stream left.
+        */
+       if (atomic_dec_and_test(&dev->nstreams))
+               uvc_delete(dev);
+}
+
+static int uvc_register_video(struct uvc_device *dev,
+               struct uvc_streaming *stream)
+{
+       struct video_device *vdev;
+       int ret;
+
+       /* Initialize the streaming interface with default streaming
+        * parameters.
+        */
+       ret = uvc_video_init(stream);
+       if (ret < 0) {
+               uvc_printk(KERN_ERR, "Failed to initialize the device "
+                       "(%d).\n", ret);
+               return ret;
+       }
+
+       uvc_debugfs_init_stream(stream);
+
+       /* Register the device with V4L. */
+       vdev = video_device_alloc();
+       if (vdev == NULL) {
+               uvc_printk(KERN_ERR, "Failed to allocate video device (%d).\n",
+                          ret);
+               return -ENOMEM;
+       }
+
+       /* We already hold a reference to dev->udev. The video device will be
+        * unregistered before the reference is released, so we don't need to
+        * get another one.
+        */
+       vdev->v4l2_dev = &dev->vdev;
+       vdev->fops = &uvc_fops;
+       vdev->release = uvc_release;
+       strlcpy(vdev->name, dev->name, sizeof vdev->name);
+
+       /* Set the driver data before calling video_register_device, otherwise
+        * uvc_v4l2_open might race us.
+        */
+       stream->vdev = vdev;
+       video_set_drvdata(vdev, stream);
+
+       ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+       if (ret < 0) {
+               uvc_printk(KERN_ERR, "Failed to register video device (%d).\n",
+                          ret);
+               stream->vdev = NULL;
+               video_device_release(vdev);
+               return ret;
+       }
+
+       atomic_inc(&dev->nstreams);
+       return 0;
+}
+
+/*
+ * Register all video devices in all chains.
+ */
+static int uvc_register_terms(struct uvc_device *dev,
+       struct uvc_video_chain *chain)
+{
+       struct uvc_streaming *stream;
+       struct uvc_entity *term;
+       int ret;
+
+       list_for_each_entry(term, &chain->entities, chain) {
+               if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING)
+                       continue;
+
+               stream = uvc_stream_by_id(dev, term->id);
+               if (stream == NULL) {
+                       uvc_printk(KERN_INFO, "No streaming interface found "
+                                  "for terminal %u.", term->id);
+                       continue;
+               }
+
+               stream->chain = chain;
+               ret = uvc_register_video(dev, stream);
+               if (ret < 0)
+                       return ret;
+
+               term->vdev = stream->vdev;
+       }
+
+       return 0;
+}
+
+static int uvc_register_chains(struct uvc_device *dev)
+{
+       struct uvc_video_chain *chain;
+       int ret;
+
+       list_for_each_entry(chain, &dev->chains, list) {
+               ret = uvc_register_terms(dev, chain);
+               if (ret < 0)
+                       return ret;
+
+#ifdef CONFIG_MEDIA_CONTROLLER
+               ret = uvc_mc_register_entities(chain);
+               if (ret < 0) {
+                       uvc_printk(KERN_INFO, "Failed to register entites "
+                               "(%d).\n", ret);
+               }
+#endif
+       }
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------------
+ * USB probe, disconnect, suspend and resume
+ */
+
+static int uvc_probe(struct usb_interface *intf,
+                    const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct uvc_device *dev;
+       int ret;
+
+       if (id->idVendor && id->idProduct)
+               uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s "
+                               "(%04x:%04x)\n", udev->devpath, id->idVendor,
+                               id->idProduct);
+       else
+               uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",
+                               udev->devpath);
+
+       /* Allocate memory for the device and initialize it. */
+       if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&dev->entities);
+       INIT_LIST_HEAD(&dev->chains);
+       INIT_LIST_HEAD(&dev->streams);
+       atomic_set(&dev->nstreams, 0);
+       atomic_set(&dev->users, 0);
+       atomic_set(&dev->nmappings, 0);
+
+       dev->udev = usb_get_dev(udev);
+       dev->intf = usb_get_intf(intf);
+       dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
+       dev->quirks = (uvc_quirks_param == -1)
+                   ? id->driver_info : uvc_quirks_param;
+
+       if (udev->product != NULL)
+               strlcpy(dev->name, udev->product, sizeof dev->name);
+       else
+               snprintf(dev->name, sizeof dev->name,
+                       "UVC Camera (%04x:%04x)",
+                       le16_to_cpu(udev->descriptor.idVendor),
+                       le16_to_cpu(udev->descriptor.idProduct));
+
+       /* Parse the Video Class control descriptor. */
+       if (uvc_parse_control(dev) < 0) {
+               uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
+                       "descriptors.\n");
+               goto error;
+       }
+
+       uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",
+               dev->uvc_version >> 8, dev->uvc_version & 0xff,
+               udev->product ? udev->product : "<unnamed>",
+               le16_to_cpu(udev->descriptor.idVendor),
+               le16_to_cpu(udev->descriptor.idProduct));
+
+       if (dev->quirks != id->driver_info) {
+               uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module "
+                       "parameter for testing purpose.\n", dev->quirks);
+               uvc_printk(KERN_INFO, "Please report required quirks to the "
+                       "linux-uvc-devel mailing list.\n");
+       }
+
+       /* Register the media and V4L2 devices. */
+#ifdef CONFIG_MEDIA_CONTROLLER
+       dev->mdev.dev = &intf->dev;
+       strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
+       if (udev->serial)
+               strlcpy(dev->mdev.serial, udev->serial,
+                       sizeof(dev->mdev.serial));
+       strcpy(dev->mdev.bus_info, udev->devpath);
+       dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
+       dev->mdev.driver_version = LINUX_VERSION_CODE;
+       if (media_device_register(&dev->mdev) < 0)
+               goto error;
+
+       dev->vdev.mdev = &dev->mdev;
+#endif
+       if (v4l2_device_register(&intf->dev, &dev->vdev) < 0)
+               goto error;
+
+       /* Initialize controls. */
+       if (uvc_ctrl_init_device(dev) < 0)
+               goto error;
+
+       /* Scan the device for video chains. */
+       if (uvc_scan_device(dev) < 0)
+               goto error;
+
+       /* Register video device nodes. */
+       if (uvc_register_chains(dev) < 0)
+               goto error;
+
+       /* Save our data pointer in the interface data. */
+       usb_set_intfdata(intf, dev);
+
+       /* Initialize the interrupt URB. */
+       if ((ret = uvc_status_init(dev)) < 0) {
+               uvc_printk(KERN_INFO, "Unable to initialize the status "
+                       "endpoint (%d), status interrupt will not be "
+                       "supported.\n", ret);
+       }
+
+       uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n");
+       usb_enable_autosuspend(udev);
+       return 0;
+
+error:
+       uvc_unregister_video(dev);
+       return -ENODEV;
+}
+
+static void uvc_disconnect(struct usb_interface *intf)
+{
+       struct uvc_device *dev = usb_get_intfdata(intf);
+
+       /* Set the USB interface data to NULL. This can be done outside the
+        * lock, as there's no other reader.
+        */
+       usb_set_intfdata(intf, NULL);
+
+       if (intf->cur_altsetting->desc.bInterfaceSubClass ==
+           UVC_SC_VIDEOSTREAMING)
+               return;
+
+       dev->state |= UVC_DEV_DISCONNECTED;
+
+       uvc_unregister_video(dev);
+}
+
+static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct uvc_device *dev = usb_get_intfdata(intf);
+       struct uvc_streaming *stream;
+
+       uvc_trace(UVC_TRACE_SUSPEND, "Suspending interface %u\n",
+               intf->cur_altsetting->desc.bInterfaceNumber);
+
+       /* Controls are cached on the fly so they don't need to be saved. */
+       if (intf->cur_altsetting->desc.bInterfaceSubClass ==
+           UVC_SC_VIDEOCONTROL)
+               return uvc_status_suspend(dev);
+
+       list_for_each_entry(stream, &dev->streams, list) {
+               if (stream->intf == intf)
+                       return uvc_video_suspend(stream);
+       }
+
+       uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB interface "
+                       "mismatch.\n");
+       return -EINVAL;
+}
+
+static int __uvc_resume(struct usb_interface *intf, int reset)
+{
+       struct uvc_device *dev = usb_get_intfdata(intf);
+       struct uvc_streaming *stream;
+
+       uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
+               intf->cur_altsetting->desc.bInterfaceNumber);
+
+       if (intf->cur_altsetting->desc.bInterfaceSubClass ==
+           UVC_SC_VIDEOCONTROL) {
+               if (reset) {
+                       int ret = uvc_ctrl_resume_device(dev);
+
+                       if (ret < 0)
+                               return ret;
+               }
+
+               return uvc_status_resume(dev);
+       }
+
+       list_for_each_entry(stream, &dev->streams, list) {
+               if (stream->intf == intf)
+                       return uvc_video_resume(stream, reset);
+       }
+
+       uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface "
+                       "mismatch.\n");
+       return -EINVAL;
+}
+
+static int uvc_resume(struct usb_interface *intf)
+{
+       return __uvc_resume(intf, 0);
+}
+
+static int uvc_reset_resume(struct usb_interface *intf)
+{
+       return __uvc_resume(intf, 1);
+}
+
+/* ------------------------------------------------------------------------
+ * Module parameters
+ */
+
+static int uvc_clock_param_get(char *buffer, struct kernel_param *kp)
+{
+       if (uvc_clock_param == CLOCK_MONOTONIC)
+               return sprintf(buffer, "CLOCK_MONOTONIC");
+       else
+               return sprintf(buffer, "CLOCK_REALTIME");
+}
+
+static int uvc_clock_param_set(const char *val, struct kernel_param *kp)
+{
+       if (strncasecmp(val, "clock_", strlen("clock_")) == 0)
+               val += strlen("clock_");
+
+       if (strcasecmp(val, "monotonic") == 0)
+               uvc_clock_param = CLOCK_MONOTONIC;
+       else if (strcasecmp(val, "realtime") == 0)
+               uvc_clock_param = CLOCK_REALTIME;
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+module_param_call(clock, uvc_clock_param_set, uvc_clock_param_get,
+                 &uvc_clock_param, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(clock, "Video buffers timestamp clock");
+module_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames");
+module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(quirks, "Forced device quirks");
+module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(trace, "Trace level bitmask");
+module_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(timeout, "Streaming control requests timeout");
+
+/* ------------------------------------------------------------------------
+ * Driver initialization and cleanup
+ */
+
+/*
+ * The Logitech cameras listed below have their interface class set to
+ * VENDOR_SPEC because they don't announce themselves as UVC devices, even
+ * though they are compliant.
+ */
+static struct usb_device_id uvc_ids[] = {
+       /* LogiLink Wireless Webcam */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x0416,
+         .idProduct            = 0xa91a,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Genius eFace 2025 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x0458,
+         .idProduct            = 0x706e,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Microsoft Lifecam NX-6000 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x045e,
+         .idProduct            = 0x00f8,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Microsoft Lifecam VX-7000 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x045e,
+         .idProduct            = 0x0723,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Logitech Quickcam Fusion */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x046d,
+         .idProduct            = 0x08c1,
+         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0 },
+       /* Logitech Quickcam Orbit MP */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x046d,
+         .idProduct            = 0x08c2,
+         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0 },
+       /* Logitech Quickcam Pro for Notebook */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x046d,
+         .idProduct            = 0x08c3,
+         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0 },
+       /* Logitech Quickcam Pro 5000 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x046d,
+         .idProduct            = 0x08c5,
+         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0 },
+       /* Logitech Quickcam OEM Dell Notebook */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x046d,
+         .idProduct            = 0x08c6,
+         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0 },
+       /* Logitech Quickcam OEM Cisco VT Camera II */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x046d,
+         .idProduct            = 0x08c7,
+         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0 },
+       /* Chicony CNF7129 (Asus EEE 100HE) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x04f2,
+         .idProduct            = 0xb071,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_RESTRICT_FRAME_RATE },
+       /* Alcor Micro AU3820 (Future Boy PC USB Webcam) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x058f,
+         .idProduct            = 0x3820,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Dell XPS m1530 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x05a9,
+         .idProduct            = 0x2640,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_DEF },
+       /* Apple Built-In iSight */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x05ac,
+         .idProduct            = 0x8501,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX
+                               | UVC_QUIRK_BUILTIN_ISIGHT },
+       /* Foxlink ("HP Webcam" on HP Mini 5103) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x05c8,
+         .idProduct            = 0x0403,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_FIX_BANDWIDTH },
+       /* Genesys Logic USB 2.0 PC Camera */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x05e3,
+         .idProduct            = 0x0505,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
+       /* Hercules Classic Silver */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x06f8,
+         .idProduct            = 0x300c,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_FIX_BANDWIDTH },
+       /* ViMicro Vega */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x0ac8,
+         .idProduct            = 0x332d,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_FIX_BANDWIDTH },
+       /* ViMicro - Minoru3D */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x0ac8,
+         .idProduct            = 0x3410,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_FIX_BANDWIDTH },
+       /* ViMicro Venus - Minoru3D */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x0ac8,
+         .idProduct            = 0x3420,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_FIX_BANDWIDTH },
+       /* Ophir Optronics - SPCAM 620U */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x0bd3,
+         .idProduct            = 0x0555,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* MT6227 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x0e8d,
+         .idProduct            = 0x0004,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX
+                               | UVC_QUIRK_PROBE_DEF },
+       /* IMC Networks (Medion Akoya) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x13d3,
+         .idProduct            = 0x5103,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
+       /* JMicron USB2.0 XGA WebCam */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x152d,
+         .idProduct            = 0x0310,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Syntek (HP Spartan) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x174f,
+         .idProduct            = 0x5212,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
+       /* Syntek (Samsung Q310) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x174f,
+         .idProduct            = 0x5931,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
+       /* Syntek (Packard Bell EasyNote MX52 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x174f,
+         .idProduct            = 0x8a12,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
+       /* Syntek (Asus F9SG) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x174f,
+         .idProduct            = 0x8a31,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
+       /* Syntek (Asus U3S) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x174f,
+         .idProduct            = 0x8a33,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
+       /* Syntek (JAOtech Smart Terminal) */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x174f,
+         .idProduct            = 0x8a34,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
+       /* Miricle 307K */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x17dc,
+         .idProduct            = 0x0202,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
+       /* Lenovo Thinkpad SL400/SL500 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x17ef,
+         .idProduct            = 0x480b,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
+       /* Aveo Technology USB 2.0 Camera */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x1871,
+         .idProduct            = 0x0306,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX
+                               | UVC_QUIRK_PROBE_EXTRAFIELDS },
+       /* Ecamm Pico iMage */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x18cd,
+         .idProduct            = 0xcafe,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_EXTRAFIELDS },
+       /* Manta MM-353 Plako */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x18ec,
+         .idProduct            = 0x3188,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* FSC WebCam V30S */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x18ec,
+         .idProduct            = 0x3288,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* Arkmicro unbranded */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x18ec,
+         .idProduct            = 0x3290,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_DEF },
+       /* The Imaging Source USB CCD cameras */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x199e,
+         .idProduct            = 0x8102,
+         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0 },
+       /* Bodelin ProScopeHR */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_DEV_HI
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x19ab,
+         .idProduct            = 0x1000,
+         .bcdDevice_hi         = 0x0126,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_STATUS_INTERVAL },
+       /* MSI StarCam 370i */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x1b3b,
+         .idProduct            = 0x2951,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
+       /* SiGma Micro USB Web Camera */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x1c4f,
+         .idProduct            = 0x3000,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX
+                               | UVC_QUIRK_IGNORE_SELECTOR_UNIT },
+       /* Generic USB Video Class */
+       { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, uvc_ids);
+
+struct uvc_driver uvc_driver = {
+       .driver = {
+               .name           = "uvcvideo",
+               .probe          = uvc_probe,
+               .disconnect     = uvc_disconnect,
+               .suspend        = uvc_suspend,
+               .resume         = uvc_resume,
+               .reset_resume   = uvc_reset_resume,
+               .id_table       = uvc_ids,
+               .supports_autosuspend = 1,
+       },
+};
+
+static int __init uvc_init(void)
+{
+       int ret;
+
+       uvc_debugfs_init();
+
+       ret = usb_register(&uvc_driver.driver);
+       if (ret < 0) {
+               uvc_debugfs_cleanup();
+               return ret;
+       }
+
+       printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");
+       return 0;
+}
+
+static void __exit uvc_cleanup(void)
+{
+       usb_deregister(&uvc_driver.driver);
+       uvc_debugfs_cleanup();
+}
+
+module_init(uvc_init);
+module_exit(uvc_cleanup);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
+
diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c
new file mode 100644 (file)
index 0000000..29e2399
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ *      uvc_entity.c  --  USB Video Class driver
+ *
+ *      Copyright (C) 2005-2011
+ *          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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-common.h>
+
+#include "uvcvideo.h"
+
+/* ------------------------------------------------------------------------
+ * Video subdevices registration and unregistration
+ */
+
+static int uvc_mc_register_entity(struct uvc_video_chain *chain,
+       struct uvc_entity *entity)
+{
+       const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE;
+       struct media_entity *sink;
+       unsigned int i;
+       int ret;
+
+       sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING)
+            ? (entity->vdev ? &entity->vdev->entity : NULL)
+            : &entity->subdev.entity;
+       if (sink == NULL)
+               return 0;
+
+       for (i = 0; i < entity->num_pads; ++i) {
+               struct media_entity *source;
+               struct uvc_entity *remote;
+               u8 remote_pad;
+
+               if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK))
+                       continue;
+
+               remote = uvc_entity_by_id(chain->dev, entity->baSourceID[i]);
+               if (remote == NULL)
+                       return -EINVAL;
+
+               source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING)
+                      ? (remote->vdev ? &remote->vdev->entity : NULL)
+                      : &remote->subdev.entity;
+               if (source == NULL)
+                       continue;
+
+               remote_pad = remote->num_pads - 1;
+               ret = media_entity_create_link(source, remote_pad,
+                                              sink, i, flags);
+               if (ret < 0)
+                       return ret;
+       }
+
+       if (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING)
+               return 0;
+
+       return v4l2_device_register_subdev(&chain->dev->vdev, &entity->subdev);
+}
+
+static struct v4l2_subdev_ops uvc_subdev_ops = {
+};
+
+void uvc_mc_cleanup_entity(struct uvc_entity *entity)
+{
+       if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING)
+               media_entity_cleanup(&entity->subdev.entity);
+       else if (entity->vdev != NULL)
+               media_entity_cleanup(&entity->vdev->entity);
+}
+
+static int uvc_mc_init_entity(struct uvc_entity *entity)
+{
+       int ret;
+
+       if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) {
+               v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops);
+               strlcpy(entity->subdev.name, entity->name,
+                       sizeof(entity->subdev.name));
+
+               ret = media_entity_init(&entity->subdev.entity,
+                                       entity->num_pads, entity->pads, 0);
+       } else if (entity->vdev != NULL) {
+               ret = media_entity_init(&entity->vdev->entity,
+                                       entity->num_pads, entity->pads, 0);
+       } else
+               ret = 0;
+
+       return ret;
+}
+
+int uvc_mc_register_entities(struct uvc_video_chain *chain)
+{
+       struct uvc_entity *entity;
+       int ret;
+
+       list_for_each_entry(entity, &chain->entities, chain) {
+               ret = uvc_mc_init_entity(entity);
+               if (ret < 0) {
+                       uvc_printk(KERN_INFO, "Failed to initialize entity for "
+                                  "entity %u\n", entity->id);
+                       return ret;
+               }
+       }
+
+       list_for_each_entry(entity, &chain->entities, chain) {
+               ret = uvc_mc_register_entity(chain, entity);
+               if (ret < 0) {
+                       uvc_printk(KERN_INFO, "Failed to register entity for "
+                                  "entity %u\n", entity->id);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
diff --git a/drivers/media/usb/uvc/uvc_isight.c b/drivers/media/usb/uvc/uvc_isight.c
new file mode 100644 (file)
index 0000000..8510e72
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ *      uvc_isight.c  --  USB Video Class driver - iSight support
+ *
+ *     Copyright (C) 2006-2007
+ *             Ivan N. Zlatev <contact@i-nz.net>
+ *     Copyright (C) 2008-2009
+ *             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.
+ *
+ */
+
+#include <linux/usb.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include "uvcvideo.h"
+
+/* Built-in iSight webcams implements most of UVC 1.0 except a
+ * different packet format. Instead of sending a header at the
+ * beginning of each isochronous transfer payload, the webcam sends a
+ * single header per image (on its own in a packet), followed by
+ * packets containing data only.
+ *
+ * Offset   Size (bytes)       Description
+ * ------------------------------------------------------------------
+ * 0x00        1       Header length
+ * 0x01        1       Flags (UVC-compliant)
+ * 0x02        4       Always equal to '11223344'
+ * 0x06        8       Always equal to 'deadbeefdeadface'
+ * 0x0e        16      Unknown
+ *
+ * The header can be prefixed by an optional, unknown-purpose byte.
+ */
+
+static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf,
+               const __u8 *data, unsigned int len)
+{
+       static const __u8 hdr[] = {
+               0x11, 0x22, 0x33, 0x44,
+               0xde, 0xad, 0xbe, 0xef,
+               0xde, 0xad, 0xfa, 0xce
+       };
+
+       unsigned int maxlen, nbytes;
+       __u8 *mem;
+       int is_header = 0;
+
+       if (buf == NULL)
+               return 0;
+
+       if ((len >= 14 && memcmp(&data[2], hdr, 12) == 0) ||
+           (len >= 15 && memcmp(&data[3], hdr, 12) == 0)) {
+               uvc_trace(UVC_TRACE_FRAME, "iSight header found\n");
+               is_header = 1;
+       }
+
+       /* Synchronize to the input stream by waiting for a header packet. */
+       if (buf->state != UVC_BUF_STATE_ACTIVE) {
+               if (!is_header) {
+                       uvc_trace(UVC_TRACE_FRAME, "Dropping packet (out of "
+                                 "sync).\n");
+                       return 0;
+               }
+
+               buf->state = UVC_BUF_STATE_ACTIVE;
+       }
+
+       /* Mark the buffer as done if we're at the beginning of a new frame.
+        *
+        * Empty buffers (bytesused == 0) don't trigger end of frame detection
+        * as it doesn't make sense to return an empty buffer.
+        */
+       if (is_header && buf->bytesused != 0) {
+               buf->state = UVC_BUF_STATE_DONE;
+               return -EAGAIN;
+       }
+
+       /* Copy the video data to the buffer. Skip header packets, as they
+        * contain no data.
+        */
+       if (!is_header) {
+               maxlen = buf->length - buf->bytesused;
+               mem = buf->mem + buf->bytesused;
+               nbytes = min(len, maxlen);
+               memcpy(mem, data, nbytes);
+               buf->bytesused += nbytes;
+
+               if (len > maxlen || buf->bytesused == buf->length) {
+                       uvc_trace(UVC_TRACE_FRAME, "Frame complete "
+                                 "(overflow).\n");
+                       buf->state = UVC_BUF_STATE_DONE;
+               }
+       }
+
+       return 0;
+}
+
+void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream,
+               struct uvc_buffer *buf)
+{
+       int ret, i;
+
+       for (i = 0; i < urb->number_of_packets; ++i) {
+               if (urb->iso_frame_desc[i].status < 0) {
+                       uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame "
+                                 "lost (%d).\n",
+                                 urb->iso_frame_desc[i].status);
+               }
+
+               /* Decode the payload packet.
+                * uvc_video_decode is entered twice when a frame transition
+                * has been detected because the end of frame can only be
+                * reliably detected when the first packet of the new frame
+                * is processed. The first pass detects the transition and
+                * closes the previous frame's buffer, the second pass
+                * processes the data of the first payload of the new frame.
+                */
+               do {
+                       ret = isight_decode(&stream->queue, buf,
+                                       urb->transfer_buffer +
+                                       urb->iso_frame_desc[i].offset,
+                                       urb->iso_frame_desc[i].actual_length);
+
+                       if (buf == NULL)
+                               break;
+
+                       if (buf->state == UVC_BUF_STATE_DONE ||
+                           buf->state == UVC_BUF_STATE_ERROR)
+                               buf = uvc_queue_next_buffer(&stream->queue,
+                                                       buf);
+               } while (ret == -EAGAIN);
+       }
+}
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
new file mode 100644 (file)
index 0000000..9288fbd
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ *      uvc_queue.c  --  USB Video Class driver - Buffers management
+ *
+ *      Copyright (C) 2005-2010
+ *          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.
+ *
+ */
+
+#include <linux/atomic.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+#include <media/videobuf2-vmalloc.h>
+
+#include "uvcvideo.h"
+
+/* ------------------------------------------------------------------------
+ * Video buffers queue management.
+ *
+ * Video queues is initialized by uvc_queue_init(). The function performs
+ * basic initialization of the uvc_video_queue struct and never fails.
+ *
+ * Video buffers are managed by videobuf2. The driver uses a mutex to protect
+ * the videobuf2 queue operations by serializing calls to videobuf2 and a
+ * spinlock to protect the IRQ queue that holds the buffers to be processed by
+ * the driver.
+ */
+
+/* -----------------------------------------------------------------------------
+ * videobuf2 queue operations
+ */
+
+static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+                          unsigned int *nbuffers, unsigned int *nplanes,
+                          unsigned int sizes[], void *alloc_ctxs[])
+{
+       struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
+       struct uvc_streaming *stream =
+                       container_of(queue, struct uvc_streaming, queue);
+
+       if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
+               *nbuffers = UVC_MAX_VIDEO_BUFFERS;
+
+       *nplanes = 1;
+
+       sizes[0] = stream->ctrl.dwMaxVideoFrameSize;
+
+       return 0;
+}
+
+static int uvc_buffer_prepare(struct vb2_buffer *vb)
+{
+       struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+       struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+
+       if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+           vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
+               uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
+               return -EINVAL;
+       }
+
+       if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED))
+               return -ENODEV;
+
+       buf->state = UVC_BUF_STATE_QUEUED;
+       buf->error = 0;
+       buf->mem = vb2_plane_vaddr(vb, 0);
+       buf->length = vb2_plane_size(vb, 0);
+       if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               buf->bytesused = 0;
+       else
+               buf->bytesused = vb2_get_plane_payload(vb, 0);
+
+       return 0;
+}
+
+static void uvc_buffer_queue(struct vb2_buffer *vb)
+{
+       struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+       struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+       unsigned long flags;
+
+       spin_lock_irqsave(&queue->irqlock, flags);
+       if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
+               list_add_tail(&buf->queue, &queue->irqqueue);
+       } else {
+               /* If the device is disconnected return the buffer to userspace
+                * directly. The next QBUF call will fail with -ENODEV.
+                */
+               buf->state = UVC_BUF_STATE_ERROR;
+               vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+       }
+
+       spin_unlock_irqrestore(&queue->irqlock, flags);
+}
+
+static int uvc_buffer_finish(struct vb2_buffer *vb)
+{
+       struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+       struct uvc_streaming *stream =
+                       container_of(queue, struct uvc_streaming, queue);
+       struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+
+       uvc_video_clock_update(stream, &vb->v4l2_buf, buf);
+       return 0;
+}
+
+static struct vb2_ops uvc_queue_qops = {
+       .queue_setup = uvc_queue_setup,
+       .buf_prepare = uvc_buffer_prepare,
+       .buf_queue = uvc_buffer_queue,
+       .buf_finish = uvc_buffer_finish,
+};
+
+void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
+                   int drop_corrupted)
+{
+       queue->queue.type = type;
+       queue->queue.io_modes = VB2_MMAP | VB2_USERPTR;
+       queue->queue.drv_priv = queue;
+       queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
+       queue->queue.ops = &uvc_queue_qops;
+       queue->queue.mem_ops = &vb2_vmalloc_memops;
+       vb2_queue_init(&queue->queue);
+
+       mutex_init(&queue->mutex);
+       spin_lock_init(&queue->irqlock);
+       INIT_LIST_HEAD(&queue->irqqueue);
+       queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 queue operations
+ */
+
+int uvc_alloc_buffers(struct uvc_video_queue *queue,
+                     struct v4l2_requestbuffers *rb)
+{
+       int ret;
+
+       mutex_lock(&queue->mutex);
+       ret = vb2_reqbufs(&queue->queue, rb);
+       mutex_unlock(&queue->mutex);
+
+       return ret ? ret : rb->count;
+}
+
+void uvc_free_buffers(struct uvc_video_queue *queue)
+{
+       mutex_lock(&queue->mutex);
+       vb2_queue_release(&queue->queue);
+       mutex_unlock(&queue->mutex);
+}
+
+int uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
+{
+       int ret;
+
+       mutex_lock(&queue->mutex);
+       ret = vb2_querybuf(&queue->queue, buf);
+       mutex_unlock(&queue->mutex);
+
+       return ret;
+}
+
+int uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
+{
+       int ret;
+
+       mutex_lock(&queue->mutex);
+       ret = vb2_qbuf(&queue->queue, buf);
+       mutex_unlock(&queue->mutex);
+
+       return ret;
+}
+
+int uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf,
+                      int nonblocking)
+{
+       int ret;
+
+       mutex_lock(&queue->mutex);
+       ret = vb2_dqbuf(&queue->queue, buf, nonblocking);
+       mutex_unlock(&queue->mutex);
+
+       return ret;
+}
+
+int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
+{
+       int ret;
+
+       mutex_lock(&queue->mutex);
+       ret = vb2_mmap(&queue->queue, vma);
+       mutex_unlock(&queue->mutex);
+
+       return ret;
+}
+
+#ifndef CONFIG_MMU
+unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
+               unsigned long pgoff)
+{
+       unsigned long ret;
+
+       mutex_lock(&queue->mutex);
+       ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0);
+       mutex_unlock(&queue->mutex);
+       return ret;
+}
+#endif
+
+unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
+                           poll_table *wait)
+{
+       unsigned int ret;
+
+       mutex_lock(&queue->mutex);
+       ret = vb2_poll(&queue->queue, file, wait);
+       mutex_unlock(&queue->mutex);
+
+       return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ *
+ */
+
+/*
+ * Check if buffers have been allocated.
+ */
+int uvc_queue_allocated(struct uvc_video_queue *queue)
+{
+       int allocated;
+
+       mutex_lock(&queue->mutex);
+       allocated = vb2_is_busy(&queue->queue);
+       mutex_unlock(&queue->mutex);
+
+       return allocated;
+}
+
+/*
+ * Enable or disable the video buffers queue.
+ *
+ * The queue must be enabled before starting video acquisition and must be
+ * disabled after stopping it. This ensures that the video buffers queue
+ * state can be properly initialized before buffers are accessed from the
+ * interrupt handler.
+ *
+ * Enabling the video queue returns -EBUSY if the queue is already enabled.
+ *
+ * Disabling the video queue cancels the queue and removes all buffers from
+ * the main queue.
+ *
+ * This function can't be called from interrupt context. Use
+ * uvc_queue_cancel() instead.
+ */
+int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
+{
+       unsigned long flags;
+       int ret;
+
+       mutex_lock(&queue->mutex);
+       if (enable) {
+               ret = vb2_streamon(&queue->queue, queue->queue.type);
+               if (ret < 0)
+                       goto done;
+
+               queue->buf_used = 0;
+       } else {
+               ret = vb2_streamoff(&queue->queue, queue->queue.type);
+               if (ret < 0)
+                       goto done;
+
+               spin_lock_irqsave(&queue->irqlock, flags);
+               INIT_LIST_HEAD(&queue->irqqueue);
+               spin_unlock_irqrestore(&queue->irqlock, flags);
+       }
+
+done:
+       mutex_unlock(&queue->mutex);
+       return ret;
+}
+
+/*
+ * Cancel the video buffers queue.
+ *
+ * Cancelling the queue marks all buffers on the irq queue as erroneous,
+ * wakes them up and removes them from the queue.
+ *
+ * If the disconnect parameter is set, further calls to uvc_queue_buffer will
+ * fail with -ENODEV.
+ *
+ * This function acquires the irq spinlock and can be called from interrupt
+ * context.
+ */
+void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
+{
+       struct uvc_buffer *buf;
+       unsigned long flags;
+
+       spin_lock_irqsave(&queue->irqlock, flags);
+       while (!list_empty(&queue->irqqueue)) {
+               buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
+                                      queue);
+               list_del(&buf->queue);
+               buf->state = UVC_BUF_STATE_ERROR;
+               vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+       }
+       /* This must be protected by the irqlock spinlock to avoid race
+        * conditions between uvc_buffer_queue and the disconnection event that
+        * could result in an interruptible wait in uvc_dequeue_buffer. Do not
+        * blindly replace this logic by checking for the UVC_QUEUE_DISCONNECTED
+        * state outside the queue code.
+        */
+       if (disconnect)
+               queue->flags |= UVC_QUEUE_DISCONNECTED;
+       spin_unlock_irqrestore(&queue->irqlock, flags);
+}
+
+struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
+               struct uvc_buffer *buf)
+{
+       struct uvc_buffer *nextbuf;
+       unsigned long flags;
+
+       if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) {
+               buf->error = 0;
+               buf->state = UVC_BUF_STATE_QUEUED;
+               vb2_set_plane_payload(&buf->buf, 0, 0);
+               return buf;
+       }
+
+       spin_lock_irqsave(&queue->irqlock, flags);
+       list_del(&buf->queue);
+       if (!list_empty(&queue->irqqueue))
+               nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
+                                          queue);
+       else
+               nextbuf = NULL;
+       spin_unlock_irqrestore(&queue->irqlock, flags);
+
+       buf->state = buf->error ? VB2_BUF_STATE_ERROR : UVC_BUF_STATE_DONE;
+       vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
+       vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
+
+       return nextbuf;
+}
diff --git a/drivers/media/usb/uvc/uvc_status.c b/drivers/media/usb/uvc/uvc_status.c
new file mode 100644 (file)
index 0000000..b749277
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ *      uvc_status.c  --  USB Video Class driver - Status endpoint
+ *
+ *      Copyright (C) 2005-2009
+ *          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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
+
+#include "uvcvideo.h"
+
+/* --------------------------------------------------------------------------
+ * Input device
+ */
+#ifdef CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV
+static int uvc_input_init(struct uvc_device *dev)
+{
+       struct input_dev *input;
+       int ret;
+
+       input = input_allocate_device();
+       if (input == NULL)
+               return -ENOMEM;
+
+       usb_make_path(dev->udev, dev->input_phys, sizeof(dev->input_phys));
+       strlcat(dev->input_phys, "/button", sizeof(dev->input_phys));
+
+       input->name = dev->name;
+       input->phys = dev->input_phys;
+       usb_to_input_id(dev->udev, &input->id);
+       input->dev.parent = &dev->intf->dev;
+
+       __set_bit(EV_KEY, input->evbit);
+       __set_bit(KEY_CAMERA, input->keybit);
+
+       if ((ret = input_register_device(input)) < 0)
+               goto error;
+
+       dev->input = input;
+       return 0;
+
+error:
+       input_free_device(input);
+       return ret;
+}
+
+static void uvc_input_cleanup(struct uvc_device *dev)
+{
+       if (dev->input)
+               input_unregister_device(dev->input);
+}
+
+static void uvc_input_report_key(struct uvc_device *dev, unsigned int code,
+       int value)
+{
+       if (dev->input) {
+               input_report_key(dev->input, code, value);
+               input_sync(dev->input);
+       }
+}
+
+#else
+#define uvc_input_init(dev)
+#define uvc_input_cleanup(dev)
+#define uvc_input_report_key(dev, code, value)
+#endif /* CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV */
+
+/* --------------------------------------------------------------------------
+ * Status interrupt endpoint
+ */
+static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len)
+{
+       if (len < 3) {
+               uvc_trace(UVC_TRACE_STATUS, "Invalid streaming status event "
+                               "received.\n");
+               return;
+       }
+
+       if (data[2] == 0) {
+               if (len < 4)
+                       return;
+               uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n",
+                       data[1], data[3] ? "pressed" : "released", len);
+               uvc_input_report_key(dev, KEY_CAMERA, data[3]);
+       } else {
+               uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x "
+                       "len %d.\n", data[1], data[2], data[3], len);
+       }
+}
+
+static void uvc_event_control(struct uvc_device *dev, __u8 *data, int len)
+{
+       char *attrs[3] = { "value", "info", "failure" };
+
+       if (len < 6 || data[2] != 0 || data[4] > 2) {
+               uvc_trace(UVC_TRACE_STATUS, "Invalid control status event "
+                               "received.\n");
+               return;
+       }
+
+       uvc_trace(UVC_TRACE_STATUS, "Control %u/%u %s change len %d.\n",
+               data[1], data[3], attrs[data[4]], len);
+}
+
+static void uvc_status_complete(struct urb *urb)
+{
+       struct uvc_device *dev = urb->context;
+       int len, ret;
+
+       switch (urb->status) {
+       case 0:
+               break;
+
+       case -ENOENT:           /* usb_kill_urb() called. */
+       case -ECONNRESET:       /* usb_unlink_urb() called. */
+       case -ESHUTDOWN:        /* The endpoint is being disabled. */
+       case -EPROTO:           /* Device is disconnected (reported by some
+                                * host controller). */
+               return;
+
+       default:
+               uvc_printk(KERN_WARNING, "Non-zero status (%d) in status "
+                       "completion handler.\n", urb->status);
+               return;
+       }
+
+       len = urb->actual_length;
+       if (len > 0) {
+               switch (dev->status[0] & 0x0f) {
+               case UVC_STATUS_TYPE_CONTROL:
+                       uvc_event_control(dev, dev->status, len);
+                       break;
+
+               case UVC_STATUS_TYPE_STREAMING:
+                       uvc_event_streaming(dev, dev->status, len);
+                       break;
+
+               default:
+                       uvc_trace(UVC_TRACE_STATUS, "Unknown status event "
+                               "type %u.\n", dev->status[0]);
+                       break;
+               }
+       }
+
+       /* Resubmit the URB. */
+       urb->interval = dev->int_ep->desc.bInterval;
+       if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+               uvc_printk(KERN_ERR, "Failed to resubmit status URB (%d).\n",
+                       ret);
+       }
+}
+
+int uvc_status_init(struct uvc_device *dev)
+{
+       struct usb_host_endpoint *ep = dev->int_ep;
+       unsigned int pipe;
+       int interval;
+
+       if (ep == NULL)
+               return 0;
+
+       uvc_input_init(dev);
+
+       dev->status = kzalloc(UVC_MAX_STATUS_SIZE, GFP_KERNEL);
+       if (dev->status == NULL)
+               return -ENOMEM;
+
+       dev->int_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (dev->int_urb == NULL) {
+               kfree(dev->status);
+               return -ENOMEM;
+       }
+
+       pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress);
+
+       /* For high-speed interrupt endpoints, the bInterval value is used as
+        * an exponent of two. Some developers forgot about it.
+        */
+       interval = ep->desc.bInterval;
+       if (interval > 16 && dev->udev->speed == USB_SPEED_HIGH &&
+           (dev->quirks & UVC_QUIRK_STATUS_INTERVAL))
+               interval = fls(interval) - 1;
+
+       usb_fill_int_urb(dev->int_urb, dev->udev, pipe,
+               dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete,
+               dev, interval);
+
+       return 0;
+}
+
+void uvc_status_cleanup(struct uvc_device *dev)
+{
+       usb_kill_urb(dev->int_urb);
+       usb_free_urb(dev->int_urb);
+       kfree(dev->status);
+       uvc_input_cleanup(dev);
+}
+
+int uvc_status_start(struct uvc_device *dev)
+{
+       if (dev->int_urb == NULL)
+               return 0;
+
+       return usb_submit_urb(dev->int_urb, GFP_KERNEL);
+}
+
+void uvc_status_stop(struct uvc_device *dev)
+{
+       usb_kill_urb(dev->int_urb);
+}
+
+int uvc_status_suspend(struct uvc_device *dev)
+{
+       if (atomic_read(&dev->users))
+               usb_kill_urb(dev->int_urb);
+
+       return 0;
+}
+
+int uvc_status_resume(struct uvc_device *dev)
+{
+       if (dev->int_urb == NULL || atomic_read(&dev->users) == 0)
+               return 0;
+
+       return usb_submit_urb(dev->int_urb, GFP_NOIO);
+}
+
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
new file mode 100644 (file)
index 0000000..f00db30
--- /dev/null
@@ -0,0 +1,1317 @@
+/*
+ *      uvc_v4l2.c  --  USB Video Class driver - V4L2 API
+ *
+ *      Copyright (C) 2005-2010
+ *          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.
+ *
+ */
+
+#include <linux/compat.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/wait.h>
+#include <linux/atomic.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ioctl.h>
+
+#include "uvcvideo.h"
+
+/* ------------------------------------------------------------------------
+ * UVC ioctls
+ */
+static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
+       struct uvc_xu_control_mapping *xmap)
+{
+       struct uvc_control_mapping *map;
+       unsigned int size;
+       int ret;
+
+       map = kzalloc(sizeof *map, GFP_KERNEL);
+       if (map == NULL)
+               return -ENOMEM;
+
+       map->id = xmap->id;
+       memcpy(map->name, xmap->name, sizeof map->name);
+       memcpy(map->entity, xmap->entity, sizeof map->entity);
+       map->selector = xmap->selector;
+       map->size = xmap->size;
+       map->offset = xmap->offset;
+       map->v4l2_type = xmap->v4l2_type;
+       map->data_type = xmap->data_type;
+
+       switch (xmap->v4l2_type) {
+       case V4L2_CTRL_TYPE_INTEGER:
+       case V4L2_CTRL_TYPE_BOOLEAN:
+       case V4L2_CTRL_TYPE_BUTTON:
+               break;
+
+       case V4L2_CTRL_TYPE_MENU:
+               /* Prevent excessive memory consumption, as well as integer
+                * overflows.
+                */
+               if (xmap->menu_count == 0 ||
+                   xmap->menu_count > UVC_MAX_CONTROL_MENU_ENTRIES) {
+                       ret = -EINVAL;
+                       goto done;
+               }
+
+               size = xmap->menu_count * sizeof(*map->menu_info);
+               map->menu_info = kmalloc(size, GFP_KERNEL);
+               if (map->menu_info == NULL) {
+                       ret = -ENOMEM;
+                       goto done;
+               }
+
+               if (copy_from_user(map->menu_info, xmap->menu_info, size)) {
+                       ret = -EFAULT;
+                       goto done;
+               }
+
+               map->menu_count = xmap->menu_count;
+               break;
+
+       default:
+               uvc_trace(UVC_TRACE_CONTROL, "Unsupported V4L2 control type "
+                         "%u.\n", xmap->v4l2_type);
+               ret = -ENOTTY;
+               goto done;
+       }
+
+       ret = uvc_ctrl_add_mapping(chain, map);
+
+done:
+       kfree(map->menu_info);
+       kfree(map);
+
+       return ret;
+}
+
+/* ------------------------------------------------------------------------
+ * V4L2 interface
+ */
+
+/*
+ * Find the frame interval closest to the requested frame interval for the
+ * given frame format and size. This should be done by the device as part of
+ * the Video Probe and Commit negotiation, but some hardware don't implement
+ * that feature.
+ */
+static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval)
+{
+       unsigned int i;
+
+       if (frame->bFrameIntervalType) {
+               __u32 best = -1, dist;
+
+               for (i = 0; i < frame->bFrameIntervalType; ++i) {
+                       dist = interval > frame->dwFrameInterval[i]
+                            ? interval - frame->dwFrameInterval[i]
+                            : frame->dwFrameInterval[i] - interval;
+
+                       if (dist > best)
+                               break;
+
+                       best = dist;
+               }
+
+               interval = frame->dwFrameInterval[i-1];
+       } else {
+               const __u32 min = frame->dwFrameInterval[0];
+               const __u32 max = frame->dwFrameInterval[1];
+               const __u32 step = frame->dwFrameInterval[2];
+
+               interval = min + (interval - min + step/2) / step * step;
+               if (interval > max)
+                       interval = max;
+       }
+
+       return interval;
+}
+
+static int uvc_v4l2_try_format(struct uvc_streaming *stream,
+       struct v4l2_format *fmt, struct uvc_streaming_control *probe,
+       struct uvc_format **uvc_format, struct uvc_frame **uvc_frame)
+{
+       struct uvc_format *format = NULL;
+       struct uvc_frame *frame = NULL;
+       __u16 rw, rh;
+       unsigned int d, maxd;
+       unsigned int i;
+       __u32 interval;
+       int ret = 0;
+       __u8 *fcc;
+
+       if (fmt->type != stream->type)
+               return -EINVAL;
+
+       fcc = (__u8 *)&fmt->fmt.pix.pixelformat;
+       uvc_trace(UVC_TRACE_FORMAT, "Trying format 0x%08x (%c%c%c%c): %ux%u.\n",
+                       fmt->fmt.pix.pixelformat,
+                       fcc[0], fcc[1], fcc[2], fcc[3],
+                       fmt->fmt.pix.width, fmt->fmt.pix.height);
+
+       /* Check if the hardware supports the requested format. */
+       for (i = 0; i < stream->nformats; ++i) {
+               format = &stream->format[i];
+               if (format->fcc == fmt->fmt.pix.pixelformat)
+                       break;
+       }
+
+       if (format == NULL || format->fcc != fmt->fmt.pix.pixelformat) {
+               uvc_trace(UVC_TRACE_FORMAT, "Unsupported format 0x%08x.\n",
+                               fmt->fmt.pix.pixelformat);
+               return -EINVAL;
+       }
+
+       /* Find the closest image size. The distance between image sizes is
+        * the size in pixels of the non-overlapping regions between the
+        * requested size and the frame-specified size.
+        */
+       rw = fmt->fmt.pix.width;
+       rh = fmt->fmt.pix.height;
+       maxd = (unsigned int)-1;
+
+       for (i = 0; i < format->nframes; ++i) {
+               __u16 w = format->frame[i].wWidth;
+               __u16 h = format->frame[i].wHeight;
+
+               d = min(w, rw) * min(h, rh);
+               d = w*h + rw*rh - 2*d;
+               if (d < maxd) {
+                       maxd = d;
+                       frame = &format->frame[i];
+               }
+
+               if (maxd == 0)
+                       break;
+       }
+
+       if (frame == NULL) {
+               uvc_trace(UVC_TRACE_FORMAT, "Unsupported size %ux%u.\n",
+                               fmt->fmt.pix.width, fmt->fmt.pix.height);
+               return -EINVAL;
+       }
+
+       /* Use the default frame interval. */
+       interval = frame->dwDefaultFrameInterval;
+       uvc_trace(UVC_TRACE_FORMAT, "Using default frame interval %u.%u us "
+               "(%u.%u fps).\n", interval/10, interval%10, 10000000/interval,
+               (100000000/interval)%10);
+
+       /* Set the format index, frame index and frame interval. */
+       memset(probe, 0, sizeof *probe);
+       probe->bmHint = 1;      /* dwFrameInterval */
+       probe->bFormatIndex = format->index;
+       probe->bFrameIndex = frame->bFrameIndex;
+       probe->dwFrameInterval = uvc_try_frame_interval(frame, interval);
+       /* Some webcams stall the probe control set request when the
+        * dwMaxVideoFrameSize field is set to zero. The UVC specification
+        * clearly states that the field is read-only from the host, so this
+        * is a webcam bug. Set dwMaxVideoFrameSize to the value reported by
+        * the webcam to work around the problem.
+        *
+        * The workaround could probably be enabled for all webcams, so the
+        * quirk can be removed if needed. It's currently useful to detect
+        * webcam bugs and fix them before they hit the market (providing
+        * developers test their webcams with the Linux driver as well as with
+        * the Windows driver).
+        */
+       mutex_lock(&stream->mutex);
+       if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)
+               probe->dwMaxVideoFrameSize =
+                       stream->ctrl.dwMaxVideoFrameSize;
+
+       /* Probe the device. */
+       ret = uvc_probe_video(stream, probe);
+       mutex_unlock(&stream->mutex);
+       if (ret < 0)
+               goto done;
+
+       fmt->fmt.pix.width = frame->wWidth;
+       fmt->fmt.pix.height = frame->wHeight;
+       fmt->fmt.pix.field = V4L2_FIELD_NONE;
+       fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8;
+       fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize;
+       fmt->fmt.pix.colorspace = format->colorspace;
+       fmt->fmt.pix.priv = 0;
+
+       if (uvc_format != NULL)
+               *uvc_format = format;
+       if (uvc_frame != NULL)
+               *uvc_frame = frame;
+
+done:
+       return ret;
+}
+
+static int uvc_v4l2_get_format(struct uvc_streaming *stream,
+       struct v4l2_format *fmt)
+{
+       struct uvc_format *format;
+       struct uvc_frame *frame;
+       int ret = 0;
+
+       if (fmt->type != stream->type)
+               return -EINVAL;
+
+       mutex_lock(&stream->mutex);
+       format = stream->cur_format;
+       frame = stream->cur_frame;
+
+       if (format == NULL || frame == NULL) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       fmt->fmt.pix.pixelformat = format->fcc;
+       fmt->fmt.pix.width = frame->wWidth;
+       fmt->fmt.pix.height = frame->wHeight;
+       fmt->fmt.pix.field = V4L2_FIELD_NONE;
+       fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8;
+       fmt->fmt.pix.sizeimage = stream->ctrl.dwMaxVideoFrameSize;
+       fmt->fmt.pix.colorspace = format->colorspace;
+       fmt->fmt.pix.priv = 0;
+
+done:
+       mutex_unlock(&stream->mutex);
+       return ret;
+}
+
+static int uvc_v4l2_set_format(struct uvc_streaming *stream,
+       struct v4l2_format *fmt)
+{
+       struct uvc_streaming_control probe;
+       struct uvc_format *format;
+       struct uvc_frame *frame;
+       int ret;
+
+       if (fmt->type != stream->type)
+               return -EINVAL;
+
+       ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);
+       if (ret < 0)
+               return ret;
+
+       mutex_lock(&stream->mutex);
+
+       if (uvc_queue_allocated(&stream->queue)) {
+               ret = -EBUSY;
+               goto done;
+       }
+
+       memcpy(&stream->ctrl, &probe, sizeof probe);
+       stream->cur_format = format;
+       stream->cur_frame = frame;
+
+done:
+       mutex_unlock(&stream->mutex);
+       return ret;
+}
+
+static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
+               struct v4l2_streamparm *parm)
+{
+       uint32_t numerator, denominator;
+
+       if (parm->type != stream->type)
+               return -EINVAL;
+
+       mutex_lock(&stream->mutex);
+       numerator = stream->ctrl.dwFrameInterval;
+       mutex_unlock(&stream->mutex);
+
+       denominator = 10000000;
+       uvc_simplify_fraction(&numerator, &denominator, 8, 333);
+
+       memset(parm, 0, sizeof *parm);
+       parm->type = stream->type;
+
+       if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+               parm->parm.capture.capturemode = 0;
+               parm->parm.capture.timeperframe.numerator = numerator;
+               parm->parm.capture.timeperframe.denominator = denominator;
+               parm->parm.capture.extendedmode = 0;
+               parm->parm.capture.readbuffers = 0;
+       } else {
+               parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+               parm->parm.output.outputmode = 0;
+               parm->parm.output.timeperframe.numerator = numerator;
+               parm->parm.output.timeperframe.denominator = denominator;
+       }
+
+       return 0;
+}
+
+static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
+               struct v4l2_streamparm *parm)
+{
+       struct uvc_streaming_control probe;
+       struct v4l2_fract timeperframe;
+       uint32_t interval;
+       int ret;
+
+       if (parm->type != stream->type)
+               return -EINVAL;
+
+       if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               timeperframe = parm->parm.capture.timeperframe;
+       else
+               timeperframe = parm->parm.output.timeperframe;
+
+       interval = uvc_fraction_to_interval(timeperframe.numerator,
+               timeperframe.denominator);
+       uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n",
+               timeperframe.numerator, timeperframe.denominator, interval);
+
+       mutex_lock(&stream->mutex);
+
+       if (uvc_queue_streaming(&stream->queue)) {
+               mutex_unlock(&stream->mutex);
+               return -EBUSY;
+       }
+
+       memcpy(&probe, &stream->ctrl, sizeof probe);
+       probe.dwFrameInterval =
+               uvc_try_frame_interval(stream->cur_frame, interval);
+
+       /* Probe the device with the new settings. */
+       ret = uvc_probe_video(stream, &probe);
+       if (ret < 0) {
+               mutex_unlock(&stream->mutex);
+               return ret;
+       }
+
+       memcpy(&stream->ctrl, &probe, sizeof probe);
+       mutex_unlock(&stream->mutex);
+
+       /* Return the actual frame period. */
+       timeperframe.numerator = probe.dwFrameInterval;
+       timeperframe.denominator = 10000000;
+       uvc_simplify_fraction(&timeperframe.numerator,
+               &timeperframe.denominator, 8, 333);
+
+       if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               parm->parm.capture.timeperframe = timeperframe;
+       else
+               parm->parm.output.timeperframe = timeperframe;
+
+       return 0;
+}
+
+/* ------------------------------------------------------------------------
+ * Privilege management
+ */
+
+/*
+ * Privilege management is the multiple-open implementation basis. The current
+ * implementation is completely transparent for the end-user and doesn't
+ * require explicit use of the VIDIOC_G_PRIORITY and VIDIOC_S_PRIORITY ioctls.
+ * Those ioctls enable finer control on the device (by making possible for a
+ * user to request exclusive access to a device), but are not mature yet.
+ * Switching to the V4L2 priority mechanism might be considered in the future
+ * if this situation changes.
+ *
+ * Each open instance of a UVC device can either be in a privileged or
+ * unprivileged state. Only a single instance can be in a privileged state at
+ * a given time. Trying to perform an operation that requires privileges will
+ * automatically acquire the required privileges if possible, or return -EBUSY
+ * otherwise. Privileges are dismissed when closing the instance or when
+ * freeing the video buffers using VIDIOC_REQBUFS.
+ *
+ * Operations that require privileges are:
+ *
+ * - VIDIOC_S_INPUT
+ * - VIDIOC_S_PARM
+ * - VIDIOC_S_FMT
+ * - VIDIOC_REQBUFS
+ */
+static int uvc_acquire_privileges(struct uvc_fh *handle)
+{
+       /* Always succeed if the handle is already privileged. */
+       if (handle->state == UVC_HANDLE_ACTIVE)
+               return 0;
+
+       /* Check if the device already has a privileged handle. */
+       if (atomic_inc_return(&handle->stream->active) != 1) {
+               atomic_dec(&handle->stream->active);
+               return -EBUSY;
+       }
+
+       handle->state = UVC_HANDLE_ACTIVE;
+       return 0;
+}
+
+static void uvc_dismiss_privileges(struct uvc_fh *handle)
+{
+       if (handle->state == UVC_HANDLE_ACTIVE)
+               atomic_dec(&handle->stream->active);
+
+       handle->state = UVC_HANDLE_PASSIVE;
+}
+
+static int uvc_has_privileges(struct uvc_fh *handle)
+{
+       return handle->state == UVC_HANDLE_ACTIVE;
+}
+
+/* ------------------------------------------------------------------------
+ * V4L2 file operations
+ */
+
+static int uvc_v4l2_open(struct file *file)
+{
+       struct uvc_streaming *stream;
+       struct uvc_fh *handle;
+       int ret = 0;
+
+       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n");
+       stream = video_drvdata(file);
+
+       if (stream->dev->state & UVC_DEV_DISCONNECTED)
+               return -ENODEV;
+
+       ret = usb_autopm_get_interface(stream->dev->intf);
+       if (ret < 0)
+               return ret;
+
+       /* Create the device handle. */
+       handle = kzalloc(sizeof *handle, GFP_KERNEL);
+       if (handle == NULL) {
+               usb_autopm_put_interface(stream->dev->intf);
+               return -ENOMEM;
+       }
+
+       if (atomic_inc_return(&stream->dev->users) == 1) {
+               ret = uvc_status_start(stream->dev);
+               if (ret < 0) {
+                       usb_autopm_put_interface(stream->dev->intf);
+                       atomic_dec(&stream->dev->users);
+                       kfree(handle);
+                       return ret;
+               }
+       }
+
+       v4l2_fh_init(&handle->vfh, stream->vdev);
+       v4l2_fh_add(&handle->vfh);
+       handle->chain = stream->chain;
+       handle->stream = stream;
+       handle->state = UVC_HANDLE_PASSIVE;
+       file->private_data = handle;
+
+       return 0;
+}
+
+static int uvc_v4l2_release(struct file *file)
+{
+       struct uvc_fh *handle = file->private_data;
+       struct uvc_streaming *stream = handle->stream;
+
+       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n");
+
+       /* Only free resources if this is a privileged handle. */
+       if (uvc_has_privileges(handle)) {
+               uvc_video_enable(stream, 0);
+               uvc_free_buffers(&stream->queue);
+       }
+
+       /* Release the file handle. */
+       uvc_dismiss_privileges(handle);
+       v4l2_fh_del(&handle->vfh);
+       v4l2_fh_exit(&handle->vfh);
+       kfree(handle);
+       file->private_data = NULL;
+
+       if (atomic_dec_return(&stream->dev->users) == 0)
+               uvc_status_stop(stream->dev);
+
+       usb_autopm_put_interface(stream->dev->intf);
+       return 0;
+}
+
+static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct uvc_fh *handle = file->private_data;
+       struct uvc_video_chain *chain = handle->chain;
+       struct uvc_streaming *stream = handle->stream;
+       long ret = 0;
+
+       switch (cmd) {
+       /* Query capabilities */
+       case VIDIOC_QUERYCAP:
+       {
+               struct v4l2_capability *cap = arg;
+
+               memset(cap, 0, sizeof *cap);
+               strlcpy(cap->driver, "uvcvideo", sizeof cap->driver);
+               strlcpy(cap->card, vdev->name, sizeof cap->card);
+               usb_make_path(stream->dev->udev,
+                             cap->bus_info, sizeof(cap->bus_info));
+               cap->version = LINUX_VERSION_CODE;
+               if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+                       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
+                                         | V4L2_CAP_STREAMING;
+               else
+                       cap->capabilities = V4L2_CAP_VIDEO_OUTPUT
+                                         | V4L2_CAP_STREAMING;
+               break;
+       }
+
+       /* Get, Set & Query control */
+       case VIDIOC_QUERYCTRL:
+               return uvc_query_v4l2_ctrl(chain, arg);
+
+       case VIDIOC_G_CTRL:
+       {
+               struct v4l2_control *ctrl = arg;
+               struct v4l2_ext_control xctrl;
+
+               memset(&xctrl, 0, sizeof xctrl);
+               xctrl.id = ctrl->id;
+
+               ret = uvc_ctrl_begin(chain);
+               if (ret < 0)
+                       return ret;
+
+               ret = uvc_ctrl_get(chain, &xctrl);
+               uvc_ctrl_rollback(handle);
+               if (ret >= 0)
+                       ctrl->value = xctrl.value;
+               break;
+       }
+
+       case VIDIOC_S_CTRL:
+       {
+               struct v4l2_control *ctrl = arg;
+               struct v4l2_ext_control xctrl;
+
+               memset(&xctrl, 0, sizeof xctrl);
+               xctrl.id = ctrl->id;
+               xctrl.value = ctrl->value;
+
+               ret = uvc_ctrl_begin(chain);
+               if (ret < 0)
+                       return ret;
+
+               ret = uvc_ctrl_set(chain, &xctrl);
+               if (ret < 0) {
+                       uvc_ctrl_rollback(handle);
+                       return ret;
+               }
+               ret = uvc_ctrl_commit(handle, &xctrl, 1);
+               if (ret == 0)
+                       ctrl->value = xctrl.value;
+               break;
+       }
+
+       case VIDIOC_QUERYMENU:
+               return uvc_query_v4l2_menu(chain, arg);
+
+       case VIDIOC_G_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *ctrls = arg;
+               struct v4l2_ext_control *ctrl = ctrls->controls;
+               unsigned int i;
+
+               ret = uvc_ctrl_begin(chain);
+               if (ret < 0)
+                       return ret;
+
+               for (i = 0; i < ctrls->count; ++ctrl, ++i) {
+                       ret = uvc_ctrl_get(chain, ctrl);
+                       if (ret < 0) {
+                               uvc_ctrl_rollback(handle);
+                               ctrls->error_idx = i;
+                               return ret;
+                       }
+               }
+               ctrls->error_idx = 0;
+               ret = uvc_ctrl_rollback(handle);
+               break;
+       }
+
+       case VIDIOC_S_EXT_CTRLS:
+       case VIDIOC_TRY_EXT_CTRLS:
+       {
+               struct v4l2_ext_controls *ctrls = arg;
+               struct v4l2_ext_control *ctrl = ctrls->controls;
+               unsigned int i;
+
+               ret = uvc_ctrl_begin(chain);
+               if (ret < 0)
+                       return ret;
+
+               for (i = 0; i < ctrls->count; ++ctrl, ++i) {
+                       ret = uvc_ctrl_set(chain, ctrl);
+                       if (ret < 0) {
+                               uvc_ctrl_rollback(handle);
+                               ctrls->error_idx = i;
+                               return ret;
+                       }
+               }
+
+               ctrls->error_idx = 0;
+
+               if (cmd == VIDIOC_S_EXT_CTRLS)
+                       ret = uvc_ctrl_commit(handle,
+                                             ctrls->controls, ctrls->count);
+               else
+                       ret = uvc_ctrl_rollback(handle);
+               break;
+       }
+
+       /* Get, Set & Enum input */
+       case VIDIOC_ENUMINPUT:
+       {
+               const struct uvc_entity *selector = chain->selector;
+               struct v4l2_input *input = arg;
+               struct uvc_entity *iterm = NULL;
+               u32 index = input->index;
+               int pin = 0;
+
+               if (selector == NULL ||
+                   (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+                       if (index != 0)
+                               return -EINVAL;
+                       list_for_each_entry(iterm, &chain->entities, chain) {
+                               if (UVC_ENTITY_IS_ITERM(iterm))
+                                       break;
+                       }
+                       pin = iterm->id;
+               } else if (index < selector->bNrInPins) {
+                       pin = selector->baSourceID[index];
+                       list_for_each_entry(iterm, &chain->entities, chain) {
+                               if (!UVC_ENTITY_IS_ITERM(iterm))
+                                       continue;
+                               if (iterm->id == pin)
+                                       break;
+                       }
+               }
+
+               if (iterm == NULL || iterm->id != pin)
+                       return -EINVAL;
+
+               memset(input, 0, sizeof *input);
+               input->index = index;
+               strlcpy(input->name, iterm->name, sizeof input->name);
+               if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA)
+                       input->type = V4L2_INPUT_TYPE_CAMERA;
+               break;
+       }
+
+       case VIDIOC_G_INPUT:
+       {
+               u8 input;
+
+               if (chain->selector == NULL ||
+                   (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+                       *(int *)arg = 0;
+                       break;
+               }
+
+               ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
+                       chain->selector->id, chain->dev->intfnum,
+                       UVC_SU_INPUT_SELECT_CONTROL, &input, 1);
+               if (ret < 0)
+                       return ret;
+
+               *(int *)arg = input - 1;
+               break;
+       }
+
+       case VIDIOC_S_INPUT:
+       {
+               u32 input = *(u32 *)arg + 1;
+
+               if ((ret = uvc_acquire_privileges(handle)) < 0)
+                       return ret;
+
+               if (chain->selector == NULL ||
+                   (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+                       if (input != 1)
+                               return -EINVAL;
+                       break;
+               }
+
+               if (input == 0 || input > chain->selector->bNrInPins)
+                       return -EINVAL;
+
+               return uvc_query_ctrl(chain->dev, UVC_SET_CUR,
+                       chain->selector->id, chain->dev->intfnum,
+                       UVC_SU_INPUT_SELECT_CONTROL, &input, 1);
+       }
+
+       /* Try, Get, Set & Enum format */
+       case VIDIOC_ENUM_FMT:
+       {
+               struct v4l2_fmtdesc *fmt = arg;
+               struct uvc_format *format;
+               enum v4l2_buf_type type = fmt->type;
+               __u32 index = fmt->index;
+
+               if (fmt->type != stream->type ||
+                   fmt->index >= stream->nformats)
+                       return -EINVAL;
+
+               memset(fmt, 0, sizeof(*fmt));
+               fmt->index = index;
+               fmt->type = type;
+
+               format = &stream->format[fmt->index];
+               fmt->flags = 0;
+               if (format->flags & UVC_FMT_FLAG_COMPRESSED)
+                       fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
+               strlcpy(fmt->description, format->name,
+                       sizeof fmt->description);
+               fmt->description[sizeof fmt->description - 1] = 0;
+               fmt->pixelformat = format->fcc;
+               break;
+       }
+
+       case VIDIOC_TRY_FMT:
+       {
+               struct uvc_streaming_control probe;
+
+               return uvc_v4l2_try_format(stream, arg, &probe, NULL, NULL);
+       }
+
+       case VIDIOC_S_FMT:
+               if ((ret = uvc_acquire_privileges(handle)) < 0)
+                       return ret;
+
+               return uvc_v4l2_set_format(stream, arg);
+
+       case VIDIOC_G_FMT:
+               return uvc_v4l2_get_format(stream, arg);
+
+       /* Frame size enumeration */
+       case VIDIOC_ENUM_FRAMESIZES:
+       {
+               struct v4l2_frmsizeenum *fsize = arg;
+               struct uvc_format *format = NULL;
+               struct uvc_frame *frame;
+               int i;
+
+               /* Look for the given pixel format */
+               for (i = 0; i < stream->nformats; i++) {
+                       if (stream->format[i].fcc ==
+                                       fsize->pixel_format) {
+                               format = &stream->format[i];
+                               break;
+                       }
+               }
+               if (format == NULL)
+                       return -EINVAL;
+
+               if (fsize->index >= format->nframes)
+                       return -EINVAL;
+
+               frame = &format->frame[fsize->index];
+               fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+               fsize->discrete.width = frame->wWidth;
+               fsize->discrete.height = frame->wHeight;
+               break;
+       }
+
+       /* Frame interval enumeration */
+       case VIDIOC_ENUM_FRAMEINTERVALS:
+       {
+               struct v4l2_frmivalenum *fival = arg;
+               struct uvc_format *format = NULL;
+               struct uvc_frame *frame = NULL;
+               int i;
+
+               /* Look for the given pixel format and frame size */
+               for (i = 0; i < stream->nformats; i++) {
+                       if (stream->format[i].fcc ==
+                                       fival->pixel_format) {
+                               format = &stream->format[i];
+                               break;
+                       }
+               }
+               if (format == NULL)
+                       return -EINVAL;
+
+               for (i = 0; i < format->nframes; i++) {
+                       if (format->frame[i].wWidth == fival->width &&
+                           format->frame[i].wHeight == fival->height) {
+                               frame = &format->frame[i];
+                               break;
+                       }
+               }
+               if (frame == NULL)
+                       return -EINVAL;
+
+               if (frame->bFrameIntervalType) {
+                       if (fival->index >= frame->bFrameIntervalType)
+                               return -EINVAL;
+
+                       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+                       fival->discrete.numerator =
+                               frame->dwFrameInterval[fival->index];
+                       fival->discrete.denominator = 10000000;
+                       uvc_simplify_fraction(&fival->discrete.numerator,
+                               &fival->discrete.denominator, 8, 333);
+               } else {
+                       fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
+                       fival->stepwise.min.numerator =
+                               frame->dwFrameInterval[0];
+                       fival->stepwise.min.denominator = 10000000;
+                       fival->stepwise.max.numerator =
+                               frame->dwFrameInterval[1];
+                       fival->stepwise.max.denominator = 10000000;
+                       fival->stepwise.step.numerator =
+                               frame->dwFrameInterval[2];
+                       fival->stepwise.step.denominator = 10000000;
+                       uvc_simplify_fraction(&fival->stepwise.min.numerator,
+                               &fival->stepwise.min.denominator, 8, 333);
+                       uvc_simplify_fraction(&fival->stepwise.max.numerator,
+                               &fival->stepwise.max.denominator, 8, 333);
+                       uvc_simplify_fraction(&fival->stepwise.step.numerator,
+                               &fival->stepwise.step.denominator, 8, 333);
+               }
+               break;
+       }
+
+       /* Get & Set streaming parameters */
+       case VIDIOC_G_PARM:
+               return uvc_v4l2_get_streamparm(stream, arg);
+
+       case VIDIOC_S_PARM:
+               if ((ret = uvc_acquire_privileges(handle)) < 0)
+                       return ret;
+
+               return uvc_v4l2_set_streamparm(stream, arg);
+
+       /* Cropping and scaling */
+       case VIDIOC_CROPCAP:
+       {
+               struct v4l2_cropcap *ccap = arg;
+
+               if (ccap->type != stream->type)
+                       return -EINVAL;
+
+               ccap->bounds.left = 0;
+               ccap->bounds.top = 0;
+
+               mutex_lock(&stream->mutex);
+               ccap->bounds.width = stream->cur_frame->wWidth;
+               ccap->bounds.height = stream->cur_frame->wHeight;
+               mutex_unlock(&stream->mutex);
+
+               ccap->defrect = ccap->bounds;
+
+               ccap->pixelaspect.numerator = 1;
+               ccap->pixelaspect.denominator = 1;
+               break;
+       }
+
+       case VIDIOC_G_CROP:
+       case VIDIOC_S_CROP:
+               return -EINVAL;
+
+       /* Buffers & streaming */
+       case VIDIOC_REQBUFS:
+               if ((ret = uvc_acquire_privileges(handle)) < 0)
+                       return ret;
+
+               mutex_lock(&stream->mutex);
+               ret = uvc_alloc_buffers(&stream->queue, arg);
+               mutex_unlock(&stream->mutex);
+               if (ret < 0)
+                       return ret;
+
+               if (ret == 0)
+                       uvc_dismiss_privileges(handle);
+
+               ret = 0;
+               break;
+
+       case VIDIOC_QUERYBUF:
+       {
+               struct v4l2_buffer *buf = arg;
+
+               if (!uvc_has_privileges(handle))
+                       return -EBUSY;
+
+               return uvc_query_buffer(&stream->queue, buf);
+       }
+
+       case VIDIOC_QBUF:
+               if (!uvc_has_privileges(handle))
+                       return -EBUSY;
+
+               return uvc_queue_buffer(&stream->queue, arg);
+
+       case VIDIOC_DQBUF:
+               if (!uvc_has_privileges(handle))
+                       return -EBUSY;
+
+               return uvc_dequeue_buffer(&stream->queue, arg,
+                       file->f_flags & O_NONBLOCK);
+
+       case VIDIOC_STREAMON:
+       {
+               int *type = arg;
+
+               if (*type != stream->type)
+                       return -EINVAL;
+
+               if (!uvc_has_privileges(handle))
+                       return -EBUSY;
+
+               mutex_lock(&stream->mutex);
+               ret = uvc_video_enable(stream, 1);
+               mutex_unlock(&stream->mutex);
+               if (ret < 0)
+                       return ret;
+               break;
+       }
+
+       case VIDIOC_STREAMOFF:
+       {
+               int *type = arg;
+
+               if (*type != stream->type)
+                       return -EINVAL;
+
+               if (!uvc_has_privileges(handle))
+                       return -EBUSY;
+
+               return uvc_video_enable(stream, 0);
+       }
+
+       case VIDIOC_SUBSCRIBE_EVENT:
+       {
+               struct v4l2_event_subscription *sub = arg;
+
+               switch (sub->type) {
+               case V4L2_EVENT_CTRL:
+                       return v4l2_event_subscribe(&handle->vfh, sub, 0,
+                                                   &uvc_ctrl_sub_ev_ops);
+               default:
+                       return -EINVAL;
+               }
+       }
+
+       case VIDIOC_UNSUBSCRIBE_EVENT:
+               return v4l2_event_unsubscribe(&handle->vfh, arg);
+
+       case VIDIOC_DQEVENT:
+               return v4l2_event_dequeue(&handle->vfh, arg,
+                                         file->f_flags & O_NONBLOCK);
+
+       /* Analog video standards make no sense for digital cameras. */
+       case VIDIOC_ENUMSTD:
+       case VIDIOC_QUERYSTD:
+       case VIDIOC_G_STD:
+       case VIDIOC_S_STD:
+
+       case VIDIOC_OVERLAY:
+
+       case VIDIOC_ENUMAUDIO:
+       case VIDIOC_ENUMAUDOUT:
+
+       case VIDIOC_ENUMOUTPUT:
+               uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd);
+               return -EINVAL;
+
+       case UVCIOC_CTRL_MAP:
+               return uvc_ioctl_ctrl_map(chain, arg);
+
+       case UVCIOC_CTRL_QUERY:
+               return uvc_xu_ctrl_query(chain, arg);
+
+       default:
+               uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd);
+               return -ENOTTY;
+       }
+
+       return ret;
+}
+
+static long uvc_v4l2_ioctl(struct file *file,
+                    unsigned int cmd, unsigned long arg)
+{
+       if (uvc_trace_param & UVC_TRACE_IOCTL) {
+               uvc_printk(KERN_DEBUG, "uvc_v4l2_ioctl(");
+               v4l_printk_ioctl(NULL, cmd);
+               printk(")\n");
+       }
+
+       return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl);
+}
+
+#ifdef CONFIG_COMPAT
+struct uvc_xu_control_mapping32 {
+       __u32 id;
+       __u8 name[32];
+       __u8 entity[16];
+       __u8 selector;
+
+       __u8 size;
+       __u8 offset;
+       __u32 v4l2_type;
+       __u32 data_type;
+
+       compat_caddr_t menu_info;
+       __u32 menu_count;
+
+       __u32 reserved[4];
+};
+
+static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp,
+                       const struct uvc_xu_control_mapping32 __user *up)
+{
+       struct uvc_menu_info __user *umenus;
+       struct uvc_menu_info __user *kmenus;
+       compat_caddr_t p;
+
+       if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+           __copy_from_user(kp, up, offsetof(typeof(*up), menu_info)) ||
+           __get_user(kp->menu_count, &up->menu_count))
+               return -EFAULT;
+
+       memset(kp->reserved, 0, sizeof(kp->reserved));
+
+       if (kp->menu_count == 0) {
+               kp->menu_info = NULL;
+               return 0;
+       }
+
+       if (__get_user(p, &up->menu_info))
+               return -EFAULT;
+       umenus = compat_ptr(p);
+       if (!access_ok(VERIFY_READ, umenus, kp->menu_count * sizeof(*umenus)))
+               return -EFAULT;
+
+       kmenus = compat_alloc_user_space(kp->menu_count * sizeof(*kmenus));
+       if (kmenus == NULL)
+               return -EFAULT;
+       kp->menu_info = kmenus;
+
+       if (copy_in_user(kmenus, umenus, kp->menu_count * sizeof(*umenus)))
+               return -EFAULT;
+
+       return 0;
+}
+
+static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp,
+                       struct uvc_xu_control_mapping32 __user *up)
+{
+       struct uvc_menu_info __user *umenus;
+       struct uvc_menu_info __user *kmenus = kp->menu_info;
+       compat_caddr_t p;
+
+       if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+           __copy_to_user(up, kp, offsetof(typeof(*up), menu_info)) ||
+           __put_user(kp->menu_count, &up->menu_count))
+               return -EFAULT;
+
+       if (__clear_user(up->reserved, sizeof(up->reserved)))
+               return -EFAULT;
+
+       if (kp->menu_count == 0)
+               return 0;
+
+       if (get_user(p, &up->menu_info))
+               return -EFAULT;
+       umenus = compat_ptr(p);
+
+       if (copy_in_user(umenus, kmenus, kp->menu_count * sizeof(*umenus)))
+               return -EFAULT;
+
+       return 0;
+}
+
+struct uvc_xu_control_query32 {
+       __u8 unit;
+       __u8 selector;
+       __u8 query;
+       __u16 size;
+       compat_caddr_t data;
+};
+
+static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp,
+                       const struct uvc_xu_control_query32 __user *up)
+{
+       u8 __user *udata;
+       u8 __user *kdata;
+       compat_caddr_t p;
+
+       if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+           __copy_from_user(kp, up, offsetof(typeof(*up), data)))
+               return -EFAULT;
+
+       if (kp->size == 0) {
+               kp->data = NULL;
+               return 0;
+       }
+
+       if (__get_user(p, &up->data))
+               return -EFAULT;
+       udata = compat_ptr(p);
+       if (!access_ok(VERIFY_READ, udata, kp->size))
+               return -EFAULT;
+
+       kdata = compat_alloc_user_space(kp->size);
+       if (kdata == NULL)
+               return -EFAULT;
+       kp->data = kdata;
+
+       if (copy_in_user(kdata, udata, kp->size))
+               return -EFAULT;
+
+       return 0;
+}
+
+static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp,
+                       struct uvc_xu_control_query32 __user *up)
+{
+       u8 __user *udata;
+       u8 __user *kdata = kp->data;
+       compat_caddr_t p;
+
+       if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+           __copy_to_user(up, kp, offsetof(typeof(*up), data)))
+               return -EFAULT;
+
+       if (kp->size == 0)
+               return 0;
+
+       if (get_user(p, &up->data))
+               return -EFAULT;
+       udata = compat_ptr(p);
+       if (!access_ok(VERIFY_READ, udata, kp->size))
+               return -EFAULT;
+
+       if (copy_in_user(udata, kdata, kp->size))
+               return -EFAULT;
+
+       return 0;
+}
+
+#define UVCIOC_CTRL_MAP32      _IOWR('u', 0x20, struct uvc_xu_control_mapping32)
+#define UVCIOC_CTRL_QUERY32    _IOWR('u', 0x21, struct uvc_xu_control_query32)
+
+static long uvc_v4l2_compat_ioctl32(struct file *file,
+                    unsigned int cmd, unsigned long arg)
+{
+       union {
+               struct uvc_xu_control_mapping xmap;
+               struct uvc_xu_control_query xqry;
+       } karg;
+       void __user *up = compat_ptr(arg);
+       mm_segment_t old_fs;
+       long ret;
+
+       switch (cmd) {
+       case UVCIOC_CTRL_MAP32:
+               cmd = UVCIOC_CTRL_MAP;
+               ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up);
+               break;
+
+       case UVCIOC_CTRL_QUERY32:
+               cmd = UVCIOC_CTRL_QUERY;
+               ret = uvc_v4l2_get_xu_query(&karg.xqry, up);
+               break;
+
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+       ret = uvc_v4l2_ioctl(file, cmd, (unsigned long)&karg);
+       set_fs(old_fs);
+
+       if (ret < 0)
+               return ret;
+
+       switch (cmd) {
+       case UVCIOC_CTRL_MAP:
+               ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up);
+               break;
+
+       case UVCIOC_CTRL_QUERY:
+               ret = uvc_v4l2_put_xu_query(&karg.xqry, up);
+               break;
+       }
+
+       return ret;
+}
+#endif
+
+static ssize_t uvc_v4l2_read(struct file *file, char __user *data,
+                   size_t count, loff_t *ppos)
+{
+       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_read: not implemented.\n");
+       return -EINVAL;
+}
+
+static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct uvc_fh *handle = file->private_data;
+       struct uvc_streaming *stream = handle->stream;
+
+       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n");
+
+       return uvc_queue_mmap(&stream->queue, vma);
+}
+
+static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
+{
+       struct uvc_fh *handle = file->private_data;
+       struct uvc_streaming *stream = handle->stream;
+
+       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n");
+
+       return uvc_queue_poll(&stream->queue, file, wait);
+}
+
+#ifndef CONFIG_MMU
+static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
+               unsigned long addr, unsigned long len, unsigned long pgoff,
+               unsigned long flags)
+{
+       struct uvc_fh *handle = file->private_data;
+       struct uvc_streaming *stream = handle->stream;
+
+       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n");
+
+       return uvc_queue_get_unmapped_area(&stream->queue, pgoff);
+}
+#endif
+
+const struct v4l2_file_operations uvc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = uvc_v4l2_open,
+       .release        = uvc_v4l2_release,
+       .unlocked_ioctl = uvc_v4l2_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl32 = uvc_v4l2_compat_ioctl32,
+#endif
+       .read           = uvc_v4l2_read,
+       .mmap           = uvc_v4l2_mmap,
+       .poll           = uvc_v4l2_poll,
+#ifndef CONFIG_MMU
+       .get_unmapped_area = uvc_v4l2_get_unmapped_area,
+#endif
+};
+
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
new file mode 100644 (file)
index 0000000..1c15b42
--- /dev/null
@@ -0,0 +1,1879 @@
+/*
+ *      uvc_video.c  --  USB Video Class driver - Video handling
+ *
+ *      Copyright (C) 2005-2010
+ *          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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+#include <linux/atomic.h>
+#include <asm/unaligned.h>
+
+#include <media/v4l2-common.h>
+
+#include "uvcvideo.h"
+
+/* ------------------------------------------------------------------------
+ * UVC Controls
+ */
+
+static int __uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
+                       __u8 intfnum, __u8 cs, void *data, __u16 size,
+                       int timeout)
+{
+       __u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+       unsigned int pipe;
+
+       pipe = (query & 0x80) ? usb_rcvctrlpipe(dev->udev, 0)
+                             : usb_sndctrlpipe(dev->udev, 0);
+       type |= (query & 0x80) ? USB_DIR_IN : USB_DIR_OUT;
+
+       return usb_control_msg(dev->udev, pipe, query, type, cs << 8,
+                       unit << 8 | intfnum, data, size, timeout);
+}
+
+static const char *uvc_query_name(__u8 query)
+{
+       switch (query) {
+       case UVC_SET_CUR:
+               return "SET_CUR";
+       case UVC_GET_CUR:
+               return "GET_CUR";
+       case UVC_GET_MIN:
+               return "GET_MIN";
+       case UVC_GET_MAX:
+               return "GET_MAX";
+       case UVC_GET_RES:
+               return "GET_RES";
+       case UVC_GET_LEN:
+               return "GET_LEN";
+       case UVC_GET_INFO:
+               return "GET_INFO";
+       case UVC_GET_DEF:
+               return "GET_DEF";
+       default:
+               return "<invalid>";
+       }
+}
+
+int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
+                       __u8 intfnum, __u8 cs, void *data, __u16 size)
+{
+       int ret;
+
+       ret = __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size,
+                               UVC_CTRL_CONTROL_TIMEOUT);
+       if (ret != size) {
+               uvc_printk(KERN_ERR, "Failed to query (%s) UVC control %u on "
+                       "unit %u: %d (exp. %u).\n", uvc_query_name(query), cs,
+                       unit, ret, size);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
+       struct uvc_streaming_control *ctrl)
+{
+       struct uvc_format *format = NULL;
+       struct uvc_frame *frame = NULL;
+       unsigned int i;
+
+       for (i = 0; i < stream->nformats; ++i) {
+               if (stream->format[i].index == ctrl->bFormatIndex) {
+                       format = &stream->format[i];
+                       break;
+               }
+       }
+
+       if (format == NULL)
+               return;
+
+       for (i = 0; i < format->nframes; ++i) {
+               if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) {
+                       frame = &format->frame[i];
+                       break;
+               }
+       }
+
+       if (frame == NULL)
+               return;
+
+       if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) ||
+            (ctrl->dwMaxVideoFrameSize == 0 &&
+             stream->dev->uvc_version < 0x0110))
+               ctrl->dwMaxVideoFrameSize =
+                       frame->dwMaxVideoFrameBufferSize;
+
+       if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) &&
+           stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH &&
+           stream->intf->num_altsetting > 1) {
+               u32 interval;
+               u32 bandwidth;
+
+               interval = (ctrl->dwFrameInterval > 100000)
+                        ? ctrl->dwFrameInterval
+                        : frame->dwFrameInterval[0];
+
+               /* Compute a bandwidth estimation by multiplying the frame
+                * size by the number of video frames per second, divide the
+                * result by the number of USB frames (or micro-frames for
+                * high-speed devices) per second and add the UVC header size
+                * (assumed to be 12 bytes long).
+                */
+               bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp;
+               bandwidth *= 10000000 / interval + 1;
+               bandwidth /= 1000;
+               if (stream->dev->udev->speed == USB_SPEED_HIGH)
+                       bandwidth /= 8;
+               bandwidth += 12;
+
+               /* The bandwidth estimate is too low for many cameras. Don't use
+                * maximum packet sizes lower than 1024 bytes to try and work
+                * around the problem. According to measurements done on two
+                * different camera models, the value is high enough to get most
+                * resolutions working while not preventing two simultaneous
+                * VGA streams at 15 fps.
+                */
+               bandwidth = max_t(u32, bandwidth, 1024);
+
+               ctrl->dwMaxPayloadTransferSize = bandwidth;
+       }
+}
+
+static int uvc_get_video_ctrl(struct uvc_streaming *stream,
+       struct uvc_streaming_control *ctrl, int probe, __u8 query)
+{
+       __u8 *data;
+       __u16 size;
+       int ret;
+
+       size = stream->dev->uvc_version >= 0x0110 ? 34 : 26;
+       if ((stream->dev->quirks & UVC_QUIRK_PROBE_DEF) &&
+                       query == UVC_GET_DEF)
+               return -EIO;
+
+       data = kmalloc(size, GFP_KERNEL);
+       if (data == NULL)
+               return -ENOMEM;
+
+       ret = __uvc_query_ctrl(stream->dev, query, 0, stream->intfnum,
+               probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data,
+               size, uvc_timeout_param);
+
+       if ((query == UVC_GET_MIN || query == UVC_GET_MAX) && ret == 2) {
+               /* Some cameras, mostly based on Bison Electronics chipsets,
+                * answer a GET_MIN or GET_MAX request with the wCompQuality
+                * field only.
+                */
+               uvc_warn_once(stream->dev, UVC_WARN_MINMAX, "UVC non "
+                       "compliance - GET_MIN/MAX(PROBE) incorrectly "
+                       "supported. Enabling workaround.\n");
+               memset(ctrl, 0, sizeof *ctrl);
+               ctrl->wCompQuality = le16_to_cpup((__le16 *)data);
+               ret = 0;
+               goto out;
+       } else if (query == UVC_GET_DEF && probe == 1 && ret != size) {
+               /* Many cameras don't support the GET_DEF request on their
+                * video probe control. Warn once and return, the caller will
+                * fall back to GET_CUR.
+                */
+               uvc_warn_once(stream->dev, UVC_WARN_PROBE_DEF, "UVC non "
+                       "compliance - GET_DEF(PROBE) not supported. "
+                       "Enabling workaround.\n");
+               ret = -EIO;
+               goto out;
+       } else if (ret != size) {
+               uvc_printk(KERN_ERR, "Failed to query (%u) UVC %s control : "
+                       "%d (exp. %u).\n", query, probe ? "probe" : "commit",
+                       ret, size);
+               ret = -EIO;
+               goto out;
+       }
+
+       ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]);
+       ctrl->bFormatIndex = data[2];
+       ctrl->bFrameIndex = data[3];
+       ctrl->dwFrameInterval = le32_to_cpup((__le32 *)&data[4]);
+       ctrl->wKeyFrameRate = le16_to_cpup((__le16 *)&data[8]);
+       ctrl->wPFrameRate = le16_to_cpup((__le16 *)&data[10]);
+       ctrl->wCompQuality = le16_to_cpup((__le16 *)&data[12]);
+       ctrl->wCompWindowSize = le16_to_cpup((__le16 *)&data[14]);
+       ctrl->wDelay = le16_to_cpup((__le16 *)&data[16]);
+       ctrl->dwMaxVideoFrameSize = get_unaligned_le32(&data[18]);
+       ctrl->dwMaxPayloadTransferSize = get_unaligned_le32(&data[22]);
+
+       if (size == 34) {
+               ctrl->dwClockFrequency = get_unaligned_le32(&data[26]);
+               ctrl->bmFramingInfo = data[30];
+               ctrl->bPreferedVersion = data[31];
+               ctrl->bMinVersion = data[32];
+               ctrl->bMaxVersion = data[33];
+       } else {
+               ctrl->dwClockFrequency = stream->dev->clock_frequency;
+               ctrl->bmFramingInfo = 0;
+               ctrl->bPreferedVersion = 0;
+               ctrl->bMinVersion = 0;
+               ctrl->bMaxVersion = 0;
+       }
+
+       /* Some broken devices return null or wrong dwMaxVideoFrameSize and
+        * dwMaxPayloadTransferSize fields. Try to get the value from the
+        * format and frame descriptors.
+        */
+       uvc_fixup_video_ctrl(stream, ctrl);
+       ret = 0;
+
+out:
+       kfree(data);
+       return ret;
+}
+
+static int uvc_set_video_ctrl(struct uvc_streaming *stream,
+       struct uvc_streaming_control *ctrl, int probe)
+{
+       __u8 *data;
+       __u16 size;
+       int ret;
+
+       size = stream->dev->uvc_version >= 0x0110 ? 34 : 26;
+       data = kzalloc(size, GFP_KERNEL);
+       if (data == NULL)
+               return -ENOMEM;
+
+       *(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint);
+       data[2] = ctrl->bFormatIndex;
+       data[3] = ctrl->bFrameIndex;
+       *(__le32 *)&data[4] = cpu_to_le32(ctrl->dwFrameInterval);
+       *(__le16 *)&data[8] = cpu_to_le16(ctrl->wKeyFrameRate);
+       *(__le16 *)&data[10] = cpu_to_le16(ctrl->wPFrameRate);
+       *(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality);
+       *(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize);
+       *(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay);
+       put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]);
+       put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]);
+
+       if (size == 34) {
+               put_unaligned_le32(ctrl->dwClockFrequency, &data[26]);
+               data[30] = ctrl->bmFramingInfo;
+               data[31] = ctrl->bPreferedVersion;
+               data[32] = ctrl->bMinVersion;
+               data[33] = ctrl->bMaxVersion;
+       }
+
+       ret = __uvc_query_ctrl(stream->dev, UVC_SET_CUR, 0, stream->intfnum,
+               probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data,
+               size, uvc_timeout_param);
+       if (ret != size) {
+               uvc_printk(KERN_ERR, "Failed to set UVC %s control : "
+                       "%d (exp. %u).\n", probe ? "probe" : "commit",
+                       ret, size);
+               ret = -EIO;
+       }
+
+       kfree(data);
+       return ret;
+}
+
+int uvc_probe_video(struct uvc_streaming *stream,
+       struct uvc_streaming_control *probe)
+{
+       struct uvc_streaming_control probe_min, probe_max;
+       __u16 bandwidth;
+       unsigned int i;
+       int ret;
+
+       /* Perform probing. The device should adjust the requested values
+        * according to its capabilities. However, some devices, namely the
+        * first generation UVC Logitech webcams, don't implement the Video
+        * Probe control properly, and just return the needed bandwidth. For
+        * that reason, if the needed bandwidth exceeds the maximum available
+        * bandwidth, try to lower the quality.
+        */
+       ret = uvc_set_video_ctrl(stream, probe, 1);
+       if (ret < 0)
+               goto done;
+
+       /* Get the minimum and maximum values for compression settings. */
+       if (!(stream->dev->quirks & UVC_QUIRK_PROBE_MINMAX)) {
+               ret = uvc_get_video_ctrl(stream, &probe_min, 1, UVC_GET_MIN);
+               if (ret < 0)
+                       goto done;
+               ret = uvc_get_video_ctrl(stream, &probe_max, 1, UVC_GET_MAX);
+               if (ret < 0)
+                       goto done;
+
+               probe->wCompQuality = probe_max.wCompQuality;
+       }
+
+       for (i = 0; i < 2; ++i) {
+               ret = uvc_set_video_ctrl(stream, probe, 1);
+               if (ret < 0)
+                       goto done;
+               ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR);
+               if (ret < 0)
+                       goto done;
+
+               if (stream->intf->num_altsetting == 1)
+                       break;
+
+               bandwidth = probe->dwMaxPayloadTransferSize;
+               if (bandwidth <= stream->maxpsize)
+                       break;
+
+               if (stream->dev->quirks & UVC_QUIRK_PROBE_MINMAX) {
+                       ret = -ENOSPC;
+                       goto done;
+               }
+
+               /* TODO: negotiate compression parameters */
+               probe->wKeyFrameRate = probe_min.wKeyFrameRate;
+               probe->wPFrameRate = probe_min.wPFrameRate;
+               probe->wCompQuality = probe_max.wCompQuality;
+               probe->wCompWindowSize = probe_min.wCompWindowSize;
+       }
+
+done:
+       return ret;
+}
+
+static int uvc_commit_video(struct uvc_streaming *stream,
+                           struct uvc_streaming_control *probe)
+{
+       return uvc_set_video_ctrl(stream, probe, 0);
+}
+
+/* -----------------------------------------------------------------------------
+ * Clocks and timestamps
+ */
+
+static void
+uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
+                      const __u8 *data, int len)
+{
+       struct uvc_clock_sample *sample;
+       unsigned int header_size;
+       bool has_pts = false;
+       bool has_scr = false;
+       unsigned long flags;
+       struct timespec ts;
+       u16 host_sof;
+       u16 dev_sof;
+
+       switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
+       case UVC_STREAM_PTS | UVC_STREAM_SCR:
+               header_size = 12;
+               has_pts = true;
+               has_scr = true;
+               break;
+       case UVC_STREAM_PTS:
+               header_size = 6;
+               has_pts = true;
+               break;
+       case UVC_STREAM_SCR:
+               header_size = 8;
+               has_scr = true;
+               break;
+       default:
+               header_size = 2;
+               break;
+       }
+
+       /* Check for invalid headers. */
+       if (len < header_size)
+               return;
+
+       /* Extract the timestamps:
+        *
+        * - store the frame PTS in the buffer structure
+        * - if the SCR field is present, retrieve the host SOF counter and
+        *   kernel timestamps and store them with the SCR STC and SOF fields
+        *   in the ring buffer
+        */
+       if (has_pts && buf != NULL)
+               buf->pts = get_unaligned_le32(&data[2]);
+
+       if (!has_scr)
+               return;
+
+       /* To limit the amount of data, drop SCRs with an SOF identical to the
+        * previous one.
+        */
+       dev_sof = get_unaligned_le16(&data[header_size - 2]);
+       if (dev_sof == stream->clock.last_sof)
+               return;
+
+       stream->clock.last_sof = dev_sof;
+
+       host_sof = usb_get_current_frame_number(stream->dev->udev);
+       ktime_get_ts(&ts);
+
+       /* The UVC specification allows device implementations that can't obtain
+        * the USB frame number to keep their own frame counters as long as they
+        * match the size and frequency of the frame number associated with USB
+        * SOF tokens. The SOF values sent by such devices differ from the USB
+        * SOF tokens by a fixed offset that needs to be estimated and accounted
+        * for to make timestamp recovery as accurate as possible.
+        *
+        * The offset is estimated the first time a device SOF value is received
+        * as the difference between the host and device SOF values. As the two
+        * SOF values can differ slightly due to transmission delays, consider
+        * that the offset is null if the difference is not higher than 10 ms
+        * (negative differences can not happen and are thus considered as an
+        * offset). The video commit control wDelay field should be used to
+        * compute a dynamic threshold instead of using a fixed 10 ms value, but
+        * devices don't report reliable wDelay values.
+        *
+        * See uvc_video_clock_host_sof() for an explanation regarding why only
+        * the 8 LSBs of the delta are kept.
+        */
+       if (stream->clock.sof_offset == (u16)-1) {
+               u16 delta_sof = (host_sof - dev_sof) & 255;
+               if (delta_sof >= 10)
+                       stream->clock.sof_offset = delta_sof;
+               else
+                       stream->clock.sof_offset = 0;
+       }
+
+       dev_sof = (dev_sof + stream->clock.sof_offset) & 2047;
+
+       spin_lock_irqsave(&stream->clock.lock, flags);
+
+       sample = &stream->clock.samples[stream->clock.head];
+       sample->dev_stc = get_unaligned_le32(&data[header_size - 6]);
+       sample->dev_sof = dev_sof;
+       sample->host_sof = host_sof;
+       sample->host_ts = ts;
+
+       /* Update the sliding window head and count. */
+       stream->clock.head = (stream->clock.head + 1) % stream->clock.size;
+
+       if (stream->clock.count < stream->clock.size)
+               stream->clock.count++;
+
+       spin_unlock_irqrestore(&stream->clock.lock, flags);
+}
+
+static void uvc_video_clock_reset(struct uvc_streaming *stream)
+{
+       struct uvc_clock *clock = &stream->clock;
+
+       clock->head = 0;
+       clock->count = 0;
+       clock->last_sof = -1;
+       clock->sof_offset = -1;
+}
+
+static int uvc_video_clock_init(struct uvc_streaming *stream)
+{
+       struct uvc_clock *clock = &stream->clock;
+
+       spin_lock_init(&clock->lock);
+       clock->size = 32;
+
+       clock->samples = kmalloc(clock->size * sizeof(*clock->samples),
+                                GFP_KERNEL);
+       if (clock->samples == NULL)
+               return -ENOMEM;
+
+       uvc_video_clock_reset(stream);
+
+       return 0;
+}
+
+static void uvc_video_clock_cleanup(struct uvc_streaming *stream)
+{
+       kfree(stream->clock.samples);
+       stream->clock.samples = NULL;
+}
+
+/*
+ * uvc_video_clock_host_sof - Return the host SOF value for a clock sample
+ *
+ * Host SOF counters reported by usb_get_current_frame_number() usually don't
+ * cover the whole 11-bits SOF range (0-2047) but are limited to the HCI frame
+ * schedule window. They can be limited to 8, 9 or 10 bits depending on the host
+ * controller and its configuration.
+ *
+ * We thus need to recover the SOF value corresponding to the host frame number.
+ * As the device and host frame numbers are sampled in a short interval, the
+ * difference between their values should be equal to a small delta plus an
+ * integer multiple of 256 caused by the host frame number limited precision.
+ *
+ * To obtain the recovered host SOF value, compute the small delta by masking
+ * the high bits of the host frame counter and device SOF difference and add it
+ * to the device SOF value.
+ */
+static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample)
+{
+       /* The delta value can be negative. */
+       s8 delta_sof;
+
+       delta_sof = (sample->host_sof - sample->dev_sof) & 255;
+
+       return (sample->dev_sof + delta_sof) & 2047;
+}
+
+/*
+ * uvc_video_clock_update - Update the buffer timestamp
+ *
+ * This function converts the buffer PTS timestamp to the host clock domain by
+ * going through the USB SOF clock domain and stores the result in the V4L2
+ * buffer timestamp field.
+ *
+ * The relationship between the device clock and the host clock isn't known.
+ * However, the device and the host share the common USB SOF clock which can be
+ * used to recover that relationship.
+ *
+ * The relationship between the device clock and the USB SOF clock is considered
+ * to be linear over the clock samples sliding window and is given by
+ *
+ * SOF = m * PTS + p
+ *
+ * Several methods to compute the slope (m) and intercept (p) can be used. As
+ * the clock drift should be small compared to the sliding window size, we
+ * assume that the line that goes through the points at both ends of the window
+ * is a good approximation. Naming those points P1 and P2, we get
+ *
+ * SOF = (SOF2 - SOF1) / (STC2 - STC1) * PTS
+ *     + (SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1)
+ *
+ * or
+ *
+ * SOF = ((SOF2 - SOF1) * PTS + SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1)   (1)
+ *
+ * to avoid loosing precision in the division. Similarly, the host timestamp is
+ * computed with
+ *
+ * TS = ((TS2 - TS1) * PTS + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1)       (2)
+ *
+ * SOF values are coded on 11 bits by USB. We extend their precision with 16
+ * decimal bits, leading to a 11.16 coding.
+ *
+ * TODO: To avoid surprises with device clock values, PTS/STC timestamps should
+ * be normalized using the nominal device clock frequency reported through the
+ * UVC descriptors.
+ *
+ * Both the PTS/STC and SOF counters roll over, after a fixed but device
+ * specific amount of time for PTS/STC and after 2048ms for SOF. As long as the
+ * sliding window size is smaller than the rollover period, differences computed
+ * on unsigned integers will produce the correct result. However, the p term in
+ * the linear relations will be miscomputed.
+ *
+ * To fix the issue, we subtract a constant from the PTS and STC values to bring
+ * PTS to half the 32 bit STC range. The sliding window STC values then fit into
+ * the 32 bit range without any rollover.
+ *
+ * Similarly, we add 2048 to the device SOF values to make sure that the SOF
+ * computed by (1) will never be smaller than 0. This offset is then compensated
+ * by adding 2048 to the SOF values used in (2). However, this doesn't prevent
+ * rollovers between (1) and (2): the SOF value computed by (1) can be slightly
+ * lower than 4096, and the host SOF counters can have rolled over to 2048. This
+ * case is handled by subtracting 2048 from the SOF value if it exceeds the host
+ * SOF value at the end of the sliding window.
+ *
+ * Finally we subtract a constant from the host timestamps to bring the first
+ * timestamp of the sliding window to 1s.
+ */
+void uvc_video_clock_update(struct uvc_streaming *stream,
+                           struct v4l2_buffer *v4l2_buf,
+                           struct uvc_buffer *buf)
+{
+       struct uvc_clock *clock = &stream->clock;
+       struct uvc_clock_sample *first;
+       struct uvc_clock_sample *last;
+       unsigned long flags;
+       struct timespec ts;
+       u32 delta_stc;
+       u32 y1, y2;
+       u32 x1, x2;
+       u32 mean;
+       u32 sof;
+       u32 div;
+       u32 rem;
+       u64 y;
+
+       spin_lock_irqsave(&clock->lock, flags);
+
+       if (clock->count < clock->size)
+               goto done;
+
+       first = &clock->samples[clock->head];
+       last = &clock->samples[(clock->head - 1) % clock->size];
+
+       /* First step, PTS to SOF conversion. */
+       delta_stc = buf->pts - (1UL << 31);
+       x1 = first->dev_stc - delta_stc;
+       x2 = last->dev_stc - delta_stc;
+       if (x1 == x2)
+               goto done;
+
+       y1 = (first->dev_sof + 2048) << 16;
+       y2 = (last->dev_sof + 2048) << 16;
+       if (y2 < y1)
+               y2 += 2048 << 16;
+
+       y = (u64)(y2 - y1) * (1ULL << 31) + (u64)y1 * (u64)x2
+         - (u64)y2 * (u64)x1;
+       y = div_u64(y, x2 - x1);
+
+       sof = y;
+
+       uvc_trace(UVC_TRACE_CLOCK, "%s: PTS %u y %llu.%06llu SOF %u.%06llu "
+                 "(x1 %u x2 %u y1 %u y2 %u SOF offset %u)\n",
+                 stream->dev->name, buf->pts,
+                 y >> 16, div_u64((y & 0xffff) * 1000000, 65536),
+                 sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
+                 x1, x2, y1, y2, clock->sof_offset);
+
+       /* Second step, SOF to host clock conversion. */
+       x1 = (uvc_video_clock_host_sof(first) + 2048) << 16;
+       x2 = (uvc_video_clock_host_sof(last) + 2048) << 16;
+       if (x2 < x1)
+               x2 += 2048 << 16;
+       if (x1 == x2)
+               goto done;
+
+       ts = timespec_sub(last->host_ts, first->host_ts);
+       y1 = NSEC_PER_SEC;
+       y2 = (ts.tv_sec + 1) * NSEC_PER_SEC + ts.tv_nsec;
+
+       /* Interpolated and host SOF timestamps can wrap around at slightly
+        * different times. Handle this by adding or removing 2048 to or from
+        * the computed SOF value to keep it close to the SOF samples mean
+        * value.
+        */
+       mean = (x1 + x2) / 2;
+       if (mean - (1024 << 16) > sof)
+               sof += 2048 << 16;
+       else if (sof > mean + (1024 << 16))
+               sof -= 2048 << 16;
+
+       y = (u64)(y2 - y1) * (u64)sof + (u64)y1 * (u64)x2
+         - (u64)y2 * (u64)x1;
+       y = div_u64(y, x2 - x1);
+
+       div = div_u64_rem(y, NSEC_PER_SEC, &rem);
+       ts.tv_sec = first->host_ts.tv_sec - 1 + div;
+       ts.tv_nsec = first->host_ts.tv_nsec + rem;
+       if (ts.tv_nsec >= NSEC_PER_SEC) {
+               ts.tv_sec++;
+               ts.tv_nsec -= NSEC_PER_SEC;
+       }
+
+       uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %lu.%06lu "
+                 "buf ts %lu.%06lu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n",
+                 stream->dev->name,
+                 sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
+                 y, ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC,
+                 v4l2_buf->timestamp.tv_sec, v4l2_buf->timestamp.tv_usec,
+                 x1, first->host_sof, first->dev_sof,
+                 x2, last->host_sof, last->dev_sof, y1, y2);
+
+       /* Update the V4L2 buffer. */
+       v4l2_buf->timestamp.tv_sec = ts.tv_sec;
+       v4l2_buf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+
+done:
+       spin_unlock_irqrestore(&stream->clock.lock, flags);
+}
+
+/* ------------------------------------------------------------------------
+ * Stream statistics
+ */
+
+static void uvc_video_stats_decode(struct uvc_streaming *stream,
+               const __u8 *data, int len)
+{
+       unsigned int header_size;
+       bool has_pts = false;
+       bool has_scr = false;
+       u16 uninitialized_var(scr_sof);
+       u32 uninitialized_var(scr_stc);
+       u32 uninitialized_var(pts);
+
+       if (stream->stats.stream.nb_frames == 0 &&
+           stream->stats.frame.nb_packets == 0)
+               ktime_get_ts(&stream->stats.stream.start_ts);
+
+       switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
+       case UVC_STREAM_PTS | UVC_STREAM_SCR:
+               header_size = 12;
+               has_pts = true;
+               has_scr = true;
+               break;
+       case UVC_STREAM_PTS:
+               header_size = 6;
+               has_pts = true;
+               break;
+       case UVC_STREAM_SCR:
+               header_size = 8;
+               has_scr = true;
+               break;
+       default:
+               header_size = 2;
+               break;
+       }
+
+       /* Check for invalid headers. */
+       if (len < header_size || data[0] < header_size) {
+               stream->stats.frame.nb_invalid++;
+               return;
+       }
+
+       /* Extract the timestamps. */
+       if (has_pts)
+               pts = get_unaligned_le32(&data[2]);
+
+       if (has_scr) {
+               scr_stc = get_unaligned_le32(&data[header_size - 6]);
+               scr_sof = get_unaligned_le16(&data[header_size - 2]);
+       }
+
+       /* Is PTS constant through the whole frame ? */
+       if (has_pts && stream->stats.frame.nb_pts) {
+               if (stream->stats.frame.pts != pts) {
+                       stream->stats.frame.nb_pts_diffs++;
+                       stream->stats.frame.last_pts_diff =
+                               stream->stats.frame.nb_packets;
+               }
+       }
+
+       if (has_pts) {
+               stream->stats.frame.nb_pts++;
+               stream->stats.frame.pts = pts;
+       }
+
+       /* Do all frames have a PTS in their first non-empty packet, or before
+        * their first empty packet ?
+        */
+       if (stream->stats.frame.size == 0) {
+               if (len > header_size)
+                       stream->stats.frame.has_initial_pts = has_pts;
+               if (len == header_size && has_pts)
+                       stream->stats.frame.has_early_pts = true;
+       }
+
+       /* Do the SCR.STC and SCR.SOF fields vary through the frame ? */
+       if (has_scr && stream->stats.frame.nb_scr) {
+               if (stream->stats.frame.scr_stc != scr_stc)
+                       stream->stats.frame.nb_scr_diffs++;
+       }
+
+       if (has_scr) {
+               /* Expand the SOF counter to 32 bits and store its value. */
+               if (stream->stats.stream.nb_frames > 0 ||
+                   stream->stats.frame.nb_scr > 0)
+                       stream->stats.stream.scr_sof_count +=
+                               (scr_sof - stream->stats.stream.scr_sof) % 2048;
+               stream->stats.stream.scr_sof = scr_sof;
+
+               stream->stats.frame.nb_scr++;
+               stream->stats.frame.scr_stc = scr_stc;
+               stream->stats.frame.scr_sof = scr_sof;
+
+               if (scr_sof < stream->stats.stream.min_sof)
+                       stream->stats.stream.min_sof = scr_sof;
+               if (scr_sof > stream->stats.stream.max_sof)
+                       stream->stats.stream.max_sof = scr_sof;
+       }
+
+       /* Record the first non-empty packet number. */
+       if (stream->stats.frame.size == 0 && len > header_size)
+               stream->stats.frame.first_data = stream->stats.frame.nb_packets;
+
+       /* Update the frame size. */
+       stream->stats.frame.size += len - header_size;
+
+       /* Update the packets counters. */
+       stream->stats.frame.nb_packets++;
+       if (len > header_size)
+               stream->stats.frame.nb_empty++;
+
+       if (data[1] & UVC_STREAM_ERR)
+               stream->stats.frame.nb_errors++;
+}
+
+static void uvc_video_stats_update(struct uvc_streaming *stream)
+{
+       struct uvc_stats_frame *frame = &stream->stats.frame;
+
+       uvc_trace(UVC_TRACE_STATS, "frame %u stats: %u/%u/%u packets, "
+                 "%u/%u/%u pts (%searly %sinitial), %u/%u scr, "
+                 "last pts/stc/sof %u/%u/%u\n",
+                 stream->sequence, frame->first_data,
+                 frame->nb_packets - frame->nb_empty, frame->nb_packets,
+                 frame->nb_pts_diffs, frame->last_pts_diff, frame->nb_pts,
+                 frame->has_early_pts ? "" : "!",
+                 frame->has_initial_pts ? "" : "!",
+                 frame->nb_scr_diffs, frame->nb_scr,
+                 frame->pts, frame->scr_stc, frame->scr_sof);
+
+       stream->stats.stream.nb_frames++;
+       stream->stats.stream.nb_packets += stream->stats.frame.nb_packets;
+       stream->stats.stream.nb_empty += stream->stats.frame.nb_empty;
+       stream->stats.stream.nb_errors += stream->stats.frame.nb_errors;
+       stream->stats.stream.nb_invalid += stream->stats.frame.nb_invalid;
+
+       if (frame->has_early_pts)
+               stream->stats.stream.nb_pts_early++;
+       if (frame->has_initial_pts)
+               stream->stats.stream.nb_pts_initial++;
+       if (frame->last_pts_diff <= frame->first_data)
+               stream->stats.stream.nb_pts_constant++;
+       if (frame->nb_scr >= frame->nb_packets - frame->nb_empty)
+               stream->stats.stream.nb_scr_count_ok++;
+       if (frame->nb_scr_diffs + 1 == frame->nb_scr)
+               stream->stats.stream.nb_scr_diffs_ok++;
+
+       memset(&stream->stats.frame, 0, sizeof(stream->stats.frame));
+}
+
+size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf,
+                           size_t size)
+{
+       unsigned int scr_sof_freq;
+       unsigned int duration;
+       struct timespec ts;
+       size_t count = 0;
+
+       ts.tv_sec = stream->stats.stream.stop_ts.tv_sec
+                 - stream->stats.stream.start_ts.tv_sec;
+       ts.tv_nsec = stream->stats.stream.stop_ts.tv_nsec
+                  - stream->stats.stream.start_ts.tv_nsec;
+       if (ts.tv_nsec < 0) {
+               ts.tv_sec--;
+               ts.tv_nsec += 1000000000;
+       }
+
+       /* Compute the SCR.SOF frequency estimate. At the nominal 1kHz SOF
+        * frequency this will not overflow before more than 1h.
+        */
+       duration = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+       if (duration != 0)
+               scr_sof_freq = stream->stats.stream.scr_sof_count * 1000
+                            / duration;
+       else
+               scr_sof_freq = 0;
+
+       count += scnprintf(buf + count, size - count,
+                          "frames:  %u\npackets: %u\nempty:   %u\n"
+                          "errors:  %u\ninvalid: %u\n",
+                          stream->stats.stream.nb_frames,
+                          stream->stats.stream.nb_packets,
+                          stream->stats.stream.nb_empty,
+                          stream->stats.stream.nb_errors,
+                          stream->stats.stream.nb_invalid);
+       count += scnprintf(buf + count, size - count,
+                          "pts: %u early, %u initial, %u ok\n",
+                          stream->stats.stream.nb_pts_early,
+                          stream->stats.stream.nb_pts_initial,
+                          stream->stats.stream.nb_pts_constant);
+       count += scnprintf(buf + count, size - count,
+                          "scr: %u count ok, %u diff ok\n",
+                          stream->stats.stream.nb_scr_count_ok,
+                          stream->stats.stream.nb_scr_diffs_ok);
+       count += scnprintf(buf + count, size - count,
+                          "sof: %u <= sof <= %u, freq %u.%03u kHz\n",
+                          stream->stats.stream.min_sof,
+                          stream->stats.stream.max_sof,
+                          scr_sof_freq / 1000, scr_sof_freq % 1000);
+
+       return count;
+}
+
+static void uvc_video_stats_start(struct uvc_streaming *stream)
+{
+       memset(&stream->stats, 0, sizeof(stream->stats));
+       stream->stats.stream.min_sof = 2048;
+}
+
+static void uvc_video_stats_stop(struct uvc_streaming *stream)
+{
+       ktime_get_ts(&stream->stats.stream.stop_ts);
+}
+
+/* ------------------------------------------------------------------------
+ * Video codecs
+ */
+
+/* Video payload decoding is handled by uvc_video_decode_start(),
+ * uvc_video_decode_data() and uvc_video_decode_end().
+ *
+ * uvc_video_decode_start is called with URB data at the start of a bulk or
+ * isochronous payload. It processes header data and returns the header size
+ * in bytes if successful. If an error occurs, it returns a negative error
+ * code. The following error codes have special meanings.
+ *
+ * - EAGAIN informs the caller that the current video buffer should be marked
+ *   as done, and that the function should be called again with the same data
+ *   and a new video buffer. This is used when end of frame conditions can be
+ *   reliably detected at the beginning of the next frame only.
+ *
+ * If an error other than -EAGAIN is returned, the caller will drop the current
+ * payload. No call to uvc_video_decode_data and uvc_video_decode_end will be
+ * made until the next payload. -ENODATA can be used to drop the current
+ * payload if no other error code is appropriate.
+ *
+ * uvc_video_decode_data is called for every URB with URB data. It copies the
+ * data to the video buffer.
+ *
+ * uvc_video_decode_end is called with header data at the end of a bulk or
+ * isochronous payload. It performs any additional header data processing and
+ * returns 0 or a negative error code if an error occurred. As header data have
+ * already been processed by uvc_video_decode_start, this functions isn't
+ * required to perform sanity checks a second time.
+ *
+ * For isochronous transfers where a payload is always transferred in a single
+ * URB, the three functions will be called in a row.
+ *
+ * To let the decoder process header data and update its internal state even
+ * when no video buffer is available, uvc_video_decode_start must be prepared
+ * to be called with a NULL buf parameter. uvc_video_decode_data and
+ * uvc_video_decode_end will never be called with a NULL buffer.
+ */
+static int uvc_video_decode_start(struct uvc_streaming *stream,
+               struct uvc_buffer *buf, const __u8 *data, int len)
+{
+       __u8 fid;
+
+       /* Sanity checks:
+        * - packet must be at least 2 bytes long
+        * - bHeaderLength value must be at least 2 bytes (see above)
+        * - bHeaderLength value can't be larger than the packet size.
+        */
+       if (len < 2 || data[0] < 2 || data[0] > len) {
+               stream->stats.frame.nb_invalid++;
+               return -EINVAL;
+       }
+
+       fid = data[1] & UVC_STREAM_FID;
+
+       /* Increase the sequence number regardless of any buffer states, so
+        * that discontinuous sequence numbers always indicate lost frames.
+        */
+       if (stream->last_fid != fid) {
+               stream->sequence++;
+               if (stream->sequence)
+                       uvc_video_stats_update(stream);
+       }
+
+       uvc_video_clock_decode(stream, buf, data, len);
+       uvc_video_stats_decode(stream, data, len);
+
+       /* Store the payload FID bit and return immediately when the buffer is
+        * NULL.
+        */
+       if (buf == NULL) {
+               stream->last_fid = fid;
+               return -ENODATA;
+       }
+
+       /* Mark the buffer as bad if the error bit is set. */
+       if (data[1] & UVC_STREAM_ERR) {
+               uvc_trace(UVC_TRACE_FRAME, "Marking buffer as bad (error bit "
+                         "set).\n");
+               buf->error = 1;
+       }
+
+       /* Synchronize to the input stream by waiting for the FID bit to be
+        * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE.
+        * stream->last_fid is initialized to -1, so the first isochronous
+        * frame will always be in sync.
+        *
+        * If the device doesn't toggle the FID bit, invert stream->last_fid
+        * when the EOF bit is set to force synchronisation on the next packet.
+        */
+       if (buf->state != UVC_BUF_STATE_ACTIVE) {
+               struct timespec ts;
+
+               if (fid == stream->last_fid) {
+                       uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of "
+                               "sync).\n");
+                       if ((stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) &&
+                           (data[1] & UVC_STREAM_EOF))
+                               stream->last_fid ^= UVC_STREAM_FID;
+                       return -ENODATA;
+               }
+
+               if (uvc_clock_param == CLOCK_MONOTONIC)
+                       ktime_get_ts(&ts);
+               else
+                       ktime_get_real_ts(&ts);
+
+               buf->buf.v4l2_buf.sequence = stream->sequence;
+               buf->buf.v4l2_buf.timestamp.tv_sec = ts.tv_sec;
+               buf->buf.v4l2_buf.timestamp.tv_usec =
+                       ts.tv_nsec / NSEC_PER_USEC;
+
+               /* TODO: Handle PTS and SCR. */
+               buf->state = UVC_BUF_STATE_ACTIVE;
+       }
+
+       /* Mark the buffer as done if we're at the beginning of a new frame.
+        * End of frame detection is better implemented by checking the EOF
+        * bit (FID bit toggling is delayed by one frame compared to the EOF
+        * bit), but some devices don't set the bit at end of frame (and the
+        * last payload can be lost anyway). We thus must check if the FID has
+        * been toggled.
+        *
+        * stream->last_fid is initialized to -1, so the first isochronous
+        * frame will never trigger an end of frame detection.
+        *
+        * Empty buffers (bytesused == 0) don't trigger end of frame detection
+        * as it doesn't make sense to return an empty buffer. This also
+        * avoids detecting end of frame conditions at FID toggling if the
+        * previous payload had the EOF bit set.
+        */
+       if (fid != stream->last_fid && buf->bytesused != 0) {
+               uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit "
+                               "toggled).\n");
+               buf->state = UVC_BUF_STATE_READY;
+               return -EAGAIN;
+       }
+
+       stream->last_fid = fid;
+
+       return data[0];
+}
+
+static void uvc_video_decode_data(struct uvc_streaming *stream,
+               struct uvc_buffer *buf, const __u8 *data, int len)
+{
+       unsigned int maxlen, nbytes;
+       void *mem;
+
+       if (len <= 0)
+               return;
+
+       /* Copy the video data to the buffer. */
+       maxlen = buf->length - buf->bytesused;
+       mem = buf->mem + buf->bytesused;
+       nbytes = min((unsigned int)len, maxlen);
+       memcpy(mem, data, nbytes);
+       buf->bytesused += nbytes;
+
+       /* Complete the current frame if the buffer size was exceeded. */
+       if (len > maxlen) {
+               uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n");
+               buf->state = UVC_BUF_STATE_READY;
+       }
+}
+
+static void uvc_video_decode_end(struct uvc_streaming *stream,
+               struct uvc_buffer *buf, const __u8 *data, int len)
+{
+       /* Mark the buffer as done if the EOF marker is set. */
+       if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) {
+               uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n");
+               if (data[0] == len)
+                       uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n");
+               buf->state = UVC_BUF_STATE_READY;
+               if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID)
+                       stream->last_fid ^= UVC_STREAM_FID;
+       }
+}
+
+/* Video payload encoding is handled by uvc_video_encode_header() and
+ * uvc_video_encode_data(). Only bulk transfers are currently supported.
+ *
+ * uvc_video_encode_header is called at the start of a payload. It adds header
+ * data to the transfer buffer and returns the header size. As the only known
+ * UVC output device transfers a whole frame in a single payload, the EOF bit
+ * is always set in the header.
+ *
+ * uvc_video_encode_data is called for every URB and copies the data from the
+ * video buffer to the transfer buffer.
+ */
+static int uvc_video_encode_header(struct uvc_streaming *stream,
+               struct uvc_buffer *buf, __u8 *data, int len)
+{
+       data[0] = 2;    /* Header length */
+       data[1] = UVC_STREAM_EOH | UVC_STREAM_EOF
+               | (stream->last_fid & UVC_STREAM_FID);
+       return 2;
+}
+
+static int uvc_video_encode_data(struct uvc_streaming *stream,
+               struct uvc_buffer *buf, __u8 *data, int len)
+{
+       struct uvc_video_queue *queue = &stream->queue;
+       unsigned int nbytes;
+       void *mem;
+
+       /* Copy video data to the URB buffer. */
+       mem = buf->mem + queue->buf_used;
+       nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
+       nbytes = min(stream->bulk.max_payload_size - stream->bulk.payload_size,
+                       nbytes);
+       memcpy(data, mem, nbytes);
+
+       queue->buf_used += nbytes;
+
+       return nbytes;
+}
+
+/* ------------------------------------------------------------------------
+ * URB handling
+ */
+
+/*
+ * Completion handler for video URBs.
+ */
+static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream,
+       struct uvc_buffer *buf)
+{
+       u8 *mem;
+       int ret, i;
+
+       for (i = 0; i < urb->number_of_packets; ++i) {
+               if (urb->iso_frame_desc[i].status < 0) {
+                       uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame "
+                               "lost (%d).\n", urb->iso_frame_desc[i].status);
+                       /* Mark the buffer as faulty. */
+                       if (buf != NULL)
+                               buf->error = 1;
+                       continue;
+               }
+
+               /* Decode the payload header. */
+               mem = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+               do {
+                       ret = uvc_video_decode_start(stream, buf, mem,
+                               urb->iso_frame_desc[i].actual_length);
+                       if (ret == -EAGAIN)
+                               buf = uvc_queue_next_buffer(&stream->queue,
+                                                           buf);
+               } while (ret == -EAGAIN);
+
+               if (ret < 0)
+                       continue;
+
+               /* Decode the payload data. */
+               uvc_video_decode_data(stream, buf, mem + ret,
+                       urb->iso_frame_desc[i].actual_length - ret);
+
+               /* Process the header again. */
+               uvc_video_decode_end(stream, buf, mem,
+                       urb->iso_frame_desc[i].actual_length);
+
+               if (buf->state == UVC_BUF_STATE_READY) {
+                       if (buf->length != buf->bytesused &&
+                           !(stream->cur_format->flags &
+                             UVC_FMT_FLAG_COMPRESSED))
+                               buf->error = 1;
+
+                       buf = uvc_queue_next_buffer(&stream->queue, buf);
+               }
+       }
+}
+
+static void uvc_video_decode_bulk(struct urb *urb, struct uvc_streaming *stream,
+       struct uvc_buffer *buf)
+{
+       u8 *mem;
+       int len, ret;
+
+       /*
+        * Ignore ZLPs if they're not part of a frame, otherwise process them
+        * to trigger the end of payload detection.
+        */
+       if (urb->actual_length == 0 && stream->bulk.header_size == 0)
+               return;
+
+       mem = urb->transfer_buffer;
+       len = urb->actual_length;
+       stream->bulk.payload_size += len;
+
+       /* If the URB is the first of its payload, decode and save the
+        * header.
+        */
+       if (stream->bulk.header_size == 0 && !stream->bulk.skip_payload) {
+               do {
+                       ret = uvc_video_decode_start(stream, buf, mem, len);
+                       if (ret == -EAGAIN)
+                               buf = uvc_queue_next_buffer(&stream->queue,
+                                                           buf);
+               } while (ret == -EAGAIN);
+
+               /* If an error occurred skip the rest of the payload. */
+               if (ret < 0 || buf == NULL) {
+                       stream->bulk.skip_payload = 1;
+               } else {
+                       memcpy(stream->bulk.header, mem, ret);
+                       stream->bulk.header_size = ret;
+
+                       mem += ret;
+                       len -= ret;
+               }
+       }
+
+       /* The buffer queue might have been cancelled while a bulk transfer
+        * was in progress, so we can reach here with buf equal to NULL. Make
+        * sure buf is never dereferenced if NULL.
+        */
+
+       /* Process video data. */
+       if (!stream->bulk.skip_payload && buf != NULL)
+               uvc_video_decode_data(stream, buf, mem, len);
+
+       /* Detect the payload end by a URB smaller than the maximum size (or
+        * a payload size equal to the maximum) and process the header again.
+        */
+       if (urb->actual_length < urb->transfer_buffer_length ||
+           stream->bulk.payload_size >= stream->bulk.max_payload_size) {
+               if (!stream->bulk.skip_payload && buf != NULL) {
+                       uvc_video_decode_end(stream, buf, stream->bulk.header,
+                               stream->bulk.payload_size);
+                       if (buf->state == UVC_BUF_STATE_READY)
+                               buf = uvc_queue_next_buffer(&stream->queue,
+                                                           buf);
+               }
+
+               stream->bulk.header_size = 0;
+               stream->bulk.skip_payload = 0;
+               stream->bulk.payload_size = 0;
+       }
+}
+
+static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream,
+       struct uvc_buffer *buf)
+{
+       u8 *mem = urb->transfer_buffer;
+       int len = stream->urb_size, ret;
+
+       if (buf == NULL) {
+               urb->transfer_buffer_length = 0;
+               return;
+       }
+
+       /* If the URB is the first of its payload, add the header. */
+       if (stream->bulk.header_size == 0) {
+               ret = uvc_video_encode_header(stream, buf, mem, len);
+               stream->bulk.header_size = ret;
+               stream->bulk.payload_size += ret;
+               mem += ret;
+               len -= ret;
+       }
+
+       /* Process video data. */
+       ret = uvc_video_encode_data(stream, buf, mem, len);
+
+       stream->bulk.payload_size += ret;
+       len -= ret;
+
+       if (buf->bytesused == stream->queue.buf_used ||
+           stream->bulk.payload_size == stream->bulk.max_payload_size) {
+               if (buf->bytesused == stream->queue.buf_used) {
+                       stream->queue.buf_used = 0;
+                       buf->state = UVC_BUF_STATE_READY;
+                       buf->buf.v4l2_buf.sequence = ++stream->sequence;
+                       uvc_queue_next_buffer(&stream->queue, buf);
+                       stream->last_fid ^= UVC_STREAM_FID;
+               }
+
+               stream->bulk.header_size = 0;
+               stream->bulk.payload_size = 0;
+       }
+
+       urb->transfer_buffer_length = stream->urb_size - len;
+}
+
+static void uvc_video_complete(struct urb *urb)
+{
+       struct uvc_streaming *stream = urb->context;
+       struct uvc_video_queue *queue = &stream->queue;
+       struct uvc_buffer *buf = NULL;
+       unsigned long flags;
+       int ret;
+
+       switch (urb->status) {
+       case 0:
+               break;
+
+       default:
+               uvc_printk(KERN_WARNING, "Non-zero status (%d) in video "
+                       "completion handler.\n", urb->status);
+
+       case -ENOENT:           /* usb_kill_urb() called. */
+               if (stream->frozen)
+                       return;
+
+       case -ECONNRESET:       /* usb_unlink_urb() called. */
+       case -ESHUTDOWN:        /* The endpoint is being disabled. */
+               uvc_queue_cancel(queue, urb->status == -ESHUTDOWN);
+               return;
+       }
+
+       spin_lock_irqsave(&queue->irqlock, flags);
+       if (!list_empty(&queue->irqqueue))
+               buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
+                                      queue);
+       spin_unlock_irqrestore(&queue->irqlock, flags);
+
+       stream->decode(urb, stream, buf);
+
+       if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+               uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n",
+                       ret);
+       }
+}
+
+/*
+ * Free transfer buffers.
+ */
+static void uvc_free_urb_buffers(struct uvc_streaming *stream)
+{
+       unsigned int i;
+
+       for (i = 0; i < UVC_URBS; ++i) {
+               if (stream->urb_buffer[i]) {
+#ifndef CONFIG_DMA_NONCOHERENT
+                       usb_free_coherent(stream->dev->udev, stream->urb_size,
+                               stream->urb_buffer[i], stream->urb_dma[i]);
+#else
+                       kfree(stream->urb_buffer[i]);
+#endif
+                       stream->urb_buffer[i] = NULL;
+               }
+       }
+
+       stream->urb_size = 0;
+}
+
+/*
+ * Allocate transfer buffers. This function can be called with buffers
+ * already allocated when resuming from suspend, in which case it will
+ * return without touching the buffers.
+ *
+ * Limit the buffer size to UVC_MAX_PACKETS bulk/isochronous packets. If the
+ * system is too low on memory try successively smaller numbers of packets
+ * until allocation succeeds.
+ *
+ * Return the number of allocated packets on success or 0 when out of memory.
+ */
+static int uvc_alloc_urb_buffers(struct uvc_streaming *stream,
+       unsigned int size, unsigned int psize, gfp_t gfp_flags)
+{
+       unsigned int npackets;
+       unsigned int i;
+
+       /* Buffers are already allocated, bail out. */
+       if (stream->urb_size)
+               return stream->urb_size / psize;
+
+       /* Compute the number of packets. Bulk endpoints might transfer UVC
+        * payloads across multiple URBs.
+        */
+       npackets = DIV_ROUND_UP(size, psize);
+       if (npackets > UVC_MAX_PACKETS)
+               npackets = UVC_MAX_PACKETS;
+
+       /* Retry allocations until one succeed. */
+       for (; npackets > 1; npackets /= 2) {
+               for (i = 0; i < UVC_URBS; ++i) {
+                       stream->urb_size = psize * npackets;
+#ifndef CONFIG_DMA_NONCOHERENT
+                       stream->urb_buffer[i] = usb_alloc_coherent(
+                               stream->dev->udev, stream->urb_size,
+                               gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]);
+#else
+                       stream->urb_buffer[i] =
+                           kmalloc(stream->urb_size, gfp_flags | __GFP_NOWARN);
+#endif
+                       if (!stream->urb_buffer[i]) {
+                               uvc_free_urb_buffers(stream);
+                               break;
+                       }
+               }
+
+               if (i == UVC_URBS) {
+                       uvc_trace(UVC_TRACE_VIDEO, "Allocated %u URB buffers "
+                               "of %ux%u bytes each.\n", UVC_URBS, npackets,
+                               psize);
+                       return npackets;
+               }
+       }
+
+       uvc_trace(UVC_TRACE_VIDEO, "Failed to allocate URB buffers (%u bytes "
+               "per packet).\n", psize);
+       return 0;
+}
+
+/*
+ * Uninitialize isochronous/bulk URBs and free transfer buffers.
+ */
+static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
+{
+       struct urb *urb;
+       unsigned int i;
+
+       uvc_video_stats_stop(stream);
+
+       for (i = 0; i < UVC_URBS; ++i) {
+               urb = stream->urb[i];
+               if (urb == NULL)
+                       continue;
+
+               usb_kill_urb(urb);
+               usb_free_urb(urb);
+               stream->urb[i] = NULL;
+       }
+
+       if (free_buffers)
+               uvc_free_urb_buffers(stream);
+}
+
+/*
+ * Compute the maximum number of bytes per interval for an endpoint.
+ */
+static unsigned int uvc_endpoint_max_bpi(struct usb_device *dev,
+                                        struct usb_host_endpoint *ep)
+{
+       u16 psize;
+
+       switch (dev->speed) {
+       case USB_SPEED_SUPER:
+               return ep->ss_ep_comp.wBytesPerInterval;
+       case USB_SPEED_HIGH:
+               psize = usb_endpoint_maxp(&ep->desc);
+               return (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+       default:
+               psize = usb_endpoint_maxp(&ep->desc);
+               return psize & 0x07ff;
+       }
+}
+
+/*
+ * Initialize isochronous URBs and allocate transfer buffers. The packet size
+ * is given by the endpoint.
+ */
+static int uvc_init_video_isoc(struct uvc_streaming *stream,
+       struct usb_host_endpoint *ep, gfp_t gfp_flags)
+{
+       struct urb *urb;
+       unsigned int npackets, i, j;
+       u16 psize;
+       u32 size;
+
+       psize = uvc_endpoint_max_bpi(stream->dev->udev, ep);
+       size = stream->ctrl.dwMaxVideoFrameSize;
+
+       npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags);
+       if (npackets == 0)
+               return -ENOMEM;
+
+       size = npackets * psize;
+
+       for (i = 0; i < UVC_URBS; ++i) {
+               urb = usb_alloc_urb(npackets, gfp_flags);
+               if (urb == NULL) {
+                       uvc_uninit_video(stream, 1);
+                       return -ENOMEM;
+               }
+
+               urb->dev = stream->dev->udev;
+               urb->context = stream;
+               urb->pipe = usb_rcvisocpipe(stream->dev->udev,
+                               ep->desc.bEndpointAddress);
+#ifndef CONFIG_DMA_NONCOHERENT
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+               urb->transfer_dma = stream->urb_dma[i];
+#else
+               urb->transfer_flags = URB_ISO_ASAP;
+#endif
+               urb->interval = ep->desc.bInterval;
+               urb->transfer_buffer = stream->urb_buffer[i];
+               urb->complete = uvc_video_complete;
+               urb->number_of_packets = npackets;
+               urb->transfer_buffer_length = size;
+
+               for (j = 0; j < npackets; ++j) {
+                       urb->iso_frame_desc[j].offset = j * psize;
+                       urb->iso_frame_desc[j].length = psize;
+               }
+
+               stream->urb[i] = urb;
+       }
+
+       return 0;
+}
+
+/*
+ * Initialize bulk URBs and allocate transfer buffers. The packet size is
+ * given by the endpoint.
+ */
+static int uvc_init_video_bulk(struct uvc_streaming *stream,
+       struct usb_host_endpoint *ep, gfp_t gfp_flags)
+{
+       struct urb *urb;
+       unsigned int npackets, pipe, i;
+       u16 psize;
+       u32 size;
+
+       psize = usb_endpoint_maxp(&ep->desc) & 0x7ff;
+       size = stream->ctrl.dwMaxPayloadTransferSize;
+       stream->bulk.max_payload_size = size;
+
+       npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags);
+       if (npackets == 0)
+               return -ENOMEM;
+
+       size = npackets * psize;
+
+       if (usb_endpoint_dir_in(&ep->desc))
+               pipe = usb_rcvbulkpipe(stream->dev->udev,
+                                      ep->desc.bEndpointAddress);
+       else
+               pipe = usb_sndbulkpipe(stream->dev->udev,
+                                      ep->desc.bEndpointAddress);
+
+       if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               size = 0;
+
+       for (i = 0; i < UVC_URBS; ++i) {
+               urb = usb_alloc_urb(0, gfp_flags);
+               if (urb == NULL) {
+                       uvc_uninit_video(stream, 1);
+                       return -ENOMEM;
+               }
+
+               usb_fill_bulk_urb(urb, stream->dev->udev, pipe,
+                       stream->urb_buffer[i], size, uvc_video_complete,
+                       stream);
+#ifndef CONFIG_DMA_NONCOHERENT
+               urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+               urb->transfer_dma = stream->urb_dma[i];
+#endif
+
+               stream->urb[i] = urb;
+       }
+
+       return 0;
+}
+
+/*
+ * Initialize isochronous/bulk URBs and allocate transfer buffers.
+ */
+static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
+{
+       struct usb_interface *intf = stream->intf;
+       struct usb_host_endpoint *ep;
+       unsigned int i;
+       int ret;
+
+       stream->sequence = -1;
+       stream->last_fid = -1;
+       stream->bulk.header_size = 0;
+       stream->bulk.skip_payload = 0;
+       stream->bulk.payload_size = 0;
+
+       uvc_video_stats_start(stream);
+
+       if (intf->num_altsetting > 1) {
+               struct usb_host_endpoint *best_ep = NULL;
+               unsigned int best_psize = UINT_MAX;
+               unsigned int bandwidth;
+               unsigned int uninitialized_var(altsetting);
+               int intfnum = stream->intfnum;
+
+               /* Isochronous endpoint, select the alternate setting. */
+               bandwidth = stream->ctrl.dwMaxPayloadTransferSize;
+
+               if (bandwidth == 0) {
+                       uvc_trace(UVC_TRACE_VIDEO, "Device requested null "
+                               "bandwidth, defaulting to lowest.\n");
+                       bandwidth = 1;
+               } else {
+                       uvc_trace(UVC_TRACE_VIDEO, "Device requested %u "
+                               "B/frame bandwidth.\n", bandwidth);
+               }
+
+               for (i = 0; i < intf->num_altsetting; ++i) {
+                       struct usb_host_interface *alts;
+                       unsigned int psize;
+
+                       alts = &intf->altsetting[i];
+                       ep = uvc_find_endpoint(alts,
+                               stream->header.bEndpointAddress);
+                       if (ep == NULL)
+                               continue;
+
+                       /* Check if the bandwidth is high enough. */
+                       psize = uvc_endpoint_max_bpi(stream->dev->udev, ep);
+                       if (psize >= bandwidth && psize <= best_psize) {
+                               altsetting = alts->desc.bAlternateSetting;
+                               best_psize = psize;
+                               best_ep = ep;
+                       }
+               }
+
+               if (best_ep == NULL) {
+                       uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting "
+                               "for requested bandwidth.\n");
+                       return -EIO;
+               }
+
+               uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u "
+                       "(%u B/frame bandwidth).\n", altsetting, best_psize);
+
+               ret = usb_set_interface(stream->dev->udev, intfnum, altsetting);
+               if (ret < 0)
+                       return ret;
+
+               ret = uvc_init_video_isoc(stream, best_ep, gfp_flags);
+       } else {
+               /* Bulk endpoint, proceed to URB initialization. */
+               ep = uvc_find_endpoint(&intf->altsetting[0],
+                               stream->header.bEndpointAddress);
+               if (ep == NULL)
+                       return -EIO;
+
+               ret = uvc_init_video_bulk(stream, ep, gfp_flags);
+       }
+
+       if (ret < 0)
+               return ret;
+
+       /* Submit the URBs. */
+       for (i = 0; i < UVC_URBS; ++i) {
+               ret = usb_submit_urb(stream->urb[i], gfp_flags);
+               if (ret < 0) {
+                       uvc_printk(KERN_ERR, "Failed to submit URB %u "
+                                       "(%d).\n", i, ret);
+                       uvc_uninit_video(stream, 1);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+/* --------------------------------------------------------------------------
+ * Suspend/resume
+ */
+
+/*
+ * Stop streaming without disabling the video queue.
+ *
+ * To let userspace applications resume without trouble, we must not touch the
+ * video buffers in any way. We mark the device as frozen to make sure the URB
+ * completion handler won't try to cancel the queue when we kill the URBs.
+ */
+int uvc_video_suspend(struct uvc_streaming *stream)
+{
+       if (!uvc_queue_streaming(&stream->queue))
+               return 0;
+
+       stream->frozen = 1;
+       uvc_uninit_video(stream, 0);
+       usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+       return 0;
+}
+
+/*
+ * Reconfigure the video interface and restart streaming if it was enabled
+ * before suspend.
+ *
+ * If an error occurs, disable the video queue. This will wake all pending
+ * buffers, making sure userspace applications are notified of the problem
+ * instead of waiting forever.
+ */
+int uvc_video_resume(struct uvc_streaming *stream, int reset)
+{
+       int ret;
+
+       /* If the bus has been reset on resume, set the alternate setting to 0.
+        * This should be the default value, but some devices crash or otherwise
+        * misbehave if they don't receive a SET_INTERFACE request before any
+        * other video control request.
+        */
+       if (reset)
+               usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+
+       stream->frozen = 0;
+
+       uvc_video_clock_reset(stream);
+
+       ret = uvc_commit_video(stream, &stream->ctrl);
+       if (ret < 0) {
+               uvc_queue_enable(&stream->queue, 0);
+               return ret;
+       }
+
+       if (!uvc_queue_streaming(&stream->queue))
+               return 0;
+
+       ret = uvc_init_video(stream, GFP_NOIO);
+       if (ret < 0)
+               uvc_queue_enable(&stream->queue, 0);
+
+       return ret;
+}
+
+/* ------------------------------------------------------------------------
+ * Video device
+ */
+
+/*
+ * Initialize the UVC video device by switching to alternate setting 0 and
+ * retrieve the default format.
+ *
+ * Some cameras (namely the Fuji Finepix) set the format and frame
+ * indexes to zero. The UVC standard doesn't clearly make this a spec
+ * violation, so try to silently fix the values if possible.
+ *
+ * This function is called before registering the device with V4L.
+ */
+int uvc_video_init(struct uvc_streaming *stream)
+{
+       struct uvc_streaming_control *probe = &stream->ctrl;
+       struct uvc_format *format = NULL;
+       struct uvc_frame *frame = NULL;
+       unsigned int i;
+       int ret;
+
+       if (stream->nformats == 0) {
+               uvc_printk(KERN_INFO, "No supported video formats found.\n");
+               return -EINVAL;
+       }
+
+       atomic_set(&stream->active, 0);
+
+       /* Initialize the video buffers queue. */
+       uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
+
+       /* Alternate setting 0 should be the default, yet the XBox Live Vision
+        * Cam (and possibly other devices) crash or otherwise misbehave if
+        * they don't receive a SET_INTERFACE request before any other video
+        * control request.
+        */
+       usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+
+       /* Set the streaming probe control with default streaming parameters
+        * retrieved from the device. Webcams that don't suport GET_DEF
+        * requests on the probe control will just keep their current streaming
+        * parameters.
+        */
+       if (uvc_get_video_ctrl(stream, probe, 1, UVC_GET_DEF) == 0)
+               uvc_set_video_ctrl(stream, probe, 1);
+
+       /* Initialize the streaming parameters with the probe control current
+        * value. This makes sure SET_CUR requests on the streaming commit
+        * control will always use values retrieved from a successful GET_CUR
+        * request on the probe control, as required by the UVC specification.
+        */
+       ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR);
+       if (ret < 0)
+               return ret;
+
+       /* Check if the default format descriptor exists. Use the first
+        * available format otherwise.
+        */
+       for (i = stream->nformats; i > 0; --i) {
+               format = &stream->format[i-1];
+               if (format->index == probe->bFormatIndex)
+                       break;
+       }
+
+       if (format->nframes == 0) {
+               uvc_printk(KERN_INFO, "No frame descriptor found for the "
+                       "default format.\n");
+               return -EINVAL;
+       }
+
+       /* Zero bFrameIndex might be correct. Stream-based formats (including
+        * MPEG-2 TS and DV) do not support frames but have a dummy frame
+        * descriptor with bFrameIndex set to zero. If the default frame
+        * descriptor is not found, use the first available frame.
+        */
+       for (i = format->nframes; i > 0; --i) {
+               frame = &format->frame[i-1];
+               if (frame->bFrameIndex == probe->bFrameIndex)
+                       break;
+       }
+
+       probe->bFormatIndex = format->index;
+       probe->bFrameIndex = frame->bFrameIndex;
+
+       stream->cur_format = format;
+       stream->cur_frame = frame;
+
+       /* Select the video decoding function */
+       if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               if (stream->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)
+                       stream->decode = uvc_video_decode_isight;
+               else if (stream->intf->num_altsetting > 1)
+                       stream->decode = uvc_video_decode_isoc;
+               else
+                       stream->decode = uvc_video_decode_bulk;
+       } else {
+               if (stream->intf->num_altsetting == 1)
+                       stream->decode = uvc_video_encode_bulk;
+               else {
+                       uvc_printk(KERN_INFO, "Isochronous endpoints are not "
+                               "supported for video output devices.\n");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Enable or disable the video stream.
+ */
+int uvc_video_enable(struct uvc_streaming *stream, int enable)
+{
+       int ret;
+
+       if (!enable) {
+               uvc_uninit_video(stream, 1);
+               usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+               uvc_queue_enable(&stream->queue, 0);
+               uvc_video_clock_cleanup(stream);
+               return 0;
+       }
+
+       ret = uvc_video_clock_init(stream);
+       if (ret < 0)
+               return ret;
+
+       ret = uvc_queue_enable(&stream->queue, 1);
+       if (ret < 0)
+               goto error_queue;
+
+       /* Commit the streaming parameters. */
+       ret = uvc_commit_video(stream, &stream->ctrl);
+       if (ret < 0)
+               goto error_commit;
+
+       ret = uvc_init_video(stream, GFP_KERNEL);
+       if (ret < 0)
+               goto error_video;
+
+       return 0;
+
+error_video:
+       usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+error_commit:
+       uvc_queue_enable(&stream->queue, 0);
+error_queue:
+       uvc_video_clock_cleanup(stream);
+
+       return ret;
+}
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
new file mode 100644 (file)
index 0000000..3764040
--- /dev/null
@@ -0,0 +1,718 @@
+#ifndef _USB_VIDEO_H_
+#define _USB_VIDEO_H_
+
+#ifndef __KERNEL__
+#error "The uvcvideo.h header is deprecated, use linux/uvcvideo.h instead."
+#endif /* __KERNEL__ */
+
+#include <linux/kernel.h>
+#include <linux/poll.h>
+#include <linux/usb.h>
+#include <linux/usb/video.h>
+#include <linux/uvcvideo.h>
+#include <linux/videodev2.h>
+#include <media/media-device.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
+#include <media/videobuf2-core.h>
+
+/* --------------------------------------------------------------------------
+ * UVC constants
+ */
+
+#define UVC_TERM_INPUT                 0x0000
+#define UVC_TERM_OUTPUT                        0x8000
+#define UVC_TERM_DIRECTION(term)       ((term)->type & 0x8000)
+
+#define UVC_ENTITY_TYPE(entity)                ((entity)->type & 0x7fff)
+#define UVC_ENTITY_IS_UNIT(entity)     (((entity)->type & 0xff00) == 0)
+#define UVC_ENTITY_IS_TERM(entity)     (((entity)->type & 0xff00) != 0)
+#define UVC_ENTITY_IS_ITERM(entity) \
+       (UVC_ENTITY_IS_TERM(entity) && \
+       ((entity)->type & 0x8000) == UVC_TERM_INPUT)
+#define UVC_ENTITY_IS_OTERM(entity) \
+       (UVC_ENTITY_IS_TERM(entity) && \
+       ((entity)->type & 0x8000) == UVC_TERM_OUTPUT)
+
+
+/* ------------------------------------------------------------------------
+ * GUIDs
+ */
+#define UVC_GUID_UVC_CAMERA \
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}
+#define UVC_GUID_UVC_OUTPUT \
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}
+#define UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT \
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
+#define UVC_GUID_UVC_PROCESSING \
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}
+#define UVC_GUID_UVC_SELECTOR \
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02}
+
+#define UVC_GUID_FORMAT_MJPEG \
+       { 'M',  'J',  'P',  'G', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_YUY2 \
+       { 'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_YUY2_ISIGHT \
+       { 'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_NV12 \
+       { 'N',  'V',  '1',  '2', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_YV12 \
+       { 'Y',  'V',  '1',  '2', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_I420 \
+       { 'I',  '4',  '2',  '0', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_UYVY \
+       { 'U',  'Y',  'V',  'Y', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y800 \
+       { 'Y',  '8',  '0',  '0', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y8 \
+       { 'Y',  '8',  ' ',  ' ', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y10 \
+       { 'Y',  '1',  '0',  ' ', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y12 \
+       { 'Y',  '1',  '2',  ' ', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y16 \
+       { 'Y',  '1',  '6',  ' ', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_BY8 \
+       { 'B',  'Y',  '8',  ' ', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#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_M420 \
+       { 'M',  '4',  '2',  '0', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+
+#define UVC_GUID_FORMAT_H264 \
+       { 'H',  '2',  '6',  '4', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+
+/* ------------------------------------------------------------------------
+ * Driver specific constants.
+ */
+
+#define DRIVER_VERSION         "1.1.1"
+
+/* Number of isochronous URBs. */
+#define UVC_URBS               5
+/* Maximum number of packets per URB. */
+#define UVC_MAX_PACKETS                32
+/* Maximum number of video buffers. */
+#define UVC_MAX_VIDEO_BUFFERS  32
+/* Maximum status buffer size in bytes of interrupt URB. */
+#define UVC_MAX_STATUS_SIZE    16
+
+#define UVC_CTRL_CONTROL_TIMEOUT       300
+#define UVC_CTRL_STREAMING_TIMEOUT     5000
+
+/* Maximum allowed number of control mappings per device */
+#define UVC_MAX_CONTROL_MAPPINGS       1024
+#define UVC_MAX_CONTROL_MENU_ENTRIES   32
+
+/* Devices quirks */
+#define UVC_QUIRK_STATUS_INTERVAL      0x00000001
+#define UVC_QUIRK_PROBE_MINMAX         0x00000002
+#define UVC_QUIRK_PROBE_EXTRAFIELDS    0x00000004
+#define UVC_QUIRK_BUILTIN_ISIGHT       0x00000008
+#define UVC_QUIRK_STREAM_NO_FID                0x00000010
+#define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020
+#define UVC_QUIRK_FIX_BANDWIDTH                0x00000080
+#define UVC_QUIRK_PROBE_DEF            0x00000100
+#define UVC_QUIRK_RESTRICT_FRAME_RATE  0x00000200
+
+/* Format flags */
+#define UVC_FMT_FLAG_COMPRESSED                0x00000001
+#define UVC_FMT_FLAG_STREAM            0x00000002
+
+/* ------------------------------------------------------------------------
+ * Structures.
+ */
+
+struct uvc_device;
+
+/* TODO: Put the most frequently accessed fields at the beginning of
+ * structures to maximize cache efficiency.
+ */
+struct uvc_control_info {
+       struct list_head mappings;
+
+       __u8 entity[16];
+       __u8 index;     /* Bit index in bmControls */
+       __u8 selector;
+
+       __u16 size;
+       __u32 flags;
+};
+
+struct uvc_control_mapping {
+       struct list_head list;
+       struct list_head ev_subs;
+
+       __u32 id;
+       __u8 name[32];
+       __u8 entity[16];
+       __u8 selector;
+
+       __u8 size;
+       __u8 offset;
+       enum v4l2_ctrl_type v4l2_type;
+       __u32 data_type;
+
+       struct uvc_menu_info *menu_info;
+       __u32 menu_count;
+
+       __u32 master_id;
+       __s32 master_manual;
+       __u32 slave_ids[2];
+
+       __s32 (*get) (struct uvc_control_mapping *mapping, __u8 query,
+                     const __u8 *data);
+       void (*set) (struct uvc_control_mapping *mapping, __s32 value,
+                    __u8 *data);
+};
+
+struct uvc_control {
+       struct uvc_entity *entity;
+       struct uvc_control_info info;
+
+       __u8 index;     /* Used to match the uvc_control entry with a
+                          uvc_control_info. */
+       __u8 dirty:1,
+            loaded:1,
+            modified:1,
+            cached:1,
+            initialized:1;
+
+       __u8 *uvc_data;
+};
+
+struct uvc_format_desc {
+       char *name;
+       __u8 guid[16];
+       __u32 fcc;
+};
+
+/* The term 'entity' refers to both UVC units and UVC terminals.
+ *
+ * The type field is either the terminal type (wTerminalType in the terminal
+ * descriptor), or the unit type (bDescriptorSubtype in the unit descriptor).
+ * As the bDescriptorSubtype field is one byte long, the type value will
+ * always have a null MSB for units. All terminal types defined by the UVC
+ * specification have a non-null MSB, so it is safe to use the MSB to
+ * differentiate between units and terminals as long as the descriptor parsing
+ * code makes sure terminal types have a non-null MSB.
+ *
+ * For terminals, the type's most significant bit stores the terminal
+ * direction (either UVC_TERM_INPUT or UVC_TERM_OUTPUT). The type field should
+ * always be accessed with the UVC_ENTITY_* macros and never directly.
+ */
+
+struct uvc_entity {
+       struct list_head list;          /* Entity as part of a UVC device. */
+       struct list_head chain;         /* Entity as part of a video device
+                                        * chain. */
+       __u8 id;
+       __u16 type;
+       char name[64];
+
+       /* Media controller-related fields. */
+       struct video_device *vdev;
+       struct v4l2_subdev subdev;
+       unsigned int num_pads;
+       unsigned int num_links;
+       struct media_pad *pads;
+
+       union {
+               struct {
+                       __u16 wObjectiveFocalLengthMin;
+                       __u16 wObjectiveFocalLengthMax;
+                       __u16 wOcularFocalLength;
+                       __u8  bControlSize;
+                       __u8  *bmControls;
+               } camera;
+
+               struct {
+                       __u8  bControlSize;
+                       __u8  *bmControls;
+                       __u8  bTransportModeSize;
+                       __u8  *bmTransportModes;
+               } media;
+
+               struct {
+               } output;
+
+               struct {
+                       __u16 wMaxMultiplier;
+                       __u8  bControlSize;
+                       __u8  *bmControls;
+                       __u8  bmVideoStandards;
+               } processing;
+
+               struct {
+               } selector;
+
+               struct {
+                       __u8  guidExtensionCode[16];
+                       __u8  bNumControls;
+                       __u8  bControlSize;
+                       __u8  *bmControls;
+                       __u8  *bmControlsType;
+               } extension;
+       };
+
+       __u8 bNrInPins;
+       __u8 *baSourceID;
+
+       unsigned int ncontrols;
+       struct uvc_control *controls;
+};
+
+struct uvc_frame {
+       __u8  bFrameIndex;
+       __u8  bmCapabilities;
+       __u16 wWidth;
+       __u16 wHeight;
+       __u32 dwMinBitRate;
+       __u32 dwMaxBitRate;
+       __u32 dwMaxVideoFrameBufferSize;
+       __u8  bFrameIntervalType;
+       __u32 dwDefaultFrameInterval;
+       __u32 *dwFrameInterval;
+};
+
+struct uvc_format {
+       __u8 type;
+       __u8 index;
+       __u8 bpp;
+       __u8 colorspace;
+       __u32 fcc;
+       __u32 flags;
+
+       char name[32];
+
+       unsigned int nframes;
+       struct uvc_frame *frame;
+};
+
+struct uvc_streaming_header {
+       __u8 bNumFormats;
+       __u8 bEndpointAddress;
+       __u8 bTerminalLink;
+       __u8 bControlSize;
+       __u8 *bmaControls;
+       /* The following fields are used by input headers only. */
+       __u8 bmInfo;
+       __u8 bStillCaptureMethod;
+       __u8 bTriggerSupport;
+       __u8 bTriggerUsage;
+};
+
+enum uvc_buffer_state {
+       UVC_BUF_STATE_IDLE      = 0,
+       UVC_BUF_STATE_QUEUED    = 1,
+       UVC_BUF_STATE_ACTIVE    = 2,
+       UVC_BUF_STATE_READY     = 3,
+       UVC_BUF_STATE_DONE      = 4,
+       UVC_BUF_STATE_ERROR     = 5,
+};
+
+struct uvc_buffer {
+       struct vb2_buffer buf;
+       struct list_head queue;
+
+       enum uvc_buffer_state state;
+       unsigned int error;
+
+       void *mem;
+       unsigned int length;
+       unsigned int bytesused;
+
+       u32 pts;
+};
+
+#define UVC_QUEUE_DISCONNECTED         (1 << 0)
+#define UVC_QUEUE_DROP_CORRUPTED       (1 << 1)
+
+struct uvc_video_queue {
+       struct vb2_queue queue;
+       struct mutex mutex;                     /* Protects queue */
+
+       unsigned int flags;
+       unsigned int buf_used;
+
+       spinlock_t irqlock;                     /* Protects irqqueue */
+       struct list_head irqqueue;
+};
+
+struct uvc_video_chain {
+       struct uvc_device *dev;
+       struct list_head list;
+
+       struct list_head entities;              /* All entities */
+       struct uvc_entity *processing;          /* Processing unit */
+       struct uvc_entity *selector;            /* Selector unit */
+
+       struct mutex ctrl_mutex;                /* Protects ctrl.info */
+};
+
+struct uvc_stats_frame {
+       unsigned int size;              /* Number of bytes captured */
+       unsigned int first_data;        /* Index of the first non-empty packet */
+
+       unsigned int nb_packets;        /* Number of packets */
+       unsigned int nb_empty;          /* Number of empty packets */
+       unsigned int nb_invalid;        /* Number of packets with an invalid header */
+       unsigned int nb_errors;         /* Number of packets with the error bit set */
+
+       unsigned int nb_pts;            /* Number of packets with a PTS timestamp */
+       unsigned int nb_pts_diffs;      /* Number of PTS differences inside a frame */
+       unsigned int last_pts_diff;     /* Index of the last PTS difference */
+       bool has_initial_pts;           /* Whether the first non-empty packet has a PTS */
+       bool has_early_pts;             /* Whether a PTS is present before the first non-empty packet */
+       u32 pts;                        /* PTS of the last packet */
+
+       unsigned int nb_scr;            /* Number of packets with a SCR timestamp */
+       unsigned int nb_scr_diffs;      /* Number of SCR.STC differences inside a frame */
+       u16 scr_sof;                    /* SCR.SOF of the last packet */
+       u32 scr_stc;                    /* SCR.STC of the last packet */
+};
+
+struct uvc_stats_stream {
+       struct timespec start_ts;       /* Stream start timestamp */
+       struct timespec stop_ts;        /* Stream stop timestamp */
+
+       unsigned int nb_frames;         /* Number of frames */
+
+       unsigned int nb_packets;        /* Number of packets */
+       unsigned int nb_empty;          /* Number of empty packets */
+       unsigned int nb_invalid;        /* Number of packets with an invalid header */
+       unsigned int nb_errors;         /* Number of packets with the error bit set */
+
+       unsigned int nb_pts_constant;   /* Number of frames with constant PTS */
+       unsigned int nb_pts_early;      /* Number of frames with early PTS */
+       unsigned int nb_pts_initial;    /* Number of frames with initial PTS */
+
+       unsigned int nb_scr_count_ok;   /* Number of frames with at least one SCR per non empty packet */
+       unsigned int nb_scr_diffs_ok;   /* Number of frames with varying SCR.STC */
+       unsigned int scr_sof_count;     /* STC.SOF counter accumulated since stream start */
+       unsigned int scr_sof;           /* STC.SOF of the last packet */
+       unsigned int min_sof;           /* Minimum STC.SOF value */
+       unsigned int max_sof;           /* Maximum STC.SOF value */
+};
+
+struct uvc_streaming {
+       struct list_head list;
+       struct uvc_device *dev;
+       struct video_device *vdev;
+       struct uvc_video_chain *chain;
+       atomic_t active;
+
+       struct usb_interface *intf;
+       int intfnum;
+       __u16 maxpsize;
+
+       struct uvc_streaming_header header;
+       enum v4l2_buf_type type;
+
+       unsigned int nformats;
+       struct uvc_format *format;
+
+       struct uvc_streaming_control ctrl;
+       struct uvc_format *cur_format;
+       struct uvc_frame *cur_frame;
+       /* Protect access to ctrl, cur_format, cur_frame and hardware video
+        * probe control.
+        */
+       struct mutex mutex;
+
+       /* Buffers queue. */
+       unsigned int frozen : 1;
+       struct uvc_video_queue queue;
+       void (*decode) (struct urb *urb, struct uvc_streaming *video,
+                       struct uvc_buffer *buf);
+
+       /* Context data used by the bulk completion handler. */
+       struct {
+               __u8 header[256];
+               unsigned int header_size;
+               int skip_payload;
+               __u32 payload_size;
+               __u32 max_payload_size;
+       } bulk;
+
+       struct urb *urb[UVC_URBS];
+       char *urb_buffer[UVC_URBS];
+       dma_addr_t urb_dma[UVC_URBS];
+       unsigned int urb_size;
+
+       __u32 sequence;
+       __u8 last_fid;
+
+       /* debugfs */
+       struct dentry *debugfs_dir;
+       struct {
+               struct uvc_stats_frame frame;
+               struct uvc_stats_stream stream;
+       } stats;
+
+       /* Timestamps support. */
+       struct uvc_clock {
+               struct uvc_clock_sample {
+                       u32 dev_stc;
+                       u16 dev_sof;
+                       struct timespec host_ts;
+                       u16 host_sof;
+               } *samples;
+
+               unsigned int head;
+               unsigned int count;
+               unsigned int size;
+
+               u16 last_sof;
+               u16 sof_offset;
+
+               spinlock_t lock;
+       } clock;
+};
+
+enum uvc_device_state {
+       UVC_DEV_DISCONNECTED = 1,
+};
+
+struct uvc_device {
+       struct usb_device *udev;
+       struct usb_interface *intf;
+       unsigned long warnings;
+       __u32 quirks;
+       int intfnum;
+       char name[32];
+
+       enum uvc_device_state state;
+       atomic_t users;
+       atomic_t nmappings;
+
+       /* Video control interface */
+#ifdef CONFIG_MEDIA_CONTROLLER
+       struct media_device mdev;
+#endif
+       struct v4l2_device vdev;
+       __u16 uvc_version;
+       __u32 clock_frequency;
+
+       struct list_head entities;
+       struct list_head chains;
+
+       /* Video Streaming interfaces */
+       struct list_head streams;
+       atomic_t nstreams;
+
+       /* Status Interrupt Endpoint */
+       struct usb_host_endpoint *int_ep;
+       struct urb *int_urb;
+       __u8 *status;
+       struct input_dev *input;
+       char input_phys[64];
+};
+
+enum uvc_handle_state {
+       UVC_HANDLE_PASSIVE      = 0,
+       UVC_HANDLE_ACTIVE       = 1,
+};
+
+struct uvc_fh {
+       struct v4l2_fh vfh;
+       struct uvc_video_chain *chain;
+       struct uvc_streaming *stream;
+       enum uvc_handle_state state;
+};
+
+struct uvc_driver {
+       struct usb_driver driver;
+};
+
+/* ------------------------------------------------------------------------
+ * Debugging, printing and logging
+ */
+
+#define UVC_TRACE_PROBE                (1 << 0)
+#define UVC_TRACE_DESCR                (1 << 1)
+#define UVC_TRACE_CONTROL      (1 << 2)
+#define UVC_TRACE_FORMAT       (1 << 3)
+#define UVC_TRACE_CAPTURE      (1 << 4)
+#define UVC_TRACE_CALLS                (1 << 5)
+#define UVC_TRACE_IOCTL                (1 << 6)
+#define UVC_TRACE_FRAME                (1 << 7)
+#define UVC_TRACE_SUSPEND      (1 << 8)
+#define UVC_TRACE_STATUS       (1 << 9)
+#define UVC_TRACE_VIDEO                (1 << 10)
+#define UVC_TRACE_STATS                (1 << 11)
+#define UVC_TRACE_CLOCK                (1 << 12)
+
+#define UVC_WARN_MINMAX                0
+#define UVC_WARN_PROBE_DEF     1
+#define UVC_WARN_XU_GET_RES    2
+
+extern unsigned int uvc_clock_param;
+extern unsigned int uvc_no_drop_param;
+extern unsigned int uvc_trace_param;
+extern unsigned int uvc_timeout_param;
+
+#define uvc_trace(flag, msg...) \
+       do { \
+               if (uvc_trace_param & flag) \
+                       printk(KERN_DEBUG "uvcvideo: " msg); \
+       } while (0)
+
+#define uvc_warn_once(dev, warn, msg...) \
+       do { \
+               if (!test_and_set_bit(warn, &dev->warnings)) \
+                       printk(KERN_INFO "uvcvideo: " msg); \
+       } while (0)
+
+#define uvc_printk(level, msg...) \
+       printk(level "uvcvideo: " msg)
+
+/* --------------------------------------------------------------------------
+ * Internal functions.
+ */
+
+/* Core driver */
+extern struct uvc_driver uvc_driver;
+
+extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id);
+
+/* Video buffers queue management. */
+extern void uvc_queue_init(struct uvc_video_queue *queue,
+               enum v4l2_buf_type type, int drop_corrupted);
+extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
+               struct v4l2_requestbuffers *rb);
+extern void uvc_free_buffers(struct uvc_video_queue *queue);
+extern int uvc_query_buffer(struct uvc_video_queue *queue,
+               struct v4l2_buffer *v4l2_buf);
+extern int uvc_queue_buffer(struct uvc_video_queue *queue,
+               struct v4l2_buffer *v4l2_buf);
+extern int uvc_dequeue_buffer(struct uvc_video_queue *queue,
+               struct v4l2_buffer *v4l2_buf, int nonblocking);
+extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
+extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
+extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
+               struct uvc_buffer *buf);
+extern int uvc_queue_mmap(struct uvc_video_queue *queue,
+               struct vm_area_struct *vma);
+extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
+               struct file *file, poll_table *wait);
+#ifndef CONFIG_MMU
+extern unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
+               unsigned long pgoff);
+#endif
+extern int uvc_queue_allocated(struct uvc_video_queue *queue);
+static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
+{
+       return vb2_is_streaming(&queue->queue);
+}
+
+/* V4L2 interface */
+extern const struct v4l2_file_operations uvc_fops;
+
+/* Media controller */
+extern int uvc_mc_register_entities(struct uvc_video_chain *chain);
+extern void uvc_mc_cleanup_entity(struct uvc_entity *entity);
+
+/* Video */
+extern int uvc_video_init(struct uvc_streaming *stream);
+extern int uvc_video_suspend(struct uvc_streaming *stream);
+extern int uvc_video_resume(struct uvc_streaming *stream, int reset);
+extern int uvc_video_enable(struct uvc_streaming *stream, int enable);
+extern int uvc_probe_video(struct uvc_streaming *stream,
+               struct uvc_streaming_control *probe);
+extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
+               __u8 intfnum, __u8 cs, void *data, __u16 size);
+void uvc_video_clock_update(struct uvc_streaming *stream,
+                           struct v4l2_buffer *v4l2_buf,
+                           struct uvc_buffer *buf);
+
+/* Status */
+extern int uvc_status_init(struct uvc_device *dev);
+extern void uvc_status_cleanup(struct uvc_device *dev);
+extern int uvc_status_start(struct uvc_device *dev);
+extern void uvc_status_stop(struct uvc_device *dev);
+extern int uvc_status_suspend(struct uvc_device *dev);
+extern int uvc_status_resume(struct uvc_device *dev);
+
+/* Controls */
+extern const struct v4l2_subscribed_event_ops uvc_ctrl_sub_ev_ops;
+
+extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
+               struct v4l2_queryctrl *v4l2_ctrl);
+extern int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
+               struct v4l2_querymenu *query_menu);
+
+extern int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
+               const struct uvc_control_mapping *mapping);
+extern int uvc_ctrl_init_device(struct uvc_device *dev);
+extern void uvc_ctrl_cleanup_device(struct uvc_device *dev);
+extern int uvc_ctrl_resume_device(struct uvc_device *dev);
+
+extern int uvc_ctrl_begin(struct uvc_video_chain *chain);
+extern int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback,
+                       const struct v4l2_ext_control *xctrls,
+                       unsigned int xctrls_count);
+static inline int uvc_ctrl_commit(struct uvc_fh *handle,
+                       const struct v4l2_ext_control *xctrls,
+                       unsigned int xctrls_count)
+{
+       return __uvc_ctrl_commit(handle, 0, xctrls, xctrls_count);
+}
+static inline int uvc_ctrl_rollback(struct uvc_fh *handle)
+{
+       return __uvc_ctrl_commit(handle, 1, NULL, 0);
+}
+
+extern int uvc_ctrl_get(struct uvc_video_chain *chain,
+               struct v4l2_ext_control *xctrl);
+extern int uvc_ctrl_set(struct uvc_video_chain *chain,
+               struct v4l2_ext_control *xctrl);
+
+extern int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
+               struct uvc_xu_control_query *xqry);
+
+/* Utility functions */
+extern void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator,
+               unsigned int n_terms, unsigned int threshold);
+extern uint32_t uvc_fraction_to_interval(uint32_t numerator,
+               uint32_t denominator);
+extern struct usb_host_endpoint *uvc_find_endpoint(
+               struct usb_host_interface *alts, __u8 epaddr);
+
+/* Quirks support */
+void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream,
+               struct uvc_buffer *buf);
+
+/* debugfs and statistics */
+int uvc_debugfs_init(void);
+void uvc_debugfs_cleanup(void);
+int uvc_debugfs_init_stream(struct uvc_streaming *stream);
+void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream);
+
+size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf,
+                           size_t size);
+
+#endif
index 068e8daa6b7b0354c8f32c210cda549b697fa872..097b17ced172ee360de02cc28845163900c2ccc6 100644 (file)
@@ -616,16 +616,6 @@ menuconfig V4L_USB_DRIVERS
 
 if V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT
 
-       comment "Webcam devices"
-
-source "drivers/media/video/uvc/Kconfig"
-
-source "drivers/media/video/gspca/Kconfig"
-
-source "drivers/media/video/pwc/Kconfig"
-
-source "drivers/media/video/cpia2/Kconfig"
-
 config USB_ZR364XX
        tristate "USB ZR364XX Camera support"
        depends on VIDEO_V4L2
@@ -662,40 +652,9 @@ config USB_S2255
          Say Y here if you want support for the Sensoray 2255 USB device.
          This driver can be compiled as a module, called s2255drv.
 
-source "drivers/media/video/sn9c102/Kconfig"
 
 endif # V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT
 
-if V4L_USB_DRIVERS
-
-       comment "Webcam and/or TV USB devices"
-
-source "drivers/media/video/em28xx/Kconfig"
-
-endif
-
-if V4L_USB_DRIVERS && MEDIA_ANALOG_TV_SUPPORT
-
-       comment "TV USB devices"
-
-source "drivers/media/video/au0828/Kconfig"
-
-source "drivers/media/video/pvrusb2/Kconfig"
-
-source "drivers/media/video/hdpvr/Kconfig"
-
-source "drivers/media/video/tlg2300/Kconfig"
-
-source "drivers/media/video/cx231xx/Kconfig"
-
-source "drivers/media/video/tm6000/Kconfig"
-
-source "drivers/media/video/usbvision/Kconfig"
-
-source "drivers/media/video/stk1160/Kconfig"
-
-endif # V4L_USB_DRIVERS
-
 #
 # PCI drivers configuration - No devices here are for webcams
 #
index 9dff3e2ec61311f11d6310f78731b257a6459d0f..a22a2580ce3043b27ef360b1e7aff391cfff03f0 100644 (file)
@@ -99,20 +99,12 @@ obj-$(CONFIG_VIDEO_VINO) += vino.o
 obj-$(CONFIG_VIDEO_MEYE) += meye.o
 obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
 obj-$(CONFIG_VIDEO_CX88) += cx88/
-obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
-obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/
-obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
 obj-$(CONFIG_VIDEO_CX25821) += cx25821/
-obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
-obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
-obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
-obj-$(CONFIG_VIDEO_TM6000) += tm6000/
 obj-$(CONFIG_VIDEO_MXB) += mxb.o
 obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
 obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
 obj-$(CONFIG_STA2X11_VIP) += sta2x11_vip.o
 obj-$(CONFIG_VIDEO_TIMBERDALE) += timblogiw.o
-obj-$(CONFIG_VIDEO_STK1160) += stk1160/
 
 obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
 
@@ -130,11 +122,6 @@ obj-$(CONFIG_VIDEO_OMAP3)  += omap3isp/
 obj-$(CONFIG_USB_ZR364XX)       += zr364xx.o
 obj-$(CONFIG_USB_STKWEBCAM)     += stkwebcam.o
 
-obj-$(CONFIG_USB_SN9C102)       += sn9c102/
-obj-$(CONFIG_USB_PWC)           += pwc/
-obj-$(CONFIG_USB_GSPCA)         += gspca/
-
-obj-$(CONFIG_VIDEO_HDPVR)      += hdpvr/
 
 obj-$(CONFIG_USB_S2255)                += s2255drv.o
 
@@ -179,9 +166,6 @@ obj-$(CONFIG_ARCH_DAVINCI)          += davinci/
 
 obj-$(CONFIG_VIDEO_SH_VOU)             += sh_vou.o
 
-obj-$(CONFIG_VIDEO_AU0828) += au0828/
-
-obj-$(CONFIG_USB_VIDEO_CLASS)  += uvc/
 obj-$(CONFIG_VIDEO_SAA7164)     += saa7164/
 
 obj-$(CONFIG_VIDEO_IR_I2C)  += ir-kbd-i2c.o
diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig
deleted file mode 100644 (file)
index 23f7fd2..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-
-config VIDEO_AU0828
-       tristate "Auvitek AU0828 support"
-       depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2
-       depends on DVB_CAPTURE_DRIVERS
-       select I2C_ALGOBIT
-       select VIDEO_TVEEPROM
-       select VIDEOBUF_VMALLOC
-       select DVB_AU8522_DTV if !DVB_FE_CUSTOMISE
-       select DVB_AU8522_V4L if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
-       ---help---
-         This is a video4linux driver for Auvitek's USB device.
-
-         To compile this driver as a module, choose M here: the
-         module will be called au0828
diff --git a/drivers/media/video/au0828/Makefile b/drivers/media/video/au0828/Makefile
deleted file mode 100644 (file)
index 98cc20c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-au0828-objs    := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-video.o au0828-vbi.o
-
-obj-$(CONFIG_VIDEO_AU0828) += au0828.o
-
-ccflags-y += -Idrivers/media/tuners
-ccflags-y += -Idrivers/media/dvb-core
-ccflags-y += -Idrivers/media/dvb-frontends
-
-ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c
deleted file mode 100644 (file)
index 448361c..0000000
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- *  Driver for the Auvitek USB bridge
- *
- *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
- *
- *  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 "au0828.h"
-#include "au0828-cards.h"
-#include "au8522.h"
-#include "media/tuner.h"
-#include "media/v4l2-common.h"
-
-void hvr950q_cs5340_audio(void *priv, int enable)
-{
-       /* Because the HVR-950q shares an i2s bus between the cs5340 and the
-          au8522, we need to hold cs5340 in reset when using the au8522 */
-       struct au0828_dev *dev = priv;
-       if (enable == 1)
-               au0828_set(dev, REG_000, 0x10);
-       else
-               au0828_clear(dev, REG_000, 0x10);
-}
-
-struct au0828_board au0828_boards[] = {
-       [AU0828_BOARD_UNKNOWN] = {
-               .name   = "Unknown board",
-               .tuner_type = UNSET,
-               .tuner_addr = ADDR_UNSET,
-       },
-       [AU0828_BOARD_HAUPPAUGE_HVR850] = {
-               .name   = "Hauppauge HVR850",
-               .tuner_type = TUNER_XC5000,
-               .tuner_addr = 0x61,
-               .i2c_clk_divider = AU0828_I2C_CLK_20KHZ,
-               .input = {
-                       {
-                               .type = AU0828_VMUX_TELEVISION,
-                               .vmux = AU8522_COMPOSITE_CH4_SIF,
-                               .amux = AU8522_AUDIO_SIF,
-                       },
-                       {
-                               .type = AU0828_VMUX_COMPOSITE,
-                               .vmux = AU8522_COMPOSITE_CH1,
-                               .amux = AU8522_AUDIO_NONE,
-                               .audio_setup = hvr950q_cs5340_audio,
-                       },
-                       {
-                               .type = AU0828_VMUX_SVIDEO,
-                               .vmux = AU8522_SVIDEO_CH13,
-                               .amux = AU8522_AUDIO_NONE,
-                               .audio_setup = hvr950q_cs5340_audio,
-                       },
-               },
-       },
-       [AU0828_BOARD_HAUPPAUGE_HVR950Q] = {
-               .name   = "Hauppauge HVR950Q",
-               .tuner_type = TUNER_XC5000,
-               .tuner_addr = 0x61,
-               /* The au0828 hardware i2c implementation does not properly
-                  support the xc5000's i2c clock stretching.  So we need to
-                  lower the clock frequency enough where the 15us clock
-                  stretch fits inside of a normal clock cycle, or else the
-                  au0828 fails to set the STOP bit.  A 30 KHz clock puts the
-                  clock pulse width at 18us */
-               .i2c_clk_divider = AU0828_I2C_CLK_20KHZ,
-               .input = {
-                       {
-                               .type = AU0828_VMUX_TELEVISION,
-                               .vmux = AU8522_COMPOSITE_CH4_SIF,
-                               .amux = AU8522_AUDIO_SIF,
-                       },
-                       {
-                               .type = AU0828_VMUX_COMPOSITE,
-                               .vmux = AU8522_COMPOSITE_CH1,
-                               .amux = AU8522_AUDIO_NONE,
-                               .audio_setup = hvr950q_cs5340_audio,
-                       },
-                       {
-                               .type = AU0828_VMUX_SVIDEO,
-                               .vmux = AU8522_SVIDEO_CH13,
-                               .amux = AU8522_AUDIO_NONE,
-                               .audio_setup = hvr950q_cs5340_audio,
-                       },
-               },
-       },
-       [AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL] = {
-               .name   = "Hauppauge HVR950Q rev xxF8",
-               .tuner_type = UNSET,
-               .tuner_addr = ADDR_UNSET,
-               .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
-       },
-       [AU0828_BOARD_DVICO_FUSIONHDTV7] = {
-               .name   = "DViCO FusionHDTV USB",
-               .tuner_type = UNSET,
-               .tuner_addr = ADDR_UNSET,
-               .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
-       },
-       [AU0828_BOARD_HAUPPAUGE_WOODBURY] = {
-               .name = "Hauppauge Woodbury",
-               .tuner_type = UNSET,
-               .tuner_addr = ADDR_UNSET,
-               .i2c_clk_divider = AU0828_I2C_CLK_250KHZ,
-       },
-};
-
-/* Tuner callback function for au0828 boards. Currently only needed
- * for HVR1500Q, which has an xc5000 tuner.
- */
-int au0828_tuner_callback(void *priv, int component, int command, int arg)
-{
-       struct au0828_dev *dev = priv;
-
-       dprintk(1, "%s()\n", __func__);
-
-       switch (dev->boardnr) {
-       case AU0828_BOARD_HAUPPAUGE_HVR850:
-       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
-       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
-       case AU0828_BOARD_DVICO_FUSIONHDTV7:
-               if (command == 0) {
-                       /* Tuner Reset Command from xc5000 */
-                       /* Drive the tuner into reset and out */
-                       au0828_clear(dev, REG_001, 2);
-                       mdelay(10);
-                       au0828_set(dev, REG_001, 2);
-                       mdelay(10);
-                       return 0;
-               } else {
-                       printk(KERN_ERR
-                               "%s(): Unknown command.\n", __func__);
-                       return -EINVAL;
-               }
-               break;
-       }
-
-       return 0; /* Should never be here */
-}
-
-static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data)
-{
-       struct tveeprom tv;
-
-       tveeprom_hauppauge_analog(&dev->i2c_client, &tv, eeprom_data);
-       dev->board.tuner_type = tv.tuner_type;
-
-       /* Make sure we support the board model */
-       switch (tv.model) {
-       case 72000: /* WinTV-HVR950q (Retail, IR, ATSC/QAM */
-       case 72001: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
-       case 72101: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
-       case 72201: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
-       case 72211: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
-       case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
-       case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
-       case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and analog video */
-       case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and analog video */
-       case 72261: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and analog video */
-       case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and analog video */
-       case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */
-               break;
-       default:
-               printk(KERN_WARNING "%s: warning: "
-                      "unknown hauppauge model #%d\n", __func__, tv.model);
-               break;
-       }
-
-       printk(KERN_INFO "%s: hauppauge eeprom: model=%d\n",
-              __func__, tv.model);
-}
-
-void au0828_card_setup(struct au0828_dev *dev)
-{
-       static u8 eeprom[256];
-       struct tuner_setup tun_setup;
-       struct v4l2_subdev *sd;
-       unsigned int mode_mask = T_ANALOG_TV;
-
-       dprintk(1, "%s()\n", __func__);
-
-       memcpy(&dev->board, &au0828_boards[dev->boardnr], sizeof(dev->board));
-
-       if (dev->i2c_rc == 0) {
-               dev->i2c_client.addr = 0xa0 >> 1;
-               tveeprom_read(&dev->i2c_client, eeprom, sizeof(eeprom));
-       }
-
-       switch (dev->boardnr) {
-       case AU0828_BOARD_HAUPPAUGE_HVR850:
-       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
-       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
-       case AU0828_BOARD_HAUPPAUGE_WOODBURY:
-               if (dev->i2c_rc == 0)
-                       hauppauge_eeprom(dev, eeprom+0xa0);
-               break;
-       }
-
-       if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED) {
-               /* Load the analog demodulator driver (note this would need to
-                  be abstracted out if we ever need to support a different
-                  demod) */
-               sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                               "au8522", 0x8e >> 1, NULL);
-               if (sd == NULL)
-                       printk(KERN_ERR "analog subdev registration failed\n");
-       }
-
-       /* Setup tuners */
-       if (dev->board.tuner_type != TUNER_ABSENT) {
-               /* Load the tuner module, which does the attach */
-               sd = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                               "tuner", dev->board.tuner_addr, NULL);
-               if (sd == NULL)
-                       printk(KERN_ERR "tuner subdev registration fail\n");
-
-               tun_setup.mode_mask      = mode_mask;
-               tun_setup.type           = dev->board.tuner_type;
-               tun_setup.addr           = dev->board.tuner_addr;
-               tun_setup.tuner_callback = au0828_tuner_callback;
-               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr,
-                                    &tun_setup);
-       }
-}
-
-/*
- * The bridge has between 8 and 12 gpios.
- * Regs 1 and 0 deal with output enables.
- * Regs 3 and 2 deal with direction.
- */
-void au0828_gpio_setup(struct au0828_dev *dev)
-{
-       dprintk(1, "%s()\n", __func__);
-
-       switch (dev->boardnr) {
-       case AU0828_BOARD_HAUPPAUGE_HVR850:
-       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
-       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
-       case AU0828_BOARD_HAUPPAUGE_WOODBURY:
-               /* GPIO's
-                * 4 - CS5340
-                * 5 - AU8522 Demodulator
-                * 6 - eeprom W/P
-                * 7 - power supply
-                * 9 - XC5000 Tuner
-                */
-
-               /* Into reset */
-               au0828_write(dev, REG_003, 0x02);
-               au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10);
-               au0828_write(dev, REG_001, 0x0);
-               au0828_write(dev, REG_000, 0x0);
-               msleep(100);
-
-               /* Out of reset (leave the cs5340 in reset until needed) */
-               au0828_write(dev, REG_003, 0x02);
-               au0828_write(dev, REG_001, 0x02);
-               au0828_write(dev, REG_002, 0x80 | 0x20 | 0x10);
-               au0828_write(dev, REG_000, 0x80 | 0x40 | 0x20);
-
-               msleep(250);
-               break;
-       case AU0828_BOARD_DVICO_FUSIONHDTV7:
-               /* GPIO's
-                * 6 - ?
-                * 8 - AU8522 Demodulator
-                * 9 - XC5000 Tuner
-                */
-
-               /* Into reset */
-               au0828_write(dev, REG_003, 0x02);
-               au0828_write(dev, REG_002, 0xa0);
-               au0828_write(dev, REG_001, 0x0);
-               au0828_write(dev, REG_000, 0x0);
-               msleep(100);
-
-               /* Out of reset */
-               au0828_write(dev, REG_003, 0x02);
-               au0828_write(dev, REG_002, 0xa0);
-               au0828_write(dev, REG_001, 0x02);
-               au0828_write(dev, REG_000, 0xa0);
-               msleep(250);
-               break;
-       }
-}
-
-/* table of devices that work with this driver */
-struct usb_device_id au0828_usb_id_table[] = {
-       { USB_DEVICE(0x2040, 0x7200),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
-       { USB_DEVICE(0x2040, 0x7240),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR850 },
-       { USB_DEVICE(0x0fe9, 0xd620),
-               .driver_info = AU0828_BOARD_DVICO_FUSIONHDTV7 },
-       { USB_DEVICE(0x2040, 0x7210),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
-       { USB_DEVICE(0x2040, 0x7217),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
-       { USB_DEVICE(0x2040, 0x721b),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
-       { USB_DEVICE(0x2040, 0x721e),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
-       { USB_DEVICE(0x2040, 0x721f),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
-       { USB_DEVICE(0x2040, 0x7280),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
-       { USB_DEVICE(0x0fd9, 0x0008),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
-       { USB_DEVICE(0x2040, 0x7201),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
-       { USB_DEVICE(0x2040, 0x7211),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
-       { USB_DEVICE(0x2040, 0x7281),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL },
-       { USB_DEVICE(0x05e1, 0x0480),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY },
-       { USB_DEVICE(0x2040, 0x8200),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_WOODBURY },
-       { USB_DEVICE(0x2040, 0x7260),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
-       { USB_DEVICE(0x2040, 0x7213),
-               .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q },
-       { },
-};
-
-MODULE_DEVICE_TABLE(usb, au0828_usb_id_table);
diff --git a/drivers/media/video/au0828/au0828-cards.h b/drivers/media/video/au0828/au0828-cards.h
deleted file mode 100644 (file)
index 48a1882..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  Driver for the Auvitek USB bridge
- *
- *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
- *
- *  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.
- */
-
-#define AU0828_BOARD_UNKNOWN           0
-#define AU0828_BOARD_HAUPPAUGE_HVR950Q 1
-#define AU0828_BOARD_HAUPPAUGE_HVR850  2
-#define AU0828_BOARD_DVICO_FUSIONHDTV7 3
-#define AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL     4
-#define AU0828_BOARD_HAUPPAUGE_WOODBURY        5
diff --git a/drivers/media/video/au0828/au0828-core.c b/drivers/media/video/au0828/au0828-core.c
deleted file mode 100644 (file)
index 745a80a..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- *  Driver for the Auvitek USB bridge
- *
- *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
- *
- *  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/module.h>
-#include <linux/slab.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <linux/mutex.h>
-
-#include "au0828.h"
-
-/*
- * 1 = General debug messages
- * 2 = USB handling
- * 4 = I2C related
- * 8 = Bridge related
- */
-int au0828_debug;
-module_param_named(debug, au0828_debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug messages");
-
-static unsigned int disable_usb_speed_check;
-module_param(disable_usb_speed_check, int, 0444);
-MODULE_PARM_DESC(disable_usb_speed_check,
-                "override min bandwidth requirement of 480M bps");
-
-#define _AU0828_BULKPIPE 0x03
-#define _BULKPIPESIZE 0xffff
-
-static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
-                           u16 index);
-static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
-       u16 index, unsigned char *cp, u16 size);
-
-/* USB Direction */
-#define CMD_REQUEST_IN         0x00
-#define CMD_REQUEST_OUT                0x01
-
-u32 au0828_readreg(struct au0828_dev *dev, u16 reg)
-{
-       u8 result = 0;
-
-       recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, &result, 1);
-       dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, result);
-
-       return result;
-}
-
-u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
-{
-       dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val);
-       return send_control_msg(dev, CMD_REQUEST_OUT, val, reg);
-}
-
-static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
-       u16 index)
-{
-       int status = -ENODEV;
-
-       if (dev->usbdev) {
-
-               /* cp must be memory that has been allocated by kmalloc */
-               status = usb_control_msg(dev->usbdev,
-                               usb_sndctrlpipe(dev->usbdev, 0),
-                               request,
-                               USB_DIR_OUT | USB_TYPE_VENDOR |
-                                       USB_RECIP_DEVICE,
-                               value, index, NULL, 0, 1000);
-
-               status = min(status, 0);
-
-               if (status < 0) {
-                       printk(KERN_ERR "%s() Failed sending control message, error %d.\n",
-                               __func__, status);
-               }
-
-       }
-
-       return status;
-}
-
-static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
-       u16 index, unsigned char *cp, u16 size)
-{
-       int status = -ENODEV;
-       mutex_lock(&dev->mutex);
-       if (dev->usbdev) {
-               status = usb_control_msg(dev->usbdev,
-                               usb_rcvctrlpipe(dev->usbdev, 0),
-                               request,
-                               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                               value, index,
-                               dev->ctrlmsg, size, 1000);
-
-               status = min(status, 0);
-
-               if (status < 0) {
-                       printk(KERN_ERR "%s() Failed receiving control message, error %d.\n",
-                               __func__, status);
-               }
-
-               /* the host controller requires heap allocated memory, which
-                  is why we didn't just pass "cp" into usb_control_msg */
-               memcpy(cp, dev->ctrlmsg, size);
-       }
-       mutex_unlock(&dev->mutex);
-       return status;
-}
-
-static void au0828_usb_disconnect(struct usb_interface *interface)
-{
-       struct au0828_dev *dev = usb_get_intfdata(interface);
-
-       dprintk(1, "%s()\n", __func__);
-
-       /* Digital TV */
-       au0828_dvb_unregister(dev);
-
-       if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED)
-               au0828_analog_unregister(dev);
-
-       /* I2C */
-       au0828_i2c_unregister(dev);
-
-       v4l2_device_unregister(&dev->v4l2_dev);
-
-       usb_set_intfdata(interface, NULL);
-
-       mutex_lock(&dev->mutex);
-       dev->usbdev = NULL;
-       mutex_unlock(&dev->mutex);
-
-       kfree(dev);
-
-}
-
-static int au0828_usb_probe(struct usb_interface *interface,
-       const struct usb_device_id *id)
-{
-       int ifnum, retval;
-       struct au0828_dev *dev;
-       struct usb_device *usbdev = interface_to_usbdev(interface);
-
-       ifnum = interface->altsetting->desc.bInterfaceNumber;
-
-       if (ifnum != 0)
-               return -ENODEV;
-
-       dprintk(1, "%s() vendor id 0x%x device id 0x%x ifnum:%d\n", __func__,
-               le16_to_cpu(usbdev->descriptor.idVendor),
-               le16_to_cpu(usbdev->descriptor.idProduct),
-               ifnum);
-
-       /*
-        * Make sure we have 480 Mbps of bandwidth, otherwise things like
-        * video stream wouldn't likely work, since 12 Mbps is generally
-        * not enough even for most Digital TV streams.
-        */
-       if (usbdev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {
-               printk(KERN_ERR "au0828: Device initialization failed.\n");
-               printk(KERN_ERR "au0828: Device must be connected to a "
-                      "high-speed USB 2.0 port.\n");
-               return -ENODEV;
-       }
-
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL) {
-               printk(KERN_ERR "%s() Unable to allocate memory\n", __func__);
-               return -ENOMEM;
-       }
-
-       mutex_init(&dev->lock);
-       mutex_lock(&dev->lock);
-       mutex_init(&dev->mutex);
-       mutex_init(&dev->dvb.lock);
-       dev->usbdev = usbdev;
-       dev->boardnr = id->driver_info;
-
-       /* Create the v4l2_device */
-       retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
-       if (retval) {
-               printk(KERN_ERR "%s() v4l2_device_register failed\n",
-                      __func__);
-               mutex_unlock(&dev->lock);
-               kfree(dev);
-               return -EIO;
-       }
-
-       /* Power Up the bridge */
-       au0828_write(dev, REG_600, 1 << 4);
-
-       /* Bring up the GPIO's and supporting devices */
-       au0828_gpio_setup(dev);
-
-       /* I2C */
-       au0828_i2c_register(dev);
-
-       /* Setup */
-       au0828_card_setup(dev);
-
-       /* Analog TV */
-       if (AUVI_INPUT(0).type != AU0828_VMUX_UNDEFINED)
-               au0828_analog_register(dev, interface);
-
-       /* Digital TV */
-       au0828_dvb_register(dev);
-
-       /* Store the pointer to the au0828_dev so it can be accessed in
-          au0828_usb_disconnect */
-       usb_set_intfdata(interface, dev);
-
-       printk(KERN_INFO "Registered device AU0828 [%s]\n",
-               dev->board.name == NULL ? "Unset" : dev->board.name);
-
-       mutex_unlock(&dev->lock);
-
-       return 0;
-}
-
-static struct usb_driver au0828_usb_driver = {
-       .name           = DRIVER_NAME,
-       .probe          = au0828_usb_probe,
-       .disconnect     = au0828_usb_disconnect,
-       .id_table       = au0828_usb_id_table,
-};
-
-static int __init au0828_init(void)
-{
-       int ret;
-
-       if (au0828_debug & 1)
-               printk(KERN_INFO "%s() Debugging is enabled\n", __func__);
-
-       if (au0828_debug & 2)
-               printk(KERN_INFO "%s() USB Debugging is enabled\n", __func__);
-
-       if (au0828_debug & 4)
-               printk(KERN_INFO "%s() I2C Debugging is enabled\n", __func__);
-
-       if (au0828_debug & 8)
-               printk(KERN_INFO "%s() Bridge Debugging is enabled\n",
-                      __func__);
-
-       printk(KERN_INFO "au0828 driver loaded\n");
-
-       ret = usb_register(&au0828_usb_driver);
-       if (ret)
-               printk(KERN_ERR "usb_register failed, error = %d\n", ret);
-
-       return ret;
-}
-
-static void __exit au0828_exit(void)
-{
-       usb_deregister(&au0828_usb_driver);
-}
-
-module_init(au0828_init);
-module_exit(au0828_exit);
-
-MODULE_DESCRIPTION("Driver for Auvitek AU0828 based products");
-MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.0.2");
diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c
deleted file mode 100644 (file)
index b328f65..0000000
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- *  Driver for the Auvitek USB bridge
- *
- *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
- *
- *  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/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/suspend.h>
-#include <media/v4l2-common.h>
-#include <media/tuner.h>
-
-#include "au0828.h"
-#include "au8522.h"
-#include "xc5000.h"
-#include "mxl5007t.h"
-#include "tda18271.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define _AU0828_BULKPIPE 0x83
-#define _BULKPIPESIZE 0xe522
-
-static u8 hauppauge_hvr950q_led_states[] = {
-       0x00, /* off */
-       0x02, /* yellow */
-       0x04, /* green */
-};
-
-static struct au8522_led_config hauppauge_hvr950q_led_cfg = {
-       .gpio_output = 0x00e0,
-       .gpio_output_enable  = 0x6006,
-       .gpio_output_disable = 0x0660,
-
-       .gpio_leds = 0x00e2,
-       .led_states  = hauppauge_hvr950q_led_states,
-       .num_led_states = sizeof(hauppauge_hvr950q_led_states),
-
-       .vsb8_strong   = 20 /* dB */ * 10,
-       .qam64_strong  = 25 /* dB */ * 10,
-       .qam256_strong = 32 /* dB */ * 10,
-};
-
-static struct au8522_config hauppauge_hvr950q_config = {
-       .demod_address = 0x8e >> 1,
-       .status_mode   = AU8522_DEMODLOCKING,
-       .qam_if        = AU8522_IF_6MHZ,
-       .vsb_if        = AU8522_IF_6MHZ,
-       .led_cfg       = &hauppauge_hvr950q_led_cfg,
-};
-
-static struct au8522_config fusionhdtv7usb_config = {
-       .demod_address = 0x8e >> 1,
-       .status_mode   = AU8522_DEMODLOCKING,
-       .qam_if        = AU8522_IF_6MHZ,
-       .vsb_if        = AU8522_IF_6MHZ,
-};
-
-static struct au8522_config hauppauge_woodbury_config = {
-       .demod_address = 0x8e >> 1,
-       .status_mode   = AU8522_DEMODLOCKING,
-       .qam_if        = AU8522_IF_4MHZ,
-       .vsb_if        = AU8522_IF_3_25MHZ,
-};
-
-static struct xc5000_config hauppauge_xc5000a_config = {
-       .i2c_address      = 0x61,
-       .if_khz           = 6000,
-       .chip_id          = XC5000A,
-};
-
-static struct xc5000_config hauppauge_xc5000c_config = {
-       .i2c_address      = 0x61,
-       .if_khz           = 6000,
-       .chip_id          = XC5000C,
-};
-
-static struct mxl5007t_config mxl5007t_hvr950q_config = {
-       .xtal_freq_hz = MxL_XTAL_24_MHZ,
-       .if_freq_hz = MxL_IF_6_MHZ,
-};
-
-static struct tda18271_config hauppauge_woodbury_tunerconfig = {
-       .gate    = TDA18271_GATE_DIGITAL,
-};
-
-static void au0828_restart_dvb_streaming(struct work_struct *work);
-
-/*-------------------------------------------------------------------*/
-static void urb_completion(struct urb *purb)
-{
-       struct au0828_dev *dev = purb->context;
-       int ptype = usb_pipetype(purb->pipe);
-       unsigned char *ptr;
-
-       dprintk(2, "%s()\n", __func__);
-
-       if (!dev)
-               return;
-
-       if (dev->urb_streaming == 0)
-               return;
-
-       if (ptype != PIPE_BULK) {
-               printk(KERN_ERR "%s() Unsupported URB type %d\n",
-                      __func__, ptype);
-               return;
-       }
-
-       /* See if the stream is corrupted (to work around a hardware
-          bug where the stream gets misaligned */
-       ptr = purb->transfer_buffer;
-       if (purb->actual_length > 0 && ptr[0] != 0x47) {
-               dprintk(1, "Need to restart streaming %02x len=%d!\n",
-                       ptr[0], purb->actual_length);
-               schedule_work(&dev->restart_streaming);
-               return;
-       }
-
-       /* Feed the transport payload into the kernel demux */
-       dvb_dmx_swfilter_packets(&dev->dvb.demux,
-               purb->transfer_buffer, purb->actual_length / 188);
-
-       /* Clean the buffer before we requeue */
-       memset(purb->transfer_buffer, 0, URB_BUFSIZE);
-
-       /* Requeue URB */
-       usb_submit_urb(purb, GFP_ATOMIC);
-}
-
-static int stop_urb_transfer(struct au0828_dev *dev)
-{
-       int i;
-
-       dprintk(2, "%s()\n", __func__);
-
-       dev->urb_streaming = 0;
-       for (i = 0; i < URB_COUNT; i++) {
-               usb_kill_urb(dev->urbs[i]);
-               kfree(dev->urbs[i]->transfer_buffer);
-               usb_free_urb(dev->urbs[i]);
-       }
-
-       return 0;
-}
-
-static int start_urb_transfer(struct au0828_dev *dev)
-{
-       struct urb *purb;
-       int i, ret = -ENOMEM;
-
-       dprintk(2, "%s()\n", __func__);
-
-       if (dev->urb_streaming) {
-               dprintk(2, "%s: bulk xfer already running!\n", __func__);
-               return 0;
-       }
-
-       for (i = 0; i < URB_COUNT; i++) {
-
-               dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
-               if (!dev->urbs[i])
-                       goto err;
-
-               purb = dev->urbs[i];
-
-               purb->transfer_buffer = kzalloc(URB_BUFSIZE, GFP_KERNEL);
-               if (!purb->transfer_buffer) {
-                       usb_free_urb(purb);
-                       dev->urbs[i] = NULL;
-                       goto err;
-               }
-
-               purb->status = -EINPROGRESS;
-               usb_fill_bulk_urb(purb,
-                                 dev->usbdev,
-                                 usb_rcvbulkpipe(dev->usbdev,
-                                       _AU0828_BULKPIPE),
-                                 purb->transfer_buffer,
-                                 URB_BUFSIZE,
-                                 urb_completion,
-                                 dev);
-
-       }
-
-       for (i = 0; i < URB_COUNT; i++) {
-               ret = usb_submit_urb(dev->urbs[i], GFP_ATOMIC);
-               if (ret != 0) {
-                       stop_urb_transfer(dev);
-                       printk(KERN_ERR "%s: failed urb submission, "
-                              "err = %d\n", __func__, ret);
-                       return ret;
-               }
-       }
-
-       dev->urb_streaming = 1;
-       ret = 0;
-
-err:
-       return ret;
-}
-
-static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
-{
-       struct dvb_demux *demux = feed->demux;
-       struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
-       struct au0828_dvb *dvb = &dev->dvb;
-       int ret = 0;
-
-       dprintk(1, "%s()\n", __func__);
-
-       if (!demux->dmx.frontend)
-               return -EINVAL;
-
-       if (dvb) {
-               mutex_lock(&dvb->lock);
-               if (dvb->feeding++ == 0) {
-                       /* Start transport */
-                       au0828_write(dev, 0x608, 0x90);
-                       au0828_write(dev, 0x609, 0x72);
-                       au0828_write(dev, 0x60a, 0x71);
-                       au0828_write(dev, 0x60b, 0x01);
-                       ret = start_urb_transfer(dev);
-               }
-               mutex_unlock(&dvb->lock);
-       }
-
-       return ret;
-}
-
-static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
-{
-       struct dvb_demux *demux = feed->demux;
-       struct au0828_dev *dev = (struct au0828_dev *) demux->priv;
-       struct au0828_dvb *dvb = &dev->dvb;
-       int ret = 0;
-
-       dprintk(1, "%s()\n", __func__);
-
-       if (dvb) {
-               mutex_lock(&dvb->lock);
-               if (--dvb->feeding == 0) {
-                       /* Stop transport */
-                       ret = stop_urb_transfer(dev);
-                       au0828_write(dev, 0x60b, 0x00);
-               }
-               mutex_unlock(&dvb->lock);
-       }
-
-       return ret;
-}
-
-static void au0828_restart_dvb_streaming(struct work_struct *work)
-{
-       struct au0828_dev *dev = container_of(work, struct au0828_dev,
-                                             restart_streaming);
-       struct au0828_dvb *dvb = &dev->dvb;
-       int ret;
-
-       if (dev->urb_streaming == 0)
-               return;
-
-       dprintk(1, "Restarting streaming...!\n");
-
-       mutex_lock(&dvb->lock);
-
-       /* Stop transport */
-       ret = stop_urb_transfer(dev);
-       au0828_write(dev, 0x608, 0x00);
-       au0828_write(dev, 0x609, 0x00);
-       au0828_write(dev, 0x60a, 0x00);
-       au0828_write(dev, 0x60b, 0x00);
-
-       /* Start transport */
-       au0828_write(dev, 0x608, 0x90);
-       au0828_write(dev, 0x609, 0x72);
-       au0828_write(dev, 0x60a, 0x71);
-       au0828_write(dev, 0x60b, 0x01);
-       ret = start_urb_transfer(dev);
-
-       mutex_unlock(&dvb->lock);
-}
-
-static int dvb_register(struct au0828_dev *dev)
-{
-       struct au0828_dvb *dvb = &dev->dvb;
-       int result;
-
-       dprintk(1, "%s()\n", __func__);
-
-       INIT_WORK(&dev->restart_streaming, au0828_restart_dvb_streaming);
-
-       /* register adapter */
-       result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
-                                     &dev->usbdev->dev, adapter_nr);
-       if (result < 0) {
-               printk(KERN_ERR "%s: dvb_register_adapter failed "
-                      "(errno = %d)\n", DRIVER_NAME, result);
-               goto fail_adapter;
-       }
-       dvb->adapter.priv = dev;
-
-       /* register frontend */
-       result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
-       if (result < 0) {
-               printk(KERN_ERR "%s: dvb_register_frontend failed "
-                      "(errno = %d)\n", DRIVER_NAME, result);
-               goto fail_frontend;
-       }
-
-       /* register demux stuff */
-       dvb->demux.dmx.capabilities =
-               DMX_TS_FILTERING | DMX_SECTION_FILTERING |
-               DMX_MEMORY_BASED_FILTERING;
-       dvb->demux.priv       = dev;
-       dvb->demux.filternum  = 256;
-       dvb->demux.feednum    = 256;
-       dvb->demux.start_feed = au0828_dvb_start_feed;
-       dvb->demux.stop_feed  = au0828_dvb_stop_feed;
-       result = dvb_dmx_init(&dvb->demux);
-       if (result < 0) {
-               printk(KERN_ERR "%s: dvb_dmx_init failed (errno = %d)\n",
-                      DRIVER_NAME, result);
-               goto fail_dmx;
-       }
-
-       dvb->dmxdev.filternum    = 256;
-       dvb->dmxdev.demux        = &dvb->demux.dmx;
-       dvb->dmxdev.capabilities = 0;
-       result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
-       if (result < 0) {
-               printk(KERN_ERR "%s: dvb_dmxdev_init failed (errno = %d)\n",
-                      DRIVER_NAME, result);
-               goto fail_dmxdev;
-       }
-
-       dvb->fe_hw.source = DMX_FRONTEND_0;
-       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
-       if (result < 0) {
-               printk(KERN_ERR "%s: add_frontend failed "
-                      "(DMX_FRONTEND_0, errno = %d)\n", DRIVER_NAME, result);
-               goto fail_fe_hw;
-       }
-
-       dvb->fe_mem.source = DMX_MEMORY_FE;
-       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
-       if (result < 0) {
-               printk(KERN_ERR "%s: add_frontend failed "
-                      "(DMX_MEMORY_FE, errno = %d)\n", DRIVER_NAME, result);
-               goto fail_fe_mem;
-       }
-
-       result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
-       if (result < 0) {
-               printk(KERN_ERR "%s: connect_frontend failed (errno = %d)\n",
-                      DRIVER_NAME, result);
-               goto fail_fe_conn;
-       }
-
-       /* register network adapter */
-       dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
-       return 0;
-
-fail_fe_conn:
-       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
-fail_fe_mem:
-       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
-fail_fe_hw:
-       dvb_dmxdev_release(&dvb->dmxdev);
-fail_dmxdev:
-       dvb_dmx_release(&dvb->demux);
-fail_dmx:
-       dvb_unregister_frontend(dvb->frontend);
-fail_frontend:
-       dvb_frontend_detach(dvb->frontend);
-       dvb_unregister_adapter(&dvb->adapter);
-fail_adapter:
-       return result;
-}
-
-void au0828_dvb_unregister(struct au0828_dev *dev)
-{
-       struct au0828_dvb *dvb = &dev->dvb;
-
-       dprintk(1, "%s()\n", __func__);
-
-       if (dvb->frontend == NULL)
-               return;
-
-       dvb_net_release(&dvb->net);
-       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
-       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
-       dvb_dmxdev_release(&dvb->dmxdev);
-       dvb_dmx_release(&dvb->demux);
-       dvb_unregister_frontend(dvb->frontend);
-       dvb_frontend_detach(dvb->frontend);
-       dvb_unregister_adapter(&dvb->adapter);
-}
-
-/* All the DVB attach calls go here, this function get's modified
- * for each new card. No other function in this file needs
- * to change.
- */
-int au0828_dvb_register(struct au0828_dev *dev)
-{
-       struct au0828_dvb *dvb = &dev->dvb;
-       int ret;
-
-       dprintk(1, "%s()\n", __func__);
-
-       /* init frontend */
-       switch (dev->boardnr) {
-       case AU0828_BOARD_HAUPPAUGE_HVR850:
-       case AU0828_BOARD_HAUPPAUGE_HVR950Q:
-               dvb->frontend = dvb_attach(au8522_attach,
-                               &hauppauge_hvr950q_config,
-                               &dev->i2c_adap);
-               if (dvb->frontend != NULL)
-                       switch (dev->board.tuner_type) {
-                       default:
-                       case TUNER_XC5000:
-                               dvb_attach(xc5000_attach, dvb->frontend,
-                                          &dev->i2c_adap,
-                                          &hauppauge_xc5000a_config);
-                               break;
-                       case TUNER_XC5000C:
-                               dvb_attach(xc5000_attach, dvb->frontend,
-                                          &dev->i2c_adap,
-                                          &hauppauge_xc5000c_config);
-                               break;
-                       }
-               break;
-       case AU0828_BOARD_HAUPPAUGE_HVR950Q_MXL:
-               dvb->frontend = dvb_attach(au8522_attach,
-                               &hauppauge_hvr950q_config,
-                               &dev->i2c_adap);
-               if (dvb->frontend != NULL)
-                       dvb_attach(mxl5007t_attach, dvb->frontend,
-                                  &dev->i2c_adap, 0x60,
-                                  &mxl5007t_hvr950q_config);
-               break;
-       case AU0828_BOARD_HAUPPAUGE_WOODBURY:
-               dvb->frontend = dvb_attach(au8522_attach,
-                               &hauppauge_woodbury_config,
-                               &dev->i2c_adap);
-               if (dvb->frontend != NULL)
-                       dvb_attach(tda18271_attach, dvb->frontend,
-                                  0x60, &dev->i2c_adap,
-                                  &hauppauge_woodbury_tunerconfig);
-               break;
-       case AU0828_BOARD_DVICO_FUSIONHDTV7:
-               dvb->frontend = dvb_attach(au8522_attach,
-                               &fusionhdtv7usb_config,
-                               &dev->i2c_adap);
-               if (dvb->frontend != NULL) {
-                       dvb_attach(xc5000_attach, dvb->frontend,
-                               &dev->i2c_adap,
-                               &hauppauge_xc5000a_config);
-               }
-               break;
-       default:
-               printk(KERN_WARNING "The frontend of your DVB/ATSC card "
-                      "isn't supported yet\n");
-               break;
-       }
-       if (NULL == dvb->frontend) {
-               printk(KERN_ERR "%s() Frontend initialization failed\n",
-                      __func__);
-               return -1;
-       }
-       /* define general-purpose callback pointer */
-       dvb->frontend->callback = au0828_tuner_callback;
-
-       /* register everything */
-       ret = dvb_register(dev);
-       if (ret < 0) {
-               if (dvb->frontend->ops.release)
-                       dvb->frontend->ops.release(dvb->frontend);
-               return ret;
-       }
-
-       return 0;
-}
diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c
deleted file mode 100644 (file)
index 4ded17f..0000000
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- *  Driver for the Auvitek AU0828 USB bridge
- *
- *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
- *
- *  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/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include "au0828.h"
-#include "media/tuner.h"
-#include <media/v4l2-common.h>
-
-static int i2c_scan;
-module_param(i2c_scan, int, 0444);
-MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
-
-#define I2C_WAIT_DELAY 25
-#define I2C_WAIT_RETRY 1000
-
-static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap)
-{
-       struct au0828_dev *dev = i2c_adap->algo_data;
-       return au0828_read(dev, AU0828_I2C_STATUS_201) &
-               AU0828_I2C_STATUS_NO_WRITE_ACK ? 0 : 1;
-}
-
-static inline int i2c_slave_did_read_ack(struct i2c_adapter *i2c_adap)
-{
-       struct au0828_dev *dev = i2c_adap->algo_data;
-       return au0828_read(dev, AU0828_I2C_STATUS_201) &
-               AU0828_I2C_STATUS_NO_READ_ACK ? 0 : 1;
-}
-
-static int i2c_wait_read_ack(struct i2c_adapter *i2c_adap)
-{
-       int count;
-
-       for (count = 0; count < I2C_WAIT_RETRY; count++) {
-               if (!i2c_slave_did_read_ack(i2c_adap))
-                       break;
-               udelay(I2C_WAIT_DELAY);
-       }
-
-       if (I2C_WAIT_RETRY == count)
-               return 0;
-
-       return 1;
-}
-
-static inline int i2c_is_read_busy(struct i2c_adapter *i2c_adap)
-{
-       struct au0828_dev *dev = i2c_adap->algo_data;
-       return au0828_read(dev, AU0828_I2C_STATUS_201) &
-               AU0828_I2C_STATUS_READ_DONE ? 0 : 1;
-}
-
-static int i2c_wait_read_done(struct i2c_adapter *i2c_adap)
-{
-       int count;
-
-       for (count = 0; count < I2C_WAIT_RETRY; count++) {
-               if (!i2c_is_read_busy(i2c_adap))
-                       break;
-               udelay(I2C_WAIT_DELAY);
-       }
-
-       if (I2C_WAIT_RETRY == count)
-               return 0;
-
-       return 1;
-}
-
-static inline int i2c_is_write_done(struct i2c_adapter *i2c_adap)
-{
-       struct au0828_dev *dev = i2c_adap->algo_data;
-       return au0828_read(dev, AU0828_I2C_STATUS_201) &
-               AU0828_I2C_STATUS_WRITE_DONE ? 1 : 0;
-}
-
-static int i2c_wait_write_done(struct i2c_adapter *i2c_adap)
-{
-       int count;
-
-       for (count = 0; count < I2C_WAIT_RETRY; count++) {
-               if (i2c_is_write_done(i2c_adap))
-                       break;
-               udelay(I2C_WAIT_DELAY);
-       }
-
-       if (I2C_WAIT_RETRY == count)
-               return 0;
-
-       return 1;
-}
-
-static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
-{
-       struct au0828_dev *dev = i2c_adap->algo_data;
-       return au0828_read(dev, AU0828_I2C_STATUS_201) &
-               AU0828_I2C_STATUS_BUSY ? 1 : 0;
-}
-
-static int i2c_wait_done(struct i2c_adapter *i2c_adap)
-{
-       int count;
-
-       for (count = 0; count < I2C_WAIT_RETRY; count++) {
-               if (!i2c_is_busy(i2c_adap))
-                       break;
-               udelay(I2C_WAIT_DELAY);
-       }
-
-       if (I2C_WAIT_RETRY == count)
-               return 0;
-
-       return 1;
-}
-
-/* FIXME: Implement join handling correctly */
-static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
-       const struct i2c_msg *msg, int joined_rlen)
-{
-       int i, strobe = 0;
-       struct au0828_dev *dev = i2c_adap->algo_data;
-
-       dprintk(4, "%s()\n", __func__);
-
-       au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
-
-       /* Set the I2C clock */
-       if (((dev->board.tuner_type == TUNER_XC5000) ||
-            (dev->board.tuner_type == TUNER_XC5000C)) &&
-           (dev->board.tuner_addr == msg->addr) &&
-           (msg->len == 64)) {
-               /* Hack to speed up firmware load.  The xc5000 lets us do up
-                  to 400 KHz when in firmware download mode */
-               au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
-                            AU0828_I2C_CLK_250KHZ);
-       } else {
-               /* Use the i2c clock speed in the board configuration */
-               au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
-                            dev->board.i2c_clk_divider);
-       }
-
-       /* Hardware needs 8 bit addresses */
-       au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
-
-       dprintk(4, "SEND: %02x\n", msg->addr);
-
-       /* Deal with i2c_scan */
-       if (msg->len == 0) {
-               /* The analog tuner detection code makes use of the SMBUS_QUICK
-                  message (which involves a zero length i2c write).  To avoid
-                  checking the status register when we didn't strobe out any
-                  actual bytes to the bus, just do a read check.  This is
-                  consistent with how I saw i2c device checking done in the
-                  USB trace of the Windows driver */
-               au0828_write(dev, AU0828_I2C_TRIGGER_200,
-                            AU0828_I2C_TRIGGER_READ);
-
-               if (!i2c_wait_done(i2c_adap))
-                       return -EIO;
-
-               if (i2c_wait_read_ack(i2c_adap))
-                       return -EIO;
-
-               return 0;
-       }
-
-       for (i = 0; i < msg->len;) {
-
-               dprintk(4, " %02x\n", msg->buf[i]);
-
-               au0828_write(dev, AU0828_I2C_WRITE_FIFO_205, msg->buf[i]);
-
-               strobe++;
-               i++;
-
-               if ((strobe >= 4) || (i >= msg->len)) {
-
-                       /* Strobe the byte into the bus */
-                       if (i < msg->len)
-                               au0828_write(dev, AU0828_I2C_TRIGGER_200,
-                                            AU0828_I2C_TRIGGER_WRITE |
-                                            AU0828_I2C_TRIGGER_HOLD);
-                       else
-                               au0828_write(dev, AU0828_I2C_TRIGGER_200,
-                                            AU0828_I2C_TRIGGER_WRITE);
-
-                       /* Reset strobe trigger */
-                       strobe = 0;
-
-                       if (!i2c_wait_write_done(i2c_adap))
-                               return -EIO;
-
-               }
-
-       }
-       if (!i2c_wait_done(i2c_adap))
-               return -EIO;
-
-       dprintk(4, "\n");
-
-       return msg->len;
-}
-
-/* FIXME: Implement join handling correctly */
-static int i2c_readbytes(struct i2c_adapter *i2c_adap,
-       const struct i2c_msg *msg, int joined)
-{
-       struct au0828_dev *dev = i2c_adap->algo_data;
-       int i;
-
-       dprintk(4, "%s()\n", __func__);
-
-       au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
-
-       /* Set the I2C clock */
-       au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
-                    dev->board.i2c_clk_divider);
-
-       /* Hardware needs 8 bit addresses */
-       au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
-
-       dprintk(4, " RECV:\n");
-
-       /* Deal with i2c_scan */
-       if (msg->len == 0) {
-               au0828_write(dev, AU0828_I2C_TRIGGER_200,
-                            AU0828_I2C_TRIGGER_READ);
-
-               if (i2c_wait_read_ack(i2c_adap))
-                       return -EIO;
-               return 0;
-       }
-
-       for (i = 0; i < msg->len;) {
-
-               i++;
-
-               if (i < msg->len)
-                       au0828_write(dev, AU0828_I2C_TRIGGER_200,
-                                    AU0828_I2C_TRIGGER_READ |
-                                    AU0828_I2C_TRIGGER_HOLD);
-               else
-                       au0828_write(dev, AU0828_I2C_TRIGGER_200,
-                                    AU0828_I2C_TRIGGER_READ);
-
-               if (!i2c_wait_read_done(i2c_adap))
-                       return -EIO;
-
-               msg->buf[i-1] = au0828_read(dev, AU0828_I2C_READ_FIFO_209) &
-                       0xff;
-
-               dprintk(4, " %02x\n", msg->buf[i-1]);
-       }
-       if (!i2c_wait_done(i2c_adap))
-               return -EIO;
-
-       dprintk(4, "\n");
-
-       return msg->len;
-}
-
-static int i2c_xfer(struct i2c_adapter *i2c_adap,
-                   struct i2c_msg *msgs, int num)
-{
-       int i, retval = 0;
-
-       dprintk(4, "%s(num = %d)\n", __func__, num);
-
-       for (i = 0; i < num; i++) {
-               dprintk(4, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
-                       __func__, num, msgs[i].addr, msgs[i].len);
-               if (msgs[i].flags & I2C_M_RD) {
-                       /* read */
-                       retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
-               } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
-                          msgs[i].addr == msgs[i + 1].addr) {
-                       /* write then read from same address */
-                       retval = i2c_sendbytes(i2c_adap, &msgs[i],
-                                              msgs[i + 1].len);
-                       if (retval < 0)
-                               goto err;
-                       i++;
-                       retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
-               } else {
-                       /* write */
-                       retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
-               }
-               if (retval < 0)
-                       goto err;
-       }
-       return num;
-
-err:
-       return retval;
-}
-
-static u32 au0828_functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm au0828_i2c_algo_template = {
-       .master_xfer    = i2c_xfer,
-       .functionality  = au0828_functionality,
-};
-
-/* ----------------------------------------------------------------------- */
-
-static struct i2c_adapter au0828_i2c_adap_template = {
-       .name              = DRIVER_NAME,
-       .owner             = THIS_MODULE,
-       .algo              = &au0828_i2c_algo_template,
-};
-
-static struct i2c_client au0828_i2c_client_template = {
-       .name   = "au0828 internal",
-};
-
-static char *i2c_devs[128] = {
-       [0x8e >> 1] = "au8522",
-       [0xa0 >> 1] = "eeprom",
-       [0xc2 >> 1] = "tuner/xc5000",
-};
-
-static void do_i2c_scan(char *name, struct i2c_client *c)
-{
-       unsigned char buf;
-       int i, rc;
-
-       for (i = 0; i < 128; i++) {
-               c->addr = i;
-               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] : "???");
-       }
-}
-
-/* init + register i2c adapter */
-int au0828_i2c_register(struct au0828_dev *dev)
-{
-       dprintk(1, "%s()\n", __func__);
-
-       memcpy(&dev->i2c_adap, &au0828_i2c_adap_template,
-              sizeof(dev->i2c_adap));
-       memcpy(&dev->i2c_algo, &au0828_i2c_algo_template,
-              sizeof(dev->i2c_algo));
-       memcpy(&dev->i2c_client, &au0828_i2c_client_template,
-              sizeof(dev->i2c_client));
-
-       dev->i2c_adap.dev.parent = &dev->usbdev->dev;
-
-       strlcpy(dev->i2c_adap.name, DRIVER_NAME,
-               sizeof(dev->i2c_adap.name));
-
-       dev->i2c_adap.algo = &dev->i2c_algo;
-       dev->i2c_adap.algo_data = dev;
-       i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
-       i2c_add_adapter(&dev->i2c_adap);
-
-       dev->i2c_client.adapter = &dev->i2c_adap;
-
-       if (0 == dev->i2c_rc) {
-               printk(KERN_INFO "%s: i2c bus registered\n", DRIVER_NAME);
-               if (i2c_scan)
-                       do_i2c_scan(DRIVER_NAME, &dev->i2c_client);
-       } else
-               printk(KERN_INFO "%s: i2c bus register FAILED\n", DRIVER_NAME);
-
-       return dev->i2c_rc;
-}
-
-int au0828_i2c_unregister(struct au0828_dev *dev)
-{
-       i2c_del_adapter(&dev->i2c_adap);
-       return 0;
-}
-
diff --git a/drivers/media/video/au0828/au0828-reg.h b/drivers/media/video/au0828/au0828-reg.h
deleted file mode 100644 (file)
index 2140f4c..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *  Driver for the Auvitek USB bridge
- *
- *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
- *
- *  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.
- */
-
-/* We'll start to rename these registers once we have a better
- * understanding of their meaning.
- */
-#define REG_000 0x000
-#define REG_001 0x001
-#define REG_002 0x002
-#define REG_003 0x003
-
-#define AU0828_SENSORCTRL_100 0x100
-#define AU0828_SENSORCTRL_VBI_103 0x103
-
-/* I2C registers */
-#define AU0828_I2C_TRIGGER_200         0x200
-#define AU0828_I2C_STATUS_201          0x201
-#define AU0828_I2C_CLK_DIVIDER_202     0x202
-#define AU0828_I2C_DEST_ADDR_203       0x203
-#define AU0828_I2C_WRITE_FIFO_205      0x205
-#define AU0828_I2C_READ_FIFO_209       0x209
-#define AU0828_I2C_MULTIBYTE_MODE_2FF  0x2ff
-
-/* Audio registers */
-#define AU0828_AUDIOCTRL_50C 0x50C
-
-#define REG_600 0x600
-
-/*********************************************************************/
-/* Here are constants for values associated with the above registers */
-
-/* I2C Trigger (Reg 0x200) */
-#define AU0828_I2C_TRIGGER_WRITE       0x01
-#define AU0828_I2C_TRIGGER_READ                0x20
-#define AU0828_I2C_TRIGGER_HOLD                0x40
-
-/* I2C Status (Reg 0x201) */
-#define AU0828_I2C_STATUS_READ_DONE    0x01
-#define AU0828_I2C_STATUS_NO_READ_ACK  0x02
-#define AU0828_I2C_STATUS_WRITE_DONE   0x04
-#define AU0828_I2C_STATUS_NO_WRITE_ACK 0x08
-#define AU0828_I2C_STATUS_BUSY         0x10
-
-/* I2C Clock Divider (Reg 0x202) */
-#define AU0828_I2C_CLK_250KHZ 0x07
-#define AU0828_I2C_CLK_100KHZ 0x14
-#define AU0828_I2C_CLK_30KHZ  0x40
-#define AU0828_I2C_CLK_20KHZ  0x60
diff --git a/drivers/media/video/au0828/au0828-vbi.c b/drivers/media/video/au0828/au0828-vbi.c
deleted file mode 100644 (file)
index 63f5930..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-   au0828-vbi.c - VBI driver for au0828
-
-   Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
-
-   This work was sponsored by GetWellNetwork Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
-#include "au0828.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)
-{
-       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);
-
-       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 = dev->vbi_width * dev->vbi_height * 2;
-
-       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)
-{
-       struct au0828_fh     *fh  = q->priv_data;
-       struct au0828_dev    *dev = fh->dev;
-       struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
-       int                  rc = 0;
-
-       buf->vb.size = dev->vbi_width * dev->vbi_height * 2;
-
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.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;
-       }
-
-       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)
-{
-       struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
-       free_buffer(q, buf);
-}
-
-struct videobuf_queue_ops au0828_vbi_qops = {
-       .buf_setup    = vbi_setup,
-       .buf_prepare  = vbi_prepare,
-       .buf_queue    = vbi_queue,
-       .buf_release  = vbi_release,
-};
diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c
deleted file mode 100644 (file)
index fa0fa9a..0000000
+++ /dev/null
@@ -1,2034 +0,0 @@
-/*
- * Auvitek AU0828 USB Bridge (Analog video support)
- *
- * Copyright (C) 2009 Devin Heitmueller <dheitmueller@linuxtv.org>
- * Copyright (C) 2005-2008 Auvitek International, 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-/* Developer Notes:
- *
- * VBI support is not yet working
- * The hardware scaler supported is unimplemented
- * AC97 audio support is unimplemented (only i2s audio mode)
- *
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/suspend.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-chip-ident.h>
-#include <media/tuner.h>
-#include "au0828.h"
-#include "au0828-reg.h"
-
-static DEFINE_MUTEX(au0828_sysfs_lock);
-
-/* ------------------------------------------------------------------
-       Videobuf operations
-   ------------------------------------------------------------------*/
-
-static unsigned int isoc_debug;
-module_param(isoc_debug, int, 0644);
-MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
-
-#define au0828_isocdbg(fmt, arg...) \
-do {\
-       if (isoc_debug) { \
-               printk(KERN_INFO "au0828 %s :"fmt, \
-                      __func__ , ##arg);          \
-       } \
-  } while (0)
-
-static inline void print_err_status(struct au0828_dev *dev,
-                                   int packet, int status)
-{
-       char *errmsg = "Unknown";
-
-       switch (status) {
-       case -ENOENT:
-               errmsg = "unlinked synchronuously";
-               break;
-       case -ECONNRESET:
-               errmsg = "unlinked asynchronuously";
-               break;
-       case -ENOSR:
-               errmsg = "Buffer error (overrun)";
-               break;
-       case -EPIPE:
-               errmsg = "Stalled (device not responding)";
-               break;
-       case -EOVERFLOW:
-               errmsg = "Babble (bad cable?)";
-               break;
-       case -EPROTO:
-               errmsg = "Bit-stuff error (bad cable?)";
-               break;
-       case -EILSEQ:
-               errmsg = "CRC/Timeout (could be anything)";
-               break;
-       case -ETIME:
-               errmsg = "Device does not respond";
-               break;
-       }
-       if (packet < 0) {
-               au0828_isocdbg("URB status %d [%s].\n", status, errmsg);
-       } else {
-               au0828_isocdbg("URB packet %d, status %d [%s].\n",
-                              packet, status, errmsg);
-       }
-}
-
-static int check_dev(struct au0828_dev *dev)
-{
-       if (dev->dev_state & DEV_DISCONNECTED) {
-               printk(KERN_INFO "v4l2 ioctl: device not present\n");
-               return -ENODEV;
-       }
-
-       if (dev->dev_state & DEV_MISCONFIGURED) {
-               printk(KERN_INFO "v4l2 ioctl: device is misconfigured; "
-                      "close and open it again\n");
-               return -EIO;
-       }
-       return 0;
-}
-
-/*
- * IRQ callback, called by URB callback
- */
-static void au0828_irq_callback(struct urb *urb)
-{
-       struct au0828_dmaqueue  *dma_q = urb->context;
-       struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
-       unsigned long flags = 0;
-       int i;
-
-       switch (urb->status) {
-       case 0:             /* success */
-       case -ETIMEDOUT:    /* NAK */
-               break;
-       case -ECONNRESET:   /* kill */
-       case -ENOENT:
-       case -ESHUTDOWN:
-               au0828_isocdbg("au0828_irq_callback called: status kill\n");
-               return;
-       default:            /* unknown error */
-               au0828_isocdbg("urb completition error %d.\n", urb->status);
-               break;
-       }
-
-       /* Copy data from URB */
-       spin_lock_irqsave(&dev->slock, flags);
-       dev->isoc_ctl.isoc_copy(dev, urb);
-       spin_unlock_irqrestore(&dev->slock, flags);
-
-       /* Reset urb buffers */
-       for (i = 0; i < urb->number_of_packets; i++) {
-               urb->iso_frame_desc[i].status = 0;
-               urb->iso_frame_desc[i].actual_length = 0;
-       }
-       urb->status = 0;
-
-       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (urb->status) {
-               au0828_isocdbg("urb resubmit failed (error=%i)\n",
-                              urb->status);
-       }
-}
-
-/*
- * Stop and Deallocate URBs
- */
-void au0828_uninit_isoc(struct au0828_dev *dev)
-{
-       struct urb *urb;
-       int i;
-
-       au0828_isocdbg("au0828: called au0828_uninit_isoc\n");
-
-       dev->isoc_ctl.nfields = -1;
-       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
-               urb = dev->isoc_ctl.urb[i];
-               if (urb) {
-                       if (!irqs_disabled())
-                               usb_kill_urb(urb);
-                       else
-                               usb_unlink_urb(urb);
-
-                       if (dev->isoc_ctl.transfer_buffer[i]) {
-                               usb_free_coherent(dev->usbdev,
-                                       urb->transfer_buffer_length,
-                                       dev->isoc_ctl.transfer_buffer[i],
-                                       urb->transfer_dma);
-                       }
-                       usb_free_urb(urb);
-                       dev->isoc_ctl.urb[i] = NULL;
-               }
-               dev->isoc_ctl.transfer_buffer[i] = NULL;
-       }
-
-       kfree(dev->isoc_ctl.urb);
-       kfree(dev->isoc_ctl.transfer_buffer);
-
-       dev->isoc_ctl.urb = NULL;
-       dev->isoc_ctl.transfer_buffer = NULL;
-       dev->isoc_ctl.num_bufs = 0;
-}
-
-/*
- * Allocate URBs and start IRQ
- */
-int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
-                    int num_bufs, int max_pkt_size,
-                    int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb))
-{
-       struct au0828_dmaqueue *dma_q = &dev->vidq;
-       int i;
-       int sb_size, pipe;
-       struct urb *urb;
-       int j, k;
-       int rc;
-
-       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;
-
-       dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs,  GFP_KERNEL);
-       if (!dev->isoc_ctl.urb) {
-               au0828_isocdbg("cannot alloc memory for usb buffers\n");
-               return -ENOMEM;
-       }
-
-       dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
-                                             GFP_KERNEL);
-       if (!dev->isoc_ctl.transfer_buffer) {
-               au0828_isocdbg("cannot allocate memory for usb transfer\n");
-               kfree(dev->isoc_ctl.urb);
-               return -ENOMEM;
-       }
-
-       dev->isoc_ctl.max_pkt_size = max_pkt_size;
-       dev->isoc_ctl.buf = NULL;
-
-       sb_size = max_packets * dev->isoc_ctl.max_pkt_size;
-
-       /* allocate urbs and transfer buffers */
-       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
-               urb = usb_alloc_urb(max_packets, GFP_KERNEL);
-               if (!urb) {
-                       au0828_isocdbg("cannot alloc isoc_ctl.urb %i\n", i);
-                       au0828_uninit_isoc(dev);
-                       return -ENOMEM;
-               }
-               dev->isoc_ctl.urb[i] = urb;
-
-               dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->usbdev,
-                       sb_size, GFP_KERNEL, &urb->transfer_dma);
-               if (!dev->isoc_ctl.transfer_buffer[i]) {
-                       printk("unable to allocate %i bytes for transfer"
-                                       " buffer %i%s\n",
-                                       sb_size, i,
-                                       in_interrupt() ? " while in int" : "");
-                       au0828_uninit_isoc(dev);
-                       return -ENOMEM;
-               }
-               memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
-
-               pipe = usb_rcvisocpipe(dev->usbdev,
-                                      dev->isoc_in_endpointaddr),
-
-               usb_fill_int_urb(urb, dev->usbdev, pipe,
-                                dev->isoc_ctl.transfer_buffer[i], sb_size,
-                                au0828_irq_callback, dma_q, 1);
-
-               urb->number_of_packets = max_packets;
-               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-
-               k = 0;
-               for (j = 0; j < max_packets; j++) {
-                       urb->iso_frame_desc[j].offset = k;
-                       urb->iso_frame_desc[j].length =
-                                               dev->isoc_ctl.max_pkt_size;
-                       k += dev->isoc_ctl.max_pkt_size;
-               }
-       }
-
-       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);
-               if (rc) {
-                       au0828_isocdbg("submit of urb %i failed (error=%i)\n",
-                                      i, rc);
-                       au0828_uninit_isoc(dev);
-                       return rc;
-               }
-       }
-
-       return 0;
-}
-
-/*
- * Announces that a buffer were filled and request the next
- */
-static inline void buffer_filled(struct au0828_dev *dev,
-                                 struct au0828_dmaqueue *dma_q,
-                                 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++;
-       do_gettimeofday(&buf->vb.ts);
-
-       dev->isoc_ctl.buf = NULL;
-
-       list_del(&buf->vb.queue);
-       wake_up(&buf->vb.done);
-}
-
-static inline void vbi_buffer_filled(struct au0828_dev *dev,
-                                    struct au0828_dmaqueue *dma_q,
-                                    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++;
-       do_gettimeofday(&buf->vb.ts);
-
-       dev->isoc_ctl.vbi_buf = NULL;
-
-       list_del(&buf->vb.queue);
-       wake_up(&buf->vb.done);
-}
-
-/*
- * Identify the buffer header type and properly handles
- */
-static void au0828_copy_video(struct au0828_dev *dev,
-                             struct au0828_dmaqueue  *dma_q,
-                             struct au0828_buffer *buf,
-                             unsigned char *p,
-                             unsigned char *outp, unsigned long len)
-{
-       void *fieldstart, *startwrite, *startread;
-       int  linesdone, currlinedone, offset, lencopy, remain;
-       int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */
-
-       if (len == 0)
-               return;
-
-       if (dma_q->pos + len > buf->vb.size)
-               len = buf->vb.size - dma_q->pos;
-
-       startread = p;
-       remain = len;
-
-       /* Interlaces frame */
-       if (buf->top_field)
-               fieldstart = outp;
-       else
-               fieldstart = outp + bytesperline;
-
-       linesdone = dma_q->pos / bytesperline;
-       currlinedone = dma_q->pos % bytesperline;
-       offset = linesdone * bytesperline * 2 + currlinedone;
-       startwrite = fieldstart + offset;
-       lencopy = bytesperline - currlinedone;
-       lencopy = lencopy > remain ? remain : lencopy;
-
-       if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
-               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;
-               lencopy = remain;
-       }
-       if (lencopy <= 0)
-               return;
-       memcpy(startwrite, startread, lencopy);
-
-       remain -= lencopy;
-
-       while (remain > 0) {
-               startwrite += lencopy + bytesperline;
-               startread += lencopy;
-               if (bytesperline > remain)
-                       lencopy = remain;
-               else
-                       lencopy = bytesperline;
-
-               if ((char *)startwrite + lencopy > (char *)outp +
-                   buf->vb.size) {
-                       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 *)startwrite;
-               }
-               if (lencopy <= 0)
-                       break;
-
-               memcpy(startwrite, startread, lencopy);
-
-               remain -= lencopy;
-       }
-
-       if (offset > 1440) {
-               /* We have enough data to check for greenscreen */
-               if (outp[0] < 0x60 && outp[1440] < 0x60)
-                       dev->greenscreen_detected = 1;
-       }
-
-       dma_q->pos += len;
-}
-
-/*
- * video-buf generic routine to get the next available buffer
- */
-static inline void get_next_buf(struct au0828_dmaqueue *dma_q,
-                               struct au0828_buffer **buf)
-{
-       struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
-
-       if (list_empty(&dma_q->active)) {
-               au0828_isocdbg("No active queue to serve\n");
-               dev->isoc_ctl.buf = NULL;
-               *buf = NULL;
-               return;
-       }
-
-       /* Get the next buffer */
-       *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
-       dev->isoc_ctl.buf = *buf;
-
-       return;
-}
-
-static void au0828_copy_vbi(struct au0828_dev *dev,
-                             struct au0828_dmaqueue  *dma_q,
-                             struct au0828_buffer *buf,
-                             unsigned char *p,
-                             unsigned char *outp, unsigned long len)
-{
-       unsigned char *startwrite, *startread;
-       int bytesperline;
-       int i, j = 0;
-
-       if (dev == NULL) {
-               au0828_isocdbg("dev is null\n");
-               return;
-       }
-
-       if (dma_q == NULL) {
-               au0828_isocdbg("dma_q is null\n");
-               return;
-       }
-       if (buf == NULL)
-               return;
-       if (p == NULL) {
-               au0828_isocdbg("p is null\n");
-               return;
-       }
-       if (outp == NULL) {
-               au0828_isocdbg("outp is null\n");
-               return;
-       }
-
-       bytesperline = dev->vbi_width;
-
-       if (dma_q->pos + len > buf->vb.size)
-               len = buf->vb.size - dma_q->pos;
-
-       startread = p;
-       startwrite = outp + (dma_q->pos / 2);
-
-       /* Make sure the bottom field populates the second half of the frame */
-       if (buf->top_field == 0)
-               startwrite += bytesperline * dev->vbi_height;
-
-       for (i = 0; i < len; i += 2)
-               startwrite[j++] = startread[i+1];
-
-       dma_q->pos += len;
-}
-
-
-/*
- * video-buf generic routine to get the next available VBI buffer
- */
-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");
-               dev->isoc_ctl.vbi_buf = NULL;
-               *buf = NULL;
-               return;
-       }
-
-       /* Get the next buffer */
-       *buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
-       /* Cleans up buffer - Useful for testing for frame/URB loss */
-       outp = videobuf_to_vmalloc(&(*buf)->vb);
-       memset(outp, 0x00, (*buf)->vb.size);
-
-       dev->isoc_ctl.vbi_buf = *buf;
-
-       return;
-}
-
-/*
- * Controls the isoc copy of each urb packet
- */
-static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
-{
-       struct au0828_buffer    *buf;
-       struct au0828_buffer    *vbi_buf;
-       struct au0828_dmaqueue  *dma_q = urb->context;
-       struct au0828_dmaqueue  *vbi_dma_q = &dev->vbiq;
-       unsigned char *outp = NULL;
-       unsigned char *vbioutp = NULL;
-       int i, len = 0, rc = 1;
-       unsigned char *p;
-       unsigned char fbyte;
-       unsigned int vbi_field_size;
-       unsigned int remain, lencopy;
-
-       if (!dev)
-               return 0;
-
-       if ((dev->dev_state & DEV_DISCONNECTED) ||
-           (dev->dev_state & DEV_MISCONFIGURED))
-               return 0;
-
-       if (urb->status < 0) {
-               print_err_status(dev, -1, urb->status);
-               if (urb->status == -ENOENT)
-                       return 0;
-       }
-
-       buf = dev->isoc_ctl.buf;
-       if (buf != NULL)
-               outp = videobuf_to_vmalloc(&buf->vb);
-
-       vbi_buf = dev->isoc_ctl.vbi_buf;
-       if (vbi_buf != NULL)
-               vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               int status = urb->iso_frame_desc[i].status;
-
-               if (status < 0) {
-                       print_err_status(dev, i, status);
-                       if (urb->iso_frame_desc[i].status != -EPROTO)
-                               continue;
-               }
-
-               if (urb->iso_frame_desc[i].actual_length <= 0)
-                       continue;
-
-               if (urb->iso_frame_desc[i].actual_length >
-                                               dev->max_pkt_size) {
-                       au0828_isocdbg("packet bigger than packet size");
-                       continue;
-               }
-
-               p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-               fbyte = p[0];
-               len = urb->iso_frame_desc[i].actual_length - 4;
-               p += 4;
-
-               if (fbyte & 0x80) {
-                       len -= 4;
-                       p += 4;
-                       au0828_isocdbg("Video frame %s\n",
-                                      (fbyte & 0x40) ? "odd" : "even");
-                       if (fbyte & 0x40) {
-                               /* VBI */
-                               if (vbi_buf != NULL)
-                                       vbi_buffer_filled(dev,
-                                                         vbi_dma_q,
-                                                         vbi_buf);
-                               vbi_get_next_buf(vbi_dma_q, &vbi_buf);
-                               if (vbi_buf == NULL)
-                                       vbioutp = NULL;
-                               else
-                                       vbioutp = videobuf_to_vmalloc(
-                                               &vbi_buf->vb);
-
-                               /* Video */
-                               if (buf != NULL)
-                                       buffer_filled(dev, dma_q, buf);
-                               get_next_buf(dma_q, &buf);
-                               if (buf == NULL)
-                                       outp = NULL;
-                               else
-                                       outp = videobuf_to_vmalloc(&buf->vb);
-
-                               /* As long as isoc traffic is arriving, keep
-                                  resetting the timer */
-                               if (dev->vid_timeout_running)
-                                       mod_timer(&dev->vid_timeout,
-                                                 jiffies + (HZ / 10));
-                               if (dev->vbi_timeout_running)
-                                       mod_timer(&dev->vbi_timeout,
-                                                 jiffies + (HZ / 10));
-                       }
-
-                       if (buf != NULL) {
-                               if (fbyte & 0x40)
-                                       buf->top_field = 1;
-                               else
-                                       buf->top_field = 0;
-                       }
-
-                       if (vbi_buf != NULL) {
-                               if (fbyte & 0x40)
-                                       vbi_buf->top_field = 1;
-                               else
-                                       vbi_buf->top_field = 0;
-                       }
-
-                       dev->vbi_read = 0;
-                       vbi_dma_q->pos = 0;
-                       dma_q->pos = 0;
-               }
-
-               vbi_field_size = dev->vbi_width * dev->vbi_height * 2;
-               if (dev->vbi_read < vbi_field_size) {
-                       remain  = vbi_field_size - dev->vbi_read;
-                       if (len < remain)
-                               lencopy = len;
-                       else
-                               lencopy = remain;
-
-                       if (vbi_buf != NULL)
-                               au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
-                                               vbioutp, len);
-
-                       len -= lencopy;
-                       p += lencopy;
-                       dev->vbi_read += lencopy;
-               }
-
-               if (dev->vbi_read >= vbi_field_size && buf != NULL)
-                       au0828_copy_video(dev, dma_q, buf, p, outp, len);
-       }
-       return rc;
-}
-
-static int
-buffer_setup(struct videobuf_queue *vq, unsigned int *count,
-            unsigned int *size)
-{
-       struct au0828_fh *fh = vq->priv_data;
-       *size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
-
-       if (0 == *count)
-               *count = AU0828_DEF_BUF;
-
-       if (*count < AU0828_MIN_BUF)
-               *count = AU0828_MIN_BUF;
-       return 0;
-}
-
-/* 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;
-}
-
-static int
-buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
-                                               enum v4l2_field field)
-{
-       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;
-
-       buf->vb.size = (fh->dev->width * fh->dev->height * 16 + 7) >> 3;
-
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
-               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) {
-                       printk(KERN_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) {
-                       printk(KERN_INFO "au0828_init_isoc failed\n");
-                       goto fail;
-               }
-       }
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
-fail:
-       free_buffer(vq, buf);
-       return rc;
-}
-
-static void
-buffer_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  *vidq    = &dev->vidq;
-
-       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);
-
-       free_buffer(vq, buf);
-}
-
-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 */
-       au0828_writereg(dev, AU0828_AUDIOCTRL_50C, 0x01);
-       return 0;
-}
-
-/*
- * Auvitek au0828 analog stream enable
- * Please set interface0 to AS5 before enable the stream
- */
-int au0828_analog_stream_enable(struct au0828_dev *d)
-{
-       dprintk(1, "au0828_analog_stream_enable called\n");
-       au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
-       au0828_writereg(d, 0x106, 0x00);
-       /* set x position */
-       au0828_writereg(d, 0x110, 0x00);
-       au0828_writereg(d, 0x111, 0x00);
-       au0828_writereg(d, 0x114, 0xa0);
-       au0828_writereg(d, 0x115, 0x05);
-       /* set y position */
-       au0828_writereg(d, 0x112, 0x00);
-       au0828_writereg(d, 0x113, 0x00);
-       au0828_writereg(d, 0x116, 0xf2);
-       au0828_writereg(d, 0x117, 0x00);
-       au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
-
-       return 0;
-}
-
-int au0828_analog_stream_disable(struct au0828_dev *d)
-{
-       dprintk(1, "au0828_analog_stream_disable called\n");
-       au0828_writereg(d, AU0828_SENSORCTRL_100, 0x0);
-       return 0;
-}
-
-void au0828_analog_stream_reset(struct au0828_dev *dev)
-{
-       dprintk(1, "au0828_analog_stream_reset called\n");
-       au0828_writereg(dev, AU0828_SENSORCTRL_100, 0x0);
-       mdelay(30);
-       au0828_writereg(dev, AU0828_SENSORCTRL_100, 0xb3);
-}
-
-/*
- * Some operations needs to stop current streaming
- */
-static int au0828_stream_interrupt(struct au0828_dev *dev)
-{
-       int ret = 0;
-
-       dev->stream_state = STREAM_INTERRUPT;
-       if (dev->dev_state == DEV_DISCONNECTED)
-               return -ENODEV;
-       else if (ret) {
-               dev->dev_state = DEV_MISCONFIGURED;
-               dprintk(1, "%s device is misconfigured!\n", __func__);
-               return ret;
-       }
-       return 0;
-}
-
-/*
- * au0828_release_resources
- * unregister v4l2 devices
- */
-void au0828_analog_unregister(struct au0828_dev *dev)
-{
-       dprintk(1, "au0828_release_resources 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);
-}
-
-
-/* Usage lock check functions */
-static int res_get(struct au0828_fh *fh, unsigned int bit)
-{
-       struct au0828_dev    *dev = fh->dev;
-
-       if (fh->resources & bit)
-               /* have it already allocated */
-               return 1;
-
-       /* is it free? */
-       if (dev->resources & bit) {
-               /* no, someone else uses it */
-               return 0;
-       }
-       /* it's free, grab it */
-       fh->resources  |= bit;
-       dev->resources |= bit;
-       dprintk(1, "res: get %d\n", bit);
-
-       return 1;
-}
-
-static int res_check(struct au0828_fh *fh, unsigned int bit)
-{
-       return fh->resources & bit;
-}
-
-static int res_locked(struct au0828_dev *dev, unsigned int bit)
-{
-       return dev->resources & bit;
-}
-
-static void res_free(struct au0828_fh *fh, unsigned int bits)
-{
-       struct au0828_dev    *dev = fh->dev;
-
-       BUG_ON((fh->resources & bits) != bits);
-
-       fh->resources  &= ~bits;
-       dev->resources &= ~bits;
-       dprintk(1, "res: put %d\n", bits);
-}
-
-static int get_ressource(struct au0828_fh *fh)
-{
-       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;
-       }
-}
-
-/* This function ensures that video frames continue to be delivered even if
-   the ITU-656 input isn't receiving any data (thereby preventing applications
-   such as tvtime from hanging) */
-void au0828_vid_buffer_timeout(unsigned long data)
-{
-       struct au0828_dev *dev = (struct au0828_dev *) data;
-       struct au0828_dmaqueue *dma_q = &dev->vidq;
-       struct au0828_buffer *buf;
-       unsigned char *vid_data;
-       unsigned long flags = 0;
-
-       spin_lock_irqsave(&dev->slock, flags);
-
-       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 */
-               buffer_filled(dev, dma_q, buf);
-       }
-       get_next_buf(dma_q, &buf);
-
-       if (dev->vid_timeout_running == 1)
-               mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
-
-       spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-void au0828_vbi_buffer_timeout(unsigned long data)
-{
-       struct au0828_dev *dev = (struct au0828_dev *) data;
-       struct au0828_dmaqueue *dma_q = &dev->vbiq;
-       struct au0828_buffer *buf;
-       unsigned char *vbi_data;
-       unsigned long flags = 0;
-
-       spin_lock_irqsave(&dev->slock, flags);
-
-       buf = dev->isoc_ctl.vbi_buf;
-       if (buf != NULL) {
-               vbi_data = videobuf_to_vmalloc(&buf->vb);
-               memset(vbi_data, 0x00, buf->vb.size);
-               vbi_buffer_filled(dev, dma_q, buf);
-       }
-       vbi_get_next_buf(dma_q, &buf);
-
-       if (dev->vbi_timeout_running == 1)
-               mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
-       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;
-       }
-
-       fh->type = type;
-       fh->dev = dev;
-       filp->private_data = fh;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
-               /* set au0828 interface0 to AS5 here again */
-               ret = usb_set_interface(dev->usbdev, 0, 5);
-               if (ret < 0) {
-                       printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
-                       return -EBUSY;
-               }
-               dev->width = NTSC_STD_W;
-               dev->height = NTSC_STD_H;
-               dev->frame_size = dev->width * dev->height * 2;
-               dev->field_size = dev->width * dev->height;
-               dev->bytesperline = dev->width * 2;
-
-               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++;
-
-       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 */
-       dev->vbi_width = 720;
-       dev->vbi_height = 1;
-       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);
-       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;
-
-       if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
-               /* 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)) {
-               /* 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) {
-               if (dev->dev_state & DEV_DISCONNECTED) {
-                       au0828_analog_unregister(dev);
-                       kfree(dev);
-                       return 0;
-               }
-
-               au0828_analog_stream_disable(dev);
-
-               au0828_uninit_isoc(dev);
-
-               /* Save some power by putting tuner to sleep */
-               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
-
-               /* When close the device, set the usb intf0 into alt0 to free
-                  USB bandwidth */
-               ret = usb_set_interface(dev->usbdev, 0, 0);
-               if (ret < 0)
-                       printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
-       }
-
-       videobuf_mmap_free(&fh->vb_vidq);
-       videobuf_mmap_free(&fh->vb_vbiq);
-       kfree(fh);
-       dev->users--;
-       wake_up_interruptible_nr(&dev->open, 1);
-       return 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 (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;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               if (!res_get(fh, AU0828_RESOURCE_VIDEO))
-                       return POLLERR;
-               return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
-       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-               if (!res_get(fh, AU0828_RESOURCE_VBI))
-                       return POLLERR;
-               return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
-       } else {
-               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)
-{
-       int ret;
-       int width = format->fmt.pix.width;
-       int height = format->fmt.pix.height;
-
-       if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       /* If they are demanding a format other than the one we support,
-          bail out (tvtime asks for UYVY and then retries with YUYV) */
-       if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY)
-               return -EINVAL;
-
-       /* format->fmt.pix.width only support 720 and height 480 */
-       if (width != 720)
-               width = 720;
-       if (height != 480)
-               height = 480;
-
-       format->fmt.pix.width = width;
-       format->fmt.pix.height = height;
-       format->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
-       format->fmt.pix.bytesperline = width * 2;
-       format->fmt.pix.sizeimage = width * height * 2;
-       format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       format->fmt.pix.field = V4L2_FIELD_INTERLACED;
-
-       if (cmd == VIDIOC_TRY_FMT)
-               return 0;
-
-       /* maybe set new image format, driver current only support 720*480 */
-       dev->width = width;
-       dev->height = height;
-       dev->frame_size = width * height * 2;
-       dev->field_size = width * height;
-       dev->bytesperline = width * 2;
-
-       if (dev->stream_state == STREAM_ON) {
-               dprintk(1, "VIDIOC_SET_FMT: interrupting stream!\n");
-               ret = au0828_stream_interrupt(dev);
-               if (ret != 0) {
-                       dprintk(1, "error interrupting video stream!\n");
-                       return ret;
-               }
-       }
-
-       /* set au0828 interface0 to AS5 here again */
-       ret = usb_set_interface(dev->usbdev, 0, 5);
-       if (ret < 0) {
-               printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
-               return -EBUSY;
-       }
-
-       au0828_analog_stream_enable(dev);
-
-       return 0;
-}
-
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-                           struct v4l2_queryctrl *qc)
-{
-       struct au0828_fh *fh = priv;
-       struct au0828_dev *dev = fh->dev;
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
-       if (qc->type)
-               return 0;
-       else
-               return -EINVAL;
-}
-
-static int vidioc_querycap(struct file *file, void  *priv,
-                          struct v4l2_capability *cap)
-{
-       struct au0828_fh *fh  = priv;
-       struct au0828_dev *dev = fh->dev;
-
-       strlcpy(cap->driver, "au0828", sizeof(cap->driver));
-       strlcpy(cap->card, dev->board.name, sizeof(cap->card));
-       strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
-
-       /*set the device capabilities */
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
-               V4L2_CAP_VBI_CAPTURE |
-               V4L2_CAP_AUDIO |
-               V4L2_CAP_READWRITE |
-               V4L2_CAP_STREAMING |
-               V4L2_CAP_TUNER;
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       if (f->index)
-               return -EINVAL;
-
-       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       strcpy(f->description, "Packed YUV2");
-
-       f->flags = 0;
-       f->pixelformat = V4L2_PIX_FMT_UYVY;
-
-       return 0;
-}
-
-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;
-
-       f->fmt.pix.width = dev->width;
-       f->fmt.pix.height = dev->height;
-       f->fmt.pix.pixelformat = V4L2_PIX_FMT_UYVY;
-       f->fmt.pix.bytesperline = dev->bytesperline;
-       f->fmt.pix.sizeimage = dev->frame_size;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; /* NTSC/PAL */
-       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       return 0;
-}
-
-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;
-
-       return au0828_set_format(dev, VIDIOC_TRY_FMT, f);
-}
-
-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;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (videobuf_queue_is_busy(&fh->vb_vidq)) {
-               printk(KERN_INFO "%s queue busy\n", __func__);
-               rc = -EBUSY;
-               goto out;
-       }
-
-       rc = au0828_set_format(dev, VIDIOC_S_FMT, f);
-out:
-       return rc;
-}
-
-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;
-
-       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
-               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1);
-
-       /* FIXME: when we support something other than NTSC, we are going to
-          have to make the au0828 bridge adjust the size of its capture
-          buffer, which is currently hardcoded at 720x480 */
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);
-       dev->std_set_in_tuner_core = 1;
-
-       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
-               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0);
-
-       return 0;
-}
-
-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;
-       unsigned int tmp;
-
-       static const char *inames[] = {
-               [AU0828_VMUX_UNDEFINED] = "Undefined",
-               [AU0828_VMUX_COMPOSITE] = "Composite",
-               [AU0828_VMUX_SVIDEO] = "S-Video",
-               [AU0828_VMUX_CABLE] = "Cable TV",
-               [AU0828_VMUX_TELEVISION] = "Television",
-               [AU0828_VMUX_DVB] = "DVB",
-               [AU0828_VMUX_DEBUG] = "tv debug"
-       };
-
-       tmp = input->index;
-
-       if (tmp >= AU0828_MAX_INPUT)
-               return -EINVAL;
-       if (AUVI_INPUT(tmp).type == 0)
-               return -EINVAL;
-
-       input->index = tmp;
-       strcpy(input->name, inames[AUVI_INPUT(tmp).type]);
-       if ((AUVI_INPUT(tmp).type == AU0828_VMUX_TELEVISION) ||
-           (AUVI_INPUT(tmp).type == AU0828_VMUX_CABLE))
-               input->type |= V4L2_INPUT_TYPE_TUNER;
-       else
-               input->type |= V4L2_INPUT_TYPE_CAMERA;
-
-       input->std = dev->vdev->tvnorms;
-
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       struct au0828_fh *fh = priv;
-       struct au0828_dev *dev = fh->dev;
-       *i = dev->ctrl_input;
-       return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
-{
-       struct au0828_fh *fh = priv;
-       struct au0828_dev *dev = fh->dev;
-       int i;
-
-       dprintk(1, "VIDIOC_S_INPUT in function %s, input=%d\n", __func__,
-               index);
-       if (index >= AU0828_MAX_INPUT)
-               return -EINVAL;
-       if (AUVI_INPUT(index).type == 0)
-               return -EINVAL;
-       dev->ctrl_input = index;
-
-       switch (AUVI_INPUT(index).type) {
-       case AU0828_VMUX_SVIDEO:
-               dev->input_type = AU0828_VMUX_SVIDEO;
-               break;
-       case AU0828_VMUX_COMPOSITE:
-               dev->input_type = AU0828_VMUX_COMPOSITE;
-               break;
-       case AU0828_VMUX_TELEVISION:
-               dev->input_type = AU0828_VMUX_TELEVISION;
-               break;
-       default:
-               dprintk(1, "VIDIOC_S_INPUT unknown input type set [%d]\n",
-                       AUVI_INPUT(index).type);
-               break;
-       }
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
-                       AUVI_INPUT(index).vmux, 0, 0);
-
-       for (i = 0; i < AU0828_MAX_INPUT; i++) {
-               int enable = 0;
-               if (AUVI_INPUT(i).audio_setup == NULL)
-                       continue;
-
-               if (i == index)
-                       enable = 1;
-               else
-                       enable = 0;
-               if (enable) {
-                       (AUVI_INPUT(i).audio_setup)(dev, enable);
-               } else {
-                       /* Make sure we leave it turned on if some
-                          other input is routed to this callback */
-                       if ((AUVI_INPUT(i).audio_setup) !=
-                           ((AUVI_INPUT(index).audio_setup))) {
-                               (AUVI_INPUT(i).audio_setup)(dev, enable);
-                       }
-               }
-       }
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
-                       AUVI_INPUT(index).amux, 0, 0);
-       return 0;
-}
-
-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;
-       unsigned int index = a->index;
-
-       if (a->index > 1)
-               return -EINVAL;
-
-       index = dev->ctrl_ainput;
-       if (index == 0)
-               strcpy(a->name, "Television");
-       else
-               strcpy(a->name, "Line in");
-
-       a->capability = V4L2_AUDCAP_STEREO;
-       a->index = index;
-       return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-       struct au0828_fh *fh = priv;
-       struct au0828_dev *dev = fh->dev;
-       if (a->index != dev->ctrl_ainput)
-               return -EINVAL;
-       return 0;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                        struct v4l2_control *ctrl)
-{
-       struct au0828_fh *fh = priv;
-       struct au0828_dev *dev = fh->dev;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
-       return 0;
-
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctrl)
-{
-       struct au0828_fh *fh = priv;
-       struct au0828_dev *dev = fh->dev;
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
-       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;
-
-       if (t->index != 0)
-               return -EINVAL;
-
-       strcpy(t->name, "Auvitek tuner");
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
-       return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct au0828_fh *fh = priv;
-       struct au0828_dev *dev = fh->dev;
-
-       if (t->index != 0)
-               return -EINVAL;
-
-       t->type = V4L2_TUNER_ANALOG_TV;
-
-       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
-               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1);
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
-
-       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
-               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0);
-
-       dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
-               t->afc);
-
-       return 0;
-
-}
-
-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;
-
-       freq->type = V4L2_TUNER_ANALOG_TV;
-       freq->frequency = dev->ctrl_freq;
-       return 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *freq)
-{
-       struct au0828_fh *fh = priv;
-       struct au0828_dev *dev = fh->dev;
-
-       if (freq->tuner != 0)
-               return -EINVAL;
-       if (freq->type != V4L2_TUNER_ANALOG_TV)
-               return -EINVAL;
-
-       dev->ctrl_freq = freq->frequency;
-
-       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
-               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1);
-
-       if (dev->std_set_in_tuner_core == 0) {
-         /* If we've never sent the standard in tuner core, do so now.  We
-            don't do this at device probe because we don't want to incur
-            the cost of a firmware load */
-         v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std,
-                              dev->vdev->tvnorms);
-         dev->std_set_in_tuner_core = 1;
-       }
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
-
-       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
-               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0);
-
-       au0828_analog_stream_reset(dev);
-
-       return 0;
-}
-
-
-/* RAW VBI ioctls */
-
-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;
-
-       format->fmt.vbi.samples_per_line = dev->vbi_width;
-       format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
-       format->fmt.vbi.offset = 0;
-       format->fmt.vbi.flags = 0;
-       format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
-
-       format->fmt.vbi.count[0] = dev->vbi_height;
-       format->fmt.vbi.count[1] = dev->vbi_height;
-       format->fmt.vbi.start[0] = 21;
-       format->fmt.vbi.start[1] = 284;
-
-       return 0;
-}
-
-static int vidioc_g_chip_ident(struct file *file, void *priv,
-              struct v4l2_dbg_chip_ident *chip)
-{
-       struct au0828_fh *fh = priv;
-       struct au0828_dev *dev = fh->dev;
-       chip->ident = V4L2_IDENT_NONE;
-       chip->revision = 0;
-
-       if (v4l2_chip_match_host(&chip->match)) {
-               chip->ident = V4L2_IDENT_AU0828;
-               return 0;
-       }
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
-       if (chip->ident == V4L2_IDENT_NONE)
-               return -EINVAL;
-
-       return 0;
-}
-
-static int vidioc_cropcap(struct file *file, void *priv,
-                         struct v4l2_cropcap *cc)
-{
-       struct au0828_fh *fh = priv;
-       struct au0828_dev *dev = fh->dev;
-
-       if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       cc->bounds.left = 0;
-       cc->bounds.top = 0;
-       cc->bounds.width = dev->width;
-       cc->bounds.height = dev->height;
-
-       cc->defrect = cc->bounds;
-
-       cc->pixelaspect.numerator = 54;
-       cc->pixelaspect.denominator = 59;
-
-       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;
-
-       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);
-
-               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;
-
-       switch (reg->match.type) {
-       case V4L2_CHIP_MATCH_I2C_DRIVER:
-               v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
-               return 0;
-       default:
-               if (!v4l2_chip_match_host(&reg->match))
-                       return -EINVAL;
-       }
-
-       reg->val = au0828_read(dev, reg->reg);
-       return 0;
-}
-
-static int vidioc_s_register(struct file *file, void *priv,
-                            struct v4l2_dbg_register *reg)
-{
-       struct au0828_fh *fh = priv;
-       struct au0828_dev *dev = fh->dev;
-
-       switch (reg->match.type) {
-       case V4L2_CHIP_MATCH_I2C_DRIVER:
-               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
-               return 0;
-       default:
-               if (!v4l2_chip_match_host(&reg->match))
-                       return -EINVAL;
-       }
-       return au0828_writereg(dev, reg->reg, reg->val);
-}
-#endif
-
-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;
-}
-
-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,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops video_ioctl_ops = {
-       .vidioc_querycap            = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap    = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap       = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap     = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,
-       .vidioc_g_fmt_vbi_cap       = vidioc_g_fmt_vbi_cap,
-       .vidioc_s_fmt_vbi_cap       = vidioc_g_fmt_vbi_cap,
-       .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_s_std               = vidioc_s_std,
-       .vidioc_enum_input          = vidioc_enum_input,
-       .vidioc_g_input             = vidioc_g_input,
-       .vidioc_s_input             = vidioc_s_input,
-       .vidioc_queryctrl           = vidioc_queryctrl,
-       .vidioc_g_ctrl              = vidioc_g_ctrl,
-       .vidioc_s_ctrl              = vidioc_s_ctrl,
-       .vidioc_streamon            = vidioc_streamon,
-       .vidioc_streamoff           = vidioc_streamoff,
-       .vidioc_g_tuner             = vidioc_g_tuner,
-       .vidioc_s_tuner             = vidioc_s_tuner,
-       .vidioc_g_frequency         = vidioc_g_frequency,
-       .vidioc_s_frequency         = vidioc_s_frequency,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register          = vidioc_g_register,
-       .vidioc_s_register          = vidioc_s_register,
-#endif
-       .vidioc_g_chip_ident        = vidioc_g_chip_ident,
-};
-
-static const struct video_device au0828_video_template = {
-       .fops                       = &au0828_v4l_fops,
-       .release                    = video_device_release,
-       .ioctl_ops                  = &video_ioctl_ops,
-       .tvnorms                    = V4L2_STD_NTSC_M,
-       .current_norm               = V4L2_STD_NTSC_M,
-};
-
-/**************************************************************************/
-
-int au0828_analog_register(struct au0828_dev *dev,
-                          struct usb_interface *interface)
-{
-       int retval = -ENOMEM;
-       struct usb_host_interface *iface_desc;
-       struct usb_endpoint_descriptor *endpoint;
-       int i, ret;
-
-       dprintk(1, "au0828_analog_register called!\n");
-
-       /* set au0828 usb interface0 to as5 */
-       retval = usb_set_interface(dev->usbdev,
-                       interface->cur_altsetting->desc.bInterfaceNumber, 5);
-       if (retval != 0) {
-               printk(KERN_INFO "Failure setting usb interface0 to as5\n");
-               return retval;
-       }
-
-       /* Figure out which endpoint has the isoc interface */
-       iface_desc = interface->cur_altsetting;
-       for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
-               endpoint = &iface_desc->endpoint[i].desc;
-               if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-                    == USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                    == USB_ENDPOINT_XFER_ISOC)) {
-
-                       /* we find our isoc in endpoint */
-                       u16 tmp = le16_to_cpu(endpoint->wMaxPacketSize);
-                       dev->max_pkt_size = (tmp & 0x07ff) *
-                               (((tmp & 0x1800) >> 11) + 1);
-                       dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
-               }
-       }
-       if (!(dev->isoc_in_endpointaddr)) {
-               printk(KERN_INFO "Could not locate isoc endpoint\n");
-               kfree(dev);
-               return -ENODEV;
-       }
-
-       init_waitqueue_head(&dev->open);
-       spin_lock_init(&dev->slock);
-
-       /* 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);
-
-       dev->width = NTSC_STD_W;
-       dev->height = NTSC_STD_H;
-       dev->field_size = dev->width * dev->height;
-       dev->frame_size = dev->field_size << 1;
-       dev->bytesperline = dev->width << 1;
-       dev->ctrl_ainput = 0;
-
-       /* allocate and fill v4l2 video struct */
-       dev->vdev = video_device_alloc();
-       if (NULL == dev->vdev) {
-               dprintk(1, "Can't allocate video_device.\n");
-               return -ENOMEM;
-       }
-
-       /* allocate the VBI struct */
-       dev->vbi_dev = video_device_alloc();
-       if (NULL == dev->vbi_dev) {
-               dprintk(1, "Can't allocate vbi_device.\n");
-               ret = -ENOMEM;
-               goto err_vdev;
-       }
-
-       /* Fill the video capture device struct */
-       *dev->vdev = au0828_video_template;
-       dev->vdev->parent = &dev->usbdev->dev;
-       dev->vdev->lock = &dev->lock;
-       strcpy(dev->vdev->name, "au0828a video");
-
-       /* Setup the VBI device */
-       *dev->vbi_dev = au0828_video_template;
-       dev->vbi_dev->parent = &dev->usbdev->dev;
-       dev->vbi_dev->lock = &dev->lock;
-       strcpy(dev->vbi_dev->name, "au0828a vbi");
-
-       /* Register the v4l2 device */
-       video_set_drvdata(dev->vdev, dev);
-       retval = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
-       if (retval != 0) {
-               dprintk(1, "unable to register video device (error = %d).\n",
-                       retval);
-               ret = -ENODEV;
-               goto err_vbi_dev;
-       }
-
-       /* Register the vbi device */
-       video_set_drvdata(dev->vbi_dev, dev);
-       retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
-       if (retval != 0) {
-               dprintk(1, "unable to register vbi device (error = %d).\n",
-                       retval);
-               ret = -ENODEV;
-               goto err_vbi_dev;
-       }
-
-       dprintk(1, "%s completed!\n", __func__);
-
-       return 0;
-
-err_vbi_dev:
-       video_device_release(dev->vbi_dev);
-err_vdev:
-       video_device_release(dev->vdev);
-       return ret;
-}
-
diff --git a/drivers/media/video/au0828/au0828.h b/drivers/media/video/au0828/au0828.h
deleted file mode 100644 (file)
index 66a56ef..0000000
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- *  Driver for the Auvitek AU0828 USB bridge
- *
- *  Copyright (c) 2008 Steven Toth <stoth@linuxtv.org>
- *
- *  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/usb.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <media/tveeprom.h>
-
-/* Analog */
-#include <linux/videodev2.h>
-#include <media/videobuf-vmalloc.h>
-#include <media/v4l2-device.h>
-
-/* DVB */
-#include "demux.h"
-#include "dmxdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-#include "dvbdev.h"
-
-#include "au0828-reg.h"
-#include "au0828-cards.h"
-
-#define DRIVER_NAME "au0828"
-#define URB_COUNT   16
-#define URB_BUFSIZE (0xe522)
-
-/* Analog constants */
-#define NTSC_STD_W      720
-#define NTSC_STD_H      480
-
-#define AU0828_INTERLACED_DEFAULT       1
-#define V4L2_CID_PRIVATE_SHARPNESS  (V4L2_CID_PRIVATE_BASE + 0)
-
-/* Defination for AU0828 USB transfer */
-#define AU0828_MAX_ISO_BUFS    12  /* maybe resize this value in the future */
-#define AU0828_ISO_PACKETS_PER_URB      128
-
-#define AU0828_MIN_BUF 4
-#define AU0828_DEF_BUF 8
-
-#define AU0828_MAX_INPUT        4
-
-/* au0828 resource types (used for res_get/res_lock etc */
-#define AU0828_RESOURCE_VIDEO 0x01
-#define AU0828_RESOURCE_VBI   0x02
-
-enum au0828_itype {
-       AU0828_VMUX_UNDEFINED = 0,
-       AU0828_VMUX_COMPOSITE,
-       AU0828_VMUX_SVIDEO,
-       AU0828_VMUX_CABLE,
-       AU0828_VMUX_TELEVISION,
-       AU0828_VMUX_DVB,
-       AU0828_VMUX_DEBUG
-};
-
-struct au0828_input {
-       enum au0828_itype type;
-       unsigned int vmux;
-       unsigned int amux;
-       void (*audio_setup) (void *priv, int enable);
-};
-
-struct au0828_board {
-       char *name;
-       unsigned int tuner_type;
-       unsigned char tuner_addr;
-       unsigned char i2c_clk_divider;
-       struct au0828_input input[AU0828_MAX_INPUT];
-
-};
-
-struct au0828_dvb {
-       struct mutex lock;
-       struct dvb_adapter adapter;
-       struct dvb_frontend *frontend;
-       struct dvb_demux demux;
-       struct dmxdev dmxdev;
-       struct dmx_frontend fe_hw;
-       struct dmx_frontend fe_mem;
-       struct dvb_net net;
-       int feeding;
-};
-
-enum au0828_stream_state {
-       STREAM_OFF,
-       STREAM_INTERRUPT,
-       STREAM_ON
-};
-
-#define AUVI_INPUT(nr) (dev->board.input[nr])
-
-/* device state */
-enum au0828_dev_state {
-       DEV_INITIALIZED = 0x01,
-       DEV_DISCONNECTED = 0x02,
-       DEV_MISCONFIGURED = 0x04
-};
-
-struct au0828_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_usb_isoc_ctl {
-               /* max packet size of isoc transaction */
-       int                             max_pkt_size;
-
-               /* number of allocated urbs */
-       int                             num_bufs;
-
-               /* urb for isoc transfers */
-       struct urb                      **urb;
-
-               /* transfer buffers for isoc transfer */
-       char                            **transfer_buffer;
-
-               /* Last buffer command and region */
-       u8                              cmd;
-       int                             pos, size, pktsize;
-
-               /* Last field: ODD or EVEN? */
-       int                             field;
-
-               /* Stores incomplete commands */
-       u32                             tmp_buf;
-       int                             tmp_buf_len;
-
-               /* Stores already requested buffers */
-       struct au0828_buffer            *buf;
-       struct au0828_buffer            *vbi_buf;
-
-               /* Stores the number of received fields */
-       int                             nfields;
-
-               /* isoc urb callback */
-       int (*isoc_copy) (struct au0828_dev *dev, struct urb *urb);
-
-};
-
-/* buffer for one video frame */
-struct au0828_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
-
-       struct list_head frame;
-       int top_field;
-       int receiving;
-};
-
-struct au0828_dmaqueue {
-       struct list_head       active;
-       struct list_head       queued;
-
-       wait_queue_head_t          wq;
-
-       /* Counters to control buffer fill */
-       int                        pos;
-};
-
-struct au0828_dev {
-       struct mutex mutex;
-       struct usb_device       *usbdev;
-       int                     boardnr;
-       struct au0828_board     board;
-       u8                      ctrlmsg[64];
-
-       /* I2C */
-       struct i2c_adapter              i2c_adap;
-       struct i2c_algorithm            i2c_algo;
-       struct i2c_client               i2c_client;
-       u32                             i2c_rc;
-
-       /* Digital */
-       struct au0828_dvb               dvb;
-       struct work_struct              restart_streaming;
-
-       /* Analog */
-       struct v4l2_device v4l2_dev;
-       int users;
-       unsigned int resources; /* resources in use */
-       struct video_device *vdev;
-       struct video_device *vbi_dev;
-       struct timer_list vid_timeout;
-       int vid_timeout_running;
-       struct timer_list vbi_timeout;
-       int vbi_timeout_running;
-       int width;
-       int height;
-       int vbi_width;
-       int vbi_height;
-       u32 vbi_read;
-       u32 field_size;
-       u32 frame_size;
-       u32 bytesperline;
-       int type;
-       u8 ctrl_ainput;
-       __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;
-       unsigned int ctrl_input;
-       enum au0828_dev_state dev_state;
-       enum au0828_stream_state stream_state;
-       wait_queue_head_t open;
-
-       struct mutex lock;
-
-       /* Isoc control struct */
-       struct au0828_dmaqueue vidq;
-       struct au0828_dmaqueue vbiq;
-       struct au0828_usb_isoc_ctl isoc_ctl;
-       spinlock_t slock;
-
-       /* usb transfer */
-       int alt;                /* alternate */
-       int max_pkt_size;       /* max packet size of isoc transaction */
-       int num_alt;            /* Number of alternative settings */
-       unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
-       struct urb *urb[AU0828_MAX_ISO_BUFS];   /* urb for isoc transfers */
-       char *transfer_buffer[AU0828_MAX_ISO_BUFS];/* transfer buffers for isoc
-                                                  transfer */
-
-       /* USB / URB Related */
-       int             urb_streaming;
-       struct urb      *urbs[URB_COUNT];
-};
-
-/* ----------------------------------------------------------- */
-#define au0828_read(dev, reg) au0828_readreg(dev, reg)
-#define au0828_write(dev, reg, value) au0828_writereg(dev, reg, value)
-#define au0828_andor(dev, reg, mask, value)                            \
-        au0828_writereg(dev, reg,                                      \
-       (au0828_readreg(dev, reg) & ~(mask)) | ((value) & (mask)))
-
-#define au0828_set(dev, reg, bit) au0828_andor(dev, (reg), (bit), (bit))
-#define au0828_clear(dev, reg, bit) au0828_andor(dev, (reg), (bit), 0)
-
-/* ----------------------------------------------------------- */
-/* au0828-core.c */
-extern u32 au0828_read(struct au0828_dev *dev, u16 reg);
-extern u32 au0828_write(struct au0828_dev *dev, u16 reg, u32 val);
-extern int au0828_debug;
-
-/* ----------------------------------------------------------- */
-/* au0828-cards.c */
-extern struct au0828_board au0828_boards[];
-extern struct usb_device_id au0828_usb_id_table[];
-extern void au0828_gpio_setup(struct au0828_dev *dev);
-extern int au0828_tuner_callback(void *priv, int component,
-                                int command, int arg);
-extern void au0828_card_setup(struct au0828_dev *dev);
-
-/* ----------------------------------------------------------- */
-/* au0828-i2c.c */
-extern int au0828_i2c_register(struct au0828_dev *dev);
-extern int au0828_i2c_unregister(struct au0828_dev *dev);
-
-/* ----------------------------------------------------------- */
-/* au0828-video.c */
-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);
-
-/* ----------------------------------------------------------- */
-/* au0828-dvb.c */
-extern int au0828_dvb_register(struct au0828_dev *dev);
-extern void au0828_dvb_unregister(struct au0828_dev *dev);
-
-/* au0828-vbi.c */
-extern struct videobuf_queue_ops au0828_vbi_qops;
-
-#define dprintk(level, fmt, arg...)\
-       do { if (au0828_debug & level)\
-               printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\
-       } while (0)
diff --git a/drivers/media/video/cpia2/Kconfig b/drivers/media/video/cpia2/Kconfig
deleted file mode 100644 (file)
index 66e9283..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-config VIDEO_CPIA2
-       tristate "CPiA2 Video For Linux"
-       depends on VIDEO_DEV && USB && VIDEO_V4L2
-       ---help---
-         This is the video4linux driver for cameras based on Vision's CPiA2
-         (Colour Processor Interface ASIC), such as the Digital Blue QX5
-         Microscope. If you have one of these cameras, say Y here
-
-         This driver is also available as a module (cpia2).
diff --git a/drivers/media/video/cpia2/Makefile b/drivers/media/video/cpia2/Makefile
deleted file mode 100644 (file)
index 828cf1b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-cpia2-objs     := cpia2_v4l.o cpia2_usb.o cpia2_core.o
-
-obj-$(CONFIG_VIDEO_CPIA2) += cpia2.o
diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h
deleted file mode 100644 (file)
index cdef677..0000000
+++ /dev/null
@@ -1,487 +0,0 @@
-/****************************************************************************
- *
- *  Filename: cpia2.h
- *
- *  Copyright 2001, STMicrolectronics, Inc.
- *
- *  Contact:  steve.miller@st.com
- *
- *  Description:
- *     This is a USB driver for CPiA2 based video cameras.
- *
- *     This driver is modelled on the cpia usb driver by
- *     Jochen Scharrlach and Johannes Erdfeldt.
- *
- *  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.
- *
- ****************************************************************************/
-
-#ifndef __CPIA2_H__
-#define __CPIA2_H__
-
-#include <linux/videodev2.h>
-#include <linux/usb.h>
-#include <linux/poll.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-
-#include "cpia2_registers.h"
-
-/* define for verbose debug output */
-//#define _CPIA2_DEBUG_
-
-/***
- * Image defines
- ***/
-
-/*  Misc constants */
-#define ALLOW_CORRUPT 0                /* Causes collater to discard checksum */
-
-/* USB Transfer mode */
-#define XFER_ISOC 0
-#define XFER_BULK 1
-
-/* USB Alternates */
-#define USBIF_CMDONLY 0
-#define USBIF_BULK 1
-#define USBIF_ISO_1 2  /*  128 bytes/ms */
-#define USBIF_ISO_2 3  /*  384 bytes/ms */
-#define USBIF_ISO_3 4  /*  640 bytes/ms */
-#define USBIF_ISO_4 5  /*  768 bytes/ms */
-#define USBIF_ISO_5 6  /*  896 bytes/ms */
-#define USBIF_ISO_6 7  /* 1023 bytes/ms */
-
-/* Flicker Modes */
-#define NEVER_FLICKER   0
-#define FLICKER_60      60
-#define FLICKER_50      50
-
-/* Debug flags */
-#define DEBUG_NONE          0
-#define DEBUG_REG           0x00000001
-#define DEBUG_DUMP_PATCH    0x00000002
-#define DEBUG_DUMP_REGS     0x00000004
-
-/***
- * Video frame sizes
- ***/
-enum {
-       VIDEOSIZE_VGA = 0,      /* 640x480 */
-       VIDEOSIZE_CIF,          /* 352x288 */
-       VIDEOSIZE_QVGA,         /* 320x240 */
-       VIDEOSIZE_QCIF,         /* 176x144 */
-       VIDEOSIZE_288_216,
-       VIDEOSIZE_256_192,
-       VIDEOSIZE_224_168,
-       VIDEOSIZE_192_144,
-};
-
-#define STV_IMAGE_CIF_ROWS    288
-#define STV_IMAGE_CIF_COLS    352
-
-#define STV_IMAGE_QCIF_ROWS   144
-#define STV_IMAGE_QCIF_COLS   176
-
-#define STV_IMAGE_VGA_ROWS    480
-#define STV_IMAGE_VGA_COLS    640
-
-#define STV_IMAGE_QVGA_ROWS   240
-#define STV_IMAGE_QVGA_COLS   320
-
-#define JPEG_MARKER_COM (1<<6) /* Comment segment */
-
-/***
- * Enums
- ***/
-/* Sensor types available with cpia2 asics */
-enum sensors {
-       CPIA2_SENSOR_410,
-       CPIA2_SENSOR_500
-};
-
-/* Asic types available in the CPiA2 architecture */
-#define  CPIA2_ASIC_672 0x67
-
-/* Device types (stv672, stv676, etc) */
-#define  DEVICE_STV_672   0x0001
-#define  DEVICE_STV_676   0x0002
-
-enum frame_status {
-       FRAME_EMPTY,
-       FRAME_READING,          /* In the process of being grabbed into */
-       FRAME_READY,            /* Ready to be read */
-       FRAME_ERROR,
-};
-
-/***
- * Register access (for USB request byte)
- ***/
-enum {
-       CAMERAACCESS_SYSTEM = 0,
-       CAMERAACCESS_VC,
-       CAMERAACCESS_VP,
-       CAMERAACCESS_IDATA
-};
-
-#define CAMERAACCESS_TYPE_BLOCK    0x00
-#define CAMERAACCESS_TYPE_RANDOM   0x04
-#define CAMERAACCESS_TYPE_MASK     0x08
-#define CAMERAACCESS_TYPE_REPEAT   0x0C
-
-#define TRANSFER_READ 0
-#define TRANSFER_WRITE 1
-
-#define DEFAULT_ALT   USBIF_ISO_6
-#define DEFAULT_BRIGHTNESS 0x46
-#define DEFAULT_CONTRAST 0x93
-#define DEFAULT_SATURATION 0x7f
-
-/* Power state */
-#define HI_POWER_MODE CPIA2_SYSTEM_CONTROL_HIGH_POWER
-#define LO_POWER_MODE CPIA2_SYSTEM_CONTROL_LOW_POWER
-
-
-/********
- * Commands
- *******/
-enum {
-       CPIA2_CMD_NONE = 0,
-       CPIA2_CMD_GET_VERSION,
-       CPIA2_CMD_GET_PNP_ID,
-       CPIA2_CMD_GET_ASIC_TYPE,
-       CPIA2_CMD_GET_SENSOR,
-       CPIA2_CMD_GET_VP_DEVICE,
-       CPIA2_CMD_GET_VP_BRIGHTNESS,
-       CPIA2_CMD_SET_VP_BRIGHTNESS,
-       CPIA2_CMD_GET_CONTRAST,
-       CPIA2_CMD_SET_CONTRAST,
-       CPIA2_CMD_GET_VP_SATURATION,
-       CPIA2_CMD_SET_VP_SATURATION,
-       CPIA2_CMD_GET_VP_GPIO_DIRECTION,
-       CPIA2_CMD_SET_VP_GPIO_DIRECTION,
-       CPIA2_CMD_GET_VP_GPIO_DATA,
-       CPIA2_CMD_SET_VP_GPIO_DATA,
-       CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION,
-       CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION,
-       CPIA2_CMD_GET_VC_MP_GPIO_DATA,
-       CPIA2_CMD_SET_VC_MP_GPIO_DATA,
-       CPIA2_CMD_ENABLE_PACKET_CTRL,
-       CPIA2_CMD_GET_FLICKER_MODES,
-       CPIA2_CMD_SET_FLICKER_MODES,
-       CPIA2_CMD_RESET_FIFO,   /* clear fifo and enable stream block */
-       CPIA2_CMD_SET_HI_POWER,
-       CPIA2_CMD_SET_LOW_POWER,
-       CPIA2_CMD_CLEAR_V2W_ERR,
-       CPIA2_CMD_SET_USER_MODE,
-       CPIA2_CMD_GET_USER_MODE,
-       CPIA2_CMD_FRAMERATE_REQ,
-       CPIA2_CMD_SET_COMPRESSION_STATE,
-       CPIA2_CMD_GET_WAKEUP,
-       CPIA2_CMD_SET_WAKEUP,
-       CPIA2_CMD_GET_PW_CONTROL,
-       CPIA2_CMD_SET_PW_CONTROL,
-       CPIA2_CMD_GET_SYSTEM_CTRL,
-       CPIA2_CMD_SET_SYSTEM_CTRL,
-       CPIA2_CMD_GET_VP_SYSTEM_STATE,
-       CPIA2_CMD_GET_VP_SYSTEM_CTRL,
-       CPIA2_CMD_SET_VP_SYSTEM_CTRL,
-       CPIA2_CMD_GET_VP_EXP_MODES,
-       CPIA2_CMD_SET_VP_EXP_MODES,
-       CPIA2_CMD_GET_DEVICE_CONFIG,
-       CPIA2_CMD_SET_DEVICE_CONFIG,
-       CPIA2_CMD_SET_SERIAL_ADDR,
-       CPIA2_CMD_SET_SENSOR_CR1,
-       CPIA2_CMD_GET_VC_CONTROL,
-       CPIA2_CMD_SET_VC_CONTROL,
-       CPIA2_CMD_SET_TARGET_KB,
-       CPIA2_CMD_SET_DEF_JPEG_OPT,
-       CPIA2_CMD_REHASH_VP4,
-       CPIA2_CMD_GET_USER_EFFECTS,
-       CPIA2_CMD_SET_USER_EFFECTS
-};
-
-enum user_cmd {
-       COMMAND_NONE = 0x00000001,
-       COMMAND_SET_FPS = 0x00000002,
-       COMMAND_SET_COLOR_PARAMS = 0x00000004,
-       COMMAND_GET_COLOR_PARAMS = 0x00000008,
-       COMMAND_SET_FORMAT = 0x00000010,        /* size, etc */
-       COMMAND_SET_FLICKER = 0x00000020
-};
-
-/***
- * Some defines specific to the 676 chip
- ***/
-#define CAMACC_CIF      0x01
-#define CAMACC_VGA      0x02
-#define CAMACC_QCIF     0x04
-#define CAMACC_QVGA     0x08
-
-
-struct cpia2_register {
-       u8 index;
-       u8 value;
-};
-
-struct cpia2_reg_mask {
-       u8 index;
-       u8 and_mask;
-       u8 or_mask;
-       u8 fill;
-};
-
-struct cpia2_command {
-       u32 command;
-       u8 req_mode;            /* (Block or random) | registerBank */
-       u8 reg_count;
-       u8 direction;
-       u8 start;
-       union reg_types {
-               struct cpia2_register registers[32];
-               struct cpia2_reg_mask masks[16];
-               u8 block_data[64];
-               u8 *patch_data; /* points to function defined block */
-       } buffer;
-};
-
-struct camera_params {
-       struct {
-               u8 firmware_revision_hi; /* For system register set (bank 0) */
-               u8 firmware_revision_lo;
-               u8 asic_id;     /* Video Compressor set (bank 1) */
-               u8 asic_rev;
-               u8 vp_device_hi;        /* Video Processor set (bank 2) */
-               u8 vp_device_lo;
-               u8 sensor_flags;
-               u8 sensor_rev;
-       } version;
-
-       struct {
-               u32 device_type;     /* enumerated from vendor/product ids.
-                                     * Currently, either STV_672 or STV_676 */
-               u16 vendor;
-               u16 product;
-               u16 device_revision;
-       } pnp_id;
-
-       struct {
-               u8 brightness;  /* CPIA2_VP_EXPOSURE_TARGET */
-               u8 contrast;    /* Note: this is CPIA2_VP_YRANGE */
-               u8 saturation;  /*  CPIA2_VP_SATURATION */
-       } color_params;
-
-       struct {
-               u8 cam_register;
-               u8 flicker_mode_req;    /* 1 if flicker on, else never flicker */
-       } flicker_control;
-
-       struct {
-               u8 jpeg_options;
-               u8 creep_period;
-               u8 user_squeeze;
-               u8 inhibit_htables;
-       } compression;
-
-       struct {
-               u8 ohsize;      /* output image size */
-               u8 ovsize;
-               u8 hcrop;       /* cropping start_pos/4 */
-               u8 vcrop;
-               u8 hphase;      /* scaling registers */
-               u8 vphase;
-               u8 hispan;
-               u8 vispan;
-               u8 hicrop;
-               u8 vicrop;
-               u8 hifraction;
-               u8 vifraction;
-       } image_size;
-
-       struct {
-               int width;      /* actual window width */
-               int height;     /* actual window height */
-       } roi;
-
-       struct {
-               u8 video_mode;
-               u8 frame_rate;
-               u8 video_size;  /* Not a register, just a convenience for cropped sizes */
-               u8 gpio_direction;
-               u8 gpio_data;
-               u8 system_ctrl;
-               u8 system_state;
-               u8 lowlight_boost;      /* Bool: 0 = off, 1 = on */
-               u8 device_config;
-               u8 exposure_modes;
-               u8 user_effects;
-       } vp_params;
-
-       struct {
-               u8 pw_control;
-               u8 wakeup;
-               u8 vc_control;
-               u8 vc_mp_direction;
-               u8 vc_mp_data;
-               u8 quality;
-       } vc_params;
-
-       struct {
-               u8 power_mode;
-               u8 system_ctrl;
-               u8 stream_mode; /* This is the current alternate for usb drivers */
-               u8 allow_corrupt;
-       } camera_state;
-};
-
-#define NUM_SBUF    2
-
-struct cpia2_sbuf {
-       char *data;
-       struct urb *urb;
-};
-
-struct framebuf {
-       struct timeval timestamp;
-       unsigned long seq;
-       int num;
-       int length;
-       int max_length;
-       volatile enum frame_status status;
-       u8 *data;
-       struct framebuf *next;
-};
-
-struct camera_data {
-       /* locks */
-       struct v4l2_device v4l2_dev;
-       struct mutex v4l2_lock; /* serialize file operations */
-       struct v4l2_ctrl_handler hdl;
-       struct {
-               /* Lights control cluster */
-               struct v4l2_ctrl *top_light;
-               struct v4l2_ctrl *bottom_light;
-       };
-       struct v4l2_ctrl *usb_alt;
-
-       /* camera status */
-       int first_image_seen;
-       enum sensors sensor_type;
-       u8 flush;
-       struct v4l2_fh *stream_fh;
-       u8 mmapped;
-       int streaming;          /* 0 = no, 1 = yes */
-       int xfer_mode;          /* XFER_BULK or XFER_ISOC */
-       struct camera_params params;    /* camera settings */
-
-       /* v4l */
-       int video_size;                 /* VIDEO_SIZE_ */
-       struct video_device vdev;       /* v4l videodev */
-       u32 width;
-       u32 height;                     /* Its size */
-       __u32 pixelformat;       /* Format fourcc      */
-
-       /* USB */
-       struct usb_device *dev;
-       unsigned char iface;
-       unsigned int cur_alt;
-       unsigned int old_alt;
-       struct cpia2_sbuf sbuf[NUM_SBUF];       /* Double buffering */
-
-       wait_queue_head_t wq_stream;
-
-       /* Buffering */
-       u32 frame_size;
-       int num_frames;
-       unsigned long frame_count;
-       u8 *frame_buffer;       /* frame buffer data */
-       struct framebuf *buffers;
-       struct framebuf * volatile curbuff;
-       struct framebuf *workbuff;
-
-       /* MJPEG Extension */
-       int APPn;               /* Number of APP segment to be written, must be 0..15 */
-       int APP_len;            /* Length of data in JPEG APPn segment */
-       char APP_data[60];      /* Data in the JPEG APPn segment. */
-
-       int COM_len;            /* Length of data in JPEG COM segment */
-       char COM_data[60];      /* Data in JPEG COM segment */
-};
-
-/* v4l */
-int cpia2_register_camera(struct camera_data *cam);
-void cpia2_unregister_camera(struct camera_data *cam);
-void cpia2_camera_release(struct v4l2_device *v4l2_dev);
-
-/* core */
-int cpia2_reset_camera(struct camera_data *cam);
-int cpia2_set_low_power(struct camera_data *cam);
-void cpia2_dbg_dump_registers(struct camera_data *cam);
-int cpia2_match_video_size(int width, int height);
-void cpia2_set_camera_state(struct camera_data *cam);
-void cpia2_save_camera_state(struct camera_data *cam);
-void cpia2_set_color_params(struct camera_data *cam);
-void cpia2_set_brightness(struct camera_data *cam, unsigned char value);
-void cpia2_set_contrast(struct camera_data *cam, unsigned char value);
-void cpia2_set_saturation(struct camera_data *cam, unsigned char value);
-int cpia2_set_flicker_mode(struct camera_data *cam, int mode);
-void cpia2_set_format(struct camera_data *cam);
-int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd);
-int cpia2_do_command(struct camera_data *cam,
-                    unsigned int command,
-                    unsigned char direction, unsigned char param);
-struct camera_data *cpia2_init_camera_struct(struct usb_interface *intf);
-int cpia2_init_camera(struct camera_data *cam);
-int cpia2_allocate_buffers(struct camera_data *cam);
-void cpia2_free_buffers(struct camera_data *cam);
-long cpia2_read(struct camera_data *cam,
-               char __user *buf, unsigned long count, int noblock);
-unsigned int cpia2_poll(struct camera_data *cam,
-                       struct file *filp, poll_table *wait);
-int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma);
-void cpia2_set_property_flip(struct camera_data *cam, int prop_val);
-void cpia2_set_property_mirror(struct camera_data *cam, int prop_val);
-int cpia2_set_gpio(struct camera_data *cam, unsigned char setting);
-int cpia2_set_fps(struct camera_data *cam, int framerate);
-
-/* usb */
-int cpia2_usb_init(void);
-void cpia2_usb_cleanup(void);
-int cpia2_usb_transfer_cmd(struct camera_data *cam, void *registers,
-                          u8 request, u8 start, u8 count, u8 direction);
-int cpia2_usb_stream_start(struct camera_data *cam, unsigned int alternate);
-int cpia2_usb_stream_stop(struct camera_data *cam);
-int cpia2_usb_stream_pause(struct camera_data *cam);
-int cpia2_usb_stream_resume(struct camera_data *cam);
-int cpia2_usb_change_streaming_alternate(struct camera_data *cam,
-                                        unsigned int alt);
-
-
-/* ----------------------- debug functions ---------------------- */
-#ifdef _CPIA2_DEBUG_
-#define ALOG(lev, fmt, args...) printk(lev "%s:%d %s(): " fmt, __FILE__, __LINE__, __func__, ## args)
-#define LOG(fmt, args...) ALOG(KERN_INFO, fmt, ## args)
-#define ERR(fmt, args...) ALOG(KERN_ERR, fmt, ## args)
-#define DBG(fmt, args...) ALOG(KERN_DEBUG, fmt, ## args)
-#else
-#define ALOG(fmt,args...) printk(fmt,##args)
-#define LOG(fmt,args...) ALOG(KERN_INFO "cpia2: "fmt,##args)
-#define ERR(fmt,args...) ALOG(KERN_ERR "cpia2: "fmt,##args)
-#define DBG(fmn,args...) do {} while(0)
-#endif
-/* No function or lineno, for shorter lines */
-#define KINFO(fmt, args...) printk(KERN_INFO fmt,##args)
-
-#endif
diff --git a/drivers/media/video/cpia2/cpia2_core.c b/drivers/media/video/cpia2/cpia2_core.c
deleted file mode 100644 (file)
index 187012c..0000000
+++ /dev/null
@@ -1,2417 +0,0 @@
-/****************************************************************************
- *
- *  Filename: cpia2_core.c
- *
- *  Copyright 2001, STMicrolectronics, Inc.
- *      Contact:  steve.miller@st.com
- *
- *  Description:
- *     This is a USB driver for CPia2 based video cameras.
- *     The infrastructure of this driver is based on the cpia usb driver by
- *     Jochen Scharrlach and Johannes Erdfeldt.
- *
- *  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.
- *
- *  Stripped of 2.4 stuff ready for main kernel submit by
- *             Alan Cox <alan@lxorguk.ukuu.org.uk>
- *
- ****************************************************************************/
-
-#include "cpia2.h"
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/firmware.h>
-
-#define FIRMWARE "cpia2/stv0672_vp4.bin"
-MODULE_FIRMWARE(FIRMWARE);
-
-/* #define _CPIA2_DEBUG_ */
-
-#ifdef _CPIA2_DEBUG_
-
-static const char *block_name[] = {
-       "System",
-       "VC",
-       "VP",
-       "IDATA"
-};
-#endif
-
-static unsigned int debugs_on; /* default 0 - DEBUG_REG */
-
-
-/******************************************************************************
- *
- *  Forward Declarations
- *
- *****************************************************************************/
-static int apply_vp_patch(struct camera_data *cam);
-static int set_default_user_mode(struct camera_data *cam);
-static int set_vw_size(struct camera_data *cam, int size);
-static int configure_sensor(struct camera_data *cam,
-                           int reqwidth, int reqheight);
-static int config_sensor_410(struct camera_data *cam,
-                           int reqwidth, int reqheight);
-static int config_sensor_500(struct camera_data *cam,
-                           int reqwidth, int reqheight);
-static int set_all_properties(struct camera_data *cam);
-static void wake_system(struct camera_data *cam);
-static void set_lowlight_boost(struct camera_data *cam);
-static void reset_camera_struct(struct camera_data *cam);
-static int cpia2_set_high_power(struct camera_data *cam);
-
-/* Here we want the physical address of the memory.
- * This is used when initializing the contents of the
- * area and marking the pages as reserved.
- */
-static inline unsigned long kvirt_to_pa(unsigned long adr)
-{
-       unsigned long kva, ret;
-
-       kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-       kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-       ret = __pa(kva);
-       return ret;
-}
-
-static void *rvmalloc(unsigned long size)
-{
-       void *mem;
-       unsigned long adr;
-
-       /* Round it off to PAGE_SIZE */
-       size = PAGE_ALIGN(size);
-
-       mem = vmalloc_32(size);
-       if (!mem)
-               return NULL;
-
-       memset(mem, 0, size);   /* Clear the ram out, no junk to the user */
-       adr = (unsigned long) mem;
-
-       while ((long)size > 0) {
-               SetPageReserved(vmalloc_to_page((void *)adr));
-               adr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-       return mem;
-}
-
-static void rvfree(void *mem, unsigned long size)
-{
-       unsigned long adr;
-
-       if (!mem)
-               return;
-
-       size = PAGE_ALIGN(size);
-
-       adr = (unsigned long) mem;
-       while ((long)size > 0) {
-               ClearPageReserved(vmalloc_to_page((void *)adr));
-               adr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-       vfree(mem);
-}
-
-/******************************************************************************
- *
- *  cpia2_do_command
- *
- *  Send an arbitrary command to the camera.  For commands that read from
- *  the camera, copy the buffers into the proper param structures.
- *****************************************************************************/
-int cpia2_do_command(struct camera_data *cam,
-                    u32 command, u8 direction, u8 param)
-{
-       int retval = 0;
-       struct cpia2_command cmd;
-       unsigned int device = cam->params.pnp_id.device_type;
-
-       cmd.command = command;
-       cmd.reg_count = 2;      /* default */
-       cmd.direction = direction;
-
-       /***
-        * Set up the command.
-        ***/
-       switch (command) {
-       case CPIA2_CMD_GET_VERSION:
-               cmd.req_mode =
-                   CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
-               cmd.start = CPIA2_SYSTEM_DEVICE_HI;
-               break;
-       case CPIA2_CMD_GET_PNP_ID:
-               cmd.req_mode =
-                   CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
-               cmd.reg_count = 8;
-               cmd.start = CPIA2_SYSTEM_DESCRIP_VID_HI;
-               break;
-       case CPIA2_CMD_GET_ASIC_TYPE:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
-               cmd.start = CPIA2_VC_ASIC_ID;
-               break;
-       case CPIA2_CMD_GET_SENSOR:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.start = CPIA2_VP_SENSOR_FLAGS;
-               break;
-       case CPIA2_CMD_GET_VP_DEVICE:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.start = CPIA2_VP_DEVICEH;
-               break;
-       case CPIA2_CMD_SET_VP_BRIGHTNESS:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_VP_BRIGHTNESS:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               if (device == DEVICE_STV_672)
-                       cmd.start = CPIA2_VP4_EXPOSURE_TARGET;
-               else
-                       cmd.start = CPIA2_VP5_EXPOSURE_TARGET;
-               break;
-       case CPIA2_CMD_SET_CONTRAST:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_CONTRAST:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VP_YRANGE;
-               break;
-       case CPIA2_CMD_SET_VP_SATURATION:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_VP_SATURATION:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               if (device == DEVICE_STV_672)
-                       cmd.start = CPIA2_VP_SATURATION;
-               else
-                       cmd.start = CPIA2_VP5_MCUVSATURATION;
-               break;
-       case CPIA2_CMD_SET_VP_GPIO_DATA:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_VP_GPIO_DATA:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VP_GPIO_DATA;
-               break;
-       case CPIA2_CMD_SET_VP_GPIO_DIRECTION:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_VP_GPIO_DIRECTION:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VP_GPIO_DIRECTION;
-               break;
-       case CPIA2_CMD_SET_VC_MP_GPIO_DATA:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_VC_MP_GPIO_DATA:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VC_MP_DATA;
-               break;
-       case CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VC_MP_DIR;
-               break;
-       case CPIA2_CMD_ENABLE_PACKET_CTRL:
-               cmd.req_mode =
-                   CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
-               cmd.start = CPIA2_SYSTEM_INT_PACKET_CTRL;
-               cmd.reg_count = 1;
-               cmd.buffer.block_data[0] = param;
-               break;
-       case CPIA2_CMD_SET_FLICKER_MODES:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_FLICKER_MODES:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VP_FLICKER_MODES;
-               break;
-       case CPIA2_CMD_RESET_FIFO:      /* clear fifo and enable stream block */
-               cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC;
-               cmd.reg_count = 2;
-               cmd.start = 0;
-               cmd.buffer.registers[0].index = CPIA2_VC_ST_CTRL;
-               cmd.buffer.registers[0].value = CPIA2_VC_ST_CTRL_SRC_VC |
-                   CPIA2_VC_ST_CTRL_DST_USB | CPIA2_VC_ST_CTRL_EOF_DETECT;
-               cmd.buffer.registers[1].index = CPIA2_VC_ST_CTRL;
-               cmd.buffer.registers[1].value = CPIA2_VC_ST_CTRL_SRC_VC |
-                   CPIA2_VC_ST_CTRL_DST_USB |
-                   CPIA2_VC_ST_CTRL_EOF_DETECT |
-                   CPIA2_VC_ST_CTRL_FIFO_ENABLE;
-               break;
-       case CPIA2_CMD_SET_HI_POWER:
-               cmd.req_mode =
-                   CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_SYSTEM;
-               cmd.reg_count = 2;
-               cmd.buffer.registers[0].index =
-                   CPIA2_SYSTEM_SYSTEM_CONTROL;
-               cmd.buffer.registers[1].index =
-                   CPIA2_SYSTEM_SYSTEM_CONTROL;
-               cmd.buffer.registers[0].value = CPIA2_SYSTEM_CONTROL_CLEAR_ERR;
-               cmd.buffer.registers[1].value =
-                   CPIA2_SYSTEM_CONTROL_HIGH_POWER;
-               break;
-       case CPIA2_CMD_SET_LOW_POWER:
-               cmd.req_mode =
-                   CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_SYSTEM_SYSTEM_CONTROL;
-               cmd.buffer.block_data[0] = 0;
-               break;
-       case CPIA2_CMD_CLEAR_V2W_ERR:
-               cmd.req_mode =
-                   CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_SYSTEM_SYSTEM_CONTROL;
-               cmd.buffer.block_data[0] = CPIA2_SYSTEM_CONTROL_CLEAR_ERR;
-               break;
-       case CPIA2_CMD_SET_USER_MODE:   /* Then fall through */
-               cmd.buffer.block_data[0] = param;
-       case CPIA2_CMD_GET_USER_MODE:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               if (device == DEVICE_STV_672)
-                       cmd.start = CPIA2_VP4_USER_MODE;
-               else
-                       cmd.start = CPIA2_VP5_USER_MODE;
-               break;
-       case CPIA2_CMD_FRAMERATE_REQ:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               if (device == DEVICE_STV_672)
-                       cmd.start = CPIA2_VP4_FRAMERATE_REQUEST;
-               else
-                       cmd.start = CPIA2_VP5_FRAMERATE_REQUEST;
-               cmd.buffer.block_data[0] = param;
-               break;
-       case CPIA2_CMD_SET_WAKEUP:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_WAKEUP:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VC_WAKEUP;
-               break;
-       case CPIA2_CMD_SET_PW_CONTROL:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_PW_CONTROL:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VC_PW_CTRL;
-               break;
-       case CPIA2_CMD_GET_VP_SYSTEM_STATE:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VP_SYSTEMSTATE;
-               break;
-       case CPIA2_CMD_SET_SYSTEM_CTRL:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_SYSTEM_CTRL:
-               cmd.req_mode =
-                   CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_SYSTEM_SYSTEM_CONTROL;
-               break;
-       case CPIA2_CMD_SET_VP_SYSTEM_CTRL:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_VP_SYSTEM_CTRL:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VP_SYSTEMCTRL;
-               break;
-       case CPIA2_CMD_SET_VP_EXP_MODES:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_VP_EXP_MODES:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VP_EXPOSURE_MODES;
-               break;
-       case CPIA2_CMD_SET_DEVICE_CONFIG:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_DEVICE_CONFIG:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VP_DEVICE_CONFIG;
-               break;
-       case CPIA2_CMD_SET_SERIAL_ADDR:
-               cmd.buffer.block_data[0] = param;
-               cmd.req_mode =
-                   CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_SYSTEM_VP_SERIAL_ADDR;
-               break;
-       case CPIA2_CMD_SET_SENSOR_CR1:
-               cmd.buffer.block_data[0] = param;
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_SENSOR_CR1;
-               break;
-       case CPIA2_CMD_SET_VC_CONTROL:
-               cmd.buffer.block_data[0] = param;       /* Then fall through */
-       case CPIA2_CMD_GET_VC_CONTROL:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VC_VC_CTRL;
-               break;
-       case CPIA2_CMD_SET_TARGET_KB:
-               cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC;
-               cmd.reg_count = 1;
-               cmd.buffer.registers[0].index = CPIA2_VC_VC_TARGET_KB;
-               cmd.buffer.registers[0].value = param;
-               break;
-       case CPIA2_CMD_SET_DEF_JPEG_OPT:
-               cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC;
-               cmd.reg_count = 4;
-               cmd.buffer.registers[0].index = CPIA2_VC_VC_JPEG_OPT;
-               cmd.buffer.registers[0].value =
-                   CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE;
-               cmd.buffer.registers[1].index = CPIA2_VC_VC_USER_SQUEEZE;
-               cmd.buffer.registers[1].value = 20;
-               cmd.buffer.registers[2].index = CPIA2_VC_VC_CREEP_PERIOD;
-               cmd.buffer.registers[2].value = 2;
-               cmd.buffer.registers[3].index = CPIA2_VC_VC_JPEG_OPT;
-               cmd.buffer.registers[3].value = CPIA2_VC_VC_JPEG_OPT_DEFAULT;
-               break;
-       case CPIA2_CMD_REHASH_VP4:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VP_REHASH_VALUES;
-               cmd.buffer.block_data[0] = param;
-               break;
-       case CPIA2_CMD_SET_USER_EFFECTS:  /* Note: Be careful with this as
-                                            this register can also affect
-                                            flicker modes */
-               cmd.buffer.block_data[0] = param;      /* Then fall through */
-       case CPIA2_CMD_GET_USER_EFFECTS:
-               cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-               cmd.reg_count = 1;
-               if (device == DEVICE_STV_672)
-                       cmd.start = CPIA2_VP4_USER_EFFECTS;
-               else
-                       cmd.start = CPIA2_VP5_USER_EFFECTS;
-               break;
-       default:
-               LOG("DoCommand received invalid command\n");
-               return -EINVAL;
-       }
-
-       retval = cpia2_send_command(cam, &cmd);
-       if (retval) {
-               return retval;
-       }
-
-       /***
-        * Now copy any results from a read into the appropriate param struct.
-        ***/
-       switch (command) {
-       case CPIA2_CMD_GET_VERSION:
-               cam->params.version.firmware_revision_hi =
-                   cmd.buffer.block_data[0];
-               cam->params.version.firmware_revision_lo =
-                   cmd.buffer.block_data[1];
-               break;
-       case CPIA2_CMD_GET_PNP_ID:
-               cam->params.pnp_id.vendor = (cmd.buffer.block_data[0] << 8) |
-                                           cmd.buffer.block_data[1];
-               cam->params.pnp_id.product = (cmd.buffer.block_data[2] << 8) |
-                                            cmd.buffer.block_data[3];
-               cam->params.pnp_id.device_revision =
-                       (cmd.buffer.block_data[4] << 8) |
-                       cmd.buffer.block_data[5];
-               if (cam->params.pnp_id.vendor == 0x553) {
-                       if (cam->params.pnp_id.product == 0x100) {
-                               cam->params.pnp_id.device_type = DEVICE_STV_672;
-                       } else if (cam->params.pnp_id.product == 0x140 ||
-                                  cam->params.pnp_id.product == 0x151) {
-                               cam->params.pnp_id.device_type = DEVICE_STV_676;
-                       }
-               }
-               break;
-       case CPIA2_CMD_GET_ASIC_TYPE:
-               cam->params.version.asic_id = cmd.buffer.block_data[0];
-               cam->params.version.asic_rev = cmd.buffer.block_data[1];
-               break;
-       case CPIA2_CMD_GET_SENSOR:
-               cam->params.version.sensor_flags = cmd.buffer.block_data[0];
-               cam->params.version.sensor_rev = cmd.buffer.block_data[1];
-               break;
-       case CPIA2_CMD_GET_VP_DEVICE:
-               cam->params.version.vp_device_hi = cmd.buffer.block_data[0];
-               cam->params.version.vp_device_lo = cmd.buffer.block_data[1];
-               break;
-       case CPIA2_CMD_GET_VP_GPIO_DATA:
-               cam->params.vp_params.gpio_data = cmd.buffer.block_data[0];
-               break;
-       case CPIA2_CMD_GET_VP_GPIO_DIRECTION:
-               cam->params.vp_params.gpio_direction = cmd.buffer.block_data[0];
-               break;
-       case CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION:
-               cam->params.vc_params.vc_mp_direction =cmd.buffer.block_data[0];
-               break;
-       case CPIA2_CMD_GET_VC_MP_GPIO_DATA:
-               cam->params.vc_params.vc_mp_data = cmd.buffer.block_data[0];
-               break;
-       case CPIA2_CMD_GET_FLICKER_MODES:
-               cam->params.flicker_control.cam_register =
-                       cmd.buffer.block_data[0];
-               break;
-       case CPIA2_CMD_GET_WAKEUP:
-               cam->params.vc_params.wakeup = cmd.buffer.block_data[0];
-               break;
-       case CPIA2_CMD_GET_PW_CONTROL:
-               cam->params.vc_params.pw_control = cmd.buffer.block_data[0];
-               break;
-       case CPIA2_CMD_GET_SYSTEM_CTRL:
-               cam->params.camera_state.system_ctrl = cmd.buffer.block_data[0];
-               break;
-       case CPIA2_CMD_GET_VP_SYSTEM_STATE:
-               cam->params.vp_params.system_state = cmd.buffer.block_data[0];
-               break;
-       case CPIA2_CMD_GET_VP_SYSTEM_CTRL:
-               cam->params.vp_params.system_ctrl = cmd.buffer.block_data[0];
-               break;
-       case CPIA2_CMD_GET_VP_EXP_MODES:
-               cam->params.vp_params.exposure_modes = cmd.buffer.block_data[0];
-               break;
-       case CPIA2_CMD_GET_DEVICE_CONFIG:
-               cam->params.vp_params.device_config = cmd.buffer.block_data[0];
-               break;
-       case CPIA2_CMD_GET_VC_CONTROL:
-               cam->params.vc_params.vc_control = cmd.buffer.block_data[0];
-               break;
-       case CPIA2_CMD_GET_USER_MODE:
-               cam->params.vp_params.video_mode = cmd.buffer.block_data[0];
-               break;
-       case CPIA2_CMD_GET_USER_EFFECTS:
-               cam->params.vp_params.user_effects = cmd.buffer.block_data[0];
-               break;
-       default:
-               break;
-       }
-       return retval;
-}
-
-/******************************************************************************
- *
- *  cpia2_send_command
- *
- *****************************************************************************/
-
-#define DIR(cmd) ((cmd->direction == TRANSFER_WRITE) ? "Write" : "Read")
-#define BINDEX(cmd) (cmd->req_mode & 0x03)
-
-int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd)
-{
-       u8 count;
-       u8 start;
-       u8 *buffer;
-       int retval;
-
-       switch (cmd->req_mode & 0x0c) {
-       case CAMERAACCESS_TYPE_RANDOM:
-               count = cmd->reg_count * sizeof(struct cpia2_register);
-               start = 0;
-               buffer = (u8 *) & cmd->buffer;
-               if (debugs_on & DEBUG_REG)
-                       DBG("%s Random: Register block %s\n", DIR(cmd),
-                           block_name[BINDEX(cmd)]);
-               break;
-       case CAMERAACCESS_TYPE_BLOCK:
-               count = cmd->reg_count;
-               start = cmd->start;
-               buffer = cmd->buffer.block_data;
-               if (debugs_on & DEBUG_REG)
-                       DBG("%s Block: Register block %s\n", DIR(cmd),
-                           block_name[BINDEX(cmd)]);
-               break;
-       case CAMERAACCESS_TYPE_MASK:
-               count = cmd->reg_count * sizeof(struct cpia2_reg_mask);
-               start = 0;
-               buffer = (u8 *) & cmd->buffer;
-               if (debugs_on & DEBUG_REG)
-                       DBG("%s Mask: Register block %s\n", DIR(cmd),
-                           block_name[BINDEX(cmd)]);
-               break;
-       case CAMERAACCESS_TYPE_REPEAT:  /* For patch blocks only */
-               count = cmd->reg_count;
-               start = cmd->start;
-               buffer = cmd->buffer.block_data;
-               if (debugs_on & DEBUG_REG)
-                       DBG("%s Repeat: Register block %s\n", DIR(cmd),
-                           block_name[BINDEX(cmd)]);
-               break;
-       default:
-               LOG("%s: invalid request mode\n",__func__);
-               return -EINVAL;
-       }
-
-       retval = cpia2_usb_transfer_cmd(cam,
-                                       buffer,
-                                       cmd->req_mode,
-                                       start, count, cmd->direction);
-#ifdef _CPIA2_DEBUG_
-       if (debugs_on & DEBUG_REG) {
-               int i;
-               for (i = 0; i < cmd->reg_count; i++) {
-                       if((cmd->req_mode & 0x0c) == CAMERAACCESS_TYPE_BLOCK)
-                               KINFO("%s Block: [0x%02X] = 0x%02X\n",
-                                   DIR(cmd), start + i, buffer[i]);
-                       if((cmd->req_mode & 0x0c) == CAMERAACCESS_TYPE_RANDOM)
-                               KINFO("%s Random: [0x%02X] = 0x%02X\n",
-                                   DIR(cmd), cmd->buffer.registers[i].index,
-                                   cmd->buffer.registers[i].value);
-               }
-       }
-#endif
-
-       return retval;
-};
-
-/*************
- * Functions to implement camera functionality
- *************/
-/******************************************************************************
- *
- *  cpia2_get_version_info
- *
- *****************************************************************************/
-static void cpia2_get_version_info(struct camera_data *cam)
-{
-       cpia2_do_command(cam, CPIA2_CMD_GET_VERSION, TRANSFER_READ, 0);
-       cpia2_do_command(cam, CPIA2_CMD_GET_PNP_ID, TRANSFER_READ, 0);
-       cpia2_do_command(cam, CPIA2_CMD_GET_ASIC_TYPE, TRANSFER_READ, 0);
-       cpia2_do_command(cam, CPIA2_CMD_GET_SENSOR, TRANSFER_READ, 0);
-       cpia2_do_command(cam, CPIA2_CMD_GET_VP_DEVICE, TRANSFER_READ, 0);
-}
-
-/******************************************************************************
- *
- *  cpia2_reset_camera
- *
- *  Called at least during the open process, sets up initial params.
- *****************************************************************************/
-int cpia2_reset_camera(struct camera_data *cam)
-{
-       u8 tmp_reg;
-       int retval = 0;
-       int target_kb;
-       int i;
-       struct cpia2_command cmd;
-
-       /***
-        * VC setup
-        ***/
-       retval = configure_sensor(cam,
-                                 cam->params.roi.width,
-                                 cam->params.roi.height);
-       if (retval < 0) {
-               ERR("Couldn't configure sensor, error=%d\n", retval);
-               return retval;
-       }
-
-       /* Clear FIFO and route/enable stream block */
-       cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC;
-       cmd.direction = TRANSFER_WRITE;
-       cmd.reg_count = 2;
-       cmd.buffer.registers[0].index = CPIA2_VC_ST_CTRL;
-       cmd.buffer.registers[0].value = CPIA2_VC_ST_CTRL_SRC_VC |
-               CPIA2_VC_ST_CTRL_DST_USB | CPIA2_VC_ST_CTRL_EOF_DETECT;
-       cmd.buffer.registers[1].index = CPIA2_VC_ST_CTRL;
-       cmd.buffer.registers[1].value = CPIA2_VC_ST_CTRL_SRC_VC |
-               CPIA2_VC_ST_CTRL_DST_USB |
-               CPIA2_VC_ST_CTRL_EOF_DETECT | CPIA2_VC_ST_CTRL_FIFO_ENABLE;
-
-       cpia2_send_command(cam, &cmd);
-
-       cpia2_set_high_power(cam);
-
-       if (cam->params.pnp_id.device_type == DEVICE_STV_672) {
-               /* Enable button notification */
-               cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_SYSTEM;
-               cmd.buffer.registers[0].index = CPIA2_SYSTEM_INT_PACKET_CTRL;
-               cmd.buffer.registers[0].value =
-                       CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_SW_XX;
-               cmd.reg_count = 1;
-               cpia2_send_command(cam, &cmd);
-       }
-
-       schedule_timeout_interruptible(msecs_to_jiffies(100));
-
-       if (cam->params.pnp_id.device_type == DEVICE_STV_672)
-               retval = apply_vp_patch(cam);
-
-       /* wait for vp to go to sleep */
-       schedule_timeout_interruptible(msecs_to_jiffies(100));
-
-       /***
-        * If this is a 676, apply VP5 fixes before we start streaming
-        ***/
-       if (cam->params.pnp_id.device_type == DEVICE_STV_676) {
-               cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP;
-
-               /* The following writes improve the picture */
-               cmd.buffer.registers[0].index = CPIA2_VP5_MYBLACK_LEVEL;
-               cmd.buffer.registers[0].value = 0; /* reduce from the default
-                                                   * rec 601 pedestal of 16 */
-               cmd.buffer.registers[1].index = CPIA2_VP5_MCYRANGE;
-               cmd.buffer.registers[1].value = 0x92; /* increase from 100% to
-                                                      * (256/256 - 31) to fill
-                                                      * available range */
-               cmd.buffer.registers[2].index = CPIA2_VP5_MYCEILING;
-               cmd.buffer.registers[2].value = 0xFF; /* Increase from the
-                                                      * default rec 601 ceiling
-                                                      * of 240 */
-               cmd.buffer.registers[3].index = CPIA2_VP5_MCUVSATURATION;
-               cmd.buffer.registers[3].value = 0xFF; /* Increase from the rec
-                                                      * 601 100% level (128)
-                                                      * to 145-192 */
-               cmd.buffer.registers[4].index = CPIA2_VP5_ANTIFLKRSETUP;
-               cmd.buffer.registers[4].value = 0x80;  /* Inhibit the
-                                                       * anti-flicker */
-
-               /* The following 4 writes are a fix to allow QVGA to work at 30 fps */
-               cmd.buffer.registers[5].index = CPIA2_VP_RAM_ADDR_H;
-               cmd.buffer.registers[5].value = 0x01;
-               cmd.buffer.registers[6].index = CPIA2_VP_RAM_ADDR_L;
-               cmd.buffer.registers[6].value = 0xE3;
-               cmd.buffer.registers[7].index = CPIA2_VP_RAM_DATA;
-               cmd.buffer.registers[7].value = 0x02;
-               cmd.buffer.registers[8].index = CPIA2_VP_RAM_DATA;
-               cmd.buffer.registers[8].value = 0xFC;
-
-               cmd.direction = TRANSFER_WRITE;
-               cmd.reg_count = 9;
-
-               cpia2_send_command(cam, &cmd);
-       }
-
-       /* Activate all settings and start the data stream */
-       /* Set user mode */
-       set_default_user_mode(cam);
-
-       /* Give VP time to wake up */
-       schedule_timeout_interruptible(msecs_to_jiffies(100));
-
-       set_all_properties(cam);
-
-       cpia2_do_command(cam, CPIA2_CMD_GET_USER_MODE, TRANSFER_READ, 0);
-       DBG("After SetAllProperties(cam), user mode is 0x%0X\n",
-           cam->params.vp_params.video_mode);
-
-       /***
-        * Set audio regulator off.  This and the code to set the compresison
-        * state are too complex to form a CPIA2_CMD_, and seem to be somewhat
-        * intertwined.  This stuff came straight from the windows driver.
-        ***/
-       /* Turn AutoExposure off in VP and enable the serial bridge to the sensor */
-       cpia2_do_command(cam, CPIA2_CMD_GET_VP_SYSTEM_CTRL, TRANSFER_READ, 0);
-       tmp_reg = cam->params.vp_params.system_ctrl;
-       cmd.buffer.registers[0].value = tmp_reg &
-               (tmp_reg & (CPIA2_VP_SYSTEMCTRL_HK_CONTROL ^ 0xFF));
-
-       cpia2_do_command(cam, CPIA2_CMD_GET_DEVICE_CONFIG, TRANSFER_READ, 0);
-       cmd.buffer.registers[1].value = cam->params.vp_params.device_config |
-                                       CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE;
-       cmd.buffer.registers[0].index = CPIA2_VP_SYSTEMCTRL;
-       cmd.buffer.registers[1].index = CPIA2_VP_DEVICE_CONFIG;
-       cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP;
-       cmd.reg_count = 2;
-       cmd.direction = TRANSFER_WRITE;
-       cmd.start = 0;
-       cpia2_send_command(cam, &cmd);
-
-       /* Set the correct I2C address in the CPiA-2 system register */
-       cpia2_do_command(cam,
-                        CPIA2_CMD_SET_SERIAL_ADDR,
-                        TRANSFER_WRITE,
-                        CPIA2_SYSTEM_VP_SERIAL_ADDR_SENSOR);
-
-       /* Now have sensor access - set bit to turn the audio regulator off */
-       cpia2_do_command(cam,
-                        CPIA2_CMD_SET_SENSOR_CR1,
-                        TRANSFER_WRITE, CPIA2_SENSOR_CR1_DOWN_AUDIO_REGULATOR);
-
-       /* Set the correct I2C address in the CPiA-2 system register */
-       if (cam->params.pnp_id.device_type == DEVICE_STV_672)
-               cpia2_do_command(cam,
-                                CPIA2_CMD_SET_SERIAL_ADDR,
-                                TRANSFER_WRITE,
-                                CPIA2_SYSTEM_VP_SERIAL_ADDR_VP); // 0x88
-       else
-               cpia2_do_command(cam,
-                                CPIA2_CMD_SET_SERIAL_ADDR,
-                                TRANSFER_WRITE,
-                                CPIA2_SYSTEM_VP_SERIAL_ADDR_676_VP); // 0x8a
-
-       /* increase signal drive strength */
-       if (cam->params.pnp_id.device_type == DEVICE_STV_676)
-               cpia2_do_command(cam,
-                                CPIA2_CMD_SET_VP_EXP_MODES,
-                                TRANSFER_WRITE,
-                                CPIA2_VP_EXPOSURE_MODES_COMPILE_EXP);
-
-       /* Start autoexposure */
-       cpia2_do_command(cam, CPIA2_CMD_GET_DEVICE_CONFIG, TRANSFER_READ, 0);
-       cmd.buffer.registers[0].value = cam->params.vp_params.device_config &
-                                 (CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE ^ 0xFF);
-
-       cpia2_do_command(cam, CPIA2_CMD_GET_VP_SYSTEM_CTRL, TRANSFER_READ, 0);
-       cmd.buffer.registers[1].value =
-           cam->params.vp_params.system_ctrl | CPIA2_VP_SYSTEMCTRL_HK_CONTROL;
-
-       cmd.buffer.registers[0].index = CPIA2_VP_DEVICE_CONFIG;
-       cmd.buffer.registers[1].index = CPIA2_VP_SYSTEMCTRL;
-       cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VP;
-       cmd.reg_count = 2;
-       cmd.direction = TRANSFER_WRITE;
-
-       cpia2_send_command(cam, &cmd);
-
-       /* Set compression state */
-       cpia2_do_command(cam, CPIA2_CMD_GET_VC_CONTROL, TRANSFER_READ, 0);
-       if (cam->params.compression.inhibit_htables) {
-               tmp_reg = cam->params.vc_params.vc_control |
-                         CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES;
-       } else  {
-               tmp_reg = cam->params.vc_params.vc_control &
-                         ~CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES;
-       }
-       cpia2_do_command(cam, CPIA2_CMD_SET_VC_CONTROL, TRANSFER_WRITE,tmp_reg);
-
-       /* Set target size (kb) on vc
-          This is a heuristic based on the quality parameter and the raw
-          framesize in kB divided by 16 (the compression factor when the
-          quality is 100%) */
-       target_kb = (cam->width * cam->height * 2 / 16384) *
-                               cam->params.vc_params.quality / 100;
-       if (target_kb < 1)
-               target_kb = 1;
-       cpia2_do_command(cam, CPIA2_CMD_SET_TARGET_KB,
-                        TRANSFER_WRITE, target_kb);
-
-       /* Wiggle VC Reset */
-       /***
-        * First read and wait a bit.
-        ***/
-       for (i = 0; i < 50; i++) {
-               cpia2_do_command(cam, CPIA2_CMD_GET_PW_CONTROL,
-                                TRANSFER_READ, 0);
-       }
-
-       tmp_reg = cam->params.vc_params.pw_control;
-       tmp_reg &= ~CPIA2_VC_PW_CTRL_VC_RESET_N;
-
-       cpia2_do_command(cam, CPIA2_CMD_SET_PW_CONTROL, TRANSFER_WRITE,tmp_reg);
-
-       tmp_reg |= CPIA2_VC_PW_CTRL_VC_RESET_N;
-       cpia2_do_command(cam, CPIA2_CMD_SET_PW_CONTROL, TRANSFER_WRITE,tmp_reg);
-
-       cpia2_do_command(cam, CPIA2_CMD_SET_DEF_JPEG_OPT, TRANSFER_WRITE, 0);
-
-       cpia2_do_command(cam, CPIA2_CMD_GET_USER_MODE, TRANSFER_READ, 0);
-       DBG("After VC RESET, user mode is 0x%0X\n",
-           cam->params.vp_params.video_mode);
-
-       return retval;
-}
-
-/******************************************************************************
- *
- *  cpia2_set_high_power
- *
- *****************************************************************************/
-static int cpia2_set_high_power(struct camera_data *cam)
-{
-       int i;
-       for (i = 0; i <= 50; i++) {
-               /* Read system status */
-               cpia2_do_command(cam,CPIA2_CMD_GET_SYSTEM_CTRL,TRANSFER_READ,0);
-
-               /* If there is an error, clear it */
-               if(cam->params.camera_state.system_ctrl &
-                  CPIA2_SYSTEM_CONTROL_V2W_ERR)
-                       cpia2_do_command(cam, CPIA2_CMD_CLEAR_V2W_ERR,
-                                        TRANSFER_WRITE, 0);
-
-               /* Try to set high power mode */
-               cpia2_do_command(cam, CPIA2_CMD_SET_SYSTEM_CTRL,
-                                TRANSFER_WRITE, 1);
-
-               /* Try to read something in VP to check if everything is awake */
-               cpia2_do_command(cam, CPIA2_CMD_GET_VP_SYSTEM_STATE,
-                                TRANSFER_READ, 0);
-               if (cam->params.vp_params.system_state &
-                   CPIA2_VP_SYSTEMSTATE_HK_ALIVE) {
-                       break;
-               } else if (i == 50) {
-                       cam->params.camera_state.power_mode = LO_POWER_MODE;
-                       ERR("Camera did not wake up\n");
-                       return -EIO;
-               }
-       }
-
-       DBG("System now in high power state\n");
-       cam->params.camera_state.power_mode = HI_POWER_MODE;
-       return 0;
-}
-
-/******************************************************************************
- *
- *  cpia2_set_low_power
- *
- *****************************************************************************/
-int cpia2_set_low_power(struct camera_data *cam)
-{
-       cam->params.camera_state.power_mode = LO_POWER_MODE;
-       cpia2_do_command(cam, CPIA2_CMD_SET_SYSTEM_CTRL, TRANSFER_WRITE, 0);
-       return 0;
-}
-
-/******************************************************************************
- *
- *  apply_vp_patch
- *
- *****************************************************************************/
-static int cpia2_send_onebyte_command(struct camera_data *cam,
-                                     struct cpia2_command *cmd,
-                                     u8 start, u8 datum)
-{
-       cmd->buffer.block_data[0] = datum;
-       cmd->start = start;
-       cmd->reg_count = 1;
-       return cpia2_send_command(cam, cmd);
-}
-
-static int apply_vp_patch(struct camera_data *cam)
-{
-       const struct firmware *fw;
-       const char fw_name[] = FIRMWARE;
-       int i, ret;
-       struct cpia2_command cmd;
-
-       ret = request_firmware(&fw, fw_name, &cam->dev->dev);
-       if (ret) {
-               printk(KERN_ERR "cpia2: failed to load VP patch \"%s\"\n",
-                      fw_name);
-               return ret;
-       }
-
-       cmd.req_mode = CAMERAACCESS_TYPE_REPEAT | CAMERAACCESS_VP;
-       cmd.direction = TRANSFER_WRITE;
-
-       /* First send the start address... */
-       cpia2_send_onebyte_command(cam, &cmd, 0x0A, fw->data[0]); /* hi */
-       cpia2_send_onebyte_command(cam, &cmd, 0x0B, fw->data[1]); /* lo */
-
-       /* ... followed by the data payload */
-       for (i = 2; i < fw->size; i += 64) {
-               cmd.start = 0x0C; /* Data */
-               cmd.reg_count = min_t(int, 64, fw->size - i);
-               memcpy(cmd.buffer.block_data, &fw->data[i], cmd.reg_count);
-               cpia2_send_command(cam, &cmd);
-       }
-
-       /* Next send the start address... */
-       cpia2_send_onebyte_command(cam, &cmd, 0x0A, fw->data[0]); /* hi */
-       cpia2_send_onebyte_command(cam, &cmd, 0x0B, fw->data[1]); /* lo */
-
-       /* ... followed by the 'goto' command */
-       cpia2_send_onebyte_command(cam, &cmd, 0x0D, 1);
-
-       release_firmware(fw);
-       return 0;
-}
-
-/******************************************************************************
- *
- *  set_default_user_mode
- *
- *****************************************************************************/
-static int set_default_user_mode(struct camera_data *cam)
-{
-       unsigned char user_mode;
-       unsigned char frame_rate;
-       int width = cam->params.roi.width;
-       int height = cam->params.roi.height;
-
-       switch (cam->params.version.sensor_flags) {
-       case CPIA2_VP_SENSOR_FLAGS_404:
-       case CPIA2_VP_SENSOR_FLAGS_407:
-       case CPIA2_VP_SENSOR_FLAGS_409:
-       case CPIA2_VP_SENSOR_FLAGS_410:
-               if ((width > STV_IMAGE_QCIF_COLS)
-                   || (height > STV_IMAGE_QCIF_ROWS)) {
-                       user_mode = CPIA2_VP_USER_MODE_CIF;
-               } else {
-                       user_mode = CPIA2_VP_USER_MODE_QCIFDS;
-               }
-               frame_rate = CPIA2_VP_FRAMERATE_30;
-               break;
-       case CPIA2_VP_SENSOR_FLAGS_500:
-               if ((width > STV_IMAGE_CIF_COLS)
-                   || (height > STV_IMAGE_CIF_ROWS)) {
-                       user_mode = CPIA2_VP_USER_MODE_VGA;
-               } else {
-                       user_mode = CPIA2_VP_USER_MODE_QVGADS;
-               }
-               if (cam->params.pnp_id.device_type == DEVICE_STV_672)
-                       frame_rate = CPIA2_VP_FRAMERATE_15;
-               else
-                       frame_rate = CPIA2_VP_FRAMERATE_30;
-               break;
-       default:
-               LOG("%s: Invalid sensor flag value 0x%0X\n",__func__,
-                   cam->params.version.sensor_flags);
-               return -EINVAL;
-       }
-
-       DBG("Sensor flag = 0x%0x, user mode = 0x%0x, frame rate = 0x%X\n",
-           cam->params.version.sensor_flags, user_mode, frame_rate);
-       cpia2_do_command(cam, CPIA2_CMD_SET_USER_MODE, TRANSFER_WRITE,
-                        user_mode);
-       if(cam->params.vp_params.frame_rate > 0 &&
-          frame_rate > cam->params.vp_params.frame_rate)
-               frame_rate = cam->params.vp_params.frame_rate;
-
-       cpia2_set_fps(cam, frame_rate);
-
-//     if (cam->params.pnp_id.device_type == DEVICE_STV_676)
-//             cpia2_do_command(cam,
-//                              CPIA2_CMD_SET_VP_SYSTEM_CTRL,
-//                              TRANSFER_WRITE,
-//                              CPIA2_VP_SYSTEMCTRL_HK_CONTROL |
-//                              CPIA2_VP_SYSTEMCTRL_POWER_CONTROL);
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  cpia2_match_video_size
- *
- *  return the best match, where 'best' is as always
- *  the largest that is not bigger than what is requested.
- *****************************************************************************/
-int cpia2_match_video_size(int width, int height)
-{
-       if (width >= STV_IMAGE_VGA_COLS && height >= STV_IMAGE_VGA_ROWS)
-               return VIDEOSIZE_VGA;
-
-       if (width >= STV_IMAGE_CIF_COLS && height >= STV_IMAGE_CIF_ROWS)
-               return VIDEOSIZE_CIF;
-
-       if (width >= STV_IMAGE_QVGA_COLS && height >= STV_IMAGE_QVGA_ROWS)
-               return VIDEOSIZE_QVGA;
-
-       if (width >= 288 && height >= 216)
-               return VIDEOSIZE_288_216;
-
-       if (width >= 256 && height >= 192)
-               return VIDEOSIZE_256_192;
-
-       if (width >= 224 && height >= 168)
-               return VIDEOSIZE_224_168;
-
-       if (width >= 192 && height >= 144)
-               return VIDEOSIZE_192_144;
-
-       if (width >= STV_IMAGE_QCIF_COLS && height >= STV_IMAGE_QCIF_ROWS)
-               return VIDEOSIZE_QCIF;
-
-       return -1;
-}
-
-/******************************************************************************
- *
- *  SetVideoSize
- *
- *****************************************************************************/
-static int set_vw_size(struct camera_data *cam, int size)
-{
-       int retval = 0;
-
-       cam->params.vp_params.video_size = size;
-
-       switch (size) {
-       case VIDEOSIZE_VGA:
-               DBG("Setting size to VGA\n");
-               cam->params.roi.width = STV_IMAGE_VGA_COLS;
-               cam->params.roi.height = STV_IMAGE_VGA_ROWS;
-               cam->width = STV_IMAGE_VGA_COLS;
-               cam->height = STV_IMAGE_VGA_ROWS;
-               break;
-       case VIDEOSIZE_CIF:
-               DBG("Setting size to CIF\n");
-               cam->params.roi.width = STV_IMAGE_CIF_COLS;
-               cam->params.roi.height = STV_IMAGE_CIF_ROWS;
-               cam->width = STV_IMAGE_CIF_COLS;
-               cam->height = STV_IMAGE_CIF_ROWS;
-               break;
-       case VIDEOSIZE_QVGA:
-               DBG("Setting size to QVGA\n");
-               cam->params.roi.width = STV_IMAGE_QVGA_COLS;
-               cam->params.roi.height = STV_IMAGE_QVGA_ROWS;
-               cam->width = STV_IMAGE_QVGA_COLS;
-               cam->height = STV_IMAGE_QVGA_ROWS;
-               break;
-       case VIDEOSIZE_288_216:
-               cam->params.roi.width = 288;
-               cam->params.roi.height = 216;
-               cam->width = 288;
-               cam->height = 216;
-               break;
-       case VIDEOSIZE_256_192:
-               cam->width = 256;
-               cam->height = 192;
-               cam->params.roi.width = 256;
-               cam->params.roi.height = 192;
-               break;
-       case VIDEOSIZE_224_168:
-               cam->width = 224;
-               cam->height = 168;
-               cam->params.roi.width = 224;
-               cam->params.roi.height = 168;
-               break;
-       case VIDEOSIZE_192_144:
-               cam->width = 192;
-               cam->height = 144;
-               cam->params.roi.width = 192;
-               cam->params.roi.height = 144;
-               break;
-       case VIDEOSIZE_QCIF:
-               DBG("Setting size to QCIF\n");
-               cam->params.roi.width = STV_IMAGE_QCIF_COLS;
-               cam->params.roi.height = STV_IMAGE_QCIF_ROWS;
-               cam->width = STV_IMAGE_QCIF_COLS;
-               cam->height = STV_IMAGE_QCIF_ROWS;
-               break;
-       default:
-               retval = -EINVAL;
-       }
-       return retval;
-}
-
-/******************************************************************************
- *
- *  configure_sensor
- *
- *****************************************************************************/
-static int configure_sensor(struct camera_data *cam,
-                           int req_width, int req_height)
-{
-       int retval;
-
-       switch (cam->params.version.sensor_flags) {
-       case CPIA2_VP_SENSOR_FLAGS_404:
-       case CPIA2_VP_SENSOR_FLAGS_407:
-       case CPIA2_VP_SENSOR_FLAGS_409:
-       case CPIA2_VP_SENSOR_FLAGS_410:
-               retval = config_sensor_410(cam, req_width, req_height);
-               break;
-       case CPIA2_VP_SENSOR_FLAGS_500:
-               retval = config_sensor_500(cam, req_width, req_height);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return retval;
-}
-
-/******************************************************************************
- *
- *  config_sensor_410
- *
- *****************************************************************************/
-static int config_sensor_410(struct camera_data *cam,
-                           int req_width, int req_height)
-{
-       struct cpia2_command cmd;
-       int i = 0;
-       int image_size;
-       int image_type;
-       int width = req_width;
-       int height = req_height;
-
-       /***
-        *  Make sure size doesn't exceed CIF.
-        ***/
-       if (width > STV_IMAGE_CIF_COLS)
-               width = STV_IMAGE_CIF_COLS;
-       if (height > STV_IMAGE_CIF_ROWS)
-               height = STV_IMAGE_CIF_ROWS;
-
-       image_size = cpia2_match_video_size(width, height);
-
-       DBG("Config 410: width = %d, height = %d\n", width, height);
-       DBG("Image size returned is %d\n", image_size);
-       if (image_size >= 0) {
-               set_vw_size(cam, image_size);
-               width = cam->params.roi.width;
-               height = cam->params.roi.height;
-
-               DBG("After set_vw_size(), width = %d, height = %d\n",
-                   width, height);
-               if (width <= 176 && height <= 144) {
-                       DBG("image type = VIDEOSIZE_QCIF\n");
-                       image_type = VIDEOSIZE_QCIF;
-               }
-               else if (width <= 320 && height <= 240) {
-                       DBG("image type = VIDEOSIZE_QVGA\n");
-                       image_type = VIDEOSIZE_QVGA;
-               }
-               else {
-                       DBG("image type = VIDEOSIZE_CIF\n");
-                       image_type = VIDEOSIZE_CIF;
-               }
-       } else {
-               ERR("ConfigSensor410 failed\n");
-               return -EINVAL;
-       }
-
-       cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC;
-       cmd.direction = TRANSFER_WRITE;
-
-       /* VC Format */
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_FORMAT;
-       if (image_type == VIDEOSIZE_CIF) {
-               cmd.buffer.registers[i++].value =
-                   (u8) (CPIA2_VC_VC_FORMAT_UFIRST |
-                         CPIA2_VC_VC_FORMAT_SHORTLINE);
-       } else {
-               cmd.buffer.registers[i++].value =
-                   (u8) CPIA2_VC_VC_FORMAT_UFIRST;
-       }
-
-       /* VC Clocks */
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_CLOCKS;
-       if (image_type == VIDEOSIZE_QCIF) {
-               if (cam->params.pnp_id.device_type == DEVICE_STV_672) {
-                       cmd.buffer.registers[i++].value=
-                               (u8)(CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3 |
-                                    CPIA2_VC_VC_672_CLOCKS_SCALING |
-                                    CPIA2_VC_VC_CLOCKS_LOGDIV2);
-                       DBG("VC_Clocks (0xc4) should be B\n");
-               }
-               else {
-                       cmd.buffer.registers[i++].value=
-                               (u8)(CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3 |
-                                    CPIA2_VC_VC_CLOCKS_LOGDIV2);
-               }
-       } else {
-               if (cam->params.pnp_id.device_type == DEVICE_STV_672) {
-                       cmd.buffer.registers[i++].value =
-                          (u8) (CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3 |
-                                CPIA2_VC_VC_CLOCKS_LOGDIV0);
-               }
-               else {
-                       cmd.buffer.registers[i++].value =
-                          (u8) (CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3 |
-                                CPIA2_VC_VC_676_CLOCKS_SCALING |
-                                CPIA2_VC_VC_CLOCKS_LOGDIV0);
-               }
-       }
-       DBG("VC_Clocks (0xc4) = 0x%0X\n", cmd.buffer.registers[i-1].value);
-
-       /* Input reqWidth from VC */
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_IHSIZE_LO;
-       if (image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value =
-                   (u8) (STV_IMAGE_QCIF_COLS / 4);
-       else
-               cmd.buffer.registers[i++].value =
-                   (u8) (STV_IMAGE_CIF_COLS / 4);
-
-       /* Timings */
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_HI;
-       if (image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value = (u8) 0;
-       else
-               cmd.buffer.registers[i++].value = (u8) 1;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_LO;
-       if (image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value = (u8) 208;
-       else
-               cmd.buffer.registers[i++].value = (u8) 160;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_HI;
-       if (image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value = (u8) 0;
-       else
-               cmd.buffer.registers[i++].value = (u8) 1;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_LO;
-       if (image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value = (u8) 160;
-       else
-               cmd.buffer.registers[i++].value = (u8) 64;
-
-       /* Output Image Size */
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_OHSIZE;
-       cmd.buffer.registers[i++].value = cam->params.roi.width / 4;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_OVSIZE;
-       cmd.buffer.registers[i++].value = cam->params.roi.height / 4;
-
-       /* Cropping */
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_HCROP;
-       if (image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value =
-                   (u8) (((STV_IMAGE_QCIF_COLS / 4) - (width / 4)) / 2);
-       else
-               cmd.buffer.registers[i++].value =
-                   (u8) (((STV_IMAGE_CIF_COLS / 4) - (width / 4)) / 2);
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_VCROP;
-       if (image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value =
-                   (u8) (((STV_IMAGE_QCIF_ROWS / 4) - (height / 4)) / 2);
-       else
-               cmd.buffer.registers[i++].value =
-                   (u8) (((STV_IMAGE_CIF_ROWS / 4) - (height / 4)) / 2);
-
-       /* Scaling registers (defaults) */
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_HPHASE;
-       cmd.buffer.registers[i++].value = (u8) 0;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_VPHASE;
-       cmd.buffer.registers[i++].value = (u8) 0;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_HISPAN;
-       cmd.buffer.registers[i++].value = (u8) 31;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_VISPAN;
-       cmd.buffer.registers[i++].value = (u8) 31;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_HICROP;
-       cmd.buffer.registers[i++].value = (u8) 0;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_VICROP;
-       cmd.buffer.registers[i++].value = (u8) 0;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_HFRACT;
-       cmd.buffer.registers[i++].value = (u8) 0x81;    /* = 8/1 = 8 (HIBYTE/LOBYTE) */
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_VFRACT;
-       cmd.buffer.registers[i++].value = (u8) 0x81;    /* = 8/1 = 8 (HIBYTE/LOBYTE) */
-
-       cmd.reg_count = i;
-
-       cpia2_send_command(cam, &cmd);
-
-       return i;
-}
-
-
-/******************************************************************************
- *
- *  config_sensor_500(cam)
- *
- *****************************************************************************/
-static int config_sensor_500(struct camera_data *cam,
-                            int req_width, int req_height)
-{
-       struct cpia2_command cmd;
-       int i = 0;
-       int image_size = VIDEOSIZE_CIF;
-       int image_type = VIDEOSIZE_VGA;
-       int width = req_width;
-       int height = req_height;
-       unsigned int device = cam->params.pnp_id.device_type;
-
-       image_size = cpia2_match_video_size(width, height);
-
-       if (width > STV_IMAGE_CIF_COLS || height > STV_IMAGE_CIF_ROWS)
-               image_type = VIDEOSIZE_VGA;
-       else if (width > STV_IMAGE_QVGA_COLS || height > STV_IMAGE_QVGA_ROWS)
-               image_type = VIDEOSIZE_CIF;
-       else if (width > STV_IMAGE_QCIF_COLS || height > STV_IMAGE_QCIF_ROWS)
-               image_type = VIDEOSIZE_QVGA;
-       else
-               image_type = VIDEOSIZE_QCIF;
-
-       if (image_size >= 0) {
-               set_vw_size(cam, image_size);
-               width = cam->params.roi.width;
-               height = cam->params.roi.height;
-       } else {
-               ERR("ConfigSensor500 failed\n");
-               return -EINVAL;
-       }
-
-       DBG("image_size = %d, width = %d, height = %d, type = %d\n",
-           image_size, width, height, image_type);
-
-       cmd.req_mode = CAMERAACCESS_TYPE_RANDOM | CAMERAACCESS_VC;
-       cmd.direction = TRANSFER_WRITE;
-       i = 0;
-
-       /* VC Format */
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_FORMAT;
-       cmd.buffer.registers[i].value = (u8) CPIA2_VC_VC_FORMAT_UFIRST;
-       if (image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i].value |= (u8) CPIA2_VC_VC_FORMAT_DECIMATING;
-       i++;
-
-       /* VC Clocks */
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_CLOCKS;
-       if (device == DEVICE_STV_672) {
-               if (image_type == VIDEOSIZE_VGA)
-                       cmd.buffer.registers[i].value =
-                               (u8)CPIA2_VC_VC_CLOCKS_LOGDIV1;
-               else
-                       cmd.buffer.registers[i].value =
-                               (u8)(CPIA2_VC_VC_672_CLOCKS_SCALING |
-                                    CPIA2_VC_VC_CLOCKS_LOGDIV3);
-       } else {
-               if (image_type == VIDEOSIZE_VGA)
-                       cmd.buffer.registers[i].value =
-                               (u8)CPIA2_VC_VC_CLOCKS_LOGDIV0;
-               else
-                       cmd.buffer.registers[i].value =
-                               (u8)(CPIA2_VC_VC_676_CLOCKS_SCALING |
-                                    CPIA2_VC_VC_CLOCKS_LOGDIV2);
-       }
-       i++;
-
-       DBG("VC_CLOCKS = 0x%X\n", cmd.buffer.registers[i-1].value);
-
-       /* Input width from VP */
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_IHSIZE_LO;
-       if (image_type == VIDEOSIZE_VGA)
-               cmd.buffer.registers[i].value =
-                   (u8) (STV_IMAGE_VGA_COLS / 4);
-       else
-               cmd.buffer.registers[i].value =
-                   (u8) (STV_IMAGE_QVGA_COLS / 4);
-       i++;
-       DBG("Input width = %d\n", cmd.buffer.registers[i-1].value);
-
-       /* Timings */
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_HI;
-       if (image_type == VIDEOSIZE_VGA)
-               cmd.buffer.registers[i++].value = (u8) 2;
-       else
-               cmd.buffer.registers[i++].value = (u8) 1;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_XLIM_LO;
-       if (image_type == VIDEOSIZE_VGA)
-               cmd.buffer.registers[i++].value = (u8) 250;
-       else if (image_type == VIDEOSIZE_QVGA)
-               cmd.buffer.registers[i++].value = (u8) 125;
-       else
-               cmd.buffer.registers[i++].value = (u8) 160;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_HI;
-       if (image_type == VIDEOSIZE_VGA)
-               cmd.buffer.registers[i++].value = (u8) 2;
-       else
-               cmd.buffer.registers[i++].value = (u8) 1;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_YLIM_LO;
-       if (image_type == VIDEOSIZE_VGA)
-               cmd.buffer.registers[i++].value = (u8) 12;
-       else if (image_type == VIDEOSIZE_QVGA)
-               cmd.buffer.registers[i++].value = (u8) 64;
-       else
-               cmd.buffer.registers[i++].value = (u8) 6;
-
-       /* Output Image Size */
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_OHSIZE;
-       if (image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value = STV_IMAGE_CIF_COLS  / 4;
-       else
-               cmd.buffer.registers[i++].value = width / 4;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_OVSIZE;
-       if (image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value = STV_IMAGE_CIF_ROWS  / 4;
-       else
-               cmd.buffer.registers[i++].value = height / 4;
-
-       /* Cropping */
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_HCROP;
-       if (image_type == VIDEOSIZE_VGA)
-               cmd.buffer.registers[i++].value =
-                   (u8) (((STV_IMAGE_VGA_COLS / 4) - (width / 4)) / 2);
-       else if (image_type == VIDEOSIZE_QVGA)
-               cmd.buffer.registers[i++].value =
-                   (u8) (((STV_IMAGE_QVGA_COLS / 4) - (width / 4)) / 2);
-       else if (image_type == VIDEOSIZE_CIF)
-               cmd.buffer.registers[i++].value =
-                   (u8) (((STV_IMAGE_CIF_COLS / 4) - (width / 4)) / 2);
-       else /*if (image_type == VIDEOSIZE_QCIF)*/
-               cmd.buffer.registers[i++].value =
-                       (u8) (((STV_IMAGE_QCIF_COLS / 4) - (width / 4)) / 2);
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_VCROP;
-       if (image_type == VIDEOSIZE_VGA)
-               cmd.buffer.registers[i++].value =
-                   (u8) (((STV_IMAGE_VGA_ROWS / 4) - (height / 4)) / 2);
-       else if (image_type == VIDEOSIZE_QVGA)
-               cmd.buffer.registers[i++].value =
-                   (u8) (((STV_IMAGE_QVGA_ROWS / 4) - (height / 4)) / 2);
-       else if (image_type == VIDEOSIZE_CIF)
-               cmd.buffer.registers[i++].value =
-                   (u8) (((STV_IMAGE_CIF_ROWS / 4) - (height / 4)) / 2);
-       else /*if (image_type == VIDEOSIZE_QCIF)*/
-               cmd.buffer.registers[i++].value =
-                   (u8) (((STV_IMAGE_QCIF_ROWS / 4) - (height / 4)) / 2);
-
-       /* Scaling registers (defaults) */
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_HPHASE;
-       if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value = (u8) 36;
-       else
-               cmd.buffer.registers[i++].value = (u8) 0;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_VPHASE;
-       if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value = (u8) 32;
-       else
-               cmd.buffer.registers[i++].value = (u8) 0;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_HISPAN;
-       if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value = (u8) 26;
-       else
-               cmd.buffer.registers[i++].value = (u8) 31;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_VISPAN;
-       if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value = (u8) 21;
-       else
-               cmd.buffer.registers[i++].value = (u8) 31;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_HICROP;
-       cmd.buffer.registers[i++].value = (u8) 0;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_VICROP;
-       cmd.buffer.registers[i++].value = (u8) 0;
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_HFRACT;
-       if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value = (u8) 0x2B;    /* 2/11 */
-       else
-               cmd.buffer.registers[i++].value = (u8) 0x81;    /* 8/1 */
-
-       cmd.buffer.registers[i].index = CPIA2_VC_VC_VFRACT;
-       if (image_type == VIDEOSIZE_CIF || image_type == VIDEOSIZE_QCIF)
-               cmd.buffer.registers[i++].value = (u8) 0x13;    /* 1/3 */
-       else
-               cmd.buffer.registers[i++].value = (u8) 0x81;    /* 8/1 */
-
-       cmd.reg_count = i;
-
-       cpia2_send_command(cam, &cmd);
-
-       return i;
-}
-
-
-/******************************************************************************
- *
- *  setallproperties
- *
- *  This sets all user changeable properties to the values in cam->params.
- *****************************************************************************/
-static int set_all_properties(struct camera_data *cam)
-{
-       /**
-        * Don't set target_kb here, it will be set later.
-        * framerate and user_mode were already set (set_default_user_mode).
-        **/
-
-       cpia2_usb_change_streaming_alternate(cam,
-                                         cam->params.camera_state.stream_mode);
-
-       cpia2_do_command(cam,
-                        CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION,
-                        TRANSFER_WRITE, cam->params.vp_params.gpio_direction);
-       cpia2_do_command(cam, CPIA2_CMD_SET_VC_MP_GPIO_DATA, TRANSFER_WRITE,
-                        cam->params.vp_params.gpio_data);
-
-       v4l2_ctrl_handler_setup(&cam->hdl);
-
-       wake_system(cam);
-
-       set_lowlight_boost(cam);
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  cpia2_save_camera_state
- *
- *****************************************************************************/
-void cpia2_save_camera_state(struct camera_data *cam)
-{
-       cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, TRANSFER_READ, 0);
-       cpia2_do_command(cam, CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION, TRANSFER_READ,
-                        0);
-       cpia2_do_command(cam, CPIA2_CMD_GET_VC_MP_GPIO_DATA, TRANSFER_READ, 0);
-       /* Don't get framerate or target_kb. Trust the values we already have */
-}
-
-
-/******************************************************************************
- *
- *  cpia2_set_flicker_mode
- *
- *****************************************************************************/
-int cpia2_set_flicker_mode(struct camera_data *cam, int mode)
-{
-       unsigned char cam_reg;
-       int err = 0;
-
-       if(cam->params.pnp_id.device_type != DEVICE_STV_672)
-               return -EINVAL;
-
-       /* Set the appropriate bits in FLICKER_MODES, preserving the rest */
-       if((err = cpia2_do_command(cam, CPIA2_CMD_GET_FLICKER_MODES,
-                                  TRANSFER_READ, 0)))
-               return err;
-       cam_reg = cam->params.flicker_control.cam_register;
-
-       switch(mode) {
-       case NEVER_FLICKER:
-               cam_reg |= CPIA2_VP_FLICKER_MODES_NEVER_FLICKER;
-               cam_reg &= ~CPIA2_VP_FLICKER_MODES_50HZ;
-               break;
-       case FLICKER_60:
-               cam_reg &= ~CPIA2_VP_FLICKER_MODES_NEVER_FLICKER;
-               cam_reg &= ~CPIA2_VP_FLICKER_MODES_50HZ;
-               break;
-       case FLICKER_50:
-               cam_reg &= ~CPIA2_VP_FLICKER_MODES_NEVER_FLICKER;
-               cam_reg |= CPIA2_VP_FLICKER_MODES_50HZ;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if((err = cpia2_do_command(cam, CPIA2_CMD_SET_FLICKER_MODES,
-                                  TRANSFER_WRITE, cam_reg)))
-               return err;
-
-       /* Set the appropriate bits in EXP_MODES, preserving the rest */
-       if((err = cpia2_do_command(cam, CPIA2_CMD_GET_VP_EXP_MODES,
-                                  TRANSFER_READ, 0)))
-               return err;
-       cam_reg = cam->params.vp_params.exposure_modes;
-
-       if (mode == NEVER_FLICKER) {
-               cam_reg |= CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER;
-       } else {
-               cam_reg &= ~CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER;
-       }
-
-       if((err = cpia2_do_command(cam, CPIA2_CMD_SET_VP_EXP_MODES,
-                                  TRANSFER_WRITE, cam_reg)))
-               return err;
-
-       if((err = cpia2_do_command(cam, CPIA2_CMD_REHASH_VP4,
-                                  TRANSFER_WRITE, 1)))
-               return err;
-
-       switch(mode) {
-       case NEVER_FLICKER:
-       case FLICKER_60:
-       case FLICKER_50:
-               cam->params.flicker_control.flicker_mode_req = mode;
-               break;
-       default:
-               err = -EINVAL;
-       }
-
-       return err;
-}
-
-/******************************************************************************
- *
- *  cpia2_set_property_flip
- *
- *****************************************************************************/
-void cpia2_set_property_flip(struct camera_data *cam, int prop_val)
-{
-       unsigned char cam_reg;
-
-       cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, TRANSFER_READ, 0);
-       cam_reg = cam->params.vp_params.user_effects;
-
-       if (prop_val)
-       {
-               cam_reg |= CPIA2_VP_USER_EFFECTS_FLIP;
-       }
-       else
-       {
-               cam_reg &= ~CPIA2_VP_USER_EFFECTS_FLIP;
-       }
-       cam->params.vp_params.user_effects = cam_reg;
-       cpia2_do_command(cam, CPIA2_CMD_SET_USER_EFFECTS, TRANSFER_WRITE,
-                        cam_reg);
-}
-
-/******************************************************************************
- *
- *  cpia2_set_property_mirror
- *
- *****************************************************************************/
-void cpia2_set_property_mirror(struct camera_data *cam, int prop_val)
-{
-       unsigned char cam_reg;
-
-       cpia2_do_command(cam, CPIA2_CMD_GET_USER_EFFECTS, TRANSFER_READ, 0);
-       cam_reg = cam->params.vp_params.user_effects;
-
-       if (prop_val)
-       {
-               cam_reg |= CPIA2_VP_USER_EFFECTS_MIRROR;
-       }
-       else
-       {
-               cam_reg &= ~CPIA2_VP_USER_EFFECTS_MIRROR;
-       }
-       cam->params.vp_params.user_effects = cam_reg;
-       cpia2_do_command(cam, CPIA2_CMD_SET_USER_EFFECTS, TRANSFER_WRITE,
-                        cam_reg);
-}
-
-/******************************************************************************
- *
- *  cpia2_set_gpio
- *
- *****************************************************************************/
-int cpia2_set_gpio(struct camera_data *cam, unsigned char setting)
-{
-       int ret;
-
-       /* Set the microport direction (register 0x90, should be defined
-        * already) to 1 (user output), and set the microport data (0x91) to
-        * the value in the ioctl argument.
-        */
-
-       ret = cpia2_do_command(cam,
-                              CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION,
-                              CPIA2_VC_MP_DIR_OUTPUT,
-                              255);
-       if (ret < 0)
-               return ret;
-       cam->params.vp_params.gpio_direction = 255;
-
-       ret = cpia2_do_command(cam,
-                              CPIA2_CMD_SET_VC_MP_GPIO_DATA,
-                              CPIA2_VC_MP_DIR_OUTPUT,
-                              setting);
-       if (ret < 0)
-               return ret;
-       cam->params.vp_params.gpio_data = setting;
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  cpia2_set_fps
- *
- *****************************************************************************/
-int cpia2_set_fps(struct camera_data *cam, int framerate)
-{
-       int retval;
-
-       switch(framerate) {
-               case CPIA2_VP_FRAMERATE_30:
-               case CPIA2_VP_FRAMERATE_25:
-                       if(cam->params.pnp_id.device_type == DEVICE_STV_672 &&
-                          cam->params.version.sensor_flags ==
-                                                   CPIA2_VP_SENSOR_FLAGS_500) {
-                               return -EINVAL;
-                       }
-                       /* Fall through */
-               case CPIA2_VP_FRAMERATE_15:
-               case CPIA2_VP_FRAMERATE_12_5:
-               case CPIA2_VP_FRAMERATE_7_5:
-               case CPIA2_VP_FRAMERATE_6_25:
-                       break;
-               default:
-                       return -EINVAL;
-       }
-
-       if (cam->params.pnp_id.device_type == DEVICE_STV_672 &&
-           framerate == CPIA2_VP_FRAMERATE_15)
-               framerate = 0; /* Work around bug in VP4 */
-
-       retval = cpia2_do_command(cam,
-                                CPIA2_CMD_FRAMERATE_REQ,
-                                TRANSFER_WRITE,
-                                framerate);
-
-       if(retval == 0)
-               cam->params.vp_params.frame_rate = framerate;
-
-       return retval;
-}
-
-/******************************************************************************
- *
- *  cpia2_set_brightness
- *
- *****************************************************************************/
-void cpia2_set_brightness(struct camera_data *cam, unsigned char value)
-{
-       /***
-        * Don't let the register be set to zero - bug in VP4 - flash of full
-        * brightness
-        ***/
-       if (cam->params.pnp_id.device_type == DEVICE_STV_672 && value == 0)
-               value++;
-       DBG("Setting brightness to %d (0x%0x)\n", value, value);
-       cpia2_do_command(cam, CPIA2_CMD_SET_VP_BRIGHTNESS, TRANSFER_WRITE, value);
-}
-
-/******************************************************************************
- *
- *  cpia2_set_contrast
- *
- *****************************************************************************/
-void cpia2_set_contrast(struct camera_data *cam, unsigned char value)
-{
-       DBG("Setting contrast to %d (0x%0x)\n", value, value);
-       cpia2_do_command(cam, CPIA2_CMD_SET_CONTRAST, TRANSFER_WRITE, value);
-}
-
-/******************************************************************************
- *
- *  cpia2_set_saturation
- *
- *****************************************************************************/
-void cpia2_set_saturation(struct camera_data *cam, unsigned char value)
-{
-       DBG("Setting saturation to %d (0x%0x)\n", value, value);
-       cpia2_do_command(cam,CPIA2_CMD_SET_VP_SATURATION, TRANSFER_WRITE,value);
-}
-
-/******************************************************************************
- *
- *  wake_system
- *
- *****************************************************************************/
-static void wake_system(struct camera_data *cam)
-{
-       cpia2_do_command(cam, CPIA2_CMD_SET_WAKEUP, TRANSFER_WRITE, 0);
-}
-
-/******************************************************************************
- *
- *  set_lowlight_boost
- *
- *  Valid for STV500 sensor only
- *****************************************************************************/
-static void set_lowlight_boost(struct camera_data *cam)
-{
-       struct cpia2_command cmd;
-
-       if (cam->params.pnp_id.device_type != DEVICE_STV_672 ||
-           cam->params.version.sensor_flags != CPIA2_VP_SENSOR_FLAGS_500)
-               return;
-
-       cmd.direction = TRANSFER_WRITE;
-       cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-       cmd.reg_count = 3;
-       cmd.start = CPIA2_VP_RAM_ADDR_H;
-
-       cmd.buffer.block_data[0] = 0;   /* High byte of address to write to */
-       cmd.buffer.block_data[1] = 0x59;        /* Low byte of address to write to */
-       cmd.buffer.block_data[2] = 0;   /* High byte of data to write */
-
-       cpia2_send_command(cam, &cmd);
-
-       if (cam->params.vp_params.lowlight_boost) {
-               cmd.buffer.block_data[0] = 0x02;        /* Low byte data to write */
-       } else {
-               cmd.buffer.block_data[0] = 0x06;
-       }
-       cmd.start = CPIA2_VP_RAM_DATA;
-       cmd.reg_count = 1;
-       cpia2_send_command(cam, &cmd);
-
-       /* Rehash the VP4 values */
-       cpia2_do_command(cam, CPIA2_CMD_REHASH_VP4, TRANSFER_WRITE, 1);
-}
-
-/******************************************************************************
- *
- *  cpia2_set_format
- *
- *  Assumes that new size is already set in param struct.
- *****************************************************************************/
-void cpia2_set_format(struct camera_data *cam)
-{
-       cam->flush = true;
-
-       cpia2_usb_stream_pause(cam);
-
-       /* reset camera to new size */
-       cpia2_set_low_power(cam);
-       cpia2_reset_camera(cam);
-       cam->flush = false;
-
-       cpia2_dbg_dump_registers(cam);
-
-       cpia2_usb_stream_resume(cam);
-}
-
-/******************************************************************************
- *
- * cpia2_dbg_dump_registers
- *
- *****************************************************************************/
-void cpia2_dbg_dump_registers(struct camera_data *cam)
-{
-#ifdef _CPIA2_DEBUG_
-       struct cpia2_command cmd;
-
-       if (!(debugs_on & DEBUG_DUMP_REGS))
-               return;
-
-       cmd.direction = TRANSFER_READ;
-
-       /* Start with bank 0 (SYSTEM) */
-       cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM;
-       cmd.reg_count = 3;
-       cmd.start = 0;
-       cpia2_send_command(cam, &cmd);
-       printk(KERN_DEBUG "System Device Hi      = 0x%X\n",
-              cmd.buffer.block_data[0]);
-       printk(KERN_DEBUG "System Device Lo      = 0x%X\n",
-              cmd.buffer.block_data[1]);
-       printk(KERN_DEBUG "System_system control = 0x%X\n",
-              cmd.buffer.block_data[2]);
-
-       /* Bank 1 (VC) */
-       cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
-       cmd.reg_count = 4;
-       cmd.start = 0x80;
-       cpia2_send_command(cam, &cmd);
-       printk(KERN_DEBUG "ASIC_ID       = 0x%X\n",
-              cmd.buffer.block_data[0]);
-       printk(KERN_DEBUG "ASIC_REV      = 0x%X\n",
-              cmd.buffer.block_data[1]);
-       printk(KERN_DEBUG "PW_CONTRL     = 0x%X\n",
-              cmd.buffer.block_data[2]);
-       printk(KERN_DEBUG "WAKEUP        = 0x%X\n",
-              cmd.buffer.block_data[3]);
-
-       cmd.start = 0xA0;       /* ST_CTRL */
-       cmd.reg_count = 1;
-       cpia2_send_command(cam, &cmd);
-       printk(KERN_DEBUG "Stream ctrl   = 0x%X\n",
-              cmd.buffer.block_data[0]);
-
-       cmd.start = 0xA4;       /* Stream status */
-       cpia2_send_command(cam, &cmd);
-       printk(KERN_DEBUG "Stream status = 0x%X\n",
-              cmd.buffer.block_data[0]);
-
-       cmd.start = 0xA8;       /* USB status */
-       cmd.reg_count = 3;
-       cpia2_send_command(cam, &cmd);
-       printk(KERN_DEBUG "USB_CTRL      = 0x%X\n",
-              cmd.buffer.block_data[0]);
-       printk(KERN_DEBUG "USB_STRM      = 0x%X\n",
-              cmd.buffer.block_data[1]);
-       printk(KERN_DEBUG "USB_STATUS    = 0x%X\n",
-              cmd.buffer.block_data[2]);
-
-       cmd.start = 0xAF;       /* USB settings */
-       cmd.reg_count = 1;
-       cpia2_send_command(cam, &cmd);
-       printk(KERN_DEBUG "USB settings  = 0x%X\n",
-              cmd.buffer.block_data[0]);
-
-       cmd.start = 0xC0;       /* VC stuff */
-       cmd.reg_count = 26;
-       cpia2_send_command(cam, &cmd);
-       printk(KERN_DEBUG "VC Control    = 0x%0X\n",
-              cmd.buffer.block_data[0]);
-       printk(KERN_DEBUG "VC Format     = 0x%0X\n",
-              cmd.buffer.block_data[3]);
-       printk(KERN_DEBUG "VC Clocks     = 0x%0X\n",
-              cmd.buffer.block_data[4]);
-       printk(KERN_DEBUG "VC IHSize     = 0x%0X\n",
-              cmd.buffer.block_data[5]);
-       printk(KERN_DEBUG "VC Xlim Hi    = 0x%0X\n",
-              cmd.buffer.block_data[6]);
-       printk(KERN_DEBUG "VC XLim Lo    = 0x%0X\n",
-              cmd.buffer.block_data[7]);
-       printk(KERN_DEBUG "VC YLim Hi    = 0x%0X\n",
-              cmd.buffer.block_data[8]);
-       printk(KERN_DEBUG "VC YLim Lo    = 0x%0X\n",
-              cmd.buffer.block_data[9]);
-       printk(KERN_DEBUG "VC OHSize     = 0x%0X\n",
-              cmd.buffer.block_data[10]);
-       printk(KERN_DEBUG "VC OVSize     = 0x%0X\n",
-              cmd.buffer.block_data[11]);
-       printk(KERN_DEBUG "VC HCrop      = 0x%0X\n",
-              cmd.buffer.block_data[12]);
-       printk(KERN_DEBUG "VC VCrop      = 0x%0X\n",
-              cmd.buffer.block_data[13]);
-       printk(KERN_DEBUG "VC HPhase     = 0x%0X\n",
-              cmd.buffer.block_data[14]);
-       printk(KERN_DEBUG "VC VPhase     = 0x%0X\n",
-              cmd.buffer.block_data[15]);
-       printk(KERN_DEBUG "VC HIspan     = 0x%0X\n",
-              cmd.buffer.block_data[16]);
-       printk(KERN_DEBUG "VC VIspan     = 0x%0X\n",
-              cmd.buffer.block_data[17]);
-       printk(KERN_DEBUG "VC HiCrop     = 0x%0X\n",
-              cmd.buffer.block_data[18]);
-       printk(KERN_DEBUG "VC ViCrop     = 0x%0X\n",
-              cmd.buffer.block_data[19]);
-       printk(KERN_DEBUG "VC HiFract    = 0x%0X\n",
-              cmd.buffer.block_data[20]);
-       printk(KERN_DEBUG "VC ViFract    = 0x%0X\n",
-              cmd.buffer.block_data[21]);
-       printk(KERN_DEBUG "VC JPeg Opt   = 0x%0X\n",
-              cmd.buffer.block_data[22]);
-       printk(KERN_DEBUG "VC Creep Per  = 0x%0X\n",
-              cmd.buffer.block_data[23]);
-       printk(KERN_DEBUG "VC User Sq.   = 0x%0X\n",
-              cmd.buffer.block_data[24]);
-       printk(KERN_DEBUG "VC Target KB  = 0x%0X\n",
-              cmd.buffer.block_data[25]);
-
-       /*** VP ***/
-       cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP;
-       cmd.reg_count = 14;
-       cmd.start = 0;
-       cpia2_send_command(cam, &cmd);
-
-       printk(KERN_DEBUG "VP Dev Hi     = 0x%0X\n",
-              cmd.buffer.block_data[0]);
-       printk(KERN_DEBUG "VP Dev Lo     = 0x%0X\n",
-              cmd.buffer.block_data[1]);
-       printk(KERN_DEBUG "VP Sys State  = 0x%0X\n",
-              cmd.buffer.block_data[2]);
-       printk(KERN_DEBUG "VP Sys Ctrl   = 0x%0X\n",
-              cmd.buffer.block_data[3]);
-       printk(KERN_DEBUG "VP Sensor flg = 0x%0X\n",
-              cmd.buffer.block_data[5]);
-       printk(KERN_DEBUG "VP Sensor Rev = 0x%0X\n",
-              cmd.buffer.block_data[6]);
-       printk(KERN_DEBUG "VP Dev Config = 0x%0X\n",
-              cmd.buffer.block_data[7]);
-       printk(KERN_DEBUG "VP GPIO_DIR   = 0x%0X\n",
-              cmd.buffer.block_data[8]);
-       printk(KERN_DEBUG "VP GPIO_DATA  = 0x%0X\n",
-              cmd.buffer.block_data[9]);
-       printk(KERN_DEBUG "VP Ram ADDR H = 0x%0X\n",
-              cmd.buffer.block_data[10]);
-       printk(KERN_DEBUG "VP Ram ADDR L = 0x%0X\n",
-              cmd.buffer.block_data[11]);
-       printk(KERN_DEBUG "VP RAM Data   = 0x%0X\n",
-              cmd.buffer.block_data[12]);
-       printk(KERN_DEBUG "Do Call       = 0x%0X\n",
-              cmd.buffer.block_data[13]);
-
-       if (cam->params.pnp_id.device_type == DEVICE_STV_672) {
-               cmd.reg_count = 9;
-               cmd.start = 0x0E;
-               cpia2_send_command(cam, &cmd);
-               printk(KERN_DEBUG "VP Clock Ctrl = 0x%0X\n",
-                      cmd.buffer.block_data[0]);
-               printk(KERN_DEBUG "VP Patch Rev  = 0x%0X\n",
-                      cmd.buffer.block_data[1]);
-               printk(KERN_DEBUG "VP Vid Mode   = 0x%0X\n",
-                      cmd.buffer.block_data[2]);
-               printk(KERN_DEBUG "VP Framerate  = 0x%0X\n",
-                      cmd.buffer.block_data[3]);
-               printk(KERN_DEBUG "VP UserEffect = 0x%0X\n",
-                      cmd.buffer.block_data[4]);
-               printk(KERN_DEBUG "VP White Bal  = 0x%0X\n",
-                      cmd.buffer.block_data[5]);
-               printk(KERN_DEBUG "VP WB thresh  = 0x%0X\n",
-                      cmd.buffer.block_data[6]);
-               printk(KERN_DEBUG "VP Exp Modes  = 0x%0X\n",
-                      cmd.buffer.block_data[7]);
-               printk(KERN_DEBUG "VP Exp Target = 0x%0X\n",
-                      cmd.buffer.block_data[8]);
-
-               cmd.reg_count = 1;
-               cmd.start = 0x1B;
-               cpia2_send_command(cam, &cmd);
-               printk(KERN_DEBUG "VP FlickerMds = 0x%0X\n",
-                      cmd.buffer.block_data[0]);
-       } else {
-               cmd.reg_count = 8 ;
-               cmd.start = 0x0E;
-               cpia2_send_command(cam, &cmd);
-               printk(KERN_DEBUG "VP Clock Ctrl = 0x%0X\n",
-                      cmd.buffer.block_data[0]);
-               printk(KERN_DEBUG "VP Patch Rev  = 0x%0X\n",
-                      cmd.buffer.block_data[1]);
-               printk(KERN_DEBUG "VP Vid Mode   = 0x%0X\n",
-                      cmd.buffer.block_data[5]);
-               printk(KERN_DEBUG "VP Framerate  = 0x%0X\n",
-                      cmd.buffer.block_data[6]);
-               printk(KERN_DEBUG "VP UserEffect = 0x%0X\n",
-                      cmd.buffer.block_data[7]);
-
-               cmd.reg_count = 1;
-               cmd.start = CPIA2_VP5_EXPOSURE_TARGET;
-               cpia2_send_command(cam, &cmd);
-               printk(KERN_DEBUG "VP5 Exp Target= 0x%0X\n",
-                      cmd.buffer.block_data[0]);
-
-               cmd.reg_count = 4;
-               cmd.start = 0x3A;
-               cpia2_send_command(cam, &cmd);
-               printk(KERN_DEBUG "VP5 MY Black  = 0x%0X\n",
-                      cmd.buffer.block_data[0]);
-               printk(KERN_DEBUG "VP5 MCY Range = 0x%0X\n",
-                      cmd.buffer.block_data[1]);
-               printk(KERN_DEBUG "VP5 MYCEILING = 0x%0X\n",
-                      cmd.buffer.block_data[2]);
-               printk(KERN_DEBUG "VP5 MCUV Sat  = 0x%0X\n",
-                      cmd.buffer.block_data[3]);
-       }
-#endif
-}
-
-/******************************************************************************
- *
- *  reset_camera_struct
- *
- *  Sets all values to the defaults
- *****************************************************************************/
-static void reset_camera_struct(struct camera_data *cam)
-{
-       /***
-        * The following parameter values are the defaults from the register map.
-        ***/
-       cam->params.vp_params.lowlight_boost = 0;
-
-       /* FlickerModes */
-       cam->params.flicker_control.flicker_mode_req = NEVER_FLICKER;
-
-       /* jpeg params */
-       cam->params.compression.jpeg_options = CPIA2_VC_VC_JPEG_OPT_DEFAULT;
-       cam->params.compression.creep_period = 2;
-       cam->params.compression.user_squeeze = 20;
-       cam->params.compression.inhibit_htables = false;
-
-       /* gpio params */
-       cam->params.vp_params.gpio_direction = 0;       /* write, the default safe mode */
-       cam->params.vp_params.gpio_data = 0;
-
-       /* Target kb params */
-       cam->params.vc_params.quality = 100;
-
-       /***
-        * Set Sensor FPS as fast as possible.
-        ***/
-       if(cam->params.pnp_id.device_type == DEVICE_STV_672) {
-               if(cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500)
-                       cam->params.vp_params.frame_rate = CPIA2_VP_FRAMERATE_15;
-               else
-                       cam->params.vp_params.frame_rate = CPIA2_VP_FRAMERATE_30;
-       } else {
-               cam->params.vp_params.frame_rate = CPIA2_VP_FRAMERATE_30;
-       }
-
-       /***
-        * Set default video mode as large as possible :
-        * for vga sensor set to vga, for cif sensor set to CIF.
-        ***/
-       if (cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500) {
-               cam->sensor_type = CPIA2_SENSOR_500;
-               cam->video_size = VIDEOSIZE_VGA;
-               cam->params.roi.width = STV_IMAGE_VGA_COLS;
-               cam->params.roi.height = STV_IMAGE_VGA_ROWS;
-       } else {
-               cam->sensor_type = CPIA2_SENSOR_410;
-               cam->video_size = VIDEOSIZE_CIF;
-               cam->params.roi.width = STV_IMAGE_CIF_COLS;
-               cam->params.roi.height = STV_IMAGE_CIF_ROWS;
-       }
-
-       cam->width = cam->params.roi.width;
-       cam->height = cam->params.roi.height;
-}
-
-/******************************************************************************
- *
- *  cpia2_init_camera_struct
- *
- *  Initializes camera struct, does not call reset to fill in defaults.
- *****************************************************************************/
-struct camera_data *cpia2_init_camera_struct(struct usb_interface *intf)
-{
-       struct camera_data *cam;
-
-       cam = kzalloc(sizeof(*cam), GFP_KERNEL);
-
-       if (!cam) {
-               ERR("couldn't kmalloc cpia2 struct\n");
-               return NULL;
-       }
-
-       cam->v4l2_dev.release = cpia2_camera_release;
-       if (v4l2_device_register(&intf->dev, &cam->v4l2_dev) < 0) {
-               v4l2_err(&cam->v4l2_dev, "couldn't register v4l2_device\n");
-               kfree(cam);
-               return NULL;
-       }
-
-       mutex_init(&cam->v4l2_lock);
-       init_waitqueue_head(&cam->wq_stream);
-
-       return cam;
-}
-
-/******************************************************************************
- *
- *  cpia2_init_camera
- *
- *  Initializes camera.
- *****************************************************************************/
-int cpia2_init_camera(struct camera_data *cam)
-{
-       DBG("Start\n");
-
-       cam->mmapped = false;
-
-       /* Get sensor and asic types before reset. */
-       cpia2_set_high_power(cam);
-       cpia2_get_version_info(cam);
-       if (cam->params.version.asic_id != CPIA2_ASIC_672) {
-               ERR("Device IO error (asicID has incorrect value of 0x%X\n",
-                   cam->params.version.asic_id);
-               return -ENODEV;
-       }
-
-       /* Set GPIO direction and data to a safe state. */
-       cpia2_do_command(cam, CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION,
-                        TRANSFER_WRITE, 0);
-       cpia2_do_command(cam, CPIA2_CMD_SET_VC_MP_GPIO_DATA,
-                        TRANSFER_WRITE, 0);
-
-       /* resetting struct requires version info for sensor and asic types */
-       reset_camera_struct(cam);
-
-       cpia2_set_low_power(cam);
-
-       DBG("End\n");
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  cpia2_allocate_buffers
- *
- *****************************************************************************/
-int cpia2_allocate_buffers(struct camera_data *cam)
-{
-       int i;
-
-       if(!cam->buffers) {
-               u32 size = cam->num_frames*sizeof(struct framebuf);
-               cam->buffers = kmalloc(size, GFP_KERNEL);
-               if(!cam->buffers) {
-                       ERR("couldn't kmalloc frame buffer structures\n");
-                       return -ENOMEM;
-               }
-       }
-
-       if(!cam->frame_buffer) {
-               cam->frame_buffer = rvmalloc(cam->frame_size*cam->num_frames);
-               if (!cam->frame_buffer) {
-                       ERR("couldn't vmalloc frame buffer data area\n");
-                       kfree(cam->buffers);
-                       cam->buffers = NULL;
-                       return -ENOMEM;
-               }
-       }
-
-       for(i=0; i<cam->num_frames-1; ++i) {
-               cam->buffers[i].next = &cam->buffers[i+1];
-               cam->buffers[i].data = cam->frame_buffer +i*cam->frame_size;
-               cam->buffers[i].status = FRAME_EMPTY;
-               cam->buffers[i].length = 0;
-               cam->buffers[i].max_length = 0;
-               cam->buffers[i].num = i;
-       }
-       cam->buffers[i].next = cam->buffers;
-       cam->buffers[i].data = cam->frame_buffer +i*cam->frame_size;
-       cam->buffers[i].status = FRAME_EMPTY;
-       cam->buffers[i].length = 0;
-       cam->buffers[i].max_length = 0;
-       cam->buffers[i].num = i;
-       cam->curbuff = cam->buffers;
-       cam->workbuff = cam->curbuff->next;
-       DBG("buffers=%p, curbuff=%p, workbuff=%p\n", cam->buffers, cam->curbuff,
-           cam->workbuff);
-       return 0;
-}
-
-/******************************************************************************
- *
- *  cpia2_free_buffers
- *
- *****************************************************************************/
-void cpia2_free_buffers(struct camera_data *cam)
-{
-       if(cam->buffers) {
-               kfree(cam->buffers);
-               cam->buffers = NULL;
-       }
-       if(cam->frame_buffer) {
-               rvfree(cam->frame_buffer, cam->frame_size*cam->num_frames);
-               cam->frame_buffer = NULL;
-       }
-}
-
-/******************************************************************************
- *
- *  cpia2_read
- *
- *****************************************************************************/
-long cpia2_read(struct camera_data *cam,
-               char __user *buf, unsigned long count, int noblock)
-{
-       struct framebuf *frame;
-
-       if (!count)
-               return 0;
-
-       if (!buf) {
-               ERR("%s: buffer NULL\n",__func__);
-               return -EINVAL;
-       }
-
-       if (!cam) {
-               ERR("%s: Internal error, camera_data NULL!\n",__func__);
-               return -EINVAL;
-       }
-
-       if (!cam->streaming) {
-               /* Start streaming */
-               cpia2_usb_stream_start(cam,
-                                      cam->params.camera_state.stream_mode);
-       }
-
-       /* Copy cam->curbuff in case it changes while we're processing */
-       frame = cam->curbuff;
-       if (noblock && frame->status != FRAME_READY) {
-               return -EAGAIN;
-       }
-
-       if (frame->status != FRAME_READY) {
-               mutex_unlock(&cam->v4l2_lock);
-               wait_event_interruptible(cam->wq_stream,
-                              !video_is_registered(&cam->vdev) ||
-                              (frame = cam->curbuff)->status == FRAME_READY);
-               mutex_lock(&cam->v4l2_lock);
-               if (signal_pending(current))
-                       return -ERESTARTSYS;
-               if (!video_is_registered(&cam->vdev))
-                       return 0;
-       }
-
-       /* copy data to user space */
-       if (frame->length > count)
-               return -EFAULT;
-       if (copy_to_user(buf, frame->data, frame->length))
-               return -EFAULT;
-
-       count = frame->length;
-
-       frame->status = FRAME_EMPTY;
-
-       return count;
-}
-
-/******************************************************************************
- *
- *  cpia2_poll
- *
- *****************************************************************************/
-unsigned int cpia2_poll(struct camera_data *cam, struct file *filp,
-                       poll_table *wait)
-{
-       unsigned int status = v4l2_ctrl_poll(filp, wait);
-
-       if ((poll_requested_events(wait) & (POLLIN | POLLRDNORM)) &&
-                       !cam->streaming) {
-               /* Start streaming */
-               cpia2_usb_stream_start(cam,
-                                      cam->params.camera_state.stream_mode);
-       }
-
-       poll_wait(filp, &cam->wq_stream, wait);
-
-       if (cam->curbuff->status == FRAME_READY)
-               status |= POLLIN | POLLRDNORM;
-
-       return status;
-}
-
-/******************************************************************************
- *
- *  cpia2_remap_buffer
- *
- *****************************************************************************/
-int cpia2_remap_buffer(struct camera_data *cam, struct vm_area_struct *vma)
-{
-       const char *adr = (const char *)vma->vm_start;
-       unsigned long size = vma->vm_end-vma->vm_start;
-       unsigned long start_offset = vma->vm_pgoff << PAGE_SHIFT;
-       unsigned long start = (unsigned long) adr;
-       unsigned long page, pos;
-
-       DBG("mmap offset:%ld size:%ld\n", start_offset, size);
-
-       if (!video_is_registered(&cam->vdev))
-               return -ENODEV;
-
-       if (size > cam->frame_size*cam->num_frames  ||
-           (start_offset % cam->frame_size) != 0 ||
-           (start_offset+size > cam->frame_size*cam->num_frames))
-               return -EINVAL;
-
-       pos = ((unsigned long) (cam->frame_buffer)) + start_offset;
-       while (size > 0) {
-               page = kvirt_to_pa(pos);
-               if (remap_pfn_range(vma, start, page >> PAGE_SHIFT, PAGE_SIZE, PAGE_SHARED))
-                       return -EAGAIN;
-               start += PAGE_SIZE;
-               pos += PAGE_SIZE;
-               if (size > PAGE_SIZE)
-                       size -= PAGE_SIZE;
-               else
-                       size = 0;
-       }
-
-       cam->mmapped = true;
-       return 0;
-}
diff --git a/drivers/media/video/cpia2/cpia2_registers.h b/drivers/media/video/cpia2/cpia2_registers.h
deleted file mode 100644 (file)
index 3bbec51..0000000
+++ /dev/null
@@ -1,476 +0,0 @@
-/****************************************************************************
- *
- *  Filename: cpia2registers.h
- *
- *  Copyright 2001, STMicrolectronics, Inc.
- *
- *  Description:
- *     Definitions for the CPia2 register set
- *
- *  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.
- *
- ****************************************************************************/
-
-#ifndef CPIA2_REGISTER_HEADER
-#define CPIA2_REGISTER_HEADER
-
-/***
- * System register set (Bank 0)
- ***/
-#define CPIA2_SYSTEM_DEVICE_HI                     0x00
-#define CPIA2_SYSTEM_DEVICE_LO                     0x01
-
-#define CPIA2_SYSTEM_SYSTEM_CONTROL                0x02
-#define CPIA2_SYSTEM_CONTROL_LOW_POWER       0x00
-#define CPIA2_SYSTEM_CONTROL_HIGH_POWER      0x01
-#define CPIA2_SYSTEM_CONTROL_SUSPEND         0x02
-#define CPIA2_SYSTEM_CONTROL_V2W_ERR         0x10
-#define CPIA2_SYSTEM_CONTROL_RB_ERR          0x10
-#define CPIA2_SYSTEM_CONTROL_CLEAR_ERR       0x80
-
-#define CPIA2_SYSTEM_INT_PACKET_CTRL                0x04
-#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_SW_XX 0x01
-#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_EOF   0x02
-#define CPIA2_SYSTEM_INT_PACKET_CTRL_ENABLE_INT1  0x04
-
-#define CPIA2_SYSTEM_CACHE_CTRL                     0x05
-#define CPIA2_SYSTEM_CACHE_CTRL_CACHE_RESET      0x01
-#define CPIA2_SYSTEM_CACHE_CTRL_CACHE_FLUSH      0x02
-
-#define CPIA2_SYSTEM_SERIAL_CTRL                    0x06
-#define CPIA2_SYSTEM_SERIAL_CTRL_NULL_CMD        0x00
-#define CPIA2_SYSTEM_SERIAL_CTRL_START_CMD       0x01
-#define CPIA2_SYSTEM_SERIAL_CTRL_STOP_CMD        0x02
-#define CPIA2_SYSTEM_SERIAL_CTRL_WRITE_CMD       0x03
-#define CPIA2_SYSTEM_SERIAL_CTRL_READ_ACK_CMD    0x04
-#define CPIA2_SYSTEM_SERIAL_CTRL_READ_NACK_CMD   0x05
-
-#define CPIA2_SYSTEM_SERIAL_DATA                     0x07
-
-#define CPIA2_SYSTEM_VP_SERIAL_ADDR                  0x08
-
-/***
- * I2C addresses for various devices in CPiA2
- ***/
-#define CPIA2_SYSTEM_VP_SERIAL_ADDR_SENSOR           0x20
-#define CPIA2_SYSTEM_VP_SERIAL_ADDR_VP               0x88
-#define CPIA2_SYSTEM_VP_SERIAL_ADDR_676_VP           0x8A
-
-#define CPIA2_SYSTEM_SPARE_REG1                      0x09
-#define CPIA2_SYSTEM_SPARE_REG2                      0x0A
-#define CPIA2_SYSTEM_SPARE_REG3                      0x0B
-
-#define CPIA2_SYSTEM_MC_PORT_0                       0x0C
-#define CPIA2_SYSTEM_MC_PORT_1                       0x0D
-#define CPIA2_SYSTEM_MC_PORT_2                       0x0E
-#define CPIA2_SYSTEM_MC_PORT_3                       0x0F
-
-#define CPIA2_SYSTEM_STATUS_PKT                      0x20
-#define CPIA2_SYSTEM_STATUS_PKT_END                  0x27
-
-#define CPIA2_SYSTEM_DESCRIP_VID_HI                  0x30
-#define CPIA2_SYSTEM_DESCRIP_VID_LO                  0x31
-#define CPIA2_SYSTEM_DESCRIP_PID_HI                  0x32
-#define CPIA2_SYSTEM_DESCRIP_PID_LO                  0x33
-
-#define CPIA2_SYSTEM_FW_VERSION_HI                   0x34
-#define CPIA2_SYSTEM_FW_VERSION_LO                   0x35
-
-#define CPIA2_SYSTEM_CACHE_START_INDEX               0x80
-#define CPIA2_SYSTEM_CACHE_MAX_WRITES                0x10
-
-/***
- * VC register set (Bank 1)
- ***/
-#define CPIA2_VC_ASIC_ID                 0x80
-
-#define CPIA2_VC_ASIC_REV                0x81
-
-#define CPIA2_VC_PW_CTRL                 0x82
-#define CPIA2_VC_PW_CTRL_COLDSTART      0x01
-#define CPIA2_VC_PW_CTRL_CP_CLK_EN      0x02
-#define CPIA2_VC_PW_CTRL_VP_RESET_N     0x04
-#define CPIA2_VC_PW_CTRL_VC_CLK_EN      0x08
-#define CPIA2_VC_PW_CTRL_VC_RESET_N     0x10
-#define CPIA2_VC_PW_CTRL_GOTO_SUSPEND   0x20
-#define CPIA2_VC_PW_CTRL_UDC_SUSPEND    0x40
-#define CPIA2_VC_PW_CTRL_PWR_DOWN       0x80
-
-#define CPIA2_VC_WAKEUP                   0x83
-#define CPIA2_VC_WAKEUP_SW_ENABLE       0x01
-#define CPIA2_VC_WAKEUP_XX_ENABLE       0x02
-#define CPIA2_VC_WAKEUP_SW_ATWAKEUP     0x04
-#define CPIA2_VC_WAKEUP_XX_ATWAKEUP     0x08
-
-#define CPIA2_VC_CLOCK_CTRL               0x84
-#define CPIA2_VC_CLOCK_CTRL_TESTUP72    0x01
-
-#define CPIA2_VC_INT_ENABLE                0x88
-#define CPIA2_VC_INT_ENABLE_XX_IE       0x01
-#define CPIA2_VC_INT_ENABLE_SW_IE       0x02
-#define CPIA2_VC_INT_ENABLE_VC_IE       0x04
-#define CPIA2_VC_INT_ENABLE_USBDATA_IE  0x08
-#define CPIA2_VC_INT_ENABLE_USBSETUP_IE 0x10
-#define CPIA2_VC_INT_ENABLE_USBCFG_IE   0x20
-
-#define CPIA2_VC_INT_FLAG                  0x89
-#define CPIA2_VC_INT_ENABLE_XX_FLAG       0x01
-#define CPIA2_VC_INT_ENABLE_SW_FLAG       0x02
-#define CPIA2_VC_INT_ENABLE_VC_FLAG       0x04
-#define CPIA2_VC_INT_ENABLE_USBDATA_FLAG  0x08
-#define CPIA2_VC_INT_ENABLE_USBSETUP_FLAG 0x10
-#define CPIA2_VC_INT_ENABLE_USBCFG_FLAG   0x20
-#define CPIA2_VC_INT_ENABLE_SET_RESET_BIT 0x80
-
-#define CPIA2_VC_INT_STATE                 0x8A
-#define CPIA2_VC_INT_STATE_XX_STATE     0x01
-#define CPIA2_VC_INT_STATE_SW_STATE     0x02
-
-#define CPIA2_VC_MP_DIR                    0x90
-#define CPIA2_VC_MP_DIR_INPUT           0x00
-#define CPIA2_VC_MP_DIR_OUTPUT          0x01
-
-#define CPIA2_VC_MP_DATA                   0x91
-
-#define CPIA2_VC_DP_CTRL                   0x98
-#define CPIA2_VC_DP_CTRL_MODE_0         0x00
-#define CPIA2_VC_DP_CTRL_MODE_A         0x01
-#define CPIA2_VC_DP_CTRL_MODE_B         0x02
-#define CPIA2_VC_DP_CTRL_MODE_C         0x03
-#define CPIA2_VC_DP_CTRL_FAKE_FST       0x04
-
-#define CPIA2_VC_AD_CTRL                   0x99
-#define CPIA2_VC_AD_CTRL_SRC_0          0x00
-#define CPIA2_VC_AD_CTRL_SRC_DIGI_A     0x01
-#define CPIA2_VC_AD_CTRL_SRC_REG        0x02
-#define CPIA2_VC_AD_CTRL_DST_USB        0x00
-#define CPIA2_VC_AD_CTRL_DST_REG        0x04
-
-#define CPIA2_VC_AD_TEST_IN                0x9B
-
-#define CPIA2_VC_AD_TEST_OUT               0x9C
-
-#define CPIA2_VC_AD_STATUS                 0x9D
-#define CPIA2_VC_AD_STATUS_EMPTY        0x01
-#define CPIA2_VC_AD_STATUS_FULL         0x02
-
-#define CPIA2_VC_DP_DATA                   0x9E
-
-#define CPIA2_VC_ST_CTRL                   0xA0
-#define CPIA2_VC_ST_CTRL_SRC_VC         0x00
-#define CPIA2_VC_ST_CTRL_SRC_DP         0x01
-#define CPIA2_VC_ST_CTRL_SRC_REG        0x02
-
-#define CPIA2_VC_ST_CTRL_RAW_SELECT     0x04
-
-#define CPIA2_VC_ST_CTRL_DST_USB        0x00
-#define CPIA2_VC_ST_CTRL_DST_DP         0x08
-#define CPIA2_VC_ST_CTRL_DST_REG        0x10
-
-#define CPIA2_VC_ST_CTRL_FIFO_ENABLE    0x20
-#define CPIA2_VC_ST_CTRL_EOF_DETECT     0x40
-
-#define CPIA2_VC_ST_TEST                   0xA1
-#define CPIA2_VC_ST_TEST_MODE_MANUAL    0x00
-#define CPIA2_VC_ST_TEST_MODE_INCREMENT 0x02
-
-#define CPIA2_VC_ST_TEST_AUTO_FILL      0x08
-
-#define CPIA2_VC_ST_TEST_REPEAT_FIFO    0x10
-
-#define CPIA2_VC_ST_TEST_IN                0xA2
-
-#define CPIA2_VC_ST_TEST_OUT               0xA3
-
-#define CPIA2_VC_ST_STATUS                 0xA4
-#define CPIA2_VC_ST_STATUS_EMPTY        0x01
-#define CPIA2_VC_ST_STATUS_FULL         0x02
-
-#define CPIA2_VC_ST_FRAME_DETECT_1         0xA5
-
-#define CPIA2_VC_ST_FRAME_DETECT_2         0xA6
-
-#define CPIA2_VC_USB_CTRL                    0xA8
-#define CPIA2_VC_USB_CTRL_CMD_STALLED      0x01
-#define CPIA2_VC_USB_CTRL_CMD_READY        0x02
-#define CPIA2_VC_USB_CTRL_CMD_STATUS       0x04
-#define CPIA2_VC_USB_CTRL_CMD_STATUS_DIR   0x08
-#define CPIA2_VC_USB_CTRL_CMD_NO_CLASH     0x10
-#define CPIA2_VC_USB_CTRL_CMD_MICRO_ACCESS 0x80
-
-#define CPIA2_VC_USB_STRM                  0xA9
-#define CPIA2_VC_USB_STRM_ISO_ENABLE    0x01
-#define CPIA2_VC_USB_STRM_BLK_ENABLE    0x02
-#define CPIA2_VC_USB_STRM_INT_ENABLE    0x04
-#define CPIA2_VC_USB_STRM_AUD_ENABLE    0x08
-
-#define CPIA2_VC_USB_STATUS                   0xAA
-#define CPIA2_VC_USB_STATUS_CMD_IN_PROGRESS  0x01
-#define CPIA2_VC_USB_STATUS_CMD_STATUS_STALL 0x02
-#define CPIA2_VC_USB_STATUS_CMD_HANDSHAKE    0x04
-#define CPIA2_VC_USB_STATUS_CMD_OVERRIDE     0x08
-#define CPIA2_VC_USB_STATUS_CMD_FIFO_BUSY    0x10
-#define CPIA2_VC_USB_STATUS_BULK_REPEAT_TXN  0x20
-#define CPIA2_VC_USB_STATUS_CONFIG_DONE      0x40
-#define CPIA2_VC_USB_STATUS_USB_SUSPEND      0x80
-
-#define CPIA2_VC_USB_CMDW                   0xAB
-
-#define CPIA2_VC_USB_DATARW                 0xAC
-
-#define CPIA2_VC_USB_INFO                   0xAD
-
-#define CPIA2_VC_USB_CONFIG                 0xAE
-
-#define CPIA2_VC_USB_SETTINGS                  0xAF
-#define CPIA2_VC_USB_SETTINGS_CONFIG_MASK    0x03
-#define CPIA2_VC_USB_SETTINGS_INTERFACE_MASK 0x0C
-#define CPIA2_VC_USB_SETTINGS_ALTERNATE_MASK 0x70
-
-#define CPIA2_VC_USB_ISOLIM                  0xB0
-
-#define CPIA2_VC_USB_ISOFAILS                0xB1
-
-#define CPIA2_VC_USB_ISOMAXPKTHI             0xB2
-
-#define CPIA2_VC_USB_ISOMAXPKTLO             0xB3
-
-#define CPIA2_VC_V2W_CTRL                    0xB8
-#define CPIA2_VC_V2W_SELECT               0x01
-
-#define CPIA2_VC_V2W_SCL                     0xB9
-
-#define CPIA2_VC_V2W_SDA                     0xBA
-
-#define CPIA2_VC_VC_CTRL                     0xC0
-#define CPIA2_VC_VC_CTRL_RUN              0x01
-#define CPIA2_VC_VC_CTRL_SINGLESHOT       0x02
-#define CPIA2_VC_VC_CTRL_IDLING           0x04
-#define CPIA2_VC_VC_CTRL_INHIBIT_H_TABLES 0x10
-#define CPIA2_VC_VC_CTRL_INHIBIT_Q_TABLES 0x20
-#define CPIA2_VC_VC_CTRL_INHIBIT_PRIVATE  0x40
-
-#define CPIA2_VC_VC_RESTART_IVAL_HI          0xC1
-
-#define CPIA2_VC_VC_RESTART_IVAL_LO          0xC2
-
-#define CPIA2_VC_VC_FORMAT                   0xC3
-#define CPIA2_VC_VC_FORMAT_UFIRST         0x01
-#define CPIA2_VC_VC_FORMAT_MONO           0x02
-#define CPIA2_VC_VC_FORMAT_DECIMATING     0x04
-#define CPIA2_VC_VC_FORMAT_SHORTLINE      0x08
-#define CPIA2_VC_VC_FORMAT_SELFTEST       0x10
-
-#define CPIA2_VC_VC_CLOCKS                         0xC4
-#define CPIA2_VC_VC_CLOCKS_CLKDIV_MASK        0x03
-#define CPIA2_VC_VC_672_CLOCKS_CIF_DIV_BY_3   0x04
-#define CPIA2_VC_VC_672_CLOCKS_SCALING        0x08
-#define CPIA2_VC_VC_CLOCKS_LOGDIV0        0x00
-#define CPIA2_VC_VC_CLOCKS_LOGDIV1        0x01
-#define CPIA2_VC_VC_CLOCKS_LOGDIV2        0x02
-#define CPIA2_VC_VC_CLOCKS_LOGDIV3        0x03
-#define CPIA2_VC_VC_676_CLOCKS_CIF_DIV_BY_3   0x08
-#define CPIA2_VC_VC_676_CLOCKS_SCALING       0x10
-
-#define CPIA2_VC_VC_IHSIZE_LO                0xC5
-
-#define CPIA2_VC_VC_XLIM_HI                  0xC6
-
-#define CPIA2_VC_VC_XLIM_LO                  0xC7
-
-#define CPIA2_VC_VC_YLIM_HI                  0xC8
-
-#define CPIA2_VC_VC_YLIM_LO                  0xC9
-
-#define CPIA2_VC_VC_OHSIZE                   0xCA
-
-#define CPIA2_VC_VC_OVSIZE                   0xCB
-
-#define CPIA2_VC_VC_HCROP                    0xCC
-
-#define CPIA2_VC_VC_VCROP                    0xCD
-
-#define CPIA2_VC_VC_HPHASE                   0xCE
-
-#define CPIA2_VC_VC_VPHASE                   0xCF
-
-#define CPIA2_VC_VC_HISPAN                   0xD0
-
-#define CPIA2_VC_VC_VISPAN                   0xD1
-
-#define CPIA2_VC_VC_HICROP                   0xD2
-
-#define CPIA2_VC_VC_VICROP                   0xD3
-
-#define CPIA2_VC_VC_HFRACT                   0xD4
-#define CPIA2_VC_VC_HFRACT_DEN_MASK       0x0F
-#define CPIA2_VC_VC_HFRACT_NUM_MASK       0xF0
-
-#define CPIA2_VC_VC_VFRACT                   0xD5
-#define CPIA2_VC_VC_VFRACT_DEN_MASK       0x0F
-#define CPIA2_VC_VC_VFRACT_NUM_MASK       0xF0
-
-#define CPIA2_VC_VC_JPEG_OPT                      0xD6
-#define CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE     0x01
-#define CPIA2_VC_VC_JPEG_OPT_NO_DC_AUTO_SQUEEZE 0x02
-#define CPIA2_VC_VC_JPEG_OPT_AUTO_SQUEEZE       0x04
-#define CPIA2_VC_VC_JPEG_OPT_DEFAULT      (CPIA2_VC_VC_JPEG_OPT_DOUBLE_SQUEEZE|\
-                                          CPIA2_VC_VC_JPEG_OPT_AUTO_SQUEEZE)
-
-
-#define CPIA2_VC_VC_CREEP_PERIOD             0xD7
-#define CPIA2_VC_VC_USER_SQUEEZE             0xD8
-#define CPIA2_VC_VC_TARGET_KB                0xD9
-
-#define CPIA2_VC_VC_AUTO_SQUEEZE             0xE6
-
-
-/***
- * VP register set (Bank 2)
- ***/
-#define CPIA2_VP_DEVICEH                             0
-#define CPIA2_VP_DEVICEL                             1
-
-#define CPIA2_VP_SYSTEMSTATE                         0x02
-#define CPIA2_VP_SYSTEMSTATE_HK_ALIVE             0x01
-
-#define CPIA2_VP_SYSTEMCTRL                          0x03
-#define CPIA2_VP_SYSTEMCTRL_REQ_CLEAR_ERROR       0x80
-#define CPIA2_VP_SYSTEMCTRL_POWER_DOWN_PLL        0x20
-#define CPIA2_VP_SYSTEMCTRL_REQ_SUSPEND_STATE     0x10
-#define CPIA2_VP_SYSTEMCTRL_REQ_SERIAL_WAKEUP     0x08
-#define CPIA2_VP_SYSTEMCTRL_REQ_AUTOLOAD          0x04
-#define CPIA2_VP_SYSTEMCTRL_HK_CONTROL            0x02
-#define CPIA2_VP_SYSTEMCTRL_POWER_CONTROL         0x01
-
-#define CPIA2_VP_SENSOR_FLAGS                        0x05
-#define CPIA2_VP_SENSOR_FLAGS_404                 0x01
-#define CPIA2_VP_SENSOR_FLAGS_407                 0x02
-#define CPIA2_VP_SENSOR_FLAGS_409                 0x04
-#define CPIA2_VP_SENSOR_FLAGS_410                 0x08
-#define CPIA2_VP_SENSOR_FLAGS_500                 0x10
-
-#define CPIA2_VP_SENSOR_REV                          0x06
-
-#define CPIA2_VP_DEVICE_CONFIG                       0x07
-#define CPIA2_VP_DEVICE_CONFIG_SERIAL_BRIDGE      0x01
-
-#define CPIA2_VP_GPIO_DIRECTION                      0x08
-#define CPIA2_VP_GPIO_READ                        0xFF
-#define CPIA2_VP_GPIO_WRITE                       0x00
-
-#define CPIA2_VP_GPIO_DATA                           0x09
-
-#define CPIA2_VP_RAM_ADDR_H                          0x0A
-#define CPIA2_VP_RAM_ADDR_L                          0x0B
-#define CPIA2_VP_RAM_DATA                            0x0C
-
-#define CPIA2_VP_PATCH_REV                           0x0F
-
-#define CPIA2_VP4_USER_MODE                           0x10
-#define CPIA2_VP5_USER_MODE                           0x13
-#define CPIA2_VP_USER_MODE_CIF                    0x01
-#define CPIA2_VP_USER_MODE_QCIFDS                 0x02
-#define CPIA2_VP_USER_MODE_QCIFPTC                0x04
-#define CPIA2_VP_USER_MODE_QVGADS                 0x08
-#define CPIA2_VP_USER_MODE_QVGAPTC                0x10
-#define CPIA2_VP_USER_MODE_VGA                    0x20
-
-#define CPIA2_VP4_FRAMERATE_REQUEST                    0x11
-#define CPIA2_VP5_FRAMERATE_REQUEST                    0x14
-#define CPIA2_VP_FRAMERATE_60                     0x80
-#define CPIA2_VP_FRAMERATE_50                     0x40
-#define CPIA2_VP_FRAMERATE_30                     0x20
-#define CPIA2_VP_FRAMERATE_25                     0x10
-#define CPIA2_VP_FRAMERATE_15                     0x08
-#define CPIA2_VP_FRAMERATE_12_5                   0x04
-#define CPIA2_VP_FRAMERATE_7_5                    0x02
-#define CPIA2_VP_FRAMERATE_6_25                   0x01
-
-#define CPIA2_VP4_USER_EFFECTS                         0x12
-#define CPIA2_VP5_USER_EFFECTS                         0x15
-#define CPIA2_VP_USER_EFFECTS_COLBARS             0x01
-#define CPIA2_VP_USER_EFFECTS_COLBARS_GRAD        0x02
-#define CPIA2_VP_USER_EFFECTS_MIRROR              0x04
-#define CPIA2_VP_USER_EFFECTS_FLIP                0x40  // VP5 only
-
-/* NOTE: CPIA2_VP_EXPOSURE_MODES shares the same register as VP5 User
- * Effects */
-#define CPIA2_VP_EXPOSURE_MODES                       0x15
-#define CPIA2_VP_EXPOSURE_MODES_INHIBIT_FLICKER   0x20
-#define CPIA2_VP_EXPOSURE_MODES_COMPILE_EXP       0x10
-
-#define CPIA2_VP4_EXPOSURE_TARGET                     0x16    // VP4
-#define CPIA2_VP5_EXPOSURE_TARGET                    0x20    // VP5
-
-#define CPIA2_VP_FLICKER_MODES                        0x1B
-#define CPIA2_VP_FLICKER_MODES_50HZ               0x80
-#define CPIA2_VP_FLICKER_MODES_CUSTOM_FLT_FFREQ   0x40
-#define CPIA2_VP_FLICKER_MODES_NEVER_FLICKER      0x20
-#define CPIA2_VP_FLICKER_MODES_INHIBIT_RUB        0x10
-#define CPIA2_VP_FLICKER_MODES_ADJUST_LINE_FREQ   0x08
-#define CPIA2_VP_FLICKER_MODES_CUSTOM_INT_FFREQ   0x04
-
-#define CPIA2_VP_UMISC                                0x1D
-#define CPIA2_VP_UMISC_FORCE_MONO                 0x80
-#define CPIA2_VP_UMISC_FORCE_ID_MASK              0x40
-#define CPIA2_VP_UMISC_INHIBIT_AUTO_FGS           0x20
-#define CPIA2_VP_UMISC_INHIBIT_AUTO_DIMS          0x08
-#define CPIA2_VP_UMISC_OPT_FOR_SENSOR_DS          0x04
-#define CPIA2_VP_UMISC_INHIBIT_AUTO_MODE_INT      0x02
-
-#define CPIA2_VP5_ANTIFLKRSETUP                       0x22  //34
-
-#define CPIA2_VP_INTERPOLATION                        0x24
-#define CPIA2_VP_INTERPOLATION_EVEN_FIRST         0x40
-#define CPIA2_VP_INTERPOLATION_HJOG               0x20
-#define CPIA2_VP_INTERPOLATION_VJOG               0x10
-
-#define CPIA2_VP_GAMMA                                0x25
-#define CPIA2_VP_DEFAULT_GAMMA                    0x10
-
-#define CPIA2_VP_YRANGE                               0x26
-
-#define CPIA2_VP_SATURATION                           0x27
-
-#define CPIA2_VP5_MYBLACK_LEVEL                       0x3A   //58
-#define CPIA2_VP5_MCYRANGE                            0x3B   //59
-#define CPIA2_VP5_MYCEILING                           0x3C   //60
-#define CPIA2_VP5_MCUVSATURATION                      0x3D   //61
-
-
-#define CPIA2_VP_REHASH_VALUES                        0x60
-
-
-/***
- * Common sensor registers
- ***/
-#define CPIA2_SENSOR_DEVICE_H                         0x00
-#define CPIA2_SENSOR_DEVICE_L                         0x01
-
-#define CPIA2_SENSOR_DATA_FORMAT                      0x16
-#define CPIA2_SENSOR_DATA_FORMAT_HMIRROR      0x08
-#define CPIA2_SENSOR_DATA_FORMAT_VMIRROR      0x10
-
-#define CPIA2_SENSOR_CR1                              0x76
-#define CPIA2_SENSOR_CR1_STAND_BY             0x01
-#define CPIA2_SENSOR_CR1_DOWN_RAMP_GEN        0x02
-#define CPIA2_SENSOR_CR1_DOWN_COLUMN_ADC      0x04
-#define CPIA2_SENSOR_CR1_DOWN_CAB_REGULATOR   0x08
-#define CPIA2_SENSOR_CR1_DOWN_AUDIO_REGULATOR 0x10
-#define CPIA2_SENSOR_CR1_DOWN_VRT_AMP         0x20
-#define CPIA2_SENSOR_CR1_DOWN_BAND_GAP        0x40
-
-#endif
diff --git a/drivers/media/video/cpia2/cpia2_usb.c b/drivers/media/video/cpia2/cpia2_usb.c
deleted file mode 100644 (file)
index 95b5d6e..0000000
+++ /dev/null
@@ -1,955 +0,0 @@
-/****************************************************************************
- *
- *  Filename: cpia2_usb.c
- *
- *  Copyright 2001, STMicrolectronics, Inc.
- *      Contact:  steve.miller@st.com
- *
- *  Description:
- *     This is a USB driver for CPia2 based video cameras.
- *     The infrastructure of this driver is based on the cpia usb driver by
- *     Jochen Scharrlach and Johannes Erdfeldt.
- *
- *  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.
- *
- *  Stripped of 2.4 stuff ready for main kernel submit by
- *             Alan Cox <alan@lxorguk.ukuu.org.uk>
- ****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/module.h>
-
-#include "cpia2.h"
-
-static int frame_sizes[] = {
-       0,      // USBIF_CMDONLY
-       0,      // USBIF_BULK
-       128,    // USBIF_ISO_1
-       384,    // USBIF_ISO_2
-       640,    // USBIF_ISO_3
-       768,    // USBIF_ISO_4
-       896,    // USBIF_ISO_5
-       1023,   // USBIF_ISO_6
-};
-
-#define FRAMES_PER_DESC    10
-#define FRAME_SIZE_PER_DESC   frame_sizes[cam->cur_alt]
-
-static void process_frame(struct camera_data *cam);
-static void cpia2_usb_complete(struct urb *urb);
-static int cpia2_usb_probe(struct usb_interface *intf,
-                          const struct usb_device_id *id);
-static void cpia2_usb_disconnect(struct usb_interface *intf);
-static int cpia2_usb_suspend(struct usb_interface *intf, pm_message_t message);
-static int cpia2_usb_resume(struct usb_interface *intf);
-
-static void free_sbufs(struct camera_data *cam);
-static void add_APPn(struct camera_data *cam);
-static void add_COM(struct camera_data *cam);
-static int submit_urbs(struct camera_data *cam);
-static int set_alternate(struct camera_data *cam, unsigned int alt);
-static int configure_transfer_mode(struct camera_data *cam, unsigned int alt);
-
-static struct usb_device_id cpia2_id_table[] = {
-       {USB_DEVICE(0x0553, 0x0100)},
-       {USB_DEVICE(0x0553, 0x0140)},
-       {USB_DEVICE(0x0553, 0x0151)},  /* STV0676 */
-       {}                      /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, cpia2_id_table);
-
-static struct usb_driver cpia2_driver = {
-       .name           = "cpia2",
-       .probe          = cpia2_usb_probe,
-       .disconnect     = cpia2_usb_disconnect,
-       .suspend        = cpia2_usb_suspend,
-       .resume         = cpia2_usb_resume,
-       .reset_resume   = cpia2_usb_resume,
-       .id_table       = cpia2_id_table
-};
-
-
-/******************************************************************************
- *
- *  process_frame
- *
- *****************************************************************************/
-static void process_frame(struct camera_data *cam)
-{
-       static int frame_count;
-
-       unsigned char *inbuff = cam->workbuff->data;
-
-       DBG("Processing frame #%d, current:%d\n",
-           cam->workbuff->num, cam->curbuff->num);
-
-       if(cam->workbuff->length > cam->workbuff->max_length)
-               cam->workbuff->max_length = cam->workbuff->length;
-
-       if ((inbuff[0] == 0xFF) && (inbuff[1] == 0xD8)) {
-               frame_count++;
-       } else {
-               cam->workbuff->status = FRAME_ERROR;
-               DBG("Start of frame not found\n");
-               return;
-       }
-
-       /***
-        * Now the output buffer should have a JPEG image in it.
-        ***/
-       if(!cam->first_image_seen) {
-               /* Always skip the first image after streaming
-                * starts. It is almost certainly corrupt. */
-               cam->first_image_seen = 1;
-               cam->workbuff->status = FRAME_EMPTY;
-               return;
-       }
-       if (cam->workbuff->length > 3) {
-               if(cam->mmapped &&
-                  cam->workbuff->length < cam->workbuff->max_length) {
-                       /* No junk in the buffers */
-                       memset(cam->workbuff->data+cam->workbuff->length,
-                              0, cam->workbuff->max_length-
-                                 cam->workbuff->length);
-               }
-               cam->workbuff->max_length = cam->workbuff->length;
-               cam->workbuff->status = FRAME_READY;
-
-               if(!cam->mmapped && cam->num_frames > 2) {
-                       /* During normal reading, the most recent
-                        * frame will be read.  If the current frame
-                        * hasn't started reading yet, it will never
-                        * be read, so mark it empty.  If the buffer is
-                        * mmapped, or we have few buffers, we need to
-                        * wait for the user to free the buffer.
-                        *
-                        * NOTE: This is not entirely foolproof with 3
-                        * buffers, but it would take an EXTREMELY
-                        * overloaded system to cause problems (possible
-                        * image data corruption).  Basically, it would
-                        * need to take more time to execute cpia2_read
-                        * than it would for the camera to send
-                        * cam->num_frames-2 frames before problems
-                        * could occur.
-                        */
-                       cam->curbuff->status = FRAME_EMPTY;
-               }
-               cam->curbuff = cam->workbuff;
-               cam->workbuff = cam->workbuff->next;
-               DBG("Changed buffers, work:%d, current:%d\n",
-                   cam->workbuff->num, cam->curbuff->num);
-               return;
-       } else {
-               DBG("Not enough data for an image.\n");
-       }
-
-       cam->workbuff->status = FRAME_ERROR;
-       return;
-}
-
-/******************************************************************************
- *
- *  add_APPn
- *
- *  Adds a user specified APPn record
- *****************************************************************************/
-static void add_APPn(struct camera_data *cam)
-{
-       if(cam->APP_len > 0) {
-               cam->workbuff->data[cam->workbuff->length++] = 0xFF;
-               cam->workbuff->data[cam->workbuff->length++] = 0xE0+cam->APPn;
-               cam->workbuff->data[cam->workbuff->length++] = 0;
-               cam->workbuff->data[cam->workbuff->length++] = cam->APP_len+2;
-               memcpy(cam->workbuff->data+cam->workbuff->length,
-                      cam->APP_data, cam->APP_len);
-               cam->workbuff->length += cam->APP_len;
-       }
-}
-
-/******************************************************************************
- *
- *  add_COM
- *
- *  Adds a user specified COM record
- *****************************************************************************/
-static void add_COM(struct camera_data *cam)
-{
-       if(cam->COM_len > 0) {
-               cam->workbuff->data[cam->workbuff->length++] = 0xFF;
-               cam->workbuff->data[cam->workbuff->length++] = 0xFE;
-               cam->workbuff->data[cam->workbuff->length++] = 0;
-               cam->workbuff->data[cam->workbuff->length++] = cam->COM_len+2;
-               memcpy(cam->workbuff->data+cam->workbuff->length,
-                      cam->COM_data, cam->COM_len);
-               cam->workbuff->length += cam->COM_len;
-       }
-}
-
-/******************************************************************************
- *
- *  cpia2_usb_complete
- *
- *  callback when incoming packet is received
- *****************************************************************************/
-static void cpia2_usb_complete(struct urb *urb)
-{
-       int i;
-       unsigned char *cdata;
-       static int frame_ready = false;
-       struct camera_data *cam = (struct camera_data *) urb->context;
-
-       if (urb->status!=0) {
-               if (!(urb->status == -ENOENT ||
-                     urb->status == -ECONNRESET ||
-                     urb->status == -ESHUTDOWN))
-               {
-                       DBG("urb->status = %d!\n", urb->status);
-               }
-               DBG("Stopping streaming\n");
-               return;
-       }
-
-       if (!cam->streaming || !video_is_registered(&cam->vdev)) {
-               LOG("Will now stop the streaming: streaming = %d, present=%d\n",
-                   cam->streaming, video_is_registered(&cam->vdev));
-               return;
-       }
-
-       /***
-        * Packet collater
-        ***/
-       //DBG("Collating %d packets\n", urb->number_of_packets);
-       for (i = 0; i < urb->number_of_packets; i++) {
-               u16 checksum, iso_checksum;
-               int j;
-               int n = urb->iso_frame_desc[i].actual_length;
-               int st = urb->iso_frame_desc[i].status;
-
-               if(cam->workbuff->status == FRAME_READY) {
-                       struct framebuf *ptr;
-                       /* Try to find an available buffer */
-                       DBG("workbuff full, searching\n");
-                       for (ptr = cam->workbuff->next;
-                            ptr != cam->workbuff;
-                            ptr = ptr->next)
-                       {
-                               if (ptr->status == FRAME_EMPTY) {
-                                       ptr->status = FRAME_READING;
-                                       ptr->length = 0;
-                                       break;
-                               }
-                       }
-                       if (ptr == cam->workbuff)
-                               break; /* No READING or EMPTY buffers left */
-
-                       cam->workbuff = ptr;
-               }
-
-               if (cam->workbuff->status == FRAME_EMPTY ||
-                   cam->workbuff->status == FRAME_ERROR) {
-                       cam->workbuff->status = FRAME_READING;
-                       cam->workbuff->length = 0;
-               }
-
-               //DBG("   Packet %d length = %d, status = %d\n", i, n, st);
-               cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-
-               if (st) {
-                       LOG("cpia2 data error: [%d] len=%d, status = %d\n",
-                           i, n, st);
-                       if(!ALLOW_CORRUPT)
-                               cam->workbuff->status = FRAME_ERROR;
-                       continue;
-               }
-
-               if(n<=2)
-                       continue;
-
-               checksum = 0;
-               for(j=0; j<n-2; ++j)
-                       checksum += cdata[j];
-               iso_checksum = cdata[j] + cdata[j+1]*256;
-               if(checksum != iso_checksum) {
-                       LOG("checksum mismatch: [%d] len=%d, calculated = %x, checksum = %x\n",
-                           i, n, (int)checksum, (int)iso_checksum);
-                       if(!ALLOW_CORRUPT) {
-                               cam->workbuff->status = FRAME_ERROR;
-                               continue;
-                       }
-               }
-               n -= 2;
-
-               if(cam->workbuff->status != FRAME_READING) {
-                       if((0xFF == cdata[0] && 0xD8 == cdata[1]) ||
-                          (0xD8 == cdata[0] && 0xFF == cdata[1] &&
-                           0 != cdata[2])) {
-                               /* frame is skipped, but increment total
-                                * frame count anyway */
-                               cam->frame_count++;
-                       }
-                       DBG("workbuff not reading, status=%d\n",
-                           cam->workbuff->status);
-                       continue;
-               }
-
-               if (cam->frame_size < cam->workbuff->length + n) {
-                       ERR("buffer overflow! length: %d, n: %d\n",
-                           cam->workbuff->length, n);
-                       cam->workbuff->status = FRAME_ERROR;
-                       if(cam->workbuff->length > cam->workbuff->max_length)
-                               cam->workbuff->max_length =
-                                       cam->workbuff->length;
-                       continue;
-               }
-
-               if (cam->workbuff->length == 0) {
-                       int data_offset;
-                       if ((0xD8 == cdata[0]) && (0xFF == cdata[1])) {
-                               data_offset = 1;
-                       } else if((0xFF == cdata[0]) && (0xD8 == cdata[1])
-                                 && (0xFF == cdata[2])) {
-                               data_offset = 2;
-                       } else {
-                               DBG("Ignoring packet, not beginning!\n");
-                               continue;
-                       }
-                       DBG("Start of frame pattern found\n");
-                       do_gettimeofday(&cam->workbuff->timestamp);
-                       cam->workbuff->seq = cam->frame_count++;
-                       cam->workbuff->data[0] = 0xFF;
-                       cam->workbuff->data[1] = 0xD8;
-                       cam->workbuff->length = 2;
-                       add_APPn(cam);
-                       add_COM(cam);
-                       memcpy(cam->workbuff->data+cam->workbuff->length,
-                              cdata+data_offset, n-data_offset);
-                       cam->workbuff->length += n-data_offset;
-               } else if (cam->workbuff->length > 0) {
-                       memcpy(cam->workbuff->data + cam->workbuff->length,
-                              cdata, n);
-                       cam->workbuff->length += n;
-               }
-
-               if ((cam->workbuff->length >= 3) &&
-                   (cam->workbuff->data[cam->workbuff->length - 3] == 0xFF) &&
-                   (cam->workbuff->data[cam->workbuff->length - 2] == 0xD9) &&
-                   (cam->workbuff->data[cam->workbuff->length - 1] == 0xFF)) {
-                       frame_ready = true;
-                       cam->workbuff->data[cam->workbuff->length - 1] = 0;
-                       cam->workbuff->length -= 1;
-               } else if ((cam->workbuff->length >= 2) &&
-                  (cam->workbuff->data[cam->workbuff->length - 2] == 0xFF) &&
-                  (cam->workbuff->data[cam->workbuff->length - 1] == 0xD9)) {
-                       frame_ready = true;
-               }
-
-               if (frame_ready) {
-                       DBG("Workbuff image size = %d\n",cam->workbuff->length);
-                       process_frame(cam);
-
-                       frame_ready = false;
-
-                       if (waitqueue_active(&cam->wq_stream))
-                               wake_up_interruptible(&cam->wq_stream);
-               }
-       }
-
-       if(cam->streaming) {
-               /* resubmit */
-               urb->dev = cam->dev;
-               if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)
-                       ERR("%s: usb_submit_urb ret %d!\n", __func__, i);
-       }
-}
-
-/******************************************************************************
- *
- * configure_transfer_mode
- *
- *****************************************************************************/
-static int configure_transfer_mode(struct camera_data *cam, unsigned int alt)
-{
-       static unsigned char iso_regs[8][4] = {
-               {0x00, 0x00, 0x00, 0x00},
-               {0x00, 0x00, 0x00, 0x00},
-               {0xB9, 0x00, 0x00, 0x7E},
-               {0xB9, 0x00, 0x01, 0x7E},
-               {0xB9, 0x00, 0x02, 0x7E},
-               {0xB9, 0x00, 0x02, 0xFE},
-               {0xB9, 0x00, 0x03, 0x7E},
-               {0xB9, 0x00, 0x03, 0xFD}
-       };
-       struct cpia2_command cmd;
-       unsigned char reg;
-
-       if (!video_is_registered(&cam->vdev))
-               return -ENODEV;
-
-       /***
-        * Write the isoc registers according to the alternate selected
-        ***/
-       cmd.direction = TRANSFER_WRITE;
-       cmd.buffer.block_data[0] = iso_regs[alt][0];
-       cmd.buffer.block_data[1] = iso_regs[alt][1];
-       cmd.buffer.block_data[2] = iso_regs[alt][2];
-       cmd.buffer.block_data[3] = iso_regs[alt][3];
-       cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
-       cmd.start = CPIA2_VC_USB_ISOLIM;
-       cmd.reg_count = 4;
-       cpia2_send_command(cam, &cmd);
-
-       /***
-        * Enable relevant streams before starting polling.
-        * First read USB Stream Config Register.
-        ***/
-       cmd.direction = TRANSFER_READ;
-       cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
-       cmd.start = CPIA2_VC_USB_STRM;
-       cmd.reg_count = 1;
-       cpia2_send_command(cam, &cmd);
-       reg = cmd.buffer.block_data[0];
-
-       /* Clear iso, bulk, and int */
-       reg &= ~(CPIA2_VC_USB_STRM_BLK_ENABLE |
-                CPIA2_VC_USB_STRM_ISO_ENABLE |
-                CPIA2_VC_USB_STRM_INT_ENABLE);
-
-       if (alt == USBIF_BULK) {
-               DBG("Enabling bulk xfer\n");
-               reg |= CPIA2_VC_USB_STRM_BLK_ENABLE;    /* Enable Bulk */
-               cam->xfer_mode = XFER_BULK;
-       } else if (alt >= USBIF_ISO_1) {
-               DBG("Enabling ISOC xfer\n");
-               reg |= CPIA2_VC_USB_STRM_ISO_ENABLE;
-               cam->xfer_mode = XFER_ISOC;
-       }
-
-       cmd.buffer.block_data[0] = reg;
-       cmd.direction = TRANSFER_WRITE;
-       cmd.start = CPIA2_VC_USB_STRM;
-       cmd.reg_count = 1;
-       cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC;
-       cpia2_send_command(cam, &cmd);
-
-       return 0;
-}
-
-/******************************************************************************
- *
- * cpia2_usb_change_streaming_alternate
- *
- *****************************************************************************/
-int cpia2_usb_change_streaming_alternate(struct camera_data *cam,
-                                        unsigned int alt)
-{
-       int ret = 0;
-
-       if(alt < USBIF_ISO_1 || alt > USBIF_ISO_6)
-               return -EINVAL;
-
-       if(alt == cam->params.camera_state.stream_mode)
-               return 0;
-
-       cpia2_usb_stream_pause(cam);
-
-       configure_transfer_mode(cam, alt);
-
-       cam->params.camera_state.stream_mode = alt;
-
-       /* Reset the camera to prevent image quality degradation */
-       cpia2_reset_camera(cam);
-
-       cpia2_usb_stream_resume(cam);
-
-       return ret;
-}
-
-/******************************************************************************
- *
- * set_alternate
- *
- *****************************************************************************/
-static int set_alternate(struct camera_data *cam, unsigned int alt)
-{
-       int ret = 0;
-
-       if(alt == cam->cur_alt)
-               return 0;
-
-       if (cam->cur_alt != USBIF_CMDONLY) {
-               DBG("Changing from alt %d to %d\n", cam->cur_alt, USBIF_CMDONLY);
-               ret = usb_set_interface(cam->dev, cam->iface, USBIF_CMDONLY);
-               if (ret != 0)
-                       return ret;
-       }
-       if (alt != USBIF_CMDONLY) {
-               DBG("Changing from alt %d to %d\n", USBIF_CMDONLY, alt);
-               ret = usb_set_interface(cam->dev, cam->iface, alt);
-               if (ret != 0)
-                       return ret;
-       }
-
-       cam->old_alt = cam->cur_alt;
-       cam->cur_alt = alt;
-
-       return ret;
-}
-
-/******************************************************************************
- *
- * free_sbufs
- *
- * Free all cam->sbuf[]. All non-NULL .data and .urb members that are non-NULL
- * are assumed to be allocated. Non-NULL .urb members are also assumed to be
- * submitted (and must therefore be killed before they are freed).
- *****************************************************************************/
-static void free_sbufs(struct camera_data *cam)
-{
-       int i;
-
-       for (i = 0; i < NUM_SBUF; i++) {
-               if(cam->sbuf[i].urb) {
-                       usb_kill_urb(cam->sbuf[i].urb);
-                       usb_free_urb(cam->sbuf[i].urb);
-                       cam->sbuf[i].urb = NULL;
-               }
-               if(cam->sbuf[i].data) {
-                       kfree(cam->sbuf[i].data);
-                       cam->sbuf[i].data = NULL;
-               }
-       }
-}
-
-/*******
-* Convenience functions
-*******/
-/****************************************************************************
- *
- *  write_packet
- *
- ***************************************************************************/
-static int write_packet(struct usb_device *udev,
-                       u8 request, u8 * registers, u16 start, size_t size)
-{
-       if (!registers || size <= 0)
-               return -EINVAL;
-
-       return usb_control_msg(udev,
-                              usb_sndctrlpipe(udev, 0),
-                              request,
-                              USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                              start,   /* value */
-                              0,       /* index */
-                              registers,       /* buffer */
-                              size,
-                              HZ);
-}
-
-/****************************************************************************
- *
- *  read_packet
- *
- ***************************************************************************/
-static int read_packet(struct usb_device *udev,
-                      u8 request, u8 * registers, u16 start, size_t size)
-{
-       if (!registers || size <= 0)
-               return -EINVAL;
-
-       return usb_control_msg(udev,
-                              usb_rcvctrlpipe(udev, 0),
-                              request,
-                              USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE,
-                              start,   /* value */
-                              0,       /* index */
-                              registers,       /* buffer */
-                              size,
-                              HZ);
-}
-
-/******************************************************************************
- *
- *  cpia2_usb_transfer_cmd
- *
- *****************************************************************************/
-int cpia2_usb_transfer_cmd(struct camera_data *cam,
-                          void *registers,
-                          u8 request, u8 start, u8 count, u8 direction)
-{
-       int err = 0;
-       struct usb_device *udev = cam->dev;
-
-       if (!udev) {
-               ERR("%s: Internal driver error: udev is NULL\n", __func__);
-               return -EINVAL;
-       }
-
-       if (!registers) {
-               ERR("%s: Internal driver error: register array is NULL\n", __func__);
-               return -EINVAL;
-       }
-
-       if (direction == TRANSFER_READ) {
-               err = read_packet(udev, request, (u8 *)registers, start, count);
-               if (err > 0)
-                       err = 0;
-       } else if (direction == TRANSFER_WRITE) {
-               err =write_packet(udev, request, (u8 *)registers, start, count);
-               if (err < 0) {
-                       LOG("Control message failed, err val = %d\n", err);
-                       LOG("Message: request = 0x%0X, start = 0x%0X\n",
-                           request, start);
-                       LOG("Message: count = %d, register[0] = 0x%0X\n",
-                           count, ((unsigned char *) registers)[0]);
-               } else
-                       err=0;
-       } else {
-               LOG("Unexpected first byte of direction: %d\n",
-                      direction);
-               return -EINVAL;
-       }
-
-       if(err != 0)
-               LOG("Unexpected error: %d\n", err);
-       return err;
-}
-
-
-/******************************************************************************
- *
- *  submit_urbs
- *
- *****************************************************************************/
-static int submit_urbs(struct camera_data *cam)
-{
-       struct urb *urb;
-       int fx, err, i, j;
-
-       for(i=0; i<NUM_SBUF; ++i) {
-               if (cam->sbuf[i].data)
-                       continue;
-               cam->sbuf[i].data =
-                   kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
-               if (!cam->sbuf[i].data) {
-                       while (--i >= 0) {
-                               kfree(cam->sbuf[i].data);
-                               cam->sbuf[i].data = NULL;
-                       }
-                       return -ENOMEM;
-               }
-       }
-
-       /* We double buffer the Isoc lists, and also know the polling
-        * interval is every frame (1 == (1 << (bInterval -1))).
-        */
-       for(i=0; i<NUM_SBUF; ++i) {
-               if(cam->sbuf[i].urb) {
-                       continue;
-               }
-               urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
-               if (!urb) {
-                       ERR("%s: usb_alloc_urb error!\n", __func__);
-                       for (j = 0; j < i; j++)
-                               usb_free_urb(cam->sbuf[j].urb);
-                       return -ENOMEM;
-               }
-
-               cam->sbuf[i].urb = urb;
-               urb->dev = cam->dev;
-               urb->context = cam;
-               urb->pipe = usb_rcvisocpipe(cam->dev, 1 /*ISOC endpoint*/);
-               urb->transfer_flags = URB_ISO_ASAP;
-               urb->transfer_buffer = cam->sbuf[i].data;
-               urb->complete = cpia2_usb_complete;
-               urb->number_of_packets = FRAMES_PER_DESC;
-               urb->interval = 1;
-               urb->transfer_buffer_length =
-                       FRAME_SIZE_PER_DESC * FRAMES_PER_DESC;
-
-               for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
-                       urb->iso_frame_desc[fx].offset =
-                               FRAME_SIZE_PER_DESC * fx;
-                       urb->iso_frame_desc[fx].length = FRAME_SIZE_PER_DESC;
-               }
-       }
-
-
-       /* Queue the ISO urbs, and resubmit in the completion handler */
-       for(i=0; i<NUM_SBUF; ++i) {
-               err = usb_submit_urb(cam->sbuf[i].urb, GFP_KERNEL);
-               if (err) {
-                       ERR("usb_submit_urb[%d]() = %d\n", i, err);
-                       return err;
-               }
-       }
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  cpia2_usb_stream_start
- *
- *****************************************************************************/
-int cpia2_usb_stream_start(struct camera_data *cam, unsigned int alternate)
-{
-       int ret;
-       int old_alt;
-
-       if(cam->streaming)
-               return 0;
-
-       if (cam->flush) {
-               int i;
-               DBG("Flushing buffers\n");
-               for(i=0; i<cam->num_frames; ++i) {
-                       cam->buffers[i].status = FRAME_EMPTY;
-                       cam->buffers[i].length = 0;
-               }
-               cam->curbuff = &cam->buffers[0];
-               cam->workbuff = cam->curbuff->next;
-               cam->flush = false;
-       }
-
-       old_alt = cam->params.camera_state.stream_mode;
-       cam->params.camera_state.stream_mode = 0;
-       ret = cpia2_usb_change_streaming_alternate(cam, alternate);
-       if (ret < 0) {
-               int ret2;
-               ERR("cpia2_usb_change_streaming_alternate() = %d!\n", ret);
-               cam->params.camera_state.stream_mode = old_alt;
-               ret2 = set_alternate(cam, USBIF_CMDONLY);
-               if (ret2 < 0) {
-                       ERR("cpia2_usb_change_streaming_alternate(%d) =%d has already "
-                           "failed. Then tried to call "
-                           "set_alternate(USBIF_CMDONLY) = %d.\n",
-                           alternate, ret, ret2);
-               }
-       } else {
-               cam->frame_count = 0;
-               cam->streaming = 1;
-               ret = cpia2_usb_stream_resume(cam);
-       }
-       return ret;
-}
-
-/******************************************************************************
- *
- *  cpia2_usb_stream_pause
- *
- *****************************************************************************/
-int cpia2_usb_stream_pause(struct camera_data *cam)
-{
-       int ret = 0;
-       if(cam->streaming) {
-               free_sbufs(cam);
-               ret = set_alternate(cam, USBIF_CMDONLY);
-       }
-       return ret;
-}
-
-/******************************************************************************
- *
- *  cpia2_usb_stream_resume
- *
- *****************************************************************************/
-int cpia2_usb_stream_resume(struct camera_data *cam)
-{
-       int ret = 0;
-       if(cam->streaming) {
-               cam->first_image_seen = 0;
-               ret = set_alternate(cam, cam->params.camera_state.stream_mode);
-               if(ret == 0) {
-                       /* for some reason the user effects need to be set
-                          again when starting streaming. */
-                       cpia2_do_command(cam, CPIA2_CMD_SET_USER_EFFECTS, TRANSFER_WRITE,
-                                       cam->params.vp_params.user_effects);
-                       ret = submit_urbs(cam);
-               }
-       }
-       return ret;
-}
-
-/******************************************************************************
- *
- *  cpia2_usb_stream_stop
- *
- *****************************************************************************/
-int cpia2_usb_stream_stop(struct camera_data *cam)
-{
-       int ret;
-
-       ret = cpia2_usb_stream_pause(cam);
-       cam->streaming = 0;
-       configure_transfer_mode(cam, 0);
-       return ret;
-}
-
-/******************************************************************************
- *
- *  cpia2_usb_probe
- *
- *  Probe and initialize.
- *****************************************************************************/
-static int cpia2_usb_probe(struct usb_interface *intf,
-                          const struct usb_device_id *id)
-{
-       struct usb_device *udev = interface_to_usbdev(intf);
-       struct usb_interface_descriptor *interface;
-       struct camera_data *cam;
-       int ret;
-
-       /* A multi-config CPiA2 camera? */
-       if (udev->descriptor.bNumConfigurations != 1)
-               return -ENODEV;
-       interface = &intf->cur_altsetting->desc;
-
-       /* If we get to this point, we found a CPiA2 camera */
-       LOG("CPiA2 USB camera found\n");
-
-       cam = cpia2_init_camera_struct(intf);
-       if (cam == NULL)
-               return -ENOMEM;
-
-       cam->dev = udev;
-       cam->iface = interface->bInterfaceNumber;
-
-       ret = set_alternate(cam, USBIF_CMDONLY);
-       if (ret < 0) {
-               ERR("%s: usb_set_interface error (ret = %d)\n", __func__, ret);
-               kfree(cam);
-               return ret;
-       }
-
-
-       if((ret = cpia2_init_camera(cam)) < 0) {
-               ERR("%s: failed to initialize cpia2 camera (ret = %d)\n", __func__, ret);
-               kfree(cam);
-               return ret;
-       }
-       LOG("  CPiA Version: %d.%02d (%d.%d)\n",
-              cam->params.version.firmware_revision_hi,
-              cam->params.version.firmware_revision_lo,
-              cam->params.version.asic_id,
-              cam->params.version.asic_rev);
-       LOG("  CPiA PnP-ID: %04x:%04x:%04x\n",
-              cam->params.pnp_id.vendor,
-              cam->params.pnp_id.product,
-              cam->params.pnp_id.device_revision);
-       LOG("  SensorID: %d.(version %d)\n",
-              cam->params.version.sensor_flags,
-              cam->params.version.sensor_rev);
-
-       usb_set_intfdata(intf, cam);
-
-       ret = cpia2_register_camera(cam);
-       if (ret < 0) {
-               ERR("%s: Failed to register cpia2 camera (ret = %d)\n", __func__, ret);
-               kfree(cam);
-               return ret;
-       }
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  cpia2_disconnect
- *
- *****************************************************************************/
-static void cpia2_usb_disconnect(struct usb_interface *intf)
-{
-       struct camera_data *cam = usb_get_intfdata(intf);
-       usb_set_intfdata(intf, NULL);
-
-       DBG("Stopping stream\n");
-       cpia2_usb_stream_stop(cam);
-
-       mutex_lock(&cam->v4l2_lock);
-       DBG("Unregistering camera\n");
-       cpia2_unregister_camera(cam);
-       v4l2_device_disconnect(&cam->v4l2_dev);
-       mutex_unlock(&cam->v4l2_lock);
-       v4l2_device_put(&cam->v4l2_dev);
-
-       if(cam->buffers) {
-               DBG("Wakeup waiting processes\n");
-               cam->curbuff->status = FRAME_READY;
-               cam->curbuff->length = 0;
-               if (waitqueue_active(&cam->wq_stream))
-                       wake_up_interruptible(&cam->wq_stream);
-       }
-
-       DBG("Releasing interface\n");
-       usb_driver_release_interface(&cpia2_driver, intf);
-
-       LOG("CPiA2 camera disconnected.\n");
-}
-
-static int cpia2_usb_suspend(struct usb_interface *intf, pm_message_t message)
-{
-       struct camera_data *cam = usb_get_intfdata(intf);
-
-       mutex_lock(&cam->v4l2_lock);
-       if (cam->streaming) {
-               cpia2_usb_stream_stop(cam);
-               cam->streaming = 1;
-       }
-       mutex_unlock(&cam->v4l2_lock);
-
-       dev_info(&intf->dev, "going into suspend..\n");
-       return 0;
-}
-
-/* Resume device - start device. */
-static int cpia2_usb_resume(struct usb_interface *intf)
-{
-       struct camera_data *cam = usb_get_intfdata(intf);
-
-       mutex_lock(&cam->v4l2_lock);
-       v4l2_ctrl_handler_setup(&cam->hdl);
-       if (cam->streaming) {
-               cam->streaming = 0;
-               cpia2_usb_stream_start(cam,
-                               cam->params.camera_state.stream_mode);
-       }
-       mutex_unlock(&cam->v4l2_lock);
-
-       dev_info(&intf->dev, "coming out of suspend..\n");
-       return 0;
-}
-
-/******************************************************************************
- *
- *  usb_cpia2_init
- *
- *****************************************************************************/
-int cpia2_usb_init(void)
-{
-       return usb_register(&cpia2_driver);
-}
-
-/******************************************************************************
- *
- *  usb_cpia_cleanup
- *
- *****************************************************************************/
-void cpia2_usb_cleanup(void)
-{
-       schedule_timeout(2 * HZ);
-       usb_deregister(&cpia2_driver);
-}
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
deleted file mode 100644 (file)
index 5ca6f44..0000000
+++ /dev/null
@@ -1,1267 +0,0 @@
-/****************************************************************************
- *
- *  Filename: cpia2_v4l.c
- *
- *  Copyright 2001, STMicrolectronics, Inc.
- *      Contact:  steve.miller@st.com
- *  Copyright 2001,2005, Scott J. Bertin <scottbertin@yahoo.com>
- *
- *  Description:
- *     This is a USB driver for CPia2 based video cameras.
- *     The infrastructure of this driver is based on the cpia usb driver by
- *     Jochen Scharrlach and Johannes Erdfeldt.
- *
- *  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.
- *
- *  Stripped of 2.4 stuff ready for main kernel submit by
- *             Alan Cox <alan@lxorguk.ukuu.org.uk>
- ****************************************************************************/
-
-#define CPIA_VERSION "3.0.1"
-
-#include <linux/module.h>
-#include <linux/time.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/videodev2.h>
-#include <linux/stringify.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-event.h>
-
-#include "cpia2.h"
-
-static int video_nr = -1;
-module_param(video_nr, int, 0);
-MODULE_PARM_DESC(video_nr, "video device to register (0=/dev/video0, etc)");
-
-static int buffer_size = 68 * 1024;
-module_param(buffer_size, int, 0);
-MODULE_PARM_DESC(buffer_size, "Size for each frame buffer in bytes (default 68k)");
-
-static int num_buffers = 3;
-module_param(num_buffers, int, 0);
-MODULE_PARM_DESC(num_buffers, "Number of frame buffers (1-"
-                __stringify(VIDEO_MAX_FRAME) ", default 3)");
-
-static int alternate = DEFAULT_ALT;
-module_param(alternate, int, 0);
-MODULE_PARM_DESC(alternate, "USB Alternate (" __stringify(USBIF_ISO_1) "-"
-                __stringify(USBIF_ISO_6) ", default "
-                __stringify(DEFAULT_ALT) ")");
-
-static int flicker_mode;
-module_param(flicker_mode, int, 0);
-MODULE_PARM_DESC(flicker_mode, "Flicker frequency (0 (disabled), " __stringify(50) " or "
-                __stringify(60) ", default 0)");
-
-MODULE_AUTHOR("Steve Miller (STMicroelectronics) <steve.miller@st.com>");
-MODULE_DESCRIPTION("V4L-driver for STMicroelectronics CPiA2 based cameras");
-MODULE_SUPPORTED_DEVICE("video");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(CPIA_VERSION);
-
-#define ABOUT "V4L-Driver for Vision CPiA2 based cameras"
-#define CPIA2_CID_USB_ALT (V4L2_CID_USER_BASE | 0xf000)
-
-/******************************************************************************
- *
- *  cpia2_open
- *
- *****************************************************************************/
-static int cpia2_open(struct file *file)
-{
-       struct camera_data *cam = video_drvdata(file);
-       int retval;
-
-       if (mutex_lock_interruptible(&cam->v4l2_lock))
-               return -ERESTARTSYS;
-       retval = v4l2_fh_open(file);
-       if (retval)
-               goto open_unlock;
-
-       if (v4l2_fh_is_singular_file(file)) {
-               if (cpia2_allocate_buffers(cam)) {
-                       v4l2_fh_release(file);
-                       retval = -ENOMEM;
-                       goto open_unlock;
-               }
-
-               /* reset the camera */
-               if (cpia2_reset_camera(cam) < 0) {
-                       v4l2_fh_release(file);
-                       retval = -EIO;
-                       goto open_unlock;
-               }
-
-               cam->APP_len = 0;
-               cam->COM_len = 0;
-       }
-
-       cpia2_dbg_dump_registers(cam);
-open_unlock:
-       mutex_unlock(&cam->v4l2_lock);
-       return retval;
-}
-
-/******************************************************************************
- *
- *  cpia2_close
- *
- *****************************************************************************/
-static int cpia2_close(struct file *file)
-{
-       struct video_device *dev = video_devdata(file);
-       struct camera_data *cam = video_get_drvdata(dev);
-
-       mutex_lock(&cam->v4l2_lock);
-       if (video_is_registered(&cam->vdev) && v4l2_fh_is_singular_file(file)) {
-               cpia2_usb_stream_stop(cam);
-
-               /* save camera state for later open */
-               cpia2_save_camera_state(cam);
-
-               cpia2_set_low_power(cam);
-               cpia2_free_buffers(cam);
-       }
-
-       if (cam->stream_fh == file->private_data) {
-               cam->stream_fh = NULL;
-               cam->mmapped = 0;
-       }
-       mutex_unlock(&cam->v4l2_lock);
-       return v4l2_fh_release(file);
-}
-
-/******************************************************************************
- *
- *  cpia2_v4l_read
- *
- *****************************************************************************/
-static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count,
-                             loff_t *off)
-{
-       struct camera_data *cam = video_drvdata(file);
-       int noblock = file->f_flags&O_NONBLOCK;
-       ssize_t ret;
-
-       if(!cam)
-               return -EINVAL;
-
-       if (mutex_lock_interruptible(&cam->v4l2_lock))
-               return -ERESTARTSYS;
-       ret = cpia2_read(cam, buf, count, noblock);
-       mutex_unlock(&cam->v4l2_lock);
-       return ret;
-}
-
-
-/******************************************************************************
- *
- *  cpia2_v4l_poll
- *
- *****************************************************************************/
-static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait)
-{
-       struct camera_data *cam = video_drvdata(filp);
-       unsigned int res;
-
-       mutex_lock(&cam->v4l2_lock);
-       res = cpia2_poll(cam, filp, wait);
-       mutex_unlock(&cam->v4l2_lock);
-       return res;
-}
-
-
-static int sync(struct camera_data *cam, int frame_nr)
-{
-       struct framebuf *frame = &cam->buffers[frame_nr];
-
-       while (1) {
-               if (frame->status == FRAME_READY)
-                       return 0;
-
-               if (!cam->streaming) {
-                       frame->status = FRAME_READY;
-                       frame->length = 0;
-                       return 0;
-               }
-
-               mutex_unlock(&cam->v4l2_lock);
-               wait_event_interruptible(cam->wq_stream,
-                                        !cam->streaming ||
-                                        frame->status == FRAME_READY);
-               mutex_lock(&cam->v4l2_lock);
-               if (signal_pending(current))
-                       return -ERESTARTSYS;
-               if (!video_is_registered(&cam->vdev))
-                       return -ENOTTY;
-       }
-}
-
-/******************************************************************************
- *
- *  ioctl_querycap
- *
- *  V4L2 device capabilities
- *
- *****************************************************************************/
-
-static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *vc)
-{
-       struct camera_data *cam = video_drvdata(file);
-
-       strcpy(vc->driver, "cpia2");
-
-       if (cam->params.pnp_id.product == 0x151)
-               strcpy(vc->card, "QX5 Microscope");
-       else
-               strcpy(vc->card, "CPiA2 Camera");
-       switch (cam->params.pnp_id.device_type) {
-       case DEVICE_STV_672:
-               strcat(vc->card, " (672/");
-               break;
-       case DEVICE_STV_676:
-               strcat(vc->card, " (676/");
-               break;
-       default:
-               strcat(vc->card, " (XXX/");
-               break;
-       }
-       switch (cam->params.version.sensor_flags) {
-       case CPIA2_VP_SENSOR_FLAGS_404:
-               strcat(vc->card, "404)");
-               break;
-       case CPIA2_VP_SENSOR_FLAGS_407:
-               strcat(vc->card, "407)");
-               break;
-       case CPIA2_VP_SENSOR_FLAGS_409:
-               strcat(vc->card, "409)");
-               break;
-       case CPIA2_VP_SENSOR_FLAGS_410:
-               strcat(vc->card, "410)");
-               break;
-       case CPIA2_VP_SENSOR_FLAGS_500:
-               strcat(vc->card, "500)");
-               break;
-       default:
-               strcat(vc->card, "XXX)");
-               break;
-       }
-
-       if (usb_make_path(cam->dev, vc->bus_info, sizeof(vc->bus_info)) <0)
-               memset(vc->bus_info,0, sizeof(vc->bus_info));
-
-       vc->device_caps = V4L2_CAP_VIDEO_CAPTURE |
-                          V4L2_CAP_READWRITE |
-                          V4L2_CAP_STREAMING;
-       vc->capabilities = vc->device_caps |
-                          V4L2_CAP_DEVICE_CAPS;
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  ioctl_input
- *
- *  V4L2 input get/set/enumerate
- *
- *****************************************************************************/
-
-static int cpia2_enum_input(struct file *file, void *fh, struct v4l2_input *i)
-{
-       if (i->index)
-               return -EINVAL;
-       strcpy(i->name, "Camera");
-       i->type = V4L2_INPUT_TYPE_CAMERA;
-       return 0;
-}
-
-static int cpia2_g_input(struct file *file, void *fh, unsigned int *i)
-{
-       *i = 0;
-       return 0;
-}
-
-static int cpia2_s_input(struct file *file, void *fh, unsigned int i)
-{
-       return i ? -EINVAL : 0;
-}
-
-/******************************************************************************
- *
- *  ioctl_enum_fmt
- *
- *  V4L2 format enumerate
- *
- *****************************************************************************/
-
-static int cpia2_enum_fmt_vid_cap(struct file *file, void *fh,
-                                           struct v4l2_fmtdesc *f)
-{
-       int index = f->index;
-
-       if (index < 0 || index > 1)
-              return -EINVAL;
-
-       memset(f, 0, sizeof(*f));
-       f->index = index;
-       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       f->flags = V4L2_FMT_FLAG_COMPRESSED;
-       switch(index) {
-       case 0:
-               strcpy(f->description, "MJPEG");
-               f->pixelformat = V4L2_PIX_FMT_MJPEG;
-               break;
-       case 1:
-               strcpy(f->description, "JPEG");
-               f->pixelformat = V4L2_PIX_FMT_JPEG;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  ioctl_try_fmt
- *
- *  V4L2 format try
- *
- *****************************************************************************/
-
-static int cpia2_try_fmt_vid_cap(struct file *file, void *fh,
-                                         struct v4l2_format *f)
-{
-       struct camera_data *cam = video_drvdata(file);
-
-       if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG &&
-           f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG)
-              return -EINVAL;
-
-       f->fmt.pix.field = V4L2_FIELD_NONE;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage = cam->frame_size;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-       f->fmt.pix.priv = 0;
-
-       switch (cpia2_match_video_size(f->fmt.pix.width, f->fmt.pix.height)) {
-       case VIDEOSIZE_VGA:
-               f->fmt.pix.width = 640;
-               f->fmt.pix.height = 480;
-               break;
-       case VIDEOSIZE_CIF:
-               f->fmt.pix.width = 352;
-               f->fmt.pix.height = 288;
-               break;
-       case VIDEOSIZE_QVGA:
-               f->fmt.pix.width = 320;
-               f->fmt.pix.height = 240;
-               break;
-       case VIDEOSIZE_288_216:
-               f->fmt.pix.width = 288;
-               f->fmt.pix.height = 216;
-               break;
-       case VIDEOSIZE_256_192:
-               f->fmt.pix.width = 256;
-               f->fmt.pix.height = 192;
-               break;
-       case VIDEOSIZE_224_168:
-               f->fmt.pix.width = 224;
-               f->fmt.pix.height = 168;
-               break;
-       case VIDEOSIZE_192_144:
-               f->fmt.pix.width = 192;
-               f->fmt.pix.height = 144;
-               break;
-       case VIDEOSIZE_QCIF:
-       default:
-               f->fmt.pix.width = 176;
-               f->fmt.pix.height = 144;
-               break;
-       }
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  ioctl_set_fmt
- *
- *  V4L2 format set
- *
- *****************************************************************************/
-
-static int cpia2_s_fmt_vid_cap(struct file *file, void *_fh,
-                                       struct v4l2_format *f)
-{
-       struct camera_data *cam = video_drvdata(file);
-       int err, frame;
-
-       err = cpia2_try_fmt_vid_cap(file, _fh, f);
-       if(err != 0)
-               return err;
-
-       cam->pixelformat = f->fmt.pix.pixelformat;
-
-       /* NOTE: This should be set to 1 for MJPEG, but some apps don't handle
-        * the missing Huffman table properly. */
-       cam->params.compression.inhibit_htables = 0;
-               /*f->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG;*/
-
-       /* we set the video window to something smaller or equal to what
-        * is requested by the user???
-        */
-       DBG("Requested width = %d, height = %d\n",
-           f->fmt.pix.width, f->fmt.pix.height);
-       if (f->fmt.pix.width != cam->width ||
-           f->fmt.pix.height != cam->height) {
-               cam->width = f->fmt.pix.width;
-               cam->height = f->fmt.pix.height;
-               cam->params.roi.width = f->fmt.pix.width;
-               cam->params.roi.height = f->fmt.pix.height;
-               cpia2_set_format(cam);
-       }
-
-       for (frame = 0; frame < cam->num_frames; ++frame) {
-               if (cam->buffers[frame].status == FRAME_READING)
-                       if ((err = sync(cam, frame)) < 0)
-                               return err;
-
-               cam->buffers[frame].status = FRAME_EMPTY;
-       }
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  ioctl_get_fmt
- *
- *  V4L2 format get
- *
- *****************************************************************************/
-
-static int cpia2_g_fmt_vid_cap(struct file *file, void *fh,
-                                       struct v4l2_format *f)
-{
-       struct camera_data *cam = video_drvdata(file);
-
-       f->fmt.pix.width = cam->width;
-       f->fmt.pix.height = cam->height;
-       f->fmt.pix.pixelformat = cam->pixelformat;
-       f->fmt.pix.field = V4L2_FIELD_NONE;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage = cam->frame_size;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
-       f->fmt.pix.priv = 0;
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  ioctl_cropcap
- *
- *  V4L2 query cropping capabilities
- *  NOTE: cropping is currently disabled
- *
- *****************************************************************************/
-
-static int cpia2_cropcap(struct file *file, void *fh, struct v4l2_cropcap *c)
-{
-       struct camera_data *cam = video_drvdata(file);
-
-       if (c->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-              return -EINVAL;
-
-       c->bounds.left = 0;
-       c->bounds.top = 0;
-       c->bounds.width = cam->width;
-       c->bounds.height = cam->height;
-       c->defrect.left = 0;
-       c->defrect.top = 0;
-       c->defrect.width = cam->width;
-       c->defrect.height = cam->height;
-       c->pixelaspect.numerator = 1;
-       c->pixelaspect.denominator = 1;
-
-       return 0;
-}
-
-struct framerate_info {
-       int value;
-       struct v4l2_fract period;
-};
-
-static const struct framerate_info framerate_controls[] = {
-       { CPIA2_VP_FRAMERATE_6_25, { 4, 25 } },
-       { CPIA2_VP_FRAMERATE_7_5,  { 2, 15 } },
-       { CPIA2_VP_FRAMERATE_12_5, { 2, 25 } },
-       { CPIA2_VP_FRAMERATE_15,   { 1, 15 } },
-       { CPIA2_VP_FRAMERATE_25,   { 1, 25 } },
-       { CPIA2_VP_FRAMERATE_30,   { 1, 30 } },
-};
-
-static int cpia2_g_parm(struct file *file, void *fh, struct v4l2_streamparm *p)
-{
-       struct camera_data *cam = video_drvdata(file);
-       struct v4l2_captureparm *cap = &p->parm.capture;
-       int i;
-
-       if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       cap->capability = V4L2_CAP_TIMEPERFRAME;
-       cap->readbuffers = cam->num_frames;
-       for (i = 0; i < ARRAY_SIZE(framerate_controls); i++)
-               if (cam->params.vp_params.frame_rate == framerate_controls[i].value) {
-                       cap->timeperframe = framerate_controls[i].period;
-                       break;
-               }
-       return 0;
-}
-
-static int cpia2_s_parm(struct file *file, void *fh, struct v4l2_streamparm *p)
-{
-       struct camera_data *cam = video_drvdata(file);
-       struct v4l2_captureparm *cap = &p->parm.capture;
-       struct v4l2_fract tpf = cap->timeperframe;
-       int max = ARRAY_SIZE(framerate_controls) - 1;
-       int ret;
-       int i;
-
-       ret = cpia2_g_parm(file, fh, p);
-       if (ret || !tpf.denominator || !tpf.numerator)
-               return ret;
-
-       /* Maximum 15 fps for this model */
-       if (cam->params.pnp_id.device_type == DEVICE_STV_672 &&
-           cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500)
-               max -= 2;
-       for (i = 0; i <= max; i++) {
-               struct v4l2_fract f1 = tpf;
-               struct v4l2_fract f2 = framerate_controls[i].period;
-
-               f1.numerator *= f2.denominator;
-               f2.numerator *= f1.denominator;
-               if (f1.numerator >= f2.numerator)
-                       break;
-       }
-       if (i > max)
-               i = max;
-       cap->timeperframe = framerate_controls[i].period;
-       return cpia2_set_fps(cam, framerate_controls[i].value);
-}
-
-static const struct {
-       u32 width;
-       u32 height;
-} cpia2_framesizes[] = {
-       { 640, 480 },
-       { 352, 288 },
-       { 320, 240 },
-       { 288, 216 },
-       { 256, 192 },
-       { 224, 168 },
-       { 192, 144 },
-       { 176, 144 },
-};
-
-static int cpia2_enum_framesizes(struct file *file, void *fh,
-                                        struct v4l2_frmsizeenum *fsize)
-{
-
-       if (fsize->pixel_format != V4L2_PIX_FMT_MJPEG &&
-           fsize->pixel_format != V4L2_PIX_FMT_JPEG)
-               return -EINVAL;
-       if (fsize->index >= ARRAY_SIZE(cpia2_framesizes))
-               return -EINVAL;
-       fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-       fsize->discrete.width = cpia2_framesizes[fsize->index].width;
-       fsize->discrete.height = cpia2_framesizes[fsize->index].height;
-
-       return 0;
-}
-
-static int cpia2_enum_frameintervals(struct file *file, void *fh,
-                                          struct v4l2_frmivalenum *fival)
-{
-       struct camera_data *cam = video_drvdata(file);
-       int max = ARRAY_SIZE(framerate_controls) - 1;
-       int i;
-
-       if (fival->pixel_format != V4L2_PIX_FMT_MJPEG &&
-           fival->pixel_format != V4L2_PIX_FMT_JPEG)
-               return -EINVAL;
-
-       /* Maximum 15 fps for this model */
-       if (cam->params.pnp_id.device_type == DEVICE_STV_672 &&
-           cam->params.version.sensor_flags == CPIA2_VP_SENSOR_FLAGS_500)
-               max -= 2;
-       if (fival->index > max)
-               return -EINVAL;
-       for (i = 0; i < ARRAY_SIZE(cpia2_framesizes); i++)
-               if (fival->width == cpia2_framesizes[i].width &&
-                   fival->height == cpia2_framesizes[i].height)
-                       break;
-       if (i == ARRAY_SIZE(cpia2_framesizes))
-               return -EINVAL;
-       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-       fival->discrete = framerate_controls[fival->index].period;
-       return 0;
-}
-
-/******************************************************************************
- *
- *  ioctl_s_ctrl
- *
- *  V4L2 set the value of a control variable
- *
- *****************************************************************************/
-
-static int cpia2_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct camera_data *cam =
-               container_of(ctrl->handler, struct camera_data, hdl);
-       static const int flicker_table[] = {
-               NEVER_FLICKER,
-               FLICKER_50,
-               FLICKER_60,
-       };
-
-       DBG("Set control id:%d, value:%d\n", ctrl->id, ctrl->val);
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               cpia2_set_brightness(cam, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               cpia2_set_contrast(cam, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               cpia2_set_saturation(cam, ctrl->val);
-               break;
-       case V4L2_CID_HFLIP:
-               cpia2_set_property_mirror(cam, ctrl->val);
-               break;
-       case V4L2_CID_VFLIP:
-               cpia2_set_property_flip(cam, ctrl->val);
-               break;
-       case V4L2_CID_POWER_LINE_FREQUENCY:
-               return cpia2_set_flicker_mode(cam, flicker_table[ctrl->val]);
-       case V4L2_CID_ILLUMINATORS_1:
-               return cpia2_set_gpio(cam, (cam->top_light->val << 6) |
-                                          (cam->bottom_light->val << 7));
-       case V4L2_CID_JPEG_ACTIVE_MARKER:
-               cam->params.compression.inhibit_htables =
-                       !(ctrl->val & V4L2_JPEG_ACTIVE_MARKER_DHT);
-               break;
-       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
-               cam->params.vc_params.quality = ctrl->val;
-               break;
-       case CPIA2_CID_USB_ALT:
-               cam->params.camera_state.stream_mode = ctrl->val;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  ioctl_g_jpegcomp
- *
- *  V4L2 get the JPEG compression parameters
- *
- *****************************************************************************/
-
-static int cpia2_g_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompression *parms)
-{
-       struct camera_data *cam = video_drvdata(file);
-
-       memset(parms, 0, sizeof(*parms));
-
-       parms->quality = 80; // TODO: Can this be made meaningful?
-
-       parms->jpeg_markers = V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI;
-       if(!cam->params.compression.inhibit_htables) {
-               parms->jpeg_markers |= V4L2_JPEG_MARKER_DHT;
-       }
-
-       parms->APPn = cam->APPn;
-       parms->APP_len = cam->APP_len;
-       if(cam->APP_len > 0) {
-               memcpy(parms->APP_data, cam->APP_data, cam->APP_len);
-               parms->jpeg_markers |= V4L2_JPEG_MARKER_APP;
-       }
-
-       parms->COM_len = cam->COM_len;
-       if(cam->COM_len > 0) {
-               memcpy(parms->COM_data, cam->COM_data, cam->COM_len);
-               parms->jpeg_markers |= JPEG_MARKER_COM;
-       }
-
-       DBG("G_JPEGCOMP APP_len:%d COM_len:%d\n",
-           parms->APP_len, parms->COM_len);
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  ioctl_s_jpegcomp
- *
- *  V4L2 set the JPEG compression parameters
- *  NOTE: quality and some jpeg_markers are ignored.
- *
- *****************************************************************************/
-
-static int cpia2_s_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompression *parms)
-{
-       struct camera_data *cam = video_drvdata(file);
-
-       DBG("S_JPEGCOMP APP_len:%d COM_len:%d\n",
-           parms->APP_len, parms->COM_len);
-
-       cam->params.compression.inhibit_htables =
-               !(parms->jpeg_markers & V4L2_JPEG_MARKER_DHT);
-       parms->jpeg_markers &= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI |
-                              V4L2_JPEG_MARKER_DHT;
-
-       if(parms->APP_len != 0) {
-               if(parms->APP_len > 0 &&
-                  parms->APP_len <= sizeof(cam->APP_data) &&
-                  parms->APPn >= 0 && parms->APPn <= 15) {
-                       cam->APPn = parms->APPn;
-                       cam->APP_len = parms->APP_len;
-                       memcpy(cam->APP_data, parms->APP_data, parms->APP_len);
-               } else {
-                       LOG("Bad APPn Params n=%d len=%d\n",
-                           parms->APPn, parms->APP_len);
-                       return -EINVAL;
-               }
-       } else {
-               cam->APP_len = 0;
-       }
-
-       if(parms->COM_len != 0) {
-               if(parms->COM_len > 0 &&
-                  parms->COM_len <= sizeof(cam->COM_data)) {
-                       cam->COM_len = parms->COM_len;
-                       memcpy(cam->COM_data, parms->COM_data, parms->COM_len);
-               } else {
-                       LOG("Bad COM_len=%d\n", parms->COM_len);
-                       return -EINVAL;
-               }
-       }
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  ioctl_reqbufs
- *
- *  V4L2 Initiate memory mapping.
- *  NOTE: The user's request is ignored. For now the buffers are fixed.
- *
- *****************************************************************************/
-
-static int cpia2_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *req)
-{
-       struct camera_data *cam = video_drvdata(file);
-
-       if(req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-          req->memory != V4L2_MEMORY_MMAP)
-               return -EINVAL;
-
-       DBG("REQBUFS requested:%d returning:%d\n", req->count, cam->num_frames);
-       req->count = cam->num_frames;
-       memset(&req->reserved, 0, sizeof(req->reserved));
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  ioctl_querybuf
- *
- *  V4L2 Query memory buffer status.
- *
- *****************************************************************************/
-
-static int cpia2_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
-{
-       struct camera_data *cam = video_drvdata(file);
-
-       if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-          buf->index > cam->num_frames)
-               return -EINVAL;
-
-       buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer;
-       buf->length = cam->frame_size;
-
-       buf->memory = V4L2_MEMORY_MMAP;
-
-       if(cam->mmapped)
-               buf->flags = V4L2_BUF_FLAG_MAPPED;
-       else
-               buf->flags = 0;
-
-       switch (cam->buffers[buf->index].status) {
-       case FRAME_EMPTY:
-       case FRAME_ERROR:
-       case FRAME_READING:
-               buf->bytesused = 0;
-               buf->flags = V4L2_BUF_FLAG_QUEUED;
-               break;
-       case FRAME_READY:
-               buf->bytesused = cam->buffers[buf->index].length;
-               buf->timestamp = cam->buffers[buf->index].timestamp;
-               buf->sequence = cam->buffers[buf->index].seq;
-               buf->flags = V4L2_BUF_FLAG_DONE;
-               break;
-       }
-
-       DBG("QUERYBUF index:%d offset:%d flags:%d seq:%d bytesused:%d\n",
-            buf->index, buf->m.offset, buf->flags, buf->sequence,
-            buf->bytesused);
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  ioctl_qbuf
- *
- *  V4L2 User is freeing buffer
- *
- *****************************************************************************/
-
-static int cpia2_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
-{
-       struct camera_data *cam = video_drvdata(file);
-
-       if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-          buf->memory != V4L2_MEMORY_MMAP ||
-          buf->index > cam->num_frames)
-               return -EINVAL;
-
-       DBG("QBUF #%d\n", buf->index);
-
-       if(cam->buffers[buf->index].status == FRAME_READY)
-               cam->buffers[buf->index].status = FRAME_EMPTY;
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  find_earliest_filled_buffer
- *
- *  Helper for ioctl_dqbuf. Find the next ready buffer.
- *
- *****************************************************************************/
-
-static int find_earliest_filled_buffer(struct camera_data *cam)
-{
-       int i;
-       int found = -1;
-       for (i=0; i<cam->num_frames; i++) {
-               if(cam->buffers[i].status == FRAME_READY) {
-                       if(found < 0) {
-                               found = i;
-                       } else {
-                               /* find which buffer is earlier */
-                               struct timeval *tv1, *tv2;
-                               tv1 = &cam->buffers[i].timestamp;
-                               tv2 = &cam->buffers[found].timestamp;
-                               if(tv1->tv_sec < tv2->tv_sec ||
-                                  (tv1->tv_sec == tv2->tv_sec &&
-                                   tv1->tv_usec < tv2->tv_usec))
-                                       found = i;
-                       }
-               }
-       }
-       return found;
-}
-
-/******************************************************************************
- *
- *  ioctl_dqbuf
- *
- *  V4L2 User is asking for a filled buffer.
- *
- *****************************************************************************/
-
-static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
-{
-       struct camera_data *cam = video_drvdata(file);
-       int frame;
-
-       if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-          buf->memory != V4L2_MEMORY_MMAP)
-               return -EINVAL;
-
-       frame = find_earliest_filled_buffer(cam);
-
-       if(frame < 0 && file->f_flags&O_NONBLOCK)
-               return -EAGAIN;
-
-       if(frame < 0) {
-               /* Wait for a frame to become available */
-               struct framebuf *cb=cam->curbuff;
-               mutex_unlock(&cam->v4l2_lock);
-               wait_event_interruptible(cam->wq_stream,
-                                        !video_is_registered(&cam->vdev) ||
-                                        (cb=cam->curbuff)->status == FRAME_READY);
-               mutex_lock(&cam->v4l2_lock);
-               if (signal_pending(current))
-                       return -ERESTARTSYS;
-               if (!video_is_registered(&cam->vdev))
-                       return -ENOTTY;
-               frame = cb->num;
-       }
-
-
-       buf->index = frame;
-       buf->bytesused = cam->buffers[buf->index].length;
-       buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
-       buf->field = V4L2_FIELD_NONE;
-       buf->timestamp = cam->buffers[buf->index].timestamp;
-       buf->sequence = cam->buffers[buf->index].seq;
-       buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer;
-       buf->length = cam->frame_size;
-       buf->reserved2 = 0;
-       buf->reserved = 0;
-       memset(&buf->timecode, 0, sizeof(buf->timecode));
-
-       DBG("DQBUF #%d status:%d seq:%d length:%d\n", buf->index,
-           cam->buffers[buf->index].status, buf->sequence, buf->bytesused);
-
-       return 0;
-}
-
-static int cpia2_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
-{
-       struct camera_data *cam = video_drvdata(file);
-       int ret = -EINVAL;
-
-       DBG("VIDIOC_STREAMON, streaming=%d\n", cam->streaming);
-       if (!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       if (!cam->streaming) {
-               ret = cpia2_usb_stream_start(cam,
-                               cam->params.camera_state.stream_mode);
-               if (!ret)
-                       v4l2_ctrl_grab(cam->usb_alt, true);
-       }
-       return ret;
-}
-
-static int cpia2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
-{
-       struct camera_data *cam = video_drvdata(file);
-       int ret = -EINVAL;
-
-       DBG("VIDIOC_STREAMOFF, streaming=%d\n", cam->streaming);
-       if (!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       if (cam->streaming) {
-               ret = cpia2_usb_stream_stop(cam);
-               if (!ret)
-                       v4l2_ctrl_grab(cam->usb_alt, false);
-       }
-       return ret;
-}
-
-/******************************************************************************
- *
- *  cpia2_mmap
- *
- *****************************************************************************/
-static int cpia2_mmap(struct file *file, struct vm_area_struct *area)
-{
-       struct camera_data *cam = video_drvdata(file);
-       int retval;
-
-       if (mutex_lock_interruptible(&cam->v4l2_lock))
-               return -ERESTARTSYS;
-       retval = cpia2_remap_buffer(cam, area);
-
-       if(!retval)
-               cam->stream_fh = file->private_data;
-       mutex_unlock(&cam->v4l2_lock);
-       return retval;
-}
-
-/******************************************************************************
- *
- *  reset_camera_struct_v4l
- *
- *  Sets all values to the defaults
- *****************************************************************************/
-static void reset_camera_struct_v4l(struct camera_data *cam)
-{
-       cam->width = cam->params.roi.width;
-       cam->height = cam->params.roi.height;
-
-       cam->frame_size = buffer_size;
-       cam->num_frames = num_buffers;
-
-       /* Flicker modes */
-       cam->params.flicker_control.flicker_mode_req = flicker_mode;
-
-       /* stream modes */
-       cam->params.camera_state.stream_mode = alternate;
-
-       cam->pixelformat = V4L2_PIX_FMT_JPEG;
-}
-
-static const struct v4l2_ioctl_ops cpia2_ioctl_ops = {
-       .vidioc_querycap                    = cpia2_querycap,
-       .vidioc_enum_input                  = cpia2_enum_input,
-       .vidioc_g_input                     = cpia2_g_input,
-       .vidioc_s_input                     = cpia2_s_input,
-       .vidioc_enum_fmt_vid_cap            = cpia2_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap               = cpia2_g_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap               = cpia2_s_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap             = cpia2_try_fmt_vid_cap,
-       .vidioc_g_jpegcomp                  = cpia2_g_jpegcomp,
-       .vidioc_s_jpegcomp                  = cpia2_s_jpegcomp,
-       .vidioc_cropcap                     = cpia2_cropcap,
-       .vidioc_reqbufs                     = cpia2_reqbufs,
-       .vidioc_querybuf                    = cpia2_querybuf,
-       .vidioc_qbuf                        = cpia2_qbuf,
-       .vidioc_dqbuf                       = cpia2_dqbuf,
-       .vidioc_streamon                    = cpia2_streamon,
-       .vidioc_streamoff                   = cpia2_streamoff,
-       .vidioc_s_parm                      = cpia2_s_parm,
-       .vidioc_g_parm                      = cpia2_g_parm,
-       .vidioc_enum_framesizes             = cpia2_enum_framesizes,
-       .vidioc_enum_frameintervals         = cpia2_enum_frameintervals,
-       .vidioc_subscribe_event             = v4l2_ctrl_subscribe_event,
-       .vidioc_unsubscribe_event           = v4l2_event_unsubscribe,
-};
-
-/***
- * The v4l video device structure initialized for this device
- ***/
-static const struct v4l2_file_operations cpia2_fops = {
-       .owner          = THIS_MODULE,
-       .open           = cpia2_open,
-       .release        = cpia2_close,
-       .read           = cpia2_v4l_read,
-       .poll           = cpia2_v4l_poll,
-       .unlocked_ioctl = video_ioctl2,
-       .mmap           = cpia2_mmap,
-};
-
-static struct video_device cpia2_template = {
-       /* I could not find any place for the old .initialize initializer?? */
-       .name =         "CPiA2 Camera",
-       .fops =         &cpia2_fops,
-       .ioctl_ops =    &cpia2_ioctl_ops,
-       .release =      video_device_release_empty,
-};
-
-void cpia2_camera_release(struct v4l2_device *v4l2_dev)
-{
-       struct camera_data *cam =
-               container_of(v4l2_dev, struct camera_data, v4l2_dev);
-
-       v4l2_ctrl_handler_free(&cam->hdl);
-       v4l2_device_unregister(&cam->v4l2_dev);
-       kfree(cam);
-}
-
-static const struct v4l2_ctrl_ops cpia2_ctrl_ops = {
-       .s_ctrl = cpia2_s_ctrl,
-};
-
-/******************************************************************************
- *
- *  cpia2_register_camera
- *
- *****************************************************************************/
-int cpia2_register_camera(struct camera_data *cam)
-{
-       struct v4l2_ctrl_handler *hdl = &cam->hdl;
-       struct v4l2_ctrl_config cpia2_usb_alt = {
-               .ops = &cpia2_ctrl_ops,
-               .id = CPIA2_CID_USB_ALT,
-               .name = "USB Alternate",
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .min = USBIF_ISO_1,
-               .max = USBIF_ISO_6,
-               .step = 1,
-       };
-       int ret;
-
-       v4l2_ctrl_handler_init(hdl, 12);
-       v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS,
-                       cam->params.pnp_id.device_type == DEVICE_STV_672 ? 1 : 0,
-                       255, 1, DEFAULT_BRIGHTNESS);
-       v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 255, 1, DEFAULT_CONTRAST);
-       v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 255, 1, DEFAULT_SATURATION);
-       v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
-                       V4L2_CID_HFLIP, 0, 1, 1, 0);
-       v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
-                       V4L2_CID_JPEG_ACTIVE_MARKER, 0,
-                       V4L2_JPEG_ACTIVE_MARKER_DHT, 0,
-                       V4L2_JPEG_ACTIVE_MARKER_DHT);
-       v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
-                       V4L2_CID_JPEG_COMPRESSION_QUALITY, 1,
-                       100, 1, 100);
-       cpia2_usb_alt.def = alternate;
-       cam->usb_alt = v4l2_ctrl_new_custom(hdl, &cpia2_usb_alt, NULL);
-       /* VP5 Only */
-       if (cam->params.pnp_id.device_type != DEVICE_STV_672)
-               v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
-                       V4L2_CID_VFLIP, 0, 1, 1, 0);
-       /* Flicker control only valid for 672 */
-       if (cam->params.pnp_id.device_type == DEVICE_STV_672)
-               v4l2_ctrl_new_std_menu(hdl, &cpia2_ctrl_ops,
-                       V4L2_CID_POWER_LINE_FREQUENCY,
-                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
-       /* Light control only valid for the QX5 Microscope */
-       if (cam->params.pnp_id.product == 0x151) {
-               cam->top_light = v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
-                               V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
-               cam->bottom_light = v4l2_ctrl_new_std(hdl, &cpia2_ctrl_ops,
-                               V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0);
-               v4l2_ctrl_cluster(2, &cam->top_light);
-       }
-
-       if (hdl->error) {
-               ret = hdl->error;
-               v4l2_ctrl_handler_free(hdl);
-               return ret;
-       }
-
-       cam->vdev = cpia2_template;
-       video_set_drvdata(&cam->vdev, cam);
-       cam->vdev.lock = &cam->v4l2_lock;
-       cam->vdev.ctrl_handler = hdl;
-       cam->vdev.v4l2_dev = &cam->v4l2_dev;
-       set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
-
-       reset_camera_struct_v4l(cam);
-
-       /* register v4l device */
-       if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
-               ERR("video_register_device failed\n");
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-/******************************************************************************
- *
- *  cpia2_unregister_camera
- *
- *****************************************************************************/
-void cpia2_unregister_camera(struct camera_data *cam)
-{
-       video_unregister_device(&cam->vdev);
-}
-
-/******************************************************************************
- *
- *  check_parameters
- *
- *  Make sure that all user-supplied parameters are sensible
- *****************************************************************************/
-static void __init check_parameters(void)
-{
-       if(buffer_size < PAGE_SIZE) {
-               buffer_size = PAGE_SIZE;
-               LOG("buffer_size too small, setting to %d\n", buffer_size);
-       } else if(buffer_size > 1024*1024) {
-               /* arbitrary upper limiit */
-               buffer_size = 1024*1024;
-               LOG("buffer_size ridiculously large, setting to %d\n",
-                   buffer_size);
-       } else {
-               buffer_size += PAGE_SIZE-1;
-               buffer_size &= ~(PAGE_SIZE-1);
-       }
-
-       if(num_buffers < 1) {
-               num_buffers = 1;
-               LOG("num_buffers too small, setting to %d\n", num_buffers);
-       } else if(num_buffers > VIDEO_MAX_FRAME) {
-               num_buffers = VIDEO_MAX_FRAME;
-               LOG("num_buffers too large, setting to %d\n", num_buffers);
-       }
-
-       if(alternate < USBIF_ISO_1 || alternate > USBIF_ISO_6) {
-               alternate = DEFAULT_ALT;
-               LOG("alternate specified is invalid, using %d\n", alternate);
-       }
-
-       if (flicker_mode != 0 && flicker_mode != FLICKER_50 && flicker_mode != FLICKER_60) {
-               flicker_mode = 0;
-               LOG("Flicker mode specified is invalid, using %d\n",
-                   flicker_mode);
-       }
-
-       DBG("Using %d buffers, each %d bytes, alternate=%d\n",
-           num_buffers, buffer_size, alternate);
-}
-
-/************   Module Stuff ***************/
-
-
-/******************************************************************************
- *
- * cpia2_init/module_init
- *
- *****************************************************************************/
-static int __init cpia2_init(void)
-{
-       LOG("%s v%s\n",
-           ABOUT, CPIA_VERSION);
-       check_parameters();
-       cpia2_usb_init();
-       return 0;
-}
-
-
-/******************************************************************************
- *
- * cpia2_exit/module_exit
- *
- *****************************************************************************/
-static void __exit cpia2_exit(void)
-{
-       cpia2_usb_cleanup();
-       schedule_timeout(2 * HZ);
-}
-
-module_init(cpia2_init);
-module_exit(cpia2_exit);
diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig
deleted file mode 100644 (file)
index 446f692..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-config VIDEO_CX231XX
-       tristate "Conexant cx231xx USB video capture support"
-       depends on VIDEO_DEV && I2C
-       select VIDEO_TUNER
-       select VIDEO_TVEEPROM
-       depends on RC_CORE
-       select VIDEOBUF_VMALLOC
-       select VIDEO_CX25840
-       select VIDEO_CX2341X
-
-       ---help---
-         This is a video4linux driver for Conexant 231xx USB based TV cards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx231xx
-
-config VIDEO_CX231XX_RC
-       bool "Conexant cx231xx Remote Controller additional support"
-       depends on RC_CORE
-       depends on VIDEO_CX231XX
-       default y
-       ---help---
-         cx231xx hardware has a builtin RX/TX support. However, a few
-         designs opted to not use it, but, instead, some other hardware.
-         This module enables the usage of those other hardware, like the
-         ones used with ISDB-T boards.
-
-         On most cases, all you need for IR is mceusb module.
-
-config VIDEO_CX231XX_ALSA
-       tristate "Conexant Cx231xx ALSA audio module"
-       depends on VIDEO_CX231XX && SND
-       select SND_PCM
-
-       ---help---
-         This is an ALSA driver for Cx231xx USB based TV cards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx231xx-alsa
-
-config VIDEO_CX231XX_DVB
-       tristate "DVB/ATSC Support for Cx231xx based TV cards"
-       depends on VIDEO_CX231XX && DVB_CORE && DVB_CAPTURE_DRIVERS
-       select VIDEOBUF_DVB
-       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
-       select DVB_MB86A20S if !DVB_FE_CUSTOMISE
-
-       ---help---
-         This adds support for DVB cards based on the
-         Conexant cx231xx chips.
diff --git a/drivers/media/video/cx231xx/Makefile b/drivers/media/video/cx231xx/Makefile
deleted file mode 100644 (file)
index 1d40fce..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-cx231xx-y += cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o
-cx231xx-y += cx231xx-avcore.o cx231xx-417.o cx231xx-pcb-cfg.o cx231xx-vbi.o
-cx231xx-$(CONFIG_VIDEO_CX231XX_RC) += cx231xx-input.o
-
-cx231xx-alsa-objs := cx231xx-audio.o
-
-obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o
-obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o
-obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o
-
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/tuners
-ccflags-y += -Idrivers/media/dvb-core
-ccflags-y += -Idrivers/media/dvb-frontends
-ccflags-y += -Idrivers/media/usb/dvb-usb
diff --git a/drivers/media/video/cx231xx/cx231xx-417.c b/drivers/media/video/cx231xx/cx231xx-417.c
deleted file mode 100644 (file)
index b024e51..0000000
+++ /dev/null
@@ -1,2197 +0,0 @@
-/*
- *
- *  Support for a cx23417 mpeg encoder via cx231xx host port.
- *
- *    (c) 2004 Jelle Foks <jelle@foks.us>
- *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
- *    (c) 2008 Steven Toth <stoth@linuxtv.org>
- *      - CX23885/7/8 support
- *
- *  Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/firmware.h>
-#include <linux/vmalloc.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/cx2341x.h>
-#include <linux/usb.h>
-
-#include "cx231xx.h"
-/*#include "cx23885-ioctl.h"*/
-
-#define CX231xx_FIRM_IMAGE_SIZE 376836
-#define CX231xx_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
-
-/* for polaris ITVC */
-#define ITVC_WRITE_DIR          0x03FDFC00
-#define ITVC_READ_DIR            0x0001FC00
-
-#define  MCI_MEMORY_DATA_BYTE0          0x00
-#define  MCI_MEMORY_DATA_BYTE1          0x08
-#define  MCI_MEMORY_DATA_BYTE2          0x10
-#define  MCI_MEMORY_DATA_BYTE3          0x18
-
-#define  MCI_MEMORY_ADDRESS_BYTE2       0x20
-#define  MCI_MEMORY_ADDRESS_BYTE1       0x28
-#define  MCI_MEMORY_ADDRESS_BYTE0       0x30
-
-#define  MCI_REGISTER_DATA_BYTE0        0x40
-#define  MCI_REGISTER_DATA_BYTE1        0x48
-#define  MCI_REGISTER_DATA_BYTE2        0x50
-#define  MCI_REGISTER_DATA_BYTE3        0x58
-
-#define  MCI_REGISTER_ADDRESS_BYTE0     0x60
-#define  MCI_REGISTER_ADDRESS_BYTE1     0x68
-
-#define  MCI_REGISTER_MODE              0x70
-
-/* Read and write modes for polaris ITVC */
-#define  MCI_MODE_REGISTER_READ         0x000
-#define  MCI_MODE_REGISTER_WRITE        0x100
-#define  MCI_MODE_MEMORY_READ           0x000
-#define  MCI_MODE_MEMORY_WRITE          0x4000
-
-static unsigned int mpegbufs = 8;
-module_param(mpegbufs, int, 0644);
-MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");
-static unsigned int mpeglines = 128;
-module_param(mpeglines, int, 0644);
-MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");
-static unsigned int mpeglinesize = 512;
-module_param(mpeglinesize, int, 0644);
-MODULE_PARM_DESC(mpeglinesize,
-       "number of bytes in each line of an MPEG buffer, range 512-1024");
-
-static unsigned int v4l_debug = 1;
-module_param(v4l_debug, int, 0644);
-MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
-struct cx231xx_dmaqueue *dma_qq;
-#define dprintk(level, fmt, arg...)\
-       do { if (v4l_debug >= level) \
-               printk(KERN_INFO "%s: " fmt, \
-               (dev) ? dev->name : "cx231xx[?]", ## arg); \
-       } while (0)
-
-static struct cx231xx_tvnorm cx231xx_tvnorms[] = {
-       {
-               .name      = "NTSC-M",
-               .id        = V4L2_STD_NTSC_M,
-       }, {
-               .name      = "NTSC-JP",
-               .id        = V4L2_STD_NTSC_M_JP,
-       }, {
-               .name      = "PAL-BG",
-               .id        = V4L2_STD_PAL_BG,
-       }, {
-               .name      = "PAL-DK",
-               .id        = V4L2_STD_PAL_DK,
-       }, {
-               .name      = "PAL-I",
-               .id        = V4L2_STD_PAL_I,
-       }, {
-               .name      = "PAL-M",
-               .id        = V4L2_STD_PAL_M,
-       }, {
-               .name      = "PAL-N",
-               .id        = V4L2_STD_PAL_N,
-       }, {
-               .name      = "PAL-Nc",
-               .id        = V4L2_STD_PAL_Nc,
-       }, {
-               .name      = "PAL-60",
-               .id        = V4L2_STD_PAL_60,
-       }, {
-               .name      = "SECAM-L",
-               .id        = V4L2_STD_SECAM_L,
-       }, {
-               .name      = "SECAM-DK",
-               .id        = V4L2_STD_SECAM_DK,
-       }
-};
-
-/* ------------------------------------------------------------------ */
-enum cx231xx_capture_type {
-       CX231xx_MPEG_CAPTURE,
-       CX231xx_RAW_CAPTURE,
-       CX231xx_RAW_PASSTHRU_CAPTURE
-};
-enum cx231xx_capture_bits {
-       CX231xx_RAW_BITS_NONE             = 0x00,
-       CX231xx_RAW_BITS_YUV_CAPTURE      = 0x01,
-       CX231xx_RAW_BITS_PCM_CAPTURE      = 0x02,
-       CX231xx_RAW_BITS_VBI_CAPTURE      = 0x04,
-       CX231xx_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
-       CX231xx_RAW_BITS_TO_HOST_CAPTURE  = 0x10
-};
-enum cx231xx_capture_end {
-       CX231xx_END_AT_GOP, /* stop at the end of gop, generate irq */
-       CX231xx_END_NOW, /* stop immediately, no irq */
-};
-enum cx231xx_framerate {
-       CX231xx_FRAMERATE_NTSC_30, /* NTSC: 30fps */
-       CX231xx_FRAMERATE_PAL_25   /* PAL: 25fps */
-};
-enum cx231xx_stream_port {
-       CX231xx_OUTPUT_PORT_MEMORY,
-       CX231xx_OUTPUT_PORT_STREAMING,
-       CX231xx_OUTPUT_PORT_SERIAL
-};
-enum cx231xx_data_xfer_status {
-       CX231xx_MORE_BUFFERS_FOLLOW,
-       CX231xx_LAST_BUFFER,
-};
-enum cx231xx_picture_mask {
-       CX231xx_PICTURE_MASK_NONE,
-       CX231xx_PICTURE_MASK_I_FRAMES,
-       CX231xx_PICTURE_MASK_I_P_FRAMES = 0x3,
-       CX231xx_PICTURE_MASK_ALL_FRAMES = 0x7,
-};
-enum cx231xx_vbi_mode_bits {
-       CX231xx_VBI_BITS_SLICED,
-       CX231xx_VBI_BITS_RAW,
-};
-enum cx231xx_vbi_insertion_bits {
-       CX231xx_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
-       CX231xx_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
-       CX231xx_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
-       CX231xx_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
-       CX231xx_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
-};
-enum cx231xx_dma_unit {
-       CX231xx_DMA_BYTES,
-       CX231xx_DMA_FRAMES,
-};
-enum cx231xx_dma_transfer_status_bits {
-       CX231xx_DMA_TRANSFER_BITS_DONE = 0x01,
-       CX231xx_DMA_TRANSFER_BITS_ERROR = 0x04,
-       CX231xx_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
-};
-enum cx231xx_pause {
-       CX231xx_PAUSE_ENCODING,
-       CX231xx_RESUME_ENCODING,
-};
-enum cx231xx_copyright {
-       CX231xx_COPYRIGHT_OFF,
-       CX231xx_COPYRIGHT_ON,
-};
-enum cx231xx_notification_type {
-       CX231xx_NOTIFICATION_REFRESH,
-};
-enum cx231xx_notification_status {
-       CX231xx_NOTIFICATION_OFF,
-       CX231xx_NOTIFICATION_ON,
-};
-enum cx231xx_notification_mailbox {
-       CX231xx_NOTIFICATION_NO_MAILBOX = -1,
-};
-enum cx231xx_field1_lines {
-       CX231xx_FIELD1_SAA7114 = 0x00EF, /* 239 */
-       CX231xx_FIELD1_SAA7115 = 0x00F0, /* 240 */
-       CX231xx_FIELD1_MICRONAS = 0x0105, /* 261 */
-};
-enum cx231xx_field2_lines {
-       CX231xx_FIELD2_SAA7114 = 0x00EF, /* 239 */
-       CX231xx_FIELD2_SAA7115 = 0x00F0, /* 240 */
-       CX231xx_FIELD2_MICRONAS = 0x0106, /* 262 */
-};
-enum cx231xx_custom_data_type {
-       CX231xx_CUSTOM_EXTENSION_USR_DATA,
-       CX231xx_CUSTOM_PRIVATE_PACKET,
-};
-enum cx231xx_mute {
-       CX231xx_UNMUTE,
-       CX231xx_MUTE,
-};
-enum cx231xx_mute_video_mask {
-       CX231xx_MUTE_VIDEO_V_MASK = 0x0000FF00,
-       CX231xx_MUTE_VIDEO_U_MASK = 0x00FF0000,
-       CX231xx_MUTE_VIDEO_Y_MASK = 0xFF000000,
-};
-enum cx231xx_mute_video_shift {
-       CX231xx_MUTE_VIDEO_V_SHIFT = 8,
-       CX231xx_MUTE_VIDEO_U_SHIFT = 16,
-       CX231xx_MUTE_VIDEO_Y_SHIFT = 24,
-};
-
-/* defines below are from ivtv-driver.h */
-#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
-
-/* Firmware API commands */
-#define IVTV_API_STD_TIMEOUT 500
-
-/* Registers */
-/* IVTV_REG_OFFSET */
-#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8)
-#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC)
-#define IVTV_REG_SPU (0x9050)
-#define IVTV_REG_HW_BLOCKS (0x9054)
-#define IVTV_REG_VPU (0x9058)
-#define IVTV_REG_APU (0xA064)
-
-/*
- * Bit definitions for MC417_RWD and MC417_OEN registers
- *
- * bits 31-16
- *+-----------+
- *| Reserved  |
- *|+-----------+
- *|  bit 15  bit 14  bit 13 bit 12  bit 11  bit 10  bit 9   bit 8
- *|+-------+-------+-------+-------+-------+-------+-------+-------+
- *|| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0|
- *|+-------+-------+-------+-------+-------+-------+-------+-------+
- *| bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
- *|+-------+-------+-------+-------+-------+-------+-------+-------+
- *||MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0|
- *|+-------+-------+-------+-------+-------+-------+-------+-------+
- */
-#define MC417_MIWR     0x8000
-#define MC417_MIRD     0x4000
-#define MC417_MICS     0x2000
-#define MC417_MIRDY    0x1000
-#define MC417_MIADDR   0x0F00
-#define MC417_MIDATA   0x00FF
-
-
-/* Bit definitions for MC417_CTL register ****
- *bits 31-6   bits 5-4   bit 3    bits 2-1       Bit 0
- *+--------+-------------+--------+--------------+------------+
- *|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN|
- *+--------+-------------+--------+--------------+------------+
- */
-#define MC417_SPD_CTL(x)       (((x) << 4) & 0x00000030)
-#define MC417_GPIO_SEL(x)      (((x) << 1) & 0x00000006)
-#define MC417_UART_GPIO_EN     0x00000001
-
-/* Values for speed control */
-#define MC417_SPD_CTL_SLOW     0x1
-#define MC417_SPD_CTL_MEDIUM   0x0
-#define MC417_SPD_CTL_FAST     0x3     /* b'1x, but we use b'11 */
-
-/* Values for GPIO select */
-#define MC417_GPIO_SEL_GPIO3   0x3
-#define MC417_GPIO_SEL_GPIO2   0x2
-#define MC417_GPIO_SEL_GPIO1   0x1
-#define MC417_GPIO_SEL_GPIO0   0x0
-
-
-#define CX23417_GPIO_MASK 0xFC0003FF
-static int setITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 value)
-{
-       int status = 0;
-       u32 _gpio_direction = 0;
-
-       _gpio_direction = _gpio_direction & CX23417_GPIO_MASK;
-       _gpio_direction = _gpio_direction|gpio_direction;
-       status = cx231xx_send_gpio_cmd(dev, _gpio_direction,
-                        (u8 *)&value, 4, 0, 0);
-       return status;
-}
-static int getITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 *pValue)
-{
-       int status = 0;
-       u32 _gpio_direction = 0;
-
-       _gpio_direction = _gpio_direction & CX23417_GPIO_MASK;
-       _gpio_direction = _gpio_direction|gpio_direction;
-
-       status = cx231xx_send_gpio_cmd(dev, _gpio_direction,
-                (u8 *)pValue, 4, 0, 1);
-       return status;
-}
-
-static int waitForMciComplete(struct cx231xx *dev)
-{
-       u32 gpio;
-       u32 gpio_driection = 0;
-       u8 count = 0;
-       getITVCReg(dev, gpio_driection, &gpio);
-
-       while (!(gpio&0x020000)) {
-               msleep(10);
-
-               getITVCReg(dev, gpio_driection, &gpio);
-
-               if (count++ > 100) {
-                       dprintk(3, "ERROR: Timeout - gpio=%x\n", gpio);
-                       return -1;
-               }
-       }
-       return 0;
-}
-
-static int mc417_register_write(struct cx231xx *dev, u16 address, u32 value)
-{
-       u32 temp;
-       int status = 0;
-
-       temp = 0x82|MCI_REGISTER_DATA_BYTE0|((value&0x000000FF)<<8);
-       temp = temp<<10;
-       status = setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       if (status < 0)
-               return status;
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*write data byte 1;*/
-       temp = 0x82|MCI_REGISTER_DATA_BYTE1|(value&0x0000FF00);
-       temp = temp<<10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*write data byte 2;*/
-       temp = 0x82|MCI_REGISTER_DATA_BYTE2|((value&0x00FF0000)>>8);
-       temp = temp<<10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*write data byte 3;*/
-       temp = 0x82|MCI_REGISTER_DATA_BYTE3|((value&0xFF000000)>>16);
-       temp = temp<<10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*write address byte 0;*/
-       temp = 0x82|MCI_REGISTER_ADDRESS_BYTE0|((address&0x000000FF)<<8);
-       temp = temp<<10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*write address byte 1;*/
-       temp = 0x82|MCI_REGISTER_ADDRESS_BYTE1|(address&0x0000FF00);
-       temp = temp<<10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*Write that the mode is write.*/
-       temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_WRITE;
-       temp = temp<<10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       return waitForMciComplete(dev);
-}
-
-static int mc417_register_read(struct cx231xx *dev, u16 address, u32 *value)
-{
-       /*write address byte 0;*/
-       u32 temp;
-       u32 return_value = 0;
-       int ret = 0;
-
-       temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE0 | ((address & 0x00FF) << 8);
-       temp = temp << 10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp | ((0x05) << 10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*write address byte 1;*/
-       temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE1 | (address & 0xFF00);
-       temp = temp << 10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp | ((0x05) << 10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*write that the mode is read;*/
-       temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_READ;
-       temp = temp << 10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp | ((0x05) << 10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*wait for the MIRDY line to be asserted ,
-       signalling that the read is done;*/
-       ret = waitForMciComplete(dev);
-
-       /*switch the DATA- GPIO to input mode;*/
-
-       /*Read data byte 0;*/
-       temp = (0x82 | MCI_REGISTER_DATA_BYTE0) << 10;
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       temp = ((0x81 | MCI_REGISTER_DATA_BYTE0) << 10);
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       getITVCReg(dev, ITVC_READ_DIR, &temp);
-       return_value |= ((temp & 0x03FC0000) >> 18);
-       setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));
-
-       /* Read data byte 1;*/
-       temp = (0x82 | MCI_REGISTER_DATA_BYTE1) << 10;
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       temp = ((0x81 | MCI_REGISTER_DATA_BYTE1) << 10);
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       getITVCReg(dev, ITVC_READ_DIR, &temp);
-
-       return_value |= ((temp & 0x03FC0000) >> 10);
-       setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));
-
-       /*Read data byte 2;*/
-       temp = (0x82 | MCI_REGISTER_DATA_BYTE2) << 10;
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       temp = ((0x81 | MCI_REGISTER_DATA_BYTE2) << 10);
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       getITVCReg(dev, ITVC_READ_DIR, &temp);
-       return_value |= ((temp & 0x03FC0000) >> 2);
-       setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));
-
-       /*Read data byte 3;*/
-       temp = (0x82 | MCI_REGISTER_DATA_BYTE3) << 10;
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       temp = ((0x81 | MCI_REGISTER_DATA_BYTE3) << 10);
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       getITVCReg(dev, ITVC_READ_DIR, &temp);
-       return_value |= ((temp & 0x03FC0000) << 6);
-       setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));
-
-       *value  = return_value;
-
-
-       return ret;
-}
-
-static int mc417_memory_write(struct cx231xx *dev, u32 address, u32 value)
-{
-       /*write data byte 0;*/
-
-       u32 temp;
-       int ret = 0;
-
-       temp = 0x82 | MCI_MEMORY_DATA_BYTE0|((value & 0x000000FF) << 8);
-       temp = temp << 10;
-       ret = setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       if (ret < 0)
-               return ret;
-       temp = temp | ((0x05) << 10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*write data byte 1;*/
-       temp = 0x82 | MCI_MEMORY_DATA_BYTE1 | (value & 0x0000FF00);
-       temp = temp << 10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp | ((0x05) << 10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*write data byte 2;*/
-       temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8);
-       temp = temp<<10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*write data byte 3;*/
-       temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16);
-       temp = temp<<10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /* write address byte 2;*/
-       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE |
-               ((address & 0x003F0000)>>8);
-       temp = temp<<10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /* write address byte 1;*/
-       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
-       temp = temp<<10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /* write address byte 0;*/
-       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8);
-       temp = temp<<10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*wait for MIRDY line;*/
-       waitForMciComplete(dev);
-
-       return 0;
-}
-
-static int mc417_memory_read(struct cx231xx *dev, u32 address, u32 *value)
-{
-       u32 temp = 0;
-       u32 return_value = 0;
-       int ret = 0;
-
-       /*write address byte 2;*/
-       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_READ |
-               ((address & 0x003F0000)>>8);
-       temp = temp<<10;
-       ret = setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       if (ret < 0)
-               return ret;
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*write address byte 1*/
-       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
-       temp = temp<<10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*write address byte 0*/
-       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF)<<8);
-       temp = temp<<10;
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-       temp = temp|((0x05)<<10);
-       setITVCReg(dev, ITVC_WRITE_DIR, temp);
-
-       /*Wait for MIRDY line*/
-       ret = waitForMciComplete(dev);
-
-
-       /*Read data byte 3;*/
-       temp = (0x82|MCI_MEMORY_DATA_BYTE3)<<10;
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       temp = ((0x81|MCI_MEMORY_DATA_BYTE3)<<10);
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       getITVCReg(dev, ITVC_READ_DIR, &temp);
-       return_value |= ((temp&0x03FC0000)<<6);
-       setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
-
-       /*Read data byte 2;*/
-       temp = (0x82|MCI_MEMORY_DATA_BYTE2)<<10;
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       temp = ((0x81|MCI_MEMORY_DATA_BYTE2)<<10);
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       getITVCReg(dev, ITVC_READ_DIR, &temp);
-       return_value |= ((temp&0x03FC0000)>>2);
-       setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
-
-       /* Read data byte 1;*/
-       temp = (0x82|MCI_MEMORY_DATA_BYTE1)<<10;
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       temp = ((0x81|MCI_MEMORY_DATA_BYTE1)<<10);
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       getITVCReg(dev, ITVC_READ_DIR, &temp);
-       return_value |= ((temp&0x03FC0000)>>10);
-       setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
-
-       /*Read data byte 0;*/
-       temp = (0x82|MCI_MEMORY_DATA_BYTE0)<<10;
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       temp = ((0x81|MCI_MEMORY_DATA_BYTE0)<<10);
-       setITVCReg(dev, ITVC_READ_DIR, temp);
-       getITVCReg(dev, ITVC_READ_DIR, &temp);
-       return_value |= ((temp&0x03FC0000)>>18);
-       setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
-
-       *value  = return_value;
-       return ret;
-}
-
-/* ------------------------------------------------------------------ */
-
-/* MPEG encoder API */
-static char *cmd_to_str(int cmd)
-{
-       switch (cmd) {
-       case CX2341X_ENC_PING_FW:
-               return  "PING_FW";
-       case CX2341X_ENC_START_CAPTURE:
-               return  "START_CAPTURE";
-       case CX2341X_ENC_STOP_CAPTURE:
-               return  "STOP_CAPTURE";
-       case CX2341X_ENC_SET_AUDIO_ID:
-               return  "SET_AUDIO_ID";
-       case CX2341X_ENC_SET_VIDEO_ID:
-               return  "SET_VIDEO_ID";
-       case CX2341X_ENC_SET_PCR_ID:
-               return  "SET_PCR_PID";
-       case CX2341X_ENC_SET_FRAME_RATE:
-               return  "SET_FRAME_RATE";
-       case CX2341X_ENC_SET_FRAME_SIZE:
-               return  "SET_FRAME_SIZE";
-       case CX2341X_ENC_SET_BIT_RATE:
-               return  "SET_BIT_RATE";
-       case CX2341X_ENC_SET_GOP_PROPERTIES:
-               return  "SET_GOP_PROPERTIES";
-       case CX2341X_ENC_SET_ASPECT_RATIO:
-               return  "SET_ASPECT_RATIO";
-       case CX2341X_ENC_SET_DNR_FILTER_MODE:
-               return  "SET_DNR_FILTER_PROPS";
-       case CX2341X_ENC_SET_DNR_FILTER_PROPS:
-               return  "SET_DNR_FILTER_PROPS";
-       case CX2341X_ENC_SET_CORING_LEVELS:
-               return  "SET_CORING_LEVELS";
-       case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
-               return  "SET_SPATIAL_FILTER_TYPE";
-       case CX2341X_ENC_SET_VBI_LINE:
-               return  "SET_VBI_LINE";
-       case CX2341X_ENC_SET_STREAM_TYPE:
-               return  "SET_STREAM_TYPE";
-       case CX2341X_ENC_SET_OUTPUT_PORT:
-               return  "SET_OUTPUT_PORT";
-       case CX2341X_ENC_SET_AUDIO_PROPERTIES:
-               return  "SET_AUDIO_PROPERTIES";
-       case CX2341X_ENC_HALT_FW:
-               return  "HALT_FW";
-       case CX2341X_ENC_GET_VERSION:
-               return  "GET_VERSION";
-       case CX2341X_ENC_SET_GOP_CLOSURE:
-               return  "SET_GOP_CLOSURE";
-       case CX2341X_ENC_GET_SEQ_END:
-               return  "GET_SEQ_END";
-       case CX2341X_ENC_SET_PGM_INDEX_INFO:
-               return  "SET_PGM_INDEX_INFO";
-       case CX2341X_ENC_SET_VBI_CONFIG:
-               return  "SET_VBI_CONFIG";
-       case CX2341X_ENC_SET_DMA_BLOCK_SIZE:
-               return  "SET_DMA_BLOCK_SIZE";
-       case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10:
-               return  "GET_PREV_DMA_INFO_MB_10";
-       case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9:
-               return  "GET_PREV_DMA_INFO_MB_9";
-       case CX2341X_ENC_SCHED_DMA_TO_HOST:
-               return  "SCHED_DMA_TO_HOST";
-       case CX2341X_ENC_INITIALIZE_INPUT:
-               return  "INITIALIZE_INPUT";
-       case CX2341X_ENC_SET_FRAME_DROP_RATE:
-               return  "SET_FRAME_DROP_RATE";
-       case CX2341X_ENC_PAUSE_ENCODER:
-               return  "PAUSE_ENCODER";
-       case CX2341X_ENC_REFRESH_INPUT:
-               return  "REFRESH_INPUT";
-       case CX2341X_ENC_SET_COPYRIGHT:
-               return  "SET_COPYRIGHT";
-       case CX2341X_ENC_SET_EVENT_NOTIFICATION:
-               return  "SET_EVENT_NOTIFICATION";
-       case CX2341X_ENC_SET_NUM_VSYNC_LINES:
-               return  "SET_NUM_VSYNC_LINES";
-       case CX2341X_ENC_SET_PLACEHOLDER:
-               return  "SET_PLACEHOLDER";
-       case CX2341X_ENC_MUTE_VIDEO:
-               return  "MUTE_VIDEO";
-       case CX2341X_ENC_MUTE_AUDIO:
-               return  "MUTE_AUDIO";
-       case CX2341X_ENC_MISC:
-               return  "MISC";
-       default:
-               return "UNKNOWN";
-       }
-}
-
-static int cx231xx_mbox_func(void *priv,
-                            u32 command,
-                            int in,
-                            int out,
-                            u32 data[CX2341X_MBOX_MAX_DATA])
-{
-       struct cx231xx *dev = priv;
-       unsigned long timeout;
-       u32 value, flag, retval = 0;
-       int i;
-
-       dprintk(3, "%s: command(0x%X) = %s\n", __func__, command,
-               cmd_to_str(command));
-
-       /* this may not be 100% safe if we can't read any memory location
-          without side effects */
-       mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);
-       if (value != 0x12345678) {
-               dprintk(3,
-                       "Firmware and/or mailbox pointer not initialized "
-                       "or corrupted, signature = 0x%x, cmd = %s\n", value,
-                       cmd_to_str(command));
-               return -1;
-       }
-
-       /* This read looks at 32 bits, but flag is only 8 bits.
-        * Seems we also bail if CMD or TIMEOUT bytes are set???
-        */
-       mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
-       if (flag) {
-               dprintk(3, "ERROR: Mailbox appears to be in use "
-                       "(%x), cmd = %s\n", flag, cmd_to_str(command));
-               return -1;
-       }
-
-       flag |= 1; /* tell 'em we're working on it */
-       mc417_memory_write(dev, dev->cx23417_mailbox, flag);
-
-       /* write command + args + fill remaining with zeros */
-       /* command code */
-       mc417_memory_write(dev, dev->cx23417_mailbox + 1, command);
-       mc417_memory_write(dev, dev->cx23417_mailbox + 3,
-               IVTV_API_STD_TIMEOUT); /* timeout */
-       for (i = 0; i < in; i++) {
-               mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]);
-               dprintk(3, "API Input %d = %d\n", i, data[i]);
-       }
-       for (; i < CX2341X_MBOX_MAX_DATA; i++)
-               mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0);
-
-       flag |= 3; /* tell 'em we're done writing */
-       mc417_memory_write(dev, dev->cx23417_mailbox, flag);
-
-       /* wait for firmware to handle the API command */
-       timeout = jiffies + msecs_to_jiffies(10);
-       for (;;) {
-               mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
-               if (0 != (flag & 4))
-                       break;
-               if (time_after(jiffies, timeout)) {
-                       dprintk(3, "ERROR: API Mailbox timeout\n");
-                       return -1;
-               }
-               udelay(10);
-       }
-
-       /* read output values */
-       for (i = 0; i < out; i++) {
-               mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i);
-               dprintk(3, "API Output %d = %d\n", i, data[i]);
-       }
-
-       mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval);
-       dprintk(3, "API result = %d\n", retval);
-
-       flag = 0;
-       mc417_memory_write(dev, dev->cx23417_mailbox, flag);
-
-       return retval;
-}
-
-/* We don't need to call the API often, so using just one
- * mailbox will probably suffice
- */
-static int cx231xx_api_cmd(struct cx231xx *dev,
-                          u32 command,
-                          u32 inputcnt,
-                          u32 outputcnt,
-                          ...)
-{
-       u32 data[CX2341X_MBOX_MAX_DATA];
-       va_list vargs;
-       int i, err;
-
-       dprintk(3, "%s() cmds = 0x%08x\n", __func__, command);
-
-       va_start(vargs, outputcnt);
-       for (i = 0; i < inputcnt; i++)
-               data[i] = va_arg(vargs, int);
-
-       err = cx231xx_mbox_func(dev, command, inputcnt, outputcnt, data);
-       for (i = 0; i < outputcnt; i++) {
-               int *vptr = va_arg(vargs, int *);
-               *vptr = data[i];
-       }
-       va_end(vargs);
-
-       return err;
-}
-
-static int cx231xx_find_mailbox(struct cx231xx *dev)
-{
-       u32 signature[4] = {
-               0x12345678, 0x34567812, 0x56781234, 0x78123456
-       };
-       int signaturecnt = 0;
-       u32 value;
-       int i;
-       int ret = 0;
-
-       dprintk(2, "%s()\n", __func__);
-
-       for (i = 0; i < 0x100; i++) {/*CX231xx_FIRM_IMAGE_SIZE*/
-               ret = mc417_memory_read(dev, i, &value);
-               if (ret < 0)
-                       return ret;
-               if (value == signature[signaturecnt])
-                       signaturecnt++;
-               else
-                       signaturecnt = 0;
-               if (4 == signaturecnt) {
-                       dprintk(1, "Mailbox signature found at 0x%x\n", i+1);
-                       return i+1;
-               }
-       }
-       dprintk(3, "Mailbox signature values not found!\n");
-       return -1;
-}
-
-static void mciWriteMemoryToGPIO(struct cx231xx *dev, u32 address, u32 value,
-               u32 *p_fw_image)
-{
-
-       u32 temp = 0;
-       int i = 0;
-
-       temp = 0x82|MCI_MEMORY_DATA_BYTE0|((value&0x000000FF)<<8);
-       temp = temp<<10;
-       *p_fw_image = temp;
-       p_fw_image++;
-       temp = temp|((0x05)<<10);
-       *p_fw_image = temp;
-       p_fw_image++;
-
-       /*write data byte 1;*/
-       temp = 0x82|MCI_MEMORY_DATA_BYTE1|(value&0x0000FF00);
-       temp = temp<<10;
-       *p_fw_image = temp;
-       p_fw_image++;
-       temp = temp|((0x05)<<10);
-       *p_fw_image = temp;
-       p_fw_image++;
-
-       /*write data byte 2;*/
-       temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8);
-       temp = temp<<10;
-       *p_fw_image = temp;
-       p_fw_image++;
-       temp = temp|((0x05)<<10);
-       *p_fw_image = temp;
-       p_fw_image++;
-
-       /*write data byte 3;*/
-       temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16);
-       temp = temp<<10;
-       *p_fw_image = temp;
-       p_fw_image++;
-       temp = temp|((0x05)<<10);
-       *p_fw_image = temp;
-       p_fw_image++;
-
-       /* write address byte 2;*/
-       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE |
-               ((address & 0x003F0000)>>8);
-       temp = temp<<10;
-       *p_fw_image = temp;
-       p_fw_image++;
-       temp = temp|((0x05)<<10);
-       *p_fw_image = temp;
-       p_fw_image++;
-
-       /* write address byte 1;*/
-       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
-       temp = temp<<10;
-       *p_fw_image = temp;
-       p_fw_image++;
-       temp = temp|((0x05)<<10);
-       *p_fw_image = temp;
-       p_fw_image++;
-
-       /* write address byte 0;*/
-       temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8);
-       temp = temp<<10;
-       *p_fw_image = temp;
-       p_fw_image++;
-       temp = temp|((0x05)<<10);
-       *p_fw_image = temp;
-       p_fw_image++;
-
-       for (i = 0; i < 6; i++) {
-               *p_fw_image = 0xFFFFFFFF;
-               p_fw_image++;
-       }
-}
-
-
-static int cx231xx_load_firmware(struct cx231xx *dev)
-{
-       static const unsigned char magic[8] = {
-               0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
-       };
-       const struct firmware *firmware;
-       int i, retval = 0;
-       u32 value = 0;
-       u32 gpio_output = 0;
-       /*u32 checksum = 0;*/
-       /*u32 *dataptr;*/
-       u32 transfer_size = 0;
-       u32 fw_data = 0;
-       u32 address = 0;
-       /*u32 current_fw[800];*/
-       u32 *p_current_fw, *p_fw;
-       u32 *p_fw_data;
-       int frame = 0;
-       u16 _buffer_size = 4096;
-       u8 *p_buffer;
-
-       p_current_fw = vmalloc(1884180 * 4);
-       p_fw = p_current_fw;
-       if (p_current_fw == NULL) {
-               dprintk(2, "FAIL!!!\n");
-               return -1;
-       }
-
-       p_buffer = vmalloc(4096);
-       if (p_buffer == NULL) {
-               dprintk(2, "FAIL!!!\n");
-               return -1;
-       }
-
-       dprintk(2, "%s()\n", __func__);
-
-       /* Save GPIO settings before reset of APU */
-       retval |= mc417_memory_read(dev, 0x9020, &gpio_output);
-       retval |= mc417_memory_read(dev, 0x900C, &value);
-
-       retval  = mc417_register_write(dev,
-               IVTV_REG_VPU, 0xFFFFFFED);
-       retval |= mc417_register_write(dev,
-               IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
-       retval |= mc417_register_write(dev,
-               IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800);
-       retval |= mc417_register_write(dev,
-               IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
-       retval |= mc417_register_write(dev,
-               IVTV_REG_APU, 0);
-
-       if (retval != 0) {
-               printk(KERN_ERR "%s: Error with mc417_register_write\n",
-                       __func__);
-               return -1;
-       }
-
-       retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME,
-                                 &dev->udev->dev);
-
-       if (retval != 0) {
-               printk(KERN_ERR
-                       "ERROR: Hotplug firmware request failed (%s).\n",
-                       CX231xx_FIRM_IMAGE_NAME);
-               printk(KERN_ERR "Please fix your hotplug setup, the board will "
-                       "not work without firmware loaded!\n");
-               return -1;
-       }
-
-       if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) {
-               printk(KERN_ERR "ERROR: Firmware size mismatch "
-                       "(have %zd, expected %d)\n",
-                       firmware->size, CX231xx_FIRM_IMAGE_SIZE);
-               release_firmware(firmware);
-               return -1;
-       }
-
-       if (0 != memcmp(firmware->data, magic, 8)) {
-               printk(KERN_ERR
-                       "ERROR: Firmware magic mismatch, wrong file?\n");
-               release_firmware(firmware);
-               return -1;
-       }
-
-       initGPIO(dev);
-
-       /* transfer to the chip */
-       dprintk(2, "Loading firmware to GPIO...\n");
-       p_fw_data = (u32 *)firmware->data;
-       dprintk(2, "firmware->size=%zd\n", firmware->size);
-       for (transfer_size = 0; transfer_size < firmware->size;
-                transfer_size += 4) {
-               fw_data = *p_fw_data;
-
-                mciWriteMemoryToGPIO(dev, address, fw_data, p_current_fw);
-               address = address + 1;
-               p_current_fw += 20;
-               p_fw_data += 1;
-       }
-
-       /*download the firmware by ep5-out*/
-
-       for (frame = 0; frame < (int)(CX231xx_FIRM_IMAGE_SIZE*20/_buffer_size);
-            frame++) {
-               for (i = 0; i < _buffer_size; i++) {
-                       *(p_buffer + i) = (u8)(*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x000000FF);
-                       i++;
-                       *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x0000FF00) >> 8);
-                       i++;
-                       *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x00FF0000) >> 16);
-                       i++;
-                       *(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0xFF000000) >> 24);
-               }
-               cx231xx_ep5_bulkout(dev, p_buffer, _buffer_size);
-       }
-
-       p_current_fw = p_fw;
-       vfree(p_current_fw);
-       p_current_fw = NULL;
-       uninitGPIO(dev);
-       release_firmware(firmware);
-       dprintk(1, "Firmware upload successful.\n");
-
-       retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,
-               IVTV_CMD_HW_BLOCKS_RST);
-       if (retval < 0) {
-               printk(KERN_ERR "%s: Error with mc417_register_write\n",
-                       __func__);
-               return retval;
-       }
-       /* F/W power up disturbs the GPIOs, restore state */
-       retval |= mc417_register_write(dev, 0x9020, gpio_output);
-       retval |= mc417_register_write(dev, 0x900C, value);
-
-       retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
-       retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
-
-       if (retval < 0) {
-               printk(KERN_ERR "%s: Error with mc417_register_write\n",
-                       __func__);
-               return retval;
-       }
-       return 0;
-}
-
-static void cx231xx_417_check_encoder(struct cx231xx *dev)
-{
-       u32 status, seq;
-
-       status = 0;
-       seq = 0;
-       cx231xx_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq);
-       dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);
-}
-
-static void cx231xx_codec_settings(struct cx231xx *dev)
-{
-       dprintk(1, "%s()\n", __func__);
-
-       /* assign frame size */
-       cx231xx_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
-                               dev->ts1.height, dev->ts1.width);
-
-       dev->mpeg_params.width = dev->ts1.width;
-       dev->mpeg_params.height = dev->ts1.height;
-
-       cx2341x_update(dev, cx231xx_mbox_func, NULL, &dev->mpeg_params);
-
-       cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);
-       cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
-}
-
-static int cx231xx_initialize_codec(struct cx231xx *dev)
-{
-       int version;
-       int retval;
-       u32 i;
-       u32 val = 0;
-
-       dprintk(1, "%s()\n", __func__);
-       cx231xx_disable656(dev);
-       retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
-       if (retval < 0) {
-               dprintk(2, "%s() PING OK\n", __func__);
-               retval = cx231xx_load_firmware(dev);
-               if (retval < 0) {
-                       printk(KERN_ERR "%s() f/w load failed\n", __func__);
-                       return retval;
-               }
-               retval = cx231xx_find_mailbox(dev);
-               if (retval < 0) {
-                       printk(KERN_ERR "%s() mailbox < 0, error\n",
-                               __func__);
-                       return -1;
-               }
-               dev->cx23417_mailbox = retval;
-               retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
-               if (retval < 0) {
-                       printk(KERN_ERR
-                               "ERROR: cx23417 firmware ping failed!\n");
-                       return -1;
-               }
-               retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
-                       &version);
-               if (retval < 0) {
-                       printk(KERN_ERR "ERROR: cx23417 firmware get encoder :"
-                               "version failed!\n");
-                       return -1;
-               }
-               dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
-               msleep(200);
-       }
-
-       for (i = 0; i < 1; i++) {
-               retval = mc417_register_read(dev, 0x20f8, &val);
-               dprintk(3, "***before enable656() VIM Capture Lines =%d ***\n",
-                                val);
-               if (retval < 0)
-                       return retval;
-       }
-
-       cx231xx_enable656(dev);
-                       /* stop mpeg capture */
-                       cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE,
-                                3, 0, 1, 3, 4);
-
-       cx231xx_codec_settings(dev);
-       msleep(60);
-
-/*     cx231xx_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
-               CX231xx_FIELD1_SAA7115, CX231xx_FIELD2_SAA7115);
-       cx231xx_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
-               CX231xx_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               0, 0);
-*/
-
-#if 0
-       /* TODO */
-       u32 data[7];
-
-       /* Setup to capture VBI */
-       data[0] = 0x0001BD00;
-       data[1] = 1;          /* frames per interrupt */
-       data[2] = 4;          /* total bufs */
-       data[3] = 0x91559155; /* start codes */
-       data[4] = 0x206080C0; /* stop codes */
-       data[5] = 6;          /* lines */
-       data[6] = 64;         /* BPL */
-
-       cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1],
-               data[2], data[3], data[4], data[5], data[6]);
-
-       for (i = 2; i <= 24; i++) {
-               int valid;
-
-               valid = ((i >= 19) && (i <= 21));
-               cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i,
-                               valid, 0 , 0, 0);
-               cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0,
-                               i | 0x80000000, valid, 0, 0, 0);
-       }
-#endif
-/*     cx231xx_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX231xx_UNMUTE);
-       msleep(60);
-*/
-       /* initialize the video input */
-       retval = cx231xx_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
-       if (retval < 0)
-               return retval;
-       msleep(60);
-
-       /* Enable VIP style pixel invalidation so we work with scaled mode */
-       mc417_memory_write(dev, 2120, 0x00000080);
-
-       /* start capturing to the host interface */
-       retval = cx231xx_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
-               CX231xx_MPEG_CAPTURE, CX231xx_RAW_BITS_NONE);
-       if (retval < 0)
-               return retval;
-       msleep(10);
-
-       for (i = 0; i < 1; i++) {
-               mc417_register_read(dev, 0x20f8, &val);
-       dprintk(3, "***VIM Capture Lines =%d ***\n", val);
-       }
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int bb_buf_setup(struct videobuf_queue *q,
-       unsigned int *count, unsigned int *size)
-{
-       struct cx231xx_fh *fh = q->priv_data;
-
-       fh->dev->ts1.ts_packet_size  = mpeglinesize;
-       fh->dev->ts1.ts_packet_count = mpeglines;
-
-       *size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
-       *count = mpegbufs;
-
-       return 0;
-}
-static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
-{
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *dev = fh->dev;
-       unsigned long flags = 0;
-
-       if (in_interrupt())
-               BUG();
-
-       spin_lock_irqsave(&dev->video_mode.slock, flags);
-       if (dev->USE_ISO) {
-               if (dev->video_mode.isoc_ctl.buf == buf)
-                       dev->video_mode.isoc_ctl.buf = NULL;
-       } else {
-               if (dev->video_mode.bulk_ctl.buf == buf)
-                       dev->video_mode.bulk_ctl.buf = NULL;
-       }
-       spin_unlock_irqrestore(&dev->video_mode.slock, flags);
-       videobuf_waiton(vq, &buf->vb, 0, 0);
-       videobuf_vmalloc_free(&buf->vb);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *urb,
-               struct cx231xx_dmaqueue *dma_q)
-{
-               void *vbuf;
-               struct cx231xx_buffer *buf;
-               u32 tail_data = 0;
-               char *p_data;
-
-               if (dma_q->mpeg_buffer_done == 0) {
-                       if (list_empty(&dma_q->active))
-                               return;
-
-                       buf = list_entry(dma_q->active.next,
-                                       struct cx231xx_buffer, vb.queue);
-                       dev->video_mode.isoc_ctl.buf = buf;
-                       dma_q->mpeg_buffer_done = 1;
-               }
-               /* Fill buffer */
-               buf = dev->video_mode.isoc_ctl.buf;
-               vbuf = videobuf_to_vmalloc(&buf->vb);
-
-               if ((dma_q->mpeg_buffer_completed+len) <
-                  mpeglines*mpeglinesize) {
-                       if (dma_q->add_ps_package_head ==
-                          CX231XX_NEED_ADD_PS_PACKAGE_HEAD) {
-                               memcpy(vbuf+dma_q->mpeg_buffer_completed,
-                                      dma_q->ps_head, 3);
-                               dma_q->mpeg_buffer_completed =
-                                 dma_q->mpeg_buffer_completed + 3;
-                               dma_q->add_ps_package_head =
-                                 CX231XX_NONEED_PS_PACKAGE_HEAD;
-                       }
-                       memcpy(vbuf+dma_q->mpeg_buffer_completed, data, len);
-                       dma_q->mpeg_buffer_completed =
-                         dma_q->mpeg_buffer_completed + len;
-               } else {
-                       dma_q->mpeg_buffer_done = 0;
-
-                       tail_data =
-                         mpeglines*mpeglinesize - dma_q->mpeg_buffer_completed;
-                       memcpy(vbuf+dma_q->mpeg_buffer_completed,
-                              data, tail_data);
-
-                       buf->vb.state = VIDEOBUF_DONE;
-                       buf->vb.field_count++;
-                       do_gettimeofday(&buf->vb.ts);
-                       list_del(&buf->vb.queue);
-                       wake_up(&buf->vb.done);
-                       dma_q->mpeg_buffer_completed = 0;
-
-                       if (len - tail_data > 0) {
-                               p_data = data + tail_data;
-                               dma_q->left_data_count = len - tail_data;
-                               memcpy(dma_q->p_left_data,
-                                      p_data, len - tail_data);
-                       }
-
-               }
-
-           return;
-}
-
-static void buffer_filled(char *data, int len, struct urb *urb,
-               struct cx231xx_dmaqueue *dma_q)
-{
-               void *vbuf;
-               struct cx231xx_buffer *buf;
-
-               if (list_empty(&dma_q->active))
-                       return;
-
-
-               buf = list_entry(dma_q->active.next,
-                                struct cx231xx_buffer, vb.queue);
-
-
-               /* Fill buffer */
-               vbuf = videobuf_to_vmalloc(&buf->vb);
-               memcpy(vbuf, data, len);
-               buf->vb.state = VIDEOBUF_DONE;
-               buf->vb.field_count++;
-               do_gettimeofday(&buf->vb.ts);
-               list_del(&buf->vb.queue);
-               wake_up(&buf->vb.done);
-
-           return;
-}
-static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
-{
-       struct cx231xx_dmaqueue *dma_q = urb->context;
-       unsigned char *p_buffer;
-       u32 buffer_size = 0;
-       u32 i = 0;
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               if (dma_q->left_data_count > 0) {
-                       buffer_copy(dev, dma_q->p_left_data,
-                                   dma_q->left_data_count, urb, dma_q);
-                       dma_q->mpeg_buffer_completed = dma_q->left_data_count;
-                       dma_q->left_data_count = 0;
-               }
-
-               p_buffer = urb->transfer_buffer +
-                               urb->iso_frame_desc[i].offset;
-               buffer_size = urb->iso_frame_desc[i].actual_length;
-
-               if (buffer_size > 0)
-                       buffer_copy(dev, p_buffer, buffer_size, urb, dma_q);
-       }
-
-       return 0;
-}
-static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
-{
-
-       /*char *outp;*/
-       /*struct cx231xx_buffer *buf;*/
-       struct cx231xx_dmaqueue *dma_q = urb->context;
-       unsigned char *p_buffer, *buffer;
-       u32 buffer_size = 0;
-
-       p_buffer = urb->transfer_buffer;
-       buffer_size = urb->actual_length;
-
-       buffer = kmalloc(buffer_size, GFP_ATOMIC);
-
-       memcpy(buffer, dma_q->ps_head, 3);
-       memcpy(buffer+3, p_buffer, buffer_size-3);
-       memcpy(dma_q->ps_head, p_buffer+buffer_size-3, 3);
-
-       p_buffer = buffer;
-       buffer_filled(p_buffer, buffer_size, urb, dma_q);
-
-       kfree(buffer);
-       return 0;
-}
-
-static int bb_buf_prepare(struct videobuf_queue *q,
-       struct videobuf_buffer *vb, enum v4l2_field field)
-{
-       struct cx231xx_fh *fh = q->priv_data;
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       struct cx231xx *dev = fh->dev;
-       int rc = 0, urb_init = 0;
-       int size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
-
-       dma_qq = &dev->video_mode.vidq;
-
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < size)
-               return -EINVAL;
-       buf->vb.width = fh->dev->ts1.ts_packet_size;
-       buf->vb.height = fh->dev->ts1.ts_packet_count;
-       buf->vb.size = size;
-       buf->vb.field = field;
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               rc = videobuf_iolock(q, &buf->vb, NULL);
-               if (rc < 0)
-                       goto fail;
-       }
-
-       if (dev->USE_ISO) {
-               if (!dev->video_mode.isoc_ctl.num_bufs)
-                       urb_init = 1;
-       } else {
-               if (!dev->video_mode.bulk_ctl.num_bufs)
-                       urb_init = 1;
-       }
-       /*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n",
-               urb_init, dev->video_mode.max_pkt_size);*/
-       dev->mode_tv = 1;
-
-       if (urb_init) {
-               rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
-               rc = cx231xx_unmute_audio(dev);
-               if (dev->USE_ISO) {
-                       cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
-                       rc = cx231xx_init_isoc(dev, mpeglines,
-                                      mpegbufs,
-                                      dev->ts1_mode.max_pkt_size,
-                                      cx231xx_isoc_copy);
-               } else {
-                       cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
-                       rc = cx231xx_init_bulk(dev, mpeglines,
-                                      mpegbufs,
-                                      dev->ts1_mode.max_pkt_size,
-                                      cx231xx_bulk_copy);
-               }
-               if (rc < 0)
-                       goto fail;
-       }
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
-fail:
-       free_buffer(q, buf);
-       return rc;
-}
-
-static void bb_buf_queue(struct videobuf_queue *q,
-       struct videobuf_buffer *vb)
-{
-       struct cx231xx_fh *fh = q->priv_data;
-
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       struct cx231xx *dev = fh->dev;
-       struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
-
-       buf->vb.state = VIDEOBUF_QUEUED;
-       list_add_tail(&buf->vb.queue, &vidq->active);
-
-}
-
-static void bb_buf_release(struct videobuf_queue *q,
-       struct videobuf_buffer *vb)
-{
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       /*struct cx231xx_fh *fh = q->priv_data;*/
-       /*struct cx231xx *dev = (struct cx231xx *)fh->dev;*/
-
-       free_buffer(q, buf);
-}
-
-static struct videobuf_queue_ops cx231xx_qops = {
-       .buf_setup    = bb_buf_setup,
-       .buf_prepare  = bb_buf_prepare,
-       .buf_queue    = bb_buf_queue,
-       .buf_release  = bb_buf_release,
-};
-
-/* ------------------------------------------------------------------ */
-
-static const u32 *ctrl_classes[] = {
-       cx2341x_mpeg_ctrls,
-       NULL
-};
-
-static int cx231xx_queryctrl(struct cx231xx *dev,
-       struct v4l2_queryctrl *qctrl)
-{
-       qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
-       if (qctrl->id == 0)
-               return -EINVAL;
-
-       /* MPEG V4L2 controls */
-       if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl))
-               qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
-
-       return 0;
-}
-
-static int cx231xx_querymenu(struct cx231xx *dev,
-       struct v4l2_querymenu *qmenu)
-{
-       struct v4l2_queryctrl qctrl;
-
-       qctrl.id = qmenu->id;
-       cx231xx_queryctrl(dev, &qctrl);
-       return v4l2_ctrl_query_menu(qmenu, &qctrl,
-               cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id));
-}
-
-static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
-
-       *norm = dev->encodernorm.id;
-       return 0;
-}
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(cx231xx_tvnorms); i++)
-               if (*id & cx231xx_tvnorms[i].id)
-                       break;
-       if (i == ARRAY_SIZE(cx231xx_tvnorms))
-               return -EINVAL;
-       dev->encodernorm = cx231xx_tvnorms[i];
-
-       if (dev->encodernorm.id & 0xb000) {
-               dprintk(3, "encodernorm set to NTSC\n");
-               dev->norm = V4L2_STD_NTSC;
-               dev->ts1.height = 480;
-               dev->mpeg_params.is_50hz = 0;
-       } else {
-               dprintk(3, "encodernorm set to PAL\n");
-               dev->norm = V4L2_STD_PAL_B;
-               dev->ts1.height = 576;
-               dev->mpeg_params.is_50hz = 1;
-       }
-       call_all(dev, core, s_std, dev->norm);
-       /* do mode control overrides */
-       cx231xx_do_mode_ctrl_overrides(dev);
-
-       dprintk(3, "exit vidioc_s_std() i=0x%x\n", i);
-       return 0;
-}
-static int vidioc_g_audio(struct file *file, void *fh,
-                                       struct v4l2_audio *a)
-{
-               struct v4l2_audio *vin = a;
-
-               int ret = -EINVAL;
-               if (vin->index > 0)
-                       return ret;
-               strncpy(vin->name, "VideoGrabber Audio", 14);
-               vin->capability = V4L2_AUDCAP_STEREO;
-return 0;
-}
-static int vidioc_enumaudio(struct file *file, void *fh,
-                                       struct v4l2_audio *a)
-{
-               struct v4l2_audio *vin = a;
-
-               int ret = -EINVAL;
-
-               if (vin->index > 0)
-                       return ret;
-               strncpy(vin->name, "VideoGrabber Audio", 14);
-               vin->capability = V4L2_AUDCAP_STEREO;
-
-
-return 0;
-}
-static const char *iname[] = {
-       [CX231XX_VMUX_COMPOSITE1] = "Composite1",
-       [CX231XX_VMUX_SVIDEO]     = "S-Video",
-       [CX231XX_VMUX_TELEVISION] = "Television",
-       [CX231XX_VMUX_CABLE]      = "Cable TV",
-       [CX231XX_VMUX_DVB]        = "DVB",
-       [CX231XX_VMUX_DEBUG]      = "for debug only",
-};
-static int vidioc_enum_input(struct file *file, void *priv,
-                               struct v4l2_input *i)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
-       struct cx231xx_input *input;
-       int n;
-       dprintk(3, "enter vidioc_enum_input()i->index=%d\n", i->index);
-
-       if (i->index >= 4)
-               return -EINVAL;
-
-
-       input = &cx231xx_boards[dev->model].input[i->index];
-
-       if (input->type == 0)
-               return -EINVAL;
-
-       /* FIXME
-        * strcpy(i->name, input->name); */
-
-       n = i->index;
-       strcpy(i->name, iname[INPUT(n)->type]);
-
-       if (input->type == CX231XX_VMUX_TELEVISION ||
-           input->type == CX231XX_VMUX_CABLE)
-               i->type = V4L2_INPUT_TYPE_TUNER;
-       else
-               i->type  = V4L2_INPUT_TYPE_CAMERA;
-
-
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       *i = 0;
-       return  0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
-
-       dprintk(3, "enter vidioc_s_input() i=%d\n", i);
-
-       mutex_lock(&dev->lock);
-
-       video_mux(dev, i);
-
-       mutex_unlock(&dev->lock);
-
-       if (i >= 4)
-               return -EINVAL;
-       dev->input = i;
-       dprintk(3, "exit vidioc_s_input()\n");
-       return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *f)
-{
-       return 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *f)
-{
-
-
-       return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctl)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
-       dprintk(3, "enter vidioc_s_ctrl()\n");
-       /* Update the A/V core */
-       call_all(dev, core, s_ctrl, ctl);
-       dprintk(3, "exit vidioc_s_ctrl()\n");
-       return 0;
-}
-static struct v4l2_capability pvr_capability = {
-       .driver         = "cx231xx",
-       .card           = "VideoGrabber",
-       .bus_info       = "usb",
-       .version        = 1,
-       .capabilities   = (V4L2_CAP_VIDEO_CAPTURE |
-                          V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
-                        V4L2_CAP_STREAMING | V4L2_CAP_READWRITE),
-};
-static int vidioc_querycap(struct file *file, void  *priv,
-                               struct v4l2_capability *cap)
-{
-
-
-
-               memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-
-       if (f->index != 0)
-               return -EINVAL;
-
-       strlcpy(f->description, "MPEG", sizeof(f->description));
-       f->pixelformat = V4L2_PIX_FMT_MPEG;
-
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
-       dprintk(3, "enter vidioc_g_fmt_vid_cap()\n");
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    =
-               dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
-       f->fmt.pix.colorspace   = 0;
-       f->fmt.pix.width        = dev->ts1.width;
-       f->fmt.pix.height       = dev->ts1.height;
-       f->fmt.pix.field        = fh->vidq.field;
-       dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
-               dev->ts1.width, dev->ts1.height, fh->vidq.field);
-       dprintk(3, "exit vidioc_g_fmt_vid_cap()\n");
-       return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
-       dprintk(3, "enter vidioc_try_fmt_vid_cap()\n");
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.sizeimage    =
-               dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
-       f->fmt.pix.colorspace   = 0;
-       dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
-               dev->ts1.width, dev->ts1.height, fh->vidq.field);
-       dprintk(3, "exit vidioc_try_fmt_vid_cap()\n");
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-
-       return 0;
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
-                               struct v4l2_requestbuffers *p)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-
-       return videobuf_reqbufs(&fh->vidq, p);
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-                               struct v4l2_buffer *p)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-
-       return videobuf_querybuf(&fh->vidq, p);
-}
-
-static int vidioc_qbuf(struct file *file, void *priv,
-                               struct v4l2_buffer *p)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-
-       return videobuf_qbuf(&fh->vidq, p);
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct cx231xx_fh  *fh  = priv;
-
-       return videobuf_dqbuf(&fh->vidq, b, file->f_flags & O_NONBLOCK);
-}
-
-
-static int vidioc_streamon(struct file *file, void *priv,
-                               enum v4l2_buf_type i)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-
-       struct cx231xx *dev = fh->dev;
-       dprintk(3, "enter vidioc_streamon()\n");
-               cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
-               cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
-               if (dev->USE_ISO)
-                       cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
-                                      CX231XX_NUM_BUFS,
-                                      dev->video_mode.max_pkt_size,
-                                      cx231xx_isoc_copy);
-               else {
-                       cx231xx_init_bulk(dev, 320,
-                                      5,
-                                      dev->ts1_mode.max_pkt_size,
-                                      cx231xx_bulk_copy);
-               }
-       dprintk(3, "exit vidioc_streamon()\n");
-       return videobuf_streamon(&fh->vidq);
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-
-       return videobuf_streamoff(&fh->vidq);
-}
-
-static int vidioc_g_ext_ctrls(struct file *file, void *priv,
-                               struct v4l2_ext_controls *f)
-{
-       struct cx231xx_fh  *fh  = priv;
-       struct cx231xx *dev = fh->dev;
-       dprintk(3, "enter vidioc_g_ext_ctrls()\n");
-       if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-               return -EINVAL;
-       dprintk(3, "exit vidioc_g_ext_ctrls()\n");
-       return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS);
-}
-
-static int vidioc_s_ext_ctrls(struct file *file, void *priv,
-                               struct v4l2_ext_controls *f)
-{
-       struct cx231xx_fh  *fh  = priv;
-       struct cx231xx *dev = fh->dev;
-       struct cx2341x_mpeg_params p;
-       int err;
-       dprintk(3, "enter vidioc_s_ext_ctrls()\n");
-       if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-               return -EINVAL;
-
-       p = dev->mpeg_params;
-       err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
-       if (err == 0) {
-               err = cx2341x_update(dev, cx231xx_mbox_func,
-                       &dev->mpeg_params, &p);
-               dev->mpeg_params = p;
-       }
-
-       return err;
-
-
-return 0;
-}
-
-static int vidioc_try_ext_ctrls(struct file *file, void *priv,
-                               struct v4l2_ext_controls *f)
-{
-       struct cx231xx_fh  *fh  = priv;
-       struct cx231xx *dev = fh->dev;
-       struct cx2341x_mpeg_params p;
-       int err;
-       dprintk(3, "enter vidioc_try_ext_ctrls()\n");
-       if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
-               return -EINVAL;
-
-       p = dev->mpeg_params;
-       err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
-       dprintk(3, "exit vidioc_try_ext_ctrls() err=%d\n", err);
-       return err;
-}
-
-static int vidioc_log_status(struct file *file, void *priv)
-{
-       struct cx231xx_fh  *fh  = priv;
-       struct cx231xx *dev = fh->dev;
-       char name[32 + 2];
-
-       snprintf(name, sizeof(name), "%s/2", dev->name);
-       dprintk(3,
-               "%s/2: ============  START LOG STATUS  ============\n",
-              dev->name);
-       call_all(dev, core, log_status);
-       cx2341x_log_status(&dev->mpeg_params, name);
-       dprintk(3,
-               "%s/2: =============  END LOG STATUS  =============\n",
-              dev->name);
-       return 0;
-}
-
-static int vidioc_querymenu(struct file *file, void *priv,
-                               struct v4l2_querymenu *a)
-{
-       struct cx231xx_fh  *fh  = priv;
-       struct cx231xx *dev = fh->dev;
-       dprintk(3, "enter vidioc_querymenu()\n");
-       dprintk(3, "exit vidioc_querymenu()\n");
-       return cx231xx_querymenu(dev, a);
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-                               struct v4l2_queryctrl *c)
-{
-       struct cx231xx_fh  *fh  = priv;
-       struct cx231xx *dev = fh->dev;
-       dprintk(3, "enter vidioc_queryctrl()\n");
-       dprintk(3, "exit vidioc_queryctrl()\n");
-       return cx231xx_queryctrl(dev, c);
-}
-
-static int mpeg_open(struct file *file)
-{
-       int minor = video_devdata(file)->minor;
-       struct cx231xx *h, *dev = NULL;
-       /*struct list_head *list;*/
-       struct cx231xx_fh *fh;
-       /*u32 value = 0;*/
-
-       dprintk(2, "%s()\n", __func__);
-
-       list_for_each_entry(h, &cx231xx_devlist, devlist) {
-               if (h->v4l_device->minor == minor)
-                       dev = h;
-       }
-
-       if (dev == NULL)
-               return -ENODEV;
-
-       mutex_lock(&dev->lock);
-
-       /* allocate + initialize per filehandle data */
-       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (NULL == fh) {
-               mutex_unlock(&dev->lock);
-               return -ENOMEM;
-       }
-
-       file->private_data = fh;
-       fh->dev      = dev;
-
-
-       videobuf_queue_vmalloc_init(&fh->vidq, &cx231xx_qops,
-                           NULL, &dev->video_mode.slock,
-                           V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED,
-                           sizeof(struct cx231xx_buffer), fh, NULL);
-/*
-       videobuf_queue_sg_init(&fh->vidq, &cx231xx_qops,
-                           &dev->udev->dev, &dev->ts1.slock,
-                           V4L2_BUF_TYPE_VIDEO_CAPTURE,
-                           V4L2_FIELD_INTERLACED,
-                           sizeof(struct cx231xx_buffer),
-                           fh, NULL);
-*/
-
-
-       cx231xx_set_alt_setting(dev, INDEX_VANC, 1);
-       cx231xx_set_gpio_value(dev, 2, 0);
-
-       cx231xx_initialize_codec(dev);
-
-       mutex_unlock(&dev->lock);
-       cx231xx_start_TS1(dev);
-
-       return 0;
-}
-
-static int mpeg_release(struct file *file)
-{
-       struct cx231xx_fh  *fh  = file->private_data;
-       struct cx231xx *dev = fh->dev;
-
-       dprintk(3, "mpeg_release()! dev=0x%p\n", dev);
-
-       if (!dev) {
-               dprintk(3, "abort!!!\n");
-               return 0;
-       }
-
-       mutex_lock(&dev->lock);
-
-       cx231xx_stop_TS1(dev);
-
-               /* do this before setting alternate! */
-               if (dev->USE_ISO)
-                       cx231xx_uninit_isoc(dev);
-               else
-                       cx231xx_uninit_bulk(dev);
-               cx231xx_set_mode(dev, CX231XX_SUSPEND);
-
-               cx231xx_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
-                               CX231xx_END_NOW, CX231xx_MPEG_CAPTURE,
-                               CX231xx_RAW_BITS_NONE);
-
-       /* FIXME: Review this crap */
-       /* Shut device down on last close */
-       if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
-               if (atomic_dec_return(&dev->v4l_reader_count) == 0) {
-                       /* stop mpeg capture */
-
-                       msleep(500);
-                       cx231xx_417_check_encoder(dev);
-
-               }
-       }
-
-       if (fh->vidq.streaming)
-               videobuf_streamoff(&fh->vidq);
-       if (fh->vidq.reading)
-               videobuf_read_stop(&fh->vidq);
-
-       videobuf_mmap_free(&fh->vidq);
-       file->private_data = NULL;
-       kfree(fh);
-       mutex_unlock(&dev->lock);
-       return 0;
-}
-
-static ssize_t mpeg_read(struct file *file, char __user *data,
-       size_t count, loff_t *ppos)
-{
-       struct cx231xx_fh *fh = file->private_data;
-       struct cx231xx *dev = fh->dev;
-
-
-       /* Deal w/ A/V decoder * and mpeg encoder sync issues. */
-       /* Start mpeg encoder on first read. */
-       if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
-               if (atomic_inc_return(&dev->v4l_reader_count) == 1) {
-                       if (cx231xx_initialize_codec(dev) < 0)
-                               return -EINVAL;
-               }
-       }
-
-       return videobuf_read_stream(&fh->vidq, data, count, ppos, 0,
-                                   file->f_flags & O_NONBLOCK);
-}
-
-static unsigned int mpeg_poll(struct file *file,
-       struct poll_table_struct *wait)
-{
-       struct cx231xx_fh *fh = file->private_data;
-       /*struct cx231xx *dev = fh->dev;*/
-
-       /*dprintk(2, "%s\n", __func__);*/
-
-       return videobuf_poll_stream(file, &fh->vidq, wait);
-}
-
-static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct cx231xx_fh *fh = file->private_data;
-       struct cx231xx *dev = fh->dev;
-
-       dprintk(2, "%s()\n", __func__);
-
-       return videobuf_mmap_mapper(&fh->vidq, vma);
-}
-
-static struct v4l2_file_operations mpeg_fops = {
-       .owner         = THIS_MODULE,
-       .open          = mpeg_open,
-       .release       = mpeg_release,
-       .read          = mpeg_read,
-       .poll          = mpeg_poll,
-       .mmap          = mpeg_mmap,
-       .ioctl         = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
-       .vidioc_s_std            = vidioc_s_std,
-       .vidioc_g_std            = vidioc_g_std,
-       .vidioc_enum_input       = vidioc_enum_input,
-       .vidioc_enumaudio        = vidioc_enumaudio,
-       .vidioc_g_audio          = vidioc_g_audio,
-       .vidioc_g_input          = vidioc_g_input,
-       .vidioc_s_input          = vidioc_s_input,
-       .vidioc_g_tuner          = vidioc_g_tuner,
-       .vidioc_s_tuner          = vidioc_s_tuner,
-       .vidioc_g_frequency      = vidioc_g_frequency,
-       .vidioc_s_frequency      = vidioc_s_frequency,
-       .vidioc_s_ctrl           = vidioc_s_ctrl,
-       .vidioc_querycap         = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap    = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap  = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap    = vidioc_s_fmt_vid_cap,
-       .vidioc_reqbufs          = vidioc_reqbufs,
-       .vidioc_querybuf         = vidioc_querybuf,
-       .vidioc_qbuf             = vidioc_qbuf,
-       .vidioc_dqbuf            = vidioc_dqbuf,
-       .vidioc_streamon         = vidioc_streamon,
-       .vidioc_streamoff        = vidioc_streamoff,
-       .vidioc_g_ext_ctrls      = vidioc_g_ext_ctrls,
-       .vidioc_s_ext_ctrls      = vidioc_s_ext_ctrls,
-       .vidioc_try_ext_ctrls    = vidioc_try_ext_ctrls,
-       .vidioc_log_status       = vidioc_log_status,
-       .vidioc_querymenu        = vidioc_querymenu,
-       .vidioc_queryctrl        = vidioc_queryctrl,
-/*     .vidioc_g_chip_ident     = cx231xx_g_chip_ident,*/
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-/*     .vidioc_g_register       = cx231xx_g_register,*/
-/*     .vidioc_s_register       = cx231xx_s_register,*/
-#endif
-};
-
-static struct video_device cx231xx_mpeg_template = {
-       .name          = "cx231xx",
-       .fops          = &mpeg_fops,
-       .ioctl_ops     = &mpeg_ioctl_ops,
-       .minor         = -1,
-       .tvnorms       = CX231xx_NORMS,
-       .current_norm  = V4L2_STD_NTSC_M,
-};
-
-void cx231xx_417_unregister(struct cx231xx *dev)
-{
-       dprintk(1, "%s()\n", __func__);
-       dprintk(3, "%s()\n", __func__);
-
-       if (dev->v4l_device) {
-               if (-1 != dev->v4l_device->minor)
-                       video_unregister_device(dev->v4l_device);
-               else
-                       video_device_release(dev->v4l_device);
-               dev->v4l_device = NULL;
-       }
-}
-
-static struct video_device *cx231xx_video_dev_alloc(
-       struct cx231xx *dev,
-       struct usb_device *usbdev,
-       struct video_device *template,
-       char *type)
-{
-       struct video_device *vfd;
-
-       dprintk(1, "%s()\n", __func__);
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-       *vfd = *template;
-       vfd->minor = -1;
-       snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
-               type, cx231xx_boards[dev->model].name);
-
-       vfd->v4l2_dev = &dev->v4l2_dev;
-       vfd->release = video_device_release;
-
-       return vfd;
-
-}
-
-int cx231xx_417_register(struct cx231xx *dev)
-{
-       /* FIXME: Port1 hardcoded here */
-       int err = -ENODEV;
-       struct cx231xx_tsport *tsport = &dev->ts1;
-
-       dprintk(1, "%s()\n", __func__);
-
-       /* Set default TV standard */
-       dev->encodernorm = cx231xx_tvnorms[0];
-
-       if (dev->encodernorm.id & V4L2_STD_525_60)
-               tsport->height = 480;
-       else
-               tsport->height = 576;
-
-       tsport->width = 720;
-       cx2341x_fill_defaults(&dev->mpeg_params);
-       dev->norm = V4L2_STD_NTSC;
-
-       dev->mpeg_params.port = CX2341X_PORT_SERIAL;
-
-       /* Allocate and initialize V4L video device */
-       dev->v4l_device = cx231xx_video_dev_alloc(dev,
-               dev->udev, &cx231xx_mpeg_template, "mpeg");
-       err = video_register_device(dev->v4l_device,
-               VFL_TYPE_GRABBER, -1);
-       if (err < 0) {
-               dprintk(3, "%s: can't register mpeg device\n", dev->name);
-               return err;
-       }
-
-       dprintk(3, "%s: registered device video%d [mpeg]\n",
-              dev->name, dev->v4l_device->num);
-
-       return 0;
-}
-
-MODULE_FIRMWARE(CX231xx_FIRM_IMAGE_NAME);
diff --git a/drivers/media/video/cx231xx/cx231xx-audio.c b/drivers/media/video/cx231xx/cx231xx-audio.c
deleted file mode 100644 (file)
index b4c99c7..0000000
+++ /dev/null
@@ -1,780 +0,0 @@
-/*
- *  Conexant Cx231xx audio extension
- *
- *  Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
- *       Based on em28xx driver
- *
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  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/usb.h>
-#include <linux/init.h>
-#include <linux/sound.h>
-#include <linux/spinlock.h>
-#include <linux/soundcard.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/proc_fs.h>
-#include <linux/module.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 "cx231xx.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "activates debug info");
-
-#define dprintk(fmt, arg...) do {                                      \
-               if (debug)                                              \
-                       printk(KERN_INFO "cx231xx-audio %s: " fmt,      \
-                               __func__, ##arg);                       \
-       } while (0)
-
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
-
-static int cx231xx_isoc_audio_deinit(struct cx231xx *dev)
-{
-       int i;
-
-       dprintk("Stopping isoc\n");
-
-       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
-               if (dev->adev.urb[i]) {
-                       if (!irqs_disabled())
-                               usb_kill_urb(dev->adev.urb[i]);
-                       else
-                               usb_unlink_urb(dev->adev.urb[i]);
-
-                       usb_free_urb(dev->adev.urb[i]);
-                       dev->adev.urb[i] = NULL;
-
-                       kfree(dev->adev.transfer_buffer[i]);
-                       dev->adev.transfer_buffer[i] = NULL;
-               }
-       }
-
-       return 0;
-}
-
-static int cx231xx_bulk_audio_deinit(struct cx231xx *dev)
-{
-       int i;
-
-       dprintk("Stopping bulk\n");
-
-       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
-               if (dev->adev.urb[i]) {
-                       if (!irqs_disabled())
-                               usb_kill_urb(dev->adev.urb[i]);
-                       else
-                               usb_unlink_urb(dev->adev.urb[i]);
-
-                       usb_free_urb(dev->adev.urb[i]);
-                       dev->adev.urb[i] = NULL;
-
-                       kfree(dev->adev.transfer_buffer[i]);
-                       dev->adev.transfer_buffer[i] = NULL;
-               }
-       }
-
-       return 0;
-}
-
-static void cx231xx_audio_isocirq(struct urb *urb)
-{
-       struct cx231xx *dev = urb->context;
-       int i;
-       unsigned int oldptr;
-       int period_elapsed = 0;
-       int status;
-       unsigned char *cp;
-       unsigned int stride;
-       struct snd_pcm_substream *substream;
-       struct snd_pcm_runtime *runtime;
-
-       if (dev->state & DEV_DISCONNECTED)
-               return;
-
-       switch (urb->status) {
-       case 0:         /* success */
-       case -ETIMEDOUT:        /* NAK */
-               break;
-       case -ECONNRESET:       /* kill */
-       case -ENOENT:
-       case -ESHUTDOWN:
-               return;
-       default:                /* error */
-               dprintk("urb completition error %d.\n", urb->status);
-               break;
-       }
-
-       if (atomic_read(&dev->stream_started) == 0)
-               return;
-
-       if (dev->adev.capture_pcm_substream) {
-               substream = dev->adev.capture_pcm_substream;
-               runtime = substream->runtime;
-               stride = runtime->frame_bits >> 3;
-
-               for (i = 0; i < urb->number_of_packets; i++) {
-                       int length = urb->iso_frame_desc[i].actual_length /
-                                    stride;
-                       cp = (unsigned char *)urb->transfer_buffer +
-                                             urb->iso_frame_desc[i].offset;
-
-                       if (!length)
-                               continue;
-
-                       oldptr = dev->adev.hwptr_done_capture;
-                       if (oldptr + length >= runtime->buffer_size) {
-                               unsigned int cnt;
-
-                               cnt = runtime->buffer_size - oldptr;
-                               memcpy(runtime->dma_area + oldptr * stride, cp,
-                                      cnt * stride);
-                               memcpy(runtime->dma_area, cp + cnt * stride,
-                                      length * stride - cnt * stride);
-                       } else {
-                               memcpy(runtime->dma_area + oldptr * stride, cp,
-                                      length * stride);
-                       }
-
-                       snd_pcm_stream_lock(substream);
-
-                       dev->adev.hwptr_done_capture += length;
-                       if (dev->adev.hwptr_done_capture >=
-                                               runtime->buffer_size)
-                               dev->adev.hwptr_done_capture -=
-                                               runtime->buffer_size;
-
-                       dev->adev.capture_transfer_done += length;
-                       if (dev->adev.capture_transfer_done >=
-                               runtime->period_size) {
-                               dev->adev.capture_transfer_done -=
-                                               runtime->period_size;
-                               period_elapsed = 1;
-                       }
-                       snd_pcm_stream_unlock(substream);
-               }
-               if (period_elapsed)
-                       snd_pcm_period_elapsed(substream);
-       }
-       urb->status = 0;
-
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status < 0) {
-               cx231xx_errdev("resubmit of audio urb failed (error=%i)\n",
-                              status);
-       }
-       return;
-}
-
-static void cx231xx_audio_bulkirq(struct urb *urb)
-{
-       struct cx231xx *dev = urb->context;
-       unsigned int oldptr;
-       int period_elapsed = 0;
-       int status;
-       unsigned char *cp;
-       unsigned int stride;
-       struct snd_pcm_substream *substream;
-       struct snd_pcm_runtime *runtime;
-
-       if (dev->state & DEV_DISCONNECTED)
-               return;
-
-       switch (urb->status) {
-       case 0:         /* success */
-       case -ETIMEDOUT:        /* NAK */
-               break;
-       case -ECONNRESET:       /* kill */
-       case -ENOENT:
-       case -ESHUTDOWN:
-               return;
-       default:                /* error */
-               dprintk("urb completition error %d.\n", urb->status);
-               break;
-       }
-
-       if (atomic_read(&dev->stream_started) == 0)
-               return;
-
-       if (dev->adev.capture_pcm_substream) {
-               substream = dev->adev.capture_pcm_substream;
-               runtime = substream->runtime;
-               stride = runtime->frame_bits >> 3;
-
-               if (1) {
-                       int length = urb->actual_length /
-                                    stride;
-                       cp = (unsigned char *)urb->transfer_buffer;
-
-                       oldptr = dev->adev.hwptr_done_capture;
-                       if (oldptr + length >= runtime->buffer_size) {
-                               unsigned int cnt;
-
-                               cnt = runtime->buffer_size - oldptr;
-                               memcpy(runtime->dma_area + oldptr * stride, cp,
-                                      cnt * stride);
-                               memcpy(runtime->dma_area, cp + cnt * stride,
-                                      length * stride - cnt * stride);
-                       } else {
-                               memcpy(runtime->dma_area + oldptr * stride, cp,
-                                      length * stride);
-                       }
-
-                       snd_pcm_stream_lock(substream);
-
-                       dev->adev.hwptr_done_capture += length;
-                       if (dev->adev.hwptr_done_capture >=
-                                               runtime->buffer_size)
-                               dev->adev.hwptr_done_capture -=
-                                               runtime->buffer_size;
-
-                       dev->adev.capture_transfer_done += length;
-                       if (dev->adev.capture_transfer_done >=
-                               runtime->period_size) {
-                               dev->adev.capture_transfer_done -=
-                                               runtime->period_size;
-                               period_elapsed = 1;
-                       }
-                       snd_pcm_stream_unlock(substream);
-               }
-               if (period_elapsed)
-                       snd_pcm_period_elapsed(substream);
-       }
-       urb->status = 0;
-
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status < 0) {
-               cx231xx_errdev("resubmit of audio urb failed (error=%i)\n",
-                              status);
-       }
-       return;
-}
-
-static int cx231xx_init_audio_isoc(struct cx231xx *dev)
-{
-       int i, errCode;
-       int sb_size;
-
-       cx231xx_info("%s: Starting ISO AUDIO transfers\n", __func__);
-
-       if (dev->state & DEV_DISCONNECTED)
-               return -ENODEV;
-
-       sb_size = CX231XX_ISO_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
-
-       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
-               struct urb *urb;
-               int j, k;
-
-               dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
-               if (!dev->adev.transfer_buffer[i])
-                       return -ENOMEM;
-
-               memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
-               urb = usb_alloc_urb(CX231XX_ISO_NUM_AUDIO_PACKETS, GFP_ATOMIC);
-               if (!urb) {
-                       cx231xx_errdev("usb_alloc_urb failed!\n");
-                       for (j = 0; j < i; j++) {
-                               usb_free_urb(dev->adev.urb[j]);
-                               kfree(dev->adev.transfer_buffer[j]);
-                       }
-                       return -ENOMEM;
-               }
-
-               urb->dev = dev->udev;
-               urb->context = dev;
-               urb->pipe = usb_rcvisocpipe(dev->udev,
-                                               dev->adev.end_point_addr);
-               urb->transfer_flags = URB_ISO_ASAP;
-               urb->transfer_buffer = dev->adev.transfer_buffer[i];
-               urb->interval = 1;
-               urb->complete = cx231xx_audio_isocirq;
-               urb->number_of_packets = CX231XX_ISO_NUM_AUDIO_PACKETS;
-               urb->transfer_buffer_length = sb_size;
-
-               for (j = k = 0; j < CX231XX_ISO_NUM_AUDIO_PACKETS;
-                       j++, k += dev->adev.max_pkt_size) {
-                       urb->iso_frame_desc[j].offset = k;
-                       urb->iso_frame_desc[j].length = dev->adev.max_pkt_size;
-               }
-               dev->adev.urb[i] = urb;
-       }
-
-       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
-               errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
-               if (errCode < 0) {
-                       cx231xx_isoc_audio_deinit(dev);
-                       return errCode;
-               }
-       }
-
-       return errCode;
-}
-
-static int cx231xx_init_audio_bulk(struct cx231xx *dev)
-{
-       int i, errCode;
-       int sb_size;
-
-       cx231xx_info("%s: Starting BULK AUDIO transfers\n", __func__);
-
-       if (dev->state & DEV_DISCONNECTED)
-               return -ENODEV;
-
-       sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
-
-       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
-               struct urb *urb;
-               int j;
-
-               dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
-               if (!dev->adev.transfer_buffer[i])
-                       return -ENOMEM;
-
-               memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
-               urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
-               if (!urb) {
-                       cx231xx_errdev("usb_alloc_urb failed!\n");
-                       for (j = 0; j < i; j++) {
-                               usb_free_urb(dev->adev.urb[j]);
-                               kfree(dev->adev.transfer_buffer[j]);
-                       }
-                       return -ENOMEM;
-               }
-
-               urb->dev = dev->udev;
-               urb->context = dev;
-               urb->pipe = usb_rcvbulkpipe(dev->udev,
-                                               dev->adev.end_point_addr);
-               urb->transfer_flags = 0;
-               urb->transfer_buffer = dev->adev.transfer_buffer[i];
-               urb->complete = cx231xx_audio_bulkirq;
-               urb->transfer_buffer_length = sb_size;
-
-               dev->adev.urb[i] = urb;
-
-       }
-
-       for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
-               errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
-               if (errCode < 0) {
-                       cx231xx_bulk_audio_deinit(dev);
-                       return errCode;
-               }
-       }
-
-       return errCode;
-}
-
-static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
-                                       size_t size)
-{
-       struct snd_pcm_runtime *runtime = subs->runtime;
-
-       dprintk("Allocating vbuffer\n");
-       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;
-
-       runtime->dma_bytes = size;
-
-       return 0;
-}
-
-static struct snd_pcm_hardware snd_cx231xx_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_CONTINUOUS | SNDRV_PCM_RATE_KNOT,
-
-       .rate_min = 48000,
-       .rate_max = 48000,
-       .channels_min = 2,
-       .channels_max = 2,
-       .buffer_bytes_max = 62720 * 8,  /* just about the value in usbaudio.c */
-       .period_bytes_min = 64,         /* 12544/2, */
-       .period_bytes_max = 12544,
-       .periods_min = 2,
-       .periods_max = 98,              /* 12544, */
-};
-
-static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream)
-{
-       struct cx231xx *dev = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       int ret = 0;
-
-       dprintk("opening device and trying to acquire exclusive lock\n");
-
-       if (!dev) {
-               cx231xx_errdev("BUG: cx231xx can't find device struct."
-                              " Can't proceed with open\n");
-               return -ENODEV;
-       }
-
-       if (dev->state & DEV_DISCONNECTED) {
-               cx231xx_errdev("Can't open. the device was removed.\n");
-               return -ENODEV;
-       }
-
-       /* Sets volume, mute, etc */
-       dev->mute = 0;
-
-       /* set alternate setting for audio interface */
-       /* 1 - 48000 samples per sec */
-       mutex_lock(&dev->lock);
-       if (dev->USE_ISO)
-               ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1);
-       else
-               ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
-       mutex_unlock(&dev->lock);
-       if (ret < 0) {
-               cx231xx_errdev("failed to set alternate setting !\n");
-
-               return ret;
-       }
-
-       runtime->hw = snd_cx231xx_hw_capture;
-
-       mutex_lock(&dev->lock);
-       /* inform hardware to start streaming */
-       ret = cx231xx_capture_start(dev, 1, Audio);
-
-       dev->adev.users++;
-       mutex_unlock(&dev->lock);
-
-       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
-       dev->adev.capture_pcm_substream = substream;
-       runtime->private_data = dev;
-
-       return 0;
-}
-
-static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream)
-{
-       int ret;
-       struct cx231xx *dev = snd_pcm_substream_chip(substream);
-
-       dprintk("closing device\n");
-
-       /* inform hardware to stop streaming */
-       mutex_lock(&dev->lock);
-       ret = cx231xx_capture_start(dev, 0, Audio);
-
-       /* set alternate setting for audio interface */
-       /* 1 - 48000 samples per sec */
-       ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
-       if (ret < 0) {
-               cx231xx_errdev("failed to set alternate setting !\n");
-
-               mutex_unlock(&dev->lock);
-               return ret;
-       }
-
-       dev->mute = 1;
-       dev->adev.users--;
-       mutex_unlock(&dev->lock);
-
-       if (dev->adev.users == 0 && dev->adev.shutdown == 1) {
-               dprintk("audio users: %d\n", dev->adev.users);
-               dprintk("disabling audio stream!\n");
-               dev->adev.shutdown = 0;
-               dprintk("released lock\n");
-               if (atomic_read(&dev->stream_started) > 0) {
-                       atomic_set(&dev->stream_started, 0);
-                       schedule_work(&dev->wq_trigger);
-               }
-       }
-       return 0;
-}
-
-static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream,
-                                        struct snd_pcm_hw_params *hw_params)
-{
-       int ret;
-
-       dprintk("Setting capture parameters\n");
-
-       ret = snd_pcm_alloc_vmalloc_buffer(substream,
-                                          params_buffer_bytes(hw_params));
-#if 0
-       /* TODO: set up cx231xx audio chip to deliver the correct audio format,
-          current default is 48000hz multiplexed => 96000hz mono
-          which shouldn't matter since analogue TV only supports mono */
-       unsigned int channels, rate, format;
-
-       format = params_format(hw_params);
-       rate = params_rate(hw_params);
-       channels = params_channels(hw_params);
-#endif
-
-       return ret;
-}
-
-static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream)
-{
-       struct cx231xx *dev = snd_pcm_substream_chip(substream);
-
-       dprintk("Stop capture, if needed\n");
-
-       if (atomic_read(&dev->stream_started) > 0) {
-               atomic_set(&dev->stream_started, 0);
-               schedule_work(&dev->wq_trigger);
-       }
-
-       return 0;
-}
-
-static int snd_cx231xx_prepare(struct snd_pcm_substream *substream)
-{
-       struct cx231xx *dev = snd_pcm_substream_chip(substream);
-
-       dev->adev.hwptr_done_capture = 0;
-       dev->adev.capture_transfer_done = 0;
-
-       return 0;
-}
-
-static void audio_trigger(struct work_struct *work)
-{
-       struct cx231xx *dev = container_of(work, struct cx231xx, wq_trigger);
-
-       if (atomic_read(&dev->stream_started)) {
-               dprintk("starting capture");
-               if (is_fw_load(dev) == 0)
-                       cx25840_call(dev, core, load_fw);
-               if (dev->USE_ISO)
-                       cx231xx_init_audio_isoc(dev);
-               else
-                       cx231xx_init_audio_bulk(dev);
-       } else {
-               dprintk("stopping capture");
-               cx231xx_isoc_audio_deinit(dev);
-       }
-}
-
-static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream,
-                                      int cmd)
-{
-       struct cx231xx *dev = snd_pcm_substream_chip(substream);
-       int retval = 0;
-
-       if (dev->state & DEV_DISCONNECTED)
-               return -ENODEV;
-
-       spin_lock(&dev->adev.slock);
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
-               atomic_set(&dev->stream_started, 1);
-               break;
-       case SNDRV_PCM_TRIGGER_STOP:
-               atomic_set(&dev->stream_started, 0);
-               break;
-       default:
-               retval = -EINVAL;
-               break;
-       }
-       spin_unlock(&dev->adev.slock);
-
-       schedule_work(&dev->wq_trigger);
-
-       return retval;
-}
-
-static snd_pcm_uframes_t snd_cx231xx_capture_pointer(struct snd_pcm_substream
-                                                    *substream)
-{
-       struct cx231xx *dev;
-       unsigned long flags;
-       snd_pcm_uframes_t hwptr_done;
-
-       dev = snd_pcm_substream_chip(substream);
-
-       spin_lock_irqsave(&dev->adev.slock, flags);
-       hwptr_done = dev->adev.hwptr_done_capture;
-       spin_unlock_irqrestore(&dev->adev.slock, flags);
-
-       return hwptr_done;
-}
-
-static struct page *snd_pcm_get_vmalloc_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 snd_cx231xx_pcm_capture = {
-       .open = snd_cx231xx_capture_open,
-       .close = snd_cx231xx_pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_cx231xx_hw_capture_params,
-       .hw_free = snd_cx231xx_hw_capture_free,
-       .prepare = snd_cx231xx_prepare,
-       .trigger = snd_cx231xx_capture_trigger,
-       .pointer = snd_cx231xx_capture_pointer,
-       .page = snd_pcm_get_vmalloc_page,
-};
-
-static int cx231xx_audio_init(struct cx231xx *dev)
-{
-       struct cx231xx_audio *adev = &dev->adev;
-       struct snd_pcm *pcm;
-       struct snd_card *card;
-       static int devnr;
-       int err;
-       struct usb_interface *uif;
-       int i, isoc_pipe = 0;
-
-       if (dev->has_alsa_audio != 1) {
-               /* This device does not support the extension (in this case
-                  the device is expecting the snd-usb-audio module or
-                  doesn't have analog audio support at all) */
-               return 0;
-       }
-
-       cx231xx_info("cx231xx-audio.c: probing for cx231xx "
-                    "non standard usbaudio\n");
-
-       err = snd_card_create(index[devnr], "Cx231xx Audio", THIS_MODULE,
-                             0, &card);
-       if (err < 0)
-               return err;
-
-       spin_lock_init(&adev->slock);
-       err = snd_pcm_new(card, "Cx231xx Audio", 0, 0, 1, &pcm);
-       if (err < 0) {
-               snd_card_free(card);
-               return err;
-       }
-
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
-                       &snd_cx231xx_pcm_capture);
-       pcm->info_flags = 0;
-       pcm->private_data = dev;
-       strcpy(pcm->name, "Conexant cx231xx Capture");
-       snd_card_set_dev(card, &dev->udev->dev);
-       strcpy(card->driver, "Cx231xx-Audio");
-       strcpy(card->shortname, "Cx231xx Audio");
-       strcpy(card->longname, "Conexant cx231xx Audio");
-
-       INIT_WORK(&dev->wq_trigger, audio_trigger);
-
-       err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
-               return err;
-       }
-       adev->sndcard = card;
-       adev->udev = dev->udev;
-
-       /* compute alternate max packet sizes for Audio */
-       uif =
-           dev->udev->actconfig->interface[dev->current_pcb_config.
-                                           hs_config_info[0].interface_info.
-                                           audio_index + 1];
-
-       adev->end_point_addr =
-           le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.
-                       bEndpointAddress);
-
-       adev->num_alt = uif->num_altsetting;
-       cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
-                    adev->end_point_addr, adev->num_alt);
-       adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL);
-
-       if (adev->alt_max_pkt_size == NULL) {
-               cx231xx_errdev("out of memory!\n");
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < adev->num_alt; i++) {
-               u16 tmp =
-                   le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.
-                               wMaxPacketSize);
-               adev->alt_max_pkt_size[i] =
-                   (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-               cx231xx_info("Alternate setting %i, max size= %i\n", i,
-                            adev->alt_max_pkt_size[i]);
-       }
-
-       return 0;
-}
-
-static int cx231xx_audio_fini(struct cx231xx *dev)
-{
-       if (dev == NULL)
-               return 0;
-
-       if (dev->has_alsa_audio != 1) {
-               /* This device does not support the extension (in this case
-                  the device is expecting the snd-usb-audio module or
-                  doesn't have analog audio support at all) */
-               return 0;
-       }
-
-       if (dev->adev.sndcard) {
-               snd_card_free(dev->adev.sndcard);
-               kfree(dev->adev.alt_max_pkt_size);
-               dev->adev.sndcard = NULL;
-       }
-
-       return 0;
-}
-
-static struct cx231xx_ops audio_ops = {
-       .id = CX231XX_AUDIO,
-       .name = "Cx231xx Audio Extension",
-       .init = cx231xx_audio_init,
-       .fini = cx231xx_audio_fini,
-};
-
-static int __init cx231xx_alsa_register(void)
-{
-       return cx231xx_register_extension(&audio_ops);
-}
-
-static void __exit cx231xx_alsa_unregister(void)
-{
-       cx231xx_unregister_extension(&audio_ops);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
-MODULE_DESCRIPTION("Cx231xx Audio driver");
-
-module_init(cx231xx_alsa_register);
-module_exit(cx231xx_alsa_unregister);
diff --git a/drivers/media/video/cx231xx/cx231xx-avcore.c b/drivers/media/video/cx231xx/cx231xx-avcore.c
deleted file mode 100644 (file)
index 447148e..0000000
+++ /dev/null
@@ -1,3087 +0,0 @@
-/*
-   cx231xx_avcore.c - driver for Conexant Cx23100/101/102
-                     USB video capture devices
-
-   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
-
-   This program contains the specific code to control the avdecoder chip and
-   other related usb control functions for cx231xx based chipset.
-
-   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/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 <linux/mm.h>
-#include <linux/mutex.h>
-#include <media/tuner.h>
-
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-chip-ident.h>
-
-#include "cx231xx.h"
-#include "cx231xx-dif.h"
-
-#define TUNER_MODE_FM_RADIO 0
-/******************************************************************************
-                       -: BLOCK ARRANGEMENT :-
-       I2S block ----------------------|
-       [I2S audio]                     |
-                                       |
-       Analog Front End --> Direct IF -|-> Cx25840 --> Audio
-       [video & audio]                 |   [Audio]
-                                       |
-                                       |-> Cx25840 --> Video
-                                           [Video]
-
-*******************************************************************************/
-/******************************************************************************
- *                    VERVE REGISTER                                          *
- *                                                                           *
- ******************************************************************************/
-static int verve_write_byte(struct cx231xx *dev, u8 saddr, u8 data)
-{
-       return cx231xx_write_i2c_data(dev, VERVE_I2C_ADDRESS,
-                                       saddr, 1, data, 1);
-}
-
-static int verve_read_byte(struct cx231xx *dev, u8 saddr, u8 *data)
-{
-       int status;
-       u32 temp = 0;
-
-       status = cx231xx_read_i2c_data(dev, VERVE_I2C_ADDRESS,
-                                       saddr, 1, &temp, 1);
-       *data = (u8) temp;
-       return status;
-}
-void initGPIO(struct cx231xx *dev)
-{
-       u32 _gpio_direction = 0;
-       u32 value = 0;
-       u8 val = 0;
-
-       _gpio_direction = _gpio_direction & 0xFC0003FF;
-       _gpio_direction = _gpio_direction | 0x03FDFC00;
-       cx231xx_send_gpio_cmd(dev, _gpio_direction, (u8 *)&value, 4, 0, 0);
-
-       verve_read_byte(dev, 0x07, &val);
-       cx231xx_info(" verve_read_byte address0x07=0x%x\n", val);
-       verve_write_byte(dev, 0x07, 0xF4);
-       verve_read_byte(dev, 0x07, &val);
-       cx231xx_info(" verve_read_byte address0x07=0x%x\n", val);
-
-       cx231xx_capture_start(dev, 1, Vbi);
-
-       cx231xx_mode_register(dev, EP_MODE_SET, 0x0500FE00);
-       cx231xx_mode_register(dev, GBULK_BIT_EN, 0xFFFDFFFF);
-
-}
-void uninitGPIO(struct cx231xx *dev)
-{
-       u8 value[4] = { 0, 0, 0, 0 };
-
-       cx231xx_capture_start(dev, 0, Vbi);
-       verve_write_byte(dev, 0x07, 0x14);
-       cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                       0x68, value, 4);
-}
-
-/******************************************************************************
- *                    A F E - B L O C K    C O N T R O L   functions          *
- *                             [ANALOG FRONT END]                            *
- ******************************************************************************/
-static int afe_write_byte(struct cx231xx *dev, u16 saddr, u8 data)
-{
-       return cx231xx_write_i2c_data(dev, AFE_DEVICE_ADDRESS,
-                                       saddr, 2, data, 1);
-}
-
-static int afe_read_byte(struct cx231xx *dev, u16 saddr, u8 *data)
-{
-       int status;
-       u32 temp = 0;
-
-       status = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS,
-                                       saddr, 2, &temp, 1);
-       *data = (u8) temp;
-       return status;
-}
-
-int cx231xx_afe_init_super_block(struct cx231xx *dev, u32 ref_count)
-{
-       int status = 0;
-       u8 temp = 0;
-       u8 afe_power_status = 0;
-       int i = 0;
-
-       /* super block initialize */
-       temp = (u8) (ref_count & 0xff);
-       status = afe_write_byte(dev, SUP_BLK_TUNE2, temp);
-       if (status < 0)
-               return status;
-
-       status = afe_read_byte(dev, SUP_BLK_TUNE2, &afe_power_status);
-       if (status < 0)
-               return status;
-
-       temp = (u8) ((ref_count & 0x300) >> 8);
-       temp |= 0x40;
-       status = afe_write_byte(dev, SUP_BLK_TUNE1, temp);
-       if (status < 0)
-               return status;
-
-       status = afe_write_byte(dev, SUP_BLK_PLL2, 0x0f);
-       if (status < 0)
-               return status;
-
-       /* enable pll     */
-       while (afe_power_status != 0x18) {
-               status = afe_write_byte(dev, SUP_BLK_PWRDN, 0x18);
-               if (status < 0) {
-                       cx231xx_info(
-                       ": Init Super Block failed in send cmd\n");
-                       break;
-               }
-
-               status = afe_read_byte(dev, SUP_BLK_PWRDN, &afe_power_status);
-               afe_power_status &= 0xff;
-               if (status < 0) {
-                       cx231xx_info(
-                       ": Init Super Block failed in receive cmd\n");
-                       break;
-               }
-               i++;
-               if (i == 10) {
-                       cx231xx_info(
-                       ": Init Super Block force break in loop !!!!\n");
-                       status = -1;
-                       break;
-               }
-       }
-
-       if (status < 0)
-               return status;
-
-       /* start tuning filter */
-       status = afe_write_byte(dev, SUP_BLK_TUNE3, 0x40);
-       if (status < 0)
-               return status;
-
-       msleep(5);
-
-       /* exit tuning */
-       status = afe_write_byte(dev, SUP_BLK_TUNE3, 0x00);
-
-       return status;
-}
-
-int cx231xx_afe_init_channels(struct cx231xx *dev)
-{
-       int status = 0;
-
-       /* power up all 3 channels, clear pd_buffer */
-       status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1, 0x00);
-       status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, 0x00);
-       status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, 0x00);
-
-       /* Enable quantizer calibration */
-       status = afe_write_byte(dev, ADC_COM_QUANT, 0x02);
-
-       /* channel initialize, force modulator (fb) reset */
-       status = afe_write_byte(dev, ADC_FB_FRCRST_CH1, 0x17);
-       status = afe_write_byte(dev, ADC_FB_FRCRST_CH2, 0x17);
-       status = afe_write_byte(dev, ADC_FB_FRCRST_CH3, 0x17);
-
-       /* start quantilizer calibration  */
-       status = afe_write_byte(dev, ADC_CAL_ATEST_CH1, 0x10);
-       status = afe_write_byte(dev, ADC_CAL_ATEST_CH2, 0x10);
-       status = afe_write_byte(dev, ADC_CAL_ATEST_CH3, 0x10);
-       msleep(5);
-
-       /* exit modulator (fb) reset */
-       status = afe_write_byte(dev, ADC_FB_FRCRST_CH1, 0x07);
-       status = afe_write_byte(dev, ADC_FB_FRCRST_CH2, 0x07);
-       status = afe_write_byte(dev, ADC_FB_FRCRST_CH3, 0x07);
-
-       /* enable the pre_clamp in each channel for single-ended input */
-       status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH1, 0xf0);
-       status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH2, 0xf0);
-       status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH3, 0xf0);
-
-       /* use diode instead of resistor, so set term_en to 0, res_en to 0  */
-       status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8,
-                                  ADC_QGAIN_RES_TRM_CH1, 3, 7, 0x00);
-       status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8,
-                                  ADC_QGAIN_RES_TRM_CH2, 3, 7, 0x00);
-       status = cx231xx_reg_mask_write(dev, AFE_DEVICE_ADDRESS, 8,
-                                  ADC_QGAIN_RES_TRM_CH3, 3, 7, 0x00);
-
-       /* dynamic element matching off */
-       status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH1, 0x03);
-       status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH2, 0x03);
-       status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH3, 0x03);
-
-       return status;
-}
-
-int cx231xx_afe_setup_AFE_for_baseband(struct cx231xx *dev)
-{
-       u8 c_value = 0;
-       int status = 0;
-
-       status = afe_read_byte(dev, ADC_PWRDN_CLAMP_CH2, &c_value);
-       c_value &= (~(0x50));
-       status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2, c_value);
-
-       return status;
-}
-
-/*
-       The Analog Front End in Cx231xx has 3 channels. These
-       channels are used to share between different inputs
-       like tuner, s-video and composite inputs.
-
-       channel 1 ----- pin 1  to pin4(in reg is 1-4)
-       channel 2 ----- pin 5  to pin8(in reg is 5-8)
-       channel 3 ----- pin 9 to pin 12(in reg is 9-11)
-*/
-int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux)
-{
-       u8 ch1_setting = (u8) input_mux;
-       u8 ch2_setting = (u8) (input_mux >> 8);
-       u8 ch3_setting = (u8) (input_mux >> 16);
-       int status = 0;
-       u8 value = 0;
-
-       if (ch1_setting != 0) {
-               status = afe_read_byte(dev, ADC_INPUT_CH1, &value);
-               value &= ~INPUT_SEL_MASK;
-               value |= (ch1_setting - 1) << 4;
-               value &= 0xff;
-               status = afe_write_byte(dev, ADC_INPUT_CH1, value);
-       }
-
-       if (ch2_setting != 0) {
-               status = afe_read_byte(dev, ADC_INPUT_CH2, &value);
-               value &= ~INPUT_SEL_MASK;
-               value |= (ch2_setting - 1) << 4;
-               value &= 0xff;
-               status = afe_write_byte(dev, ADC_INPUT_CH2, value);
-       }
-
-       /* For ch3_setting, the value to put in the register is
-          7 less than the input number */
-       if (ch3_setting != 0) {
-               status = afe_read_byte(dev, ADC_INPUT_CH3, &value);
-               value &= ~INPUT_SEL_MASK;
-               value |= (ch3_setting - 1) << 4;
-               value &= 0xff;
-               status = afe_write_byte(dev, ADC_INPUT_CH3, value);
-       }
-
-       return status;
-}
-
-int cx231xx_afe_set_mode(struct cx231xx *dev, enum AFE_MODE mode)
-{
-       int status = 0;
-
-       /*
-       * FIXME: We need to implement the AFE code for LOW IF and for HI IF.
-       * Currently, only baseband works.
-       */
-
-       switch (mode) {
-       case AFE_MODE_LOW_IF:
-               cx231xx_Setup_AFE_for_LowIF(dev);
-               break;
-       case AFE_MODE_BASEBAND:
-               status = cx231xx_afe_setup_AFE_for_baseband(dev);
-               break;
-       case AFE_MODE_EU_HI_IF:
-               /* SetupAFEforEuHiIF(); */
-               break;
-       case AFE_MODE_US_HI_IF:
-               /* SetupAFEforUsHiIF(); */
-               break;
-       case AFE_MODE_JAPAN_HI_IF:
-               /* SetupAFEforJapanHiIF(); */
-               break;
-       }
-
-       if ((mode != dev->afe_mode) &&
-               (dev->video_input == CX231XX_VMUX_TELEVISION))
-               status = cx231xx_afe_adjust_ref_count(dev,
-                                                    CX231XX_VMUX_TELEVISION);
-
-       dev->afe_mode = mode;
-
-       return status;
-}
-
-int cx231xx_afe_update_power_control(struct cx231xx *dev,
-                                       enum AV_MODE avmode)
-{
-       u8 afe_power_status = 0;
-       int status = 0;
-
-       switch (dev->model) {
-       case CX231XX_BOARD_CNXT_CARRAERA:
-       case CX231XX_BOARD_CNXT_RDE_250:
-       case CX231XX_BOARD_CNXT_SHELBY:
-       case CX231XX_BOARD_CNXT_RDU_250:
-       case CX231XX_BOARD_CNXT_RDE_253S:
-       case CX231XX_BOARD_CNXT_RDU_253S:
-       case CX231XX_BOARD_CNXT_VIDEO_GRABBER:
-       case CX231XX_BOARD_HAUPPAUGE_EXETER:
-       case CX231XX_BOARD_HAUPPAUGE_USBLIVE2:
-       case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
-       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
-       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
-               if (avmode == POLARIS_AVMODE_ANALOGT_TV) {
-                       while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
-                                               FLD_PWRDN_ENABLE_PLL)) {
-                               status = afe_write_byte(dev, SUP_BLK_PWRDN,
-                                                       FLD_PWRDN_TUNING_BIAS |
-                                                       FLD_PWRDN_ENABLE_PLL);
-                               status |= afe_read_byte(dev, SUP_BLK_PWRDN,
-                                                       &afe_power_status);
-                               if (status < 0)
-                                       break;
-                       }
-
-                       status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
-                                                       0x00);
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
-                                                       0x00);
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
-                                                       0x00);
-               } else if (avmode == POLARIS_AVMODE_DIGITAL) {
-                       status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
-                                                       0x70);
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
-                                                       0x70);
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
-                                                       0x70);
-
-                       status |= afe_read_byte(dev, SUP_BLK_PWRDN,
-                                                 &afe_power_status);
-                       afe_power_status |= FLD_PWRDN_PD_BANDGAP |
-                                               FLD_PWRDN_PD_BIAS |
-                                               FLD_PWRDN_PD_TUNECK;
-                       status |= afe_write_byte(dev, SUP_BLK_PWRDN,
-                                                  afe_power_status);
-               } else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) {
-                       while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
-                                               FLD_PWRDN_ENABLE_PLL)) {
-                               status = afe_write_byte(dev, SUP_BLK_PWRDN,
-                                                       FLD_PWRDN_TUNING_BIAS |
-                                                       FLD_PWRDN_ENABLE_PLL);
-                               status |= afe_read_byte(dev, SUP_BLK_PWRDN,
-                                                       &afe_power_status);
-                               if (status < 0)
-                                       break;
-                       }
-
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
-                                               0x00);
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
-                                               0x00);
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
-                                               0x00);
-               } else {
-                       cx231xx_info("Invalid AV mode input\n");
-                       status = -1;
-               }
-               break;
-       default:
-               if (avmode == POLARIS_AVMODE_ANALOGT_TV) {
-                       while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
-                                               FLD_PWRDN_ENABLE_PLL)) {
-                               status = afe_write_byte(dev, SUP_BLK_PWRDN,
-                                                       FLD_PWRDN_TUNING_BIAS |
-                                                       FLD_PWRDN_ENABLE_PLL);
-                               status |= afe_read_byte(dev, SUP_BLK_PWRDN,
-                                                       &afe_power_status);
-                               if (status < 0)
-                                       break;
-                       }
-
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
-                                                       0x40);
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
-                                                       0x40);
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
-                                                       0x00);
-               } else if (avmode == POLARIS_AVMODE_DIGITAL) {
-                       status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
-                                                       0x70);
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
-                                                       0x70);
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
-                                                       0x70);
-
-                       status |= afe_read_byte(dev, SUP_BLK_PWRDN,
-                                                      &afe_power_status);
-                       afe_power_status |= FLD_PWRDN_PD_BANDGAP |
-                                               FLD_PWRDN_PD_BIAS |
-                                               FLD_PWRDN_PD_TUNECK;
-                       status |= afe_write_byte(dev, SUP_BLK_PWRDN,
-                                                       afe_power_status);
-               } else if (avmode == POLARIS_AVMODE_ENXTERNAL_AV) {
-                       while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
-                                               FLD_PWRDN_ENABLE_PLL)) {
-                               status = afe_write_byte(dev, SUP_BLK_PWRDN,
-                                                       FLD_PWRDN_TUNING_BIAS |
-                                                       FLD_PWRDN_ENABLE_PLL);
-                               status |= afe_read_byte(dev, SUP_BLK_PWRDN,
-                                                       &afe_power_status);
-                               if (status < 0)
-                                       break;
-                       }
-
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH1,
-                                                       0x00);
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH2,
-                                                       0x00);
-                       status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
-                                                       0x40);
-               } else {
-                       cx231xx_info("Invalid AV mode input\n");
-                       status = -1;
-               }
-       }                       /* switch  */
-
-       return status;
-}
-
-int cx231xx_afe_adjust_ref_count(struct cx231xx *dev, u32 video_input)
-{
-       u8 input_mode = 0;
-       u8 ntf_mode = 0;
-       int status = 0;
-
-       dev->video_input = video_input;
-
-       if (video_input == CX231XX_VMUX_TELEVISION) {
-               status = afe_read_byte(dev, ADC_INPUT_CH3, &input_mode);
-               status = afe_read_byte(dev, ADC_NTF_PRECLMP_EN_CH3,
-                                       &ntf_mode);
-       } else {
-               status = afe_read_byte(dev, ADC_INPUT_CH1, &input_mode);
-               status = afe_read_byte(dev, ADC_NTF_PRECLMP_EN_CH1,
-                                       &ntf_mode);
-       }
-
-       input_mode = (ntf_mode & 0x3) | ((input_mode & 0x6) << 1);
-
-       switch (input_mode) {
-       case SINGLE_ENDED:
-               dev->afe_ref_count = 0x23C;
-               break;
-       case LOW_IF:
-               dev->afe_ref_count = 0x24C;
-               break;
-       case EU_IF:
-               dev->afe_ref_count = 0x258;
-               break;
-       case US_IF:
-               dev->afe_ref_count = 0x260;
-               break;
-       default:
-               break;
-       }
-
-       status = cx231xx_afe_init_super_block(dev, dev->afe_ref_count);
-
-       return status;
-}
-
-/******************************************************************************
- *     V I D E O / A U D I O    D E C O D E R    C O N T R O L   functions    *
- ******************************************************************************/
-static int vid_blk_write_byte(struct cx231xx *dev, u16 saddr, u8 data)
-{
-       return cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS,
-                                       saddr, 2, data, 1);
-}
-
-static int vid_blk_read_byte(struct cx231xx *dev, u16 saddr, u8 *data)
-{
-       int status;
-       u32 temp = 0;
-
-       status = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
-                                       saddr, 2, &temp, 1);
-       *data = (u8) temp;
-       return status;
-}
-
-static int vid_blk_write_word(struct cx231xx *dev, u16 saddr, u32 data)
-{
-       return cx231xx_write_i2c_data(dev, VID_BLK_I2C_ADDRESS,
-                                       saddr, 2, data, 4);
-}
-
-static int vid_blk_read_word(struct cx231xx *dev, u16 saddr, u32 *data)
-{
-       return cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
-                                       saddr, 2, data, 4);
-}
-int cx231xx_check_fw(struct cx231xx *dev)
-{
-       u8 temp = 0;
-       int status = 0;
-       status = vid_blk_read_byte(dev, DL_CTL_ADDRESS_LOW, &temp);
-       if (status < 0)
-               return status;
-       else
-               return temp;
-
-}
-
-int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input)
-{
-       int status = 0;
-
-       switch (INPUT(input)->type) {
-       case CX231XX_VMUX_COMPOSITE1:
-       case CX231XX_VMUX_SVIDEO:
-               if ((dev->current_pcb_config.type == USB_BUS_POWER) &&
-                   (dev->power_mode != POLARIS_AVMODE_ENXTERNAL_AV)) {
-                       /* External AV */
-                       status = cx231xx_set_power_mode(dev,
-                                       POLARIS_AVMODE_ENXTERNAL_AV);
-                       if (status < 0) {
-                               cx231xx_errdev("%s: set_power_mode : Failed to"
-                                               " set Power - errCode [%d]!\n",
-                                               __func__, status);
-                               return status;
-                       }
-               }
-               status = cx231xx_set_decoder_video_input(dev,
-                                                        INPUT(input)->type,
-                                                        INPUT(input)->vmux);
-               break;
-       case CX231XX_VMUX_TELEVISION:
-       case CX231XX_VMUX_CABLE:
-               if ((dev->current_pcb_config.type == USB_BUS_POWER) &&
-                   (dev->power_mode != POLARIS_AVMODE_ANALOGT_TV)) {
-                       /* Tuner */
-                       status = cx231xx_set_power_mode(dev,
-                                               POLARIS_AVMODE_ANALOGT_TV);
-                       if (status < 0) {
-                               cx231xx_errdev("%s: set_power_mode:Failed"
-                                       " to set Power - errCode [%d]!\n",
-                                       __func__, status);
-                               return status;
-                       }
-               }
-               if (dev->tuner_type == TUNER_NXP_TDA18271)
-                       status = cx231xx_set_decoder_video_input(dev,
-                                                       CX231XX_VMUX_TELEVISION,
-                                                       INPUT(input)->vmux);
-               else
-                       status = cx231xx_set_decoder_video_input(dev,
-                                                       CX231XX_VMUX_COMPOSITE1,
-                                                       INPUT(input)->vmux);
-
-               break;
-       default:
-               cx231xx_errdev("%s: set_power_mode : Unknown Input %d !\n",
-                    __func__, INPUT(input)->type);
-               break;
-       }
-
-       /* save the selection */
-       dev->video_input = input;
-
-       return status;
-}
-
-int cx231xx_set_decoder_video_input(struct cx231xx *dev,
-                               u8 pin_type, u8 input)
-{
-       int status = 0;
-       u32 value = 0;
-
-       if (pin_type != dev->video_input) {
-               status = cx231xx_afe_adjust_ref_count(dev, pin_type);
-               if (status < 0) {
-                       cx231xx_errdev("%s: adjust_ref_count :Failed to set"
-                               "AFE input mux - errCode [%d]!\n",
-                               __func__, status);
-                       return status;
-               }
-       }
-
-       /* call afe block to set video inputs */
-       status = cx231xx_afe_set_input_mux(dev, input);
-       if (status < 0) {
-               cx231xx_errdev("%s: set_input_mux :Failed to set"
-                               " AFE input mux - errCode [%d]!\n",
-                               __func__, status);
-               return status;
-       }
-
-       switch (pin_type) {
-       case CX231XX_VMUX_COMPOSITE1:
-               status = vid_blk_read_word(dev, AFE_CTRL, &value);
-               value |= (0 << 13) | (1 << 4);
-               value &= ~(1 << 5);
-
-               /* set [24:23] [22:15] to 0  */
-               value &= (~(0x1ff8000));
-               /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0  */
-               value |= 0x1000000;
-               status = vid_blk_write_word(dev, AFE_CTRL, value);
-
-               status = vid_blk_read_word(dev, OUT_CTRL1, &value);
-               value |= (1 << 7);
-               status = vid_blk_write_word(dev, OUT_CTRL1, value);
-
-               /* Set output mode */
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       OUT_CTRL1,
-                                                       FLD_OUT_MODE,
-                                                       dev->board.output_mode);
-
-               /* Tell DIF object to go to baseband mode  */
-               status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
-               if (status < 0) {
-                       cx231xx_errdev("%s: cx231xx_dif set to By pass"
-                                                  " mode- errCode [%d]!\n",
-                               __func__, status);
-                       return status;
-               }
-
-               /* Read the DFE_CTRL1 register */
-               status = vid_blk_read_word(dev, DFE_CTRL1, &value);
-
-               /* enable the VBI_GATE_EN */
-               value |= FLD_VBI_GATE_EN;
-
-               /* Enable the auto-VGA enable */
-               value |= FLD_VGA_AUTO_EN;
-
-               /* Write it back */
-               status = vid_blk_write_word(dev, DFE_CTRL1, value);
-
-               /* Disable auto config of registers */
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                                       VID_BLK_I2C_ADDRESS,
-                                       MODE_CTRL, FLD_ACFG_DIS,
-                                       cx231xx_set_field(FLD_ACFG_DIS, 1));
-
-               /* Set CVBS input mode */
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                       VID_BLK_I2C_ADDRESS,
-                       MODE_CTRL, FLD_INPUT_MODE,
-                       cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_CVBS_0));
-               break;
-       case CX231XX_VMUX_SVIDEO:
-               /* Disable the use of  DIF */
-
-               status = vid_blk_read_word(dev, AFE_CTRL, &value);
-
-               /* set [24:23] [22:15] to 0 */
-               value &= (~(0x1ff8000));
-               /* set FUNC_MODE[24:23] = 2
-               IF_MOD[22:15] = 0 DCR_BYP_CH2[4:4] = 1; */
-               value |= 0x1000010;
-               status = vid_blk_write_word(dev, AFE_CTRL, value);
-
-               /* Tell DIF object to go to baseband mode */
-               status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
-               if (status < 0) {
-                       cx231xx_errdev("%s: cx231xx_dif set to By pass"
-                                                  " mode- errCode [%d]!\n",
-                               __func__, status);
-                       return status;
-               }
-
-               /* Read the DFE_CTRL1 register */
-               status = vid_blk_read_word(dev, DFE_CTRL1, &value);
-
-               /* enable the VBI_GATE_EN */
-               value |= FLD_VBI_GATE_EN;
-
-               /* Enable the auto-VGA enable */
-               value |= FLD_VGA_AUTO_EN;
-
-               /* Write it back */
-               status = vid_blk_write_word(dev, DFE_CTRL1, value);
-
-               /* Disable auto config of registers  */
-               status =  cx231xx_read_modify_write_i2c_dword(dev,
-                                       VID_BLK_I2C_ADDRESS,
-                                       MODE_CTRL, FLD_ACFG_DIS,
-                                       cx231xx_set_field(FLD_ACFG_DIS, 1));
-
-               /* Set YC input mode */
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                       VID_BLK_I2C_ADDRESS,
-                       MODE_CTRL,
-                       FLD_INPUT_MODE,
-                       cx231xx_set_field(FLD_INPUT_MODE, INPUT_MODE_YC_1));
-
-               /* Chroma to ADC2 */
-               status = vid_blk_read_word(dev, AFE_CTRL, &value);
-               value |= FLD_CHROMA_IN_SEL;     /* set the chroma in select */
-
-               /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8)
-                  This sets them to use video
-                  rather than audio.  Only one of the two will be in use. */
-               value &= ~(FLD_VGA_SEL_CH2 | FLD_VGA_SEL_CH3);
-
-               status = vid_blk_write_word(dev, AFE_CTRL, value);
-
-               status = cx231xx_afe_set_mode(dev, AFE_MODE_BASEBAND);
-               break;
-       case CX231XX_VMUX_TELEVISION:
-       case CX231XX_VMUX_CABLE:
-       default:
-               /* TODO: Test if this is also needed for xc2028/xc3028 */
-               if (dev->board.tuner_type == TUNER_XC5000) {
-                       /* Disable the use of  DIF   */
-
-                       status = vid_blk_read_word(dev, AFE_CTRL, &value);
-                       value |= (0 << 13) | (1 << 4);
-                       value &= ~(1 << 5);
-
-                       /* set [24:23] [22:15] to 0 */
-                       value &= (~(0x1FF8000));
-                       /* set FUNC_MODE[24:23] = 2 IF_MOD[22:15] = 0 */
-                       value |= 0x1000000;
-                       status = vid_blk_write_word(dev, AFE_CTRL, value);
-
-                       status = vid_blk_read_word(dev, OUT_CTRL1, &value);
-                       value |= (1 << 7);
-                       status = vid_blk_write_word(dev, OUT_CTRL1, value);
-
-                       /* Set output mode */
-                       status = cx231xx_read_modify_write_i2c_dword(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       OUT_CTRL1, FLD_OUT_MODE,
-                                                       dev->board.output_mode);
-
-                       /* Tell DIF object to go to baseband mode */
-                       status = cx231xx_dif_set_standard(dev,
-                                                         DIF_USE_BASEBAND);
-                       if (status < 0) {
-                               cx231xx_errdev("%s: cx231xx_dif set to By pass"
-                                               " mode- errCode [%d]!\n",
-                                               __func__, status);
-                               return status;
-                       }
-
-                       /* Read the DFE_CTRL1 register */
-                       status = vid_blk_read_word(dev, DFE_CTRL1, &value);
-
-                       /* enable the VBI_GATE_EN */
-                       value |= FLD_VBI_GATE_EN;
-
-                       /* Enable the auto-VGA enable */
-                       value |= FLD_VGA_AUTO_EN;
-
-                       /* Write it back */
-                       status = vid_blk_write_word(dev, DFE_CTRL1, value);
-
-                       /* Disable auto config of registers */
-                       status = cx231xx_read_modify_write_i2c_dword(dev,
-                                       VID_BLK_I2C_ADDRESS,
-                                       MODE_CTRL, FLD_ACFG_DIS,
-                                       cx231xx_set_field(FLD_ACFG_DIS, 1));
-
-                       /* Set CVBS input mode */
-                       status = cx231xx_read_modify_write_i2c_dword(dev,
-                               VID_BLK_I2C_ADDRESS,
-                               MODE_CTRL, FLD_INPUT_MODE,
-                               cx231xx_set_field(FLD_INPUT_MODE,
-                                               INPUT_MODE_CVBS_0));
-               } else {
-                       /* Enable the DIF for the tuner */
-
-                       /* Reinitialize the DIF */
-                       status = cx231xx_dif_set_standard(dev, dev->norm);
-                       if (status < 0) {
-                               cx231xx_errdev("%s: cx231xx_dif set to By pass"
-                                               " mode- errCode [%d]!\n",
-                                               __func__, status);
-                               return status;
-                       }
-
-                       /* Make sure bypass is cleared */
-                       status = vid_blk_read_word(dev, DIF_MISC_CTRL, &value);
-
-                       /* Clear the bypass bit */
-                       value &= ~FLD_DIF_DIF_BYPASS;
-
-                       /* Enable the use of the DIF block */
-                       status = vid_blk_write_word(dev, DIF_MISC_CTRL, value);
-
-                       /* Read the DFE_CTRL1 register */
-                       status = vid_blk_read_word(dev, DFE_CTRL1, &value);
-
-                       /* Disable the VBI_GATE_EN */
-                       value &= ~FLD_VBI_GATE_EN;
-
-                       /* Enable the auto-VGA enable, AGC, and
-                          set the skip count to 2 */
-                       value |= FLD_VGA_AUTO_EN | FLD_AGC_AUTO_EN | 0x00200000;
-
-                       /* Write it back */
-                       status = vid_blk_write_word(dev, DFE_CTRL1, value);
-
-                       /* Wait until AGC locks up */
-                       msleep(1);
-
-                       /* Disable the auto-VGA enable AGC */
-                       value &= ~(FLD_VGA_AUTO_EN);
-
-                       /* Write it back */
-                       status = vid_blk_write_word(dev, DFE_CTRL1, value);
-
-                       /* Enable Polaris B0 AGC output */
-                       status = vid_blk_read_word(dev, PIN_CTRL, &value);
-                       value |= (FLD_OEF_AGC_RF) |
-                                (FLD_OEF_AGC_IFVGA) |
-                                (FLD_OEF_AGC_IF);
-                       status = vid_blk_write_word(dev, PIN_CTRL, value);
-
-                       /* Set output mode */
-                       status = cx231xx_read_modify_write_i2c_dword(dev,
-                                               VID_BLK_I2C_ADDRESS,
-                                               OUT_CTRL1, FLD_OUT_MODE,
-                                               dev->board.output_mode);
-
-                       /* Disable auto config of registers */
-                       status = cx231xx_read_modify_write_i2c_dword(dev,
-                                       VID_BLK_I2C_ADDRESS,
-                                       MODE_CTRL, FLD_ACFG_DIS,
-                                       cx231xx_set_field(FLD_ACFG_DIS, 1));
-
-                       /* Set CVBS input mode */
-                       status = cx231xx_read_modify_write_i2c_dword(dev,
-                               VID_BLK_I2C_ADDRESS,
-                               MODE_CTRL, FLD_INPUT_MODE,
-                               cx231xx_set_field(FLD_INPUT_MODE,
-                                               INPUT_MODE_CVBS_0));
-
-                       /* Set some bits in AFE_CTRL so that channel 2 or 3
-                        * is ready to receive audio */
-                       /* Clear clamp for channels 2 and 3      (bit 16-17) */
-                       /* Clear droop comp                      (bit 19-20) */
-                       /* Set VGA_SEL (for audio control)       (bit 7-8) */
-                       status = vid_blk_read_word(dev, AFE_CTRL, &value);
-
-                       /*Set Func mode:01-DIF 10-baseband 11-YUV*/
-                       value &= (~(FLD_FUNC_MODE));
-                       value |= 0x800000;
-
-                       value |= FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2;
-
-                       status = vid_blk_write_word(dev, AFE_CTRL, value);
-
-                       if (dev->tuner_type == TUNER_NXP_TDA18271) {
-                               status = vid_blk_read_word(dev, PIN_CTRL,
-                                &value);
-                               status = vid_blk_write_word(dev, PIN_CTRL,
-                                (value & 0xFFFFFFEF));
-                       }
-
-                       break;
-
-               }
-               break;
-       }
-
-       /* Set raw VBI mode */
-       status = cx231xx_read_modify_write_i2c_dword(dev,
-                               VID_BLK_I2C_ADDRESS,
-                               OUT_CTRL1, FLD_VBIHACTRAW_EN,
-                               cx231xx_set_field(FLD_VBIHACTRAW_EN, 1));
-
-       status = vid_blk_read_word(dev, OUT_CTRL1, &value);
-       if (value & 0x02) {
-               value |= (1 << 19);
-               status = vid_blk_write_word(dev, OUT_CTRL1, value);
-       }
-
-       return status;
-}
-
-void cx231xx_enable656(struct cx231xx *dev)
-{
-       u8 temp = 0;
-       /*enable TS1 data[0:7] as output to export 656*/
-
-       vid_blk_write_byte(dev, TS1_PIN_CTL0, 0xFF);
-
-       /*enable TS1 clock as output to export 656*/
-
-       vid_blk_read_byte(dev, TS1_PIN_CTL1, &temp);
-       temp = temp|0x04;
-
-       vid_blk_write_byte(dev, TS1_PIN_CTL1, temp);
-}
-EXPORT_SYMBOL_GPL(cx231xx_enable656);
-
-void cx231xx_disable656(struct cx231xx *dev)
-{
-       u8 temp = 0;
-
-       vid_blk_write_byte(dev, TS1_PIN_CTL0, 0x00);
-
-       vid_blk_read_byte(dev, TS1_PIN_CTL1, &temp);
-       temp = temp&0xFB;
-
-       vid_blk_write_byte(dev, TS1_PIN_CTL1, temp);
-}
-EXPORT_SYMBOL_GPL(cx231xx_disable656);
-
-/*
- * Handle any video-mode specific overrides that are different
- * on a per video standards basis after touching the MODE_CTRL
- * register which resets many values for autodetect
- */
-int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev)
-{
-       int status = 0;
-
-       cx231xx_info("do_mode_ctrl_overrides : 0x%x\n",
-                    (unsigned int)dev->norm);
-
-       /* Change the DFE_CTRL3 bp_percent to fix flagging */
-       status = vid_blk_write_word(dev, DFE_CTRL3, 0xCD3F0280);
-
-       if (dev->norm & (V4L2_STD_NTSC | V4L2_STD_PAL_M)) {
-               cx231xx_info("do_mode_ctrl_overrides NTSC\n");
-
-               /* Move the close caption lines out of active video,
-                  adjust the active video start point */
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       VERT_TIM_CTRL,
-                                                       FLD_VBLANK_CNT, 0x18);
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       VERT_TIM_CTRL,
-                                                       FLD_VACTIVE_CNT,
-                                                       0x1E7000);
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       VERT_TIM_CTRL,
-                                                       FLD_V656BLANK_CNT,
-                                                       0x1C000000);
-
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       HORIZ_TIM_CTRL,
-                                                       FLD_HBLANK_CNT,
-                                                       cx231xx_set_field
-                                                       (FLD_HBLANK_CNT, 0x79));
-
-       } else if (dev->norm & V4L2_STD_SECAM) {
-               cx231xx_info("do_mode_ctrl_overrides SECAM\n");
-               status =  cx231xx_read_modify_write_i2c_dword(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       VERT_TIM_CTRL,
-                                                       FLD_VBLANK_CNT, 0x20);
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       VERT_TIM_CTRL,
-                                                       FLD_VACTIVE_CNT,
-                                                       cx231xx_set_field
-                                                       (FLD_VACTIVE_CNT,
-                                                        0x244));
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       VERT_TIM_CTRL,
-                                                       FLD_V656BLANK_CNT,
-                                                       cx231xx_set_field
-                                                       (FLD_V656BLANK_CNT,
-                                                       0x24));
-               /* Adjust the active video horizontal start point */
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       HORIZ_TIM_CTRL,
-                                                       FLD_HBLANK_CNT,
-                                                       cx231xx_set_field
-                                                       (FLD_HBLANK_CNT, 0x85));
-       } else {
-               cx231xx_info("do_mode_ctrl_overrides PAL\n");
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       VERT_TIM_CTRL,
-                                                       FLD_VBLANK_CNT, 0x20);
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       VERT_TIM_CTRL,
-                                                       FLD_VACTIVE_CNT,
-                                                       cx231xx_set_field
-                                                       (FLD_VACTIVE_CNT,
-                                                        0x244));
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       VERT_TIM_CTRL,
-                                                       FLD_V656BLANK_CNT,
-                                                       cx231xx_set_field
-                                                       (FLD_V656BLANK_CNT,
-                                                       0x24));
-               /* Adjust the active video horizontal start point */
-               status = cx231xx_read_modify_write_i2c_dword(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       HORIZ_TIM_CTRL,
-                                                       FLD_HBLANK_CNT,
-                                                       cx231xx_set_field
-                                                       (FLD_HBLANK_CNT, 0x85));
-
-       }
-
-       return status;
-}
-
-int cx231xx_unmute_audio(struct cx231xx *dev)
-{
-       return vid_blk_write_byte(dev, PATH1_VOL_CTL, 0x24);
-}
-EXPORT_SYMBOL_GPL(cx231xx_unmute_audio);
-
-int stopAudioFirmware(struct cx231xx *dev)
-{
-       return vid_blk_write_byte(dev, DL_CTL_CONTROL, 0x03);
-}
-
-int restartAudioFirmware(struct cx231xx *dev)
-{
-       return vid_blk_write_byte(dev, DL_CTL_CONTROL, 0x13);
-}
-
-int cx231xx_set_audio_input(struct cx231xx *dev, u8 input)
-{
-       int status = 0;
-       enum AUDIO_INPUT ainput = AUDIO_INPUT_LINE;
-
-       switch (INPUT(input)->amux) {
-       case CX231XX_AMUX_VIDEO:
-               ainput = AUDIO_INPUT_TUNER_TV;
-               break;
-       case CX231XX_AMUX_LINE_IN:
-               status = cx231xx_i2s_blk_set_audio_input(dev, input);
-               ainput = AUDIO_INPUT_LINE;
-               break;
-       default:
-               break;
-       }
-
-       status = cx231xx_set_audio_decoder_input(dev, ainput);
-
-       return status;
-}
-
-int cx231xx_set_audio_decoder_input(struct cx231xx *dev,
-                                   enum AUDIO_INPUT audio_input)
-{
-       u32 dwval;
-       int status;
-       u8 gen_ctrl;
-       u32 value = 0;
-
-       /* Put it in soft reset   */
-       status = vid_blk_read_byte(dev, GENERAL_CTL, &gen_ctrl);
-       gen_ctrl |= 1;
-       status = vid_blk_write_byte(dev, GENERAL_CTL, gen_ctrl);
-
-       switch (audio_input) {
-       case AUDIO_INPUT_LINE:
-               /* setup AUD_IO control from Merlin paralle output */
-               value = cx231xx_set_field(FLD_AUD_CHAN1_SRC,
-                                         AUD_CHAN_SRC_PARALLEL);
-               status = vid_blk_write_word(dev, AUD_IO_CTRL, value);
-
-               /* setup input to Merlin, SRC2 connect to AC97
-                  bypass upsample-by-2, slave mode, sony mode, left justify
-                  adr 091c, dat 01000000 */
-               status = vid_blk_read_word(dev, AC97_CTL, &dwval);
-
-               status = vid_blk_write_word(dev, AC97_CTL,
-                                          (dwval | FLD_AC97_UP2X_BYPASS));
-
-               /* select the parallel1 and SRC3 */
-               status = vid_blk_write_word(dev, BAND_OUT_SEL,
-                               cx231xx_set_field(FLD_SRC3_IN_SEL, 0x0) |
-                               cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x0) |
-                               cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x0));
-
-               /* unmute all, AC97 in, independence mode
-                  adr 08d0, data 0x00063073 */
-               status = vid_blk_write_word(dev, DL_CTL, 0x3000001);
-               status = vid_blk_write_word(dev, PATH1_CTL1, 0x00063073);
-
-               /* set AVC maximum threshold, adr 08d4, dat ffff0024 */
-               status = vid_blk_read_word(dev, PATH1_VOL_CTL, &dwval);
-               status = vid_blk_write_word(dev, PATH1_VOL_CTL,
-                                          (dwval | FLD_PATH1_AVC_THRESHOLD));
-
-               /* set SC maximum threshold, adr 08ec, dat ffffb3a3 */
-               status = vid_blk_read_word(dev, PATH1_SC_CTL, &dwval);
-               status = vid_blk_write_word(dev, PATH1_SC_CTL,
-                                          (dwval | FLD_PATH1_SC_THRESHOLD));
-               break;
-
-       case AUDIO_INPUT_TUNER_TV:
-       default:
-               status = stopAudioFirmware(dev);
-               /* Setup SRC sources and clocks */
-               status = vid_blk_write_word(dev, BAND_OUT_SEL,
-                       cx231xx_set_field(FLD_SRC6_IN_SEL, 0x00)         |
-                       cx231xx_set_field(FLD_SRC6_CLK_SEL, 0x01)        |
-                       cx231xx_set_field(FLD_SRC5_IN_SEL, 0x00)         |
-                       cx231xx_set_field(FLD_SRC5_CLK_SEL, 0x02)        |
-                       cx231xx_set_field(FLD_SRC4_IN_SEL, 0x02)         |
-                       cx231xx_set_field(FLD_SRC4_CLK_SEL, 0x03)        |
-                       cx231xx_set_field(FLD_SRC3_IN_SEL, 0x00)         |
-                       cx231xx_set_field(FLD_SRC3_CLK_SEL, 0x00)        |
-                       cx231xx_set_field(FLD_BASEBAND_BYPASS_CTL, 0x00) |
-                       cx231xx_set_field(FLD_AC97_SRC_SEL, 0x03)        |
-                       cx231xx_set_field(FLD_I2S_SRC_SEL, 0x00)         |
-                       cx231xx_set_field(FLD_PARALLEL2_SRC_SEL, 0x02)   |
-                       cx231xx_set_field(FLD_PARALLEL1_SRC_SEL, 0x01));
-
-               /* Setup the AUD_IO control */
-               status = vid_blk_write_word(dev, AUD_IO_CTRL,
-                       cx231xx_set_field(FLD_I2S_PORT_DIR, 0x00)  |
-                       cx231xx_set_field(FLD_I2S_OUT_SRC, 0x00)   |
-                       cx231xx_set_field(FLD_AUD_CHAN3_SRC, 0x00) |
-                       cx231xx_set_field(FLD_AUD_CHAN2_SRC, 0x00) |
-                       cx231xx_set_field(FLD_AUD_CHAN1_SRC, 0x03));
-
-               status = vid_blk_write_word(dev, PATH1_CTL1, 0x1F063870);
-
-               /* setAudioStandard(_audio_standard); */
-               status = vid_blk_write_word(dev, PATH1_CTL1, 0x00063870);
-
-               status = restartAudioFirmware(dev);
-
-               switch (dev->board.tuner_type) {
-               case TUNER_XC5000:
-                       /* SIF passthrough at 28.6363 MHz sample rate */
-                       status = cx231xx_read_modify_write_i2c_dword(dev,
-                                       VID_BLK_I2C_ADDRESS,
-                                       CHIP_CTRL,
-                                       FLD_SIF_EN,
-                                       cx231xx_set_field(FLD_SIF_EN, 1));
-                       break;
-               case TUNER_NXP_TDA18271:
-                       /* Normal mode: SIF passthrough at 14.32 MHz */
-                       status = cx231xx_read_modify_write_i2c_dword(dev,
-                                       VID_BLK_I2C_ADDRESS,
-                                       CHIP_CTRL,
-                                       FLD_SIF_EN,
-                                       cx231xx_set_field(FLD_SIF_EN, 0));
-                       break;
-               default:
-                       /* This is just a casual suggestion to people adding
-                          new boards in case they use a tuner type we don't
-                          currently know about */
-                       printk(KERN_INFO "Unknown tuner type configuring SIF");
-                       break;
-               }
-               break;
-
-       case AUDIO_INPUT_TUNER_FM:
-               /*  use SIF for FM radio
-                  setupFM();
-                  setAudioStandard(_audio_standard);
-                */
-               break;
-
-       case AUDIO_INPUT_MUTE:
-               status = vid_blk_write_word(dev, PATH1_CTL1, 0x1F011012);
-               break;
-       }
-
-       /* Take it out of soft reset */
-       status = vid_blk_read_byte(dev, GENERAL_CTL, &gen_ctrl);
-       gen_ctrl &= ~1;
-       status = vid_blk_write_byte(dev, GENERAL_CTL, gen_ctrl);
-
-       return status;
-}
-
-/******************************************************************************
- *                    C H I P Specific  C O N T R O L   functions             *
- ******************************************************************************/
-int cx231xx_init_ctrl_pin_status(struct cx231xx *dev)
-{
-       u32 value;
-       int status = 0;
-
-       status = vid_blk_read_word(dev, PIN_CTRL, &value);
-       value |= (~dev->board.ctl_pin_status_mask);
-       status = vid_blk_write_word(dev, PIN_CTRL, value);
-
-       return status;
-}
-
-int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev,
-                                             u8 analog_or_digital)
-{
-       int status = 0;
-
-       /* first set the direction to output */
-       status = cx231xx_set_gpio_direction(dev,
-                                           dev->board.
-                                           agc_analog_digital_select_gpio, 1);
-
-       /* 0 - demod ; 1 - Analog mode */
-       status = cx231xx_set_gpio_value(dev,
-                                  dev->board.agc_analog_digital_select_gpio,
-                                  analog_or_digital);
-
-       return status;
-}
-
-int cx231xx_enable_i2c_port_3(struct cx231xx *dev, bool is_port_3)
-{
-       u8 value[4] = { 0, 0, 0, 0 };
-       int status = 0;
-       bool current_is_port_3;
-
-       if (dev->board.dont_use_port_3)
-               is_port_3 = false;
-       status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER,
-                                      PWR_CTL_EN, value, 4);
-       if (status < 0)
-               return status;
-
-       current_is_port_3 = value[0] & I2C_DEMOD_EN ? true : false;
-
-       /* Just return, if already using the right port */
-       if (current_is_port_3 == is_port_3)
-               return 0;
-
-       if (is_port_3)
-               value[0] |= I2C_DEMOD_EN;
-       else
-               value[0] &= ~I2C_DEMOD_EN;
-
-       cx231xx_info("Changing the i2c master port to %d\n",
-                    is_port_3 ?  3 : 1);
-
-       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                       PWR_CTL_EN, value, 4);
-
-       return status;
-
-}
-EXPORT_SYMBOL_GPL(cx231xx_enable_i2c_port_3);
-
-void update_HH_register_after_set_DIF(struct cx231xx *dev)
-{
-/*
-       u8 status = 0;
-       u32 value = 0;
-
-       vid_blk_write_word(dev, PIN_CTRL, 0xA0FFF82F);
-       vid_blk_write_word(dev, DIF_MISC_CTRL, 0x0A203F11);
-       vid_blk_write_word(dev, DIF_SRC_PHASE_INC, 0x1BEFBF06);
-
-       status = vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
-       vid_blk_write_word(dev, AFE_CTRL_C2HH_SRC_CTRL, 0x4485D390);
-       status = vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL,  &value);
-*/
-}
-
-void cx231xx_dump_HH_reg(struct cx231xx *dev)
-{
-       u32 value = 0;
-       u16  i = 0;
-
-       value = 0x45005390;
-       vid_blk_write_word(dev, 0x104, value);
-
-       for (i = 0x100; i < 0x140; i++) {
-               vid_blk_read_word(dev, i, &value);
-               cx231xx_info("reg0x%x=0x%x\n", i, value);
-               i = i+3;
-       }
-
-       for (i = 0x300; i < 0x400; i++) {
-               vid_blk_read_word(dev, i, &value);
-               cx231xx_info("reg0x%x=0x%x\n", i, value);
-               i = i+3;
-       }
-
-       for (i = 0x400; i < 0x440; i++) {
-               vid_blk_read_word(dev, i,  &value);
-               cx231xx_info("reg0x%x=0x%x\n", i, value);
-               i = i+3;
-       }
-
-       vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
-       cx231xx_info("AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
-       vid_blk_write_word(dev, AFE_CTRL_C2HH_SRC_CTRL, 0x4485D390);
-       vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
-       cx231xx_info("AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
-}
-
-void cx231xx_dump_SC_reg(struct cx231xx *dev)
-{
-       u8 value[4] = { 0, 0, 0, 0 };
-       cx231xx_info("cx231xx_dump_SC_reg!\n");
-
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", BOARD_CFG_STAT, value[0],
-                                value[1], value[2], value[3]);
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS_MODE_REG,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS_MODE_REG, value[0],
-                                value[1], value[2], value[3]);
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS1_CFG_REG,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_CFG_REG, value[0],
-                                value[1], value[2], value[3]);
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS1_LENGTH_REG,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_LENGTH_REG, value[0],
-                                value[1], value[2], value[3]);
-
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS2_CFG_REG,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_CFG_REG, value[0],
-                                value[1], value[2], value[3]);
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS2_LENGTH_REG,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_LENGTH_REG, value[0],
-                                value[1], value[2], value[3]);
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", EP_MODE_SET, value[0],
-                                value[1], value[2], value[3]);
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN1,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN1, value[0],
-                                value[1], value[2], value[3]);
-
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN2,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN2, value[0],
-                                value[1], value[2], value[3]);
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN3,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN3, value[0],
-                                value[1], value[2], value[3]);
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK0,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK0, value[0],
-                                value[1], value[2], value[3]);
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK1,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK1, value[0],
-                                value[1], value[2], value[3]);
-
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK2,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK2, value[0],
-                                value[1], value[2], value[3]);
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_GAIN,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_GAIN, value[0],
-                                value[1], value[2], value[3]);
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_CAR_REG,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_CAR_REG, value[0],
-                                value[1], value[2], value[3]);
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_OT_CFG1,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG1, value[0],
-                                value[1], value[2], value[3]);
-
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_OT_CFG2,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG2, value[0],
-                                value[1], value[2], value[3]);
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
-                                value, 4);
-       cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN, value[0],
-                                value[1], value[2], value[3]);
-
-
-}
-
-void cx231xx_Setup_AFE_for_LowIF(struct cx231xx *dev)
-
-{
-       u8 value = 0;
-
-       afe_read_byte(dev, ADC_STATUS2_CH3, &value);
-       value = (value & 0xFE)|0x01;
-       afe_write_byte(dev, ADC_STATUS2_CH3, value);
-
-       afe_read_byte(dev, ADC_STATUS2_CH3, &value);
-       value = (value & 0xFE)|0x00;
-       afe_write_byte(dev, ADC_STATUS2_CH3, value);
-
-
-/*
-       config colibri to lo-if mode
-
-       FIXME: ntf_mode = 2'b00 by default. But set 0x1 would reduce
-               the diff IF input by half,
-
-               for low-if agc defect
-*/
-
-       afe_read_byte(dev, ADC_NTF_PRECLMP_EN_CH3, &value);
-       value = (value & 0xFC)|0x00;
-       afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH3, value);
-
-       afe_read_byte(dev, ADC_INPUT_CH3, &value);
-       value = (value & 0xF9)|0x02;
-       afe_write_byte(dev, ADC_INPUT_CH3, value);
-
-       afe_read_byte(dev, ADC_FB_FRCRST_CH3, &value);
-       value = (value & 0xFB)|0x04;
-       afe_write_byte(dev, ADC_FB_FRCRST_CH3, value);
-
-       afe_read_byte(dev, ADC_DCSERVO_DEM_CH3, &value);
-       value = (value & 0xFC)|0x03;
-       afe_write_byte(dev, ADC_DCSERVO_DEM_CH3, value);
-
-       afe_read_byte(dev, ADC_CTRL_DAC1_CH3, &value);
-       value = (value & 0xFB)|0x04;
-       afe_write_byte(dev, ADC_CTRL_DAC1_CH3, value);
-
-       afe_read_byte(dev, ADC_CTRL_DAC23_CH3, &value);
-       value = (value & 0xF8)|0x06;
-       afe_write_byte(dev, ADC_CTRL_DAC23_CH3, value);
-
-       afe_read_byte(dev, ADC_CTRL_DAC23_CH3, &value);
-       value = (value & 0x8F)|0x40;
-       afe_write_byte(dev, ADC_CTRL_DAC23_CH3, value);
-
-       afe_read_byte(dev, ADC_PWRDN_CLAMP_CH3, &value);
-       value = (value & 0xDF)|0x20;
-       afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, value);
-}
-
-void cx231xx_set_Colibri_For_LowIF(struct cx231xx *dev, u32 if_freq,
-                u8 spectral_invert, u32 mode)
-{
-       u32 colibri_carrier_offset = 0;
-       u32 func_mode = 0x01; /* Device has a DIF if this function is called */
-       u32 standard = 0;
-       u8 value[4] = { 0, 0, 0, 0 };
-
-       cx231xx_info("Enter cx231xx_set_Colibri_For_LowIF()\n");
-       value[0] = (u8) 0x6F;
-       value[1] = (u8) 0x6F;
-       value[2] = (u8) 0x6F;
-       value[3] = (u8) 0x6F;
-       cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                       PWR_CTL_EN, value, 4);
-
-       /*Set colibri for low IF*/
-       cx231xx_afe_set_mode(dev, AFE_MODE_LOW_IF);
-
-       /* Set C2HH for low IF operation.*/
-       standard = dev->norm;
-       cx231xx_dif_configure_C2HH_for_low_IF(dev, dev->active_mode,
-                                                      func_mode, standard);
-
-       /* Get colibri offsets.*/
-       colibri_carrier_offset = cx231xx_Get_Colibri_CarrierOffset(mode,
-                                                                  standard);
-
-       cx231xx_info("colibri_carrier_offset=%d, standard=0x%x\n",
-                    colibri_carrier_offset, standard);
-
-       /* Set the band Pass filter for DIF*/
-       cx231xx_set_DIF_bandpass(dev, (if_freq+colibri_carrier_offset),
-                                spectral_invert, mode);
-}
-
-u32 cx231xx_Get_Colibri_CarrierOffset(u32 mode, u32 standerd)
-{
-       u32 colibri_carrier_offset = 0;
-
-       if (mode == TUNER_MODE_FM_RADIO) {
-               colibri_carrier_offset = 1100000;
-       } else if (standerd & (V4L2_STD_MN | V4L2_STD_NTSC_M_JP)) {
-               colibri_carrier_offset = 4832000;  /*4.83MHz    */
-       } else if (standerd & (V4L2_STD_PAL_B | V4L2_STD_PAL_G)) {
-               colibri_carrier_offset = 2700000;  /*2.70MHz       */
-       } else if (standerd & (V4L2_STD_PAL_D | V4L2_STD_PAL_I
-                       | V4L2_STD_SECAM)) {
-               colibri_carrier_offset = 2100000;  /*2.10MHz    */
-       }
-
-       return colibri_carrier_offset;
-}
-
-void cx231xx_set_DIF_bandpass(struct cx231xx *dev, u32 if_freq,
-                u8 spectral_invert, u32 mode)
-{
-       unsigned long pll_freq_word;
-       u32 dif_misc_ctrl_value = 0;
-       u64 pll_freq_u64 = 0;
-       u32 i = 0;
-
-       cx231xx_info("if_freq=%d;spectral_invert=0x%x;mode=0x%x\n",
-                        if_freq, spectral_invert, mode);
-
-
-       if (mode == TUNER_MODE_FM_RADIO) {
-               pll_freq_word = 0x905A1CAC;
-               vid_blk_write_word(dev, DIF_PLL_FREQ_WORD,  pll_freq_word);
-
-       } else /*KSPROPERTY_TUNER_MODE_TV*/{
-               /* Calculate the PLL frequency word based on the adjusted if_freq*/
-               pll_freq_word = if_freq;
-               pll_freq_u64 = (u64)pll_freq_word << 28L;
-               do_div(pll_freq_u64, 50000000);
-               pll_freq_word = (u32)pll_freq_u64;
-               /*pll_freq_word = 0x3463497;*/
-               vid_blk_write_word(dev, DIF_PLL_FREQ_WORD,  pll_freq_word);
-
-       if (spectral_invert) {
-               if_freq -= 400000;
-               /* Enable Spectral Invert*/
-               vid_blk_read_word(dev, DIF_MISC_CTRL,
-                                       &dif_misc_ctrl_value);
-               dif_misc_ctrl_value = dif_misc_ctrl_value | 0x00200000;
-               vid_blk_write_word(dev, DIF_MISC_CTRL,
-                                       dif_misc_ctrl_value);
-       } else {
-               if_freq += 400000;
-               /* Disable Spectral Invert*/
-               vid_blk_read_word(dev, DIF_MISC_CTRL,
-                                       &dif_misc_ctrl_value);
-               dif_misc_ctrl_value = dif_misc_ctrl_value & 0xFFDFFFFF;
-               vid_blk_write_word(dev, DIF_MISC_CTRL,
-                                       dif_misc_ctrl_value);
-       }
-
-       if_freq = (if_freq/100000)*100000;
-
-       if (if_freq < 3000000)
-               if_freq = 3000000;
-
-       if (if_freq > 16000000)
-               if_freq = 16000000;
-       }
-
-       cx231xx_info("Enter IF=%zd\n",
-                       ARRAY_SIZE(Dif_set_array));
-       for (i = 0; i < ARRAY_SIZE(Dif_set_array); i++) {
-               if (Dif_set_array[i].if_freq == if_freq) {
-                       vid_blk_write_word(dev,
-                       Dif_set_array[i].register_address, Dif_set_array[i].value);
-               }
-       }
-}
-
-/******************************************************************************
- *                 D I F - B L O C K    C O N T R O L   functions             *
- ******************************************************************************/
-int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode,
-                                         u32 function_mode, u32 standard)
-{
-       int status = 0;
-
-
-       if (mode == V4L2_TUNER_RADIO) {
-               /* C2HH */
-               /* lo if big signal */
-               status = cx231xx_reg_mask_write(dev,
-                               VID_BLK_I2C_ADDRESS, 32,
-                               AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);
-               /* FUNC_MODE = DIF */
-               status = cx231xx_reg_mask_write(dev,
-                               VID_BLK_I2C_ADDRESS, 32,
-                               AFE_CTRL_C2HH_SRC_CTRL, 23, 24, function_mode);
-               /* IF_MODE */
-               status = cx231xx_reg_mask_write(dev,
-                               VID_BLK_I2C_ADDRESS, 32,
-                               AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xFF);
-               /* no inv */
-               status = cx231xx_reg_mask_write(dev,
-                               VID_BLK_I2C_ADDRESS, 32,
-                               AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);
-       } else if (standard != DIF_USE_BASEBAND) {
-               if (standard & V4L2_STD_MN) {
-                       /* lo if big signal */
-                       status = cx231xx_reg_mask_write(dev,
-                                       VID_BLK_I2C_ADDRESS, 32,
-                                       AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);
-                       /* FUNC_MODE = DIF */
-                       status = cx231xx_reg_mask_write(dev,
-                                       VID_BLK_I2C_ADDRESS, 32,
-                                       AFE_CTRL_C2HH_SRC_CTRL, 23, 24,
-                                       function_mode);
-                       /* IF_MODE */
-                       status = cx231xx_reg_mask_write(dev,
-                                       VID_BLK_I2C_ADDRESS, 32,
-                                       AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xb);
-                       /* no inv */
-                       status = cx231xx_reg_mask_write(dev,
-                                       VID_BLK_I2C_ADDRESS, 32,
-                                       AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);
-                       /* 0x124, AUD_CHAN1_SRC = 0x3 */
-                       status = cx231xx_reg_mask_write(dev,
-                                       VID_BLK_I2C_ADDRESS, 32,
-                                       AUD_IO_CTRL, 0, 31, 0x00000003);
-               } else if ((standard == V4L2_STD_PAL_I) |
-                       (standard & V4L2_STD_PAL_D) |
-                       (standard & V4L2_STD_SECAM)) {
-                       /* C2HH setup */
-                       /* lo if big signal */
-                       status = cx231xx_reg_mask_write(dev,
-                                       VID_BLK_I2C_ADDRESS, 32,
-                                       AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);
-                       /* FUNC_MODE = DIF */
-                       status = cx231xx_reg_mask_write(dev,
-                                       VID_BLK_I2C_ADDRESS, 32,
-                                       AFE_CTRL_C2HH_SRC_CTRL, 23, 24,
-                                       function_mode);
-                       /* IF_MODE */
-                       status = cx231xx_reg_mask_write(dev,
-                                       VID_BLK_I2C_ADDRESS, 32,
-                                       AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xF);
-                       /* no inv */
-                       status = cx231xx_reg_mask_write(dev,
-                                       VID_BLK_I2C_ADDRESS, 32,
-                                       AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);
-               } else {
-                       /* default PAL BG */
-                       /* C2HH setup */
-                       /* lo if big signal */
-                       status = cx231xx_reg_mask_write(dev,
-                                       VID_BLK_I2C_ADDRESS, 32,
-                                       AFE_CTRL_C2HH_SRC_CTRL, 30, 31, 0x1);
-                       /* FUNC_MODE = DIF */
-                       status = cx231xx_reg_mask_write(dev,
-                                       VID_BLK_I2C_ADDRESS, 32,
-                                       AFE_CTRL_C2HH_SRC_CTRL, 23, 24,
-                                       function_mode);
-                       /* IF_MODE */
-                       status = cx231xx_reg_mask_write(dev,
-                                       VID_BLK_I2C_ADDRESS, 32,
-                                       AFE_CTRL_C2HH_SRC_CTRL, 15, 22, 0xE);
-                       /* no inv */
-                       status = cx231xx_reg_mask_write(dev,
-                                       VID_BLK_I2C_ADDRESS, 32,
-                                       AFE_CTRL_C2HH_SRC_CTRL, 9, 9, 0x1);
-               }
-       }
-
-       return status;
-}
-
-int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard)
-{
-       int status = 0;
-       u32 dif_misc_ctrl_value = 0;
-       u32 func_mode = 0;
-
-       cx231xx_info("%s: setStandard to %x\n", __func__, standard);
-
-       status = vid_blk_read_word(dev, DIF_MISC_CTRL, &dif_misc_ctrl_value);
-       if (standard != DIF_USE_BASEBAND)
-               dev->norm = standard;
-
-       switch (dev->model) {
-       case CX231XX_BOARD_CNXT_CARRAERA:
-       case CX231XX_BOARD_CNXT_RDE_250:
-       case CX231XX_BOARD_CNXT_SHELBY:
-       case CX231XX_BOARD_CNXT_RDU_250:
-       case CX231XX_BOARD_CNXT_VIDEO_GRABBER:
-       case CX231XX_BOARD_HAUPPAUGE_EXETER:
-               func_mode = 0x03;
-               break;
-       case CX231XX_BOARD_CNXT_RDE_253S:
-       case CX231XX_BOARD_CNXT_RDU_253S:
-       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
-       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
-               func_mode = 0x01;
-               break;
-       default:
-               func_mode = 0x01;
-       }
-
-       status = cx231xx_dif_configure_C2HH_for_low_IF(dev, dev->active_mode,
-                                                 func_mode, standard);
-
-       if (standard == DIF_USE_BASEBAND) {     /* base band */
-               /* There is a different SRC_PHASE_INC value
-                  for baseband vs. DIF */
-               status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC, 0xDF7DF83);
-               status = vid_blk_read_word(dev, DIF_MISC_CTRL,
-                                               &dif_misc_ctrl_value);
-               dif_misc_ctrl_value |= FLD_DIF_DIF_BYPASS;
-               status = vid_blk_write_word(dev, DIF_MISC_CTRL,
-                                               dif_misc_ctrl_value);
-       } else if (standard & V4L2_STD_PAL_D) {
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL3, 0, 31, 0x00008800);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_IF_REF, 0, 31, 0x444C1380);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_IF, 0, 31, 0xDA302600);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_INT, 0, 31, 0xDA261700);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_RF, 0, 31, 0xDA262600);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_IF_INT_CURRENT, 0, 31,
-                                          0x26001700);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_RF_CURRENT, 0, 31,
-                                          0x00002660);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_VIDEO_AGC_CTRL, 0, 31,
-                                          0x72500800);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_VID_AUD_OVERRIDE, 0, 31,
-                                          0x27000100);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AV_SEP_CTRL, 0, 31, 0x3F3934EA);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_COMP_FLT_CTRL, 0, 31,
-                                          0x00000000);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_SRC_PHASE_INC, 0, 31,
-                                          0x1befbf06);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_SRC_GAIN_CONTROL, 0, 31,
-                                          0x000035e8);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_RPT_VARIANCE, 0, 31, 0x00000000);
-               /* Save the Spec Inversion value */
-               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
-               dif_misc_ctrl_value |= 0x3a023F11;
-       } else if (standard & V4L2_STD_PAL_I) {
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL3, 0, 31, 0x00008800);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_IF_REF, 0, 31, 0x444C1380);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_IF, 0, 31, 0xDA302600);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_INT, 0, 31, 0xDA261700);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_RF, 0, 31, 0xDA262600);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_IF_INT_CURRENT, 0, 31,
-                                          0x26001700);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_RF_CURRENT, 0, 31,
-                                          0x00002660);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_VIDEO_AGC_CTRL, 0, 31,
-                                          0x72500800);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_VID_AUD_OVERRIDE, 0, 31,
-                                          0x27000100);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AV_SEP_CTRL, 0, 31, 0x5F39A934);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_COMP_FLT_CTRL, 0, 31,
-                                          0x00000000);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_SRC_PHASE_INC, 0, 31,
-                                          0x1befbf06);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_SRC_GAIN_CONTROL, 0, 31,
-                                          0x000035e8);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_RPT_VARIANCE, 0, 31, 0x00000000);
-               /* Save the Spec Inversion value */
-               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
-               dif_misc_ctrl_value |= 0x3a033F11;
-       } else if (standard & V4L2_STD_PAL_M) {
-               /* improved Low Frequency Phase Noise */
-               status = vid_blk_write_word(dev, DIF_PLL_CTRL, 0xFF01FF0C);
-               status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xbd038c85);
-               status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1db4640a);
-               status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800);
-               status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C1380);
-               status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT,
-                                               0x26001700);
-               status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT,
-                                               0x00002660);
-               status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL,
-                                               0x72500800);
-               status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE,
-                                               0x27000100);
-               status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL, 0x012c405d);
-               status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL,
-                                               0x009f50c1);
-               status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC,
-                                               0x1befbf06);
-               status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL,
-                                               0x000035e8);
-               status = vid_blk_write_word(dev, DIF_SOFT_RST_CTRL_REVB,
-                                               0x00000000);
-               /* Save the Spec Inversion value */
-               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
-               dif_misc_ctrl_value |= 0x3A0A3F10;
-       } else if (standard & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) {
-               /* improved Low Frequency Phase Noise */
-               status = vid_blk_write_word(dev, DIF_PLL_CTRL, 0xFF01FF0C);
-               status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xbd038c85);
-               status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1db4640a);
-               status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800);
-               status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C1380);
-               status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT,
-                                               0x26001700);
-               status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT,
-                                               0x00002660);
-               status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL,
-                                               0x72500800);
-               status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE,
-                                               0x27000100);
-               status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL,
-                                               0x012c405d);
-               status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL,
-                                               0x009f50c1);
-               status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC,
-                                               0x1befbf06);
-               status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL,
-                                               0x000035e8);
-               status = vid_blk_write_word(dev, DIF_SOFT_RST_CTRL_REVB,
-                                               0x00000000);
-               /* Save the Spec Inversion value */
-               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
-               dif_misc_ctrl_value = 0x3A093F10;
-       } else if (standard &
-                 (V4L2_STD_SECAM_B | V4L2_STD_SECAM_D | V4L2_STD_SECAM_G |
-                  V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1)) {
-
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL3, 0, 31, 0x00008800);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_IF_REF, 0, 31, 0x888C0380);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_IF, 0, 31, 0xe0262600);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_INT, 0, 31, 0xc2171700);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_RF, 0, 31, 0xc2262600);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_IF_INT_CURRENT, 0, 31,
-                                          0x26001700);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_RF_CURRENT, 0, 31,
-                                          0x00002660);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_VID_AUD_OVERRIDE, 0, 31,
-                                          0x27000100);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_COMP_FLT_CTRL, 0, 31,
-                                          0x00000000);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_SRC_PHASE_INC, 0, 31,
-                                          0x1befbf06);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_SRC_GAIN_CONTROL, 0, 31,
-                                          0x000035e8);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_RPT_VARIANCE, 0, 31, 0x00000000);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_VIDEO_AGC_CTRL, 0, 31,
-                                          0xf4000000);
-
-               /* Save the Spec Inversion value */
-               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
-               dif_misc_ctrl_value |= 0x3a023F11;
-       } else if (standard & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) {
-               /* Is it SECAM_L1? */
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL3, 0, 31, 0x00008800);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_IF_REF, 0, 31, 0x888C0380);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_IF, 0, 31, 0xe0262600);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_INT, 0, 31, 0xc2171700);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_RF, 0, 31, 0xc2262600);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_IF_INT_CURRENT, 0, 31,
-                                          0x26001700);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_RF_CURRENT, 0, 31,
-                                          0x00002660);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_VID_AUD_OVERRIDE, 0, 31,
-                                          0x27000100);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AV_SEP_CTRL, 0, 31, 0x3F3530ec);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_COMP_FLT_CTRL, 0, 31,
-                                          0x00000000);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_SRC_PHASE_INC, 0, 31,
-                                          0x1befbf06);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_SRC_GAIN_CONTROL, 0, 31,
-                                          0x000035e8);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_RPT_VARIANCE, 0, 31, 0x00000000);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_VIDEO_AGC_CTRL, 0, 31,
-                                          0xf2560000);
-
-               /* Save the Spec Inversion value */
-               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
-               dif_misc_ctrl_value |= 0x3a023F11;
-
-       } else if (standard & V4L2_STD_NTSC_M) {
-               /* V4L2_STD_NTSC_M (75 IRE Setup) Or
-                  V4L2_STD_NTSC_M_JP (Japan,  0 IRE Setup) */
-
-               /* For NTSC the centre frequency of video coming out of
-                  sidewinder is around 7.1MHz or 3.6MHz depending on the
-                  spectral inversion. so for a non spectrally inverted channel
-                  the pll freq word is 0x03420c49
-                */
-
-               status = vid_blk_write_word(dev, DIF_PLL_CTRL, 0x6503BC0C);
-               status = vid_blk_write_word(dev, DIF_PLL_CTRL1, 0xBD038C85);
-               status = vid_blk_write_word(dev, DIF_PLL_CTRL2, 0x1DB4640A);
-               status = vid_blk_write_word(dev, DIF_PLL_CTRL3, 0x00008800);
-               status = vid_blk_write_word(dev, DIF_AGC_IF_REF, 0x444C0380);
-               status = vid_blk_write_word(dev, DIF_AGC_IF_INT_CURRENT,
-                                               0x26001700);
-               status = vid_blk_write_word(dev, DIF_AGC_RF_CURRENT,
-                                               0x00002660);
-               status = vid_blk_write_word(dev, DIF_VIDEO_AGC_CTRL,
-                                               0x04000800);
-               status = vid_blk_write_word(dev, DIF_VID_AUD_OVERRIDE,
-                                               0x27000100);
-               status = vid_blk_write_word(dev, DIF_AV_SEP_CTRL, 0x01296e1f);
-
-               status = vid_blk_write_word(dev, DIF_COMP_FLT_CTRL,
-                                               0x009f50c1);
-               status = vid_blk_write_word(dev, DIF_SRC_PHASE_INC,
-                                               0x1befbf06);
-               status = vid_blk_write_word(dev, DIF_SRC_GAIN_CONTROL,
-                                               0x000035e8);
-
-               status = vid_blk_write_word(dev, DIF_AGC_CTRL_IF, 0xC2262600);
-               status = vid_blk_write_word(dev, DIF_AGC_CTRL_INT,
-                                               0xC2262600);
-               status = vid_blk_write_word(dev, DIF_AGC_CTRL_RF, 0xC2262600);
-
-               /* Save the Spec Inversion value */
-               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
-               dif_misc_ctrl_value |= 0x3a003F10;
-       } else {
-               /* default PAL BG */
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL, 0, 31, 0x6503bc0c);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL1, 0, 31, 0xbd038c85);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL2, 0, 31, 0x1db4640a);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_PLL_CTRL3, 0, 31, 0x00008800);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_IF_REF, 0, 31, 0x444C1380);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_IF, 0, 31, 0xDA302600);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_INT, 0, 31, 0xDA261700);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_CTRL_RF, 0, 31, 0xDA262600);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_IF_INT_CURRENT, 0, 31,
-                                          0x26001700);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AGC_RF_CURRENT, 0, 31,
-                                          0x00002660);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_VIDEO_AGC_CTRL, 0, 31,
-                                          0x72500800);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_VID_AUD_OVERRIDE, 0, 31,
-                                          0x27000100);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_AV_SEP_CTRL, 0, 31, 0x3F3530EC);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_COMP_FLT_CTRL, 0, 31,
-                                          0x00A653A8);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_SRC_PHASE_INC, 0, 31,
-                                          0x1befbf06);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_SRC_GAIN_CONTROL, 0, 31,
-                                          0x000035e8);
-               status = cx231xx_reg_mask_write(dev, VID_BLK_I2C_ADDRESS, 32,
-                                          DIF_RPT_VARIANCE, 0, 31, 0x00000000);
-               /* Save the Spec Inversion value */
-               dif_misc_ctrl_value &= FLD_DIF_SPEC_INV;
-               dif_misc_ctrl_value |= 0x3a013F11;
-       }
-
-       /* The AGC values should be the same for all standards,
-          AUD_SRC_SEL[19] should always be disabled    */
-       dif_misc_ctrl_value &= ~FLD_DIF_AUD_SRC_SEL;
-
-       /* It is still possible to get Set Standard calls even when we
-          are in FM mode.
-          This is done to override the value for FM. */
-       if (dev->active_mode == V4L2_TUNER_RADIO)
-               dif_misc_ctrl_value = 0x7a080000;
-
-       /* Write the calculated value for misc ontrol register      */
-       status = vid_blk_write_word(dev, DIF_MISC_CTRL, dif_misc_ctrl_value);
-
-       return status;
-}
-
-int cx231xx_tuner_pre_channel_change(struct cx231xx *dev)
-{
-       int status = 0;
-       u32 dwval;
-
-       /* Set the RF and IF k_agc values to 3 */
-       status = vid_blk_read_word(dev, DIF_AGC_IF_REF, &dwval);
-       dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF);
-       dwval |= 0x33000000;
-
-       status = vid_blk_write_word(dev, DIF_AGC_IF_REF, dwval);
-
-       return status;
-}
-
-int cx231xx_tuner_post_channel_change(struct cx231xx *dev)
-{
-       int status = 0;
-       u32 dwval;
-       cx231xx_info("cx231xx_tuner_post_channel_change  dev->tuner_type =0%d\n",
-                    dev->tuner_type);
-       /* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for
-        * SECAM L/B/D standards */
-       status = vid_blk_read_word(dev, DIF_AGC_IF_REF, &dwval);
-       dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF);
-
-       if (dev->norm & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_B |
-                        V4L2_STD_SECAM_D)) {
-                       if (dev->tuner_type == TUNER_NXP_TDA18271) {
-                               dwval &= ~FLD_DIF_IF_REF;
-                               dwval |= 0x88000300;
-                       } else
-                               dwval |= 0x88000000;
-               } else {
-                       if (dev->tuner_type == TUNER_NXP_TDA18271) {
-                               dwval &= ~FLD_DIF_IF_REF;
-                               dwval |= 0xCC000300;
-                       } else
-                               dwval |= 0x44000000;
-               }
-
-       status = vid_blk_write_word(dev, DIF_AGC_IF_REF, dwval);
-
-       return status;
-}
-
-/******************************************************************************
- *                 I 2 S - B L O C K    C O N T R O L   functions            *
- ******************************************************************************/
-int cx231xx_i2s_blk_initialize(struct cx231xx *dev)
-{
-       int status = 0;
-       u32 value;
-
-       status = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
-                                      CH_PWR_CTRL1, 1, &value, 1);
-       /* enables clock to delta-sigma and decimation filter */
-       value |= 0x80;
-       status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
-                                       CH_PWR_CTRL1, 1, value, 1);
-       /* power up all channel */
-       status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
-                                       CH_PWR_CTRL2, 1, 0x00, 1);
-
-       return status;
-}
-
-int cx231xx_i2s_blk_update_power_control(struct cx231xx *dev,
-                                       enum AV_MODE avmode)
-{
-       int status = 0;
-       u32 value = 0;
-
-       if (avmode != POLARIS_AVMODE_ENXTERNAL_AV) {
-               status = cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
-                                         CH_PWR_CTRL2, 1, &value, 1);
-               value |= 0xfe;
-               status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
-                                               CH_PWR_CTRL2, 1, value, 1);
-       } else {
-               status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
-                                               CH_PWR_CTRL2, 1, 0x00, 1);
-       }
-
-       return status;
-}
-
-/* set i2s_blk for audio input types */
-int cx231xx_i2s_blk_set_audio_input(struct cx231xx *dev, u8 audio_input)
-{
-       int status = 0;
-
-       switch (audio_input) {
-       case CX231XX_AMUX_LINE_IN:
-               status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
-                                               CH_PWR_CTRL2, 1, 0x00, 1);
-               status = cx231xx_write_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
-                                               CH_PWR_CTRL1, 1, 0x80, 1);
-               break;
-       case CX231XX_AMUX_VIDEO:
-       default:
-               break;
-       }
-
-       dev->ctl_ainput = audio_input;
-
-       return status;
-}
-
-/******************************************************************************
- *                  P O W E R      C O N T R O L   functions                  *
- ******************************************************************************/
-int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode)
-{
-       u8 value[4] = { 0, 0, 0, 0 };
-       u32 tmp = 0;
-       int status = 0;
-
-       if (dev->power_mode != mode)
-               dev->power_mode = mode;
-       else {
-               cx231xx_info(" setPowerMode::mode = %d, No Change req.\n",
-                            mode);
-               return 0;
-       }
-
-       status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value,
-                                      4);
-       if (status < 0)
-               return status;
-
-       tmp = *((u32 *) value);
-
-       switch (mode) {
-       case POLARIS_AVMODE_ENXTERNAL_AV:
-
-               tmp &= (~PWR_MODE_MASK);
-
-               tmp |= PWR_AV_EN;
-               value[0] = (u8) tmp;
-               value[1] = (u8) (tmp >> 8);
-               value[2] = (u8) (tmp >> 16);
-               value[3] = (u8) (tmp >> 24);
-               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                               PWR_CTL_EN, value, 4);
-               msleep(PWR_SLEEP_INTERVAL);
-
-               tmp |= PWR_ISO_EN;
-               value[0] = (u8) tmp;
-               value[1] = (u8) (tmp >> 8);
-               value[2] = (u8) (tmp >> 16);
-               value[3] = (u8) (tmp >> 24);
-               status =
-                   cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN,
-                                          value, 4);
-               msleep(PWR_SLEEP_INTERVAL);
-
-               tmp |= POLARIS_AVMODE_ENXTERNAL_AV;
-               value[0] = (u8) tmp;
-               value[1] = (u8) (tmp >> 8);
-               value[2] = (u8) (tmp >> 16);
-               value[3] = (u8) (tmp >> 24);
-               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                               PWR_CTL_EN, value, 4);
-
-               /* reset state of xceive tuner */
-               dev->xc_fw_load_done = 0;
-               break;
-
-       case POLARIS_AVMODE_ANALOGT_TV:
-
-               tmp |= PWR_DEMOD_EN;
-               tmp |= (I2C_DEMOD_EN);
-               value[0] = (u8) tmp;
-               value[1] = (u8) (tmp >> 8);
-               value[2] = (u8) (tmp >> 16);
-               value[3] = (u8) (tmp >> 24);
-               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                               PWR_CTL_EN, value, 4);
-               msleep(PWR_SLEEP_INTERVAL);
-
-               if (!(tmp & PWR_TUNER_EN)) {
-                       tmp |= (PWR_TUNER_EN);
-                       value[0] = (u8) tmp;
-                       value[1] = (u8) (tmp >> 8);
-                       value[2] = (u8) (tmp >> 16);
-                       value[3] = (u8) (tmp >> 24);
-                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                                       PWR_CTL_EN, value, 4);
-                       msleep(PWR_SLEEP_INTERVAL);
-               }
-
-               if (!(tmp & PWR_AV_EN)) {
-                       tmp |= PWR_AV_EN;
-                       value[0] = (u8) tmp;
-                       value[1] = (u8) (tmp >> 8);
-                       value[2] = (u8) (tmp >> 16);
-                       value[3] = (u8) (tmp >> 24);
-                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                                       PWR_CTL_EN, value, 4);
-                       msleep(PWR_SLEEP_INTERVAL);
-               }
-               if (!(tmp & PWR_ISO_EN)) {
-                       tmp |= PWR_ISO_EN;
-                       value[0] = (u8) tmp;
-                       value[1] = (u8) (tmp >> 8);
-                       value[2] = (u8) (tmp >> 16);
-                       value[3] = (u8) (tmp >> 24);
-                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                                       PWR_CTL_EN, value, 4);
-                       msleep(PWR_SLEEP_INTERVAL);
-               }
-
-               if (!(tmp & POLARIS_AVMODE_ANALOGT_TV)) {
-                       tmp |= POLARIS_AVMODE_ANALOGT_TV;
-                       value[0] = (u8) tmp;
-                       value[1] = (u8) (tmp >> 8);
-                       value[2] = (u8) (tmp >> 16);
-                       value[3] = (u8) (tmp >> 24);
-                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                                       PWR_CTL_EN, value, 4);
-                       msleep(PWR_SLEEP_INTERVAL);
-               }
-
-               if (dev->board.tuner_type != TUNER_ABSENT) {
-                       /* Enable tuner */
-                       cx231xx_enable_i2c_port_3(dev, true);
-
-                       /* reset the Tuner */
-                       if (dev->board.tuner_gpio)
-                               cx231xx_gpio_set(dev, dev->board.tuner_gpio);
-
-                       if (dev->cx231xx_reset_analog_tuner)
-                               dev->cx231xx_reset_analog_tuner(dev);
-               }
-
-               break;
-
-       case POLARIS_AVMODE_DIGITAL:
-               if (!(tmp & PWR_TUNER_EN)) {
-                       tmp |= (PWR_TUNER_EN);
-                       value[0] = (u8) tmp;
-                       value[1] = (u8) (tmp >> 8);
-                       value[2] = (u8) (tmp >> 16);
-                       value[3] = (u8) (tmp >> 24);
-                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                                       PWR_CTL_EN, value, 4);
-                       msleep(PWR_SLEEP_INTERVAL);
-               }
-               if (!(tmp & PWR_AV_EN)) {
-                       tmp |= PWR_AV_EN;
-                       value[0] = (u8) tmp;
-                       value[1] = (u8) (tmp >> 8);
-                       value[2] = (u8) (tmp >> 16);
-                       value[3] = (u8) (tmp >> 24);
-                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                                       PWR_CTL_EN, value, 4);
-                       msleep(PWR_SLEEP_INTERVAL);
-               }
-               if (!(tmp & PWR_ISO_EN)) {
-                       tmp |= PWR_ISO_EN;
-                       value[0] = (u8) tmp;
-                       value[1] = (u8) (tmp >> 8);
-                       value[2] = (u8) (tmp >> 16);
-                       value[3] = (u8) (tmp >> 24);
-                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                                       PWR_CTL_EN, value, 4);
-                       msleep(PWR_SLEEP_INTERVAL);
-               }
-
-               tmp &= (~PWR_AV_MODE);
-               tmp |= POLARIS_AVMODE_DIGITAL | I2C_DEMOD_EN;
-               value[0] = (u8) tmp;
-               value[1] = (u8) (tmp >> 8);
-               value[2] = (u8) (tmp >> 16);
-               value[3] = (u8) (tmp >> 24);
-               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                               PWR_CTL_EN, value, 4);
-               msleep(PWR_SLEEP_INTERVAL);
-
-               if (!(tmp & PWR_DEMOD_EN)) {
-                       tmp |= PWR_DEMOD_EN;
-                       value[0] = (u8) tmp;
-                       value[1] = (u8) (tmp >> 8);
-                       value[2] = (u8) (tmp >> 16);
-                       value[3] = (u8) (tmp >> 24);
-                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                                       PWR_CTL_EN, value, 4);
-                       msleep(PWR_SLEEP_INTERVAL);
-               }
-
-               if (dev->board.tuner_type != TUNER_ABSENT) {
-                       /*
-                        * Enable tuner
-                        *      Hauppauge Exeter seems to need to do something different!
-                        */
-                       if (dev->model == CX231XX_BOARD_HAUPPAUGE_EXETER)
-                               cx231xx_enable_i2c_port_3(dev, false);
-                       else
-                               cx231xx_enable_i2c_port_3(dev, true);
-
-                       /* reset the Tuner */
-                       if (dev->board.tuner_gpio)
-                               cx231xx_gpio_set(dev, dev->board.tuner_gpio);
-
-                       if (dev->cx231xx_reset_analog_tuner)
-                               dev->cx231xx_reset_analog_tuner(dev);
-               }
-               break;
-
-       default:
-               break;
-       }
-
-       msleep(PWR_SLEEP_INTERVAL);
-
-       /* For power saving, only enable Pwr_resetout_n
-          when digital TV is selected. */
-       if (mode == POLARIS_AVMODE_DIGITAL) {
-               tmp |= PWR_RESETOUT_EN;
-               value[0] = (u8) tmp;
-               value[1] = (u8) (tmp >> 8);
-               value[2] = (u8) (tmp >> 16);
-               value[3] = (u8) (tmp >> 24);
-               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                               PWR_CTL_EN, value, 4);
-               msleep(PWR_SLEEP_INTERVAL);
-       }
-
-       /* update power control for afe */
-       status = cx231xx_afe_update_power_control(dev, mode);
-
-       /* update power control for i2s_blk */
-       status = cx231xx_i2s_blk_update_power_control(dev, mode);
-
-       status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value,
-                                      4);
-
-       return status;
-}
-
-int cx231xx_power_suspend(struct cx231xx *dev)
-{
-       u8 value[4] = { 0, 0, 0, 0 };
-       u32 tmp = 0;
-       int status = 0;
-
-       status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
-                                      value, 4);
-       if (status > 0)
-               return status;
-
-       tmp = *((u32 *) value);
-       tmp &= (~PWR_MODE_MASK);
-
-       value[0] = (u8) tmp;
-       value[1] = (u8) (tmp >> 8);
-       value[2] = (u8) (tmp >> 16);
-       value[3] = (u8) (tmp >> 24);
-       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, PWR_CTL_EN,
-                                       value, 4);
-
-       return status;
-}
-
-/******************************************************************************
- *                  S T R E A M    C O N T R O L   functions                  *
- ******************************************************************************/
-int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask)
-{
-       u8 value[4] = { 0x0, 0x0, 0x0, 0x0 };
-       u32 tmp = 0;
-       int status = 0;
-
-       cx231xx_info("cx231xx_start_stream():: ep_mask = %x\n", ep_mask);
-       status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET,
-                                      value, 4);
-       if (status < 0)
-               return status;
-
-       tmp = *((u32 *) value);
-       tmp |= ep_mask;
-       value[0] = (u8) tmp;
-       value[1] = (u8) (tmp >> 8);
-       value[2] = (u8) (tmp >> 16);
-       value[3] = (u8) (tmp >> 24);
-
-       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, EP_MODE_SET,
-                                       value, 4);
-
-       return status;
-}
-
-int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask)
-{
-       u8 value[4] = { 0x0, 0x0, 0x0, 0x0 };
-       u32 tmp = 0;
-       int status = 0;
-
-       cx231xx_info("cx231xx_stop_stream():: ep_mask = %x\n", ep_mask);
-       status =
-           cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET, value, 4);
-       if (status < 0)
-               return status;
-
-       tmp = *((u32 *) value);
-       tmp &= (~ep_mask);
-       value[0] = (u8) tmp;
-       value[1] = (u8) (tmp >> 8);
-       value[2] = (u8) (tmp >> 16);
-       value[3] = (u8) (tmp >> 24);
-
-       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, EP_MODE_SET,
-                                       value, 4);
-
-       return status;
-}
-
-int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type)
-{
-       int status = 0;
-       u32 value = 0;
-       u8 val[4] = { 0, 0, 0, 0 };
-
-       if (dev->udev->speed == USB_SPEED_HIGH) {
-               switch (media_type) {
-               case Audio:
-                       cx231xx_info("%s: Audio enter HANC\n", __func__);
-                       status =
-                           cx231xx_mode_register(dev, TS_MODE_REG, 0x9300);
-                       break;
-
-               case Vbi:
-                       cx231xx_info("%s: set vanc registers\n", __func__);
-                       status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300);
-                       break;
-
-               case Sliced_cc:
-                       cx231xx_info("%s: set hanc registers\n", __func__);
-                       status =
-                           cx231xx_mode_register(dev, TS_MODE_REG, 0x1300);
-                       break;
-
-               case Raw_Video:
-                       cx231xx_info("%s: set video registers\n", __func__);
-                       status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
-                       break;
-
-               case TS1_serial_mode:
-                       cx231xx_info("%s: set ts1 registers", __func__);
-
-               if (dev->board.has_417) {
-                       cx231xx_info(" MPEG\n");
-                       value &= 0xFFFFFFFC;
-                       value |= 0x3;
-
-                       status = cx231xx_mode_register(dev, TS_MODE_REG, value);
-
-                       val[0] = 0x04;
-                       val[1] = 0xA3;
-                       val[2] = 0x3B;
-                       val[3] = 0x00;
-                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                TS1_CFG_REG, val, 4);
-
-                       val[0] = 0x00;
-                       val[1] = 0x08;
-                       val[2] = 0x00;
-                       val[3] = 0x08;
-                       status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                TS1_LENGTH_REG, val, 4);
-
-               } else {
-                       cx231xx_info(" BDA\n");
-                       status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101);
-                       status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x010);
-               }
-                       break;
-
-               case TS1_parallel_mode:
-                       cx231xx_info("%s: set ts1 parallel mode registers\n",
-                                    __func__);
-                       status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
-                       status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400);
-                       break;
-               }
-       } else {
-               status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101);
-       }
-
-       return status;
-}
-
-int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type)
-{
-       int rc = -1;
-       u32 ep_mask = -1;
-       struct pcb_config *pcb_config;
-
-       /* get EP for media type */
-       pcb_config = (struct pcb_config *)&dev->current_pcb_config;
-
-       if (pcb_config->config_num) {
-               switch (media_type) {
-               case Raw_Video:
-                       ep_mask = ENABLE_EP4;   /* ep4  [00:1000] */
-                       break;
-               case Audio:
-                       ep_mask = ENABLE_EP3;   /* ep3  [00:0100] */
-                       break;
-               case Vbi:
-                       ep_mask = ENABLE_EP5;   /* ep5 [01:0000] */
-                       break;
-               case Sliced_cc:
-                       ep_mask = ENABLE_EP6;   /* ep6 [10:0000] */
-                       break;
-               case TS1_serial_mode:
-               case TS1_parallel_mode:
-                       ep_mask = ENABLE_EP1;   /* ep1 [00:0001] */
-                       break;
-               case TS2:
-                       ep_mask = ENABLE_EP2;   /* ep2 [00:0010] */
-                       break;
-               }
-       }
-
-       if (start) {
-               rc = cx231xx_initialize_stream_xfer(dev, media_type);
-
-               if (rc < 0)
-                       return rc;
-
-               /* enable video capture */
-               if (ep_mask > 0)
-                       rc = cx231xx_start_stream(dev, ep_mask);
-       } else {
-               /* disable video capture */
-               if (ep_mask > 0)
-                       rc = cx231xx_stop_stream(dev, ep_mask);
-       }
-
-       if (dev->mode == CX231XX_ANALOG_MODE)
-               ;/* do any in Analog mode */
-       else
-               ;/* do any in digital mode */
-
-       return rc;
-}
-EXPORT_SYMBOL_GPL(cx231xx_capture_start);
-
-/*****************************************************************************
-*                   G P I O   B I T control functions                        *
-******************************************************************************/
-int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val)
-{
-       int status = 0;
-
-       status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 0);
-
-       return status;
-}
-
-int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val)
-{
-       int status = 0;
-
-       status = cx231xx_send_gpio_cmd(dev, gpio_bit, gpio_val, 4, 0, 1);
-
-       return status;
-}
-
-/*
-* cx231xx_set_gpio_direction
-*      Sets the direction of the GPIO pin to input or output
-*
-* Parameters :
-*      pin_number : The GPIO Pin number to program the direction for
-*                   from 0 to 31
-*      pin_value : The Direction of the GPIO Pin under reference.
-*                      0 = Input direction
-*                      1 = Output direction
-*/
-int cx231xx_set_gpio_direction(struct cx231xx *dev,
-                              int pin_number, int pin_value)
-{
-       int status = 0;
-       u32 value = 0;
-
-       /* Check for valid pin_number - if 32 , bail out */
-       if (pin_number >= 32)
-               return -EINVAL;
-
-       /* input */
-       if (pin_value == 0)
-               value = dev->gpio_dir & (~(1 << pin_number));   /* clear */
-       else
-               value = dev->gpio_dir | (1 << pin_number);
-
-       status = cx231xx_set_gpio_bit(dev, value, (u8 *) &dev->gpio_val);
-
-       /* cache the value for future */
-       dev->gpio_dir = value;
-
-       return status;
-}
-
-/*
-* cx231xx_set_gpio_value
-*      Sets the value of the GPIO pin to Logic high or low. The Pin under
-*      reference should ALREADY BE SET IN OUTPUT MODE !!!!!!!!!
-*
-* Parameters :
-*      pin_number : The GPIO Pin number to program the direction for
-*      pin_value : The value of the GPIO Pin under reference.
-*                      0 = set it to 0
-*                      1 = set it to 1
-*/
-int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value)
-{
-       int status = 0;
-       u32 value = 0;
-
-       /* Check for valid pin_number - if 0xFF , bail out */
-       if (pin_number >= 32)
-               return -EINVAL;
-
-       /* first do a sanity check - if the Pin is not output, make it output */
-       if ((dev->gpio_dir & (1 << pin_number)) == 0x00) {
-               /* It was in input mode */
-               value = dev->gpio_dir | (1 << pin_number);
-               dev->gpio_dir = value;
-               status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-                                             (u8 *) &dev->gpio_val);
-               value = 0;
-       }
-
-       if (pin_value == 0)
-               value = dev->gpio_val & (~(1 << pin_number));
-       else
-               value = dev->gpio_val | (1 << pin_number);
-
-       /* store the value */
-       dev->gpio_val = value;
-
-       /* toggle bit0 of GP_IO */
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-
-       return status;
-}
-
-/*****************************************************************************
-*                      G P I O I2C related functions                         *
-******************************************************************************/
-int cx231xx_gpio_i2c_start(struct cx231xx *dev)
-{
-       int status = 0;
-
-       /* set SCL to output 1 ; set SDA to output 1 */
-       dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio;
-       dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio;
-       dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
-       dev->gpio_val |= 1 << dev->board.tuner_sda_gpio;
-
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-       if (status < 0)
-               return -EINVAL;
-
-       /* set SCL to output 1; set SDA to output 0 */
-       dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
-       dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
-
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-       if (status < 0)
-               return -EINVAL;
-
-       /* set SCL to output 0; set SDA to output 0      */
-       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-       dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
-
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-       if (status < 0)
-               return -EINVAL;
-
-       return status;
-}
-
-int cx231xx_gpio_i2c_end(struct cx231xx *dev)
-{
-       int status = 0;
-
-       /* set SCL to output 0; set SDA to output 0      */
-       dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio;
-       dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio;
-
-       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-       dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
-
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-       if (status < 0)
-               return -EINVAL;
-
-       /* set SCL to output 1; set SDA to output 0      */
-       dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
-       dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
-
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-       if (status < 0)
-               return -EINVAL;
-
-       /* set SCL to input ,release SCL cable control
-          set SDA to input ,release SDA cable control */
-       dev->gpio_dir &= ~(1 << dev->board.tuner_scl_gpio);
-       dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio);
-
-       status =
-           cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-       if (status < 0)
-               return -EINVAL;
-
-       return status;
-}
-
-int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data)
-{
-       int status = 0;
-       u8 i;
-
-       /* set SCL to output ; set SDA to output */
-       dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio;
-       dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio;
-
-       for (i = 0; i < 8; i++) {
-               if (((data << i) & 0x80) == 0) {
-                       /* set SCL to output 0; set SDA to output 0     */
-                       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-                       dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
-                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-                                                     (u8 *)&dev->gpio_val);
-
-                       /* set SCL to output 1; set SDA to output 0     */
-                       dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
-                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-                                                     (u8 *)&dev->gpio_val);
-
-                       /* set SCL to output 0; set SDA to output 0     */
-                       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-                                                     (u8 *)&dev->gpio_val);
-               } else {
-                       /* set SCL to output 0; set SDA to output 1     */
-                       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-                       dev->gpio_val |= 1 << dev->board.tuner_sda_gpio;
-                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-                                                     (u8 *)&dev->gpio_val);
-
-                       /* set SCL to output 1; set SDA to output 1     */
-                       dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
-                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-                                                     (u8 *)&dev->gpio_val);
-
-                       /* set SCL to output 0; set SDA to output 1     */
-                       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-                       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-                                                     (u8 *)&dev->gpio_val);
-               }
-       }
-       return status;
-}
-
-int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf)
-{
-       u8 value = 0;
-       int status = 0;
-       u32 gpio_logic_value = 0;
-       u8 i;
-
-       /* read byte */
-       for (i = 0; i < 8; i++) {       /* send write I2c addr */
-
-               /* set SCL to output 0; set SDA to input */
-               dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-               status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-                                             (u8 *)&dev->gpio_val);
-
-               /* set SCL to output 1; set SDA to input */
-               dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
-               status = cx231xx_set_gpio_bit(dev, dev->gpio_dir,
-                                             (u8 *)&dev->gpio_val);
-
-               /* get SDA data bit */
-               gpio_logic_value = dev->gpio_val;
-               status = cx231xx_get_gpio_bit(dev, dev->gpio_dir,
-                                             (u8 *)&dev->gpio_val);
-               if ((dev->gpio_val & (1 << dev->board.tuner_sda_gpio)) != 0)
-                       value |= (1 << (8 - i - 1));
-
-               dev->gpio_val = gpio_logic_value;
-       }
-
-       /* set SCL to output 0,finish the read latest SCL signal.
-          !!!set SDA to input, never to modify SDA direction at
-          the same times */
-       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-
-       /* store the value */
-       *buf = value & 0xff;
-
-       return status;
-}
-
-int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev)
-{
-       int status = 0;
-       u32 gpio_logic_value = 0;
-       int nCnt = 10;
-       int nInit = nCnt;
-
-       /* clock stretch; set SCL to input; set SDA to input;
-          get SCL value till SCL = 1 */
-       dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio);
-       dev->gpio_dir &= ~(1 << dev->board.tuner_scl_gpio);
-
-       gpio_logic_value = dev->gpio_val;
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-
-       do {
-               msleep(2);
-               status = cx231xx_get_gpio_bit(dev, dev->gpio_dir,
-                                             (u8 *)&dev->gpio_val);
-               nCnt--;
-       } while (((dev->gpio_val &
-                         (1 << dev->board.tuner_scl_gpio)) == 0) &&
-                        (nCnt > 0));
-
-       if (nCnt == 0)
-               cx231xx_info("No ACK after %d msec -GPIO I2C failed!",
-                            nInit * 10);
-
-       /*
-        * readAck
-        * through clock stretch, slave has given a SCL signal,
-        * so the SDA data can be directly read.
-        */
-       status = cx231xx_get_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-
-       if ((dev->gpio_val & 1 << dev->board.tuner_sda_gpio) == 0) {
-               dev->gpio_val = gpio_logic_value;
-               dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
-               status = 0;
-       } else {
-               dev->gpio_val = gpio_logic_value;
-               dev->gpio_val |= (1 << dev->board.tuner_sda_gpio);
-       }
-
-       /* read SDA end, set the SCL to output 0, after this operation,
-          SDA direction can be changed. */
-       dev->gpio_val = gpio_logic_value;
-       dev->gpio_dir |= (1 << dev->board.tuner_scl_gpio);
-       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-
-       return status;
-}
-
-int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev)
-{
-       int status = 0;
-
-       /* set SDA to ouput */
-       dev->gpio_dir |= 1 << dev->board.tuner_sda_gpio;
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-
-       /* set SCL = 0 (output); set SDA = 0 (output) */
-       dev->gpio_val &= ~(1 << dev->board.tuner_sda_gpio);
-       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-
-       /* set SCL = 1 (output); set SDA = 0 (output) */
-       dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-
-       /* set SCL = 0 (output); set SDA = 0 (output) */
-       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-
-       /* set SDA to input,and then the slave will read data from SDA. */
-       dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio);
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-
-       return status;
-}
-
-int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev)
-{
-       int status = 0;
-
-       /* set scl to output ; set sda to input */
-       dev->gpio_dir |= 1 << dev->board.tuner_scl_gpio;
-       dev->gpio_dir &= ~(1 << dev->board.tuner_sda_gpio);
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-
-       /* set scl to output 0; set sda to input */
-       dev->gpio_val &= ~(1 << dev->board.tuner_scl_gpio);
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-
-       /* set scl to output 1; set sda to input */
-       dev->gpio_val |= 1 << dev->board.tuner_scl_gpio;
-       status = cx231xx_set_gpio_bit(dev, dev->gpio_dir, (u8 *)&dev->gpio_val);
-
-       return status;
-}
-
-/*****************************************************************************
-*                      G P I O I2C related functions                         *
-******************************************************************************/
-/* cx231xx_gpio_i2c_read
- * Function to read data from gpio based I2C interface
- */
-int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len)
-{
-       int status = 0;
-       int i = 0;
-
-       /* get the lock */
-       mutex_lock(&dev->gpio_i2c_lock);
-
-       /* start */
-       status = cx231xx_gpio_i2c_start(dev);
-
-       /* write dev_addr */
-       status = cx231xx_gpio_i2c_write_byte(dev, (dev_addr << 1) + 1);
-
-       /* readAck */
-       status = cx231xx_gpio_i2c_read_ack(dev);
-
-       /* read data */
-       for (i = 0; i < len; i++) {
-               /* read data */
-               buf[i] = 0;
-               status = cx231xx_gpio_i2c_read_byte(dev, &buf[i]);
-
-               if ((i + 1) != len) {
-                       /* only do write ack if we more length */
-                       status = cx231xx_gpio_i2c_write_ack(dev);
-               }
-       }
-
-       /* write NAK - inform reads are complete */
-       status = cx231xx_gpio_i2c_write_nak(dev);
-
-       /* write end */
-       status = cx231xx_gpio_i2c_end(dev);
-
-       /* release the lock */
-       mutex_unlock(&dev->gpio_i2c_lock);
-
-       return status;
-}
-
-/* cx231xx_gpio_i2c_write
- * Function to write data to gpio based I2C interface
- */
-int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len)
-{
-       int i = 0;
-
-       /* get the lock */
-       mutex_lock(&dev->gpio_i2c_lock);
-
-       /* start */
-       cx231xx_gpio_i2c_start(dev);
-
-       /* write dev_addr */
-       cx231xx_gpio_i2c_write_byte(dev, dev_addr << 1);
-
-       /* read Ack */
-       cx231xx_gpio_i2c_read_ack(dev);
-
-       for (i = 0; i < len; i++) {
-               /* Write data */
-               cx231xx_gpio_i2c_write_byte(dev, buf[i]);
-
-               /* read Ack */
-               cx231xx_gpio_i2c_read_ack(dev);
-       }
-
-       /* write End */
-       cx231xx_gpio_i2c_end(dev);
-
-       /* release the lock */
-       mutex_unlock(&dev->gpio_i2c_lock);
-
-       return 0;
-}
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c
deleted file mode 100644 (file)
index 02d4d36..0000000
+++ /dev/null
@@ -1,1370 +0,0 @@
-/*
-   cx231xx-cards.c - driver for Conexant Cx23100/101/102
-                               USB video capture devices
-
-   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
-                               Based on em28xx driver
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   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/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/usb.h>
-#include <media/tuner.h>
-#include <media/tveeprom.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-chip-ident.h>
-
-#include <media/cx25840.h>
-#include "dvb-usb-ids.h"
-#include "xc5000.h"
-#include "tda18271.h"
-
-#include "cx231xx.h"
-
-static int tuner = -1;
-module_param(tuner, int, 0444);
-MODULE_PARM_DESC(tuner, "tuner type");
-
-static int transfer_mode = 1;
-module_param(transfer_mode, int, 0444);
-MODULE_PARM_DESC(transfer_mode, "transfer mode (1-ISO or 0-BULK)");
-
-static unsigned int disable_ir;
-module_param(disable_ir, int, 0444);
-MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
-
-/* Bitmask marking allocated devices from 0 to CX231XX_MAXBOARDS */
-static unsigned long cx231xx_devused;
-
-/*
- *  Reset sequences for analog/digital modes
- */
-
-static struct cx231xx_reg_seq RDE250_XCV_TUNER[] = {
-       {0x03, 0x01, 10},
-       {0x03, 0x00, 30},
-       {0x03, 0x01, 10},
-       {-1, -1, -1},
-};
-
-/*
- *  Board definitions
- */
-struct cx231xx_board cx231xx_boards[] = {
-       [CX231XX_BOARD_UNKNOWN] = {
-               .name = "Unknown CX231xx video grabber",
-               .tuner_type = TUNER_ABSENT,
-               .input = {{
-                               .type = CX231XX_VMUX_TELEVISION,
-                               .vmux = CX231XX_VIN_3_1,
-                               .amux = CX231XX_AMUX_VIDEO,
-                               .gpio = NULL,
-                       }, {
-                               .type = CX231XX_VMUX_COMPOSITE1,
-                               .vmux = CX231XX_VIN_2_1,
-                               .amux = CX231XX_AMUX_LINE_IN,
-                               .gpio = NULL,
-                       }, {
-                               .type = CX231XX_VMUX_SVIDEO,
-                               .vmux = CX231XX_VIN_1_1 |
-                                       (CX231XX_VIN_1_2 << 8) |
-                                       CX25840_SVIDEO_ON,
-                               .amux = CX231XX_AMUX_LINE_IN,
-                               .gpio = NULL,
-                       }
-               },
-       },
-       [CX231XX_BOARD_CNXT_CARRAERA] = {
-               .name = "Conexant Hybrid TV - CARRAERA",
-               .tuner_type = TUNER_XC5000,
-               .tuner_addr = 0x61,
-               .tuner_gpio = RDE250_XCV_TUNER,
-               .tuner_sif_gpio = 0x05,
-               .tuner_scl_gpio = 0x1a,
-               .tuner_sda_gpio = 0x1b,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .demod_xfer_mode = 0,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x0c,
-               .gpio_pin_status_mask = 0x4001000,
-               .tuner_i2c_master = 1,
-               .demod_i2c_master = 2,
-               .has_dvb = 1,
-               .demod_addr = 0x02,
-               .norm = V4L2_STD_PAL,
-
-               .input = {{
-                               .type = CX231XX_VMUX_TELEVISION,
-                               .vmux = CX231XX_VIN_3_1,
-                               .amux = CX231XX_AMUX_VIDEO,
-                               .gpio = NULL,
-                       }, {
-                               .type = CX231XX_VMUX_COMPOSITE1,
-                               .vmux = CX231XX_VIN_2_1,
-                               .amux = CX231XX_AMUX_LINE_IN,
-                               .gpio = NULL,
-                       }, {
-                               .type = CX231XX_VMUX_SVIDEO,
-                               .vmux = CX231XX_VIN_1_1 |
-                                       (CX231XX_VIN_1_2 << 8) |
-                                       CX25840_SVIDEO_ON,
-                               .amux = CX231XX_AMUX_LINE_IN,
-                               .gpio = NULL,
-                       }
-               },
-       },
-       [CX231XX_BOARD_CNXT_SHELBY] = {
-               .name = "Conexant Hybrid TV - SHELBY",
-               .tuner_type = TUNER_XC5000,
-               .tuner_addr = 0x61,
-               .tuner_gpio = RDE250_XCV_TUNER,
-               .tuner_sif_gpio = 0x05,
-               .tuner_scl_gpio = 0x1a,
-               .tuner_sda_gpio = 0x1b,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .demod_xfer_mode = 0,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x0c,
-               .gpio_pin_status_mask = 0x4001000,
-               .tuner_i2c_master = 1,
-               .demod_i2c_master = 2,
-               .has_dvb = 1,
-               .demod_addr = 0x32,
-               .norm = V4L2_STD_NTSC,
-
-               .input = {{
-                               .type = CX231XX_VMUX_TELEVISION,
-                               .vmux = CX231XX_VIN_3_1,
-                               .amux = CX231XX_AMUX_VIDEO,
-                               .gpio = NULL,
-                       }, {
-                               .type = CX231XX_VMUX_COMPOSITE1,
-                               .vmux = CX231XX_VIN_2_1,
-                               .amux = CX231XX_AMUX_LINE_IN,
-                               .gpio = NULL,
-                       }, {
-                               .type = CX231XX_VMUX_SVIDEO,
-                               .vmux = CX231XX_VIN_1_1 |
-                                       (CX231XX_VIN_1_2 << 8) |
-                                       CX25840_SVIDEO_ON,
-                               .amux = CX231XX_AMUX_LINE_IN,
-                               .gpio = NULL,
-                       }
-               },
-       },
-       [CX231XX_BOARD_CNXT_RDE_253S] = {
-               .name = "Conexant Hybrid TV - RDE253S",
-               .tuner_type = TUNER_NXP_TDA18271,
-               .tuner_addr = 0x60,
-               .tuner_gpio = RDE250_XCV_TUNER,
-               .tuner_sif_gpio = 0x05,
-               .tuner_scl_gpio = 0x1a,
-               .tuner_sda_gpio = 0x1b,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .demod_xfer_mode = 0,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x1c,
-               .gpio_pin_status_mask = 0x4001000,
-               .tuner_i2c_master = 1,
-               .demod_i2c_master = 2,
-               .has_dvb = 1,
-               .demod_addr = 0x02,
-               .norm = V4L2_STD_PAL,
-
-               .input = {{
-                               .type = CX231XX_VMUX_TELEVISION,
-                               .vmux = CX231XX_VIN_3_1,
-                               .amux = CX231XX_AMUX_VIDEO,
-                               .gpio = NULL,
-                       }, {
-                               .type = CX231XX_VMUX_COMPOSITE1,
-                               .vmux = CX231XX_VIN_2_1,
-                               .amux = CX231XX_AMUX_LINE_IN,
-                               .gpio = NULL,
-                       }, {
-                               .type = CX231XX_VMUX_SVIDEO,
-                               .vmux = CX231XX_VIN_1_1 |
-                                       (CX231XX_VIN_1_2 << 8) |
-                                       CX25840_SVIDEO_ON,
-                               .amux = CX231XX_AMUX_LINE_IN,
-                               .gpio = NULL,
-                       }
-               },
-       },
-
-       [CX231XX_BOARD_CNXT_RDU_253S] = {
-               .name = "Conexant Hybrid TV - RDU253S",
-               .tuner_type = TUNER_NXP_TDA18271,
-               .tuner_addr = 0x60,
-               .tuner_gpio = RDE250_XCV_TUNER,
-               .tuner_sif_gpio = 0x05,
-               .tuner_scl_gpio = 0x1a,
-               .tuner_sda_gpio = 0x1b,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .demod_xfer_mode = 0,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x1c,
-               .gpio_pin_status_mask = 0x4001000,
-               .tuner_i2c_master = 1,
-               .demod_i2c_master = 2,
-               .has_dvb = 1,
-               .demod_addr = 0x02,
-               .norm = V4L2_STD_PAL,
-
-               .input = {{
-                               .type = CX231XX_VMUX_TELEVISION,
-                               .vmux = CX231XX_VIN_3_1,
-                               .amux = CX231XX_AMUX_VIDEO,
-                               .gpio = NULL,
-                       }, {
-                               .type = CX231XX_VMUX_COMPOSITE1,
-                               .vmux = CX231XX_VIN_2_1,
-                               .amux = CX231XX_AMUX_LINE_IN,
-                               .gpio = NULL,
-                       }, {
-                               .type = CX231XX_VMUX_SVIDEO,
-                               .vmux = CX231XX_VIN_1_1 |
-                                       (CX231XX_VIN_1_2 << 8) |
-                                       CX25840_SVIDEO_ON,
-                               .amux = CX231XX_AMUX_LINE_IN,
-                               .gpio = NULL,
-                       }
-               },
-       },
-       [CX231XX_BOARD_CNXT_VIDEO_GRABBER] = {
-               .name = "Conexant VIDEO GRABBER",
-               .tuner_type = TUNER_ABSENT,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x1c,
-               .gpio_pin_status_mask = 0x4001000,
-               .norm = V4L2_STD_PAL,
-               .no_alt_vanc = 1,
-               .external_av = 1,
-               .has_417 = 1,
-
-               .input = {{
-                               .type = CX231XX_VMUX_COMPOSITE1,
-                               .vmux = CX231XX_VIN_2_1,
-                               .amux = CX231XX_AMUX_LINE_IN,
-                               .gpio = NULL,
-                       }, {
-                               .type = CX231XX_VMUX_SVIDEO,
-                               .vmux = CX231XX_VIN_1_1 |
-                                       (CX231XX_VIN_1_2 << 8) |
-                                       CX25840_SVIDEO_ON,
-                               .amux = CX231XX_AMUX_LINE_IN,
-                               .gpio = NULL,
-                       }
-               },
-       },
-       [CX231XX_BOARD_CNXT_RDE_250] = {
-               .name = "Conexant Hybrid TV - rde 250",
-               .tuner_type = TUNER_XC5000,
-               .tuner_addr = 0x61,
-               .tuner_gpio = RDE250_XCV_TUNER,
-               .tuner_sif_gpio = 0x05,
-               .tuner_scl_gpio = 0x1a,
-               .tuner_sda_gpio = 0x1b,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .demod_xfer_mode = 0,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x0c,
-               .gpio_pin_status_mask = 0x4001000,
-               .tuner_i2c_master = 1,
-               .demod_i2c_master = 2,
-               .has_dvb = 1,
-               .demod_addr = 0x02,
-               .norm = V4L2_STD_PAL,
-
-               .input = {{
-                               .type = CX231XX_VMUX_TELEVISION,
-                               .vmux = CX231XX_VIN_2_1,
-                               .amux = CX231XX_AMUX_VIDEO,
-                               .gpio = NULL,
-                       }
-               },
-       },
-       [CX231XX_BOARD_CNXT_RDU_250] = {
-               .name = "Conexant Hybrid TV - RDU 250",
-               .tuner_type = TUNER_XC5000,
-               .tuner_addr = 0x61,
-               .tuner_gpio = RDE250_XCV_TUNER,
-               .tuner_sif_gpio = 0x05,
-               .tuner_scl_gpio = 0x1a,
-               .tuner_sda_gpio = 0x1b,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .demod_xfer_mode = 0,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x0c,
-               .gpio_pin_status_mask = 0x4001000,
-               .tuner_i2c_master = 1,
-               .demod_i2c_master = 2,
-               .has_dvb = 1,
-               .demod_addr = 0x32,
-               .norm = V4L2_STD_NTSC,
-
-               .input = {{
-                               .type = CX231XX_VMUX_TELEVISION,
-                               .vmux = CX231XX_VIN_2_1,
-                               .amux = CX231XX_AMUX_VIDEO,
-                               .gpio = NULL,
-                       }
-               },
-       },
-       [CX231XX_BOARD_HAUPPAUGE_EXETER] = {
-               .name = "Hauppauge EXETER",
-               .tuner_type = TUNER_NXP_TDA18271,
-               .tuner_addr = 0x60,
-               .tuner_gpio = RDE250_XCV_TUNER,
-               .tuner_sif_gpio = 0x05,
-               .tuner_scl_gpio = 0x1a,
-               .tuner_sda_gpio = 0x1b,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .demod_xfer_mode = 0,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x0c,
-               .gpio_pin_status_mask = 0x4001000,
-               .tuner_i2c_master = 1,
-               .demod_i2c_master = 2,
-               .has_dvb = 1,
-               .demod_addr = 0x0e,
-               .norm = V4L2_STD_NTSC,
-
-               .input = {{
-                       .type = CX231XX_VMUX_TELEVISION,
-                       .vmux = CX231XX_VIN_3_1,
-                       .amux = CX231XX_AMUX_VIDEO,
-                       .gpio = NULL,
-               }, {
-                       .type = CX231XX_VMUX_COMPOSITE1,
-                       .vmux = CX231XX_VIN_2_1,
-                       .amux = CX231XX_AMUX_LINE_IN,
-                       .gpio = NULL,
-               }, {
-                       .type = CX231XX_VMUX_SVIDEO,
-                       .vmux = CX231XX_VIN_1_1 |
-                               (CX231XX_VIN_1_2 << 8) |
-                               CX25840_SVIDEO_ON,
-                       .amux = CX231XX_AMUX_LINE_IN,
-                       .gpio = NULL,
-               } },
-       },
-       [CX231XX_BOARD_HAUPPAUGE_USBLIVE2] = {
-               .name = "Hauppauge USB Live 2",
-               .tuner_type = TUNER_ABSENT,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .demod_xfer_mode = 0,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x0c,
-               .gpio_pin_status_mask = 0x4001000,
-               .norm = V4L2_STD_NTSC,
-               .no_alt_vanc = 1,
-               .external_av = 1,
-               .dont_use_port_3 = 1,
-               .input = {{
-                       .type = CX231XX_VMUX_COMPOSITE1,
-                       .vmux = CX231XX_VIN_2_1,
-                       .amux = CX231XX_AMUX_LINE_IN,
-                       .gpio = NULL,
-               }, {
-                       .type = CX231XX_VMUX_SVIDEO,
-                       .vmux = CX231XX_VIN_1_1 |
-                               (CX231XX_VIN_1_2 << 8) |
-                               CX25840_SVIDEO_ON,
-                       .amux = CX231XX_AMUX_LINE_IN,
-                       .gpio = NULL,
-               } },
-       },
-       [CX231XX_BOARD_KWORLD_UB430_USB_HYBRID] = {
-               .name = "Kworld UB430 USB Hybrid",
-               .tuner_type = TUNER_NXP_TDA18271,
-               .tuner_addr = 0x60,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .demod_xfer_mode = 0,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x11, /* According with PV cxPolaris.inf file */
-               .tuner_sif_gpio = -1,
-               .tuner_scl_gpio = -1,
-               .tuner_sda_gpio = -1,
-               .gpio_pin_status_mask = 0x4001000,
-               .tuner_i2c_master = 2,
-               .demod_i2c_master = 1,
-               .ir_i2c_master = 2,
-               .has_dvb = 1,
-               .demod_addr = 0x10,
-               .norm = V4L2_STD_PAL_M,
-               .input = {{
-                       .type = CX231XX_VMUX_TELEVISION,
-                       .vmux = CX231XX_VIN_3_1,
-                       .amux = CX231XX_AMUX_VIDEO,
-                       .gpio = NULL,
-               }, {
-                       .type = CX231XX_VMUX_COMPOSITE1,
-                       .vmux = CX231XX_VIN_2_1,
-                       .amux = CX231XX_AMUX_LINE_IN,
-                       .gpio = NULL,
-               }, {
-                       .type = CX231XX_VMUX_SVIDEO,
-                       .vmux = CX231XX_VIN_1_1 |
-                               (CX231XX_VIN_1_2 << 8) |
-                               CX25840_SVIDEO_ON,
-                       .amux = CX231XX_AMUX_LINE_IN,
-                       .gpio = NULL,
-               } },
-       },
-       [CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = {
-               .name = "Pixelview PlayTV USB Hybrid",
-               .tuner_type = TUNER_NXP_TDA18271,
-               .tuner_addr = 0x60,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .demod_xfer_mode = 0,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x00, /* According with PV cxPolaris.inf file */
-               .tuner_sif_gpio = -1,
-               .tuner_scl_gpio = -1,
-               .tuner_sda_gpio = -1,
-               .gpio_pin_status_mask = 0x4001000,
-               .tuner_i2c_master = 2,
-               .demod_i2c_master = 1,
-               .ir_i2c_master = 2,
-               .rc_map_name = RC_MAP_PIXELVIEW_002T,
-               .has_dvb = 1,
-               .demod_addr = 0x10,
-               .norm = V4L2_STD_PAL_M,
-               .input = {{
-                       .type = CX231XX_VMUX_TELEVISION,
-                       .vmux = CX231XX_VIN_3_1,
-                       .amux = CX231XX_AMUX_VIDEO,
-                       .gpio = NULL,
-               }, {
-                       .type = CX231XX_VMUX_COMPOSITE1,
-                       .vmux = CX231XX_VIN_2_1,
-                       .amux = CX231XX_AMUX_LINE_IN,
-                       .gpio = NULL,
-               }, {
-                       .type = CX231XX_VMUX_SVIDEO,
-                       .vmux = CX231XX_VIN_1_1 |
-                               (CX231XX_VIN_1_2 << 8) |
-                               CX25840_SVIDEO_ON,
-                       .amux = CX231XX_AMUX_LINE_IN,
-                       .gpio = NULL,
-               } },
-       },
-       [CX231XX_BOARD_PV_XCAPTURE_USB] = {
-               .name = "Pixelview Xcapture USB",
-               .tuner_type = TUNER_ABSENT,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .demod_xfer_mode = 0,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x0c,
-               .gpio_pin_status_mask = 0x4001000,
-               .norm = V4L2_STD_NTSC,
-               .no_alt_vanc = 1,
-               .external_av = 1,
-               .dont_use_port_3 = 1,
-
-               .input = {{
-                               .type = CX231XX_VMUX_COMPOSITE1,
-                               .vmux = CX231XX_VIN_2_1,
-                               .amux = CX231XX_AMUX_LINE_IN,
-                               .gpio = NULL,
-                       }, {
-                               .type = CX231XX_VMUX_SVIDEO,
-                               .vmux = CX231XX_VIN_1_1 |
-                                       (CX231XX_VIN_1_2 << 8) |
-                                       CX25840_SVIDEO_ON,
-                               .amux = CX231XX_AMUX_LINE_IN,
-                               .gpio = NULL,
-                       }
-               },
-       },
-
-       [CX231XX_BOARD_ICONBIT_U100] = {
-               .name = "Iconbit Analog Stick U100 FM",
-               .tuner_type = TUNER_ABSENT,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .demod_xfer_mode = 0,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x1C,
-               .gpio_pin_status_mask = 0x4001000,
-
-               .input = {{
-                       .type = CX231XX_VMUX_COMPOSITE1,
-                       .vmux = CX231XX_VIN_2_1,
-                       .amux = CX231XX_AMUX_LINE_IN,
-                       .gpio = NULL,
-               }, {
-                       .type = CX231XX_VMUX_SVIDEO,
-                       .vmux = CX231XX_VIN_1_1 |
-                               (CX231XX_VIN_1_2 << 8) |
-                               CX25840_SVIDEO_ON,
-                       .amux = CX231XX_AMUX_LINE_IN,
-                       .gpio = NULL,
-               } },
-       },
-       [CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL] = {
-               .name = "Hauppauge WinTV USB2 FM (PAL)",
-               .tuner_type = TUNER_NXP_TDA18271,
-               .tuner_addr = 0x60,
-               .tuner_gpio = RDE250_XCV_TUNER,
-               .tuner_sif_gpio = 0x05,
-               .tuner_scl_gpio = 0x1a,
-               .tuner_sda_gpio = 0x1b,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x0c,
-               .gpio_pin_status_mask = 0x4001000,
-               .tuner_i2c_master = 1,
-               .norm = V4L2_STD_PAL,
-
-               .input = {{
-                       .type = CX231XX_VMUX_TELEVISION,
-                       .vmux = CX231XX_VIN_3_1,
-                       .amux = CX231XX_AMUX_VIDEO,
-                       .gpio = NULL,
-               }, {
-                       .type = CX231XX_VMUX_COMPOSITE1,
-                       .vmux = CX231XX_VIN_2_1,
-                       .amux = CX231XX_AMUX_LINE_IN,
-                       .gpio = NULL,
-               }, {
-                       .type = CX231XX_VMUX_SVIDEO,
-                       .vmux = CX231XX_VIN_1_1 |
-                               (CX231XX_VIN_1_2 << 8) |
-                               CX25840_SVIDEO_ON,
-                       .amux = CX231XX_AMUX_LINE_IN,
-                       .gpio = NULL,
-               } },
-       },
-       [CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC] = {
-               .name = "Hauppauge WinTV USB2 FM (NTSC)",
-               .tuner_type = TUNER_NXP_TDA18271,
-               .tuner_addr = 0x60,
-               .tuner_gpio = RDE250_XCV_TUNER,
-               .tuner_sif_gpio = 0x05,
-               .tuner_scl_gpio = 0x1a,
-               .tuner_sda_gpio = 0x1b,
-               .decoder = CX231XX_AVDECODER,
-               .output_mode = OUT_MODE_VIP11,
-               .ctl_pin_status_mask = 0xFFFFFFC4,
-               .agc_analog_digital_select_gpio = 0x0c,
-               .gpio_pin_status_mask = 0x4001000,
-               .tuner_i2c_master = 1,
-               .norm = V4L2_STD_NTSC,
-
-               .input = {{
-                       .type = CX231XX_VMUX_TELEVISION,
-                       .vmux = CX231XX_VIN_3_1,
-                       .amux = CX231XX_AMUX_VIDEO,
-                       .gpio = NULL,
-               }, {
-                       .type = CX231XX_VMUX_COMPOSITE1,
-                       .vmux = CX231XX_VIN_2_1,
-                       .amux = CX231XX_AMUX_LINE_IN,
-                       .gpio = NULL,
-               }, {
-                       .type = CX231XX_VMUX_SVIDEO,
-                       .vmux = CX231XX_VIN_1_1 |
-                               (CX231XX_VIN_1_2 << 8) |
-                               CX25840_SVIDEO_ON,
-                       .amux = CX231XX_AMUX_LINE_IN,
-                       .gpio = NULL,
-               } },
-       },
-};
-const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
-
-/* table of devices that work with this driver */
-struct usb_device_id cx231xx_id_table[] = {
-       {USB_DEVICE(0x0572, 0x5A3C),
-        .driver_info = CX231XX_BOARD_UNKNOWN},
-       {USB_DEVICE(0x0572, 0x58A2),
-        .driver_info = CX231XX_BOARD_CNXT_CARRAERA},
-       {USB_DEVICE(0x0572, 0x58A1),
-        .driver_info = CX231XX_BOARD_CNXT_SHELBY},
-       {USB_DEVICE(0x0572, 0x58A4),
-        .driver_info = CX231XX_BOARD_CNXT_RDE_253S},
-       {USB_DEVICE(0x0572, 0x58A5),
-        .driver_info = CX231XX_BOARD_CNXT_RDU_253S},
-       {USB_DEVICE(0x0572, 0x58A6),
-        .driver_info = CX231XX_BOARD_CNXT_VIDEO_GRABBER},
-       {USB_DEVICE(0x0572, 0x589E),
-        .driver_info = CX231XX_BOARD_CNXT_RDE_250},
-       {USB_DEVICE(0x0572, 0x58A0),
-        .driver_info = CX231XX_BOARD_CNXT_RDU_250},
-       {USB_DEVICE(0x2040, 0xb110),
-        .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL},
-       {USB_DEVICE(0x2040, 0xb111),
-        .driver_info = CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC},
-       {USB_DEVICE(0x2040, 0xb120),
-        .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
-       {USB_DEVICE(0x2040, 0xb140),
-        .driver_info = CX231XX_BOARD_HAUPPAUGE_EXETER},
-       {USB_DEVICE(0x2040, 0xc200),
-        .driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2},
-       {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001),
-        .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID},
-       {USB_DEVICE(USB_VID_PIXELVIEW, 0x5014),
-        .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
-       {USB_DEVICE(0x1b80, 0xe424),
-        .driver_info = CX231XX_BOARD_KWORLD_UB430_USB_HYBRID},
-       {USB_DEVICE(0x1f4d, 0x0237),
-        .driver_info = CX231XX_BOARD_ICONBIT_U100},
-       {},
-};
-
-MODULE_DEVICE_TABLE(usb, cx231xx_id_table);
-
-/* cx231xx_tuner_callback
- * will be used to reset XC5000 tuner using GPIO pin
- */
-
-int cx231xx_tuner_callback(void *ptr, int component, int command, int arg)
-{
-       int rc = 0;
-       struct cx231xx *dev = ptr;
-
-       if (dev->tuner_type == TUNER_XC5000) {
-               if (command == XC5000_TUNER_RESET) {
-                       cx231xx_info
-                               ("Tuner CB: RESET: cmd %d : tuner type %d \n",
-                                command, dev->tuner_type);
-                       cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
-                                              1);
-                       msleep(10);
-                       cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
-                                              0);
-                       msleep(330);
-                       cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
-                                              1);
-                       msleep(10);
-               }
-       } else if (dev->tuner_type == TUNER_NXP_TDA18271) {
-               switch (command) {
-               case TDA18271_CALLBACK_CMD_AGC_ENABLE:
-                       if (dev->model == CX231XX_BOARD_PV_PLAYTV_USB_HYBRID)
-                               rc = cx231xx_set_agc_analog_digital_mux_select(dev, arg);
-                       break;
-               default:
-                       rc = -EINVAL;
-                       break;
-               }
-       }
-       return rc;
-}
-EXPORT_SYMBOL_GPL(cx231xx_tuner_callback);
-
-void cx231xx_reset_out(struct cx231xx *dev)
-{
-       cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
-       msleep(200);
-       cx231xx_set_gpio_value(dev, CX23417_RESET, 0);
-       msleep(200);
-       cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
-}
-void cx231xx_enable_OSC(struct cx231xx *dev)
-{
-       cx231xx_set_gpio_value(dev, CX23417_OSC_EN, 1);
-}
-void cx231xx_sleep_s5h1432(struct cx231xx *dev)
-{
-       cx231xx_set_gpio_value(dev, SLEEP_S5H1432, 0);
-}
-
-static inline void cx231xx_set_model(struct cx231xx *dev)
-{
-       memcpy(&dev->board, &cx231xx_boards[dev->model], sizeof(dev->board));
-}
-
-/* Since cx231xx_pre_card_setup() requires a proper dev->model,
- * this won't work for boards with generic PCI IDs
- */
-void cx231xx_pre_card_setup(struct cx231xx *dev)
-{
-
-       cx231xx_set_model(dev);
-
-       cx231xx_info("Identified as %s (card=%d)\n",
-                    dev->board.name, dev->model);
-
-       /* set the direction for GPIO pins */
-       if (dev->board.tuner_gpio) {
-               cx231xx_set_gpio_direction(dev, dev->board.tuner_gpio->bit, 1);
-               cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit, 1);
-       }
-       if (dev->board.tuner_sif_gpio >= 0)
-               cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1);
-
-       /* request some modules if any required */
-
-       /* set the mode to Analog mode initially */
-       cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
-
-       /* Unlock device */
-       /* cx231xx_set_mode(dev, CX231XX_SUSPEND); */
-
-}
-
-static void cx231xx_config_tuner(struct cx231xx *dev)
-{
-       struct tuner_setup tun_setup;
-       struct v4l2_frequency f;
-
-       if (dev->tuner_type == TUNER_ABSENT)
-               return;
-
-       tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
-       tun_setup.type = dev->tuner_type;
-       tun_setup.addr = dev->tuner_addr;
-       tun_setup.tuner_callback = cx231xx_tuner_callback;
-
-       tuner_call(dev, tuner, s_type_addr, &tun_setup);
-
-#if 0
-       if (tun_setup.type == TUNER_XC5000) {
-               static struct xc2028_ctrl ctrl = {
-                       .fname = XC5000_DEFAULT_FIRMWARE,
-                       .max_len = 64,
-                       .demod = 0;
-               };
-               struct v4l2_priv_tun_config cfg = {
-                       .tuner = dev->tuner_type,
-                       .priv = &ctrl,
-               };
-               tuner_call(dev, tuner, s_config, &cfg);
-       }
-#endif
-       /* configure tuner */
-       f.tuner = 0;
-       f.type = V4L2_TUNER_ANALOG_TV;
-       f.frequency = 9076;     /* just a magic number */
-       dev->ctl_freq = f.frequency;
-       call_all(dev, tuner, s_frequency, &f);
-
-}
-
-void cx231xx_card_setup(struct cx231xx *dev)
-{
-
-       cx231xx_set_model(dev);
-
-       dev->tuner_type = cx231xx_boards[dev->model].tuner_type;
-       if (cx231xx_boards[dev->model].tuner_addr)
-               dev->tuner_addr = cx231xx_boards[dev->model].tuner_addr;
-
-       /* request some modules */
-       if (dev->board.decoder == CX231XX_AVDECODER) {
-               dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                                       &dev->i2c_bus[0].i2c_adap,
-                                       "cx25840", 0x88 >> 1, NULL);
-               if (dev->sd_cx25840 == NULL)
-                       cx231xx_info("cx25840 subdev registration failure\n");
-               cx25840_call(dev, core, load_fw);
-
-       }
-
-       /* Initialize the tuner */
-       if (dev->board.tuner_type != TUNER_ABSENT) {
-               dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                                                   &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
-                                                   "tuner",
-                                                   dev->tuner_addr, NULL);
-               if (dev->sd_tuner == NULL)
-                       cx231xx_info("tuner subdev registration failure\n");
-               else
-                       cx231xx_config_tuner(dev);
-       }
-}
-
-/*
- * cx231xx_config()
- * inits registers with sane defaults
- */
-int cx231xx_config(struct cx231xx *dev)
-{
-       /* TBD need to add cx231xx specific code */
-       dev->mute = 1;          /* maybe not the right place... */
-       dev->volume = 0x1f;
-
-       return 0;
-}
-
-/*
- * cx231xx_config_i2c()
- * configure i2c attached devices
- */
-void cx231xx_config_i2c(struct cx231xx *dev)
-{
-       /* u32 input = INPUT(dev->video_input)->vmux; */
-
-       call_all(dev, video, s_stream, 1);
-}
-
-/*
- * cx231xx_realease_resources()
- * unregisters the v4l2,i2c and usb devices
- * called when the device gets disconected or at module unload
-*/
-void cx231xx_release_resources(struct cx231xx *dev)
-{
-       cx231xx_release_analog_resources(dev);
-
-       cx231xx_remove_from_devlist(dev);
-
-       cx231xx_ir_exit(dev);
-
-       /* Release I2C buses */
-       cx231xx_dev_uninit(dev);
-
-       /* delete v4l2 device */
-       v4l2_device_unregister(&dev->v4l2_dev);
-
-       usb_put_dev(dev->udev);
-
-       /* Mark device as unused */
-       clear_bit(dev->devno, &cx231xx_devused);
-
-       kfree(dev->video_mode.alt_max_pkt_size);
-       kfree(dev->vbi_mode.alt_max_pkt_size);
-       kfree(dev->sliced_cc_mode.alt_max_pkt_size);
-       kfree(dev->ts1_mode.alt_max_pkt_size);
-       kfree(dev);
-}
-
-/*
- * cx231xx_init_dev()
- * allocates and inits the device structs, registers i2c bus and v4l device
- */
-static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev,
-                           int minor)
-{
-       int retval = -ENOMEM;
-       int errCode;
-       unsigned int maxh, maxw;
-
-       dev->udev = udev;
-       mutex_init(&dev->lock);
-       mutex_init(&dev->ctrl_urb_lock);
-       mutex_init(&dev->gpio_i2c_lock);
-       mutex_init(&dev->i2c_lock);
-
-       spin_lock_init(&dev->video_mode.slock);
-       spin_lock_init(&dev->vbi_mode.slock);
-       spin_lock_init(&dev->sliced_cc_mode.slock);
-
-       init_waitqueue_head(&dev->open);
-       init_waitqueue_head(&dev->wait_frame);
-       init_waitqueue_head(&dev->wait_stream);
-
-       dev->cx231xx_read_ctrl_reg = cx231xx_read_ctrl_reg;
-       dev->cx231xx_write_ctrl_reg = cx231xx_write_ctrl_reg;
-       dev->cx231xx_send_usb_command = cx231xx_send_usb_command;
-       dev->cx231xx_gpio_i2c_read = cx231xx_gpio_i2c_read;
-       dev->cx231xx_gpio_i2c_write = cx231xx_gpio_i2c_write;
-
-       /* Query cx231xx to find what pcb config it is related to */
-       initialize_cx231xx(dev);
-
-       /*To workaround error number=-71 on EP0 for VideoGrabber,
-                need set alt here.*/
-       if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER ||
-           dev->model == CX231XX_BOARD_HAUPPAUGE_USBLIVE2) {
-               cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3);
-               cx231xx_set_alt_setting(dev, INDEX_VANC, 1);
-       }
-       /* Cx231xx pre card setup */
-       cx231xx_pre_card_setup(dev);
-
-       errCode = cx231xx_config(dev);
-       if (errCode) {
-               cx231xx_errdev("error configuring device\n");
-               return -ENOMEM;
-       }
-
-       /* set default norm */
-       dev->norm = dev->board.norm;
-
-       /* register i2c bus */
-       errCode = cx231xx_dev_init(dev);
-       if (errCode < 0) {
-               cx231xx_dev_uninit(dev);
-               cx231xx_errdev("%s: cx231xx_i2c_register - errCode [%d]!\n",
-                              __func__, errCode);
-               return errCode;
-       }
-
-       /* Do board specific init */
-       cx231xx_card_setup(dev);
-
-       /* configure the device */
-       cx231xx_config_i2c(dev);
-
-       maxw = norm_maxw(dev);
-       maxh = norm_maxh(dev);
-
-       /* set default image size */
-       dev->width = maxw;
-       dev->height = maxh;
-       dev->interlaced = 0;
-       dev->video_input = 0;
-
-       errCode = cx231xx_config(dev);
-       if (errCode < 0) {
-               cx231xx_errdev("%s: cx231xx_config - errCode [%d]!\n",
-                              __func__, errCode);
-               return errCode;
-       }
-
-       /* init video dma queues */
-       INIT_LIST_HEAD(&dev->video_mode.vidq.active);
-       INIT_LIST_HEAD(&dev->video_mode.vidq.queued);
-
-       /* init vbi dma queues */
-       INIT_LIST_HEAD(&dev->vbi_mode.vidq.active);
-       INIT_LIST_HEAD(&dev->vbi_mode.vidq.queued);
-
-       /* Reset other chips required if they are tied up with GPIO pins */
-       cx231xx_add_into_devlist(dev);
-
-       if (dev->board.has_417) {
-               printk(KERN_INFO "attach 417 %d\n", dev->model);
-               if (cx231xx_417_register(dev) < 0) {
-                       printk(KERN_ERR
-                               "%s() Failed to register 417 on VID_B\n",
-                              __func__);
-               }
-       }
-
-       retval = cx231xx_register_analog_devices(dev);
-       if (retval < 0) {
-               cx231xx_release_resources(dev);
-               return retval;
-       }
-
-       cx231xx_ir_init(dev);
-
-       cx231xx_init_extension(dev);
-
-       return 0;
-}
-
-#if defined(CONFIG_MODULES) && defined(MODULE)
-static void request_module_async(struct work_struct *work)
-{
-       struct cx231xx *dev = container_of(work,
-                                          struct cx231xx, request_module_wk);
-
-       if (dev->has_alsa_audio)
-               request_module("cx231xx-alsa");
-
-       if (dev->board.has_dvb)
-               request_module("cx231xx-dvb");
-
-}
-
-static void request_modules(struct cx231xx *dev)
-{
-       INIT_WORK(&dev->request_module_wk, request_module_async);
-       schedule_work(&dev->request_module_wk);
-}
-
-static void flush_request_modules(struct cx231xx *dev)
-{
-       flush_work_sync(&dev->request_module_wk);
-}
-#else
-#define request_modules(dev)
-#define flush_request_modules(dev)
-#endif /* CONFIG_MODULES */
-
-/*
- * cx231xx_usb_probe()
- * checks for supported devices
- */
-static int cx231xx_usb_probe(struct usb_interface *interface,
-                            const struct usb_device_id *id)
-{
-       struct usb_device *udev;
-       struct usb_interface *uif;
-       struct cx231xx *dev = NULL;
-       int retval = -ENODEV;
-       int nr = 0, ifnum;
-       int i, isoc_pipe = 0;
-       char *speed;
-       struct usb_interface_assoc_descriptor *assoc_desc;
-
-       udev = usb_get_dev(interface_to_usbdev(interface));
-       ifnum = interface->altsetting[0].desc.bInterfaceNumber;
-
-       /*
-        * Interface number 0 - IR interface (handled by mceusb driver)
-        * Interface number 1 - AV interface (handled by this driver)
-        */
-       if (ifnum != 1)
-               return -ENODEV;
-
-       /* Check to see next free device and mark as used */
-       do {
-               nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
-               if (nr >= CX231XX_MAXBOARDS) {
-                       /* No free device slots */
-                       cx231xx_err(DRIVER_NAME ": Supports only %i devices.\n",
-                                       CX231XX_MAXBOARDS);
-                       return -ENOMEM;
-               }
-       } while (test_and_set_bit(nr, &cx231xx_devused));
-
-       /* allocate memory for our device state and initialize it */
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL) {
-               cx231xx_err(DRIVER_NAME ": out of memory!\n");
-               clear_bit(nr, &cx231xx_devused);
-               return -ENOMEM;
-       }
-
-       snprintf(dev->name, 29, "cx231xx #%d", nr);
-       dev->devno = nr;
-       dev->model = id->driver_info;
-       dev->video_mode.alt = -1;
-
-       dev->interface_count++;
-       /* reset gpio dir and value */
-       dev->gpio_dir = 0;
-       dev->gpio_val = 0;
-       dev->xc_fw_load_done = 0;
-       dev->has_alsa_audio = 1;
-       dev->power_mode = -1;
-       atomic_set(&dev->devlist_count, 0);
-
-       /* 0 - vbi ; 1 -sliced cc mode */
-       dev->vbi_or_sliced_cc_mode = 0;
-
-       /* get maximum no.of IAD interfaces */
-       assoc_desc = udev->actconfig->intf_assoc[0];
-       dev->max_iad_interface_count = assoc_desc->bInterfaceCount;
-
-       /* init CIR module TBD */
-
-       /*mode_tv: digital=1 or analog=0*/
-       dev->mode_tv = 0;
-
-       dev->USE_ISO = transfer_mode;
-
-       switch (udev->speed) {
-       case USB_SPEED_LOW:
-               speed = "1.5";
-               break;
-       case USB_SPEED_UNKNOWN:
-       case USB_SPEED_FULL:
-               speed = "12";
-               break;
-       case USB_SPEED_HIGH:
-               speed = "480";
-               break;
-       default:
-               speed = "unknown";
-       }
-
-       cx231xx_info("New device %s %s @ %s Mbps "
-            "(%04x:%04x) with %d interfaces\n",
-            udev->manufacturer ? udev->manufacturer : "",
-            udev->product ? udev->product : "",
-            speed,
-            le16_to_cpu(udev->descriptor.idVendor),
-            le16_to_cpu(udev->descriptor.idProduct),
-            dev->max_iad_interface_count);
-
-       /* increment interface count */
-       dev->interface_count++;
-
-       /* get device number */
-       nr = dev->devno;
-
-       assoc_desc = udev->actconfig->intf_assoc[0];
-       if (assoc_desc->bFirstInterface != ifnum) {
-               cx231xx_err(DRIVER_NAME ": Not found "
-                           "matching IAD interface\n");
-               clear_bit(dev->devno, &cx231xx_devused);
-               kfree(dev);
-               dev = NULL;
-               return -ENODEV;
-       }
-
-       cx231xx_info("registering interface %d\n", ifnum);
-
-       /* save our data pointer in this interface device */
-       usb_set_intfdata(interface, dev);
-
-       /*
-        * AV device initialization - only done at the last interface
-        */
-
-       /* Create v4l2 device */
-       retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
-       if (retval) {
-               cx231xx_errdev("v4l2_device_register failed\n");
-               clear_bit(dev->devno, &cx231xx_devused);
-               kfree(dev);
-               dev = NULL;
-               return -EIO;
-       }
-       /* allocate device struct */
-       retval = cx231xx_init_dev(dev, udev, nr);
-       if (retval) {
-               clear_bit(dev->devno, &cx231xx_devused);
-               v4l2_device_unregister(&dev->v4l2_dev);
-               kfree(dev);
-               dev = NULL;
-               usb_set_intfdata(interface, NULL);
-
-               return retval;
-       }
-
-       /* compute alternate max packet sizes for video */
-       uif = udev->actconfig->interface[dev->current_pcb_config.
-                      hs_config_info[0].interface_info.video_index + 1];
-
-       dev->video_mode.end_point_addr = le16_to_cpu(uif->altsetting[0].
-                       endpoint[isoc_pipe].desc.bEndpointAddress);
-
-       dev->video_mode.num_alt = uif->num_altsetting;
-       cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
-                    dev->video_mode.end_point_addr,
-                    dev->video_mode.num_alt);
-       dev->video_mode.alt_max_pkt_size =
-               kmalloc(32 * dev->video_mode.num_alt, GFP_KERNEL);
-
-       if (dev->video_mode.alt_max_pkt_size == NULL) {
-               cx231xx_errdev("out of memory!\n");
-               clear_bit(dev->devno, &cx231xx_devused);
-               v4l2_device_unregister(&dev->v4l2_dev);
-               kfree(dev);
-               dev = NULL;
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < dev->video_mode.num_alt; i++) {
-               u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
-                               desc.wMaxPacketSize);
-               dev->video_mode.alt_max_pkt_size[i] =
-                   (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-               cx231xx_info("Alternate setting %i, max size= %i\n", i,
-                            dev->video_mode.alt_max_pkt_size[i]);
-       }
-
-       /* compute alternate max packet sizes for vbi */
-       uif = udev->actconfig->interface[dev->current_pcb_config.
-                                      hs_config_info[0].interface_info.
-                                      vanc_index + 1];
-
-       dev->vbi_mode.end_point_addr =
-           le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.
-                       bEndpointAddress);
-
-       dev->vbi_mode.num_alt = uif->num_altsetting;
-       cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
-                    dev->vbi_mode.end_point_addr,
-                    dev->vbi_mode.num_alt);
-       dev->vbi_mode.alt_max_pkt_size =
-           kmalloc(32 * dev->vbi_mode.num_alt, GFP_KERNEL);
-
-       if (dev->vbi_mode.alt_max_pkt_size == NULL) {
-               cx231xx_errdev("out of memory!\n");
-               clear_bit(dev->devno, &cx231xx_devused);
-               v4l2_device_unregister(&dev->v4l2_dev);
-               kfree(dev);
-               dev = NULL;
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < dev->vbi_mode.num_alt; i++) {
-               u16 tmp =
-                   le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
-                               desc.wMaxPacketSize);
-               dev->vbi_mode.alt_max_pkt_size[i] =
-                   (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-               cx231xx_info("Alternate setting %i, max size= %i\n", i,
-                            dev->vbi_mode.alt_max_pkt_size[i]);
-       }
-
-       /* compute alternate max packet sizes for sliced CC */
-       uif = udev->actconfig->interface[dev->current_pcb_config.
-                                      hs_config_info[0].interface_info.
-                                      hanc_index + 1];
-
-       dev->sliced_cc_mode.end_point_addr =
-           le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].desc.
-                       bEndpointAddress);
-
-       dev->sliced_cc_mode.num_alt = uif->num_altsetting;
-       cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
-                    dev->sliced_cc_mode.end_point_addr,
-                    dev->sliced_cc_mode.num_alt);
-       dev->sliced_cc_mode.alt_max_pkt_size =
-               kmalloc(32 * dev->sliced_cc_mode.num_alt, GFP_KERNEL);
-
-       if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) {
-               cx231xx_errdev("out of memory!\n");
-               clear_bit(dev->devno, &cx231xx_devused);
-               v4l2_device_unregister(&dev->v4l2_dev);
-               kfree(dev);
-               dev = NULL;
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) {
-               u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
-                               desc.wMaxPacketSize);
-               dev->sliced_cc_mode.alt_max_pkt_size[i] =
-                   (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-               cx231xx_info("Alternate setting %i, max size= %i\n", i,
-                            dev->sliced_cc_mode.alt_max_pkt_size[i]);
-       }
-
-       if (dev->current_pcb_config.ts1_source != 0xff) {
-               /* compute alternate max packet sizes for TS1 */
-               uif = udev->actconfig->interface[dev->current_pcb_config.
-                                              hs_config_info[0].
-                                              interface_info.
-                                              ts1_index + 1];
-
-               dev->ts1_mode.end_point_addr =
-                   le16_to_cpu(uif->altsetting[0].endpoint[isoc_pipe].
-                               desc.bEndpointAddress);
-
-               dev->ts1_mode.num_alt = uif->num_altsetting;
-               cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
-                            dev->ts1_mode.end_point_addr,
-                            dev->ts1_mode.num_alt);
-               dev->ts1_mode.alt_max_pkt_size =
-                       kmalloc(32 * dev->ts1_mode.num_alt, GFP_KERNEL);
-
-               if (dev->ts1_mode.alt_max_pkt_size == NULL) {
-                       cx231xx_errdev("out of memory!\n");
-                       clear_bit(dev->devno, &cx231xx_devused);
-                       v4l2_device_unregister(&dev->v4l2_dev);
-                       kfree(dev);
-                       dev = NULL;
-                       return -ENOMEM;
-               }
-
-               for (i = 0; i < dev->ts1_mode.num_alt; i++) {
-                       u16 tmp = le16_to_cpu(uif->altsetting[i].
-                                               endpoint[isoc_pipe].desc.
-                                               wMaxPacketSize);
-                       dev->ts1_mode.alt_max_pkt_size[i] =
-                           (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-                       cx231xx_info("Alternate setting %i, max size= %i\n", i,
-                                    dev->ts1_mode.alt_max_pkt_size[i]);
-               }
-       }
-
-       if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) {
-               cx231xx_enable_OSC(dev);
-               cx231xx_reset_out(dev);
-               cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3);
-       }
-
-       if (dev->model == CX231XX_BOARD_CNXT_RDE_253S)
-               cx231xx_sleep_s5h1432(dev);
-
-       /* load other modules required */
-       request_modules(dev);
-
-       return 0;
-}
-
-/*
- * cx231xx_usb_disconnect()
- * called when the device gets diconencted
- * video device will be unregistered on v4l2_close in case it is still open
- */
-static void cx231xx_usb_disconnect(struct usb_interface *interface)
-{
-       struct cx231xx *dev;
-
-       dev = usb_get_intfdata(interface);
-       usb_set_intfdata(interface, NULL);
-
-       if (!dev)
-               return;
-
-       if (!dev->udev)
-               return;
-
-       dev->state |= DEV_DISCONNECTED;
-
-       flush_request_modules(dev);
-
-       /* wait until all current v4l2 io is finished then deallocate
-          resources */
-       mutex_lock(&dev->lock);
-
-       wake_up_interruptible_all(&dev->open);
-
-       if (dev->users) {
-               cx231xx_warn
-                   ("device %s is open! Deregistration and memory "
-                    "deallocation are deferred on close.\n",
-                    video_device_node_name(dev->vdev));
-
-               /* Even having users, it is safe to remove the RC i2c driver */
-               cx231xx_ir_exit(dev);
-
-               if (dev->USE_ISO)
-                       cx231xx_uninit_isoc(dev);
-               else
-                       cx231xx_uninit_bulk(dev);
-               wake_up_interruptible(&dev->wait_frame);
-               wake_up_interruptible(&dev->wait_stream);
-       } else {
-       }
-
-       cx231xx_close_extension(dev);
-
-       mutex_unlock(&dev->lock);
-
-       if (!dev->users)
-               cx231xx_release_resources(dev);
-}
-
-static struct usb_driver cx231xx_usb_driver = {
-       .name = "cx231xx",
-       .probe = cx231xx_usb_probe,
-       .disconnect = cx231xx_usb_disconnect,
-       .id_table = cx231xx_id_table,
-};
-
-module_usb_driver(cx231xx_usb_driver);
diff --git a/drivers/media/video/cx231xx/cx231xx-conf-reg.h b/drivers/media/video/cx231xx/cx231xx-conf-reg.h
deleted file mode 100644 (file)
index 25593f2..0000000
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
-   cx231xx_conf-reg.h - driver for Conexant Cx23100/101/102 USB
-                       video capture devices
-
-   Copyright (C) 2008 <srinivasa.deevi at conexant dot 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.
-
-   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.
- */
-
-#ifndef _POLARIS_REG_H_
-#define _POLARIS_REG_H_
-
-#define BOARD_CFG_STAT          0x0
-#define TS_MODE_REG             0x4
-#define TS1_CFG_REG             0x8
-#define TS1_LENGTH_REG          0xc
-#define TS2_CFG_REG             0x10
-#define TS2_LENGTH_REG          0x14
-#define EP_MODE_SET             0x18
-#define CIR_PWR_PTN1            0x1c
-#define CIR_PWR_PTN2            0x20
-#define CIR_PWR_PTN3            0x24
-#define CIR_PWR_MASK0           0x28
-#define CIR_PWR_MASK1           0x2c
-#define CIR_PWR_MASK2           0x30
-#define CIR_GAIN                0x34
-#define CIR_CAR_REG             0x38
-#define CIR_OT_CFG1             0x40
-#define CIR_OT_CFG2             0x44
-#define GBULK_BIT_EN            0x68
-#define PWR_CTL_EN              0x74
-
-/* Polaris Endpoints capture mask for register EP_MODE_SET */
-#define ENABLE_EP1              0x01   /* Bit[0]=1 */
-#define ENABLE_EP2              0x02   /* Bit[1]=1 */
-#define ENABLE_EP3              0x04   /* Bit[2]=1 */
-#define ENABLE_EP4              0x08   /* Bit[3]=1 */
-#define ENABLE_EP5              0x10   /* Bit[4]=1 */
-#define ENABLE_EP6              0x20   /* Bit[5]=1 */
-
-/* Bit definition for register PWR_CTL_EN */
-#define PWR_MODE_MASK           0x17f
-#define PWR_AV_EN               0x08   /* bit3 */
-#define PWR_ISO_EN              0x40   /* bit6 */
-#define PWR_AV_MODE             0x30   /* bit4,5  */
-#define PWR_TUNER_EN            0x04   /* bit2 */
-#define PWR_DEMOD_EN            0x02   /* bit1 */
-#define I2C_DEMOD_EN            0x01   /* bit0 */
-#define PWR_RESETOUT_EN         0x100  /* bit8 */
-
-enum AV_MODE{
-       POLARIS_AVMODE_DEFAULT = 0,
-       POLARIS_AVMODE_DIGITAL = 0x10,
-       POLARIS_AVMODE_ANALOGT_TV = 0x20,
-       POLARIS_AVMODE_ENXTERNAL_AV = 0x30,
-
-};
-
-/* Colibri Registers */
-
-#define SINGLE_ENDED            0x0
-#define LOW_IF                  0x4
-#define EU_IF                   0x9
-#define US_IF                   0xa
-
-#define SUP_BLK_TUNE1           0x00
-#define SUP_BLK_TUNE2           0x01
-#define SUP_BLK_TUNE3           0x02
-#define SUP_BLK_XTAL            0x03
-#define SUP_BLK_PLL1            0x04
-#define SUP_BLK_PLL2            0x05
-#define SUP_BLK_PLL3            0x06
-#define SUP_BLK_REF             0x07
-#define SUP_BLK_PWRDN           0x08
-#define SUP_BLK_TESTPAD         0x09
-#define ADC_COM_INT5_STAB_REF   0x0a
-#define ADC_COM_QUANT           0x0b
-#define ADC_COM_BIAS1           0x0c
-#define ADC_COM_BIAS2           0x0d
-#define ADC_COM_BIAS3           0x0e
-#define TESTBUS_CTRL            0x12
-
-#define FLD_PWRDN_TUNING_BIAS  0x10
-#define FLD_PWRDN_ENABLE_PLL   0x08
-#define FLD_PWRDN_PD_BANDGAP   0x04
-#define FLD_PWRDN_PD_BIAS      0x02
-#define FLD_PWRDN_PD_TUNECK    0x01
-
-
-#define ADC_STATUS_CH1          0x20
-#define ADC_STATUS_CH2          0x40
-#define ADC_STATUS_CH3          0x60
-
-#define ADC_STATUS2_CH1         0x21
-#define ADC_STATUS2_CH2         0x41
-#define ADC_STATUS2_CH3         0x61
-
-#define ADC_CAL_ATEST_CH1       0x22
-#define ADC_CAL_ATEST_CH2       0x42
-#define ADC_CAL_ATEST_CH3       0x62
-
-#define ADC_PWRDN_CLAMP_CH1     0x23
-#define ADC_PWRDN_CLAMP_CH2     0x43
-#define ADC_PWRDN_CLAMP_CH3     0x63
-
-#define ADC_CTRL_DAC23_CH1      0x24
-#define ADC_CTRL_DAC23_CH2      0x44
-#define ADC_CTRL_DAC23_CH3      0x64
-
-#define ADC_CTRL_DAC1_CH1       0x25
-#define ADC_CTRL_DAC1_CH2       0x45
-#define ADC_CTRL_DAC1_CH3       0x65
-
-#define ADC_DCSERVO_DEM_CH1     0x26
-#define ADC_DCSERVO_DEM_CH2     0x46
-#define ADC_DCSERVO_DEM_CH3     0x66
-
-#define ADC_FB_FRCRST_CH1       0x27
-#define ADC_FB_FRCRST_CH2       0x47
-#define ADC_FB_FRCRST_CH3       0x67
-
-#define ADC_INPUT_CH1           0x28
-#define ADC_INPUT_CH2           0x48
-#define ADC_INPUT_CH3           0x68
-#define INPUT_SEL_MASK          0x30   /* [5:4] in_sel */
-
-#define ADC_NTF_PRECLMP_EN_CH1  0x29
-#define ADC_NTF_PRECLMP_EN_CH2  0x49
-#define ADC_NTF_PRECLMP_EN_CH3  0x69
-
-#define ADC_QGAIN_RES_TRM_CH1   0x2a
-#define ADC_QGAIN_RES_TRM_CH2   0x4a
-#define ADC_QGAIN_RES_TRM_CH3   0x6a
-
-#define ADC_SOC_PRECLMP_TERM_CH1    0x2b
-#define ADC_SOC_PRECLMP_TERM_CH2    0x4b
-#define ADC_SOC_PRECLMP_TERM_CH3    0x6b
-
-#define TESTBUS_CTRL_CH1        0x32
-#define TESTBUS_CTRL_CH2        0x52
-#define TESTBUS_CTRL_CH3        0x72
-
-/******************************************************************************
-                           * DIF registers *
- ******************************************************************************/
-#define      DIRECT_IF_REVB_BASE  0x00300
-
-/*****************************************************************************/
-#define      DIF_PLL_FREQ_WORD        (DIRECT_IF_REVB_BASE + 0x00000000)
-/*****************************************************************************/
-#define      FLD_DIF_PLL_LOCK                           0x80000000
-/*  Reserved                                [30:29] */
-#define      FLD_DIF_PLL_FREE_RUN                       0x10000000
-#define      FLD_DIF_PLL_FREQ                           0x0fffffff
-
-/*****************************************************************************/
-#define      DIF_PLL_CTRL             (DIRECT_IF_REVB_BASE + 0x00000004)
-/*****************************************************************************/
-#define      FLD_DIF_KD_PD                              0xff000000
-/*  Reserved                             [23:20] */
-#define      FLD_DIF_KDS_PD                             0x000f0000
-#define      FLD_DIF_KI_PD                              0x0000ff00
-/*  Reserved                             [7:4] */
-#define      FLD_DIF_KIS_PD                             0x0000000f
-
-/*****************************************************************************/
-#define      DIF_PLL_CTRL1            (DIRECT_IF_REVB_BASE + 0x00000008)
-/*****************************************************************************/
-#define      FLD_DIF_KD_FD                              0xff000000
-/*  Reserved                             [23:20] */
-#define      FLD_DIF_KDS_FD                             0x000f0000
-#define      FLD_DIF_KI_FD                              0x0000ff00
-#define      FLD_DIF_SIG_PROP_SZ                        0x000000f0
-#define      FLD_DIF_KIS_FD                             0x0000000f
-
-/*****************************************************************************/
-#define      DIF_PLL_CTRL2            (DIRECT_IF_REVB_BASE + 0x0000000c)
-/*****************************************************************************/
-#define      FLD_DIF_PLL_AGC_REF                        0xfff00000
-#define      FLD_DIF_PLL_AGC_KI                         0x000f0000
-/*  Reserved                             [15] */
-#define      FLD_DIF_FREQ_LIMIT                         0x00007000
-#define      FLD_DIF_K_FD                               0x00000f00
-#define      FLD_DIF_DOWNSMPL_FD                        0x000000ff
-
-/*****************************************************************************/
-#define      DIF_PLL_CTRL3            (DIRECT_IF_REVB_BASE + 0x00000010)
-/*****************************************************************************/
-/*  Reserved                             [31:16] */
-#define      FLD_DIF_PLL_AGC_EN                         0x00008000
-/*  Reserved                             [14:12] */
-#define      FLD_DIF_PLL_MAN_GAIN                       0x00000fff
-
-/*****************************************************************************/
-#define      DIF_AGC_IF_REF           (DIRECT_IF_REVB_BASE + 0x00000014)
-/*****************************************************************************/
-#define      FLD_DIF_K_AGC_RF                           0xf0000000
-#define      FLD_DIF_K_AGC_IF                           0x0f000000
-#define      FLD_DIF_K_AGC_INT                          0x00f00000
-/*  Reserved                             [19:12] */
-#define      FLD_DIF_IF_REF                             0x00000fff
-
-/*****************************************************************************/
-#define      DIF_AGC_CTRL_IF          (DIRECT_IF_REVB_BASE + 0x00000018)
-/*****************************************************************************/
-#define      FLD_DIF_IF_MAX                             0xff000000
-#define      FLD_DIF_IF_MIN                             0x00ff0000
-#define      FLD_DIF_IF_AGC                             0x0000ffff
-
-/*****************************************************************************/
-#define      DIF_AGC_CTRL_INT         (DIRECT_IF_REVB_BASE + 0x0000001c)
-/*****************************************************************************/
-#define      FLD_DIF_INT_MAX                            0xff000000
-#define      FLD_DIF_INT_MIN                            0x00ff0000
-#define      FLD_DIF_INT_AGC                            0x0000ffff
-
-/*****************************************************************************/
-#define      DIF_AGC_CTRL_RF          (DIRECT_IF_REVB_BASE + 0x00000020)
-/*****************************************************************************/
-#define      FLD_DIF_RF_MAX                             0xff000000
-#define      FLD_DIF_RF_MIN                             0x00ff0000
-#define      FLD_DIF_RF_AGC                             0x0000ffff
-
-/*****************************************************************************/
-#define      DIF_AGC_IF_INT_CURRENT   (DIRECT_IF_REVB_BASE + 0x00000024)
-/*****************************************************************************/
-#define      FLD_DIF_IF_AGC_IN                          0xffff0000
-#define      FLD_DIF_INT_AGC_IN                         0x0000ffff
-
-/*****************************************************************************/
-#define      DIF_AGC_RF_CURRENT       (DIRECT_IF_REVB_BASE + 0x00000028)
-/*****************************************************************************/
-/*  Reserved                            [31:16] */
-#define      FLD_DIF_RF_AGC_IN                          0x0000ffff
-
-/*****************************************************************************/
-#define      DIF_VIDEO_AGC_CTRL       (DIRECT_IF_REVB_BASE + 0x0000002c)
-/*****************************************************************************/
-#define      FLD_DIF_AFD                                0xc0000000
-#define      FLD_DIF_K_VID_AGC                          0x30000000
-#define      FLD_DIF_LINE_LENGTH                        0x0fff0000
-#define      FLD_DIF_AGC_GAIN                           0x0000ffff
-
-/*****************************************************************************/
-#define      DIF_VID_AUD_OVERRIDE     (DIRECT_IF_REVB_BASE + 0x00000030)
-/*****************************************************************************/
-#define      FLD_DIF_AUDIO_AGC_OVERRIDE                 0x80000000
-/*  Reserved                             [30:30] */
-#define      FLD_DIF_AUDIO_MAN_GAIN                     0x3f000000
-/*  Reserved                             [23:17] */
-#define      FLD_DIF_VID_AGC_OVERRIDE                   0x00010000
-#define      FLD_DIF_VID_MAN_GAIN                       0x0000ffff
-
-/*****************************************************************************/
-#define      DIF_AV_SEP_CTRL          (DIRECT_IF_REVB_BASE + 0x00000034)
-/*****************************************************************************/
-#define      FLD_DIF_LPF_FREQ                           0xc0000000
-#define      FLD_DIF_AV_PHASE_INC                       0x3f000000
-#define      FLD_DIF_AUDIO_FREQ                         0x00ffffff
-
-/*****************************************************************************/
-#define      DIF_COMP_FLT_CTRL        (DIRECT_IF_REVB_BASE + 0x00000038)
-/*****************************************************************************/
-/*  Reserved                            [31:24] */
-#define      FLD_DIF_IIR23_R2                           0x00ff0000
-#define      FLD_DIF_IIR23_R1                           0x0000ff00
-#define      FLD_DIF_IIR1_R1                            0x000000ff
-
-/*****************************************************************************/
-#define      DIF_MISC_CTRL            (DIRECT_IF_REVB_BASE + 0x0000003c)
-/*****************************************************************************/
-#define      FLD_DIF_DIF_BYPASS                         0x80000000
-#define      FLD_DIF_FM_NYQ_GAIN                        0x40000000
-#define      FLD_DIF_RF_AGC_ENA                         0x20000000
-#define      FLD_DIF_INT_AGC_ENA                        0x10000000
-#define      FLD_DIF_IF_AGC_ENA                         0x08000000
-#define      FLD_DIF_FORCE_RF_IF_LOCK                   0x04000000
-#define      FLD_DIF_VIDEO_AGC_ENA                      0x02000000
-#define      FLD_DIF_RF_AGC_INV                         0x01000000
-#define      FLD_DIF_INT_AGC_INV                        0x00800000
-#define      FLD_DIF_IF_AGC_INV                         0x00400000
-#define      FLD_DIF_SPEC_INV                           0x00200000
-#define      FLD_DIF_AUD_FULL_BW                        0x00100000
-#define      FLD_DIF_AUD_SRC_SEL                        0x00080000
-/*  Reserved                             [18] */
-#define      FLD_DIF_IF_FREQ                            0x00030000
-/*  Reserved                             [15:14] */
-#define      FLD_DIF_TIP_OFFSET                         0x00003f00
-/*  Reserved                             [7:5] */
-#define      FLD_DIF_DITHER_ENA                         0x00000010
-/*  Reserved                             [3:1] */
-#define      FLD_DIF_RF_IF_LOCK                         0x00000001
-
-/*****************************************************************************/
-#define      DIF_SRC_PHASE_INC        (DIRECT_IF_REVB_BASE + 0x00000040)
-/*****************************************************************************/
-/*  Reserved                             [31:29] */
-#define      FLD_DIF_PHASE_INC                          0x1fffffff
-
-/*****************************************************************************/
-#define      DIF_SRC_GAIN_CONTROL     (DIRECT_IF_REVB_BASE + 0x00000044)
-/*****************************************************************************/
-/*  Reserved                             [31:16] */
-#define      FLD_DIF_SRC_KI                             0x0000ff00
-#define      FLD_DIF_SRC_KD                             0x000000ff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF01          (DIRECT_IF_REVB_BASE + 0x00000048)
-/*****************************************************************************/
-/*  Reserved                             [31:19] */
-#define      FLD_DIF_BPF_COEFF_0                        0x00070000
-/*  Reserved                             [15:4] */
-#define      FLD_DIF_BPF_COEFF_1                        0x0000000f
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF23          (DIRECT_IF_REVB_BASE + 0x0000004c)
-/*****************************************************************************/
-/*  Reserved                             [31:22] */
-#define      FLD_DIF_BPF_COEFF_2                        0x003f0000
-/*  Reserved                             [15:7] */
-#define      FLD_DIF_BPF_COEFF_3                        0x0000007f
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF45          (DIRECT_IF_REVB_BASE + 0x00000050)
-/*****************************************************************************/
-/*  Reserved                             [31:24] */
-#define      FLD_DIF_BPF_COEFF_4                        0x00ff0000
-/*  Reserved                             [15:8] */
-#define      FLD_DIF_BPF_COEFF_5                        0x000000ff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF67          (DIRECT_IF_REVB_BASE + 0x00000054)
-/*****************************************************************************/
-/*  Reserved                             [31:25] */
-#define      FLD_DIF_BPF_COEFF_6                        0x01ff0000
-/*  Reserved                             [15:9] */
-#define      FLD_DIF_BPF_COEFF_7                        0x000001ff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF89          (DIRECT_IF_REVB_BASE + 0x00000058)
-/*****************************************************************************/
-/*  Reserved                             [31:26] */
-#define      FLD_DIF_BPF_COEFF_8                        0x03ff0000
-/*  Reserved                             [15:10] */
-#define      FLD_DIF_BPF_COEFF_9                        0x000003ff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF1011        (DIRECT_IF_REVB_BASE + 0x0000005c)
-/*****************************************************************************/
-/*  Reserved                             [31:27] */
-#define      FLD_DIF_BPF_COEFF_10                       0x07ff0000
-/*  Reserved                             [15:11] */
-#define      FLD_DIF_BPF_COEFF_11                       0x000007ff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF1213        (DIRECT_IF_REVB_BASE + 0x00000060)
-/*****************************************************************************/
-/*  Reserved                             [31:27] */
-#define      FLD_DIF_BPF_COEFF_12                       0x07ff0000
-/*  Reserved                             [15:12] */
-#define      FLD_DIF_BPF_COEFF_13                       0x00000fff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF1415        (DIRECT_IF_REVB_BASE + 0x00000064)
-/*****************************************************************************/
-/*  Reserved                             [31:28] */
-#define      FLD_DIF_BPF_COEFF_14                       0x0fff0000
-/*  Reserved                             [15:12] */
-#define      FLD_DIF_BPF_COEFF_15                       0x00000fff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF1617        (DIRECT_IF_REVB_BASE + 0x00000068)
-/*****************************************************************************/
-/*  Reserved                             [31:29] */
-#define      FLD_DIF_BPF_COEFF_16                       0x1fff0000
-/*  Reserved                             [15:13] */
-#define      FLD_DIF_BPF_COEFF_17                       0x00001fff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF1819        (DIRECT_IF_REVB_BASE + 0x0000006c)
-/*****************************************************************************/
-/*  Reserved                             [31:29] */
-#define      FLD_DIF_BPF_COEFF_18                       0x1fff0000
-/*  Reserved                             [15:13] */
-#define      FLD_DIF_BPF_COEFF_19                       0x00001fff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF2021        (DIRECT_IF_REVB_BASE + 0x00000070)
-/*****************************************************************************/
-/*  Reserved                             [31:29] */
-#define      FLD_DIF_BPF_COEFF_20                       0x1fff0000
-/*  Reserved                             [15:14] */
-#define      FLD_DIF_BPF_COEFF_21                       0x00003fff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF2223        (DIRECT_IF_REVB_BASE + 0x00000074)
-/*****************************************************************************/
-/*  Reserved                             [31:30] */
-#define      FLD_DIF_BPF_COEFF_22                       0x3fff0000
-/*  Reserved                             [15:14] */
-#define      FLD_DIF_BPF_COEFF_23                       0x00003fff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF2425        (DIRECT_IF_REVB_BASE + 0x00000078)
-/*****************************************************************************/
-/*  Reserved                             [31:30] */
-#define      FLD_DIF_BPF_COEFF_24                       0x3fff0000
-/*  Reserved                             [15:14] */
-#define      FLD_DIF_BPF_COEFF_25                       0x00003fff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF2627        (DIRECT_IF_REVB_BASE + 0x0000007c)
-/*****************************************************************************/
-/*  Reserved                             [31:30] */
-#define      FLD_DIF_BPF_COEFF_26                       0x3fff0000
-/*  Reserved                             [15:14] */
-#define      FLD_DIF_BPF_COEFF_27                       0x00003fff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF2829        (DIRECT_IF_REVB_BASE + 0x00000080)
-/*****************************************************************************/
-/*  Reserved                             [31:30] */
-#define      FLD_DIF_BPF_COEFF_28                       0x3fff0000
-/*  Reserved                             [15:14] */
-#define      FLD_DIF_BPF_COEFF_29                       0x00003fff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF3031        (DIRECT_IF_REVB_BASE + 0x00000084)
-/*****************************************************************************/
-/*  Reserved                             [31:30] */
-#define      FLD_DIF_BPF_COEFF_30                       0x3fff0000
-/*  Reserved                             [15:14] */
-#define      FLD_DIF_BPF_COEFF_31                       0x00003fff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF3233        (DIRECT_IF_REVB_BASE + 0x00000088)
-/*****************************************************************************/
-/*  Reserved                             [31:30] */
-#define      FLD_DIF_BPF_COEFF_32                       0x3fff0000
-/*  Reserved                             [15:14] */
-#define      FLD_DIF_BPF_COEFF_33                       0x00003fff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF3435        (DIRECT_IF_REVB_BASE + 0x0000008c)
-/*****************************************************************************/
-/*  Reserved                             [31:30] */
-#define      FLD_DIF_BPF_COEFF_34                       0x3fff0000
-/*  Reserved                             [15:14] */
-#define      FLD_DIF_BPF_COEFF_35                       0x00003fff
-
-/*****************************************************************************/
-#define      DIF_BPF_COEFF36          (DIRECT_IF_REVB_BASE + 0x00000090)
-/*****************************************************************************/
-/*  Reserved                             [31:30] */
-#define      FLD_DIF_BPF_COEFF_36                       0x3fff0000
-/*  Reserved                             [15:0] */
-
-/*****************************************************************************/
-#define      DIF_RPT_VARIANCE         (DIRECT_IF_REVB_BASE + 0x00000094)
-/*****************************************************************************/
-/*  Reserved                             [31:20] */
-#define      FLD_DIF_RPT_VARIANCE                       0x000fffff
-
-/*****************************************************************************/
-#define      DIF_SOFT_RST_CTRL_REVB       (DIRECT_IF_REVB_BASE + 0x00000098)
-/*****************************************************************************/
-/*  Reserved                             [31:8] */
-#define      FLD_DIF_DIF_SOFT_RST                       0x00000080
-#define      FLD_DIF_DIF_REG_RST_MSK                    0x00000040
-#define      FLD_DIF_AGC_RST_MSK                        0x00000020
-#define      FLD_DIF_CMP_RST_MSK                        0x00000010
-#define      FLD_DIF_AVS_RST_MSK                        0x00000008
-#define      FLD_DIF_NYQ_RST_MSK                        0x00000004
-#define      FLD_DIF_DIF_SRC_RST_MSK                    0x00000002
-#define      FLD_DIF_PLL_RST_MSK                        0x00000001
-
-/*****************************************************************************/
-#define      DIF_PLL_FREQ_ERR         (DIRECT_IF_REVB_BASE + 0x0000009c)
-/*****************************************************************************/
-/*  Reserved                             [31:25] */
-#define      FLD_DIF_CTL_IP                             0x01ffffff
-
-#endif
diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c
deleted file mode 100644 (file)
index 05358d4..0000000
+++ /dev/null
@@ -1,1736 +0,0 @@
-/*
-   cx231xx-core.c - driver for Conexant Cx23100/101/102
-                               USB video capture devices
-
-   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
-                               Based on em28xx driver
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/vmalloc.h>
-#include <media/v4l2-common.h>
-#include <media/tuner.h>
-
-#include "cx231xx.h"
-#include "cx231xx-reg.h"
-
-/* #define ENABLE_DEBUG_ISOC_FRAMES */
-
-static unsigned int core_debug;
-module_param(core_debug, int, 0644);
-MODULE_PARM_DESC(core_debug, "enable debug messages [core]");
-
-#define cx231xx_coredbg(fmt, arg...) do {\
-       if (core_debug) \
-               printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __func__ , ##arg); } while (0)
-
-static unsigned int reg_debug;
-module_param(reg_debug, int, 0644);
-MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]");
-
-static int alt = CX231XX_PINOUT;
-module_param(alt, int, 0644);
-MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
-
-#define cx231xx_isocdbg(fmt, arg...) do {\
-       if (core_debug) \
-               printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __func__ , ##arg); } while (0)
-
-/*****************************************************************
-*             Device control list functions                                     *
-******************************************************************/
-
-LIST_HEAD(cx231xx_devlist);
-static DEFINE_MUTEX(cx231xx_devlist_mutex);
-
-/*
- * cx231xx_realease_resources()
- * unregisters the v4l2,i2c and usb devices
- * called when the device gets disconected or at module unload
-*/
-void cx231xx_remove_from_devlist(struct cx231xx *dev)
-{
-       if (dev == NULL)
-               return;
-       if (dev->udev == NULL)
-               return;
-
-       if (atomic_read(&dev->devlist_count) > 0) {
-               mutex_lock(&cx231xx_devlist_mutex);
-               list_del(&dev->devlist);
-               atomic_dec(&dev->devlist_count);
-               mutex_unlock(&cx231xx_devlist_mutex);
-       }
-};
-
-void cx231xx_add_into_devlist(struct cx231xx *dev)
-{
-       mutex_lock(&cx231xx_devlist_mutex);
-       list_add_tail(&dev->devlist, &cx231xx_devlist);
-       atomic_inc(&dev->devlist_count);
-       mutex_unlock(&cx231xx_devlist_mutex);
-};
-
-static LIST_HEAD(cx231xx_extension_devlist);
-
-int cx231xx_register_extension(struct cx231xx_ops *ops)
-{
-       struct cx231xx *dev = NULL;
-
-       mutex_lock(&cx231xx_devlist_mutex);
-       list_add_tail(&ops->next, &cx231xx_extension_devlist);
-       list_for_each_entry(dev, &cx231xx_devlist, devlist)
-               ops->init(dev);
-
-       printk(KERN_INFO DRIVER_NAME ": %s initialized\n", ops->name);
-       mutex_unlock(&cx231xx_devlist_mutex);
-       return 0;
-}
-EXPORT_SYMBOL(cx231xx_register_extension);
-
-void cx231xx_unregister_extension(struct cx231xx_ops *ops)
-{
-       struct cx231xx *dev = NULL;
-
-       mutex_lock(&cx231xx_devlist_mutex);
-       list_for_each_entry(dev, &cx231xx_devlist, devlist)
-               ops->fini(dev);
-
-
-       printk(KERN_INFO DRIVER_NAME ": %s removed\n", ops->name);
-       list_del(&ops->next);
-       mutex_unlock(&cx231xx_devlist_mutex);
-}
-EXPORT_SYMBOL(cx231xx_unregister_extension);
-
-void cx231xx_init_extension(struct cx231xx *dev)
-{
-       struct cx231xx_ops *ops = NULL;
-
-       mutex_lock(&cx231xx_devlist_mutex);
-       if (!list_empty(&cx231xx_extension_devlist)) {
-               list_for_each_entry(ops, &cx231xx_extension_devlist, next) {
-                       if (ops->init)
-                               ops->init(dev);
-               }
-       }
-       mutex_unlock(&cx231xx_devlist_mutex);
-}
-
-void cx231xx_close_extension(struct cx231xx *dev)
-{
-       struct cx231xx_ops *ops = NULL;
-
-       mutex_lock(&cx231xx_devlist_mutex);
-       if (!list_empty(&cx231xx_extension_devlist)) {
-               list_for_each_entry(ops, &cx231xx_extension_devlist, next) {
-                       if (ops->fini)
-                               ops->fini(dev);
-               }
-       }
-       mutex_unlock(&cx231xx_devlist_mutex);
-}
-
-/****************************************************************
-*               U S B related functions                         *
-*****************************************************************/
-int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus,
-                            struct cx231xx_i2c_xfer_data *req_data)
-{
-       int status = 0;
-       struct cx231xx *dev = i2c_bus->dev;
-       struct VENDOR_REQUEST_IN ven_req;
-
-       u8 saddr_len = 0;
-       u8 _i2c_period = 0;
-       u8 _i2c_nostop = 0;
-       u8 _i2c_reserve = 0;
-
-       if (dev->state & DEV_DISCONNECTED)
-               return -ENODEV;
-
-       /* Get the I2C period, nostop and reserve parameters */
-       _i2c_period = i2c_bus->i2c_period;
-       _i2c_nostop = i2c_bus->i2c_nostop;
-       _i2c_reserve = i2c_bus->i2c_reserve;
-
-       saddr_len = req_data->saddr_len;
-
-       /* Set wValue */
-       if (saddr_len == 1)     /* need check saddr_len == 0  */
-               ven_req.wValue =
-                   req_data->
-                   dev_addr << 9 | _i2c_period << 4 | saddr_len << 2 |
-                   _i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6;
-       else
-               ven_req.wValue =
-                   req_data->
-                   dev_addr << 9 | _i2c_period << 4 | saddr_len << 2 |
-                   _i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6;
-
-       /* set channel number */
-       if (req_data->direction & I2C_M_RD) {
-               /* channel number, for read,spec required channel_num +4 */
-               ven_req.bRequest = i2c_bus->nr + 4;
-       } else
-               ven_req.bRequest = i2c_bus->nr; /* channel number,  */
-
-       /* set index value */
-       switch (saddr_len) {
-       case 0:
-               ven_req.wIndex = 0;     /* need check */
-               break;
-       case 1:
-               ven_req.wIndex = (req_data->saddr_dat & 0xff);
-               break;
-       case 2:
-               ven_req.wIndex = req_data->saddr_dat;
-               break;
-       }
-
-       /* set wLength value */
-       ven_req.wLength = req_data->buf_size;
-
-       /* set bData value */
-       ven_req.bData = 0;
-
-       /* set the direction */
-       if (req_data->direction) {
-               ven_req.direction = USB_DIR_IN;
-               memset(req_data->p_buffer, 0x00, ven_req.wLength);
-       } else
-               ven_req.direction = USB_DIR_OUT;
-
-       /* set the buffer for read / write */
-       ven_req.pBuff = req_data->p_buffer;
-
-
-       /* call common vendor command request */
-       status = cx231xx_send_vendor_cmd(dev, &ven_req);
-       if (status < 0) {
-               cx231xx_info
-                   ("UsbInterface::sendCommand, failed with status -%d\n",
-                    status);
-       }
-
-       return status;
-}
-EXPORT_SYMBOL_GPL(cx231xx_send_usb_command);
-
-/*
- * Sends/Receives URB control messages, assuring to use a kalloced buffer
- * for all operations (dev->urb_buf), to avoid using stacked buffers, as
- * they aren't safe for usage with USB, due to DMA restrictions.
- * Also implements the debug code for control URB's.
- */
-static int __usb_control_msg(struct cx231xx *dev, unsigned int pipe,
-       __u8 request, __u8 requesttype, __u16 value, __u16 index,
-       void *data, __u16 size, int timeout)
-{
-       int rc, i;
-
-       if (reg_debug) {
-               printk(KERN_DEBUG "%s: (pipe 0x%08x): "
-                               "%s:  %02x %02x %02x %02x %02x %02x %02x %02x ",
-                               dev->name,
-                               pipe,
-                               (requesttype & USB_DIR_IN) ? "IN" : "OUT",
-                               requesttype,
-                               request,
-                               value & 0xff, value >> 8,
-                               index & 0xff, index >> 8,
-                               size & 0xff, size >> 8);
-               if (!(requesttype & USB_DIR_IN)) {
-                       printk(KERN_CONT ">>>");
-                       for (i = 0; i < size; i++)
-                               printk(KERN_CONT " %02x",
-                                      ((unsigned char *)data)[i]);
-               }
-       }
-
-       /* Do the real call to usb_control_msg */
-       mutex_lock(&dev->ctrl_urb_lock);
-       if (!(requesttype & USB_DIR_IN) && size)
-               memcpy(dev->urb_buf, data, size);
-       rc = usb_control_msg(dev->udev, pipe, request, requesttype, value,
-                            index, dev->urb_buf, size, timeout);
-       if ((requesttype & USB_DIR_IN) && size)
-               memcpy(data, dev->urb_buf, size);
-       mutex_unlock(&dev->ctrl_urb_lock);
-
-       if (reg_debug) {
-               if (unlikely(rc < 0)) {
-                       printk(KERN_CONT "FAILED!\n");
-                       return rc;
-               }
-
-               if ((requesttype & USB_DIR_IN)) {
-                       printk(KERN_CONT "<<<");
-                       for (i = 0; i < size; i++)
-                               printk(KERN_CONT " %02x",
-                                      ((unsigned char *)data)[i]);
-               }
-               printk(KERN_CONT "\n");
-       }
-
-       return rc;
-}
-
-
-/*
- * cx231xx_read_ctrl_reg()
- * reads data from the usb device specifying bRequest and wValue
- */
-int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg,
-                         char *buf, int len)
-{
-       u8 val = 0;
-       int ret;
-       int pipe = usb_rcvctrlpipe(dev->udev, 0);
-
-       if (dev->state & DEV_DISCONNECTED)
-               return -ENODEV;
-
-       if (len > URB_MAX_CTRL_SIZE)
-               return -EINVAL;
-
-       switch (len) {
-       case 1:
-               val = ENABLE_ONE_BYTE;
-               break;
-       case 2:
-               val = ENABLE_TWE_BYTE;
-               break;
-       case 3:
-               val = ENABLE_THREE_BYTE;
-               break;
-       case 4:
-               val = ENABLE_FOUR_BYTE;
-               break;
-       default:
-               val = 0xFF;     /* invalid option */
-       }
-
-       if (val == 0xFF)
-               return -EINVAL;
-
-       ret = __usb_control_msg(dev, pipe, req,
-                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             val, reg, buf, len, HZ);
-       return ret;
-}
-
-int cx231xx_send_vendor_cmd(struct cx231xx *dev,
-                               struct VENDOR_REQUEST_IN *ven_req)
-{
-       int ret;
-       int pipe = 0;
-       int unsend_size = 0;
-       u8 *pdata;
-
-       if (dev->state & DEV_DISCONNECTED)
-               return -ENODEV;
-
-       if ((ven_req->wLength > URB_MAX_CTRL_SIZE))
-               return -EINVAL;
-
-       if (ven_req->direction)
-               pipe = usb_rcvctrlpipe(dev->udev, 0);
-       else
-               pipe = usb_sndctrlpipe(dev->udev, 0);
-
-       /*
-        * If the cx23102 read more than 4 bytes with i2c bus,
-        * need chop to 4 byte per request
-        */
-       if ((ven_req->wLength > 4) && ((ven_req->bRequest == 0x4) ||
-                                       (ven_req->bRequest == 0x5) ||
-                                       (ven_req->bRequest == 0x6))) {
-               unsend_size = 0;
-               pdata = ven_req->pBuff;
-
-
-               unsend_size = ven_req->wLength;
-
-               /* the first package */
-               ven_req->wValue = ven_req->wValue & 0xFFFB;
-               ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x2;
-               ret = __usb_control_msg(dev, pipe, ven_req->bRequest,
-                       ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       ven_req->wValue, ven_req->wIndex, pdata,
-                       0x0004, HZ);
-               unsend_size = unsend_size - 4;
-
-               /* the middle package */
-               ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x42;
-               while (unsend_size - 4 > 0) {
-                       pdata = pdata + 4;
-                       ret = __usb_control_msg(dev, pipe,
-                               ven_req->bRequest,
-                               ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                               ven_req->wValue, ven_req->wIndex, pdata,
-                               0x0004, HZ);
-                       unsend_size = unsend_size - 4;
-               }
-
-               /* the last package */
-               ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x40;
-               pdata = pdata + 4;
-               ret = __usb_control_msg(dev, pipe, ven_req->bRequest,
-                       ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       ven_req->wValue, ven_req->wIndex, pdata,
-                       unsend_size, HZ);
-       } else {
-               ret = __usb_control_msg(dev, pipe, ven_req->bRequest,
-                               ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                               ven_req->wValue, ven_req->wIndex,
-                               ven_req->pBuff, ven_req->wLength, HZ);
-       }
-
-       return ret;
-}
-
-/*
- * cx231xx_write_ctrl_reg()
- * sends data to the usb device, specifying bRequest
- */
-int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf,
-                          int len)
-{
-       u8 val = 0;
-       int ret;
-       int pipe = usb_sndctrlpipe(dev->udev, 0);
-
-       if (dev->state & DEV_DISCONNECTED)
-               return -ENODEV;
-
-       if ((len < 1) || (len > URB_MAX_CTRL_SIZE))
-               return -EINVAL;
-
-       switch (len) {
-       case 1:
-               val = ENABLE_ONE_BYTE;
-               break;
-       case 2:
-               val = ENABLE_TWE_BYTE;
-               break;
-       case 3:
-               val = ENABLE_THREE_BYTE;
-               break;
-       case 4:
-               val = ENABLE_FOUR_BYTE;
-               break;
-       default:
-               val = 0xFF;     /* invalid option */
-       }
-
-       if (val == 0xFF)
-               return -EINVAL;
-
-       if (reg_debug) {
-               int byte;
-
-               cx231xx_isocdbg("(pipe 0x%08x): "
-                       "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>",
-                       pipe,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       req, 0, val, reg & 0xff,
-                       reg >> 8, len & 0xff, len >> 8);
-
-               for (byte = 0; byte < len; byte++)
-                       cx231xx_isocdbg(" %02x", (unsigned char)buf[byte]);
-               cx231xx_isocdbg("\n");
-       }
-
-       ret = __usb_control_msg(dev, pipe, req,
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             val, reg, buf, len, HZ);
-
-       return ret;
-}
-
-/****************************************************************
-*           USB Alternate Setting functions                     *
-*****************************************************************/
-
-int cx231xx_set_video_alternate(struct cx231xx *dev)
-{
-       int errCode, prev_alt = dev->video_mode.alt;
-       unsigned int min_pkt_size = dev->width * 2 + 4;
-       u32 usb_interface_index = 0;
-
-       /* When image size is bigger than a certain value,
-          the frame size should be increased, otherwise, only
-          green screen will be received.
-        */
-       if (dev->width * 2 * dev->height > 720 * 240 * 2)
-               min_pkt_size *= 2;
-
-       if (dev->width > 360) {
-               /* resolutions: 720,704,640 */
-               dev->video_mode.alt = 3;
-       } else if (dev->width > 180) {
-               /* resolutions: 360,352,320,240 */
-               dev->video_mode.alt = 2;
-       } else if (dev->width > 0) {
-               /* resolutions: 180,176,160,128,88 */
-               dev->video_mode.alt = 1;
-       } else {
-               /* Change to alt0 BULK to release USB bandwidth */
-               dev->video_mode.alt = 0;
-       }
-
-       if (dev->USE_ISO == 0)
-               dev->video_mode.alt = 0;
-
-       cx231xx_coredbg("dev->video_mode.alt= %d\n", dev->video_mode.alt);
-
-       /* Get the correct video interface Index */
-       usb_interface_index =
-           dev->current_pcb_config.hs_config_info[0].interface_info.
-           video_index + 1;
-
-       if (dev->video_mode.alt != prev_alt) {
-               cx231xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
-                               min_pkt_size, dev->video_mode.alt);
-
-               if (dev->video_mode.alt_max_pkt_size != NULL)
-                       dev->video_mode.max_pkt_size =
-                       dev->video_mode.alt_max_pkt_size[dev->video_mode.alt];
-               cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
-                               dev->video_mode.alt,
-                               dev->video_mode.max_pkt_size);
-               errCode =
-                   usb_set_interface(dev->udev, usb_interface_index,
-                                     dev->video_mode.alt);
-               if (errCode < 0) {
-                       cx231xx_errdev
-                           ("cannot change alt number to %d (error=%i)\n",
-                            dev->video_mode.alt, errCode);
-                       return errCode;
-               }
-       }
-       return 0;
-}
-
-int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt)
-{
-       int status = 0;
-       u32 usb_interface_index = 0;
-       u32 max_pkt_size = 0;
-
-       switch (index) {
-       case INDEX_TS1:
-               usb_interface_index =
-                   dev->current_pcb_config.hs_config_info[0].interface_info.
-                   ts1_index + 1;
-               dev->ts1_mode.alt = alt;
-               if (dev->ts1_mode.alt_max_pkt_size != NULL)
-                       max_pkt_size = dev->ts1_mode.max_pkt_size =
-                           dev->ts1_mode.alt_max_pkt_size[dev->ts1_mode.alt];
-               break;
-       case INDEX_TS2:
-               usb_interface_index =
-                   dev->current_pcb_config.hs_config_info[0].interface_info.
-                   ts2_index + 1;
-               break;
-       case INDEX_AUDIO:
-               usb_interface_index =
-                   dev->current_pcb_config.hs_config_info[0].interface_info.
-                   audio_index + 1;
-               dev->adev.alt = alt;
-               if (dev->adev.alt_max_pkt_size != NULL)
-                       max_pkt_size = dev->adev.max_pkt_size =
-                           dev->adev.alt_max_pkt_size[dev->adev.alt];
-               break;
-       case INDEX_VIDEO:
-               usb_interface_index =
-                   dev->current_pcb_config.hs_config_info[0].interface_info.
-                   video_index + 1;
-               dev->video_mode.alt = alt;
-               if (dev->video_mode.alt_max_pkt_size != NULL)
-                       max_pkt_size = dev->video_mode.max_pkt_size =
-                           dev->video_mode.alt_max_pkt_size[dev->video_mode.
-                                                            alt];
-               break;
-       case INDEX_VANC:
-               if (dev->board.no_alt_vanc)
-                       return 0;
-               usb_interface_index =
-                   dev->current_pcb_config.hs_config_info[0].interface_info.
-                   vanc_index + 1;
-               dev->vbi_mode.alt = alt;
-               if (dev->vbi_mode.alt_max_pkt_size != NULL)
-                       max_pkt_size = dev->vbi_mode.max_pkt_size =
-                           dev->vbi_mode.alt_max_pkt_size[dev->vbi_mode.alt];
-               break;
-       case INDEX_HANC:
-               usb_interface_index =
-                   dev->current_pcb_config.hs_config_info[0].interface_info.
-                   hanc_index + 1;
-               dev->sliced_cc_mode.alt = alt;
-               if (dev->sliced_cc_mode.alt_max_pkt_size != NULL)
-                       max_pkt_size = dev->sliced_cc_mode.max_pkt_size =
-                           dev->sliced_cc_mode.alt_max_pkt_size[dev->
-                                                                sliced_cc_mode.
-                                                                alt];
-               break;
-       default:
-               break;
-       }
-
-       if (alt > 0 && max_pkt_size == 0) {
-               cx231xx_errdev
-               ("can't change interface %d alt no. to %d: Max. Pkt size = 0\n",
-               usb_interface_index, alt);
-               /*To workaround error number=-71 on EP0 for videograbber,
-                need add following codes.*/
-               if (dev->board.no_alt_vanc)
-                       return -1;
-       }
-
-       cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u,"
-                       "Interface = %d\n", alt, max_pkt_size,
-                       usb_interface_index);
-
-       if (usb_interface_index > 0) {
-               status = usb_set_interface(dev->udev, usb_interface_index, alt);
-               if (status < 0) {
-                       cx231xx_errdev
-                       ("can't change interface %d alt no. to %d (err=%i)\n",
-                       usb_interface_index, alt, status);
-                       return status;
-               }
-       }
-
-       return status;
-}
-EXPORT_SYMBOL_GPL(cx231xx_set_alt_setting);
-
-int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio)
-{
-       int rc = 0;
-
-       if (!gpio)
-               return rc;
-
-       /* Send GPIO reset sequences specified at board entry */
-       while (gpio->sleep >= 0) {
-               rc = cx231xx_set_gpio_value(dev, gpio->bit, gpio->val);
-               if (rc < 0)
-                       return rc;
-
-               if (gpio->sleep > 0)
-                       msleep(gpio->sleep);
-
-               gpio++;
-       }
-       return rc;
-}
-
-int cx231xx_demod_reset(struct cx231xx *dev)
-{
-
-       u8 status = 0;
-       u8 value[4] = { 0, 0, 0, 0 };
-
-       status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
-                                value, 4);
-
-       cx231xx_coredbg("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN,
-                       value[0], value[1], value[2], value[3]);
-
-       cx231xx_coredbg("Enter cx231xx_demod_reset()\n");
-
-               value[1] = (u8) 0x3;
-               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                               PWR_CTL_EN, value, 4);
-                       msleep(10);
-
-               value[1] = (u8) 0x0;
-               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                               PWR_CTL_EN, value, 4);
-                       msleep(10);
-
-               value[1] = (u8) 0x3;
-               status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                                               PWR_CTL_EN, value, 4);
-                       msleep(10);
-
-
-
-       status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
-                                value, 4);
-
-       cx231xx_coredbg("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN,
-                       value[0], value[1], value[2], value[3]);
-
-       return status;
-}
-EXPORT_SYMBOL_GPL(cx231xx_demod_reset);
-int is_fw_load(struct cx231xx *dev)
-{
-       return cx231xx_check_fw(dev);
-}
-EXPORT_SYMBOL_GPL(is_fw_load);
-
-int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode)
-{
-       int errCode = 0;
-
-       if (dev->mode == set_mode)
-               return 0;
-
-       if (set_mode == CX231XX_SUSPEND) {
-               /* Set the chip in power saving mode */
-               dev->mode = set_mode;
-       }
-
-       /* Resource is locked */
-       if (dev->mode != CX231XX_SUSPEND)
-               return -EINVAL;
-
-       dev->mode = set_mode;
-
-       if (dev->mode == CX231XX_DIGITAL_MODE)/* Set Digital power mode */ {
-       /* set AGC mode to Digital */
-               switch (dev->model) {
-               case CX231XX_BOARD_CNXT_CARRAERA:
-               case CX231XX_BOARD_CNXT_RDE_250:
-               case CX231XX_BOARD_CNXT_SHELBY:
-               case CX231XX_BOARD_CNXT_RDU_250:
-               errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
-                       break;
-               case CX231XX_BOARD_CNXT_RDE_253S:
-               case CX231XX_BOARD_CNXT_RDU_253S:
-                       errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);
-                       break;
-               case CX231XX_BOARD_HAUPPAUGE_EXETER:
-                       errCode = cx231xx_set_power_mode(dev,
-                                               POLARIS_AVMODE_DIGITAL);
-                       break;
-               default:
-                       break;
-               }
-       } else/* Set Analog Power mode */ {
-       /* set AGC mode to Analog */
-               switch (dev->model) {
-               case CX231XX_BOARD_CNXT_CARRAERA:
-               case CX231XX_BOARD_CNXT_RDE_250:
-               case CX231XX_BOARD_CNXT_SHELBY:
-               case CX231XX_BOARD_CNXT_RDU_250:
-               errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);
-                       break;
-               case CX231XX_BOARD_CNXT_RDE_253S:
-               case CX231XX_BOARD_CNXT_RDU_253S:
-               case CX231XX_BOARD_HAUPPAUGE_EXETER:
-               case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
-               case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
-               case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
-               errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       return errCode ? -EINVAL : 0;
-}
-EXPORT_SYMBOL_GPL(cx231xx_set_mode);
-
-int cx231xx_ep5_bulkout(struct cx231xx *dev, u8 *firmware, u16 size)
-{
-       int errCode = 0;
-       int actlen, ret = -ENOMEM;
-       u32 *buffer;
-
-       buffer = kzalloc(4096, GFP_KERNEL);
-       if (buffer == NULL) {
-               cx231xx_info("out of mem\n");
-               return -ENOMEM;
-       }
-       memcpy(&buffer[0], firmware, 4096);
-
-       ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 5),
-                       buffer, 4096, &actlen, 2000);
-
-       if (ret)
-               cx231xx_info("bulk message failed: %d (%d/%d)", ret,
-                               size, actlen);
-       else {
-               errCode = actlen != size ? -1 : 0;
-       }
-       kfree(buffer);
-       return errCode;
-}
-
-/*****************************************************************
-*                URB Streaming functions                         *
-******************************************************************/
-
-/*
- * IRQ callback, called by URB callback
- */
-static void cx231xx_isoc_irq_callback(struct urb *urb)
-{
-       struct cx231xx_dmaqueue *dma_q = urb->context;
-       struct cx231xx_video_mode *vmode =
-           container_of(dma_q, struct cx231xx_video_mode, vidq);
-       struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode);
-       int i;
-
-       switch (urb->status) {
-       case 0:         /* success */
-       case -ETIMEDOUT:        /* NAK */
-               break;
-       case -ECONNRESET:       /* kill */
-       case -ENOENT:
-       case -ESHUTDOWN:
-               return;
-       default:                /* error */
-               cx231xx_isocdbg("urb completition error %d.\n", urb->status);
-               break;
-       }
-
-       /* Copy data from URB */
-       spin_lock(&dev->video_mode.slock);
-       dev->video_mode.isoc_ctl.isoc_copy(dev, urb);
-       spin_unlock(&dev->video_mode.slock);
-
-       /* Reset urb buffers */
-       for (i = 0; i < urb->number_of_packets; i++) {
-               urb->iso_frame_desc[i].status = 0;
-               urb->iso_frame_desc[i].actual_length = 0;
-       }
-
-       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (urb->status) {
-               cx231xx_isocdbg("urb resubmit failed (error=%i)\n",
-                               urb->status);
-       }
-}
-/*****************************************************************
-*                URB Streaming functions                         *
-******************************************************************/
-
-/*
- * IRQ callback, called by URB callback
- */
-static void cx231xx_bulk_irq_callback(struct urb *urb)
-{
-       struct cx231xx_dmaqueue *dma_q = urb->context;
-       struct cx231xx_video_mode *vmode =
-           container_of(dma_q, struct cx231xx_video_mode, vidq);
-       struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode);
-
-       switch (urb->status) {
-       case 0:         /* success */
-       case -ETIMEDOUT:        /* NAK */
-               break;
-       case -ECONNRESET:       /* kill */
-       case -ENOENT:
-       case -ESHUTDOWN:
-               return;
-       default:                /* error */
-               cx231xx_isocdbg("urb completition error %d.\n", urb->status);
-               break;
-       }
-
-       /* Copy data from URB */
-       spin_lock(&dev->video_mode.slock);
-       dev->video_mode.bulk_ctl.bulk_copy(dev, urb);
-       spin_unlock(&dev->video_mode.slock);
-
-       /* Reset urb buffers */
-       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (urb->status) {
-               cx231xx_isocdbg("urb resubmit failed (error=%i)\n",
-                               urb->status);
-       }
-}
-/*
- * Stop and Deallocate URBs
- */
-void cx231xx_uninit_isoc(struct cx231xx *dev)
-{
-       struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq;
-       struct urb *urb;
-       int i;
-
-       cx231xx_isocdbg("cx231xx: called cx231xx_uninit_isoc\n");
-
-       dev->video_mode.isoc_ctl.nfields = -1;
-       for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
-               urb = dev->video_mode.isoc_ctl.urb[i];
-               if (urb) {
-                       if (!irqs_disabled())
-                               usb_kill_urb(urb);
-                       else
-                               usb_unlink_urb(urb);
-
-                       if (dev->video_mode.isoc_ctl.transfer_buffer[i]) {
-                               usb_free_coherent(dev->udev,
-                                                 urb->transfer_buffer_length,
-                                                 dev->video_mode.isoc_ctl.
-                                                 transfer_buffer[i],
-                                                 urb->transfer_dma);
-                       }
-                       usb_free_urb(urb);
-                       dev->video_mode.isoc_ctl.urb[i] = NULL;
-               }
-               dev->video_mode.isoc_ctl.transfer_buffer[i] = NULL;
-       }
-
-       kfree(dev->video_mode.isoc_ctl.urb);
-       kfree(dev->video_mode.isoc_ctl.transfer_buffer);
-       kfree(dma_q->p_left_data);
-
-       dev->video_mode.isoc_ctl.urb = NULL;
-       dev->video_mode.isoc_ctl.transfer_buffer = NULL;
-       dev->video_mode.isoc_ctl.num_bufs = 0;
-       dma_q->p_left_data = NULL;
-
-       if (dev->mode_tv == 0)
-               cx231xx_capture_start(dev, 0, Raw_Video);
-       else
-               cx231xx_capture_start(dev, 0, TS1_serial_mode);
-
-
-}
-EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc);
-
-/*
- * Stop and Deallocate URBs
- */
-void cx231xx_uninit_bulk(struct cx231xx *dev)
-{
-       struct urb *urb;
-       int i;
-
-       cx231xx_isocdbg("cx231xx: called cx231xx_uninit_bulk\n");
-
-       dev->video_mode.bulk_ctl.nfields = -1;
-       for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) {
-               urb = dev->video_mode.bulk_ctl.urb[i];
-               if (urb) {
-                       if (!irqs_disabled())
-                               usb_kill_urb(urb);
-                       else
-                               usb_unlink_urb(urb);
-
-                       if (dev->video_mode.bulk_ctl.transfer_buffer[i]) {
-                               usb_free_coherent(dev->udev,
-                                               urb->transfer_buffer_length,
-                                               dev->video_mode.isoc_ctl.
-                                               transfer_buffer[i],
-                                               urb->transfer_dma);
-                       }
-                       usb_free_urb(urb);
-                       dev->video_mode.bulk_ctl.urb[i] = NULL;
-               }
-               dev->video_mode.bulk_ctl.transfer_buffer[i] = NULL;
-       }
-
-       kfree(dev->video_mode.bulk_ctl.urb);
-       kfree(dev->video_mode.bulk_ctl.transfer_buffer);
-
-       dev->video_mode.bulk_ctl.urb = NULL;
-       dev->video_mode.bulk_ctl.transfer_buffer = NULL;
-       dev->video_mode.bulk_ctl.num_bufs = 0;
-
-       if (dev->mode_tv == 0)
-               cx231xx_capture_start(dev, 0, Raw_Video);
-       else
-               cx231xx_capture_start(dev, 0, TS1_serial_mode);
-
-
-}
-EXPORT_SYMBOL_GPL(cx231xx_uninit_bulk);
-
-/*
- * Allocate URBs and start IRQ
- */
-int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
-                     int num_bufs, int max_pkt_size,
-                     int (*isoc_copy) (struct cx231xx *dev, struct urb *urb))
-{
-       struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq;
-       int i;
-       int sb_size, pipe;
-       struct urb *urb;
-       int j, k;
-       int rc;
-
-       /* De-allocates all pending stuff */
-       cx231xx_uninit_isoc(dev);
-
-       dma_q->p_left_data = kzalloc(4096, GFP_KERNEL);
-       if (dma_q->p_left_data == NULL) {
-               cx231xx_info("out of mem\n");
-               return -ENOMEM;
-       }
-
-
-
-       dev->video_mode.isoc_ctl.isoc_copy = isoc_copy;
-       dev->video_mode.isoc_ctl.num_bufs = num_bufs;
-       dma_q->pos = 0;
-       dma_q->is_partial_line = 0;
-       dma_q->last_sav = 0;
-       dma_q->current_field = -1;
-       dma_q->field1_done = 0;
-       dma_q->lines_per_field = dev->height / 2;
-       dma_q->bytes_left_in_line = dev->width << 1;
-       dma_q->lines_completed = 0;
-       dma_q->mpeg_buffer_done = 0;
-       dma_q->left_data_count = 0;
-       dma_q->mpeg_buffer_completed = 0;
-       dma_q->add_ps_package_head = CX231XX_NEED_ADD_PS_PACKAGE_HEAD;
-       dma_q->ps_head[0] = 0x00;
-       dma_q->ps_head[1] = 0x00;
-       dma_q->ps_head[2] = 0x01;
-       dma_q->ps_head[3] = 0xBA;
-       for (i = 0; i < 8; i++)
-               dma_q->partial_buf[i] = 0;
-
-       dev->video_mode.isoc_ctl.urb =
-           kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
-       if (!dev->video_mode.isoc_ctl.urb) {
-               cx231xx_errdev("cannot alloc memory for usb buffers\n");
-               return -ENOMEM;
-       }
-
-       dev->video_mode.isoc_ctl.transfer_buffer =
-           kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
-       if (!dev->video_mode.isoc_ctl.transfer_buffer) {
-               cx231xx_errdev("cannot allocate memory for usbtransfer\n");
-               kfree(dev->video_mode.isoc_ctl.urb);
-               return -ENOMEM;
-       }
-
-       dev->video_mode.isoc_ctl.max_pkt_size = max_pkt_size;
-       dev->video_mode.isoc_ctl.buf = NULL;
-
-       sb_size = max_packets * dev->video_mode.isoc_ctl.max_pkt_size;
-
-       if (dev->mode_tv == 1)
-               dev->video_mode.end_point_addr = 0x81;
-       else
-               dev->video_mode.end_point_addr = 0x84;
-
-
-       /* allocate urbs and transfer buffers */
-       for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
-               urb = usb_alloc_urb(max_packets, GFP_KERNEL);
-               if (!urb) {
-                       cx231xx_err("cannot alloc isoc_ctl.urb %i\n", i);
-                       cx231xx_uninit_isoc(dev);
-                       return -ENOMEM;
-               }
-               dev->video_mode.isoc_ctl.urb[i] = urb;
-
-               dev->video_mode.isoc_ctl.transfer_buffer[i] =
-                   usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,
-                                      &urb->transfer_dma);
-               if (!dev->video_mode.isoc_ctl.transfer_buffer[i]) {
-                       cx231xx_err("unable to allocate %i bytes for transfer"
-                                   " buffer %i%s\n",
-                                   sb_size, i,
-                                   in_interrupt() ? " while in int" : "");
-                       cx231xx_uninit_isoc(dev);
-                       return -ENOMEM;
-               }
-               memset(dev->video_mode.isoc_ctl.transfer_buffer[i], 0, sb_size);
-
-               pipe =
-                   usb_rcvisocpipe(dev->udev, dev->video_mode.end_point_addr);
-
-               usb_fill_int_urb(urb, dev->udev, pipe,
-                                dev->video_mode.isoc_ctl.transfer_buffer[i],
-                                sb_size, cx231xx_isoc_irq_callback, dma_q, 1);
-
-               urb->number_of_packets = max_packets;
-               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-
-               k = 0;
-               for (j = 0; j < max_packets; j++) {
-                       urb->iso_frame_desc[j].offset = k;
-                       urb->iso_frame_desc[j].length =
-                           dev->video_mode.isoc_ctl.max_pkt_size;
-                       k += dev->video_mode.isoc_ctl.max_pkt_size;
-               }
-       }
-
-       init_waitqueue_head(&dma_q->wq);
-
-       /* submit urbs and enables IRQ */
-       for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
-               rc = usb_submit_urb(dev->video_mode.isoc_ctl.urb[i],
-                                   GFP_ATOMIC);
-               if (rc) {
-                       cx231xx_err("submit of urb %i failed (error=%i)\n", i,
-                                   rc);
-                       cx231xx_uninit_isoc(dev);
-                       return rc;
-               }
-       }
-
-       if (dev->mode_tv == 0)
-               cx231xx_capture_start(dev, 1, Raw_Video);
-       else
-               cx231xx_capture_start(dev, 1, TS1_serial_mode);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(cx231xx_init_isoc);
-
-/*
- * Allocate URBs and start IRQ
- */
-int cx231xx_init_bulk(struct cx231xx *dev, int max_packets,
-                     int num_bufs, int max_pkt_size,
-                     int (*bulk_copy) (struct cx231xx *dev, struct urb *urb))
-{
-       struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq;
-       int i;
-       int sb_size, pipe;
-       struct urb *urb;
-       int rc;
-
-       dev->video_input = dev->video_input > 2 ? 2 : dev->video_input;
-
-       cx231xx_coredbg("Setting Video mux to %d\n", dev->video_input);
-
-       video_mux(dev, dev->video_input);
-
-       /* De-allocates all pending stuff */
-       cx231xx_uninit_bulk(dev);
-
-       dev->video_mode.bulk_ctl.bulk_copy = bulk_copy;
-       dev->video_mode.bulk_ctl.num_bufs = num_bufs;
-       dma_q->pos = 0;
-       dma_q->is_partial_line = 0;
-       dma_q->last_sav = 0;
-       dma_q->current_field = -1;
-       dma_q->field1_done = 0;
-       dma_q->lines_per_field = dev->height / 2;
-       dma_q->bytes_left_in_line = dev->width << 1;
-       dma_q->lines_completed = 0;
-       dma_q->mpeg_buffer_done = 0;
-       dma_q->left_data_count = 0;
-       dma_q->mpeg_buffer_completed = 0;
-       dma_q->ps_head[0] = 0x00;
-       dma_q->ps_head[1] = 0x00;
-       dma_q->ps_head[2] = 0x01;
-       dma_q->ps_head[3] = 0xBA;
-       for (i = 0; i < 8; i++)
-               dma_q->partial_buf[i] = 0;
-
-       dev->video_mode.bulk_ctl.urb =
-           kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
-       if (!dev->video_mode.bulk_ctl.urb) {
-               cx231xx_errdev("cannot alloc memory for usb buffers\n");
-               return -ENOMEM;
-       }
-
-       dev->video_mode.bulk_ctl.transfer_buffer =
-           kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
-       if (!dev->video_mode.bulk_ctl.transfer_buffer) {
-               cx231xx_errdev("cannot allocate memory for usbtransfer\n");
-               kfree(dev->video_mode.bulk_ctl.urb);
-               return -ENOMEM;
-       }
-
-       dev->video_mode.bulk_ctl.max_pkt_size = max_pkt_size;
-       dev->video_mode.bulk_ctl.buf = NULL;
-
-       sb_size = max_packets * dev->video_mode.bulk_ctl.max_pkt_size;
-
-       if (dev->mode_tv == 1)
-               dev->video_mode.end_point_addr = 0x81;
-       else
-               dev->video_mode.end_point_addr = 0x84;
-
-
-       /* allocate urbs and transfer buffers */
-       for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) {
-               urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (!urb) {
-                       cx231xx_err("cannot alloc bulk_ctl.urb %i\n", i);
-                       cx231xx_uninit_bulk(dev);
-                       return -ENOMEM;
-               }
-               dev->video_mode.bulk_ctl.urb[i] = urb;
-               urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
-
-               dev->video_mode.bulk_ctl.transfer_buffer[i] =
-                   usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,
-                                    &urb->transfer_dma);
-               if (!dev->video_mode.bulk_ctl.transfer_buffer[i]) {
-                       cx231xx_err("unable to allocate %i bytes for transfer"
-                                   " buffer %i%s\n",
-                                   sb_size, i,
-                                   in_interrupt() ? " while in int" : "");
-                       cx231xx_uninit_bulk(dev);
-                       return -ENOMEM;
-               }
-               memset(dev->video_mode.bulk_ctl.transfer_buffer[i], 0, sb_size);
-
-               pipe = usb_rcvbulkpipe(dev->udev,
-                                dev->video_mode.end_point_addr);
-               usb_fill_bulk_urb(urb, dev->udev, pipe,
-                                 dev->video_mode.bulk_ctl.transfer_buffer[i],
-                                 sb_size, cx231xx_bulk_irq_callback, dma_q);
-       }
-
-       init_waitqueue_head(&dma_q->wq);
-
-       /* submit urbs and enables IRQ */
-       for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) {
-               rc = usb_submit_urb(dev->video_mode.bulk_ctl.urb[i],
-                                   GFP_ATOMIC);
-               if (rc) {
-                       cx231xx_err("submit of urb %i failed (error=%i)\n", i,
-                                   rc);
-                       cx231xx_uninit_bulk(dev);
-                       return rc;
-               }
-       }
-
-       if (dev->mode_tv == 0)
-               cx231xx_capture_start(dev, 1, Raw_Video);
-       else
-               cx231xx_capture_start(dev, 1, TS1_serial_mode);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(cx231xx_init_bulk);
-void cx231xx_stop_TS1(struct cx231xx *dev)
-{
-       u8 val[4] = { 0, 0, 0, 0 };
-
-       val[0] = 0x00;
-       val[1] = 0x03;
-       val[2] = 0x00;
-       val[3] = 0x00;
-       cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                       TS_MODE_REG, val, 4);
-
-       val[0] = 0x00;
-       val[1] = 0x70;
-       val[2] = 0x04;
-       val[3] = 0x00;
-       cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                       TS1_CFG_REG, val, 4);
-}
-/* EXPORT_SYMBOL_GPL(cx231xx_stop_TS1); */
-void cx231xx_start_TS1(struct cx231xx *dev)
-{
-       u8 val[4] = { 0, 0, 0, 0 };
-
-       val[0] = 0x03;
-       val[1] = 0x03;
-       val[2] = 0x00;
-       val[3] = 0x00;
-       cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                       TS_MODE_REG, val, 4);
-
-       val[0] = 0x04;
-       val[1] = 0xA3;
-       val[2] = 0x3B;
-       val[3] = 0x00;
-       cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
-                       TS1_CFG_REG, val, 4);
-}
-/* EXPORT_SYMBOL_GPL(cx231xx_start_TS1); */
-/*****************************************************************
-*             Device Init/UnInit functions                       *
-******************************************************************/
-int cx231xx_dev_init(struct cx231xx *dev)
-{
-       int errCode = 0;
-
-       /* Initialize I2C bus */
-
-       /* External Master 1 Bus */
-       dev->i2c_bus[0].nr = 0;
-       dev->i2c_bus[0].dev = dev;
-       dev->i2c_bus[0].i2c_period = I2C_SPEED_100K;    /* 100 KHz */
-       dev->i2c_bus[0].i2c_nostop = 0;
-       dev->i2c_bus[0].i2c_reserve = 0;
-
-       /* External Master 2 Bus */
-       dev->i2c_bus[1].nr = 1;
-       dev->i2c_bus[1].dev = dev;
-       dev->i2c_bus[1].i2c_period = I2C_SPEED_100K;    /* 100 KHz */
-       dev->i2c_bus[1].i2c_nostop = 0;
-       dev->i2c_bus[1].i2c_reserve = 0;
-
-       /* Internal Master 3 Bus */
-       dev->i2c_bus[2].nr = 2;
-       dev->i2c_bus[2].dev = dev;
-       dev->i2c_bus[2].i2c_period = I2C_SPEED_100K;    /* 100kHz */
-       dev->i2c_bus[2].i2c_nostop = 0;
-       dev->i2c_bus[2].i2c_reserve = 0;
-
-       /* register I2C buses */
-       cx231xx_i2c_register(&dev->i2c_bus[0]);
-       cx231xx_i2c_register(&dev->i2c_bus[1]);
-       cx231xx_i2c_register(&dev->i2c_bus[2]);
-
-       /* init hardware */
-       /* Note : with out calling set power mode function,
-       afe can not be set up correctly */
-       if (dev->board.external_av) {
-               errCode = cx231xx_set_power_mode(dev,
-                                POLARIS_AVMODE_ENXTERNAL_AV);
-               if (errCode < 0) {
-                       cx231xx_errdev
-                       ("%s: Failed to set Power - errCode [%d]!\n",
-                       __func__, errCode);
-                       return errCode;
-               }
-       } else {
-               errCode = cx231xx_set_power_mode(dev,
-                                POLARIS_AVMODE_ANALOGT_TV);
-               if (errCode < 0) {
-                       cx231xx_errdev
-                       ("%s: Failed to set Power - errCode [%d]!\n",
-                       __func__, errCode);
-                       return errCode;
-               }
-       }
-
-       /* reset the Tuner, if it is a Xceive tuner */
-       if ((dev->board.tuner_type == TUNER_XC5000) ||
-           (dev->board.tuner_type == TUNER_XC2028))
-                       cx231xx_gpio_set(dev, dev->board.tuner_gpio);
-
-       /* initialize Colibri block */
-       errCode = cx231xx_afe_init_super_block(dev, 0x23c);
-       if (errCode < 0) {
-               cx231xx_errdev
-                   ("%s: cx231xx_afe init super block - errCode [%d]!\n",
-                    __func__, errCode);
-               return errCode;
-       }
-       errCode = cx231xx_afe_init_channels(dev);
-       if (errCode < 0) {
-               cx231xx_errdev
-                   ("%s: cx231xx_afe init channels - errCode [%d]!\n",
-                    __func__, errCode);
-               return errCode;
-       }
-
-       /* Set DIF in By pass mode */
-       errCode = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
-       if (errCode < 0) {
-               cx231xx_errdev
-                   ("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n",
-                    __func__, errCode);
-               return errCode;
-       }
-
-       /* I2S block related functions */
-       errCode = cx231xx_i2s_blk_initialize(dev);
-       if (errCode < 0) {
-               cx231xx_errdev
-                   ("%s: cx231xx_i2s block initialize - errCode [%d]!\n",
-                    __func__, errCode);
-               return errCode;
-       }
-
-       /* init control pins */
-       errCode = cx231xx_init_ctrl_pin_status(dev);
-       if (errCode < 0) {
-               cx231xx_errdev("%s: cx231xx_init ctrl pins - errCode [%d]!\n",
-                              __func__, errCode);
-               return errCode;
-       }
-
-       /* set AGC mode to Analog */
-       switch (dev->model) {
-       case CX231XX_BOARD_CNXT_CARRAERA:
-       case CX231XX_BOARD_CNXT_RDE_250:
-       case CX231XX_BOARD_CNXT_SHELBY:
-       case CX231XX_BOARD_CNXT_RDU_250:
-       errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);
-               break;
-       case CX231XX_BOARD_CNXT_RDE_253S:
-       case CX231XX_BOARD_CNXT_RDU_253S:
-       case CX231XX_BOARD_HAUPPAUGE_EXETER:
-       case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
-       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL:
-       case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
-       errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
-               break;
-       default:
-               break;
-       }
-       if (errCode < 0) {
-               cx231xx_errdev
-                   ("%s: cx231xx_AGC mode to Analog - errCode [%d]!\n",
-                    __func__, errCode);
-               return errCode;
-       }
-
-       /* set all alternate settings to zero initially */
-       cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);
-       cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
-       cx231xx_set_alt_setting(dev, INDEX_HANC, 0);
-       if (dev->board.has_dvb)
-               cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
-
-       /* set the I2C master port to 3 on channel 1 */
-       errCode = cx231xx_enable_i2c_port_3(dev, true);
-
-       return errCode;
-}
-EXPORT_SYMBOL_GPL(cx231xx_dev_init);
-
-void cx231xx_dev_uninit(struct cx231xx *dev)
-{
-       /* Un Initialize I2C bus */
-       cx231xx_i2c_unregister(&dev->i2c_bus[2]);
-       cx231xx_i2c_unregister(&dev->i2c_bus[1]);
-       cx231xx_i2c_unregister(&dev->i2c_bus[0]);
-}
-EXPORT_SYMBOL_GPL(cx231xx_dev_uninit);
-
-/*****************************************************************
-*              G P I O related functions                         *
-******************************************************************/
-int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val,
-                         u8 len, u8 request, u8 direction)
-{
-       int status = 0;
-       struct VENDOR_REQUEST_IN ven_req;
-
-       /* Set wValue */
-       ven_req.wValue = (u16) (gpio_bit >> 16 & 0xffff);
-
-       /* set request */
-       if (!request) {
-               if (direction)
-                       ven_req.bRequest = VRT_GET_GPIO;        /* 0x8 gpio */
-               else
-                       ven_req.bRequest = VRT_SET_GPIO;        /* 0x9 gpio */
-       } else {
-               if (direction)
-                       ven_req.bRequest = VRT_GET_GPIE;        /* 0xa gpie */
-               else
-                       ven_req.bRequest = VRT_SET_GPIE;        /* 0xb gpie */
-       }
-
-       /* set index value */
-       ven_req.wIndex = (u16) (gpio_bit & 0xffff);
-
-       /* set wLength value */
-       ven_req.wLength = len;
-
-       /* set bData value */
-       ven_req.bData = 0;
-
-       /* set the buffer for read / write */
-       ven_req.pBuff = gpio_val;
-
-       /* set the direction */
-       if (direction) {
-               ven_req.direction = USB_DIR_IN;
-               memset(ven_req.pBuff, 0x00, ven_req.wLength);
-       } else
-               ven_req.direction = USB_DIR_OUT;
-
-
-       /* call common vendor command request */
-       status = cx231xx_send_vendor_cmd(dev, &ven_req);
-       if (status < 0) {
-               cx231xx_info
-                   ("UsbInterface::sendCommand, failed with status -%d\n",
-                    status);
-       }
-
-       return status;
-}
-EXPORT_SYMBOL_GPL(cx231xx_send_gpio_cmd);
-
-/*****************************************************************
- *    C O N T R O L - Register R E A D / W R I T E functions     *
- *****************************************************************/
-int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode)
-{
-       u8 value[4] = { 0x0, 0x0, 0x0, 0x0 };
-       u32 tmp = 0;
-       int status = 0;
-
-       status =
-           cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, address, value, 4);
-       if (status < 0)
-               return status;
-
-       tmp = *((u32 *) value);
-       tmp |= mode;
-
-       value[0] = (u8) tmp;
-       value[1] = (u8) (tmp >> 8);
-       value[2] = (u8) (tmp >> 16);
-       value[3] = (u8) (tmp >> 24);
-
-       status =
-           cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, address, value, 4);
-
-       return status;
-}
-
-/*****************************************************************
- *            I 2 C Internal C O N T R O L   functions           *
- *****************************************************************/
-int cx231xx_read_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,
-                         u8 saddr_len, u32 *data, u8 data_len, int master)
-{
-       int status = 0;
-       struct cx231xx_i2c_xfer_data req_data;
-       u8 value[64] = "0";
-
-       if (saddr_len == 0)
-               saddr = 0;
-       else if (saddr_len == 1)
-               saddr &= 0xff;
-
-       /* prepare xfer_data struct */
-       req_data.dev_addr = dev_addr >> 1;
-       req_data.direction = I2C_M_RD;
-       req_data.saddr_len = saddr_len;
-       req_data.saddr_dat = saddr;
-       req_data.buf_size = data_len;
-       req_data.p_buffer = (u8 *) value;
-
-       /* usb send command */
-       if (master == 0)
-               status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0],
-                                        &req_data);
-       else if (master == 1)
-               status = dev->cx231xx_send_usb_command(&dev->i2c_bus[1],
-                                        &req_data);
-       else if (master == 2)
-               status = dev->cx231xx_send_usb_command(&dev->i2c_bus[2],
-                                        &req_data);
-
-       if (status >= 0) {
-               /* Copy the data read back to main buffer */
-               if (data_len == 1)
-                       *data = value[0];
-               else if (data_len == 4)
-                       *data =
-                           value[0] | value[1] << 8 | value[2] << 16 | value[3]
-                           << 24;
-               else if (data_len > 4)
-                       *data = value[saddr];
-       }
-
-       return status;
-}
-
-int cx231xx_write_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,
-                          u8 saddr_len, u32 data, u8 data_len, int master)
-{
-       int status = 0;
-       u8 value[4] = { 0, 0, 0, 0 };
-       struct cx231xx_i2c_xfer_data req_data;
-
-       value[0] = (u8) data;
-       value[1] = (u8) (data >> 8);
-       value[2] = (u8) (data >> 16);
-       value[3] = (u8) (data >> 24);
-
-       if (saddr_len == 0)
-               saddr = 0;
-       else if (saddr_len == 1)
-               saddr &= 0xff;
-
-       /* prepare xfer_data struct */
-       req_data.dev_addr = dev_addr >> 1;
-       req_data.direction = 0;
-       req_data.saddr_len = saddr_len;
-       req_data.saddr_dat = saddr;
-       req_data.buf_size = data_len;
-       req_data.p_buffer = value;
-
-       /* usb send command */
-       if (master == 0)
-               status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0],
-                                &req_data);
-       else if (master == 1)
-               status = dev->cx231xx_send_usb_command(&dev->i2c_bus[1],
-                                &req_data);
-       else if (master == 2)
-               status = dev->cx231xx_send_usb_command(&dev->i2c_bus[2],
-                                &req_data);
-
-       return status;
-}
-
-int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr,
-                         u8 saddr_len, u32 *data, u8 data_len)
-{
-       int status = 0;
-       struct cx231xx_i2c_xfer_data req_data;
-       u8 value[4] = { 0, 0, 0, 0 };
-
-       if (saddr_len == 0)
-               saddr = 0;
-       else if (saddr_len == 1)
-               saddr &= 0xff;
-
-       /* prepare xfer_data struct */
-       req_data.dev_addr = dev_addr >> 1;
-       req_data.direction = I2C_M_RD;
-       req_data.saddr_len = saddr_len;
-       req_data.saddr_dat = saddr;
-       req_data.buf_size = data_len;
-       req_data.p_buffer = (u8 *) value;
-
-       /* usb send command */
-       status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data);
-
-       if (status >= 0) {
-               /* Copy the data read back to main buffer */
-               if (data_len == 1)
-                       *data = value[0];
-               else
-                       *data =
-                           value[0] | value[1] << 8 | value[2] << 16 | value[3]
-                           << 24;
-       }
-
-       return status;
-}
-
-int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr,
-                          u8 saddr_len, u32 data, u8 data_len)
-{
-       int status = 0;
-       u8 value[4] = { 0, 0, 0, 0 };
-       struct cx231xx_i2c_xfer_data req_data;
-
-       value[0] = (u8) data;
-       value[1] = (u8) (data >> 8);
-       value[2] = (u8) (data >> 16);
-       value[3] = (u8) (data >> 24);
-
-       if (saddr_len == 0)
-               saddr = 0;
-       else if (saddr_len == 1)
-               saddr &= 0xff;
-
-       /* prepare xfer_data struct */
-       req_data.dev_addr = dev_addr >> 1;
-       req_data.direction = 0;
-       req_data.saddr_len = saddr_len;
-       req_data.saddr_dat = saddr;
-       req_data.buf_size = data_len;
-       req_data.p_buffer = value;
-
-       /* usb send command */
-       status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data);
-
-       return status;
-}
-
-int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size,
-                          u16 register_address, u8 bit_start, u8 bit_end,
-                          u32 value)
-{
-       int status = 0;
-       u32 tmp;
-       u32 mask = 0;
-       int i;
-
-       if (bit_start > (size - 1) || bit_end > (size - 1))
-               return -1;
-
-       if (size == 8) {
-               status =
-                   cx231xx_read_i2c_data(dev, dev_addr, register_address, 2,
-                                         &tmp, 1);
-       } else {
-               status =
-                   cx231xx_read_i2c_data(dev, dev_addr, register_address, 2,
-                                         &tmp, 4);
-       }
-
-       if (status < 0)
-               return status;
-
-       mask = 1 << bit_end;
-       for (i = bit_end; i > bit_start && i > 0; i--)
-               mask = mask + (1 << (i - 1));
-
-       value <<= bit_start;
-
-       if (size == 8) {
-               tmp &= ~mask;
-               tmp |= value;
-               tmp &= 0xff;
-               status =
-                   cx231xx_write_i2c_data(dev, dev_addr, register_address, 2,
-                                          tmp, 1);
-       } else {
-               tmp &= ~mask;
-               tmp |= value;
-               status =
-                   cx231xx_write_i2c_data(dev, dev_addr, register_address, 2,
-                                          tmp, 4);
-       }
-
-       return status;
-}
-
-int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr,
-                                       u16 saddr, u32 mask, u32 value)
-{
-       u32 temp;
-       int status = 0;
-
-       status = cx231xx_read_i2c_data(dev, dev_addr, saddr, 2, &temp, 4);
-
-       if (status < 0)
-               return status;
-
-       temp &= ~mask;
-       temp |= value;
-
-       status = cx231xx_write_i2c_data(dev, dev_addr, saddr, 2, temp, 4);
-
-       return status;
-}
-
-u32 cx231xx_set_field(u32 field_mask, u32 data)
-{
-       u32 temp;
-
-       for (temp = field_mask; (temp & 1) == 0; temp >>= 1)
-               data <<= 1;
-
-       return data;
-}
diff --git a/drivers/media/video/cx231xx/cx231xx-dif.h b/drivers/media/video/cx231xx/cx231xx-dif.h
deleted file mode 100644 (file)
index 2b63c2f..0000000
+++ /dev/null
@@ -1,3178 +0,0 @@
-/*
- *  cx231xx-dif.h - driver for Conexant Cx23100/101/102 USB video capture devices
- *
- *  Copyright {C} 2009 <Bill.Liu@conexant.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.
- *
- *  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.
- */
-
-#ifndef _CX231XX_DIF_H
-#define _CX231XX_DIF_H
-
-#include "cx231xx-reg.h"
-
-struct dif_settings{
-       u32 if_freq;
-       u32 register_address;
-       u32 value;
-};
-
-static struct dif_settings Dif_set_array[] = {
-
-/*case 3000000:*/
-/* BEGIN - DIF BPF register values from 30_quant.dat*/
-{3000000, DIF_BPF_COEFF01,    0x00000002},
-{3000000, DIF_BPF_COEFF23,    0x00080012},
-{3000000, DIF_BPF_COEFF45,    0x001e0024},
-{3000000, DIF_BPF_COEFF67,    0x001bfff8},
-{3000000, DIF_BPF_COEFF89,    0xffb4ff50},
-{3000000, DIF_BPF_COEFF1011,  0xfed8fe68},
-{3000000, DIF_BPF_COEFF1213,  0xfe24fe34},
-{3000000, DIF_BPF_COEFF1415,  0xfebaffc7},
-{3000000, DIF_BPF_COEFF1617,  0x014d031f},
-{3000000, DIF_BPF_COEFF1819,  0x04f0065d},
-{3000000, DIF_BPF_COEFF2021,  0x07010688},
-{3000000, DIF_BPF_COEFF2223,  0x04c901d6},
-{3000000, DIF_BPF_COEFF2425,  0xfe00f9d3},
-{3000000, DIF_BPF_COEFF2627,  0xf600f342},
-{3000000, DIF_BPF_COEFF2829,  0xf235f337},
-{3000000, DIF_BPF_COEFF3031,  0xf64efb22},
-{3000000, DIF_BPF_COEFF3233,  0x0105070f},
-{3000000, DIF_BPF_COEFF3435,  0x0c460fce},
-{3000000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 30_quant.dat*/
-
-
-/*case 3100000:*/
-/* BEGIN - DIF BPF register values from 31_quant.dat*/
-{3100000, DIF_BPF_COEFF01,    0x00000001},
-{3100000, DIF_BPF_COEFF23,    0x00070012},
-{3100000, DIF_BPF_COEFF45,    0x00220032},
-{3100000, DIF_BPF_COEFF67,    0x00370026},
-{3100000, DIF_BPF_COEFF89,    0xfff0ff91},
-{3100000, DIF_BPF_COEFF1011,  0xff0efe7c},
-{3100000, DIF_BPF_COEFF1213,  0xfe01fdcc},
-{3100000, DIF_BPF_COEFF1415,  0xfe0afedb},
-{3100000, DIF_BPF_COEFF1617,  0x00440224},
-{3100000, DIF_BPF_COEFF1819,  0x0434060c},
-{3100000, DIF_BPF_COEFF2021,  0x0738074e},
-{3100000, DIF_BPF_COEFF2223,  0x06090361},
-{3100000, DIF_BPF_COEFF2425,  0xff99fb39},
-{3100000, DIF_BPF_COEFF2627,  0xf6fef3b6},
-{3100000, DIF_BPF_COEFF2829,  0xf21af2a5},
-{3100000, DIF_BPF_COEFF3031,  0xf573fa33},
-{3100000, DIF_BPF_COEFF3233,  0x0034067d},
-{3100000, DIF_BPF_COEFF3435,  0x0bfb0fb9},
-{3100000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 31_quant.dat*/
-
-
-/*case 3200000:*/
-/* BEGIN - DIF BPF register values from 32_quant.dat*/
-{3200000, DIF_BPF_COEFF01,    0x00000000},
-{3200000, DIF_BPF_COEFF23,    0x0004000e},
-{3200000, DIF_BPF_COEFF45,    0x00200038},
-{3200000, DIF_BPF_COEFF67,    0x004c004f},
-{3200000, DIF_BPF_COEFF89,    0x002fffdf},
-{3200000, DIF_BPF_COEFF1011,  0xff5cfeb6},
-{3200000, DIF_BPF_COEFF1213,  0xfe0dfd92},
-{3200000, DIF_BPF_COEFF1415,  0xfd7ffe03},
-{3200000, DIF_BPF_COEFF1617,  0xff36010a},
-{3200000, DIF_BPF_COEFF1819,  0x03410575},
-{3200000, DIF_BPF_COEFF2021,  0x072607d2},
-{3200000, DIF_BPF_COEFF2223,  0x071804d5},
-{3200000, DIF_BPF_COEFF2425,  0x0134fcb7},
-{3200000, DIF_BPF_COEFF2627,  0xf81ff451},
-{3200000, DIF_BPF_COEFF2829,  0xf223f22e},
-{3200000, DIF_BPF_COEFF3031,  0xf4a7f94b},
-{3200000, DIF_BPF_COEFF3233,  0xff6405e8},
-{3200000, DIF_BPF_COEFF3435,  0x0bae0fa4},
-{3200000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 32_quant.dat*/
-
-
-/*case 3300000:*/
-/* BEGIN - DIF BPF register values from 33_quant.dat*/
-{3300000, DIF_BPF_COEFF01,    0x0000ffff},
-{3300000, DIF_BPF_COEFF23,    0x00000008},
-{3300000, DIF_BPF_COEFF45,    0x001a0036},
-{3300000, DIF_BPF_COEFF67,    0x0056006d},
-{3300000, DIF_BPF_COEFF89,    0x00670030},
-{3300000, DIF_BPF_COEFF1011,  0xffbdff10},
-{3300000, DIF_BPF_COEFF1213,  0xfe46fd8d},
-{3300000, DIF_BPF_COEFF1415,  0xfd25fd4f},
-{3300000, DIF_BPF_COEFF1617,  0xfe35ffe0},
-{3300000, DIF_BPF_COEFF1819,  0x0224049f},
-{3300000, DIF_BPF_COEFF2021,  0x06c9080e},
-{3300000, DIF_BPF_COEFF2223,  0x07ef0627},
-{3300000, DIF_BPF_COEFF2425,  0x02c9fe45},
-{3300000, DIF_BPF_COEFF2627,  0xf961f513},
-{3300000, DIF_BPF_COEFF2829,  0xf250f1d2},
-{3300000, DIF_BPF_COEFF3031,  0xf3ecf869},
-{3300000, DIF_BPF_COEFF3233,  0xfe930552},
-{3300000, DIF_BPF_COEFF3435,  0x0b5f0f8f},
-{3300000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 33_quant.dat*/
-
-
-/*case 3400000:*/
-/* BEGIN - DIF BPF register values from 34_quant.dat*/
-{3400000, DIF_BPF_COEFF01,    0xfffffffe},
-{3400000, DIF_BPF_COEFF23,    0xfffd0001},
-{3400000, DIF_BPF_COEFF45,    0x000f002c},
-{3400000, DIF_BPF_COEFF67,    0x0054007d},
-{3400000, DIF_BPF_COEFF89,    0x0093007c},
-{3400000, DIF_BPF_COEFF1011,  0x0024ff82},
-{3400000, DIF_BPF_COEFF1213,  0xfea6fdbb},
-{3400000, DIF_BPF_COEFF1415,  0xfd03fcca},
-{3400000, DIF_BPF_COEFF1617,  0xfd51feb9},
-{3400000, DIF_BPF_COEFF1819,  0x00eb0392},
-{3400000, DIF_BPF_COEFF2021,  0x06270802},
-{3400000, DIF_BPF_COEFF2223,  0x08880750},
-{3400000, DIF_BPF_COEFF2425,  0x044dffdb},
-{3400000, DIF_BPF_COEFF2627,  0xfabdf5f8},
-{3400000, DIF_BPF_COEFF2829,  0xf2a0f193},
-{3400000, DIF_BPF_COEFF3031,  0xf342f78f},
-{3400000, DIF_BPF_COEFF3233,  0xfdc404b9},
-{3400000, DIF_BPF_COEFF3435,  0x0b0e0f78},
-{3400000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 34_quant.dat*/
-
-
-/*case 3500000:*/
-/* BEGIN - DIF BPF register values from 35_quant.dat*/
-{3500000, DIF_BPF_COEFF01,    0xfffffffd},
-{3500000, DIF_BPF_COEFF23,    0xfffafff9},
-{3500000, DIF_BPF_COEFF45,    0x0002001b},
-{3500000, DIF_BPF_COEFF67,    0x0046007d},
-{3500000, DIF_BPF_COEFF89,    0x00ad00ba},
-{3500000, DIF_BPF_COEFF1011,  0x00870000},
-{3500000, DIF_BPF_COEFF1213,  0xff26fe1a},
-{3500000, DIF_BPF_COEFF1415,  0xfd1bfc7e},
-{3500000, DIF_BPF_COEFF1617,  0xfc99fda4},
-{3500000, DIF_BPF_COEFF1819,  0xffa5025c},
-{3500000, DIF_BPF_COEFF2021,  0x054507ad},
-{3500000, DIF_BPF_COEFF2223,  0x08dd0847},
-{3500000, DIF_BPF_COEFF2425,  0x05b80172},
-{3500000, DIF_BPF_COEFF2627,  0xfc2ef6ff},
-{3500000, DIF_BPF_COEFF2829,  0xf313f170},
-{3500000, DIF_BPF_COEFF3031,  0xf2abf6bd},
-{3500000, DIF_BPF_COEFF3233,  0xfcf6041f},
-{3500000, DIF_BPF_COEFF3435,  0x0abc0f61},
-{3500000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 35_quant.dat*/
-
-
-/*case 3600000:*/
-/* BEGIN - DIF BPF register values from 36_quant.dat*/
-{3600000, DIF_BPF_COEFF01,    0xfffffffd},
-{3600000, DIF_BPF_COEFF23,    0xfff8fff3},
-{3600000, DIF_BPF_COEFF45,    0xfff50006},
-{3600000, DIF_BPF_COEFF67,    0x002f006c},
-{3600000, DIF_BPF_COEFF89,    0x00b200e3},
-{3600000, DIF_BPF_COEFF1011,  0x00dc007e},
-{3600000, DIF_BPF_COEFF1213,  0xffb9fea0},
-{3600000, DIF_BPF_COEFF1415,  0xfd6bfc71},
-{3600000, DIF_BPF_COEFF1617,  0xfc17fcb1},
-{3600000, DIF_BPF_COEFF1819,  0xfe65010b},
-{3600000, DIF_BPF_COEFF2021,  0x042d0713},
-{3600000, DIF_BPF_COEFF2223,  0x08ec0906},
-{3600000, DIF_BPF_COEFF2425,  0x07020302},
-{3600000, DIF_BPF_COEFF2627,  0xfdaff823},
-{3600000, DIF_BPF_COEFF2829,  0xf3a7f16a},
-{3600000, DIF_BPF_COEFF3031,  0xf228f5f5},
-{3600000, DIF_BPF_COEFF3233,  0xfc2a0384},
-{3600000, DIF_BPF_COEFF3435,  0x0a670f4a},
-{3600000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 36_quant.dat*/
-
-
-/*case 3700000:*/
-/* BEGIN - DIF BPF register values from 37_quant.dat*/
-{3700000, DIF_BPF_COEFF01,    0x0000fffd},
-{3700000, DIF_BPF_COEFF23,    0xfff7ffef},
-{3700000, DIF_BPF_COEFF45,    0xffe9fff1},
-{3700000, DIF_BPF_COEFF67,    0x0010004d},
-{3700000, DIF_BPF_COEFF89,    0x00a100f2},
-{3700000, DIF_BPF_COEFF1011,  0x011a00f0},
-{3700000, DIF_BPF_COEFF1213,  0x0053ff44},
-{3700000, DIF_BPF_COEFF1415,  0xfdedfca2},
-{3700000, DIF_BPF_COEFF1617,  0xfbd3fbef},
-{3700000, DIF_BPF_COEFF1819,  0xfd39ffae},
-{3700000, DIF_BPF_COEFF2021,  0x02ea0638},
-{3700000, DIF_BPF_COEFF2223,  0x08b50987},
-{3700000, DIF_BPF_COEFF2425,  0x08230483},
-{3700000, DIF_BPF_COEFF2627,  0xff39f960},
-{3700000, DIF_BPF_COEFF2829,  0xf45bf180},
-{3700000, DIF_BPF_COEFF3031,  0xf1b8f537},
-{3700000, DIF_BPF_COEFF3233,  0xfb6102e7},
-{3700000, DIF_BPF_COEFF3435,  0x0a110f32},
-{3700000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 37_quant.dat*/
-
-
-/*case 3800000:*/
-/* BEGIN - DIF BPF register values from 38_quant.dat*/
-{3800000, DIF_BPF_COEFF01,    0x0000fffe},
-{3800000, DIF_BPF_COEFF23,    0xfff9ffee},
-{3800000, DIF_BPF_COEFF45,    0xffe1ffdd},
-{3800000, DIF_BPF_COEFF67,    0xfff00024},
-{3800000, DIF_BPF_COEFF89,    0x007c00e5},
-{3800000, DIF_BPF_COEFF1011,  0x013a014a},
-{3800000, DIF_BPF_COEFF1213,  0x00e6fff8},
-{3800000, DIF_BPF_COEFF1415,  0xfe98fd0f},
-{3800000, DIF_BPF_COEFF1617,  0xfbd3fb67},
-{3800000, DIF_BPF_COEFF1819,  0xfc32fe54},
-{3800000, DIF_BPF_COEFF2021,  0x01880525},
-{3800000, DIF_BPF_COEFF2223,  0x083909c7},
-{3800000, DIF_BPF_COEFF2425,  0x091505ee},
-{3800000, DIF_BPF_COEFF2627,  0x00c7fab3},
-{3800000, DIF_BPF_COEFF2829,  0xf52df1b4},
-{3800000, DIF_BPF_COEFF3031,  0xf15df484},
-{3800000, DIF_BPF_COEFF3233,  0xfa9b0249},
-{3800000, DIF_BPF_COEFF3435,  0x09ba0f19},
-{3800000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 38_quant.dat*/
-
-
-/*case 3900000:*/
-/* BEGIN - DIF BPF register values from 39_quant.dat*/
-{3900000, DIF_BPF_COEFF01,    0x00000000},
-{3900000, DIF_BPF_COEFF23,    0xfffbfff0},
-{3900000, DIF_BPF_COEFF45,    0xffdeffcf},
-{3900000, DIF_BPF_COEFF67,    0xffd1fff6},
-{3900000, DIF_BPF_COEFF89,    0x004800be},
-{3900000, DIF_BPF_COEFF1011,  0x01390184},
-{3900000, DIF_BPF_COEFF1213,  0x016300ac},
-{3900000, DIF_BPF_COEFF1415,  0xff5efdb1},
-{3900000, DIF_BPF_COEFF1617,  0xfc17fb23},
-{3900000, DIF_BPF_COEFF1819,  0xfb5cfd0d},
-{3900000, DIF_BPF_COEFF2021,  0x001703e4},
-{3900000, DIF_BPF_COEFF2223,  0x077b09c4},
-{3900000, DIF_BPF_COEFF2425,  0x09d2073c},
-{3900000, DIF_BPF_COEFF2627,  0x0251fc18},
-{3900000, DIF_BPF_COEFF2829,  0xf61cf203},
-{3900000, DIF_BPF_COEFF3031,  0xf118f3dc},
-{3900000, DIF_BPF_COEFF3233,  0xf9d801aa},
-{3900000, DIF_BPF_COEFF3435,  0x09600eff},
-{3900000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 39_quant.dat*/
-
-
-/*case 4000000:*/
-/* BEGIN - DIF BPF register values from 40_quant.dat*/
-{4000000, DIF_BPF_COEFF01,    0x00000001},
-{4000000, DIF_BPF_COEFF23,    0xfffefff4},
-{4000000, DIF_BPF_COEFF45,    0xffe1ffc8},
-{4000000, DIF_BPF_COEFF67,    0xffbaffca},
-{4000000, DIF_BPF_COEFF89,    0x000b0082},
-{4000000, DIF_BPF_COEFF1011,  0x01170198},
-{4000000, DIF_BPF_COEFF1213,  0x01c10152},
-{4000000, DIF_BPF_COEFF1415,  0x0030fe7b},
-{4000000, DIF_BPF_COEFF1617,  0xfc99fb24},
-{4000000, DIF_BPF_COEFF1819,  0xfac3fbe9},
-{4000000, DIF_BPF_COEFF2021,  0xfea5027f},
-{4000000, DIF_BPF_COEFF2223,  0x0683097f},
-{4000000, DIF_BPF_COEFF2425,  0x0a560867},
-{4000000, DIF_BPF_COEFF2627,  0x03d2fd89},
-{4000000, DIF_BPF_COEFF2829,  0xf723f26f},
-{4000000, DIF_BPF_COEFF3031,  0xf0e8f341},
-{4000000, DIF_BPF_COEFF3233,  0xf919010a},
-{4000000, DIF_BPF_COEFF3435,  0x09060ee5},
-{4000000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 40_quant.dat*/
-
-
-/*case 4100000:*/
-/* BEGIN - DIF BPF register values from 41_quant.dat*/
-{4100000, DIF_BPF_COEFF01,    0x00010002},
-{4100000, DIF_BPF_COEFF23,    0x0002fffb},
-{4100000, DIF_BPF_COEFF45,    0xffe8ffca},
-{4100000, DIF_BPF_COEFF67,    0xffacffa4},
-{4100000, DIF_BPF_COEFF89,    0xffcd0036},
-{4100000, DIF_BPF_COEFF1011,  0x00d70184},
-{4100000, DIF_BPF_COEFF1213,  0x01f601dc},
-{4100000, DIF_BPF_COEFF1415,  0x00ffff60},
-{4100000, DIF_BPF_COEFF1617,  0xfd51fb6d},
-{4100000, DIF_BPF_COEFF1819,  0xfa6efaf5},
-{4100000, DIF_BPF_COEFF2021,  0xfd410103},
-{4100000, DIF_BPF_COEFF2223,  0x055708f9},
-{4100000, DIF_BPF_COEFF2425,  0x0a9e0969},
-{4100000, DIF_BPF_COEFF2627,  0x0543ff02},
-{4100000, DIF_BPF_COEFF2829,  0xf842f2f5},
-{4100000, DIF_BPF_COEFF3031,  0xf0cef2b2},
-{4100000, DIF_BPF_COEFF3233,  0xf85e006b},
-{4100000, DIF_BPF_COEFF3435,  0x08aa0ecb},
-{4100000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 41_quant.dat*/
-
-
-/*case 4200000:*/
-/* BEGIN - DIF BPF register values from 42_quant.dat*/
-{4200000, DIF_BPF_COEFF01,    0x00010003},
-{4200000, DIF_BPF_COEFF23,    0x00050003},
-{4200000, DIF_BPF_COEFF45,    0xfff3ffd3},
-{4200000, DIF_BPF_COEFF67,    0xffaaff8b},
-{4200000, DIF_BPF_COEFF89,    0xff95ffe5},
-{4200000, DIF_BPF_COEFF1011,  0x0080014a},
-{4200000, DIF_BPF_COEFF1213,  0x01fe023f},
-{4200000, DIF_BPF_COEFF1415,  0x01ba0050},
-{4200000, DIF_BPF_COEFF1617,  0xfe35fbf8},
-{4200000, DIF_BPF_COEFF1819,  0xfa62fa3b},
-{4200000, DIF_BPF_COEFF2021,  0xfbf9ff7e},
-{4200000, DIF_BPF_COEFF2223,  0x04010836},
-{4200000, DIF_BPF_COEFF2425,  0x0aa90a3d},
-{4200000, DIF_BPF_COEFF2627,  0x069f007f},
-{4200000, DIF_BPF_COEFF2829,  0xf975f395},
-{4200000, DIF_BPF_COEFF3031,  0xf0cbf231},
-{4200000, DIF_BPF_COEFF3233,  0xf7a9ffcb},
-{4200000, DIF_BPF_COEFF3435,  0x084c0eaf},
-{4200000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 42_quant.dat*/
-
-
-/*case 4300000:*/
-/* BEGIN - DIF BPF register values from 43_quant.dat*/
-{4300000, DIF_BPF_COEFF01,    0x00010003},
-{4300000, DIF_BPF_COEFF23,    0x0008000a},
-{4300000, DIF_BPF_COEFF45,    0x0000ffe4},
-{4300000, DIF_BPF_COEFF67,    0xffb4ff81},
-{4300000, DIF_BPF_COEFF89,    0xff6aff96},
-{4300000, DIF_BPF_COEFF1011,  0x001c00f0},
-{4300000, DIF_BPF_COEFF1213,  0x01d70271},
-{4300000, DIF_BPF_COEFF1415,  0x0254013b},
-{4300000, DIF_BPF_COEFF1617,  0xff36fcbd},
-{4300000, DIF_BPF_COEFF1819,  0xfa9ff9c5},
-{4300000, DIF_BPF_COEFF2021,  0xfadbfdfe},
-{4300000, DIF_BPF_COEFF2223,  0x028c073b},
-{4300000, DIF_BPF_COEFF2425,  0x0a750adf},
-{4300000, DIF_BPF_COEFF2627,  0x07e101fa},
-{4300000, DIF_BPF_COEFF2829,  0xfab8f44e},
-{4300000, DIF_BPF_COEFF3031,  0xf0ddf1be},
-{4300000, DIF_BPF_COEFF3233,  0xf6f9ff2b},
-{4300000, DIF_BPF_COEFF3435,  0x07ed0e94},
-{4300000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 43_quant.dat*/
-
-
-/*case 4400000:*/
-/* BEGIN - DIF BPF register values from 44_quant.dat*/
-{4400000, DIF_BPF_COEFF01,    0x00000003},
-{4400000, DIF_BPF_COEFF23,    0x0009000f},
-{4400000, DIF_BPF_COEFF45,    0x000efff8},
-{4400000, DIF_BPF_COEFF67,    0xffc9ff87},
-{4400000, DIF_BPF_COEFF89,    0xff52ff54},
-{4400000, DIF_BPF_COEFF1011,  0xffb5007e},
-{4400000, DIF_BPF_COEFF1213,  0x01860270},
-{4400000, DIF_BPF_COEFF1415,  0x02c00210},
-{4400000, DIF_BPF_COEFF1617,  0x0044fdb2},
-{4400000, DIF_BPF_COEFF1819,  0xfb22f997},
-{4400000, DIF_BPF_COEFF2021,  0xf9f2fc90},
-{4400000, DIF_BPF_COEFF2223,  0x0102060f},
-{4400000, DIF_BPF_COEFF2425,  0x0a050b4c},
-{4400000, DIF_BPF_COEFF2627,  0x0902036e},
-{4400000, DIF_BPF_COEFF2829,  0xfc0af51e},
-{4400000, DIF_BPF_COEFF3031,  0xf106f15a},
-{4400000, DIF_BPF_COEFF3233,  0xf64efe8b},
-{4400000, DIF_BPF_COEFF3435,  0x078d0e77},
-{4400000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 44_quant.dat*/
-
-
-/*case 4500000:*/
-/* BEGIN - DIF BPF register values from 45_quant.dat*/
-{4500000, DIF_BPF_COEFF01,    0x00000002},
-{4500000, DIF_BPF_COEFF23,    0x00080012},
-{4500000, DIF_BPF_COEFF45,    0x0019000e},
-{4500000, DIF_BPF_COEFF67,    0xffe5ff9e},
-{4500000, DIF_BPF_COEFF89,    0xff4fff25},
-{4500000, DIF_BPF_COEFF1011,  0xff560000},
-{4500000, DIF_BPF_COEFF1213,  0x0112023b},
-{4500000, DIF_BPF_COEFF1415,  0x02f702c0},
-{4500000, DIF_BPF_COEFF1617,  0x014dfec8},
-{4500000, DIF_BPF_COEFF1819,  0xfbe5f9b3},
-{4500000, DIF_BPF_COEFF2021,  0xf947fb41},
-{4500000, DIF_BPF_COEFF2223,  0xff7004b9},
-{4500000, DIF_BPF_COEFF2425,  0x095a0b81},
-{4500000, DIF_BPF_COEFF2627,  0x0a0004d8},
-{4500000, DIF_BPF_COEFF2829,  0xfd65f603},
-{4500000, DIF_BPF_COEFF3031,  0xf144f104},
-{4500000, DIF_BPF_COEFF3233,  0xf5aafdec},
-{4500000, DIF_BPF_COEFF3435,  0x072b0e5a},
-{4500000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 45_quant.dat*/
-
-
-/*case 4600000:*/
-/* BEGIN - DIF BPF register values from 46_quant.dat*/
-{4600000, DIF_BPF_COEFF01,    0x00000001},
-{4600000, DIF_BPF_COEFF23,    0x00060012},
-{4600000, DIF_BPF_COEFF45,    0x00200022},
-{4600000, DIF_BPF_COEFF67,    0x0005ffc1},
-{4600000, DIF_BPF_COEFF89,    0xff61ff10},
-{4600000, DIF_BPF_COEFF1011,  0xff09ff82},
-{4600000, DIF_BPF_COEFF1213,  0x008601d7},
-{4600000, DIF_BPF_COEFF1415,  0x02f50340},
-{4600000, DIF_BPF_COEFF1617,  0x0241fff0},
-{4600000, DIF_BPF_COEFF1819,  0xfcddfa19},
-{4600000, DIF_BPF_COEFF2021,  0xf8e2fa1e},
-{4600000, DIF_BPF_COEFF2223,  0xfde30343},
-{4600000, DIF_BPF_COEFF2425,  0x08790b7f},
-{4600000, DIF_BPF_COEFF2627,  0x0ad50631},
-{4600000, DIF_BPF_COEFF2829,  0xfec7f6fc},
-{4600000, DIF_BPF_COEFF3031,  0xf198f0bd},
-{4600000, DIF_BPF_COEFF3233,  0xf50dfd4e},
-{4600000, DIF_BPF_COEFF3435,  0x06c90e3d},
-{4600000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 46_quant.dat*/
-
-
-/*case 4700000:*/
-/* BEGIN - DIF BPF register values from 47_quant.dat*/
-{4700000, DIF_BPF_COEFF01,    0x0000ffff},
-{4700000, DIF_BPF_COEFF23,    0x0003000f},
-{4700000, DIF_BPF_COEFF45,    0x00220030},
-{4700000, DIF_BPF_COEFF67,    0x0025ffed},
-{4700000, DIF_BPF_COEFF89,    0xff87ff15},
-{4700000, DIF_BPF_COEFF1011,  0xfed6ff10},
-{4700000, DIF_BPF_COEFF1213,  0xffed014c},
-{4700000, DIF_BPF_COEFF1415,  0x02b90386},
-{4700000, DIF_BPF_COEFF1617,  0x03110119},
-{4700000, DIF_BPF_COEFF1819,  0xfdfefac4},
-{4700000, DIF_BPF_COEFF2021,  0xf8c6f92f},
-{4700000, DIF_BPF_COEFF2223,  0xfc6701b7},
-{4700000, DIF_BPF_COEFF2425,  0x07670b44},
-{4700000, DIF_BPF_COEFF2627,  0x0b7e0776},
-{4700000, DIF_BPF_COEFF2829,  0x002df807},
-{4700000, DIF_BPF_COEFF3031,  0xf200f086},
-{4700000, DIF_BPF_COEFF3233,  0xf477fcb1},
-{4700000, DIF_BPF_COEFF3435,  0x06650e1e},
-{4700000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 47_quant.dat*/
-
-
-/*case 4800000:*/
-/* BEGIN - DIF BPF register values from 48_quant.dat*/
-{4800000, DIF_BPF_COEFF01,    0xfffffffe},
-{4800000, DIF_BPF_COEFF23,    0xffff0009},
-{4800000, DIF_BPF_COEFF45,    0x001e0038},
-{4800000, DIF_BPF_COEFF67,    0x003f001b},
-{4800000, DIF_BPF_COEFF89,    0xffbcff36},
-{4800000, DIF_BPF_COEFF1011,  0xfec2feb6},
-{4800000, DIF_BPF_COEFF1213,  0xff5600a5},
-{4800000, DIF_BPF_COEFF1415,  0x0248038d},
-{4800000, DIF_BPF_COEFF1617,  0x03b00232},
-{4800000, DIF_BPF_COEFF1819,  0xff39fbab},
-{4800000, DIF_BPF_COEFF2021,  0xf8f4f87f},
-{4800000, DIF_BPF_COEFF2223,  0xfb060020},
-{4800000, DIF_BPF_COEFF2425,  0x062a0ad2},
-{4800000, DIF_BPF_COEFF2627,  0x0bf908a3},
-{4800000, DIF_BPF_COEFF2829,  0x0192f922},
-{4800000, DIF_BPF_COEFF3031,  0xf27df05e},
-{4800000, DIF_BPF_COEFF3233,  0xf3e8fc14},
-{4800000, DIF_BPF_COEFF3435,  0x06000e00},
-{4800000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 48_quant.dat*/
-
-
-/*case 4900000:*/
-/* BEGIN - DIF BPF register values from 49_quant.dat*/
-{4900000, DIF_BPF_COEFF01,    0xfffffffd},
-{4900000, DIF_BPF_COEFF23,    0xfffc0002},
-{4900000, DIF_BPF_COEFF45,    0x00160037},
-{4900000, DIF_BPF_COEFF67,    0x00510046},
-{4900000, DIF_BPF_COEFF89,    0xfff9ff6d},
-{4900000, DIF_BPF_COEFF1011,  0xfed0fe7c},
-{4900000, DIF_BPF_COEFF1213,  0xfecefff0},
-{4900000, DIF_BPF_COEFF1415,  0x01aa0356},
-{4900000, DIF_BPF_COEFF1617,  0x0413032b},
-{4900000, DIF_BPF_COEFF1819,  0x007ffcc5},
-{4900000, DIF_BPF_COEFF2021,  0xf96cf812},
-{4900000, DIF_BPF_COEFF2223,  0xf9cefe87},
-{4900000, DIF_BPF_COEFF2425,  0x04c90a2c},
-{4900000, DIF_BPF_COEFF2627,  0x0c4309b4},
-{4900000, DIF_BPF_COEFF2829,  0x02f3fa4a},
-{4900000, DIF_BPF_COEFF3031,  0xf30ef046},
-{4900000, DIF_BPF_COEFF3233,  0xf361fb7a},
-{4900000, DIF_BPF_COEFF3435,  0x059b0de0},
-{4900000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 49_quant.dat*/
-
-
-/*case 5000000:*/
-/* BEGIN - DIF BPF register values from 50_quant.dat*/
-{5000000, DIF_BPF_COEFF01,    0xfffffffd},
-{5000000, DIF_BPF_COEFF23,    0xfff9fffa},
-{5000000, DIF_BPF_COEFF45,    0x000a002d},
-{5000000, DIF_BPF_COEFF67,    0x00570067},
-{5000000, DIF_BPF_COEFF89,    0x0037ffb5},
-{5000000, DIF_BPF_COEFF1011,  0xfefffe68},
-{5000000, DIF_BPF_COEFF1213,  0xfe62ff3d},
-{5000000, DIF_BPF_COEFF1415,  0x00ec02e3},
-{5000000, DIF_BPF_COEFF1617,  0x043503f6},
-{5000000, DIF_BPF_COEFF1819,  0x01befe05},
-{5000000, DIF_BPF_COEFF2021,  0xfa27f7ee},
-{5000000, DIF_BPF_COEFF2223,  0xf8c6fcf8},
-{5000000, DIF_BPF_COEFF2425,  0x034c0954},
-{5000000, DIF_BPF_COEFF2627,  0x0c5c0aa4},
-{5000000, DIF_BPF_COEFF2829,  0x044cfb7e},
-{5000000, DIF_BPF_COEFF3031,  0xf3b1f03f},
-{5000000, DIF_BPF_COEFF3233,  0xf2e2fae1},
-{5000000, DIF_BPF_COEFF3435,  0x05340dc0},
-{5000000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 50_quant.dat*/
-
-
-/*case 5100000:*/
-/* BEGIN - DIF BPF register values from 51_quant.dat*/
-{5100000, DIF_BPF_COEFF01,    0x0000fffd},
-{5100000, DIF_BPF_COEFF23,    0xfff8fff4},
-{5100000, DIF_BPF_COEFF45,    0xfffd001e},
-{5100000, DIF_BPF_COEFF67,    0x0051007b},
-{5100000, DIF_BPF_COEFF89,    0x006e0006},
-{5100000, DIF_BPF_COEFF1011,  0xff48fe7c},
-{5100000, DIF_BPF_COEFF1213,  0xfe1bfe9a},
-{5100000, DIF_BPF_COEFF1415,  0x001d023e},
-{5100000, DIF_BPF_COEFF1617,  0x04130488},
-{5100000, DIF_BPF_COEFF1819,  0x02e6ff5b},
-{5100000, DIF_BPF_COEFF2021,  0xfb1ef812},
-{5100000, DIF_BPF_COEFF2223,  0xf7f7fb7f},
-{5100000, DIF_BPF_COEFF2425,  0x01bc084e},
-{5100000, DIF_BPF_COEFF2627,  0x0c430b72},
-{5100000, DIF_BPF_COEFF2829,  0x059afcba},
-{5100000, DIF_BPF_COEFF3031,  0xf467f046},
-{5100000, DIF_BPF_COEFF3233,  0xf26cfa4a},
-{5100000, DIF_BPF_COEFF3435,  0x04cd0da0},
-{5100000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 51_quant.dat*/
-
-
-/*case 5200000:*/
-/* BEGIN - DIF BPF register values from 52_quant.dat*/
-{5200000, DIF_BPF_COEFF01,    0x0000fffe},
-{5200000, DIF_BPF_COEFF23,    0xfff8ffef},
-{5200000, DIF_BPF_COEFF45,    0xfff00009},
-{5200000, DIF_BPF_COEFF67,    0x003f007f},
-{5200000, DIF_BPF_COEFF89,    0x00980056},
-{5200000, DIF_BPF_COEFF1011,  0xffa5feb6},
-{5200000, DIF_BPF_COEFF1213,  0xfe00fe15},
-{5200000, DIF_BPF_COEFF1415,  0xff4b0170},
-{5200000, DIF_BPF_COEFF1617,  0x03b004d7},
-{5200000, DIF_BPF_COEFF1819,  0x03e800b9},
-{5200000, DIF_BPF_COEFF2021,  0xfc48f87f},
-{5200000, DIF_BPF_COEFF2223,  0xf768fa23},
-{5200000, DIF_BPF_COEFF2425,  0x0022071f},
-{5200000, DIF_BPF_COEFF2627,  0x0bf90c1b},
-{5200000, DIF_BPF_COEFF2829,  0x06dafdfd},
-{5200000, DIF_BPF_COEFF3031,  0xf52df05e},
-{5200000, DIF_BPF_COEFF3233,  0xf1fef9b5},
-{5200000, DIF_BPF_COEFF3435,  0x04640d7f},
-{5200000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 52_quant.dat*/
-
-
-/*case 5300000:*/
-/* BEGIN - DIF BPF register values from 53_quant.dat*/
-{5300000, DIF_BPF_COEFF01,    0x0000ffff},
-{5300000, DIF_BPF_COEFF23,    0xfff9ffee},
-{5300000, DIF_BPF_COEFF45,    0xffe6fff3},
-{5300000, DIF_BPF_COEFF67,    0x00250072},
-{5300000, DIF_BPF_COEFF89,    0x00af009c},
-{5300000, DIF_BPF_COEFF1011,  0x000cff10},
-{5300000, DIF_BPF_COEFF1213,  0xfe13fdb8},
-{5300000, DIF_BPF_COEFF1415,  0xfe870089},
-{5300000, DIF_BPF_COEFF1617,  0x031104e1},
-{5300000, DIF_BPF_COEFF1819,  0x04b8020f},
-{5300000, DIF_BPF_COEFF2021,  0xfd98f92f},
-{5300000, DIF_BPF_COEFF2223,  0xf71df8f0},
-{5300000, DIF_BPF_COEFF2425,  0xfe8805ce},
-{5300000, DIF_BPF_COEFF2627,  0x0b7e0c9c},
-{5300000, DIF_BPF_COEFF2829,  0x0808ff44},
-{5300000, DIF_BPF_COEFF3031,  0xf603f086},
-{5300000, DIF_BPF_COEFF3233,  0xf19af922},
-{5300000, DIF_BPF_COEFF3435,  0x03fb0d5e},
-{5300000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 53_quant.dat*/
-
-
-/*case 5400000:*/
-/* BEGIN - DIF BPF register values from 54_quant.dat*/
-{5400000, DIF_BPF_COEFF01,    0x00000001},
-{5400000, DIF_BPF_COEFF23,    0xfffcffef},
-{5400000, DIF_BPF_COEFF45,    0xffe0ffe0},
-{5400000, DIF_BPF_COEFF67,    0x00050056},
-{5400000, DIF_BPF_COEFF89,    0x00b000d1},
-{5400000, DIF_BPF_COEFF1011,  0x0071ff82},
-{5400000, DIF_BPF_COEFF1213,  0xfe53fd8c},
-{5400000, DIF_BPF_COEFF1415,  0xfddfff99},
-{5400000, DIF_BPF_COEFF1617,  0x024104a3},
-{5400000, DIF_BPF_COEFF1819,  0x054a034d},
-{5400000, DIF_BPF_COEFF2021,  0xff01fa1e},
-{5400000, DIF_BPF_COEFF2223,  0xf717f7ed},
-{5400000, DIF_BPF_COEFF2425,  0xfcf50461},
-{5400000, DIF_BPF_COEFF2627,  0x0ad50cf4},
-{5400000, DIF_BPF_COEFF2829,  0x0921008d},
-{5400000, DIF_BPF_COEFF3031,  0xf6e7f0bd},
-{5400000, DIF_BPF_COEFF3233,  0xf13ff891},
-{5400000, DIF_BPF_COEFF3435,  0x03920d3b},
-{5400000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 54_quant.dat*/
-
-
-/*case 5500000:*/
-/* BEGIN - DIF BPF register values from 55_quant.dat*/
-{5500000, DIF_BPF_COEFF01,    0x00010002},
-{5500000, DIF_BPF_COEFF23,    0xfffffff3},
-{5500000, DIF_BPF_COEFF45,    0xffdeffd1},
-{5500000, DIF_BPF_COEFF67,    0xffe5002f},
-{5500000, DIF_BPF_COEFF89,    0x009c00ed},
-{5500000, DIF_BPF_COEFF1011,  0x00cb0000},
-{5500000, DIF_BPF_COEFF1213,  0xfebafd94},
-{5500000, DIF_BPF_COEFF1415,  0xfd61feb0},
-{5500000, DIF_BPF_COEFF1617,  0x014d0422},
-{5500000, DIF_BPF_COEFF1819,  0x05970464},
-{5500000, DIF_BPF_COEFF2021,  0x0074fb41},
-{5500000, DIF_BPF_COEFF2223,  0xf759f721},
-{5500000, DIF_BPF_COEFF2425,  0xfb7502de},
-{5500000, DIF_BPF_COEFF2627,  0x0a000d21},
-{5500000, DIF_BPF_COEFF2829,  0x0a2201d4},
-{5500000, DIF_BPF_COEFF3031,  0xf7d9f104},
-{5500000, DIF_BPF_COEFF3233,  0xf0edf804},
-{5500000, DIF_BPF_COEFF3435,  0x03280d19},
-{5500000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 55_quant.dat*/
-
-
-/*case 5600000:*/
-/* BEGIN - DIF BPF register values from 56_quant.dat*/
-{5600000, DIF_BPF_COEFF01,    0x00010003},
-{5600000, DIF_BPF_COEFF23,    0x0003fffa},
-{5600000, DIF_BPF_COEFF45,    0xffe3ffc9},
-{5600000, DIF_BPF_COEFF67,    0xffc90002},
-{5600000, DIF_BPF_COEFF89,    0x007500ef},
-{5600000, DIF_BPF_COEFF1011,  0x010e007e},
-{5600000, DIF_BPF_COEFF1213,  0xff3dfdcf},
-{5600000, DIF_BPF_COEFF1415,  0xfd16fddd},
-{5600000, DIF_BPF_COEFF1617,  0x00440365},
-{5600000, DIF_BPF_COEFF1819,  0x059b0548},
-{5600000, DIF_BPF_COEFF2021,  0x01e3fc90},
-{5600000, DIF_BPF_COEFF2223,  0xf7dff691},
-{5600000, DIF_BPF_COEFF2425,  0xfa0f014d},
-{5600000, DIF_BPF_COEFF2627,  0x09020d23},
-{5600000, DIF_BPF_COEFF2829,  0x0b0a0318},
-{5600000, DIF_BPF_COEFF3031,  0xf8d7f15a},
-{5600000, DIF_BPF_COEFF3233,  0xf0a5f779},
-{5600000, DIF_BPF_COEFF3435,  0x02bd0cf6},
-{5600000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 56_quant.dat*/
-
-
-/*case 5700000:*/
-/* BEGIN - DIF BPF register values from 57_quant.dat*/
-{5700000, DIF_BPF_COEFF01,    0x00010003},
-{5700000, DIF_BPF_COEFF23,    0x00060001},
-{5700000, DIF_BPF_COEFF45,    0xffecffc9},
-{5700000, DIF_BPF_COEFF67,    0xffb4ffd4},
-{5700000, DIF_BPF_COEFF89,    0x004000d5},
-{5700000, DIF_BPF_COEFF1011,  0x013600f0},
-{5700000, DIF_BPF_COEFF1213,  0xffd3fe39},
-{5700000, DIF_BPF_COEFF1415,  0xfd04fd31},
-{5700000, DIF_BPF_COEFF1617,  0xff360277},
-{5700000, DIF_BPF_COEFF1819,  0x055605ef},
-{5700000, DIF_BPF_COEFF2021,  0x033efdfe},
-{5700000, DIF_BPF_COEFF2223,  0xf8a5f642},
-{5700000, DIF_BPF_COEFF2425,  0xf8cbffb6},
-{5700000, DIF_BPF_COEFF2627,  0x07e10cfb},
-{5700000, DIF_BPF_COEFF2829,  0x0bd50456},
-{5700000, DIF_BPF_COEFF3031,  0xf9dff1be},
-{5700000, DIF_BPF_COEFF3233,  0xf067f6f2},
-{5700000, DIF_BPF_COEFF3435,  0x02520cd2},
-{5700000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 57_quant.dat*/
-
-
-/*case 5800000:*/
-/* BEGIN - DIF BPF register values from 58_quant.dat*/
-{5800000, DIF_BPF_COEFF01,    0x00000003},
-{5800000, DIF_BPF_COEFF23,    0x00080009},
-{5800000, DIF_BPF_COEFF45,    0xfff8ffd2},
-{5800000, DIF_BPF_COEFF67,    0xffaaffac},
-{5800000, DIF_BPF_COEFF89,    0x000200a3},
-{5800000, DIF_BPF_COEFF1011,  0x013c014a},
-{5800000, DIF_BPF_COEFF1213,  0x006dfec9},
-{5800000, DIF_BPF_COEFF1415,  0xfd2bfcb7},
-{5800000, DIF_BPF_COEFF1617,  0xfe350165},
-{5800000, DIF_BPF_COEFF1819,  0x04cb0651},
-{5800000, DIF_BPF_COEFF2021,  0x0477ff7e},
-{5800000, DIF_BPF_COEFF2223,  0xf9a5f635},
-{5800000, DIF_BPF_COEFF2425,  0xf7b1fe20},
-{5800000, DIF_BPF_COEFF2627,  0x069f0ca8},
-{5800000, DIF_BPF_COEFF2829,  0x0c81058b},
-{5800000, DIF_BPF_COEFF3031,  0xfaf0f231},
-{5800000, DIF_BPF_COEFF3233,  0xf033f66d},
-{5800000, DIF_BPF_COEFF3435,  0x01e60cae},
-{5800000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 58_quant.dat*/
-
-
-/*case 5900000:*/
-/* BEGIN - DIF BPF register values from 59_quant.dat*/
-{5900000, DIF_BPF_COEFF01,    0x00000002},
-{5900000, DIF_BPF_COEFF23,    0x0009000e},
-{5900000, DIF_BPF_COEFF45,    0x0005ffe1},
-{5900000, DIF_BPF_COEFF67,    0xffacff90},
-{5900000, DIF_BPF_COEFF89,    0xffc5005f},
-{5900000, DIF_BPF_COEFF1011,  0x01210184},
-{5900000, DIF_BPF_COEFF1213,  0x00fcff72},
-{5900000, DIF_BPF_COEFF1415,  0xfd8afc77},
-{5900000, DIF_BPF_COEFF1617,  0xfd51003f},
-{5900000, DIF_BPF_COEFF1819,  0x04020669},
-{5900000, DIF_BPF_COEFF2021,  0x05830103},
-{5900000, DIF_BPF_COEFF2223,  0xfad7f66b},
-{5900000, DIF_BPF_COEFF2425,  0xf6c8fc93},
-{5900000, DIF_BPF_COEFF2627,  0x05430c2b},
-{5900000, DIF_BPF_COEFF2829,  0x0d0d06b5},
-{5900000, DIF_BPF_COEFF3031,  0xfc08f2b2},
-{5900000, DIF_BPF_COEFF3233,  0xf00af5ec},
-{5900000, DIF_BPF_COEFF3435,  0x017b0c89},
-{5900000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 59_quant.dat*/
-
-
-/*case 6000000:*/
-/* BEGIN - DIF BPF register values from 60_quant.dat*/
-{6000000, DIF_BPF_COEFF01,    0x00000001},
-{6000000, DIF_BPF_COEFF23,    0x00070012},
-{6000000, DIF_BPF_COEFF45,    0x0012fff5},
-{6000000, DIF_BPF_COEFF67,    0xffbaff82},
-{6000000, DIF_BPF_COEFF89,    0xff8e000f},
-{6000000, DIF_BPF_COEFF1011,  0x00e80198},
-{6000000, DIF_BPF_COEFF1213,  0x01750028},
-{6000000, DIF_BPF_COEFF1415,  0xfe18fc75},
-{6000000, DIF_BPF_COEFF1617,  0xfc99ff15},
-{6000000, DIF_BPF_COEFF1819,  0x03050636},
-{6000000, DIF_BPF_COEFF2021,  0x0656027f},
-{6000000, DIF_BPF_COEFF2223,  0xfc32f6e2},
-{6000000, DIF_BPF_COEFF2425,  0xf614fb17},
-{6000000, DIF_BPF_COEFF2627,  0x03d20b87},
-{6000000, DIF_BPF_COEFF2829,  0x0d7707d2},
-{6000000, DIF_BPF_COEFF3031,  0xfd26f341},
-{6000000, DIF_BPF_COEFF3233,  0xefeaf56f},
-{6000000, DIF_BPF_COEFF3435,  0x010f0c64},
-{6000000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 60_quant.dat*/
-
-
-/*case 6100000:*/
-/* BEGIN - DIF BPF register values from 61_quant.dat*/
-{6100000, DIF_BPF_COEFF01,    0xffff0000},
-{6100000, DIF_BPF_COEFF23,    0x00050012},
-{6100000, DIF_BPF_COEFF45,    0x001c000b},
-{6100000, DIF_BPF_COEFF67,    0xffd1ff84},
-{6100000, DIF_BPF_COEFF89,    0xff66ffbe},
-{6100000, DIF_BPF_COEFF1011,  0x00960184},
-{6100000, DIF_BPF_COEFF1213,  0x01cd00da},
-{6100000, DIF_BPF_COEFF1415,  0xfeccfcb2},
-{6100000, DIF_BPF_COEFF1617,  0xfc17fdf9},
-{6100000, DIF_BPF_COEFF1819,  0x01e005bc},
-{6100000, DIF_BPF_COEFF2021,  0x06e703e4},
-{6100000, DIF_BPF_COEFF2223,  0xfdabf798},
-{6100000, DIF_BPF_COEFF2425,  0xf599f9b3},
-{6100000, DIF_BPF_COEFF2627,  0x02510abd},
-{6100000, DIF_BPF_COEFF2829,  0x0dbf08df},
-{6100000, DIF_BPF_COEFF3031,  0xfe48f3dc},
-{6100000, DIF_BPF_COEFF3233,  0xefd5f4f6},
-{6100000, DIF_BPF_COEFF3435,  0x00a20c3e},
-{6100000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 61_quant.dat*/
-
-
-/*case 6200000:*/
-/* BEGIN - DIF BPF register values from 62_quant.dat*/
-{6200000, DIF_BPF_COEFF01,    0xfffffffe},
-{6200000, DIF_BPF_COEFF23,    0x0002000f},
-{6200000, DIF_BPF_COEFF45,    0x0021001f},
-{6200000, DIF_BPF_COEFF67,    0xfff0ff97},
-{6200000, DIF_BPF_COEFF89,    0xff50ff74},
-{6200000, DIF_BPF_COEFF1011,  0x0034014a},
-{6200000, DIF_BPF_COEFF1213,  0x01fa0179},
-{6200000, DIF_BPF_COEFF1415,  0xff97fd2a},
-{6200000, DIF_BPF_COEFF1617,  0xfbd3fcfa},
-{6200000, DIF_BPF_COEFF1819,  0x00a304fe},
-{6200000, DIF_BPF_COEFF2021,  0x07310525},
-{6200000, DIF_BPF_COEFF2223,  0xff37f886},
-{6200000, DIF_BPF_COEFF2425,  0xf55cf86e},
-{6200000, DIF_BPF_COEFF2627,  0x00c709d0},
-{6200000, DIF_BPF_COEFF2829,  0x0de209db},
-{6200000, DIF_BPF_COEFF3031,  0xff6df484},
-{6200000, DIF_BPF_COEFF3233,  0xefcbf481},
-{6200000, DIF_BPF_COEFF3435,  0x00360c18},
-{6200000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 62_quant.dat*/
-
-
-/*case 6300000:*/
-/* BEGIN - DIF BPF register values from 63_quant.dat*/
-{6300000, DIF_BPF_COEFF01,    0xfffffffd},
-{6300000, DIF_BPF_COEFF23,    0xfffe000a},
-{6300000, DIF_BPF_COEFF45,    0x0021002f},
-{6300000, DIF_BPF_COEFF67,    0x0010ffb8},
-{6300000, DIF_BPF_COEFF89,    0xff50ff3b},
-{6300000, DIF_BPF_COEFF1011,  0xffcc00f0},
-{6300000, DIF_BPF_COEFF1213,  0x01fa01fa},
-{6300000, DIF_BPF_COEFF1415,  0x0069fdd4},
-{6300000, DIF_BPF_COEFF1617,  0xfbd3fc26},
-{6300000, DIF_BPF_COEFF1819,  0xff5d0407},
-{6300000, DIF_BPF_COEFF2021,  0x07310638},
-{6300000, DIF_BPF_COEFF2223,  0x00c9f9a8},
-{6300000, DIF_BPF_COEFF2425,  0xf55cf74e},
-{6300000, DIF_BPF_COEFF2627,  0xff3908c3},
-{6300000, DIF_BPF_COEFF2829,  0x0de20ac3},
-{6300000, DIF_BPF_COEFF3031,  0x0093f537},
-{6300000, DIF_BPF_COEFF3233,  0xefcbf410},
-{6300000, DIF_BPF_COEFF3435,  0xffca0bf2},
-{6300000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 63_quant.dat*/
-
-
-/*case 6400000:*/
-/* BEGIN - DIF BPF register values from 64_quant.dat*/
-{6400000, DIF_BPF_COEFF01,    0xfffffffd},
-{6400000, DIF_BPF_COEFF23,    0xfffb0003},
-{6400000, DIF_BPF_COEFF45,    0x001c0037},
-{6400000, DIF_BPF_COEFF67,    0x002fffe2},
-{6400000, DIF_BPF_COEFF89,    0xff66ff17},
-{6400000, DIF_BPF_COEFF1011,  0xff6a007e},
-{6400000, DIF_BPF_COEFF1213,  0x01cd0251},
-{6400000, DIF_BPF_COEFF1415,  0x0134fea5},
-{6400000, DIF_BPF_COEFF1617,  0xfc17fb8b},
-{6400000, DIF_BPF_COEFF1819,  0xfe2002e0},
-{6400000, DIF_BPF_COEFF2021,  0x06e70713},
-{6400000, DIF_BPF_COEFF2223,  0x0255faf5},
-{6400000, DIF_BPF_COEFF2425,  0xf599f658},
-{6400000, DIF_BPF_COEFF2627,  0xfdaf0799},
-{6400000, DIF_BPF_COEFF2829,  0x0dbf0b96},
-{6400000, DIF_BPF_COEFF3031,  0x01b8f5f5},
-{6400000, DIF_BPF_COEFF3233,  0xefd5f3a3},
-{6400000, DIF_BPF_COEFF3435,  0xff5e0bca},
-{6400000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 64_quant.dat*/
-
-
-/*case 6500000:*/
-/* BEGIN - DIF BPF register values from 65_quant.dat*/
-{6500000, DIF_BPF_COEFF01,    0x0000fffd},
-{6500000, DIF_BPF_COEFF23,    0xfff9fffb},
-{6500000, DIF_BPF_COEFF45,    0x00120037},
-{6500000, DIF_BPF_COEFF67,    0x00460010},
-{6500000, DIF_BPF_COEFF89,    0xff8eff0f},
-{6500000, DIF_BPF_COEFF1011,  0xff180000},
-{6500000, DIF_BPF_COEFF1213,  0x01750276},
-{6500000, DIF_BPF_COEFF1415,  0x01e8ff8d},
-{6500000, DIF_BPF_COEFF1617,  0xfc99fb31},
-{6500000, DIF_BPF_COEFF1819,  0xfcfb0198},
-{6500000, DIF_BPF_COEFF2021,  0x065607ad},
-{6500000, DIF_BPF_COEFF2223,  0x03cefc64},
-{6500000, DIF_BPF_COEFF2425,  0xf614f592},
-{6500000, DIF_BPF_COEFF2627,  0xfc2e0656},
-{6500000, DIF_BPF_COEFF2829,  0x0d770c52},
-{6500000, DIF_BPF_COEFF3031,  0x02daf6bd},
-{6500000, DIF_BPF_COEFF3233,  0xefeaf33b},
-{6500000, DIF_BPF_COEFF3435,  0xfef10ba3},
-{6500000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 65_quant.dat*/
-
-
-/*case 6600000:*/
-/* BEGIN - DIF BPF register values from 66_quant.dat*/
-{6600000, DIF_BPF_COEFF01,    0x0000fffe},
-{6600000, DIF_BPF_COEFF23,    0xfff7fff5},
-{6600000, DIF_BPF_COEFF45,    0x0005002f},
-{6600000, DIF_BPF_COEFF67,    0x0054003c},
-{6600000, DIF_BPF_COEFF89,    0xffc5ff22},
-{6600000, DIF_BPF_COEFF1011,  0xfedfff82},
-{6600000, DIF_BPF_COEFF1213,  0x00fc0267},
-{6600000, DIF_BPF_COEFF1415,  0x0276007e},
-{6600000, DIF_BPF_COEFF1617,  0xfd51fb1c},
-{6600000, DIF_BPF_COEFF1819,  0xfbfe003e},
-{6600000, DIF_BPF_COEFF2021,  0x05830802},
-{6600000, DIF_BPF_COEFF2223,  0x0529fdec},
-{6600000, DIF_BPF_COEFF2425,  0xf6c8f4fe},
-{6600000, DIF_BPF_COEFF2627,  0xfabd04ff},
-{6600000, DIF_BPF_COEFF2829,  0x0d0d0cf6},
-{6600000, DIF_BPF_COEFF3031,  0x03f8f78f},
-{6600000, DIF_BPF_COEFF3233,  0xf00af2d7},
-{6600000, DIF_BPF_COEFF3435,  0xfe850b7b},
-{6600000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 66_quant.dat*/
-
-
-/*case 6700000:*/
-/* BEGIN - DIF BPF register values from 67_quant.dat*/
-{6700000, DIF_BPF_COEFF01,    0x0000ffff},
-{6700000, DIF_BPF_COEFF23,    0xfff8fff0},
-{6700000, DIF_BPF_COEFF45,    0xfff80020},
-{6700000, DIF_BPF_COEFF67,    0x00560060},
-{6700000, DIF_BPF_COEFF89,    0x0002ff4e},
-{6700000, DIF_BPF_COEFF1011,  0xfec4ff10},
-{6700000, DIF_BPF_COEFF1213,  0x006d0225},
-{6700000, DIF_BPF_COEFF1415,  0x02d50166},
-{6700000, DIF_BPF_COEFF1617,  0xfe35fb4e},
-{6700000, DIF_BPF_COEFF1819,  0xfb35fee1},
-{6700000, DIF_BPF_COEFF2021,  0x0477080e},
-{6700000, DIF_BPF_COEFF2223,  0x065bff82},
-{6700000, DIF_BPF_COEFF2425,  0xf7b1f4a0},
-{6700000, DIF_BPF_COEFF2627,  0xf9610397},
-{6700000, DIF_BPF_COEFF2829,  0x0c810d80},
-{6700000, DIF_BPF_COEFF3031,  0x0510f869},
-{6700000, DIF_BPF_COEFF3233,  0xf033f278},
-{6700000, DIF_BPF_COEFF3435,  0xfe1a0b52},
-{6700000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 67_quant.dat*/
-
-
-/*case 6800000:*/
-/* BEGIN - DIF BPF register values from 68_quant.dat*/
-{6800000, DIF_BPF_COEFF01,    0x00010000},
-{6800000, DIF_BPF_COEFF23,    0xfffaffee},
-{6800000, DIF_BPF_COEFF45,    0xffec000c},
-{6800000, DIF_BPF_COEFF67,    0x004c0078},
-{6800000, DIF_BPF_COEFF89,    0x0040ff8e},
-{6800000, DIF_BPF_COEFF1011,  0xfecafeb6},
-{6800000, DIF_BPF_COEFF1213,  0xffd301b6},
-{6800000, DIF_BPF_COEFF1415,  0x02fc0235},
-{6800000, DIF_BPF_COEFF1617,  0xff36fbc5},
-{6800000, DIF_BPF_COEFF1819,  0xfaaafd90},
-{6800000, DIF_BPF_COEFF2021,  0x033e07d2},
-{6800000, DIF_BPF_COEFF2223,  0x075b011b},
-{6800000, DIF_BPF_COEFF2425,  0xf8cbf47a},
-{6800000, DIF_BPF_COEFF2627,  0xf81f0224},
-{6800000, DIF_BPF_COEFF2829,  0x0bd50def},
-{6800000, DIF_BPF_COEFF3031,  0x0621f94b},
-{6800000, DIF_BPF_COEFF3233,  0xf067f21e},
-{6800000, DIF_BPF_COEFF3435,  0xfdae0b29},
-{6800000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 68_quant.dat*/
-
-
-/*case 6900000:*/
-/* BEGIN - DIF BPF register values from 69_quant.dat*/
-{6900000, DIF_BPF_COEFF01,    0x00010001},
-{6900000, DIF_BPF_COEFF23,    0xfffdffef},
-{6900000, DIF_BPF_COEFF45,    0xffe3fff6},
-{6900000, DIF_BPF_COEFF67,    0x0037007f},
-{6900000, DIF_BPF_COEFF89,    0x0075ffdc},
-{6900000, DIF_BPF_COEFF1011,  0xfef2fe7c},
-{6900000, DIF_BPF_COEFF1213,  0xff3d0122},
-{6900000, DIF_BPF_COEFF1415,  0x02ea02dd},
-{6900000, DIF_BPF_COEFF1617,  0x0044fc79},
-{6900000, DIF_BPF_COEFF1819,  0xfa65fc5d},
-{6900000, DIF_BPF_COEFF2021,  0x01e3074e},
-{6900000, DIF_BPF_COEFF2223,  0x082102ad},
-{6900000, DIF_BPF_COEFF2425,  0xfa0ff48c},
-{6900000, DIF_BPF_COEFF2627,  0xf6fe00a9},
-{6900000, DIF_BPF_COEFF2829,  0x0b0a0e43},
-{6900000, DIF_BPF_COEFF3031,  0x0729fa33},
-{6900000, DIF_BPF_COEFF3233,  0xf0a5f1c9},
-{6900000, DIF_BPF_COEFF3435,  0xfd430b00},
-{6900000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 69_quant.dat*/
-
-
-/*case 7000000:*/
-/* BEGIN - DIF BPF register values from 70_quant.dat*/
-{7000000, DIF_BPF_COEFF01,    0x00010002},
-{7000000, DIF_BPF_COEFF23,    0x0001fff3},
-{7000000, DIF_BPF_COEFF45,    0xffdeffe2},
-{7000000, DIF_BPF_COEFF67,    0x001b0076},
-{7000000, DIF_BPF_COEFF89,    0x009c002d},
-{7000000, DIF_BPF_COEFF1011,  0xff35fe68},
-{7000000, DIF_BPF_COEFF1213,  0xfeba0076},
-{7000000, DIF_BPF_COEFF1415,  0x029f0352},
-{7000000, DIF_BPF_COEFF1617,  0x014dfd60},
-{7000000, DIF_BPF_COEFF1819,  0xfa69fb53},
-{7000000, DIF_BPF_COEFF2021,  0x00740688},
-{7000000, DIF_BPF_COEFF2223,  0x08a7042d},
-{7000000, DIF_BPF_COEFF2425,  0xfb75f4d6},
-{7000000, DIF_BPF_COEFF2627,  0xf600ff2d},
-{7000000, DIF_BPF_COEFF2829,  0x0a220e7a},
-{7000000, DIF_BPF_COEFF3031,  0x0827fb22},
-{7000000, DIF_BPF_COEFF3233,  0xf0edf17a},
-{7000000, DIF_BPF_COEFF3435,  0xfcd80ad6},
-{7000000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 70_quant.dat*/
-
-
-/*case 7100000:*/
-/* BEGIN - DIF BPF register values from 71_quant.dat*/
-{7100000, DIF_BPF_COEFF01,    0x00000003},
-{7100000, DIF_BPF_COEFF23,    0x0004fff9},
-{7100000, DIF_BPF_COEFF45,    0xffe0ffd2},
-{7100000, DIF_BPF_COEFF67,    0xfffb005e},
-{7100000, DIF_BPF_COEFF89,    0x00b0007a},
-{7100000, DIF_BPF_COEFF1011,  0xff8ffe7c},
-{7100000, DIF_BPF_COEFF1213,  0xfe53ffc1},
-{7100000, DIF_BPF_COEFF1415,  0x0221038c},
-{7100000, DIF_BPF_COEFF1617,  0x0241fe6e},
-{7100000, DIF_BPF_COEFF1819,  0xfab6fa80},
-{7100000, DIF_BPF_COEFF2021,  0xff010587},
-{7100000, DIF_BPF_COEFF2223,  0x08e90590},
-{7100000, DIF_BPF_COEFF2425,  0xfcf5f556},
-{7100000, DIF_BPF_COEFF2627,  0xf52bfdb3},
-{7100000, DIF_BPF_COEFF2829,  0x09210e95},
-{7100000, DIF_BPF_COEFF3031,  0x0919fc15},
-{7100000, DIF_BPF_COEFF3233,  0xf13ff12f},
-{7100000, DIF_BPF_COEFF3435,  0xfc6e0aab},
-{7100000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 71_quant.dat*/
-
-
-/*case 7200000:*/
-/* BEGIN - DIF BPF register values from 72_quant.dat*/
-{7200000, DIF_BPF_COEFF01,    0x00000003},
-{7200000, DIF_BPF_COEFF23,    0x00070000},
-{7200000, DIF_BPF_COEFF45,    0xffe6ffc9},
-{7200000, DIF_BPF_COEFF67,    0xffdb0039},
-{7200000, DIF_BPF_COEFF89,    0x00af00b8},
-{7200000, DIF_BPF_COEFF1011,  0xfff4feb6},
-{7200000, DIF_BPF_COEFF1213,  0xfe13ff10},
-{7200000, DIF_BPF_COEFF1415,  0x01790388},
-{7200000, DIF_BPF_COEFF1617,  0x0311ff92},
-{7200000, DIF_BPF_COEFF1819,  0xfb48f9ed},
-{7200000, DIF_BPF_COEFF2021,  0xfd980453},
-{7200000, DIF_BPF_COEFF2223,  0x08e306cd},
-{7200000, DIF_BPF_COEFF2425,  0xfe88f60a},
-{7200000, DIF_BPF_COEFF2627,  0xf482fc40},
-{7200000, DIF_BPF_COEFF2829,  0x08080e93},
-{7200000, DIF_BPF_COEFF3031,  0x09fdfd0c},
-{7200000, DIF_BPF_COEFF3233,  0xf19af0ea},
-{7200000, DIF_BPF_COEFF3435,  0xfc050a81},
-{7200000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 72_quant.dat*/
-
-
-/*case 7300000:*/
-/* BEGIN - DIF BPF register values from 73_quant.dat*/
-{7300000, DIF_BPF_COEFF01,    0x00000002},
-{7300000, DIF_BPF_COEFF23,    0x00080008},
-{7300000, DIF_BPF_COEFF45,    0xfff0ffc9},
-{7300000, DIF_BPF_COEFF67,    0xffc1000d},
-{7300000, DIF_BPF_COEFF89,    0x009800e2},
-{7300000, DIF_BPF_COEFF1011,  0x005bff10},
-{7300000, DIF_BPF_COEFF1213,  0xfe00fe74},
-{7300000, DIF_BPF_COEFF1415,  0x00b50345},
-{7300000, DIF_BPF_COEFF1617,  0x03b000bc},
-{7300000, DIF_BPF_COEFF1819,  0xfc18f9a1},
-{7300000, DIF_BPF_COEFF2021,  0xfc4802f9},
-{7300000, DIF_BPF_COEFF2223,  0x089807dc},
-{7300000, DIF_BPF_COEFF2425,  0x0022f6f0},
-{7300000, DIF_BPF_COEFF2627,  0xf407fada},
-{7300000, DIF_BPF_COEFF2829,  0x06da0e74},
-{7300000, DIF_BPF_COEFF3031,  0x0ad3fe06},
-{7300000, DIF_BPF_COEFF3233,  0xf1fef0ab},
-{7300000, DIF_BPF_COEFF3435,  0xfb9c0a55},
-{7300000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 73_quant.dat*/
-
-
-/*case 7400000:*/
-/* BEGIN - DIF BPF register values from 74_quant.dat*/
-{7400000, DIF_BPF_COEFF01,    0x00000001},
-{7400000, DIF_BPF_COEFF23,    0x0008000e},
-{7400000, DIF_BPF_COEFF45,    0xfffdffd0},
-{7400000, DIF_BPF_COEFF67,    0xffafffdf},
-{7400000, DIF_BPF_COEFF89,    0x006e00f2},
-{7400000, DIF_BPF_COEFF1011,  0x00b8ff82},
-{7400000, DIF_BPF_COEFF1213,  0xfe1bfdf8},
-{7400000, DIF_BPF_COEFF1415,  0xffe302c8},
-{7400000, DIF_BPF_COEFF1617,  0x041301dc},
-{7400000, DIF_BPF_COEFF1819,  0xfd1af99e},
-{7400000, DIF_BPF_COEFF2021,  0xfb1e0183},
-{7400000, DIF_BPF_COEFF2223,  0x080908b5},
-{7400000, DIF_BPF_COEFF2425,  0x01bcf801},
-{7400000, DIF_BPF_COEFF2627,  0xf3bdf985},
-{7400000, DIF_BPF_COEFF2829,  0x059a0e38},
-{7400000, DIF_BPF_COEFF3031,  0x0b99ff03},
-{7400000, DIF_BPF_COEFF3233,  0xf26cf071},
-{7400000, DIF_BPF_COEFF3435,  0xfb330a2a},
-{7400000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 74_quant.dat*/
-
-
-/*case 7500000:*/
-/* BEGIN - DIF BPF register values from 75_quant.dat*/
-{7500000, DIF_BPF_COEFF01,    0xffff0000},
-{7500000, DIF_BPF_COEFF23,    0x00070011},
-{7500000, DIF_BPF_COEFF45,    0x000affdf},
-{7500000, DIF_BPF_COEFF67,    0xffa9ffb5},
-{7500000, DIF_BPF_COEFF89,    0x003700e6},
-{7500000, DIF_BPF_COEFF1011,  0x01010000},
-{7500000, DIF_BPF_COEFF1213,  0xfe62fda8},
-{7500000, DIF_BPF_COEFF1415,  0xff140219},
-{7500000, DIF_BPF_COEFF1617,  0x043502e1},
-{7500000, DIF_BPF_COEFF1819,  0xfe42f9e6},
-{7500000, DIF_BPF_COEFF2021,  0xfa270000},
-{7500000, DIF_BPF_COEFF2223,  0x073a0953},
-{7500000, DIF_BPF_COEFF2425,  0x034cf939},
-{7500000, DIF_BPF_COEFF2627,  0xf3a4f845},
-{7500000, DIF_BPF_COEFF2829,  0x044c0de1},
-{7500000, DIF_BPF_COEFF3031,  0x0c4f0000},
-{7500000, DIF_BPF_COEFF3233,  0xf2e2f03c},
-{7500000, DIF_BPF_COEFF3435,  0xfacc09fe},
-{7500000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 75_quant.dat*/
-
-
-/*case 7600000:*/
-/* BEGIN - DIF BPF register values from 76_quant.dat*/
-{7600000, DIF_BPF_COEFF01,    0xffffffff},
-{7600000, DIF_BPF_COEFF23,    0x00040012},
-{7600000, DIF_BPF_COEFF45,    0x0016fff3},
-{7600000, DIF_BPF_COEFF67,    0xffafff95},
-{7600000, DIF_BPF_COEFF89,    0xfff900c0},
-{7600000, DIF_BPF_COEFF1011,  0x0130007e},
-{7600000, DIF_BPF_COEFF1213,  0xfecefd89},
-{7600000, DIF_BPF_COEFF1415,  0xfe560146},
-{7600000, DIF_BPF_COEFF1617,  0x041303bc},
-{7600000, DIF_BPF_COEFF1819,  0xff81fa76},
-{7600000, DIF_BPF_COEFF2021,  0xf96cfe7d},
-{7600000, DIF_BPF_COEFF2223,  0x063209b1},
-{7600000, DIF_BPF_COEFF2425,  0x04c9fa93},
-{7600000, DIF_BPF_COEFF2627,  0xf3bdf71e},
-{7600000, DIF_BPF_COEFF2829,  0x02f30d6e},
-{7600000, DIF_BPF_COEFF3031,  0x0cf200fd},
-{7600000, DIF_BPF_COEFF3233,  0xf361f00e},
-{7600000, DIF_BPF_COEFF3435,  0xfa6509d1},
-{7600000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 76_quant.dat*/
-
-
-/*case 7700000:*/
-/* BEGIN - DIF BPF register values from 77_quant.dat*/
-{7700000, DIF_BPF_COEFF01,    0xfffffffe},
-{7700000, DIF_BPF_COEFF23,    0x00010010},
-{7700000, DIF_BPF_COEFF45,    0x001e0008},
-{7700000, DIF_BPF_COEFF67,    0xffc1ff84},
-{7700000, DIF_BPF_COEFF89,    0xffbc0084},
-{7700000, DIF_BPF_COEFF1011,  0x013e00f0},
-{7700000, DIF_BPF_COEFF1213,  0xff56fd9f},
-{7700000, DIF_BPF_COEFF1415,  0xfdb8005c},
-{7700000, DIF_BPF_COEFF1617,  0x03b00460},
-{7700000, DIF_BPF_COEFF1819,  0x00c7fb45},
-{7700000, DIF_BPF_COEFF2021,  0xf8f4fd07},
-{7700000, DIF_BPF_COEFF2223,  0x04fa09ce},
-{7700000, DIF_BPF_COEFF2425,  0x062afc07},
-{7700000, DIF_BPF_COEFF2627,  0xf407f614},
-{7700000, DIF_BPF_COEFF2829,  0x01920ce0},
-{7700000, DIF_BPF_COEFF3031,  0x0d8301fa},
-{7700000, DIF_BPF_COEFF3233,  0xf3e8efe5},
-{7700000, DIF_BPF_COEFF3435,  0xfa0009a4},
-{7700000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 77_quant.dat*/
-
-
-/*case 7800000:*/
-/* BEGIN - DIF BPF register values from 78_quant.dat*/
-{7800000, DIF_BPF_COEFF01,    0x0000fffd},
-{7800000, DIF_BPF_COEFF23,    0xfffd000b},
-{7800000, DIF_BPF_COEFF45,    0x0022001d},
-{7800000, DIF_BPF_COEFF67,    0xffdbff82},
-{7800000, DIF_BPF_COEFF89,    0xff870039},
-{7800000, DIF_BPF_COEFF1011,  0x012a014a},
-{7800000, DIF_BPF_COEFF1213,  0xffedfde7},
-{7800000, DIF_BPF_COEFF1415,  0xfd47ff6b},
-{7800000, DIF_BPF_COEFF1617,  0x031104c6},
-{7800000, DIF_BPF_COEFF1819,  0x0202fc4c},
-{7800000, DIF_BPF_COEFF2021,  0xf8c6fbad},
-{7800000, DIF_BPF_COEFF2223,  0x039909a7},
-{7800000, DIF_BPF_COEFF2425,  0x0767fd8e},
-{7800000, DIF_BPF_COEFF2627,  0xf482f52b},
-{7800000, DIF_BPF_COEFF2829,  0x002d0c39},
-{7800000, DIF_BPF_COEFF3031,  0x0e0002f4},
-{7800000, DIF_BPF_COEFF3233,  0xf477efc2},
-{7800000, DIF_BPF_COEFF3435,  0xf99b0977},
-{7800000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 78_quant.dat*/
-
-
-/*case 7900000:*/
-/* BEGIN - DIF BPF register values from 79_quant.dat*/
-{7900000, DIF_BPF_COEFF01,    0x0000fffd},
-{7900000, DIF_BPF_COEFF23,    0xfffa0004},
-{7900000, DIF_BPF_COEFF45,    0x0020002d},
-{7900000, DIF_BPF_COEFF67,    0xfffbff91},
-{7900000, DIF_BPF_COEFF89,    0xff61ffe8},
-{7900000, DIF_BPF_COEFF1011,  0x00f70184},
-{7900000, DIF_BPF_COEFF1213,  0x0086fe5c},
-{7900000, DIF_BPF_COEFF1415,  0xfd0bfe85},
-{7900000, DIF_BPF_COEFF1617,  0x024104e5},
-{7900000, DIF_BPF_COEFF1819,  0x0323fd7d},
-{7900000, DIF_BPF_COEFF2021,  0xf8e2fa79},
-{7900000, DIF_BPF_COEFF2223,  0x021d093f},
-{7900000, DIF_BPF_COEFF2425,  0x0879ff22},
-{7900000, DIF_BPF_COEFF2627,  0xf52bf465},
-{7900000, DIF_BPF_COEFF2829,  0xfec70b79},
-{7900000, DIF_BPF_COEFF3031,  0x0e6803eb},
-{7900000, DIF_BPF_COEFF3233,  0xf50defa5},
-{7900000, DIF_BPF_COEFF3435,  0xf937094a},
-{7900000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 79_quant.dat*/
-
-
-/*case 8000000:*/
-/* BEGIN - DIF BPF register values from 80_quant.dat*/
-{8000000, DIF_BPF_COEFF01,    0x0000fffe},
-{8000000, DIF_BPF_COEFF23,    0xfff8fffd},
-{8000000, DIF_BPF_COEFF45,    0x00190036},
-{8000000, DIF_BPF_COEFF67,    0x001bffaf},
-{8000000, DIF_BPF_COEFF89,    0xff4fff99},
-{8000000, DIF_BPF_COEFF1011,  0x00aa0198},
-{8000000, DIF_BPF_COEFF1213,  0x0112fef3},
-{8000000, DIF_BPF_COEFF1415,  0xfd09fdb9},
-{8000000, DIF_BPF_COEFF1617,  0x014d04be},
-{8000000, DIF_BPF_COEFF1819,  0x041bfecc},
-{8000000, DIF_BPF_COEFF2021,  0xf947f978},
-{8000000, DIF_BPF_COEFF2223,  0x00900897},
-{8000000, DIF_BPF_COEFF2425,  0x095a00b9},
-{8000000, DIF_BPF_COEFF2627,  0xf600f3c5},
-{8000000, DIF_BPF_COEFF2829,  0xfd650aa3},
-{8000000, DIF_BPF_COEFF3031,  0x0ebc04de},
-{8000000, DIF_BPF_COEFF3233,  0xf5aaef8e},
-{8000000, DIF_BPF_COEFF3435,  0xf8d5091c},
-{8000000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 80_quant.dat*/
-
-
-/*case 8100000:*/
-/* BEGIN - DIF BPF register values from 81_quant.dat*/
-{8100000, DIF_BPF_COEFF01,    0x0000ffff},
-{8100000, DIF_BPF_COEFF23,    0xfff7fff6},
-{8100000, DIF_BPF_COEFF45,    0x000e0038},
-{8100000, DIF_BPF_COEFF67,    0x0037ffd7},
-{8100000, DIF_BPF_COEFF89,    0xff52ff56},
-{8100000, DIF_BPF_COEFF1011,  0x004b0184},
-{8100000, DIF_BPF_COEFF1213,  0x0186ffa1},
-{8100000, DIF_BPF_COEFF1415,  0xfd40fd16},
-{8100000, DIF_BPF_COEFF1617,  0x00440452},
-{8100000, DIF_BPF_COEFF1819,  0x04de0029},
-{8100000, DIF_BPF_COEFF2021,  0xf9f2f8b2},
-{8100000, DIF_BPF_COEFF2223,  0xfefe07b5},
-{8100000, DIF_BPF_COEFF2425,  0x0a05024d},
-{8100000, DIF_BPF_COEFF2627,  0xf6fef34d},
-{8100000, DIF_BPF_COEFF2829,  0xfc0a09b8},
-{8100000, DIF_BPF_COEFF3031,  0x0efa05cd},
-{8100000, DIF_BPF_COEFF3233,  0xf64eef7d},
-{8100000, DIF_BPF_COEFF3435,  0xf87308ed},
-{8100000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 81_quant.dat*/
-
-
-/*case 8200000:*/
-/* BEGIN - DIF BPF register values from 82_quant.dat*/
-{8200000, DIF_BPF_COEFF01,    0x00010000},
-{8200000, DIF_BPF_COEFF23,    0xfff8fff0},
-{8200000, DIF_BPF_COEFF45,    0x00000031},
-{8200000, DIF_BPF_COEFF67,    0x004c0005},
-{8200000, DIF_BPF_COEFF89,    0xff6aff27},
-{8200000, DIF_BPF_COEFF1011,  0xffe4014a},
-{8200000, DIF_BPF_COEFF1213,  0x01d70057},
-{8200000, DIF_BPF_COEFF1415,  0xfdacfca6},
-{8200000, DIF_BPF_COEFF1617,  0xff3603a7},
-{8200000, DIF_BPF_COEFF1819,  0x05610184},
-{8200000, DIF_BPF_COEFF2021,  0xfadbf82e},
-{8200000, DIF_BPF_COEFF2223,  0xfd74069f},
-{8200000, DIF_BPF_COEFF2425,  0x0a7503d6},
-{8200000, DIF_BPF_COEFF2627,  0xf81ff2ff},
-{8200000, DIF_BPF_COEFF2829,  0xfab808b9},
-{8200000, DIF_BPF_COEFF3031,  0x0f2306b5},
-{8200000, DIF_BPF_COEFF3233,  0xf6f9ef72},
-{8200000, DIF_BPF_COEFF3435,  0xf81308bf},
-{8200000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 82_quant.dat*/
-
-
-/*case 8300000:*/
-/* BEGIN - DIF BPF register values from 83_quant.dat*/
-{8300000, DIF_BPF_COEFF01,    0x00010001},
-{8300000, DIF_BPF_COEFF23,    0xfffbffee},
-{8300000, DIF_BPF_COEFF45,    0xfff30022},
-{8300000, DIF_BPF_COEFF67,    0x00560032},
-{8300000, DIF_BPF_COEFF89,    0xff95ff10},
-{8300000, DIF_BPF_COEFF1011,  0xff8000f0},
-{8300000, DIF_BPF_COEFF1213,  0x01fe0106},
-{8300000, DIF_BPF_COEFF1415,  0xfe46fc71},
-{8300000, DIF_BPF_COEFF1617,  0xfe3502c7},
-{8300000, DIF_BPF_COEFF1819,  0x059e02ce},
-{8300000, DIF_BPF_COEFF2021,  0xfbf9f7f2},
-{8300000, DIF_BPF_COEFF2223,  0xfbff055b},
-{8300000, DIF_BPF_COEFF2425,  0x0aa9054c},
-{8300000, DIF_BPF_COEFF2627,  0xf961f2db},
-{8300000, DIF_BPF_COEFF2829,  0xf97507aa},
-{8300000, DIF_BPF_COEFF3031,  0x0f350797},
-{8300000, DIF_BPF_COEFF3233,  0xf7a9ef6d},
-{8300000, DIF_BPF_COEFF3435,  0xf7b40890},
-{8300000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 83_quant.dat*/
-
-
-/*case 8400000:*/
-/* BEGIN - DIF BPF register values from 84_quant.dat*/
-{8400000, DIF_BPF_COEFF01,    0x00010002},
-{8400000, DIF_BPF_COEFF23,    0xfffeffee},
-{8400000, DIF_BPF_COEFF45,    0xffe8000f},
-{8400000, DIF_BPF_COEFF67,    0x00540058},
-{8400000, DIF_BPF_COEFF89,    0xffcdff14},
-{8400000, DIF_BPF_COEFF1011,  0xff29007e},
-{8400000, DIF_BPF_COEFF1213,  0x01f6019e},
-{8400000, DIF_BPF_COEFF1415,  0xff01fc7c},
-{8400000, DIF_BPF_COEFF1617,  0xfd5101bf},
-{8400000, DIF_BPF_COEFF1819,  0x059203f6},
-{8400000, DIF_BPF_COEFF2021,  0xfd41f7fe},
-{8400000, DIF_BPF_COEFF2223,  0xfaa903f3},
-{8400000, DIF_BPF_COEFF2425,  0x0a9e06a9},
-{8400000, DIF_BPF_COEFF2627,  0xfabdf2e2},
-{8400000, DIF_BPF_COEFF2829,  0xf842068b},
-{8400000, DIF_BPF_COEFF3031,  0x0f320871},
-{8400000, DIF_BPF_COEFF3233,  0xf85eef6e},
-{8400000, DIF_BPF_COEFF3435,  0xf7560860},
-{8400000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 84_quant.dat*/
-
-
-/*case 8500000:*/
-/* BEGIN - DIF BPF register values from 85_quant.dat*/
-{8500000, DIF_BPF_COEFF01,    0x00000003},
-{8500000, DIF_BPF_COEFF23,    0x0002fff2},
-{8500000, DIF_BPF_COEFF45,    0xffe1fff9},
-{8500000, DIF_BPF_COEFF67,    0x00460073},
-{8500000, DIF_BPF_COEFF89,    0x000bff34},
-{8500000, DIF_BPF_COEFF1011,  0xfee90000},
-{8500000, DIF_BPF_COEFF1213,  0x01c10215},
-{8500000, DIF_BPF_COEFF1415,  0xffd0fcc5},
-{8500000, DIF_BPF_COEFF1617,  0xfc99009d},
-{8500000, DIF_BPF_COEFF1819,  0x053d04f1},
-{8500000, DIF_BPF_COEFF2021,  0xfea5f853},
-{8500000, DIF_BPF_COEFF2223,  0xf97d0270},
-{8500000, DIF_BPF_COEFF2425,  0x0a5607e4},
-{8500000, DIF_BPF_COEFF2627,  0xfc2ef314},
-{8500000, DIF_BPF_COEFF2829,  0xf723055f},
-{8500000, DIF_BPF_COEFF3031,  0x0f180943},
-{8500000, DIF_BPF_COEFF3233,  0xf919ef75},
-{8500000, DIF_BPF_COEFF3435,  0xf6fa0830},
-{8500000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 85_quant.dat*/
-
-
-/*case 8600000:*/
-/* BEGIN - DIF BPF register values from 86_quant.dat*/
-{8600000, DIF_BPF_COEFF01,    0x00000003},
-{8600000, DIF_BPF_COEFF23,    0x0005fff8},
-{8600000, DIF_BPF_COEFF45,    0xffdeffe4},
-{8600000, DIF_BPF_COEFF67,    0x002f007f},
-{8600000, DIF_BPF_COEFF89,    0x0048ff6b},
-{8600000, DIF_BPF_COEFF1011,  0xfec7ff82},
-{8600000, DIF_BPF_COEFF1213,  0x0163025f},
-{8600000, DIF_BPF_COEFF1415,  0x00a2fd47},
-{8600000, DIF_BPF_COEFF1617,  0xfc17ff73},
-{8600000, DIF_BPF_COEFF1819,  0x04a405b2},
-{8600000, DIF_BPF_COEFF2021,  0x0017f8ed},
-{8600000, DIF_BPF_COEFF2223,  0xf88500dc},
-{8600000, DIF_BPF_COEFF2425,  0x09d208f9},
-{8600000, DIF_BPF_COEFF2627,  0xfdaff370},
-{8600000, DIF_BPF_COEFF2829,  0xf61c0429},
-{8600000, DIF_BPF_COEFF3031,  0x0ee80a0b},
-{8600000, DIF_BPF_COEFF3233,  0xf9d8ef82},
-{8600000, DIF_BPF_COEFF3435,  0xf6a00800},
-{8600000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 86_quant.dat*/
-
-
-/*case 8700000:*/
-/* BEGIN - DIF BPF register values from 87_quant.dat*/
-{8700000, DIF_BPF_COEFF01,    0x00000003},
-{8700000, DIF_BPF_COEFF23,    0x0007ffff},
-{8700000, DIF_BPF_COEFF45,    0xffe1ffd4},
-{8700000, DIF_BPF_COEFF67,    0x0010007a},
-{8700000, DIF_BPF_COEFF89,    0x007cffb2},
-{8700000, DIF_BPF_COEFF1011,  0xfec6ff10},
-{8700000, DIF_BPF_COEFF1213,  0x00e60277},
-{8700000, DIF_BPF_COEFF1415,  0x0168fdf9},
-{8700000, DIF_BPF_COEFF1617,  0xfbd3fe50},
-{8700000, DIF_BPF_COEFF1819,  0x03ce0631},
-{8700000, DIF_BPF_COEFF2021,  0x0188f9c8},
-{8700000, DIF_BPF_COEFF2223,  0xf7c7ff43},
-{8700000, DIF_BPF_COEFF2425,  0x091509e3},
-{8700000, DIF_BPF_COEFF2627,  0xff39f3f6},
-{8700000, DIF_BPF_COEFF2829,  0xf52d02ea},
-{8700000, DIF_BPF_COEFF3031,  0x0ea30ac9},
-{8700000, DIF_BPF_COEFF3233,  0xfa9bef95},
-{8700000, DIF_BPF_COEFF3435,  0xf64607d0},
-{8700000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 87_quant.dat*/
-
-
-/*case 8800000:*/
-/* BEGIN - DIF BPF register values from 88_quant.dat*/
-{8800000, DIF_BPF_COEFF01,    0x00000002},
-{8800000, DIF_BPF_COEFF23,    0x00090007},
-{8800000, DIF_BPF_COEFF45,    0xffe9ffca},
-{8800000, DIF_BPF_COEFF67,    0xfff00065},
-{8800000, DIF_BPF_COEFF89,    0x00a10003},
-{8800000, DIF_BPF_COEFF1011,  0xfee6feb6},
-{8800000, DIF_BPF_COEFF1213,  0x0053025b},
-{8800000, DIF_BPF_COEFF1415,  0x0213fed0},
-{8800000, DIF_BPF_COEFF1617,  0xfbd3fd46},
-{8800000, DIF_BPF_COEFF1819,  0x02c70668},
-{8800000, DIF_BPF_COEFF2021,  0x02eafadb},
-{8800000, DIF_BPF_COEFF2223,  0xf74bfdae},
-{8800000, DIF_BPF_COEFF2425,  0x08230a9c},
-{8800000, DIF_BPF_COEFF2627,  0x00c7f4a3},
-{8800000, DIF_BPF_COEFF2829,  0xf45b01a6},
-{8800000, DIF_BPF_COEFF3031,  0x0e480b7c},
-{8800000, DIF_BPF_COEFF3233,  0xfb61efae},
-{8800000, DIF_BPF_COEFF3435,  0xf5ef079f},
-{8800000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 88_quant.dat*/
-
-
-/*case 8900000:*/
-/* BEGIN - DIF BPF register values from 89_quant.dat*/
-{8900000, DIF_BPF_COEFF01,    0xffff0000},
-{8900000, DIF_BPF_COEFF23,    0x0008000d},
-{8900000, DIF_BPF_COEFF45,    0xfff5ffc8},
-{8900000, DIF_BPF_COEFF67,    0xffd10043},
-{8900000, DIF_BPF_COEFF89,    0x00b20053},
-{8900000, DIF_BPF_COEFF1011,  0xff24fe7c},
-{8900000, DIF_BPF_COEFF1213,  0xffb9020c},
-{8900000, DIF_BPF_COEFF1415,  0x0295ffbb},
-{8900000, DIF_BPF_COEFF1617,  0xfc17fc64},
-{8900000, DIF_BPF_COEFF1819,  0x019b0654},
-{8900000, DIF_BPF_COEFF2021,  0x042dfc1c},
-{8900000, DIF_BPF_COEFF2223,  0xf714fc2a},
-{8900000, DIF_BPF_COEFF2425,  0x07020b21},
-{8900000, DIF_BPF_COEFF2627,  0x0251f575},
-{8900000, DIF_BPF_COEFF2829,  0xf3a7005e},
-{8900000, DIF_BPF_COEFF3031,  0x0dd80c24},
-{8900000, DIF_BPF_COEFF3233,  0xfc2aefcd},
-{8900000, DIF_BPF_COEFF3435,  0xf599076e},
-{8900000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 89_quant.dat*/
-
-
-/*case 9000000:*/
-/* BEGIN - DIF BPF register values from 90_quant.dat*/
-{9000000, DIF_BPF_COEFF01,    0xffffffff},
-{9000000, DIF_BPF_COEFF23,    0x00060011},
-{9000000, DIF_BPF_COEFF45,    0x0002ffcf},
-{9000000, DIF_BPF_COEFF67,    0xffba0018},
-{9000000, DIF_BPF_COEFF89,    0x00ad009a},
-{9000000, DIF_BPF_COEFF1011,  0xff79fe68},
-{9000000, DIF_BPF_COEFF1213,  0xff260192},
-{9000000, DIF_BPF_COEFF1415,  0x02e500ab},
-{9000000, DIF_BPF_COEFF1617,  0xfc99fbb6},
-{9000000, DIF_BPF_COEFF1819,  0x005b05f7},
-{9000000, DIF_BPF_COEFF2021,  0x0545fd81},
-{9000000, DIF_BPF_COEFF2223,  0xf723fabf},
-{9000000, DIF_BPF_COEFF2425,  0x05b80b70},
-{9000000, DIF_BPF_COEFF2627,  0x03d2f669},
-{9000000, DIF_BPF_COEFF2829,  0xf313ff15},
-{9000000, DIF_BPF_COEFF3031,  0x0d550cbf},
-{9000000, DIF_BPF_COEFF3233,  0xfcf6eff2},
-{9000000, DIF_BPF_COEFF3435,  0xf544073d},
-{9000000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 90_quant.dat*/
-
-
-/*case 9100000:*/
-/* BEGIN - DIF BPF register values from 91_quant.dat*/
-{9100000, DIF_BPF_COEFF01,    0xfffffffe},
-{9100000, DIF_BPF_COEFF23,    0x00030012},
-{9100000, DIF_BPF_COEFF45,    0x000fffdd},
-{9100000, DIF_BPF_COEFF67,    0xffacffea},
-{9100000, DIF_BPF_COEFF89,    0x009300cf},
-{9100000, DIF_BPF_COEFF1011,  0xffdcfe7c},
-{9100000, DIF_BPF_COEFF1213,  0xfea600f7},
-{9100000, DIF_BPF_COEFF1415,  0x02fd0190},
-{9100000, DIF_BPF_COEFF1617,  0xfd51fb46},
-{9100000, DIF_BPF_COEFF1819,  0xff150554},
-{9100000, DIF_BPF_COEFF2021,  0x0627fefd},
-{9100000, DIF_BPF_COEFF2223,  0xf778f978},
-{9100000, DIF_BPF_COEFF2425,  0x044d0b87},
-{9100000, DIF_BPF_COEFF2627,  0x0543f77d},
-{9100000, DIF_BPF_COEFF2829,  0xf2a0fdcf},
-{9100000, DIF_BPF_COEFF3031,  0x0cbe0d4e},
-{9100000, DIF_BPF_COEFF3233,  0xfdc4f01d},
-{9100000, DIF_BPF_COEFF3435,  0xf4f2070b},
-{9100000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 91_quant.dat*/
-
-
-/*case 9200000:*/
-/* BEGIN - DIF BPF register values from 92_quant.dat*/
-{9200000, DIF_BPF_COEFF01,    0x0000fffd},
-{9200000, DIF_BPF_COEFF23,    0x00000010},
-{9200000, DIF_BPF_COEFF45,    0x001afff0},
-{9200000, DIF_BPF_COEFF67,    0xffaaffbf},
-{9200000, DIF_BPF_COEFF89,    0x006700ed},
-{9200000, DIF_BPF_COEFF1011,  0x0043feb6},
-{9200000, DIF_BPF_COEFF1213,  0xfe460047},
-{9200000, DIF_BPF_COEFF1415,  0x02db0258},
-{9200000, DIF_BPF_COEFF1617,  0xfe35fb1b},
-{9200000, DIF_BPF_COEFF1819,  0xfddc0473},
-{9200000, DIF_BPF_COEFF2021,  0x06c90082},
-{9200000, DIF_BPF_COEFF2223,  0xf811f85e},
-{9200000, DIF_BPF_COEFF2425,  0x02c90b66},
-{9200000, DIF_BPF_COEFF2627,  0x069ff8ad},
-{9200000, DIF_BPF_COEFF2829,  0xf250fc8d},
-{9200000, DIF_BPF_COEFF3031,  0x0c140dcf},
-{9200000, DIF_BPF_COEFF3233,  0xfe93f04d},
-{9200000, DIF_BPF_COEFF3435,  0xf4a106d9},
-{9200000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 92_quant.dat*/
-
-
-/*case 9300000:*/
-/* BEGIN - DIF BPF register values from 93_quant.dat*/
-{9300000, DIF_BPF_COEFF01,    0x0000fffd},
-{9300000, DIF_BPF_COEFF23,    0xfffc000c},
-{9300000, DIF_BPF_COEFF45,    0x00200006},
-{9300000, DIF_BPF_COEFF67,    0xffb4ff9c},
-{9300000, DIF_BPF_COEFF89,    0x002f00ef},
-{9300000, DIF_BPF_COEFF1011,  0x00a4ff10},
-{9300000, DIF_BPF_COEFF1213,  0xfe0dff92},
-{9300000, DIF_BPF_COEFF1415,  0x028102f7},
-{9300000, DIF_BPF_COEFF1617,  0xff36fb37},
-{9300000, DIF_BPF_COEFF1819,  0xfcbf035e},
-{9300000, DIF_BPF_COEFF2021,  0x07260202},
-{9300000, DIF_BPF_COEFF2223,  0xf8e8f778},
-{9300000, DIF_BPF_COEFF2425,  0x01340b0d},
-{9300000, DIF_BPF_COEFF2627,  0x07e1f9f4},
-{9300000, DIF_BPF_COEFF2829,  0xf223fb51},
-{9300000, DIF_BPF_COEFF3031,  0x0b590e42},
-{9300000, DIF_BPF_COEFF3233,  0xff64f083},
-{9300000, DIF_BPF_COEFF3435,  0xf45206a7},
-{9300000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 93_quant.dat*/
-
-
-/*case 9400000:*/
-/* BEGIN - DIF BPF register values from 94_quant.dat*/
-{9400000, DIF_BPF_COEFF01,    0x0000fffd},
-{9400000, DIF_BPF_COEFF23,    0xfff90005},
-{9400000, DIF_BPF_COEFF45,    0x0022001a},
-{9400000, DIF_BPF_COEFF67,    0xffc9ff86},
-{9400000, DIF_BPF_COEFF89,    0xfff000d7},
-{9400000, DIF_BPF_COEFF1011,  0x00f2ff82},
-{9400000, DIF_BPF_COEFF1213,  0xfe01fee5},
-{9400000, DIF_BPF_COEFF1415,  0x01f60362},
-{9400000, DIF_BPF_COEFF1617,  0x0044fb99},
-{9400000, DIF_BPF_COEFF1819,  0xfbcc0222},
-{9400000, DIF_BPF_COEFF2021,  0x07380370},
-{9400000, DIF_BPF_COEFF2223,  0xf9f7f6cc},
-{9400000, DIF_BPF_COEFF2425,  0xff990a7e},
-{9400000, DIF_BPF_COEFF2627,  0x0902fb50},
-{9400000, DIF_BPF_COEFF2829,  0xf21afa1f},
-{9400000, DIF_BPF_COEFF3031,  0x0a8d0ea6},
-{9400000, DIF_BPF_COEFF3233,  0x0034f0bf},
-{9400000, DIF_BPF_COEFF3435,  0xf4050675},
-{9400000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 94_quant.dat*/
-
-
-/*case 9500000:*/
-/* BEGIN - DIF BPF register values from 95_quant.dat*/
-{9500000, DIF_BPF_COEFF01,    0x0000fffe},
-{9500000, DIF_BPF_COEFF23,    0xfff8fffe},
-{9500000, DIF_BPF_COEFF45,    0x001e002b},
-{9500000, DIF_BPF_COEFF67,    0xffe5ff81},
-{9500000, DIF_BPF_COEFF89,    0xffb400a5},
-{9500000, DIF_BPF_COEFF1011,  0x01280000},
-{9500000, DIF_BPF_COEFF1213,  0xfe24fe50},
-{9500000, DIF_BPF_COEFF1415,  0x01460390},
-{9500000, DIF_BPF_COEFF1617,  0x014dfc3a},
-{9500000, DIF_BPF_COEFF1819,  0xfb1000ce},
-{9500000, DIF_BPF_COEFF2021,  0x070104bf},
-{9500000, DIF_BPF_COEFF2223,  0xfb37f65f},
-{9500000, DIF_BPF_COEFF2425,  0xfe0009bc},
-{9500000, DIF_BPF_COEFF2627,  0x0a00fcbb},
-{9500000, DIF_BPF_COEFF2829,  0xf235f8f8},
-{9500000, DIF_BPF_COEFF3031,  0x09b20efc},
-{9500000, DIF_BPF_COEFF3233,  0x0105f101},
-{9500000, DIF_BPF_COEFF3435,  0xf3ba0642},
-{9500000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 95_quant.dat*/
-
-
-/*case 9600000:*/
-/* BEGIN - DIF BPF register values from 96_quant.dat*/
-{9600000, DIF_BPF_COEFF01,    0x0001ffff},
-{9600000, DIF_BPF_COEFF23,    0xfff8fff7},
-{9600000, DIF_BPF_COEFF45,    0x00150036},
-{9600000, DIF_BPF_COEFF67,    0x0005ff8c},
-{9600000, DIF_BPF_COEFF89,    0xff810061},
-{9600000, DIF_BPF_COEFF1011,  0x013d007e},
-{9600000, DIF_BPF_COEFF1213,  0xfe71fddf},
-{9600000, DIF_BPF_COEFF1415,  0x007c0380},
-{9600000, DIF_BPF_COEFF1617,  0x0241fd13},
-{9600000, DIF_BPF_COEFF1819,  0xfa94ff70},
-{9600000, DIF_BPF_COEFF2021,  0x068005e2},
-{9600000, DIF_BPF_COEFF2223,  0xfc9bf633},
-{9600000, DIF_BPF_COEFF2425,  0xfc7308ca},
-{9600000, DIF_BPF_COEFF2627,  0x0ad5fe30},
-{9600000, DIF_BPF_COEFF2829,  0xf274f7e0},
-{9600000, DIF_BPF_COEFF3031,  0x08c90f43},
-{9600000, DIF_BPF_COEFF3233,  0x01d4f147},
-{9600000, DIF_BPF_COEFF3435,  0xf371060f},
-{9600000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 96_quant.dat*/
-
-
-/*case 9700000:*/
-/* BEGIN - DIF BPF register values from 97_quant.dat*/
-{9700000, DIF_BPF_COEFF01,    0x00010001},
-{9700000, DIF_BPF_COEFF23,    0xfff9fff1},
-{9700000, DIF_BPF_COEFF45,    0x00090038},
-{9700000, DIF_BPF_COEFF67,    0x0025ffa7},
-{9700000, DIF_BPF_COEFF89,    0xff5e0012},
-{9700000, DIF_BPF_COEFF1011,  0x013200f0},
-{9700000, DIF_BPF_COEFF1213,  0xfee3fd9b},
-{9700000, DIF_BPF_COEFF1415,  0xffaa0331},
-{9700000, DIF_BPF_COEFF1617,  0x0311fe15},
-{9700000, DIF_BPF_COEFF1819,  0xfa60fe18},
-{9700000, DIF_BPF_COEFF2021,  0x05bd06d1},
-{9700000, DIF_BPF_COEFF2223,  0xfe1bf64a},
-{9700000, DIF_BPF_COEFF2425,  0xfafa07ae},
-{9700000, DIF_BPF_COEFF2627,  0x0b7effab},
-{9700000, DIF_BPF_COEFF2829,  0xf2d5f6d7},
-{9700000, DIF_BPF_COEFF3031,  0x07d30f7a},
-{9700000, DIF_BPF_COEFF3233,  0x02a3f194},
-{9700000, DIF_BPF_COEFF3435,  0xf32905dc},
-{9700000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 97_quant.dat*/
-
-
-/*case 9800000:*/
-/* BEGIN - DIF BPF register values from 98_quant.dat*/
-{9800000, DIF_BPF_COEFF01,    0x00010002},
-{9800000, DIF_BPF_COEFF23,    0xfffcffee},
-{9800000, DIF_BPF_COEFF45,    0xfffb0032},
-{9800000, DIF_BPF_COEFF67,    0x003fffcd},
-{9800000, DIF_BPF_COEFF89,    0xff4effc1},
-{9800000, DIF_BPF_COEFF1011,  0x0106014a},
-{9800000, DIF_BPF_COEFF1213,  0xff6efd8a},
-{9800000, DIF_BPF_COEFF1415,  0xfedd02aa},
-{9800000, DIF_BPF_COEFF1617,  0x03b0ff34},
-{9800000, DIF_BPF_COEFF1819,  0xfa74fcd7},
-{9800000, DIF_BPF_COEFF2021,  0x04bf0781},
-{9800000, DIF_BPF_COEFF2223,  0xffaaf6a3},
-{9800000, DIF_BPF_COEFF2425,  0xf99e066b},
-{9800000, DIF_BPF_COEFF2627,  0x0bf90128},
-{9800000, DIF_BPF_COEFF2829,  0xf359f5e1},
-{9800000, DIF_BPF_COEFF3031,  0x06d20fa2},
-{9800000, DIF_BPF_COEFF3233,  0x0370f1e5},
-{9800000, DIF_BPF_COEFF3435,  0xf2e405a8},
-{9800000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 98_quant.dat*/
-
-
-/*case 9900000:*/
-/* BEGIN - DIF BPF register values from 99_quant.dat*/
-{9900000, DIF_BPF_COEFF01,    0x00000003},
-{9900000, DIF_BPF_COEFF23,    0xffffffee},
-{9900000, DIF_BPF_COEFF45,    0xffef0024},
-{9900000, DIF_BPF_COEFF67,    0x0051fffa},
-{9900000, DIF_BPF_COEFF89,    0xff54ff77},
-{9900000, DIF_BPF_COEFF1011,  0x00be0184},
-{9900000, DIF_BPF_COEFF1213,  0x0006fdad},
-{9900000, DIF_BPF_COEFF1415,  0xfe2701f3},
-{9900000, DIF_BPF_COEFF1617,  0x0413005e},
-{9900000, DIF_BPF_COEFF1819,  0xfad1fbba},
-{9900000, DIF_BPF_COEFF2021,  0x039007ee},
-{9900000, DIF_BPF_COEFF2223,  0x013bf73d},
-{9900000, DIF_BPF_COEFF2425,  0xf868050a},
-{9900000, DIF_BPF_COEFF2627,  0x0c4302a1},
-{9900000, DIF_BPF_COEFF2829,  0xf3fdf4fe},
-{9900000, DIF_BPF_COEFF3031,  0x05c70fba},
-{9900000, DIF_BPF_COEFF3233,  0x043bf23c},
-{9900000, DIF_BPF_COEFF3435,  0xf2a10575},
-{9900000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 99_quant.dat*/
-
-
-/*case 10000000:*/
-/* BEGIN - DIF BPF register values from 100_quant.dat*/
-{10000000, DIF_BPF_COEFF01,    0x00000003},
-{10000000, DIF_BPF_COEFF23,    0x0003fff1},
-{10000000, DIF_BPF_COEFF45,    0xffe50011},
-{10000000, DIF_BPF_COEFF67,    0x00570027},
-{10000000, DIF_BPF_COEFF89,    0xff70ff3c},
-{10000000, DIF_BPF_COEFF1011,  0x00620198},
-{10000000, DIF_BPF_COEFF1213,  0x009efe01},
-{10000000, DIF_BPF_COEFF1415,  0xfd95011a},
-{10000000, DIF_BPF_COEFF1617,  0x04350183},
-{10000000, DIF_BPF_COEFF1819,  0xfb71fad0},
-{10000000, DIF_BPF_COEFF2021,  0x023c0812},
-{10000000, DIF_BPF_COEFF2223,  0x02c3f811},
-{10000000, DIF_BPF_COEFF2425,  0xf75e0390},
-{10000000, DIF_BPF_COEFF2627,  0x0c5c0411},
-{10000000, DIF_BPF_COEFF2829,  0xf4c1f432},
-{10000000, DIF_BPF_COEFF3031,  0x04b30fc1},
-{10000000, DIF_BPF_COEFF3233,  0x0503f297},
-{10000000, DIF_BPF_COEFF3435,  0xf2610541},
-{10000000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 100_quant.dat*/
-
-
-/*case 10100000:*/
-/* BEGIN - DIF BPF register values from 101_quant.dat*/
-{10100000, DIF_BPF_COEFF01,    0x00000003},
-{10100000, DIF_BPF_COEFF23,    0x0006fff7},
-{10100000, DIF_BPF_COEFF45,    0xffdffffc},
-{10100000, DIF_BPF_COEFF67,    0x00510050},
-{10100000, DIF_BPF_COEFF89,    0xff9dff18},
-{10100000, DIF_BPF_COEFF1011,  0xfffc0184},
-{10100000, DIF_BPF_COEFF1213,  0x0128fe80},
-{10100000, DIF_BPF_COEFF1415,  0xfd32002e},
-{10100000, DIF_BPF_COEFF1617,  0x04130292},
-{10100000, DIF_BPF_COEFF1819,  0xfc4dfa21},
-{10100000, DIF_BPF_COEFF2021,  0x00d107ee},
-{10100000, DIF_BPF_COEFF2223,  0x0435f91c},
-{10100000, DIF_BPF_COEFF2425,  0xf6850205},
-{10100000, DIF_BPF_COEFF2627,  0x0c430573},
-{10100000, DIF_BPF_COEFF2829,  0xf5a1f37d},
-{10100000, DIF_BPF_COEFF3031,  0x03990fba},
-{10100000, DIF_BPF_COEFF3233,  0x05c7f2f8},
-{10100000, DIF_BPF_COEFF3435,  0xf222050d},
-{10100000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 101_quant.dat*/
-
-
-/*case 10200000:*/
-/* BEGIN - DIF BPF register values from 102_quant.dat*/
-{10200000, DIF_BPF_COEFF01,    0x00000002},
-{10200000, DIF_BPF_COEFF23,    0x0008fffe},
-{10200000, DIF_BPF_COEFF45,    0xffdfffe7},
-{10200000, DIF_BPF_COEFF67,    0x003f006e},
-{10200000, DIF_BPF_COEFF89,    0xffd6ff0f},
-{10200000, DIF_BPF_COEFF1011,  0xff96014a},
-{10200000, DIF_BPF_COEFF1213,  0x0197ff1f},
-{10200000, DIF_BPF_COEFF1415,  0xfd05ff3e},
-{10200000, DIF_BPF_COEFF1617,  0x03b0037c},
-{10200000, DIF_BPF_COEFF1819,  0xfd59f9b7},
-{10200000, DIF_BPF_COEFF2021,  0xff5d0781},
-{10200000, DIF_BPF_COEFF2223,  0x0585fa56},
-{10200000, DIF_BPF_COEFF2425,  0xf5e4006f},
-{10200000, DIF_BPF_COEFF2627,  0x0bf906c4},
-{10200000, DIF_BPF_COEFF2829,  0xf69df2e0},
-{10200000, DIF_BPF_COEFF3031,  0x02790fa2},
-{10200000, DIF_BPF_COEFF3233,  0x0688f35d},
-{10200000, DIF_BPF_COEFF3435,  0xf1e604d8},
-{10200000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 102_quant.dat*/
-
-
-/*case 10300000:*/
-/* BEGIN - DIF BPF register values from 103_quant.dat*/
-{10300000, DIF_BPF_COEFF01,    0xffff0001},
-{10300000, DIF_BPF_COEFF23,    0x00090005},
-{10300000, DIF_BPF_COEFF45,    0xffe4ffd6},
-{10300000, DIF_BPF_COEFF67,    0x0025007e},
-{10300000, DIF_BPF_COEFF89,    0x0014ff20},
-{10300000, DIF_BPF_COEFF1011,  0xff3c00f0},
-{10300000, DIF_BPF_COEFF1213,  0x01e1ffd0},
-{10300000, DIF_BPF_COEFF1415,  0xfd12fe5c},
-{10300000, DIF_BPF_COEFF1617,  0x03110433},
-{10300000, DIF_BPF_COEFF1819,  0xfe88f996},
-{10300000, DIF_BPF_COEFF2021,  0xfdf106d1},
-{10300000, DIF_BPF_COEFF2223,  0x06aafbb7},
-{10300000, DIF_BPF_COEFF2425,  0xf57efed8},
-{10300000, DIF_BPF_COEFF2627,  0x0b7e07ff},
-{10300000, DIF_BPF_COEFF2829,  0xf7b0f25e},
-{10300000, DIF_BPF_COEFF3031,  0x01560f7a},
-{10300000, DIF_BPF_COEFF3233,  0x0745f3c7},
-{10300000, DIF_BPF_COEFF3435,  0xf1ac04a4},
-{10300000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 103_quant.dat*/
-
-
-/*case 10400000:*/
-/* BEGIN - DIF BPF register values from 104_quant.dat*/
-{10400000, DIF_BPF_COEFF01,    0xffffffff},
-{10400000, DIF_BPF_COEFF23,    0x0008000c},
-{10400000, DIF_BPF_COEFF45,    0xffedffcb},
-{10400000, DIF_BPF_COEFF67,    0x0005007d},
-{10400000, DIF_BPF_COEFF89,    0x0050ff4c},
-{10400000, DIF_BPF_COEFF1011,  0xfef6007e},
-{10400000, DIF_BPF_COEFF1213,  0x01ff0086},
-{10400000, DIF_BPF_COEFF1415,  0xfd58fd97},
-{10400000, DIF_BPF_COEFF1617,  0x024104ad},
-{10400000, DIF_BPF_COEFF1819,  0xffcaf9c0},
-{10400000, DIF_BPF_COEFF2021,  0xfc9905e2},
-{10400000, DIF_BPF_COEFF2223,  0x079afd35},
-{10400000, DIF_BPF_COEFF2425,  0xf555fd46},
-{10400000, DIF_BPF_COEFF2627,  0x0ad50920},
-{10400000, DIF_BPF_COEFF2829,  0xf8d9f1f6},
-{10400000, DIF_BPF_COEFF3031,  0x00310f43},
-{10400000, DIF_BPF_COEFF3233,  0x07fdf435},
-{10400000, DIF_BPF_COEFF3435,  0xf174046f},
-{10400000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 104_quant.dat*/
-
-
-/*case 10500000:*/
-/* BEGIN - DIF BPF register values from 105_quant.dat*/
-{10500000, DIF_BPF_COEFF01,    0xfffffffe},
-{10500000, DIF_BPF_COEFF23,    0x00050011},
-{10500000, DIF_BPF_COEFF45,    0xfffaffc8},
-{10500000, DIF_BPF_COEFF67,    0xffe5006b},
-{10500000, DIF_BPF_COEFF89,    0x0082ff8c},
-{10500000, DIF_BPF_COEFF1011,  0xfecc0000},
-{10500000, DIF_BPF_COEFF1213,  0x01f00130},
-{10500000, DIF_BPF_COEFF1415,  0xfdd2fcfc},
-{10500000, DIF_BPF_COEFF1617,  0x014d04e3},
-{10500000, DIF_BPF_COEFF1819,  0x010efa32},
-{10500000, DIF_BPF_COEFF2021,  0xfb6404bf},
-{10500000, DIF_BPF_COEFF2223,  0x084efec5},
-{10500000, DIF_BPF_COEFF2425,  0xf569fbc2},
-{10500000, DIF_BPF_COEFF2627,  0x0a000a23},
-{10500000, DIF_BPF_COEFF2829,  0xfa15f1ab},
-{10500000, DIF_BPF_COEFF3031,  0xff0b0efc},
-{10500000, DIF_BPF_COEFF3233,  0x08b0f4a7},
-{10500000, DIF_BPF_COEFF3435,  0xf13f043a},
-{10500000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 105_quant.dat*/
-
-
-/*case 10600000:*/
-/* BEGIN - DIF BPF register values from 106_quant.dat*/
-{10600000, DIF_BPF_COEFF01,    0x0000fffd},
-{10600000, DIF_BPF_COEFF23,    0x00020012},
-{10600000, DIF_BPF_COEFF45,    0x0007ffcd},
-{10600000, DIF_BPF_COEFF67,    0xffc9004c},
-{10600000, DIF_BPF_COEFF89,    0x00a4ffd9},
-{10600000, DIF_BPF_COEFF1011,  0xfec3ff82},
-{10600000, DIF_BPF_COEFF1213,  0x01b401c1},
-{10600000, DIF_BPF_COEFF1415,  0xfe76fc97},
-{10600000, DIF_BPF_COEFF1617,  0x004404d2},
-{10600000, DIF_BPF_COEFF1819,  0x0245fae8},
-{10600000, DIF_BPF_COEFF2021,  0xfa5f0370},
-{10600000, DIF_BPF_COEFF2223,  0x08c1005f},
-{10600000, DIF_BPF_COEFF2425,  0xf5bcfa52},
-{10600000, DIF_BPF_COEFF2627,  0x09020b04},
-{10600000, DIF_BPF_COEFF2829,  0xfb60f17b},
-{10600000, DIF_BPF_COEFF3031,  0xfde70ea6},
-{10600000, DIF_BPF_COEFF3233,  0x095df51e},
-{10600000, DIF_BPF_COEFF3435,  0xf10c0405},
-{10600000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 106_quant.dat*/
-
-
-/*case 10700000:*/
-/* BEGIN - DIF BPF register values from 107_quant.dat*/
-{10700000, DIF_BPF_COEFF01,    0x0000fffd},
-{10700000, DIF_BPF_COEFF23,    0xffff0011},
-{10700000, DIF_BPF_COEFF45,    0x0014ffdb},
-{10700000, DIF_BPF_COEFF67,    0xffb40023},
-{10700000, DIF_BPF_COEFF89,    0x00b2002a},
-{10700000, DIF_BPF_COEFF1011,  0xfedbff10},
-{10700000, DIF_BPF_COEFF1213,  0x0150022d},
-{10700000, DIF_BPF_COEFF1415,  0xff38fc6f},
-{10700000, DIF_BPF_COEFF1617,  0xff36047b},
-{10700000, DIF_BPF_COEFF1819,  0x035efbda},
-{10700000, DIF_BPF_COEFF2021,  0xf9940202},
-{10700000, DIF_BPF_COEFF2223,  0x08ee01f5},
-{10700000, DIF_BPF_COEFF2425,  0xf649f8fe},
-{10700000, DIF_BPF_COEFF2627,  0x07e10bc2},
-{10700000, DIF_BPF_COEFF2829,  0xfcb6f169},
-{10700000, DIF_BPF_COEFF3031,  0xfcc60e42},
-{10700000, DIF_BPF_COEFF3233,  0x0a04f599},
-{10700000, DIF_BPF_COEFF3435,  0xf0db03d0},
-{10700000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 107_quant.dat*/
-
-
-/*case 10800000:*/
-/* BEGIN - DIF BPF register values from 108_quant.dat*/
-{10800000, DIF_BPF_COEFF01,    0x0000fffd},
-{10800000, DIF_BPF_COEFF23,    0xfffb000d},
-{10800000, DIF_BPF_COEFF45,    0x001dffed},
-{10800000, DIF_BPF_COEFF67,    0xffaafff5},
-{10800000, DIF_BPF_COEFF89,    0x00aa0077},
-{10800000, DIF_BPF_COEFF1011,  0xff13feb6},
-{10800000, DIF_BPF_COEFF1213,  0x00ce026b},
-{10800000, DIF_BPF_COEFF1415,  0x000afc85},
-{10800000, DIF_BPF_COEFF1617,  0xfe3503e3},
-{10800000, DIF_BPF_COEFF1819,  0x044cfcfb},
-{10800000, DIF_BPF_COEFF2021,  0xf90c0082},
-{10800000, DIF_BPF_COEFF2223,  0x08d5037f},
-{10800000, DIF_BPF_COEFF2425,  0xf710f7cc},
-{10800000, DIF_BPF_COEFF2627,  0x069f0c59},
-{10800000, DIF_BPF_COEFF2829,  0xfe16f173},
-{10800000, DIF_BPF_COEFF3031,  0xfbaa0dcf},
-{10800000, DIF_BPF_COEFF3233,  0x0aa5f617},
-{10800000, DIF_BPF_COEFF3435,  0xf0ad039b},
-{10800000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 108_quant.dat*/
-
-
-/*case 10900000:*/
-/* BEGIN - DIF BPF register values from 109_quant.dat*/
-{10900000, DIF_BPF_COEFF01,    0x0000fffe},
-{10900000, DIF_BPF_COEFF23,    0xfff90006},
-{10900000, DIF_BPF_COEFF45,    0x00210003},
-{10900000, DIF_BPF_COEFF67,    0xffacffc8},
-{10900000, DIF_BPF_COEFF89,    0x008e00b6},
-{10900000, DIF_BPF_COEFF1011,  0xff63fe7c},
-{10900000, DIF_BPF_COEFF1213,  0x003a0275},
-{10900000, DIF_BPF_COEFF1415,  0x00dafcda},
-{10900000, DIF_BPF_COEFF1617,  0xfd510313},
-{10900000, DIF_BPF_COEFF1819,  0x0501fe40},
-{10900000, DIF_BPF_COEFF2021,  0xf8cbfefd},
-{10900000, DIF_BPF_COEFF2223,  0x087604f0},
-{10900000, DIF_BPF_COEFF2425,  0xf80af6c2},
-{10900000, DIF_BPF_COEFF2627,  0x05430cc8},
-{10900000, DIF_BPF_COEFF2829,  0xff7af19a},
-{10900000, DIF_BPF_COEFF3031,  0xfa940d4e},
-{10900000, DIF_BPF_COEFF3233,  0x0b3ff699},
-{10900000, DIF_BPF_COEFF3435,  0xf0810365},
-{10900000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 109_quant.dat*/
-
-
-/*case 11000000:*/
-/* BEGIN - DIF BPF register values from 110_quant.dat*/
-{11000000, DIF_BPF_COEFF01,    0x0001ffff},
-{11000000, DIF_BPF_COEFF23,    0xfff8ffff},
-{11000000, DIF_BPF_COEFF45,    0x00210018},
-{11000000, DIF_BPF_COEFF67,    0xffbaffa3},
-{11000000, DIF_BPF_COEFF89,    0x006000e1},
-{11000000, DIF_BPF_COEFF1011,  0xffc4fe68},
-{11000000, DIF_BPF_COEFF1213,  0xffa0024b},
-{11000000, DIF_BPF_COEFF1415,  0x019afd66},
-{11000000, DIF_BPF_COEFF1617,  0xfc990216},
-{11000000, DIF_BPF_COEFF1819,  0x0575ff99},
-{11000000, DIF_BPF_COEFF2021,  0xf8d4fd81},
-{11000000, DIF_BPF_COEFF2223,  0x07d40640},
-{11000000, DIF_BPF_COEFF2425,  0xf932f5e6},
-{11000000, DIF_BPF_COEFF2627,  0x03d20d0d},
-{11000000, DIF_BPF_COEFF2829,  0x00dff1de},
-{11000000, DIF_BPF_COEFF3031,  0xf9860cbf},
-{11000000, DIF_BPF_COEFF3233,  0x0bd1f71e},
-{11000000, DIF_BPF_COEFF3435,  0xf058032f},
-{11000000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 110_quant.dat*/
-
-
-/*case 11100000:*/
-/* BEGIN - DIF BPF register values from 111_quant.dat*/
-{11100000, DIF_BPF_COEFF01,    0x00010000},
-{11100000, DIF_BPF_COEFF23,    0xfff8fff8},
-{11100000, DIF_BPF_COEFF45,    0x001b0029},
-{11100000, DIF_BPF_COEFF67,    0xffd1ff8a},
-{11100000, DIF_BPF_COEFF89,    0x002600f2},
-{11100000, DIF_BPF_COEFF1011,  0x002cfe7c},
-{11100000, DIF_BPF_COEFF1213,  0xff0f01f0},
-{11100000, DIF_BPF_COEFF1415,  0x023bfe20},
-{11100000, DIF_BPF_COEFF1617,  0xfc1700fa},
-{11100000, DIF_BPF_COEFF1819,  0x05a200f7},
-{11100000, DIF_BPF_COEFF2021,  0xf927fc1c},
-{11100000, DIF_BPF_COEFF2223,  0x06f40765},
-{11100000, DIF_BPF_COEFF2425,  0xfa82f53b},
-{11100000, DIF_BPF_COEFF2627,  0x02510d27},
-{11100000, DIF_BPF_COEFF2829,  0x0243f23d},
-{11100000, DIF_BPF_COEFF3031,  0xf8810c24},
-{11100000, DIF_BPF_COEFF3233,  0x0c5cf7a7},
-{11100000, DIF_BPF_COEFF3435,  0xf03102fa},
-{11100000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 111_quant.dat*/
-
-
-/*case 11200000:*/
-/* BEGIN - DIF BPF register values from 112_quant.dat*/
-{11200000, DIF_BPF_COEFF01,    0x00010002},
-{11200000, DIF_BPF_COEFF23,    0xfffafff2},
-{11200000, DIF_BPF_COEFF45,    0x00110035},
-{11200000, DIF_BPF_COEFF67,    0xfff0ff81},
-{11200000, DIF_BPF_COEFF89,    0xffe700e7},
-{11200000, DIF_BPF_COEFF1011,  0x008ffeb6},
-{11200000, DIF_BPF_COEFF1213,  0xfe94016d},
-{11200000, DIF_BPF_COEFF1415,  0x02b0fefb},
-{11200000, DIF_BPF_COEFF1617,  0xfbd3ffd1},
-{11200000, DIF_BPF_COEFF1819,  0x05850249},
-{11200000, DIF_BPF_COEFF2021,  0xf9c1fadb},
-{11200000, DIF_BPF_COEFF2223,  0x05de0858},
-{11200000, DIF_BPF_COEFF2425,  0xfbf2f4c4},
-{11200000, DIF_BPF_COEFF2627,  0x00c70d17},
-{11200000, DIF_BPF_COEFF2829,  0x03a0f2b8},
-{11200000, DIF_BPF_COEFF3031,  0xf7870b7c},
-{11200000, DIF_BPF_COEFF3233,  0x0cdff833},
-{11200000, DIF_BPF_COEFF3435,  0xf00d02c4},
-{11200000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 112_quant.dat*/
-
-
-/*case 11300000:*/
-/* BEGIN - DIF BPF register values from 113_quant.dat*/
-{11300000, DIF_BPF_COEFF01,    0x00000003},
-{11300000, DIF_BPF_COEFF23,    0xfffdffee},
-{11300000, DIF_BPF_COEFF45,    0x00040038},
-{11300000, DIF_BPF_COEFF67,    0x0010ff88},
-{11300000, DIF_BPF_COEFF89,    0xffac00c2},
-{11300000, DIF_BPF_COEFF1011,  0x00e2ff10},
-{11300000, DIF_BPF_COEFF1213,  0xfe3900cb},
-{11300000, DIF_BPF_COEFF1415,  0x02f1ffe9},
-{11300000, DIF_BPF_COEFF1617,  0xfbd3feaa},
-{11300000, DIF_BPF_COEFF1819,  0x05210381},
-{11300000, DIF_BPF_COEFF2021,  0xfa9cf9c8},
-{11300000, DIF_BPF_COEFF2223,  0x04990912},
-{11300000, DIF_BPF_COEFF2425,  0xfd7af484},
-{11300000, DIF_BPF_COEFF2627,  0xff390cdb},
-{11300000, DIF_BPF_COEFF2829,  0x04f4f34d},
-{11300000, DIF_BPF_COEFF3031,  0xf69a0ac9},
-{11300000, DIF_BPF_COEFF3233,  0x0d5af8c1},
-{11300000, DIF_BPF_COEFF3435,  0xefec028e},
-{11300000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 113_quant.dat*/
-
-
-/*case 11400000:*/
-/* BEGIN - DIF BPF register values from 114_quant.dat*/
-{11400000, DIF_BPF_COEFF01,    0x00000003},
-{11400000, DIF_BPF_COEFF23,    0x0000ffee},
-{11400000, DIF_BPF_COEFF45,    0xfff60033},
-{11400000, DIF_BPF_COEFF67,    0x002fff9f},
-{11400000, DIF_BPF_COEFF89,    0xff7b0087},
-{11400000, DIF_BPF_COEFF1011,  0x011eff82},
-{11400000, DIF_BPF_COEFF1213,  0xfe080018},
-{11400000, DIF_BPF_COEFF1415,  0x02f900d8},
-{11400000, DIF_BPF_COEFF1617,  0xfc17fd96},
-{11400000, DIF_BPF_COEFF1819,  0x04790490},
-{11400000, DIF_BPF_COEFF2021,  0xfbadf8ed},
-{11400000, DIF_BPF_COEFF2223,  0x032f098e},
-{11400000, DIF_BPF_COEFF2425,  0xff10f47d},
-{11400000, DIF_BPF_COEFF2627,  0xfdaf0c75},
-{11400000, DIF_BPF_COEFF2829,  0x063cf3fc},
-{11400000, DIF_BPF_COEFF3031,  0xf5ba0a0b},
-{11400000, DIF_BPF_COEFF3233,  0x0dccf952},
-{11400000, DIF_BPF_COEFF3435,  0xefcd0258},
-{11400000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 114_quant.dat*/
-
-
-/*case 11500000:*/
-/* BEGIN - DIF BPF register values from 115_quant.dat*/
-{11500000, DIF_BPF_COEFF01,    0x00000003},
-{11500000, DIF_BPF_COEFF23,    0x0004fff1},
-{11500000, DIF_BPF_COEFF45,    0xffea0026},
-{11500000, DIF_BPF_COEFF67,    0x0046ffc3},
-{11500000, DIF_BPF_COEFF89,    0xff5a003c},
-{11500000, DIF_BPF_COEFF1011,  0x013b0000},
-{11500000, DIF_BPF_COEFF1213,  0xfe04ff63},
-{11500000, DIF_BPF_COEFF1415,  0x02c801b8},
-{11500000, DIF_BPF_COEFF1617,  0xfc99fca6},
-{11500000, DIF_BPF_COEFF1819,  0x0397056a},
-{11500000, DIF_BPF_COEFF2021,  0xfcecf853},
-{11500000, DIF_BPF_COEFF2223,  0x01ad09c9},
-{11500000, DIF_BPF_COEFF2425,  0x00acf4ad},
-{11500000, DIF_BPF_COEFF2627,  0xfc2e0be7},
-{11500000, DIF_BPF_COEFF2829,  0x0773f4c2},
-{11500000, DIF_BPF_COEFF3031,  0xf4e90943},
-{11500000, DIF_BPF_COEFF3233,  0x0e35f9e6},
-{11500000, DIF_BPF_COEFF3435,  0xefb10221},
-{11500000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 115_quant.dat*/
-
-
-/*case 11600000:*/
-/* BEGIN - DIF BPF register values from 116_quant.dat*/
-{11600000, DIF_BPF_COEFF01,    0x00000002},
-{11600000, DIF_BPF_COEFF23,    0x0007fff6},
-{11600000, DIF_BPF_COEFF45,    0xffe20014},
-{11600000, DIF_BPF_COEFF67,    0x0054ffee},
-{11600000, DIF_BPF_COEFF89,    0xff4effeb},
-{11600000, DIF_BPF_COEFF1011,  0x0137007e},
-{11600000, DIF_BPF_COEFF1213,  0xfe2efebb},
-{11600000, DIF_BPF_COEFF1415,  0x0260027a},
-{11600000, DIF_BPF_COEFF1617,  0xfd51fbe6},
-{11600000, DIF_BPF_COEFF1819,  0x02870605},
-{11600000, DIF_BPF_COEFF2021,  0xfe4af7fe},
-{11600000, DIF_BPF_COEFF2223,  0x001d09c1},
-{11600000, DIF_BPF_COEFF2425,  0x0243f515},
-{11600000, DIF_BPF_COEFF2627,  0xfabd0b32},
-{11600000, DIF_BPF_COEFF2829,  0x0897f59e},
-{11600000, DIF_BPF_COEFF3031,  0xf4280871},
-{11600000, DIF_BPF_COEFF3233,  0x0e95fa7c},
-{11600000, DIF_BPF_COEFF3435,  0xef9701eb},
-{11600000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 116_quant.dat*/
-
-
-/*case 11700000:*/
-/* BEGIN - DIF BPF register values from 117_quant.dat*/
-{11700000, DIF_BPF_COEFF01,    0xffff0001},
-{11700000, DIF_BPF_COEFF23,    0x0008fffd},
-{11700000, DIF_BPF_COEFF45,    0xffdeffff},
-{11700000, DIF_BPF_COEFF67,    0x0056001d},
-{11700000, DIF_BPF_COEFF89,    0xff57ff9c},
-{11700000, DIF_BPF_COEFF1011,  0x011300f0},
-{11700000, DIF_BPF_COEFF1213,  0xfe82fe2e},
-{11700000, DIF_BPF_COEFF1415,  0x01ca0310},
-{11700000, DIF_BPF_COEFF1617,  0xfe35fb62},
-{11700000, DIF_BPF_COEFF1819,  0x0155065a},
-{11700000, DIF_BPF_COEFF2021,  0xffbaf7f2},
-{11700000, DIF_BPF_COEFF2223,  0xfe8c0977},
-{11700000, DIF_BPF_COEFF2425,  0x03cef5b2},
-{11700000, DIF_BPF_COEFF2627,  0xf9610a58},
-{11700000, DIF_BPF_COEFF2829,  0x09a5f68f},
-{11700000, DIF_BPF_COEFF3031,  0xf3790797},
-{11700000, DIF_BPF_COEFF3233,  0x0eebfb14},
-{11700000, DIF_BPF_COEFF3435,  0xef8001b5},
-{11700000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 117_quant.dat*/
-
-
-/*case 11800000:*/
-/* BEGIN - DIF BPF register values from 118_quant.dat*/
-{11800000, DIF_BPF_COEFF01,    0xffff0000},
-{11800000, DIF_BPF_COEFF23,    0x00080004},
-{11800000, DIF_BPF_COEFF45,    0xffe0ffe9},
-{11800000, DIF_BPF_COEFF67,    0x004c0047},
-{11800000, DIF_BPF_COEFF89,    0xff75ff58},
-{11800000, DIF_BPF_COEFF1011,  0x00d1014a},
-{11800000, DIF_BPF_COEFF1213,  0xfef9fdc8},
-{11800000, DIF_BPF_COEFF1415,  0x0111036f},
-{11800000, DIF_BPF_COEFF1617,  0xff36fb21},
-{11800000, DIF_BPF_COEFF1819,  0x00120665},
-{11800000, DIF_BPF_COEFF2021,  0x012df82e},
-{11800000, DIF_BPF_COEFF2223,  0xfd0708ec},
-{11800000, DIF_BPF_COEFF2425,  0x0542f682},
-{11800000, DIF_BPF_COEFF2627,  0xf81f095c},
-{11800000, DIF_BPF_COEFF2829,  0x0a9af792},
-{11800000, DIF_BPF_COEFF3031,  0xf2db06b5},
-{11800000, DIF_BPF_COEFF3233,  0x0f38fbad},
-{11800000, DIF_BPF_COEFF3435,  0xef6c017e},
-{11800000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 118_quant.dat*/
-
-
-/*case 11900000:*/
-/* BEGIN - DIF BPF register values from 119_quant.dat*/
-{11900000, DIF_BPF_COEFF01,    0xffffffff},
-{11900000, DIF_BPF_COEFF23,    0x0007000b},
-{11900000, DIF_BPF_COEFF45,    0xffe7ffd8},
-{11900000, DIF_BPF_COEFF67,    0x00370068},
-{11900000, DIF_BPF_COEFF89,    0xffa4ff28},
-{11900000, DIF_BPF_COEFF1011,  0x00790184},
-{11900000, DIF_BPF_COEFF1213,  0xff87fd91},
-{11900000, DIF_BPF_COEFF1415,  0x00430392},
-{11900000, DIF_BPF_COEFF1617,  0x0044fb26},
-{11900000, DIF_BPF_COEFF1819,  0xfece0626},
-{11900000, DIF_BPF_COEFF2021,  0x0294f8b2},
-{11900000, DIF_BPF_COEFF2223,  0xfb990825},
-{11900000, DIF_BPF_COEFF2425,  0x0698f77f},
-{11900000, DIF_BPF_COEFF2627,  0xf6fe0842},
-{11900000, DIF_BPF_COEFF2829,  0x0b73f8a7},
-{11900000, DIF_BPF_COEFF3031,  0xf25105cd},
-{11900000, DIF_BPF_COEFF3233,  0x0f7bfc48},
-{11900000, DIF_BPF_COEFF3435,  0xef5a0148},
-{11900000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 119_quant.dat*/
-
-
-/*case 12000000:*/
-/* BEGIN - DIF BPF register values from 120_quant.dat*/
-{12000000, DIF_BPF_COEFF01,    0x0000fffe},
-{12000000, DIF_BPF_COEFF23,    0x00050010},
-{12000000, DIF_BPF_COEFF45,    0xfff2ffcc},
-{12000000, DIF_BPF_COEFF67,    0x001b007b},
-{12000000, DIF_BPF_COEFF89,    0xffdfff10},
-{12000000, DIF_BPF_COEFF1011,  0x00140198},
-{12000000, DIF_BPF_COEFF1213,  0x0020fd8e},
-{12000000, DIF_BPF_COEFF1415,  0xff710375},
-{12000000, DIF_BPF_COEFF1617,  0x014dfb73},
-{12000000, DIF_BPF_COEFF1819,  0xfd9a059f},
-{12000000, DIF_BPF_COEFF2021,  0x03e0f978},
-{12000000, DIF_BPF_COEFF2223,  0xfa4e0726},
-{12000000, DIF_BPF_COEFF2425,  0x07c8f8a7},
-{12000000, DIF_BPF_COEFF2627,  0xf600070c},
-{12000000, DIF_BPF_COEFF2829,  0x0c2ff9c9},
-{12000000, DIF_BPF_COEFF3031,  0xf1db04de},
-{12000000, DIF_BPF_COEFF3233,  0x0fb4fce5},
-{12000000, DIF_BPF_COEFF3435,  0xef4b0111},
-{12000000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 120_quant.dat*/
-
-
-/*case 12100000:*/
-/* BEGIN - DIF BPF register values from 121_quant.dat*/
-{12100000, DIF_BPF_COEFF01,    0x0000fffd},
-{12100000, DIF_BPF_COEFF23,    0x00010012},
-{12100000, DIF_BPF_COEFF45,    0xffffffc8},
-{12100000, DIF_BPF_COEFF67,    0xfffb007e},
-{12100000, DIF_BPF_COEFF89,    0x001dff14},
-{12100000, DIF_BPF_COEFF1011,  0xffad0184},
-{12100000, DIF_BPF_COEFF1213,  0x00b7fdbe},
-{12100000, DIF_BPF_COEFF1415,  0xfea9031b},
-{12100000, DIF_BPF_COEFF1617,  0x0241fc01},
-{12100000, DIF_BPF_COEFF1819,  0xfc8504d6},
-{12100000, DIF_BPF_COEFF2021,  0x0504fa79},
-{12100000, DIF_BPF_COEFF2223,  0xf93005f6},
-{12100000, DIF_BPF_COEFF2425,  0x08caf9f2},
-{12100000, DIF_BPF_COEFF2627,  0xf52b05c0},
-{12100000, DIF_BPF_COEFF2829,  0x0ccbfaf9},
-{12100000, DIF_BPF_COEFF3031,  0xf17903eb},
-{12100000, DIF_BPF_COEFF3233,  0x0fe3fd83},
-{12100000, DIF_BPF_COEFF3435,  0xef3f00db},
-{12100000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 121_quant.dat*/
-
-
-/*case 12200000:*/
-/* BEGIN - DIF BPF register values from 122_quant.dat*/
-{12200000, DIF_BPF_COEFF01,    0x0000fffd},
-{12200000, DIF_BPF_COEFF23,    0xfffe0011},
-{12200000, DIF_BPF_COEFF45,    0x000cffcc},
-{12200000, DIF_BPF_COEFF67,    0xffdb0071},
-{12200000, DIF_BPF_COEFF89,    0x0058ff32},
-{12200000, DIF_BPF_COEFF1011,  0xff4f014a},
-{12200000, DIF_BPF_COEFF1213,  0x013cfe1f},
-{12200000, DIF_BPF_COEFF1415,  0xfdfb028a},
-{12200000, DIF_BPF_COEFF1617,  0x0311fcc9},
-{12200000, DIF_BPF_COEFF1819,  0xfb9d03d6},
-{12200000, DIF_BPF_COEFF2021,  0x05f4fbad},
-{12200000, DIF_BPF_COEFF2223,  0xf848049d},
-{12200000, DIF_BPF_COEFF2425,  0x0999fb5b},
-{12200000, DIF_BPF_COEFF2627,  0xf4820461},
-{12200000, DIF_BPF_COEFF2829,  0x0d46fc32},
-{12200000, DIF_BPF_COEFF3031,  0xf12d02f4},
-{12200000, DIF_BPF_COEFF3233,  0x1007fe21},
-{12200000, DIF_BPF_COEFF3435,  0xef3600a4},
-{12200000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 122_quant.dat*/
-
-
-/*case 12300000:*/
-/* BEGIN - DIF BPF register values from 123_quant.dat*/
-{12300000, DIF_BPF_COEFF01,    0x0000fffe},
-{12300000, DIF_BPF_COEFF23,    0xfffa000e},
-{12300000, DIF_BPF_COEFF45,    0x0017ffd9},
-{12300000, DIF_BPF_COEFF67,    0xffc10055},
-{12300000, DIF_BPF_COEFF89,    0x0088ff68},
-{12300000, DIF_BPF_COEFF1011,  0xff0400f0},
-{12300000, DIF_BPF_COEFF1213,  0x01a6fea7},
-{12300000, DIF_BPF_COEFF1415,  0xfd7501cc},
-{12300000, DIF_BPF_COEFF1617,  0x03b0fdc0},
-{12300000, DIF_BPF_COEFF1819,  0xfaef02a8},
-{12300000, DIF_BPF_COEFF2021,  0x06a7fd07},
-{12300000, DIF_BPF_COEFF2223,  0xf79d0326},
-{12300000, DIF_BPF_COEFF2425,  0x0a31fcda},
-{12300000, DIF_BPF_COEFF2627,  0xf40702f3},
-{12300000, DIF_BPF_COEFF2829,  0x0d9ffd72},
-{12300000, DIF_BPF_COEFF3031,  0xf0f601fa},
-{12300000, DIF_BPF_COEFF3233,  0x1021fec0},
-{12300000, DIF_BPF_COEFF3435,  0xef2f006d},
-{12300000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 123_quant.dat*/
-
-
-/*case 12400000:*/
-/* BEGIN - DIF BPF register values from 124_quant.dat*/
-{12400000, DIF_BPF_COEFF01,    0x0001ffff},
-{12400000, DIF_BPF_COEFF23,    0xfff80007},
-{12400000, DIF_BPF_COEFF45,    0x001fffeb},
-{12400000, DIF_BPF_COEFF67,    0xffaf002d},
-{12400000, DIF_BPF_COEFF89,    0x00a8ffb0},
-{12400000, DIF_BPF_COEFF1011,  0xfed3007e},
-{12400000, DIF_BPF_COEFF1213,  0x01e9ff4c},
-{12400000, DIF_BPF_COEFF1415,  0xfd2000ee},
-{12400000, DIF_BPF_COEFF1617,  0x0413fed8},
-{12400000, DIF_BPF_COEFF1819,  0xfa82015c},
-{12400000, DIF_BPF_COEFF2021,  0x0715fe7d},
-{12400000, DIF_BPF_COEFF2223,  0xf7340198},
-{12400000, DIF_BPF_COEFF2425,  0x0a8dfe69},
-{12400000, DIF_BPF_COEFF2627,  0xf3bd017c},
-{12400000, DIF_BPF_COEFF2829,  0x0dd5feb8},
-{12400000, DIF_BPF_COEFF3031,  0xf0d500fd},
-{12400000, DIF_BPF_COEFF3233,  0x1031ff60},
-{12400000, DIF_BPF_COEFF3435,  0xef2b0037},
-{12400000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 124_quant.dat*/
-
-
-/*case 12500000:*/
-/* BEGIN - DIF BPF register values from 125_quant.dat*/
-{12500000, DIF_BPF_COEFF01,    0x00010000},
-{12500000, DIF_BPF_COEFF23,    0xfff70000},
-{12500000, DIF_BPF_COEFF45,    0x00220000},
-{12500000, DIF_BPF_COEFF67,    0xffa90000},
-{12500000, DIF_BPF_COEFF89,    0x00b30000},
-{12500000, DIF_BPF_COEFF1011,  0xfec20000},
-{12500000, DIF_BPF_COEFF1213,  0x02000000},
-{12500000, DIF_BPF_COEFF1415,  0xfd030000},
-{12500000, DIF_BPF_COEFF1617,  0x04350000},
-{12500000, DIF_BPF_COEFF1819,  0xfa5e0000},
-{12500000, DIF_BPF_COEFF2021,  0x073b0000},
-{12500000, DIF_BPF_COEFF2223,  0xf7110000},
-{12500000, DIF_BPF_COEFF2425,  0x0aac0000},
-{12500000, DIF_BPF_COEFF2627,  0xf3a40000},
-{12500000, DIF_BPF_COEFF2829,  0x0de70000},
-{12500000, DIF_BPF_COEFF3031,  0xf0c90000},
-{12500000, DIF_BPF_COEFF3233,  0x10360000},
-{12500000, DIF_BPF_COEFF3435,  0xef290000},
-{12500000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 125_quant.dat*/
-
-
-/*case 12600000:*/
-/* BEGIN - DIF BPF register values from 126_quant.dat*/
-{12600000, DIF_BPF_COEFF01,    0x00010001},
-{12600000, DIF_BPF_COEFF23,    0xfff8fff9},
-{12600000, DIF_BPF_COEFF45,    0x001f0015},
-{12600000, DIF_BPF_COEFF67,    0xffafffd3},
-{12600000, DIF_BPF_COEFF89,    0x00a80050},
-{12600000, DIF_BPF_COEFF1011,  0xfed3ff82},
-{12600000, DIF_BPF_COEFF1213,  0x01e900b4},
-{12600000, DIF_BPF_COEFF1415,  0xfd20ff12},
-{12600000, DIF_BPF_COEFF1617,  0x04130128},
-{12600000, DIF_BPF_COEFF1819,  0xfa82fea4},
-{12600000, DIF_BPF_COEFF2021,  0x07150183},
-{12600000, DIF_BPF_COEFF2223,  0xf734fe68},
-{12600000, DIF_BPF_COEFF2425,  0x0a8d0197},
-{12600000, DIF_BPF_COEFF2627,  0xf3bdfe84},
-{12600000, DIF_BPF_COEFF2829,  0x0dd50148},
-{12600000, DIF_BPF_COEFF3031,  0xf0d5ff03},
-{12600000, DIF_BPF_COEFF3233,  0x103100a0},
-{12600000, DIF_BPF_COEFF3435,  0xef2bffc9},
-{12600000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 126_quant.dat*/
-
-
-/*case 12700000:*/
-/* BEGIN - DIF BPF register values from 127_quant.dat*/
-{12700000, DIF_BPF_COEFF01,    0x00000002},
-{12700000, DIF_BPF_COEFF23,    0xfffafff2},
-{12700000, DIF_BPF_COEFF45,    0x00170027},
-{12700000, DIF_BPF_COEFF67,    0xffc1ffab},
-{12700000, DIF_BPF_COEFF89,    0x00880098},
-{12700000, DIF_BPF_COEFF1011,  0xff04ff10},
-{12700000, DIF_BPF_COEFF1213,  0x01a60159},
-{12700000, DIF_BPF_COEFF1415,  0xfd75fe34},
-{12700000, DIF_BPF_COEFF1617,  0x03b00240},
-{12700000, DIF_BPF_COEFF1819,  0xfaeffd58},
-{12700000, DIF_BPF_COEFF2021,  0x06a702f9},
-{12700000, DIF_BPF_COEFF2223,  0xf79dfcda},
-{12700000, DIF_BPF_COEFF2425,  0x0a310326},
-{12700000, DIF_BPF_COEFF2627,  0xf407fd0d},
-{12700000, DIF_BPF_COEFF2829,  0x0d9f028e},
-{12700000, DIF_BPF_COEFF3031,  0xf0f6fe06},
-{12700000, DIF_BPF_COEFF3233,  0x10210140},
-{12700000, DIF_BPF_COEFF3435,  0xef2fff93},
-{12700000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 127_quant.dat*/
-
-
-/*case 12800000:*/
-/* BEGIN - DIF BPF register values from 128_quant.dat*/
-{12800000, DIF_BPF_COEFF01,    0x00000003},
-{12800000, DIF_BPF_COEFF23,    0xfffeffef},
-{12800000, DIF_BPF_COEFF45,    0x000c0034},
-{12800000, DIF_BPF_COEFF67,    0xffdbff8f},
-{12800000, DIF_BPF_COEFF89,    0x005800ce},
-{12800000, DIF_BPF_COEFF1011,  0xff4ffeb6},
-{12800000, DIF_BPF_COEFF1213,  0x013c01e1},
-{12800000, DIF_BPF_COEFF1415,  0xfdfbfd76},
-{12800000, DIF_BPF_COEFF1617,  0x03110337},
-{12800000, DIF_BPF_COEFF1819,  0xfb9dfc2a},
-{12800000, DIF_BPF_COEFF2021,  0x05f40453},
-{12800000, DIF_BPF_COEFF2223,  0xf848fb63},
-{12800000, DIF_BPF_COEFF2425,  0x099904a5},
-{12800000, DIF_BPF_COEFF2627,  0xf482fb9f},
-{12800000, DIF_BPF_COEFF2829,  0x0d4603ce},
-{12800000, DIF_BPF_COEFF3031,  0xf12dfd0c},
-{12800000, DIF_BPF_COEFF3233,  0x100701df},
-{12800000, DIF_BPF_COEFF3435,  0xef36ff5c},
-{12800000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 128_quant.dat*/
-
-
-/*case 12900000:*/
-/* BEGIN - DIF BPF register values from 129_quant.dat*/
-{12900000, DIF_BPF_COEFF01,    0x00000003},
-{12900000, DIF_BPF_COEFF23,    0x0001ffee},
-{12900000, DIF_BPF_COEFF45,    0xffff0038},
-{12900000, DIF_BPF_COEFF67,    0xfffbff82},
-{12900000, DIF_BPF_COEFF89,    0x001d00ec},
-{12900000, DIF_BPF_COEFF1011,  0xffadfe7c},
-{12900000, DIF_BPF_COEFF1213,  0x00b70242},
-{12900000, DIF_BPF_COEFF1415,  0xfea9fce5},
-{12900000, DIF_BPF_COEFF1617,  0x024103ff},
-{12900000, DIF_BPF_COEFF1819,  0xfc85fb2a},
-{12900000, DIF_BPF_COEFF2021,  0x05040587},
-{12900000, DIF_BPF_COEFF2223,  0xf930fa0a},
-{12900000, DIF_BPF_COEFF2425,  0x08ca060e},
-{12900000, DIF_BPF_COEFF2627,  0xf52bfa40},
-{12900000, DIF_BPF_COEFF2829,  0x0ccb0507},
-{12900000, DIF_BPF_COEFF3031,  0xf179fc15},
-{12900000, DIF_BPF_COEFF3233,  0x0fe3027d},
-{12900000, DIF_BPF_COEFF3435,  0xef3fff25},
-{12900000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 129_quant.dat*/
-
-
-/*case 113000000:*/
-/* BEGIN - DIF BPF register values from 130_quant.dat*/
-{13000000, DIF_BPF_COEFF01,    0x00000002},
-{13000000, DIF_BPF_COEFF23,    0x0005fff0},
-{13000000, DIF_BPF_COEFF45,    0xfff20034},
-{13000000, DIF_BPF_COEFF67,    0x001bff85},
-{13000000, DIF_BPF_COEFF89,    0xffdf00f0},
-{13000000, DIF_BPF_COEFF1011,  0x0014fe68},
-{13000000, DIF_BPF_COEFF1213,  0x00200272},
-{13000000, DIF_BPF_COEFF1415,  0xff71fc8b},
-{13000000, DIF_BPF_COEFF1617,  0x014d048d},
-{13000000, DIF_BPF_COEFF1819,  0xfd9afa61},
-{13000000, DIF_BPF_COEFF2021,  0x03e00688},
-{13000000, DIF_BPF_COEFF2223,  0xfa4ef8da},
-{13000000, DIF_BPF_COEFF2425,  0x07c80759},
-{13000000, DIF_BPF_COEFF2627,  0xf600f8f4},
-{13000000, DIF_BPF_COEFF2829,  0x0c2f0637},
-{13000000, DIF_BPF_COEFF3031,  0xf1dbfb22},
-{13000000, DIF_BPF_COEFF3233,  0x0fb4031b},
-{13000000, DIF_BPF_COEFF3435,  0xef4bfeef},
-{13000000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 130_quant.dat*/
-
-
-/*case 13100000:*/
-/* BEGIN - DIF BPF register values from 131_quant.dat*/
-{13100000, DIF_BPF_COEFF01,    0xffff0001},
-{13100000, DIF_BPF_COEFF23,    0x0007fff5},
-{13100000, DIF_BPF_COEFF45,    0xffe70028},
-{13100000, DIF_BPF_COEFF67,    0x0037ff98},
-{13100000, DIF_BPF_COEFF89,    0xffa400d8},
-{13100000, DIF_BPF_COEFF1011,  0x0079fe7c},
-{13100000, DIF_BPF_COEFF1213,  0xff87026f},
-{13100000, DIF_BPF_COEFF1415,  0x0043fc6e},
-{13100000, DIF_BPF_COEFF1617,  0x004404da},
-{13100000, DIF_BPF_COEFF1819,  0xfecef9da},
-{13100000, DIF_BPF_COEFF2021,  0x0294074e},
-{13100000, DIF_BPF_COEFF2223,  0xfb99f7db},
-{13100000, DIF_BPF_COEFF2425,  0x06980881},
-{13100000, DIF_BPF_COEFF2627,  0xf6fef7be},
-{13100000, DIF_BPF_COEFF2829,  0x0b730759},
-{13100000, DIF_BPF_COEFF3031,  0xf251fa33},
-{13100000, DIF_BPF_COEFF3233,  0x0f7b03b8},
-{13100000, DIF_BPF_COEFF3435,  0xef5afeb8},
-{13100000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 131_quant.dat*/
-
-
-/*case 13200000:*/
-/* BEGIN - DIF BPF register values from 132_quant.dat*/
-{13200000, DIF_BPF_COEFF01,    0xffff0000},
-{13200000, DIF_BPF_COEFF23,    0x0008fffc},
-{13200000, DIF_BPF_COEFF45,    0xffe00017},
-{13200000, DIF_BPF_COEFF67,    0x004cffb9},
-{13200000, DIF_BPF_COEFF89,    0xff7500a8},
-{13200000, DIF_BPF_COEFF1011,  0x00d1feb6},
-{13200000, DIF_BPF_COEFF1213,  0xfef90238},
-{13200000, DIF_BPF_COEFF1415,  0x0111fc91},
-{13200000, DIF_BPF_COEFF1617,  0xff3604df},
-{13200000, DIF_BPF_COEFF1819,  0x0012f99b},
-{13200000, DIF_BPF_COEFF2021,  0x012d07d2},
-{13200000, DIF_BPF_COEFF2223,  0xfd07f714},
-{13200000, DIF_BPF_COEFF2425,  0x0542097e},
-{13200000, DIF_BPF_COEFF2627,  0xf81ff6a4},
-{13200000, DIF_BPF_COEFF2829,  0x0a9a086e},
-{13200000, DIF_BPF_COEFF3031,  0xf2dbf94b},
-{13200000, DIF_BPF_COEFF3233,  0x0f380453},
-{13200000, DIF_BPF_COEFF3435,  0xef6cfe82},
-{13200000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 132_quant.dat*/
-
-
-/*case 13300000:*/
-/* BEGIN - DIF BPF register values from 133_quant.dat*/
-{13300000, DIF_BPF_COEFF01,    0xffffffff},
-{13300000, DIF_BPF_COEFF23,    0x00080003},
-{13300000, DIF_BPF_COEFF45,    0xffde0001},
-{13300000, DIF_BPF_COEFF67,    0x0056ffe3},
-{13300000, DIF_BPF_COEFF89,    0xff570064},
-{13300000, DIF_BPF_COEFF1011,  0x0113ff10},
-{13300000, DIF_BPF_COEFF1213,  0xfe8201d2},
-{13300000, DIF_BPF_COEFF1415,  0x01cafcf0},
-{13300000, DIF_BPF_COEFF1617,  0xfe35049e},
-{13300000, DIF_BPF_COEFF1819,  0x0155f9a6},
-{13300000, DIF_BPF_COEFF2021,  0xffba080e},
-{13300000, DIF_BPF_COEFF2223,  0xfe8cf689},
-{13300000, DIF_BPF_COEFF2425,  0x03ce0a4e},
-{13300000, DIF_BPF_COEFF2627,  0xf961f5a8},
-{13300000, DIF_BPF_COEFF2829,  0x09a50971},
-{13300000, DIF_BPF_COEFF3031,  0xf379f869},
-{13300000, DIF_BPF_COEFF3233,  0x0eeb04ec},
-{13300000, DIF_BPF_COEFF3435,  0xef80fe4b},
-{13300000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 133_quant.dat*/
-
-
-/*case 13400000:*/
-/* BEGIN - DIF BPF register values from 134_quant.dat*/
-{13400000, DIF_BPF_COEFF01,    0x0000fffe},
-{13400000, DIF_BPF_COEFF23,    0x0007000a},
-{13400000, DIF_BPF_COEFF45,    0xffe2ffec},
-{13400000, DIF_BPF_COEFF67,    0x00540012},
-{13400000, DIF_BPF_COEFF89,    0xff4e0015},
-{13400000, DIF_BPF_COEFF1011,  0x0137ff82},
-{13400000, DIF_BPF_COEFF1213,  0xfe2e0145},
-{13400000, DIF_BPF_COEFF1415,  0x0260fd86},
-{13400000, DIF_BPF_COEFF1617,  0xfd51041a},
-{13400000, DIF_BPF_COEFF1819,  0x0287f9fb},
-{13400000, DIF_BPF_COEFF2021,  0xfe4a0802},
-{13400000, DIF_BPF_COEFF2223,  0x001df63f},
-{13400000, DIF_BPF_COEFF2425,  0x02430aeb},
-{13400000, DIF_BPF_COEFF2627,  0xfabdf4ce},
-{13400000, DIF_BPF_COEFF2829,  0x08970a62},
-{13400000, DIF_BPF_COEFF3031,  0xf428f78f},
-{13400000, DIF_BPF_COEFF3233,  0x0e950584},
-{13400000, DIF_BPF_COEFF3435,  0xef97fe15},
-{13400000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 134_quant.dat*/
-
-
-/*case 13500000:*/
-/* BEGIN - DIF BPF register values from 135_quant.dat*/
-{13500000, DIF_BPF_COEFF01,    0x0000fffd},
-{13500000, DIF_BPF_COEFF23,    0x0004000f},
-{13500000, DIF_BPF_COEFF45,    0xffeaffda},
-{13500000, DIF_BPF_COEFF67,    0x0046003d},
-{13500000, DIF_BPF_COEFF89,    0xff5affc4},
-{13500000, DIF_BPF_COEFF1011,  0x013b0000},
-{13500000, DIF_BPF_COEFF1213,  0xfe04009d},
-{13500000, DIF_BPF_COEFF1415,  0x02c8fe48},
-{13500000, DIF_BPF_COEFF1617,  0xfc99035a},
-{13500000, DIF_BPF_COEFF1819,  0x0397fa96},
-{13500000, DIF_BPF_COEFF2021,  0xfcec07ad},
-{13500000, DIF_BPF_COEFF2223,  0x01adf637},
-{13500000, DIF_BPF_COEFF2425,  0x00ac0b53},
-{13500000, DIF_BPF_COEFF2627,  0xfc2ef419},
-{13500000, DIF_BPF_COEFF2829,  0x07730b3e},
-{13500000, DIF_BPF_COEFF3031,  0xf4e9f6bd},
-{13500000, DIF_BPF_COEFF3233,  0x0e35061a},
-{13500000, DIF_BPF_COEFF3435,  0xefb1fddf},
-{13500000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 135_quant.dat*/
-
-
-/*case 13600000:*/
-/* BEGIN - DIF BPF register values from 136_quant.dat*/
-{13600000, DIF_BPF_COEFF01,    0x0000fffd},
-{13600000, DIF_BPF_COEFF23,    0x00000012},
-{13600000, DIF_BPF_COEFF45,    0xfff6ffcd},
-{13600000, DIF_BPF_COEFF67,    0x002f0061},
-{13600000, DIF_BPF_COEFF89,    0xff7bff79},
-{13600000, DIF_BPF_COEFF1011,  0x011e007e},
-{13600000, DIF_BPF_COEFF1213,  0xfe08ffe8},
-{13600000, DIF_BPF_COEFF1415,  0x02f9ff28},
-{13600000, DIF_BPF_COEFF1617,  0xfc17026a},
-{13600000, DIF_BPF_COEFF1819,  0x0479fb70},
-{13600000, DIF_BPF_COEFF2021,  0xfbad0713},
-{13600000, DIF_BPF_COEFF2223,  0x032ff672},
-{13600000, DIF_BPF_COEFF2425,  0xff100b83},
-{13600000, DIF_BPF_COEFF2627,  0xfdaff38b},
-{13600000, DIF_BPF_COEFF2829,  0x063c0c04},
-{13600000, DIF_BPF_COEFF3031,  0xf5baf5f5},
-{13600000, DIF_BPF_COEFF3233,  0x0dcc06ae},
-{13600000, DIF_BPF_COEFF3435,  0xefcdfda8},
-{13600000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 136_quant.dat*/
-
-
-/*case 13700000:*/
-/* BEGIN - DIF BPF register values from 137_quant.dat*/
-{13700000, DIF_BPF_COEFF01,    0x0000fffd},
-{13700000, DIF_BPF_COEFF23,    0xfffd0012},
-{13700000, DIF_BPF_COEFF45,    0x0004ffc8},
-{13700000, DIF_BPF_COEFF67,    0x00100078},
-{13700000, DIF_BPF_COEFF89,    0xffacff3e},
-{13700000, DIF_BPF_COEFF1011,  0x00e200f0},
-{13700000, DIF_BPF_COEFF1213,  0xfe39ff35},
-{13700000, DIF_BPF_COEFF1415,  0x02f10017},
-{13700000, DIF_BPF_COEFF1617,  0xfbd30156},
-{13700000, DIF_BPF_COEFF1819,  0x0521fc7f},
-{13700000, DIF_BPF_COEFF2021,  0xfa9c0638},
-{13700000, DIF_BPF_COEFF2223,  0x0499f6ee},
-{13700000, DIF_BPF_COEFF2425,  0xfd7a0b7c},
-{13700000, DIF_BPF_COEFF2627,  0xff39f325},
-{13700000, DIF_BPF_COEFF2829,  0x04f40cb3},
-{13700000, DIF_BPF_COEFF3031,  0xf69af537},
-{13700000, DIF_BPF_COEFF3233,  0x0d5a073f},
-{13700000, DIF_BPF_COEFF3435,  0xefecfd72},
-{13700000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 137_quant.dat*/
-
-
-/*case 13800000:*/
-/* BEGIN - DIF BPF register values from 138_quant.dat*/
-{13800000, DIF_BPF_COEFF01,    0x0001fffe},
-{13800000, DIF_BPF_COEFF23,    0xfffa000e},
-{13800000, DIF_BPF_COEFF45,    0x0011ffcb},
-{13800000, DIF_BPF_COEFF67,    0xfff0007f},
-{13800000, DIF_BPF_COEFF89,    0xffe7ff19},
-{13800000, DIF_BPF_COEFF1011,  0x008f014a},
-{13800000, DIF_BPF_COEFF1213,  0xfe94fe93},
-{13800000, DIF_BPF_COEFF1415,  0x02b00105},
-{13800000, DIF_BPF_COEFF1617,  0xfbd3002f},
-{13800000, DIF_BPF_COEFF1819,  0x0585fdb7},
-{13800000, DIF_BPF_COEFF2021,  0xf9c10525},
-{13800000, DIF_BPF_COEFF2223,  0x05def7a8},
-{13800000, DIF_BPF_COEFF2425,  0xfbf20b3c},
-{13800000, DIF_BPF_COEFF2627,  0x00c7f2e9},
-{13800000, DIF_BPF_COEFF2829,  0x03a00d48},
-{13800000, DIF_BPF_COEFF3031,  0xf787f484},
-{13800000, DIF_BPF_COEFF3233,  0x0cdf07cd},
-{13800000, DIF_BPF_COEFF3435,  0xf00dfd3c},
-{13800000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 138_quant.dat*/
-
-
-/*case 13900000:*/
-/* BEGIN - DIF BPF register values from 139_quant.dat*/
-{13900000, DIF_BPF_COEFF01,    0x00010000},
-{13900000, DIF_BPF_COEFF23,    0xfff80008},
-{13900000, DIF_BPF_COEFF45,    0x001bffd7},
-{13900000, DIF_BPF_COEFF67,    0xffd10076},
-{13900000, DIF_BPF_COEFF89,    0x0026ff0e},
-{13900000, DIF_BPF_COEFF1011,  0x002c0184},
-{13900000, DIF_BPF_COEFF1213,  0xff0ffe10},
-{13900000, DIF_BPF_COEFF1415,  0x023b01e0},
-{13900000, DIF_BPF_COEFF1617,  0xfc17ff06},
-{13900000, DIF_BPF_COEFF1819,  0x05a2ff09},
-{13900000, DIF_BPF_COEFF2021,  0xf92703e4},
-{13900000, DIF_BPF_COEFF2223,  0x06f4f89b},
-{13900000, DIF_BPF_COEFF2425,  0xfa820ac5},
-{13900000, DIF_BPF_COEFF2627,  0x0251f2d9},
-{13900000, DIF_BPF_COEFF2829,  0x02430dc3},
-{13900000, DIF_BPF_COEFF3031,  0xf881f3dc},
-{13900000, DIF_BPF_COEFF3233,  0x0c5c0859},
-{13900000, DIF_BPF_COEFF3435,  0xf031fd06},
-{13900000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 139_quant.dat*/
-
-
-/*case 14000000:*/
-/* BEGIN - DIF BPF register values from 140_quant.dat*/
-{14000000, DIF_BPF_COEFF01,    0x00010001},
-{14000000, DIF_BPF_COEFF23,    0xfff80001},
-{14000000, DIF_BPF_COEFF45,    0x0021ffe8},
-{14000000, DIF_BPF_COEFF67,    0xffba005d},
-{14000000, DIF_BPF_COEFF89,    0x0060ff1f},
-{14000000, DIF_BPF_COEFF1011,  0xffc40198},
-{14000000, DIF_BPF_COEFF1213,  0xffa0fdb5},
-{14000000, DIF_BPF_COEFF1415,  0x019a029a},
-{14000000, DIF_BPF_COEFF1617,  0xfc99fdea},
-{14000000, DIF_BPF_COEFF1819,  0x05750067},
-{14000000, DIF_BPF_COEFF2021,  0xf8d4027f},
-{14000000, DIF_BPF_COEFF2223,  0x07d4f9c0},
-{14000000, DIF_BPF_COEFF2425,  0xf9320a1a},
-{14000000, DIF_BPF_COEFF2627,  0x03d2f2f3},
-{14000000, DIF_BPF_COEFF2829,  0x00df0e22},
-{14000000, DIF_BPF_COEFF3031,  0xf986f341},
-{14000000, DIF_BPF_COEFF3233,  0x0bd108e2},
-{14000000, DIF_BPF_COEFF3435,  0xf058fcd1},
-{14000000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 140_quant.dat*/
-
-
-/*case 14100000:*/
-/* BEGIN - DIF BPF register values from 141_quant.dat*/
-{14100000, DIF_BPF_COEFF01,    0x00000002},
-{14100000, DIF_BPF_COEFF23,    0xfff9fffa},
-{14100000, DIF_BPF_COEFF45,    0x0021fffd},
-{14100000, DIF_BPF_COEFF67,    0xffac0038},
-{14100000, DIF_BPF_COEFF89,    0x008eff4a},
-{14100000, DIF_BPF_COEFF1011,  0xff630184},
-{14100000, DIF_BPF_COEFF1213,  0x003afd8b},
-{14100000, DIF_BPF_COEFF1415,  0x00da0326},
-{14100000, DIF_BPF_COEFF1617,  0xfd51fced},
-{14100000, DIF_BPF_COEFF1819,  0x050101c0},
-{14100000, DIF_BPF_COEFF2021,  0xf8cb0103},
-{14100000, DIF_BPF_COEFF2223,  0x0876fb10},
-{14100000, DIF_BPF_COEFF2425,  0xf80a093e},
-{14100000, DIF_BPF_COEFF2627,  0x0543f338},
-{14100000, DIF_BPF_COEFF2829,  0xff7a0e66},
-{14100000, DIF_BPF_COEFF3031,  0xfa94f2b2},
-{14100000, DIF_BPF_COEFF3233,  0x0b3f0967},
-{14100000, DIF_BPF_COEFF3435,  0xf081fc9b},
-{14100000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 141_quant.dat*/
-
-
-/*case 14200000:*/
-/* BEGIN - DIF BPF register values from 142_quant.dat*/
-{14200000, DIF_BPF_COEFF01,    0x00000003},
-{14200000, DIF_BPF_COEFF23,    0xfffbfff3},
-{14200000, DIF_BPF_COEFF45,    0x001d0013},
-{14200000, DIF_BPF_COEFF67,    0xffaa000b},
-{14200000, DIF_BPF_COEFF89,    0x00aaff89},
-{14200000, DIF_BPF_COEFF1011,  0xff13014a},
-{14200000, DIF_BPF_COEFF1213,  0x00cefd95},
-{14200000, DIF_BPF_COEFF1415,  0x000a037b},
-{14200000, DIF_BPF_COEFF1617,  0xfe35fc1d},
-{14200000, DIF_BPF_COEFF1819,  0x044c0305},
-{14200000, DIF_BPF_COEFF2021,  0xf90cff7e},
-{14200000, DIF_BPF_COEFF2223,  0x08d5fc81},
-{14200000, DIF_BPF_COEFF2425,  0xf7100834},
-{14200000, DIF_BPF_COEFF2627,  0x069ff3a7},
-{14200000, DIF_BPF_COEFF2829,  0xfe160e8d},
-{14200000, DIF_BPF_COEFF3031,  0xfbaaf231},
-{14200000, DIF_BPF_COEFF3233,  0x0aa509e9},
-{14200000, DIF_BPF_COEFF3435,  0xf0adfc65},
-{14200000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 142_quant.dat*/
-
-
-/*case 14300000:*/
-/* BEGIN - DIF BPF register values from 143_quant.dat*/
-{14300000, DIF_BPF_COEFF01,    0x00000003},
-{14300000, DIF_BPF_COEFF23,    0xffffffef},
-{14300000, DIF_BPF_COEFF45,    0x00140025},
-{14300000, DIF_BPF_COEFF67,    0xffb4ffdd},
-{14300000, DIF_BPF_COEFF89,    0x00b2ffd6},
-{14300000, DIF_BPF_COEFF1011,  0xfedb00f0},
-{14300000, DIF_BPF_COEFF1213,  0x0150fdd3},
-{14300000, DIF_BPF_COEFF1415,  0xff380391},
-{14300000, DIF_BPF_COEFF1617,  0xff36fb85},
-{14300000, DIF_BPF_COEFF1819,  0x035e0426},
-{14300000, DIF_BPF_COEFF2021,  0xf994fdfe},
-{14300000, DIF_BPF_COEFF2223,  0x08eefe0b},
-{14300000, DIF_BPF_COEFF2425,  0xf6490702},
-{14300000, DIF_BPF_COEFF2627,  0x07e1f43e},
-{14300000, DIF_BPF_COEFF2829,  0xfcb60e97},
-{14300000, DIF_BPF_COEFF3031,  0xfcc6f1be},
-{14300000, DIF_BPF_COEFF3233,  0x0a040a67},
-{14300000, DIF_BPF_COEFF3435,  0xf0dbfc30},
-{14300000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 143_quant.dat*/
-
-
-/*case 14400000:*/
-/* BEGIN - DIF BPF register values from 144_quant.dat*/
-{14400000, DIF_BPF_COEFF01,    0x00000003},
-{14400000, DIF_BPF_COEFF23,    0x0002ffee},
-{14400000, DIF_BPF_COEFF45,    0x00070033},
-{14400000, DIF_BPF_COEFF67,    0xffc9ffb4},
-{14400000, DIF_BPF_COEFF89,    0x00a40027},
-{14400000, DIF_BPF_COEFF1011,  0xfec3007e},
-{14400000, DIF_BPF_COEFF1213,  0x01b4fe3f},
-{14400000, DIF_BPF_COEFF1415,  0xfe760369},
-{14400000, DIF_BPF_COEFF1617,  0x0044fb2e},
-{14400000, DIF_BPF_COEFF1819,  0x02450518},
-{14400000, DIF_BPF_COEFF2021,  0xfa5ffc90},
-{14400000, DIF_BPF_COEFF2223,  0x08c1ffa1},
-{14400000, DIF_BPF_COEFF2425,  0xf5bc05ae},
-{14400000, DIF_BPF_COEFF2627,  0x0902f4fc},
-{14400000, DIF_BPF_COEFF2829,  0xfb600e85},
-{14400000, DIF_BPF_COEFF3031,  0xfde7f15a},
-{14400000, DIF_BPF_COEFF3233,  0x095d0ae2},
-{14400000, DIF_BPF_COEFF3435,  0xf10cfbfb},
-{14400000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 144_quant.dat*/
-
-
-/*case 14500000:*/
-/* BEGIN - DIF BPF register values from 145_quant.dat*/
-{14500000, DIF_BPF_COEFF01,    0xffff0002},
-{14500000, DIF_BPF_COEFF23,    0x0005ffef},
-{14500000, DIF_BPF_COEFF45,    0xfffa0038},
-{14500000, DIF_BPF_COEFF67,    0xffe5ff95},
-{14500000, DIF_BPF_COEFF89,    0x00820074},
-{14500000, DIF_BPF_COEFF1011,  0xfecc0000},
-{14500000, DIF_BPF_COEFF1213,  0x01f0fed0},
-{14500000, DIF_BPF_COEFF1415,  0xfdd20304},
-{14500000, DIF_BPF_COEFF1617,  0x014dfb1d},
-{14500000, DIF_BPF_COEFF1819,  0x010e05ce},
-{14500000, DIF_BPF_COEFF2021,  0xfb64fb41},
-{14500000, DIF_BPF_COEFF2223,  0x084e013b},
-{14500000, DIF_BPF_COEFF2425,  0xf569043e},
-{14500000, DIF_BPF_COEFF2627,  0x0a00f5dd},
-{14500000, DIF_BPF_COEFF2829,  0xfa150e55},
-{14500000, DIF_BPF_COEFF3031,  0xff0bf104},
-{14500000, DIF_BPF_COEFF3233,  0x08b00b59},
-{14500000, DIF_BPF_COEFF3435,  0xf13ffbc6},
-{14500000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 145_quant.dat*/
-
-
-/*case 14600000:*/
-/* BEGIN - DIF BPF register values from 146_quant.dat*/
-{14600000, DIF_BPF_COEFF01,    0xffff0001},
-{14600000, DIF_BPF_COEFF23,    0x0008fff4},
-{14600000, DIF_BPF_COEFF45,    0xffed0035},
-{14600000, DIF_BPF_COEFF67,    0x0005ff83},
-{14600000, DIF_BPF_COEFF89,    0x005000b4},
-{14600000, DIF_BPF_COEFF1011,  0xfef6ff82},
-{14600000, DIF_BPF_COEFF1213,  0x01ffff7a},
-{14600000, DIF_BPF_COEFF1415,  0xfd580269},
-{14600000, DIF_BPF_COEFF1617,  0x0241fb53},
-{14600000, DIF_BPF_COEFF1819,  0xffca0640},
-{14600000, DIF_BPF_COEFF2021,  0xfc99fa1e},
-{14600000, DIF_BPF_COEFF2223,  0x079a02cb},
-{14600000, DIF_BPF_COEFF2425,  0xf55502ba},
-{14600000, DIF_BPF_COEFF2627,  0x0ad5f6e0},
-{14600000, DIF_BPF_COEFF2829,  0xf8d90e0a},
-{14600000, DIF_BPF_COEFF3031,  0x0031f0bd},
-{14600000, DIF_BPF_COEFF3233,  0x07fd0bcb},
-{14600000, DIF_BPF_COEFF3435,  0xf174fb91},
-{14600000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 146_quant.dat*/
-
-
-/*case 14700000:*/
-/* BEGIN - DIF BPF register values from 147_quant.dat*/
-{14700000, DIF_BPF_COEFF01,    0xffffffff},
-{14700000, DIF_BPF_COEFF23,    0x0009fffb},
-{14700000, DIF_BPF_COEFF45,    0xffe4002a},
-{14700000, DIF_BPF_COEFF67,    0x0025ff82},
-{14700000, DIF_BPF_COEFF89,    0x001400e0},
-{14700000, DIF_BPF_COEFF1011,  0xff3cff10},
-{14700000, DIF_BPF_COEFF1213,  0x01e10030},
-{14700000, DIF_BPF_COEFF1415,  0xfd1201a4},
-{14700000, DIF_BPF_COEFF1617,  0x0311fbcd},
-{14700000, DIF_BPF_COEFF1819,  0xfe88066a},
-{14700000, DIF_BPF_COEFF2021,  0xfdf1f92f},
-{14700000, DIF_BPF_COEFF2223,  0x06aa0449},
-{14700000, DIF_BPF_COEFF2425,  0xf57e0128},
-{14700000, DIF_BPF_COEFF2627,  0x0b7ef801},
-{14700000, DIF_BPF_COEFF2829,  0xf7b00da2},
-{14700000, DIF_BPF_COEFF3031,  0x0156f086},
-{14700000, DIF_BPF_COEFF3233,  0x07450c39},
-{14700000, DIF_BPF_COEFF3435,  0xf1acfb5c},
-{14700000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 147_quant.dat*/
-
-
-/*case 14800000:*/
-/* BEGIN - DIF BPF register values from 148_quant.dat*/
-{14800000, DIF_BPF_COEFF01,    0x0000fffe},
-{14800000, DIF_BPF_COEFF23,    0x00080002},
-{14800000, DIF_BPF_COEFF45,    0xffdf0019},
-{14800000, DIF_BPF_COEFF67,    0x003fff92},
-{14800000, DIF_BPF_COEFF89,    0xffd600f1},
-{14800000, DIF_BPF_COEFF1011,  0xff96feb6},
-{14800000, DIF_BPF_COEFF1213,  0x019700e1},
-{14800000, DIF_BPF_COEFF1415,  0xfd0500c2},
-{14800000, DIF_BPF_COEFF1617,  0x03b0fc84},
-{14800000, DIF_BPF_COEFF1819,  0xfd590649},
-{14800000, DIF_BPF_COEFF2021,  0xff5df87f},
-{14800000, DIF_BPF_COEFF2223,  0x058505aa},
-{14800000, DIF_BPF_COEFF2425,  0xf5e4ff91},
-{14800000, DIF_BPF_COEFF2627,  0x0bf9f93c},
-{14800000, DIF_BPF_COEFF2829,  0xf69d0d20},
-{14800000, DIF_BPF_COEFF3031,  0x0279f05e},
-{14800000, DIF_BPF_COEFF3233,  0x06880ca3},
-{14800000, DIF_BPF_COEFF3435,  0xf1e6fb28},
-{14800000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 148_quant.dat*/
-
-
-/*case 14900000:*/
-/* BEGIN - DIF BPF register values from 149_quant.dat*/
-{14900000, DIF_BPF_COEFF01,    0x0000fffd},
-{14900000, DIF_BPF_COEFF23,    0x00060009},
-{14900000, DIF_BPF_COEFF45,    0xffdf0004},
-{14900000, DIF_BPF_COEFF67,    0x0051ffb0},
-{14900000, DIF_BPF_COEFF89,    0xff9d00e8},
-{14900000, DIF_BPF_COEFF1011,  0xfffcfe7c},
-{14900000, DIF_BPF_COEFF1213,  0x01280180},
-{14900000, DIF_BPF_COEFF1415,  0xfd32ffd2},
-{14900000, DIF_BPF_COEFF1617,  0x0413fd6e},
-{14900000, DIF_BPF_COEFF1819,  0xfc4d05df},
-{14900000, DIF_BPF_COEFF2021,  0x00d1f812},
-{14900000, DIF_BPF_COEFF2223,  0x043506e4},
-{14900000, DIF_BPF_COEFF2425,  0xf685fdfb},
-{14900000, DIF_BPF_COEFF2627,  0x0c43fa8d},
-{14900000, DIF_BPF_COEFF2829,  0xf5a10c83},
-{14900000, DIF_BPF_COEFF3031,  0x0399f046},
-{14900000, DIF_BPF_COEFF3233,  0x05c70d08},
-{14900000, DIF_BPF_COEFF3435,  0xf222faf3},
-{14900000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 149_quant.dat*/
-
-
-/*case 15000000:*/
-/* BEGIN - DIF BPF register values from 150_quant.dat*/
-{15000000, DIF_BPF_COEFF01,    0x0000fffd},
-{15000000, DIF_BPF_COEFF23,    0x0003000f},
-{15000000, DIF_BPF_COEFF45,    0xffe5ffef},
-{15000000, DIF_BPF_COEFF67,    0x0057ffd9},
-{15000000, DIF_BPF_COEFF89,    0xff7000c4},
-{15000000, DIF_BPF_COEFF1011,  0x0062fe68},
-{15000000, DIF_BPF_COEFF1213,  0x009e01ff},
-{15000000, DIF_BPF_COEFF1415,  0xfd95fee6},
-{15000000, DIF_BPF_COEFF1617,  0x0435fe7d},
-{15000000, DIF_BPF_COEFF1819,  0xfb710530},
-{15000000, DIF_BPF_COEFF2021,  0x023cf7ee},
-{15000000, DIF_BPF_COEFF2223,  0x02c307ef},
-{15000000, DIF_BPF_COEFF2425,  0xf75efc70},
-{15000000, DIF_BPF_COEFF2627,  0x0c5cfbef},
-{15000000, DIF_BPF_COEFF2829,  0xf4c10bce},
-{15000000, DIF_BPF_COEFF3031,  0x04b3f03f},
-{15000000, DIF_BPF_COEFF3233,  0x05030d69},
-{15000000, DIF_BPF_COEFF3435,  0xf261fabf},
-{15000000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 150_quant.dat*/
-
-
-/*case 15100000:*/
-/* BEGIN - DIF BPF register values from 151_quant.dat*/
-{15100000, DIF_BPF_COEFF01,    0x0000fffd},
-{15100000, DIF_BPF_COEFF23,    0xffff0012},
-{15100000, DIF_BPF_COEFF45,    0xffefffdc},
-{15100000, DIF_BPF_COEFF67,    0x00510006},
-{15100000, DIF_BPF_COEFF89,    0xff540089},
-{15100000, DIF_BPF_COEFF1011,  0x00befe7c},
-{15100000, DIF_BPF_COEFF1213,  0x00060253},
-{15100000, DIF_BPF_COEFF1415,  0xfe27fe0d},
-{15100000, DIF_BPF_COEFF1617,  0x0413ffa2},
-{15100000, DIF_BPF_COEFF1819,  0xfad10446},
-{15100000, DIF_BPF_COEFF2021,  0x0390f812},
-{15100000, DIF_BPF_COEFF2223,  0x013b08c3},
-{15100000, DIF_BPF_COEFF2425,  0xf868faf6},
-{15100000, DIF_BPF_COEFF2627,  0x0c43fd5f},
-{15100000, DIF_BPF_COEFF2829,  0xf3fd0b02},
-{15100000, DIF_BPF_COEFF3031,  0x05c7f046},
-{15100000, DIF_BPF_COEFF3233,  0x043b0dc4},
-{15100000, DIF_BPF_COEFF3435,  0xf2a1fa8b},
-{15100000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 151_quant.dat*/
-
-
-/*case 15200000:*/
-/* BEGIN - DIF BPF register values from 152_quant.dat*/
-{15200000, DIF_BPF_COEFF01,    0x0001fffe},
-{15200000, DIF_BPF_COEFF23,    0xfffc0012},
-{15200000, DIF_BPF_COEFF45,    0xfffbffce},
-{15200000, DIF_BPF_COEFF67,    0x003f0033},
-{15200000, DIF_BPF_COEFF89,    0xff4e003f},
-{15200000, DIF_BPF_COEFF1011,  0x0106feb6},
-{15200000, DIF_BPF_COEFF1213,  0xff6e0276},
-{15200000, DIF_BPF_COEFF1415,  0xfeddfd56},
-{15200000, DIF_BPF_COEFF1617,  0x03b000cc},
-{15200000, DIF_BPF_COEFF1819,  0xfa740329},
-{15200000, DIF_BPF_COEFF2021,  0x04bff87f},
-{15200000, DIF_BPF_COEFF2223,  0xffaa095d},
-{15200000, DIF_BPF_COEFF2425,  0xf99ef995},
-{15200000, DIF_BPF_COEFF2627,  0x0bf9fed8},
-{15200000, DIF_BPF_COEFF2829,  0xf3590a1f},
-{15200000, DIF_BPF_COEFF3031,  0x06d2f05e},
-{15200000, DIF_BPF_COEFF3233,  0x03700e1b},
-{15200000, DIF_BPF_COEFF3435,  0xf2e4fa58},
-{15200000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 152_quant.dat*/
-
-
-/*case 115300000:*/
-/* BEGIN - DIF BPF register values from 153_quant.dat*/
-{15300000, DIF_BPF_COEFF01,    0x0001ffff},
-{15300000, DIF_BPF_COEFF23,    0xfff9000f},
-{15300000, DIF_BPF_COEFF45,    0x0009ffc8},
-{15300000, DIF_BPF_COEFF67,    0x00250059},
-{15300000, DIF_BPF_COEFF89,    0xff5effee},
-{15300000, DIF_BPF_COEFF1011,  0x0132ff10},
-{15300000, DIF_BPF_COEFF1213,  0xfee30265},
-{15300000, DIF_BPF_COEFF1415,  0xffaafccf},
-{15300000, DIF_BPF_COEFF1617,  0x031101eb},
-{15300000, DIF_BPF_COEFF1819,  0xfa6001e8},
-{15300000, DIF_BPF_COEFF2021,  0x05bdf92f},
-{15300000, DIF_BPF_COEFF2223,  0xfe1b09b6},
-{15300000, DIF_BPF_COEFF2425,  0xfafaf852},
-{15300000, DIF_BPF_COEFF2627,  0x0b7e0055},
-{15300000, DIF_BPF_COEFF2829,  0xf2d50929},
-{15300000, DIF_BPF_COEFF3031,  0x07d3f086},
-{15300000, DIF_BPF_COEFF3233,  0x02a30e6c},
-{15300000, DIF_BPF_COEFF3435,  0xf329fa24},
-{15300000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 153_quant.dat*/
-
-
-/*case 115400000:*/
-/* BEGIN - DIF BPF register values from 154_quant.dat*/
-{15400000, DIF_BPF_COEFF01,    0x00010001},
-{15400000, DIF_BPF_COEFF23,    0xfff80009},
-{15400000, DIF_BPF_COEFF45,    0x0015ffca},
-{15400000, DIF_BPF_COEFF67,    0x00050074},
-{15400000, DIF_BPF_COEFF89,    0xff81ff9f},
-{15400000, DIF_BPF_COEFF1011,  0x013dff82},
-{15400000, DIF_BPF_COEFF1213,  0xfe710221},
-{15400000, DIF_BPF_COEFF1415,  0x007cfc80},
-{15400000, DIF_BPF_COEFF1617,  0x024102ed},
-{15400000, DIF_BPF_COEFF1819,  0xfa940090},
-{15400000, DIF_BPF_COEFF2021,  0x0680fa1e},
-{15400000, DIF_BPF_COEFF2223,  0xfc9b09cd},
-{15400000, DIF_BPF_COEFF2425,  0xfc73f736},
-{15400000, DIF_BPF_COEFF2627,  0x0ad501d0},
-{15400000, DIF_BPF_COEFF2829,  0xf2740820},
-{15400000, DIF_BPF_COEFF3031,  0x08c9f0bd},
-{15400000, DIF_BPF_COEFF3233,  0x01d40eb9},
-{15400000, DIF_BPF_COEFF3435,  0xf371f9f1},
-{15400000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 154_quant.dat*/
-
-
-/*case 115500000:*/
-/* BEGIN - DIF BPF register values from 155_quant.dat*/
-{15500000, DIF_BPF_COEFF01,    0x00000002},
-{15500000, DIF_BPF_COEFF23,    0xfff80002},
-{15500000, DIF_BPF_COEFF45,    0x001effd5},
-{15500000, DIF_BPF_COEFF67,    0xffe5007f},
-{15500000, DIF_BPF_COEFF89,    0xffb4ff5b},
-{15500000, DIF_BPF_COEFF1011,  0x01280000},
-{15500000, DIF_BPF_COEFF1213,  0xfe2401b0},
-{15500000, DIF_BPF_COEFF1415,  0x0146fc70},
-{15500000, DIF_BPF_COEFF1617,  0x014d03c6},
-{15500000, DIF_BPF_COEFF1819,  0xfb10ff32},
-{15500000, DIF_BPF_COEFF2021,  0x0701fb41},
-{15500000, DIF_BPF_COEFF2223,  0xfb3709a1},
-{15500000, DIF_BPF_COEFF2425,  0xfe00f644},
-{15500000, DIF_BPF_COEFF2627,  0x0a000345},
-{15500000, DIF_BPF_COEFF2829,  0xf2350708},
-{15500000, DIF_BPF_COEFF3031,  0x09b2f104},
-{15500000, DIF_BPF_COEFF3233,  0x01050eff},
-{15500000, DIF_BPF_COEFF3435,  0xf3baf9be},
-{15500000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 155_quant.dat*/
-
-
-/*case 115600000:*/
-/* BEGIN - DIF BPF register values from 156_quant.dat*/
-{15600000, DIF_BPF_COEFF01,    0x00000003},
-{15600000, DIF_BPF_COEFF23,    0xfff9fffb},
-{15600000, DIF_BPF_COEFF45,    0x0022ffe6},
-{15600000, DIF_BPF_COEFF67,    0xffc9007a},
-{15600000, DIF_BPF_COEFF89,    0xfff0ff29},
-{15600000, DIF_BPF_COEFF1011,  0x00f2007e},
-{15600000, DIF_BPF_COEFF1213,  0xfe01011b},
-{15600000, DIF_BPF_COEFF1415,  0x01f6fc9e},
-{15600000, DIF_BPF_COEFF1617,  0x00440467},
-{15600000, DIF_BPF_COEFF1819,  0xfbccfdde},
-{15600000, DIF_BPF_COEFF2021,  0x0738fc90},
-{15600000, DIF_BPF_COEFF2223,  0xf9f70934},
-{15600000, DIF_BPF_COEFF2425,  0xff99f582},
-{15600000, DIF_BPF_COEFF2627,  0x090204b0},
-{15600000, DIF_BPF_COEFF2829,  0xf21a05e1},
-{15600000, DIF_BPF_COEFF3031,  0x0a8df15a},
-{15600000, DIF_BPF_COEFF3233,  0x00340f41},
-{15600000, DIF_BPF_COEFF3435,  0xf405f98b},
-{15600000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 156_quant.dat*/
-
-
-/*case 115700000:*/
-/* BEGIN - DIF BPF register values from 157_quant.dat*/
-{15700000, DIF_BPF_COEFF01,    0x00000003},
-{15700000, DIF_BPF_COEFF23,    0xfffcfff4},
-{15700000, DIF_BPF_COEFF45,    0x0020fffa},
-{15700000, DIF_BPF_COEFF67,    0xffb40064},
-{15700000, DIF_BPF_COEFF89,    0x002fff11},
-{15700000, DIF_BPF_COEFF1011,  0x00a400f0},
-{15700000, DIF_BPF_COEFF1213,  0xfe0d006e},
-{15700000, DIF_BPF_COEFF1415,  0x0281fd09},
-{15700000, DIF_BPF_COEFF1617,  0xff3604c9},
-{15700000, DIF_BPF_COEFF1819,  0xfcbffca2},
-{15700000, DIF_BPF_COEFF2021,  0x0726fdfe},
-{15700000, DIF_BPF_COEFF2223,  0xf8e80888},
-{15700000, DIF_BPF_COEFF2425,  0x0134f4f3},
-{15700000, DIF_BPF_COEFF2627,  0x07e1060c},
-{15700000, DIF_BPF_COEFF2829,  0xf22304af},
-{15700000, DIF_BPF_COEFF3031,  0x0b59f1be},
-{15700000, DIF_BPF_COEFF3233,  0xff640f7d},
-{15700000, DIF_BPF_COEFF3435,  0xf452f959},
-{15700000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 157_quant.dat*/
-
-
-/*case 115800000:*/
-/* BEGIN - DIF BPF register values from 158_quant.dat*/
-{15800000, DIF_BPF_COEFF01,    0x00000003},
-{15800000, DIF_BPF_COEFF23,    0x0000fff0},
-{15800000, DIF_BPF_COEFF45,    0x001a0010},
-{15800000, DIF_BPF_COEFF67,    0xffaa0041},
-{15800000, DIF_BPF_COEFF89,    0x0067ff13},
-{15800000, DIF_BPF_COEFF1011,  0x0043014a},
-{15800000, DIF_BPF_COEFF1213,  0xfe46ffb9},
-{15800000, DIF_BPF_COEFF1415,  0x02dbfda8},
-{15800000, DIF_BPF_COEFF1617,  0xfe3504e5},
-{15800000, DIF_BPF_COEFF1819,  0xfddcfb8d},
-{15800000, DIF_BPF_COEFF2021,  0x06c9ff7e},
-{15800000, DIF_BPF_COEFF2223,  0xf81107a2},
-{15800000, DIF_BPF_COEFF2425,  0x02c9f49a},
-{15800000, DIF_BPF_COEFF2627,  0x069f0753},
-{15800000, DIF_BPF_COEFF2829,  0xf2500373},
-{15800000, DIF_BPF_COEFF3031,  0x0c14f231},
-{15800000, DIF_BPF_COEFF3233,  0xfe930fb3},
-{15800000, DIF_BPF_COEFF3435,  0xf4a1f927},
-{15800000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 158_quant.dat*/
-
-
-/*case 115900000:*/
-/* BEGIN - DIF BPF register values from 159_quant.dat*/
-{15900000, DIF_BPF_COEFF01,    0xffff0002},
-{15900000, DIF_BPF_COEFF23,    0x0003ffee},
-{15900000, DIF_BPF_COEFF45,    0x000f0023},
-{15900000, DIF_BPF_COEFF67,    0xffac0016},
-{15900000, DIF_BPF_COEFF89,    0x0093ff31},
-{15900000, DIF_BPF_COEFF1011,  0xffdc0184},
-{15900000, DIF_BPF_COEFF1213,  0xfea6ff09},
-{15900000, DIF_BPF_COEFF1415,  0x02fdfe70},
-{15900000, DIF_BPF_COEFF1617,  0xfd5104ba},
-{15900000, DIF_BPF_COEFF1819,  0xff15faac},
-{15900000, DIF_BPF_COEFF2021,  0x06270103},
-{15900000, DIF_BPF_COEFF2223,  0xf7780688},
-{15900000, DIF_BPF_COEFF2425,  0x044df479},
-{15900000, DIF_BPF_COEFF2627,  0x05430883},
-{15900000, DIF_BPF_COEFF2829,  0xf2a00231},
-{15900000, DIF_BPF_COEFF3031,  0x0cbef2b2},
-{15900000, DIF_BPF_COEFF3233,  0xfdc40fe3},
-{15900000, DIF_BPF_COEFF3435,  0xf4f2f8f5},
-{15900000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 159_quant.dat*/
-
-
-/*case 116000000:*/
-/* BEGIN - DIF BPF register values from 160_quant.dat*/
-{16000000, DIF_BPF_COEFF01,    0xffff0001},
-{16000000, DIF_BPF_COEFF23,    0x0006ffef},
-{16000000, DIF_BPF_COEFF45,    0x00020031},
-{16000000, DIF_BPF_COEFF67,    0xffbaffe8},
-{16000000, DIF_BPF_COEFF89,    0x00adff66},
-{16000000, DIF_BPF_COEFF1011,  0xff790198},
-{16000000, DIF_BPF_COEFF1213,  0xff26fe6e},
-{16000000, DIF_BPF_COEFF1415,  0x02e5ff55},
-{16000000, DIF_BPF_COEFF1617,  0xfc99044a},
-{16000000, DIF_BPF_COEFF1819,  0x005bfa09},
-{16000000, DIF_BPF_COEFF2021,  0x0545027f},
-{16000000, DIF_BPF_COEFF2223,  0xf7230541},
-{16000000, DIF_BPF_COEFF2425,  0x05b8f490},
-{16000000, DIF_BPF_COEFF2627,  0x03d20997},
-{16000000, DIF_BPF_COEFF2829,  0xf31300eb},
-{16000000, DIF_BPF_COEFF3031,  0x0d55f341},
-{16000000, DIF_BPF_COEFF3233,  0xfcf6100e},
-{16000000, DIF_BPF_COEFF3435,  0xf544f8c3},
-{16000000, DIF_BPF_COEFF36,    0x110d0000},
-/* END - DIF BPF register values from 160_quant.dat*/
-};
-
-#endif
diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c
deleted file mode 100644 (file)
index 7c4e360..0000000
+++ /dev/null
@@ -1,796 +0,0 @@
-/*
- DVB device driver for cx231xx
-
- Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
-               Based on em28xx driver
-
- This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   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/slab.h>
-#include <linux/usb.h>
-
-#include "cx231xx.h"
-#include <media/v4l2-common.h>
-#include <media/videobuf-vmalloc.h>
-
-#include "xc5000.h"
-#include "s5h1432.h"
-#include "tda18271.h"
-#include "s5h1411.h"
-#include "lgdt3305.h"
-#include "mb86a20s.h"
-
-MODULE_DESCRIPTION("driver for cx231xx based DVB cards");
-MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
-MODULE_LICENSE("GPL");
-
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define dprintk(level, fmt, arg...) do {                       \
-if (debug >= level)                                            \
-       printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \
-} while (0)
-
-#define CX231XX_DVB_NUM_BUFS 5
-#define CX231XX_DVB_MAX_PACKETSIZE 564
-#define CX231XX_DVB_MAX_PACKETS 64
-
-struct cx231xx_dvb {
-       struct dvb_frontend *frontend;
-
-       /* feed count management */
-       struct mutex lock;
-       int nfeeds;
-
-       /* general boilerplate stuff */
-       struct dvb_adapter adapter;
-       struct dvb_demux demux;
-       struct dmxdev dmxdev;
-       struct dmx_frontend fe_hw;
-       struct dmx_frontend fe_mem;
-       struct dvb_net net;
-};
-
-static struct s5h1432_config dvico_s5h1432_config = {
-       .output_mode   = S5H1432_SERIAL_OUTPUT,
-       .gpio          = S5H1432_GPIO_ON,
-       .qam_if        = S5H1432_IF_4000,
-       .vsb_if        = S5H1432_IF_4000,
-       .inversion     = S5H1432_INVERSION_OFF,
-       .status_mode   = S5H1432_DEMODLOCKING,
-       .mpeg_timing   = S5H1432_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-
-static struct tda18271_std_map cnxt_rde253s_tda18271_std_map = {
-       .dvbt_6   = { .if_freq = 4000, .agc_mode = 3, .std = 4,
-                     .if_lvl = 1, .rfagc_top = 0x37, },
-       .dvbt_7   = { .if_freq = 4000, .agc_mode = 3, .std = 5,
-                     .if_lvl = 1, .rfagc_top = 0x37, },
-       .dvbt_8   = { .if_freq = 4000, .agc_mode = 3, .std = 6,
-                     .if_lvl = 1, .rfagc_top = 0x37, },
-};
-
-static struct tda18271_std_map mb86a20s_tda18271_config = {
-       .dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
-                     .if_lvl = 7, .rfagc_top = 0x37, },
-};
-
-static struct tda18271_config cnxt_rde253s_tunerconfig = {
-       .std_map = &cnxt_rde253s_tda18271_std_map,
-       .gate    = TDA18271_GATE_ANALOG,
-};
-
-static struct s5h1411_config tda18271_s5h1411_config = {
-       .output_mode   = S5H1411_SERIAL_OUTPUT,
-       .gpio          = S5H1411_GPIO_OFF,
-       .vsb_if        = S5H1411_IF_3250,
-       .qam_if        = S5H1411_IF_4000,
-       .inversion     = S5H1411_INVERSION_ON,
-       .status_mode   = S5H1411_DEMODLOCKING,
-       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-static struct s5h1411_config xc5000_s5h1411_config = {
-       .output_mode   = S5H1411_SERIAL_OUTPUT,
-       .gpio          = S5H1411_GPIO_OFF,
-       .vsb_if        = S5H1411_IF_3250,
-       .qam_if        = S5H1411_IF_3250,
-       .inversion     = S5H1411_INVERSION_OFF,
-       .status_mode   = S5H1411_DEMODLOCKING,
-       .mpeg_timing   = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
-};
-
-static struct lgdt3305_config hcw_lgdt3305_config = {
-       .i2c_addr           = 0x0e,
-       .mpeg_mode          = LGDT3305_MPEG_SERIAL,
-       .tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
-       .tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
-       .deny_i2c_rptr      = 1,
-       .spectral_inversion = 1,
-       .qam_if_khz         = 4000,
-       .vsb_if_khz         = 3250,
-};
-
-static struct tda18271_std_map hauppauge_tda18271_std_map = {
-       .atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 4,
-                     .if_lvl = 1, .rfagc_top = 0x58, },
-       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 5,
-                     .if_lvl = 1, .rfagc_top = 0x58, },
-};
-
-static struct tda18271_config hcw_tda18271_config = {
-       .std_map = &hauppauge_tda18271_std_map,
-       .gate    = TDA18271_GATE_DIGITAL,
-};
-
-static const struct mb86a20s_config pv_mb86a20s_config = {
-       .demod_address = 0x10,
-       .is_serial = true,
-};
-
-static struct tda18271_config pv_tda18271_config = {
-       .std_map = &mb86a20s_tda18271_config,
-       .gate    = TDA18271_GATE_DIGITAL,
-       .small_i2c = TDA18271_03_BYTE_CHUNK_INIT,
-};
-
-static inline void print_err_status(struct cx231xx *dev, int packet, int status)
-{
-       char *errmsg = "Unknown";
-
-       switch (status) {
-       case -ENOENT:
-               errmsg = "unlinked synchronuously";
-               break;
-       case -ECONNRESET:
-               errmsg = "unlinked asynchronuously";
-               break;
-       case -ENOSR:
-               errmsg = "Buffer error (overrun)";
-               break;
-       case -EPIPE:
-               errmsg = "Stalled (device not responding)";
-               break;
-       case -EOVERFLOW:
-               errmsg = "Babble (bad cable?)";
-               break;
-       case -EPROTO:
-               errmsg = "Bit-stuff error (bad cable?)";
-               break;
-       case -EILSEQ:
-               errmsg = "CRC/Timeout (could be anything)";
-               break;
-       case -ETIME:
-               errmsg = "Device does not respond";
-               break;
-       }
-       if (packet < 0) {
-               dprintk(1, "URB status %d [%s].\n", status, errmsg);
-       } else {
-               dprintk(1, "URB packet %d, status %d [%s].\n",
-                       packet, status, errmsg);
-       }
-}
-
-static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb)
-{
-       int i;
-
-       if (!dev)
-               return 0;
-
-       if (dev->state & DEV_DISCONNECTED)
-               return 0;
-
-       if (urb->status < 0) {
-               print_err_status(dev, -1, urb->status);
-               if (urb->status == -ENOENT)
-                       return 0;
-       }
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               int status = urb->iso_frame_desc[i].status;
-
-               if (status < 0) {
-                       print_err_status(dev, i, status);
-                       if (urb->iso_frame_desc[i].status != -EPROTO)
-                               continue;
-               }
-
-               dvb_dmx_swfilter(&dev->dvb->demux,
-                                urb->transfer_buffer +
-                               urb->iso_frame_desc[i].offset,
-                               urb->iso_frame_desc[i].actual_length);
-       }
-
-       return 0;
-}
-
-static inline int dvb_bulk_copy(struct cx231xx *dev, struct urb *urb)
-{
-       if (!dev)
-               return 0;
-
-       if (dev->state & DEV_DISCONNECTED)
-               return 0;
-
-       if (urb->status < 0) {
-               print_err_status(dev, -1, urb->status);
-               if (urb->status == -ENOENT)
-                       return 0;
-       }
-
-       /* Feed the transport payload into the kernel demux */
-       dvb_dmx_swfilter(&dev->dvb->demux,
-               urb->transfer_buffer, urb->actual_length);
-
-       return 0;
-}
-
-static int start_streaming(struct cx231xx_dvb *dvb)
-{
-       int rc;
-       struct cx231xx *dev = dvb->adapter.priv;
-
-       if (dev->USE_ISO) {
-               cx231xx_info("DVB transfer mode is ISO.\n");
-               mutex_lock(&dev->i2c_lock);
-               cx231xx_enable_i2c_port_3(dev, false);
-               cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
-               cx231xx_enable_i2c_port_3(dev, true);
-               mutex_unlock(&dev->i2c_lock);
-               rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
-               if (rc < 0)
-                       return rc;
-               dev->mode_tv = 1;
-               return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS,
-                                       CX231XX_DVB_NUM_BUFS,
-                                       dev->ts1_mode.max_pkt_size,
-                                       dvb_isoc_copy);
-       } else {
-               cx231xx_info("DVB transfer mode is BULK.\n");
-               cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
-               rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
-               if (rc < 0)
-                       return rc;
-               dev->mode_tv = 1;
-               return cx231xx_init_bulk(dev, CX231XX_DVB_MAX_PACKETS,
-                                       CX231XX_DVB_NUM_BUFS,
-                                       dev->ts1_mode.max_pkt_size,
-                                       dvb_bulk_copy);
-       }
-
-}
-
-static int stop_streaming(struct cx231xx_dvb *dvb)
-{
-       struct cx231xx *dev = dvb->adapter.priv;
-
-       if (dev->USE_ISO)
-               cx231xx_uninit_isoc(dev);
-       else
-               cx231xx_uninit_bulk(dev);
-
-       cx231xx_set_mode(dev, CX231XX_SUSPEND);
-
-       return 0;
-}
-
-static int start_feed(struct dvb_demux_feed *feed)
-{
-       struct dvb_demux *demux = feed->demux;
-       struct cx231xx_dvb *dvb = demux->priv;
-       int rc, ret;
-
-       if (!demux->dmx.frontend)
-               return -EINVAL;
-
-       mutex_lock(&dvb->lock);
-       dvb->nfeeds++;
-       rc = dvb->nfeeds;
-
-       if (dvb->nfeeds == 1) {
-               ret = start_streaming(dvb);
-               if (ret < 0)
-                       rc = ret;
-       }
-
-       mutex_unlock(&dvb->lock);
-       return rc;
-}
-
-static int stop_feed(struct dvb_demux_feed *feed)
-{
-       struct dvb_demux *demux = feed->demux;
-       struct cx231xx_dvb *dvb = demux->priv;
-       int err = 0;
-
-       mutex_lock(&dvb->lock);
-       dvb->nfeeds--;
-
-       if (0 == dvb->nfeeds)
-               err = stop_streaming(dvb);
-
-       mutex_unlock(&dvb->lock);
-       return err;
-}
-
-/* ------------------------------------------------------------------ */
-static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
-{
-       struct cx231xx *dev = fe->dvb->priv;
-
-       if (acquire)
-               return cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
-       else
-               return cx231xx_set_mode(dev, CX231XX_SUSPEND);
-}
-
-/* ------------------------------------------------------------------ */
-
-static struct xc5000_config cnxt_rde250_tunerconfig = {
-       .i2c_address = 0x61,
-       .if_khz = 4000,
-};
-static struct xc5000_config cnxt_rdu250_tunerconfig = {
-       .i2c_address = 0x61,
-       .if_khz = 3250,
-};
-
-/* ------------------------------------------------------------------ */
-#if 0
-static int attach_xc5000(u8 addr, struct cx231xx *dev)
-{
-
-       struct dvb_frontend *fe;
-       struct xc5000_config cfg;
-
-       memset(&cfg, 0, sizeof(cfg));
-       cfg.i2c_adap = &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap;
-       cfg.i2c_addr = addr;
-
-       if (!dev->dvb->frontend) {
-               printk(KERN_ERR "%s/2: dvb frontend not attached. "
-                      "Can't attach xc5000\n", dev->name);
-               return -EINVAL;
-       }
-
-       fe = dvb_attach(xc5000_attach, dev->dvb->frontend, &cfg);
-       if (!fe) {
-               printk(KERN_ERR "%s/2: xc5000 attach failed\n", dev->name);
-               dvb_frontend_detach(dev->dvb->frontend);
-               dev->dvb->frontend = NULL;
-               return -EINVAL;
-       }
-
-       printk(KERN_INFO "%s/2: xc5000 attached\n", dev->name);
-
-       return 0;
-}
-#endif
-
-int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq)
-{
-       int status = 0;
-
-       if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) {
-
-               struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops;
-
-               if (dops->set_analog_params != NULL) {
-                       struct analog_parameters params;
-
-                       params.frequency = freq;
-                       params.std = dev->norm;
-                       params.mode = 0;        /* 0- Air; 1 - cable */
-                       /*params.audmode = ;       */
-
-                       /* Set the analog parameters to set the frequency */
-                       dops->set_analog_params(dev->dvb->frontend, &params);
-               }
-
-       }
-
-       return status;
-}
-
-int cx231xx_reset_analog_tuner(struct cx231xx *dev)
-{
-       int status = 0;
-
-       if ((dev->dvb != NULL) && (dev->dvb->frontend != NULL)) {
-
-               struct dvb_tuner_ops *dops = &dev->dvb->frontend->ops.tuner_ops;
-
-               if (dops->init != NULL && !dev->xc_fw_load_done) {
-
-                       cx231xx_info("Reloading firmware for XC5000\n");
-                       status = dops->init(dev->dvb->frontend);
-                       if (status == 0) {
-                               dev->xc_fw_load_done = 1;
-                               cx231xx_info
-                                   ("XC5000 firmware download completed\n");
-                       } else {
-                               dev->xc_fw_load_done = 0;
-                               cx231xx_info
-                                   ("XC5000 firmware download failed !!!\n");
-                       }
-               }
-
-       }
-
-       return status;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int register_dvb(struct cx231xx_dvb *dvb,
-                       struct module *module,
-                       struct cx231xx *dev, struct device *device)
-{
-       int result;
-
-       mutex_init(&dvb->lock);
-
-       /* register adapter */
-       result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
-                                     adapter_nr);
-       if (result < 0) {
-               printk(KERN_WARNING
-                      "%s: dvb_register_adapter failed (errno = %d)\n",
-                      dev->name, result);
-               goto fail_adapter;
-       }
-
-       /* Ensure all frontends negotiate bus access */
-       dvb->frontend->ops.ts_bus_ctrl = cx231xx_dvb_bus_ctrl;
-
-       dvb->adapter.priv = dev;
-
-       /* register frontend */
-       result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
-       if (result < 0) {
-               printk(KERN_WARNING
-                      "%s: dvb_register_frontend failed (errno = %d)\n",
-                      dev->name, result);
-               goto fail_frontend;
-       }
-
-       /* register demux stuff */
-       dvb->demux.dmx.capabilities =
-           DMX_TS_FILTERING | DMX_SECTION_FILTERING |
-           DMX_MEMORY_BASED_FILTERING;
-       dvb->demux.priv = dvb;
-       dvb->demux.filternum = 256;
-       dvb->demux.feednum = 256;
-       dvb->demux.start_feed = start_feed;
-       dvb->demux.stop_feed = stop_feed;
-
-       result = dvb_dmx_init(&dvb->demux);
-       if (result < 0) {
-               printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
-                      dev->name, result);
-               goto fail_dmx;
-       }
-
-       dvb->dmxdev.filternum = 256;
-       dvb->dmxdev.demux = &dvb->demux.dmx;
-       dvb->dmxdev.capabilities = 0;
-       result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
-       if (result < 0) {
-               printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
-                      dev->name, result);
-               goto fail_dmxdev;
-       }
-
-       dvb->fe_hw.source = DMX_FRONTEND_0;
-       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
-       if (result < 0) {
-               printk(KERN_WARNING
-                      "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
-                      dev->name, result);
-               goto fail_fe_hw;
-       }
-
-       dvb->fe_mem.source = DMX_MEMORY_FE;
-       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
-       if (result < 0) {
-               printk(KERN_WARNING
-                      "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
-                      dev->name, result);
-               goto fail_fe_mem;
-       }
-
-       result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
-       if (result < 0) {
-               printk(KERN_WARNING
-                      "%s: connect_frontend failed (errno = %d)\n", dev->name,
-                      result);
-               goto fail_fe_conn;
-       }
-
-       /* register network adapter */
-       dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
-       return 0;
-
-fail_fe_conn:
-       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
-fail_fe_mem:
-       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
-fail_fe_hw:
-       dvb_dmxdev_release(&dvb->dmxdev);
-fail_dmxdev:
-       dvb_dmx_release(&dvb->demux);
-fail_dmx:
-       dvb_unregister_frontend(dvb->frontend);
-fail_frontend:
-       dvb_frontend_detach(dvb->frontend);
-       dvb_unregister_adapter(&dvb->adapter);
-fail_adapter:
-       return result;
-}
-
-static void unregister_dvb(struct cx231xx_dvb *dvb)
-{
-       dvb_net_release(&dvb->net);
-       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
-       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
-       dvb_dmxdev_release(&dvb->dmxdev);
-       dvb_dmx_release(&dvb->demux);
-       dvb_unregister_frontend(dvb->frontend);
-       dvb_frontend_detach(dvb->frontend);
-       dvb_unregister_adapter(&dvb->adapter);
-}
-
-static int dvb_init(struct cx231xx *dev)
-{
-       int result = 0;
-       struct cx231xx_dvb *dvb;
-
-       if (!dev->board.has_dvb) {
-               /* This device does not support the extension */
-               return 0;
-       }
-
-       dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL);
-
-       if (dvb == NULL) {
-               printk(KERN_INFO "cx231xx_dvb: memory allocation failed\n");
-               return -ENOMEM;
-       }
-       dev->dvb = dvb;
-       dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq;
-       dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner;
-
-       mutex_lock(&dev->lock);
-       cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
-       cx231xx_demod_reset(dev);
-       /* init frontend */
-       switch (dev->model) {
-       case CX231XX_BOARD_CNXT_CARRAERA:
-       case CX231XX_BOARD_CNXT_RDE_250:
-
-               dev->dvb->frontend = dvb_attach(s5h1432_attach,
-                                       &dvico_s5h1432_config,
-                                       &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
-
-               if (dev->dvb->frontend == NULL) {
-                       printk(DRIVER_NAME
-                              ": Failed to attach s5h1432 front end\n");
-                       result = -EINVAL;
-                       goto out_free;
-               }
-
-               /* define general-purpose callback pointer */
-               dvb->frontend->callback = cx231xx_tuner_callback;
-
-               if (!dvb_attach(xc5000_attach, dev->dvb->frontend,
-                              &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
-                              &cnxt_rde250_tunerconfig)) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-
-               break;
-       case CX231XX_BOARD_CNXT_SHELBY:
-       case CX231XX_BOARD_CNXT_RDU_250:
-
-               dev->dvb->frontend = dvb_attach(s5h1411_attach,
-                                              &xc5000_s5h1411_config,
-                                              &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
-
-               if (dev->dvb->frontend == NULL) {
-                       printk(DRIVER_NAME
-                              ": Failed to attach s5h1411 front end\n");
-                       result = -EINVAL;
-                       goto out_free;
-               }
-
-               /* define general-purpose callback pointer */
-               dvb->frontend->callback = cx231xx_tuner_callback;
-
-               if (!dvb_attach(xc5000_attach, dev->dvb->frontend,
-                              &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
-                              &cnxt_rdu250_tunerconfig)) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               break;
-       case CX231XX_BOARD_CNXT_RDE_253S:
-
-               dev->dvb->frontend = dvb_attach(s5h1432_attach,
-                                       &dvico_s5h1432_config,
-                                       &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
-
-               if (dev->dvb->frontend == NULL) {
-                       printk(DRIVER_NAME
-                              ": Failed to attach s5h1432 front end\n");
-                       result = -EINVAL;
-                       goto out_free;
-               }
-
-               /* define general-purpose callback pointer */
-               dvb->frontend->callback = cx231xx_tuner_callback;
-
-               if (!dvb_attach(tda18271_attach, dev->dvb->frontend,
-                              0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
-                              &cnxt_rde253s_tunerconfig)) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               break;
-       case CX231XX_BOARD_CNXT_RDU_253S:
-
-               dev->dvb->frontend = dvb_attach(s5h1411_attach,
-                                              &tda18271_s5h1411_config,
-                                              &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
-
-               if (dev->dvb->frontend == NULL) {
-                       printk(DRIVER_NAME
-                              ": Failed to attach s5h1411 front end\n");
-                       result = -EINVAL;
-                       goto out_free;
-               }
-
-               /* define general-purpose callback pointer */
-               dvb->frontend->callback = cx231xx_tuner_callback;
-
-               if (!dvb_attach(tda18271_attach, dev->dvb->frontend,
-                              0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
-                              &cnxt_rde253s_tunerconfig)) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               break;
-       case CX231XX_BOARD_HAUPPAUGE_EXETER:
-
-               printk(KERN_INFO "%s: looking for tuner / demod on i2c bus: %d\n",
-                      __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap));
-
-               dev->dvb->frontend = dvb_attach(lgdt3305_attach,
-                                               &hcw_lgdt3305_config,
-                                               &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap);
-
-               if (dev->dvb->frontend == NULL) {
-                       printk(DRIVER_NAME
-                              ": Failed to attach LG3305 front end\n");
-                       result = -EINVAL;
-                       goto out_free;
-               }
-
-               /* define general-purpose callback pointer */
-               dvb->frontend->callback = cx231xx_tuner_callback;
-
-               dvb_attach(tda18271_attach, dev->dvb->frontend,
-                          0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
-                          &hcw_tda18271_config);
-               break;
-
-       case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
-       case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID:
-
-               printk(KERN_INFO "%s: looking for demod on i2c bus: %d\n",
-                      __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap));
-
-               dev->dvb->frontend = dvb_attach(mb86a20s_attach,
-                                               &pv_mb86a20s_config,
-                                               &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
-
-               if (dev->dvb->frontend == NULL) {
-                       printk(DRIVER_NAME
-                              ": Failed to attach mb86a20s demod\n");
-                       result = -EINVAL;
-                       goto out_free;
-               }
-
-               /* define general-purpose callback pointer */
-               dvb->frontend->callback = cx231xx_tuner_callback;
-
-               dvb_attach(tda18271_attach, dev->dvb->frontend,
-                          0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
-                          &pv_tda18271_config);
-               break;
-
-       default:
-               printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
-                      " isn't supported yet\n", dev->name);
-               break;
-       }
-       if (NULL == dvb->frontend) {
-               printk(KERN_ERR
-                      "%s/2: frontend initialization failed\n", dev->name);
-               result = -EINVAL;
-               goto out_free;
-       }
-
-       /* register everything */
-       result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
-
-       if (result < 0)
-               goto out_free;
-
-
-       printk(KERN_INFO "Successfully loaded cx231xx-dvb\n");
-
-ret:
-       cx231xx_set_mode(dev, CX231XX_SUSPEND);
-       mutex_unlock(&dev->lock);
-       return result;
-
-out_free:
-       kfree(dvb);
-       dev->dvb = NULL;
-       goto ret;
-}
-
-static int dvb_fini(struct cx231xx *dev)
-{
-       if (!dev->board.has_dvb) {
-               /* This device does not support the extension */
-               return 0;
-       }
-
-       if (dev->dvb) {
-               unregister_dvb(dev->dvb);
-               dev->dvb = NULL;
-       }
-
-       return 0;
-}
-
-static struct cx231xx_ops dvb_ops = {
-       .id = CX231XX_DVB,
-       .name = "Cx231xx dvb Extension",
-       .init = dvb_init,
-       .fini = dvb_fini,
-};
-
-static int __init cx231xx_dvb_register(void)
-{
-       return cx231xx_register_extension(&dvb_ops);
-}
-
-static void __exit cx231xx_dvb_unregister(void)
-{
-       cx231xx_unregister_extension(&dvb_ops);
-}
-
-module_init(cx231xx_dvb_register);
-module_exit(cx231xx_dvb_unregister);
diff --git a/drivers/media/video/cx231xx/cx231xx-i2c.c b/drivers/media/video/cx231xx/cx231xx-i2c.c
deleted file mode 100644 (file)
index 781feed..0000000
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
-   cx231xx-i2c.c - driver for Conexant Cx23100/101/102 USB video capture devices
-
-   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
-               Based on em28xx driver
-               Based on Cx23885 driver
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   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/module.h>
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/i2c.h>
-#include <media/v4l2-common.h>
-#include <media/tuner.h>
-
-#include "cx231xx.h"
-
-/* ----------------------------------------------------------- */
-
-static unsigned int i2c_scan;
-module_param(i2c_scan, int, 0444);
-MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
-
-static unsigned int i2c_debug;
-module_param(i2c_debug, int, 0644);
-MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
-
-#define dprintk1(lvl, fmt, args...)                    \
-do {                                                   \
-       if (i2c_debug >= lvl) {                         \
-               printk(fmt, ##args);                    \
-               }                                       \
-} while (0)
-
-#define dprintk2(lvl, fmt, args...)                    \
-do {                                                   \
-       if (i2c_debug >= lvl) {                         \
-               printk(KERN_DEBUG "%s at %s: " fmt,     \
-                      dev->name, __func__ , ##args);   \
-      }                                                \
-} while (0)
-
-static inline bool is_tuner(struct cx231xx *dev, struct cx231xx_i2c *bus,
-                       const struct i2c_msg *msg, int tuner_type)
-{
-       if (bus->nr != dev->board.tuner_i2c_master)
-               return false;
-
-       if (msg->addr != dev->board.tuner_addr)
-               return false;
-
-       if (dev->tuner_type != tuner_type)
-               return false;
-
-       return true;
-}
-
-/*
- * cx231xx_i2c_send_bytes()
- */
-int cx231xx_i2c_send_bytes(struct i2c_adapter *i2c_adap,
-                          const struct i2c_msg *msg)
-{
-       struct cx231xx_i2c *bus = i2c_adap->algo_data;
-       struct cx231xx *dev = bus->dev;
-       struct cx231xx_i2c_xfer_data req_data;
-       int status = 0;
-       u16 size = 0;
-       u8 loop = 0;
-       u8 saddr_len = 1;
-       u8 *buf_ptr = NULL;
-       u16 saddr = 0;
-       u8 need_gpio = 0;
-
-       if (is_tuner(dev, bus, msg, TUNER_XC5000)) {
-               size = msg->len;
-
-               if (size == 2) {        /* register write sub addr */
-                       /* Just writing sub address will cause problem
-                       * to XC5000. So ignore the request */
-                       return 0;
-               } else if (size == 4) { /* register write with sub addr */
-                       if (msg->len >= 2)
-                               saddr = msg->buf[0] << 8 | msg->buf[1];
-                       else if (msg->len == 1)
-                               saddr = msg->buf[0];
-
-                       switch (saddr) {
-                       case 0x0000:    /* start tuner calibration mode */
-                               need_gpio = 1;
-                               /* FW Loading is done */
-                               dev->xc_fw_load_done = 1;
-                               break;
-                       case 0x000D:    /* Set signal source */
-                       case 0x0001:    /* Set TV standard - Video */
-                       case 0x0002:    /* Set TV standard - Audio */
-                       case 0x0003:    /* Set RF Frequency */
-                               need_gpio = 1;
-                               break;
-                       default:
-                               if (dev->xc_fw_load_done)
-                                       need_gpio = 1;
-                               break;
-                       }
-
-                       if (need_gpio) {
-                               dprintk1(1,
-                               "GPIO WRITE: addr 0x%x, len %d, saddr 0x%x\n",
-                               msg->addr, msg->len, saddr);
-
-                               return dev->cx231xx_gpio_i2c_write(dev,
-                                                                  msg->addr,
-                                                                  msg->buf,
-                                                                  msg->len);
-                       }
-               }
-
-               /* special case for Xc5000 tuner case */
-               saddr_len = 1;
-
-               /* adjust the length to correct length */
-               size -= saddr_len;
-               buf_ptr = (u8 *) (msg->buf + 1);
-
-               do {
-                       /* prepare xfer_data struct */
-                       req_data.dev_addr = msg->addr;
-                       req_data.direction = msg->flags;
-                       req_data.saddr_len = saddr_len;
-                       req_data.saddr_dat = msg->buf[0];
-                       req_data.buf_size = size > 16 ? 16 : size;
-                       req_data.p_buffer = (u8 *) (buf_ptr + loop * 16);
-
-                       bus->i2c_nostop = (size > 16) ? 1 : 0;
-                       bus->i2c_reserve = (loop == 0) ? 0 : 1;
-
-                       /* usb send command */
-                       status = dev->cx231xx_send_usb_command(bus, &req_data);
-                       loop++;
-
-                       if (size >= 16)
-                               size -= 16;
-                       else
-                               size = 0;
-
-               } while (size > 0);
-
-               bus->i2c_nostop = 0;
-               bus->i2c_reserve = 0;
-
-       } else {                /* regular case */
-
-               /* prepare xfer_data struct */
-               req_data.dev_addr = msg->addr;
-               req_data.direction = msg->flags;
-               req_data.saddr_len = 0;
-               req_data.saddr_dat = 0;
-               req_data.buf_size = msg->len;
-               req_data.p_buffer = msg->buf;
-
-               /* usb send command */
-               status = dev->cx231xx_send_usb_command(bus, &req_data);
-       }
-
-       return status < 0 ? status : 0;
-}
-
-/*
- * cx231xx_i2c_recv_bytes()
- * read a byte from the i2c device
- */
-static int cx231xx_i2c_recv_bytes(struct i2c_adapter *i2c_adap,
-                                 const struct i2c_msg *msg)
-{
-       struct cx231xx_i2c *bus = i2c_adap->algo_data;
-       struct cx231xx *dev = bus->dev;
-       struct cx231xx_i2c_xfer_data req_data;
-       int status = 0;
-       u16 saddr = 0;
-       u8 need_gpio = 0;
-
-       if (is_tuner(dev, bus, msg, TUNER_XC5000)) {
-               if (msg->len == 2)
-                       saddr = msg->buf[0] << 8 | msg->buf[1];
-               else if (msg->len == 1)
-                       saddr = msg->buf[0];
-
-               if (dev->xc_fw_load_done) {
-
-                       switch (saddr) {
-                       case 0x0009:    /* BUSY check */
-                               dprintk1(1,
-                               "GPIO R E A D: Special case BUSY check \n");
-                               /*Try read BUSY register, just set it to zero*/
-                               msg->buf[0] = 0;
-                               if (msg->len == 2)
-                                       msg->buf[1] = 0;
-                               return 0;
-                       case 0x0004:    /* read Lock status */
-                               need_gpio = 1;
-                               break;
-
-                       }
-
-                       if (need_gpio) {
-                               /* this is a special case to handle Xceive tuner
-                               clock stretch issue with gpio based I2C */
-
-                               dprintk1(1,
-                               "GPIO R E A D: addr 0x%x, len %d, saddr 0x%x\n",
-                               msg->addr, msg->len,
-                               msg->buf[0] << 8 | msg->buf[1]);
-
-                               status =
-                                   dev->cx231xx_gpio_i2c_write(dev, msg->addr,
-                                                               msg->buf,
-                                                               msg->len);
-                               status =
-                                   dev->cx231xx_gpio_i2c_read(dev, msg->addr,
-                                                              msg->buf,
-                                                              msg->len);
-                               return status;
-                       }
-               }
-
-               /* prepare xfer_data struct */
-               req_data.dev_addr = msg->addr;
-               req_data.direction = msg->flags;
-               req_data.saddr_len = msg->len;
-               req_data.saddr_dat = msg->buf[0] << 8 | msg->buf[1];
-               req_data.buf_size = msg->len;
-               req_data.p_buffer = msg->buf;
-
-               /* usb send command */
-               status = dev->cx231xx_send_usb_command(bus, &req_data);
-
-       } else {
-
-               /* prepare xfer_data struct */
-               req_data.dev_addr = msg->addr;
-               req_data.direction = msg->flags;
-               req_data.saddr_len = 0;
-               req_data.saddr_dat = 0;
-               req_data.buf_size = msg->len;
-               req_data.p_buffer = msg->buf;
-
-               /* usb send command */
-               status = dev->cx231xx_send_usb_command(bus, &req_data);
-       }
-
-       return status < 0 ? status : 0;
-}
-
-/*
- * cx231xx_i2c_recv_bytes_with_saddr()
- * read a byte from the i2c device
- */
-static int cx231xx_i2c_recv_bytes_with_saddr(struct i2c_adapter *i2c_adap,
-                                            const struct i2c_msg *msg1,
-                                            const struct i2c_msg *msg2)
-{
-       struct cx231xx_i2c *bus = i2c_adap->algo_data;
-       struct cx231xx *dev = bus->dev;
-       struct cx231xx_i2c_xfer_data req_data;
-       int status = 0;
-       u16 saddr = 0;
-       u8 need_gpio = 0;
-
-       if (msg1->len == 2)
-               saddr = msg1->buf[0] << 8 | msg1->buf[1];
-       else if (msg1->len == 1)
-               saddr = msg1->buf[0];
-
-       if (is_tuner(dev, bus, msg2, TUNER_XC5000)) {
-               if ((msg2->len < 16)) {
-
-                       dprintk1(1,
-                       "i2c_read: addr 0x%x, len %d, saddr 0x%x, len %d\n",
-                       msg2->addr, msg2->len, saddr, msg1->len);
-
-                       switch (saddr) {
-                       case 0x0008:    /* read FW load status */
-                               need_gpio = 1;
-                               break;
-                       case 0x0004:    /* read Lock status */
-                               need_gpio = 1;
-                               break;
-                       }
-
-                       if (need_gpio) {
-                               status =
-                                   dev->cx231xx_gpio_i2c_write(dev, msg1->addr,
-                                                               msg1->buf,
-                                                               msg1->len);
-                               status =
-                                   dev->cx231xx_gpio_i2c_read(dev, msg2->addr,
-                                                              msg2->buf,
-                                                              msg2->len);
-                               return status;
-                       }
-               }
-       }
-
-       /* prepare xfer_data struct */
-       req_data.dev_addr = msg2->addr;
-       req_data.direction = msg2->flags;
-       req_data.saddr_len = msg1->len;
-       req_data.saddr_dat = saddr;
-       req_data.buf_size = msg2->len;
-       req_data.p_buffer = msg2->buf;
-
-       /* usb send command */
-       status = dev->cx231xx_send_usb_command(bus, &req_data);
-
-       return status < 0 ? status : 0;
-}
-
-/*
- * cx231xx_i2c_check_for_device()
- * check if there is a i2c_device at the supplied address
- */
-static int cx231xx_i2c_check_for_device(struct i2c_adapter *i2c_adap,
-                                       const struct i2c_msg *msg)
-{
-       struct cx231xx_i2c *bus = i2c_adap->algo_data;
-       struct cx231xx *dev = bus->dev;
-       struct cx231xx_i2c_xfer_data req_data;
-       int status = 0;
-
-       /* prepare xfer_data struct */
-       req_data.dev_addr = msg->addr;
-       req_data.direction = msg->flags;
-       req_data.saddr_len = 0;
-       req_data.saddr_dat = 0;
-       req_data.buf_size = 0;
-       req_data.p_buffer = NULL;
-
-       /* usb send command */
-       status = dev->cx231xx_send_usb_command(bus, &req_data);
-
-       return status < 0 ? status : 0;
-}
-
-/*
- * cx231xx_i2c_xfer()
- * the main i2c transfer function
- */
-static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap,
-                           struct i2c_msg msgs[], int num)
-{
-       struct cx231xx_i2c *bus = i2c_adap->algo_data;
-       struct cx231xx *dev = bus->dev;
-       int addr, rc, i, byte;
-
-       if (num <= 0)
-               return 0;
-       mutex_lock(&dev->i2c_lock);
-       for (i = 0; i < num; i++) {
-
-               addr = msgs[i].addr >> 1;
-
-               dprintk2(2, "%s %s addr=%x len=%d:",
-                        (msgs[i].flags & I2C_M_RD) ? "read" : "write",
-                        i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
-               if (!msgs[i].len) {
-                       /* no len: check only for device presence */
-                       rc = cx231xx_i2c_check_for_device(i2c_adap, &msgs[i]);
-                       if (rc < 0) {
-                               dprintk2(2, " no device\n");
-                               mutex_unlock(&dev->i2c_lock);
-                               return rc;
-                       }
-
-               } else if (msgs[i].flags & I2C_M_RD) {
-                       /* read bytes */
-                       rc = cx231xx_i2c_recv_bytes(i2c_adap, &msgs[i]);
-                       if (i2c_debug >= 2) {
-                               for (byte = 0; byte < msgs[i].len; byte++)
-                                       printk(" %02x", msgs[i].buf[byte]);
-                       }
-               } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
-                          msgs[i].addr == msgs[i + 1].addr
-                          && (msgs[i].len <= 2) && (bus->nr < 3)) {
-                       /* read bytes */
-                       rc = cx231xx_i2c_recv_bytes_with_saddr(i2c_adap,
-                                                              &msgs[i],
-                                                              &msgs[i + 1]);
-                       if (i2c_debug >= 2) {
-                               for (byte = 0; byte < msgs[i].len; byte++)
-                                       printk(" %02x", msgs[i].buf[byte]);
-                       }
-                       i++;
-               } else {
-                       /* write bytes */
-                       if (i2c_debug >= 2) {
-                               for (byte = 0; byte < msgs[i].len; byte++)
-                                       printk(" %02x", msgs[i].buf[byte]);
-                       }
-                       rc = cx231xx_i2c_send_bytes(i2c_adap, &msgs[i]);
-               }
-               if (rc < 0)
-                       goto err;
-               if (i2c_debug >= 2)
-                       printk("\n");
-       }
-       mutex_unlock(&dev->i2c_lock);
-       return num;
-err:
-       dprintk2(2, " ERROR: %i\n", rc);
-       mutex_unlock(&dev->i2c_lock);
-       return rc;
-}
-
-/* ----------------------------------------------------------- */
-
-/*
- * functionality()
- */
-static u32 functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm cx231xx_algo = {
-       .master_xfer = cx231xx_i2c_xfer,
-       .functionality = functionality,
-};
-
-static struct i2c_adapter cx231xx_adap_template = {
-       .owner = THIS_MODULE,
-       .name = "cx231xx",
-       .algo = &cx231xx_algo,
-};
-
-static struct i2c_client cx231xx_client_template = {
-       .name = "cx231xx internal",
-};
-
-/* ----------------------------------------------------------- */
-
-/*
- * i2c_devs
- * incomplete list of known devices
- */
-static char *i2c_devs[128] = {
-       [0x60 >> 1] = "colibri",
-       [0x88 >> 1] = "hammerhead",
-       [0x8e >> 1] = "CIR",
-       [0x32 >> 1] = "GeminiIII",
-       [0x02 >> 1] = "Aquarius",
-       [0xa0 >> 1] = "eeprom",
-       [0xc0 >> 1] = "tuner",
-       [0xc2 >> 1] = "tuner",
-};
-
-/*
- * cx231xx_do_i2c_scan()
- * check i2c address range for devices
- */
-void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c)
-{
-       unsigned char buf;
-       int i, rc;
-
-       cx231xx_info(": Checking for I2C devices ..\n");
-       for (i = 0; i < 128; i++) {
-               c->addr = i;
-               rc = i2c_master_recv(c, &buf, 0);
-               if (rc < 0)
-                       continue;
-               cx231xx_info("%s: i2c scan: found device @ 0x%x  [%s]\n",
-                            dev->name, i << 1,
-                            i2c_devs[i] ? i2c_devs[i] : "???");
-       }
-       cx231xx_info(": Completed Checking for I2C devices.\n");
-}
-
-/*
- * cx231xx_i2c_register()
- * register i2c bus
- */
-int cx231xx_i2c_register(struct cx231xx_i2c *bus)
-{
-       struct cx231xx *dev = bus->dev;
-
-       BUG_ON(!dev->cx231xx_send_usb_command);
-
-       bus->i2c_adap = cx231xx_adap_template;
-       bus->i2c_client = cx231xx_client_template;
-       bus->i2c_adap.dev.parent = &dev->udev->dev;
-
-       strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
-
-       bus->i2c_adap.algo_data = bus;
-       i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
-       i2c_add_adapter(&bus->i2c_adap);
-
-       bus->i2c_client.adapter = &bus->i2c_adap;
-
-       if (0 == bus->i2c_rc) {
-               if (i2c_scan)
-                       cx231xx_do_i2c_scan(dev, &bus->i2c_client);
-       } else
-               cx231xx_warn("%s: i2c bus %d register FAILED\n",
-                            dev->name, bus->nr);
-
-       return bus->i2c_rc;
-}
-
-/*
- * cx231xx_i2c_unregister()
- * unregister i2c_bus
- */
-int cx231xx_i2c_unregister(struct cx231xx_i2c *bus)
-{
-       i2c_del_adapter(&bus->i2c_adap);
-       return 0;
-}
diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c
deleted file mode 100644 (file)
index 96176e9..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- *   cx231xx IR glue driver
- *
- *   Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- *   Polaris (cx231xx) has its support for IR's with a design close to MCE.
- *   however, a few designs are using an external I2C chip for IR, instead
- *   of using the one provided by the chip.
- *   This driver provides support for those extra devices
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License as
- *   published by the Free Software Foundation version 2.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   General Public License for more details.
- */
-
-#include "cx231xx.h"
-#include <linux/usb.h>
-#include <linux/slab.h>
-
-#define MODULE_NAME "cx231xx-input"
-
-static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key,
-                        u32 *ir_raw)
-{
-       int     rc;
-       u8      cmd, scancode;
-
-       dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__);
-
-               /* poll IR chip */
-       rc = i2c_master_recv(ir->c, &cmd, 1);
-       if (rc < 0)
-               return rc;
-       if (rc != 1)
-               return -EIO;
-
-       /* it seems that 0xFE indicates that a button is still hold
-          down, while 0xff indicates that no button is hold
-          down. 0xfe sequences are sometimes interrupted by 0xFF */
-
-       if (cmd == 0xff)
-               return 0;
-
-       scancode =
-                ((cmd & 0x01) ? 0x80 : 0) |
-                ((cmd & 0x02) ? 0x40 : 0) |
-                ((cmd & 0x04) ? 0x20 : 0) |
-                ((cmd & 0x08) ? 0x10 : 0) |
-                ((cmd & 0x10) ? 0x08 : 0) |
-                ((cmd & 0x20) ? 0x04 : 0) |
-                ((cmd & 0x40) ? 0x02 : 0) |
-                ((cmd & 0x80) ? 0x01 : 0);
-
-       dev_dbg(&ir->rc->input_dev->dev, "cmd %02x, scan = %02x\n",
-               cmd, scancode);
-
-       *ir_key = scancode;
-       *ir_raw = scancode;
-       return 1;
-}
-
-int cx231xx_ir_init(struct cx231xx *dev)
-{
-       struct i2c_board_info info;
-       u8 ir_i2c_bus;
-
-       dev_dbg(&dev->udev->dev, "%s\n", __func__);
-
-       /* Only initialize if a rc keycode map is defined */
-       if (!cx231xx_boards[dev->model].rc_map_name)
-               return -ENODEV;
-
-       request_module("ir-kbd-i2c");
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       memset(&dev->init_data, 0, sizeof(dev->init_data));
-       dev->init_data.rc_dev = rc_allocate_device();
-       if (!dev->init_data.rc_dev)
-               return -ENOMEM;
-
-       dev->init_data.name = cx231xx_boards[dev->model].name;
-
-       strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
-       info.platform_data = &dev->init_data;
-
-       /*
-        * Board-dependent values
-        *
-        * For now, there's just one type of hardware design using
-        * an i2c device.
-        */
-       dev->init_data.get_key = get_key_isdbt;
-       dev->init_data.ir_codes = cx231xx_boards[dev->model].rc_map_name;
-       /* The i2c micro-controller only outputs the cmd part of NEC protocol */
-       dev->init_data.rc_dev->scanmask = 0xff;
-       dev->init_data.rc_dev->driver_name = "cx231xx";
-       dev->init_data.type = RC_TYPE_NEC;
-       info.addr = 0x30;
-
-       /* Load and bind ir-kbd-i2c */
-       ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master;
-       dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n",
-               ir_i2c_bus, info.addr);
-       dev->ir_i2c_client = i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info);
-
-       return 0;
-}
-
-void cx231xx_ir_exit(struct cx231xx *dev)
-{
-       if (dev->ir_i2c_client)
-               i2c_unregister_device(dev->ir_i2c_client);
-       dev->ir_i2c_client = NULL;
-}
diff --git a/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c b/drivers/media/video/cx231xx/cx231xx-pcb-cfg.c
deleted file mode 100644 (file)
index 7473c33..0000000
+++ /dev/null
@@ -1,795 +0,0 @@
-/*
-   cx231xx-pcb-config.c - driver for Conexant
-               Cx23100/101/102 USB video capture devices
-
-   Copyright (C) 2008 <srinivasa.deevi at conexant dot 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.
-
-   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 "cx231xx.h"
-#include "cx231xx-conf-reg.h"
-
-static unsigned int pcb_debug;
-module_param(pcb_debug, int, 0644);
-MODULE_PARM_DESC(pcb_debug, "enable pcb config debug messages [video]");
-
-/******************************************************************************/
-
-struct pcb_config cx231xx_Scenario[] = {
-       {
-        INDEX_SELFPOWER_DIGITAL_ONLY,  /* index */
-        USB_SELF_POWER,        /* power_type */
-        0,                     /* speed , not decide yet */
-        MOD_DIGITAL,           /* mode */
-        SOURCE_TS_BDA,         /* ts1_source, digital tv only */
-        NOT_SUPPORTED,         /* ts2_source  */
-        NOT_SUPPORTED,         /* analog source */
-
-        0,                     /* digital_index  */
-        0,                     /* analog index */
-        0,                     /* dif_index   */
-        0,                     /* external_index */
-
-        1,                     /* only one configuration */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           1,                  /* ts1 index */
-           NOT_SUPPORTED,      /* TS2 index */
-           NOT_SUPPORTED,      /* AUDIO */
-           NOT_SUPPORTED,      /* VIDEO */
-           NOT_SUPPORTED,      /* VANC */
-           NOT_SUPPORTED,      /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          ,
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        ,
-        /* full-speed config */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           1,                  /* ts1 index */
-           NOT_SUPPORTED,      /* TS2 index */
-           NOT_SUPPORTED,      /* AUDIO */
-           NOT_SUPPORTED,      /* VIDEO */
-           NOT_SUPPORTED,      /* VANC */
-           NOT_SUPPORTED,      /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        }
-       ,
-
-       {
-        INDEX_SELFPOWER_DUAL_DIGITAL,  /* index */
-        USB_SELF_POWER,        /* power_type */
-        0,                     /* speed , not decide yet */
-        MOD_DIGITAL,           /* mode */
-        SOURCE_TS_BDA,         /* ts1_source, digital tv only */
-        0,                     /* ts2_source,need update from register */
-        NOT_SUPPORTED,         /* analog source */
-        0,                     /* digital_index  */
-        0,                     /* analog index */
-        0,                     /* dif_index */
-        0,                     /* external_index */
-
-        1,                     /* only one configuration */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           1,                  /* ts1 index */
-           2,                  /* TS2 index */
-           NOT_SUPPORTED,      /* AUDIO */
-           NOT_SUPPORTED,      /* VIDEO */
-           NOT_SUPPORTED,      /* VANC */
-           NOT_SUPPORTED,      /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        ,
-        /* full-speed */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           1,                  /* ts1 index */
-           2,                  /* TS2 index */
-           NOT_SUPPORTED,      /* AUDIO */
-           NOT_SUPPORTED,      /* VIDEO */
-           NOT_SUPPORTED,      /* VANC */
-           NOT_SUPPORTED,      /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        }
-       ,
-
-       {
-        INDEX_SELFPOWER_ANALOG_ONLY,   /* index */
-        USB_SELF_POWER,        /* power_type */
-        0,                     /* speed , not decide yet */
-        MOD_ANALOG | MOD_DIF | MOD_EXTERNAL,   /* mode ,analog tv only */
-        NOT_SUPPORTED,         /* ts1_source, NOT SUPPORT */
-        NOT_SUPPORTED,         /* ts2_source,NOT SUPPORT */
-        0,                     /* analog source, need update */
-
-        0,                     /* digital_index  */
-        0,                     /* analog index */
-        0,                     /* dif_index */
-        0,                     /* external_index */
-
-        1,                     /* only one configuration */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           NOT_SUPPORTED,      /* ts1 index */
-           NOT_SUPPORTED,      /* TS2 index */
-           1,                  /* AUDIO */
-           2,                  /* VIDEO */
-           3,                  /* VANC */
-           4,                  /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        ,
-        /* full-speed */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           NOT_SUPPORTED,      /* ts1 index */
-           NOT_SUPPORTED,      /* TS2 index */
-           1,                  /* AUDIO */
-           2,                  /* VIDEO */
-           NOT_SUPPORTED,      /* VANC */
-           NOT_SUPPORTED,      /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        }
-       ,
-
-       {
-        INDEX_SELFPOWER_DUAL,  /* index */
-        USB_SELF_POWER,        /* power_type */
-        0,                     /* speed , not decide yet */
-        /* mode ,analog tv and digital path */
-        MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL,
-        0,                     /* ts1_source,will update in register */
-        NOT_SUPPORTED,         /* ts2_source,NOT SUPPORT */
-        0,                     /* analog source need update */
-        0,                     /* digital_index  */
-        0,                     /* analog index */
-        0,                     /* dif_index */
-        0,                     /* external_index */
-        1,                     /* only one configuration */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           1,                  /* ts1 index */
-           NOT_SUPPORTED,      /* TS2 index */
-           2,                  /* AUDIO */
-           3,                  /* VIDEO */
-           4,                  /* VANC */
-           5,                  /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        ,
-        /* full-speed */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           1,                  /* ts1 index */
-           NOT_SUPPORTED,      /* TS2 index */
-           2,                  /* AUDIO */
-           3,                  /* VIDEO */
-           NOT_SUPPORTED,      /* VANC */
-           NOT_SUPPORTED,      /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        }
-       ,
-
-       {
-        INDEX_SELFPOWER_TRIPLE,        /* index */
-        USB_SELF_POWER,        /* power_type */
-        0,                     /* speed , not decide yet */
-        /* mode ,analog tv and digital path */
-        MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL,
-        0,                     /* ts1_source, update in register */
-        0,                     /* ts2_source,update in register */
-        0,                     /* analog source, need update */
-
-        0,                     /* digital_index  */
-        0,                     /* analog index */
-        0,                     /* dif_index */
-        0,                     /* external_index */
-        1,                     /* only one configuration */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           1,                  /* ts1 index */
-           2,                  /* TS2 index */
-           3,                  /* AUDIO */
-           4,                  /* VIDEO */
-           5,                  /* VANC */
-           6,                  /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        ,
-        /* full-speed */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           1,                  /* ts1 index */
-           2,                  /* TS2 index */
-           3,                  /* AUDIO */
-           4,                  /* VIDEO */
-           NOT_SUPPORTED,      /* VANC */
-           NOT_SUPPORTED,      /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        }
-       ,
-
-       {
-        INDEX_SELFPOWER_COMPRESSOR,    /* index */
-        USB_SELF_POWER,        /* power_type */
-        0,                     /* speed , not decide yet */
-        /* mode ,analog tv AND DIGITAL path */
-        MOD_ANALOG | MOD_DIF | MOD_DIGITAL | MOD_EXTERNAL,
-        NOT_SUPPORTED,         /* ts1_source, disable */
-        SOURCE_TS_BDA,         /* ts2_source */
-        0,                     /* analog source,need update */
-        0,                     /* digital_index  */
-        0,                     /* analog index */
-        0,                     /* dif_index */
-        0,                     /* external_index */
-        1,                     /* only one configuration */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           NOT_SUPPORTED,      /* ts1 index */
-           1,                  /* TS2 index */
-           2,                  /* AUDIO */
-           3,                  /* VIDEO */
-           4,                  /* VANC */
-           5,                  /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        ,
-        /* full-speed  */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           NOT_SUPPORTED,      /* ts1 index */
-           1,                  /* TS2 index */
-           2,                  /* AUDIO */
-           3,                  /* VIDEO */
-           NOT_SUPPORTED,      /* VANC */
-           NOT_SUPPORTED,      /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        }
-       ,
-
-       {
-        INDEX_BUSPOWER_DIGITAL_ONLY,   /* index */
-        USB_BUS_POWER,         /* power_type */
-        0,                     /* speed , not decide yet */
-        MOD_DIGITAL,           /* mode ,analog tv AND DIGITAL path */
-        SOURCE_TS_BDA,         /* ts1_source, disable */
-        NOT_SUPPORTED,         /* ts2_source */
-        NOT_SUPPORTED,         /* analog source */
-
-        0,                     /* digital_index  */
-        0,                     /* analog index */
-        0,                     /* dif_index */
-        0,                     /* external_index */
-
-        1,                     /* only one configuration */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index  = 2 */
-           1,                  /* ts1 index */
-           NOT_SUPPORTED,      /* TS2 index */
-           NOT_SUPPORTED,      /* AUDIO */
-           NOT_SUPPORTED,      /* VIDEO */
-           NOT_SUPPORTED,      /* VANC */
-           NOT_SUPPORTED,      /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        ,
-        /* full-speed */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index  = 2 */
-           1,                  /* ts1 index */
-           NOT_SUPPORTED,      /* TS2 index */
-           NOT_SUPPORTED,      /* AUDIO */
-           NOT_SUPPORTED,      /* VIDEO */
-           NOT_SUPPORTED,      /* VANC */
-           NOT_SUPPORTED,      /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        }
-       ,
-       {
-        INDEX_BUSPOWER_ANALOG_ONLY,    /* index */
-        USB_BUS_POWER,         /* power_type */
-        0,                     /* speed , not decide yet */
-        MOD_ANALOG,            /* mode ,analog tv AND DIGITAL path */
-        NOT_SUPPORTED,         /* ts1_source, disable */
-        NOT_SUPPORTED,         /* ts2_source */
-        SOURCE_ANALOG,         /* analog source--analog */
-        0,                     /* digital_index  */
-        0,                     /* analog index */
-        0,                     /* dif_index */
-        0,                     /* external_index */
-        1,                     /* only one configuration */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           NOT_SUPPORTED,      /* ts1 index */
-           NOT_SUPPORTED,      /* TS2 index */
-           1,                  /* AUDIO */
-           2,                  /* VIDEO */
-           3,                  /* VANC */
-           4,                  /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        ,
-        {                      /* full-speed */
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           NOT_SUPPORTED,      /* ts1 index */
-           NOT_SUPPORTED,      /* TS2 index */
-           1,                  /* AUDIO */
-           2,                  /* VIDEO */
-           NOT_SUPPORTED,      /* VANC */
-           NOT_SUPPORTED,      /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        }
-       ,
-       {
-        INDEX_BUSPOWER_DIF_ONLY,       /* index */
-        USB_BUS_POWER,         /* power_type */
-        0,                     /* speed , not decide yet */
-        /* mode ,analog tv AND DIGITAL path */
-        MOD_DIF | MOD_ANALOG | MOD_DIGITAL | MOD_EXTERNAL,
-        SOURCE_TS_BDA,         /* ts1_source, disable */
-        NOT_SUPPORTED,         /* ts2_source */
-        SOURCE_DIF | SOURCE_ANALOG | SOURCE_EXTERNAL,  /* analog source, dif */
-        0,                     /* digital_index  */
-        0,                     /* analog index */
-        0,                     /* dif_index */
-        0,                     /* external_index */
-        1,                     /* only one configuration */
-        {
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           1,                  /* ts1 index */
-           NOT_SUPPORTED,      /* TS2 index */
-           2,                  /* AUDIO */
-           3,                  /* VIDEO */
-           4,                  /* VANC */
-           5,                  /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        ,
-        {                      /* full speed */
-         {
-          0,                   /* config index */
-          {
-           0,                  /* interrupt ep index */
-           1,                  /* ts1 index */
-           NOT_SUPPORTED,      /* TS2 index */
-           2,                  /* AUDIO */
-           3,                  /* VIDEO */
-           NOT_SUPPORTED,      /* VANC */
-           NOT_SUPPORTED,      /* HANC */
-           NOT_SUPPORTED       /* ir_index */
-           }
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         ,
-         {NOT_SUPPORTED, {NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED, NOT_SUPPORTED, NOT_SUPPORTED,
-                          NOT_SUPPORTED}
-          }
-         }
-        }
-       ,
-
-};
-
-/*****************************************************************/
-
-u32 initialize_cx231xx(struct cx231xx *dev)
-{
-       u32 config_info = 0;
-       struct pcb_config *p_pcb_info;
-       u8 usb_speed = 1;       /* from register,1--HS, 0--FS  */
-       u8 data[4] = { 0, 0, 0, 0 };
-       u32 ts1_source = 0;
-       u32 ts2_source = 0;
-       u32 analog_source = 0;
-       u8 _current_scenario_idx = 0xff;
-
-       ts1_source = SOURCE_TS_BDA;
-       ts2_source = SOURCE_TS_BDA;
-
-       /* read board config register to find out which
-       pcb config it is related to */
-       cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT, data, 4);
-
-       config_info = *((u32 *) data);
-       usb_speed = (u8) (config_info & 0x1);
-
-       /* Verify this device belongs to Bus power or Self power device */
-       if (config_info & BUS_POWER) {  /* bus-power */
-               switch (config_info & BUSPOWER_MASK) {
-               case TS1_PORT | BUS_POWER:
-                       cx231xx_Scenario[INDEX_BUSPOWER_DIGITAL_ONLY].speed =
-                           usb_speed;
-                       p_pcb_info =
-                           &cx231xx_Scenario[INDEX_BUSPOWER_DIGITAL_ONLY];
-                       _current_scenario_idx = INDEX_BUSPOWER_DIGITAL_ONLY;
-                       break;
-               case AVDEC_ENABLE | BUS_POWER:
-                       cx231xx_Scenario[INDEX_BUSPOWER_ANALOG_ONLY].speed =
-                           usb_speed;
-                       p_pcb_info =
-                           &cx231xx_Scenario[INDEX_BUSPOWER_ANALOG_ONLY];
-                       _current_scenario_idx = INDEX_BUSPOWER_ANALOG_ONLY;
-                       break;
-               case AVDEC_ENABLE | BUS_POWER | TS1_PORT:
-                       cx231xx_Scenario[INDEX_BUSPOWER_DIF_ONLY].speed =
-                           usb_speed;
-                       p_pcb_info = &cx231xx_Scenario[INDEX_BUSPOWER_DIF_ONLY];
-                       _current_scenario_idx = INDEX_BUSPOWER_DIF_ONLY;
-                       break;
-               default:
-                       cx231xx_info("bad config in buspower!!!!\n");
-                       cx231xx_info("config_info=%x\n",
-                                    (config_info & BUSPOWER_MASK));
-                       return 1;
-               }
-       } else {                /* self-power */
-
-               switch (config_info & SELFPOWER_MASK) {
-               case TS1_PORT | SELF_POWER:
-                       cx231xx_Scenario[INDEX_SELFPOWER_DIGITAL_ONLY].speed =
-                           usb_speed;
-                       p_pcb_info =
-                           &cx231xx_Scenario[INDEX_SELFPOWER_DIGITAL_ONLY];
-                       _current_scenario_idx = INDEX_SELFPOWER_DIGITAL_ONLY;
-                       break;
-               case TS1_TS2_PORT | SELF_POWER:
-                       cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL].speed =
-                           usb_speed;
-                       cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL].
-                           ts2_source = ts2_source;
-                       p_pcb_info =
-                           &cx231xx_Scenario[INDEX_SELFPOWER_DUAL_DIGITAL];
-                       _current_scenario_idx = INDEX_SELFPOWER_DUAL_DIGITAL;
-                       break;
-               case AVDEC_ENABLE | SELF_POWER:
-                       cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY].speed =
-                           usb_speed;
-                       cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY].
-                           analog_source = analog_source;
-                       p_pcb_info =
-                           &cx231xx_Scenario[INDEX_SELFPOWER_ANALOG_ONLY];
-                       _current_scenario_idx = INDEX_SELFPOWER_ANALOG_ONLY;
-                       break;
-               case AVDEC_ENABLE | TS1_PORT | SELF_POWER:
-                       cx231xx_Scenario[INDEX_SELFPOWER_DUAL].speed =
-                           usb_speed;
-                       cx231xx_Scenario[INDEX_SELFPOWER_DUAL].ts1_source =
-                           ts1_source;
-                       cx231xx_Scenario[INDEX_SELFPOWER_DUAL].analog_source =
-                           analog_source;
-                       p_pcb_info = &cx231xx_Scenario[INDEX_SELFPOWER_DUAL];
-                       _current_scenario_idx = INDEX_SELFPOWER_DUAL;
-                       break;
-               case AVDEC_ENABLE | TS1_TS2_PORT | SELF_POWER:
-                       cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].speed =
-                           usb_speed;
-                       cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].ts1_source =
-                           ts1_source;
-                       cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].ts2_source =
-                           ts2_source;
-                       cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE].analog_source =
-                           analog_source;
-                       p_pcb_info = &cx231xx_Scenario[INDEX_SELFPOWER_TRIPLE];
-                       _current_scenario_idx = INDEX_SELFPOWER_TRIPLE;
-                       break;
-               case AVDEC_ENABLE | TS1VIP_TS2_PORT | SELF_POWER:
-                       cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR].speed =
-                           usb_speed;
-                       cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR].
-                           analog_source = analog_source;
-                       p_pcb_info =
-                           &cx231xx_Scenario[INDEX_SELFPOWER_COMPRESSOR];
-                       _current_scenario_idx = INDEX_SELFPOWER_COMPRESSOR;
-                       break;
-               default:
-                       cx231xx_info("bad senario!!!!!\n");
-                       cx231xx_info("config_info=%x\n",
-                                    (config_info & SELFPOWER_MASK));
-                       return 1;
-               }
-       }
-
-       dev->current_scenario_idx = _current_scenario_idx;
-
-       memcpy(&dev->current_pcb_config, p_pcb_info,
-                  sizeof(struct pcb_config));
-
-       if (pcb_debug) {
-               cx231xx_info("SC(0x00) register = 0x%x\n", config_info);
-               cx231xx_info("scenario %d\n",
-                           (dev->current_pcb_config.index) + 1);
-               cx231xx_info("type=%x\n", dev->current_pcb_config.type);
-               cx231xx_info("mode=%x\n", dev->current_pcb_config.mode);
-               cx231xx_info("speed=%x\n", dev->current_pcb_config.speed);
-               cx231xx_info("ts1_source=%x\n",
-                            dev->current_pcb_config.ts1_source);
-               cx231xx_info("ts2_source=%x\n",
-                            dev->current_pcb_config.ts2_source);
-               cx231xx_info("analog_source=%x\n",
-                            dev->current_pcb_config.analog_source);
-       }
-
-       return 0;
-}
diff --git a/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h b/drivers/media/video/cx231xx/cx231xx-pcb-cfg.h
deleted file mode 100644 (file)
index f5e46e8..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
-   cx231xx-pcb-cfg.h - driver for Conexant
-               Cx23100/101/102 USB video capture devices
-
-   Copyright (C) 2008 <srinivasa.deevi at conexant dot 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.
-
-   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.
- */
-
-#ifndef _PCB_CONFIG_H_
-#define _PCB_CONFIG_H_
-
-#include <linux/init.h>
-#include <linux/module.h>
-
-/***************************************************************************
-                               * Class Information *
-***************************************************************************/
-#define CLASS_DEFAULT       0xFF
-
-enum VENDOR_REQUEST_TYPE {
-       /* Set/Get I2C */
-       VRT_SET_I2C0 = 0x0,
-       VRT_SET_I2C1 = 0x1,
-       VRT_SET_I2C2 = 0x2,
-       VRT_GET_I2C0 = 0x4,
-       VRT_GET_I2C1 = 0x5,
-       VRT_GET_I2C2 = 0x6,
-
-       /* Set/Get GPIO */
-       VRT_SET_GPIO = 0x8,
-       VRT_GET_GPIO = 0x9,
-
-       /* Set/Get GPIE */
-       VRT_SET_GPIE = 0xA,
-       VRT_GET_GPIE = 0xB,
-
-       /* Set/Get Register Control/Status */
-       VRT_SET_REGISTER = 0xC,
-       VRT_GET_REGISTER = 0xD,
-
-       /* Get Extended Compat ID Descriptor */
-       VRT_GET_EXTCID_DESC = 0xFF,
-};
-
-enum BYTE_ENABLE_MASK {
-       ENABLE_ONE_BYTE = 0x1,
-       ENABLE_TWE_BYTE = 0x3,
-       ENABLE_THREE_BYTE = 0x7,
-       ENABLE_FOUR_BYTE = 0xF,
-};
-
-#define SPEED_MASK      0x1
-enum USB_SPEED{
-       FULL_SPEED = 0x0,       /* 0: full speed */
-       HIGH_SPEED = 0x1        /* 1: high speed */
-};
-
-enum _true_false{
-       FALSE = 0,
-       TRUE = 1
-};
-
-#define TS_MASK         0x6
-enum TS_PORT{
-       NO_TS_PORT = 0x0,       /* 2'b00: Neither port used. PCB not a Hybrid,
-                                  only offers Analog TV or Video */
-       TS1_PORT = 0x4,         /* 2'b10: TS1 Input (Hybrid mode :
-                               Digital or External Analog/Compressed source) */
-       TS1_TS2_PORT = 0x6,     /* 2'b11: TS1 & TS2 Inputs
-                               (Dual inputs from Digital and/or
-                               External Analog/Compressed sources) */
-       TS1_EXT_CLOCK = 0x6,    /* 2'b11: TS1 & TS2 as selector
-                                               to external clock */
-       TS1VIP_TS2_PORT = 0x2   /* 2'b01: TS1 used as 656/VIP Output,
-                                  TS2 Input (from Compressor) */
-};
-
-#define EAVP_MASK       0x8
-enum EAV_PRESENT{
-       NO_EXTERNAL_AV = 0x0,   /* 0: No External A/V inputs
-                                               (no need for i2s blcok),
-                                               Analog Tuner must be present */
-       EXTERNAL_AV = 0x8       /* 1: External A/V inputs
-                                               present (requires i2s blk) */
-};
-
-#define ATM_MASK        0x30
-enum AT_MODE{
-       DIF_TUNER = 0x30,       /* 2'b11: IF Tuner (requires use of DIF) */
-       BASEBAND_SOUND = 0x20,  /* 2'b10: Baseband Composite &
-                                               Sound-IF Signals present */
-       NO_TUNER = 0x10         /* 2'b0x: No Analog Tuner present */
-};
-
-#define PWR_SEL_MASK    0x40
-enum POWE_TYPE{
-       SELF_POWER = 0x0,       /* 0: self power */
-       BUS_POWER = 0x40        /* 1: bus power */
-};
-
-enum USB_POWE_TYPE{
-       USB_SELF_POWER = 0,
-       USB_BUS_POWER
-};
-
-#define BO_0_MASK       0x80
-enum AVDEC_STATUS{
-       AVDEC_DISABLE = 0x0,    /* 0: A/V Decoder Disabled */
-       AVDEC_ENABLE = 0x80     /* 1: A/V Decoder Enabled */
-};
-
-#define BO_1_MASK       0x100
-
-#define BUSPOWER_MASK   0xC4   /* for Polaris spec 0.8 */
-#define SELFPOWER_MASK  0x86
-
-/***************************************************************************/
-#define NOT_DECIDE_YET  0xFE
-#define NOT_SUPPORTED   0xFF
-
-/***************************************************************************
-                               * for mod field use *
-***************************************************************************/
-#define MOD_DIGITAL     0x1
-#define MOD_ANALOG      0x2
-#define MOD_DIF         0x4
-#define MOD_EXTERNAL    0x8
-#define CAP_ALL_MOD     0x0f
-
-/***************************************************************************
-                               * source define *
-***************************************************************************/
-#define SOURCE_DIGITAL          0x1
-#define SOURCE_ANALOG           0x2
-#define SOURCE_DIF              0x4
-#define SOURCE_EXTERNAL         0x8
-#define SOURCE_TS_BDA                  0x10
-#define SOURCE_TS_ENCODE               0x20
-#define SOURCE_TS_EXTERNAL     0x40
-
-/***************************************************************************
-                               * interface information define *
-***************************************************************************/
-struct INTERFACE_INFO {
-       u8 interrupt_index;
-       u8 ts1_index;
-       u8 ts2_index;
-       u8 audio_index;
-       u8 video_index;
-       u8 vanc_index;          /* VBI */
-       u8 hanc_index;          /* Sliced CC */
-       u8 ir_index;
-};
-
-enum INDEX_INTERFACE_INFO{
-       INDEX_INTERRUPT = 0x0,
-       INDEX_TS1,
-       INDEX_TS2,
-       INDEX_AUDIO,
-       INDEX_VIDEO,
-       INDEX_VANC,
-       INDEX_HANC,
-       INDEX_IR,
-};
-
-/***************************************************************************
-                               * configuration information define *
-***************************************************************************/
-struct CONFIG_INFO {
-       u8 config_index;
-       struct INTERFACE_INFO interface_info;
-};
-
-struct pcb_config {
-       u8 index;
-       u8 type;                /* bus power or self power,
-                                          self power--0, bus_power--1 */
-       u8 speed;               /* usb speed, 2.0--1, 1.1--0 */
-       u8 mode;                /* digital , anlog, dif or external A/V */
-       u32 ts1_source;         /* three source -- BDA,External,encode */
-       u32 ts2_source;
-       u32 analog_source;
-       u8 digital_index;       /* bus-power used */
-       u8 analog_index;        /* bus-power used */
-       u8 dif_index;           /* bus-power used */
-       u8 external_index;      /* bus-power used */
-       u8 config_num;          /* current config num, 0,1,2,
-                                                  for self-power, always 0 */
-       struct CONFIG_INFO hs_config_info[3];
-       struct CONFIG_INFO fs_config_info[3];
-};
-
-enum INDEX_PCB_CONFIG{
-       INDEX_SELFPOWER_DIGITAL_ONLY = 0x0,
-       INDEX_SELFPOWER_DUAL_DIGITAL,
-       INDEX_SELFPOWER_ANALOG_ONLY,
-       INDEX_SELFPOWER_DUAL,
-       INDEX_SELFPOWER_TRIPLE,
-       INDEX_SELFPOWER_COMPRESSOR,
-       INDEX_BUSPOWER_DIGITAL_ONLY,
-       INDEX_BUSPOWER_ANALOG_ONLY,
-       INDEX_BUSPOWER_DIF_ONLY,
-       INDEX_BUSPOWER_EXTERNAL_ONLY,
-       INDEX_BUSPOWER_EXTERNAL_ANALOG,
-       INDEX_BUSPOWER_EXTERNAL_DIF,
-       INDEX_BUSPOWER_EXTERNAL_DIGITAL,
-       INDEX_BUSPOWER_DIGITAL_ANALOG,
-       INDEX_BUSPOWER_DIGITAL_DIF,
-       INDEX_BUSPOWER_DIGITAL_ANALOG_EXTERNAL,
-       INDEX_BUSPOWER_DIGITAL_DIF_EXTERNAL,
-};
-
-/***************************************************************************/
-struct cx231xx;
-
-u32 initialize_cx231xx(struct cx231xx *p_dev);
-
-#endif
diff --git a/drivers/media/video/cx231xx/cx231xx-reg.h b/drivers/media/video/cx231xx/cx231xx-reg.h
deleted file mode 100644 (file)
index 750c5d3..0000000
+++ /dev/null
@@ -1,1564 +0,0 @@
-/*
-   cx231xx-reg.h - driver for Conexant Cx23100/101/102
-              USB video capture devices
-
-   Copyright (C) 2008 <srinivasa.deevi at conexant dot 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.
-
-   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.
- */
-
-#ifndef _CX231XX_REG_H
-#define _CX231XX_REG_H
-
-/*****************************************************************************
-                               * VBI codes *
-*****************************************************************************/
-
-#define SAV_ACTIVE_VIDEO_FIELD1                0x80
-#define EAV_ACTIVE_VIDEO_FIELD1                0x90
-
-#define SAV_ACTIVE_VIDEO_FIELD2                0xc0
-#define EAV_ACTIVE_VIDEO_FIELD2                0xd0
-
-#define SAV_VBLANK_FIELD1              0xa0
-#define EAV_VBLANK_FIELD1              0xb0
-
-#define SAV_VBLANK_FIELD2              0xe0
-#define EAV_VBLANK_FIELD2              0xf0
-
-#define SAV_VBI_FIELD1                 0x20
-#define EAV_VBI_FIELD1                 0x30
-
-#define SAV_VBI_FIELD2                 0x60
-#define EAV_VBI_FIELD2                 0x70
-
-/*****************************************************************************/
-/* Audio ADC Registers */
-#define CH_PWR_CTRL1                   0x0000000e
-#define CH_PWR_CTRL2                   0x0000000f
-/*****************************************************************************/
-
-#define      HOST_REG1                0x000
-#define      FLD_FORCE_CHIP_SEL       0x80
-#define      FLD_AUTO_INC_DIS         0x20
-#define      FLD_PREFETCH_EN          0x10
-/* Reserved [2:3] */
-#define      FLD_DIGITAL_PWR_DN       0x02
-#define      FLD_SLEEP                0x01
-
-/*****************************************************************************/
-#define      HOST_REG2                0x001
-
-/*****************************************************************************/
-#define      HOST_REG3                0x002
-
-/*****************************************************************************/
-/* added for polaris */
-#define      GPIO_PIN_CTL0            0x3
-#define      GPIO_PIN_CTL1            0x4
-#define      GPIO_PIN_CTL2            0x5
-#define      GPIO_PIN_CTL3            0x6
-#define      TS1_PIN_CTL0             0x7
-#define      TS1_PIN_CTL1             0x8
-/*****************************************************************************/
-
-#define      FLD_CLK_IN_EN            0x80
-#define      FLD_XTAL_CTRL            0x70
-#define      FLD_BB_CLK_MODE          0x0C
-#define      FLD_REF_DIV_PLL          0x02
-#define      FLD_REF_SEL_PLL1         0x01
-
-/*****************************************************************************/
-#define      CHIP_CTRL                0x100
-/* Reserved [27] */
-/* Reserved [31:21] */
-#define      FLD_CHIP_ACFG_DIS        0x00100000
-/* Reserved [19] */
-#define      FLD_DUAL_MODE_ADC2       0x00040000
-#define      FLD_SIF_EN               0x00020000
-#define      FLD_SOFT_RST             0x00010000
-#define      FLD_DEVICE_ID            0x0000ffff
-
-/*****************************************************************************/
-#define      AFE_CTRL                 0x104
-#define      AFE_CTRL_C2HH_SRC_CTRL   0x104
-#define      FLD_DIF_OUT_SEL          0xc0000000
-#define      FLD_AUX_PLL_CLK_ALT_SEL  0x3c000000
-#define      FLD_UV_ORDER_MODE        0x02000000
-#define      FLD_FUNC_MODE            0x01800000
-#define      FLD_ROT1_PHASE_CTL       0x007f8000
-#define      FLD_AUD_IN_SEL           0x00004000
-#define      FLD_LUMA_IN_SEL          0x00002000
-#define      FLD_CHROMA_IN_SEL        0x00001000
-/* reserve [11:10] */
-#define      FLD_INV_SPEC_DIS         0x00000200
-#define      FLD_VGA_SEL_CH3          0x00000100
-#define      FLD_VGA_SEL_CH2          0x00000080
-#define      FLD_VGA_SEL_CH1          0x00000040
-#define      FLD_DCR_BYP_CH1          0x00000020
-#define      FLD_DCR_BYP_CH2          0x00000010
-#define      FLD_DCR_BYP_CH3          0x00000008
-#define      FLD_EN_12DB_CH3          0x00000004
-#define      FLD_EN_12DB_CH2          0x00000002
-#define      FLD_EN_12DB_CH1          0x00000001
-
-/* redefine in Cx231xx */
-/*****************************************************************************/
-#define      DC_CTRL1                 0x108
-/* reserve [31:30] */
-#define      FLD_CLAMP_LVL_CH1        0x3fff8000
-#define      FLD_CLAMP_LVL_CH2        0x00007fff
-/*****************************************************************************/
-
-/*****************************************************************************/
-#define      DC_CTRL2                 0x10c
-/* reserve [31:28] */
-#define      FLD_CLAMP_LVL_CH3        0x00fffe00
-#define      FLD_CLAMP_WIND_LENTH     0x000001e0
-#define      FLD_C2HH_SAT_MIN         0x0000001e
-#define      FLD_FLT_BYP_SEL          0x00000001
-/*****************************************************************************/
-
-/*****************************************************************************/
-#define      DC_CTRL3                 0x110
-/* reserve [31:16] */
-#define      FLD_ERR_GAIN_CTL         0x00070000
-#define      FLD_LPF_MIN              0x0000ffff
-/*****************************************************************************/
-
-/*****************************************************************************/
-#define      DC_CTRL4                 0x114
-/* reserve [31:31] */
-#define      FLD_INTG_CH1             0x7fffffff
-/*****************************************************************************/
-
-/*****************************************************************************/
-#define      DC_CTRL5                 0x118
-/* reserve [31:31] */
-#define      FLD_INTG_CH2             0x7fffffff
-/*****************************************************************************/
-
-/*****************************************************************************/
-#define      DC_CTRL6                 0x11c
-/* reserve [31:31] */
-#define      FLD_INTG_CH3             0x7fffffff
-/*****************************************************************************/
-
-/*****************************************************************************/
-#define      PIN_CTRL                 0x120
-#define      FLD_OEF_AGC_RF           0x00000001
-#define      FLD_OEF_AGC_IFVGA        0x00000002
-#define      FLD_OEF_AGC_IF           0x00000004
-#define      FLD_REG_BO_PUD           0x80000000
-#define      FLD_IR_IRQ_STAT          0x40000000
-#define      FLD_AUD_IRQ_STAT         0x20000000
-#define      FLD_VID_IRQ_STAT         0x10000000
-/* Reserved [27:26] */
-#define      FLD_IRQ_N_OUT_EN         0x02000000
-#define      FLD_IRQ_N_POLAR          0x01000000
-/* Reserved [23:6] */
-#define      FLD_OE_AUX_PLL_CLK       0x00000020
-#define      FLD_OE_I2S_BCLK          0x00000010
-#define      FLD_OE_I2S_WCLK          0x00000008
-#define      FLD_OE_AGC_IF            0x00000004
-#define      FLD_OE_AGC_IFVGA         0x00000002
-#define      FLD_OE_AGC_RF            0x00000001
-
-/*****************************************************************************/
-#define      AUD_IO_CTRL              0x124
-/* Reserved [31:8] */
-#define      FLD_I2S_PORT_DIR         0x00000080
-#define      FLD_I2S_OUT_SRC          0x00000040
-#define      FLD_AUD_CHAN3_SRC        0x00000030
-#define      FLD_AUD_CHAN2_SRC        0x0000000c
-#define      FLD_AUD_CHAN1_SRC        0x00000003
-
-/*****************************************************************************/
-#define      AUD_LOCK1                0x128
-#define      FLD_AUD_LOCK_KI_SHIFT    0xc0000000
-#define      FLD_AUD_LOCK_KD_SHIFT    0x30000000
-/* Reserved [27:25] */
-#define      FLD_EN_AV_LOCK           0x01000000
-#define      FLD_VID_COUNT            0x00ffffff
-
-/*****************************************************************************/
-#define      AUD_LOCK2                0x12c
-#define      FLD_AUD_LOCK_KI_MULT     0xf0000000
-#define      FLD_AUD_LOCK_KD_MULT     0x0F000000
-/* Reserved [23:22] */
-#define      FLD_AUD_LOCK_FREQ_SHIFT  0x00300000
-#define      FLD_AUD_COUNT            0x000fffff
-
-/*****************************************************************************/
-#define      AFE_DIAG_CTRL1           0x134
-/* Reserved [31:16] */
-#define      FLD_CUV_DLY_LENGTH       0x0000ff00
-#define      FLD_YC_DLY_LENGTH        0x000000ff
-
-/*****************************************************************************/
-/* Poalris redefine */
-#define      AFE_DIAG_CTRL3           0x138
-/* Reserved [31:26] */
-#define      FLD_AUD_DUAL_FLAG_POL    0x02000000
-#define      FLD_VID_DUAL_FLAG_POL    0x01000000
-/* Reserved [23:23] */
-#define      FLD_COL_CLAMP_DIS_CH1    0x00400000
-#define      FLD_COL_CLAMP_DIS_CH2    0x00200000
-#define      FLD_COL_CLAMP_DIS_CH3    0x00100000
-
-#define      TEST_CTRL1               0x144
-/* Reserved [31:29] */
-#define      FLD_LBIST_EN             0x10000000
-/* Reserved [27:10] */
-#define      FLD_FI_BIST_INTR_R       0x0000200
-#define      FLD_FI_BIST_INTR_L       0x0000100
-#define      FLD_BIST_FAIL_AUD_PLL    0x0000080
-#define      FLD_BIST_INTR_AUD_PLL    0x0000040
-#define      FLD_BIST_FAIL_VID_PLL    0x0000020
-#define      FLD_BIST_INTR_VID_PLL    0x0000010
-/* Reserved [3:1] */
-#define      FLD_CIR_TEST_DIS         0x00000001
-
-/*****************************************************************************/
-#define      TEST_CTRL2               0x148
-#define      FLD_TSXCLK_POL_CTL       0x80000000
-#define      FLD_ISO_CTL_SEL          0x40000000
-#define      FLD_ISO_CTL_EN           0x20000000
-#define      FLD_BIST_DEBUGZ          0x10000000
-#define      FLD_AUD_BIST_TEST_H      0x0f000000
-/* Reserved [23:22] */
-#define      FLD_FLTRN_BIST_TEST_H    0x00020000
-#define      FLD_VID_BIST_TEST_H      0x00010000
-/* Reserved [19:17] */
-#define      FLD_BIST_TEST_H          0x00010000
-/* Reserved [15:13] */
-#define      FLD_TAB_EN               0x00001000
-/* Reserved [11:0] */
-
-/*****************************************************************************/
-#define      BIST_STAT                0x14c
-#define      FLD_AUD_BIST_FAIL_H      0xfff00000
-#define      FLD_FLTRN_BIST_FAIL_H    0x00180000
-#define      FLD_VID_BIST_FAIL_H      0x00070000
-#define      FLD_AUD_BIST_TST_DONE    0x0000fff0
-#define      FLD_FLTRN_BIST_TST_DONE  0x00000008
-#define      FLD_VID_BIST_TST_DONE    0x00000007
-
-/*****************************************************************************/
-/* DirectIF registers definition have been moved to DIF_reg.h                */
-/*****************************************************************************/
-#define      MODE_CTRL                0x400
-#define      FLD_AFD_PAL60_DIS        0x20000000
-#define      FLD_AFD_FORCE_SECAM      0x10000000
-#define      FLD_AFD_FORCE_PALNC      0x08000000
-#define      FLD_AFD_FORCE_PAL        0x04000000
-#define      FLD_AFD_PALM_SEL         0x03000000
-#define      FLD_CKILL_MODE           0x00300000
-#define      FLD_COMB_NOTCH_MODE      0x00c00000       /* bit[19:18] */
-#define      FLD_CLR_LOCK_STAT        0x00020000
-#define      FLD_FAST_LOCK_MD         0x00010000
-#define      FLD_WCEN                 0x00008000
-#define      FLD_CAGCEN               0x00004000
-#define      FLD_CKILLEN              0x00002000
-#define      FLD_AUTO_SC_LOCK         0x00001000
-#define      FLD_MAN_SC_FAST_LOCK     0x00000800
-#define      FLD_INPUT_MODE           0x00000600
-#define      FLD_AFD_ACQUIRE          0x00000100
-#define      FLD_AFD_NTSC_SEL         0x00000080
-#define      FLD_AFD_PAL_SEL          0x00000040
-#define      FLD_ACFG_DIS             0x00000020
-#define      FLD_SQ_PIXEL             0x00000010
-#define      FLD_VID_FMT_SEL          0x0000000f
-
-/*****************************************************************************/
-#define      OUT_CTRL1                0x404
-#define      FLD_POLAR                0x7f000000
-/* Reserved [23] */
-#define      FLD_RND_MODE             0x00600000
-#define      FLD_VIPCLAMP_EN          0x00100000
-#define      FLD_VIPBLANK_EN          0x00080000
-#define      FLD_VIP_OPT_AL           0x00040000
-#define      FLD_IDID0_SOURCE         0x00020000
-#define      FLD_DCMODE               0x00010000
-#define      FLD_CLK_GATING           0x0000c000
-#define      FLD_CLK_INVERT           0x00002000
-#define      FLD_HSFMT                0x00001000
-#define      FLD_VALIDFMT             0x00000800
-#define      FLD_ACTFMT               0x00000400
-#define      FLD_SWAPRAW              0x00000200
-#define      FLD_CLAMPRAW_EN          0x00000100
-#define      FLD_BLUE_FIELD_EN        0x00000080
-#define      FLD_BLUE_FIELD_ACT       0x00000040
-#define      FLD_TASKBIT_VAL          0x00000020
-#define      FLD_ANC_DATA_EN          0x00000010
-#define      FLD_VBIHACTRAW_EN        0x00000008
-#define      FLD_MODE10B              0x00000004
-#define      FLD_OUT_MODE             0x00000003
-
-/*****************************************************************************/
-#define      OUT_CTRL2                0x408
-#define      FLD_AUD_GRP              0xc0000000
-#define      FLD_SAMPLE_RATE          0x30000000
-#define      FLD_AUD_ANC_EN           0x08000000
-#define      FLD_EN_C                 0x04000000
-#define      FLD_EN_B                 0x02000000
-#define      FLD_EN_A                 0x01000000
-/* Reserved [23:20] */
-#define      FLD_IDID1_LSB            0x000c0000
-#define      FLD_IDID0_LSB            0x00030000
-#define      FLD_IDID1_MSB            0x0000ff00
-#define      FLD_IDID0_MSB            0x000000ff
-
-/*****************************************************************************/
-#define      GEN_STAT                 0x40c
-#define      FLD_VCR_DETECT           0x00800000
-#define      FLD_SPECIAL_PLAY_N       0x00400000
-#define      FLD_VPRES                0x00200000
-#define      FLD_AGC_LOCK             0x00100000
-#define      FLD_CSC_LOCK             0x00080000
-#define      FLD_VLOCK                0x00040000
-#define      FLD_SRC_LOCK             0x00020000
-#define      FLD_HLOCK                0x00010000
-#define      FLD_VSYNC_N              0x00008000
-#define      FLD_SRC_FIFO_UFLOW       0x00004000
-#define      FLD_SRC_FIFO_OFLOW       0x00002000
-#define      FLD_FIELD                0x00001000
-#define      FLD_AFD_FMT_STAT         0x00000f00
-#define      FLD_MV_TYPE2_PAIR        0x00000080
-#define      FLD_MV_T3CS              0x00000040
-#define      FLD_MV_CS                0x00000020
-#define      FLD_MV_PSP               0x00000010
-/* Reserved [3] */
-#define      FLD_MV_CDAT              0x00000003
-
-/*****************************************************************************/
-#define      INT_STAT_MASK            0x410
-#define      FLD_COMB_3D_FIFO_MSK     0x80000000
-#define      FLD_WSS_DAT_AVAIL_MSK    0x40000000
-#define      FLD_GS2_DAT_AVAIL_MSK    0x20000000
-#define      FLD_GS1_DAT_AVAIL_MSK    0x10000000
-#define      FLD_CC_DAT_AVAIL_MSK     0x08000000
-#define      FLD_VPRES_CHANGE_MSK     0x04000000
-#define      FLD_MV_CHANGE_MSK        0x02000000
-#define      FLD_END_VBI_EVEN_MSK     0x01000000
-#define      FLD_END_VBI_ODD_MSK      0x00800000
-#define      FLD_FMT_CHANGE_MSK       0x00400000
-#define      FLD_VSYNC_TRAIL_MSK      0x00200000
-#define      FLD_HLOCK_CHANGE_MSK     0x00100000
-#define      FLD_VLOCK_CHANGE_MSK     0x00080000
-#define      FLD_CSC_LOCK_CHANGE_MSK  0x00040000
-#define      FLD_SRC_FIFO_UFLOW_MSK   0x00020000
-#define      FLD_SRC_FIFO_OFLOW_MSK   0x00010000
-#define      FLD_COMB_3D_FIFO_STAT    0x00008000
-#define      FLD_WSS_DAT_AVAIL_STAT   0x00004000
-#define      FLD_GS2_DAT_AVAIL_STAT   0x00002000
-#define      FLD_GS1_DAT_AVAIL_STAT   0x00001000
-#define      FLD_CC_DAT_AVAIL_STAT    0x00000800
-#define      FLD_VPRES_CHANGE_STAT    0x00000400
-#define      FLD_MV_CHANGE_STAT       0x00000200
-#define      FLD_END_VBI_EVEN_STAT    0x00000100
-#define      FLD_END_VBI_ODD_STAT     0x00000080
-#define      FLD_FMT_CHANGE_STAT      0x00000040
-#define      FLD_VSYNC_TRAIL_STAT     0x00000020
-#define      FLD_HLOCK_CHANGE_STAT    0x00000010
-#define      FLD_VLOCK_CHANGE_STAT    0x00000008
-#define      FLD_CSC_LOCK_CHANGE_STAT 0x00000004
-#define      FLD_SRC_FIFO_UFLOW_STAT  0x00000002
-#define      FLD_SRC_FIFO_OFLOW_STAT  0x00000001
-
-/*****************************************************************************/
-#define      LUMA_CTRL                0x414
-#define      BRIGHTNESS_CTRL_BYTE     0x414
-#define      CONTRAST_CTRL_BYTE       0x415
-#define      LUMA_CTRL_BYTE_3         0x416
-#define      FLD_LUMA_CORE_SEL        0x00c00000
-#define      FLD_RANGE                0x00300000
-/* Reserved [19] */
-#define      FLD_PEAK_EN              0x00040000
-#define      FLD_PEAK_SEL             0x00030000
-#define      FLD_CNTRST               0x0000ff00
-#define      FLD_BRITE                0x000000ff
-
-/*****************************************************************************/
-#define      HSCALE_CTRL              0x418
-#define      FLD_HFILT                0x03000000
-#define      FLD_HSCALE               0x00ffffff
-
-/*****************************************************************************/
-#define      VSCALE_CTRL              0x41c
-#define      FLD_LINE_AVG_DIS         0x01000000
-/* Reserved [23:20] */
-#define      FLD_VS_INTRLACE          0x00080000
-#define      FLD_VFILT                0x00070000
-/* Reserved [15:13] */
-#define      FLD_VSCALE               0x00001fff
-
-/*****************************************************************************/
-#define      CHROMA_CTRL              0x420
-#define      USAT_CTRL_BYTE           0x420
-#define      VSAT_CTRL_BYTE           0x421
-#define      HUE_CTRL_BYTE            0x422
-#define      FLD_C_LPF_EN             0x20000000
-#define      FLD_CHR_DELAY            0x1c000000
-#define      FLD_C_CORE_SEL           0x03000000
-#define      FLD_HUE                  0x00ff0000
-#define      FLD_VSAT                 0x0000ff00
-#define      FLD_USAT                 0x000000ff
-
-/*****************************************************************************/
-#define      VBI_LINE_CTRL1           0x424
-#define      FLD_VBI_MD_LINE4         0xff000000
-#define      FLD_VBI_MD_LINE3         0x00ff0000
-#define      FLD_VBI_MD_LINE2         0x0000ff00
-#define      FLD_VBI_MD_LINE1         0x000000ff
-
-/*****************************************************************************/
-#define      VBI_LINE_CTRL2           0x428
-#define      FLD_VBI_MD_LINE8         0xff000000
-#define      FLD_VBI_MD_LINE7         0x00ff0000
-#define      FLD_VBI_MD_LINE6         0x0000ff00
-#define      FLD_VBI_MD_LINE5         0x000000ff
-
-/*****************************************************************************/
-#define      VBI_LINE_CTRL3           0x42c
-#define      FLD_VBI_MD_LINE12        0xff000000
-#define      FLD_VBI_MD_LINE11        0x00ff0000
-#define      FLD_VBI_MD_LINE10        0x0000ff00
-#define      FLD_VBI_MD_LINE9         0x000000ff
-
-/*****************************************************************************/
-#define      VBI_LINE_CTRL4           0x430
-#define      FLD_VBI_MD_LINE16        0xff000000
-#define      FLD_VBI_MD_LINE15        0x00ff0000
-#define      FLD_VBI_MD_LINE14        0x0000ff00
-#define      FLD_VBI_MD_LINE13        0x000000ff
-
-/*****************************************************************************/
-#define      VBI_LINE_CTRL5           0x434
-#define      FLD_VBI_MD_LINE17        0x000000ff
-
-/*****************************************************************************/
-#define      VBI_FC_CFG               0x438
-#define      FLD_FC_ALT2              0xff000000
-#define      FLD_FC_ALT1              0x00ff0000
-#define      FLD_FC_ALT2_TYPE         0x0000f000
-#define      FLD_FC_ALT1_TYPE         0x00000f00
-/* Reserved [7:1] */
-#define      FLD_FC_SEARCH_MODE       0x00000001
-
-/*****************************************************************************/
-#define      VBI_MISC_CFG1            0x43c
-#define      FLD_TTX_PKTADRU          0xfff00000
-#define      FLD_TTX_PKTADRL          0x000fff00
-/* Reserved [7:6] */
-#define      FLD_MOJI_PACK_DIS        0x00000020
-#define      FLD_VPS_DEC_DIS          0x00000010
-#define      FLD_CRI_MARG_SCALE       0x0000000c
-#define      FLD_EDGE_RESYNC_EN       0x00000002
-#define      FLD_ADAPT_SLICE_DIS      0x00000001
-
-/*****************************************************************************/
-#define      VBI_MISC_CFG2            0x440
-#define      FLD_HAMMING_TYPE         0x0f000000
-/* Reserved [23:20] */
-#define      FLD_WSS_FIFO_RST         0x00080000
-#define      FLD_GS2_FIFO_RST         0x00040000
-#define      FLD_GS1_FIFO_RST         0x00020000
-#define      FLD_CC_FIFO_RST          0x00010000
-/* Reserved [15:12] */
-#define      FLD_VBI3_SDID            0x00000f00
-#define      FLD_VBI2_SDID            0x000000f0
-#define      FLD_VBI1_SDID            0x0000000f
-
-/*****************************************************************************/
-#define      VBI_PAY1                 0x444
-#define      FLD_GS1_FIFO_DAT         0xFF000000
-#define      FLD_GS1_STAT             0x00FF0000
-#define      FLD_CC_FIFO_DAT          0x0000FF00
-#define      FLD_CC_STAT              0x000000FF
-
-/*****************************************************************************/
-#define      VBI_PAY2                 0x448
-#define      FLD_WSS_FIFO_DAT         0xff000000
-#define      FLD_WSS_STAT             0x00ff0000
-#define      FLD_GS2_FIFO_DAT         0x0000ff00
-#define      FLD_GS2_STAT             0x000000ff
-
-/*****************************************************************************/
-#define      VBI_CUST1_CFG1           0x44c
-/* Reserved [31] */
-#define      FLD_VBI1_CRIWIN          0x7f000000
-#define      FLD_VBI1_SLICE_DIST      0x00f00000
-#define      FLD_VBI1_BITINC          0x000fff00
-#define      FLD_VBI1_HDELAY          0x000000ff
-
-/*****************************************************************************/
-#define      VBI_CUST1_CFG2           0x450
-#define      FLD_VBI1_FC_LENGTH       0x1f000000
-#define      FLD_VBI1_FRAME_CODE      0x00ffffff
-
-/*****************************************************************************/
-#define      VBI_CUST1_CFG3           0x454
-#define      FLD_VBI1_HAM_EN          0x80000000
-#define      FLD_VBI1_FIFO_MODE       0x70000000
-#define      FLD_VBI1_FORMAT_TYPE     0x0f000000
-#define      FLD_VBI1_PAYLD_LENGTH    0x00ff0000
-#define      FLD_VBI1_CRI_LENGTH      0x0000f000
-#define      FLD_VBI1_CRI_MARGIN      0x00000f00
-#define      FLD_VBI1_CRI_TIME        0x000000ff
-
-/*****************************************************************************/
-#define      VBI_CUST2_CFG1           0x458
-/* Reserved [31] */
-#define      FLD_VBI2_CRIWIN          0x7f000000
-#define      FLD_VBI2_SLICE_DIST      0x00f00000
-#define      FLD_VBI2_BITINC          0x000fff00
-#define      FLD_VBI2_HDELAY          0x000000ff
-
-/*****************************************************************************/
-#define      VBI_CUST2_CFG2           0x45c
-#define      FLD_VBI2_FC_LENGTH       0x1f000000
-#define      FLD_VBI2_FRAME_CODE      0x00ffffff
-
-/*****************************************************************************/
-#define      VBI_CUST2_CFG3           0x460
-#define      FLD_VBI2_HAM_EN          0x80000000
-#define      FLD_VBI2_FIFO_MODE       0x70000000
-#define      FLD_VBI2_FORMAT_TYPE     0x0f000000
-#define      FLD_VBI2_PAYLD_LENGTH    0x00ff0000
-#define      FLD_VBI2_CRI_LENGTH      0x0000f000
-#define      FLD_VBI2_CRI_MARGIN      0x00000f00
-#define      FLD_VBI2_CRI_TIME        0x000000ff
-
-/*****************************************************************************/
-#define      VBI_CUST3_CFG1           0x464
-/* Reserved [31] */
-#define      FLD_VBI3_CRIWIN          0x7f000000
-#define      FLD_VBI3_SLICE_DIST      0x00f00000
-#define      FLD_VBI3_BITINC          0x000fff00
-#define      FLD_VBI3_HDELAY          0x000000ff
-
-/*****************************************************************************/
-#define      VBI_CUST3_CFG2           0x468
-#define      FLD_VBI3_FC_LENGTH       0x1f000000
-#define      FLD_VBI3_FRAME_CODE      0x00ffffff
-
-/*****************************************************************************/
-#define      VBI_CUST3_CFG3           0x46c
-#define      FLD_VBI3_HAM_EN          0x80000000
-#define      FLD_VBI3_FIFO_MODE       0x70000000
-#define      FLD_VBI3_FORMAT_TYPE     0x0f000000
-#define      FLD_VBI3_PAYLD_LENGTH    0x00ff0000
-#define      FLD_VBI3_CRI_LENGTH      0x0000f000
-#define      FLD_VBI3_CRI_MARGIN      0x00000f00
-#define      FLD_VBI3_CRI_TIME        0x000000ff
-
-/*****************************************************************************/
-#define      HORIZ_TIM_CTRL           0x470
-#define      FLD_BGDEL_CNT            0xff000000
-/* Reserved [23:22] */
-#define      FLD_HACTIVE_CNT          0x003ff000
-/* Reserved [11:10] */
-#define      FLD_HBLANK_CNT           0x000003ff
-
-/*****************************************************************************/
-#define      VERT_TIM_CTRL            0x474
-#define      FLD_V656BLANK_CNT        0xff000000
-/* Reserved [23:22] */
-#define      FLD_VACTIVE_CNT          0x003ff000
-/* Reserved [11:10] */
-#define      FLD_VBLANK_CNT           0x000003ff
-
-/*****************************************************************************/
-#define      SRC_COMB_CFG             0x478
-#define      FLD_CCOMB_2LN_CHECK      0x80000000
-#define      FLD_CCOMB_3LN_EN         0x40000000
-#define      FLD_CCOMB_2LN_EN         0x20000000
-#define      FLD_CCOMB_3D_EN          0x10000000
-/* Reserved [27] */
-#define      FLD_LCOMB_3LN_EN         0x04000000
-#define      FLD_LCOMB_2LN_EN         0x02000000
-#define      FLD_LCOMB_3D_EN          0x01000000
-#define      FLD_LUMA_LPF_SEL         0x00c00000
-#define      FLD_UV_LPF_SEL           0x00300000
-#define      FLD_BLEND_SLOPE          0x000f0000
-#define      FLD_CCOMB_REDUCE_EN      0x00008000
-/* Reserved [14:10] */
-#define      FLD_SRC_DECIM_RATIO      0x000003ff
-
-/*****************************************************************************/
-#define      CHROMA_VBIOFF_CFG        0x47c
-#define      FLD_VBI_VOFFSET          0x1f000000
-/* Reserved [23:20] */
-#define      FLD_SC_STEP              0x000fffff
-
-/*****************************************************************************/
-#define      FIELD_COUNT              0x480
-#define      FLD_FIELD_COUNT_FLD      0x000003ff
-
-/*****************************************************************************/
-#define      MISC_TIM_CTRL            0x484
-#define      FLD_DEBOUNCE_COUNT       0xc0000000
-#define      FLD_VT_LINE_CNT_HYST     0x30000000
-/* Reserved [27] */
-#define      FLD_AFD_STAT             0x07ff0000
-#define      FLD_VPRES_VERT_EN        0x00008000
-/* Reserved [14:12] */
-#define      FLD_HR32                 0x00000800
-#define      FLD_TDALGN               0x00000400
-#define      FLD_TDFIELD              0x00000200
-/* Reserved [8:6] */
-#define      FLD_TEMPDEC              0x0000003f
-
-/*****************************************************************************/
-#define      DFE_CTRL1                0x488
-#define      FLD_CLAMP_AUTO_EN        0x80000000
-#define      FLD_AGC_AUTO_EN          0x40000000
-#define      FLD_VGA_CRUSH_EN         0x20000000
-#define      FLD_VGA_AUTO_EN          0x10000000
-#define      FLD_VBI_GATE_EN          0x08000000
-#define      FLD_CLAMP_LEVEL          0x07000000
-/* Reserved [23:22] */
-#define      FLD_CLAMP_SKIP_CNT       0x00300000
-#define      FLD_AGC_GAIN             0x000fff00
-/* Reserved [7:6] */
-#define      FLD_VGA_GAIN             0x0000003f
-
-/*****************************************************************************/
-#define      DFE_CTRL2                0x48c
-#define      FLD_VGA_ACQUIRE_RANGE    0x00ff0000
-#define      FLD_VGA_TRACK_RANGE      0x0000ff00
-#define      FLD_VGA_SYNC             0x000000ff
-
-/*****************************************************************************/
-#define      DFE_CTRL3                0x490
-#define      FLD_BP_PERCENT           0xff000000
-#define      FLD_DFT_THRESHOLD        0x00ff0000
-/* Reserved [15:12] */
-#define      FLD_SYNC_WIDTH_SEL       0x00000600
-#define      FLD_BP_LOOP_GAIN         0x00000300
-#define      FLD_SYNC_LOOP_GAIN       0x000000c0
-/* Reserved [5:4] */
-#define      FLD_AGC_LOOP_GAIN        0x0000000c
-#define      FLD_DCC_LOOP_GAIN        0x00000003
-
-/*****************************************************************************/
-#define      PLL_CTRL                 0x494
-#define      FLD_PLL_KD               0xff000000
-#define      FLD_PLL_KI               0x00ff0000
-#define      FLD_PLL_MAX_OFFSET       0x0000ffff
-
-/*****************************************************************************/
-#define      HTL_CTRL                 0x498
-/* Reserved [31:24] */
-#define      FLD_AUTO_LOCK_SPD        0x00080000
-#define      FLD_MAN_FAST_LOCK        0x00040000
-#define      FLD_HTL_15K_EN           0x00020000
-#define      FLD_HTL_500K_EN          0x00010000
-#define      FLD_HTL_KD               0x0000ff00
-#define      FLD_HTL_KI               0x000000ff
-
-/*****************************************************************************/
-#define      COMB_CTRL                0x49c
-#define      FLD_COMB_PHASE_LIMIT     0xff000000
-#define      FLD_CCOMB_ERR_LIMIT      0x00ff0000
-#define      FLD_LUMA_THRESHOLD       0x0000ff00
-#define      FLD_LCOMB_ERR_LIMIT      0x000000ff
-
-/*****************************************************************************/
-#define      CRUSH_CTRL               0x4a0
-#define      FLD_WTW_EN               0x00400000
-#define      FLD_CRUSH_FREQ           0x00200000
-#define      FLD_MAJ_SEL_EN           0x00100000
-#define      FLD_MAJ_SEL              0x000c0000
-/* Reserved [17:15] */
-#define      FLD_SYNC_TIP_REDUCE      0x00007e00
-/* Reserved [8:6] */
-#define      FLD_SYNC_TIP_INC         0x0000003f
-
-/*****************************************************************************/
-#define      SOFT_RST_CTRL            0x4a4
-#define      FLD_VD_SOFT_RST          0x00008000
-/* Reserved [14:12] */
-#define      FLD_REG_RST_MSK          0x00000800
-#define      FLD_VOF_RST_MSK          0x00000400
-#define      FLD_MVDET_RST_MSK        0x00000200
-#define      FLD_VBI_RST_MSK          0x00000100
-#define      FLD_SCALE_RST_MSK        0x00000080
-#define      FLD_CHROMA_RST_MSK       0x00000040
-#define      FLD_LUMA_RST_MSK         0x00000020
-#define      FLD_VTG_RST_MSK          0x00000010
-#define      FLD_YCSEP_RST_MSK        0x00000008
-#define      FLD_SRC_RST_MSK          0x00000004
-#define      FLD_DFE_RST_MSK          0x00000002
-/* Reserved [0] */
-
-/*****************************************************************************/
-#define      MV_DT_CTRL1              0x4a8
-/* Reserved [31:29] */
-#define      FLD_PSP_STOP_LINE        0x1f000000
-/* Reserved [23:21] */
-#define      FLD_PSP_STRT_LINE        0x001f0000
-/* Reserved [15] */
-#define      FLD_PSP_LLIMW            0x00007f00
-/* Reserved [7] */
-#define      FLD_PSP_ULIMW            0x0000007f
-
-/*****************************************************************************/
-#define      MV_DT_CTRL2              0x4aC
-#define      FLD_CS_STOPWIN           0xff000000
-#define      FLD_CS_STRTWIN           0x00ff0000
-#define      FLD_CS_WIDTH             0x0000ff00
-#define      FLD_PSP_SPEC_VAL         0x000000ff
-
-/*****************************************************************************/
-#define      MV_DT_CTRL3              0x4B0
-#define      FLD_AUTO_RATE_DIS        0x80000000
-#define      FLD_HLOCK_DIS            0x40000000
-#define      FLD_SEL_FIELD_CNT        0x20000000
-#define      FLD_CS_TYPE2_SEL         0x10000000
-#define      FLD_CS_LINE_THRSH_SEL    0x08000000
-#define      FLD_CS_ATHRESH_SEL       0x04000000
-#define      FLD_PSP_SPEC_SEL         0x02000000
-#define      FLD_PSP_LINES_SEL        0x01000000
-#define      FLD_FIELD_CNT            0x00f00000
-#define      FLD_CS_TYPE2_CNT         0x000fc000
-#define      FLD_CS_LINE_CNT          0x00003f00
-#define      FLD_CS_ATHRESH_LEV       0x000000ff
-
-/*****************************************************************************/
-#define      CHIP_VERSION             0x4b4
-/* Cx231xx redefine  */
-#define      VERSION                  0x4b4
-#define      FLD_REV_ID               0x000000ff
-
-/*****************************************************************************/
-#define      MISC_DIAG_CTRL           0x4b8
-/* Reserved [31:24] */
-#define      FLD_SC_CONVERGE_THRESH   0x00ff0000
-#define      FLD_CCOMB_ERR_LIMIT_3D   0x0000ff00
-#define      FLD_LCOMB_ERR_LIMIT_3D   0x000000ff
-
-/*****************************************************************************/
-#define      VBI_PASS_CTRL            0x4bc
-#define      FLD_VBI_PASS_MD          0x00200000
-#define      FLD_VBI_SETUP_DIS        0x00100000
-#define      FLD_PASS_LINE_CTRL       0x000fffff
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      VCR_DET_CTRL             0x4c0
-#define      FLD_EN_FIELD_PHASE_DET   0x80000000
-#define      FLD_EN_HEAD_SW_DET       0x40000000
-#define      FLD_FIELD_PHASE_LENGTH   0x01ff0000
-/* Reserved [29:25] */
-#define      FLD_FIELD_PHASE_DELAY    0x0000ff00
-#define      FLD_FIELD_PHASE_LIMIT    0x000000f0
-#define      FLD_HEAD_SW_DET_LIMIT    0x0000000f
-
-/*****************************************************************************/
-#define      DL_CTL                   0x800
-#define      DL_CTL_ADDRESS_LOW       0x800    /* Byte 1 in DL_CTL */
-#define      DL_CTL_ADDRESS_HIGH      0x801    /* Byte 2 in DL_CTL */
-#define      DL_CTL_DATA              0x802    /* Byte 3 in DL_CTL */
-#define      DL_CTL_CONTROL           0x803    /* Byte 4 in DL_CTL */
-/* Reserved [31:5] */
-#define      FLD_START_8051           0x10000000
-#define      FLD_DL_ENABLE            0x08000000
-#define      FLD_DL_AUTO_INC          0x04000000
-#define      FLD_DL_MAP               0x03000000
-
-/*****************************************************************************/
-#define      STD_DET_STATUS           0x804
-#define      FLD_SPARE_STATUS1        0xff000000
-#define      FLD_SPARE_STATUS0        0x00ff0000
-#define      FLD_MOD_DET_STATUS1      0x0000ff00
-#define      FLD_MOD_DET_STATUS0      0x000000ff
-
-/*****************************************************************************/
-#define      AUD_BUILD_NUM            0x806
-#define      AUD_VER_NUM              0x807
-#define      STD_DET_CTL              0x808
-#define      STD_DET_CTL_AUD_CTL      0x808    /* Byte 1 in STD_DET_CTL */
-#define      STD_DET_CTL_PREF_MODE    0x809    /* Byte 2 in STD_DET_CTL */
-#define      FLD_SPARE_CTL0           0xff000000
-#define      FLD_DIS_DBX              0x00800000
-#define      FLD_DIS_BTSC             0x00400000
-#define      FLD_DIS_NICAM_A2         0x00200000
-#define      FLD_VIDEO_PRESENT        0x00100000
-#define      FLD_DW8051_VIDEO_FORMAT  0x000f0000
-#define      FLD_PREF_DEC_MODE        0x0000ff00
-#define      FLD_AUD_CONFIG           0x000000ff
-
-/*****************************************************************************/
-#define      DW8051_INT               0x80c
-#define      FLD_VIDEO_PRESENT_CHANGE 0x80000000
-#define      FLD_VIDEO_CHANGE         0x40000000
-#define      FLD_RDS_READY            0x20000000
-#define      FLD_AC97_INT             0x10000000
-#define      FLD_NICAM_BIT_ERROR_TOO_HIGH         0x08000000
-#define      FLD_NICAM_LOCK           0x04000000
-#define      FLD_NICAM_UNLOCK         0x02000000
-#define      FLD_DFT4_TH_CMP          0x01000000
-/* Reserved [23:22] */
-#define      FLD_LOCK_IND_INT         0x00200000
-#define      FLD_DFT3_TH_CMP          0x00100000
-#define      FLD_DFT2_TH_CMP          0x00080000
-#define      FLD_DFT1_TH_CMP          0x00040000
-#define      FLD_FM2_DFT_TH_CMP       0x00020000
-#define      FLD_FM1_DFT_TH_CMP       0x00010000
-#define      FLD_VIDEO_PRESENT_EN     0x00008000
-#define      FLD_VIDEO_CHANGE_EN      0x00004000
-#define      FLD_RDS_READY_EN         0x00002000
-#define      FLD_AC97_INT_EN          0x00001000
-#define      FLD_NICAM_BIT_ERROR_TOO_HIGH_EN      0x00000800
-#define      FLD_NICAM_LOCK_EN        0x00000400
-#define      FLD_NICAM_UNLOCK_EN      0x00000200
-#define      FLD_DFT4_TH_CMP_EN       0x00000100
-/* Reserved [7] */
-#define      FLD_DW8051_INT6_CTL1     0x00000040
-#define      FLD_DW8051_INT5_CTL1     0x00000020
-#define      FLD_DW8051_INT4_CTL1     0x00000010
-#define      FLD_DW8051_INT3_CTL1     0x00000008
-#define      FLD_DW8051_INT2_CTL1     0x00000004
-#define      FLD_DW8051_INT1_CTL1     0x00000002
-#define      FLD_DW8051_INT0_CTL1     0x00000001
-
-/*****************************************************************************/
-#define      GENERAL_CTL              0x810
-#define      FLD_RDS_INT              0x80000000
-#define      FLD_NBER_INT             0x40000000
-#define      FLD_NLL_INT              0x20000000
-#define      FLD_IFL_INT              0x10000000
-#define      FLD_FDL_INT              0x08000000
-#define      FLD_AFC_INT              0x04000000
-#define      FLD_AMC_INT              0x02000000
-#define      FLD_AC97_INT_CTL         0x01000000
-#define      FLD_RDS_INT_DIS          0x00800000
-#define      FLD_NBER_INT_DIS         0x00400000
-#define      FLD_NLL_INT_DIS          0x00200000
-#define      FLD_IFL_INT_DIS          0x00100000
-#define      FLD_FDL_INT_DIS          0x00080000
-#define      FLD_FC_INT_DIS           0x00040000
-#define      FLD_AMC_INT_DIS          0x00020000
-#define      FLD_AC97_INT_DIS         0x00010000
-#define      FLD_REV_NUM              0x0000ff00
-/* Reserved [7:5] */
-#define      FLD_DBX_SOFT_RESET_REG   0x00000010
-#define      FLD_AD_SOFT_RESET_REG    0x00000008
-#define      FLD_SRC_SOFT_RESET_REG   0x00000004
-#define      FLD_CDMOD_SOFT_RESET     0x00000002
-#define      FLD_8051_SOFT_RESET      0x00000001
-
-/*****************************************************************************/
-#define      AAGC_CTL                 0x814
-#define      FLD_AFE_12DB_EN          0x80000000
-#define      FLD_AAGC_DEFAULT_EN      0x40000000
-#define      FLD_AAGC_DEFAULT         0x3f000000
-/* Reserved [23] */
-#define      FLD_AAGC_GAIN            0x00600000
-#define      FLD_AAGC_TH              0x001f0000
-/* Reserved [15:14] */
-#define      FLD_AAGC_HYST2           0x00003f00
-/* Reserved [7:6] */
-#define      FLD_AAGC_HYST1           0x0000003f
-
-/*****************************************************************************/
-#define      IF_SRC_CTL               0x818
-#define      FLD_DBX_BYPASS           0x80000000
-/* Reserved [30:25] */
-#define      FLD_IF_SRC_MODE          0x01000000
-/* Reserved [23:18] */
-#define      FLD_IF_SRC_PHASE_INC     0x0001ffff
-
-/*****************************************************************************/
-#define      ANALOG_DEMOD_CTL         0x81c
-#define      FLD_ROT1_PHACC_PROG      0xffff0000
-/* Reserved [15] */
-#define      FLD_FM1_DELAY_FIX        0x00007000
-#define      FLD_PDF4_SHIFT           0x00000c00
-#define      FLD_PDF3_SHIFT           0x00000300
-#define      FLD_PDF2_SHIFT           0x000000c0
-#define      FLD_PDF1_SHIFT           0x00000030
-#define      FLD_FMBYPASS_MODE2       0x00000008
-#define      FLD_FMBYPASS_MODE1       0x00000004
-#define      FLD_NICAM_MODE           0x00000002
-#define      FLD_BTSC_FMRADIO_MODE    0x00000001
-
-/*****************************************************************************/
-#define      ROT_FREQ_CTL             0x820
-#define      FLD_ROT3_PHACC_PROG      0xffff0000
-#define      FLD_ROT2_PHACC_PROG      0x0000ffff
-
-/*****************************************************************************/
-#define      FM_CTL                   0x824
-#define      FLD_FM2_DC_FB_SHIFT      0xf0000000
-#define      FLD_FM2_DC_INT_SHIFT     0x0f000000
-#define      FLD_FM2_AFC_RESET        0x00800000
-#define      FLD_FM2_DC_PASS_IN       0x00400000
-#define      FLD_FM2_DAGC_SHIFT       0x00380000
-#define      FLD_FM2_CORDIC_SHIFT     0x00070000
-#define      FLD_FM1_DC_FB_SHIFT      0x0000f000
-#define      FLD_FM1_DC_INT_SHIFT     0x00000f00
-#define      FLD_FM1_AFC_RESET        0x00000080
-#define      FLD_FM1_DC_PASS_IN       0x00000040
-#define      FLD_FM1_DAGC_SHIFT       0x00000038
-#define      FLD_FM1_CORDIC_SHIFT     0x00000007
-
-/*****************************************************************************/
-#define      LPF_PDF_CTL              0x828
-/* Reserved [31:30] */
-#define      FLD_LPF32_SHIFT1         0x30000000
-#define      FLD_LPF32_SHIFT2         0x0c000000
-#define      FLD_LPF160_SHIFTA        0x03000000
-#define      FLD_LPF160_SHIFTB        0x00c00000
-#define      FLD_LPF160_SHIFTC        0x00300000
-#define      FLD_LPF32_COEF_SEL2      0x000c0000
-#define      FLD_LPF32_COEF_SEL1      0x00030000
-#define      FLD_LPF160_COEF_SELC     0x0000c000
-#define      FLD_LPF160_COEF_SELB     0x00003000
-#define      FLD_LPF160_COEF_SELA     0x00000c00
-#define      FLD_LPF160_IN_EN_REG     0x00000300
-#define      FLD_PDF4_PDF_SEL         0x000000c0
-#define      FLD_PDF3_PDF_SEL         0x00000030
-#define      FLD_PDF2_PDF_SEL         0x0000000c
-#define      FLD_PDF1_PDF_SEL         0x00000003
-
-/*****************************************************************************/
-#define      DFT1_CTL1                0x82c
-#define      FLD_DFT1_DWELL           0xffff0000
-#define      FLD_DFT1_FREQ            0x0000ffff
-
-/*****************************************************************************/
-#define      DFT1_CTL2                0x830
-#define      FLD_DFT1_THRESHOLD       0xffffff00
-#define      FLD_DFT1_CMP_CTL         0x00000080
-#define      FLD_DFT1_AVG             0x00000070
-/* Reserved [3:1] */
-#define      FLD_DFT1_START           0x00000001
-
-/*****************************************************************************/
-#define      DFT1_STATUS              0x834
-#define      FLD_DFT1_DONE            0x80000000
-#define      FLD_DFT1_TH_CMP_STAT     0x40000000
-#define      FLD_DFT1_RESULT          0x3fffffff
-
-/*****************************************************************************/
-#define      DFT2_CTL1                0x838
-#define      FLD_DFT2_DWELL           0xffff0000
-#define      FLD_DFT2_FREQ            0x0000ffff
-
-/*****************************************************************************/
-#define      DFT2_CTL2                0x83C
-#define      FLD_DFT2_THRESHOLD       0xffffff00
-#define      FLD_DFT2_CMP_CTL         0x00000080
-#define      FLD_DFT2_AVG             0x00000070
-/* Reserved [3:1] */
-#define      FLD_DFT2_START           0x00000001
-
-/*****************************************************************************/
-#define      DFT2_STATUS              0x840
-#define      FLD_DFT2_DONE            0x80000000
-#define      FLD_DFT2_TH_CMP_STAT     0x40000000
-#define      FLD_DFT2_RESULT          0x3fffffff
-
-/*****************************************************************************/
-#define      DFT3_CTL1                0x844
-#define      FLD_DFT3_DWELL           0xffff0000
-#define      FLD_DFT3_FREQ            0x0000ffff
-
-/*****************************************************************************/
-#define      DFT3_CTL2                0x848
-#define      FLD_DFT3_THRESHOLD       0xffffff00
-#define      FLD_DFT3_CMP_CTL         0x00000080
-#define      FLD_DFT3_AVG             0x00000070
-/* Reserved [3:1] */
-#define      FLD_DFT3_START           0x00000001
-
-/*****************************************************************************/
-#define      DFT3_STATUS              0x84c
-#define      FLD_DFT3_DONE            0x80000000
-#define      FLD_DFT3_TH_CMP_STAT     0x40000000
-#define      FLD_DFT3_RESULT          0x3fffffff
-
-/*****************************************************************************/
-#define      DFT4_CTL1                0x850
-#define      FLD_DFT4_DWELL           0xffff0000
-#define      FLD_DFT4_FREQ            0x0000ffff
-
-/*****************************************************************************/
-#define      DFT4_CTL2                0x854
-#define      FLD_DFT4_THRESHOLD       0xffffff00
-#define      FLD_DFT4_CMP_CTL         0x00000080
-#define      FLD_DFT4_AVG             0x00000070
-/* Reserved [3:1] */
-#define      FLD_DFT4_START           0x00000001
-
-/*****************************************************************************/
-#define      DFT4_STATUS              0x858
-#define      FLD_DFT4_DONE            0x80000000
-#define      FLD_DFT4_TH_CMP_STAT     0x40000000
-#define      FLD_DFT4_RESULT          0x3fffffff
-
-/*****************************************************************************/
-#define      AM_MTS_DET               0x85c
-#define      FLD_AM_MTS_MODE          0x80000000
-/* Reserved [30:26] */
-#define      FLD_AM_SUB               0x02000000
-#define      FLD_AM_GAIN_EN           0x01000000
-/* Reserved [23:16] */
-#define      FLD_AMMTS_GAIN_SCALE     0x0000e000
-#define      FLD_MTS_PDF_SHIFT        0x00001800
-#define      FLD_AM_REG_GAIN          0x00000700
-#define      FLD_AGC_REF              0x000000ff
-
-/*****************************************************************************/
-#define      ANALOG_MUX_CTL           0x860
-/* Reserved [31:29] */
-#define      FLD_MUX21_SEL            0x10000000
-#define      FLD_MUX20_SEL            0x08000000
-#define      FLD_MUX19_SEL            0x04000000
-#define      FLD_MUX18_SEL            0x02000000
-#define      FLD_MUX17_SEL            0x01000000
-#define      FLD_MUX16_SEL            0x00800000
-#define      FLD_MUX15_SEL            0x00400000
-#define      FLD_MUX14_SEL            0x00300000
-#define      FLD_MUX13_SEL            0x000C0000
-#define      FLD_MUX12_SEL            0x00020000
-#define      FLD_MUX11_SEL            0x00018000
-#define      FLD_MUX10_SEL            0x00004000
-#define      FLD_MUX9_SEL             0x00002000
-#define      FLD_MUX8_SEL             0x00001000
-#define      FLD_MUX7_SEL             0x00000800
-#define      FLD_MUX6_SEL             0x00000600
-#define      FLD_MUX5_SEL             0x00000100
-#define      FLD_MUX4_SEL             0x000000c0
-#define      FLD_MUX3_SEL             0x00000030
-#define      FLD_MUX2_SEL             0x0000000c
-#define      FLD_MUX1_SEL             0x00000003
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      DPLL_CTRL1               0x864
-#define      DIG_PLL_CTL1             0x864
-
-#define      FLD_PLL_STATUS           0x07000000
-#define      FLD_BANDWIDTH_SELECT     0x00030000
-#define      FLD_PLL_SHIFT_REG        0x00007000
-#define      FLD_PHASE_SHIFT          0x000007ff
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      DPLL_CTRL2               0x868
-#define      DIG_PLL_CTL2             0x868
-#define      FLD_PLL_UNLOCK_THR       0xff000000
-#define      FLD_PLL_LOCK_THR         0x00ff0000
-/* Reserved [15:8] */
-#define      FLD_AM_PDF_SEL2          0x000000c0
-#define      FLD_AM_PDF_SEL1          0x00000030
-#define      FLD_DPLL_FSM_CTRL        0x0000000c
-/* Reserved [1] */
-#define      FLD_PLL_PILOT_DET        0x00000001
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      DPLL_CTRL3               0x86c
-#define      DIG_PLL_CTL3             0x86c
-#define      FLD_DISABLE_LOOP         0x01000000
-#define      FLD_A1_DS1_SEL           0x000c0000
-#define      FLD_A1_DS2_SEL           0x00030000
-#define      FLD_A1_KI                0x0000ff00
-#define      FLD_A1_KD                0x000000ff
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      DPLL_CTRL4               0x870
-#define      DIG_PLL_CTL4             0x870
-#define      FLD_A2_DS1_SEL           0x000c0000
-#define      FLD_A2_DS2_SEL           0x00030000
-#define      FLD_A2_KI                0x0000ff00
-#define      FLD_A2_KD                0x000000ff
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      DPLL_CTRL5               0x874
-#define      DIG_PLL_CTL5             0x874
-#define      FLD_TRK_DS1_SEL          0x000c0000
-#define      FLD_TRK_DS2_SEL          0x00030000
-#define      FLD_TRK_KI               0x0000ff00
-#define      FLD_TRK_KD               0x000000ff
-
-/*****************************************************************************/
-#define      DEEMPH_GAIN_CTL          0x878
-#define      FLD_DEEMPH2_GAIN         0xFFFF0000
-#define      FLD_DEEMPH1_GAIN         0x0000FFFF
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      DEEMPH_COEFF1            0x87c
-#define      DEEMPH_COEF1             0x87c
-#define      FLD_DEEMPH_B0            0xffff0000
-#define      FLD_DEEMPH_A0            0x0000ffff
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      DEEMPH_COEFF2            0x880
-#define      DEEMPH_COEF2             0x880
-#define      FLD_DEEMPH_B1            0xFFFF0000
-#define      FLD_DEEMPH_A1            0x0000FFFF
-
-/*****************************************************************************/
-#define      DBX1_CTL1                0x884
-#define      FLD_DBX1_WBE_GAIN        0xffff0000
-#define      FLD_DBX1_IN_GAIN         0x0000ffff
-
-/*****************************************************************************/
-#define      DBX1_CTL2                0x888
-#define      FLD_DBX1_SE_BYPASS       0xffff0000
-#define      FLD_DBX1_SE_GAIN         0x0000ffff
-
-/*****************************************************************************/
-#define      DBX1_RMS_SE              0x88C
-#define      FLD_DBX1_RMS_WBE         0xffff0000
-#define      FLD_DBX1_RMS_SE_FLD      0x0000ffff
-
-/*****************************************************************************/
-#define      DBX2_CTL1                0x890
-#define      FLD_DBX2_WBE_GAIN        0xffff0000
-#define      FLD_DBX2_IN_GAIN         0x0000ffff
-
-/*****************************************************************************/
-#define      DBX2_CTL2                0x894
-#define      FLD_DBX2_SE_BYPASS       0xffff0000
-#define      FLD_DBX2_SE_GAIN         0x0000ffff
-
-/*****************************************************************************/
-#define      DBX2_RMS_SE              0x898
-#define      FLD_DBX2_RMS_WBE         0xffff0000
-#define      FLD_DBX2_RMS_SE_FLD      0x0000ffff
-
-/*****************************************************************************/
-#define      AM_FM_DIFF               0x89c
-/* Reserved [31] */
-#define      FLD_FM_DIFF_OUT          0x7fff0000
-/* Reserved [15] */
-#define      FLD_AM_DIFF_OUT          0x00007fff
-
-/*****************************************************************************/
-#define      NICAM_FAW                0x8a0
-#define      FLD_FAWDETWINEND         0xFc000000
-#define      FLD_FAWDETWINSTR         0x03ff0000
-/* Reserved [15:12] */
-#define      FLD_FAWDETTHRSHLD3       0x00000f00
-#define      FLD_FAWDETTHRSHLD2       0x000000f0
-#define      FLD_FAWDETTHRSHLD1       0x0000000f
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      DEEMPH_GAIN              0x8a4
-#define      NICAM_DEEMPHGAIN         0x8a4
-/* Reserved [31:18] */
-#define      FLD_DEEMPHGAIN           0x0003ffff
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      DEEMPH_NUMER1            0x8a8
-#define      NICAM_DEEMPHNUMER1       0x8a8
-/* Reserved [31:18] */
-#define      FLD_DEEMPHNUMER1         0x0003ffff
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      DEEMPH_NUMER2            0x8ac
-#define      NICAM_DEEMPHNUMER2       0x8ac
-/* Reserved [31:18] */
-#define      FLD_DEEMPHNUMER2         0x0003ffff
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      DEEMPH_DENOM1            0x8b0
-#define      NICAM_DEEMPHDENOM1       0x8b0
-/* Reserved [31:18] */
-#define      FLD_DEEMPHDENOM1         0x0003ffff
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      DEEMPH_DENOM2            0x8b4
-#define      NICAM_DEEMPHDENOM2       0x8b4
-/* Reserved [31:18] */
-#define      FLD_DEEMPHDENOM2         0x0003ffff
-
-/*****************************************************************************/
-#define      NICAM_ERRLOG_CTL1        0x8B8
-/* Reserved [31:28] */
-#define      FLD_ERRINTRPTTHSHLD1     0x0fff0000
-/* Reserved [15:12] */
-#define      FLD_ERRLOGPERIOD         0x00000fff
-
-/*****************************************************************************/
-#define      NICAM_ERRLOG_CTL2        0x8bc
-/* Reserved [31:28] */
-#define      FLD_ERRINTRPTTHSHLD3     0x0fff0000
-/* Reserved [15:12] */
-#define      FLD_ERRINTRPTTHSHLD2     0x00000fff
-
-/*****************************************************************************/
-#define      NICAM_ERRLOG_STS1        0x8c0
-/* Reserved [31:28] */
-#define      FLD_ERRLOG2              0x0fff0000
-/* Reserved [15:12] */
-#define      FLD_ERRLOG1              0x00000fff
-
-/*****************************************************************************/
-#define      NICAM_ERRLOG_STS2        0x8c4
-/* Reserved [31:12] */
-#define      FLD_ERRLOG3              0x00000fff
-
-/*****************************************************************************/
-#define      NICAM_STATUS             0x8c8
-/* Reserved [31:20] */
-#define      FLD_NICAM_CIB            0x000c0000
-#define      FLD_NICAM_LOCK_STAT      0x00020000
-#define      FLD_NICAM_MUTE           0x00010000
-#define      FLD_NICAMADDIT_DATA      0x0000ffe0
-#define      FLD_NICAMCNTRL           0x0000001f
-
-/*****************************************************************************/
-#define      DEMATRIX_CTL             0x8cc
-#define      FLD_AC97_IN_SHIFT        0xf0000000
-#define      FLD_I2S_IN_SHIFT         0x0f000000
-#define      FLD_DEMATRIX_SEL_CTL     0x00ff0000
-/* Reserved [15:11] */
-#define      FLD_DMTRX_BYPASS         0x00000400
-#define      FLD_DEMATRIX_MODE        0x00000300
-/* Reserved [7:6] */
-#define      FLD_PH_DBX_SEL           0x00000020
-#define      FLD_PH_CH_SEL            0x00000010
-#define      FLD_PHASE_FIX            0x0000000f
-
-/*****************************************************************************/
-#define      PATH1_CTL1               0x8d0
-/* Reserved [31:29] */
-#define      FLD_PATH1_MUTE_CTL       0x1f000000
-/* Reserved [23:22] */
-#define      FLD_PATH1_AVC_CG         0x00300000
-#define      FLD_PATH1_AVC_RT         0x000f0000
-#define      FLD_PATH1_AVC_AT         0x0000f000
-#define      FLD_PATH1_AVC_STEREO     0x00000800
-#define      FLD_PATH1_AVC_CR         0x00000700
-#define      FLD_PATH1_AVC_RMS_CON    0x000000f0
-#define      FLD_PATH1_SEL_CTL        0x0000000f
-
-/*****************************************************************************/
-#define      PATH1_VOL_CTL            0x8d4
-#define      FLD_PATH1_AVC_THRESHOLD  0x7fff0000
-#define      FLD_PATH1_BAL_LEFT       0x00008000
-#define      FLD_PATH1_BAL_LEVEL      0x00007f00
-#define      FLD_PATH1_VOLUME         0x000000ff
-
-/*****************************************************************************/
-#define      PATH1_EQ_CTL             0x8d8
-/* Reserved [31:30] */
-#define      FLD_PATH1_EQ_TREBLE_VOL  0x3f000000
-/* Reserved [23:22] */
-#define      FLD_PATH1_EQ_MID_VOL     0x003f0000
-/* Reserved [15:14] */
-#define      FLD_PATH1_EQ_BASS_VOL    0x00003f00
-/* Reserved [7:1] */
-#define      FLD_PATH1_EQ_BAND_SEL    0x00000001
-
-/*****************************************************************************/
-#define      PATH1_SC_CTL             0x8dc
-#define      FLD_PATH1_SC_THRESHOLD   0x7fff0000
-#define      FLD_PATH1_SC_RT          0x0000f000
-#define      FLD_PATH1_SC_AT          0x00000f00
-#define      FLD_PATH1_SC_STEREO      0x00000080
-#define      FLD_PATH1_SC_CR          0x00000070
-#define      FLD_PATH1_SC_RMS_CON     0x0000000f
-
-/*****************************************************************************/
-#define      PATH2_CTL1               0x8e0
-/* Reserved [31:26] */
-#define      FLD_PATH2_MUTE_CTL       0x03000000
-/* Reserved [23:22] */
-#define      FLD_PATH2_AVC_CG         0x00300000
-#define      FLD_PATH2_AVC_RT         0x000f0000
-#define      FLD_PATH2_AVC_AT         0x0000f000
-#define      FLD_PATH2_AVC_STEREO     0x00000800
-#define      FLD_PATH2_AVC_CR         0x00000700
-#define      FLD_PATH2_AVC_RMS_CON    0x000000f0
-#define      FLD_PATH2_SEL_CTL        0x0000000f
-
-/*****************************************************************************/
-#define      PATH2_VOL_CTL            0x8e4
-#define      FLD_PATH2_AVC_THRESHOLD  0xffff0000
-#define      FLD_PATH2_BAL_LEFT       0x00008000
-#define      FLD_PATH2_BAL_LEVEL      0x00007f00
-#define      FLD_PATH2_VOLUME         0x000000ff
-
-/*****************************************************************************/
-#define      PATH2_EQ_CTL             0x8e8
-/* Reserved [31:30] */
-#define      FLD_PATH2_EQ_TREBLE_VOL  0x3f000000
-/* Reserved [23:22] */
-#define      FLD_PATH2_EQ_MID_VOL     0x003f0000
-/* Reserved [15:14] */
-#define      FLD_PATH2_EQ_BASS_VOL    0x00003f00
-/* Reserved [7:1] */
-#define      FLD_PATH2_EQ_BAND_SEL    0x00000001
-
-/*****************************************************************************/
-#define      PATH2_SC_CTL             0x8eC
-#define      FLD_PATH2_SC_THRESHOLD   0xffff0000
-#define      FLD_PATH2_SC_RT          0x0000f000
-#define      FLD_PATH2_SC_AT          0x00000f00
-#define      FLD_PATH2_SC_STEREO      0x00000080
-#define      FLD_PATH2_SC_CR          0x00000070
-#define      FLD_PATH2_SC_RMS_CON     0x0000000f
-
-/*****************************************************************************/
-#define      SRC_CTL                  0x8f0
-#define      FLD_SRC_STATUS           0xffffff00
-#define      FLD_FIFO_LF_EN           0x000000fc
-#define      FLD_BYPASS_LI            0x00000002
-#define      FLD_BYPASS_PF            0x00000001
-
-/*****************************************************************************/
-#define      SRC_LF_COEF              0x8f4
-#define      FLD_LOOP_FILTER_COEF2    0xffff0000
-#define      FLD_LOOP_FILTER_COEF1    0x0000ffff
-
-/*****************************************************************************/
-#define      SRC1_CTL                 0x8f8
-/* Reserved [31:28] */
-#define      FLD_SRC1_FIFO_RD_TH      0x0f000000
-/* Reserved [23:18] */
-#define      FLD_SRC1_PHASE_INC       0x0003ffff
-
-/*****************************************************************************/
-#define      SRC2_CTL                 0x8fc
-/* Reserved [31:28] */
-#define      FLD_SRC2_FIFO_RD_TH      0x0f000000
-/* Reserved [23:18] */
-#define      FLD_SRC2_PHASE_INC       0x0003ffff
-
-/*****************************************************************************/
-#define      SRC3_CTL                 0x900
-/* Reserved [31:28] */
-#define      FLD_SRC3_FIFO_RD_TH      0x0f000000
-/* Reserved [23:18] */
-#define      FLD_SRC3_PHASE_INC       0x0003ffff
-
-/*****************************************************************************/
-#define      SRC4_CTL                 0x904
-/* Reserved [31:28] */
-#define      FLD_SRC4_FIFO_RD_TH      0x0f000000
-/* Reserved [23:18] */
-#define      FLD_SRC4_PHASE_INC       0x0003ffff
-
-/*****************************************************************************/
-#define      SRC5_CTL                 0x908
-/* Reserved [31:28] */
-#define      FLD_SRC5_FIFO_RD_TH      0x0f000000
-/* Reserved [23:18] */
-#define      FLD_SRC5_PHASE_INC       0x0003ffff
-
-/*****************************************************************************/
-#define      SRC6_CTL                 0x90c
-/* Reserved [31:28] */
-#define      FLD_SRC6_FIFO_RD_TH      0x0f000000
-/* Reserved [23:18] */
-#define      FLD_SRC6_PHASE_INC       0x0003ffff
-
-/*****************************************************************************/
-#define      BAND_OUT_SEL             0x910
-#define      FLD_SRC6_IN_SEL          0xc0000000
-#define      FLD_SRC6_CLK_SEL         0x30000000
-#define      FLD_SRC5_IN_SEL          0x0c000000
-#define      FLD_SRC5_CLK_SEL         0x03000000
-#define      FLD_SRC4_IN_SEL          0x00c00000
-#define      FLD_SRC4_CLK_SEL         0x00300000
-#define      FLD_SRC3_IN_SEL          0x000c0000
-#define      FLD_SRC3_CLK_SEL         0x00030000
-#define      FLD_BASEBAND_BYPASS_CTL  0x0000ff00
-#define      FLD_AC97_SRC_SEL         0x000000c0
-#define      FLD_I2S_SRC_SEL          0x00000030
-#define      FLD_PARALLEL2_SRC_SEL    0x0000000c
-#define      FLD_PARALLEL1_SRC_SEL    0x00000003
-
-/*****************************************************************************/
-#define      I2S_IN_CTL               0x914
-/* Reserved [31:11] */
-#define      FLD_I2S_UP2X_BW20K       0x00000400
-#define      FLD_I2S_UP2X_BYPASS      0x00000200
-#define      FLD_I2S_IN_MASTER_MODE   0x00000100
-#define      FLD_I2S_IN_SONY_MODE     0x00000080
-#define      FLD_I2S_IN_RIGHT_JUST    0x00000040
-#define      FLD_I2S_IN_WS_SEL        0x00000020
-#define      FLD_I2S_IN_BCN_DEL       0x0000001f
-
-/*****************************************************************************/
-#define      I2S_OUT_CTL              0x918
-/* Reserved [31:17] */
-#define      FLD_I2S_OUT_SOFT_RESET_EN  0x00010000
-/* Reserved [15:9] */
-#define      FLD_I2S_OUT_MASTER_MODE  0x00000100
-#define      FLD_I2S_OUT_SONY_MODE    0x00000080
-#define      FLD_I2S_OUT_RIGHT_JUST   0x00000040
-#define      FLD_I2S_OUT_WS_SEL       0x00000020
-#define      FLD_I2S_OUT_BCN_DEL      0x0000001f
-
-/*****************************************************************************/
-#define      AC97_CTL                 0x91c
-/* Reserved [31:26] */
-#define      FLD_AC97_UP2X_BW20K      0x02000000
-#define      FLD_AC97_UP2X_BYPASS     0x01000000
-/* Reserved [23:17] */
-#define      FLD_AC97_RST_ACL         0x00010000
-/* Reserved [15:9] */
-#define      FLD_AC97_WAKE_UP_SYNC    0x00000100
-/* Reserved [7:1] */
-#define      FLD_AC97_SHUTDOWN        0x00000001
-
-/* Cx231xx redefine */
-#define      QPSK_IAGC_CTL1            0x94c
-#define      QPSK_IAGC_CTL2            0x950
-#define      QPSK_FEPR_FREQ            0x954
-#define      QPSK_BTL_CTL1             0x958
-#define      QPSK_BTL_CTL2             0x95c
-#define      QPSK_CTL_CTL1             0x960
-#define      QPSK_CTL_CTL2             0x964
-#define      QPSK_MF_FAGC_CTL          0x968
-#define      QPSK_EQ_CTL               0x96c
-#define      QPSK_LOCK_CTL             0x970
-
-/*****************************************************************************/
-#define      FM1_DFT_CTL              0x9a8
-#define      FLD_FM1_DFT_THRESHOLD    0xffff0000
-/* Reserved [15:8] */
-#define      FLD_FM1_DFT_CMP_CTL      0x00000080
-#define      FLD_FM1_DFT_AVG          0x00000070
-/* Reserved [3:1] */
-#define      FLD_FM1_DFT_START        0x00000001
-
-/*****************************************************************************/
-#define      FM1_DFT_STATUS           0x9ac
-#define      FLD_FM1_DFT_DONE         0x80000000
-/* Reserved [30:19] */
-#define      FLD_FM_DFT_TH_CMP        0x00040000
-#define      FLD_FM1_DFT              0x0003ffff
-
-/*****************************************************************************/
-#define      FM2_DFT_CTL              0x9b0
-#define      FLD_FM2_DFT_THRESHOLD    0xffff0000
-/* Reserved [15:8] */
-#define      FLD_FM2_DFT_CMP_CTL      0x00000080
-#define      FLD_FM2_DFT_AVG          0x00000070
-/* Reserved [3:1] */
-#define      FLD_FM2_DFT_START        0x00000001
-
-/*****************************************************************************/
-#define      FM2_DFT_STATUS           0x9b4
-#define      FLD_FM2_DFT_DONE         0x80000000
-/* Reserved [30:19] */
-#define      FLD_FM2_DFT_TH_CMP_STAT  0x00040000
-#define      FLD_FM2_DFT              0x0003ffff
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      AAGC_STATUS_REG          0x9b8
-#define      AAGC_STATUS              0x9b8
-/* Reserved [31:27] */
-#define      FLD_FM2_DAGC_OUT         0x07000000
-/* Reserved [23:19] */
-#define      FLD_FM1_DAGC_OUT         0x00070000
-/* Reserved [15:6] */
-#define      FLD_AFE_VGA_OUT          0x0000003f
-
-/*****************************************************************************/
-#define      MTS_GAIN_STATUS          0x9bc
-/* Reserved [31:14] */
-#define      FLD_MTS_GAIN             0x00003fff
-
-#define      RDS_OUT                  0x9c0
-#define      FLD_RDS_Q                0xffff0000
-#define      FLD_RDS_I                0x0000ffff
-
-/*****************************************************************************/
-#define      AUTOCONFIG_REG           0x9c4
-/* Reserved [31:4] */
-#define      FLD_AUTOCONFIG_MODE      0x0000000f
-
-#define      FM_AFC                   0x9c8
-#define      FLD_FM2_AFC              0xffff0000
-#define      FLD_FM1_AFC              0x0000ffff
-
-/*****************************************************************************/
-/* Cx231xx redefine */
-#define      NEW_SPARE                0x9cc
-#define      NEW_SPARE_REG            0x9cc
-
-/*****************************************************************************/
-#define      DBX_ADJ                  0x9d0
-/* Reserved [31:28] */
-#define      FLD_DBX2_ADJ             0x0fff0000
-/* Reserved [15:12] */
-#define      FLD_DBX1_ADJ             0x00000fff
-
-#define      VID_FMT_AUTO              0
-#define      VID_FMT_NTSC_M            1
-#define      VID_FMT_NTSC_J            2
-#define      VID_FMT_NTSC_443          3
-#define      VID_FMT_PAL_BDGHI         4
-#define      VID_FMT_PAL_M             5
-#define      VID_FMT_PAL_N             6
-#define      VID_FMT_PAL_NC            7
-#define      VID_FMT_PAL_60            8
-#define      VID_FMT_SECAM             12
-#define      VID_FMT_SECAM_60          13
-
-#define      INPUT_MODE_CVBS_0         0       /* INPUT_MODE_VALUE(0) */
-#define      INPUT_MODE_YC_1           1       /* INPUT_MODE_VALUE(1) */
-#define      INPUT_MODE_YC2_2          2       /* INPUT_MODE_VALUE(2) */
-#define      INPUT_MODE_YUV_3          3       /* INPUT_MODE_VALUE(3) */
-
-#define      LUMA_LPF_LOW_BANDPASS     0       /* 0.6Mhz LPF BW */
-#define      LUMA_LPF_MEDIUM_BANDPASS  1       /* 1.0Mhz LPF BW */
-#define      LUMA_LPF_HIGH_BANDPASS    2       /* 1.5Mhz LPF BW */
-
-#define      UV_LPF_LOW_BANDPASS       0       /* 0.6Mhz LPF BW */
-#define      UV_LPF_MEDIUM_BANDPASS    1       /* 1.0Mhz LPF BW */
-#define      UV_LPF_HIGH_BANDPASS      2       /* 1.5Mhz LPF BW */
-
-#define      TWO_TAP_FILT              0
-#define      THREE_TAP_FILT            1
-#define      FOUR_TAP_FILT             2
-#define      FIVE_TAP_FILT             3
-
-#define      AUD_CHAN_SRC_PARALLEL     0
-#define      AUD_CHAN_SRC_I2S_INPUT    1
-#define      AUD_CHAN_SRC_FLATIRON     2
-#define      AUD_CHAN_SRC_PARALLEL3    3
-
-#define      OUT_MODE_601              0
-#define      OUT_MODE_656              1
-#define      OUT_MODE_VIP11            2
-#define      OUT_MODE_VIP20            3
-
-#define      PHASE_INC_49MHZ          0x0df22
-#define      PHASE_INC_56MHZ          0x0fa5b
-#define      PHASE_INC_28MHZ          0x010000
-
-#endif
diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c
deleted file mode 100644 (file)
index ac7db52..0000000
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
-   cx231xx_vbi.c - driver for Conexant Cx23100/101/102 USB video capture devices
-
-   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
-       Based on cx88 driver
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   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/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 <linux/mm.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-chip-ident.h>
-#include <media/msp3400.h>
-#include <media/tuner.h>
-
-#include "cx231xx.h"
-#include "cx231xx-vbi.h"
-
-static inline void print_err_status(struct cx231xx *dev, int packet, int status)
-{
-       char *errmsg = "Unknown";
-
-       switch (status) {
-       case -ENOENT:
-               errmsg = "unlinked synchronuously";
-               break;
-       case -ECONNRESET:
-               errmsg = "unlinked asynchronuously";
-               break;
-       case -ENOSR:
-               errmsg = "Buffer error (overrun)";
-               break;
-       case -EPIPE:
-               errmsg = "Stalled (device not responding)";
-               break;
-       case -EOVERFLOW:
-               errmsg = "Babble (bad cable?)";
-               break;
-       case -EPROTO:
-               errmsg = "Bit-stuff error (bad cable?)";
-               break;
-       case -EILSEQ:
-               errmsg = "CRC/Timeout (could be anything)";
-               break;
-       case -ETIME:
-               errmsg = "Device does not respond";
-               break;
-       }
-       if (packet < 0) {
-               cx231xx_err(DRIVER_NAME "URB status %d [%s].\n", status,
-                           errmsg);
-       } else {
-               cx231xx_err(DRIVER_NAME "URB packet %d, status %d [%s].\n",
-                           packet, status, errmsg);
-       }
-}
-
-/*
- * Controls the isoc copy of each urb packet
- */
-static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb)
-{
-       struct cx231xx_dmaqueue *dma_q = urb->context;
-       int rc = 1;
-       unsigned char *p_buffer;
-       u32 bytes_parsed = 0, buffer_size = 0;
-       u8 sav_eav = 0;
-
-       if (!dev)
-               return 0;
-
-       if (dev->state & DEV_DISCONNECTED)
-               return 0;
-
-       if (urb->status < 0) {
-               print_err_status(dev, -1, urb->status);
-               if (urb->status == -ENOENT)
-                       return 0;
-       }
-
-       /* get buffer pointer and length */
-       p_buffer = urb->transfer_buffer;
-       buffer_size = urb->actual_length;
-
-       if (buffer_size > 0) {
-               bytes_parsed = 0;
-
-               if (dma_q->is_partial_line) {
-                       /* Handle the case where we were working on a partial
-                          line */
-                       sav_eav = dma_q->last_sav;
-               } else {
-                       /* Check for a SAV/EAV overlapping the
-                          buffer boundary */
-
-                       sav_eav = cx231xx_find_boundary_SAV_EAV(p_buffer,
-                                                         dma_q->partial_buf,
-                                                         &bytes_parsed);
-               }
-
-               sav_eav &= 0xF0;
-               /* Get the first line if we have some portion of an SAV/EAV from
-                  the last buffer or a partial line */
-               if (sav_eav) {
-                       bytes_parsed += cx231xx_get_vbi_line(dev, dma_q,
-                               sav_eav,                       /* SAV/EAV */
-                               p_buffer + bytes_parsed,       /* p_buffer */
-                               buffer_size - bytes_parsed);   /* buffer size */
-               }
-
-               /* Now parse data that is completely in this buffer */
-               dma_q->is_partial_line = 0;
-
-               while (bytes_parsed < buffer_size) {
-                       u32 bytes_used = 0;
-
-                       sav_eav = cx231xx_find_next_SAV_EAV(
-                               p_buffer + bytes_parsed,        /* p_buffer */
-                               buffer_size - bytes_parsed, /* buffer size */
-                               &bytes_used);   /* bytes used to get SAV/EAV */
-
-                       bytes_parsed += bytes_used;
-
-                       sav_eav &= 0xF0;
-                       if (sav_eav && (bytes_parsed < buffer_size)) {
-                               bytes_parsed += cx231xx_get_vbi_line(dev,
-                                       dma_q, sav_eav, /* SAV/EAV */
-                                       p_buffer+bytes_parsed, /* p_buffer */
-                                       buffer_size-bytes_parsed);/*buf size*/
-                       }
-               }
-
-               /* Save the last four bytes of the buffer so we can
-               check the buffer boundary condition next time */
-               memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4);
-               bytes_parsed = 0;
-       }
-
-       return rc;
-}
-
-/* ------------------------------------------------------------------
-       Vbi buf operations
-   ------------------------------------------------------------------*/
-
-static int
-vbi_buffer_setup(struct videobuf_queue *vq, unsigned int *count,
-                unsigned int *size)
-{
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *dev = fh->dev;
-       u32 height = 0;
-
-       height = ((dev->norm & V4L2_STD_625_50) ?
-                 PAL_VBI_LINES : NTSC_VBI_LINES);
-
-       *size = (dev->width * height * 2 * 2);
-       if (0 == *count)
-               *count = CX231XX_DEF_VBI_BUF;
-
-       if (*count < CX231XX_MIN_BUF)
-               *count = CX231XX_MIN_BUF;
-
-       return 0;
-}
-
-/* This is called *without* dev->slock held; please keep it that way */
-static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
-{
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *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->vbi_mode.slock, flags);
-       if (dev->vbi_mode.bulk_ctl.buf == buf)
-               dev->vbi_mode.bulk_ctl.buf = NULL;
-       spin_unlock_irqrestore(&dev->vbi_mode.slock, flags);
-
-       videobuf_vmalloc_free(&buf->vb);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int
-vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
-                  enum v4l2_field field)
-{
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       struct cx231xx *dev = fh->dev;
-       int rc = 0, urb_init = 0;
-       u32 height = 0;
-
-       height = ((dev->norm & V4L2_STD_625_50) ?
-                 PAL_VBI_LINES : NTSC_VBI_LINES);
-       buf->vb.size = ((dev->width << 1) * height * 2);
-
-       if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
-               return -EINVAL;
-
-       buf->vb.width = dev->width;
-       buf->vb.height = height;
-       buf->vb.field = field;
-       buf->vb.field = V4L2_FIELD_SEQ_TB;
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               rc = videobuf_iolock(vq, &buf->vb, NULL);
-               if (rc < 0)
-                       goto fail;
-       }
-
-       if (!dev->vbi_mode.bulk_ctl.num_bufs)
-               urb_init = 1;
-
-       if (urb_init) {
-               rc = cx231xx_init_vbi_isoc(dev, CX231XX_NUM_VBI_PACKETS,
-                                          CX231XX_NUM_VBI_BUFS,
-                                          dev->vbi_mode.alt_max_pkt_size[0],
-                                          cx231xx_isoc_vbi_copy);
-               if (rc < 0)
-                       goto fail;
-       }
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
-fail:
-       free_buffer(vq, buf);
-       return rc;
-}
-
-static void
-vbi_buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *dev = fh->dev;
-       struct cx231xx_dmaqueue *vidq = &dev->vbi_mode.vidq;
-
-       buf->vb.state = VIDEOBUF_QUEUED;
-       list_add_tail(&buf->vb.queue, &vidq->active);
-
-}
-
-static void vbi_buffer_release(struct videobuf_queue *vq,
-                              struct videobuf_buffer *vb)
-{
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-
-
-       free_buffer(vq, buf);
-}
-
-struct videobuf_queue_ops cx231xx_vbi_qops = {
-       .buf_setup   = vbi_buffer_setup,
-       .buf_prepare = vbi_buffer_prepare,
-       .buf_queue   = vbi_buffer_queue,
-       .buf_release = vbi_buffer_release,
-};
-
-/* ------------------------------------------------------------------
-       URB control
-   ------------------------------------------------------------------*/
-
-/*
- * IRQ callback, called by URB callback
- */
-static void cx231xx_irq_vbi_callback(struct urb *urb)
-{
-       struct cx231xx_dmaqueue *dma_q = urb->context;
-       struct cx231xx_video_mode *vmode =
-           container_of(dma_q, struct cx231xx_video_mode, vidq);
-       struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode);
-
-       switch (urb->status) {
-       case 0:         /* success */
-       case -ETIMEDOUT:        /* NAK */
-               break;
-       case -ECONNRESET:       /* kill */
-       case -ENOENT:
-       case -ESHUTDOWN:
-               return;
-       default:                /* error */
-               cx231xx_err(DRIVER_NAME "urb completition error %d.\n",
-                           urb->status);
-               break;
-       }
-
-       /* Copy data from URB */
-       spin_lock(&dev->vbi_mode.slock);
-       dev->vbi_mode.bulk_ctl.bulk_copy(dev, urb);
-       spin_unlock(&dev->vbi_mode.slock);
-
-       /* Reset status */
-       urb->status = 0;
-
-       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (urb->status) {
-               cx231xx_err(DRIVER_NAME "urb resubmit failed (error=%i)\n",
-                           urb->status);
-       }
-}
-
-/*
- * Stop and Deallocate URBs
- */
-void cx231xx_uninit_vbi_isoc(struct cx231xx *dev)
-{
-       struct urb *urb;
-       int i;
-
-       cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_uninit_vbi_isoc\n");
-
-       dev->vbi_mode.bulk_ctl.nfields = -1;
-       for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
-               urb = dev->vbi_mode.bulk_ctl.urb[i];
-               if (urb) {
-                       if (!irqs_disabled())
-                               usb_kill_urb(urb);
-                       else
-                               usb_unlink_urb(urb);
-
-                       if (dev->vbi_mode.bulk_ctl.transfer_buffer[i]) {
-
-                               kfree(dev->vbi_mode.bulk_ctl.
-                                     transfer_buffer[i]);
-                               dev->vbi_mode.bulk_ctl.transfer_buffer[i] =
-                                   NULL;
-                       }
-                       usb_free_urb(urb);
-                       dev->vbi_mode.bulk_ctl.urb[i] = NULL;
-               }
-               dev->vbi_mode.bulk_ctl.transfer_buffer[i] = NULL;
-       }
-
-       kfree(dev->vbi_mode.bulk_ctl.urb);
-       kfree(dev->vbi_mode.bulk_ctl.transfer_buffer);
-
-       dev->vbi_mode.bulk_ctl.urb = NULL;
-       dev->vbi_mode.bulk_ctl.transfer_buffer = NULL;
-       dev->vbi_mode.bulk_ctl.num_bufs = 0;
-
-       cx231xx_capture_start(dev, 0, Vbi);
-}
-EXPORT_SYMBOL_GPL(cx231xx_uninit_vbi_isoc);
-
-/*
- * Allocate URBs and start IRQ
- */
-int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
-                         int num_bufs, int max_pkt_size,
-                         int (*bulk_copy) (struct cx231xx *dev,
-                                           struct urb *urb))
-{
-       struct cx231xx_dmaqueue *dma_q = &dev->vbi_mode.vidq;
-       int i;
-       int sb_size, pipe;
-       struct urb *urb;
-       int rc;
-
-       cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_prepare_isoc\n");
-
-       /* De-allocates all pending stuff */
-       cx231xx_uninit_vbi_isoc(dev);
-
-       /* clear if any halt */
-       usb_clear_halt(dev->udev,
-                      usb_rcvbulkpipe(dev->udev,
-                                      dev->vbi_mode.end_point_addr));
-
-       dev->vbi_mode.bulk_ctl.bulk_copy = bulk_copy;
-       dev->vbi_mode.bulk_ctl.num_bufs = num_bufs;
-       dma_q->pos = 0;
-       dma_q->is_partial_line = 0;
-       dma_q->last_sav = 0;
-       dma_q->current_field = -1;
-       dma_q->bytes_left_in_line = dev->width << 1;
-       dma_q->lines_per_field = ((dev->norm & V4L2_STD_625_50) ?
-                                 PAL_VBI_LINES : NTSC_VBI_LINES);
-       dma_q->lines_completed = 0;
-       for (i = 0; i < 8; i++)
-               dma_q->partial_buf[i] = 0;
-
-       dev->vbi_mode.bulk_ctl.urb = kzalloc(sizeof(void *) * num_bufs,
-                                            GFP_KERNEL);
-       if (!dev->vbi_mode.bulk_ctl.urb) {
-               cx231xx_errdev("cannot alloc memory for usb buffers\n");
-               return -ENOMEM;
-       }
-
-       dev->vbi_mode.bulk_ctl.transfer_buffer =
-           kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
-       if (!dev->vbi_mode.bulk_ctl.transfer_buffer) {
-               cx231xx_errdev("cannot allocate memory for usbtransfer\n");
-               kfree(dev->vbi_mode.bulk_ctl.urb);
-               return -ENOMEM;
-       }
-
-       dev->vbi_mode.bulk_ctl.max_pkt_size = max_pkt_size;
-       dev->vbi_mode.bulk_ctl.buf = NULL;
-
-       sb_size = max_packets * dev->vbi_mode.bulk_ctl.max_pkt_size;
-
-       /* allocate urbs and transfer buffers */
-       for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
-
-               urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (!urb) {
-                       cx231xx_err(DRIVER_NAME
-                                   ": cannot alloc bulk_ctl.urb %i\n", i);
-                       cx231xx_uninit_vbi_isoc(dev);
-                       return -ENOMEM;
-               }
-               dev->vbi_mode.bulk_ctl.urb[i] = urb;
-               urb->transfer_flags = 0;
-
-               dev->vbi_mode.bulk_ctl.transfer_buffer[i] =
-                   kzalloc(sb_size, GFP_KERNEL);
-               if (!dev->vbi_mode.bulk_ctl.transfer_buffer[i]) {
-                       cx231xx_err(DRIVER_NAME
-                                   ": unable to allocate %i bytes for transfer"
-                                   " buffer %i%s\n", sb_size, i,
-                                   in_interrupt() ? " while in int" : "");
-                       cx231xx_uninit_vbi_isoc(dev);
-                       return -ENOMEM;
-               }
-
-               pipe = usb_rcvbulkpipe(dev->udev, dev->vbi_mode.end_point_addr);
-               usb_fill_bulk_urb(urb, dev->udev, pipe,
-                                 dev->vbi_mode.bulk_ctl.transfer_buffer[i],
-                                 sb_size, cx231xx_irq_vbi_callback, dma_q);
-       }
-
-       init_waitqueue_head(&dma_q->wq);
-
-       /* submit urbs and enables IRQ */
-       for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
-               rc = usb_submit_urb(dev->vbi_mode.bulk_ctl.urb[i], GFP_ATOMIC);
-               if (rc) {
-                       cx231xx_err(DRIVER_NAME
-                                   ": submit of urb %i failed (error=%i)\n", i,
-                                   rc);
-                       cx231xx_uninit_vbi_isoc(dev);
-                       return rc;
-               }
-       }
-
-       cx231xx_capture_start(dev, 1, Vbi);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(cx231xx_init_vbi_isoc);
-
-u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
-                        u8 sav_eav, u8 *p_buffer, u32 buffer_size)
-{
-       u32 bytes_copied = 0;
-       int current_field = -1;
-
-       switch (sav_eav) {
-
-       case SAV_VBI_FIELD1:
-               current_field = 1;
-               break;
-
-       case SAV_VBI_FIELD2:
-               current_field = 2;
-               break;
-       default:
-               break;
-       }
-
-       if (current_field < 0)
-               return bytes_copied;
-
-       dma_q->last_sav = sav_eav;
-
-       bytes_copied =
-           cx231xx_copy_vbi_line(dev, dma_q, p_buffer, buffer_size,
-                                 current_field);
-
-       return bytes_copied;
-}
-
-/*
- * Announces that a buffer were filled and request the next
- */
-static inline void vbi_buffer_filled(struct cx231xx *dev,
-                                    struct cx231xx_dmaqueue *dma_q,
-                                    struct cx231xx_buffer *buf)
-{
-       /* Advice that buffer was filled */
-       /* cx231xx_info(DRIVER_NAME "[%p/%d] wakeup\n", buf, buf->vb.i); */
-
-       buf->vb.state = VIDEOBUF_DONE;
-       buf->vb.field_count++;
-       do_gettimeofday(&buf->vb.ts);
-
-       dev->vbi_mode.bulk_ctl.buf = NULL;
-
-       list_del(&buf->vb.queue);
-       wake_up(&buf->vb.done);
-}
-
-u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
-                         u8 *p_line, u32 length, int field_number)
-{
-       u32 bytes_to_copy;
-       struct cx231xx_buffer *buf;
-       u32 _line_size = dev->width * 2;
-
-       if (dma_q->current_field == -1) {
-               /* Just starting up */
-               cx231xx_reset_vbi_buffer(dev, dma_q);
-       }
-
-       if (dma_q->current_field != field_number)
-               dma_q->lines_completed = 0;
-
-       /* get the buffer pointer */
-       buf = dev->vbi_mode.bulk_ctl.buf;
-
-       /* Remember the field number for next time */
-       dma_q->current_field = field_number;
-
-       bytes_to_copy = dma_q->bytes_left_in_line;
-       if (bytes_to_copy > length)
-               bytes_to_copy = length;
-
-       if (dma_q->lines_completed >= dma_q->lines_per_field) {
-               dma_q->bytes_left_in_line -= bytes_to_copy;
-               dma_q->is_partial_line =
-                   (dma_q->bytes_left_in_line == 0) ? 0 : 1;
-               return 0;
-       }
-
-       dma_q->is_partial_line = 1;
-
-       /* If we don't have a buffer, just return the number of bytes we would
-          have copied if we had a buffer. */
-       if (!buf) {
-               dma_q->bytes_left_in_line -= bytes_to_copy;
-               dma_q->is_partial_line =
-                   (dma_q->bytes_left_in_line == 0) ? 0 : 1;
-               return bytes_to_copy;
-       }
-
-       /* copy the data to video buffer */
-       cx231xx_do_vbi_copy(dev, dma_q, p_line, bytes_to_copy);
-
-       dma_q->pos += bytes_to_copy;
-       dma_q->bytes_left_in_line -= bytes_to_copy;
-
-       if (dma_q->bytes_left_in_line == 0) {
-
-               dma_q->bytes_left_in_line = _line_size;
-               dma_q->lines_completed++;
-               dma_q->is_partial_line = 0;
-
-               if (cx231xx_is_vbi_buffer_done(dev, dma_q) && buf) {
-
-                       vbi_buffer_filled(dev, dma_q, buf);
-
-                       dma_q->pos = 0;
-                       dma_q->lines_completed = 0;
-                       cx231xx_reset_vbi_buffer(dev, dma_q);
-               }
-       }
-
-       return bytes_to_copy;
-}
-
-/*
- * video-buf generic routine to get the next available buffer
- */
-static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q,
-                                   struct cx231xx_buffer **buf)
-{
-       struct cx231xx_video_mode *vmode =
-           container_of(dma_q, struct cx231xx_video_mode, vidq);
-       struct cx231xx *dev = container_of(vmode, struct cx231xx, vbi_mode);
-       char *outp;
-
-       if (list_empty(&dma_q->active)) {
-               cx231xx_err(DRIVER_NAME ": No active queue to serve\n");
-               dev->vbi_mode.bulk_ctl.buf = NULL;
-               *buf = NULL;
-               return;
-       }
-
-       /* Get the next buffer */
-       *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue);
-
-       /* Cleans up buffer - Useful for testing for frame/URB loss */
-       outp = videobuf_to_vmalloc(&(*buf)->vb);
-       memset(outp, 0, (*buf)->vb.size);
-
-       dev->vbi_mode.bulk_ctl.buf = *buf;
-
-       return;
-}
-
-void cx231xx_reset_vbi_buffer(struct cx231xx *dev,
-                             struct cx231xx_dmaqueue *dma_q)
-{
-       struct cx231xx_buffer *buf;
-
-       buf = dev->vbi_mode.bulk_ctl.buf;
-
-       if (buf == NULL) {
-               /* first try to get the buffer */
-               get_next_vbi_buf(dma_q, &buf);
-
-               dma_q->pos = 0;
-               dma_q->current_field = -1;
-       }
-
-       dma_q->bytes_left_in_line = dev->width << 1;
-       dma_q->lines_completed = 0;
-}
-
-int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
-                       u8 *p_buffer, u32 bytes_to_copy)
-{
-       u8 *p_out_buffer = NULL;
-       u32 current_line_bytes_copied = 0;
-       struct cx231xx_buffer *buf;
-       u32 _line_size = dev->width << 1;
-       void *startwrite;
-       int offset, lencopy;
-
-       buf = dev->vbi_mode.bulk_ctl.buf;
-
-       if (buf == NULL)
-               return -EINVAL;
-
-       p_out_buffer = videobuf_to_vmalloc(&buf->vb);
-
-       if (dma_q->bytes_left_in_line != _line_size) {
-               current_line_bytes_copied =
-                   _line_size - dma_q->bytes_left_in_line;
-       }
-
-       offset = (dma_q->lines_completed * _line_size) +
-                current_line_bytes_copied;
-
-       if (dma_q->current_field == 2) {
-               /* Populate the second half of the frame */
-               offset += (dev->width * 2 * dma_q->lines_per_field);
-       }
-
-       /* prepare destination address */
-       startwrite = p_out_buffer + offset;
-
-       lencopy = dma_q->bytes_left_in_line > bytes_to_copy ?
-                 bytes_to_copy : dma_q->bytes_left_in_line;
-
-       memcpy(startwrite, p_buffer, lencopy);
-
-       return 0;
-}
-
-u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev,
-                             struct cx231xx_dmaqueue *dma_q)
-{
-       u32 height = 0;
-
-       height = ((dev->norm & V4L2_STD_625_50) ?
-                 PAL_VBI_LINES : NTSC_VBI_LINES);
-       if (dma_q->lines_completed == height && dma_q->current_field == 2)
-               return 1;
-       else
-               return 0;
-}
diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.h b/drivers/media/video/cx231xx/cx231xx-vbi.h
deleted file mode 100644 (file)
index 16c7d20..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-   cx231xx_vbi.h - driver for Conexant Cx23100/101/102 USB video capture devices
-
-   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
-               Based on cx88 driver
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   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.
- */
-
-#ifndef _CX231XX_VBI_H
-#define _CX231XX_VBI_H
-
-extern struct videobuf_queue_ops cx231xx_vbi_qops;
-
-#define   NTSC_VBI_START_LINE 10       /* line 10 - 21 */
-#define   NTSC_VBI_END_LINE   21
-#define   NTSC_VBI_LINES         (NTSC_VBI_END_LINE-NTSC_VBI_START_LINE+1)
-
-#define   PAL_VBI_START_LINE  6
-#define   PAL_VBI_END_LINE    23
-#define   PAL_VBI_LINES       (PAL_VBI_END_LINE-PAL_VBI_START_LINE+1)
-
-#define   VBI_STRIDE            1440
-#define   VBI_SAMPLES_PER_LINE  1440
-
-#define   CX231XX_NUM_VBI_PACKETS       4
-#define   CX231XX_NUM_VBI_BUFS          5
-
-/* stream functions */
-int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
-                         int num_bufs, int max_pkt_size,
-                         int (*bulk_copy) (struct cx231xx *dev,
-                                           struct urb *urb));
-
-void cx231xx_uninit_vbi_isoc(struct cx231xx *dev);
-
-/* vbi data copy functions */
-u32 cx231xx_get_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
-                        u8 sav_eav, u8 *p_buffer, u32 buffer_size);
-
-u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
-                         u8 *p_line, u32 length, int field_number);
-
-void cx231xx_reset_vbi_buffer(struct cx231xx *dev,
-                             struct cx231xx_dmaqueue *dma_q);
-
-int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
-                       u8 *p_buffer, u32 bytes_to_copy);
-
-u8 cx231xx_is_vbi_buffer_done(struct cx231xx *dev,
-                             struct cx231xx_dmaqueue *dma_q);
-
-#endif
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c
deleted file mode 100644 (file)
index 790b28d..0000000
+++ /dev/null
@@ -1,2670 +0,0 @@
-/*
-   cx231xx-video.c - driver for Conexant Cx23100/101/102
-                    USB video capture devices
-
-   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
-       Based on em28xx driver
-       Based on cx23885 driver
-       Based on cx88 driver
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   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/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 <linux/mm.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-chip-ident.h>
-#include <media/msp3400.h>
-#include <media/tuner.h>
-
-#include "dvb_frontend.h"
-
-#include "cx231xx.h"
-#include "cx231xx-vbi.h"
-
-#define CX231XX_VERSION "0.0.2"
-
-#define DRIVER_AUTHOR   "Srinivasa Deevi <srinivasa.deevi@conexant.com>"
-#define DRIVER_DESC     "Conexant cx231xx based USB video device driver"
-
-#define cx231xx_videodbg(fmt, arg...) do {\
-       if (video_debug) \
-               printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __func__ , ##arg); } while (0)
-
-static unsigned int isoc_debug;
-module_param(isoc_debug, int, 0644);
-MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
-
-#define cx231xx_isocdbg(fmt, arg...) \
-do {\
-       if (isoc_debug) { \
-               printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __func__ , ##arg); \
-       } \
-  } while (0)
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(CX231XX_VERSION);
-
-static unsigned int card[]     = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
-static unsigned int video_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
-static unsigned int vbi_nr[]   = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
-static unsigned int radio_nr[] = {[0 ... (CX231XX_MAXBOARDS - 1)] = UNSET };
-
-module_param_array(card, int, NULL, 0444);
-module_param_array(video_nr, int, NULL, 0444);
-module_param_array(vbi_nr, int, NULL, 0444);
-module_param_array(radio_nr, int, NULL, 0444);
-
-MODULE_PARM_DESC(card, "card type");
-MODULE_PARM_DESC(video_nr, "video device numbers");
-MODULE_PARM_DESC(vbi_nr, "vbi device numbers");
-MODULE_PARM_DESC(radio_nr, "radio device numbers");
-
-static unsigned int video_debug;
-module_param(video_debug, int, 0644);
-MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
-
-/* supported video standards */
-static struct cx231xx_fmt format[] = {
-       {
-        .name = "16bpp YUY2, 4:2:2, packed",
-        .fourcc = V4L2_PIX_FMT_YUYV,
-        .depth = 16,
-        .reg = 0,
-        },
-};
-
-/* supported controls */
-/* Common to all boards */
-
-/* ------------------------------------------------------------------- */
-
-static const struct v4l2_queryctrl no_ctl = {
-       .name = "42",
-       .flags = V4L2_CTRL_FLAG_DISABLED,
-};
-
-static struct cx231xx_ctrl cx231xx_ctls[] = {
-       /* --- video --- */
-       {
-               .v = {
-                       .id = V4L2_CID_BRIGHTNESS,
-                       .name = "Brightness",
-                       .minimum = 0x00,
-                       .maximum = 0xff,
-                       .step = 1,
-                       .default_value = 0x7f,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-               },
-               .off = 128,
-               .reg = LUMA_CTRL,
-               .mask = 0x00ff,
-               .shift = 0,
-       }, {
-               .v = {
-                       .id = V4L2_CID_CONTRAST,
-                       .name = "Contrast",
-                       .minimum = 0,
-                       .maximum = 0xff,
-                       .step = 1,
-                       .default_value = 0x3f,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-               },
-               .off = 0,
-               .reg = LUMA_CTRL,
-               .mask = 0xff00,
-               .shift = 8,
-       }, {
-               .v = {
-                       .id = V4L2_CID_HUE,
-                       .name = "Hue",
-                       .minimum = 0,
-                       .maximum = 0xff,
-                       .step = 1,
-                       .default_value = 0x7f,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-               },
-               .off = 128,
-               .reg = CHROMA_CTRL,
-               .mask = 0xff0000,
-               .shift = 16,
-       }, {
-       /* strictly, this only describes only U saturation.
-       * V saturation is handled specially through code.
-       */
-               .v = {
-                       .id = V4L2_CID_SATURATION,
-                       .name = "Saturation",
-                       .minimum = 0,
-                       .maximum = 0xff,
-                       .step = 1,
-                       .default_value = 0x7f,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-               },
-               .off = 0,
-               .reg = CHROMA_CTRL,
-               .mask = 0x00ff,
-               .shift = 0,
-       }, {
-               /* --- audio --- */
-               .v = {
-                       .id = V4L2_CID_AUDIO_MUTE,
-                       .name = "Mute",
-                       .minimum = 0,
-                       .maximum = 1,
-                       .default_value = 1,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-               },
-               .reg = PATH1_CTL1,
-               .mask = (0x1f << 24),
-               .shift = 24,
-       }, {
-               .v = {
-                       .id = V4L2_CID_AUDIO_VOLUME,
-                       .name = "Volume",
-                       .minimum = 0,
-                       .maximum = 0x3f,
-                       .step = 1,
-                       .default_value = 0x3f,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-               },
-               .reg = PATH1_VOL_CTL,
-               .mask = 0xff,
-               .shift = 0,
-       }
-};
-static const int CX231XX_CTLS = ARRAY_SIZE(cx231xx_ctls);
-
-static const u32 cx231xx_user_ctrls[] = {
-       V4L2_CID_USER_CLASS,
-       V4L2_CID_BRIGHTNESS,
-       V4L2_CID_CONTRAST,
-       V4L2_CID_SATURATION,
-       V4L2_CID_HUE,
-       V4L2_CID_AUDIO_VOLUME,
-#if 0
-       V4L2_CID_AUDIO_BALANCE,
-#endif
-       V4L2_CID_AUDIO_MUTE,
-       0
-};
-
-static const u32 *ctrl_classes[] = {
-       cx231xx_user_ctrls,
-       NULL
-};
-
-/* ------------------------------------------------------------------
-       Video buffer and parser functions
-   ------------------------------------------------------------------*/
-
-/*
- * Announces that a buffer were filled and request the next
- */
-static inline void buffer_filled(struct cx231xx *dev,
-                                struct cx231xx_dmaqueue *dma_q,
-                                struct cx231xx_buffer *buf)
-{
-       /* Advice that buffer was filled */
-       cx231xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
-       buf->vb.state = VIDEOBUF_DONE;
-       buf->vb.field_count++;
-       do_gettimeofday(&buf->vb.ts);
-
-       if (dev->USE_ISO)
-               dev->video_mode.isoc_ctl.buf = NULL;
-       else
-               dev->video_mode.bulk_ctl.buf = NULL;
-
-       list_del(&buf->vb.queue);
-       wake_up(&buf->vb.done);
-}
-
-static inline void print_err_status(struct cx231xx *dev, int packet, int status)
-{
-       char *errmsg = "Unknown";
-
-       switch (status) {
-       case -ENOENT:
-               errmsg = "unlinked synchronuously";
-               break;
-       case -ECONNRESET:
-               errmsg = "unlinked asynchronuously";
-               break;
-       case -ENOSR:
-               errmsg = "Buffer error (overrun)";
-               break;
-       case -EPIPE:
-               errmsg = "Stalled (device not responding)";
-               break;
-       case -EOVERFLOW:
-               errmsg = "Babble (bad cable?)";
-               break;
-       case -EPROTO:
-               errmsg = "Bit-stuff error (bad cable?)";
-               break;
-       case -EILSEQ:
-               errmsg = "CRC/Timeout (could be anything)";
-               break;
-       case -ETIME:
-               errmsg = "Device does not respond";
-               break;
-       }
-       if (packet < 0) {
-               cx231xx_isocdbg("URB status %d [%s].\n", status, errmsg);
-       } else {
-               cx231xx_isocdbg("URB packet %d, status %d [%s].\n",
-                               packet, status, errmsg);
-       }
-}
-
-/*
- * video-buf generic routine to get the next available buffer
- */
-static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q,
-                               struct cx231xx_buffer **buf)
-{
-       struct cx231xx_video_mode *vmode =
-           container_of(dma_q, struct cx231xx_video_mode, vidq);
-       struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode);
-
-       char *outp;
-
-       if (list_empty(&dma_q->active)) {
-               cx231xx_isocdbg("No active queue to serve\n");
-               if (dev->USE_ISO)
-                       dev->video_mode.isoc_ctl.buf = NULL;
-               else
-                       dev->video_mode.bulk_ctl.buf = NULL;
-               *buf = NULL;
-               return;
-       }
-
-       /* Get the next buffer */
-       *buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue);
-
-       /* Cleans up buffer - Useful for testing for frame/URB loss */
-       outp = videobuf_to_vmalloc(&(*buf)->vb);
-       memset(outp, 0, (*buf)->vb.size);
-
-       if (dev->USE_ISO)
-               dev->video_mode.isoc_ctl.buf = *buf;
-       else
-               dev->video_mode.bulk_ctl.buf = *buf;
-
-       return;
-}
-
-/*
- * Controls the isoc copy of each urb packet
- */
-static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
-{
-       struct cx231xx_dmaqueue *dma_q = urb->context;
-       int i, rc = 1;
-       unsigned char *p_buffer;
-       u32 bytes_parsed = 0, buffer_size = 0;
-       u8 sav_eav = 0;
-
-       if (!dev)
-               return 0;
-
-       if (dev->state & DEV_DISCONNECTED)
-               return 0;
-
-       if (urb->status < 0) {
-               print_err_status(dev, -1, urb->status);
-               if (urb->status == -ENOENT)
-                       return 0;
-       }
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               int status = urb->iso_frame_desc[i].status;
-
-               if (status < 0) {
-                       print_err_status(dev, i, status);
-                       if (urb->iso_frame_desc[i].status != -EPROTO)
-                               continue;
-               }
-
-               if (urb->iso_frame_desc[i].actual_length <= 0) {
-                       /* cx231xx_isocdbg("packet %d is empty",i); - spammy */
-                       continue;
-               }
-               if (urb->iso_frame_desc[i].actual_length >
-                   dev->video_mode.max_pkt_size) {
-                       cx231xx_isocdbg("packet bigger than packet size");
-                       continue;
-               }
-
-               /*  get buffer pointer and length */
-               p_buffer = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-               buffer_size = urb->iso_frame_desc[i].actual_length;
-               bytes_parsed = 0;
-
-               if (dma_q->is_partial_line) {
-                       /* Handle the case of a partial line */
-                       sav_eav = dma_q->last_sav;
-               } else {
-                       /* Check for a SAV/EAV overlapping
-                               the buffer boundary */
-                       sav_eav =
-                           cx231xx_find_boundary_SAV_EAV(p_buffer,
-                                                         dma_q->partial_buf,
-                                                         &bytes_parsed);
-               }
-
-               sav_eav &= 0xF0;
-               /* Get the first line if we have some portion of an SAV/EAV from
-                  the last buffer or a partial line  */
-               if (sav_eav) {
-                       bytes_parsed += cx231xx_get_video_line(dev, dma_q,
-                               sav_eav,        /* SAV/EAV */
-                               p_buffer + bytes_parsed,        /* p_buffer */
-                               buffer_size - bytes_parsed);/* buf size */
-               }
-
-               /* Now parse data that is completely in this buffer */
-               /* dma_q->is_partial_line = 0;  */
-
-               while (bytes_parsed < buffer_size) {
-                       u32 bytes_used = 0;
-
-                       sav_eav = cx231xx_find_next_SAV_EAV(
-                               p_buffer + bytes_parsed,        /* p_buffer */
-                               buffer_size - bytes_parsed,     /* buf size */
-                               &bytes_used);/* bytes used to get SAV/EAV */
-
-                       bytes_parsed += bytes_used;
-
-                       sav_eav &= 0xF0;
-                       if (sav_eav && (bytes_parsed < buffer_size)) {
-                               bytes_parsed += cx231xx_get_video_line(dev,
-                                       dma_q, sav_eav, /* SAV/EAV */
-                                       p_buffer + bytes_parsed,/* p_buffer */
-                                       buffer_size - bytes_parsed);/*buf size*/
-                       }
-               }
-
-               /* Save the last four bytes of the buffer so we can check the
-                  buffer boundary condition next time */
-               memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4);
-               bytes_parsed = 0;
-
-       }
-       return rc;
-}
-
-static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
-{
-       struct cx231xx_dmaqueue *dma_q = urb->context;
-       int rc = 1;
-       unsigned char *p_buffer;
-       u32 bytes_parsed = 0, buffer_size = 0;
-       u8 sav_eav = 0;
-
-       if (!dev)
-               return 0;
-
-       if (dev->state & DEV_DISCONNECTED)
-               return 0;
-
-       if (urb->status < 0) {
-               print_err_status(dev, -1, urb->status);
-               if (urb->status == -ENOENT)
-                       return 0;
-       }
-
-       if (1) {
-
-               /*  get buffer pointer and length */
-               p_buffer = urb->transfer_buffer;
-               buffer_size = urb->actual_length;
-               bytes_parsed = 0;
-
-               if (dma_q->is_partial_line) {
-                       /* Handle the case of a partial line */
-                       sav_eav = dma_q->last_sav;
-               } else {
-                       /* Check for a SAV/EAV overlapping
-                               the buffer boundary */
-                       sav_eav =
-                           cx231xx_find_boundary_SAV_EAV(p_buffer,
-                                                         dma_q->partial_buf,
-                                                         &bytes_parsed);
-               }
-
-               sav_eav &= 0xF0;
-               /* Get the first line if we have some portion of an SAV/EAV from
-                  the last buffer or a partial line  */
-               if (sav_eav) {
-                       bytes_parsed += cx231xx_get_video_line(dev, dma_q,
-                               sav_eav,        /* SAV/EAV */
-                               p_buffer + bytes_parsed,        /* p_buffer */
-                               buffer_size - bytes_parsed);/* buf size */
-               }
-
-               /* Now parse data that is completely in this buffer */
-               /* dma_q->is_partial_line = 0;  */
-
-               while (bytes_parsed < buffer_size) {
-                       u32 bytes_used = 0;
-
-                       sav_eav = cx231xx_find_next_SAV_EAV(
-                               p_buffer + bytes_parsed,        /* p_buffer */
-                               buffer_size - bytes_parsed,     /* buf size */
-                               &bytes_used);/* bytes used to get SAV/EAV */
-
-                       bytes_parsed += bytes_used;
-
-                       sav_eav &= 0xF0;
-                       if (sav_eav && (bytes_parsed < buffer_size)) {
-                               bytes_parsed += cx231xx_get_video_line(dev,
-                                       dma_q, sav_eav, /* SAV/EAV */
-                                       p_buffer + bytes_parsed,/* p_buffer */
-                                       buffer_size - bytes_parsed);/*buf size*/
-                       }
-               }
-
-               /* Save the last four bytes of the buffer so we can check the
-                  buffer boundary condition next time */
-               memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4);
-               bytes_parsed = 0;
-
-       }
-       return rc;
-}
-
-
-u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf,
-                                u32 *p_bytes_used)
-{
-       u32 bytes_used;
-       u8 boundary_bytes[8];
-       u8 sav_eav = 0;
-
-       *p_bytes_used = 0;
-
-       /* Create an array of the last 4 bytes of the last buffer and the first
-          4 bytes of the current buffer. */
-
-       memcpy(boundary_bytes, partial_buf, 4);
-       memcpy(boundary_bytes + 4, p_buffer, 4);
-
-       /* Check for the SAV/EAV in the boundary buffer */
-       sav_eav = cx231xx_find_next_SAV_EAV((u8 *)&boundary_bytes, 8,
-                                           &bytes_used);
-
-       if (sav_eav) {
-               /* found a boundary SAV/EAV.  Updates the bytes used to reflect
-                  only those used in the new buffer */
-               *p_bytes_used = bytes_used - 4;
-       }
-
-       return sav_eav;
-}
-
-u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size, u32 *p_bytes_used)
-{
-       u32 i;
-       u8 sav_eav = 0;
-
-       /*
-        * Don't search if the buffer size is less than 4.  It causes a page
-        * fault since buffer_size - 4 evaluates to a large number in that
-        * case.
-        */
-       if (buffer_size < 4) {
-               *p_bytes_used = buffer_size;
-               return 0;
-       }
-
-       for (i = 0; i < (buffer_size - 3); i++) {
-
-               if ((p_buffer[i] == 0xFF) &&
-                   (p_buffer[i + 1] == 0x00) && (p_buffer[i + 2] == 0x00)) {
-
-                       *p_bytes_used = i + 4;
-                       sav_eav = p_buffer[i + 3];
-                       return sav_eav;
-               }
-       }
-
-       *p_bytes_used = buffer_size;
-       return 0;
-}
-
-u32 cx231xx_get_video_line(struct cx231xx *dev,
-                          struct cx231xx_dmaqueue *dma_q, u8 sav_eav,
-                          u8 *p_buffer, u32 buffer_size)
-{
-       u32 bytes_copied = 0;
-       int current_field = -1;
-
-       switch (sav_eav) {
-       case SAV_ACTIVE_VIDEO_FIELD1:
-               /* looking for skipped line which occurred in PAL 720x480 mode.
-                  In this case, there will be no active data contained
-                  between the SAV and EAV */
-               if ((buffer_size > 3) && (p_buffer[0] == 0xFF) &&
-                   (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) &&
-                   ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) ||
-                    (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) ||
-                    (p_buffer[3] == EAV_VBLANK_FIELD1) ||
-                    (p_buffer[3] == EAV_VBLANK_FIELD2)))
-                       return bytes_copied;
-               current_field = 1;
-               break;
-
-       case SAV_ACTIVE_VIDEO_FIELD2:
-               /* looking for skipped line which occurred in PAL 720x480 mode.
-                  In this case, there will be no active data contained between
-                  the SAV and EAV */
-               if ((buffer_size > 3) && (p_buffer[0] == 0xFF) &&
-                   (p_buffer[1] == 0x00) && (p_buffer[2] == 0x00) &&
-                   ((p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD1) ||
-                    (p_buffer[3] == EAV_ACTIVE_VIDEO_FIELD2) ||
-                    (p_buffer[3] == EAV_VBLANK_FIELD1)       ||
-                    (p_buffer[3] == EAV_VBLANK_FIELD2)))
-                       return bytes_copied;
-               current_field = 2;
-               break;
-       }
-
-       dma_q->last_sav = sav_eav;
-
-       bytes_copied = cx231xx_copy_video_line(dev, dma_q, p_buffer,
-                                              buffer_size, current_field);
-
-       return bytes_copied;
-}
-
-u32 cx231xx_copy_video_line(struct cx231xx *dev,
-                           struct cx231xx_dmaqueue *dma_q, u8 *p_line,
-                           u32 length, int field_number)
-{
-       u32 bytes_to_copy;
-       struct cx231xx_buffer *buf;
-       u32 _line_size = dev->width * 2;
-
-       if (dma_q->current_field != field_number)
-               cx231xx_reset_video_buffer(dev, dma_q);
-
-       /* get the buffer pointer */
-       if (dev->USE_ISO)
-               buf = dev->video_mode.isoc_ctl.buf;
-       else
-               buf = dev->video_mode.bulk_ctl.buf;
-
-       /* Remember the field number for next time */
-       dma_q->current_field = field_number;
-
-       bytes_to_copy = dma_q->bytes_left_in_line;
-       if (bytes_to_copy > length)
-               bytes_to_copy = length;
-
-       if (dma_q->lines_completed >= dma_q->lines_per_field) {
-               dma_q->bytes_left_in_line -= bytes_to_copy;
-               dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0) ?
-                                         0 : 1;
-               return 0;
-       }
-
-       dma_q->is_partial_line = 1;
-
-       /* If we don't have a buffer, just return the number of bytes we would
-          have copied if we had a buffer. */
-       if (!buf) {
-               dma_q->bytes_left_in_line -= bytes_to_copy;
-               dma_q->is_partial_line = (dma_q->bytes_left_in_line == 0)
-                                        ? 0 : 1;
-               return bytes_to_copy;
-       }
-
-       /* copy the data to video buffer */
-       cx231xx_do_copy(dev, dma_q, p_line, bytes_to_copy);
-
-       dma_q->pos += bytes_to_copy;
-       dma_q->bytes_left_in_line -= bytes_to_copy;
-
-       if (dma_q->bytes_left_in_line == 0) {
-               dma_q->bytes_left_in_line = _line_size;
-               dma_q->lines_completed++;
-               dma_q->is_partial_line = 0;
-
-               if (cx231xx_is_buffer_done(dev, dma_q) && buf) {
-                       buffer_filled(dev, dma_q, buf);
-
-                       dma_q->pos = 0;
-                       buf = NULL;
-                       dma_q->lines_completed = 0;
-               }
-       }
-
-       return bytes_to_copy;
-}
-
-void cx231xx_reset_video_buffer(struct cx231xx *dev,
-                               struct cx231xx_dmaqueue *dma_q)
-{
-       struct cx231xx_buffer *buf;
-
-       /* handle the switch from field 1 to field 2 */
-       if (dma_q->current_field == 1) {
-               if (dma_q->lines_completed >= dma_q->lines_per_field)
-                       dma_q->field1_done = 1;
-               else
-                       dma_q->field1_done = 0;
-       }
-
-       if (dev->USE_ISO)
-               buf = dev->video_mode.isoc_ctl.buf;
-       else
-               buf = dev->video_mode.bulk_ctl.buf;
-
-       if (buf == NULL) {
-               /* first try to get the buffer */
-               get_next_buf(dma_q, &buf);
-
-               dma_q->pos = 0;
-               dma_q->field1_done = 0;
-               dma_q->current_field = -1;
-       }
-
-       /* reset the counters */
-       dma_q->bytes_left_in_line = dev->width << 1;
-       dma_q->lines_completed = 0;
-}
-
-int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
-                   u8 *p_buffer, u32 bytes_to_copy)
-{
-       u8 *p_out_buffer = NULL;
-       u32 current_line_bytes_copied = 0;
-       struct cx231xx_buffer *buf;
-       u32 _line_size = dev->width << 1;
-       void *startwrite;
-       int offset, lencopy;
-
-       if (dev->USE_ISO)
-               buf = dev->video_mode.isoc_ctl.buf;
-       else
-               buf = dev->video_mode.bulk_ctl.buf;
-
-       if (buf == NULL)
-               return -1;
-
-       p_out_buffer = videobuf_to_vmalloc(&buf->vb);
-
-       current_line_bytes_copied = _line_size - dma_q->bytes_left_in_line;
-
-       /* Offset field 2 one line from the top of the buffer */
-       offset = (dma_q->current_field == 1) ? 0 : _line_size;
-
-       /* Offset for field 2 */
-       startwrite = p_out_buffer + offset;
-
-       /* lines already completed in the current field */
-       startwrite += (dma_q->lines_completed * _line_size * 2);
-
-       /* bytes already completed in the current line */
-       startwrite += current_line_bytes_copied;
-
-       lencopy = dma_q->bytes_left_in_line > bytes_to_copy ?
-                 bytes_to_copy : dma_q->bytes_left_in_line;
-
-       if ((u8 *)(startwrite + lencopy) > (u8 *)(p_out_buffer + buf->vb.size))
-               return 0;
-
-       /* The below copies the UYVY data straight into video buffer */
-       cx231xx_swab((u16 *) p_buffer, (u16 *) startwrite, (u16) lencopy);
-
-       return 0;
-}
-
-void cx231xx_swab(u16 *from, u16 *to, u16 len)
-{
-       u16 i;
-
-       if (len <= 0)
-               return;
-
-       for (i = 0; i < len / 2; i++)
-               to[i] = (from[i] << 8) | (from[i] >> 8);
-}
-
-u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q)
-{
-       u8 buffer_complete = 0;
-
-       /* Dual field stream */
-       buffer_complete = ((dma_q->current_field == 2) &&
-                          (dma_q->lines_completed >= dma_q->lines_per_field) &&
-                           dma_q->field1_done);
-
-       return buffer_complete;
-}
-
-/* ------------------------------------------------------------------
-       Videobuf operations
-   ------------------------------------------------------------------*/
-
-static int
-buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
-{
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *dev = fh->dev;
-
-       *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7)>>3;
-       if (0 == *count)
-               *count = CX231XX_DEF_BUF;
-
-       if (*count < CX231XX_MIN_BUF)
-               *count = CX231XX_MIN_BUF;
-
-       return 0;
-}
-
-/* This is called *without* dev->slock held; please keep it that way */
-static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
-{
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *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->video_mode.slock, flags);
-       if (dev->USE_ISO) {
-               if (dev->video_mode.isoc_ctl.buf == buf)
-                       dev->video_mode.isoc_ctl.buf = NULL;
-       } else {
-               if (dev->video_mode.bulk_ctl.buf == buf)
-                       dev->video_mode.bulk_ctl.buf = NULL;
-       }
-       spin_unlock_irqrestore(&dev->video_mode.slock, flags);
-
-       videobuf_vmalloc_free(&buf->vb);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int
-buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
-              enum v4l2_field field)
-{
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       struct cx231xx *dev = fh->dev;
-       int rc = 0, urb_init = 0;
-
-       /* The only currently supported format is 16 bits/pixel */
-       buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth
-                       + 7) >> 3;
-       if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
-               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)
-                       goto fail;
-       }
-
-       if (dev->USE_ISO) {
-               if (!dev->video_mode.isoc_ctl.num_bufs)
-                       urb_init = 1;
-       } else {
-               if (!dev->video_mode.bulk_ctl.num_bufs)
-                       urb_init = 1;
-       }
-       /*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n",
-               urb_init, dev->video_mode.max_pkt_size);*/
-       if (urb_init) {
-               dev->mode_tv = 0;
-               if (dev->USE_ISO)
-                       rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
-                                      CX231XX_NUM_BUFS,
-                                      dev->video_mode.max_pkt_size,
-                                      cx231xx_isoc_copy);
-               else
-                       rc = cx231xx_init_bulk(dev, CX231XX_NUM_PACKETS,
-                                      CX231XX_NUM_BUFS,
-                                      dev->video_mode.max_pkt_size,
-                                      cx231xx_bulk_copy);
-               if (rc < 0)
-                       goto fail;
-       }
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
-fail:
-       free_buffer(vq, buf);
-       return rc;
-}
-
-static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-       struct cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *dev = fh->dev;
-       struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
-
-       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 cx231xx_buffer *buf =
-           container_of(vb, struct cx231xx_buffer, vb);
-       struct cx231xx_fh *fh = vq->priv_data;
-       struct cx231xx *dev = (struct cx231xx *)fh->dev;
-
-       cx231xx_isocdbg("cx231xx: called buffer_release\n");
-
-       free_buffer(vq, buf);
-}
-
-static struct videobuf_queue_ops cx231xx_video_qops = {
-       .buf_setup = buffer_setup,
-       .buf_prepare = buffer_prepare,
-       .buf_queue = buffer_queue,
-       .buf_release = buffer_release,
-};
-
-/*********************  v4l2 interface  **************************************/
-
-void video_mux(struct cx231xx *dev, int index)
-{
-       dev->video_input = index;
-       dev->ctl_ainput = INPUT(index)->amux;
-
-       cx231xx_set_video_input_mux(dev, index);
-
-       cx25840_call(dev, video, s_routing, INPUT(index)->vmux, 0, 0);
-
-       cx231xx_set_audio_input(dev, dev->ctl_ainput);
-
-       cx231xx_info("video_mux : %d\n", index);
-
-       /* do mode control overrides if required */
-       cx231xx_do_mode_ctrl_overrides(dev);
-}
-
-/* Usage lock check functions */
-static int res_get(struct cx231xx_fh *fh)
-{
-       struct cx231xx *dev = fh->dev;
-       int rc = 0;
-
-       /* This instance already has stream_on */
-       if (fh->stream_on)
-               return rc;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               if (dev->stream_on)
-                       return -EBUSY;
-               dev->stream_on = 1;
-       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-               if (dev->vbi_stream_on)
-                       return -EBUSY;
-               dev->vbi_stream_on = 1;
-       } else
-               return -EINVAL;
-
-       fh->stream_on = 1;
-
-       return rc;
-}
-
-static int res_check(struct cx231xx_fh *fh)
-{
-       return fh->stream_on;
-}
-
-static void res_free(struct cx231xx_fh *fh)
-{
-       struct cx231xx *dev = fh->dev;
-
-       fh->stream_on = 0;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               dev->stream_on = 0;
-       if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-               dev->vbi_stream_on = 0;
-}
-
-static int check_dev(struct cx231xx *dev)
-{
-       if (dev->state & DEV_DISCONNECTED) {
-               cx231xx_errdev("v4l2 ioctl: device not present\n");
-               return -ENODEV;
-       }
-       return 0;
-}
-
-/* ------------------------------------------------------------------
-       IOCTL vidioc handling
-   ------------------------------------------------------------------*/
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-
-       f->fmt.pix.width = dev->width;
-       f->fmt.pix.height = dev->height;
-       f->fmt.pix.pixelformat = dev->format->fourcc;
-       f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;
-       f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * dev->height;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-
-       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-
-       return 0;
-}
-
-static struct cx231xx_fmt *format_by_fourcc(unsigned int fourcc)
-{
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(format); i++)
-               if (format[i].fourcc == fourcc)
-                       return &format[i];
-
-       return NULL;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                                 struct v4l2_format *f)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       unsigned int width = f->fmt.pix.width;
-       unsigned int height = f->fmt.pix.height;
-       unsigned int maxw = norm_maxw(dev);
-       unsigned int maxh = norm_maxh(dev);
-       struct cx231xx_fmt *fmt;
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-       if (!fmt) {
-               cx231xx_videodbg("Fourcc format (%08x) invalid.\n",
-                                f->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       /* width must even because of the YUYV format
-          height must be even because of interlacing */
-       v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh, 1, 0);
-
-       f->fmt.pix.width = width;
-       f->fmt.pix.height = height;
-       f->fmt.pix.pixelformat = fmt->fourcc;
-       f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3;
-       f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-       struct cx231xx_fmt *fmt;
-       struct v4l2_mbus_framefmt mbus_fmt;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       vidioc_try_fmt_vid_cap(file, priv, f);
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-       if (!fmt)
-               return -EINVAL;
-
-       if (videobuf_queue_is_busy(&fh->vb_vidq)) {
-               cx231xx_errdev("%s queue busy\n", __func__);
-               return -EBUSY;
-       }
-
-       if (dev->stream_on && !fh->stream_on) {
-               cx231xx_errdev("%s device in use by another fh\n", __func__);
-               return -EBUSY;
-       }
-
-       /* set new image size */
-       dev->width = f->fmt.pix.width;
-       dev->height = f->fmt.pix.height;
-       dev->format = fmt;
-
-       v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
-       call_all(dev, video, s_mbus_fmt, &mbus_fmt);
-       v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
-
-       return rc;
-}
-
-static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-
-       *id = dev->norm;
-       return 0;
-}
-
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       struct v4l2_mbus_framefmt mbus_fmt;
-       struct v4l2_format f;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       cx231xx_info("vidioc_s_std : 0x%x\n", (unsigned int)*norm);
-
-       dev->norm = *norm;
-
-       /* Adjusts width/height, if needed */
-       f.fmt.pix.width = dev->width;
-       f.fmt.pix.height = dev->height;
-       vidioc_try_fmt_vid_cap(file, priv, &f);
-
-       call_all(dev, core, s_std, dev->norm);
-
-       /* We need to reset basic properties in the decoder related to
-          resolution (since a standard change effects things like the number
-          of lines in VACT, etc) */
-       v4l2_fill_mbus_format(&mbus_fmt, &f.fmt.pix, V4L2_MBUS_FMT_FIXED);
-       call_all(dev, video, s_mbus_fmt, &mbus_fmt);
-       v4l2_fill_pix_format(&f.fmt.pix, &mbus_fmt);
-
-       /* set new image size */
-       dev->width = f.fmt.pix.width;
-       dev->height = f.fmt.pix.height;
-
-       /* do mode control overrides */
-       cx231xx_do_mode_ctrl_overrides(dev);
-
-       return 0;
-}
-
-static const char *iname[] = {
-       [CX231XX_VMUX_COMPOSITE1] = "Composite1",
-       [CX231XX_VMUX_SVIDEO]     = "S-Video",
-       [CX231XX_VMUX_TELEVISION] = "Television",
-       [CX231XX_VMUX_CABLE]      = "Cable TV",
-       [CX231XX_VMUX_DVB]        = "DVB",
-       [CX231XX_VMUX_DEBUG]      = "for debug only",
-};
-
-static int vidioc_enum_input(struct file *file, void *priv,
-                            struct v4l2_input *i)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       u32 gen_stat;
-       unsigned int ret, n;
-
-       n = i->index;
-       if (n >= MAX_CX231XX_INPUT)
-               return -EINVAL;
-       if (0 == INPUT(n)->type)
-               return -EINVAL;
-
-       i->index = n;
-       i->type = V4L2_INPUT_TYPE_CAMERA;
-
-       strcpy(i->name, iname[INPUT(n)->type]);
-
-       if ((CX231XX_VMUX_TELEVISION == INPUT(n)->type) ||
-           (CX231XX_VMUX_CABLE == INPUT(n)->type))
-               i->type = V4L2_INPUT_TYPE_TUNER;
-
-       i->std = dev->vdev->tvnorms;
-
-       /* If they are asking about the active input, read signal status */
-       if (n == dev->video_input) {
-               ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
-                                           GEN_STAT, 2, &gen_stat, 4);
-               if (ret > 0) {
-                       if ((gen_stat & FLD_VPRES) == 0x00)
-                               i->status |= V4L2_IN_ST_NO_SIGNAL;
-                       if ((gen_stat & FLD_HLOCK) == 0x00)
-                               i->status |= V4L2_IN_ST_NO_H_LOCK;
-               }
-       }
-
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-
-       *i = dev->video_input;
-
-       return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       dev->mode_tv = 0;
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (i >= MAX_CX231XX_INPUT)
-               return -EINVAL;
-       if (0 == INPUT(i)->type)
-               return -EINVAL;
-
-       video_mux(dev, i);
-
-       if (INPUT(i)->type == CX231XX_VMUX_TELEVISION ||
-           INPUT(i)->type == CX231XX_VMUX_CABLE) {
-               /* There's a tuner, so reset the standard and put it on the
-                  last known frequency (since it was probably powered down
-                  until now */
-               call_all(dev, core, s_std, dev->norm);
-       }
-
-       return 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-
-       switch (a->index) {
-       case CX231XX_AMUX_VIDEO:
-               strcpy(a->name, "Television");
-               break;
-       case CX231XX_AMUX_LINE_IN:
-               strcpy(a->name, "Line In");
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       a->index = dev->ctl_ainput;
-       a->capability = V4L2_AUDCAP_STEREO;
-
-       return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int status = 0;
-
-       /* Doesn't allow manual routing */
-       if (a->index != dev->ctl_ainput)
-               return -EINVAL;
-
-       dev->ctl_ainput = INPUT(a->index)->amux;
-       status = cx231xx_set_audio_input(dev, dev->ctl_ainput);
-
-       return status;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-                           struct v4l2_queryctrl *qc)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int id = qc->id;
-       int i;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       qc->id = v4l2_ctrl_next(ctrl_classes, qc->id);
-       if (unlikely(qc->id == 0))
-               return -EINVAL;
-
-       memset(qc, 0, sizeof(*qc));
-
-       qc->id = id;
-
-       if (qc->id < V4L2_CID_BASE || qc->id >= V4L2_CID_LASTP1)
-               return -EINVAL;
-
-       for (i = 0; i < CX231XX_CTLS; i++)
-               if (cx231xx_ctls[i].v.id == qc->id)
-                       break;
-
-       if (i == CX231XX_CTLS) {
-               *qc = no_ctl;
-               return 0;
-       }
-       *qc = cx231xx_ctls[i].v;
-
-       call_all(dev, core, queryctrl, qc);
-
-       if (qc->type)
-               return 0;
-       else
-               return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                        struct v4l2_control *ctrl)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       call_all(dev, core, g_ctrl, ctrl);
-       return rc;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                        struct v4l2_control *ctrl)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       call_all(dev, core, s_ctrl, ctrl);
-       return rc;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (0 != t->index)
-               return -EINVAL;
-
-       strcpy(t->name, "Tuner");
-
-       t->type = V4L2_TUNER_ANALOG_TV;
-       t->capability = V4L2_TUNER_CAP_NORM;
-       t->rangehigh = 0xffffffffUL;
-       t->signal = 0xffff;     /* LOCKED */
-
-       return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (0 != t->index)
-               return -EINVAL;
-#if 0
-       call_all(dev, tuner, s_tuner, t);
-#endif
-       return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-                             struct v4l2_frequency *f)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-
-       f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-       f->frequency = dev->ctl_freq;
-
-       call_all(dev, tuner, g_frequency, f);
-
-       return 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
-                             struct v4l2_frequency *f)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-       u32 if_frequency = 5400000;
-
-       cx231xx_info("Enter vidioc_s_frequency()f->frequency=%d;f->type=%d\n",
-                f->frequency, f->type);
-       /*cx231xx_info("f->type:  1-radio 2-analogTV 3-digitalTV\n");*/
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (0 != f->tuner)
-               return -EINVAL;
-
-       if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
-               return -EINVAL;
-       if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
-               return -EINVAL;
-
-       /* set pre channel change settings in DIF first */
-       rc = cx231xx_tuner_pre_channel_change(dev);
-
-       dev->ctl_freq = f->frequency;
-       call_all(dev, tuner, s_frequency, f);
-
-       /* set post channel change settings in DIF first */
-       rc = cx231xx_tuner_post_channel_change(dev);
-
-       if (dev->tuner_type == TUNER_NXP_TDA18271) {
-               if (dev->norm & (V4L2_STD_MN | V4L2_STD_NTSC_443))
-                       if_frequency = 5400000;  /*5.4MHz       */
-               else if (dev->norm & V4L2_STD_B)
-                       if_frequency = 6000000;  /*6.0MHz       */
-               else if (dev->norm & (V4L2_STD_PAL_DK | V4L2_STD_SECAM_DK))
-                       if_frequency = 6900000;  /*6.9MHz       */
-               else if (dev->norm & V4L2_STD_GH)
-                       if_frequency = 7100000;  /*7.1MHz       */
-               else if (dev->norm & V4L2_STD_PAL_I)
-                       if_frequency = 7250000;  /*7.25MHz      */
-               else if (dev->norm & V4L2_STD_SECAM_L)
-                       if_frequency = 6900000;  /*6.9MHz       */
-               else if (dev->norm & V4L2_STD_SECAM_LC)
-                       if_frequency = 1250000;  /*1.25MHz      */
-
-               cx231xx_info("if_frequency is set to %d\n", if_frequency);
-               cx231xx_set_Colibri_For_LowIF(dev, if_frequency, 1, 1);
-
-               update_HH_register_after_set_DIF(dev);
-       }
-
-       cx231xx_info("Set New FREQUENCY to %d\n", f->frequency);
-
-       return rc;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-
-/*
-  -R, --list-registers=type=<host/i2cdrv/i2caddr>,
-                               chip=<chip>[,min=<addr>,max=<addr>]
-                    dump registers from <min> to <max> [VIDIOC_DBG_G_REGISTER]
-  -r, --set-register=type=<host/i2cdrv/i2caddr>,
-                               chip=<chip>,reg=<addr>,val=<val>
-                    set the register [VIDIOC_DBG_S_REGISTER]
-
-  if type == host, then <chip> is the hosts chip ID (default 0)
-  if type == i2cdrv (default), then <chip> is the I2C driver name or ID
-  if type == i2caddr, then <chip> is the 7-bit I2C address
-*/
-
-static int vidioc_g_register(struct file *file, void *priv,
-                            struct v4l2_dbg_register *reg)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int ret = 0;
-       u8 value[4] = { 0, 0, 0, 0 };
-       u32 data = 0;
-
-       switch (reg->match.type) {
-       case V4L2_CHIP_MATCH_HOST:
-               switch (reg->match.addr) {
-               case 0: /* Cx231xx - internal registers */
-                       ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER,
-                                                 (u16)reg->reg, value, 4);
-                       reg->val = value[0] | value[1] << 8 |
-                                  value[2] << 16 | value[3] << 24;
-                       break;
-               case 1: /* AFE - read byte */
-                       ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS,
-                                                 (u16)reg->reg, 2, &data, 1);
-                       reg->val = le32_to_cpu(data & 0xff);
-                       break;
-               case 14: /* AFE - read dword */
-                       ret = cx231xx_read_i2c_data(dev, AFE_DEVICE_ADDRESS,
-                                                 (u16)reg->reg, 2, &data, 4);
-                       reg->val = le32_to_cpu(data);
-                       break;
-               case 2: /* Video Block - read byte */
-                       ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
-                                                 (u16)reg->reg, 2, &data, 1);
-                       reg->val = le32_to_cpu(data & 0xff);
-                       break;
-               case 24: /* Video Block - read dword */
-                       ret = cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
-                                                 (u16)reg->reg, 2, &data, 4);
-                       reg->val = le32_to_cpu(data);
-                       break;
-               case 3: /* I2S block - read byte */
-                       ret = cx231xx_read_i2c_data(dev,
-                                                   I2S_BLK_DEVICE_ADDRESS,
-                                                   (u16)reg->reg, 1,
-                                                   &data, 1);
-                       reg->val = le32_to_cpu(data & 0xff);
-                       break;
-               case 34: /* I2S Block - read dword */
-                       ret =
-                           cx231xx_read_i2c_data(dev, I2S_BLK_DEVICE_ADDRESS,
-                                                 (u16)reg->reg, 1, &data, 4);
-                       reg->val = le32_to_cpu(data);
-                       break;
-               }
-               return ret < 0 ? ret : 0;
-
-       case V4L2_CHIP_MATCH_I2C_DRIVER:
-               call_all(dev, core, g_register, reg);
-               return 0;
-       case V4L2_CHIP_MATCH_I2C_ADDR:/*for register debug*/
-               switch (reg->match.addr) {
-               case 0: /* Cx231xx - internal registers */
-                       ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER,
-                                                 (u16)reg->reg, value, 4);
-                       reg->val = value[0] | value[1] << 8 |
-                                  value[2] << 16 | value[3] << 24;
-
-                       break;
-               case 0x600:/* AFE - read byte */
-                       ret = cx231xx_read_i2c_master(dev, AFE_DEVICE_ADDRESS,
-                                                (u16)reg->reg, 2,
-                                                &data, 1 , 0);
-                       reg->val = le32_to_cpu(data & 0xff);
-                       break;
-
-               case 0x880:/* Video Block - read byte */
-                       if (reg->reg < 0x0b) {
-                               ret = cx231xx_read_i2c_master(dev,
-                                               VID_BLK_I2C_ADDRESS,
-                                                (u16)reg->reg, 2,
-                                                &data, 1 , 0);
-                               reg->val = le32_to_cpu(data & 0xff);
-                       } else {
-                               ret = cx231xx_read_i2c_master(dev,
-                                               VID_BLK_I2C_ADDRESS,
-                                                (u16)reg->reg, 2,
-                                                &data, 4 , 0);
-                               reg->val = le32_to_cpu(data);
-                       }
-                       break;
-               case 0x980:
-                       ret = cx231xx_read_i2c_master(dev,
-                                               I2S_BLK_DEVICE_ADDRESS,
-                                               (u16)reg->reg, 1,
-                                               &data, 1 , 0);
-                       reg->val = le32_to_cpu(data & 0xff);
-                       break;
-               case 0x400:
-                       ret =
-                           cx231xx_read_i2c_master(dev, 0x40,
-                                                 (u16)reg->reg, 1,
-                                                &data, 1 , 0);
-                       reg->val = le32_to_cpu(data & 0xff);
-                       break;
-               case 0xc01:
-                       ret =
-                               cx231xx_read_i2c_master(dev, 0xc0,
-                                               (u16)reg->reg, 2,
-                                                &data, 38, 1);
-                       reg->val = le32_to_cpu(data);
-                       break;
-               case 0x022:
-                       ret =
-                               cx231xx_read_i2c_master(dev, 0x02,
-                                               (u16)reg->reg, 1,
-                                                &data, 1, 2);
-                       reg->val = le32_to_cpu(data & 0xff);
-                       break;
-               case 0x322:
-                       ret = cx231xx_read_i2c_master(dev,
-                                               0x32,
-                                                (u16)reg->reg, 1,
-                                                &data, 4 , 2);
-                               reg->val = le32_to_cpu(data);
-                       break;
-               case 0x342:
-                       ret = cx231xx_read_i2c_master(dev,
-                                               0x34,
-                                                (u16)reg->reg, 1,
-                                                &data, 4 , 2);
-                               reg->val = le32_to_cpu(data);
-                       break;
-
-               default:
-                       cx231xx_info("no match device address!!\n");
-                       break;
-                       }
-               return ret < 0 ? ret : 0;
-               /*return -EINVAL;*/
-       default:
-               if (!v4l2_chip_match_host(&reg->match))
-                       return -EINVAL;
-       }
-
-       call_all(dev, core, g_register, reg);
-
-       return ret;
-}
-
-static int vidioc_s_register(struct file *file, void *priv,
-                            struct v4l2_dbg_register *reg)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int ret = 0;
-       __le64 buf;
-       u32 value;
-       u8 data[4] = { 0, 0, 0, 0 };
-
-       buf = cpu_to_le64(reg->val);
-
-       switch (reg->match.type) {
-       case V4L2_CHIP_MATCH_HOST:
-               {
-                       value = (u32) buf & 0xffffffff;
-
-                       switch (reg->match.addr) {
-                       case 0: /* cx231xx internal registers */
-                               data[0] = (u8) value;
-                               data[1] = (u8) (value >> 8);
-                               data[2] = (u8) (value >> 16);
-                               data[3] = (u8) (value >> 24);
-                               ret = cx231xx_write_ctrl_reg(dev,
-                                                          VRT_SET_REGISTER,
-                                                          (u16)reg->reg, data,
-                                                          4);
-                               break;
-                       case 1: /* AFE - read byte */
-                               ret = cx231xx_write_i2c_data(dev,
-                                                       AFE_DEVICE_ADDRESS,
-                                                       (u16)reg->reg, 2,
-                                                       value, 1);
-                               break;
-                       case 14: /* AFE - read dword */
-                               ret = cx231xx_write_i2c_data(dev,
-                                                       AFE_DEVICE_ADDRESS,
-                                                       (u16)reg->reg, 2,
-                                                       value, 4);
-                               break;
-                       case 2: /* Video Block - read byte */
-                               ret =
-                                   cx231xx_write_i2c_data(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       (u16)reg->reg, 2,
-                                                       value, 1);
-                               break;
-                       case 24: /* Video Block - read dword */
-                               ret =
-                                   cx231xx_write_i2c_data(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       (u16)reg->reg, 2,
-                                                       value, 4);
-                               break;
-                       case 3: /* I2S block - read byte */
-                               ret =
-                                   cx231xx_write_i2c_data(dev,
-                                                       I2S_BLK_DEVICE_ADDRESS,
-                                                       (u16)reg->reg, 1,
-                                                       value, 1);
-                               break;
-                       case 34: /* I2S block - read dword */
-                               ret =
-                                   cx231xx_write_i2c_data(dev,
-                                                       I2S_BLK_DEVICE_ADDRESS,
-                                                       (u16)reg->reg, 1,
-                                                       value, 4);
-                               break;
-                       }
-               }
-               return ret < 0 ? ret : 0;
-       case V4L2_CHIP_MATCH_I2C_ADDR:
-               {
-                       value = (u32) buf & 0xffffffff;
-
-                       switch (reg->match.addr) {
-                       case 0:/*cx231xx internal registers*/
-                                       data[0] = (u8) value;
-                                       data[1] = (u8) (value >> 8);
-                                       data[2] = (u8) (value >> 16);
-                                       data[3] = (u8) (value >> 24);
-                                       ret = cx231xx_write_ctrl_reg(dev,
-                                                          VRT_SET_REGISTER,
-                                                          (u16)reg->reg, data,
-                                                          4);
-                                       break;
-                       case 0x600:/* AFE - read byte */
-                                       ret = cx231xx_write_i2c_master(dev,
-                                                       AFE_DEVICE_ADDRESS,
-                                                       (u16)reg->reg, 2,
-                                                       value, 1 , 0);
-                                       break;
-
-                       case 0x880:/* Video Block - read byte */
-                                       if (reg->reg < 0x0b)
-                                               cx231xx_write_i2c_master(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       (u16)reg->reg, 2,
-                                                       value, 1, 0);
-                                       else
-                                               cx231xx_write_i2c_master(dev,
-                                                       VID_BLK_I2C_ADDRESS,
-                                                       (u16)reg->reg, 2,
-                                                       value, 4, 0);
-                                       break;
-                       case 0x980:
-                                       ret =
-                                               cx231xx_write_i2c_master(dev,
-                                                       I2S_BLK_DEVICE_ADDRESS,
-                                                       (u16)reg->reg, 1,
-                                                       value, 1, 0);
-                                       break;
-                       case 0x400:
-                                       ret =
-                                               cx231xx_write_i2c_master(dev,
-                                                       0x40,
-                                                       (u16)reg->reg, 1,
-                                                       value, 1, 0);
-                                       break;
-                       case 0xc01:
-                                       ret =
-                                               cx231xx_write_i2c_master(dev,
-                                                        0xc0,
-                                                        (u16)reg->reg, 1,
-                                                        value, 1, 1);
-                                       break;
-
-                       case 0x022:
-                                       ret =
-                                               cx231xx_write_i2c_master(dev,
-                                                       0x02,
-                                                       (u16)reg->reg, 1,
-                                                       value, 1, 2);
-                       case 0x322:
-                                       ret =
-                                               cx231xx_write_i2c_master(dev,
-                                                       0x32,
-                                                       (u16)reg->reg, 1,
-                                                       value, 4, 2);
-                                       break;
-
-                       case 0x342:
-                                       ret =
-                                               cx231xx_write_i2c_master(dev,
-                                                       0x34,
-                                                       (u16)reg->reg, 1,
-                                                       value, 4, 2);
-                                       break;
-                       default:
-                               cx231xx_info("no match device address, "
-                                       "the value is %x\n", reg->match.addr);
-                                       break;
-
-                                       }
-
-               }
-       default:
-               break;
-       }
-
-       call_all(dev, core, s_register, reg);
-
-       return ret;
-}
-#endif
-
-static int vidioc_cropcap(struct file *file, void *priv,
-                         struct v4l2_cropcap *cc)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-
-       if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       cc->bounds.left = 0;
-       cc->bounds.top = 0;
-       cc->bounds.width = dev->width;
-       cc->bounds.height = dev->height;
-       cc->defrect = cc->bounds;
-       cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */
-       cc->pixelaspect.denominator = 59;
-
-       return 0;
-}
-
-static int vidioc_streamon(struct file *file, void *priv,
-                          enum v4l2_buf_type type)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       rc = res_get(fh);
-
-       if (likely(rc >= 0))
-               rc = videobuf_streamon(&fh->vb_vidq);
-
-       call_all(dev, video, s_stream, 1);
-
-       return rc;
-}
-
-static int vidioc_streamoff(struct file *file, void *priv,
-                           enum v4l2_buf_type type)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       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;
-
-       cx25840_call(dev, video, s_stream, 0);
-
-       videobuf_streamoff(&fh->vb_vidq);
-       res_free(fh);
-
-       return 0;
-}
-
-static int vidioc_querycap(struct file *file, void *priv,
-                          struct v4l2_capability *cap)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-
-       strlcpy(cap->driver, "cx231xx", sizeof(cap->driver));
-       strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
-       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
-
-       cap->capabilities = V4L2_CAP_VBI_CAPTURE |
-#if 0
-               V4L2_CAP_SLICED_VBI_CAPTURE |
-#endif
-               V4L2_CAP_VIDEO_CAPTURE  |
-               V4L2_CAP_AUDIO          |
-               V4L2_CAP_READWRITE      |
-               V4L2_CAP_STREAMING;
-
-       if (dev->tuner_type != TUNER_ABSENT)
-               cap->capabilities |= V4L2_CAP_TUNER;
-
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
-                                  struct v4l2_fmtdesc *f)
-{
-       if (unlikely(f->index >= ARRAY_SIZE(format)))
-               return -EINVAL;
-
-       strlcpy(f->description, format[f->index].name, sizeof(f->description));
-       f->pixelformat = format[f->index].fourcc;
-
-       return 0;
-}
-
-/* Sliced VBI ioctls */
-static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
-                                      struct v4l2_format *f)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       f->fmt.sliced.service_set = 0;
-
-       call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced);
-
-       if (f->fmt.sliced.service_set == 0)
-               rc = -EINVAL;
-
-       return rc;
-}
-
-static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
-                                        struct v4l2_format *f)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       call_all(dev, vbi, g_sliced_fmt, &f->fmt.sliced);
-
-       if (f->fmt.sliced.service_set == 0)
-               return -EINVAL;
-
-       return 0;
-}
-
-/* RAW VBI ioctls */
-
-static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
-                               struct v4l2_format *f)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       f->fmt.vbi.sampling_rate = 6750000 * 4;
-       f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
-       f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
-       f->fmt.vbi.offset = 0;
-       f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ?
-           PAL_VBI_START_LINE : NTSC_VBI_START_LINE;
-       f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ?
-           PAL_VBI_LINES : NTSC_VBI_LINES;
-       f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ?
-           PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263;
-       f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
-
-       return 0;
-
-}
-
-static int vidioc_try_fmt_vbi_cap(struct file *file, void *priv,
-                                 struct v4l2_format *f)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-
-       if (dev->vbi_stream_on && !fh->stream_on) {
-               cx231xx_errdev("%s device in use by another fh\n", __func__);
-               return -EBUSY;
-       }
-
-       f->type = V4L2_BUF_TYPE_VBI_CAPTURE;
-       f->fmt.vbi.sampling_rate = 6750000 * 4;
-       f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
-       f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
-       f->fmt.vbi.offset = 0;
-       f->fmt.vbi.flags = 0;
-       f->fmt.vbi.start[0] = (dev->norm & V4L2_STD_625_50) ?
-           PAL_VBI_START_LINE : NTSC_VBI_START_LINE;
-       f->fmt.vbi.count[0] = (dev->norm & V4L2_STD_625_50) ?
-           PAL_VBI_LINES : NTSC_VBI_LINES;
-       f->fmt.vbi.start[1] = (dev->norm & V4L2_STD_625_50) ?
-           PAL_VBI_START_LINE + 312 : NTSC_VBI_START_LINE + 263;
-       f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
-
-       return 0;
-
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
-                         struct v4l2_requestbuffers *rb)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       return videobuf_reqbufs(&fh->vb_vidq, rb);
-}
-
-static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       return videobuf_querybuf(&fh->vb_vidq, b);
-}
-
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       return videobuf_qbuf(&fh->vb_vidq, b);
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct cx231xx_fh *fh = priv;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags & O_NONBLOCK);
-}
-
-/* ----------------------------------------------------------- */
-/* RADIO ESPECIFIC IOCTLS                                      */
-/* ----------------------------------------------------------- */
-
-static int radio_querycap(struct file *file, void *priv,
-                         struct v4l2_capability *cap)
-{
-       struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
-
-       strlcpy(cap->driver, "cx231xx", sizeof(cap->driver));
-       strlcpy(cap->card, cx231xx_boards[dev->model].name, sizeof(cap->card));
-       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
-
-       cap->capabilities = V4L2_CAP_TUNER;
-       return 0;
-}
-
-static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
-{
-       struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
-
-       if (unlikely(t->index > 0))
-               return -EINVAL;
-
-       strcpy(t->name, "Radio");
-       t->type = V4L2_TUNER_RADIO;
-
-       call_all(dev, tuner, s_tuner, t);
-
-       return 0;
-}
-
-static int radio_enum_input(struct file *file, void *priv, struct v4l2_input *i)
-{
-       if (i->index != 0)
-               return -EINVAL;
-       strcpy(i->name, "Radio");
-       i->type = V4L2_INPUT_TYPE_TUNER;
-
-       return 0;
-}
-
-static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-       if (unlikely(a->index))
-               return -EINVAL;
-
-       strcpy(a->name, "Radio");
-       return 0;
-}
-
-static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
-{
-       struct cx231xx *dev = ((struct cx231xx_fh *)priv)->dev;
-
-       if (0 != t->index)
-               return -EINVAL;
-
-       call_all(dev, tuner, s_tuner, t);
-
-       return 0;
-}
-
-static int radio_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
-{
-       return 0;
-}
-
-static int radio_s_input(struct file *file, void *fh, unsigned int i)
-{
-       return 0;
-}
-
-static int radio_queryctrl(struct file *file, void *priv,
-                          struct v4l2_queryctrl *c)
-{
-       int i;
-
-       if (c->id < V4L2_CID_BASE || c->id >= V4L2_CID_LASTP1)
-               return -EINVAL;
-       if (c->id == V4L2_CID_AUDIO_MUTE) {
-               for (i = 0; i < CX231XX_CTLS; i++) {
-                       if (cx231xx_ctls[i].v.id == c->id)
-                               break;
-               }
-               if (i == CX231XX_CTLS)
-                       return -EINVAL;
-               *c = cx231xx_ctls[i].v;
-       } else
-               *c = no_ctl;
-       return 0;
-}
-
-/*
- * cx231xx_v4l2_open()
- * inits the device and starts isoc transfer
- */
-static int cx231xx_v4l2_open(struct file *filp)
-{
-       int errCode = 0, radio = 0;
-       struct video_device *vdev = video_devdata(filp);
-       struct cx231xx *dev = video_drvdata(filp);
-       struct cx231xx_fh *fh;
-       enum v4l2_buf_type fh_type = 0;
-
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_GRABBER:
-               fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               break;
-       case VFL_TYPE_VBI:
-               fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
-               break;
-       case VFL_TYPE_RADIO:
-               radio = 1;
-               break;
-       }
-
-       cx231xx_videodbg("open dev=%s type=%s users=%d\n",
-                        video_device_node_name(vdev), v4l2_type_names[fh_type],
-                        dev->users);
-
-#if 0
-       errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
-       if (errCode < 0) {
-               cx231xx_errdev
-                   ("Device locked on digital mode. Can't open analog\n");
-               return -EBUSY;
-       }
-#endif
-
-       fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL);
-       if (!fh) {
-               cx231xx_errdev("cx231xx-video.c: Out of memory?!\n");
-               return -ENOMEM;
-       }
-       if (mutex_lock_interruptible(&dev->lock)) {
-               kfree(fh);
-               return -ERESTARTSYS;
-       }
-       fh->dev = dev;
-       fh->radio = radio;
-       fh->type = fh_type;
-       filp->private_data = fh;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
-               dev->width = norm_maxw(dev);
-               dev->height = norm_maxh(dev);
-
-               /* Power up in Analog TV mode */
-               if (dev->board.external_av)
-                       cx231xx_set_power_mode(dev,
-                                POLARIS_AVMODE_ENXTERNAL_AV);
-               else
-                       cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV);
-
-#if 0
-               cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
-#endif
-
-               /* set video alternate setting */
-               cx231xx_set_video_alternate(dev);
-
-               /* Needed, since GPIO might have disabled power of
-                  some i2c device */
-               cx231xx_config_i2c(dev);
-
-               /* device needs to be initialized before isoc transfer */
-               dev->video_input = dev->video_input > 2 ? 2 : dev->video_input;
-
-       }
-       if (fh->radio) {
-               cx231xx_videodbg("video_open: setting radio device\n");
-
-               /* cx231xx_start_radio(dev); */
-
-               call_all(dev, tuner, s_radio);
-       }
-
-       dev->users++;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_video_qops,
-                                           NULL, &dev->video_mode.slock,
-                                           fh->type, V4L2_FIELD_INTERLACED,
-                                           sizeof(struct cx231xx_buffer),
-                                           fh, &dev->lock);
-       if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-               /* Set the required alternate setting  VBI interface works in
-                  Bulk mode only */
-               cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
-
-               videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops,
-                                           NULL, &dev->vbi_mode.slock,
-                                           fh->type, V4L2_FIELD_SEQ_TB,
-                                           sizeof(struct cx231xx_buffer),
-                                           fh, &dev->lock);
-       }
-       mutex_unlock(&dev->lock);
-
-       return errCode;
-}
-
-/*
- * cx231xx_realease_resources()
- * unregisters the v4l2,i2c and usb devices
- * called when the device gets disconected or at module unload
-*/
-void cx231xx_release_analog_resources(struct cx231xx *dev)
-{
-
-       /*FIXME: I2C IR should be disconnected */
-
-       if (dev->radio_dev) {
-               if (video_is_registered(dev->radio_dev))
-                       video_unregister_device(dev->radio_dev);
-               else
-                       video_device_release(dev->radio_dev);
-               dev->radio_dev = NULL;
-       }
-       if (dev->vbi_dev) {
-               cx231xx_info("V4L2 device %s deregistered\n",
-                            video_device_node_name(dev->vbi_dev));
-               if (video_is_registered(dev->vbi_dev))
-                       video_unregister_device(dev->vbi_dev);
-               else
-                       video_device_release(dev->vbi_dev);
-               dev->vbi_dev = NULL;
-       }
-       if (dev->vdev) {
-               cx231xx_info("V4L2 device %s deregistered\n",
-                            video_device_node_name(dev->vdev));
-
-               if (dev->board.has_417)
-                       cx231xx_417_unregister(dev);
-
-               if (video_is_registered(dev->vdev))
-                       video_unregister_device(dev->vdev);
-               else
-                       video_device_release(dev->vdev);
-               dev->vdev = NULL;
-       }
-}
-
-/*
- * cx231xx_close()
- * stops streaming and deallocates all resources allocated by the v4l2
- * calls and ioctls
- */
-static int cx231xx_close(struct file *filp)
-{
-       struct cx231xx_fh *fh = filp->private_data;
-       struct cx231xx *dev = fh->dev;
-
-       cx231xx_videodbg("users=%d\n", dev->users);
-
-       cx231xx_videodbg("users=%d\n", dev->users);
-       if (res_check(fh))
-               res_free(fh);
-
-       /*
-        * To workaround error number=-71 on EP0 for VideoGrabber,
-        *       need exclude following.
-        * FIXME: It is probably safe to remove most of these, as we're
-        * now avoiding the alternate setting for INDEX_VANC
-        */
-       if (!dev->board.no_alt_vanc)
-               if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-                       videobuf_stop(&fh->vb_vidq);
-                       videobuf_mmap_free(&fh->vb_vidq);
-
-                       /* the device is already disconnect,
-                          free the remaining resources */
-                       if (dev->state & DEV_DISCONNECTED) {
-                               if (atomic_read(&dev->devlist_count) > 0) {
-                                       cx231xx_release_resources(dev);
-                                       fh->dev = NULL;
-                                       return 0;
-                               }
-                               return 0;
-                       }
-
-                       /* do this before setting alternate! */
-                       cx231xx_uninit_vbi_isoc(dev);
-
-                       /* set alternate 0 */
-                       if (!dev->vbi_or_sliced_cc_mode)
-                               cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
-                       else
-                               cx231xx_set_alt_setting(dev, INDEX_HANC, 0);
-
-                       kfree(fh);
-                       dev->users--;
-                       wake_up_interruptible_nr(&dev->open, 1);
-                       return 0;
-               }
-
-       dev->users--;
-       if (!dev->users) {
-               videobuf_stop(&fh->vb_vidq);
-               videobuf_mmap_free(&fh->vb_vidq);
-
-               /* the device is already disconnect,
-                  free the remaining resources */
-               if (dev->state & DEV_DISCONNECTED) {
-                       cx231xx_release_resources(dev);
-                       fh->dev = NULL;
-                       return 0;
-               }
-
-               /* Save some power by putting tuner to sleep */
-               call_all(dev, core, s_power, 0);
-
-               /* do this before setting alternate! */
-               if (dev->USE_ISO)
-                       cx231xx_uninit_isoc(dev);
-               else
-                       cx231xx_uninit_bulk(dev);
-               cx231xx_set_mode(dev, CX231XX_SUSPEND);
-
-               /* set alternate 0 */
-               cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);
-       }
-       kfree(fh);
-       wake_up_interruptible_nr(&dev->open, 1);
-       return 0;
-}
-
-static int cx231xx_v4l2_close(struct file *filp)
-{
-       struct cx231xx_fh *fh = filp->private_data;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       mutex_lock(&dev->lock);
-       rc = cx231xx_close(filp);
-       mutex_unlock(&dev->lock);
-       return rc;
-}
-
-/*
- * cx231xx_v4l2_read()
- * will allocate buffers when called for the first time
- */
-static ssize_t
-cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
-                 loff_t *pos)
-{
-       struct cx231xx_fh *fh = filp->private_data;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if ((fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
-           (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)) {
-               rc = res_get(fh);
-
-               if (unlikely(rc < 0))
-                       return rc;
-
-               if (mutex_lock_interruptible(&dev->lock))
-                       return -ERESTARTSYS;
-               rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
-                                           filp->f_flags & O_NONBLOCK);
-               mutex_unlock(&dev->lock);
-               return rc;
-       }
-       return 0;
-}
-
-/*
- * cx231xx_v4l2_poll()
- * will allocate buffers when called for the first time
- */
-static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table *wait)
-{
-       struct cx231xx_fh *fh = filp->private_data;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       rc = res_get(fh);
-
-       if (unlikely(rc < 0))
-               return POLLERR;
-
-       if ((V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) ||
-           (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)) {
-               unsigned int res;
-
-               mutex_lock(&dev->lock);
-               res = videobuf_poll_stream(filp, &fh->vb_vidq, wait);
-               mutex_unlock(&dev->lock);
-               return res;
-       }
-       return POLLERR;
-}
-
-/*
- * cx231xx_v4l2_mmap()
- */
-static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-       struct cx231xx_fh *fh = filp->private_data;
-       struct cx231xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       rc = res_get(fh);
-
-       if (unlikely(rc < 0))
-               return rc;
-
-       if (mutex_lock_interruptible(&dev->lock))
-               return -ERESTARTSYS;
-       rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
-       mutex_unlock(&dev->lock);
-
-       cx231xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
-                        (unsigned long)vma->vm_start,
-                        (unsigned long)vma->vm_end -
-                        (unsigned long)vma->vm_start, rc);
-
-       return rc;
-}
-
-static const struct v4l2_file_operations cx231xx_v4l_fops = {
-       .owner   = THIS_MODULE,
-       .open    = cx231xx_v4l2_open,
-       .release = cx231xx_v4l2_close,
-       .read    = cx231xx_v4l2_read,
-       .poll    = cx231xx_v4l2_poll,
-       .mmap    = cx231xx_v4l2_mmap,
-       .unlocked_ioctl   = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops video_ioctl_ops = {
-       .vidioc_querycap               = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap       = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap          = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap        = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap          = vidioc_s_fmt_vid_cap,
-       .vidioc_g_fmt_vbi_cap          = vidioc_g_fmt_vbi_cap,
-       .vidioc_try_fmt_vbi_cap        = vidioc_try_fmt_vbi_cap,
-       .vidioc_s_fmt_vbi_cap          = vidioc_try_fmt_vbi_cap,
-       .vidioc_g_audio                =  vidioc_g_audio,
-       .vidioc_s_audio                = vidioc_s_audio,
-       .vidioc_cropcap                = vidioc_cropcap,
-       .vidioc_g_fmt_sliced_vbi_cap   = vidioc_g_fmt_sliced_vbi_cap,
-       .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
-       .vidioc_reqbufs                = vidioc_reqbufs,
-       .vidioc_querybuf               = vidioc_querybuf,
-       .vidioc_qbuf                   = vidioc_qbuf,
-       .vidioc_dqbuf                  = vidioc_dqbuf,
-       .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_queryctrl              = vidioc_queryctrl,
-       .vidioc_g_ctrl                 = vidioc_g_ctrl,
-       .vidioc_s_ctrl                 = vidioc_s_ctrl,
-       .vidioc_streamon               = vidioc_streamon,
-       .vidioc_streamoff              = vidioc_streamoff,
-       .vidioc_g_tuner                = vidioc_g_tuner,
-       .vidioc_s_tuner                = vidioc_s_tuner,
-       .vidioc_g_frequency            = vidioc_g_frequency,
-       .vidioc_s_frequency            = vidioc_s_frequency,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register             = vidioc_g_register,
-       .vidioc_s_register             = vidioc_s_register,
-#endif
-};
-
-static struct video_device cx231xx_vbi_template;
-
-static const struct video_device cx231xx_video_template = {
-       .fops         = &cx231xx_v4l_fops,
-       .release      = video_device_release,
-       .ioctl_ops    = &video_ioctl_ops,
-       .tvnorms      = V4L2_STD_ALL,
-       .current_norm = V4L2_STD_PAL,
-};
-
-static const struct v4l2_file_operations radio_fops = {
-       .owner   = THIS_MODULE,
-       .open   = cx231xx_v4l2_open,
-       .release = cx231xx_v4l2_close,
-       .ioctl   = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops radio_ioctl_ops = {
-       .vidioc_querycap    = radio_querycap,
-       .vidioc_g_tuner     = radio_g_tuner,
-       .vidioc_enum_input  = radio_enum_input,
-       .vidioc_g_audio     = radio_g_audio,
-       .vidioc_s_tuner     = radio_s_tuner,
-       .vidioc_s_audio     = radio_s_audio,
-       .vidioc_s_input     = radio_s_input,
-       .vidioc_queryctrl   = radio_queryctrl,
-       .vidioc_g_ctrl      = vidioc_g_ctrl,
-       .vidioc_s_ctrl      = vidioc_s_ctrl,
-       .vidioc_g_frequency = vidioc_g_frequency,
-       .vidioc_s_frequency = vidioc_s_frequency,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register  = vidioc_g_register,
-       .vidioc_s_register  = vidioc_s_register,
-#endif
-};
-
-static struct video_device cx231xx_radio_template = {
-       .name      = "cx231xx-radio",
-       .fops      = &radio_fops,
-       .ioctl_ops = &radio_ioctl_ops,
-};
-
-/******************************** usb interface ******************************/
-
-static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
-               const struct video_device
-               *template, const char *type_name)
-{
-       struct video_device *vfd;
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-
-       *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);
-
-       video_set_drvdata(vfd, dev);
-       return vfd;
-}
-
-int cx231xx_register_analog_devices(struct cx231xx *dev)
-{
-       int ret;
-
-       cx231xx_info("%s: v4l2 driver version %s\n",
-                    dev->name, CX231XX_VERSION);
-
-       /* set default norm */
-       /*dev->norm = cx231xx_video_template.current_norm; */
-       dev->width = norm_maxw(dev);
-       dev->height = norm_maxh(dev);
-       dev->interlaced = 0;
-
-       /* Analog specific initialization */
-       dev->format = &format[0];
-
-       /* Set the initial input */
-       video_mux(dev, dev->video_input);
-
-       /* Audio defaults */
-       dev->mute = 1;
-       dev->volume = 0x1f;
-
-       /* enable vbi capturing */
-       /* write code here...  */
-
-       /* allocate and fill video video_device struct */
-       dev->vdev = cx231xx_vdev_init(dev, &cx231xx_video_template, "video");
-       if (!dev->vdev) {
-               cx231xx_errdev("cannot allocate video_device.\n");
-               return -ENODEV;
-       }
-
-       /* register v4l2 video video_device */
-       ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
-                                   video_nr[dev->devno]);
-       if (ret) {
-               cx231xx_errdev("unable to register video device (error=%i).\n",
-                              ret);
-               return ret;
-       }
-
-       cx231xx_info("%s/0: registered device %s [v4l2]\n",
-                    dev->name, video_device_node_name(dev->vdev));
-
-       /* Initialize VBI template */
-       memcpy(&cx231xx_vbi_template, &cx231xx_video_template,
-              sizeof(cx231xx_vbi_template));
-       strcpy(cx231xx_vbi_template.name, "cx231xx-vbi");
-
-       /* Allocate and fill vbi video_device struct */
-       dev->vbi_dev = cx231xx_vdev_init(dev, &cx231xx_vbi_template, "vbi");
-
-       /* register v4l2 vbi video_device */
-       ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
-                                   vbi_nr[dev->devno]);
-       if (ret < 0) {
-               cx231xx_errdev("unable to register vbi device\n");
-               return ret;
-       }
-
-       cx231xx_info("%s/0: registered device %s\n",
-                    dev->name, video_device_node_name(dev->vbi_dev));
-
-       if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) {
-               dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template,
-                                                  "radio");
-               if (!dev->radio_dev) {
-                       cx231xx_errdev("cannot allocate video_device.\n");
-                       return -ENODEV;
-               }
-               ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
-                                           radio_nr[dev->devno]);
-               if (ret < 0) {
-                       cx231xx_errdev("can't register radio device\n");
-                       return ret;
-               }
-               cx231xx_info("Registered radio device as %s\n",
-                            video_device_node_name(dev->radio_dev));
-       }
-
-       cx231xx_info("V4L2 device registered as %s and %s\n",
-                    video_device_node_name(dev->vdev),
-                    video_device_node_name(dev->vbi_dev));
-
-       return 0;
-}
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h
deleted file mode 100644 (file)
index a89d020..0000000
+++ /dev/null
@@ -1,1012 +0,0 @@
-/*
-   cx231xx.h - driver for Conexant Cx23100/101/102 USB video capture devices
-
-   Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
-       Based on em28xx driver
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   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.
- */
-
-#ifndef _CX231XX_H
-#define _CX231XX_H
-
-#include <linux/videodev2.h>
-#include <linux/types.h>
-#include <linux/ioctl.h>
-#include <linux/i2c.h>
-#include <linux/workqueue.h>
-#include <linux/mutex.h>
-
-#include <media/cx2341x.h>
-
-#include <media/videobuf-vmalloc.h>
-#include <media/v4l2-device.h>
-#include <media/rc-core.h>
-#include <media/ir-kbd-i2c.h>
-#include <media/videobuf-dvb.h>
-
-#include "cx231xx-reg.h"
-#include "cx231xx-pcb-cfg.h"
-#include "cx231xx-conf-reg.h"
-
-#define DRIVER_NAME                     "cx231xx"
-#define PWR_SLEEP_INTERVAL              10
-
-/* I2C addresses for control block in Cx231xx */
-#define     AFE_DEVICE_ADDRESS         0x60
-#define     I2S_BLK_DEVICE_ADDRESS     0x98
-#define     VID_BLK_I2C_ADDRESS                0x88
-#define     VERVE_I2C_ADDRESS           0x40
-#define     DIF_USE_BASEBAND            0xFFFFFFFF
-
-/* Boards supported by driver */
-#define CX231XX_BOARD_UNKNOWN              0
-#define CX231XX_BOARD_CNXT_CARRAERA    1
-#define CX231XX_BOARD_CNXT_SHELBY      2
-#define CX231XX_BOARD_CNXT_RDE_253S    3
-#define CX231XX_BOARD_CNXT_RDU_253S    4
-#define CX231XX_BOARD_CNXT_VIDEO_GRABBER       5
-#define CX231XX_BOARD_CNXT_RDE_250     6
-#define CX231XX_BOARD_CNXT_RDU_250     7
-#define CX231XX_BOARD_HAUPPAUGE_EXETER  8
-#define CX231XX_BOARD_HAUPPAUGE_USBLIVE2 9
-#define CX231XX_BOARD_PV_PLAYTV_USB_HYBRID 10
-#define CX231XX_BOARD_PV_XCAPTURE_USB 11
-#define CX231XX_BOARD_KWORLD_UB430_USB_HYBRID 12
-#define CX231XX_BOARD_ICONBIT_U100 13
-#define CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL 14
-#define CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC 15
-
-/* Limits minimum and default number of buffers */
-#define CX231XX_MIN_BUF                 4
-#define CX231XX_DEF_BUF                 12
-#define CX231XX_DEF_VBI_BUF             6
-
-#define VBI_LINE_COUNT                  17
-#define VBI_LINE_LENGTH                 1440
-
-/*Limits the max URB message size */
-#define URB_MAX_CTRL_SIZE               80
-
-/* Params for validated field */
-#define CX231XX_BOARD_NOT_VALIDATED     1
-#define CX231XX_BOARD_VALIDATED                0
-
-/* maximum number of cx231xx boards */
-#define CX231XX_MAXBOARDS               8
-
-/* maximum number of frames that can be queued */
-#define CX231XX_NUM_FRAMES              5
-
-/* number of buffers for isoc transfers */
-#define CX231XX_NUM_BUFS                8
-
-/* number of packets for each buffer
-   windows requests only 40 packets .. so we better do the same
-   this is what I found out for all alternate numbers there!
- */
-#define CX231XX_NUM_PACKETS             40
-
-/* default alternate; 0 means choose the best */
-#define CX231XX_PINOUT                  0
-
-#define CX231XX_INTERLACED_DEFAULT      1
-
-/* time to wait when stopping the isoc transfer */
-#define CX231XX_URB_TIMEOUT            \
-               msecs_to_jiffies(CX231XX_NUM_BUFS * CX231XX_NUM_PACKETS)
-
-#define CX231xx_NORMS (\
-       V4L2_STD_NTSC_M |  V4L2_STD_NTSC_M_JP |  V4L2_STD_NTSC_443 | \
-       V4L2_STD_PAL_BG |  V4L2_STD_PAL_DK    |  V4L2_STD_PAL_I    | \
-       V4L2_STD_PAL_M  |  V4L2_STD_PAL_N     |  V4L2_STD_PAL_Nc   | \
-       V4L2_STD_PAL_60 |  V4L2_STD_SECAM_L   |  V4L2_STD_SECAM_DK)
-
-#define SLEEP_S5H1432    30
-#define CX23417_OSC_EN   8
-#define CX23417_RESET    9
-
-struct cx23417_fmt {
-       char  *name;
-       u32   fourcc;          /* v4l2 format id */
-       int   depth;
-       int   flags;
-       u32   cxformat;
-};
-enum cx231xx_mode {
-       CX231XX_SUSPEND,
-       CX231XX_ANALOG_MODE,
-       CX231XX_DIGITAL_MODE,
-};
-
-enum cx231xx_std_mode {
-       CX231XX_TV_AIR = 0,
-       CX231XX_TV_CABLE
-};
-
-enum cx231xx_stream_state {
-       STREAM_OFF,
-       STREAM_INTERRUPT,
-       STREAM_ON,
-};
-
-struct cx231xx;
-
-struct cx231xx_isoc_ctl {
-       /* max packet size of isoc transaction */
-       int max_pkt_size;
-
-       /* number of allocated urbs */
-       int num_bufs;
-
-       /* urb for isoc transfers */
-       struct urb **urb;
-
-       /* transfer buffers for isoc transfer */
-       char **transfer_buffer;
-
-       /* Last buffer command and region */
-       u8 cmd;
-       int pos, size, pktsize;
-
-       /* Last field: ODD or EVEN? */
-       int field;
-
-       /* Stores incomplete commands */
-       u32 tmp_buf;
-       int tmp_buf_len;
-
-       /* Stores already requested buffers */
-       struct cx231xx_buffer *buf;
-
-       /* Stores the number of received fields */
-       int nfields;
-
-       /* isoc urb callback */
-       int (*isoc_copy) (struct cx231xx *dev, struct urb *urb);
-};
-
-struct cx231xx_bulk_ctl {
-       /* max packet size of bulk transaction */
-       int max_pkt_size;
-
-       /* number of allocated urbs */
-       int num_bufs;
-
-       /* urb for bulk transfers */
-       struct urb **urb;
-
-       /* transfer buffers for bulk transfer */
-       char **transfer_buffer;
-
-       /* Last buffer command and region */
-       u8 cmd;
-       int pos, size, pktsize;
-
-       /* Last field: ODD or EVEN? */
-       int field;
-
-       /* Stores incomplete commands */
-       u32 tmp_buf;
-       int tmp_buf_len;
-
-       /* Stores already requested buffers */
-       struct cx231xx_buffer *buf;
-
-       /* Stores the number of received fields */
-       int nfields;
-
-       /* bulk urb callback */
-       int (*bulk_copy) (struct cx231xx *dev, struct urb *urb);
-};
-
-struct cx231xx_fmt {
-       char *name;
-       u32 fourcc;             /* v4l2 format id */
-       int depth;
-       int reg;
-};
-
-/* buffer for one video frame */
-struct cx231xx_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
-
-       struct list_head frame;
-       int top_field;
-       int receiving;
-};
-
-enum ps_package_head {
-       CX231XX_NEED_ADD_PS_PACKAGE_HEAD = 0,
-       CX231XX_NONEED_PS_PACKAGE_HEAD
-};
-
-struct cx231xx_dmaqueue {
-       struct list_head active;
-       struct list_head queued;
-
-       wait_queue_head_t wq;
-
-       /* Counters to control buffer fill */
-       int pos;
-       u8 is_partial_line;
-       u8 partial_buf[8];
-       u8 last_sav;
-       int current_field;
-       u32 bytes_left_in_line;
-       u32 lines_completed;
-       u8 field1_done;
-       u32 lines_per_field;
-
-       /*Mpeg2 control buffer*/
-       u8 *p_left_data;
-       u32 left_data_count;
-       u8 mpeg_buffer_done;
-       u32 mpeg_buffer_completed;
-       enum ps_package_head add_ps_package_head;
-       char ps_head[10];
-};
-
-/* inputs */
-
-#define MAX_CX231XX_INPUT               4
-
-enum cx231xx_itype {
-       CX231XX_VMUX_COMPOSITE1 = 1,
-       CX231XX_VMUX_SVIDEO,
-       CX231XX_VMUX_TELEVISION,
-       CX231XX_VMUX_CABLE,
-       CX231XX_RADIO,
-       CX231XX_VMUX_DVB,
-       CX231XX_VMUX_DEBUG
-};
-
-enum cx231xx_v_input {
-       CX231XX_VIN_1_1 = 0x1,
-       CX231XX_VIN_2_1,
-       CX231XX_VIN_3_1,
-       CX231XX_VIN_4_1,
-       CX231XX_VIN_1_2 = 0x01,
-       CX231XX_VIN_2_2,
-       CX231XX_VIN_3_2,
-       CX231XX_VIN_1_3 = 0x1,
-       CX231XX_VIN_2_3,
-       CX231XX_VIN_3_3,
-};
-
-/* cx231xx has two audio inputs: tuner and line in */
-enum cx231xx_amux {
-       /* This is the only entry for cx231xx tuner input */
-       CX231XX_AMUX_VIDEO,     /* cx231xx tuner */
-       CX231XX_AMUX_LINE_IN,   /* Line In */
-};
-
-struct cx231xx_reg_seq {
-       unsigned char bit;
-       unsigned char val;
-       int sleep;
-};
-
-struct cx231xx_input {
-       enum cx231xx_itype type;
-       unsigned int vmux;
-       enum cx231xx_amux amux;
-       struct cx231xx_reg_seq *gpio;
-};
-
-#define INPUT(nr) (&cx231xx_boards[dev->model].input[nr])
-
-enum cx231xx_decoder {
-       CX231XX_NODECODER,
-       CX231XX_AVDECODER
-};
-
-enum CX231XX_I2C_MASTER_PORT {
-       I2C_0 = 0,
-       I2C_1 = 1,
-       I2C_2 = 2,
-       I2C_3 = 3
-};
-
-struct cx231xx_board {
-       char *name;
-       int vchannels;
-       int tuner_type;
-       int tuner_addr;
-       v4l2_std_id norm;       /* tv norm */
-
-       /* demod related */
-       int demod_addr;
-       u8 demod_xfer_mode;     /* 0 - Serial; 1 - parallel */
-
-       /* GPIO Pins */
-       struct cx231xx_reg_seq *dvb_gpio;
-       struct cx231xx_reg_seq *suspend_gpio;
-       struct cx231xx_reg_seq *tuner_gpio;
-               /* Negative means don't use it */
-       s8 tuner_sif_gpio;
-       s8 tuner_scl_gpio;
-       s8 tuner_sda_gpio;
-
-       /* PIN ctrl */
-       u32 ctl_pin_status_mask;
-       u8 agc_analog_digital_select_gpio;
-       u32 gpio_pin_status_mask;
-
-       /* i2c masters */
-       u8 tuner_i2c_master;
-       u8 demod_i2c_master;
-       u8 ir_i2c_master;
-
-       /* for devices with I2C chips for IR */
-       char *rc_map_name;
-
-       unsigned int max_range_640_480:1;
-       unsigned int has_dvb:1;
-       unsigned int has_417:1;
-       unsigned int valid:1;
-       unsigned int no_alt_vanc:1;
-       unsigned int external_av:1;
-       unsigned int dont_use_port_3:1;
-
-       unsigned char xclk, i2c_speed;
-
-       enum cx231xx_decoder decoder;
-       int output_mode;
-
-       struct cx231xx_input input[MAX_CX231XX_INPUT];
-       struct cx231xx_input radio;
-       struct rc_map *ir_codes;
-};
-
-/* device states */
-enum cx231xx_dev_state {
-       DEV_INITIALIZED = 0x01,
-       DEV_DISCONNECTED = 0x02,
-};
-
-enum AFE_MODE {
-       AFE_MODE_LOW_IF,
-       AFE_MODE_BASEBAND,
-       AFE_MODE_EU_HI_IF,
-       AFE_MODE_US_HI_IF,
-       AFE_MODE_JAPAN_HI_IF
-};
-
-enum AUDIO_INPUT {
-       AUDIO_INPUT_MUTE,
-       AUDIO_INPUT_LINE,
-       AUDIO_INPUT_TUNER_TV,
-       AUDIO_INPUT_SPDIF,
-       AUDIO_INPUT_TUNER_FM
-};
-
-#define CX231XX_AUDIO_BUFS              5
-#define CX231XX_NUM_AUDIO_PACKETS       16
-#define CX231XX_ISO_NUM_AUDIO_PACKETS  64
-
-/* cx231xx extensions */
-#define CX231XX_AUDIO                   0x10
-#define CX231XX_DVB                     0x20
-
-struct cx231xx_audio {
-       char name[50];
-       char *transfer_buffer[CX231XX_AUDIO_BUFS];
-       struct urb *urb[CX231XX_AUDIO_BUFS];
-       struct usb_device *udev;
-       unsigned int capture_transfer_done;
-       struct snd_pcm_substream *capture_pcm_substream;
-
-       unsigned int hwptr_done_capture;
-       struct snd_card *sndcard;
-
-       int users, shutdown;
-       /* locks */
-       spinlock_t slock;
-
-       int alt;                /* alternate */
-       int max_pkt_size;       /* max packet size of isoc transaction */
-       int num_alt;            /* Number of alternative settings */
-       unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
-       u16 end_point_addr;
-};
-
-struct cx231xx;
-
-struct cx231xx_fh {
-       struct cx231xx *dev;
-       unsigned int stream_on:1;       /* Locks streams */
-       int radio;
-
-       struct videobuf_queue vb_vidq;
-
-       enum v4l2_buf_type type;
-
-
-
-/*following is copyed from cx23885.h*/
-       u32                        resources;
-
-       /* video overlay */
-       struct v4l2_window         win;
-       struct v4l2_clip           *clips;
-       unsigned int               nclips;
-
-       /* video capture */
-       struct cx23417_fmt         *fmt;
-       unsigned int               width, height;
-
-       /* vbi capture */
-       struct videobuf_queue      vidq;
-       struct videobuf_queue      vbiq;
-
-       /* MPEG Encoder specifics ONLY */
-
-       atomic_t                   v4l_reading;
-};
-
-/*****************************************************************/
-/* set/get i2c */
-/* 00--1Mb/s, 01-400kb/s, 10--100kb/s, 11--5Mb/s */
-#define I2C_SPEED_1M            0x0
-#define I2C_SPEED_400K          0x1
-#define I2C_SPEED_100K          0x2
-#define I2C_SPEED_5M            0x3
-
-/* 0-- STOP transaction */
-#define I2C_STOP                0x0
-/* 1-- do not transmit STOP at end of transaction */
-#define I2C_NOSTOP              0x1
-/* 1--allow slave to insert clock wait states */
-#define I2C_SYNC                0x1
-
-struct cx231xx_i2c {
-       struct cx231xx *dev;
-
-       int nr;
-
-       /* i2c i/o */
-       struct i2c_adapter i2c_adap;
-       struct i2c_client i2c_client;
-       u32 i2c_rc;
-
-       /* different settings for each bus */
-       u8 i2c_period;
-       u8 i2c_nostop;
-       u8 i2c_reserve;
-};
-
-struct cx231xx_i2c_xfer_data {
-       u8 dev_addr;
-       u8 direction;           /* 1 - IN, 0 - OUT */
-       u8 saddr_len;           /* sub address len */
-       u16 saddr_dat;          /* sub addr data */
-       u8 buf_size;            /* buffer size */
-       u8 *p_buffer;           /* pointer to the buffer */
-};
-
-struct VENDOR_REQUEST_IN {
-       u8 bRequest;
-       u16 wValue;
-       u16 wIndex;
-       u16 wLength;
-       u8 direction;
-       u8 bData;
-       u8 *pBuff;
-};
-
-struct cx231xx_tvnorm {
-       char            *name;
-       v4l2_std_id     id;
-       u32             cxiformat;
-       u32             cxoformat;
-};
-
-struct cx231xx_ctrl {
-       struct v4l2_queryctrl v;
-       u32 off;
-       u32 reg;
-       u32 mask;
-       u32 shift;
-};
-
-enum TRANSFER_TYPE {
-       Raw_Video = 0,
-       Audio,
-       Vbi,                    /* VANC */
-       Sliced_cc,              /* HANC */
-       TS1_serial_mode,
-       TS2,
-       TS1_parallel_mode
-} ;
-
-struct cx231xx_video_mode {
-       /* Isoc control struct */
-       struct cx231xx_dmaqueue vidq;
-       struct cx231xx_isoc_ctl isoc_ctl;
-       struct cx231xx_bulk_ctl bulk_ctl;
-       /* locks */
-       spinlock_t slock;
-
-       /* usb transfer */
-       int alt;                /* alternate */
-       int max_pkt_size;       /* max packet size of isoc transaction */
-       int num_alt;            /* Number of alternative settings */
-       unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
-       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;
-
-       int                        nr;
-       int                        sram_chno;
-
-       struct videobuf_dvb_frontends frontends;
-
-       /* dma queues */
-
-       u32                        ts_packet_size;
-       u32                        ts_packet_count;
-
-       int                        width;
-       int                        height;
-
-       /* locks */
-       spinlock_t                 slock;
-
-       /* registers */
-       u32                        reg_gpcnt;
-       u32                        reg_gpcnt_ctl;
-       u32                        reg_dma_ctl;
-       u32                        reg_lngth;
-       u32                        reg_hw_sop_ctrl;
-       u32                        reg_gen_ctrl;
-       u32                        reg_bd_pkt_status;
-       u32                        reg_sop_status;
-       u32                        reg_fifo_ovfl_stat;
-       u32                        reg_vld_misc;
-       u32                        reg_ts_clk_en;
-       u32                        reg_ts_int_msk;
-       u32                        reg_ts_int_stat;
-       u32                        reg_src_sel;
-
-       /* Default register vals */
-       int                        pci_irqmask;
-       u32                        dma_ctl_val;
-       u32                        ts_int_msk_val;
-       u32                        gen_ctrl_val;
-       u32                        ts_clk_en_val;
-       u32                        src_sel_val;
-       u32                        vld_misc_val;
-       u32                        hw_sop_ctrl_val;
-
-       /* Allow a single tsport to have multiple frontends */
-       u32                        num_frontends;
-       void                       *port_priv;
-};
-
-/* main device struct */
-struct cx231xx {
-       /* generic device properties */
-       char name[30];          /* name (including minor) of the device */
-       int model;              /* index in the device_data struct */
-       int devno;              /* marks the number of this device */
-
-       struct cx231xx_board board;
-
-       /* For I2C IR support */
-       struct IR_i2c_init_data    init_data;
-       struct i2c_client          *ir_i2c_client;
-
-       unsigned int stream_on:1;       /* Locks streams */
-       unsigned int vbi_stream_on:1;   /* Locks streams for VBI */
-       unsigned int has_audio_class:1;
-       unsigned int has_alsa_audio:1;
-
-       struct cx231xx_fmt *format;
-
-       struct v4l2_device v4l2_dev;
-       struct v4l2_subdev *sd_cx25840;
-       struct v4l2_subdev *sd_tuner;
-
-       struct work_struct wq_trigger;          /* Trigger to start/stop audio for alsa module */
-       atomic_t           stream_started;      /* stream should be running if true */
-
-       struct list_head devlist;
-
-       int tuner_type;         /* type of the tuner */
-       int tuner_addr;         /* tuner address */
-
-       /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
-       struct cx231xx_i2c i2c_bus[3];
-       unsigned int xc_fw_load_done:1;
-       /* locks */
-       struct mutex gpio_i2c_lock;
-       struct mutex i2c_lock;
-
-       /* video for linux */
-       int users;              /* user count for exclusive use */
-       struct video_device *vdev;      /* video for linux device struct */
-       v4l2_std_id norm;       /* selected tv norm */
-       int ctl_freq;           /* selected frequency */
-       unsigned int ctl_ainput;        /* selected audio input */
-       int mute;
-       int volume;
-
-       /* frame properties */
-       int width;              /* current frame width */
-       int height;             /* current frame height */
-       int interlaced;         /* 1=interlace fileds, 0=just top fileds */
-
-       struct cx231xx_audio adev;
-
-       /* states */
-       enum cx231xx_dev_state state;
-
-       struct work_struct request_module_wk;
-
-       /* locks */
-       struct mutex lock;
-       struct mutex ctrl_urb_lock;     /* protects urb_buf */
-       struct list_head inqueue, outqueue;
-       wait_queue_head_t open, wait_frame, wait_stream;
-       struct video_device *vbi_dev;
-       struct video_device *radio_dev;
-
-       unsigned char eedata[256];
-
-       struct cx231xx_video_mode video_mode;
-       struct cx231xx_video_mode vbi_mode;
-       struct cx231xx_video_mode sliced_cc_mode;
-       struct cx231xx_video_mode ts1_mode;
-
-       atomic_t devlist_count;
-
-       struct usb_device *udev;        /* the usb device */
-       char urb_buf[URB_MAX_CTRL_SIZE];        /* urb control msg buffer */
-
-       /* helper funcs that call usb_control_msg */
-       int (*cx231xx_read_ctrl_reg) (struct cx231xx *dev, u8 req, u16 reg,
-                                     char *buf, int len);
-       int (*cx231xx_write_ctrl_reg) (struct cx231xx *dev, u8 req, u16 reg,
-                                      char *buf, int len);
-       int (*cx231xx_send_usb_command) (struct cx231xx_i2c *i2c_bus,
-                               struct cx231xx_i2c_xfer_data *req_data);
-       int (*cx231xx_gpio_i2c_read) (struct cx231xx *dev, u8 dev_addr,
-                                     u8 *buf, u8 len);
-       int (*cx231xx_gpio_i2c_write) (struct cx231xx *dev, u8 dev_addr,
-                                      u8 *buf, u8 len);
-
-       int (*cx231xx_set_analog_freq) (struct cx231xx *dev, u32 freq);
-       int (*cx231xx_reset_analog_tuner) (struct cx231xx *dev);
-
-       enum cx231xx_mode mode;
-
-       struct cx231xx_dvb *dvb;
-
-       /* Cx231xx supported PCB config's */
-       struct pcb_config current_pcb_config;
-       u8 current_scenario_idx;
-       u8 interface_count;
-       u8 max_iad_interface_count;
-
-       /* GPIO related register direction and values */
-       u32 gpio_dir;
-       u32 gpio_val;
-
-       /* Power Modes */
-       int power_mode;
-
-       /* afe parameters */
-       enum AFE_MODE afe_mode;
-       u32 afe_ref_count;
-
-       /* video related parameters */
-       u32 video_input;
-       u32 active_mode;
-       u8 vbi_or_sliced_cc_mode;       /* 0 - vbi ; 1 - sliced cc mode */
-       enum cx231xx_std_mode std_mode; /* 0 - Air; 1 - cable */
-
-       /*mode: digital=1 or analog=0*/
-       u8 mode_tv;
-
-       u8 USE_ISO;
-       struct cx231xx_tvnorm      encodernorm;
-       struct cx231xx_tsport      ts1, ts2;
-       struct cx2341x_mpeg_params mpeg_params;
-       struct video_device        *v4l_device;
-       atomic_t                   v4l_reader_count;
-       u32                        freq;
-       unsigned int               input;
-       u32                        cx23417_mailbox;
-       u32                        __iomem *lmmio;
-       u8                         __iomem *bmmio;
-};
-
-extern struct list_head cx231xx_devlist;
-
-#define cx25840_call(cx231xx, o, f, args...) \
-       v4l2_subdev_call(cx231xx->sd_cx25840, o, f, ##args)
-#define tuner_call(cx231xx, o, f, args...) \
-       v4l2_subdev_call(cx231xx->sd_tuner, o, f, ##args)
-#define call_all(dev, o, f, args...) \
-       v4l2_device_call_until_err(&dev->v4l2_dev, 0, o, f, ##args)
-
-struct cx231xx_ops {
-       struct list_head next;
-       char *name;
-       int id;
-       int (*init) (struct cx231xx *);
-       int (*fini) (struct cx231xx *);
-};
-
-/* call back functions in dvb module */
-int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq);
-int cx231xx_reset_analog_tuner(struct cx231xx *dev);
-
-/* Provided by cx231xx-i2c.c */
-void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c);
-int cx231xx_i2c_register(struct cx231xx_i2c *bus);
-int cx231xx_i2c_unregister(struct cx231xx_i2c *bus);
-
-/* Internal block control functions */
-int cx231xx_read_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,
-                u8 saddr_len, u32 *data, u8 data_len, int master);
-int cx231xx_write_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,
-                u8 saddr_len, u32 data, u8 data_len, int master);
-int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr,
-                         u16 saddr, u8 saddr_len, u32 *data, u8 data_len);
-int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr,
-                          u16 saddr, u8 saddr_len, u32 data, u8 data_len);
-int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size,
-                          u16 register_address, u8 bit_start, u8 bit_end,
-                          u32 value);
-int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr,
-                                       u16 saddr, u32 mask, u32 value);
-u32 cx231xx_set_field(u32 field_mask, u32 data);
-
-/*verve r/w*/
-void initGPIO(struct cx231xx *dev);
-void uninitGPIO(struct cx231xx *dev);
-/* afe related functions */
-int cx231xx_afe_init_super_block(struct cx231xx *dev, u32 ref_count);
-int cx231xx_afe_init_channels(struct cx231xx *dev);
-int cx231xx_afe_setup_AFE_for_baseband(struct cx231xx *dev);
-int cx231xx_afe_set_input_mux(struct cx231xx *dev, u32 input_mux);
-int cx231xx_afe_set_mode(struct cx231xx *dev, enum AFE_MODE mode);
-int cx231xx_afe_update_power_control(struct cx231xx *dev,
-                                       enum AV_MODE avmode);
-int cx231xx_afe_adjust_ref_count(struct cx231xx *dev, u32 video_input);
-
-/* i2s block related functions */
-int cx231xx_i2s_blk_initialize(struct cx231xx *dev);
-int cx231xx_i2s_blk_update_power_control(struct cx231xx *dev,
-                                       enum AV_MODE avmode);
-int cx231xx_i2s_blk_set_audio_input(struct cx231xx *dev, u8 audio_input);
-
-/* DIF related functions */
-int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode,
-                                         u32 function_mode, u32 standard);
-void cx231xx_set_Colibri_For_LowIF(struct cx231xx *dev, u32 if_freq,
-                                        u8 spectral_invert, u32 mode);
-u32 cx231xx_Get_Colibri_CarrierOffset(u32 mode, u32 standerd);
-void cx231xx_set_DIF_bandpass(struct cx231xx *dev, u32 if_freq,
-                                        u8 spectral_invert, u32 mode);
-void cx231xx_Setup_AFE_for_LowIF(struct cx231xx *dev);
-void reset_s5h1432_demod(struct cx231xx *dev);
-void cx231xx_dump_HH_reg(struct cx231xx *dev);
-void update_HH_register_after_set_DIF(struct cx231xx *dev);
-void cx231xx_dump_SC_reg(struct cx231xx *dev);
-
-
-
-int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard);
-int cx231xx_tuner_pre_channel_change(struct cx231xx *dev);
-int cx231xx_tuner_post_channel_change(struct cx231xx *dev);
-
-/* video parser functions */
-u8 cx231xx_find_next_SAV_EAV(u8 *p_buffer, u32 buffer_size,
-                            u32 *p_bytes_used);
-u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf,
-                                u32 *p_bytes_used);
-int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
-                   u8 *p_buffer, u32 bytes_to_copy);
-void cx231xx_reset_video_buffer(struct cx231xx *dev,
-                               struct cx231xx_dmaqueue *dma_q);
-u8 cx231xx_is_buffer_done(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q);
-u32 cx231xx_copy_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
-                           u8 *p_line, u32 length, int field_number);
-u32 cx231xx_get_video_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
-                          u8 sav_eav, u8 *p_buffer, u32 buffer_size);
-void cx231xx_swab(u16 *from, u16 *to, u16 len);
-
-/* Provided by cx231xx-core.c */
-
-u32 cx231xx_request_buffers(struct cx231xx *dev, u32 count);
-void cx231xx_queue_unusedframes(struct cx231xx *dev);
-void cx231xx_release_buffers(struct cx231xx *dev);
-
-/* read from control pipe */
-int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg,
-                         char *buf, int len);
-
-/* write to control pipe */
-int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg,
-                          char *buf, int len);
-int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode);
-
-int cx231xx_send_vendor_cmd(struct cx231xx *dev,
-                               struct VENDOR_REQUEST_IN *ven_req);
-int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus,
-                               struct cx231xx_i2c_xfer_data *req_data);
-
-/* Gpio related functions */
-int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val,
-                         u8 len, u8 request, u8 direction);
-int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val);
-int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val);
-int cx231xx_set_gpio_value(struct cx231xx *dev, int pin_number, int pin_value);
-int cx231xx_set_gpio_direction(struct cx231xx *dev, int pin_number,
-                              int pin_value);
-
-int cx231xx_gpio_i2c_start(struct cx231xx *dev);
-int cx231xx_gpio_i2c_end(struct cx231xx *dev);
-int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data);
-int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf);
-int cx231xx_gpio_i2c_read_ack(struct cx231xx *dev);
-int cx231xx_gpio_i2c_write_ack(struct cx231xx *dev);
-int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev);
-
-int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len);
-int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len);
-
-/* audio related functions */
-int cx231xx_set_audio_decoder_input(struct cx231xx *dev,
-                                   enum AUDIO_INPUT audio_input);
-
-int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type);
-int cx231xx_set_video_alternate(struct cx231xx *dev);
-int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt);
-int is_fw_load(struct cx231xx *dev);
-int cx231xx_check_fw(struct cx231xx *dev);
-int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
-                     int num_bufs, int max_pkt_size,
-                     int (*isoc_copy) (struct cx231xx *dev,
-                                       struct urb *urb));
-int cx231xx_init_bulk(struct cx231xx *dev, int max_packets,
-                     int num_bufs, int max_pkt_size,
-                     int (*bulk_copy) (struct cx231xx *dev,
-                                       struct urb *urb));
-void cx231xx_stop_TS1(struct cx231xx *dev);
-void cx231xx_start_TS1(struct cx231xx *dev);
-void cx231xx_uninit_isoc(struct cx231xx *dev);
-void cx231xx_uninit_bulk(struct cx231xx *dev);
-int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode);
-int cx231xx_unmute_audio(struct cx231xx *dev);
-int cx231xx_ep5_bulkout(struct cx231xx *dev, u8 *firmware, u16 size);
-void cx231xx_disable656(struct cx231xx *dev);
-void cx231xx_enable656(struct cx231xx *dev);
-int cx231xx_demod_reset(struct cx231xx *dev);
-int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio);
-
-/* Device list functions */
-void cx231xx_release_resources(struct cx231xx *dev);
-void cx231xx_release_analog_resources(struct cx231xx *dev);
-int cx231xx_register_analog_devices(struct cx231xx *dev);
-void cx231xx_remove_from_devlist(struct cx231xx *dev);
-void cx231xx_add_into_devlist(struct cx231xx *dev);
-void cx231xx_init_extension(struct cx231xx *dev);
-void cx231xx_close_extension(struct cx231xx *dev);
-
-/* hardware init functions */
-int cx231xx_dev_init(struct cx231xx *dev);
-void cx231xx_dev_uninit(struct cx231xx *dev);
-void cx231xx_config_i2c(struct cx231xx *dev);
-int cx231xx_config(struct cx231xx *dev);
-
-/* Stream control functions */
-int cx231xx_start_stream(struct cx231xx *dev, u32 ep_mask);
-int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask);
-
-int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type);
-
-/* Power control functions */
-int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode);
-int cx231xx_power_suspend(struct cx231xx *dev);
-
-/* chip specific control functions */
-int cx231xx_init_ctrl_pin_status(struct cx231xx *dev);
-int cx231xx_set_agc_analog_digital_mux_select(struct cx231xx *dev,
-                                             u8 analog_or_digital);
-int cx231xx_enable_i2c_port_3(struct cx231xx *dev, bool is_port_3);
-
-/* video audio decoder related functions */
-void video_mux(struct cx231xx *dev, int index);
-int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input);
-int cx231xx_set_decoder_video_input(struct cx231xx *dev, u8 pin_type, u8 input);
-int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev);
-int cx231xx_set_audio_input(struct cx231xx *dev, u8 input);
-
-/* Provided by cx231xx-video.c */
-int cx231xx_register_extension(struct cx231xx_ops *dev);
-void cx231xx_unregister_extension(struct cx231xx_ops *dev);
-void cx231xx_init_extension(struct cx231xx *dev);
-void cx231xx_close_extension(struct cx231xx *dev);
-
-/* Provided by cx231xx-cards.c */
-extern void cx231xx_pre_card_setup(struct cx231xx *dev);
-extern void cx231xx_card_setup(struct cx231xx *dev);
-extern struct cx231xx_board cx231xx_boards[];
-extern struct usb_device_id cx231xx_id_table[];
-extern const unsigned int cx231xx_bcount;
-int cx231xx_tuner_callback(void *ptr, int component, int command, int arg);
-
-/* cx23885-417.c                                               */
-extern int cx231xx_417_register(struct cx231xx *dev);
-extern void cx231xx_417_unregister(struct cx231xx *dev);
-
-/* cx23885-input.c                                             */
-
-#if defined(CONFIG_VIDEO_CX231XX_RC)
-int cx231xx_ir_init(struct cx231xx *dev);
-void cx231xx_ir_exit(struct cx231xx *dev);
-#else
-#define cx231xx_ir_init(dev)   (0)
-#define cx231xx_ir_exit(dev)   (0)
-#endif
-
-
-/* printk macros */
-
-#define cx231xx_err(fmt, arg...) do {\
-       printk(KERN_ERR fmt , ##arg); } while (0)
-
-#define cx231xx_errdev(fmt, arg...) do {\
-       printk(KERN_ERR "%s: "fmt,\
-                       dev->name , ##arg); } while (0)
-
-#define cx231xx_info(fmt, arg...) do {\
-       printk(KERN_INFO "%s: "fmt,\
-                       dev->name , ##arg); } while (0)
-#define cx231xx_warn(fmt, arg...) do {\
-       printk(KERN_WARNING "%s: "fmt,\
-                       dev->name , ##arg); } while (0)
-
-static inline unsigned int norm_maxw(struct cx231xx *dev)
-{
-       if (dev->board.max_range_640_480)
-               return 640;
-       else
-               return 720;
-}
-
-static inline unsigned int norm_maxh(struct cx231xx *dev)
-{
-       if (dev->board.max_range_640_480)
-               return 480;
-       else
-               return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
-}
-#endif
diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig
deleted file mode 100644 (file)
index 928ef0d..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-config VIDEO_EM28XX
-       tristate "Empia EM28xx USB video capture support"
-       depends on VIDEO_DEV && I2C
-       select VIDEO_TUNER
-       select VIDEO_TVEEPROM
-       select VIDEOBUF_VMALLOC
-       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO
-
-       ---help---
-         This is a video4linux driver for Empia 28xx based TV cards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called em28xx
-
-config VIDEO_EM28XX_ALSA
-       depends on VIDEO_EM28XX && SND
-       select SND_PCM
-       tristate "Empia EM28xx ALSA audio module"
-       ---help---
-         This is an ALSA driver for some Empia 28xx based TV cards.
-
-         This is not required for em2800/em2820/em2821 boards. However,
-         newer em28xx devices uses Vendor Class for audio, instead of
-         implementing the USB Audio Class. For those chips, this module
-         will enable digital audio.
-
-         To compile this driver as a module, choose M here: the
-         module will be called em28xx-alsa
-
-config VIDEO_EM28XX_DVB
-       tristate "DVB/ATSC Support for em28xx based TV cards"
-       depends on VIDEO_EM28XX && DVB_CORE
-       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10023 if !DVB_FE_CUSTOMISE
-       select DVB_S921 if !DVB_FE_CUSTOMISE
-       select DVB_DRXD if !DVB_FE_CUSTOMISE
-       select DVB_CXD2820R if !DVB_FE_CUSTOMISE
-       select DVB_DRXK if !DVB_FE_CUSTOMISE
-       select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
-       select DVB_TDA10071 if !DVB_FE_CUSTOMISE
-       select DVB_A8293 if !DVB_FE_CUSTOMISE
-       select VIDEOBUF_DVB
-       ---help---
-         This adds support for DVB cards based on the
-         Empiatech em28xx chips.
-
-config VIDEO_EM28XX_RC
-        tristate "EM28XX Remote Controller support"
-        depends on RC_CORE
-        depends on VIDEO_EM28XX
-        depends on !(RC_CORE=m && VIDEO_EM28XX=y)
-        default VIDEO_EM28XX
-        ---help---
-          Enables Remote Controller support on em28xx driver.
diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile
deleted file mode 100644 (file)
index 65c7c29..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-em28xx-y :=    em28xx-video.o em28xx-i2c.o em28xx-cards.o
-em28xx-y +=    em28xx-core.o  em28xx-vbi.o
-
-em28xx-alsa-objs := em28xx-audio.o
-em28xx-rc-objs := em28xx-input.o
-
-obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o
-obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
-obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o
-obj-$(CONFIG_VIDEO_EM28XX_RC) += em28xx-rc.o
-
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/tuners
-ccflags-y += -Idrivers/media/dvb-core
-ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
deleted file mode 100644 (file)
index 2fdb66e..0000000
+++ /dev/null
@@ -1,751 +0,0 @@
-/*
- *  Empiatech em28x1 audio extension
- *
- *  Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com>
- *
- *  Copyright (C) 2007-2011 Mauro Carvalho Chehab <mchehab@redhat.com>
- *     - Port to work with the in-kernel driver
- *     - Cleanups, fixes, alsa-controls, etc.
- *
- *  This driver is based on my previous au600 usb pstn audio driver
- *  and inherits all the copyrights
- *
- *  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/usb.h>
-#include <linux/init.h>
-#include <linux/sound.h>
-#include <linux/spinlock.h>
-#include <linux/soundcard.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/proc_fs.h>
-#include <linux/module.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 <sound/tlv.h>
-#include <sound/ac97_codec.h>
-#include <media/v4l2-common.h>
-#include "em28xx.h"
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "activates debug info");
-
-#define dprintk(fmt, arg...) do {                                      \
-           if (debug)                                                  \
-               printk(KERN_INFO "em28xx-audio %s: " fmt,               \
-                                 __func__, ##arg);             \
-       } while (0)
-
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
-
-static int em28xx_deinit_isoc_audio(struct em28xx *dev)
-{
-       int i;
-
-       dprintk("Stopping isoc\n");
-       for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
-               if (!irqs_disabled())
-                       usb_kill_urb(dev->adev.urb[i]);
-               else
-                       usb_unlink_urb(dev->adev.urb[i]);
-
-               usb_free_urb(dev->adev.urb[i]);
-               dev->adev.urb[i] = NULL;
-
-               kfree(dev->adev.transfer_buffer[i]);
-               dev->adev.transfer_buffer[i] = NULL;
-       }
-
-       return 0;
-}
-
-static void em28xx_audio_isocirq(struct urb *urb)
-{
-       struct em28xx            *dev = urb->context;
-       int                      i;
-       unsigned int             oldptr;
-       int                      period_elapsed = 0;
-       int                      status;
-       unsigned char            *cp;
-       unsigned int             stride;
-       struct snd_pcm_substream *substream;
-       struct snd_pcm_runtime   *runtime;
-
-       switch (urb->status) {
-       case 0:             /* success */
-       case -ETIMEDOUT:    /* NAK */
-               break;
-       case -ECONNRESET:   /* kill */
-       case -ENOENT:
-       case -ESHUTDOWN:
-               return;
-       default:            /* error */
-               dprintk("urb completition error %d.\n", urb->status);
-               break;
-       }
-
-       if (atomic_read(&dev->stream_started) == 0)
-               return;
-
-       if (dev->adev.capture_pcm_substream) {
-               substream = dev->adev.capture_pcm_substream;
-               runtime = substream->runtime;
-               stride = runtime->frame_bits >> 3;
-
-               for (i = 0; i < urb->number_of_packets; i++) {
-                       int length =
-                           urb->iso_frame_desc[i].actual_length / stride;
-                       cp = (unsigned char *)urb->transfer_buffer +
-                           urb->iso_frame_desc[i].offset;
-
-                       if (!length)
-                               continue;
-
-                       oldptr = dev->adev.hwptr_done_capture;
-                       if (oldptr + length >= 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,
-                                      length * stride - cnt * stride);
-                       } else {
-                               memcpy(runtime->dma_area + oldptr * stride, cp,
-                                      length * stride);
-                       }
-
-                       snd_pcm_stream_lock(substream);
-
-                       dev->adev.hwptr_done_capture += length;
-                       if (dev->adev.hwptr_done_capture >=
-                           runtime->buffer_size)
-                               dev->adev.hwptr_done_capture -=
-                                   runtime->buffer_size;
-
-                       dev->adev.capture_transfer_done += length;
-                       if (dev->adev.capture_transfer_done >=
-                           runtime->period_size) {
-                               dev->adev.capture_transfer_done -=
-                                   runtime->period_size;
-                               period_elapsed = 1;
-                       }
-
-                       snd_pcm_stream_unlock(substream);
-               }
-               if (period_elapsed)
-                       snd_pcm_period_elapsed(substream);
-       }
-       urb->status = 0;
-
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status < 0) {
-               em28xx_errdev("resubmit of audio urb failed (error=%i)\n",
-                             status);
-       }
-       return;
-}
-
-static int em28xx_init_audio_isoc(struct em28xx *dev)
-{
-       int       i, errCode;
-       const int sb_size = EM28XX_NUM_AUDIO_PACKETS *
-                           EM28XX_AUDIO_MAX_PACKET_SIZE;
-
-       dprintk("Starting isoc transfers\n");
-
-       for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
-               struct urb *urb;
-               int j, k;
-
-               dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
-               if (!dev->adev.transfer_buffer[i])
-                       return -ENOMEM;
-
-               memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
-               urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
-               if (!urb) {
-                       em28xx_errdev("usb_alloc_urb failed!\n");
-                       for (j = 0; j < i; j++) {
-                               usb_free_urb(dev->adev.urb[j]);
-                               kfree(dev->adev.transfer_buffer[j]);
-                       }
-                       return -ENOMEM;
-               }
-
-               urb->dev = dev->udev;
-               urb->context = dev;
-               urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO);
-               urb->transfer_flags = URB_ISO_ASAP;
-               urb->transfer_buffer = dev->adev.transfer_buffer[i];
-               urb->interval = 1;
-               urb->complete = em28xx_audio_isocirq;
-               urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS;
-               urb->transfer_buffer_length = sb_size;
-
-               for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS;
-                            j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) {
-                       urb->iso_frame_desc[j].offset = k;
-                       urb->iso_frame_desc[j].length =
-                           EM28XX_AUDIO_MAX_PACKET_SIZE;
-               }
-               dev->adev.urb[i] = urb;
-       }
-
-       for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
-               errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
-               if (errCode) {
-                       em28xx_errdev("submit of audio urb failed\n");
-                       em28xx_deinit_isoc_audio(dev);
-                       atomic_set(&dev->stream_started, 0);
-                       return errCode;
-               }
-
-       }
-
-       return 0;
-}
-
-static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
-                                       size_t size)
-{
-       struct snd_pcm_runtime *runtime = subs->runtime;
-
-       dprintk("Allocating vbuffer\n");
-       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;
-
-       runtime->dma_bytes = size;
-
-       return 0;
-}
-
-static struct snd_pcm_hardware snd_em28xx_hw_capture = {
-       .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
-               SNDRV_PCM_INFO_MMAP           |
-               SNDRV_PCM_INFO_INTERLEAVED    |
-               SNDRV_PCM_INFO_BATCH          |
-               SNDRV_PCM_INFO_MMAP_VALID,
-
-       .formats = SNDRV_PCM_FMTBIT_S16_LE,
-
-       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT,
-
-       .rate_min = 48000,
-       .rate_max = 48000,
-       .channels_min = 2,
-       .channels_max = 2,
-       .buffer_bytes_max = 62720 * 8,  /* just about the value in usbaudio.c */
-       .period_bytes_min = 64,         /* 12544/2, */
-       .period_bytes_max = 12544,
-       .periods_min = 2,
-       .periods_max = 98,              /* 12544, */
-};
-
-static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
-{
-       struct em28xx *dev = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       int ret = 0;
-
-       dprintk("opening device and trying to acquire exclusive lock\n");
-
-       if (!dev) {
-               em28xx_err("BUG: em28xx can't find device struct."
-                               " Can't proceed with open\n");
-               return -ENODEV;
-       }
-
-       runtime->hw = snd_em28xx_hw_capture;
-       if ((dev->alt == 0 || dev->audio_ifnum) && dev->adev.users == 0) {
-               if (dev->audio_ifnum)
-                       dev->alt = 1;
-               else
-                       dev->alt = 7;
-
-               dprintk("changing alternate number on interface %d to %d\n",
-                       dev->audio_ifnum, dev->alt);
-               usb_set_interface(dev->udev, dev->audio_ifnum, dev->alt);
-
-               /* Sets volume, mute, etc */
-               dev->mute = 0;
-               mutex_lock(&dev->lock);
-               ret = em28xx_audio_analog_set(dev);
-               if (ret < 0)
-                       goto err;
-
-               dev->adev.users++;
-               mutex_unlock(&dev->lock);
-       }
-
-       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
-       dev->adev.capture_pcm_substream = substream;
-
-       return 0;
-err:
-       mutex_unlock(&dev->lock);
-
-       em28xx_err("Error while configuring em28xx mixer\n");
-       return ret;
-}
-
-static int snd_em28xx_pcm_close(struct snd_pcm_substream *substream)
-{
-       struct em28xx *dev = snd_pcm_substream_chip(substream);
-
-       dprintk("closing device\n");
-
-       dev->mute = 1;
-       mutex_lock(&dev->lock);
-       dev->adev.users--;
-       if (atomic_read(&dev->stream_started) > 0) {
-               atomic_set(&dev->stream_started, 0);
-               schedule_work(&dev->wq_trigger);
-       }
-
-       em28xx_audio_analog_set(dev);
-       if (substream->runtime->dma_area) {
-               dprintk("freeing\n");
-               vfree(substream->runtime->dma_area);
-               substream->runtime->dma_area = NULL;
-       }
-       mutex_unlock(&dev->lock);
-
-       return 0;
-}
-
-static int snd_em28xx_hw_capture_params(struct snd_pcm_substream *substream,
-                                       struct snd_pcm_hw_params *hw_params)
-{
-       int ret;
-
-       dprintk("Setting capture parameters\n");
-
-       ret = snd_pcm_alloc_vmalloc_buffer(substream,
-                               params_buffer_bytes(hw_params));
-       if (ret < 0)
-               return ret;
-#if 0
-       /* TODO: set up em28xx audio chip to deliver the correct audio format,
-          current default is 48000hz multiplexed => 96000hz mono
-          which shouldn't matter since analogue TV only supports mono */
-       unsigned int channels, rate, format;
-
-       format = params_format(hw_params);
-       rate = params_rate(hw_params);
-       channels = params_channels(hw_params);
-#endif
-
-       return 0;
-}
-
-static int snd_em28xx_hw_capture_free(struct snd_pcm_substream *substream)
-{
-       struct em28xx *dev = snd_pcm_substream_chip(substream);
-
-       dprintk("Stop capture, if needed\n");
-
-       if (atomic_read(&dev->stream_started) > 0) {
-               atomic_set(&dev->stream_started, 0);
-               schedule_work(&dev->wq_trigger);
-       }
-
-       return 0;
-}
-
-static int snd_em28xx_prepare(struct snd_pcm_substream *substream)
-{
-       struct em28xx *dev = snd_pcm_substream_chip(substream);
-
-       dev->adev.hwptr_done_capture = 0;
-       dev->adev.capture_transfer_done = 0;
-
-       return 0;
-}
-
-static void audio_trigger(struct work_struct *work)
-{
-       struct em28xx *dev = container_of(work, struct em28xx, wq_trigger);
-
-       if (atomic_read(&dev->stream_started)) {
-               dprintk("starting capture");
-               em28xx_init_audio_isoc(dev);
-       } else {
-               dprintk("stopping capture");
-               em28xx_deinit_isoc_audio(dev);
-       }
-}
-
-static int snd_em28xx_capture_trigger(struct snd_pcm_substream *substream,
-                                     int cmd)
-{
-       struct em28xx *dev = snd_pcm_substream_chip(substream);
-       int retval = 0;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
-       case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
-       case SNDRV_PCM_TRIGGER_START:
-               atomic_set(&dev->stream_started, 1);
-               break;
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
-       case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
-       case SNDRV_PCM_TRIGGER_STOP:
-               atomic_set(&dev->stream_started, 0);
-               break;
-       default:
-               retval = -EINVAL;
-       }
-       schedule_work(&dev->wq_trigger);
-       return retval;
-}
-
-static snd_pcm_uframes_t snd_em28xx_capture_pointer(struct snd_pcm_substream
-                                                   *substream)
-{
-       unsigned long flags;
-       struct em28xx *dev;
-       snd_pcm_uframes_t hwptr_done;
-
-       dev = snd_pcm_substream_chip(substream);
-       spin_lock_irqsave(&dev->adev.slock, flags);
-       hwptr_done = dev->adev.hwptr_done_capture;
-       spin_unlock_irqrestore(&dev->adev.slock, flags);
-
-       return hwptr_done;
-}
-
-static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
-                                            unsigned long offset)
-{
-       void *pageptr = subs->runtime->dma_area + offset;
-
-       return vmalloc_to_page(pageptr);
-}
-
-/*
- * AC97 volume control support
- */
-static int em28xx_vol_info(struct snd_kcontrol *kcontrol,
-                               struct snd_ctl_elem_info *info)
-{
-       info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-       info->count = 2;
-       info->value.integer.min = 0;
-       info->value.integer.max = 0x1f;
-
-       return 0;
-}
-
-static int em28xx_vol_put(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *value)
-{
-       struct em28xx *dev = snd_kcontrol_chip(kcontrol);
-       u16 val = (0x1f - (value->value.integer.value[0] & 0x1f)) |
-                 (0x1f - (value->value.integer.value[1] & 0x1f)) << 8;
-       int rc;
-
-       mutex_lock(&dev->lock);
-       rc = em28xx_read_ac97(dev, kcontrol->private_value);
-       if (rc < 0)
-               goto err;
-
-       val |= rc & 0x8000;     /* Preserve the mute flag */
-
-       rc = em28xx_write_ac97(dev, kcontrol->private_value, val);
-       if (rc < 0)
-               goto err;
-
-       dprintk("%sleft vol %d, right vol %d (0x%04x) to ac97 volume control 0x%04x\n",
-               (val & 0x8000) ? "muted " : "",
-               0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
-               val, (int)kcontrol->private_value);
-
-err:
-       mutex_unlock(&dev->lock);
-       return rc;
-}
-
-static int em28xx_vol_get(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *value)
-{
-       struct em28xx *dev = snd_kcontrol_chip(kcontrol);
-       int val;
-
-       mutex_lock(&dev->lock);
-       val = em28xx_read_ac97(dev, kcontrol->private_value);
-       mutex_unlock(&dev->lock);
-       if (val < 0)
-               return val;
-
-       dprintk("%sleft vol %d, right vol %d (0x%04x) from ac97 volume control 0x%04x\n",
-               (val & 0x8000) ? "muted " : "",
-               0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
-               val, (int)kcontrol->private_value);
-
-       value->value.integer.value[0] = 0x1f - (val & 0x1f);
-       value->value.integer.value[1] = 0x1f - ((val << 8) & 0x1f);
-
-       return 0;
-}
-
-static int em28xx_vol_put_mute(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *value)
-{
-       struct em28xx *dev = snd_kcontrol_chip(kcontrol);
-       u16 val = value->value.integer.value[0];
-       int rc;
-
-       mutex_lock(&dev->lock);
-       rc = em28xx_read_ac97(dev, kcontrol->private_value);
-       if (rc < 0)
-               goto err;
-
-       if (val)
-               rc &= 0x1f1f;
-       else
-               rc |= 0x8000;
-
-       rc = em28xx_write_ac97(dev, kcontrol->private_value, rc);
-       if (rc < 0)
-               goto err;
-
-       dprintk("%sleft vol %d, right vol %d (0x%04x) to ac97 volume control 0x%04x\n",
-               (val & 0x8000) ? "muted " : "",
-               0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
-               val, (int)kcontrol->private_value);
-
-err:
-       mutex_unlock(&dev->lock);
-       return rc;
-}
-
-static int em28xx_vol_get_mute(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *value)
-{
-       struct em28xx *dev = snd_kcontrol_chip(kcontrol);
-       int val;
-
-       mutex_lock(&dev->lock);
-       val = em28xx_read_ac97(dev, kcontrol->private_value);
-       mutex_unlock(&dev->lock);
-       if (val < 0)
-               return val;
-
-       if (val & 0x8000)
-               value->value.integer.value[0] = 0;
-       else
-               value->value.integer.value[0] = 1;
-
-       dprintk("%sleft vol %d, right vol %d (0x%04x) from ac97 volume control 0x%04x\n",
-               (val & 0x8000) ? "muted " : "",
-               0x1f - ((val >> 8) & 0x1f), 0x1f - (val & 0x1f),
-               val, (int)kcontrol->private_value);
-
-       return 0;
-}
-
-static const DECLARE_TLV_DB_SCALE(em28xx_db_scale, -3450, 150, 0);
-
-static int em28xx_cvol_new(struct snd_card *card, struct em28xx *dev,
-                          char *name, int id)
-{
-       int err;
-       char ctl_name[44];
-       struct snd_kcontrol *kctl;
-       struct snd_kcontrol_new tmp;
-
-       memset (&tmp, 0, sizeof(tmp));
-       tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       tmp.private_value = id,
-       tmp.name  = ctl_name,
-
-       /* Add Mute Control */
-       sprintf(ctl_name, "%s Switch", name);
-       tmp.get  = em28xx_vol_get_mute;
-       tmp.put  = em28xx_vol_put_mute;
-       tmp.info = snd_ctl_boolean_mono_info;
-       kctl = snd_ctl_new1(&tmp, dev);
-       err = snd_ctl_add(card, kctl);
-       if (err < 0)
-               return err;
-       dprintk("Added control %s for ac97 volume control 0x%04x\n",
-               ctl_name, id);
-
-       memset (&tmp, 0, sizeof(tmp));
-       tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       tmp.private_value = id,
-       tmp.name  = ctl_name,
-
-       /* Add Volume Control */
-       sprintf(ctl_name, "%s Volume", name);
-       tmp.get   = em28xx_vol_get;
-       tmp.put   = em28xx_vol_put;
-       tmp.info  = em28xx_vol_info;
-       tmp.tlv.p = em28xx_db_scale,
-       kctl = snd_ctl_new1(&tmp, dev);
-       err = snd_ctl_add(card, kctl);
-       if (err < 0)
-               return err;
-       dprintk("Added control %s for ac97 volume control 0x%04x\n",
-               ctl_name, id);
-
-       return 0;
-}
-
-/*
- * register/unregister code and data
- */
-static struct snd_pcm_ops snd_em28xx_pcm_capture = {
-       .open      = snd_em28xx_capture_open,
-       .close     = snd_em28xx_pcm_close,
-       .ioctl     = snd_pcm_lib_ioctl,
-       .hw_params = snd_em28xx_hw_capture_params,
-       .hw_free   = snd_em28xx_hw_capture_free,
-       .prepare   = snd_em28xx_prepare,
-       .trigger   = snd_em28xx_capture_trigger,
-       .pointer   = snd_em28xx_capture_pointer,
-       .page      = snd_pcm_get_vmalloc_page,
-};
-
-static int em28xx_audio_init(struct em28xx *dev)
-{
-       struct em28xx_audio *adev = &dev->adev;
-       struct snd_pcm      *pcm;
-       struct snd_card     *card;
-       static int          devnr;
-       int                 err;
-
-       if (!dev->has_alsa_audio || dev->audio_ifnum < 0) {
-               /* This device does not support the extension (in this case
-                  the device is expecting the snd-usb-audio module or
-                  doesn't have analog audio support at all) */
-               return 0;
-       }
-
-       printk(KERN_INFO "em28xx-audio.c: probing for em28xx Audio Vendor Class\n");
-       printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
-                        "Rechberger\n");
-       printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2007-2011 Mauro Carvalho Chehab\n");
-
-       err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0,
-                             &card);
-       if (err < 0)
-               return err;
-
-       spin_lock_init(&adev->slock);
-       err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm);
-       if (err < 0) {
-               snd_card_free(card);
-               return err;
-       }
-
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_em28xx_pcm_capture);
-       pcm->info_flags = 0;
-       pcm->private_data = dev;
-       strcpy(pcm->name, "Empia 28xx Capture");
-
-       snd_card_set_dev(card, &dev->udev->dev);
-       strcpy(card->driver, "Em28xx-Audio");
-       strcpy(card->shortname, "Em28xx Audio");
-       strcpy(card->longname, "Empia Em28xx Audio");
-
-       INIT_WORK(&dev->wq_trigger, audio_trigger);
-
-       if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
-               em28xx_cvol_new(card, dev, "Video", AC97_VIDEO);
-               em28xx_cvol_new(card, dev, "Line In", AC97_LINE);
-               em28xx_cvol_new(card, dev, "Phone", AC97_PHONE);
-               em28xx_cvol_new(card, dev, "Microphone", AC97_MIC);
-               em28xx_cvol_new(card, dev, "CD", AC97_CD);
-               em28xx_cvol_new(card, dev, "AUX", AC97_AUX);
-               em28xx_cvol_new(card, dev, "PCM", AC97_PCM);
-
-               em28xx_cvol_new(card, dev, "Master", AC97_MASTER);
-               em28xx_cvol_new(card, dev, "Line", AC97_HEADPHONE);
-               em28xx_cvol_new(card, dev, "Mono", AC97_MASTER_MONO);
-               em28xx_cvol_new(card, dev, "LFE", AC97_CENTER_LFE_MASTER);
-               em28xx_cvol_new(card, dev, "Surround", AC97_SURROUND_MASTER);
-       }
-
-       err = snd_card_register(card);
-       if (err < 0) {
-               snd_card_free(card);
-               return err;
-       }
-       adev->sndcard = card;
-       adev->udev = dev->udev;
-
-       return 0;
-}
-
-static int em28xx_audio_fini(struct em28xx *dev)
-{
-       if (dev == NULL)
-               return 0;
-
-       if (dev->has_alsa_audio != 1) {
-               /* This device does not support the extension (in this case
-                  the device is expecting the snd-usb-audio module or
-                  doesn't have analog audio support at all) */
-               return 0;
-       }
-
-       if (dev->adev.sndcard) {
-               snd_card_free(dev->adev.sndcard);
-               dev->adev.sndcard = NULL;
-       }
-
-       return 0;
-}
-
-static struct em28xx_ops audio_ops = {
-       .id   = EM28XX_AUDIO,
-       .name = "Em28xx Audio Extension",
-       .init = em28xx_audio_init,
-       .fini = em28xx_audio_fini,
-};
-
-static int __init em28xx_alsa_register(void)
-{
-       return em28xx_register_extension(&audio_ops);
-}
-
-static void __exit em28xx_alsa_unregister(void)
-{
-       em28xx_unregister_extension(&audio_ops);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Markus Rechberger <mrechberger@gmail.com>");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_DESCRIPTION("Em28xx Audio driver");
-
-module_init(em28xx_alsa_register);
-module_exit(em28xx_alsa_unregister);
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
deleted file mode 100644 (file)
index ca62b99..0000000
+++ /dev/null
@@ -1,3417 +0,0 @@
-/*
-   em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB
-                   video capture devices
-
-   Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
-                     Markus Rechberger <mrechberger@gmail.com>
-                     Mauro Carvalho Chehab <mchehab@infradead.org>
-                     Sascha Sommer <saschasommer@freenet.de>
-
-   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/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/usb.h>
-#include <media/tuner.h>
-#include <media/msp3400.h>
-#include <media/saa7115.h>
-#include <media/tvp5150.h>
-#include <media/tvaudio.h>
-#include <media/mt9v011.h>
-#include <media/i2c-addr.h>
-#include <media/tveeprom.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-chip-ident.h>
-
-#include "em28xx.h"
-
-#define DRIVER_NAME         "em28xx"
-
-static int tuner = -1;
-module_param(tuner, int, 0444);
-MODULE_PARM_DESC(tuner, "tuner type");
-
-static unsigned int disable_ir;
-module_param(disable_ir, int, 0444);
-MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
-
-static unsigned int disable_usb_speed_check;
-module_param(disable_usb_speed_check, int, 0444);
-MODULE_PARM_DESC(disable_usb_speed_check,
-                "override min bandwidth requirement of 480M bps");
-
-static unsigned int card[]     = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
-module_param_array(card,  int, NULL, 0444);
-MODULE_PARM_DESC(card,     "card type");
-
-/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS - 1 */
-static unsigned long em28xx_devused;
-
-struct em28xx_hash_table {
-       unsigned long hash;
-       unsigned int  model;
-       unsigned int  tuner;
-};
-
-static void em28xx_pre_card_setup(struct em28xx *dev);
-
-/*
- *  Reset sequences for analog/digital modes
- */
-
-/* Reset for the most [analog] boards */
-static struct em28xx_reg_seq default_analog[] = {
-       {EM28XX_R08_GPIO,       0x6d,   ~EM_GPIO_4,     10},
-       {       -1,             -1,     -1,             -1},
-};
-
-/* Reset for the most [digital] boards */
-static struct em28xx_reg_seq default_digital[] = {
-       {EM28XX_R08_GPIO,       0x6e,   ~EM_GPIO_4,     10},
-       {       -1,             -1,     -1,             -1},
-};
-
-/* Board Hauppauge WinTV HVR 900 analog */
-static struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] = {
-       {EM28XX_R08_GPIO,       0x2d,   ~EM_GPIO_4,     10},
-       {0x05,                  0xff,   0x10,           10},
-       {  -1,                  -1,     -1,             -1},
-};
-
-/* Board Hauppauge WinTV HVR 900 digital */
-static struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] = {
-       {EM28XX_R08_GPIO,       0x2e,   ~EM_GPIO_4,     10},
-       {EM2880_R04_GPO,        0x04,   0x0f,           10},
-       {EM2880_R04_GPO,        0x0c,   0x0f,           10},
-       { -1,                   -1,     -1,             -1},
-};
-
-/* Board Hauppauge WinTV HVR 900 (R2) digital */
-static struct em28xx_reg_seq hauppauge_wintv_hvr_900R2_digital[] = {
-       {EM28XX_R08_GPIO,       0x2e,   ~EM_GPIO_4,     10},
-       {EM2880_R04_GPO,        0x0c,   0x0f,           10},
-       { -1,                   -1,     -1,             -1},
-};
-
-/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */
-static struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] = {
-       {EM28XX_R08_GPIO,       0x69,   ~EM_GPIO_4,      10},
-       {       -1,             -1,     -1,              -1},
-};
-
-/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */
-
-/* Board  - EM2870 Kworld 355u
-   Analog - No input analog */
-
-/* Board - EM2882 Kworld 315U digital */
-static struct em28xx_reg_seq em2882_kworld_315u_digital[] = {
-       {EM28XX_R08_GPIO,       0xff,   0xff,           10},
-       {EM28XX_R08_GPIO,       0xfe,   0xff,           10},
-       {EM2880_R04_GPO,        0x04,   0xff,           10},
-       {EM2880_R04_GPO,        0x0c,   0xff,           10},
-       {EM28XX_R08_GPIO,       0x7e,   0xff,           10},
-       {  -1,                  -1,     -1,             -1},
-};
-
-static struct em28xx_reg_seq em2882_kworld_315u_tuner_gpio[] = {
-       {EM2880_R04_GPO,        0x08,   0xff,           10},
-       {EM2880_R04_GPO,        0x0c,   0xff,           10},
-       {EM2880_R04_GPO,        0x08,   0xff,           10},
-       {EM2880_R04_GPO,        0x0c,   0xff,           10},
-       {  -1,                  -1,     -1,             -1},
-};
-
-static struct em28xx_reg_seq kworld_330u_analog[] = {
-       {EM28XX_R08_GPIO,       0x6d,   ~EM_GPIO_4,     10},
-       {EM2880_R04_GPO,        0x00,   0xff,           10},
-       { -1,                   -1,     -1,             -1},
-};
-
-static struct em28xx_reg_seq kworld_330u_digital[] = {
-       {EM28XX_R08_GPIO,       0x6e,   ~EM_GPIO_4,     10},
-       {EM2880_R04_GPO,        0x08,   0xff,           10},
-       { -1,                   -1,     -1,             -1},
-};
-
-/* Evga inDtube
-   GPIO0 - Enable digital power (s5h1409) - low to enable
-   GPIO1 - Enable analog power (tvp5150/emp202) - low to enable
-   GPIO4 - xc3028 reset
-   GOP3  - s5h1409 reset
- */
-static struct em28xx_reg_seq evga_indtube_analog[] = {
-       {EM28XX_R08_GPIO,       0x79,   0xff,           60},
-       {       -1,             -1,     -1,             -1},
-};
-
-static struct em28xx_reg_seq evga_indtube_digital[] = {
-       {EM28XX_R08_GPIO,       0x7a,   0xff,            1},
-       {EM2880_R04_GPO,        0x04,   0xff,           10},
-       {EM2880_R04_GPO,        0x0c,   0xff,            1},
-       { -1,                   -1,     -1,             -1},
-};
-
-/*
- * KWorld PlusTV 340U and UB435-Q (ATSC) GPIOs map:
- * EM_GPIO_0 - currently unknown
- * EM_GPIO_1 - LED disable/enable (1 = off, 0 = on)
- * EM_GPIO_2 - currently unknown
- * EM_GPIO_3 - currently unknown
- * EM_GPIO_4 - TDA18271HD/C1 tuner (1 = active, 0 = in reset)
- * EM_GPIO_5 - LGDT3304 ATSC/QAM demod (1 = active, 0 = in reset)
- * EM_GPIO_6 - currently unknown
- * EM_GPIO_7 - currently unknown
- */
-static struct em28xx_reg_seq kworld_a340_digital[] = {
-       {EM28XX_R08_GPIO,       0x6d,           ~EM_GPIO_4,     10},
-       { -1,                   -1,             -1,             -1},
-};
-
-/* Pinnacle Hybrid Pro eb1a:2881 */
-static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = {
-       {EM28XX_R08_GPIO,       0xfd,   ~EM_GPIO_4,     10},
-       {       -1,             -1,     -1,             -1},
-};
-
-static struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] = {
-       {EM28XX_R08_GPIO,       0x6e,   ~EM_GPIO_4,     10},
-       {EM2880_R04_GPO,        0x04,   0xff,          100},/* zl10353 reset */
-       {EM2880_R04_GPO,        0x0c,   0xff,            1},
-       {       -1,             -1,     -1,             -1},
-};
-
-static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_analog[] = {
-       {EM28XX_R08_GPIO,       0x6d,   ~EM_GPIO_4,     10},
-       {EM2880_R04_GPO,        0x00,   0xff,           10},
-       { -1,                   -1,     -1,             -1},
-};
-
-static struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_digital[] = {
-       {EM28XX_R08_GPIO,       0x6e,   ~EM_GPIO_4,     10},
-       {EM2880_R04_GPO,        0x08,   0xff,           10},
-       { -1,                   -1,     -1,             -1},
-};
-
-/* eb1a:2868 Reddo DVB-C USB TV Box
-   GPIO4 - CU1216L NIM
-   Other GPIOs seems to be don't care. */
-static struct em28xx_reg_seq reddo_dvb_c_usb_box[] = {
-       {EM28XX_R08_GPIO,       0xfe,   0xff,           10},
-       {EM28XX_R08_GPIO,       0xde,   0xff,           10},
-       {EM28XX_R08_GPIO,       0xfe,   0xff,           10},
-       {EM28XX_R08_GPIO,       0xff,   0xff,           10},
-       {EM28XX_R08_GPIO,       0x7f,   0xff,           10},
-       {EM28XX_R08_GPIO,       0x6f,   0xff,           10},
-       {EM28XX_R08_GPIO,       0xff,   0xff,           10},
-       {-1,                    -1,     -1,             -1},
-};
-
-/* Callback for the most boards */
-static struct em28xx_reg_seq default_tuner_gpio[] = {
-       {EM28XX_R08_GPIO,       EM_GPIO_4,      EM_GPIO_4,      10},
-       {EM28XX_R08_GPIO,       0,              EM_GPIO_4,      10},
-       {EM28XX_R08_GPIO,       EM_GPIO_4,      EM_GPIO_4,      10},
-       {  -1,                  -1,             -1,             -1},
-};
-
-/* Mute/unmute */
-static struct em28xx_reg_seq compro_unmute_tv_gpio[] = {
-       {EM28XX_R08_GPIO,       5,              7,              10},
-       {  -1,                  -1,             -1,             -1},
-};
-
-static struct em28xx_reg_seq compro_unmute_svid_gpio[] = {
-       {EM28XX_R08_GPIO,       4,              7,              10},
-       {  -1,                  -1,             -1,             -1},
-};
-
-static struct em28xx_reg_seq compro_mute_gpio[] = {
-       {EM28XX_R08_GPIO,       6,              7,              10},
-       {  -1,                  -1,             -1,             -1},
-};
-
-/* Terratec AV350 */
-static struct em28xx_reg_seq terratec_av350_mute_gpio[] = {
-       {EM28XX_R08_GPIO,       0xff,   0x7f,           10},
-       {       -1,             -1,     -1,             -1},
-};
-
-static struct em28xx_reg_seq terratec_av350_unmute_gpio[] = {
-       {EM28XX_R08_GPIO,       0xff,   0xff,           10},
-       {       -1,             -1,     -1,             -1},
-};
-
-static struct em28xx_reg_seq silvercrest_reg_seq[] = {
-       {EM28XX_R08_GPIO,       0xff,   0xff,           10},
-       {EM28XX_R08_GPIO,       0x01,   0xf7,           10},
-       {       -1,             -1,     -1,             -1},
-};
-
-static struct em28xx_reg_seq vc211a_enable[] = {
-       {EM28XX_R08_GPIO,       0xff,   0x07,           10},
-       {EM28XX_R08_GPIO,       0xff,   0x0f,           10},
-       {EM28XX_R08_GPIO,       0xff,   0x0b,           10},
-       {       -1,             -1,     -1,             -1},
-};
-
-static struct em28xx_reg_seq dikom_dk300_digital[] = {
-       {EM28XX_R08_GPIO,       0x6e,   ~EM_GPIO_4,     10},
-       {EM2880_R04_GPO,        0x08,   0xff,           10},
-       { -1,                   -1,     -1,             -1},
-};
-
-
-/* Reset for the most [digital] boards */
-static struct em28xx_reg_seq leadership_digital[] = {
-       {EM2874_R80_GPIO,       0x70,   0xff,   10},
-       {       -1,             -1,     -1,     -1},
-};
-
-static struct em28xx_reg_seq leadership_reset[] = {
-       {EM2874_R80_GPIO,       0xf0,   0xff,   10},
-       {EM2874_R80_GPIO,       0xb0,   0xff,   10},
-       {EM2874_R80_GPIO,       0xf0,   0xff,   10},
-       {       -1,             -1,     -1,     -1},
-};
-
-/* 2013:024f PCTV nanoStick T2 290e
- * GPIO_6 - demod reset
- * GPIO_7 - LED
- */
-static struct em28xx_reg_seq pctv_290e[] = {
-       {EM2874_R80_GPIO,       0x00,   0xff,           80},
-       {EM2874_R80_GPIO,       0x40,   0xff,           80}, /* GPIO_6 = 1 */
-       {EM2874_R80_GPIO,       0xc0,   0xff,           80}, /* GPIO_7 = 1 */
-       {-1,                    -1,     -1,             -1},
-};
-
-#if 0
-static struct em28xx_reg_seq terratec_h5_gpio[] = {
-       {EM28XX_R08_GPIO,       0xff,   0xff,   10},
-       {EM2874_R80_GPIO,       0xf6,   0xff,   100},
-       {EM2874_R80_GPIO,       0xf2,   0xff,   50},
-       {EM2874_R80_GPIO,       0xf6,   0xff,   50},
-       { -1,                   -1,     -1,     -1},
-};
-
-static struct em28xx_reg_seq terratec_h5_digital[] = {
-       {EM2874_R80_GPIO,       0xf6,   0xff,   10},
-       {EM2874_R80_GPIO,       0xe6,   0xff,   100},
-       {EM2874_R80_GPIO,       0xa6,   0xff,   10},
-       { -1,                   -1,     -1,     -1},
-};
-#endif
-
-/* 2013:024f PCTV DVB-S2 Stick 460e
- * GPIO_0 - POWER_ON
- * GPIO_1 - BOOST
- * GPIO_2 - VUV_LNB (red LED)
- * GPIO_3 - EXT_12V
- * GPIO_4 - INT_DEM (DEMOD GPIO_0)
- * GPIO_5 - INT_LNB
- * GPIO_6 - RESET_DEM
- * GPIO_7 - LED (green LED)
- */
-static struct em28xx_reg_seq pctv_460e[] = {
-       {EM2874_R80_GPIO, 0x01, 0xff,  50},
-       {0x0d,            0xff, 0xff,  50},
-       {EM2874_R80_GPIO, 0x41, 0xff,  50}, /* GPIO_6=1 */
-       {0x0d,            0x42, 0xff,  50},
-       {EM2874_R80_GPIO, 0x61, 0xff,  50}, /* GPIO_5=1 */
-       {             -1,   -1,   -1,  -1},
-};
-
-#if 0
-static struct em28xx_reg_seq hauppauge_930c_gpio[] = {
-       {EM2874_R80_GPIO,       0x6f,   0xff,   10},
-       {EM2874_R80_GPIO,       0x4f,   0xff,   10}, /* xc5000 reset */
-       {EM2874_R80_GPIO,       0x6f,   0xff,   10},
-       {EM2874_R80_GPIO,       0x4f,   0xff,   10},
-       { -1,                   -1,     -1,     -1},
-};
-
-static struct em28xx_reg_seq hauppauge_930c_digital[] = {
-       {EM2874_R80_GPIO,       0xf6,   0xff,   10},
-       {EM2874_R80_GPIO,       0xe6,   0xff,   100},
-       {EM2874_R80_GPIO,       0xa6,   0xff,   10},
-       { -1,                   -1,     -1,     -1},
-};
-#endif
-
-/* 1b80:e425 MaxMedia UB425-TC
- * GPIO_6 - demod reset, 0=active
- * GPIO_7 - LED, 0=active
- */
-static struct em28xx_reg_seq maxmedia_ub425_tc[] = {
-       {EM2874_R80_GPIO,  0x83,  0xff,  100},
-       {EM2874_R80_GPIO,  0xc3,  0xff,  100}, /* GPIO_6 = 1 */
-       {EM2874_R80_GPIO,  0x43,  0xff,  000}, /* GPIO_7 = 0 */
-       {-1,                 -1,    -1,   -1},
-};
-
-/* 2304:0242 PCTV QuatroStick (510e)
- * GPIO_2: decoder reset, 0=active
- * GPIO_4: decoder suspend, 0=active
- * GPIO_6: demod reset, 0=active
- * GPIO_7: LED, 1=active
- */
-static struct em28xx_reg_seq pctv_510e[] = {
-       {EM2874_R80_GPIO, 0x10, 0xff, 100},
-       {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */
-       {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */
-       {             -1,   -1,   -1,  -1},
-};
-
-/* 2013:0251 PCTV QuatroStick nano (520e)
- * GPIO_2: decoder reset, 0=active
- * GPIO_4: decoder suspend, 0=active
- * GPIO_6: demod reset, 0=active
- * GPIO_7: LED, 1=active
- */
-static struct em28xx_reg_seq pctv_520e[] = {
-       {EM2874_R80_GPIO, 0x10, 0xff, 100},
-       {EM2874_R80_GPIO, 0x14, 0xff, 100}, /* GPIO_2 = 1 */
-       {EM2874_R80_GPIO, 0x54, 0xff, 050}, /* GPIO_6 = 1 */
-       {EM2874_R80_GPIO, 0xd4, 0xff, 000}, /* GPIO_7 = 1 */
-       {             -1,   -1,   -1,  -1},
-};
-
-/*
- *  Board definitions
- */
-struct em28xx_board em28xx_boards[] = {
-       [EM2750_BOARD_UNKNOWN] = {
-               .name          = "EM2710/EM2750/EM2751 webcam grabber",
-               .xclk          = EM28XX_XCLK_FREQUENCY_20MHZ,
-               .tuner_type    = TUNER_ABSENT,
-               .is_webcam     = 1,
-               .input         = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = silvercrest_reg_seq,
-               } },
-       },
-       [EM2800_BOARD_UNKNOWN] = {
-               .name         = "Unknown EM2800 video grabber",
-               .is_em2800    = 1,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA711X,
-               .tuner_type   = TUNER_ABSENT,
-               .input        = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2820_BOARD_UNKNOWN] = {
-               .name          = "Unknown EM2750/28xx video grabber",
-               .tuner_type    = TUNER_ABSENT,
-               .is_webcam     = 1,     /* To enable sensor probe */
-       },
-       [EM2750_BOARD_DLCW_130] = {
-               /* Beijing Huaqi Information Digital Technology Co., Ltd */
-               .name          = "Huaqi DLCW-130",
-               .valid         = EM28XX_BOARD_NOT_VALIDATED,
-               .xclk          = EM28XX_XCLK_FREQUENCY_48MHZ,
-               .tuner_type    = TUNER_ABSENT,
-               .is_webcam     = 1,
-               .input         = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               } },
-       },
-       [EM2820_BOARD_KWORLD_PVRTV2800RF] = {
-               .name         = "Kworld PVR TV 2800 RF",
-               .tuner_type   = TUNER_TEMIC_PAL,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2820_BOARD_GADMEI_TVR200] = {
-               .name         = "Gadmei TVR200",
-               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2820_BOARD_TERRATEC_CINERGY_250] = {
-               .name         = "Terratec Cinergy 250 USB",
-               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
-               .has_ir_i2c   = 1,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2820_BOARD_PINNACLE_USB_2] = {
-               .name         = "Pinnacle PCTV USB 2",
-               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
-               .has_ir_i2c   = 1,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2820_BOARD_HAUPPAUGE_WINTV_USB_2] = {
-               .name         = "Hauppauge WinTV USB 2",
-               .tuner_type   = TUNER_PHILIPS_FM1236_MK3,
-               .tda9887_conf = TDA9887_PRESENT |
-                               TDA9887_PORT1_ACTIVE |
-                               TDA9887_PORT2_ACTIVE,
-               .decoder      = EM28XX_TVP5150,
-               .has_msp34xx  = 1,
-               .has_ir_i2c   = 1,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = MSP_INPUT_DEFAULT,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
-                                       MSP_DSP_IN_SCART, MSP_DSP_IN_SCART),
-               } },
-       },
-       [EM2820_BOARD_DLINK_USB_TV] = {
-               .name         = "D-Link DUB-T210 TV Tuner",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2820_BOARD_HERCULES_SMART_TV_USB2] = {
-               .name         = "Hercules Smart TV USB 2.0",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2820_BOARD_PINNACLE_USB_2_FM1216ME] = {
-               .name         = "Pinnacle PCTV USB 2 (Philips FM1216ME)",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_PHILIPS_FM1216ME_MK3,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2820_BOARD_GADMEI_UTV310] = {
-               .name         = "Gadmei UTV310",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_TNF_5335MF,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE] = {
-               .name         = "Leadtek Winfast USB II Deluxe",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_PHILIPS_FM1216ME_MK3,
-               .has_ir_i2c   = 1,
-               .tvaudio_addr = 0x58,
-               .tda9887_conf = TDA9887_PRESENT |
-                               TDA9887_PORT2_ACTIVE |
-                               TDA9887_QSS,
-               .decoder      = EM28XX_SAA711X,
-               .adecoder     = EM28XX_TVAUDIO,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE4,
-                       .amux     = EM28XX_AMUX_AUX,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE5,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-                       .radio    = {
-                       .type     = EM28XX_RADIO,
-                       .amux     = EM28XX_AMUX_AUX,
-                       }
-       },
-       [EM2820_BOARD_VIDEOLOGY_20K14XUSB] = {
-               .name         = "Videology 20K14XUSB USB2.0",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_ABSENT,
-               .is_webcam    = 1,
-               .input        = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               } },
-       },
-       [EM2820_BOARD_SILVERCREST_WEBCAM] = {
-               .name         = "Silvercrest Webcam 1.3mpix",
-               .tuner_type   = TUNER_ABSENT,
-               .is_webcam    = 1,
-               .input        = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = silvercrest_reg_seq,
-               } },
-       },
-       [EM2821_BOARD_SUPERCOMP_USB_2] = {
-               .name         = "Supercomp USB 2.0 TV",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_PHILIPS_FM1236_MK3,
-               .tda9887_conf = TDA9887_PRESENT |
-                               TDA9887_PORT1_ACTIVE |
-                               TDA9887_PORT2_ACTIVE,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2821_BOARD_USBGEAR_VD204] = {
-               .name         = "Usbgear VD204v9",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_ABSENT,   /* Capture only device */
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type  = EM28XX_VMUX_COMPOSITE1,
-                       .vmux  = SAA7115_COMPOSITE0,
-                       .amux  = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type  = EM28XX_VMUX_SVIDEO,
-                       .vmux  = SAA7115_SVIDEO3,
-                       .amux  = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2860_BOARD_NETGMBH_CAM] = {
-               /* Beijing Huaqi Information Digital Technology Co., Ltd */
-               .name         = "NetGMBH Cam",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_ABSENT,
-               .is_webcam    = 1,
-               .input        = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = 0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               } },
-       },
-       [EM2860_BOARD_TYPHOON_DVD_MAKER] = {
-               .name         = "Typhoon DVD Maker",
-               .decoder      = EM28XX_SAA711X,
-               .tuner_type   = TUNER_ABSENT,   /* Capture only device */
-               .input        = { {
-                       .type  = EM28XX_VMUX_COMPOSITE1,
-                       .vmux  = SAA7115_COMPOSITE0,
-                       .amux  = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type  = EM28XX_VMUX_SVIDEO,
-                       .vmux  = SAA7115_SVIDEO3,
-                       .amux  = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2860_BOARD_GADMEI_UTV330] = {
-               .name         = "Gadmei UTV330",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_TNF_5335MF,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2861_BOARD_GADMEI_UTV330PLUS] = {
-               .name         = "Gadmei UTV330+",
-               .tuner_type   = TUNER_TNF_5335MF,
-               .tda9887_conf = TDA9887_PRESENT,
-               .ir_codes     = RC_MAP_GADMEI_RM008Z,
-               .decoder      = EM28XX_SAA711X,
-               .xclk         = EM28XX_XCLK_FREQUENCY_12MHZ,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2860_BOARD_TERRATEC_HYBRID_XS] = {
-               .name         = "Terratec Cinergy A Hybrid XS",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .decoder      = EM28XX_TVP5150,
-
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               } },
-       },
-       [EM2861_BOARD_KWORLD_PVRTV_300U] = {
-               .name         = "KWorld PVRTV 300U",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .decoder      = EM28XX_TVP5150,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2861_BOARD_YAKUMO_MOVIE_MIXER] = {
-               .name          = "Yakumo MovieMixer",
-               .tuner_type    = TUNER_ABSENT,  /* Capture only device */
-               .decoder       = EM28XX_TVP5150,
-               .input         = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2860_BOARD_TVP5150_REFERENCE_DESIGN] = {
-               .name          = "EM2860/TVP5150 Reference Design",
-               .tuner_type    = TUNER_ABSENT,  /* Capture only device */
-               .decoder       = EM28XX_TVP5150,
-               .input         = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2861_BOARD_PLEXTOR_PX_TV100U] = {
-               .name         = "Plextor ConvertX PX-TV100U",
-               .tuner_type   = TUNER_TNF_5335MF,
-               .xclk         = EM28XX_XCLK_I2S_MSB_TIMING |
-                               EM28XX_XCLK_FREQUENCY_12MHZ,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_TVP5150,
-               .has_msp34xx  = 1,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = pinnacle_hybrid_pro_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = pinnacle_hybrid_pro_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = pinnacle_hybrid_pro_analog,
-               } },
-       },
-
-       /* Those boards with em2870 are DVB Only*/
-
-       [EM2870_BOARD_TERRATEC_XS] = {
-               .name         = "Terratec Cinergy T XS",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-       },
-       [EM2870_BOARD_TERRATEC_XS_MT2060] = {
-               .name         = "Terratec Cinergy T XS (MT2060)",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_ABSENT, /* MT2060 */
-       },
-       [EM2870_BOARD_KWORLD_350U] = {
-               .name         = "Kworld 350 U DVB-T",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-       },
-       [EM2870_BOARD_KWORLD_355U] = {
-               .name         = "Kworld 355 U DVB-T",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_ABSENT,
-               .tuner_gpio   = default_tuner_gpio,
-               .has_dvb      = 1,
-               .dvb_gpio     = default_digital,
-       },
-       [EM2870_BOARD_PINNACLE_PCTV_DVB] = {
-               .name         = "Pinnacle PCTV DVB-T",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_ABSENT, /* MT2060 */
-               /* djh - I have serious doubts this is right... */
-               .xclk         = EM28XX_XCLK_IR_RC5_MODE |
-                               EM28XX_XCLK_FREQUENCY_10MHZ,
-       },
-       [EM2870_BOARD_COMPRO_VIDEOMATE] = {
-               .name         = "Compro, VideoMate U3",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_ABSENT, /* MT2060 */
-       },
-
-       [EM2880_BOARD_TERRATEC_HYBRID_XS_FR] = {
-               .name         = "Terratec Hybrid XS Secam",
-               .has_msp34xx  = 1,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .decoder      = EM28XX_TVP5150,
-               .has_dvb      = 1,
-               .dvb_gpio     = terratec_cinergy_USB_XS_FR_digital,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = terratec_cinergy_USB_XS_FR_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = terratec_cinergy_USB_XS_FR_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = terratec_cinergy_USB_XS_FR_analog,
-               } },
-       },
-       [EM2884_BOARD_TERRATEC_H5] = {
-               .name         = "Terratec Cinergy H5",
-               .has_dvb      = 1,
-#if 0
-               .tuner_type   = TUNER_PHILIPS_TDA8290,
-               .tuner_addr   = 0x41,
-               .dvb_gpio     = terratec_h5_digital, /* FIXME: probably wrong */
-               .tuner_gpio   = terratec_h5_gpio,
-#else
-               .tuner_type   = TUNER_ABSENT,
-#endif
-               .i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
-                               EM28XX_I2C_CLK_WAIT_ENABLE |
-                               EM28XX_I2C_FREQ_400_KHZ,
-       },
-       [EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C] = {
-               .name         = "Hauppauge WinTV HVR 930C",
-               .has_dvb      = 1,
-#if 0 /* FIXME: Add analog support */
-               .tuner_type   = TUNER_XC5000,
-               .tuner_addr   = 0x41,
-               .dvb_gpio     = hauppauge_930c_digital,
-               .tuner_gpio   = hauppauge_930c_gpio,
-#else
-               .tuner_type   = TUNER_ABSENT,
-#endif
-               .ir_codes     = RC_MAP_HAUPPAUGE,
-               .i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
-                               EM28XX_I2C_CLK_WAIT_ENABLE |
-                               EM28XX_I2C_FREQ_400_KHZ,
-       },
-       [EM2884_BOARD_CINERGY_HTC_STICK] = {
-               .name         = "Terratec Cinergy HTC Stick",
-               .has_dvb      = 1,
-               .ir_codes     = RC_MAP_NEC_TERRATEC_CINERGY_XS,
-               .tuner_type   = TUNER_ABSENT,
-               .i2c_speed    = EM2874_I2C_SECONDARY_BUS_SELECT |
-                               EM28XX_I2C_CLK_WAIT_ENABLE |
-                               EM28XX_I2C_FREQ_400_KHZ,
-       },
-       [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900] = {
-               .name         = "Hauppauge WinTV HVR 900",
-               .tda9887_conf = TDA9887_PRESENT,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .mts_firmware = 1,
-               .has_dvb      = 1,
-               .dvb_gpio     = hauppauge_wintv_hvr_900_digital,
-               .ir_codes     = RC_MAP_HAUPPAUGE,
-               .decoder      = EM28XX_TVP5150,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               } },
-       },
-       [EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2] = {
-               .name         = "Hauppauge WinTV HVR 900 (R2)",
-               .tda9887_conf = TDA9887_PRESENT,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .mts_firmware = 1,
-               .has_dvb      = 1,
-               .dvb_gpio     = hauppauge_wintv_hvr_900R2_digital,
-               .ir_codes     = RC_MAP_HAUPPAUGE,
-               .decoder      = EM28XX_TVP5150,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               } },
-       },
-       [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850] = {
-               .name           = "Hauppauge WinTV HVR 850",
-               .tuner_type     = TUNER_XC2028,
-               .tuner_gpio     = default_tuner_gpio,
-               .mts_firmware   = 1,
-               .has_dvb        = 1,
-               .dvb_gpio       = hauppauge_wintv_hvr_900_digital,
-               .ir_codes       = RC_MAP_HAUPPAUGE,
-               .decoder        = EM28XX_TVP5150,
-               .input          = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               } },
-       },
-       [EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950] = {
-               .name           = "Hauppauge WinTV HVR 950",
-               .tuner_type     = TUNER_XC2028,
-               .tuner_gpio     = default_tuner_gpio,
-               .mts_firmware   = 1,
-               .has_dvb        = 1,
-               .dvb_gpio       = hauppauge_wintv_hvr_900_digital,
-               .ir_codes       = RC_MAP_HAUPPAUGE,
-               .decoder        = EM28XX_TVP5150,
-               .input          = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               } },
-       },
-       [EM2880_BOARD_PINNACLE_PCTV_HD_PRO] = {
-               .name           = "Pinnacle PCTV HD Pro Stick",
-               .tuner_type     = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .mts_firmware   = 1,
-               .has_dvb        = 1,
-               .dvb_gpio       = hauppauge_wintv_hvr_900_digital,
-               .ir_codes       = RC_MAP_PINNACLE_PCTV_HD,
-               .decoder        = EM28XX_TVP5150,
-               .input          = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               } },
-       },
-       [EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600] = {
-               .name           = "AMD ATI TV Wonder HD 600",
-               .tuner_type     = TUNER_XC2028,
-               .tuner_gpio     = default_tuner_gpio,
-               .mts_firmware   = 1,
-               .has_dvb        = 1,
-               .dvb_gpio       = hauppauge_wintv_hvr_900_digital,
-               .ir_codes       = RC_MAP_ATI_TV_WONDER_HD_600,
-               .decoder        = EM28XX_TVP5150,
-               .input          = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               } },
-       },
-       [EM2880_BOARD_TERRATEC_HYBRID_XS] = {
-               .name           = "Terratec Hybrid XS",
-               .tuner_type     = TUNER_XC2028,
-               .tuner_gpio     = default_tuner_gpio,
-               .decoder        = EM28XX_TVP5150,
-               .has_dvb        = 1,
-               .dvb_gpio       = default_digital,
-               .ir_codes       = RC_MAP_TERRATEC_CINERGY_XS,
-               .xclk           = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */
-               .input          = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = default_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = default_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = default_analog,
-               } },
-       },
-       /* maybe there's a reason behind it why Terratec sells the Hybrid XS
-          as Prodigy XS with a different PID, let's keep it separated for now
-          maybe we'll need it lateron */
-       [EM2880_BOARD_TERRATEC_PRODIGY_XS] = {
-               .name         = "Terratec Prodigy XS",
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .decoder      = EM28XX_TVP5150,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               } },
-       },
-       [EM2820_BOARD_MSI_VOX_USB_2] = {
-               .name              = "MSI VOX USB 2.0",
-               .tuner_type        = TUNER_LG_PAL_NEW_TAPC,
-               .tda9887_conf      = TDA9887_PRESENT      |
-                                    TDA9887_PORT1_ACTIVE |
-                                    TDA9887_PORT2_ACTIVE,
-               .max_range_640_480 = 1,
-               .decoder           = EM28XX_SAA711X,
-               .input             = { {
-                       .type      = EM28XX_VMUX_TELEVISION,
-                       .vmux      = SAA7115_COMPOSITE4,
-                       .amux      = EM28XX_AMUX_VIDEO,
-               }, {
-                       .type      = EM28XX_VMUX_COMPOSITE1,
-                       .vmux      = SAA7115_COMPOSITE0,
-                       .amux      = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type      = EM28XX_VMUX_SVIDEO,
-                       .vmux      = SAA7115_SVIDEO3,
-                       .amux      = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2800_BOARD_TERRATEC_CINERGY_200] = {
-               .name         = "Terratec Cinergy 200 USB",
-               .is_em2800    = 1,
-               .has_ir_i2c   = 1,
-               .tuner_type   = TUNER_LG_TALN,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2800_BOARD_GRABBEEX_USB2800] = {
-               .name       = "eMPIA Technology, Inc. GrabBeeX+ Video Encoder",
-               .is_em2800  = 1,
-               .decoder    = EM28XX_SAA711X,
-               .tuner_type = TUNER_ABSENT, /* capture only board */
-               .input      = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2800_BOARD_VC211A] = {
-               .name         = "Actionmaster/LinXcel/Digitus VC211A",
-               .is_em2800    = 1,
-               .tuner_type   = TUNER_ABSENT,   /* Capture-only board */
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = vc211a_enable,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = vc211a_enable,
-               } },
-       },
-       [EM2800_BOARD_LEADTEK_WINFAST_USBII] = {
-               .name         = "Leadtek Winfast USB II",
-               .is_em2800    = 1,
-               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2800_BOARD_KWORLD_USB2800] = {
-               .name         = "Kworld USB2800",
-               .is_em2800    = 1,
-               .tuner_type   = TUNER_PHILIPS_FCV1236D,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2820_BOARD_PINNACLE_DVC_90] = {
-               .name         = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker "
-                              "/ Kworld DVD Maker 2 / Plextor ConvertX PX-AV100U",
-               .tuner_type   = TUNER_ABSENT, /* capture only board */
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2800_BOARD_VGEAR_POCKETTV] = {
-               .name         = "V-Gear PocketTV",
-               .is_em2800    = 1,
-               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2] = {
-               .name         = "Pixelview PlayTV Box 4 USB 2.0",
-               .tda9887_conf = TDA9887_PRESENT,
-               .tuner_type   = TUNER_YMEC_TVF_5533MF,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .aout     = EM28XX_AOUT_MONO |  /* I2S */
-                                   EM28XX_AOUT_MASTER, /* Line out pin */
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2820_BOARD_PROLINK_PLAYTV_USB2] = {
-               .name         = "SIIG AVTuner-PVR / Pixelview Prolink PlayTV USB 2.0",
-               .has_snapshot_button = 1,
-               .tda9887_conf = TDA9887_PRESENT,
-               .tuner_type   = TUNER_YMEC_TVF_5533MF,
-               .decoder      = EM28XX_SAA711X,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = SAA7115_COMPOSITE2,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .aout     = EM28XX_AOUT_MONO |  /* I2S */
-                                   EM28XX_AOUT_MASTER, /* Line out pin */
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2860_BOARD_SAA711X_REFERENCE_DESIGN] = {
-               .name                = "EM2860/SAA711X Reference Design",
-               .has_snapshot_button = 1,
-               .tuner_type          = TUNER_ABSENT,
-               .decoder             = EM28XX_SAA711X,
-               .input               = { {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-               } },
-       },
-
-       [EM2874_BOARD_LEADERSHIP_ISDBT] = {
-               .i2c_speed      = EM2874_I2C_SECONDARY_BUS_SELECT |
-                                 EM28XX_I2C_CLK_WAIT_ENABLE |
-                                 EM28XX_I2C_FREQ_100_KHZ,
-               .xclk           = EM28XX_XCLK_FREQUENCY_10MHZ,
-               .name           = "EM2874 Leadership ISDBT",
-               .tuner_type     = TUNER_ABSENT,
-               .tuner_gpio     = leadership_reset,
-               .dvb_gpio       = leadership_digital,
-               .has_dvb        = 1,
-       },
-
-       [EM2880_BOARD_MSI_DIGIVOX_AD] = {
-               .name         = "MSI DigiVox A/D",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .decoder      = EM28XX_TVP5150,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = em2880_msi_digivox_ad_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = em2880_msi_digivox_ad_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = em2880_msi_digivox_ad_analog,
-               } },
-       },
-       [EM2880_BOARD_MSI_DIGIVOX_AD_II] = {
-               .name         = "MSI DigiVox A/D II",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .decoder      = EM28XX_TVP5150,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = em2880_msi_digivox_ad_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = em2880_msi_digivox_ad_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = em2880_msi_digivox_ad_analog,
-               } },
-       },
-       [EM2880_BOARD_KWORLD_DVB_305U] = {
-               .name         = "KWorld DVB-T 305U",
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .decoder      = EM28XX_TVP5150,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2880_BOARD_KWORLD_DVB_310U] = {
-               .name         = "KWorld DVB-T 310U",
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .has_dvb      = 1,
-               .dvb_gpio     = default_digital,
-               .mts_firmware = 1,
-               .decoder      = EM28XX_TVP5150,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = default_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = default_analog,
-               }, {    /* S-video has not been tested yet */
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = default_analog,
-               } },
-       },
-       [EM2882_BOARD_KWORLD_ATSC_315U] = {
-               .name           = "KWorld ATSC 315U HDTV TV Box",
-               .valid          = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type     = TUNER_THOMSON_DTT761X,
-               .tuner_gpio     = em2882_kworld_315u_tuner_gpio,
-               .tda9887_conf   = TDA9887_PRESENT,
-               .decoder        = EM28XX_SAA711X,
-               .has_dvb        = 1,
-               .dvb_gpio       = em2882_kworld_315u_digital,
-               .ir_codes       = RC_MAP_KWORLD_315U,
-               .xclk           = EM28XX_XCLK_FREQUENCY_12MHZ,
-               .i2c_speed      = EM28XX_I2C_CLK_WAIT_ENABLE,
-               /* Analog mode - still not ready */
-               /*.input        = { {
-                       .type = EM28XX_VMUX_TELEVISION,
-                       .vmux = SAA7115_COMPOSITE2,
-                       .amux = EM28XX_AMUX_VIDEO,
-                       .gpio = em2882_kworld_315u_analog,
-                       .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
-               }, {
-                       .type = EM28XX_VMUX_COMPOSITE1,
-                       .vmux = SAA7115_COMPOSITE0,
-                       .amux = EM28XX_AMUX_LINE_IN,
-                       .gpio = em2882_kworld_315u_analog1,
-                       .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
-               }, {
-                       .type = EM28XX_VMUX_SVIDEO,
-                       .vmux = SAA7115_SVIDEO3,
-                       .amux = EM28XX_AMUX_LINE_IN,
-                       .gpio = em2882_kworld_315u_analog1,
-                       .aout = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
-               } }, */
-       },
-       [EM2880_BOARD_EMPIRE_DUAL_TV] = {
-               .name = "Empire dual TV",
-               .tuner_type = TUNER_XC2028,
-               .tuner_gpio = default_tuner_gpio,
-               .has_dvb = 1,
-               .dvb_gpio = default_digital,
-               .mts_firmware = 1,
-               .decoder = EM28XX_TVP5150,
-               .input = { {
-                       .type = EM28XX_VMUX_TELEVISION,
-                       .vmux = TVP5150_COMPOSITE0,
-                       .amux = EM28XX_AMUX_VIDEO,
-                       .gpio = default_analog,
-               }, {
-                       .type = EM28XX_VMUX_COMPOSITE1,
-                       .vmux = TVP5150_COMPOSITE1,
-                       .amux = EM28XX_AMUX_LINE_IN,
-                       .gpio = default_analog,
-               }, {
-                       .type = EM28XX_VMUX_SVIDEO,
-                       .vmux = TVP5150_SVIDEO,
-                       .amux = EM28XX_AMUX_LINE_IN,
-                       .gpio = default_analog,
-               } },
-       },
-       [EM2881_BOARD_DNT_DA2_HYBRID] = {
-               .name         = "DNT DA2 Hybrid",
-               .valid        = EM28XX_BOARD_NOT_VALIDATED,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .decoder      = EM28XX_TVP5150,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = default_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = default_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = default_analog,
-               } },
-       },
-       [EM2881_BOARD_PINNACLE_HYBRID_PRO] = {
-               .name         = "Pinnacle Hybrid Pro",
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .decoder      = EM28XX_TVP5150,
-               .has_dvb      = 1,
-               .dvb_gpio     = pinnacle_hybrid_pro_digital,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = pinnacle_hybrid_pro_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = pinnacle_hybrid_pro_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = pinnacle_hybrid_pro_analog,
-               } },
-       },
-       [EM2882_BOARD_PINNACLE_HYBRID_PRO_330E] = {
-               .name         = "Pinnacle Hybrid Pro (330e)",
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .mts_firmware = 1,
-               .has_dvb      = 1,
-               .dvb_gpio     = hauppauge_wintv_hvr_900R2_digital,
-               .ir_codes     = RC_MAP_PINNACLE_PCTV_HD,
-               .decoder      = EM28XX_TVP5150,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               } },
-       },
-       [EM2882_BOARD_KWORLD_VS_DVBT] = {
-               .name         = "Kworld VS-DVB-T 323UR",
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .decoder      = EM28XX_TVP5150,
-               .mts_firmware = 1,
-               .has_dvb      = 1,
-               .dvb_gpio     = kworld_330u_digital,
-               .xclk         = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */
-               .ir_codes     = RC_MAP_KWORLD_315U,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2882_BOARD_TERRATEC_HYBRID_XS] = {
-               .name         = "Terratec Cinnergy Hybrid T USB XS (em2882)",
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .mts_firmware = 1,
-               .decoder      = EM28XX_TVP5150,
-               .has_dvb      = 1,
-               .dvb_gpio     = hauppauge_wintv_hvr_900_digital,
-               .ir_codes     = RC_MAP_TERRATEC_CINERGY_XS,
-               .xclk         = EM28XX_XCLK_FREQUENCY_12MHZ,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = hauppauge_wintv_hvr_900_analog,
-               } },
-       },
-       [EM2882_BOARD_DIKOM_DK300] = {
-               .name         = "Dikom DK300",
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .decoder      = EM28XX_TVP5150,
-               .mts_firmware = 1,
-               .has_dvb      = 1,
-               .dvb_gpio     = dikom_dk300_digital,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = default_analog,
-               } },
-       },
-       [EM2883_BOARD_KWORLD_HYBRID_330U] = {
-               .name         = "Kworld PlusTV HD Hybrid 330",
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .decoder      = EM28XX_TVP5150,
-               .mts_firmware = 1,
-               .has_dvb      = 1,
-               .dvb_gpio     = kworld_330u_digital,
-               .xclk             = EM28XX_XCLK_FREQUENCY_12MHZ,
-               .i2c_speed        = EM28XX_I2C_CLK_WAIT_ENABLE |
-                                   EM28XX_I2C_EEPROM_ON_BOARD |
-                                   EM28XX_I2C_EEPROM_KEY_VALID,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = kworld_330u_analog,
-                       .aout     = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = kworld_330u_analog,
-                       .aout     = EM28XX_AOUT_PCM_IN | EM28XX_AOUT_PCM_STEREO,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = kworld_330u_analog,
-               } },
-       },
-       [EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU] = {
-               .name         = "Compro VideoMate ForYou/Stereo",
-               .tuner_type   = TUNER_LG_PAL_NEW_TAPC,
-               .tvaudio_addr = 0xb0,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_TVP5150,
-               .adecoder     = EM28XX_TVAUDIO,
-               .mute_gpio    = compro_mute_gpio,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = compro_unmute_tv_gpio,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = compro_unmute_svid_gpio,
-               } },
-       },
-       [EM2860_BOARD_KAIOMY_TVNPC_U2] = {
-               .name         = "Kaiomy TVnPC U2",
-               .vchannels    = 3,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_addr   = 0x61,
-               .mts_firmware = 1,
-               .decoder      = EM28XX_TVP5150,
-               .tuner_gpio   = default_tuner_gpio,
-               .ir_codes     = RC_MAP_KAIOMY,
-               .input          = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-               .radio          = {
-                       .type     = EM28XX_RADIO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }
-       },
-       [EM2860_BOARD_EASYCAP] = {
-               .name         = "Easy Cap Capture DC-60",
-               .vchannels    = 2,
-               .tuner_type   = TUNER_ABSENT,
-               .decoder      = EM28XX_SAA711X,
-               .input           = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2820_BOARD_IODATA_GVMVP_SZ] = {
-               .name       = "IO-DATA GV-MVP/SZ",
-               .tuner_type   = TUNER_PHILIPS_FM1236_MK3,
-               .tuner_gpio   = default_tuner_gpio,
-               .tda9887_conf = TDA9887_PRESENT,
-               .decoder      = EM28XX_TVP5150,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, { /* Composite has not been tested yet */
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               }, { /* S-video has not been tested yet */
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_VIDEO,
-               } },
-       },
-       [EM2860_BOARD_TERRATEC_GRABBY] = {
-               .name            = "Terratec Grabby",
-               .vchannels       = 2,
-               .tuner_type      = TUNER_ABSENT,
-               .decoder         = EM28XX_SAA711X,
-               .xclk            = EM28XX_XCLK_FREQUENCY_12MHZ,
-               .input           = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       [EM2860_BOARD_TERRATEC_AV350] = {
-               .name            = "Terratec AV350",
-               .vchannels       = 2,
-               .tuner_type      = TUNER_ABSENT,
-               .decoder         = EM28XX_TVP5150,
-               .xclk            = EM28XX_XCLK_FREQUENCY_12MHZ,
-               .mute_gpio       = terratec_av350_mute_gpio,
-               .input           = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AUDIO_SRC_LINE,
-                       .gpio     = terratec_av350_unmute_gpio,
-
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AUDIO_SRC_LINE,
-                       .gpio     = terratec_av350_unmute_gpio,
-               } },
-       },
-
-       [EM2860_BOARD_ELGATO_VIDEO_CAPTURE] = {
-               .name         = "Elgato Video Capture",
-               .decoder      = EM28XX_SAA711X,
-               .tuner_type   = TUNER_ABSENT,   /* Capture only device */
-               .input        = { {
-                       .type  = EM28XX_VMUX_COMPOSITE1,
-                       .vmux  = SAA7115_COMPOSITE0,
-                       .amux  = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type  = EM28XX_VMUX_SVIDEO,
-                       .vmux  = SAA7115_SVIDEO3,
-                       .amux  = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-
-       [EM2882_BOARD_EVGA_INDTUBE] = {
-               .name         = "Evga inDtube",
-               .tuner_type   = TUNER_XC2028,
-               .tuner_gpio   = default_tuner_gpio,
-               .decoder      = EM28XX_TVP5150,
-               .xclk         = EM28XX_XCLK_FREQUENCY_12MHZ, /* NEC IR */
-               .mts_firmware = 1,
-               .has_dvb      = 1,
-               .dvb_gpio     = evga_indtube_digital,
-               .ir_codes     = RC_MAP_EVGA_INDTUBE,
-               .input        = { {
-                       .type     = EM28XX_VMUX_TELEVISION,
-                       .vmux     = TVP5150_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_VIDEO,
-                       .gpio     = evga_indtube_analog,
-               }, {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = TVP5150_COMPOSITE1,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = evga_indtube_analog,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = TVP5150_SVIDEO,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-                       .gpio     = evga_indtube_analog,
-               } },
-       },
-       /* eb1a:2868 Empia EM2870 + Philips CU1216L NIM (Philips TDA10023 +
-          Infineon TUA6034) */
-       [EM2870_BOARD_REDDO_DVB_C_USB_BOX] = {
-               .name          = "Reddo DVB-C USB TV Box",
-               .tuner_type    = TUNER_ABSENT,
-               .tuner_gpio    = reddo_dvb_c_usb_box,
-               .has_dvb       = 1,
-       },
-       /* 1b80:a340 - Empia EM2870, NXP TDA18271HD and LG DT3304, sold
-        * initially as the KWorld PlusTV 340U, then as the UB435-Q.
-        * Early variants have a TDA18271HD/C1, later ones a TDA18271HD/C2 */
-       [EM2870_BOARD_KWORLD_A340] = {
-               .name       = "KWorld PlusTV 340U or UB435-Q (ATSC)",
-               .tuner_type = TUNER_ABSENT,     /* Digital-only TDA18271HD */
-               .has_dvb    = 1,
-               .dvb_gpio   = kworld_a340_digital,
-               .tuner_gpio = default_tuner_gpio,
-       },
-       /* 2013:024f PCTV nanoStick T2 290e.
-        * Empia EM28174, Sony CXD2820R and NXP TDA18271HD/C2 */
-       [EM28174_BOARD_PCTV_290E] = {
-               .name          = "PCTV nanoStick T2 290e",
-               .i2c_speed      = EM2874_I2C_SECONDARY_BUS_SELECT |
-                       EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_100_KHZ,
-               .tuner_type    = TUNER_ABSENT,
-               .tuner_gpio    = pctv_290e,
-               .has_dvb       = 1,
-               .ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
-       },
-       /* 2013:024f PCTV DVB-S2 Stick 460e
-        * Empia EM28174, NXP TDA10071, Conexant CX24118A and Allegro A8293 */
-       [EM28174_BOARD_PCTV_460E] = {
-               .i2c_speed     = EM2874_I2C_SECONDARY_BUS_SELECT |
-                       EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
-               .name          = "PCTV DVB-S2 Stick (460e)",
-               .tuner_type    = TUNER_ABSENT,
-               .tuner_gpio    = pctv_460e,
-               .has_dvb       = 1,
-               .ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
-       },
-       /* eb1a:5006 Honestech VIDBOX NW03
-        * Empia EM2860, Philips SAA7113, Empia EMP202, No Tuner */
-       [EM2860_BOARD_HT_VIDBOX_NW03] = {
-               .name                = "Honestech Vidbox NW03",
-               .tuner_type          = TUNER_ABSENT,
-               .decoder             = EM28XX_SAA711X,
-               .input               = { {
-                       .type     = EM28XX_VMUX_COMPOSITE1,
-                       .vmux     = SAA7115_COMPOSITE0,
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               }, {
-                       .type     = EM28XX_VMUX_SVIDEO,
-                       .vmux     = SAA7115_SVIDEO3,  /* S-VIDEO needs confirming */
-                       .amux     = EM28XX_AMUX_LINE_IN,
-               } },
-       },
-       /* 1b80:e425 MaxMedia UB425-TC
-        * Empia EM2874B + Micronas DRX 3913KA2 + NXP TDA18271HDC2 */
-       [EM2874_BOARD_MAXMEDIA_UB425_TC] = {
-               .name          = "MaxMedia UB425-TC",
-               .tuner_type    = TUNER_ABSENT,
-               .tuner_gpio    = maxmedia_ub425_tc,
-               .has_dvb       = 1,
-               .i2c_speed     = EM2874_I2C_SECONDARY_BUS_SELECT |
-                               EM28XX_I2C_CLK_WAIT_ENABLE |
-                               EM28XX_I2C_FREQ_400_KHZ,
-       },
-       /* 2304:0242 PCTV QuatroStick (510e)
-        * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */
-       [EM2884_BOARD_PCTV_510E] = {
-               .name          = "PCTV QuatroStick (510e)",
-               .tuner_type    = TUNER_ABSENT,
-               .tuner_gpio    = pctv_510e,
-               .has_dvb       = 1,
-               .ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
-               .i2c_speed     = EM2874_I2C_SECONDARY_BUS_SELECT |
-                               EM28XX_I2C_CLK_WAIT_ENABLE |
-                               EM28XX_I2C_FREQ_400_KHZ,
-       },
-       /* 2013:0251 PCTV QuatroStick nano (520e)
-        * Empia EM2884 + Micronas DRX 3926K + NXP TDA18271HDC2 */
-       [EM2884_BOARD_PCTV_520E] = {
-               .name          = "PCTV QuatroStick nano (520e)",
-               .tuner_type    = TUNER_ABSENT,
-               .tuner_gpio    = pctv_520e,
-               .has_dvb       = 1,
-               .ir_codes      = RC_MAP_PINNACLE_PCTV_HD,
-               .i2c_speed     = EM2874_I2C_SECONDARY_BUS_SELECT |
-                               EM28XX_I2C_CLK_WAIT_ENABLE |
-                               EM28XX_I2C_FREQ_400_KHZ,
-       },
-};
-const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
-
-/* table of devices that work with this driver */
-struct usb_device_id em28xx_id_table[] = {
-       { USB_DEVICE(0xeb1a, 0x2750),
-                       .driver_info = EM2750_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0x2751),
-                       .driver_info = EM2750_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0x2800),
-                       .driver_info = EM2800_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0x2710),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0x2820),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0x2821),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0x2860),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0x2861),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0x2862),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0x2863),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0x2870),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0x2881),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0x2883),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0x2868),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0x2875),
-                       .driver_info = EM2820_BOARD_UNKNOWN },
-       { USB_DEVICE(0xeb1a, 0xe300),
-                       .driver_info = EM2861_BOARD_KWORLD_PVRTV_300U },
-       { USB_DEVICE(0xeb1a, 0xe303),
-                       .driver_info = EM2860_BOARD_KAIOMY_TVNPC_U2 },
-       { USB_DEVICE(0xeb1a, 0xe305),
-                       .driver_info = EM2880_BOARD_KWORLD_DVB_305U },
-       { USB_DEVICE(0xeb1a, 0xe310),
-                       .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD },
-       { USB_DEVICE(0xeb1a, 0xa313),
-               .driver_info = EM2882_BOARD_KWORLD_ATSC_315U },
-       { USB_DEVICE(0xeb1a, 0xa316),
-                       .driver_info = EM2883_BOARD_KWORLD_HYBRID_330U },
-       { USB_DEVICE(0xeb1a, 0xe320),
-                       .driver_info = EM2880_BOARD_MSI_DIGIVOX_AD_II },
-       { USB_DEVICE(0xeb1a, 0xe323),
-                       .driver_info = EM2882_BOARD_KWORLD_VS_DVBT },
-       { USB_DEVICE(0xeb1a, 0xe350),
-                       .driver_info = EM2870_BOARD_KWORLD_350U },
-       { USB_DEVICE(0xeb1a, 0xe355),
-                       .driver_info = EM2870_BOARD_KWORLD_355U },
-       { USB_DEVICE(0xeb1a, 0x2801),
-                       .driver_info = EM2800_BOARD_GRABBEEX_USB2800 },
-       { USB_DEVICE(0xeb1a, 0xe357),
-                       .driver_info = EM2870_BOARD_KWORLD_355U },
-       { USB_DEVICE(0xeb1a, 0xe359),
-                       .driver_info = EM2870_BOARD_KWORLD_355U },
-       { USB_DEVICE(0x1b80, 0xe302),
-                       .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kaiser Baas Video to DVD maker */
-       { USB_DEVICE(0x1b80, 0xe304),
-                       .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kworld DVD Maker 2 */
-       { USB_DEVICE(0x0ccd, 0x0036),
-                       .driver_info = EM2820_BOARD_TERRATEC_CINERGY_250 },
-       { USB_DEVICE(0x0ccd, 0x004c),
-                       .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS_FR },
-       { USB_DEVICE(0x0ccd, 0x004f),
-                       .driver_info = EM2860_BOARD_TERRATEC_HYBRID_XS },
-       { USB_DEVICE(0x0ccd, 0x005e),
-                       .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS },
-       { USB_DEVICE(0x0ccd, 0x0042),
-                       .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS },
-       { USB_DEVICE(0x0ccd, 0x0043),
-                       .driver_info = EM2870_BOARD_TERRATEC_XS },
-       { USB_DEVICE(0x0ccd, 0x008e),   /* Cinergy HTC USB XS Rev. 1 */
-                       .driver_info = EM2884_BOARD_TERRATEC_H5 },
-       { USB_DEVICE(0x0ccd, 0x00ac),   /* Cinergy HTC USB XS Rev. 2 */
-                       .driver_info = EM2884_BOARD_TERRATEC_H5 },
-       { USB_DEVICE(0x0ccd, 0x10a2),   /* H5 Rev. 1 */
-                       .driver_info = EM2884_BOARD_TERRATEC_H5 },
-       { USB_DEVICE(0x0ccd, 0x10ad),   /* H5 Rev. 2 */
-                       .driver_info = EM2884_BOARD_TERRATEC_H5 },
-       { USB_DEVICE(0x0ccd, 0x0084),
-                       .driver_info = EM2860_BOARD_TERRATEC_AV350 },
-       { USB_DEVICE(0x0ccd, 0x0096),
-                       .driver_info = EM2860_BOARD_TERRATEC_GRABBY },
-       { USB_DEVICE(0x0ccd, 0x10AF),
-                       .driver_info = EM2860_BOARD_TERRATEC_GRABBY },
-       { USB_DEVICE(0x0ccd, 0x00b2),
-                       .driver_info = EM2884_BOARD_CINERGY_HTC_STICK },
-       { USB_DEVICE(0x0fd9, 0x0033),
-                       .driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE},
-       { USB_DEVICE(0x185b, 0x2870),
-                       .driver_info = EM2870_BOARD_COMPRO_VIDEOMATE },
-       { USB_DEVICE(0x185b, 0x2041),
-                       .driver_info = EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU },
-       { USB_DEVICE(0x2040, 0x4200),
-                       .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 },
-       { USB_DEVICE(0x2040, 0x4201),
-                       .driver_info = EM2820_BOARD_HAUPPAUGE_WINTV_USB_2 },
-       { USB_DEVICE(0x2040, 0x6500),
-                       .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 },
-       { USB_DEVICE(0x2040, 0x6502),
-                       .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 },
-       { USB_DEVICE(0x2040, 0x6513), /* HCW HVR-980 */
-                       .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 },
-       { USB_DEVICE(0x2040, 0x6517), /* HP  HVR-950 */
-                       .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 },
-       { USB_DEVICE(0x2040, 0x651b), /* RP  HVR-950 */
-                       .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 },
-       { USB_DEVICE(0x2040, 0x651f),
-                       .driver_info = EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 },
-       { USB_DEVICE(0x0438, 0xb002),
-                       .driver_info = EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 },
-       { USB_DEVICE(0x2001, 0xf112),
-                       .driver_info = EM2820_BOARD_DLINK_USB_TV },
-       { USB_DEVICE(0x2304, 0x0207),
-                       .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
-       { USB_DEVICE(0x2304, 0x0208),
-                       .driver_info = EM2820_BOARD_PINNACLE_USB_2 },
-       { USB_DEVICE(0x2304, 0x021a),
-                       .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
-       { USB_DEVICE(0x2304, 0x0226),
-                       .driver_info = EM2882_BOARD_PINNACLE_HYBRID_PRO_330E },
-       { USB_DEVICE(0x2304, 0x0227),
-                       .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO },
-       { USB_DEVICE(0x0413, 0x6023),
-                       .driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII },
-       { USB_DEVICE(0x093b, 0xa003),
-                      .driver_info = EM2820_BOARD_PINNACLE_DVC_90 },
-       { USB_DEVICE(0x093b, 0xa005),
-                       .driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U },
-       { USB_DEVICE(0x04bb, 0x0515),
-                       .driver_info = EM2820_BOARD_IODATA_GVMVP_SZ },
-       { USB_DEVICE(0xeb1a, 0x50a6),
-                       .driver_info = EM2860_BOARD_GADMEI_UTV330 },
-       { USB_DEVICE(0x1b80, 0xa340),
-                       .driver_info = EM2870_BOARD_KWORLD_A340 },
-       { USB_DEVICE(0x2013, 0x024f),
-                       .driver_info = EM28174_BOARD_PCTV_290E },
-       { USB_DEVICE(0x2013, 0x024c),
-                       .driver_info = EM28174_BOARD_PCTV_460E },
-       { USB_DEVICE(0x2040, 0x1605),
-                       .driver_info = EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C },
-       { USB_DEVICE(0xeb1a, 0x5006),
-                       .driver_info = EM2860_BOARD_HT_VIDBOX_NW03 },
-       { USB_DEVICE(0x1b80, 0xe309), /* Sveon STV40 */
-                       .driver_info = EM2860_BOARD_EASYCAP },
-       { USB_DEVICE(0x1b80, 0xe425),
-                       .driver_info = EM2874_BOARD_MAXMEDIA_UB425_TC },
-       { USB_DEVICE(0x2304, 0x0242),
-                       .driver_info = EM2884_BOARD_PCTV_510E },
-       { USB_DEVICE(0x2013, 0x0251),
-                       .driver_info = EM2884_BOARD_PCTV_520E },
-       { },
-};
-MODULE_DEVICE_TABLE(usb, em28xx_id_table);
-
-/*
- * EEPROM hash table for devices with generic USB IDs
- */
-static struct em28xx_hash_table em28xx_eeprom_hash[] = {
-       /* P/N: SA 60002070465 Tuner: TVF7533-MF */
-       {0x6ce05a8f, EM2820_BOARD_PROLINK_PLAYTV_USB2, TUNER_YMEC_TVF_5533MF},
-       {0x72cc5a8b, EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2, TUNER_YMEC_TVF_5533MF},
-       {0x966a0441, EM2880_BOARD_KWORLD_DVB_310U, TUNER_XC2028},
-       {0x166a0441, EM2880_BOARD_EMPIRE_DUAL_TV, TUNER_XC2028},
-       {0xcee44a99, EM2882_BOARD_EVGA_INDTUBE, TUNER_XC2028},
-       {0xb8846b20, EM2881_BOARD_PINNACLE_HYBRID_PRO, TUNER_XC2028},
-       {0x63f653bd, EM2870_BOARD_REDDO_DVB_C_USB_BOX, TUNER_ABSENT},
-       {0x4e913442, EM2882_BOARD_DIKOM_DK300, TUNER_XC2028},
-};
-
-/* I2C devicelist hash table for devices with generic USB IDs */
-static struct em28xx_hash_table em28xx_i2c_hash[] = {
-       {0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC},
-       {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC},
-       {0x1ba50080, EM2860_BOARD_SAA711X_REFERENCE_DESIGN, TUNER_ABSENT},
-       {0x77800080, EM2860_BOARD_TVP5150_REFERENCE_DESIGN, TUNER_ABSENT},
-       {0xc51200e3, EM2820_BOARD_GADMEI_TVR200, TUNER_LG_PAL_NEW_TAPC},
-       {0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF},
-       {0x6b800080, EM2874_BOARD_LEADERSHIP_ISDBT, TUNER_ABSENT},
-};
-
-/* I2C possible address to saa7115, tvp5150, msp3400, tvaudio */
-static unsigned short saa711x_addrs[] = {
-       0x4a >> 1, 0x48 >> 1,   /* SAA7111, SAA7111A and SAA7113 */
-       0x42 >> 1, 0x40 >> 1,   /* SAA7114, SAA7115 and SAA7118 */
-       I2C_CLIENT_END };
-
-static unsigned short tvp5150_addrs[] = {
-       0xb8 >> 1,
-       0xba >> 1,
-       I2C_CLIENT_END
-};
-
-static unsigned short msp3400_addrs[] = {
-       0x80 >> 1,
-       0x88 >> 1,
-       I2C_CLIENT_END
-};
-
-int em28xx_tuner_callback(void *ptr, int component, int command, int arg)
-{
-       int rc = 0;
-       struct em28xx *dev = ptr;
-
-       if (dev->tuner_type != TUNER_XC2028 && dev->tuner_type != TUNER_XC5000)
-               return 0;
-
-       if (command != XC2028_TUNER_RESET && command != XC5000_TUNER_RESET)
-               return 0;
-
-       rc = em28xx_gpio_set(dev, dev->board.tuner_gpio);
-
-       return rc;
-}
-EXPORT_SYMBOL_GPL(em28xx_tuner_callback);
-
-static inline void em28xx_set_model(struct em28xx *dev)
-{
-       memcpy(&dev->board, &em28xx_boards[dev->model], sizeof(dev->board));
-
-       /* Those are the default values for the majority of boards
-          Use those values if not specified otherwise at boards entry
-        */
-       if (!dev->board.xclk)
-               dev->board.xclk = EM28XX_XCLK_IR_RC5_MODE |
-                                 EM28XX_XCLK_FREQUENCY_12MHZ;
-
-       if (!dev->board.i2c_speed)
-               dev->board.i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE |
-                                      EM28XX_I2C_FREQ_100_KHZ;
-}
-
-
-/* FIXME: Should be replaced by a proper mt9m111 driver */
-static int em28xx_initialize_mt9m111(struct em28xx *dev)
-{
-       int i;
-       unsigned char regs[][3] = {
-               { 0x0d, 0x00, 0x01, },  /* reset and use defaults */
-               { 0x0d, 0x00, 0x00, },
-               { 0x0a, 0x00, 0x21, },
-               { 0x21, 0x04, 0x00, },  /* full readout speed, no row/col skipping */
-       };
-
-       for (i = 0; i < ARRAY_SIZE(regs); i++)
-               i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
-
-       return 0;
-}
-
-
-/* FIXME: Should be replaced by a proper mt9m001 driver */
-static int em28xx_initialize_mt9m001(struct em28xx *dev)
-{
-       int i;
-       unsigned char regs[][3] = {
-               { 0x0d, 0x00, 0x01, },
-               { 0x0d, 0x00, 0x00, },
-               { 0x04, 0x05, 0x00, },  /* hres = 1280 */
-               { 0x03, 0x04, 0x00, },  /* vres = 1024 */
-               { 0x20, 0x11, 0x00, },
-               { 0x06, 0x00, 0x10, },
-               { 0x2b, 0x00, 0x24, },
-               { 0x2e, 0x00, 0x24, },
-               { 0x35, 0x00, 0x24, },
-               { 0x2d, 0x00, 0x20, },
-               { 0x2c, 0x00, 0x20, },
-               { 0x09, 0x0a, 0xd4, },
-               { 0x35, 0x00, 0x57, },
-       };
-
-       for (i = 0; i < ARRAY_SIZE(regs); i++)
-               i2c_master_send(&dev->i2c_client, &regs[i][0], 3);
-
-       return 0;
-}
-
-/* HINT method: webcam I2C chips
- *
- * This method works for webcams with Micron sensors
- */
-static int em28xx_hint_sensor(struct em28xx *dev)
-{
-       int rc;
-       char *sensor_name;
-       unsigned char cmd;
-       __be16 version_be;
-       u16 version;
-
-       /* Micron sensor detection */
-       dev->i2c_client.addr = 0xba >> 1;
-       cmd = 0;
-       i2c_master_send(&dev->i2c_client, &cmd, 1);
-       rc = i2c_master_recv(&dev->i2c_client, (char *)&version_be, 2);
-       if (rc != 2)
-               return -EINVAL;
-
-       version = be16_to_cpu(version_be);
-       switch (version) {
-       case 0x8232:            /* mt9v011 640x480 1.3 Mpix sensor */
-       case 0x8243:            /* mt9v011 rev B 640x480 1.3 Mpix sensor */
-               dev->model = EM2820_BOARD_SILVERCREST_WEBCAM;
-               em28xx_set_model(dev);
-
-               sensor_name = "mt9v011";
-               dev->em28xx_sensor = EM28XX_MT9V011;
-               dev->sensor_xres = 640;
-               dev->sensor_yres = 480;
-               /*
-                * FIXME: mt9v011 uses I2S speed as xtal clk - at least with
-                * the Silvercrest cam I have here for testing - for higher
-                * resolutions, a high clock cause horizontal artifacts, so we
-                * need to use a lower xclk frequency.
-                * Yet, it would be possible to adjust xclk depending on the
-                * desired resolution, since this affects directly the
-                * frame rate.
-                */
-               dev->board.xclk = EM28XX_XCLK_FREQUENCY_4_3MHZ;
-               dev->sensor_xtal = 4300000;
-
-               /* probably means GRGB 16 bit bayer */
-               dev->vinmode = 0x0d;
-               dev->vinctl = 0x00;
-
-               break;
-
-       case 0x143a:    /* MT9M111 as found in the ECS G200 */
-               dev->model = EM2750_BOARD_UNKNOWN;
-               em28xx_set_model(dev);
-
-               sensor_name = "mt9m111";
-               dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ;
-               dev->em28xx_sensor = EM28XX_MT9M111;
-               em28xx_initialize_mt9m111(dev);
-               dev->sensor_xres = 640;
-               dev->sensor_yres = 512;
-
-               dev->vinmode = 0x0a;
-               dev->vinctl = 0x00;
-
-               break;
-
-       case 0x8431:
-               dev->model = EM2750_BOARD_UNKNOWN;
-               em28xx_set_model(dev);
-
-               sensor_name = "mt9m001";
-               dev->em28xx_sensor = EM28XX_MT9M001;
-               em28xx_initialize_mt9m001(dev);
-               dev->sensor_xres = 1280;
-               dev->sensor_yres = 1024;
-
-               /* probably means BGGR 16 bit bayer */
-               dev->vinmode = 0x0c;
-               dev->vinctl = 0x00;
-
-               break;
-       default:
-               printk("Unknown Micron Sensor 0x%04x\n", version);
-               return -EINVAL;
-       }
-
-       /* Setup webcam defaults */
-       em28xx_pre_card_setup(dev);
-
-       em28xx_errdev("Sensor is %s, using model %s entry.\n",
-                     sensor_name, em28xx_boards[dev->model].name);
-
-       return 0;
-}
-
-/* Since em28xx_pre_card_setup() requires a proper dev->model,
- * this won't work for boards with generic PCI IDs
- */
-static void em28xx_pre_card_setup(struct em28xx *dev)
-{
-       /* Set the initial XCLK and I2C clock values based on the board
-          definition */
-       em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f);
-       if (!dev->board.is_em2800)
-               em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
-       msleep(50);
-
-       /* request some modules */
-       switch (dev->model) {
-       case EM2861_BOARD_PLEXTOR_PX_TV100U:
-               /* Sets the msp34xx I2S speed */
-               dev->i2s_speed = 2048000;
-               break;
-       case EM2861_BOARD_KWORLD_PVRTV_300U:
-       case EM2880_BOARD_KWORLD_DVB_305U:
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x6d);
-               msleep(10);
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0x7d);
-               msleep(10);
-               break;
-       case EM2870_BOARD_COMPRO_VIDEOMATE:
-               /* TODO: someone can do some cleanup here...
-                        not everything's needed */
-               em28xx_write_reg(dev, EM2880_R04_GPO, 0x00);
-               msleep(10);
-               em28xx_write_reg(dev, EM2880_R04_GPO, 0x01);
-               msleep(10);
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
-               mdelay(70);
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc);
-               mdelay(70);
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xdc);
-               mdelay(70);
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfc);
-               mdelay(70);
-               break;
-       case EM2870_BOARD_TERRATEC_XS_MT2060:
-               /* this device needs some gpio writes to get the DVB-T
-                  demod work */
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
-               mdelay(70);
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xde);
-               mdelay(70);
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
-               mdelay(70);
-               break;
-       case EM2870_BOARD_PINNACLE_PCTV_DVB:
-               /* this device needs some gpio writes to get the
-                  DVB-T demod work */
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
-               mdelay(70);
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xde);
-               mdelay(70);
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
-               mdelay(70);
-               break;
-       case EM2820_BOARD_GADMEI_UTV310:
-       case EM2820_BOARD_MSI_VOX_USB_2:
-               /* enables audio for that devices */
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
-               break;
-
-       case EM2882_BOARD_KWORLD_ATSC_315U:
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
-               msleep(10);
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
-               msleep(10);
-               em28xx_write_reg(dev, EM2880_R04_GPO, 0x00);
-               msleep(10);
-               em28xx_write_reg(dev, EM2880_R04_GPO, 0x08);
-               msleep(10);
-               break;
-
-       case EM2860_BOARD_KAIOMY_TVNPC_U2:
-               em28xx_write_regs(dev, EM28XX_R0F_XCLK, "\x07", 1);
-               em28xx_write_regs(dev, EM28XX_R06_I2C_CLK, "\x40", 1);
-               em28xx_write_regs(dev, 0x0d, "\x42", 1);
-               em28xx_write_regs(dev, 0x08, "\xfd", 1);
-               msleep(10);
-               em28xx_write_regs(dev, 0x08, "\xff", 1);
-               msleep(10);
-               em28xx_write_regs(dev, 0x08, "\x7f", 1);
-               msleep(10);
-               em28xx_write_regs(dev, 0x08, "\x6b", 1);
-
-               break;
-       case EM2860_BOARD_EASYCAP:
-               em28xx_write_regs(dev, 0x08, "\xf8", 1);
-               break;
-
-       case EM2820_BOARD_IODATA_GVMVP_SZ:
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
-               msleep(70);
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7);
-               msleep(10);
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfe);
-               msleep(70);
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
-               msleep(70);
-               break;
-       }
-
-       em28xx_gpio_set(dev, dev->board.tuner_gpio);
-       em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
-
-       /* Unlock device */
-       em28xx_set_mode(dev, EM28XX_SUSPEND);
-}
-
-static void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
-{
-       memset(ctl, 0, sizeof(*ctl));
-
-       ctl->fname   = XC2028_DEFAULT_FIRMWARE;
-       ctl->max_len = 64;
-       ctl->mts = em28xx_boards[dev->model].mts_firmware;
-
-       switch (dev->model) {
-       case EM2880_BOARD_EMPIRE_DUAL_TV:
-       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
-       case EM2882_BOARD_TERRATEC_HYBRID_XS:
-               ctl->demod = XC3028_FE_ZARLINK456;
-               break;
-       case EM2880_BOARD_TERRATEC_HYBRID_XS:
-       case EM2880_BOARD_TERRATEC_HYBRID_XS_FR:
-       case EM2881_BOARD_PINNACLE_HYBRID_PRO:
-               ctl->demod = XC3028_FE_ZARLINK456;
-               break;
-       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
-       case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
-               ctl->demod = XC3028_FE_DEFAULT;
-               break;
-       case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
-               ctl->demod = XC3028_FE_DEFAULT;
-               ctl->fname = XC3028L_DEFAULT_FIRMWARE;
-               break;
-       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
-       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
-       case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
-               /* FIXME: Better to specify the needed IF */
-               ctl->demod = XC3028_FE_DEFAULT;
-               break;
-       case EM2883_BOARD_KWORLD_HYBRID_330U:
-       case EM2882_BOARD_DIKOM_DK300:
-       case EM2882_BOARD_KWORLD_VS_DVBT:
-               ctl->demod = XC3028_FE_CHINA;
-               ctl->fname = XC2028_DEFAULT_FIRMWARE;
-               break;
-       case EM2882_BOARD_EVGA_INDTUBE:
-               ctl->demod = XC3028_FE_CHINA;
-               ctl->fname = XC3028L_DEFAULT_FIRMWARE;
-               break;
-       default:
-               ctl->demod = XC3028_FE_OREN538;
-       }
-}
-
-static void em28xx_tuner_setup(struct em28xx *dev)
-{
-       struct tuner_setup           tun_setup;
-       struct v4l2_frequency        f;
-
-       if (dev->tuner_type == TUNER_ABSENT)
-               return;
-
-       memset(&tun_setup, 0, sizeof(tun_setup));
-
-       tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
-       tun_setup.tuner_callback = em28xx_tuner_callback;
-
-       if (dev->board.radio.type) {
-               tun_setup.type = dev->board.radio.type;
-               tun_setup.addr = dev->board.radio_addr;
-
-               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
-       }
-
-       if ((dev->tuner_type != TUNER_ABSENT) && (dev->tuner_type)) {
-               tun_setup.type   = dev->tuner_type;
-               tun_setup.addr   = dev->tuner_addr;
-
-               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
-       }
-
-       if (dev->tda9887_conf) {
-               struct v4l2_priv_tun_config tda9887_cfg;
-
-               tda9887_cfg.tuner = TUNER_TDA9887;
-               tda9887_cfg.priv = &dev->tda9887_conf;
-
-               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &tda9887_cfg);
-       }
-
-       if (dev->tuner_type == TUNER_XC2028) {
-               struct v4l2_priv_tun_config  xc2028_cfg;
-               struct xc2028_ctrl           ctl;
-
-               memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
-               memset(&ctl, 0, sizeof(ctl));
-
-               em28xx_setup_xc3028(dev, &ctl);
-
-               xc2028_cfg.tuner = TUNER_XC2028;
-               xc2028_cfg.priv  = &ctl;
-
-               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config, &xc2028_cfg);
-       }
-
-       /* configure tuner */
-       f.tuner = 0;
-       f.type = V4L2_TUNER_ANALOG_TV;
-       f.frequency = 9076;     /* just a magic number */
-       dev->ctl_freq = f.frequency;
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
-}
-
-static int em28xx_hint_board(struct em28xx *dev)
-{
-       int i;
-
-       /* HINT method: EEPROM
-        *
-        * This method works only for boards with eeprom.
-        * Uses a hash of all eeprom bytes. The hash should be
-        * unique for a vendor/tuner pair.
-        * There are a high chance that tuners for different
-        * video standards produce different hashes.
-        */
-       for (i = 0; i < ARRAY_SIZE(em28xx_eeprom_hash); i++) {
-               if (dev->hash == em28xx_eeprom_hash[i].hash) {
-                       dev->model = em28xx_eeprom_hash[i].model;
-                       dev->tuner_type = em28xx_eeprom_hash[i].tuner;
-
-                       em28xx_errdev("Your board has no unique USB ID.\n");
-                       em28xx_errdev("A hint were successfully done, "
-                                     "based on eeprom hash.\n");
-                       em28xx_errdev("This method is not 100%% failproof.\n");
-                       em28xx_errdev("If the board were missdetected, "
-                                     "please email this log to:\n");
-                       em28xx_errdev("\tV4L Mailing List "
-                                     " <linux-media@vger.kernel.org>\n");
-                       em28xx_errdev("Board detected as %s\n",
-                                     em28xx_boards[dev->model].name);
-
-                       return 0;
-               }
-       }
-
-       /* HINT method: I2C attached devices
-        *
-        * This method works for all boards.
-        * Uses a hash of i2c scanned devices.
-        * Devices with the same i2c attached chips will
-        * be considered equal.
-        * This method is less precise than the eeprom one.
-        */
-
-       /* user did not request i2c scanning => do it now */
-       if (!dev->i2c_hash)
-               em28xx_do_i2c_scan(dev);
-
-       for (i = 0; i < ARRAY_SIZE(em28xx_i2c_hash); i++) {
-               if (dev->i2c_hash == em28xx_i2c_hash[i].hash) {
-                       dev->model = em28xx_i2c_hash[i].model;
-                       dev->tuner_type = em28xx_i2c_hash[i].tuner;
-                       em28xx_errdev("Your board has no unique USB ID.\n");
-                       em28xx_errdev("A hint were successfully done, "
-                                     "based on i2c devicelist hash.\n");
-                       em28xx_errdev("This method is not 100%% failproof.\n");
-                       em28xx_errdev("If the board were missdetected, "
-                                     "please email this log to:\n");
-                       em28xx_errdev("\tV4L Mailing List "
-                                     " <linux-media@vger.kernel.org>\n");
-                       em28xx_errdev("Board detected as %s\n",
-                                     em28xx_boards[dev->model].name);
-
-                       return 0;
-               }
-       }
-
-       em28xx_errdev("Your board has no unique USB ID and thus need a "
-                     "hint to be detected.\n");
-       em28xx_errdev("You may try to use card=<n> insmod option to "
-                     "workaround that.\n");
-       em28xx_errdev("Please send an email with this log to:\n");
-       em28xx_errdev("\tV4L Mailing List <linux-media@vger.kernel.org>\n");
-       em28xx_errdev("Board eeprom hash is 0x%08lx\n", dev->hash);
-       em28xx_errdev("Board i2c devicelist hash is 0x%08lx\n", dev->i2c_hash);
-
-       em28xx_errdev("Here is a list of valid choices for the card=<n>"
-                     " insmod option:\n");
-       for (i = 0; i < em28xx_bcount; i++) {
-               em28xx_errdev("    card=%d -> %s\n",
-                               i, em28xx_boards[i].name);
-       }
-       return -1;
-}
-
-static void em28xx_card_setup(struct em28xx *dev)
-{
-       /*
-        * If the device can be a webcam, seek for a sensor.
-        * If sensor is not found, then it isn't a webcam.
-        */
-       if (dev->board.is_webcam) {
-               if (em28xx_hint_sensor(dev) < 0)
-                       dev->board.is_webcam = 0;
-               else
-                       dev->progressive = 1;
-       }
-
-       if (!dev->board.is_webcam) {
-               switch (dev->model) {
-               case EM2820_BOARD_UNKNOWN:
-               case EM2800_BOARD_UNKNOWN:
-               /*
-                * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD.
-                *
-                * This occurs because they share identical USB vendor and
-                * product IDs.
-                *
-                * What we do here is look up the EEPROM hash of the K-WORLD
-                * and if it is found then we decide that we do not have
-                * a DIGIVOX and reset the device to the K-WORLD instead.
-                *
-                * This solution is only valid if they do not share eeprom
-                * hash identities which has not been determined as yet.
-                */
-               if (em28xx_hint_board(dev) < 0)
-                       em28xx_errdev("Board not discovered\n");
-               else {
-                       em28xx_set_model(dev);
-                       em28xx_pre_card_setup(dev);
-               }
-               break;
-               default:
-                       em28xx_set_model(dev);
-               }
-       }
-
-       em28xx_info("Identified as %s (card=%d)\n",
-                   dev->board.name, dev->model);
-
-       dev->tuner_type = em28xx_boards[dev->model].tuner_type;
-       if (em28xx_boards[dev->model].tuner_addr)
-               dev->tuner_addr = em28xx_boards[dev->model].tuner_addr;
-
-       if (em28xx_boards[dev->model].tda9887_conf)
-               dev->tda9887_conf = em28xx_boards[dev->model].tda9887_conf;
-
-       /* request some modules */
-       switch (dev->model) {
-       case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
-       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
-       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
-       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
-       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
-       {
-               struct tveeprom tv;
-#if defined(CONFIG_MODULES) && defined(MODULE)
-               request_module("tveeprom");
-#endif
-               /* Call first TVeeprom */
-
-               dev->i2c_client.addr = 0xa0 >> 1;
-               tveeprom_hauppauge_analog(&dev->i2c_client, &tv, dev->eedata);
-
-               dev->tuner_type = tv.tuner_type;
-
-               if (tv.audio_processor == V4L2_IDENT_MSPX4XX) {
-                       dev->i2s_speed = 2048000;
-                       dev->board.has_msp34xx = 1;
-               }
-               break;
-       }
-       case EM2882_BOARD_KWORLD_ATSC_315U:
-               em28xx_write_reg(dev, 0x0d, 0x42);
-               msleep(10);
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xfd);
-               msleep(10);
-               break;
-       case EM2820_BOARD_KWORLD_PVRTV2800RF:
-               /* GPIO enables sound on KWORLD PVR TV 2800RF */
-               em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf9);
-               break;
-       case EM2820_BOARD_UNKNOWN:
-       case EM2800_BOARD_UNKNOWN:
-               /*
-                * The K-WORLD DVB-T 310U is detected as an MSI Digivox AD.
-                *
-                * This occurs because they share identical USB vendor and
-                * product IDs.
-                *
-                * What we do here is look up the EEPROM hash of the K-WORLD
-                * and if it is found then we decide that we do not have
-                * a DIGIVOX and reset the device to the K-WORLD instead.
-                *
-                * This solution is only valid if they do not share eeprom
-                * hash identities which has not been determined as yet.
-                */
-       case EM2880_BOARD_MSI_DIGIVOX_AD:
-               if (!em28xx_hint_board(dev))
-                       em28xx_set_model(dev);
-
-               /* In cases where we had to use a board hint, the call to
-                  em28xx_set_mode() in em28xx_pre_card_setup() was a no-op,
-                  so make the call now so the analog GPIOs are set properly
-                  before probing the i2c bus. */
-               em28xx_gpio_set(dev, dev->board.tuner_gpio);
-               em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
-               break;
-
-/*
-                * The Dikom DK300 is detected as an Kworld VS-DVB-T 323UR.
-                *
-                * This occurs because they share identical USB vendor and
-                * product IDs.
-                *
-                * What we do here is look up the EEPROM hash of the Dikom
-                * and if it is found then we decide that we do not have
-                * a Kworld and reset the device to the Dikom instead.
-                *
-                * This solution is only valid if they do not share eeprom
-                * hash identities which has not been determined as yet.
-                */
-       case EM2882_BOARD_KWORLD_VS_DVBT:
-               if (!em28xx_hint_board(dev))
-                       em28xx_set_model(dev);
-
-               /* In cases where we had to use a board hint, the call to
-                  em28xx_set_mode() in em28xx_pre_card_setup() was a no-op,
-                  so make the call now so the analog GPIOs are set properly
-                  before probing the i2c bus. */
-               em28xx_gpio_set(dev, dev->board.tuner_gpio);
-               em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
-               break;
-       }
-
-       if (dev->board.valid == EM28XX_BOARD_NOT_VALIDATED) {
-               em28xx_errdev("\n\n");
-               em28xx_errdev("The support for this board weren't "
-                             "valid yet.\n");
-               em28xx_errdev("Please send a report of having this working\n");
-               em28xx_errdev("not to V4L mailing list (and/or to other "
-                               "addresses)\n\n");
-       }
-
-       /* Allow override tuner type by a module parameter */
-       if (tuner >= 0)
-               dev->tuner_type = tuner;
-
-       /* request some modules */
-       if (dev->board.has_msp34xx)
-               v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                       "msp3400", 0, msp3400_addrs);
-
-       if (dev->board.decoder == EM28XX_SAA711X)
-               v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                       "saa7115_auto", 0, saa711x_addrs);
-
-       if (dev->board.decoder == EM28XX_TVP5150)
-               v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                       "tvp5150", 0, tvp5150_addrs);
-
-       if (dev->em28xx_sensor == EM28XX_MT9V011) {
-               struct mt9v011_platform_data pdata;
-               struct i2c_board_info mt9v011_info = {
-                       .type = "mt9v011",
-                       .addr = 0xba >> 1,
-                       .platform_data = &pdata,
-               };
-
-               pdata.xtal = dev->sensor_xtal;
-               v4l2_i2c_new_subdev_board(&dev->v4l2_dev, &dev->i2c_adap,
-                               &mt9v011_info, NULL);
-       }
-
-
-       if (dev->board.adecoder == EM28XX_TVAUDIO)
-               v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                       "tvaudio", dev->board.tvaudio_addr, NULL);
-
-       if (dev->board.tuner_type != TUNER_ABSENT) {
-               int has_demod = (dev->tda9887_conf & TDA9887_PRESENT);
-
-               if (dev->board.radio.type)
-                       v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                               "tuner", dev->board.radio_addr, NULL);
-
-               if (has_demod)
-                       v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_adap, "tuner",
-                               0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
-               if (dev->tuner_addr == 0) {
-                       enum v4l2_i2c_tuner_type type =
-                               has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
-                       struct v4l2_subdev *sd;
-
-                       sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-                               &dev->i2c_adap, "tuner",
-                               0, v4l2_i2c_tuner_addrs(type));
-
-                       if (sd)
-                               dev->tuner_addr = v4l2_i2c_subdev_addr(sd);
-               } else {
-                       v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                               "tuner", dev->tuner_addr, NULL);
-               }
-       }
-
-       em28xx_tuner_setup(dev);
-}
-
-
-#if defined(CONFIG_MODULES) && defined(MODULE)
-static void request_module_async(struct work_struct *work)
-{
-       struct em28xx *dev = container_of(work,
-                            struct em28xx, request_module_wk);
-
-       if (dev->has_audio_class)
-               request_module("snd-usb-audio");
-       else if (dev->has_alsa_audio)
-               request_module("em28xx-alsa");
-
-       if (dev->board.has_dvb)
-               request_module("em28xx-dvb");
-       if (dev->board.ir_codes && !disable_ir)
-               request_module("em28xx-rc");
-}
-
-static void request_modules(struct em28xx *dev)
-{
-       INIT_WORK(&dev->request_module_wk, request_module_async);
-       schedule_work(&dev->request_module_wk);
-}
-
-static void flush_request_modules(struct em28xx *dev)
-{
-       flush_work_sync(&dev->request_module_wk);
-}
-#else
-#define request_modules(dev)
-#define flush_request_modules(dev)
-#endif /* CONFIG_MODULES */
-
-/*
- * em28xx_release_resources()
- * unregisters the v4l2,i2c and usb devices
- * called when the device gets disconnected or at module unload
-*/
-void em28xx_release_resources(struct em28xx *dev)
-{
-       /*FIXME: I2C IR should be disconnected */
-
-       em28xx_release_analog_resources(dev);
-
-       em28xx_i2c_unregister(dev);
-
-       v4l2_device_unregister(&dev->v4l2_dev);
-
-       usb_put_dev(dev->udev);
-
-       /* Mark device as unused */
-       clear_bit(dev->devno, &em28xx_devused);
-};
-
-/*
- * em28xx_init_dev()
- * allocates and inits the device structs, registers i2c bus and v4l device
- */
-static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
-                          struct usb_interface *interface,
-                          int minor)
-{
-       int retval;
-
-       dev->udev = udev;
-       mutex_init(&dev->ctrl_urb_lock);
-       spin_lock_init(&dev->slock);
-
-       dev->em28xx_write_regs = em28xx_write_regs;
-       dev->em28xx_read_reg = em28xx_read_reg;
-       dev->em28xx_read_reg_req_len = em28xx_read_reg_req_len;
-       dev->em28xx_write_regs_req = em28xx_write_regs_req;
-       dev->em28xx_read_reg_req = em28xx_read_reg_req;
-       dev->board.is_em2800 = em28xx_boards[dev->model].is_em2800;
-
-       em28xx_set_model(dev);
-
-       /* Set the default GPO/GPIO for legacy devices */
-       dev->reg_gpo_num = EM2880_R04_GPO;
-       dev->reg_gpio_num = EM28XX_R08_GPIO;
-
-       dev->wait_after_write = 5;
-
-       /* Based on the Chip ID, set the device configuration */
-       retval = em28xx_read_reg(dev, EM28XX_R0A_CHIPID);
-       if (retval > 0) {
-               dev->chip_id = retval;
-
-               switch (dev->chip_id) {
-               case CHIP_ID_EM2800:
-                       em28xx_info("chip ID is em2800\n");
-                       break;
-               case CHIP_ID_EM2710:
-                       em28xx_info("chip ID is em2710\n");
-                       break;
-               case CHIP_ID_EM2750:
-                       em28xx_info("chip ID is em2750\n");
-                       break;
-               case CHIP_ID_EM2820:
-                       em28xx_info("chip ID is em2820 (or em2710)\n");
-                       break;
-               case CHIP_ID_EM2840:
-                       em28xx_info("chip ID is em2840\n");
-                       break;
-               case CHIP_ID_EM2860:
-                       em28xx_info("chip ID is em2860\n");
-                       break;
-               case CHIP_ID_EM2870:
-                       em28xx_info("chip ID is em2870\n");
-                       dev->wait_after_write = 0;
-                       break;
-               case CHIP_ID_EM2874:
-                       em28xx_info("chip ID is em2874\n");
-                       dev->reg_gpio_num = EM2874_R80_GPIO;
-                       dev->wait_after_write = 0;
-                       break;
-               case CHIP_ID_EM28174:
-                       em28xx_info("chip ID is em28174\n");
-                       dev->reg_gpio_num = EM2874_R80_GPIO;
-                       dev->wait_after_write = 0;
-                       break;
-               case CHIP_ID_EM2883:
-                       em28xx_info("chip ID is em2882/em2883\n");
-                       dev->wait_after_write = 0;
-                       break;
-               case CHIP_ID_EM2884:
-                       em28xx_info("chip ID is em2884\n");
-                       dev->reg_gpio_num = EM2874_R80_GPIO;
-                       dev->wait_after_write = 0;
-                       break;
-               default:
-                       em28xx_info("em28xx chip ID = %d\n", dev->chip_id);
-               }
-       }
-
-       if (dev->is_audio_only) {
-               retval = em28xx_audio_setup(dev);
-               if (retval)
-                       return -ENODEV;
-               em28xx_init_extension(dev);
-
-               return 0;
-       }
-
-       /* Prepopulate cached GPO register content */
-       retval = em28xx_read_reg(dev, dev->reg_gpo_num);
-       if (retval >= 0)
-               dev->reg_gpo = retval;
-
-       em28xx_pre_card_setup(dev);
-
-       if (!dev->board.is_em2800) {
-               /* Resets I2C speed */
-               retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed);
-               if (retval < 0) {
-                       em28xx_errdev("%s: em28xx_write_reg failed!"
-                                     " retval [%d]\n",
-                                     __func__, retval);
-                       return retval;
-               }
-       }
-
-       retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
-       if (retval < 0) {
-               em28xx_errdev("Call to v4l2_device_register() failed!\n");
-               return retval;
-       }
-
-       /* register i2c bus */
-       retval = em28xx_i2c_register(dev);
-       if (retval < 0) {
-               em28xx_errdev("%s: em28xx_i2c_register - error [%d]!\n",
-                       __func__, retval);
-               goto unregister_dev;
-       }
-
-       /*
-        * Default format, used for tvp5150 or saa711x output formats
-        */
-       dev->vinmode = 0x10;
-       dev->vinctl  = EM28XX_VINCTRL_INTERLACED |
-                      EM28XX_VINCTRL_CCIR656_ENABLE;
-
-       /* Do board specific init and eeprom reading */
-       em28xx_card_setup(dev);
-
-       /* Configure audio */
-       retval = em28xx_audio_setup(dev);
-       if (retval < 0) {
-               em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
-                       __func__, retval);
-               goto fail;
-       }
-
-       /* wake i2c devices */
-       em28xx_wake_i2c(dev);
-
-       /* init video dma queues */
-       INIT_LIST_HEAD(&dev->vidq.active);
-       INIT_LIST_HEAD(&dev->vbiq.active);
-
-       if (dev->board.has_msp34xx) {
-               /* Send a reset to other chips via gpio */
-               retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xf7);
-               if (retval < 0) {
-                       em28xx_errdev("%s: em28xx_write_reg - "
-                                     "msp34xx(1) failed! error [%d]\n",
-                                     __func__, retval);
-                       goto fail;
-               }
-               msleep(3);
-
-               retval = em28xx_write_reg(dev, EM28XX_R08_GPIO, 0xff);
-               if (retval < 0) {
-                       em28xx_errdev("%s: em28xx_write_reg - "
-                                     "msp34xx(2) failed! error [%d]\n",
-                                     __func__, retval);
-                       goto fail;
-               }
-               msleep(3);
-       }
-
-       retval = em28xx_register_analog_devices(dev);
-       if (retval < 0) {
-               goto fail;
-       }
-
-       /* Save some power by putting tuner to sleep */
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
-
-       return 0;
-
-fail:
-       em28xx_i2c_unregister(dev);
-
-unregister_dev:
-       v4l2_device_unregister(&dev->v4l2_dev);
-
-       return retval;
-}
-
-/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
-#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
-
-/*
- * em28xx_usb_probe()
- * checks for supported devices
- */
-static int em28xx_usb_probe(struct usb_interface *interface,
-                           const struct usb_device_id *id)
-{
-       struct usb_device *udev;
-       struct em28xx *dev = NULL;
-       int retval;
-       bool has_audio = false, has_video = false, has_dvb = false;
-       int i, nr;
-       const int ifnum = interface->altsetting[0].desc.bInterfaceNumber;
-       char *speed;
-
-       udev = usb_get_dev(interface_to_usbdev(interface));
-
-       /* Check to see next free device and mark as used */
-       do {
-               nr = find_first_zero_bit(&em28xx_devused, EM28XX_MAXBOARDS);
-               if (nr >= EM28XX_MAXBOARDS) {
-                       /* No free device slots */
-                       printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
-                                       EM28XX_MAXBOARDS);
-                       retval = -ENOMEM;
-                       goto err_no_slot;
-               }
-       } while (test_and_set_bit(nr, &em28xx_devused));
-
-       /* Don't register audio interfaces */
-       if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
-               em28xx_err(DRIVER_NAME " audio device (%04x:%04x): "
-                       "interface %i, class %i\n",
-                       le16_to_cpu(udev->descriptor.idVendor),
-                       le16_to_cpu(udev->descriptor.idProduct),
-                       ifnum,
-                       interface->altsetting[0].desc.bInterfaceClass);
-
-               retval = -ENODEV;
-               goto err;
-       }
-
-       /* allocate memory for our device state and initialize it */
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL) {
-               em28xx_err(DRIVER_NAME ": out of memory!\n");
-               retval = -ENOMEM;
-               goto err;
-       }
-
-       /* compute alternate max packet sizes */
-       dev->alt_max_pkt_size = kmalloc(sizeof(dev->alt_max_pkt_size[0]) *
-                                       interface->num_altsetting, GFP_KERNEL);
-       if (dev->alt_max_pkt_size == NULL) {
-               em28xx_errdev("out of memory!\n");
-               kfree(dev);
-               retval = -ENOMEM;
-               goto err;
-       }
-
-       /* Get endpoints */
-       for (i = 0; i < interface->num_altsetting; i++) {
-               int ep;
-
-               for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) {
-                       const struct usb_endpoint_descriptor *e;
-                       int sizedescr, size;
-
-                       e = &interface->altsetting[i].endpoint[ep].desc;
-
-                       sizedescr = le16_to_cpu(e->wMaxPacketSize);
-                       size = sizedescr & 0x7ff;
-
-                       if (udev->speed == USB_SPEED_HIGH)
-                               size = size * hb_mult(sizedescr);
-
-                       if (usb_endpoint_xfer_isoc(e) &&
-                           usb_endpoint_dir_in(e)) {
-                               switch (e->bEndpointAddress) {
-                               case EM28XX_EP_AUDIO:
-                                       has_audio = true;
-                                       break;
-                               case EM28XX_EP_ANALOG:
-                                       has_video = true;
-                                       dev->alt_max_pkt_size[i] = size;
-                                       break;
-                               case EM28XX_EP_DIGITAL:
-                                       has_dvb = true;
-                                       if (size > dev->dvb_max_pkt_size) {
-                                               dev->dvb_max_pkt_size = size;
-                                               dev->dvb_alt = i;
-                                       }
-                                       break;
-                               }
-                       }
-               }
-       }
-
-       if (!(has_audio || has_video || has_dvb)) {
-               retval = -ENODEV;
-               goto err_free;
-       }
-
-       switch (udev->speed) {
-       case USB_SPEED_LOW:
-               speed = "1.5";
-               break;
-       case USB_SPEED_UNKNOWN:
-       case USB_SPEED_FULL:
-               speed = "12";
-               break;
-       case USB_SPEED_HIGH:
-               speed = "480";
-               break;
-       default:
-               speed = "unknown";
-       }
-
-       printk(KERN_INFO DRIVER_NAME
-               ": New device %s %s @ %s Mbps "
-               "(%04x:%04x, interface %d, class %d)\n",
-               udev->manufacturer ? udev->manufacturer : "",
-               udev->product ? udev->product : "",
-               speed,
-               le16_to_cpu(udev->descriptor.idVendor),
-               le16_to_cpu(udev->descriptor.idProduct),
-               ifnum,
-               interface->altsetting->desc.bInterfaceNumber);
-
-       if (has_audio)
-               printk(KERN_INFO DRIVER_NAME
-                      ": Audio Vendor Class interface %i found\n",
-                      ifnum);
-       if (has_video)
-               printk(KERN_INFO DRIVER_NAME
-                      ": Video interface %i found\n",
-                      ifnum);
-       if (has_dvb)
-               printk(KERN_INFO DRIVER_NAME
-                      ": DVB interface %i found\n",
-                      ifnum);
-
-       /*
-        * Make sure we have 480 Mbps of bandwidth, otherwise things like
-        * video stream wouldn't likely work, since 12 Mbps is generally
-        * not enough even for most Digital TV streams.
-        */
-       if (udev->speed != USB_SPEED_HIGH && disable_usb_speed_check == 0) {
-               printk(DRIVER_NAME ": Device initialization failed.\n");
-               printk(DRIVER_NAME ": Device must be connected to a high-speed"
-                      " USB 2.0 port.\n");
-               retval = -ENODEV;
-               goto err_free;
-       }
-
-       snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr);
-       dev->devno = nr;
-       dev->model = id->driver_info;
-       dev->alt   = -1;
-       dev->is_audio_only = has_audio && !(has_video || has_dvb);
-       dev->has_alsa_audio = has_audio;
-       dev->audio_ifnum = ifnum;
-
-       /* Checks if audio is provided by some interface */
-       for (i = 0; i < udev->config->desc.bNumInterfaces; i++) {
-               struct usb_interface *uif = udev->config->interface[i];
-               if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
-                       dev->has_audio_class = 1;
-                       break;
-               }
-       }
-
-       dev->num_alt = interface->num_altsetting;
-
-       if ((card[nr] >= 0) && (card[nr] < em28xx_bcount))
-               dev->model = card[nr];
-
-       /* save our data pointer in this interface device */
-       usb_set_intfdata(interface, dev);
-
-       /* allocate device struct */
-       mutex_init(&dev->lock);
-       mutex_lock(&dev->lock);
-       retval = em28xx_init_dev(dev, udev, interface, nr);
-       if (retval) {
-               goto unlock_and_free;
-       }
-
-       if (has_dvb) {
-               /* pre-allocate DVB isoc transfer buffers */
-               retval = em28xx_alloc_isoc(dev, EM28XX_DIGITAL_MODE,
-                                          EM28XX_DVB_MAX_PACKETS,
-                                          EM28XX_DVB_NUM_BUFS,
-                                          dev->dvb_max_pkt_size);
-               if (retval) {
-                       goto unlock_and_free;
-               }
-       }
-
-       request_modules(dev);
-
-       /* Should be the last thing to do, to avoid newer udev's to
-          open the device before fully initializing it
-        */
-       mutex_unlock(&dev->lock);
-
-       /*
-        * These extensions can be modules. If the modules are already
-        * loaded then we can initialise the device now, otherwise we
-        * will initialise it when the modules load instead.
-        */
-       em28xx_init_extension(dev);
-
-       return 0;
-
-unlock_and_free:
-       mutex_unlock(&dev->lock);
-
-err_free:
-       kfree(dev->alt_max_pkt_size);
-       kfree(dev);
-
-err:
-       clear_bit(nr, &em28xx_devused);
-
-err_no_slot:
-       usb_put_dev(udev);
-       return retval;
-}
-
-/*
- * em28xx_usb_disconnect()
- * called when the device gets disconnected
- * video device will be unregistered on v4l2_close in case it is still open
- */
-static void em28xx_usb_disconnect(struct usb_interface *interface)
-{
-       struct em28xx *dev;
-
-       dev = usb_get_intfdata(interface);
-       usb_set_intfdata(interface, NULL);
-
-       if (!dev)
-               return;
-
-       if (dev->is_audio_only) {
-               mutex_lock(&dev->lock);
-               em28xx_close_extension(dev);
-               mutex_unlock(&dev->lock);
-               return;
-       }
-
-       em28xx_info("disconnecting %s\n", dev->vdev->name);
-
-       flush_request_modules(dev);
-
-       /* wait until all current v4l2 io is finished then deallocate
-          resources */
-       mutex_lock(&dev->lock);
-
-       v4l2_device_disconnect(&dev->v4l2_dev);
-
-       if (dev->users) {
-               em28xx_warn
-                   ("device %s is open! Deregistration and memory "
-                    "deallocation are deferred on close.\n",
-                    video_device_node_name(dev->vdev));
-
-               dev->state |= DEV_MISCONFIGURED;
-               em28xx_uninit_isoc(dev, dev->mode);
-               dev->state |= DEV_DISCONNECTED;
-       } else {
-               dev->state |= DEV_DISCONNECTED;
-               em28xx_release_resources(dev);
-       }
-
-       /* free DVB isoc buffers */
-       em28xx_uninit_isoc(dev, EM28XX_DIGITAL_MODE);
-
-       mutex_unlock(&dev->lock);
-
-       em28xx_close_extension(dev);
-
-       if (!dev->users) {
-               kfree(dev->alt_max_pkt_size);
-               kfree(dev);
-       }
-}
-
-static struct usb_driver em28xx_usb_driver = {
-       .name = "em28xx",
-       .probe = em28xx_usb_probe,
-       .disconnect = em28xx_usb_disconnect,
-       .id_table = em28xx_id_table,
-};
-
-module_usb_driver(em28xx_usb_driver);
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
deleted file mode 100644 (file)
index bed07a6..0000000
+++ /dev/null
@@ -1,1260 +0,0 @@
-/*
-   em28xx-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
-
-   Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
-                     Markus Rechberger <mrechberger@gmail.com>
-                     Mauro Carvalho Chehab <mchehab@infradead.org>
-                     Sascha Sommer <saschasommer@freenet.de>
-
-   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/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/vmalloc.h>
-#include <sound/ac97_codec.h>
-#include <media/v4l2-common.h>
-
-#include "em28xx.h"
-
-/* #define ENABLE_DEBUG_ISOC_FRAMES */
-
-static unsigned int core_debug;
-module_param(core_debug, int, 0644);
-MODULE_PARM_DESC(core_debug, "enable debug messages [core]");
-
-#define em28xx_coredbg(fmt, arg...) do {\
-       if (core_debug) \
-               printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __func__ , ##arg); } while (0)
-
-static unsigned int reg_debug;
-module_param(reg_debug, int, 0644);
-MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]");
-
-#define em28xx_regdbg(fmt, arg...) do {\
-       if (reg_debug) \
-               printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __func__ , ##arg); } while (0)
-
-static int alt;
-module_param(alt, int, 0644);
-MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
-
-static unsigned int disable_vbi;
-module_param(disable_vbi, int, 0644);
-MODULE_PARM_DESC(disable_vbi, "disable vbi support");
-
-/* FIXME */
-#define em28xx_isocdbg(fmt, arg...) do {\
-       if (core_debug) \
-               printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __func__ , ##arg); } while (0)
-
-/*
- * em28xx_read_reg_req()
- * reads data from the usb device specifying bRequest
- */
-int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
-                                  char *buf, int len)
-{
-       int ret;
-       int pipe = usb_rcvctrlpipe(dev->udev, 0);
-
-       if (dev->state & DEV_DISCONNECTED)
-               return -ENODEV;
-
-       if (len > URB_MAX_CTRL_SIZE)
-               return -EINVAL;
-
-       if (reg_debug) {
-               printk(KERN_DEBUG "(pipe 0x%08x): "
-                       "IN:  %02x %02x %02x %02x %02x %02x %02x %02x ",
-                       pipe,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       req, 0, 0,
-                       reg & 0xff, reg >> 8,
-                       len & 0xff, len >> 8);
-       }
-
-       mutex_lock(&dev->ctrl_urb_lock);
-       ret = usb_control_msg(dev->udev, pipe, req,
-                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             0x0000, reg, dev->urb_buf, len, HZ);
-       if (ret < 0) {
-               if (reg_debug)
-                       printk(" failed!\n");
-               mutex_unlock(&dev->ctrl_urb_lock);
-               return ret;
-       }
-
-       if (len)
-               memcpy(buf, dev->urb_buf, len);
-
-       mutex_unlock(&dev->ctrl_urb_lock);
-
-       if (reg_debug) {
-               int byte;
-
-               printk("<<<");
-               for (byte = 0; byte < len; byte++)
-                       printk(" %02x", (unsigned char)buf[byte]);
-               printk("\n");
-       }
-
-       return ret;
-}
-
-/*
- * em28xx_read_reg_req()
- * reads data from the usb device specifying bRequest
- */
-int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg)
-{
-       int ret;
-       u8 val;
-
-       ret = em28xx_read_reg_req_len(dev, req, reg, &val, 1);
-       if (ret < 0)
-               return ret;
-
-       return val;
-}
-
-int em28xx_read_reg(struct em28xx *dev, u16 reg)
-{
-       return em28xx_read_reg_req(dev, USB_REQ_GET_STATUS, reg);
-}
-EXPORT_SYMBOL_GPL(em28xx_read_reg);
-
-/*
- * em28xx_write_regs_req()
- * sends data to the usb device, specifying bRequest
- */
-int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
-                                int len)
-{
-       int ret;
-       int pipe = usb_sndctrlpipe(dev->udev, 0);
-
-       if (dev->state & DEV_DISCONNECTED)
-               return -ENODEV;
-
-       if ((len < 1) || (len > URB_MAX_CTRL_SIZE))
-               return -EINVAL;
-
-       if (reg_debug) {
-               int byte;
-
-               printk(KERN_DEBUG "(pipe 0x%08x): "
-                       "OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>",
-                       pipe,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       req, 0, 0,
-                       reg & 0xff, reg >> 8,
-                       len & 0xff, len >> 8);
-
-               for (byte = 0; byte < len; byte++)
-                       printk(" %02x", (unsigned char)buf[byte]);
-               printk("\n");
-       }
-
-       mutex_lock(&dev->ctrl_urb_lock);
-       memcpy(dev->urb_buf, buf, len);
-       ret = usb_control_msg(dev->udev, pipe, req,
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             0x0000, reg, dev->urb_buf, len, HZ);
-       mutex_unlock(&dev->ctrl_urb_lock);
-
-       if (dev->wait_after_write)
-               msleep(dev->wait_after_write);
-
-       return ret;
-}
-
-int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len)
-{
-       int rc;
-
-       rc = em28xx_write_regs_req(dev, USB_REQ_GET_STATUS, reg, buf, len);
-
-       /* Stores GPO/GPIO values at the cache, if changed
-          Only write values should be stored, since input on a GPIO
-          register will return the input bits.
-          Not sure what happens on reading GPO register.
-        */
-       if (rc >= 0) {
-               if (reg == dev->reg_gpo_num)
-                       dev->reg_gpo = buf[0];
-               else if (reg == dev->reg_gpio_num)
-                       dev->reg_gpio = buf[0];
-       }
-
-       return rc;
-}
-EXPORT_SYMBOL_GPL(em28xx_write_regs);
-
-/* Write a single register */
-int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val)
-{
-       return em28xx_write_regs(dev, reg, &val, 1);
-}
-EXPORT_SYMBOL_GPL(em28xx_write_reg);
-
-/*
- * em28xx_write_reg_bits()
- * sets only some bits (specified by bitmask) of a register, by first reading
- * the actual value
- */
-int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
-                                u8 bitmask)
-{
-       int oldval;
-       u8 newval;
-
-       /* Uses cache for gpo/gpio registers */
-       if (reg == dev->reg_gpo_num)
-               oldval = dev->reg_gpo;
-       else if (reg == dev->reg_gpio_num)
-               oldval = dev->reg_gpio;
-       else
-               oldval = em28xx_read_reg(dev, reg);
-
-       if (oldval < 0)
-               return oldval;
-
-       newval = (((u8) oldval) & ~bitmask) | (val & bitmask);
-
-       return em28xx_write_regs(dev, reg, &newval, 1);
-}
-EXPORT_SYMBOL_GPL(em28xx_write_reg_bits);
-
-/*
- * em28xx_is_ac97_ready()
- * Checks if ac97 is ready
- */
-static int em28xx_is_ac97_ready(struct em28xx *dev)
-{
-       int ret, i;
-
-       /* Wait up to 50 ms for AC97 command to complete */
-       for (i = 0; i < 10; i++, msleep(5)) {
-               ret = em28xx_read_reg(dev, EM28XX_R43_AC97BUSY);
-               if (ret < 0)
-                       return ret;
-
-               if (!(ret & 0x01))
-                       return 0;
-       }
-
-       em28xx_warn("AC97 command still being executed: not handled properly!\n");
-       return -EBUSY;
-}
-
-/*
- * em28xx_read_ac97()
- * write a 16 bit value to the specified AC97 address (LSB first!)
- */
-int em28xx_read_ac97(struct em28xx *dev, u8 reg)
-{
-       int ret;
-       u8 addr = (reg & 0x7f) | 0x80;
-       u16 val;
-
-       ret = em28xx_is_ac97_ready(dev);
-       if (ret < 0)
-               return ret;
-
-       ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1);
-       if (ret < 0)
-               return ret;
-
-       ret = dev->em28xx_read_reg_req_len(dev, 0, EM28XX_R40_AC97LSB,
-                                          (u8 *)&val, sizeof(val));
-
-       if (ret < 0)
-               return ret;
-       return le16_to_cpu(val);
-}
-EXPORT_SYMBOL_GPL(em28xx_read_ac97);
-
-/*
- * em28xx_write_ac97()
- * write a 16 bit value to the specified AC97 address (LSB first!)
- */
-int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val)
-{
-       int ret;
-       u8 addr = reg & 0x7f;
-       __le16 value;
-
-       value = cpu_to_le16(val);
-
-       ret = em28xx_is_ac97_ready(dev);
-       if (ret < 0)
-               return ret;
-
-       ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, (u8 *) &value, 2);
-       if (ret < 0)
-               return ret;
-
-       ret = em28xx_write_regs(dev, EM28XX_R42_AC97ADDR, &addr, 1);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(em28xx_write_ac97);
-
-struct em28xx_vol_itable {
-       enum em28xx_amux mux;
-       u8               reg;
-};
-
-static struct em28xx_vol_itable inputs[] = {
-       { EM28XX_AMUX_VIDEO,    AC97_VIDEO      },
-       { EM28XX_AMUX_LINE_IN,  AC97_LINE       },
-       { EM28XX_AMUX_PHONE,    AC97_PHONE      },
-       { EM28XX_AMUX_MIC,      AC97_MIC        },
-       { EM28XX_AMUX_CD,       AC97_CD         },
-       { EM28XX_AMUX_AUX,      AC97_AUX        },
-       { EM28XX_AMUX_PCM_OUT,  AC97_PCM        },
-};
-
-static int set_ac97_input(struct em28xx *dev)
-{
-       int ret, i;
-       enum em28xx_amux amux = dev->ctl_ainput;
-
-       /* EM28XX_AMUX_VIDEO2 is a special case used to indicate that
-          em28xx should point to LINE IN, while AC97 should use VIDEO
-        */
-       if (amux == EM28XX_AMUX_VIDEO2)
-               amux = EM28XX_AMUX_VIDEO;
-
-       /* Mute all entres but the one that were selected */
-       for (i = 0; i < ARRAY_SIZE(inputs); i++) {
-               if (amux == inputs[i].mux)
-                       ret = em28xx_write_ac97(dev, inputs[i].reg, 0x0808);
-               else
-                       ret = em28xx_write_ac97(dev, inputs[i].reg, 0x8000);
-
-               if (ret < 0)
-                       em28xx_warn("couldn't setup AC97 register %d\n",
-                                    inputs[i].reg);
-       }
-       return 0;
-}
-
-static int em28xx_set_audio_source(struct em28xx *dev)
-{
-       int ret;
-       u8 input;
-
-       if (dev->board.is_em2800) {
-               if (dev->ctl_ainput == EM28XX_AMUX_VIDEO)
-                       input = EM2800_AUDIO_SRC_TUNER;
-               else
-                       input = EM2800_AUDIO_SRC_LINE;
-
-               ret = em28xx_write_regs(dev, EM2800_R08_AUDIOSRC, &input, 1);
-               if (ret < 0)
-                       return ret;
-       }
-
-       if (dev->board.has_msp34xx)
-               input = EM28XX_AUDIO_SRC_TUNER;
-       else {
-               switch (dev->ctl_ainput) {
-               case EM28XX_AMUX_VIDEO:
-                       input = EM28XX_AUDIO_SRC_TUNER;
-                       break;
-               default:
-                       input = EM28XX_AUDIO_SRC_LINE;
-                       break;
-               }
-       }
-
-       if (dev->board.mute_gpio && dev->mute)
-               em28xx_gpio_set(dev, dev->board.mute_gpio);
-       else
-               em28xx_gpio_set(dev, INPUT(dev->ctl_input)->gpio);
-
-       ret = em28xx_write_reg_bits(dev, EM28XX_R0E_AUDIOSRC, input, 0xc0);
-       if (ret < 0)
-               return ret;
-       msleep(5);
-
-       switch (dev->audio_mode.ac97) {
-       case EM28XX_NO_AC97:
-               break;
-       default:
-               ret = set_ac97_input(dev);
-       }
-
-       return ret;
-}
-
-struct em28xx_vol_otable {
-       enum em28xx_aout mux;
-       u8               reg;
-};
-
-static const struct em28xx_vol_otable outputs[] = {
-       { EM28XX_AOUT_MASTER, AC97_MASTER               },
-       { EM28XX_AOUT_LINE,   AC97_HEADPHONE            },
-       { EM28XX_AOUT_MONO,   AC97_MASTER_MONO          },
-       { EM28XX_AOUT_LFE,    AC97_CENTER_LFE_MASTER    },
-       { EM28XX_AOUT_SURR,   AC97_SURROUND_MASTER      },
-};
-
-int em28xx_audio_analog_set(struct em28xx *dev)
-{
-       int ret, i;
-       u8 xclk;
-
-       if (!dev->audio_mode.has_audio)
-               return 0;
-
-       /* It is assumed that all devices use master volume for output.
-          It would be possible to use also line output.
-        */
-       if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
-               /* Mute all outputs */
-               for (i = 0; i < ARRAY_SIZE(outputs); i++) {
-                       ret = em28xx_write_ac97(dev, outputs[i].reg, 0x8000);
-                       if (ret < 0)
-                               em28xx_warn("couldn't setup AC97 register %d\n",
-                                    outputs[i].reg);
-               }
-       }
-
-       xclk = dev->board.xclk & 0x7f;
-       if (!dev->mute)
-               xclk |= EM28XX_XCLK_AUDIO_UNMUTE;
-
-       ret = em28xx_write_reg(dev, EM28XX_R0F_XCLK, xclk);
-       if (ret < 0)
-               return ret;
-       msleep(10);
-
-       /* Selects the proper audio input */
-       ret = em28xx_set_audio_source(dev);
-
-       /* Sets volume */
-       if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
-               int vol;
-
-               em28xx_write_ac97(dev, AC97_POWERDOWN, 0x4200);
-               em28xx_write_ac97(dev, AC97_EXTENDED_STATUS, 0x0031);
-               em28xx_write_ac97(dev, AC97_PCM_LR_ADC_RATE, 0xbb80);
-
-               /* LSB: left channel - both channels with the same level */
-               vol = (0x1f - dev->volume) | ((0x1f - dev->volume) << 8);
-
-               /* Mute device, if needed */
-               if (dev->mute)
-                       vol |= 0x8000;
-
-               /* Sets volume */
-               for (i = 0; i < ARRAY_SIZE(outputs); i++) {
-                       if (dev->ctl_aoutput & outputs[i].mux)
-                               ret = em28xx_write_ac97(dev, outputs[i].reg,
-                                                       vol);
-                       if (ret < 0)
-                               em28xx_warn("couldn't setup AC97 register %d\n",
-                                    outputs[i].reg);
-               }
-
-               if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) {
-                       int sel = ac97_return_record_select(dev->ctl_aoutput);
-
-                       /* Use the same input for both left and right
-                          channels */
-                       sel |= (sel << 8);
-
-                       em28xx_write_ac97(dev, AC97_REC_SEL, sel);
-               }
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(em28xx_audio_analog_set);
-
-int em28xx_audio_setup(struct em28xx *dev)
-{
-       int vid1, vid2, feat, cfg;
-       u32 vid;
-
-       if (dev->chip_id == CHIP_ID_EM2870 || dev->chip_id == CHIP_ID_EM2874
-               || dev->chip_id == CHIP_ID_EM28174) {
-               /* Digital only device - don't load any alsa module */
-               dev->audio_mode.has_audio = false;
-               dev->has_audio_class = false;
-               dev->has_alsa_audio = false;
-               return 0;
-       }
-
-       dev->audio_mode.has_audio = true;
-
-       /* See how this device is configured */
-       cfg = em28xx_read_reg(dev, EM28XX_R00_CHIPCFG);
-       em28xx_info("Config register raw data: 0x%02x\n", cfg);
-       if (cfg < 0) {
-               /* Register read error?  */
-               cfg = EM28XX_CHIPCFG_AC97; /* Be conservative */
-       } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) == 0x00) {
-               /* The device doesn't have vendor audio at all */
-               dev->has_alsa_audio = false;
-               dev->audio_mode.has_audio = false;
-               return 0;
-       } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
-                  EM28XX_CHIPCFG_I2S_3_SAMPRATES) {
-               em28xx_info("I2S Audio (3 sample rates)\n");
-               dev->audio_mode.i2s_3rates = 1;
-       } else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
-                  EM28XX_CHIPCFG_I2S_5_SAMPRATES) {
-               em28xx_info("I2S Audio (5 sample rates)\n");
-               dev->audio_mode.i2s_5rates = 1;
-       }
-
-       if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) != EM28XX_CHIPCFG_AC97) {
-               /* Skip the code that does AC97 vendor detection */
-               dev->audio_mode.ac97 = EM28XX_NO_AC97;
-               goto init_audio;
-       }
-
-       dev->audio_mode.ac97 = EM28XX_AC97_OTHER;
-
-       vid1 = em28xx_read_ac97(dev, AC97_VENDOR_ID1);
-       if (vid1 < 0) {
-               /*
-                * Device likely doesn't support AC97
-                * Note: (some) em2800 devices without eeprom reports 0x91 on
-                *       CHIPCFG register, even not having an AC97 chip
-                */
-               em28xx_warn("AC97 chip type couldn't be determined\n");
-               dev->audio_mode.ac97 = EM28XX_NO_AC97;
-               dev->has_alsa_audio = false;
-               dev->audio_mode.has_audio = false;
-               goto init_audio;
-       }
-
-       vid2 = em28xx_read_ac97(dev, AC97_VENDOR_ID2);
-       if (vid2 < 0)
-               goto init_audio;
-
-       vid = vid1 << 16 | vid2;
-
-       dev->audio_mode.ac97_vendor_id = vid;
-       em28xx_warn("AC97 vendor ID = 0x%08x\n", vid);
-
-       feat = em28xx_read_ac97(dev, AC97_RESET);
-       if (feat < 0)
-               goto init_audio;
-
-       dev->audio_mode.ac97_feat = feat;
-       em28xx_warn("AC97 features = 0x%04x\n", feat);
-
-       /* Try to identify what audio processor we have */
-       if (((vid == 0xffffffff) || (vid == 0x83847650)) && (feat == 0x6a90))
-               dev->audio_mode.ac97 = EM28XX_AC97_EM202;
-       else if ((vid >> 8) == 0x838476)
-               dev->audio_mode.ac97 = EM28XX_AC97_SIGMATEL;
-
-init_audio:
-       /* Reports detected AC97 processor */
-       switch (dev->audio_mode.ac97) {
-       case EM28XX_NO_AC97:
-               em28xx_info("No AC97 audio processor\n");
-               break;
-       case EM28XX_AC97_EM202:
-               em28xx_info("Empia 202 AC97 audio processor detected\n");
-               break;
-       case EM28XX_AC97_SIGMATEL:
-               em28xx_info("Sigmatel audio processor detected(stac 97%02x)\n",
-                           dev->audio_mode.ac97_vendor_id & 0xff);
-               break;
-       case EM28XX_AC97_OTHER:
-               em28xx_warn("Unknown AC97 audio processor detected!\n");
-               break;
-       default:
-               break;
-       }
-
-       return em28xx_audio_analog_set(dev);
-}
-EXPORT_SYMBOL_GPL(em28xx_audio_setup);
-
-int em28xx_colorlevels_set_default(struct em28xx *dev)
-{
-       em28xx_write_reg(dev, EM28XX_R20_YGAIN, 0x10);  /* contrast */
-       em28xx_write_reg(dev, EM28XX_R21_YOFFSET, 0x00);        /* brightness */
-       em28xx_write_reg(dev, EM28XX_R22_UVGAIN, 0x10); /* saturation */
-       em28xx_write_reg(dev, EM28XX_R23_UOFFSET, 0x00);
-       em28xx_write_reg(dev, EM28XX_R24_VOFFSET, 0x00);
-       em28xx_write_reg(dev, EM28XX_R25_SHARPNESS, 0x00);
-
-       em28xx_write_reg(dev, EM28XX_R14_GAMMA, 0x20);
-       em28xx_write_reg(dev, EM28XX_R15_RGAIN, 0x20);
-       em28xx_write_reg(dev, EM28XX_R16_GGAIN, 0x20);
-       em28xx_write_reg(dev, EM28XX_R17_BGAIN, 0x20);
-       em28xx_write_reg(dev, EM28XX_R18_ROFFSET, 0x00);
-       em28xx_write_reg(dev, EM28XX_R19_GOFFSET, 0x00);
-       return em28xx_write_reg(dev, EM28XX_R1A_BOFFSET, 0x00);
-}
-
-int em28xx_capture_start(struct em28xx *dev, int start)
-{
-       int rc;
-
-       if (dev->chip_id == CHIP_ID_EM2874 ||
-           dev->chip_id == CHIP_ID_EM2884 ||
-           dev->chip_id == CHIP_ID_EM28174) {
-               /* The Transport Stream Enable Register moved in em2874 */
-               if (!start) {
-                       rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE,
-                                                  0x00,
-                                                  EM2874_TS1_CAPTURE_ENABLE);
-                       return rc;
-               }
-
-               /* Enable Transport Stream */
-               rc = em28xx_write_reg_bits(dev, EM2874_R5F_TS_ENABLE,
-                                          EM2874_TS1_CAPTURE_ENABLE,
-                                          EM2874_TS1_CAPTURE_ENABLE);
-               return rc;
-       }
-
-
-       /* FIXME: which is the best order? */
-       /* video registers are sampled by VREF */
-       rc = em28xx_write_reg_bits(dev, EM28XX_R0C_USBSUSP,
-                                  start ? 0x10 : 0x00, 0x10);
-       if (rc < 0)
-               return rc;
-
-       if (!start) {
-               /* disable video capture */
-               rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x27);
-               return rc;
-       }
-
-       if (dev->board.is_webcam)
-               rc = em28xx_write_reg(dev, 0x13, 0x0c);
-
-       /* enable video capture */
-       rc = em28xx_write_reg(dev, 0x48, 0x00);
-
-       if (dev->mode == EM28XX_ANALOG_MODE)
-               rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67);
-       else
-               rc = em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37);
-
-       msleep(6);
-
-       return rc;
-}
-
-int em28xx_vbi_supported(struct em28xx *dev)
-{
-       /* Modprobe option to manually disable */
-       if (disable_vbi == 1)
-               return 0;
-
-       if (dev->chip_id == CHIP_ID_EM2860 ||
-           dev->chip_id == CHIP_ID_EM2883)
-               return 1;
-
-       /* Version of em28xx that does not support VBI */
-       return 0;
-}
-
-int em28xx_set_outfmt(struct em28xx *dev)
-{
-       int ret;
-       u8 vinctrl;
-
-       ret = em28xx_write_reg_bits(dev, EM28XX_R27_OUTFMT,
-                               dev->format->reg | 0x20, 0xff);
-       if (ret < 0)
-                       return ret;
-
-       ret = em28xx_write_reg(dev, EM28XX_R10_VINMODE, dev->vinmode);
-       if (ret < 0)
-               return ret;
-
-       vinctrl = dev->vinctl;
-       if (em28xx_vbi_supported(dev) == 1) {
-               vinctrl |= EM28XX_VINCTRL_VBI_RAW;
-               em28xx_write_reg(dev, EM28XX_R34_VBI_START_H, 0x00);
-               em28xx_write_reg(dev, EM28XX_R36_VBI_WIDTH, dev->vbi_width/4);
-               em28xx_write_reg(dev, EM28XX_R37_VBI_HEIGHT, dev->vbi_height);
-               if (dev->norm & V4L2_STD_525_60) {
-                       /* NTSC */
-                       em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x09);
-               } else if (dev->norm & V4L2_STD_625_50) {
-                       /* PAL */
-                       em28xx_write_reg(dev, EM28XX_R35_VBI_START_V, 0x07);
-               }
-       }
-
-       return em28xx_write_reg(dev, EM28XX_R11_VINCTRL, vinctrl);
-}
-
-static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
-                                 u8 ymin, u8 ymax)
-{
-       em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n",
-                       xmin, ymin, xmax, ymax);
-
-       em28xx_write_regs(dev, EM28XX_R28_XMIN, &xmin, 1);
-       em28xx_write_regs(dev, EM28XX_R29_XMAX, &xmax, 1);
-       em28xx_write_regs(dev, EM28XX_R2A_YMIN, &ymin, 1);
-       return em28xx_write_regs(dev, EM28XX_R2B_YMAX, &ymax, 1);
-}
-
-static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
-                                  u16 width, u16 height)
-{
-       u8 cwidth = width;
-       u8 cheight = height;
-       u8 overflow = (height >> 7 & 0x02) | (width >> 8 & 0x01);
-
-       em28xx_coredbg("em28xx Area Set: (%d,%d)\n",
-                       (width | (overflow & 2) << 7),
-                       (height | (overflow & 1) << 8));
-
-       em28xx_write_regs(dev, EM28XX_R1C_HSTART, &hstart, 1);
-       em28xx_write_regs(dev, EM28XX_R1D_VSTART, &vstart, 1);
-       em28xx_write_regs(dev, EM28XX_R1E_CWIDTH, &cwidth, 1);
-       em28xx_write_regs(dev, EM28XX_R1F_CHEIGHT, &cheight, 1);
-       return em28xx_write_regs(dev, EM28XX_R1B_OFLOW, &overflow, 1);
-}
-
-static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
-{
-       u8 mode;
-       /* the em2800 scaler only supports scaling down to 50% */
-
-       if (dev->board.is_em2800) {
-               mode = (v ? 0x20 : 0x00) | (h ? 0x10 : 0x00);
-       } else {
-               u8 buf[2];
-
-               buf[0] = h;
-               buf[1] = h >> 8;
-               em28xx_write_regs(dev, EM28XX_R30_HSCALELOW, (char *)buf, 2);
-
-               buf[0] = v;
-               buf[1] = v >> 8;
-               em28xx_write_regs(dev, EM28XX_R32_VSCALELOW, (char *)buf, 2);
-               /* it seems that both H and V scalers must be active
-                  to work correctly */
-               mode = (h || v) ? 0x30 : 0x00;
-       }
-       return em28xx_write_reg_bits(dev, EM28XX_R26_COMPR, mode, 0x30);
-}
-
-/* FIXME: this only function read values from dev */
-int em28xx_resolution_set(struct em28xx *dev)
-{
-       int width, height;
-       width = norm_maxw(dev);
-       height = norm_maxh(dev);
-
-       /* Properly setup VBI */
-       dev->vbi_width = 720;
-       if (dev->norm & V4L2_STD_525_60)
-               dev->vbi_height = 12;
-       else
-               dev->vbi_height = 18;
-
-       em28xx_set_outfmt(dev);
-
-       em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
-
-       /* If we don't set the start position to 2 in VBI mode, we end up
-          with line 20/21 being YUYV encoded instead of being in 8-bit
-          greyscale.  The core of the issue is that line 21 (and line 23 for
-          PAL WSS) are inside of active video region, and as a result they
-          get the pixelformatting associated with that area.  So by cropping
-          it out, we end up with the same format as the rest of the VBI
-          region */
-       if (em28xx_vbi_supported(dev) == 1)
-               em28xx_capture_area_set(dev, 0, 2, width >> 2, height >> 2);
-       else
-               em28xx_capture_area_set(dev, 0, 0, width >> 2, height >> 2);
-
-       return em28xx_scaler_set(dev, dev->hscale, dev->vscale);
-}
-
-int em28xx_set_alternate(struct em28xx *dev)
-{
-       int errCode, prev_alt = dev->alt;
-       int i;
-       unsigned int min_pkt_size = dev->width * 2 + 4;
-
-       /*
-        * alt = 0 is used only for control messages, so, only values
-        * greater than 0 can be used for streaming.
-        */
-       if (alt && alt < dev->num_alt) {
-               em28xx_coredbg("alternate forced to %d\n", dev->alt);
-               dev->alt = alt;
-               goto set_alt;
-       }
-
-       /* When image size is bigger than a certain value,
-          the frame size should be increased, otherwise, only
-          green screen will be received.
-        */
-       if (dev->width * 2 * dev->height > 720 * 240 * 2)
-               min_pkt_size *= 2;
-
-       for (i = 0; i < dev->num_alt; i++) {
-               /* stop when the selected alt setting offers enough bandwidth */
-               if (dev->alt_max_pkt_size[i] >= min_pkt_size) {
-                       dev->alt = i;
-                       break;
-               /* otherwise make sure that we end up with the maximum bandwidth
-                  because the min_pkt_size equation might be wrong...
-               */
-               } else if (dev->alt_max_pkt_size[i] >
-                          dev->alt_max_pkt_size[dev->alt])
-                       dev->alt = i;
-       }
-
-set_alt:
-       if (dev->alt != prev_alt) {
-               em28xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
-                               min_pkt_size, dev->alt);
-               dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
-               em28xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
-                              dev->alt, dev->max_pkt_size);
-               errCode = usb_set_interface(dev->udev, 0, dev->alt);
-               if (errCode < 0) {
-                       em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
-                                       dev->alt, errCode);
-                       return errCode;
-               }
-       }
-       return 0;
-}
-
-int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio)
-{
-       int rc = 0;
-
-       if (!gpio)
-               return rc;
-
-       if (dev->mode != EM28XX_SUSPEND) {
-               em28xx_write_reg(dev, 0x48, 0x00);
-               if (dev->mode == EM28XX_ANALOG_MODE)
-                       em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x67);
-               else
-                       em28xx_write_reg(dev, EM28XX_R12_VINENABLE, 0x37);
-               msleep(6);
-       }
-
-       /* Send GPIO reset sequences specified at board entry */
-       while (gpio->sleep >= 0) {
-               if (gpio->reg >= 0) {
-                       rc = em28xx_write_reg_bits(dev,
-                                                  gpio->reg,
-                                                  gpio->val,
-                                                  gpio->mask);
-                       if (rc < 0)
-                               return rc;
-               }
-               if (gpio->sleep > 0)
-                       msleep(gpio->sleep);
-
-               gpio++;
-       }
-       return rc;
-}
-EXPORT_SYMBOL_GPL(em28xx_gpio_set);
-
-int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode)
-{
-       if (dev->mode == set_mode)
-               return 0;
-
-       if (set_mode == EM28XX_SUSPEND) {
-               dev->mode = set_mode;
-
-               /* FIXME: add suspend support for ac97 */
-
-               return em28xx_gpio_set(dev, dev->board.suspend_gpio);
-       }
-
-       dev->mode = set_mode;
-
-       if (dev->mode == EM28XX_DIGITAL_MODE)
-               return em28xx_gpio_set(dev, dev->board.dvb_gpio);
-       else
-               return em28xx_gpio_set(dev, INPUT(dev->ctl_input)->gpio);
-}
-EXPORT_SYMBOL_GPL(em28xx_set_mode);
-
-/* ------------------------------------------------------------------
-       URB control
-   ------------------------------------------------------------------*/
-
-/*
- * IRQ callback, called by URB callback
- */
-static void em28xx_irq_callback(struct urb *urb)
-{
-       struct em28xx *dev = urb->context;
-       int i;
-
-       switch (urb->status) {
-       case 0:             /* success */
-       case -ETIMEDOUT:    /* NAK */
-               break;
-       case -ECONNRESET:   /* kill */
-       case -ENOENT:
-       case -ESHUTDOWN:
-               return;
-       default:            /* error */
-               em28xx_isocdbg("urb completition error %d.\n", urb->status);
-               break;
-       }
-
-       /* Copy data from URB */
-       spin_lock(&dev->slock);
-       dev->isoc_ctl.isoc_copy(dev, urb);
-       spin_unlock(&dev->slock);
-
-       /* Reset urb buffers */
-       for (i = 0; i < urb->number_of_packets; i++) {
-               urb->iso_frame_desc[i].status = 0;
-               urb->iso_frame_desc[i].actual_length = 0;
-       }
-       urb->status = 0;
-
-       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (urb->status) {
-               em28xx_isocdbg("urb resubmit failed (error=%i)\n",
-                              urb->status);
-       }
-}
-
-/*
- * Stop and Deallocate URBs
- */
-void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode)
-{
-       struct urb *urb;
-       struct em28xx_usb_isoc_bufs *isoc_bufs;
-       int i;
-
-       em28xx_isocdbg("em28xx: called em28xx_uninit_isoc in mode %d\n", mode);
-
-       if (mode == EM28XX_DIGITAL_MODE)
-               isoc_bufs = &dev->isoc_ctl.digital_bufs;
-       else
-               isoc_bufs = &dev->isoc_ctl.analog_bufs;
-
-       for (i = 0; i < isoc_bufs->num_bufs; i++) {
-               urb = isoc_bufs->urb[i];
-               if (urb) {
-                       if (!irqs_disabled())
-                               usb_kill_urb(urb);
-                       else
-                               usb_unlink_urb(urb);
-
-                       if (isoc_bufs->transfer_buffer[i]) {
-                               usb_free_coherent(dev->udev,
-                                       urb->transfer_buffer_length,
-                                       isoc_bufs->transfer_buffer[i],
-                                       urb->transfer_dma);
-                       }
-                       usb_free_urb(urb);
-                       isoc_bufs->urb[i] = NULL;
-               }
-               isoc_bufs->transfer_buffer[i] = NULL;
-       }
-
-       kfree(isoc_bufs->urb);
-       kfree(isoc_bufs->transfer_buffer);
-
-       isoc_bufs->urb = NULL;
-       isoc_bufs->transfer_buffer = NULL;
-       isoc_bufs->num_bufs = 0;
-
-       em28xx_capture_start(dev, 0);
-}
-EXPORT_SYMBOL_GPL(em28xx_uninit_isoc);
-
-/*
- * Stop URBs
- */
-void em28xx_stop_urbs(struct em28xx *dev)
-{
-       int i;
-       struct urb *urb;
-       struct em28xx_usb_isoc_bufs *isoc_bufs = &dev->isoc_ctl.digital_bufs;
-
-       em28xx_isocdbg("em28xx: called em28xx_stop_urbs\n");
-
-       for (i = 0; i < isoc_bufs->num_bufs; i++) {
-               urb = isoc_bufs->urb[i];
-               if (urb) {
-                       if (!irqs_disabled())
-                               usb_kill_urb(urb);
-                       else
-                               usb_unlink_urb(urb);
-               }
-       }
-
-       em28xx_capture_start(dev, 0);
-}
-EXPORT_SYMBOL_GPL(em28xx_stop_urbs);
-
-/*
- * Allocate URBs
- */
-int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode,
-                     int max_packets, int num_bufs, int max_pkt_size)
-{
-       struct em28xx_usb_isoc_bufs *isoc_bufs;
-       int i;
-       int sb_size, pipe;
-       struct urb *urb;
-       int j, k;
-
-       em28xx_isocdbg("em28xx: called em28xx_alloc_isoc in mode %d\n", mode);
-
-       if (mode == EM28XX_DIGITAL_MODE)
-               isoc_bufs = &dev->isoc_ctl.digital_bufs;
-       else
-               isoc_bufs = &dev->isoc_ctl.analog_bufs;
-
-       /* De-allocates all pending stuff */
-       em28xx_uninit_isoc(dev, mode);
-
-       isoc_bufs->num_bufs = num_bufs;
-
-       isoc_bufs->urb = kzalloc(sizeof(void *)*num_bufs,  GFP_KERNEL);
-       if (!isoc_bufs->urb) {
-               em28xx_errdev("cannot alloc memory for usb buffers\n");
-               return -ENOMEM;
-       }
-
-       isoc_bufs->transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
-                                            GFP_KERNEL);
-       if (!isoc_bufs->transfer_buffer) {
-               em28xx_errdev("cannot allocate memory for usb transfer\n");
-               kfree(isoc_bufs->urb);
-               return -ENOMEM;
-       }
-
-       isoc_bufs->max_pkt_size = max_pkt_size;
-       isoc_bufs->num_packets = max_packets;
-       dev->isoc_ctl.vid_buf = NULL;
-       dev->isoc_ctl.vbi_buf = NULL;
-
-       sb_size = isoc_bufs->num_packets * isoc_bufs->max_pkt_size;
-
-       /* allocate urbs and transfer buffers */
-       for (i = 0; i < isoc_bufs->num_bufs; i++) {
-               urb = usb_alloc_urb(isoc_bufs->num_packets, GFP_KERNEL);
-               if (!urb) {
-                       em28xx_err("cannot alloc isoc_ctl.urb %i\n", i);
-                       em28xx_uninit_isoc(dev, mode);
-                       return -ENOMEM;
-               }
-               isoc_bufs->urb[i] = urb;
-
-               isoc_bufs->transfer_buffer[i] = usb_alloc_coherent(dev->udev,
-                       sb_size, GFP_KERNEL, &urb->transfer_dma);
-               if (!isoc_bufs->transfer_buffer[i]) {
-                       em28xx_err("unable to allocate %i bytes for transfer"
-                                       " buffer %i%s\n",
-                                       sb_size, i,
-                                       in_interrupt() ? " while in int" : "");
-                       em28xx_uninit_isoc(dev, mode);
-                       return -ENOMEM;
-               }
-               memset(isoc_bufs->transfer_buffer[i], 0, sb_size);
-
-               /* FIXME: this is a hack - should be
-                       'desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK'
-                       should also be using 'desc.bInterval'
-                */
-               pipe = usb_rcvisocpipe(dev->udev,
-                                      mode == EM28XX_ANALOG_MODE ?
-                                      EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL);
-
-               usb_fill_int_urb(urb, dev->udev, pipe,
-                                isoc_bufs->transfer_buffer[i], sb_size,
-                                em28xx_irq_callback, dev, 1);
-
-               urb->number_of_packets = isoc_bufs->num_packets;
-               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-
-               k = 0;
-               for (j = 0; j < isoc_bufs->num_packets; j++) {
-                       urb->iso_frame_desc[j].offset = k;
-                       urb->iso_frame_desc[j].length =
-                                               isoc_bufs->max_pkt_size;
-                       k += isoc_bufs->max_pkt_size;
-               }
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(em28xx_alloc_isoc);
-
-/*
- * Allocate URBs and start IRQ
- */
-int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode,
-                    int max_packets, int num_bufs, int max_pkt_size,
-                    int (*isoc_copy) (struct em28xx *dev, struct urb *urb))
-{
-       struct em28xx_dmaqueue *dma_q = &dev->vidq;
-       struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
-       struct em28xx_usb_isoc_bufs *isoc_bufs;
-       int i;
-       int rc;
-       int alloc;
-
-       em28xx_isocdbg("em28xx: called em28xx_init_isoc in mode %d\n", mode);
-
-       dev->isoc_ctl.isoc_copy = isoc_copy;
-
-       if (mode == EM28XX_DIGITAL_MODE) {
-               isoc_bufs = &dev->isoc_ctl.digital_bufs;
-               /* no need to free/alloc isoc buffers in digital mode */
-               alloc = 0;
-       } else {
-               isoc_bufs = &dev->isoc_ctl.analog_bufs;
-               alloc = 1;
-       }
-
-       if (alloc) {
-               rc = em28xx_alloc_isoc(dev, mode, max_packets,
-                                      num_bufs, max_pkt_size);
-               if (rc)
-                       return rc;
-       }
-
-       init_waitqueue_head(&dma_q->wq);
-       init_waitqueue_head(&vbi_dma_q->wq);
-
-       em28xx_capture_start(dev, 1);
-
-       /* submit urbs and enables IRQ */
-       for (i = 0; i < isoc_bufs->num_bufs; i++) {
-               rc = usb_submit_urb(isoc_bufs->urb[i], GFP_ATOMIC);
-               if (rc) {
-                       em28xx_err("submit of urb %i failed (error=%i)\n", i,
-                                  rc);
-                       em28xx_uninit_isoc(dev, mode);
-                       return rc;
-               }
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(em28xx_init_isoc);
-
-/*
- * em28xx_wake_i2c()
- * configure i2c attached devices
- */
-void em28xx_wake_i2c(struct em28xx *dev)
-{
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core,  reset, 0);
-       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
-                       INPUT(dev->ctl_input)->vmux, 0, 0);
-       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
-}
-
-/*
- * Device control list
- */
-
-static LIST_HEAD(em28xx_devlist);
-static DEFINE_MUTEX(em28xx_devlist_mutex);
-
-/*
- * Extension interface
- */
-
-static LIST_HEAD(em28xx_extension_devlist);
-
-int em28xx_register_extension(struct em28xx_ops *ops)
-{
-       struct em28xx *dev = NULL;
-
-       mutex_lock(&em28xx_devlist_mutex);
-       list_add_tail(&ops->next, &em28xx_extension_devlist);
-       list_for_each_entry(dev, &em28xx_devlist, devlist) {
-               ops->init(dev);
-       }
-       mutex_unlock(&em28xx_devlist_mutex);
-       printk(KERN_INFO "Em28xx: Initialized (%s) extension\n", ops->name);
-       return 0;
-}
-EXPORT_SYMBOL(em28xx_register_extension);
-
-void em28xx_unregister_extension(struct em28xx_ops *ops)
-{
-       struct em28xx *dev = NULL;
-
-       mutex_lock(&em28xx_devlist_mutex);
-       list_for_each_entry(dev, &em28xx_devlist, devlist) {
-               ops->fini(dev);
-       }
-       list_del(&ops->next);
-       mutex_unlock(&em28xx_devlist_mutex);
-       printk(KERN_INFO "Em28xx: Removed (%s) extension\n", ops->name);
-}
-EXPORT_SYMBOL(em28xx_unregister_extension);
-
-void em28xx_init_extension(struct em28xx *dev)
-{
-       const struct em28xx_ops *ops = NULL;
-
-       mutex_lock(&em28xx_devlist_mutex);
-       list_add_tail(&dev->devlist, &em28xx_devlist);
-       list_for_each_entry(ops, &em28xx_extension_devlist, next) {
-               if (ops->init)
-                       ops->init(dev);
-       }
-       mutex_unlock(&em28xx_devlist_mutex);
-}
-
-void em28xx_close_extension(struct em28xx *dev)
-{
-       const struct em28xx_ops *ops = NULL;
-
-       mutex_lock(&em28xx_devlist_mutex);
-       list_for_each_entry(ops, &em28xx_extension_devlist, next) {
-               if (ops->fini)
-                       ops->fini(dev);
-       }
-       list_del(&dev->devlist);
-       mutex_unlock(&em28xx_devlist_mutex);
-}
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
deleted file mode 100644 (file)
index a16531f..0000000
+++ /dev/null
@@ -1,1197 +0,0 @@
-/*
- DVB device driver for em28xx
-
- (c) 2008-2011 Mauro Carvalho Chehab <mchehab@infradead.org>
-
- (c) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
-       - Fixes for the driver to properly work with HVR-950
-       - Fixes for the driver to properly work with Pinnacle PCTV HD Pro Stick
-       - Fixes for the driver to properly work with AMD ATI TV Wonder HD 600
-
- (c) 2008 Aidan Thornton <makosoft@googlemail.com>
-
- Based on cx88-dvb, saa7134-dvb and videobuf-dvb originally written by:
-       (c) 2004, 2005 Chris Pascoe <c.pascoe@itee.uq.edu.au>
-       (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
-
- 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-
-#include "em28xx.h"
-#include <media/v4l2-common.h>
-#include <media/videobuf-vmalloc.h>
-#include <media/tuner.h>
-#include "tuner-simple.h"
-
-#include "lgdt330x.h"
-#include "lgdt3305.h"
-#include "zl10353.h"
-#include "s5h1409.h"
-#include "mt352.h"
-#include "mt352_priv.h" /* FIXME */
-#include "tda1002x.h"
-#include "tda18271.h"
-#include "s921.h"
-#include "drxd.h"
-#include "cxd2820r.h"
-#include "tda18271c2dd.h"
-#include "drxk.h"
-#include "tda10071.h"
-#include "a8293.h"
-#include "qt1010.h"
-
-MODULE_DESCRIPTION("driver for em28xx based DVB cards");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
-MODULE_LICENSE("GPL");
-
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define dprintk(level, fmt, arg...) do {                       \
-if (debug >= level)                                            \
-       printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \
-} while (0)
-
-struct em28xx_dvb {
-       struct dvb_frontend        *fe[2];
-
-       /* feed count management */
-       struct mutex               lock;
-       int                        nfeeds;
-
-       /* general boilerplate stuff */
-       struct dvb_adapter         adapter;
-       struct dvb_demux           demux;
-       struct dmxdev              dmxdev;
-       struct dmx_frontend        fe_hw;
-       struct dmx_frontend        fe_mem;
-       struct dvb_net             net;
-
-       /* Due to DRX-K - probably need changes */
-       int (*gate_ctrl)(struct dvb_frontend *, int);
-       struct semaphore      pll_mutex;
-       bool                    dont_attach_fe1;
-};
-
-
-static inline void print_err_status(struct em28xx *dev,
-                                    int packet, int status)
-{
-       char *errmsg = "Unknown";
-
-       switch (status) {
-       case -ENOENT:
-               errmsg = "unlinked synchronuously";
-               break;
-       case -ECONNRESET:
-               errmsg = "unlinked asynchronuously";
-               break;
-       case -ENOSR:
-               errmsg = "Buffer error (overrun)";
-               break;
-       case -EPIPE:
-               errmsg = "Stalled (device not responding)";
-               break;
-       case -EOVERFLOW:
-               errmsg = "Babble (bad cable?)";
-               break;
-       case -EPROTO:
-               errmsg = "Bit-stuff error (bad cable?)";
-               break;
-       case -EILSEQ:
-               errmsg = "CRC/Timeout (could be anything)";
-               break;
-       case -ETIME:
-               errmsg = "Device does not respond";
-               break;
-       }
-       if (packet < 0) {
-               dprintk(1, "URB status %d [%s].\n", status, errmsg);
-       } else {
-               dprintk(1, "URB packet %d, status %d [%s].\n",
-                       packet, status, errmsg);
-       }
-}
-
-static inline int em28xx_dvb_isoc_copy(struct em28xx *dev, struct urb *urb)
-{
-       int i;
-
-       if (!dev)
-               return 0;
-
-       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
-               return 0;
-
-       if (urb->status < 0) {
-               print_err_status(dev, -1, urb->status);
-               if (urb->status == -ENOENT)
-                       return 0;
-       }
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               int status = urb->iso_frame_desc[i].status;
-
-               if (status < 0) {
-                       print_err_status(dev, i, status);
-                       if (urb->iso_frame_desc[i].status != -EPROTO)
-                               continue;
-               }
-
-               dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer +
-                                urb->iso_frame_desc[i].offset,
-                                urb->iso_frame_desc[i].actual_length);
-       }
-
-       return 0;
-}
-
-static int em28xx_start_streaming(struct em28xx_dvb *dvb)
-{
-       int rc;
-       struct em28xx *dev = dvb->adapter.priv;
-       int max_dvb_packet_size;
-
-       usb_set_interface(dev->udev, 0, dev->dvb_alt);
-       rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
-       if (rc < 0)
-               return rc;
-
-       max_dvb_packet_size = dev->dvb_max_pkt_size;
-       if (max_dvb_packet_size < 0)
-               return max_dvb_packet_size;
-       dprintk(1, "Using %d buffers each with %d x %d bytes\n",
-               EM28XX_DVB_NUM_BUFS,
-               EM28XX_DVB_MAX_PACKETS,
-               max_dvb_packet_size);
-
-       return em28xx_init_isoc(dev, EM28XX_DIGITAL_MODE,
-                               EM28XX_DVB_MAX_PACKETS, EM28XX_DVB_NUM_BUFS,
-                               max_dvb_packet_size, em28xx_dvb_isoc_copy);
-}
-
-static int em28xx_stop_streaming(struct em28xx_dvb *dvb)
-{
-       struct em28xx *dev = dvb->adapter.priv;
-
-       em28xx_stop_urbs(dev);
-
-       em28xx_set_mode(dev, EM28XX_SUSPEND);
-
-       return 0;
-}
-
-static int em28xx_start_feed(struct dvb_demux_feed *feed)
-{
-       struct dvb_demux *demux  = feed->demux;
-       struct em28xx_dvb *dvb = demux->priv;
-       int rc, ret;
-
-       if (!demux->dmx.frontend)
-               return -EINVAL;
-
-       mutex_lock(&dvb->lock);
-       dvb->nfeeds++;
-       rc = dvb->nfeeds;
-
-       if (dvb->nfeeds == 1) {
-               ret = em28xx_start_streaming(dvb);
-               if (ret < 0)
-                       rc = ret;
-       }
-
-       mutex_unlock(&dvb->lock);
-       return rc;
-}
-
-static int em28xx_stop_feed(struct dvb_demux_feed *feed)
-{
-       struct dvb_demux *demux  = feed->demux;
-       struct em28xx_dvb *dvb = demux->priv;
-       int err = 0;
-
-       mutex_lock(&dvb->lock);
-       dvb->nfeeds--;
-
-       if (0 == dvb->nfeeds)
-               err = em28xx_stop_streaming(dvb);
-
-       mutex_unlock(&dvb->lock);
-       return err;
-}
-
-
-
-/* ------------------------------------------------------------------ */
-static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
-{
-       struct em28xx *dev = fe->dvb->priv;
-
-       if (acquire)
-               return em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
-       else
-               return em28xx_set_mode(dev, EM28XX_SUSPEND);
-}
-
-/* ------------------------------------------------------------------ */
-
-static struct lgdt330x_config em2880_lgdt3303_dev = {
-       .demod_address = 0x0e,
-       .demod_chip = LGDT3303,
-};
-
-static struct lgdt3305_config em2870_lgdt3304_dev = {
-       .i2c_addr           = 0x0e,
-       .demod_chip         = LGDT3304,
-       .spectral_inversion = 1,
-       .deny_i2c_rptr      = 1,
-       .mpeg_mode          = LGDT3305_MPEG_PARALLEL,
-       .tpclk_edge         = LGDT3305_TPCLK_FALLING_EDGE,
-       .tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
-       .vsb_if_khz         = 3250,
-       .qam_if_khz         = 4000,
-};
-
-static struct s921_config sharp_isdbt = {
-       .demod_address = 0x30 >> 1
-};
-
-static struct zl10353_config em28xx_zl10353_with_xc3028 = {
-       .demod_address = (0x1e >> 1),
-       .no_tuner = 1,
-       .parallel_ts = 1,
-       .if2 = 45600,
-};
-
-static struct s5h1409_config em28xx_s5h1409_with_xc3028 = {
-       .demod_address = 0x32 >> 1,
-       .output_mode   = S5H1409_PARALLEL_OUTPUT,
-       .gpio          = S5H1409_GPIO_OFF,
-       .inversion     = S5H1409_INVERSION_OFF,
-       .status_mode   = S5H1409_DEMODLOCKING,
-       .mpeg_timing   = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
-};
-
-static struct tda18271_std_map kworld_a340_std_map = {
-       .atsc_6   = { .if_freq = 3250, .agc_mode = 3, .std = 0,
-                     .if_lvl = 1, .rfagc_top = 0x37, },
-       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 1,
-                     .if_lvl = 1, .rfagc_top = 0x37, },
-};
-
-static struct tda18271_config kworld_a340_config = {
-       .std_map           = &kworld_a340_std_map,
-};
-
-static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {
-       .demod_address = (0x1e >> 1),
-       .no_tuner = 1,
-       .disable_i2c_gate_ctrl = 1,
-       .parallel_ts = 1,
-       .if2 = 45600,
-};
-
-static struct drxd_config em28xx_drxd = {
-       .demod_address = 0x70,
-       .demod_revision = 0xa2,
-       .pll_type = DRXD_PLL_NONE,
-       .clock = 12000,
-       .insert_rs_byte = 1,
-       .IF = 42800000,
-       .disable_i2c_gate_ctrl = 1,
-};
-
-static struct drxk_config terratec_h5_drxk = {
-       .adr = 0x29,
-       .single_master = 1,
-       .no_i2c_bridge = 1,
-       .microcode_name = "dvb-usb-terratec-h5-drxk.fw",
-       .qam_demod_parameter_count = 2,
-};
-
-static struct drxk_config hauppauge_930c_drxk = {
-       .adr = 0x29,
-       .single_master = 1,
-       .no_i2c_bridge = 1,
-       .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw",
-       .chunk_size = 56,
-       .qam_demod_parameter_count = 2,
-};
-
-struct drxk_config terratec_htc_stick_drxk = {
-       .adr = 0x29,
-       .single_master = 1,
-       .no_i2c_bridge = 1,
-       .microcode_name = "dvb-usb-terratec-htc-stick-drxk.fw",
-       .chunk_size = 54,
-       .qam_demod_parameter_count = 2,
-       /* Required for the antenna_gpio to disable LNA. */
-       .antenna_dvbt = true,
-       /* The windows driver uses the same. This will disable LNA. */
-       .antenna_gpio = 0x6,
-};
-
-static struct drxk_config maxmedia_ub425_tc_drxk = {
-       .adr = 0x29,
-       .single_master = 1,
-       .no_i2c_bridge = 1,
-};
-
-static struct drxk_config pctv_520e_drxk = {
-       .adr = 0x29,
-       .single_master = 1,
-       .microcode_name = "dvb-demod-drxk-pctv.fw",
-       .qam_demod_parameter_count = 2,
-       .chunk_size = 58,
-       .antenna_dvbt = true, /* disable LNA */
-       .antenna_gpio = (1 << 2), /* disable LNA */
-};
-
-static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
-{
-       struct em28xx_dvb *dvb = fe->sec_priv;
-       int status;
-
-       if (!dvb)
-               return -EINVAL;
-
-       if (enable) {
-               down(&dvb->pll_mutex);
-               status = dvb->gate_ctrl(fe, 1);
-       } else {
-               status = dvb->gate_ctrl(fe, 0);
-               up(&dvb->pll_mutex);
-       }
-       return status;
-}
-
-static void hauppauge_hvr930c_init(struct em28xx *dev)
-{
-       int i;
-
-       struct em28xx_reg_seq hauppauge_hvr930c_init[] = {
-               {EM2874_R80_GPIO,       0xff,   0xff,   0x65},
-               {EM2874_R80_GPIO,       0xfb,   0xff,   0x32},
-               {EM2874_R80_GPIO,       0xff,   0xff,   0xb8},
-               { -1,                   -1,     -1,     -1},
-       };
-       struct em28xx_reg_seq hauppauge_hvr930c_end[] = {
-               {EM2874_R80_GPIO,       0xef,   0xff,   0x01},
-               {EM2874_R80_GPIO,       0xaf,   0xff,   0x65},
-               {EM2874_R80_GPIO,       0xef,   0xff,   0x76},
-               {EM2874_R80_GPIO,       0xef,   0xff,   0x01},
-               {EM2874_R80_GPIO,       0xcf,   0xff,   0x0b},
-               {EM2874_R80_GPIO,       0xef,   0xff,   0x40},
-
-               {EM2874_R80_GPIO,       0xcf,   0xff,   0x65},
-               {EM2874_R80_GPIO,       0xef,   0xff,   0x65},
-               {EM2874_R80_GPIO,       0xcf,   0xff,   0x0b},
-               {EM2874_R80_GPIO,       0xef,   0xff,   0x65},
-
-               { -1,                   -1,     -1,     -1},
-       };
-
-       struct {
-               unsigned char r[4];
-               int len;
-       } regs[] = {
-               {{ 0x06, 0x02, 0x00, 0x31 }, 4},
-               {{ 0x01, 0x02 }, 2},
-               {{ 0x01, 0x02, 0x00, 0xc6 }, 4},
-               {{ 0x01, 0x00 }, 2},
-               {{ 0x01, 0x00, 0xff, 0xaf }, 4},
-               {{ 0x01, 0x00, 0x03, 0xa0 }, 4},
-               {{ 0x01, 0x00 }, 2},
-               {{ 0x01, 0x00, 0x73, 0xaf }, 4},
-               {{ 0x04, 0x00 }, 2},
-               {{ 0x00, 0x04 }, 2},
-               {{ 0x00, 0x04, 0x00, 0x0a }, 4},
-               {{ 0x04, 0x14 }, 2},
-               {{ 0x04, 0x14, 0x00, 0x00 }, 4},
-       };
-
-       em28xx_gpio_set(dev, hauppauge_hvr930c_init);
-       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
-       msleep(10);
-       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
-       msleep(10);
-
-       dev->i2c_client.addr = 0x82 >> 1;
-
-       for (i = 0; i < ARRAY_SIZE(regs); i++)
-               i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
-       em28xx_gpio_set(dev, hauppauge_hvr930c_end);
-
-       msleep(100);
-
-       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
-       msleep(30);
-
-       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
-       msleep(10);
-
-}
-
-static void terratec_h5_init(struct em28xx *dev)
-{
-       int i;
-       struct em28xx_reg_seq terratec_h5_init[] = {
-               {EM28XX_R08_GPIO,       0xff,   0xff,   10},
-               {EM2874_R80_GPIO,       0xf6,   0xff,   100},
-               {EM2874_R80_GPIO,       0xf2,   0xff,   50},
-               {EM2874_R80_GPIO,       0xf6,   0xff,   100},
-               { -1,                   -1,     -1,     -1},
-       };
-       struct em28xx_reg_seq terratec_h5_end[] = {
-               {EM2874_R80_GPIO,       0xe6,   0xff,   100},
-               {EM2874_R80_GPIO,       0xa6,   0xff,   50},
-               {EM2874_R80_GPIO,       0xe6,   0xff,   100},
-               { -1,                   -1,     -1,     -1},
-       };
-       struct {
-               unsigned char r[4];
-               int len;
-       } regs[] = {
-               {{ 0x06, 0x02, 0x00, 0x31 }, 4},
-               {{ 0x01, 0x02 }, 2},
-               {{ 0x01, 0x02, 0x00, 0xc6 }, 4},
-               {{ 0x01, 0x00 }, 2},
-               {{ 0x01, 0x00, 0xff, 0xaf }, 4},
-               {{ 0x01, 0x00, 0x03, 0xa0 }, 4},
-               {{ 0x01, 0x00 }, 2},
-               {{ 0x01, 0x00, 0x73, 0xaf }, 4},
-               {{ 0x04, 0x00 }, 2},
-               {{ 0x00, 0x04 }, 2},
-               {{ 0x00, 0x04, 0x00, 0x0a }, 4},
-               {{ 0x04, 0x14 }, 2},
-               {{ 0x04, 0x14, 0x00, 0x00 }, 4},
-       };
-
-       em28xx_gpio_set(dev, terratec_h5_init);
-       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
-       msleep(10);
-       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45);
-       msleep(10);
-
-       dev->i2c_client.addr = 0x82 >> 1;
-
-       for (i = 0; i < ARRAY_SIZE(regs); i++)
-               i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
-       em28xx_gpio_set(dev, terratec_h5_end);
-};
-
-static void terratec_htc_stick_init(struct em28xx *dev)
-{
-       int i;
-
-       /*
-        * GPIO configuration:
-        * 0xff: unknown (does not affect DVB-T).
-        * 0xf6: DRX-K (demodulator).
-        * 0xe6: unknown (does not affect DVB-T).
-        * 0xb6: unknown (does not affect DVB-T).
-        */
-       struct em28xx_reg_seq terratec_htc_stick_init[] = {
-               {EM28XX_R08_GPIO,       0xff,   0xff,   10},
-               {EM2874_R80_GPIO,       0xf6,   0xff,   100},
-               {EM2874_R80_GPIO,       0xe6,   0xff,   50},
-               {EM2874_R80_GPIO,       0xf6,   0xff,   100},
-               { -1,                   -1,     -1,     -1},
-       };
-       struct em28xx_reg_seq terratec_htc_stick_end[] = {
-               {EM2874_R80_GPIO,       0xb6,   0xff,   100},
-               {EM2874_R80_GPIO,       0xf6,   0xff,   50},
-               { -1,                   -1,     -1,     -1},
-       };
-
-       /* Init the analog decoder? */
-       struct {
-               unsigned char r[4];
-               int len;
-       } regs[] = {
-               {{ 0x06, 0x02, 0x00, 0x31 }, 4},
-               {{ 0x01, 0x02 }, 2},
-               {{ 0x01, 0x02, 0x00, 0xc6 }, 4},
-               {{ 0x01, 0x00 }, 2},
-               {{ 0x01, 0x00, 0xff, 0xaf }, 4},
-       };
-
-       em28xx_gpio_set(dev, terratec_htc_stick_init);
-
-       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40);
-       msleep(10);
-       em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44);
-       msleep(10);
-
-       dev->i2c_client.addr = 0x82 >> 1;
-
-       for (i = 0; i < ARRAY_SIZE(regs); i++)
-               i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
-
-       em28xx_gpio_set(dev, terratec_htc_stick_end);
-};
-
-static void pctv_520e_init(struct em28xx *dev)
-{
-       /*
-        * Init AVF4910B analog decoder. Looks like I2C traffic to
-        * digital demodulator and tuner are routed via AVF4910B.
-        */
-       int i;
-       struct {
-               unsigned char r[4];
-               int len;
-       } regs[] = {
-               {{ 0x06, 0x02, 0x00, 0x31 }, 4},
-               {{ 0x01, 0x02 }, 2},
-               {{ 0x01, 0x02, 0x00, 0xc6 }, 4},
-               {{ 0x01, 0x00 }, 2},
-               {{ 0x01, 0x00, 0xff, 0xaf }, 4},
-               {{ 0x01, 0x00, 0x03, 0xa0 }, 4},
-               {{ 0x01, 0x00 }, 2},
-               {{ 0x01, 0x00, 0x73, 0xaf }, 4},
-       };
-
-       dev->i2c_client.addr = 0x82 >> 1; /* 0x41 */
-
-       for (i = 0; i < ARRAY_SIZE(regs); i++)
-               i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
-};
-
-static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe)
-{
-       /* Values extracted from a USB trace of the Terratec Windows driver */
-       static u8 clock_config[]   = { CLOCK_CTL,  0x38, 0x2c };
-       static u8 reset[]          = { RESET,      0x80 };
-       static u8 adc_ctl_1_cfg[]  = { ADC_CTL_1,  0x40 };
-       static u8 agc_cfg[]        = { AGC_TARGET, 0x28, 0xa0 };
-       static u8 input_freq_cfg[] = { INPUT_FREQ_1, 0x31, 0xb8 };
-       static u8 rs_err_cfg[]     = { RS_ERR_PER_1, 0x00, 0x4d };
-       static u8 capt_range_cfg[] = { CAPT_RANGE, 0x32 };
-       static u8 trl_nom_cfg[]    = { TRL_NOMINAL_RATE_1, 0x64, 0x00 };
-       static u8 tps_given_cfg[]  = { TPS_GIVEN_1, 0x40, 0x80, 0x50 };
-       static u8 tuner_go[]       = { TUNER_GO, 0x01};
-
-       mt352_write(fe, clock_config,   sizeof(clock_config));
-       udelay(200);
-       mt352_write(fe, reset,          sizeof(reset));
-       mt352_write(fe, adc_ctl_1_cfg,  sizeof(adc_ctl_1_cfg));
-       mt352_write(fe, agc_cfg,        sizeof(agc_cfg));
-       mt352_write(fe, input_freq_cfg, sizeof(input_freq_cfg));
-       mt352_write(fe, rs_err_cfg,     sizeof(rs_err_cfg));
-       mt352_write(fe, capt_range_cfg, sizeof(capt_range_cfg));
-       mt352_write(fe, trl_nom_cfg,    sizeof(trl_nom_cfg));
-       mt352_write(fe, tps_given_cfg,  sizeof(tps_given_cfg));
-       mt352_write(fe, tuner_go,       sizeof(tuner_go));
-       return 0;
-}
-
-static struct mt352_config terratec_xs_mt352_cfg = {
-       .demod_address = (0x1e >> 1),
-       .no_tuner = 1,
-       .if2 = 45600,
-       .demod_init = em28xx_mt352_terratec_xs_init,
-};
-
-static struct tda10023_config em28xx_tda10023_config = {
-       .demod_address = 0x0c,
-       .invert = 1,
-};
-
-static struct cxd2820r_config em28xx_cxd2820r_config = {
-       .i2c_address = (0xd8 >> 1),
-       .ts_mode = CXD2820R_TS_SERIAL,
-
-       /* enable LNA for DVB-T, DVB-T2 and DVB-C */
-       .gpio_dvbt[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L,
-       .gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L,
-       .gpio_dvbc[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L,
-};
-
-static struct tda18271_config em28xx_cxd2820r_tda18271_config = {
-       .output_opt = TDA18271_OUTPUT_LT_OFF,
-       .gate = TDA18271_GATE_DIGITAL,
-};
-
-static const struct tda10071_config em28xx_tda10071_config = {
-       .i2c_address = 0x55, /* (0xaa >> 1) */
-       .i2c_wr_max = 64,
-       .ts_mode = TDA10071_TS_SERIAL,
-       .spec_inv = 0,
-       .xtal = 40444000, /* 40.444 MHz */
-       .pll_multiplier = 20,
-};
-
-static const struct a8293_config em28xx_a8293_config = {
-       .i2c_addr = 0x08, /* (0x10 >> 1) */
-};
-
-static struct zl10353_config em28xx_zl10353_no_i2c_gate_dev = {
-       .demod_address = (0x1e >> 1),
-       .disable_i2c_gate_ctrl = 1,
-       .no_tuner = 1,
-       .parallel_ts = 1,
-};
-static struct qt1010_config em28xx_qt1010_config = {
-       .i2c_address = 0x62
-
-};
-
-/* ------------------------------------------------------------------ */
-
-static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev)
-{
-       struct dvb_frontend *fe;
-       struct xc2028_config cfg;
-
-       memset(&cfg, 0, sizeof(cfg));
-       cfg.i2c_adap  = &dev->i2c_adap;
-       cfg.i2c_addr  = addr;
-
-       if (!dev->dvb->fe[0]) {
-               em28xx_errdev("/2: dvb frontend not attached. "
-                               "Can't attach xc3028\n");
-               return -EINVAL;
-       }
-
-       fe = dvb_attach(xc2028_attach, dev->dvb->fe[0], &cfg);
-       if (!fe) {
-               em28xx_errdev("/2: xc3028 attach failed\n");
-               dvb_frontend_detach(dev->dvb->fe[0]);
-               dev->dvb->fe[0] = NULL;
-               return -EINVAL;
-       }
-
-       em28xx_info("%s/2: xc3028 attached\n", dev->name);
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------ */
-
-static int em28xx_register_dvb(struct em28xx_dvb *dvb, struct module *module,
-                              struct em28xx *dev, struct device *device)
-{
-       int result;
-
-       mutex_init(&dvb->lock);
-
-       /* register adapter */
-       result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
-                                     adapter_nr);
-       if (result < 0) {
-               printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
-                      dev->name, result);
-               goto fail_adapter;
-       }
-
-       /* Ensure all frontends negotiate bus access */
-       dvb->fe[0]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
-       if (dvb->fe[1])
-               dvb->fe[1]->ops.ts_bus_ctrl = em28xx_dvb_bus_ctrl;
-
-       dvb->adapter.priv = dev;
-
-       /* register frontend */
-       result = dvb_register_frontend(&dvb->adapter, dvb->fe[0]);
-       if (result < 0) {
-               printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n",
-                      dev->name, result);
-               goto fail_frontend0;
-       }
-
-       /* register 2nd frontend */
-       if (dvb->fe[1]) {
-               result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]);
-               if (result < 0) {
-                       printk(KERN_WARNING "%s: 2nd dvb_register_frontend failed (errno = %d)\n",
-                               dev->name, result);
-                       goto fail_frontend1;
-               }
-       }
-
-       /* register demux stuff */
-       dvb->demux.dmx.capabilities =
-               DMX_TS_FILTERING | DMX_SECTION_FILTERING |
-               DMX_MEMORY_BASED_FILTERING;
-       dvb->demux.priv       = dvb;
-       dvb->demux.filternum  = 256;
-       dvb->demux.feednum    = 256;
-       dvb->demux.start_feed = em28xx_start_feed;
-       dvb->demux.stop_feed  = em28xx_stop_feed;
-
-       result = dvb_dmx_init(&dvb->demux);
-       if (result < 0) {
-               printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
-                      dev->name, result);
-               goto fail_dmx;
-       }
-
-       dvb->dmxdev.filternum    = 256;
-       dvb->dmxdev.demux        = &dvb->demux.dmx;
-       dvb->dmxdev.capabilities = 0;
-       result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
-       if (result < 0) {
-               printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
-                      dev->name, result);
-               goto fail_dmxdev;
-       }
-
-       dvb->fe_hw.source = DMX_FRONTEND_0;
-       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
-       if (result < 0) {
-               printk(KERN_WARNING "%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
-                      dev->name, result);
-               goto fail_fe_hw;
-       }
-
-       dvb->fe_mem.source = DMX_MEMORY_FE;
-       result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
-       if (result < 0) {
-               printk(KERN_WARNING "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
-                      dev->name, result);
-               goto fail_fe_mem;
-       }
-
-       result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
-       if (result < 0) {
-               printk(KERN_WARNING "%s: connect_frontend failed (errno = %d)\n",
-                      dev->name, result);
-               goto fail_fe_conn;
-       }
-
-       /* register network adapter */
-       dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
-       return 0;
-
-fail_fe_conn:
-       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
-fail_fe_mem:
-       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
-fail_fe_hw:
-       dvb_dmxdev_release(&dvb->dmxdev);
-fail_dmxdev:
-       dvb_dmx_release(&dvb->demux);
-fail_dmx:
-       if (dvb->fe[1])
-               dvb_unregister_frontend(dvb->fe[1]);
-       dvb_unregister_frontend(dvb->fe[0]);
-fail_frontend1:
-       if (dvb->fe[1])
-               dvb_frontend_detach(dvb->fe[1]);
-fail_frontend0:
-       dvb_frontend_detach(dvb->fe[0]);
-       dvb_unregister_adapter(&dvb->adapter);
-fail_adapter:
-       return result;
-}
-
-static void em28xx_unregister_dvb(struct em28xx_dvb *dvb)
-{
-       dvb_net_release(&dvb->net);
-       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_mem);
-       dvb->demux.dmx.remove_frontend(&dvb->demux.dmx, &dvb->fe_hw);
-       dvb_dmxdev_release(&dvb->dmxdev);
-       dvb_dmx_release(&dvb->demux);
-       if (dvb->fe[1])
-               dvb_unregister_frontend(dvb->fe[1]);
-       dvb_unregister_frontend(dvb->fe[0]);
-       if (dvb->fe[1] && !dvb->dont_attach_fe1)
-               dvb_frontend_detach(dvb->fe[1]);
-       dvb_frontend_detach(dvb->fe[0]);
-       dvb_unregister_adapter(&dvb->adapter);
-}
-
-static int em28xx_dvb_init(struct em28xx *dev)
-{
-       int result = 0, mfe_shared = 0;
-       struct em28xx_dvb *dvb;
-
-       if (!dev->board.has_dvb) {
-               /* This device does not support the extension */
-               printk(KERN_INFO "em28xx_dvb: This device does not support the extension\n");
-               return 0;
-       }
-
-       dvb = kzalloc(sizeof(struct em28xx_dvb), GFP_KERNEL);
-
-       if (dvb == NULL) {
-               em28xx_info("em28xx_dvb: memory allocation failed\n");
-               return -ENOMEM;
-       }
-       dev->dvb = dvb;
-       dvb->fe[0] = dvb->fe[1] = NULL;
-
-       mutex_lock(&dev->lock);
-       em28xx_set_mode(dev, EM28XX_DIGITAL_MODE);
-       /* init frontend */
-       switch (dev->model) {
-       case EM2874_BOARD_LEADERSHIP_ISDBT:
-               dvb->fe[0] = dvb_attach(s921_attach,
-                               &sharp_isdbt, &dev->i2c_adap);
-
-               if (!dvb->fe[0]) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-
-               break;
-       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850:
-       case EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950:
-       case EM2880_BOARD_PINNACLE_PCTV_HD_PRO:
-       case EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600:
-               dvb->fe[0] = dvb_attach(lgdt330x_attach,
-                                          &em2880_lgdt3303_dev,
-                                          &dev->i2c_adap);
-               if (em28xx_attach_xc3028(0x61, dev) < 0) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               break;
-       case EM2880_BOARD_KWORLD_DVB_310U:
-               dvb->fe[0] = dvb_attach(zl10353_attach,
-                                          &em28xx_zl10353_with_xc3028,
-                                          &dev->i2c_adap);
-               if (em28xx_attach_xc3028(0x61, dev) < 0) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               break;
-       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900:
-       case EM2882_BOARD_TERRATEC_HYBRID_XS:
-       case EM2880_BOARD_EMPIRE_DUAL_TV:
-               dvb->fe[0] = dvb_attach(zl10353_attach,
-                                          &em28xx_zl10353_xc3028_no_i2c_gate,
-                                          &dev->i2c_adap);
-               if (em28xx_attach_xc3028(0x61, dev) < 0) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               break;
-       case EM2880_BOARD_TERRATEC_HYBRID_XS:
-       case EM2880_BOARD_TERRATEC_HYBRID_XS_FR:
-       case EM2881_BOARD_PINNACLE_HYBRID_PRO:
-       case EM2882_BOARD_DIKOM_DK300:
-       case EM2882_BOARD_KWORLD_VS_DVBT:
-               dvb->fe[0] = dvb_attach(zl10353_attach,
-                                          &em28xx_zl10353_xc3028_no_i2c_gate,
-                                          &dev->i2c_adap);
-               if (dvb->fe[0] == NULL) {
-                       /* This board could have either a zl10353 or a mt352.
-                          If the chip id isn't for zl10353, try mt352 */
-                       dvb->fe[0] = dvb_attach(mt352_attach,
-                                                  &terratec_xs_mt352_cfg,
-                                                  &dev->i2c_adap);
-               }
-
-               if (em28xx_attach_xc3028(0x61, dev) < 0) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               break;
-       case EM2870_BOARD_KWORLD_355U:
-               dvb->fe[0] = dvb_attach(zl10353_attach,
-                                          &em28xx_zl10353_no_i2c_gate_dev,
-                                          &dev->i2c_adap);
-               if (dvb->fe[0] != NULL)
-                       dvb_attach(qt1010_attach, dvb->fe[0],
-                                  &dev->i2c_adap, &em28xx_qt1010_config);
-               break;
-       case EM2883_BOARD_KWORLD_HYBRID_330U:
-       case EM2882_BOARD_EVGA_INDTUBE:
-               dvb->fe[0] = dvb_attach(s5h1409_attach,
-                                          &em28xx_s5h1409_with_xc3028,
-                                          &dev->i2c_adap);
-               if (em28xx_attach_xc3028(0x61, dev) < 0) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               break;
-       case EM2882_BOARD_KWORLD_ATSC_315U:
-               dvb->fe[0] = dvb_attach(lgdt330x_attach,
-                                          &em2880_lgdt3303_dev,
-                                          &dev->i2c_adap);
-               if (dvb->fe[0] != NULL) {
-                       if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
-                               &dev->i2c_adap, 0x61, TUNER_THOMSON_DTT761X)) {
-                               result = -EINVAL;
-                               goto out_free;
-                       }
-               }
-               break;
-       case EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2:
-       case EM2882_BOARD_PINNACLE_HYBRID_PRO_330E:
-               dvb->fe[0] = dvb_attach(drxd_attach, &em28xx_drxd, NULL,
-                                          &dev->i2c_adap, &dev->udev->dev);
-               if (em28xx_attach_xc3028(0x61, dev) < 0) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               break;
-       case EM2870_BOARD_REDDO_DVB_C_USB_BOX:
-               /* Philips CU1216L NIM (Philips TDA10023 + Infineon TUA6034) */
-               dvb->fe[0] = dvb_attach(tda10023_attach,
-                       &em28xx_tda10023_config,
-                       &dev->i2c_adap, 0x48);
-               if (dvb->fe[0]) {
-                       if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
-                               &dev->i2c_adap, 0x60, TUNER_PHILIPS_CU1216L)) {
-                               result = -EINVAL;
-                               goto out_free;
-                       }
-               }
-               break;
-       case EM2870_BOARD_KWORLD_A340:
-               dvb->fe[0] = dvb_attach(lgdt3305_attach,
-                                          &em2870_lgdt3304_dev,
-                                          &dev->i2c_adap);
-               if (dvb->fe[0] != NULL)
-                       dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
-                                  &dev->i2c_adap, &kworld_a340_config);
-               break;
-       case EM28174_BOARD_PCTV_290E:
-               dvb->fe[0] = dvb_attach(cxd2820r_attach,
-                                       &em28xx_cxd2820r_config,
-                                       &dev->i2c_adap);
-               if (dvb->fe[0]) {
-                       /* FE 0 attach tuner */
-                       if (!dvb_attach(tda18271_attach,
-                                       dvb->fe[0],
-                                       0x60,
-                                       &dev->i2c_adap,
-                                       &em28xx_cxd2820r_tda18271_config)) {
-
-                               dvb_frontend_detach(dvb->fe[0]);
-                               result = -EINVAL;
-                               goto out_free;
-                       }
-               }
-               break;
-       case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C:
-       {
-               struct xc5000_config cfg;
-               hauppauge_hvr930c_init(dev);
-
-               dvb->fe[0] = dvb_attach(drxk_attach,
-                                       &hauppauge_930c_drxk, &dev->i2c_adap);
-               if (!dvb->fe[0]) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               /* FIXME: do we need a pll semaphore? */
-               dvb->fe[0]->sec_priv = dvb;
-               sema_init(&dvb->pll_mutex, 1);
-               dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
-               dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
-
-               /* Attach xc5000 */
-               memset(&cfg, 0, sizeof(cfg));
-               cfg.i2c_address  = 0x61;
-               cfg.if_khz = 4000;
-
-               if (dvb->fe[0]->ops.i2c_gate_ctrl)
-                       dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
-               if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap,
-                               &cfg)) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               if (dvb->fe[0]->ops.i2c_gate_ctrl)
-                       dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
-
-               break;
-       }
-       case EM2884_BOARD_TERRATEC_H5:
-               terratec_h5_init(dev);
-
-               dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap);
-               if (!dvb->fe[0]) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               /* FIXME: do we need a pll semaphore? */
-               dvb->fe[0]->sec_priv = dvb;
-               sema_init(&dvb->pll_mutex, 1);
-               dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl;
-               dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
-
-               /* Attach tda18271 to DVB-C frontend */
-               if (dvb->fe[0]->ops.i2c_gate_ctrl)
-                       dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1);
-               if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0], &dev->i2c_adap, 0x60)) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               if (dvb->fe[0]->ops.i2c_gate_ctrl)
-                       dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0);
-
-               break;
-       case EM28174_BOARD_PCTV_460E:
-               /* attach demod */
-               dvb->fe[0] = dvb_attach(tda10071_attach,
-                       &em28xx_tda10071_config, &dev->i2c_adap);
-
-               /* attach SEC */
-               if (dvb->fe[0])
-                       dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap,
-                               &em28xx_a8293_config);
-               break;
-       case EM2874_BOARD_MAXMEDIA_UB425_TC:
-               /* attach demodulator */
-               dvb->fe[0] = dvb_attach(drxk_attach, &maxmedia_ub425_tc_drxk,
-                               &dev->i2c_adap);
-
-               if (dvb->fe[0]) {
-                       /* disable I2C-gate */
-                       dvb->fe[0]->ops.i2c_gate_ctrl = NULL;
-
-                       /* attach tuner */
-                       if (!dvb_attach(tda18271c2dd_attach, dvb->fe[0],
-                                       &dev->i2c_adap, 0x60)) {
-                               dvb_frontend_detach(dvb->fe[0]);
-                               result = -EINVAL;
-                               goto out_free;
-                       }
-               }
-
-               /* TODO: we need drx-3913k firmware in order to support DVB-T */
-               em28xx_info("MaxMedia UB425-TC: only DVB-C supported by that " \
-                               "driver version\n");
-
-               break;
-       case EM2884_BOARD_PCTV_510E:
-       case EM2884_BOARD_PCTV_520E:
-               pctv_520e_init(dev);
-
-               /* attach demodulator */
-               dvb->fe[0] = dvb_attach(drxk_attach, &pctv_520e_drxk,
-                               &dev->i2c_adap);
-
-               if (dvb->fe[0]) {
-                       /* attach tuner */
-                       if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
-                                       &dev->i2c_adap,
-                                       &em28xx_cxd2820r_tda18271_config)) {
-                               dvb_frontend_detach(dvb->fe[0]);
-                               result = -EINVAL;
-                               goto out_free;
-                       }
-               }
-               break;
-       case EM2884_BOARD_CINERGY_HTC_STICK:
-               terratec_htc_stick_init(dev);
-
-               /* attach demodulator */
-               dvb->fe[0] = dvb_attach(drxk_attach, &terratec_htc_stick_drxk,
-                                       &dev->i2c_adap);
-               if (!dvb->fe[0]) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-
-               /* Attach the demodulator. */
-               if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
-                               &dev->i2c_adap,
-                               &em28xx_cxd2820r_tda18271_config)) {
-                       result = -EINVAL;
-                       goto out_free;
-               }
-               break;
-       default:
-               em28xx_errdev("/2: The frontend of your DVB/ATSC card"
-                               " isn't supported yet\n");
-               break;
-       }
-       if (NULL == dvb->fe[0]) {
-               em28xx_errdev("/2: frontend initialization failed\n");
-               result = -EINVAL;
-               goto out_free;
-       }
-       /* define general-purpose callback pointer */
-       dvb->fe[0]->callback = em28xx_tuner_callback;
-       if (dvb->fe[1])
-               dvb->fe[1]->callback = em28xx_tuner_callback;
-
-       /* register everything */
-       result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
-
-       if (result < 0)
-               goto out_free;
-
-       /* MFE lock */
-       dvb->adapter.mfe_shared = mfe_shared;
-
-       em28xx_info("Successfully loaded em28xx-dvb\n");
-ret:
-       em28xx_set_mode(dev, EM28XX_SUSPEND);
-       mutex_unlock(&dev->lock);
-       return result;
-
-out_free:
-       kfree(dvb);
-       dev->dvb = NULL;
-       goto ret;
-}
-
-static inline void prevent_sleep(struct dvb_frontend_ops *ops)
-{
-       ops->set_voltage = NULL;
-       ops->sleep = NULL;
-       ops->tuner_ops.sleep = NULL;
-}
-
-static int em28xx_dvb_fini(struct em28xx *dev)
-{
-       if (!dev->board.has_dvb) {
-               /* This device does not support the extension */
-               return 0;
-       }
-
-       if (dev->dvb) {
-               struct em28xx_dvb *dvb = dev->dvb;
-
-               if (dev->state & DEV_DISCONNECTED) {
-                       /* We cannot tell the device to sleep
-                        * once it has been unplugged. */
-                       if (dvb->fe[0])
-                               prevent_sleep(&dvb->fe[0]->ops);
-                       if (dvb->fe[1])
-                               prevent_sleep(&dvb->fe[1]->ops);
-               }
-
-               em28xx_unregister_dvb(dvb);
-               kfree(dvb);
-               dev->dvb = NULL;
-       }
-
-       return 0;
-}
-
-static struct em28xx_ops dvb_ops = {
-       .id   = EM28XX_DVB,
-       .name = "Em28xx dvb Extension",
-       .init = em28xx_dvb_init,
-       .fini = em28xx_dvb_fini,
-};
-
-static int __init em28xx_dvb_register(void)
-{
-       return em28xx_register_extension(&dvb_ops);
-}
-
-static void __exit em28xx_dvb_unregister(void)
-{
-       em28xx_unregister_extension(&dvb_ops);
-}
-
-module_init(em28xx_dvb_register);
-module_exit(em28xx_dvb_unregister);
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
deleted file mode 100644 (file)
index 1683bd9..0000000
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
-   em28xx-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices
-
-   Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
-                     Markus Rechberger <mrechberger@gmail.com>
-                     Mauro Carvalho Chehab <mchehab@infradead.org>
-                     Sascha Sommer <saschasommer@freenet.de>
-
-   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/module.h>
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/i2c.h>
-
-#include "em28xx.h"
-#include "tuner-xc2028.h"
-#include <media/v4l2-common.h>
-#include <media/tuner.h>
-
-/* ----------------------------------------------------------- */
-
-static unsigned int i2c_scan;
-module_param(i2c_scan, int, 0444);
-MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
-
-static unsigned int i2c_debug;
-module_param(i2c_debug, int, 0644);
-MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
-
-#define dprintk2(lvl, fmt, args...)                    \
-do {                                                   \
-       if (i2c_debug >= lvl) {                         \
-               printk(KERN_DEBUG "%s at %s: " fmt,     \
-                      dev->name, __func__ , ##args);   \
-      }                                                \
-} while (0)
-
-/*
- * em2800_i2c_send_max4()
- * send up to 4 bytes to the i2c device
- */
-static int em2800_i2c_send_max4(struct em28xx *dev, unsigned char addr,
-                               char *buf, int len)
-{
-       int ret;
-       int write_timeout;
-       unsigned char b2[6];
-       BUG_ON(len < 1 || len > 4);
-       b2[5] = 0x80 + len - 1;
-       b2[4] = addr;
-       b2[3] = buf[0];
-       if (len > 1)
-               b2[2] = buf[1];
-       if (len > 2)
-               b2[1] = buf[2];
-       if (len > 3)
-               b2[0] = buf[3];
-
-       ret = dev->em28xx_write_regs(dev, 4 - len, &b2[4 - len], 2 + len);
-       if (ret != 2 + len) {
-               em28xx_warn("writing to i2c device failed (error=%i)\n", ret);
-               return -EIO;
-       }
-       for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
-            write_timeout -= 5) {
-               ret = dev->em28xx_read_reg(dev, 0x05);
-               if (ret == 0x80 + len - 1)
-                       return len;
-               msleep(5);
-       }
-       em28xx_warn("i2c write timed out\n");
-       return -EIO;
-}
-
-/*
- * em2800_i2c_send_bytes()
- */
-static int em2800_i2c_send_bytes(void *data, unsigned char addr, char *buf,
-                                short len)
-{
-       char *bufPtr = buf;
-       int ret;
-       int wrcount = 0;
-       int count;
-       int maxLen = 4;
-       struct em28xx *dev = (struct em28xx *)data;
-       while (len > 0) {
-               count = (len > maxLen) ? maxLen : len;
-               ret = em2800_i2c_send_max4(dev, addr, bufPtr, count);
-               if (ret > 0) {
-                       len -= count;
-                       bufPtr += count;
-                       wrcount += count;
-               } else
-                       return (ret < 0) ? ret : -EFAULT;
-       }
-       return wrcount;
-}
-
-/*
- * em2800_i2c_check_for_device()
- * check if there is a i2c_device at the supplied address
- */
-static int em2800_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
-{
-       char msg;
-       int ret;
-       int write_timeout;
-       msg = addr;
-       ret = dev->em28xx_write_regs(dev, 0x04, &msg, 1);
-       if (ret < 0) {
-               em28xx_warn("setting i2c device address failed (error=%i)\n",
-                           ret);
-               return ret;
-       }
-       msg = 0x84;
-       ret = dev->em28xx_write_regs(dev, 0x05, &msg, 1);
-       if (ret < 0) {
-               em28xx_warn("preparing i2c read failed (error=%i)\n", ret);
-               return ret;
-       }
-       for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
-            write_timeout -= 5) {
-               unsigned reg = dev->em28xx_read_reg(dev, 0x5);
-
-               if (reg == 0x94)
-                       return -ENODEV;
-               else if (reg == 0x84)
-                       return 0;
-               msleep(5);
-       }
-       return -ENODEV;
-}
-
-/*
- * em2800_i2c_recv_bytes()
- * read from the i2c device
- */
-static int em2800_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
-                                char *buf, int len)
-{
-       int ret;
-       /* check for the device and set i2c read address */
-       ret = em2800_i2c_check_for_device(dev, addr);
-       if (ret) {
-               em28xx_warn
-                   ("preparing read at i2c address 0x%x failed (error=%i)\n",
-                    addr, ret);
-               return ret;
-       }
-       ret = dev->em28xx_read_reg_req_len(dev, 0x0, 0x3, buf, len);
-       if (ret < 0) {
-               em28xx_warn("reading from i2c device at 0x%x failed (error=%i)",
-                           addr, ret);
-               return ret;
-       }
-       return ret;
-}
-
-/*
- * em28xx_i2c_send_bytes()
- */
-static int em28xx_i2c_send_bytes(void *data, unsigned char addr, char *buf,
-                                short len, int stop)
-{
-       int wrcount = 0;
-       struct em28xx *dev = (struct em28xx *)data;
-       int write_timeout, ret;
-
-       wrcount = dev->em28xx_write_regs_req(dev, stop ? 2 : 3, addr, buf, len);
-
-       /* Seems to be required after a write */
-       for (write_timeout = EM2800_I2C_WRITE_TIMEOUT; write_timeout > 0;
-            write_timeout -= 5) {
-               ret = dev->em28xx_read_reg(dev, 0x05);
-               if (!ret)
-                       break;
-               msleep(5);
-       }
-
-       return wrcount;
-}
-
-/*
- * em28xx_i2c_recv_bytes()
- * read a byte from the i2c device
- */
-static int em28xx_i2c_recv_bytes(struct em28xx *dev, unsigned char addr,
-                                char *buf, int len)
-{
-       int ret;
-       ret = dev->em28xx_read_reg_req_len(dev, 2, addr, buf, len);
-       if (ret < 0) {
-               em28xx_warn("reading i2c device failed (error=%i)\n", ret);
-               return ret;
-       }
-       if (dev->em28xx_read_reg(dev, 0x5) != 0)
-               return -ENODEV;
-       return ret;
-}
-
-/*
- * em28xx_i2c_check_for_device()
- * check if there is a i2c_device at the supplied address
- */
-static int em28xx_i2c_check_for_device(struct em28xx *dev, unsigned char addr)
-{
-       int ret;
-
-       ret = dev->em28xx_read_reg_req(dev, 2, addr);
-       if (ret < 0) {
-               em28xx_warn("reading from i2c device failed (error=%i)\n", ret);
-               return ret;
-       }
-       if (dev->em28xx_read_reg(dev, 0x5) != 0)
-               return -ENODEV;
-       return 0;
-}
-
-/*
- * em28xx_i2c_xfer()
- * the main i2c transfer function
- */
-static int em28xx_i2c_xfer(struct i2c_adapter *i2c_adap,
-                          struct i2c_msg msgs[], int num)
-{
-       struct em28xx *dev = i2c_adap->algo_data;
-       int addr, rc, i, byte;
-
-       if (num <= 0)
-               return 0;
-       for (i = 0; i < num; i++) {
-               addr = msgs[i].addr << 1;
-               dprintk2(2, "%s %s addr=%x len=%d:",
-                        (msgs[i].flags & I2C_M_RD) ? "read" : "write",
-                        i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
-               if (!msgs[i].len) { /* no len: check only for device presence */
-                       if (dev->board.is_em2800)
-                               rc = em2800_i2c_check_for_device(dev, addr);
-                       else
-                               rc = em28xx_i2c_check_for_device(dev, addr);
-                       if (rc < 0) {
-                               dprintk2(2, " no device\n");
-                               return rc;
-                       }
-
-               } else if (msgs[i].flags & I2C_M_RD) {
-                       /* read bytes */
-                       if (dev->board.is_em2800)
-                               rc = em2800_i2c_recv_bytes(dev, addr,
-                                                          msgs[i].buf,
-                                                          msgs[i].len);
-                       else
-                               rc = em28xx_i2c_recv_bytes(dev, addr,
-                                                          msgs[i].buf,
-                                                          msgs[i].len);
-                       if (i2c_debug >= 2) {
-                               for (byte = 0; byte < msgs[i].len; byte++)
-                                       printk(" %02x", msgs[i].buf[byte]);
-                       }
-               } else {
-                       /* write bytes */
-                       if (i2c_debug >= 2) {
-                               for (byte = 0; byte < msgs[i].len; byte++)
-                                       printk(" %02x", msgs[i].buf[byte]);
-                       }
-                       if (dev->board.is_em2800)
-                               rc = em2800_i2c_send_bytes(dev, addr,
-                                                          msgs[i].buf,
-                                                          msgs[i].len);
-                       else
-                               rc = em28xx_i2c_send_bytes(dev, addr,
-                                                          msgs[i].buf,
-                                                          msgs[i].len,
-                                                          i == num - 1);
-               }
-               if (rc < 0)
-                       goto err;
-               if (i2c_debug >= 2)
-                       printk("\n");
-       }
-
-       return num;
-err:
-       dprintk2(2, " ERROR: %i\n", rc);
-       return rc;
-}
-
-/* based on linux/sunrpc/svcauth.h and linux/hash.h
- * The original hash function returns a different value, if arch is x86_64
- *  or i386.
- */
-static inline unsigned long em28xx_hash_mem(char *buf, int length, int bits)
-{
-       unsigned long hash = 0;
-       unsigned long l = 0;
-       int len = 0;
-       unsigned char c;
-       do {
-               if (len == length) {
-                       c = (char)len;
-                       len = -1;
-               } else
-                       c = *buf++;
-               l = (l << 8) | c;
-               len++;
-               if ((len & (32 / 8 - 1)) == 0)
-                       hash = ((hash^l) * 0x9e370001UL);
-       } while (len);
-
-       return (hash >> (32 - bits)) & 0xffffffffUL;
-}
-
-static int em28xx_i2c_eeprom(struct em28xx *dev, unsigned char *eedata, int len)
-{
-       unsigned char buf, *p = eedata;
-       struct em28xx_eeprom *em_eeprom = (void *)eedata;
-       int i, err, size = len, block;
-
-       if (dev->chip_id == CHIP_ID_EM2874 ||
-           dev->chip_id == CHIP_ID_EM28174 ||
-           dev->chip_id == CHIP_ID_EM2884) {
-               /* Empia switched to a 16-bit addressable eeprom in newer
-                  devices.  While we could certainly write a routine to read
-                  the eeprom, there is nothing of use in there that cannot be
-                  accessed through registers, and there is the risk that we
-                  could corrupt the eeprom (since a 16-bit read call is
-                  interpreted as a write call by 8-bit eeproms).
-               */
-               return 0;
-       }
-
-       dev->i2c_client.addr = 0xa0 >> 1;
-
-       /* Check if board has eeprom */
-       err = i2c_master_recv(&dev->i2c_client, &buf, 0);
-       if (err < 0) {
-               em28xx_errdev("board has no eeprom\n");
-               memset(eedata, 0, len);
-               return -ENODEV;
-       }
-
-       buf = 0;
-
-       err = i2c_master_send(&dev->i2c_client, &buf, 1);
-       if (err != 1) {
-               printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
-                      dev->name, err);
-               return err;
-       }
-       while (size > 0) {
-               if (size > 16)
-                       block = 16;
-               else
-                       block = size;
-
-               if (block !=
-                   (err = i2c_master_recv(&dev->i2c_client, p, block))) {
-                       printk(KERN_WARNING
-                              "%s: i2c eeprom read error (err=%d)\n",
-                              dev->name, err);
-                       return err;
-               }
-               size -= block;
-               p += block;
-       }
-       for (i = 0; i < len; i++) {
-               if (0 == (i % 16))
-                       printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
-               printk(" %02x", eedata[i]);
-               if (15 == (i % 16))
-                       printk("\n");
-       }
-
-       if (em_eeprom->id == 0x9567eb1a)
-               dev->hash = em28xx_hash_mem(eedata, len, 32);
-
-       printk(KERN_INFO "%s: EEPROM ID= 0x%08x, EEPROM hash = 0x%08lx\n",
-              dev->name, em_eeprom->id, dev->hash);
-
-       printk(KERN_INFO "%s: EEPROM info:\n", dev->name);
-
-       switch (em_eeprom->chip_conf >> 4 & 0x3) {
-       case 0:
-               printk(KERN_INFO "%s:\tNo audio on board.\n", dev->name);
-               break;
-       case 1:
-               printk(KERN_INFO "%s:\tAC97 audio (5 sample rates)\n",
-                                dev->name);
-               break;
-       case 2:
-               printk(KERN_INFO "%s:\tI2S audio, sample rate=32k\n",
-                                dev->name);
-               break;
-       case 3:
-               printk(KERN_INFO "%s:\tI2S audio, 3 sample rates\n",
-                                dev->name);
-               break;
-       }
-
-       if (em_eeprom->chip_conf & 1 << 3)
-               printk(KERN_INFO "%s:\tUSB Remote wakeup capable\n", dev->name);
-
-       if (em_eeprom->chip_conf & 1 << 2)
-               printk(KERN_INFO "%s:\tUSB Self power capable\n", dev->name);
-
-       switch (em_eeprom->chip_conf & 0x3) {
-       case 0:
-               printk(KERN_INFO "%s:\t500mA max power\n", dev->name);
-               break;
-       case 1:
-               printk(KERN_INFO "%s:\t400mA max power\n", dev->name);
-               break;
-       case 2:
-               printk(KERN_INFO "%s:\t300mA max power\n", dev->name);
-               break;
-       case 3:
-               printk(KERN_INFO "%s:\t200mA max power\n", dev->name);
-               break;
-       }
-       printk(KERN_INFO "%s:\tTable at 0x%02x, strings=0x%04x, 0x%04x, 0x%04x\n",
-                               dev->name,
-                               em_eeprom->string_idx_table,
-                               em_eeprom->string1,
-                               em_eeprom->string2,
-                               em_eeprom->string3);
-
-       return 0;
-}
-
-/* ----------------------------------------------------------- */
-
-/*
- * functionality()
- */
-static u32 functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_SMBUS_EMUL;
-}
-
-static struct i2c_algorithm em28xx_algo = {
-       .master_xfer   = em28xx_i2c_xfer,
-       .functionality = functionality,
-};
-
-static struct i2c_adapter em28xx_adap_template = {
-       .owner = THIS_MODULE,
-       .name = "em28xx",
-       .algo = &em28xx_algo,
-};
-
-static struct i2c_client em28xx_client_template = {
-       .name = "em28xx internal",
-};
-
-/* ----------------------------------------------------------- */
-
-/*
- * i2c_devs
- * incomplete list of known devices
- */
-static char *i2c_devs[128] = {
-       [0x4a >> 1] = "saa7113h",
-       [0x52 >> 1] = "drxk",
-       [0x60 >> 1] = "remote IR sensor",
-       [0x8e >> 1] = "remote IR sensor",
-       [0x86 >> 1] = "tda9887",
-       [0x80 >> 1] = "msp34xx",
-       [0x88 >> 1] = "msp34xx",
-       [0xa0 >> 1] = "eeprom",
-       [0xb0 >> 1] = "tda9874",
-       [0xb8 >> 1] = "tvp5150a",
-       [0xba >> 1] = "webcam sensor or tvp5150a",
-       [0xc0 >> 1] = "tuner (analog)",
-       [0xc2 >> 1] = "tuner (analog)",
-       [0xc4 >> 1] = "tuner (analog)",
-       [0xc6 >> 1] = "tuner (analog)",
-};
-
-/*
- * do_i2c_scan()
- * check i2c address range for devices
- */
-void em28xx_do_i2c_scan(struct em28xx *dev)
-{
-       u8 i2c_devicelist[128];
-       unsigned char buf;
-       int i, rc;
-
-       memset(i2c_devicelist, 0, ARRAY_SIZE(i2c_devicelist));
-
-       for (i = 0; i < ARRAY_SIZE(i2c_devs); i++) {
-               dev->i2c_client.addr = i;
-               rc = i2c_master_recv(&dev->i2c_client, &buf, 0);
-               if (rc < 0)
-                       continue;
-               i2c_devicelist[i] = i;
-               printk(KERN_INFO "%s: found i2c device @ 0x%x [%s]\n",
-                      dev->name, i << 1, i2c_devs[i] ? i2c_devs[i] : "???");
-       }
-
-       dev->i2c_hash = em28xx_hash_mem(i2c_devicelist,
-                                       ARRAY_SIZE(i2c_devicelist), 32);
-}
-
-/*
- * em28xx_i2c_register()
- * register i2c bus
- */
-int em28xx_i2c_register(struct em28xx *dev)
-{
-       int retval;
-
-       BUG_ON(!dev->em28xx_write_regs || !dev->em28xx_read_reg);
-       BUG_ON(!dev->em28xx_write_regs_req || !dev->em28xx_read_reg_req);
-       dev->i2c_adap = em28xx_adap_template;
-       dev->i2c_adap.dev.parent = &dev->udev->dev;
-       strcpy(dev->i2c_adap.name, dev->name);
-       dev->i2c_adap.algo_data = dev;
-       i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
-
-       retval = i2c_add_adapter(&dev->i2c_adap);
-       if (retval < 0) {
-               em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n",
-                       __func__, retval);
-               return retval;
-       }
-
-       dev->i2c_client = em28xx_client_template;
-       dev->i2c_client.adapter = &dev->i2c_adap;
-
-       retval = em28xx_i2c_eeprom(dev, dev->eedata, sizeof(dev->eedata));
-       if ((retval < 0) && (retval != -ENODEV)) {
-               em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
-                       __func__, retval);
-
-               return retval;
-       }
-
-       if (i2c_scan)
-               em28xx_do_i2c_scan(dev);
-
-       return 0;
-}
-
-/*
- * em28xx_i2c_unregister()
- * unregister i2c_bus
- */
-int em28xx_i2c_unregister(struct em28xx *dev)
-{
-       i2c_del_adapter(&dev->i2c_adap);
-       return 0;
-}
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
deleted file mode 100644 (file)
index 97d36b4..0000000
+++ /dev/null
@@ -1,645 +0,0 @@
-/*
-  handle em28xx IR remotes via linux kernel input layer.
-
-   Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
-                     Markus Rechberger <mrechberger@gmail.com>
-                     Mauro Carvalho Chehab <mchehab@infradead.org>
-                     Sascha Sommer <saschasommer@freenet.de>
-
-  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/usb.h>
-#include <linux/slab.h>
-
-#include "em28xx.h"
-
-#define EM28XX_SNAPSHOT_KEY KEY_CAMERA
-#define EM28XX_SBUTTON_QUERY_INTERVAL 500
-#define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20
-
-static unsigned int ir_debug;
-module_param(ir_debug, int, 0644);
-MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
-
-#define MODULE_NAME "em28xx"
-
-#define i2cdprintk(fmt, arg...) \
-       if (ir_debug) { \
-               printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
-       }
-
-#define dprintk(fmt, arg...) \
-       if (ir_debug) { \
-               printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
-       }
-
-/**********************************************************
- Polling structure used by em28xx IR's
- **********************************************************/
-
-struct em28xx_ir_poll_result {
-       unsigned int toggle_bit:1;
-       unsigned int read_count:7;
-       u8 rc_address;
-       u8 rc_data[4]; /* 1 byte on em2860/2880, 4 on em2874 */
-};
-
-struct em28xx_IR {
-       struct em28xx *dev;
-       struct rc_dev *rc;
-       char name[32];
-       char phys[32];
-
-       /* poll external decoder */
-       int polling;
-       struct delayed_work work;
-       unsigned int full_code:1;
-       unsigned int last_readcount;
-
-       int  (*get_key)(struct em28xx_IR *, struct em28xx_ir_poll_result *);
-};
-
-/**********************************************************
- I2C IR based get keycodes - should be used with ir-kbd-i2c
- **********************************************************/
-
-static int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
-{
-       unsigned char b;
-
-       /* poll IR chip */
-       if (1 != i2c_master_recv(ir->c, &b, 1)) {
-               i2cdprintk("read error\n");
-               return -EIO;
-       }
-
-       /* it seems that 0xFE indicates that a button is still hold
-          down, while 0xff indicates that no button is hold
-          down. 0xfe sequences are sometimes interrupted by 0xFF */
-
-       i2cdprintk("key %02x\n", b);
-
-       if (b == 0xff)
-               return 0;
-
-       if (b == 0xfe)
-               /* keep old data */
-               return 1;
-
-       *ir_key = b;
-       *ir_raw = b;
-       return 1;
-}
-
-static int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
-{
-       unsigned char buf[2];
-       u16 code;
-       int size;
-
-       /* poll IR chip */
-       size = i2c_master_recv(ir->c, buf, sizeof(buf));
-
-       if (size != 2)
-               return -EIO;
-
-       /* Does eliminate repeated parity code */
-       if (buf[1] == 0xff)
-               return 0;
-
-       ir->old = buf[1];
-
-       /*
-        * Rearranges bits to the right order.
-        * The bit order were determined experimentally by using
-        * The original Hauppauge Grey IR and another RC5 that uses addr=0x08
-        * The RC5 code has 14 bits, but we've experimentally determined
-        * the meaning for only 11 bits.
-        * So, the code translation is not complete. Yet, it is enough to
-        * work with the provided RC5 IR.
-        */
-       code =
-                ((buf[0] & 0x01) ? 0x0020 : 0) | /*            0010 0000 */
-                ((buf[0] & 0x02) ? 0x0010 : 0) | /*            0001 0000 */
-                ((buf[0] & 0x04) ? 0x0008 : 0) | /*            0000 1000 */
-                ((buf[0] & 0x08) ? 0x0004 : 0) | /*            0000 0100 */
-                ((buf[0] & 0x10) ? 0x0002 : 0) | /*            0000 0010 */
-                ((buf[0] & 0x20) ? 0x0001 : 0) | /*            0000 0001 */
-                ((buf[1] & 0x08) ? 0x1000 : 0) | /* 0001 0000            */
-                ((buf[1] & 0x10) ? 0x0800 : 0) | /* 0000 1000            */
-                ((buf[1] & 0x20) ? 0x0400 : 0) | /* 0000 0100            */
-                ((buf[1] & 0x40) ? 0x0200 : 0) | /* 0000 0010            */
-                ((buf[1] & 0x80) ? 0x0100 : 0);  /* 0000 0001            */
-
-       i2cdprintk("ir hauppauge (em2840): code=0x%02x (rcv=0x%02x%02x)\n",
-                       code, buf[1], buf[0]);
-
-       /* return key */
-       *ir_key = code;
-       *ir_raw = code;
-       return 1;
-}
-
-static int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
-                                    u32 *ir_raw)
-{
-       unsigned char buf[3];
-
-       /* poll IR chip */
-
-       if (3 != i2c_master_recv(ir->c, buf, 3)) {
-               i2cdprintk("read error\n");
-               return -EIO;
-       }
-
-       i2cdprintk("key %02x\n", buf[2]&0x3f);
-       if (buf[0] != 0x00)
-               return 0;
-
-       *ir_key = buf[2]&0x3f;
-       *ir_raw = buf[2]&0x3f;
-
-       return 1;
-}
-
-static int em28xx_get_key_winfast_usbii_deluxe(struct IR_i2c *ir, u32 *ir_key,
-                                       u32 *ir_raw)
-{
-       unsigned char subaddr, keydetect, key;
-
-       struct i2c_msg msg[] = { { .addr = ir->c->addr, .flags = 0, .buf = &subaddr, .len = 1},
-
-                               { .addr = ir->c->addr, .flags = I2C_M_RD, .buf = &keydetect, .len = 1} };
-
-       subaddr = 0x10;
-       if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
-               i2cdprintk("read error\n");
-               return -EIO;
-       }
-       if (keydetect == 0x00)
-               return 0;
-
-       subaddr = 0x00;
-       msg[1].buf = &key;
-       if (2 != i2c_transfer(ir->c->adapter, msg, 2)) {
-               i2cdprintk("read error\n");
-       return -EIO;
-       }
-       if (key == 0x00)
-               return 0;
-
-       *ir_key = key;
-       *ir_raw = key;
-       return 1;
-}
-
-/**********************************************************
- Poll based get keycode functions
- **********************************************************/
-
-/* This is for the em2860/em2880 */
-static int default_polling_getkey(struct em28xx_IR *ir,
-                                 struct em28xx_ir_poll_result *poll_result)
-{
-       struct em28xx *dev = ir->dev;
-       int rc;
-       u8 msg[3] = { 0, 0, 0 };
-
-       /* Read key toggle, brand, and key code
-          on registers 0x45, 0x46 and 0x47
-        */
-       rc = dev->em28xx_read_reg_req_len(dev, 0, EM28XX_R45_IR,
-                                         msg, sizeof(msg));
-       if (rc < 0)
-               return rc;
-
-       /* Infrared toggle (Reg 0x45[7]) */
-       poll_result->toggle_bit = (msg[0] >> 7);
-
-       /* Infrared read count (Reg 0x45[6:0] */
-       poll_result->read_count = (msg[0] & 0x7f);
-
-       /* Remote Control Address (Reg 0x46) */
-       poll_result->rc_address = msg[1];
-
-       /* Remote Control Data (Reg 0x47) */
-       poll_result->rc_data[0] = msg[2];
-
-       return 0;
-}
-
-static int em2874_polling_getkey(struct em28xx_IR *ir,
-                                struct em28xx_ir_poll_result *poll_result)
-{
-       struct em28xx *dev = ir->dev;
-       int rc;
-       u8 msg[5] = { 0, 0, 0, 0, 0 };
-
-       /* Read key toggle, brand, and key code
-          on registers 0x51-55
-        */
-       rc = dev->em28xx_read_reg_req_len(dev, 0, EM2874_R51_IR,
-                                         msg, sizeof(msg));
-       if (rc < 0)
-               return rc;
-
-       /* Infrared toggle (Reg 0x51[7]) */
-       poll_result->toggle_bit = (msg[0] >> 7);
-
-       /* Infrared read count (Reg 0x51[6:0] */
-       poll_result->read_count = (msg[0] & 0x7f);
-
-       /* Remote Control Address (Reg 0x52) */
-       poll_result->rc_address = msg[1];
-
-       /* Remote Control Data (Reg 0x53-55) */
-       poll_result->rc_data[0] = msg[2];
-       poll_result->rc_data[1] = msg[3];
-       poll_result->rc_data[2] = msg[4];
-
-       return 0;
-}
-
-/**********************************************************
- Polling code for em28xx
- **********************************************************/
-
-static void em28xx_ir_handle_key(struct em28xx_IR *ir)
-{
-       int result;
-       struct em28xx_ir_poll_result poll_result;
-
-       /* read the registers containing the IR status */
-       result = ir->get_key(ir, &poll_result);
-       if (unlikely(result < 0)) {
-               dprintk("ir->get_key() failed %d\n", result);
-               return;
-       }
-
-       if (unlikely(poll_result.read_count != ir->last_readcount)) {
-               dprintk("%s: toggle: %d, count: %d, key 0x%02x%02x\n", __func__,
-                       poll_result.toggle_bit, poll_result.read_count,
-                       poll_result.rc_address, poll_result.rc_data[0]);
-               if (ir->full_code)
-                       rc_keydown(ir->rc,
-                                  poll_result.rc_address << 8 |
-                                  poll_result.rc_data[0],
-                                  poll_result.toggle_bit);
-               else
-                       rc_keydown(ir->rc,
-                                  poll_result.rc_data[0],
-                                  poll_result.toggle_bit);
-
-               if (ir->dev->chip_id == CHIP_ID_EM2874 ||
-                   ir->dev->chip_id == CHIP_ID_EM2884)
-                       /* The em2874 clears the readcount field every time the
-                          register is read.  The em2860/2880 datasheet says that it
-                          is supposed to clear the readcount, but it doesn't.  So with
-                          the em2874, we are looking for a non-zero read count as
-                          opposed to a readcount that is incrementing */
-                       ir->last_readcount = 0;
-               else
-                       ir->last_readcount = poll_result.read_count;
-       }
-}
-
-static void em28xx_ir_work(struct work_struct *work)
-{
-       struct em28xx_IR *ir = container_of(work, struct em28xx_IR, work.work);
-
-       em28xx_ir_handle_key(ir);
-       schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
-}
-
-static int em28xx_ir_start(struct rc_dev *rc)
-{
-       struct em28xx_IR *ir = rc->priv;
-
-       INIT_DELAYED_WORK(&ir->work, em28xx_ir_work);
-       schedule_delayed_work(&ir->work, 0);
-
-       return 0;
-}
-
-static void em28xx_ir_stop(struct rc_dev *rc)
-{
-       struct em28xx_IR *ir = rc->priv;
-
-       cancel_delayed_work_sync(&ir->work);
-}
-
-static int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type)
-{
-       int rc = 0;
-       struct em28xx_IR *ir = rc_dev->priv;
-       struct em28xx *dev = ir->dev;
-       u8 ir_config = EM2874_IR_RC5;
-
-       /* Adjust xclk based o IR table for RC5/NEC tables */
-
-       if (rc_type == RC_TYPE_RC5) {
-               dev->board.xclk |= EM28XX_XCLK_IR_RC5_MODE;
-               ir->full_code = 1;
-       } else if (rc_type == RC_TYPE_NEC) {
-               dev->board.xclk &= ~EM28XX_XCLK_IR_RC5_MODE;
-               ir_config = EM2874_IR_NEC;
-               ir->full_code = 1;
-       } else if (rc_type != RC_TYPE_UNKNOWN)
-               rc = -EINVAL;
-
-       em28xx_write_reg_bits(dev, EM28XX_R0F_XCLK, dev->board.xclk,
-                             EM28XX_XCLK_IR_RC5_MODE);
-
-       /* Setup the proper handler based on the chip */
-       switch (dev->chip_id) {
-       case CHIP_ID_EM2860:
-       case CHIP_ID_EM2883:
-               ir->get_key = default_polling_getkey;
-               break;
-       case CHIP_ID_EM2884:
-       case CHIP_ID_EM2874:
-       case CHIP_ID_EM28174:
-               ir->get_key = em2874_polling_getkey;
-               em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1);
-               break;
-       default:
-               printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n",
-                       dev->chip_id);
-               rc = -EINVAL;
-       }
-
-       return rc;
-}
-
-static void em28xx_register_i2c_ir(struct em28xx *dev)
-{
-       /* Leadtek winfast tv USBII deluxe can find a non working IR-device */
-       /* at address 0x18, so if that address is needed for another board in */
-       /* the future, please put it after 0x1f. */
-       struct i2c_board_info info;
-       const unsigned short addr_list[] = {
-                0x1f, 0x30, 0x47, I2C_CLIENT_END
-       };
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       memset(&dev->init_data, 0, sizeof(dev->init_data));
-       strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
-
-       /* detect & configure */
-       switch (dev->model) {
-       case EM2800_BOARD_TERRATEC_CINERGY_200:
-       case EM2820_BOARD_TERRATEC_CINERGY_250:
-               dev->init_data.ir_codes = RC_MAP_EM_TERRATEC;
-               dev->init_data.get_key = em28xx_get_key_terratec;
-               dev->init_data.name = "i2c IR (EM28XX Terratec)";
-               break;
-       case EM2820_BOARD_PINNACLE_USB_2:
-               dev->init_data.ir_codes = RC_MAP_PINNACLE_GREY;
-               dev->init_data.get_key = em28xx_get_key_pinnacle_usb_grey;
-               dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)";
-               break;
-       case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
-               dev->init_data.ir_codes = RC_MAP_HAUPPAUGE;
-               dev->init_data.get_key = em28xx_get_key_em_haup;
-               dev->init_data.name = "i2c IR (EM2840 Hauppauge)";
-               break;
-       case EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE:
-               dev->init_data.ir_codes = RC_MAP_WINFAST_USBII_DELUXE;
-               dev->init_data.get_key = em28xx_get_key_winfast_usbii_deluxe;
-               dev->init_data.name = "i2c IR (EM2820 Winfast TV USBII Deluxe)";
-               break;
-       }
-
-       if (dev->init_data.name)
-               info.platform_data = &dev->init_data;
-       i2c_new_probed_device(&dev->i2c_adap, &info, addr_list, NULL);
-}
-
-/**********************************************************
- Handle Webcam snapshot button
- **********************************************************/
-
-static void em28xx_query_sbutton(struct work_struct *work)
-{
-       /* Poll the register and see if the button is depressed */
-       struct em28xx *dev =
-               container_of(work, struct em28xx, sbutton_query_work.work);
-       int ret;
-
-       ret = em28xx_read_reg(dev, EM28XX_R0C_USBSUSP);
-
-       if (ret & EM28XX_R0C_USBSUSP_SNAPSHOT) {
-               u8 cleared;
-               /* Button is depressed, clear the register */
-               cleared = ((u8) ret) & ~EM28XX_R0C_USBSUSP_SNAPSHOT;
-               em28xx_write_regs(dev, EM28XX_R0C_USBSUSP, &cleared, 1);
-
-               /* Not emulate the keypress */
-               input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY,
-                                1);
-               /* Now unpress the key */
-               input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY,
-                                0);
-       }
-
-       /* Schedule next poll */
-       schedule_delayed_work(&dev->sbutton_query_work,
-                             msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL));
-}
-
-static void em28xx_register_snapshot_button(struct em28xx *dev)
-{
-       struct input_dev *input_dev;
-       int err;
-
-       em28xx_info("Registering snapshot button...\n");
-       input_dev = input_allocate_device();
-       if (!input_dev) {
-               em28xx_errdev("input_allocate_device failed\n");
-               return;
-       }
-
-       usb_make_path(dev->udev, dev->snapshot_button_path,
-                     sizeof(dev->snapshot_button_path));
-       strlcat(dev->snapshot_button_path, "/sbutton",
-               sizeof(dev->snapshot_button_path));
-       INIT_DELAYED_WORK(&dev->sbutton_query_work, em28xx_query_sbutton);
-
-       input_dev->name = "em28xx snapshot button";
-       input_dev->phys = dev->snapshot_button_path;
-       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
-       set_bit(EM28XX_SNAPSHOT_KEY, input_dev->keybit);
-       input_dev->keycodesize = 0;
-       input_dev->keycodemax = 0;
-       input_dev->id.bustype = BUS_USB;
-       input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
-       input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
-       input_dev->id.version = 1;
-       input_dev->dev.parent = &dev->udev->dev;
-
-       err = input_register_device(input_dev);
-       if (err) {
-               em28xx_errdev("input_register_device failed\n");
-               input_free_device(input_dev);
-               return;
-       }
-
-       dev->sbutton_input_dev = input_dev;
-       schedule_delayed_work(&dev->sbutton_query_work,
-                             msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL));
-       return;
-
-}
-
-static void em28xx_deregister_snapshot_button(struct em28xx *dev)
-{
-       if (dev->sbutton_input_dev != NULL) {
-               em28xx_info("Deregistering snapshot button\n");
-               cancel_delayed_work_sync(&dev->sbutton_query_work);
-               input_unregister_device(dev->sbutton_input_dev);
-               dev->sbutton_input_dev = NULL;
-       }
-       return;
-}
-
-static int em28xx_ir_init(struct em28xx *dev)
-{
-       struct em28xx_IR *ir;
-       struct rc_dev *rc;
-       int err = -ENOMEM;
-
-       if (dev->board.ir_codes == NULL) {
-               /* No remote control support */
-               em28xx_warn("Remote control support is not available for "
-                               "this card.\n");
-               return 0;
-       }
-
-       ir = kzalloc(sizeof(*ir), GFP_KERNEL);
-       rc = rc_allocate_device();
-       if (!ir || !rc)
-               goto err_out_free;
-
-       /* record handles to ourself */
-       ir->dev = dev;
-       dev->ir = ir;
-       ir->rc = rc;
-
-       /*
-        * em2874 supports more protocols. For now, let's just announce
-        * the two protocols that were already tested
-        */
-       rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
-       rc->priv = ir;
-       rc->change_protocol = em28xx_ir_change_protocol;
-       rc->open = em28xx_ir_start;
-       rc->close = em28xx_ir_stop;
-
-       /* By default, keep protocol field untouched */
-       err = em28xx_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
-       if (err)
-               goto err_out_free;
-
-       /* This is how often we ask the chip for IR information */
-       ir->polling = 100; /* ms */
-
-       /* init input device */
-       snprintf(ir->name, sizeof(ir->name), "em28xx IR (%s)",
-                                               dev->name);
-
-       usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
-       strlcat(ir->phys, "/input0", sizeof(ir->phys));
-
-       rc->input_name = ir->name;
-       rc->input_phys = ir->phys;
-       rc->input_id.bustype = BUS_USB;
-       rc->input_id.version = 1;
-       rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
-       rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
-       rc->dev.parent = &dev->udev->dev;
-       rc->map_name = dev->board.ir_codes;
-       rc->driver_name = MODULE_NAME;
-
-       /* all done */
-       err = rc_register_device(rc);
-       if (err)
-               goto err_out_stop;
-
-       em28xx_register_i2c_ir(dev);
-
-#if defined(CONFIG_MODULES) && defined(MODULE)
-       if (dev->board.has_ir_i2c)
-               request_module("ir-kbd-i2c");
-#endif
-       if (dev->board.has_snapshot_button)
-               em28xx_register_snapshot_button(dev);
-
-       return 0;
-
- err_out_stop:
-       dev->ir = NULL;
- err_out_free:
-       rc_free_device(rc);
-       kfree(ir);
-       return err;
-}
-
-static int em28xx_ir_fini(struct em28xx *dev)
-{
-       struct em28xx_IR *ir = dev->ir;
-
-       em28xx_deregister_snapshot_button(dev);
-
-       /* skip detach on non attached boards */
-       if (!ir)
-               return 0;
-
-       if (ir->rc)
-               rc_unregister_device(ir->rc);
-
-       /* done */
-       kfree(ir);
-       dev->ir = NULL;
-       return 0;
-}
-
-static struct em28xx_ops rc_ops = {
-       .id   = EM28XX_RC,
-       .name = "Em28xx Input Extension",
-       .init = em28xx_ir_init,
-       .fini = em28xx_ir_fini,
-};
-
-static int __init em28xx_rc_register(void)
-{
-       return em28xx_register_extension(&rc_ops);
-}
-
-static void __exit em28xx_rc_unregister(void)
-{
-       em28xx_unregister_extension(&rc_ops);
-}
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_DESCRIPTION("Em28xx Input driver");
-
-module_init(em28xx_rc_register);
-module_exit(em28xx_rc_unregister);
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h
deleted file mode 100644 (file)
index 6ff3682..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-#define EM_GPIO_0  (1 << 0)
-#define EM_GPIO_1  (1 << 1)
-#define EM_GPIO_2  (1 << 2)
-#define EM_GPIO_3  (1 << 3)
-#define EM_GPIO_4  (1 << 4)
-#define EM_GPIO_5  (1 << 5)
-#define EM_GPIO_6  (1 << 6)
-#define EM_GPIO_7  (1 << 7)
-
-#define EM_GPO_0   (1 << 0)
-#define EM_GPO_1   (1 << 1)
-#define EM_GPO_2   (1 << 2)
-#define EM_GPO_3   (1 << 3)
-
-/* em28xx endpoints */
-#define EM28XX_EP_ANALOG       0x82
-#define EM28XX_EP_AUDIO                0x83
-#define EM28XX_EP_DIGITAL      0x84
-
-/* em2800 registers */
-#define EM2800_R08_AUDIOSRC 0x08
-
-/* em28xx registers */
-
-#define EM28XX_R00_CHIPCFG     0x00
-
-/* em28xx Chip Configuration 0x00 */
-#define EM28XX_CHIPCFG_VENDOR_AUDIO            0x80
-#define EM28XX_CHIPCFG_I2S_VOLUME_CAPABLE      0x40
-#define EM28XX_CHIPCFG_I2S_5_SAMPRATES         0x30
-#define EM28XX_CHIPCFG_I2S_3_SAMPRATES         0x20
-#define EM28XX_CHIPCFG_AC97                    0x10
-#define EM28XX_CHIPCFG_AUDIOMASK               0x30
-
-#define EM28XX_R01_CHIPCFG2    0x01
-
-/* em28xx Chip Configuration 2 0x01 */
-#define EM28XX_CHIPCFG2_TS_PRESENT             0x10
-#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_MASK   0x0c /* bits 3-2 */
-#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_1MF    0x00
-#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_2MF    0x04
-#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_4MF    0x08
-#define EM28XX_CHIPCFG2_TS_REQ_INTERVAL_8MF    0x0c
-#define EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK     0x03 /* bits 0-1 */
-#define EM28XX_CHIPCFG2_TS_PACKETSIZE_188      0x00
-#define EM28XX_CHIPCFG2_TS_PACKETSIZE_376      0x01
-#define EM28XX_CHIPCFG2_TS_PACKETSIZE_564      0x02
-#define EM28XX_CHIPCFG2_TS_PACKETSIZE_752      0x03
-
-
-       /* GPIO/GPO registers */
-#define EM2880_R04_GPO 0x04    /* em2880-em2883 only */
-#define EM28XX_R08_GPIO        0x08    /* em2820 or upper */
-
-#define EM28XX_R06_I2C_CLK     0x06
-
-/* em28xx I2C Clock Register (0x06) */
-#define EM28XX_I2C_CLK_ACK_LAST_READ   0x80
-#define EM28XX_I2C_CLK_WAIT_ENABLE     0x40
-#define EM28XX_I2C_EEPROM_ON_BOARD     0x08
-#define EM28XX_I2C_EEPROM_KEY_VALID    0x04
-#define EM2874_I2C_SECONDARY_BUS_SELECT        0x04 /* em2874 has two i2c busses */
-#define EM28XX_I2C_FREQ_1_5_MHZ                0x03 /* bus frequency (bits [1-0]) */
-#define EM28XX_I2C_FREQ_25_KHZ         0x02
-#define EM28XX_I2C_FREQ_400_KHZ                0x01
-#define EM28XX_I2C_FREQ_100_KHZ                0x00
-
-
-#define EM28XX_R0A_CHIPID      0x0a
-#define EM28XX_R0C_USBSUSP     0x0c    /* */
-
-#define EM28XX_R0E_AUDIOSRC    0x0e
-#define EM28XX_R0F_XCLK        0x0f
-
-/* em28xx XCLK Register (0x0f) */
-#define EM28XX_XCLK_AUDIO_UNMUTE       0x80 /* otherwise audio muted */
-#define EM28XX_XCLK_I2S_MSB_TIMING     0x40 /* otherwise standard timing */
-#define EM28XX_XCLK_IR_RC5_MODE                0x20 /* otherwise NEC mode */
-#define EM28XX_XCLK_IR_NEC_CHK_PARITY  0x10
-#define EM28XX_XCLK_FREQUENCY_30MHZ    0x00 /* Freq. select (bits [3-0]) */
-#define EM28XX_XCLK_FREQUENCY_15MHZ    0x01
-#define EM28XX_XCLK_FREQUENCY_10MHZ    0x02
-#define EM28XX_XCLK_FREQUENCY_7_5MHZ   0x03
-#define EM28XX_XCLK_FREQUENCY_6MHZ     0x04
-#define EM28XX_XCLK_FREQUENCY_5MHZ     0x05
-#define EM28XX_XCLK_FREQUENCY_4_3MHZ   0x06
-#define EM28XX_XCLK_FREQUENCY_12MHZ    0x07
-#define EM28XX_XCLK_FREQUENCY_20MHZ    0x08
-#define EM28XX_XCLK_FREQUENCY_20MHZ_2  0x09
-#define EM28XX_XCLK_FREQUENCY_48MHZ    0x0a
-#define EM28XX_XCLK_FREQUENCY_24MHZ    0x0b
-
-#define EM28XX_R10_VINMODE     0x10
-
-#define EM28XX_R11_VINCTRL     0x11
-
-/* em28xx Video Input Control Register 0x11 */
-#define EM28XX_VINCTRL_VBI_SLICED      0x80
-#define EM28XX_VINCTRL_VBI_RAW         0x40
-#define EM28XX_VINCTRL_VOUT_MODE_IN    0x20 /* HREF,VREF,VACT in output */
-#define EM28XX_VINCTRL_CCIR656_ENABLE  0x10
-#define EM28XX_VINCTRL_VBI_16BIT_RAW   0x08 /* otherwise 8-bit raw */
-#define EM28XX_VINCTRL_FID_ON_HREF     0x04
-#define EM28XX_VINCTRL_DUAL_EDGE_STROBE        0x02
-#define EM28XX_VINCTRL_INTERLACED      0x01
-
-#define EM28XX_R12_VINENABLE   0x12    /* */
-
-#define EM28XX_R14_GAMMA       0x14
-#define EM28XX_R15_RGAIN       0x15
-#define EM28XX_R16_GGAIN       0x16
-#define EM28XX_R17_BGAIN       0x17
-#define EM28XX_R18_ROFFSET     0x18
-#define EM28XX_R19_GOFFSET     0x19
-#define EM28XX_R1A_BOFFSET     0x1a
-
-#define EM28XX_R1B_OFLOW       0x1b
-#define EM28XX_R1C_HSTART      0x1c
-#define EM28XX_R1D_VSTART      0x1d
-#define EM28XX_R1E_CWIDTH      0x1e
-#define EM28XX_R1F_CHEIGHT     0x1f
-
-#define EM28XX_R20_YGAIN       0x20
-#define EM28XX_R21_YOFFSET     0x21
-#define EM28XX_R22_UVGAIN      0x22
-#define EM28XX_R23_UOFFSET     0x23
-#define EM28XX_R24_VOFFSET     0x24
-#define EM28XX_R25_SHARPNESS   0x25
-
-#define EM28XX_R26_COMPR       0x26
-#define EM28XX_R27_OUTFMT      0x27
-
-/* em28xx Output Format Register (0x27) */
-#define EM28XX_OUTFMT_RGB_8_RGRG       0x00
-#define EM28XX_OUTFMT_RGB_8_GRGR       0x01
-#define EM28XX_OUTFMT_RGB_8_GBGB       0x02
-#define EM28XX_OUTFMT_RGB_8_BGBG       0x03
-#define EM28XX_OUTFMT_RGB_16_656       0x04
-#define EM28XX_OUTFMT_RGB_8_BAYER      0x08 /* Pattern in Reg 0x10[1-0] */
-#define EM28XX_OUTFMT_YUV211           0x10
-#define EM28XX_OUTFMT_YUV422_Y0UY1V    0x14
-#define EM28XX_OUTFMT_YUV422_Y1UY0V    0x15
-#define EM28XX_OUTFMT_YUV411           0x18
-
-
-#define EM28XX_R28_XMIN        0x28
-#define EM28XX_R29_XMAX        0x29
-#define EM28XX_R2A_YMIN        0x2a
-#define EM28XX_R2B_YMAX        0x2b
-
-#define EM28XX_R30_HSCALELOW   0x30
-#define EM28XX_R31_HSCALEHIGH  0x31
-#define EM28XX_R32_VSCALELOW   0x32
-#define EM28XX_R33_VSCALEHIGH  0x33
-#define EM28XX_R34_VBI_START_H 0x34
-#define EM28XX_R35_VBI_START_V 0x35
-#define EM28XX_R36_VBI_WIDTH   0x36
-#define EM28XX_R37_VBI_HEIGHT  0x37
-
-#define EM28XX_R40_AC97LSB     0x40
-#define EM28XX_R41_AC97MSB     0x41
-#define EM28XX_R42_AC97ADDR    0x42
-#define EM28XX_R43_AC97BUSY    0x43
-
-#define EM28XX_R45_IR          0x45
-       /* 0x45  bit 7    - parity bit
-                bits 6-0 - count
-          0x46  IR brand
-          0x47  IR data
-        */
-
-/* em2874 registers */
-#define EM2874_R50_IR_CONFIG    0x50
-#define EM2874_R51_IR           0x51
-#define EM2874_R5F_TS_ENABLE    0x5f
-#define EM2874_R80_GPIO         0x80
-
-/* em2874 IR config register (0x50) */
-#define EM2874_IR_NEC           0x00
-#define EM2874_IR_RC5           0x04
-#define EM2874_IR_RC6_MODE_0    0x08
-#define EM2874_IR_RC6_MODE_6A   0x0b
-
-/* em2874 Transport Stream Enable Register (0x5f) */
-#define EM2874_TS1_CAPTURE_ENABLE (1 << 0)
-#define EM2874_TS1_FILTER_ENABLE  (1 << 1)
-#define EM2874_TS1_NULL_DISCARD   (1 << 2)
-#define EM2874_TS2_CAPTURE_ENABLE (1 << 4)
-#define EM2874_TS2_FILTER_ENABLE  (1 << 5)
-#define EM2874_TS2_NULL_DISCARD   (1 << 6)
-
-/* register settings */
-#define EM2800_AUDIO_SRC_TUNER  0x0d
-#define EM2800_AUDIO_SRC_LINE   0x0c
-#define EM28XX_AUDIO_SRC_TUNER 0xc0
-#define EM28XX_AUDIO_SRC_LINE  0x80
-
-/* FIXME: Need to be populated with the other chip ID's */
-enum em28xx_chip_id {
-       CHIP_ID_EM2800 = 7,
-       CHIP_ID_EM2710 = 17,
-       CHIP_ID_EM2820 = 18,    /* Also used by some em2710 */
-       CHIP_ID_EM2840 = 20,
-       CHIP_ID_EM2750 = 33,
-       CHIP_ID_EM2860 = 34,
-       CHIP_ID_EM2870 = 35,
-       CHIP_ID_EM2883 = 36,
-       CHIP_ID_EM2874 = 65,
-       CHIP_ID_EM2884 = 68,
-       CHIP_ID_EM28174 = 113,
-};
-
-/*
- * Registers used by em202
- */
-
-/* EMP202 vendor registers */
-#define EM202_EXT_MODEM_CTRL     0x3e
-#define EM202_GPIO_CONF          0x4c
-#define EM202_GPIO_POLARITY      0x4e
-#define EM202_GPIO_STICKY        0x50
-#define EM202_GPIO_MASK          0x52
-#define EM202_GPIO_STATUS        0x54
-#define EM202_SPDIF_OUT_SEL      0x6a
-#define EM202_ANTIPOP            0x72
-#define EM202_EAPD_GPIO_ACCESS   0x74
diff --git a/drivers/media/video/em28xx/em28xx-vbi.c b/drivers/media/video/em28xx/em28xx-vbi.c
deleted file mode 100644 (file)
index 2b4c9cb..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
-   em28xx-vbi.c - VBI driver for em28xx
-
-   Copyright (C) 2009 Devin Heitmueller <dheitmueller@kernellabs.com>
-
-   This work was sponsored by EyeMagnet Limited.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/hardirq.h>
-#include <linux/init.h>
-
-#include "em28xx.h"
-
-static unsigned int vbibufs = 5;
-module_param(vbibufs, int, 0644);
-MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32");
-
-static unsigned int vbi_debug;
-module_param(vbi_debug, int, 0644);
-MODULE_PARM_DESC(vbi_debug, "enable debug messages [vbi]");
-
-#define dprintk(level, fmt, arg...)    if (vbi_debug >= level) \
-       printk(KERN_DEBUG "%s: " fmt, dev->core->name , ## arg)
-
-/* ------------------------------------------------------------------ */
-
-static void
-free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
-{
-       struct em28xx_fh     *fh  = vq->priv_data;
-       struct em28xx        *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);
-
-       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 em28xx_fh     *fh  = q->priv_data;
-       struct em28xx        *dev = fh->dev;
-
-       *size = dev->vbi_width * dev->vbi_height * 2;
-
-       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)
-{
-       struct em28xx_fh     *fh  = q->priv_data;
-       struct em28xx        *dev = fh->dev;
-       struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
-       int                  rc = 0;
-
-       buf->vb.size = dev->vbi_width * dev->vbi_height * 2;
-
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.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;
-       }
-
-       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 em28xx_buffer    *buf     = container_of(vb,
-                                                       struct em28xx_buffer,
-                                                       vb);
-       struct em28xx_fh        *fh      = vq->priv_data;
-       struct em28xx           *dev     = fh->dev;
-       struct em28xx_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)
-{
-       struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
-       free_buffer(q, buf);
-}
-
-struct videobuf_queue_ops em28xx_vbi_qops = {
-       .buf_setup    = vbi_setup,
-       .buf_prepare  = vbi_prepare,
-       .buf_queue    = vbi_queue,
-       .buf_release  = vbi_release,
-};
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
deleted file mode 100644 (file)
index ecb23df..0000000
+++ /dev/null
@@ -1,2624 +0,0 @@
-/*
-   em28xx-video.c - driver for Empia EM2800/EM2820/2840 USB
-                   video capture devices
-
-   Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
-                     Markus Rechberger <mrechberger@gmail.com>
-                     Mauro Carvalho Chehab <mchehab@infradead.org>
-                     Sascha Sommer <saschasommer@freenet.de>
-
-       Some parts based on SN9C10x PC Camera Controllers GPL driver made
-               by Luca Risolia <luca.risolia@studio.unibo.it>
-
-   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/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 <linux/mm.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-
-#include "em28xx.h"
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-chip-ident.h>
-#include <media/msp3400.h>
-#include <media/tuner.h>
-
-#define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
-                     "Markus Rechberger <mrechberger@gmail.com>, " \
-                     "Mauro Carvalho Chehab <mchehab@infradead.org>, " \
-                     "Sascha Sommer <saschasommer@freenet.de>"
-
-#define DRIVER_DESC         "Empia em28xx based USB video device driver"
-
-#define EM28XX_VERSION "0.1.3"
-
-#define em28xx_videodbg(fmt, arg...) do {\
-       if (video_debug) \
-               printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __func__ , ##arg); } while (0)
-
-static unsigned int isoc_debug;
-module_param(isoc_debug, int, 0644);
-MODULE_PARM_DESC(isoc_debug, "enable debug messages [isoc transfers]");
-
-#define em28xx_isocdbg(fmt, arg...) \
-do {\
-       if (isoc_debug) { \
-               printk(KERN_INFO "%s %s :"fmt, \
-                        dev->name, __func__ , ##arg); \
-       } \
-  } while (0)
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(EM28XX_VERSION);
-
-static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
-static unsigned int vbi_nr[]   = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
-static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = UNSET };
-
-module_param_array(video_nr, int, NULL, 0444);
-module_param_array(vbi_nr, int, NULL, 0444);
-module_param_array(radio_nr, int, NULL, 0444);
-MODULE_PARM_DESC(video_nr, "video device numbers");
-MODULE_PARM_DESC(vbi_nr,   "vbi device numbers");
-MODULE_PARM_DESC(radio_nr, "radio device numbers");
-
-static unsigned int video_debug;
-module_param(video_debug, int, 0644);
-MODULE_PARM_DESC(video_debug, "enable debug messages [video]");
-
-/* supported video standards */
-static struct em28xx_fmt format[] = {
-       {
-               .name     = "16 bpp YUY2, 4:2:2, packed",
-               .fourcc   = V4L2_PIX_FMT_YUYV,
-               .depth    = 16,
-               .reg      = EM28XX_OUTFMT_YUV422_Y0UY1V,
-       }, {
-               .name     = "16 bpp RGB 565, LE",
-               .fourcc   = V4L2_PIX_FMT_RGB565,
-               .depth    = 16,
-               .reg      = EM28XX_OUTFMT_RGB_16_656,
-       }, {
-               .name     = "8 bpp Bayer BGBG..GRGR",
-               .fourcc   = V4L2_PIX_FMT_SBGGR8,
-               .depth    = 8,
-               .reg      = EM28XX_OUTFMT_RGB_8_BGBG,
-       }, {
-               .name     = "8 bpp Bayer GRGR..BGBG",
-               .fourcc   = V4L2_PIX_FMT_SGRBG8,
-               .depth    = 8,
-               .reg      = EM28XX_OUTFMT_RGB_8_GRGR,
-       }, {
-               .name     = "8 bpp Bayer GBGB..RGRG",
-               .fourcc   = V4L2_PIX_FMT_SGBRG8,
-               .depth    = 8,
-               .reg      = EM28XX_OUTFMT_RGB_8_GBGB,
-       }, {
-               .name     = "12 bpp YUV411",
-               .fourcc   = V4L2_PIX_FMT_YUV411P,
-               .depth    = 12,
-               .reg      = EM28XX_OUTFMT_YUV411,
-       },
-};
-
-/* supported controls */
-/* Common to all boards */
-static struct v4l2_queryctrl ac97_qctrl[] = {
-       {
-               .id = V4L2_CID_AUDIO_VOLUME,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Volume",
-               .minimum = 0x0,
-               .maximum = 0x1f,
-               .step = 0x1,
-               .default_value = 0x1f,
-               .flags = V4L2_CTRL_FLAG_SLIDER,
-       }, {
-               .id = V4L2_CID_AUDIO_MUTE,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Mute",
-               .minimum = 0,
-               .maximum = 1,
-               .step = 1,
-               .default_value = 1,
-               .flags = 0,
-       }
-};
-
-/* ------------------------------------------------------------------
-       DMA and thread functions
-   ------------------------------------------------------------------*/
-
-/*
- * Announces that a buffer were filled and request the next
- */
-static inline void buffer_filled(struct em28xx *dev,
-                                 struct em28xx_dmaqueue *dma_q,
-                                 struct em28xx_buffer *buf)
-{
-       /* Advice that buffer was filled */
-       em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
-       buf->vb.state = VIDEOBUF_DONE;
-       buf->vb.field_count++;
-       do_gettimeofday(&buf->vb.ts);
-
-       dev->isoc_ctl.vid_buf = NULL;
-
-       list_del(&buf->vb.queue);
-       wake_up(&buf->vb.done);
-}
-
-static inline void vbi_buffer_filled(struct em28xx *dev,
-                                    struct em28xx_dmaqueue *dma_q,
-                                    struct em28xx_buffer *buf)
-{
-       /* Advice that buffer was filled */
-       em28xx_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
-
-       buf->vb.state = VIDEOBUF_DONE;
-       buf->vb.field_count++;
-       do_gettimeofday(&buf->vb.ts);
-
-       dev->isoc_ctl.vbi_buf = NULL;
-
-       list_del(&buf->vb.queue);
-       wake_up(&buf->vb.done);
-}
-
-/*
- * Identify the buffer header type and properly handles
- */
-static void em28xx_copy_video(struct em28xx *dev,
-                             struct em28xx_dmaqueue  *dma_q,
-                             struct em28xx_buffer *buf,
-                             unsigned char *p,
-                             unsigned char *outp, unsigned long len)
-{
-       void *fieldstart, *startwrite, *startread;
-       int  linesdone, currlinedone, offset, lencopy, remain;
-       int bytesperline = dev->width << 1;
-
-       if (dma_q->pos + len > buf->vb.size)
-               len = buf->vb.size - dma_q->pos;
-
-       startread = p;
-       remain = len;
-
-       if (dev->progressive)
-               fieldstart = outp;
-       else {
-               /* Interlaces two half frames */
-               if (buf->top_field)
-                       fieldstart = outp;
-               else
-                       fieldstart = outp + bytesperline;
-       }
-
-       linesdone = dma_q->pos / bytesperline;
-       currlinedone = dma_q->pos % bytesperline;
-
-       if (dev->progressive)
-               offset = linesdone * bytesperline + currlinedone;
-       else
-               offset = linesdone * bytesperline * 2 + currlinedone;
-
-       startwrite = fieldstart + offset;
-       lencopy = bytesperline - currlinedone;
-       lencopy = lencopy > remain ? remain : lencopy;
-
-       if ((char *)startwrite + lencopy > (char *)outp + buf->vb.size) {
-               em28xx_isocdbg("Overflow of %zi bytes past buffer end (1)\n",
-                              ((char *)startwrite + lencopy) -
-                              ((char *)outp + buf->vb.size));
-               remain = (char *)outp + buf->vb.size - (char *)startwrite;
-               lencopy = remain;
-       }
-       if (lencopy <= 0)
-               return;
-       memcpy(startwrite, startread, lencopy);
-
-       remain -= lencopy;
-
-       while (remain > 0) {
-               startwrite += lencopy + bytesperline;
-               startread += lencopy;
-               if (bytesperline > remain)
-                       lencopy = remain;
-               else
-                       lencopy = bytesperline;
-
-               if ((char *)startwrite + lencopy > (char *)outp +
-                   buf->vb.size) {
-                       em28xx_isocdbg("Overflow of %zi bytes past buffer end"
-                                      "(2)\n",
-                                      ((char *)startwrite + lencopy) -
-                                      ((char *)outp + buf->vb.size));
-                       lencopy = remain = (char *)outp + buf->vb.size -
-                                          (char *)startwrite;
-               }
-               if (lencopy <= 0)
-                       break;
-
-               memcpy(startwrite, startread, lencopy);
-
-               remain -= lencopy;
-       }
-
-       dma_q->pos += len;
-}
-
-static void em28xx_copy_vbi(struct em28xx *dev,
-                             struct em28xx_dmaqueue  *dma_q,
-                             struct em28xx_buffer *buf,
-                             unsigned char *p,
-                             unsigned char *outp, unsigned long len)
-{
-       void *startwrite, *startread;
-       int  offset;
-       int bytesperline;
-
-       if (dev == NULL) {
-               em28xx_isocdbg("dev is null\n");
-               return;
-       }
-       bytesperline = dev->vbi_width;
-
-       if (dma_q == NULL) {
-               em28xx_isocdbg("dma_q is null\n");
-               return;
-       }
-       if (buf == NULL) {
-               return;
-       }
-       if (p == NULL) {
-               em28xx_isocdbg("p is null\n");
-               return;
-       }
-       if (outp == NULL) {
-               em28xx_isocdbg("outp is null\n");
-               return;
-       }
-
-       if (dma_q->pos + len > buf->vb.size)
-               len = buf->vb.size - dma_q->pos;
-
-       startread = p;
-
-       startwrite = outp + dma_q->pos;
-       offset = dma_q->pos;
-
-       /* Make sure the bottom field populates the second half of the frame */
-       if (buf->top_field == 0) {
-               startwrite += bytesperline * dev->vbi_height;
-               offset += bytesperline * dev->vbi_height;
-       }
-
-       memcpy(startwrite, startread, len);
-       dma_q->pos += len;
-}
-
-static inline void print_err_status(struct em28xx *dev,
-                                    int packet, int status)
-{
-       char *errmsg = "Unknown";
-
-       switch (status) {
-       case -ENOENT:
-               errmsg = "unlinked synchronuously";
-               break;
-       case -ECONNRESET:
-               errmsg = "unlinked asynchronuously";
-               break;
-       case -ENOSR:
-               errmsg = "Buffer error (overrun)";
-               break;
-       case -EPIPE:
-               errmsg = "Stalled (device not responding)";
-               break;
-       case -EOVERFLOW:
-               errmsg = "Babble (bad cable?)";
-               break;
-       case -EPROTO:
-               errmsg = "Bit-stuff error (bad cable?)";
-               break;
-       case -EILSEQ:
-               errmsg = "CRC/Timeout (could be anything)";
-               break;
-       case -ETIME:
-               errmsg = "Device does not respond";
-               break;
-       }
-       if (packet < 0) {
-               em28xx_isocdbg("URB status %d [%s].\n", status, errmsg);
-       } else {
-               em28xx_isocdbg("URB packet %d, status %d [%s].\n",
-                              packet, status, errmsg);
-       }
-}
-
-/*
- * video-buf generic routine to get the next available buffer
- */
-static inline void get_next_buf(struct em28xx_dmaqueue *dma_q,
-                                         struct em28xx_buffer **buf)
-{
-       struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
-       char *outp;
-
-       if (list_empty(&dma_q->active)) {
-               em28xx_isocdbg("No active queue to serve\n");
-               dev->isoc_ctl.vid_buf = NULL;
-               *buf = NULL;
-               return;
-       }
-
-       /* Get the next buffer */
-       *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
-
-       /* Cleans up buffer - Useful for testing for frame/URB loss */
-       outp = videobuf_to_vmalloc(&(*buf)->vb);
-       memset(outp, 0, (*buf)->vb.size);
-
-       dev->isoc_ctl.vid_buf = *buf;
-
-       return;
-}
-
-/*
- * video-buf generic routine to get the next available VBI buffer
- */
-static inline void vbi_get_next_buf(struct em28xx_dmaqueue *dma_q,
-                                   struct em28xx_buffer **buf)
-{
-       struct em28xx *dev = container_of(dma_q, struct em28xx, vbiq);
-       char *outp;
-
-       if (list_empty(&dma_q->active)) {
-               em28xx_isocdbg("No active queue to serve\n");
-               dev->isoc_ctl.vbi_buf = NULL;
-               *buf = NULL;
-               return;
-       }
-
-       /* Get the next buffer */
-       *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
-       /* Cleans up buffer - Useful for testing for frame/URB loss */
-       outp = videobuf_to_vmalloc(&(*buf)->vb);
-       memset(outp, 0x00, (*buf)->vb.size);
-
-       dev->isoc_ctl.vbi_buf = *buf;
-
-       return;
-}
-
-/*
- * Controls the isoc copy of each urb packet
- */
-static inline int em28xx_isoc_copy(struct em28xx *dev, struct urb *urb)
-{
-       struct em28xx_buffer    *buf;
-       struct em28xx_dmaqueue  *dma_q = &dev->vidq;
-       unsigned char *outp = NULL;
-       int i, len = 0, rc = 1;
-       unsigned char *p;
-
-       if (!dev)
-               return 0;
-
-       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
-               return 0;
-
-       if (urb->status < 0) {
-               print_err_status(dev, -1, urb->status);
-               if (urb->status == -ENOENT)
-                       return 0;
-       }
-
-       buf = dev->isoc_ctl.vid_buf;
-       if (buf != NULL)
-               outp = videobuf_to_vmalloc(&buf->vb);
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               int status = urb->iso_frame_desc[i].status;
-
-               if (status < 0) {
-                       print_err_status(dev, i, status);
-                       if (urb->iso_frame_desc[i].status != -EPROTO)
-                               continue;
-               }
-
-               len = urb->iso_frame_desc[i].actual_length - 4;
-
-               if (urb->iso_frame_desc[i].actual_length <= 0) {
-                       /* em28xx_isocdbg("packet %d is empty",i); - spammy */
-                       continue;
-               }
-               if (urb->iso_frame_desc[i].actual_length >
-                                               dev->max_pkt_size) {
-                       em28xx_isocdbg("packet bigger than packet size");
-                       continue;
-               }
-
-               p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-
-               /* FIXME: incomplete buffer checks where removed to make
-                  logic simpler. Impacts of those changes should be evaluated
-                */
-               if (p[0] == 0x33 && p[1] == 0x95 && p[2] == 0x00) {
-                       em28xx_isocdbg("VBI HEADER!!!\n");
-                       /* FIXME: Should add vbi copy */
-                       continue;
-               }
-               if (p[0] == 0x22 && p[1] == 0x5a) {
-                       em28xx_isocdbg("Video frame %d, length=%i, %s\n", p[2],
-                                      len, (p[2] & 1) ? "odd" : "even");
-
-                       if (dev->progressive || !(p[2] & 1)) {
-                               if (buf != NULL)
-                                       buffer_filled(dev, dma_q, buf);
-                               get_next_buf(dma_q, &buf);
-                               if (buf == NULL)
-                                       outp = NULL;
-                               else
-                                       outp = videobuf_to_vmalloc(&buf->vb);
-                       }
-
-                       if (buf != NULL) {
-                               if (p[2] & 1)
-                                       buf->top_field = 0;
-                               else
-                                       buf->top_field = 1;
-                       }
-
-                       dma_q->pos = 0;
-               }
-               if (buf != NULL) {
-                       if (p[0] != 0x88 && p[0] != 0x22) {
-                               em28xx_isocdbg("frame is not complete\n");
-                               len += 4;
-                       } else {
-                               p += 4;
-                       }
-                       em28xx_copy_video(dev, dma_q, buf, p, outp, len);
-               }
-       }
-       return rc;
-}
-
-/* Version of isoc handler that takes into account a mixture of video and
-   VBI data */
-static inline int em28xx_isoc_copy_vbi(struct em28xx *dev, struct urb *urb)
-{
-       struct em28xx_buffer    *buf, *vbi_buf;
-       struct em28xx_dmaqueue  *dma_q = &dev->vidq;
-       struct em28xx_dmaqueue  *vbi_dma_q = &dev->vbiq;
-       unsigned char *outp = NULL;
-       unsigned char *vbioutp = NULL;
-       int i, len = 0, rc = 1;
-       unsigned char *p;
-       int vbi_size;
-
-       if (!dev)
-               return 0;
-
-       if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
-               return 0;
-
-       if (urb->status < 0) {
-               print_err_status(dev, -1, urb->status);
-               if (urb->status == -ENOENT)
-                       return 0;
-       }
-
-       buf = dev->isoc_ctl.vid_buf;
-       if (buf != NULL)
-               outp = videobuf_to_vmalloc(&buf->vb);
-
-       vbi_buf = dev->isoc_ctl.vbi_buf;
-       if (vbi_buf != NULL)
-               vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               int status = urb->iso_frame_desc[i].status;
-
-               if (status < 0) {
-                       print_err_status(dev, i, status);
-                       if (urb->iso_frame_desc[i].status != -EPROTO)
-                               continue;
-               }
-
-               len = urb->iso_frame_desc[i].actual_length;
-               if (urb->iso_frame_desc[i].actual_length <= 0) {
-                       /* em28xx_isocdbg("packet %d is empty",i); - spammy */
-                       continue;
-               }
-               if (urb->iso_frame_desc[i].actual_length >
-                                               dev->max_pkt_size) {
-                       em28xx_isocdbg("packet bigger than packet size");
-                       continue;
-               }
-
-               p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-
-               /* capture type 0 = vbi start
-                  capture type 1 = video start
-                  capture type 2 = video in progress */
-               if (p[0] == 0x33 && p[1] == 0x95) {
-                       dev->capture_type = 0;
-                       dev->vbi_read = 0;
-                       em28xx_isocdbg("VBI START HEADER!!!\n");
-                       dev->cur_field = p[2];
-                       p += 4;
-                       len -= 4;
-               } else if (p[0] == 0x88 && p[1] == 0x88 &&
-                          p[2] == 0x88 && p[3] == 0x88) {
-                       /* continuation */
-                       p += 4;
-                       len -= 4;
-               } else if (p[0] == 0x22 && p[1] == 0x5a) {
-                       /* start video */
-                       p += 4;
-                       len -= 4;
-               }
-
-               vbi_size = dev->vbi_width * dev->vbi_height;
-
-               if (dev->capture_type == 0) {
-                       if (dev->vbi_read >= vbi_size) {
-                               /* We've already read all the VBI data, so
-                                  treat the rest as video */
-                               em28xx_isocdbg("dev->vbi_read > vbi_size\n");
-                       } else if ((dev->vbi_read + len) < vbi_size) {
-                               /* This entire frame is VBI data */
-                               if (dev->vbi_read == 0 &&
-                                   (!(dev->cur_field & 1))) {
-                                       /* Brand new frame */
-                                       if (vbi_buf != NULL)
-                                               vbi_buffer_filled(dev,
-                                                                 vbi_dma_q,
-                                                                 vbi_buf);
-                                       vbi_get_next_buf(vbi_dma_q, &vbi_buf);
-                                       if (vbi_buf == NULL)
-                                               vbioutp = NULL;
-                                       else
-                                               vbioutp = videobuf_to_vmalloc(
-                                                       &vbi_buf->vb);
-                               }
-
-                               if (dev->vbi_read == 0) {
-                                       vbi_dma_q->pos = 0;
-                                       if (vbi_buf != NULL) {
-                                               if (dev->cur_field & 1)
-                                                       vbi_buf->top_field = 0;
-                                               else
-                                                       vbi_buf->top_field = 1;
-                                       }
-                               }
-
-                               dev->vbi_read += len;
-                               em28xx_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
-                                               vbioutp, len);
-                       } else {
-                               /* Some of this frame is VBI data and some is
-                                  video data */
-                               int vbi_data_len = vbi_size - dev->vbi_read;
-                               dev->vbi_read += vbi_data_len;
-                               em28xx_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
-                                               vbioutp, vbi_data_len);
-                               dev->capture_type = 1;
-                               p += vbi_data_len;
-                               len -= vbi_data_len;
-                       }
-               }
-
-               if (dev->capture_type == 1) {
-                       dev->capture_type = 2;
-                       if (dev->progressive || !(dev->cur_field & 1)) {
-                               if (buf != NULL)
-                                       buffer_filled(dev, dma_q, buf);
-                               get_next_buf(dma_q, &buf);
-                               if (buf == NULL)
-                                       outp = NULL;
-                               else
-                                       outp = videobuf_to_vmalloc(&buf->vb);
-                       }
-                       if (buf != NULL) {
-                               if (dev->cur_field & 1)
-                                       buf->top_field = 0;
-                               else
-                                       buf->top_field = 1;
-                       }
-
-                       dma_q->pos = 0;
-               }
-
-               if (buf != NULL && dev->capture_type == 2) {
-                       if (len >= 4 && p[0] == 0x88 && p[1] == 0x88 &&
-                           p[2] == 0x88 && p[3] == 0x88) {
-                               p += 4;
-                               len -= 4;
-                       }
-                       if (len >= 4 && p[0] == 0x22 && p[1] == 0x5a) {
-                               em28xx_isocdbg("Video frame %d, len=%i, %s\n",
-                                              p[2], len, (p[2] & 1) ?
-                                              "odd" : "even");
-                               p += 4;
-                               len -= 4;
-                       }
-
-                       if (len > 0)
-                               em28xx_copy_video(dev, dma_q, buf, p, outp,
-                                                 len);
-               }
-       }
-       return rc;
-}
-
-
-/* ------------------------------------------------------------------
-       Videobuf operations
-   ------------------------------------------------------------------*/
-
-static int
-buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
-{
-       struct em28xx_fh *fh = vq->priv_data;
-       struct em28xx        *dev = fh->dev;
-       struct v4l2_frequency f;
-
-       *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7)
-               >> 3;
-
-       if (0 == *count)
-               *count = EM28XX_DEF_BUF;
-
-       if (*count < EM28XX_MIN_BUF)
-               *count = EM28XX_MIN_BUF;
-
-       /* Ask tuner to go to analog or radio mode */
-       memset(&f, 0, sizeof(f));
-       f.frequency = dev->ctl_freq;
-       f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
-
-       return 0;
-}
-
-/* This is called *without* dev->slock held; please keep it that way */
-static void free_buffer(struct videobuf_queue *vq, struct em28xx_buffer *buf)
-{
-       struct em28xx_fh     *fh  = vq->priv_data;
-       struct em28xx        *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.vid_buf == buf)
-               dev->isoc_ctl.vid_buf = NULL;
-       spin_unlock_irqrestore(&dev->slock, flags);
-
-       videobuf_vmalloc_free(&buf->vb);
-       buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int
-buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
-                                               enum v4l2_field field)
-{
-       struct em28xx_fh     *fh  = vq->priv_data;
-       struct em28xx_buffer *buf = container_of(vb, struct em28xx_buffer, vb);
-       struct em28xx        *dev = fh->dev;
-       int                  rc = 0, urb_init = 0;
-
-       buf->vb.size = (fh->dev->width * fh->dev->height * dev->format->depth
-                       + 7) >> 3;
-
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
-               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)
-                       goto fail;
-       }
-
-       if (!dev->isoc_ctl.analog_bufs.num_bufs)
-               urb_init = 1;
-
-       if (urb_init) {
-               if (em28xx_vbi_supported(dev) == 1)
-                       rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE,
-                                             EM28XX_NUM_PACKETS,
-                                             EM28XX_NUM_BUFS,
-                                             dev->max_pkt_size,
-                                             em28xx_isoc_copy_vbi);
-               else
-                       rc = em28xx_init_isoc(dev, EM28XX_ANALOG_MODE,
-                                             EM28XX_NUM_PACKETS,
-                                             EM28XX_NUM_BUFS,
-                                             dev->max_pkt_size,
-                                             em28xx_isoc_copy);
-               if (rc < 0)
-                       goto fail;
-       }
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
-fail:
-       free_buffer(vq, buf);
-       return rc;
-}
-
-static void
-buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-       struct em28xx_buffer    *buf     = container_of(vb,
-                                                       struct em28xx_buffer,
-                                                       vb);
-       struct em28xx_fh        *fh      = vq->priv_data;
-       struct em28xx           *dev     = fh->dev;
-       struct em28xx_dmaqueue  *vidq    = &dev->vidq;
-
-       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 em28xx_buffer   *buf  = container_of(vb,
-                                                   struct em28xx_buffer,
-                                                   vb);
-       struct em28xx_fh       *fh   = vq->priv_data;
-       struct em28xx          *dev  = (struct em28xx *)fh->dev;
-
-       em28xx_isocdbg("em28xx: called buffer_release\n");
-
-       free_buffer(vq, buf);
-}
-
-static struct videobuf_queue_ops em28xx_video_qops = {
-       .buf_setup      = buffer_setup,
-       .buf_prepare    = buffer_prepare,
-       .buf_queue      = buffer_queue,
-       .buf_release    = buffer_release,
-};
-
-/*********************  v4l2 interface  **************************************/
-
-static void video_mux(struct em28xx *dev, int index)
-{
-       dev->ctl_input = index;
-       dev->ctl_ainput = INPUT(index)->amux;
-       dev->ctl_aoutput = INPUT(index)->aout;
-
-       if (!dev->ctl_aoutput)
-               dev->ctl_aoutput = EM28XX_AOUT_MASTER;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
-                       INPUT(index)->vmux, 0, 0);
-
-       if (dev->board.has_msp34xx) {
-               if (dev->i2s_speed) {
-                       v4l2_device_call_all(&dev->v4l2_dev, 0, audio,
-                               s_i2s_clock_freq, dev->i2s_speed);
-               }
-               /* Note: this is msp3400 specific */
-               v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
-                        dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
-       }
-
-       if (dev->board.adecoder != EM28XX_NOADECODER) {
-               v4l2_device_call_all(&dev->v4l2_dev, 0, audio, s_routing,
-                       dev->ctl_ainput, dev->ctl_aoutput, 0);
-       }
-
-       em28xx_audio_analog_set(dev);
-}
-
-/* Usage lock check functions */
-static int res_get(struct em28xx_fh *fh, unsigned int bit)
-{
-       struct em28xx    *dev = fh->dev;
-
-       if (fh->resources & bit)
-               /* have it already allocated */
-               return 1;
-
-       /* is it free? */
-       if (dev->resources & bit) {
-               /* no, someone else uses it */
-               return 0;
-       }
-       /* it's free, grab it */
-       fh->resources  |= bit;
-       dev->resources |= bit;
-       em28xx_videodbg("res: get %d\n", bit);
-       return 1;
-}
-
-static int res_check(struct em28xx_fh *fh, unsigned int bit)
-{
-       return fh->resources & bit;
-}
-
-static int res_locked(struct em28xx *dev, unsigned int bit)
-{
-       return dev->resources & bit;
-}
-
-static void res_free(struct em28xx_fh *fh, unsigned int bits)
-{
-       struct em28xx    *dev = fh->dev;
-
-       BUG_ON((fh->resources & bits) != bits);
-
-       fh->resources  &= ~bits;
-       dev->resources &= ~bits;
-       em28xx_videodbg("res: put %d\n", bits);
-}
-
-static int get_ressource(struct em28xx_fh *fh)
-{
-       switch (fh->type) {
-       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               return EM28XX_RESOURCE_VIDEO;
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               return EM28XX_RESOURCE_VBI;
-       default:
-               BUG();
-               return 0;
-       }
-}
-
-/*
- * ac97_queryctrl()
- * return the ac97 supported controls
- */
-static int ac97_queryctrl(struct v4l2_queryctrl *qc)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) {
-               if (qc->id && qc->id == ac97_qctrl[i].id) {
-                       memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc));
-                       return 0;
-               }
-       }
-
-       /* Control is not ac97 related */
-       return 1;
-}
-
-/*
- * ac97_get_ctrl()
- * return the current values for ac97 mute and volume
- */
-static int ac97_get_ctrl(struct em28xx *dev, struct v4l2_control *ctrl)
-{
-       switch (ctrl->id) {
-       case V4L2_CID_AUDIO_MUTE:
-               ctrl->value = dev->mute;
-               return 0;
-       case V4L2_CID_AUDIO_VOLUME:
-               ctrl->value = dev->volume;
-               return 0;
-       default:
-               /* Control is not ac97 related */
-               return 1;
-       }
-}
-
-/*
- * ac97_set_ctrl()
- * set values for ac97 mute and volume
- */
-static int ac97_set_ctrl(struct em28xx *dev, const struct v4l2_control *ctrl)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++)
-               if (ctrl->id == ac97_qctrl[i].id)
-                       goto handle;
-
-       /* Announce that hasn't handle it */
-       return 1;
-
-handle:
-       if (ctrl->value < ac97_qctrl[i].minimum ||
-           ctrl->value > ac97_qctrl[i].maximum)
-               return -ERANGE;
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUDIO_MUTE:
-               dev->mute = ctrl->value;
-               break;
-       case V4L2_CID_AUDIO_VOLUME:
-               dev->volume = ctrl->value;
-               break;
-       }
-
-       return em28xx_audio_analog_set(dev);
-}
-
-static int check_dev(struct em28xx *dev)
-{
-       if (dev->state & DEV_DISCONNECTED) {
-               em28xx_errdev("v4l2 ioctl: device not present\n");
-               return -ENODEV;
-       }
-
-       if (dev->state & DEV_MISCONFIGURED) {
-               em28xx_errdev("v4l2 ioctl: device is misconfigured; "
-                             "close and open it again\n");
-               return -EIO;
-       }
-       return 0;
-}
-
-static void get_scale(struct em28xx *dev,
-                       unsigned int width, unsigned int height,
-                       unsigned int *hscale, unsigned int *vscale)
-{
-       unsigned int          maxw = norm_maxw(dev);
-       unsigned int          maxh = norm_maxh(dev);
-
-       *hscale = (((unsigned long)maxw) << 12) / width - 4096L;
-       if (*hscale >= 0x4000)
-               *hscale = 0x3fff;
-
-       *vscale = (((unsigned long)maxh) << 12) / height - 4096L;
-       if (*vscale >= 0x4000)
-               *vscale = 0x3fff;
-}
-
-/* ------------------------------------------------------------------
-       IOCTL vidioc handling
-   ------------------------------------------------------------------*/
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-
-       f->fmt.pix.width = dev->width;
-       f->fmt.pix.height = dev->height;
-       f->fmt.pix.pixelformat = dev->format->fourcc;
-       f->fmt.pix.bytesperline = (dev->width * dev->format->depth + 7) >> 3;
-       f->fmt.pix.sizeimage = f->fmt.pix.bytesperline  * dev->height;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-
-       /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */
-       if (dev->progressive)
-               f->fmt.pix.field = V4L2_FIELD_NONE;
-       else
-               f->fmt.pix.field = dev->interlaced ?
-                          V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
-       return 0;
-}
-
-static struct em28xx_fmt *format_by_fourcc(unsigned int fourcc)
-{
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(format); i++)
-               if (format[i].fourcc == fourcc)
-                       return &format[i];
-
-       return NULL;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                       struct v4l2_format *f)
-{
-       struct em28xx_fh      *fh    = priv;
-       struct em28xx         *dev   = fh->dev;
-       unsigned int          width  = f->fmt.pix.width;
-       unsigned int          height = f->fmt.pix.height;
-       unsigned int          maxw   = norm_maxw(dev);
-       unsigned int          maxh   = norm_maxh(dev);
-       unsigned int          hscale, vscale;
-       struct em28xx_fmt     *fmt;
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-       if (!fmt) {
-               em28xx_videodbg("Fourcc format (%08x) invalid.\n",
-                               f->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       if (dev->board.is_em2800) {
-               /* the em2800 can only scale down to 50% */
-               height = height > (3 * maxh / 4) ? maxh : maxh / 2;
-               width = width > (3 * maxw / 4) ? maxw : maxw / 2;
-                /* MaxPacketSize for em2800 is too small to capture at full resolution
-                 * use half of maxw as the scaler can only scale to 50% */
-               if (width == maxw && height == maxh)
-                       width /= 2;
-       } else {
-               /* width must even because of the YUYV format
-                  height must be even because of interlacing */
-               v4l_bound_align_image(&width, 48, maxw, 1, &height, 32, maxh,
-                                     1, 0);
-       }
-
-       get_scale(dev, width, height, &hscale, &vscale);
-
-       width = (((unsigned long)maxw) << 12) / (hscale + 4096L);
-       height = (((unsigned long)maxh) << 12) / (vscale + 4096L);
-
-       f->fmt.pix.width = width;
-       f->fmt.pix.height = height;
-       f->fmt.pix.pixelformat = fmt->fourcc;
-       f->fmt.pix.bytesperline = (dev->width * fmt->depth + 7) >> 3;
-       f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       if (dev->progressive)
-               f->fmt.pix.field = V4L2_FIELD_NONE;
-       else
-               f->fmt.pix.field = dev->interlaced ?
-                          V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP;
-
-       return 0;
-}
-
-static int em28xx_set_video_format(struct em28xx *dev, unsigned int fourcc,
-                                  unsigned width, unsigned height)
-{
-       struct em28xx_fmt     *fmt;
-
-       fmt = format_by_fourcc(fourcc);
-       if (!fmt)
-               return -EINVAL;
-
-       dev->format = fmt;
-       dev->width  = width;
-       dev->height = height;
-
-       /* set new image size */
-       get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
-
-       em28xx_set_alternate(dev);
-       em28xx_resolution_set(dev);
-
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                       struct v4l2_format *f)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       vidioc_try_fmt_vid_cap(file, priv, f);
-
-       if (videobuf_queue_is_busy(&fh->vb_vidq)) {
-               em28xx_errdev("%s queue busy\n", __func__);
-               return -EBUSY;
-       }
-
-       return em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
-                               f->fmt.pix.width, f->fmt.pix.height);
-}
-
-static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
-{
-       struct em28xx_fh   *fh  = priv;
-       struct em28xx      *dev = fh->dev;
-       int                rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       *norm = dev->norm;
-
-       return 0;
-}
-
-static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
-{
-       struct em28xx_fh   *fh  = priv;
-       struct em28xx      *dev = fh->dev;
-       int                rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm);
-
-       return 0;
-}
-
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
-{
-       struct em28xx_fh   *fh  = priv;
-       struct em28xx      *dev = fh->dev;
-       struct v4l2_format f;
-       int                rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       dev->norm = *norm;
-
-       /* Adjusts width/height, if needed */
-       f.fmt.pix.width = dev->width;
-       f.fmt.pix.height = dev->height;
-       vidioc_try_fmt_vid_cap(file, priv, &f);
-
-       /* set new image size */
-       dev->width = f.fmt.pix.width;
-       dev->height = f.fmt.pix.height;
-       get_scale(dev, dev->width, dev->height, &dev->hscale, &dev->vscale);
-
-       em28xx_resolution_set(dev);
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
-
-       return 0;
-}
-
-static int vidioc_g_parm(struct file *file, void *priv,
-                        struct v4l2_streamparm *p)
-{
-       struct em28xx_fh   *fh  = priv;
-       struct em28xx      *dev = fh->dev;
-       int rc = 0;
-
-       if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       if (dev->board.is_webcam)
-               rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0,
-                                               video, g_parm, p);
-       else
-               v4l2_video_std_frame_period(dev->norm,
-                                                &p->parm.capture.timeperframe);
-
-       return rc;
-}
-
-static int vidioc_s_parm(struct file *file, void *priv,
-                        struct v4l2_streamparm *p)
-{
-       struct em28xx_fh   *fh  = priv;
-       struct em28xx      *dev = fh->dev;
-
-       if (!dev->board.is_webcam)
-               return -EINVAL;
-
-       if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       return v4l2_device_call_until_err(&dev->v4l2_dev, 0, video, s_parm, p);
-}
-
-static const char *iname[] = {
-       [EM28XX_VMUX_COMPOSITE1] = "Composite1",
-       [EM28XX_VMUX_COMPOSITE2] = "Composite2",
-       [EM28XX_VMUX_COMPOSITE3] = "Composite3",
-       [EM28XX_VMUX_COMPOSITE4] = "Composite4",
-       [EM28XX_VMUX_SVIDEO]     = "S-Video",
-       [EM28XX_VMUX_TELEVISION] = "Television",
-       [EM28XX_VMUX_CABLE]      = "Cable TV",
-       [EM28XX_VMUX_DVB]        = "DVB",
-       [EM28XX_VMUX_DEBUG]      = "for debug only",
-};
-
-static int vidioc_enum_input(struct file *file, void *priv,
-                               struct v4l2_input *i)
-{
-       struct em28xx_fh   *fh  = priv;
-       struct em28xx      *dev = fh->dev;
-       unsigned int       n;
-
-       n = i->index;
-       if (n >= MAX_EM28XX_INPUT)
-               return -EINVAL;
-       if (0 == INPUT(n)->type)
-               return -EINVAL;
-
-       i->index = n;
-       i->type = V4L2_INPUT_TYPE_CAMERA;
-
-       strcpy(i->name, iname[INPUT(n)->type]);
-
-       if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
-               (EM28XX_VMUX_CABLE == INPUT(n)->type))
-               i->type = V4L2_INPUT_TYPE_TUNER;
-
-       i->std = dev->vdev->tvnorms;
-
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       struct em28xx_fh   *fh  = priv;
-       struct em28xx      *dev = fh->dev;
-
-       *i = dev->ctl_input;
-
-       return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       struct em28xx_fh   *fh  = priv;
-       struct em28xx      *dev = fh->dev;
-       int                rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (i >= MAX_EM28XX_INPUT)
-               return -EINVAL;
-       if (0 == INPUT(i)->type)
-               return -EINVAL;
-
-       video_mux(dev, i);
-       return 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-       struct em28xx_fh   *fh    = priv;
-       struct em28xx      *dev   = fh->dev;
-
-       if (!dev->audio_mode.has_audio)
-               return -EINVAL;
-
-       switch (a->index) {
-       case EM28XX_AMUX_VIDEO:
-               strcpy(a->name, "Television");
-               break;
-       case EM28XX_AMUX_LINE_IN:
-               strcpy(a->name, "Line In");
-               break;
-       case EM28XX_AMUX_VIDEO2:
-               strcpy(a->name, "Television alt");
-               break;
-       case EM28XX_AMUX_PHONE:
-               strcpy(a->name, "Phone");
-               break;
-       case EM28XX_AMUX_MIC:
-               strcpy(a->name, "Mic");
-               break;
-       case EM28XX_AMUX_CD:
-               strcpy(a->name, "CD");
-               break;
-       case EM28XX_AMUX_AUX:
-               strcpy(a->name, "Aux");
-               break;
-       case EM28XX_AMUX_PCM_OUT:
-               strcpy(a->name, "PCM");
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       a->index = dev->ctl_ainput;
-       a->capability = V4L2_AUDCAP_STEREO;
-
-       return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-       struct em28xx_fh   *fh  = priv;
-       struct em28xx      *dev = fh->dev;
-
-
-       if (!dev->audio_mode.has_audio)
-               return -EINVAL;
-
-       if (a->index >= MAX_EM28XX_INPUT)
-               return -EINVAL;
-       if (0 == INPUT(a->index)->type)
-               return -EINVAL;
-
-       dev->ctl_ainput = INPUT(a->index)->amux;
-       dev->ctl_aoutput = INPUT(a->index)->aout;
-
-       if (!dev->ctl_aoutput)
-               dev->ctl_aoutput = EM28XX_AOUT_MASTER;
-
-       return 0;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-                               struct v4l2_queryctrl *qc)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   id  = qc->id;
-       int                   rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       memset(qc, 0, sizeof(*qc));
-
-       qc->id = id;
-
-       /* enumerate AC97 controls */
-       if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
-               rc = ac97_queryctrl(qc);
-               if (!rc)
-                       return 0;
-       }
-
-       /* enumerate V4L2 device controls */
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, qc);
-
-       if (qc->type)
-               return 0;
-       else
-               return -EINVAL;
-}
-
-/*
- * FIXME: This is an indirect way to check if a control exists at a
- * subdev. Instead of that hack, maybe the better would be to change all
- * subdevs to return -ENOIOCTLCMD, if an ioctl is not supported.
- */
-static int check_subdev_ctrl(struct em28xx *dev, int id)
-{
-       struct v4l2_queryctrl qc;
-
-       memset(&qc, 0, sizeof(qc));
-       qc.id = id;
-
-       /* enumerate V4L2 device controls */
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, &qc);
-
-       if (qc.type)
-               return 0;
-       else
-               return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctrl)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-       rc = 0;
-
-       /* Set an AC97 control */
-       if (dev->audio_mode.ac97 != EM28XX_NO_AC97)
-               rc = ac97_get_ctrl(dev, ctrl);
-       else
-               rc = 1;
-
-       /* It were not an AC97 control. Sends it to the v4l2 dev interface */
-       if (rc == 1) {
-               if (check_subdev_ctrl(dev, ctrl->id))
-                       return -EINVAL;
-
-               v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
-               rc = 0;
-       }
-
-       return rc;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctrl)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       /* Set an AC97 control */
-       if (dev->audio_mode.ac97 != EM28XX_NO_AC97)
-               rc = ac97_set_ctrl(dev, ctrl);
-       else
-               rc = 1;
-
-       /* It isn't an AC97 control. Sends it to the v4l2 dev interface */
-       if (rc == 1) {
-               rc = check_subdev_ctrl(dev, ctrl->id);
-               if (!rc)
-                       v4l2_device_call_all(&dev->v4l2_dev, 0,
-                                            core, s_ctrl, ctrl);
-               /*
-                * In the case of non-AC97 volume controls, we still need
-                * to do some setups at em28xx, in order to mute/unmute
-                * and to adjust audio volume. However, the value ranges
-                * should be checked by the corresponding V4L subdriver.
-                */
-               switch (ctrl->id) {
-               case V4L2_CID_AUDIO_MUTE:
-                       dev->mute = ctrl->value;
-                       rc = em28xx_audio_analog_set(dev);
-                       break;
-               case V4L2_CID_AUDIO_VOLUME:
-                       dev->volume = ctrl->value;
-                       rc = em28xx_audio_analog_set(dev);
-               }
-       }
-       return (rc < 0) ? rc : 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (0 != t->index)
-               return -EINVAL;
-
-       strcpy(t->name, "Tuner");
-       t->type = V4L2_TUNER_ANALOG_TV;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
-       return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (0 != t->index)
-               return -EINVAL;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
-       return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *f)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-
-       f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-       f->frequency = dev->ctl_freq;
-       return 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *f)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (0 != f->tuner)
-               return -EINVAL;
-
-       if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV))
-               return -EINVAL;
-       if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO))
-               return -EINVAL;
-
-       dev->ctl_freq = f->frequency;
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f);
-
-       return 0;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int em28xx_reg_len(int reg)
-{
-       switch (reg) {
-       case EM28XX_R40_AC97LSB:
-       case EM28XX_R30_HSCALELOW:
-       case EM28XX_R32_VSCALELOW:
-               return 2;
-       default:
-               return 1;
-       }
-}
-
-static int vidioc_g_chip_ident(struct file *file, void *priv,
-              struct v4l2_dbg_chip_ident *chip)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-
-       chip->ident = V4L2_IDENT_NONE;
-       chip->revision = 0;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_chip_ident, chip);
-
-       return 0;
-}
-
-
-static int vidioc_g_register(struct file *file, void *priv,
-                            struct v4l2_dbg_register *reg)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int ret;
-
-       switch (reg->match.type) {
-       case V4L2_CHIP_MATCH_AC97:
-               ret = em28xx_read_ac97(dev, reg->reg);
-               if (ret < 0)
-                       return ret;
-
-               reg->val = ret;
-               reg->size = 1;
-               return 0;
-       case V4L2_CHIP_MATCH_I2C_DRIVER:
-               v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
-               return 0;
-       case V4L2_CHIP_MATCH_I2C_ADDR:
-               /* TODO: is this correct? */
-               v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
-               return 0;
-       default:
-               if (!v4l2_chip_match_host(&reg->match))
-                       return -EINVAL;
-       }
-
-       /* Match host */
-       reg->size = em28xx_reg_len(reg->reg);
-       if (reg->size == 1) {
-               ret = em28xx_read_reg(dev, reg->reg);
-
-               if (ret < 0)
-                       return ret;
-
-               reg->val = ret;
-       } else {
-               __le16 val = 0;
-               ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
-                                                  reg->reg, (char *)&val, 2);
-               if (ret < 0)
-                       return ret;
-
-               reg->val = le16_to_cpu(val);
-       }
-
-       return 0;
-}
-
-static int vidioc_s_register(struct file *file, void *priv,
-                            struct v4l2_dbg_register *reg)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       __le16 buf;
-
-       switch (reg->match.type) {
-       case V4L2_CHIP_MATCH_AC97:
-               return em28xx_write_ac97(dev, reg->reg, reg->val);
-       case V4L2_CHIP_MATCH_I2C_DRIVER:
-               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
-               return 0;
-       case V4L2_CHIP_MATCH_I2C_ADDR:
-               /* TODO: is this correct? */
-               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
-               return 0;
-       default:
-               if (!v4l2_chip_match_host(&reg->match))
-                       return -EINVAL;
-       }
-
-       /* Match host */
-       buf = cpu_to_le16(reg->val);
-
-       return em28xx_write_regs(dev, reg->reg, (char *)&buf,
-                              em28xx_reg_len(reg->reg));
-}
-#endif
-
-
-static int vidioc_cropcap(struct file *file, void *priv,
-                                       struct v4l2_cropcap *cc)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-
-       if (cc->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       cc->bounds.left = 0;
-       cc->bounds.top = 0;
-       cc->bounds.width = dev->width;
-       cc->bounds.height = dev->height;
-       cc->defrect = cc->bounds;
-       cc->pixelaspect.numerator = 54; /* 4:3 FIXME: remove magic numbers */
-       cc->pixelaspect.denominator = 59;
-
-       return 0;
-}
-
-static int vidioc_streamon(struct file *file, void *priv,
-                                       enum v4l2_buf_type type)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   rc = -EINVAL;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (unlikely(type != fh->type))
-               return -EINVAL;
-
-       em28xx_videodbg("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;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               rc = videobuf_streamon(&fh->vb_vidq);
-       else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
-               rc = videobuf_streamon(&fh->vb_vbiq);
-
-       return rc;
-}
-
-static int vidioc_streamoff(struct file *file, void *priv,
-                                       enum v4l2_buf_type type)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   rc;
-
-       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;
-
-       em28xx_videodbg("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) {
-               if (res_check(fh, EM28XX_RESOURCE_VIDEO)) {
-                       videobuf_streamoff(&fh->vb_vidq);
-                       res_free(fh, EM28XX_RESOURCE_VIDEO);
-               }
-       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-               if (res_check(fh, EM28XX_RESOURCE_VBI)) {
-                       videobuf_streamoff(&fh->vb_vbiq);
-                       res_free(fh, EM28XX_RESOURCE_VBI);
-               }
-       }
-
-       return 0;
-}
-
-static int vidioc_querycap(struct file *file, void  *priv,
-                                       struct v4l2_capability *cap)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-
-       strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
-       strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
-       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
-
-       cap->capabilities =
-                       V4L2_CAP_SLICED_VBI_CAPTURE |
-                       V4L2_CAP_VIDEO_CAPTURE |
-                       V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
-
-       if (dev->vbi_dev)
-               cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
-
-       if (dev->audio_mode.has_audio)
-               cap->capabilities |= V4L2_CAP_AUDIO;
-
-       if (dev->tuner_type != TUNER_ABSENT)
-               cap->capabilities |= V4L2_CAP_TUNER;
-
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       if (unlikely(f->index >= ARRAY_SIZE(format)))
-               return -EINVAL;
-
-       strlcpy(f->description, format[f->index].name, sizeof(f->description));
-       f->pixelformat = format[f->index].fourcc;
-
-       return 0;
-}
-
-static int vidioc_enum_framesizes(struct file *file, void *priv,
-                                 struct v4l2_frmsizeenum *fsize)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       struct em28xx_fmt     *fmt;
-       unsigned int          maxw = norm_maxw(dev);
-       unsigned int          maxh = norm_maxh(dev);
-
-       fmt = format_by_fourcc(fsize->pixel_format);
-       if (!fmt) {
-               em28xx_videodbg("Fourcc format (%08x) invalid.\n",
-                               fsize->pixel_format);
-               return -EINVAL;
-       }
-
-       if (dev->board.is_em2800) {
-               if (fsize->index > 1)
-                       return -EINVAL;
-               fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-               fsize->discrete.width = maxw / (1 + fsize->index);
-               fsize->discrete.height = maxh / (1 + fsize->index);
-               return 0;
-       }
-
-       if (fsize->index != 0)
-               return -EINVAL;
-
-       /* Report a continuous range */
-       fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
-       fsize->stepwise.min_width = 48;
-       fsize->stepwise.min_height = 32;
-       fsize->stepwise.max_width = maxw;
-       fsize->stepwise.max_height = maxh;
-       fsize->stepwise.step_width = 1;
-       fsize->stepwise.step_height = 1;
-       return 0;
-}
-
-/* Sliced VBI ioctls */
-static int vidioc_g_fmt_sliced_vbi_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       f->fmt.sliced.service_set = 0;
-       v4l2_device_call_all(&dev->v4l2_dev, 0, vbi, g_sliced_fmt, &f->fmt.sliced);
-
-       if (f->fmt.sliced.service_set == 0)
-               rc = -EINVAL;
-
-       return rc;
-}
-
-static int vidioc_try_set_sliced_vbi_cap(struct file *file, void *priv,
-                       struct v4l2_format *f)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, vbi, g_sliced_fmt, &f->fmt.sliced);
-
-       if (f->fmt.sliced.service_set == 0)
-               return -EINVAL;
-
-       return 0;
-}
-
-/* RAW VBI ioctls */
-
-static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
-                               struct v4l2_format *format)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-
-       format->fmt.vbi.samples_per_line = dev->vbi_width;
-       format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
-       format->fmt.vbi.offset = 0;
-       format->fmt.vbi.flags = 0;
-       format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
-       format->fmt.vbi.count[0] = dev->vbi_height;
-       format->fmt.vbi.count[1] = dev->vbi_height;
-
-       /* Varies by video standard (NTSC, PAL, etc.) */
-       if (dev->norm & V4L2_STD_525_60) {
-               /* NTSC */
-               format->fmt.vbi.start[0] = 10;
-               format->fmt.vbi.start[1] = 273;
-       } else if (dev->norm & V4L2_STD_625_50) {
-               /* PAL */
-               format->fmt.vbi.start[0] = 6;
-               format->fmt.vbi.start[1] = 318;
-       }
-
-       return 0;
-}
-
-static int vidioc_s_fmt_vbi_cap(struct file *file, void *priv,
-                               struct v4l2_format *format)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-
-       format->fmt.vbi.samples_per_line = dev->vbi_width;
-       format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
-       format->fmt.vbi.offset = 0;
-       format->fmt.vbi.flags = 0;
-       format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
-       format->fmt.vbi.count[0] = dev->vbi_height;
-       format->fmt.vbi.count[1] = dev->vbi_height;
-
-       /* Varies by video standard (NTSC, PAL, etc.) */
-       if (dev->norm & V4L2_STD_525_60) {
-               /* NTSC */
-               format->fmt.vbi.start[0] = 10;
-               format->fmt.vbi.start[1] = 273;
-       } else if (dev->norm & V4L2_STD_625_50) {
-               /* PAL */
-               format->fmt.vbi.start[0] = 6;
-               format->fmt.vbi.start[1] = 318;
-       }
-
-       return 0;
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
-                         struct v4l2_requestbuffers *rb)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return videobuf_reqbufs(&fh->vb_vidq, rb);
-       else
-               return videobuf_reqbufs(&fh->vb_vbiq, rb);
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-                          struct v4l2_buffer *b)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return videobuf_querybuf(&fh->vb_vidq, b);
-       else {
-               /* FIXME: I'm not sure yet whether this is a bug in zvbi or
-                  the videobuf framework, but we probably shouldn't be
-                  returning a buffer larger than that which was asked for.
-                  At a minimum, it causes a crash in zvbi since it does
-                  a memcpy based on the source buffer length */
-               int result = videobuf_querybuf(&fh->vb_vbiq, b);
-               b->length = dev->vbi_width * dev->vbi_height * 2;
-
-               return result;
-       }
-}
-
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return videobuf_qbuf(&fh->vb_vidq, b);
-       else
-               return videobuf_qbuf(&fh->vb_vbiq, b);
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
-{
-       struct em28xx_fh      *fh  = priv;
-       struct em28xx         *dev = fh->dev;
-       int                   rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return videobuf_dqbuf(&fh->vb_vidq, b, file->f_flags &
-                                     O_NONBLOCK);
-       else
-               return videobuf_dqbuf(&fh->vb_vbiq, b, file->f_flags &
-                                     O_NONBLOCK);
-}
-
-/* ----------------------------------------------------------- */
-/* RADIO ESPECIFIC IOCTLS                                      */
-/* ----------------------------------------------------------- */
-
-static int radio_querycap(struct file *file, void  *priv,
-                         struct v4l2_capability *cap)
-{
-       struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
-
-       strlcpy(cap->driver, "em28xx", sizeof(cap->driver));
-       strlcpy(cap->card, em28xx_boards[dev->model].name, sizeof(cap->card));
-       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
-
-       cap->capabilities = V4L2_CAP_TUNER;
-       return 0;
-}
-
-static int radio_g_tuner(struct file *file, void *priv,
-                        struct v4l2_tuner *t)
-{
-       struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
-
-       if (unlikely(t->index > 0))
-               return -EINVAL;
-
-       strcpy(t->name, "Radio");
-       t->type = V4L2_TUNER_RADIO;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
-
-       return 0;
-}
-
-static int radio_enum_input(struct file *file, void *priv,
-                           struct v4l2_input *i)
-{
-       if (i->index != 0)
-               return -EINVAL;
-       strcpy(i->name, "Radio");
-       i->type = V4L2_INPUT_TYPE_TUNER;
-
-       return 0;
-}
-
-static int radio_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-       if (unlikely(a->index))
-               return -EINVAL;
-
-       strcpy(a->name, "Radio");
-       return 0;
-}
-
-static int radio_s_tuner(struct file *file, void *priv,
-                        struct v4l2_tuner *t)
-{
-       struct em28xx *dev = ((struct em28xx_fh *)priv)->dev;
-
-       if (0 != t->index)
-               return -EINVAL;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
-
-       return 0;
-}
-
-static int radio_s_audio(struct file *file, void *fh,
-                        struct v4l2_audio *a)
-{
-       return 0;
-}
-
-static int radio_s_input(struct file *file, void *fh, unsigned int i)
-{
-       return 0;
-}
-
-static int radio_queryctrl(struct file *file, void *priv,
-                          struct v4l2_queryctrl *qc)
-{
-       int i;
-
-       if (qc->id <  V4L2_CID_BASE ||
-               qc->id >= V4L2_CID_LASTP1)
-               return -EINVAL;
-
-       for (i = 0; i < ARRAY_SIZE(ac97_qctrl); i++) {
-               if (qc->id && qc->id == ac97_qctrl[i].id) {
-                       memcpy(qc, &(ac97_qctrl[i]), sizeof(*qc));
-                       return 0;
-               }
-       }
-
-       return -EINVAL;
-}
-
-/*
- * em28xx_v4l2_open()
- * inits the device and starts isoc transfer
- */
-static int em28xx_v4l2_open(struct file *filp)
-{
-       int errCode = 0, radio = 0;
-       struct video_device *vdev = video_devdata(filp);
-       struct em28xx *dev = video_drvdata(filp);
-       enum v4l2_buf_type fh_type = 0;
-       struct em28xx_fh *fh;
-       enum v4l2_field field;
-
-       switch (vdev->vfl_type) {
-       case VFL_TYPE_GRABBER:
-               fh_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               break;
-       case VFL_TYPE_VBI:
-               fh_type = V4L2_BUF_TYPE_VBI_CAPTURE;
-               break;
-       case VFL_TYPE_RADIO:
-               radio = 1;
-               break;
-       }
-
-       em28xx_videodbg("open dev=%s type=%s users=%d\n",
-                       video_device_node_name(vdev), v4l2_type_names[fh_type],
-                       dev->users);
-
-
-       if (mutex_lock_interruptible(&dev->lock))
-               return -ERESTARTSYS;
-       fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
-       if (!fh) {
-               em28xx_errdev("em28xx-video.c: Out of memory?!\n");
-               mutex_unlock(&dev->lock);
-               return -ENOMEM;
-       }
-       fh->dev = dev;
-       fh->radio = radio;
-       fh->type = fh_type;
-       filp->private_data = fh;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 0) {
-               em28xx_set_mode(dev, EM28XX_ANALOG_MODE);
-               em28xx_set_alternate(dev);
-               em28xx_resolution_set(dev);
-
-               /* Needed, since GPIO might have disabled power of
-                  some i2c device
-                */
-               em28xx_wake_i2c(dev);
-
-       }
-       if (fh->radio) {
-               em28xx_videodbg("video_open: setting radio device\n");
-               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio);
-       }
-
-       dev->users++;
-
-       if (dev->progressive)
-               field = V4L2_FIELD_NONE;
-       else
-               field = V4L2_FIELD_INTERLACED;
-
-       videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
-                                   NULL, &dev->slock,
-                                   V4L2_BUF_TYPE_VIDEO_CAPTURE, field,
-                                   sizeof(struct em28xx_buffer), fh, &dev->lock);
-
-       videobuf_queue_vmalloc_init(&fh->vb_vbiq, &em28xx_vbi_qops,
-                                   NULL, &dev->slock,
-                                   V4L2_BUF_TYPE_VBI_CAPTURE,
-                                   V4L2_FIELD_SEQ_TB,
-                                   sizeof(struct em28xx_buffer), fh, &dev->lock);
-       mutex_unlock(&dev->lock);
-
-       return errCode;
-}
-
-/*
- * em28xx_realease_resources()
- * unregisters the v4l2,i2c and usb devices
- * called when the device gets disconected or at module unload
-*/
-void em28xx_release_analog_resources(struct em28xx *dev)
-{
-
-       /*FIXME: I2C IR should be disconnected */
-
-       if (dev->radio_dev) {
-               if (video_is_registered(dev->radio_dev))
-                       video_unregister_device(dev->radio_dev);
-               else
-                       video_device_release(dev->radio_dev);
-               dev->radio_dev = NULL;
-       }
-       if (dev->vbi_dev) {
-               em28xx_info("V4L2 device %s deregistered\n",
-                           video_device_node_name(dev->vbi_dev));
-               if (video_is_registered(dev->vbi_dev))
-                       video_unregister_device(dev->vbi_dev);
-               else
-                       video_device_release(dev->vbi_dev);
-               dev->vbi_dev = NULL;
-       }
-       if (dev->vdev) {
-               em28xx_info("V4L2 device %s deregistered\n",
-                           video_device_node_name(dev->vdev));
-               if (video_is_registered(dev->vdev))
-                       video_unregister_device(dev->vdev);
-               else
-                       video_device_release(dev->vdev);
-               dev->vdev = NULL;
-       }
-}
-
-/*
- * em28xx_v4l2_close()
- * stops streaming and deallocates all resources allocated by the v4l2
- * calls and ioctls
- */
-static int em28xx_v4l2_close(struct file *filp)
-{
-       struct em28xx_fh *fh  = filp->private_data;
-       struct em28xx    *dev = fh->dev;
-       int              errCode;
-
-       em28xx_videodbg("users=%d\n", dev->users);
-
-       mutex_lock(&dev->lock);
-       if (res_check(fh, EM28XX_RESOURCE_VIDEO)) {
-               videobuf_stop(&fh->vb_vidq);
-               res_free(fh, EM28XX_RESOURCE_VIDEO);
-       }
-
-       if (res_check(fh, EM28XX_RESOURCE_VBI)) {
-               videobuf_stop(&fh->vb_vbiq);
-               res_free(fh, EM28XX_RESOURCE_VBI);
-       }
-
-       if (dev->users == 1) {
-               /* the device is already disconnect,
-                  free the remaining resources */
-               if (dev->state & DEV_DISCONNECTED) {
-                       em28xx_release_resources(dev);
-                       kfree(dev->alt_max_pkt_size);
-                       kfree(dev);
-                       kfree(fh);
-                       mutex_unlock(&dev->lock);
-                       return 0;
-               }
-
-               /* Save some power by putting tuner to sleep */
-               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_power, 0);
-
-               /* do this before setting alternate! */
-               em28xx_uninit_isoc(dev, EM28XX_ANALOG_MODE);
-               em28xx_set_mode(dev, EM28XX_SUSPEND);
-
-               /* set alternate 0 */
-               dev->alt = 0;
-               em28xx_videodbg("setting alternate 0\n");
-               errCode = usb_set_interface(dev->udev, 0, 0);
-               if (errCode < 0) {
-                       em28xx_errdev("cannot change alternate number to "
-                                       "0 (error=%i)\n", errCode);
-               }
-       }
-
-       videobuf_mmap_free(&fh->vb_vidq);
-       videobuf_mmap_free(&fh->vb_vbiq);
-       kfree(fh);
-       dev->users--;
-       mutex_unlock(&dev->lock);
-       return 0;
-}
-
-/*
- * em28xx_v4l2_read()
- * will allocate buffers when called for the first time
- */
-static ssize_t
-em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
-                loff_t *pos)
-{
-       struct em28xx_fh *fh = filp->private_data;
-       struct em28xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (mutex_lock_interruptible(&dev->lock))
-               return -ERESTARTSYS;
-       /* FIXME: read() is not prepared to allow changing the video
-          resolution while streaming. Seems a bug at em28xx_set_fmt
-        */
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               if (res_locked(dev, EM28XX_RESOURCE_VIDEO))
-                       rc = -EBUSY;
-               else
-                       rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
-                                       filp->f_flags & O_NONBLOCK);
-       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-               if (!res_get(fh, EM28XX_RESOURCE_VBI))
-                       rc = -EBUSY;
-               else
-                       rc = videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
-                                       filp->f_flags & O_NONBLOCK);
-       }
-       mutex_unlock(&dev->lock);
-
-       return rc;
-}
-
-/*
- * em28xx_poll()
- * will allocate buffers when called for the first time
- */
-static unsigned int em28xx_poll(struct file *filp, poll_table *wait)
-{
-       struct em28xx_fh *fh = filp->private_data;
-       struct em28xx *dev = fh->dev;
-       int rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               if (!res_get(fh, EM28XX_RESOURCE_VIDEO))
-                       return POLLERR;
-               return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
-       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
-               if (!res_get(fh, EM28XX_RESOURCE_VBI))
-                       return POLLERR;
-               return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
-       } else {
-               return POLLERR;
-       }
-}
-
-static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait)
-{
-       struct em28xx_fh *fh = filp->private_data;
-       struct em28xx *dev = fh->dev;
-       unsigned int res;
-
-       mutex_lock(&dev->lock);
-       res = em28xx_poll(filp, wait);
-       mutex_unlock(&dev->lock);
-       return res;
-}
-
-/*
- * em28xx_v4l2_mmap()
- */
-static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
-{
-       struct em28xx_fh *fh    = filp->private_data;
-       struct em28xx    *dev   = fh->dev;
-       int              rc;
-
-       rc = check_dev(dev);
-       if (rc < 0)
-               return rc;
-
-       if (mutex_lock_interruptible(&dev->lock))
-               return -ERESTARTSYS;
-       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);
-       mutex_unlock(&dev->lock);
-
-       em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
-               (unsigned long)vma->vm_start,
-               (unsigned long)vma->vm_end-(unsigned long)vma->vm_start,
-               rc);
-
-       return rc;
-}
-
-static const struct v4l2_file_operations em28xx_v4l_fops = {
-       .owner         = THIS_MODULE,
-       .open          = em28xx_v4l2_open,
-       .release       = em28xx_v4l2_close,
-       .read          = em28xx_v4l2_read,
-       .poll          = em28xx_v4l2_poll,
-       .mmap          = em28xx_v4l2_mmap,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops video_ioctl_ops = {
-       .vidioc_querycap            = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap    = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap       = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap     = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap       = vidioc_s_fmt_vid_cap,
-       .vidioc_g_fmt_vbi_cap       = vidioc_g_fmt_vbi_cap,
-       .vidioc_s_fmt_vbi_cap       = vidioc_s_fmt_vbi_cap,
-       .vidioc_enum_framesizes     = vidioc_enum_framesizes,
-       .vidioc_g_audio             = vidioc_g_audio,
-       .vidioc_s_audio             = vidioc_s_audio,
-       .vidioc_cropcap             = vidioc_cropcap,
-       .vidioc_g_fmt_sliced_vbi_cap   = vidioc_g_fmt_sliced_vbi_cap,
-       .vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
-       .vidioc_s_fmt_sliced_vbi_cap   = vidioc_try_set_sliced_vbi_cap,
-
-       .vidioc_reqbufs             = vidioc_reqbufs,
-       .vidioc_querybuf            = vidioc_querybuf,
-       .vidioc_qbuf                = vidioc_qbuf,
-       .vidioc_dqbuf               = vidioc_dqbuf,
-       .vidioc_g_std               = vidioc_g_std,
-       .vidioc_querystd            = vidioc_querystd,
-       .vidioc_s_std               = vidioc_s_std,
-       .vidioc_g_parm              = vidioc_g_parm,
-       .vidioc_s_parm              = vidioc_s_parm,
-       .vidioc_enum_input          = vidioc_enum_input,
-       .vidioc_g_input             = vidioc_g_input,
-       .vidioc_s_input             = vidioc_s_input,
-       .vidioc_queryctrl           = vidioc_queryctrl,
-       .vidioc_g_ctrl              = vidioc_g_ctrl,
-       .vidioc_s_ctrl              = vidioc_s_ctrl,
-       .vidioc_streamon            = vidioc_streamon,
-       .vidioc_streamoff           = vidioc_streamoff,
-       .vidioc_g_tuner             = vidioc_g_tuner,
-       .vidioc_s_tuner             = vidioc_s_tuner,
-       .vidioc_g_frequency         = vidioc_g_frequency,
-       .vidioc_s_frequency         = vidioc_s_frequency,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register          = vidioc_g_register,
-       .vidioc_s_register          = vidioc_s_register,
-       .vidioc_g_chip_ident        = vidioc_g_chip_ident,
-#endif
-};
-
-static const struct video_device em28xx_video_template = {
-       .fops                       = &em28xx_v4l_fops,
-       .release                    = video_device_release,
-       .ioctl_ops                  = &video_ioctl_ops,
-
-       .tvnorms                    = V4L2_STD_ALL,
-       .current_norm               = V4L2_STD_PAL,
-};
-
-static const struct v4l2_file_operations radio_fops = {
-       .owner         = THIS_MODULE,
-       .open          = em28xx_v4l2_open,
-       .release       = em28xx_v4l2_close,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops radio_ioctl_ops = {
-       .vidioc_querycap      = radio_querycap,
-       .vidioc_g_tuner       = radio_g_tuner,
-       .vidioc_enum_input    = radio_enum_input,
-       .vidioc_g_audio       = radio_g_audio,
-       .vidioc_s_tuner       = radio_s_tuner,
-       .vidioc_s_audio       = radio_s_audio,
-       .vidioc_s_input       = radio_s_input,
-       .vidioc_queryctrl     = radio_queryctrl,
-       .vidioc_g_ctrl        = vidioc_g_ctrl,
-       .vidioc_s_ctrl        = vidioc_s_ctrl,
-       .vidioc_g_frequency   = vidioc_g_frequency,
-       .vidioc_s_frequency   = vidioc_s_frequency,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register    = vidioc_g_register,
-       .vidioc_s_register    = vidioc_s_register,
-#endif
-};
-
-static struct video_device em28xx_radio_template = {
-       .name                 = "em28xx-radio",
-       .fops                 = &radio_fops,
-       .ioctl_ops            = &radio_ioctl_ops,
-};
-
-/******************************** usb interface ******************************/
-
-
-
-static struct video_device *em28xx_vdev_init(struct em28xx *dev,
-                                       const struct video_device *template,
-                                       const char *type_name)
-{
-       struct video_device *vfd;
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-
-       *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);
-
-       video_set_drvdata(vfd, dev);
-       return vfd;
-}
-
-int em28xx_register_analog_devices(struct em28xx *dev)
-{
-      u8 val;
-       int ret;
-       unsigned int maxw;
-
-       printk(KERN_INFO "%s: v4l2 driver version %s\n",
-               dev->name, EM28XX_VERSION);
-
-       /* set default norm */
-       dev->norm = em28xx_video_template.current_norm;
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
-       dev->interlaced = EM28XX_INTERLACED_DEFAULT;
-
-       /* Analog specific initialization */
-       dev->format = &format[0];
-
-       maxw = norm_maxw(dev);
-        /* MaxPacketSize for em2800 is too small to capture at full resolution
-         * use half of maxw as the scaler can only scale to 50% */
-        if (dev->board.is_em2800)
-            maxw /= 2;
-
-       em28xx_set_video_format(dev, format[0].fourcc,
-                               maxw, norm_maxh(dev));
-
-       video_mux(dev, 0);
-
-       /* Audio defaults */
-       dev->mute = 1;
-       dev->volume = 0x1f;
-
-/*     em28xx_write_reg(dev, EM28XX_R0E_AUDIOSRC, 0xc0); audio register */
-       val = (u8)em28xx_read_reg(dev, EM28XX_R0F_XCLK);
-       em28xx_write_reg(dev, EM28XX_R0F_XCLK,
-                        (EM28XX_XCLK_AUDIO_UNMUTE | val));
-
-       em28xx_set_outfmt(dev);
-       em28xx_colorlevels_set_default(dev);
-       em28xx_compression_disable(dev);
-
-       /* allocate and fill video video_device struct */
-       dev->vdev = em28xx_vdev_init(dev, &em28xx_video_template, "video");
-       if (!dev->vdev) {
-               em28xx_errdev("cannot allocate video_device.\n");
-               return -ENODEV;
-       }
-
-       /* register v4l2 video video_device */
-       ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
-                                      video_nr[dev->devno]);
-       if (ret) {
-               em28xx_errdev("unable to register video device (error=%i).\n",
-                             ret);
-               return ret;
-       }
-
-       /* Allocate and fill vbi video_device struct */
-       if (em28xx_vbi_supported(dev) == 1) {
-               dev->vbi_dev = em28xx_vdev_init(dev, &em28xx_video_template,
-                                               "vbi");
-
-               /* register v4l2 vbi video_device */
-               ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
-                                           vbi_nr[dev->devno]);
-               if (ret < 0) {
-                       em28xx_errdev("unable to register vbi device\n");
-                       return ret;
-               }
-       }
-
-       if (em28xx_boards[dev->model].radio.type == EM28XX_RADIO) {
-               dev->radio_dev = em28xx_vdev_init(dev, &em28xx_radio_template,
-                                                 "radio");
-               if (!dev->radio_dev) {
-                       em28xx_errdev("cannot allocate video_device.\n");
-                       return -ENODEV;
-               }
-               ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
-                                           radio_nr[dev->devno]);
-               if (ret < 0) {
-                       em28xx_errdev("can't register radio device\n");
-                       return ret;
-               }
-               em28xx_info("Registered radio device as %s\n",
-                           video_device_node_name(dev->radio_dev));
-       }
-
-       em28xx_info("V4L2 video device registered as %s\n",
-                   video_device_node_name(dev->vdev));
-
-       if (dev->vbi_dev)
-               em28xx_info("V4L2 VBI device registered as %s\n",
-                           video_device_node_name(dev->vbi_dev));
-
-       return 0;
-}
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
deleted file mode 100644 (file)
index 8757523..0000000
+++ /dev/null
@@ -1,809 +0,0 @@
-/*
-   em28xx.h - driver for Empia EM2800/EM2820/2840 USB video capture devices
-
-   Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
-                     Ludovico Cavedon <cavedon@sssup.it>
-                     Mauro Carvalho Chehab <mchehab@infradead.org>
-
-   Based on the em2800 driver from Sascha Sommer <saschasommer@freenet.de>
-
-   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.
- */
-
-#ifndef _EM28XX_H
-#define _EM28XX_H
-
-#include <linux/workqueue.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <linux/videodev2.h>
-
-#include <media/videobuf-vmalloc.h>
-#include <media/v4l2-device.h>
-#include <media/ir-kbd-i2c.h>
-#include <media/rc-core.h>
-#if defined(CONFIG_VIDEO_EM28XX_DVB) || defined(CONFIG_VIDEO_EM28XX_DVB_MODULE)
-#include <media/videobuf-dvb.h>
-#endif
-#include "tuner-xc2028.h"
-#include "xc5000.h"
-#include "em28xx-reg.h"
-
-/* Boards supported by driver */
-#define EM2800_BOARD_UNKNOWN                   0
-#define EM2820_BOARD_UNKNOWN                   1
-#define EM2820_BOARD_TERRATEC_CINERGY_250      2
-#define EM2820_BOARD_PINNACLE_USB_2            3
-#define EM2820_BOARD_HAUPPAUGE_WINTV_USB_2      4
-#define EM2820_BOARD_MSI_VOX_USB_2              5
-#define EM2800_BOARD_TERRATEC_CINERGY_200       6
-#define EM2800_BOARD_LEADTEK_WINFAST_USBII      7
-#define EM2800_BOARD_KWORLD_USB2800             8
-#define EM2820_BOARD_PINNACLE_DVC_90           9
-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900   10
-#define EM2880_BOARD_TERRATEC_HYBRID_XS                11
-#define EM2820_BOARD_KWORLD_PVRTV2800RF                12
-#define EM2880_BOARD_TERRATEC_PRODIGY_XS       13
-#define EM2820_BOARD_PROLINK_PLAYTV_USB2       14
-#define EM2800_BOARD_VGEAR_POCKETTV             15
-#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950   16
-#define EM2880_BOARD_PINNACLE_PCTV_HD_PRO      17
-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2        18
-#define EM2860_BOARD_SAA711X_REFERENCE_DESIGN  19
-#define EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600   20
-#define EM2800_BOARD_GRABBEEX_USB2800           21
-#define EM2750_BOARD_UNKNOWN                     22
-#define EM2750_BOARD_DLCW_130                    23
-#define EM2820_BOARD_DLINK_USB_TV                24
-#define EM2820_BOARD_GADMEI_UTV310               25
-#define EM2820_BOARD_HERCULES_SMART_TV_USB2      26
-#define EM2820_BOARD_PINNACLE_USB_2_FM1216ME     27
-#define EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE 28
-#define EM2860_BOARD_TVP5150_REFERENCE_DESIGN    29
-#define EM2820_BOARD_VIDEOLOGY_20K14XUSB         30
-#define EM2821_BOARD_USBGEAR_VD204               31
-#define EM2821_BOARD_SUPERCOMP_USB_2             32
-#define EM2860_BOARD_ELGATO_VIDEO_CAPTURE        33
-#define EM2860_BOARD_TERRATEC_HYBRID_XS                  34
-#define EM2860_BOARD_TYPHOON_DVD_MAKER           35
-#define EM2860_BOARD_NETGMBH_CAM                 36
-#define EM2860_BOARD_GADMEI_UTV330               37
-#define EM2861_BOARD_YAKUMO_MOVIE_MIXER                  38
-#define EM2861_BOARD_KWORLD_PVRTV_300U           39
-#define EM2861_BOARD_PLEXTOR_PX_TV100U           40
-#define EM2870_BOARD_KWORLD_350U                 41
-#define EM2870_BOARD_KWORLD_355U                 42
-#define EM2870_BOARD_TERRATEC_XS                 43
-#define EM2870_BOARD_TERRATEC_XS_MT2060                  44
-#define EM2870_BOARD_PINNACLE_PCTV_DVB           45
-#define EM2870_BOARD_COMPRO_VIDEOMATE            46
-#define EM2880_BOARD_KWORLD_DVB_305U             47
-#define EM2880_BOARD_KWORLD_DVB_310U             48
-#define EM2880_BOARD_MSI_DIGIVOX_AD              49
-#define EM2880_BOARD_MSI_DIGIVOX_AD_II           50
-#define EM2880_BOARD_TERRATEC_HYBRID_XS_FR       51
-#define EM2881_BOARD_DNT_DA2_HYBRID              52
-#define EM2881_BOARD_PINNACLE_HYBRID_PRO         53
-#define EM2882_BOARD_KWORLD_VS_DVBT              54
-#define EM2882_BOARD_TERRATEC_HYBRID_XS                  55
-#define EM2882_BOARD_PINNACLE_HYBRID_PRO_330E    56
-#define EM2883_BOARD_KWORLD_HYBRID_330U                  57
-#define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU     58
-#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850     60
-#define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2    61
-#define EM2820_BOARD_GADMEI_TVR200               62
-#define EM2860_BOARD_KAIOMY_TVNPC_U2              63
-#define EM2860_BOARD_EASYCAP                      64
-#define EM2820_BOARD_IODATA_GVMVP_SZ             65
-#define EM2880_BOARD_EMPIRE_DUAL_TV              66
-#define EM2860_BOARD_TERRATEC_GRABBY             67
-#define EM2860_BOARD_TERRATEC_AV350              68
-#define EM2882_BOARD_KWORLD_ATSC_315U            69
-#define EM2882_BOARD_EVGA_INDTUBE                70
-#define EM2820_BOARD_SILVERCREST_WEBCAM           71
-#define EM2861_BOARD_GADMEI_UTV330PLUS           72
-#define EM2870_BOARD_REDDO_DVB_C_USB_BOX          73
-#define EM2800_BOARD_VC211A                      74
-#define EM2882_BOARD_DIKOM_DK300                 75
-#define EM2870_BOARD_KWORLD_A340                 76
-#define EM2874_BOARD_LEADERSHIP_ISDBT            77
-#define EM28174_BOARD_PCTV_290E                   78
-#define EM2884_BOARD_TERRATEC_H5                 79
-#define EM28174_BOARD_PCTV_460E                   80
-#define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C    81
-#define EM2884_BOARD_CINERGY_HTC_STICK           82
-#define EM2860_BOARD_HT_VIDBOX_NW03              83
-#define EM2874_BOARD_MAXMEDIA_UB425_TC            84
-#define EM2884_BOARD_PCTV_510E                    85
-#define EM2884_BOARD_PCTV_520E                    86
-
-/* Limits minimum and default number of buffers */
-#define EM28XX_MIN_BUF 4
-#define EM28XX_DEF_BUF 8
-
-/*Limits the max URB message size */
-#define URB_MAX_CTRL_SIZE 80
-
-/* Params for validated field */
-#define EM28XX_BOARD_NOT_VALIDATED 1
-#define EM28XX_BOARD_VALIDATED    0
-
-/* Params for em28xx_cmd() audio */
-#define EM28XX_START_AUDIO      1
-#define EM28XX_STOP_AUDIO       0
-
-/* maximum number of em28xx boards */
-#define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
-
-/* maximum number of frames that can be queued */
-#define EM28XX_NUM_FRAMES 5
-/* number of frames that get used for v4l2_read() */
-#define EM28XX_NUM_READ_FRAMES 2
-
-/* number of buffers for isoc transfers */
-#define EM28XX_NUM_BUFS 5
-#define EM28XX_DVB_NUM_BUFS 5
-
-/* number of packets for each buffer
-   windows requests only 64 packets .. so we better do the same
-   this is what I found out for all alternate numbers there!
- */
-#define EM28XX_NUM_PACKETS 64
-#define EM28XX_DVB_MAX_PACKETS 64
-
-#define EM28XX_INTERLACED_DEFAULT 1
-
-/*
-#define (use usbview if you want to get the other alternate number infos)
-#define
-#define alternate number 2
-#define                        Endpoint Address: 82
-                       Direction: in
-                       Attribute: 1
-                       Type: Isoc
-                       Max Packet Size: 1448
-                       Interval: 125us
-
-  alternate number 7
-
-                       Endpoint Address: 82
-                       Direction: in
-                       Attribute: 1
-                       Type: Isoc
-                       Max Packet Size: 3072
-                       Interval: 125us
-*/
-
-/* time to wait when stopping the isoc transfer */
-#define EM28XX_URB_TIMEOUT \
-                       msecs_to_jiffies(EM28XX_NUM_BUFS * EM28XX_NUM_PACKETS)
-
-/* time in msecs to wait for i2c writes to finish */
-#define EM2800_I2C_WRITE_TIMEOUT 20
-
-enum em28xx_mode {
-       EM28XX_SUSPEND,
-       EM28XX_ANALOG_MODE,
-       EM28XX_DIGITAL_MODE,
-};
-
-
-struct em28xx;
-
-struct em28xx_usb_isoc_bufs {
-               /* max packet size of isoc transaction */
-       int                             max_pkt_size;
-
-               /* number of packets in each buffer */
-       int                             num_packets;
-
-               /* number of allocated urbs */
-       int                             num_bufs;
-
-               /* urb for isoc transfers */
-       struct urb                      **urb;
-
-               /* transfer buffers for isoc transfer */
-       char                            **transfer_buffer;
-};
-
-struct em28xx_usb_isoc_ctl {
-               /* isoc transfer buffers for analog mode */
-       struct em28xx_usb_isoc_bufs     analog_bufs;
-
-               /* isoc transfer buffers for digital mode */
-       struct em28xx_usb_isoc_bufs     digital_bufs;
-
-               /* Stores already requested buffers */
-       struct em28xx_buffer            *vid_buf;
-       struct em28xx_buffer            *vbi_buf;
-
-               /* isoc urb callback */
-       int (*isoc_copy) (struct em28xx *dev, struct urb *urb);
-
-};
-
-/* Struct to enumberate video formats */
-struct em28xx_fmt {
-       char  *name;
-       u32   fourcc;          /* v4l2 format id */
-       int   depth;
-       int   reg;
-};
-
-/* buffer for one video frame */
-struct em28xx_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
-
-       struct list_head frame;
-       int top_field;
-};
-
-struct em28xx_dmaqueue {
-       struct list_head       active;
-
-       wait_queue_head_t          wq;
-
-       /* Counters to control buffer fill */
-       int                        pos;
-};
-
-/* inputs */
-
-#define MAX_EM28XX_INPUT 4
-enum enum28xx_itype {
-       EM28XX_VMUX_COMPOSITE1 = 1,
-       EM28XX_VMUX_COMPOSITE2,
-       EM28XX_VMUX_COMPOSITE3,
-       EM28XX_VMUX_COMPOSITE4,
-       EM28XX_VMUX_SVIDEO,
-       EM28XX_VMUX_TELEVISION,
-       EM28XX_VMUX_CABLE,
-       EM28XX_VMUX_DVB,
-       EM28XX_VMUX_DEBUG,
-       EM28XX_RADIO,
-};
-
-enum em28xx_ac97_mode {
-       EM28XX_NO_AC97 = 0,
-       EM28XX_AC97_EM202,
-       EM28XX_AC97_SIGMATEL,
-       EM28XX_AC97_OTHER,
-};
-
-struct em28xx_audio_mode {
-       enum em28xx_ac97_mode ac97;
-
-       u16 ac97_feat;
-       u32 ac97_vendor_id;
-
-       unsigned int has_audio:1;
-
-       unsigned int i2s_3rates:1;
-       unsigned int i2s_5rates:1;
-};
-
-/* em28xx has two audio inputs: tuner and line in.
-   However, on most devices, an auxiliary AC97 codec device is used.
-   The AC97 device may have several different inputs and outputs,
-   depending on their model. So, it is possible to use AC97 mixer to
-   address more than two different entries.
- */
-enum em28xx_amux {
-       /* This is the only entry for em28xx tuner input */
-       EM28XX_AMUX_VIDEO,      /* em28xx tuner, AC97 mixer Video */
-
-       EM28XX_AMUX_LINE_IN,    /* AC97 mixer Line In */
-
-       /* Some less-common mixer setups */
-       EM28XX_AMUX_VIDEO2,     /* em28xx Line in, AC97 mixer Video */
-       EM28XX_AMUX_PHONE,
-       EM28XX_AMUX_MIC,
-       EM28XX_AMUX_CD,
-       EM28XX_AMUX_AUX,
-       EM28XX_AMUX_PCM_OUT,
-};
-
-enum em28xx_aout {
-       /* AC97 outputs */
-       EM28XX_AOUT_MASTER = 1 << 0,
-       EM28XX_AOUT_LINE   = 1 << 1,
-       EM28XX_AOUT_MONO   = 1 << 2,
-       EM28XX_AOUT_LFE    = 1 << 3,
-       EM28XX_AOUT_SURR   = 1 << 4,
-
-       /* PCM IN Mixer - used by AC97_RECORD_SELECT register */
-       EM28XX_AOUT_PCM_IN = 1 << 7,
-
-       /* Bits 10-8 are used to indicate the PCM IN record select */
-       EM28XX_AOUT_PCM_MIC_PCM = 0 << 8,
-       EM28XX_AOUT_PCM_CD      = 1 << 8,
-       EM28XX_AOUT_PCM_VIDEO   = 2 << 8,
-       EM28XX_AOUT_PCM_AUX     = 3 << 8,
-       EM28XX_AOUT_PCM_LINE    = 4 << 8,
-       EM28XX_AOUT_PCM_STEREO  = 5 << 8,
-       EM28XX_AOUT_PCM_MONO    = 6 << 8,
-       EM28XX_AOUT_PCM_PHONE   = 7 << 8,
-};
-
-static inline int ac97_return_record_select(int a_out)
-{
-       return (a_out & 0x700) >> 8;
-}
-
-struct em28xx_reg_seq {
-       int reg;
-       unsigned char val, mask;
-       int sleep;
-};
-
-struct em28xx_input {
-       enum enum28xx_itype type;
-       unsigned int vmux;
-       enum em28xx_amux amux;
-       enum em28xx_aout aout;
-       struct em28xx_reg_seq *gpio;
-};
-
-#define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
-
-enum em28xx_decoder {
-       EM28XX_NODECODER = 0,
-       EM28XX_TVP5150,
-       EM28XX_SAA711X,
-};
-
-enum em28xx_sensor {
-       EM28XX_NOSENSOR = 0,
-       EM28XX_MT9V011,
-       EM28XX_MT9M001,
-       EM28XX_MT9M111,
-};
-
-enum em28xx_adecoder {
-       EM28XX_NOADECODER = 0,
-       EM28XX_TVAUDIO,
-};
-
-struct em28xx_board {
-       char *name;
-       int vchannels;
-       int tuner_type;
-       int tuner_addr;
-
-       /* i2c flags */
-       unsigned int tda9887_conf;
-
-       /* GPIO sequences */
-       struct em28xx_reg_seq *dvb_gpio;
-       struct em28xx_reg_seq *suspend_gpio;
-       struct em28xx_reg_seq *tuner_gpio;
-       struct em28xx_reg_seq *mute_gpio;
-
-       unsigned int is_em2800:1;
-       unsigned int has_msp34xx:1;
-       unsigned int mts_firmware:1;
-       unsigned int max_range_640_480:1;
-       unsigned int has_dvb:1;
-       unsigned int has_snapshot_button:1;
-       unsigned int is_webcam:1;
-       unsigned int valid:1;
-       unsigned int has_ir_i2c:1;
-
-       unsigned char xclk, i2c_speed;
-       unsigned char radio_addr;
-       unsigned short tvaudio_addr;
-
-       enum em28xx_decoder decoder;
-       enum em28xx_adecoder adecoder;
-
-       struct em28xx_input       input[MAX_EM28XX_INPUT];
-       struct em28xx_input       radio;
-       char                      *ir_codes;
-};
-
-struct em28xx_eeprom {
-       u32 id;                 /* 0x9567eb1a */
-       u16 vendor_ID;
-       u16 product_ID;
-
-       u16 chip_conf;
-
-       u16 board_conf;
-
-       u16 string1, string2, string3;
-
-       u8 string_idx_table;
-};
-
-/* device states */
-enum em28xx_dev_state {
-       DEV_INITIALIZED = 0x01,
-       DEV_DISCONNECTED = 0x02,
-       DEV_MISCONFIGURED = 0x04,
-};
-
-#define EM28XX_AUDIO_BUFS 5
-#define EM28XX_NUM_AUDIO_PACKETS 64
-#define EM28XX_AUDIO_MAX_PACKET_SIZE 196 /* static value */
-#define EM28XX_CAPTURE_STREAM_EN 1
-
-/* em28xx extensions */
-#define EM28XX_AUDIO   0x10
-#define EM28XX_DVB     0x20
-#define EM28XX_RC      0x30
-
-/* em28xx resource types (used for res_get/res_lock etc */
-#define EM28XX_RESOURCE_VIDEO 0x01
-#define EM28XX_RESOURCE_VBI   0x02
-
-struct em28xx_audio {
-       char name[50];
-       char *transfer_buffer[EM28XX_AUDIO_BUFS];
-       struct urb *urb[EM28XX_AUDIO_BUFS];
-       struct usb_device *udev;
-       unsigned int capture_transfer_done;
-       struct snd_pcm_substream   *capture_pcm_substream;
-
-       unsigned int hwptr_done_capture;
-       struct snd_card            *sndcard;
-
-       int users;
-       spinlock_t slock;
-};
-
-struct em28xx;
-
-struct em28xx_fh {
-       struct em28xx *dev;
-       int           radio;
-       unsigned int  resources;
-
-       struct videobuf_queue        vb_vidq;
-       struct videobuf_queue        vb_vbiq;
-
-       enum v4l2_buf_type           type;
-};
-
-/* main device struct */
-struct em28xx {
-       /* generic device properties */
-       char name[30];          /* name (including minor) of the device */
-       int model;              /* index in the device_data struct */
-       int devno;              /* marks the number of this device */
-       enum em28xx_chip_id chip_id;
-
-       int audio_ifnum;
-
-       struct v4l2_device v4l2_dev;
-       struct em28xx_board board;
-
-       /* Webcam specific fields */
-       enum em28xx_sensor em28xx_sensor;
-       int sensor_xres, sensor_yres;
-       int sensor_xtal;
-
-       /* Allows progressive (e. g. non-interlaced) mode */
-       int progressive;
-
-       /* Vinmode/Vinctl used at the driver */
-       int vinmode, vinctl;
-
-       unsigned int has_audio_class:1;
-       unsigned int has_alsa_audio:1;
-       unsigned int is_audio_only:1;
-
-       /* Controls audio streaming */
-       struct work_struct wq_trigger;              /* Trigger to start/stop audio for alsa module */
-        atomic_t       stream_started;      /* stream should be running if true */
-
-       struct em28xx_fmt *format;
-
-       struct em28xx_IR *ir;
-
-       /* Some older em28xx chips needs a waiting time after writing */
-       unsigned int wait_after_write;
-
-       struct list_head        devlist;
-
-       u32 i2s_speed;          /* I2S speed for audio digital stream */
-
-       struct em28xx_audio_mode audio_mode;
-
-       int tuner_type;         /* type of the tuner */
-       int tuner_addr;         /* tuner address */
-       int tda9887_conf;
-       /* i2c i/o */
-       struct i2c_adapter i2c_adap;
-       struct i2c_client i2c_client;
-       /* video for linux */
-       int users;              /* user count for exclusive use */
-       struct video_device *vdev;      /* video for linux device struct */
-       v4l2_std_id norm;       /* selected tv norm */
-       int ctl_freq;           /* selected frequency */
-       unsigned int ctl_input; /* selected input */
-       unsigned int ctl_ainput;/* selected audio input */
-       unsigned int ctl_aoutput;/* selected audio output */
-       int mute;
-       int volume;
-       /* frame properties */
-       int width;              /* current frame width */
-       int height;             /* current frame height */
-       unsigned hscale;        /* horizontal scale factor (see datasheet) */
-       unsigned vscale;        /* vertical scale factor (see datasheet) */
-       int interlaced;         /* 1=interlace fileds, 0=just top fileds */
-       unsigned int video_bytesread;   /* Number of bytes read */
-
-       unsigned long hash;     /* eeprom hash - for boards with generic ID */
-       unsigned long i2c_hash; /* i2c devicelist hash -
-                                  for boards with generic ID */
-
-       struct em28xx_audio adev;
-
-       /* states */
-       enum em28xx_dev_state state;
-
-       /* vbi related state tracking */
-       int capture_type;
-       int vbi_read;
-       unsigned char cur_field;
-       unsigned int vbi_width;
-       unsigned int vbi_height; /* lines per field */
-
-       struct work_struct         request_module_wk;
-
-       /* locks */
-       struct mutex lock;
-       struct mutex ctrl_urb_lock;     /* protects urb_buf */
-       /* spinlock_t queue_lock; */
-       struct list_head inqueue, outqueue;
-       struct video_device *vbi_dev;
-       struct video_device *radio_dev;
-
-       /* resources in use */
-       unsigned int resources;
-
-       unsigned char eedata[256];
-
-       /* Isoc control struct */
-       struct em28xx_dmaqueue vidq;
-       struct em28xx_dmaqueue vbiq;
-       struct em28xx_usb_isoc_ctl isoc_ctl;
-       spinlock_t slock;
-
-       /* usb transfer */
-       struct usb_device *udev;        /* the usb device */
-       int alt;                /* alternate */
-       int max_pkt_size;       /* max packet size of isoc transaction */
-       int num_alt;            /* Number of alternative settings */
-       unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
-       int dvb_alt;                            /* alternate for DVB */
-       unsigned int dvb_max_pkt_size;          /* wMaxPacketSize for DVB */
-       char urb_buf[URB_MAX_CTRL_SIZE];        /* urb control msg buffer */
-
-       /* helper funcs that call usb_control_msg */
-       int (*em28xx_write_regs) (struct em28xx *dev, u16 reg,
-                                       char *buf, int len);
-       int (*em28xx_read_reg) (struct em28xx *dev, u16 reg);
-       int (*em28xx_read_reg_req_len) (struct em28xx *dev, u8 req, u16 reg,
-                                       char *buf, int len);
-       int (*em28xx_write_regs_req) (struct em28xx *dev, u8 req, u16 reg,
-                                     char *buf, int len);
-       int (*em28xx_read_reg_req) (struct em28xx *dev, u8 req, u16 reg);
-
-       enum em28xx_mode mode;
-
-       /* register numbers for GPO/GPIO registers */
-       u16 reg_gpo_num, reg_gpio_num;
-
-       /* Caches GPO and GPIO registers */
-       unsigned char   reg_gpo, reg_gpio;
-
-       /* Snapshot button */
-       char snapshot_button_path[30];  /* path of the input dev */
-       struct input_dev *sbutton_input_dev;
-       struct delayed_work sbutton_query_work;
-
-       struct em28xx_dvb *dvb;
-
-       /* I2C keyboard data */
-       struct IR_i2c_init_data init_data;
-};
-
-struct em28xx_ops {
-       struct list_head next;
-       char *name;
-       int id;
-       int (*init)(struct em28xx *);
-       int (*fini)(struct em28xx *);
-};
-
-/* Provided by em28xx-i2c.c */
-void em28xx_do_i2c_scan(struct em28xx *dev);
-int  em28xx_i2c_register(struct em28xx *dev);
-int  em28xx_i2c_unregister(struct em28xx *dev);
-
-/* Provided by em28xx-core.c */
-
-u32 em28xx_request_buffers(struct em28xx *dev, u32 count);
-void em28xx_queue_unusedframes(struct em28xx *dev);
-void em28xx_release_buffers(struct em28xx *dev);
-
-int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
-                           char *buf, int len);
-int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg);
-int em28xx_read_reg(struct em28xx *dev, u16 reg);
-int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
-                         int len);
-int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len);
-int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val);
-int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
-                                u8 bitmask);
-
-int em28xx_read_ac97(struct em28xx *dev, u8 reg);
-int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val);
-
-int em28xx_audio_analog_set(struct em28xx *dev);
-int em28xx_audio_setup(struct em28xx *dev);
-
-int em28xx_colorlevels_set_default(struct em28xx *dev);
-int em28xx_capture_start(struct em28xx *dev, int start);
-int em28xx_vbi_supported(struct em28xx *dev);
-int em28xx_set_outfmt(struct em28xx *dev);
-int em28xx_resolution_set(struct em28xx *dev);
-int em28xx_set_alternate(struct em28xx *dev);
-int em28xx_alloc_isoc(struct em28xx *dev, enum em28xx_mode mode,
-                     int max_packets, int num_bufs, int max_pkt_size);
-int em28xx_init_isoc(struct em28xx *dev, enum em28xx_mode mode,
-                    int max_packets, int num_bufs, int max_pkt_size,
-                    int (*isoc_copy) (struct em28xx *dev, struct urb *urb));
-void em28xx_uninit_isoc(struct em28xx *dev, enum em28xx_mode mode);
-void em28xx_stop_urbs(struct em28xx *dev);
-int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev);
-int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
-int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
-void em28xx_wake_i2c(struct em28xx *dev);
-int em28xx_register_extension(struct em28xx_ops *dev);
-void em28xx_unregister_extension(struct em28xx_ops *dev);
-void em28xx_init_extension(struct em28xx *dev);
-void em28xx_close_extension(struct em28xx *dev);
-
-/* Provided by em28xx-video.c */
-int em28xx_register_analog_devices(struct em28xx *dev);
-void em28xx_release_analog_resources(struct em28xx *dev);
-
-/* Provided by em28xx-cards.c */
-extern int em2800_variant_detect(struct usb_device *udev, int model);
-extern struct em28xx_board em28xx_boards[];
-extern struct usb_device_id em28xx_id_table[];
-extern const unsigned int em28xx_bcount;
-int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
-void em28xx_release_resources(struct em28xx *dev);
-
-/* Provided by em28xx-vbi.c */
-extern struct videobuf_queue_ops em28xx_vbi_qops;
-
-/* printk macros */
-
-#define em28xx_err(fmt, arg...) do {\
-       printk(KERN_ERR fmt , ##arg); } while (0)
-
-#define em28xx_errdev(fmt, arg...) do {\
-       printk(KERN_ERR "%s: "fmt,\
-                       dev->name , ##arg); } while (0)
-
-#define em28xx_info(fmt, arg...) do {\
-       printk(KERN_INFO "%s: "fmt,\
-                       dev->name , ##arg); } while (0)
-#define em28xx_warn(fmt, arg...) do {\
-       printk(KERN_WARNING "%s: "fmt,\
-                       dev->name , ##arg); } while (0)
-
-static inline int em28xx_compression_disable(struct em28xx *dev)
-{
-       /* side effect of disabling scaler and mixer */
-       return em28xx_write_reg(dev, EM28XX_R26_COMPR, 0x00);
-}
-
-static inline int em28xx_contrast_get(struct em28xx *dev)
-{
-       return em28xx_read_reg(dev, EM28XX_R20_YGAIN) & 0x1f;
-}
-
-static inline int em28xx_brightness_get(struct em28xx *dev)
-{
-       return em28xx_read_reg(dev, EM28XX_R21_YOFFSET);
-}
-
-static inline int em28xx_saturation_get(struct em28xx *dev)
-{
-       return em28xx_read_reg(dev, EM28XX_R22_UVGAIN) & 0x1f;
-}
-
-static inline int em28xx_u_balance_get(struct em28xx *dev)
-{
-       return em28xx_read_reg(dev, EM28XX_R23_UOFFSET);
-}
-
-static inline int em28xx_v_balance_get(struct em28xx *dev)
-{
-       return em28xx_read_reg(dev, EM28XX_R24_VOFFSET);
-}
-
-static inline int em28xx_gamma_get(struct em28xx *dev)
-{
-       return em28xx_read_reg(dev, EM28XX_R14_GAMMA) & 0x3f;
-}
-
-static inline int em28xx_contrast_set(struct em28xx *dev, s32 val)
-{
-       u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, EM28XX_R20_YGAIN, &tmp, 1);
-}
-
-static inline int em28xx_brightness_set(struct em28xx *dev, s32 val)
-{
-       u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, EM28XX_R21_YOFFSET, &tmp, 1);
-}
-
-static inline int em28xx_saturation_set(struct em28xx *dev, s32 val)
-{
-       u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, EM28XX_R22_UVGAIN, &tmp, 1);
-}
-
-static inline int em28xx_u_balance_set(struct em28xx *dev, s32 val)
-{
-       u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, EM28XX_R23_UOFFSET, &tmp, 1);
-}
-
-static inline int em28xx_v_balance_set(struct em28xx *dev, s32 val)
-{
-       u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, EM28XX_R24_VOFFSET, &tmp, 1);
-}
-
-static inline int em28xx_gamma_set(struct em28xx *dev, s32 val)
-{
-       u8 tmp = (u8) val;
-       return em28xx_write_regs(dev, EM28XX_R14_GAMMA, &tmp, 1);
-}
-
-/*FIXME: maxw should be dependent of alt mode */
-static inline unsigned int norm_maxw(struct em28xx *dev)
-{
-       if (dev->board.is_webcam)
-               return dev->sensor_xres;
-
-       if (dev->board.max_range_640_480)
-               return 640;
-
-       return 720;
-}
-
-static inline unsigned int norm_maxh(struct em28xx *dev)
-{
-       if (dev->board.is_webcam)
-               return dev->sensor_yres;
-
-       if (dev->board.max_range_640_480)
-               return 480;
-
-       return (dev->norm & V4L2_STD_625_50) ? 576 : 480;
-}
-#endif
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig
deleted file mode 100644 (file)
index dfe268b..0000000
+++ /dev/null
@@ -1,425 +0,0 @@
-menuconfig USB_GSPCA
-       tristate "GSPCA based webcams"
-       depends on VIDEO_V4L2
-       default m
-       ---help---
-         Say Y here if you want to enable selecting webcams based
-         on the GSPCA framework.
-
-         See <file:Documentation/video4linux/gspca.txt> for more info.
-
-         This driver uses the Video For Linux API. You must say Y or M to
-         "Video For Linux" to use this driver.
-
-         To compile this driver as modules, choose M here: the
-         module will be called gspca_main.
-
-
-if USB_GSPCA && VIDEO_V4L2
-
-source "drivers/media/video/gspca/m5602/Kconfig"
-source "drivers/media/video/gspca/stv06xx/Kconfig"
-source "drivers/media/video/gspca/gl860/Kconfig"
-
-config USB_GSPCA_BENQ
-       tristate "Benq USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for the Benq DC E300 camera.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_benq.
-
-config USB_GSPCA_CONEX
-       tristate "Conexant Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the Conexant chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_conex.
-
-config USB_GSPCA_CPIA1
-       tristate "cpia CPiA (version 1) Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for USB cameras based on the cpia
-         CPiA chip. Note that you need atleast version 0.6.4 of libv4l for
-         applications to understand the videoformat generated by this driver.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_cpia1.
-
-config USB_GSPCA_ETOMS
-       tristate "Etoms USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the Etoms chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_etoms.
-
-config USB_GSPCA_FINEPIX
-       tristate "Fujifilm FinePix USB V4L2 driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the FinePix chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_finepix.
-
-config USB_GSPCA_JEILINJ
-       tristate "Jeilin JPEG USB V4L2 driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on this Jeilin chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_jeilinj.
-
-config USB_GSPCA_JL2005BCD
-       tristate "JL2005B/C/D USB V4L2 driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based the
-         JL2005B, JL2005C, or JL2005D chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_jl2005bcd.
-
-config USB_GSPCA_KINECT
-       tristate "Kinect sensor device USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for the Microsoft Kinect sensor device.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_kinect.
-
-config USB_GSPCA_KONICA
-       tristate "Konica USB Camera V4L2 driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the Konica chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_konica.
-
-config USB_GSPCA_MARS
-       tristate "Mars USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the Mars chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_mars.
-
-config USB_GSPCA_MR97310A
-       tristate "Mars-Semi MR97310A USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the MR97310A chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_mr97310a.
-
-config USB_GSPCA_NW80X
-       tristate "Divio based (NW80x) USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the NW80x chips.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_nw80x.
-
-config USB_GSPCA_OV519
-       tristate "OV51x / OVFX2 / W996xCF USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on one of these:
-         OV511(+), OV518(+), OV519, OVFX2, W9967CF, W9968CF
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_ov519.
-
-config USB_GSPCA_OV534
-       tristate "OV534 OV772x USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the OV534 chip
-         and sensor OV772x (e.g. Sony Playstation EYE)
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_ov534.
-
-config USB_GSPCA_OV534_9
-       tristate "OV534 OV965x USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the OV534 chip
-         and sensor OV965x (e.g. Hercules Dualpix)
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_ov534_9.
-
-config USB_GSPCA_PAC207
-       tristate "Pixart PAC207 USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the PAC207 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_pac207.
-
-config USB_GSPCA_PAC7302
-       tristate "Pixart PAC7302 USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the PAC7302 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_pac7302.
-
-config USB_GSPCA_PAC7311
-       tristate "Pixart PAC7311 USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the PAC7311 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_pac7311.
-
-config USB_GSPCA_SE401
-       tristate "SE401 USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-        Say Y here if you want support for cameras based on the
-        Endpoints (formerly known as AOX) se401 chip.
-
-        To compile this driver as a module, choose M here: the
-        module will be called gspca_se401.
-
-config USB_GSPCA_SN9C2028
-       tristate "SONIX Dual-Mode USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want streaming support for Sonix SN9C2028 cameras.
-         These are supported as stillcams in libgphoto2/camlibs/sonix.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_sn9c2028.
-
-config USB_GSPCA_SN9C20X
-       tristate "SN9C20X USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-        Say Y here if you want support for cameras based on the
-        sn9c20x chips (SN9C201 and SN9C202).
-
-        To compile this driver as a module, choose M here: the
-        module will be called gspca_sn9c20x.
-
-config USB_GSPCA_SONIXB
-       tristate "SONIX Bayer USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the Sonix
-         chips with Bayer format (SN9C101, SN9C102 and SN9C103).
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_sonixb.
-
-config USB_GSPCA_SONIXJ
-       tristate "SONIX JPEG USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the Sonix
-         chips with JPEG format (SN9C102P, SN9C105 and >= SN9C110).
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_sonixj
-
-config USB_GSPCA_SPCA500
-       tristate "SPCA500 USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the SPCA500 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_spca500.
-
-config USB_GSPCA_SPCA501
-       tristate "SPCA501 USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the SPCA501 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_spca501.
-
-config USB_GSPCA_SPCA505
-       tristate "SPCA505 USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the SPCA505 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_spca505.
-
-config USB_GSPCA_SPCA506
-       tristate "SPCA506 USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the SPCA506 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_spca506.
-
-config USB_GSPCA_SPCA508
-       tristate "SPCA508 USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the SPCA508 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_spca508.
-
-config USB_GSPCA_SPCA561
-       tristate "SPCA561 USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the SPCA561 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_spca561.
-
-config USB_GSPCA_SPCA1528
-       tristate "SPCA1528 USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the SPCA1528 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_spca1528.
-
-config USB_GSPCA_SQ905
-       tristate "SQ Technologies SQ905 based USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the SQ905 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_sq905.
-
-config USB_GSPCA_SQ905C
-       tristate "SQ Technologies SQ905C based USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the SQ905C chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_sq905c.
-
-config USB_GSPCA_SQ930X
-       tristate "SQ Technologies SQ930X based USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the SQ930X chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_sq930x.
-
-config USB_GSPCA_STK014
-       tristate "Syntek DV4000 (STK014) USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the STK014 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_stk014.
-
-config USB_GSPCA_STV0680
-       tristate "STV0680 USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the STV0680 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_stv0680.
-
-config USB_GSPCA_SUNPLUS
-       tristate "SUNPLUS USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the Sunplus
-         SPCA504(abc) SPCA533 SPCA536 chips.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_sunplus.
-
-config USB_GSPCA_T613
-       tristate "T613 (JPEG Compliance) USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the T613 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_t613.
-
-config USB_GSPCA_TOPRO
-       tristate "TOPRO USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the
-         TP6800 and TP6810 Topro chips.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_topro.
-
-config USB_GSPCA_TV8532
-       tristate "TV8532 USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the TV8531 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_tv8532.
-
-config USB_GSPCA_VC032X
-       tristate "VC032X USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the VC032X chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_vc032x.
-
-config USB_GSPCA_VICAM
-       tristate "ViCam USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for the 3com homeconnect camera
-         (vicam).
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_vicam.
-
-config USB_GSPCA_XIRLINK_CIT
-       tristate "Xirlink C-It USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for Xirlink C-It bases cameras.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_xirlink_cit.
-
-config USB_GSPCA_ZC3XX
-       tristate "ZC3XX USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the ZC3XX chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_zc3xx.
-
-endif
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile
deleted file mode 100644 (file)
index c901da0..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-obj-$(CONFIG_USB_GSPCA)          += gspca_main.o
-obj-$(CONFIG_USB_GSPCA_BENQ)     += gspca_benq.o
-obj-$(CONFIG_USB_GSPCA_CONEX)    += gspca_conex.o
-obj-$(CONFIG_USB_GSPCA_CPIA1)    += gspca_cpia1.o
-obj-$(CONFIG_USB_GSPCA_ETOMS)    += gspca_etoms.o
-obj-$(CONFIG_USB_GSPCA_FINEPIX)  += gspca_finepix.o
-obj-$(CONFIG_USB_GSPCA_JEILINJ)  += gspca_jeilinj.o
-obj-$(CONFIG_USB_GSPCA_JL2005BCD) += gspca_jl2005bcd.o
-obj-$(CONFIG_USB_GSPCA_KINECT)   += gspca_kinect.o
-obj-$(CONFIG_USB_GSPCA_KONICA)   += gspca_konica.o
-obj-$(CONFIG_USB_GSPCA_MARS)     += gspca_mars.o
-obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o
-obj-$(CONFIG_USB_GSPCA_NW80X)    += gspca_nw80x.o
-obj-$(CONFIG_USB_GSPCA_OV519)    += gspca_ov519.o
-obj-$(CONFIG_USB_GSPCA_OV534)    += gspca_ov534.o
-obj-$(CONFIG_USB_GSPCA_OV534_9)  += gspca_ov534_9.o
-obj-$(CONFIG_USB_GSPCA_PAC207)   += gspca_pac207.o
-obj-$(CONFIG_USB_GSPCA_PAC7302)  += gspca_pac7302.o
-obj-$(CONFIG_USB_GSPCA_PAC7311)  += gspca_pac7311.o
-obj-$(CONFIG_USB_GSPCA_SE401)    += gspca_se401.o
-obj-$(CONFIG_USB_GSPCA_SN9C2028) += gspca_sn9c2028.o
-obj-$(CONFIG_USB_GSPCA_SN9C20X)  += gspca_sn9c20x.o
-obj-$(CONFIG_USB_GSPCA_SONIXB)   += gspca_sonixb.o
-obj-$(CONFIG_USB_GSPCA_SONIXJ)   += gspca_sonixj.o
-obj-$(CONFIG_USB_GSPCA_SPCA500)  += gspca_spca500.o
-obj-$(CONFIG_USB_GSPCA_SPCA501)  += gspca_spca501.o
-obj-$(CONFIG_USB_GSPCA_SPCA505)  += gspca_spca505.o
-obj-$(CONFIG_USB_GSPCA_SPCA506)  += gspca_spca506.o
-obj-$(CONFIG_USB_GSPCA_SPCA508)  += gspca_spca508.o
-obj-$(CONFIG_USB_GSPCA_SPCA561)  += gspca_spca561.o
-obj-$(CONFIG_USB_GSPCA_SPCA1528) += gspca_spca1528.o
-obj-$(CONFIG_USB_GSPCA_SQ905)    += gspca_sq905.o
-obj-$(CONFIG_USB_GSPCA_SQ905C)   += gspca_sq905c.o
-obj-$(CONFIG_USB_GSPCA_SQ930X)   += gspca_sq930x.o
-obj-$(CONFIG_USB_GSPCA_SUNPLUS)  += gspca_sunplus.o
-obj-$(CONFIG_USB_GSPCA_STK014)   += gspca_stk014.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_TV8532)   += gspca_tv8532.o
-obj-$(CONFIG_USB_GSPCA_VC032X)   += gspca_vc032x.o
-obj-$(CONFIG_USB_GSPCA_VICAM)    += gspca_vicam.o
-obj-$(CONFIG_USB_GSPCA_XIRLINK_CIT) += gspca_xirlink_cit.o
-obj-$(CONFIG_USB_GSPCA_ZC3XX)    += gspca_zc3xx.o
-
-gspca_main-objs     := gspca.o autogain_functions.o
-gspca_benq-objs     := benq.o
-gspca_conex-objs    := conex.o
-gspca_cpia1-objs    := cpia1.o
-gspca_etoms-objs    := etoms.o
-gspca_finepix-objs  := finepix.o
-gspca_jeilinj-objs  := jeilinj.o
-gspca_jl2005bcd-objs  := jl2005bcd.o
-gspca_kinect-objs   := kinect.o
-gspca_konica-objs   := konica.o
-gspca_mars-objs     := mars.o
-gspca_mr97310a-objs := mr97310a.o
-gspca_nw80x-objs    := nw80x.o
-gspca_ov519-objs    := ov519.o
-gspca_ov534-objs    := ov534.o
-gspca_ov534_9-objs  := ov534_9.o
-gspca_pac207-objs   := pac207.o
-gspca_pac7302-objs  := pac7302.o
-gspca_pac7311-objs  := pac7311.o
-gspca_se401-objs    := se401.o
-gspca_sn9c2028-objs := sn9c2028.o
-gspca_sn9c20x-objs  := sn9c20x.o
-gspca_sonixb-objs   := sonixb.o
-gspca_sonixj-objs   := sonixj.o
-gspca_spca500-objs  := spca500.o
-gspca_spca501-objs  := spca501.o
-gspca_spca505-objs  := spca505.o
-gspca_spca506-objs  := spca506.o
-gspca_spca508-objs  := spca508.o
-gspca_spca561-objs  := spca561.o
-gspca_spca1528-objs := spca1528.o
-gspca_sq905-objs    := sq905.o
-gspca_sq905c-objs   := sq905c.o
-gspca_sq930x-objs   := sq930x.o
-gspca_stk014-objs   := stk014.o
-gspca_stv0680-objs  := stv0680.o
-gspca_sunplus-objs  := sunplus.o
-gspca_t613-objs     := t613.o
-gspca_topro-objs    := topro.o
-gspca_tv8532-objs   := tv8532.o
-gspca_vc032x-objs   := vc032x.o
-gspca_vicam-objs    := vicam.o
-gspca_xirlink_cit-objs := xirlink_cit.o
-gspca_zc3xx-objs    := zc3xx.o
-
-obj-$(CONFIG_USB_M5602)   += m5602/
-obj-$(CONFIG_USB_STV06XX) += stv06xx/
-obj-$(CONFIG_USB_GL860)   += gl860/
diff --git a/drivers/media/video/gspca/autogain_functions.c b/drivers/media/video/gspca/autogain_functions.c
deleted file mode 100644 (file)
index 67db674..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Functions for auto gain.
- *
- * Copyright (C) 2010-2012 Hans de Goede <hdegoede@redhat.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include "gspca.h"
-
-/* auto gain and exposure algorithm based on the knee algorithm described here:
-   http://ytse.tricolour.net/docs/LowLightOptimization.html
-
-   Returns 0 if no changes were made, 1 if the gain and or exposure settings
-   where changed. */
-int gspca_expo_autogain(
-                       struct gspca_dev *gspca_dev,
-                       int avg_lum,
-                       int desired_avg_lum,
-                       int deadzone,
-                       int gain_knee,
-                       int exposure_knee)
-{
-       s32 gain, orig_gain, exposure, orig_exposure;
-       int i, steps, retval = 0;
-
-       if (v4l2_ctrl_g_ctrl(gspca_dev->autogain) == 0)
-               return 0;
-
-       orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
-       orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
-
-       /* If we are of a multiple of deadzone, do multiple steps to reach the
-          desired lumination fast (with the risc of a slight overshoot) */
-       steps = abs(desired_avg_lum - avg_lum) / deadzone;
-
-       PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
-               avg_lum, desired_avg_lum, steps);
-
-       for (i = 0; i < steps; i++) {
-               if (avg_lum > desired_avg_lum) {
-                       if (gain > gain_knee)
-                               gain--;
-                       else if (exposure > exposure_knee)
-                               exposure--;
-                       else if (gain > gspca_dev->gain->default_value)
-                               gain--;
-                       else if (exposure > gspca_dev->exposure->minimum)
-                               exposure--;
-                       else if (gain > gspca_dev->gain->minimum)
-                               gain--;
-                       else
-                               break;
-               } else {
-                       if (gain < gspca_dev->gain->default_value)
-                               gain++;
-                       else if (exposure < exposure_knee)
-                               exposure++;
-                       else if (gain < gain_knee)
-                               gain++;
-                       else if (exposure < gspca_dev->exposure->maximum)
-                               exposure++;
-                       else if (gain < gspca_dev->gain->maximum)
-                               gain++;
-                       else
-                               break;
-               }
-       }
-
-       if (gain != orig_gain) {
-               v4l2_ctrl_s_ctrl(gspca_dev->gain, gain);
-               retval = 1;
-       }
-       if (exposure != orig_exposure) {
-               v4l2_ctrl_s_ctrl(gspca_dev->exposure, exposure);
-               retval = 1;
-       }
-
-       if (retval)
-               PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
-                       gain, exposure);
-       return retval;
-}
-EXPORT_SYMBOL(gspca_expo_autogain);
-
-/* Autogain + exposure algorithm for cameras with a coarse exposure control
-   (usually this means we can only control the clockdiv to change exposure)
-   As changing the clockdiv so that the fps drops from 30 to 15 fps for
-   example, will lead to a huge exposure change (it effectively doubles),
-   this algorithm normally tries to only adjust the gain (between 40 and
-   80 %) and if that does not help, only then changes exposure. This leads
-   to a much more stable image then using the knee algorithm which at
-   certain points of the knee graph will only try to adjust exposure,
-   which leads to oscilating as one exposure step is huge.
-
-   Returns 0 if no changes were made, 1 if the gain and or exposure settings
-   where changed. */
-int gspca_coarse_grained_expo_autogain(
-                       struct gspca_dev *gspca_dev,
-                       int avg_lum,
-                       int desired_avg_lum,
-                       int deadzone)
-{
-       s32 gain_low, gain_high, gain, orig_gain, exposure, orig_exposure;
-       int steps, retval = 0;
-
-       if (v4l2_ctrl_g_ctrl(gspca_dev->autogain) == 0)
-               return 0;
-
-       orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
-       orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
-
-       gain_low  = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
-                   5 * 2 + gspca_dev->gain->minimum;
-       gain_high = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
-                   5 * 4 + gspca_dev->gain->minimum;
-
-       /* If we are of a multiple of deadzone, do multiple steps to reach the
-          desired lumination fast (with the risc of a slight overshoot) */
-       steps = (desired_avg_lum - avg_lum) / deadzone;
-
-       PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
-               avg_lum, desired_avg_lum, steps);
-
-       if ((gain + steps) > gain_high &&
-           exposure < gspca_dev->exposure->maximum) {
-               gain = gain_high;
-               gspca_dev->exp_too_low_cnt++;
-               gspca_dev->exp_too_high_cnt = 0;
-       } else if ((gain + steps) < gain_low &&
-                  exposure > gspca_dev->exposure->minimum) {
-               gain = gain_low;
-               gspca_dev->exp_too_high_cnt++;
-               gspca_dev->exp_too_low_cnt = 0;
-       } else {
-               gain += steps;
-               if (gain > gspca_dev->gain->maximum)
-                       gain = gspca_dev->gain->maximum;
-               else if (gain < gspca_dev->gain->minimum)
-                       gain = gspca_dev->gain->minimum;
-               gspca_dev->exp_too_high_cnt = 0;
-               gspca_dev->exp_too_low_cnt = 0;
-       }
-
-       if (gspca_dev->exp_too_high_cnt > 3) {
-               exposure--;
-               gspca_dev->exp_too_high_cnt = 0;
-       } else if (gspca_dev->exp_too_low_cnt > 3) {
-               exposure++;
-               gspca_dev->exp_too_low_cnt = 0;
-       }
-
-       if (gain != orig_gain) {
-               v4l2_ctrl_s_ctrl(gspca_dev->gain, gain);
-               retval = 1;
-       }
-       if (exposure != orig_exposure) {
-               v4l2_ctrl_s_ctrl(gspca_dev->exposure, exposure);
-               retval = 1;
-       }
-
-       if (retval)
-               PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
-                       gain, exposure);
-       return retval;
-}
-EXPORT_SYMBOL(gspca_coarse_grained_expo_autogain);
diff --git a/drivers/media/video/gspca/autogain_functions.h b/drivers/media/video/gspca/autogain_functions.h
deleted file mode 100644 (file)
index d625eaf..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Functions for auto gain.
- *
- * Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifdef WANT_REGULAR_AUTOGAIN
-/* auto gain and exposure algorithm based on the knee algorithm described here:
-   http://ytse.tricolour.net/docs/LowLightOptimization.html
-
-   Returns 0 if no changes were made, 1 if the gain and or exposure settings
-   where changed. */
-static inline int auto_gain_n_exposure(
-                       struct gspca_dev *gspca_dev,
-                       int avg_lum,
-                       int desired_avg_lum,
-                       int deadzone,
-                       int gain_knee,
-                       int exposure_knee)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i, steps, gain, orig_gain, exposure, orig_exposure;
-       int retval = 0;
-
-       orig_gain = gain = sd->ctrls[GAIN].val;
-       orig_exposure = exposure = sd->ctrls[EXPOSURE].val;
-
-       /* If we are of a multiple of deadzone, do multiple steps to reach the
-          desired lumination fast (with the risc of a slight overshoot) */
-       steps = abs(desired_avg_lum - avg_lum) / deadzone;
-
-       PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
-               avg_lum, desired_avg_lum, steps);
-
-       for (i = 0; i < steps; i++) {
-               if (avg_lum > desired_avg_lum) {
-                       if (gain > gain_knee)
-                               gain--;
-                       else if (exposure > exposure_knee)
-                               exposure--;
-                       else if (gain > sd->ctrls[GAIN].def)
-                               gain--;
-                       else if (exposure > sd->ctrls[EXPOSURE].min)
-                               exposure--;
-                       else if (gain > sd->ctrls[GAIN].min)
-                               gain--;
-                       else
-                               break;
-               } else {
-                       if (gain < sd->ctrls[GAIN].def)
-                               gain++;
-                       else if (exposure < exposure_knee)
-                               exposure++;
-                       else if (gain < gain_knee)
-                               gain++;
-                       else if (exposure < sd->ctrls[EXPOSURE].max)
-                               exposure++;
-                       else if (gain < sd->ctrls[GAIN].max)
-                               gain++;
-                       else
-                               break;
-               }
-       }
-
-       if (gain != orig_gain) {
-               sd->ctrls[GAIN].val = gain;
-               setgain(gspca_dev);
-               retval = 1;
-       }
-       if (exposure != orig_exposure) {
-               sd->ctrls[EXPOSURE].val = exposure;
-               setexposure(gspca_dev);
-               retval = 1;
-       }
-
-       if (retval)
-               PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
-                       gain, exposure);
-       return retval;
-}
-#endif
-
-#ifdef WANT_COARSE_EXPO_AUTOGAIN
-/* Autogain + exposure algorithm for cameras with a coarse exposure control
-   (usually this means we can only control the clockdiv to change exposure)
-   As changing the clockdiv so that the fps drops from 30 to 15 fps for
-   example, will lead to a huge exposure change (it effectively doubles),
-   this algorithm normally tries to only adjust the gain (between 40 and
-   80 %) and if that does not help, only then changes exposure. This leads
-   to a much more stable image then using the knee algorithm which at
-   certain points of the knee graph will only try to adjust exposure,
-   which leads to oscilating as one exposure step is huge.
-
-   Note this assumes that the sd struct for the cam in question has
-   exp_too_low_cnt and exp_too_high_cnt int members for use by this function.
-
-   Returns 0 if no changes were made, 1 if the gain and or exposure settings
-   where changed. */
-static inline int coarse_grained_expo_autogain(
-                       struct gspca_dev *gspca_dev,
-                       int avg_lum,
-                       int desired_avg_lum,
-                       int deadzone)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int steps, gain, orig_gain, exposure, orig_exposure;
-       int gain_low, gain_high;
-       int retval = 0;
-
-       orig_gain = gain = sd->ctrls[GAIN].val;
-       orig_exposure = exposure = sd->ctrls[EXPOSURE].val;
-
-       gain_low = (sd->ctrls[GAIN].max - sd->ctrls[GAIN].min) / 5 * 2;
-       gain_low += sd->ctrls[GAIN].min;
-       gain_high = (sd->ctrls[GAIN].max - sd->ctrls[GAIN].min) / 5 * 4;
-       gain_high += sd->ctrls[GAIN].min;
-
-       /* If we are of a multiple of deadzone, do multiple steps to reach the
-          desired lumination fast (with the risc of a slight overshoot) */
-       steps = (desired_avg_lum - avg_lum) / deadzone;
-
-       PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
-               avg_lum, desired_avg_lum, steps);
-
-       if ((gain + steps) > gain_high &&
-           exposure < sd->ctrls[EXPOSURE].max) {
-               gain = gain_high;
-               sd->exp_too_low_cnt++;
-               sd->exp_too_high_cnt = 0;
-       } else if ((gain + steps) < gain_low &&
-                  exposure > sd->ctrls[EXPOSURE].min) {
-               gain = gain_low;
-               sd->exp_too_high_cnt++;
-               sd->exp_too_low_cnt = 0;
-       } else {
-               gain += steps;
-               if (gain > sd->ctrls[GAIN].max)
-                       gain = sd->ctrls[GAIN].max;
-               else if (gain < sd->ctrls[GAIN].min)
-                       gain = sd->ctrls[GAIN].min;
-               sd->exp_too_high_cnt = 0;
-               sd->exp_too_low_cnt = 0;
-       }
-
-       if (sd->exp_too_high_cnt > 3) {
-               exposure--;
-               sd->exp_too_high_cnt = 0;
-       } else if (sd->exp_too_low_cnt > 3) {
-               exposure++;
-               sd->exp_too_low_cnt = 0;
-       }
-
-       if (gain != orig_gain) {
-               sd->ctrls[GAIN].val = gain;
-               setgain(gspca_dev);
-               retval = 1;
-       }
-       if (exposure != orig_exposure) {
-               sd->ctrls[EXPOSURE].val = exposure;
-               setexposure(gspca_dev);
-               retval = 1;
-       }
-
-       if (retval)
-               PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
-                       gain, exposure);
-       return retval;
-}
-#endif
diff --git a/drivers/media/video/gspca/benq.c b/drivers/media/video/gspca/benq.c
deleted file mode 100644 (file)
index 352f321..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * Benq DC E300 subdriver
- *
- * Copyright (C) 2009 Jean-Francois Moine (http://moinejf.free.fr)
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "benq"
-
-#include "gspca.h"
-
-MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
-MODULE_DESCRIPTION("Benq DC E300 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-};
-
-static void sd_isoc_irq(struct urb *urb);
-
-/* -- write a register -- */
-static void reg_w(struct gspca_dev *gspca_dev,
-                       u16 value, u16 index)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-                       0x02,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value,
-                       index,
-                       NULL,
-                       0,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_w err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-/* this function is called at probe time */
-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);
-       gspca_dev->cam.no_urb_create = 1;
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       return 0;
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct urb *urb;
-       int i, n;
-
-       /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */
-#if MAX_NURBS < 4
-#error "Not enough URBs in the gspca table"
-#endif
-#define SD_PKT_SZ 64
-#define SD_NPKT 32
-       for (n = 0; n < 4; n++) {
-               urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
-               if (!urb) {
-                       pr_err("usb_alloc_urb failed\n");
-                       return -ENOMEM;
-               }
-               gspca_dev->urb[n] = urb;
-               urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
-                                               SD_PKT_SZ * SD_NPKT,
-                                               GFP_KERNEL,
-                                               &urb->transfer_dma);
-
-               if (urb->transfer_buffer == NULL) {
-                       pr_err("usb_alloc_coherent failed\n");
-                       return -ENOMEM;
-               }
-               urb->dev = gspca_dev->dev;
-               urb->context = gspca_dev;
-               urb->transfer_buffer_length = SD_PKT_SZ * SD_NPKT;
-               urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
-                                       n & 1 ? 0x82 : 0x83);
-               urb->transfer_flags = URB_ISO_ASAP
-                                       | URB_NO_TRANSFER_DMA_MAP;
-               urb->interval = 1;
-               urb->complete = sd_isoc_irq;
-               urb->number_of_packets = SD_NPKT;
-               for (i = 0; i < SD_NPKT; i++) {
-                       urb->iso_frame_desc[i].length = SD_PKT_SZ;
-                       urb->iso_frame_desc[i].offset = SD_PKT_SZ * i;
-               }
-       }
-
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct usb_interface *intf;
-
-       reg_w(gspca_dev, 0x003c, 0x0003);
-       reg_w(gspca_dev, 0x003c, 0x0004);
-       reg_w(gspca_dev, 0x003c, 0x0005);
-       reg_w(gspca_dev, 0x003c, 0x0006);
-       reg_w(gspca_dev, 0x003c, 0x0007);
-
-       intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
-       usb_set_interface(gspca_dev->dev, gspca_dev->iface,
-                                       intf->num_altsetting - 1);
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,               /* isoc packet */
-                       int len)                /* iso packet length */
-{
-       /* unused */
-}
-
-/* reception of an URB */
-static void sd_isoc_irq(struct urb *urb)
-{
-       struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
-       struct urb *urb0;
-       u8 *data;
-       int i, st;
-
-       PDEBUG(D_PACK, "sd isoc irq");
-       if (!gspca_dev->streaming)
-               return;
-       if (urb->status != 0) {
-               if (urb->status == -ESHUTDOWN)
-                       return;         /* disconnection */
-#ifdef CONFIG_PM
-               if (gspca_dev->frozen)
-                       return;
-#endif
-               pr_err("urb status: %d\n", urb->status);
-               return;
-       }
-
-       /* if this is a control URN (ep 0x83), wait */
-       if (urb == gspca_dev->urb[0] || urb == gspca_dev->urb[2])
-               return;
-
-       /* scan both received URBs */
-       if (urb == gspca_dev->urb[1])
-               urb0 = gspca_dev->urb[0];
-       else
-               urb0 = gspca_dev->urb[2];
-       for (i = 0; i < urb->number_of_packets; i++) {
-
-               /* check the packet status and length */
-               if (urb0->iso_frame_desc[i].actual_length != SD_PKT_SZ
-                   || urb->iso_frame_desc[i].actual_length != SD_PKT_SZ) {
-                       PDEBUG(D_ERR, "ISOC bad lengths %d / %d",
-                               urb0->iso_frame_desc[i].actual_length,
-                               urb->iso_frame_desc[i].actual_length);
-                       gspca_dev->last_packet_type = DISCARD_PACKET;
-                       continue;
-               }
-               st = urb0->iso_frame_desc[i].status;
-               if (st == 0)
-                       st = urb->iso_frame_desc[i].status;
-               if (st) {
-                       pr_err("ISOC data error: [%d] status=%d\n",
-                               i, st);
-                       gspca_dev->last_packet_type = DISCARD_PACKET;
-                       continue;
-               }
-
-               /*
-                * The images are received in URBs of different endpoints
-                * (0x83 and 0x82).
-                * Image pieces in URBs of ep 0x83 are continuated in URBs of
-                * ep 0x82 of the same index.
-                * The packets in the URBs of endpoint 0x83 start with:
-                *      - 80 ba/bb 00 00 = start of image followed by 'ff d8'
-                *      - 04 ba/bb oo oo = image piece
-                *              where 'oo oo' is the image offset
-                                               (not cheked)
-                *      - (other -> bad frame)
-                * The images are JPEG encoded with full header and
-                * normal ff escape.
-                * The end of image ('ff d9') may occur in any URB.
-                * (not cheked)
-                */
-               data = (u8 *) urb0->transfer_buffer
-                                       + urb0->iso_frame_desc[i].offset;
-               if (data[0] == 0x80 && (data[1] & 0xfe) == 0xba) {
-
-                       /* new image */
-                       gspca_frame_add(gspca_dev, LAST_PACKET,
-                                       NULL, 0);
-                       gspca_frame_add(gspca_dev, FIRST_PACKET,
-                                       data + 4, SD_PKT_SZ - 4);
-               } else if (data[0] == 0x04 && (data[1] & 0xfe) == 0xba) {
-                       gspca_frame_add(gspca_dev, INTER_PACKET,
-                                       data + 4, SD_PKT_SZ - 4);
-               } else {
-                       gspca_dev->last_packet_type = DISCARD_PACKET;
-                       continue;
-               }
-               data = (u8 *) urb->transfer_buffer
-                                       + urb->iso_frame_desc[i].offset;
-                       gspca_frame_add(gspca_dev, INTER_PACKET,
-                                       data, SD_PKT_SZ);
-       }
-
-       /* resubmit the URBs */
-       st = usb_submit_urb(urb0, GFP_ATOMIC);
-       if (st < 0)
-               pr_err("usb_submit_urb(0) ret %d\n", st);
-       st = usb_submit_urb(urb, GFP_ATOMIC);
-       if (st < 0)
-               pr_err("usb_submit_urb() ret %d\n", st);
-}
-
-/* sub-driver description */
-static const struct sd_desc sd_desc = {
-       .name = MODULE_NAME,
-       .config = sd_config,
-       .init = sd_init,
-       .start = sd_start,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x04a5, 0x3035)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/conex.c b/drivers/media/video/gspca/conex.c
deleted file mode 100644 (file)
index c9052f2..0000000
+++ /dev/null
@@ -1,966 +0,0 @@
-/*
- *             Connexant Cx11646 library
- *             Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
- *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "conex"
-
-#include "gspca.h"
-#define CONEX_CAM 1            /* special JPEG header */
-#include "jpeg.h"
-
-MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
-MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
-MODULE_LICENSE("GPL");
-
-#define QUALITY 50
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-       struct v4l2_ctrl *brightness;
-       struct v4l2_ctrl *contrast;
-       struct v4l2_ctrl *sat;
-
-       u8 jpeg_hdr[JPEG_HDR_SZ];
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 3},
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 2},
-       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-
-/* the read bytes are found in gspca_dev->usb_buf */
-static void reg_r(struct gspca_dev *gspca_dev,
-                 __u16 index,
-                 __u16 len)
-{
-       struct usb_device *dev = gspca_dev->dev;
-
-#ifdef GSPCA_DEBUG
-       if (len > USB_BUF_SZ) {
-               pr_err("reg_r: buffer overflow\n");
-               return;
-       }
-#endif
-       usb_control_msg(dev,
-                       usb_rcvctrlpipe(dev, 0),
-                       0,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,
-                       index, gspca_dev->usb_buf, len,
-                       500);
-       PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
-                       index, gspca_dev->usb_buf[0]);
-}
-
-/* the bytes to write are in gspca_dev->usb_buf */
-static void reg_w_val(struct gspca_dev *gspca_dev,
-                       __u16 index,
-                       __u8 val)
-{
-       struct usb_device *dev = gspca_dev->dev;
-
-       gspca_dev->usb_buf[0] = val;
-       usb_control_msg(dev,
-                       usb_sndctrlpipe(dev, 0),
-                       0,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,
-                       index, gspca_dev->usb_buf, 1, 500);
-}
-
-static void reg_w(struct gspca_dev *gspca_dev,
-                 __u16 index,
-                 const __u8 *buffer,
-                 __u16 len)
-{
-       struct usb_device *dev = gspca_dev->dev;
-
-#ifdef GSPCA_DEBUG
-       if (len > USB_BUF_SZ) {
-               pr_err("reg_w: buffer overflow\n");
-               return;
-       }
-       PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
-#endif
-       memcpy(gspca_dev->usb_buf, buffer, len);
-       usb_control_msg(dev,
-                       usb_sndctrlpipe(dev, 0),
-                       0,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,
-                       index, gspca_dev->usb_buf, len, 500);
-}
-
-static const __u8 cx_sensor_init[][4] = {
-       {0x88, 0x11, 0x01, 0x01},
-       {0x88, 0x12, 0x70, 0x01},
-       {0x88, 0x0f, 0x00, 0x01},
-       {0x88, 0x05, 0x01, 0x01},
-       {}
-};
-
-static const __u8 cx11646_fw1[][3] = {
-       {0x00, 0x02, 0x00},
-       {0x01, 0x43, 0x00},
-       {0x02, 0xA7, 0x00},
-       {0x03, 0x8B, 0x01},
-       {0x04, 0xE9, 0x02},
-       {0x05, 0x08, 0x04},
-       {0x06, 0x08, 0x05},
-       {0x07, 0x07, 0x06},
-       {0x08, 0xE7, 0x06},
-       {0x09, 0xC6, 0x07},
-       {0x0A, 0x86, 0x08},
-       {0x0B, 0x46, 0x09},
-       {0x0C, 0x05, 0x0A},
-       {0x0D, 0xA5, 0x0A},
-       {0x0E, 0x45, 0x0B},
-       {0x0F, 0xE5, 0x0B},
-       {0x10, 0x85, 0x0C},
-       {0x11, 0x25, 0x0D},
-       {0x12, 0xC4, 0x0D},
-       {0x13, 0x45, 0x0E},
-       {0x14, 0xE4, 0x0E},
-       {0x15, 0x64, 0x0F},
-       {0x16, 0xE4, 0x0F},
-       {0x17, 0x64, 0x10},
-       {0x18, 0xE4, 0x10},
-       {0x19, 0x64, 0x11},
-       {0x1A, 0xE4, 0x11},
-       {0x1B, 0x64, 0x12},
-       {0x1C, 0xE3, 0x12},
-       {0x1D, 0x44, 0x13},
-       {0x1E, 0xC3, 0x13},
-       {0x1F, 0x24, 0x14},
-       {0x20, 0xA3, 0x14},
-       {0x21, 0x04, 0x15},
-       {0x22, 0x83, 0x15},
-       {0x23, 0xE3, 0x15},
-       {0x24, 0x43, 0x16},
-       {0x25, 0xA4, 0x16},
-       {0x26, 0x23, 0x17},
-       {0x27, 0x83, 0x17},
-       {0x28, 0xE3, 0x17},
-       {0x29, 0x43, 0x18},
-       {0x2A, 0xA3, 0x18},
-       {0x2B, 0x03, 0x19},
-       {0x2C, 0x63, 0x19},
-       {0x2D, 0xC3, 0x19},
-       {0x2E, 0x22, 0x1A},
-       {0x2F, 0x63, 0x1A},
-       {0x30, 0xC3, 0x1A},
-       {0x31, 0x23, 0x1B},
-       {0x32, 0x83, 0x1B},
-       {0x33, 0xE2, 0x1B},
-       {0x34, 0x23, 0x1C},
-       {0x35, 0x83, 0x1C},
-       {0x36, 0xE2, 0x1C},
-       {0x37, 0x23, 0x1D},
-       {0x38, 0x83, 0x1D},
-       {0x39, 0xE2, 0x1D},
-       {0x3A, 0x23, 0x1E},
-       {0x3B, 0x82, 0x1E},
-       {0x3C, 0xC3, 0x1E},
-       {0x3D, 0x22, 0x1F},
-       {0x3E, 0x63, 0x1F},
-       {0x3F, 0xC1, 0x1F},
-       {}
-};
-static void cx11646_fw(struct gspca_dev*gspca_dev)
-{
-       int i = 0;
-
-       reg_w_val(gspca_dev, 0x006a, 0x02);
-       while (cx11646_fw1[i][1]) {
-               reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
-               i++;
-       }
-       reg_w_val(gspca_dev, 0x006a, 0x00);
-}
-
-static const __u8 cxsensor[] = {
-       0x88, 0x12, 0x70, 0x01,
-       0x88, 0x0d, 0x02, 0x01,
-       0x88, 0x0f, 0x00, 0x01,
-       0x88, 0x03, 0x71, 0x01, 0x88, 0x04, 0x00, 0x01, /* 3 */
-       0x88, 0x02, 0x10, 0x01,
-       0x88, 0x00, 0xD4, 0x01, 0x88, 0x01, 0x01, 0x01, /* 5 */
-       0x88, 0x0B, 0x00, 0x01,
-       0x88, 0x0A, 0x0A, 0x01,
-       0x88, 0x00, 0x08, 0x01, 0x88, 0x01, 0x00, 0x01, /* 8 */
-       0x88, 0x05, 0x01, 0x01,
-       0xA1, 0x18, 0x00, 0x01,
-       0x00
-};
-
-static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
-static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
-static const __u8 reg10[] = { 0xb1, 0xb1 };
-static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e };       /* 640 */
-static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
-       /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
-static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
-                                       /* 320{0x04,0x0c,0x05,0x0f}; //320 */
-static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 };       /* 176 */
-static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
-
-static void cx_sensor(struct gspca_dev*gspca_dev)
-{
-       int i = 0;
-       int length;
-       const __u8 *ptsensor = cxsensor;
-
-       reg_w(gspca_dev, 0x0020, reg20, 8);
-       reg_w(gspca_dev, 0x0028, reg28, 8);
-       reg_w(gspca_dev, 0x0010, reg10, 2);
-       reg_w_val(gspca_dev, 0x0092, 0x03);
-
-       switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
-       case 0:
-               reg_w(gspca_dev, 0x0071, reg71a, 4);
-               break;
-       case 1:
-               reg_w(gspca_dev, 0x0071, reg71b, 4);
-               break;
-       default:
-/*     case 2: */
-               reg_w(gspca_dev, 0x0071, reg71c, 4);
-               break;
-       case 3:
-               reg_w(gspca_dev, 0x0071, reg71d, 4);
-               break;
-       }
-       reg_w(gspca_dev, 0x007b, reg7b, 6);
-       reg_w_val(gspca_dev, 0x00f8, 0x00);
-       reg_w(gspca_dev, 0x0010, reg10, 2);
-       reg_w_val(gspca_dev, 0x0098, 0x41);
-       for (i = 0; i < 11; i++) {
-               if (i == 3 || i == 5 || i == 8)
-                       length = 8;
-               else
-                       length = 4;
-               reg_w(gspca_dev, 0x00e5, ptsensor, length);
-               if (length == 4)
-                       reg_r(gspca_dev, 0x00e8, 1);
-               else
-                       reg_r(gspca_dev, 0x00e8, length);
-               ptsensor += length;
-       }
-       reg_r(gspca_dev, 0x00e7, 8);
-}
-
-static const __u8 cx_inits_176[] = {
-       0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
-       0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
-       0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
-       0x3B, 0x25, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00,
-       0xDC, 0xFF, 0xEE, 0xFF, 0xC5, 0xFF, 0xBF, 0xFF,
-       0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
-       0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-static const __u8 cx_inits_320[] = {
-       0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
-       0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
-       0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
-       0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-       0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
-       0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
-       0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-static const __u8 cx_inits_352[] = {
-       0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
-       0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
-       0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
-       0x3b, 0x30, 0x25, 0x1b, 0x10, 0x05, 0x00, 0x00,
-       0xe3, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
-       0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
-       0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-static const __u8 cx_inits_640[] = {
-       0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
-       0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
-       0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
-       0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-       0xe2, 0xff, 0xf1, 0xff, 0xc2, 0xff, 0xbc, 0xff,
-       0xf6, 0xff, 0x7b, 0xff, 0x01, 0x02, 0x43, 0x02,
-       0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static void cx11646_initsize(struct gspca_dev *gspca_dev)
-{
-       const __u8 *cxinit;
-       static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
-       static const __u8 reg17[] =
-                       { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
-
-       switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
-       case 0:
-               cxinit = cx_inits_640;
-               break;
-       case 1:
-               cxinit = cx_inits_352;
-               break;
-       default:
-/*     case 2: */
-               cxinit = cx_inits_320;
-               break;
-       case 3:
-               cxinit = cx_inits_176;
-               break;
-       }
-       reg_w_val(gspca_dev, 0x009a, 0x01);
-       reg_w_val(gspca_dev, 0x0010, 0x10);
-       reg_w(gspca_dev, 0x0012, reg12, 5);
-       reg_w(gspca_dev, 0x0017, reg17, 8);
-       reg_w_val(gspca_dev, 0x00c0, 0x00);
-       reg_w_val(gspca_dev, 0x00c1, 0x04);
-       reg_w_val(gspca_dev, 0x00c2, 0x04);
-
-       reg_w(gspca_dev, 0x0061, cxinit, 8);
-       cxinit += 8;
-       reg_w(gspca_dev, 0x00ca, cxinit, 8);
-       cxinit += 8;
-       reg_w(gspca_dev, 0x00d2, cxinit, 8);
-       cxinit += 8;
-       reg_w(gspca_dev, 0x00da, cxinit, 6);
-       cxinit += 8;
-       reg_w(gspca_dev, 0x0041, cxinit, 8);
-       cxinit += 8;
-       reg_w(gspca_dev, 0x0049, cxinit, 8);
-       cxinit += 8;
-       reg_w(gspca_dev, 0x0051, cxinit, 2);
-
-       reg_r(gspca_dev, 0x0010, 1);
-}
-
-static const __u8 cx_jpeg_init[][8] = {
-       {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15},       /* 1 */
-       {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
-       {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
-       {0x20, 0x1d, 0x1d, 0x20, 0x41, 0x2e, 0x31, 0x26},
-       {0x35, 0x4d, 0x43, 0x51, 0x4f, 0x4b, 0x43, 0x4a},
-       {0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A, 0x73},
-       {0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73, 0x7D},
-       {0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95, 0xA0},
-       {0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83, 0x01},
-       {0x15, 0x0F, 0x10, 0x12, 0x10, 0x0D, 0x15, 0x12},
-       {0x11, 0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35},
-       {0x22, 0x20, 0x1D, 0x1D, 0x20, 0x41, 0x2E, 0x31},
-       {0x26, 0x35, 0x4D, 0x43, 0x51, 0x4F, 0x4B, 0x43},
-       {0x4A, 0x49, 0x55, 0x5F, 0x79, 0x67, 0x55, 0x5A},
-       {0x73, 0x5B, 0x49, 0x4A, 0x6A, 0x90, 0x6B, 0x73},
-       {0x7D, 0x81, 0x88, 0x89, 0x88, 0x52, 0x66, 0x95},
-       {0xA0, 0x94, 0x84, 0x9E, 0x79, 0x85, 0x88, 0x83},
-       {0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05},
-       {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00},
-       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02},
-       {0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A},
-       {0x0B, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01},
-       {0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00},
-       {0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
-       {0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00},
-       {0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05},
-       {0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 0x01},
-       {0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21},
-       {0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22},
-       {0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23},
-       {0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24},
-       {0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17},
-       {0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29},
-       {0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A},
-       {0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A},
-       {0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A},
-       {0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A},
-       {0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A},
-       {0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A},
-       {0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99},
-       {0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8},
-       {0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7},
-       {0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6},
-       {0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5},
-       {0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3},
-       {0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1},
-       {0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9},
-       {0xFA, 0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04},
-       {0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01},
-       {0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04},
-       {0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07},
-       {0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14},
-       {0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33},
-       {0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16},
-       {0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19},
-       {0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36},
-       {0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46},
-       {0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56},
-       {0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66},
-       {0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76},
-       {0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85},
-       {0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94},
-       {0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3},
-       {0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2},
-       {0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA},
-       {0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9},
-       {0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8},
-       {0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7},
-       {0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6},
-       {0xF7, 0xF8, 0xF9, 0xFA, 0xFF, 0x20, 0x00, 0x1F},
-       {0x02, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00},
-       {0x00, 0x00, 0x11, 0x00, 0x11, 0x22, 0x00, 0x22},
-       {0x22, 0x11, 0x22, 0x22, 0x11, 0x33, 0x33, 0x11},
-       {0x44, 0x66, 0x22, 0x55, 0x66, 0xFF, 0xDD, 0x00},
-       {0x04, 0x00, 0x14, 0xFF, 0xC0, 0x00, 0x11, 0x08},
-       {0x00, 0xF0, 0x01, 0x40, 0x03, 0x00, 0x21, 0x00},
-       {0x01, 0x11, 0x01, 0x02, 0x11, 0x01, 0xFF, 0xDA},
-       {0x00, 0x0C, 0x03, 0x00, 0x00, 0x01, 0x11, 0x02},
-       {0x11, 0x00, 0x3F, 0x00, 0xFF, 0xD9, 0x00, 0x00}        /* 79 */
-};
-
-
-static const __u8 cxjpeg_640[][8] = {
-       {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10},       /* 1 */
-       {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
-       {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
-       {0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25, 0x1d},
-       {0x28, 0x3a, 0x33, 0x3D, 0x3C, 0x39, 0x33, 0x38},
-       {0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44, 0x57},
-       {0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57, 0x5F},
-       {0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71, 0x79},
-       {0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63, 0x01},
-       {0x10, 0x0B, 0x0C, 0x0E, 0x0C, 0x0A, 0x10, 0x0E},
-       {0x0D, 0x0E, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28},
-       {0x1A, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25},
-       {0x1D, 0x28, 0x3A, 0x33, 0x3D, 0x3C, 0x39, 0x33},
-       {0x38, 0x37, 0x40, 0x48, 0x5C, 0x4E, 0x40, 0x44},
-       {0x57, 0x45, 0x37, 0x38, 0x50, 0x6D, 0x51, 0x57},
-       {0x5F, 0x62, 0x67, 0x68, 0x67, 0x3E, 0x4D, 0x71},
-       {0x79, 0x70, 0x64, 0x78, 0x5C, 0x65, 0x67, 0x63},
-       {0xFF, 0x20, 0x00, 0x1F, 0x00, 0x83, 0x00, 0x00},
-       {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
-       {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
-       {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
-       {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x28, 0xFF},
-       {0xC0, 0x00, 0x11, 0x08, 0x01, 0xE0, 0x02, 0x80},
-       {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
-       {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
-       {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
-       {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}        /* 27 */
-};
-static const __u8 cxjpeg_352[][8] = {
-       {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
-       {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
-       {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
-       {0x13, 0x11, 0x11, 0x13, 0x26, 0x1b, 0x1d, 0x17},
-       {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
-       {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
-       {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
-       {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
-       {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
-       {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
-       {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
-       {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
-       {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
-       {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
-       {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
-       {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
-       {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
-       {0xFF, 0x20, 0x00, 0x1F, 0x01, 0x83, 0x00, 0x00},
-       {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
-       {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
-       {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
-       {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x16, 0xFF},
-       {0xC0, 0x00, 0x11, 0x08, 0x01, 0x20, 0x01, 0x60},
-       {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
-       {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
-       {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
-       {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
-};
-static const __u8 cxjpeg_320[][8] = {
-       {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
-       {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
-       {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
-       {0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09},
-       {0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0f, 0x11},
-       {0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14, 0x1A},
-       {0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A, 0x1D},
-       {0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22, 0x24},
-       {0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E, 0x01},
-       {0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04},
-       {0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0C},
-       {0x08, 0x07, 0x07, 0x07, 0x07, 0x0F, 0x0B, 0x0B},
-       {0x09, 0x0C, 0x11, 0x0F, 0x12, 0x12, 0x11, 0x0F},
-       {0x11, 0x11, 0x13, 0x16, 0x1C, 0x17, 0x13, 0x14},
-       {0x1A, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1A},
-       {0x1D, 0x1D, 0x1F, 0x1F, 0x1F, 0x13, 0x17, 0x22},
-       {0x24, 0x22, 0x1E, 0x24, 0x1C, 0x1E, 0x1F, 0x1E},
-       {0xFF, 0x20, 0x00, 0x1F, 0x02, 0x0C, 0x00, 0x00},
-       {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
-       {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
-       {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
-       {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x14, 0xFF},
-       {0xC0, 0x00, 0x11, 0x08, 0x00, 0xF0, 0x01, 0x40},
-       {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
-       {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
-       {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
-       {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}        /* 27 */
-};
-static const __u8 cxjpeg_176[][8] = {
-       {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
-       {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
-       {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
-       {0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D, 0x17},
-       {0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28, 0x2C},
-       {0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35, 0x44},
-       {0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44, 0x4A},
-       {0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58, 0x5F},
-       {0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D, 0x01},
-       {0x0D, 0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B},
-       {0x0A, 0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F},
-       {0x14, 0x13, 0x11, 0x11, 0x13, 0x26, 0x1B, 0x1D},
-       {0x17, 0x1F, 0x2D, 0x28, 0x30, 0x2F, 0x2D, 0x28},
-       {0x2C, 0x2B, 0x32, 0x38, 0x48, 0x3D, 0x32, 0x35},
-       {0x44, 0x36, 0x2B, 0x2C, 0x3F, 0x55, 0x3F, 0x44},
-       {0x4A, 0x4D, 0x50, 0x51, 0x50, 0x30, 0x3C, 0x58},
-       {0x5F, 0x58, 0x4E, 0x5E, 0x48, 0x4F, 0x50, 0x4D},
-       {0xFF, 0x20, 0x00, 0x1F, 0x03, 0xA1, 0x00, 0x00},
-       {0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00},
-       {0x11, 0x22, 0x00, 0x22, 0x22, 0x11, 0x22, 0x22},
-       {0x11, 0x33, 0x33, 0x11, 0x44, 0x66, 0x22, 0x55},
-       {0x66, 0xFF, 0xDD, 0x00, 0x04, 0x00, 0x0B, 0xFF},
-       {0xC0, 0x00, 0x11, 0x08, 0x00, 0x90, 0x00, 0xB0},
-       {0x03, 0x00, 0x21, 0x00, 0x01, 0x11, 0x01, 0x02},
-       {0x11, 0x01, 0xFF, 0xDA, 0x00, 0x0C, 0x03, 0x00},
-       {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
-       {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
-};
-/* 640 take with the zcx30x part */
-static const __u8 cxjpeg_qtable[][8] = {
-       {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
-       {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
-       {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
-       {0x0c, 0x0b, 0x0b, 0x0c, 0x19, 0x12, 0x13, 0x0f},
-       {0x14, 0x1d, 0x1a, 0x1f, 0x1e, 0x1d, 0x1a, 0x1c},
-       {0x1c, 0x20, 0x24, 0x2e, 0x27, 0x20, 0x22, 0x2c},
-       {0x23, 0x1c, 0x1c, 0x28, 0x37, 0x29, 0x2c, 0x30},
-       {0x31, 0x34, 0x34, 0x34, 0x1f, 0x27, 0x39, 0x3d},
-       {0x38, 0x32, 0x3c, 0x2e, 0x33, 0x34, 0x32, 0x01},
-       {0x09, 0x09, 0x09, 0x0c, 0x0b, 0x0c, 0x18, 0x0a},
-       {0x0a, 0x18, 0x32, 0x21, 0x1c, 0x21, 0x32, 0x32},
-       {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
-       {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
-       {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
-       {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
-       {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
-       {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32},
-       {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}        /* 18 */
-};
-
-
-static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
-{
-       int i;
-       int length;
-
-       reg_w_val(gspca_dev, 0x00c0, 0x01);
-       reg_w_val(gspca_dev, 0x00c3, 0x00);
-       reg_w_val(gspca_dev, 0x00c0, 0x00);
-       reg_r(gspca_dev, 0x0001, 1);
-       length = 8;
-       for (i = 0; i < 79; i++) {
-               if (i == 78)
-                       length = 6;
-               reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
-       }
-       reg_r(gspca_dev, 0x0002, 1);
-       reg_w_val(gspca_dev, 0x0055, 0x14);
-}
-
-static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
-static const __u8 regE5_8[] =
-               { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
-static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
-static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
-static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
-static const __u8 reg51[] = { 0x77, 0x03 };
-#define reg70 0x03
-
-static void cx11646_jpeg(struct gspca_dev*gspca_dev)
-{
-       int i;
-       int length;
-       __u8 Reg55;
-       int retry;
-
-       reg_w_val(gspca_dev, 0x00c0, 0x01);
-       reg_w_val(gspca_dev, 0x00c3, 0x00);
-       reg_w_val(gspca_dev, 0x00c0, 0x00);
-       reg_r(gspca_dev, 0x0001, 1);
-       length = 8;
-       switch (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv) {
-       case 0:
-               for (i = 0; i < 27; i++) {
-                       if (i == 26)
-                               length = 2;
-                       reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
-               }
-               Reg55 = 0x28;
-               break;
-       case 1:
-               for (i = 0; i < 27; i++) {
-                       if (i == 26)
-                               length = 2;
-                       reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
-               }
-               Reg55 = 0x16;
-               break;
-       default:
-/*     case 2: */
-               for (i = 0; i < 27; i++) {
-                       if (i == 26)
-                               length = 2;
-                       reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
-               }
-               Reg55 = 0x14;
-               break;
-       case 3:
-               for (i = 0; i < 27; i++) {
-                       if (i == 26)
-                               length = 2;
-                       reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
-               }
-               Reg55 = 0x0B;
-               break;
-       }
-
-       reg_r(gspca_dev, 0x0002, 1);
-       reg_w_val(gspca_dev, 0x0055, Reg55);
-       reg_r(gspca_dev, 0x0002, 1);
-       reg_w(gspca_dev, 0x0010, reg10, 2);
-       reg_w_val(gspca_dev, 0x0054, 0x02);
-       reg_w_val(gspca_dev, 0x0054, 0x01);
-       reg_w_val(gspca_dev, 0x0000, 0x94);
-       reg_w_val(gspca_dev, 0x0053, 0xc0);
-       reg_w_val(gspca_dev, 0x00fc, 0xe1);
-       reg_w_val(gspca_dev, 0x0000, 0x00);
-       /* wait for completion */
-       retry = 50;
-       do {
-               reg_r(gspca_dev, 0x0002, 1);
-                                                       /* 0x07 until 0x00 */
-               if (gspca_dev->usb_buf[0] == 0x00)
-                       break;
-               reg_w_val(gspca_dev, 0x0053, 0x00);
-       } while (--retry);
-       if (retry == 0)
-               PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
-       /* send the qtable now */
-       reg_r(gspca_dev, 0x0001, 1);            /* -> 0x18 */
-       length = 8;
-       for (i = 0; i < 18; i++) {
-               if (i == 17)
-                       length = 2;
-               reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
-
-       }
-       reg_r(gspca_dev, 0x0002, 1);    /* 0x00 */
-       reg_r(gspca_dev, 0x0053, 1);    /* 0x00 */
-       reg_w_val(gspca_dev, 0x0054, 0x02);
-       reg_w_val(gspca_dev, 0x0054, 0x01);
-       reg_w_val(gspca_dev, 0x0000, 0x94);
-       reg_w_val(gspca_dev, 0x0053, 0xc0);
-
-       reg_r(gspca_dev, 0x0038, 1);            /* 0x40 */
-       reg_r(gspca_dev, 0x0038, 1);            /* 0x40 */
-       reg_r(gspca_dev, 0x001f, 1);            /* 0x38 */
-       reg_w(gspca_dev, 0x0012, reg12, 5);
-       reg_w(gspca_dev, 0x00e5, regE5_8, 8);
-       reg_r(gspca_dev, 0x00e8, 8);
-       reg_w(gspca_dev, 0x00e5, regE5a, 4);
-       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
-       reg_w_val(gspca_dev, 0x009a, 0x01);
-       reg_w(gspca_dev, 0x00e5, regE5b, 4);
-       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
-       reg_w(gspca_dev, 0x00e5, regE5c, 4);
-       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
-
-       reg_w(gspca_dev, 0x0051, reg51, 2);
-       reg_w(gspca_dev, 0x0010, reg10, 2);
-       reg_w_val(gspca_dev, 0x0070, reg70);
-}
-
-static void cx11646_init1(struct gspca_dev *gspca_dev)
-{
-       int i = 0;
-
-       reg_w_val(gspca_dev, 0x0010, 0x00);
-       reg_w_val(gspca_dev, 0x0053, 0x00);
-       reg_w_val(gspca_dev, 0x0052, 0x00);
-       reg_w_val(gspca_dev, 0x009b, 0x2f);
-       reg_w_val(gspca_dev, 0x009c, 0x10);
-       reg_r(gspca_dev, 0x0098, 1);
-       reg_w_val(gspca_dev, 0x0098, 0x40);
-       reg_r(gspca_dev, 0x0099, 1);
-       reg_w_val(gspca_dev, 0x0099, 0x07);
-       reg_w_val(gspca_dev, 0x0039, 0x40);
-       reg_w_val(gspca_dev, 0x003c, 0xff);
-       reg_w_val(gspca_dev, 0x003f, 0x1f);
-       reg_w_val(gspca_dev, 0x003d, 0x40);
-/*     reg_w_val(gspca_dev, 0x003d, 0x60); */
-       reg_r(gspca_dev, 0x0099, 1);                    /* ->0x07 */
-
-       while (cx_sensor_init[i][0]) {
-               reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
-               reg_r(gspca_dev, 0x00e8, 1);            /* -> 0x00 */
-               if (i == 1) {
-                       reg_w_val(gspca_dev, 0x00ed, 0x01);
-                       reg_r(gspca_dev, 0x00ed, 1);    /* -> 0x01 */
-               }
-               i++;
-       }
-       reg_w_val(gspca_dev, 0x00c3, 0x00);
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct cam *cam;
-
-       cam = &gspca_dev->cam;
-       cam->cam_mode = vga_mode;
-       cam->nmodes = ARRAY_SIZE(vga_mode);
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       cx11646_init1(gspca_dev);
-       cx11646_initsize(gspca_dev);
-       cx11646_fw(gspca_dev);
-       cx_sensor(gspca_dev);
-       cx11646_jpegInit(gspca_dev);
-       return 0;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* create the JPEG header */
-       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
-                       0x22);          /* JPEG 411 */
-       jpeg_set_qual(sd->jpeg_hdr, QUALITY);
-
-       cx11646_initsize(gspca_dev);
-       cx11646_fw(gspca_dev);
-       cx_sensor(gspca_dev);
-       cx11646_jpeg(gspca_dev);
-       return 0;
-}
-
-/* called on streamoff with alt 0 and on disconnect */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       int retry = 50;
-
-       if (!gspca_dev->present)
-               return;
-       reg_w_val(gspca_dev, 0x0000, 0x00);
-       reg_r(gspca_dev, 0x0002, 1);
-       reg_w_val(gspca_dev, 0x0053, 0x00);
-
-       while (retry--) {
-/*             reg_r(gspca_dev, 0x0002, 1);*/
-               reg_r(gspca_dev, 0x0053, 1);
-               if (gspca_dev->usb_buf[0] == 0)
-                       break;
-       }
-       reg_w_val(gspca_dev, 0x0000, 0x00);
-       reg_r(gspca_dev, 0x0002, 1);
-
-       reg_w_val(gspca_dev, 0x0010, 0x00);
-       reg_r(gspca_dev, 0x0033, 1);
-       reg_w_val(gspca_dev, 0x00fc, 0xe0);
-}
-
-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 (data[0] == 0xff && data[1] == 0xd8) {
-
-               /* start of frame */
-               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-
-               /* put the JPEG header in the new frame */
-               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                               sd->jpeg_hdr, JPEG_HDR_SZ);
-               data += 2;
-               len -= 2;
-       }
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val, s32 sat)
-{
-       __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
-       __u8 reg51c[2];
-
-       regE5cbx[2] = val;
-       reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
-       reg_r(gspca_dev, 0x00e8, 8);
-       reg_w(gspca_dev, 0x00e5, regE5c, 4);
-       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
-
-       reg51c[0] = 0x77;
-       reg51c[1] = sat;
-       reg_w(gspca_dev, 0x0051, reg51c, 2);
-       reg_w(gspca_dev, 0x0010, reg10, 2);
-       reg_w_val(gspca_dev, 0x0070, reg70);
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, s32 val, s32 sat)
-{
-       __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 };   /* seem MSB */
-/*     __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01};     * LSB */
-       __u8 reg51c[2];
-
-       regE5acx[2] = val;
-       reg_w(gspca_dev, 0x00e5, regE5acx, 4);
-       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
-       reg51c[0] = 0x77;
-       reg51c[1] = sat;
-       reg_w(gspca_dev, 0x0051, reg51c, 2);
-       reg_w(gspca_dev, 0x0010, reg10, 2);
-       reg_w_val(gspca_dev, 0x0070, reg70);
-}
-
-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_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val, sd->sat->cur.val);
-               break;
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val, sd->sat->cur.val);
-               break;
-       case V4L2_CID_SATURATION:
-               setbrightness(gspca_dev, sd->brightness->cur.val, ctrl->val);
-               setcontrast(gspca_dev, sd->contrast->cur.val, ctrl->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, 3);
-       sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 0xd4);
-       sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0x0a, 0x1f, 1, 0x0c);
-       sd->sat = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 7, 1, 3);
-       if (hdl->error) {
-               pr_err("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,
-       .stop0 = sd_stop0,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x0572, 0x0041)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/cpia1.c b/drivers/media/video/gspca/cpia1.c
deleted file mode 100644 (file)
index 2499a88..0000000
+++ /dev/null
@@ -1,1905 +0,0 @@
-/*
- * cpia CPiA (1) gspca driver
- *
- * Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com>
- *
- * This module is adapted from the in kernel v4l1 cpia driver which is :
- *
- * (C) Copyright 1999-2000 Peter Pregler
- * (C) Copyright 1999-2000 Scott J. Bertin
- * (C) Copyright 1999-2000 Johannes Erdfelt <johannes@erdfelt.com>
- * (C) Copyright 2000 STMicroelectronics
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "cpia1"
-
-#include <linux/input.h>
-#include "gspca.h"
-
-MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
-MODULE_DESCRIPTION("Vision CPiA");
-MODULE_LICENSE("GPL");
-
-/* constant value's */
-#define MAGIC_0                0x19
-#define MAGIC_1                0x68
-#define DATA_IN                0xc0
-#define DATA_OUT       0x40
-#define VIDEOSIZE_QCIF 0       /* 176x144 */
-#define VIDEOSIZE_CIF  1       /* 352x288 */
-#define SUBSAMPLE_420  0
-#define SUBSAMPLE_422  1
-#define YUVORDER_YUYV  0
-#define YUVORDER_UYVY  1
-#define NOT_COMPRESSED 0
-#define COMPRESSED     1
-#define NO_DECIMATION  0
-#define DECIMATION_ENAB        1
-#define EOI            0xff    /* End Of Image */
-#define EOL            0xfd    /* End Of Line */
-#define FRAME_HEADER_SIZE      64
-
-/* Image grab modes */
-#define CPIA_GRAB_SINGLE       0
-#define CPIA_GRAB_CONTINEOUS   1
-
-/* Compression parameters */
-#define CPIA_COMPRESSION_NONE  0
-#define CPIA_COMPRESSION_AUTO  1
-#define CPIA_COMPRESSION_MANUAL        2
-#define CPIA_COMPRESSION_TARGET_QUALITY         0
-#define CPIA_COMPRESSION_TARGET_FRAMERATE       1
-
-/* Return offsets for GetCameraState */
-#define SYSTEMSTATE    0
-#define GRABSTATE      1
-#define STREAMSTATE    2
-#define FATALERROR     3
-#define CMDERROR       4
-#define DEBUGFLAGS     5
-#define VPSTATUS       6
-#define ERRORCODE      7
-
-/* SystemState */
-#define UNINITIALISED_STATE    0
-#define PASS_THROUGH_STATE     1
-#define LO_POWER_STATE         2
-#define HI_POWER_STATE         3
-#define WARM_BOOT_STATE                4
-
-/* GrabState */
-#define GRAB_IDLE              0
-#define GRAB_ACTIVE            1
-#define GRAB_DONE              2
-
-/* StreamState */
-#define STREAM_NOT_READY       0
-#define STREAM_READY           1
-#define STREAM_OPEN            2
-#define STREAM_PAUSED          3
-#define STREAM_FINISHED                4
-
-/* Fatal Error, CmdError, and DebugFlags */
-#define CPIA_FLAG        1
-#define SYSTEM_FLAG      2
-#define INT_CTRL_FLAG    4
-#define PROCESS_FLAG     8
-#define COM_FLAG        16
-#define VP_CTRL_FLAG    32
-#define CAPTURE_FLAG    64
-#define DEBUG_FLAG     128
-
-/* VPStatus */
-#define VP_STATE_OK                    0x00
-
-#define VP_STATE_FAILED_VIDEOINIT      0x01
-#define VP_STATE_FAILED_AECACBINIT     0x02
-#define VP_STATE_AEC_MAX               0x04
-#define VP_STATE_ACB_BMAX              0x08
-
-#define VP_STATE_ACB_RMIN              0x10
-#define VP_STATE_ACB_GMIN              0x20
-#define VP_STATE_ACB_RMAX              0x40
-#define VP_STATE_ACB_GMAX              0x80
-
-/* default (minimum) compensation values */
-#define COMP_RED        220
-#define COMP_GREEN1     214
-#define COMP_GREEN2     COMP_GREEN1
-#define COMP_BLUE       230
-
-/* exposure status */
-#define EXPOSURE_VERY_LIGHT 0
-#define EXPOSURE_LIGHT      1
-#define EXPOSURE_NORMAL     2
-#define EXPOSURE_DARK       3
-#define EXPOSURE_VERY_DARK  4
-
-#define CPIA_MODULE_CPIA                       (0 << 5)
-#define CPIA_MODULE_SYSTEM                     (1 << 5)
-#define CPIA_MODULE_VP_CTRL                    (5 << 5)
-#define CPIA_MODULE_CAPTURE                    (6 << 5)
-#define CPIA_MODULE_DEBUG                      (7 << 5)
-
-#define INPUT (DATA_IN << 8)
-#define OUTPUT (DATA_OUT << 8)
-
-#define CPIA_COMMAND_GetCPIAVersion    (INPUT | CPIA_MODULE_CPIA | 1)
-#define CPIA_COMMAND_GetPnPID          (INPUT | CPIA_MODULE_CPIA | 2)
-#define CPIA_COMMAND_GetCameraStatus   (INPUT | CPIA_MODULE_CPIA | 3)
-#define CPIA_COMMAND_GotoHiPower       (OUTPUT | CPIA_MODULE_CPIA | 4)
-#define CPIA_COMMAND_GotoLoPower       (OUTPUT | CPIA_MODULE_CPIA | 5)
-#define CPIA_COMMAND_GotoSuspend       (OUTPUT | CPIA_MODULE_CPIA | 7)
-#define CPIA_COMMAND_GotoPassThrough   (OUTPUT | CPIA_MODULE_CPIA | 8)
-#define CPIA_COMMAND_ModifyCameraStatus        (OUTPUT | CPIA_MODULE_CPIA | 10)
-
-#define CPIA_COMMAND_ReadVCRegs                (INPUT | CPIA_MODULE_SYSTEM | 1)
-#define CPIA_COMMAND_WriteVCReg                (OUTPUT | CPIA_MODULE_SYSTEM | 2)
-#define CPIA_COMMAND_ReadMCPorts       (INPUT | CPIA_MODULE_SYSTEM | 3)
-#define CPIA_COMMAND_WriteMCPort       (OUTPUT | CPIA_MODULE_SYSTEM | 4)
-#define CPIA_COMMAND_SetBaudRate       (OUTPUT | CPIA_MODULE_SYSTEM | 5)
-#define CPIA_COMMAND_SetECPTiming      (OUTPUT | CPIA_MODULE_SYSTEM | 6)
-#define CPIA_COMMAND_ReadIDATA         (INPUT | CPIA_MODULE_SYSTEM | 7)
-#define CPIA_COMMAND_WriteIDATA                (OUTPUT | CPIA_MODULE_SYSTEM | 8)
-#define CPIA_COMMAND_GenericCall       (OUTPUT | CPIA_MODULE_SYSTEM | 9)
-#define CPIA_COMMAND_I2CStart          (OUTPUT | CPIA_MODULE_SYSTEM | 10)
-#define CPIA_COMMAND_I2CStop           (OUTPUT | CPIA_MODULE_SYSTEM | 11)
-#define CPIA_COMMAND_I2CWrite          (OUTPUT | CPIA_MODULE_SYSTEM | 12)
-#define CPIA_COMMAND_I2CRead           (INPUT | CPIA_MODULE_SYSTEM | 13)
-
-#define CPIA_COMMAND_GetVPVersion      (INPUT | CPIA_MODULE_VP_CTRL | 1)
-#define CPIA_COMMAND_ResetFrameCounter (INPUT | CPIA_MODULE_VP_CTRL | 2)
-#define CPIA_COMMAND_SetColourParams   (OUTPUT | CPIA_MODULE_VP_CTRL | 3)
-#define CPIA_COMMAND_SetExposure       (OUTPUT | CPIA_MODULE_VP_CTRL | 4)
-#define CPIA_COMMAND_SetColourBalance  (OUTPUT | CPIA_MODULE_VP_CTRL | 6)
-#define CPIA_COMMAND_SetSensorFPS      (OUTPUT | CPIA_MODULE_VP_CTRL | 7)
-#define CPIA_COMMAND_SetVPDefaults     (OUTPUT | CPIA_MODULE_VP_CTRL | 8)
-#define CPIA_COMMAND_SetApcor          (OUTPUT | CPIA_MODULE_VP_CTRL | 9)
-#define CPIA_COMMAND_SetFlickerCtrl    (OUTPUT | CPIA_MODULE_VP_CTRL | 10)
-#define CPIA_COMMAND_SetVLOffset       (OUTPUT | CPIA_MODULE_VP_CTRL | 11)
-#define CPIA_COMMAND_GetColourParams   (INPUT | CPIA_MODULE_VP_CTRL | 16)
-#define CPIA_COMMAND_GetColourBalance  (INPUT | CPIA_MODULE_VP_CTRL | 17)
-#define CPIA_COMMAND_GetExposure       (INPUT | CPIA_MODULE_VP_CTRL | 18)
-#define CPIA_COMMAND_SetSensorMatrix   (OUTPUT | CPIA_MODULE_VP_CTRL | 19)
-#define CPIA_COMMAND_ColourBars                (OUTPUT | CPIA_MODULE_VP_CTRL | 25)
-#define CPIA_COMMAND_ReadVPRegs                (INPUT | CPIA_MODULE_VP_CTRL | 30)
-#define CPIA_COMMAND_WriteVPReg                (OUTPUT | CPIA_MODULE_VP_CTRL | 31)
-
-#define CPIA_COMMAND_GrabFrame         (OUTPUT | CPIA_MODULE_CAPTURE | 1)
-#define CPIA_COMMAND_UploadFrame       (OUTPUT | CPIA_MODULE_CAPTURE | 2)
-#define CPIA_COMMAND_SetGrabMode       (OUTPUT | CPIA_MODULE_CAPTURE | 3)
-#define CPIA_COMMAND_InitStreamCap     (OUTPUT | CPIA_MODULE_CAPTURE | 4)
-#define CPIA_COMMAND_FiniStreamCap     (OUTPUT | CPIA_MODULE_CAPTURE | 5)
-#define CPIA_COMMAND_StartStreamCap    (OUTPUT | CPIA_MODULE_CAPTURE | 6)
-#define CPIA_COMMAND_EndStreamCap      (OUTPUT | CPIA_MODULE_CAPTURE | 7)
-#define CPIA_COMMAND_SetFormat         (OUTPUT | CPIA_MODULE_CAPTURE | 8)
-#define CPIA_COMMAND_SetROI            (OUTPUT | CPIA_MODULE_CAPTURE | 9)
-#define CPIA_COMMAND_SetCompression    (OUTPUT | CPIA_MODULE_CAPTURE | 10)
-#define CPIA_COMMAND_SetCompressionTarget (OUTPUT | CPIA_MODULE_CAPTURE | 11)
-#define CPIA_COMMAND_SetYUVThresh      (OUTPUT | CPIA_MODULE_CAPTURE | 12)
-#define CPIA_COMMAND_SetCompressionParams (OUTPUT | CPIA_MODULE_CAPTURE | 13)
-#define CPIA_COMMAND_DiscardFrame      (OUTPUT | CPIA_MODULE_CAPTURE | 14)
-#define CPIA_COMMAND_GrabReset         (OUTPUT | CPIA_MODULE_CAPTURE | 15)
-
-#define CPIA_COMMAND_OutputRS232       (OUTPUT | CPIA_MODULE_DEBUG | 1)
-#define CPIA_COMMAND_AbortProcess      (OUTPUT | CPIA_MODULE_DEBUG | 4)
-#define CPIA_COMMAND_SetDramPage       (OUTPUT | CPIA_MODULE_DEBUG | 5)
-#define CPIA_COMMAND_StartDramUpload   (OUTPUT | CPIA_MODULE_DEBUG | 6)
-#define CPIA_COMMAND_StartDummyDtream  (OUTPUT | CPIA_MODULE_DEBUG | 8)
-#define CPIA_COMMAND_AbortStream       (OUTPUT | CPIA_MODULE_DEBUG | 9)
-#define CPIA_COMMAND_DownloadDRAM      (OUTPUT | CPIA_MODULE_DEBUG | 10)
-#define CPIA_COMMAND_Null              (OUTPUT | CPIA_MODULE_DEBUG | 11)
-
-#define ROUND_UP_EXP_FOR_FLICKER 15
-
-/* Constants for automatic frame rate adjustment */
-#define MAX_EXP       302
-#define MAX_EXP_102   255
-#define LOW_EXP       140
-#define VERY_LOW_EXP   70
-#define TC             94
-#define        EXP_ACC_DARK   50
-#define        EXP_ACC_LIGHT  90
-#define HIGH_COMP_102 160
-#define MAX_COMP      239
-#define DARK_TIME       3
-#define LIGHT_TIME      3
-
-#define FIRMWARE_VERSION(x, y) (sd->params.version.firmwareVersion == (x) && \
-                               sd->params.version.firmwareRevision == (y))
-
-#define CPIA1_CID_COMP_TARGET (V4L2_CTRL_CLASS_USER + 0x1000)
-#define BRIGHTNESS_DEF 50
-#define CONTRAST_DEF 48
-#define SATURATION_DEF 50
-#define FREQ_DEF V4L2_CID_POWER_LINE_FREQUENCY_50HZ
-#define ILLUMINATORS_1_DEF 0
-#define ILLUMINATORS_2_DEF 0
-#define COMP_TARGET_DEF CPIA_COMPRESSION_TARGET_QUALITY
-
-/* Developer's Guide Table 5 p 3-34
- * indexed by [mains][sensorFps.baserate][sensorFps.divisor]*/
-static u8 flicker_jumps[2][2][4] =
-{ { { 76, 38, 19, 9 }, { 92, 46, 23, 11 } },
-  { { 64, 32, 16, 8 }, { 76, 38, 19, 9} }
-};
-
-struct cam_params {
-       struct {
-               u8 firmwareVersion;
-               u8 firmwareRevision;
-               u8 vcVersion;
-               u8 vcRevision;
-       } version;
-       struct {
-               u16 vendor;
-               u16 product;
-               u16 deviceRevision;
-       } pnpID;
-       struct {
-               u8 vpVersion;
-               u8 vpRevision;
-               u16 cameraHeadID;
-       } vpVersion;
-       struct {
-               u8 systemState;
-               u8 grabState;
-               u8 streamState;
-               u8 fatalError;
-               u8 cmdError;
-               u8 debugFlags;
-               u8 vpStatus;
-               u8 errorCode;
-       } status;
-       struct {
-               u8 brightness;
-               u8 contrast;
-               u8 saturation;
-       } colourParams;
-       struct {
-               u8 gainMode;
-               u8 expMode;
-               u8 compMode;
-               u8 centreWeight;
-               u8 gain;
-               u8 fineExp;
-               u8 coarseExpLo;
-               u8 coarseExpHi;
-               u8 redComp;
-               u8 green1Comp;
-               u8 green2Comp;
-               u8 blueComp;
-       } exposure;
-       struct {
-               u8 balanceMode;
-               u8 redGain;
-               u8 greenGain;
-               u8 blueGain;
-       } colourBalance;
-       struct {
-               u8 divisor;
-               u8 baserate;
-       } sensorFps;
-       struct {
-               u8 gain1;
-               u8 gain2;
-               u8 gain4;
-               u8 gain8;
-       } apcor;
-       struct {
-               u8 disabled;
-               u8 flickerMode;
-               u8 coarseJump;
-               u8 allowableOverExposure;
-       } flickerControl;
-       struct {
-               u8 gain1;
-               u8 gain2;
-               u8 gain4;
-               u8 gain8;
-       } vlOffset;
-       struct {
-               u8 mode;
-               u8 decimation;
-       } compression;
-       struct {
-               u8 frTargeting;
-               u8 targetFR;
-               u8 targetQ;
-       } compressionTarget;
-       struct {
-               u8 yThreshold;
-               u8 uvThreshold;
-       } yuvThreshold;
-       struct {
-               u8 hysteresis;
-               u8 threshMax;
-               u8 smallStep;
-               u8 largeStep;
-               u8 decimationHysteresis;
-               u8 frDiffStepThresh;
-               u8 qDiffStepThresh;
-               u8 decimationThreshMod;
-       } compressionParams;
-       struct {
-               u8 videoSize;           /* CIF/QCIF */
-               u8 subSample;
-               u8 yuvOrder;
-       } format;
-       struct {                        /* Intel QX3 specific data */
-               u8 qx3_detected;        /* a QX3 is present */
-               u8 toplight;            /* top light lit , R/W */
-               u8 bottomlight;         /* bottom light lit, R/W */
-               u8 button;              /* snapshot button pressed (R/O) */
-               u8 cradled;             /* microscope is in cradle (R/O) */
-       } qx3;
-       struct {
-               u8 colStart;            /* skip first 8*colStart pixels */
-               u8 colEnd;              /* finish at 8*colEnd pixels */
-               u8 rowStart;            /* skip first 4*rowStart lines */
-               u8 rowEnd;              /* finish at 4*rowEnd lines */
-       } roi;
-       u8 ecpTiming;
-       u8 streamStartLine;
-};
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;             /* !! must be the first item */
-       struct cam_params params;               /* camera settings */
-
-       atomic_t cam_exposure;
-       atomic_t fps;
-       int exposure_count;
-       u8 exposure_status;
-       struct v4l2_ctrl *freq;
-       u8 mainsFreq;                           /* 0 = 50hz, 1 = 60hz */
-       u8 first_frame;
-};
-
-static const struct v4l2_pix_format mode[] = {
-       {160, 120, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
-               /* The sizeimage is trial and error, as with low framerates
-                  the camera will pad out usb frames, making the image
-                  data larger then strictly necessary */
-               .bytesperline = 160,
-               .sizeimage = 65536,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 3},
-       {176, 144, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
-               .bytesperline = 172,
-               .sizeimage = 65536,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2},
-       {320, 240, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 262144,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {352, 288, V4L2_PIX_FMT_CPIA1, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 262144,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-/**********************************************************************
- *
- * General functions
- *
- **********************************************************************/
-
-static int cpia_usb_transferCmd(struct gspca_dev *gspca_dev, u8 *command)
-{
-       u8 requesttype;
-       unsigned int pipe;
-       int ret, databytes = command[6] | (command[7] << 8);
-       /* Sometimes we see spurious EPIPE errors */
-       int retries = 3;
-
-       if (command[0] == DATA_IN) {
-               pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
-               requesttype = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-       } else if (command[0] == DATA_OUT) {
-               pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
-               requesttype = USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-       } else {
-               PDEBUG(D_ERR, "Unexpected first byte of command: %x",
-                      command[0]);
-               return -EINVAL;
-       }
-
-retry:
-       ret = usb_control_msg(gspca_dev->dev, pipe,
-                             command[1],
-                             requesttype,
-                             command[2] | (command[3] << 8),
-                             command[4] | (command[5] << 8),
-                             gspca_dev->usb_buf, databytes, 1000);
-
-       if (ret < 0)
-               pr_err("usb_control_msg %02x, error %d\n", command[1], ret);
-
-       if (ret == -EPIPE && retries > 0) {
-               retries--;
-               goto retry;
-       }
-
-       return (ret < 0) ? ret : 0;
-}
-
-/* send an arbitrary command to the camera */
-static int do_command(struct gspca_dev *gspca_dev, u16 command,
-                     u8 a, u8 b, u8 c, u8 d)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int ret, datasize;
-       u8 cmd[8];
-
-       switch (command) {
-       case CPIA_COMMAND_GetCPIAVersion:
-       case CPIA_COMMAND_GetPnPID:
-       case CPIA_COMMAND_GetCameraStatus:
-       case CPIA_COMMAND_GetVPVersion:
-       case CPIA_COMMAND_GetColourParams:
-       case CPIA_COMMAND_GetColourBalance:
-       case CPIA_COMMAND_GetExposure:
-               datasize = 8;
-               break;
-       case CPIA_COMMAND_ReadMCPorts:
-       case CPIA_COMMAND_ReadVCRegs:
-               datasize = 4;
-               break;
-       default:
-               datasize = 0;
-               break;
-       }
-
-       cmd[0] = command >> 8;
-       cmd[1] = command & 0xff;
-       cmd[2] = a;
-       cmd[3] = b;
-       cmd[4] = c;
-       cmd[5] = d;
-       cmd[6] = datasize;
-       cmd[7] = 0;
-
-       ret = cpia_usb_transferCmd(gspca_dev, cmd);
-       if (ret)
-               return ret;
-
-       switch (command) {
-       case CPIA_COMMAND_GetCPIAVersion:
-               sd->params.version.firmwareVersion = gspca_dev->usb_buf[0];
-               sd->params.version.firmwareRevision = gspca_dev->usb_buf[1];
-               sd->params.version.vcVersion = gspca_dev->usb_buf[2];
-               sd->params.version.vcRevision = gspca_dev->usb_buf[3];
-               break;
-       case CPIA_COMMAND_GetPnPID:
-               sd->params.pnpID.vendor =
-                       gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8);
-               sd->params.pnpID.product =
-                       gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8);
-               sd->params.pnpID.deviceRevision =
-                       gspca_dev->usb_buf[4] | (gspca_dev->usb_buf[5] << 8);
-               break;
-       case CPIA_COMMAND_GetCameraStatus:
-               sd->params.status.systemState = gspca_dev->usb_buf[0];
-               sd->params.status.grabState = gspca_dev->usb_buf[1];
-               sd->params.status.streamState = gspca_dev->usb_buf[2];
-               sd->params.status.fatalError = gspca_dev->usb_buf[3];
-               sd->params.status.cmdError = gspca_dev->usb_buf[4];
-               sd->params.status.debugFlags = gspca_dev->usb_buf[5];
-               sd->params.status.vpStatus = gspca_dev->usb_buf[6];
-               sd->params.status.errorCode = gspca_dev->usb_buf[7];
-               break;
-       case CPIA_COMMAND_GetVPVersion:
-               sd->params.vpVersion.vpVersion = gspca_dev->usb_buf[0];
-               sd->params.vpVersion.vpRevision = gspca_dev->usb_buf[1];
-               sd->params.vpVersion.cameraHeadID =
-                       gspca_dev->usb_buf[2] | (gspca_dev->usb_buf[3] << 8);
-               break;
-       case CPIA_COMMAND_GetColourParams:
-               sd->params.colourParams.brightness = gspca_dev->usb_buf[0];
-               sd->params.colourParams.contrast = gspca_dev->usb_buf[1];
-               sd->params.colourParams.saturation = gspca_dev->usb_buf[2];
-               break;
-       case CPIA_COMMAND_GetColourBalance:
-               sd->params.colourBalance.redGain = gspca_dev->usb_buf[0];
-               sd->params.colourBalance.greenGain = gspca_dev->usb_buf[1];
-               sd->params.colourBalance.blueGain = gspca_dev->usb_buf[2];
-               break;
-       case CPIA_COMMAND_GetExposure:
-               sd->params.exposure.gain = gspca_dev->usb_buf[0];
-               sd->params.exposure.fineExp = gspca_dev->usb_buf[1];
-               sd->params.exposure.coarseExpLo = gspca_dev->usb_buf[2];
-               sd->params.exposure.coarseExpHi = gspca_dev->usb_buf[3];
-               sd->params.exposure.redComp = gspca_dev->usb_buf[4];
-               sd->params.exposure.green1Comp = gspca_dev->usb_buf[5];
-               sd->params.exposure.green2Comp = gspca_dev->usb_buf[6];
-               sd->params.exposure.blueComp = gspca_dev->usb_buf[7];
-               break;
-
-       case CPIA_COMMAND_ReadMCPorts:
-               /* test button press */
-               a = ((gspca_dev->usb_buf[1] & 0x02) == 0);
-               if (a != sd->params.qx3.button) {
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-                       input_report_key(gspca_dev->input_dev, KEY_CAMERA, a);
-                       input_sync(gspca_dev->input_dev);
-#endif
-                       sd->params.qx3.button = a;
-               }
-               if (sd->params.qx3.button) {
-                       /* button pressed - unlock the latch */
-                       do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
-                                  3, 0xdf, 0xdf, 0);
-                       do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
-                                  3, 0xff, 0xff, 0);
-               }
-
-               /* test whether microscope is cradled */
-               sd->params.qx3.cradled = ((gspca_dev->usb_buf[2] & 0x40) == 0);
-               break;
-       }
-
-       return 0;
-}
-
-/* send a command to the camera with an additional data transaction */
-static int do_command_extended(struct gspca_dev *gspca_dev, u16 command,
-                              u8 a, u8 b, u8 c, u8 d,
-                              u8 e, u8 f, u8 g, u8 h,
-                              u8 i, u8 j, u8 k, u8 l)
-{
-       u8 cmd[8];
-
-       cmd[0] = command >> 8;
-       cmd[1] = command & 0xff;
-       cmd[2] = a;
-       cmd[3] = b;
-       cmd[4] = c;
-       cmd[5] = d;
-       cmd[6] = 8;
-       cmd[7] = 0;
-       gspca_dev->usb_buf[0] = e;
-       gspca_dev->usb_buf[1] = f;
-       gspca_dev->usb_buf[2] = g;
-       gspca_dev->usb_buf[3] = h;
-       gspca_dev->usb_buf[4] = i;
-       gspca_dev->usb_buf[5] = j;
-       gspca_dev->usb_buf[6] = k;
-       gspca_dev->usb_buf[7] = l;
-
-       return cpia_usb_transferCmd(gspca_dev, cmd);
-}
-
-/*  find_over_exposure
- *  Finds a suitable value of OverExposure for use with SetFlickerCtrl
- *  Some calculation is required because this value changes with the brightness
- *  set with SetColourParameters
- *
- *  Parameters: Brightness - last brightness value set with SetColourParameters
- *
- *  Returns: OverExposure value to use with SetFlickerCtrl
- */
-#define FLICKER_MAX_EXPOSURE                    250
-#define FLICKER_ALLOWABLE_OVER_EXPOSURE         146
-#define FLICKER_BRIGHTNESS_CONSTANT             59
-static int find_over_exposure(int brightness)
-{
-       int MaxAllowableOverExposure, OverExposure;
-
-       MaxAllowableOverExposure = FLICKER_MAX_EXPOSURE - brightness -
-                                  FLICKER_BRIGHTNESS_CONSTANT;
-
-       if (MaxAllowableOverExposure < FLICKER_ALLOWABLE_OVER_EXPOSURE)
-               OverExposure = MaxAllowableOverExposure;
-       else
-               OverExposure = FLICKER_ALLOWABLE_OVER_EXPOSURE;
-
-       return OverExposure;
-}
-#undef FLICKER_MAX_EXPOSURE
-#undef FLICKER_ALLOWABLE_OVER_EXPOSURE
-#undef FLICKER_BRIGHTNESS_CONSTANT
-
-/* initialise cam_data structure  */
-static void reset_camera_params(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam_params *params = &sd->params;
-
-       /* The following parameter values are the defaults from
-        * "Software Developer's Guide for CPiA Cameras".  Any changes
-        * to the defaults are noted in comments. */
-       params->colourParams.brightness = BRIGHTNESS_DEF;
-       params->colourParams.contrast = CONTRAST_DEF;
-       params->colourParams.saturation = SATURATION_DEF;
-       params->exposure.gainMode = 4;
-       params->exposure.expMode = 2;           /* AEC */
-       params->exposure.compMode = 1;
-       params->exposure.centreWeight = 1;
-       params->exposure.gain = 0;
-       params->exposure.fineExp = 0;
-       params->exposure.coarseExpLo = 185;
-       params->exposure.coarseExpHi = 0;
-       params->exposure.redComp = COMP_RED;
-       params->exposure.green1Comp = COMP_GREEN1;
-       params->exposure.green2Comp = COMP_GREEN2;
-       params->exposure.blueComp = COMP_BLUE;
-       params->colourBalance.balanceMode = 2;  /* ACB */
-       params->colourBalance.redGain = 32;
-       params->colourBalance.greenGain = 6;
-       params->colourBalance.blueGain = 92;
-       params->apcor.gain1 = 0x18;
-       params->apcor.gain2 = 0x16;
-       params->apcor.gain4 = 0x24;
-       params->apcor.gain8 = 0x34;
-       params->vlOffset.gain1 = 20;
-       params->vlOffset.gain2 = 24;
-       params->vlOffset.gain4 = 26;
-       params->vlOffset.gain8 = 26;
-       params->compressionParams.hysteresis = 3;
-       params->compressionParams.threshMax = 11;
-       params->compressionParams.smallStep = 1;
-       params->compressionParams.largeStep = 3;
-       params->compressionParams.decimationHysteresis = 2;
-       params->compressionParams.frDiffStepThresh = 5;
-       params->compressionParams.qDiffStepThresh = 3;
-       params->compressionParams.decimationThreshMod = 2;
-       /* End of default values from Software Developer's Guide */
-
-       /* Set Sensor FPS to 15fps. This seems better than 30fps
-        * for indoor lighting. */
-       params->sensorFps.divisor = 1;
-       params->sensorFps.baserate = 1;
-
-       params->flickerControl.flickerMode = 0;
-       params->flickerControl.disabled = 1;
-       params->flickerControl.coarseJump =
-               flicker_jumps[sd->mainsFreq]
-                            [params->sensorFps.baserate]
-                            [params->sensorFps.divisor];
-       params->flickerControl.allowableOverExposure =
-               find_over_exposure(params->colourParams.brightness);
-
-       params->yuvThreshold.yThreshold = 6; /* From windows driver */
-       params->yuvThreshold.uvThreshold = 6; /* From windows driver */
-
-       params->format.subSample = SUBSAMPLE_420;
-       params->format.yuvOrder = YUVORDER_YUYV;
-
-       params->compression.mode = CPIA_COMPRESSION_AUTO;
-       params->compression.decimation = NO_DECIMATION;
-
-       params->compressionTarget.frTargeting = COMP_TARGET_DEF;
-       params->compressionTarget.targetFR = 15; /* From windows driver */
-       params->compressionTarget.targetQ = 5; /* From windows driver */
-
-       params->qx3.qx3_detected = 0;
-       params->qx3.toplight = 0;
-       params->qx3.bottomlight = 0;
-       params->qx3.button = 0;
-       params->qx3.cradled = 0;
-}
-
-static void printstatus(struct cam_params *params)
-{
-       PDEBUG(D_PROBE, "status: %02x %02x %02x %02x %02x %02x %02x %02x",
-              params->status.systemState, params->status.grabState,
-              params->status.streamState, params->status.fatalError,
-              params->status.cmdError, params->status.debugFlags,
-              params->status.vpStatus, params->status.errorCode);
-}
-
-static int goto_low_power(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int ret;
-
-       ret = do_command(gspca_dev, CPIA_COMMAND_GotoLoPower, 0, 0, 0, 0);
-       if (ret)
-               return ret;
-
-       ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
-       if (ret)
-               return ret;
-
-       if (sd->params.status.systemState != LO_POWER_STATE) {
-               if (sd->params.status.systemState != WARM_BOOT_STATE) {
-                       PDEBUG(D_ERR,
-                              "unexpected state after lo power cmd: %02x",
-                              sd->params.status.systemState);
-                       printstatus(&sd->params);
-               }
-               return -EIO;
-       }
-
-       PDEBUG(D_CONF, "camera now in LOW power state");
-       return 0;
-}
-
-static int goto_high_power(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int ret;
-
-       ret = do_command(gspca_dev, CPIA_COMMAND_GotoHiPower, 0, 0, 0, 0);
-       if (ret)
-               return ret;
-
-       msleep_interruptible(40);       /* windows driver does it too */
-
-       if (signal_pending(current))
-               return -EINTR;
-
-       do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
-       if (ret)
-               return ret;
-
-       if (sd->params.status.systemState != HI_POWER_STATE) {
-               PDEBUG(D_ERR, "unexpected state after hi power cmd: %02x",
-                              sd->params.status.systemState);
-               printstatus(&sd->params);
-               return -EIO;
-       }
-
-       PDEBUG(D_CONF, "camera now in HIGH power state");
-       return 0;
-}
-
-static int get_version_information(struct gspca_dev *gspca_dev)
-{
-       int ret;
-
-       /* GetCPIAVersion */
-       ret = do_command(gspca_dev, CPIA_COMMAND_GetCPIAVersion, 0, 0, 0, 0);
-       if (ret)
-               return ret;
-
-       /* GetPnPID */
-       return do_command(gspca_dev, CPIA_COMMAND_GetPnPID, 0, 0, 0, 0);
-}
-
-static int save_camera_state(struct gspca_dev *gspca_dev)
-{
-       int ret;
-
-       ret = do_command(gspca_dev, CPIA_COMMAND_GetColourBalance, 0, 0, 0, 0);
-       if (ret)
-               return ret;
-
-       return do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
-}
-
-static int command_setformat(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int ret;
-
-       ret = do_command(gspca_dev, CPIA_COMMAND_SetFormat,
-                        sd->params.format.videoSize,
-                        sd->params.format.subSample,
-                        sd->params.format.yuvOrder, 0);
-       if (ret)
-               return ret;
-
-       return do_command(gspca_dev, CPIA_COMMAND_SetROI,
-                         sd->params.roi.colStart, sd->params.roi.colEnd,
-                         sd->params.roi.rowStart, sd->params.roi.rowEnd);
-}
-
-static int command_setcolourparams(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       return do_command(gspca_dev, CPIA_COMMAND_SetColourParams,
-                         sd->params.colourParams.brightness,
-                         sd->params.colourParams.contrast,
-                         sd->params.colourParams.saturation, 0);
-}
-
-static int command_setapcor(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       return do_command(gspca_dev, CPIA_COMMAND_SetApcor,
-                         sd->params.apcor.gain1,
-                         sd->params.apcor.gain2,
-                         sd->params.apcor.gain4,
-                         sd->params.apcor.gain8);
-}
-
-static int command_setvloffset(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       return do_command(gspca_dev, CPIA_COMMAND_SetVLOffset,
-                         sd->params.vlOffset.gain1,
-                         sd->params.vlOffset.gain2,
-                         sd->params.vlOffset.gain4,
-                         sd->params.vlOffset.gain8);
-}
-
-static int command_setexposure(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int ret;
-
-       ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure,
-                                 sd->params.exposure.gainMode,
-                                 1,
-                                 sd->params.exposure.compMode,
-                                 sd->params.exposure.centreWeight,
-                                 sd->params.exposure.gain,
-                                 sd->params.exposure.fineExp,
-                                 sd->params.exposure.coarseExpLo,
-                                 sd->params.exposure.coarseExpHi,
-                                 sd->params.exposure.redComp,
-                                 sd->params.exposure.green1Comp,
-                                 sd->params.exposure.green2Comp,
-                                 sd->params.exposure.blueComp);
-       if (ret)
-               return ret;
-
-       if (sd->params.exposure.expMode != 1) {
-               ret = do_command_extended(gspca_dev, CPIA_COMMAND_SetExposure,
-                                         0,
-                                         sd->params.exposure.expMode,
-                                         0, 0,
-                                         sd->params.exposure.gain,
-                                         sd->params.exposure.fineExp,
-                                         sd->params.exposure.coarseExpLo,
-                                         sd->params.exposure.coarseExpHi,
-                                         0, 0, 0, 0);
-       }
-
-       return ret;
-}
-
-static int command_setcolourbalance(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->params.colourBalance.balanceMode == 1) {
-               int ret;
-
-               ret = do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
-                                1,
-                                sd->params.colourBalance.redGain,
-                                sd->params.colourBalance.greenGain,
-                                sd->params.colourBalance.blueGain);
-               if (ret)
-                       return ret;
-
-               return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
-                                 3, 0, 0, 0);
-       }
-       if (sd->params.colourBalance.balanceMode == 2) {
-               return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
-                                 2, 0, 0, 0);
-       }
-       if (sd->params.colourBalance.balanceMode == 3) {
-               return do_command(gspca_dev, CPIA_COMMAND_SetColourBalance,
-                                 3, 0, 0, 0);
-       }
-
-       return -EINVAL;
-}
-
-static int command_setcompressiontarget(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       return do_command(gspca_dev, CPIA_COMMAND_SetCompressionTarget,
-                         sd->params.compressionTarget.frTargeting,
-                         sd->params.compressionTarget.targetFR,
-                         sd->params.compressionTarget.targetQ, 0);
-}
-
-static int command_setyuvtresh(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       return do_command(gspca_dev, CPIA_COMMAND_SetYUVThresh,
-                         sd->params.yuvThreshold.yThreshold,
-                         sd->params.yuvThreshold.uvThreshold, 0, 0);
-}
-
-static int command_setcompressionparams(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       return do_command_extended(gspca_dev,
-                           CPIA_COMMAND_SetCompressionParams,
-                           0, 0, 0, 0,
-                           sd->params.compressionParams.hysteresis,
-                           sd->params.compressionParams.threshMax,
-                           sd->params.compressionParams.smallStep,
-                           sd->params.compressionParams.largeStep,
-                           sd->params.compressionParams.decimationHysteresis,
-                           sd->params.compressionParams.frDiffStepThresh,
-                           sd->params.compressionParams.qDiffStepThresh,
-                           sd->params.compressionParams.decimationThreshMod);
-}
-
-static int command_setcompression(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       return do_command(gspca_dev, CPIA_COMMAND_SetCompression,
-                         sd->params.compression.mode,
-                         sd->params.compression.decimation, 0, 0);
-}
-
-static int command_setsensorfps(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       return do_command(gspca_dev, CPIA_COMMAND_SetSensorFPS,
-                         sd->params.sensorFps.divisor,
-                         sd->params.sensorFps.baserate, 0, 0);
-}
-
-static int command_setflickerctrl(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       return do_command(gspca_dev, CPIA_COMMAND_SetFlickerCtrl,
-                         sd->params.flickerControl.flickerMode,
-                         sd->params.flickerControl.coarseJump,
-                         sd->params.flickerControl.allowableOverExposure,
-                         0);
-}
-
-static int command_setecptiming(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       return do_command(gspca_dev, CPIA_COMMAND_SetECPTiming,
-                         sd->params.ecpTiming, 0, 0, 0);
-}
-
-static int command_pause(struct gspca_dev *gspca_dev)
-{
-       return do_command(gspca_dev, CPIA_COMMAND_EndStreamCap, 0, 0, 0, 0);
-}
-
-static int command_resume(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       return do_command(gspca_dev, CPIA_COMMAND_InitStreamCap,
-                         0, sd->params.streamStartLine, 0, 0);
-}
-
-static int command_setlights(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int ret, p1, p2;
-
-       p1 = (sd->params.qx3.bottomlight == 0) << 1;
-       p2 = (sd->params.qx3.toplight == 0) << 3;
-
-       ret = do_command(gspca_dev, CPIA_COMMAND_WriteVCReg,
-                        0x90, 0x8f, 0x50, 0);
-       if (ret)
-               return ret;
-
-       return do_command(gspca_dev, CPIA_COMMAND_WriteMCPort, 2, 0,
-                         p1 | p2 | 0xe0, 0);
-}
-
-static int set_flicker(struct gspca_dev *gspca_dev, int on, int apply)
-{
-       /* Everything in here is from the Windows driver */
-/* define for compgain calculation */
-#if 0
-#define COMPGAIN(base, curexp, newexp) \
-    (u8) ((((float) base - 128.0) * ((float) curexp / (float) newexp)) + 128.5)
-#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
-    (u16)((float)curexp * (float)(u8)(curcomp + 128) / \
-    (float)(u8)(basecomp - 128))
-#else
-  /* equivalent functions without floating point math */
-#define COMPGAIN(base, curexp, newexp) \
-    (u8)(128 + (((u32)(2*(base-128)*curexp + newexp)) / (2 * newexp)))
-#define EXP_FROM_COMP(basecomp, curcomp, curexp) \
-    (u16)(((u32)(curexp * (u8)(curcomp + 128)) / (u8)(basecomp - 128)))
-#endif
-
-       struct sd *sd = (struct sd *) gspca_dev;
-       int currentexp = sd->params.exposure.coarseExpLo +
-                        sd->params.exposure.coarseExpHi * 256;
-       int ret, startexp;
-
-       if (on) {
-               int cj = sd->params.flickerControl.coarseJump;
-               sd->params.flickerControl.flickerMode = 1;
-               sd->params.flickerControl.disabled = 0;
-               if (sd->params.exposure.expMode != 2) {
-                       sd->params.exposure.expMode = 2;
-                       sd->exposure_status = EXPOSURE_NORMAL;
-               }
-               currentexp = currentexp << sd->params.exposure.gain;
-               sd->params.exposure.gain = 0;
-               /* round down current exposure to nearest value */
-               startexp = (currentexp + ROUND_UP_EXP_FOR_FLICKER) / cj;
-               if (startexp < 1)
-                       startexp = 1;
-               startexp = (startexp * cj) - 1;
-               if (FIRMWARE_VERSION(1, 2))
-                       while (startexp > MAX_EXP_102)
-                               startexp -= cj;
-               else
-                       while (startexp > MAX_EXP)
-                               startexp -= cj;
-               sd->params.exposure.coarseExpLo = startexp & 0xff;
-               sd->params.exposure.coarseExpHi = startexp >> 8;
-               if (currentexp > startexp) {
-                       if (currentexp > (2 * startexp))
-                               currentexp = 2 * startexp;
-                       sd->params.exposure.redComp =
-                               COMPGAIN(COMP_RED, currentexp, startexp);
-                       sd->params.exposure.green1Comp =
-                               COMPGAIN(COMP_GREEN1, currentexp, startexp);
-                       sd->params.exposure.green2Comp =
-                               COMPGAIN(COMP_GREEN2, currentexp, startexp);
-                       sd->params.exposure.blueComp =
-                               COMPGAIN(COMP_BLUE, currentexp, startexp);
-               } else {
-                       sd->params.exposure.redComp = COMP_RED;
-                       sd->params.exposure.green1Comp = COMP_GREEN1;
-                       sd->params.exposure.green2Comp = COMP_GREEN2;
-                       sd->params.exposure.blueComp = COMP_BLUE;
-               }
-               if (FIRMWARE_VERSION(1, 2))
-                       sd->params.exposure.compMode = 0;
-               else
-                       sd->params.exposure.compMode = 1;
-
-               sd->params.apcor.gain1 = 0x18;
-               sd->params.apcor.gain2 = 0x18;
-               sd->params.apcor.gain4 = 0x16;
-               sd->params.apcor.gain8 = 0x14;
-       } else {
-               sd->params.flickerControl.flickerMode = 0;
-               sd->params.flickerControl.disabled = 1;
-               /* Average equivalent coarse for each comp channel */
-               startexp = EXP_FROM_COMP(COMP_RED,
-                               sd->params.exposure.redComp, currentexp);
-               startexp += EXP_FROM_COMP(COMP_GREEN1,
-                               sd->params.exposure.green1Comp, currentexp);
-               startexp += EXP_FROM_COMP(COMP_GREEN2,
-                               sd->params.exposure.green2Comp, currentexp);
-               startexp += EXP_FROM_COMP(COMP_BLUE,
-                               sd->params.exposure.blueComp, currentexp);
-               startexp = startexp >> 2;
-               while (startexp > MAX_EXP && sd->params.exposure.gain <
-                      sd->params.exposure.gainMode - 1) {
-                       startexp = startexp >> 1;
-                       ++sd->params.exposure.gain;
-               }
-               if (FIRMWARE_VERSION(1, 2) && startexp > MAX_EXP_102)
-                       startexp = MAX_EXP_102;
-               if (startexp > MAX_EXP)
-                       startexp = MAX_EXP;
-               sd->params.exposure.coarseExpLo = startexp & 0xff;
-               sd->params.exposure.coarseExpHi = startexp >> 8;
-               sd->params.exposure.redComp = COMP_RED;
-               sd->params.exposure.green1Comp = COMP_GREEN1;
-               sd->params.exposure.green2Comp = COMP_GREEN2;
-               sd->params.exposure.blueComp = COMP_BLUE;
-               sd->params.exposure.compMode = 1;
-               sd->params.apcor.gain1 = 0x18;
-               sd->params.apcor.gain2 = 0x16;
-               sd->params.apcor.gain4 = 0x24;
-               sd->params.apcor.gain8 = 0x34;
-       }
-       sd->params.vlOffset.gain1 = 20;
-       sd->params.vlOffset.gain2 = 24;
-       sd->params.vlOffset.gain4 = 26;
-       sd->params.vlOffset.gain8 = 26;
-
-       if (apply) {
-               ret = command_setexposure(gspca_dev);
-               if (ret)
-                       return ret;
-
-               ret = command_setapcor(gspca_dev);
-               if (ret)
-                       return ret;
-
-               ret = command_setvloffset(gspca_dev);
-               if (ret)
-                       return ret;
-
-               ret = command_setflickerctrl(gspca_dev);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-#undef EXP_FROM_COMP
-#undef COMPGAIN
-}
-
-/* monitor the exposure and adjust the sensor frame rate if needed */
-static void monitor_exposure(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 exp_acc, bcomp, cmd[8];
-       int ret, light_exp, dark_exp, very_dark_exp;
-       int old_exposure, new_exposure, framerate;
-       int setfps = 0, setexp = 0, setflicker = 0;
-
-       /* get necessary stats and register settings from camera */
-       /* do_command can't handle this, so do it ourselves */
-       cmd[0] = CPIA_COMMAND_ReadVPRegs >> 8;
-       cmd[1] = CPIA_COMMAND_ReadVPRegs & 0xff;
-       cmd[2] = 30;
-       cmd[3] = 4;
-       cmd[4] = 9;
-       cmd[5] = 8;
-       cmd[6] = 8;
-       cmd[7] = 0;
-       ret = cpia_usb_transferCmd(gspca_dev, cmd);
-       if (ret) {
-               pr_err("ReadVPRegs(30,4,9,8) - failed: %d\n", ret);
-               return;
-       }
-       exp_acc = gspca_dev->usb_buf[0];
-       bcomp = gspca_dev->usb_buf[1];
-
-       light_exp = sd->params.colourParams.brightness +
-                   TC - 50 + EXP_ACC_LIGHT;
-       if (light_exp > 255)
-               light_exp = 255;
-       dark_exp = sd->params.colourParams.brightness +
-                  TC - 50 - EXP_ACC_DARK;
-       if (dark_exp < 0)
-               dark_exp = 0;
-       very_dark_exp = dark_exp / 2;
-
-       old_exposure = sd->params.exposure.coarseExpHi * 256 +
-                      sd->params.exposure.coarseExpLo;
-
-       if (!sd->params.flickerControl.disabled) {
-               /* Flicker control on */
-               int max_comp = FIRMWARE_VERSION(1, 2) ? MAX_COMP :
-                                                       HIGH_COMP_102;
-               bcomp += 128;   /* decode */
-               if (bcomp >= max_comp && exp_acc < dark_exp) {
-                       /* dark */
-                       if (exp_acc < very_dark_exp) {
-                               /* very dark */
-                               if (sd->exposure_status == EXPOSURE_VERY_DARK)
-                                       ++sd->exposure_count;
-                               else {
-                                       sd->exposure_status =
-                                               EXPOSURE_VERY_DARK;
-                                       sd->exposure_count = 1;
-                               }
-                       } else {
-                               /* just dark */
-                               if (sd->exposure_status == EXPOSURE_DARK)
-                                       ++sd->exposure_count;
-                               else {
-                                       sd->exposure_status = EXPOSURE_DARK;
-                                       sd->exposure_count = 1;
-                               }
-                       }
-               } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) {
-                       /* light */
-                       if (old_exposure <= VERY_LOW_EXP) {
-                               /* very light */
-                               if (sd->exposure_status == EXPOSURE_VERY_LIGHT)
-                                       ++sd->exposure_count;
-                               else {
-                                       sd->exposure_status =
-                                               EXPOSURE_VERY_LIGHT;
-                                       sd->exposure_count = 1;
-                               }
-                       } else {
-                               /* just light */
-                               if (sd->exposure_status == EXPOSURE_LIGHT)
-                                       ++sd->exposure_count;
-                               else {
-                                       sd->exposure_status = EXPOSURE_LIGHT;
-                                       sd->exposure_count = 1;
-                               }
-                       }
-               } else {
-                       /* not dark or light */
-                       sd->exposure_status = EXPOSURE_NORMAL;
-               }
-       } else {
-               /* Flicker control off */
-               if (old_exposure >= MAX_EXP && exp_acc < dark_exp) {
-                       /* dark */
-                       if (exp_acc < very_dark_exp) {
-                               /* very dark */
-                               if (sd->exposure_status == EXPOSURE_VERY_DARK)
-                                       ++sd->exposure_count;
-                               else {
-                                       sd->exposure_status =
-                                               EXPOSURE_VERY_DARK;
-                                       sd->exposure_count = 1;
-                               }
-                       } else {
-                               /* just dark */
-                               if (sd->exposure_status == EXPOSURE_DARK)
-                                       ++sd->exposure_count;
-                               else {
-                                       sd->exposure_status = EXPOSURE_DARK;
-                                       sd->exposure_count = 1;
-                               }
-                       }
-               } else if (old_exposure <= LOW_EXP || exp_acc > light_exp) {
-                       /* light */
-                       if (old_exposure <= VERY_LOW_EXP) {
-                               /* very light */
-                               if (sd->exposure_status == EXPOSURE_VERY_LIGHT)
-                                       ++sd->exposure_count;
-                               else {
-                                       sd->exposure_status =
-                                               EXPOSURE_VERY_LIGHT;
-                                       sd->exposure_count = 1;
-                               }
-                       } else {
-                               /* just light */
-                               if (sd->exposure_status == EXPOSURE_LIGHT)
-                                       ++sd->exposure_count;
-                               else {
-                                       sd->exposure_status = EXPOSURE_LIGHT;
-                                       sd->exposure_count = 1;
-                               }
-                       }
-               } else {
-                       /* not dark or light */
-                       sd->exposure_status = EXPOSURE_NORMAL;
-               }
-       }
-
-       framerate = atomic_read(&sd->fps);
-       if (framerate > 30 || framerate < 1)
-               framerate = 1;
-
-       if (!sd->params.flickerControl.disabled) {
-               /* Flicker control on */
-               if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
-                    sd->exposure_status == EXPOSURE_DARK) &&
-                   sd->exposure_count >= DARK_TIME * framerate &&
-                   sd->params.sensorFps.divisor < 2) {
-
-                       /* dark for too long */
-                       ++sd->params.sensorFps.divisor;
-                       setfps = 1;
-
-                       sd->params.flickerControl.coarseJump =
-                               flicker_jumps[sd->mainsFreq]
-                                            [sd->params.sensorFps.baserate]
-                                            [sd->params.sensorFps.divisor];
-                       setflicker = 1;
-
-                       new_exposure = sd->params.flickerControl.coarseJump-1;
-                       while (new_exposure < old_exposure / 2)
-                               new_exposure +=
-                                       sd->params.flickerControl.coarseJump;
-                       sd->params.exposure.coarseExpLo = new_exposure & 0xff;
-                       sd->params.exposure.coarseExpHi = new_exposure >> 8;
-                       setexp = 1;
-                       sd->exposure_status = EXPOSURE_NORMAL;
-                       PDEBUG(D_CONF, "Automatically decreasing sensor_fps");
-
-               } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT ||
-                           sd->exposure_status == EXPOSURE_LIGHT) &&
-                          sd->exposure_count >= LIGHT_TIME * framerate &&
-                          sd->params.sensorFps.divisor > 0) {
-
-                       /* light for too long */
-                       int max_exp = FIRMWARE_VERSION(1, 2) ? MAX_EXP_102 :
-                                                              MAX_EXP;
-                       --sd->params.sensorFps.divisor;
-                       setfps = 1;
-
-                       sd->params.flickerControl.coarseJump =
-                               flicker_jumps[sd->mainsFreq]
-                                            [sd->params.sensorFps.baserate]
-                                            [sd->params.sensorFps.divisor];
-                       setflicker = 1;
-
-                       new_exposure = sd->params.flickerControl.coarseJump-1;
-                       while (new_exposure < 2 * old_exposure &&
-                              new_exposure +
-                              sd->params.flickerControl.coarseJump < max_exp)
-                               new_exposure +=
-                                       sd->params.flickerControl.coarseJump;
-                       sd->params.exposure.coarseExpLo = new_exposure & 0xff;
-                       sd->params.exposure.coarseExpHi = new_exposure >> 8;
-                       setexp = 1;
-                       sd->exposure_status = EXPOSURE_NORMAL;
-                       PDEBUG(D_CONF, "Automatically increasing sensor_fps");
-               }
-       } else {
-               /* Flicker control off */
-               if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
-                    sd->exposure_status == EXPOSURE_DARK) &&
-                   sd->exposure_count >= DARK_TIME * framerate &&
-                   sd->params.sensorFps.divisor < 2) {
-
-                       /* dark for too long */
-                       ++sd->params.sensorFps.divisor;
-                       setfps = 1;
-
-                       if (sd->params.exposure.gain > 0) {
-                               --sd->params.exposure.gain;
-                               setexp = 1;
-                       }
-                       sd->exposure_status = EXPOSURE_NORMAL;
-                       PDEBUG(D_CONF, "Automatically decreasing sensor_fps");
-
-               } else if ((sd->exposure_status == EXPOSURE_VERY_LIGHT ||
-                           sd->exposure_status == EXPOSURE_LIGHT) &&
-                          sd->exposure_count >= LIGHT_TIME * framerate &&
-                          sd->params.sensorFps.divisor > 0) {
-
-                       /* light for too long */
-                       --sd->params.sensorFps.divisor;
-                       setfps = 1;
-
-                       if (sd->params.exposure.gain <
-                           sd->params.exposure.gainMode - 1) {
-                               ++sd->params.exposure.gain;
-                               setexp = 1;
-                       }
-                       sd->exposure_status = EXPOSURE_NORMAL;
-                       PDEBUG(D_CONF, "Automatically increasing sensor_fps");
-               }
-       }
-
-       if (setexp)
-               command_setexposure(gspca_dev);
-
-       if (setfps)
-               command_setsensorfps(gspca_dev);
-
-       if (setflicker)
-               command_setflickerctrl(gspca_dev);
-}
-
-/*-----------------------------------------------------------------*/
-/* if flicker is switched off, this function switches it back on.It checks,
-   however, that conditions are suitable before restarting it.
-   This should only be called for firmware version 1.2.
-
-   It also adjust the colour balance when an exposure step is detected - as
-   long as flicker is running
-*/
-static void restart_flicker(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int cam_exposure, old_exp;
-
-       if (!FIRMWARE_VERSION(1, 2))
-               return;
-
-       cam_exposure = atomic_read(&sd->cam_exposure);
-
-       if (sd->params.flickerControl.flickerMode == 0 ||
-           cam_exposure == 0)
-               return;
-
-       old_exp = sd->params.exposure.coarseExpLo +
-                 sd->params.exposure.coarseExpHi*256;
-       /*
-         see how far away camera exposure is from a valid
-         flicker exposure value
-       */
-       cam_exposure %= sd->params.flickerControl.coarseJump;
-       if (!sd->params.flickerControl.disabled &&
-           cam_exposure <= sd->params.flickerControl.coarseJump - 3) {
-               /* Flicker control auto-disabled */
-               sd->params.flickerControl.disabled = 1;
-       }
-
-       if (sd->params.flickerControl.disabled &&
-           old_exp > sd->params.flickerControl.coarseJump +
-                     ROUND_UP_EXP_FOR_FLICKER) {
-               /* exposure is now high enough to switch
-                  flicker control back on */
-               set_flicker(gspca_dev, 1, 1);
-       }
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-
-       sd->mainsFreq = FREQ_DEF == V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
-       reset_camera_params(gspca_dev);
-
-       PDEBUG(D_PROBE, "cpia CPiA camera detected (vid/pid 0x%04X:0x%04X)",
-              id->idVendor, id->idProduct);
-
-       cam = &gspca_dev->cam;
-       cam->cam_mode = mode;
-       cam->nmodes = ARRAY_SIZE(mode);
-
-       goto_low_power(gspca_dev);
-       /* Check the firmware version. */
-       sd->params.version.firmwareVersion = 0;
-       get_version_information(gspca_dev);
-       if (sd->params.version.firmwareVersion != 1) {
-               PDEBUG(D_ERR, "only firmware version 1 is supported (got: %d)",
-                      sd->params.version.firmwareVersion);
-               return -ENODEV;
-       }
-
-       /* A bug in firmware 1-02 limits gainMode to 2 */
-       if (sd->params.version.firmwareRevision <= 2 &&
-           sd->params.exposure.gainMode > 2) {
-               sd->params.exposure.gainMode = 2;
-       }
-
-       /* set QX3 detected flag */
-       sd->params.qx3.qx3_detected = (sd->params.pnpID.vendor == 0x0813 &&
-                                      sd->params.pnpID.product == 0x0001);
-       return 0;
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int priv, ret;
-
-       /* Start the camera in low power mode */
-       if (goto_low_power(gspca_dev)) {
-               if (sd->params.status.systemState != WARM_BOOT_STATE) {
-                       PDEBUG(D_ERR, "unexpected systemstate: %02x",
-                              sd->params.status.systemState);
-                       printstatus(&sd->params);
-                       return -ENODEV;
-               }
-
-               /* FIXME: this is just dirty trial and error */
-               ret = goto_high_power(gspca_dev);
-               if (ret)
-                       return ret;
-
-               ret = do_command(gspca_dev, CPIA_COMMAND_DiscardFrame,
-                                0, 0, 0, 0);
-               if (ret)
-                       return ret;
-
-               ret = goto_low_power(gspca_dev);
-               if (ret)
-                       return ret;
-       }
-
-       /* procedure described in developer's guide p3-28 */
-
-       /* Check the firmware version. */
-       sd->params.version.firmwareVersion = 0;
-       get_version_information(gspca_dev);
-
-       /* The fatal error checking should be done after
-        * the camera powers up (developer's guide p 3-38) */
-
-       /* Set streamState before transition to high power to avoid bug
-        * in firmware 1-02 */
-       ret = do_command(gspca_dev, CPIA_COMMAND_ModifyCameraStatus,
-                        STREAMSTATE, 0, STREAM_NOT_READY, 0);
-       if (ret)
-               return ret;
-
-       /* GotoHiPower */
-       ret = goto_high_power(gspca_dev);
-       if (ret)
-               return ret;
-
-       /* Check the camera status */
-       ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
-       if (ret)
-               return ret;
-
-       if (sd->params.status.fatalError) {
-               PDEBUG(D_ERR, "fatal_error: %04x, vp_status: %04x",
-                      sd->params.status.fatalError,
-                      sd->params.status.vpStatus);
-               return -EIO;
-       }
-
-       /* VPVersion can't be retrieved before the camera is in HiPower,
-        * so get it here instead of in get_version_information. */
-       ret = do_command(gspca_dev, CPIA_COMMAND_GetVPVersion, 0, 0, 0, 0);
-       if (ret)
-               return ret;
-
-       /* Determine video mode settings */
-       sd->params.streamStartLine = 120;
-
-       priv = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-       if (priv & 0x01) { /* crop */
-               sd->params.roi.colStart = 2;
-               sd->params.roi.rowStart = 6;
-       } else {
-               sd->params.roi.colStart = 0;
-               sd->params.roi.rowStart = 0;
-       }
-
-       if (priv & 0x02) { /* quarter */
-               sd->params.format.videoSize = VIDEOSIZE_QCIF;
-               sd->params.roi.colStart /= 2;
-               sd->params.roi.rowStart /= 2;
-               sd->params.streamStartLine /= 2;
-       } else
-               sd->params.format.videoSize = VIDEOSIZE_CIF;
-
-       sd->params.roi.colEnd = sd->params.roi.colStart +
-                               (gspca_dev->width >> 3);
-       sd->params.roi.rowEnd = sd->params.roi.rowStart +
-                               (gspca_dev->height >> 2);
-
-       /* And now set the camera to a known state */
-       ret = do_command(gspca_dev, CPIA_COMMAND_SetGrabMode,
-                        CPIA_GRAB_CONTINEOUS, 0, 0, 0);
-       if (ret)
-               return ret;
-       /* We start with compression disabled, as we need one uncompressed
-          frame to handle later compressed frames */
-       ret = do_command(gspca_dev, CPIA_COMMAND_SetCompression,
-                        CPIA_COMPRESSION_NONE,
-                        NO_DECIMATION, 0, 0);
-       if (ret)
-               return ret;
-       ret = command_setcompressiontarget(gspca_dev);
-       if (ret)
-               return ret;
-       ret = command_setcolourparams(gspca_dev);
-       if (ret)
-               return ret;
-       ret = command_setformat(gspca_dev);
-       if (ret)
-               return ret;
-       ret = command_setyuvtresh(gspca_dev);
-       if (ret)
-               return ret;
-       ret = command_setecptiming(gspca_dev);
-       if (ret)
-               return ret;
-       ret = command_setcompressionparams(gspca_dev);
-       if (ret)
-               return ret;
-       ret = command_setexposure(gspca_dev);
-       if (ret)
-               return ret;
-       ret = command_setcolourbalance(gspca_dev);
-       if (ret)
-               return ret;
-       ret = command_setsensorfps(gspca_dev);
-       if (ret)
-               return ret;
-       ret = command_setapcor(gspca_dev);
-       if (ret)
-               return ret;
-       ret = command_setflickerctrl(gspca_dev);
-       if (ret)
-               return ret;
-       ret = command_setvloffset(gspca_dev);
-       if (ret)
-               return ret;
-
-       /* Start stream */
-       ret = command_resume(gspca_dev);
-       if (ret)
-               return ret;
-
-       /* Wait 6 frames before turning compression on for the sensor to get
-          all settings and AEC/ACB to settle */
-       sd->first_frame = 6;
-       sd->exposure_status = EXPOSURE_NORMAL;
-       sd->exposure_count = 0;
-       atomic_set(&sd->cam_exposure, 0);
-       atomic_set(&sd->fps, 0);
-
-       return 0;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       command_pause(gspca_dev);
-
-       /* save camera state for later open (developers guide ch 3.5.3) */
-       save_camera_state(gspca_dev);
-
-       /* GotoLoPower */
-       goto_low_power(gspca_dev);
-
-       /* Update the camera status */
-       do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       /* If the last button state is pressed, release it now! */
-       if (sd->params.qx3.button) {
-               /* The camera latch will hold the pressed state until we reset
-                  the latch, so we do not reset sd->params.qx3.button now, to
-                  avoid a false keypress being reported the next sd_start */
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
-               input_sync(gspca_dev->input_dev);
-       }
-#endif
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int ret;
-
-       /* Start / Stop the camera to make sure we are talking to
-          a supported camera, and to get some information from it
-          to print. */
-       ret = sd_start(gspca_dev);
-       if (ret)
-               return ret;
-
-       /* Ensure the QX3 illuminators' states are restored upon resume,
-          or disable the illuminator controls, if this isn't a QX3 */
-       if (sd->params.qx3.qx3_detected)
-               command_setlights(gspca_dev);
-
-       sd_stopN(gspca_dev);
-
-       PDEBUG(D_PROBE, "CPIA Version:             %d.%02d (%d.%d)",
-                       sd->params.version.firmwareVersion,
-                       sd->params.version.firmwareRevision,
-                       sd->params.version.vcVersion,
-                       sd->params.version.vcRevision);
-       PDEBUG(D_PROBE, "CPIA PnP-ID:              %04x:%04x:%04x",
-                       sd->params.pnpID.vendor, sd->params.pnpID.product,
-                       sd->params.pnpID.deviceRevision);
-       PDEBUG(D_PROBE, "VP-Version:               %d.%d %04x",
-                       sd->params.vpVersion.vpVersion,
-                       sd->params.vpVersion.vpRevision,
-                       sd->params.vpVersion.cameraHeadID);
-
-       return 0;
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,
-                       int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* Check for SOF */
-       if (len >= 64 &&
-           data[0] == MAGIC_0 && data[1] == MAGIC_1 &&
-           data[16] == sd->params.format.videoSize &&
-           data[17] == sd->params.format.subSample &&
-           data[18] == sd->params.format.yuvOrder &&
-           data[24] == sd->params.roi.colStart &&
-           data[25] == sd->params.roi.colEnd &&
-           data[26] == sd->params.roi.rowStart &&
-           data[27] == sd->params.roi.rowEnd) {
-               u8 *image;
-
-               atomic_set(&sd->cam_exposure, data[39] * 2);
-               atomic_set(&sd->fps, data[41]);
-
-               /* Check for proper EOF for last frame */
-               image = gspca_dev->image;
-               if (image != NULL &&
-                   gspca_dev->image_len > 4 &&
-                   image[gspca_dev->image_len - 4] == 0xff &&
-                   image[gspca_dev->image_len - 3] == 0xff &&
-                   image[gspca_dev->image_len - 2] == 0xff &&
-                   image[gspca_dev->image_len - 1] == 0xff)
-                       gspca_frame_add(gspca_dev, LAST_PACKET,
-                                               NULL, 0);
-
-               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
-               return;
-       }
-
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-static void sd_dq_callback(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* Set the normal compression settings once we have captured a
-          few uncompressed frames (and AEC has hopefully settled) */
-       if (sd->first_frame) {
-               sd->first_frame--;
-               if (sd->first_frame == 0)
-                       command_setcompression(gspca_dev);
-       }
-
-       /* Switch flicker control back on if it got turned off */
-       restart_flicker(gspca_dev);
-
-       /* If AEC is enabled, monitor the exposure and
-          adjust the sensor frame rate if needed */
-       if (sd->params.exposure.expMode == 2)
-               monitor_exposure(gspca_dev);
-
-       /* Update our knowledge of the camera state */
-       do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
-       do_command(gspca_dev, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 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 && ctrl->id != V4L2_CID_POWER_LINE_FREQUENCY)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               sd->params.colourParams.brightness = ctrl->val;
-               sd->params.flickerControl.allowableOverExposure =
-                       find_over_exposure(sd->params.colourParams.brightness);
-               gspca_dev->usb_err = command_setcolourparams(gspca_dev);
-               if (!gspca_dev->usb_err)
-                       gspca_dev->usb_err = command_setflickerctrl(gspca_dev);
-               break;
-       case V4L2_CID_CONTRAST:
-               sd->params.colourParams.contrast = ctrl->val;
-               gspca_dev->usb_err = command_setcolourparams(gspca_dev);
-               break;
-       case V4L2_CID_SATURATION:
-               sd->params.colourParams.saturation = ctrl->val;
-               gspca_dev->usb_err = command_setcolourparams(gspca_dev);
-               break;
-       case V4L2_CID_POWER_LINE_FREQUENCY:
-               sd->mainsFreq = ctrl->val == V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
-               sd->params.flickerControl.coarseJump =
-                       flicker_jumps[sd->mainsFreq]
-                       [sd->params.sensorFps.baserate]
-                       [sd->params.sensorFps.divisor];
-
-               gspca_dev->usb_err = set_flicker(gspca_dev,
-                       ctrl->val != V4L2_CID_POWER_LINE_FREQUENCY_DISABLED,
-                       gspca_dev->streaming);
-               break;
-       case V4L2_CID_ILLUMINATORS_1:
-               sd->params.qx3.bottomlight = ctrl->val;
-               gspca_dev->usb_err = command_setlights(gspca_dev);
-               break;
-       case V4L2_CID_ILLUMINATORS_2:
-               sd->params.qx3.toplight = ctrl->val;
-               gspca_dev->usb_err = command_setlights(gspca_dev);
-               break;
-       case CPIA1_CID_COMP_TARGET:
-               sd->params.compressionTarget.frTargeting = ctrl->val;
-               gspca_dev->usb_err = command_setcompressiontarget(gspca_dev);
-               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;
-       static const char * const comp_target_menu[] = {
-               "Quality",
-               "Framerate",
-               NULL
-       };
-       static const struct v4l2_ctrl_config comp_target = {
-               .ops = &sd_ctrl_ops,
-               .id = CPIA1_CID_COMP_TARGET,
-               .type = V4L2_CTRL_TYPE_MENU,
-               .name = "Compression Target",
-               .qmenu = comp_target_menu,
-               .max = 1,
-               .def = COMP_TARGET_DEF,
-       };
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 7);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 100, 1, BRIGHTNESS_DEF);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 96, 8, CONTRAST_DEF);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 100, 1, SATURATION_DEF);
-       sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
-                       V4L2_CID_POWER_LINE_FREQUENCY,
-                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
-                       FREQ_DEF);
-       if (sd->params.qx3.qx3_detected) {
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                               V4L2_CID_ILLUMINATORS_1, 0, 1, 1,
-                               ILLUMINATORS_1_DEF);
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                               V4L2_CID_ILLUMINATORS_2, 0, 1, 1,
-                               ILLUMINATORS_2_DEF);
-       }
-       v4l2_ctrl_new_custom(hdl, &comp_target, NULL);
-
-       if (hdl->error) {
-               pr_err("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,
-       .stopN = sd_stopN,
-       .dq_callback = sd_dq_callback,
-       .pkt_scan = sd_pkt_scan,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .other_input = 1,
-#endif
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x0553, 0x0002)},
-       {USB_DEVICE(0x0813, 0x0001)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/etoms.c b/drivers/media/video/gspca/etoms.c
deleted file mode 100644 (file)
index 38f68e1..0000000
+++ /dev/null
@@ -1,799 +0,0 @@
-/*
- * Etoms Et61x151 GPL Linux driver by Michel Xhaard (09/09/2004)
- *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "etoms"
-
-#include "gspca.h"
-
-MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
-MODULE_DESCRIPTION("Etoms USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       unsigned char autogain;
-
-       char sensor;
-#define SENSOR_PAS106 0
-#define SENSOR_TAS5130CXX 1
-       signed char ag_cnt;
-#define AG_CNT_START 13
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-/*     {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0}, */
-};
-
-static const struct v4l2_pix_format sif_mode[] = {
-       {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-#define ETOMS_ALT_SIZE_1000   12
-
-#define ET_GPIO_DIR_CTRL 0x04  /* Control IO bit[0..5] (0 in  1 out) */
-#define ET_GPIO_OUT 0x05       /* Only IO data */
-#define ET_GPIO_IN 0x06                /* Read Only IO data */
-#define ET_RESET_ALL 0x03
-#define ET_ClCK 0x01
-#define ET_CTRL 0x02           /* enable i2c OutClck Powerdown mode */
-
-#define ET_COMP 0x12           /* Compression register */
-#define ET_MAXQt 0x13
-#define ET_MINQt 0x14
-#define ET_COMP_VAL0 0x02
-#define ET_COMP_VAL1 0x03
-
-#define ET_REG1d 0x1d
-#define ET_REG1e 0x1e
-#define ET_REG1f 0x1f
-#define ET_REG20 0x20
-#define ET_REG21 0x21
-#define ET_REG22 0x22
-#define ET_REG23 0x23
-#define ET_REG24 0x24
-#define ET_REG25 0x25
-/* base registers for luma calculation */
-#define ET_LUMA_CENTER 0x39
-
-#define ET_G_RED 0x4d
-#define ET_G_GREEN1 0x4e
-#define ET_G_BLUE 0x4f
-#define ET_G_GREEN2 0x50
-#define ET_G_GR_H 0x51
-#define ET_G_GB_H 0x52
-
-#define ET_O_RED 0x34
-#define ET_O_GREEN1 0x35
-#define ET_O_BLUE 0x36
-#define ET_O_GREEN2 0x37
-
-#define ET_SYNCHRO 0x68
-#define ET_STARTX 0x69
-#define ET_STARTY 0x6a
-#define ET_WIDTH_LOW 0x6b
-#define ET_HEIGTH_LOW 0x6c
-#define ET_W_H_HEIGTH 0x6d
-
-#define ET_REG6e 0x6e          /* OBW */
-#define ET_REG6f 0x6f          /* OBW */
-#define ET_REG70 0x70          /* OBW_AWB */
-#define ET_REG71 0x71          /* OBW_AWB */
-#define ET_REG72 0x72          /* OBW_AWB */
-#define ET_REG73 0x73          /* Clkdelay ns */
-#define ET_REG74 0x74          /* test pattern */
-#define ET_REG75 0x75          /* test pattern */
-
-#define ET_I2C_CLK 0x8c
-#define ET_PXL_CLK 0x60
-
-#define ET_I2C_BASE 0x89
-#define ET_I2C_COUNT 0x8a
-#define ET_I2C_PREFETCH 0x8b
-#define ET_I2C_REG 0x88
-#define ET_I2C_DATA7 0x87
-#define ET_I2C_DATA6 0x86
-#define ET_I2C_DATA5 0x85
-#define ET_I2C_DATA4 0x84
-#define ET_I2C_DATA3 0x83
-#define ET_I2C_DATA2 0x82
-#define ET_I2C_DATA1 0x81
-#define ET_I2C_DATA0 0x80
-
-#define PAS106_REG2 0x02       /* pxlClk = systemClk/(reg2) */
-#define PAS106_REG3 0x03       /* line/frame H [11..4] */
-#define PAS106_REG4 0x04       /* line/frame L [3..0] */
-#define PAS106_REG5 0x05       /* exposure time line offset(default 5) */
-#define PAS106_REG6 0x06       /* exposure time pixel offset(default 6) */
-#define PAS106_REG7 0x07       /* signbit Dac (default 0) */
-#define PAS106_REG9 0x09
-#define PAS106_REG0e 0x0e      /* global gain [4..0](default 0x0e) */
-#define PAS106_REG13 0x13      /* end i2c write */
-
-static const __u8 GainRGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
-
-static const __u8 I2c2[] = { 0x08, 0x08, 0x08, 0x08, 0x0d };
-
-static const __u8 I2c3[] = { 0x12, 0x05 };
-
-static const __u8 I2c4[] = { 0x41, 0x08 };
-
-/* read 'len' bytes to gspca_dev->usb_buf */
-static void reg_r(struct gspca_dev *gspca_dev,
-                 __u16 index,
-                 __u16 len)
-{
-       struct usb_device *dev = gspca_dev->dev;
-
-#ifdef GSPCA_DEBUG
-       if (len > USB_BUF_SZ) {
-               pr_err("reg_r: buffer overflow\n");
-               return;
-       }
-#endif
-       usb_control_msg(dev,
-                       usb_rcvctrlpipe(dev, 0),
-                       0,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       0,
-                       index, gspca_dev->usb_buf, len, 500);
-       PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
-                       index, gspca_dev->usb_buf[0]);
-}
-
-static void reg_w_val(struct gspca_dev *gspca_dev,
-                       __u16 index,
-                       __u8 val)
-{
-       struct usb_device *dev = gspca_dev->dev;
-
-       gspca_dev->usb_buf[0] = val;
-       usb_control_msg(dev,
-                       usb_sndctrlpipe(dev, 0),
-                       0,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       0,
-                       index, gspca_dev->usb_buf, 1, 500);
-}
-
-static void reg_w(struct gspca_dev *gspca_dev,
-                 __u16 index,
-                 const __u8 *buffer,
-                 __u16 len)
-{
-       struct usb_device *dev = gspca_dev->dev;
-
-#ifdef GSPCA_DEBUG
-       if (len > USB_BUF_SZ) {
-               pr_err("reg_w: buffer overflow\n");
-               return;
-       }
-       PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
-#endif
-       memcpy(gspca_dev->usb_buf, buffer, len);
-       usb_control_msg(dev,
-                       usb_sndctrlpipe(dev, 0),
-                       0,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       0, index, gspca_dev->usb_buf, len, 500);
-}
-
-static int i2c_w(struct gspca_dev *gspca_dev,
-                __u8 reg,
-                const __u8 *buffer,
-                int len, __u8 mode)
-{
-       /* buffer should be [D0..D7] */
-       __u8 ptchcount;
-
-       /* set the base address */
-       reg_w_val(gspca_dev, ET_I2C_BASE, 0x40);
-                                        /* sensor base for the pas106 */
-       /* set count and prefetch */
-       ptchcount = ((len & 0x07) << 4) | (mode & 0x03);
-       reg_w_val(gspca_dev, ET_I2C_COUNT, ptchcount);
-       /* set the register base */
-       reg_w_val(gspca_dev, ET_I2C_REG, reg);
-       while (--len >= 0)
-               reg_w_val(gspca_dev, ET_I2C_DATA0 + len, buffer[len]);
-       return 0;
-}
-
-static int i2c_r(struct gspca_dev *gspca_dev,
-                       __u8 reg)
-{
-       /* set the base address */
-       reg_w_val(gspca_dev, ET_I2C_BASE, 0x40);
-                                       /* sensor base for the pas106 */
-       /* set count and prefetch (cnd: 4 bits - mode: 4 bits) */
-       reg_w_val(gspca_dev, ET_I2C_COUNT, 0x11);
-       reg_w_val(gspca_dev, ET_I2C_REG, reg);  /* set the register base */
-       reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x02);    /* prefetch */
-       reg_w_val(gspca_dev, ET_I2C_PREFETCH, 0x00);
-       reg_r(gspca_dev, ET_I2C_DATA0, 1);      /* read one byte */
-       return 0;
-}
-
-static int Et_WaitStatus(struct gspca_dev *gspca_dev)
-{
-       int retry = 10;
-
-       while (retry--) {
-               reg_r(gspca_dev, ET_ClCK, 1);
-               if (gspca_dev->usb_buf[0] != 0)
-                       return 1;
-       }
-       return 0;
-}
-
-static int et_video(struct gspca_dev *gspca_dev,
-                   int on)
-{
-       int ret;
-
-       reg_w_val(gspca_dev, ET_GPIO_OUT,
-                 on ? 0x10             /* startvideo - set Bit5 */
-                    : 0);              /* stopvideo */
-       ret = Et_WaitStatus(gspca_dev);
-       if (ret != 0)
-               PDEBUG(D_ERR, "timeout video on/off");
-       return ret;
-}
-
-static void Et_init2(struct gspca_dev *gspca_dev)
-{
-       __u8 value;
-       static const __u8 FormLine[] = { 0x84, 0x03, 0x14, 0xf4, 0x01, 0x05 };
-
-       PDEBUG(D_STREAM, "Open Init2 ET");
-       reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 0x2f);
-       reg_w_val(gspca_dev, ET_GPIO_OUT, 0x10);
-       reg_r(gspca_dev, ET_GPIO_IN, 1);
-       reg_w_val(gspca_dev, ET_ClCK, 0x14); /* 0x14 // 0x16 enabled pattern */
-       reg_w_val(gspca_dev, ET_CTRL, 0x1b);
-
-       /*  compression et subsampling */
-       if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
-               value = ET_COMP_VAL1;   /* 320 */
-       else
-               value = ET_COMP_VAL0;   /* 640 */
-       reg_w_val(gspca_dev, ET_COMP, value);
-       reg_w_val(gspca_dev, ET_MAXQt, 0x1f);
-       reg_w_val(gspca_dev, ET_MINQt, 0x04);
-       /* undocumented registers */
-       reg_w_val(gspca_dev, ET_REG1d, 0xff);
-       reg_w_val(gspca_dev, ET_REG1e, 0xff);
-       reg_w_val(gspca_dev, ET_REG1f, 0xff);
-       reg_w_val(gspca_dev, ET_REG20, 0x35);
-       reg_w_val(gspca_dev, ET_REG21, 0x01);
-       reg_w_val(gspca_dev, ET_REG22, 0x00);
-       reg_w_val(gspca_dev, ET_REG23, 0xff);
-       reg_w_val(gspca_dev, ET_REG24, 0xff);
-       reg_w_val(gspca_dev, ET_REG25, 0x0f);
-       /* colors setting */
-       reg_w_val(gspca_dev, 0x30, 0x11);               /* 0x30 */
-       reg_w_val(gspca_dev, 0x31, 0x40);
-       reg_w_val(gspca_dev, 0x32, 0x00);
-       reg_w_val(gspca_dev, ET_O_RED, 0x00);           /* 0x34 */
-       reg_w_val(gspca_dev, ET_O_GREEN1, 0x00);
-       reg_w_val(gspca_dev, ET_O_BLUE, 0x00);
-       reg_w_val(gspca_dev, ET_O_GREEN2, 0x00);
-       /*************/
-       reg_w_val(gspca_dev, ET_G_RED, 0x80);           /* 0x4d */
-       reg_w_val(gspca_dev, ET_G_GREEN1, 0x80);
-       reg_w_val(gspca_dev, ET_G_BLUE, 0x80);
-       reg_w_val(gspca_dev, ET_G_GREEN2, 0x80);
-       reg_w_val(gspca_dev, ET_G_GR_H, 0x00);
-       reg_w_val(gspca_dev, ET_G_GB_H, 0x00);          /* 0x52 */
-       /* Window control registers */
-       reg_w_val(gspca_dev, 0x61, 0x80);               /* use cmc_out */
-       reg_w_val(gspca_dev, 0x62, 0x02);
-       reg_w_val(gspca_dev, 0x63, 0x03);
-       reg_w_val(gspca_dev, 0x64, 0x14);
-       reg_w_val(gspca_dev, 0x65, 0x0e);
-       reg_w_val(gspca_dev, 0x66, 0x02);
-       reg_w_val(gspca_dev, 0x67, 0x02);
-
-       /**************************************/
-       reg_w_val(gspca_dev, ET_SYNCHRO, 0x8f);         /* 0x68 */
-       reg_w_val(gspca_dev, ET_STARTX, 0x69);          /* 0x6a //0x69 */
-       reg_w_val(gspca_dev, ET_STARTY, 0x0d);          /* 0x0d //0x0c */
-       reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x80);
-       reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0xe0);
-       reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x60);      /* 6d */
-       reg_w_val(gspca_dev, ET_REG6e, 0x86);
-       reg_w_val(gspca_dev, ET_REG6f, 0x01);
-       reg_w_val(gspca_dev, ET_REG70, 0x26);
-       reg_w_val(gspca_dev, ET_REG71, 0x7a);
-       reg_w_val(gspca_dev, ET_REG72, 0x01);
-       /* Clock Pattern registers ***************** */
-       reg_w_val(gspca_dev, ET_REG73, 0x00);
-       reg_w_val(gspca_dev, ET_REG74, 0x18);           /* 0x28 */
-       reg_w_val(gspca_dev, ET_REG75, 0x0f);           /* 0x01 */
-       /**********************************************/
-       reg_w_val(gspca_dev, 0x8a, 0x20);
-       reg_w_val(gspca_dev, 0x8d, 0x0f);
-       reg_w_val(gspca_dev, 0x8e, 0x08);
-       /**************************************/
-       reg_w_val(gspca_dev, 0x03, 0x08);
-       reg_w_val(gspca_dev, ET_PXL_CLK, 0x03);
-       reg_w_val(gspca_dev, 0x81, 0xff);
-       reg_w_val(gspca_dev, 0x80, 0x00);
-       reg_w_val(gspca_dev, 0x81, 0xff);
-       reg_w_val(gspca_dev, 0x80, 0x20);
-       reg_w_val(gspca_dev, 0x03, 0x01);
-       reg_w_val(gspca_dev, 0x03, 0x00);
-       reg_w_val(gspca_dev, 0x03, 0x08);
-       /********************************************/
-
-/*     reg_r(gspca_dev, ET_I2C_BASE, 1);
-                                        always 0x40 as the pas106 ??? */
-       /* set the sensor */
-       if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
-               value = 0x04;           /* 320 */
-       else                            /* 640 */
-               value = 0x1e;   /* 0x17  * setting PixelClock
-                                        * 0x03 mean 24/(3+1) = 6 Mhz
-                                        * 0x05 -> 24/(5+1) = 4 Mhz
-                                        * 0x0b -> 24/(11+1) = 2 Mhz
-                                        * 0x17 -> 24/(23+1) = 1 Mhz
-                                        */
-       reg_w_val(gspca_dev, ET_PXL_CLK, value);
-       /* now set by fifo the FormatLine setting */
-       reg_w(gspca_dev, 0x62, FormLine, 6);
-
-       /* set exposure times [ 0..0x78] 0->longvalue 0x78->shortvalue */
-       reg_w_val(gspca_dev, 0x81, 0x47);       /* 0x47; */
-       reg_w_val(gspca_dev, 0x80, 0x40);       /* 0x40; */
-       /* Pedro change */
-       /* Brightness change Brith+ decrease value */
-       /* Brigth- increase value */
-       /* original value = 0x70; */
-       reg_w_val(gspca_dev, 0x81, 0x30);       /* 0x20; - set brightness */
-       reg_w_val(gspca_dev, 0x80, 0x20);       /* 0x20; */
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       int i;
-
-       for (i = 0; i < 4; i++)
-               reg_w_val(gspca_dev, ET_O_RED + i, val);
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
-{
-       __u8 RGBG[] = { 0x80, 0x80, 0x80, 0x80, 0x00, 0x00 };
-
-       memset(RGBG, val, sizeof(RGBG) - 2);
-       reg_w(gspca_dev, ET_G_RED, RGBG, 6);
-}
-
-static void setcolors(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       __u8 I2cc[] = { 0x05, 0x02, 0x02, 0x05, 0x0d };
-       __u8 i2cflags = 0x01;
-       /* __u8 green = 0; */
-
-       I2cc[3] = val;  /* red */
-       I2cc[0] = 15 - val;     /* blue */
-       /* green = 15 - ((((7*I2cc[0]) >> 2 ) + I2cc[3]) >> 1); */
-       /* I2cc[1] = I2cc[2] = green; */
-       if (sd->sensor == SENSOR_PAS106) {
-               i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3);
-               i2c_w(gspca_dev, PAS106_REG9, I2cc, sizeof I2cc, 1);
-       }
-/*     PDEBUG(D_CONF , "Etoms red %d blue %d green %d",
-               I2cc[3], I2cc[0], green); */
-}
-
-static s32 getcolors(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_PAS106) {
-/*             i2c_r(gspca_dev, PAS106_REG9);           * blue */
-               i2c_r(gspca_dev, PAS106_REG9 + 3);      /* red */
-               return gspca_dev->usb_buf[0] & 0x0f;
-       }
-       return 0;
-}
-
-static void setautogain(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->autogain)
-               sd->ag_cnt = AG_CNT_START;
-       else
-               sd->ag_cnt = -1;
-}
-
-static void Et_init1(struct gspca_dev *gspca_dev)
-{
-       __u8 value;
-/*     __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0x22, 0xac, 0x00, 0x01, 0x00}; */
-       __u8 I2c0[] = { 0x0a, 0x12, 0x05, 0x6d, 0xcd, 0x00, 0x01, 0x00 };
-                                               /* try 1/120 0x6d 0xcd 0x40 */
-/*     __u8 I2c0 [] = {0x0a, 0x12, 0x05, 0xfe, 0xfe, 0xc0, 0x01, 0x00};
-                                                * 1/60000 hmm ?? */
-
-       PDEBUG(D_STREAM, "Open Init1 ET");
-       reg_w_val(gspca_dev, ET_GPIO_DIR_CTRL, 7);
-       reg_r(gspca_dev, ET_GPIO_IN, 1);
-       reg_w_val(gspca_dev, ET_RESET_ALL, 1);
-       reg_w_val(gspca_dev, ET_RESET_ALL, 0);
-       reg_w_val(gspca_dev, ET_ClCK, 0x10);
-       reg_w_val(gspca_dev, ET_CTRL, 0x19);
-       /*   compression et subsampling */
-       if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv)
-               value = ET_COMP_VAL1;
-       else
-               value = ET_COMP_VAL0;
-       PDEBUG(D_STREAM, "Open mode %d Compression %d",
-              gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv,
-              value);
-       reg_w_val(gspca_dev, ET_COMP, value);
-       reg_w_val(gspca_dev, ET_MAXQt, 0x1d);
-       reg_w_val(gspca_dev, ET_MINQt, 0x02);
-       /* undocumented registers */
-       reg_w_val(gspca_dev, ET_REG1d, 0xff);
-       reg_w_val(gspca_dev, ET_REG1e, 0xff);
-       reg_w_val(gspca_dev, ET_REG1f, 0xff);
-       reg_w_val(gspca_dev, ET_REG20, 0x35);
-       reg_w_val(gspca_dev, ET_REG21, 0x01);
-       reg_w_val(gspca_dev, ET_REG22, 0x00);
-       reg_w_val(gspca_dev, ET_REG23, 0xf7);
-       reg_w_val(gspca_dev, ET_REG24, 0xff);
-       reg_w_val(gspca_dev, ET_REG25, 0x07);
-       /* colors setting */
-       reg_w_val(gspca_dev, ET_G_RED, 0x80);
-       reg_w_val(gspca_dev, ET_G_GREEN1, 0x80);
-       reg_w_val(gspca_dev, ET_G_BLUE, 0x80);
-       reg_w_val(gspca_dev, ET_G_GREEN2, 0x80);
-       reg_w_val(gspca_dev, ET_G_GR_H, 0x00);
-       reg_w_val(gspca_dev, ET_G_GB_H, 0x00);
-       /* Window control registers */
-       reg_w_val(gspca_dev, ET_SYNCHRO, 0xf0);
-       reg_w_val(gspca_dev, ET_STARTX, 0x56);          /* 0x56 */
-       reg_w_val(gspca_dev, ET_STARTY, 0x05);          /* 0x04 */
-       reg_w_val(gspca_dev, ET_WIDTH_LOW, 0x60);
-       reg_w_val(gspca_dev, ET_HEIGTH_LOW, 0x20);
-       reg_w_val(gspca_dev, ET_W_H_HEIGTH, 0x50);
-       reg_w_val(gspca_dev, ET_REG6e, 0x86);
-       reg_w_val(gspca_dev, ET_REG6f, 0x01);
-       reg_w_val(gspca_dev, ET_REG70, 0x86);
-       reg_w_val(gspca_dev, ET_REG71, 0x14);
-       reg_w_val(gspca_dev, ET_REG72, 0x00);
-       /* Clock Pattern registers */
-       reg_w_val(gspca_dev, ET_REG73, 0x00);
-       reg_w_val(gspca_dev, ET_REG74, 0x00);
-       reg_w_val(gspca_dev, ET_REG75, 0x0a);
-       reg_w_val(gspca_dev, ET_I2C_CLK, 0x04);
-       reg_w_val(gspca_dev, ET_PXL_CLK, 0x01);
-       /* set the sensor */
-       if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
-               I2c0[0] = 0x06;
-               i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1);
-               i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1);
-               value = 0x06;
-               i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1);
-               i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1);
-               /* value = 0x1f; */
-               value = 0x04;
-               i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1);
-       } else {
-               I2c0[0] = 0x0a;
-
-               i2c_w(gspca_dev, PAS106_REG2, I2c0, sizeof I2c0, 1);
-               i2c_w(gspca_dev, PAS106_REG9, I2c2, sizeof I2c2, 1);
-               value = 0x0a;
-               i2c_w(gspca_dev, PAS106_REG2, &value, 1, 1);
-               i2c_w(gspca_dev, PAS106_REG3, I2c3, sizeof I2c3, 1);
-               value = 0x04;
-               /* value = 0x10; */
-               i2c_w(gspca_dev, PAS106_REG0e, &value, 1, 1);
-               /* bit 2 enable bit 1:2 select 0 1 2 3
-                  value = 0x07;                                * curve 0 *
-                  i2c_w(gspca_dev, PAS106_REG0f, &value, 1, 1);
-                */
-       }
-
-/*     value = 0x01; */
-/*     value = 0x22; */
-/*     i2c_w(gspca_dev, PAS106_REG5, &value, 1, 1); */
-       /* magnetude and sign bit for DAC */
-       i2c_w(gspca_dev, PAS106_REG7, I2c4, sizeof I2c4, 1);
-       /* now set by fifo the whole colors setting */
-       reg_w(gspca_dev, ET_G_RED, GainRGBG, 6);
-       setcolors(gspca_dev, getcolors(gspca_dev));
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                    const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-
-       cam = &gspca_dev->cam;
-       sd->sensor = id->driver_info;
-       if (sd->sensor == SENSOR_PAS106) {
-               cam->cam_mode = sif_mode;
-               cam->nmodes = ARRAY_SIZE(sif_mode);
-       } else {
-               cam->cam_mode = vga_mode;
-               cam->nmodes = ARRAY_SIZE(vga_mode);
-       }
-       sd->ag_cnt = -1;
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_PAS106)
-               Et_init1(gspca_dev);
-       else
-               Et_init2(gspca_dev);
-       reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
-       et_video(gspca_dev, 0);         /* video off */
-       return 0;
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_PAS106)
-               Et_init1(gspca_dev);
-       else
-               Et_init2(gspca_dev);
-
-       setautogain(gspca_dev);
-
-       reg_w_val(gspca_dev, ET_RESET_ALL, 0x08);
-       et_video(gspca_dev, 1);         /* video on */
-       return 0;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       et_video(gspca_dev, 0);         /* video off */
-}
-
-static __u8 Et_getgainG(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_PAS106) {
-               i2c_r(gspca_dev, PAS106_REG0e);
-               PDEBUG(D_CONF, "Etoms gain G %d", gspca_dev->usb_buf[0]);
-               return gspca_dev->usb_buf[0];
-       }
-       return 0x1f;
-}
-
-static void Et_setgainG(struct gspca_dev *gspca_dev, __u8 gain)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_PAS106) {
-               __u8 i2cflags = 0x01;
-
-               i2c_w(gspca_dev, PAS106_REG13, &i2cflags, 1, 3);
-               i2c_w(gspca_dev, PAS106_REG0e, &gain, 1, 1);
-       }
-}
-
-#define BLIMIT(bright) \
-       (u8)((bright > 0x1f) ? 0x1f : ((bright < 4) ? 3 : bright))
-#define LIMIT(color) \
-       (u8)((color > 0xff) ? 0xff : ((color < 0) ? 0 : color))
-
-static void do_autogain(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       __u8 luma;
-       __u8 luma_mean = 128;
-       __u8 luma_delta = 20;
-       __u8 spring = 4;
-       int Gbright;
-       __u8 r, g, b;
-
-       if (sd->ag_cnt < 0)
-               return;
-       if (--sd->ag_cnt >= 0)
-               return;
-       sd->ag_cnt = AG_CNT_START;
-
-       Gbright = Et_getgainG(gspca_dev);
-       reg_r(gspca_dev, ET_LUMA_CENTER, 4);
-       g = (gspca_dev->usb_buf[0] + gspca_dev->usb_buf[3]) >> 1;
-       r = gspca_dev->usb_buf[1];
-       b = gspca_dev->usb_buf[2];
-       r = ((r << 8) - (r << 4) - (r << 3)) >> 10;
-       b = ((b << 7) >> 10);
-       g = ((g << 9) + (g << 7) + (g << 5)) >> 10;
-       luma = LIMIT(r + g + b);
-       PDEBUG(D_FRAM, "Etoms luma G %d", luma);
-       if (luma < luma_mean - luma_delta || luma > luma_mean + luma_delta) {
-               Gbright += (luma_mean - luma) >> spring;
-               Gbright = BLIMIT(Gbright);
-               PDEBUG(D_FRAM, "Etoms Gbright %d", Gbright);
-               Et_setgainG(gspca_dev, (__u8) Gbright);
-       }
-}
-
-#undef BLIMIT
-#undef LIMIT
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,                       /* isoc packet */
-                       int len)                        /* iso packet length */
-{
-       int seqframe;
-
-       seqframe = data[0] & 0x3f;
-       len = (int) (((data[0] & 0xc0) << 2) | data[1]);
-       if (seqframe == 0x3f) {
-               PDEBUG(D_FRAM,
-                      "header packet found datalength %d !!", len);
-               PDEBUG(D_FRAM, "G %d R %d G %d B %d",
-                      data[2], data[3], data[4], data[5]);
-               data += 30;
-               /* don't change datalength as the chips provided it */
-               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
-               return;
-       }
-       if (len) {
-               data += 8;
-               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-       } else {                        /* Drop Packet */
-               gspca_dev->last_packet_type = DISCARD_PACKET;
-       }
-}
-
-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_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               setcolors(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               sd->autogain = ctrl->val;
-               setautogain(gspca_dev);
-               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);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 1, 127, 1, 63);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 255, 1, 127);
-       if (sd->sensor == SENSOR_PAS106)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 15, 1, 7);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-       if (hdl->error) {
-               pr_err("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,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-       .dq_callback = do_autogain,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x102c, 0x6151), .driver_info = SENSOR_PAS106},
-#if !defined CONFIG_USB_ET61X251 && !defined CONFIG_USB_ET61X251_MODULE
-       {USB_DEVICE(0x102c, 0x6251), .driver_info = SENSOR_TAS5130CXX},
-#endif
-       {}
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/finepix.c b/drivers/media/video/gspca/finepix.c
deleted file mode 100644 (file)
index c8f2201..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Fujifilm Finepix subdriver
- *
- * Copyright (C) 2008 Frank Zago
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "finepix"
-
-#include "gspca.h"
-
-MODULE_AUTHOR("Frank Zago <frank@zago.net>");
-MODULE_DESCRIPTION("Fujifilm FinePix USB V4L2 driver");
-MODULE_LICENSE("GPL");
-
-/* Default timeout, in ms */
-#define FPIX_TIMEOUT 250
-
-/* Maximum transfer size to use. The windows driver reads by chunks of
- * 0x2000 bytes, so do the same. Note: reading more seems to work
- * too. */
-#define FPIX_MAX_TRANSFER 0x2000
-
-/* Structure to hold all of our device specific stuff */
-struct usb_fpix {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       struct work_struct work_struct;
-       struct workqueue_struct *work_thread;
-};
-
-/* Delay after which claim the next frame. If the delay is too small,
- * the camera will return old frames. On the 4800Z, 20ms is bad, 25ms
- * will fail every 4 or 5 frames, but 30ms is perfect. On the A210,
- * 30ms is bad while 35ms is perfect. */
-#define NEXT_FRAME_DELAY 35
-
-/* These cameras only support 320x200. */
-static const struct v4l2_pix_format fpix_mode[1] = {
-       { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0}
-};
-
-/* send a command to the webcam */
-static int command(struct gspca_dev *gspca_dev,
-               int order)      /* 0: reset, 1: frame request */
-{
-       static u8 order_values[2][12] = {
-               {0xc6, 0, 0, 0, 0, 0, 0,    0, 0x20, 0, 0, 0},  /* reset */
-               {0xd3, 0, 0, 0, 0, 0, 0, 0x01,    0, 0, 0, 0},  /* fr req */
-       };
-
-       memcpy(gspca_dev->usb_buf, order_values[order], 12);
-       return usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       USB_REQ_GET_STATUS,
-                       USB_DIR_OUT | USB_TYPE_CLASS |
-                       USB_RECIP_INTERFACE, 0, 0, gspca_dev->usb_buf,
-                       12, FPIX_TIMEOUT);
-}
-
-/* workqueue */
-static void dostream(struct work_struct *work)
-{
-       struct usb_fpix *dev = container_of(work, struct usb_fpix, work_struct);
-       struct gspca_dev *gspca_dev = &dev->gspca_dev;
-       struct urb *urb = gspca_dev->urb[0];
-       u8 *data = urb->transfer_buffer;
-       int ret = 0;
-       int len;
-
-       /* synchronize with the main driver */
-       mutex_lock(&gspca_dev->usb_lock);
-       mutex_unlock(&gspca_dev->usb_lock);
-       PDEBUG(D_STREAM, "dostream started");
-
-       /* loop reading a frame */
-again:
-       while (gspca_dev->dev && gspca_dev->streaming) {
-#ifdef CONFIG_PM
-               if (gspca_dev->frozen)
-                       break;
-#endif
-
-               /* request a frame */
-               mutex_lock(&gspca_dev->usb_lock);
-               ret = command(gspca_dev, 1);
-               mutex_unlock(&gspca_dev->usb_lock);
-               if (ret < 0)
-                       break;
-#ifdef CONFIG_PM
-               if (gspca_dev->frozen)
-                       break;
-#endif
-               if (!gspca_dev->dev || !gspca_dev->streaming)
-                       break;
-
-               /* the frame comes in parts */
-               for (;;) {
-                       ret = usb_bulk_msg(gspca_dev->dev,
-                                       urb->pipe,
-                                       data,
-                                       FPIX_MAX_TRANSFER,
-                                       &len, FPIX_TIMEOUT);
-                       if (ret < 0) {
-                               /* Most of the time we get a timeout
-                                * error. Just restart. */
-                               goto again;
-                       }
-#ifdef CONFIG_PM
-                       if (gspca_dev->frozen)
-                               goto out;
-#endif
-                       if (!gspca_dev->dev || !gspca_dev->streaming)
-                               goto out;
-                       if (len < FPIX_MAX_TRANSFER ||
-                               (data[len - 2] == 0xff &&
-                                       data[len - 1] == 0xd9)) {
-
-                               /* If the result is less than what was asked
-                                * for, then it's the end of the
-                                * frame. Sometimes the jpeg is not complete,
-                                * but there's nothing we can do. We also end
-                                * here if the the jpeg ends right at the end
-                                * of the frame. */
-                               gspca_frame_add(gspca_dev, LAST_PACKET,
-                                               data, len);
-                               break;
-                       }
-
-                       /* got a partial image */
-                       gspca_frame_add(gspca_dev,
-                                       gspca_dev->last_packet_type
-                                               == LAST_PACKET
-                                       ? FIRST_PACKET : INTER_PACKET,
-                                       data, len);
-               }
-
-               /* We must wait before trying reading the next
-                * frame. If we don't, or if the delay is too short,
-                * the camera will disconnect. */
-               msleep(NEXT_FRAME_DELAY);
-       }
-
-out:
-       PDEBUG(D_STREAM, "dostream stopped");
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-               const struct usb_device_id *id)
-{
-       struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
-       struct cam *cam = &gspca_dev->cam;
-
-       cam->cam_mode = fpix_mode;
-       cam->nmodes = 1;
-       cam->bulk = 1;
-       cam->bulk_size = FPIX_MAX_TRANSFER;
-
-       INIT_WORK(&dev->work_struct, dostream);
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       return 0;
-}
-
-/* start the camera */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
-       int ret, len;
-
-       /* Init the device */
-       ret = command(gspca_dev, 0);
-       if (ret < 0) {
-               pr_err("init failed %d\n", ret);
-               return ret;
-       }
-
-       /* Read the result of the command. Ignore the result, for it
-        * varies with the device. */
-       ret = usb_bulk_msg(gspca_dev->dev,
-                       gspca_dev->urb[0]->pipe,
-                       gspca_dev->urb[0]->transfer_buffer,
-                       FPIX_MAX_TRANSFER, &len,
-                       FPIX_TIMEOUT);
-       if (ret < 0) {
-               pr_err("usb_bulk_msg failed %d\n", ret);
-               return ret;
-       }
-
-       /* Request a frame, but don't read it */
-       ret = command(gspca_dev, 1);
-       if (ret < 0) {
-               pr_err("frame request failed %d\n", ret);
-               return ret;
-       }
-
-       /* Again, reset bulk in endpoint */
-       usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
-
-       /* Start the workqueue function to do the streaming */
-       dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
-       queue_work(dev->work_thread, &dev->work_struct);
-
-       return 0;
-}
-
-/* called on streamoff with alt==0 and on disconnect */
-/* the usb_lock is held at entry - restore on exit */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       struct usb_fpix *dev = (struct usb_fpix *) gspca_dev;
-
-       /* wait for the work queue to terminate */
-       mutex_unlock(&gspca_dev->usb_lock);
-       destroy_workqueue(dev->work_thread);
-       mutex_lock(&gspca_dev->usb_lock);
-       dev->work_thread = NULL;
-}
-
-/* Table of supported USB devices */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x04cb, 0x0104)},
-       {USB_DEVICE(0x04cb, 0x0109)},
-       {USB_DEVICE(0x04cb, 0x010b)},
-       {USB_DEVICE(0x04cb, 0x010f)},
-       {USB_DEVICE(0x04cb, 0x0111)},
-       {USB_DEVICE(0x04cb, 0x0113)},
-       {USB_DEVICE(0x04cb, 0x0115)},
-       {USB_DEVICE(0x04cb, 0x0117)},
-       {USB_DEVICE(0x04cb, 0x0119)},
-       {USB_DEVICE(0x04cb, 0x011b)},
-       {USB_DEVICE(0x04cb, 0x011d)},
-       {USB_DEVICE(0x04cb, 0x0121)},
-       {USB_DEVICE(0x04cb, 0x0123)},
-       {USB_DEVICE(0x04cb, 0x0125)},
-       {USB_DEVICE(0x04cb, 0x0127)},
-       {USB_DEVICE(0x04cb, 0x0129)},
-       {USB_DEVICE(0x04cb, 0x012b)},
-       {USB_DEVICE(0x04cb, 0x012d)},
-       {USB_DEVICE(0x04cb, 0x012f)},
-       {USB_DEVICE(0x04cb, 0x0131)},
-       {USB_DEVICE(0x04cb, 0x013b)},
-       {USB_DEVICE(0x04cb, 0x013d)},
-       {USB_DEVICE(0x04cb, 0x013f)},
-       {}
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* sub-driver description */
-static const struct sd_desc sd_desc = {
-       .name   = MODULE_NAME,
-       .config = sd_config,
-       .init   = sd_init,
-       .start  = sd_start,
-       .stop0  = sd_stop0,
-};
-
-/* -- device connect -- */
-static int sd_probe(struct usb_interface *intf,
-               const struct usb_device_id *id)
-{
-       return gspca_dev_probe(intf, id,
-                       &sd_desc,
-                       sizeof(struct usb_fpix),
-                       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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/gl860/Kconfig b/drivers/media/video/gspca/gl860/Kconfig
deleted file mode 100644 (file)
index 22772f5..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-config USB_GL860
-       tristate "GL860 USB Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the GL860 chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_gl860.
diff --git a/drivers/media/video/gspca/gl860/Makefile b/drivers/media/video/gspca/gl860/Makefile
deleted file mode 100644 (file)
index 773ea34..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-obj-$(CONFIG_USB_GL860) += gspca_gl860.o
-
-gspca_gl860-objs := gl860.o \
-                   gl860-mi1320.o \
-                   gl860-ov2640.o \
-                   gl860-ov9655.o \
-                   gl860-mi2020.o
-
-ccflags-y += -I$(srctree)/drivers/media/video/gspca
-
diff --git a/drivers/media/video/gspca/gl860/gl860-mi1320.c b/drivers/media/video/gspca/gl860/gl860-mi1320.c
deleted file mode 100644 (file)
index b57160e..0000000
+++ /dev/null
@@ -1,536 +0,0 @@
-/* Subdriver for the GL860 chip with the MI1320 sensor
- * Author Olivier LORIN from own logs
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Sensor : MI1320 */
-
-#include "gl860.h"
-
-static struct validx tbl_common[] = {
-       {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba51, 0x0066}, {0xba02, 0x00f1},
-       {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
-       {0xffff, 0xffff},
-       {0xba00, 0x00f0}, {0xba02, 0x00f1}, {0xbafa, 0x0028}, {0xba02, 0x00f1},
-       {0xba00, 0x00f0}, {0xba01, 0x00f1}, {0xbaf0, 0x0006}, {0xba0e, 0x00f1},
-       {0xba70, 0x0006}, {0xba0e, 0x00f1},
-       {0xffff, 0xffff},
-       {0xba74, 0x0006}, {0xba0e, 0x00f1},
-       {0xffff, 0xffff},
-       {0x0061, 0x0000}, {0x0068, 0x000d},
-};
-
-static struct validx tbl_init_at_startup[] = {
-       {0x0000, 0x0000}, {0x0010, 0x0010},
-       {35, 0xffff},
-       {0x0008, 0x00c0}, {0x0001, 0x00c1}, {0x0001, 0x00c2}, {0x0020, 0x0006},
-       {0x006a, 0x000d},
-};
-
-static struct validx tbl_sensor_settings_common[] = {
-       {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2}, {0x0040, 0x0000},
-       {0x006a, 0x0007}, {0x006a, 0x000d}, {0x0063, 0x0006},
-};
-static struct validx tbl_sensor_settings_1280[] = {
-       {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba5a, 0x0066}, {0xba02, 0x00f1},
-       {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xba20, 0x0065}, {0xba00, 0x00f1},
-};
-static struct validx tbl_sensor_settings_800[] = {
-       {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xba5a, 0x0066}, {0xba02, 0x00f1},
-       {0xba05, 0x0067}, {0xba05, 0x00f1}, {0xba20, 0x0065}, {0xba00, 0x00f1},
-};
-static struct validx tbl_sensor_settings_640[] = {
-       {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
-       {0xba51, 0x0066}, {0xba02, 0x00f1}, {0xba05, 0x0067}, {0xba05, 0x00f1},
-       {0xba20, 0x0065}, {0xba00, 0x00f1},
-};
-static struct validx tbl_post_unset_alt[] = {
-       {0xba00, 0x00f0}, {0xba00, 0x00f1}, {0xbaa0, 0x0065}, {0xba00, 0x00f1},
-       {0x0061, 0x0000}, {0x0068, 0x000d},
-};
-
-static u8 *tbl_1280[] = {
-       "\x0d\x80\xf1\x08\x03\x04\xf1\x00" "\x04\x05\xf1\x02\x05\x00\xf1\xf1"
-       "\x06\x00\xf1\x0d\x20\x01\xf1\x00" "\x21\x84\xf1\x00\x0d\x00\xf1\x08"
-       "\xf0\x00\xf1\x01\x34\x00\xf1\x00" "\x9b\x43\xf1\x00\xa6\x05\xf1\x00"
-       "\xa9\x04\xf1\x00\xa1\x05\xf1\x00" "\xa4\x04\xf1\x00\xae\x0a\xf1\x08"
-       ,
-       "\xf0\x00\xf1\x02\x3a\x05\xf1\xf1" "\x3c\x05\xf1\xf1\x59\x01\xf1\x47"
-       "\x5a\x01\xf1\x88\x5c\x0a\xf1\x06" "\x5d\x0e\xf1\x0a\x64\x5e\xf1\x1c"
-       "\xd2\x00\xf1\xcf\xcb\x00\xf1\x01"
-       ,
-       "\xd3\x02\xd4\x28\xd5\x01\xd0\x02" "\xd1\x18\xd2\xc1"
-};
-
-static u8 *tbl_800[] = {
-       "\x0d\x80\xf1\x08\x03\x03\xf1\xc0" "\x04\x05\xf1\x02\x05\x00\xf1\xf1"
-       "\x06\x00\xf1\x0d\x20\x01\xf1\x00" "\x21\x84\xf1\x00\x0d\x00\xf1\x08"
-       "\xf0\x00\xf1\x01\x34\x00\xf1\x00" "\x9b\x43\xf1\x00\xa6\x05\xf1\x00"
-       "\xa9\x03\xf1\xc0\xa1\x03\xf1\x20" "\xa4\x02\xf1\x5a\xae\x0a\xf1\x08"
-       ,
-       "\xf0\x00\xf1\x02\x3a\x05\xf1\xf1" "\x3c\x05\xf1\xf1\x59\x01\xf1\x47"
-       "\x5a\x01\xf1\x88\x5c\x0a\xf1\x06" "\x5d\x0e\xf1\x0a\x64\x5e\xf1\x1c"
-       "\xd2\x00\xf1\xcf\xcb\x00\xf1\x01"
-       ,
-       "\xd3\x02\xd4\x18\xd5\x21\xd0\x02" "\xd1\x10\xd2\x59"
-};
-
-static u8 *tbl_640[] = {
-       "\x0d\x80\xf1\x08\x03\x04\xf1\x04" "\x04\x05\xf1\x02\x07\x01\xf1\x7c"
-       "\x08\x00\xf1\x0e\x21\x80\xf1\x00" "\x0d\x00\xf1\x08\xf0\x00\xf1\x01"
-       "\x34\x10\xf1\x10\x3a\x43\xf1\x00" "\xa6\x05\xf1\x02\xa9\x04\xf1\x04"
-       "\xa7\x02\xf1\x81\xaa\x01\xf1\xe2" "\xae\x0c\xf1\x09"
-       ,
-       "\xf0\x00\xf1\x02\x39\x03\xf1\xfc" "\x3b\x04\xf1\x04\x57\x01\xf1\xb6"
-       "\x58\x02\xf1\x0d\x5c\x1f\xf1\x19" "\x5d\x24\xf1\x1e\x64\x5e\xf1\x1c"
-       "\xd2\x00\xf1\x00\xcb\x00\xf1\x01"
-       ,
-       "\xd3\x02\xd4\x10\xd5\x81\xd0\x02" "\xd1\x08\xd2\xe1"
-};
-
-static s32 tbl_sat[] = {0x25, 0x1d, 0x15, 0x0d, 0x05, 0x4d, 0x55, 0x5d, 0x2d};
-static s32 tbl_bright[] = {0, 8, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70};
-static s32 tbl_backlight[] = {0x0e, 0x06, 0x02};
-
-static s32 tbl_cntr1[] = {
-       0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xe0, 0xf0};
-static s32 tbl_cntr2[] = {
-       0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40, 0x38, 0x30, 0x20, 0x10};
-
-static u8 dat_wbalNL[] =
-       "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x3b\x04\xf1\x2a\x47\x10\xf1\x10"
-       "\x9d\x3c\xf1\xae\xaf\x10\xf1\x00" "\xf0\x00\xf1\x02\x2f\x91\xf1\x20"
-       "\x9c\x91\xf1\x20\x37\x03\xf1\x00" "\x9d\xc5\xf1\x0f\xf0\x00\xf1\x00";
-
-static u8 dat_wbalLL[] =
-       "\xf0\x00\xf1\x01\x05\x00\xf1\x0c" "\x3b\x04\xf1\x2a\x47\x40\xf1\x40"
-       "\x9d\x20\xf1\xae\xaf\x10\xf1\x00" "\xf0\x00\xf1\x02\x2f\xd1\xf1\x00"
-       "\x9c\xd1\xf1\x00\x37\x03\xf1\x00" "\x9d\xc5\xf1\x3f\xf0\x00\xf1\x00";
-
-static u8 dat_wbalBL[] =
-       "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x47\x10\xf1\x30\x9d\x3c\xf1\xae"
-       "\xaf\x10\xf1\x00\xf0\x00\xf1\x02" "\x2f\x91\xf1\x20\x9c\x91\xf1\x20"
-       "\x37\x03\xf1\x00\x9d\xc5\xf1\x2f" "\xf0\x00\xf1\x00";
-
-static u8 dat_hvflip1[] = {0xf0, 0x00, 0xf1, 0x00};
-
-static u8 dat_common00[] =
-       "\x00\x01\x07\x6a\x06\x63\x0d\x6a" "\xc0\x00\x10\x10\xc1\x03\xc2\x42"
-       "\xd8\x04\x58\x00\x04\x02";
-static u8 dat_common01[] =
-       "\x0d\x00\xf1\x0b\x0d\x00\xf1\x08" "\x35\x00\xf1\x22\x68\x00\xf1\x5d"
-       "\xf0\x00\xf1\x01\x06\x70\xf1\x0e" "\xf0\x00\xf1\x02\xdd\x18\xf1\xe0";
-static u8 dat_common02[] =
-       "\x05\x01\xf1\x84\x06\x00\xf1\x44" "\x07\x00\xf1\xbe\x08\x00\xf1\x1e"
-       "\x20\x01\xf1\x03\x21\x84\xf1\x00" "\x22\x0d\xf1\x0f\x24\x80\xf1\x00"
-       "\x34\x18\xf1\x2d\x35\x00\xf1\x22" "\x43\x83\xf1\x83\x59\x00\xf1\xff";
-static u8 dat_common03[] =
-       "\xf0\x00\xf1\x02\x39\x06\xf1\x8c" "\x3a\x06\xf1\x8c\x3b\x03\xf1\xda"
-       "\x3c\x05\xf1\x30\x57\x01\xf1\x0c" "\x58\x01\xf1\x42\x59\x01\xf1\x0c"
-       "\x5a\x01\xf1\x42\x5c\x13\xf1\x0e" "\x5d\x17\xf1\x12\x64\x1e\xf1\x1c";
-static u8 dat_common04[] =
-       "\xf0\x00\xf1\x02\x24\x5f\xf1\x20" "\x28\xea\xf1\x02\x5f\x41\xf1\x43";
-static u8 dat_common05[] =
-       "\x02\x00\xf1\xee\x03\x29\xf1\x1a" "\x04\x02\xf1\xa4\x09\x00\xf1\x68"
-       "\x0a\x00\xf1\x2a\x0b\x00\xf1\x04" "\x0c\x00\xf1\x93\x0d\x00\xf1\x82"
-       "\x0e\x00\xf1\x40\x0f\x00\xf1\x5f" "\x10\x00\xf1\x4e\x11\x00\xf1\x5b";
-static u8 dat_common06[] =
-       "\x15\x00\xf1\xc9\x16\x00\xf1\x5e" "\x17\x00\xf1\x9d\x18\x00\xf1\x06"
-       "\x19\x00\xf1\x89\x1a\x00\xf1\x12" "\x1b\x00\xf1\xa1\x1c\x00\xf1\xe4"
-       "\x1d\x00\xf1\x7a\x1e\x00\xf1\x64" "\xf6\x00\xf1\x5f";
-static u8 dat_common07[] =
-       "\xf0\x00\xf1\x01\x53\x09\xf1\x03" "\x54\x3d\xf1\x1c\x55\x99\xf1\x72"
-       "\x56\xc1\xf1\xb1\x57\xd8\xf1\xce" "\x58\xe0\xf1\x00\xdc\x0a\xf1\x03"
-       "\xdd\x45\xf1\x20\xde\xae\xf1\x82" "\xdf\xdc\xf1\xc9\xe0\xf6\xf1\xea"
-       "\xe1\xff\xf1\x00";
-static u8 dat_common08[] =
-       "\xf0\x00\xf1\x01\x80\x00\xf1\x06" "\x81\xf6\xf1\x08\x82\xfb\xf1\xf7"
-       "\x83\x00\xf1\xfe\xb6\x07\xf1\x03" "\xb7\x18\xf1\x0c\x84\xfb\xf1\x06"
-       "\x85\xfb\xf1\xf9\x86\x00\xf1\xff" "\xb8\x07\xf1\x04\xb9\x16\xf1\x0a";
-static u8 dat_common09[] =
-       "\x87\xfa\xf1\x05\x88\xfc\xf1\xf9" "\x89\x00\xf1\xff\xba\x06\xf1\x03"
-       "\xbb\x17\xf1\x09\x8a\xe8\xf1\x14" "\x8b\xf7\xf1\xf0\x8c\xfd\xf1\xfa"
-       "\x8d\x00\xf1\x00\xbc\x05\xf1\x01" "\xbd\x0c\xf1\x08\xbe\x00\xf1\x14";
-static u8 dat_common10[] =
-       "\x8e\xea\xf1\x13\x8f\xf7\xf1\xf2" "\x90\xfd\xf1\xfa\x91\x00\xf1\x00"
-       "\xbf\x05\xf1\x01\xc0\x0a\xf1\x08" "\xc1\x00\xf1\x0c\x92\xed\xf1\x0f"
-       "\x93\xf9\xf1\xf4\x94\xfe\xf1\xfb" "\x95\x00\xf1\x00\xc2\x04\xf1\x01"
-       "\xc3\x0a\xf1\x07\xc4\x00\xf1\x10";
-static u8 dat_common11[] =
-       "\xf0\x00\xf1\x01\x05\x00\xf1\x06" "\x25\x00\xf1\x55\x34\x10\xf1\x10"
-       "\x35\xf0\xf1\x10\x3a\x02\xf1\x03" "\x3b\x04\xf1\x2a\x9b\x43\xf1\x00"
-       "\xa4\x03\xf1\xc0\xa7\x02\xf1\x81";
-
-static int  mi1320_init_at_startup(struct gspca_dev *gspca_dev);
-static int  mi1320_configure_alt(struct gspca_dev *gspca_dev);
-static int  mi1320_init_pre_alt(struct gspca_dev *gspca_dev);
-static int  mi1320_init_post_alt(struct gspca_dev *gspca_dev);
-static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev);
-static int  mi1320_sensor_settings(struct gspca_dev *gspca_dev);
-static int  mi1320_camera_settings(struct gspca_dev *gspca_dev);
-/*==========================================================================*/
-
-void mi1320_init_settings(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->vcur.backlight  =  0;
-       sd->vcur.brightness =  0;
-       sd->vcur.sharpness  =  6;
-       sd->vcur.contrast   = 10;
-       sd->vcur.gamma      = 20;
-       sd->vcur.hue        =  0;
-       sd->vcur.saturation =  6;
-       sd->vcur.whitebal   =  0;
-       sd->vcur.mirror     = 0;
-       sd->vcur.flip       = 0;
-       sd->vcur.AC50Hz     = 1;
-
-       sd->vmax.backlight  =  2;
-       sd->vmax.brightness =  8;
-       sd->vmax.sharpness  =  7;
-       sd->vmax.contrast   =  0; /* 10 but not working with this driver */
-       sd->vmax.gamma      = 40;
-       sd->vmax.hue        =  5 + 1;
-       sd->vmax.saturation =  8;
-       sd->vmax.whitebal   =  2;
-       sd->vmax.mirror     = 1;
-       sd->vmax.flip       = 1;
-       sd->vmax.AC50Hz     = 1;
-
-       sd->dev_camera_settings = mi1320_camera_settings;
-       sd->dev_init_at_startup = mi1320_init_at_startup;
-       sd->dev_configure_alt   = mi1320_configure_alt;
-       sd->dev_init_pre_alt    = mi1320_init_pre_alt;
-       sd->dev_post_unset_alt  = mi1320_post_unset_alt;
-}
-
-/*==========================================================================*/
-
-static void common(struct gspca_dev *gspca_dev)
-{
-       s32 n; /* reserved for FETCH functions */
-
-       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 22, dat_common00);
-       ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL);
-       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 32, dat_common01);
-       n = fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common));
-       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common02);
-       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common03);
-       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 16, dat_common04);
-       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common05);
-       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 44, dat_common06);
-       keep_on_fetching_validx(gspca_dev, tbl_common,
-                                       ARRAY_SIZE(tbl_common), n);
-       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 52, dat_common07);
-       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common08);
-       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 48, dat_common09);
-       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 56, dat_common10);
-       keep_on_fetching_validx(gspca_dev, tbl_common,
-                                       ARRAY_SIZE(tbl_common), n);
-       ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, dat_common11);
-       keep_on_fetching_validx(gspca_dev, tbl_common,
-                                       ARRAY_SIZE(tbl_common), n);
-}
-
-static int mi1320_init_at_startup(struct gspca_dev *gspca_dev)
-{
-       fetch_validx(gspca_dev, tbl_init_at_startup,
-                               ARRAY_SIZE(tbl_init_at_startup));
-
-       common(gspca_dev);
-
-/*     ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */
-
-       return 0;
-}
-
-static int mi1320_init_pre_alt(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->mirrorMask = 0;
-
-       sd->vold.backlight  = -1;
-       sd->vold.brightness = -1;
-       sd->vold.sharpness  = -1;
-       sd->vold.contrast   = -1;
-       sd->vold.saturation = -1;
-       sd->vold.gamma    = -1;
-       sd->vold.hue      = -1;
-       sd->vold.whitebal = -1;
-       sd->vold.mirror   = -1;
-       sd->vold.flip     = -1;
-       sd->vold.AC50Hz   = -1;
-
-       common(gspca_dev);
-
-       mi1320_sensor_settings(gspca_dev);
-
-       mi1320_init_post_alt(gspca_dev);
-
-       return 0;
-}
-
-static int mi1320_init_post_alt(struct gspca_dev *gspca_dev)
-{
-       mi1320_camera_settings(gspca_dev);
-
-       return 0;
-}
-
-static int mi1320_sensor_settings(struct gspca_dev *gspca_dev)
-{
-       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
-
-       ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
-
-       fetch_validx(gspca_dev, tbl_sensor_settings_common,
-                               ARRAY_SIZE(tbl_sensor_settings_common));
-
-       switch (reso) {
-       case IMAGE_1280:
-               fetch_validx(gspca_dev, tbl_sensor_settings_1280,
-                                       ARRAY_SIZE(tbl_sensor_settings_1280));
-               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 64, tbl_1280[0]);
-               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_1280[1]);
-               ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_1280[2]);
-               break;
-
-       case IMAGE_800:
-               fetch_validx(gspca_dev, tbl_sensor_settings_800,
-                                       ARRAY_SIZE(tbl_sensor_settings_800));
-               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 64, tbl_800[0]);
-               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_800[1]);
-               ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_800[2]);
-               break;
-
-       default:
-               fetch_validx(gspca_dev, tbl_sensor_settings_640,
-                                       ARRAY_SIZE(tbl_sensor_settings_640));
-               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 60, tbl_640[0]);
-               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 40, tbl_640[1]);
-               ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, tbl_640[2]);
-               break;
-       }
-       return 0;
-}
-
-static int mi1320_configure_alt(struct gspca_dev *gspca_dev)
-{
-       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
-
-       switch (reso) {
-       case IMAGE_640:
-               gspca_dev->alt = 3 + 1;
-               break;
-
-       case IMAGE_800:
-       case IMAGE_1280:
-               gspca_dev->alt = 1 + 1;
-               break;
-       }
-       return 0;
-}
-
-static int mi1320_camera_settings(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       s32 backlight = sd->vcur.backlight;
-       s32 bright = sd->vcur.brightness;
-       s32 sharp  = sd->vcur.sharpness;
-       s32 cntr   = sd->vcur.contrast;
-       s32 gam    = sd->vcur.gamma;
-       s32 hue    = sd->vcur.hue;
-       s32 sat    = sd->vcur.saturation;
-       s32 wbal   = sd->vcur.whitebal;
-       s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
-       s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) > 0);
-       s32 freq   = (sd->vcur.AC50Hz > 0);
-       s32 i;
-
-       if (freq != sd->vold.AC50Hz) {
-               sd->vold.AC50Hz = freq;
-
-               freq = 2 * (freq == 0);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba02, 0x00f1, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00       , 0x005b, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba01 + freq, 0x00f1, 0, NULL);
-       }
-
-       if (wbal != sd->vold.whitebal) {
-               sd->vold.whitebal = wbal;
-               if (wbal < 0 || wbal > sd->vmax.whitebal)
-                       wbal = 0;
-
-               for (i = 0; i < 2; i++) {
-                       if (wbal == 0) { /* Normal light */
-                               ctrl_out(gspca_dev, 0x40, 1,
-                                               0x0010, 0x0010, 0, NULL);
-                               ctrl_out(gspca_dev, 0x40, 1,
-                                               0x0003, 0x00c1, 0, NULL);
-                               ctrl_out(gspca_dev, 0x40, 1,
-                                               0x0042, 0x00c2, 0, NULL);
-                               ctrl_out(gspca_dev, 0x40, 3,
-                                               0xba00, 0x0200, 48, dat_wbalNL);
-                       }
-
-                       if (wbal == 1) { /* Low light */
-                               ctrl_out(gspca_dev, 0x40, 1,
-                                               0x0010, 0x0010, 0, NULL);
-                               ctrl_out(gspca_dev, 0x40, 1,
-                                               0x0004, 0x00c1, 0, NULL);
-                               ctrl_out(gspca_dev, 0x40, 1,
-                                               0x0043, 0x00c2, 0, NULL);
-                               ctrl_out(gspca_dev, 0x40, 3,
-                                               0xba00, 0x0200, 48, dat_wbalLL);
-                       }
-
-                       if (wbal == 2) { /* Back light */
-                               ctrl_out(gspca_dev, 0x40, 1,
-                                               0x0010, 0x0010, 0, NULL);
-                               ctrl_out(gspca_dev, 0x40, 1,
-                                               0x0003, 0x00c1, 0, NULL);
-                               ctrl_out(gspca_dev, 0x40, 1,
-                                               0x0042, 0x00c2, 0, NULL);
-                               ctrl_out(gspca_dev, 0x40, 3,
-                                               0xba00, 0x0200, 44, dat_wbalBL);
-                       }
-               }
-       }
-
-       if (bright != sd->vold.brightness) {
-               sd->vold.brightness = bright;
-               if (bright < 0 || bright > sd->vmax.brightness)
-                       bright = 0;
-
-               bright = tbl_bright[bright];
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + bright, 0x0034, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + bright, 0x00f1, 0, NULL);
-       }
-
-       if (sat != sd->vold.saturation) {
-               sd->vold.saturation = sat;
-               if (sat < 0 || sat > sd->vmax.saturation)
-                       sat = 0;
-
-               sat = tbl_sat[sat];
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00      , 0x0025, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + sat, 0x00f1, 0, NULL);
-       }
-
-       if (sharp != sd->vold.sharpness) {
-               sd->vold.sharpness = sharp;
-               if (sharp < 0 || sharp > sd->vmax.sharpness)
-                       sharp = 0;
-
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00        , 0x0005, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + sharp, 0x00f1, 0, NULL);
-       }
-
-       if (hue != sd->vold.hue) {
-               /* 0=normal  1=NB  2="sepia"  3=negative  4=other  5=other2 */
-               if (hue < 0 || hue > sd->vmax.hue)
-                       hue = 0;
-               if (hue == sd->vmax.hue)
-                       sd->swapRB = 1;
-               else
-                       sd->swapRB = 0;
-
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba70, 0x00e2, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + hue * (hue < 6), 0x00f1,
-                                                       0, NULL);
-       }
-
-       if (backlight != sd->vold.backlight) {
-               sd->vold.backlight = backlight;
-               if (backlight < 0 || backlight > sd->vmax.backlight)
-                       backlight = 0;
-
-               backlight = tbl_backlight[backlight];
-               for (i = 0; i < 2; i++) {
-                       ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
-                       ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
-                       ctrl_out(gspca_dev, 0x40, 1, 0xba74, 0x0006, 0, NULL);
-                       ctrl_out(gspca_dev, 0x40, 1, 0xba80 + backlight, 0x00f1,
-                                                               0, NULL);
-               }
-       }
-
-       if (hue != sd->vold.hue) {
-               sd->vold.hue = hue;
-
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba70, 0x00e2, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + hue * (hue < 6), 0x00f1,
-                                                       0, NULL);
-       }
-
-       if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
-               u8 dat_hvflip2[4] = {0x20, 0x01, 0xf1, 0x00};
-               sd->vold.mirror = mirror;
-               sd->vold.flip = flip;
-
-               dat_hvflip2[3] = flip + 2 * mirror;
-               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 4, dat_hvflip1);
-               ctrl_out(gspca_dev, 0x40, 3, 0xba00, 0x0200, 4, dat_hvflip2);
-       }
-
-       if (gam != sd->vold.gamma) {
-               sd->vold.gamma = gam;
-               if (gam < 0 || gam > sd->vmax.gamma)
-                       gam = 0;
-
-               gam = 2 * gam;
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba04      , 0x003b, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba02 + gam, 0x00f1, 0, NULL);
-       }
-
-       if (cntr != sd->vold.contrast) {
-               sd->vold.contrast = cntr;
-               if (cntr < 0 || cntr > sd->vmax.contrast)
-                       cntr = 0;
-
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00, 0x00f0, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba01, 0x00f1, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + tbl_cntr1[cntr], 0x0035,
-                                                       0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0xba00 + tbl_cntr2[cntr], 0x00f1,
-                                                       0, NULL);
-       }
-
-       return 0;
-}
-
-static void mi1320_post_unset_alt(struct gspca_dev *gspca_dev)
-{
-       ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
-
-       fetch_validx(gspca_dev, tbl_post_unset_alt,
-                               ARRAY_SIZE(tbl_post_unset_alt));
-}
diff --git a/drivers/media/video/gspca/gl860/gl860-mi2020.c b/drivers/media/video/gspca/gl860/gl860-mi2020.c
deleted file mode 100644 (file)
index 2edda6b..0000000
+++ /dev/null
@@ -1,733 +0,0 @@
-/* Subdriver for the GL860 chip with the MI2020 sensor
- * Author Olivier LORIN, from logs by Iceman/Soro2005 + Fret_saw/Hulkie/Tricid
- * with the help of Kytrix/BUGabundo/Blazercist.
- * Driver achieved thanks to a webcam gift by Kytrix.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Sensor : MI2020 */
-
-#include "gl860.h"
-
-static u8 dat_wbal1[] = {0x8c, 0xa2, 0x0c};
-
-static u8 dat_bright1[] = {0x8c, 0xa2, 0x06};
-static u8 dat_bright3[] = {0x8c, 0xa1, 0x02};
-static u8 dat_bright4[] = {0x90, 0x00, 0x0f};
-static u8 dat_bright5[] = {0x8c, 0xa1, 0x03};
-static u8 dat_bright6[] = {0x90, 0x00, 0x05};
-
-static u8 dat_hvflip1[] = {0x8c, 0x27, 0x19};
-static u8 dat_hvflip3[] = {0x8c, 0x27, 0x3b};
-static u8 dat_hvflip5[] = {0x8c, 0xa1, 0x03};
-static u8 dat_hvflip6[] = {0x90, 0x00, 0x06};
-
-static struct idxdata tbl_middle_hvflip_low[] = {
-       {0x33, "\x90\x00\x06"},
-       {6, "\xff\xff\xff"},
-       {0x33, "\x90\x00\x06"},
-       {6, "\xff\xff\xff"},
-       {0x33, "\x90\x00\x06"},
-       {6, "\xff\xff\xff"},
-       {0x33, "\x90\x00\x06"},
-       {6, "\xff\xff\xff"},
-};
-
-static struct idxdata tbl_middle_hvflip_big[] = {
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa1\x20"},
-       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"},
-       {102, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa1\x20"},
-       {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
-};
-
-static struct idxdata tbl_end_hvflip[] = {
-       {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
-       {6, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
-       {6, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
-       {6, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x02"}, {0x33, "\x90\x00\x1f"},
-};
-
-static u8 dat_freq1[] = { 0x8c, 0xa4, 0x04 };
-
-static u8 dat_multi5[] = { 0x8c, 0xa1, 0x03 };
-static u8 dat_multi6[] = { 0x90, 0x00, 0x05 };
-
-static struct validx tbl_init_at_startup[] = {
-       {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1},
-       {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d},
-       {53, 0xffff},
-       {0x0040, 0x0000}, {0x0063, 0x0006},
-};
-
-static struct validx tbl_common_0B[] = {
-       {0x0002, 0x0004}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a, 0x000d},
-       {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0003, 0x00c1}, {0x0042, 0x00c2},
-       {0x0004, 0x00d8}, {0x0000, 0x0058}, {0x0041, 0x0000},
-};
-
-static struct idxdata tbl_common_3B[] = {
-       {0x33, "\x86\x25\x01"}, {0x33, "\x86\x25\x00"},
-       {2, "\xff\xff\xff"},
-       {0x30, "\x1a\x0a\xcc"}, {0x32, "\x02\x00\x08"}, {0x33, "\xf4\x03\x1d"},
-       {6, "\xff\xff\xff"}, /* 12 */
-       {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
-       {2, "\xff\xff\xff"}, /* - */
-       {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\x22\x23"},
-       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa2\x0f"}, {0x33, "\x90\x00\x0d"},
-       {0x33, "\x8c\xa2\x10"}, {0x33, "\x90\x00\x0b"}, {0x33, "\x8c\xa2\x11"},
-       {0x33, "\x90\x00\x07"}, {0x33, "\xf4\x03\x1d"}, {0x35, "\xa2\x00\xe2"},
-       {0x33, "\x8c\xab\x05"}, {0x33, "\x90\x00\x01"}, {0x32, "\x6e\x00\x86"},
-       {0x32, "\x70\x0f\xaa"}, {0x32, "\x72\x0f\xe4"}, {0x33, "\x8c\xa3\x4a"},
-       {0x33, "\x90\x00\x5a"}, {0x33, "\x8c\xa3\x4b"}, {0x33, "\x90\x00\xa6"},
-       {0x33, "\x8c\xa3\x61"}, {0x33, "\x90\x00\xc8"}, {0x33, "\x8c\xa3\x62"},
-       {0x33, "\x90\x00\xe1"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"},
-       {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"},
-       {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"},
-       {0x34, "\xde\x01\x5b"}, {0x34, "\xe6\x01\x13"}, {0x34, "\xee\x0b\xf0"},
-       {0x34, "\xf6\x0b\xa4"}, {0x35, "\x00\xf6\xe7"}, {0x35, "\x08\x0d\xfd"},
-       {0x35, "\x10\x25\x63"}, {0x35, "\x18\x35\x6c"}, {0x35, "\x20\x42\x7e"},
-       {0x35, "\x28\x19\x44"}, {0x35, "\x30\x39\xd4"}, {0x35, "\x38\xf5\xa8"},
-       {0x35, "\x4c\x07\x90"}, {0x35, "\x44\x07\xb8"}, {0x35, "\x5c\x06\x88"},
-       {0x35, "\x54\x07\xff"}, {0x34, "\xe0\x01\x52"}, {0x34, "\xe8\x00\xcc"},
-       {0x34, "\xf0\x0d\x83"}, {0x34, "\xf8\x0c\xb3"}, {0x35, "\x02\xfe\xba"},
-       {0x35, "\x0a\x04\xe0"}, {0x35, "\x12\x1c\x63"}, {0x35, "\x1a\x2b\x5a"},
-       {0x35, "\x22\x32\x5e"}, {0x35, "\x2a\x0d\x28"}, {0x35, "\x32\x2c\x02"},
-       {0x35, "\x3a\xf4\xfa"}, {0x35, "\x4e\x07\xef"}, {0x35, "\x46\x07\x88"},
-       {0x35, "\x5e\x07\xc1"}, {0x35, "\x56\x04\x64"}, {0x34, "\xe4\x01\x15"},
-       {0x34, "\xec\x00\x82"}, {0x34, "\xf4\x0c\xce"}, {0x34, "\xfc\x0c\xba"},
-       {0x35, "\x06\x1f\x02"}, {0x35, "\x0e\x02\xe3"}, {0x35, "\x16\x1a\x50"},
-       {0x35, "\x1e\x24\x39"}, {0x35, "\x26\x23\x4c"}, {0x35, "\x2e\xf9\x1b"},
-       {0x35, "\x36\x23\x19"}, {0x35, "\x3e\x12\x08"}, {0x35, "\x52\x07\x22"},
-       {0x35, "\x4a\x03\xd3"}, {0x35, "\x62\x06\x54"}, {0x35, "\x5a\x04\x5d"},
-       {0x34, "\xe2\x01\x04"}, {0x34, "\xea\x00\xa0"}, {0x34, "\xf2\x0c\xbc"},
-       {0x34, "\xfa\x0c\x5b"}, {0x35, "\x04\x17\xf2"}, {0x35, "\x0c\x02\x08"},
-       {0x35, "\x14\x28\x43"}, {0x35, "\x1c\x28\x62"}, {0x35, "\x24\x2b\x60"},
-       {0x35, "\x2c\x07\x33"}, {0x35, "\x34\x1f\xb0"}, {0x35, "\x3c\xed\xcd"},
-       {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"},
-       {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"},
-       {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"},
-       {0x33, "\x78\x00\x00"},
-       {2, "\xff\xff\xff"},
-       {0x35, "\xb8\x1f\x20"}, {0x33, "\x8c\xa2\x06"}, {0x33, "\x90\x00\x10"},
-       {0x33, "\x8c\xa2\x07"}, {0x33, "\x90\x00\x08"}, {0x33, "\x8c\xa2\x42"},
-       {0x33, "\x90\x00\x0b"}, {0x33, "\x8c\xa2\x4a"}, {0x33, "\x90\x00\x8c"},
-       {0x35, "\xba\xfa\x08"}, {0x33, "\x8c\xa2\x02"}, {0x33, "\x90\x00\x22"},
-       {0x33, "\x8c\xa2\x03"}, {0x33, "\x90\x00\xbb"}, {0x33, "\x8c\xa4\x04"},
-       {0x33, "\x90\x00\x80"}, {0x33, "\x8c\xa7\x9d"}, {0x33, "\x90\x00\x00"},
-       {0x33, "\x8c\xa7\x9e"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa2\x0c"},
-       {0x33, "\x90\x00\x17"}, {0x33, "\x8c\xa2\x15"}, {0x33, "\x90\x00\x04"},
-       {0x33, "\x8c\xa2\x14"}, {0x33, "\x90\x00\x20"}, {0x33, "\x8c\xa1\x03"},
-       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"}, {0x33, "\x90\x21\x11"},
-       {0x33, "\x8c\x27\x1b"}, {0x33, "\x90\x02\x4f"}, {0x33, "\x8c\x27\x25"},
-       {0x33, "\x90\x06\x0f"}, {0x33, "\x8c\x27\x39"}, {0x33, "\x90\x21\x11"},
-       {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"}, {0x33, "\x8c\x27\x47"},
-       {0x33, "\x90\x09\x4c"}, {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x02\x84"},
-       {0x33, "\x8c\x27\x05"}, {0x33, "\x90\x01\xe2"}, {0x33, "\x8c\x27\x07"},
-       {0x33, "\x90\x06\x40"}, {0x33, "\x8c\x27\x09"}, {0x33, "\x90\x04\xb0"},
-       {0x33, "\x8c\x27\x0d"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x0f"},
-       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x11"}, {0x33, "\x90\x04\xbd"},
-       {0x33, "\x8c\x27\x13"}, {0x33, "\x90\x06\x4d"}, {0x33, "\x8c\x27\x15"},
-       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x17"}, {0x33, "\x90\x21\x11"},
-       {0x33, "\x8c\x27\x19"}, {0x33, "\x90\x04\x6c"}, {0x33, "\x8c\x27\x1b"},
-       {0x33, "\x90\x02\x4f"}, {0x33, "\x8c\x27\x1d"}, {0x33, "\x90\x01\x02"},
-       {0x33, "\x8c\x27\x1f"}, {0x33, "\x90\x02\x79"}, {0x33, "\x8c\x27\x21"},
-       {0x33, "\x90\x01\x55"}, {0x33, "\x8c\x27\x23"}, {0x33, "\x90\x02\x85"},
-       {0x33, "\x8c\x27\x25"}, {0x33, "\x90\x06\x0f"}, {0x33, "\x8c\x27\x27"},
-       {0x33, "\x90\x20\x20"}, {0x33, "\x8c\x27\x29"}, {0x33, "\x90\x20\x20"},
-       {0x33, "\x8c\x27\x2b"}, {0x33, "\x90\x10\x20"}, {0x33, "\x8c\x27\x2d"},
-       {0x33, "\x90\x20\x07"}, {0x33, "\x8c\x27\x2f"}, {0x33, "\x90\x00\x04"},
-       {0x33, "\x8c\x27\x31"}, {0x33, "\x90\x00\x04"}, {0x33, "\x8c\x27\x33"},
-       {0x33, "\x90\x04\xbb"}, {0x33, "\x8c\x27\x35"}, {0x33, "\x90\x06\x4b"},
-       {0x33, "\x8c\x27\x37"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x39"},
-       {0x33, "\x90\x21\x11"}, {0x33, "\x8c\x27\x3b"}, {0x33, "\x90\x00\x24"},
-       {0x33, "\x8c\x27\x3d"}, {0x33, "\x90\x01\x20"}, {0x33, "\x8c\x27\x41"},
-       {0x33, "\x90\x01\x69"}, {0x33, "\x8c\x27\x45"}, {0x33, "\x90\x04\xed"},
-       {0x33, "\x8c\x27\x47"}, {0x33, "\x90\x09\x4c"}, {0x33, "\x8c\x27\x51"},
-       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x53"}, {0x33, "\x90\x03\x20"},
-       {0x33, "\x8c\x27\x55"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x57"},
-       {0x33, "\x90\x02\x58"}, {0x33, "\x8c\x27\x5f"}, {0x33, "\x90\x00\x00"},
-       {0x33, "\x8c\x27\x61"}, {0x33, "\x90\x06\x40"}, {0x33, "\x8c\x27\x63"},
-       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x65"}, {0x33, "\x90\x04\xb0"},
-       {0x33, "\x8c\x22\x2e"}, {0x33, "\x90\x00\xa1"}, {0x33, "\x8c\xa4\x08"},
-       {0x33, "\x90\x00\x1f"}, {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x21"},
-       {0x33, "\x8c\xa4\x0a"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\xa4\x0b"},
-       {0x33, "\x90\x00\x27"}, {0x33, "\x8c\x24\x11"}, {0x33, "\x90\x00\xa1"},
-       {0x33, "\x8c\x24\x13"}, {0x33, "\x90\x00\xc1"}, {0x33, "\x8c\x24\x15"},
-       {0x33, "\x90\x00\x6a"}, {0x33, "\x8c\x24\x17"}, {0x33, "\x90\x00\x80"},
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
-       {2, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
-       {3, "\xff\xff\xff"},
-};
-
-static struct idxdata tbl_init_post_alt_low1[] = {
-       {0x33, "\x8c\x27\x15"}, {0x33, "\x90\x00\x25"}, {0x33, "\x8c\x22\x2e"},
-       {0x33, "\x90\x00\x81"}, {0x33, "\x8c\xa4\x08"}, {0x33, "\x90\x00\x17"},
-       {0x33, "\x8c\xa4\x09"}, {0x33, "\x90\x00\x1a"}, {0x33, "\x8c\xa4\x0a"},
-       {0x33, "\x90\x00\x1d"}, {0x33, "\x8c\xa4\x0b"}, {0x33, "\x90\x00\x20"},
-       {0x33, "\x8c\x24\x11"}, {0x33, "\x90\x00\x81"}, {0x33, "\x8c\x24\x13"},
-       {0x33, "\x90\x00\x9b"},
-};
-
-static struct idxdata tbl_init_post_alt_low2[] = {
-       {0x33, "\x8c\x27\x03"}, {0x33, "\x90\x03\x24"}, {0x33, "\x8c\x27\x05"},
-       {0x33, "\x90\x02\x58"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
-       {2, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
-       {2, "\xff\xff\xff"},
-};
-
-static struct idxdata tbl_init_post_alt_low3[] = {
-       {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
-       {2, "\xff\xff\xff"},
-       {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x20"},
-       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x01"},
-       {0x33, "\x2e\x01\x00"}, {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"},
-       {0x33, "\x90\x00\x00"}, {0x33, "\x8c\x27\x95"}, {0x33, "\x90\x01\x00"},
-       {2, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x03"},
-       {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
-       {2, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"},
-       {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"},
-       {2, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
-       {2, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
-       {2, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
-       {2, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
-};
-
-static struct idxdata tbl_init_post_alt_big[] = {
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
-       {2, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
-       {2, "\xff\xff\xff"},
-       {0x34, "\x1e\x8f\x09"}, {0x34, "\x1c\x01\x28"}, {0x34, "\x1e\x8f\x09"},
-       {2, "\xff\xff\xff"},
-       {0x34, "\x1e\x8f\x09"}, {0x32, "\x14\x06\xe6"}, {0x33, "\x8c\xa1\x03"},
-       {0x33, "\x90\x00\x05"},
-       {2, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"},
-       {2, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x05"},
-       {2, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x06"}, {0x33, "\x8c\xa1\x20"},
-       {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x30"}, {0x33, "\x90\x00\x03"},
-       {0x33, "\x8c\xa1\x31"}, {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa1\x32"},
-       {0x33, "\x90\x00\x03"}, {0x33, "\x8c\xa1\x34"}, {0x33, "\x90\x00\x03"},
-       {0x33, "\x8c\xa1\x03"}, {0x33, "\x90\x00\x02"}, {0x33, "\x2e\x01\x00"},
-       {0x34, "\x04\x00\x2a"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
-       {0x33, "\x8c\x27\x97"}, {0x33, "\x90\x01\x00"},
-       {51, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x00"}, {0x33, "\x8c\xa1\x03"},
-       {0x33, "\x90\x00\x01"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x00"},
-       {51, "\xff\xff\xff"},
-       {0x33, "\x8c\xa1\x20"}, {0x33, "\x90\x00\x72"}, {0x33, "\x8c\xa1\x03"},
-       {0x33, "\x90\x00\x02"}, {0x33, "\x8c\xa7\x02"}, {0x33, "\x90\x00\x01"},
-       {51, "\xff\xff\xff"},
-};
-
-static struct idxdata tbl_init_post_alt_3B[] = {
-       {0x32, "\x10\x01\xf8"}, {0x34, "\xce\x01\xa8"}, {0x34, "\xd0\x66\x33"},
-       {0x34, "\xd2\x31\x9a"}, {0x34, "\xd4\x94\x63"}, {0x34, "\xd6\x4b\x25"},
-       {0x34, "\xd8\x26\x70"}, {0x34, "\xda\x72\x4c"}, {0x34, "\xdc\xff\x04"},
-       {0x34, "\xde\x01\x5b"}, {0x34, "\xe6\x01\x13"}, {0x34, "\xee\x0b\xf0"},
-       {0x34, "\xf6\x0b\xa4"}, {0x35, "\x00\xf6\xe7"}, {0x35, "\x08\x0d\xfd"},
-       {0x35, "\x10\x25\x63"}, {0x35, "\x18\x35\x6c"}, {0x35, "\x20\x42\x7e"},
-       {0x35, "\x28\x19\x44"}, {0x35, "\x30\x39\xd4"}, {0x35, "\x38\xf5\xa8"},
-       {0x35, "\x4c\x07\x90"}, {0x35, "\x44\x07\xb8"}, {0x35, "\x5c\x06\x88"},
-       {0x35, "\x54\x07\xff"}, {0x34, "\xe0\x01\x52"}, {0x34, "\xe8\x00\xcc"},
-       {0x34, "\xf0\x0d\x83"}, {0x34, "\xf8\x0c\xb3"}, {0x35, "\x02\xfe\xba"},
-       {0x35, "\x0a\x04\xe0"}, {0x35, "\x12\x1c\x63"}, {0x35, "\x1a\x2b\x5a"},
-       {0x35, "\x22\x32\x5e"}, {0x35, "\x2a\x0d\x28"}, {0x35, "\x32\x2c\x02"},
-       {0x35, "\x3a\xf4\xfa"}, {0x35, "\x4e\x07\xef"}, {0x35, "\x46\x07\x88"},
-       {0x35, "\x5e\x07\xc1"}, {0x35, "\x56\x04\x64"}, {0x34, "\xe4\x01\x15"},
-       {0x34, "\xec\x00\x82"}, {0x34, "\xf4\x0c\xce"}, {0x34, "\xfc\x0c\xba"},
-       {0x35, "\x06\x1f\x02"}, {0x35, "\x0e\x02\xe3"}, {0x35, "\x16\x1a\x50"},
-       {0x35, "\x1e\x24\x39"}, {0x35, "\x26\x23\x4c"}, {0x35, "\x2e\xf9\x1b"},
-       {0x35, "\x36\x23\x19"}, {0x35, "\x3e\x12\x08"}, {0x35, "\x52\x07\x22"},
-       {0x35, "\x4a\x03\xd3"}, {0x35, "\x62\x06\x54"}, {0x35, "\x5a\x04\x5d"},
-       {0x34, "\xe2\x01\x04"}, {0x34, "\xea\x00\xa0"}, {0x34, "\xf2\x0c\xbc"},
-       {0x34, "\xfa\x0c\x5b"}, {0x35, "\x04\x17\xf2"}, {0x35, "\x0c\x02\x08"},
-       {0x35, "\x14\x28\x43"}, {0x35, "\x1c\x28\x62"}, {0x35, "\x24\x2b\x60"},
-       {0x35, "\x2c\x07\x33"}, {0x35, "\x34\x1f\xb0"}, {0x35, "\x3c\xed\xcd"},
-       {0x35, "\x50\x00\x06"}, {0x35, "\x48\x07\xff"}, {0x35, "\x60\x05\x89"},
-       {0x35, "\x58\x07\xff"}, {0x35, "\x40\x00\xa0"}, {0x35, "\x42\x00\x00"},
-       {0x32, "\x10\x01\xfc"}, {0x33, "\x8c\xa1\x18"}, {0x33, "\x90\x00\x3c"},
-};
-
-static u8 *dat_640  = "\xd0\x02\xd1\x08\xd2\xe1\xd3\x02\xd4\x10\xd5\x81";
-static u8 *dat_800  = "\xd0\x02\xd1\x10\xd2\x57\xd3\x02\xd4\x18\xd5\x21";
-static u8 *dat_1280 = "\xd0\x02\xd1\x20\xd2\x01\xd3\x02\xd4\x28\xd5\x01";
-static u8 *dat_1600 = "\xd0\x02\xd1\x20\xd2\xaf\xd3\x02\xd4\x30\xd5\x41";
-
-static int  mi2020_init_at_startup(struct gspca_dev *gspca_dev);
-static int  mi2020_configure_alt(struct gspca_dev *gspca_dev);
-static int  mi2020_init_pre_alt(struct gspca_dev *gspca_dev);
-static int  mi2020_init_post_alt(struct gspca_dev *gspca_dev);
-static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev);
-static int  mi2020_camera_settings(struct gspca_dev *gspca_dev);
-/*==========================================================================*/
-
-void mi2020_init_settings(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->vcur.backlight  =  0;
-       sd->vcur.brightness = 70;
-       sd->vcur.sharpness  = 20;
-       sd->vcur.contrast   =  0;
-       sd->vcur.gamma      =  0;
-       sd->vcur.hue        =  0;
-       sd->vcur.saturation = 60;
-       sd->vcur.whitebal   =  0; /* 50, not done by hardware */
-       sd->vcur.mirror = 0;
-       sd->vcur.flip   = 0;
-       sd->vcur.AC50Hz = 1;
-
-       sd->vmax.backlight  =  64;
-       sd->vmax.brightness = 128;
-       sd->vmax.sharpness  =  40;
-       sd->vmax.contrast   =   3;
-       sd->vmax.gamma      =   2;
-       sd->vmax.hue        =   0 + 1; /* 200, not done by hardware */
-       sd->vmax.saturation =   0;     /* 100, not done by hardware */
-       sd->vmax.whitebal   =   2;     /* 100, not done by hardware */
-       sd->vmax.mirror = 1;
-       sd->vmax.flip   = 1;
-       sd->vmax.AC50Hz = 1;
-
-       sd->dev_camera_settings = mi2020_camera_settings;
-       sd->dev_init_at_startup = mi2020_init_at_startup;
-       sd->dev_configure_alt   = mi2020_configure_alt;
-       sd->dev_init_pre_alt    = mi2020_init_pre_alt;
-       sd->dev_post_unset_alt  = mi2020_post_unset_alt;
-}
-
-/*==========================================================================*/
-
-static void common(struct gspca_dev *gspca_dev)
-{
-       fetch_validx(gspca_dev, tbl_common_0B, ARRAY_SIZE(tbl_common_0B));
-       fetch_idxdata(gspca_dev, tbl_common_3B, ARRAY_SIZE(tbl_common_3B));
-       ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x0000, 0, NULL);
-}
-
-static int mi2020_init_at_startup(struct gspca_dev *gspca_dev)
-{
-       u8 c;
-
-       ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &c);
-       ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &c);
-
-       fetch_validx(gspca_dev, tbl_init_at_startup,
-                       ARRAY_SIZE(tbl_init_at_startup));
-
-       ctrl_out(gspca_dev, 0x40,  1, 0x7a00, 0x8030,  0, NULL);
-       ctrl_in(gspca_dev, 0xc0,  2, 0x7a00, 0x8030,  1, &c);
-
-       common(gspca_dev);
-
-       msleep(61);
-/*     ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000,  0, NULL); */
-/*     msleep(36); */
-       ctrl_out(gspca_dev, 0x40,  1, 0x0001, 0x0000,  0, NULL);
-
-       return 0;
-}
-
-static int mi2020_init_pre_alt(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->mirrorMask =  0;
-       sd->vold.hue   = -1;
-
-       /* These controls need to be reset */
-       sd->vold.brightness = -1;
-       sd->vold.sharpness  = -1;
-
-       /* If not different from default, they do not need to be set */
-       sd->vold.contrast  = 0;
-       sd->vold.gamma     = 0;
-       sd->vold.backlight = 0;
-
-       mi2020_init_post_alt(gspca_dev);
-
-       return 0;
-}
-
-static int mi2020_init_post_alt(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
-
-       s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
-       s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) > 0);
-       s32 freq   = (sd->vcur.AC50Hz  > 0);
-       s32 wbal   = sd->vcur.whitebal;
-
-       u8 dat_freq2[] = {0x90, 0x00, 0x80};
-       u8 dat_multi1[] = {0x8c, 0xa7, 0x00};
-       u8 dat_multi2[] = {0x90, 0x00, 0x00};
-       u8 dat_multi3[] = {0x8c, 0xa7, 0x00};
-       u8 dat_multi4[] = {0x90, 0x00, 0x00};
-       u8 dat_hvflip2[] = {0x90, 0x04, 0x6c};
-       u8 dat_hvflip4[] = {0x90, 0x00, 0x24};
-       u8 dat_wbal2[] = {0x90, 0x00, 0x00};
-       u8 c;
-
-       sd->nbIm = -1;
-
-       dat_freq2[2] = freq ? 0xc0 : 0x80;
-       dat_multi1[2] = 0x9d;
-       dat_multi3[2] = dat_multi1[2] + 1;
-       if (wbal == 0) {
-               dat_multi4[2] = dat_multi2[2] = 0;
-               dat_wbal2[2] = 0x17;
-       } else if (wbal == 1) {
-               dat_multi4[2] = dat_multi2[2] = 0;
-               dat_wbal2[2] = 0x35;
-       } else if (wbal == 2) {
-               dat_multi4[2] = dat_multi2[2] = 0x20;
-               dat_wbal2[2] = 0x17;
-       }
-       dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror);
-       dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror);
-
-       msleep(200);
-       ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
-       msleep(2);
-
-       common(gspca_dev);
-
-       msleep(142);
-       ctrl_out(gspca_dev, 0x40,  1, 0x0010, 0x0010,  0, NULL);
-       ctrl_out(gspca_dev, 0x40,  1, 0x0003, 0x00c1,  0, NULL);
-       ctrl_out(gspca_dev, 0x40,  1, 0x0042, 0x00c2,  0, NULL);
-       ctrl_out(gspca_dev, 0x40,  1, 0x006a, 0x000d,  0, NULL);
-
-       switch (reso) {
-       case IMAGE_640:
-       case IMAGE_800:
-               if (reso != IMAGE_800)
-                       ctrl_out(gspca_dev, 0x40,  3, 0x0000, 0x0200,
-                               12, dat_640);
-               else
-                       ctrl_out(gspca_dev, 0x40,  3, 0x0000, 0x0200,
-                               12, dat_800);
-
-               fetch_idxdata(gspca_dev, tbl_init_post_alt_low1,
-                                       ARRAY_SIZE(tbl_init_post_alt_low1));
-
-               if (reso == IMAGE_800)
-                       fetch_idxdata(gspca_dev, tbl_init_post_alt_low2,
-                                       ARRAY_SIZE(tbl_init_post_alt_low2));
-
-               fetch_idxdata(gspca_dev, tbl_init_post_alt_low3,
-                               ARRAY_SIZE(tbl_init_post_alt_low3));
-
-               ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
-               msleep(120);
-               break;
-
-       case IMAGE_1280:
-       case IMAGE_1600:
-               if (reso == IMAGE_1280) {
-                       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
-                                       12, dat_1280);
-                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
-                                       3, "\x8c\x27\x07");
-                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
-                                       3, "\x90\x05\x04");
-                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
-                                       3, "\x8c\x27\x09");
-                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
-                                       3, "\x90\x04\x02");
-               } else {
-                       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
-                                       12, dat_1600);
-                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
-                                       3, "\x8c\x27\x07");
-                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
-                                       3, "\x90\x06\x40");
-                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
-                                       3, "\x8c\x27\x09");
-                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033,
-                                       3, "\x90\x04\xb0");
-               }
-
-               fetch_idxdata(gspca_dev, tbl_init_post_alt_big,
-                               ARRAY_SIZE(tbl_init_post_alt_big));
-
-               ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0010, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x00c1, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x0041, 0x00c2, 0, NULL);
-               msleep(1850);
-       }
-
-       ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
-       msleep(40);
-
-       /* AC power frequency */
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1);
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2);
-       msleep(33);
-       /* light source */
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal1);
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal2);
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
-       msleep(7);
-       ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, &c);
-
-       fetch_idxdata(gspca_dev, tbl_init_post_alt_3B,
-                       ARRAY_SIZE(tbl_init_post_alt_3B));
-
-       /* hvflip */
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1);
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2);
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3);
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4);
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5);
-       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6);
-       msleep(250);
-
-       if (reso == IMAGE_640 || reso == IMAGE_800)
-               fetch_idxdata(gspca_dev, tbl_middle_hvflip_low,
-                               ARRAY_SIZE(tbl_middle_hvflip_low));
-       else
-               fetch_idxdata(gspca_dev, tbl_middle_hvflip_big,
-                               ARRAY_SIZE(tbl_middle_hvflip_big));
-
-       fetch_idxdata(gspca_dev, tbl_end_hvflip,
-                       ARRAY_SIZE(tbl_end_hvflip));
-
-       sd->nbIm = 0;
-
-       sd->vold.mirror    = mirror;
-       sd->vold.flip      = flip;
-       sd->vold.AC50Hz    = freq;
-       sd->vold.whitebal  = wbal;
-
-       mi2020_camera_settings(gspca_dev);
-
-       return 0;
-}
-
-static int mi2020_configure_alt(struct gspca_dev *gspca_dev)
-{
-       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
-
-       switch (reso) {
-       case IMAGE_640:
-               gspca_dev->alt = 3 + 1;
-               break;
-
-       case IMAGE_800:
-       case IMAGE_1280:
-       case IMAGE_1600:
-               gspca_dev->alt = 1 + 1;
-               break;
-       }
-       return 0;
-}
-
-static int mi2020_camera_settings(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
-
-       s32 backlight = sd->vcur.backlight;
-       s32 bright =  sd->vcur.brightness;
-       s32 sharp  =  sd->vcur.sharpness;
-       s32 cntr   =  sd->vcur.contrast;
-       s32 gam    =  sd->vcur.gamma;
-       s32 hue    = (sd->vcur.hue > 0);
-       s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) > 0);
-       s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) > 0);
-       s32 freq   = (sd->vcur.AC50Hz > 0);
-       s32 wbal   = sd->vcur.whitebal;
-
-       u8 dat_sharp[] = {0x6c, 0x00, 0x08};
-       u8 dat_bright2[] = {0x90, 0x00, 0x00};
-       u8 dat_freq2[] = {0x90, 0x00, 0x80};
-       u8 dat_multi1[] = {0x8c, 0xa7, 0x00};
-       u8 dat_multi2[] = {0x90, 0x00, 0x00};
-       u8 dat_multi3[] = {0x8c, 0xa7, 0x00};
-       u8 dat_multi4[] = {0x90, 0x00, 0x00};
-       u8 dat_hvflip2[] = {0x90, 0x04, 0x6c};
-       u8 dat_hvflip4[] = {0x90, 0x00, 0x24};
-       u8 dat_wbal2[] = {0x90, 0x00, 0x00};
-
-       /* Less than 4 images received -> too early to set the settings */
-       if (sd->nbIm < 4) {
-               sd->waitSet = 1;
-               return 0;
-       }
-       sd->waitSet = 0;
-
-       if (freq != sd->vold.AC50Hz) {
-               sd->vold.AC50Hz = freq;
-
-               dat_freq2[2] = freq ? 0xc0 : 0x80;
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq1);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_freq2);
-               msleep(20);
-       }
-
-       if (wbal != sd->vold.whitebal) {
-               sd->vold.whitebal = wbal;
-               if (wbal < 0 || wbal > sd->vmax.whitebal)
-                       wbal = 0;
-
-               dat_multi1[2] = 0x9d;
-               dat_multi3[2] = dat_multi1[2] + 1;
-               if (wbal == 0) {
-                       dat_multi4[2] = dat_multi2[2] = 0;
-                       dat_wbal2[2] = 0x17;
-               } else if (wbal == 1) {
-                       dat_multi4[2] = dat_multi2[2] = 0;
-                       dat_wbal2[2] = 0x35;
-               } else if (wbal == 2) {
-                       dat_multi4[2] = dat_multi2[2] = 0x20;
-                       dat_wbal2[2] = 0x17;
-               }
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal1);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_wbal2);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
-       }
-
-       if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
-               sd->vold.mirror = mirror;
-               sd->vold.flip   = flip;
-
-               dat_hvflip2[2] = 0x6c + 2 * (1 - flip) + (1 - mirror);
-               dat_hvflip4[2] = 0x24 + 2 * (1 - flip) + (1 - mirror);
-
-               fetch_idxdata(gspca_dev, tbl_init_post_alt_3B,
-                               ARRAY_SIZE(tbl_init_post_alt_3B));
-
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip1);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip2);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip3);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip4);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip5);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_hvflip6);
-               msleep(40);
-
-               if (reso == IMAGE_640 || reso == IMAGE_800)
-                       fetch_idxdata(gspca_dev, tbl_middle_hvflip_low,
-                                       ARRAY_SIZE(tbl_middle_hvflip_low));
-               else
-                       fetch_idxdata(gspca_dev, tbl_middle_hvflip_big,
-                                       ARRAY_SIZE(tbl_middle_hvflip_big));
-
-               fetch_idxdata(gspca_dev, tbl_end_hvflip,
-                               ARRAY_SIZE(tbl_end_hvflip));
-       }
-
-       if (bright != sd->vold.brightness) {
-               sd->vold.brightness = bright;
-               if (bright < 0 || bright > sd->vmax.brightness)
-                       bright = 0;
-
-               dat_bright2[2] = bright;
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright1);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright2);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright3);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright4);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright5);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_bright6);
-       }
-
-       if (cntr != sd->vold.contrast || gam != sd->vold.gamma) {
-               sd->vold.contrast = cntr;
-               if (cntr < 0 || cntr > sd->vmax.contrast)
-                       cntr = 0;
-               sd->vold.gamma = gam;
-               if (gam < 0 || gam > sd->vmax.gamma)
-                       gam = 0;
-
-               dat_multi1[2] = 0x6d;
-               dat_multi3[2] = dat_multi1[2] + 1;
-               if (cntr == 0)
-                       cntr = 4;
-               dat_multi4[2] = dat_multi2[2] = cntr * 0x10 + 2 - gam;
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
-       }
-
-       if (backlight != sd->vold.backlight) {
-               sd->vold.backlight = backlight;
-               if (backlight < 0 || backlight > sd->vmax.backlight)
-                       backlight = 0;
-
-               dat_multi1[2] = 0x9d;
-               dat_multi3[2] = dat_multi1[2] + 1;
-               dat_multi4[2] = dat_multi2[2] = backlight;
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi1);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi2);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi3);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi4);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi5);
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0033, 3, dat_multi6);
-       }
-
-       if (sharp != sd->vold.sharpness) {
-               sd->vold.sharpness = sharp;
-               if (sharp < 0 || sharp > sd->vmax.sharpness)
-                       sharp = 0;
-
-               dat_sharp[1] = sharp;
-               ctrl_out(gspca_dev, 0x40, 3, 0x7a00, 0x0032, 3, dat_sharp);
-       }
-
-       if (hue != sd->vold.hue) {
-               sd->swapRB = hue;
-               sd->vold.hue = hue;
-       }
-
-       return 0;
-}
-
-static void mi2020_post_unset_alt(struct gspca_dev *gspca_dev)
-{
-       ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
-       msleep(40);
-       ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x0000, 0, NULL);
-}
diff --git a/drivers/media/video/gspca/gl860/gl860-ov2640.c b/drivers/media/video/gspca/gl860/gl860-ov2640.c
deleted file mode 100644 (file)
index 768cac5..0000000
+++ /dev/null
@@ -1,489 +0,0 @@
-/* Subdriver for the GL860 chip with the OV2640 sensor
- * Author Olivier LORIN, from Malmostoso's logs
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Sensor : OV2640 */
-
-#include "gl860.h"
-
-static u8 dat_init1[] = "\x00\x41\x07\x6a\x06\x61\x0d\x6a" "\x10\x10\xc1\x01";
-
-static u8 c61[] = {0x61}; /* expected */
-static u8 c51[] = {0x51}; /* expected */
-static u8 c50[] = {0x50}; /* expected */
-static u8 c28[] = {0x28}; /* expected */
-static u8 ca8[] = {0xa8}; /* expected */
-
-static u8 dat_post[] =
-       "\x00\x41\x07\x6a\x06\xef\x0d\x6a" "\x10\x10\xc1\x01";
-
-static u8 dat_640[]  = "\xd0\x01\xd1\x08\xd2\xe0\xd3\x02\xd4\x10\xd5\x81";
-static u8 dat_800[]  = "\xd0\x01\xd1\x10\xd2\x58\xd3\x02\xd4\x18\xd5\x21";
-static u8 dat_1280[] = "\xd0\x01\xd1\x18\xd2\xc0\xd3\x02\xd4\x28\xd5\x01";
-static u8 dat_1600[] = "\xd0\x01\xd1\x20\xd2\xb0\xd3\x02\xd4\x30\xd5\x41";
-
-static struct validx tbl_init_at_startup[] = {
-       {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1},
-       {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d},
-       {0x0050, 0x0000}, {0x0041, 0x0000}, {0x006a, 0x0007}, {0x0061, 0x0006},
-       {0x006a, 0x000d}, {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1},
-       {0x0041, 0x00c2}, {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058},
-       {0x0041, 0x0000}, {0x0061, 0x0000},
-};
-
-static struct validx tbl_common[] = {
-       {0x6000, 0x00ff}, {0x60ff, 0x002c}, {0x60df, 0x002e}, {0x6001, 0x00ff},
-       {0x6080, 0x0012}, {0x6000, 0x0000}, {0x6000, 0x0045}, {0x6000, 0x0010},
-       {0x6035, 0x003c}, {0x6000, 0x0011}, {0x6028, 0x0004}, {0x60e5, 0x0013},
-       {0x6088, 0x0014}, {0x600c, 0x002c}, {0x6078, 0x0033}, {0x60f7, 0x003b},
-       {0x6000, 0x003e}, {0x6011, 0x0043}, {0x6010, 0x0016}, {0x6082, 0x0039},
-       {0x6088, 0x0035}, {0x600a, 0x0022}, {0x6040, 0x0037}, {0x6000, 0x0023},
-       {0x60a0, 0x0034}, {0x601a, 0x0036}, {0x6002, 0x0006}, {0x60c0, 0x0007},
-       {0x60b7, 0x000d}, {0x6001, 0x000e}, {0x6000, 0x004c}, {0x6081, 0x004a},
-       {0x6099, 0x0021}, {0x6002, 0x0009}, {0x603e, 0x0024}, {0x6034, 0x0025},
-       {0x6081, 0x0026}, {0x6000, 0x0000}, {0x6000, 0x0045}, {0x6000, 0x0010},
-       {0x6000, 0x005c}, {0x6000, 0x0063}, {0x6000, 0x007c}, {0x6070, 0x0061},
-       {0x6080, 0x0062}, {0x6080, 0x0020}, {0x6030, 0x0028}, {0x6000, 0x006c},
-       {0x6000, 0x006e}, {0x6002, 0x0070}, {0x6094, 0x0071}, {0x60c1, 0x0073},
-       {0x6034, 0x003d}, {0x6057, 0x005a}, {0x60bb, 0x004f}, {0x609c, 0x0050},
-       {0x6080, 0x006d}, {0x6002, 0x0039}, {0x6033, 0x003a}, {0x60f1, 0x003b},
-       {0x6031, 0x003c}, {0x6000, 0x00ff}, {0x6014, 0x00e0}, {0x60ff, 0x0076},
-       {0x60a0, 0x0033}, {0x6020, 0x0042}, {0x6018, 0x0043}, {0x6000, 0x004c},
-       {0x60d0, 0x0087}, {0x600f, 0x0088}, {0x6003, 0x00d7}, {0x6010, 0x00d9},
-       {0x6005, 0x00da}, {0x6082, 0x00d3}, {0x60c0, 0x00f9}, {0x6006, 0x0044},
-       {0x6007, 0x00d1}, {0x6002, 0x00d2}, {0x6000, 0x00d2}, {0x6011, 0x00d8},
-       {0x6008, 0x00c8}, {0x6080, 0x00c9}, {0x6008, 0x007c}, {0x6020, 0x007d},
-       {0x6020, 0x007d}, {0x6000, 0x0090}, {0x600e, 0x0091}, {0x601a, 0x0091},
-       {0x6031, 0x0091}, {0x605a, 0x0091}, {0x6069, 0x0091}, {0x6075, 0x0091},
-       {0x607e, 0x0091}, {0x6088, 0x0091}, {0x608f, 0x0091}, {0x6096, 0x0091},
-       {0x60a3, 0x0091}, {0x60af, 0x0091}, {0x60c4, 0x0091}, {0x60d7, 0x0091},
-       {0x60e8, 0x0091}, {0x6020, 0x0091}, {0x6000, 0x0092}, {0x6006, 0x0093},
-       {0x60e3, 0x0093}, {0x6005, 0x0093}, {0x6005, 0x0093}, {0x6000, 0x0093},
-       {0x6004, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093},
-       {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093}, {0x6000, 0x0093},
-       {0x6000, 0x0096}, {0x6008, 0x0097}, {0x6019, 0x0097}, {0x6002, 0x0097},
-       {0x600c, 0x0097}, {0x6024, 0x0097}, {0x6030, 0x0097}, {0x6028, 0x0097},
-       {0x6026, 0x0097}, {0x6002, 0x0097}, {0x6098, 0x0097}, {0x6080, 0x0097},
-       {0x6000, 0x0097}, {0x6000, 0x0097}, {0x60ed, 0x00c3}, {0x609a, 0x00c4},
-       {0x6000, 0x00a4}, {0x6011, 0x00c5}, {0x6051, 0x00c6}, {0x6010, 0x00c7},
-       {0x6066, 0x00b6}, {0x60a5, 0x00b8}, {0x6064, 0x00b7}, {0x607c, 0x00b9},
-       {0x60af, 0x00b3}, {0x6097, 0x00b4}, {0x60ff, 0x00b5}, {0x60c5, 0x00b0},
-       {0x6094, 0x00b1}, {0x600f, 0x00b2}, {0x605c, 0x00c4}, {0x6000, 0x00a8},
-       {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x601d, 0x0086}, {0x6000, 0x0050},
-       {0x6090, 0x0051}, {0x6018, 0x0052}, {0x6000, 0x0053}, {0x6000, 0x0054},
-       {0x6088, 0x0055}, {0x6000, 0x0057}, {0x6090, 0x005a}, {0x6018, 0x005b},
-       {0x6005, 0x005c}, {0x60ed, 0x00c3}, {0x6000, 0x007f}, {0x6005, 0x00da},
-       {0x601f, 0x00e5}, {0x6067, 0x00e1}, {0x6000, 0x00e0}, {0x60ff, 0x00dd},
-       {0x6000, 0x0005}, {0x6001, 0x00ff}, {0x6000, 0x0000}, {0x6000, 0x0045},
-       {0x6000, 0x0010},
-};
-
-static struct validx tbl_sensor_settings_common1[] = {
-       {0x0041, 0x0000}, {0x006a, 0x0007}, {0x00ef, 0x0006}, {0x006a, 0x000d},
-       {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, {0x0041, 0x00c2},
-       {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, {0x0041, 0x0000},
-       {50, 0xffff},
-       {0x0061, 0x0000},
-       {0xffff, 0xffff},
-       {0x6000, 0x00ff}, {0x6000, 0x007c}, {0x6007, 0x007d},
-       {30, 0xffff},
-       {0x0040, 0x0000},
-};
-
-static struct validx tbl_sensor_settings_common2[] = {
-       {0x6001, 0x00ff}, {0x6038, 0x000c},
-       {10, 0xffff},
-       {0x6000, 0x0011},
-};
-
-static struct validx tbl_640[] = {
-       {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, {0x6067, 0x00e1},
-       {0x6004, 0x00da}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0},
-       {0x6001, 0x00ff}, {0x6000, 0x0012}, {0x6000, 0x0011}, {0x6011, 0x0017},
-       {0x6075, 0x0018}, {0x6001, 0x0019}, {0x6097, 0x001a}, {0x6036, 0x0032},
-       {0x60bb, 0x004f}, {0x6057, 0x005a}, {0x609c, 0x0050}, {0x6080, 0x006d},
-       {0x6092, 0x0026}, {0x60ff, 0x0020}, {0x6000, 0x0027}, {0x6000, 0x00ff},
-       {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x6000, 0x008c}, {0x603d, 0x0086},
-       {0x6089, 0x0050}, {0x6090, 0x0051}, {0x602c, 0x0052}, {0x6000, 0x0053},
-       {0x6000, 0x0054}, {0x6088, 0x0055}, {0x6000, 0x0057}, {0x60a0, 0x005a},
-       {0x6078, 0x005b}, {0x6000, 0x005c}, {0x6004, 0x00d3}, {0x6000, 0x00e0},
-       {0x60ff, 0x00dd}, {0x60a1, 0x005a},
-};
-
-static struct validx tbl_800[] = {
-       {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0}, {0x6067, 0x00e1},
-       {0x6004, 0x00da}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0},
-       {0x6001, 0x00ff}, {0x6040, 0x0012}, {0x6000, 0x0011}, {0x6011, 0x0017},
-       {0x6043, 0x0018}, {0x6000, 0x0019}, {0x604b, 0x001a}, {0x6009, 0x0032},
-       {0x60ca, 0x004f}, {0x60a8, 0x0050}, {0x6000, 0x006d}, {0x6038, 0x003d},
-       {0x60c8, 0x0035}, {0x6000, 0x0022}, {0x6092, 0x0026}, {0x60ff, 0x0020},
-       {0x6000, 0x0027}, {0x6000, 0x00ff}, {0x6064, 0x00c0}, {0x604b, 0x00c1},
-       {0x6000, 0x008c}, {0x601d, 0x0086}, {0x6082, 0x00d3}, {0x6000, 0x00e0},
-       {0x60ff, 0x00dd}, {0x6020, 0x008c}, {0x6001, 0x00ff}, {0x6044, 0x0018},
-};
-
-static struct validx tbl_big1[] = {
-       {0x0002, 0x00c1}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0},
-       {0x6001, 0x00ff}, {0x6000, 0x0012}, {0x6000, 0x0000}, {0x6000, 0x0045},
-       {0x6000, 0x0010}, {0x6000, 0x0011}, {0x6011, 0x0017}, {0x6075, 0x0018},
-       {0x6001, 0x0019}, {0x6097, 0x001a}, {0x6036, 0x0032}, {0x60bb, 0x004f},
-       {0x609c, 0x0050}, {0x6057, 0x005a}, {0x6080, 0x006d}, {0x6043, 0x000f},
-       {0x608f, 0x0003}, {0x6005, 0x007c}, {0x6081, 0x0026}, {0x6000, 0x00ff},
-       {0x60c8, 0x00c0}, {0x6096, 0x00c1}, {0x6000, 0x008c},
-};
-
-static struct validx tbl_big2[] = {
-       {0x603d, 0x0086}, {0x6000, 0x0050}, {0x6090, 0x0051}, {0x602c, 0x0052},
-       {0x6000, 0x0053}, {0x6000, 0x0054}, {0x6088, 0x0055}, {0x6000, 0x0057},
-       {0x6040, 0x005a}, {0x60f0, 0x005b}, {0x6001, 0x005c}, {0x6082, 0x00d3},
-       {0x6000, 0x008e},
-};
-
-static struct validx tbl_big3[] = {
-       {0x6004, 0x00da}, {0x6000, 0x00e0}, {0x6067, 0x00e1}, {0x60ff, 0x00dd},
-       {0x6001, 0x00ff}, {0x6000, 0x00ff}, {0x60f1, 0x00dd}, {0x6004, 0x00e0},
-       {0x6001, 0x00ff}, {0x6000, 0x0011}, {0x6000, 0x00ff}, {0x6010, 0x00c7},
-       {0x6000, 0x0092}, {0x6006, 0x0093}, {0x60e3, 0x0093}, {0x6005, 0x0093},
-       {0x6005, 0x0093}, {0x60ed, 0x00c3}, {0x6000, 0x00a4}, {0x60d0, 0x0087},
-       {0x6003, 0x0096}, {0x600c, 0x0097}, {0x6024, 0x0097}, {0x6030, 0x0097},
-       {0x6028, 0x0097}, {0x6026, 0x0097}, {0x6002, 0x0097}, {0x6001, 0x00ff},
-       {0x6043, 0x000f}, {0x608f, 0x0003}, {0x6000, 0x002d}, {0x6000, 0x002e},
-       {0x600a, 0x0022}, {0x6002, 0x0070}, {0x6008, 0x0014}, {0x6048, 0x0014},
-       {0x6000, 0x00ff}, {0x6000, 0x00e0}, {0x60ff, 0x00dd},
-};
-
-static struct validx tbl_post_unset_alt[] = {
-       {0x006a, 0x000d}, {0x6001, 0x00ff}, {0x6081, 0x0026}, {0x6000, 0x0000},
-       {0x6000, 0x0045}, {0x6000, 0x0010}, {0x6068, 0x000d},
-       {50, 0xffff},
-       {0x0021, 0x0000},
-};
-
-static int  ov2640_init_at_startup(struct gspca_dev *gspca_dev);
-static int  ov2640_configure_alt(struct gspca_dev *gspca_dev);
-static int  ov2640_init_pre_alt(struct gspca_dev *gspca_dev);
-static int  ov2640_init_post_alt(struct gspca_dev *gspca_dev);
-static void ov2640_post_unset_alt(struct gspca_dev *gspca_dev);
-static int  ov2640_camera_settings(struct gspca_dev *gspca_dev);
-/*==========================================================================*/
-
-void ov2640_init_settings(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->vcur.backlight  =  32;
-       sd->vcur.brightness =   0;
-       sd->vcur.sharpness  =   6;
-       sd->vcur.contrast   =   0;
-       sd->vcur.gamma      =  32;
-       sd->vcur.hue        =   0;
-       sd->vcur.saturation = 128;
-       sd->vcur.whitebal   =  64;
-       sd->vcur.mirror     =   0;
-       sd->vcur.flip       =   0;
-
-       sd->vmax.backlight  =  64;
-       sd->vmax.brightness = 255;
-       sd->vmax.sharpness  =  31;
-       sd->vmax.contrast   = 255;
-       sd->vmax.gamma      =  64;
-       sd->vmax.hue        = 254 + 2;
-       sd->vmax.saturation = 255;
-       sd->vmax.whitebal   = 128;
-       sd->vmax.mirror     = 1;
-       sd->vmax.flip       = 1;
-       sd->vmax.AC50Hz     = 0;
-
-       sd->dev_camera_settings = ov2640_camera_settings;
-       sd->dev_init_at_startup = ov2640_init_at_startup;
-       sd->dev_configure_alt   = ov2640_configure_alt;
-       sd->dev_init_pre_alt    = ov2640_init_pre_alt;
-       sd->dev_post_unset_alt  = ov2640_post_unset_alt;
-}
-
-/*==========================================================================*/
-
-static void common(struct gspca_dev *gspca_dev)
-{
-       fetch_validx(gspca_dev, tbl_common, ARRAY_SIZE(tbl_common));
-}
-
-static int ov2640_init_at_startup(struct gspca_dev *gspca_dev)
-{
-       fetch_validx(gspca_dev, tbl_init_at_startup,
-                       ARRAY_SIZE(tbl_init_at_startup));
-
-       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_init1);
-
-       common(gspca_dev);
-
-       ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0006, 1, c61);
-
-       ctrl_out(gspca_dev, 0x40, 1, 0x00ef, 0x0006, 0, NULL);
-
-       ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c51);
-
-       ctrl_out(gspca_dev, 0x40, 1, 0x0051, 0x0000, 0, NULL);
-/*     ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL); */
-
-       return 0;
-}
-
-static int ov2640_init_pre_alt(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->mirrorMask = 0;
-
-       sd->vold.backlight  = -1;
-       sd->vold.brightness = -1;
-       sd->vold.sharpness  = -1;
-       sd->vold.contrast   = -1;
-       sd->vold.saturation = -1;
-       sd->vold.gamma    = -1;
-       sd->vold.hue      = -1;
-       sd->vold.whitebal = -1;
-       sd->vold.mirror = -1;
-       sd->vold.flip   = -1;
-
-       ov2640_init_post_alt(gspca_dev);
-
-       return 0;
-}
-
-static int ov2640_init_post_alt(struct gspca_dev *gspca_dev)
-{
-       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
-       s32 n; /* reserved for FETCH functions */
-
-       ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
-
-       n = fetch_validx(gspca_dev, tbl_sensor_settings_common1,
-                       ARRAY_SIZE(tbl_sensor_settings_common1));
-       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_post);
-       common(gspca_dev);
-       keep_on_fetching_validx(gspca_dev, tbl_sensor_settings_common1,
-                               ARRAY_SIZE(tbl_sensor_settings_common1), n);
-
-       switch (reso) {
-       case IMAGE_640:
-               n = fetch_validx(gspca_dev, tbl_640, ARRAY_SIZE(tbl_640));
-               ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_640);
-               break;
-
-       case IMAGE_800:
-               n = fetch_validx(gspca_dev, tbl_800, ARRAY_SIZE(tbl_800));
-               ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 12, dat_800);
-               break;
-
-       case IMAGE_1600:
-       case IMAGE_1280:
-               n = fetch_validx(gspca_dev, tbl_big1, ARRAY_SIZE(tbl_big1));
-
-               if (reso == IMAGE_1280) {
-                       n = fetch_validx(gspca_dev, tbl_big2,
-                                       ARRAY_SIZE(tbl_big2));
-               } else {
-                       ctrl_out(gspca_dev, 0x40, 1, 0x601d, 0x0086, 0, NULL);
-                       ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00d7, 0, NULL);
-                       ctrl_out(gspca_dev, 0x40, 1, 0x6082, 0x00d3, 0, NULL);
-               }
-
-               n = fetch_validx(gspca_dev, tbl_big3, ARRAY_SIZE(tbl_big3));
-
-               if (reso == IMAGE_1280) {
-                       ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL);
-                       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
-                                       12, dat_1280);
-               } else {
-                       ctrl_out(gspca_dev, 0x40, 1, 0x6020, 0x008c, 0, NULL);
-                       ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL);
-                       ctrl_out(gspca_dev, 0x40, 1, 0x6076, 0x0018, 0, NULL);
-                       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
-                                       12, dat_1600);
-               }
-               break;
-       }
-
-       n = fetch_validx(gspca_dev, tbl_sensor_settings_common2,
-                       ARRAY_SIZE(tbl_sensor_settings_common2));
-
-       ov2640_camera_settings(gspca_dev);
-
-       return 0;
-}
-
-static int ov2640_configure_alt(struct gspca_dev *gspca_dev)
-{
-       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
-
-       switch (reso) {
-       case IMAGE_640:
-               gspca_dev->alt = 3 + 1;
-               break;
-
-       case IMAGE_800:
-       case IMAGE_1280:
-       case IMAGE_1600:
-               gspca_dev->alt = 1 + 1;
-               break;
-       }
-       return 0;
-}
-
-static int ov2640_camera_settings(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       s32 backlight = sd->vcur.backlight;
-       s32 bright = sd->vcur.brightness;
-       s32 sharp  = sd->vcur.sharpness;
-       s32 gam    = sd->vcur.gamma;
-       s32 cntr   = sd->vcur.contrast;
-       s32 sat    = sd->vcur.saturation;
-       s32 hue    = sd->vcur.hue;
-       s32 wbal   = sd->vcur.whitebal;
-       s32 mirror = (((sd->vcur.mirror > 0) ^ sd->mirrorMask) == 0);
-       s32 flip   = (((sd->vcur.flip   > 0) ^ sd->mirrorMask) == 0);
-
-       if (backlight != sd->vold.backlight) {
-               /* No sd->vold.backlight=backlight; (to be done again later) */
-               if (backlight < 0 || backlight > sd->vmax.backlight)
-                       backlight = 0;
-
-               ctrl_out(gspca_dev, 0x40, 1, 0x6001                 , 0x00ff,
-                               0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight     , 0x0024,
-                               0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025,
-                               0, NULL);
-       }
-
-       if (bright != sd->vold.brightness) {
-               sd->vold.brightness = bright;
-               if (bright < 0 || bright > sd->vmax.brightness)
-                       bright = 0;
-
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000         , 0x00ff, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6009         , 0x007c, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000 + bright, 0x007d, 0, NULL);
-       }
-
-       if (wbal != sd->vold.whitebal) {
-               sd->vold.whitebal = wbal;
-               if (wbal < 0 || wbal > sd->vmax.whitebal)
-                       wbal = 0;
-
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000       , 0x00ff, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6003       , 0x007c, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000 + wbal, 0x007d, 0, NULL);
-       }
-
-       if (cntr != sd->vold.contrast) {
-               sd->vold.contrast = cntr;
-               if (cntr < 0 || cntr > sd->vmax.contrast)
-                       cntr = 0;
-
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000       , 0x00ff, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6007       , 0x007c, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000 + cntr, 0x007d, 0, NULL);
-       }
-
-       if (sat != sd->vold.saturation) {
-               sd->vold.saturation = sat;
-               if (sat < 0 || sat > sd->vmax.saturation)
-                       sat = 0;
-
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000      , 0x00ff, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6001      , 0x007c, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000 + sat, 0x007d, 0, NULL);
-       }
-
-       if (sharp != sd->vold.sharpness) {
-               sd->vold.sharpness = sharp;
-               if (sharp < 0 || sharp > sd->vmax.sharpness)
-                       sharp = 0;
-
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000        , 0x00ff, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6001        , 0x0092, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x60c0 + sharp, 0x0093, 0, NULL);
-       }
-
-       if (hue != sd->vold.hue) {
-               sd->vold.hue = hue;
-               if (hue < 0 || hue > sd->vmax.hue)
-                       hue = 0;
-
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000     , 0x00ff, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6002     , 0x007c, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000 + hue * (hue < 255), 0x007d,
-                               0, NULL);
-               if (hue >= 255)
-                       sd->swapRB = 1;
-               else
-                       sd->swapRB = 0;
-       }
-
-       if (gam != sd->vold.gamma) {
-               sd->vold.gamma = gam;
-               if (gam < 0 || gam > sd->vmax.gamma)
-                       gam = 0;
-
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000      , 0x00ff, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6008      , 0x007c, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000 + gam, 0x007d, 0, NULL);
-       }
-
-       if (mirror != sd->vold.mirror || flip != sd->vold.flip) {
-               sd->vold.mirror = mirror;
-               sd->vold.flip   = flip;
-
-               mirror = 0x80 * mirror;
-               ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL);
-               ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, c28);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6028 + mirror, 0x0004, 0, NULL);
-
-               flip = 0x50 * flip + mirror;
-               ctrl_out(gspca_dev, 0x40, 1, 0x6001, 0x00ff, 0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x8004, 0, NULL);
-               ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x8004, 1, ca8);
-               ctrl_out(gspca_dev, 0x40, 1, 0x6028 + flip, 0x0004, 0, NULL);
-
-               ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, c50);
-       }
-
-       if (backlight != sd->vold.backlight) {
-               sd->vold.backlight = backlight;
-
-               ctrl_out(gspca_dev, 0x40, 1, 0x6001                 , 0x00ff,
-                               0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight     , 0x0024,
-                               0, NULL);
-               ctrl_out(gspca_dev, 0x40, 1, 0x601e + backlight - 10, 0x0025,
-                               0, NULL);
-       }
-
-       return 0;
-}
-
-static void ov2640_post_unset_alt(struct gspca_dev *gspca_dev)
-{
-       ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
-       msleep(20);
-       fetch_validx(gspca_dev, tbl_post_unset_alt,
-                       ARRAY_SIZE(tbl_post_unset_alt));
-}
diff --git a/drivers/media/video/gspca/gl860/gl860-ov9655.c b/drivers/media/video/gspca/gl860/gl860-ov9655.c
deleted file mode 100644 (file)
index 5ae9619..0000000
+++ /dev/null
@@ -1,336 +0,0 @@
-/* Subdriver for the GL860 chip with the OV9655 sensor
- * Author Olivier LORIN, from logs done by Simon (Sur3) and Almighurt
- * on dsd's weblog
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Sensor : OV9655 */
-
-#include "gl860.h"
-
-static struct validx tbl_init_at_startup[] = {
-       {0x0000, 0x0000}, {0x0010, 0x0010}, {0x0008, 0x00c0}, {0x0001, 0x00c1},
-       {0x0001, 0x00c2}, {0x0020, 0x0006}, {0x006a, 0x000d},
-
-       {0x0040, 0x0000},
-};
-
-static struct validx tbl_commmon[] = {
-       {0x0041, 0x0000}, {0x006a, 0x0007}, {0x0063, 0x0006}, {0x006a, 0x000d},
-       {0x0000, 0x00c0}, {0x0010, 0x0010}, {0x0001, 0x00c1}, {0x0041, 0x00c2},
-       {0x0004, 0x00d8}, {0x0012, 0x0004}, {0x0000, 0x0058}, {0x0040, 0x0000},
-       {0x00f3, 0x0006}, {0x0058, 0x0000}, {0x0048, 0x0000}, {0x0061, 0x0000},
-};
-
-static s32 tbl_length[] = {12, 56, 52, 54, 56, 42, 32, 12};
-
-static u8 *tbl_640[] = {
-       "\x00\x40\x07\x6a\x06\xf3\x0d\x6a" "\x10\x10\xc1\x01"
-       ,
-       "\x12\x80\x00\x00\x01\x98\x02\x80" "\x03\x12\x04\x03\x0b\x57\x0e\x61"
-       "\x0f\x42\x11\x01\x12\x60\x13\x00" "\x14\x3a\x16\x24\x17\x14\x18\x00"
-       "\x19\x01\x1a\x3d\x1e\x04\x24\x3c" "\x25\x36\x26\x72\x27\x08\x28\x08"
-       "\x29\x15\x2a\x00\x2b\x00\x2c\x08"
-       ,
-       "\x32\xff\x33\x00\x34\x3d\x35\x00" "\x36\xfa\x38\x72\x39\x57\x3a\x00"
-       "\x3b\x0c\x3d\x99\x3e\x0c\x3f\xc1" "\x40\xc0\x41\x00\x42\xc0\x43\x0a"
-       "\x44\xf0\x45\x46\x46\x62\x47\x2a" "\x48\x3c\x4a\xee\x4b\xe7\x4c\xe7"
-       "\x4d\xe7\x4e\xe7"
-       ,
-       "\x4f\x98\x50\x98\x51\x00\x52\x28" "\x53\x70\x54\x98\x58\x1a\x59\x85"
-       "\x5a\xa9\x5b\x64\x5c\x84\x5d\x53" "\x5e\x0e\x5f\xf0\x60\xf0\x61\xf0"
-       "\x62\x00\x63\x00\x64\x02\x65\x20" "\x66\x00\x69\x0a\x6b\x5a\x6c\x04"
-       "\x6d\x55\x6e\x00\x6f\x9d"
-       ,
-       "\x70\x15\x71\x78\x72\x00\x73\x00" "\x74\x3a\x75\x35\x76\x01\x77\x02"
-       "\x7a\x24\x7b\x04\x7c\x07\x7d\x10" "\x7e\x28\x7f\x36\x80\x44\x81\x52"
-       "\x82\x60\x83\x6c\x84\x78\x85\x8c" "\x86\x9e\x87\xbb\x88\xd2\x89\xe5"
-       "\x8a\x23\x8c\x8d\x90\x7c\x91\x7b"
-       ,
-       "\x9d\x02\x9e\x02\x9f\x74\xa0\x73" "\xa1\x40\xa4\x50\xa5\x68\xa6\x70"
-       "\xa8\xc1\xa9\xef\xaa\x92\xab\x04" "\xac\x80\xad\x80\xae\x80\xaf\x80"
-       "\xb2\xf2\xb3\x20\xb4\x20\xb5\x00" "\xb6\xaf"
-       ,
-       "\xbb\xae\xbc\x4f\xbd\x4e\xbe\x6a" "\xbf\x68\xc0\xaa\xc1\xc0\xc2\x01"
-       "\xc3\x4e\xc6\x85\xc7\x81\xc9\xe0" "\xca\xe8\xcb\xf0\xcc\xd8\xcd\x93"
-       ,
-       "\xd0\x01\xd1\x08\xd2\xe0\xd3\x01" "\xd4\x10\xd5\x80"
-};
-
-static u8 *tbl_1280[] = {
-       "\x00\x40\x07\x6a\x06\xf3\x0d\x6a" "\x10\x10\xc1\x01"
-       ,
-       "\x12\x80\x00\x00\x01\x98\x02\x80" "\x03\x12\x04\x01\x0b\x57\x0e\x61"
-       "\x0f\x42\x11\x00\x12\x00\x13\x00" "\x14\x3a\x16\x24\x17\x1b\x18\xbb"
-       "\x19\x01\x1a\x81\x1e\x04\x24\x3c" "\x25\x36\x26\x72\x27\x08\x28\x08"
-       "\x29\x15\x2a\x00\x2b\x00\x2c\x08"
-       ,
-       "\x32\xa4\x33\x00\x34\x3d\x35\x00" "\x36\xf8\x38\x72\x39\x57\x3a\x00"
-       "\x3b\x0c\x3d\x99\x3e\x0c\x3f\xc2" "\x40\xc0\x41\x00\x42\xc0\x43\x0a"
-       "\x44\xf0\x45\x46\x46\x62\x47\x2a" "\x48\x3c\x4a\xec\x4b\xe8\x4c\xe8"
-       "\x4d\xe8\x4e\xe8"
-       ,
-       "\x4f\x98\x50\x98\x51\x00\x52\x28" "\x53\x70\x54\x98\x58\x1a\x59\x85"
-       "\x5a\xa9\x5b\x64\x5c\x84\x5d\x53" "\x5e\x0e\x5f\xf0\x60\xf0\x61\xf0"
-       "\x62\x00\x63\x00\x64\x02\x65\x20" "\x66\x00\x69\x02\x6b\x5a\x6c\x04"
-       "\x6d\x55\x6e\x00\x6f\x9d"
-       ,
-       "\x70\x08\x71\x78\x72\x00\x73\x01" "\x74\x3a\x75\x35\x76\x01\x77\x02"
-       "\x7a\x24\x7b\x04\x7c\x07\x7d\x10" "\x7e\x28\x7f\x36\x80\x44\x81\x52"
-       "\x82\x60\x83\x6c\x84\x78\x85\x8c" "\x86\x9e\x87\xbb\x88\xd2\x89\xe5"
-       "\x8a\x23\x8c\x0d\x90\x90\x91\x90"
-       ,
-       "\x9d\x02\x9e\x02\x9f\x94\xa0\x94" "\xa1\x01\xa4\x50\xa5\x68\xa6\x70"
-       "\xa8\xc1\xa9\xef\xaa\x92\xab\x04" "\xac\x80\xad\x80\xae\x80\xaf\x80"
-       "\xb2\xf2\xb3\x20\xb4\x20\xb5\x00" "\xb6\xaf"
-       ,
-       "\xbb\xae\xbc\x38\xbd\x39\xbe\x01" "\xbf\x01\xc0\xe2\xc1\xc0\xc2\x01"
-       "\xc3\x4e\xc6\x85\xc7\x81\xc9\xe0" "\xca\xe8\xcb\xf0\xcc\xd8\xcd\x93"
-       ,
-       "\xd0\x21\xd1\x18\xd2\xe0\xd3\x01" "\xd4\x28\xd5\x00"
-};
-
-static u8 c04[] = {0x04};
-static u8 dat_post1[] = "\x04\x00\x10\x20\xa1\x00\x00\x02";
-static u8 dat_post2[] = "\x10\x10\xc1\x02";
-static u8 dat_post3[] = "\x04\x00\x10\x7c\xa1\x00\x00\x04";
-static u8 dat_post4[] = "\x10\x02\xc1\x06";
-static u8 dat_post5[] = "\x04\x00\x10\x7b\xa1\x00\x00\x08";
-static u8 dat_post6[] = "\x10\x10\xc1\x05";
-static u8 dat_post7[] = "\x04\x00\x10\x7c\xa1\x00\x00\x08";
-static u8 dat_post8[] = "\x04\x00\x10\x7c\xa1\x00\x00\x09";
-
-static struct validx tbl_init_post_alt[] = {
-       {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x603c, 0x00ff},
-       {0x6003, 0x00ff}, {0x6032, 0x00ff}, {0x6032, 0x00ff}, {0x6001, 0x00ff},
-       {0x6000, 0x801e},
-       {0xffff, 0xffff},
-       {0x6004, 0x001e}, {0x6000, 0x801e},
-       {0xffff, 0xffff},
-       {0x6004, 0x001e}, {0x6012, 0x0003}, {0x6000, 0x801e},
-       {0xffff, 0xffff},
-       {0x6004, 0x001e}, {0x6000, 0x801e},
-       {0xffff, 0xffff},
-       {0x6004, 0x001e}, {0x6012, 0x0003},
-       {0xffff, 0xffff},
-       {0x6000, 0x801e},
-       {0xffff, 0xffff},
-       {0x6004, 0x001e}, {0x6000, 0x801e},
-       {0xffff, 0xffff},
-       {0x6004, 0x001e}, {0x6012, 0x0003}, {0x6000, 0x801e},
-       {0xffff, 0xffff},
-       {0x6004, 0x001e}, {0x6000, 0x801e},
-       {0xffff, 0xffff},
-       {0x6004, 0x001e}, {0x6012, 0x0003},
-       {0xffff, 0xffff},
-       {0x6000, 0x801e},
-       {0xffff, 0xffff},
-       {0x6004, 0x001e}, {0x6000, 0x801e},
-       {0xffff, 0xffff},
-       {0x6004, 0x001e}, {0x6012, 0x0003},
-};
-
-static int  ov9655_init_at_startup(struct gspca_dev *gspca_dev);
-static int  ov9655_configure_alt(struct gspca_dev *gspca_dev);
-static int  ov9655_init_pre_alt(struct gspca_dev *gspca_dev);
-static int  ov9655_init_post_alt(struct gspca_dev *gspca_dev);
-static void ov9655_post_unset_alt(struct gspca_dev *gspca_dev);
-static int  ov9655_camera_settings(struct gspca_dev *gspca_dev);
-/*==========================================================================*/
-
-void ov9655_init_settings(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->vcur.backlight  =   0;
-       sd->vcur.brightness = 128;
-       sd->vcur.sharpness  =   0;
-       sd->vcur.contrast   =   0;
-       sd->vcur.gamma      =   0;
-       sd->vcur.hue        =   0;
-       sd->vcur.saturation =   0;
-       sd->vcur.whitebal   =   0;
-
-       sd->vmax.backlight  =   0;
-       sd->vmax.brightness = 255;
-       sd->vmax.sharpness  =   0;
-       sd->vmax.contrast   =   0;
-       sd->vmax.gamma      =   0;
-       sd->vmax.hue        =   0 + 1;
-       sd->vmax.saturation =   0;
-       sd->vmax.whitebal   =   0;
-       sd->vmax.mirror     = 0;
-       sd->vmax.flip       = 0;
-       sd->vmax.AC50Hz     = 0;
-
-       sd->dev_camera_settings = ov9655_camera_settings;
-       sd->dev_init_at_startup = ov9655_init_at_startup;
-       sd->dev_configure_alt   = ov9655_configure_alt;
-       sd->dev_init_pre_alt    = ov9655_init_pre_alt;
-       sd->dev_post_unset_alt  = ov9655_post_unset_alt;
-}
-
-/*==========================================================================*/
-
-static int ov9655_init_at_startup(struct gspca_dev *gspca_dev)
-{
-       fetch_validx(gspca_dev, tbl_init_at_startup,
-                       ARRAY_SIZE(tbl_init_at_startup));
-       fetch_validx(gspca_dev, tbl_commmon, ARRAY_SIZE(tbl_commmon));
-/*     ctrl_out(gspca_dev, 0x40, 11, 0x0000, 0x0000, 0, NULL);*/
-
-       return 0;
-}
-
-static int ov9655_init_pre_alt(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->vold.brightness = -1;
-       sd->vold.hue = -1;
-
-       fetch_validx(gspca_dev, tbl_commmon, ARRAY_SIZE(tbl_commmon));
-
-       ov9655_init_post_alt(gspca_dev);
-
-       return 0;
-}
-
-static int ov9655_init_post_alt(struct gspca_dev *gspca_dev)
-{
-       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
-       s32 n; /* reserved for FETCH functions */
-       s32 i;
-       u8 **tbl;
-
-       ctrl_out(gspca_dev, 0x40, 5, 0x0001, 0x0000, 0, NULL);
-
-       tbl = (reso == IMAGE_640) ? tbl_640 : tbl_1280;
-
-       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
-                       tbl_length[0], tbl[0]);
-       for (i = 1; i < 7; i++)
-               ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200,
-                               tbl_length[i], tbl[i]);
-       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200,
-                       tbl_length[7], tbl[7]);
-
-       n = fetch_validx(gspca_dev, tbl_init_post_alt,
-                       ARRAY_SIZE(tbl_init_post_alt));
-
-       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
-       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
-                                       ARRAY_SIZE(tbl_init_post_alt), n);
-       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
-       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
-                                       ARRAY_SIZE(tbl_init_post_alt), n);
-       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
-       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
-                                       ARRAY_SIZE(tbl_init_post_alt), n);
-       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
-       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
-                                       ARRAY_SIZE(tbl_init_post_alt), n);
-       ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1);
-       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
-                                       ARRAY_SIZE(tbl_init_post_alt), n);
-
-       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
-       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
-                                       ARRAY_SIZE(tbl_init_post_alt), n);
-       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
-       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
-                                       ARRAY_SIZE(tbl_init_post_alt), n);
-       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
-       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
-                                       ARRAY_SIZE(tbl_init_post_alt), n);
-       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
-       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
-                                       ARRAY_SIZE(tbl_init_post_alt), n);
-       ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1);
-       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
-                                       ARRAY_SIZE(tbl_init_post_alt), n);
-
-       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
-       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
-                                       ARRAY_SIZE(tbl_init_post_alt), n);
-       ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x801e, 1, c04);
-       keep_on_fetching_validx(gspca_dev, tbl_init_post_alt,
-                                       ARRAY_SIZE(tbl_init_post_alt), n);
-
-       ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post1);
-
-       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post2);
-       ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post3);
-
-       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post4);
-       ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post5);
-
-       ctrl_out(gspca_dev, 0x40, 3, 0x0000, 0x0200, 4, dat_post6);
-       ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post7);
-
-       ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_post8);
-
-       ov9655_camera_settings(gspca_dev);
-
-       return 0;
-}
-
-static int ov9655_configure_alt(struct gspca_dev *gspca_dev)
-{
-       s32 reso = gspca_dev->cam.cam_mode[(s32) gspca_dev->curr_mode].priv;
-
-       switch (reso) {
-       case IMAGE_640:
-               gspca_dev->alt = 1 + 1;
-               break;
-
-       default:
-               gspca_dev->alt = 1 + 1;
-               break;
-       }
-       return 0;
-}
-
-static int ov9655_camera_settings(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       u8 dat_bright[] = "\x04\x00\x10\x7c\xa1\x00\x00\x70";
-
-       s32 bright = sd->vcur.brightness;
-       s32 hue    = sd->vcur.hue;
-
-       if (bright != sd->vold.brightness) {
-               sd->vold.brightness = bright;
-               if (bright < 0 || bright > sd->vmax.brightness)
-                       bright = 0;
-
-               dat_bright[3] = bright;
-               ctrl_out(gspca_dev, 0x40, 3, 0x6000, 0x0200, 8, dat_bright);
-       }
-
-       if (hue != sd->vold.hue) {
-               sd->vold.hue = hue;
-               sd->swapRB = (hue != 0);
-       }
-
-       return 0;
-}
-
-static void ov9655_post_unset_alt(struct gspca_dev *gspca_dev)
-{
-       ctrl_out(gspca_dev, 0x40, 5, 0x0000, 0x0000, 0, NULL);
-       ctrl_out(gspca_dev, 0x40, 1, 0x0061, 0x0000, 0, NULL);
-}
diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c
deleted file mode 100644 (file)
index ced3b71..0000000
+++ /dev/null
@@ -1,725 +0,0 @@
-/* GSPCA subdrivers for Genesys Logic webcams with the GL860 chip
- * Subdriver core
- *
- * 2009/09/24 Olivier Lorin <o.lorin@laposte.net>
- * GSPCA by Jean-Francois Moine <http://moinejf.free.fr>
- * Thanks BUGabundo and Malmostoso for your amazing help!
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "gspca.h"
-#include "gl860.h"
-
-MODULE_AUTHOR("Olivier Lorin <o.lorin@laposte.net>");
-MODULE_DESCRIPTION("Genesys Logic USB PC Camera Driver");
-MODULE_LICENSE("GPL");
-
-/*======================== static function declarations ====================*/
-
-static void (*dev_init_settings)(struct gspca_dev *gspca_dev);
-
-static int  sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id);
-static int  sd_init(struct gspca_dev *gspca_dev);
-static int  sd_isoc_init(struct gspca_dev *gspca_dev);
-static int  sd_start(struct gspca_dev *gspca_dev);
-static void sd_stop0(struct gspca_dev *gspca_dev);
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data, int len);
-static void sd_callback(struct gspca_dev *gspca_dev);
-
-static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
-                               u16 vendor_id, u16 product_id);
-
-/*============================ driver options ==============================*/
-
-static s32 AC50Hz = 0xff;
-module_param(AC50Hz, int, 0644);
-MODULE_PARM_DESC(AC50Hz, " Does AC power frequency is 50Hz? (0/1)");
-
-static char sensor[7];
-module_param_string(sensor, sensor, sizeof(sensor), 0644);
-MODULE_PARM_DESC(sensor,
-               " Driver sensor ('MI1320'/'MI2020'/'OV9655'/'OV2640')");
-
-/*============================ webcam controls =============================*/
-
-/* Functions to get and set a control value */
-#define SD_SETGET(thename) \
-static int sd_set_##thename(struct gspca_dev *gspca_dev, s32 val)\
-{\
-       struct sd *sd = (struct sd *) gspca_dev;\
-\
-       sd->vcur.thename = val;\
-       if (gspca_dev->streaming)\
-               sd->waitSet = 1;\
-       return 0;\
-} \
-static int sd_get_##thename(struct gspca_dev *gspca_dev, s32 *val)\
-{\
-       struct sd *sd = (struct sd *) gspca_dev;\
-\
-       *val = sd->vcur.thename;\
-       return 0;\
-}
-
-SD_SETGET(mirror)
-SD_SETGET(flip)
-SD_SETGET(AC50Hz)
-SD_SETGET(backlight)
-SD_SETGET(brightness)
-SD_SETGET(gamma)
-SD_SETGET(hue)
-SD_SETGET(saturation)
-SD_SETGET(sharpness)
-SD_SETGET(whitebal)
-SD_SETGET(contrast)
-
-#define GL860_NCTRLS 11
-
-/* control table */
-static struct ctrl sd_ctrls_mi1320[GL860_NCTRLS];
-static struct ctrl sd_ctrls_mi2020[GL860_NCTRLS];
-static struct ctrl sd_ctrls_ov2640[GL860_NCTRLS];
-static struct ctrl sd_ctrls_ov9655[GL860_NCTRLS];
-
-#define SET_MY_CTRL(theid, \
-       thetype, thelabel, thename) \
-       if (sd->vmax.thename != 0) {\
-               sd_ctrls[nCtrls].qctrl.id   = theid;\
-               sd_ctrls[nCtrls].qctrl.type = thetype;\
-               strcpy(sd_ctrls[nCtrls].qctrl.name, thelabel);\
-               sd_ctrls[nCtrls].qctrl.minimum = 0;\
-               sd_ctrls[nCtrls].qctrl.maximum = sd->vmax.thename;\
-               sd_ctrls[nCtrls].qctrl.default_value = sd->vcur.thename;\
-               sd_ctrls[nCtrls].qctrl.step = \
-                       (sd->vmax.thename < 16) ? 1 : sd->vmax.thename/16;\
-               sd_ctrls[nCtrls].set = sd_set_##thename;\
-               sd_ctrls[nCtrls].get = sd_get_##thename;\
-               nCtrls++;\
-       }
-
-static int gl860_build_control_table(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct ctrl *sd_ctrls;
-       int nCtrls = 0;
-
-       if (_MI1320_)
-               sd_ctrls = sd_ctrls_mi1320;
-       else if (_MI2020_)
-               sd_ctrls = sd_ctrls_mi2020;
-       else if (_OV2640_)
-               sd_ctrls = sd_ctrls_ov2640;
-       else if (_OV9655_)
-               sd_ctrls = sd_ctrls_ov9655;
-       else
-               return 0;
-
-       memset(sd_ctrls, 0, GL860_NCTRLS * sizeof(struct ctrl));
-
-       SET_MY_CTRL(V4L2_CID_BRIGHTNESS,
-               V4L2_CTRL_TYPE_INTEGER, "Brightness", brightness)
-       SET_MY_CTRL(V4L2_CID_SHARPNESS,
-               V4L2_CTRL_TYPE_INTEGER, "Sharpness", sharpness)
-       SET_MY_CTRL(V4L2_CID_CONTRAST,
-               V4L2_CTRL_TYPE_INTEGER, "Contrast", contrast)
-       SET_MY_CTRL(V4L2_CID_GAMMA,
-               V4L2_CTRL_TYPE_INTEGER, "Gamma", gamma)
-       SET_MY_CTRL(V4L2_CID_HUE,
-               V4L2_CTRL_TYPE_INTEGER, "Palette", hue)
-       SET_MY_CTRL(V4L2_CID_SATURATION,
-               V4L2_CTRL_TYPE_INTEGER, "Saturation", saturation)
-       SET_MY_CTRL(V4L2_CID_WHITE_BALANCE_TEMPERATURE,
-               V4L2_CTRL_TYPE_INTEGER, "White Bal.", whitebal)
-       SET_MY_CTRL(V4L2_CID_BACKLIGHT_COMPENSATION,
-               V4L2_CTRL_TYPE_INTEGER, "Backlight" , backlight)
-
-       SET_MY_CTRL(V4L2_CID_HFLIP,
-               V4L2_CTRL_TYPE_BOOLEAN, "Mirror", mirror)
-       SET_MY_CTRL(V4L2_CID_VFLIP,
-               V4L2_CTRL_TYPE_BOOLEAN, "Flip", flip)
-       SET_MY_CTRL(V4L2_CID_POWER_LINE_FREQUENCY,
-               V4L2_CTRL_TYPE_BOOLEAN, "AC power 50Hz", AC50Hz)
-
-       return nCtrls;
-}
-
-/*==================== sud-driver structure initialisation =================*/
-
-static const struct sd_desc sd_desc_mi1320 = {
-       .name        = MODULE_NAME,
-       .ctrls       = sd_ctrls_mi1320,
-       .nctrls      = GL860_NCTRLS,
-       .config      = sd_config,
-       .init        = sd_init,
-       .isoc_init   = sd_isoc_init,
-       .start       = sd_start,
-       .stop0       = sd_stop0,
-       .pkt_scan    = sd_pkt_scan,
-       .dq_callback = sd_callback,
-};
-
-static const struct sd_desc sd_desc_mi2020 = {
-       .name        = MODULE_NAME,
-       .ctrls       = sd_ctrls_mi2020,
-       .nctrls      = GL860_NCTRLS,
-       .config      = sd_config,
-       .init        = sd_init,
-       .isoc_init   = sd_isoc_init,
-       .start       = sd_start,
-       .stop0       = sd_stop0,
-       .pkt_scan    = sd_pkt_scan,
-       .dq_callback = sd_callback,
-};
-
-static const struct sd_desc sd_desc_ov2640 = {
-       .name        = MODULE_NAME,
-       .ctrls       = sd_ctrls_ov2640,
-       .nctrls      = GL860_NCTRLS,
-       .config      = sd_config,
-       .init        = sd_init,
-       .isoc_init   = sd_isoc_init,
-       .start       = sd_start,
-       .stop0       = sd_stop0,
-       .pkt_scan    = sd_pkt_scan,
-       .dq_callback = sd_callback,
-};
-
-static const struct sd_desc sd_desc_ov9655 = {
-       .name        = MODULE_NAME,
-       .ctrls       = sd_ctrls_ov9655,
-       .nctrls      = GL860_NCTRLS,
-       .config      = sd_config,
-       .init        = sd_init,
-       .isoc_init   = sd_isoc_init,
-       .start       = sd_start,
-       .stop0       = sd_stop0,
-       .pkt_scan    = sd_pkt_scan,
-       .dq_callback = sd_callback,
-};
-
-/*=========================== sub-driver image sizes =======================*/
-
-static struct v4l2_pix_format mi2020_mode[] = {
-       { 640,  480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0
-       },
-       { 800,  598, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 800,
-               .sizeimage = 800 * 598,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1
-       },
-       {1280, 1024, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 1280,
-               .sizeimage = 1280 * 1024,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2
-       },
-       {1600, 1198, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 1600,
-               .sizeimage = 1600 * 1198,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 3
-       },
-};
-
-static struct v4l2_pix_format ov2640_mode[] = {
-       { 640,  480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0
-       },
-       { 800,  600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 800,
-               .sizeimage = 800 * 600,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1
-       },
-       {1280,  960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 1280,
-               .sizeimage = 1280 * 960,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2
-       },
-       {1600, 1200, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 1600,
-               .sizeimage = 1600 * 1200,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 3
-       },
-};
-
-static struct v4l2_pix_format mi1320_mode[] = {
-       { 640,  480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0
-       },
-       { 800,  600, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 800,
-               .sizeimage = 800 * 600,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1
-       },
-       {1280,  960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 1280,
-               .sizeimage = 1280 * 960,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2
-       },
-};
-
-static struct v4l2_pix_format ov9655_mode[] = {
-       { 640,  480, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0
-       },
-       {1280,  960, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 1280,
-               .sizeimage = 1280 * 960,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1
-       },
-};
-
-/*========================= sud-driver functions ===========================*/
-
-/* This function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-       u16 vendor_id, product_id;
-
-       /* Get USB VendorID and ProductID */
-       vendor_id  = id->idVendor;
-       product_id = id->idProduct;
-
-       sd->nbRightUp = 1;
-       sd->nbIm = -1;
-
-       sd->sensor = 0xff;
-       if (strcmp(sensor, "MI1320") == 0)
-               sd->sensor = ID_MI1320;
-       else if (strcmp(sensor, "OV2640") == 0)
-               sd->sensor = ID_OV2640;
-       else if (strcmp(sensor, "OV9655") == 0)
-               sd->sensor = ID_OV9655;
-       else if (strcmp(sensor, "MI2020") == 0)
-               sd->sensor = ID_MI2020;
-
-       /* Get sensor and set the suitable init/start/../stop functions */
-       if (gl860_guess_sensor(gspca_dev, vendor_id, product_id) == -1)
-               return -1;
-
-       cam = &gspca_dev->cam;
-
-       switch (sd->sensor) {
-       case ID_MI1320:
-               gspca_dev->sd_desc = &sd_desc_mi1320;
-               cam->cam_mode = mi1320_mode;
-               cam->nmodes = ARRAY_SIZE(mi1320_mode);
-               dev_init_settings   = mi1320_init_settings;
-               break;
-
-       case ID_MI2020:
-               gspca_dev->sd_desc = &sd_desc_mi2020;
-               cam->cam_mode = mi2020_mode;
-               cam->nmodes = ARRAY_SIZE(mi2020_mode);
-               dev_init_settings   = mi2020_init_settings;
-               break;
-
-       case ID_OV2640:
-               gspca_dev->sd_desc = &sd_desc_ov2640;
-               cam->cam_mode = ov2640_mode;
-               cam->nmodes = ARRAY_SIZE(ov2640_mode);
-               dev_init_settings   = ov2640_init_settings;
-               break;
-
-       case ID_OV9655:
-               gspca_dev->sd_desc = &sd_desc_ov9655;
-               cam->cam_mode = ov9655_mode;
-               cam->nmodes = ARRAY_SIZE(ov9655_mode);
-               dev_init_settings   = ov9655_init_settings;
-               break;
-       }
-
-       dev_init_settings(gspca_dev);
-       if (AC50Hz != 0xff)
-               ((struct sd *) gspca_dev)->vcur.AC50Hz = AC50Hz;
-       gl860_build_control_table(gspca_dev);
-
-       return 0;
-}
-
-/* This function is called at probe time after sd_config */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       return sd->dev_init_at_startup(gspca_dev);
-}
-
-/* This function is called before to choose the alt setting */
-static int sd_isoc_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       return sd->dev_configure_alt(gspca_dev);
-}
-
-/* This function is called to start the webcam */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       return sd->dev_init_pre_alt(gspca_dev);
-}
-
-/* This function is called to stop the webcam */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (!sd->gspca_dev.present)
-               return;
-
-       return sd->dev_post_unset_alt(gspca_dev);
-}
-
-/* This function is called when an image is being received */
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data, int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       static s32 nSkipped;
-
-       s32 mode = (s32) gspca_dev->curr_mode;
-       s32 nToSkip =
-               sd->swapRB * (gspca_dev->cam.cam_mode[mode].bytesperline + 1);
-
-       /* Test only against 0202h, so endianess does not matter */
-       switch (*(s16 *) data) {
-       case 0x0202:            /* End of frame, start a new one */
-               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-               nSkipped = 0;
-               if (sd->nbIm >= 0 && sd->nbIm < 10)
-                       sd->nbIm++;
-               gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
-               break;
-
-       default:
-               data += 2;
-               len  -= 2;
-               if (nSkipped + len <= nToSkip)
-                       nSkipped += len;
-               else {
-                       if (nSkipped < nToSkip && nSkipped + len > nToSkip) {
-                               data += nToSkip - nSkipped;
-                               len  -= nToSkip - nSkipped;
-                               nSkipped = nToSkip + 1;
-                       }
-                       gspca_frame_add(gspca_dev,
-                               INTER_PACKET, data, len);
-               }
-               break;
-       }
-}
-
-/* This function is called when an image has been read */
-/* This function is used to monitor webcam orientation */
-static void sd_callback(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (!_OV9655_) {
-               u8 state;
-               u8 upsideDown;
-
-               /* Probe sensor orientation */
-               ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0000, 1, (void *)&state);
-
-               /* C8/40 means upside-down (looking backwards) */
-               /* D8/50 means right-up (looking onwards) */
-               upsideDown = (state == 0xc8 || state == 0x40);
-
-               if (upsideDown && sd->nbRightUp > -4) {
-                       if (sd->nbRightUp > 0)
-                               sd->nbRightUp = 0;
-                       if (sd->nbRightUp == -3) {
-                               sd->mirrorMask = 1;
-                               sd->waitSet = 1;
-                       }
-                       sd->nbRightUp--;
-               }
-               if (!upsideDown && sd->nbRightUp < 4) {
-                       if (sd->nbRightUp  < 0)
-                               sd->nbRightUp = 0;
-                       if (sd->nbRightUp == 3) {
-                               sd->mirrorMask = 0;
-                               sd->waitSet = 1;
-                       }
-                       sd->nbRightUp++;
-               }
-       }
-
-       if (sd->waitSet)
-               sd->dev_camera_settings(gspca_dev);
-}
-
-/*=================== USB driver structure initialisation ==================*/
-
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x05e3, 0x0503)},
-       {USB_DEVICE(0x05e3, 0xf191)},
-       {}
-};
-
-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_mi1320, sizeof(struct sd), THIS_MODULE);
-}
-
-static void sd_disconnect(struct usb_interface *intf)
-{
-       gspca_disconnect(intf);
-}
-
-static struct usb_driver sd_driver = {
-       .name       = MODULE_NAME,
-       .id_table   = device_table,
-       .probe      = sd_probe,
-       .disconnect = sd_disconnect,
-#ifdef CONFIG_PM
-       .suspend    = gspca_suspend,
-       .resume     = gspca_resume,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-/*====================== Init and Exit module functions ====================*/
-
-module_usb_driver(sd_driver);
-
-/*==========================================================================*/
-
-int gl860_RTx(struct gspca_dev *gspca_dev,
-               unsigned char pref, u32 req, u16 val, u16 index,
-               s32 len, void *pdata)
-{
-       struct usb_device *udev = gspca_dev->dev;
-       s32 r = 0;
-
-       if (pref == 0x40) { /* Send */
-               if (len > 0) {
-                       memcpy(gspca_dev->usb_buf, pdata, len);
-                       r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                       req, pref, val, index,
-                                       gspca_dev->usb_buf,
-                                       len, 400 + 200 * (len > 1));
-               } else {
-                       r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                       req, pref, val, index, NULL, len, 400);
-               }
-       } else { /* Receive */
-               if (len > 0) {
-                       r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-                                       req, pref, val, index,
-                                       gspca_dev->usb_buf,
-                                       len, 400 + 200 * (len > 1));
-                       memcpy(pdata, gspca_dev->usb_buf, len);
-               } else {
-                       r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-                                       req, pref, val, index, NULL, len, 400);
-               }
-       }
-
-       if (r < 0)
-               pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n",
-                      r, pref, req, val, index, len);
-       else if (len > 1 && r < len)
-               PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len);
-
-       msleep(1);
-
-       return r;
-}
-
-int fetch_validx(struct gspca_dev *gspca_dev, struct validx *tbl, int len)
-{
-       int n;
-
-       for (n = 0; n < len; n++) {
-               if (tbl[n].idx != 0xffff)
-                       ctrl_out(gspca_dev, 0x40, 1, tbl[n].val,
-                                       tbl[n].idx, 0, NULL);
-               else if (tbl[n].val == 0xffff)
-                       break;
-               else
-                       msleep(tbl[n].val);
-       }
-       return n;
-}
-
-int keep_on_fetching_validx(struct gspca_dev *gspca_dev, struct validx *tbl,
-                               int len, int n)
-{
-       while (++n < len) {
-               if (tbl[n].idx != 0xffff)
-                       ctrl_out(gspca_dev, 0x40, 1, tbl[n].val, tbl[n].idx,
-                                       0, NULL);
-               else if (tbl[n].val == 0xffff)
-                       break;
-               else
-                       msleep(tbl[n].val);
-       }
-       return n;
-}
-
-void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len)
-{
-       int n;
-
-       for (n = 0; n < len; n++) {
-               if (memcmp(tbl[n].data, "\xff\xff\xff", 3) != 0)
-                       ctrl_out(gspca_dev, 0x40, 3, 0x7a00, tbl[n].idx,
-                                       3, tbl[n].data);
-               else
-                       msleep(tbl[n].idx);
-       }
-}
-
-static int gl860_guess_sensor(struct gspca_dev *gspca_dev,
-                               u16 vendor_id, u16 product_id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 probe, nb26, nb96, nOV, ntry;
-
-       if (product_id == 0xf191)
-               sd->sensor = ID_MI1320;
-
-       if (sd->sensor == 0xff) {
-               ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);
-               ctrl_in(gspca_dev, 0xc0, 2, 0x0000, 0x0004, 1, &probe);
-
-               ctrl_out(gspca_dev, 0x40, 1, 0x0000, 0x0000, 0, NULL);
-               msleep(3);
-               ctrl_out(gspca_dev, 0x40, 1, 0x0010, 0x0010, 0, NULL);
-               msleep(3);
-               ctrl_out(gspca_dev, 0x40, 1, 0x0008, 0x00c0, 0, NULL);
-               msleep(3);
-               ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c1, 0, NULL);
-               msleep(3);
-               ctrl_out(gspca_dev, 0x40, 1, 0x0001, 0x00c2, 0, NULL);
-               msleep(3);
-               ctrl_out(gspca_dev, 0x40, 1, 0x0020, 0x0006, 0, NULL);
-               msleep(3);
-               ctrl_out(gspca_dev, 0x40, 1, 0x006a, 0x000d, 0, NULL);
-               msleep(56);
-
-               PDEBUG(D_PROBE, "probing for sensor MI2020 or OVXXXX");
-               nOV = 0;
-               for (ntry = 0; ntry < 4; ntry++) {
-                       ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000, 0, NULL);
-                       msleep(3);
-                       ctrl_out(gspca_dev, 0x40, 1, 0x0063, 0x0006, 0, NULL);
-                       msleep(3);
-                       ctrl_out(gspca_dev, 0x40, 1, 0x7a00, 0x8030, 0, NULL);
-                       msleep(10);
-                       ctrl_in(gspca_dev, 0xc0, 2, 0x7a00, 0x8030, 1, &probe);
-                       PDEBUG(D_PROBE, "probe=0x%02x", probe);
-                       if (probe == 0xff)
-                               nOV++;
-               }
-
-               if (nOV) {
-                       PDEBUG(D_PROBE, "0xff -> OVXXXX");
-                       PDEBUG(D_PROBE, "probing for sensor OV2640 or OV9655");
-
-                       nb26 = nb96 = 0;
-                       for (ntry = 0; ntry < 4; ntry++) {
-                               ctrl_out(gspca_dev, 0x40, 1, 0x0040, 0x0000,
-                                               0, NULL);
-                               msleep(3);
-                               ctrl_out(gspca_dev, 0x40, 1, 0x6000, 0x800a,
-                                               0, NULL);
-                               msleep(10);
-
-                               /* Wait for 26(OV2640) or 96(OV9655) */
-                               ctrl_in(gspca_dev, 0xc0, 2, 0x6000, 0x800a,
-                                               1, &probe);
-
-                               if (probe == 0x26 || probe == 0x40) {
-                                       PDEBUG(D_PROBE,
-                                               "probe=0x%02x -> OV2640",
-                                               probe);
-                                       sd->sensor = ID_OV2640;
-                                       nb26 += 4;
-                                       break;
-                               }
-                               if (probe == 0x96 || probe == 0x55) {
-                                       PDEBUG(D_PROBE,
-                                               "probe=0x%02x -> OV9655",
-                                               probe);
-                                       sd->sensor = ID_OV9655;
-                                       nb96 += 4;
-                                       break;
-                               }
-                               PDEBUG(D_PROBE, "probe=0x%02x", probe);
-                               if (probe == 0x00)
-                                       nb26++;
-                               if (probe == 0xff)
-                                       nb96++;
-                               msleep(3);
-                       }
-                       if (nb26 < 4 && nb96 < 4)
-                               return -1;
-               } else {
-                       PDEBUG(D_PROBE, "Not any 0xff -> MI2020");
-                       sd->sensor = ID_MI2020;
-               }
-       }
-
-       if (_MI1320_) {
-               PDEBUG(D_PROBE, "05e3:f191 sensor MI1320 (1.3M)");
-       } else if (_MI2020_) {
-               PDEBUG(D_PROBE, "05e3:0503 sensor MI2020 (2.0M)");
-       } else if (_OV9655_) {
-               PDEBUG(D_PROBE, "05e3:0503 sensor OV9655 (1.3M)");
-       } else if (_OV2640_) {
-               PDEBUG(D_PROBE, "05e3:0503 sensor OV2640 (2.0M)");
-       } else {
-               PDEBUG(D_PROBE, "***** Unknown sensor *****");
-               return -1;
-       }
-
-       return 0;
-}
diff --git a/drivers/media/video/gspca/gl860/gl860.h b/drivers/media/video/gspca/gl860/gl860.h
deleted file mode 100644 (file)
index 0330a02..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/* GSPCA subdrivers for Genesys Logic webcams with the GL860 chip
- * Subdriver declarations
- *
- * 2009/10/14 Olivier LORIN <o.lorin@laposte.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * 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, see <http://www.gnu.org/licenses/>.
- */
-#ifndef GL860_DEV_H
-#define GL860_DEV_H
-
-#include "gspca.h"
-
-#define MODULE_NAME "gspca_gl860"
-#define DRIVER_VERSION "0.9d10"
-
-#define ctrl_in  gl860_RTx
-#define ctrl_out gl860_RTx
-
-#define ID_MI1320   1
-#define ID_OV2640   2
-#define ID_OV9655   4
-#define ID_MI2020   8
-
-#define _MI1320_  (((struct sd *) gspca_dev)->sensor == ID_MI1320)
-#define _MI2020_  (((struct sd *) gspca_dev)->sensor == ID_MI2020)
-#define _OV2640_  (((struct sd *) gspca_dev)->sensor == ID_OV2640)
-#define _OV9655_  (((struct sd *) gspca_dev)->sensor == ID_OV9655)
-
-#define IMAGE_640   0
-#define IMAGE_800   1
-#define IMAGE_1280  2
-#define IMAGE_1600  3
-
-struct sd_gl860 {
-       u16 backlight;
-       u16 brightness;
-       u16 sharpness;
-       u16 contrast;
-       u16 gamma;
-       u16 hue;
-       u16 saturation;
-       u16 whitebal;
-       u8  mirror;
-       u8  flip;
-       u8  AC50Hz;
-};
-
-/* Specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       struct sd_gl860 vcur;
-       struct sd_gl860 vold;
-       struct sd_gl860 vmax;
-
-       int  (*dev_configure_alt)  (struct gspca_dev *);
-       int  (*dev_init_at_startup)(struct gspca_dev *);
-       int  (*dev_init_pre_alt)   (struct gspca_dev *);
-       void (*dev_post_unset_alt) (struct gspca_dev *);
-       int  (*dev_camera_settings)(struct gspca_dev *);
-
-       u8   swapRB;
-       u8   mirrorMask;
-       u8   sensor;
-       s32  nbIm;
-       s32  nbRightUp;
-       u8   waitSet;
-};
-
-struct validx {
-       u16 val;
-       u16 idx;
-};
-
-struct idxdata {
-       u8 idx;
-       u8 data[3];
-};
-
-int fetch_validx(struct gspca_dev *gspca_dev, struct validx *tbl, int len);
-int keep_on_fetching_validx(struct gspca_dev *gspca_dev, struct validx *tbl,
-                               int len, int n);
-void fetch_idxdata(struct gspca_dev *gspca_dev, struct idxdata *tbl, int len);
-
-int gl860_RTx(struct gspca_dev *gspca_dev,
-                       unsigned char pref, u32 req, u16 val, u16 index,
-                       s32 len, void *pdata);
-
-void mi1320_init_settings(struct gspca_dev *);
-void ov2640_init_settings(struct gspca_dev *);
-void ov9655_init_settings(struct gspca_dev *);
-void mi2020_init_settings(struct gspca_dev *);
-
-#endif
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
deleted file mode 100644 (file)
index d4e8343..0000000
+++ /dev/null
@@ -1,2456 +0,0 @@
-/*
- * Main USB camera driver
- *
- * Copyright (C) 2008-2011 Jean-François Moine <http://moinejf.free.fr>
- *
- * Camera button input handling by Márton Németh
- * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
- *
- * 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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define GSPCA_VERSION  "2.14.0"
-
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/vmalloc.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pagemap.h>
-#include <linux/io.h>
-#include <asm/page.h>
-#include <linux/uaccess.h>
-#include <linux/ktime.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-event.h>
-
-#include "gspca.h"
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-#include <linux/input.h>
-#include <linux/usb/input.h>
-#endif
-
-/* global values */
-#define DEF_NURBS 3            /* default number of URBs */
-#if DEF_NURBS > MAX_NURBS
-#error "DEF_NURBS too big"
-#endif
-
-MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
-MODULE_DESCRIPTION("GSPCA USB Camera Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(GSPCA_VERSION);
-
-#ifdef GSPCA_DEBUG
-int gspca_debug = D_ERR | D_PROBE;
-EXPORT_SYMBOL(gspca_debug);
-
-static void PDEBUG_MODE(char *txt, __u32 pixfmt, int w, int h)
-{
-       if ((pixfmt >> 24) >= '0' && (pixfmt >> 24) <= 'z') {
-               PDEBUG(D_CONF|D_STREAM, "%s %c%c%c%c %dx%d",
-                       txt,
-                       pixfmt & 0xff,
-                       (pixfmt >> 8) & 0xff,
-                       (pixfmt >> 16) & 0xff,
-                       pixfmt >> 24,
-                       w, h);
-       } else {
-               PDEBUG(D_CONF|D_STREAM, "%s 0x%08x %dx%d",
-                       txt,
-                       pixfmt,
-                       w, h);
-       }
-}
-#else
-#define PDEBUG_MODE(txt, pixfmt, w, h)
-#endif
-
-/* specific memory types - !! should be different from V4L2_MEMORY_xxx */
-#define GSPCA_MEMORY_NO 0      /* V4L2_MEMORY_xxx starts from 1 */
-#define GSPCA_MEMORY_READ 7
-
-#define BUF_ALL_FLAGS (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)
-
-/*
- * VMA operations.
- */
-static void gspca_vm_open(struct vm_area_struct *vma)
-{
-       struct gspca_frame *frame = vma->vm_private_data;
-
-       frame->vma_use_count++;
-       frame->v4l2_buf.flags |= V4L2_BUF_FLAG_MAPPED;
-}
-
-static void gspca_vm_close(struct vm_area_struct *vma)
-{
-       struct gspca_frame *frame = vma->vm_private_data;
-
-       if (--frame->vma_use_count <= 0)
-               frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_MAPPED;
-}
-
-static const struct vm_operations_struct gspca_vm_ops = {
-       .open           = gspca_vm_open,
-       .close          = gspca_vm_close,
-};
-
-/*
- * Input and interrupt endpoint handling functions
- */
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-static void int_irq(struct urb *urb)
-{
-       struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
-       int ret;
-
-       ret = urb->status;
-       switch (ret) {
-       case 0:
-               if (gspca_dev->sd_desc->int_pkt_scan(gspca_dev,
-                   urb->transfer_buffer, urb->actual_length) < 0) {
-                       PDEBUG(D_ERR, "Unknown packet received");
-               }
-               break;
-
-       case -ENOENT:
-       case -ECONNRESET:
-       case -ENODEV:
-       case -ESHUTDOWN:
-               /* Stop is requested either by software or hardware is gone,
-                * keep the ret value non-zero and don't resubmit later.
-                */
-               break;
-
-       default:
-               PDEBUG(D_ERR, "URB error %i, resubmitting", urb->status);
-               urb->status = 0;
-               ret = 0;
-       }
-
-       if (ret == 0) {
-               ret = usb_submit_urb(urb, GFP_ATOMIC);
-               if (ret < 0)
-                       pr_err("Resubmit URB failed with error %i\n", ret);
-       }
-}
-
-static int gspca_input_connect(struct gspca_dev *dev)
-{
-       struct input_dev *input_dev;
-       int err = 0;
-
-       dev->input_dev = NULL;
-       if (dev->sd_desc->int_pkt_scan || dev->sd_desc->other_input)  {
-               input_dev = input_allocate_device();
-               if (!input_dev)
-                       return -ENOMEM;
-
-               usb_make_path(dev->dev, dev->phys, sizeof(dev->phys));
-               strlcat(dev->phys, "/input0", sizeof(dev->phys));
-
-               input_dev->name = dev->sd_desc->name;
-               input_dev->phys = dev->phys;
-
-               usb_to_input_id(dev->dev, &input_dev->id);
-
-               input_dev->evbit[0] = BIT_MASK(EV_KEY);
-               input_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
-               input_dev->dev.parent = &dev->dev->dev;
-
-               err = input_register_device(input_dev);
-               if (err) {
-                       pr_err("Input device registration failed with error %i\n",
-                              err);
-                       input_dev->dev.parent = NULL;
-                       input_free_device(input_dev);
-               } else {
-                       dev->input_dev = input_dev;
-               }
-       }
-
-       return err;
-}
-
-static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
-                         struct usb_endpoint_descriptor *ep)
-{
-       unsigned int buffer_len;
-       int interval;
-       struct urb *urb;
-       struct usb_device *dev;
-       void *buffer = NULL;
-       int ret = -EINVAL;
-
-       buffer_len = le16_to_cpu(ep->wMaxPacketSize);
-       interval = ep->bInterval;
-       PDEBUG(D_CONF, "found int in endpoint: 0x%x, "
-               "buffer_len=%u, interval=%u",
-               ep->bEndpointAddress, buffer_len, interval);
-
-       dev = gspca_dev->dev;
-
-       urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!urb) {
-               ret = -ENOMEM;
-               goto error;
-       }
-
-       buffer = usb_alloc_coherent(dev, buffer_len,
-                               GFP_KERNEL, &urb->transfer_dma);
-       if (!buffer) {
-               ret = -ENOMEM;
-               goto error_buffer;
-       }
-       usb_fill_int_urb(urb, dev,
-               usb_rcvintpipe(dev, ep->bEndpointAddress),
-               buffer, buffer_len,
-               int_irq, (void *)gspca_dev, interval);
-       urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-       ret = usb_submit_urb(urb, GFP_KERNEL);
-       if (ret < 0) {
-               PDEBUG(D_ERR, "submit int URB failed with error %i", ret);
-               goto error_submit;
-       }
-       gspca_dev->int_urb = urb;
-       return ret;
-
-error_submit:
-       usb_free_coherent(dev,
-                         urb->transfer_buffer_length,
-                         urb->transfer_buffer,
-                         urb->transfer_dma);
-error_buffer:
-       usb_free_urb(urb);
-error:
-       return ret;
-}
-
-static void gspca_input_create_urb(struct gspca_dev *gspca_dev)
-{
-       struct usb_interface *intf;
-       struct usb_host_interface *intf_desc;
-       struct usb_endpoint_descriptor *ep;
-       int i;
-
-       if (gspca_dev->sd_desc->int_pkt_scan)  {
-               intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
-               intf_desc = intf->cur_altsetting;
-               for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
-                       ep = &intf_desc->endpoint[i].desc;
-                       if (usb_endpoint_dir_in(ep) &&
-                           usb_endpoint_xfer_int(ep)) {
-
-                               alloc_and_submit_int_urb(gspca_dev, ep);
-                               break;
-                       }
-               }
-       }
-}
-
-static void gspca_input_destroy_urb(struct gspca_dev *gspca_dev)
-{
-       struct urb *urb;
-
-       urb = gspca_dev->int_urb;
-       if (urb) {
-               gspca_dev->int_urb = NULL;
-               usb_kill_urb(urb);
-               usb_free_coherent(gspca_dev->dev,
-                                 urb->transfer_buffer_length,
-                                 urb->transfer_buffer,
-                                 urb->transfer_dma);
-               usb_free_urb(urb);
-       }
-}
-#else
-static inline void gspca_input_destroy_urb(struct gspca_dev *gspca_dev)
-{
-}
-
-static inline void gspca_input_create_urb(struct gspca_dev *gspca_dev)
-{
-}
-
-static inline int gspca_input_connect(struct gspca_dev *dev)
-{
-       return 0;
-}
-#endif
-
-/*
- * fill a video frame from an URB and resubmit
- */
-static void fill_frame(struct gspca_dev *gspca_dev,
-                       struct urb *urb)
-{
-       u8 *data;               /* address of data in the iso message */
-       int i, len, st;
-       cam_pkt_op pkt_scan;
-
-       if (urb->status != 0) {
-               if (urb->status == -ESHUTDOWN)
-                       return;         /* disconnection */
-#ifdef CONFIG_PM
-               if (gspca_dev->frozen)
-                       return;
-#endif
-               PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
-               urb->status = 0;
-               goto resubmit;
-       }
-       pkt_scan = gspca_dev->sd_desc->pkt_scan;
-       for (i = 0; i < urb->number_of_packets; i++) {
-               len = urb->iso_frame_desc[i].actual_length;
-
-               /* check the packet status and length */
-               st = urb->iso_frame_desc[i].status;
-               if (st) {
-                       pr_err("ISOC data error: [%d] len=%d, status=%d\n",
-                              i, len, st);
-                       gspca_dev->last_packet_type = DISCARD_PACKET;
-                       continue;
-               }
-               if (len == 0) {
-                       if (gspca_dev->empty_packet == 0)
-                               gspca_dev->empty_packet = 1;
-                       continue;
-               }
-
-               /* let the packet be analyzed by the subdriver */
-               PDEBUG(D_PACK, "packet [%d] o:%d l:%d",
-                       i, urb->iso_frame_desc[i].offset, len);
-               data = (u8 *) urb->transfer_buffer
-                                       + urb->iso_frame_desc[i].offset;
-               pkt_scan(gspca_dev, data, len);
-       }
-
-resubmit:
-       /* resubmit the URB */
-       st = usb_submit_urb(urb, GFP_ATOMIC);
-       if (st < 0)
-               pr_err("usb_submit_urb() ret %d\n", st);
-}
-
-/*
- * ISOC message interrupt from the USB device
- *
- * Analyse each packet and call the subdriver for copy to the frame buffer.
- */
-static void isoc_irq(struct urb *urb)
-{
-       struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
-
-       PDEBUG(D_PACK, "isoc irq");
-       if (!gspca_dev->streaming)
-               return;
-       fill_frame(gspca_dev, urb);
-}
-
-/*
- * bulk message interrupt from the USB device
- */
-static void bulk_irq(struct urb *urb)
-{
-       struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
-       int st;
-
-       PDEBUG(D_PACK, "bulk irq");
-       if (!gspca_dev->streaming)
-               return;
-       switch (urb->status) {
-       case 0:
-               break;
-       case -ESHUTDOWN:
-               return;         /* disconnection */
-       default:
-#ifdef CONFIG_PM
-               if (gspca_dev->frozen)
-                       return;
-#endif
-               PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
-               urb->status = 0;
-               goto resubmit;
-       }
-
-       PDEBUG(D_PACK, "packet l:%d", urb->actual_length);
-       gspca_dev->sd_desc->pkt_scan(gspca_dev,
-                               urb->transfer_buffer,
-                               urb->actual_length);
-
-resubmit:
-       /* resubmit the URB */
-       if (gspca_dev->cam.bulk_nurbs != 0) {
-               st = usb_submit_urb(urb, GFP_ATOMIC);
-               if (st < 0)
-                       pr_err("usb_submit_urb() ret %d\n", st);
-       }
-}
-
-/*
- * add data to the current frame
- *
- * This function is called by the subdrivers at interrupt level.
- *
- * To build a frame, these ones must add
- *     - one FIRST_PACKET
- *     - 0 or many INTER_PACKETs
- *     - one LAST_PACKET
- * DISCARD_PACKET invalidates the whole frame.
- */
-void gspca_frame_add(struct gspca_dev *gspca_dev,
-                       enum gspca_packet_type packet_type,
-                       const u8 *data,
-                       int len)
-{
-       struct gspca_frame *frame;
-       int i, j;
-
-       PDEBUG(D_PACK, "add t:%d l:%d", packet_type, len);
-
-       if (packet_type == FIRST_PACKET) {
-               i = atomic_read(&gspca_dev->fr_i);
-
-               /* if there are no queued buffer, discard the whole frame */
-               if (i == atomic_read(&gspca_dev->fr_q)) {
-                       gspca_dev->last_packet_type = DISCARD_PACKET;
-                       gspca_dev->sequence++;
-                       return;
-               }
-               j = gspca_dev->fr_queue[i];
-               frame = &gspca_dev->frame[j];
-               frame->v4l2_buf.timestamp = ktime_to_timeval(ktime_get());
-               frame->v4l2_buf.sequence = gspca_dev->sequence++;
-               gspca_dev->image = frame->data;
-               gspca_dev->image_len = 0;
-       } else {
-               switch (gspca_dev->last_packet_type) {
-               case DISCARD_PACKET:
-                       if (packet_type == LAST_PACKET) {
-                               gspca_dev->last_packet_type = packet_type;
-                               gspca_dev->image = NULL;
-                               gspca_dev->image_len = 0;
-                       }
-                       return;
-               case LAST_PACKET:
-                       return;
-               }
-       }
-
-       /* append the packet to the frame buffer */
-       if (len > 0) {
-               if (gspca_dev->image_len + len > gspca_dev->frsz) {
-                       PDEBUG(D_ERR|D_PACK, "frame overflow %d > %d",
-                               gspca_dev->image_len + len,
-                               gspca_dev->frsz);
-                       packet_type = DISCARD_PACKET;
-               } else {
-/* !! image is NULL only when last pkt is LAST or DISCARD
-                       if (gspca_dev->image == NULL) {
-                               pr_err("gspca_frame_add() image == NULL\n");
-                               return;
-                       }
- */
-                       memcpy(gspca_dev->image + gspca_dev->image_len,
-                               data, len);
-                       gspca_dev->image_len += len;
-               }
-       }
-       gspca_dev->last_packet_type = packet_type;
-
-       /* if last packet, invalidate packet concatenation until
-        * next first packet, wake up the application and advance
-        * in the queue */
-       if (packet_type == LAST_PACKET) {
-               i = atomic_read(&gspca_dev->fr_i);
-               j = gspca_dev->fr_queue[i];
-               frame = &gspca_dev->frame[j];
-               frame->v4l2_buf.bytesused = gspca_dev->image_len;
-               frame->v4l2_buf.flags = (frame->v4l2_buf.flags
-                                        | V4L2_BUF_FLAG_DONE)
-                                       & ~V4L2_BUF_FLAG_QUEUED;
-               i = (i + 1) % GSPCA_MAX_FRAMES;
-               atomic_set(&gspca_dev->fr_i, i);
-               wake_up_interruptible(&gspca_dev->wq);  /* event = new frame */
-               PDEBUG(D_FRAM, "frame complete len:%d",
-                       frame->v4l2_buf.bytesused);
-               gspca_dev->image = NULL;
-               gspca_dev->image_len = 0;
-       }
-}
-EXPORT_SYMBOL(gspca_frame_add);
-
-static int frame_alloc(struct gspca_dev *gspca_dev, struct file *file,
-                       enum v4l2_memory memory, unsigned int count)
-{
-       struct gspca_frame *frame;
-       unsigned int frsz;
-       int i;
-
-       i = gspca_dev->curr_mode;
-       frsz = gspca_dev->cam.cam_mode[i].sizeimage;
-       PDEBUG(D_STREAM, "frame alloc frsz: %d", frsz);
-       frsz = PAGE_ALIGN(frsz);
-       if (count >= GSPCA_MAX_FRAMES)
-               count = GSPCA_MAX_FRAMES - 1;
-       gspca_dev->frbuf = vmalloc_32(frsz * count);
-       if (!gspca_dev->frbuf) {
-               pr_err("frame alloc failed\n");
-               return -ENOMEM;
-       }
-       gspca_dev->capt_file = file;
-       gspca_dev->memory = memory;
-       gspca_dev->frsz = frsz;
-       gspca_dev->nframes = count;
-       for (i = 0; i < count; i++) {
-               frame = &gspca_dev->frame[i];
-               frame->v4l2_buf.index = i;
-               frame->v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               frame->v4l2_buf.flags = 0;
-               frame->v4l2_buf.field = V4L2_FIELD_NONE;
-               frame->v4l2_buf.length = frsz;
-               frame->v4l2_buf.memory = memory;
-               frame->v4l2_buf.sequence = 0;
-               frame->data = gspca_dev->frbuf + i * frsz;
-               frame->v4l2_buf.m.offset = i * frsz;
-       }
-       atomic_set(&gspca_dev->fr_q, 0);
-       atomic_set(&gspca_dev->fr_i, 0);
-       gspca_dev->fr_o = 0;
-       return 0;
-}
-
-static void frame_free(struct gspca_dev *gspca_dev)
-{
-       int i;
-
-       PDEBUG(D_STREAM, "frame free");
-       if (gspca_dev->frbuf != NULL) {
-               vfree(gspca_dev->frbuf);
-               gspca_dev->frbuf = NULL;
-               for (i = 0; i < gspca_dev->nframes; i++)
-                       gspca_dev->frame[i].data = NULL;
-       }
-       gspca_dev->nframes = 0;
-       gspca_dev->frsz = 0;
-       gspca_dev->capt_file = NULL;
-       gspca_dev->memory = GSPCA_MEMORY_NO;
-}
-
-static void destroy_urbs(struct gspca_dev *gspca_dev)
-{
-       struct urb *urb;
-       unsigned int i;
-
-       PDEBUG(D_STREAM, "kill transfer");
-       for (i = 0; i < MAX_NURBS; i++) {
-               urb = gspca_dev->urb[i];
-               if (urb == NULL)
-                       break;
-
-               gspca_dev->urb[i] = NULL;
-               usb_kill_urb(urb);
-               if (urb->transfer_buffer != NULL)
-                       usb_free_coherent(gspca_dev->dev,
-                                         urb->transfer_buffer_length,
-                                         urb->transfer_buffer,
-                                         urb->transfer_dma);
-               usb_free_urb(urb);
-       }
-}
-
-static int gspca_set_alt0(struct gspca_dev *gspca_dev)
-{
-       int ret;
-
-       if (gspca_dev->alt == 0)
-               return 0;
-       ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0);
-       if (ret < 0)
-               pr_err("set alt 0 err %d\n", ret);
-       return ret;
-}
-
-/* Note: both the queue and the usb locks should be held when calling this */
-static void gspca_stream_off(struct gspca_dev *gspca_dev)
-{
-       gspca_dev->streaming = 0;
-       gspca_dev->usb_err = 0;
-       if (gspca_dev->sd_desc->stopN)
-               gspca_dev->sd_desc->stopN(gspca_dev);
-       destroy_urbs(gspca_dev);
-       gspca_input_destroy_urb(gspca_dev);
-       gspca_set_alt0(gspca_dev);
-       gspca_input_create_urb(gspca_dev);
-       if (gspca_dev->sd_desc->stop0)
-               gspca_dev->sd_desc->stop0(gspca_dev);
-       PDEBUG(D_STREAM, "stream off OK");
-}
-
-/*
- * look for an input transfer endpoint in an alternate setting
- */
-static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
-                                         int xfer)
-{
-       struct usb_host_endpoint *ep;
-       int i, attr;
-
-       for (i = 0; i < alt->desc.bNumEndpoints; i++) {
-               ep = &alt->endpoint[i];
-               attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-               if (attr == xfer
-                   && ep->desc.wMaxPacketSize != 0
-                   && usb_endpoint_dir_in(&ep->desc))
-                       return ep;
-       }
-       return NULL;
-}
-
-/* compute the minimum bandwidth for the current transfer */
-static u32 which_bandwidth(struct gspca_dev *gspca_dev)
-{
-       u32 bandwidth;
-       int i;
-
-       /* get the (max) image size */
-       i = gspca_dev->curr_mode;
-       bandwidth = gspca_dev->cam.cam_mode[i].sizeimage;
-
-       /* if the image is compressed, estimate its mean size */
-       if (!gspca_dev->cam.needs_full_bandwidth &&
-           bandwidth < gspca_dev->cam.cam_mode[i].width *
-                               gspca_dev->cam.cam_mode[i].height)
-               bandwidth = bandwidth * 3 / 8;  /* 0.375 */
-
-       /* estimate the frame rate */
-       if (gspca_dev->sd_desc->get_streamparm) {
-               struct v4l2_streamparm parm;
-
-               gspca_dev->sd_desc->get_streamparm(gspca_dev, &parm);
-               bandwidth *= parm.parm.capture.timeperframe.denominator;
-               bandwidth /= parm.parm.capture.timeperframe.numerator;
-       } else {
-
-               /* don't hope more than 15 fps with USB 1.1 and
-                * image resolution >= 640x480 */
-               if (gspca_dev->width >= 640
-                && gspca_dev->dev->speed == USB_SPEED_FULL)
-                       bandwidth *= 15;                /* 15 fps */
-               else
-                       bandwidth *= 30;                /* 30 fps */
-       }
-
-       PDEBUG(D_STREAM, "min bandwidth: %d", bandwidth);
-       return bandwidth;
-}
-
-/* endpoint table */
-#define MAX_ALT 16
-struct ep_tb_s {
-       u32 alt;
-       u32 bandwidth;
-};
-
-/*
- * build the table of the endpoints
- * and compute the minimum bandwidth for the image transfer
- */
-static int build_isoc_ep_tb(struct gspca_dev *gspca_dev,
-                       struct usb_interface *intf,
-                       struct ep_tb_s *ep_tb)
-{
-       struct usb_host_endpoint *ep;
-       int i, j, nbalt, psize, found;
-       u32 bandwidth, last_bw;
-
-       nbalt = intf->num_altsetting;
-       if (nbalt > MAX_ALT)
-               nbalt = MAX_ALT;        /* fixme: should warn */
-
-       /* build the endpoint table */
-       i = 0;
-       last_bw = 0;
-       for (;;) {
-               ep_tb->bandwidth = 2000 * 2000 * 120;
-               found = 0;
-               for (j = 0; j < nbalt; j++) {
-                       ep = alt_xfer(&intf->altsetting[j],
-                                     USB_ENDPOINT_XFER_ISOC);
-                       if (ep == NULL)
-                               continue;
-                       if (ep->desc.bInterval == 0) {
-                               pr_err("alt %d iso endp with 0 interval\n", j);
-                               continue;
-                       }
-                       psize = le16_to_cpu(ep->desc.wMaxPacketSize);
-                       psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
-                       bandwidth = psize * 1000;
-                       if (gspca_dev->dev->speed == USB_SPEED_HIGH
-                        || gspca_dev->dev->speed == USB_SPEED_SUPER)
-                               bandwidth *= 8;
-                       bandwidth /= 1 << (ep->desc.bInterval - 1);
-                       if (bandwidth <= last_bw)
-                               continue;
-                       if (bandwidth < ep_tb->bandwidth) {
-                               ep_tb->bandwidth = bandwidth;
-                               ep_tb->alt = j;
-                               found = 1;
-                       }
-               }
-               if (!found)
-                       break;
-               PDEBUG(D_STREAM, "alt %d bandwidth %d",
-                               ep_tb->alt, ep_tb->bandwidth);
-               last_bw = ep_tb->bandwidth;
-               i++;
-               ep_tb++;
-       }
-
-       /*
-        * If the camera:
-        * has a usb audio class interface (a built in usb mic); and
-        * is a usb 1 full speed device; and
-        * uses the max full speed iso bandwidth; and
-        * and has more than 1 alt setting
-        * then skip the highest alt setting to spare bandwidth for the mic
-        */
-       if (gspca_dev->audio &&
-                       gspca_dev->dev->speed == USB_SPEED_FULL &&
-                       last_bw >= 1000000 &&
-                       i > 1) {
-               PDEBUG(D_STREAM, "dev has usb audio, skipping highest alt");
-               i--;
-               ep_tb--;
-       }
-
-       /* get the requested bandwidth and start at the highest atlsetting */
-       bandwidth = which_bandwidth(gspca_dev);
-       ep_tb--;
-       while (i > 1) {
-               ep_tb--;
-               if (ep_tb->bandwidth < bandwidth)
-                       break;
-               i--;
-       }
-       return i;
-}
-
-/*
- * create the URBs for image transfer
- */
-static int create_urbs(struct gspca_dev *gspca_dev,
-                       struct usb_host_endpoint *ep)
-{
-       struct urb *urb;
-       int n, nurbs, i, psize, npkt, bsize;
-
-       /* calculate the packet size and the number of packets */
-       psize = le16_to_cpu(ep->desc.wMaxPacketSize);
-
-       if (!gspca_dev->cam.bulk) {             /* isoc */
-
-               /* See paragraph 5.9 / table 5-11 of the usb 2.0 spec. */
-               if (gspca_dev->pkt_size == 0)
-                       psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
-               else
-                       psize = gspca_dev->pkt_size;
-               npkt = gspca_dev->cam.npkt;
-               if (npkt == 0)
-                       npkt = 32;              /* default value */
-               bsize = psize * npkt;
-               PDEBUG(D_STREAM,
-                       "isoc %d pkts size %d = bsize:%d",
-                       npkt, psize, bsize);
-               nurbs = DEF_NURBS;
-       } else {                                /* bulk */
-               npkt = 0;
-               bsize = gspca_dev->cam.bulk_size;
-               if (bsize == 0)
-                       bsize = psize;
-               PDEBUG(D_STREAM, "bulk bsize:%d", bsize);
-               if (gspca_dev->cam.bulk_nurbs != 0)
-                       nurbs = gspca_dev->cam.bulk_nurbs;
-               else
-                       nurbs = 1;
-       }
-
-       for (n = 0; n < nurbs; n++) {
-               urb = usb_alloc_urb(npkt, GFP_KERNEL);
-               if (!urb) {
-                       pr_err("usb_alloc_urb failed\n");
-                       return -ENOMEM;
-               }
-               gspca_dev->urb[n] = urb;
-               urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
-                                               bsize,
-                                               GFP_KERNEL,
-                                               &urb->transfer_dma);
-
-               if (urb->transfer_buffer == NULL) {
-                       pr_err("usb_alloc_coherent failed\n");
-                       return -ENOMEM;
-               }
-               urb->dev = gspca_dev->dev;
-               urb->context = gspca_dev;
-               urb->transfer_buffer_length = bsize;
-               if (npkt != 0) {                /* ISOC */
-                       urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
-                                                   ep->desc.bEndpointAddress);
-                       urb->transfer_flags = URB_ISO_ASAP
-                                       | URB_NO_TRANSFER_DMA_MAP;
-                       urb->interval = 1 << (ep->desc.bInterval - 1);
-                       urb->complete = isoc_irq;
-                       urb->number_of_packets = npkt;
-                       for (i = 0; i < npkt; i++) {
-                               urb->iso_frame_desc[i].length = psize;
-                               urb->iso_frame_desc[i].offset = psize * i;
-                       }
-               } else {                /* bulk */
-                       urb->pipe = usb_rcvbulkpipe(gspca_dev->dev,
-                                               ep->desc.bEndpointAddress);
-                       urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
-                       urb->complete = bulk_irq;
-               }
-       }
-       return 0;
-}
-
-/*
- * start the USB transfer
- */
-static int gspca_init_transfer(struct gspca_dev *gspca_dev)
-{
-       struct usb_interface *intf;
-       struct usb_host_endpoint *ep;
-       struct urb *urb;
-       struct ep_tb_s ep_tb[MAX_ALT];
-       int n, ret, xfer, alt, alt_idx;
-
-       /* reset the streaming variables */
-       gspca_dev->image = NULL;
-       gspca_dev->image_len = 0;
-       gspca_dev->last_packet_type = DISCARD_PACKET;
-       gspca_dev->sequence = 0;
-
-       gspca_dev->usb_err = 0;
-
-       /* do the specific subdriver stuff before endpoint selection */
-       intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
-       gspca_dev->alt = gspca_dev->cam.bulk ? intf->num_altsetting : 0;
-       if (gspca_dev->sd_desc->isoc_init) {
-               ret = gspca_dev->sd_desc->isoc_init(gspca_dev);
-               if (ret < 0)
-                       return ret;
-       }
-       xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK
-                                  : USB_ENDPOINT_XFER_ISOC;
-
-       /* if bulk or the subdriver forced an altsetting, get the endpoint */
-       if (gspca_dev->alt != 0) {
-               gspca_dev->alt--;       /* (previous version compatibility) */
-               ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer);
-               if (ep == NULL) {
-                       pr_err("bad altsetting %d\n", gspca_dev->alt);
-                       return -EIO;
-               }
-               ep_tb[0].alt = gspca_dev->alt;
-               alt_idx = 1;
-       } else {
-
-       /* else, compute the minimum bandwidth
-        * and build the endpoint table */
-               alt_idx = build_isoc_ep_tb(gspca_dev, intf, ep_tb);
-               if (alt_idx <= 0) {
-                       pr_err("no transfer endpoint found\n");
-                       return -EIO;
-               }
-       }
-
-       /* set the highest alternate setting and
-        * loop until urb submit succeeds */
-       gspca_input_destroy_urb(gspca_dev);
-
-       gspca_dev->alt = ep_tb[--alt_idx].alt;
-       alt = -1;
-       for (;;) {
-               if (alt != gspca_dev->alt) {
-                       alt = gspca_dev->alt;
-                       if (intf->num_altsetting > 1) {
-                               ret = usb_set_interface(gspca_dev->dev,
-                                                       gspca_dev->iface,
-                                                       alt);
-                               if (ret < 0) {
-                                       if (ret == -ENOSPC)
-                                               goto retry; /*fixme: ugly*/
-                                       pr_err("set alt %d err %d\n", alt, ret);
-                                       goto out;
-                               }
-                       }
-               }
-               if (!gspca_dev->cam.no_urb_create) {
-                       PDEBUG(D_STREAM, "init transfer alt %d", alt);
-                       ret = create_urbs(gspca_dev,
-                               alt_xfer(&intf->altsetting[alt], xfer));
-                       if (ret < 0) {
-                               destroy_urbs(gspca_dev);
-                               goto out;
-                       }
-               }
-
-               /* clear the bulk endpoint */
-               if (gspca_dev->cam.bulk)
-                       usb_clear_halt(gspca_dev->dev,
-                                       gspca_dev->urb[0]->pipe);
-
-               /* start the cam */
-               ret = gspca_dev->sd_desc->start(gspca_dev);
-               if (ret < 0) {
-                       destroy_urbs(gspca_dev);
-                       goto out;
-               }
-               gspca_dev->streaming = 1;
-               v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler);
-
-               /* some bulk transfers are started by the subdriver */
-               if (gspca_dev->cam.bulk && gspca_dev->cam.bulk_nurbs == 0)
-                       break;
-
-               /* submit the URBs */
-               for (n = 0; n < MAX_NURBS; n++) {
-                       urb = gspca_dev->urb[n];
-                       if (urb == NULL)
-                               break;
-                       ret = usb_submit_urb(urb, GFP_KERNEL);
-                       if (ret < 0)
-                               break;
-               }
-               if (ret >= 0)
-                       break;                  /* transfer is started */
-
-               /* something when wrong
-                * stop the webcam and free the transfer resources */
-               gspca_stream_off(gspca_dev);
-               if (ret != -ENOSPC) {
-                       pr_err("usb_submit_urb alt %d err %d\n",
-                              gspca_dev->alt, ret);
-                       goto out;
-               }
-
-               /* the bandwidth is not wide enough
-                * negotiate or try a lower alternate setting */
-retry:
-               PDEBUG(D_ERR|D_STREAM,
-                       "alt %d - bandwidth not wide enough - trying again",
-                       alt);
-               msleep(20);     /* wait for kill complete */
-               if (gspca_dev->sd_desc->isoc_nego) {
-                       ret = gspca_dev->sd_desc->isoc_nego(gspca_dev);
-                       if (ret < 0)
-                               goto out;
-               } else {
-                       if (alt_idx <= 0) {
-                               pr_err("no transfer endpoint found\n");
-                               ret = -EIO;
-                               goto out;
-                       }
-                       gspca_dev->alt = ep_tb[--alt_idx].alt;
-               }
-       }
-out:
-       gspca_input_create_urb(gspca_dev);
-       return ret;
-}
-
-static void gspca_set_default_mode(struct gspca_dev *gspca_dev)
-{
-       struct gspca_ctrl *ctrl;
-       int i;
-
-       i = gspca_dev->cam.nmodes - 1;  /* take the highest mode */
-       gspca_dev->curr_mode = i;
-       gspca_dev->width = gspca_dev->cam.cam_mode[i].width;
-       gspca_dev->height = gspca_dev->cam.cam_mode[i].height;
-       gspca_dev->pixfmt = gspca_dev->cam.cam_mode[i].pixelformat;
-
-       /* set the current control values to their default values
-        * which may have changed in sd_init() */
-       /* does nothing if ctrl_handler == NULL */
-       v4l2_ctrl_handler_setup(gspca_dev->vdev.ctrl_handler);
-       ctrl = gspca_dev->cam.ctrls;
-       if (ctrl != NULL) {
-               for (i = 0;
-                    i < gspca_dev->sd_desc->nctrls;
-                    i++, ctrl++)
-                       ctrl->val = ctrl->def;
-       }
-}
-
-static int wxh_to_mode(struct gspca_dev *gspca_dev,
-                       int width, int height)
-{
-       int i;
-
-       for (i = gspca_dev->cam.nmodes; --i > 0; ) {
-               if (width >= gspca_dev->cam.cam_mode[i].width
-                   && height >= gspca_dev->cam.cam_mode[i].height)
-                       break;
-       }
-       return i;
-}
-
-/*
- * search a mode with the right pixel format
- */
-static int gspca_get_mode(struct gspca_dev *gspca_dev,
-                       int mode,
-                       int pixfmt)
-{
-       int modeU, modeD;
-
-       modeU = modeD = mode;
-       while ((modeU < gspca_dev->cam.nmodes) || modeD >= 0) {
-               if (--modeD >= 0) {
-                       if (gspca_dev->cam.cam_mode[modeD].pixelformat
-                                                               == pixfmt)
-                               return modeD;
-               }
-               if (++modeU < gspca_dev->cam.nmodes) {
-                       if (gspca_dev->cam.cam_mode[modeU].pixelformat
-                                                               == pixfmt)
-                               return modeU;
-               }
-       }
-       return -EINVAL;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int vidioc_g_register(struct file *file, void *priv,
-                       struct v4l2_dbg_register *reg)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-
-       gspca_dev->usb_err = 0;
-       return gspca_dev->sd_desc->get_register(gspca_dev, reg);
-}
-
-static int vidioc_s_register(struct file *file, void *priv,
-                       struct v4l2_dbg_register *reg)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-
-       gspca_dev->usb_err = 0;
-       return gspca_dev->sd_desc->set_register(gspca_dev, reg);
-}
-#endif
-
-static int vidioc_g_chip_ident(struct file *file, void *priv,
-                       struct v4l2_dbg_chip_ident *chip)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-
-       gspca_dev->usb_err = 0;
-       return gspca_dev->sd_desc->get_chip_ident(gspca_dev, chip);
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-                               struct v4l2_fmtdesc *fmtdesc)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       int i, j, index;
-       __u32 fmt_tb[8];
-
-       /* give an index to each format */
-       index = 0;
-       j = 0;
-       for (i = gspca_dev->cam.nmodes; --i >= 0; ) {
-               fmt_tb[index] = gspca_dev->cam.cam_mode[i].pixelformat;
-               j = 0;
-               for (;;) {
-                       if (fmt_tb[j] == fmt_tb[index])
-                               break;
-                       j++;
-               }
-               if (j == index) {
-                       if (fmtdesc->index == index)
-                               break;          /* new format */
-                       index++;
-                       if (index >= ARRAY_SIZE(fmt_tb))
-                               return -EINVAL;
-               }
-       }
-       if (i < 0)
-               return -EINVAL;         /* no more format */
-
-       fmtdesc->pixelformat = fmt_tb[index];
-       if (gspca_dev->cam.cam_mode[i].sizeimage <
-                       gspca_dev->cam.cam_mode[i].width *
-                               gspca_dev->cam.cam_mode[i].height)
-               fmtdesc->flags = V4L2_FMT_FLAG_COMPRESSED;
-       fmtdesc->description[0] = fmtdesc->pixelformat & 0xff;
-       fmtdesc->description[1] = (fmtdesc->pixelformat >> 8) & 0xff;
-       fmtdesc->description[2] = (fmtdesc->pixelformat >> 16) & 0xff;
-       fmtdesc->description[3] = fmtdesc->pixelformat >> 24;
-       fmtdesc->description[4] = '\0';
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                           struct v4l2_format *fmt)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       int mode;
-
-       mode = gspca_dev->curr_mode;
-       fmt->fmt.pix = gspca_dev->cam.cam_mode[mode];
-       /* some drivers use priv internally, zero it before giving it to
-          userspace */
-       fmt->fmt.pix.priv = 0;
-       return 0;
-}
-
-static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
-                       struct v4l2_format *fmt)
-{
-       int w, h, mode, mode2;
-
-       w = fmt->fmt.pix.width;
-       h = fmt->fmt.pix.height;
-
-#ifdef GSPCA_DEBUG
-       if (gspca_debug & D_CONF)
-               PDEBUG_MODE("try fmt cap", fmt->fmt.pix.pixelformat, w, h);
-#endif
-       /* search the closest mode for width and height */
-       mode = wxh_to_mode(gspca_dev, w, h);
-
-       /* OK if right palette */
-       if (gspca_dev->cam.cam_mode[mode].pixelformat
-                                               != fmt->fmt.pix.pixelformat) {
-
-               /* else, search the closest mode with the same pixel format */
-               mode2 = gspca_get_mode(gspca_dev, mode,
-                                       fmt->fmt.pix.pixelformat);
-               if (mode2 >= 0)
-                       mode = mode2;
-/*             else
-                       ;                * no chance, return this mode */
-       }
-       fmt->fmt.pix = gspca_dev->cam.cam_mode[mode];
-       /* some drivers use priv internally, zero it before giving it to
-          userspace */
-       fmt->fmt.pix.priv = 0;
-       return mode;                    /* used when s_fmt */
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file,
-                             void *priv,
-                             struct v4l2_format *fmt)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       int ret;
-
-       ret = try_fmt_vid_cap(gspca_dev, fmt);
-       if (ret < 0)
-               return ret;
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                           struct v4l2_format *fmt)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       int ret;
-
-       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
-               return -ERESTARTSYS;
-
-       ret = try_fmt_vid_cap(gspca_dev, fmt);
-       if (ret < 0)
-               goto out;
-
-       if (gspca_dev->nframes != 0
-           && fmt->fmt.pix.sizeimage > gspca_dev->frsz) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       if (ret == gspca_dev->curr_mode) {
-               ret = 0;
-               goto out;                       /* same mode */
-       }
-
-       if (gspca_dev->streaming) {
-               ret = -EBUSY;
-               goto out;
-       }
-       gspca_dev->width = fmt->fmt.pix.width;
-       gspca_dev->height = fmt->fmt.pix.height;
-       gspca_dev->pixfmt = fmt->fmt.pix.pixelformat;
-       gspca_dev->curr_mode = ret;
-
-       ret = 0;
-out:
-       mutex_unlock(&gspca_dev->queue_lock);
-       return ret;
-}
-
-static int vidioc_enum_framesizes(struct file *file, void *priv,
-                                 struct v4l2_frmsizeenum *fsize)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       int i;
-       __u32 index = 0;
-
-       for (i = 0; i < gspca_dev->cam.nmodes; i++) {
-               if (fsize->pixel_format !=
-                               gspca_dev->cam.cam_mode[i].pixelformat)
-                       continue;
-
-               if (fsize->index == index) {
-                       fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-                       fsize->discrete.width =
-                               gspca_dev->cam.cam_mode[i].width;
-                       fsize->discrete.height =
-                               gspca_dev->cam.cam_mode[i].height;
-                       return 0;
-               }
-               index++;
-       }
-
-       return -EINVAL;
-}
-
-static int vidioc_enum_frameintervals(struct file *filp, void *priv,
-                                     struct v4l2_frmivalenum *fival)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(filp);
-       int mode = wxh_to_mode(gspca_dev, fival->width, fival->height);
-       __u32 i;
-
-       if (gspca_dev->cam.mode_framerates == NULL ||
-                       gspca_dev->cam.mode_framerates[mode].nrates == 0)
-               return -EINVAL;
-
-       if (fival->pixel_format !=
-                       gspca_dev->cam.cam_mode[mode].pixelformat)
-               return -EINVAL;
-
-       for (i = 0; i < gspca_dev->cam.mode_framerates[mode].nrates; i++) {
-               if (fival->index == i) {
-                       fival->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-                       fival->discrete.numerator = 1;
-                       fival->discrete.denominator =
-                               gspca_dev->cam.mode_framerates[mode].rates[i];
-                       return 0;
-               }
-       }
-
-       return -EINVAL;
-}
-
-static void gspca_release(struct v4l2_device *v4l2_device)
-{
-       struct gspca_dev *gspca_dev =
-               container_of(v4l2_device, struct gspca_dev, v4l2_dev);
-
-       v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler);
-       v4l2_device_unregister(&gspca_dev->v4l2_dev);
-       kfree(gspca_dev->usb_buf);
-       kfree(gspca_dev);
-}
-
-static int dev_open(struct file *file)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-
-       PDEBUG(D_STREAM, "[%s] open", current->comm);
-
-       /* protect the subdriver against rmmod */
-       if (!try_module_get(gspca_dev->module))
-               return -ENODEV;
-
-#ifdef GSPCA_DEBUG
-       /* activate the v4l2 debug */
-       if (gspca_debug & D_V4L2)
-               gspca_dev->vdev.debug |= V4L2_DEBUG_IOCTL
-                                       | V4L2_DEBUG_IOCTL_ARG;
-       else
-               gspca_dev->vdev.debug &= ~(V4L2_DEBUG_IOCTL
-                                       | V4L2_DEBUG_IOCTL_ARG);
-#endif
-       return v4l2_fh_open(file);
-}
-
-static int dev_close(struct file *file)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-
-       PDEBUG(D_STREAM, "[%s] close", current->comm);
-
-       /* Needed for gspca_stream_off, always lock before queue_lock! */
-       if (mutex_lock_interruptible(&gspca_dev->usb_lock))
-               return -ERESTARTSYS;
-
-       if (mutex_lock_interruptible(&gspca_dev->queue_lock)) {
-               mutex_unlock(&gspca_dev->usb_lock);
-               return -ERESTARTSYS;
-       }
-
-       /* if the file did the capture, free the streaming resources */
-       if (gspca_dev->capt_file == file) {
-               if (gspca_dev->streaming)
-                       gspca_stream_off(gspca_dev);
-               frame_free(gspca_dev);
-       }
-       module_put(gspca_dev->module);
-       mutex_unlock(&gspca_dev->queue_lock);
-       mutex_unlock(&gspca_dev->usb_lock);
-
-       PDEBUG(D_STREAM, "close done");
-
-       return v4l2_fh_release(file);
-}
-
-static int vidioc_querycap(struct file *file, void  *priv,
-                          struct v4l2_capability *cap)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-
-       strlcpy((char *) cap->driver, gspca_dev->sd_desc->name,
-                       sizeof cap->driver);
-       if (gspca_dev->dev->product != NULL) {
-               strlcpy((char *) cap->card, gspca_dev->dev->product,
-                       sizeof cap->card);
-       } else {
-               snprintf((char *) cap->card, sizeof cap->card,
-                       "USB Camera (%04x:%04x)",
-                       le16_to_cpu(gspca_dev->dev->descriptor.idVendor),
-                       le16_to_cpu(gspca_dev->dev->descriptor.idProduct));
-       }
-       usb_make_path(gspca_dev->dev, (char *) cap->bus_info,
-                       sizeof(cap->bus_info));
-       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
-                         | V4L2_CAP_STREAMING
-                         | V4L2_CAP_READWRITE;
-       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-       return 0;
-}
-
-static int get_ctrl(struct gspca_dev *gspca_dev,
-                                  int id)
-{
-       const struct ctrl *ctrls;
-       int i;
-
-       for (i = 0, ctrls = gspca_dev->sd_desc->ctrls;
-            i < gspca_dev->sd_desc->nctrls;
-            i++, ctrls++) {
-               if (gspca_dev->ctrl_dis & (1 << i))
-                       continue;
-               if (id == ctrls->qctrl.id)
-                       return i;
-       }
-       return -1;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-                          struct v4l2_queryctrl *q_ctrl)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       const struct ctrl *ctrls;
-       struct gspca_ctrl *gspca_ctrl;
-       int i, idx;
-       u32 id;
-
-       id = q_ctrl->id;
-       if (id & V4L2_CTRL_FLAG_NEXT_CTRL) {
-               id &= V4L2_CTRL_ID_MASK;
-               id++;
-               idx = -1;
-               for (i = 0; i < gspca_dev->sd_desc->nctrls; i++) {
-                       if (gspca_dev->ctrl_dis & (1 << i))
-                               continue;
-                       if (gspca_dev->sd_desc->ctrls[i].qctrl.id < id)
-                               continue;
-                       if (idx >= 0
-                        && gspca_dev->sd_desc->ctrls[i].qctrl.id
-                                   > gspca_dev->sd_desc->ctrls[idx].qctrl.id)
-                               continue;
-                       idx = i;
-               }
-       } else {
-               idx = get_ctrl(gspca_dev, id);
-       }
-       if (idx < 0)
-               return -EINVAL;
-       ctrls = &gspca_dev->sd_desc->ctrls[idx];
-       memcpy(q_ctrl, &ctrls->qctrl, sizeof *q_ctrl);
-       if (gspca_dev->cam.ctrls != NULL) {
-               gspca_ctrl = &gspca_dev->cam.ctrls[idx];
-               q_ctrl->default_value = gspca_ctrl->def;
-               q_ctrl->minimum = gspca_ctrl->min;
-               q_ctrl->maximum = gspca_ctrl->max;
-       }
-       if (gspca_dev->ctrl_inac & (1 << idx))
-               q_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
-       return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                        struct v4l2_control *ctrl)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       const struct ctrl *ctrls;
-       struct gspca_ctrl *gspca_ctrl;
-       int idx;
-
-       idx = get_ctrl(gspca_dev, ctrl->id);
-       if (idx < 0)
-               return -EINVAL;
-       if (gspca_dev->ctrl_inac & (1 << idx))
-               return -EINVAL;
-       ctrls = &gspca_dev->sd_desc->ctrls[idx];
-       if (gspca_dev->cam.ctrls != NULL) {
-               gspca_ctrl = &gspca_dev->cam.ctrls[idx];
-               if (ctrl->value < gspca_ctrl->min
-                   || ctrl->value > gspca_ctrl->max)
-                       return -ERANGE;
-       } else {
-               gspca_ctrl = NULL;
-               if (ctrl->value < ctrls->qctrl.minimum
-                   || ctrl->value > ctrls->qctrl.maximum)
-                       return -ERANGE;
-       }
-       PDEBUG(D_CONF, "set ctrl [%08x] = %d", ctrl->id, ctrl->value);
-       gspca_dev->usb_err = 0;
-       if (ctrls->set != NULL)
-               return ctrls->set(gspca_dev, ctrl->value);
-       if (gspca_ctrl != NULL) {
-               gspca_ctrl->val = ctrl->value;
-               if (ctrls->set_control != NULL
-                && gspca_dev->streaming)
-                       ctrls->set_control(gspca_dev);
-       }
-       return gspca_dev->usb_err;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                        struct v4l2_control *ctrl)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       const struct ctrl *ctrls;
-       int idx;
-
-       idx = get_ctrl(gspca_dev, ctrl->id);
-       if (idx < 0)
-               return -EINVAL;
-       ctrls = &gspca_dev->sd_desc->ctrls[idx];
-
-       gspca_dev->usb_err = 0;
-       if (ctrls->get != NULL)
-               return ctrls->get(gspca_dev, &ctrl->value);
-       if (gspca_dev->cam.ctrls != NULL)
-               ctrl->value = gspca_dev->cam.ctrls[idx].val;
-       return 0;
-}
-
-static int vidioc_querymenu(struct file *file, void *priv,
-                           struct v4l2_querymenu *qmenu)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-
-       if (!gspca_dev->sd_desc->querymenu)
-               return -ENOTTY;
-       return gspca_dev->sd_desc->querymenu(gspca_dev, qmenu);
-}
-
-static int vidioc_enum_input(struct file *file, void *priv,
-                               struct v4l2_input *input)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-
-       if (input->index != 0)
-               return -EINVAL;
-       input->type = V4L2_INPUT_TYPE_CAMERA;
-       input->status = gspca_dev->cam.input_flags;
-       strlcpy(input->name, gspca_dev->sd_desc->name,
-               sizeof input->name);
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       *i = 0;
-       return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       if (i > 0)
-               return -EINVAL;
-       return (0);
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
-                         struct v4l2_requestbuffers *rb)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       int i, ret = 0, streaming;
-
-       i = rb->memory;                 /* (avoid compilation warning) */
-       switch (i) {
-       case GSPCA_MEMORY_READ:                 /* (internal call) */
-       case V4L2_MEMORY_MMAP:
-       case V4L2_MEMORY_USERPTR:
-               break;
-       default:
-               return -EINVAL;
-       }
-       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
-               return -ERESTARTSYS;
-
-       if (gspca_dev->memory != GSPCA_MEMORY_NO
-           && gspca_dev->memory != GSPCA_MEMORY_READ
-           && gspca_dev->memory != rb->memory) {
-               ret = -EBUSY;
-               goto out;
-       }
-
-       /* only one file may do the capture */
-       if (gspca_dev->capt_file != NULL
-           && gspca_dev->capt_file != file) {
-               ret = -EBUSY;
-               goto out;
-       }
-
-       /* if allocated, the buffers must not be mapped */
-       for (i = 0; i < gspca_dev->nframes; i++) {
-               if (gspca_dev->frame[i].vma_use_count) {
-                       ret = -EBUSY;
-                       goto out;
-               }
-       }
-
-       /* stop streaming */
-       streaming = gspca_dev->streaming;
-       if (streaming) {
-               gspca_stream_off(gspca_dev);
-
-               /* Don't restart the stream when switching from read
-                * to mmap mode */
-               if (gspca_dev->memory == GSPCA_MEMORY_READ)
-                       streaming = 0;
-       }
-
-       /* free the previous allocated buffers, if any */
-       if (gspca_dev->nframes != 0)
-               frame_free(gspca_dev);
-       if (rb->count == 0)                     /* unrequest */
-               goto out;
-       ret = frame_alloc(gspca_dev, file, rb->memory, rb->count);
-       if (ret == 0) {
-               rb->count = gspca_dev->nframes;
-               if (streaming)
-                       ret = gspca_init_transfer(gspca_dev);
-       }
-out:
-       mutex_unlock(&gspca_dev->queue_lock);
-       PDEBUG(D_STREAM, "reqbufs st:%d c:%d", ret, rb->count);
-       return ret;
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-                          struct v4l2_buffer *v4l2_buf)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       struct gspca_frame *frame;
-
-       if (v4l2_buf->index < 0
-           || v4l2_buf->index >= gspca_dev->nframes)
-               return -EINVAL;
-
-       frame = &gspca_dev->frame[v4l2_buf->index];
-       memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
-       return 0;
-}
-
-static int vidioc_streamon(struct file *file, void *priv,
-                          enum v4l2_buf_type buf_type)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       int ret;
-
-       if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
-               return -ERESTARTSYS;
-
-       /* check the capture file */
-       if (gspca_dev->capt_file != file) {
-               ret = -EBUSY;
-               goto out;
-       }
-
-       if (gspca_dev->nframes == 0
-           || !(gspca_dev->frame[0].v4l2_buf.flags & V4L2_BUF_FLAG_QUEUED)) {
-               ret = -EINVAL;
-               goto out;
-       }
-       if (!gspca_dev->streaming) {
-               ret = gspca_init_transfer(gspca_dev);
-               if (ret < 0)
-                       goto out;
-       }
-#ifdef GSPCA_DEBUG
-       if (gspca_debug & D_STREAM) {
-               PDEBUG_MODE("stream on OK",
-                       gspca_dev->pixfmt,
-                       gspca_dev->width,
-                       gspca_dev->height);
-       }
-#endif
-       ret = 0;
-out:
-       mutex_unlock(&gspca_dev->queue_lock);
-       return ret;
-}
-
-static int vidioc_streamoff(struct file *file, void *priv,
-                               enum v4l2_buf_type buf_type)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       int i, ret;
-
-       if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
-               return -ERESTARTSYS;
-
-       if (!gspca_dev->streaming) {
-               ret = 0;
-               goto out;
-       }
-
-       /* check the capture file */
-       if (gspca_dev->capt_file != file) {
-               ret = -EBUSY;
-               goto out;
-       }
-
-       /* stop streaming */
-       gspca_stream_off(gspca_dev);
-       /* In case another thread is waiting in dqbuf */
-       wake_up_interruptible(&gspca_dev->wq);
-
-       /* empty the transfer queues */
-       for (i = 0; i < gspca_dev->nframes; i++)
-               gspca_dev->frame[i].v4l2_buf.flags &= ~BUF_ALL_FLAGS;
-       atomic_set(&gspca_dev->fr_q, 0);
-       atomic_set(&gspca_dev->fr_i, 0);
-       gspca_dev->fr_o = 0;
-       ret = 0;
-out:
-       mutex_unlock(&gspca_dev->queue_lock);
-       return ret;
-}
-
-static int vidioc_g_jpegcomp(struct file *file, void *priv,
-                       struct v4l2_jpegcompression *jpegcomp)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-
-       gspca_dev->usb_err = 0;
-       return gspca_dev->sd_desc->get_jcomp(gspca_dev, jpegcomp);
-}
-
-static int vidioc_s_jpegcomp(struct file *file, void *priv,
-                       struct v4l2_jpegcompression *jpegcomp)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-
-       gspca_dev->usb_err = 0;
-       return gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp);
-}
-
-static int vidioc_g_parm(struct file *filp, void *priv,
-                       struct v4l2_streamparm *parm)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(filp);
-
-       parm->parm.capture.readbuffers = gspca_dev->nbufread;
-
-       if (gspca_dev->sd_desc->get_streamparm) {
-               gspca_dev->usb_err = 0;
-               gspca_dev->sd_desc->get_streamparm(gspca_dev, parm);
-               return gspca_dev->usb_err;
-       }
-       return 0;
-}
-
-static int vidioc_s_parm(struct file *filp, void *priv,
-                       struct v4l2_streamparm *parm)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(filp);
-       int n;
-
-       n = parm->parm.capture.readbuffers;
-       if (n == 0 || n >= GSPCA_MAX_FRAMES)
-               parm->parm.capture.readbuffers = gspca_dev->nbufread;
-       else
-               gspca_dev->nbufread = n;
-
-       if (gspca_dev->sd_desc->set_streamparm) {
-               gspca_dev->usb_err = 0;
-               gspca_dev->sd_desc->set_streamparm(gspca_dev, parm);
-               return gspca_dev->usb_err;
-       }
-
-       return 0;
-}
-
-static int dev_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       struct gspca_frame *frame;
-       struct page *page;
-       unsigned long addr, start, size;
-       int i, ret;
-
-       start = vma->vm_start;
-       size = vma->vm_end - vma->vm_start;
-       PDEBUG(D_STREAM, "mmap start:%08x size:%d", (int) start, (int) size);
-
-       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
-               return -ERESTARTSYS;
-       if (gspca_dev->capt_file != file) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       frame = NULL;
-       for (i = 0; i < gspca_dev->nframes; ++i) {
-               if (gspca_dev->frame[i].v4l2_buf.memory != V4L2_MEMORY_MMAP) {
-                       PDEBUG(D_STREAM, "mmap bad memory type");
-                       break;
-               }
-               if ((gspca_dev->frame[i].v4l2_buf.m.offset >> PAGE_SHIFT)
-                                               == vma->vm_pgoff) {
-                       frame = &gspca_dev->frame[i];
-                       break;
-               }
-       }
-       if (frame == NULL) {
-               PDEBUG(D_STREAM, "mmap no frame buffer found");
-               ret = -EINVAL;
-               goto out;
-       }
-       if (size != frame->v4l2_buf.length) {
-               PDEBUG(D_STREAM, "mmap bad size");
-               ret = -EINVAL;
-               goto out;
-       }
-
-       /*
-        * - VM_IO marks the area as being a mmaped region for I/O to a
-        *   device. It also prevents the region from being core dumped.
-        */
-       vma->vm_flags |= VM_IO;
-
-       addr = (unsigned long) frame->data;
-       while (size > 0) {
-               page = vmalloc_to_page((void *) addr);
-               ret = vm_insert_page(vma, start, page);
-               if (ret < 0)
-                       goto out;
-               start += PAGE_SIZE;
-               addr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-
-       vma->vm_ops = &gspca_vm_ops;
-       vma->vm_private_data = frame;
-       gspca_vm_open(vma);
-       ret = 0;
-out:
-       mutex_unlock(&gspca_dev->queue_lock);
-       return ret;
-}
-
-static int frame_ready_nolock(struct gspca_dev *gspca_dev, struct file *file,
-                               enum v4l2_memory memory)
-{
-       if (!gspca_dev->present)
-               return -ENODEV;
-       if (gspca_dev->capt_file != file || gspca_dev->memory != memory ||
-                       !gspca_dev->streaming)
-               return -EINVAL;
-
-       /* check if a frame is ready */
-       return gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i);
-}
-
-static int frame_ready(struct gspca_dev *gspca_dev, struct file *file,
-                       enum v4l2_memory memory)
-{
-       int ret;
-
-       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
-               return -ERESTARTSYS;
-       ret = frame_ready_nolock(gspca_dev, file, memory);
-       mutex_unlock(&gspca_dev->queue_lock);
-       return ret;
-}
-
-/*
- * dequeue a video buffer
- *
- * If nonblock_ing is false, block until a buffer is available.
- */
-static int vidioc_dqbuf(struct file *file, void *priv,
-                       struct v4l2_buffer *v4l2_buf)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       struct gspca_frame *frame;
-       int i, j, ret;
-
-       PDEBUG(D_FRAM, "dqbuf");
-
-       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
-               return -ERESTARTSYS;
-
-       for (;;) {
-               ret = frame_ready_nolock(gspca_dev, file, v4l2_buf->memory);
-               if (ret < 0)
-                       goto out;
-               if (ret > 0)
-                       break;
-
-               mutex_unlock(&gspca_dev->queue_lock);
-
-               if (file->f_flags & O_NONBLOCK)
-                       return -EAGAIN;
-
-               /* wait till a frame is ready */
-               ret = wait_event_interruptible_timeout(gspca_dev->wq,
-                       frame_ready(gspca_dev, file, v4l2_buf->memory),
-                       msecs_to_jiffies(3000));
-               if (ret < 0)
-                       return ret;
-               if (ret == 0)
-                       return -EIO;
-
-               if (mutex_lock_interruptible(&gspca_dev->queue_lock))
-                       return -ERESTARTSYS;
-       }
-
-       i = gspca_dev->fr_o;
-       j = gspca_dev->fr_queue[i];
-       frame = &gspca_dev->frame[j];
-
-       gspca_dev->fr_o = (i + 1) % GSPCA_MAX_FRAMES;
-
-       frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
-       memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
-       PDEBUG(D_FRAM, "dqbuf %d", j);
-       ret = 0;
-
-       if (gspca_dev->memory == V4L2_MEMORY_USERPTR) {
-               if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr,
-                                frame->data,
-                                frame->v4l2_buf.bytesused)) {
-                       PDEBUG(D_ERR|D_STREAM,
-                               "dqbuf cp to user failed");
-                       ret = -EFAULT;
-               }
-       }
-out:
-       mutex_unlock(&gspca_dev->queue_lock);
-
-       if (ret == 0 && gspca_dev->sd_desc->dq_callback) {
-               mutex_lock(&gspca_dev->usb_lock);
-               gspca_dev->usb_err = 0;
-               if (gspca_dev->present)
-                       gspca_dev->sd_desc->dq_callback(gspca_dev);
-               mutex_unlock(&gspca_dev->usb_lock);
-       }
-
-       return ret;
-}
-
-/*
- * queue a video buffer
- *
- * Attempting to queue a buffer that has already been
- * queued will return -EINVAL.
- */
-static int vidioc_qbuf(struct file *file, void *priv,
-                       struct v4l2_buffer *v4l2_buf)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       struct gspca_frame *frame;
-       int i, index, ret;
-
-       PDEBUG(D_FRAM, "qbuf %d", v4l2_buf->index);
-
-       if (mutex_lock_interruptible(&gspca_dev->queue_lock))
-               return -ERESTARTSYS;
-
-       index = v4l2_buf->index;
-       if ((unsigned) index >= gspca_dev->nframes) {
-               PDEBUG(D_FRAM,
-                       "qbuf idx %d >= %d", index, gspca_dev->nframes);
-               ret = -EINVAL;
-               goto out;
-       }
-       if (v4l2_buf->memory != gspca_dev->memory) {
-               PDEBUG(D_FRAM, "qbuf bad memory type");
-               ret = -EINVAL;
-               goto out;
-       }
-
-       frame = &gspca_dev->frame[index];
-       if (frame->v4l2_buf.flags & BUF_ALL_FLAGS) {
-               PDEBUG(D_FRAM, "qbuf bad state");
-               ret = -EINVAL;
-               goto out;
-       }
-
-       frame->v4l2_buf.flags |= V4L2_BUF_FLAG_QUEUED;
-
-       if (frame->v4l2_buf.memory == V4L2_MEMORY_USERPTR) {
-               frame->v4l2_buf.m.userptr = v4l2_buf->m.userptr;
-               frame->v4l2_buf.length = v4l2_buf->length;
-       }
-
-       /* put the buffer in the 'queued' queue */
-       i = atomic_read(&gspca_dev->fr_q);
-       gspca_dev->fr_queue[i] = index;
-       atomic_set(&gspca_dev->fr_q, (i + 1) % GSPCA_MAX_FRAMES);
-
-       v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
-       v4l2_buf->flags &= ~V4L2_BUF_FLAG_DONE;
-       ret = 0;
-out:
-       mutex_unlock(&gspca_dev->queue_lock);
-       return ret;
-}
-
-/*
- * allocate the resources for read()
- */
-static int read_alloc(struct gspca_dev *gspca_dev,
-                       struct file *file)
-{
-       struct v4l2_buffer v4l2_buf;
-       int i, ret;
-
-       PDEBUG(D_STREAM, "read alloc");
-
-       if (mutex_lock_interruptible(&gspca_dev->usb_lock))
-               return -ERESTARTSYS;
-
-       if (gspca_dev->nframes == 0) {
-               struct v4l2_requestbuffers rb;
-
-               memset(&rb, 0, sizeof rb);
-               rb.count = gspca_dev->nbufread;
-               rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               rb.memory = GSPCA_MEMORY_READ;
-               ret = vidioc_reqbufs(file, gspca_dev, &rb);
-               if (ret != 0) {
-                       PDEBUG(D_STREAM, "read reqbuf err %d", ret);
-                       goto out;
-               }
-               memset(&v4l2_buf, 0, sizeof v4l2_buf);
-               v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               v4l2_buf.memory = GSPCA_MEMORY_READ;
-               for (i = 0; i < gspca_dev->nbufread; i++) {
-                       v4l2_buf.index = i;
-                       ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
-                       if (ret != 0) {
-                               PDEBUG(D_STREAM, "read qbuf err: %d", ret);
-                               goto out;
-                       }
-               }
-       }
-
-       /* start streaming */
-       ret = vidioc_streamon(file, gspca_dev, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-       if (ret != 0)
-               PDEBUG(D_STREAM, "read streamon err %d", ret);
-out:
-       mutex_unlock(&gspca_dev->usb_lock);
-       return ret;
-}
-
-static unsigned int dev_poll(struct file *file, poll_table *wait)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       unsigned long req_events = poll_requested_events(wait);
-       int ret = 0;
-
-       PDEBUG(D_FRAM, "poll");
-
-       if (req_events & POLLPRI)
-               ret |= v4l2_ctrl_poll(file, wait);
-
-       if (req_events & (POLLIN | POLLRDNORM)) {
-               /* if reqbufs is not done, the user would use read() */
-               if (gspca_dev->memory == GSPCA_MEMORY_NO) {
-                       if (read_alloc(gspca_dev, file) != 0) {
-                               ret |= POLLERR;
-                               goto out;
-                       }
-               }
-
-               poll_wait(file, &gspca_dev->wq, wait);
-
-               /* check if an image has been received */
-               if (mutex_lock_interruptible(&gspca_dev->queue_lock) != 0) {
-                       ret |= POLLERR;
-                       goto out;
-               }
-               if (gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i))
-                       ret |= POLLIN | POLLRDNORM;
-               mutex_unlock(&gspca_dev->queue_lock);
-       }
-
-out:
-       if (!gspca_dev->present)
-               ret |= POLLHUP;
-
-       return ret;
-}
-
-static ssize_t dev_read(struct file *file, char __user *data,
-                   size_t count, loff_t *ppos)
-{
-       struct gspca_dev *gspca_dev = video_drvdata(file);
-       struct gspca_frame *frame;
-       struct v4l2_buffer v4l2_buf;
-       struct timeval timestamp;
-       int n, ret, ret2;
-
-       PDEBUG(D_FRAM, "read (%zd)", count);
-       if (gspca_dev->memory == GSPCA_MEMORY_NO) { /* first time ? */
-               ret = read_alloc(gspca_dev, file);
-               if (ret != 0)
-                       return ret;
-       }
-
-       /* get a frame */
-       timestamp = ktime_to_timeval(ktime_get());
-       timestamp.tv_sec--;
-       n = 2;
-       for (;;) {
-               memset(&v4l2_buf, 0, sizeof v4l2_buf);
-               v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               v4l2_buf.memory = GSPCA_MEMORY_READ;
-               ret = vidioc_dqbuf(file, gspca_dev, &v4l2_buf);
-               if (ret != 0) {
-                       PDEBUG(D_STREAM, "read dqbuf err %d", ret);
-                       return ret;
-               }
-
-               /* if the process slept for more than 1 second,
-                * get a newer frame */
-               frame = &gspca_dev->frame[v4l2_buf.index];
-               if (--n < 0)
-                       break;                  /* avoid infinite loop */
-               if (frame->v4l2_buf.timestamp.tv_sec >= timestamp.tv_sec)
-                       break;
-               ret = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
-               if (ret != 0) {
-                       PDEBUG(D_STREAM, "read qbuf err %d", ret);
-                       return ret;
-               }
-       }
-
-       /* copy the frame */
-       if (count > frame->v4l2_buf.bytesused)
-               count = frame->v4l2_buf.bytesused;
-       ret = copy_to_user(data, frame->data, count);
-       if (ret != 0) {
-               PDEBUG(D_ERR|D_STREAM,
-                       "read cp to user lack %d / %zd", ret, count);
-               ret = -EFAULT;
-               goto out;
-       }
-       ret = count;
-out:
-       /* in each case, requeue the buffer */
-       ret2 = vidioc_qbuf(file, gspca_dev, &v4l2_buf);
-       if (ret2 != 0)
-               return ret2;
-       return ret;
-}
-
-static struct v4l2_file_operations dev_fops = {
-       .owner = THIS_MODULE,
-       .open = dev_open,
-       .release = dev_close,
-       .read = dev_read,
-       .mmap = dev_mmap,
-       .unlocked_ioctl = video_ioctl2,
-       .poll   = dev_poll,
-};
-
-static const struct v4l2_ioctl_ops dev_ioctl_ops = {
-       .vidioc_querycap        = vidioc_querycap,
-       .vidioc_dqbuf           = vidioc_dqbuf,
-       .vidioc_qbuf            = vidioc_qbuf,
-       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap   = vidioc_g_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap   = vidioc_s_fmt_vid_cap,
-       .vidioc_streamon        = vidioc_streamon,
-       .vidioc_queryctrl       = vidioc_queryctrl,
-       .vidioc_g_ctrl          = vidioc_g_ctrl,
-       .vidioc_s_ctrl          = vidioc_s_ctrl,
-       .vidioc_querymenu       = vidioc_querymenu,
-       .vidioc_enum_input      = vidioc_enum_input,
-       .vidioc_g_input         = vidioc_g_input,
-       .vidioc_s_input         = vidioc_s_input,
-       .vidioc_reqbufs         = vidioc_reqbufs,
-       .vidioc_querybuf        = vidioc_querybuf,
-       .vidioc_streamoff       = vidioc_streamoff,
-       .vidioc_g_jpegcomp      = vidioc_g_jpegcomp,
-       .vidioc_s_jpegcomp      = vidioc_s_jpegcomp,
-       .vidioc_g_parm          = vidioc_g_parm,
-       .vidioc_s_parm          = vidioc_s_parm,
-       .vidioc_enum_framesizes = vidioc_enum_framesizes,
-       .vidioc_enum_frameintervals = vidioc_enum_frameintervals,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register      = vidioc_g_register,
-       .vidioc_s_register      = vidioc_s_register,
-#endif
-       .vidioc_g_chip_ident    = vidioc_g_chip_ident,
-       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
-       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-static const struct video_device gspca_template = {
-       .name = "gspca main driver",
-       .fops = &dev_fops,
-       .ioctl_ops = &dev_ioctl_ops,
-       .release = video_device_release_empty, /* We use v4l2_dev.release */
-};
-
-/* initialize the controls */
-static void ctrls_init(struct gspca_dev *gspca_dev)
-{
-       struct gspca_ctrl *ctrl;
-       int i;
-
-       for (i = 0, ctrl = gspca_dev->cam.ctrls;
-            i < gspca_dev->sd_desc->nctrls;
-            i++, ctrl++) {
-               ctrl->def = gspca_dev->sd_desc->ctrls[i].qctrl.default_value;
-               ctrl->val = ctrl->def;
-               ctrl->min = gspca_dev->sd_desc->ctrls[i].qctrl.minimum;
-               ctrl->max = gspca_dev->sd_desc->ctrls[i].qctrl.maximum;
-       }
-}
-
-/*
- * probe and create a new gspca device
- *
- * This function must be called by the sub-driver when it is
- * called for probing a new device.
- */
-int gspca_dev_probe2(struct usb_interface *intf,
-               const struct usb_device_id *id,
-               const struct sd_desc *sd_desc,
-               int dev_size,
-               struct module *module)
-{
-       struct gspca_dev *gspca_dev;
-       struct usb_device *dev = interface_to_usbdev(intf);
-       int ret;
-
-       pr_info("%s-" GSPCA_VERSION " probing %04x:%04x\n",
-               sd_desc->name, id->idVendor, id->idProduct);
-
-       /* create the device */
-       if (dev_size < sizeof *gspca_dev)
-               dev_size = sizeof *gspca_dev;
-       gspca_dev = kzalloc(dev_size, GFP_KERNEL);
-       if (!gspca_dev) {
-               pr_err("couldn't kzalloc gspca struct\n");
-               return -ENOMEM;
-       }
-       gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL);
-       if (!gspca_dev->usb_buf) {
-               pr_err("out of memory\n");
-               ret = -ENOMEM;
-               goto out;
-       }
-       gspca_dev->dev = dev;
-       gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber;
-
-       /* check if any audio device */
-       if (dev->actconfig->desc.bNumInterfaces != 1) {
-               int i;
-               struct usb_interface *intf2;
-
-               for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
-                       intf2 = dev->actconfig->interface[i];
-                       if (intf2 != NULL
-                        && intf2->altsetting != NULL
-                        && intf2->altsetting->desc.bInterfaceClass ==
-                                        USB_CLASS_AUDIO) {
-                               gspca_dev->audio = 1;
-                               break;
-                       }
-               }
-       }
-
-       gspca_dev->v4l2_dev.release = gspca_release;
-       ret = v4l2_device_register(&intf->dev, &gspca_dev->v4l2_dev);
-       if (ret)
-               goto out;
-       gspca_dev->sd_desc = sd_desc;
-       gspca_dev->nbufread = 2;
-       gspca_dev->empty_packet = -1;   /* don't check the empty packets */
-       gspca_dev->vdev = gspca_template;
-       gspca_dev->vdev.v4l2_dev = &gspca_dev->v4l2_dev;
-       video_set_drvdata(&gspca_dev->vdev, gspca_dev);
-       set_bit(V4L2_FL_USE_FH_PRIO, &gspca_dev->vdev.flags);
-       gspca_dev->module = module;
-       gspca_dev->present = 1;
-
-       mutex_init(&gspca_dev->usb_lock);
-       gspca_dev->vdev.lock = &gspca_dev->usb_lock;
-       mutex_init(&gspca_dev->queue_lock);
-       init_waitqueue_head(&gspca_dev->wq);
-
-       /* configure the subdriver and initialize the USB device */
-       ret = sd_desc->config(gspca_dev, id);
-       if (ret < 0)
-               goto out;
-       if (gspca_dev->cam.ctrls != NULL)
-               ctrls_init(gspca_dev);
-       ret = sd_desc->init(gspca_dev);
-       if (ret < 0)
-               goto out;
-       if (sd_desc->init_controls)
-               ret = sd_desc->init_controls(gspca_dev);
-       if (ret < 0)
-               goto out;
-       gspca_set_default_mode(gspca_dev);
-
-       ret = gspca_input_connect(gspca_dev);
-       if (ret)
-               goto out;
-
-       /*
-        * Don't take usb_lock for these ioctls. This improves latency if
-        * usb_lock is taken for a long time, e.g. when changing a control
-        * value, and a new frame is ready to be dequeued.
-        */
-       v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_DQBUF);
-       v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_QBUF);
-       v4l2_disable_ioctl_locking(&gspca_dev->vdev, VIDIOC_QUERYBUF);
-       if (!gspca_dev->sd_desc->get_chip_ident)
-               v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_G_CHIP_IDENT);
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       if (!gspca_dev->sd_desc->get_chip_ident ||
-           !gspca_dev->sd_desc->get_register)
-               v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_G_REGISTER);
-       if (!gspca_dev->sd_desc->get_chip_ident ||
-           !gspca_dev->sd_desc->set_register)
-               v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_DBG_S_REGISTER);
-#endif
-       if (!gspca_dev->sd_desc->get_jcomp)
-               v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_G_JPEGCOMP);
-       if (!gspca_dev->sd_desc->set_jcomp)
-               v4l2_disable_ioctl(&gspca_dev->vdev, VIDIOC_S_JPEGCOMP);
-
-       /* init video stuff */
-       ret = video_register_device(&gspca_dev->vdev,
-                                 VFL_TYPE_GRABBER,
-                                 -1);
-       if (ret < 0) {
-               pr_err("video_register_device err %d\n", ret);
-               goto out;
-       }
-
-       usb_set_intfdata(intf, gspca_dev);
-       PDEBUG(D_PROBE, "%s created", video_device_node_name(&gspca_dev->vdev));
-
-       gspca_input_create_urb(gspca_dev);
-
-       return 0;
-out:
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       if (gspca_dev->input_dev)
-               input_unregister_device(gspca_dev->input_dev);
-#endif
-       v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler);
-       kfree(gspca_dev->usb_buf);
-       kfree(gspca_dev);
-       return ret;
-}
-EXPORT_SYMBOL(gspca_dev_probe2);
-
-/* same function as the previous one, but check the interface */
-int gspca_dev_probe(struct usb_interface *intf,
-               const struct usb_device_id *id,
-               const struct sd_desc *sd_desc,
-               int dev_size,
-               struct module *module)
-{
-       struct usb_device *dev = interface_to_usbdev(intf);
-
-       /* we don't handle multi-config cameras */
-       if (dev->descriptor.bNumConfigurations != 1) {
-               pr_err("%04x:%04x too many config\n",
-                      id->idVendor, id->idProduct);
-               return -ENODEV;
-       }
-
-       /* the USB video interface must be the first one */
-       if (dev->actconfig->desc.bNumInterfaces != 1
-        && intf->cur_altsetting->desc.bInterfaceNumber != 0)
-               return -ENODEV;
-
-       return gspca_dev_probe2(intf, id, sd_desc, dev_size, module);
-}
-EXPORT_SYMBOL(gspca_dev_probe);
-
-/*
- * USB disconnection
- *
- * This function must be called by the sub-driver
- * when the device disconnects, after the specific resources are freed.
- */
-void gspca_disconnect(struct usb_interface *intf)
-{
-       struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       struct input_dev *input_dev;
-#endif
-
-       PDEBUG(D_PROBE, "%s disconnect",
-               video_device_node_name(&gspca_dev->vdev));
-
-       mutex_lock(&gspca_dev->usb_lock);
-
-       usb_set_intfdata(intf, NULL);
-       gspca_dev->dev = NULL;
-       gspca_dev->present = 0;
-       destroy_urbs(gspca_dev);
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       gspca_input_destroy_urb(gspca_dev);
-       input_dev = gspca_dev->input_dev;
-       if (input_dev) {
-               gspca_dev->input_dev = NULL;
-               input_unregister_device(input_dev);
-       }
-#endif
-       /* Free subdriver's streaming resources / stop sd workqueue(s) */
-       if (gspca_dev->sd_desc->stop0 && gspca_dev->streaming)
-               gspca_dev->sd_desc->stop0(gspca_dev);
-       gspca_dev->streaming = 0;
-       wake_up_interruptible(&gspca_dev->wq);
-
-       v4l2_device_disconnect(&gspca_dev->v4l2_dev);
-       video_unregister_device(&gspca_dev->vdev);
-
-       mutex_unlock(&gspca_dev->usb_lock);
-
-       /* (this will call gspca_release() immediately or on last close) */
-       v4l2_device_put(&gspca_dev->v4l2_dev);
-}
-EXPORT_SYMBOL(gspca_disconnect);
-
-#ifdef CONFIG_PM
-int gspca_suspend(struct usb_interface *intf, pm_message_t message)
-{
-       struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
-
-       if (!gspca_dev->streaming)
-               return 0;
-       mutex_lock(&gspca_dev->usb_lock);
-       gspca_dev->frozen = 1;          /* avoid urb error messages */
-       gspca_dev->usb_err = 0;
-       if (gspca_dev->sd_desc->stopN)
-               gspca_dev->sd_desc->stopN(gspca_dev);
-       destroy_urbs(gspca_dev);
-       gspca_input_destroy_urb(gspca_dev);
-       gspca_set_alt0(gspca_dev);
-       if (gspca_dev->sd_desc->stop0)
-               gspca_dev->sd_desc->stop0(gspca_dev);
-       mutex_unlock(&gspca_dev->usb_lock);
-       return 0;
-}
-EXPORT_SYMBOL(gspca_suspend);
-
-int gspca_resume(struct usb_interface *intf)
-{
-       struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
-       int streaming, ret = 0;
-
-       mutex_lock(&gspca_dev->usb_lock);
-       gspca_dev->frozen = 0;
-       gspca_dev->usb_err = 0;
-       gspca_dev->sd_desc->init(gspca_dev);
-       gspca_input_create_urb(gspca_dev);
-       /*
-        * Most subdrivers send all ctrl values on sd_start and thus
-        * only write to the device registers on s_ctrl when streaming ->
-        * Clear streaming to avoid setting all ctrls twice.
-        */
-       streaming = gspca_dev->streaming;
-       gspca_dev->streaming = 0;
-       if (streaming)
-               ret = gspca_init_transfer(gspca_dev);
-       mutex_unlock(&gspca_dev->usb_lock);
-       return ret;
-}
-EXPORT_SYMBOL(gspca_resume);
-#endif
-
-/* -- module insert / remove -- */
-static int __init gspca_init(void)
-{
-       pr_info("v" GSPCA_VERSION " registered\n");
-       return 0;
-}
-static void __exit gspca_exit(void)
-{
-}
-
-module_init(gspca_init);
-module_exit(gspca_exit);
-
-#ifdef GSPCA_DEBUG
-module_param_named(debug, gspca_debug, int, 0644);
-MODULE_PARM_DESC(debug,
-               "Debug (bit) 0x01:error 0x02:probe 0x04:config"
-               " 0x08:stream 0x10:frame 0x20:packet"
-               " 0x0100: v4l2");
-#endif
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
deleted file mode 100644 (file)
index dc688c7..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-#ifndef GSPCAV2_H
-#define GSPCAV2_H
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <linux/mutex.h>
-
-/* compilation option */
-/*#define GSPCA_DEBUG 1*/
-
-#ifdef GSPCA_DEBUG
-/* GSPCA our debug messages */
-extern int gspca_debug;
-#define PDEBUG(level, fmt, ...)                                        \
-do {                                                           \
-       if (gspca_debug & (level))                              \
-               pr_info(fmt, ##__VA_ARGS__);                    \
-} while (0)
-
-#define D_ERR  0x01
-#define D_PROBE 0x02
-#define D_CONF 0x04
-#define D_STREAM 0x08
-#define D_FRAM 0x10
-#define D_PACK 0x20
-#define D_USBI 0x00
-#define D_USBO 0x00
-#define D_V4L2 0x0100
-#else
-#define PDEBUG(level, fmt, ...)
-#endif
-
-#define GSPCA_MAX_FRAMES 16    /* maximum number of video frame buffers */
-/* image transfers */
-#define MAX_NURBS 4            /* max number of URBs */
-
-
-/* used to list framerates supported by a camera mode (resolution) */
-struct framerates {
-       const u8 *rates;
-       int nrates;
-};
-
-/* control definition */
-struct gspca_ctrl {
-       s16 val;        /* current value */
-       s16 def;        /* default value */
-       s16 min, max;   /* minimum and maximum values */
-};
-
-/* device information - set at probe time */
-struct cam {
-       const struct v4l2_pix_format *cam_mode; /* size nmodes */
-       const struct framerates *mode_framerates; /* must have size nmodes,
-                                                  * just like cam_mode */
-       struct gspca_ctrl *ctrls;       /* control table - size nctrls */
-                                       /* may be NULL */
-       u32 bulk_size;          /* buffer size when image transfer by bulk */
-       u32 input_flags;        /* value for ENUM_INPUT status flags */
-       u8 nmodes;              /* size of cam_mode */
-       u8 no_urb_create;       /* don't create transfer URBs */
-       u8 bulk_nurbs;          /* number of URBs in bulk mode
-                                * - cannot be > MAX_NURBS
-                                * - when 0 and bulk_size != 0 means
-                                *   1 URB and submit done by subdriver */
-       u8 bulk;                /* image transfer by 0:isoc / 1:bulk */
-       u8 npkt;                /* number of packets in an ISOC message
-                                * 0 is the default value: 32 packets */
-       u8 needs_full_bandwidth;/* Set this flag to notify the bandwidth calc.
-                                * code that the cam fills all image buffers to
-                                * the max, even when using compression. */
-};
-
-struct gspca_dev;
-struct gspca_frame;
-
-/* subdriver operations */
-typedef int (*cam_op) (struct gspca_dev *);
-typedef void (*cam_v_op) (struct gspca_dev *);
-typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *);
-typedef int (*cam_jpg_op) (struct gspca_dev *,
-                               struct v4l2_jpegcompression *);
-typedef int (*cam_reg_op) (struct gspca_dev *,
-                               struct v4l2_dbg_register *);
-typedef int (*cam_ident_op) (struct gspca_dev *,
-                               struct v4l2_dbg_chip_ident *);
-typedef void (*cam_streamparm_op) (struct gspca_dev *,
-                                 struct v4l2_streamparm *);
-typedef int (*cam_qmnu_op) (struct gspca_dev *,
-                       struct v4l2_querymenu *);
-typedef void (*cam_pkt_op) (struct gspca_dev *gspca_dev,
-                               u8 *data,
-                               int len);
-typedef int (*cam_int_pkt_op) (struct gspca_dev *gspca_dev,
-                               u8 *data,
-                               int len);
-
-struct ctrl {
-       struct v4l2_queryctrl qctrl;
-       int (*set)(struct gspca_dev *, __s32);
-       int (*get)(struct gspca_dev *, __s32 *);
-       cam_v_op set_control;
-};
-
-/* subdriver description */
-struct sd_desc {
-/* information */
-       const char *name;       /* sub-driver name */
-/* controls */
-       const struct ctrl *ctrls;       /* static control definition */
-       int nctrls;
-/* mandatory operations */
-       cam_cf_op config;       /* called on probe */
-       cam_op init;            /* called on probe and resume */
-       cam_op init_controls;   /* called on probe */
-       cam_op start;           /* called on stream on after URBs creation */
-       cam_pkt_op pkt_scan;
-/* optional operations */
-       cam_op isoc_init;       /* called on stream on before getting the EP */
-       cam_op isoc_nego;       /* called when URB submit failed with NOSPC */
-       cam_v_op stopN;         /* called on stream off - main alt */
-       cam_v_op stop0;         /* called on stream off & disconnect - alt 0 */
-       cam_v_op dq_callback;   /* called when a frame has been dequeued */
-       cam_jpg_op get_jcomp;
-       cam_jpg_op set_jcomp;
-       cam_qmnu_op querymenu;
-       cam_streamparm_op get_streamparm;
-       cam_streamparm_op set_streamparm;
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       cam_reg_op set_register;
-       cam_reg_op get_register;
-#endif
-       cam_ident_op get_chip_ident;
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       cam_int_pkt_op int_pkt_scan;
-       /* other_input makes the gspca core create gspca_dev->input even when
-          int_pkt_scan is NULL, for cams with non interrupt driven buttons */
-       u8 other_input;
-#endif
-};
-
-/* packet types when moving from iso buf to frame buf */
-enum gspca_packet_type {
-       DISCARD_PACKET,
-       FIRST_PACKET,
-       INTER_PACKET,
-       LAST_PACKET
-};
-
-struct gspca_frame {
-       __u8 *data;                     /* frame buffer */
-       int vma_use_count;
-       struct v4l2_buffer v4l2_buf;
-};
-
-struct gspca_dev {
-       struct video_device vdev;       /* !! must be the first item */
-       struct module *module;          /* subdriver handling the device */
-       struct v4l2_device v4l2_dev;
-       struct usb_device *dev;
-       struct file *capt_file;         /* file doing video capture */
-                                       /* protected by queue_lock */
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       struct input_dev *input_dev;
-       char phys[64];                  /* physical device path */
-#endif
-
-       struct cam cam;                         /* device information */
-       const struct sd_desc *sd_desc;          /* subdriver description */
-       unsigned ctrl_dis;              /* disabled controls (bit map) */
-       unsigned ctrl_inac;             /* inactive controls (bit map) */
-       struct v4l2_ctrl_handler ctrl_handler;
-
-       /* autogain and exposure or gain control cluster, these are global as
-          the autogain/exposure functions in autogain_functions.c use them */
-       struct {
-               struct v4l2_ctrl *autogain;
-               struct v4l2_ctrl *exposure;
-               struct v4l2_ctrl *gain;
-               int exp_too_low_cnt, exp_too_high_cnt;
-       };
-
-#define USB_BUF_SZ 64
-       __u8 *usb_buf;                          /* buffer for USB exchanges */
-       struct urb *urb[MAX_NURBS];
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       struct urb *int_urb;
-#endif
-
-       __u8 *frbuf;                            /* buffer for nframes */
-       struct gspca_frame frame[GSPCA_MAX_FRAMES];
-       u8 *image;                              /* image beeing filled */
-       __u32 frsz;                             /* frame size */
-       u32 image_len;                          /* current length of image */
-       atomic_t fr_q;                          /* next frame to queue */
-       atomic_t fr_i;                          /* frame being filled */
-       signed char fr_queue[GSPCA_MAX_FRAMES]; /* frame queue */
-       char nframes;                           /* number of frames */
-       u8 fr_o;                                /* next frame to dequeue */
-       __u8 last_packet_type;
-       __s8 empty_packet;              /* if (-1) don't check empty packets */
-       __u8 streaming;                 /* protected by both mutexes (*) */
-
-       __u8 curr_mode;                 /* current camera mode */
-       __u32 pixfmt;                   /* current mode parameters */
-       __u16 width;
-       __u16 height;
-       __u32 sequence;                 /* frame sequence number */
-
-       wait_queue_head_t wq;           /* wait queue */
-       struct mutex usb_lock;          /* usb exchange protection */
-       struct mutex queue_lock;        /* ISOC queue protection */
-       int usb_err;                    /* USB error - protected by usb_lock */
-       u16 pkt_size;                   /* ISOC packet size */
-#ifdef CONFIG_PM
-       char frozen;                    /* suspend - resume */
-#endif
-       char present;                   /* device connected */
-       char nbufread;                  /* number of buffers for read() */
-       char memory;                    /* memory type (V4L2_MEMORY_xxx) */
-       __u8 iface;                     /* USB interface number */
-       __u8 alt;                       /* USB alternate setting */
-       u8 audio;                       /* presence of audio device */
-
-       /* (*) These variables are proteced by both usb_lock and queue_lock,
-          that is any code setting them is holding *both*, which means that
-          any code getting them needs to hold at least one of them */
-};
-
-int gspca_dev_probe(struct usb_interface *intf,
-               const struct usb_device_id *id,
-               const struct sd_desc *sd_desc,
-               int dev_size,
-               struct module *module);
-int gspca_dev_probe2(struct usb_interface *intf,
-               const struct usb_device_id *id,
-               const struct sd_desc *sd_desc,
-               int dev_size,
-               struct module *module);
-void gspca_disconnect(struct usb_interface *intf);
-void gspca_frame_add(struct gspca_dev *gspca_dev,
-                       enum gspca_packet_type packet_type,
-                       const u8 *data,
-                       int len);
-#ifdef CONFIG_PM
-int gspca_suspend(struct usb_interface *intf, pm_message_t message);
-int gspca_resume(struct usb_interface *intf);
-#endif
-int gspca_expo_autogain(struct gspca_dev *gspca_dev, int avg_lum,
-       int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee);
-int gspca_coarse_grained_expo_autogain(struct gspca_dev *gspca_dev,
-        int avg_lum, int desired_avg_lum, int deadzone);
-
-#endif /* GSPCAV2_H */
diff --git a/drivers/media/video/gspca/jeilinj.c b/drivers/media/video/gspca/jeilinj.c
deleted file mode 100644 (file)
index 26b9931..0000000
+++ /dev/null
@@ -1,548 +0,0 @@
-/*
- * Jeilinj subdriver
- *
- * Supports some Jeilin dual-mode cameras which use bulk transport and
- * download raw JPEG data.
- *
- * Copyright (C) 2009 Theodore Kilgore
- *
- * Sportscam DV15 support and control settings are
- * Copyright (C) 2011 Patrice Chotard
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "jeilinj"
-
-#include <linux/slab.h>
-#include "gspca.h"
-#include "jpeg.h"
-
-MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
-MODULE_DESCRIPTION("GSPCA/JEILINJ USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* Default timeouts, in ms */
-#define JEILINJ_CMD_TIMEOUT 500
-#define JEILINJ_CMD_DELAY 160
-#define JEILINJ_DATA_TIMEOUT 1000
-
-/* Maximum transfer size to use. */
-#define JEILINJ_MAX_TRANSFER 0x200
-#define FRAME_HEADER_LEN 0x10
-#define FRAME_START 0xFFFFFFFF
-
-enum {
-       SAKAR_57379,
-       SPORTSCAM_DV15,
-};
-
-#define CAMQUALITY_MIN 0       /* highest cam quality */
-#define CAMQUALITY_MAX 97      /* lowest cam quality  */
-
-/* Structure to hold all of our device specific stuff */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-       int blocks_left;
-       const struct v4l2_pix_format *cap_mode;
-       struct v4l2_ctrl *freq;
-       struct v4l2_ctrl *jpegqual;
-       /* Driver stuff */
-       u8 type;
-       u8 quality;                              /* image quality */
-#define QUALITY_MIN 35
-#define QUALITY_MAX 85
-#define QUALITY_DEF 85
-       u8 jpeg_hdr[JPEG_HDR_SZ];
-};
-
-struct jlj_command {
-       unsigned char instruction[2];
-       unsigned char ack_wanted;
-       unsigned char delay;
-};
-
-/* AFAICT these cameras will only do 320x240. */
-static struct v4l2_pix_format jlj_mode[] = {
-       { 320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-       { 640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0}
-};
-
-/*
- * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
- * and 0x82 for bulk transfer.
- */
-
-/* All commands are two bytes only */
-static void jlj_write2(struct gspca_dev *gspca_dev, unsigned char *command)
-{
-       int retval;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       memcpy(gspca_dev->usb_buf, command, 2);
-       retval = usb_bulk_msg(gspca_dev->dev,
-                       usb_sndbulkpipe(gspca_dev->dev, 3),
-                       gspca_dev->usb_buf, 2, NULL, 500);
-       if (retval < 0) {
-               pr_err("command write [%02x] error %d\n",
-                      gspca_dev->usb_buf[0], retval);
-               gspca_dev->usb_err = retval;
-       }
-}
-
-/* Responses are one byte only */
-static void jlj_read1(struct gspca_dev *gspca_dev, unsigned char response)
-{
-       int retval;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       retval = usb_bulk_msg(gspca_dev->dev,
-       usb_rcvbulkpipe(gspca_dev->dev, 0x84),
-                               gspca_dev->usb_buf, 1, NULL, 500);
-       response = gspca_dev->usb_buf[0];
-       if (retval < 0) {
-               pr_err("read command [%02x] error %d\n",
-                      gspca_dev->usb_buf[0], retval);
-               gspca_dev->usb_err = retval;
-       }
-}
-
-static void setfreq(struct gspca_dev *gspca_dev, s32 val)
-{
-       u8 freq_commands[][2] = {
-               {0x71, 0x80},
-               {0x70, 0x07}
-       };
-
-       freq_commands[0][1] |= val >> 1;
-
-       jlj_write2(gspca_dev, freq_commands[0]);
-       jlj_write2(gspca_dev, freq_commands[1]);
-}
-
-static void setcamquality(struct gspca_dev *gspca_dev, s32 val)
-{
-       u8 quality_commands[][2] = {
-               {0x71, 0x1E},
-               {0x70, 0x06}
-       };
-       u8 camquality;
-
-       /* adapt camera quality from jpeg quality */
-       camquality = ((QUALITY_MAX - val) * CAMQUALITY_MAX)
-               / (QUALITY_MAX - QUALITY_MIN);
-       quality_commands[0][1] += camquality;
-
-       jlj_write2(gspca_dev, quality_commands[0]);
-       jlj_write2(gspca_dev, quality_commands[1]);
-}
-
-static void setautogain(struct gspca_dev *gspca_dev, s32 val)
-{
-       u8 autogain_commands[][2] = {
-               {0x94, 0x02},
-               {0xcf, 0x00}
-       };
-
-       autogain_commands[1][1] = val << 4;
-
-       jlj_write2(gspca_dev, autogain_commands[0]);
-       jlj_write2(gspca_dev, autogain_commands[1]);
-}
-
-static void setred(struct gspca_dev *gspca_dev, s32 val)
-{
-       u8 setred_commands[][2] = {
-               {0x94, 0x02},
-               {0xe6, 0x00}
-       };
-
-       setred_commands[1][1] = val;
-
-       jlj_write2(gspca_dev, setred_commands[0]);
-       jlj_write2(gspca_dev, setred_commands[1]);
-}
-
-static void setgreen(struct gspca_dev *gspca_dev, s32 val)
-{
-       u8 setgreen_commands[][2] = {
-               {0x94, 0x02},
-               {0xe7, 0x00}
-       };
-
-       setgreen_commands[1][1] = val;
-
-       jlj_write2(gspca_dev, setgreen_commands[0]);
-       jlj_write2(gspca_dev, setgreen_commands[1]);
-}
-
-static void setblue(struct gspca_dev *gspca_dev, s32 val)
-{
-       u8 setblue_commands[][2] = {
-               {0x94, 0x02},
-               {0xe9, 0x00}
-       };
-
-       setblue_commands[1][1] = val;
-
-       jlj_write2(gspca_dev, setblue_commands[0]);
-       jlj_write2(gspca_dev, setblue_commands[1]);
-}
-
-static int jlj_start(struct gspca_dev *gspca_dev)
-{
-       int i;
-       int start_commands_size;
-       u8 response = 0xff;
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct jlj_command start_commands[] = {
-               {{0x71, 0x81}, 0, 0},
-               {{0x70, 0x05}, 0, JEILINJ_CMD_DELAY},
-               {{0x95, 0x70}, 1, 0},
-               {{0x71, 0x81 - gspca_dev->curr_mode}, 0, 0},
-               {{0x70, 0x04}, 0, JEILINJ_CMD_DELAY},
-               {{0x95, 0x70}, 1, 0},
-               {{0x71, 0x00}, 0, 0},   /* start streaming ??*/
-               {{0x70, 0x08}, 0, JEILINJ_CMD_DELAY},
-               {{0x95, 0x70}, 1, 0},
-#define SPORTSCAM_DV15_CMD_SIZE 9
-               {{0x94, 0x02}, 0, 0},
-               {{0xde, 0x24}, 0, 0},
-               {{0x94, 0x02}, 0, 0},
-               {{0xdd, 0xf0}, 0, 0},
-               {{0x94, 0x02}, 0, 0},
-               {{0xe3, 0x2c}, 0, 0},
-               {{0x94, 0x02}, 0, 0},
-               {{0xe4, 0x00}, 0, 0},
-               {{0x94, 0x02}, 0, 0},
-               {{0xe5, 0x00}, 0, 0},
-               {{0x94, 0x02}, 0, 0},
-               {{0xe6, 0x2c}, 0, 0},
-               {{0x94, 0x03}, 0, 0},
-               {{0xaa, 0x00}, 0, 0}
-       };
-
-       sd->blocks_left = 0;
-       /* Under Windows, USB spy shows that only the 9 first start
-        * commands are used for SPORTSCAM_DV15 webcam
-        */
-       if (sd->type == SPORTSCAM_DV15)
-               start_commands_size = SPORTSCAM_DV15_CMD_SIZE;
-       else
-               start_commands_size = ARRAY_SIZE(start_commands);
-
-       for (i = 0; i < start_commands_size; i++) {
-               jlj_write2(gspca_dev, start_commands[i].instruction);
-               if (start_commands[i].delay)
-                       msleep(start_commands[i].delay);
-               if (start_commands[i].ack_wanted)
-                       jlj_read1(gspca_dev, response);
-       }
-       setcamquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
-       msleep(2);
-       setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
-       if (gspca_dev->usb_err < 0)
-               PDEBUG(D_ERR, "Start streaming command failed");
-       return gspca_dev->usb_err;
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data, int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int packet_type;
-       u32 header_marker;
-
-       PDEBUG(D_STREAM, "Got %d bytes out of %d for Block 0",
-                       len, JEILINJ_MAX_TRANSFER);
-       if (len != JEILINJ_MAX_TRANSFER) {
-               PDEBUG(D_PACK, "bad length");
-               goto discard;
-       }
-       /* check if it's start of frame */
-       header_marker = ((u32 *)data)[0];
-       if (header_marker == FRAME_START) {
-               sd->blocks_left = data[0x0a] - 1;
-               PDEBUG(D_STREAM, "blocks_left = 0x%x", sd->blocks_left);
-               /* Start a new frame, and add the JPEG header, first thing */
-               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                               sd->jpeg_hdr, JPEG_HDR_SZ);
-               /* Toss line 0 of data block 0, keep the rest. */
-               gspca_frame_add(gspca_dev, INTER_PACKET,
-                               data + FRAME_HEADER_LEN,
-                               JEILINJ_MAX_TRANSFER - FRAME_HEADER_LEN);
-       } else if (sd->blocks_left > 0) {
-               PDEBUG(D_STREAM, "%d blocks remaining for frame",
-                               sd->blocks_left);
-               sd->blocks_left -= 1;
-               if (sd->blocks_left == 0)
-                       packet_type = LAST_PACKET;
-               else
-                       packet_type = INTER_PACKET;
-               gspca_frame_add(gspca_dev, packet_type,
-                               data, JEILINJ_MAX_TRANSFER);
-       } else
-               goto discard;
-       return;
-discard:
-       /* Discard data until a new frame starts. */
-       gspca_dev->last_packet_type = DISCARD_PACKET;
-}
-
-/* This function is called at probe time just before sd_init */
-static int sd_config(struct gspca_dev *gspca_dev,
-               const struct usb_device_id *id)
-{
-       struct cam *cam = &gspca_dev->cam;
-       struct sd *dev  = (struct sd *) gspca_dev;
-
-       dev->type = id->driver_info;
-       dev->quality = QUALITY_DEF;
-
-       cam->cam_mode = jlj_mode;
-       cam->nmodes = ARRAY_SIZE(jlj_mode);
-       cam->bulk = 1;
-       cam->bulk_nurbs = 1;
-       cam->bulk_size = JEILINJ_MAX_TRANSFER;
-       return 0;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       int i;
-       u8 *buf;
-       static u8 stop_commands[][2] = {
-               {0x71, 0x00},
-               {0x70, 0x09},
-               {0x71, 0x80},
-               {0x70, 0x05}
-       };
-
-       for (;;) {
-               /* get the image remaining blocks */
-               usb_bulk_msg(gspca_dev->dev,
-                               gspca_dev->urb[0]->pipe,
-                               gspca_dev->urb[0]->transfer_buffer,
-                               JEILINJ_MAX_TRANSFER, NULL,
-                               JEILINJ_DATA_TIMEOUT);
-
-               /* search for 0xff 0xd9  (EOF for JPEG) */
-               i = 0;
-               buf = gspca_dev->urb[0]->transfer_buffer;
-               while ((i < (JEILINJ_MAX_TRANSFER - 1)) &&
-                       ((buf[i] != 0xff) || (buf[i+1] != 0xd9)))
-                       i++;
-
-               if (i != (JEILINJ_MAX_TRANSFER - 1))
-                       /* last remaining block found */
-                       break;
-               }
-
-       for (i = 0; i < ARRAY_SIZE(stop_commands); i++)
-               jlj_write2(gspca_dev, stop_commands[i]);
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       return gspca_dev->usb_err;
-}
-
-/* Set up for getting frames. */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *dev = (struct sd *) gspca_dev;
-
-       /* create the JPEG header */
-       jpeg_define(dev->jpeg_hdr, gspca_dev->height, gspca_dev->width,
-                       0x21);          /* JPEG 422 */
-       jpeg_set_qual(dev->jpeg_hdr, dev->quality);
-       PDEBUG(D_STREAM, "Start streaming at %dx%d",
-               gspca_dev->height, gspca_dev->width);
-       jlj_start(gspca_dev);
-       return gspca_dev->usb_err;
-}
-
-/* Table of supported USB devices */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x0979, 0x0280), .driver_info = SAKAR_57379},
-       {USB_DEVICE(0x0979, 0x0270), .driver_info = SPORTSCAM_DV15},
-       {}
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-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_POWER_LINE_FREQUENCY:
-               setfreq(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_RED_BALANCE:
-               setred(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_GAIN:
-               setgreen(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               setblue(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               setautogain(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
-               jpeg_set_qual(sd->jpeg_hdr, ctrl->val);
-               setcamquality(gspca_dev, ctrl->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;
-       static const struct v4l2_ctrl_config custom_autogain = {
-               .ops = &sd_ctrl_ops,
-               .id = V4L2_CID_AUTOGAIN,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Automatic Gain (and Exposure)",
-               .max = 3,
-               .step = 1,
-               .def = 0,
-       };
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 6);
-       sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
-                       V4L2_CID_POWER_LINE_FREQUENCY,
-                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
-                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ);
-       v4l2_ctrl_new_custom(hdl, &custom_autogain, NULL);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_RED_BALANCE, 0, 3, 1, 2);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAIN, 0, 3, 1, 2);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BLUE_BALANCE, 0, 3, 1, 2);
-       sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_JPEG_COMPRESSION_QUALITY,
-                       QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-       return 0;
-}
-
-static int sd_set_jcomp(struct gspca_dev *gspca_dev,
-                       struct v4l2_jpegcompression *jcomp)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
-       return 0;
-}
-
-static int sd_get_jcomp(struct gspca_dev *gspca_dev,
-                       struct v4l2_jpegcompression *jcomp)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       memset(jcomp, 0, sizeof *jcomp);
-       jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
-       jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
-                       | V4L2_JPEG_MARKER_DQT;
-       return 0;
-}
-
-
-/* sub-driver description */
-static const struct sd_desc sd_desc_sakar_57379 = {
-       .name   = MODULE_NAME,
-       .config = sd_config,
-       .init   = sd_init,
-       .start  = sd_start,
-       .stopN  = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* sub-driver description */
-static const struct sd_desc sd_desc_sportscam_dv15 = {
-       .name   = MODULE_NAME,
-       .config = sd_config,
-       .init   = sd_init,
-       .init_controls = sd_init_controls,
-       .start  = sd_start,
-       .stopN  = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-       .get_jcomp = sd_get_jcomp,
-       .set_jcomp = sd_set_jcomp,
-};
-
-static const struct sd_desc *sd_desc[2] = {
-       &sd_desc_sakar_57379,
-       &sd_desc_sportscam_dv15
-};
-
-/* -- device connect -- */
-static int sd_probe(struct usb_interface *intf,
-               const struct usb_device_id *id)
-{
-       return gspca_dev_probe(intf, id,
-                       sd_desc[id->driver_info],
-                       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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/jl2005bcd.c b/drivers/media/video/gspca/jl2005bcd.c
deleted file mode 100644 (file)
index cf9d9fc..0000000
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * Jeilin JL2005B/C/D library
- *
- * Copyright (C) 2011 Theodore Kilgore <kilgota@auburn.edu>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define MODULE_NAME "jl2005bcd"
-
-#include <linux/workqueue.h>
-#include <linux/slab.h>
-#include "gspca.h"
-
-
-MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
-MODULE_DESCRIPTION("JL2005B/C/D USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* Default timeouts, in ms */
-#define JL2005C_CMD_TIMEOUT 500
-#define JL2005C_DATA_TIMEOUT 1000
-
-/* Maximum transfer size to use. */
-#define JL2005C_MAX_TRANSFER 0x200
-#define FRAME_HEADER_LEN 16
-
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;  /* !! must be the first item */
-       unsigned char firmware_id[6];
-       const struct v4l2_pix_format *cap_mode;
-       /* Driver stuff */
-       struct work_struct work_struct;
-       struct workqueue_struct *work_thread;
-       u8 frame_brightness;
-       int block_size; /* block size of camera */
-       int vga;        /* 1 if vga cam, 0 if cif cam */
-};
-
-
-/* Camera has two resolution settings. What they are depends on model. */
-static const struct v4l2_pix_format cif_mode[] = {
-       {176, 144, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-       {352, 288, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-       {640, 480, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-/*
- * cam uses endpoint 0x03 to send commands, 0x84 for read commands,
- * and 0x82 for bulk data transfer.
- */
-
-/* All commands are two bytes only */
-static int jl2005c_write2(struct gspca_dev *gspca_dev, unsigned char *command)
-{
-       int retval;
-
-       memcpy(gspca_dev->usb_buf, command, 2);
-       retval = usb_bulk_msg(gspca_dev->dev,
-                       usb_sndbulkpipe(gspca_dev->dev, 3),
-                       gspca_dev->usb_buf, 2, NULL, 500);
-       if (retval < 0)
-               pr_err("command write [%02x] error %d\n",
-                      gspca_dev->usb_buf[0], retval);
-       return retval;
-}
-
-/* Response to a command is one byte in usb_buf[0], only if requested. */
-static int jl2005c_read1(struct gspca_dev *gspca_dev)
-{
-       int retval;
-
-       retval = usb_bulk_msg(gspca_dev->dev,
-                               usb_rcvbulkpipe(gspca_dev->dev, 0x84),
-                               gspca_dev->usb_buf, 1, NULL, 500);
-       if (retval < 0)
-               pr_err("read command [0x%02x] error %d\n",
-                      gspca_dev->usb_buf[0], retval);
-       return retval;
-}
-
-/* Response appears in gspca_dev->usb_buf[0] */
-static int jl2005c_read_reg(struct gspca_dev *gspca_dev, unsigned char reg)
-{
-       int retval;
-
-       static u8 instruction[2] = {0x95, 0x00};
-       /* put register to read in byte 1 */
-       instruction[1] = reg;
-       /* Send the read request */
-       retval = jl2005c_write2(gspca_dev, instruction);
-       if (retval < 0)
-               return retval;
-       retval = jl2005c_read1(gspca_dev);
-
-       return retval;
-}
-
-static int jl2005c_start_new_frame(struct gspca_dev *gspca_dev)
-{
-       int i;
-       int retval;
-       int frame_brightness = 0;
-
-       static u8 instruction[2] = {0x7f, 0x01};
-
-       retval = jl2005c_write2(gspca_dev, instruction);
-       if (retval < 0)
-               return retval;
-
-       i = 0;
-       while (i < 20 && !frame_brightness) {
-               /* If we tried 20 times, give up. */
-               retval = jl2005c_read_reg(gspca_dev, 0x7e);
-               if (retval < 0)
-                       return retval;
-               frame_brightness = gspca_dev->usb_buf[0];
-               retval = jl2005c_read_reg(gspca_dev, 0x7d);
-               if (retval < 0)
-                       return retval;
-               i++;
-       }
-       PDEBUG(D_FRAM, "frame_brightness is 0x%02x", gspca_dev->usb_buf[0]);
-       return retval;
-}
-
-static int jl2005c_write_reg(struct gspca_dev *gspca_dev, unsigned char reg,
-                                                   unsigned char value)
-{
-       int retval;
-       u8 instruction[2];
-
-       instruction[0] = reg;
-       instruction[1] = value;
-
-       retval = jl2005c_write2(gspca_dev, instruction);
-       if (retval < 0)
-                       return retval;
-
-       return retval;
-}
-
-static int jl2005c_get_firmware_id(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *)gspca_dev;
-       int i = 0;
-       int retval = -1;
-       unsigned char regs_to_read[] = {0x57, 0x02, 0x03, 0x5d, 0x5e, 0x5f};
-
-       PDEBUG(D_PROBE, "Running jl2005c_get_firmware_id");
-       /* Read the first ID byte once for warmup */
-       retval = jl2005c_read_reg(gspca_dev, regs_to_read[0]);
-       PDEBUG(D_PROBE, "response is %02x", gspca_dev->usb_buf[0]);
-       if (retval < 0)
-               return retval;
-       /* Now actually get the ID string */
-       for (i = 0; i < 6; i++) {
-               retval = jl2005c_read_reg(gspca_dev, regs_to_read[i]);
-               if (retval < 0)
-                       return retval;
-               sd->firmware_id[i] = gspca_dev->usb_buf[0];
-       }
-       PDEBUG(D_PROBE, "firmware ID is %02x%02x%02x%02x%02x%02x",
-                                               sd->firmware_id[0],
-                                               sd->firmware_id[1],
-                                               sd->firmware_id[2],
-                                               sd->firmware_id[3],
-                                               sd->firmware_id[4],
-                                               sd->firmware_id[5]);
-       return 0;
-}
-
-static int jl2005c_stream_start_vga_lg
-                   (struct gspca_dev *gspca_dev)
-{
-       int i;
-       int retval = -1;
-       static u8 instruction[][2] = {
-               {0x05, 0x00},
-               {0x7c, 0x00},
-               {0x7d, 0x18},
-               {0x02, 0x00},
-               {0x01, 0x00},
-               {0x04, 0x52},
-       };
-
-       for (i = 0; i < ARRAY_SIZE(instruction); i++) {
-               msleep(60);
-               retval = jl2005c_write2(gspca_dev, instruction[i]);
-               if (retval < 0)
-                       return retval;
-       }
-       msleep(60);
-       return retval;
-}
-
-static int jl2005c_stream_start_vga_small(struct gspca_dev *gspca_dev)
-{
-       int i;
-       int retval = -1;
-       static u8 instruction[][2] = {
-               {0x06, 0x00},
-               {0x7c, 0x00},
-               {0x7d, 0x1a},
-               {0x02, 0x00},
-               {0x01, 0x00},
-               {0x04, 0x52},
-       };
-
-       for (i = 0; i < ARRAY_SIZE(instruction); i++) {
-               msleep(60);
-               retval = jl2005c_write2(gspca_dev, instruction[i]);
-               if (retval < 0)
-                       return retval;
-       }
-       msleep(60);
-       return retval;
-}
-
-static int jl2005c_stream_start_cif_lg(struct gspca_dev *gspca_dev)
-{
-       int i;
-       int retval = -1;
-       static u8 instruction[][2] = {
-               {0x05, 0x00},
-               {0x7c, 0x00},
-               {0x7d, 0x30},
-               {0x02, 0x00},
-               {0x01, 0x00},
-               {0x04, 0x42},
-       };
-
-       for (i = 0; i < ARRAY_SIZE(instruction); i++) {
-               msleep(60);
-               retval = jl2005c_write2(gspca_dev, instruction[i]);
-               if (retval < 0)
-                       return retval;
-       }
-       msleep(60);
-       return retval;
-}
-
-static int jl2005c_stream_start_cif_small(struct gspca_dev *gspca_dev)
-{
-       int i;
-       int retval = -1;
-       static u8 instruction[][2] = {
-               {0x06, 0x00},
-               {0x7c, 0x00},
-               {0x7d, 0x32},
-               {0x02, 0x00},
-               {0x01, 0x00},
-               {0x04, 0x42},
-       };
-
-       for (i = 0; i < ARRAY_SIZE(instruction); i++) {
-               msleep(60);
-               retval = jl2005c_write2(gspca_dev, instruction[i]);
-               if (retval < 0)
-                       return retval;
-       }
-       msleep(60);
-       return retval;
-}
-
-
-static int jl2005c_stop(struct gspca_dev *gspca_dev)
-{
-       int retval;
-
-       retval = jl2005c_write_reg(gspca_dev, 0x07, 0x00);
-       return retval;
-}
-
-/* This function is called as a workqueue function and runs whenever the camera
- * is streaming data. Because it is a workqueue function it is allowed to sleep
- * so we can use synchronous USB calls. To avoid possible collisions with other
- * threads attempting to use the camera's USB interface the gspca usb_lock is
- * used when performing the one USB control operation inside the workqueue,
- * which tells the camera to close the stream. In practice the only thing
- * which needs to be protected against is the usb_set_interface call that
- * gspca makes during stream_off. Otherwise the camera doesn't provide any
- * controls that the user could try to change.
- */
-static void jl2005c_dostream(struct work_struct *work)
-{
-       struct sd *dev = container_of(work, struct sd, work_struct);
-       struct gspca_dev *gspca_dev = &dev->gspca_dev;
-       int bytes_left = 0; /* bytes remaining in current frame. */
-       int data_len;   /* size to use for the next read. */
-       int header_read = 0;
-       unsigned char header_sig[2] = {0x4a, 0x4c};
-       int act_len;
-       int packet_type;
-       int ret;
-       u8 *buffer;
-
-       buffer = kmalloc(JL2005C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
-       if (!buffer) {
-               pr_err("Couldn't allocate USB buffer\n");
-               goto quit_stream;
-       }
-
-       while (gspca_dev->dev && gspca_dev->streaming) {
-#ifdef CONFIG_PM
-               if (gspca_dev->frozen)
-                       break;
-#endif
-               /* Check if this is a new frame. If so, start the frame first */
-               if (!header_read) {
-                       mutex_lock(&gspca_dev->usb_lock);
-                       ret = jl2005c_start_new_frame(gspca_dev);
-                       mutex_unlock(&gspca_dev->usb_lock);
-                       if (ret < 0)
-                               goto quit_stream;
-                       ret = usb_bulk_msg(gspca_dev->dev,
-                               usb_rcvbulkpipe(gspca_dev->dev, 0x82),
-                               buffer, JL2005C_MAX_TRANSFER, &act_len,
-                               JL2005C_DATA_TIMEOUT);
-                       PDEBUG(D_PACK,
-                               "Got %d bytes out of %d for header",
-                                       act_len, JL2005C_MAX_TRANSFER);
-                       if (ret < 0 || act_len < JL2005C_MAX_TRANSFER)
-                               goto quit_stream;
-                       /* Check whether we actually got the first blodk */
-                       if (memcmp(header_sig, buffer, 2) != 0) {
-                               pr_err("First block is not the first block\n");
-                               goto quit_stream;
-                       }
-                       /* total size to fetch is byte 7, times blocksize
-                        * of which we already got act_len */
-                       bytes_left = buffer[0x07] * dev->block_size - act_len;
-                       PDEBUG(D_PACK, "bytes_left = 0x%x", bytes_left);
-                       /* We keep the header. It has other information, too.*/
-                       packet_type = FIRST_PACKET;
-                       gspca_frame_add(gspca_dev, packet_type,
-                                       buffer, act_len);
-                       header_read = 1;
-               }
-               while (bytes_left > 0 && gspca_dev->dev) {
-                       data_len = bytes_left > JL2005C_MAX_TRANSFER ?
-                               JL2005C_MAX_TRANSFER : bytes_left;
-                       ret = usb_bulk_msg(gspca_dev->dev,
-                               usb_rcvbulkpipe(gspca_dev->dev, 0x82),
-                               buffer, data_len, &act_len,
-                               JL2005C_DATA_TIMEOUT);
-                       if (ret < 0 || act_len < data_len)
-                               goto quit_stream;
-                       PDEBUG(D_PACK,
-                               "Got %d bytes out of %d for frame",
-                                               data_len, bytes_left);
-                       bytes_left -= data_len;
-                       if (bytes_left == 0) {
-                               packet_type = LAST_PACKET;
-                               header_read = 0;
-                       } else
-                               packet_type = INTER_PACKET;
-                       gspca_frame_add(gspca_dev, packet_type,
-                                       buffer, data_len);
-               }
-       }
-quit_stream:
-       if (gspca_dev->dev) {
-               mutex_lock(&gspca_dev->usb_lock);
-               jl2005c_stop(gspca_dev);
-               mutex_unlock(&gspca_dev->usb_lock);
-       }
-       kfree(buffer);
-}
-
-
-
-
-/* This function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct cam *cam;
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       cam = &gspca_dev->cam;
-       /* We don't use the buffer gspca allocates so make it small. */
-       cam->bulk_size = 64;
-       cam->bulk = 1;
-       /* For the rest, the camera needs to be detected */
-       jl2005c_get_firmware_id(gspca_dev);
-       /* Here are some known firmware IDs
-        * First some JL2005B cameras
-        * {0x41, 0x07, 0x04, 0x2c, 0xe8, 0xf2} Sakar KidzCam
-        * {0x45, 0x02, 0x08, 0xb9, 0x00, 0xd2} No-name JL2005B
-        * JL2005C cameras
-        * {0x01, 0x0c, 0x16, 0x10, 0xf8, 0xc8} Argus DC-1512
-        * {0x12, 0x04, 0x03, 0xc0, 0x00, 0xd8} ICarly
-        * {0x86, 0x08, 0x05, 0x02, 0x00, 0xd4} Jazz
-        *
-        * Based upon this scanty evidence, we can detect a CIF camera by
-        * testing byte 0 for 0x4x.
-        */
-       if ((sd->firmware_id[0] & 0xf0) == 0x40) {
-               cam->cam_mode   = cif_mode;
-               cam->nmodes     = ARRAY_SIZE(cif_mode);
-               sd->block_size  = 0x80;
-       } else {
-               cam->cam_mode   = vga_mode;
-               cam->nmodes     = ARRAY_SIZE(vga_mode);
-               sd->block_size  = 0x200;
-       }
-
-       INIT_WORK(&sd->work_struct, jl2005c_dostream);
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       return 0;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-
-       struct sd *sd = (struct sd *) gspca_dev;
-       sd->cap_mode = gspca_dev->cam.cam_mode;
-
-       switch (gspca_dev->width) {
-       case 640:
-               PDEBUG(D_STREAM, "Start streaming at vga resolution");
-               jl2005c_stream_start_vga_lg(gspca_dev);
-               break;
-       case 320:
-               PDEBUG(D_STREAM, "Start streaming at qvga resolution");
-               jl2005c_stream_start_vga_small(gspca_dev);
-               break;
-       case 352:
-               PDEBUG(D_STREAM, "Start streaming at cif resolution");
-               jl2005c_stream_start_cif_lg(gspca_dev);
-               break;
-       case 176:
-               PDEBUG(D_STREAM, "Start streaming at qcif resolution");
-               jl2005c_stream_start_cif_small(gspca_dev);
-               break;
-       default:
-               pr_err("Unknown resolution specified\n");
-               return -1;
-       }
-
-       /* Start the workqueue function to do the streaming */
-       sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
-       queue_work(sd->work_thread, &sd->work_struct);
-
-       return 0;
-}
-
-/* called on streamoff with alt==0 and on disconnect */
-/* the usb_lock is held at entry - restore on exit */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       struct sd *dev = (struct sd *) gspca_dev;
-
-       /* wait for the work queue to terminate */
-       mutex_unlock(&gspca_dev->usb_lock);
-       /* This waits for sq905c_dostream to finish */
-       destroy_workqueue(dev->work_thread);
-       dev->work_thread = NULL;
-       mutex_lock(&gspca_dev->usb_lock);
-}
-
-
-
-/* sub-driver description */
-static const struct sd_desc sd_desc = {
-       .name = MODULE_NAME,
-       .config = sd_config,
-       .init = sd_init,
-       .start = sd_start,
-       .stop0 = sd_stop0,
-};
-
-/* -- module initialisation -- */
-static const __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x0979, 0x0227)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-/* -- module insert / remove -- */
-static int __init sd_mod_init(void)
-{
-       int ret;
-
-       ret = usb_register(&sd_driver);
-       if (ret < 0)
-               return ret;
-       return 0;
-}
-static void __exit sd_mod_exit(void)
-{
-       usb_deregister(&sd_driver);
-}
-
-module_init(sd_mod_init);
-module_exit(sd_mod_exit);
diff --git a/drivers/media/video/gspca/jpeg.h b/drivers/media/video/gspca/jpeg.h
deleted file mode 100644 (file)
index ab54910..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-#ifndef JPEG_H
-#define JPEG_H 1
-/*
- * Insert a JPEG header at start of frame
- *
- * This module is used by the gspca subdrivers.
- * A special case is done for Conexant webcams.
- *
- * Copyright (C) Jean-Francois Moine (http://moinejf.free.fr)
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-/*
- * generation options
- *     CONEX_CAM       Conexant if present
- */
-
-/* JPEG header */
-static const u8 jpeg_head[] = {
-       0xff, 0xd8,                     /* jpeg */
-
-/* quantization table quality 50% */
-       0xff, 0xdb, 0x00, 0x84,         /* DQT */
-0,
-#define JPEG_QT0_OFFSET 7
-       0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
-       0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
-       0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
-       0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
-       0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
-       0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
-       0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
-       0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
-1,
-#define JPEG_QT1_OFFSET 72
-       0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
-       0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-
-/* huffman table */
-       0xff, 0xc4, 0x01, 0xa2,
-       0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
-       0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01, 0x00, 0x03,
-       0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-       0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
-       0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01, 0x03, 0x03,
-       0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00,
-       0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
-       0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13,
-       0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81,
-       0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15,
-       0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82,
-       0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
-       0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36,
-       0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46,
-       0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56,
-       0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66,
-       0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
-       0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86,
-       0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95,
-       0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4,
-       0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3,
-       0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
-       0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca,
-       0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
-       0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
-       0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5,
-       0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
-       0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
-       0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01,
-       0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06,
-       0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22,
-       0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
-       0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62,
-       0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25,
-       0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28,
-       0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
-       0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
-       0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
-       0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a,
-       0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
-       0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
-       0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
-       0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-       0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
-       0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
-       0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
-       0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
-       0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2,
-       0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa,
-#ifdef CONEX_CAM
-/* the Conexant frames start with SOF0 */
-#define JPEG_HDR_SZ 556
-#else
-       0xff, 0xc0, 0x00, 0x11,         /* SOF0 (start of frame 0 */
-       0x08,                           /* data precision */
-#define JPEG_HEIGHT_OFFSET 561
-       0x01, 0xe0,                     /* height */
-       0x02, 0x80,                     /* width */
-       0x03,                           /* component number */
-               0x01,
-                       0x21,           /* samples Y */
-                       0x00,           /* quant Y */
-               0x02, 0x11, 0x01,       /* samples CbCr - quant CbCr */
-               0x03, 0x11, 0x01,
-
-       0xff, 0xda, 0x00, 0x0c,         /* SOS (start of scan) */
-       0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
-#define JPEG_HDR_SZ 589
-#endif
-};
-
-/* define the JPEG header */
-static void jpeg_define(u8 *jpeg_hdr,
-                       int height,
-                       int width,
-                       int samplesY)
-{
-       memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head);
-#ifndef CONEX_CAM
-       jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8;
-       jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height;
-       jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8;
-       jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width;
-       jpeg_hdr[JPEG_HEIGHT_OFFSET + 6] = samplesY;
-#endif
-}
-
-/* set the JPEG quality */
-static void jpeg_set_qual(u8 *jpeg_hdr,
-                         int quality)
-{
-       int i, sc;
-
-       if (quality < 50)
-               sc = 5000 / quality;
-       else
-               sc = 200 - quality * 2;
-       for (i = 0; i < 64; i++) {
-               jpeg_hdr[JPEG_QT0_OFFSET + i] =
-                       (jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100;
-               jpeg_hdr[JPEG_QT1_OFFSET + i] =
-                       (jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100;
-       }
-}
-#endif
diff --git a/drivers/media/video/gspca/kinect.c b/drivers/media/video/gspca/kinect.c
deleted file mode 100644 (file)
index 40ad668..0000000
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * kinect sensor device camera, gspca driver
- *
- * Copyright (C) 2011  Antonio Ospite <ospite@studenti.unina.it>
- *
- * Based on the OpenKinect project and libfreenect
- * http://openkinect.org/wiki/Init_Analysis
- *
- * Special thanks to Steven Toth and kernellabs.com for sponsoring a Kinect
- * sensor device which I tested the driver on.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "kinect"
-
-#include "gspca.h"
-
-#define CTRL_TIMEOUT 500
-
-MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
-MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-struct pkt_hdr {
-       uint8_t magic[2];
-       uint8_t pad;
-       uint8_t flag;
-       uint8_t unk1;
-       uint8_t seq;
-       uint8_t unk2;
-       uint8_t unk3;
-       uint32_t timestamp;
-};
-
-struct cam_hdr {
-       uint8_t magic[2];
-       uint16_t len;
-       uint16_t cmd;
-       uint16_t tag;
-};
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev; /* !! must be the first item */
-       uint16_t cam_tag;           /* a sequence number for packets */
-       uint8_t stream_flag;        /* to identify different stream types */
-       uint8_t obuf[0x400];        /* output buffer for control commands */
-       uint8_t ibuf[0x200];        /* input buffer for control commands */
-};
-
-#define MODE_640x480   0x0001
-#define MODE_640x488   0x0002
-#define MODE_1280x1024 0x0004
-
-#define FORMAT_BAYER   0x0010
-#define FORMAT_UYVY    0x0020
-#define FORMAT_Y10B    0x0040
-
-#define FPS_HIGH       0x0100
-
-static const struct v4l2_pix_format video_camera_mode[] = {
-       {640, 480, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
-        .bytesperline = 640,
-        .sizeimage = 640 * 480,
-        .colorspace = V4L2_COLORSPACE_SRGB,
-        .priv = MODE_640x480 | FORMAT_BAYER | FPS_HIGH},
-       {640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
-        .bytesperline = 640 * 2,
-        .sizeimage = 640 * 480 * 2,
-        .colorspace = V4L2_COLORSPACE_SRGB,
-        .priv = MODE_640x480 | FORMAT_UYVY},
-       {1280, 1024, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
-        .bytesperline = 1280,
-        .sizeimage = 1280 * 1024,
-        .colorspace = V4L2_COLORSPACE_SRGB,
-        .priv = MODE_1280x1024 | FORMAT_BAYER},
-       {640, 488, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
-        .bytesperline = 640 * 10 / 8,
-        .sizeimage =  640 * 488 * 10 / 8,
-        .colorspace = V4L2_COLORSPACE_SRGB,
-        .priv = MODE_640x488 | FORMAT_Y10B | FPS_HIGH},
-       {1280, 1024, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
-        .bytesperline = 1280 * 10 / 8,
-        .sizeimage =  1280 * 1024 * 10 / 8,
-        .colorspace = V4L2_COLORSPACE_SRGB,
-        .priv = MODE_1280x1024 | FORMAT_Y10B},
-};
-
-static int kinect_write(struct usb_device *udev, uint8_t *data,
-                       uint16_t wLength)
-{
-       return usb_control_msg(udev,
-                             usb_sndctrlpipe(udev, 0),
-                             0x00,
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             0, 0, data, wLength, CTRL_TIMEOUT);
-}
-
-static int kinect_read(struct usb_device *udev, uint8_t *data, uint16_t wLength)
-{
-       return usb_control_msg(udev,
-                             usb_rcvctrlpipe(udev, 0),
-                             0x00,
-                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             0, 0, data, wLength, CTRL_TIMEOUT);
-}
-
-static int send_cmd(struct gspca_dev *gspca_dev, uint16_t cmd, void *cmdbuf,
-               unsigned int cmd_len, void *replybuf, unsigned int reply_len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct usb_device *udev = gspca_dev->dev;
-       int res, actual_len;
-       uint8_t *obuf = sd->obuf;
-       uint8_t *ibuf = sd->ibuf;
-       struct cam_hdr *chdr = (void *)obuf;
-       struct cam_hdr *rhdr = (void *)ibuf;
-
-       if (cmd_len & 1 || cmd_len > (0x400 - sizeof(*chdr))) {
-               pr_err("send_cmd: Invalid command length (0x%x)\n", cmd_len);
-               return -1;
-       }
-
-       chdr->magic[0] = 0x47;
-       chdr->magic[1] = 0x4d;
-       chdr->cmd = cpu_to_le16(cmd);
-       chdr->tag = cpu_to_le16(sd->cam_tag);
-       chdr->len = cpu_to_le16(cmd_len / 2);
-
-       memcpy(obuf+sizeof(*chdr), cmdbuf, cmd_len);
-
-       res = kinect_write(udev, obuf, cmd_len + sizeof(*chdr));
-       PDEBUG(D_USBO, "Control cmd=%04x tag=%04x len=%04x: %d", cmd,
-               sd->cam_tag, cmd_len, res);
-       if (res < 0) {
-               pr_err("send_cmd: Output control transfer failed (%d)\n", res);
-               return res;
-       }
-
-       do {
-               actual_len = kinect_read(udev, ibuf, 0x200);
-       } while (actual_len == 0);
-       PDEBUG(D_USBO, "Control reply: %d", res);
-       if (actual_len < sizeof(*rhdr)) {
-               pr_err("send_cmd: Input control transfer failed (%d)\n", res);
-               return res;
-       }
-       actual_len -= sizeof(*rhdr);
-
-       if (rhdr->magic[0] != 0x52 || rhdr->magic[1] != 0x42) {
-               pr_err("send_cmd: Bad magic %02x %02x\n",
-                      rhdr->magic[0], rhdr->magic[1]);
-               return -1;
-       }
-       if (rhdr->cmd != chdr->cmd) {
-               pr_err("send_cmd: Bad cmd %02x != %02x\n",
-                      rhdr->cmd, chdr->cmd);
-               return -1;
-       }
-       if (rhdr->tag != chdr->tag) {
-               pr_err("send_cmd: Bad tag %04x != %04x\n",
-                      rhdr->tag, chdr->tag);
-               return -1;
-       }
-       if (cpu_to_le16(rhdr->len) != (actual_len/2)) {
-               pr_err("send_cmd: Bad len %04x != %04x\n",
-                      cpu_to_le16(rhdr->len), (int)(actual_len/2));
-               return -1;
-       }
-
-       if (actual_len > reply_len) {
-               pr_warn("send_cmd: Data buffer is %d bytes long, but got %d bytes\n",
-                       reply_len, actual_len);
-               memcpy(replybuf, ibuf+sizeof(*rhdr), reply_len);
-       } else {
-               memcpy(replybuf, ibuf+sizeof(*rhdr), actual_len);
-       }
-
-       sd->cam_tag++;
-
-       return actual_len;
-}
-
-static int write_register(struct gspca_dev *gspca_dev, uint16_t reg,
-                       uint16_t data)
-{
-       uint16_t reply[2];
-       uint16_t cmd[2];
-       int res;
-
-       cmd[0] = cpu_to_le16(reg);
-       cmd[1] = cpu_to_le16(data);
-
-       PDEBUG(D_USBO, "Write Reg 0x%04x <= 0x%02x", reg, data);
-       res = send_cmd(gspca_dev, 0x03, cmd, 4, reply, 4);
-       if (res < 0)
-               return res;
-       if (res != 2) {
-               pr_warn("send_cmd returned %d [%04x %04x], 0000 expected\n",
-                       res, reply[0], reply[1]);
-       }
-       return 0;
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                    const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-
-       sd->cam_tag = 0;
-
-       /* Only video stream is supported for now,
-        * which has stream flag = 0x80 */
-       sd->stream_flag = 0x80;
-
-       cam = &gspca_dev->cam;
-
-       cam->cam_mode = video_camera_mode;
-       cam->nmodes = ARRAY_SIZE(video_camera_mode);
-
-#if 0
-       /* Setting those values is not needed for video stream */
-       cam->npkt = 15;
-       gspca_dev->pkt_size = 960 * 2;
-#endif
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       PDEBUG(D_PROBE, "Kinect Camera device.");
-
-       return 0;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       int mode;
-       uint8_t fmt_reg, fmt_val;
-       uint8_t res_reg, res_val;
-       uint8_t fps_reg, fps_val;
-       uint8_t mode_val;
-
-       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-
-       if (mode & FORMAT_Y10B) {
-               fmt_reg = 0x19;
-               res_reg = 0x1a;
-               fps_reg = 0x1b;
-               mode_val = 0x03;
-       } else {
-               fmt_reg = 0x0c;
-               res_reg = 0x0d;
-               fps_reg = 0x0e;
-               mode_val = 0x01;
-       }
-
-       /* format */
-       if (mode & FORMAT_UYVY)
-               fmt_val = 0x05;
-       else
-               fmt_val = 0x00;
-
-       if (mode & MODE_1280x1024)
-               res_val = 0x02;
-       else
-               res_val = 0x01;
-
-       if (mode & FPS_HIGH)
-               fps_val = 0x1e;
-       else
-               fps_val = 0x0f;
-
-
-       /* turn off IR-reset function */
-       write_register(gspca_dev, 0x105, 0x00);
-
-       /* Reset video stream */
-       write_register(gspca_dev, 0x05, 0x00);
-
-       /* Due to some ridiculous condition in the firmware, we have to start
-        * and stop the depth stream before the camera will hand us 1280x1024
-        * IR.  This is a stupid workaround, but we've yet to find a better
-        * solution.
-        *
-        * Thanks to Drew Fisher for figuring this out.
-        */
-       if (mode & (FORMAT_Y10B | MODE_1280x1024)) {
-               write_register(gspca_dev, 0x13, 0x01);
-               write_register(gspca_dev, 0x14, 0x1e);
-               write_register(gspca_dev, 0x06, 0x02);
-               write_register(gspca_dev, 0x06, 0x00);
-       }
-
-       write_register(gspca_dev, fmt_reg, fmt_val);
-       write_register(gspca_dev, res_reg, res_val);
-       write_register(gspca_dev, fps_reg, fps_val);
-
-       /* Start video stream */
-       write_register(gspca_dev, 0x05, mode_val);
-
-       /* disable Hflip */
-       write_register(gspca_dev, 0x47, 0x00);
-
-       return 0;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       /* reset video stream */
-       write_register(gspca_dev, 0x05, 0x00);
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       struct pkt_hdr *hdr = (void *)__data;
-       uint8_t *data = __data + sizeof(*hdr);
-       int datalen = len - sizeof(*hdr);
-
-       uint8_t sof = sd->stream_flag | 1;
-       uint8_t mof = sd->stream_flag | 2;
-       uint8_t eof = sd->stream_flag | 5;
-
-       if (len < 12)
-               return;
-
-       if (hdr->magic[0] != 'R' || hdr->magic[1] != 'B') {
-               pr_warn("[Stream %02x] Invalid magic %02x%02x\n",
-                       sd->stream_flag, hdr->magic[0], hdr->magic[1]);
-               return;
-       }
-
-       if (hdr->flag == sof)
-               gspca_frame_add(gspca_dev, FIRST_PACKET, data, datalen);
-
-       else if (hdr->flag == mof)
-               gspca_frame_add(gspca_dev, INTER_PACKET, data, datalen);
-
-       else if (hdr->flag == eof)
-               gspca_frame_add(gspca_dev, LAST_PACKET, data, datalen);
-
-       else
-               pr_warn("Packet type not recognized...\n");
-}
-
-/* sub-driver description */
-static const struct sd_desc sd_desc = {
-       .name      = MODULE_NAME,
-       .config    = sd_config,
-       .init      = sd_init,
-       .start     = sd_start,
-       .stopN     = sd_stopN,
-       .pkt_scan  = sd_pkt_scan,
-       /*
-       .get_streamparm = sd_get_streamparm,
-       .set_streamparm = sd_set_streamparm,
-       */
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x045e, 0x02ae)},
-       {}
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/konica.c b/drivers/media/video/gspca/konica.c
deleted file mode 100644 (file)
index bbf91e0..0000000
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * Driver for USB webcams based on Konica chipset. This
- * chipset is used in Intel YC76 camera.
- *
- * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.com>
- *
- * Based on the usbvideo v4l1 konicawc driver which is:
- *
- * Copyright (C) 2002 Simon Evans <spse@secret.org.uk>
- *
- * The code for making gspca work with a webcam with 2 isoc endpoints was
- * taken from the benq gspca subdriver which is:
- *
- * Copyright (C) 2009 Jean-Francois Moine (http://moinejf.free.fr)
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "konica"
-
-#include <linux/input.h>
-#include "gspca.h"
-
-MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
-MODULE_DESCRIPTION("Konica chipset USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-#define WHITEBAL_REG   0x01
-#define BRIGHTNESS_REG 0x02
-#define SHARPNESS_REG  0x03
-#define CONTRAST_REG   0x04
-#define SATURATION_REG 0x05
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-       struct urb *last_data_urb;
-       u8 snapshot_pressed;
-};
-
-
-/* .priv is what goes to register 8 for this mode, known working values:
-   0x00 -> 176x144, cropped
-   0x01 -> 176x144, cropped
-   0x02 -> 176x144, cropped
-   0x03 -> 176x144, cropped
-   0x04 -> 176x144, binned
-   0x05 -> 320x240
-   0x06 -> 320x240
-   0x07 -> 160x120, cropped
-   0x08 -> 160x120, cropped
-   0x09 -> 160x120, binned (note has 136 lines)
-   0x0a -> 160x120, binned (note has 136 lines)
-   0x0b -> 160x120, cropped
-*/
-static const struct v4l2_pix_format vga_mode[] = {
-       {160, 120, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 136 * 3 / 2 + 960,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0x0a},
-       {176, 144, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 3 / 2 + 960,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0x04},
-       {320, 240, V4L2_PIX_FMT_KONICA420, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 2 + 960,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0x05},
-};
-
-static void sd_isoc_irq(struct urb *urb);
-
-static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-                       0x02,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value,
-                       index,
-                       NULL,
-                       0,
-                       1000);
-       if (ret < 0) {
-               pr_err("reg_w err writing %02x to %02x: %d\n",
-                      value, index, ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void reg_r(struct gspca_dev *gspca_dev, u16 value, u16 index)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-                       0x03,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value,
-                       index,
-                       gspca_dev->usb_buf,
-                       2,
-                       1000);
-       if (ret < 0) {
-               pr_err("reg_r err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void konica_stream_on(struct gspca_dev *gspca_dev)
-{
-       reg_w(gspca_dev, 1, 0x0b);
-}
-
-static void konica_stream_off(struct gspca_dev *gspca_dev)
-{
-       reg_w(gspca_dev, 0, 0x0b);
-}
-
-/* this function is called at probe time */
-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);
-       gspca_dev->cam.no_urb_create = 1;
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       int i;
-
-       /*
-        * The konica needs a freaking large time to "boot" (approx 6.5 sec.),
-        * and does not want to be bothered while doing so :|
-        * Register 0x10 counts from 1 - 3, with 3 being "ready"
-        */
-       msleep(6000);
-       for (i = 0; i < 20; i++) {
-               reg_r(gspca_dev, 0, 0x10);
-               if (gspca_dev->usb_buf[0] == 3)
-                       break;
-               msleep(100);
-       }
-       reg_w(gspca_dev, 0, 0x0d);
-
-       return gspca_dev->usb_err;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct urb *urb;
-       int i, n, packet_size;
-       struct usb_host_interface *alt;
-       struct usb_interface *intf;
-
-       intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
-       alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
-       if (!alt) {
-               pr_err("Couldn't get altsetting\n");
-               return -EIO;
-       }
-
-       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
-
-       n = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-       reg_w(gspca_dev, n, 0x08);
-
-       konica_stream_on(gspca_dev);
-
-       if (gspca_dev->usb_err)
-               return gspca_dev->usb_err;
-
-       /* create 4 URBs - 2 on endpoint 0x83 and 2 on 0x082 */
-#if MAX_NURBS < 4
-#error "Not enough URBs in the gspca table"
-#endif
-#define SD_NPKT 32
-       for (n = 0; n < 4; n++) {
-               i = n & 1 ? 0 : 1;
-               packet_size =
-                       le16_to_cpu(alt->endpoint[i].desc.wMaxPacketSize);
-               urb = usb_alloc_urb(SD_NPKT, GFP_KERNEL);
-               if (!urb) {
-                       pr_err("usb_alloc_urb failed\n");
-                       return -ENOMEM;
-               }
-               gspca_dev->urb[n] = urb;
-               urb->transfer_buffer = usb_alloc_coherent(gspca_dev->dev,
-                                               packet_size * SD_NPKT,
-                                               GFP_KERNEL,
-                                               &urb->transfer_dma);
-               if (urb->transfer_buffer == NULL) {
-                       pr_err("usb_buffer_alloc failed\n");
-                       return -ENOMEM;
-               }
-
-               urb->dev = gspca_dev->dev;
-               urb->context = gspca_dev;
-               urb->transfer_buffer_length = packet_size * SD_NPKT;
-               urb->pipe = usb_rcvisocpipe(gspca_dev->dev,
-                                       n & 1 ? 0x81 : 0x82);
-               urb->transfer_flags = URB_ISO_ASAP
-                                       | URB_NO_TRANSFER_DMA_MAP;
-               urb->interval = 1;
-               urb->complete = sd_isoc_irq;
-               urb->number_of_packets = SD_NPKT;
-               for (i = 0; i < SD_NPKT; i++) {
-                       urb->iso_frame_desc[i].length = packet_size;
-                       urb->iso_frame_desc[i].offset = packet_size * i;
-               }
-       }
-
-       return 0;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       konica_stream_off(gspca_dev);
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       /* Don't keep the button in the pressed state "forever" if it was
-          pressed when streaming is stopped */
-       if (sd->snapshot_pressed) {
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
-               input_sync(gspca_dev->input_dev);
-               sd->snapshot_pressed = 0;
-       }
-#endif
-}
-
-/* reception of an URB */
-static void sd_isoc_irq(struct urb *urb)
-{
-       struct gspca_dev *gspca_dev = (struct gspca_dev *) urb->context;
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct urb *data_urb, *status_urb;
-       u8 *data;
-       int i, st;
-
-       PDEBUG(D_PACK, "sd isoc irq");
-       if (!gspca_dev->streaming)
-               return;
-
-       if (urb->status != 0) {
-               if (urb->status == -ESHUTDOWN)
-                       return;         /* disconnection */
-#ifdef CONFIG_PM
-               if (gspca_dev->frozen)
-                       return;
-#endif
-               PDEBUG(D_ERR, "urb status: %d", urb->status);
-               st = usb_submit_urb(urb, GFP_ATOMIC);
-               if (st < 0)
-                       pr_err("resubmit urb error %d\n", st);
-               return;
-       }
-
-       /* if this is a data URB (ep 0x82), wait */
-       if (urb->transfer_buffer_length > 32) {
-               sd->last_data_urb = urb;
-               return;
-       }
-
-       status_urb = urb;
-       data_urb   = sd->last_data_urb;
-       sd->last_data_urb = NULL;
-
-       if (!data_urb || data_urb->start_frame != status_urb->start_frame) {
-               PDEBUG(D_ERR|D_PACK, "lost sync on frames");
-               goto resubmit;
-       }
-
-       if (data_urb->number_of_packets != status_urb->number_of_packets) {
-               PDEBUG(D_ERR|D_PACK,
-                      "no packets does not match, data: %d, status: %d",
-                      data_urb->number_of_packets,
-                      status_urb->number_of_packets);
-               goto resubmit;
-       }
-
-       for (i = 0; i < status_urb->number_of_packets; i++) {
-               if (data_urb->iso_frame_desc[i].status ||
-                   status_urb->iso_frame_desc[i].status) {
-                       PDEBUG(D_ERR|D_PACK,
-                              "pkt %d data-status %d, status-status %d", i,
-                              data_urb->iso_frame_desc[i].status,
-                              status_urb->iso_frame_desc[i].status);
-                       gspca_dev->last_packet_type = DISCARD_PACKET;
-                       continue;
-               }
-
-               if (status_urb->iso_frame_desc[i].actual_length != 1) {
-                       PDEBUG(D_ERR|D_PACK,
-                              "bad status packet length %d",
-                              status_urb->iso_frame_desc[i].actual_length);
-                       gspca_dev->last_packet_type = DISCARD_PACKET;
-                       continue;
-               }
-
-               st = *((u8 *)status_urb->transfer_buffer
-                               + status_urb->iso_frame_desc[i].offset);
-
-               data = (u8 *)data_urb->transfer_buffer
-                               + data_urb->iso_frame_desc[i].offset;
-
-               /* st: 0x80-0xff: frame start with frame number (ie 0-7f)
-                * otherwise:
-                * bit 0 0: keep packet
-                *       1: drop packet (padding data)
-                *
-                * bit 4 0 button not clicked
-                *       1 button clicked
-                * button is used to `take a picture' (in software)
-                */
-               if (st & 0x80) {
-                       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-                       gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
-               } else {
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-                       u8 button_state = st & 0x40 ? 1 : 0;
-                       if (sd->snapshot_pressed != button_state) {
-                               input_report_key(gspca_dev->input_dev,
-                                                KEY_CAMERA,
-                                                button_state);
-                               input_sync(gspca_dev->input_dev);
-                               sd->snapshot_pressed = button_state;
-                       }
-#endif
-                       if (st & 0x01)
-                               continue;
-               }
-               gspca_frame_add(gspca_dev, INTER_PACKET, data,
-                               data_urb->iso_frame_desc[i].actual_length);
-       }
-
-resubmit:
-       if (data_urb) {
-               st = usb_submit_urb(data_urb, GFP_ATOMIC);
-               if (st < 0)
-                       PDEBUG(D_ERR|D_PACK,
-                              "usb_submit_urb(data_urb) ret %d", st);
-       }
-       st = usb_submit_urb(status_urb, GFP_ATOMIC);
-       if (st < 0)
-               pr_err("usb_submit_urb(status_urb) ret %d\n", st);
-}
-
-static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct gspca_dev *gspca_dev =
-               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
-
-       gspca_dev->usb_err = 0;
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               konica_stream_off(gspca_dev);
-               reg_w(gspca_dev, ctrl->val, BRIGHTNESS_REG);
-               konica_stream_on(gspca_dev);
-               break;
-       case V4L2_CID_CONTRAST:
-               konica_stream_off(gspca_dev);
-               reg_w(gspca_dev, ctrl->val, CONTRAST_REG);
-               konica_stream_on(gspca_dev);
-               break;
-       case V4L2_CID_SATURATION:
-               konica_stream_off(gspca_dev);
-               reg_w(gspca_dev, ctrl->val, SATURATION_REG);
-               konica_stream_on(gspca_dev);
-               break;
-       case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
-               konica_stream_off(gspca_dev);
-               reg_w(gspca_dev, ctrl->val, WHITEBAL_REG);
-               konica_stream_on(gspca_dev);
-               break;
-       case V4L2_CID_SHARPNESS:
-               konica_stream_off(gspca_dev);
-               reg_w(gspca_dev, ctrl->val, SHARPNESS_REG);
-               konica_stream_on(gspca_dev);
-               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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 5);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 9, 1, 4);
-       /* Needs to be verified */
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 9, 1, 4);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 9, 1, 4);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_WHITE_BALANCE_TEMPERATURE,
-                       0, 33, 1, 25);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SHARPNESS, 0, 9, 1, 4);
-
-       if (hdl->error) {
-               pr_err("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,
-       .stopN = sd_stopN,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .other_input = 1,
-#endif
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x04c8, 0x0720)}, /* Intel YC 76 */
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/m5602/Kconfig b/drivers/media/video/gspca/m5602/Kconfig
deleted file mode 100644 (file)
index 5a69016..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-config USB_M5602
-       tristate "ALi USB m5602 Camera Driver"
-       depends on VIDEO_V4L2 && USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on the
-         ALi m5602 connected to various image sensors.
-
-         See <file:Documentation/video4linux/m5602.txt> for more info.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_m5602.
diff --git a/drivers/media/video/gspca/m5602/Makefile b/drivers/media/video/gspca/m5602/Makefile
deleted file mode 100644 (file)
index 575b75b..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-obj-$(CONFIG_USB_M5602) += gspca_m5602.o
-
-gspca_m5602-objs := m5602_core.o \
-                   m5602_ov9650.o \
-                   m5602_ov7660.o \
-                   m5602_mt9m111.o \
-                   m5602_po1030.o \
-                   m5602_s5k83a.o \
-                   m5602_s5k4aa.o
-
-ccflags-y += -I$(srctree)/drivers/media/video/gspca
diff --git a/drivers/media/video/gspca/m5602/m5602_bridge.h b/drivers/media/video/gspca/m5602/m5602_bridge.h
deleted file mode 100644 (file)
index 51af3ee..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * USB Driver for ALi m5602 based webcams
- *
- * Copyright (C) 2008 Erik Andrén
- * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#ifndef M5602_BRIDGE_H_
-#define M5602_BRIDGE_H_
-
-#include <linux/slab.h>
-#include "gspca.h"
-
-#define MODULE_NAME "ALi m5602"
-
-/*****************************************************************************/
-
-#define M5602_XB_SENSOR_TYPE           0x00
-#define M5602_XB_SENSOR_CTRL           0x01
-#define M5602_XB_LINE_OF_FRAME_H       0x02
-#define M5602_XB_LINE_OF_FRAME_L       0x03
-#define M5602_XB_PIX_OF_LINE_H         0x04
-#define M5602_XB_PIX_OF_LINE_L         0x05
-#define M5602_XB_VSYNC_PARA            0x06
-#define M5602_XB_HSYNC_PARA            0x07
-#define M5602_XB_TEST_MODE_1           0x08
-#define M5602_XB_TEST_MODE_2           0x09
-#define M5602_XB_SIG_INI               0x0a
-#define M5602_XB_DS_PARA               0x0e
-#define M5602_XB_TRIG_PARA             0x0f
-#define M5602_XB_CLK_PD                        0x10
-#define M5602_XB_MCU_CLK_CTRL          0x12
-#define M5602_XB_MCU_CLK_DIV           0x13
-#define M5602_XB_SEN_CLK_CTRL          0x14
-#define M5602_XB_SEN_CLK_DIV           0x15
-#define M5602_XB_AUD_CLK_CTRL          0x16
-#define M5602_XB_AUD_CLK_DIV           0x17
-#define M5602_OB_AC_LINK_STATE         0x22
-#define M5602_OB_PCM_SLOT_INDEX                0x24
-#define M5602_OB_GPIO_SLOT_INDEX       0x25
-#define M5602_OB_ACRX_STATUS_ADDRESS_H 0x28
-#define M5602_OB_ACRX_STATUS_DATA_L    0x29
-#define M5602_OB_ACRX_STATUS_DATA_H    0x2a
-#define M5602_OB_ACTX_COMMAND_ADDRESS  0x31
-#define M5602_OB_ACRX_COMMAND_DATA_L   0x32
-#define M5602_OB_ACTX_COMMAND_DATA_H   0X33
-#define M5602_XB_DEVCTR1               0x41
-#define M5602_XB_EPSETR0               0x42
-#define M5602_XB_EPAFCTR               0x47
-#define M5602_XB_EPBFCTR               0x49
-#define M5602_XB_EPEFCTR               0x4f
-#define M5602_XB_TEST_REG              0x53
-#define M5602_XB_ALT2SIZE              0x54
-#define M5602_XB_ALT3SIZE              0x55
-#define M5602_XB_OBSFRAME              0x56
-#define M5602_XB_PWR_CTL               0x59
-#define M5602_XB_ADC_CTRL              0x60
-#define M5602_XB_ADC_DATA              0x61
-#define M5602_XB_MISC_CTRL             0x62
-#define M5602_XB_SNAPSHOT              0x63
-#define M5602_XB_SCRATCH_1             0x64
-#define M5602_XB_SCRATCH_2             0x65
-#define M5602_XB_SCRATCH_3             0x66
-#define M5602_XB_SCRATCH_4             0x67
-#define M5602_XB_I2C_CTRL              0x68
-#define M5602_XB_I2C_CLK_DIV           0x69
-#define M5602_XB_I2C_DEV_ADDR          0x6a
-#define M5602_XB_I2C_REG_ADDR          0x6b
-#define M5602_XB_I2C_DATA              0x6c
-#define M5602_XB_I2C_STATUS            0x6d
-#define M5602_XB_GPIO_DAT_H            0x70
-#define M5602_XB_GPIO_DAT_L            0x71
-#define M5602_XB_GPIO_DIR_H            0x72
-#define M5602_XB_GPIO_DIR_L            0x73
-#define M5602_XB_GPIO_EN_H             0x74
-#define M5602_XB_GPIO_EN_L             0x75
-#define M5602_XB_GPIO_DAT              0x76
-#define M5602_XB_GPIO_DIR              0x77
-#define M5602_XB_SEN_CLK_CONTROL       0x80
-#define M5602_XB_SEN_CLK_DIVISION      0x81
-#define M5602_XB_CPR_CLK_CONTROL       0x82
-#define M5602_XB_CPR_CLK_DIVISION      0x83
-#define M5602_XB_MCU_CLK_CONTROL       0x84
-#define M5602_XB_MCU_CLK_DIVISION      0x85
-#define M5602_XB_DCT_CLK_CONTROL       0x86
-#define M5602_XB_DCT_CLK_DIVISION      0x87
-#define M5602_XB_EC_CLK_CONTROL                0x88
-#define M5602_XB_EC_CLK_DIVISION       0x89
-#define M5602_XB_LBUF_CLK_CONTROL      0x8a
-#define M5602_XB_LBUF_CLK_DIVISION     0x8b
-
-#define I2C_BUSY 0x80
-
-/*****************************************************************************/
-
-/* Driver info */
-#define DRIVER_AUTHOR "ALi m5602 Linux Driver Project"
-#define DRIVER_DESC "ALi m5602 webcam driver"
-
-#define M5602_ISOC_ENDPOINT_ADDR 0x81
-#define M5602_INTR_ENDPOINT_ADDR 0x82
-
-#define M5602_URB_MSG_TIMEOUT   5000
-
-/*****************************************************************************/
-
-/* A skeleton used for sending messages to the m5602 bridge */
-static const unsigned char bridge_urb_skeleton[] = {
-       0x13, 0x00, 0x81, 0x00
-};
-
-/* A skeleton used for sending messages to the sensor */
-static const unsigned char sensor_urb_skeleton[] = {
-       0x23, M5602_XB_GPIO_EN_H, 0x81, 0x06,
-       0x23, M5602_XB_MISC_CTRL, 0x81, 0x80,
-       0x13, M5602_XB_I2C_DEV_ADDR, 0x81, 0x00,
-       0x13, M5602_XB_I2C_REG_ADDR, 0x81, 0x00,
-       0x13, M5602_XB_I2C_DATA, 0x81, 0x00,
-       0x13, M5602_XB_I2C_CTRL, 0x81, 0x11
-};
-
-struct sd {
-       struct gspca_dev gspca_dev;
-
-       /* A pointer to the currently connected sensor */
-       const struct m5602_sensor *sensor;
-
-       struct sd_desc *desc;
-
-       /* Sensor private data */
-       void *sensor_priv;
-
-       /* The current frame's id, used to detect frame boundaries */
-       u8 frame_id;
-
-       /* The current frame count */
-       u32 frame_count;
-};
-
-int m5602_read_bridge(
-       struct sd *sd, const u8 address, u8 *i2c_data);
-
-int m5602_write_bridge(
-       struct sd *sd, const u8 address, const u8 i2c_data);
-
-int m5602_write_sensor(struct sd *sd, const u8 address,
-                      u8 *i2c_data, const u8 len);
-
-int m5602_read_sensor(struct sd *sd, const u8 address,
-                     u8 *i2c_data, const u8 len);
-
-#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_core.c b/drivers/media/video/gspca/m5602/m5602_core.c
deleted file mode 100644 (file)
index ed22638..0000000
+++ /dev/null
@@ -1,424 +0,0 @@
- /*
- * USB Driver for ALi m5602 based webcams
- *
- * Copyright (C) 2008 Erik Andrén
- * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "m5602_ov9650.h"
-#include "m5602_ov7660.h"
-#include "m5602_mt9m111.h"
-#include "m5602_po1030.h"
-#include "m5602_s5k83a.h"
-#include "m5602_s5k4aa.h"
-
-/* Kernel module parameters */
-int force_sensor;
-static bool dump_bridge;
-bool dump_sensor;
-
-static const struct usb_device_id m5602_table[] = {
-       {USB_DEVICE(0x0402, 0x5602)},
-       {}
-};
-
-MODULE_DEVICE_TABLE(usb, m5602_table);
-
-/* Reads a byte from the m5602 */
-int m5602_read_bridge(struct sd *sd, const u8 address, u8 *i2c_data)
-{
-       int err;
-       struct usb_device *udev = sd->gspca_dev.dev;
-       __u8 *buf = sd->gspca_dev.usb_buf;
-
-       err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-                             0x04, 0xc0, 0x14,
-                             0x8100 + address, buf,
-                             1, M5602_URB_MSG_TIMEOUT);
-       *i2c_data = buf[0];
-
-       PDEBUG(D_CONF, "Reading bridge register 0x%x containing 0x%x",
-              address, *i2c_data);
-
-       /* usb_control_msg(...) returns the number of bytes sent upon success,
-       mask that and return zero instead*/
-       return (err < 0) ? err : 0;
-}
-
-/* Writes a byte to the m5602 */
-int m5602_write_bridge(struct sd *sd, const u8 address, const u8 i2c_data)
-{
-       int err;
-       struct usb_device *udev = sd->gspca_dev.dev;
-       __u8 *buf = sd->gspca_dev.usb_buf;
-
-       PDEBUG(D_CONF, "Writing bridge register 0x%x with 0x%x",
-              address, i2c_data);
-
-       memcpy(buf, bridge_urb_skeleton,
-              sizeof(bridge_urb_skeleton));
-       buf[1] = address;
-       buf[3] = i2c_data;
-
-       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                               0x04, 0x40, 0x19,
-                               0x0000, buf,
-                               4, M5602_URB_MSG_TIMEOUT);
-
-       /* usb_control_msg(...) returns the number of bytes sent upon success,
-          mask that and return zero instead */
-       return (err < 0) ? err : 0;
-}
-
-static int m5602_wait_for_i2c(struct sd *sd)
-{
-       int err;
-       u8 data;
-
-       do {
-               err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, &data);
-       } while ((data & I2C_BUSY) && !err);
-       return err;
-}
-
-int m5602_read_sensor(struct sd *sd, const u8 address,
-                      u8 *i2c_data, const u8 len)
-{
-       int err, i;
-
-       if (!len || len > sd->sensor->i2c_regW)
-               return -EINVAL;
-
-       err = m5602_wait_for_i2c(sd);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
-                                sd->sensor->i2c_slave_id);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
-       if (err < 0)
-               return err;
-
-       /* Sensors with registers that are of only
-          one byte width are differently read */
-
-       /* FIXME: This works with the ov9650, but has issues with the po1030 */
-       if (sd->sensor->i2c_regW == 1) {
-               err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 1);
-               if (err < 0)
-                       return err;
-
-               err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x08);
-       } else {
-               err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x18 + len);
-       }
-
-       for (i = 0; (i < len) && !err; i++) {
-               err = m5602_wait_for_i2c(sd);
-               if (err < 0)
-                       return err;
-
-               err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
-
-               PDEBUG(D_CONF, "Reading sensor register "
-                              "0x%x containing 0x%x ", address, *i2c_data);
-       }
-       return err;
-}
-
-int m5602_write_sensor(struct sd *sd, const u8 address,
-                       u8 *i2c_data, const u8 len)
-{
-       int err, i;
-       u8 *p;
-       struct usb_device *udev = sd->gspca_dev.dev;
-       __u8 *buf = sd->gspca_dev.usb_buf;
-
-       /* No sensor with a data width larger than 16 bits has yet been seen */
-       if (len > sd->sensor->i2c_regW || !len)
-               return -EINVAL;
-
-       memcpy(buf, sensor_urb_skeleton,
-              sizeof(sensor_urb_skeleton));
-
-       buf[11] = sd->sensor->i2c_slave_id;
-       buf[15] = address;
-
-       /* Special case larger sensor writes */
-       p = buf + 16;
-
-       /* Copy a four byte write sequence for each byte to be written to */
-       for (i = 0; i < len; i++) {
-               memcpy(p, sensor_urb_skeleton + 16, 4);
-               p[3] = i2c_data[i];
-               p += 4;
-               PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
-                      address, i2c_data[i]);
-       }
-
-       /* Copy the tailer */
-       memcpy(p, sensor_urb_skeleton + 20, 4);
-
-       /* Set the total length */
-       p[3] = 0x10 + len;
-
-       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                             0x04, 0x40, 0x19,
-                             0x0000, buf,
-                             20 + len * 4, M5602_URB_MSG_TIMEOUT);
-
-       return (err < 0) ? err : 0;
-}
-
-/* Dump all the registers of the m5602 bridge,
-   unfortunately this breaks the camera until it's power cycled */
-static void m5602_dump_bridge(struct sd *sd)
-{
-       int i;
-       for (i = 0; i < 0x80; i++) {
-               unsigned char val = 0;
-               m5602_read_bridge(sd, i, &val);
-               pr_info("ALi m5602 address 0x%x contains 0x%x\n", i, val);
-       }
-       pr_info("Warning: The ALi m5602 webcam probably won't work until it's power cycled\n");
-}
-
-static int m5602_probe_sensor(struct sd *sd)
-{
-       /* Try the po1030 */
-       sd->sensor = &po1030;
-       if (!sd->sensor->probe(sd))
-               return 0;
-
-       /* Try the mt9m111 sensor */
-       sd->sensor = &mt9m111;
-       if (!sd->sensor->probe(sd))
-               return 0;
-
-       /* Try the s5k4aa */
-       sd->sensor = &s5k4aa;
-       if (!sd->sensor->probe(sd))
-               return 0;
-
-       /* Try the ov9650 */
-       sd->sensor = &ov9650;
-       if (!sd->sensor->probe(sd))
-               return 0;
-
-       /* Try the ov7660 */
-       sd->sensor = &ov7660;
-       if (!sd->sensor->probe(sd))
-               return 0;
-
-       /* Try the s5k83a */
-       sd->sensor = &s5k83a;
-       if (!sd->sensor->probe(sd))
-               return 0;
-
-       /* More sensor probe function goes here */
-       pr_info("Failed to find a sensor\n");
-       sd->sensor = NULL;
-       return -ENODEV;
-}
-
-static int m5602_configure(struct gspca_dev *gspca_dev,
-                          const struct usb_device_id *id);
-
-static int m5602_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int err;
-
-       PDEBUG(D_CONF, "Initializing ALi m5602 webcam");
-       /* Run the init sequence */
-       err = sd->sensor->init(sd);
-
-       return err;
-}
-
-static int m5602_start_transfer(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       __u8 *buf = sd->gspca_dev.usb_buf;
-       int err;
-
-       /* Send start command to the camera */
-       const u8 buffer[4] = {0x13, 0xf9, 0x0f, 0x01};
-
-       if (sd->sensor->start)
-               sd->sensor->start(sd);
-
-       memcpy(buf, buffer, sizeof(buffer));
-       err = usb_control_msg(gspca_dev->dev,
-                             usb_sndctrlpipe(gspca_dev->dev, 0),
-                             0x04, 0x40, 0x19, 0x0000, buf,
-                             sizeof(buffer), M5602_URB_MSG_TIMEOUT);
-
-       PDEBUG(D_STREAM, "Transfer started");
-       return (err < 0) ? err : 0;
-}
-
-static void m5602_urb_complete(struct gspca_dev *gspca_dev,
-                               u8 *data, int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (len < 6) {
-               PDEBUG(D_PACK, "Packet is less than 6 bytes");
-               return;
-       }
-
-       /* Frame delimiter: ff xx xx xx ff ff */
-       if (data[0] == 0xff && data[4] == 0xff && data[5] == 0xff &&
-           data[2] != sd->frame_id) {
-               PDEBUG(D_FRAM, "Frame delimiter detected");
-               sd->frame_id = data[2];
-
-               /* Remove the extra fluff appended on each header */
-               data += 6;
-               len -= 6;
-
-               /* Complete the last frame (if any) */
-               gspca_frame_add(gspca_dev, LAST_PACKET,
-                               NULL, 0);
-               sd->frame_count++;
-
-               /* Create a new frame */
-               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
-
-               PDEBUG(D_FRAM, "Starting new frame %d",
-                      sd->frame_count);
-
-       } else {
-               int cur_frame_len;
-
-               cur_frame_len = gspca_dev->image_len;
-               /* Remove urb header */
-               data += 4;
-               len -= 4;
-
-               if (cur_frame_len + len <= gspca_dev->frsz) {
-                       PDEBUG(D_FRAM, "Continuing frame %d copying %d bytes",
-                              sd->frame_count, len);
-
-                       gspca_frame_add(gspca_dev, INTER_PACKET,
-                                       data, len);
-               } else {
-                       /* Add the remaining data up to frame size */
-                       gspca_frame_add(gspca_dev, INTER_PACKET, data,
-                                   gspca_dev->frsz - cur_frame_len);
-               }
-       }
-}
-
-static void m5602_stop_transfer(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* Run the sensor specific end transfer sequence */
-       if (sd->sensor->stop)
-               sd->sensor->stop(sd);
-}
-
-/* sub-driver description, the ctrl and nctrl is filled at probe time */
-static struct sd_desc sd_desc = {
-       .name           = MODULE_NAME,
-       .config         = m5602_configure,
-       .init           = m5602_init,
-       .start          = m5602_start_transfer,
-       .stopN          = m5602_stop_transfer,
-       .pkt_scan       = m5602_urb_complete
-};
-
-/* this function is called at probe time */
-static int m5602_configure(struct gspca_dev *gspca_dev,
-                          const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-       int err;
-
-       cam = &gspca_dev->cam;
-       sd->desc = &sd_desc;
-
-       if (dump_bridge)
-               m5602_dump_bridge(sd);
-
-       /* Probe sensor */
-       err = m5602_probe_sensor(sd);
-       if (err)
-               goto fail;
-
-       return 0;
-
-fail:
-       PDEBUG(D_ERR, "ALi m5602 webcam failed");
-       cam->cam_mode = NULL;
-       cam->nmodes = 0;
-
-       return err;
-}
-
-static int m5602_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 void m5602_disconnect(struct usb_interface *intf)
-{
-       struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor->disconnect)
-               sd->sensor->disconnect(sd);
-
-       gspca_disconnect(intf);
-}
-
-static struct usb_driver sd_driver = {
-       .name = MODULE_NAME,
-       .id_table = m5602_table,
-       .probe = m5602_probe,
-#ifdef CONFIG_PM
-       .suspend = gspca_suspend,
-       .resume = gspca_resume,
-       .reset_resume = gspca_resume,
-#endif
-       .disconnect = m5602_disconnect
-};
-
-module_usb_driver(sd_driver);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-module_param(force_sensor, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(force_sensor,
-               "forces detection of a sensor, "
-               "1 = OV9650, 2 = S5K83A, 3 = S5K4AA, "
-               "4 = MT9M111, 5 = PO1030, 6 = OV7660");
-
-module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
-
-module_param(dump_sensor, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(dump_sensor, "Dumps all usb sensor registers "
-               "at startup providing a sensor is found");
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.c b/drivers/media/video/gspca/m5602/m5602_mt9m111.c
deleted file mode 100644 (file)
index 6268aa2..0000000
+++ /dev/null
@@ -1,647 +0,0 @@
-/*
- * Driver for the mt9m111 sensor
- *
- * Copyright (C) 2008 Erik Andrén
- * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "m5602_mt9m111.h"
-
-static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
-                                        __s32 val);
-static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
-                                         __s32 *val);
-static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
-
-static struct v4l2_pix_format mt9m111_modes[] = {
-       {
-               640,
-               480,
-               V4L2_PIX_FMT_SBGGR8,
-               V4L2_FIELD_NONE,
-               .sizeimage = 640 * 480,
-               .bytesperline = 640,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0
-       }
-};
-
-static const struct ctrl mt9m111_ctrls[] = {
-#define VFLIP_IDX 0
-       {
-               {
-                       .id             = V4L2_CID_VFLIP,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "vertical flip",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 0
-               },
-               .set = mt9m111_set_vflip,
-               .get = mt9m111_get_vflip
-       },
-#define HFLIP_IDX 1
-       {
-               {
-                       .id             = V4L2_CID_HFLIP,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "horizontal flip",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 0
-               },
-               .set = mt9m111_set_hflip,
-               .get = mt9m111_get_hflip
-       },
-#define GAIN_IDX 2
-       {
-               {
-                       .id             = V4L2_CID_GAIN,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "gain",
-                       .minimum        = 0,
-                       .maximum        = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
-                       .step           = 1,
-                       .default_value  = MT9M111_DEFAULT_GAIN,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = mt9m111_set_gain,
-               .get = mt9m111_get_gain
-       },
-#define AUTO_WHITE_BALANCE_IDX 3
-       {
-               {
-                       .id             = V4L2_CID_AUTO_WHITE_BALANCE,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "auto white balance",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 0,
-               },
-               .set = mt9m111_set_auto_white_balance,
-               .get = mt9m111_get_auto_white_balance
-       },
-#define GREEN_BALANCE_IDX 4
-       {
-               {
-                       .id             = M5602_V4L2_CID_GREEN_BALANCE,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "green balance",
-                       .minimum        = 0x00,
-                       .maximum        = 0x7ff,
-                       .step           = 0x1,
-                       .default_value  = MT9M111_GREEN_GAIN_DEFAULT,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = mt9m111_set_green_balance,
-               .get = mt9m111_get_green_balance
-       },
-#define BLUE_BALANCE_IDX 5
-       {
-               {
-                       .id             = V4L2_CID_BLUE_BALANCE,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "blue balance",
-                       .minimum        = 0x00,
-                       .maximum        = 0x7ff,
-                       .step           = 0x1,
-                       .default_value  = MT9M111_BLUE_GAIN_DEFAULT,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = mt9m111_set_blue_balance,
-               .get = mt9m111_get_blue_balance
-       },
-#define RED_BALANCE_IDX 5
-       {
-               {
-                       .id             = V4L2_CID_RED_BALANCE,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "red balance",
-                       .minimum        = 0x00,
-                       .maximum        = 0x7ff,
-                       .step           = 0x1,
-                       .default_value  = MT9M111_RED_GAIN_DEFAULT,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = mt9m111_set_red_balance,
-               .get = mt9m111_get_red_balance
-       },
-};
-
-static void mt9m111_dump_registers(struct sd *sd);
-
-int mt9m111_probe(struct sd *sd)
-{
-       u8 data[2] = {0x00, 0x00};
-       int i;
-       s32 *sensor_settings;
-
-       if (force_sensor) {
-               if (force_sensor == MT9M111_SENSOR) {
-                       pr_info("Forcing a %s sensor\n", mt9m111.name);
-                       goto sensor_found;
-               }
-               /* If we want to force another sensor, don't try to probe this
-                * one */
-               return -ENODEV;
-       }
-
-       PDEBUG(D_PROBE, "Probing for a mt9m111 sensor");
-
-       /* Do the preinit */
-       for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
-               if (preinit_mt9m111[i][0] == BRIDGE) {
-                       m5602_write_bridge(sd,
-                               preinit_mt9m111[i][1],
-                               preinit_mt9m111[i][2]);
-               } else {
-                       data[0] = preinit_mt9m111[i][2];
-                       data[1] = preinit_mt9m111[i][3];
-                       m5602_write_sensor(sd,
-                               preinit_mt9m111[i][1], data, 2);
-               }
-       }
-
-       if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
-               return -ENODEV;
-
-       if ((data[0] == 0x14) && (data[1] == 0x3a)) {
-               pr_info("Detected a mt9m111 sensor\n");
-               goto sensor_found;
-       }
-
-       return -ENODEV;
-
-sensor_found:
-       sensor_settings = kmalloc(ARRAY_SIZE(mt9m111_ctrls) * sizeof(s32),
-                                 GFP_KERNEL);
-       if (!sensor_settings)
-               return -ENOMEM;
-
-       sd->gspca_dev.cam.cam_mode = mt9m111_modes;
-       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
-       sd->desc->ctrls = mt9m111_ctrls;
-       sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls);
-
-       for (i = 0; i < ARRAY_SIZE(mt9m111_ctrls); i++)
-               sensor_settings[i] = mt9m111_ctrls[i].qctrl.default_value;
-       sd->sensor_priv = sensor_settings;
-
-       return 0;
-}
-
-int mt9m111_init(struct sd *sd)
-{
-       int i, err = 0;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       /* Init the sensor */
-       for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
-               u8 data[2];
-
-               if (init_mt9m111[i][0] == BRIDGE) {
-                       err = m5602_write_bridge(sd,
-                               init_mt9m111[i][1],
-                               init_mt9m111[i][2]);
-               } else {
-                       data[0] = init_mt9m111[i][2];
-                       data[1] = init_mt9m111[i][3];
-                       err = m5602_write_sensor(sd,
-                               init_mt9m111[i][1], data, 2);
-               }
-       }
-
-       if (dump_sensor)
-               mt9m111_dump_registers(sd);
-
-       err = mt9m111_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
-       if (err < 0)
-               return err;
-
-       err = mt9m111_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
-       if (err < 0)
-               return err;
-
-       err = mt9m111_set_green_balance(&sd->gspca_dev,
-                                        sensor_settings[GREEN_BALANCE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = mt9m111_set_blue_balance(&sd->gspca_dev,
-                                        sensor_settings[BLUE_BALANCE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = mt9m111_set_red_balance(&sd->gspca_dev,
-                                       sensor_settings[RED_BALANCE_IDX]);
-       if (err < 0)
-               return err;
-
-       return mt9m111_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
-}
-
-int mt9m111_start(struct sd *sd)
-{
-       int i, err = 0;
-       u8 data[2];
-       struct cam *cam = &sd->gspca_dev.cam;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       int width = cam->cam_mode[sd->gspca_dev.curr_mode].width - 1;
-       int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
-
-       for (i = 0; i < ARRAY_SIZE(start_mt9m111) && !err; i++) {
-               if (start_mt9m111[i][0] == BRIDGE) {
-                       err = m5602_write_bridge(sd,
-                               start_mt9m111[i][1],
-                               start_mt9m111[i][2]);
-               } else {
-                       data[0] = start_mt9m111[i][2];
-                       data[1] = start_mt9m111[i][3];
-                       err = m5602_write_sensor(sd,
-                               start_mt9m111[i][1], data, 2);
-               }
-       }
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
-       if (err < 0)
-               return err;
-
-       for (i = 0; i < 2 && !err; i++)
-               err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
-       if (err < 0)
-               return err;
-
-       for (i = 0; i < 2 && !err; i++)
-               err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
-                                (width >> 8) & 0xff);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, width & 0xff);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
-       if (err < 0)
-               return err;
-
-       switch (width) {
-       case 640:
-               PDEBUG(D_V4L2, "Configuring camera for VGA mode");
-               data[0] = MT9M111_RMB_OVER_SIZED;
-               data[1] = MT9M111_RMB_ROW_SKIP_2X |
-                         MT9M111_RMB_COLUMN_SKIP_2X |
-                         (sensor_settings[VFLIP_IDX] << 0) |
-                         (sensor_settings[HFLIP_IDX] << 1);
-
-               err = m5602_write_sensor(sd,
-                                        MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
-               break;
-
-       case 320:
-               PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
-               data[0] = MT9M111_RMB_OVER_SIZED;
-               data[1] = MT9M111_RMB_ROW_SKIP_4X |
-                               MT9M111_RMB_COLUMN_SKIP_4X |
-                               (sensor_settings[VFLIP_IDX] << 0) |
-                               (sensor_settings[HFLIP_IDX] << 1);
-               err = m5602_write_sensor(sd,
-                                        MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
-               break;
-       }
-       return err;
-}
-
-void mt9m111_disconnect(struct sd *sd)
-{
-       sd->sensor = NULL;
-       kfree(sd->sensor_priv);
-}
-
-static int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[VFLIP_IDX];
-       PDEBUG(D_V4L2, "Read vertical flip %d", *val);
-
-       return 0;
-}
-
-static int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 data[2] = {0x00, 0x00};
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Set vertical flip to %d", val);
-
-       sensor_settings[VFLIP_IDX] = val;
-
-       /* The mt9m111 is flipped by default */
-       val = !val;
-
-       /* Set the correct page map */
-       err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
-       if (err < 0)
-               return err;
-
-       err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
-       if (err < 0)
-               return err;
-
-       data[1] = (data[1] & 0xfe) | val;
-       err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
-                                  data, 2);
-       return err;
-}
-
-static int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[HFLIP_IDX];
-       PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
-
-       return 0;
-}
-
-static int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 data[2] = {0x00, 0x00};
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
-
-       sensor_settings[HFLIP_IDX] = val;
-
-       /* The mt9m111 is flipped by default */
-       val = !val;
-
-       /* Set the correct page map */
-       err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
-       if (err < 0)
-               return err;
-
-       err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
-       if (err < 0)
-               return err;
-
-       data[1] = (data[1] & 0xfd) | ((val << 1) & 0x02);
-       err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
-                                       data, 2);
-       return err;
-}
-
-static int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[GAIN_IDX];
-       PDEBUG(D_V4L2, "Read gain %d", *val);
-
-       return 0;
-}
-
-static int mt9m111_set_auto_white_balance(struct gspca_dev *gspca_dev,
-                                         __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       int err;
-       u8 data[2];
-
-       err = m5602_read_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
-       if (err < 0)
-               return err;
-
-       sensor_settings[AUTO_WHITE_BALANCE_IDX] = val & 0x01;
-       data[1] = ((data[1] & 0xfd) | ((val & 0x01) << 1));
-
-       err = m5602_write_sensor(sd, MT9M111_CP_OPERATING_MODE_CTL, data, 2);
-
-       PDEBUG(D_V4L2, "Set auto white balance %d", val);
-       return err;
-}
-
-static int mt9m111_get_auto_white_balance(struct gspca_dev *gspca_dev,
-                                         __s32 *val) {
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
-       PDEBUG(D_V4L2, "Read auto white balance %d", *val);
-       return 0;
-}
-
-static int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err, tmp;
-       u8 data[2] = {0x00, 0x00};
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       sensor_settings[GAIN_IDX] = val;
-
-       /* Set the correct page map */
-       err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
-       if (err < 0)
-               return err;
-
-       if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
-               return -EINVAL;
-
-       if ((val >= INITIAL_MAX_GAIN * 2 * 2) &&
-           (val < (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2))
-               tmp = (1 << 10) | (val << 9) |
-                               (val << 8) | (val / 8);
-       else if ((val >= INITIAL_MAX_GAIN * 2) &&
-                (val <  INITIAL_MAX_GAIN * 2 * 2))
-               tmp = (1 << 9) | (1 << 8) | (val / 4);
-       else if ((val >= INITIAL_MAX_GAIN) &&
-                (val < INITIAL_MAX_GAIN * 2))
-               tmp = (1 << 8) | (val / 2);
-       else
-               tmp = val;
-
-       data[1] = (tmp & 0xff);
-       data[0] = (tmp & 0xff00) >> 8;
-       PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
-              data[1], data[0]);
-
-       err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
-                                  data, 2);
-
-       return err;
-}
-
-static int mt9m111_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 data[2];
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       sensor_settings[GREEN_BALANCE_IDX] = val;
-       data[1] = (val & 0xff);
-       data[0] = (val & 0xff00) >> 8;
-
-       PDEBUG(D_V4L2, "Set green balance %d", val);
-       err = m5602_write_sensor(sd, MT9M111_SC_GREEN_1_GAIN,
-                                data, 2);
-       if (err < 0)
-               return err;
-
-       return m5602_write_sensor(sd, MT9M111_SC_GREEN_2_GAIN,
-                                 data, 2);
-}
-
-static int mt9m111_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[GREEN_BALANCE_IDX];
-       PDEBUG(D_V4L2, "Read green balance %d", *val);
-       return 0;
-}
-
-static int mt9m111_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
-{
-       u8 data[2];
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       sensor_settings[BLUE_BALANCE_IDX] = val;
-       data[1] = (val & 0xff);
-       data[0] = (val & 0xff00) >> 8;
-
-       PDEBUG(D_V4L2, "Set blue balance %d", val);
-
-       return m5602_write_sensor(sd, MT9M111_SC_BLUE_GAIN,
-                                 data, 2);
-}
-
-static int mt9m111_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[BLUE_BALANCE_IDX];
-       PDEBUG(D_V4L2, "Read blue balance %d", *val);
-       return 0;
-}
-
-static int mt9m111_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
-{
-       u8 data[2];
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       sensor_settings[RED_BALANCE_IDX] = val;
-       data[1] = (val & 0xff);
-       data[0] = (val & 0xff00) >> 8;
-
-       PDEBUG(D_V4L2, "Set red balance %d", val);
-
-       return m5602_write_sensor(sd, MT9M111_SC_RED_GAIN,
-                                 data, 2);
-}
-
-static int mt9m111_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[RED_BALANCE_IDX];
-       PDEBUG(D_V4L2, "Read red balance %d", *val);
-       return 0;
-}
-
-static void mt9m111_dump_registers(struct sd *sd)
-{
-       u8 address, value[2] = {0x00, 0x00};
-
-       pr_info("Dumping the mt9m111 register state\n");
-
-       pr_info("Dumping the mt9m111 sensor core registers\n");
-       value[1] = MT9M111_SENSOR_CORE;
-       m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
-       for (address = 0; address < 0xff; address++) {
-               m5602_read_sensor(sd, address, value, 2);
-               pr_info("register 0x%x contains 0x%x%x\n",
-                       address, value[0], value[1]);
-       }
-
-       pr_info("Dumping the mt9m111 color pipeline registers\n");
-       value[1] = MT9M111_COLORPIPE;
-       m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
-       for (address = 0; address < 0xff; address++) {
-               m5602_read_sensor(sd, address, value, 2);
-               pr_info("register 0x%x contains 0x%x%x\n",
-                       address, value[0], value[1]);
-       }
-
-       pr_info("Dumping the mt9m111 camera control registers\n");
-       value[1] = MT9M111_CAMERA_CONTROL;
-       m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
-       for (address = 0; address < 0xff; address++) {
-               m5602_read_sensor(sd, address, value, 2);
-               pr_info("register 0x%x contains 0x%x%x\n",
-                       address, value[0], value[1]);
-       }
-
-       pr_info("mt9m111 register state dump complete\n");
-}
diff --git a/drivers/media/video/gspca/m5602/m5602_mt9m111.h b/drivers/media/video/gspca/m5602/m5602_mt9m111.h
deleted file mode 100644 (file)
index 8c672b5..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Driver for the mt9m111 sensor
- *
- * Copyright (C) 2008 Erik Andrén
- * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * Some defines taken from the mt9m111 sensor driver
- * Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#ifndef M5602_MT9M111_H_
-#define M5602_MT9M111_H_
-
-#include "m5602_sensor.h"
-
-/*****************************************************************************/
-
-#define MT9M111_SC_CHIPVER                     0x00
-#define MT9M111_SC_ROWSTART                    0x01
-#define MT9M111_SC_COLSTART                    0x02
-#define MT9M111_SC_WINDOW_HEIGHT               0x03
-#define MT9M111_SC_WINDOW_WIDTH                        0x04
-#define MT9M111_SC_HBLANK_CONTEXT_B            0x05
-#define MT9M111_SC_VBLANK_CONTEXT_B            0x06
-#define MT9M111_SC_HBLANK_CONTEXT_A            0x07
-#define MT9M111_SC_VBLANK_CONTEXT_A            0x08
-#define MT9M111_SC_SHUTTER_WIDTH               0x09
-#define MT9M111_SC_ROW_SPEED                   0x0a
-#define MT9M111_SC_EXTRA_DELAY                 0x0b
-#define MT9M111_SC_SHUTTER_DELAY               0x0c
-#define MT9M111_SC_RESET                       0x0d
-#define MT9M111_SC_R_MODE_CONTEXT_B            0x20
-#define MT9M111_SC_R_MODE_CONTEXT_A            0x21
-#define MT9M111_SC_FLASH_CONTROL               0x23
-#define MT9M111_SC_GREEN_1_GAIN                        0x2b
-#define MT9M111_SC_BLUE_GAIN                   0x2c
-#define MT9M111_SC_RED_GAIN                    0x2d
-#define MT9M111_SC_GREEN_2_GAIN                        0x2e
-#define MT9M111_SC_GLOBAL_GAIN                 0x2f
-
-#define MT9M111_CONTEXT_CONTROL                        0xc8
-#define MT9M111_PAGE_MAP                       0xf0
-#define MT9M111_BYTEWISE_ADDRESS               0xf1
-
-#define MT9M111_CP_OPERATING_MODE_CTL          0x06
-#define MT9M111_CP_LUMA_OFFSET                 0x34
-#define MT9M111_CP_LUMA_CLIP                   0x35
-#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A 0x3a
-#define MT9M111_CP_LENS_CORRECTION_1           0x3b
-#define MT9M111_CP_DEFECT_CORR_CONTEXT_A       0x4c
-#define MT9M111_CP_DEFECT_CORR_CONTEXT_B       0x4d
-#define MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B 0x9b
-#define MT9M111_CP_GLOBAL_CLK_CONTROL          0xb3
-
-#define MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18   0x65
-#define MT9M111_CC_AWB_PARAMETER_7             0x28
-
-#define MT9M111_SENSOR_CORE                    0x00
-#define MT9M111_COLORPIPE                      0x01
-#define MT9M111_CAMERA_CONTROL                 0x02
-
-#define MT9M111_RESET                          (1 << 0)
-#define MT9M111_RESTART                                (1 << 1)
-#define MT9M111_ANALOG_STANDBY                 (1 << 2)
-#define MT9M111_CHIP_ENABLE                    (1 << 3)
-#define MT9M111_CHIP_DISABLE                   (0 << 3)
-#define MT9M111_OUTPUT_DISABLE                 (1 << 4)
-#define MT9M111_SHOW_BAD_FRAMES                        (1 << 0)
-#define MT9M111_RESTART_BAD_FRAMES             (1 << 1)
-#define MT9M111_SYNCHRONIZE_CHANGES            (1 << 7)
-
-#define MT9M111_RMB_OVER_SIZED                 (1 << 0)
-#define MT9M111_RMB_MIRROR_ROWS                        (1 << 0)
-#define MT9M111_RMB_MIRROR_COLS                        (1 << 1)
-#define MT9M111_RMB_ROW_SKIP_2X                        (1 << 2)
-#define MT9M111_RMB_COLUMN_SKIP_2X             (1 << 3)
-#define MT9M111_RMB_ROW_SKIP_4X                        (1 << 4)
-#define MT9M111_RMB_COLUMN_SKIP_4X             (1 << 5)
-
-#define MT9M111_COLOR_MATRIX_BYPASS            (1 << 4)
-#define MT9M111_SEL_CONTEXT_B                  (1 << 3)
-
-#define MT9M111_TRISTATE_PIN_IN_STANDBY                (1 << 1)
-#define MT9M111_SOC_SOFT_STANDBY               (1 << 0)
-
-#define MT9M111_2D_DEFECT_CORRECTION_ENABLE    (1 << 0)
-
-#define INITIAL_MAX_GAIN                       64
-#define MT9M111_DEFAULT_GAIN                   283
-#define MT9M111_GREEN_GAIN_DEFAULT             0x20
-#define MT9M111_BLUE_GAIN_DEFAULT              0x20
-#define MT9M111_RED_GAIN_DEFAULT               0x20
-
-/*****************************************************************************/
-
-/* Kernel module parameters */
-extern int force_sensor;
-extern bool dump_sensor;
-
-int mt9m111_probe(struct sd *sd);
-int mt9m111_init(struct sd *sd);
-int mt9m111_start(struct sd *sd);
-void mt9m111_disconnect(struct sd *sd);
-
-static const struct m5602_sensor mt9m111 = {
-       .name = "MT9M111",
-
-       .i2c_slave_id = 0xba,
-       .i2c_regW = 2,
-
-       .probe = mt9m111_probe,
-       .init = mt9m111_init,
-       .disconnect = mt9m111_disconnect,
-       .start = mt9m111_start,
-};
-
-static const unsigned char preinit_mt9m111[][4] = {
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-
-       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-       {SENSOR, MT9M111_SC_RESET,
-               MT9M111_RESET |
-               MT9M111_RESTART |
-               MT9M111_ANALOG_STANDBY |
-               MT9M111_CHIP_DISABLE,
-               MT9M111_SHOW_BAD_FRAMES |
-               MT9M111_RESTART_BAD_FRAMES |
-               MT9M111_SYNCHRONIZE_CHANGES},
-
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x05, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3e, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
-
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
-
-       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00}
-};
-
-static const unsigned char init_mt9m111[][4] = {
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x04, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3e, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x07, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x0b, 0x00},
-       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a, 0x00},
-
-       {SENSOR, MT9M111_SC_RESET, 0x00, 0x29},
-       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-       {SENSOR, MT9M111_SC_RESET, 0x00, 0x08},
-       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x01},
-       {SENSOR, MT9M111_CP_OPERATING_MODE_CTL, 0x00,
-                       MT9M111_CP_OPERATING_MODE_CTL},
-       {SENSOR, MT9M111_CP_LENS_CORRECTION_1, 0x04, 0x2a},
-       {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_A, 0x00,
-                               MT9M111_2D_DEFECT_CORRECTION_ENABLE},
-       {SENSOR, MT9M111_CP_DEFECT_CORR_CONTEXT_B, 0x00,
-                               MT9M111_2D_DEFECT_CORRECTION_ENABLE},
-       {SENSOR, MT9M111_CP_LUMA_OFFSET, 0x00, 0x00},
-       {SENSOR, MT9M111_CP_LUMA_CLIP, 0xff, 0x00},
-       {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_A, 0x14, 0x00},
-       {SENSOR, MT9M111_CP_OUTPUT_FORMAT_CTL2_CONTEXT_B, 0x14, 0x00},
-       {SENSOR, 0xcd, 0x00, 0x0e},
-       {SENSOR, 0xd0, 0x00, 0x40},
-
-       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x02},
-       {SENSOR, MT9M111_CC_AUTO_EXPOSURE_PARAMETER_18, 0x00, 0x00},
-       {SENSOR, MT9M111_CC_AWB_PARAMETER_7, 0xef, 0x03},
-
-       {SENSOR, MT9M111_PAGE_MAP, 0x00, 0x00},
-       {SENSOR, 0x33, 0x03, 0x49},
-       {SENSOR, 0x34, 0xc0, 0x19},
-       {SENSOR, 0x3f, 0x20, 0x20},
-       {SENSOR, 0x40, 0x20, 0x20},
-       {SENSOR, 0x5a, 0xc0, 0x0a},
-       {SENSOR, 0x70, 0x7b, 0x0a},
-       {SENSOR, 0x71, 0xff, 0x00},
-       {SENSOR, 0x72, 0x19, 0x0e},
-       {SENSOR, 0x73, 0x18, 0x0f},
-       {SENSOR, 0x74, 0x57, 0x32},
-       {SENSOR, 0x75, 0x56, 0x34},
-       {SENSOR, 0x76, 0x73, 0x35},
-       {SENSOR, 0x77, 0x30, 0x12},
-       {SENSOR, 0x78, 0x79, 0x02},
-       {SENSOR, 0x79, 0x75, 0x06},
-       {SENSOR, 0x7a, 0x77, 0x0a},
-       {SENSOR, 0x7b, 0x78, 0x09},
-       {SENSOR, 0x7c, 0x7d, 0x06},
-       {SENSOR, 0x7d, 0x31, 0x10},
-       {SENSOR, 0x7e, 0x00, 0x7e},
-       {SENSOR, 0x80, 0x59, 0x04},
-       {SENSOR, 0x81, 0x59, 0x04},
-       {SENSOR, 0x82, 0x57, 0x0a},
-       {SENSOR, 0x83, 0x58, 0x0b},
-       {SENSOR, 0x84, 0x47, 0x0c},
-       {SENSOR, 0x85, 0x48, 0x0e},
-       {SENSOR, 0x86, 0x5b, 0x02},
-       {SENSOR, 0x87, 0x00, 0x5c},
-       {SENSOR, MT9M111_CONTEXT_CONTROL, 0x00, MT9M111_SEL_CONTEXT_B},
-       {SENSOR, 0x60, 0x00, 0x80},
-       {SENSOR, 0x61, 0x00, 0x00},
-       {SENSOR, 0x62, 0x00, 0x00},
-       {SENSOR, 0x63, 0x00, 0x00},
-       {SENSOR, 0x64, 0x00, 0x00},
-
-       {SENSOR, MT9M111_SC_ROWSTART, 0x00, 0x0d}, /* 13 */
-       {SENSOR, MT9M111_SC_COLSTART, 0x00, 0x12}, /* 18 */
-       {SENSOR, MT9M111_SC_WINDOW_HEIGHT, 0x04, 0x00}, /* 1024 */
-       {SENSOR, MT9M111_SC_WINDOW_WIDTH, 0x05, 0x10}, /* 1296 */
-       {SENSOR, MT9M111_SC_HBLANK_CONTEXT_B, 0x01, 0x60}, /* 352 */
-       {SENSOR, MT9M111_SC_VBLANK_CONTEXT_B, 0x00, 0x11}, /* 17 */
-       {SENSOR, MT9M111_SC_HBLANK_CONTEXT_A, 0x01, 0x60}, /* 352 */
-       {SENSOR, MT9M111_SC_VBLANK_CONTEXT_A, 0x00, 0x11}, /* 17 */
-       {SENSOR, MT9M111_SC_R_MODE_CONTEXT_A, 0x01, 0x0f}, /* 271 */
-       {SENSOR, 0x30, 0x04, 0x00},
-       /* Set number of blank rows chosen to 400 */
-       {SENSOR, MT9M111_SC_SHUTTER_WIDTH, 0x01, 0x90},
-};
-
-static const unsigned char start_mt9m111[][4] = {
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
-       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-};
-#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.c b/drivers/media/video/gspca/m5602/m5602_ov7660.c
deleted file mode 100644 (file)
index 9a14835..0000000
+++ /dev/null
@@ -1,488 +0,0 @@
-/*
- * Driver for the ov7660 sensor
- *
- * Copyright (C) 2009 Erik Andrén
- * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "m5602_ov7660.h"
-
-static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
-                                        __s32 *val);
-static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
-                                        __s32 val);
-static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
-static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-
-static const struct ctrl ov7660_ctrls[] = {
-#define GAIN_IDX 1
-       {
-               {
-                       .id             = V4L2_CID_GAIN,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "gain",
-                       .minimum        = 0x00,
-                       .maximum        = 0xff,
-                       .step           = 0x1,
-                       .default_value  = OV7660_DEFAULT_GAIN,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = ov7660_set_gain,
-               .get = ov7660_get_gain
-       },
-#define BLUE_BALANCE_IDX 2
-#define RED_BALANCE_IDX 3
-#define AUTO_WHITE_BALANCE_IDX 4
-       {
-               {
-                       .id             = V4L2_CID_AUTO_WHITE_BALANCE,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "auto white balance",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 1
-               },
-               .set = ov7660_set_auto_white_balance,
-               .get = ov7660_get_auto_white_balance
-       },
-#define AUTO_GAIN_CTRL_IDX 5
-       {
-               {
-                       .id             = V4L2_CID_AUTOGAIN,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "auto gain control",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 1
-               },
-               .set = ov7660_set_auto_gain,
-               .get = ov7660_get_auto_gain
-       },
-#define AUTO_EXPOSURE_IDX 6
-       {
-               {
-                       .id             = V4L2_CID_EXPOSURE_AUTO,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "auto exposure",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 1
-               },
-               .set = ov7660_set_auto_exposure,
-               .get = ov7660_get_auto_exposure
-       },
-#define HFLIP_IDX 7
-       {
-               {
-                       .id             = V4L2_CID_HFLIP,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "horizontal flip",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 0
-               },
-               .set = ov7660_set_hflip,
-               .get = ov7660_get_hflip
-       },
-#define VFLIP_IDX 8
-       {
-               {
-                       .id             = V4L2_CID_VFLIP,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "vertical flip",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 0
-               },
-               .set = ov7660_set_vflip,
-               .get = ov7660_get_vflip
-       },
-
-};
-
-static struct v4l2_pix_format ov7660_modes[] = {
-       {
-               640,
-               480,
-               V4L2_PIX_FMT_SBGGR8,
-               V4L2_FIELD_NONE,
-               .sizeimage =
-                       640 * 480,
-               .bytesperline = 640,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0
-       }
-};
-
-static void ov7660_dump_registers(struct sd *sd);
-
-int ov7660_probe(struct sd *sd)
-{
-       int err = 0, i;
-       u8 prod_id = 0, ver_id = 0;
-
-       s32 *sensor_settings;
-
-       if (force_sensor) {
-               if (force_sensor == OV7660_SENSOR) {
-                       pr_info("Forcing an %s sensor\n", ov7660.name);
-                       goto sensor_found;
-               }
-               /* If we want to force another sensor,
-               don't try to probe this one */
-               return -ENODEV;
-       }
-
-       /* Do the preinit */
-       for (i = 0; i < ARRAY_SIZE(preinit_ov7660) && !err; i++) {
-               u8 data[2];
-
-               if (preinit_ov7660[i][0] == BRIDGE) {
-                       err = m5602_write_bridge(sd,
-                               preinit_ov7660[i][1],
-                               preinit_ov7660[i][2]);
-               } else {
-                       data[0] = preinit_ov7660[i][2];
-                       err = m5602_write_sensor(sd,
-                               preinit_ov7660[i][1], data, 1);
-               }
-       }
-       if (err < 0)
-               return err;
-
-       if (m5602_read_sensor(sd, OV7660_PID, &prod_id, 1))
-               return -ENODEV;
-
-       if (m5602_read_sensor(sd, OV7660_VER, &ver_id, 1))
-               return -ENODEV;
-
-       pr_info("Sensor reported 0x%x%x\n", prod_id, ver_id);
-
-       if ((prod_id == 0x76) && (ver_id == 0x60)) {
-               pr_info("Detected a ov7660 sensor\n");
-               goto sensor_found;
-       }
-       return -ENODEV;
-
-sensor_found:
-       sensor_settings = kmalloc(
-               ARRAY_SIZE(ov7660_ctrls) * sizeof(s32), GFP_KERNEL);
-       if (!sensor_settings)
-               return -ENOMEM;
-
-       sd->gspca_dev.cam.cam_mode = ov7660_modes;
-       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov7660_modes);
-       sd->desc->ctrls = ov7660_ctrls;
-       sd->desc->nctrls = ARRAY_SIZE(ov7660_ctrls);
-
-       for (i = 0; i < ARRAY_SIZE(ov7660_ctrls); i++)
-               sensor_settings[i] = ov7660_ctrls[i].qctrl.default_value;
-       sd->sensor_priv = sensor_settings;
-
-       return 0;
-}
-
-int ov7660_init(struct sd *sd)
-{
-       int i, err = 0;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       /* Init the sensor */
-       for (i = 0; i < ARRAY_SIZE(init_ov7660); i++) {
-               u8 data[2];
-
-               if (init_ov7660[i][0] == BRIDGE) {
-                       err = m5602_write_bridge(sd,
-                               init_ov7660[i][1],
-                               init_ov7660[i][2]);
-               } else {
-                       data[0] = init_ov7660[i][2];
-                       err = m5602_write_sensor(sd,
-                               init_ov7660[i][1], data, 1);
-               }
-       }
-
-       if (dump_sensor)
-               ov7660_dump_registers(sd);
-
-       err = ov7660_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
-       if (err < 0)
-               return err;
-
-       err = ov7660_set_auto_white_balance(&sd->gspca_dev,
-               sensor_settings[AUTO_WHITE_BALANCE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = ov7660_set_auto_gain(&sd->gspca_dev,
-               sensor_settings[AUTO_GAIN_CTRL_IDX]);
-       if (err < 0)
-               return err;
-
-       err = ov7660_set_auto_exposure(&sd->gspca_dev,
-               sensor_settings[AUTO_EXPOSURE_IDX]);
-       if (err < 0)
-               return err;
-       err = ov7660_set_hflip(&sd->gspca_dev,
-               sensor_settings[HFLIP_IDX]);
-       if (err < 0)
-               return err;
-
-       err = ov7660_set_vflip(&sd->gspca_dev,
-               sensor_settings[VFLIP_IDX]);
-
-       return err;
-}
-
-int ov7660_start(struct sd *sd)
-{
-       return 0;
-}
-
-int ov7660_stop(struct sd *sd)
-{
-       return 0;
-}
-
-void ov7660_disconnect(struct sd *sd)
-{
-       ov7660_stop(sd);
-
-       sd->sensor = NULL;
-       kfree(sd->sensor_priv);
-}
-
-static int ov7660_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[GAIN_IDX];
-       PDEBUG(D_V4L2, "Read gain %d", *val);
-       return 0;
-}
-
-static int ov7660_set_gain(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Setting gain to %d", val);
-
-       sensor_settings[GAIN_IDX] = val;
-
-       err = m5602_write_sensor(sd, OV7660_GAIN, &i2c_data, 1);
-       return err;
-}
-
-
-static int ov7660_get_auto_white_balance(struct gspca_dev *gspca_dev,
-                                        __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
-       return 0;
-}
-
-static int ov7660_set_auto_white_balance(struct gspca_dev *gspca_dev,
-                                        __s32 val)
-{
-       int err;
-       u8 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Set auto white balance to %d", val);
-
-       sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
-       err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
-       err = m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
-
-       return err;
-}
-
-static int ov7660_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
-       PDEBUG(D_V4L2, "Read auto gain control %d", *val);
-       return 0;
-}
-
-static int ov7660_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Set auto gain control to %d", val);
-
-       sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
-       err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
-
-       return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
-}
-
-static int ov7660_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[AUTO_EXPOSURE_IDX];
-       PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
-       return 0;
-}
-
-static int ov7660_set_auto_exposure(struct gspca_dev *gspca_dev,
-                                   __s32 val)
-{
-       int err;
-       u8 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
-
-       sensor_settings[AUTO_EXPOSURE_IDX] = val;
-       err = m5602_read_sensor(sd, OV7660_COM8, &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
-
-       return m5602_write_sensor(sd, OV7660_COM8, &i2c_data, 1);
-}
-
-static int ov7660_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[HFLIP_IDX];
-       PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
-       return 0;
-}
-
-static int ov7660_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
-
-       sensor_settings[HFLIP_IDX] = val;
-
-       i2c_data = ((val & 0x01) << 5) |
-               (sensor_settings[VFLIP_IDX] << 4);
-
-       err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
-
-       return err;
-}
-
-static int ov7660_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[VFLIP_IDX];
-       PDEBUG(D_V4L2, "Read vertical flip %d", *val);
-
-       return 0;
-}
-
-static int ov7660_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Set vertical flip to %d", val);
-       sensor_settings[VFLIP_IDX] = val;
-
-       i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
-       err = m5602_write_sensor(sd, OV7660_MVFP, &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       /* When vflip is toggled we need to readjust the bridge hsync/vsync */
-       if (gspca_dev->streaming)
-               err = ov7660_start(sd);
-
-       return err;
-}
-
-static void ov7660_dump_registers(struct sd *sd)
-{
-       int address;
-       pr_info("Dumping the ov7660 register state\n");
-       for (address = 0; address < 0xa9; address++) {
-               u8 value;
-               m5602_read_sensor(sd, address, &value, 1);
-               pr_info("register 0x%x contains 0x%x\n", address, value);
-       }
-
-       pr_info("ov7660 register state dump complete\n");
-
-       pr_info("Probing for which registers that are read/write\n");
-       for (address = 0; address < 0xff; address++) {
-               u8 old_value, ctrl_value;
-               u8 test_value[2] = {0xff, 0xff};
-
-               m5602_read_sensor(sd, address, &old_value, 1);
-               m5602_write_sensor(sd, address, test_value, 1);
-               m5602_read_sensor(sd, address, &ctrl_value, 1);
-
-               if (ctrl_value == test_value[0])
-                       pr_info("register 0x%x is writeable\n", address);
-               else
-                       pr_info("register 0x%x is read only\n", address);
-
-               /* Restore original value */
-               m5602_write_sensor(sd, address, &old_value, 1);
-       }
-}
diff --git a/drivers/media/video/gspca/m5602/m5602_ov7660.h b/drivers/media/video/gspca/m5602/m5602_ov7660.h
deleted file mode 100644 (file)
index 2b6a13b..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Driver for the ov7660 sensor
- *
- * Copyright (C) 2009 Erik Andrén
- * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#ifndef M5602_OV7660_H_
-#define M5602_OV7660_H_
-
-#include "m5602_sensor.h"
-
-#define OV7660_GAIN            0x00
-#define OV7660_BLUE_GAIN       0x01
-#define OV7660_RED_GAIN                0x02
-#define OV7660_VREF            0x03
-#define OV7660_COM1            0x04
-#define OV7660_BAVE            0x05
-#define OV7660_GEAVE           0x06
-#define OV7660_AECHH           0x07
-#define OV7660_RAVE            0x08
-#define OV7660_COM2            0x09
-#define OV7660_PID             0x0a
-#define OV7660_VER             0x0b
-#define OV7660_COM3            0x0c
-#define OV7660_COM4            0x0d
-#define OV7660_COM5            0x0e
-#define OV7660_COM6            0x0f
-#define OV7660_AECH            0x10
-#define OV7660_CLKRC           0x11
-#define OV7660_COM7            0x12
-#define OV7660_COM8            0x13
-#define OV7660_COM9            0x14
-#define OV7660_COM10           0x15
-#define OV7660_RSVD16          0x16
-#define OV7660_HSTART          0x17
-#define OV7660_HSTOP           0x18
-#define OV7660_VSTART          0x19
-#define OV7660_VSTOP           0x1a
-#define OV7660_PSHFT           0x1b
-#define OV7660_MIDH            0x1c
-#define OV7660_MIDL            0x1d
-#define OV7660_MVFP            0x1e
-#define OV7660_LAEC            0x1f
-#define OV7660_BOS             0x20
-#define OV7660_GBOS            0x21
-#define OV7660_GROS            0x22
-#define OV7660_ROS             0x23
-#define OV7660_AEW             0x24
-#define OV7660_AEB             0x25
-#define OV7660_VPT             0x26
-#define OV7660_BBIAS           0x27
-#define OV7660_GbBIAS          0x28
-#define OV7660_RSVD29          0x29
-#define OV7660_RBIAS           0x2c
-#define OV7660_HREF            0x32
-#define OV7660_ADC             0x37
-#define OV7660_OFON            0x39
-#define OV7660_TSLB            0x3a
-#define OV7660_COM12           0x3c
-#define OV7660_COM13           0x3d
-#define OV7660_LCC1            0x62
-#define OV7660_LCC2            0x63
-#define OV7660_LCC3            0x64
-#define OV7660_LCC4            0x65
-#define OV7660_LCC5            0x66
-#define OV7660_HV              0x69
-#define OV7660_RSVDA1          0xa1
-
-#define OV7660_DEFAULT_GAIN            0x0e
-#define OV7660_DEFAULT_RED_GAIN                0x80
-#define OV7660_DEFAULT_BLUE_GAIN       0x80
-#define OV7660_DEFAULT_SATURATION      0x00
-#define OV7660_DEFAULT_EXPOSURE                0x20
-
-/* Kernel module parameters */
-extern int force_sensor;
-extern bool dump_sensor;
-
-int ov7660_probe(struct sd *sd);
-int ov7660_init(struct sd *sd);
-int ov7660_start(struct sd *sd);
-int ov7660_stop(struct sd *sd);
-void ov7660_disconnect(struct sd *sd);
-
-static const struct m5602_sensor ov7660 = {
-       .name = "ov7660",
-       .i2c_slave_id = 0x42,
-       .i2c_regW = 1,
-       .probe = ov7660_probe,
-       .init = ov7660_init,
-       .start = ov7660_start,
-       .stop = ov7660_stop,
-       .disconnect = ov7660_disconnect,
-};
-
-static const unsigned char preinit_ov7660[][4] = {
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
-       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x03},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x03},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-
-       {SENSOR, OV7660_OFON, 0x0c},
-       {SENSOR, OV7660_COM2, 0x11},
-       {SENSOR, OV7660_COM7, 0x05},
-
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00}
-};
-
-static const unsigned char init_ov7660[][4] = {
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d},
-       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
-       {SENSOR, OV7660_COM7, 0x80},
-       {SENSOR, OV7660_CLKRC, 0x80},
-       {SENSOR, OV7660_COM9, 0x4c},
-       {SENSOR, OV7660_OFON, 0x43},
-       {SENSOR, OV7660_COM12, 0x28},
-       {SENSOR, OV7660_COM8, 0x00},
-       {SENSOR, OV7660_COM10, 0x40},
-       {SENSOR, OV7660_HSTART, 0x0c},
-       {SENSOR, OV7660_HSTOP, 0x61},
-       {SENSOR, OV7660_HREF, 0xa4},
-       {SENSOR, OV7660_PSHFT, 0x0b},
-       {SENSOR, OV7660_VSTART, 0x01},
-       {SENSOR, OV7660_VSTOP, 0x7a},
-       {SENSOR, OV7660_VSTOP, 0x00},
-       {SENSOR, OV7660_COM7, 0x05},
-       {SENSOR, OV7660_COM6, 0x42},
-       {SENSOR, OV7660_BBIAS, 0x94},
-       {SENSOR, OV7660_GbBIAS, 0x94},
-       {SENSOR, OV7660_RSVD29, 0x94},
-       {SENSOR, OV7660_RBIAS, 0x94},
-       {SENSOR, OV7660_COM1, 0x00},
-       {SENSOR, OV7660_AECH, 0x00},
-       {SENSOR, OV7660_AECHH, 0x00},
-       {SENSOR, OV7660_ADC, 0x05},
-       {SENSOR, OV7660_COM13, 0x00},
-       {SENSOR, OV7660_RSVDA1, 0x23},
-       {SENSOR, OV7660_TSLB, 0x0d},
-       {SENSOR, OV7660_HV, 0x80},
-       {SENSOR, OV7660_LCC1, 0x00},
-       {SENSOR, OV7660_LCC2, 0x00},
-       {SENSOR, OV7660_LCC3, 0x10},
-       {SENSOR, OV7660_LCC4, 0x40},
-       {SENSOR, OV7660_LCC5, 0x01},
-
-       {SENSOR, OV7660_AECH, 0x20},
-       {SENSOR, OV7660_COM1, 0x00},
-       {SENSOR, OV7660_OFON, 0x0c},
-       {SENSOR, OV7660_COM2, 0x11},
-       {SENSOR, OV7660_COM7, 0x05},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
-       {SENSOR, OV7660_AECH, 0x5f},
-       {SENSOR, OV7660_COM1, 0x03},
-       {SENSOR, OV7660_OFON, 0x0c},
-       {SENSOR, OV7660_COM2, 0x11},
-       {SENSOR, OV7660_COM7, 0x05},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x01},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x08},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
-
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81},
-       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
-       {BRIDGE, M5602_XB_SIG_INI, 0x01},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x08},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0xec},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x02},
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00},
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x27},
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02},
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0xa7},
-       {BRIDGE, M5602_XB_SIG_INI, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-};
-#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.c b/drivers/media/video/gspca/m5602/m5602_ov9650.c
deleted file mode 100644 (file)
index 2114a8b..0000000
+++ /dev/null
@@ -1,881 +0,0 @@
-/*
- * Driver for the ov9650 sensor
- *
- * Copyright (C) 2008 Erik Andrén
- * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "m5602_ov9650.h"
-
-static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
-                                        __s32 *val);
-static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
-                                        __s32 val);
-static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev, __s32 val);
-
-/* Vertically and horizontally flips the image if matched, needed for machines
-   where the sensor is mounted upside down */
-static
-    const
-       struct dmi_system_id ov9650_flip_dmi_table[] = {
-       {
-               .ident = "ASUS A6Ja",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "A6J")
-               }
-       },
-       {
-               .ident = "ASUS A6JC",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "A6JC")
-               }
-       },
-       {
-               .ident = "ASUS A6K",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "A6K")
-               }
-       },
-       {
-               .ident = "ASUS A6Kt",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "A6Kt")
-               }
-       },
-       {
-               .ident = "ASUS A6VA",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "A6VA")
-               }
-       },
-       {
-
-               .ident = "ASUS A6VC",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "A6VC")
-               }
-       },
-       {
-               .ident = "ASUS A6VM",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "A6VM")
-               }
-       },
-       {
-               .ident = "ASUS A7V",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "A7V")
-               }
-       },
-       {
-               .ident = "Alienware Aurora m9700",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "alienware"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Aurora m9700")
-               }
-       },
-       {}
-};
-
-static const struct ctrl ov9650_ctrls[] = {
-#define EXPOSURE_IDX 0
-       {
-               {
-                       .id             = V4L2_CID_EXPOSURE,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "exposure",
-                       .minimum        = 0x00,
-                       .maximum        = 0x1ff,
-                       .step           = 0x4,
-                       .default_value  = EXPOSURE_DEFAULT,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = ov9650_set_exposure,
-               .get = ov9650_get_exposure
-       },
-#define GAIN_IDX 1
-       {
-               {
-                       .id             = V4L2_CID_GAIN,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "gain",
-                       .minimum        = 0x00,
-                       .maximum        = 0x3ff,
-                       .step           = 0x1,
-                       .default_value  = GAIN_DEFAULT,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = ov9650_set_gain,
-               .get = ov9650_get_gain
-       },
-#define RED_BALANCE_IDX 2
-       {
-               {
-                       .id             = V4L2_CID_RED_BALANCE,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "red balance",
-                       .minimum        = 0x00,
-                       .maximum        = 0xff,
-                       .step           = 0x1,
-                       .default_value  = RED_GAIN_DEFAULT,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = ov9650_set_red_balance,
-               .get = ov9650_get_red_balance
-       },
-#define BLUE_BALANCE_IDX 3
-       {
-               {
-                       .id             = V4L2_CID_BLUE_BALANCE,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "blue balance",
-                       .minimum        = 0x00,
-                       .maximum        = 0xff,
-                       .step           = 0x1,
-                       .default_value  = BLUE_GAIN_DEFAULT,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = ov9650_set_blue_balance,
-               .get = ov9650_get_blue_balance
-       },
-#define HFLIP_IDX 4
-       {
-               {
-                       .id             = V4L2_CID_HFLIP,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "horizontal flip",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 0
-               },
-               .set = ov9650_set_hflip,
-               .get = ov9650_get_hflip
-       },
-#define VFLIP_IDX 5
-       {
-               {
-                       .id             = V4L2_CID_VFLIP,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "vertical flip",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 0
-               },
-               .set = ov9650_set_vflip,
-               .get = ov9650_get_vflip
-       },
-#define AUTO_WHITE_BALANCE_IDX 6
-       {
-               {
-                       .id             = V4L2_CID_AUTO_WHITE_BALANCE,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "auto white balance",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 1
-               },
-               .set = ov9650_set_auto_white_balance,
-               .get = ov9650_get_auto_white_balance
-       },
-#define AUTO_GAIN_CTRL_IDX 7
-       {
-               {
-                       .id             = V4L2_CID_AUTOGAIN,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "auto gain control",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 1
-               },
-               .set = ov9650_set_auto_gain,
-               .get = ov9650_get_auto_gain
-       },
-#define AUTO_EXPOSURE_IDX 8
-       {
-               {
-                       .id             = V4L2_CID_EXPOSURE_AUTO,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "auto exposure",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 1
-               },
-               .set = ov9650_set_auto_exposure,
-               .get = ov9650_get_auto_exposure
-       }
-
-};
-
-static struct v4l2_pix_format ov9650_modes[] = {
-       {
-               176,
-               144,
-               V4L2_PIX_FMT_SBGGR8,
-               V4L2_FIELD_NONE,
-               .sizeimage =
-                       176 * 144,
-               .bytesperline = 176,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 9
-       }, {
-               320,
-               240,
-               V4L2_PIX_FMT_SBGGR8,
-               V4L2_FIELD_NONE,
-               .sizeimage =
-                       320 * 240,
-               .bytesperline = 320,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 8
-       }, {
-               352,
-               288,
-               V4L2_PIX_FMT_SBGGR8,
-               V4L2_FIELD_NONE,
-               .sizeimage =
-                       352 * 288,
-               .bytesperline = 352,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 9
-       }, {
-               640,
-               480,
-               V4L2_PIX_FMT_SBGGR8,
-               V4L2_FIELD_NONE,
-               .sizeimage =
-                       640 * 480,
-               .bytesperline = 640,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 9
-       }
-};
-
-static void ov9650_dump_registers(struct sd *sd);
-
-int ov9650_probe(struct sd *sd)
-{
-       int err = 0;
-       u8 prod_id = 0, ver_id = 0, i;
-       s32 *sensor_settings;
-
-       if (force_sensor) {
-               if (force_sensor == OV9650_SENSOR) {
-                       pr_info("Forcing an %s sensor\n", ov9650.name);
-                       goto sensor_found;
-               }
-               /* If we want to force another sensor,
-                  don't try to probe this one */
-               return -ENODEV;
-       }
-
-       PDEBUG(D_PROBE, "Probing for an ov9650 sensor");
-
-       /* Run the pre-init before probing the sensor */
-       for (i = 0; i < ARRAY_SIZE(preinit_ov9650) && !err; i++) {
-               u8 data = preinit_ov9650[i][2];
-               if (preinit_ov9650[i][0] == SENSOR)
-                       err = m5602_write_sensor(sd,
-                               preinit_ov9650[i][1], &data, 1);
-               else
-                       err = m5602_write_bridge(sd,
-                               preinit_ov9650[i][1], data);
-       }
-
-       if (err < 0)
-               return err;
-
-       if (m5602_read_sensor(sd, OV9650_PID, &prod_id, 1))
-               return -ENODEV;
-
-       if (m5602_read_sensor(sd, OV9650_VER, &ver_id, 1))
-               return -ENODEV;
-
-       if ((prod_id == 0x96) && (ver_id == 0x52)) {
-               pr_info("Detected an ov9650 sensor\n");
-               goto sensor_found;
-       }
-       return -ENODEV;
-
-sensor_found:
-       sensor_settings = kmalloc(
-               ARRAY_SIZE(ov9650_ctrls) * sizeof(s32), GFP_KERNEL);
-       if (!sensor_settings)
-               return -ENOMEM;
-
-       sd->gspca_dev.cam.cam_mode = ov9650_modes;
-       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(ov9650_modes);
-       sd->desc->ctrls = ov9650_ctrls;
-       sd->desc->nctrls = ARRAY_SIZE(ov9650_ctrls);
-
-       for (i = 0; i < ARRAY_SIZE(ov9650_ctrls); i++)
-               sensor_settings[i] = ov9650_ctrls[i].qctrl.default_value;
-       sd->sensor_priv = sensor_settings;
-       return 0;
-}
-
-int ov9650_init(struct sd *sd)
-{
-       int i, err = 0;
-       u8 data;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       if (dump_sensor)
-               ov9650_dump_registers(sd);
-
-       for (i = 0; i < ARRAY_SIZE(init_ov9650) && !err; i++) {
-               data = init_ov9650[i][2];
-               if (init_ov9650[i][0] == SENSOR)
-                       err = m5602_write_sensor(sd, init_ov9650[i][1],
-                                                 &data, 1);
-               else
-                       err = m5602_write_bridge(sd, init_ov9650[i][1], data);
-       }
-
-       err = ov9650_set_exposure(&sd->gspca_dev,
-                                  sensor_settings[EXPOSURE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = ov9650_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
-       if (err < 0)
-               return err;
-
-       err = ov9650_set_red_balance(&sd->gspca_dev,
-                                     sensor_settings[RED_BALANCE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = ov9650_set_blue_balance(&sd->gspca_dev,
-                                      sensor_settings[BLUE_BALANCE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = ov9650_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
-       if (err < 0)
-               return err;
-
-       err = ov9650_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
-       if (err < 0)
-               return err;
-
-       err = ov9650_set_auto_exposure(&sd->gspca_dev,
-                               sensor_settings[AUTO_EXPOSURE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = ov9650_set_auto_white_balance(&sd->gspca_dev,
-                               sensor_settings[AUTO_WHITE_BALANCE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = ov9650_set_auto_gain(&sd->gspca_dev,
-                               sensor_settings[AUTO_GAIN_CTRL_IDX]);
-       return err;
-}
-
-int ov9650_start(struct sd *sd)
-{
-       u8 data;
-       int i, err = 0;
-       struct cam *cam = &sd->gspca_dev.cam;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
-       int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
-       int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
-       int hor_offs = OV9650_LEFT_OFFSET;
-
-       if ((!dmi_check_system(ov9650_flip_dmi_table) &&
-               sensor_settings[VFLIP_IDX]) ||
-               (dmi_check_system(ov9650_flip_dmi_table) &&
-               !sensor_settings[VFLIP_IDX]))
-               ver_offs--;
-
-       if (width <= 320)
-               hor_offs /= 2;
-
-       /* Synthesize the vsync/hsync setup */
-       for (i = 0; i < ARRAY_SIZE(res_init_ov9650) && !err; i++) {
-               if (res_init_ov9650[i][0] == BRIDGE)
-                       err = m5602_write_bridge(sd, res_init_ov9650[i][1],
-                               res_init_ov9650[i][2]);
-               else if (res_init_ov9650[i][0] == SENSOR) {
-                       data = res_init_ov9650[i][2];
-                       err = m5602_write_sensor(sd,
-                               res_init_ov9650[i][1], &data, 1);
-               }
-       }
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
-                                ((ver_offs >> 8) & 0xff));
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
-       if (err < 0)
-               return err;
-
-       for (i = 0; i < 2 && !err; i++)
-               err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 2);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
-                                (hor_offs >> 8) & 0xff);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, hor_offs & 0xff);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
-                                ((width + hor_offs) >> 8) & 0xff);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA,
-                                ((width + hor_offs) & 0xff));
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
-       if (err < 0)
-               return err;
-
-       switch (width) {
-       case 640:
-               PDEBUG(D_V4L2, "Configuring camera for VGA mode");
-
-               data = OV9650_VGA_SELECT | OV9650_RGB_SELECT |
-                      OV9650_RAW_RGB_SELECT;
-               err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
-               break;
-
-       case 352:
-               PDEBUG(D_V4L2, "Configuring camera for CIF mode");
-
-               data = OV9650_CIF_SELECT | OV9650_RGB_SELECT |
-                               OV9650_RAW_RGB_SELECT;
-               err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
-               break;
-
-       case 320:
-               PDEBUG(D_V4L2, "Configuring camera for QVGA mode");
-
-               data = OV9650_QVGA_SELECT | OV9650_RGB_SELECT |
-                               OV9650_RAW_RGB_SELECT;
-               err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
-               break;
-
-       case 176:
-               PDEBUG(D_V4L2, "Configuring camera for QCIF mode");
-
-               data = OV9650_QCIF_SELECT | OV9650_RGB_SELECT |
-                       OV9650_RAW_RGB_SELECT;
-               err = m5602_write_sensor(sd, OV9650_COM7, &data, 1);
-               break;
-       }
-       return err;
-}
-
-int ov9650_stop(struct sd *sd)
-{
-       u8 data = OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X;
-       return m5602_write_sensor(sd, OV9650_COM2, &data, 1);
-}
-
-void ov9650_disconnect(struct sd *sd)
-{
-       ov9650_stop(sd);
-
-       sd->sensor = NULL;
-       kfree(sd->sensor_priv);
-}
-
-static int ov9650_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[EXPOSURE_IDX];
-       PDEBUG(D_V4L2, "Read exposure %d", *val);
-       return 0;
-}
-
-static int ov9650_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 i2c_data;
-       int err;
-
-       PDEBUG(D_V4L2, "Set exposure to %d", val);
-
-       sensor_settings[EXPOSURE_IDX] = val;
-       /* The 6 MSBs */
-       i2c_data = (val >> 10) & 0x3f;
-       err = m5602_write_sensor(sd, OV9650_AECHM,
-                                 &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       /* The 8 middle bits */
-       i2c_data = (val >> 2) & 0xff;
-       err = m5602_write_sensor(sd, OV9650_AECH,
-                                 &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       /* The 2 LSBs */
-       i2c_data = val & 0x03;
-       err = m5602_write_sensor(sd, OV9650_COM1, &i2c_data, 1);
-       return err;
-}
-
-static int ov9650_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[GAIN_IDX];
-       PDEBUG(D_V4L2, "Read gain %d", *val);
-       return 0;
-}
-
-static int ov9650_set_gain(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Setting gain to %d", val);
-
-       sensor_settings[GAIN_IDX] = val;
-
-       /* The 2 MSB */
-       /* Read the OV9650_VREF register first to avoid
-          corrupting the VREF high and low bits */
-       err = m5602_read_sensor(sd, OV9650_VREF, &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       /* Mask away all uninteresting bits */
-       i2c_data = ((val & 0x0300) >> 2) |
-                       (i2c_data & 0x3f);
-       err = m5602_write_sensor(sd, OV9650_VREF, &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       /* The 8 LSBs */
-       i2c_data = val & 0xff;
-       err = m5602_write_sensor(sd, OV9650_GAIN, &i2c_data, 1);
-       return err;
-}
-
-static int ov9650_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[RED_BALANCE_IDX];
-       PDEBUG(D_V4L2, "Read red gain %d", *val);
-       return 0;
-}
-
-static int ov9650_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Set red gain to %d", val);
-
-       sensor_settings[RED_BALANCE_IDX] = val;
-
-       i2c_data = val & 0xff;
-       err = m5602_write_sensor(sd, OV9650_RED, &i2c_data, 1);
-       return err;
-}
-
-static int ov9650_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[BLUE_BALANCE_IDX];
-       PDEBUG(D_V4L2, "Read blue gain %d", *val);
-
-       return 0;
-}
-
-static int ov9650_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Set blue gain to %d", val);
-
-       sensor_settings[BLUE_BALANCE_IDX] = val;
-
-       i2c_data = val & 0xff;
-       err = m5602_write_sensor(sd, OV9650_BLUE, &i2c_data, 1);
-       return err;
-}
-
-static int ov9650_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[HFLIP_IDX];
-       PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
-       return 0;
-}
-
-static int ov9650_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
-
-       sensor_settings[HFLIP_IDX] = val;
-
-       if (!dmi_check_system(ov9650_flip_dmi_table))
-               i2c_data = ((val & 0x01) << 5) |
-                               (sensor_settings[VFLIP_IDX] << 4);
-       else
-               i2c_data = ((val & 0x01) << 5) |
-                               (!sensor_settings[VFLIP_IDX] << 4);
-
-       err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
-
-       return err;
-}
-
-static int ov9650_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[VFLIP_IDX];
-       PDEBUG(D_V4L2, "Read vertical flip %d", *val);
-
-       return 0;
-}
-
-static int ov9650_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Set vertical flip to %d", val);
-       sensor_settings[VFLIP_IDX] = val;
-
-       if (dmi_check_system(ov9650_flip_dmi_table))
-               val = !val;
-
-       i2c_data = ((val & 0x01) << 4) | (sensor_settings[VFLIP_IDX] << 5);
-       err = m5602_write_sensor(sd, OV9650_MVFP, &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       /* When vflip is toggled we need to readjust the bridge hsync/vsync */
-       if (gspca_dev->streaming)
-               err = ov9650_start(sd);
-
-       return err;
-}
-
-static int ov9650_get_auto_exposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[AUTO_EXPOSURE_IDX];
-       PDEBUG(D_V4L2, "Read auto exposure control %d", *val);
-       return 0;
-}
-
-static int ov9650_set_auto_exposure(struct gspca_dev *gspca_dev,
-                                   __s32 val)
-{
-       int err;
-       u8 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Set auto exposure control to %d", val);
-
-       sensor_settings[AUTO_EXPOSURE_IDX] = val;
-       err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       i2c_data = ((i2c_data & 0xfe) | ((val & 0x01) << 0));
-
-       return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
-}
-
-static int ov9650_get_auto_white_balance(struct gspca_dev *gspca_dev,
-                                        __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
-       return 0;
-}
-
-static int ov9650_set_auto_white_balance(struct gspca_dev *gspca_dev,
-                                        __s32 val)
-{
-       int err;
-       u8 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Set auto white balance to %d", val);
-
-       sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
-       err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       i2c_data = ((i2c_data & 0xfd) | ((val & 0x01) << 1));
-       err = m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
-
-       return err;
-}
-
-static int ov9650_get_auto_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[AUTO_GAIN_CTRL_IDX];
-       PDEBUG(D_V4L2, "Read auto gain control %d", *val);
-       return 0;
-}
-
-static int ov9650_set_auto_gain(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       PDEBUG(D_V4L2, "Set auto gain control to %d", val);
-
-       sensor_settings[AUTO_GAIN_CTRL_IDX] = val;
-       err = m5602_read_sensor(sd, OV9650_COM8, &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       i2c_data = ((i2c_data & 0xfb) | ((val & 0x01) << 2));
-
-       return m5602_write_sensor(sd, OV9650_COM8, &i2c_data, 1);
-}
-
-static void ov9650_dump_registers(struct sd *sd)
-{
-       int address;
-       pr_info("Dumping the ov9650 register state\n");
-       for (address = 0; address < 0xa9; address++) {
-               u8 value;
-               m5602_read_sensor(sd, address, &value, 1);
-               pr_info("register 0x%x contains 0x%x\n", address, value);
-       }
-
-       pr_info("ov9650 register state dump complete\n");
-
-       pr_info("Probing for which registers that are read/write\n");
-       for (address = 0; address < 0xff; address++) {
-               u8 old_value, ctrl_value;
-               u8 test_value[2] = {0xff, 0xff};
-
-               m5602_read_sensor(sd, address, &old_value, 1);
-               m5602_write_sensor(sd, address, test_value, 1);
-               m5602_read_sensor(sd, address, &ctrl_value, 1);
-
-               if (ctrl_value == test_value[0])
-                       pr_info("register 0x%x is writeable\n", address);
-               else
-                       pr_info("register 0x%x is read only\n", address);
-
-               /* Restore original value */
-               m5602_write_sensor(sd, address, &old_value, 1);
-       }
-}
diff --git a/drivers/media/video/gspca/m5602/m5602_ov9650.h b/drivers/media/video/gspca/m5602/m5602_ov9650.h
deleted file mode 100644 (file)
index f7aa5bf..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Driver for the ov9650 sensor
- *
- * Copyright (C) 2008 Erik Andrén
- * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#ifndef M5602_OV9650_H_
-#define M5602_OV9650_H_
-
-#include <linux/dmi.h>
-#include "m5602_sensor.h"
-
-/*****************************************************************************/
-
-#define OV9650_GAIN                    0x00
-#define OV9650_BLUE                    0x01
-#define OV9650_RED                     0x02
-#define OV9650_VREF                    0x03
-#define OV9650_COM1                    0x04
-#define OV9650_BAVE                    0x05
-#define OV9650_GEAVE                   0x06
-#define OV9650_RSVD7                   0x07
-#define OV9650_COM2                    0x09
-#define OV9650_PID                     0x0a
-#define OV9650_VER                     0x0b
-#define OV9650_COM3                    0x0c
-#define OV9650_COM4                    0x0d
-#define OV9650_COM5                    0x0e
-#define OV9650_COM6                    0x0f
-#define OV9650_AECH                    0x10
-#define OV9650_CLKRC                   0x11
-#define OV9650_COM7                    0x12
-#define OV9650_COM8                    0x13
-#define OV9650_COM9                    0x14
-#define OV9650_COM10                   0x15
-#define OV9650_RSVD16                  0x16
-#define OV9650_HSTART                  0x17
-#define OV9650_HSTOP                   0x18
-#define OV9650_VSTRT                   0x19
-#define OV9650_VSTOP                   0x1a
-#define OV9650_PSHFT                   0x1b
-#define OV9650_MVFP                    0x1e
-#define OV9650_AEW                     0x24
-#define OV9650_AEB                     0x25
-#define OV9650_VPT                     0x26
-#define OV9650_BBIAS                   0x27
-#define OV9650_GbBIAS                  0x28
-#define OV9650_Gr_COM                  0x29
-#define OV9650_RBIAS                   0x2c
-#define OV9650_HREF                    0x32
-#define OV9650_CHLF                    0x33
-#define OV9650_ARBLM                   0x34
-#define OV9650_RSVD35                  0x35
-#define OV9650_RSVD36                  0x36
-#define OV9650_ADC                     0x37
-#define OV9650_ACOM38                  0x38
-#define OV9650_OFON                    0x39
-#define OV9650_TSLB                    0x3a
-#define OV9650_COM12                   0x3c
-#define OV9650_COM13                   0x3d
-#define OV9650_COM15                   0x40
-#define OV9650_COM16                   0x41
-#define OV9650_LCC1                    0x62
-#define OV9650_LCC2                    0x63
-#define OV9650_LCC3                    0x64
-#define OV9650_LCC4                    0x65
-#define OV9650_LCC5                    0x66
-#define OV9650_HV                      0x69
-#define OV9650_DBLV                    0x6b
-#define OV9650_COM21                   0x8b
-#define OV9650_COM22                   0x8c
-#define OV9650_COM24                   0x8e
-#define OV9650_DBLC1                   0x8f
-#define OV9650_RSVD94                  0x94
-#define OV9650_RSVD95                  0x95
-#define OV9650_RSVD96                  0x96
-#define OV9650_LCCFB                   0x9d
-#define OV9650_LCCFR                   0x9e
-#define OV9650_AECHM                   0xa1
-#define OV9650_COM26                   0xa5
-#define OV9650_ACOMA8                  0xa8
-#define OV9650_ACOMA9                  0xa9
-
-#define OV9650_REGISTER_RESET          (1 << 7)
-#define OV9650_VGA_SELECT              (1 << 6)
-#define OV9650_CIF_SELECT              (1 << 5)
-#define OV9650_QVGA_SELECT             (1 << 4)
-#define OV9650_QCIF_SELECT             (1 << 3)
-#define OV9650_RGB_SELECT              (1 << 2)
-#define OV9650_RAW_RGB_SELECT          (1 << 0)
-
-#define OV9650_FAST_AGC_AEC            (1 << 7)
-#define OV9650_AEC_UNLIM_STEP_SIZE     (1 << 6)
-#define OV9650_BANDING                 (1 << 5)
-#define OV9650_AGC_EN                  (1 << 2)
-#define OV9650_AWB_EN                  (1 << 1)
-#define OV9650_AEC_EN                  (1 << 0)
-
-#define OV9650_VARIOPIXEL              (1 << 2)
-#define OV9650_SYSTEM_CLK_SEL          (1 << 7)
-#define OV9650_SLAM_MODE               (1 << 4)
-
-#define OV9650_QVGA_VARIOPIXEL         (1 << 7)
-
-#define OV9650_VFLIP                   (1 << 4)
-#define OV9650_HFLIP                   (1 << 5)
-
-#define OV9650_SOFT_SLEEP              (1 << 4)
-#define OV9650_OUTPUT_DRIVE_2X         (1 << 0)
-
-#define OV9650_DENOISE_ENABLE          (1 << 5)
-#define OV9650_WHITE_PIXEL_ENABLE      (1 << 1)
-#define OV9650_WHITE_PIXEL_OPTION      (1 << 0)
-
-#define OV9650_LEFT_OFFSET             0x62
-
-#define GAIN_DEFAULT                   0x14
-#define RED_GAIN_DEFAULT               0x70
-#define BLUE_GAIN_DEFAULT              0x20
-#define EXPOSURE_DEFAULT               0x1ff
-
-/*****************************************************************************/
-
-/* Kernel module parameters */
-extern int force_sensor;
-extern bool dump_sensor;
-
-int ov9650_probe(struct sd *sd);
-int ov9650_init(struct sd *sd);
-int ov9650_start(struct sd *sd);
-int ov9650_stop(struct sd *sd);
-void ov9650_disconnect(struct sd *sd);
-
-static const struct m5602_sensor ov9650 = {
-       .name = "OV9650",
-       .i2c_slave_id = 0x60,
-       .i2c_regW = 1,
-       .probe = ov9650_probe,
-       .init = ov9650_init,
-       .start = ov9650_start,
-       .stop = ov9650_stop,
-       .disconnect = ov9650_disconnect,
-};
-
-static const unsigned char preinit_ov9650[][3] = {
-       /* [INITCAM] */
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
-
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
-       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
-       /* Reset chip */
-       {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
-       /* Enable double clock */
-       {SENSOR, OV9650_CLKRC, 0x80},
-       /* Do something out of spec with the power */
-       {SENSOR, OV9650_OFON, 0x40}
-};
-
-static const unsigned char init_ov9650[][3] = {
-       /* [INITCAM] */
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
-
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
-       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x0a},
-
-       /* Reset chip */
-       {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
-       /* One extra reset is needed in order to make the sensor behave
-          properly when resuming from ram, could be a timing issue */
-       {SENSOR, OV9650_COM7, OV9650_REGISTER_RESET},
-
-       /* Enable double clock */
-       {SENSOR, OV9650_CLKRC, 0x80},
-       /* Do something out of spec with the power */
-       {SENSOR, OV9650_OFON, 0x40},
-
-       /* Set fast AGC/AEC algorithm with unlimited step size */
-       {SENSOR, OV9650_COM8, OV9650_FAST_AGC_AEC |
-                             OV9650_AEC_UNLIM_STEP_SIZE},
-
-       {SENSOR, OV9650_CHLF, 0x10},
-       {SENSOR, OV9650_ARBLM, 0xbf},
-       {SENSOR, OV9650_ACOM38, 0x81},
-       /* Turn off color matrix coefficient double option */
-       {SENSOR, OV9650_COM16, 0x00},
-       /* Enable color matrix for RGB/YUV, Delay Y channel,
-       set output Y/UV delay to 1 */
-       {SENSOR, OV9650_COM13, 0x19},
-       /* Enable digital BLC, Set output mode to U Y V Y */
-       {SENSOR, OV9650_TSLB, 0x0c},
-       /* Limit the AGC/AEC stable upper region */
-       {SENSOR, OV9650_COM24, 0x00},
-       /* Enable HREF and some out of spec things */
-       {SENSOR, OV9650_COM12, 0x73},
-       /* Set all DBLC offset signs to positive and
-       do some out of spec stuff */
-       {SENSOR, OV9650_DBLC1, 0xdf},
-       {SENSOR, OV9650_COM21, 0x06},
-       {SENSOR, OV9650_RSVD35, 0x91},
-       /* Necessary, no camera stream without it */
-       {SENSOR, OV9650_RSVD16, 0x06},
-       {SENSOR, OV9650_RSVD94, 0x99},
-       {SENSOR, OV9650_RSVD95, 0x99},
-       {SENSOR, OV9650_RSVD96, 0x04},
-       /* Enable full range output */
-       {SENSOR, OV9650_COM15, 0x0},
-       /* Enable HREF at optical black, enable ADBLC bias,
-       enable ADBLC, reset timings at format change */
-       {SENSOR, OV9650_COM6, 0x4b},
-       /* Subtract 32 from the B channel bias */
-       {SENSOR, OV9650_BBIAS, 0xa0},
-       /* Subtract 32 from the Gb channel bias */
-       {SENSOR, OV9650_GbBIAS, 0xa0},
-       /* Do not bypass the analog BLC and to some out of spec stuff */
-       {SENSOR, OV9650_Gr_COM, 0x00},
-       /* Subtract 32 from the R channel bias */
-       {SENSOR, OV9650_RBIAS, 0xa0},
-       /* Subtract 32 from the R channel bias */
-       {SENSOR, OV9650_RBIAS, 0x0},
-       {SENSOR, OV9650_COM26, 0x80},
-       {SENSOR, OV9650_ACOMA9, 0x98},
-       /* Set the AGC/AEC stable region upper limit */
-       {SENSOR, OV9650_AEW, 0x68},
-       /* Set the AGC/AEC stable region lower limit */
-       {SENSOR, OV9650_AEB, 0x5c},
-       /* Set the high and low limit nibbles to 3 */
-       {SENSOR, OV9650_VPT, 0xc3},
-       /* Set the Automatic Gain Ceiling (AGC) to 128x,
-       drop VSYNC at frame drop,
-       limit exposure timing,
-       drop frame when the AEC step is larger than the exposure gap */
-       {SENSOR, OV9650_COM9, 0x6e},
-       /* Set VSYNC negative, Set RESET to SLHS (slave mode horizontal sync)
-       and set PWDN to SLVS (slave mode vertical sync) */
-       {SENSOR, OV9650_COM10, 0x42},
-       /* Set horizontal column start high to default value */
-       {SENSOR, OV9650_HSTART, 0x1a}, /* 210 */
-       /* Set horizontal column end */
-       {SENSOR, OV9650_HSTOP, 0xbf}, /* 1534 */
-       /* Complementing register to the two writes above */
-       {SENSOR, OV9650_HREF, 0xb2},
-       /* Set vertical row start high bits */
-       {SENSOR, OV9650_VSTRT, 0x02},
-       /* Set vertical row end low bits */
-       {SENSOR, OV9650_VSTOP, 0x7e},
-       /* Set complementing vertical frame control */
-       {SENSOR, OV9650_VREF, 0x10},
-       {SENSOR, OV9650_ADC, 0x04},
-       {SENSOR, OV9650_HV, 0x40},
-
-       /* Enable denoise, and white-pixel erase */
-       {SENSOR, OV9650_COM22, OV9650_DENOISE_ENABLE |
-                OV9650_WHITE_PIXEL_ENABLE |
-                OV9650_WHITE_PIXEL_OPTION},
-
-       /* Enable VARIOPIXEL */
-       {SENSOR, OV9650_COM3, OV9650_VARIOPIXEL},
-       {SENSOR, OV9650_COM4, OV9650_QVGA_VARIOPIXEL},
-
-       /* Put the sensor in soft sleep mode */
-       {SENSOR, OV9650_COM2, OV9650_SOFT_SLEEP | OV9650_OUTPUT_DRIVE_2X},
-};
-
-static const unsigned char res_init_ov9650[][3] = {
-       {SENSOR, OV9650_COM2, OV9650_OUTPUT_DRIVE_2X},
-
-       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x82},
-       {BRIDGE, M5602_XB_LINE_OF_FRAME_L, 0x00},
-       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82},
-       {BRIDGE, M5602_XB_PIX_OF_LINE_L, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x01}
-};
-#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.c b/drivers/media/video/gspca/m5602/m5602_po1030.c
deleted file mode 100644 (file)
index b877169..0000000
+++ /dev/null
@@ -1,763 +0,0 @@
-/*
- * Driver for the po1030 sensor
- *
- * Copyright (c) 2008 Erik Andrén
- * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "m5602_po1030.h"
-
-static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val);
-static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
-                                        __s32 val);
-static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
-                                        __s32 *val);
-static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
-                                        __s32 val);
-static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
-                                        __s32 *val);
-
-static struct v4l2_pix_format po1030_modes[] = {
-       {
-               640,
-               480,
-               V4L2_PIX_FMT_SBGGR8,
-               V4L2_FIELD_NONE,
-               .sizeimage = 640 * 480,
-               .bytesperline = 640,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2
-       }
-};
-
-static const struct ctrl po1030_ctrls[] = {
-#define GAIN_IDX 0
-       {
-               {
-                       .id             = V4L2_CID_GAIN,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "gain",
-                       .minimum        = 0x00,
-                       .maximum        = 0x4f,
-                       .step           = 0x1,
-                       .default_value  = PO1030_GLOBAL_GAIN_DEFAULT,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = po1030_set_gain,
-               .get = po1030_get_gain
-       },
-#define EXPOSURE_IDX 1
-       {
-               {
-                       .id             = V4L2_CID_EXPOSURE,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "exposure",
-                       .minimum        = 0x00,
-                       .maximum        = 0x02ff,
-                       .step           = 0x1,
-                       .default_value  = PO1030_EXPOSURE_DEFAULT,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = po1030_set_exposure,
-               .get = po1030_get_exposure
-       },
-#define RED_BALANCE_IDX 2
-       {
-               {
-                       .id             = V4L2_CID_RED_BALANCE,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "red balance",
-                       .minimum        = 0x00,
-                       .maximum        = 0xff,
-                       .step           = 0x1,
-                       .default_value  = PO1030_RED_GAIN_DEFAULT,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = po1030_set_red_balance,
-               .get = po1030_get_red_balance
-       },
-#define BLUE_BALANCE_IDX 3
-       {
-               {
-                       .id             = V4L2_CID_BLUE_BALANCE,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "blue balance",
-                       .minimum        = 0x00,
-                       .maximum        = 0xff,
-                       .step           = 0x1,
-                       .default_value  = PO1030_BLUE_GAIN_DEFAULT,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = po1030_set_blue_balance,
-               .get = po1030_get_blue_balance
-       },
-#define HFLIP_IDX 4
-       {
-               {
-                       .id             = V4L2_CID_HFLIP,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "horizontal flip",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 0,
-               },
-               .set = po1030_set_hflip,
-               .get = po1030_get_hflip
-       },
-#define VFLIP_IDX 5
-       {
-               {
-                       .id             = V4L2_CID_VFLIP,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "vertical flip",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 0,
-               },
-               .set = po1030_set_vflip,
-               .get = po1030_get_vflip
-       },
-#define AUTO_WHITE_BALANCE_IDX 6
-       {
-               {
-                       .id             = V4L2_CID_AUTO_WHITE_BALANCE,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "auto white balance",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 0,
-               },
-               .set = po1030_set_auto_white_balance,
-               .get = po1030_get_auto_white_balance
-       },
-#define AUTO_EXPOSURE_IDX 7
-       {
-               {
-                       .id             = V4L2_CID_EXPOSURE_AUTO,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "auto exposure",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 0,
-               },
-               .set = po1030_set_auto_exposure,
-               .get = po1030_get_auto_exposure
-       },
-#define GREEN_BALANCE_IDX 8
-       {
-               {
-                       .id             = M5602_V4L2_CID_GREEN_BALANCE,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "green balance",
-                       .minimum        = 0x00,
-                       .maximum        = 0xff,
-                       .step           = 0x1,
-                       .default_value  = PO1030_GREEN_GAIN_DEFAULT,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = po1030_set_green_balance,
-               .get = po1030_get_green_balance
-       },
-};
-
-static void po1030_dump_registers(struct sd *sd);
-
-int po1030_probe(struct sd *sd)
-{
-       u8 dev_id_h = 0, i;
-       s32 *sensor_settings;
-
-       if (force_sensor) {
-               if (force_sensor == PO1030_SENSOR) {
-                       pr_info("Forcing a %s sensor\n", po1030.name);
-                       goto sensor_found;
-               }
-               /* If we want to force another sensor, don't try to probe this
-                * one */
-               return -ENODEV;
-       }
-
-       PDEBUG(D_PROBE, "Probing for a po1030 sensor");
-
-       /* Run the pre-init to actually probe the unit */
-       for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
-               u8 data = preinit_po1030[i][2];
-               if (preinit_po1030[i][0] == SENSOR)
-                       m5602_write_sensor(sd,
-                               preinit_po1030[i][1], &data, 1);
-               else
-                       m5602_write_bridge(sd, preinit_po1030[i][1], data);
-       }
-
-       if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1))
-               return -ENODEV;
-
-       if (dev_id_h == 0x30) {
-               pr_info("Detected a po1030 sensor\n");
-               goto sensor_found;
-       }
-       return -ENODEV;
-
-sensor_found:
-       sensor_settings = kmalloc(
-               ARRAY_SIZE(po1030_ctrls) * sizeof(s32), GFP_KERNEL);
-       if (!sensor_settings)
-               return -ENOMEM;
-
-       sd->gspca_dev.cam.cam_mode = po1030_modes;
-       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(po1030_modes);
-       sd->desc->ctrls = po1030_ctrls;
-       sd->desc->nctrls = ARRAY_SIZE(po1030_ctrls);
-
-       for (i = 0; i < ARRAY_SIZE(po1030_ctrls); i++)
-               sensor_settings[i] = po1030_ctrls[i].qctrl.default_value;
-       sd->sensor_priv = sensor_settings;
-
-       return 0;
-}
-
-int po1030_init(struct sd *sd)
-{
-       s32 *sensor_settings = sd->sensor_priv;
-       int i, err = 0;
-
-       /* Init the sensor */
-       for (i = 0; i < ARRAY_SIZE(init_po1030) && !err; i++) {
-               u8 data[2] = {0x00, 0x00};
-
-               switch (init_po1030[i][0]) {
-               case BRIDGE:
-                       err = m5602_write_bridge(sd,
-                               init_po1030[i][1],
-                               init_po1030[i][2]);
-                       break;
-
-               case SENSOR:
-                       data[0] = init_po1030[i][2];
-                       err = m5602_write_sensor(sd,
-                               init_po1030[i][1], data, 1);
-                       break;
-
-               default:
-                       pr_info("Invalid stream command, exiting init\n");
-                       return -EINVAL;
-               }
-       }
-       if (err < 0)
-               return err;
-
-       if (dump_sensor)
-               po1030_dump_registers(sd);
-
-       err = po1030_set_exposure(&sd->gspca_dev,
-                                  sensor_settings[EXPOSURE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = po1030_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
-       if (err < 0)
-               return err;
-
-       err = po1030_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
-       if (err < 0)
-               return err;
-
-       err = po1030_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
-       if (err < 0)
-               return err;
-
-       err = po1030_set_red_balance(&sd->gspca_dev,
-                                     sensor_settings[RED_BALANCE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = po1030_set_blue_balance(&sd->gspca_dev,
-                                     sensor_settings[BLUE_BALANCE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = po1030_set_green_balance(&sd->gspca_dev,
-                                      sensor_settings[GREEN_BALANCE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = po1030_set_auto_white_balance(&sd->gspca_dev,
-                               sensor_settings[AUTO_WHITE_BALANCE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = po1030_set_auto_exposure(&sd->gspca_dev,
-                               sensor_settings[AUTO_EXPOSURE_IDX]);
-       return err;
-}
-
-int po1030_start(struct sd *sd)
-{
-       struct cam *cam = &sd->gspca_dev.cam;
-       int i, err = 0;
-       int width = cam->cam_mode[sd->gspca_dev.curr_mode].width;
-       int height = cam->cam_mode[sd->gspca_dev.curr_mode].height;
-       int ver_offs = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
-       u8 data;
-
-       switch (width) {
-       case 320:
-               data = PO1030_SUBSAMPLING;
-               err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
-               if (err < 0)
-                       return err;
-
-               data = ((width + 3) >> 8) & 0xff;
-               err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
-               if (err < 0)
-                       return err;
-
-               data = (width + 3) & 0xff;
-               err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
-               if (err < 0)
-                       return err;
-
-               data = ((height + 1) >> 8) & 0xff;
-               err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
-               if (err < 0)
-                       return err;
-
-               data = (height + 1) & 0xff;
-               err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
-
-               height += 6;
-               width -= 1;
-               break;
-
-       case 640:
-               data = 0;
-               err = m5602_write_sensor(sd, PO1030_CONTROL3, &data, 1);
-               if (err < 0)
-                       return err;
-
-               data = ((width + 7) >> 8) & 0xff;
-               err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_H, &data, 1);
-               if (err < 0)
-                       return err;
-
-               data = (width + 7) & 0xff;
-               err = m5602_write_sensor(sd, PO1030_WINDOWWIDTH_L, &data, 1);
-               if (err < 0)
-                       return err;
-
-               data = ((height + 3) >> 8) & 0xff;
-               err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_H, &data, 1);
-               if (err < 0)
-                       return err;
-
-               data = (height + 3) & 0xff;
-               err = m5602_write_sensor(sd, PO1030_WINDOWHEIGHT_L, &data, 1);
-
-               height += 12;
-               width -= 2;
-               break;
-       }
-       err = m5602_write_bridge(sd, M5602_XB_SENSOR_TYPE, 0x0c);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_LINE_OF_FRAME_H, 0x81);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_PIX_OF_LINE_H, 0x82);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0x01);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA,
-                                ((ver_offs >> 8) & 0xff));
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (ver_offs & 0xff));
-       if (err < 0)
-               return err;
-
-       for (i = 0; i < 2 && !err; i++)
-               err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height >> 8) & 0xff);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, (height & 0xff));
-       if (err < 0)
-               return err;
-
-       for (i = 0; i < 2 && !err; i++)
-               err = m5602_write_bridge(sd, M5602_XB_VSYNC_PARA, 0);
-
-       for (i = 0; i < 2 && !err; i++)
-               err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
-
-       for (i = 0; i < 2 && !err; i++)
-               err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, 0);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width >> 8) & 0xff);
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_HSYNC_PARA, (width & 0xff));
-       if (err < 0)
-               return err;
-
-       err = m5602_write_bridge(sd, M5602_XB_SIG_INI, 0);
-       return err;
-}
-
-static int po1030_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[EXPOSURE_IDX];
-       PDEBUG(D_V4L2, "Exposure read as %d", *val);
-       return 0;
-}
-
-static int po1030_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 i2c_data;
-       int err;
-
-       sensor_settings[EXPOSURE_IDX] = val;
-       PDEBUG(D_V4L2, "Set exposure to %d", val & 0xffff);
-
-       i2c_data = ((val & 0xff00) >> 8);
-       PDEBUG(D_V4L2, "Set exposure to high byte to 0x%x",
-              i2c_data);
-
-       err = m5602_write_sensor(sd, PO1030_INTEGLINES_H,
-                                 &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       i2c_data = (val & 0xff);
-       PDEBUG(D_V4L2, "Set exposure to low byte to 0x%x",
-              i2c_data);
-       err = m5602_write_sensor(sd, PO1030_INTEGLINES_M,
-                                 &i2c_data, 1);
-
-       return err;
-}
-
-static int po1030_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[GAIN_IDX];
-       PDEBUG(D_V4L2, "Read global gain %d", *val);
-       return 0;
-}
-
-static int po1030_set_gain(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 i2c_data;
-       int err;
-
-       sensor_settings[GAIN_IDX] = val;
-
-       i2c_data = val & 0xff;
-       PDEBUG(D_V4L2, "Set global gain to %d", i2c_data);
-       err = m5602_write_sensor(sd, PO1030_GLOBALGAIN,
-                                &i2c_data, 1);
-       return err;
-}
-
-static int po1030_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[HFLIP_IDX];
-       PDEBUG(D_V4L2, "Read hflip %d", *val);
-
-       return 0;
-}
-
-static int po1030_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 i2c_data;
-       int err;
-
-       sensor_settings[HFLIP_IDX] = val;
-
-       PDEBUG(D_V4L2, "Set hflip %d", val);
-       err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       i2c_data = (0x7f & i2c_data) | ((val & 0x01) << 7);
-
-       err = m5602_write_sensor(sd, PO1030_CONTROL2,
-                                &i2c_data, 1);
-
-       return err;
-}
-
-static int po1030_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[VFLIP_IDX];
-       PDEBUG(D_V4L2, "Read vflip %d", *val);
-
-       return 0;
-}
-
-static int po1030_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 i2c_data;
-       int err;
-
-       sensor_settings[VFLIP_IDX] = val;
-
-       PDEBUG(D_V4L2, "Set vflip %d", val);
-       err = m5602_read_sensor(sd, PO1030_CONTROL2, &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       i2c_data = (i2c_data & 0xbf) | ((val & 0x01) << 6);
-
-       err = m5602_write_sensor(sd, PO1030_CONTROL2,
-                                &i2c_data, 1);
-
-       return err;
-}
-
-static int po1030_get_red_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[RED_BALANCE_IDX];
-       PDEBUG(D_V4L2, "Read red gain %d", *val);
-       return 0;
-}
-
-static int po1030_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 i2c_data;
-       int err;
-
-       sensor_settings[RED_BALANCE_IDX] = val;
-
-       i2c_data = val & 0xff;
-       PDEBUG(D_V4L2, "Set red gain to %d", i2c_data);
-       err = m5602_write_sensor(sd, PO1030_RED_GAIN,
-                                 &i2c_data, 1);
-       return err;
-}
-
-static int po1030_get_blue_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[BLUE_BALANCE_IDX];
-       PDEBUG(D_V4L2, "Read blue gain %d", *val);
-
-       return 0;
-}
-
-static int po1030_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 i2c_data;
-       int err;
-
-       sensor_settings[BLUE_BALANCE_IDX] = val;
-
-       i2c_data = val & 0xff;
-       PDEBUG(D_V4L2, "Set blue gain to %d", i2c_data);
-       err = m5602_write_sensor(sd, PO1030_BLUE_GAIN,
-                                 &i2c_data, 1);
-
-       return err;
-}
-
-static int po1030_get_green_balance(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[GREEN_BALANCE_IDX];
-       PDEBUG(D_V4L2, "Read green gain %d", *val);
-
-       return 0;
-}
-
-static int po1030_set_green_balance(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 i2c_data;
-       int err;
-
-       sensor_settings[GREEN_BALANCE_IDX] = val;
-       i2c_data = val & 0xff;
-       PDEBUG(D_V4L2, "Set green gain to %d", i2c_data);
-
-       err = m5602_write_sensor(sd, PO1030_GREEN_1_GAIN,
-                          &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       return m5602_write_sensor(sd, PO1030_GREEN_2_GAIN,
-                                &i2c_data, 1);
-}
-
-static int po1030_get_auto_white_balance(struct gspca_dev *gspca_dev,
-                                        __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[AUTO_WHITE_BALANCE_IDX];
-       PDEBUG(D_V4L2, "Auto white balancing is %d", *val);
-
-       return 0;
-}
-
-static int po1030_set_auto_white_balance(struct gspca_dev *gspca_dev,
-                                        __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 i2c_data;
-       int err;
-
-       sensor_settings[AUTO_WHITE_BALANCE_IDX] = val;
-
-       err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       PDEBUG(D_V4L2, "Set auto white balance to %d", val);
-       i2c_data = (i2c_data & 0xfe) | (val & 0x01);
-       err = m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
-       return err;
-}
-
-static int po1030_get_auto_exposure(struct gspca_dev *gspca_dev,
-                                   __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[AUTO_EXPOSURE_IDX];
-       PDEBUG(D_V4L2, "Auto exposure is %d", *val);
-       return 0;
-}
-
-static int po1030_set_auto_exposure(struct gspca_dev *gspca_dev,
-                                   __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 i2c_data;
-       int err;
-
-       sensor_settings[AUTO_EXPOSURE_IDX] = val;
-       err = m5602_read_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
-       if (err < 0)
-               return err;
-
-       PDEBUG(D_V4L2, "Set auto exposure to %d", val);
-       i2c_data = (i2c_data & 0xfd) | ((val & 0x01) << 1);
-       return m5602_write_sensor(sd, PO1030_AUTOCTRL1, &i2c_data, 1);
-}
-
-void po1030_disconnect(struct sd *sd)
-{
-       sd->sensor = NULL;
-       kfree(sd->sensor_priv);
-}
-
-static void po1030_dump_registers(struct sd *sd)
-{
-       int address;
-       u8 value = 0;
-
-       pr_info("Dumping the po1030 sensor core registers\n");
-       for (address = 0; address < 0x7f; address++) {
-               m5602_read_sensor(sd, address, &value, 1);
-               pr_info("register 0x%x contains 0x%x\n", address, value);
-       }
-
-       pr_info("po1030 register state dump complete\n");
-
-       pr_info("Probing for which registers that are read/write\n");
-       for (address = 0; address < 0xff; address++) {
-               u8 old_value, ctrl_value;
-               u8 test_value[2] = {0xff, 0xff};
-
-               m5602_read_sensor(sd, address, &old_value, 1);
-               m5602_write_sensor(sd, address, test_value, 1);
-               m5602_read_sensor(sd, address, &ctrl_value, 1);
-
-               if (ctrl_value == test_value[0])
-                       pr_info("register 0x%x is writeable\n", address);
-               else
-                       pr_info("register 0x%x is read only\n", address);
-
-               /* Restore original value */
-               m5602_write_sensor(sd, address, &old_value, 1);
-       }
-}
diff --git a/drivers/media/video/gspca/m5602/m5602_po1030.h b/drivers/media/video/gspca/m5602/m5602_po1030.h
deleted file mode 100644 (file)
index 81a2bcb..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Driver for the po1030 sensor.
- *
- * Copyright (c) 2008 Erik Andrén
- * Copyright (c) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (c) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * Register defines taken from Pascal Stangs Procyon Armlib
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#ifndef M5602_PO1030_H_
-#define M5602_PO1030_H_
-
-#include "m5602_sensor.h"
-
-/*****************************************************************************/
-
-#define PO1030_DEVID_H         0x00
-#define PO1030_DEVID_L         0x01
-#define PO1030_FRAMEWIDTH_H    0x04
-#define PO1030_FRAMEWIDTH_L    0x05
-#define PO1030_FRAMEHEIGHT_H   0x06
-#define PO1030_FRAMEHEIGHT_L   0x07
-#define PO1030_WINDOWX_H       0x08
-#define PO1030_WINDOWX_L       0x09
-#define PO1030_WINDOWY_H       0x0a
-#define PO1030_WINDOWY_L       0x0b
-#define PO1030_WINDOWWIDTH_H   0x0c
-#define PO1030_WINDOWWIDTH_L   0x0d
-#define PO1030_WINDOWHEIGHT_H  0x0e
-#define PO1030_WINDOWHEIGHT_L  0x0f
-
-#define PO1030_GLOBALIBIAS     0x12
-#define PO1030_PIXELIBIAS      0x13
-
-#define PO1030_GLOBALGAIN      0x15
-#define PO1030_RED_GAIN                0x16
-#define PO1030_GREEN_1_GAIN    0x17
-#define PO1030_BLUE_GAIN       0x18
-#define PO1030_GREEN_2_GAIN    0x19
-
-#define PO1030_INTEGLINES_H    0x1a
-#define PO1030_INTEGLINES_M    0x1b
-#define PO1030_INTEGLINES_L    0x1c
-
-#define PO1030_CONTROL1                0x1d
-#define PO1030_CONTROL2                0x1e
-#define PO1030_CONTROL3                0x1f
-#define PO1030_CONTROL4                0x20
-
-#define PO1030_PERIOD50_H      0x23
-#define PO1030_PERIOD50_L      0x24
-#define PO1030_PERIOD60_H      0x25
-#define PO1030_PERIOD60_L      0x26
-#define PO1030_REGCLK167       0x27
-#define PO1030_FLICKER_DELTA50 0x28
-#define PO1030_FLICKERDELTA60  0x29
-
-#define PO1030_ADCOFFSET       0x2c
-
-/* Gamma Correction Coeffs */
-#define PO1030_GC0             0x2d
-#define PO1030_GC1             0x2e
-#define PO1030_GC2             0x2f
-#define PO1030_GC3             0x30
-#define PO1030_GC4             0x31
-#define PO1030_GC5             0x32
-#define PO1030_GC6             0x33
-#define PO1030_GC7             0x34
-
-/* Color Transform Matrix */
-#define PO1030_CT0             0x35
-#define PO1030_CT1             0x36
-#define PO1030_CT2             0x37
-#define PO1030_CT3             0x38
-#define PO1030_CT4             0x39
-#define PO1030_CT5             0x3a
-#define PO1030_CT6             0x3b
-#define PO1030_CT7             0x3c
-#define PO1030_CT8             0x3d
-
-#define PO1030_AUTOCTRL1       0x3e
-#define PO1030_AUTOCTRL2       0x3f
-
-#define PO1030_YTARGET         0x40
-#define PO1030_GLOBALGAINMIN   0x41
-#define PO1030_GLOBALGAINMAX   0x42
-
-#define PO1030_AWB_RED_TUNING  0x47
-#define PO1030_AWB_BLUE_TUNING 0x48
-
-/* Output format control */
-#define PO1030_OUTFORMCTRL1    0x5a
-#define PO1030_OUTFORMCTRL2    0x5b
-#define PO1030_OUTFORMCTRL3    0x5c
-#define PO1030_OUTFORMCTRL4    0x5d
-#define PO1030_OUTFORMCTRL5    0x5e
-
-#define PO1030_EDGE_ENH_OFF    0x5f
-#define PO1030_EGA             0x60
-
-#define PO1030_Cb_U_GAIN       0x63
-#define PO1030_Cr_V_GAIN       0x64
-
-#define PO1030_YCONTRAST       0x74
-#define PO1030_YSATURATION     0x75
-
-#define PO1030_HFLIP           (1 << 7)
-#define PO1030_VFLIP           (1 << 6)
-
-#define PO1030_HREF_ENABLE     (1 << 6)
-
-#define PO1030_RAW_RGB_BAYER   0x4
-
-#define PO1030_FRAME_EQUAL     (1 << 3)
-#define PO1030_AUTO_SUBSAMPLING (1 << 4)
-
-#define PO1030_WEIGHT_WIN_2X   (1 << 3)
-
-#define PO1030_SHUTTER_MODE    (1 << 6)
-#define PO1030_AUTO_SUBSAMPLING        (1 << 4)
-#define PO1030_FRAME_EQUAL     (1 << 3)
-
-#define PO1030_SENSOR_RESET    (1 << 5)
-
-#define PO1030_SUBSAMPLING     (1 << 6)
-
-/*****************************************************************************/
-
-#define PO1030_GLOBAL_GAIN_DEFAULT     0x12
-#define PO1030_EXPOSURE_DEFAULT                0x0085
-#define PO1030_BLUE_GAIN_DEFAULT       0x36
-#define PO1030_RED_GAIN_DEFAULT                0x36
-#define PO1030_GREEN_GAIN_DEFAULT      0x40
-
-/*****************************************************************************/
-
-/* Kernel module parameters */
-extern int force_sensor;
-extern bool dump_sensor;
-
-int po1030_probe(struct sd *sd);
-int po1030_init(struct sd *sd);
-int po1030_start(struct sd *sd);
-void po1030_disconnect(struct sd *sd);
-
-static const struct m5602_sensor po1030 = {
-       .name = "PO1030",
-
-       .i2c_slave_id = 0xdc,
-       .i2c_regW = 1,
-
-       .probe = po1030_probe,
-       .init = po1030_init,
-       .start = po1030_start,
-       .disconnect = po1030_disconnect,
-};
-
-static const unsigned char preinit_po1030[][3] = {
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
-
-       {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)},
-
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x00}
-};
-
-static const unsigned char init_po1030[][3] = {
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0},
-       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0c},
-
-       {SENSOR, PO1030_AUTOCTRL2, PO1030_SENSOR_RESET | (1 << 2)},
-
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x04},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x02},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x04},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
-
-       {SENSOR, PO1030_AUTOCTRL2, 0x04},
-
-       {SENSOR, PO1030_OUTFORMCTRL2, PO1030_RAW_RGB_BAYER},
-       {SENSOR, PO1030_AUTOCTRL1, PO1030_WEIGHT_WIN_2X},
-
-       {SENSOR, PO1030_CONTROL2, 0x03},
-       {SENSOR, 0x21, 0x90},
-       {SENSOR, PO1030_YTARGET, 0x60},
-       {SENSOR, 0x59, 0x13},
-       {SENSOR, PO1030_OUTFORMCTRL1, PO1030_HREF_ENABLE},
-       {SENSOR, PO1030_EDGE_ENH_OFF, 0x00},
-       {SENSOR, PO1030_EGA, 0x80},
-       {SENSOR, 0x78, 0x14},
-       {SENSOR, 0x6f, 0x01},
-       {SENSOR, PO1030_GLOBALGAINMAX, 0x14},
-       {SENSOR, PO1030_Cb_U_GAIN, 0x38},
-       {SENSOR, PO1030_Cr_V_GAIN, 0x38},
-       {SENSOR, PO1030_CONTROL1, PO1030_SHUTTER_MODE |
-                                 PO1030_AUTO_SUBSAMPLING |
-                                 PO1030_FRAME_EQUAL},
-       {SENSOR, PO1030_GC0, 0x10},
-       {SENSOR, PO1030_GC1, 0x20},
-       {SENSOR, PO1030_GC2, 0x40},
-       {SENSOR, PO1030_GC3, 0x60},
-       {SENSOR, PO1030_GC4, 0x80},
-       {SENSOR, PO1030_GC5, 0xa0},
-       {SENSOR, PO1030_GC6, 0xc0},
-       {SENSOR, PO1030_GC7, 0xff},
-
-       /* Set the width to 751 */
-       {SENSOR, PO1030_FRAMEWIDTH_H, 0x02},
-       {SENSOR, PO1030_FRAMEWIDTH_L, 0xef},
-
-       /* Set the height to 540 */
-       {SENSOR, PO1030_FRAMEHEIGHT_H, 0x02},
-       {SENSOR, PO1030_FRAMEHEIGHT_L, 0x1c},
-
-       /* Set the x window to 1 */
-       {SENSOR, PO1030_WINDOWX_H, 0x00},
-       {SENSOR, PO1030_WINDOWX_L, 0x01},
-
-       /* Set the y window to 1 */
-       {SENSOR, PO1030_WINDOWY_H, 0x00},
-       {SENSOR, PO1030_WINDOWY_L, 0x01},
-
-       /* with a very low lighted environment increase the exposure but
-        * decrease the FPS (Frame Per Second) */
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0},
-
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x05},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00},
-};
-#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c
deleted file mode 100644 (file)
index cc8ec3f..0000000
+++ /dev/null
@@ -1,726 +0,0 @@
-/*
- * Driver for the s5k4aa sensor
- *
- * Copyright (C) 2008 Erik Andrén
- * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "m5602_s5k4aa.h"
-
-static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
-
-static
-    const
-       struct dmi_system_id s5k4aa_vflip_dmi_table[] = {
-       {
-               .ident = "BRUNEINIT",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "BRUNENIT"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "BRUNENIT"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "00030D0000000001")
-               }
-       }, {
-               .ident = "Fujitsu-Siemens Amilo Xa 2528",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xa 2528")
-               }
-       }, {
-               .ident = "Fujitsu-Siemens Amilo Xi 2428",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2428")
-               }
-       }, {
-               .ident = "Fujitsu-Siemens Amilo Xi 2528",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2528")
-               }
-       }, {
-               .ident = "Fujitsu-Siemens Amilo Xi 2550",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2550")
-               }
-       }, {
-               .ident = "Fujitsu-Siemens Amilo Pa 2548",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 2548")
-               }
-       }, {
-               .ident = "MSI GX700",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
-                       DMI_MATCH(DMI_BIOS_DATE, "12/02/2008")
-               }
-       }, {
-               .ident = "MSI GX700",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
-                       DMI_MATCH(DMI_BIOS_DATE, "07/26/2007")
-               }
-       }, {
-               .ident = "MSI GX700",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "GX700"),
-                       DMI_MATCH(DMI_BIOS_DATE, "07/19/2007")
-               }
-       }, {
-               .ident = "MSI GX700/GX705/EX700",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "GX700/GX705/EX700")
-               }
-       }, {
-               .ident = "MSI L735",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "MS-1717X")
-               }
-       }, {
-               .ident = "Lenovo Y300",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "L3000 Y300"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "Y300")
-               }
-       },
-       { }
-};
-
-static struct v4l2_pix_format s5k4aa_modes[] = {
-       {
-               640,
-               480,
-               V4L2_PIX_FMT_SBGGR8,
-               V4L2_FIELD_NONE,
-               .sizeimage =
-                       640 * 480,
-               .bytesperline = 640,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0
-       },
-       {
-               1280,
-               1024,
-               V4L2_PIX_FMT_SBGGR8,
-               V4L2_FIELD_NONE,
-               .sizeimage =
-                       1280 * 1024,
-               .bytesperline = 1280,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0
-       }
-};
-
-static const struct ctrl s5k4aa_ctrls[] = {
-#define VFLIP_IDX 0
-       {
-               {
-                       .id             = V4L2_CID_VFLIP,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "vertical flip",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 0
-               },
-               .set = s5k4aa_set_vflip,
-               .get = s5k4aa_get_vflip
-       },
-#define HFLIP_IDX 1
-       {
-               {
-                       .id             = V4L2_CID_HFLIP,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "horizontal flip",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 0
-               },
-               .set = s5k4aa_set_hflip,
-               .get = s5k4aa_get_hflip
-       },
-#define GAIN_IDX 2
-       {
-               {
-                       .id             = V4L2_CID_GAIN,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "Gain",
-                       .minimum        = 0,
-                       .maximum        = 127,
-                       .step           = 1,
-                       .default_value  = S5K4AA_DEFAULT_GAIN,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = s5k4aa_set_gain,
-               .get = s5k4aa_get_gain
-       },
-#define EXPOSURE_IDX 3
-       {
-               {
-                       .id             = V4L2_CID_EXPOSURE,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "Exposure",
-                       .minimum        = 13,
-                       .maximum        = 0xfff,
-                       .step           = 1,
-                       .default_value  = 0x100,
-                       .flags          = V4L2_CTRL_FLAG_SLIDER
-               },
-               .set = s5k4aa_set_exposure,
-               .get = s5k4aa_get_exposure
-       },
-#define NOISE_SUPP_IDX 4
-       {
-               {
-                       .id             = V4L2_CID_PRIVATE_BASE,
-                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name           = "Noise suppression (smoothing)",
-                       .minimum        = 0,
-                       .maximum        = 1,
-                       .step           = 1,
-                       .default_value  = 1,
-               },
-                       .set = s5k4aa_set_noise,
-                       .get = s5k4aa_get_noise
-       },
-#define BRIGHTNESS_IDX 5
-       {
-               {
-                       .id             = V4L2_CID_BRIGHTNESS,
-                       .type           = V4L2_CTRL_TYPE_INTEGER,
-                       .name           = "Brightness",
-                       .minimum        = 0,
-                       .maximum        = 0x1f,
-                       .step           = 1,
-                       .default_value  = S5K4AA_DEFAULT_BRIGHTNESS,
-               },
-                       .set = s5k4aa_set_brightness,
-                       .get = s5k4aa_get_brightness
-       },
-
-};
-
-static void s5k4aa_dump_registers(struct sd *sd);
-
-int s5k4aa_probe(struct sd *sd)
-{
-       u8 prod_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-       const u8 expected_prod_id[6] = {0x00, 0x10, 0x00, 0x4b, 0x33, 0x75};
-       int i, err = 0;
-       s32 *sensor_settings;
-
-       if (force_sensor) {
-               if (force_sensor == S5K4AA_SENSOR) {
-                       pr_info("Forcing a %s sensor\n", s5k4aa.name);
-                       goto sensor_found;
-               }
-               /* If we want to force another sensor, don't try to probe this
-                * one */
-               return -ENODEV;
-       }
-
-       PDEBUG(D_PROBE, "Probing for a s5k4aa sensor");
-
-       /* Preinit the sensor */
-       for (i = 0; i < ARRAY_SIZE(preinit_s5k4aa) && !err; i++) {
-               u8 data[2] = {0x00, 0x00};
-
-               switch (preinit_s5k4aa[i][0]) {
-               case BRIDGE:
-                       err = m5602_write_bridge(sd,
-                                                preinit_s5k4aa[i][1],
-                                                preinit_s5k4aa[i][2]);
-                       break;
-
-               case SENSOR:
-                       data[0] = preinit_s5k4aa[i][2];
-                       err = m5602_write_sensor(sd,
-                                                 preinit_s5k4aa[i][1],
-                                                 data, 1);
-                       break;
-
-               case SENSOR_LONG:
-                       data[0] = preinit_s5k4aa[i][2];
-                       data[1] = preinit_s5k4aa[i][3];
-                       err = m5602_write_sensor(sd,
-                                                 preinit_s5k4aa[i][1],
-                                                 data, 2);
-                       break;
-               default:
-                       pr_info("Invalid stream command, exiting init\n");
-                       return -EINVAL;
-               }
-       }
-
-       /* Test some registers, but we don't know their exact meaning yet */
-       if (m5602_read_sensor(sd, 0x00, prod_id, 2))
-               return -ENODEV;
-       if (m5602_read_sensor(sd, 0x02, prod_id+2, 2))
-               return -ENODEV;
-       if (m5602_read_sensor(sd, 0x04, prod_id+4, 2))
-               return -ENODEV;
-
-       if (memcmp(prod_id, expected_prod_id, sizeof(prod_id)))
-               return -ENODEV;
-       else
-               pr_info("Detected a s5k4aa sensor\n");
-
-sensor_found:
-       sensor_settings = kmalloc(
-               ARRAY_SIZE(s5k4aa_ctrls) * sizeof(s32), GFP_KERNEL);
-       if (!sensor_settings)
-               return -ENOMEM;
-
-       sd->gspca_dev.cam.cam_mode = s5k4aa_modes;
-       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k4aa_modes);
-       sd->desc->ctrls = s5k4aa_ctrls;
-       sd->desc->nctrls = ARRAY_SIZE(s5k4aa_ctrls);
-
-       for (i = 0; i < ARRAY_SIZE(s5k4aa_ctrls); i++)
-               sensor_settings[i] = s5k4aa_ctrls[i].qctrl.default_value;
-       sd->sensor_priv = sensor_settings;
-
-       return 0;
-}
-
-int s5k4aa_start(struct sd *sd)
-{
-       int i, err = 0;
-       u8 data[2];
-       struct cam *cam = &sd->gspca_dev.cam;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       switch (cam->cam_mode[sd->gspca_dev.curr_mode].width) {
-       case 1280:
-               PDEBUG(D_V4L2, "Configuring camera for SXGA mode");
-
-               for (i = 0; i < ARRAY_SIZE(SXGA_s5k4aa); i++) {
-                       switch (SXGA_s5k4aa[i][0]) {
-                       case BRIDGE:
-                               err = m5602_write_bridge(sd,
-                                                SXGA_s5k4aa[i][1],
-                                                SXGA_s5k4aa[i][2]);
-                       break;
-
-                       case SENSOR:
-                               data[0] = SXGA_s5k4aa[i][2];
-                               err = m5602_write_sensor(sd,
-                                                SXGA_s5k4aa[i][1],
-                                                data, 1);
-                       break;
-
-                       case SENSOR_LONG:
-                               data[0] = SXGA_s5k4aa[i][2];
-                               data[1] = SXGA_s5k4aa[i][3];
-                               err = m5602_write_sensor(sd,
-                                                 SXGA_s5k4aa[i][1],
-                                                 data, 2);
-                       break;
-
-                       default:
-                               pr_err("Invalid stream command, exiting init\n");
-                               return -EINVAL;
-                       }
-               }
-               err = s5k4aa_set_noise(&sd->gspca_dev, 0);
-               if (err < 0)
-                       return err;
-               break;
-
-       case 640:
-               PDEBUG(D_V4L2, "Configuring camera for VGA mode");
-
-               for (i = 0; i < ARRAY_SIZE(VGA_s5k4aa); i++) {
-                       switch (VGA_s5k4aa[i][0]) {
-                       case BRIDGE:
-                               err = m5602_write_bridge(sd,
-                                                VGA_s5k4aa[i][1],
-                                                VGA_s5k4aa[i][2]);
-                       break;
-
-                       case SENSOR:
-                               data[0] = VGA_s5k4aa[i][2];
-                               err = m5602_write_sensor(sd,
-                                                VGA_s5k4aa[i][1],
-                                                data, 1);
-                       break;
-
-                       case SENSOR_LONG:
-                               data[0] = VGA_s5k4aa[i][2];
-                               data[1] = VGA_s5k4aa[i][3];
-                               err = m5602_write_sensor(sd,
-                                                 VGA_s5k4aa[i][1],
-                                                 data, 2);
-                       break;
-
-                       default:
-                               pr_err("Invalid stream command, exiting init\n");
-                               return -EINVAL;
-                       }
-               }
-               err = s5k4aa_set_noise(&sd->gspca_dev, 1);
-               if (err < 0)
-                       return err;
-               break;
-       }
-       if (err < 0)
-               return err;
-
-       err = s5k4aa_set_exposure(&sd->gspca_dev,
-                                  sensor_settings[EXPOSURE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = s5k4aa_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
-       if (err < 0)
-               return err;
-
-       err = s5k4aa_set_brightness(&sd->gspca_dev,
-                                    sensor_settings[BRIGHTNESS_IDX]);
-       if (err < 0)
-               return err;
-
-       err = s5k4aa_set_noise(&sd->gspca_dev, sensor_settings[NOISE_SUPP_IDX]);
-       if (err < 0)
-               return err;
-
-       err = s5k4aa_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
-       if (err < 0)
-               return err;
-
-       return s5k4aa_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
-}
-
-int s5k4aa_init(struct sd *sd)
-{
-       int i, err = 0;
-
-       for (i = 0; i < ARRAY_SIZE(init_s5k4aa) && !err; i++) {
-               u8 data[2] = {0x00, 0x00};
-
-               switch (init_s5k4aa[i][0]) {
-               case BRIDGE:
-                       err = m5602_write_bridge(sd,
-                               init_s5k4aa[i][1],
-                               init_s5k4aa[i][2]);
-                       break;
-
-               case SENSOR:
-                       data[0] = init_s5k4aa[i][2];
-                       err = m5602_write_sensor(sd,
-                               init_s5k4aa[i][1], data, 1);
-                       break;
-
-               case SENSOR_LONG:
-                       data[0] = init_s5k4aa[i][2];
-                       data[1] = init_s5k4aa[i][3];
-                       err = m5602_write_sensor(sd,
-                               init_s5k4aa[i][1], data, 2);
-                       break;
-               default:
-                       pr_info("Invalid stream command, exiting init\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (dump_sensor)
-               s5k4aa_dump_registers(sd);
-
-       return err;
-}
-
-static int s5k4aa_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[EXPOSURE_IDX];
-       PDEBUG(D_V4L2, "Read exposure %d", *val);
-
-       return 0;
-}
-
-static int s5k4aa_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 data = S5K4AA_PAGE_MAP_2;
-       int err;
-
-       sensor_settings[EXPOSURE_IDX] = val;
-       PDEBUG(D_V4L2, "Set exposure to %d", val);
-       err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-       if (err < 0)
-               return err;
-       data = (val >> 8) & 0xff;
-       err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_HI, &data, 1);
-       if (err < 0)
-               return err;
-       data = val & 0xff;
-       err = m5602_write_sensor(sd, S5K4AA_EXPOSURE_LO, &data, 1);
-
-       return err;
-}
-
-static int s5k4aa_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[VFLIP_IDX];
-       PDEBUG(D_V4L2, "Read vertical flip %d", *val);
-
-       return 0;
-}
-
-static int s5k4aa_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 data = S5K4AA_PAGE_MAP_2;
-       int err;
-
-       sensor_settings[VFLIP_IDX] = val;
-
-       PDEBUG(D_V4L2, "Set vertical flip to %d", val);
-       err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-       if (err < 0)
-               return err;
-
-       err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
-       if (err < 0)
-               return err;
-
-       if (dmi_check_system(s5k4aa_vflip_dmi_table))
-               val = !val;
-
-       data = ((data & ~S5K4AA_RM_V_FLIP) | ((val & 0x01) << 7));
-       err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
-       if (err < 0)
-               return err;
-
-       err = m5602_read_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
-       if (err < 0)
-               return err;
-       if (val)
-               data &= 0xfe;
-       else
-               data |= 0x01;
-       err = m5602_write_sensor(sd, S5K4AA_ROWSTART_LO, &data, 1);
-       return err;
-}
-
-static int s5k4aa_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[HFLIP_IDX];
-       PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
-
-       return 0;
-}
-
-static int s5k4aa_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 data = S5K4AA_PAGE_MAP_2;
-       int err;
-
-       sensor_settings[HFLIP_IDX] = val;
-
-       PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
-       err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-       if (err < 0)
-               return err;
-
-       err = m5602_read_sensor(sd, S5K4AA_READ_MODE, &data, 1);
-       if (err < 0)
-               return err;
-
-       if (dmi_check_system(s5k4aa_vflip_dmi_table))
-               val = !val;
-
-       data = ((data & ~S5K4AA_RM_H_FLIP) | ((val & 0x01) << 6));
-       err = m5602_write_sensor(sd, S5K4AA_READ_MODE, &data, 1);
-       if (err < 0)
-               return err;
-
-       err = m5602_read_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
-       if (err < 0)
-               return err;
-       if (val)
-               data &= 0xfe;
-       else
-               data |= 0x01;
-       err = m5602_write_sensor(sd, S5K4AA_COLSTART_LO, &data, 1);
-       return err;
-}
-
-static int s5k4aa_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[GAIN_IDX];
-       PDEBUG(D_V4L2, "Read gain %d", *val);
-       return 0;
-}
-
-static int s5k4aa_set_gain(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 data = S5K4AA_PAGE_MAP_2;
-       int err;
-
-       sensor_settings[GAIN_IDX] = val;
-
-       PDEBUG(D_V4L2, "Set gain to %d", val);
-       err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-       if (err < 0)
-               return err;
-
-       data = val & 0xff;
-       err = m5602_write_sensor(sd, S5K4AA_GAIN, &data, 1);
-
-       return err;
-}
-
-static int s5k4aa_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[BRIGHTNESS_IDX];
-       PDEBUG(D_V4L2, "Read brightness %d", *val);
-       return 0;
-}
-
-static int s5k4aa_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 data = S5K4AA_PAGE_MAP_2;
-       int err;
-
-       sensor_settings[BRIGHTNESS_IDX] = val;
-
-       PDEBUG(D_V4L2, "Set brightness to %d", val);
-       err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-       if (err < 0)
-               return err;
-
-       data = val & 0xff;
-       return m5602_write_sensor(sd, S5K4AA_BRIGHTNESS, &data, 1);
-}
-
-static int s5k4aa_get_noise(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[NOISE_SUPP_IDX];
-       PDEBUG(D_V4L2, "Read noise %d", *val);
-       return 0;
-}
-
-static int s5k4aa_set_noise(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-       u8 data = S5K4AA_PAGE_MAP_2;
-       int err;
-
-       sensor_settings[NOISE_SUPP_IDX] = val;
-
-       PDEBUG(D_V4L2, "Set noise to %d", val);
-       err = m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &data, 1);
-       if (err < 0)
-               return err;
-
-       data = val & 0x01;
-       return m5602_write_sensor(sd, S5K4AA_NOISE_SUPP, &data, 1);
-}
-
-void s5k4aa_disconnect(struct sd *sd)
-{
-       sd->sensor = NULL;
-       kfree(sd->sensor_priv);
-}
-
-static void s5k4aa_dump_registers(struct sd *sd)
-{
-       int address;
-       u8 page, old_page;
-       m5602_read_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
-       for (page = 0; page < 16; page++) {
-               m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
-               pr_info("Dumping the s5k4aa register state for page 0x%x\n",
-                       page);
-               for (address = 0; address <= 0xff; address++) {
-                       u8 value = 0;
-                       m5602_read_sensor(sd, address, &value, 1);
-                       pr_info("register 0x%x contains 0x%x\n",
-                               address, value);
-               }
-       }
-       pr_info("s5k4aa register state dump complete\n");
-
-       for (page = 0; page < 16; page++) {
-               m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &page, 1);
-               pr_info("Probing for which registers that are read/write for page 0x%x\n",
-                       page);
-               for (address = 0; address <= 0xff; address++) {
-                       u8 old_value, ctrl_value, test_value = 0xff;
-
-                       m5602_read_sensor(sd, address, &old_value, 1);
-                       m5602_write_sensor(sd, address, &test_value, 1);
-                       m5602_read_sensor(sd, address, &ctrl_value, 1);
-
-                       if (ctrl_value == test_value)
-                               pr_info("register 0x%x is writeable\n",
-                                       address);
-                       else
-                               pr_info("register 0x%x is read only\n",
-                                       address);
-
-                       /* Restore original value */
-                       m5602_write_sensor(sd, address, &old_value, 1);
-               }
-       }
-       pr_info("Read/write register probing complete\n");
-       m5602_write_sensor(sd, S5K4AA_PAGE_MAP, &old_page, 1);
-}
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.h b/drivers/media/video/gspca/m5602/m5602_s5k4aa.h
deleted file mode 100644 (file)
index 8e0035e..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Driver for the s5k4aa sensor
- *
- * Copyright (C) 2008 Erik Andrén
- * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#ifndef M5602_S5K4AA_H_
-#define M5602_S5K4AA_H_
-
-#include <linux/dmi.h>
-
-#include "m5602_sensor.h"
-
-/*****************************************************************************/
-
-#define S5K4AA_PAGE_MAP                        0xec
-
-#define S5K4AA_PAGE_MAP_0              0x00
-#define S5K4AA_PAGE_MAP_1              0x01
-#define S5K4AA_PAGE_MAP_2              0x02
-
-/* Sensor register definitions for page 0x02 */
-#define S5K4AA_READ_MODE               0x03
-#define S5K4AA_ROWSTART_HI             0x04
-#define S5K4AA_ROWSTART_LO             0x05
-#define S5K4AA_COLSTART_HI             0x06
-#define S5K4AA_COLSTART_LO             0x07
-#define S5K4AA_WINDOW_HEIGHT_HI                0x08
-#define S5K4AA_WINDOW_HEIGHT_LO                0x09
-#define S5K4AA_WINDOW_WIDTH_HI         0x0a
-#define S5K4AA_WINDOW_WIDTH_LO         0x0b
-#define S5K4AA_GLOBAL_GAIN__           0x0f
-/* sync lost, if too low, reduces frame rate if too high */
-#define S5K4AA_H_BLANK_HI__            0x1d
-#define S5K4AA_H_BLANK_LO__            0x1e
-#define S5K4AA_EXPOSURE_HI             0x17
-#define S5K4AA_EXPOSURE_LO             0x18
-#define S5K4AA_BRIGHTNESS              0x1f /* (digital?) gain : 5 bits */
-#define S5K4AA_GAIN                    0x20 /* (analogue?) gain : 7 bits */
-#define S5K4AA_NOISE_SUPP              0x37
-
-#define S5K4AA_RM_ROW_SKIP_4X          0x08
-#define S5K4AA_RM_ROW_SKIP_2X          0x04
-#define S5K4AA_RM_COL_SKIP_4X          0x02
-#define S5K4AA_RM_COL_SKIP_2X          0x01
-#define S5K4AA_RM_H_FLIP               0x40
-#define S5K4AA_RM_V_FLIP               0x80
-
-#define S5K4AA_DEFAULT_GAIN            0x5f
-#define S5K4AA_DEFAULT_BRIGHTNESS      0x10
-
-/*****************************************************************************/
-
-/* Kernel module parameters */
-extern int force_sensor;
-extern bool dump_sensor;
-
-int s5k4aa_probe(struct sd *sd);
-int s5k4aa_init(struct sd *sd);
-int s5k4aa_start(struct sd *sd);
-void s5k4aa_disconnect(struct sd *sd);
-
-static const struct m5602_sensor s5k4aa = {
-       .name = "S5K4AA",
-       .i2c_slave_id = 0x5a,
-       .i2c_regW = 2,
-
-       .probe = s5k4aa_probe,
-       .init = s5k4aa_init,
-       .start = s5k4aa_start,
-       .disconnect = s5k4aa_disconnect,
-};
-
-static const unsigned char preinit_s5k4aa[][4] = {
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
-
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
-
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
-       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
-
-       {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00}
-};
-
-static const unsigned char init_s5k4aa[][4] = {
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
-
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x00, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
-
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x14, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
-       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
-
-       {SENSOR, S5K4AA_PAGE_MAP, 0x07, 0x00},
-       {SENSOR, 0x36, 0x01, 0x00},
-       {SENSOR, S5K4AA_PAGE_MAP, 0x00, 0x00},
-       {SENSOR, 0x7b, 0xff, 0x00},
-       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
-       {SENSOR, 0x0c, 0x05, 0x00},
-       {SENSOR, 0x02, 0x0e, 0x00},
-       {SENSOR, S5K4AA_READ_MODE, 0xa0, 0x00},
-       {SENSOR, 0x37, 0x00, 0x00},
-};
-
-static const unsigned char VGA_s5k4aa[][4] = {
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
-       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
-       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       /* VSYNC_PARA, VSYNC_PARA : img height 480 = 0x01e0 */
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0xe0, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-       /* HSYNC_PARA, HSYNC_PARA : img width 640 = 0x0280 */
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x80, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */
-
-       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
-       {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP | S5K4AA_RM_ROW_SKIP_2X
-               | S5K4AA_RM_COL_SKIP_2X, 0x00},
-       /* 0x37 : Fix image stability when light is too bright and improves
-        * image quality in 640x480, but worsens it in 1280x1024 */
-       {SENSOR, 0x37, 0x01, 0x00},
-       /* ROWSTART_HI, ROWSTART_LO : 10 + (1024-960)/2 = 42 = 0x002a */
-       {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
-       {SENSOR, S5K4AA_ROWSTART_LO, 0x29, 0x00},
-       {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
-       {SENSOR, S5K4AA_COLSTART_LO, 0x0c, 0x00},
-       /* window_height_hi, window_height_lo : 960 = 0x03c0 */
-       {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x03, 0x00},
-       {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0xc0, 0x00},
-       /* window_width_hi, window_width_lo : 1280 = 0x0500 */
-       {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
-       {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00},
-       {SENSOR, S5K4AA_H_BLANK_HI__, 0x00, 0x00},
-       {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00}, /* helps to sync... */
-       {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00},
-       {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00},
-       {SENSOR, 0x11, 0x04, 0x00},
-       {SENSOR, 0x12, 0xc3, 0x00},
-       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
-       {SENSOR, 0x02, 0x0e, 0x00},
-};
-
-static const unsigned char SXGA_s5k4aa[][4] = {
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x08, 0x00},
-       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
-       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       /* VSYNC_PARA, VSYNC_PARA : img height 1024 = 0x0400 */
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x04, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-       /* HSYNC_PARA, HSYNC_PARA : img width 1280 = 0x0500 */
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x05, 0x00},
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xa0, 0x00}, /* 48 MHz */
-
-       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
-       {SENSOR, S5K4AA_READ_MODE, S5K4AA_RM_H_FLIP, 0x00},
-       {SENSOR, 0x37, 0x01, 0x00},
-       {SENSOR, S5K4AA_ROWSTART_HI, 0x00, 0x00},
-       {SENSOR, S5K4AA_ROWSTART_LO, 0x09, 0x00},
-       {SENSOR, S5K4AA_COLSTART_HI, 0x00, 0x00},
-       {SENSOR, S5K4AA_COLSTART_LO, 0x0a, 0x00},
-       {SENSOR, S5K4AA_WINDOW_HEIGHT_HI, 0x04, 0x00},
-       {SENSOR, S5K4AA_WINDOW_HEIGHT_LO, 0x00, 0x00},
-       {SENSOR, S5K4AA_WINDOW_WIDTH_HI, 0x05, 0x00},
-       {SENSOR, S5K4AA_WINDOW_WIDTH_LO, 0x00, 0x00},
-       {SENSOR, S5K4AA_H_BLANK_HI__, 0x01, 0x00},
-       {SENSOR, S5K4AA_H_BLANK_LO__, 0xa8, 0x00},
-       {SENSOR, S5K4AA_EXPOSURE_HI, 0x01, 0x00},
-       {SENSOR, S5K4AA_EXPOSURE_LO, 0x00, 0x00},
-       {SENSOR, 0x11, 0x04, 0x00},
-       {SENSOR, 0x12, 0xc3, 0x00},
-       {SENSOR, S5K4AA_PAGE_MAP, 0x02, 0x00},
-       {SENSOR, 0x02, 0x0e, 0x00},
-};
-#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.c b/drivers/media/video/gspca/m5602/m5602_s5k83a.c
deleted file mode 100644 (file)
index 1de743a..0000000
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * Driver for the s5k83a sensor
- *
- * Copyright (C) 2008 Erik Andrén
- * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kthread.h>
-#include "m5602_s5k83a.h"
-
-static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-
-static struct v4l2_pix_format s5k83a_modes[] = {
-       {
-               640,
-               480,
-               V4L2_PIX_FMT_SBGGR8,
-               V4L2_FIELD_NONE,
-               .sizeimage =
-                       640 * 480,
-               .bytesperline = 640,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0
-       }
-};
-
-static const struct ctrl s5k83a_ctrls[] = {
-#define GAIN_IDX 0
-       {
-               {
-                       .id = V4L2_CID_GAIN,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "gain",
-                       .minimum = 0x00,
-                       .maximum = 0xff,
-                       .step = 0x01,
-                       .default_value = S5K83A_DEFAULT_GAIN,
-                       .flags = V4L2_CTRL_FLAG_SLIDER
-               },
-                       .set = s5k83a_set_gain,
-                       .get = s5k83a_get_gain
-
-       },
-#define BRIGHTNESS_IDX 1
-       {
-               {
-                       .id = V4L2_CID_BRIGHTNESS,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "brightness",
-                       .minimum = 0x00,
-                       .maximum = 0xff,
-                       .step = 0x01,
-                       .default_value = S5K83A_DEFAULT_BRIGHTNESS,
-                       .flags = V4L2_CTRL_FLAG_SLIDER
-               },
-                       .set = s5k83a_set_brightness,
-                       .get = s5k83a_get_brightness,
-       },
-#define EXPOSURE_IDX 2
-       {
-               {
-                       .id = V4L2_CID_EXPOSURE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "exposure",
-                       .minimum = 0x00,
-                       .maximum = S5K83A_MAXIMUM_EXPOSURE,
-                       .step = 0x01,
-                       .default_value = S5K83A_DEFAULT_EXPOSURE,
-                       .flags = V4L2_CTRL_FLAG_SLIDER
-               },
-                       .set = s5k83a_set_exposure,
-                       .get = s5k83a_get_exposure
-       },
-#define HFLIP_IDX 3
-       {
-               {
-                       .id = V4L2_CID_HFLIP,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "horizontal flip",
-                       .minimum = 0,
-                       .maximum = 1,
-                       .step = 1,
-                       .default_value = 0
-               },
-                       .set = s5k83a_set_hflip,
-                       .get = s5k83a_get_hflip
-       },
-#define VFLIP_IDX 4
-       {
-               {
-                       .id = V4L2_CID_VFLIP,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "vertical flip",
-                       .minimum = 0,
-                       .maximum = 1,
-                       .step = 1,
-                       .default_value = 0
-               },
-               .set = s5k83a_set_vflip,
-               .get = s5k83a_get_vflip
-       }
-};
-
-static void s5k83a_dump_registers(struct sd *sd);
-static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data);
-static int s5k83a_set_led_indication(struct sd *sd, u8 val);
-static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
-                               __s32 vflip, __s32 hflip);
-
-int s5k83a_probe(struct sd *sd)
-{
-       struct s5k83a_priv *sens_priv;
-       u8 prod_id = 0, ver_id = 0;
-       int i, err = 0;
-
-       if (force_sensor) {
-               if (force_sensor == S5K83A_SENSOR) {
-                       pr_info("Forcing a %s sensor\n", s5k83a.name);
-                       goto sensor_found;
-               }
-               /* If we want to force another sensor, don't try to probe this
-                * one */
-               return -ENODEV;
-       }
-
-       PDEBUG(D_PROBE, "Probing for a s5k83a sensor");
-
-       /* Preinit the sensor */
-       for (i = 0; i < ARRAY_SIZE(preinit_s5k83a) && !err; i++) {
-               u8 data[2] = {preinit_s5k83a[i][2], preinit_s5k83a[i][3]};
-               if (preinit_s5k83a[i][0] == SENSOR)
-                       err = m5602_write_sensor(sd, preinit_s5k83a[i][1],
-                               data, 2);
-               else
-                       err = m5602_write_bridge(sd, preinit_s5k83a[i][1],
-                               data[0]);
-       }
-
-       /* We don't know what register (if any) that contain the product id
-        * Just pick the first addresses that seem to produce the same results
-        * on multiple machines */
-       if (m5602_read_sensor(sd, 0x00, &prod_id, 1))
-               return -ENODEV;
-
-       if (m5602_read_sensor(sd, 0x01, &ver_id, 1))
-               return -ENODEV;
-
-       if ((prod_id == 0xff) || (ver_id == 0xff))
-               return -ENODEV;
-       else
-               pr_info("Detected a s5k83a sensor\n");
-
-sensor_found:
-       sens_priv = kmalloc(
-               sizeof(struct s5k83a_priv), GFP_KERNEL);
-       if (!sens_priv)
-               return -ENOMEM;
-
-       sens_priv->settings =
-       kmalloc(sizeof(s32)*ARRAY_SIZE(s5k83a_ctrls), GFP_KERNEL);
-       if (!sens_priv->settings) {
-               kfree(sens_priv);
-               return -ENOMEM;
-       }
-
-       sd->gspca_dev.cam.cam_mode = s5k83a_modes;
-       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(s5k83a_modes);
-       sd->desc->ctrls = s5k83a_ctrls;
-       sd->desc->nctrls = ARRAY_SIZE(s5k83a_ctrls);
-
-       /* null the pointer! thread is't running now */
-       sens_priv->rotation_thread = NULL;
-
-       for (i = 0; i < ARRAY_SIZE(s5k83a_ctrls); i++)
-               sens_priv->settings[i] = s5k83a_ctrls[i].qctrl.default_value;
-
-       sd->sensor_priv = sens_priv;
-       return 0;
-}
-
-int s5k83a_init(struct sd *sd)
-{
-       int i, err = 0;
-       s32 *sensor_settings =
-                       ((struct s5k83a_priv *) sd->sensor_priv)->settings;
-
-       for (i = 0; i < ARRAY_SIZE(init_s5k83a) && !err; i++) {
-               u8 data[2] = {0x00, 0x00};
-
-               switch (init_s5k83a[i][0]) {
-               case BRIDGE:
-                       err = m5602_write_bridge(sd,
-                                       init_s5k83a[i][1],
-                                       init_s5k83a[i][2]);
-                       break;
-
-               case SENSOR:
-                       data[0] = init_s5k83a[i][2];
-                       err = m5602_write_sensor(sd,
-                               init_s5k83a[i][1], data, 1);
-                       break;
-
-               case SENSOR_LONG:
-                       data[0] = init_s5k83a[i][2];
-                       data[1] = init_s5k83a[i][3];
-                       err = m5602_write_sensor(sd,
-                               init_s5k83a[i][1], data, 2);
-                       break;
-               default:
-                       pr_info("Invalid stream command, exiting init\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (dump_sensor)
-               s5k83a_dump_registers(sd);
-
-       err = s5k83a_set_gain(&sd->gspca_dev, sensor_settings[GAIN_IDX]);
-       if (err < 0)
-               return err;
-
-       err = s5k83a_set_brightness(&sd->gspca_dev,
-                                    sensor_settings[BRIGHTNESS_IDX]);
-       if (err < 0)
-               return err;
-
-       err = s5k83a_set_exposure(&sd->gspca_dev,
-                                  sensor_settings[EXPOSURE_IDX]);
-       if (err < 0)
-               return err;
-
-       err = s5k83a_set_hflip(&sd->gspca_dev, sensor_settings[HFLIP_IDX]);
-       if (err < 0)
-               return err;
-
-       err = s5k83a_set_vflip(&sd->gspca_dev, sensor_settings[VFLIP_IDX]);
-
-       return err;
-}
-
-static int rotation_thread_function(void *data)
-{
-       struct sd *sd = (struct sd *) data;
-       struct s5k83a_priv *sens_priv = sd->sensor_priv;
-       u8 reg, previous_rotation = 0;
-       __s32 vflip, hflip;
-
-       set_current_state(TASK_INTERRUPTIBLE);
-       while (!schedule_timeout(100)) {
-               if (mutex_lock_interruptible(&sd->gspca_dev.usb_lock))
-                       break;
-
-               s5k83a_get_rotation(sd, &reg);
-               if (previous_rotation != reg) {
-                       previous_rotation = reg;
-                       pr_info("Camera was flipped\n");
-
-                       s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
-                       s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
-
-                       if (reg) {
-                               vflip = !vflip;
-                               hflip = !hflip;
-                       }
-                       s5k83a_set_flip_real((struct gspca_dev *) sd,
-                                             vflip, hflip);
-               }
-
-               mutex_unlock(&sd->gspca_dev.usb_lock);
-               set_current_state(TASK_INTERRUPTIBLE);
-       }
-
-       /* return to "front" flip */
-       if (previous_rotation) {
-               s5k83a_get_vflip((struct gspca_dev *) sd, &vflip);
-               s5k83a_get_hflip((struct gspca_dev *) sd, &hflip);
-               s5k83a_set_flip_real((struct gspca_dev *) sd, vflip, hflip);
-       }
-
-       sens_priv->rotation_thread = NULL;
-       return 0;
-}
-
-int s5k83a_start(struct sd *sd)
-{
-       int i, err = 0;
-       struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-       /* Create another thread, polling the GPIO ports of the camera to check
-          if it got rotated. This is how the windows driver does it so we have
-          to assume that there is no better way of accomplishing this */
-       sens_priv->rotation_thread = kthread_create(rotation_thread_function,
-                                                   sd, "rotation thread");
-       wake_up_process(sens_priv->rotation_thread);
-
-       /* Preinit the sensor */
-       for (i = 0; i < ARRAY_SIZE(start_s5k83a) && !err; i++) {
-               u8 data[2] = {start_s5k83a[i][2], start_s5k83a[i][3]};
-               if (start_s5k83a[i][0] == SENSOR)
-                       err = m5602_write_sensor(sd, start_s5k83a[i][1],
-                               data, 2);
-               else
-                       err = m5602_write_bridge(sd, start_s5k83a[i][1],
-                               data[0]);
-       }
-       if (err < 0)
-               return err;
-
-       return s5k83a_set_led_indication(sd, 1);
-}
-
-int s5k83a_stop(struct sd *sd)
-{
-       struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-       if (sens_priv->rotation_thread)
-               kthread_stop(sens_priv->rotation_thread);
-
-       return s5k83a_set_led_indication(sd, 0);
-}
-
-void s5k83a_disconnect(struct sd *sd)
-{
-       struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-       s5k83a_stop(sd);
-
-       sd->sensor = NULL;
-       kfree(sens_priv->settings);
-       kfree(sens_priv);
-}
-
-static int s5k83a_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-       *val = sens_priv->settings[GAIN_IDX];
-       return 0;
-}
-
-static int s5k83a_set_gain(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 data[2];
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-       sens_priv->settings[GAIN_IDX] = val;
-
-       data[0] = 0x00;
-       data[1] = 0x20;
-       err = m5602_write_sensor(sd, 0x14, data, 2);
-       if (err < 0)
-               return err;
-
-       data[0] = 0x01;
-       data[1] = 0x00;
-       err = m5602_write_sensor(sd, 0x0d, data, 2);
-       if (err < 0)
-               return err;
-
-       /* FIXME: This is not sane, we need to figure out the composition
-                 of these registers */
-       data[0] = val >> 3; /* gain, high 5 bits */
-       data[1] = val >> 1; /* gain, high 7 bits */
-       err = m5602_write_sensor(sd, S5K83A_GAIN, data, 2);
-
-       return err;
-}
-
-static int s5k83a_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-       *val = sens_priv->settings[BRIGHTNESS_IDX];
-       return 0;
-}
-
-static int s5k83a_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 data[1];
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-       sens_priv->settings[BRIGHTNESS_IDX] = val;
-       data[0] = val;
-       err = m5602_write_sensor(sd, S5K83A_BRIGHTNESS, data, 1);
-       return err;
-}
-
-static int s5k83a_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-       *val = sens_priv->settings[EXPOSURE_IDX];
-       return 0;
-}
-
-static int s5k83a_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 data[2];
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-       sens_priv->settings[EXPOSURE_IDX] = val;
-       data[0] = 0;
-       data[1] = val;
-       err = m5602_write_sensor(sd, S5K83A_EXPOSURE, data, 2);
-       return err;
-}
-
-static int s5k83a_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-       *val = sens_priv->settings[VFLIP_IDX];
-       return 0;
-}
-
-static int s5k83a_set_flip_real(struct gspca_dev *gspca_dev,
-                               __s32 vflip, __s32 hflip)
-{
-       int err;
-       u8 data[1];
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       data[0] = 0x05;
-       err = m5602_write_sensor(sd, S5K83A_PAGE_MAP, data, 1);
-       if (err < 0)
-               return err;
-
-       /* six bit is vflip, seven is hflip */
-       data[0] = S5K83A_FLIP_MASK;
-       data[0] = (vflip) ? data[0] | 0x40 : data[0];
-       data[0] = (hflip) ? data[0] | 0x80 : data[0];
-
-       err = m5602_write_sensor(sd, S5K83A_FLIP, data, 1);
-       if (err < 0)
-               return err;
-
-       data[0] = (vflip) ? 0x0b : 0x0a;
-       err = m5602_write_sensor(sd, S5K83A_VFLIP_TUNE, data, 1);
-       if (err < 0)
-               return err;
-
-       data[0] = (hflip) ? 0x0a : 0x0b;
-       err = m5602_write_sensor(sd, S5K83A_HFLIP_TUNE, data, 1);
-       return err;
-}
-
-static int s5k83a_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 reg;
-       __s32 hflip;
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-       sens_priv->settings[VFLIP_IDX] = val;
-
-       s5k83a_get_hflip(gspca_dev, &hflip);
-
-       err = s5k83a_get_rotation(sd, &reg);
-       if (err < 0)
-               return err;
-       if (reg) {
-               val = !val;
-               hflip = !hflip;
-       }
-
-       err = s5k83a_set_flip_real(gspca_dev, val, hflip);
-       return err;
-}
-
-static int s5k83a_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-       *val = sens_priv->settings[HFLIP_IDX];
-       return 0;
-}
-
-static int s5k83a_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u8 reg;
-       __s32 vflip;
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct s5k83a_priv *sens_priv = sd->sensor_priv;
-
-       sens_priv->settings[HFLIP_IDX] = val;
-
-       s5k83a_get_vflip(gspca_dev, &vflip);
-
-       err = s5k83a_get_rotation(sd, &reg);
-       if (err < 0)
-               return err;
-       if (reg) {
-               val = !val;
-               vflip = !vflip;
-       }
-
-       err = s5k83a_set_flip_real(gspca_dev, vflip, val);
-       return err;
-}
-
-static int s5k83a_set_led_indication(struct sd *sd, u8 val)
-{
-       int err = 0;
-       u8 data[1];
-
-       err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, data);
-       if (err < 0)
-               return err;
-
-       if (val)
-               data[0] = data[0] | S5K83A_GPIO_LED_MASK;
-       else
-               data[0] = data[0] & ~S5K83A_GPIO_LED_MASK;
-
-       err = m5602_write_bridge(sd, M5602_XB_GPIO_DAT, data[0]);
-
-       return err;
-}
-
-/* Get camera rotation on Acer notebooks */
-static int s5k83a_get_rotation(struct sd *sd, u8 *reg_data)
-{
-       int err = m5602_read_bridge(sd, M5602_XB_GPIO_DAT, reg_data);
-       *reg_data = (*reg_data & S5K83A_GPIO_ROTATION_MASK) ? 0 : 1;
-       return err;
-}
-
-static void s5k83a_dump_registers(struct sd *sd)
-{
-       int address;
-       u8 page, old_page;
-       m5602_read_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
-
-       for (page = 0; page < 16; page++) {
-               m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
-               pr_info("Dumping the s5k83a register state for page 0x%x\n",
-                       page);
-               for (address = 0; address <= 0xff; address++) {
-                       u8 val = 0;
-                       m5602_read_sensor(sd, address, &val, 1);
-                       pr_info("register 0x%x contains 0x%x\n", address, val);
-               }
-       }
-       pr_info("s5k83a register state dump complete\n");
-
-       for (page = 0; page < 16; page++) {
-               m5602_write_sensor(sd, S5K83A_PAGE_MAP, &page, 1);
-               pr_info("Probing for which registers that are read/write for page 0x%x\n",
-                       page);
-               for (address = 0; address <= 0xff; address++) {
-                       u8 old_val, ctrl_val, test_val = 0xff;
-
-                       m5602_read_sensor(sd, address, &old_val, 1);
-                       m5602_write_sensor(sd, address, &test_val, 1);
-                       m5602_read_sensor(sd, address, &ctrl_val, 1);
-
-                       if (ctrl_val == test_val)
-                               pr_info("register 0x%x is writeable\n",
-                                       address);
-                       else
-                               pr_info("register 0x%x is read only\n",
-                                       address);
-
-                       /* Restore original val */
-                       m5602_write_sensor(sd, address, &old_val, 1);
-               }
-       }
-       pr_info("Read/write register probing complete\n");
-       m5602_write_sensor(sd, S5K83A_PAGE_MAP, &old_page, 1);
-}
diff --git a/drivers/media/video/gspca/m5602/m5602_s5k83a.h b/drivers/media/video/gspca/m5602/m5602_s5k83a.h
deleted file mode 100644 (file)
index 7995224..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Driver for the s5k83a sensor
- *
- * Copyright (C) 2008 Erik Andrén
- * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#ifndef M5602_S5K83A_H_
-#define M5602_S5K83A_H_
-
-#include "m5602_sensor.h"
-
-#define S5K83A_FLIP                    0x01
-#define S5K83A_HFLIP_TUNE              0x03
-#define S5K83A_VFLIP_TUNE              0x05
-#define S5K83A_BRIGHTNESS              0x0a
-#define S5K83A_EXPOSURE                        0x18
-#define S5K83A_GAIN                    0x1b
-#define S5K83A_PAGE_MAP                        0xec
-
-#define S5K83A_DEFAULT_GAIN            0x71
-#define S5K83A_DEFAULT_BRIGHTNESS      0x7e
-#define S5K83A_DEFAULT_EXPOSURE                0x00
-#define S5K83A_MAXIMUM_EXPOSURE                0x3c
-#define S5K83A_FLIP_MASK               0x10
-#define S5K83A_GPIO_LED_MASK           0x10
-#define S5K83A_GPIO_ROTATION_MASK      0x40
-
-/*****************************************************************************/
-
-/* Kernel module parameters */
-extern int force_sensor;
-extern bool dump_sensor;
-
-int s5k83a_probe(struct sd *sd);
-int s5k83a_init(struct sd *sd);
-int s5k83a_start(struct sd *sd);
-int s5k83a_stop(struct sd *sd);
-void s5k83a_disconnect(struct sd *sd);
-
-static const struct m5602_sensor s5k83a = {
-       .name = "S5K83A",
-       .probe = s5k83a_probe,
-       .init = s5k83a_init,
-       .start = s5k83a_start,
-       .stop = s5k83a_stop,
-       .disconnect = s5k83a_disconnect,
-       .i2c_slave_id = 0x5a,
-       .i2c_regW = 2,
-};
-
-struct s5k83a_priv {
-       /* We use another thread periodically
-          probing the orientation of the camera */
-       struct task_struct *rotation_thread;
-       s32 *settings;
-};
-
-static const unsigned char preinit_s5k83a[][4] = {
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x0d, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_CTRL, 0x00, 0x00},
-
-       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x1c, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
-       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
-};
-
-/* This could probably be considerably shortened.
-   I don't have the hardware to experiment with it, patches welcome
-*/
-static const unsigned char init_s5k83a[][4] = {
-       /* The following sequence is useless after a clean boot
-          but is necessary after resume from suspend */
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x3f, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x3f, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0xff, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_L, 0xff, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_L, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0x80, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-       {BRIDGE, M5602_XB_MCU_CLK_DIV, 0x02, 0x00},
-       {BRIDGE, M5602_XB_MCU_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xf0, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR, 0x1d, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT, 0x08, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_H, 0x06, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DIR_H, 0x06, 0x00},
-       {BRIDGE, M5602_XB_GPIO_DAT_H, 0x00, 0x00},
-       {BRIDGE, M5602_XB_GPIO_EN_L, 0x00, 0x00},
-       {BRIDGE, M5602_XB_I2C_CLK_DIV, 0x20, 0x00},
-
-       {SENSOR, S5K83A_PAGE_MAP, 0x04, 0x00},
-       {SENSOR, 0xaf, 0x01, 0x00},
-       {SENSOR, S5K83A_PAGE_MAP, 0x00, 0x00},
-       {SENSOR, 0x7b, 0xff, 0x00},
-       {SENSOR, S5K83A_PAGE_MAP, 0x05, 0x00},
-       {SENSOR, 0x01, 0x50, 0x00},
-       {SENSOR, 0x12, 0x20, 0x00},
-       {SENSOR, 0x17, 0x40, 0x00},
-       {SENSOR, 0x1c, 0x00, 0x00},
-       {SENSOR, 0x02, 0x70, 0x00},
-       {SENSOR, 0x03, 0x0b, 0x00},
-       {SENSOR, 0x04, 0xf0, 0x00},
-       {SENSOR, 0x05, 0x0b, 0x00},
-       {SENSOR, 0x06, 0x71, 0x00},
-       {SENSOR, 0x07, 0xe8, 0x00}, /* 488 */
-       {SENSOR, 0x08, 0x02, 0x00},
-       {SENSOR, 0x09, 0x88, 0x00}, /* 648 */
-       {SENSOR, 0x14, 0x00, 0x00},
-       {SENSOR, 0x15, 0x20, 0x00}, /* 32 */
-       {SENSOR, 0x19, 0x00, 0x00},
-       {SENSOR, 0x1a, 0x98, 0x00}, /* 152 */
-       {SENSOR, 0x0f, 0x02, 0x00},
-       {SENSOR, 0x10, 0xe5, 0x00}, /* 741 */
-       /* normal colors
-       (this is value after boot, but after tries can be different) */
-       {SENSOR, 0x00, 0x06, 0x00},
-};
-
-static const unsigned char start_s5k83a[][4] = {
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x06, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-       {BRIDGE, M5602_XB_ADC_CTRL, 0xc0, 0x00},
-       {BRIDGE, M5602_XB_SENSOR_TYPE, 0x09, 0x00},
-       {BRIDGE, M5602_XB_LINE_OF_FRAME_H, 0x81, 0x00},
-       {BRIDGE, M5602_XB_PIX_OF_LINE_H, 0x82, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x01, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x01, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0xe4, 0x00}, /* 484 */
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_VSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SIG_INI, 0x02, 0x00},
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x00, 0x00},
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x02, 0x00},
-       {BRIDGE, M5602_XB_HSYNC_PARA, 0x7f, 0x00}, /* 639 */
-       {BRIDGE, M5602_XB_SIG_INI, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_DIV, 0x00, 0x00},
-       {BRIDGE, M5602_XB_SEN_CLK_CTRL, 0xb0, 0x00},
-};
-#endif
diff --git a/drivers/media/video/gspca/m5602/m5602_sensor.h b/drivers/media/video/gspca/m5602/m5602_sensor.h
deleted file mode 100644 (file)
index edff4f1..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * USB Driver for ALi m5602 based webcams
- *
- * Copyright (C) 2008 Erik Andrén
- * Copyright (C) 2007 Ilyes Gouta. Based on the m5603x Linux Driver Project.
- * Copyright (C) 2005 m5603x Linux Driver Project <m5602@x3ng.com.br>
- *
- * Portions of code to USB interface and ALi driver software,
- * Copyright (c) 2006 Willem Duinker
- * v4l2 interface modeled after the V4L2 driver
- * for SN9C10x PC Camera Controllers
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2.
- *
- */
-
-#ifndef M5602_SENSOR_H_
-#define M5602_SENSOR_H_
-
-#include "m5602_bridge.h"
-
-#define M5602_V4L2_CID_GREEN_BALANCE   (V4L2_CID_PRIVATE_BASE + 0)
-#define M5602_V4L2_CID_NOISE_SUPPRESION        (V4L2_CID_PRIVATE_BASE + 1)
-
-/* Enumerates all supported sensors */
-enum sensors {
-       OV9650_SENSOR   = 1,
-       S5K83A_SENSOR   = 2,
-       S5K4AA_SENSOR   = 3,
-       MT9M111_SENSOR  = 4,
-       PO1030_SENSOR   = 5,
-       OV7660_SENSOR   = 6,
-};
-
-/* Enumerates all possible instruction types */
-enum instruction {
-       BRIDGE,
-       SENSOR,
-       SENSOR_LONG
-};
-
-struct m5602_sensor {
-       /* Defines the name of a sensor */
-       char name[32];
-
-       /* What i2c address the sensor is connected to */
-       u8 i2c_slave_id;
-
-       /* Width of each i2c register (in bytes) */
-       u8 i2c_regW;
-
-       /* Probes if the sensor is connected */
-       int (*probe)(struct sd *sd);
-
-       /* Performs a initialization sequence */
-       int (*init)(struct sd *sd);
-
-       /* Executed when the camera starts to send data */
-       int (*start)(struct sd *sd);
-
-       /* Executed when the camera ends to send data */
-       int (*stop)(struct sd *sd);
-
-       /* Executed when the device is disconnected */
-       void (*disconnect)(struct sd *sd);
-};
-
-#endif
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c
deleted file mode 100644 (file)
index ff2c5ab..0000000
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- *             Mars-Semi MR97311A library
- *             Copyright (C) 2005 <bradlch@hotmail.com>
- *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "mars"
-
-#include "gspca.h"
-#include "jpeg.h"
-
-MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
-MODULE_DESCRIPTION("GSPCA/Mars USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-#define QUALITY 50
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       struct v4l2_ctrl *brightness;
-       struct v4l2_ctrl *saturation;
-       struct v4l2_ctrl *sharpness;
-       struct v4l2_ctrl *gamma;
-       struct { /* illuminator control cluster */
-               struct v4l2_ctrl *illum_top;
-               struct v4l2_ctrl *illum_bottom;
-       };
-       u8 jpeg_hdr[JPEG_HDR_SZ];
-};
-
-/* V4L2 controls supported by the driver */
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val);
-static void setcolors(struct gspca_dev *gspca_dev, s32 val);
-static void setgamma(struct gspca_dev *gspca_dev, s32 val);
-static void setsharpness(struct gspca_dev *gspca_dev, s32 val);
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 2},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-};
-
-static const __u8 mi_data[0x20] = {
-/*      01    02   03     04    05    06    07    08 */
-       0x48, 0x22, 0x01, 0x47, 0x10, 0x00, 0x00, 0x00,
-/*      09    0a   0b     0c    0d    0e    0f    10 */
-       0x00, 0x01, 0x30, 0x01, 0x30, 0x01, 0x30, 0x01,
-/*      11    12   13     14    15    16    17    18 */
-       0x30, 0x00, 0x04, 0x00, 0x06, 0x01, 0xe2, 0x02,
-/*      19    1a   1b     1c    1d    1e    1f    20 */
-       0x82, 0x00, 0x20, 0x17, 0x80, 0x08, 0x0c, 0x00
-};
-
-/* write <len> bytes from gspca_dev->usb_buf */
-static void reg_w(struct gspca_dev *gspca_dev,
-                int len)
-{
-       int alen, ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-
-       ret = usb_bulk_msg(gspca_dev->dev,
-                       usb_sndbulkpipe(gspca_dev->dev, 4),
-                       gspca_dev->usb_buf,
-                       len,
-                       &alen,
-                       500);   /* timeout in milliseconds */
-       if (ret < 0) {
-               pr_err("reg write [%02x] error %d\n",
-                      gspca_dev->usb_buf[0], ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void mi_w(struct gspca_dev *gspca_dev,
-                u8 addr,
-                u8 value)
-{
-       gspca_dev->usb_buf[0] = 0x1f;
-       gspca_dev->usb_buf[1] = 0;                      /* control byte */
-       gspca_dev->usb_buf[2] = addr;
-       gspca_dev->usb_buf[3] = value;
-
-       reg_w(gspca_dev, 4);
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       gspca_dev->usb_buf[0] = 0x61;
-       gspca_dev->usb_buf[1] = val;
-       reg_w(gspca_dev, 2);
-}
-
-static void setcolors(struct gspca_dev *gspca_dev, s32 val)
-{
-       gspca_dev->usb_buf[0] = 0x5f;
-       gspca_dev->usb_buf[1] = val << 3;
-       gspca_dev->usb_buf[2] = ((val >> 2) & 0xf8) | 0x04;
-       reg_w(gspca_dev, 3);
-}
-
-static void setgamma(struct gspca_dev *gspca_dev, s32 val)
-{
-       gspca_dev->usb_buf[0] = 0x06;
-       gspca_dev->usb_buf[1] = val * 0x40;
-       reg_w(gspca_dev, 2);
-}
-
-static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
-{
-       gspca_dev->usb_buf[0] = 0x67;
-       gspca_dev->usb_buf[1] = val * 4 + 3;
-       reg_w(gspca_dev, 2);
-}
-
-static void setilluminators(struct gspca_dev *gspca_dev, bool top, bool bottom)
-{
-       /* both are off if not streaming */
-       gspca_dev->usb_buf[0] = 0x22;
-       if (top)
-               gspca_dev->usb_buf[1] = 0x76;
-       else if (bottom)
-               gspca_dev->usb_buf[1] = 0x7a;
-       else
-               gspca_dev->usb_buf[1] = 0x7e;
-       reg_w(gspca_dev, 2);
-}
-
-static int mars_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 (ctrl->id == V4L2_CID_ILLUMINATORS_1) {
-               /* only one can be on at a time */
-               if (ctrl->is_new && ctrl->val)
-                       sd->illum_bottom->val = 0;
-               if (sd->illum_bottom->is_new && sd->illum_bottom->val)
-                       sd->illum_top->val = 0;
-       }
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               setcolors(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_GAMMA:
-               setgamma(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_ILLUMINATORS_1:
-               setilluminators(gspca_dev, sd->illum_top->val,
-                                          sd->illum_bottom->val);
-               break;
-       case V4L2_CID_SHARPNESS:
-               setsharpness(gspca_dev, ctrl->val);
-               break;
-       default:
-               return -EINVAL;
-       }
-       return gspca_dev->usb_err;
-}
-
-static const struct v4l2_ctrl_ops mars_ctrl_ops = {
-       .s_ctrl = mars_s_ctrl,
-};
-
-/* this function is called at probe time */
-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, 6);
-       sd->brightness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 30, 1, 15);
-       sd->saturation = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 255, 1, 200);
-       sd->gamma = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
-                       V4L2_CID_GAMMA, 0, 3, 1, 1);
-       sd->sharpness = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
-                       V4L2_CID_SHARPNESS, 0, 2, 1, 1);
-       sd->illum_top = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
-                       V4L2_CID_ILLUMINATORS_1, 0, 1, 1, 0);
-       sd->illum_top->flags |= V4L2_CTRL_FLAG_UPDATE;
-       sd->illum_bottom = v4l2_ctrl_new_std(hdl, &mars_ctrl_ops,
-                       V4L2_CID_ILLUMINATORS_2, 0, 1, 1, 0);
-       sd->illum_bottom->flags |= V4L2_CTRL_FLAG_UPDATE;
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-       v4l2_ctrl_cluster(2, &sd->illum_top);
-       return 0;
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct cam *cam;
-
-       cam = &gspca_dev->cam;
-       cam->cam_mode = vga_mode;
-       cam->nmodes = ARRAY_SIZE(vga_mode);
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       return 0;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 *data;
-       int i;
-
-       /* create the JPEG header */
-       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
-                       0x21);          /* JPEG 422 */
-       jpeg_set_qual(sd->jpeg_hdr, QUALITY);
-
-       data = gspca_dev->usb_buf;
-
-       data[0] = 0x01;         /* address */
-       data[1] = 0x01;
-       reg_w(gspca_dev, 2);
-
-       /*
-          Initialize the MR97113 chip register
-        */
-       data[0] = 0x00;         /* address */
-       data[1] = 0x0c | 0x01;  /* reg 0 */
-       data[2] = 0x01;         /* reg 1 */
-       data[3] = gspca_dev->width / 8;         /* h_size , reg 2 */
-       data[4] = gspca_dev->height / 8;        /* v_size , reg 3 */
-       data[5] = 0x30;         /* reg 4, MI, PAS5101 :
-                                *      0x30 for 24mhz , 0x28 for 12mhz */
-       data[6] = 0x02;         /* reg 5, H start - was 0x04 */
-       data[7] = v4l2_ctrl_g_ctrl(sd->gamma) * 0x40;   /* reg 0x06: gamma */
-       data[8] = 0x01;         /* reg 7, V start - was 0x03 */
-/*     if (h_size == 320 ) */
-/*             data[9]= 0x56;   * reg 8, 24MHz, 2:1 scale down */
-/*     else */
-       data[9] = 0x52;         /* reg 8, 24MHz, no scale down */
-/*jfm: from win trace*/
-       data[10] = 0x18;
-
-       reg_w(gspca_dev, 11);
-
-       data[0] = 0x23;         /* address */
-       data[1] = 0x09;         /* reg 35, append frame header */
-
-       reg_w(gspca_dev, 2);
-
-       data[0] = 0x3c;         /* address */
-/*     if (gspca_dev->width == 1280) */
-/*             data[1] = 200;   * reg 60, pc-cam frame size
-                                *      (unit: 4KB) 800KB */
-/*     else */
-       data[1] = 50;           /* 50 reg 60, pc-cam frame size
-                                *      (unit: 4KB) 200KB */
-       reg_w(gspca_dev, 2);
-
-       /* auto dark-gain */
-       data[0] = 0x5e;         /* address */
-       data[1] = 0;            /* reg 94, Y Gain (auto) */
-/*jfm: from win trace*/
-                               /* reg 0x5f/0x60 (LE) = saturation */
-                               /* h (60): xxxx x100
-                                * l (5f): xxxx x000 */
-       data[2] = v4l2_ctrl_g_ctrl(sd->saturation) << 3;
-       data[3] = ((v4l2_ctrl_g_ctrl(sd->saturation) >> 2) & 0xf8) | 0x04;
-       data[4] = v4l2_ctrl_g_ctrl(sd->brightness); /* reg 0x61 = brightness */
-       data[5] = 0x00;
-
-       reg_w(gspca_dev, 6);
-
-       data[0] = 0x67;
-/*jfm: from win trace*/
-       data[1] = v4l2_ctrl_g_ctrl(sd->sharpness) * 4 + 3;
-       data[2] = 0x14;
-       reg_w(gspca_dev, 3);
-
-       data[0] = 0x69;
-       data[1] = 0x2f;
-       data[2] = 0x28;
-       data[3] = 0x42;
-       reg_w(gspca_dev, 4);
-
-       data[0] = 0x63;
-       data[1] = 0x07;
-       reg_w(gspca_dev, 2);
-/*jfm: win trace - many writes here to reg 0x64*/
-
-       /* initialize the MI sensor */
-       for (i = 0; i < sizeof mi_data; i++)
-               mi_w(gspca_dev, i + 1, mi_data[i]);
-
-       data[0] = 0x00;
-       data[1] = 0x4d;         /* ISOC transferring enable... */
-       reg_w(gspca_dev, 2);
-
-       setilluminators(gspca_dev, v4l2_ctrl_g_ctrl(sd->illum_top),
-                                  v4l2_ctrl_g_ctrl(sd->illum_bottom));
-
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (v4l2_ctrl_g_ctrl(sd->illum_top) ||
-           v4l2_ctrl_g_ctrl(sd->illum_bottom)) {
-               setilluminators(gspca_dev, false, false);
-               msleep(20);
-       }
-
-       gspca_dev->usb_buf[0] = 1;
-       gspca_dev->usb_buf[1] = 0;
-       reg_w(gspca_dev, 2);
-}
-
-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;
-       int p;
-
-       if (len < 6) {
-/*             gspca_dev->last_packet_type = DISCARD_PACKET; */
-               return;
-       }
-       for (p = 0; p < len - 6; p++) {
-               if (data[0 + p] == 0xff
-                   && data[1 + p] == 0xff
-                   && data[2 + p] == 0x00
-                   && data[3 + p] == 0xff
-                   && data[4 + p] == 0x96) {
-                       if (data[5 + p] == 0x64
-                           || data[5 + p] == 0x65
-                           || data[5 + p] == 0x66
-                           || data[5 + p] == 0x67) {
-                               PDEBUG(D_PACK, "sof offset: %d len: %d",
-                                       p, len);
-                               gspca_frame_add(gspca_dev, LAST_PACKET,
-                                               data, p);
-
-                               /* put the JPEG header */
-                               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                                       sd->jpeg_hdr, JPEG_HDR_SZ);
-                               data += p + 16;
-                               len -= p + 16;
-                               break;
-                       }
-               }
-       }
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-/* 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,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x093a, 0x050f)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/mr97310a.c b/drivers/media/video/gspca/mr97310a.c
deleted file mode 100644 (file)
index 8f4714d..0000000
+++ /dev/null
@@ -1,1091 +0,0 @@
-/*
- * Mars MR97310A library
- *
- * The original mr97310a driver, which supported the Aiptek Pencam VGA+, is
- * Copyright (C) 2009 Kyle Guinn <elyk03@gmail.com>
- *
- * Support for the MR97310A cameras in addition to the Aiptek Pencam VGA+
- * and for the routines for detecting and classifying these various cameras,
- * is Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
- *
- * Support for the control settings for the CIF cameras is
- * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> and
- * Thomas Kaiser <thomas@kaiser-linux.li>
- *
- * Support for the control settings for the VGA cameras is
- * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
- *
- * Several previously unsupported cameras are owned and have been tested by
- * Hans de Goede <hdegoede@redhat.com> and
- * Thomas Kaiser <thomas@kaiser-linux.li> and
- * Theodore Kilgore <kilgota@auburn.edu> and
- * Edmond Rodriguez <erodrig_97@yahoo.com> and
- * Aurelien Jacobs <aurel@gnuage.org>
- *
- * The MR97311A support in gspca/mars.c has been helpful in understanding some
- * of the registers in these cameras.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "mr97310a"
-
-#include "gspca.h"
-
-#define CAM_TYPE_CIF                   0
-#define CAM_TYPE_VGA                   1
-
-#define MR97310A_BRIGHTNESS_DEFAULT    0
-
-#define MR97310A_EXPOSURE_MIN          0
-#define MR97310A_EXPOSURE_MAX          4095
-#define MR97310A_EXPOSURE_DEFAULT      1000
-
-#define MR97310A_GAIN_MIN              0
-#define MR97310A_GAIN_MAX              31
-#define MR97310A_GAIN_DEFAULT          25
-
-#define MR97310A_CONTRAST_MIN          0
-#define MR97310A_CONTRAST_MAX          31
-#define MR97310A_CONTRAST_DEFAULT      23
-
-#define MR97310A_CS_GAIN_MIN           0
-#define MR97310A_CS_GAIN_MAX           0x7ff
-#define MR97310A_CS_GAIN_DEFAULT       0x110
-
-#define MR97310A_CID_CLOCKDIV (V4L2_CTRL_CLASS_USER + 0x1000)
-#define MR97310A_MIN_CLOCKDIV_MIN      3
-#define MR97310A_MIN_CLOCKDIV_MAX      8
-#define MR97310A_MIN_CLOCKDIV_DEFAULT  3
-
-MODULE_AUTHOR("Kyle Guinn <elyk03@gmail.com>,"
-             "Theodore Kilgore <kilgota@auburn.edu>");
-MODULE_DESCRIPTION("GSPCA/Mars-Semi MR97310A USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* global parameters */
-static int force_sensor_type = -1;
-module_param(force_sensor_type, int, 0644);
-MODULE_PARM_DESC(force_sensor_type, "Force sensor type (-1 (auto), 0 or 1)");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;  /* !! must be the first item */
-       struct { /* exposure/min_clockdiv control cluster */
-               struct v4l2_ctrl *exposure;
-               struct v4l2_ctrl *min_clockdiv;
-       };
-       u8 sof_read;
-       u8 cam_type;    /* 0 is CIF and 1 is VGA */
-       u8 sensor_type; /* We use 0 and 1 here, too. */
-       u8 do_lcd_stop;
-       u8 adj_colors;
-};
-
-struct sensor_w_data {
-       u8 reg;
-       u8 flags;
-       u8 data[16];
-       int len;
-};
-
-static void sd_stopN(struct gspca_dev *gspca_dev);
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {160, 120, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 4},
-       {176, 144, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 3},
-       {320, 240, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2},
-       {352, 288, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_MR97310A, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-/* the bytes to write are in gspca_dev->usb_buf */
-static int mr_write(struct gspca_dev *gspca_dev, int len)
-{
-       int rc;
-
-       rc = usb_bulk_msg(gspca_dev->dev,
-                         usb_sndbulkpipe(gspca_dev->dev, 4),
-                         gspca_dev->usb_buf, len, NULL, 500);
-       if (rc < 0)
-               pr_err("reg write [%02x] error %d\n",
-                      gspca_dev->usb_buf[0], rc);
-       return rc;
-}
-
-/* the bytes are read into gspca_dev->usb_buf */
-static int mr_read(struct gspca_dev *gspca_dev, int len)
-{
-       int rc;
-
-       rc = usb_bulk_msg(gspca_dev->dev,
-                         usb_rcvbulkpipe(gspca_dev->dev, 3),
-                         gspca_dev->usb_buf, len, NULL, 500);
-       if (rc < 0)
-               pr_err("reg read [%02x] error %d\n",
-                      gspca_dev->usb_buf[0], rc);
-       return rc;
-}
-
-static int sensor_write_reg(struct gspca_dev *gspca_dev, u8 reg, u8 flags,
-       const u8 *data, int len)
-{
-       gspca_dev->usb_buf[0] = 0x1f;
-       gspca_dev->usb_buf[1] = flags;
-       gspca_dev->usb_buf[2] = reg;
-       memcpy(gspca_dev->usb_buf + 3, data, len);
-
-       return mr_write(gspca_dev, len + 3);
-}
-
-static int sensor_write_regs(struct gspca_dev *gspca_dev,
-       const struct sensor_w_data *data, int len)
-{
-       int i, rc;
-
-       for (i = 0; i < len; i++) {
-               rc = sensor_write_reg(gspca_dev, data[i].reg, data[i].flags,
-                                         data[i].data, data[i].len);
-               if (rc < 0)
-                       return rc;
-       }
-
-       return 0;
-}
-
-static int sensor_write1(struct gspca_dev *gspca_dev, u8 reg, u8 data)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 buf, confirm_reg;
-       int rc;
-
-       buf = data;
-       if (sd->cam_type == CAM_TYPE_CIF) {
-               rc = sensor_write_reg(gspca_dev, reg, 0x01, &buf, 1);
-               confirm_reg = sd->sensor_type ? 0x13 : 0x11;
-       } else {
-               rc = sensor_write_reg(gspca_dev, reg, 0x00, &buf, 1);
-               confirm_reg = 0x11;
-       }
-       if (rc < 0)
-               return rc;
-
-       buf = 0x01;
-       rc = sensor_write_reg(gspca_dev, confirm_reg, 0x00, &buf, 1);
-       if (rc < 0)
-               return rc;
-
-       return 0;
-}
-
-static int cam_get_response16(struct gspca_dev *gspca_dev, u8 reg, int verbose)
-{
-       int err_code;
-
-       gspca_dev->usb_buf[0] = reg;
-       err_code = mr_write(gspca_dev, 1);
-       if (err_code < 0)
-               return err_code;
-
-       err_code = mr_read(gspca_dev, 16);
-       if (err_code < 0)
-               return err_code;
-
-       if (verbose)
-               PDEBUG(D_PROBE, "Register: %02x reads %02x%02x%02x", reg,
-                      gspca_dev->usb_buf[0],
-                      gspca_dev->usb_buf[1],
-                      gspca_dev->usb_buf[2]);
-
-       return 0;
-}
-
-static int zero_the_pointer(struct gspca_dev *gspca_dev)
-{
-       __u8 *data = gspca_dev->usb_buf;
-       int err_code;
-       u8 status = 0;
-       int tries = 0;
-
-       err_code = cam_get_response16(gspca_dev, 0x21, 0);
-       if (err_code < 0)
-               return err_code;
-
-       data[0] = 0x19;
-       data[1] = 0x51;
-       err_code = mr_write(gspca_dev, 2);
-       if (err_code < 0)
-               return err_code;
-
-       err_code = cam_get_response16(gspca_dev, 0x21, 0);
-       if (err_code < 0)
-               return err_code;
-
-       data[0] = 0x19;
-       data[1] = 0xba;
-       err_code = mr_write(gspca_dev, 2);
-       if (err_code < 0)
-               return err_code;
-
-       err_code = cam_get_response16(gspca_dev, 0x21, 0);
-       if (err_code < 0)
-               return err_code;
-
-       data[0] = 0x19;
-       data[1] = 0x00;
-       err_code = mr_write(gspca_dev, 2);
-       if (err_code < 0)
-               return err_code;
-
-       err_code = cam_get_response16(gspca_dev, 0x21, 0);
-       if (err_code < 0)
-               return err_code;
-
-       data[0] = 0x19;
-       data[1] = 0x00;
-       err_code = mr_write(gspca_dev, 2);
-       if (err_code < 0)
-               return err_code;
-
-       while (status != 0x0a && tries < 256) {
-               err_code = cam_get_response16(gspca_dev, 0x21, 0);
-               status = data[0];
-               tries++;
-               if (err_code < 0)
-                       return err_code;
-       }
-       if (status != 0x0a)
-               PDEBUG(D_ERR, "status is %02x", status);
-
-       tries = 0;
-       while (tries < 4) {
-               data[0] = 0x19;
-               data[1] = 0x00;
-               err_code = mr_write(gspca_dev, 2);
-               if (err_code < 0)
-                       return err_code;
-
-               err_code = cam_get_response16(gspca_dev, 0x21, 0);
-               status = data[0];
-               tries++;
-               if (err_code < 0)
-                       return err_code;
-       }
-
-       data[0] = 0x19;
-       err_code = mr_write(gspca_dev, 1);
-       if (err_code < 0)
-               return err_code;
-
-       err_code = mr_read(gspca_dev, 16);
-       if (err_code < 0)
-               return err_code;
-
-       return 0;
-}
-
-static int stream_start(struct gspca_dev *gspca_dev)
-{
-       gspca_dev->usb_buf[0] = 0x01;
-       gspca_dev->usb_buf[1] = 0x01;
-       return mr_write(gspca_dev, 2);
-}
-
-static void stream_stop(struct gspca_dev *gspca_dev)
-{
-       gspca_dev->usb_buf[0] = 0x01;
-       gspca_dev->usb_buf[1] = 0x00;
-       if (mr_write(gspca_dev, 2) < 0)
-               PDEBUG(D_ERR, "Stream Stop failed");
-}
-
-static void lcd_stop(struct gspca_dev *gspca_dev)
-{
-       gspca_dev->usb_buf[0] = 0x19;
-       gspca_dev->usb_buf[1] = 0x54;
-       if (mr_write(gspca_dev, 2) < 0)
-               PDEBUG(D_ERR, "LCD Stop failed");
-}
-
-static int isoc_enable(struct gspca_dev *gspca_dev)
-{
-       gspca_dev->usb_buf[0] = 0x00;
-       gspca_dev->usb_buf[1] = 0x4d;  /* ISOC transferring enable... */
-       return mr_write(gspca_dev, 2);
-}
-
-/* This function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                    const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-       int err_code;
-
-       cam = &gspca_dev->cam;
-       cam->cam_mode = vga_mode;
-       cam->nmodes = ARRAY_SIZE(vga_mode);
-       sd->do_lcd_stop = 0;
-
-       /* Several of the supported CIF cameras share the same USB ID but
-        * require different initializations and different control settings.
-        * The same is true of the VGA cameras. Therefore, we are forced
-        * to start the initialization process in order to determine which
-        * camera is present. Some of the supported cameras require the
-        * memory pointer to be set to 0 as the very first item of business
-        * or else they will not stream. So we do that immediately.
-        */
-       err_code = zero_the_pointer(gspca_dev);
-       if (err_code < 0)
-               return err_code;
-
-       err_code = stream_start(gspca_dev);
-       if (err_code < 0)
-               return err_code;
-
-       /* Now, the query for sensor type. */
-       err_code = cam_get_response16(gspca_dev, 0x07, 1);
-       if (err_code < 0)
-               return err_code;
-
-       if (id->idProduct == 0x0110 || id->idProduct == 0x010e) {
-               sd->cam_type = CAM_TYPE_CIF;
-               cam->nmodes--;
-               /*
-                * All but one of the known CIF cameras share the same USB ID,
-                * but two different init routines are in use, and the control
-                * settings are different, too. We need to detect which camera
-                * of the two known varieties is connected!
-                *
-                * A list of known CIF cameras follows. They all report either
-                * 0200 for type 0 or 0300 for type 1.
-                * If you have another to report, please do
-                *
-                * Name         sd->sensor_type         reported by
-                *
-                * Sakar 56379 Spy-shot 0               T. Kilgore
-                * Innovage             0               T. Kilgore
-                * Vivitar Mini         0               H. De Goede
-                * Vivitar Mini         0               E. Rodriguez
-                * Vivitar Mini         1               T. Kilgore
-                * Elta-Media 8212dc    1               T. Kaiser
-                * Philips dig. keych.  1               T. Kilgore
-                * Trust Spyc@m 100     1               A. Jacobs
-                */
-               switch (gspca_dev->usb_buf[0]) {
-               case 2:
-                       sd->sensor_type = 0;
-                       break;
-               case 3:
-                       sd->sensor_type = 1;
-                       break;
-               default:
-                       pr_err("Unknown CIF Sensor id : %02x\n",
-                              gspca_dev->usb_buf[1]);
-                       return -ENODEV;
-               }
-               PDEBUG(D_PROBE, "MR97310A CIF camera detected, sensor: %d",
-                      sd->sensor_type);
-       } else {
-               sd->cam_type = CAM_TYPE_VGA;
-
-               /*
-                * Here is a table of the responses to the query for sensor
-                * type, from the known MR97310A VGA cameras. Six different
-                * cameras of which five share the same USB ID.
-                *
-                * Name                 gspca_dev->usb_buf[]    sd->sensor_type
-                *                              sd->do_lcd_stop
-                * Aiptek Pencam VGA+   0300            0               1
-                * ION digital          0300            0               1
-                * Argus DC-1620        0450            1               0
-                * Argus QuickClix      0420            1               1
-                * Sakar 77379 Digital  0350            0               1
-                * Sakar 1638x CyberPix 0120            0               2
-                *
-                * Based upon these results, we assume default settings
-                * and then correct as necessary, as follows.
-                *
-                */
-
-               sd->sensor_type = 1;
-               sd->do_lcd_stop = 0;
-               sd->adj_colors = 0;
-               if (gspca_dev->usb_buf[0] == 0x01) {
-                       sd->sensor_type = 2;
-               } else if ((gspca_dev->usb_buf[0] != 0x03) &&
-                                       (gspca_dev->usb_buf[0] != 0x04)) {
-                       pr_err("Unknown VGA Sensor id Byte 0: %02x\n",
-                              gspca_dev->usb_buf[0]);
-                       pr_err("Defaults assumed, may not work\n");
-                       pr_err("Please report this\n");
-               }
-               /* Sakar Digital color needs to be adjusted. */
-               if ((gspca_dev->usb_buf[0] == 0x03) &&
-                                       (gspca_dev->usb_buf[1] == 0x50))
-                       sd->adj_colors = 1;
-               if (gspca_dev->usb_buf[0] == 0x04) {
-                       sd->do_lcd_stop = 1;
-                       switch (gspca_dev->usb_buf[1]) {
-                       case 0x50:
-                               sd->sensor_type = 0;
-                               PDEBUG(D_PROBE, "sensor_type corrected to 0");
-                               break;
-                       case 0x20:
-                               /* Nothing to do here. */
-                               break;
-                       default:
-                               pr_err("Unknown VGA Sensor id Byte 1: %02x\n",
-                                      gspca_dev->usb_buf[1]);
-                               pr_err("Defaults assumed, may not work\n");
-                               pr_err("Please report this\n");
-                       }
-               }
-               PDEBUG(D_PROBE, "MR97310A VGA camera detected, sensor: %d",
-                      sd->sensor_type);
-       }
-       /* Stop streaming as we've started it only to probe the sensor type. */
-       sd_stopN(gspca_dev);
-
-       if (force_sensor_type != -1) {
-               sd->sensor_type = !!force_sensor_type;
-               PDEBUG(D_PROBE, "Forcing sensor type to: %d",
-                      sd->sensor_type);
-       }
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       return 0;
-}
-
-static int start_cif_cam(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       __u8 *data = gspca_dev->usb_buf;
-       int err_code;
-       static const __u8 startup_string[] = {
-               0x00,
-               0x0d,
-               0x01,
-               0x00, /* Hsize/8 for 352 or 320 */
-               0x00, /* Vsize/4 for 288 or 240 */
-               0x13, /* or 0xbb, depends on sensor */
-               0x00, /* Hstart, depends on res. */
-               0x00, /* reserved ? */
-               0x00, /* Vstart, depends on res. and sensor */
-               0x50, /* 0x54 to get 176 or 160 */
-               0xc0
-       };
-
-       /* Note: Some of the above descriptions guessed from MR97113A driver */
-
-       memcpy(data, startup_string, 11);
-       if (sd->sensor_type)
-               data[5] = 0xbb;
-
-       switch (gspca_dev->width) {
-       case 160:
-               data[9] |= 0x04;  /* reg 8, 2:1 scale down from 320 */
-               /* fall thru */
-       case 320:
-       default:
-               data[3] = 0x28;                    /* reg 2, H size/8 */
-               data[4] = 0x3c;                    /* reg 3, V size/4 */
-               data[6] = 0x14;                    /* reg 5, H start  */
-               data[8] = 0x1a + sd->sensor_type;  /* reg 7, V start  */
-               break;
-       case 176:
-               data[9] |= 0x04;  /* reg 8, 2:1 scale down from 352 */
-               /* fall thru */
-       case 352:
-               data[3] = 0x2c;                    /* reg 2, H size/8 */
-               data[4] = 0x48;                    /* reg 3, V size/4 */
-               data[6] = 0x06;                    /* reg 5, H start  */
-               data[8] = 0x06 - sd->sensor_type;  /* reg 7, V start  */
-               break;
-       }
-       err_code = mr_write(gspca_dev, 11);
-       if (err_code < 0)
-               return err_code;
-
-       if (!sd->sensor_type) {
-               static const struct sensor_w_data cif_sensor0_init_data[] = {
-                       {0x02, 0x00, {0x03, 0x5a, 0xb5, 0x01,
-                                     0x0f, 0x14, 0x0f, 0x10}, 8},
-                       {0x0c, 0x00, {0x04, 0x01, 0x01, 0x00, 0x1f}, 5},
-                       {0x12, 0x00, {0x07}, 1},
-                       {0x1f, 0x00, {0x06}, 1},
-                       {0x27, 0x00, {0x04}, 1},
-                       {0x29, 0x00, {0x0c}, 1},
-                       {0x40, 0x00, {0x40, 0x00, 0x04}, 3},
-                       {0x50, 0x00, {0x60}, 1},
-                       {0x60, 0x00, {0x06}, 1},
-                       {0x6b, 0x00, {0x85, 0x85, 0xc8, 0xc8, 0xc8, 0xc8}, 6},
-                       {0x72, 0x00, {0x1e, 0x56}, 2},
-                       {0x75, 0x00, {0x58, 0x40, 0xa2, 0x02, 0x31, 0x02,
-                                     0x31, 0x80, 0x00}, 9},
-                       {0x11, 0x00, {0x01}, 1},
-                       {0, 0, {0}, 0}
-               };
-               err_code = sensor_write_regs(gspca_dev, cif_sensor0_init_data,
-                                        ARRAY_SIZE(cif_sensor0_init_data));
-       } else {        /* sd->sensor_type = 1 */
-               static const struct sensor_w_data cif_sensor1_init_data[] = {
-                       /* Reg 3,4, 7,8 get set by the controls */
-                       {0x02, 0x00, {0x10}, 1},
-                       {0x05, 0x01, {0x22}, 1}, /* 5/6 also seen as 65h/32h */
-                       {0x06, 0x01, {0x00}, 1},
-                       {0x09, 0x02, {0x0e}, 1},
-                       {0x0a, 0x02, {0x05}, 1},
-                       {0x0b, 0x02, {0x05}, 1},
-                       {0x0c, 0x02, {0x0f}, 1},
-                       {0x0d, 0x02, {0x07}, 1},
-                       {0x0e, 0x02, {0x0c}, 1},
-                       {0x0f, 0x00, {0x00}, 1},
-                       {0x10, 0x00, {0x06}, 1},
-                       {0x11, 0x00, {0x07}, 1},
-                       {0x12, 0x00, {0x00}, 1},
-                       {0x13, 0x00, {0x01}, 1},
-                       {0, 0, {0}, 0}
-               };
-               /* Without this command the cam won't work with USB-UHCI */
-               gspca_dev->usb_buf[0] = 0x0a;
-               gspca_dev->usb_buf[1] = 0x00;
-               err_code = mr_write(gspca_dev, 2);
-               if (err_code < 0)
-                       return err_code;
-               err_code = sensor_write_regs(gspca_dev, cif_sensor1_init_data,
-                                        ARRAY_SIZE(cif_sensor1_init_data));
-       }
-       return err_code;
-}
-
-static int start_vga_cam(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       __u8 *data = gspca_dev->usb_buf;
-       int err_code;
-       static const __u8 startup_string[] =
-               {0x00, 0x0d, 0x01, 0x00, 0x00, 0x2b, 0x00, 0x00,
-                0x00, 0x50, 0xc0};
-       /* What some of these mean is explained in start_cif_cam(), above */
-
-       memcpy(data, startup_string, 11);
-       if (!sd->sensor_type) {
-               data[5]  = 0x00;
-               data[10] = 0x91;
-       }
-       if (sd->sensor_type == 2) {
-               data[5]  = 0x00;
-               data[10] = 0x18;
-       }
-
-       switch (gspca_dev->width) {
-       case 160:
-               data[9] |= 0x0c;  /* reg 8, 4:1 scale down */
-               /* fall thru */
-       case 320:
-               data[9] |= 0x04;  /* reg 8, 2:1 scale down */
-               /* fall thru */
-       case 640:
-       default:
-               data[3] = 0x50;  /* reg 2, H size/8 */
-               data[4] = 0x78;  /* reg 3, V size/4 */
-               data[6] = 0x04;  /* reg 5, H start */
-               data[8] = 0x03;  /* reg 7, V start */
-               if (sd->sensor_type == 2) {
-                       data[6] = 2;
-                       data[8] = 1;
-               }
-               if (sd->do_lcd_stop)
-                       data[8] = 0x04;  /* Bayer tile shifted */
-               break;
-
-       case 176:
-               data[9] |= 0x04;  /* reg 8, 2:1 scale down */
-               /* fall thru */
-       case 352:
-               data[3] = 0x2c;  /* reg 2, H size */
-               data[4] = 0x48;  /* reg 3, V size */
-               data[6] = 0x94;  /* reg 5, H start */
-               data[8] = 0x63;  /* reg 7, V start */
-               if (sd->do_lcd_stop)
-                       data[8] = 0x64;  /* Bayer tile shifted */
-               break;
-       }
-
-       err_code = mr_write(gspca_dev, 11);
-       if (err_code < 0)
-               return err_code;
-
-       if (!sd->sensor_type) {
-               static const struct sensor_w_data vga_sensor0_init_data[] = {
-                       {0x01, 0x00, {0x0c, 0x00, 0x04}, 3},
-                       {0x14, 0x00, {0x01, 0xe4, 0x02, 0x84}, 4},
-                       {0x20, 0x00, {0x00, 0x80, 0x00, 0x08}, 4},
-                       {0x25, 0x00, {0x03, 0xa9, 0x80}, 3},
-                       {0x30, 0x00, {0x30, 0x18, 0x10, 0x18}, 4},
-                       {0, 0, {0}, 0}
-               };
-               err_code = sensor_write_regs(gspca_dev, vga_sensor0_init_data,
-                                        ARRAY_SIZE(vga_sensor0_init_data));
-       } else if (sd->sensor_type == 1) {
-               static const struct sensor_w_data color_adj[] = {
-                       {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
-                               /* adjusted blue, green, red gain correct
-                                  too much blue from the Sakar Digital */
-                               0x05, 0x01, 0x04}, 8}
-               };
-
-               static const struct sensor_w_data color_no_adj[] = {
-                       {0x02, 0x00, {0x06, 0x59, 0x0c, 0x16, 0x00,
-                               /* default blue, green, red gain settings */
-                               0x07, 0x00, 0x01}, 8}
-               };
-
-               static const struct sensor_w_data vga_sensor1_init_data[] = {
-                       {0x11, 0x04, {0x01}, 1},
-                       {0x0a, 0x00, {0x00, 0x01, 0x00, 0x00, 0x01,
-                       /* These settings may be better for some cameras */
-                       /* {0x0a, 0x00, {0x01, 0x06, 0x00, 0x00, 0x01, */
-                               0x00, 0x0a}, 7},
-                       {0x11, 0x04, {0x01}, 1},
-                       {0x12, 0x00, {0x00, 0x63, 0x00, 0x70, 0x00, 0x00}, 6},
-                       {0x11, 0x04, {0x01}, 1},
-                       {0, 0, {0}, 0}
-               };
-
-               if (sd->adj_colors)
-                       err_code = sensor_write_regs(gspca_dev, color_adj,
-                                        ARRAY_SIZE(color_adj));
-               else
-                       err_code = sensor_write_regs(gspca_dev, color_no_adj,
-                                        ARRAY_SIZE(color_no_adj));
-
-               if (err_code < 0)
-                       return err_code;
-
-               err_code = sensor_write_regs(gspca_dev, vga_sensor1_init_data,
-                                        ARRAY_SIZE(vga_sensor1_init_data));
-       } else {        /* sensor type == 2 */
-               static const struct sensor_w_data vga_sensor2_init_data[] = {
-
-                       {0x01, 0x00, {0x48}, 1},
-                       {0x02, 0x00, {0x22}, 1},
-                       /* Reg 3 msb and 4 is lsb of the exposure setting*/
-                       {0x05, 0x00, {0x10}, 1},
-                       {0x06, 0x00, {0x00}, 1},
-                       {0x07, 0x00, {0x00}, 1},
-                       {0x08, 0x00, {0x00}, 1},
-                       {0x09, 0x00, {0x00}, 1},
-                       /* The following are used in the gain control
-                        * which is BTW completely borked in the OEM driver
-                        * The values for each color go from 0 to 0x7ff
-                        *{0x0a, 0x00, {0x01}, 1},  green1 gain msb
-                        *{0x0b, 0x00, {0x10}, 1},  green1 gain lsb
-                        *{0x0c, 0x00, {0x01}, 1},  red gain msb
-                        *{0x0d, 0x00, {0x10}, 1},  red gain lsb
-                        *{0x0e, 0x00, {0x01}, 1},  blue gain msb
-                        *{0x0f, 0x00, {0x10}, 1},  blue gain lsb
-                        *{0x10, 0x00, {0x01}, 1}, green2 gain msb
-                        *{0x11, 0x00, {0x10}, 1}, green2 gain lsb
-                        */
-                       {0x12, 0x00, {0x00}, 1},
-                       {0x13, 0x00, {0x04}, 1}, /* weird effect on colors */
-                       {0x14, 0x00, {0x00}, 1},
-                       {0x15, 0x00, {0x06}, 1},
-                       {0x16, 0x00, {0x01}, 1},
-                       {0x17, 0x00, {0xe2}, 1}, /* vertical alignment */
-                       {0x18, 0x00, {0x02}, 1},
-                       {0x19, 0x00, {0x82}, 1}, /* don't mess with */
-                       {0x1a, 0x00, {0x00}, 1},
-                       {0x1b, 0x00, {0x20}, 1},
-                       /* {0x1c, 0x00, {0x17}, 1}, contrast control */
-                       {0x1d, 0x00, {0x80}, 1}, /* moving causes a mess */
-                       {0x1e, 0x00, {0x08}, 1}, /* moving jams the camera */
-                       {0x1f, 0x00, {0x0c}, 1},
-                       {0x20, 0x00, {0x00}, 1},
-                       {0, 0, {0}, 0}
-               };
-               err_code = sensor_write_regs(gspca_dev, vga_sensor2_init_data,
-                                        ARRAY_SIZE(vga_sensor2_init_data));
-       }
-       return err_code;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int err_code;
-
-       sd->sof_read = 0;
-
-       /* Some of the VGA cameras require the memory pointer
-        * to be set to 0 again. We have been forced to start the
-        * stream in sd_config() to detect the hardware, and closed it.
-        * Thus, we need here to do a completely fresh and clean start. */
-       err_code = zero_the_pointer(gspca_dev);
-       if (err_code < 0)
-               return err_code;
-
-       err_code = stream_start(gspca_dev);
-       if (err_code < 0)
-               return err_code;
-
-       if (sd->cam_type == CAM_TYPE_CIF) {
-               err_code = start_cif_cam(gspca_dev);
-       } else {
-               err_code = start_vga_cam(gspca_dev);
-       }
-       if (err_code < 0)
-               return err_code;
-
-       return isoc_enable(gspca_dev);
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       stream_stop(gspca_dev);
-       /* Not all the cams need this, but even if not, probably a good idea */
-       zero_the_pointer(gspca_dev);
-       if (sd->do_lcd_stop)
-               lcd_stop(gspca_dev);
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 sign_reg = 7;  /* This reg and the next one used on CIF cams. */
-       u8 value_reg = 8; /* VGA cams seem to use regs 0x0b and 0x0c */
-       static const u8 quick_clix_table[] =
-       /*        0  1  2   3  4  5  6  7  8  9  10  11  12  13  14  15 */
-               { 0, 4, 8, 12, 1, 2, 3, 5, 6, 9,  7, 10, 13, 11, 14, 15};
-       if (sd->cam_type == CAM_TYPE_VGA) {
-               sign_reg += 4;
-               value_reg += 4;
-       }
-
-       /* Note register 7 is also seen as 0x8x or 0xCx in some dumps */
-       if (val > 0) {
-               sensor_write1(gspca_dev, sign_reg, 0x00);
-       } else {
-               sensor_write1(gspca_dev, sign_reg, 0x01);
-               val = 257 - val;
-       }
-       /* Use lookup table for funky Argus QuickClix brightness */
-       if (sd->do_lcd_stop)
-               val = quick_clix_table[val];
-
-       sensor_write1(gspca_dev, value_reg, val);
-}
-
-static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 min_clockdiv)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int exposure = MR97310A_EXPOSURE_DEFAULT;
-       u8 buf[2];
-
-       if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1) {
-               /* This cam does not like exposure settings < 300,
-                  so scale 0 - 4095 to 300 - 4095 */
-               exposure = (expo * 9267) / 10000 + 300;
-               sensor_write1(gspca_dev, 3, exposure >> 4);
-               sensor_write1(gspca_dev, 4, exposure & 0x0f);
-       } else if (sd->sensor_type == 2) {
-               exposure = expo;
-               exposure >>= 3;
-               sensor_write1(gspca_dev, 3, exposure >> 8);
-               sensor_write1(gspca_dev, 4, exposure & 0xff);
-       } else {
-               /* We have both a clock divider and an exposure register.
-                  We first calculate the clock divider, as that determines
-                  the maximum exposure and then we calculate the exposure
-                  register setting (which goes from 0 - 511).
-
-                  Note our 0 - 4095 exposure is mapped to 0 - 511
-                  milliseconds exposure time */
-               u8 clockdiv = (60 * expo + 7999) / 8000;
-
-               /* Limit framerate to not exceed usb bandwidth */
-               if (clockdiv < min_clockdiv && gspca_dev->width >= 320)
-                       clockdiv = min_clockdiv;
-               else if (clockdiv < 2)
-                       clockdiv = 2;
-
-               if (sd->cam_type == CAM_TYPE_VGA && clockdiv < 4)
-                       clockdiv = 4;
-
-               /* Frame exposure time in ms = 1000 * clockdiv / 60 ->
-               exposure = (sd->exposure / 8) * 511 / (1000 * clockdiv / 60) */
-               exposure = (60 * 511 * expo) / (8000 * clockdiv);
-               if (exposure > 511)
-                       exposure = 511;
-
-               /* exposure register value is reversed! */
-               exposure = 511 - exposure;
-
-               buf[0] = exposure & 0xff;
-               buf[1] = exposure >> 8;
-               sensor_write_reg(gspca_dev, 0x0e, 0, buf, 2);
-               sensor_write1(gspca_dev, 0x02, clockdiv);
-       }
-}
-
-static void setgain(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 gainreg;
-
-       if (sd->cam_type == CAM_TYPE_CIF && sd->sensor_type == 1)
-               sensor_write1(gspca_dev, 0x0e, val);
-       else if (sd->cam_type == CAM_TYPE_VGA && sd->sensor_type == 2)
-               for (gainreg = 0x0a; gainreg < 0x11; gainreg += 2) {
-                       sensor_write1(gspca_dev, gainreg, val >> 8);
-                       sensor_write1(gspca_dev, gainreg + 1, val & 0xff);
-               }
-       else
-               sensor_write1(gspca_dev, 0x10, val);
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
-{
-       sensor_write1(gspca_dev, 0x1c, val);
-}
-
-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_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_EXPOSURE:
-               setexposure(gspca_dev, sd->exposure->val,
-                           sd->min_clockdiv ? sd->min_clockdiv->val : 0);
-               break;
-       case V4L2_CID_GAIN:
-               setgain(gspca_dev, ctrl->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;
-       static const struct v4l2_ctrl_config clockdiv = {
-               .ops = &sd_ctrl_ops,
-               .id = MR97310A_CID_CLOCKDIV,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Minimum Clock Divider",
-               .min = MR97310A_MIN_CLOCKDIV_MIN,
-               .max = MR97310A_MIN_CLOCKDIV_MAX,
-               .step = 1,
-               .def = MR97310A_MIN_CLOCKDIV_DEFAULT,
-       };
-       bool has_brightness = false;
-       bool has_argus_brightness = false;
-       bool has_contrast = false;
-       bool has_gain = false;
-       bool has_cs_gain = false;
-       bool has_exposure = false;
-       bool has_clockdiv = false;
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 4);
-
-       /* Setup controls depending on camera type */
-       if (sd->cam_type == CAM_TYPE_CIF) {
-               /* No brightness for sensor_type 0 */
-               if (sd->sensor_type == 0)
-                       has_exposure = has_gain = has_clockdiv = true;
-               else
-                       has_exposure = has_gain = has_brightness = true;
-       } else {
-               /* All controls need to be disabled if VGA sensor_type is 0 */
-               if (sd->sensor_type == 0)
-                       ; /* no controls! */
-               else if (sd->sensor_type == 2)
-                       has_exposure = has_cs_gain = has_contrast = true;
-               else if (sd->do_lcd_stop)
-                       has_exposure = has_gain = has_argus_brightness =
-                               has_clockdiv = true;
-               else
-                       has_exposure = has_gain = has_brightness =
-                               has_clockdiv = true;
-       }
-
-       /* Separate brightness control description for Argus QuickClix as it has
-        * different limits from the other mr97310a cameras, and separate gain
-        * control for Sakar CyberPix camera. */
-       /*
-        * This control is disabled for CIF type 1 and VGA type 0 cameras.
-        * It does not quite act linearly for the Argus QuickClix camera,
-        * but it does control brightness. The values are 0 - 15 only, and
-        * the table above makes them act consecutively.
-        */
-       if (has_brightness)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, -254, 255, 1,
-                       MR97310A_BRIGHTNESS_DEFAULT);
-       else if (has_argus_brightness)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 15, 1,
-                       MR97310A_BRIGHTNESS_DEFAULT);
-       if (has_contrast)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, MR97310A_CONTRAST_MIN,
-                       MR97310A_CONTRAST_MAX, 1, MR97310A_CONTRAST_DEFAULT);
-       if (has_gain)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAIN, MR97310A_GAIN_MIN, MR97310A_GAIN_MAX,
-                       1, MR97310A_GAIN_DEFAULT);
-       else if (has_cs_gain)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAIN,
-                       MR97310A_CS_GAIN_MIN, MR97310A_CS_GAIN_MAX,
-                       1, MR97310A_CS_GAIN_DEFAULT);
-       if (has_exposure)
-               sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_EXPOSURE, MR97310A_EXPOSURE_MIN,
-                       MR97310A_EXPOSURE_MAX, 1, MR97310A_EXPOSURE_DEFAULT);
-       if (has_clockdiv)
-               sd->min_clockdiv = v4l2_ctrl_new_custom(hdl, &clockdiv, NULL);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-       if (has_exposure && has_clockdiv)
-               v4l2_ctrl_cluster(2, &sd->exposure);
-       return 0;
-}
-
-/* Include pac common sof detection functions */
-#include "pac_common.h"
-
-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;
-       unsigned char *sof;
-
-       sof = pac_find_sof(&sd->sof_read, data, len);
-       if (sof) {
-               int n;
-
-               /* finish decoding current frame */
-               n = sof - data;
-               if (n > sizeof pac_sof_marker)
-                       n -= sizeof pac_sof_marker;
-               else
-                       n = 0;
-               gspca_frame_add(gspca_dev, LAST_PACKET,
-                                       data, n);
-               /* Start next frame. */
-               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                       pac_sof_marker, sizeof pac_sof_marker);
-               len -= sof - data;
-               data = sof;
-       }
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-/* 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,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x08ca, 0x0110)},   /* Trust Spyc@m 100 */
-       {USB_DEVICE(0x08ca, 0x0111)},   /* Aiptek Pencam VGA+ */
-       {USB_DEVICE(0x093a, 0x010f)},   /* All other known MR97310A VGA cams */
-       {USB_DEVICE(0x093a, 0x010e)},   /* All known MR97310A CIF cams */
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/nw80x.c b/drivers/media/video/gspca/nw80x.c
deleted file mode 100644 (file)
index 44c9964..0000000
+++ /dev/null
@@ -1,2110 +0,0 @@
-/*
- * DivIO nw80x subdriver
- *
- * Copyright (C) 2011 Jean-François Moine (http://moinejf.free.fr)
- * Copyright (C) 2003 Sylvain Munaut <tnt@246tNt.com>
- *                     Kjell Claesson <keyson@users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "nw80x"
-
-#include "gspca.h"
-
-MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
-MODULE_DESCRIPTION("NW80x USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-static int webcam;
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       u32 ae_res;
-       s8 ag_cnt;
-#define AG_CNT_START 13
-       u8 exp_too_low_cnt;
-       u8 exp_too_high_cnt;
-
-       u8 bridge;
-       u8 webcam;
-};
-
-enum bridges {
-       BRIDGE_NW800,   /* and et31x110 */
-       BRIDGE_NW801,
-       BRIDGE_NW802,
-};
-enum webcams {
-       Generic800,
-       SpaceCam,       /* Trust 120 SpaceCam */
-       SpaceCam2,      /* other Trust 120 SpaceCam */
-       Cvideopro,      /* Conceptronic Video Pro */
-       Dlink350c,
-       DS3303u,
-       Kr651us,
-       Kritter,
-       Mustek300,
-       Proscope,
-       Twinkle,
-       DvcV6,
-       P35u,
-       Generic802,
-       NWEBCAMS        /* number of webcams */
-};
-
-static const u8 webcam_chip[NWEBCAMS] = {
-       [Generic800]    = BRIDGE_NW800, /* 06a5:0000
-                                        * Typhoon Webcam 100 USB */
-
-       [SpaceCam]      = BRIDGE_NW800, /* 06a5:d800
-                               * Trust SpaceCam120 or SpaceCam100 PORTABLE */
-
-       [SpaceCam2]     = BRIDGE_NW800, /* 06a5:d800 - pas106
-                       * other Trust SpaceCam120 or SpaceCam100 PORTABLE */
-
-       [Cvideopro]     = BRIDGE_NW802, /* 06a5:d001
-                       * Conceptronic Video Pro 'CVIDEOPRO USB Webcam CCD' */
-
-       [Dlink350c]     = BRIDGE_NW802, /* 06a5:d001
-                                        * D-Link NetQam Pro 250plus */
-
-       [DS3303u]       = BRIDGE_NW801, /* 06a5:d001
-                               * Plustek Opticam 500U or ProLink DS3303u */
-
-       [Kr651us]       = BRIDGE_NW802, /* 06a5:d001
-                                        * Panasonic GP-KR651US */
-
-       [Kritter]       = BRIDGE_NW802, /* 06a5:d001
-                                        * iRez Kritter cam */
-
-       [Mustek300]     = BRIDGE_NW802, /* 055f:d001
-                                        * Mustek Wcam 300 mini */
-
-       [Proscope]      = BRIDGE_NW802, /* 06a5:d001
-                                        * Scalar USB Microscope (ProScope) */
-
-       [Twinkle]       = BRIDGE_NW800, /* 06a5:d800 - hv7121b? (seems pas106)
-                                        * Divio Chicony TwinkleCam
-                                        * DSB-C110 */
-
-       [DvcV6]         = BRIDGE_NW802, /* 0502:d001
-                                        * DVC V6 */
-
-       [P35u]          = BRIDGE_NW801, /* 052b:d001, 06a5:d001 and 06be:d001
-                                        * EZCam Pro p35u */
-
-       [Generic802]    = BRIDGE_NW802,
-};
-/*
- * other webcams:
- *     - nw801 046d:d001
- *             Logitech QuickCam Pro (dark focus ring)
- *     - nw801 0728:d001
- *             AVerMedia Camguard
- *     - nw??? 06a5:d001
- *             D-Link NetQam Pro 250plus
- *     - nw800 065a:d800
- *             Showcam NGS webcam
- *     - nw??? ????:????
- *             Sceptre svc300
- */
-
-/*
- * registers
- *    nw800/et31x110     nw801           nw802
- *     0000..009e      0000..00a1      0000..009e
- *     0200..0211         id              id
- *     0300..0302         id              id
- *     0400..0406        (inex)        0400..0406
- *     0500..0505      0500..0506        (inex)
- *     0600..061a      0600..0601      0600..0601
- *     0800..0814         id              id
- *     1000..109c      1000..10a1      1000..109a
- */
-
-/* resolutions
- *     nw800: 320x240, 352x288
- *     nw801/802: 320x240, 640x480
- */
-static const struct v4l2_pix_format cif_mode[] = {
-       {320, 240, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 4 / 8,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-       {352, 288, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 4 / 8,
-               .colorspace = V4L2_COLORSPACE_JPEG}
-};
-static const struct v4l2_pix_format vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 4 / 8,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-       {640, 480, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-};
-
-/*
- * The sequences below contain:
- *     - 1st and 2nd bytes: either
- *             - register number (BE)
- *             - I2C0 + i2c address
- *     - 3rd byte: data length (=0 for end of sequence)
- *     - n bytes: data
- */
-#define I2C0 0xff
-
-static const u8 nw800_init[] = {
-       0x04, 0x05, 0x01, 0x61,
-       0x04, 0x04, 0x01, 0x01,
-       0x04, 0x06, 0x01, 0x04,
-       0x04, 0x04, 0x03, 0x00, 0x00, 0x00,
-       0x05, 0x05, 0x01, 0x00,
-       0, 0, 0
-};
-static const u8 nw800_start[] = {
-       0x04, 0x06, 0x01, 0xc0,
-       0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
-                         0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
-                         0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
-                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
-                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
-                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
-       0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
-                         0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
-                         0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
-       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
-       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0xc0,
-       0x05, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x20,
-       0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
-                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
-                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
-                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
-                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
-       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
-                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
-                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
-                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
-       0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
-                         0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
-                         0x01, 0x60, 0x01, 0x00, 0x00,
-
-       0x04, 0x04, 0x01, 0xff,
-       0x04, 0x06, 0x01, 0xc4,
-
-       0x04, 0x06, 0x01, 0xc0,
-       0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
-                         0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
-                         0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
-                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
-                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
-                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
-       0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
-                         0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
-                         0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
-       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
-       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0xc0,
-       0x05, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x20,
-       0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
-                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
-                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
-                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
-                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
-       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
-                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
-                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
-                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
-       0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
-                         0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
-                         0x01, 0x60, 0x01, 0x00, 0x00,
-
-       0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
-                         0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
-                         0x40,
-       0x00, 0x80, 0x01, 0xa0,
-       0x10, 0x1a, 0x01, 0x00,
-       0x00, 0x91, 0x02, 0x6c, 0x01,
-       0x00, 0x03, 0x02, 0xc8, 0x01,
-       0x10, 0x1a, 0x01, 0x00,
-       0x10, 0x00, 0x01, 0x83,
-       0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
-                         0x20, 0x01, 0x60, 0x01,
-       0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
-       0x10, 0x1b, 0x02, 0x69, 0x00,
-       0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
-       0x05, 0x02, 0x01, 0x02,
-       0x06, 0x00, 0x02, 0x04, 0xd9,
-       0x05, 0x05, 0x01, 0x20,
-       0x05, 0x05, 0x01, 0x21,
-       0x10, 0x0e, 0x01, 0x08,
-       0x10, 0x41, 0x11, 0x00, 0x08, 0x21, 0x3d, 0x52, 0x63, 0x75, 0x83,
-                         0x91, 0x9e, 0xaa, 0xb6, 0xc1, 0xcc, 0xd6, 0xe0,
-                         0xea,
-       0x10, 0x03, 0x01, 0x00,
-       0x10, 0x0f, 0x02, 0x13, 0x13,
-       0x10, 0x03, 0x01, 0x14,
-       0x10, 0x41, 0x11, 0x00, 0x08, 0x21, 0x3d, 0x52, 0x63, 0x75, 0x83,
-                         0x91, 0x9e, 0xaa, 0xb6, 0xc1, 0xcc, 0xd6, 0xe0,
-                         0xea,
-       0x10, 0x0b, 0x01, 0x14,
-       0x10, 0x0d, 0x01, 0x20,
-       0x10, 0x0c, 0x01, 0x34,
-       0x04, 0x06, 0x01, 0xc3,
-       0x04, 0x04, 0x01, 0x00,
-       0x05, 0x02, 0x01, 0x02,
-       0x06, 0x00, 0x02, 0x00, 0x48,
-       0x05, 0x05, 0x01, 0x20,
-       0x05, 0x05, 0x01, 0x21,
-       0, 0, 0
-};
-
-/* 06a5:d001 - nw801 - Panasonic
- *             P35u */
-static const u8 nw801_start_1[] = {
-       0x05, 0x06, 0x01, 0x04,
-       0x00, 0x00, 0x40, 0x0e, 0x00, 0x00, 0xf9, 0x02, 0x11, 0x00, 0x0e,
-                         0x01, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
-                         0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
-                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
-                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
-                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
-       0x00, 0x80, 0x22, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x08, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x69, 0xa8, 0x1f, 0x00,
-                         0x0d, 0x02, 0x07, 0x00, 0x01, 0x00, 0x19, 0x00,
-                         0xf2, 0x00, 0x18, 0x06, 0x10, 0x06, 0x10, 0x00,
-                         0x36, 0x00,
-       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
-       0x05, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x06, 0x00, 0x02, 0x09, 0x99,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0x22, 0x02, 0x80, 0x00, 0x1e, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x0a, 0x15, 0x08, 0x08, 0x0a,
-                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x01, 0x35, 0xfd, 0x07, 0x3d, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x14, 0x02,
-                         0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
-                         0x40, 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x06,
-                         0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, 0xf7,
-       0x10, 0x40, 0x40, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, 0x80,
-                         0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, 0xa4,
-                         0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, 0xcf,
-                         0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64,
-                         0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2,
-                         0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-       0x10, 0x80, 0x22, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x82, 0x02,
-                         0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, 0x01,
-                         0xf0, 0x00,
-       0, 0, 0,
-};
-static const u8 nw801_start_qvga[] = {
-       0x02, 0x00, 0x10, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
-                         0x00, 0x78, 0x18, 0x0b, 0x06, 0xa2, 0x86, 0x78,
-       0x02, 0x0f, 0x01, 0x6b,
-       0x10, 0x1a, 0x01, 0x15,
-       0x00, 0x00, 0x01, 0x1e,
-       0x10, 0x00, 0x01, 0x2f,
-       0x10, 0x8c, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
-       0x10, 0x11, 0x08, 0x29, 0x00, 0x18, 0x01, 0x1f, 0x00, 0xd2, 0x00,
-                                                       /* AE window */
-       0, 0, 0,
-};
-static const u8 nw801_start_vga[] = {
-       0x02, 0x00, 0x10, 0x78, 0xa0, 0x97, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xf0,
-       0x02, 0x0f, 0x01, 0xd5,
-       0x10, 0x1a, 0x01, 0x15,
-       0x00, 0x00, 0x01, 0x0e,
-       0x10, 0x00, 0x01, 0x22,
-       0x10, 0x8c, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
-       0x10, 0x11, 0x08, 0x51, 0x00, 0x30, 0x02, 0x3d, 0x00, 0xa4, 0x01,
-       0, 0, 0,
-};
-static const u8 nw801_start_2[] = {
-       0x10, 0x04, 0x01, 0x1a,
-       0x10, 0x19, 0x01, 0x09,                         /* clock */
-       0x10, 0x24, 0x06, 0xc0, 0x00, 0x3f, 0x02, 0x00, 0x01,
-                                                        /* .. gain .. */
-       0x00, 0x03, 0x02, 0x92, 0x03,
-       0x00, 0x1d, 0x04, 0xf2, 0x00, 0x24, 0x07,
-       0x00, 0x7b, 0x01, 0xcf,
-       0x10, 0x94, 0x01, 0x07,
-       0x05, 0x05, 0x01, 0x01,
-       0x05, 0x04, 0x01, 0x01,
-       0x10, 0x0e, 0x01, 0x08,
-       0x10, 0x48, 0x11, 0x00, 0x37, 0x55, 0x6b, 0x7d, 0x8d, 0x9b, 0xa8,
-                         0xb4, 0xbf, 0xca, 0xd4, 0xdd, 0xe6, 0xef, 0xf0,
-                         0xf0,
-       0x10, 0x03, 0x01, 0x00,
-       0x10, 0x0f, 0x02, 0x0c, 0x0c,
-       0x10, 0x03, 0x01, 0x08,
-       0x10, 0x48, 0x11, 0x00, 0x37, 0x55, 0x6b, 0x7d, 0x8d, 0x9b, 0xa8,
-                         0xb4, 0xbf, 0xca, 0xd4, 0xdd, 0xe6, 0xef, 0xf0,
-                         0xf0,
-       0x10, 0x0b, 0x01, 0x0b,
-       0x10, 0x0d, 0x01, 0x0b,
-       0x10, 0x0c, 0x01, 0x1f,
-       0x05, 0x06, 0x01, 0x03,
-       0, 0, 0
-};
-
-/* nw802 (sharp IR3Y38M?) */
-static const u8 nw802_start[] = {
-       0x04, 0x06, 0x01, 0x04,
-       0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0xf9, 0x02, 0x10, 0x00, 0x4d,
-                         0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
-                         0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
-                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
-                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
-                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
-       0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
-                         0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
-                         0x00, 0x10, 0x06, 0x08, 0x00, 0x18, 0x00,
-       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
-       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
-       0x06, 0x00, 0x02, 0x09, 0x99,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x1d, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
-                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x49, 0x13, 0xff, 0x01, 0xc0, 0x00, 0x14,
-                         0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
-                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
-                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
-                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
-       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
-                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
-                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
-                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
-       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x05, 0x82,
-                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
-                         0x01, 0xf0, 0x00,
-       0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
-                         0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
-                         0x40,
-       0x10, 0x1a, 0x01, 0x00,
-       0x10, 0x00, 0x01, 0xad,
-       0x00, 0x00, 0x01, 0x08,
-       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
-       0x10, 0x1b, 0x02, 0x00, 0x00,
-       0x10, 0x11, 0x08, 0x51, 0x00, 0xf0, 0x00, 0x3d, 0x00, 0xb4, 0x00,
-       0x10, 0x1d, 0x08, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
-       0x10, 0x0e, 0x01, 0x27,
-       0x10, 0x41, 0x11, 0x00, 0x0e, 0x35, 0x4f, 0x62, 0x71, 0x7f, 0x8b,
-                         0x96, 0xa0, 0xa9, 0xb2, 0xbb, 0xc3, 0xca, 0xd2,
-                         0xd8,
-       0x10, 0x03, 0x01, 0x00,
-       0x10, 0x0f, 0x02, 0x14, 0x14,
-       0x10, 0x03, 0x01, 0x0c,
-       0x10, 0x41, 0x11, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64, 0x74,
-                         0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2, 0xf1,
-                         0xff,
-/*                       0x00, 0x0e, 0x35, 0x4f, 0x62, 0x71, 0x7f, 0x8b,
- *                       0x96, 0xa0, 0xa9, 0xb2, 0xbb, 0xc3, 0xca, 0xd2,
- *                       0xd8, */
-       0x10, 0x0b, 0x01, 0x10,
-       0x10, 0x0d, 0x01, 0x11,
-       0x10, 0x0c, 0x01, 0x1c,
-       0x04, 0x06, 0x01, 0x03,
-       0x04, 0x04, 0x01, 0x00,
-       0, 0, 0
-};
-/* et31x110 - Trust 120 SpaceCam */
-static const u8 spacecam_init[] = {
-       0x04, 0x05, 0x01, 0x01,
-       0x04, 0x04, 0x01, 0x01,
-       0x04, 0x06, 0x01, 0x04,
-       0x04, 0x04, 0x03, 0x00, 0x00, 0x00,
-       0x05, 0x05, 0x01, 0x00,
-       0, 0, 0
-};
-static const u8 spacecam_start[] = {
-       0x04, 0x06, 0x01, 0x44,
-       0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
-                         0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
-                         0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
-                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
-                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
-                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
-       0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
-                         0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
-                         0x00, 0x4b, 0x00, 0x7c, 0x00, 0x80, 0x00,
-       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
-       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
-                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
-                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
-                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
-                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
-       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
-                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
-                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
-                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
-       0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
-                         0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
-                         0x01, 0x60, 0x01, 0x00, 0x00,
-       0x04, 0x06, 0x01, 0xc0,
-       0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
-       0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
-                         0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
-                         0x40,
-       0x00, 0x80, 0x01, 0xa0,
-       0x10, 0x1a, 0x01, 0x00,
-       0x00, 0x91, 0x02, 0x32, 0x01,
-       0x00, 0x03, 0x02, 0x08, 0x02,
-       0x10, 0x00, 0x01, 0x83,
-       0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
-                         0x20, 0x01, 0x60, 0x01,
-       0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
-       0x10, 0x0e, 0x01, 0x08,
-       0x10, 0x41, 0x11, 0x00, 0x64, 0x99, 0xc0, 0xe2, 0xf9, 0xf9, 0xf9,
-                         0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
-                         0xf9,
-       0x10, 0x03, 0x01, 0x00,
-       0x10, 0x0f, 0x02, 0x13, 0x13,
-       0x10, 0x03, 0x01, 0x06,
-       0x10, 0x41, 0x11, 0x00, 0x64, 0x99, 0xc0, 0xe2, 0xf9, 0xf9, 0xf9,
-                         0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
-                         0xf9,
-       0x10, 0x0b, 0x01, 0x08,
-       0x10, 0x0d, 0x01, 0x10,
-       0x10, 0x0c, 0x01, 0x1f,
-       0x04, 0x06, 0x01, 0xc3,
-       0x04, 0x05, 0x01, 0x40,
-       0x04, 0x04, 0x01, 0x40,
-       0, 0, 0
-};
-/* et31x110 - pas106 - other Trust SpaceCam120 */
-static const u8 spacecam2_start[] = {
-       0x04, 0x06, 0x01, 0x44,
-       0x04, 0x06, 0x01, 0x00,
-       0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f,
-                         0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc,
-                         0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
-                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
-                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
-                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
-       0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03,
-                         0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
-                         0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
-       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
-       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00,
-       0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
-                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
-                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
-                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
-                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
-       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
-                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
-                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
-                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
-       0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62,
-                         0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
-                         0x01, 0x60, 0x01, 0x00, 0x00,
-       0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
-       0x04, 0x04, 0x01, 0x40,
-       0x04, 0x04, 0x01, 0x00,
-       I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x05,
-                         0x00, 0x00, 0x05, 0x05,
-       I2C0, 0x40, 0x02, 0x11, 0x06,
-       I2C0, 0x40, 0x02, 0x14, 0x00,
-       I2C0, 0x40, 0x02, 0x13, 0x01,           /* i2c end */
-       0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
-                         0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
-                         0x40,
-       I2C0, 0x40, 0x02, 0x02, 0x0c,           /* pixel clock */
-       I2C0, 0x40, 0x02, 0x0f, 0x00,
-       I2C0, 0x40, 0x02, 0x13, 0x01,           /* i2c end */
-       0x10, 0x00, 0x01, 0x01,
-       0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
-                         0x20, 0x01, 0x60, 0x01,
-       I2C0, 0x40, 0x02, 0x05, 0x0f,           /* exposure */
-       I2C0, 0x40, 0x02, 0x13, 0x01,           /* i2c end */
-       I2C0, 0x40, 0x07, 0x09, 0x0b, 0x0f, 0x05, 0x05, 0x0f, 0x00,
-                                               /* gains */
-       I2C0, 0x40, 0x03, 0x12, 0x04, 0x01,
-       0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
-       0x10, 0x0e, 0x01, 0x08,
-       0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
-                         0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
-                         0xf9,
-       0x10, 0x03, 0x01, 0x00,
-       0x10, 0x0f, 0x02, 0x13, 0x13,
-       0x10, 0x03, 0x01, 0x06,
-       0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
-                         0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
-                         0xf9,
-       0x10, 0x0b, 0x01, 0x11,
-       0x10, 0x0d, 0x01, 0x10,
-       0x10, 0x0c, 0x01, 0x14,
-       0x04, 0x06, 0x01, 0x03,
-       0x04, 0x05, 0x01, 0x61,
-       0x04, 0x04, 0x01, 0x00,
-       0, 0, 0
-};
-
-/* nw802 - Conceptronic Video Pro */
-static const u8 cvideopro_start[] = {
-       0x04, 0x06, 0x01, 0x04,
-       0x00, 0x00, 0x40, 0x54, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x4c,
-                         0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
-                         0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
-                         0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
-                         0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
-       0x00, 0x80, 0x1f, 0x98, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
-                         0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
-                         0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
-                         0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
-       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
-       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
-       0x06, 0x00, 0x02, 0x09, 0x99,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
-                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
-                         0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
-                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
-                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
-                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
-       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
-                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
-                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
-                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
-       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
-                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
-                         0x01, 0xf0, 0x00,
-       0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00,
-                         0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
-                         0x40,
-       0x10, 0x1a, 0x01, 0x03,
-       0x10, 0x00, 0x01, 0xac,
-       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
-       0x10, 0x1b, 0x02, 0x3b, 0x01,
-       0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
-       0x10, 0x1f, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
-       0x10, 0x1d, 0x02, 0x40, 0x06,
-       0x10, 0x0e, 0x01, 0x08,
-       0x10, 0x41, 0x11, 0x00, 0x0f, 0x46, 0x62, 0x76, 0x86, 0x94, 0xa0,
-                         0xab, 0xb6, 0xbf, 0xc8, 0xcf, 0xd7, 0xdc, 0xdc,
-                         0xdc,
-       0x10, 0x03, 0x01, 0x00,
-       0x10, 0x0f, 0x02, 0x12, 0x12,
-       0x10, 0x03, 0x01, 0x0c,
-       0x10, 0x41, 0x11, 0x00, 0x0f, 0x46, 0x62, 0x76, 0x86, 0x94, 0xa0,
-                         0xab, 0xb6, 0xbf, 0xc8, 0xcf, 0xd7, 0xdc, 0xdc,
-                         0xdc,
-       0x10, 0x0b, 0x01, 0x09,
-       0x10, 0x0d, 0x01, 0x10,
-       0x10, 0x0c, 0x01, 0x2f,
-       0x04, 0x06, 0x01, 0x03,
-       0x04, 0x04, 0x01, 0x00,
-       0, 0, 0
-};
-
-/* nw802 - D-link dru-350c cam */
-static const u8 dlink_start[] = {
-       0x04, 0x06, 0x01, 0x04,
-       0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x92, 0x03, 0x10, 0x00, 0x4d,
-                         0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
-                         0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
-                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
-                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
-                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
-       0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
-                         0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
-                         0x00, 0x10, 0x06, 0x10, 0x00, 0x36, 0x00,
-       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
-       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
-       0x06, 0x00, 0x02, 0x09, 0x99,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
-                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x49, 0x13, 0x00, 0x00, 0xc0, 0x00, 0x14,
-                         0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
-                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
-                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
-                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
-       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
-                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
-                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
-                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
-       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x01, 0x82,
-                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
-                         0x01, 0xf0, 0x00,
-       0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
-                         0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
-                         0x40,
-       0x10, 0x1a, 0x01, 0x00,
-       0x10, 0x00, 0x01, 0xad,
-       0x00, 0x00, 0x01, 0x08,
-       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
-       0x10, 0x1b, 0x02, 0x00, 0x00,
-       0x10, 0x11, 0x08, 0x51, 0x00, 0xf0, 0x00, 0x3d, 0x00, 0xb4, 0x00,
-       0x10, 0x1d, 0x08, 0x40, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
-       0x10, 0x0e, 0x01, 0x20,
-       0x10, 0x41, 0x11, 0x00, 0x07, 0x1e, 0x38, 0x4d, 0x60, 0x70, 0x7f,
-                         0x8e, 0x9b, 0xa8, 0xb4, 0xbf, 0xca, 0xd5, 0xdf,
-                         0xea,
-       0x10, 0x03, 0x01, 0x00,
-       0x10, 0x0f, 0x02, 0x11, 0x11,
-       0x10, 0x03, 0x01, 0x10,
-       0x10, 0x41, 0x11, 0x00, 0x07, 0x1e, 0x38, 0x4d, 0x60, 0x70, 0x7f,
-                         0x8e, 0x9b, 0xa8, 0xb4, 0xbf, 0xca, 0xd5, 0xdf,
-                         0xea,
-       0x10, 0x0b, 0x01, 0x19,
-       0x10, 0x0d, 0x01, 0x10,
-       0x10, 0x0c, 0x01, 0x1e,
-       0x04, 0x06, 0x01, 0x03,
-       0x04, 0x04, 0x01, 0x00,
-       0, 0, 0
-};
-
-/* 06a5:d001 - nw801 - Sony
- *             Plustek Opticam 500U or ProLink DS3303u (Hitachi HD49322BF) */
-/*fixme: 320x240 only*/
-static const u8 ds3303_start[] = {
-       0x05, 0x06, 0x01, 0x04,
-       0x00, 0x00, 0x40, 0x16, 0x00, 0x00, 0xf9, 0x02, 0x11, 0x00, 0x0e,
-                         0x01, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
-                         0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
-                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
-                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
-                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
-       0x00, 0x80, 0x22, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x08, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0xa9, 0xa8, 0x1f, 0x00,
-                         0x0d, 0x02, 0x07, 0x00, 0x01, 0x00, 0x19, 0x00,
-                         0xf2, 0x00, 0x18, 0x06, 0x10, 0x06, 0x10, 0x00,
-                         0x36, 0x00,
-       0x02, 0x00, 0x12, 0x03, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0x50,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
-       0x05, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
-       0x06, 0x00, 0x02, 0x09, 0x99,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0x2f, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x10, 0x1f, 0x10, 0x08, 0x0a,
-                         0x0a, 0x51, 0x00, 0xf1, 0x00, 0x3c, 0x00, 0xb4,
-                         0x00, 0x01, 0x15, 0xfd, 0x07, 0x3d, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x8c, 0x04, 0x01, 0x20,
-                         0x02, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00,
-                         0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x03,
-                         0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, 0xf7,
-       0x10, 0x40, 0x40, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, 0x80,
-                         0x00, 0x2d, 0x46, 0x58, 0x67, 0x74, 0x7f, 0x88,
-                         0x94, 0x9d, 0xa6, 0xae, 0xb5, 0xbd, 0xc4, 0xcb,
-                         0xd1, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64,
-                         0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2,
-                         0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-       0x10, 0x80, 0x22, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x3f, 0x01,
-                         0x00, 0x00, 0xef, 0x00, 0x02, 0x0a, 0x82, 0x02,
-                         0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, 0x01,
-                         0xf0, 0x00,
-
-       0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
-                         0x00, 0x78, 0x3f, 0x3f, 0x00, 0xf2, 0x8f, 0x81,
-                         0x40,
-       0x10, 0x1a, 0x01, 0x15,
-       0x10, 0x00, 0x01, 0x2f,
-       0x10, 0x8c, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
-       0x10, 0x1b, 0x02, 0x00, 0x00,
-       0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
-       0x10, 0x26, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
-       0x10, 0x24, 0x02, 0x40, 0x06,
-       0x10, 0x0e, 0x01, 0x08,
-       0x10, 0x48, 0x11, 0x00, 0x15, 0x40, 0x67, 0x84, 0x9d, 0xb2, 0xc6,
-                         0xd6, 0xe7, 0xf6, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
-                         0xf9,
-       0x10, 0x03, 0x01, 0x00,
-       0x10, 0x0f, 0x02, 0x16, 0x16,
-       0x10, 0x03, 0x01, 0x0c,
-       0x10, 0x48, 0x11, 0x00, 0x15, 0x40, 0x67, 0x84, 0x9d, 0xb2, 0xc6,
-                         0xd6, 0xe7, 0xf6, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
-                         0xf9,
-       0x10, 0x0b, 0x01, 0x26,
-       0x10, 0x0d, 0x01, 0x10,
-       0x10, 0x0c, 0x01, 0x1c,
-       0x05, 0x06, 0x01, 0x03,
-       0x05, 0x04, 0x01, 0x00,
-       0, 0, 0
-};
-
-/* 06a5:d001 - nw802 - Panasonic
- *             GP-KR651US (Philips TDA8786) */
-static const u8 kr651_start_1[] = {
-       0x04, 0x06, 0x01, 0x04,
-       0x00, 0x00, 0x40, 0x44, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x48,
-                         0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
-                         0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
-                         0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
-                         0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
-       0x00, 0x80, 0x1f, 0x18, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
-                         0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
-                         0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
-                         0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
-       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x02, 0x00, 0x00,
-       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
-       0x06, 0x00, 0x02, 0x09, 0x99,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
-                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
-                         0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
-                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
-                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
-                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
-       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
-                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
-                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
-                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
-       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
-                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
-                         0x01, 0xf0, 0x00,
-       0, 0, 0
-};
-static const u8 kr651_start_qvga[] = {
-       0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
-                         0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
-                         0x40,
-       0x10, 0x1a, 0x01, 0x03,
-       0x10, 0x00, 0x01, 0xac,
-       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
-       0x10, 0x1b, 0x02, 0x00, 0x00,
-       0x10, 0x11, 0x08, 0x29, 0x00, 0x18, 0x01, 0x1f, 0x00, 0xd2, 0x00,
-       0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
-       0x10, 0x1d, 0x02, 0x28, 0x01,
-       0, 0, 0
-};
-static const u8 kr651_start_vga[] = {
-       0x02, 0x00, 0x11, 0x78, 0xa0, 0x8c, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x30, 0x03, 0x01, 0x82, 0x82, 0x98,
-                         0x80,
-       0x10, 0x1a, 0x01, 0x03,
-       0x10, 0x00, 0x01, 0xa0,
-       0x10, 0x85, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
-       0x10, 0x1b, 0x02, 0x00, 0x00,
-       0x10, 0x11, 0x08, 0x51, 0x00, 0x30, 0x02, 0x3d, 0x00, 0xa4, 0x01,
-       0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
-       0x10, 0x1d, 0x02, 0x68, 0x00,
-};
-static const u8 kr651_start_2[] = {
-       0x10, 0x0e, 0x01, 0x08,
-       0x10, 0x41, 0x11, 0x00, 0x11, 0x3c, 0x5c, 0x74, 0x88, 0x99, 0xa8,
-                         0xb7, 0xc4, 0xd0, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
-                         0xdc,
-       0x10, 0x03, 0x01, 0x00,
-       0x10, 0x0f, 0x02, 0x0c, 0x0c,
-       0x10, 0x03, 0x01, 0x0c,
-       0x10, 0x41, 0x11, 0x00, 0x11, 0x3c, 0x5c, 0x74, 0x88, 0x99, 0xa8,
-                         0xb7, 0xc4, 0xd0, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
-                         0xdc,
-       0x10, 0x0b, 0x01, 0x10,
-       0x10, 0x0d, 0x01, 0x10,
-       0x10, 0x0c, 0x01, 0x2d,
-       0x04, 0x06, 0x01, 0x03,
-       0x04, 0x04, 0x01, 0x00,
-       0, 0, 0
-};
-
-/* nw802 - iRez Kritter cam */
-static const u8 kritter_start[] = {
-       0x04, 0x06, 0x01, 0x06,
-       0x00, 0x00, 0x40, 0x44, 0x96, 0x98, 0x94, 0x03, 0x18, 0x00, 0x48,
-                         0x0f, 0x1e, 0x00, 0x0c, 0x02, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x0b, 0x00, 0x1b, 0x00, 0x0a, 0x01, 0x28,
-                         0x07, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
-                         0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
-                         0x00, 0x5d, 0x00, 0x0e, 0x00, 0x7e, 0x00, 0x30,
-       0x00, 0x80, 0x1f, 0x18, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
-                         0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
-                         0x00, 0x0b, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
-                         0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
-       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x02, 0x00, 0x00,
-       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
-       0x06, 0x00, 0x02, 0x09, 0x99,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
-                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
-                         0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
-                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
-                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
-                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
-       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
-                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
-                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
-                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
-       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x82,
-                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
-                         0x01, 0xf0, 0x00,
-       0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00,
-                         0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
-                         0x40,
-       0x10, 0x1a, 0x01, 0x03,
-       0x10, 0x00, 0x01, 0xaf,
-       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
-       0x10, 0x1b, 0x02, 0x3b, 0x01,
-       0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
-       0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
-       0x10, 0x1d, 0x02, 0x00, 0x00,
-       0x10, 0x0e, 0x01, 0x08,
-       0x10, 0x41, 0x11, 0x00, 0x0d, 0x36, 0x4e, 0x60, 0x6f, 0x7b, 0x86,
-                         0x90, 0x98, 0xa1, 0xa9, 0xb1, 0xb7, 0xbe, 0xc4,
-                         0xcb,
-       0x10, 0x03, 0x01, 0x00,
-       0x10, 0x0f, 0x02, 0x0d, 0x0d,
-       0x10, 0x03, 0x01, 0x02,
-       0x10, 0x41, 0x11, 0x00, 0x0d, 0x36, 0x4e, 0x60, 0x6f, 0x7b, 0x86,
-                         0x90, 0x98, 0xa1, 0xa9, 0xb1, 0xb7, 0xbe, 0xc4,
-                         0xcb,
-       0x10, 0x0b, 0x01, 0x17,
-       0x10, 0x0d, 0x01, 0x10,
-       0x10, 0x0c, 0x01, 0x1e,
-       0x04, 0x06, 0x01, 0x03,
-       0x04, 0x04, 0x01, 0x00,
-       0, 0, 0
-};
-
-/* nw802 - Mustek Wcam 300 mini */
-static const u8 mustek_start[] = {
-       0x04, 0x06, 0x01, 0x04,
-       0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x92, 0x03, 0x10, 0x00, 0x4d,
-                         0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
-                         0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
-                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
-                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
-                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
-       0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
-                         0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
-                         0x00, 0x10, 0x06, 0xfc, 0x05, 0x0c, 0x06,
-       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
-       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
-       0x06, 0x00, 0x02, 0x09, 0x99,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x13, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
-                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x49, 0x13, 0x00, 0x00, 0xc0, 0x00, 0x14,
-                         0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
-                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
-                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
-                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
-       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
-                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
-                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
-                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
-       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x82,
-                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
-                         0x01, 0xf0, 0x00,
-       0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
-                         0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
-                         0x40,
-       0x10, 0x1a, 0x01, 0x00,
-       0x10, 0x00, 0x01, 0xad,
-       0x00, 0x00, 0x01, 0x08,
-       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
-       0x10, 0x1b, 0x02, 0x00, 0x00,
-       0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
-       0x10, 0x1d, 0x08, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
-       0x10, 0x0e, 0x01, 0x0f,
-       0x10, 0x41, 0x11, 0x00, 0x0f, 0x29, 0x4a, 0x64, 0x7a, 0x8c, 0x9e,
-                         0xad, 0xba, 0xc7, 0xd3, 0xde, 0xe8, 0xf1, 0xf9,
-                         0xff,
-       0x10, 0x0f, 0x02, 0x11, 0x11,
-       0x10, 0x03, 0x01, 0x0c,
-       0x10, 0x41, 0x11, 0x00, 0x0f, 0x29, 0x4a, 0x64, 0x7a, 0x8c, 0x9e,
-                         0xad, 0xba, 0xc7, 0xd3, 0xde, 0xe8, 0xf1, 0xf9,
-                         0xff,
-       0x10, 0x0b, 0x01, 0x1c,
-       0x10, 0x0d, 0x01, 0x1a,
-       0x10, 0x0c, 0x01, 0x34,
-       0x04, 0x05, 0x01, 0x61,
-       0x04, 0x04, 0x01, 0x40,
-       0x04, 0x06, 0x01, 0x03,
-       0, 0, 0
-};
-
-/* nw802 - Scope USB Microscope M2 (ProScope) (Hitachi HD49322BF) */
-static const u8 proscope_init[] = {
-       0x04, 0x05, 0x01, 0x21,
-       0x04, 0x04, 0x01, 0x01,
-       0, 0, 0
-};
-static const u8 proscope_start_1[] = {
-       0x04, 0x06, 0x01, 0x04,
-       0x00, 0x00, 0x40, 0x10, 0x01, 0x00, 0xf9, 0x02, 0x10, 0x00, 0x04,
-                         0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x08, 0x00, 0x17, 0x00, 0xce, 0x00, 0xf4,
-                         0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
-                         0x00, 0xce, 0x00, 0xf8, 0x03, 0x3e, 0x00, 0x86,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0xb6,
-                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xf6, 0x03, 0x34, 0x04, 0xf6, 0x03, 0x34,
-                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xe8,
-                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
-       0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x1f, 0x0f, 0x08, 0x20, 0xa8, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
-                         0x00, 0x0c, 0x02, 0x01, 0x00, 0x19, 0x00, 0x94,
-                         0x00, 0x10, 0x06, 0x10, 0x00, 0x36, 0x00,
-       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
-       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
-       0x06, 0x00, 0x02, 0x09, 0x99,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0xad, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x10, 0x1f, 0x10, 0x08, 0x0a,
-                         0x0a, 0x51, 0x00, 0xf1, 0x00, 0x3c, 0x00, 0xb4,
-                         0x00, 0x49, 0x13, 0x00, 0x00, 0x8c, 0x04, 0x01,
-                         0x20, 0x02, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00,
-                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
-                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
-                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
-       0x10, 0x40, 0x40, 0x80, 0x00, 0x2d, 0x46, 0x58, 0x67, 0x74, 0x7f,
-                         0x88, 0x94, 0x9d, 0xa6, 0xae, 0xb5, 0xbd, 0xc4,
-                         0xcb, 0xd1, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
-                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
-       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x3f,
-                         0x01, 0x00, 0x00, 0xef, 0x00, 0x09, 0x05, 0x82,
-                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
-                         0x01, 0xf0, 0x00,
-       0, 0, 0
-};
-static const u8 proscope_start_qvga[] = {
-       0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
-                         0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
-                         0x40,
-       0x10, 0x1a, 0x01, 0x06,
-       0x00, 0x03, 0x02, 0xf9, 0x02,
-       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
-       0x10, 0x1b, 0x02, 0x00, 0x00,
-       0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
-       0x10, 0x1d, 0x08, 0xc0, 0x0d, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
-       0x10, 0x0e, 0x01, 0x10,
-       0, 0, 0
-};
-static const u8 proscope_start_vga[] = {
-       0x00, 0x03, 0x02, 0xf9, 0x02,
-       0x10, 0x85, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
-       0x02, 0x00, 0x11, 0x78, 0xa0, 0x8c, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x16, 0x00, 0x00, 0x82, 0x84, 0x00,
-                         0x80,
-       0x10, 0x1a, 0x01, 0x06,
-       0x10, 0x00, 0x01, 0xa1,
-       0x10, 0x1b, 0x02, 0x00, 0x00,
-       0x10, 0x1d, 0x08, 0xc0, 0x0d, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
-       0x10, 0x11, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
-       0x10, 0x0e, 0x01, 0x10,
-       0x10, 0x41, 0x11, 0x00, 0x10, 0x51, 0x6e, 0x83, 0x93, 0xa1, 0xae,
-                         0xb9, 0xc3, 0xcc, 0xd4, 0xdd, 0xe4, 0xeb, 0xf2,
-                         0xf9,
-       0x10, 0x03, 0x01, 0x00,
-       0, 0, 0
-};
-static const u8 proscope_start_2[] = {
-       0x10, 0x0f, 0x02, 0x0c, 0x0c,
-       0x10, 0x03, 0x01, 0x0c,
-       0x10, 0x41, 0x11, 0x00, 0x10, 0x51, 0x6e, 0x83, 0x93, 0xa1, 0xae,
-                         0xb9, 0xc3, 0xcc, 0xd4, 0xdd, 0xe4, 0xeb, 0xf2,
-                         0xf9,
-       0x10, 0x0b, 0x01, 0x0b,
-       0x10, 0x0d, 0x01, 0x10,
-       0x10, 0x0c, 0x01, 0x1b,
-       0x04, 0x06, 0x01, 0x03,
-       0x04, 0x05, 0x01, 0x21,
-       0x04, 0x04, 0x01, 0x00,
-       0, 0, 0
-};
-
-/* nw800 - hv7121b? (seems pas106) - Divio Chicony TwinkleCam */
-static const u8 twinkle_start[] = {
-       0x04, 0x06, 0x01, 0x44,
-       0x04, 0x06, 0x01, 0x00,
-       0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f,
-                         0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc,
-                         0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
-                         0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
-                         0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
-                         0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
-                         0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
-                         0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
-       0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03,
-                         0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
-                         0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
-       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
-       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00,
-       0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x08,
-                         0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
-                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
-                         0x03, 0x00, 0x00, 0x10, 0x00, 0x20, 0x10, 0x06,
-                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x00, 0x80,
-       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
-                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
-                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
-                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
-       0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62,
-                         0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
-                         0x01, 0x60, 0x01, 0x00, 0x00,
-
-       0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
-       0x04, 0x04, 0x01, 0x10,
-       0x04, 0x04, 0x01, 0x00,
-       0x04, 0x05, 0x01, 0x61,
-       0x04, 0x04, 0x01, 0x01,
-       I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x0a,
-       I2C0, 0x40, 0x02, 0x11, 0x06,
-       I2C0, 0x40, 0x02, 0x14, 0x00,
-       I2C0, 0x40, 0x02, 0x13, 0x01,           /* i2c end */
-       I2C0, 0x40, 0x02, 0x07, 0x01,
-       0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
-                         0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
-                         0x40,
-       I2C0, 0x40, 0x02, 0x02, 0x0c,
-       I2C0, 0x40, 0x02, 0x13, 0x01,
-       0x10, 0x00, 0x01, 0x01,
-       0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
-                         0x20, 0x01, 0x60, 0x01,
-       I2C0, 0x40, 0x02, 0x05, 0x0f,
-       I2C0, 0x40, 0x02, 0x13, 0x01,
-       I2C0, 0x40, 0x08, 0x08, 0x04, 0x0b, 0x01, 0x01, 0x02, 0x00, 0x17,
-       I2C0, 0x40, 0x03, 0x12, 0x00, 0x01,
-       0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
-       I2C0, 0x40, 0x02, 0x12, 0x00,
-       I2C0, 0x40, 0x02, 0x0e, 0x00,
-       I2C0, 0x40, 0x02, 0x11, 0x06,
-       0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
-                         0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
-                         0xf9,
-       0x10, 0x03, 0x01, 0x00,
-       0x10, 0x0f, 0x02, 0x0c, 0x0c,
-       0x10, 0x03, 0x01, 0x06,
-       0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
-                         0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
-                         0xf9,
-       0x10, 0x0b, 0x01, 0x19,
-       0x10, 0x0d, 0x01, 0x10,
-       0x10, 0x0c, 0x01, 0x0d,
-       0x04, 0x06, 0x01, 0x03,
-       0x04, 0x05, 0x01, 0x61,
-       0x04, 0x04, 0x01, 0x41,
-       0, 0, 0
-};
-
-/* nw802 dvc-v6 */
-static const u8 dvcv6_start[] = {
-       0x04, 0x06, 0x01, 0x06,
-       0x00, 0x00, 0x40, 0x54, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x4c,
-                         0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
-                         0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
-                         0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
-                         0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-       0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
-                         0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
-                         0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
-                         0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
-                         0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
-       0x00, 0x80, 0x1f, 0x98, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
-                         0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
-                         0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
-                         0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
-       0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
-                         0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
-                         0x40, 0x20,
-       0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
-       0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
-       0x06, 0x00, 0x02, 0x09, 0x99,
-       0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00,
-       0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
-                         0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                         0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
-                         0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
-                         0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
-                         0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
-                         0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
-       0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
-                         0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
-                         0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
-                         0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
-                         0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
-                         0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
-                         0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
-                         0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
-       0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
-                         0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
-                         0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
-                         0x01, 0xf0, 0x00,
-       0x00, 0x03, 0x02, 0x94, 0x03,
-       0x00, 0x1d, 0x04, 0x0a, 0x01, 0x28, 0x07,
-       0x00, 0x7b, 0x02, 0xe0, 0x00,
-       0x10, 0x8d, 0x01, 0x00,
-       0x00, 0x09, 0x04, 0x1e, 0x00, 0x0c, 0x02,
-       0x00, 0x91, 0x02, 0x0b, 0x02,
-       0x10, 0x00, 0x01, 0xaf,
-       0x02, 0x00, 0x11, 0x3c, 0x50, 0x8f, 0x3c, 0x50, 0x00, 0x00, 0x00,
-                         0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
-                         0x40,
-       0x10, 0x1a, 0x01, 0x02,
-       0x10, 0x00, 0x01, 0xaf,
-       0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
-       0x10, 0x1b, 0x02, 0x07, 0x01,
-       0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
-       0x10, 0x1f, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
-       0x10, 0x1d, 0x02, 0x40, 0x06,
-       0x10, 0x0e, 0x01, 0x08,
-       0x10, 0x41, 0x11, 0x00, 0x0f, 0x54, 0x6f, 0x82, 0x91, 0x9f, 0xaa,
-                         0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xdb, 0xdc, 0xdc,
-                         0xdc,
-       0x10, 0x03, 0x01, 0x00,
-       0x10, 0x0f, 0x02, 0x12, 0x12,
-       0x10, 0x03, 0x01, 0x11,
-       0x10, 0x41, 0x11, 0x00, 0x0f, 0x54, 0x6f, 0x82, 0x91, 0x9f, 0xaa,
-                         0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xdb, 0xdc, 0xdc,
-                         0xdc,
-       0x10, 0x0b, 0x01, 0x16,
-       0x10, 0x0d, 0x01, 0x10,
-       0x10, 0x0c, 0x01, 0x1a,
-       0x04, 0x06, 0x01, 0x03,
-       0x04, 0x04, 0x01, 0x00,
-};
-
-static const u8 *webcam_start[] = {
-       [Generic800] = nw800_start,
-       [SpaceCam] = spacecam_start,
-       [SpaceCam2] = spacecam2_start,
-       [Cvideopro] = cvideopro_start,
-       [Dlink350c] = dlink_start,
-       [DS3303u] = ds3303_start,
-       [Kr651us] = kr651_start_1,
-       [Kritter] = kritter_start,
-       [Mustek300] = mustek_start,
-       [Proscope] = proscope_start_1,
-       [Twinkle] = twinkle_start,
-       [DvcV6] = dvcv6_start,
-       [P35u] = nw801_start_1,
-       [Generic802] = nw802_start,
-};
-
-/* -- write a register -- */
-static void reg_w(struct gspca_dev *gspca_dev,
-                       u16 index,
-                       const u8 *data,
-                       int len)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       if (len == 1)
-               PDEBUG(D_USBO, "SET 00 0000 %04x %02x", index, *data);
-       else
-               PDEBUG(D_USBO, "SET 00 0000 %04x %02x %02x ...",
-                               index, *data, data[1]);
-       memcpy(gspca_dev->usb_buf, data, len);
-       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-                       0x00,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0x00,           /* value */
-                       index,
-                       gspca_dev->usb_buf,
-                       len,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_w err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-/* -- read registers in usb_buf -- */
-static void reg_r(struct gspca_dev *gspca_dev,
-                       u16 index,
-                       int len)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-                       0x00,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0x00, index,
-                       gspca_dev->usb_buf, len, 500);
-       if (ret < 0) {
-               pr_err("reg_r err %d\n", ret);
-               gspca_dev->usb_err = ret;
-               return;
-       }
-       if (len == 1)
-               PDEBUG(D_USBI, "GET 00 0000 %04x %02x",
-                               index, gspca_dev->usb_buf[0]);
-       else
-               PDEBUG(D_USBI, "GET 00 0000 %04x %02x %02x ..",
-                               index, gspca_dev->usb_buf[0],
-                               gspca_dev->usb_buf[1]);
-}
-
-static void i2c_w(struct gspca_dev *gspca_dev,
-                       u8 i2c_addr,
-                       const u8 *data,
-                       int len)
-{
-       u8 val[2];
-       int i;
-
-       reg_w(gspca_dev, 0x0600, data + 1, len - 1);
-       reg_w(gspca_dev, 0x0600, data, len);
-       val[0] = len;
-       val[1] = i2c_addr;
-       reg_w(gspca_dev, 0x0502, val, 2);
-       val[0] = 0x01;
-       reg_w(gspca_dev, 0x0501, val, 1);
-       for (i = 5; --i >= 0; ) {
-               msleep(4);
-               reg_r(gspca_dev, 0x0505, 1);
-               if (gspca_dev->usb_err < 0)
-                       return;
-               if (gspca_dev->usb_buf[0] == 0)
-                       return;
-       }
-       gspca_dev->usb_err = -ETIME;
-}
-
-static void reg_w_buf(struct gspca_dev *gspca_dev,
-                       const u8 *cmd)
-{
-       u16 reg;
-       int len;
-
-       for (;;) {
-               reg = *cmd++ << 8;
-               reg += *cmd++;
-               len = *cmd++;
-               if (len == 0)
-                       break;
-               if (cmd[-3] != I2C0)
-                       reg_w(gspca_dev, reg, cmd, len);
-               else
-                       i2c_w(gspca_dev, reg, cmd, len);
-               cmd += len;
-       }
-}
-
-static int swap_bits(int v)
-{
-       int r, i;
-
-       r = 0;
-       for (i = 0; i < 8; i++) {
-               r <<= 1;
-               if (v & 1)
-                       r++;
-               v >>= 1;
-       }
-       return r;
-}
-
-static void setgain(struct gspca_dev *gspca_dev, u8 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 v[2];
-
-       switch (sd->webcam) {
-       case P35u:
-               reg_w(gspca_dev, 0x1026, &val, 1);
-               break;
-       case Kr651us:
-               /* 0 - 253 */
-               val = swap_bits(val);
-               v[0] = val << 3;
-               v[1] = val >> 5;
-               reg_w(gspca_dev, 0x101d, v, 2); /* SIF reg0/1 (AGC) */
-               break;
-       }
-}
-
-static void setexposure(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 v[2];
-
-       switch (sd->webcam) {
-       case P35u:
-               v[0] = ((9 - val) << 3) | 0x01;
-               reg_w(gspca_dev, 0x1019, v, 1);
-               break;
-       case Cvideopro:
-       case DvcV6:
-       case Kritter:
-       case Kr651us:
-               v[0] = val;
-               v[1] = val >> 8;
-               reg_w(gspca_dev, 0x101b, v, 2);
-               break;
-       }
-}
-
-static void setautogain(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int w, h;
-
-       if (!val) {
-               sd->ag_cnt = -1;
-               return;
-       }
-       sd->ag_cnt = AG_CNT_START;
-
-       reg_r(gspca_dev, 0x1004, 1);
-       if (gspca_dev->usb_buf[0] & 0x04) {     /* if AE_FULL_FRM */
-               sd->ae_res = gspca_dev->width * gspca_dev->height;
-       } else {                                /* get the AE window size */
-               reg_r(gspca_dev, 0x1011, 8);
-               w = (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]
-                 - (gspca_dev->usb_buf[3] << 8) - gspca_dev->usb_buf[2];
-               h = (gspca_dev->usb_buf[5] << 8) + gspca_dev->usb_buf[4]
-                 - (gspca_dev->usb_buf[7] << 8) - gspca_dev->usb_buf[6];
-               sd->ae_res = h * w;
-               if (sd->ae_res == 0)
-                       sd->ae_res = gspca_dev->width * gspca_dev->height;
-       }
-}
-
-static int nw802_test_reg(struct gspca_dev *gspca_dev,
-                       u16 index,
-                       u8 value)
-{
-       /* write the value */
-       reg_w(gspca_dev, index, &value, 1);
-
-       /* read it */
-       reg_r(gspca_dev, index, 1);
-
-       return gspca_dev->usb_buf[0] == value;
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if ((unsigned) webcam >= NWEBCAMS)
-               webcam = 0;
-       sd->webcam = webcam;
-       gspca_dev->cam.needs_full_bandwidth = 1;
-       sd->ag_cnt = -1;
-
-       /*
-        * Autodetect sequence inspired from some log.
-        * We try to detect what registers exist or not.
-        * If 0x0500 does not exist => NW802
-        * If it does, test 0x109b. If it doesn't exist,
-        * then it's a NW801. Else, a NW800
-        * If a et31x110 (nw800 and 06a5:d800)
-        *      get the sensor ID
-        */
-       if (!nw802_test_reg(gspca_dev, 0x0500, 0x55)) {
-               sd->bridge = BRIDGE_NW802;
-               if (sd->webcam == Generic800)
-                       sd->webcam = Generic802;
-       } else if (!nw802_test_reg(gspca_dev, 0x109b, 0xaa)) {
-               sd->bridge = BRIDGE_NW801;
-               if (sd->webcam == Generic800)
-                       sd->webcam = P35u;
-       } else if (id->idVendor == 0x06a5 && id->idProduct == 0xd800) {
-               reg_r(gspca_dev, 0x0403, 1);            /* GPIO */
-               PDEBUG(D_PROBE, "et31x110 sensor type %02x",
-                               gspca_dev->usb_buf[0]);
-               switch (gspca_dev->usb_buf[0] >> 1) {
-               case 0x00:                              /* ?? */
-                       if (sd->webcam == Generic800)
-                               sd->webcam = SpaceCam;
-                       break;
-               case 0x01:                              /* Hynix? */
-                       if (sd->webcam == Generic800)
-                               sd->webcam = Twinkle;
-                       break;
-               case 0x0a:                              /* Pixart */
-                       if (sd->webcam == Generic800)
-                               sd->webcam = SpaceCam2;
-                       break;
-               }
-       }
-       if (webcam_chip[sd->webcam] != sd->bridge) {
-               pr_err("Bad webcam type %d for NW80%d\n",
-                      sd->webcam, sd->bridge);
-               gspca_dev->usb_err = -ENODEV;
-               return gspca_dev->usb_err;
-       }
-       PDEBUG(D_PROBE, "Bridge nw80%d - type: %d", sd->bridge, sd->webcam);
-
-       if (sd->bridge == BRIDGE_NW800) {
-               switch (sd->webcam) {
-               case DS3303u:
-                       gspca_dev->cam.cam_mode = cif_mode;     /* qvga */
-                       break;
-               default:
-                       gspca_dev->cam.cam_mode = &cif_mode[1]; /* cif */
-                       break;
-               }
-               gspca_dev->cam.nmodes = 1;
-       } else {
-               gspca_dev->cam.cam_mode = vga_mode;
-               switch (sd->webcam) {
-               case Kr651us:
-               case Proscope:
-               case P35u:
-                       gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
-                       break;
-               default:
-                       gspca_dev->cam.nmodes = 1;      /* qvga only */
-                       break;
-               }
-       }
-
-       return gspca_dev->usb_err;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->bridge) {
-       case BRIDGE_NW800:
-               switch (sd->webcam) {
-               case SpaceCam:
-                       reg_w_buf(gspca_dev, spacecam_init);
-                       break;
-               default:
-                       reg_w_buf(gspca_dev, nw800_init);
-                       break;
-               }
-               break;
-       default:
-               switch (sd->webcam) {
-               case Mustek300:
-               case P35u:
-               case Proscope:
-                       reg_w_buf(gspca_dev, proscope_init);
-                       break;
-               }
-               break;
-       }
-       return gspca_dev->usb_err;
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       const u8 *cmd;
-
-       cmd = webcam_start[sd->webcam];
-       reg_w_buf(gspca_dev, cmd);
-       switch (sd->webcam) {
-       case P35u:
-               if (gspca_dev->width == 320)
-                       reg_w_buf(gspca_dev, nw801_start_qvga);
-               else
-                       reg_w_buf(gspca_dev, nw801_start_vga);
-               reg_w_buf(gspca_dev, nw801_start_2);
-               break;
-       case Kr651us:
-               if (gspca_dev->width == 320)
-                       reg_w_buf(gspca_dev, kr651_start_qvga);
-               else
-                       reg_w_buf(gspca_dev, kr651_start_vga);
-               reg_w_buf(gspca_dev, kr651_start_2);
-               break;
-       case Proscope:
-               if (gspca_dev->width == 320)
-                       reg_w_buf(gspca_dev, proscope_start_qvga);
-               else
-                       reg_w_buf(gspca_dev, proscope_start_vga);
-               reg_w_buf(gspca_dev, proscope_start_2);
-               break;
-       }
-
-       sd->exp_too_high_cnt = 0;
-       sd->exp_too_low_cnt = 0;
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 value;
-
-       /* 'go' off */
-       if (sd->bridge != BRIDGE_NW801) {
-               value = 0x02;
-               reg_w(gspca_dev, 0x0406, &value, 1);
-       }
-
-       /* LED off */
-       switch (sd->webcam) {
-       case Cvideopro:
-       case Kr651us:
-       case DvcV6:
-       case Kritter:
-               value = 0xff;
-               break;
-       case Dlink350c:
-               value = 0x21;
-               break;
-       case SpaceCam:
-       case SpaceCam2:
-       case Proscope:
-       case Twinkle:
-               value = 0x01;
-               break;
-       default:
-               return;
-       }
-       reg_w(gspca_dev, 0x0404, &value, 1);
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,                       /* isoc packet */
-                       int len)                        /* iso packet length */
-{
-       /*
-        * frame header = '00 00 hh ww ss xx ff ff'
-        * with:
-        *      - 'hh': height / 4
-        *      - 'ww': width / 4
-        *      - 'ss': frame sequence number c0..dd
-        */
-       if (data[0] == 0x00 && data[1] == 0x00
-        && data[6] == 0xff && data[7] == 0xff) {
-               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-               gspca_frame_add(gspca_dev, FIRST_PACKET, data + 8, len - 8);
-       } else {
-               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-       }
-}
-
-static void do_autogain(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int luma;
-
-       if (sd->ag_cnt < 0)
-               return;
-       if (--sd->ag_cnt >= 0)
-               return;
-       sd->ag_cnt = AG_CNT_START;
-
-       /* get the average luma */
-       reg_r(gspca_dev, sd->bridge == BRIDGE_NW801 ? 0x080d : 0x080c, 4);
-       luma = (gspca_dev->usb_buf[3] << 24) + (gspca_dev->usb_buf[2] << 16)
-               + (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
-       luma /= sd->ae_res;
-
-       switch (sd->webcam) {
-       case P35u:
-               gspca_coarse_grained_expo_autogain(gspca_dev, luma, 100, 5);
-               break;
-       default:
-               gspca_expo_autogain(gspca_dev, luma, 100, 5, 230, 0);
-               break;
-       }
-}
-
-
-static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct gspca_dev *gspca_dev =
-               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
-
-       gspca_dev->usb_err = 0;
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       /* autogain/gain/exposure control cluster */
-       case V4L2_CID_AUTOGAIN:
-               if (ctrl->is_new)
-                       setautogain(gspca_dev, ctrl->val);
-               if (!ctrl->val) {
-                       if (gspca_dev->gain->is_new)
-                               setgain(gspca_dev, gspca_dev->gain->val);
-                       if (gspca_dev->exposure->is_new)
-                               setexposure(gspca_dev,
-                                           gspca_dev->exposure->val);
-               }
-               break;
-       /* Some webcams only have exposure, so handle that separately from the
-          autogain/gain/exposure cluster in the previous case. */
-       case V4L2_CID_EXPOSURE:
-               setexposure(gspca_dev, gspca_dev->exposure->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, 3);
-       switch (sd->webcam) {
-       case P35u:
-               gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-               /* For P35u choose coarse expo auto gain function gain minimum,
-                * to avoid a large settings jump the first auto adjustment */
-               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAIN, 0, 127, 1, 127 / 5 * 2);
-               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 0, 9, 1, 9);
-               break;
-       case Kr651us:
-               gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAIN, 0, 253, 1, 128);
-               /* fall through */
-       case Cvideopro:
-       case DvcV6:
-       case Kritter:
-               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 0, 315, 1, 150);
-               break;
-       default:
-               break;
-       }
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-       if (gspca_dev->autogain)
-               v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
-       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,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-       .dq_callback = do_autogain,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x046d, 0xd001)},
-       {USB_DEVICE(0x0502, 0xd001)},
-       {USB_DEVICE(0x052b, 0xd001)},
-       {USB_DEVICE(0x055f, 0xd001)},
-       {USB_DEVICE(0x06a5, 0x0000)},
-       {USB_DEVICE(0x06a5, 0xd001)},
-       {USB_DEVICE(0x06a5, 0xd800)},
-       {USB_DEVICE(0x06be, 0xd001)},
-       {USB_DEVICE(0x0728, 0xd001)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
-
-module_param(webcam, int, 0644);
-MODULE_PARM_DESC(webcam,
-       "Webcam type\n"
-       "0: generic\n"
-       "1: Trust 120 SpaceCam\n"
-       "2: other Trust 120 SpaceCam\n"
-       "3: Conceptronic Video Pro\n"
-       "4: D-link dru-350c\n"
-       "5: Plustek Opticam 500U\n"
-       "6: Panasonic GP-KR651US\n"
-       "7: iRez Kritter\n"
-       "8: Mustek Wcam 300 mini\n"
-       "9: Scalar USB Microscope M2 (Proscope)\n"
-       "10: Divio Chicony TwinkleCam\n"
-       "11: DVC-V6\n");
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
deleted file mode 100644 (file)
index bfc7cef..0000000
+++ /dev/null
@@ -1,4991 +0,0 @@
-/**
- * OV519 driver
- *
- * Copyright (C) 2008-2011 Jean-François Moine <moinejf@free.fr>
- * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com>
- *
- * This module is adapted from the ov51x-jpeg package, which itself
- * was adapted from the ov511 driver.
- *
- * Original copyright for the ov511 driver is:
- *
- * Copyright (c) 1999-2006 Mark W. McClelland
- * Support for OV519, OV8610 Copyright (c) 2003 Joerg Heckenbach
- * Many improvements by Bret Wallach <bwallac1@san.rr.com>
- * Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000)
- * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org>
- * Changes by Claudio Matsuoka <claudio@conectiva.com>
- *
- * ov51x-jpeg original copyright is:
- *
- * Copyright (c) 2004-2007 Romain Beauxis <toots@rastageeks.org>
- * Support for OV7670 sensors was contributed by Sam Skipsey <aoanla@yahoo.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
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "ov519"
-
-#include <linux/input.h>
-#include "gspca.h"
-
-/* The jpeg_hdr is used by w996Xcf only */
-/* The CONEX_CAM define for jpeg.h needs renaming, now its used here too */
-#define CONEX_CAM
-#include "jpeg.h"
-
-MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
-MODULE_DESCRIPTION("OV519 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* global parameters */
-static int frame_rate;
-
-/* Number of times to retry a failed I2C transaction. Increase this if you
- * are getting "Failed to read sensor ID..." */
-static int i2c_detect_tries = 10;
-
-/* ov519 device descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;             /* !! must be the first item */
-
-       struct v4l2_ctrl *jpegqual;
-       struct v4l2_ctrl *freq;
-       struct { /* h/vflip control cluster */
-               struct v4l2_ctrl *hflip;
-               struct v4l2_ctrl *vflip;
-       };
-       struct { /* autobrightness/brightness control cluster */
-               struct v4l2_ctrl *autobright;
-               struct v4l2_ctrl *brightness;
-       };
-
-       u8 packet_nr;
-
-       char bridge;
-#define BRIDGE_OV511           0
-#define BRIDGE_OV511PLUS       1
-#define BRIDGE_OV518           2
-#define BRIDGE_OV518PLUS       3
-#define BRIDGE_OV519           4               /* = ov530 */
-#define BRIDGE_OVFX2           5
-#define BRIDGE_W9968CF         6
-#define BRIDGE_MASK            7
-
-       char invert_led;
-#define BRIDGE_INVERT_LED      8
-
-       char snapshot_pressed;
-       char snapshot_needs_reset;
-
-       /* Determined by sensor type */
-       u8 sif;
-
-#define QUALITY_MIN 50
-#define QUALITY_MAX 70
-#define QUALITY_DEF 50
-
-       u8 stopped;             /* Streaming is temporarily paused */
-       u8 first_frame;
-
-       u8 frame_rate;          /* current Framerate */
-       u8 clockdiv;            /* clockdiv override */
-
-       s8 sensor;              /* Type of image sensor chip (SEN_*) */
-
-       u8 sensor_addr;
-       u16 sensor_width;
-       u16 sensor_height;
-       s16 sensor_reg_cache[256];
-
-       u8 jpeg_hdr[JPEG_HDR_SZ];
-};
-enum sensors {
-       SEN_OV2610,
-       SEN_OV2610AE,
-       SEN_OV3610,
-       SEN_OV6620,
-       SEN_OV6630,
-       SEN_OV66308AF,
-       SEN_OV7610,
-       SEN_OV7620,
-       SEN_OV7620AE,
-       SEN_OV7640,
-       SEN_OV7648,
-       SEN_OV7660,
-       SEN_OV7670,
-       SEN_OV76BE,
-       SEN_OV8610,
-       SEN_OV9600,
-};
-
-/* Note this is a bit of a hack, but the w9968cf driver needs the code for all
-   the ov sensors which is already present here. When we have the time we
-   really should move the sensor drivers to v4l2 sub drivers. */
-#include "w996Xcf.c"
-
-/* table of the disabled controls */
-struct ctrl_valid {
-       int has_brightness:1;
-       int has_contrast:1;
-       int has_exposure:1;
-       int has_autogain:1;
-       int has_sat:1;
-       int has_hvflip:1;
-       int has_autobright:1;
-       int has_freq:1;
-};
-
-static const struct ctrl_valid valid_controls[] = {
-       [SEN_OV2610] = {
-               .has_exposure = 1,
-               .has_autogain = 1,
-       },
-       [SEN_OV2610AE] = {
-               .has_exposure = 1,
-               .has_autogain = 1,
-       },
-       [SEN_OV3610] = {
-               /* No controls */
-       },
-       [SEN_OV6620] = {
-               .has_brightness = 1,
-               .has_contrast = 1,
-               .has_sat = 1,
-               .has_autobright = 1,
-               .has_freq = 1,
-       },
-       [SEN_OV6630] = {
-               .has_brightness = 1,
-               .has_contrast = 1,
-               .has_sat = 1,
-               .has_autobright = 1,
-               .has_freq = 1,
-       },
-       [SEN_OV66308AF] = {
-               .has_brightness = 1,
-               .has_contrast = 1,
-               .has_sat = 1,
-               .has_autobright = 1,
-               .has_freq = 1,
-       },
-       [SEN_OV7610] = {
-               .has_brightness = 1,
-               .has_contrast = 1,
-               .has_sat = 1,
-               .has_autobright = 1,
-               .has_freq = 1,
-       },
-       [SEN_OV7620] = {
-               .has_brightness = 1,
-               .has_contrast = 1,
-               .has_sat = 1,
-               .has_autobright = 1,
-               .has_freq = 1,
-       },
-       [SEN_OV7620AE] = {
-               .has_brightness = 1,
-               .has_contrast = 1,
-               .has_sat = 1,
-               .has_autobright = 1,
-               .has_freq = 1,
-       },
-       [SEN_OV7640] = {
-               .has_brightness = 1,
-               .has_sat = 1,
-               .has_freq = 1,
-       },
-       [SEN_OV7648] = {
-               .has_brightness = 1,
-               .has_sat = 1,
-               .has_freq = 1,
-       },
-       [SEN_OV7660] = {
-               .has_brightness = 1,
-               .has_contrast = 1,
-               .has_sat = 1,
-               .has_hvflip = 1,
-               .has_freq = 1,
-       },
-       [SEN_OV7670] = {
-               .has_brightness = 1,
-               .has_contrast = 1,
-               .has_hvflip = 1,
-               .has_freq = 1,
-       },
-       [SEN_OV76BE] = {
-               .has_brightness = 1,
-               .has_contrast = 1,
-               .has_sat = 1,
-               .has_autobright = 1,
-               .has_freq = 1,
-       },
-       [SEN_OV8610] = {
-               .has_brightness = 1,
-               .has_contrast = 1,
-               .has_sat = 1,
-               .has_autobright = 1,
-       },
-       [SEN_OV9600] = {
-               .has_exposure = 1,
-               .has_autogain = 1,
-       },
-};
-
-static const struct v4l2_pix_format ov519_vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-static const struct v4l2_pix_format ov519_sif_mode[] = {
-       {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 3},
-       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 2},
-       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-
-/* Note some of the sizeimage values for the ov511 / ov518 may seem
-   larger then necessary, however they need to be this big as the ov511 /
-   ov518 always fills the entire isoc frame, using 0 padding bytes when
-   it doesn't have any data. So with low framerates the amount of data
-   transferred can become quite large (libv4l will remove all the 0 padding
-   in userspace). */
-static const struct v4l2_pix_format ov518_vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 2,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-static const struct v4l2_pix_format ov518_sif_mode[] = {
-       {160, 120, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 70000,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 3},
-       {176, 144, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 70000,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {320, 240, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 2},
-       {352, 288, V4L2_PIX_FMT_OV518, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 3,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-
-static const struct v4l2_pix_format ov511_vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 2,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-static const struct v4l2_pix_format ov511_sif_mode[] = {
-       {160, 120, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 70000,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 3},
-       {176, 144, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 70000,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {320, 240, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 2},
-       {352, 288, V4L2_PIX_FMT_OV511, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 3,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-
-static const struct v4l2_pix_format ovfx2_vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-static const struct v4l2_pix_format ovfx2_cif_mode[] = {
-       {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 3},
-       {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2},
-       {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-static const struct v4l2_pix_format ovfx2_ov2610_mode[] = {
-       {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 800,
-               .sizeimage = 800 * 600,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 1600,
-               .sizeimage = 1600 * 1200,
-               .colorspace = V4L2_COLORSPACE_SRGB},
-};
-static const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
-       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 800,
-               .sizeimage = 800 * 600,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {1024, 768, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 1024,
-               .sizeimage = 1024 * 768,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 1600,
-               .sizeimage = 1600 * 1200,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-       {2048, 1536, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 2048,
-               .sizeimage = 2048 * 1536,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-static const struct v4l2_pix_format ovfx2_ov9600_mode[] = {
-       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 1280,
-               .sizeimage = 1280 * 1024,
-               .colorspace = V4L2_COLORSPACE_SRGB},
-};
-
-/* Registers common to OV511 / OV518 */
-#define R51x_FIFO_PSIZE                        0x30    /* 2 bytes wide w/ OV518(+) */
-#define R51x_SYS_RESET                 0x50
-       /* Reset type flags */
-       #define OV511_RESET_OMNICE      0x08
-#define R51x_SYS_INIT                  0x53
-#define R51x_SYS_SNAP                  0x52
-#define R51x_SYS_CUST_ID               0x5f
-#define R51x_COMP_LUT_BEGIN            0x80
-
-/* OV511 Camera interface register numbers */
-#define R511_CAM_DELAY                 0x10
-#define R511_CAM_EDGE                  0x11
-#define R511_CAM_PXCNT                 0x12
-#define R511_CAM_LNCNT                 0x13
-#define R511_CAM_PXDIV                 0x14
-#define R511_CAM_LNDIV                 0x15
-#define R511_CAM_UV_EN                 0x16
-#define R511_CAM_LINE_MODE             0x17
-#define R511_CAM_OPTS                  0x18
-
-#define R511_SNAP_FRAME                        0x19
-#define R511_SNAP_PXCNT                        0x1a
-#define R511_SNAP_LNCNT                        0x1b
-#define R511_SNAP_PXDIV                        0x1c
-#define R511_SNAP_LNDIV                        0x1d
-#define R511_SNAP_UV_EN                        0x1e
-#define R511_SNAP_OPTS                 0x1f
-
-#define R511_DRAM_FLOW_CTL             0x20
-#define R511_FIFO_OPTS                 0x31
-#define R511_I2C_CTL                   0x40
-#define R511_SYS_LED_CTL               0x55    /* OV511+ only */
-#define R511_COMP_EN                   0x78
-#define R511_COMP_LUT_EN               0x79
-
-/* OV518 Camera interface register numbers */
-#define R518_GPIO_OUT                  0x56    /* OV518(+) only */
-#define R518_GPIO_CTL                  0x57    /* OV518(+) only */
-
-/* OV519 Camera interface register numbers */
-#define OV519_R10_H_SIZE               0x10
-#define OV519_R11_V_SIZE               0x11
-#define OV519_R12_X_OFFSETL            0x12
-#define OV519_R13_X_OFFSETH            0x13
-#define OV519_R14_Y_OFFSETL            0x14
-#define OV519_R15_Y_OFFSETH            0x15
-#define OV519_R16_DIVIDER              0x16
-#define OV519_R20_DFR                  0x20
-#define OV519_R25_FORMAT               0x25
-
-/* OV519 System Controller register numbers */
-#define OV519_R51_RESET1               0x51
-#define OV519_R54_EN_CLK1              0x54
-#define OV519_R57_SNAPSHOT             0x57
-
-#define OV519_GPIO_DATA_OUT0           0x71
-#define OV519_GPIO_IO_CTRL0            0x72
-
-/*#define OV511_ENDPOINT_ADDRESS 1      * Isoc endpoint number */
-
-/*
- * The FX2 chip does not give us a zero length read at end of frame.
- * It does, however, give a short read at the end of a frame, if
- * necessary, rather than run two frames together.
- *
- * By choosing the right bulk transfer size, we are guaranteed to always
- * get a short read for the last read of each frame.  Frame sizes are
- * always a composite number (width * height, or a multiple) so if we
- * choose a prime number, we are guaranteed that the last read of a
- * frame will be short.
- *
- * But it isn't that easy: the 2.6 kernel requires a multiple of 4KB,
- * otherwise EOVERFLOW "babbling" errors occur.  I have not been able
- * to figure out why.  [PMiller]
- *
- * The constant (13 * 4096) is the largest "prime enough" number less than 64KB.
- *
- * It isn't enough to know the number of bytes per frame, in case we
- * have data dropouts or buffer overruns (even though the FX2 double
- * buffers, there are some pretty strict real time constraints for
- * isochronous transfer for larger frame sizes).
- */
-/*jfm: this value does not work for 800x600 - see isoc_init */
-#define OVFX2_BULK_SIZE (13 * 4096)
-
-/* I2C registers */
-#define R51x_I2C_W_SID         0x41
-#define R51x_I2C_SADDR_3       0x42
-#define R51x_I2C_SADDR_2       0x43
-#define R51x_I2C_R_SID         0x44
-#define R51x_I2C_DATA          0x45
-#define R518_I2C_CTL           0x47    /* OV518(+) only */
-#define OVFX2_I2C_ADDR         0x00
-
-/* I2C ADDRESSES */
-#define OV7xx0_SID   0x42
-#define OV_HIRES_SID 0x60              /* OV9xxx / OV2xxx / OV3xxx */
-#define OV8xx0_SID   0xa0
-#define OV6xx0_SID   0xc0
-
-/* OV7610 registers */
-#define OV7610_REG_GAIN                0x00    /* gain setting (5:0) */
-#define OV7610_REG_BLUE                0x01    /* blue channel balance */
-#define OV7610_REG_RED         0x02    /* red channel balance */
-#define OV7610_REG_SAT         0x03    /* saturation */
-#define OV8610_REG_HUE         0x04    /* 04 reserved */
-#define OV7610_REG_CNT         0x05    /* Y contrast */
-#define OV7610_REG_BRT         0x06    /* Y brightness */
-#define OV7610_REG_COM_C       0x14    /* misc common regs */
-#define OV7610_REG_ID_HIGH     0x1c    /* manufacturer ID MSB */
-#define OV7610_REG_ID_LOW      0x1d    /* manufacturer ID LSB */
-#define OV7610_REG_COM_I       0x29    /* misc settings */
-
-/* OV7660 and OV7670 registers */
-#define OV7670_R00_GAIN                0x00    /* Gain lower 8 bits (rest in vref) */
-#define OV7670_R01_BLUE                0x01    /* blue gain */
-#define OV7670_R02_RED         0x02    /* red gain */
-#define OV7670_R03_VREF                0x03    /* Pieces of GAIN, VSTART, VSTOP */
-#define OV7670_R04_COM1                0x04    /* Control 1 */
-/*#define OV7670_R07_AECHH     0x07     * AEC MS 5 bits */
-#define OV7670_R0C_COM3                0x0c    /* Control 3 */
-#define OV7670_R0D_COM4                0x0d    /* Control 4 */
-#define OV7670_R0E_COM5                0x0e    /* All "reserved" */
-#define OV7670_R0F_COM6                0x0f    /* Control 6 */
-#define OV7670_R10_AECH                0x10    /* More bits of AEC value */
-#define OV7670_R11_CLKRC       0x11    /* Clock control */
-#define OV7670_R12_COM7                0x12    /* Control 7 */
-#define   OV7670_COM7_FMT_VGA   0x00
-/*#define   OV7670_COM7_YUV     0x00    * YUV */
-#define   OV7670_COM7_FMT_QVGA  0x10   /* QVGA format */
-#define   OV7670_COM7_FMT_MASK  0x38
-#define   OV7670_COM7_RESET     0x80   /* Register reset */
-#define OV7670_R13_COM8                0x13    /* Control 8 */
-#define   OV7670_COM8_AEC       0x01   /* Auto exposure enable */
-#define   OV7670_COM8_AWB       0x02   /* White balance enable */
-#define   OV7670_COM8_AGC       0x04   /* Auto gain enable */
-#define   OV7670_COM8_BFILT     0x20   /* Band filter enable */
-#define   OV7670_COM8_AECSTEP   0x40   /* Unlimited AEC step size */
-#define   OV7670_COM8_FASTAEC   0x80   /* Enable fast AGC/AEC */
-#define OV7670_R14_COM9                0x14    /* Control 9 - gain ceiling */
-#define OV7670_R15_COM10       0x15    /* Control 10 */
-#define OV7670_R17_HSTART      0x17    /* Horiz start high bits */
-#define OV7670_R18_HSTOP       0x18    /* Horiz stop high bits */
-#define OV7670_R19_VSTART      0x19    /* Vert start high bits */
-#define OV7670_R1A_VSTOP       0x1a    /* Vert stop high bits */
-#define OV7670_R1E_MVFP                0x1e    /* Mirror / vflip */
-#define   OV7670_MVFP_VFLIP     0x10   /* vertical flip */
-#define   OV7670_MVFP_MIRROR    0x20   /* Mirror image */
-#define OV7670_R24_AEW         0x24    /* AGC upper limit */
-#define OV7670_R25_AEB         0x25    /* AGC lower limit */
-#define OV7670_R26_VPT         0x26    /* AGC/AEC fast mode op region */
-#define OV7670_R32_HREF                0x32    /* HREF pieces */
-#define OV7670_R3A_TSLB                0x3a    /* lots of stuff */
-#define OV7670_R3B_COM11       0x3b    /* Control 11 */
-#define   OV7670_COM11_EXP      0x02
-#define   OV7670_COM11_HZAUTO   0x10   /* Auto detect 50/60 Hz */
-#define OV7670_R3C_COM12       0x3c    /* Control 12 */
-#define OV7670_R3D_COM13       0x3d    /* Control 13 */
-#define   OV7670_COM13_GAMMA    0x80   /* Gamma enable */
-#define   OV7670_COM13_UVSAT    0x40   /* UV saturation auto adjustment */
-#define OV7670_R3E_COM14       0x3e    /* Control 14 */
-#define OV7670_R3F_EDGE                0x3f    /* Edge enhancement factor */
-#define OV7670_R40_COM15       0x40    /* Control 15 */
-/*#define   OV7670_COM15_R00FF  0xc0    *      00 to FF */
-#define OV7670_R41_COM16       0x41    /* Control 16 */
-#define   OV7670_COM16_AWBGAIN  0x08   /* AWB gain enable */
-/* end of ov7660 common registers */
-#define OV7670_R55_BRIGHT      0x55    /* Brightness */
-#define OV7670_R56_CONTRAS     0x56    /* Contrast control */
-#define OV7670_R69_GFIX                0x69    /* Fix gain control */
-/*#define OV7670_R8C_RGB444    0x8c     * RGB 444 control */
-#define OV7670_R9F_HAECC1      0x9f    /* Hist AEC/AGC control 1 */
-#define OV7670_RA0_HAECC2      0xa0    /* Hist AEC/AGC control 2 */
-#define OV7670_RA5_BD50MAX     0xa5    /* 50hz banding step limit */
-#define OV7670_RA6_HAECC3      0xa6    /* Hist AEC/AGC control 3 */
-#define OV7670_RA7_HAECC4      0xa7    /* Hist AEC/AGC control 4 */
-#define OV7670_RA8_HAECC5      0xa8    /* Hist AEC/AGC control 5 */
-#define OV7670_RA9_HAECC6      0xa9    /* Hist AEC/AGC control 6 */
-#define OV7670_RAA_HAECC7      0xaa    /* Hist AEC/AGC control 7 */
-#define OV7670_RAB_BD60MAX     0xab    /* 60hz banding step limit */
-
-struct ov_regvals {
-       u8 reg;
-       u8 val;
-};
-struct ov_i2c_regvals {
-       u8 reg;
-       u8 val;
-};
-
-/* Settings for OV2610 camera chip */
-static const struct ov_i2c_regvals norm_2610[] = {
-       { 0x12, 0x80 }, /* reset */
-};
-
-static const struct ov_i2c_regvals norm_2610ae[] = {
-       {0x12, 0x80},   /* reset */
-       {0x13, 0xcd},
-       {0x09, 0x01},
-       {0x0d, 0x00},
-       {0x11, 0x80},
-       {0x12, 0x20},   /* 1600x1200 */
-       {0x33, 0x0c},
-       {0x35, 0x90},
-       {0x36, 0x37},
-/* ms-win traces */
-       {0x11, 0x83},   /* clock / 3 ? */
-       {0x2d, 0x00},   /* 60 Hz filter */
-       {0x24, 0xb0},   /* normal colors */
-       {0x25, 0x90},
-       {0x10, 0x43},
-};
-
-static const struct ov_i2c_regvals norm_3620b[] = {
-       /*
-        * From the datasheet: "Note that after writing to register COMH
-        * (0x12) to change the sensor mode, registers related to the
-        * sensor’s cropping window will be reset back to their default
-        * values."
-        *
-        * "wait 4096 external clock ... to make sure the sensor is
-        * stable and ready to access registers" i.e. 160us at 24MHz
-        */
-       { 0x12, 0x80 }, /* COMH reset */
-       { 0x12, 0x00 }, /* QXGA, master */
-
-       /*
-        * 11 CLKRC "Clock Rate Control"
-        * [7] internal frequency doublers: on
-        * [6] video port mode: master
-        * [5:0] clock divider: 1
-        */
-       { 0x11, 0x80 },
-
-       /*
-        * 13 COMI "Common Control I"
-        *                  = 192 (0xC0) 11000000
-        *    COMI[7] "AEC speed selection"
-        *                  =   1 (0x01) 1....... "Faster AEC correction"
-        *    COMI[6] "AEC speed step selection"
-        *                  =   1 (0x01) .1...... "Big steps, fast"
-        *    COMI[5] "Banding filter on off"
-        *                  =   0 (0x00) ..0..... "Off"
-        *    COMI[4] "Banding filter option"
-        *                  =   0 (0x00) ...0.... "Main clock is 48 MHz and
-        *                                         the PLL is ON"
-        *    COMI[3] "Reserved"
-        *                  =   0 (0x00) ....0...
-        *    COMI[2] "AGC auto manual control selection"
-        *                  =   0 (0x00) .....0.. "Manual"
-        *    COMI[1] "AWB auto manual control selection"
-        *                  =   0 (0x00) ......0. "Manual"
-        *    COMI[0] "Exposure control"
-        *                  =   0 (0x00) .......0 "Manual"
-        */
-       { 0x13, 0xc0 },
-
-       /*
-        * 09 COMC "Common Control C"
-        *                  =   8 (0x08) 00001000
-        *    COMC[7:5] "Reserved"
-        *                  =   0 (0x00) 000.....
-        *    COMC[4] "Sleep Mode Enable"
-        *                  =   0 (0x00) ...0.... "Normal mode"
-        *    COMC[3:2] "Sensor sampling reset timing selection"
-        *                  =   2 (0x02) ....10.. "Longer reset time"
-        *    COMC[1:0] "Output drive current select"
-        *                  =   0 (0x00) ......00 "Weakest"
-        */
-       { 0x09, 0x08 },
-
-       /*
-        * 0C COMD "Common Control D"
-        *                  =   8 (0x08) 00001000
-        *    COMD[7] "Reserved"
-        *                  =   0 (0x00) 0.......
-        *    COMD[6] "Swap MSB and LSB at the output port"
-        *                  =   0 (0x00) .0...... "False"
-        *    COMD[5:3] "Reserved"
-        *                  =   1 (0x01) ..001...
-        *    COMD[2] "Output Average On Off"
-        *                  =   0 (0x00) .....0.. "Output Normal"
-        *    COMD[1] "Sensor precharge voltage selection"
-        *                  =   0 (0x00) ......0. "Selects internal
-        *                                         reference precharge
-        *                                         voltage"
-        *    COMD[0] "Snapshot option"
-        *                  =   0 (0x00) .......0 "Enable live video output
-        *                                         after snapshot sequence"
-        */
-       { 0x0c, 0x08 },
-
-       /*
-        * 0D COME "Common Control E"
-        *                  = 161 (0xA1) 10100001
-        *    COME[7] "Output average option"
-        *                  =   1 (0x01) 1....... "Output average of 4 pixels"
-        *    COME[6] "Anti-blooming control"
-        *                  =   0 (0x00) .0...... "Off"
-        *    COME[5:3] "Reserved"
-        *                  =   4 (0x04) ..100...
-        *    COME[2] "Clock output power down pin status"
-        *                  =   0 (0x00) .....0.. "Tri-state data output pin
-        *                                         on power down"
-        *    COME[1] "Data output pin status selection at power down"
-        *                  =   0 (0x00) ......0. "Tri-state VSYNC, PCLK,
-        *                                         HREF, and CHSYNC pins on
-        *                                         power down"
-        *    COME[0] "Auto zero circuit select"
-        *                  =   1 (0x01) .......1 "On"
-        */
-       { 0x0d, 0xa1 },
-
-       /*
-        * 0E COMF "Common Control F"
-        *                  = 112 (0x70) 01110000
-        *    COMF[7] "System clock selection"
-        *                  =   0 (0x00) 0....... "Use 24 MHz system clock"
-        *    COMF[6:4] "Reserved"
-        *                  =   7 (0x07) .111....
-        *    COMF[3] "Manual auto negative offset canceling selection"
-        *                  =   0 (0x00) ....0... "Auto detect negative
-        *                                         offset and cancel it"
-        *    COMF[2:0] "Reserved"
-        *                  =   0 (0x00) .....000
-        */
-       { 0x0e, 0x70 },
-
-       /*
-        * 0F COMG "Common Control G"
-        *                  =  66 (0x42) 01000010
-        *    COMG[7] "Optical black output selection"
-        *                  =   0 (0x00) 0....... "Disable"
-        *    COMG[6] "Black level calibrate selection"
-        *                  =   1 (0x01) .1...... "Use optical black pixels
-        *                                         to calibrate"
-        *    COMG[5:4] "Reserved"
-        *                  =   0 (0x00) ..00....
-        *    COMG[3] "Channel offset adjustment"
-        *                  =   0 (0x00) ....0... "Disable offset adjustment"
-        *    COMG[2] "ADC black level calibration option"
-        *                  =   0 (0x00) .....0.. "Use B/G line and G/R
-        *                                         line to calibrate each
-        *                                         channel's black level"
-        *    COMG[1] "Reserved"
-        *                  =   1 (0x01) ......1.
-        *    COMG[0] "ADC black level calibration enable"
-        *                  =   0 (0x00) .......0 "Disable"
-        */
-       { 0x0f, 0x42 },
-
-       /*
-        * 14 COMJ "Common Control J"
-        *                  = 198 (0xC6) 11000110
-        *    COMJ[7:6] "AGC gain ceiling"
-        *                  =   3 (0x03) 11...... "8x"
-        *    COMJ[5:4] "Reserved"
-        *                  =   0 (0x00) ..00....
-        *    COMJ[3] "Auto banding filter"
-        *                  =   0 (0x00) ....0... "Banding filter is always
-        *                                         on off depending on
-        *                                         COMI[5] setting"
-        *    COMJ[2] "VSYNC drop option"
-        *                  =   1 (0x01) .....1.. "SYNC is dropped if frame
-        *                                         data is dropped"
-        *    COMJ[1] "Frame data drop"
-        *                  =   1 (0x01) ......1. "Drop frame data if
-        *                                         exposure is not within
-        *                                         tolerance.  In AEC mode,
-        *                                         data is normally dropped
-        *                                         when data is out of
-        *                                         range."
-        *    COMJ[0] "Reserved"
-        *                  =   0 (0x00) .......0
-        */
-       { 0x14, 0xc6 },
-
-       /*
-        * 15 COMK "Common Control K"
-        *                  =   2 (0x02) 00000010
-        *    COMK[7] "CHSYNC pin output swap"
-        *                  =   0 (0x00) 0....... "CHSYNC"
-        *    COMK[6] "HREF pin output swap"
-        *                  =   0 (0x00) .0...... "HREF"
-        *    COMK[5] "PCLK output selection"
-        *                  =   0 (0x00) ..0..... "PCLK always output"
-        *    COMK[4] "PCLK edge selection"
-        *                  =   0 (0x00) ...0.... "Data valid on falling edge"
-        *    COMK[3] "HREF output polarity"
-        *                  =   0 (0x00) ....0... "positive"
-        *    COMK[2] "Reserved"
-        *                  =   0 (0x00) .....0..
-        *    COMK[1] "VSYNC polarity"
-        *                  =   1 (0x01) ......1. "negative"
-        *    COMK[0] "HSYNC polarity"
-        *                  =   0 (0x00) .......0 "positive"
-        */
-       { 0x15, 0x02 },
-
-       /*
-        * 33 CHLF "Current Control"
-        *                  =   9 (0x09) 00001001
-        *    CHLF[7:6] "Sensor current control"
-        *                  =   0 (0x00) 00......
-        *    CHLF[5] "Sensor current range control"
-        *                  =   0 (0x00) ..0..... "normal range"
-        *    CHLF[4] "Sensor current"
-        *                  =   0 (0x00) ...0.... "normal current"
-        *    CHLF[3] "Sensor buffer current control"
-        *                  =   1 (0x01) ....1... "half current"
-        *    CHLF[2] "Column buffer current control"
-        *                  =   0 (0x00) .....0.. "normal current"
-        *    CHLF[1] "Analog DSP current control"
-        *                  =   0 (0x00) ......0. "normal current"
-        *    CHLF[1] "ADC current control"
-        *                  =   0 (0x00) ......0. "normal current"
-        */
-       { 0x33, 0x09 },
-
-       /*
-        * 34 VBLM "Blooming Control"
-        *                  =  80 (0x50) 01010000
-        *    VBLM[7] "Hard soft reset switch"
-        *                  =   0 (0x00) 0....... "Hard reset"
-        *    VBLM[6:4] "Blooming voltage selection"
-        *                  =   5 (0x05) .101....
-        *    VBLM[3:0] "Sensor current control"
-        *                  =   0 (0x00) ....0000
-        */
-       { 0x34, 0x50 },
-
-       /*
-        * 36 VCHG "Sensor Precharge Voltage Control"
-        *                  =   0 (0x00) 00000000
-        *    VCHG[7] "Reserved"
-        *                  =   0 (0x00) 0.......
-        *    VCHG[6:4] "Sensor precharge voltage control"
-        *                  =   0 (0x00) .000....
-        *    VCHG[3:0] "Sensor array common reference"
-        *                  =   0 (0x00) ....0000
-        */
-       { 0x36, 0x00 },
-
-       /*
-        * 37 ADC "ADC Reference Control"
-        *                  =   4 (0x04) 00000100
-        *    ADC[7:4] "Reserved"
-        *                  =   0 (0x00) 0000....
-        *    ADC[3] "ADC input signal range"
-        *                  =   0 (0x00) ....0... "Input signal 1.0x"
-        *    ADC[2:0] "ADC range control"
-        *                  =   4 (0x04) .....100
-        */
-       { 0x37, 0x04 },
-
-       /*
-        * 38 ACOM "Analog Common Ground"
-        *                  =  82 (0x52) 01010010
-        *    ACOM[7] "Analog gain control"
-        *                  =   0 (0x00) 0....... "Gain 1x"
-        *    ACOM[6] "Analog black level calibration"
-        *                  =   1 (0x01) .1...... "On"
-        *    ACOM[5:0] "Reserved"
-        *                  =  18 (0x12) ..010010
-        */
-       { 0x38, 0x52 },
-
-       /*
-        * 3A FREFA "Internal Reference Adjustment"
-        *                  =   0 (0x00) 00000000
-        *    FREFA[7:0] "Range"
-        *                  =   0 (0x00) 00000000
-        */
-       { 0x3a, 0x00 },
-
-       /*
-        * 3C FVOPT "Internal Reference Adjustment"
-        *                  =  31 (0x1F) 00011111
-        *    FVOPT[7:0] "Range"
-        *                  =  31 (0x1F) 00011111
-        */
-       { 0x3c, 0x1f },
-
-       /*
-        * 44 Undocumented  =   0 (0x00) 00000000
-        *    44[7:0] "It's a secret"
-        *                  =   0 (0x00) 00000000
-        */
-       { 0x44, 0x00 },
-
-       /*
-        * 40 Undocumented  =   0 (0x00) 00000000
-        *    40[7:0] "It's a secret"
-        *                  =   0 (0x00) 00000000
-        */
-       { 0x40, 0x00 },
-
-       /*
-        * 41 Undocumented  =   0 (0x00) 00000000
-        *    41[7:0] "It's a secret"
-        *                  =   0 (0x00) 00000000
-        */
-       { 0x41, 0x00 },
-
-       /*
-        * 42 Undocumented  =   0 (0x00) 00000000
-        *    42[7:0] "It's a secret"
-        *                  =   0 (0x00) 00000000
-        */
-       { 0x42, 0x00 },
-
-       /*
-        * 43 Undocumented  =   0 (0x00) 00000000
-        *    43[7:0] "It's a secret"
-        *                  =   0 (0x00) 00000000
-        */
-       { 0x43, 0x00 },
-
-       /*
-        * 45 Undocumented  = 128 (0x80) 10000000
-        *    45[7:0] "It's a secret"
-        *                  = 128 (0x80) 10000000
-        */
-       { 0x45, 0x80 },
-
-       /*
-        * 48 Undocumented  = 192 (0xC0) 11000000
-        *    48[7:0] "It's a secret"
-        *                  = 192 (0xC0) 11000000
-        */
-       { 0x48, 0xc0 },
-
-       /*
-        * 49 Undocumented  =  25 (0x19) 00011001
-        *    49[7:0] "It's a secret"
-        *                  =  25 (0x19) 00011001
-        */
-       { 0x49, 0x19 },
-
-       /*
-        * 4B Undocumented  = 128 (0x80) 10000000
-        *    4B[7:0] "It's a secret"
-        *                  = 128 (0x80) 10000000
-        */
-       { 0x4b, 0x80 },
-
-       /*
-        * 4D Undocumented  = 196 (0xC4) 11000100
-        *    4D[7:0] "It's a secret"
-        *                  = 196 (0xC4) 11000100
-        */
-       { 0x4d, 0xc4 },
-
-       /*
-        * 35 VREF "Reference Voltage Control"
-        *                  =  76 (0x4c) 01001100
-        *    VREF[7:5] "Column high reference control"
-        *                  =   2 (0x02) 010..... "higher voltage"
-        *    VREF[4:2] "Column low reference control"
-        *                  =   3 (0x03) ...011.. "Highest voltage"
-        *    VREF[1:0] "Reserved"
-        *                  =   0 (0x00) ......00
-        */
-       { 0x35, 0x4c },
-
-       /*
-        * 3D Undocumented  =   0 (0x00) 00000000
-        *    3D[7:0] "It's a secret"
-        *                  =   0 (0x00) 00000000
-        */
-       { 0x3d, 0x00 },
-
-       /*
-        * 3E Undocumented  =   0 (0x00) 00000000
-        *    3E[7:0] "It's a secret"
-        *                  =   0 (0x00) 00000000
-        */
-       { 0x3e, 0x00 },
-
-       /*
-        * 3B FREFB "Internal Reference Adjustment"
-        *                  =  24 (0x18) 00011000
-        *    FREFB[7:0] "Range"
-        *                  =  24 (0x18) 00011000
-        */
-       { 0x3b, 0x18 },
-
-       /*
-        * 33 CHLF "Current Control"
-        *                  =  25 (0x19) 00011001
-        *    CHLF[7:6] "Sensor current control"
-        *                  =   0 (0x00) 00......
-        *    CHLF[5] "Sensor current range control"
-        *                  =   0 (0x00) ..0..... "normal range"
-        *    CHLF[4] "Sensor current"
-        *                  =   1 (0x01) ...1.... "double current"
-        *    CHLF[3] "Sensor buffer current control"
-        *                  =   1 (0x01) ....1... "half current"
-        *    CHLF[2] "Column buffer current control"
-        *                  =   0 (0x00) .....0.. "normal current"
-        *    CHLF[1] "Analog DSP current control"
-        *                  =   0 (0x00) ......0. "normal current"
-        *    CHLF[1] "ADC current control"
-        *                  =   0 (0x00) ......0. "normal current"
-        */
-       { 0x33, 0x19 },
-
-       /*
-        * 34 VBLM "Blooming Control"
-        *                  =  90 (0x5A) 01011010
-        *    VBLM[7] "Hard soft reset switch"
-        *                  =   0 (0x00) 0....... "Hard reset"
-        *    VBLM[6:4] "Blooming voltage selection"
-        *                  =   5 (0x05) .101....
-        *    VBLM[3:0] "Sensor current control"
-        *                  =  10 (0x0A) ....1010
-        */
-       { 0x34, 0x5a },
-
-       /*
-        * 3B FREFB "Internal Reference Adjustment"
-        *                  =   0 (0x00) 00000000
-        *    FREFB[7:0] "Range"
-        *                  =   0 (0x00) 00000000
-        */
-       { 0x3b, 0x00 },
-
-       /*
-        * 33 CHLF "Current Control"
-        *                  =   9 (0x09) 00001001
-        *    CHLF[7:6] "Sensor current control"
-        *                  =   0 (0x00) 00......
-        *    CHLF[5] "Sensor current range control"
-        *                  =   0 (0x00) ..0..... "normal range"
-        *    CHLF[4] "Sensor current"
-        *                  =   0 (0x00) ...0.... "normal current"
-        *    CHLF[3] "Sensor buffer current control"
-        *                  =   1 (0x01) ....1... "half current"
-        *    CHLF[2] "Column buffer current control"
-        *                  =   0 (0x00) .....0.. "normal current"
-        *    CHLF[1] "Analog DSP current control"
-        *                  =   0 (0x00) ......0. "normal current"
-        *    CHLF[1] "ADC current control"
-        *                  =   0 (0x00) ......0. "normal current"
-        */
-       { 0x33, 0x09 },
-
-       /*
-        * 34 VBLM "Blooming Control"
-        *                  =  80 (0x50) 01010000
-        *    VBLM[7] "Hard soft reset switch"
-        *                  =   0 (0x00) 0....... "Hard reset"
-        *    VBLM[6:4] "Blooming voltage selection"
-        *                  =   5 (0x05) .101....
-        *    VBLM[3:0] "Sensor current control"
-        *                  =   0 (0x00) ....0000
-        */
-       { 0x34, 0x50 },
-
-       /*
-        * 12 COMH "Common Control H"
-        *                  =  64 (0x40) 01000000
-        *    COMH[7] "SRST"
-        *                  =   0 (0x00) 0....... "No-op"
-        *    COMH[6:4] "Resolution selection"
-        *                  =   4 (0x04) .100.... "XGA"
-        *    COMH[3] "Master slave selection"
-        *                  =   0 (0x00) ....0... "Master mode"
-        *    COMH[2] "Internal B/R channel option"
-        *                  =   0 (0x00) .....0.. "B/R use same channel"
-        *    COMH[1] "Color bar test pattern"
-        *                  =   0 (0x00) ......0. "Off"
-        *    COMH[0] "Reserved"
-        *                  =   0 (0x00) .......0
-        */
-       { 0x12, 0x40 },
-
-       /*
-        * 17 HREFST "Horizontal window start"
-        *                  =  31 (0x1F) 00011111
-        *    HREFST[7:0] "Horizontal window start, 8 MSBs"
-        *                  =  31 (0x1F) 00011111
-        */
-       { 0x17, 0x1f },
-
-       /*
-        * 18 HREFEND "Horizontal window end"
-        *                  =  95 (0x5F) 01011111
-        *    HREFEND[7:0] "Horizontal Window End, 8 MSBs"
-        *                  =  95 (0x5F) 01011111
-        */
-       { 0x18, 0x5f },
-
-       /*
-        * 19 VSTRT "Vertical window start"
-        *                  =   0 (0x00) 00000000
-        *    VSTRT[7:0] "Vertical Window Start, 8 MSBs"
-        *                  =   0 (0x00) 00000000
-        */
-       { 0x19, 0x00 },
-
-       /*
-        * 1A VEND "Vertical window end"
-        *                  =  96 (0x60) 01100000
-        *    VEND[7:0] "Vertical Window End, 8 MSBs"
-        *                  =  96 (0x60) 01100000
-        */
-       { 0x1a, 0x60 },
-
-       /*
-        * 32 COMM "Common Control M"
-        *                  =  18 (0x12) 00010010
-        *    COMM[7:6] "Pixel clock divide option"
-        *                  =   0 (0x00) 00...... "/1"
-        *    COMM[5:3] "Horizontal window end position, 3 LSBs"
-        *                  =   2 (0x02) ..010...
-        *    COMM[2:0] "Horizontal window start position, 3 LSBs"
-        *                  =   2 (0x02) .....010
-        */
-       { 0x32, 0x12 },
-
-       /*
-        * 03 COMA "Common Control A"
-        *                  =  74 (0x4A) 01001010
-        *    COMA[7:4] "AWB Update Threshold"
-        *                  =   4 (0x04) 0100....
-        *    COMA[3:2] "Vertical window end line control 2 LSBs"
-        *                  =   2 (0x02) ....10..
-        *    COMA[1:0] "Vertical window start line control 2 LSBs"
-        *                  =   2 (0x02) ......10
-        */
-       { 0x03, 0x4a },
-
-       /*
-        * 11 CLKRC "Clock Rate Control"
-        *                  = 128 (0x80) 10000000
-        *    CLKRC[7] "Internal frequency doublers on off seclection"
-        *                  =   1 (0x01) 1....... "On"
-        *    CLKRC[6] "Digital video master slave selection"
-        *                  =   0 (0x00) .0...... "Master mode, sensor
-        *                                         provides PCLK"
-        *    CLKRC[5:0] "Clock divider { CLK = PCLK/(1+CLKRC[5:0]) }"
-        *                  =   0 (0x00) ..000000
-        */
-       { 0x11, 0x80 },
-
-       /*
-        * 12 COMH "Common Control H"
-        *                  =   0 (0x00) 00000000
-        *    COMH[7] "SRST"
-        *                  =   0 (0x00) 0....... "No-op"
-        *    COMH[6:4] "Resolution selection"
-        *                  =   0 (0x00) .000.... "QXGA"
-        *    COMH[3] "Master slave selection"
-        *                  =   0 (0x00) ....0... "Master mode"
-        *    COMH[2] "Internal B/R channel option"
-        *                  =   0 (0x00) .....0.. "B/R use same channel"
-        *    COMH[1] "Color bar test pattern"
-        *                  =   0 (0x00) ......0. "Off"
-        *    COMH[0] "Reserved"
-        *                  =   0 (0x00) .......0
-        */
-       { 0x12, 0x00 },
-
-       /*
-        * 12 COMH "Common Control H"
-        *                  =  64 (0x40) 01000000
-        *    COMH[7] "SRST"
-        *                  =   0 (0x00) 0....... "No-op"
-        *    COMH[6:4] "Resolution selection"
-        *                  =   4 (0x04) .100.... "XGA"
-        *    COMH[3] "Master slave selection"
-        *                  =   0 (0x00) ....0... "Master mode"
-        *    COMH[2] "Internal B/R channel option"
-        *                  =   0 (0x00) .....0.. "B/R use same channel"
-        *    COMH[1] "Color bar test pattern"
-        *                  =   0 (0x00) ......0. "Off"
-        *    COMH[0] "Reserved"
-        *                  =   0 (0x00) .......0
-        */
-       { 0x12, 0x40 },
-
-       /*
-        * 17 HREFST "Horizontal window start"
-        *                  =  31 (0x1F) 00011111
-        *    HREFST[7:0] "Horizontal window start, 8 MSBs"
-        *                  =  31 (0x1F) 00011111
-        */
-       { 0x17, 0x1f },
-
-       /*
-        * 18 HREFEND "Horizontal window end"
-        *                  =  95 (0x5F) 01011111
-        *    HREFEND[7:0] "Horizontal Window End, 8 MSBs"
-        *                  =  95 (0x5F) 01011111
-        */
-       { 0x18, 0x5f },
-
-       /*
-        * 19 VSTRT "Vertical window start"
-        *                  =   0 (0x00) 00000000
-        *    VSTRT[7:0] "Vertical Window Start, 8 MSBs"
-        *                  =   0 (0x00) 00000000
-        */
-       { 0x19, 0x00 },
-
-       /*
-        * 1A VEND "Vertical window end"
-        *                  =  96 (0x60) 01100000
-        *    VEND[7:0] "Vertical Window End, 8 MSBs"
-        *                  =  96 (0x60) 01100000
-        */
-       { 0x1a, 0x60 },
-
-       /*
-        * 32 COMM "Common Control M"
-        *                  =  18 (0x12) 00010010
-        *    COMM[7:6] "Pixel clock divide option"
-        *                  =   0 (0x00) 00...... "/1"
-        *    COMM[5:3] "Horizontal window end position, 3 LSBs"
-        *                  =   2 (0x02) ..010...
-        *    COMM[2:0] "Horizontal window start position, 3 LSBs"
-        *                  =   2 (0x02) .....010
-        */
-       { 0x32, 0x12 },
-
-       /*
-        * 03 COMA "Common Control A"
-        *                  =  74 (0x4A) 01001010
-        *    COMA[7:4] "AWB Update Threshold"
-        *                  =   4 (0x04) 0100....
-        *    COMA[3:2] "Vertical window end line control 2 LSBs"
-        *                  =   2 (0x02) ....10..
-        *    COMA[1:0] "Vertical window start line control 2 LSBs"
-        *                  =   2 (0x02) ......10
-        */
-       { 0x03, 0x4a },
-
-       /*
-        * 02 RED "Red Gain Control"
-        *                  = 175 (0xAF) 10101111
-        *    RED[7] "Action"
-        *                  =   1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))"
-        *    RED[6:0] "Value"
-        *                  =  47 (0x2F) .0101111
-        */
-       { 0x02, 0xaf },
-
-       /*
-        * 2D ADDVSL "VSYNC Pulse Width"
-        *                  = 210 (0xD2) 11010010
-        *    ADDVSL[7:0] "VSYNC pulse width, LSB"
-        *                  = 210 (0xD2) 11010010
-        */
-       { 0x2d, 0xd2 },
-
-       /*
-        * 00 GAIN          =  24 (0x18) 00011000
-        *    GAIN[7:6] "Reserved"
-        *                  =   0 (0x00) 00......
-        *    GAIN[5] "Double"
-        *                  =   0 (0x00) ..0..... "False"
-        *    GAIN[4] "Double"
-        *                  =   1 (0x01) ...1.... "True"
-        *    GAIN[3:0] "Range"
-        *                  =   8 (0x08) ....1000
-        */
-       { 0x00, 0x18 },
-
-       /*
-        * 01 BLUE "Blue Gain Control"
-        *                  = 240 (0xF0) 11110000
-        *    BLUE[7] "Action"
-        *                  =   1 (0x01) 1....... "gain = 1/(1+bitrev([6:0]))"
-        *    BLUE[6:0] "Value"
-        *                  = 112 (0x70) .1110000
-        */
-       { 0x01, 0xf0 },
-
-       /*
-        * 10 AEC "Automatic Exposure Control"
-        *                  =  10 (0x0A) 00001010
-        *    AEC[7:0] "Automatic Exposure Control, 8 MSBs"
-        *                  =  10 (0x0A) 00001010
-        */
-       { 0x10, 0x0a },
-
-       { 0xe1, 0x67 },
-       { 0xe3, 0x03 },
-       { 0xe4, 0x26 },
-       { 0xe5, 0x3e },
-       { 0xf8, 0x01 },
-       { 0xff, 0x01 },
-};
-
-static const struct ov_i2c_regvals norm_6x20[] = {
-       { 0x12, 0x80 }, /* reset */
-       { 0x11, 0x01 },
-       { 0x03, 0x60 },
-       { 0x05, 0x7f }, /* For when autoadjust is off */
-       { 0x07, 0xa8 },
-       /* The ratio of 0x0c and 0x0d controls the white point */
-       { 0x0c, 0x24 },
-       { 0x0d, 0x24 },
-       { 0x0f, 0x15 }, /* COMS */
-       { 0x10, 0x75 }, /* AEC Exposure time */
-       { 0x12, 0x24 }, /* Enable AGC */
-       { 0x14, 0x04 },
-       /* 0x16: 0x06 helps frame stability with moving objects */
-       { 0x16, 0x06 },
-/*     { 0x20, 0x30 },  * Aperture correction enable */
-       { 0x26, 0xb2 }, /* BLC enable */
-       /* 0x28: 0x05 Selects RGB format if RGB on */
-       { 0x28, 0x05 },
-       { 0x2a, 0x04 }, /* Disable framerate adjust */
-/*     { 0x2b, 0xac },  * Framerate; Set 2a[7] first */
-       { 0x2d, 0x85 },
-       { 0x33, 0xa0 }, /* Color Processing Parameter */
-       { 0x34, 0xd2 }, /* Max A/D range */
-       { 0x38, 0x8b },
-       { 0x39, 0x40 },
-
-       { 0x3c, 0x39 }, /* Enable AEC mode changing */
-       { 0x3c, 0x3c }, /* Change AEC mode */
-       { 0x3c, 0x24 }, /* Disable AEC mode changing */
-
-       { 0x3d, 0x80 },
-       /* These next two registers (0x4a, 0x4b) are undocumented.
-        * They control the color balance */
-       { 0x4a, 0x80 },
-       { 0x4b, 0x80 },
-       { 0x4d, 0xd2 }, /* This reduces noise a bit */
-       { 0x4e, 0xc1 },
-       { 0x4f, 0x04 },
-/* Do 50-53 have any effect? */
-/* Toggle 0x12[2] off and on here? */
-};
-
-static const struct ov_i2c_regvals norm_6x30[] = {
-       { 0x12, 0x80 }, /* Reset */
-       { 0x00, 0x1f }, /* Gain */
-       { 0x01, 0x99 }, /* Blue gain */
-       { 0x02, 0x7c }, /* Red gain */
-       { 0x03, 0xc0 }, /* Saturation */
-       { 0x05, 0x0a }, /* Contrast */
-       { 0x06, 0x95 }, /* Brightness */
-       { 0x07, 0x2d }, /* Sharpness */
-       { 0x0c, 0x20 },
-       { 0x0d, 0x20 },
-       { 0x0e, 0xa0 }, /* Was 0x20, bit7 enables a 2x gain which we need */
-       { 0x0f, 0x05 },
-       { 0x10, 0x9a },
-       { 0x11, 0x00 }, /* Pixel clock = fastest */
-       { 0x12, 0x24 }, /* Enable AGC and AWB */
-       { 0x13, 0x21 },
-       { 0x14, 0x80 },
-       { 0x15, 0x01 },
-       { 0x16, 0x03 },
-       { 0x17, 0x38 },
-       { 0x18, 0xea },
-       { 0x19, 0x04 },
-       { 0x1a, 0x93 },
-       { 0x1b, 0x00 },
-       { 0x1e, 0xc4 },
-       { 0x1f, 0x04 },
-       { 0x20, 0x20 },
-       { 0x21, 0x10 },
-       { 0x22, 0x88 },
-       { 0x23, 0xc0 }, /* Crystal circuit power level */
-       { 0x25, 0x9a }, /* Increase AEC black ratio */
-       { 0x26, 0xb2 }, /* BLC enable */
-       { 0x27, 0xa2 },
-       { 0x28, 0x00 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x84 }, /* 60 Hz power */
-       { 0x2b, 0xa8 }, /* 60 Hz power */
-       { 0x2c, 0xa0 },
-       { 0x2d, 0x95 }, /* Enable auto-brightness */
-       { 0x2e, 0x88 },
-       { 0x33, 0x26 },
-       { 0x34, 0x03 },
-       { 0x36, 0x8f },
-       { 0x37, 0x80 },
-       { 0x38, 0x83 },
-       { 0x39, 0x80 },
-       { 0x3a, 0x0f },
-       { 0x3b, 0x3c },
-       { 0x3c, 0x1a },
-       { 0x3d, 0x80 },
-       { 0x3e, 0x80 },
-       { 0x3f, 0x0e },
-       { 0x40, 0x00 }, /* White bal */
-       { 0x41, 0x00 }, /* White bal */
-       { 0x42, 0x80 },
-       { 0x43, 0x3f }, /* White bal */
-       { 0x44, 0x80 },
-       { 0x45, 0x20 },
-       { 0x46, 0x20 },
-       { 0x47, 0x80 },
-       { 0x48, 0x7f },
-       { 0x49, 0x00 },
-       { 0x4a, 0x00 },
-       { 0x4b, 0x80 },
-       { 0x4c, 0xd0 },
-       { 0x4d, 0x10 }, /* U = 0.563u, V = 0.714v */
-       { 0x4e, 0x40 },
-       { 0x4f, 0x07 }, /* UV avg., col. killer: max */
-       { 0x50, 0xff },
-       { 0x54, 0x23 }, /* Max AGC gain: 18dB */
-       { 0x55, 0xff },
-       { 0x56, 0x12 },
-       { 0x57, 0x81 },
-       { 0x58, 0x75 },
-       { 0x59, 0x01 }, /* AGC dark current comp.: +1 */
-       { 0x5a, 0x2c },
-       { 0x5b, 0x0f }, /* AWB chrominance levels */
-       { 0x5c, 0x10 },
-       { 0x3d, 0x80 },
-       { 0x27, 0xa6 },
-       { 0x12, 0x20 }, /* Toggle AWB */
-       { 0x12, 0x24 },
-};
-
-/* Lawrence Glaister <lg@jfm.bc.ca> reports:
- *
- * Register 0x0f in the 7610 has the following effects:
- *
- * 0x85 (AEC method 1): Best overall, good contrast range
- * 0x45 (AEC method 2): Very overexposed
- * 0xa5 (spec sheet default): Ok, but the black level is
- *     shifted resulting in loss of contrast
- * 0x05 (old driver setting): very overexposed, too much
- *     contrast
- */
-static const struct ov_i2c_regvals norm_7610[] = {
-       { 0x10, 0xff },
-       { 0x16, 0x06 },
-       { 0x28, 0x24 },
-       { 0x2b, 0xac },
-       { 0x12, 0x00 },
-       { 0x38, 0x81 },
-       { 0x28, 0x24 }, /* 0c */
-       { 0x0f, 0x85 }, /* lg's setting */
-       { 0x15, 0x01 },
-       { 0x20, 0x1c },
-       { 0x23, 0x2a },
-       { 0x24, 0x10 },
-       { 0x25, 0x8a },
-       { 0x26, 0xa2 },
-       { 0x27, 0xc2 },
-       { 0x2a, 0x04 },
-       { 0x2c, 0xfe },
-       { 0x2d, 0x93 },
-       { 0x30, 0x71 },
-       { 0x31, 0x60 },
-       { 0x32, 0x26 },
-       { 0x33, 0x20 },
-       { 0x34, 0x48 },
-       { 0x12, 0x24 },
-       { 0x11, 0x01 },
-       { 0x0c, 0x24 },
-       { 0x0d, 0x24 },
-};
-
-static const struct ov_i2c_regvals norm_7620[] = {
-       { 0x12, 0x80 },         /* reset */
-       { 0x00, 0x00 },         /* gain */
-       { 0x01, 0x80 },         /* blue gain */
-       { 0x02, 0x80 },         /* red gain */
-       { 0x03, 0xc0 },         /* OV7670_R03_VREF */
-       { 0x06, 0x60 },
-       { 0x07, 0x00 },
-       { 0x0c, 0x24 },
-       { 0x0c, 0x24 },
-       { 0x0d, 0x24 },
-       { 0x11, 0x01 },
-       { 0x12, 0x24 },
-       { 0x13, 0x01 },
-       { 0x14, 0x84 },
-       { 0x15, 0x01 },
-       { 0x16, 0x03 },
-       { 0x17, 0x2f },
-       { 0x18, 0xcf },
-       { 0x19, 0x06 },
-       { 0x1a, 0xf5 },
-       { 0x1b, 0x00 },
-       { 0x20, 0x18 },
-       { 0x21, 0x80 },
-       { 0x22, 0x80 },
-       { 0x23, 0x00 },
-       { 0x26, 0xa2 },
-       { 0x27, 0xea },
-       { 0x28, 0x22 }, /* Was 0x20, bit1 enables a 2x gain which we need */
-       { 0x29, 0x00 },
-       { 0x2a, 0x10 },
-       { 0x2b, 0x00 },
-       { 0x2c, 0x88 },
-       { 0x2d, 0x91 },
-       { 0x2e, 0x80 },
-       { 0x2f, 0x44 },
-       { 0x60, 0x27 },
-       { 0x61, 0x02 },
-       { 0x62, 0x5f },
-       { 0x63, 0xd5 },
-       { 0x64, 0x57 },
-       { 0x65, 0x83 },
-       { 0x66, 0x55 },
-       { 0x67, 0x92 },
-       { 0x68, 0xcf },
-       { 0x69, 0x76 },
-       { 0x6a, 0x22 },
-       { 0x6b, 0x00 },
-       { 0x6c, 0x02 },
-       { 0x6d, 0x44 },
-       { 0x6e, 0x80 },
-       { 0x6f, 0x1d },
-       { 0x70, 0x8b },
-       { 0x71, 0x00 },
-       { 0x72, 0x14 },
-       { 0x73, 0x54 },
-       { 0x74, 0x00 },
-       { 0x75, 0x8e },
-       { 0x76, 0x00 },
-       { 0x77, 0xff },
-       { 0x78, 0x80 },
-       { 0x79, 0x80 },
-       { 0x7a, 0x80 },
-       { 0x7b, 0xe2 },
-       { 0x7c, 0x00 },
-};
-
-/* 7640 and 7648. The defaults should be OK for most registers. */
-static const struct ov_i2c_regvals norm_7640[] = {
-       { 0x12, 0x80 },
-       { 0x12, 0x14 },
-};
-
-static const struct ov_regvals init_519_ov7660[] = {
-       { 0x5d, 0x03 }, /* Turn off suspend mode */
-       { 0x53, 0x9b }, /* 0x9f enables the (unused) microcontroller */
-       { 0x54, 0x0f }, /* bit2 (jpeg enable) */
-       { 0xa2, 0x20 }, /* a2-a5 are undocumented */
-       { 0xa3, 0x18 },
-       { 0xa4, 0x04 },
-       { 0xa5, 0x28 },
-       { 0x37, 0x00 }, /* SetUsbInit */
-       { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
-       /* Enable both fields, YUV Input, disable defect comp (why?) */
-       { 0x20, 0x0c }, /* 0x0d does U <-> V swap */
-       { 0x21, 0x38 },
-       { 0x22, 0x1d },
-       { 0x17, 0x50 }, /* undocumented */
-       { 0x37, 0x00 }, /* undocumented */
-       { 0x40, 0xff }, /* I2C timeout counter */
-       { 0x46, 0x00 }, /* I2C clock prescaler */
-};
-static const struct ov_i2c_regvals norm_7660[] = {
-       {OV7670_R12_COM7, OV7670_COM7_RESET},
-       {OV7670_R11_CLKRC, 0x81},
-       {0x92, 0x00},                   /* DM_LNL */
-       {0x93, 0x00},                   /* DM_LNH */
-       {0x9d, 0x4c},                   /* BD50ST */
-       {0x9e, 0x3f},                   /* BD60ST */
-       {OV7670_R3B_COM11, 0x02},
-       {OV7670_R13_COM8, 0xf5},
-       {OV7670_R10_AECH, 0x00},
-       {OV7670_R00_GAIN, 0x00},
-       {OV7670_R01_BLUE, 0x7c},
-       {OV7670_R02_RED, 0x9d},
-       {OV7670_R12_COM7, 0x00},
-       {OV7670_R04_COM1, 00},
-       {OV7670_R18_HSTOP, 0x01},
-       {OV7670_R17_HSTART, 0x13},
-       {OV7670_R32_HREF, 0x92},
-       {OV7670_R19_VSTART, 0x02},
-       {OV7670_R1A_VSTOP, 0x7a},
-       {OV7670_R03_VREF, 0x00},
-       {OV7670_R0E_COM5, 0x04},
-       {OV7670_R0F_COM6, 0x62},
-       {OV7670_R15_COM10, 0x00},
-       {0x16, 0x02},                   /* RSVD */
-       {0x1b, 0x00},                   /* PSHFT */
-       {OV7670_R1E_MVFP, 0x01},
-       {0x29, 0x3c},                   /* RSVD */
-       {0x33, 0x00},                   /* CHLF */
-       {0x34, 0x07},                   /* ARBLM */
-       {0x35, 0x84},                   /* RSVD */
-       {0x36, 0x00},                   /* RSVD */
-       {0x37, 0x04},                   /* ADC */
-       {0x39, 0x43},                   /* OFON */
-       {OV7670_R3A_TSLB, 0x00},
-       {OV7670_R3C_COM12, 0x6c},
-       {OV7670_R3D_COM13, 0x98},
-       {OV7670_R3F_EDGE, 0x23},
-       {OV7670_R40_COM15, 0xc1},
-       {OV7670_R41_COM16, 0x22},
-       {0x6b, 0x0a},                   /* DBLV */
-       {0xa1, 0x08},                   /* RSVD */
-       {0x69, 0x80},                   /* HV */
-       {0x43, 0xf0},                   /* RSVD.. */
-       {0x44, 0x10},
-       {0x45, 0x78},
-       {0x46, 0xa8},
-       {0x47, 0x60},
-       {0x48, 0x80},
-       {0x59, 0xba},
-       {0x5a, 0x9a},
-       {0x5b, 0x22},
-       {0x5c, 0xb9},
-       {0x5d, 0x9b},
-       {0x5e, 0x10},
-       {0x5f, 0xe0},
-       {0x60, 0x85},
-       {0x61, 0x60},
-       {0x9f, 0x9d},                   /* RSVD */
-       {0xa0, 0xa0},                   /* DSPC2 */
-       {0x4f, 0x60},                   /* matrix */
-       {0x50, 0x64},
-       {0x51, 0x04},
-       {0x52, 0x18},
-       {0x53, 0x3c},
-       {0x54, 0x54},
-       {0x55, 0x40},
-       {0x56, 0x40},
-       {0x57, 0x40},
-       {0x58, 0x0d},                   /* matrix sign */
-       {0x8b, 0xcc},                   /* RSVD */
-       {0x8c, 0xcc},
-       {0x8d, 0xcf},
-       {0x6c, 0x40},                   /* gamma curve */
-       {0x6d, 0xe0},
-       {0x6e, 0xa0},
-       {0x6f, 0x80},
-       {0x70, 0x70},
-       {0x71, 0x80},
-       {0x72, 0x60},
-       {0x73, 0x60},
-       {0x74, 0x50},
-       {0x75, 0x40},
-       {0x76, 0x38},
-       {0x77, 0x3c},
-       {0x78, 0x32},
-       {0x79, 0x1a},
-       {0x7a, 0x28},
-       {0x7b, 0x24},
-       {0x7c, 0x04},                   /* gamma curve */
-       {0x7d, 0x12},
-       {0x7e, 0x26},
-       {0x7f, 0x46},
-       {0x80, 0x54},
-       {0x81, 0x64},
-       {0x82, 0x70},
-       {0x83, 0x7c},
-       {0x84, 0x86},
-       {0x85, 0x8e},
-       {0x86, 0x9c},
-       {0x87, 0xab},
-       {0x88, 0xc4},
-       {0x89, 0xd1},
-       {0x8a, 0xe5},
-       {OV7670_R14_COM9, 0x1e},
-       {OV7670_R24_AEW, 0x80},
-       {OV7670_R25_AEB, 0x72},
-       {OV7670_R26_VPT, 0xb3},
-       {0x62, 0x80},                   /* LCC1 */
-       {0x63, 0x80},                   /* LCC2 */
-       {0x64, 0x06},                   /* LCC3 */
-       {0x65, 0x00},                   /* LCC4 */
-       {0x66, 0x01},                   /* LCC5 */
-       {0x94, 0x0e},                   /* RSVD.. */
-       {0x95, 0x14},
-       {OV7670_R13_COM8, OV7670_COM8_FASTAEC
-                       | OV7670_COM8_AECSTEP
-                       | OV7670_COM8_BFILT
-                       | 0x10
-                       | OV7670_COM8_AGC
-                       | OV7670_COM8_AWB
-                       | OV7670_COM8_AEC},
-       {0xa1, 0xc8}
-};
-static const struct ov_i2c_regvals norm_9600[] = {
-       {0x12, 0x80},
-       {0x0c, 0x28},
-       {0x11, 0x80},
-       {0x13, 0xb5},
-       {0x14, 0x3e},
-       {0x1b, 0x04},
-       {0x24, 0xb0},
-       {0x25, 0x90},
-       {0x26, 0x94},
-       {0x35, 0x90},
-       {0x37, 0x07},
-       {0x38, 0x08},
-       {0x01, 0x8e},
-       {0x02, 0x85}
-};
-
-/* 7670. Defaults taken from OmniVision provided data,
-*  as provided by Jonathan Corbet of OLPC              */
-static const struct ov_i2c_regvals norm_7670[] = {
-       { OV7670_R12_COM7, OV7670_COM7_RESET },
-       { OV7670_R3A_TSLB, 0x04 },              /* OV */
-       { OV7670_R12_COM7, OV7670_COM7_FMT_VGA }, /* VGA */
-       { OV7670_R11_CLKRC, 0x01 },
-/*
- * Set the hardware window.  These values from OV don't entirely
- * make sense - hstop is less than hstart.  But they work...
- */
-       { OV7670_R17_HSTART, 0x13 },
-       { OV7670_R18_HSTOP, 0x01 },
-       { OV7670_R32_HREF, 0xb6 },
-       { OV7670_R19_VSTART, 0x02 },
-       { OV7670_R1A_VSTOP, 0x7a },
-       { OV7670_R03_VREF, 0x0a },
-
-       { OV7670_R0C_COM3, 0x00 },
-       { OV7670_R3E_COM14, 0x00 },
-/* Mystery scaling numbers */
-       { 0x70, 0x3a },
-       { 0x71, 0x35 },
-       { 0x72, 0x11 },
-       { 0x73, 0xf0 },
-       { 0xa2, 0x02 },
-/*     { OV7670_R15_COM10, 0x0 }, */
-
-/* Gamma curve values */
-       { 0x7a, 0x20 },
-       { 0x7b, 0x10 },
-       { 0x7c, 0x1e },
-       { 0x7d, 0x35 },
-       { 0x7e, 0x5a },
-       { 0x7f, 0x69 },
-       { 0x80, 0x76 },
-       { 0x81, 0x80 },
-       { 0x82, 0x88 },
-       { 0x83, 0x8f },
-       { 0x84, 0x96 },
-       { 0x85, 0xa3 },
-       { 0x86, 0xaf },
-       { 0x87, 0xc4 },
-       { 0x88, 0xd7 },
-       { 0x89, 0xe8 },
-
-/* AGC and AEC parameters.  Note we start by disabling those features,
-   then turn them only after tweaking the values. */
-       { OV7670_R13_COM8, OV7670_COM8_FASTAEC
-                        | OV7670_COM8_AECSTEP
-                        | OV7670_COM8_BFILT },
-       { OV7670_R00_GAIN, 0x00 },
-       { OV7670_R10_AECH, 0x00 },
-       { OV7670_R0D_COM4, 0x40 }, /* magic reserved bit */
-       { OV7670_R14_COM9, 0x18 }, /* 4x gain + magic rsvd bit */
-       { OV7670_RA5_BD50MAX, 0x05 },
-       { OV7670_RAB_BD60MAX, 0x07 },
-       { OV7670_R24_AEW, 0x95 },
-       { OV7670_R25_AEB, 0x33 },
-       { OV7670_R26_VPT, 0xe3 },
-       { OV7670_R9F_HAECC1, 0x78 },
-       { OV7670_RA0_HAECC2, 0x68 },
-       { 0xa1, 0x03 }, /* magic */
-       { OV7670_RA6_HAECC3, 0xd8 },
-       { OV7670_RA7_HAECC4, 0xd8 },
-       { OV7670_RA8_HAECC5, 0xf0 },
-       { OV7670_RA9_HAECC6, 0x90 },
-       { OV7670_RAA_HAECC7, 0x94 },
-       { OV7670_R13_COM8, OV7670_COM8_FASTAEC
-                       | OV7670_COM8_AECSTEP
-                       | OV7670_COM8_BFILT
-                       | OV7670_COM8_AGC
-                       | OV7670_COM8_AEC },
-
-/* Almost all of these are magic "reserved" values.  */
-       { OV7670_R0E_COM5, 0x61 },
-       { OV7670_R0F_COM6, 0x4b },
-       { 0x16, 0x02 },
-       { OV7670_R1E_MVFP, 0x07 },
-       { 0x21, 0x02 },
-       { 0x22, 0x91 },
-       { 0x29, 0x07 },
-       { 0x33, 0x0b },
-       { 0x35, 0x0b },
-       { 0x37, 0x1d },
-       { 0x38, 0x71 },
-       { 0x39, 0x2a },
-       { OV7670_R3C_COM12, 0x78 },
-       { 0x4d, 0x40 },
-       { 0x4e, 0x20 },
-       { OV7670_R69_GFIX, 0x00 },
-       { 0x6b, 0x4a },
-       { 0x74, 0x10 },
-       { 0x8d, 0x4f },
-       { 0x8e, 0x00 },
-       { 0x8f, 0x00 },
-       { 0x90, 0x00 },
-       { 0x91, 0x00 },
-       { 0x96, 0x00 },
-       { 0x9a, 0x00 },
-       { 0xb0, 0x84 },
-       { 0xb1, 0x0c },
-       { 0xb2, 0x0e },
-       { 0xb3, 0x82 },
-       { 0xb8, 0x0a },
-
-/* More reserved magic, some of which tweaks white balance */
-       { 0x43, 0x0a },
-       { 0x44, 0xf0 },
-       { 0x45, 0x34 },
-       { 0x46, 0x58 },
-       { 0x47, 0x28 },
-       { 0x48, 0x3a },
-       { 0x59, 0x88 },
-       { 0x5a, 0x88 },
-       { 0x5b, 0x44 },
-       { 0x5c, 0x67 },
-       { 0x5d, 0x49 },
-       { 0x5e, 0x0e },
-       { 0x6c, 0x0a },
-       { 0x6d, 0x55 },
-       { 0x6e, 0x11 },
-       { 0x6f, 0x9f },                 /* "9e for advance AWB" */
-       { 0x6a, 0x40 },
-       { OV7670_R01_BLUE, 0x40 },
-       { OV7670_R02_RED, 0x60 },
-       { OV7670_R13_COM8, OV7670_COM8_FASTAEC
-                       | OV7670_COM8_AECSTEP
-                       | OV7670_COM8_BFILT
-                       | OV7670_COM8_AGC
-                       | OV7670_COM8_AEC
-                       | OV7670_COM8_AWB },
-
-/* Matrix coefficients */
-       { 0x4f, 0x80 },
-       { 0x50, 0x80 },
-       { 0x51, 0x00 },
-       { 0x52, 0x22 },
-       { 0x53, 0x5e },
-       { 0x54, 0x80 },
-       { 0x58, 0x9e },
-
-       { OV7670_R41_COM16, OV7670_COM16_AWBGAIN },
-       { OV7670_R3F_EDGE, 0x00 },
-       { 0x75, 0x05 },
-       { 0x76, 0xe1 },
-       { 0x4c, 0x00 },
-       { 0x77, 0x01 },
-       { OV7670_R3D_COM13, OV7670_COM13_GAMMA
-                         | OV7670_COM13_UVSAT
-                         | 2},         /* was 3 */
-       { 0x4b, 0x09 },
-       { 0xc9, 0x60 },
-       { OV7670_R41_COM16, 0x38 },
-       { 0x56, 0x40 },
-
-       { 0x34, 0x11 },
-       { OV7670_R3B_COM11, OV7670_COM11_EXP|OV7670_COM11_HZAUTO },
-       { 0xa4, 0x88 },
-       { 0x96, 0x00 },
-       { 0x97, 0x30 },
-       { 0x98, 0x20 },
-       { 0x99, 0x30 },
-       { 0x9a, 0x84 },
-       { 0x9b, 0x29 },
-       { 0x9c, 0x03 },
-       { 0x9d, 0x4c },
-       { 0x9e, 0x3f },
-       { 0x78, 0x04 },
-
-/* Extra-weird stuff.  Some sort of multiplexor register */
-       { 0x79, 0x01 },
-       { 0xc8, 0xf0 },
-       { 0x79, 0x0f },
-       { 0xc8, 0x00 },
-       { 0x79, 0x10 },
-       { 0xc8, 0x7e },
-       { 0x79, 0x0a },
-       { 0xc8, 0x80 },
-       { 0x79, 0x0b },
-       { 0xc8, 0x01 },
-       { 0x79, 0x0c },
-       { 0xc8, 0x0f },
-       { 0x79, 0x0d },
-       { 0xc8, 0x20 },
-       { 0x79, 0x09 },
-       { 0xc8, 0x80 },
-       { 0x79, 0x02 },
-       { 0xc8, 0xc0 },
-       { 0x79, 0x03 },
-       { 0xc8, 0x40 },
-       { 0x79, 0x05 },
-       { 0xc8, 0x30 },
-       { 0x79, 0x26 },
-};
-
-static const struct ov_i2c_regvals norm_8610[] = {
-       { 0x12, 0x80 },
-       { 0x00, 0x00 },
-       { 0x01, 0x80 },
-       { 0x02, 0x80 },
-       { 0x03, 0xc0 },
-       { 0x04, 0x30 },
-       { 0x05, 0x30 }, /* was 0x10, new from windrv 090403 */
-       { 0x06, 0x70 }, /* was 0x80, new from windrv 090403 */
-       { 0x0a, 0x86 },
-       { 0x0b, 0xb0 },
-       { 0x0c, 0x20 },
-       { 0x0d, 0x20 },
-       { 0x11, 0x01 },
-       { 0x12, 0x25 },
-       { 0x13, 0x01 },
-       { 0x14, 0x04 },
-       { 0x15, 0x01 }, /* Lin and Win think different about UV order */
-       { 0x16, 0x03 },
-       { 0x17, 0x38 }, /* was 0x2f, new from windrv 090403 */
-       { 0x18, 0xea }, /* was 0xcf, new from windrv 090403 */
-       { 0x19, 0x02 }, /* was 0x06, new from windrv 090403 */
-       { 0x1a, 0xf5 },
-       { 0x1b, 0x00 },
-       { 0x20, 0xd0 }, /* was 0x90, new from windrv 090403 */
-       { 0x23, 0xc0 }, /* was 0x00, new from windrv 090403 */
-       { 0x24, 0x30 }, /* was 0x1d, new from windrv 090403 */
-       { 0x25, 0x50 }, /* was 0x57, new from windrv 090403 */
-       { 0x26, 0xa2 },
-       { 0x27, 0xea },
-       { 0x28, 0x00 },
-       { 0x29, 0x00 },
-       { 0x2a, 0x80 },
-       { 0x2b, 0xc8 }, /* was 0xcc, new from windrv 090403 */
-       { 0x2c, 0xac },
-       { 0x2d, 0x45 }, /* was 0xd5, new from windrv 090403 */
-       { 0x2e, 0x80 },
-       { 0x2f, 0x14 }, /* was 0x01, new from windrv 090403 */
-       { 0x4c, 0x00 },
-       { 0x4d, 0x30 }, /* was 0x10, new from windrv 090403 */
-       { 0x60, 0x02 }, /* was 0x01, new from windrv 090403 */
-       { 0x61, 0x00 }, /* was 0x09, new from windrv 090403 */
-       { 0x62, 0x5f }, /* was 0xd7, new from windrv 090403 */
-       { 0x63, 0xff },
-       { 0x64, 0x53 }, /* new windrv 090403 says 0x57,
-                        * maybe thats wrong */
-       { 0x65, 0x00 },
-       { 0x66, 0x55 },
-       { 0x67, 0xb0 },
-       { 0x68, 0xc0 }, /* was 0xaf, new from windrv 090403 */
-       { 0x69, 0x02 },
-       { 0x6a, 0x22 },
-       { 0x6b, 0x00 },
-       { 0x6c, 0x99 }, /* was 0x80, old windrv says 0x00, but
-                        * deleting bit7 colors the first images red */
-       { 0x6d, 0x11 }, /* was 0x00, new from windrv 090403 */
-       { 0x6e, 0x11 }, /* was 0x00, new from windrv 090403 */
-       { 0x6f, 0x01 },
-       { 0x70, 0x8b },
-       { 0x71, 0x00 },
-       { 0x72, 0x14 },
-       { 0x73, 0x54 },
-       { 0x74, 0x00 },/* 0x60? - was 0x00, new from windrv 090403 */
-       { 0x75, 0x0e },
-       { 0x76, 0x02 }, /* was 0x02, new from windrv 090403 */
-       { 0x77, 0xff },
-       { 0x78, 0x80 },
-       { 0x79, 0x80 },
-       { 0x7a, 0x80 },
-       { 0x7b, 0x10 }, /* was 0x13, new from windrv 090403 */
-       { 0x7c, 0x00 },
-       { 0x7d, 0x08 }, /* was 0x09, new from windrv 090403 */
-       { 0x7e, 0x08 }, /* was 0xc0, new from windrv 090403 */
-       { 0x7f, 0xfb },
-       { 0x80, 0x28 },
-       { 0x81, 0x00 },
-       { 0x82, 0x23 },
-       { 0x83, 0x0b },
-       { 0x84, 0x00 },
-       { 0x85, 0x62 }, /* was 0x61, new from windrv 090403 */
-       { 0x86, 0xc9 },
-       { 0x87, 0x00 },
-       { 0x88, 0x00 },
-       { 0x89, 0x01 },
-       { 0x12, 0x20 },
-       { 0x12, 0x25 }, /* was 0x24, new from windrv 090403 */
-};
-
-static unsigned char ov7670_abs_to_sm(unsigned char v)
-{
-       if (v > 127)
-               return v & 0x7f;
-       return (128 - v) | 0x80;
-}
-
-/* Write a OV519 register */
-static void reg_w(struct sd *sd, u16 index, u16 value)
-{
-       int ret, req = 0;
-
-       if (sd->gspca_dev.usb_err < 0)
-               return;
-
-       switch (sd->bridge) {
-       case BRIDGE_OV511:
-       case BRIDGE_OV511PLUS:
-               req = 2;
-               break;
-       case BRIDGE_OVFX2:
-               req = 0x0a;
-               /* fall through */
-       case BRIDGE_W9968CF:
-               PDEBUG(D_USBO, "SET %02x %04x %04x",
-                               req, value, index);
-               ret = usb_control_msg(sd->gspca_dev.dev,
-                       usb_sndctrlpipe(sd->gspca_dev.dev, 0),
-                       req,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index, NULL, 0, 500);
-               goto leave;
-       default:
-               req = 1;
-       }
-
-       PDEBUG(D_USBO, "SET %02x 0000 %04x %02x",
-                       req, index, value);
-       sd->gspca_dev.usb_buf[0] = value;
-       ret = usb_control_msg(sd->gspca_dev.dev,
-                       usb_sndctrlpipe(sd->gspca_dev.dev, 0),
-                       req,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0, index,
-                       sd->gspca_dev.usb_buf, 1, 500);
-leave:
-       if (ret < 0) {
-               pr_err("reg_w %02x failed %d\n", index, ret);
-               sd->gspca_dev.usb_err = ret;
-               return;
-       }
-}
-
-/* Read from a OV519 register, note not valid for the w9968cf!! */
-/* returns: negative is error, pos or zero is data */
-static int reg_r(struct sd *sd, u16 index)
-{
-       int ret;
-       int req;
-
-       if (sd->gspca_dev.usb_err < 0)
-               return -1;
-
-       switch (sd->bridge) {
-       case BRIDGE_OV511:
-       case BRIDGE_OV511PLUS:
-               req = 3;
-               break;
-       case BRIDGE_OVFX2:
-               req = 0x0b;
-               break;
-       default:
-               req = 1;
-       }
-
-       ret = usb_control_msg(sd->gspca_dev.dev,
-                       usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
-                       req,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0, index, sd->gspca_dev.usb_buf, 1, 500);
-
-       if (ret >= 0) {
-               ret = sd->gspca_dev.usb_buf[0];
-               PDEBUG(D_USBI, "GET %02x 0000 %04x %02x",
-                       req, index, ret);
-       } else {
-               pr_err("reg_r %02x failed %d\n", index, ret);
-               sd->gspca_dev.usb_err = ret;
-       }
-
-       return ret;
-}
-
-/* Read 8 values from a OV519 register */
-static int reg_r8(struct sd *sd,
-                 u16 index)
-{
-       int ret;
-
-       if (sd->gspca_dev.usb_err < 0)
-               return -1;
-
-       ret = usb_control_msg(sd->gspca_dev.dev,
-                       usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
-                       1,                      /* REQ_IO */
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0, index, sd->gspca_dev.usb_buf, 8, 500);
-
-       if (ret >= 0) {
-               ret = sd->gspca_dev.usb_buf[0];
-       } else {
-               pr_err("reg_r8 %02x failed %d\n", index, ret);
-               sd->gspca_dev.usb_err = ret;
-       }
-
-       return ret;
-}
-
-/*
- * Writes bits at positions specified by mask to an OV51x reg. Bits that are in
- * the same position as 1's in "mask" are cleared and set to "value". Bits
- * that are in the same position as 0's in "mask" are preserved, regardless
- * of their respective state in "value".
- */
-static void reg_w_mask(struct sd *sd,
-                       u16 index,
-                       u8 value,
-                       u8 mask)
-{
-       int ret;
-       u8 oldval;
-
-       if (mask != 0xff) {
-               value &= mask;                  /* Enforce mask on value */
-               ret = reg_r(sd, index);
-               if (ret < 0)
-                       return;
-
-               oldval = ret & ~mask;           /* Clear the masked bits */
-               value |= oldval;                /* Set the desired bits */
-       }
-       reg_w(sd, index, value);
-}
-
-/*
- * Writes multiple (n) byte value to a single register. Only valid with certain
- * registers (0x30 and 0xc4 - 0xce).
- */
-static void ov518_reg_w32(struct sd *sd, u16 index, u32 value, int n)
-{
-       int ret;
-
-       if (sd->gspca_dev.usb_err < 0)
-               return;
-
-       *((__le32 *) sd->gspca_dev.usb_buf) = __cpu_to_le32(value);
-
-       ret = usb_control_msg(sd->gspca_dev.dev,
-                       usb_sndctrlpipe(sd->gspca_dev.dev, 0),
-                       1 /* REG_IO */,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0, index,
-                       sd->gspca_dev.usb_buf, n, 500);
-       if (ret < 0) {
-               pr_err("reg_w32 %02x failed %d\n", index, ret);
-               sd->gspca_dev.usb_err = ret;
-       }
-}
-
-static void ov511_i2c_w(struct sd *sd, u8 reg, u8 value)
-{
-       int rc, retries;
-
-       PDEBUG(D_USBO, "ov511_i2c_w %02x %02x", reg, value);
-
-       /* Three byte write cycle */
-       for (retries = 6; ; ) {
-               /* Select camera register */
-               reg_w(sd, R51x_I2C_SADDR_3, reg);
-
-               /* Write "value" to I2C data port of OV511 */
-               reg_w(sd, R51x_I2C_DATA, value);
-
-               /* Initiate 3-byte write cycle */
-               reg_w(sd, R511_I2C_CTL, 0x01);
-
-               do {
-                       rc = reg_r(sd, R511_I2C_CTL);
-               } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
-
-               if (rc < 0)
-                       return;
-
-               if ((rc & 2) == 0) /* Ack? */
-                       break;
-               if (--retries < 0) {
-                       PDEBUG(D_USBO, "i2c write retries exhausted");
-                       return;
-               }
-       }
-}
-
-static int ov511_i2c_r(struct sd *sd, u8 reg)
-{
-       int rc, value, retries;
-
-       /* Two byte write cycle */
-       for (retries = 6; ; ) {
-               /* Select camera register */
-               reg_w(sd, R51x_I2C_SADDR_2, reg);
-
-               /* Initiate 2-byte write cycle */
-               reg_w(sd, R511_I2C_CTL, 0x03);
-
-               do {
-                       rc = reg_r(sd, R511_I2C_CTL);
-               } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
-
-               if (rc < 0)
-                       return rc;
-
-               if ((rc & 2) == 0) /* Ack? */
-                       break;
-
-               /* I2C abort */
-               reg_w(sd, R511_I2C_CTL, 0x10);
-
-               if (--retries < 0) {
-                       PDEBUG(D_USBI, "i2c write retries exhausted");
-                       return -1;
-               }
-       }
-
-       /* Two byte read cycle */
-       for (retries = 6; ; ) {
-               /* Initiate 2-byte read cycle */
-               reg_w(sd, R511_I2C_CTL, 0x05);
-
-               do {
-                       rc = reg_r(sd, R511_I2C_CTL);
-               } while (rc > 0 && ((rc & 1) == 0)); /* Retry until idle */
-
-               if (rc < 0)
-                       return rc;
-
-               if ((rc & 2) == 0) /* Ack? */
-                       break;
-
-               /* I2C abort */
-               reg_w(sd, R511_I2C_CTL, 0x10);
-
-               if (--retries < 0) {
-                       PDEBUG(D_USBI, "i2c read retries exhausted");
-                       return -1;
-               }
-       }
-
-       value = reg_r(sd, R51x_I2C_DATA);
-
-       PDEBUG(D_USBI, "ov511_i2c_r %02x %02x", reg, value);
-
-       /* This is needed to make i2c_w() work */
-       reg_w(sd, R511_I2C_CTL, 0x05);
-
-       return value;
-}
-
-/*
- * The OV518 I2C I/O procedure is different, hence, this function.
- * This is normally only called from i2c_w(). Note that this function
- * always succeeds regardless of whether the sensor is present and working.
- */
-static void ov518_i2c_w(struct sd *sd,
-               u8 reg,
-               u8 value)
-{
-       PDEBUG(D_USBO, "ov518_i2c_w %02x %02x", reg, value);
-
-       /* Select camera register */
-       reg_w(sd, R51x_I2C_SADDR_3, reg);
-
-       /* Write "value" to I2C data port of OV511 */
-       reg_w(sd, R51x_I2C_DATA, value);
-
-       /* Initiate 3-byte write cycle */
-       reg_w(sd, R518_I2C_CTL, 0x01);
-
-       /* wait for write complete */
-       msleep(4);
-       reg_r8(sd, R518_I2C_CTL);
-}
-
-/*
- * returns: negative is error, pos or zero is data
- *
- * The OV518 I2C I/O procedure is different, hence, this function.
- * This is normally only called from i2c_r(). Note that this function
- * always succeeds regardless of whether the sensor is present and working.
- */
-static int ov518_i2c_r(struct sd *sd, u8 reg)
-{
-       int value;
-
-       /* Select camera register */
-       reg_w(sd, R51x_I2C_SADDR_2, reg);
-
-       /* Initiate 2-byte write cycle */
-       reg_w(sd, R518_I2C_CTL, 0x03);
-       reg_r8(sd, R518_I2C_CTL);
-
-       /* Initiate 2-byte read cycle */
-       reg_w(sd, R518_I2C_CTL, 0x05);
-       reg_r8(sd, R518_I2C_CTL);
-
-       value = reg_r(sd, R51x_I2C_DATA);
-       PDEBUG(D_USBI, "ov518_i2c_r %02x %02x", reg, value);
-       return value;
-}
-
-static void ovfx2_i2c_w(struct sd *sd, u8 reg, u8 value)
-{
-       int ret;
-
-       if (sd->gspca_dev.usb_err < 0)
-               return;
-
-       ret = usb_control_msg(sd->gspca_dev.dev,
-                       usb_sndctrlpipe(sd->gspca_dev.dev, 0),
-                       0x02,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       (u16) value, (u16) reg, NULL, 0, 500);
-
-       if (ret < 0) {
-               pr_err("ovfx2_i2c_w %02x failed %d\n", reg, ret);
-               sd->gspca_dev.usb_err = ret;
-       }
-
-       PDEBUG(D_USBO, "ovfx2_i2c_w %02x %02x", reg, value);
-}
-
-static int ovfx2_i2c_r(struct sd *sd, u8 reg)
-{
-       int ret;
-
-       if (sd->gspca_dev.usb_err < 0)
-               return -1;
-
-       ret = usb_control_msg(sd->gspca_dev.dev,
-                       usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
-                       0x03,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0, (u16) reg, sd->gspca_dev.usb_buf, 1, 500);
-
-       if (ret >= 0) {
-               ret = sd->gspca_dev.usb_buf[0];
-               PDEBUG(D_USBI, "ovfx2_i2c_r %02x %02x", reg, ret);
-       } else {
-               pr_err("ovfx2_i2c_r %02x failed %d\n", reg, ret);
-               sd->gspca_dev.usb_err = ret;
-       }
-
-       return ret;
-}
-
-static void i2c_w(struct sd *sd, u8 reg, u8 value)
-{
-       if (sd->sensor_reg_cache[reg] == value)
-               return;
-
-       switch (sd->bridge) {
-       case BRIDGE_OV511:
-       case BRIDGE_OV511PLUS:
-               ov511_i2c_w(sd, reg, value);
-               break;
-       case BRIDGE_OV518:
-       case BRIDGE_OV518PLUS:
-       case BRIDGE_OV519:
-               ov518_i2c_w(sd, reg, value);
-               break;
-       case BRIDGE_OVFX2:
-               ovfx2_i2c_w(sd, reg, value);
-               break;
-       case BRIDGE_W9968CF:
-               w9968cf_i2c_w(sd, reg, value);
-               break;
-       }
-
-       if (sd->gspca_dev.usb_err >= 0) {
-               /* Up on sensor reset empty the register cache */
-               if (reg == 0x12 && (value & 0x80))
-                       memset(sd->sensor_reg_cache, -1,
-                               sizeof(sd->sensor_reg_cache));
-               else
-                       sd->sensor_reg_cache[reg] = value;
-       }
-}
-
-static int i2c_r(struct sd *sd, u8 reg)
-{
-       int ret = -1;
-
-       if (sd->sensor_reg_cache[reg] != -1)
-               return sd->sensor_reg_cache[reg];
-
-       switch (sd->bridge) {
-       case BRIDGE_OV511:
-       case BRIDGE_OV511PLUS:
-               ret = ov511_i2c_r(sd, reg);
-               break;
-       case BRIDGE_OV518:
-       case BRIDGE_OV518PLUS:
-       case BRIDGE_OV519:
-               ret = ov518_i2c_r(sd, reg);
-               break;
-       case BRIDGE_OVFX2:
-               ret = ovfx2_i2c_r(sd, reg);
-               break;
-       case BRIDGE_W9968CF:
-               ret = w9968cf_i2c_r(sd, reg);
-               break;
-       }
-
-       if (ret >= 0)
-               sd->sensor_reg_cache[reg] = ret;
-
-       return ret;
-}
-
-/* Writes bits at positions specified by mask to an I2C reg. Bits that are in
- * the same position as 1's in "mask" are cleared and set to "value". Bits
- * that are in the same position as 0's in "mask" are preserved, regardless
- * of their respective state in "value".
- */
-static void i2c_w_mask(struct sd *sd,
-                       u8 reg,
-                       u8 value,
-                       u8 mask)
-{
-       int rc;
-       u8 oldval;
-
-       value &= mask;                  /* Enforce mask on value */
-       rc = i2c_r(sd, reg);
-       if (rc < 0)
-               return;
-       oldval = rc & ~mask;            /* Clear the masked bits */
-       value |= oldval;                /* Set the desired bits */
-       i2c_w(sd, reg, value);
-}
-
-/* Temporarily stops OV511 from functioning. Must do this before changing
- * registers while the camera is streaming */
-static inline void ov51x_stop(struct sd *sd)
-{
-       PDEBUG(D_STREAM, "stopping");
-       sd->stopped = 1;
-       switch (sd->bridge) {
-       case BRIDGE_OV511:
-       case BRIDGE_OV511PLUS:
-               reg_w(sd, R51x_SYS_RESET, 0x3d);
-               break;
-       case BRIDGE_OV518:
-       case BRIDGE_OV518PLUS:
-               reg_w_mask(sd, R51x_SYS_RESET, 0x3a, 0x3a);
-               break;
-       case BRIDGE_OV519:
-               reg_w(sd, OV519_R51_RESET1, 0x0f);
-               reg_w(sd, OV519_R51_RESET1, 0x00);
-               reg_w(sd, 0x22, 0x00);          /* FRAR */
-               break;
-       case BRIDGE_OVFX2:
-               reg_w_mask(sd, 0x0f, 0x00, 0x02);
-               break;
-       case BRIDGE_W9968CF:
-               reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */
-               break;
-       }
-}
-
-/* Restarts OV511 after ov511_stop() is called. Has no effect if it is not
- * actually stopped (for performance). */
-static inline void ov51x_restart(struct sd *sd)
-{
-       PDEBUG(D_STREAM, "restarting");
-       if (!sd->stopped)
-               return;
-       sd->stopped = 0;
-
-       /* Reinitialize the stream */
-       switch (sd->bridge) {
-       case BRIDGE_OV511:
-       case BRIDGE_OV511PLUS:
-               reg_w(sd, R51x_SYS_RESET, 0x00);
-               break;
-       case BRIDGE_OV518:
-       case BRIDGE_OV518PLUS:
-               reg_w(sd, 0x2f, 0x80);
-               reg_w(sd, R51x_SYS_RESET, 0x00);
-               break;
-       case BRIDGE_OV519:
-               reg_w(sd, OV519_R51_RESET1, 0x0f);
-               reg_w(sd, OV519_R51_RESET1, 0x00);
-               reg_w(sd, 0x22, 0x1d);          /* FRAR */
-               break;
-       case BRIDGE_OVFX2:
-               reg_w_mask(sd, 0x0f, 0x02, 0x02);
-               break;
-       case BRIDGE_W9968CF:
-               reg_w(sd, 0x3c, 0x8a05); /* USB FIFO enable */
-               break;
-       }
-}
-
-static void ov51x_set_slave_ids(struct sd *sd, u8 slave);
-
-/* This does an initial reset of an OmniVision sensor and ensures that I2C
- * is synchronized. Returns <0 on failure.
- */
-static int init_ov_sensor(struct sd *sd, u8 slave)
-{
-       int i;
-
-       ov51x_set_slave_ids(sd, slave);
-
-       /* Reset the sensor */
-       i2c_w(sd, 0x12, 0x80);
-
-       /* Wait for it to initialize */
-       msleep(150);
-
-       for (i = 0; i < i2c_detect_tries; i++) {
-               if (i2c_r(sd, OV7610_REG_ID_HIGH) == 0x7f &&
-                   i2c_r(sd, OV7610_REG_ID_LOW) == 0xa2) {
-                       PDEBUG(D_PROBE, "I2C synced in %d attempt(s)", i);
-                       return 0;
-               }
-
-               /* Reset the sensor */
-               i2c_w(sd, 0x12, 0x80);
-
-               /* Wait for it to initialize */
-               msleep(150);
-
-               /* Dummy read to sync I2C */
-               if (i2c_r(sd, 0x00) < 0)
-                       return -1;
-       }
-       return -1;
-}
-
-/* Set the read and write slave IDs. The "slave" argument is the write slave,
- * and the read slave will be set to (slave + 1).
- * This should not be called from outside the i2c I/O functions.
- * Sets I2C read and write slave IDs. Returns <0 for error
- */
-static void ov51x_set_slave_ids(struct sd *sd,
-                               u8 slave)
-{
-       switch (sd->bridge) {
-       case BRIDGE_OVFX2:
-               reg_w(sd, OVFX2_I2C_ADDR, slave);
-               return;
-       case BRIDGE_W9968CF:
-               sd->sensor_addr = slave;
-               return;
-       }
-
-       reg_w(sd, R51x_I2C_W_SID, slave);
-       reg_w(sd, R51x_I2C_R_SID, slave + 1);
-}
-
-static void write_regvals(struct sd *sd,
-                        const struct ov_regvals *regvals,
-                        int n)
-{
-       while (--n >= 0) {
-               reg_w(sd, regvals->reg, regvals->val);
-               regvals++;
-       }
-}
-
-static void write_i2c_regvals(struct sd *sd,
-                       const struct ov_i2c_regvals *regvals,
-                       int n)
-{
-       while (--n >= 0) {
-               i2c_w(sd, regvals->reg, regvals->val);
-               regvals++;
-       }
-}
-
-/****************************************************************************
- *
- * OV511 and sensor configuration
- *
- ***************************************************************************/
-
-/* This initializes the OV2x10 / OV3610 / OV3620 / OV9600 */
-static void ov_hires_configure(struct sd *sd)
-{
-       int high, low;
-
-       if (sd->bridge != BRIDGE_OVFX2) {
-               pr_err("error hires sensors only supported with ovfx2\n");
-               return;
-       }
-
-       PDEBUG(D_PROBE, "starting ov hires configuration");
-
-       /* Detect sensor (sub)type */
-       high = i2c_r(sd, 0x0a);
-       low = i2c_r(sd, 0x0b);
-       /* info("%x, %x", high, low); */
-       switch (high) {
-       case 0x96:
-               switch (low) {
-               case 0x40:
-                       PDEBUG(D_PROBE, "Sensor is a OV2610");
-                       sd->sensor = SEN_OV2610;
-                       return;
-               case 0x41:
-                       PDEBUG(D_PROBE, "Sensor is a OV2610AE");
-                       sd->sensor = SEN_OV2610AE;
-                       return;
-               case 0xb1:
-                       PDEBUG(D_PROBE, "Sensor is a OV9600");
-                       sd->sensor = SEN_OV9600;
-                       return;
-               }
-               break;
-       case 0x36:
-               if ((low & 0x0f) == 0x00) {
-                       PDEBUG(D_PROBE, "Sensor is a OV3610");
-                       sd->sensor = SEN_OV3610;
-                       return;
-               }
-               break;
-       }
-       pr_err("Error unknown sensor type: %02x%02x\n", high, low);
-}
-
-/* This initializes the OV8110, OV8610 sensor. The OV8110 uses
- * the same register settings as the OV8610, since they are very similar.
- */
-static void ov8xx0_configure(struct sd *sd)
-{
-       int rc;
-
-       PDEBUG(D_PROBE, "starting ov8xx0 configuration");
-
-       /* Detect sensor (sub)type */
-       rc = i2c_r(sd, OV7610_REG_COM_I);
-       if (rc < 0) {
-               PDEBUG(D_ERR, "Error detecting sensor type");
-               return;
-       }
-       if ((rc & 3) == 1)
-               sd->sensor = SEN_OV8610;
-       else
-               pr_err("Unknown image sensor version: %d\n", rc & 3);
-}
-
-/* This initializes the OV7610, OV7620, or OV76BE sensor. The OV76BE uses
- * the same register settings as the OV7610, since they are very similar.
- */
-static void ov7xx0_configure(struct sd *sd)
-{
-       int rc, high, low;
-
-       PDEBUG(D_PROBE, "starting OV7xx0 configuration");
-
-       /* Detect sensor (sub)type */
-       rc = i2c_r(sd, OV7610_REG_COM_I);
-
-       /* add OV7670 here
-        * it appears to be wrongly detected as a 7610 by default */
-       if (rc < 0) {
-               pr_err("Error detecting sensor type\n");
-               return;
-       }
-       if ((rc & 3) == 3) {
-               /* quick hack to make OV7670s work */
-               high = i2c_r(sd, 0x0a);
-               low = i2c_r(sd, 0x0b);
-               /* info("%x, %x", high, low); */
-               if (high == 0x76 && (low & 0xf0) == 0x70) {
-                       PDEBUG(D_PROBE, "Sensor is an OV76%02x", low);
-                       sd->sensor = SEN_OV7670;
-               } else {
-                       PDEBUG(D_PROBE, "Sensor is an OV7610");
-                       sd->sensor = SEN_OV7610;
-               }
-       } else if ((rc & 3) == 1) {
-               /* I don't know what's different about the 76BE yet. */
-               if (i2c_r(sd, 0x15) & 1) {
-                       PDEBUG(D_PROBE, "Sensor is an OV7620AE");
-                       sd->sensor = SEN_OV7620AE;
-               } else {
-                       PDEBUG(D_PROBE, "Sensor is an OV76BE");
-                       sd->sensor = SEN_OV76BE;
-               }
-       } else if ((rc & 3) == 0) {
-               /* try to read product id registers */
-               high = i2c_r(sd, 0x0a);
-               if (high < 0) {
-                       pr_err("Error detecting camera chip PID\n");
-                       return;
-               }
-               low = i2c_r(sd, 0x0b);
-               if (low < 0) {
-                       pr_err("Error detecting camera chip VER\n");
-                       return;
-               }
-               if (high == 0x76) {
-                       switch (low) {
-                       case 0x30:
-                               pr_err("Sensor is an OV7630/OV7635\n");
-                               pr_err("7630 is not supported by this driver\n");
-                               return;
-                       case 0x40:
-                               PDEBUG(D_PROBE, "Sensor is an OV7645");
-                               sd->sensor = SEN_OV7640; /* FIXME */
-                               break;
-                       case 0x45:
-                               PDEBUG(D_PROBE, "Sensor is an OV7645B");
-                               sd->sensor = SEN_OV7640; /* FIXME */
-                               break;
-                       case 0x48:
-                               PDEBUG(D_PROBE, "Sensor is an OV7648");
-                               sd->sensor = SEN_OV7648;
-                               break;
-                       case 0x60:
-                               PDEBUG(D_PROBE, "Sensor is a OV7660");
-                               sd->sensor = SEN_OV7660;
-                               break;
-                       default:
-                               pr_err("Unknown sensor: 0x76%02x\n", low);
-                               return;
-                       }
-               } else {
-                       PDEBUG(D_PROBE, "Sensor is an OV7620");
-                       sd->sensor = SEN_OV7620;
-               }
-       } else {
-               pr_err("Unknown image sensor version: %d\n", rc & 3);
-       }
-}
-
-/* This initializes the OV6620, OV6630, OV6630AE, or OV6630AF sensor. */
-static void ov6xx0_configure(struct sd *sd)
-{
-       int rc;
-       PDEBUG(D_PROBE, "starting OV6xx0 configuration");
-
-       /* Detect sensor (sub)type */
-       rc = i2c_r(sd, OV7610_REG_COM_I);
-       if (rc < 0) {
-               pr_err("Error detecting sensor type\n");
-               return;
-       }
-
-       /* Ugh. The first two bits are the version bits, but
-        * the entire register value must be used. I guess OVT
-        * underestimated how many variants they would make. */
-       switch (rc) {
-       case 0x00:
-               sd->sensor = SEN_OV6630;
-               pr_warn("WARNING: Sensor is an OV66308. Your camera may have been misdetected in previous driver versions.\n");
-               break;
-       case 0x01:
-               sd->sensor = SEN_OV6620;
-               PDEBUG(D_PROBE, "Sensor is an OV6620");
-               break;
-       case 0x02:
-               sd->sensor = SEN_OV6630;
-               PDEBUG(D_PROBE, "Sensor is an OV66308AE");
-               break;
-       case 0x03:
-               sd->sensor = SEN_OV66308AF;
-               PDEBUG(D_PROBE, "Sensor is an OV66308AF");
-               break;
-       case 0x90:
-               sd->sensor = SEN_OV6630;
-               pr_warn("WARNING: Sensor is an OV66307. Your camera may have been misdetected in previous driver versions.\n");
-               break;
-       default:
-               pr_err("FATAL: Unknown sensor version: 0x%02x\n", rc);
-               return;
-       }
-
-       /* Set sensor-specific vars */
-       sd->sif = 1;
-}
-
-/* Turns on or off the LED. Only has an effect with OV511+/OV518(+)/OV519 */
-static void ov51x_led_control(struct sd *sd, int on)
-{
-       if (sd->invert_led)
-               on = !on;
-
-       switch (sd->bridge) {
-       /* OV511 has no LED control */
-       case BRIDGE_OV511PLUS:
-               reg_w(sd, R511_SYS_LED_CTL, on);
-               break;
-       case BRIDGE_OV518:
-       case BRIDGE_OV518PLUS:
-               reg_w_mask(sd, R518_GPIO_OUT, 0x02 * on, 0x02);
-               break;
-       case BRIDGE_OV519:
-               reg_w_mask(sd, OV519_GPIO_DATA_OUT0, on, 1);
-               break;
-       }
-}
-
-static void sd_reset_snapshot(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (!sd->snapshot_needs_reset)
-               return;
-
-       /* Note it is important that we clear sd->snapshot_needs_reset,
-          before actually clearing the snapshot state in the bridge
-          otherwise we might race with the pkt_scan interrupt handler */
-       sd->snapshot_needs_reset = 0;
-
-       switch (sd->bridge) {
-       case BRIDGE_OV511:
-       case BRIDGE_OV511PLUS:
-               reg_w(sd, R51x_SYS_SNAP, 0x02);
-               reg_w(sd, R51x_SYS_SNAP, 0x00);
-               break;
-       case BRIDGE_OV518:
-       case BRIDGE_OV518PLUS:
-               reg_w(sd, R51x_SYS_SNAP, 0x02); /* Reset */
-               reg_w(sd, R51x_SYS_SNAP, 0x01); /* Enable */
-               break;
-       case BRIDGE_OV519:
-               reg_w(sd, R51x_SYS_RESET, 0x40);
-               reg_w(sd, R51x_SYS_RESET, 0x00);
-               break;
-       }
-}
-
-static void ov51x_upload_quan_tables(struct sd *sd)
-{
-       const unsigned char yQuanTable511[] = {
-               0, 1, 1, 2, 2, 3, 3, 4,
-               1, 1, 1, 2, 2, 3, 4, 4,
-               1, 1, 2, 2, 3, 4, 4, 4,
-               2, 2, 2, 3, 4, 4, 4, 4,
-               2, 2, 3, 4, 4, 5, 5, 5,
-               3, 3, 4, 4, 5, 5, 5, 5,
-               3, 4, 4, 4, 5, 5, 5, 5,
-               4, 4, 4, 4, 5, 5, 5, 5
-       };
-
-       const unsigned char uvQuanTable511[] = {
-               0, 2, 2, 3, 4, 4, 4, 4,
-               2, 2, 2, 4, 4, 4, 4, 4,
-               2, 2, 3, 4, 4, 4, 4, 4,
-               3, 4, 4, 4, 4, 4, 4, 4,
-               4, 4, 4, 4, 4, 4, 4, 4,
-               4, 4, 4, 4, 4, 4, 4, 4,
-               4, 4, 4, 4, 4, 4, 4, 4,
-               4, 4, 4, 4, 4, 4, 4, 4
-       };
-
-       /* OV518 quantization tables are 8x4 (instead of 8x8) */
-       const unsigned char yQuanTable518[] = {
-               5, 4, 5, 6, 6, 7, 7, 7,
-               5, 5, 5, 5, 6, 7, 7, 7,
-               6, 6, 6, 6, 7, 7, 7, 8,
-               7, 7, 6, 7, 7, 7, 8, 8
-       };
-       const unsigned char uvQuanTable518[] = {
-               6, 6, 6, 7, 7, 7, 7, 7,
-               6, 6, 6, 7, 7, 7, 7, 7,
-               6, 6, 6, 7, 7, 7, 7, 8,
-               7, 7, 7, 7, 7, 7, 8, 8
-       };
-
-       const unsigned char *pYTable, *pUVTable;
-       unsigned char val0, val1;
-       int i, size, reg = R51x_COMP_LUT_BEGIN;
-
-       PDEBUG(D_PROBE, "Uploading quantization tables");
-
-       if (sd->bridge == BRIDGE_OV511 || sd->bridge == BRIDGE_OV511PLUS) {
-               pYTable = yQuanTable511;
-               pUVTable = uvQuanTable511;
-               size = 32;
-       } else {
-               pYTable = yQuanTable518;
-               pUVTable = uvQuanTable518;
-               size = 16;
-       }
-
-       for (i = 0; i < size; i++) {
-               val0 = *pYTable++;
-               val1 = *pYTable++;
-               val0 &= 0x0f;
-               val1 &= 0x0f;
-               val0 |= val1 << 4;
-               reg_w(sd, reg, val0);
-
-               val0 = *pUVTable++;
-               val1 = *pUVTable++;
-               val0 &= 0x0f;
-               val1 &= 0x0f;
-               val0 |= val1 << 4;
-               reg_w(sd, reg + size, val0);
-
-               reg++;
-       }
-}
-
-/* This initializes the OV511/OV511+ and the sensor */
-static void ov511_configure(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* For 511 and 511+ */
-       const struct ov_regvals init_511[] = {
-               { R51x_SYS_RESET,       0x7f },
-               { R51x_SYS_INIT,        0x01 },
-               { R51x_SYS_RESET,       0x7f },
-               { R51x_SYS_INIT,        0x01 },
-               { R51x_SYS_RESET,       0x3f },
-               { R51x_SYS_INIT,        0x01 },
-               { R51x_SYS_RESET,       0x3d },
-       };
-
-       const struct ov_regvals norm_511[] = {
-               { R511_DRAM_FLOW_CTL,   0x01 },
-               { R51x_SYS_SNAP,        0x00 },
-               { R51x_SYS_SNAP,        0x02 },
-               { R51x_SYS_SNAP,        0x00 },
-               { R511_FIFO_OPTS,       0x1f },
-               { R511_COMP_EN,         0x00 },
-               { R511_COMP_LUT_EN,     0x03 },
-       };
-
-       const struct ov_regvals norm_511_p[] = {
-               { R511_DRAM_FLOW_CTL,   0xff },
-               { R51x_SYS_SNAP,        0x00 },
-               { R51x_SYS_SNAP,        0x02 },
-               { R51x_SYS_SNAP,        0x00 },
-               { R511_FIFO_OPTS,       0xff },
-               { R511_COMP_EN,         0x00 },
-               { R511_COMP_LUT_EN,     0x03 },
-       };
-
-       const struct ov_regvals compress_511[] = {
-               { 0x70, 0x1f },
-               { 0x71, 0x05 },
-               { 0x72, 0x06 },
-               { 0x73, 0x06 },
-               { 0x74, 0x14 },
-               { 0x75, 0x03 },
-               { 0x76, 0x04 },
-               { 0x77, 0x04 },
-       };
-
-       PDEBUG(D_PROBE, "Device custom id %x", reg_r(sd, R51x_SYS_CUST_ID));
-
-       write_regvals(sd, init_511, ARRAY_SIZE(init_511));
-
-       switch (sd->bridge) {
-       case BRIDGE_OV511:
-               write_regvals(sd, norm_511, ARRAY_SIZE(norm_511));
-               break;
-       case BRIDGE_OV511PLUS:
-               write_regvals(sd, norm_511_p, ARRAY_SIZE(norm_511_p));
-               break;
-       }
-
-       /* Init compression */
-       write_regvals(sd, compress_511, ARRAY_SIZE(compress_511));
-
-       ov51x_upload_quan_tables(sd);
-}
-
-/* This initializes the OV518/OV518+ and the sensor */
-static void ov518_configure(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* For 518 and 518+ */
-       const struct ov_regvals init_518[] = {
-               { R51x_SYS_RESET,       0x40 },
-               { R51x_SYS_INIT,        0xe1 },
-               { R51x_SYS_RESET,       0x3e },
-               { R51x_SYS_INIT,        0xe1 },
-               { R51x_SYS_RESET,       0x00 },
-               { R51x_SYS_INIT,        0xe1 },
-               { 0x46,                 0x00 },
-               { 0x5d,                 0x03 },
-       };
-
-       const struct ov_regvals norm_518[] = {
-               { R51x_SYS_SNAP,        0x02 }, /* Reset */
-               { R51x_SYS_SNAP,        0x01 }, /* Enable */
-               { 0x31,                 0x0f },
-               { 0x5d,                 0x03 },
-               { 0x24,                 0x9f },
-               { 0x25,                 0x90 },
-               { 0x20,                 0x00 },
-               { 0x51,                 0x04 },
-               { 0x71,                 0x19 },
-               { 0x2f,                 0x80 },
-       };
-
-       const struct ov_regvals norm_518_p[] = {
-               { R51x_SYS_SNAP,        0x02 }, /* Reset */
-               { R51x_SYS_SNAP,        0x01 }, /* Enable */
-               { 0x31,                 0x0f },
-               { 0x5d,                 0x03 },
-               { 0x24,                 0x9f },
-               { 0x25,                 0x90 },
-               { 0x20,                 0x60 },
-               { 0x51,                 0x02 },
-               { 0x71,                 0x19 },
-               { 0x40,                 0xff },
-               { 0x41,                 0x42 },
-               { 0x46,                 0x00 },
-               { 0x33,                 0x04 },
-               { 0x21,                 0x19 },
-               { 0x3f,                 0x10 },
-               { 0x2f,                 0x80 },
-       };
-
-       /* First 5 bits of custom ID reg are a revision ID on OV518 */
-       PDEBUG(D_PROBE, "Device revision %d",
-               0x1f & reg_r(sd, R51x_SYS_CUST_ID));
-
-       write_regvals(sd, init_518, ARRAY_SIZE(init_518));
-
-       /* Set LED GPIO pin to output mode */
-       reg_w_mask(sd, R518_GPIO_CTL, 0x00, 0x02);
-
-       switch (sd->bridge) {
-       case BRIDGE_OV518:
-               write_regvals(sd, norm_518, ARRAY_SIZE(norm_518));
-               break;
-       case BRIDGE_OV518PLUS:
-               write_regvals(sd, norm_518_p, ARRAY_SIZE(norm_518_p));
-               break;
-       }
-
-       ov51x_upload_quan_tables(sd);
-
-       reg_w(sd, 0x2f, 0x80);
-}
-
-static void ov519_configure(struct sd *sd)
-{
-       static const struct ov_regvals init_519[] = {
-               { 0x5a, 0x6d }, /* EnableSystem */
-               { 0x53, 0x9b }, /* don't enable the microcontroller */
-               { OV519_R54_EN_CLK1, 0xff }, /* set bit2 to enable jpeg */
-               { 0x5d, 0x03 },
-               { 0x49, 0x01 },
-               { 0x48, 0x00 },
-               /* Set LED pin to output mode. Bit 4 must be cleared or sensor
-                * detection will fail. This deserves further investigation. */
-               { OV519_GPIO_IO_CTRL0,   0xee },
-               { OV519_R51_RESET1, 0x0f },
-               { OV519_R51_RESET1, 0x00 },
-               { 0x22, 0x00 },
-               /* windows reads 0x55 at this point*/
-       };
-
-       write_regvals(sd, init_519, ARRAY_SIZE(init_519));
-}
-
-static void ovfx2_configure(struct sd *sd)
-{
-       static const struct ov_regvals init_fx2[] = {
-               { 0x00, 0x60 },
-               { 0x02, 0x01 },
-               { 0x0f, 0x1d },
-               { 0xe9, 0x82 },
-               { 0xea, 0xc7 },
-               { 0xeb, 0x10 },
-               { 0xec, 0xf6 },
-       };
-
-       sd->stopped = 1;
-
-       write_regvals(sd, init_fx2, ARRAY_SIZE(init_fx2));
-}
-
-/* set the mode */
-/* This function works for ov7660 only */
-static void ov519_set_mode(struct sd *sd)
-{
-       static const struct ov_regvals bridge_ov7660[2][10] = {
-               {{0x10, 0x14}, {0x11, 0x1e}, {0x12, 0x00}, {0x13, 0x00},
-                {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c},
-                {0x25, 0x01}, {0x26, 0x00}},
-               {{0x10, 0x28}, {0x11, 0x3c}, {0x12, 0x00}, {0x13, 0x00},
-                {0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x20, 0x0c},
-                {0x25, 0x03}, {0x26, 0x00}}
-       };
-       static const struct ov_i2c_regvals sensor_ov7660[2][3] = {
-               {{0x12, 0x00}, {0x24, 0x00}, {0x0c, 0x0c}},
-               {{0x12, 0x00}, {0x04, 0x00}, {0x0c, 0x00}}
-       };
-       static const struct ov_i2c_regvals sensor_ov7660_2[] = {
-               {OV7670_R17_HSTART, 0x13},
-               {OV7670_R18_HSTOP, 0x01},
-               {OV7670_R32_HREF, 0x92},
-               {OV7670_R19_VSTART, 0x02},
-               {OV7670_R1A_VSTOP, 0x7a},
-               {OV7670_R03_VREF, 0x00},
-/*             {0x33, 0x00}, */
-/*             {0x34, 0x07}, */
-/*             {0x36, 0x00}, */
-/*             {0x6b, 0x0a}, */
-       };
-
-       write_regvals(sd, bridge_ov7660[sd->gspca_dev.curr_mode],
-                       ARRAY_SIZE(bridge_ov7660[0]));
-       write_i2c_regvals(sd, sensor_ov7660[sd->gspca_dev.curr_mode],
-                       ARRAY_SIZE(sensor_ov7660[0]));
-       write_i2c_regvals(sd, sensor_ov7660_2,
-                       ARRAY_SIZE(sensor_ov7660_2));
-}
-
-/* set the frame rate */
-/* This function works for sensors ov7640, ov7648 ov7660 and ov7670 only */
-static void ov519_set_fr(struct sd *sd)
-{
-       int fr;
-       u8 clock;
-       /* frame rate table with indices:
-        *      - mode = 0: 320x240, 1: 640x480
-        *      - fr rate = 0: 30, 1: 25, 2: 20, 3: 15, 4: 10, 5: 5
-        *      - reg = 0: bridge a4, 1: bridge 23, 2: sensor 11 (clock)
-        */
-       static const u8 fr_tb[2][6][3] = {
-               {{0x04, 0xff, 0x00},
-                {0x04, 0x1f, 0x00},
-                {0x04, 0x1b, 0x00},
-                {0x04, 0x15, 0x00},
-                {0x04, 0x09, 0x00},
-                {0x04, 0x01, 0x00}},
-               {{0x0c, 0xff, 0x00},
-                {0x0c, 0x1f, 0x00},
-                {0x0c, 0x1b, 0x00},
-                {0x04, 0xff, 0x01},
-                {0x04, 0x1f, 0x01},
-                {0x04, 0x1b, 0x01}},
-       };
-
-       if (frame_rate > 0)
-               sd->frame_rate = frame_rate;
-       if (sd->frame_rate >= 30)
-               fr = 0;
-       else if (sd->frame_rate >= 25)
-               fr = 1;
-       else if (sd->frame_rate >= 20)
-               fr = 2;
-       else if (sd->frame_rate >= 15)
-               fr = 3;
-       else if (sd->frame_rate >= 10)
-               fr = 4;
-       else
-               fr = 5;
-       reg_w(sd, 0xa4, fr_tb[sd->gspca_dev.curr_mode][fr][0]);
-       reg_w(sd, 0x23, fr_tb[sd->gspca_dev.curr_mode][fr][1]);
-       clock = fr_tb[sd->gspca_dev.curr_mode][fr][2];
-       if (sd->sensor == SEN_OV7660)
-               clock |= 0x80;          /* enable double clock */
-       ov518_i2c_w(sd, OV7670_R11_CLKRC, clock);
-}
-
-static void setautogain(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       i2c_w_mask(sd, 0x13, val ? 0x05 : 0x00, 0x05);
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam = &gspca_dev->cam;
-
-       sd->bridge = id->driver_info & BRIDGE_MASK;
-       sd->invert_led = (id->driver_info & BRIDGE_INVERT_LED) != 0;
-
-       switch (sd->bridge) {
-       case BRIDGE_OV511:
-       case BRIDGE_OV511PLUS:
-               cam->cam_mode = ov511_vga_mode;
-               cam->nmodes = ARRAY_SIZE(ov511_vga_mode);
-               break;
-       case BRIDGE_OV518:
-       case BRIDGE_OV518PLUS:
-               cam->cam_mode = ov518_vga_mode;
-               cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
-               break;
-       case BRIDGE_OV519:
-               cam->cam_mode = ov519_vga_mode;
-               cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
-               break;
-       case BRIDGE_OVFX2:
-               cam->cam_mode = ov519_vga_mode;
-               cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
-               cam->bulk_size = OVFX2_BULK_SIZE;
-               cam->bulk_nurbs = MAX_NURBS;
-               cam->bulk = 1;
-               break;
-       case BRIDGE_W9968CF:
-               cam->cam_mode = w9968cf_vga_mode;
-               cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
-               break;
-       }
-
-       sd->frame_rate = 15;
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam = &gspca_dev->cam;
-
-       switch (sd->bridge) {
-       case BRIDGE_OV511:
-       case BRIDGE_OV511PLUS:
-               ov511_configure(gspca_dev);
-               break;
-       case BRIDGE_OV518:
-       case BRIDGE_OV518PLUS:
-               ov518_configure(gspca_dev);
-               break;
-       case BRIDGE_OV519:
-               ov519_configure(sd);
-               break;
-       case BRIDGE_OVFX2:
-               ovfx2_configure(sd);
-               break;
-       case BRIDGE_W9968CF:
-               w9968cf_configure(sd);
-               break;
-       }
-
-       /* The OV519 must be more aggressive about sensor detection since
-        * I2C write will never fail if the sensor is not present. We have
-        * to try to initialize the sensor to detect its presence */
-       sd->sensor = -1;
-
-       /* Test for 76xx */
-       if (init_ov_sensor(sd, OV7xx0_SID) >= 0) {
-               ov7xx0_configure(sd);
-
-       /* Test for 6xx0 */
-       } else if (init_ov_sensor(sd, OV6xx0_SID) >= 0) {
-               ov6xx0_configure(sd);
-
-       /* Test for 8xx0 */
-       } else if (init_ov_sensor(sd, OV8xx0_SID) >= 0) {
-               ov8xx0_configure(sd);
-
-       /* Test for 3xxx / 2xxx */
-       } else if (init_ov_sensor(sd, OV_HIRES_SID) >= 0) {
-               ov_hires_configure(sd);
-       } else {
-               pr_err("Can't determine sensor slave IDs\n");
-               goto error;
-       }
-
-       if (sd->sensor < 0)
-               goto error;
-
-       ov51x_led_control(sd, 0);       /* turn LED off */
-
-       switch (sd->bridge) {
-       case BRIDGE_OV511:
-       case BRIDGE_OV511PLUS:
-               if (sd->sif) {
-                       cam->cam_mode = ov511_sif_mode;
-                       cam->nmodes = ARRAY_SIZE(ov511_sif_mode);
-               }
-               break;
-       case BRIDGE_OV518:
-       case BRIDGE_OV518PLUS:
-               if (sd->sif) {
-                       cam->cam_mode = ov518_sif_mode;
-                       cam->nmodes = ARRAY_SIZE(ov518_sif_mode);
-               }
-               break;
-       case BRIDGE_OV519:
-               if (sd->sif) {
-                       cam->cam_mode = ov519_sif_mode;
-                       cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
-               }
-               break;
-       case BRIDGE_OVFX2:
-               switch (sd->sensor) {
-               case SEN_OV2610:
-               case SEN_OV2610AE:
-                       cam->cam_mode = ovfx2_ov2610_mode;
-                       cam->nmodes = ARRAY_SIZE(ovfx2_ov2610_mode);
-                       break;
-               case SEN_OV3610:
-                       cam->cam_mode = ovfx2_ov3610_mode;
-                       cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode);
-                       break;
-               case SEN_OV9600:
-                       cam->cam_mode = ovfx2_ov9600_mode;
-                       cam->nmodes = ARRAY_SIZE(ovfx2_ov9600_mode);
-                       break;
-               default:
-                       if (sd->sif) {
-                               cam->cam_mode = ov519_sif_mode;
-                               cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
-                       }
-                       break;
-               }
-               break;
-       case BRIDGE_W9968CF:
-               if (sd->sif)
-                       cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode) - 1;
-
-               /* w9968cf needs initialisation once the sensor is known */
-               w9968cf_init(sd);
-               break;
-       }
-
-       /* initialize the sensor */
-       switch (sd->sensor) {
-       case SEN_OV2610:
-               write_i2c_regvals(sd, norm_2610, ARRAY_SIZE(norm_2610));
-
-               /* Enable autogain, autoexpo, awb, bandfilter */
-               i2c_w_mask(sd, 0x13, 0x27, 0x27);
-               break;
-       case SEN_OV2610AE:
-               write_i2c_regvals(sd, norm_2610ae, ARRAY_SIZE(norm_2610ae));
-
-               /* enable autoexpo */
-               i2c_w_mask(sd, 0x13, 0x05, 0x05);
-               break;
-       case SEN_OV3610:
-               write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b));
-
-               /* Enable autogain, autoexpo, awb, bandfilter */
-               i2c_w_mask(sd, 0x13, 0x27, 0x27);
-               break;
-       case SEN_OV6620:
-               write_i2c_regvals(sd, norm_6x20, ARRAY_SIZE(norm_6x20));
-               break;
-       case SEN_OV6630:
-       case SEN_OV66308AF:
-               write_i2c_regvals(sd, norm_6x30, ARRAY_SIZE(norm_6x30));
-               break;
-       default:
-/*     case SEN_OV7610: */
-/*     case SEN_OV76BE: */
-               write_i2c_regvals(sd, norm_7610, ARRAY_SIZE(norm_7610));
-               i2c_w_mask(sd, 0x0e, 0x00, 0x40);
-               break;
-       case SEN_OV7620:
-       case SEN_OV7620AE:
-               write_i2c_regvals(sd, norm_7620, ARRAY_SIZE(norm_7620));
-               break;
-       case SEN_OV7640:
-       case SEN_OV7648:
-               write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640));
-               break;
-       case SEN_OV7660:
-               i2c_w(sd, OV7670_R12_COM7, OV7670_COM7_RESET);
-               msleep(14);
-               reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
-               write_regvals(sd, init_519_ov7660,
-                               ARRAY_SIZE(init_519_ov7660));
-               write_i2c_regvals(sd, norm_7660, ARRAY_SIZE(norm_7660));
-               sd->gspca_dev.curr_mode = 1;    /* 640x480 */
-               ov519_set_mode(sd);
-               ov519_set_fr(sd);
-               sd_reset_snapshot(gspca_dev);
-               ov51x_restart(sd);
-               ov51x_stop(sd);                 /* not in win traces */
-               ov51x_led_control(sd, 0);
-               break;
-       case SEN_OV7670:
-               write_i2c_regvals(sd, norm_7670, ARRAY_SIZE(norm_7670));
-               break;
-       case SEN_OV8610:
-               write_i2c_regvals(sd, norm_8610, ARRAY_SIZE(norm_8610));
-               break;
-       case SEN_OV9600:
-               write_i2c_regvals(sd, norm_9600, ARRAY_SIZE(norm_9600));
-
-               /* enable autoexpo */
-/*             i2c_w_mask(sd, 0x13, 0x05, 0x05); */
-               break;
-       }
-       return gspca_dev->usb_err;
-error:
-       PDEBUG(D_ERR, "OV519 Config failed");
-       return -EINVAL;
-}
-
-/* function called at start time before URB creation */
-static int sd_isoc_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->bridge) {
-       case BRIDGE_OVFX2:
-               if (gspca_dev->width != 800)
-                       gspca_dev->cam.bulk_size = OVFX2_BULK_SIZE;
-               else
-                       gspca_dev->cam.bulk_size = 7 * 4096;
-               break;
-       }
-       return 0;
-}
-
-/* Set up the OV511/OV511+ with the given image parameters.
- *
- * Do not put any sensor-specific code in here (including I2C I/O functions)
- */
-static void ov511_mode_init_regs(struct sd *sd)
-{
-       int hsegs, vsegs, packet_size, fps, needed;
-       int interlaced = 0;
-       struct usb_host_interface *alt;
-       struct usb_interface *intf;
-
-       intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
-       alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
-       if (!alt) {
-               pr_err("Couldn't get altsetting\n");
-               sd->gspca_dev.usb_err = -EIO;
-               return;
-       }
-
-       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
-       reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5);
-
-       reg_w(sd, R511_CAM_UV_EN, 0x01);
-       reg_w(sd, R511_SNAP_UV_EN, 0x01);
-       reg_w(sd, R511_SNAP_OPTS, 0x03);
-
-       /* Here I'm assuming that snapshot size == image size.
-        * I hope that's always true. --claudio
-        */
-       hsegs = (sd->gspca_dev.width >> 3) - 1;
-       vsegs = (sd->gspca_dev.height >> 3) - 1;
-
-       reg_w(sd, R511_CAM_PXCNT, hsegs);
-       reg_w(sd, R511_CAM_LNCNT, vsegs);
-       reg_w(sd, R511_CAM_PXDIV, 0x00);
-       reg_w(sd, R511_CAM_LNDIV, 0x00);
-
-       /* YUV420, low pass filter on */
-       reg_w(sd, R511_CAM_OPTS, 0x03);
-
-       /* Snapshot additions */
-       reg_w(sd, R511_SNAP_PXCNT, hsegs);
-       reg_w(sd, R511_SNAP_LNCNT, vsegs);
-       reg_w(sd, R511_SNAP_PXDIV, 0x00);
-       reg_w(sd, R511_SNAP_LNDIV, 0x00);
-
-       /******** Set the framerate ********/
-       if (frame_rate > 0)
-               sd->frame_rate = frame_rate;
-
-       switch (sd->sensor) {
-       case SEN_OV6620:
-               /* No framerate control, doesn't like higher rates yet */
-               sd->clockdiv = 3;
-               break;
-
-       /* Note once the FIXME's in mode_init_ov_sensor_regs() are fixed
-          for more sensors we need to do this for them too */
-       case SEN_OV7620:
-       case SEN_OV7620AE:
-       case SEN_OV7640:
-       case SEN_OV7648:
-       case SEN_OV76BE:
-               if (sd->gspca_dev.width == 320)
-                       interlaced = 1;
-               /* Fall through */
-       case SEN_OV6630:
-       case SEN_OV7610:
-       case SEN_OV7670:
-               switch (sd->frame_rate) {
-               case 30:
-               case 25:
-                       /* Not enough bandwidth to do 640x480 @ 30 fps */
-                       if (sd->gspca_dev.width != 640) {
-                               sd->clockdiv = 0;
-                               break;
-                       }
-                       /* Fall through for 640x480 case */
-               default:
-/*             case 20: */
-/*             case 15: */
-                       sd->clockdiv = 1;
-                       break;
-               case 10:
-                       sd->clockdiv = 2;
-                       break;
-               case 5:
-                       sd->clockdiv = 5;
-                       break;
-               }
-               if (interlaced) {
-                       sd->clockdiv = (sd->clockdiv + 1) * 2 - 1;
-                       /* Higher then 10 does not work */
-                       if (sd->clockdiv > 10)
-                               sd->clockdiv = 10;
-               }
-               break;
-
-       case SEN_OV8610:
-               /* No framerate control ?? */
-               sd->clockdiv = 0;
-               break;
-       }
-
-       /* Check if we have enough bandwidth to disable compression */
-       fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1;
-       needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2;
-       /* 1000 isoc packets/sec */
-       if (needed > 1000 * packet_size) {
-               /* Enable Y and UV quantization and compression */
-               reg_w(sd, R511_COMP_EN, 0x07);
-               reg_w(sd, R511_COMP_LUT_EN, 0x03);
-       } else {
-               reg_w(sd, R511_COMP_EN, 0x06);
-               reg_w(sd, R511_COMP_LUT_EN, 0x00);
-       }
-
-       reg_w(sd, R51x_SYS_RESET, OV511_RESET_OMNICE);
-       reg_w(sd, R51x_SYS_RESET, 0);
-}
-
-/* Sets up the OV518/OV518+ with the given image parameters
- *
- * OV518 needs a completely different approach, until we can figure out what
- * the individual registers do. Also, only 15 FPS is supported now.
- *
- * Do not put any sensor-specific code in here (including I2C I/O functions)
- */
-static void ov518_mode_init_regs(struct sd *sd)
-{
-       int hsegs, vsegs, packet_size;
-       struct usb_host_interface *alt;
-       struct usb_interface *intf;
-
-       intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
-       alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
-       if (!alt) {
-               pr_err("Couldn't get altsetting\n");
-               sd->gspca_dev.usb_err = -EIO;
-               return;
-       }
-
-       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
-       ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2);
-
-       /******** Set the mode ********/
-       reg_w(sd, 0x2b, 0);
-       reg_w(sd, 0x2c, 0);
-       reg_w(sd, 0x2d, 0);
-       reg_w(sd, 0x2e, 0);
-       reg_w(sd, 0x3b, 0);
-       reg_w(sd, 0x3c, 0);
-       reg_w(sd, 0x3d, 0);
-       reg_w(sd, 0x3e, 0);
-
-       if (sd->bridge == BRIDGE_OV518) {
-               /* Set 8-bit (YVYU) input format */
-               reg_w_mask(sd, 0x20, 0x08, 0x08);
-
-               /* Set 12-bit (4:2:0) output format */
-               reg_w_mask(sd, 0x28, 0x80, 0xf0);
-               reg_w_mask(sd, 0x38, 0x80, 0xf0);
-       } else {
-               reg_w(sd, 0x28, 0x80);
-               reg_w(sd, 0x38, 0x80);
-       }
-
-       hsegs = sd->gspca_dev.width / 16;
-       vsegs = sd->gspca_dev.height / 4;
-
-       reg_w(sd, 0x29, hsegs);
-       reg_w(sd, 0x2a, vsegs);
-
-       reg_w(sd, 0x39, hsegs);
-       reg_w(sd, 0x3a, vsegs);
-
-       /* Windows driver does this here; who knows why */
-       reg_w(sd, 0x2f, 0x80);
-
-       /******** Set the framerate ********/
-       sd->clockdiv = 1;
-
-       /* Mode independent, but framerate dependent, regs */
-       /* 0x51: Clock divider; Only works on some cams which use 2 crystals */
-       reg_w(sd, 0x51, 0x04);
-       reg_w(sd, 0x22, 0x18);
-       reg_w(sd, 0x23, 0xff);
-
-       if (sd->bridge == BRIDGE_OV518PLUS) {
-               switch (sd->sensor) {
-               case SEN_OV7620AE:
-                       if (sd->gspca_dev.width == 320) {
-                               reg_w(sd, 0x20, 0x00);
-                               reg_w(sd, 0x21, 0x19);
-                       } else {
-                               reg_w(sd, 0x20, 0x60);
-                               reg_w(sd, 0x21, 0x1f);
-                       }
-                       break;
-               case SEN_OV7620:
-                       reg_w(sd, 0x20, 0x00);
-                       reg_w(sd, 0x21, 0x19);
-                       break;
-               default:
-                       reg_w(sd, 0x21, 0x19);
-               }
-       } else
-               reg_w(sd, 0x71, 0x17);  /* Compression-related? */
-
-       /* FIXME: Sensor-specific */
-       /* Bit 5 is what matters here. Of course, it is "reserved" */
-       i2c_w(sd, 0x54, 0x23);
-
-       reg_w(sd, 0x2f, 0x80);
-
-       if (sd->bridge == BRIDGE_OV518PLUS) {
-               reg_w(sd, 0x24, 0x94);
-               reg_w(sd, 0x25, 0x90);
-               ov518_reg_w32(sd, 0xc4,    400, 2);     /* 190h   */
-               ov518_reg_w32(sd, 0xc6,    540, 2);     /* 21ch   */
-               ov518_reg_w32(sd, 0xc7,    540, 2);     /* 21ch   */
-               ov518_reg_w32(sd, 0xc8,    108, 2);     /* 6ch    */
-               ov518_reg_w32(sd, 0xca, 131098, 3);     /* 2001ah */
-               ov518_reg_w32(sd, 0xcb,    532, 2);     /* 214h   */
-               ov518_reg_w32(sd, 0xcc,   2400, 2);     /* 960h   */
-               ov518_reg_w32(sd, 0xcd,     32, 2);     /* 20h    */
-               ov518_reg_w32(sd, 0xce,    608, 2);     /* 260h   */
-       } else {
-               reg_w(sd, 0x24, 0x9f);
-               reg_w(sd, 0x25, 0x90);
-               ov518_reg_w32(sd, 0xc4,    400, 2);     /* 190h   */
-               ov518_reg_w32(sd, 0xc6,    381, 2);     /* 17dh   */
-               ov518_reg_w32(sd, 0xc7,    381, 2);     /* 17dh   */
-               ov518_reg_w32(sd, 0xc8,    128, 2);     /* 80h    */
-               ov518_reg_w32(sd, 0xca, 183331, 3);     /* 2cc23h */
-               ov518_reg_w32(sd, 0xcb,    746, 2);     /* 2eah   */
-               ov518_reg_w32(sd, 0xcc,   1750, 2);     /* 6d6h   */
-               ov518_reg_w32(sd, 0xcd,     45, 2);     /* 2dh    */
-               ov518_reg_w32(sd, 0xce,    851, 2);     /* 353h   */
-       }
-
-       reg_w(sd, 0x2f, 0x80);
-}
-
-/* Sets up the OV519 with the given image parameters
- *
- * OV519 needs a completely different approach, until we can figure out what
- * the individual registers do.
- *
- * Do not put any sensor-specific code in here (including I2C I/O functions)
- */
-static void ov519_mode_init_regs(struct sd *sd)
-{
-       static const struct ov_regvals mode_init_519_ov7670[] = {
-               { 0x5d, 0x03 }, /* Turn off suspend mode */
-               { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
-               { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */
-               { 0xa2, 0x20 }, /* a2-a5 are undocumented */
-               { 0xa3, 0x18 },
-               { 0xa4, 0x04 },
-               { 0xa5, 0x28 },
-               { 0x37, 0x00 }, /* SetUsbInit */
-               { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
-               /* Enable both fields, YUV Input, disable defect comp (why?) */
-               { 0x20, 0x0c },
-               { 0x21, 0x38 },
-               { 0x22, 0x1d },
-               { 0x17, 0x50 }, /* undocumented */
-               { 0x37, 0x00 }, /* undocumented */
-               { 0x40, 0xff }, /* I2C timeout counter */
-               { 0x46, 0x00 }, /* I2C clock prescaler */
-               { 0x59, 0x04 }, /* new from windrv 090403 */
-               { 0xff, 0x00 }, /* undocumented */
-               /* windows reads 0x55 at this point, why? */
-       };
-
-       static const struct ov_regvals mode_init_519[] = {
-               { 0x5d, 0x03 }, /* Turn off suspend mode */
-               { 0x53, 0x9f }, /* was 9b in 1.65-1.08 */
-               { OV519_R54_EN_CLK1, 0x0f }, /* bit2 (jpeg enable) */
-               { 0xa2, 0x20 }, /* a2-a5 are undocumented */
-               { 0xa3, 0x18 },
-               { 0xa4, 0x04 },
-               { 0xa5, 0x28 },
-               { 0x37, 0x00 }, /* SetUsbInit */
-               { 0x55, 0x02 }, /* 4.096 Mhz audio clock */
-               /* Enable both fields, YUV Input, disable defect comp (why?) */
-               { 0x22, 0x1d },
-               { 0x17, 0x50 }, /* undocumented */
-               { 0x37, 0x00 }, /* undocumented */
-               { 0x40, 0xff }, /* I2C timeout counter */
-               { 0x46, 0x00 }, /* I2C clock prescaler */
-               { 0x59, 0x04 }, /* new from windrv 090403 */
-               { 0xff, 0x00 }, /* undocumented */
-               /* windows reads 0x55 at this point, why? */
-       };
-
-       /******** Set the mode ********/
-       switch (sd->sensor) {
-       default:
-               write_regvals(sd, mode_init_519, ARRAY_SIZE(mode_init_519));
-               if (sd->sensor == SEN_OV7640 ||
-                   sd->sensor == SEN_OV7648) {
-                       /* Select 8-bit input mode */
-                       reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10);
-               }
-               break;
-       case SEN_OV7660:
-               return;         /* done by ov519_set_mode/fr() */
-       case SEN_OV7670:
-               write_regvals(sd, mode_init_519_ov7670,
-                               ARRAY_SIZE(mode_init_519_ov7670));
-               break;
-       }
-
-       reg_w(sd, OV519_R10_H_SIZE,     sd->gspca_dev.width >> 4);
-       reg_w(sd, OV519_R11_V_SIZE,     sd->gspca_dev.height >> 3);
-       if (sd->sensor == SEN_OV7670 &&
-           sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
-               reg_w(sd, OV519_R12_X_OFFSETL, 0x04);
-       else if (sd->sensor == SEN_OV7648 &&
-           sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
-               reg_w(sd, OV519_R12_X_OFFSETL, 0x01);
-       else
-               reg_w(sd, OV519_R12_X_OFFSETL, 0x00);
-       reg_w(sd, OV519_R13_X_OFFSETH,  0x00);
-       reg_w(sd, OV519_R14_Y_OFFSETL,  0x00);
-       reg_w(sd, OV519_R15_Y_OFFSETH,  0x00);
-       reg_w(sd, OV519_R16_DIVIDER,    0x00);
-       reg_w(sd, OV519_R25_FORMAT,     0x03); /* YUV422 */
-       reg_w(sd, 0x26,                 0x00); /* Undocumented */
-
-       /******** Set the framerate ********/
-       if (frame_rate > 0)
-               sd->frame_rate = frame_rate;
-
-/* FIXME: These are only valid at the max resolution. */
-       sd->clockdiv = 0;
-       switch (sd->sensor) {
-       case SEN_OV7640:
-       case SEN_OV7648:
-               switch (sd->frame_rate) {
-               default:
-/*             case 30: */
-                       reg_w(sd, 0xa4, 0x0c);
-                       reg_w(sd, 0x23, 0xff);
-                       break;
-               case 25:
-                       reg_w(sd, 0xa4, 0x0c);
-                       reg_w(sd, 0x23, 0x1f);
-                       break;
-               case 20:
-                       reg_w(sd, 0xa4, 0x0c);
-                       reg_w(sd, 0x23, 0x1b);
-                       break;
-               case 15:
-                       reg_w(sd, 0xa4, 0x04);
-                       reg_w(sd, 0x23, 0xff);
-                       sd->clockdiv = 1;
-                       break;
-               case 10:
-                       reg_w(sd, 0xa4, 0x04);
-                       reg_w(sd, 0x23, 0x1f);
-                       sd->clockdiv = 1;
-                       break;
-               case 5:
-                       reg_w(sd, 0xa4, 0x04);
-                       reg_w(sd, 0x23, 0x1b);
-                       sd->clockdiv = 1;
-                       break;
-               }
-               break;
-       case SEN_OV8610:
-               switch (sd->frame_rate) {
-               default:        /* 15 fps */
-/*             case 15: */
-                       reg_w(sd, 0xa4, 0x06);
-                       reg_w(sd, 0x23, 0xff);
-                       break;
-               case 10:
-                       reg_w(sd, 0xa4, 0x06);
-                       reg_w(sd, 0x23, 0x1f);
-                       break;
-               case 5:
-                       reg_w(sd, 0xa4, 0x06);
-                       reg_w(sd, 0x23, 0x1b);
-                       break;
-               }
-               break;
-       case SEN_OV7670:                /* guesses, based on 7640 */
-               PDEBUG(D_STREAM, "Setting framerate to %d fps",
-                                (sd->frame_rate == 0) ? 15 : sd->frame_rate);
-               reg_w(sd, 0xa4, 0x10);
-               switch (sd->frame_rate) {
-               case 30:
-                       reg_w(sd, 0x23, 0xff);
-                       break;
-               case 20:
-                       reg_w(sd, 0x23, 0x1b);
-                       break;
-               default:
-/*             case 15: */
-                       reg_w(sd, 0x23, 0xff);
-                       sd->clockdiv = 1;
-                       break;
-               }
-               break;
-       }
-}
-
-static void mode_init_ov_sensor_regs(struct sd *sd)
-{
-       struct gspca_dev *gspca_dev;
-       int qvga, xstart, xend, ystart, yend;
-       u8 v;
-
-       gspca_dev = &sd->gspca_dev;
-       qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
-
-       /******** Mode (VGA/QVGA) and sensor specific regs ********/
-       switch (sd->sensor) {
-       case SEN_OV2610:
-               i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
-               i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
-               i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
-               i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
-               i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
-               i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
-               i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
-               return;
-       case SEN_OV2610AE: {
-               u8 v;
-
-               /* frame rates:
-                *      10fps / 5 fps for 1600x1200
-                *      40fps / 20fps for 800x600
-                */
-               v = 80;
-               if (qvga) {
-                       if (sd->frame_rate < 25)
-                               v = 0x81;
-               } else {
-                       if (sd->frame_rate < 10)
-                               v = 0x81;
-               }
-               i2c_w(sd, 0x11, v);
-               i2c_w(sd, 0x12, qvga ? 0x60 : 0x20);
-               return;
-           }
-       case SEN_OV3610:
-               if (qvga) {
-                       xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4);
-                       ystart = (776 - gspca_dev->height) / 2;
-               } else {
-                       xstart = (2076 - gspca_dev->width) / 2 + (0x10 << 4);
-                       ystart = (1544 - gspca_dev->height) / 2;
-               }
-               xend = xstart + gspca_dev->width;
-               yend = ystart + gspca_dev->height;
-               /* Writing to the COMH register resets the other windowing regs
-                  to their default values, so we must do this first. */
-               i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0xf0);
-               i2c_w_mask(sd, 0x32,
-                          (((xend >> 1) & 7) << 3) | ((xstart >> 1) & 7),
-                          0x3f);
-               i2c_w_mask(sd, 0x03,
-                          (((yend >> 1) & 3) << 2) | ((ystart >> 1) & 3),
-                          0x0f);
-               i2c_w(sd, 0x17, xstart >> 4);
-               i2c_w(sd, 0x18, xend >> 4);
-               i2c_w(sd, 0x19, ystart >> 3);
-               i2c_w(sd, 0x1a, yend >> 3);
-               return;
-       case SEN_OV8610:
-               /* For OV8610 qvga means qsvga */
-               i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5);
-               i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
-               i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
-               i2c_w_mask(sd, 0x2d, 0x00, 0x40); /* from windrv 090403 */
-               i2c_w_mask(sd, 0x28, 0x20, 0x20); /* progressive mode on */
-               break;
-       case SEN_OV7610:
-               i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
-               i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e);
-               i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
-               i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
-               break;
-       case SEN_OV7620:
-       case SEN_OV7620AE:
-       case SEN_OV76BE:
-               i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
-               i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
-               i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
-               i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
-               i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
-               i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0);
-               i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
-               i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
-               i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
-               if (sd->sensor == SEN_OV76BE)
-                       i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e);
-               break;
-       case SEN_OV7640:
-       case SEN_OV7648:
-               i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
-               i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
-               /* Setting this undocumented bit in qvga mode removes a very
-                  annoying vertical shaking of the image */
-               i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
-               /* Unknown */
-               i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
-               /* Allow higher automatic gain (to allow higher framerates) */
-               i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
-               i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */
-               break;
-       case SEN_OV7670:
-               /* set COM7_FMT_VGA or COM7_FMT_QVGA
-                * do we need to set anything else?
-                *      HSTART etc are set in set_ov_sensor_window itself */
-               i2c_w_mask(sd, OV7670_R12_COM7,
-                        qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA,
-                        OV7670_COM7_FMT_MASK);
-               i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
-               i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_AWB,
-                               OV7670_COM8_AWB);
-               if (qvga) {             /* QVGA from ov7670.c by
-                                        * Jonathan Corbet */
-                       xstart = 164;
-                       xend = 28;
-                       ystart = 14;
-                       yend = 494;
-               } else {                /* VGA */
-                       xstart = 158;
-                       xend = 14;
-                       ystart = 10;
-                       yend = 490;
-               }
-               /* OV7670 hardware window registers are split across
-                * multiple locations */
-               i2c_w(sd, OV7670_R17_HSTART, xstart >> 3);
-               i2c_w(sd, OV7670_R18_HSTOP, xend >> 3);
-               v = i2c_r(sd, OV7670_R32_HREF);
-               v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07);
-               msleep(10);     /* need to sleep between read and write to
-                                * same reg! */
-               i2c_w(sd, OV7670_R32_HREF, v);
-
-               i2c_w(sd, OV7670_R19_VSTART, ystart >> 2);
-               i2c_w(sd, OV7670_R1A_VSTOP, yend >> 2);
-               v = i2c_r(sd, OV7670_R03_VREF);
-               v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03);
-               msleep(10);     /* need to sleep between read and write to
-                                * same reg! */
-               i2c_w(sd, OV7670_R03_VREF, v);
-               break;
-       case SEN_OV6620:
-               i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
-               i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */
-               i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
-               break;
-       case SEN_OV6630:
-       case SEN_OV66308AF:
-               i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
-               i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */
-               break;
-       case SEN_OV9600: {
-               const struct ov_i2c_regvals *vals;
-               static const struct ov_i2c_regvals sxga_15[] = {
-                       {0x11, 0x80}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75}
-               };
-               static const struct ov_i2c_regvals sxga_7_5[] = {
-                       {0x11, 0x81}, {0x14, 0x3e}, {0x24, 0x85}, {0x25, 0x75}
-               };
-               static const struct ov_i2c_regvals vga_30[] = {
-                       {0x11, 0x81}, {0x14, 0x7e}, {0x24, 0x70}, {0x25, 0x60}
-               };
-               static const struct ov_i2c_regvals vga_15[] = {
-                       {0x11, 0x83}, {0x14, 0x3e}, {0x24, 0x80}, {0x25, 0x70}
-               };
-
-               /* frame rates:
-                *      15fps / 7.5 fps for 1280x1024
-                *      30fps / 15fps for 640x480
-                */
-               i2c_w_mask(sd, 0x12, qvga ? 0x40 : 0x00, 0x40);
-               if (qvga)
-                       vals = sd->frame_rate < 30 ? vga_15 : vga_30;
-               else
-                       vals = sd->frame_rate < 15 ? sxga_7_5 : sxga_15;
-               write_i2c_regvals(sd, vals, ARRAY_SIZE(sxga_15));
-               return;
-           }
-       default:
-               return;
-       }
-
-       /******** Clock programming ********/
-       i2c_w(sd, 0x11, sd->clockdiv);
-}
-
-/* this function works for bridge ov519 and sensors ov7660 and ov7670 only */
-static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->gspca_dev.streaming)
-               reg_w(sd, OV519_R51_RESET1, 0x0f);      /* block stream */
-       i2c_w_mask(sd, OV7670_R1E_MVFP,
-               OV7670_MVFP_MIRROR * hflip | OV7670_MVFP_VFLIP * vflip,
-               OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP);
-       if (sd->gspca_dev.streaming)
-               reg_w(sd, OV519_R51_RESET1, 0x00);      /* restart stream */
-}
-
-static void set_ov_sensor_window(struct sd *sd)
-{
-       struct gspca_dev *gspca_dev;
-       int qvga, crop;
-       int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale;
-
-       /* mode setup is fully handled in mode_init_ov_sensor_regs for these */
-       switch (sd->sensor) {
-       case SEN_OV2610:
-       case SEN_OV2610AE:
-       case SEN_OV3610:
-       case SEN_OV7670:
-       case SEN_OV9600:
-               mode_init_ov_sensor_regs(sd);
-               return;
-       case SEN_OV7660:
-               ov519_set_mode(sd);
-               ov519_set_fr(sd);
-               return;
-       }
-
-       gspca_dev = &sd->gspca_dev;
-       qvga = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 1;
-       crop = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv & 2;
-
-       /* The different sensor ICs handle setting up of window differently.
-        * IF YOU SET IT WRONG, YOU WILL GET ALL ZERO ISOC DATA FROM OV51x!! */
-       switch (sd->sensor) {
-       case SEN_OV8610:
-               hwsbase = 0x1e;
-               hwebase = 0x1e;
-               vwsbase = 0x02;
-               vwebase = 0x02;
-               break;
-       case SEN_OV7610:
-       case SEN_OV76BE:
-               hwsbase = 0x38;
-               hwebase = 0x3a;
-               vwsbase = vwebase = 0x05;
-               break;
-       case SEN_OV6620:
-       case SEN_OV6630:
-       case SEN_OV66308AF:
-               hwsbase = 0x38;
-               hwebase = 0x3a;
-               vwsbase = 0x05;
-               vwebase = 0x06;
-               if (sd->sensor == SEN_OV66308AF && qvga)
-                       /* HDG: this fixes U and V getting swapped */
-                       hwsbase++;
-               if (crop) {
-                       hwsbase += 8;
-                       hwebase += 8;
-                       vwsbase += 11;
-                       vwebase += 11;
-               }
-               break;
-       case SEN_OV7620:
-       case SEN_OV7620AE:
-               hwsbase = 0x2f;         /* From 7620.SET (spec is wrong) */
-               hwebase = 0x2f;
-               vwsbase = vwebase = 0x05;
-               break;
-       case SEN_OV7640:
-       case SEN_OV7648:
-               hwsbase = 0x1a;
-               hwebase = 0x1a;
-               vwsbase = vwebase = 0x03;
-               break;
-       default:
-               return;
-       }
-
-       switch (sd->sensor) {
-       case SEN_OV6620:
-       case SEN_OV6630:
-       case SEN_OV66308AF:
-               if (qvga) {             /* QCIF */
-                       hwscale = 0;
-                       vwscale = 0;
-               } else {                /* CIF */
-                       hwscale = 1;
-                       vwscale = 1;    /* The datasheet says 0;
-                                        * it's wrong */
-               }
-               break;
-       case SEN_OV8610:
-               if (qvga) {             /* QSVGA */
-                       hwscale = 1;
-                       vwscale = 1;
-               } else {                /* SVGA */
-                       hwscale = 2;
-                       vwscale = 2;
-               }
-               break;
-       default:                        /* SEN_OV7xx0 */
-               if (qvga) {             /* QVGA */
-                       hwscale = 1;
-                       vwscale = 0;
-               } else {                /* VGA */
-                       hwscale = 2;
-                       vwscale = 1;
-               }
-       }
-
-       mode_init_ov_sensor_regs(sd);
-
-       i2c_w(sd, 0x17, hwsbase);
-       i2c_w(sd, 0x18, hwebase + (sd->sensor_width >> hwscale));
-       i2c_w(sd, 0x19, vwsbase);
-       i2c_w(sd, 0x1a, vwebase + (sd->sensor_height >> vwscale));
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* Default for most bridges, allow bridge_mode_init_regs to override */
-       sd->sensor_width = sd->gspca_dev.width;
-       sd->sensor_height = sd->gspca_dev.height;
-
-       switch (sd->bridge) {
-       case BRIDGE_OV511:
-       case BRIDGE_OV511PLUS:
-               ov511_mode_init_regs(sd);
-               break;
-       case BRIDGE_OV518:
-       case BRIDGE_OV518PLUS:
-               ov518_mode_init_regs(sd);
-               break;
-       case BRIDGE_OV519:
-               ov519_mode_init_regs(sd);
-               break;
-       /* case BRIDGE_OVFX2: nothing to do */
-       case BRIDGE_W9968CF:
-               w9968cf_mode_init_regs(sd);
-               break;
-       }
-
-       set_ov_sensor_window(sd);
-
-       /* Force clear snapshot state in case the snapshot button was
-          pressed while we weren't streaming */
-       sd->snapshot_needs_reset = 1;
-       sd_reset_snapshot(gspca_dev);
-
-       sd->first_frame = 3;
-
-       ov51x_restart(sd);
-       ov51x_led_control(sd, 1);
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       ov51x_stop(sd);
-       ov51x_led_control(sd, 0);
-}
-
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (!sd->gspca_dev.present)
-               return;
-       if (sd->bridge == BRIDGE_W9968CF)
-               w9968cf_stop0(sd);
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       /* If the last button state is pressed, release it now! */
-       if (sd->snapshot_pressed) {
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
-               input_sync(gspca_dev->input_dev);
-               sd->snapshot_pressed = 0;
-       }
-#endif
-       if (sd->bridge == BRIDGE_OV519)
-               reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
-}
-
-static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->snapshot_pressed != state) {
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, state);
-               input_sync(gspca_dev->input_dev);
-#endif
-               if (state)
-                       sd->snapshot_needs_reset = 1;
-
-               sd->snapshot_pressed = state;
-       } else {
-               /* On the ov511 / ov519 we need to reset the button state
-                  multiple times, as resetting does not work as long as the
-                  button stays pressed */
-               switch (sd->bridge) {
-               case BRIDGE_OV511:
-               case BRIDGE_OV511PLUS:
-               case BRIDGE_OV519:
-                       if (state)
-                               sd->snapshot_needs_reset = 1;
-                       break;
-               }
-       }
-}
-
-static void ov511_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *in,                 /* isoc packet */
-                       int len)                /* iso packet length */
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
-        * byte non-zero. The EOF packet has image width/height in the
-        * 10th and 11th bytes. The 9th byte is given as follows:
-        *
-        * bit 7: EOF
-        *     6: compression enabled
-        *     5: 422/420/400 modes
-        *     4: 422/420/400 modes
-        *     3: 1
-        *     2: snapshot button on
-        *     1: snapshot frame
-        *     0: even/odd field
-        */
-       if (!(in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) &&
-           (in[8] & 0x08)) {
-               ov51x_handle_button(gspca_dev, (in[8] >> 2) & 1);
-               if (in[8] & 0x80) {
-                       /* Frame end */
-                       if ((in[9] + 1) * 8 != gspca_dev->width ||
-                           (in[10] + 1) * 8 != gspca_dev->height) {
-                               PDEBUG(D_ERR, "Invalid frame size, got: %dx%d,"
-                                       " requested: %dx%d\n",
-                                       (in[9] + 1) * 8, (in[10] + 1) * 8,
-                                       gspca_dev->width, gspca_dev->height);
-                               gspca_dev->last_packet_type = DISCARD_PACKET;
-                               return;
-                       }
-                       /* Add 11 byte footer to frame, might be useful */
-                       gspca_frame_add(gspca_dev, LAST_PACKET, in, 11);
-                       return;
-               } else {
-                       /* Frame start */
-                       gspca_frame_add(gspca_dev, FIRST_PACKET, in, 0);
-                       sd->packet_nr = 0;
-               }
-       }
-
-       /* Ignore the packet number */
-       len--;
-
-       /* intermediate packet */
-       gspca_frame_add(gspca_dev, INTER_PACKET, in, len);
-}
-
-static void ov518_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,                       /* isoc packet */
-                       int len)                        /* iso packet length */
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* A false positive here is likely, until OVT gives me
-        * the definitive SOF/EOF format */
-       if ((!(data[0] | data[1] | data[2] | data[3] | data[5])) && data[6]) {
-               ov51x_handle_button(gspca_dev, (data[6] >> 1) & 1);
-               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-               gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
-               sd->packet_nr = 0;
-       }
-
-       if (gspca_dev->last_packet_type == DISCARD_PACKET)
-               return;
-
-       /* Does this device use packet numbers ? */
-       if (len & 7) {
-               len--;
-               if (sd->packet_nr == data[len])
-                       sd->packet_nr++;
-               /* The last few packets of the frame (which are all 0's
-                  except that they may contain part of the footer), are
-                  numbered 0 */
-               else if (sd->packet_nr == 0 || data[len]) {
-                       PDEBUG(D_ERR, "Invalid packet nr: %d (expect: %d)",
-                               (int)data[len], (int)sd->packet_nr);
-                       gspca_dev->last_packet_type = DISCARD_PACKET;
-                       return;
-               }
-       }
-
-       /* intermediate packet */
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-static void ov519_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,                       /* isoc packet */
-                       int len)                        /* iso packet length */
-{
-       /* Header of ov519 is 16 bytes:
-        *     Byte     Value      Description
-        *      0       0xff    magic
-        *      1       0xff    magic
-        *      2       0xff    magic
-        *      3       0xXX    0x50 = SOF, 0x51 = EOF
-        *      9       0xXX    0x01 initial frame without data,
-        *                      0x00 standard frame with image
-        *      14      Lo      in EOF: length of image data / 8
-        *      15      Hi
-        */
-
-       if (data[0] == 0xff && data[1] == 0xff && data[2] == 0xff) {
-               switch (data[3]) {
-               case 0x50:              /* start of frame */
-                       /* Don't check the button state here, as the state
-                          usually (always ?) changes at EOF and checking it
-                          here leads to unnecessary snapshot state resets. */
-#define HDRSZ 16
-                       data += HDRSZ;
-                       len -= HDRSZ;
-#undef HDRSZ
-                       if (data[0] == 0xff || data[1] == 0xd8)
-                               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                                               data, len);
-                       else
-                               gspca_dev->last_packet_type = DISCARD_PACKET;
-                       return;
-               case 0x51:              /* end of frame */
-                       ov51x_handle_button(gspca_dev, data[11] & 1);
-                       if (data[9] != 0)
-                               gspca_dev->last_packet_type = DISCARD_PACKET;
-                       gspca_frame_add(gspca_dev, LAST_PACKET,
-                                       NULL, 0);
-                       return;
-               }
-       }
-
-       /* intermediate packet */
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-static void ovfx2_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,                       /* isoc packet */
-                       int len)                        /* iso packet length */
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-
-       /* A short read signals EOF */
-       if (len < gspca_dev->cam.bulk_size) {
-               /* If the frame is short, and it is one of the first ones
-                  the sensor and bridge are still syncing, so drop it. */
-               if (sd->first_frame) {
-                       sd->first_frame--;
-                       if (gspca_dev->image_len <
-                                 sd->gspca_dev.width * sd->gspca_dev.height)
-                               gspca_dev->last_packet_type = DISCARD_PACKET;
-               }
-               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-               gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 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;
-
-       switch (sd->bridge) {
-       case BRIDGE_OV511:
-       case BRIDGE_OV511PLUS:
-               ov511_pkt_scan(gspca_dev, data, len);
-               break;
-       case BRIDGE_OV518:
-       case BRIDGE_OV518PLUS:
-               ov518_pkt_scan(gspca_dev, data, len);
-               break;
-       case BRIDGE_OV519:
-               ov519_pkt_scan(gspca_dev, data, len);
-               break;
-       case BRIDGE_OVFX2:
-               ovfx2_pkt_scan(gspca_dev, data, len);
-               break;
-       case BRIDGE_W9968CF:
-               w9968cf_pkt_scan(gspca_dev, data, len);
-               break;
-       }
-}
-
-/* -- management routines -- */
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       static const struct ov_i2c_regvals brit_7660[][7] = {
-               {{0x0f, 0x6a}, {0x24, 0x40}, {0x25, 0x2b}, {0x26, 0x90},
-                       {0x27, 0xe0}, {0x28, 0xe0}, {0x2c, 0xe0}},
-               {{0x0f, 0x6a}, {0x24, 0x50}, {0x25, 0x40}, {0x26, 0xa1},
-                       {0x27, 0xc0}, {0x28, 0xc0}, {0x2c, 0xc0}},
-               {{0x0f, 0x6a}, {0x24, 0x68}, {0x25, 0x58}, {0x26, 0xc2},
-                       {0x27, 0xa0}, {0x28, 0xa0}, {0x2c, 0xa0}},
-               {{0x0f, 0x6a}, {0x24, 0x70}, {0x25, 0x68}, {0x26, 0xd3},
-                       {0x27, 0x80}, {0x28, 0x80}, {0x2c, 0x80}},
-               {{0x0f, 0x6a}, {0x24, 0x80}, {0x25, 0x70}, {0x26, 0xd3},
-                       {0x27, 0x20}, {0x28, 0x20}, {0x2c, 0x20}},
-               {{0x0f, 0x6a}, {0x24, 0x88}, {0x25, 0x78}, {0x26, 0xd3},
-                       {0x27, 0x40}, {0x28, 0x40}, {0x2c, 0x40}},
-               {{0x0f, 0x6a}, {0x24, 0x90}, {0x25, 0x80}, {0x26, 0xd4},
-                       {0x27, 0x60}, {0x28, 0x60}, {0x2c, 0x60}}
-       };
-
-       switch (sd->sensor) {
-       case SEN_OV8610:
-       case SEN_OV7610:
-       case SEN_OV76BE:
-       case SEN_OV6620:
-       case SEN_OV6630:
-       case SEN_OV66308AF:
-       case SEN_OV7640:
-       case SEN_OV7648:
-               i2c_w(sd, OV7610_REG_BRT, val);
-               break;
-       case SEN_OV7620:
-       case SEN_OV7620AE:
-               i2c_w(sd, OV7610_REG_BRT, val);
-               break;
-       case SEN_OV7660:
-               write_i2c_regvals(sd, brit_7660[val],
-                               ARRAY_SIZE(brit_7660[0]));
-               break;
-       case SEN_OV7670:
-/*win trace
- *             i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_AEC); */
-               i2c_w(sd, OV7670_R55_BRIGHT, ov7670_abs_to_sm(val));
-               break;
-       }
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       static const struct ov_i2c_regvals contrast_7660[][31] = {
-               {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0xa0},
-                {0x70, 0x58}, {0x71, 0x38}, {0x72, 0x30}, {0x73, 0x30},
-                {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x24}, {0x77, 0x24},
-                {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x34},
-                {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x65},
-                {0x80, 0x70}, {0x81, 0x77}, {0x82, 0x7d}, {0x83, 0x83},
-                {0x84, 0x88}, {0x85, 0x8d}, {0x86, 0x96}, {0x87, 0x9f},
-                {0x88, 0xb0}, {0x89, 0xc4}, {0x8a, 0xd9}},
-               {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf8}, {0x6f, 0x94},
-                {0x70, 0x58}, {0x71, 0x40}, {0x72, 0x30}, {0x73, 0x30},
-                {0x74, 0x30}, {0x75, 0x30}, {0x76, 0x2c}, {0x77, 0x24},
-                {0x78, 0x22}, {0x79, 0x28}, {0x7a, 0x2a}, {0x7b, 0x31},
-                {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3d}, {0x7f, 0x62},
-                {0x80, 0x6d}, {0x81, 0x75}, {0x82, 0x7b}, {0x83, 0x81},
-                {0x84, 0x87}, {0x85, 0x8d}, {0x86, 0x98}, {0x87, 0xa1},
-                {0x88, 0xb2}, {0x89, 0xc6}, {0x8a, 0xdb}},
-               {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x84},
-                {0x70, 0x58}, {0x71, 0x48}, {0x72, 0x40}, {0x73, 0x40},
-                {0x74, 0x28}, {0x75, 0x28}, {0x76, 0x28}, {0x77, 0x24},
-                {0x78, 0x26}, {0x79, 0x28}, {0x7a, 0x28}, {0x7b, 0x34},
-                {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x5d},
-                {0x80, 0x68}, {0x81, 0x71}, {0x82, 0x79}, {0x83, 0x81},
-                {0x84, 0x86}, {0x85, 0x8b}, {0x86, 0x95}, {0x87, 0x9e},
-                {0x88, 0xb1}, {0x89, 0xc5}, {0x8a, 0xd9}},
-               {{0x6c, 0xf0}, {0x6d, 0xf0}, {0x6e, 0xf0}, {0x6f, 0x70},
-                {0x70, 0x58}, {0x71, 0x58}, {0x72, 0x48}, {0x73, 0x48},
-                {0x74, 0x38}, {0x75, 0x40}, {0x76, 0x34}, {0x77, 0x34},
-                {0x78, 0x2e}, {0x79, 0x28}, {0x7a, 0x24}, {0x7b, 0x22},
-                {0x7c, 0x0f}, {0x7d, 0x1e}, {0x7e, 0x3c}, {0x7f, 0x58},
-                {0x80, 0x63}, {0x81, 0x6e}, {0x82, 0x77}, {0x83, 0x80},
-                {0x84, 0x87}, {0x85, 0x8f}, {0x86, 0x9c}, {0x87, 0xa9},
-                {0x88, 0xc0}, {0x89, 0xd4}, {0x8a, 0xe6}},
-               {{0x6c, 0xa0}, {0x6d, 0xf0}, {0x6e, 0x90}, {0x6f, 0x80},
-                {0x70, 0x70}, {0x71, 0x80}, {0x72, 0x60}, {0x73, 0x60},
-                {0x74, 0x58}, {0x75, 0x60}, {0x76, 0x4c}, {0x77, 0x38},
-                {0x78, 0x38}, {0x79, 0x2a}, {0x7a, 0x20}, {0x7b, 0x0e},
-                {0x7c, 0x0a}, {0x7d, 0x14}, {0x7e, 0x26}, {0x7f, 0x46},
-                {0x80, 0x54}, {0x81, 0x64}, {0x82, 0x70}, {0x83, 0x7c},
-                {0x84, 0x87}, {0x85, 0x93}, {0x86, 0xa6}, {0x87, 0xb4},
-                {0x88, 0xd0}, {0x89, 0xe5}, {0x8a, 0xf5}},
-               {{0x6c, 0x60}, {0x6d, 0x80}, {0x6e, 0x60}, {0x6f, 0x80},
-                {0x70, 0x80}, {0x71, 0x80}, {0x72, 0x88}, {0x73, 0x30},
-                {0x74, 0x70}, {0x75, 0x68}, {0x76, 0x64}, {0x77, 0x50},
-                {0x78, 0x3c}, {0x79, 0x22}, {0x7a, 0x10}, {0x7b, 0x08},
-                {0x7c, 0x06}, {0x7d, 0x0e}, {0x7e, 0x1a}, {0x7f, 0x3a},
-                {0x80, 0x4a}, {0x81, 0x5a}, {0x82, 0x6b}, {0x83, 0x7b},
-                {0x84, 0x89}, {0x85, 0x96}, {0x86, 0xaf}, {0x87, 0xc3},
-                {0x88, 0xe1}, {0x89, 0xf2}, {0x8a, 0xfa}},
-               {{0x6c, 0x20}, {0x6d, 0x40}, {0x6e, 0x20}, {0x6f, 0x60},
-                {0x70, 0x88}, {0x71, 0xc8}, {0x72, 0xc0}, {0x73, 0xb8},
-                {0x74, 0xa8}, {0x75, 0xb8}, {0x76, 0x80}, {0x77, 0x5c},
-                {0x78, 0x26}, {0x79, 0x10}, {0x7a, 0x08}, {0x7b, 0x04},
-                {0x7c, 0x02}, {0x7d, 0x06}, {0x7e, 0x0a}, {0x7f, 0x22},
-                {0x80, 0x33}, {0x81, 0x4c}, {0x82, 0x64}, {0x83, 0x7b},
-                {0x84, 0x90}, {0x85, 0xa7}, {0x86, 0xc7}, {0x87, 0xde},
-                {0x88, 0xf1}, {0x89, 0xf9}, {0x8a, 0xfd}},
-       };
-
-       switch (sd->sensor) {
-       case SEN_OV7610:
-       case SEN_OV6620:
-               i2c_w(sd, OV7610_REG_CNT, val);
-               break;
-       case SEN_OV6630:
-       case SEN_OV66308AF:
-               i2c_w_mask(sd, OV7610_REG_CNT, val >> 4, 0x0f);
-               break;
-       case SEN_OV8610: {
-               static const u8 ctab[] = {
-                       0x03, 0x09, 0x0b, 0x0f, 0x53, 0x6f, 0x35, 0x7f
-               };
-
-               /* Use Y gamma control instead. Bit 0 enables it. */
-               i2c_w(sd, 0x64, ctab[val >> 5]);
-               break;
-           }
-       case SEN_OV7620:
-       case SEN_OV7620AE: {
-               static const u8 ctab[] = {
-                       0x01, 0x05, 0x09, 0x11, 0x15, 0x35, 0x37, 0x57,
-                       0x5b, 0xa5, 0xa7, 0xc7, 0xc9, 0xcf, 0xef, 0xff
-               };
-
-               /* Use Y gamma control instead. Bit 0 enables it. */
-               i2c_w(sd, 0x64, ctab[val >> 4]);
-               break;
-           }
-       case SEN_OV7660:
-               write_i2c_regvals(sd, contrast_7660[val],
-                                       ARRAY_SIZE(contrast_7660[0]));
-               break;
-       case SEN_OV7670:
-               /* check that this isn't just the same as ov7610 */
-               i2c_w(sd, OV7670_R56_CONTRAS, val >> 1);
-               break;
-       }
-}
-
-static void setexposure(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       i2c_w(sd, 0x10, val);
-}
-
-static void setcolors(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       static const struct ov_i2c_regvals colors_7660[][6] = {
-               {{0x4f, 0x28}, {0x50, 0x2a}, {0x51, 0x02}, {0x52, 0x0a},
-                {0x53, 0x19}, {0x54, 0x23}},
-               {{0x4f, 0x47}, {0x50, 0x4a}, {0x51, 0x03}, {0x52, 0x11},
-                {0x53, 0x2c}, {0x54, 0x3e}},
-               {{0x4f, 0x66}, {0x50, 0x6b}, {0x51, 0x05}, {0x52, 0x19},
-                {0x53, 0x40}, {0x54, 0x59}},
-               {{0x4f, 0x84}, {0x50, 0x8b}, {0x51, 0x06}, {0x52, 0x20},
-                {0x53, 0x53}, {0x54, 0x73}},
-               {{0x4f, 0xa3}, {0x50, 0xab}, {0x51, 0x08}, {0x52, 0x28},
-                {0x53, 0x66}, {0x54, 0x8e}},
-       };
-
-       switch (sd->sensor) {
-       case SEN_OV8610:
-       case SEN_OV7610:
-       case SEN_OV76BE:
-       case SEN_OV6620:
-       case SEN_OV6630:
-       case SEN_OV66308AF:
-               i2c_w(sd, OV7610_REG_SAT, val);
-               break;
-       case SEN_OV7620:
-       case SEN_OV7620AE:
-               /* Use UV gamma control instead. Bits 0 & 7 are reserved. */
-/*             rc = ov_i2c_write(sd->dev, 0x62, (val >> 9) & 0x7e);
-               if (rc < 0)
-                       goto out; */
-               i2c_w(sd, OV7610_REG_SAT, val);
-               break;
-       case SEN_OV7640:
-       case SEN_OV7648:
-               i2c_w(sd, OV7610_REG_SAT, val & 0xf0);
-               break;
-       case SEN_OV7660:
-               write_i2c_regvals(sd, colors_7660[val],
-                                       ARRAY_SIZE(colors_7660[0]));
-               break;
-       case SEN_OV7670:
-               /* supported later once I work out how to do it
-                * transparently fail now! */
-               /* set REG_COM13 values for UV sat auto mode */
-               break;
-       }
-}
-
-static void setautobright(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       i2c_w_mask(sd, 0x2d, val ? 0x10 : 0x00, 0x10);
-}
-
-static void setfreq_i(struct sd *sd, s32 val)
-{
-       if (sd->sensor == SEN_OV7660
-        || sd->sensor == SEN_OV7670) {
-               switch (val) {
-               case 0: /* Banding filter disabled */
-                       i2c_w_mask(sd, OV7670_R13_COM8, 0, OV7670_COM8_BFILT);
-                       break;
-               case 1: /* 50 hz */
-                       i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
-                                  OV7670_COM8_BFILT);
-                       i2c_w_mask(sd, OV7670_R3B_COM11, 0x08, 0x18);
-                       break;
-               case 2: /* 60 hz */
-                       i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
-                                  OV7670_COM8_BFILT);
-                       i2c_w_mask(sd, OV7670_R3B_COM11, 0x00, 0x18);
-                       break;
-               case 3: /* Auto hz - ov7670 only */
-                       i2c_w_mask(sd, OV7670_R13_COM8, OV7670_COM8_BFILT,
-                                  OV7670_COM8_BFILT);
-                       i2c_w_mask(sd, OV7670_R3B_COM11, OV7670_COM11_HZAUTO,
-                                  0x18);
-                       break;
-               }
-       } else {
-               switch (val) {
-               case 0: /* Banding filter disabled */
-                       i2c_w_mask(sd, 0x2d, 0x00, 0x04);
-                       i2c_w_mask(sd, 0x2a, 0x00, 0x80);
-                       break;
-               case 1: /* 50 hz (filter on and framerate adj) */
-                       i2c_w_mask(sd, 0x2d, 0x04, 0x04);
-                       i2c_w_mask(sd, 0x2a, 0x80, 0x80);
-                       /* 20 fps -> 16.667 fps */
-                       if (sd->sensor == SEN_OV6620 ||
-                           sd->sensor == SEN_OV6630 ||
-                           sd->sensor == SEN_OV66308AF)
-                               i2c_w(sd, 0x2b, 0x5e);
-                       else
-                               i2c_w(sd, 0x2b, 0xac);
-                       break;
-               case 2: /* 60 hz (filter on, ...) */
-                       i2c_w_mask(sd, 0x2d, 0x04, 0x04);
-                       if (sd->sensor == SEN_OV6620 ||
-                           sd->sensor == SEN_OV6630 ||
-                           sd->sensor == SEN_OV66308AF) {
-                               /* 20 fps -> 15 fps */
-                               i2c_w_mask(sd, 0x2a, 0x80, 0x80);
-                               i2c_w(sd, 0x2b, 0xa8);
-                       } else {
-                               /* no framerate adj. */
-                               i2c_w_mask(sd, 0x2a, 0x00, 0x80);
-                       }
-                       break;
-               }
-       }
-}
-
-static void setfreq(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       setfreq_i(sd, val);
-
-       /* Ugly but necessary */
-       if (sd->bridge == BRIDGE_W9968CF)
-               w9968cf_set_crop_window(sd);
-}
-
-static int sd_get_jcomp(struct gspca_dev *gspca_dev,
-                       struct v4l2_jpegcompression *jcomp)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->bridge != BRIDGE_W9968CF)
-               return -ENOTTY;
-
-       memset(jcomp, 0, sizeof *jcomp);
-       jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
-       jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT |
-                             V4L2_JPEG_MARKER_DRI;
-       return 0;
-}
-
-static int sd_set_jcomp(struct gspca_dev *gspca_dev,
-                       struct v4l2_jpegcompression *jcomp)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->bridge != BRIDGE_W9968CF)
-               return -ENOTTY;
-
-       v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
-       return 0;
-}
-
-static int sd_g_volatile_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;
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUTOGAIN:
-               gspca_dev->exposure->val = i2c_r(sd, 0x10);
-               break;
-       }
-       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_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_POWER_LINE_FREQUENCY:
-               setfreq(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_AUTOBRIGHTNESS:
-               if (ctrl->is_new)
-                       setautobright(gspca_dev, ctrl->val);
-               if (!ctrl->val && sd->brightness->is_new)
-                       setbrightness(gspca_dev, sd->brightness->val);
-               break;
-       case V4L2_CID_SATURATION:
-               setcolors(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_HFLIP:
-               sethvflip(gspca_dev, ctrl->val, sd->vflip->val);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               if (ctrl->is_new)
-                       setautogain(gspca_dev, ctrl->val);
-               if (!ctrl->val && gspca_dev->exposure->is_new)
-                       setexposure(gspca_dev, gspca_dev->exposure->val);
-               break;
-       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
-               return -EBUSY; /* Should never happen, as we grab the ctrl */
-       }
-       return gspca_dev->usb_err;
-}
-
-static const struct v4l2_ctrl_ops sd_ctrl_ops = {
-       .g_volatile_ctrl = sd_g_volatile_ctrl,
-       .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, 10);
-       if (valid_controls[sd->sensor].has_brightness)
-               sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0,
-                       sd->sensor == SEN_OV7660 ? 6 : 255, 1,
-                       sd->sensor == SEN_OV7660 ? 3 : 127);
-       if (valid_controls[sd->sensor].has_contrast) {
-               if (sd->sensor == SEN_OV7660)
-                       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                               V4L2_CID_CONTRAST, 0, 6, 1, 3);
-               else
-                       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                               V4L2_CID_CONTRAST, 0, 255, 1,
-                               (sd->sensor == SEN_OV6630 ||
-                                sd->sensor == SEN_OV66308AF) ? 200 : 127);
-       }
-       if (valid_controls[sd->sensor].has_sat)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 0,
-                       sd->sensor == SEN_OV7660 ? 4 : 255, 1,
-                       sd->sensor == SEN_OV7660 ? 2 : 127);
-       if (valid_controls[sd->sensor].has_exposure)
-               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 0, 255, 1, 127);
-       if (valid_controls[sd->sensor].has_hvflip) {
-               sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_HFLIP, 0, 1, 1, 0);
-               sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_VFLIP, 0, 1, 1, 0);
-       }
-       if (valid_controls[sd->sensor].has_autobright)
-               sd->autobright = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_AUTOBRIGHTNESS, 0, 1, 1, 1);
-       if (valid_controls[sd->sensor].has_autogain)
-               gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-       if (valid_controls[sd->sensor].has_freq) {
-               if (sd->sensor == SEN_OV7670)
-                       sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
-                               V4L2_CID_POWER_LINE_FREQUENCY,
-                               V4L2_CID_POWER_LINE_FREQUENCY_AUTO, 0,
-                               V4L2_CID_POWER_LINE_FREQUENCY_AUTO);
-               else
-                       sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
-                               V4L2_CID_POWER_LINE_FREQUENCY,
-                               V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
-       }
-       if (sd->bridge == BRIDGE_W9968CF)
-               sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_JPEG_COMPRESSION_QUALITY,
-                       QUALITY_MIN, QUALITY_MAX, 1, QUALITY_DEF);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-       if (gspca_dev->autogain)
-               v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, true);
-       if (sd->autobright)
-               v4l2_ctrl_auto_cluster(2, &sd->autobright, 0, false);
-       if (sd->hflip)
-               v4l2_ctrl_cluster(2, &sd->hflip);
-       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,
-       .isoc_init = sd_isoc_init,
-       .start = sd_start,
-       .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .pkt_scan = sd_pkt_scan,
-       .dq_callback = sd_reset_snapshot,
-       .get_jcomp = sd_get_jcomp,
-       .set_jcomp = sd_set_jcomp,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .other_input = 1,
-#endif
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x041e, 0x4003), .driver_info = BRIDGE_W9968CF },
-       {USB_DEVICE(0x041e, 0x4052),
-               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
-       {USB_DEVICE(0x041e, 0x405f), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x041e, 0x4060), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x041e, 0x4061), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x041e, 0x4064), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x041e, 0x4067), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x041e, 0x4068), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x045e, 0x028c),
-               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
-       {USB_DEVICE(0x054c, 0x0154), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x054c, 0x0155), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x05a9, 0x0511), .driver_info = BRIDGE_OV511 },
-       {USB_DEVICE(0x05a9, 0x0518), .driver_info = BRIDGE_OV518 },
-       {USB_DEVICE(0x05a9, 0x0519),
-               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
-       {USB_DEVICE(0x05a9, 0x0530),
-               .driver_info = BRIDGE_OV519 | BRIDGE_INVERT_LED },
-       {USB_DEVICE(0x05a9, 0x2800), .driver_info = BRIDGE_OVFX2 },
-       {USB_DEVICE(0x05a9, 0x4519), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x05a9, 0x8519), .driver_info = BRIDGE_OV519 },
-       {USB_DEVICE(0x05a9, 0xa511), .driver_info = BRIDGE_OV511PLUS },
-       {USB_DEVICE(0x05a9, 0xa518), .driver_info = BRIDGE_OV518PLUS },
-       {USB_DEVICE(0x0813, 0x0002), .driver_info = BRIDGE_OV511PLUS },
-       {USB_DEVICE(0x0b62, 0x0059), .driver_info = BRIDGE_OVFX2 },
-       {USB_DEVICE(0x0e96, 0xc001), .driver_info = BRIDGE_OVFX2 },
-       {USB_DEVICE(0x1046, 0x9967), .driver_info = BRIDGE_W9968CF },
-       {USB_DEVICE(0x8020, 0xef04), .driver_info = BRIDGE_OVFX2 },
-       {}
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
-
-module_param(frame_rate, int, 0644);
-MODULE_PARM_DESC(frame_rate, "Frame rate (5, 10, 15, 20 or 30 fps)");
diff --git a/drivers/media/video/gspca/ov534.c b/drivers/media/video/gspca/ov534.c
deleted file mode 100644 (file)
index bb09d78..0000000
+++ /dev/null
@@ -1,1544 +0,0 @@
-/*
- * ov534-ov7xxx gspca driver
- *
- * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
- * Copyright (C) 2008 Jim Paris <jim@jtan.com>
- * Copyright (C) 2009 Jean-Francois Moine http://moinejf.free.fr
- *
- * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>
- * USB protocol reverse engineered by Jim Paris <jim@jtan.com>
- * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/
- *
- * 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>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "ov534"
-
-#include "gspca.h"
-
-#include <linux/fixp-arith.h>
-#include <media/v4l2-ctrls.h>
-
-#define OV534_REG_ADDRESS      0xf1    /* sensor address */
-#define OV534_REG_SUBADDR      0xf2
-#define OV534_REG_WRITE                0xf3
-#define OV534_REG_READ         0xf4
-#define OV534_REG_OPERATION    0xf5
-#define OV534_REG_STATUS       0xf6
-
-#define OV534_OP_WRITE_3       0x37
-#define OV534_OP_WRITE_2       0x33
-#define OV534_OP_READ_2                0xf9
-
-#define CTRL_TIMEOUT 500
-
-MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
-MODULE_DESCRIPTION("GSPCA/OV534 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       struct v4l2_ctrl_handler ctrl_handler;
-       struct v4l2_ctrl *hue;
-       struct v4l2_ctrl *saturation;
-       struct v4l2_ctrl *brightness;
-       struct v4l2_ctrl *contrast;
-       struct { /* gain control cluster */
-               struct v4l2_ctrl *autogain;
-               struct v4l2_ctrl *gain;
-       };
-       struct v4l2_ctrl *autowhitebalance;
-       struct { /* exposure control cluster */
-               struct v4l2_ctrl *autoexposure;
-               struct v4l2_ctrl *exposure;
-       };
-       struct v4l2_ctrl *sharpness;
-       struct v4l2_ctrl *hflip;
-       struct v4l2_ctrl *vflip;
-       struct v4l2_ctrl *plfreq;
-
-       __u32 last_pts;
-       u16 last_fid;
-       u8 frame_rate;
-
-       u8 sensor;
-};
-enum sensors {
-       SENSOR_OV767x,
-       SENSOR_OV772x,
-       NSENSORS
-};
-
-static int sd_start(struct gspca_dev *gspca_dev);
-static void sd_stopN(struct gspca_dev *gspca_dev);
-
-
-static const struct v4l2_pix_format ov772x_mode[] = {
-       {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-        .bytesperline = 320 * 2,
-        .sizeimage = 320 * 240 * 2,
-        .colorspace = V4L2_COLORSPACE_SRGB,
-        .priv = 1},
-       {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-        .bytesperline = 640 * 2,
-        .sizeimage = 640 * 480 * 2,
-        .colorspace = V4L2_COLORSPACE_SRGB,
-        .priv = 0},
-};
-static const struct v4l2_pix_format ov767x_mode[] = {
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-};
-
-static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30};
-static const u8 vga_rates[] = {60, 50, 40, 30, 15};
-
-static const struct framerates ov772x_framerates[] = {
-       { /* 320x240 */
-               .rates = qvga_rates,
-               .nrates = ARRAY_SIZE(qvga_rates),
-       },
-       { /* 640x480 */
-               .rates = vga_rates,
-               .nrates = ARRAY_SIZE(vga_rates),
-       },
-};
-
-struct reg_array {
-       const u8 (*val)[2];
-       int len;
-};
-
-static const u8 bridge_init_767x[][2] = {
-/* comments from the ms-win file apollo7670.set */
-/* str1 */
-       {0xf1, 0x42},
-       {0x88, 0xf8},
-       {0x89, 0xff},
-       {0x76, 0x03},
-       {0x92, 0x03},
-       {0x95, 0x10},
-       {0xe2, 0x00},
-       {0xe7, 0x3e},
-       {0x8d, 0x1c},
-       {0x8e, 0x00},
-       {0x8f, 0x00},
-       {0x1f, 0x00},
-       {0xc3, 0xf9},
-       {0x89, 0xff},
-       {0x88, 0xf8},
-       {0x76, 0x03},
-       {0x92, 0x01},
-       {0x93, 0x18},
-       {0x1c, 0x00},
-       {0x1d, 0x48},
-       {0x1d, 0x00},
-       {0x1d, 0xff},
-       {0x1d, 0x02},
-       {0x1d, 0x58},
-       {0x1d, 0x00},
-       {0x1c, 0x0a},
-       {0x1d, 0x0a},
-       {0x1d, 0x0e},
-       {0xc0, 0x50},   /* HSize 640 */
-       {0xc1, 0x3c},   /* VSize 480 */
-       {0x34, 0x05},   /* enable Audio Suspend mode */
-       {0xc2, 0x0c},   /* Input YUV */
-       {0xc3, 0xf9},   /* enable PRE */
-       {0x34, 0x05},   /* enable Audio Suspend mode */
-       {0xe7, 0x2e},   /* this solves failure of "SuspendResumeTest" */
-       {0x31, 0xf9},   /* enable 1.8V Suspend */
-       {0x35, 0x02},   /* turn on JPEG */
-       {0xd9, 0x10},
-       {0x25, 0x42},   /* GPIO[8]:Input */
-       {0x94, 0x11},   /* If the default setting is loaded when
-                        * system boots up, this flag is closed here */
-};
-static const u8 sensor_init_767x[][2] = {
-       {0x12, 0x80},
-       {0x11, 0x03},
-       {0x3a, 0x04},
-       {0x12, 0x00},
-       {0x17, 0x13},
-       {0x18, 0x01},
-       {0x32, 0xb6},
-       {0x19, 0x02},
-       {0x1a, 0x7a},
-       {0x03, 0x0a},
-       {0x0c, 0x00},
-       {0x3e, 0x00},
-       {0x70, 0x3a},
-       {0x71, 0x35},
-       {0x72, 0x11},
-       {0x73, 0xf0},
-       {0xa2, 0x02},
-       {0x7a, 0x2a},   /* set Gamma=1.6 below */
-       {0x7b, 0x12},
-       {0x7c, 0x1d},
-       {0x7d, 0x2d},
-       {0x7e, 0x45},
-       {0x7f, 0x50},
-       {0x80, 0x59},
-       {0x81, 0x62},
-       {0x82, 0x6b},
-       {0x83, 0x73},
-       {0x84, 0x7b},
-       {0x85, 0x8a},
-       {0x86, 0x98},
-       {0x87, 0xb2},
-       {0x88, 0xca},
-       {0x89, 0xe0},
-       {0x13, 0xe0},
-       {0x00, 0x00},
-       {0x10, 0x00},
-       {0x0d, 0x40},
-       {0x14, 0x38},   /* gain max 16x */
-       {0xa5, 0x05},
-       {0xab, 0x07},
-       {0x24, 0x95},
-       {0x25, 0x33},
-       {0x26, 0xe3},
-       {0x9f, 0x78},
-       {0xa0, 0x68},
-       {0xa1, 0x03},
-       {0xa6, 0xd8},
-       {0xa7, 0xd8},
-       {0xa8, 0xf0},
-       {0xa9, 0x90},
-       {0xaa, 0x94},
-       {0x13, 0xe5},
-       {0x0e, 0x61},
-       {0x0f, 0x4b},
-       {0x16, 0x02},
-       {0x21, 0x02},
-       {0x22, 0x91},
-       {0x29, 0x07},
-       {0x33, 0x0b},
-       {0x35, 0x0b},
-       {0x37, 0x1d},
-       {0x38, 0x71},
-       {0x39, 0x2a},
-       {0x3c, 0x78},
-       {0x4d, 0x40},
-       {0x4e, 0x20},
-       {0x69, 0x00},
-       {0x6b, 0x4a},
-       {0x74, 0x10},
-       {0x8d, 0x4f},
-       {0x8e, 0x00},
-       {0x8f, 0x00},
-       {0x90, 0x00},
-       {0x91, 0x00},
-       {0x96, 0x00},
-       {0x9a, 0x80},
-       {0xb0, 0x84},
-       {0xb1, 0x0c},
-       {0xb2, 0x0e},
-       {0xb3, 0x82},
-       {0xb8, 0x0a},
-       {0x43, 0x0a},
-       {0x44, 0xf0},
-       {0x45, 0x34},
-       {0x46, 0x58},
-       {0x47, 0x28},
-       {0x48, 0x3a},
-       {0x59, 0x88},
-       {0x5a, 0x88},
-       {0x5b, 0x44},
-       {0x5c, 0x67},
-       {0x5d, 0x49},
-       {0x5e, 0x0e},
-       {0x6c, 0x0a},
-       {0x6d, 0x55},
-       {0x6e, 0x11},
-       {0x6f, 0x9f},
-       {0x6a, 0x40},
-       {0x01, 0x40},
-       {0x02, 0x40},
-       {0x13, 0xe7},
-       {0x4f, 0x80},
-       {0x50, 0x80},
-       {0x51, 0x00},
-       {0x52, 0x22},
-       {0x53, 0x5e},
-       {0x54, 0x80},
-       {0x58, 0x9e},
-       {0x41, 0x08},
-       {0x3f, 0x00},
-       {0x75, 0x04},
-       {0x76, 0xe1},
-       {0x4c, 0x00},
-       {0x77, 0x01},
-       {0x3d, 0xc2},
-       {0x4b, 0x09},
-       {0xc9, 0x60},
-       {0x41, 0x38},   /* jfm: auto sharpness + auto de-noise  */
-       {0x56, 0x40},
-       {0x34, 0x11},
-       {0x3b, 0xc2},
-       {0xa4, 0x8a},   /* Night mode trigger point */
-       {0x96, 0x00},
-       {0x97, 0x30},
-       {0x98, 0x20},
-       {0x99, 0x20},
-       {0x9a, 0x84},
-       {0x9b, 0x29},
-       {0x9c, 0x03},
-       {0x9d, 0x4c},
-       {0x9e, 0x3f},
-       {0x78, 0x04},
-       {0x79, 0x01},
-       {0xc8, 0xf0},
-       {0x79, 0x0f},
-       {0xc8, 0x00},
-       {0x79, 0x10},
-       {0xc8, 0x7e},
-       {0x79, 0x0a},
-       {0xc8, 0x80},
-       {0x79, 0x0b},
-       {0xc8, 0x01},
-       {0x79, 0x0c},
-       {0xc8, 0x0f},
-       {0x79, 0x0d},
-       {0xc8, 0x20},
-       {0x79, 0x09},
-       {0xc8, 0x80},
-       {0x79, 0x02},
-       {0xc8, 0xc0},
-       {0x79, 0x03},
-       {0xc8, 0x20},
-       {0x79, 0x26},
-};
-static const u8 bridge_start_vga_767x[][2] = {
-/* str59 JPG */
-       {0x94, 0xaa},
-       {0xf1, 0x42},
-       {0xe5, 0x04},
-       {0xc0, 0x50},
-       {0xc1, 0x3c},
-       {0xc2, 0x0c},
-       {0x35, 0x02},   /* turn on JPEG */
-       {0xd9, 0x10},
-       {0xda, 0x00},   /* for higher clock rate(30fps) */
-       {0x34, 0x05},   /* enable Audio Suspend mode */
-       {0xc3, 0xf9},   /* enable PRE */
-       {0x8c, 0x00},   /* CIF VSize LSB[2:0] */
-       {0x8d, 0x1c},   /* output YUV */
-/*     {0x34, 0x05},    * enable Audio Suspend mode (?) */
-       {0x50, 0x00},   /* H/V divider=0 */
-       {0x51, 0xa0},   /* input H=640/4 */
-       {0x52, 0x3c},   /* input V=480/4 */
-       {0x53, 0x00},   /* offset X=0 */
-       {0x54, 0x00},   /* offset Y=0 */
-       {0x55, 0x00},   /* H/V size[8]=0 */
-       {0x57, 0x00},   /* H-size[9]=0 */
-       {0x5c, 0x00},   /* output size[9:8]=0 */
-       {0x5a, 0xa0},   /* output H=640/4 */
-       {0x5b, 0x78},   /* output V=480/4 */
-       {0x1c, 0x0a},
-       {0x1d, 0x0a},
-       {0x94, 0x11},
-};
-static const u8 sensor_start_vga_767x[][2] = {
-       {0x11, 0x01},
-       {0x1e, 0x04},
-       {0x19, 0x02},
-       {0x1a, 0x7a},
-};
-static const u8 bridge_start_qvga_767x[][2] = {
-/* str86 JPG */
-       {0x94, 0xaa},
-       {0xf1, 0x42},
-       {0xe5, 0x04},
-       {0xc0, 0x80},
-       {0xc1, 0x60},
-       {0xc2, 0x0c},
-       {0x35, 0x02},   /* turn on JPEG */
-       {0xd9, 0x10},
-       {0xc0, 0x50},   /* CIF HSize 640 */
-       {0xc1, 0x3c},   /* CIF VSize 480 */
-       {0x8c, 0x00},   /* CIF VSize LSB[2:0] */
-       {0x8d, 0x1c},   /* output YUV */
-       {0x34, 0x05},   /* enable Audio Suspend mode */
-       {0xc2, 0x4c},   /* output YUV and Enable DCW */
-       {0xc3, 0xf9},   /* enable PRE */
-       {0x1c, 0x00},   /* indirect addressing */
-       {0x1d, 0x48},   /* output YUV422 */
-       {0x50, 0x89},   /* H/V divider=/2; plus DCW AVG */
-       {0x51, 0xa0},   /* DCW input H=640/4 */
-       {0x52, 0x78},   /* DCW input V=480/4 */
-       {0x53, 0x00},   /* offset X=0 */
-       {0x54, 0x00},   /* offset Y=0 */
-       {0x55, 0x00},   /* H/V size[8]=0 */
-       {0x57, 0x00},   /* H-size[9]=0 */
-       {0x5c, 0x00},   /* DCW output size[9:8]=0 */
-       {0x5a, 0x50},   /* DCW output H=320/4 */
-       {0x5b, 0x3c},   /* DCW output V=240/4 */
-       {0x1c, 0x0a},
-       {0x1d, 0x0a},
-       {0x94, 0x11},
-};
-static const u8 sensor_start_qvga_767x[][2] = {
-       {0x11, 0x01},
-       {0x1e, 0x04},
-       {0x19, 0x02},
-       {0x1a, 0x7a},
-};
-
-static const u8 bridge_init_772x[][2] = {
-       { 0xc2, 0x0c },
-       { 0x88, 0xf8 },
-       { 0xc3, 0x69 },
-       { 0x89, 0xff },
-       { 0x76, 0x03 },
-       { 0x92, 0x01 },
-       { 0x93, 0x18 },
-       { 0x94, 0x10 },
-       { 0x95, 0x10 },
-       { 0xe2, 0x00 },
-       { 0xe7, 0x3e },
-
-       { 0x96, 0x00 },
-
-       { 0x97, 0x20 },
-       { 0x97, 0x20 },
-       { 0x97, 0x20 },
-       { 0x97, 0x0a },
-       { 0x97, 0x3f },
-       { 0x97, 0x4a },
-       { 0x97, 0x20 },
-       { 0x97, 0x15 },
-       { 0x97, 0x0b },
-
-       { 0x8e, 0x40 },
-       { 0x1f, 0x81 },
-       { 0x34, 0x05 },
-       { 0xe3, 0x04 },
-       { 0x88, 0x00 },
-       { 0x89, 0x00 },
-       { 0x76, 0x00 },
-       { 0xe7, 0x2e },
-       { 0x31, 0xf9 },
-       { 0x25, 0x42 },
-       { 0x21, 0xf0 },
-
-       { 0x1c, 0x00 },
-       { 0x1d, 0x40 },
-       { 0x1d, 0x02 }, /* payload size 0x0200 * 4 = 2048 bytes */
-       { 0x1d, 0x00 }, /* payload size */
-
-       { 0x1d, 0x02 }, /* frame size 0x025800 * 4 = 614400 */
-       { 0x1d, 0x58 }, /* frame size */
-       { 0x1d, 0x00 }, /* frame size */
-
-       { 0x1c, 0x0a },
-       { 0x1d, 0x08 }, /* turn on UVC header */
-       { 0x1d, 0x0e }, /* .. */
-
-       { 0x8d, 0x1c },
-       { 0x8e, 0x80 },
-       { 0xe5, 0x04 },
-
-       { 0xc0, 0x50 },
-       { 0xc1, 0x3c },
-       { 0xc2, 0x0c },
-};
-static const u8 sensor_init_772x[][2] = {
-       { 0x12, 0x80 },
-       { 0x11, 0x01 },
-/*fixme: better have a delay?*/
-       { 0x11, 0x01 },
-       { 0x11, 0x01 },
-       { 0x11, 0x01 },
-       { 0x11, 0x01 },
-       { 0x11, 0x01 },
-       { 0x11, 0x01 },
-       { 0x11, 0x01 },
-       { 0x11, 0x01 },
-       { 0x11, 0x01 },
-       { 0x11, 0x01 },
-
-       { 0x3d, 0x03 },
-       { 0x17, 0x26 },
-       { 0x18, 0xa0 },
-       { 0x19, 0x07 },
-       { 0x1a, 0xf0 },
-       { 0x32, 0x00 },
-       { 0x29, 0xa0 },
-       { 0x2c, 0xf0 },
-       { 0x65, 0x20 },
-       { 0x11, 0x01 },
-       { 0x42, 0x7f },
-       { 0x63, 0xaa },         /* AWB - was e0 */
-       { 0x64, 0xff },
-       { 0x66, 0x00 },
-       { 0x13, 0xf0 },         /* com8 */
-       { 0x0d, 0x41 },
-       { 0x0f, 0xc5 },
-       { 0x14, 0x11 },
-
-       { 0x22, 0x7f },
-       { 0x23, 0x03 },
-       { 0x24, 0x40 },
-       { 0x25, 0x30 },
-       { 0x26, 0xa1 },
-       { 0x2a, 0x00 },
-       { 0x2b, 0x00 },
-       { 0x6b, 0xaa },
-       { 0x13, 0xff },         /* AWB */
-
-       { 0x90, 0x05 },
-       { 0x91, 0x01 },
-       { 0x92, 0x03 },
-       { 0x93, 0x00 },
-       { 0x94, 0x60 },
-       { 0x95, 0x3c },
-       { 0x96, 0x24 },
-       { 0x97, 0x1e },
-       { 0x98, 0x62 },
-       { 0x99, 0x80 },
-       { 0x9a, 0x1e },
-       { 0x9b, 0x08 },
-       { 0x9c, 0x20 },
-       { 0x9e, 0x81 },
-
-       { 0xa6, 0x07 },
-       { 0x7e, 0x0c },
-       { 0x7f, 0x16 },
-       { 0x80, 0x2a },
-       { 0x81, 0x4e },
-       { 0x82, 0x61 },
-       { 0x83, 0x6f },
-       { 0x84, 0x7b },
-       { 0x85, 0x86 },
-       { 0x86, 0x8e },
-       { 0x87, 0x97 },
-       { 0x88, 0xa4 },
-       { 0x89, 0xaf },
-       { 0x8a, 0xc5 },
-       { 0x8b, 0xd7 },
-       { 0x8c, 0xe8 },
-       { 0x8d, 0x20 },
-
-       { 0x0c, 0x90 },
-
-       { 0x2b, 0x00 },
-       { 0x22, 0x7f },
-       { 0x23, 0x03 },
-       { 0x11, 0x01 },
-       { 0x0c, 0xd0 },
-       { 0x64, 0xff },
-       { 0x0d, 0x41 },
-
-       { 0x14, 0x41 },
-       { 0x0e, 0xcd },
-       { 0xac, 0xbf },
-       { 0x8e, 0x00 },         /* De-noise threshold */
-       { 0x0c, 0xd0 }
-};
-static const u8 bridge_start_vga_772x[][2] = {
-       {0x1c, 0x00},
-       {0x1d, 0x40},
-       {0x1d, 0x02},
-       {0x1d, 0x00},
-       {0x1d, 0x02},
-       {0x1d, 0x58},
-       {0x1d, 0x00},
-       {0xc0, 0x50},
-       {0xc1, 0x3c},
-};
-static const u8 sensor_start_vga_772x[][2] = {
-       {0x12, 0x00},
-       {0x17, 0x26},
-       {0x18, 0xa0},
-       {0x19, 0x07},
-       {0x1a, 0xf0},
-       {0x29, 0xa0},
-       {0x2c, 0xf0},
-       {0x65, 0x20},
-};
-static const u8 bridge_start_qvga_772x[][2] = {
-       {0x1c, 0x00},
-       {0x1d, 0x40},
-       {0x1d, 0x02},
-       {0x1d, 0x00},
-       {0x1d, 0x01},
-       {0x1d, 0x4b},
-       {0x1d, 0x00},
-       {0xc0, 0x28},
-       {0xc1, 0x1e},
-};
-static const u8 sensor_start_qvga_772x[][2] = {
-       {0x12, 0x40},
-       {0x17, 0x3f},
-       {0x18, 0x50},
-       {0x19, 0x03},
-       {0x1a, 0x78},
-       {0x29, 0x50},
-       {0x2c, 0x78},
-       {0x65, 0x2f},
-};
-
-static void ov534_reg_write(struct gspca_dev *gspca_dev, u16 reg, u8 val)
-{
-       struct usb_device *udev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-
-       PDEBUG(D_USBO, "SET 01 0000 %04x %02x", reg, val);
-       gspca_dev->usb_buf[0] = val;
-       ret = usb_control_msg(udev,
-                             usb_sndctrlpipe(udev, 0),
-                             0x01,
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
-       if (ret < 0) {
-               pr_err("write failed %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static u8 ov534_reg_read(struct gspca_dev *gspca_dev, u16 reg)
-{
-       struct usb_device *udev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return 0;
-       ret = usb_control_msg(udev,
-                             usb_rcvctrlpipe(udev, 0),
-                             0x01,
-                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
-       PDEBUG(D_USBI, "GET 01 0000 %04x %02x", reg, gspca_dev->usb_buf[0]);
-       if (ret < 0) {
-               pr_err("read failed %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-       return gspca_dev->usb_buf[0];
-}
-
-/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
- * (direction and output)? */
-static void ov534_set_led(struct gspca_dev *gspca_dev, int status)
-{
-       u8 data;
-
-       PDEBUG(D_CONF, "led status: %d", status);
-
-       data = ov534_reg_read(gspca_dev, 0x21);
-       data |= 0x80;
-       ov534_reg_write(gspca_dev, 0x21, data);
-
-       data = ov534_reg_read(gspca_dev, 0x23);
-       if (status)
-               data |= 0x80;
-       else
-               data &= ~0x80;
-
-       ov534_reg_write(gspca_dev, 0x23, data);
-
-       if (!status) {
-               data = ov534_reg_read(gspca_dev, 0x21);
-               data &= ~0x80;
-               ov534_reg_write(gspca_dev, 0x21, data);
-       }
-}
-
-static int sccb_check_status(struct gspca_dev *gspca_dev)
-{
-       u8 data;
-       int i;
-
-       for (i = 0; i < 5; i++) {
-               msleep(10);
-               data = ov534_reg_read(gspca_dev, OV534_REG_STATUS);
-
-               switch (data) {
-               case 0x00:
-                       return 1;
-               case 0x04:
-                       return 0;
-               case 0x03:
-                       break;
-               default:
-                       PDEBUG(D_ERR, "sccb status 0x%02x, attempt %d/5",
-                              data, i + 1);
-               }
-       }
-       return 0;
-}
-
-static void sccb_reg_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
-{
-       PDEBUG(D_USBO, "sccb write: %02x %02x", reg, val);
-       ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
-       ov534_reg_write(gspca_dev, OV534_REG_WRITE, val);
-       ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
-
-       if (!sccb_check_status(gspca_dev)) {
-               pr_err("sccb_reg_write failed\n");
-               gspca_dev->usb_err = -EIO;
-       }
-}
-
-static u8 sccb_reg_read(struct gspca_dev *gspca_dev, u16 reg)
-{
-       ov534_reg_write(gspca_dev, OV534_REG_SUBADDR, reg);
-       ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
-       if (!sccb_check_status(gspca_dev))
-               pr_err("sccb_reg_read failed 1\n");
-
-       ov534_reg_write(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
-       if (!sccb_check_status(gspca_dev))
-               pr_err("sccb_reg_read failed 2\n");
-
-       return ov534_reg_read(gspca_dev, OV534_REG_READ);
-}
-
-/* output a bridge sequence (reg - val) */
-static void reg_w_array(struct gspca_dev *gspca_dev,
-                       const u8 (*data)[2], int len)
-{
-       while (--len >= 0) {
-               ov534_reg_write(gspca_dev, (*data)[0], (*data)[1]);
-               data++;
-       }
-}
-
-/* output a sensor sequence (reg - val) */
-static void sccb_w_array(struct gspca_dev *gspca_dev,
-                       const u8 (*data)[2], int len)
-{
-       while (--len >= 0) {
-               if ((*data)[0] != 0xff) {
-                       sccb_reg_write(gspca_dev, (*data)[0], (*data)[1]);
-               } else {
-                       sccb_reg_read(gspca_dev, (*data)[1]);
-                       sccb_reg_write(gspca_dev, 0xff, 0x00);
-               }
-               data++;
-       }
-}
-
-/* ov772x specific controls */
-static void set_frame_rate(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i;
-       struct rate_s {
-               u8 fps;
-               u8 r11;
-               u8 r0d;
-               u8 re5;
-       };
-       const struct rate_s *r;
-       static const struct rate_s rate_0[] = { /* 640x480 */
-               {60, 0x01, 0xc1, 0x04},
-               {50, 0x01, 0x41, 0x02},
-               {40, 0x02, 0xc1, 0x04},
-               {30, 0x04, 0x81, 0x02},
-               {15, 0x03, 0x41, 0x04},
-       };
-       static const struct rate_s rate_1[] = { /* 320x240 */
-               {125, 0x02, 0x81, 0x02},
-               {100, 0x02, 0xc1, 0x04},
-               {75, 0x03, 0xc1, 0x04},
-               {60, 0x04, 0xc1, 0x04},
-               {50, 0x02, 0x41, 0x04},
-               {40, 0x03, 0x41, 0x04},
-               {30, 0x04, 0x41, 0x04},
-       };
-
-       if (sd->sensor != SENSOR_OV772x)
-               return;
-       if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) {
-               r = rate_0;
-               i = ARRAY_SIZE(rate_0);
-       } else {
-               r = rate_1;
-               i = ARRAY_SIZE(rate_1);
-       }
-       while (--i > 0) {
-               if (sd->frame_rate >= r->fps)
-                       break;
-               r++;
-       }
-
-       sccb_reg_write(gspca_dev, 0x11, r->r11);
-       sccb_reg_write(gspca_dev, 0x0d, r->r0d);
-       ov534_reg_write(gspca_dev, 0xe5, r->re5);
-
-       PDEBUG(D_PROBE, "frame_rate: %d", r->fps);
-}
-
-static void sethue(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_OV767x) {
-               /* TBD */
-       } else {
-               s16 huesin;
-               s16 huecos;
-
-               /* fixp_sin and fixp_cos accept only positive values, while
-                * our val is between -90 and 90
-                */
-               val += 360;
-
-               /* According to the datasheet the registers expect HUESIN and
-                * HUECOS to be the result of the trigonometric functions,
-                * scaled by 0x80.
-                *
-                * The 0x100 here represents the maximun absolute value
-                * returned byt fixp_sin and fixp_cos, so the scaling will
-                * consider the result like in the interval [-1.0, 1.0].
-                */
-               huesin = fixp_sin(val) * 0x80 / 0x100;
-               huecos = fixp_cos(val) * 0x80 / 0x100;
-
-               if (huesin < 0) {
-                       sccb_reg_write(gspca_dev, 0xab,
-                               sccb_reg_read(gspca_dev, 0xab) | 0x2);
-                       huesin = -huesin;
-               } else {
-                       sccb_reg_write(gspca_dev, 0xab,
-                               sccb_reg_read(gspca_dev, 0xab) & ~0x2);
-
-               }
-               sccb_reg_write(gspca_dev, 0xa9, (u8)huecos);
-               sccb_reg_write(gspca_dev, 0xaa, (u8)huesin);
-       }
-}
-
-static void setsaturation(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_OV767x) {
-               int i;
-               static u8 color_tb[][6] = {
-                       {0x42, 0x42, 0x00, 0x11, 0x30, 0x41},
-                       {0x52, 0x52, 0x00, 0x16, 0x3c, 0x52},
-                       {0x66, 0x66, 0x00, 0x1b, 0x4b, 0x66},
-                       {0x80, 0x80, 0x00, 0x22, 0x5e, 0x80},
-                       {0x9a, 0x9a, 0x00, 0x29, 0x71, 0x9a},
-                       {0xb8, 0xb8, 0x00, 0x31, 0x87, 0xb8},
-                       {0xdd, 0xdd, 0x00, 0x3b, 0xa2, 0xdd},
-               };
-
-               for (i = 0; i < ARRAY_SIZE(color_tb[0]); i++)
-                       sccb_reg_write(gspca_dev, 0x4f + i, color_tb[val][i]);
-       } else {
-               sccb_reg_write(gspca_dev, 0xa7, val); /* U saturation */
-               sccb_reg_write(gspca_dev, 0xa8, val); /* V saturation */
-       }
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_OV767x) {
-               if (val < 0)
-                       val = 0x80 - val;
-               sccb_reg_write(gspca_dev, 0x55, val);   /* bright */
-       } else {
-               sccb_reg_write(gspca_dev, 0x9b, val);
-       }
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_OV767x)
-               sccb_reg_write(gspca_dev, 0x56, val);   /* contras */
-       else
-               sccb_reg_write(gspca_dev, 0x9c, val);
-}
-
-static void setgain(struct gspca_dev *gspca_dev, s32 val)
-{
-       switch (val & 0x30) {
-       case 0x00:
-               val &= 0x0f;
-               break;
-       case 0x10:
-               val &= 0x0f;
-               val |= 0x30;
-               break;
-       case 0x20:
-               val &= 0x0f;
-               val |= 0x70;
-               break;
-       default:
-/*     case 0x30: */
-               val &= 0x0f;
-               val |= 0xf0;
-               break;
-       }
-       sccb_reg_write(gspca_dev, 0x00, val);
-}
-
-static s32 getgain(struct gspca_dev *gspca_dev)
-{
-       return sccb_reg_read(gspca_dev, 0x00);
-}
-
-static void setexposure(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_OV767x) {
-
-               /* set only aec[9:2] */
-               sccb_reg_write(gspca_dev, 0x10, val);   /* aech */
-       } else {
-
-               /* 'val' is one byte and represents half of the exposure value
-                * we are going to set into registers, a two bytes value:
-                *
-                *    MSB: ((u16) val << 1) >> 8   == val >> 7
-                *    LSB: ((u16) val << 1) & 0xff == val << 1
-                */
-               sccb_reg_write(gspca_dev, 0x08, val >> 7);
-               sccb_reg_write(gspca_dev, 0x10, val << 1);
-       }
-}
-
-static s32 getexposure(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_OV767x) {
-               /* get only aec[9:2] */
-               return sccb_reg_read(gspca_dev, 0x10);  /* aech */
-       } else {
-               u8 hi = sccb_reg_read(gspca_dev, 0x08);
-               u8 lo = sccb_reg_read(gspca_dev, 0x10);
-               return (hi << 8 | lo) >> 1;
-       }
-}
-
-static void setagc(struct gspca_dev *gspca_dev, s32 val)
-{
-       if (val) {
-               sccb_reg_write(gspca_dev, 0x13,
-                               sccb_reg_read(gspca_dev, 0x13) | 0x04);
-               sccb_reg_write(gspca_dev, 0x64,
-                               sccb_reg_read(gspca_dev, 0x64) | 0x03);
-       } else {
-               sccb_reg_write(gspca_dev, 0x13,
-                               sccb_reg_read(gspca_dev, 0x13) & ~0x04);
-               sccb_reg_write(gspca_dev, 0x64,
-                               sccb_reg_read(gspca_dev, 0x64) & ~0x03);
-       }
-}
-
-static void setawb(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (val) {
-               sccb_reg_write(gspca_dev, 0x13,
-                               sccb_reg_read(gspca_dev, 0x13) | 0x02);
-               if (sd->sensor == SENSOR_OV772x)
-                       sccb_reg_write(gspca_dev, 0x63,
-                               sccb_reg_read(gspca_dev, 0x63) | 0xc0);
-       } else {
-               sccb_reg_write(gspca_dev, 0x13,
-                               sccb_reg_read(gspca_dev, 0x13) & ~0x02);
-               if (sd->sensor == SENSOR_OV772x)
-                       sccb_reg_write(gspca_dev, 0x63,
-                               sccb_reg_read(gspca_dev, 0x63) & ~0xc0);
-       }
-}
-
-static void setaec(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 data;
-
-       data = sd->sensor == SENSOR_OV767x ?
-                       0x05 :          /* agc + aec */
-                       0x01;           /* agc */
-       switch (val) {
-       case V4L2_EXPOSURE_AUTO:
-               sccb_reg_write(gspca_dev, 0x13,
-                               sccb_reg_read(gspca_dev, 0x13) | data);
-               break;
-       case V4L2_EXPOSURE_MANUAL:
-               sccb_reg_write(gspca_dev, 0x13,
-                               sccb_reg_read(gspca_dev, 0x13) & ~data);
-               break;
-       }
-}
-
-static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
-{
-       sccb_reg_write(gspca_dev, 0x91, val);   /* Auto de-noise threshold */
-       sccb_reg_write(gspca_dev, 0x8e, val);   /* De-noise threshold */
-}
-
-static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 val;
-
-       if (sd->sensor == SENSOR_OV767x) {
-               val = sccb_reg_read(gspca_dev, 0x1e);   /* mvfp */
-               val &= ~0x30;
-               if (hflip)
-                       val |= 0x20;
-               if (vflip)
-                       val |= 0x10;
-               sccb_reg_write(gspca_dev, 0x1e, val);
-       } else {
-               val = sccb_reg_read(gspca_dev, 0x0c);
-               val &= ~0xc0;
-               if (hflip == 0)
-                       val |= 0x40;
-               if (vflip == 0)
-                       val |= 0x80;
-               sccb_reg_write(gspca_dev, 0x0c, val);
-       }
-}
-
-static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       val = val ? 0x9e : 0x00;
-       if (sd->sensor == SENSOR_OV767x) {
-               sccb_reg_write(gspca_dev, 0x2a, 0x00);
-               if (val)
-                       val = 0x9d;     /* insert dummy to 25fps for 50Hz */
-       }
-       sccb_reg_write(gspca_dev, 0x2b, val);
-}
-
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                    const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-
-       cam = &gspca_dev->cam;
-
-       cam->cam_mode = ov772x_mode;
-       cam->nmodes = ARRAY_SIZE(ov772x_mode);
-
-       sd->frame_rate = 30;
-
-       return 0;
-}
-
-static int ov534_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct sd *sd = container_of(ctrl->handler, struct sd, ctrl_handler);
-       struct gspca_dev *gspca_dev = &sd->gspca_dev;
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUTOGAIN:
-               gspca_dev->usb_err = 0;
-               if (ctrl->val && sd->gain && gspca_dev->streaming)
-                       sd->gain->val = getgain(gspca_dev);
-               return gspca_dev->usb_err;
-
-       case V4L2_CID_EXPOSURE_AUTO:
-               gspca_dev->usb_err = 0;
-               if (ctrl->val == V4L2_EXPOSURE_AUTO && sd->exposure &&
-                   gspca_dev->streaming)
-                       sd->exposure->val = getexposure(gspca_dev);
-               return gspca_dev->usb_err;
-       }
-       return -EINVAL;
-}
-
-static int ov534_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct sd *sd = container_of(ctrl->handler, struct sd, ctrl_handler);
-       struct gspca_dev *gspca_dev = &sd->gspca_dev;
-
-       gspca_dev->usb_err = 0;
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_HUE:
-               sethue(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               setsaturation(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_AUTOGAIN:
-       /* case V4L2_CID_GAIN: */
-               setagc(gspca_dev, ctrl->val);
-               if (!gspca_dev->usb_err && !ctrl->val && sd->gain)
-                       setgain(gspca_dev, sd->gain->val);
-               break;
-       case V4L2_CID_AUTO_WHITE_BALANCE:
-               setawb(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_EXPOSURE_AUTO:
-       /* case V4L2_CID_EXPOSURE: */
-               setaec(gspca_dev, ctrl->val);
-               if (!gspca_dev->usb_err && ctrl->val == V4L2_EXPOSURE_MANUAL &&
-                   sd->exposure)
-                       setexposure(gspca_dev, sd->exposure->val);
-               break;
-       case V4L2_CID_SHARPNESS:
-               setsharpness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_HFLIP:
-               sethvflip(gspca_dev, ctrl->val, sd->vflip->val);
-               break;
-       case V4L2_CID_VFLIP:
-               sethvflip(gspca_dev, sd->hflip->val, ctrl->val);
-               break;
-       case V4L2_CID_POWER_LINE_FREQUENCY:
-               setlightfreq(gspca_dev, ctrl->val);
-               break;
-       }
-       return gspca_dev->usb_err;
-}
-
-static const struct v4l2_ctrl_ops ov534_ctrl_ops = {
-       .g_volatile_ctrl = ov534_g_volatile_ctrl,
-       .s_ctrl = ov534_s_ctrl,
-};
-
-static int sd_init_controls(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct v4l2_ctrl_handler *hdl = &sd->ctrl_handler;
-       /* parameters with different values between the supported sensors */
-       int saturation_min;
-       int saturation_max;
-       int saturation_def;
-       int brightness_min;
-       int brightness_max;
-       int brightness_def;
-       int contrast_max;
-       int contrast_def;
-       int exposure_min;
-       int exposure_max;
-       int exposure_def;
-       int hflip_def;
-
-       if (sd->sensor == SENSOR_OV767x) {
-               saturation_min = 0,
-               saturation_max = 6,
-               saturation_def = 3,
-               brightness_min = -127;
-               brightness_max = 127;
-               brightness_def = 0;
-               contrast_max = 0x80;
-               contrast_def = 0x40;
-               exposure_min = 0x08;
-               exposure_max = 0x60;
-               exposure_def = 0x13;
-               hflip_def = 1;
-       } else {
-               saturation_min = 0,
-               saturation_max = 255,
-               saturation_def = 64,
-               brightness_min = 0;
-               brightness_max = 255;
-               brightness_def = 0;
-               contrast_max = 255;
-               contrast_def = 32;
-               exposure_min = 0;
-               exposure_max = 255;
-               exposure_def = 120;
-               hflip_def = 0;
-       }
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-
-       v4l2_ctrl_handler_init(hdl, 13);
-
-       if (sd->sensor == SENSOR_OV772x)
-               sd->hue = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
-                               V4L2_CID_HUE, -90, 90, 1, 0);
-
-       sd->saturation = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
-                       V4L2_CID_SATURATION, saturation_min, saturation_max, 1,
-                       saturation_def);
-       sd->brightness = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, brightness_min, brightness_max, 1,
-                       brightness_def);
-       sd->contrast = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, contrast_max, 1, contrast_def);
-
-       if (sd->sensor == SENSOR_OV772x) {
-               sd->autogain = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
-                               V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-               sd->gain = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
-                               V4L2_CID_GAIN, 0, 63, 1, 20);
-       }
-
-       sd->autoexposure = v4l2_ctrl_new_std_menu(hdl, &ov534_ctrl_ops,
-                       V4L2_CID_EXPOSURE_AUTO,
-                       V4L2_EXPOSURE_MANUAL, 0,
-                       V4L2_EXPOSURE_AUTO);
-       sd->exposure = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
-                       V4L2_CID_EXPOSURE, exposure_min, exposure_max, 1,
-                       exposure_def);
-
-       sd->autowhitebalance = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
-                       V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
-
-       if (sd->sensor == SENSOR_OV772x)
-               sd->sharpness = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
-                               V4L2_CID_SHARPNESS, 0, 63, 1, 0);
-
-       sd->hflip = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
-                       V4L2_CID_HFLIP, 0, 1, 1, hflip_def);
-       sd->vflip = v4l2_ctrl_new_std(hdl, &ov534_ctrl_ops,
-                       V4L2_CID_VFLIP, 0, 1, 1, 0);
-       sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &ov534_ctrl_ops,
-                       V4L2_CID_POWER_LINE_FREQUENCY,
-                       V4L2_CID_POWER_LINE_FREQUENCY_50HZ, 0,
-                       V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-
-       if (sd->sensor == SENSOR_OV772x)
-               v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, true);
-
-       v4l2_ctrl_auto_cluster(2, &sd->autoexposure, V4L2_EXPOSURE_MANUAL,
-                              true);
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u16 sensor_id;
-       static const struct reg_array bridge_init[NSENSORS] = {
-       [SENSOR_OV767x] = {bridge_init_767x, ARRAY_SIZE(bridge_init_767x)},
-       [SENSOR_OV772x] = {bridge_init_772x, ARRAY_SIZE(bridge_init_772x)},
-       };
-       static const struct reg_array sensor_init[NSENSORS] = {
-       [SENSOR_OV767x] = {sensor_init_767x, ARRAY_SIZE(sensor_init_767x)},
-       [SENSOR_OV772x] = {sensor_init_772x, ARRAY_SIZE(sensor_init_772x)},
-       };
-
-       /* reset bridge */
-       ov534_reg_write(gspca_dev, 0xe7, 0x3a);
-       ov534_reg_write(gspca_dev, 0xe0, 0x08);
-       msleep(100);
-
-       /* initialize the sensor address */
-       ov534_reg_write(gspca_dev, OV534_REG_ADDRESS, 0x42);
-
-       /* reset sensor */
-       sccb_reg_write(gspca_dev, 0x12, 0x80);
-       msleep(10);
-
-       /* probe the sensor */
-       sccb_reg_read(gspca_dev, 0x0a);
-       sensor_id = sccb_reg_read(gspca_dev, 0x0a) << 8;
-       sccb_reg_read(gspca_dev, 0x0b);
-       sensor_id |= sccb_reg_read(gspca_dev, 0x0b);
-       PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
-
-       if ((sensor_id & 0xfff0) == 0x7670) {
-               sd->sensor = SENSOR_OV767x;
-               gspca_dev->cam.cam_mode = ov767x_mode;
-               gspca_dev->cam.nmodes = ARRAY_SIZE(ov767x_mode);
-       } else {
-               sd->sensor = SENSOR_OV772x;
-               gspca_dev->cam.bulk = 1;
-               gspca_dev->cam.bulk_size = 16384;
-               gspca_dev->cam.bulk_nurbs = 2;
-               gspca_dev->cam.mode_framerates = ov772x_framerates;
-       }
-
-       /* initialize */
-       reg_w_array(gspca_dev, bridge_init[sd->sensor].val,
-                       bridge_init[sd->sensor].len);
-       ov534_set_led(gspca_dev, 1);
-       sccb_w_array(gspca_dev, sensor_init[sd->sensor].val,
-                       sensor_init[sd->sensor].len);
-       if (sd->sensor == SENSOR_OV767x)
-               sd_start(gspca_dev);
-       sd_stopN(gspca_dev);
-/*     set_frame_rate(gspca_dev);      */
-
-       return gspca_dev->usb_err;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int mode;
-       static const struct reg_array bridge_start[NSENSORS][2] = {
-       [SENSOR_OV767x] = {{bridge_start_qvga_767x,
-                                       ARRAY_SIZE(bridge_start_qvga_767x)},
-                       {bridge_start_vga_767x,
-                                       ARRAY_SIZE(bridge_start_vga_767x)}},
-       [SENSOR_OV772x] = {{bridge_start_qvga_772x,
-                                       ARRAY_SIZE(bridge_start_qvga_772x)},
-                       {bridge_start_vga_772x,
-                                       ARRAY_SIZE(bridge_start_vga_772x)}},
-       };
-       static const struct reg_array sensor_start[NSENSORS][2] = {
-       [SENSOR_OV767x] = {{sensor_start_qvga_767x,
-                                       ARRAY_SIZE(sensor_start_qvga_767x)},
-                       {sensor_start_vga_767x,
-                                       ARRAY_SIZE(sensor_start_vga_767x)}},
-       [SENSOR_OV772x] = {{sensor_start_qvga_772x,
-                                       ARRAY_SIZE(sensor_start_qvga_772x)},
-                       {sensor_start_vga_772x,
-                                       ARRAY_SIZE(sensor_start_vga_772x)}},
-       };
-
-       /* (from ms-win trace) */
-       if (sd->sensor == SENSOR_OV767x)
-               sccb_reg_write(gspca_dev, 0x1e, 0x04);
-                                       /* black sun enable ? */
-
-       mode = gspca_dev->curr_mode;    /* 0: 320x240, 1: 640x480 */
-       reg_w_array(gspca_dev, bridge_start[sd->sensor][mode].val,
-                               bridge_start[sd->sensor][mode].len);
-       sccb_w_array(gspca_dev, sensor_start[sd->sensor][mode].val,
-                               sensor_start[sd->sensor][mode].len);
-
-       set_frame_rate(gspca_dev);
-
-       if (sd->hue)
-               sethue(gspca_dev, v4l2_ctrl_g_ctrl(sd->hue));
-       setsaturation(gspca_dev, v4l2_ctrl_g_ctrl(sd->saturation));
-       if (sd->autogain)
-               setagc(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
-       setawb(gspca_dev, v4l2_ctrl_g_ctrl(sd->autowhitebalance));
-       setaec(gspca_dev, v4l2_ctrl_g_ctrl(sd->autoexposure));
-       if (sd->gain)
-               setgain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
-       setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
-       setbrightness(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness));
-       setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast));
-       if (sd->sharpness)
-               setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
-       sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip),
-                 v4l2_ctrl_g_ctrl(sd->vflip));
-       setlightfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->plfreq));
-
-       ov534_set_led(gspca_dev, 1);
-       ov534_reg_write(gspca_dev, 0xe0, 0x00);
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       ov534_reg_write(gspca_dev, 0xe0, 0x09);
-       ov534_set_led(gspca_dev, 0);
-}
-
-/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
-#define UVC_STREAM_EOH (1 << 7)
-#define UVC_STREAM_ERR (1 << 6)
-#define UVC_STREAM_STI (1 << 5)
-#define UVC_STREAM_RES (1 << 4)
-#define UVC_STREAM_SCR (1 << 3)
-#define UVC_STREAM_PTS (1 << 2)
-#define UVC_STREAM_EOF (1 << 1)
-#define UVC_STREAM_FID (1 << 0)
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data, int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       __u32 this_pts;
-       u16 this_fid;
-       int remaining_len = len;
-       int payload_len;
-
-       payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
-       do {
-               len = min(remaining_len, payload_len);
-
-               /* Payloads are prefixed with a UVC-style header.  We
-                  consider a frame to start when the FID toggles, or the PTS
-                  changes.  A frame ends when EOF is set, and we've received
-                  the correct number of bytes. */
-
-               /* Verify UVC header.  Header length is always 12 */
-               if (data[0] != 12 || len < 12) {
-                       PDEBUG(D_PACK, "bad header");
-                       goto discard;
-               }
-
-               /* Check errors */
-               if (data[1] & UVC_STREAM_ERR) {
-                       PDEBUG(D_PACK, "payload error");
-                       goto discard;
-               }
-
-               /* Extract PTS and FID */
-               if (!(data[1] & UVC_STREAM_PTS)) {
-                       PDEBUG(D_PACK, "PTS not present");
-                       goto discard;
-               }
-               this_pts = (data[5] << 24) | (data[4] << 16)
-                                               | (data[3] << 8) | data[2];
-               this_fid = (data[1] & UVC_STREAM_FID) ? 1 : 0;
-
-               /* If PTS or FID has changed, start a new frame. */
-               if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
-                       if (gspca_dev->last_packet_type == INTER_PACKET)
-                               gspca_frame_add(gspca_dev, LAST_PACKET,
-                                               NULL, 0);
-                       sd->last_pts = this_pts;
-                       sd->last_fid = this_fid;
-                       gspca_frame_add(gspca_dev, FIRST_PACKET,
-                                       data + 12, len - 12);
-               /* If this packet is marked as EOF, end the frame */
-               } else if (data[1] & UVC_STREAM_EOF) {
-                       sd->last_pts = 0;
-                       if (gspca_dev->pixfmt == V4L2_PIX_FMT_YUYV
-                        && gspca_dev->image_len + len - 12 !=
-                                  gspca_dev->width * gspca_dev->height * 2) {
-                               PDEBUG(D_PACK, "wrong sized frame");
-                               goto discard;
-                       }
-                       gspca_frame_add(gspca_dev, LAST_PACKET,
-                                       data + 12, len - 12);
-               } else {
-
-                       /* Add the data from this payload */
-                       gspca_frame_add(gspca_dev, INTER_PACKET,
-                                       data + 12, len - 12);
-               }
-
-               /* Done this payload */
-               goto scan_next;
-
-discard:
-               /* Discard data until a new frame starts. */
-               gspca_dev->last_packet_type = DISCARD_PACKET;
-
-scan_next:
-               remaining_len -= len;
-               data += len;
-       } while (remaining_len > 0);
-}
-
-/* get stream parameters (framerate) */
-static void sd_get_streamparm(struct gspca_dev *gspca_dev,
-                            struct v4l2_streamparm *parm)
-{
-       struct v4l2_captureparm *cp = &parm->parm.capture;
-       struct v4l2_fract *tpf = &cp->timeperframe;
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       cp->capability |= V4L2_CAP_TIMEPERFRAME;
-       tpf->numerator = 1;
-       tpf->denominator = sd->frame_rate;
-}
-
-/* set stream parameters (framerate) */
-static void sd_set_streamparm(struct gspca_dev *gspca_dev,
-                            struct v4l2_streamparm *parm)
-{
-       struct v4l2_captureparm *cp = &parm->parm.capture;
-       struct v4l2_fract *tpf = &cp->timeperframe;
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* Set requested framerate */
-       sd->frame_rate = tpf->denominator / tpf->numerator;
-       if (gspca_dev->streaming)
-               set_frame_rate(gspca_dev);
-
-       /* Return the actual framerate */
-       tpf->numerator = 1;
-       tpf->denominator = sd->frame_rate;
-}
-
-/* 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,
-       .stopN    = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-       .get_streamparm = sd_get_streamparm,
-       .set_streamparm = sd_set_streamparm,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x1415, 0x2000)},
-       {USB_DEVICE(0x06f8, 0x3002)},
-       {}
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c
deleted file mode 100644 (file)
index c4cd028..0000000
+++ /dev/null
@@ -1,1500 +0,0 @@
-/*
- * ov534-ov9xxx gspca driver
- *
- * Copyright (C) 2009-2011 Jean-Francois Moine http://moinejf.free.fr
- * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
- * Copyright (C) 2008 Jim Paris <jim@jtan.com>
- *
- * Based on a prototype written by Mark Ferrell <majortrips@gmail.com>
- * USB protocol reverse engineered by Jim Paris <jim@jtan.com>
- * https://jim.sh/svn/jim/devl/playstation/ps3/eye/test/
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "ov534_9"
-
-#include "gspca.h"
-
-#define OV534_REG_ADDRESS      0xf1    /* sensor address */
-#define OV534_REG_SUBADDR      0xf2
-#define OV534_REG_WRITE                0xf3
-#define OV534_REG_READ         0xf4
-#define OV534_REG_OPERATION    0xf5
-#define OV534_REG_STATUS       0xf6
-
-#define OV534_OP_WRITE_3       0x37
-#define OV534_OP_WRITE_2       0x33
-#define OV534_OP_READ_2                0xf9
-
-#define CTRL_TIMEOUT 500
-
-MODULE_AUTHOR("Jean-Francois Moine <moinejf@free.fr>");
-MODULE_DESCRIPTION("GSPCA/OV534_9 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-       __u32 last_pts;
-       u8 last_fid;
-
-       u8 sensor;
-};
-enum sensors {
-       SENSOR_OV965x,          /* ov9657 */
-       SENSOR_OV971x,          /* ov9712 */
-       SENSOR_OV562x,          /* ov5621 */
-       NSENSORS
-};
-
-static const struct v4l2_pix_format ov965x_mode[] = {
-#define QVGA_MODE 0
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-#define VGA_MODE 1
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-#define SVGA_MODE 2
-       {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 800,
-               .sizeimage = 800 * 600 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-#define XGA_MODE 3
-       {1024, 768, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 1024,
-               .sizeimage = 1024 * 768 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-#define SXGA_MODE 4
-       {1280, 1024, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 1280,
-               .sizeimage = 1280 * 1024 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-};
-
-static const struct v4l2_pix_format ov971x_mode[] = {
-       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB
-       }
-};
-
-static const struct v4l2_pix_format ov562x_mode[] = {
-       {2592, 1680, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 2592,
-               .sizeimage = 2592 * 1680,
-               .colorspace = V4L2_COLORSPACE_SRGB
-       }
-};
-
-static const u8 bridge_init[][2] = {
-       {0x88, 0xf8},
-       {0x89, 0xff},
-       {0x76, 0x03},
-       {0x92, 0x03},
-       {0x95, 0x10},
-       {0xe2, 0x00},
-       {0xe7, 0x3e},
-       {0x8d, 0x1c},
-       {0x8e, 0x00},
-       {0x8f, 0x00},
-       {0x1f, 0x00},
-       {0xc3, 0xf9},
-       {0x89, 0xff},
-       {0x88, 0xf8},
-       {0x76, 0x03},
-       {0x92, 0x01},
-       {0x93, 0x18},
-       {0x1c, 0x0a},
-       {0x1d, 0x48},
-       {0xc0, 0x50},
-       {0xc1, 0x3c},
-       {0x34, 0x05},
-       {0xc2, 0x0c},
-       {0xc3, 0xf9},
-       {0x34, 0x05},
-       {0xe7, 0x2e},
-       {0x31, 0xf9},
-       {0x35, 0x02},
-       {0xd9, 0x10},
-       {0x25, 0x42},
-       {0x94, 0x11},
-};
-
-static const u8 ov965x_init[][2] = {
-       {0x12, 0x80},   /* com7 - SSCB reset */
-       {0x00, 0x00},   /* gain */
-       {0x01, 0x80},   /* blue */
-       {0x02, 0x80},   /* red */
-       {0x03, 0x1b},   /* vref */
-       {0x04, 0x03},   /* com1 - exposure low bits */
-       {0x0b, 0x57},   /* ver */
-       {0x0e, 0x61},   /* com5 */
-       {0x0f, 0x42},   /* com6 */
-       {0x11, 0x00},   /* clkrc */
-       {0x12, 0x02},   /* com7 - 15fps VGA YUYV */
-       {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
-       {0x14, 0x28},   /* com9 */
-       {0x16, 0x24},   /* reg16 */
-       {0x17, 0x1d},   /* hstart*/
-       {0x18, 0xbd},   /* hstop */
-       {0x19, 0x01},   /* vstrt */
-       {0x1a, 0x81},   /* vstop*/
-       {0x1e, 0x04},   /* mvfp */
-       {0x24, 0x3c},   /* aew */
-       {0x25, 0x36},   /* aeb */
-       {0x26, 0x71},   /* vpt */
-       {0x27, 0x08},   /* bbias */
-       {0x28, 0x08},   /* gbbias */
-       {0x29, 0x15},   /* gr com */
-       {0x2a, 0x00},   /* exhch */
-       {0x2b, 0x00},   /* exhcl */
-       {0x2c, 0x08},   /* rbias */
-       {0x32, 0xff},   /* href */
-       {0x33, 0x00},   /* chlf */
-       {0x34, 0x3f},   /* aref1 */
-       {0x35, 0x00},   /* aref2 */
-       {0x36, 0xf8},   /* aref3 */
-       {0x38, 0x72},   /* adc2 */
-       {0x39, 0x57},   /* aref4 */
-       {0x3a, 0x80},   /* tslb - yuyv */
-       {0x3b, 0xc4},   /* com11 - night mode 1/4 frame rate */
-       {0x3d, 0x99},   /* com13 */
-       {0x3f, 0xc1},   /* edge */
-       {0x40, 0xc0},   /* com15 */
-       {0x41, 0x40},   /* com16 */
-       {0x42, 0xc0},   /* com17 */
-       {0x43, 0x0a},   /* rsvd */
-       {0x44, 0xf0},
-       {0x45, 0x46},
-       {0x46, 0x62},
-       {0x47, 0x2a},
-       {0x48, 0x3c},
-       {0x4a, 0xfc},
-       {0x4b, 0xfc},
-       {0x4c, 0x7f},
-       {0x4d, 0x7f},
-       {0x4e, 0x7f},
-       {0x4f, 0x98},   /* matrix */
-       {0x50, 0x98},
-       {0x51, 0x00},
-       {0x52, 0x28},
-       {0x53, 0x70},
-       {0x54, 0x98},
-       {0x58, 0x1a},   /* matrix coef sign */
-       {0x59, 0x85},   /* AWB control */
-       {0x5a, 0xa9},
-       {0x5b, 0x64},
-       {0x5c, 0x84},
-       {0x5d, 0x53},
-       {0x5e, 0x0e},
-       {0x5f, 0xf0},   /* AWB blue limit */
-       {0x60, 0xf0},   /* AWB red limit */
-       {0x61, 0xf0},   /* AWB green limit */
-       {0x62, 0x00},   /* lcc1 */
-       {0x63, 0x00},   /* lcc2 */
-       {0x64, 0x02},   /* lcc3 */
-       {0x65, 0x16},   /* lcc4 */
-       {0x66, 0x01},   /* lcc5 */
-       {0x69, 0x02},   /* hv */
-       {0x6b, 0x5a},   /* dbvl */
-       {0x6c, 0x04},
-       {0x6d, 0x55},
-       {0x6e, 0x00},
-       {0x6f, 0x9d},
-       {0x70, 0x21},   /* dnsth */
-       {0x71, 0x78},
-       {0x72, 0x00},   /* poidx */
-       {0x73, 0x01},   /* pckdv */
-       {0x74, 0x3a},   /* xindx */
-       {0x75, 0x35},   /* yindx */
-       {0x76, 0x01},
-       {0x77, 0x02},
-       {0x7a, 0x12},   /* gamma curve */
-       {0x7b, 0x08},
-       {0x7c, 0x16},
-       {0x7d, 0x30},
-       {0x7e, 0x5e},
-       {0x7f, 0x72},
-       {0x80, 0x82},
-       {0x81, 0x8e},
-       {0x82, 0x9a},
-       {0x83, 0xa4},
-       {0x84, 0xac},
-       {0x85, 0xb8},
-       {0x86, 0xc3},
-       {0x87, 0xd6},
-       {0x88, 0xe6},
-       {0x89, 0xf2},
-       {0x8a, 0x03},
-       {0x8c, 0x89},   /* com19 */
-       {0x14, 0x28},   /* com9 */
-       {0x90, 0x7d},
-       {0x91, 0x7b},
-       {0x9d, 0x03},   /* lcc6 */
-       {0x9e, 0x04},   /* lcc7 */
-       {0x9f, 0x7a},
-       {0xa0, 0x79},
-       {0xa1, 0x40},   /* aechm */
-       {0xa4, 0x50},   /* com21 */
-       {0xa5, 0x68},   /* com26 */
-       {0xa6, 0x4a},   /* AWB green */
-       {0xa8, 0xc1},   /* refa8 */
-       {0xa9, 0xef},   /* refa9 */
-       {0xaa, 0x92},
-       {0xab, 0x04},
-       {0xac, 0x80},   /* black level control */
-       {0xad, 0x80},
-       {0xae, 0x80},
-       {0xaf, 0x80},
-       {0xb2, 0xf2},
-       {0xb3, 0x20},
-       {0xb4, 0x20},   /* ctrlb4 */
-       {0xb5, 0x00},
-       {0xb6, 0xaf},
-       {0xbb, 0xae},
-       {0xbc, 0x7f},   /* ADC channel offsets */
-       {0xdb, 0x7f},
-       {0xbe, 0x7f},
-       {0xbf, 0x7f},
-       {0xc0, 0xe2},
-       {0xc1, 0xc0},
-       {0xc2, 0x01},
-       {0xc3, 0x4e},
-       {0xc6, 0x85},
-       {0xc7, 0x80},   /* com24 */
-       {0xc9, 0xe0},
-       {0xca, 0xe8},
-       {0xcb, 0xf0},
-       {0xcc, 0xd8},
-       {0xcd, 0xf1},
-       {0x4f, 0x98},   /* matrix */
-       {0x50, 0x98},
-       {0x51, 0x00},
-       {0x52, 0x28},
-       {0x53, 0x70},
-       {0x54, 0x98},
-       {0x58, 0x1a},
-       {0xff, 0x41},   /* read 41, write ff 00 */
-       {0x41, 0x40},   /* com16 */
-
-       {0xc5, 0x03},   /* 60 Hz banding filter */
-       {0x6a, 0x02},   /* 50 Hz banding filter */
-
-       {0x12, 0x62},   /* com7 - 30fps VGA YUV */
-       {0x36, 0xfa},   /* aref3 */
-       {0x69, 0x0a},   /* hv */
-       {0x8c, 0x89},   /* com22 */
-       {0x14, 0x28},   /* com9 */
-       {0x3e, 0x0c},
-       {0x41, 0x40},   /* com16 */
-       {0x72, 0x00},
-       {0x73, 0x00},
-       {0x74, 0x3a},
-       {0x75, 0x35},
-       {0x76, 0x01},
-       {0xc7, 0x80},
-       {0x03, 0x12},   /* vref */
-       {0x17, 0x16},   /* hstart */
-       {0x18, 0x02},   /* hstop */
-       {0x19, 0x01},   /* vstrt */
-       {0x1a, 0x3d},   /* vstop */
-       {0x32, 0xff},   /* href */
-       {0xc0, 0xaa},
-};
-
-static const u8 bridge_init_2[][2] = {
-       {0x94, 0xaa},
-       {0xf1, 0x60},
-       {0xe5, 0x04},
-       {0xc0, 0x50},
-       {0xc1, 0x3c},
-       {0x8c, 0x00},
-       {0x8d, 0x1c},
-       {0x34, 0x05},
-
-       {0xc2, 0x0c},
-       {0xc3, 0xf9},
-       {0xda, 0x01},
-       {0x50, 0x00},
-       {0x51, 0xa0},
-       {0x52, 0x3c},
-       {0x53, 0x00},
-       {0x54, 0x00},
-       {0x55, 0x00},
-       {0x57, 0x00},
-       {0x5c, 0x00},
-       {0x5a, 0xa0},
-       {0x5b, 0x78},
-       {0x35, 0x02},
-       {0xd9, 0x10},
-       {0x94, 0x11},
-};
-
-static const u8 ov965x_init_2[][2] = {
-       {0x3b, 0xc4},
-       {0x1e, 0x04},   /* mvfp */
-       {0x13, 0xe0},   /* com8 */
-       {0x00, 0x00},   /* gain */
-       {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
-       {0x11, 0x03},   /* clkrc */
-       {0x6b, 0x5a},   /* dblv */
-       {0x6a, 0x05},
-       {0xc5, 0x07},
-       {0xa2, 0x4b},
-       {0xa3, 0x3e},
-       {0x2d, 0x00},
-       {0xff, 0x42},   /* read 42, write ff 00 */
-       {0x42, 0xc0},   /* com17 */
-       {0x2d, 0x00},
-       {0xff, 0x42},   /* read 42, write ff 00 */
-       {0x42, 0xc1},   /* com17 */
-/* sharpness */
-       {0x3f, 0x01},
-       {0xff, 0x42},   /* read 42, write ff 00 */
-       {0x42, 0xc1},   /* com17 */
-/* saturation */
-       {0x4f, 0x98},   /* matrix */
-       {0x50, 0x98},
-       {0x51, 0x00},
-       {0x52, 0x28},
-       {0x53, 0x70},
-       {0x54, 0x98},
-       {0x58, 0x1a},
-       {0xff, 0x41},   /* read 41, write ff 00 */
-       {0x41, 0x40},   /* com16 */
-/* contrast */
-       {0x56, 0x40},
-/* brightness */
-       {0x55, 0x8f},
-/* expo */
-       {0x10, 0x25},   /* aech - exposure high bits */
-       {0xff, 0x13},   /* read 13, write ff 00 */
-       {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
-};
-
-static const u8 ov971x_init[][2] = {
-       {0x12, 0x80},
-       {0x09, 0x10},
-       {0x1e, 0x07},
-       {0x5f, 0x18},
-       {0x69, 0x04},
-       {0x65, 0x2a},
-       {0x68, 0x0a},
-       {0x39, 0x28},
-       {0x4d, 0x90},
-       {0xc1, 0x80},
-       {0x0c, 0x30},
-       {0x6d, 0x02},
-       {0x96, 0xf1},
-       {0xbc, 0x68},
-       {0x12, 0x00},
-       {0x3b, 0x00},
-       {0x97, 0x80},
-       {0x17, 0x25},
-       {0x18, 0xa2},
-       {0x19, 0x01},
-       {0x1a, 0xca},
-       {0x03, 0x0a},
-       {0x32, 0x07},
-       {0x98, 0x40},   /*{0x98, 0x00},*/
-       {0x99, 0xA0},   /*{0x99, 0x00},*/
-       {0x9a, 0x01},   /*{0x9a, 0x00},*/
-       {0x57, 0x00},
-       {0x58, 0x78},   /*{0x58, 0xc8},*/
-       {0x59, 0x50},   /*{0x59, 0xa0},*/
-       {0x4c, 0x13},
-       {0x4b, 0x36},
-       {0x3d, 0x3c},
-       {0x3e, 0x03},
-       {0xbd, 0x50},   /*{0xbd, 0xa0},*/
-       {0xbe, 0x78},   /*{0xbe, 0xc8},*/
-       {0x4e, 0x55},
-       {0x4f, 0x55},
-       {0x50, 0x55},
-       {0x51, 0x55},
-       {0x24, 0x55},
-       {0x25, 0x40},
-       {0x26, 0xa1},
-       {0x5c, 0x59},
-       {0x5d, 0x00},
-       {0x11, 0x00},
-       {0x2a, 0x98},
-       {0x2b, 0x06},
-       {0x2d, 0x00},
-       {0x2e, 0x00},
-       {0x13, 0xa5},
-       {0x14, 0x40},
-       {0x4a, 0x00},
-       {0x49, 0xce},
-       {0x22, 0x03},
-       {0x09, 0x00}
-};
-
-static const u8 ov965x_start_1_vga[][2] = {    /* same for qvga */
-       {0x12, 0x62},   /* com7 - 30fps VGA YUV */
-       {0x36, 0xfa},   /* aref3 */
-       {0x69, 0x0a},   /* hv */
-       {0x8c, 0x89},   /* com22 */
-       {0x14, 0x28},   /* com9 */
-       {0x3e, 0x0c},   /* com14 */
-       {0x41, 0x40},   /* com16 */
-       {0x72, 0x00},
-       {0x73, 0x00},
-       {0x74, 0x3a},
-       {0x75, 0x35},
-       {0x76, 0x01},
-       {0xc7, 0x80},   /* com24 */
-       {0x03, 0x12},   /* vref */
-       {0x17, 0x16},   /* hstart */
-       {0x18, 0x02},   /* hstop */
-       {0x19, 0x01},   /* vstrt */
-       {0x1a, 0x3d},   /* vstop */
-       {0x32, 0xff},   /* href */
-       {0xc0, 0xaa},
-};
-
-static const u8 ov965x_start_1_svga[][2] = {
-       {0x12, 0x02},   /* com7 - YUYV - VGA 15 full resolution */
-       {0x36, 0xf8},   /* aref3 */
-       {0x69, 0x02},   /* hv */
-       {0x8c, 0x0d},   /* com22 */
-       {0x3e, 0x0c},   /* com14 */
-       {0x41, 0x40},   /* com16 */
-       {0x72, 0x00},
-       {0x73, 0x01},
-       {0x74, 0x3a},
-       {0x75, 0x35},
-       {0x76, 0x01},
-       {0xc7, 0x80},   /* com24 */
-       {0x03, 0x1b},   /* vref */
-       {0x17, 0x1d},   /* hstart */
-       {0x18, 0xbd},   /* hstop */
-       {0x19, 0x01},   /* vstrt */
-       {0x1a, 0x81},   /* vstop */
-       {0x32, 0xff},   /* href */
-       {0xc0, 0xe2},
-};
-
-static const u8 ov965x_start_1_xga[][2] = {
-       {0x12, 0x02},   /* com7 */
-       {0x36, 0xf8},   /* aref3 */
-       {0x69, 0x02},   /* hv */
-       {0x8c, 0x89},   /* com22 */
-       {0x14, 0x28},   /* com9 */
-       {0x3e, 0x0c},   /* com14 */
-       {0x41, 0x40},   /* com16 */
-       {0x72, 0x00},
-       {0x73, 0x01},
-       {0x74, 0x3a},
-       {0x75, 0x35},
-       {0x76, 0x01},
-       {0xc7, 0x80},   /* com24 */
-       {0x03, 0x1b},   /* vref */
-       {0x17, 0x1d},   /* hstart */
-       {0x18, 0xbd},   /* hstop */
-       {0x19, 0x01},   /* vstrt */
-       {0x1a, 0x81},   /* vstop */
-       {0x32, 0xff},   /* href */
-       {0xc0, 0xe2},
-};
-
-static const u8 ov965x_start_1_sxga[][2] = {
-       {0x12, 0x02},   /* com7 */
-       {0x36, 0xf8},   /* aref3 */
-       {0x69, 0x02},   /* hv */
-       {0x8c, 0x89},   /* com22 */
-       {0x14, 0x28},   /* com9 */
-       {0x3e, 0x0c},   /* com14 */
-       {0x41, 0x40},   /* com16 */
-       {0x72, 0x00},
-       {0x73, 0x01},
-       {0x74, 0x3a},
-       {0x75, 0x35},
-       {0x76, 0x01},
-       {0xc7, 0x80},   /* com24 */
-       {0x03, 0x1b},   /* vref */
-       {0x17, 0x1d},   /* hstart */
-       {0x18, 0x02},   /* hstop */
-       {0x19, 0x01},   /* vstrt */
-       {0x1a, 0x81},   /* vstop */
-       {0x32, 0xff},   /* href */
-       {0xc0, 0xe2},
-};
-
-static const u8 bridge_start_qvga[][2] = {
-       {0x94, 0xaa},
-       {0xf1, 0x60},
-       {0xe5, 0x04},
-       {0xc0, 0x50},
-       {0xc1, 0x3c},
-       {0x8c, 0x00},
-       {0x8d, 0x1c},
-       {0x34, 0x05},
-
-       {0xc2, 0x4c},
-       {0xc3, 0xf9},
-       {0xda, 0x00},
-       {0x50, 0x00},
-       {0x51, 0xa0},
-       {0x52, 0x78},
-       {0x53, 0x00},
-       {0x54, 0x00},
-       {0x55, 0x00},
-       {0x57, 0x00},
-       {0x5c, 0x00},
-       {0x5a, 0x50},
-       {0x5b, 0x3c},
-       {0x35, 0x02},
-       {0xd9, 0x10},
-       {0x94, 0x11},
-};
-
-static const u8 bridge_start_vga[][2] = {
-       {0x94, 0xaa},
-       {0xf1, 0x60},
-       {0xe5, 0x04},
-       {0xc0, 0x50},
-       {0xc1, 0x3c},
-       {0x8c, 0x00},
-       {0x8d, 0x1c},
-       {0x34, 0x05},
-       {0xc2, 0x0c},
-       {0xc3, 0xf9},
-       {0xda, 0x01},
-       {0x50, 0x00},
-       {0x51, 0xa0},
-       {0x52, 0x3c},
-       {0x53, 0x00},
-       {0x54, 0x00},
-       {0x55, 0x00},
-       {0x57, 0x00},
-       {0x5c, 0x00},
-       {0x5a, 0xa0},
-       {0x5b, 0x78},
-       {0x35, 0x02},
-       {0xd9, 0x10},
-       {0x94, 0x11},
-};
-
-static const u8 bridge_start_svga[][2] = {
-       {0x94, 0xaa},
-       {0xf1, 0x60},
-       {0xe5, 0x04},
-       {0xc0, 0xa0},
-       {0xc1, 0x80},
-       {0x8c, 0x00},
-       {0x8d, 0x1c},
-       {0x34, 0x05},
-       {0xc2, 0x4c},
-       {0xc3, 0xf9},
-       {0x50, 0x00},
-       {0x51, 0x40},
-       {0x52, 0x00},
-       {0x53, 0x00},
-       {0x54, 0x00},
-       {0x55, 0x88},
-       {0x57, 0x00},
-       {0x5c, 0x00},
-       {0x5a, 0xc8},
-       {0x5b, 0x96},
-       {0x35, 0x02},
-       {0xd9, 0x10},
-       {0xda, 0x00},
-       {0x94, 0x11},
-};
-
-static const u8 bridge_start_xga[][2] = {
-       {0x94, 0xaa},
-       {0xf1, 0x60},
-       {0xe5, 0x04},
-       {0xc0, 0xa0},
-       {0xc1, 0x80},
-       {0x8c, 0x00},
-       {0x8d, 0x1c},
-       {0x34, 0x05},
-       {0xc2, 0x4c},
-       {0xc3, 0xf9},
-       {0x50, 0x00},
-       {0x51, 0x40},
-       {0x52, 0x00},
-       {0x53, 0x00},
-       {0x54, 0x00},
-       {0x55, 0x88},
-       {0x57, 0x00},
-       {0x5c, 0x01},
-       {0x5a, 0x00},
-       {0x5b, 0xc0},
-       {0x35, 0x02},
-       {0xd9, 0x10},
-       {0xda, 0x01},
-       {0x94, 0x11},
-};
-
-static const u8 bridge_start_sxga[][2] = {
-       {0x94, 0xaa},
-       {0xf1, 0x60},
-       {0xe5, 0x04},
-       {0xc0, 0xa0},
-       {0xc1, 0x80},
-       {0x8c, 0x00},
-       {0x8d, 0x1c},
-       {0x34, 0x05},
-       {0xc2, 0x0c},
-       {0xc3, 0xf9},
-       {0xda, 0x00},
-       {0x35, 0x02},
-       {0xd9, 0x10},
-       {0x94, 0x11},
-};
-
-static const u8 ov965x_start_2_qvga[][2] = {
-       {0x3b, 0xe4},   /* com11 - night mode 1/4 frame rate */
-       {0x1e, 0x04},   /* mvfp */
-       {0x13, 0xe0},   /* com8 */
-       {0x00, 0x00},
-       {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
-       {0x11, 0x01},   /* clkrc */
-       {0x6b, 0x5a},   /* dblv */
-       {0x6a, 0x02},   /* 50 Hz banding filter */
-       {0xc5, 0x03},   /* 60 Hz banding filter */
-       {0xa2, 0x96},   /* bd50 */
-       {0xa3, 0x7d},   /* bd60 */
-
-       {0xff, 0x13},   /* read 13, write ff 00 */
-       {0x13, 0xe7},
-       {0x3a, 0x80},   /* tslb - yuyv */
-};
-
-static const u8 ov965x_start_2_vga[][2] = {
-       {0x3b, 0xc4},   /* com11 - night mode 1/4 frame rate */
-       {0x1e, 0x04},   /* mvfp */
-       {0x13, 0xe0},   /* com8 */
-       {0x00, 0x00},
-       {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
-       {0x11, 0x03},   /* clkrc */
-       {0x6b, 0x5a},   /* dblv */
-       {0x6a, 0x05},   /* 50 Hz banding filter */
-       {0xc5, 0x07},   /* 60 Hz banding filter */
-       {0xa2, 0x4b},   /* bd50 */
-       {0xa3, 0x3e},   /* bd60 */
-
-       {0x2d, 0x00},   /* advfl */
-};
-
-static const u8 ov965x_start_2_svga[][2] = {   /* same for xga */
-       {0x3b, 0xc4},   /* com11 - night mode 1/4 frame rate */
-       {0x1e, 0x04},   /* mvfp */
-       {0x13, 0xe0},   /* com8 */
-       {0x00, 0x00},
-       {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
-       {0x11, 0x01},   /* clkrc */
-       {0x6b, 0x5a},   /* dblv */
-       {0x6a, 0x0c},   /* 50 Hz banding filter */
-       {0xc5, 0x0f},   /* 60 Hz banding filter */
-       {0xa2, 0x4e},   /* bd50 */
-       {0xa3, 0x41},   /* bd60 */
-};
-
-static const u8 ov965x_start_2_sxga[][2] = {
-       {0x13, 0xe0},   /* com8 */
-       {0x00, 0x00},
-       {0x13, 0xe7},   /* com8 - everything (AGC, AWB and AEC) */
-       {0x3b, 0xc4},   /* com11 - night mode 1/4 frame rate */
-       {0x1e, 0x04},   /* mvfp */
-       {0x11, 0x01},   /* clkrc */
-       {0x6b, 0x5a},   /* dblv */
-       {0x6a, 0x0c},   /* 50 Hz banding filter */
-       {0xc5, 0x0f},   /* 60 Hz banding filter */
-       {0xa2, 0x4e},   /* bd50 */
-       {0xa3, 0x41},   /* bd60 */
-};
-
-static const u8 ov562x_init[][2] = {
-       {0x88, 0x20},
-       {0x89, 0x0a},
-       {0x8a, 0x90},
-       {0x8b, 0x06},
-       {0x8c, 0x01},
-       {0x8d, 0x10},
-       {0x1c, 0x00},
-       {0x1d, 0x48},
-       {0x1d, 0x00},
-       {0x1d, 0xff},
-       {0x1c, 0x0a},
-       {0x1d, 0x2e},
-       {0x1d, 0x1e},
-};
-
-static const u8 ov562x_init_2[][2] = {
-       {0x12, 0x80},
-       {0x11, 0x41},
-       {0x13, 0x00},
-       {0x10, 0x1e},
-       {0x3b, 0x07},
-       {0x5b, 0x40},
-       {0x39, 0x07},
-       {0x53, 0x02},
-       {0x54, 0x60},
-       {0x04, 0x20},
-       {0x27, 0x04},
-       {0x3d, 0x40},
-       {0x36, 0x00},
-       {0xc5, 0x04},
-       {0x4e, 0x00},
-       {0x4f, 0x93},
-       {0x50, 0x7b},
-       {0xca, 0x0c},
-       {0xcb, 0x0f},
-       {0x39, 0x07},
-       {0x4a, 0x10},
-       {0x3e, 0x0a},
-       {0x3d, 0x00},
-       {0x0c, 0x38},
-       {0x38, 0x90},
-       {0x46, 0x30},
-       {0x4f, 0x93},
-       {0x50, 0x7b},
-       {0xab, 0x00},
-       {0xca, 0x0c},
-       {0xcb, 0x0f},
-       {0x37, 0x02},
-       {0x44, 0x48},
-       {0x8d, 0x44},
-       {0x2a, 0x00},
-       {0x2b, 0x00},
-       {0x32, 0x00},
-       {0x38, 0x90},
-       {0x53, 0x02},
-       {0x54, 0x60},
-       {0x12, 0x00},
-       {0x17, 0x12},
-       {0x18, 0xb4},
-       {0x19, 0x0c},
-       {0x1a, 0xf4},
-       {0x03, 0x4a},
-       {0x89, 0x20},
-       {0x83, 0x80},
-       {0xb7, 0x9d},
-       {0xb6, 0x11},
-       {0xb5, 0x55},
-       {0xb4, 0x00},
-       {0xa9, 0xf0},
-       {0xa8, 0x0a},
-       {0xb8, 0xf0},
-       {0xb9, 0xf0},
-       {0xba, 0xf0},
-       {0x81, 0x07},
-       {0x63, 0x44},
-       {0x13, 0xc7},
-       {0x14, 0x60},
-       {0x33, 0x75},
-       {0x2c, 0x00},
-       {0x09, 0x00},
-       {0x35, 0x30},
-       {0x27, 0x04},
-       {0x3c, 0x07},
-       {0x3a, 0x0a},
-       {0x3b, 0x07},
-       {0x01, 0x40},
-       {0x02, 0x40},
-       {0x16, 0x40},
-       {0x52, 0xb0},
-       {0x51, 0x83},
-       {0x21, 0xbb},
-       {0x22, 0x10},
-       {0x23, 0x03},
-       {0x35, 0x38},
-       {0x20, 0x90},
-       {0x28, 0x30},
-       {0x73, 0xe1},
-       {0x6c, 0x00},
-       {0x6d, 0x80},
-       {0x6e, 0x00},
-       {0x70, 0x04},
-       {0x71, 0x00},
-       {0x8d, 0x04},
-       {0x64, 0x00},
-       {0x65, 0x00},
-       {0x66, 0x00},
-       {0x67, 0x00},
-       {0x68, 0x00},
-       {0x69, 0x00},
-       {0x6a, 0x00},
-       {0x6b, 0x00},
-       {0x71, 0x94},
-       {0x74, 0x20},
-       {0x80, 0x09},
-       {0x85, 0xc0},
-};
-
-static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val)
-{
-       struct usb_device *udev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       gspca_dev->usb_buf[0] = val;
-       ret = usb_control_msg(udev,
-                             usb_sndctrlpipe(udev, 0),
-                             0x01,
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
-       if (ret < 0) {
-               pr_err("reg_w failed %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void reg_w(struct gspca_dev *gspca_dev, u16 reg, u8 val)
-{
-       PDEBUG(D_USBO, "reg_w [%04x] = %02x", reg, val);
-       reg_w_i(gspca_dev, reg, val);
-}
-
-static u8 reg_r(struct gspca_dev *gspca_dev, u16 reg)
-{
-       struct usb_device *udev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return 0;
-       ret = usb_control_msg(udev,
-                             usb_rcvctrlpipe(udev, 0),
-                             0x01,
-                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             0x00, reg, gspca_dev->usb_buf, 1, CTRL_TIMEOUT);
-       PDEBUG(D_USBI, "reg_r [%04x] -> %02x", reg, gspca_dev->usb_buf[0]);
-       if (ret < 0) {
-               pr_err("reg_r err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-       return gspca_dev->usb_buf[0];
-}
-
-static int sccb_check_status(struct gspca_dev *gspca_dev)
-{
-       u8 data;
-       int i;
-
-       for (i = 0; i < 5; i++) {
-               msleep(10);
-               data = reg_r(gspca_dev, OV534_REG_STATUS);
-
-               switch (data) {
-               case 0x00:
-                       return 1;
-               case 0x04:
-                       return 0;
-               case 0x03:
-                       break;
-               default:
-                       PDEBUG(D_USBI|D_USBO,
-                               "sccb status 0x%02x, attempt %d/5",
-                               data, i + 1);
-               }
-       }
-       return 0;
-}
-
-static void sccb_write(struct gspca_dev *gspca_dev, u8 reg, u8 val)
-{
-       PDEBUG(D_USBO, "sccb_write [%02x] = %02x", reg, val);
-       reg_w_i(gspca_dev, OV534_REG_SUBADDR, reg);
-       reg_w_i(gspca_dev, OV534_REG_WRITE, val);
-       reg_w_i(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_3);
-
-       if (!sccb_check_status(gspca_dev))
-               pr_err("sccb_write failed\n");
-}
-
-static u8 sccb_read(struct gspca_dev *gspca_dev, u16 reg)
-{
-       reg_w(gspca_dev, OV534_REG_SUBADDR, reg);
-       reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_WRITE_2);
-       if (!sccb_check_status(gspca_dev))
-               pr_err("sccb_read failed 1\n");
-
-       reg_w(gspca_dev, OV534_REG_OPERATION, OV534_OP_READ_2);
-       if (!sccb_check_status(gspca_dev))
-               pr_err("sccb_read failed 2\n");
-
-       return reg_r(gspca_dev, OV534_REG_READ);
-}
-
-/* output a bridge sequence (reg - val) */
-static void reg_w_array(struct gspca_dev *gspca_dev,
-                       const u8 (*data)[2], int len)
-{
-       while (--len >= 0) {
-               reg_w(gspca_dev, (*data)[0], (*data)[1]);
-               data++;
-       }
-}
-
-/* output a sensor sequence (reg - val) */
-static void sccb_w_array(struct gspca_dev *gspca_dev,
-                       const u8 (*data)[2], int len)
-{
-       while (--len >= 0) {
-               if ((*data)[0] != 0xff) {
-                       sccb_write(gspca_dev, (*data)[0], (*data)[1]);
-               } else {
-                       sccb_read(gspca_dev, (*data)[1]);
-                       sccb_write(gspca_dev, 0xff, 0x00);
-               }
-               data++;
-       }
-}
-
-/* Two bits control LED: 0x21 bit 7 and 0x23 bit 7.
- * (direction and output)? */
-static void set_led(struct gspca_dev *gspca_dev, int status)
-{
-       u8 data;
-
-       PDEBUG(D_CONF, "led status: %d", status);
-
-       data = reg_r(gspca_dev, 0x21);
-       data |= 0x80;
-       reg_w(gspca_dev, 0x21, data);
-
-       data = reg_r(gspca_dev, 0x23);
-       if (status)
-               data |= 0x80;
-       else
-               data &= ~0x80;
-
-       reg_w(gspca_dev, 0x23, data);
-
-       if (!status) {
-               data = reg_r(gspca_dev, 0x21);
-               data &= ~0x80;
-               reg_w(gspca_dev, 0x21, data);
-       }
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 val;
-       s8 sval;
-
-       if (sd->sensor == SENSOR_OV562x) {
-               sval = brightness;
-               val = 0x76;
-               val += sval;
-               sccb_write(gspca_dev, 0x24, val);
-               val = 0x6a;
-               val += sval;
-               sccb_write(gspca_dev, 0x25, val);
-               if (sval < -40)
-                       val = 0x71;
-               else if (sval < 20)
-                       val = 0x94;
-               else
-                       val = 0xe6;
-               sccb_write(gspca_dev, 0x26, val);
-       } else {
-               val = brightness;
-               if (val < 8)
-                       val = 15 - val;         /* f .. 8 */
-               else
-                       val = val - 8;          /* 0 .. 7 */
-               sccb_write(gspca_dev, 0x55,     /* brtn - brightness adjustment */
-                               0x0f | (val << 4));
-       }
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
-{
-       sccb_write(gspca_dev, 0x56,     /* cnst1 - contrast 1 ctrl coeff */
-                       val << 4);
-}
-
-static void setautogain(struct gspca_dev *gspca_dev, s32 autogain)
-{
-       u8 val;
-
-/*fixme: should adjust agc/awb/aec by different controls */
-       val = sccb_read(gspca_dev, 0x13);               /* com8 */
-       sccb_write(gspca_dev, 0xff, 0x00);
-       if (autogain)
-               val |= 0x05;            /* agc & aec */
-       else
-               val &= 0xfa;
-       sccb_write(gspca_dev, 0x13, val);
-}
-
-static void setexposure(struct gspca_dev *gspca_dev, s32 exposure)
-{
-       static const u8 expo[4] = {0x00, 0x25, 0x38, 0x5e};
-       u8 val;
-
-       sccb_write(gspca_dev, 0x10, expo[exposure]);    /* aec[9:2] */
-
-       val = sccb_read(gspca_dev, 0x13);               /* com8 */
-       sccb_write(gspca_dev, 0xff, 0x00);
-       sccb_write(gspca_dev, 0x13, val);
-
-       val = sccb_read(gspca_dev, 0xa1);               /* aech */
-       sccb_write(gspca_dev, 0xff, 0x00);
-       sccb_write(gspca_dev, 0xa1, val & 0xe0);        /* aec[15:10] = 0 */
-}
-
-static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
-{
-       if (val < 0) {                          /* auto */
-               val = sccb_read(gspca_dev, 0x42);       /* com17 */
-               sccb_write(gspca_dev, 0xff, 0x00);
-               sccb_write(gspca_dev, 0x42, val | 0x40);
-                               /* Edge enhancement strength auto adjust */
-               return;
-       }
-       if (val != 0)
-               val = 1 << (val - 1);
-       sccb_write(gspca_dev, 0x3f,     /* edge - edge enhance. factor */
-                       val);
-       val = sccb_read(gspca_dev, 0x42);               /* com17 */
-       sccb_write(gspca_dev, 0xff, 0x00);
-       sccb_write(gspca_dev, 0x42, val & 0xbf);
-}
-
-static void setsatur(struct gspca_dev *gspca_dev, s32 val)
-{
-       u8 val1, val2, val3;
-       static const u8 matrix[5][2] = {
-               {0x14, 0x38},
-               {0x1e, 0x54},
-               {0x28, 0x70},
-               {0x32, 0x8c},
-               {0x48, 0x90}
-       };
-
-       val1 = matrix[val][0];
-       val2 = matrix[val][1];
-       val3 = val1 + val2;
-       sccb_write(gspca_dev, 0x4f, val3);      /* matrix coeff */
-       sccb_write(gspca_dev, 0x50, val3);
-       sccb_write(gspca_dev, 0x51, 0x00);
-       sccb_write(gspca_dev, 0x52, val1);
-       sccb_write(gspca_dev, 0x53, val2);
-       sccb_write(gspca_dev, 0x54, val3);
-       sccb_write(gspca_dev, 0x58, 0x1a);      /* mtxs - coeff signs */
-
-       val1 = sccb_read(gspca_dev, 0x41);      /* com16 */
-       sccb_write(gspca_dev, 0xff, 0x00);
-       sccb_write(gspca_dev, 0x41, val1);
-}
-
-static void setlightfreq(struct gspca_dev *gspca_dev, s32 freq)
-{
-       u8 val;
-
-       val = sccb_read(gspca_dev, 0x13);               /* com8 */
-       sccb_write(gspca_dev, 0xff, 0x00);
-       if (freq == 0) {
-               sccb_write(gspca_dev, 0x13, val & 0xdf);
-               return;
-       }
-       sccb_write(gspca_dev, 0x13, val | 0x20);
-
-       val = sccb_read(gspca_dev, 0x42);               /* com17 */
-       sccb_write(gspca_dev, 0xff, 0x00);
-       if (freq == 1)
-               val |= 0x01;
-       else
-               val &= 0xfe;
-       sccb_write(gspca_dev, 0x42, val);
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                    const struct usb_device_id *id)
-{
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u16 sensor_id;
-
-       /* reset bridge */
-       reg_w(gspca_dev, 0xe7, 0x3a);
-       reg_w(gspca_dev, 0xe0, 0x08);
-       msleep(100);
-
-       /* initialize the sensor address */
-       reg_w(gspca_dev, OV534_REG_ADDRESS, 0x60);
-
-       /* reset sensor */
-       sccb_write(gspca_dev, 0x12, 0x80);
-       msleep(10);
-
-       /* probe the sensor */
-       sccb_read(gspca_dev, 0x0a);
-       sensor_id = sccb_read(gspca_dev, 0x0a) << 8;
-       sccb_read(gspca_dev, 0x0b);
-       sensor_id |= sccb_read(gspca_dev, 0x0b);
-       PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
-
-       /* initialize */
-       if ((sensor_id & 0xfff0) == 0x9650) {
-               sd->sensor = SENSOR_OV965x;
-
-               gspca_dev->cam.cam_mode = ov965x_mode;
-               gspca_dev->cam.nmodes = ARRAY_SIZE(ov965x_mode);
-
-               reg_w_array(gspca_dev, bridge_init,
-                               ARRAY_SIZE(bridge_init));
-               sccb_w_array(gspca_dev, ov965x_init,
-                               ARRAY_SIZE(ov965x_init));
-               reg_w_array(gspca_dev, bridge_init_2,
-                               ARRAY_SIZE(bridge_init_2));
-               sccb_w_array(gspca_dev, ov965x_init_2,
-                               ARRAY_SIZE(ov965x_init_2));
-               reg_w(gspca_dev, 0xe0, 0x00);
-               reg_w(gspca_dev, 0xe0, 0x01);
-               set_led(gspca_dev, 0);
-               reg_w(gspca_dev, 0xe0, 0x00);
-       } else if ((sensor_id & 0xfff0) == 0x9710) {
-               const char *p;
-               int l;
-
-               sd->sensor = SENSOR_OV971x;
-
-               gspca_dev->cam.cam_mode = ov971x_mode;
-               gspca_dev->cam.nmodes = ARRAY_SIZE(ov971x_mode);
-
-               gspca_dev->cam.bulk = 1;
-               gspca_dev->cam.bulk_size = 16384;
-               gspca_dev->cam.bulk_nurbs = 2;
-
-               sccb_w_array(gspca_dev, ov971x_init,
-                               ARRAY_SIZE(ov971x_init));
-
-               /* set video format on bridge processor */
-               /* access bridge processor's video format registers at: 0x00 */
-               reg_w(gspca_dev, 0x1c, 0x00);
-               /*set register: 0x00 is 'RAW8', 0x40 is 'YUV422' (YUYV?)*/
-               reg_w(gspca_dev, 0x1d, 0x00);
-
-               /* Will W. specific stuff
-                * set VSYNC to
-                *      output (0x1f) if first webcam
-                *      input (0x17) if 2nd or 3rd webcam */
-               p = video_device_node_name(&gspca_dev->vdev);
-               l = strlen(p) - 1;
-               if (p[l] == '0')
-                       reg_w(gspca_dev, 0x56, 0x1f);
-               else
-                       reg_w(gspca_dev, 0x56, 0x17);
-       } else if ((sensor_id & 0xfff0) == 0x5620) {
-               sd->sensor = SENSOR_OV562x;
-               gspca_dev->cam.cam_mode = ov562x_mode;
-               gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode);
-
-               reg_w_array(gspca_dev, ov562x_init,
-                               ARRAY_SIZE(ov562x_init));
-               sccb_w_array(gspca_dev, ov562x_init_2,
-                               ARRAY_SIZE(ov562x_init_2));
-               reg_w(gspca_dev, 0xe0, 0x00);
-       } else {
-               pr_err("Unknown sensor %04x", sensor_id);
-               return -EINVAL;
-       }
-
-       return gspca_dev->usb_err;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_OV971x)
-               return gspca_dev->usb_err;
-       if (sd->sensor == SENSOR_OV562x)
-               return gspca_dev->usb_err;
-
-       switch (gspca_dev->curr_mode) {
-       case QVGA_MODE:                 /* 320x240 */
-               sccb_w_array(gspca_dev, ov965x_start_1_vga,
-                               ARRAY_SIZE(ov965x_start_1_vga));
-               reg_w_array(gspca_dev, bridge_start_qvga,
-                               ARRAY_SIZE(bridge_start_qvga));
-               sccb_w_array(gspca_dev, ov965x_start_2_qvga,
-                               ARRAY_SIZE(ov965x_start_2_qvga));
-               break;
-       case VGA_MODE:                  /* 640x480 */
-               sccb_w_array(gspca_dev, ov965x_start_1_vga,
-                               ARRAY_SIZE(ov965x_start_1_vga));
-               reg_w_array(gspca_dev, bridge_start_vga,
-                               ARRAY_SIZE(bridge_start_vga));
-               sccb_w_array(gspca_dev, ov965x_start_2_vga,
-                               ARRAY_SIZE(ov965x_start_2_vga));
-               break;
-       case SVGA_MODE:                 /* 800x600 */
-               sccb_w_array(gspca_dev, ov965x_start_1_svga,
-                               ARRAY_SIZE(ov965x_start_1_svga));
-               reg_w_array(gspca_dev, bridge_start_svga,
-                               ARRAY_SIZE(bridge_start_svga));
-               sccb_w_array(gspca_dev, ov965x_start_2_svga,
-                               ARRAY_SIZE(ov965x_start_2_svga));
-               break;
-       case XGA_MODE:                  /* 1024x768 */
-               sccb_w_array(gspca_dev, ov965x_start_1_xga,
-                               ARRAY_SIZE(ov965x_start_1_xga));
-               reg_w_array(gspca_dev, bridge_start_xga,
-                               ARRAY_SIZE(bridge_start_xga));
-               sccb_w_array(gspca_dev, ov965x_start_2_svga,
-                               ARRAY_SIZE(ov965x_start_2_svga));
-               break;
-       default:
-/*     case SXGA_MODE:                  * 1280x1024 */
-               sccb_w_array(gspca_dev, ov965x_start_1_sxga,
-                               ARRAY_SIZE(ov965x_start_1_sxga));
-               reg_w_array(gspca_dev, bridge_start_sxga,
-                               ARRAY_SIZE(bridge_start_sxga));
-               sccb_w_array(gspca_dev, ov965x_start_2_sxga,
-                               ARRAY_SIZE(ov965x_start_2_sxga));
-               break;
-       }
-
-       reg_w(gspca_dev, 0xe0, 0x00);
-       reg_w(gspca_dev, 0xe0, 0x00);
-       set_led(gspca_dev, 1);
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       reg_w(gspca_dev, 0xe0, 0x01);
-       set_led(gspca_dev, 0);
-       reg_w(gspca_dev, 0xe0, 0x00);
-}
-
-/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */
-#define UVC_STREAM_EOH (1 << 7)
-#define UVC_STREAM_ERR (1 << 6)
-#define UVC_STREAM_STI (1 << 5)
-#define UVC_STREAM_RES (1 << 4)
-#define UVC_STREAM_SCR (1 << 3)
-#define UVC_STREAM_PTS (1 << 2)
-#define UVC_STREAM_EOF (1 << 1)
-#define UVC_STREAM_FID (1 << 0)
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data, int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       __u32 this_pts;
-       u8 this_fid;
-       int remaining_len = len;
-       int payload_len;
-
-       payload_len = gspca_dev->cam.bulk ? 2048 : 2040;
-       do {
-               len = min(remaining_len, payload_len);
-
-               /* Payloads are prefixed with a UVC-style header.  We
-                  consider a frame to start when the FID toggles, or the PTS
-                  changes.  A frame ends when EOF is set, and we've received
-                  the correct number of bytes. */
-
-               /* Verify UVC header.  Header length is always 12 */
-               if (data[0] != 12 || len < 12) {
-                       PDEBUG(D_PACK, "bad header");
-                       goto discard;
-               }
-
-               /* Check errors */
-               if (data[1] & UVC_STREAM_ERR) {
-                       PDEBUG(D_PACK, "payload error");
-                       goto discard;
-               }
-
-               /* Extract PTS and FID */
-               if (!(data[1] & UVC_STREAM_PTS)) {
-                       PDEBUG(D_PACK, "PTS not present");
-                       goto discard;
-               }
-               this_pts = (data[5] << 24) | (data[4] << 16)
-                                               | (data[3] << 8) | data[2];
-               this_fid = data[1] & UVC_STREAM_FID;
-
-               /* If PTS or FID has changed, start a new frame. */
-               if (this_pts != sd->last_pts || this_fid != sd->last_fid) {
-                       if (gspca_dev->last_packet_type == INTER_PACKET)
-                               gspca_frame_add(gspca_dev, LAST_PACKET,
-                                               NULL, 0);
-                       sd->last_pts = this_pts;
-                       sd->last_fid = this_fid;
-                       gspca_frame_add(gspca_dev, FIRST_PACKET,
-                                       data + 12, len - 12);
-               /* If this packet is marked as EOF, end the frame */
-               } else if (data[1] & UVC_STREAM_EOF) {
-                       sd->last_pts = 0;
-                       gspca_frame_add(gspca_dev, LAST_PACKET,
-                                       data + 12, len - 12);
-               } else {
-
-                       /* Add the data from this payload */
-                       gspca_frame_add(gspca_dev, INTER_PACKET,
-                                       data + 12, len - 12);
-               }
-
-               /* Done this payload */
-               goto scan_next;
-
-discard:
-               /* Discard data until a new frame starts. */
-               gspca_dev->last_packet_type = DISCARD_PACKET;
-
-scan_next:
-               remaining_len -= len;
-               data += len;
-       } while (remaining_len > 0);
-}
-
-static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct gspca_dev *gspca_dev =
-               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
-
-       gspca_dev->usb_err = 0;
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               setsatur(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_POWER_LINE_FREQUENCY:
-               setlightfreq(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SHARPNESS:
-               setsharpness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               if (ctrl->is_new)
-                       setautogain(gspca_dev, ctrl->val);
-               if (!ctrl->val && gspca_dev->exposure->is_new)
-                       setexposure(gspca_dev, gspca_dev->exposure->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;
-
-       if (sd->sensor == SENSOR_OV971x)
-               return 0;
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 7);
-       if (sd->sensor == SENSOR_OV562x) {
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, -90, 90, 1, 0);
-       } else {
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 15, 1, 7);
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 15, 1, 3);
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 4, 1, 2);
-               /* -1 = auto */
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SHARPNESS, -1, 4, 1, -1);
-               gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 0, 3, 1, 0);
-               v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
-                       V4L2_CID_POWER_LINE_FREQUENCY,
-                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
-               v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
-       }
-
-       if (hdl->error) {
-               pr_err("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,
-       .stopN    = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x05a9, 0x8065)},
-       {USB_DEVICE(0x06f8, 0x3003)},
-       {USB_DEVICE(0x05a9, 0x1550)},
-       {}
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c
deleted file mode 100644 (file)
index d236d17..0000000
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * Pixart PAC207BCA library
- *
- * Copyright (C) 2008 Hans de Goede <hdegoede@redhat.com>
- * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
- * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr
- *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "pac207"
-
-#include <linux/input.h>
-#include "gspca.h"
-/* Include pac common sof detection functions */
-#include "pac_common.h"
-
-MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
-MODULE_DESCRIPTION("Pixart PAC207");
-MODULE_LICENSE("GPL");
-
-#define PAC207_CTRL_TIMEOUT            100  /* ms */
-
-#define PAC207_BRIGHTNESS_MIN          0
-#define PAC207_BRIGHTNESS_MAX          255
-#define PAC207_BRIGHTNESS_DEFAULT      46
-#define PAC207_BRIGHTNESS_REG          0x08
-
-#define PAC207_EXPOSURE_MIN            3
-#define PAC207_EXPOSURE_MAX            90 /* 1 sec expo time / 1 fps */
-#define PAC207_EXPOSURE_DEFAULT                5 /* power on default: 3 */
-#define PAC207_EXPOSURE_REG            0x02
-
-#define PAC207_GAIN_MIN                        0
-#define PAC207_GAIN_MAX                        31
-#define PAC207_GAIN_DEFAULT            7 /* power on default: 9 */
-#define PAC207_GAIN_REG                        0x0e
-
-#define PAC207_AUTOGAIN_DEADZONE       30
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;             /* !! must be the first item */
-
-       struct v4l2_ctrl *brightness;
-
-       u8 mode;
-       u8 sof_read;
-       u8 header_read;
-       u8 autogain_ignore_frames;
-
-       atomic_t avg_lum;
-};
-
-static const struct v4l2_pix_format sif_mode[] = {
-       {176, 144, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = (176 + 2) * 144,
-                       /* uncompressed, add 2 bytes / line for line header */
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {352, 288, V4L2_PIX_FMT_PAC207, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-                       /* compressed, but only when needed (not compressed
-                          when the framerate is low) */
-               .sizeimage = (352 + 2) * 288,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-static const __u8 pac207_sensor_init[][8] = {
-       {0x10, 0x12, 0x0d, 0x12, 0x0c, 0x01, 0x29, 0x84},
-       {0x49, 0x64, 0x64, 0x64, 0x04, 0x10, 0xf0, 0x30},
-       {0x00, 0x00, 0x00, 0x70, 0xa0, 0xf8, 0x00, 0x00},
-       {0x32, 0x00, 0x96, 0x00, 0xa2, 0x02, 0xaf, 0x00},
-};
-
-static void pac207_write_regs(struct gspca_dev *gspca_dev, u16 index,
-       const u8 *buffer, u16 length)
-{
-       struct usb_device *udev = gspca_dev->dev;
-       int err;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-
-       memcpy(gspca_dev->usb_buf, buffer, length);
-
-       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       0x00, index,
-                       gspca_dev->usb_buf, length, PAC207_CTRL_TIMEOUT);
-       if (err < 0) {
-               pr_err("Failed to write registers to index 0x%04X, error %d\n",
-                      index, err);
-               gspca_dev->usb_err = err;
-       }
-}
-
-static void pac207_write_reg(struct gspca_dev *gspca_dev, u16 index, u16 value)
-{
-       struct usb_device *udev = gspca_dev->dev;
-       int err;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-
-       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       value, index, NULL, 0, PAC207_CTRL_TIMEOUT);
-       if (err) {
-               pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
-                      index, value, err);
-               gspca_dev->usb_err = err;
-       }
-}
-
-static int pac207_read_reg(struct gspca_dev *gspca_dev, u16 index)
-{
-       struct usb_device *udev = gspca_dev->dev;
-       int res;
-
-       if (gspca_dev->usb_err < 0)
-               return 0;
-
-       res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       0x00, index,
-                       gspca_dev->usb_buf, 1, PAC207_CTRL_TIMEOUT);
-       if (res < 0) {
-               pr_err("Failed to read a register (index 0x%04X, error %d)\n",
-                      index, res);
-               gspca_dev->usb_err = res;
-               return 0;
-       }
-
-       return gspca_dev->usb_buf[0];
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct cam *cam;
-       u8 idreg[2];
-
-       idreg[0] = pac207_read_reg(gspca_dev, 0x0000);
-       idreg[1] = pac207_read_reg(gspca_dev, 0x0001);
-       idreg[0] = ((idreg[0] & 0x0f) << 4) | ((idreg[1] & 0xf0) >> 4);
-       idreg[1] = idreg[1] & 0x0f;
-       PDEBUG(D_PROBE, "Pixart Sensor ID 0x%02X Chips ID 0x%02X",
-               idreg[0], idreg[1]);
-
-       if (idreg[0] != 0x27) {
-               PDEBUG(D_PROBE, "Error invalid sensor ID!");
-               return -ENODEV;
-       }
-
-       PDEBUG(D_PROBE,
-               "Pixart PAC207BCA Image Processor and Control Chip detected"
-               " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
-
-       cam = &gspca_dev->cam;
-       cam->cam_mode = sif_mode;
-       cam->nmodes = ARRAY_SIZE(sif_mode);
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       pac207_write_reg(gspca_dev, 0x41, 0x00);
-                               /* Bit_0=Image Format,
-                                * Bit_1=LED,
-                                * Bit_2=Compression test mode enable */
-       pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
-
-       return gspca_dev->usb_err;
-}
-
-static void setcontrol(struct gspca_dev *gspca_dev, u16 reg, u16 val)
-{
-       pac207_write_reg(gspca_dev, reg, val);
-       pac207_write_reg(gspca_dev, 0x13, 0x01);        /* Bit 0, auto clear */
-       pac207_write_reg(gspca_dev, 0x1c, 0x01);        /* not documented */
-}
-
-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 (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
-               /* when switching to autogain set defaults to make sure
-                  we are on a valid point of the autogain gain /
-                  exposure knee graph, and give this change time to
-                  take effect before doing autogain. */
-               gspca_dev->exposure->val    = PAC207_EXPOSURE_DEFAULT;
-               gspca_dev->gain->val        = PAC207_GAIN_DEFAULT;
-               sd->autogain_ignore_frames  = PAC_AUTOGAIN_IGNORE_FRAMES;
-       }
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               setcontrol(gspca_dev, PAC207_BRIGHTNESS_REG, ctrl->val);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
-                       setcontrol(gspca_dev, PAC207_EXPOSURE_REG,
-                                  gspca_dev->exposure->val);
-               if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
-                       setcontrol(gspca_dev, PAC207_GAIN_REG,
-                                  gspca_dev->gain->val);
-               break;
-       default:
-               return -EINVAL;
-       }
-       return gspca_dev->usb_err;
-}
-
-static const struct v4l2_ctrl_ops sd_ctrl_ops = {
-       .s_ctrl = sd_s_ctrl,
-};
-
-/* this function is called at probe time */
-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);
-
-       sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                               V4L2_CID_BRIGHTNESS,
-                               PAC207_BRIGHTNESS_MIN, PAC207_BRIGHTNESS_MAX,
-                               1, PAC207_BRIGHTNESS_DEFAULT);
-       gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                               V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-       gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                               V4L2_CID_EXPOSURE,
-                               PAC207_EXPOSURE_MIN, PAC207_EXPOSURE_MAX,
-                               1, PAC207_EXPOSURE_DEFAULT);
-       gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                               V4L2_CID_GAIN,
-                               PAC207_GAIN_MIN, PAC207_GAIN_MAX,
-                               1, PAC207_GAIN_DEFAULT);
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-       v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
-       return 0;
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       __u8 mode;
-
-       pac207_write_reg(gspca_dev, 0x0f, 0x10); /* Power control (Bit 6-0) */
-       pac207_write_regs(gspca_dev, 0x0002, pac207_sensor_init[0], 8);
-       pac207_write_regs(gspca_dev, 0x000a, pac207_sensor_init[1], 8);
-       pac207_write_regs(gspca_dev, 0x0012, pac207_sensor_init[2], 8);
-       pac207_write_regs(gspca_dev, 0x0042, pac207_sensor_init[3], 8);
-
-       /* Compression Balance */
-       if (gspca_dev->width == 176)
-               pac207_write_reg(gspca_dev, 0x4a, 0xff);
-       else
-               pac207_write_reg(gspca_dev, 0x4a, 0x30);
-       pac207_write_reg(gspca_dev, 0x4b, 0x00); /* Sram test value */
-       pac207_write_reg(gspca_dev, 0x08, v4l2_ctrl_g_ctrl(sd->brightness));
-
-       /* PGA global gain (Bit 4-0) */
-       pac207_write_reg(gspca_dev, 0x0e,
-               v4l2_ctrl_g_ctrl(gspca_dev->gain));
-       pac207_write_reg(gspca_dev, 0x02,
-               v4l2_ctrl_g_ctrl(gspca_dev->exposure)); /* PXCK = 12MHz /n */
-
-       mode = 0x02; /* Image Format (Bit 0), LED (1), Compr. test mode (2) */
-       if (gspca_dev->width == 176) {  /* 176x144 */
-               mode |= 0x01;
-               PDEBUG(D_STREAM, "pac207_start mode 176x144");
-       } else {                                /* 352x288 */
-               PDEBUG(D_STREAM, "pac207_start mode 352x288");
-       }
-       pac207_write_reg(gspca_dev, 0x41, mode);
-
-       pac207_write_reg(gspca_dev, 0x13, 0x01); /* Bit 0, auto clear */
-       pac207_write_reg(gspca_dev, 0x1c, 0x01); /* not documented */
-       msleep(10);
-       pac207_write_reg(gspca_dev, 0x40, 0x01); /* Start ISO pipe */
-
-       sd->sof_read = 0;
-       sd->autogain_ignore_frames = 0;
-       atomic_set(&sd->avg_lum, -1);
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       pac207_write_reg(gspca_dev, 0x40, 0x00); /* Stop ISO pipe */
-       pac207_write_reg(gspca_dev, 0x41, 0x00); /* Turn of LED */
-       pac207_write_reg(gspca_dev, 0x0f, 0x00); /* Power Control */
-}
-
-
-static void pac207_do_auto_gain(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int avg_lum = atomic_read(&sd->avg_lum);
-
-       if (avg_lum == -1)
-               return;
-
-       if (sd->autogain_ignore_frames > 0)
-               sd->autogain_ignore_frames--;
-       else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
-                       90, PAC207_AUTOGAIN_DEADZONE))
-               sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,
-                       int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       unsigned char *sof;
-
-       sof = pac_find_sof(&sd->sof_read, data, len);
-       if (sof) {
-               int n;
-
-               /* finish decoding current frame */
-               n = sof - data;
-               if (n > sizeof pac_sof_marker)
-                       n -= sizeof pac_sof_marker;
-               else
-                       n = 0;
-               gspca_frame_add(gspca_dev, LAST_PACKET,
-                               data, n);
-               sd->header_read = 0;
-               gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
-               len -= sof - data;
-               data = sof;
-       }
-       if (sd->header_read < 11) {
-               int needed;
-
-               /* get average lumination from frame header (byte 5) */
-               if (sd->header_read < 5) {
-                       needed = 5 - sd->header_read;
-                       if (len >= needed)
-                               atomic_set(&sd->avg_lum, data[needed - 1]);
-               }
-               /* skip the rest of the header */
-               needed = 11 - sd->header_read;
-               if (len <= needed) {
-                       sd->header_read += len;
-                       return;
-               }
-               data += needed;
-               len -= needed;
-               sd->header_read = 11;
-       }
-
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,               /* interrupt packet data */
-                       int len)                /* interrput packet length */
-{
-       int ret = -EINVAL;
-
-       if (len == 2 && data[0] == 0x5a && data[1] == 0x5a) {
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
-               input_sync(gspca_dev->input_dev);
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
-               input_sync(gspca_dev->input_dev);
-               ret = 0;
-       }
-
-       return ret;
-}
-#endif
-
-/* 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,
-       .stopN = sd_stopN,
-       .dq_callback = pac207_do_auto_gain,
-       .pkt_scan = sd_pkt_scan,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .int_pkt_scan = sd_int_pkt_scan,
-#endif
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x041e, 0x4028)},
-       {USB_DEVICE(0x093a, 0x2460)},
-       {USB_DEVICE(0x093a, 0x2461)},
-       {USB_DEVICE(0x093a, 0x2463)},
-       {USB_DEVICE(0x093a, 0x2464)},
-       {USB_DEVICE(0x093a, 0x2468)},
-       {USB_DEVICE(0x093a, 0x2470)},
-       {USB_DEVICE(0x093a, 0x2471)},
-       {USB_DEVICE(0x093a, 0x2472)},
-       {USB_DEVICE(0x093a, 0x2474)},
-       {USB_DEVICE(0x093a, 0x2476)},
-       {USB_DEVICE(0x145f, 0x013a)},
-       {USB_DEVICE(0x2001, 0xf115)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c
deleted file mode 100644 (file)
index 4877f7a..0000000
+++ /dev/null
@@ -1,932 +0,0 @@
-/*
- * Pixart PAC7302 driver
- *
- * Copyright (C) 2008-2012 Jean-Francois Moine <http://moinejf.free.fr>
- * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
- *
- * Separated from Pixart PAC7311 library by Márton Németh
- * Camera button input handling by Márton Németh <nm127@freemail.hu>
- * Copyright (C) 2009-2010 Márton Németh <nm127@freemail.hu>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * Some documentation about various registers as determined by trial and error.
- *
- * Register page 1:
- *
- * Address     Description
- * 0x78                Global control, bit 6 controls the LED (inverted)
- * 0x80                Compression balance, 2 interesting settings:
- *             0x0f Default
- *             0x50 Values >= this switch the camera to a lower compression,
- *                  using the same table for both luminance and chrominance.
- *                  This gives a sharper picture. Only usable when running
- *                  at < 15 fps! Note currently the driver does not use this
- *                  as the quality gain is small and the generated JPG-s are
- *                  only understood by v4l-utils >= 0.8.9
- *
- * Register page 3:
- *
- * Address     Description
- * 0x02                Clock divider 3-63, fps = 90 / val. Must be a multiple of 3 on
- *             the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
- * 0x03                Variable framerate ctrl reg2==3: 0 -> ~30 fps, 255 -> ~22fps
- * 0x04                Another var framerate ctrl reg2==3, reg3==0: 0 -> ~30 fps,
- *             63 -> ~27 fps, the 2 msb's must always be 1 !!
- * 0x05                Another var framerate ctrl reg2==3, reg3==0, reg4==0xc0:
- *             1 -> ~30 fps, 2 -> ~20 fps
- * 0x0e                Exposure bits 0-7, 0-448, 0 = use full frame time
- * 0x0f                Exposure bit 8, 0-448, 448 = no exposure at all
- * 0x10                Gain 0-31
- * 0x12                Another gain 0-31, unlike 0x10 this one seems to start with an
- *             amplification value of 1 rather then 0 at its lowest setting
- * 0x21                Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
- * 0x80                Another framerate control, best left at 1, moving it from 1 to
- *             2 causes the framerate to become 3/4th of what it was, and
- *             also seems to cause pixel averaging, resulting in an effective
- *             resolution of 320x240 and thus a much blockier image
- *
- * The registers are accessed in the following functions:
- *
- * Page | Register   | Function
- * -----+------------+---------------------------------------------------
- *  0   | 0x0f..0x20 | setcolors()
- *  0   | 0xa2..0xab | setbrightcont()
- *  0   | 0xc5       | setredbalance()
- *  0   | 0xc6       | setwhitebalance()
- *  0   | 0xc7       | setbluebalance()
- *  0   | 0xdc       | setbrightcont(), setcolors()
- *  3   | 0x02       | setexposure()
- *  3   | 0x10, 0x12 | setgain()
- *  3   | 0x11       | setcolors(), setgain(), setexposure(), sethvflip()
- *  3   | 0x21       | sethvflip()
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/input.h>
-#include <media/v4l2-chip-ident.h>
-#include "gspca.h"
-/* Include pac common sof detection functions */
-#include "pac_common.h"
-
-#define PAC7302_GAIN_DEFAULT      15
-#define PAC7302_GAIN_KNEE         42
-#define PAC7302_EXPOSURE_DEFAULT  66 /* 33 ms / 30 fps */
-#define PAC7302_EXPOSURE_KNEE    133 /* 66 ms / 15 fps */
-
-MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
-               "Thomas Kaiser thomas@kaiser-linux.li");
-MODULE_DESCRIPTION("Pixart PAC7302");
-MODULE_LICENSE("GPL");
-
-struct sd {
-       struct gspca_dev gspca_dev;             /* !! must be the first item */
-
-       struct { /* brightness / contrast cluster */
-               struct v4l2_ctrl *brightness;
-               struct v4l2_ctrl *contrast;
-       };
-       struct v4l2_ctrl *saturation;
-       struct v4l2_ctrl *white_balance;
-       struct v4l2_ctrl *red_balance;
-       struct v4l2_ctrl *blue_balance;
-       struct { /* flip cluster */
-               struct v4l2_ctrl *hflip;
-               struct v4l2_ctrl *vflip;
-       };
-       u8 flags;
-#define FL_HFLIP 0x01          /* mirrored by default */
-#define FL_VFLIP 0x02          /* vertical flipped by default */
-
-       u8 sof_read;
-       s8 autogain_ignore_frames;
-
-       atomic_t avg_lum;
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-       },
-};
-
-#define LOAD_PAGE3             255
-#define END_OF_SEQUENCE                0
-
-static const u8 init_7302[] = {
-/*     index,value */
-       0xff, 0x01,             /* page 1 */
-       0x78, 0x00,             /* deactivate */
-       0xff, 0x01,
-       0x78, 0x40,             /* led off */
-};
-static const u8 start_7302[] = {
-/*     index, len, [value]* */
-       0xff, 1,        0x00,           /* page 0 */
-       0x00, 12,       0x01, 0x40, 0x40, 0x40, 0x01, 0xe0, 0x02, 0x80,
-                       0x00, 0x00, 0x00, 0x00,
-       0x0d, 24,       0x03, 0x01, 0x00, 0xb5, 0x07, 0xcb, 0x00, 0x00,
-                       0x07, 0xc8, 0x00, 0xea, 0x07, 0xcf, 0x07, 0xf7,
-                       0x07, 0x7e, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x11,
-       0x26, 2,        0xaa, 0xaa,
-       0x2e, 1,        0x31,
-       0x38, 1,        0x01,
-       0x3a, 3,        0x14, 0xff, 0x5a,
-       0x43, 11,       0x00, 0x0a, 0x18, 0x11, 0x01, 0x2c, 0x88, 0x11,
-                       0x00, 0x54, 0x11,
-       0x55, 1,        0x00,
-       0x62, 4,        0x10, 0x1e, 0x1e, 0x18,
-       0x6b, 1,        0x00,
-       0x6e, 3,        0x08, 0x06, 0x00,
-       0x72, 3,        0x00, 0xff, 0x00,
-       0x7d, 23,       0x01, 0x01, 0x58, 0x46, 0x50, 0x3c, 0x50, 0x3c,
-                       0x54, 0x46, 0x54, 0x56, 0x52, 0x50, 0x52, 0x50,
-                       0x56, 0x64, 0xa4, 0x00, 0xda, 0x00, 0x00,
-       0xa2, 10,       0x22, 0x2c, 0x3c, 0x54, 0x69, 0x7c, 0x9c, 0xb9,
-                       0xd2, 0xeb,
-       0xaf, 1,        0x02,
-       0xb5, 2,        0x08, 0x08,
-       0xb8, 2,        0x08, 0x88,
-       0xc4, 4,        0xae, 0x01, 0x04, 0x01,
-       0xcc, 1,        0x00,
-       0xd1, 11,       0x01, 0x30, 0x49, 0x5e, 0x6f, 0x7f, 0x8e, 0xa9,
-                       0xc1, 0xd7, 0xec,
-       0xdc, 1,        0x01,
-       0xff, 1,        0x01,           /* page 1 */
-       0x12, 3,        0x02, 0x00, 0x01,
-       0x3e, 2,        0x00, 0x00,
-       0x76, 5,        0x01, 0x20, 0x40, 0x00, 0xf2,
-       0x7c, 1,        0x00,
-       0x7f, 10,       0x4b, 0x0f, 0x01, 0x2c, 0x02, 0x58, 0x03, 0x20,
-                       0x02, 0x00,
-       0x96, 5,        0x01, 0x10, 0x04, 0x01, 0x04,
-       0xc8, 14,       0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
-                       0x07, 0x00, 0x01, 0x07, 0x04, 0x01,
-       0xd8, 1,        0x01,
-       0xdb, 2,        0x00, 0x01,
-       0xde, 7,        0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x00,
-       0xe6, 4,        0x00, 0x00, 0x00, 0x01,
-       0xeb, 1,        0x00,
-       0xff, 1,        0x02,           /* page 2 */
-       0x22, 1,        0x00,
-       0xff, 1,        0x03,           /* page 3 */
-       0, LOAD_PAGE3,                  /* load the page 3 */
-       0x11, 1,        0x01,
-       0xff, 1,        0x02,           /* page 2 */
-       0x13, 1,        0x00,
-       0x22, 4,        0x1f, 0xa4, 0xf0, 0x96,
-       0x27, 2,        0x14, 0x0c,
-       0x2a, 5,        0xc8, 0x00, 0x18, 0x12, 0x22,
-       0x64, 8,        0x00, 0x00, 0xf0, 0x01, 0x14, 0x44, 0x44, 0x44,
-       0x6e, 1,        0x08,
-       0xff, 1,        0x01,           /* page 1 */
-       0x78, 1,        0x00,
-       0, END_OF_SEQUENCE              /* end of sequence */
-};
-
-#define SKIP           0xaa
-/* page 3 - the value SKIP says skip the index - see reg_w_page() */
-static const u8 page3_7302[] = {
-       0x90, 0x40, 0x03, 0x00, 0xc0, 0x01, 0x14, 0x16,
-       0x14, 0x12, 0x00, 0x00, 0x00, 0x02, 0x33, 0x00,
-       0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x47, 0x01, 0xb3, 0x01, 0x00,
-       0x00, 0x08, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x21,
-       0x00, 0x00, 0x00, 0x54, 0xf4, 0x02, 0x52, 0x54,
-       0xa4, 0xb8, 0xe0, 0x2a, 0xf6, 0x00, 0x00, 0x00,
-       0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0xfc, 0x00, 0xf2, 0x1f, 0x04, 0x00, 0x00,
-       SKIP, 0x00, 0x00, 0xc0, 0xc0, 0x10, 0x00, 0x00,
-       0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x40, 0xff, 0x03, 0x19, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0xc8, 0xc8,
-       0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50,
-       0x08, 0x10, 0x24, 0x40, 0x00, 0x00, 0x00, 0x00,
-       0x01, 0x00, 0x02, 0x47, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x02, 0xfa, 0x00, 0x64, 0x5a, 0x28, 0x00,
-       0x00
-};
-
-static void reg_w_buf(struct gspca_dev *gspca_dev,
-               u8 index,
-                 const u8 *buffer, int len)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       memcpy(gspca_dev->usb_buf, buffer, len);
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0,              /* request */
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,              /* value */
-                       index, gspca_dev->usb_buf, len,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_w_buf failed i: %02x error %d\n",
-                      index, ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-
-static void reg_w(struct gspca_dev *gspca_dev,
-               u8 index,
-               u8 value)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       gspca_dev->usb_buf[0] = value;
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0,                      /* request */
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0, index, gspca_dev->usb_buf, 1,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_w() failed i: %02x v: %02x error %d\n",
-                      index, value, ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void reg_w_seq(struct gspca_dev *gspca_dev,
-               const u8 *seq, int len)
-{
-       while (--len >= 0) {
-               reg_w(gspca_dev, seq[0], seq[1]);
-               seq += 2;
-       }
-}
-
-/* load the beginning of a page */
-static void reg_w_page(struct gspca_dev *gspca_dev,
-                       const u8 *page, int len)
-{
-       int index;
-       int ret = 0;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       for (index = 0; index < len; index++) {
-               if (page[index] == SKIP)                /* skip this index */
-                       continue;
-               gspca_dev->usb_buf[0] = page[index];
-               ret = usb_control_msg(gspca_dev->dev,
-                               usb_sndctrlpipe(gspca_dev->dev, 0),
-                               0,                      /* request */
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                               0, index, gspca_dev->usb_buf, 1,
-                               500);
-               if (ret < 0) {
-                       pr_err("reg_w_page() failed i: %02x v: %02x error %d\n",
-                              index, page[index], ret);
-                       gspca_dev->usb_err = ret;
-                       break;
-               }
-       }
-}
-
-/* output a variable sequence */
-static void reg_w_var(struct gspca_dev *gspca_dev,
-                       const u8 *seq,
-                       const u8 *page3, unsigned int page3_len)
-{
-       int index, len;
-
-       for (;;) {
-               index = *seq++;
-               len = *seq++;
-               switch (len) {
-               case END_OF_SEQUENCE:
-                       return;
-               case LOAD_PAGE3:
-                       reg_w_page(gspca_dev, page3, page3_len);
-                       break;
-               default:
-#ifdef GSPCA_DEBUG
-                       if (len > USB_BUF_SZ) {
-                               PDEBUG(D_ERR|D_STREAM,
-                                       "Incorrect variable sequence");
-                               return;
-                       }
-#endif
-                       while (len > 0) {
-                               if (len < 8) {
-                                       reg_w_buf(gspca_dev,
-                                               index, seq, len);
-                                       seq += len;
-                                       break;
-                               }
-                               reg_w_buf(gspca_dev, index, seq, 8);
-                               seq += 8;
-                               index += 8;
-                               len -= 8;
-                       }
-               }
-       }
-       /* not reached */
-}
-
-/* this function is called at probe time for pac7302 */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-
-       cam = &gspca_dev->cam;
-
-       cam->cam_mode = vga_mode;       /* only 640x480 */
-       cam->nmodes = ARRAY_SIZE(vga_mode);
-
-       sd->flags = id->driver_info;
-       return 0;
-}
-
-static void setbrightcont(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i, v;
-       static const u8 max[10] =
-               {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
-                0xd4, 0xec};
-       static const u8 delta[10] =
-               {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
-                0x11, 0x0b};
-
-       reg_w(gspca_dev, 0xff, 0x00);           /* page 0 */
-       for (i = 0; i < 10; i++) {
-               v = max[i];
-               v += (sd->brightness->val - sd->brightness->maximum)
-                       * 150 / sd->brightness->maximum; /* 200 ? */
-               v -= delta[i] * sd->contrast->val / sd->contrast->maximum;
-               if (v < 0)
-                       v = 0;
-               else if (v > 0xff)
-                       v = 0xff;
-               reg_w(gspca_dev, 0xa2 + i, v);
-       }
-       reg_w(gspca_dev, 0xdc, 0x01);
-}
-
-static void setcolors(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i, v;
-       static const int a[9] =
-               {217, -212, 0, -101, 170, -67, -38, -315, 355};
-       static const int b[9] =
-               {19, 106, 0, 19, 106, 1, 19, 106, 1};
-
-       reg_w(gspca_dev, 0xff, 0x03);                   /* page 3 */
-       reg_w(gspca_dev, 0x11, 0x01);
-       reg_w(gspca_dev, 0xff, 0x00);                   /* page 0 */
-       for (i = 0; i < 9; i++) {
-               v = a[i] * sd->saturation->val / sd->saturation->maximum;
-               v += b[i];
-               reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
-               reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
-       }
-       reg_w(gspca_dev, 0xdc, 0x01);
-}
-
-static void setwhitebalance(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       reg_w(gspca_dev, 0xff, 0x00);           /* page 0 */
-       reg_w(gspca_dev, 0xc6, sd->white_balance->val);
-
-       reg_w(gspca_dev, 0xdc, 0x01);
-}
-
-static void setredbalance(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       reg_w(gspca_dev, 0xff, 0x00);           /* page 0 */
-       reg_w(gspca_dev, 0xc5, sd->red_balance->val);
-
-       reg_w(gspca_dev, 0xdc, 0x01);
-}
-
-static void setbluebalance(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       reg_w(gspca_dev, 0xff, 0x00);                   /* page 0 */
-       reg_w(gspca_dev, 0xc7, sd->blue_balance->val);
-
-       reg_w(gspca_dev, 0xdc, 0x01);
-}
-
-static void setgain(struct gspca_dev *gspca_dev)
-{
-       u8 reg10, reg12;
-
-       if (gspca_dev->gain->val < 32) {
-               reg10 = gspca_dev->gain->val;
-               reg12 = 0;
-       } else {
-               reg10 = 31;
-               reg12 = gspca_dev->gain->val - 31;
-       }
-
-       reg_w(gspca_dev, 0xff, 0x03);                   /* page 3 */
-       reg_w(gspca_dev, 0x10, reg10);
-       reg_w(gspca_dev, 0x12, reg12);
-
-       /* load registers to sensor (Bit 0, auto clear) */
-       reg_w(gspca_dev, 0x11, 0x01);
-}
-
-static void setexposure(struct gspca_dev *gspca_dev)
-{
-       u8 clockdiv;
-       u16 exposure;
-
-       /*
-        * Register 2 of frame 3 contains the clock divider configuring the
-        * no fps according to the formula: 90 / reg. sd->exposure is the
-        * desired exposure time in 0.5 ms.
-        */
-       clockdiv = (90 * gspca_dev->exposure->val + 1999) / 2000;
-
-       /*
-        * Note clockdiv = 3 also works, but when running at 30 fps, depending
-        * on the scene being recorded, the camera switches to another
-        * quantization table for certain JPEG blocks, and we don't know how
-        * to decompress these blocks. So we cap the framerate at 15 fps.
-        */
-       if (clockdiv < 6)
-               clockdiv = 6;
-       else if (clockdiv > 63)
-               clockdiv = 63;
-
-       /*
-        * Register 2 MUST be a multiple of 3, except when between 6 and 12?
-        * Always round up, otherwise we cannot get the desired frametime
-        * using the partial frame time exposure control.
-        */
-       if (clockdiv < 6 || clockdiv > 12)
-               clockdiv = ((clockdiv + 2) / 3) * 3;
-
-       /*
-        * frame exposure time in ms = 1000 * clockdiv / 90    ->
-        * exposure = (sd->exposure / 2) * 448 / (1000 * clockdiv / 90)
-        */
-       exposure = (gspca_dev->exposure->val * 45 * 448) / (1000 * clockdiv);
-       /* 0 = use full frametime, 448 = no exposure, reverse it */
-       exposure = 448 - exposure;
-
-       reg_w(gspca_dev, 0xff, 0x03);                   /* page 3 */
-       reg_w(gspca_dev, 0x02, clockdiv);
-       reg_w(gspca_dev, 0x0e, exposure & 0xff);
-       reg_w(gspca_dev, 0x0f, exposure >> 8);
-
-       /* load registers to sensor (Bit 0, auto clear) */
-       reg_w(gspca_dev, 0x11, 0x01);
-}
-
-static void sethvflip(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 data, hflip, vflip;
-
-       hflip = sd->hflip->val;
-       if (sd->flags & FL_HFLIP)
-               hflip = !hflip;
-       vflip = sd->vflip->val;
-       if (sd->flags & FL_VFLIP)
-               vflip = !vflip;
-
-       reg_w(gspca_dev, 0xff, 0x03);                   /* page 3 */
-       data = (hflip ? 0x08 : 0x00) | (vflip ? 0x04 : 0x00);
-       reg_w(gspca_dev, 0x21, data);
-
-       /* load registers to sensor (Bit 0, auto clear) */
-       reg_w(gspca_dev, 0x11, 0x01);
-}
-
-/* this function is called at probe and resume time for pac7302 */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       reg_w_seq(gspca_dev, init_7302, sizeof(init_7302)/2);
-       return gspca_dev->usb_err;
-}
-
-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 (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
-               /* when switching to autogain set defaults to make sure
-                  we are on a valid point of the autogain gain /
-                  exposure knee graph, and give this change time to
-                  take effect before doing autogain. */
-               gspca_dev->exposure->val    = PAC7302_EXPOSURE_DEFAULT;
-               gspca_dev->gain->val        = PAC7302_GAIN_DEFAULT;
-               sd->autogain_ignore_frames  = PAC_AUTOGAIN_IGNORE_FRAMES;
-       }
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               setbrightcont(gspca_dev);
-               break;
-       case V4L2_CID_SATURATION:
-               setcolors(gspca_dev);
-               break;
-       case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
-               setwhitebalance(gspca_dev);
-               break;
-       case V4L2_CID_RED_BALANCE:
-               setredbalance(gspca_dev);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               setbluebalance(gspca_dev);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
-                       setexposure(gspca_dev);
-               if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
-                       setgain(gspca_dev);
-               break;
-       case V4L2_CID_HFLIP:
-               sethvflip(gspca_dev);
-               break;
-       default:
-               return -EINVAL;
-       }
-       return gspca_dev->usb_err;
-}
-
-static const struct v4l2_ctrl_ops sd_ctrl_ops = {
-       .s_ctrl = sd_s_ctrl,
-};
-
-/* this function is called at probe time */
-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, 11);
-
-       sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_BRIGHTNESS, 0, 32, 1, 16);
-       sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_CONTRAST, 0, 255, 1, 127);
-
-       sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_SATURATION, 0, 255, 1, 127);
-       sd->white_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_WHITE_BALANCE_TEMPERATURE,
-                                       0, 255, 1, 4);
-       sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_RED_BALANCE, 0, 3, 1, 1);
-       sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_RED_BALANCE, 0, 3, 1, 1);
-
-       gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-       gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_EXPOSURE, 0, 1023, 1,
-                                       PAC7302_EXPOSURE_DEFAULT);
-       gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_GAIN, 0, 62, 1,
-                                       PAC7302_GAIN_DEFAULT);
-
-       sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-               V4L2_CID_HFLIP, 0, 1, 1, 0);
-       sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-               V4L2_CID_VFLIP, 0, 1, 1, 0);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-
-       v4l2_ctrl_cluster(2, &sd->brightness);
-       v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
-       v4l2_ctrl_cluster(2, &sd->hflip);
-       return 0;
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       reg_w_var(gspca_dev, start_7302,
-               page3_7302, sizeof(page3_7302));
-       setbrightcont(gspca_dev);
-       setcolors(gspca_dev);
-       setwhitebalance(gspca_dev);
-       setredbalance(gspca_dev);
-       setbluebalance(gspca_dev);
-       setexposure(gspca_dev);
-       setgain(gspca_dev);
-       sethvflip(gspca_dev);
-
-       sd->sof_read = 0;
-       sd->autogain_ignore_frames = 0;
-       atomic_set(&sd->avg_lum, 270 + sd->brightness->val);
-
-       /* start stream */
-       reg_w(gspca_dev, 0xff, 0x01);
-       reg_w(gspca_dev, 0x78, 0x01);
-
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-
-       /* stop stream */
-       reg_w(gspca_dev, 0xff, 0x01);
-       reg_w(gspca_dev, 0x78, 0x00);
-}
-
-/* called on streamoff with alt 0 and on disconnect for pac7302 */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       if (!gspca_dev->present)
-               return;
-       reg_w(gspca_dev, 0xff, 0x01);
-       reg_w(gspca_dev, 0x78, 0x40);
-}
-
-static void do_autogain(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int avg_lum = atomic_read(&sd->avg_lum);
-       int desired_lum;
-       const int deadzone = 30;
-
-       if (sd->autogain_ignore_frames < 0)
-               return;
-
-       if (sd->autogain_ignore_frames > 0) {
-               sd->autogain_ignore_frames--;
-       } else {
-               desired_lum = 270 + sd->brightness->val;
-
-               if (gspca_expo_autogain(gspca_dev, avg_lum, desired_lum,
-                                       deadzone, PAC7302_GAIN_KNEE,
-                                       PAC7302_EXPOSURE_KNEE))
-                       sd->autogain_ignore_frames =
-                                               PAC_AUTOGAIN_IGNORE_FRAMES;
-       }
-}
-
-/* JPEG header */
-static const u8 jpeg_header[] = {
-       0xff, 0xd8,     /* SOI: Start of Image */
-
-       0xff, 0xc0,     /* SOF0: Start of Frame (Baseline DCT) */
-       0x00, 0x11,     /* length = 17 bytes (including this length field) */
-       0x08,           /* Precision: 8 */
-       0x02, 0x80,     /* height = 640 (image rotated) */
-       0x01, 0xe0,     /* width = 480 */
-       0x03,           /* Number of image components: 3 */
-       0x01, 0x21, 0x00, /* ID=1, Subsampling 1x1, Quantization table: 0 */
-       0x02, 0x11, 0x01, /* ID=2, Subsampling 2x1, Quantization table: 1 */
-       0x03, 0x11, 0x01, /* ID=3, Subsampling 2x1, Quantization table: 1 */
-
-       0xff, 0xda,     /* SOS: Start Of Scan */
-       0x00, 0x0c,     /* length = 12 bytes (including this length field) */
-       0x03,           /* number of components: 3 */
-       0x01, 0x00,     /* selector 1, table 0x00 */
-       0x02, 0x11,     /* selector 2, table 0x11 */
-       0x03, 0x11,     /* selector 3, table 0x11 */
-       0x00, 0x3f,     /* Spectral selection: 0 .. 63 */
-       0x00            /* Successive approximation: 0 */
-};
-
-/* this function is run at interrupt level */
-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;
-       u8 *image;
-       u8 *sof;
-
-       sof = pac_find_sof(&sd->sof_read, data, len);
-       if (sof) {
-               int n, lum_offset, footer_length;
-
-               /*
-                * 6 bytes after the FF D9 EOF marker a number of lumination
-                * bytes are send corresponding to different parts of the
-                * image, the 14th and 15th byte after the EOF seem to
-                * correspond to the center of the image.
-                */
-               lum_offset = 61 + sizeof pac_sof_marker;
-               footer_length = 74;
-
-               /* Finish decoding current frame */
-               n = (sof - data) - (footer_length + sizeof pac_sof_marker);
-               if (n < 0) {
-                       gspca_dev->image_len += n;
-                       n = 0;
-               } else {
-                       gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
-               }
-
-               image = gspca_dev->image;
-               if (image != NULL
-                && image[gspca_dev->image_len - 2] == 0xff
-                && image[gspca_dev->image_len - 1] == 0xd9)
-                       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-
-               n = sof - data;
-               len -= n;
-               data = sof;
-
-               /* Get average lumination */
-               if (gspca_dev->last_packet_type == LAST_PACKET &&
-                               n >= lum_offset)
-                       atomic_set(&sd->avg_lum, data[-lum_offset] +
-                                               data[-lum_offset + 1]);
-
-               /* Start the new frame with the jpeg header */
-               /* The PAC7302 has the image rotated 90 degrees */
-               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                               jpeg_header, sizeof jpeg_header);
-       }
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
-                       struct v4l2_dbg_register *reg)
-{
-       u8 index;
-       u8 value;
-
-       /*
-        * reg->reg: bit0..15: reserved for register index (wIndex is 16bit
-        *                     long on the USB bus)
-        */
-       if (reg->match.type == V4L2_CHIP_MATCH_HOST &&
-           reg->match.addr == 0 &&
-           (reg->reg < 0x000000ff) &&
-           (reg->val <= 0x000000ff)
-       ) {
-               /* Currently writing to page 0 is only supported. */
-               /* reg_w() only supports 8bit index */
-               index = reg->reg;
-               value = reg->val;
-
-               /*
-                * Note that there shall be no access to other page
-                * by any other function between the page switch and
-                * the actual register write.
-                */
-               reg_w(gspca_dev, 0xff, 0x00);           /* page 0 */
-               reg_w(gspca_dev, index, value);
-
-               reg_w(gspca_dev, 0xdc, 0x01);
-       }
-       return gspca_dev->usb_err;
-}
-
-static int sd_chip_ident(struct gspca_dev *gspca_dev,
-                       struct v4l2_dbg_chip_ident *chip)
-{
-       int ret = -EINVAL;
-
-       if (chip->match.type == V4L2_CHIP_MATCH_HOST &&
-           chip->match.addr == 0) {
-               chip->revision = 0;
-               chip->ident = V4L2_IDENT_UNKNOWN;
-               ret = 0;
-       }
-       return ret;
-}
-#endif
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,               /* interrupt packet data */
-                       int len)                /* interrput packet length */
-{
-       int ret = -EINVAL;
-       u8 data0, data1;
-
-       if (len == 2) {
-               data0 = data[0];
-               data1 = data[1];
-               if ((data0 == 0x00 && data1 == 0x11) ||
-                   (data0 == 0x22 && data1 == 0x33) ||
-                   (data0 == 0x44 && data1 == 0x55) ||
-                   (data0 == 0x66 && data1 == 0x77) ||
-                   (data0 == 0x88 && data1 == 0x99) ||
-                   (data0 == 0xaa && data1 == 0xbb) ||
-                   (data0 == 0xcc && data1 == 0xdd) ||
-                   (data0 == 0xee && data1 == 0xff)) {
-                       input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
-                       input_sync(gspca_dev->input_dev);
-                       input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
-                       input_sync(gspca_dev->input_dev);
-                       ret = 0;
-               }
-       }
-
-       return ret;
-}
-#endif
-
-/* sub-driver description for pac7302 */
-static const struct sd_desc sd_desc = {
-       .name = KBUILD_MODNAME,
-       .config = sd_config,
-       .init = sd_init,
-       .init_controls = sd_init_controls,
-       .start = sd_start,
-       .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .pkt_scan = sd_pkt_scan,
-       .dq_callback = do_autogain,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .set_register = sd_dbg_s_register,
-       .get_chip_ident = sd_chip_ident,
-#endif
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .int_pkt_scan = sd_int_pkt_scan,
-#endif
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x06f8, 0x3009)},
-       {USB_DEVICE(0x06f8, 0x301b)},
-       {USB_DEVICE(0x093a, 0x2620)},
-       {USB_DEVICE(0x093a, 0x2621)},
-       {USB_DEVICE(0x093a, 0x2622), .driver_info = FL_VFLIP},
-       {USB_DEVICE(0x093a, 0x2624), .driver_info = FL_VFLIP},
-       {USB_DEVICE(0x093a, 0x2625)},
-       {USB_DEVICE(0x093a, 0x2626)},
-       {USB_DEVICE(0x093a, 0x2627), .driver_info = FL_VFLIP},
-       {USB_DEVICE(0x093a, 0x2628)},
-       {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP},
-       {USB_DEVICE(0x093a, 0x262a)},
-       {USB_DEVICE(0x093a, 0x262c)},
-       {USB_DEVICE(0x145f, 0x013c)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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 = KBUILD_MODNAME,
-       .id_table = device_table,
-       .probe = sd_probe,
-       .disconnect = gspca_disconnect,
-#ifdef CONFIG_PM
-       .suspend = gspca_suspend,
-       .resume = gspca_resume,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/pac7311.c b/drivers/media/video/gspca/pac7311.c
deleted file mode 100644 (file)
index ba3558d..0000000
+++ /dev/null
@@ -1,701 +0,0 @@
-/*
- *             Pixart PAC7311 library
- *             Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
- *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* Some documentation about various registers as determined by trial and error.
- *
- * Register page 1:
- *
- * Address     Description
- * 0x08                Unknown compressor related, must always be 8 except when not
- *             in 640x480 resolution and page 4 reg 2 <= 3 then set it to 9 !
- * 0x1b                Auto white balance related, bit 0 is AWB enable (inverted)
- *             bits 345 seem to toggle per color gains on/off (inverted)
- * 0x78                Global control, bit 6 controls the LED (inverted)
- * 0x80                Compression balance, interesting settings:
- *             0x01 Use this to allow the camera to switch to higher compr.
- *                  on the fly. Needed to stay within bandwidth @ 640x480@30
- *             0x1c From usb captures under Windows for 640x480
- *             0x2a Values >= this switch the camera to a lower compression,
- *                  using the same table for both luminance and chrominance.
- *                  This gives a sharper picture. Usable only at 640x480@ <
- *                  15 fps or 320x240 / 160x120. Note currently the driver
- *                  does not use this as the quality gain is small and the
- *                  generated JPG-s are only understood by v4l-utils >= 0.8.9
- *             0x3f From usb captures under Windows for 320x240
- *             0x69 From usb captures under Windows for 160x120
- *
- * Register page 4:
- *
- * Address     Description
- * 0x02                Clock divider 2-63, fps =~ 60 / val. Must be a multiple of 3 on
- *             the 7302, so one of 3, 6, 9, ..., except when between 6 and 12?
- * 0x0f                Master gain 1-245, low value = high gain
- * 0x10                Another gain 0-15, limited influence (1-2x gain I guess)
- * 0x21                Bitfield: 0-1 unused, 2-3 vflip/hflip, 4-5 unknown, 6-7 unused
- *             Note setting vflip disabled leads to a much lower image quality,
- *             so we always vflip, and tell userspace to flip it back
- * 0x27                Seems to toggle various gains on / off, Setting bit 7 seems to
- *             completely disable the analog amplification block. Set to 0x68
- *             for max gain, 0x14 for minimal gain.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "pac7311"
-
-#include <linux/input.h>
-#include "gspca.h"
-/* Include pac common sof detection functions */
-#include "pac_common.h"
-
-#define PAC7311_GAIN_DEFAULT     122
-#define PAC7311_EXPOSURE_DEFAULT   3 /* 20 fps, avoid using high compr. */
-
-MODULE_AUTHOR("Thomas Kaiser thomas@kaiser-linux.li");
-MODULE_DESCRIPTION("Pixart PAC7311");
-MODULE_LICENSE("GPL");
-
-struct sd {
-       struct gspca_dev gspca_dev;             /* !! must be the first item */
-
-       struct v4l2_ctrl *contrast;
-       struct v4l2_ctrl *hflip;
-
-       u8 sof_read;
-       u8 autogain_ignore_frames;
-
-       atomic_t avg_lum;
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {160, 120, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 2},
-       {320, 240, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_PJPG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-
-#define LOAD_PAGE4             254
-#define END_OF_SEQUENCE                0
-
-static const __u8 init_7311[] = {
-       0xff, 0x01,
-       0x78, 0x40,     /* Bit_0=start stream, Bit_6=LED */
-       0x78, 0x40,     /* Bit_0=start stream, Bit_6=LED */
-       0x78, 0x44,     /* Bit_0=start stream, Bit_6=LED */
-       0xff, 0x04,
-       0x27, 0x80,
-       0x28, 0xca,
-       0x29, 0x53,
-       0x2a, 0x0e,
-       0xff, 0x01,
-       0x3e, 0x20,
-};
-
-static const __u8 start_7311[] = {
-/*     index, len, [value]* */
-       0xff, 1,        0x01,           /* page 1 */
-       0x02, 43,       0x48, 0x0a, 0x40, 0x08, 0x00, 0x00, 0x08, 0x00,
-                       0x06, 0xff, 0x11, 0xff, 0x5a, 0x30, 0x90, 0x4c,
-                       0x00, 0x07, 0x00, 0x0a, 0x10, 0x00, 0xa0, 0x10,
-                       0x02, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x00,
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                       0x00, 0x00, 0x00,
-       0x3e, 42,       0x00, 0x00, 0x78, 0x52, 0x4a, 0x52, 0x78, 0x6e,
-                       0x48, 0x46, 0x48, 0x6e, 0x5f, 0x49, 0x42, 0x49,
-                       0x5f, 0x5f, 0x49, 0x42, 0x49, 0x5f, 0x6e, 0x48,
-                       0x46, 0x48, 0x6e, 0x78, 0x52, 0x4a, 0x52, 0x78,
-                       0x00, 0x00, 0x09, 0x1b, 0x34, 0x49, 0x5c, 0x9b,
-                       0xd0, 0xff,
-       0x78, 6,        0x44, 0x00, 0xf2, 0x01, 0x01, 0x80,
-       0x7f, 18,       0x2a, 0x1c, 0x00, 0xc8, 0x02, 0x58, 0x03, 0x84,
-                       0x12, 0x00, 0x1a, 0x04, 0x08, 0x0c, 0x10, 0x14,
-                       0x18, 0x20,
-       0x96, 3,        0x01, 0x08, 0x04,
-       0xa0, 4,        0x44, 0x44, 0x44, 0x04,
-       0xf0, 13,       0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x20, 0x00,
-                       0x3f, 0x00, 0x0a, 0x01, 0x00,
-       0xff, 1,        0x04,           /* page 4 */
-       0, LOAD_PAGE4,                  /* load the page 4 */
-       0x11, 1,        0x01,
-       0, END_OF_SEQUENCE              /* end of sequence */
-};
-
-#define SKIP           0xaa
-/* page 4 - the value SKIP says skip the index - see reg_w_page() */
-static const __u8 page4_7311[] = {
-       SKIP, SKIP, 0x04, 0x54, 0x07, 0x2b, 0x09, 0x0f,
-       0x09, 0x00, SKIP, SKIP, 0x07, 0x00, 0x00, 0x62,
-       0x08, SKIP, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x03, 0xa0, 0x01, 0xf4, SKIP,
-       SKIP, 0x00, 0x08, SKIP, 0x03, SKIP, 0x00, 0x68,
-       0xca, 0x10, 0x06, 0x78, 0x00, 0x00, 0x00, 0x00,
-       0x23, 0x28, 0x04, 0x11, 0x00, 0x00
-};
-
-static void reg_w_buf(struct gspca_dev *gspca_dev,
-                 __u8 index,
-                 const u8 *buffer, int len)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       memcpy(gspca_dev->usb_buf, buffer, len);
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0,              /* request */
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,              /* value */
-                       index, gspca_dev->usb_buf, len,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_w_buf() failed index 0x%02x, error %d\n",
-                      index, ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-
-static void reg_w(struct gspca_dev *gspca_dev,
-                 __u8 index,
-                 __u8 value)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       gspca_dev->usb_buf[0] = value;
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0,                      /* request */
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0, index, gspca_dev->usb_buf, 1,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_w() failed index 0x%02x, value 0x%02x, error %d\n",
-                      index, value, ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void reg_w_seq(struct gspca_dev *gspca_dev,
-               const __u8 *seq, int len)
-{
-       while (--len >= 0) {
-               reg_w(gspca_dev, seq[0], seq[1]);
-               seq += 2;
-       }
-}
-
-/* load the beginning of a page */
-static void reg_w_page(struct gspca_dev *gspca_dev,
-                       const __u8 *page, int len)
-{
-       int index;
-       int ret = 0;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       for (index = 0; index < len; index++) {
-               if (page[index] == SKIP)                /* skip this index */
-                       continue;
-               gspca_dev->usb_buf[0] = page[index];
-               ret = usb_control_msg(gspca_dev->dev,
-                               usb_sndctrlpipe(gspca_dev->dev, 0),
-                               0,                      /* request */
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                               0, index, gspca_dev->usb_buf, 1,
-                               500);
-               if (ret < 0) {
-                       pr_err("reg_w_page() failed index 0x%02x, value 0x%02x, error %d\n",
-                              index, page[index], ret);
-                       gspca_dev->usb_err = ret;
-                       break;
-               }
-       }
-}
-
-/* output a variable sequence */
-static void reg_w_var(struct gspca_dev *gspca_dev,
-                       const __u8 *seq,
-                       const __u8 *page4, unsigned int page4_len)
-{
-       int index, len;
-
-       for (;;) {
-               index = *seq++;
-               len = *seq++;
-               switch (len) {
-               case END_OF_SEQUENCE:
-                       return;
-               case LOAD_PAGE4:
-                       reg_w_page(gspca_dev, page4, page4_len);
-                       break;
-               default:
-                       if (len > USB_BUF_SZ) {
-                               PDEBUG(D_ERR|D_STREAM,
-                                       "Incorrect variable sequence");
-                               return;
-                       }
-                       while (len > 0) {
-                               if (len < 8) {
-                                       reg_w_buf(gspca_dev,
-                                               index, seq, len);
-                                       seq += len;
-                                       break;
-                               }
-                               reg_w_buf(gspca_dev, index, seq, 8);
-                               seq += 8;
-                               index += 8;
-                               len -= 8;
-                       }
-               }
-       }
-       /* not reached */
-}
-
-/* this function is called at probe time for pac7311 */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct cam *cam = &gspca_dev->cam;
-
-       cam->cam_mode = vga_mode;
-       cam->nmodes = ARRAY_SIZE(vga_mode);
-       cam->input_flags = V4L2_IN_ST_VFLIP;
-
-       return 0;
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_w(gspca_dev, 0xff, 0x04);
-       reg_w(gspca_dev, 0x10, val);
-       /* load registers to sensor (Bit 0, auto clear) */
-       reg_w(gspca_dev, 0x11, 0x01);
-}
-
-static void setgain(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_w(gspca_dev, 0xff, 0x04);                   /* page 4 */
-       reg_w(gspca_dev, 0x0e, 0x00);
-       reg_w(gspca_dev, 0x0f, gspca_dev->gain->maximum - val + 1);
-
-       /* load registers to sensor (Bit 0, auto clear) */
-       reg_w(gspca_dev, 0x11, 0x01);
-}
-
-static void setexposure(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_w(gspca_dev, 0xff, 0x04);                   /* page 4 */
-       reg_w(gspca_dev, 0x02, val);
-
-       /* load registers to sensor (Bit 0, auto clear) */
-       reg_w(gspca_dev, 0x11, 0x01);
-
-       /*
-        * Page 1 register 8 must always be 0x08 except when not in
-        *  640x480 mode and page 4 reg 2 <= 3 then it must be 9
-        */
-       reg_w(gspca_dev, 0xff, 0x01);
-       if (gspca_dev->width != 640 && val <= 3)
-               reg_w(gspca_dev, 0x08, 0x09);
-       else
-               reg_w(gspca_dev, 0x08, 0x08);
-
-       /*
-        * Page1 register 80 sets the compression balance, normally we
-        * want / use 0x1c, but for 640x480@30fps we must allow the
-        * camera to use higher compression or we may run out of
-        * bandwidth.
-        */
-       if (gspca_dev->width == 640 && val == 2)
-               reg_w(gspca_dev, 0x80, 0x01);
-       else
-               reg_w(gspca_dev, 0x80, 0x1c);
-
-       /* load registers to sensor (Bit 0, auto clear) */
-       reg_w(gspca_dev, 0x11, 0x01);
-}
-
-static void sethvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
-{
-       __u8 data;
-
-       reg_w(gspca_dev, 0xff, 0x04);                   /* page 4 */
-       data = (hflip ? 0x04 : 0x00) |
-              (vflip ? 0x08 : 0x00);
-       reg_w(gspca_dev, 0x21, data);
-
-       /* load registers to sensor (Bit 0, auto clear) */
-       reg_w(gspca_dev, 0x11, 0x01);
-}
-
-/* this function is called at probe and resume time for pac7311 */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       reg_w_seq(gspca_dev, init_7311, sizeof(init_7311)/2);
-       return gspca_dev->usb_err;
-}
-
-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 (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
-               /* when switching to autogain set defaults to make sure
-                  we are on a valid point of the autogain gain /
-                  exposure knee graph, and give this change time to
-                  take effect before doing autogain. */
-               gspca_dev->exposure->val    = PAC7311_EXPOSURE_DEFAULT;
-               gspca_dev->gain->val        = PAC7311_GAIN_DEFAULT;
-               sd->autogain_ignore_frames  = PAC_AUTOGAIN_IGNORE_FRAMES;
-       }
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
-                       setexposure(gspca_dev, gspca_dev->exposure->val);
-               if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
-                       setgain(gspca_dev, gspca_dev->gain->val);
-               break;
-       case V4L2_CID_HFLIP:
-               sethvflip(gspca_dev, sd->hflip->val, 1);
-               break;
-       default:
-               return -EINVAL;
-       }
-       return gspca_dev->usb_err;
-}
-
-static const struct v4l2_ctrl_ops sd_ctrl_ops = {
-       .s_ctrl = sd_s_ctrl,
-};
-
-/* this function is called at probe time */
-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, 5);
-
-       sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_CONTRAST, 0, 15, 1, 7);
-       gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-       gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_EXPOSURE, 2, 63, 1,
-                                       PAC7311_EXPOSURE_DEFAULT);
-       gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_GAIN, 0, 244, 1,
-                                       PAC7311_GAIN_DEFAULT);
-       sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-               V4L2_CID_HFLIP, 0, 1, 1, 0);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-
-       v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
-       return 0;
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->sof_read = 0;
-
-       reg_w_var(gspca_dev, start_7311,
-               page4_7311, sizeof(page4_7311));
-       setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->contrast));
-       setgain(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->gain));
-       setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
-       sethvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip), 1);
-
-       /* set correct resolution */
-       switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
-       case 2:                                 /* 160x120 */
-               reg_w(gspca_dev, 0xff, 0x01);
-               reg_w(gspca_dev, 0x17, 0x20);
-               reg_w(gspca_dev, 0x87, 0x10);
-               break;
-       case 1:                                 /* 320x240 */
-               reg_w(gspca_dev, 0xff, 0x01);
-               reg_w(gspca_dev, 0x17, 0x30);
-               reg_w(gspca_dev, 0x87, 0x11);
-               break;
-       case 0:                                 /* 640x480 */
-               reg_w(gspca_dev, 0xff, 0x01);
-               reg_w(gspca_dev, 0x17, 0x00);
-               reg_w(gspca_dev, 0x87, 0x12);
-               break;
-       }
-
-       sd->sof_read = 0;
-       sd->autogain_ignore_frames = 0;
-       atomic_set(&sd->avg_lum, -1);
-
-       /* start stream */
-       reg_w(gspca_dev, 0xff, 0x01);
-       reg_w(gspca_dev, 0x78, 0x05);
-
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       reg_w(gspca_dev, 0xff, 0x04);
-       reg_w(gspca_dev, 0x27, 0x80);
-       reg_w(gspca_dev, 0x28, 0xca);
-       reg_w(gspca_dev, 0x29, 0x53);
-       reg_w(gspca_dev, 0x2a, 0x0e);
-       reg_w(gspca_dev, 0xff, 0x01);
-       reg_w(gspca_dev, 0x3e, 0x20);
-       reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
-       reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
-       reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_6=LED */
-}
-
-static void do_autogain(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int avg_lum = atomic_read(&sd->avg_lum);
-       int desired_lum, deadzone;
-
-       if (avg_lum == -1)
-               return;
-
-       desired_lum = 170;
-       deadzone = 20;
-
-       if (sd->autogain_ignore_frames > 0)
-               sd->autogain_ignore_frames--;
-       else if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
-                                                   desired_lum, deadzone))
-               sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES;
-}
-
-/* JPEG header, part 1 */
-static const unsigned char pac_jpeg_header1[] = {
-  0xff, 0xd8,          /* SOI: Start of Image */
-
-  0xff, 0xc0,          /* SOF0: Start of Frame (Baseline DCT) */
-  0x00, 0x11,          /* length = 17 bytes (including this length field) */
-  0x08                 /* Precision: 8 */
-  /* 2 bytes is placed here: number of image lines */
-  /* 2 bytes is placed here: samples per line */
-};
-
-/* JPEG header, continued */
-static const unsigned char pac_jpeg_header2[] = {
-  0x03,                        /* Number of image components: 3 */
-  0x01, 0x21, 0x00,    /* ID=1, Subsampling 1x1, Quantization table: 0 */
-  0x02, 0x11, 0x01,    /* ID=2, Subsampling 2x1, Quantization table: 1 */
-  0x03, 0x11, 0x01,    /* ID=3, Subsampling 2x1, Quantization table: 1 */
-
-  0xff, 0xda,          /* SOS: Start Of Scan */
-  0x00, 0x0c,          /* length = 12 bytes (including this length field) */
-  0x03,                        /* number of components: 3 */
-  0x01, 0x00,          /* selector 1, table 0x00 */
-  0x02, 0x11,          /* selector 2, table 0x11 */
-  0x03, 0x11,          /* selector 3, table 0x11 */
-  0x00, 0x3f,          /* Spectral selection: 0 .. 63 */
-  0x00                 /* Successive approximation: 0 */
-};
-
-static void pac_start_frame(struct gspca_dev *gspca_dev,
-               __u16 lines, __u16 samples_per_line)
-{
-       unsigned char tmpbuf[4];
-
-       gspca_frame_add(gspca_dev, FIRST_PACKET,
-               pac_jpeg_header1, sizeof(pac_jpeg_header1));
-
-       tmpbuf[0] = lines >> 8;
-       tmpbuf[1] = lines & 0xff;
-       tmpbuf[2] = samples_per_line >> 8;
-       tmpbuf[3] = samples_per_line & 0xff;
-
-       gspca_frame_add(gspca_dev, INTER_PACKET,
-               tmpbuf, sizeof(tmpbuf));
-       gspca_frame_add(gspca_dev, INTER_PACKET,
-               pac_jpeg_header2, sizeof(pac_jpeg_header2));
-}
-
-/* this function is run at interrupt level */
-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;
-       u8 *image;
-       unsigned char *sof;
-
-       sof = pac_find_sof(&sd->sof_read, data, len);
-       if (sof) {
-               int n, lum_offset, footer_length;
-
-               /*
-                * 6 bytes after the FF D9 EOF marker a number of lumination
-                * bytes are send corresponding to different parts of the
-                * image, the 14th and 15th byte after the EOF seem to
-                * correspond to the center of the image.
-                */
-               lum_offset = 24 + sizeof pac_sof_marker;
-               footer_length = 26;
-
-               /* Finish decoding current frame */
-               n = (sof - data) - (footer_length + sizeof pac_sof_marker);
-               if (n < 0) {
-                       gspca_dev->image_len += n;
-                       n = 0;
-               } else {
-                       gspca_frame_add(gspca_dev, INTER_PACKET, data, n);
-               }
-               image = gspca_dev->image;
-               if (image != NULL
-                && image[gspca_dev->image_len - 2] == 0xff
-                && image[gspca_dev->image_len - 1] == 0xd9)
-                       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-
-               n = sof - data;
-               len -= n;
-               data = sof;
-
-               /* Get average lumination */
-               if (gspca_dev->last_packet_type == LAST_PACKET &&
-                               n >= lum_offset)
-                       atomic_set(&sd->avg_lum, data[-lum_offset] +
-                                               data[-lum_offset + 1]);
-               else
-                       atomic_set(&sd->avg_lum, -1);
-
-               /* Start the new frame with the jpeg header */
-               pac_start_frame(gspca_dev,
-                       gspca_dev->height, gspca_dev->width);
-       }
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,               /* interrupt packet data */
-                       int len)                /* interrupt packet length */
-{
-       int ret = -EINVAL;
-       u8 data0, data1;
-
-       if (len == 2) {
-               data0 = data[0];
-               data1 = data[1];
-               if ((data0 == 0x00 && data1 == 0x11) ||
-                   (data0 == 0x22 && data1 == 0x33) ||
-                   (data0 == 0x44 && data1 == 0x55) ||
-                   (data0 == 0x66 && data1 == 0x77) ||
-                   (data0 == 0x88 && data1 == 0x99) ||
-                   (data0 == 0xaa && data1 == 0xbb) ||
-                   (data0 == 0xcc && data1 == 0xdd) ||
-                   (data0 == 0xee && data1 == 0xff)) {
-                       input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
-                       input_sync(gspca_dev->input_dev);
-                       input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
-                       input_sync(gspca_dev->input_dev);
-                       ret = 0;
-               }
-       }
-
-       return ret;
-}
-#endif
-
-static const struct sd_desc sd_desc = {
-       .name = MODULE_NAME,
-       .config = sd_config,
-       .init = sd_init,
-       .init_controls = sd_init_controls,
-       .start = sd_start,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-       .dq_callback = do_autogain,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .int_pkt_scan = sd_int_pkt_scan,
-#endif
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x093a, 0x2600)},
-       {USB_DEVICE(0x093a, 0x2601)},
-       {USB_DEVICE(0x093a, 0x2603)},
-       {USB_DEVICE(0x093a, 0x2608)},
-       {USB_DEVICE(0x093a, 0x260e)},
-       {USB_DEVICE(0x093a, 0x260f)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/pac_common.h b/drivers/media/video/gspca/pac_common.h
deleted file mode 100644 (file)
index 8462a7c..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Pixart PAC207BCA / PAC73xx common functions
- *
- * Copyright (C) 2008 Hans de Goede <j.w.r.degoede@hhs.nl>
- * Copyright (C) 2005 Thomas Kaiser thomas@kaiser-linux.li
- * Copyleft (C) 2005 Michel Xhaard mxhaard@magic.fr
- *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-/* We calculate the autogain at the end of the transfer of a frame, at this
-   moment a frame with the old settings is being captured and transmitted. So
-   if we adjust the gain or exposure we must ignore atleast the next frame for
-   the new settings to come into effect before doing any other adjustments. */
-#define PAC_AUTOGAIN_IGNORE_FRAMES     2
-
-static const unsigned char pac_sof_marker[5] =
-               { 0xff, 0xff, 0x00, 0xff, 0x96 };
-
-/*
-   The following state machine finds the SOF marker sequence
-   0xff, 0xff, 0x00, 0xff, 0x96 in a byte stream.
-
-          +----------+
-          | 0: START |<---------------\
-          +----------+<-\             |
-            |       \---/otherwise    |
-            v 0xff                    |
-          +----------+ otherwise      |
-          |     1    |--------------->*
-          |          |                ^
-          +----------+                |
-            |                         |
-            v 0xff                    |
-          +----------+<-\0xff         |
-       /->|          |--/             |
-       |  |     2    |--------------->*
-       |  |          | otherwise      ^
-       |  +----------+                |
-       |    |                         |
-       |    v 0x00                    |
-       |  +----------+                |
-       |  |     3    |                |
-       |  |          |--------------->*
-       |  +----------+ otherwise      ^
-       |    |                         |
-   0xff |    v 0xff                    |
-       |  +----------+                |
-       \--|     4    |                |
-          |          |----------------/
-          +----------+ otherwise
-            |
-            v 0x96
-          +----------+
-          |  FOUND   |
-          +----------+
-*/
-
-static unsigned char *pac_find_sof(u8 *sof_read,
-                                       unsigned char *m, int len)
-{
-       int i;
-
-       /* Search for the SOF marker (fixed part) in the header */
-       for (i = 0; i < len; i++) {
-               switch (*sof_read) {
-               case 0:
-                       if (m[i] == 0xff)
-                               *sof_read = 1;
-                       break;
-               case 1:
-                       if (m[i] == 0xff)
-                               *sof_read = 2;
-                       else
-                               *sof_read = 0;
-                       break;
-               case 2:
-                       switch (m[i]) {
-                       case 0x00:
-                               *sof_read = 3;
-                               break;
-                       case 0xff:
-                               /* stay in this state */
-                               break;
-                       default:
-                               *sof_read = 0;
-                       }
-                       break;
-               case 3:
-                       if (m[i] == 0xff)
-                               *sof_read = 4;
-                       else
-                               *sof_read = 0;
-                       break;
-               case 4:
-                       switch (m[i]) {
-                       case 0x96:
-                               /* Pattern found */
-                               PDEBUG(D_FRAM,
-                                       "SOF found, bytes to analyze: %u."
-                                       " Frame starts at byte #%u",
-                                       len, i + 1);
-                               *sof_read = 0;
-                               return m + i + 1;
-                               break;
-                       case 0xff:
-                               *sof_read = 2;
-                               break;
-                       default:
-                               *sof_read = 0;
-                       }
-                       break;
-               default:
-                       *sof_read = 0;
-               }
-       }
-
-       return NULL;
-}
diff --git a/drivers/media/video/gspca/se401.c b/drivers/media/video/gspca/se401.c
deleted file mode 100644 (file)
index a33cb78..0000000
+++ /dev/null
@@ -1,739 +0,0 @@
-/*
- * GSPCA Endpoints (formerly known as AOX) se401 USB Camera sub Driver
- *
- * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>
- *
- * Based on the v4l1 se401 driver which is:
- *
- * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "se401"
-
-#define BULK_SIZE 4096
-#define PACKET_SIZE 1024
-#define READ_REQ_SIZE 64
-#define MAX_MODES ((READ_REQ_SIZE - 6) / 4)
-/* The se401 compression algorithm uses a fixed quant factor, which
-   can be configured by setting the high nibble of the SE401_OPERATINGMODE
-   feature. This needs to exactly match what is in libv4l! */
-#define SE401_QUANT_FACT 8
-
-#include <linux/input.h>
-#include <linux/slab.h>
-#include "gspca.h"
-#include "se401.h"
-
-MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
-MODULE_DESCRIPTION("Endpoints se401");
-MODULE_LICENSE("GPL");
-
-/* exposure change state machine states */
-enum {
-       EXPO_CHANGED,
-       EXPO_DROP_FRAME,
-       EXPO_NO_CHANGE,
-};
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-       struct { /* exposure/freq control cluster */
-               struct v4l2_ctrl *exposure;
-               struct v4l2_ctrl *freq;
-       };
-       bool has_brightness;
-       struct v4l2_pix_format fmts[MAX_MODES];
-       int pixels_read;
-       int packet_read;
-       u8 packet[PACKET_SIZE];
-       u8 restart_stream;
-       u8 button_state;
-       u8 resetlevel;
-       u8 resetlevel_frame_count;
-       int resetlevel_adjust_dir;
-       int expo_change_state;
-};
-
-
-static void se401_write_req(struct gspca_dev *gspca_dev, u16 req, u16 value,
-                           int silent)
-{
-       int err;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-
-       err = usb_control_msg(gspca_dev->dev,
-                             usb_sndctrlpipe(gspca_dev->dev, 0), req,
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             value, 0, NULL, 0, 1000);
-       if (err < 0) {
-               if (!silent)
-                       pr_err("write req failed req %#04x val %#04x error %d\n",
-                              req, value, err);
-               gspca_dev->usb_err = err;
-       }
-}
-
-static void se401_read_req(struct gspca_dev *gspca_dev, u16 req, int silent)
-{
-       int err;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-
-       if (USB_BUF_SZ < READ_REQ_SIZE) {
-               pr_err("USB_BUF_SZ too small!!\n");
-               gspca_dev->usb_err = -ENOBUFS;
-               return;
-       }
-
-       err = usb_control_msg(gspca_dev->dev,
-                             usb_rcvctrlpipe(gspca_dev->dev, 0), req,
-                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             0, 0, gspca_dev->usb_buf, READ_REQ_SIZE, 1000);
-       if (err < 0) {
-               if (!silent)
-                       pr_err("read req failed req %#04x error %d\n",
-                              req, err);
-               gspca_dev->usb_err = err;
-       }
-}
-
-static void se401_set_feature(struct gspca_dev *gspca_dev,
-                             u16 selector, u16 param)
-{
-       int err;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-
-       err = usb_control_msg(gspca_dev->dev,
-                             usb_sndctrlpipe(gspca_dev->dev, 0),
-                             SE401_REQ_SET_EXT_FEATURE,
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             param, selector, NULL, 0, 1000);
-       if (err < 0) {
-               pr_err("set feature failed sel %#04x param %#04x error %d\n",
-                      selector, param, err);
-               gspca_dev->usb_err = err;
-       }
-}
-
-static int se401_get_feature(struct gspca_dev *gspca_dev, u16 selector)
-{
-       int err;
-
-       if (gspca_dev->usb_err < 0)
-               return gspca_dev->usb_err;
-
-       if (USB_BUF_SZ < 2) {
-               pr_err("USB_BUF_SZ too small!!\n");
-               gspca_dev->usb_err = -ENOBUFS;
-               return gspca_dev->usb_err;
-       }
-
-       err = usb_control_msg(gspca_dev->dev,
-                             usb_rcvctrlpipe(gspca_dev->dev, 0),
-                             SE401_REQ_GET_EXT_FEATURE,
-                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             0, selector, gspca_dev->usb_buf, 2, 1000);
-       if (err < 0) {
-               pr_err("get feature failed sel %#04x error %d\n",
-                      selector, err);
-               gspca_dev->usb_err = err;
-               return err;
-       }
-       return gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8);
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       /* HDG: this does not seem to do anything on my cam */
-       se401_write_req(gspca_dev, SE401_REQ_SET_BRT, val, 0);
-}
-
-static void setgain(struct gspca_dev *gspca_dev, s32 val)
-{
-       u16 gain = 63 - val;
-
-       /* red color gain */
-       se401_set_feature(gspca_dev, HV7131_REG_ARCG, gain);
-       /* green color gain */
-       se401_set_feature(gspca_dev, HV7131_REG_AGCG, gain);
-       /* blue color gain */
-       se401_set_feature(gspca_dev, HV7131_REG_ABCG, gain);
-}
-
-static void setexposure(struct gspca_dev *gspca_dev, s32 val, s32 freq)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int integration = val << 6;
-       u8 expose_h, expose_m, expose_l;
-
-       /* Do this before the set_feature calls, for proper timing wrt
-          the interrupt driven pkt_scan. Note we may still race but that
-          is not a big issue, the expo change state machine is merely for
-          avoiding underexposed frames getting send out, if one sneaks
-          through so be it */
-       sd->expo_change_state = EXPO_CHANGED;
-
-       if (freq == V4L2_CID_POWER_LINE_FREQUENCY_50HZ)
-               integration = integration - integration % 106667;
-       if (freq == V4L2_CID_POWER_LINE_FREQUENCY_60HZ)
-               integration = integration - integration % 88889;
-
-       expose_h = (integration >> 16);
-       expose_m = (integration >> 8);
-       expose_l = integration;
-
-       /* integration time low */
-       se401_set_feature(gspca_dev, HV7131_REG_TITL, expose_l);
-       /* integration time mid */
-       se401_set_feature(gspca_dev, HV7131_REG_TITM, expose_m);
-       /* integration time high */
-       se401_set_feature(gspca_dev, HV7131_REG_TITU, expose_h);
-}
-
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *)gspca_dev;
-       struct cam *cam = &gspca_dev->cam;
-       u8 *cd = gspca_dev->usb_buf;
-       int i, j, n;
-       int widths[MAX_MODES], heights[MAX_MODES];
-
-       /* Read the camera descriptor */
-       se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, 1);
-       if (gspca_dev->usb_err) {
-               /* Sometimes after being idle for a while the se401 won't
-                  respond and needs a good kicking  */
-               usb_reset_device(gspca_dev->dev);
-               gspca_dev->usb_err = 0;
-               se401_read_req(gspca_dev, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0);
-       }
-
-       /* Some cameras start with their LED on */
-       se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 0, 0);
-       if (gspca_dev->usb_err)
-               return gspca_dev->usb_err;
-
-       if (cd[1] != 0x41) {
-               pr_err("Wrong descriptor type\n");
-               return -ENODEV;
-       }
-
-       if (!(cd[2] & SE401_FORMAT_BAYER)) {
-               pr_err("Bayer format not supported!\n");
-               return -ENODEV;
-       }
-
-       if (cd[3])
-               pr_info("ExtraFeatures: %d\n", cd[3]);
-
-       n = cd[4] | (cd[5] << 8);
-       if (n > MAX_MODES) {
-               pr_err("Too many frame sizes\n");
-               return -ENODEV;
-       }
-
-       for (i = 0; i < n ; i++) {
-               widths[i] = cd[6 + i * 4 + 0] | (cd[6 + i * 4 + 1] << 8);
-               heights[i] = cd[6 + i * 4 + 2] | (cd[6 + i * 4 + 3] << 8);
-       }
-
-       for (i = 0; i < n ; i++) {
-               sd->fmts[i].width = widths[i];
-               sd->fmts[i].height = heights[i];
-               sd->fmts[i].field = V4L2_FIELD_NONE;
-               sd->fmts[i].colorspace = V4L2_COLORSPACE_SRGB;
-               sd->fmts[i].priv = 1;
-
-               /* janggu compression only works for 1/4th or 1/16th res */
-               for (j = 0; j < n; j++) {
-                       if (widths[j] / 2 == widths[i] &&
-                           heights[j] / 2 == heights[i]) {
-                               sd->fmts[i].priv = 2;
-                               break;
-                       }
-               }
-               /* 1/16th if available too is better then 1/4th, because
-                  we then use a larger area of the sensor */
-               for (j = 0; j < n; j++) {
-                       if (widths[j] / 4 == widths[i] &&
-                           heights[j] / 4 == heights[i]) {
-                               sd->fmts[i].priv = 4;
-                               break;
-                       }
-               }
-
-               if (sd->fmts[i].priv == 1) {
-                       /* Not a 1/4th or 1/16th res, use bayer */
-                       sd->fmts[i].pixelformat = V4L2_PIX_FMT_SBGGR8;
-                       sd->fmts[i].bytesperline = widths[i];
-                       sd->fmts[i].sizeimage = widths[i] * heights[i];
-                       pr_info("Frame size: %dx%d bayer\n",
-                               widths[i], heights[i]);
-               } else {
-                       /* Found a match use janggu compression */
-                       sd->fmts[i].pixelformat = V4L2_PIX_FMT_SE401;
-                       sd->fmts[i].bytesperline = 0;
-                       sd->fmts[i].sizeimage = widths[i] * heights[i] * 3;
-                       pr_info("Frame size: %dx%d 1/%dth janggu\n",
-                               widths[i], heights[i],
-                               sd->fmts[i].priv * sd->fmts[i].priv);
-               }
-       }
-
-       cam->cam_mode = sd->fmts;
-       cam->nmodes = n;
-       cam->bulk = 1;
-       cam->bulk_size = BULK_SIZE;
-       cam->bulk_nurbs = 4;
-       sd->resetlevel = 0x2d; /* Set initial resetlevel */
-
-       /* See if the camera supports brightness */
-       se401_read_req(gspca_dev, SE401_REQ_GET_BRT, 1);
-       sd->has_brightness = !!gspca_dev->usb_err;
-       gspca_dev->usb_err = 0;
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       return 0;
-}
-
-/* function called at start time before URB creation */
-static int sd_isoc_init(struct gspca_dev *gspca_dev)
-{
-       gspca_dev->alt = 1;     /* Ignore the bogus isoc alt settings */
-
-       return gspca_dev->usb_err;
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *)gspca_dev;
-       int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-       int mode = 0;
-
-       se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 1, 1);
-       if (gspca_dev->usb_err) {
-               /* Sometimes after being idle for a while the se401 won't
-                  respond and needs a good kicking  */
-               usb_reset_device(gspca_dev->dev);
-               gspca_dev->usb_err = 0;
-               se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 1, 0);
-       }
-       se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 1, 0);
-
-       se401_set_feature(gspca_dev, HV7131_REG_MODE_B, 0x05);
-
-       /* set size + mode */
-       se401_write_req(gspca_dev, SE401_REQ_SET_WIDTH,
-                       gspca_dev->width * mult, 0);
-       se401_write_req(gspca_dev, SE401_REQ_SET_HEIGHT,
-                       gspca_dev->height * mult, 0);
-       /*
-        * HDG: disabled this as it does not seem to do anything
-        * se401_write_req(gspca_dev, SE401_REQ_SET_OUTPUT_MODE,
-        *                 SE401_FORMAT_BAYER, 0);
-        */
-
-       switch (mult) {
-       case 1: /* Raw bayer */
-               mode = 0x03; break;
-       case 2: /* 1/4th janggu */
-               mode = SE401_QUANT_FACT << 4; break;
-       case 4: /* 1/16th janggu */
-               mode = (SE401_QUANT_FACT << 4) | 0x02; break;
-       }
-       se401_set_feature(gspca_dev, SE401_OPERATINGMODE, mode);
-
-       se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel);
-
-       sd->packet_read = 0;
-       sd->pixels_read = 0;
-       sd->restart_stream = 0;
-       sd->resetlevel_frame_count = 0;
-       sd->resetlevel_adjust_dir = 0;
-       sd->expo_change_state = EXPO_NO_CHANGE;
-
-       se401_write_req(gspca_dev, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, 0);
-
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       se401_write_req(gspca_dev, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, 0);
-       se401_write_req(gspca_dev, SE401_REQ_LED_CONTROL, 0, 0);
-       se401_write_req(gspca_dev, SE401_REQ_CAMERA_POWER, 0, 0);
-}
-
-static void sd_dq_callback(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *)gspca_dev;
-       unsigned int ahrc, alrc;
-       int oldreset, adjust_dir;
-
-       /* Restart the stream if requested do so by pkt_scan */
-       if (sd->restart_stream) {
-               sd_stopN(gspca_dev);
-               sd_start(gspca_dev);
-               sd->restart_stream = 0;
-       }
-
-       /* Automatically adjust sensor reset level
-          Hyundai have some really nice docs about this and other sensor
-          related stuff on their homepage: www.hei.co.kr */
-       sd->resetlevel_frame_count++;
-       if (sd->resetlevel_frame_count < 20)
-               return;
-
-       /* For some reason this normally read-only register doesn't get reset
-          to zero after reading them just once... */
-       se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH);
-       se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL);
-       se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH);
-       se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL);
-       ahrc = 256*se401_get_feature(gspca_dev, HV7131_REG_HIREFNOH) +
-           se401_get_feature(gspca_dev, HV7131_REG_HIREFNOL);
-       alrc = 256*se401_get_feature(gspca_dev, HV7131_REG_LOREFNOH) +
-           se401_get_feature(gspca_dev, HV7131_REG_LOREFNOL);
-
-       /* Not an exact science, but it seems to work pretty well... */
-       oldreset = sd->resetlevel;
-       if (alrc > 10) {
-               while (alrc >= 10 && sd->resetlevel < 63) {
-                       sd->resetlevel++;
-                       alrc /= 2;
-               }
-       } else if (ahrc > 20) {
-               while (ahrc >= 20 && sd->resetlevel > 0) {
-                       sd->resetlevel--;
-                       ahrc /= 2;
-               }
-       }
-       /* Detect ping-pong-ing and halve adjustment to avoid overshoot */
-       if (sd->resetlevel > oldreset)
-               adjust_dir = 1;
-       else
-               adjust_dir = -1;
-       if (sd->resetlevel_adjust_dir &&
-           sd->resetlevel_adjust_dir != adjust_dir)
-               sd->resetlevel = oldreset + (sd->resetlevel - oldreset) / 2;
-
-       if (sd->resetlevel != oldreset) {
-               sd->resetlevel_adjust_dir = adjust_dir;
-               se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel);
-       }
-
-       sd->resetlevel_frame_count = 0;
-}
-
-static void sd_complete_frame(struct gspca_dev *gspca_dev, u8 *data, int len)
-{
-       struct sd *sd = (struct sd *)gspca_dev;
-
-       switch (sd->expo_change_state) {
-       case EXPO_CHANGED:
-               /* The exposure was changed while this frame
-                  was being send, so this frame is ok */
-               sd->expo_change_state = EXPO_DROP_FRAME;
-               break;
-       case EXPO_DROP_FRAME:
-               /* The exposure was changed while this frame
-                  was being captured, drop it! */
-               gspca_dev->last_packet_type = DISCARD_PACKET;
-               sd->expo_change_state = EXPO_NO_CHANGE;
-               break;
-       case EXPO_NO_CHANGE:
-               break;
-       }
-       gspca_frame_add(gspca_dev, LAST_PACKET, data, len);
-}
-
-static void sd_pkt_scan_janggu(struct gspca_dev *gspca_dev, u8 *data, int len)
-{
-       struct sd *sd = (struct sd *)gspca_dev;
-       int imagesize = gspca_dev->width * gspca_dev->height;
-       int i, plen, bits, pixels, info, count;
-
-       if (sd->restart_stream)
-               return;
-
-       /* Sometimes a 1024 bytes garbage bulk packet is send between frames */
-       if (gspca_dev->last_packet_type == LAST_PACKET && len == 1024) {
-               gspca_dev->last_packet_type = DISCARD_PACKET;
-               return;
-       }
-
-       i = 0;
-       while (i < len) {
-               /* Read header if not already be present from prev bulk pkt */
-               if (sd->packet_read < 4) {
-                       count = 4 - sd->packet_read;
-                       if (count > len - i)
-                               count = len - i;
-                       memcpy(&sd->packet[sd->packet_read], &data[i], count);
-                       sd->packet_read += count;
-                       i += count;
-                       if (sd->packet_read < 4)
-                               break;
-               }
-               bits   = sd->packet[3] + (sd->packet[2] << 8);
-               pixels = sd->packet[1] + ((sd->packet[0] & 0x3f) << 8);
-               info   = (sd->packet[0] & 0xc0) >> 6;
-               plen   = ((bits + 47) >> 4) << 1;
-               /* Sanity checks */
-               if (plen > 1024) {
-                       pr_err("invalid packet len %d restarting stream\n",
-                              plen);
-                       goto error;
-               }
-               if (info == 3) {
-                       pr_err("unknown frame info value restarting stream\n");
-                       goto error;
-               }
-
-               /* Read (remainder of) packet contents */
-               count = plen - sd->packet_read;
-               if (count > len - i)
-                       count = len - i;
-               memcpy(&sd->packet[sd->packet_read], &data[i], count);
-               sd->packet_read += count;
-               i += count;
-               if (sd->packet_read < plen)
-                       break;
-
-               sd->pixels_read += pixels;
-               sd->packet_read = 0;
-
-               switch (info) {
-               case 0: /* Frame data */
-                       gspca_frame_add(gspca_dev, INTER_PACKET, sd->packet,
-                                       plen);
-                       break;
-               case 1: /* EOF */
-                       if (sd->pixels_read != imagesize) {
-                               pr_err("frame size %d expected %d\n",
-                                      sd->pixels_read, imagesize);
-                               goto error;
-                       }
-                       sd_complete_frame(gspca_dev, sd->packet, plen);
-                       return; /* Discard the rest of the bulk packet !! */
-               case 2: /* SOF */
-                       gspca_frame_add(gspca_dev, FIRST_PACKET, sd->packet,
-                                       plen);
-                       sd->pixels_read = pixels;
-                       break;
-               }
-       }
-       return;
-
-error:
-       sd->restart_stream = 1;
-       /* Give userspace a 0 bytes frame, so our dq callback gets
-          called and it can restart the stream */
-       gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
-       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-}
-
-static void sd_pkt_scan_bayer(struct gspca_dev *gspca_dev, u8 *data, int len)
-{
-       struct cam *cam = &gspca_dev->cam;
-       int imagesize = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
-
-       if (gspca_dev->image_len == 0) {
-               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
-               return;
-       }
-
-       if (gspca_dev->image_len + len >= imagesize) {
-               sd_complete_frame(gspca_dev, data, len);
-               return;
-       }
-
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
-{
-       int mult = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-
-       if (len == 0)
-               return;
-
-       if (mult == 1) /* mult == 1 means raw bayer */
-               sd_pkt_scan_bayer(gspca_dev, data, len);
-       else
-               sd_pkt_scan_janggu(gspca_dev, data, len);
-}
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
-{
-       struct sd *sd = (struct sd *)gspca_dev;
-       u8 state;
-
-       if (len != 2)
-               return -EINVAL;
-
-       switch (data[0]) {
-       case 0:
-       case 1:
-               state = data[0];
-               break;
-       default:
-               return -EINVAL;
-       }
-       if (sd->button_state != state) {
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, state);
-               input_sync(gspca_dev->input_dev);
-               sd->button_state = state;
-       }
-
-       return 0;
-}
-#endif
-
-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_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_GAIN:
-               setgain(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_EXPOSURE:
-               setexposure(gspca_dev, ctrl->val, sd->freq->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);
-       if (sd->has_brightness)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 15);
-       /* max is really 63 but > 50 is not pretty */
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAIN, 0, 50, 1, 25);
-       sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 0, 32767, 1, 15000);
-       sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
-                       V4L2_CID_POWER_LINE_FREQUENCY,
-                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-       v4l2_ctrl_cluster(2, &sd->exposure);
-       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,
-       .isoc_init = sd_isoc_init,
-       .start = sd_start,
-       .stopN = sd_stopN,
-       .dq_callback = sd_dq_callback,
-       .pkt_scan = sd_pkt_scan,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .int_pkt_scan = sd_int_pkt_scan,
-#endif
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x03e8, 0x0004)}, /* Endpoints/Aox SE401 */
-       {USB_DEVICE(0x0471, 0x030b)}, /* Philips PCVC665K */
-       {USB_DEVICE(0x047d, 0x5001)}, /* Kensington 67014 */
-       {USB_DEVICE(0x047d, 0x5002)}, /* Kensington 6701(5/7) */
-       {USB_DEVICE(0x047d, 0x5003)}, /* Kensington 67016 */
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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 int sd_pre_reset(struct usb_interface *intf)
-{
-       return 0;
-}
-
-static int sd_post_reset(struct usb_interface *intf)
-{
-       return 0;
-}
-
-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,
-       .reset_resume = gspca_resume,
-#endif
-       .pre_reset = sd_pre_reset,
-       .post_reset = sd_post_reset,
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/se401.h b/drivers/media/video/gspca/se401.h
deleted file mode 100644 (file)
index 96d8ebf..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * GSPCA Endpoints (formerly known as AOX) se401 USB Camera sub Driver
- *
- * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>
- *
- * Based on the v4l1 se401 driver which is:
- *
- * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#define SE401_REQ_GET_CAMERA_DESCRIPTOR                0x06
-#define SE401_REQ_START_CONTINUOUS_CAPTURE     0x41
-#define SE401_REQ_STOP_CONTINUOUS_CAPTURE      0x42
-#define SE401_REQ_CAPTURE_FRAME                        0x43
-#define SE401_REQ_GET_BRT                      0x44
-#define SE401_REQ_SET_BRT                      0x45
-#define SE401_REQ_GET_WIDTH                    0x4c
-#define SE401_REQ_SET_WIDTH                    0x4d
-#define SE401_REQ_GET_HEIGHT                   0x4e
-#define SE401_REQ_SET_HEIGHT                   0x4f
-#define SE401_REQ_GET_OUTPUT_MODE              0x50
-#define SE401_REQ_SET_OUTPUT_MODE              0x51
-#define SE401_REQ_GET_EXT_FEATURE              0x52
-#define SE401_REQ_SET_EXT_FEATURE              0x53
-#define SE401_REQ_CAMERA_POWER                 0x56
-#define SE401_REQ_LED_CONTROL                  0x57
-#define SE401_REQ_BIOS                         0xff
-
-#define SE401_BIOS_READ                                0x07
-
-#define SE401_FORMAT_BAYER     0x40
-
-/* Hyundai hv7131b registers
-   7121 and 7141 should be the same (haven't really checked...) */
-/* Mode registers: */
-#define HV7131_REG_MODE_A              0x00
-#define HV7131_REG_MODE_B              0x01
-#define HV7131_REG_MODE_C              0x02
-/* Frame registers: */
-#define HV7131_REG_FRSU                0x10
-#define HV7131_REG_FRSL                0x11
-#define HV7131_REG_FCSU                0x12
-#define HV7131_REG_FCSL                0x13
-#define HV7131_REG_FWHU                0x14
-#define HV7131_REG_FWHL                0x15
-#define HV7131_REG_FWWU                0x16
-#define HV7131_REG_FWWL                0x17
-/* Timing registers: */
-#define HV7131_REG_THBU                0x20
-#define HV7131_REG_THBL                0x21
-#define HV7131_REG_TVBU                0x22
-#define HV7131_REG_TVBL                0x23
-#define HV7131_REG_TITU                0x25
-#define HV7131_REG_TITM                0x26
-#define HV7131_REG_TITL                0x27
-#define HV7131_REG_TMCD                0x28
-/* Adjust Registers: */
-#define HV7131_REG_ARLV                0x30
-#define HV7131_REG_ARCG                0x31
-#define HV7131_REG_AGCG                0x32
-#define HV7131_REG_ABCG                0x33
-#define HV7131_REG_APBV                0x34
-#define HV7131_REG_ASLP                0x54
-/* Offset Registers: */
-#define HV7131_REG_OFSR                0x50
-#define HV7131_REG_OFSG                0x51
-#define HV7131_REG_OFSB                0x52
-/* REset level statistics registers: */
-#define HV7131_REG_LOREFNOH    0x57
-#define HV7131_REG_LOREFNOL    0x58
-#define HV7131_REG_HIREFNOH    0x59
-#define HV7131_REG_HIREFNOL    0x5a
-
-/* se401 registers */
-#define SE401_OPERATINGMODE    0x2000
diff --git a/drivers/media/video/gspca/sn9c2028.c b/drivers/media/video/gspca/sn9c2028.c
deleted file mode 100644 (file)
index 03fa3fd..0000000
+++ /dev/null
@@ -1,735 +0,0 @@
-/*
- * SN9C2028 library
- *
- * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn.edu>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "sn9c2028"
-
-#include "gspca.h"
-
-MODULE_AUTHOR("Theodore Kilgore");
-MODULE_DESCRIPTION("Sonix SN9C2028 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;  /* !! must be the first item */
-       u8 sof_read;
-       u16 model;
-};
-
-struct init_command {
-       unsigned char instruction[6];
-       unsigned char to_read; /* length to read. 0 means no reply requested */
-};
-
-/* How to change the resolution of any of the VGA cams is unknown */
-static const struct v4l2_pix_format vga_mode[] = {
-       {640, 480, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 4,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-/* No way to change the resolution of the CIF cams is known */
-static const struct v4l2_pix_format cif_mode[] = {
-       {352, 288, V4L2_PIX_FMT_SN9C2028, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 3 / 4,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-/* the bytes to write are in gspca_dev->usb_buf */
-static int sn9c2028_command(struct gspca_dev *gspca_dev, u8 *command)
-{
-       int rc;
-
-       PDEBUG(D_USBO, "sending command %02x%02x%02x%02x%02x%02x", command[0],
-              command[1], command[2], command[3], command[4], command[5]);
-
-       memcpy(gspca_dev->usb_buf, command, 6);
-       rc = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       USB_REQ_GET_CONFIGURATION,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       2, 0, gspca_dev->usb_buf, 6, 500);
-       if (rc < 0) {
-               pr_err("command write [%02x] error %d\n",
-                      gspca_dev->usb_buf[0], rc);
-               return rc;
-       }
-
-       return 0;
-}
-
-static int sn9c2028_read1(struct gspca_dev *gspca_dev)
-{
-       int rc;
-
-       rc = usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       USB_REQ_GET_STATUS,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       1, 0, gspca_dev->usb_buf, 1, 500);
-       if (rc != 1) {
-               pr_err("read1 error %d\n", rc);
-               return (rc < 0) ? rc : -EIO;
-       }
-       PDEBUG(D_USBI, "read1 response %02x", gspca_dev->usb_buf[0]);
-       return gspca_dev->usb_buf[0];
-}
-
-static int sn9c2028_read4(struct gspca_dev *gspca_dev, u8 *reading)
-{
-       int rc;
-       rc = usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       USB_REQ_GET_STATUS,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       4, 0, gspca_dev->usb_buf, 4, 500);
-       if (rc != 4) {
-               pr_err("read4 error %d\n", rc);
-               return (rc < 0) ? rc : -EIO;
-       }
-       memcpy(reading, gspca_dev->usb_buf, 4);
-       PDEBUG(D_USBI, "read4 response %02x%02x%02x%02x", reading[0],
-              reading[1], reading[2], reading[3]);
-       return rc;
-}
-
-static int sn9c2028_long_command(struct gspca_dev *gspca_dev, u8 *command)
-{
-       int i, status;
-       __u8 reading[4];
-
-       status = sn9c2028_command(gspca_dev, command);
-       if (status < 0)
-               return status;
-
-       status = -1;
-       for (i = 0; i < 256 && status < 2; i++)
-               status = sn9c2028_read1(gspca_dev);
-       if (status != 2) {
-               pr_err("long command status read error %d\n", status);
-               return (status < 0) ? status : -EIO;
-       }
-
-       memset(reading, 0, 4);
-       status = sn9c2028_read4(gspca_dev, reading);
-       if (status < 0)
-               return status;
-
-       /* in general, the first byte of the response is the first byte of
-        * the command, or'ed with 8 */
-       status = sn9c2028_read1(gspca_dev);
-       if (status < 0)
-               return status;
-
-       return 0;
-}
-
-static int sn9c2028_short_command(struct gspca_dev *gspca_dev, u8 *command)
-{
-       int err_code;
-
-       err_code = sn9c2028_command(gspca_dev, command);
-       if (err_code < 0)
-               return err_code;
-
-       err_code = sn9c2028_read1(gspca_dev);
-       if (err_code < 0)
-               return err_code;
-
-       return 0;
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                    const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam = &gspca_dev->cam;
-
-       PDEBUG(D_PROBE, "SN9C2028 camera detected (vid/pid 0x%04X:0x%04X)",
-              id->idVendor, id->idProduct);
-
-       sd->model = id->idProduct;
-
-       switch (sd->model) {
-       case 0x7005:
-               PDEBUG(D_PROBE, "Genius Smart 300 camera");
-               break;
-       case 0x8000:
-               PDEBUG(D_PROBE, "DC31VC");
-               break;
-       case 0x8001:
-               PDEBUG(D_PROBE, "Spy camera");
-               break;
-       case 0x8003:
-               PDEBUG(D_PROBE, "CIF camera");
-               break;
-       case 0x8008:
-               PDEBUG(D_PROBE, "Mini-Shotz ms-350 camera");
-               break;
-       case 0x800a:
-               PDEBUG(D_PROBE, "Vivitar 3350b type camera");
-               cam->input_flags = V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
-               break;
-       }
-
-       switch (sd->model) {
-       case 0x8000:
-       case 0x8001:
-       case 0x8003:
-               cam->cam_mode = cif_mode;
-               cam->nmodes = ARRAY_SIZE(cif_mode);
-               break;
-       default:
-               cam->cam_mode = vga_mode;
-               cam->nmodes = ARRAY_SIZE(vga_mode);
-       }
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       int status = -1;
-
-       sn9c2028_read1(gspca_dev);
-       sn9c2028_read1(gspca_dev);
-       status = sn9c2028_read1(gspca_dev);
-
-       return (status < 0) ? status : 0;
-}
-
-static int run_start_commands(struct gspca_dev *gspca_dev,
-                             struct init_command *cam_commands, int n)
-{
-       int i, err_code = -1;
-
-       for (i = 0; i < n; i++) {
-               switch (cam_commands[i].to_read) {
-               case 4:
-                       err_code = sn9c2028_long_command(gspca_dev,
-                                       cam_commands[i].instruction);
-                       break;
-               case 1:
-                       err_code = sn9c2028_short_command(gspca_dev,
-                                       cam_commands[i].instruction);
-                       break;
-               case 0:
-                       err_code = sn9c2028_command(gspca_dev,
-                                       cam_commands[i].instruction);
-                       break;
-               }
-               if (err_code < 0)
-                       return err_code;
-       }
-       return 0;
-}
-
-static int start_spy_cam(struct gspca_dev *gspca_dev)
-{
-       struct init_command spy_start_commands[] = {
-               {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
-               {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
-               {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, /* width  352 */
-               {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, /* height 288 */
-               /* {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4}, */
-               {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4},
-               {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* red gain ?*/
-               /* {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4}, */
-               {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
-               /* {{0x13, 0x29, 0x01, 0x0c, 0x00, 0x00}, 4}, */
-               {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
-               /* {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4}, */
-               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
-               {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
-               /* {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4}, */
-               {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
-               {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
-               {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
-               {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x02, 0x06, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x03, 0x13, 0x00, 0x00, 0x00}, 4}, /*don't mess with*/
-               /*{{0x11, 0x04, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
-               {{0x11, 0x04, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
-               /*{{0x11, 0x05, 0x65, 0x00, 0x00, 0x00}, 4}, observed */
-               {{0x11, 0x05, 0x00, 0x00, 0x00, 0x00}, 4}, /* brighter */
-               {{0x11, 0x06, 0xb1, 0x00, 0x00, 0x00}, 4}, /* observed */
-               {{0x11, 0x07, 0x00, 0x00, 0x00, 0x00}, 4},
-               /*{{0x11, 0x08, 0x06, 0x00, 0x00, 0x00}, 4}, observed */
-               {{0x11, 0x08, 0x0b, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x09, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x0a, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x0c, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x0d, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x0e, 0x04, 0x00, 0x00, 0x00}, 4},
-               /* {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4}, */
-               /* brightness or gain. 0 is default. 4 is good
-                * indoors at night with incandescent lighting */
-               {{0x11, 0x0f, 0x04, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x10, 0x06, 0x00, 0x00, 0x00}, 4}, /*hstart or hoffs*/
-               {{0x11, 0x11, 0x06, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x14, 0x02, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x13, 0x01, 0x00, 0x00, 0x00}, 4},
-               /* {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1}, observed */
-               {{0x1b, 0x02, 0x11, 0x00, 0x00, 0x00}, 1}, /* brighter */
-               /* {{0x1b, 0x13, 0x01, 0x00, 0x00, 0x00}, 1}, observed */
-               {{0x1b, 0x13, 0x11, 0x00, 0x00, 0x00}, 1},
-               {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}, /* compresses */
-               /* Camera should start to capture now. */
-       };
-
-       return run_start_commands(gspca_dev, spy_start_commands,
-                                 ARRAY_SIZE(spy_start_commands));
-}
-
-static int start_cif_cam(struct gspca_dev *gspca_dev)
-{
-       struct init_command cif_start_commands[] = {
-               {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
-               /* The entire sequence below seems redundant */
-               /* {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x22, 0x01, 0x06, 0x00, 0x00}, 4},
-               {{0x13, 0x23, 0x01, 0x02, 0x00, 0x00}, 4},
-               {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4}, width?
-               {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4}, height?
-               {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
-               {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
-               {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
-               {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
-               {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
-               {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
-               {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
-               {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},*/
-               {{0x1b, 0x21, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x17, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x19, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x03, 0x5a, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x04, 0x27, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x05, 0x01, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x12, 0x14, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x14, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x15, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x16, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x77, 0xa2, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x06, 0x0f, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x07, 0x14, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x08, 0x0f, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x09, 0x10, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x12, 0x07, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x10, 0x1f, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
-               {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 1}, /* width/8 */
-               {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 1}, /* height/8 */
-               /* {{0x13, 0x27, 0x01, 0x68, 0x00, 0x00}, 4}, subsample?
-                * {{0x13, 0x28, 0x01, 0x1e, 0x00, 0x00}, 4}, does nothing
-                * {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4}, */
-               /* {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
-                * causes subsampling
-                * but not a change in the resolution setting! */
-               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
-               {{0x13, 0x2d, 0x01, 0x01, 0x00, 0x00}, 4},
-               {{0x13, 0x2e, 0x01, 0x08, 0x00, 0x00}, 4},
-               {{0x13, 0x2f, 0x01, 0x06, 0x00, 0x00}, 4},
-               {{0x13, 0x28, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x1b, 0x04, 0x6d, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x05, 0x03, 0x00, 0x00, 0x00}, 1},
-               {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x0e, 0x01, 0x00, 0x00, 0x00}, 1},
-               {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x1b, 0x0f, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x10, 0x0f, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x02, 0x06, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
-               {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1},/* use compression */
-               /* Camera should start to capture now. */
-       };
-
-       return run_start_commands(gspca_dev, cif_start_commands,
-                                 ARRAY_SIZE(cif_start_commands));
-}
-
-static int start_ms350_cam(struct gspca_dev *gspca_dev)
-{
-       struct init_command ms350_start_commands[] = {
-               {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x22, 0x01, 0x04, 0x00, 0x00}, 4},
-               {{0x13, 0x23, 0x01, 0x03, 0x00, 0x00}, 4},
-               {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
-               {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
-               {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
-               {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4},
-               {{0x13, 0x29, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
-               {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
-               {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
-               {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
-               {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
-               {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x00, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x01, 0x70, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x02, 0x05, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x03, 0x5d, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x04, 0x07, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x05, 0x25, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x06, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x07, 0x09, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x08, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x09, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x0b, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x0c, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x0d, 0x0c, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x0e, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x0f, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x11, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x13, 0x63, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x15, 0x70, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x18, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x11, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* width  */
-               {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* height */
-               {{0x13, 0x28, 0x01, 0x09, 0x00, 0x00}, 4}, /* vstart? */
-               {{0x13, 0x27, 0x01, 0x28, 0x00, 0x00}, 4},
-               {{0x13, 0x29, 0x01, 0x40, 0x00, 0x00}, 4}, /* hstart? */
-               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
-               {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
-               {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
-               {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
-               {{0x1b, 0x02, 0x05, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 1},
-               {{0x20, 0x18, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x02, 0x0a, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x11, 0x01, 0x00, 0x00, 0x00}, 0},
-               /* Camera should start to capture now. */
-       };
-
-       return run_start_commands(gspca_dev, ms350_start_commands,
-                                 ARRAY_SIZE(ms350_start_commands));
-}
-
-static int start_genius_cam(struct gspca_dev *gspca_dev)
-{
-       struct init_command genius_start_commands[] = {
-               {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x16, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x25, 0x01, 0x16, 0x00, 0x00}, 4},
-               {{0x13, 0x26, 0x01, 0x12, 0x00, 0x00}, 4},
-               /* "preliminary" width and height settings */
-               {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
-               {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
-               {{0x13, 0x29, 0x01, 0x22, 0x00, 0x00}, 4},
-               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
-               {{0x13, 0x2d, 0x01, 0x02, 0x00, 0x00}, 4},
-               {{0x13, 0x2e, 0x01, 0x09, 0x00, 0x00}, 4},
-               {{0x13, 0x2f, 0x01, 0x07, 0x00, 0x00}, 4},
-               {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x11, 0x64, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x13, 0x91, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x15, 0x20, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x16, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x17, 0x60, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x21, 0x2d, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x23, 0x03, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x25, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x26, 0x02, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x27, 0x88, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x30, 0x38, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x31, 0x2a, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x32, 0x2a, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x33, 0x2a, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x34, 0x02, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x5b, 0x0a, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4}, /* real width */
-               {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4}, /* real height */
-               {{0x13, 0x28, 0x01, 0x0e, 0x00, 0x00}, 4},
-               {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
-               {{0x13, 0x29, 0x01, 0x62, 0x00, 0x00}, 4},
-               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
-               {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
-               {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
-               {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
-               {{0x11, 0x20, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x21, 0x2a, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x22, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x23, 0x28, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x10, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x11, 0x04, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x12, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x13, 0x03, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x14, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x15, 0xe0, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x16, 0x02, 0x00, 0x00, 0x00}, 4},
-               {{0x11, 0x17, 0x80, 0x00, 0x00, 0x00}, 4},
-               {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
-               {{0x1c, 0x20, 0x00, 0x2a, 0x00, 0x00}, 1},
-               {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 0}
-               /* Camera should start to capture now. */
-       };
-
-       return run_start_commands(gspca_dev, genius_start_commands,
-                                 ARRAY_SIZE(genius_start_commands));
-}
-
-static int start_vivitar_cam(struct gspca_dev *gspca_dev)
-{
-       struct init_command vivitar_start_commands[] = {
-               {{0x0c, 0x01, 0x00, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x20, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x21, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x22, 0x01, 0x01, 0x00, 0x00}, 4},
-               {{0x13, 0x23, 0x01, 0x01, 0x00, 0x00}, 4},
-               {{0x13, 0x24, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
-               {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
-               {{0x13, 0x27, 0x01, 0x20, 0x00, 0x00}, 4},
-               {{0x13, 0x28, 0x01, 0x0a, 0x00, 0x00}, 4},
-               /*
-                * Above is changed from OEM 0x0b. Fixes Bayer tiling.
-                * Presumably gives a vertical shift of one row.
-                */
-               {{0x13, 0x29, 0x01, 0x20, 0x00, 0x00}, 4},
-               /* Above seems to do horizontal shift. */
-               {{0x13, 0x2a, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x2b, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x2c, 0x01, 0x02, 0x00, 0x00}, 4},
-               {{0x13, 0x2d, 0x01, 0x03, 0x00, 0x00}, 4},
-               {{0x13, 0x2e, 0x01, 0x0f, 0x00, 0x00}, 4},
-               {{0x13, 0x2f, 0x01, 0x0c, 0x00, 0x00}, 4},
-               /* Above three commands seem to relate to brightness. */
-               {{0x12, 0x34, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x13, 0x34, 0x01, 0xa1, 0x00, 0x00}, 4},
-               {{0x13, 0x35, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x1b, 0x12, 0x80, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x01, 0x77, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x02, 0x3a, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x12, 0x78, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x13, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x14, 0x80, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x15, 0x34, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x1b, 0x04, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x20, 0x44, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x23, 0xee, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x26, 0xa0, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x27, 0x9a, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x28, 0xa0, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x2a, 0x80, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x2b, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x2f, 0x3d, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x30, 0x24, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x32, 0x86, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x60, 0xa9, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x61, 0x42, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x65, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x69, 0x38, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x6f, 0x88, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x70, 0x0b, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x71, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x74, 0x21, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x75, 0x86, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x76, 0x00, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x7d, 0xf3, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x17, 0x1c, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x18, 0xc0, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x19, 0x05, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x1a, 0xf6, 0x00, 0x00, 0x00}, 1},
-               /* {{0x13, 0x25, 0x01, 0x28, 0x00, 0x00}, 4},
-               {{0x13, 0x26, 0x01, 0x1e, 0x00, 0x00}, 4},
-               {{0x13, 0x28, 0x01, 0x0b, 0x00, 0x00}, 4}, */
-               {{0x20, 0x36, 0x06, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x10, 0x26, 0x00, 0x00, 0x00}, 1},
-               {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x1b, 0x76, 0x03, 0x00, 0x00, 0x00}, 1},
-               {{0x20, 0x36, 0x05, 0x00, 0x00, 0x00}, 1},
-               {{0x1b, 0x00, 0x3f, 0x00, 0x00, 0x00}, 1},
-               /* Above is brightness; OEM driver setting is 0x10 */
-               {{0x12, 0x27, 0x01, 0x00, 0x00, 0x00}, 4},
-               {{0x20, 0x29, 0x30, 0x00, 0x00, 0x00}, 1},
-               {{0x20, 0x34, 0xa1, 0x00, 0x00, 0x00}, 1}
-       };
-
-       return run_start_commands(gspca_dev, vivitar_start_commands,
-                                 ARRAY_SIZE(vivitar_start_commands));
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int err_code;
-
-       sd->sof_read = 0;
-
-       switch (sd->model) {
-       case 0x7005:
-               err_code = start_genius_cam(gspca_dev);
-               break;
-       case 0x8001:
-               err_code = start_spy_cam(gspca_dev);
-               break;
-       case 0x8003:
-               err_code = start_cif_cam(gspca_dev);
-               break;
-       case 0x8008:
-               err_code = start_ms350_cam(gspca_dev);
-               break;
-       case 0x800a:
-               err_code = start_vivitar_cam(gspca_dev);
-               break;
-       default:
-               pr_err("Starting unknown camera, please report this\n");
-               return -ENXIO;
-       }
-
-       return err_code;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       int result;
-       __u8 data[6];
-
-       result = sn9c2028_read1(gspca_dev);
-       if (result < 0)
-               PDEBUG(D_ERR, "Camera Stop read failed");
-
-       memset(data, 0, 6);
-       data[0] = 0x14;
-       result = sn9c2028_command(gspca_dev, data);
-       if (result < 0)
-               PDEBUG(D_ERR, "Camera Stop command failed");
-}
-
-/* Include sn9c2028 sof detection functions */
-#include "sn9c2028.h"
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       __u8 *data,                     /* isoc packet */
-                       int len)                        /* iso packet length */
-{
-       unsigned char *sof;
-
-       sof = sn9c2028_find_sof(gspca_dev, data, len);
-       if (sof) {
-               int n;
-
-               /* finish decoding current frame */
-               n = sof - data;
-               if (n > sizeof sn9c2028_sof_marker)
-                       n -= sizeof sn9c2028_sof_marker;
-               else
-                       n = 0;
-               gspca_frame_add(gspca_dev, LAST_PACKET, data, n);
-               /* Start next frame. */
-               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                       sn9c2028_sof_marker, sizeof sn9c2028_sof_marker);
-               len -= sof - data;
-               data = sof;
-       }
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-/* sub-driver description */
-static const struct sd_desc sd_desc = {
-       .name = MODULE_NAME,
-       .config = sd_config,
-       .init = sd_init,
-       .start = sd_start,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x0458, 0x7005)}, /* Genius Smart 300, version 2 */
-       /* The Genius Smart is untested. I can't find an owner ! */
-       /* {USB_DEVICE(0x0c45, 0x8000)}, DC31VC, Don't know this camera */
-       {USB_DEVICE(0x0c45, 0x8001)}, /* Wild Planet digital spy cam */
-       {USB_DEVICE(0x0c45, 0x8003)}, /* Several small CIF cameras */
-       /* {USB_DEVICE(0x0c45, 0x8006)}, Unknown VGA camera */
-       {USB_DEVICE(0x0c45, 0x8008)}, /* Mini-Shotz ms-350 */
-       {USB_DEVICE(0x0c45, 0x800a)}, /* Vivicam 3350B */
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/sn9c2028.h b/drivers/media/video/gspca/sn9c2028.h
deleted file mode 100644 (file)
index 8fd1d3e..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SN9C2028 common functions
- *
- * Copyright (C) 2009 Theodore Kilgore <kilgota@auburn,edu>
- *
- * Based closely upon the file gspca/pac_common.h
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-static const unsigned char sn9c2028_sof_marker[5] =
-       { 0xff, 0xff, 0x00, 0xc4, 0xc4 };
-
-static unsigned char *sn9c2028_find_sof(struct gspca_dev *gspca_dev,
-                                       unsigned char *m, int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i;
-
-       /* Search for the SOF marker (fixed part) in the header */
-       for (i = 0; i < len; i++) {
-               if (m[i] == sn9c2028_sof_marker[sd->sof_read]) {
-                       sd->sof_read++;
-                       if (sd->sof_read == sizeof(sn9c2028_sof_marker)) {
-                               PDEBUG(D_FRAM,
-                                       "SOF found, bytes to analyze: %u."
-                                       " Frame starts at byte #%u",
-                                       len, i + 1);
-                               sd->sof_read = 0;
-                               return m + i + 1;
-                       }
-               } else {
-                       sd->sof_read = 0;
-               }
-       }
-
-       return NULL;
-}
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c
deleted file mode 100644 (file)
index b9c6f17..0000000
+++ /dev/null
@@ -1,2428 +0,0 @@
-/*
- *     Sonix sn9c201 sn9c202 library
- *
- * Copyright (C) 2012 Jean-Francois Moine <http://moinejf.free.fr>
- *     Copyright (C) 2008-2009 microdia project <microdia@googlegroups.com>
- *     Copyright (C) 2009 Brian Johnson <brijohn@gmail.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
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/input.h>
-
-#include "gspca.h"
-#include "jpeg.h"
-
-#include <media/v4l2-chip-ident.h>
-#include <linux/dmi.h>
-
-MODULE_AUTHOR("Brian Johnson <brijohn@gmail.com>, "
-               "microdia project <microdia@googlegroups.com>");
-MODULE_DESCRIPTION("GSPCA/SN9C20X USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/*
- * Pixel format private data
- */
-#define SCALE_MASK     0x0f
-#define SCALE_160x120  0
-#define SCALE_320x240  1
-#define SCALE_640x480  2
-#define SCALE_1280x1024        3
-#define MODE_RAW       0x10
-#define MODE_JPEG      0x20
-#define MODE_SXGA      0x80
-
-#define SENSOR_OV9650  0
-#define SENSOR_OV9655  1
-#define SENSOR_SOI968  2
-#define SENSOR_OV7660  3
-#define SENSOR_OV7670  4
-#define SENSOR_MT9V011 5
-#define SENSOR_MT9V111 6
-#define SENSOR_MT9V112 7
-#define SENSOR_MT9M001 8
-#define SENSOR_MT9M111 9
-#define SENSOR_MT9M112  10
-#define SENSOR_HV7131R 11
-#define SENSOR_MT9VPRB 12
-
-/* camera flags */
-#define HAS_NO_BUTTON  0x1
-#define LED_REVERSE    0x2 /* some cameras unset gpio to turn on leds */
-#define FLIP_DETECT    0x4
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;
-
-       struct { /* color control cluster */
-               struct v4l2_ctrl *brightness;
-               struct v4l2_ctrl *contrast;
-               struct v4l2_ctrl *saturation;
-               struct v4l2_ctrl *hue;
-       };
-       struct { /* blue/red balance control cluster */
-               struct v4l2_ctrl *blue;
-               struct v4l2_ctrl *red;
-       };
-       struct { /* h/vflip control cluster */
-               struct v4l2_ctrl *hflip;
-               struct v4l2_ctrl *vflip;
-       };
-       struct v4l2_ctrl *gamma;
-       struct { /* autogain and exposure or gain control cluster */
-               struct v4l2_ctrl *autogain;
-               struct v4l2_ctrl *exposure;
-               struct v4l2_ctrl *gain;
-       };
-       struct v4l2_ctrl *jpegqual;
-
-       struct work_struct work;
-       struct workqueue_struct *work_thread;
-
-       u32 pktsz;                      /* (used by pkt_scan) */
-       u16 npkt;
-       s8 nchg;
-       u8 fmt;                         /* (used for JPEG QTAB update */
-
-#define MIN_AVG_LUM 80
-#define MAX_AVG_LUM 130
-       atomic_t avg_lum;
-       u8 old_step;
-       u8 older_step;
-       u8 exposure_step;
-
-       u8 i2c_addr;
-       u8 i2c_intf;
-       u8 sensor;
-       u8 hstart;
-       u8 vstart;
-
-       u8 jpeg_hdr[JPEG_HDR_SZ];
-
-       u8 flags;
-};
-
-static void qual_upd(struct work_struct *work);
-
-struct i2c_reg_u8 {
-       u8 reg;
-       u8 val;
-};
-
-struct i2c_reg_u16 {
-       u8 reg;
-       u16 val;
-};
-
-static const struct dmi_system_id flip_dmi_table[] = {
-       {
-               .ident = "MSI MS-1034",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "MS-1034"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "0341")
-               }
-       },
-       {
-               .ident = "MSI MS-1632",
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
-                       DMI_MATCH(DMI_BOARD_NAME, "MS-1632")
-               }
-       },
-       {
-               .ident = "MSI MS-1633X",
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
-                       DMI_MATCH(DMI_BOARD_NAME, "MS-1633X")
-               }
-       },
-       {
-               .ident = "MSI MS-1635X",
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
-                       DMI_MATCH(DMI_BOARD_NAME, "MS-1635X")
-               }
-       },
-       {
-               .ident = "ASUSTeK W7J",
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
-                       DMI_MATCH(DMI_BOARD_NAME, "W7J       ")
-               }
-       },
-       {}
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 4 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = SCALE_160x120 | MODE_JPEG},
-       {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_160x120 | MODE_RAW},
-       {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 240 * 120,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_160x120},
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 4 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = SCALE_320x240 | MODE_JPEG},
-       {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 ,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_320x240 | MODE_RAW},
-       {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 480 * 240 ,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_320x240},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 4 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = SCALE_640x480 | MODE_JPEG},
-       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_640x480 | MODE_RAW},
-       {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 960 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_640x480},
-};
-
-static const struct v4l2_pix_format sxga_mode[] = {
-       {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 4 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = SCALE_160x120 | MODE_JPEG},
-       {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_160x120 | MODE_RAW},
-       {160, 120, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 240 * 120,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_160x120},
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 4 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = SCALE_320x240 | MODE_JPEG},
-       {320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 ,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_320x240 | MODE_RAW},
-       {320, 240, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 480 * 240 ,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_320x240},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 4 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = SCALE_640x480 | MODE_JPEG},
-       {640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_640x480 | MODE_RAW},
-       {640, 480, V4L2_PIX_FMT_SN9C20X_I420, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 960 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_640x480},
-       {1280, 1024, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 1280,
-               .sizeimage = 1280 * 1024,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
-};
-
-static const struct v4l2_pix_format mono_mode[] = {
-       {160, 120, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_160x120 | MODE_RAW},
-       {320, 240, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 ,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_320x240 | MODE_RAW},
-       {640, 480, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_640x480 | MODE_RAW},
-       {1280, 1024, V4L2_PIX_FMT_GREY, V4L2_FIELD_NONE,
-               .bytesperline = 1280,
-               .sizeimage = 1280 * 1024,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = SCALE_1280x1024 | MODE_RAW | MODE_SXGA},
-};
-
-static const s16 hsv_red_x[] = {
-       41,  44,  46,  48,  50,  52,  54,  56,
-       58,  60,  62,  64,  66,  68,  70,  72,
-       74,  76,  78,  80,  81,  83,  85,  87,
-       88,  90,  92,  93,  95,  97,  98, 100,
-       101, 102, 104, 105, 107, 108, 109, 110,
-       112, 113, 114, 115, 116, 117, 118, 119,
-       120, 121, 122, 123, 123, 124, 125, 125,
-       126, 127, 127, 128, 128, 129, 129, 129,
-       130, 130, 130, 130, 131, 131, 131, 131,
-       131, 131, 131, 131, 130, 130, 130, 130,
-       129, 129, 129, 128, 128, 127, 127, 126,
-       125, 125, 124, 123, 122, 122, 121, 120,
-       119, 118, 117, 116, 115, 114, 112, 111,
-       110, 109, 107, 106, 105, 103, 102, 101,
-       99,  98,  96,  94,  93,  91,  90,  88,
-       86,  84,  83,  81,  79,  77,  75,  74,
-       72,  70,  68,  66,  64,  62,  60,  58,
-       56,  54,  52,  49,  47,  45,  43,  41,
-       39,  36,  34,  32,  30,  28,  25,  23,
-       21,  19,  16,  14,  12,   9,   7,   5,
-       3,   0,  -1,  -3,  -6,  -8, -10, -12,
-       -15, -17, -19, -22, -24, -26, -28, -30,
-       -33, -35, -37, -39, -41, -44, -46, -48,
-       -50, -52, -54, -56, -58, -60, -62, -64,
-       -66, -68, -70, -72, -74, -76, -78, -80,
-       -81, -83, -85, -87, -88, -90, -92, -93,
-       -95, -97, -98, -100, -101, -102, -104, -105,
-       -107, -108, -109, -110, -112, -113, -114, -115,
-       -116, -117, -118, -119, -120, -121, -122, -123,
-       -123, -124, -125, -125, -126, -127, -127, -128,
-       -128, -128, -128, -128, -128, -128, -128, -128,
-       -128, -128, -128, -128, -128, -128, -128, -128,
-       -128, -128, -128, -128, -128, -128, -128, -128,
-       -128, -127, -127, -126, -125, -125, -124, -123,
-       -122, -122, -121, -120, -119, -118, -117, -116,
-       -115, -114, -112, -111, -110, -109, -107, -106,
-       -105, -103, -102, -101, -99, -98, -96, -94,
-       -93, -91, -90, -88, -86, -84, -83, -81,
-       -79, -77, -75, -74, -72, -70, -68, -66,
-       -64, -62, -60, -58, -56, -54, -52, -49,
-       -47, -45, -43, -41, -39, -36, -34, -32,
-       -30, -28, -25, -23, -21, -19, -16, -14,
-       -12,  -9,  -7,  -5,  -3,   0,   1,   3,
-       6,   8,  10,  12,  15,  17,  19,  22,
-       24,  26,  28,  30,  33,  35,  37,  39, 41
-};
-
-static const s16 hsv_red_y[] = {
-       82,  80,  78,  76,  74,  73,  71,  69,
-       67,  65,  63,  61,  58,  56,  54,  52,
-       50,  48,  46,  44,  41,  39,  37,  35,
-       32,  30,  28,  26,  23,  21,  19,  16,
-       14,  12,  10,   7,   5,   3,   0,  -1,
-       -3,  -6,  -8, -10, -13, -15, -17, -19,
-       -22, -24, -26, -29, -31, -33, -35, -38,
-       -40, -42, -44, -46, -48, -51, -53, -55,
-       -57, -59, -61, -63, -65, -67, -69, -71,
-       -73, -75, -77, -79, -81, -82, -84, -86,
-       -88, -89, -91, -93, -94, -96, -98, -99,
-       -101, -102, -104, -105, -106, -108, -109, -110,
-       -112, -113, -114, -115, -116, -117, -119, -120,
-       -120, -121, -122, -123, -124, -125, -126, -126,
-       -127, -128, -128, -128, -128, -128, -128, -128,
-       -128, -128, -128, -128, -128, -128, -128, -128,
-       -128, -128, -128, -128, -128, -128, -128, -128,
-       -128, -128, -128, -128, -128, -128, -128, -128,
-       -127, -127, -126, -125, -125, -124, -123, -122,
-       -121, -120, -119, -118, -117, -116, -115, -114,
-       -113, -111, -110, -109, -107, -106, -105, -103,
-       -102, -100, -99, -97, -96, -94, -92, -91,
-       -89, -87, -85, -84, -82, -80, -78, -76,
-       -74, -73, -71, -69, -67, -65, -63, -61,
-       -58, -56, -54, -52, -50, -48, -46, -44,
-       -41, -39, -37, -35, -32, -30, -28, -26,
-       -23, -21, -19, -16, -14, -12, -10,  -7,
-       -5,  -3,   0,   1,   3,   6,   8,  10,
-       13,  15,  17,  19,  22,  24,  26,  29,
-       31,  33,  35,  38,  40,  42,  44,  46,
-       48,  51,  53,  55,  57,  59,  61,  63,
-       65,  67,  69,  71,  73,  75,  77,  79,
-       81,  82,  84,  86,  88,  89,  91,  93,
-       94,  96,  98,  99, 101, 102, 104, 105,
-       106, 108, 109, 110, 112, 113, 114, 115,
-       116, 117, 119, 120, 120, 121, 122, 123,
-       124, 125, 126, 126, 127, 128, 128, 129,
-       129, 130, 130, 131, 131, 131, 131, 132,
-       132, 132, 132, 132, 132, 132, 132, 132,
-       132, 132, 132, 131, 131, 131, 130, 130,
-       130, 129, 129, 128, 127, 127, 126, 125,
-       125, 124, 123, 122, 121, 120, 119, 118,
-       117, 116, 115, 114, 113, 111, 110, 109,
-       107, 106, 105, 103, 102, 100,  99,  97,
-       96, 94, 92, 91, 89, 87, 85, 84, 82
-};
-
-static const s16 hsv_green_x[] = {
-       -124, -124, -125, -125, -125, -125, -125, -125,
-       -125, -126, -126, -125, -125, -125, -125, -125,
-       -125, -124, -124, -124, -123, -123, -122, -122,
-       -121, -121, -120, -120, -119, -118, -117, -117,
-       -116, -115, -114, -113, -112, -111, -110, -109,
-       -108, -107, -105, -104, -103, -102, -100, -99,
-       -98, -96, -95, -93, -92, -91, -89, -87,
-       -86, -84, -83, -81, -79, -77, -76, -74,
-       -72, -70, -69, -67, -65, -63, -61, -59,
-       -57, -55, -53, -51, -49, -47, -45, -43,
-       -41, -39, -37, -35, -33, -30, -28, -26,
-       -24, -22, -20, -18, -15, -13, -11,  -9,
-       -7,  -4,  -2,   0,   1,   3,   6,   8,
-       10,  12,  14,  17,  19,  21,  23,  25,
-       27,  29,  32,  34,  36,  38,  40,  42,
-       44,  46,  48,  50,  52,  54,  56,  58,
-       60,  62,  64,  66,  68,  70,  71,  73,
-       75,  77,  78,  80,  82,  83,  85,  87,
-       88,  90,  91,  93,  94,  96,  97,  98,
-       100, 101, 102, 104, 105, 106, 107, 108,
-       109, 111, 112, 113, 113, 114, 115, 116,
-       117, 118, 118, 119, 120, 120, 121, 122,
-       122, 123, 123, 124, 124, 124, 125, 125,
-       125, 125, 125, 125, 125, 126, 126, 125,
-       125, 125, 125, 125, 125, 124, 124, 124,
-       123, 123, 122, 122, 121, 121, 120, 120,
-       119, 118, 117, 117, 116, 115, 114, 113,
-       112, 111, 110, 109, 108, 107, 105, 104,
-       103, 102, 100,  99,  98,  96,  95,  93,
-       92,  91,  89,  87,  86,  84,  83,  81,
-       79,  77,  76,  74,  72,  70,  69,  67,
-       65,  63,  61,  59,  57,  55,  53,  51,
-       49,  47,  45,  43,  41,  39,  37,  35,
-       33,  30,  28,  26,  24,  22,  20,  18,
-       15,  13,  11,   9,   7,   4,   2,   0,
-       -1,  -3,  -6,  -8, -10, -12, -14, -17,
-       -19, -21, -23, -25, -27, -29, -32, -34,
-       -36, -38, -40, -42, -44, -46, -48, -50,
-       -52, -54, -56, -58, -60, -62, -64, -66,
-       -68, -70, -71, -73, -75, -77, -78, -80,
-       -82, -83, -85, -87, -88, -90, -91, -93,
-       -94, -96, -97, -98, -100, -101, -102, -104,
-       -105, -106, -107, -108, -109, -111, -112, -113,
-       -113, -114, -115, -116, -117, -118, -118, -119,
-       -120, -120, -121, -122, -122, -123, -123, -124, -124
-};
-
-static const s16 hsv_green_y[] = {
-       -100, -99, -98, -97, -95, -94, -93, -91,
-       -90, -89, -87, -86, -84, -83, -81, -80,
-       -78, -76, -75, -73, -71, -70, -68, -66,
-       -64, -63, -61, -59, -57, -55, -53, -51,
-       -49, -48, -46, -44, -42, -40, -38, -36,
-       -34, -32, -30, -27, -25, -23, -21, -19,
-       -17, -15, -13, -11,  -9,  -7,  -4,  -2,
-       0,   1,   3,   5,   7,   9,  11,  14,
-       16,  18,  20,  22,  24,  26,  28,  30,
-       32,  34,  36,  38,  40,  42,  44,  46,
-       48,  50,  52,  54,  56,  58,  59,  61,
-       63,  65,  67,  68,  70,  72,  74,  75,
-       77,  78,  80,  82,  83,  85,  86,  88,
-       89,  90,  92,  93,  95,  96,  97,  98,
-       100, 101, 102, 103, 104, 105, 106, 107,
-       108, 109, 110, 111, 112, 112, 113, 114,
-       115, 115, 116, 116, 117, 117, 118, 118,
-       119, 119, 119, 120, 120, 120, 120, 120,
-       121, 121, 121, 121, 121, 121, 120, 120,
-       120, 120, 120, 119, 119, 119, 118, 118,
-       117, 117, 116, 116, 115, 114, 114, 113,
-       112, 111, 111, 110, 109, 108, 107, 106,
-       105, 104, 103, 102, 100,  99,  98,  97,
-       95,  94,  93,  91,  90,  89,  87,  86,
-       84,  83,  81,  80,  78,  76,  75,  73,
-       71,  70,  68,  66,  64,  63,  61,  59,
-       57,  55,  53,  51,  49,  48,  46,  44,
-       42,  40,  38,  36,  34,  32,  30,  27,
-       25,  23,  21,  19,  17,  15,  13,  11,
-       9,   7,   4,   2,   0,  -1,  -3,  -5,
-       -7,  -9, -11, -14, -16, -18, -20, -22,
-       -24, -26, -28, -30, -32, -34, -36, -38,
-       -40, -42, -44, -46, -48, -50, -52, -54,
-       -56, -58, -59, -61, -63, -65, -67, -68,
-       -70, -72, -74, -75, -77, -78, -80, -82,
-       -83, -85, -86, -88, -89, -90, -92, -93,
-       -95, -96, -97, -98, -100, -101, -102, -103,
-       -104, -105, -106, -107, -108, -109, -110, -111,
-       -112, -112, -113, -114, -115, -115, -116, -116,
-       -117, -117, -118, -118, -119, -119, -119, -120,
-       -120, -120, -120, -120, -121, -121, -121, -121,
-       -121, -121, -120, -120, -120, -120, -120, -119,
-       -119, -119, -118, -118, -117, -117, -116, -116,
-       -115, -114, -114, -113, -112, -111, -111, -110,
-       -109, -108, -107, -106, -105, -104, -103, -102, -100
-};
-
-static const s16 hsv_blue_x[] = {
-       112, 113, 114, 114, 115, 116, 117, 117,
-       118, 118, 119, 119, 120, 120, 120, 121,
-       121, 121, 122, 122, 122, 122, 122, 122,
-       122, 122, 122, 122, 122, 122, 121, 121,
-       121, 120, 120, 120, 119, 119, 118, 118,
-       117, 116, 116, 115, 114, 113, 113, 112,
-       111, 110, 109, 108, 107, 106, 105, 104,
-       103, 102, 100,  99,  98,  97,  95,  94,
-       93,  91,  90,  88,  87,  85,  84,  82,
-       80,  79,  77,  76,  74,  72,  70,  69,
-       67,  65,  63,  61,  60,  58,  56,  54,
-       52,  50,  48,  46,  44,  42,  40,  38,
-       36,  34,  32,  30,  28,  26,  24,  22,
-       19,  17,  15,  13,  11,   9,   7,   5,
-       2,   0,  -1,  -3,  -5,  -7,  -9, -12,
-       -14, -16, -18, -20, -22, -24, -26, -28,
-       -31, -33, -35, -37, -39, -41, -43, -45,
-       -47, -49, -51, -53, -54, -56, -58, -60,
-       -62, -64, -66, -67, -69, -71, -73, -74,
-       -76, -78, -79, -81, -83, -84, -86, -87,
-       -89, -90, -92, -93, -94, -96, -97, -98,
-       -99, -101, -102, -103, -104, -105, -106, -107,
-       -108, -109, -110, -111, -112, -113, -114, -114,
-       -115, -116, -117, -117, -118, -118, -119, -119,
-       -120, -120, -120, -121, -121, -121, -122, -122,
-       -122, -122, -122, -122, -122, -122, -122, -122,
-       -122, -122, -121, -121, -121, -120, -120, -120,
-       -119, -119, -118, -118, -117, -116, -116, -115,
-       -114, -113, -113, -112, -111, -110, -109, -108,
-       -107, -106, -105, -104, -103, -102, -100, -99,
-       -98, -97, -95, -94, -93, -91, -90, -88,
-       -87, -85, -84, -82, -80, -79, -77, -76,
-       -74, -72, -70, -69, -67, -65, -63, -61,
-       -60, -58, -56, -54, -52, -50, -48, -46,
-       -44, -42, -40, -38, -36, -34, -32, -30,
-       -28, -26, -24, -22, -19, -17, -15, -13,
-       -11,  -9,  -7,  -5,  -2,   0,   1,   3,
-       5,   7,   9,  12,  14,  16,  18,  20,
-       22,  24,  26,  28,  31,  33,  35,  37,
-       39,  41,  43,  45,  47,  49,  51,  53,
-       54,  56,  58,  60,  62,  64,  66,  67,
-       69,  71,  73,  74,  76,  78,  79,  81,
-       83,  84,  86,  87,  89,  90,  92,  93,
-       94,  96,  97,  98,  99, 101, 102, 103,
-       104, 105, 106, 107, 108, 109, 110, 111, 112
-};
-
-static const s16 hsv_blue_y[] = {
-       -11, -13, -15, -17, -19, -21, -23, -25,
-       -27, -29, -31, -33, -35, -37, -39, -41,
-       -43, -45, -46, -48, -50, -52, -54, -55,
-       -57, -59, -61, -62, -64, -66, -67, -69,
-       -71, -72, -74, -75, -77, -78, -80, -81,
-       -83, -84, -86, -87, -88, -90, -91, -92,
-       -93, -95, -96, -97, -98, -99, -100, -101,
-       -102, -103, -104, -105, -106, -106, -107, -108,
-       -109, -109, -110, -111, -111, -112, -112, -113,
-       -113, -114, -114, -114, -115, -115, -115, -115,
-       -116, -116, -116, -116, -116, -116, -116, -116,
-       -116, -115, -115, -115, -115, -114, -114, -114,
-       -113, -113, -112, -112, -111, -111, -110, -110,
-       -109, -108, -108, -107, -106, -105, -104, -103,
-       -102, -101, -100, -99, -98, -97, -96, -95,
-       -94, -93, -91, -90, -89, -88, -86, -85,
-       -84, -82, -81, -79, -78, -76, -75, -73,
-       -71, -70, -68, -67, -65, -63, -62, -60,
-       -58, -56, -55, -53, -51, -49, -47, -45,
-       -44, -42, -40, -38, -36, -34, -32, -30,
-       -28, -26, -24, -22, -20, -18, -16, -14,
-       -12, -10,  -8,  -6,  -4,  -2,   0,   1,
-       3,   5,   7,   9,  11,  13,  15,  17,
-       19,  21,  23,  25,  27,  29,  31,  33,
-       35,  37,  39,  41,  43,  45,  46,  48,
-       50,  52,  54,  55,  57,  59,  61,  62,
-       64,  66,  67,  69,  71,  72,  74,  75,
-       77,  78,  80,  81,  83,  84,  86,  87,
-       88,  90,  91,  92,  93,  95,  96,  97,
-       98,  99, 100, 101, 102, 103, 104, 105,
-       106, 106, 107, 108, 109, 109, 110, 111,
-       111, 112, 112, 113, 113, 114, 114, 114,
-       115, 115, 115, 115, 116, 116, 116, 116,
-       116, 116, 116, 116, 116, 115, 115, 115,
-       115, 114, 114, 114, 113, 113, 112, 112,
-       111, 111, 110, 110, 109, 108, 108, 107,
-       106, 105, 104, 103, 102, 101, 100,  99,
-       98,  97,  96,  95,  94,  93,  91,  90,
-       89,  88,  86,  85,  84,  82,  81,  79,
-       78,  76,  75,  73,  71,  70,  68,  67,
-       65,  63,  62,  60,  58,  56,  55,  53,
-       51,  49,  47,  45,  44,  42,  40,  38,
-       36,  34,  32,  30,  28,  26,  24,  22,
-       20,  18,  16,  14,  12,  10,   8,   6,
-       4,   2,   0,  -1,  -3,  -5,  -7,  -9, -11
-};
-
-static const u16 i2c_ident[] = {
-       V4L2_IDENT_OV9650,
-       V4L2_IDENT_OV9655,
-       V4L2_IDENT_SOI968,
-       V4L2_IDENT_OV7660,
-       V4L2_IDENT_OV7670,
-       V4L2_IDENT_MT9V011,
-       V4L2_IDENT_MT9V111,
-       V4L2_IDENT_MT9V112,
-       V4L2_IDENT_MT9M001C12ST,
-       V4L2_IDENT_MT9M111,
-       V4L2_IDENT_MT9M112,
-       V4L2_IDENT_HV7131R,
-[SENSOR_MT9VPRB] = V4L2_IDENT_UNKNOWN,
-};
-
-static const u16 bridge_init[][2] = {
-       {0x1000, 0x78}, {0x1001, 0x40}, {0x1002, 0x1c},
-       {0x1020, 0x80}, {0x1061, 0x01}, {0x1067, 0x40},
-       {0x1068, 0x30}, {0x1069, 0x20}, {0x106a, 0x10},
-       {0x106b, 0x08}, {0x1188, 0x87}, {0x11a1, 0x00},
-       {0x11a2, 0x00}, {0x11a3, 0x6a}, {0x11a4, 0x50},
-       {0x11ab, 0x00}, {0x11ac, 0x00}, {0x11ad, 0x50},
-       {0x11ae, 0x3c}, {0x118a, 0x04}, {0x0395, 0x04},
-       {0x11b8, 0x3a}, {0x118b, 0x0e}, {0x10f7, 0x05},
-       {0x10f8, 0x14}, {0x10fa, 0xff}, {0x10f9, 0x00},
-       {0x11ba, 0x0a}, {0x11a5, 0x2d}, {0x11a6, 0x2d},
-       {0x11a7, 0x3a}, {0x11a8, 0x05}, {0x11a9, 0x04},
-       {0x11aa, 0x3f}, {0x11af, 0x28}, {0x11b0, 0xd8},
-       {0x11b1, 0x14}, {0x11b2, 0xec}, {0x11b3, 0x32},
-       {0x11b4, 0xdd}, {0x11b5, 0x32}, {0x11b6, 0xdd},
-       {0x10e0, 0x2c}, {0x11bc, 0x40}, {0x11bd, 0x01},
-       {0x11be, 0xf0}, {0x11bf, 0x00}, {0x118c, 0x1f},
-       {0x118d, 0x1f}, {0x118e, 0x1f}, {0x118f, 0x1f},
-       {0x1180, 0x01}, {0x1181, 0x00}, {0x1182, 0x01},
-       {0x1183, 0x00}, {0x1184, 0x50}, {0x1185, 0x80},
-       {0x1007, 0x00}
-};
-
-/* Gain = (bit[3:0] / 16 + 1) * (bit[4] + 1) * (bit[5] + 1) * (bit[6] + 1) */
-static const u8 ov_gain[] = {
-       0x00 /* 1x */, 0x04 /* 1.25x */, 0x08 /* 1.5x */, 0x0c /* 1.75x */,
-       0x10 /* 2x */, 0x12 /* 2.25x */, 0x14 /* 2.5x */, 0x16 /* 2.75x */,
-       0x18 /* 3x */, 0x1a /* 3.25x */, 0x1c /* 3.5x */, 0x1e /* 3.75x */,
-       0x30 /* 4x */, 0x31 /* 4.25x */, 0x32 /* 4.5x */, 0x33 /* 4.75x */,
-       0x34 /* 5x */, 0x35 /* 5.25x */, 0x36 /* 5.5x */, 0x37 /* 5.75x */,
-       0x38 /* 6x */, 0x39 /* 6.25x */, 0x3a /* 6.5x */, 0x3b /* 6.75x */,
-       0x3c /* 7x */, 0x3d /* 7.25x */, 0x3e /* 7.5x */, 0x3f /* 7.75x */,
-       0x70 /* 8x */
-};
-
-/* Gain = (bit[8] + 1) * (bit[7] + 1) * (bit[6:0] * 0.03125) */
-static const u16 micron1_gain[] = {
-       /* 1x   1.25x   1.5x    1.75x */
-       0x0020, 0x0028, 0x0030, 0x0038,
-       /* 2x   2.25x   2.5x    2.75x */
-       0x00a0, 0x00a4, 0x00a8, 0x00ac,
-       /* 3x   3.25x   3.5x    3.75x */
-       0x00b0, 0x00b4, 0x00b8, 0x00bc,
-       /* 4x   4.25x   4.5x    4.75x */
-       0x00c0, 0x00c4, 0x00c8, 0x00cc,
-       /* 5x   5.25x   5.5x    5.75x */
-       0x00d0, 0x00d4, 0x00d8, 0x00dc,
-       /* 6x   6.25x   6.5x    6.75x */
-       0x00e0, 0x00e4, 0x00e8, 0x00ec,
-       /* 7x   7.25x   7.5x    7.75x */
-       0x00f0, 0x00f4, 0x00f8, 0x00fc,
-       /* 8x */
-       0x01c0
-};
-
-/* mt9m001 sensor uses a different gain formula then other micron sensors */
-/* Gain = (bit[6] + 1) * (bit[5-0] * 0.125) */
-static const u16 micron2_gain[] = {
-       /* 1x   1.25x   1.5x    1.75x */
-       0x0008, 0x000a, 0x000c, 0x000e,
-       /* 2x   2.25x   2.5x    2.75x */
-       0x0010, 0x0012, 0x0014, 0x0016,
-       /* 3x   3.25x   3.5x    3.75x */
-       0x0018, 0x001a, 0x001c, 0x001e,
-       /* 4x   4.25x   4.5x    4.75x */
-       0x0020, 0x0051, 0x0052, 0x0053,
-       /* 5x   5.25x   5.5x    5.75x */
-       0x0054, 0x0055, 0x0056, 0x0057,
-       /* 6x   6.25x   6.5x    6.75x */
-       0x0058, 0x0059, 0x005a, 0x005b,
-       /* 7x   7.25x   7.5x    7.75x */
-       0x005c, 0x005d, 0x005e, 0x005f,
-       /* 8x */
-       0x0060
-};
-
-/* Gain = .5 + bit[7:0] / 16 */
-static const u8 hv7131r_gain[] = {
-       0x08 /* 1x */, 0x0c /* 1.25x */, 0x10 /* 1.5x */, 0x14 /* 1.75x */,
-       0x18 /* 2x */, 0x1c /* 2.25x */, 0x20 /* 2.5x */, 0x24 /* 2.75x */,
-       0x28 /* 3x */, 0x2c /* 3.25x */, 0x30 /* 3.5x */, 0x34 /* 3.75x */,
-       0x38 /* 4x */, 0x3c /* 4.25x */, 0x40 /* 4.5x */, 0x44 /* 4.75x */,
-       0x48 /* 5x */, 0x4c /* 5.25x */, 0x50 /* 5.5x */, 0x54 /* 5.75x */,
-       0x58 /* 6x */, 0x5c /* 6.25x */, 0x60 /* 6.5x */, 0x64 /* 6.75x */,
-       0x68 /* 7x */, 0x6c /* 7.25x */, 0x70 /* 7.5x */, 0x74 /* 7.75x */,
-       0x78 /* 8x */
-};
-
-static const struct i2c_reg_u8 soi968_init[] = {
-       {0x0c, 0x00}, {0x0f, 0x1f},
-       {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
-       {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
-       {0x37, 0x04}, {0x45, 0x04}, {0x47, 0xff},
-       {0x3e, 0x00}, {0x3f, 0x00}, {0x3b, 0x20},
-       {0x3a, 0x96}, {0x3d, 0x0a}, {0x14, 0x8e},
-       {0x13, 0x8b}, {0x12, 0x40}, {0x17, 0x13},
-       {0x18, 0x63}, {0x19, 0x01}, {0x1a, 0x79},
-       {0x32, 0x24}, {0x03, 0x00}, {0x11, 0x40},
-       {0x2a, 0x10}, {0x2b, 0xe0}, {0x10, 0x32},
-       {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
-};
-
-static const struct i2c_reg_u8 ov7660_init[] = {
-       {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
-       {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
-       {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
-       /* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
-          0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
-       {0x17, 0x10}, {0x18, 0x61},
-       {0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
-       {0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0x00},
-       {0x2e, 0x00}, {0x01, 0x78}, {0x02, 0x50},
-};
-
-static const struct i2c_reg_u8 ov7670_init[] = {
-       {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
-       {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
-       {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
-       {0xa2, 0x02}, {0x13, 0xe0}, {0x00, 0x00}, {0x10, 0x00},
-       {0x0d, 0x40}, {0x14, 0x28}, {0xa5, 0x05}, {0xab, 0x07},
-       {0x24, 0x95}, {0x25, 0x33}, {0x26, 0xe3}, {0x9f, 0x75},
-       {0xa0, 0x65}, {0xa1, 0x0b}, {0xa6, 0xd8}, {0xa7, 0xd8},
-       {0xa8, 0xf0}, {0xa9, 0x90}, {0xaa, 0x94}, {0x13, 0xe5},
-       {0x0e, 0x61}, {0x0f, 0x4b}, {0x16, 0x02}, {0x1e, 0x27},
-       {0x21, 0x02}, {0x22, 0x91}, {0x29, 0x07}, {0x33, 0x0b},
-       {0x35, 0x0b}, {0x37, 0x1d}, {0x38, 0x71}, {0x39, 0x2a},
-       {0x3c, 0x78}, {0x4d, 0x40}, {0x4e, 0x20}, {0x69, 0x00},
-       {0x74, 0x19}, {0x8d, 0x4f}, {0x8e, 0x00}, {0x8f, 0x00},
-       {0x90, 0x00}, {0x91, 0x00}, {0x96, 0x00}, {0x9a, 0x80},
-       {0xb0, 0x84}, {0xb1, 0x0c}, {0xb2, 0x0e}, {0xb3, 0x82},
-       {0xb8, 0x0a}, {0x43, 0x0a}, {0x44, 0xf0}, {0x45, 0x20},
-       {0x46, 0x7d}, {0x47, 0x29}, {0x48, 0x4a}, {0x59, 0x8c},
-       {0x5a, 0xa5}, {0x5b, 0xde}, {0x5c, 0x96}, {0x5d, 0x66},
-       {0x5e, 0x10}, {0x6c, 0x0a}, {0x6d, 0x55}, {0x6e, 0x11},
-       {0x6f, 0x9e}, {0x6a, 0x40}, {0x01, 0x40}, {0x02, 0x40},
-       {0x13, 0xe7}, {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x02},
-       {0x52, 0x1d}, {0x53, 0x56}, {0x54, 0x73}, {0x55, 0x0a},
-       {0x56, 0x55}, {0x57, 0x80}, {0x58, 0x9e}, {0x41, 0x08},
-       {0x3f, 0x02}, {0x75, 0x03}, {0x76, 0x63}, {0x4c, 0x04},
-       {0x77, 0x06}, {0x3d, 0x02}, {0x4b, 0x09}, {0xc9, 0x30},
-       {0x41, 0x08}, {0x56, 0x48}, {0x34, 0x11}, {0xa4, 0x88},
-       {0x96, 0x00}, {0x97, 0x30}, {0x98, 0x20}, {0x99, 0x30},
-       {0x9a, 0x84}, {0x9b, 0x29}, {0x9c, 0x03}, {0x9d, 0x99},
-       {0x9e, 0x7f}, {0x78, 0x04}, {0x79, 0x01}, {0xc8, 0xf0},
-       {0x79, 0x0f}, {0xc8, 0x00}, {0x79, 0x10}, {0xc8, 0x7e},
-       {0x79, 0x0a}, {0xc8, 0x80}, {0x79, 0x0b}, {0xc8, 0x01},
-       {0x79, 0x0c}, {0xc8, 0x0f}, {0x79, 0x0d}, {0xc8, 0x20},
-       {0x79, 0x09}, {0xc8, 0x80}, {0x79, 0x02}, {0xc8, 0xc0},
-       {0x79, 0x03}, {0xc8, 0x40}, {0x79, 0x05}, {0xc8, 0x30},
-       {0x79, 0x26}, {0x62, 0x20}, {0x63, 0x00}, {0x64, 0x06},
-       {0x65, 0x00}, {0x66, 0x05}, {0x94, 0x05}, {0x95, 0x0a},
-       {0x17, 0x13}, {0x18, 0x01}, {0x19, 0x02}, {0x1a, 0x7a},
-       {0x46, 0x59}, {0x47, 0x30}, {0x58, 0x9a}, {0x59, 0x84},
-       {0x5a, 0x91}, {0x5b, 0x57}, {0x5c, 0x75}, {0x5d, 0x6d},
-       {0x5e, 0x13}, {0x64, 0x07}, {0x94, 0x07}, {0x95, 0x0d},
-       {0xa6, 0xdf}, {0xa7, 0xdf}, {0x48, 0x4d}, {0x51, 0x00},
-       {0x6b, 0x0a}, {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00},
-       {0x92, 0x00}, {0x93, 0x00}, {0x55, 0x0a}, {0x56, 0x60},
-       {0x4f, 0x6e}, {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d},
-       {0x53, 0x56}, {0x54, 0x73}, {0x58, 0x9a}, {0x4f, 0x6e},
-       {0x50, 0x70}, {0x51, 0x00}, {0x52, 0x1d}, {0x53, 0x56},
-       {0x54, 0x73}, {0x58, 0x9a}, {0x3f, 0x01}, {0x7b, 0x03},
-       {0x7c, 0x09}, {0x7d, 0x16}, {0x7e, 0x38}, {0x7f, 0x47},
-       {0x80, 0x53}, {0x81, 0x5e}, {0x82, 0x6a}, {0x83, 0x74},
-       {0x84, 0x80}, {0x85, 0x8c}, {0x86, 0x9b}, {0x87, 0xb2},
-       {0x88, 0xcc}, {0x89, 0xe5}, {0x7a, 0x24}, {0x3b, 0x00},
-       {0x9f, 0x76}, {0xa0, 0x65}, {0x13, 0xe2}, {0x6b, 0x0a},
-       {0x11, 0x80}, {0x2a, 0x00}, {0x2b, 0x00}, {0x92, 0x00},
-       {0x93, 0x00},
-};
-
-static const struct i2c_reg_u8 ov9650_init[] = {
-       {0x00, 0x00}, {0x01, 0x78},
-       {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
-       {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
-       {0x09, 0x01}, {0x0c, 0x00}, {0x0d, 0x00},
-       {0x0e, 0xa0}, {0x0f, 0x52}, {0x10, 0x7c},
-       {0x11, 0x80}, {0x12, 0x45}, {0x13, 0xc2},
-       {0x14, 0x2e}, {0x15, 0x00}, {0x16, 0x07},
-       {0x17, 0x24}, {0x18, 0xc5}, {0x19, 0x00},
-       {0x1a, 0x3c}, {0x1b, 0x00}, {0x1e, 0x04},
-       {0x1f, 0x00}, {0x24, 0x78}, {0x25, 0x68},
-       {0x26, 0xd4}, {0x27, 0x80}, {0x28, 0x80},
-       {0x29, 0x30}, {0x2a, 0x00}, {0x2b, 0x00},
-       {0x2c, 0x80}, {0x2d, 0x00}, {0x2e, 0x00},
-       {0x2f, 0x00}, {0x30, 0x08}, {0x31, 0x30},
-       {0x32, 0x84}, {0x33, 0xe2}, {0x34, 0xbf},
-       {0x35, 0x81}, {0x36, 0xf9}, {0x37, 0x00},
-       {0x38, 0x93}, {0x39, 0x50}, {0x3a, 0x01},
-       {0x3b, 0x01}, {0x3c, 0x73}, {0x3d, 0x19},
-       {0x3e, 0x0b}, {0x3f, 0x80}, {0x40, 0xc1},
-       {0x41, 0x00}, {0x42, 0x08}, {0x67, 0x80},
-       {0x68, 0x80}, {0x69, 0x40}, {0x6a, 0x00},
-       {0x6b, 0x0a}, {0x8b, 0x06}, {0x8c, 0x20},
-       {0x8d, 0x00}, {0x8e, 0x00}, {0x8f, 0xdf},
-       {0x92, 0x00}, {0x93, 0x00}, {0x94, 0x88},
-       {0x95, 0x88}, {0x96, 0x04}, {0xa1, 0x00},
-       {0xa5, 0x80}, {0xa8, 0x80}, {0xa9, 0xb8},
-       {0xaa, 0x92}, {0xab, 0x0a},
-};
-
-static const struct i2c_reg_u8 ov9655_init[] = {
-       {0x0e, 0x61}, {0x11, 0x80}, {0x13, 0xba},
-       {0x14, 0x2e}, {0x16, 0x24}, {0x1e, 0x04}, {0x27, 0x08},
-       {0x28, 0x08}, {0x29, 0x15}, {0x2c, 0x08}, {0x34, 0x3d},
-       {0x35, 0x00}, {0x38, 0x12}, {0x0f, 0x42}, {0x39, 0x57},
-       {0x3a, 0x00}, {0x3b, 0xcc}, {0x3c, 0x0c}, {0x3d, 0x19},
-       {0x3e, 0x0c}, {0x3f, 0x01}, {0x41, 0x40}, {0x42, 0x80},
-       {0x45, 0x46}, {0x46, 0x62}, {0x47, 0x2a}, {0x48, 0x3c},
-       {0x4a, 0xf0}, {0x4b, 0xdc}, {0x4c, 0xdc}, {0x4d, 0xdc},
-       {0x4e, 0xdc}, {0x6c, 0x04}, {0x6f, 0x9e}, {0x70, 0x05},
-       {0x71, 0x78}, {0x77, 0x02}, {0x8a, 0x23}, {0x90, 0x7e},
-       {0x91, 0x7c}, {0x9f, 0x6e}, {0xa0, 0x6e}, {0xa5, 0x68},
-       {0xa6, 0x60}, {0xa8, 0xc1}, {0xa9, 0xfa}, {0xaa, 0x92},
-       {0xab, 0x04}, {0xac, 0x80}, {0xad, 0x80}, {0xae, 0x80},
-       {0xaf, 0x80}, {0xb2, 0xf2}, {0xb3, 0x20}, {0xb5, 0x00},
-       {0xb6, 0xaf}, {0xbb, 0xae}, {0xbc, 0x44}, {0xbd, 0x44},
-       {0xbe, 0x3b}, {0xbf, 0x3a}, {0xc1, 0xc8}, {0xc2, 0x01},
-       {0xc4, 0x00}, {0xc6, 0x85}, {0xc7, 0x81}, {0xc9, 0xe0},
-       {0xca, 0xe8}, {0xcc, 0xd8}, {0xcd, 0x93}, {0x2d, 0x00},
-       {0x2e, 0x00}, {0x01, 0x80}, {0x02, 0x80}, {0x12, 0x61},
-       {0x36, 0xfa}, {0x8c, 0x8d}, {0xc0, 0xaa}, {0x69, 0x0a},
-       {0x03, 0x09}, {0x17, 0x16}, {0x18, 0x6e}, {0x19, 0x01},
-       {0x1a, 0x3e}, {0x32, 0x09}, {0x2a, 0x10}, {0x2b, 0x0a},
-       {0x92, 0x00}, {0x93, 0x00}, {0xa1, 0x00}, {0x10, 0x7c},
-       {0x04, 0x03}, {0x00, 0x13},
-};
-
-static const struct i2c_reg_u16 mt9v112_init[] = {
-       {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
-       {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
-       {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
-       {0x05, 0x0000}, {0x06, 0x340c}, {0x3b, 0x042a},
-       {0x3c, 0x0400}, {0xf0, 0x0002}, {0x2e, 0x0c58},
-       {0x5b, 0x0001}, {0xc8, 0x9f0b}, {0xf0, 0x0001},
-       {0x9b, 0x5300}, {0xf0, 0x0000}, {0x2b, 0x0020},
-       {0x2c, 0x002a}, {0x2d, 0x0032}, {0x2e, 0x0020},
-       {0x09, 0x01dc}, {0x01, 0x000c}, {0x02, 0x0020},
-       {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
-       {0x05, 0x0098}, {0x20, 0x0703}, {0x09, 0x01f2},
-       {0x2b, 0x00a0}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
-       {0x2e, 0x00a0}, {0x01, 0x000c}, {0x02, 0x0020},
-       {0x03, 0x01e0}, {0x04, 0x0280}, {0x06, 0x000c},
-       {0x05, 0x0098}, {0x09, 0x01c1}, {0x2b, 0x00ae},
-       {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
-};
-
-static const struct i2c_reg_u16 mt9v111_init[] = {
-       {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
-       {0x01, 0x0001}, {0x05, 0x0004}, {0x2d, 0xe0a0},
-       {0x2e, 0x0c64}, {0x2f, 0x0064}, {0x06, 0x600e},
-       {0x08, 0x0480}, {0x01, 0x0004}, {0x02, 0x0016},
-       {0x03, 0x01e7}, {0x04, 0x0287}, {0x05, 0x0004},
-       {0x06, 0x002d}, {0x07, 0x3002}, {0x08, 0x0008},
-       {0x0e, 0x0008}, {0x20, 0x0000}
-};
-
-static const struct i2c_reg_u16 mt9v011_init[] = {
-       {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
-       {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
-       {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
-       {0x0d, 0x0002}, {0x0a, 0x0000}, {0x0b, 0x0000},
-       {0x0c, 0x0000}, {0x0d, 0x0000}, {0x0e, 0x0000},
-       {0x0f, 0x0000}, {0x10, 0x0000}, {0x11, 0x0000},
-       {0x12, 0x0000}, {0x13, 0x0000}, {0x14, 0x0000},
-       {0x15, 0x0000}, {0x16, 0x0000}, {0x17, 0x0000},
-       {0x18, 0x0000}, {0x19, 0x0000}, {0x1a, 0x0000},
-       {0x1b, 0x0000}, {0x1c, 0x0000}, {0x1d, 0x0000},
-       {0x32, 0x0000}, {0x20, 0x1101}, {0x21, 0x0000},
-       {0x22, 0x0000}, {0x23, 0x0000}, {0x24, 0x0000},
-       {0x25, 0x0000}, {0x26, 0x0000}, {0x27, 0x0024},
-       {0x2f, 0xf7b0}, {0x30, 0x0005}, {0x31, 0x0000},
-       {0x32, 0x0000}, {0x33, 0x0000}, {0x34, 0x0100},
-       {0x3d, 0x068f}, {0x40, 0x01e0}, {0x41, 0x00d1},
-       {0x44, 0x0082}, {0x5a, 0x0000}, {0x5b, 0x0000},
-       {0x5c, 0x0000}, {0x5d, 0x0000}, {0x5e, 0x0000},
-       {0x5f, 0xa31d}, {0x62, 0x0611}, {0x0a, 0x0000},
-       {0x06, 0x0029}, {0x05, 0x0009}, {0x20, 0x1101},
-       {0x20, 0x1101}, {0x09, 0x0064}, {0x07, 0x0003},
-       {0x2b, 0x0033}, {0x2c, 0x00a0}, {0x2d, 0x00a0},
-       {0x2e, 0x0033}, {0x07, 0x0002}, {0x06, 0x0000},
-       {0x06, 0x0029}, {0x05, 0x0009},
-};
-
-static const struct i2c_reg_u16 mt9m001_init[] = {
-       {0x0d, 0x0001},
-       {0x0d, 0x0000},
-       {0x04, 0x0500},         /* hres = 1280 */
-       {0x03, 0x0400},         /* vres = 1024 */
-       {0x20, 0x1100},
-       {0x06, 0x0010},
-       {0x2b, 0x0024},
-       {0x2e, 0x0024},
-       {0x35, 0x0024},
-       {0x2d, 0x0020},
-       {0x2c, 0x0020},
-       {0x09, 0x0ad4},
-       {0x35, 0x0057},
-};
-
-static const struct i2c_reg_u16 mt9m111_init[] = {
-       {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
-       {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
-       {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
-       {0xf0, 0x0000},
-};
-
-static const struct i2c_reg_u16 mt9m112_init[] = {
-       {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
-       {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
-       {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
-       {0xf0, 0x0000},
-};
-
-static const struct i2c_reg_u8 hv7131r_init[] = {
-       {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
-       {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
-       {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
-       {0x01, 0x08}, {0x01, 0x08}, {0x25, 0x07},
-       {0x26, 0xc3}, {0x27, 0x50}, {0x30, 0x62},
-       {0x31, 0x10}, {0x32, 0x06}, {0x33, 0x10},
-       {0x20, 0x00}, {0x21, 0xd0}, {0x22, 0x00},
-       {0x23, 0x09}, {0x01, 0x08},
-};
-
-static void reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int result;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-                       0x00,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       reg,
-                       0x00,
-                       gspca_dev->usb_buf,
-                       length,
-                       500);
-       if (unlikely(result < 0 || result != length)) {
-               pr_err("Read register %02x failed %d\n", reg, result);
-               gspca_dev->usb_err = result;
-       }
-}
-
-static void reg_w(struct gspca_dev *gspca_dev, u16 reg,
-                const u8 *buffer, int length)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int result;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       memcpy(gspca_dev->usb_buf, buffer, length);
-       result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-                       0x08,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       reg,
-                       0x00,
-                       gspca_dev->usb_buf,
-                       length,
-                       500);
-       if (unlikely(result < 0 || result != length)) {
-               pr_err("Write register %02x failed %d\n", reg, result);
-               gspca_dev->usb_err = result;
-       }
-}
-
-static void reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
-{
-       reg_w(gspca_dev, reg, &value, 1);
-}
-
-static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
-{
-       int i;
-
-       reg_w(gspca_dev, 0x10c0, buffer, 8);
-       for (i = 0; i < 5; i++) {
-               reg_r(gspca_dev, 0x10c0, 1);
-               if (gspca_dev->usb_err < 0)
-                       return;
-               if (gspca_dev->usb_buf[0] & 0x04) {
-                       if (gspca_dev->usb_buf[0] & 0x08) {
-                               pr_err("i2c_w error\n");
-                               gspca_dev->usb_err = -EIO;
-                       }
-                       return;
-               }
-               msleep(10);
-       }
-       pr_err("i2c_w reg %02x no response\n", buffer[2]);
-/*     gspca_dev->usb_err = -EIO;      fixme: may occur */
-}
-
-static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 row[8];
-
-       /*
-        * from the point of view of the bridge, the length
-        * includes the address
-        */
-       row[0] = sd->i2c_intf | (2 << 4);
-       row[1] = sd->i2c_addr;
-       row[2] = reg;
-       row[3] = val;
-       row[4] = 0x00;
-       row[5] = 0x00;
-       row[6] = 0x00;
-       row[7] = 0x10;
-
-       i2c_w(gspca_dev, row);
-}
-
-static void i2c_w1_buf(struct gspca_dev *gspca_dev,
-                       const struct i2c_reg_u8 *buf, int sz)
-{
-       while (--sz >= 0) {
-               i2c_w1(gspca_dev, buf->reg, buf->val);
-               buf++;
-       }
-}
-
-static void i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 row[8];
-
-       /*
-        * from the point of view of the bridge, the length
-        * includes the address
-        */
-       row[0] = sd->i2c_intf | (3 << 4);
-       row[1] = sd->i2c_addr;
-       row[2] = reg;
-       row[3] = val >> 8;
-       row[4] = val;
-       row[5] = 0x00;
-       row[6] = 0x00;
-       row[7] = 0x10;
-
-       i2c_w(gspca_dev, row);
-}
-
-static void i2c_w2_buf(struct gspca_dev *gspca_dev,
-                       const struct i2c_reg_u16 *buf, int sz)
-{
-       while (--sz >= 0) {
-               i2c_w2(gspca_dev, buf->reg, buf->val);
-               buf++;
-       }
-}
-
-static void i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 row[8];
-
-       row[0] = sd->i2c_intf | (1 << 4);
-       row[1] = sd->i2c_addr;
-       row[2] = reg;
-       row[3] = 0;
-       row[4] = 0;
-       row[5] = 0;
-       row[6] = 0;
-       row[7] = 0x10;
-       i2c_w(gspca_dev, row);
-       row[0] = sd->i2c_intf | (1 << 4) | 0x02;
-       row[2] = 0;
-       i2c_w(gspca_dev, row);
-       reg_r(gspca_dev, 0x10c2, 5);
-       *val = gspca_dev->usb_buf[4];
-}
-
-static void i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 row[8];
-
-       row[0] = sd->i2c_intf | (1 << 4);
-       row[1] = sd->i2c_addr;
-       row[2] = reg;
-       row[3] = 0;
-       row[4] = 0;
-       row[5] = 0;
-       row[6] = 0;
-       row[7] = 0x10;
-       i2c_w(gspca_dev, row);
-       row[0] = sd->i2c_intf | (2 << 4) | 0x02;
-       row[2] = 0;
-       i2c_w(gspca_dev, row);
-       reg_r(gspca_dev, 0x10c2, 5);
-       *val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
-}
-
-static void ov9650_init_sensor(struct gspca_dev *gspca_dev)
-{
-       u16 id;
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       i2c_r2(gspca_dev, 0x1c, &id);
-       if (gspca_dev->usb_err < 0)
-               return;
-
-       if (id != 0x7fa2) {
-               pr_err("sensor id for ov9650 doesn't match (0x%04x)\n", id);
-               gspca_dev->usb_err = -ENODEV;
-               return;
-       }
-
-       i2c_w1(gspca_dev, 0x12, 0x80);          /* sensor reset */
-       msleep(200);
-       i2c_w1_buf(gspca_dev, ov9650_init, ARRAY_SIZE(ov9650_init));
-       if (gspca_dev->usb_err < 0)
-               pr_err("OV9650 sensor initialization failed\n");
-       sd->hstart = 1;
-       sd->vstart = 7;
-}
-
-static void ov9655_init_sensor(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       i2c_w1(gspca_dev, 0x12, 0x80);          /* sensor reset */
-       msleep(200);
-       i2c_w1_buf(gspca_dev, ov9655_init, ARRAY_SIZE(ov9655_init));
-       if (gspca_dev->usb_err < 0)
-               pr_err("OV9655 sensor initialization failed\n");
-
-       sd->hstart = 1;
-       sd->vstart = 2;
-}
-
-static void soi968_init_sensor(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       i2c_w1(gspca_dev, 0x12, 0x80);          /* sensor reset */
-       msleep(200);
-       i2c_w1_buf(gspca_dev, soi968_init, ARRAY_SIZE(soi968_init));
-       if (gspca_dev->usb_err < 0)
-               pr_err("SOI968 sensor initialization failed\n");
-
-       sd->hstart = 60;
-       sd->vstart = 11;
-}
-
-static void ov7660_init_sensor(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       i2c_w1(gspca_dev, 0x12, 0x80);          /* sensor reset */
-       msleep(200);
-       i2c_w1_buf(gspca_dev, ov7660_init, ARRAY_SIZE(ov7660_init));
-       if (gspca_dev->usb_err < 0)
-               pr_err("OV7660 sensor initialization failed\n");
-       sd->hstart = 3;
-       sd->vstart = 3;
-}
-
-static void ov7670_init_sensor(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       i2c_w1(gspca_dev, 0x12, 0x80);          /* sensor reset */
-       msleep(200);
-       i2c_w1_buf(gspca_dev, ov7670_init, ARRAY_SIZE(ov7670_init));
-       if (gspca_dev->usb_err < 0)
-               pr_err("OV7670 sensor initialization failed\n");
-
-       sd->hstart = 0;
-       sd->vstart = 1;
-}
-
-static void mt9v_init_sensor(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u16 value;
-
-       sd->i2c_addr = 0x5d;
-       i2c_r2(gspca_dev, 0xff, &value);
-       if (gspca_dev->usb_err >= 0
-        && value == 0x8243) {
-               i2c_w2_buf(gspca_dev, mt9v011_init, ARRAY_SIZE(mt9v011_init));
-               if (gspca_dev->usb_err < 0) {
-                       pr_err("MT9V011 sensor initialization failed\n");
-                       return;
-               }
-               sd->hstart = 2;
-               sd->vstart = 2;
-               sd->sensor = SENSOR_MT9V011;
-               pr_info("MT9V011 sensor detected\n");
-               return;
-       }
-
-       gspca_dev->usb_err = 0;
-       sd->i2c_addr = 0x5c;
-       i2c_w2(gspca_dev, 0x01, 0x0004);
-       i2c_r2(gspca_dev, 0xff, &value);
-       if (gspca_dev->usb_err >= 0
-        && value == 0x823a) {
-               i2c_w2_buf(gspca_dev, mt9v111_init, ARRAY_SIZE(mt9v111_init));
-               if (gspca_dev->usb_err < 0) {
-                       pr_err("MT9V111 sensor initialization failed\n");
-                       return;
-               }
-               sd->hstart = 2;
-               sd->vstart = 2;
-               sd->sensor = SENSOR_MT9V111;
-               pr_info("MT9V111 sensor detected\n");
-               return;
-       }
-
-       gspca_dev->usb_err = 0;
-       sd->i2c_addr = 0x5d;
-       i2c_w2(gspca_dev, 0xf0, 0x0000);
-       if (gspca_dev->usb_err < 0) {
-               gspca_dev->usb_err = 0;
-               sd->i2c_addr = 0x48;
-               i2c_w2(gspca_dev, 0xf0, 0x0000);
-       }
-       i2c_r2(gspca_dev, 0x00, &value);
-       if (gspca_dev->usb_err >= 0
-        && value == 0x1229) {
-               i2c_w2_buf(gspca_dev, mt9v112_init, ARRAY_SIZE(mt9v112_init));
-               if (gspca_dev->usb_err < 0) {
-                       pr_err("MT9V112 sensor initialization failed\n");
-                       return;
-               }
-               sd->hstart = 6;
-               sd->vstart = 2;
-               sd->sensor = SENSOR_MT9V112;
-               pr_info("MT9V112 sensor detected\n");
-               return;
-       }
-
-       gspca_dev->usb_err = -ENODEV;
-}
-
-static void mt9m112_init_sensor(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       i2c_w2_buf(gspca_dev, mt9m112_init, ARRAY_SIZE(mt9m112_init));
-       if (gspca_dev->usb_err < 0)
-               pr_err("MT9M112 sensor initialization failed\n");
-
-       sd->hstart = 0;
-       sd->vstart = 2;
-}
-
-static void mt9m111_init_sensor(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       i2c_w2_buf(gspca_dev, mt9m111_init, ARRAY_SIZE(mt9m111_init));
-       if (gspca_dev->usb_err < 0)
-               pr_err("MT9M111 sensor initialization failed\n");
-
-       sd->hstart = 0;
-       sd->vstart = 2;
-}
-
-static void mt9m001_init_sensor(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u16 id;
-
-       i2c_r2(gspca_dev, 0x00, &id);
-       if (gspca_dev->usb_err < 0)
-               return;
-
-       /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
-       switch (id) {
-       case 0x8411:
-       case 0x8421:
-               pr_info("MT9M001 color sensor detected\n");
-               break;
-       case 0x8431:
-               pr_info("MT9M001 mono sensor detected\n");
-               break;
-       default:
-               pr_err("No MT9M001 chip detected, ID = %x\n\n", id);
-               gspca_dev->usb_err = -ENODEV;
-               return;
-       }
-
-       i2c_w2_buf(gspca_dev, mt9m001_init, ARRAY_SIZE(mt9m001_init));
-       if (gspca_dev->usb_err < 0)
-               pr_err("MT9M001 sensor initialization failed\n");
-
-       sd->hstart = 1;
-       sd->vstart = 1;
-}
-
-static void hv7131r_init_sensor(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       i2c_w1_buf(gspca_dev, hv7131r_init, ARRAY_SIZE(hv7131r_init));
-       if (gspca_dev->usb_err < 0)
-               pr_err("HV7131R Sensor initialization failed\n");
-
-       sd->hstart = 0;
-       sd->vstart = 1;
-}
-
-static void set_cmatrix(struct gspca_dev *gspca_dev,
-               s32 brightness, s32 contrast, s32 satur, s32 hue)
-{
-       s32 hue_coord, hue_index = 180 + hue;
-       u8 cmatrix[21];
-
-       memset(cmatrix, 0, sizeof cmatrix);
-       cmatrix[2] = (contrast * 0x25 / 0x100) + 0x26;
-       cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
-       cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
-       cmatrix[18] = brightness - 0x80;
-
-       hue_coord = (hsv_red_x[hue_index] * satur) >> 8;
-       cmatrix[6] = hue_coord;
-       cmatrix[7] = (hue_coord >> 8) & 0x0f;
-
-       hue_coord = (hsv_red_y[hue_index] * satur) >> 8;
-       cmatrix[8] = hue_coord;
-       cmatrix[9] = (hue_coord >> 8) & 0x0f;
-
-       hue_coord = (hsv_green_x[hue_index] * satur) >> 8;
-       cmatrix[10] = hue_coord;
-       cmatrix[11] = (hue_coord >> 8) & 0x0f;
-
-       hue_coord = (hsv_green_y[hue_index] * satur) >> 8;
-       cmatrix[12] = hue_coord;
-       cmatrix[13] = (hue_coord >> 8) & 0x0f;
-
-       hue_coord = (hsv_blue_x[hue_index] * satur) >> 8;
-       cmatrix[14] = hue_coord;
-       cmatrix[15] = (hue_coord >> 8) & 0x0f;
-
-       hue_coord = (hsv_blue_y[hue_index] * satur) >> 8;
-       cmatrix[16] = hue_coord;
-       cmatrix[17] = (hue_coord >> 8) & 0x0f;
-
-       reg_w(gspca_dev, 0x10e1, cmatrix, 21);
-}
-
-static void set_gamma(struct gspca_dev *gspca_dev, s32 val)
-{
-       u8 gamma[17];
-       u8 gval = val * 0xb8 / 0x100;
-
-       gamma[0] = 0x0a;
-       gamma[1] = 0x13 + (gval * (0xcb - 0x13) / 0xb8);
-       gamma[2] = 0x25 + (gval * (0xee - 0x25) / 0xb8);
-       gamma[3] = 0x37 + (gval * (0xfa - 0x37) / 0xb8);
-       gamma[4] = 0x45 + (gval * (0xfc - 0x45) / 0xb8);
-       gamma[5] = 0x55 + (gval * (0xfb - 0x55) / 0xb8);
-       gamma[6] = 0x65 + (gval * (0xfc - 0x65) / 0xb8);
-       gamma[7] = 0x74 + (gval * (0xfd - 0x74) / 0xb8);
-       gamma[8] = 0x83 + (gval * (0xfe - 0x83) / 0xb8);
-       gamma[9] = 0x92 + (gval * (0xfc - 0x92) / 0xb8);
-       gamma[10] = 0xa1 + (gval * (0xfc - 0xa1) / 0xb8);
-       gamma[11] = 0xb0 + (gval * (0xfc - 0xb0) / 0xb8);
-       gamma[12] = 0xbf + (gval * (0xfb - 0xbf) / 0xb8);
-       gamma[13] = 0xce + (gval * (0xfb - 0xce) / 0xb8);
-       gamma[14] = 0xdf + (gval * (0xfd - 0xdf) / 0xb8);
-       gamma[15] = 0xea + (gval * (0xf9 - 0xea) / 0xb8);
-       gamma[16] = 0xf5;
-
-       reg_w(gspca_dev, 0x1190, gamma, 17);
-}
-
-static void set_redblue(struct gspca_dev *gspca_dev, s32 blue, s32 red)
-{
-       reg_w1(gspca_dev, 0x118c, red);
-       reg_w1(gspca_dev, 0x118f, blue);
-}
-
-static void set_hvflip(struct gspca_dev *gspca_dev, s32 hflip, s32 vflip)
-{
-       u8 value, tslb;
-       u16 value2;
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if ((sd->flags & FLIP_DETECT) && dmi_check_system(flip_dmi_table)) {
-               hflip = !hflip;
-               vflip = !vflip;
-       }
-
-       switch (sd->sensor) {
-       case SENSOR_OV7660:
-               value = 0x01;
-               if (hflip)
-                       value |= 0x20;
-               if (vflip) {
-                       value |= 0x10;
-                       sd->vstart = 2;
-               } else {
-                       sd->vstart = 3;
-               }
-               reg_w1(gspca_dev, 0x1182, sd->vstart);
-               i2c_w1(gspca_dev, 0x1e, value);
-               break;
-       case SENSOR_OV9650:
-               i2c_r1(gspca_dev, 0x1e, &value);
-               value &= ~0x30;
-               tslb = 0x01;
-               if (hflip)
-                       value |= 0x20;
-               if (vflip) {
-                       value |= 0x10;
-                       tslb = 0x49;
-               }
-               i2c_w1(gspca_dev, 0x1e, value);
-               i2c_w1(gspca_dev, 0x3a, tslb);
-               break;
-       case SENSOR_MT9V111:
-       case SENSOR_MT9V011:
-               i2c_r2(gspca_dev, 0x20, &value2);
-               value2 &= ~0xc0a0;
-               if (hflip)
-                       value2 |= 0x8080;
-               if (vflip)
-                       value2 |= 0x4020;
-               i2c_w2(gspca_dev, 0x20, value2);
-               break;
-       case SENSOR_MT9M112:
-       case SENSOR_MT9M111:
-       case SENSOR_MT9V112:
-               i2c_r2(gspca_dev, 0x20, &value2);
-               value2 &= ~0x0003;
-               if (hflip)
-                       value2 |= 0x0002;
-               if (vflip)
-                       value2 |= 0x0001;
-               i2c_w2(gspca_dev, 0x20, value2);
-               break;
-       case SENSOR_HV7131R:
-               i2c_r1(gspca_dev, 0x01, &value);
-               value &= ~0x03;
-               if (vflip)
-                       value |= 0x01;
-               if (hflip)
-                       value |= 0x02;
-               i2c_w1(gspca_dev, 0x01, value);
-               break;
-       }
-}
-
-static void set_exposure(struct gspca_dev *gspca_dev, s32 expo)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 exp[8] = {sd->i2c_intf, sd->i2c_addr,
-                               0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
-       int expo2;
-
-       if (gspca_dev->streaming)
-               exp[7] = 0x1e;
-
-       switch (sd->sensor) {
-       case SENSOR_OV7660:
-       case SENSOR_OV7670:
-       case SENSOR_OV9655:
-       case SENSOR_OV9650:
-               if (expo > 547)
-                       expo2 = 547;
-               else
-                       expo2 = expo;
-               exp[0] |= (2 << 4);
-               exp[2] = 0x10;                  /* AECH */
-               exp[3] = expo2 >> 2;
-               exp[7] = 0x10;
-               i2c_w(gspca_dev, exp);
-               exp[2] = 0x04;                  /* COM1 */
-               exp[3] = expo2 & 0x0003;
-               exp[7] = 0x10;
-               i2c_w(gspca_dev, exp);
-               expo -= expo2;
-               exp[7] = 0x1e;
-               exp[0] |= (3 << 4);
-               exp[2] = 0x2d;                  /* ADVFL & ADVFH */
-               exp[3] = expo;
-               exp[4] = expo >> 8;
-               break;
-       case SENSOR_MT9M001:
-       case SENSOR_MT9V112:
-       case SENSOR_MT9V011:
-               exp[0] |= (3 << 4);
-               exp[2] = 0x09;
-               exp[3] = expo >> 8;
-               exp[4] = expo;
-               break;
-       case SENSOR_HV7131R:
-               exp[0] |= (4 << 4);
-               exp[2] = 0x25;
-               exp[3] = expo >> 5;
-               exp[4] = expo << 3;
-               exp[5] = 0;
-               break;
-       default:
-               return;
-       }
-       i2c_w(gspca_dev, exp);
-}
-
-static void set_gain(struct gspca_dev *gspca_dev, s32 g)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 gain[8] = {sd->i2c_intf, sd->i2c_addr,
-                               0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
-
-       if (gspca_dev->streaming)
-               gain[7] = 0x15;         /* or 1d ? */
-
-       switch (sd->sensor) {
-       case SENSOR_OV7660:
-       case SENSOR_OV7670:
-       case SENSOR_SOI968:
-       case SENSOR_OV9655:
-       case SENSOR_OV9650:
-               gain[0] |= (2 << 4);
-               gain[3] = ov_gain[g];
-               break;
-       case SENSOR_MT9V011:
-               gain[0] |= (3 << 4);
-               gain[2] = 0x35;
-               gain[3] = micron1_gain[g] >> 8;
-               gain[4] = micron1_gain[g];
-               break;
-       case SENSOR_MT9V112:
-               gain[0] |= (3 << 4);
-               gain[2] = 0x2f;
-               gain[3] = micron1_gain[g] >> 8;
-               gain[4] = micron1_gain[g];
-               break;
-       case SENSOR_MT9M001:
-               gain[0] |= (3 << 4);
-               gain[2] = 0x2f;
-               gain[3] = micron2_gain[g] >> 8;
-               gain[4] = micron2_gain[g];
-               break;
-       case SENSOR_HV7131R:
-               gain[0] |= (2 << 4);
-               gain[2] = 0x30;
-               gain[3] = hv7131r_gain[g];
-               break;
-       default:
-               return;
-       }
-       i2c_w(gspca_dev, gain);
-}
-
-static void set_quality(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       jpeg_set_qual(sd->jpeg_hdr, val);
-       reg_w1(gspca_dev, 0x1061, 0x01);        /* stop transfer */
-       reg_w1(gspca_dev, 0x10e0, sd->fmt | 0x20); /* write QTAB */
-       reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
-       reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
-       reg_w1(gspca_dev, 0x1061, 0x03);        /* restart transfer */
-       reg_w1(gspca_dev, 0x10e0, sd->fmt);
-       sd->fmt ^= 0x0c;                        /* invert QTAB use + write */
-       reg_w1(gspca_dev, 0x10e0, sd->fmt);
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int sd_dbg_g_register(struct gspca_dev *gspca_dev,
-                       struct v4l2_dbg_register *reg)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (reg->match.type) {
-       case V4L2_CHIP_MATCH_HOST:
-               if (reg->match.addr != 0)
-                       return -EINVAL;
-               if (reg->reg < 0x1000 || reg->reg > 0x11ff)
-                       return -EINVAL;
-               reg_r(gspca_dev, reg->reg, 1);
-               reg->val = gspca_dev->usb_buf[0];
-               return gspca_dev->usb_err;
-       case V4L2_CHIP_MATCH_I2C_ADDR:
-               if (reg->match.addr != sd->i2c_addr)
-                       return -EINVAL;
-               if (sd->sensor >= SENSOR_MT9V011 &&
-                   sd->sensor <= SENSOR_MT9M112) {
-                       i2c_r2(gspca_dev, reg->reg, (u16 *) &reg->val);
-               } else {
-                       i2c_r1(gspca_dev, reg->reg, (u8 *) &reg->val);
-               }
-               return gspca_dev->usb_err;
-       }
-       return -EINVAL;
-}
-
-static int sd_dbg_s_register(struct gspca_dev *gspca_dev,
-                       struct v4l2_dbg_register *reg)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (reg->match.type) {
-       case V4L2_CHIP_MATCH_HOST:
-               if (reg->match.addr != 0)
-                       return -EINVAL;
-               if (reg->reg < 0x1000 || reg->reg > 0x11ff)
-                       return -EINVAL;
-               reg_w1(gspca_dev, reg->reg, reg->val);
-               return gspca_dev->usb_err;
-       case V4L2_CHIP_MATCH_I2C_ADDR:
-               if (reg->match.addr != sd->i2c_addr)
-                       return -EINVAL;
-               if (sd->sensor >= SENSOR_MT9V011 &&
-                   sd->sensor <= SENSOR_MT9M112) {
-                       i2c_w2(gspca_dev, reg->reg, reg->val);
-               } else {
-                       i2c_w1(gspca_dev, reg->reg, reg->val);
-               }
-               return gspca_dev->usb_err;
-       }
-       return -EINVAL;
-}
-#endif
-
-static int sd_chip_ident(struct gspca_dev *gspca_dev,
-                       struct v4l2_dbg_chip_ident *chip)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (chip->match.type) {
-       case V4L2_CHIP_MATCH_HOST:
-               if (chip->match.addr != 0)
-                       return -EINVAL;
-               chip->revision = 0;
-               chip->ident = V4L2_IDENT_SN9C20X;
-               return 0;
-       case V4L2_CHIP_MATCH_I2C_ADDR:
-               if (chip->match.addr != sd->i2c_addr)
-                       return -EINVAL;
-               chip->revision = 0;
-               chip->ident = i2c_ident[sd->sensor];
-               return 0;
-       }
-       return -EINVAL;
-}
-
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-
-       cam = &gspca_dev->cam;
-       cam->needs_full_bandwidth = 1;
-
-       sd->sensor = id->driver_info >> 8;
-       sd->i2c_addr = id->driver_info;
-       sd->flags = id->driver_info >> 16;
-       sd->i2c_intf = 0x80;                    /* i2c 100 Kb/s */
-
-       switch (sd->sensor) {
-       case SENSOR_MT9M112:
-       case SENSOR_MT9M111:
-       case SENSOR_OV9650:
-       case SENSOR_SOI968:
-               cam->cam_mode = sxga_mode;
-               cam->nmodes = ARRAY_SIZE(sxga_mode);
-               break;
-       case SENSOR_MT9M001:
-               cam->cam_mode = mono_mode;
-               cam->nmodes = ARRAY_SIZE(mono_mode);
-               break;
-       case SENSOR_HV7131R:
-               sd->i2c_intf = 0x81;                    /* i2c 400 Kb/s */
-               /* fall thru */
-       default:
-               cam->cam_mode = vga_mode;
-               cam->nmodes = ARRAY_SIZE(vga_mode);
-               break;
-       }
-
-       sd->old_step = 0;
-       sd->older_step = 0;
-       sd->exposure_step = 16;
-
-       INIT_WORK(&sd->work, qual_upd);
-
-       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) {
-       /* color control cluster */
-       case V4L2_CID_BRIGHTNESS:
-               set_cmatrix(gspca_dev, sd->brightness->val,
-                       sd->contrast->val, sd->saturation->val, sd->hue->val);
-               break;
-       case V4L2_CID_GAMMA:
-               set_gamma(gspca_dev, ctrl->val);
-               break;
-       /* blue/red balance cluster */
-       case V4L2_CID_BLUE_BALANCE:
-               set_redblue(gspca_dev, sd->blue->val, sd->red->val);
-               break;
-       /* h/vflip cluster */
-       case V4L2_CID_HFLIP:
-               set_hvflip(gspca_dev, sd->hflip->val, sd->vflip->val);
-               break;
-       /* standalone exposure control */
-       case V4L2_CID_EXPOSURE:
-               set_exposure(gspca_dev, ctrl->val);
-               break;
-       /* standalone gain control */
-       case V4L2_CID_GAIN:
-               set_gain(gspca_dev, ctrl->val);
-               break;
-       /* autogain + exposure or gain control cluster */
-       case V4L2_CID_AUTOGAIN:
-               if (sd->sensor == SENSOR_SOI968)
-                       set_gain(gspca_dev, sd->gain->val);
-               else
-                       set_exposure(gspca_dev, sd->exposure->val);
-               break;
-       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
-               set_quality(gspca_dev, ctrl->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, 13);
-
-       sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
-       sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 255, 1, 127);
-       sd->saturation = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 255, 1, 127);
-       sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_HUE, -180, 180, 1, 0);
-
-       sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAMMA, 0, 255, 1, 0x10);
-
-       sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BLUE_BALANCE, 0, 127, 1, 0x28);
-       sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_RED_BALANCE, 0, 127, 1, 0x28);
-
-       if (sd->sensor != SENSOR_OV9655 && sd->sensor != SENSOR_SOI968 &&
-           sd->sensor != SENSOR_OV7670 && sd->sensor != SENSOR_MT9M001 &&
-           sd->sensor != SENSOR_MT9VPRB) {
-               sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_HFLIP, 0, 1, 1, 0);
-               sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_VFLIP, 0, 1, 1, 0);
-       }
-
-       if (sd->sensor != SENSOR_SOI968 && sd->sensor != SENSOR_MT9VPRB &&
-           sd->sensor != SENSOR_MT9M112 && sd->sensor != SENSOR_MT9M111 &&
-           sd->sensor != SENSOR_MT9V111)
-               sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 0, 0x1780, 1, 0x33);
-
-       if (sd->sensor != SENSOR_MT9VPRB && sd->sensor != SENSOR_MT9M112 &&
-           sd->sensor != SENSOR_MT9M111 && sd->sensor != SENSOR_MT9V111) {
-               sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAIN, 0, 28, 1, 0);
-               sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-       }
-
-       sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_JPEG_COMPRESSION_QUALITY, 50, 90, 1, 80);
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-
-       v4l2_ctrl_cluster(4, &sd->brightness);
-       v4l2_ctrl_cluster(2, &sd->blue);
-       if (sd->hflip)
-               v4l2_ctrl_cluster(2, &sd->hflip);
-       if (sd->autogain) {
-               if (sd->sensor == SENSOR_SOI968)
-                       /* this sensor doesn't have the exposure control and
-                          autogain is clustered with gain instead. This works
-                          because sd->exposure == NULL. */
-                       v4l2_ctrl_auto_cluster(3, &sd->autogain, 0, false);
-               else
-                       /* Otherwise autogain is clustered with exposure. */
-                       v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, false);
-       }
-       return 0;
-}
-
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i;
-       u8 value;
-       u8 i2c_init[9] =
-               {0x80, sd->i2c_addr, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
-
-       for (i = 0; i < ARRAY_SIZE(bridge_init); i++) {
-               value = bridge_init[i][1];
-               reg_w(gspca_dev, bridge_init[i][0], &value, 1);
-               if (gspca_dev->usb_err < 0) {
-                       pr_err("Device initialization failed\n");
-                       return gspca_dev->usb_err;
-               }
-       }
-
-       if (sd->flags & LED_REVERSE)
-               reg_w1(gspca_dev, 0x1006, 0x00);
-       else
-               reg_w1(gspca_dev, 0x1006, 0x20);
-
-       reg_w(gspca_dev, 0x10c0, i2c_init, 9);
-       if (gspca_dev->usb_err < 0) {
-               pr_err("Device initialization failed\n");
-               return gspca_dev->usb_err;
-       }
-
-       switch (sd->sensor) {
-       case SENSOR_OV9650:
-               ov9650_init_sensor(gspca_dev);
-               if (gspca_dev->usb_err < 0)
-                       break;
-               pr_info("OV9650 sensor detected\n");
-               break;
-       case SENSOR_OV9655:
-               ov9655_init_sensor(gspca_dev);
-               if (gspca_dev->usb_err < 0)
-                       break;
-               pr_info("OV9655 sensor detected\n");
-               break;
-       case SENSOR_SOI968:
-               soi968_init_sensor(gspca_dev);
-               if (gspca_dev->usb_err < 0)
-                       break;
-               pr_info("SOI968 sensor detected\n");
-               break;
-       case SENSOR_OV7660:
-               ov7660_init_sensor(gspca_dev);
-               if (gspca_dev->usb_err < 0)
-                       break;
-               pr_info("OV7660 sensor detected\n");
-               break;
-       case SENSOR_OV7670:
-               ov7670_init_sensor(gspca_dev);
-               if (gspca_dev->usb_err < 0)
-                       break;
-               pr_info("OV7670 sensor detected\n");
-               break;
-       case SENSOR_MT9VPRB:
-               mt9v_init_sensor(gspca_dev);
-               if (gspca_dev->usb_err < 0)
-                       break;
-               pr_info("MT9VPRB sensor detected\n");
-               break;
-       case SENSOR_MT9M111:
-               mt9m111_init_sensor(gspca_dev);
-               if (gspca_dev->usb_err < 0)
-                       break;
-               pr_info("MT9M111 sensor detected\n");
-               break;
-       case SENSOR_MT9M112:
-               mt9m112_init_sensor(gspca_dev);
-               if (gspca_dev->usb_err < 0)
-                       break;
-               pr_info("MT9M112 sensor detected\n");
-               break;
-       case SENSOR_MT9M001:
-               mt9m001_init_sensor(gspca_dev);
-               if (gspca_dev->usb_err < 0)
-                       break;
-               break;
-       case SENSOR_HV7131R:
-               hv7131r_init_sensor(gspca_dev);
-               if (gspca_dev->usb_err < 0)
-                       break;
-               pr_info("HV7131R sensor detected\n");
-               break;
-       default:
-               pr_err("Unsupported sensor\n");
-               gspca_dev->usb_err = -ENODEV;
-       }
-       return gspca_dev->usb_err;
-}
-
-static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 value;
-
-       switch (sd->sensor) {
-       case SENSOR_SOI968:
-               if (mode & MODE_SXGA) {
-                       i2c_w1(gspca_dev, 0x17, 0x1d);
-                       i2c_w1(gspca_dev, 0x18, 0xbd);
-                       i2c_w1(gspca_dev, 0x19, 0x01);
-                       i2c_w1(gspca_dev, 0x1a, 0x81);
-                       i2c_w1(gspca_dev, 0x12, 0x00);
-                       sd->hstart = 140;
-                       sd->vstart = 19;
-               } else {
-                       i2c_w1(gspca_dev, 0x17, 0x13);
-                       i2c_w1(gspca_dev, 0x18, 0x63);
-                       i2c_w1(gspca_dev, 0x19, 0x01);
-                       i2c_w1(gspca_dev, 0x1a, 0x79);
-                       i2c_w1(gspca_dev, 0x12, 0x40);
-                       sd->hstart = 60;
-                       sd->vstart = 11;
-               }
-               break;
-       case SENSOR_OV9650:
-               if (mode & MODE_SXGA) {
-                       i2c_w1(gspca_dev, 0x17, 0x1b);
-                       i2c_w1(gspca_dev, 0x18, 0xbc);
-                       i2c_w1(gspca_dev, 0x19, 0x01);
-                       i2c_w1(gspca_dev, 0x1a, 0x82);
-                       i2c_r1(gspca_dev, 0x12, &value);
-                       i2c_w1(gspca_dev, 0x12, value & 0x07);
-               } else {
-                       i2c_w1(gspca_dev, 0x17, 0x24);
-                       i2c_w1(gspca_dev, 0x18, 0xc5);
-                       i2c_w1(gspca_dev, 0x19, 0x00);
-                       i2c_w1(gspca_dev, 0x1a, 0x3c);
-                       i2c_r1(gspca_dev, 0x12, &value);
-                       i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
-               }
-               break;
-       case SENSOR_MT9M112:
-       case SENSOR_MT9M111:
-               if (mode & MODE_SXGA) {
-                       i2c_w2(gspca_dev, 0xf0, 0x0002);
-                       i2c_w2(gspca_dev, 0xc8, 0x970b);
-                       i2c_w2(gspca_dev, 0xf0, 0x0000);
-               } else {
-                       i2c_w2(gspca_dev, 0xf0, 0x0002);
-                       i2c_w2(gspca_dev, 0xc8, 0x8000);
-                       i2c_w2(gspca_dev, 0xf0, 0x0000);
-               }
-               break;
-       }
-}
-
-static int sd_isoc_init(struct gspca_dev *gspca_dev)
-{
-       struct usb_interface *intf;
-       u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv;
-
-       /*
-        * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth
-        * than our regular bandwidth calculations reserve, so we force the
-        * use of a specific altsetting when using the SN9C20X_I420 fmt.
-        */
-       if (!(flags & (MODE_RAW | MODE_JPEG))) {
-               intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
-
-               if (intf->num_altsetting != 9) {
-                       pr_warn("sn9c20x camera with unknown number of alt "
-                               "settings (%d), please report!\n",
-                               intf->num_altsetting);
-                       gspca_dev->alt = intf->num_altsetting;
-                       return 0;
-               }
-
-               switch (gspca_dev->width) {
-               case 160: /* 160x120 */
-                       gspca_dev->alt = 2;
-                       break;
-               case 320: /* 320x240 */
-                       gspca_dev->alt = 6;
-                       break;
-               default:  /* >= 640x480 */
-                       gspca_dev->alt = 9;
-                       break;
-               }
-       }
-
-       return 0;
-}
-
-#define HW_WIN(mode, hstart, vstart) \
-((const u8 []){hstart, 0, vstart, 0, \
-(mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
-(mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
-
-#define CLR_WIN(width, height) \
-((const u8 [])\
-{0, width >> 2, 0, height >> 1,\
-((width >> 10) & 0x01) | ((height >> 8) & 0x6)})
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
-       int width = gspca_dev->width;
-       int height = gspca_dev->height;
-       u8 fmt, scale = 0;
-
-       jpeg_define(sd->jpeg_hdr, height, width,
-                       0x21);
-       jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
-
-       if (mode & MODE_RAW)
-               fmt = 0x2d;
-       else if (mode & MODE_JPEG)
-               fmt = 0x24;
-       else
-               fmt = 0x2f;     /* YUV 420 */
-       sd->fmt = fmt;
-
-       switch (mode & SCALE_MASK) {
-       case SCALE_1280x1024:
-               scale = 0xc0;
-               pr_info("Set 1280x1024\n");
-               break;
-       case SCALE_640x480:
-               scale = 0x80;
-               pr_info("Set 640x480\n");
-               break;
-       case SCALE_320x240:
-               scale = 0x90;
-               pr_info("Set 320x240\n");
-               break;
-       case SCALE_160x120:
-               scale = 0xa0;
-               pr_info("Set 160x120\n");
-               break;
-       }
-
-       configure_sensor_output(gspca_dev, mode);
-       reg_w(gspca_dev, 0x1100, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
-       reg_w(gspca_dev, 0x1140, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
-       reg_w(gspca_dev, 0x10fb, CLR_WIN(width, height), 5);
-       reg_w(gspca_dev, 0x1180, HW_WIN(mode, sd->hstart, sd->vstart), 6);
-       reg_w1(gspca_dev, 0x1189, scale);
-       reg_w1(gspca_dev, 0x10e0, fmt);
-
-       set_cmatrix(gspca_dev, v4l2_ctrl_g_ctrl(sd->brightness),
-                       v4l2_ctrl_g_ctrl(sd->contrast),
-                       v4l2_ctrl_g_ctrl(sd->saturation),
-                       v4l2_ctrl_g_ctrl(sd->hue));
-       set_gamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
-       set_redblue(gspca_dev, v4l2_ctrl_g_ctrl(sd->blue),
-                       v4l2_ctrl_g_ctrl(sd->red));
-       if (sd->gain)
-               set_gain(gspca_dev, v4l2_ctrl_g_ctrl(sd->gain));
-       if (sd->exposure)
-               set_exposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
-       if (sd->hflip)
-               set_hvflip(gspca_dev, v4l2_ctrl_g_ctrl(sd->hflip),
-                               v4l2_ctrl_g_ctrl(sd->vflip));
-
-       reg_w1(gspca_dev, 0x1007, 0x20);
-       reg_w1(gspca_dev, 0x1061, 0x03);
-
-       /* if JPEG, prepare the compression quality update */
-       if (mode & MODE_JPEG) {
-               sd->pktsz = sd->npkt = 0;
-               sd->nchg = 0;
-               sd->work_thread =
-                       create_singlethread_workqueue(KBUILD_MODNAME);
-       }
-
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       reg_w1(gspca_dev, 0x1007, 0x00);
-       reg_w1(gspca_dev, 0x1061, 0x01);
-}
-
-/* called on streamoff with alt==0 and on disconnect */
-/* the usb_lock is held at entry - restore on exit */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->work_thread != NULL) {
-               mutex_unlock(&gspca_dev->usb_lock);
-               destroy_workqueue(sd->work_thread);
-               mutex_lock(&gspca_dev->usb_lock);
-               sd->work_thread = NULL;
-       }
-}
-
-static void do_autoexposure(struct gspca_dev *gspca_dev, u16 avg_lum)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 cur_exp = v4l2_ctrl_g_ctrl(sd->exposure);
-       s32 max = sd->exposure->maximum - sd->exposure_step;
-       s32 min = sd->exposure->minimum + sd->exposure_step;
-       s16 new_exp;
-
-       /*
-        * some hardcoded values are present
-        * like those for maximal/minimal exposure
-        * and exposure steps
-        */
-       if (avg_lum < MIN_AVG_LUM) {
-               if (cur_exp > max)
-                       return;
-
-               new_exp = cur_exp + sd->exposure_step;
-               if (new_exp > max)
-                       new_exp = max;
-               if (new_exp < min)
-                       new_exp = min;
-               v4l2_ctrl_s_ctrl(sd->exposure, new_exp);
-
-               sd->older_step = sd->old_step;
-               sd->old_step = 1;
-
-               if (sd->old_step ^ sd->older_step)
-                       sd->exposure_step /= 2;
-               else
-                       sd->exposure_step += 2;
-       }
-       if (avg_lum > MAX_AVG_LUM) {
-               if (cur_exp < min)
-                       return;
-               new_exp = cur_exp - sd->exposure_step;
-               if (new_exp > max)
-                       new_exp = max;
-               if (new_exp < min)
-                       new_exp = min;
-               v4l2_ctrl_s_ctrl(sd->exposure, new_exp);
-               sd->older_step = sd->old_step;
-               sd->old_step = 0;
-
-               if (sd->old_step ^ sd->older_step)
-                       sd->exposure_step /= 2;
-               else
-                       sd->exposure_step += 2;
-       }
-}
-
-static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 cur_gain = v4l2_ctrl_g_ctrl(sd->gain);
-
-       if (avg_lum < MIN_AVG_LUM && cur_gain < sd->gain->maximum)
-               v4l2_ctrl_s_ctrl(sd->gain, cur_gain + 1);
-       if (avg_lum > MAX_AVG_LUM && cur_gain > sd->gain->minimum)
-               v4l2_ctrl_s_ctrl(sd->gain, cur_gain - 1);
-}
-
-static void sd_dqcallback(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int avg_lum;
-
-       if (sd->autogain == NULL || !v4l2_ctrl_g_ctrl(sd->autogain))
-               return;
-
-       avg_lum = atomic_read(&sd->avg_lum);
-       if (sd->sensor == SENSOR_SOI968)
-               do_autogain(gspca_dev, avg_lum);
-       else
-               do_autoexposure(gspca_dev, avg_lum);
-}
-
-/* JPEG quality update */
-/* This function is executed from a work queue. */
-static void qual_upd(struct work_struct *work)
-{
-       struct sd *sd = container_of(work, struct sd, work);
-       struct gspca_dev *gspca_dev = &sd->gspca_dev;
-       s32 qual = v4l2_ctrl_g_ctrl(sd->jpegqual);
-
-       mutex_lock(&gspca_dev->usb_lock);
-       PDEBUG(D_STREAM, "qual_upd %d%%", qual);
-       set_quality(gspca_dev, qual);
-       mutex_unlock(&gspca_dev->usb_lock);
-}
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,               /* interrupt packet */
-                       int len)                /* interrupt packet length */
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (!(sd->flags & HAS_NO_BUTTON) && len == 1) {
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
-               input_sync(gspca_dev->input_dev);
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
-               input_sync(gspca_dev->input_dev);
-               return 0;
-       }
-       return -EINVAL;
-}
-#endif
-
-/* check the JPEG compression */
-static void transfer_check(struct gspca_dev *gspca_dev,
-                       u8 *data)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int new_qual, r;
-
-       new_qual = 0;
-
-       /* if USB error, discard the frame and decrease the quality */
-       if (data[6] & 0x08) {                           /* USB FIFO full */
-               gspca_dev->last_packet_type = DISCARD_PACKET;
-               new_qual = -5;
-       } else {
-
-               /* else, compute the filling rate and a new JPEG quality */
-               r = (sd->pktsz * 100) /
-                       (sd->npkt *
-                               gspca_dev->urb[0]->iso_frame_desc[0].length);
-               if (r >= 85)
-                       new_qual = -3;
-               else if (r < 75)
-                       new_qual = 2;
-       }
-       if (new_qual != 0) {
-               sd->nchg += new_qual;
-               if (sd->nchg < -6 || sd->nchg >= 12) {
-                       /* Note: we are in interrupt context, so we can't
-                          use v4l2_ctrl_g/s_ctrl here. Access the value
-                          directly instead. */
-                       s32 curqual = sd->jpegqual->cur.val;
-                       sd->nchg = 0;
-                       new_qual += curqual;
-                       if (new_qual < sd->jpegqual->minimum)
-                               new_qual = sd->jpegqual->minimum;
-                       else if (new_qual > sd->jpegqual->maximum)
-                               new_qual = sd->jpegqual->maximum;
-                       if (new_qual != curqual) {
-                               sd->jpegqual->cur.val = new_qual;
-                               queue_work(sd->work_thread, &sd->work);
-                       }
-               }
-       } else {
-               sd->nchg = 0;
-       }
-       sd->pktsz = sd->npkt = 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;
-       int avg_lum, is_jpeg;
-       static const u8 frame_header[] =
-               {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
-
-       is_jpeg = (sd->fmt & 0x03) == 0;
-       if (len >= 64 && memcmp(data, frame_header, 6) == 0) {
-               avg_lum = ((data[35] >> 2) & 3) |
-                          (data[20] << 2) |
-                          (data[19] << 10);
-               avg_lum += ((data[35] >> 4) & 3) |
-                           (data[22] << 2) |
-                           (data[21] << 10);
-               avg_lum += ((data[35] >> 6) & 3) |
-                           (data[24] << 2) |
-                           (data[23] << 10);
-               avg_lum += (data[36] & 3) |
-                          (data[26] << 2) |
-                          (data[25] << 10);
-               avg_lum += ((data[36] >> 2) & 3) |
-                           (data[28] << 2) |
-                           (data[27] << 10);
-               avg_lum += ((data[36] >> 4) & 3) |
-                           (data[30] << 2) |
-                           (data[29] << 10);
-               avg_lum += ((data[36] >> 6) & 3) |
-                           (data[32] << 2) |
-                           (data[31] << 10);
-               avg_lum += ((data[44] >> 4) & 3) |
-                           (data[34] << 2) |
-                           (data[33] << 10);
-               avg_lum >>= 9;
-               atomic_set(&sd->avg_lum, avg_lum);
-
-               if (is_jpeg)
-                       transfer_check(gspca_dev, data);
-
-               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-               len -= 64;
-               if (len == 0)
-                       return;
-               data += 64;
-       }
-       if (gspca_dev->last_packet_type == LAST_PACKET) {
-               if (is_jpeg) {
-                       gspca_frame_add(gspca_dev, FIRST_PACKET,
-                               sd->jpeg_hdr, JPEG_HDR_SZ);
-                       gspca_frame_add(gspca_dev, INTER_PACKET,
-                               data, len);
-               } else {
-                       gspca_frame_add(gspca_dev, FIRST_PACKET,
-                               data, len);
-               }
-       } else {
-               /* if JPEG, count the packets and their size */
-               if (is_jpeg) {
-                       sd->npkt++;
-                       sd->pktsz += len;
-               }
-               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-       }
-}
-
-/* sub-driver description */
-static const struct sd_desc sd_desc = {
-       .name = KBUILD_MODNAME,
-       .config = sd_config,
-       .init = sd_init,
-       .init_controls = sd_init_controls,
-       .isoc_init = sd_isoc_init,
-       .start = sd_start,
-       .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .pkt_scan = sd_pkt_scan,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .int_pkt_scan = sd_int_pkt_scan,
-#endif
-       .dq_callback = sd_dqcallback,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .set_register = sd_dbg_s_register,
-       .get_register = sd_dbg_g_register,
-#endif
-       .get_chip_ident = sd_chip_ident,
-};
-
-#define SN9C20X(sensor, i2c_addr, flags) \
-       .driver_info =  ((flags & 0xff) << 16) \
-                       | (SENSOR_ ## sensor << 8) \
-                       | (i2c_addr)
-
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x0c45, 0x6240), SN9C20X(MT9M001, 0x5d, 0)},
-       {USB_DEVICE(0x0c45, 0x6242), SN9C20X(MT9M111, 0x5d, 0)},
-       {USB_DEVICE(0x0c45, 0x6248), SN9C20X(OV9655, 0x30, 0)},
-       {USB_DEVICE(0x0c45, 0x624c), SN9C20X(MT9M112, 0x5d, 0)},
-       {USB_DEVICE(0x0c45, 0x624e), SN9C20X(SOI968, 0x30, LED_REVERSE)},
-       {USB_DEVICE(0x0c45, 0x624f), SN9C20X(OV9650, 0x30,
-                                            (FLIP_DETECT | HAS_NO_BUTTON))},
-       {USB_DEVICE(0x0c45, 0x6251), SN9C20X(OV9650, 0x30, 0)},
-       {USB_DEVICE(0x0c45, 0x6253), SN9C20X(OV9650, 0x30, 0)},
-       {USB_DEVICE(0x0c45, 0x6260), SN9C20X(OV7670, 0x21, 0)},
-       {USB_DEVICE(0x0c45, 0x6270), SN9C20X(MT9VPRB, 0x00, 0)},
-       {USB_DEVICE(0x0c45, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
-       {USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
-       {USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
-       {USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
-       {USB_DEVICE(0x0c45, 0x6282), SN9C20X(MT9M111, 0x5d, 0)},
-       {USB_DEVICE(0x0c45, 0x6288), SN9C20X(OV9655, 0x30, 0)},
-       {USB_DEVICE(0x0c45, 0x628c), SN9C20X(MT9M112, 0x5d, 0)},
-       {USB_DEVICE(0x0c45, 0x628e), SN9C20X(SOI968, 0x30, 0)},
-       {USB_DEVICE(0x0c45, 0x628f), SN9C20X(OV9650, 0x30, 0)},
-       {USB_DEVICE(0x0c45, 0x62a0), SN9C20X(OV7670, 0x21, 0)},
-       {USB_DEVICE(0x0c45, 0x62b0), SN9C20X(MT9VPRB, 0x00, 0)},
-       {USB_DEVICE(0x0c45, 0x62b3), SN9C20X(OV9655, 0x30, LED_REVERSE)},
-       {USB_DEVICE(0x0c45, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
-       {USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
-       {USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
-       {USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
-       {USB_DEVICE(0x0458, 0x7029), SN9C20X(HV7131R, 0x11, 0)},
-       {USB_DEVICE(0x0458, 0x704a), SN9C20X(MT9M112, 0x5d, 0)},
-       {USB_DEVICE(0x0458, 0x704c), SN9C20X(MT9M112, 0x5d, 0)},
-       {USB_DEVICE(0xa168, 0x0610), SN9C20X(HV7131R, 0x11, 0)},
-       {USB_DEVICE(0xa168, 0x0611), SN9C20X(HV7131R, 0x11, 0)},
-       {USB_DEVICE(0xa168, 0x0613), SN9C20X(HV7131R, 0x11, 0)},
-       {USB_DEVICE(0xa168, 0x0618), SN9C20X(HV7131R, 0x11, 0)},
-       {USB_DEVICE(0xa168, 0x0614), SN9C20X(MT9M111, 0x5d, 0)},
-       {USB_DEVICE(0xa168, 0x0615), SN9C20X(MT9M111, 0x5d, 0)},
-       {USB_DEVICE(0xa168, 0x0617), SN9C20X(MT9M111, 0x5d, 0)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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 = KBUILD_MODNAME,
-       .id_table = device_table,
-       .probe = sd_probe,
-       .disconnect = gspca_disconnect,
-#ifdef CONFIG_PM
-       .suspend = gspca_suspend,
-       .resume = gspca_resume,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c
deleted file mode 100644 (file)
index fd1f8d2..0000000
+++ /dev/null
@@ -1,1493 +0,0 @@
-/*
- *             sonix sn9c102 (bayer) library
- *
- * Copyright (C) 2009-2011 Jean-François Moine <http://moinejf.free.fr>
- * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
- * Add Pas106 Stefano Mozzi (C) 2004
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* Some documentation on known sonixb registers:
-
-Reg    Use
-sn9c101 / sn9c102:
-0x10   high nibble red gain low nibble blue gain
-0x11   low nibble green gain
-sn9c103:
-0x05   red gain 0-127
-0x06   blue gain 0-127
-0x07   green gain 0-127
-all:
-0x08-0x0f i2c / 3wire registers
-0x12   hstart
-0x13   vstart
-0x15   hsize (hsize = register-value * 16)
-0x16   vsize (vsize = register-value * 16)
-0x17   bit 0 toggle compression quality (according to sn9c102 driver)
-0x18   bit 7 enables compression, bit 4-5 set image down scaling:
-       00 scale 1, 01 scale 1/2, 10, scale 1/4
-0x19   high-nibble is sensor clock divider, changes exposure on sensors which
-       use a clock generated by the bridge. Some sensors have their own clock.
-0x1c   auto_exposure area (for avg_lum) startx (startx = register-value * 32)
-0x1d   auto_exposure area (for avg_lum) starty (starty = register-value * 32)
-0x1e   auto_exposure area (for avg_lum) stopx (hsize = (0x1e - 0x1c) * 32)
-0x1f   auto_exposure area (for avg_lum) stopy (vsize = (0x1f - 0x1d) * 32)
-*/
-
-#define MODULE_NAME "sonixb"
-
-#include <linux/input.h>
-#include "gspca.h"
-
-MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
-MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       struct v4l2_ctrl *brightness;
-       struct v4l2_ctrl *plfreq;
-
-       atomic_t avg_lum;
-       int prev_avg_lum;
-       int exposure_knee;
-       int header_read;
-       u8 header[12]; /* Header without sof marker */
-
-       unsigned char autogain_ignore_frames;
-       unsigned char frames_to_drop;
-
-       __u8 bridge;                    /* Type of bridge */
-#define BRIDGE_101 0
-#define BRIDGE_102 0 /* We make no difference between 101 and 102 */
-#define BRIDGE_103 1
-
-       __u8 sensor;                    /* Type of image sensor chip */
-#define SENSOR_HV7131D 0
-#define SENSOR_HV7131R 1
-#define SENSOR_OV6650 2
-#define SENSOR_OV7630 3
-#define SENSOR_PAS106 4
-#define SENSOR_PAS202 5
-#define SENSOR_TAS5110C 6
-#define SENSOR_TAS5110D 7
-#define SENSOR_TAS5130CXX 8
-       __u8 reg11;
-};
-
-typedef const __u8 sensor_init_t[8];
-
-struct sensor_data {
-       const __u8 *bridge_init;
-       sensor_init_t *sensor_init;
-       int sensor_init_size;
-       int flags;
-       __u8 sensor_addr;
-};
-
-/* sensor_data flags */
-#define F_SIF          0x01    /* sif or vga */
-
-/* priv field of struct v4l2_pix_format flags (do not use low nibble!) */
-#define MODE_RAW 0x10          /* raw bayer mode */
-#define MODE_REDUCED_SIF 0x20  /* vga mode (320x240 / 160x120) on sif cam */
-
-#define COMP 0xc7              /* 0x87 //0x07 */
-#define COMP1 0xc9             /* 0x89 //0x09 */
-
-#define MCK_INIT 0x63
-#define MCK_INIT1 0x20         /*fixme: Bayer - 0x50 for JPEG ??*/
-
-#define SYS_CLK 0x04
-
-#define SENS(bridge, sensor, _flags, _sensor_addr) \
-{ \
-       .bridge_init = bridge, \
-       .sensor_init = sensor, \
-       .sensor_init_size = sizeof(sensor), \
-       .flags = _flags, .sensor_addr = _sensor_addr \
-}
-
-/* We calculate the autogain at the end of the transfer of a frame, at this
-   moment a frame with the old settings is being captured and transmitted. So
-   if we adjust the gain or exposure we must ignore atleast the next frame for
-   the new settings to come into effect before doing any other adjustments. */
-#define AUTOGAIN_IGNORE_FRAMES 1
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2 | MODE_RAW},
-       {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 5 / 4,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2},
-       {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 5 / 4,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 5 / 4,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-static const struct v4l2_pix_format sif_mode[] = {
-       {160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1 | MODE_RAW | MODE_REDUCED_SIF},
-       {160, 120, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 5 / 4,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1 | MODE_REDUCED_SIF},
-       {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1 | MODE_RAW},
-       {176, 144, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 5 / 4,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {320, 240, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 5 / 4,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0 | MODE_REDUCED_SIF},
-       {352, 288, V4L2_PIX_FMT_SN9C10X, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 5 / 4,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-static const __u8 initHv7131d[] = {
-       0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
-       0x00, 0x00,
-       0x00, 0x00, 0x00, 0x02, 0x02, 0x00,
-       0x28, 0x1e, 0x60, 0x8e, 0x42,
-};
-static const __u8 hv7131d_sensor_init[][8] = {
-       {0xa0, 0x11, 0x01, 0x04, 0x00, 0x00, 0x00, 0x17},
-       {0xa0, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x17},
-       {0xa0, 0x11, 0x28, 0x00, 0x00, 0x00, 0x00, 0x17},
-       {0xa0, 0x11, 0x30, 0x30, 0x00, 0x00, 0x00, 0x17}, /* reset level */
-       {0xa0, 0x11, 0x34, 0x02, 0x00, 0x00, 0x00, 0x17}, /* pixel bias volt */
-};
-
-static const __u8 initHv7131r[] = {
-       0x46, 0x77, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00, 0x00,
-       0x00, 0x00,
-       0x00, 0x00, 0x00, 0x02, 0x01, 0x00,
-       0x28, 0x1e, 0x60, 0x8a, 0x20,
-};
-static const __u8 hv7131r_sensor_init[][8] = {
-       {0xc0, 0x11, 0x31, 0x38, 0x2a, 0x2e, 0x00, 0x10},
-       {0xa0, 0x11, 0x01, 0x08, 0x2a, 0x2e, 0x00, 0x10},
-       {0xb0, 0x11, 0x20, 0x00, 0xd0, 0x2e, 0x00, 0x10},
-       {0xc0, 0x11, 0x25, 0x03, 0x0e, 0x28, 0x00, 0x16},
-       {0xa0, 0x11, 0x30, 0x10, 0x0e, 0x28, 0x00, 0x15},
-};
-static const __u8 initOv6650[] = {
-       0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-       0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x01, 0x01, 0x0a, 0x16, 0x12, 0x68, 0x8b,
-       0x10,
-};
-static const __u8 ov6650_sensor_init[][8] = {
-       /* Bright, contrast, etc are set through SCBB interface.
-        * AVCAP on win2 do not send any data on this controls. */
-       /* Anyway, some registers appears to alter bright and constrat */
-
-       /* Reset sensor */
-       {0xa0, 0x60, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
-       /* Set clock register 0x11 low nibble is clock divider */
-       {0xd0, 0x60, 0x11, 0xc0, 0x1b, 0x18, 0xc1, 0x10},
-       /* Next some unknown stuff */
-       {0xb0, 0x60, 0x15, 0x00, 0x02, 0x18, 0xc1, 0x10},
-/*     {0xa0, 0x60, 0x1b, 0x01, 0x02, 0x18, 0xc1, 0x10},
-                * THIS SET GREEN SCREEN
-                * (pixels could be innverted in decode kind of "brg",
-                * but blue wont be there. Avoid this data ... */
-       {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10}, /* format out? */
-       {0xd0, 0x60, 0x26, 0x01, 0x14, 0xd8, 0xa4, 0x10},
-       {0xa0, 0x60, 0x30, 0x3d, 0x0a, 0xd8, 0xa4, 0x10},
-       /* Enable rgb brightness control */
-       {0xa0, 0x60, 0x61, 0x08, 0x00, 0x00, 0x00, 0x10},
-       /* HDG: Note windows uses the line below, which sets both register 0x60
-          and 0x61 I believe these registers of the ov6650 are identical as
-          those of the ov7630, because if this is true the windows settings
-          add a bit additional red gain and a lot additional blue gain, which
-          matches my findings that the windows settings make blue much too
-          blue and red a little too red.
-       {0xb0, 0x60, 0x60, 0x66, 0x68, 0xd8, 0xa4, 0x10}, */
-       /* Some more unknown stuff */
-       {0xa0, 0x60, 0x68, 0x04, 0x68, 0xd8, 0xa4, 0x10},
-       {0xd0, 0x60, 0x17, 0x24, 0xd6, 0x04, 0x94, 0x10}, /* Clipreg */
-};
-
-static const __u8 initOv7630[] = {
-       0x04, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* r01 .. r08 */
-       0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* r09 .. r10 */
-       0x00, 0x01, 0x01, 0x0a,                         /* r11 .. r14 */
-       0x28, 0x1e,                     /* H & V sizes     r15 .. r16 */
-       0x68, 0x8f, MCK_INIT1,                          /* r17 .. r19 */
-};
-static const __u8 ov7630_sensor_init[][8] = {
-       {0xa0, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {0xb0, 0x21, 0x01, 0x77, 0x3a, 0x00, 0x00, 0x10},
-/*     {0xd0, 0x21, 0x12, 0x7c, 0x01, 0x80, 0x34, 0x10},          jfm */
-       {0xd0, 0x21, 0x12, 0x5c, 0x00, 0x80, 0x34, 0x10},       /* jfm */
-       {0xa0, 0x21, 0x1b, 0x04, 0x00, 0x80, 0x34, 0x10},
-       {0xa0, 0x21, 0x20, 0x44, 0x00, 0x80, 0x34, 0x10},
-       {0xa0, 0x21, 0x23, 0xee, 0x00, 0x80, 0x34, 0x10},
-       {0xd0, 0x21, 0x26, 0xa0, 0x9a, 0xa0, 0x30, 0x10},
-       {0xb0, 0x21, 0x2a, 0x80, 0x00, 0xa0, 0x30, 0x10},
-       {0xb0, 0x21, 0x2f, 0x3d, 0x24, 0xa0, 0x30, 0x10},
-       {0xa0, 0x21, 0x32, 0x86, 0x24, 0xa0, 0x30, 0x10},
-       {0xb0, 0x21, 0x60, 0xa9, 0x4a, 0xa0, 0x30, 0x10},
-/*     {0xb0, 0x21, 0x60, 0xa9, 0x42, 0xa0, 0x30, 0x10},        * jfm */
-       {0xa0, 0x21, 0x65, 0x00, 0x42, 0xa0, 0x30, 0x10},
-       {0xa0, 0x21, 0x69, 0x38, 0x42, 0xa0, 0x30, 0x10},
-       {0xc0, 0x21, 0x6f, 0x88, 0x0b, 0x00, 0x30, 0x10},
-       {0xc0, 0x21, 0x74, 0x21, 0x8e, 0x00, 0x30, 0x10},
-       {0xa0, 0x21, 0x7d, 0xf7, 0x8e, 0x00, 0x30, 0x10},
-       {0xd0, 0x21, 0x17, 0x1c, 0xbd, 0x06, 0xf6, 0x10},
-};
-
-static const __u8 initPas106[] = {
-       0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x00, 0x00,
-       0x00, 0x00,
-       0x00, 0x00, 0x00, 0x04, 0x01, 0x00,
-       0x16, 0x12, 0x24, COMP1, MCK_INIT1,
-};
-/* compression 0x86 mckinit1 0x2b */
-
-/* "Known" PAS106B registers:
-  0x02 clock divider
-  0x03 Variable framerate bits 4-11
-  0x04 Var framerate bits 0-3, one must leave the 4 msb's at 0 !!
-       The variable framerate control must never be set lower then 300,
-       which sets the framerate at 90 / reg02, otherwise vsync is lost.
-  0x05 Shutter Time Line Offset, this can be used as an exposure control:
-       0 = use full frame time, 255 = no exposure at all
-       Note this may never be larger then "var-framerate control" / 2 - 2.
-       When var-framerate control is < 514, no exposure is reached at the max
-       allowed value for the framerate control value, rather then at 255.
-  0x06 Shutter Time Pixel Offset, like reg05 this influences exposure, but
-       only a very little bit, leave at 0xcd
-  0x07 offset sign bit (bit0 1 > negative offset)
-  0x08 offset
-  0x09 Blue Gain
-  0x0a Green1 Gain
-  0x0b Green2 Gain
-  0x0c Red Gain
-  0x0e Global gain
-  0x13 Write 1 to commit settings to sensor
-*/
-
-static const __u8 pas106_sensor_init[][8] = {
-       /* Pixel Clock Divider 6 */
-       { 0xa1, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14 },
-       /* Frame Time MSB (also seen as 0x12) */
-       { 0xa1, 0x40, 0x03, 0x13, 0x00, 0x00, 0x00, 0x14 },
-       /* Frame Time LSB (also seen as 0x05) */
-       { 0xa1, 0x40, 0x04, 0x06, 0x00, 0x00, 0x00, 0x14 },
-       /* Shutter Time Line Offset (also seen as 0x6d) */
-       { 0xa1, 0x40, 0x05, 0x65, 0x00, 0x00, 0x00, 0x14 },
-       /* Shutter Time Pixel Offset (also seen as 0xb1) */
-       { 0xa1, 0x40, 0x06, 0xcd, 0x00, 0x00, 0x00, 0x14 },
-       /* Black Level Subtract Sign (also seen 0x00) */
-       { 0xa1, 0x40, 0x07, 0xc1, 0x00, 0x00, 0x00, 0x14 },
-       /* Black Level Subtract Level (also seen 0x01) */
-       { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
-       { 0xa1, 0x40, 0x08, 0x06, 0x00, 0x00, 0x00, 0x14 },
-       /* Color Gain B Pixel 5 a */
-       { 0xa1, 0x40, 0x09, 0x05, 0x00, 0x00, 0x00, 0x14 },
-       /* Color Gain G1 Pixel 1 5 */
-       { 0xa1, 0x40, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x14 },
-       /* Color Gain G2 Pixel 1 0 5 */
-       { 0xa1, 0x40, 0x0b, 0x04, 0x00, 0x00, 0x00, 0x14 },
-       /* Color Gain R Pixel 3 1 */
-       { 0xa1, 0x40, 0x0c, 0x05, 0x00, 0x00, 0x00, 0x14 },
-       /* Color GainH  Pixel */
-       { 0xa1, 0x40, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x14 },
-       /* Global Gain */
-       { 0xa1, 0x40, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x14 },
-       /* Contrast */
-       { 0xa1, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x14 },
-       /* H&V synchro polarity */
-       { 0xa1, 0x40, 0x10, 0x06, 0x00, 0x00, 0x00, 0x14 },
-       /* ?default */
-       { 0xa1, 0x40, 0x11, 0x06, 0x00, 0x00, 0x00, 0x14 },
-       /* DAC scale */
-       { 0xa1, 0x40, 0x12, 0x06, 0x00, 0x00, 0x00, 0x14 },
-       /* ?default */
-       { 0xa1, 0x40, 0x14, 0x02, 0x00, 0x00, 0x00, 0x14 },
-       /* Validate Settings */
-       { 0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14 },
-};
-
-static const __u8 initPas202[] = {
-       0x44, 0x44, 0x21, 0x30, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
-       0x00, 0x00,
-       0x00, 0x00, 0x00, 0x06, 0x03, 0x0a,
-       0x28, 0x1e, 0x20, 0x89, 0x20,
-};
-
-/* "Known" PAS202BCB registers:
-  0x02 clock divider
-  0x04 Variable framerate bits 6-11 (*)
-  0x05 Var framerate  bits 0-5, one must leave the 2 msb's at 0 !!
-  0x07 Blue Gain
-  0x08 Green Gain
-  0x09 Red Gain
-  0x0b offset sign bit (bit0 1 > negative offset)
-  0x0c offset
-  0x0e Unknown image is slightly brighter when bit 0 is 0, if reg0f is 0 too,
-       leave at 1 otherwise we get a jump in our exposure control
-  0x0f Exposure 0-255, 0 = use full frame time, 255 = no exposure at all
-  0x10 Master gain 0 - 31
-  0x11 write 1 to apply changes
-  (*) The variable framerate control must never be set lower then 500
-      which sets the framerate at 30 / reg02, otherwise vsync is lost.
-*/
-static const __u8 pas202_sensor_init[][8] = {
-       /* Set the clock divider to 4 -> 30 / 4 = 7.5 fps, we would like
-          to set it lower, but for some reason the bridge starts missing
-          vsync's then */
-       {0xa0, 0x40, 0x02, 0x04, 0x00, 0x00, 0x00, 0x10},
-       {0xd0, 0x40, 0x04, 0x07, 0x34, 0x00, 0x09, 0x10},
-       {0xd0, 0x40, 0x08, 0x01, 0x00, 0x00, 0x01, 0x10},
-       {0xd0, 0x40, 0x0c, 0x00, 0x0c, 0x01, 0x32, 0x10},
-       {0xd0, 0x40, 0x10, 0x00, 0x01, 0x00, 0x63, 0x10},
-       {0xa0, 0x40, 0x15, 0x70, 0x01, 0x00, 0x63, 0x10},
-       {0xa0, 0x40, 0x18, 0x00, 0x01, 0x00, 0x63, 0x10},
-       {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
-       {0xa0, 0x40, 0x03, 0x56, 0x01, 0x00, 0x63, 0x10},
-       {0xa0, 0x40, 0x11, 0x01, 0x01, 0x00, 0x63, 0x10},
-};
-
-static const __u8 initTas5110c[] = {
-       0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
-       0x00, 0x00,
-       0x00, 0x00, 0x00, 0x45, 0x09, 0x0a,
-       0x16, 0x12, 0x60, 0x86, 0x2b,
-};
-/* Same as above, except a different hstart */
-static const __u8 initTas5110d[] = {
-       0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
-       0x00, 0x00,
-       0x00, 0x00, 0x00, 0x41, 0x09, 0x0a,
-       0x16, 0x12, 0x60, 0x86, 0x2b,
-};
-/* tas5110c is 3 wire, tas5110d is 2 wire (regular i2c) */
-static const __u8 tas5110c_sensor_init[][8] = {
-       {0x30, 0x11, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10},
-       {0x30, 0x11, 0x02, 0x20, 0xa9, 0x00, 0x00, 0x10},
-};
-/* Known TAS5110D registers
- * reg02: gain, bit order reversed!! 0 == max gain, 255 == min gain
- * reg03: bit3: vflip, bit4: ~hflip, bit7: ~gainboost (~ == inverted)
- *        Note: writing reg03 seems to only work when written together with 02
- */
-static const __u8 tas5110d_sensor_init[][8] = {
-       {0xa0, 0x61, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x17}, /* reset */
-};
-
-static const __u8 initTas5130[] = {
-       0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x11, 0x00, 0x00, 0x00,
-       0x00, 0x00,
-       0x00, 0x00, 0x00, 0x68, 0x0c, 0x0a,
-       0x28, 0x1e, 0x60, COMP, MCK_INIT,
-};
-static const __u8 tas5130_sensor_init[][8] = {
-/*     {0x30, 0x11, 0x00, 0x40, 0x47, 0x00, 0x00, 0x10},
-                                       * shutter 0x47 short exposure? */
-       {0x30, 0x11, 0x00, 0x40, 0x01, 0x00, 0x00, 0x10},
-                                       /* shutter 0x01 long exposure */
-       {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
-};
-
-static const struct sensor_data sensor_data[] = {
-       SENS(initHv7131d, hv7131d_sensor_init, 0, 0),
-       SENS(initHv7131r, hv7131r_sensor_init, 0, 0),
-       SENS(initOv6650, ov6650_sensor_init, F_SIF, 0x60),
-       SENS(initOv7630, ov7630_sensor_init, 0, 0x21),
-       SENS(initPas106, pas106_sensor_init, F_SIF, 0),
-       SENS(initPas202, pas202_sensor_init, 0, 0),
-       SENS(initTas5110c, tas5110c_sensor_init, F_SIF, 0),
-       SENS(initTas5110d, tas5110d_sensor_init, F_SIF, 0),
-       SENS(initTas5130, tas5130_sensor_init, 0, 0),
-};
-
-/* get one byte in gspca_dev->usb_buf */
-static void reg_r(struct gspca_dev *gspca_dev,
-                 __u16 value)
-{
-       int res;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-
-       res = usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       0,                      /* request */
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       value,
-                       0,                      /* index */
-                       gspca_dev->usb_buf, 1,
-                       500);
-
-       if (res < 0) {
-               dev_err(gspca_dev->v4l2_dev.dev,
-                       "Error reading register %02x: %d\n", value, res);
-               gspca_dev->usb_err = res;
-       }
-}
-
-static void reg_w(struct gspca_dev *gspca_dev,
-                 __u16 value,
-                 const __u8 *buffer,
-                 int len)
-{
-       int res;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-
-       memcpy(gspca_dev->usb_buf, buffer, len);
-       res = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0x08,                   /* request */
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       value,
-                       0,                      /* index */
-                       gspca_dev->usb_buf, len,
-                       500);
-
-       if (res < 0) {
-               dev_err(gspca_dev->v4l2_dev.dev,
-                       "Error writing register %02x: %d\n", value, res);
-               gspca_dev->usb_err = res;
-       }
-}
-
-static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
-{
-       int retry = 60;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-
-       /* is i2c ready */
-       reg_w(gspca_dev, 0x08, buffer, 8);
-       while (retry--) {
-               if (gspca_dev->usb_err < 0)
-                       return;
-               msleep(10);
-               reg_r(gspca_dev, 0x08);
-               if (gspca_dev->usb_buf[0] & 0x04) {
-                       if (gspca_dev->usb_buf[0] & 0x08) {
-                               dev_err(gspca_dev->v4l2_dev.dev,
-                                       "i2c write error\n");
-                               gspca_dev->usb_err = -EIO;
-                       }
-                       return;
-               }
-       }
-
-       dev_err(gspca_dev->v4l2_dev.dev, "i2c write timeout\n");
-       gspca_dev->usb_err = -EIO;
-}
-
-static void i2c_w_vector(struct gspca_dev *gspca_dev,
-                       const __u8 buffer[][8], int len)
-{
-       for (;;) {
-               if (gspca_dev->usb_err < 0)
-                       return;
-               reg_w(gspca_dev, 0x08, *buffer, 8);
-               len -= 8;
-               if (len <= 0)
-                       break;
-               buffer++;
-       }
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->sensor) {
-       case  SENSOR_OV6650:
-       case  SENSOR_OV7630: {
-               __u8 i2cOV[] =
-                       {0xa0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10};
-
-               /* change reg 0x06 */
-               i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
-               i2cOV[3] = sd->brightness->val;
-               i2c_w(gspca_dev, i2cOV);
-               break;
-       }
-       case SENSOR_PAS106:
-       case SENSOR_PAS202: {
-               __u8 i2cpbright[] =
-                       {0xb0, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x16};
-               __u8 i2cpdoit[] =
-                       {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
-
-               /* PAS106 uses reg 7 and 8 instead of b and c */
-               if (sd->sensor == SENSOR_PAS106) {
-                       i2cpbright[2] = 7;
-                       i2cpdoit[2] = 0x13;
-               }
-
-               if (sd->brightness->val < 127) {
-                       /* change reg 0x0b, signreg */
-                       i2cpbright[3] = 0x01;
-                       /* set reg 0x0c, offset */
-                       i2cpbright[4] = 127 - sd->brightness->val;
-               } else
-                       i2cpbright[4] = sd->brightness->val - 127;
-
-               i2c_w(gspca_dev, i2cpbright);
-               i2c_w(gspca_dev, i2cpdoit);
-               break;
-       }
-       default:
-               break;
-       }
-}
-
-static void setgain(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 gain = gspca_dev->gain->val;
-
-       switch (sd->sensor) {
-       case SENSOR_HV7131D: {
-               __u8 i2c[] =
-                       {0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17};
-
-               i2c[3] = 0x3f - gain;
-               i2c[4] = 0x3f - gain;
-               i2c[5] = 0x3f - gain;
-
-               i2c_w(gspca_dev, i2c);
-               break;
-       }
-       case SENSOR_TAS5110C:
-       case SENSOR_TAS5130CXX: {
-               __u8 i2c[] =
-                       {0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10};
-
-               i2c[4] = 255 - gain;
-               i2c_w(gspca_dev, i2c);
-               break;
-       }
-       case SENSOR_TAS5110D: {
-               __u8 i2c[] = {
-                       0xb0, 0x61, 0x02, 0x00, 0x10, 0x00, 0x00, 0x17 };
-               gain = 255 - gain;
-               /* The bits in the register are the wrong way around!! */
-               i2c[3] |= (gain & 0x80) >> 7;
-               i2c[3] |= (gain & 0x40) >> 5;
-               i2c[3] |= (gain & 0x20) >> 3;
-               i2c[3] |= (gain & 0x10) >> 1;
-               i2c[3] |= (gain & 0x08) << 1;
-               i2c[3] |= (gain & 0x04) << 3;
-               i2c[3] |= (gain & 0x02) << 5;
-               i2c[3] |= (gain & 0x01) << 7;
-               i2c_w(gspca_dev, i2c);
-               break;
-       }
-       case SENSOR_OV6650:
-       case SENSOR_OV7630: {
-               __u8 i2c[] = {0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
-
-               /*
-                * The ov7630's gain is weird, at 32 the gain drops to the
-                * same level as at 16, so skip 32-47 (of the 0-63 scale).
-                */
-               if (sd->sensor == SENSOR_OV7630 && gain >= 32)
-                       gain += 16;
-
-               i2c[1] = sensor_data[sd->sensor].sensor_addr;
-               i2c[3] = gain;
-               i2c_w(gspca_dev, i2c);
-               break;
-       }
-       case SENSOR_PAS106:
-       case SENSOR_PAS202: {
-               __u8 i2cpgain[] =
-                       {0xa0, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15};
-               __u8 i2cpcolorgain[] =
-                       {0xc0, 0x40, 0x07, 0x00, 0x00, 0x00, 0x00, 0x15};
-               __u8 i2cpdoit[] =
-                       {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
-
-               /* PAS106 uses different regs (and has split green gains) */
-               if (sd->sensor == SENSOR_PAS106) {
-                       i2cpgain[2] = 0x0e;
-                       i2cpcolorgain[0] = 0xd0;
-                       i2cpcolorgain[2] = 0x09;
-                       i2cpdoit[2] = 0x13;
-               }
-
-               i2cpgain[3] = gain;
-               i2cpcolorgain[3] = gain >> 1;
-               i2cpcolorgain[4] = gain >> 1;
-               i2cpcolorgain[5] = gain >> 1;
-               i2cpcolorgain[6] = gain >> 1;
-
-               i2c_w(gspca_dev, i2cpgain);
-               i2c_w(gspca_dev, i2cpcolorgain);
-               i2c_w(gspca_dev, i2cpdoit);
-               break;
-       }
-       default:
-               if (sd->bridge == BRIDGE_103) {
-                       u8 buf[3] = { gain, gain, gain }; /* R, G, B */
-                       reg_w(gspca_dev, 0x05, buf, 3);
-               } else {
-                       u8 buf[2];
-                       buf[0] = gain << 4 | gain; /* Red and blue */
-                       buf[1] = gain; /* Green */
-                       reg_w(gspca_dev, 0x10, buf, 2);
-               }
-       }
-}
-
-static void setexposure(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->sensor) {
-       case SENSOR_HV7131D: {
-               /* Note the datasheet wrongly says line mode exposure uses reg
-                  0x26 and 0x27, testing has shown 0x25 + 0x26 */
-               __u8 i2c[] = {0xc0, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x17};
-               u16 reg = gspca_dev->exposure->val;
-
-               i2c[3] = reg >> 8;
-               i2c[4] = reg & 0xff;
-               i2c_w(gspca_dev, i2c);
-               break;
-       }
-       case SENSOR_TAS5110C:
-       case SENSOR_TAS5110D: {
-               /* register 19's high nibble contains the sn9c10x clock divider
-                  The high nibble configures the no fps according to the
-                  formula: 60 / high_nibble. With a maximum of 30 fps */
-               u8 reg = gspca_dev->exposure->val;
-
-               reg = (reg << 4) | 0x0b;
-               reg_w(gspca_dev, 0x19, &reg, 1);
-               break;
-       }
-       case SENSOR_OV6650:
-       case SENSOR_OV7630: {
-               /* The ov6650 / ov7630 have 2 registers which both influence
-                  exposure, register 11, whose low nibble sets the nr off fps
-                  according to: fps = 30 / (low_nibble + 1)
-
-                  The fps configures the maximum exposure setting, but it is
-                  possible to use less exposure then what the fps maximum
-                  allows by setting register 10. register 10 configures the
-                  actual exposure as quotient of the full exposure, with 0
-                  being no exposure at all (not very useful) and reg10_max
-                  being max exposure possible at that framerate.
-
-                  The code maps our 0 - 510 ms exposure ctrl to these 2
-                  registers, trying to keep fps as high as possible.
-               */
-               __u8 i2c[] = {0xb0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10};
-               int reg10, reg11, reg10_max;
-
-               /* ov6645 datasheet says reg10_max is 9a, but that uses
-                  tline * 2 * reg10 as formula for calculating texpo, the
-                  ov6650 probably uses the same formula as the 7730 which uses
-                  tline * 4 * reg10, which explains why the reg10max we've
-                  found experimentally for the ov6650 is exactly half that of
-                  the ov6645. The ov7630 datasheet says the max is 0x41. */
-               if (sd->sensor == SENSOR_OV6650) {
-                       reg10_max = 0x4d;
-                       i2c[4] = 0xc0; /* OV6650 needs non default vsync pol */
-               } else
-                       reg10_max = 0x41;
-
-               reg11 = (15 * gspca_dev->exposure->val + 999) / 1000;
-               if (reg11 < 1)
-                       reg11 = 1;
-               else if (reg11 > 16)
-                       reg11 = 16;
-
-               /* In 640x480, if the reg11 has less than 4, the image is
-                  unstable (the bridge goes into a higher compression mode
-                  which we have not reverse engineered yet). */
-               if (gspca_dev->width == 640 && reg11 < 4)
-                       reg11 = 4;
-
-               /* frame exposure time in ms = 1000 * reg11 / 30    ->
-               reg10 = (gspca_dev->exposure->val / 2) * reg10_max
-                               / (1000 * reg11 / 30) */
-               reg10 = (gspca_dev->exposure->val * 15 * reg10_max)
-                               / (1000 * reg11);
-
-               /* Don't allow this to get below 10 when using autogain, the
-                  steps become very large (relatively) when below 10 causing
-                  the image to oscilate from much too dark, to much too bright
-                  and back again. */
-               if (gspca_dev->autogain->val && reg10 < 10)
-                       reg10 = 10;
-               else if (reg10 > reg10_max)
-                       reg10 = reg10_max;
-
-               /* Write reg 10 and reg11 low nibble */
-               i2c[1] = sensor_data[sd->sensor].sensor_addr;
-               i2c[3] = reg10;
-               i2c[4] |= reg11 - 1;
-
-               /* If register 11 didn't change, don't change it */
-               if (sd->reg11 == reg11)
-                       i2c[0] = 0xa0;
-
-               i2c_w(gspca_dev, i2c);
-               if (gspca_dev->usb_err == 0)
-                       sd->reg11 = reg11;
-               break;
-       }
-       case SENSOR_PAS202: {
-               __u8 i2cpframerate[] =
-                       {0xb0, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x16};
-               __u8 i2cpexpo[] =
-                       {0xa0, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x16};
-               const __u8 i2cpdoit[] =
-                       {0xa0, 0x40, 0x11, 0x01, 0x00, 0x00, 0x00, 0x16};
-               int framerate_ctrl;
-
-               /* The exposure knee for the autogain algorithm is 200
-                  (100 ms / 10 fps on other sensors), for values below this
-                  use the control for setting the partial frame expose time,
-                  above that use variable framerate. This way we run at max
-                  framerate (640x480@7.5 fps, 320x240@10fps) until the knee
-                  is reached. Using the variable framerate control above 200
-                  is better then playing around with both clockdiv + partial
-                  frame exposure times (like we are doing with the ov chips),
-                  as that sometimes leads to jumps in the exposure control,
-                  which are bad for auto exposure. */
-               if (gspca_dev->exposure->val < 200) {
-                       i2cpexpo[3] = 255 - (gspca_dev->exposure->val * 255)
-                                               / 200;
-                       framerate_ctrl = 500;
-               } else {
-                       /* The PAS202's exposure control goes from 0 - 4095,
-                          but anything below 500 causes vsync issues, so scale
-                          our 200-1023 to 500-4095 */
-                       framerate_ctrl = (gspca_dev->exposure->val - 200)
-                                                       * 1000 / 229 +  500;
-               }
-
-               i2cpframerate[3] = framerate_ctrl >> 6;
-               i2cpframerate[4] = framerate_ctrl & 0x3f;
-               i2c_w(gspca_dev, i2cpframerate);
-               i2c_w(gspca_dev, i2cpexpo);
-               i2c_w(gspca_dev, i2cpdoit);
-               break;
-       }
-       case SENSOR_PAS106: {
-               __u8 i2cpframerate[] =
-                       {0xb1, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x14};
-               __u8 i2cpexpo[] =
-                       {0xa1, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x14};
-               const __u8 i2cpdoit[] =
-                       {0xa1, 0x40, 0x13, 0x01, 0x00, 0x00, 0x00, 0x14};
-               int framerate_ctrl;
-
-               /* For values below 150 use partial frame exposure, above
-                  that use framerate ctrl */
-               if (gspca_dev->exposure->val < 150) {
-                       i2cpexpo[3] = 150 - gspca_dev->exposure->val;
-                       framerate_ctrl = 300;
-               } else {
-                       /* The PAS106's exposure control goes from 0 - 4095,
-                          but anything below 300 causes vsync issues, so scale
-                          our 150-1023 to 300-4095 */
-                       framerate_ctrl = (gspca_dev->exposure->val - 150)
-                                               * 1000 / 230 + 300;
-               }
-
-               i2cpframerate[3] = framerate_ctrl >> 4;
-               i2cpframerate[4] = framerate_ctrl & 0x0f;
-               i2c_w(gspca_dev, i2cpframerate);
-               i2c_w(gspca_dev, i2cpexpo);
-               i2c_w(gspca_dev, i2cpdoit);
-               break;
-       }
-       default:
-               break;
-       }
-}
-
-static void setfreq(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630) {
-               /* Framerate adjust register for artificial light 50 hz flicker
-                  compensation, for the ov6650 this is identical to ov6630
-                  0x2b register, see ov6630 datasheet.
-                  0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
-               __u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
-               switch (sd->plfreq->val) {
-               default:
-/*             case 0:                  * no filter*/
-/*             case 2:                  * 60 hz */
-                       i2c[3] = 0;
-                       break;
-               case 1:                 /* 50 hz */
-                       i2c[3] = (sd->sensor == SENSOR_OV6650)
-                                       ? 0x4f : 0x8a;
-                       break;
-               }
-               i2c[1] = sensor_data[sd->sensor].sensor_addr;
-               i2c_w(gspca_dev, i2c);
-       }
-}
-
-static void do_autogain(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int deadzone, desired_avg_lum, avg_lum;
-
-       avg_lum = atomic_read(&sd->avg_lum);
-       if (avg_lum == -1)
-               return;
-
-       if (sd->autogain_ignore_frames > 0) {
-               sd->autogain_ignore_frames--;
-               return;
-       }
-
-       /* SIF / VGA sensors have a different autoexposure area and thus
-          different avg_lum values for the same picture brightness */
-       if (sensor_data[sd->sensor].flags & F_SIF) {
-               deadzone = 500;
-               /* SIF sensors tend to overexpose, so keep this small */
-               desired_avg_lum = 5000;
-       } else {
-               deadzone = 1500;
-               desired_avg_lum = 13000;
-       }
-
-       if (sd->brightness)
-               desired_avg_lum = sd->brightness->val * desired_avg_lum / 127;
-
-       if (gspca_dev->exposure->maximum < 500) {
-               if (gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
-                               desired_avg_lum, deadzone))
-                       sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
-       } else {
-               int gain_knee = gspca_dev->gain->maximum * 9 / 10;
-               if (gspca_expo_autogain(gspca_dev, avg_lum, desired_avg_lum,
-                               deadzone, gain_knee, sd->exposure_knee))
-                       sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
-       }
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-
-       reg_r(gspca_dev, 0x00);
-       if (gspca_dev->usb_buf[0] != 0x10)
-               return -ENODEV;
-
-       /* copy the webcam info from the device id */
-       sd->sensor = id->driver_info >> 8;
-       sd->bridge = id->driver_info & 0xff;
-
-       cam = &gspca_dev->cam;
-       if (!(sensor_data[sd->sensor].flags & F_SIF)) {
-               cam->cam_mode = vga_mode;
-               cam->nmodes = ARRAY_SIZE(vga_mode);
-       } else {
-               cam->cam_mode = sif_mode;
-               cam->nmodes = ARRAY_SIZE(sif_mode);
-       }
-       cam->npkt = 36;                 /* 36 packets per ISOC message */
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       const __u8 stop = 0x09; /* Disable stream turn of LED */
-
-       reg_w(gspca_dev, 0x01, &stop, 1);
-
-       return gspca_dev->usb_err;
-}
-
-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 (ctrl->id == V4L2_CID_AUTOGAIN && ctrl->is_new && ctrl->val) {
-               /* when switching to autogain set defaults to make sure
-                  we are on a valid point of the autogain gain /
-                  exposure knee graph, and give this change time to
-                  take effect before doing autogain. */
-               gspca_dev->gain->val = gspca_dev->gain->default_value;
-               gspca_dev->exposure->val = gspca_dev->exposure->default_value;
-               sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
-       }
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               setbrightness(gspca_dev);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               if (gspca_dev->exposure->is_new || (ctrl->is_new && ctrl->val))
-                       setexposure(gspca_dev);
-               if (gspca_dev->gain->is_new || (ctrl->is_new && ctrl->val))
-                       setgain(gspca_dev);
-               break;
-       case V4L2_CID_POWER_LINE_FREQUENCY:
-               setfreq(gspca_dev);
-               break;
-       default:
-               return -EINVAL;
-       }
-       return gspca_dev->usb_err;
-}
-
-static const struct v4l2_ctrl_ops sd_ctrl_ops = {
-       .s_ctrl = sd_s_ctrl,
-};
-
-/* this function is called at probe time */
-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, 5);
-
-       if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630 ||
-           sd->sensor == SENSOR_PAS106 || sd->sensor == SENSOR_PAS202)
-               sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
-
-       /* Gain range is sensor dependent */
-       switch (sd->sensor) {
-       case SENSOR_OV6650:
-       case SENSOR_PAS106:
-       case SENSOR_PAS202:
-               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_GAIN, 0, 31, 1, 15);
-               break;
-       case SENSOR_OV7630:
-               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_GAIN, 0, 47, 1, 31);
-               break;
-       case SENSOR_HV7131D:
-               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_GAIN, 0, 63, 1, 31);
-               break;
-       case SENSOR_TAS5110C:
-       case SENSOR_TAS5110D:
-       case SENSOR_TAS5130CXX:
-               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_GAIN, 0, 255, 1, 127);
-               break;
-       default:
-               if (sd->bridge == BRIDGE_103) {
-                       gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                               V4L2_CID_GAIN, 0, 127, 1, 63);
-               } else {
-                       gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                               V4L2_CID_GAIN, 0, 15, 1, 7);
-               }
-       }
-
-       /* Exposure range is sensor dependent, and not all have exposure */
-       switch (sd->sensor) {
-       case SENSOR_HV7131D:
-               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_EXPOSURE, 0, 8191, 1, 482);
-               sd->exposure_knee = 964;
-               break;
-       case SENSOR_OV6650:
-       case SENSOR_OV7630:
-       case SENSOR_PAS106:
-       case SENSOR_PAS202:
-               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_EXPOSURE, 0, 1023, 1, 66);
-               sd->exposure_knee = 200;
-               break;
-       case SENSOR_TAS5110C:
-       case SENSOR_TAS5110D:
-               gspca_dev->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_EXPOSURE, 2, 15, 1, 2);
-               break;
-       }
-
-       if (gspca_dev->exposure) {
-               gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                               V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-       }
-
-       if (sd->sensor == SENSOR_OV6650 || sd->sensor == SENSOR_OV7630)
-               sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
-                       V4L2_CID_POWER_LINE_FREQUENCY,
-                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
-                       V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-
-       if (gspca_dev->autogain)
-               v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
-
-       return 0;
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam = &gspca_dev->cam;
-       int i, mode;
-       __u8 regs[0x31];
-
-       mode = cam->cam_mode[gspca_dev->curr_mode].priv & 0x07;
-       /* Copy registers 0x01 - 0x19 from the template */
-       memcpy(&regs[0x01], sensor_data[sd->sensor].bridge_init, 0x19);
-       /* Set the mode */
-       regs[0x18] |= mode << 4;
-
-       /* Set bridge gain to 1.0 */
-       if (sd->bridge == BRIDGE_103) {
-               regs[0x05] = 0x20; /* Red */
-               regs[0x06] = 0x20; /* Green */
-               regs[0x07] = 0x20; /* Blue */
-       } else {
-               regs[0x10] = 0x00; /* Red and blue */
-               regs[0x11] = 0x00; /* Green */
-       }
-
-       /* Setup pixel numbers and auto exposure window */
-       if (sensor_data[sd->sensor].flags & F_SIF) {
-               regs[0x1a] = 0x14; /* HO_SIZE 640, makes no sense */
-               regs[0x1b] = 0x0a; /* VO_SIZE 320, makes no sense */
-               regs[0x1c] = 0x02; /* AE H-start 64 */
-               regs[0x1d] = 0x02; /* AE V-start 64 */
-               regs[0x1e] = 0x09; /* AE H-end 288 */
-               regs[0x1f] = 0x07; /* AE V-end 224 */
-       } else {
-               regs[0x1a] = 0x1d; /* HO_SIZE 960, makes no sense */
-               regs[0x1b] = 0x10; /* VO_SIZE 512, makes no sense */
-               regs[0x1c] = 0x05; /* AE H-start 160 */
-               regs[0x1d] = 0x03; /* AE V-start 96 */
-               regs[0x1e] = 0x0f; /* AE H-end 480 */
-               regs[0x1f] = 0x0c; /* AE V-end 384 */
-       }
-
-       /* Setup the gamma table (only used with the sn9c103 bridge) */
-       for (i = 0; i < 16; i++)
-               regs[0x20 + i] = i * 16;
-       regs[0x20 + i] = 255;
-
-       /* Special cases where some regs depend on mode or bridge */
-       switch (sd->sensor) {
-       case SENSOR_TAS5130CXX:
-               /* FIXME / TESTME
-                  probably not mode specific at all most likely the upper
-                  nibble of 0x19 is exposure (clock divider) just as with
-                  the tas5110, we need someone to test this. */
-               regs[0x19] = mode ? 0x23 : 0x43;
-               break;
-       case SENSOR_OV7630:
-               /* FIXME / TESTME for some reason with the 101/102 bridge the
-                  clock is set to 12 Mhz (reg1 == 0x04), rather then 24.
-                  Also the hstart needs to go from 1 to 2 when using a 103,
-                  which is likely related. This does not seem right. */
-               if (sd->bridge == BRIDGE_103) {
-                       regs[0x01] = 0x44; /* Select 24 Mhz clock */
-                       regs[0x12] = 0x02; /* Set hstart to 2 */
-               }
-       }
-       /* Disable compression when the raw bayer format has been selected */
-       if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW)
-               regs[0x18] &= ~0x80;
-
-       /* Vga mode emulation on SIF sensor? */
-       if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_REDUCED_SIF) {
-               regs[0x12] += 16;       /* hstart adjust */
-               regs[0x13] += 24;       /* vstart adjust */
-               regs[0x15]  = 320 / 16; /* hsize */
-               regs[0x16]  = 240 / 16; /* vsize */
-       }
-
-       /* reg 0x01 bit 2 video transfert on */
-       reg_w(gspca_dev, 0x01, &regs[0x01], 1);
-       /* reg 0x17 SensorClk enable inv Clk 0x60 */
-       reg_w(gspca_dev, 0x17, &regs[0x17], 1);
-       /* Set the registers from the template */
-       reg_w(gspca_dev, 0x01, &regs[0x01],
-             (sd->bridge == BRIDGE_103) ? 0x30 : 0x1f);
-
-       /* Init the sensor */
-       i2c_w_vector(gspca_dev, sensor_data[sd->sensor].sensor_init,
-                       sensor_data[sd->sensor].sensor_init_size);
-
-       /* Mode / bridge specific sensor setup */
-       switch (sd->sensor) {
-       case SENSOR_PAS202: {
-               const __u8 i2cpclockdiv[] =
-                       {0xa0, 0x40, 0x02, 0x03, 0x00, 0x00, 0x00, 0x10};
-               /* clockdiv from 4 to 3 (7.5 -> 10 fps) when in low res mode */
-               if (mode)
-                       i2c_w(gspca_dev, i2cpclockdiv);
-               break;
-           }
-       case SENSOR_OV7630:
-               /* FIXME / TESTME We should be able to handle this identical
-                  for the 101/102 and the 103 case */
-               if (sd->bridge == BRIDGE_103) {
-                       const __u8 i2c[] = { 0xa0, 0x21, 0x13,
-                                            0x80, 0x00, 0x00, 0x00, 0x10 };
-                       i2c_w(gspca_dev, i2c);
-               }
-               break;
-       }
-       /* H_size V_size 0x28, 0x1e -> 640x480. 0x16, 0x12 -> 352x288 */
-       reg_w(gspca_dev, 0x15, &regs[0x15], 2);
-       /* compression register */
-       reg_w(gspca_dev, 0x18, &regs[0x18], 1);
-       /* H_start */
-       reg_w(gspca_dev, 0x12, &regs[0x12], 1);
-       /* V_START */
-       reg_w(gspca_dev, 0x13, &regs[0x13], 1);
-       /* reset 0x17 SensorClk enable inv Clk 0x60 */
-                               /*fixme: ov7630 [17]=68 8f (+20 if 102)*/
-       reg_w(gspca_dev, 0x17, &regs[0x17], 1);
-       /*MCKSIZE ->3 */        /*fixme: not ov7630*/
-       reg_w(gspca_dev, 0x19, &regs[0x19], 1);
-       /* AE_STRX AE_STRY AE_ENDX AE_ENDY */
-       reg_w(gspca_dev, 0x1c, &regs[0x1c], 4);
-       /* Enable video transfert */
-       reg_w(gspca_dev, 0x01, &regs[0x01], 1);
-       /* Compression */
-       reg_w(gspca_dev, 0x18, &regs[0x18], 2);
-       msleep(20);
-
-       sd->reg11 = -1;
-
-       setgain(gspca_dev);
-       setbrightness(gspca_dev);
-       setexposure(gspca_dev);
-       setfreq(gspca_dev);
-
-       sd->frames_to_drop = 0;
-       sd->autogain_ignore_frames = 0;
-       gspca_dev->exp_too_high_cnt = 0;
-       gspca_dev->exp_too_low_cnt = 0;
-       atomic_set(&sd->avg_lum, -1);
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       sd_init(gspca_dev);
-}
-
-static u8* find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i, header_size = (sd->bridge == BRIDGE_103) ? 18 : 12;
-
-       /* frames start with:
-        *      ff ff 00 c4 c4 96       synchro
-        *      00              (unknown)
-        *      xx              (frame sequence / size / compression)
-        *      (xx)            (idem - extra byte for sn9c103)
-        *      ll mm           brightness sum inside auto exposure
-        *      ll mm           brightness sum outside auto exposure
-        *      (xx xx xx xx xx)        audio values for snc103
-        */
-       for (i = 0; i < len; i++) {
-               switch (sd->header_read) {
-               case 0:
-                       if (data[i] == 0xff)
-                               sd->header_read++;
-                       break;
-               case 1:
-                       if (data[i] == 0xff)
-                               sd->header_read++;
-                       else
-                               sd->header_read = 0;
-                       break;
-               case 2:
-                       if (data[i] == 0x00)
-                               sd->header_read++;
-                       else if (data[i] != 0xff)
-                               sd->header_read = 0;
-                       break;
-               case 3:
-                       if (data[i] == 0xc4)
-                               sd->header_read++;
-                       else if (data[i] == 0xff)
-                               sd->header_read = 1;
-                       else
-                               sd->header_read = 0;
-                       break;
-               case 4:
-                       if (data[i] == 0xc4)
-                               sd->header_read++;
-                       else if (data[i] == 0xff)
-                               sd->header_read = 1;
-                       else
-                               sd->header_read = 0;
-                       break;
-               case 5:
-                       if (data[i] == 0x96)
-                               sd->header_read++;
-                       else if (data[i] == 0xff)
-                               sd->header_read = 1;
-                       else
-                               sd->header_read = 0;
-                       break;
-               default:
-                       sd->header[sd->header_read - 6] = data[i];
-                       sd->header_read++;
-                       if (sd->header_read == header_size) {
-                               sd->header_read = 0;
-                               return data + i + 1;
-                       }
-               }
-       }
-       return NULL;
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,                       /* isoc packet */
-                       int len)                        /* iso packet length */
-{
-       int fr_h_sz = 0, lum_offset = 0, len_after_sof = 0;
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam = &gspca_dev->cam;
-       u8 *sof;
-
-       sof = find_sof(gspca_dev, data, len);
-       if (sof) {
-               if (sd->bridge == BRIDGE_103) {
-                       fr_h_sz = 18;
-                       lum_offset = 3;
-               } else {
-                       fr_h_sz = 12;
-                       lum_offset = 2;
-               }
-
-               len_after_sof = len - (sof - data);
-               len = (sof - data) - fr_h_sz;
-               if (len < 0)
-                       len = 0;
-       }
-
-       if (cam->cam_mode[gspca_dev->curr_mode].priv & MODE_RAW) {
-               /* In raw mode we sometimes get some garbage after the frame
-                  ignore this */
-               int used;
-               int size = cam->cam_mode[gspca_dev->curr_mode].sizeimage;
-
-               used = gspca_dev->image_len;
-               if (used + len > size)
-                       len = size - used;
-       }
-
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-
-       if (sof) {
-               int  lum = sd->header[lum_offset] +
-                         (sd->header[lum_offset + 1] << 8);
-
-               /* When exposure changes midway a frame we
-                  get a lum of 0 in this case drop 2 frames
-                  as the frames directly after an exposure
-                  change have an unstable image. Sometimes lum
-                  *really* is 0 (cam used in low light with
-                  low exposure setting), so do not drop frames
-                  if the previous lum was 0 too. */
-               if (lum == 0 && sd->prev_avg_lum != 0) {
-                       lum = -1;
-                       sd->frames_to_drop = 2;
-                       sd->prev_avg_lum = 0;
-               } else
-                       sd->prev_avg_lum = lum;
-               atomic_set(&sd->avg_lum, lum);
-
-               if (sd->frames_to_drop)
-                       sd->frames_to_drop--;
-               else
-                       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-
-               gspca_frame_add(gspca_dev, FIRST_PACKET, sof, len_after_sof);
-       }
-}
-
-static int sd_querymenu(struct gspca_dev *gspca_dev,
-                       struct v4l2_querymenu *menu)
-{
-       switch (menu->id) {
-       case V4L2_CID_POWER_LINE_FREQUENCY:
-               switch (menu->index) {
-               case 0:         /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
-                       strcpy((char *) menu->name, "NoFliker");
-                       return 0;
-               case 1:         /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
-                       strcpy((char *) menu->name, "50 Hz");
-                       return 0;
-               case 2:         /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
-                       strcpy((char *) menu->name, "60 Hz");
-                       return 0;
-               }
-               break;
-       }
-       return -EINVAL;
-}
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,               /* interrupt packet data */
-                       int len)                /* interrupt packet length */
-{
-       int ret = -EINVAL;
-
-       if (len == 1 && data[0] == 1) {
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
-               input_sync(gspca_dev->input_dev);
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
-               input_sync(gspca_dev->input_dev);
-               ret = 0;
-       }
-
-       return ret;
-}
-#endif
-
-/* 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,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-       .querymenu = sd_querymenu,
-       .dq_callback = do_autogain,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .int_pkt_scan = sd_int_pkt_scan,
-#endif
-};
-
-/* -- module initialisation -- */
-#define SB(sensor, bridge) \
-       .driver_info = (SENSOR_ ## sensor << 8) | BRIDGE_ ## bridge
-
-
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x0c45, 0x6001), SB(TAS5110C, 102)}, /* TAS5110C1B */
-       {USB_DEVICE(0x0c45, 0x6005), SB(TAS5110C, 101)}, /* TAS5110C1B */
-       {USB_DEVICE(0x0c45, 0x6007), SB(TAS5110D, 101)}, /* TAS5110D */
-       {USB_DEVICE(0x0c45, 0x6009), SB(PAS106, 101)},
-       {USB_DEVICE(0x0c45, 0x600d), SB(PAS106, 101)},
-       {USB_DEVICE(0x0c45, 0x6011), SB(OV6650, 101)},
-       {USB_DEVICE(0x0c45, 0x6019), SB(OV7630, 101)},
-#if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
-       {USB_DEVICE(0x0c45, 0x6024), SB(TAS5130CXX, 102)},
-       {USB_DEVICE(0x0c45, 0x6025), SB(TAS5130CXX, 102)},
-#endif
-       {USB_DEVICE(0x0c45, 0x6028), SB(PAS202, 102)},
-       {USB_DEVICE(0x0c45, 0x6029), SB(PAS106, 102)},
-       {USB_DEVICE(0x0c45, 0x602a), SB(HV7131D, 102)},
-       /* {USB_DEVICE(0x0c45, 0x602b), SB(MI0343, 102)}, */
-       {USB_DEVICE(0x0c45, 0x602c), SB(OV7630, 102)},
-       {USB_DEVICE(0x0c45, 0x602d), SB(HV7131R, 102)},
-       {USB_DEVICE(0x0c45, 0x602e), SB(OV7630, 102)},
-       /* {USB_DEVICE(0x0c45, 0x6030), SB(MI03XX, 102)}, */ /* MI0343 MI0360 MI0330 */
-       /* {USB_DEVICE(0x0c45, 0x6082), SB(MI03XX, 103)}, */ /* MI0343 MI0360 */
-       {USB_DEVICE(0x0c45, 0x6083), SB(HV7131D, 103)},
-       {USB_DEVICE(0x0c45, 0x608c), SB(HV7131R, 103)},
-       /* {USB_DEVICE(0x0c45, 0x608e), SB(CISVF10, 103)}, */
-       {USB_DEVICE(0x0c45, 0x608f), SB(OV7630, 103)},
-       {USB_DEVICE(0x0c45, 0x60a8), SB(PAS106, 103)},
-       {USB_DEVICE(0x0c45, 0x60aa), SB(TAS5130CXX, 103)},
-       {USB_DEVICE(0x0c45, 0x60af), SB(PAS202, 103)},
-       {USB_DEVICE(0x0c45, 0x60b0), SB(OV7630, 103)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c
deleted file mode 100644 (file)
index 150b2df..0000000
+++ /dev/null
@@ -1,3206 +0,0 @@
-/*
- * Sonix sn9c102p sn9c105 sn9c120 (jpeg) subdriver
- *
- * Copyright (C) 2009-2011 Jean-François Moine <http://moinejf.free.fr>
- * Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "sonixj"
-
-#include <linux/input.h>
-#include "gspca.h"
-#include "jpeg.h"
-
-MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
-MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* controls */
-enum e_ctrl {
-       BRIGHTNESS,
-       CONTRAST,
-       COLORS,
-       BLUE,
-       RED,
-       GAMMA,
-       EXPOSURE,
-       AUTOGAIN,
-       GAIN,
-       HFLIP,
-       VFLIP,
-       SHARPNESS,
-       ILLUM,
-       FREQ,
-       NCTRLS          /* number of controls */
-};
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       struct gspca_ctrl ctrls[NCTRLS];
-
-       atomic_t avg_lum;
-       u32 exposure;
-
-       struct work_struct work;
-       struct workqueue_struct *work_thread;
-
-       u32 pktsz;                      /* (used by pkt_scan) */
-       u16 npkt;
-       s8 nchg;
-       s8 short_mark;
-
-       u8 quality;                     /* image quality */
-#define QUALITY_MIN 25
-#define QUALITY_MAX 90
-#define QUALITY_DEF 70
-
-       u8 reg01;
-       u8 reg17;
-       u8 reg18;
-       u8 flags;
-
-       s8 ag_cnt;
-#define AG_CNT_START 13
-
-       u8 bridge;
-#define BRIDGE_SN9C102P 0
-#define BRIDGE_SN9C105 1
-#define BRIDGE_SN9C110 2
-#define BRIDGE_SN9C120 3
-       u8 sensor;                      /* Type of image sensor chip */
-       u8 i2c_addr;
-
-       u8 jpeg_hdr[JPEG_HDR_SZ];
-};
-enum sensors {
-       SENSOR_ADCM1700,
-       SENSOR_GC0307,
-       SENSOR_HV7131R,
-       SENSOR_MI0360,
-       SENSOR_MI0360B,
-       SENSOR_MO4000,
-       SENSOR_MT9V111,
-       SENSOR_OM6802,
-       SENSOR_OV7630,
-       SENSOR_OV7648,
-       SENSOR_OV7660,
-       SENSOR_PO1030,
-       SENSOR_PO2030N,
-       SENSOR_SOI768,
-       SENSOR_SP80708,
-};
-
-static void qual_upd(struct work_struct *work);
-
-/* device flags */
-#define F_PDN_INV      0x01    /* inverse pin S_PWR_DN / sn_xxx tables */
-#define F_ILLUM                0x02    /* presence of illuminator */
-
-/* sn9c1xx definitions */
-/* register 0x01 */
-#define S_PWR_DN       0x01    /* sensor power down */
-#define S_PDN_INV      0x02    /* inverse pin S_PWR_DN */
-#define V_TX_EN                0x04    /* video transfer enable */
-#define LED            0x08    /* output to pin LED */
-#define SCL_SEL_OD     0x20    /* open-drain mode */
-#define SYS_SEL_48M    0x40    /* system clock 0: 24MHz, 1: 48MHz */
-/* register 0x17 */
-#define MCK_SIZE_MASK  0x1f    /* sensor master clock */
-#define SEN_CLK_EN     0x20    /* enable sensor clock */
-#define DEF_EN         0x80    /* defect pixel by 0: soft, 1: hard */
-
-/* V4L2 controls supported by the driver */
-static void setbrightness(struct gspca_dev *gspca_dev);
-static void setcontrast(struct gspca_dev *gspca_dev);
-static void setcolors(struct gspca_dev *gspca_dev);
-static void setredblue(struct gspca_dev *gspca_dev);
-static void setgamma(struct gspca_dev *gspca_dev);
-static void setexposure(struct gspca_dev *gspca_dev);
-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
-static void setgain(struct gspca_dev *gspca_dev);
-static void sethvflip(struct gspca_dev *gspca_dev);
-static void setsharpness(struct gspca_dev *gspca_dev);
-static void setillum(struct gspca_dev *gspca_dev);
-static void setfreq(struct gspca_dev *gspca_dev);
-
-static const struct ctrl sd_ctrls[NCTRLS] = {
-[BRIGHTNESS] = {
-           {
-               .id      = V4L2_CID_BRIGHTNESS,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Brightness",
-               .minimum = 0,
-               .maximum = 0xff,
-               .step    = 1,
-               .default_value = 0x80,
-           },
-           .set_control = setbrightness
-       },
-[CONTRAST] = {
-           {
-               .id      = V4L2_CID_CONTRAST,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Contrast",
-               .minimum = 0,
-#define CONTRAST_MAX 127
-               .maximum = CONTRAST_MAX,
-               .step    = 1,
-               .default_value = 20,
-           },
-           .set_control = setcontrast
-       },
-[COLORS] = {
-           {
-               .id      = V4L2_CID_SATURATION,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Saturation",
-               .minimum = 0,
-               .maximum = 40,
-               .step    = 1,
-#define COLORS_DEF 25
-               .default_value = COLORS_DEF,
-           },
-           .set_control = setcolors
-       },
-[BLUE] = {
-           {
-               .id      = V4L2_CID_BLUE_BALANCE,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Blue Balance",
-               .minimum = 24,
-               .maximum = 40,
-               .step    = 1,
-               .default_value = 32,
-           },
-           .set_control = setredblue
-       },
-[RED] = {
-           {
-               .id      = V4L2_CID_RED_BALANCE,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Red Balance",
-               .minimum = 24,
-               .maximum = 40,
-               .step    = 1,
-               .default_value = 32,
-           },
-           .set_control = setredblue
-       },
-[GAMMA] = {
-           {
-               .id      = V4L2_CID_GAMMA,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Gamma",
-               .minimum = 0,
-               .maximum = 40,
-               .step    = 1,
-#define GAMMA_DEF 20
-               .default_value = GAMMA_DEF,
-           },
-           .set_control = setgamma
-       },
-[EXPOSURE] = {
-           {
-               .id      = V4L2_CID_EXPOSURE,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Exposure",
-               .minimum = 500,
-               .maximum = 1500,
-               .step    = 1,
-               .default_value = 1024
-           },
-           .set_control = setexposure
-       },
-[AUTOGAIN] = {
-           {
-               .id      = V4L2_CID_AUTOGAIN,
-               .type    = V4L2_CTRL_TYPE_BOOLEAN,
-               .name    = "Auto Gain",
-               .minimum = 0,
-               .maximum = 1,
-               .step    = 1,
-               .default_value = 1
-           },
-           .set = sd_setautogain,
-       },
-[GAIN] = {
-           {
-               .id      = V4L2_CID_GAIN,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Gain",
-               .minimum = 4,
-               .maximum = 49,
-               .step    = 1,
-               .default_value = 15
-           },
-           .set_control = setgain
-       },
-[HFLIP] = {
-           {
-               .id      = V4L2_CID_HFLIP,
-               .type    = V4L2_CTRL_TYPE_BOOLEAN,
-               .name    = "Mirror",
-               .minimum = 0,
-               .maximum = 1,
-               .step    = 1,
-               .default_value = 0,
-           },
-           .set_control = sethvflip
-       },
-[VFLIP] = {
-           {
-               .id      = V4L2_CID_VFLIP,
-               .type    = V4L2_CTRL_TYPE_BOOLEAN,
-               .name    = "Vflip",
-               .minimum = 0,
-               .maximum = 1,
-               .step    = 1,
-               .default_value = 0,
-           },
-           .set_control = sethvflip
-       },
-[SHARPNESS] = {
-           {
-               .id      = V4L2_CID_SHARPNESS,
-               .type    = V4L2_CTRL_TYPE_INTEGER,
-               .name    = "Sharpness",
-               .minimum = 0,
-               .maximum = 255,
-               .step    = 1,
-               .default_value = 90,
-           },
-           .set_control = setsharpness
-       },
-[ILLUM] = {
-           {
-               .id      = V4L2_CID_ILLUMINATORS_1,
-               .type    = V4L2_CTRL_TYPE_BOOLEAN,
-               .name    = "Illuminator / infrared",
-               .minimum = 0,
-               .maximum = 1,
-               .step    = 1,
-               .default_value = 0,
-           },
-           .set_control = setillum
-       },
-/* ov7630/ov7648/ov7660 only */
-[FREQ] = {
-           {
-               .id      = V4L2_CID_POWER_LINE_FREQUENCY,
-               .type    = V4L2_CTRL_TYPE_MENU,
-               .name    = "Light frequency filter",
-               .minimum = 0,
-               .maximum = 2,   /* 0: 0, 1: 50Hz, 2:60Hz */
-               .step    = 1,
-               .default_value = 1,
-           },
-           .set_control = setfreq
-       },
-};
-
-/* table of the disabled controls */
-static const __u32 ctrl_dis[] = {
-[SENSOR_ADCM1700] =    (1 << EXPOSURE) |
-                       (1 << AUTOGAIN) |
-                       (1 << GAIN) |
-                       (1 << HFLIP) |
-                       (1 << VFLIP) |
-                       (1 << FREQ),
-
-[SENSOR_GC0307] =      (1 << EXPOSURE) |
-                       (1 << GAIN) |
-                       (1 << HFLIP) |
-                       (1 << VFLIP) |
-                       (1 << FREQ),
-
-[SENSOR_HV7131R] =     (1 << EXPOSURE) |
-                       (1 << GAIN) |
-                       (1 << HFLIP) |
-                       (1 << FREQ),
-
-[SENSOR_MI0360] =      (1 << EXPOSURE) |
-                       (1 << GAIN) |
-                       (1 << HFLIP) |
-                       (1 << VFLIP) |
-                       (1 << FREQ),
-
-[SENSOR_MI0360B] =     (1 << EXPOSURE) |
-                       (1 << GAIN) |
-                       (1 << HFLIP) |
-                       (1 << VFLIP) |
-                       (1 << FREQ),
-
-[SENSOR_MO4000] =      (1 << EXPOSURE) |
-                       (1 << GAIN) |
-                       (1 << HFLIP) |
-                       (1 << VFLIP) |
-                       (1 << FREQ),
-
-[SENSOR_MT9V111] =     (1 << EXPOSURE) |
-                       (1 << GAIN) |
-                       (1 << HFLIP) |
-                       (1 << VFLIP) |
-                       (1 << FREQ),
-
-[SENSOR_OM6802] =      (1 << EXPOSURE) |
-                       (1 << GAIN) |
-                       (1 << HFLIP) |
-                       (1 << VFLIP) |
-                       (1 << FREQ),
-
-[SENSOR_OV7630] =      (1 << EXPOSURE) |
-                       (1 << GAIN) |
-                       (1 << HFLIP),
-
-[SENSOR_OV7648] =      (1 << EXPOSURE) |
-                       (1 << GAIN) |
-                       (1 << HFLIP),
-
-[SENSOR_OV7660] =      (1 << EXPOSURE) |
-                       (1 << AUTOGAIN) |
-                       (1 << GAIN) |
-                       (1 << HFLIP) |
-                       (1 << VFLIP),
-
-[SENSOR_PO1030] =      (1 << EXPOSURE) |
-                       (1 << AUTOGAIN) |
-                       (1 << GAIN) |
-                       (1 << HFLIP) |
-                       (1 << VFLIP) |
-                       (1 << FREQ),
-
-[SENSOR_PO2030N] =     (1 << FREQ),
-
-[SENSOR_SOI768] =      (1 << EXPOSURE) |
-                       (1 << AUTOGAIN) |
-                       (1 << GAIN) |
-                       (1 << HFLIP) |
-                       (1 << VFLIP) |
-                       (1 << FREQ),
-
-[SENSOR_SP80708] =     (1 << EXPOSURE) |
-                       (1 << AUTOGAIN) |
-                       (1 << GAIN) |
-                       (1 << HFLIP) |
-                       (1 << VFLIP) |
-                       (1 << FREQ),
-};
-
-static const struct v4l2_pix_format cif_mode[] = {
-       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 4 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-static const struct v4l2_pix_format vga_mode[] = {
-       {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 4 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 2},
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               /* Note 3 / 8 is not large enough, not even 5 / 8 is ?! */
-               .sizeimage = 640 * 480 * 3 / 4 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-
-static const u8 sn_adcm1700[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x43,   0x60,   0x00,   0x1a,   0x00,   0x00,   0x00,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x80,   0x51,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,   0x00,   0x05,   0x01,   0x05,   0x16,   0x12,   0x42,
-/*     reg18   reg19   reg1a   reg1b */
-       0x06,   0x00,   0x00,   0x00
-};
-
-static const u8 sn_gc0307[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x61,   0x62,   0x00,   0x1a,   0x00,   0x00,   0x00,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x80,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,   0x00,   0x03,   0x01,   0x08,   0x28,   0x1e,   0x02,
-/*     reg18   reg19   reg1a   reg1b */
-       0x06,   0x00,   0x00,   0x00
-};
-
-static const u8 sn_hv7131[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x03,   0x60,   0x00,   0x1a,   0x20,   0x20,   0x20,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x81,   0x11,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,   0x00,   0x00,   0x01,   0x03,   0x28,   0x1e,   0x41,
-/*     reg18   reg19   reg1a   reg1b */
-       0x0a,   0x00,   0x00,   0x00
-};
-
-static const u8 sn_mi0360[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x63,   0x40,   0x00,   0x1a,   0x20,   0x20,   0x20,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x81,   0x5d,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,   0x00,   0x00,   0x02,   0x0a,   0x28,   0x1e,   0x61,
-/*     reg18   reg19   reg1a   reg1b */
-       0x06,   0x00,   0x00,   0x00
-};
-
-static const u8 sn_mi0360b[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x61,   0x40,   0x00,   0x1a,   0x00,   0x00,   0x00,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x81,   0x5d,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,   0x00,   0x00,   0x02,   0x0a,   0x28,   0x1e,   0x40,
-/*     reg18   reg19   reg1a   reg1b */
-       0x06,   0x00,   0x00,   0x00
-};
-
-static const u8 sn_mo4000[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x23,   0x60,   0x00,   0x1a,   0x00,   0x20,   0x18,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x81,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,    0x00,  0x0b,   0x0f,   0x14,   0x28,   0x1e,   0x40,
-/*     reg18   reg19   reg1a   reg1b */
-       0x08,   0x00,   0x00,   0x00
-};
-
-static const u8 sn_mt9v111[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x61,   0x40,   0x00,   0x1a,   0x20,   0x20,   0x20,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x81,   0x5c,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,   0x00,   0x00,   0x02,   0x1c,   0x28,   0x1e,   0x40,
-/*     reg18   reg19   reg1a   reg1b */
-       0x06,   0x00,   0x00,   0x00
-};
-
-static const u8 sn_om6802[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x23,   0x72,   0x00,   0x1a,   0x20,   0x20,   0x19,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x80,   0x34,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,   0x00,   0x51,   0x01,   0x00,   0x28,   0x1e,   0x40,
-/*     reg18   reg19   reg1a   reg1b */
-       0x05,   0x00,   0x00,   0x00
-};
-
-static const u8 sn_ov7630[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x21,   0x40,   0x00,   0x1a,   0x00,   0x00,   0x00,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x81,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,   0x00,   0x04,   0x01,   0x0a,   0x28,   0x1e,   0xc2,
-/*     reg18   reg19   reg1a   reg1b */
-       0x0b,   0x00,   0x00,   0x00
-};
-
-static const u8 sn_ov7648[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x63,   0x40,   0x00,   0x1a,   0x20,   0x20,   0x20,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x81,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,   0x00,   0x00,   0x01,   0x00,   0x28,   0x1e,   0x00,
-/*     reg18   reg19   reg1a   reg1b */
-       0x0b,   0x00,   0x00,   0x00
-};
-
-static const u8 sn_ov7660[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x61,   0x40,   0x00,   0x1a,   0x00,   0x00,   0x00,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x81,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,   0x00,   0x01,   0x01,   0x08,   0x28,   0x1e,   0x20,
-/*     reg18   reg19   reg1a   reg1b */
-       0x07,   0x00,   0x00,   0x00
-};
-
-static const u8 sn_po1030[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x21,   0x62,   0x00,   0x1a,   0x20,   0x20,   0x20,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x81,   0x6e,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,   0x00,   0x00,   0x06,   0x06,   0x28,   0x1e,   0x00,
-/*     reg18   reg19   reg1a   reg1b */
-       0x07,   0x00,   0x00,   0x00
-};
-
-static const u8 sn_po2030n[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x63,   0x40,   0x00,   0x1a,   0x00,   0x00,   0x00,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x81,   0x6e,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,   0x00,   0x00,   0x01,   0x14,   0x28,   0x1e,   0x00,
-/*     reg18   reg19   reg1a   reg1b */
-       0x07,   0x00,   0x00,   0x00
-};
-
-static const u8 sn_soi768[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x21,   0x40,   0x00,   0x1a,   0x00,   0x00,   0x00,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x81,   0x21,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,   0x00,   0x00,   0x01,   0x08,   0x28,   0x1e,   0x00,
-/*     reg18   reg19   reg1a   reg1b */
-       0x07,   0x00,   0x00,   0x00
-};
-
-static const u8 sn_sp80708[0x1c] = {
-/*     reg0    reg1    reg2    reg3    reg4    reg5    reg6    reg7 */
-       0x00,   0x63,   0x60,   0x00,   0x1a,   0x20,   0x20,   0x20,
-/*     reg8    reg9    rega    regb    regc    regd    rege    regf */
-       0x81,   0x18,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00,
-/*     reg10   reg11   reg12   reg13   reg14   reg15   reg16   reg17 */
-       0x03,   0x00,   0x00,   0x03,   0x04,   0x28,   0x1e,   0x00,
-/*     reg18   reg19   reg1a   reg1b */
-       0x07,   0x00,   0x00,   0x00
-};
-
-/* sequence specific to the sensors - !! index = SENSOR_xxx */
-static const u8 *sn_tb[] = {
-[SENSOR_ADCM1700] =    sn_adcm1700,
-[SENSOR_GC0307] =      sn_gc0307,
-[SENSOR_HV7131R] =     sn_hv7131,
-[SENSOR_MI0360] =      sn_mi0360,
-[SENSOR_MI0360B] =     sn_mi0360b,
-[SENSOR_MO4000] =      sn_mo4000,
-[SENSOR_MT9V111] =     sn_mt9v111,
-[SENSOR_OM6802] =      sn_om6802,
-[SENSOR_OV7630] =      sn_ov7630,
-[SENSOR_OV7648] =      sn_ov7648,
-[SENSOR_OV7660] =      sn_ov7660,
-[SENSOR_PO1030] =      sn_po1030,
-[SENSOR_PO2030N] =     sn_po2030n,
-[SENSOR_SOI768] =      sn_soi768,
-[SENSOR_SP80708] =     sn_sp80708,
-};
-
-/* default gamma table */
-static const u8 gamma_def[17] = {
-       0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
-       0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
-};
-/* gamma for sensor ADCM1700 */
-static const u8 gamma_spec_0[17] = {
-       0x0f, 0x39, 0x5a, 0x74, 0x86, 0x95, 0xa6, 0xb4,
-       0xbd, 0xc4, 0xcc, 0xd4, 0xd5, 0xde, 0xe4, 0xed, 0xf5
-};
-/* gamma for sensors HV7131R and MT9V111 */
-static const u8 gamma_spec_1[17] = {
-       0x08, 0x3a, 0x52, 0x65, 0x75, 0x83, 0x91, 0x9d,
-       0xa9, 0xb4, 0xbe, 0xc8, 0xd2, 0xdb, 0xe4, 0xed, 0xf5
-};
-/* gamma for sensor GC0307 */
-static const u8 gamma_spec_2[17] = {
-       0x14, 0x37, 0x50, 0x6a, 0x7c, 0x8d, 0x9d, 0xab,
-       0xb5, 0xbf, 0xc2, 0xcb, 0xd1, 0xd6, 0xdb, 0xe1, 0xeb
-};
-/* gamma for sensor SP80708 */
-static const u8 gamma_spec_3[17] = {
-       0x0a, 0x2d, 0x4e, 0x68, 0x7d, 0x8f, 0x9f, 0xab,
-       0xb7, 0xc2, 0xcc, 0xd3, 0xd8, 0xde, 0xe2, 0xe5, 0xe6
-};
-
-/* color matrix and offsets */
-static const u8 reg84[] = {
-       0x14, 0x00, 0x27, 0x00, 0x07, 0x00,     /* YR YG YB gains */
-       0xe8, 0x0f, 0xda, 0x0f, 0x40, 0x00,     /* UR UG UB */
-       0x3e, 0x00, 0xcd, 0x0f, 0xf7, 0x0f,     /* VR VG VB */
-       0x00, 0x00, 0x00                        /* YUV offsets */
-};
-
-#define DELAY  0xdd
-
-static const u8 adcm1700_sensor_init[][8] = {
-       {0xa0, 0x51, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xb0, 0x51, 0x04, 0x08, 0x00, 0x00, 0x00, 0x10},       /* reset */
-       {DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-       {0xb0, 0x51, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {DELAY, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-       {0xb0, 0x51, 0x0c, 0xe0, 0x2e, 0x00, 0x00, 0x10},
-       {0xb0, 0x51, 0x10, 0x02, 0x02, 0x00, 0x00, 0x10},
-       {0xb0, 0x51, 0x14, 0x0e, 0x0e, 0x00, 0x00, 0x10},
-       {0xb0, 0x51, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x10},
-       {0xb0, 0x51, 0x20, 0x01, 0x00, 0x00, 0x00, 0x10},
-       {DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-       {0xb0, 0x51, 0x04, 0x04, 0x00, 0x00, 0x00, 0x10},
-       {DELAY, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
-       {0xb0, 0x51, 0x04, 0x01, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
-       {0xb0, 0x51, 0x14, 0x01, 0x00, 0x00, 0x00, 0x10},
-       {0xb0, 0x51, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {}
-};
-static const u8 adcm1700_sensor_param1[][8] = {
-       {0xb0, 0x51, 0x26, 0xf9, 0x01, 0x00, 0x00, 0x10},       /* exposure? */
-       {0xd0, 0x51, 0x1e, 0x8e, 0x8e, 0x8e, 0x8e, 0x10},
-
-       {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
-       {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
-       {0xb0, 0x51, 0x32, 0x00, 0x72, 0x00, 0x00, 0x10},
-       {0xd0, 0x51, 0x1e, 0xbe, 0xd7, 0xe8, 0xbe, 0x10},       /* exposure? */
-
-       {0xa0, 0x51, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x10},
-       {0xb0, 0x51, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x51, 0xfe, 0x10, 0x00, 0x00, 0x00, 0x10},
-       {0xb0, 0x51, 0x32, 0x00, 0xa2, 0x00, 0x00, 0x10},
-       {}
-};
-static const u8 gc0307_sensor_init[][8] = {
-       {0xa0, 0x21, 0x43, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x44, 0xa2, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x01, 0x6a, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x02, 0x70, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x11, 0x05, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x08, 0x02, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x09, 0x01, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x0a, 0xe8, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x0b, 0x02, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x0c, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x0d, 0x22, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x0e, 0x02, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x0f, 0xb2, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x12, 0x70, 0x00, 0x00, 0x00, 0x10},
-       {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 10ms*/
-       {0xa0, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x15, 0xb8, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x16, 0x13, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x17, 0x52, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x18, 0x50, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x1e, 0x0d, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x1f, 0x32, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x61, 0x90, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x63, 0x70, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x65, 0x98, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x67, 0x90, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x04, 0x96, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x45, 0x27, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x47, 0x2c, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x43, 0x47, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x44, 0xd8, 0x00, 0x00, 0x00, 0x10},
-       {}
-};
-static const u8 gc0307_sensor_param1[][8] = {
-       {0xa0, 0x21, 0x68, 0x13, 0x00, 0x00, 0x00, 0x10},
-       {0xd0, 0x21, 0x61, 0x80, 0x00, 0x80, 0x00, 0x10},
-       {0xc0, 0x21, 0x65, 0x80, 0x00, 0x80, 0x00, 0x10},
-       {0xc0, 0x21, 0x63, 0xa0, 0x00, 0xa6, 0x00, 0x10},
-/*param3*/
-       {0xa0, 0x21, 0x01, 0x6e, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x21, 0x02, 0x88, 0x00, 0x00, 0x00, 0x10},
-       {}
-};
-
-static const u8 hv7131r_sensor_init[][8] = {
-       {0xc1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
-       {0xb1, 0x11, 0x34, 0x17, 0x7f, 0x00, 0x00, 0x10},
-       {0xd1, 0x11, 0x40, 0xff, 0x7f, 0x7f, 0x7f, 0x10},
-/*     {0x91, 0x11, 0x44, 0x00, 0x00, 0x00, 0x00, 0x10}, */
-       {0xd1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x11, 0x14, 0x01, 0xe2, 0x02, 0x82, 0x10},
-/*     {0x91, 0x11, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10}, */
-
-       {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
-       {0xc1, 0x11, 0x25, 0x00, 0x61, 0xa8, 0x00, 0x10},
-       {0xa1, 0x11, 0x30, 0x22, 0x00, 0x00, 0x00, 0x10},
-       {0xc1, 0x11, 0x31, 0x20, 0x2e, 0x20, 0x00, 0x10},
-       {0xc1, 0x11, 0x25, 0x00, 0xc3, 0x50, 0x00, 0x10},
-       {0xa1, 0x11, 0x30, 0x07, 0x00, 0x00, 0x00, 0x10}, /* gain14 */
-       {0xc1, 0x11, 0x31, 0x10, 0x10, 0x10, 0x00, 0x10}, /* r g b 101a10 */
-
-       {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x11, 0x23, 0x09, 0x00, 0x00, 0x00, 0x10},
-
-       {0xa1, 0x11, 0x01, 0x08, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x11, 0x21, 0xd0, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x11, 0x23, 0x10, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x11, 0x01, 0x18, 0x00, 0x00, 0x00, 0x10},
-                                                       /* set sensor clock */
-       {}
-};
-static const u8 mi0360_sensor_init[][8] = {
-       {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
-       {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
-       {0xd1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x53, 0x10},
-       {0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
-       {0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
-       {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
-       {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
-       {0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
-       {0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
-       {0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
-
-       {0xb1, 0x5d, 0x20, 0x91, 0x01, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x2b, 0x00, 0xa0, 0x00, 0xb0, 0x10},
-       {0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0xa0, 0x10},
-
-       {0xb1, 0x5d, 0x0a, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor clck ?2 */
-       {0xb1, 0x5d, 0x06, 0x00, 0x30, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
-
-       {0xd1, 0x5d, 0x2b, 0x00, 0xb9, 0x00, 0xe3, 0x10},
-       {0xd1, 0x5d, 0x2d, 0x00, 0x5f, 0x00, 0xb9, 0x10}, /* 42 */
-/*     {0xb1, 0x5d, 0x35, 0x00, 0x67, 0x00, 0x00, 0x10}, * gain orig */
-/*     {0xb1, 0x5d, 0x35, 0x00, 0x20, 0x00, 0x00, 0x10}, * gain */
-       {0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
-       {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
-       {}
-};
-static const u8 mi0360b_sensor_init[][8] = {
-       {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10},
-       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/
-       {0xb1, 0x5d, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /*delay 20ms*/
-       {0xd1, 0x5d, 0x01, 0x00, 0x08, 0x00, 0x16, 0x10},
-       {0xd1, 0x5d, 0x03, 0x01, 0xe2, 0x02, 0x82, 0x10},
-       {0xd1, 0x5d, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x0d, 0x00, 0x02, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x32, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x24, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x26, 0x00, 0x00, 0x00, 0x24, 0x10},
-       {0xd1, 0x5d, 0x2f, 0xf7, 0xb0, 0x00, 0x04, 0x10},
-       {0xd1, 0x5d, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x33, 0x00, 0x00, 0x01, 0x00, 0x10},
-       {0xb1, 0x5d, 0x3d, 0x06, 0x8f, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x40, 0x01, 0xe0, 0x00, 0xd1, 0x10},
-       {0xb1, 0x5d, 0x44, 0x00, 0x82, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x58, 0x00, 0x78, 0x00, 0x43, 0x10},
-       {0xd1, 0x5d, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x5e, 0x00, 0x00, 0xa3, 0x1d, 0x10},
-       {0xb1, 0x5d, 0x62, 0x04, 0x11, 0x00, 0x00, 0x10},
-
-       {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x20, 0x11, 0x01, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x09, 0x00, 0x64, 0x00, 0x00, 0x10},
-       {0xd1, 0x5d, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10},
-       {0xd1, 0x5d, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10},
-       {}
-};
-static const u8 mi0360b_sensor_param1[][8] = {
-       {0xb1, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x06, 0x00, 0x53, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10},
-       {0xb1, 0x5d, 0x09, 0x02, 0x35, 0x00, 0x00, 0x10}, /* exposure 2 */
-
-       {0xd1, 0x5d, 0x2b, 0x00, 0xd1, 0x01, 0xc9, 0x10},
-       {0xd1, 0x5d, 0x2d, 0x00, 0xed, 0x00, 0xd1, 0x10},
-       {0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10}, /* update */
-       {0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10}, /* sensor on */
-       {}
-};
-static const u8 mo4000_sensor_init[][8] = {
-       {0xa1, 0x21, 0x01, 0x02, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x05, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x05, 0x04, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x06, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x06, 0x81, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x11, 0x20, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x11, 0x30, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x0f, 0x20, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x11, 0x38, 0x00, 0x00, 0x00, 0x10},
-       {}
-};
-static const u8 mt9v111_sensor_init[][8] = {
-       {0xb1, 0x5c, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x10}, /* reset? */
-       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
-       {0xb1, 0x5c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */
-       {0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */
-       {0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */
-       {0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */
-       {0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */
-       {0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */
-       {0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */
-       {0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */
-       {0xb1, 0x5c, 0x07, 0x30, 0x02, 0x00, 0x00, 0x10}, /* output ctrl */
-       {0xb1, 0x5c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x10}, /* shutter delay */
-       {0xb1, 0x5c, 0x12, 0x00, 0xb0, 0x00, 0x00, 0x10}, /* zoom col start */
-       {0xb1, 0x5c, 0x13, 0x00, 0x7c, 0x00, 0x00, 0x10}, /* zoom row start */
-       {0xb1, 0x5c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* digital zoom */
-       {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10}, /* read mode */
-       {0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {}
-};
-static const u8 mt9v111_sensor_param1[][8] = {
-       {0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xad, 0x10}, /* G1 and B gains */
-       {0xd1, 0x5c, 0x2d, 0x00, 0xad, 0x00, 0x33, 0x10}, /* R and G2 gains */
-       {0xb1, 0x5c, 0x06, 0x00, 0x40, 0x00, 0x00, 0x10}, /* vert blanking */
-       {0xb1, 0x5c, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10}, /* horiz blanking */
-       {0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */
-       {}
-};
-static const u8 om6802_init0[2][8] = {
-/*fixme: variable*/
-       {0xa0, 0x34, 0x29, 0x0e, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x34, 0x23, 0xb0, 0x00, 0x00, 0x00, 0x10},
-};
-static const u8 om6802_sensor_init[][8] = {
-       {0xa0, 0x34, 0xdf, 0x6d, 0x00, 0x00, 0x00, 0x10},
-                                               /* factory mode */
-       {0xa0, 0x34, 0xdd, 0x18, 0x00, 0x00, 0x00, 0x10},
-                                               /* output raw RGB */
-       {0xa0, 0x34, 0x5a, 0xc0, 0x00, 0x00, 0x00, 0x10},
-/*     {0xa0, 0x34, 0xfb, 0x11, 0x00, 0x00, 0x00, 0x10}, */
-       {0xa0, 0x34, 0xf0, 0x04, 0x00, 0x00, 0x00, 0x10},
-               /* auto-exposure speed (0) / white balance mode (auto RGB) */
-/*     {0xa0, 0x34, 0xf1, 0x02, 0x00, 0x00, 0x00, 0x10},
-                                                        * set color mode */
-/*     {0xa0, 0x34, 0xfe, 0x5b, 0x00, 0x00, 0x00, 0x10},
-                                                * max AGC value in AE */
-/*     {0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10},
-                                                        * preset AGC */
-/*     {0xa0, 0x34, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x10},
-                                                * preset brightness */
-/*     {0xa0, 0x34, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10},
-                                                        * preset contrast */
-/*     {0xa0, 0x34, 0xe8, 0x31, 0x00, 0x00, 0x00, 0x10},
-                                                        * preset gamma */
-       {0xa0, 0x34, 0xe9, 0x0f, 0x00, 0x00, 0x00, 0x10},
-                               /* luminance mode (0x4f -> AutoExpo on) */
-       {0xa0, 0x34, 0xe4, 0xff, 0x00, 0x00, 0x00, 0x10},
-                                                       /* preset shutter */
-/*     {0xa0, 0x34, 0xef, 0x00, 0x00, 0x00, 0x00, 0x10},
-                                                        * auto frame rate */
-/*     {0xa0, 0x34, 0xfb, 0xee, 0x00, 0x00, 0x00, 0x10}, */
-       {0xa0, 0x34, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {}
-};
-static const u8 om6802_sensor_param1[][8] = {
-       {0xa0, 0x34, 0x71, 0x84, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x34, 0x72, 0x05, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x34, 0x68, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {0xa0, 0x34, 0x69, 0x01, 0x00, 0x00, 0x00, 0x10},
-       {}
-};
-static const u8 ov7630_sensor_init[][8] = {
-       {0xa1, 0x21, 0x76, 0x01, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
-       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
-       {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
-       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
-       {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
-/* win: i2c_r from 00 to 80 */
-       {0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
-       {0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
-/* HDG: 0x11 was 0x00 change to 0x01 for better exposure (15 fps instead of 30)
-       0x13 was 0xc0 change to 0xc3 for auto gain and exposure */
-       {0xd1, 0x21, 0x11, 0x01, 0x48, 0xc3, 0x00, 0x10},
-       {0xb1, 0x21, 0x15, 0x80, 0x03, 0x00, 0x00, 0x10},
-       {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
-       {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x21, 0x1f, 0x00, 0x80, 0x80, 0x80, 0x10},
-       {0xd1, 0x21, 0x23, 0xde, 0x10, 0x8a, 0xa0, 0x10},
-       {0xc1, 0x21, 0x27, 0xca, 0xa2, 0x74, 0x00, 0x10},
-       {0xd1, 0x21, 0x2a, 0x88, 0x00, 0x88, 0x01, 0x10},
-       {0xc1, 0x21, 0x2e, 0x80, 0x00, 0x18, 0x00, 0x10},
-       {0xa1, 0x21, 0x21, 0x08, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xb1, 0x21, 0x32, 0xc2, 0x08, 0x00, 0x00, 0x10},
-       {0xb1, 0x21, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x21, 0x60, 0x05, 0x40, 0x12, 0x57, 0x10},
-       {0xa1, 0x21, 0x64, 0x73, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x21, 0x65, 0x00, 0x55, 0x01, 0xac, 0x10},
-       {0xa1, 0x21, 0x69, 0x38, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x21, 0x6f, 0x1f, 0x01, 0x00, 0x10, 0x10},
-       {0xd1, 0x21, 0x73, 0x50, 0x20, 0x02, 0x01, 0x10},
-       {0xd1, 0x21, 0x77, 0xf3, 0x90, 0x98, 0x98, 0x10},
-       {0xc1, 0x21, 0x7b, 0x00, 0x4c, 0xf7, 0x00, 0x10},
-       {0xd1, 0x21, 0x17, 0x1b, 0xbd, 0x05, 0xf6, 0x10},
-       {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
-       {}
-};
-static const u8 ov7630_sensor_param1[][8] = {
-       {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
-/*fixme: + 0x12, 0x04*/
-/*     {0xa1, 0x21, 0x75, 0x82, 0x00, 0x00, 0x00, 0x10},  * COMN
-                                                        * set by setvflip */
-       {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
-/* */
-/*     {0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
-/*     {0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10}, * set by setfreq */
-/* */
-       {0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
-/*     {0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10}, */
-       {}
-};
-
-static const u8 ov7648_sensor_init[][8] = {
-       {0xa1, 0x21, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10},       /* reset */
-       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
-       {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x21, 0x03, 0xa4, 0x30, 0x88, 0x00, 0x10},
-       {0xb1, 0x21, 0x11, 0x80, 0x08, 0x00, 0x00, 0x10},
-       {0xc1, 0x21, 0x13, 0xa0, 0x04, 0x84, 0x00, 0x10},
-       {0xd1, 0x21, 0x17, 0x1a, 0x02, 0xba, 0xf4, 0x10},
-       {0xa1, 0x21, 0x1b, 0x04, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x21, 0x1f, 0x41, 0xc0, 0x80, 0x80, 0x10},
-       {0xd1, 0x21, 0x23, 0xde, 0xa0, 0x80, 0x32, 0x10},
-       {0xd1, 0x21, 0x27, 0xfe, 0xa0, 0x00, 0x91, 0x10},
-       {0xd1, 0x21, 0x2b, 0x00, 0x88, 0x85, 0x80, 0x10},
-       {0xc1, 0x21, 0x2f, 0x9c, 0x00, 0xc4, 0x00, 0x10},
-       {0xd1, 0x21, 0x60, 0xa6, 0x60, 0x88, 0x12, 0x10},
-       {0xd1, 0x21, 0x64, 0x88, 0x00, 0x00, 0x94, 0x10},
-       {0xd1, 0x21, 0x68, 0x7a, 0x0c, 0x00, 0x00, 0x10},
-       {0xd1, 0x21, 0x6c, 0x11, 0x33, 0x22, 0x00, 0x10},
-       {0xd1, 0x21, 0x70, 0x11, 0x00, 0x10, 0x50, 0x10},
-       {0xd1, 0x21, 0x74, 0x20, 0x06, 0x00, 0xb5, 0x10},
-       {0xd1, 0x21, 0x78, 0x8a, 0x00, 0x00, 0x00, 0x10},
-       {0xb1, 0x21, 0x7c, 0x00, 0x43, 0x00, 0x00, 0x10},
-
-       {0xd1, 0x21, 0x21, 0x86, 0x00, 0xde, 0xa0, 0x10},
-/*     {0xd1, 0x21, 0x25, 0x80, 0x32, 0xfe, 0xa0, 0x10}, jfm done */
-/*     {0xd1, 0x21, 0x29, 0x00, 0x91, 0x00, 0x88, 0x10}, jfm done */
-/*     {0xb1, 0x21, 0x2d, 0x85, 0x00, 0x00, 0x00, 0x10}, set by setfreq */
-       {}
-};
-static const u8 ov7648_sensor_param1[][8] = {
-/*     {0xa1, 0x21, 0x12, 0x08, 0x00, 0x00, 0x00, 0x10}, jfm done */
-/*     {0xa1, 0x21, 0x75, 0x06, 0x00, 0x00, 0x00, 0x10},   * COMN
-                                                        * set by setvflip */
-       {0xa1, 0x21, 0x19, 0x02, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
-/*     {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
-/*     {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},  * GAIN - def */
-/*     {0xb1, 0x21, 0x01, 0x6c, 0x6c, 0x00, 0x00, 0x10},  * B R - def: 80 */
-/*...*/
-       {0xa1, 0x21, 0x11, 0x81, 0x00, 0x00, 0x00, 0x10}, /* CLKRC */
-/*     {0xa1, 0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
-/*     {0xa1, 0x21, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
-/*     {0xa1, 0x21, 0x2a, 0x91, 0x00, 0x00, 0x00, 0x10}, jfm done */
-/*     {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, jfm done */
-/*     {0xb1, 0x21, 0x01, 0x64, 0x84, 0x00, 0x00, 0x10},  * B R - def: 80 */
-
-       {}
-};
-
-static const u8 ov7660_sensor_init[][8] = {
-       {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset SCCB */
-       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
-       {0xa1, 0x21, 0x12, 0x05, 0x00, 0x00, 0x00, 0x10},
-                                               /* Outformat = rawRGB */
-       {0xa1, 0x21, 0x13, 0xb8, 0x00, 0x00, 0x00, 0x10}, /* init COM8 */
-       {0xd1, 0x21, 0x00, 0x01, 0x74, 0x92, 0x00, 0x10},
-                                               /* GAIN BLUE RED VREF */
-       {0xd1, 0x21, 0x04, 0x00, 0x7d, 0x62, 0x00, 0x10},
-                                               /* COM 1 BAVE GEAVE AECHH */
-       {0xb1, 0x21, 0x08, 0x83, 0x01, 0x00, 0x00, 0x10}, /* RAVE COM2 */
-       {0xd1, 0x21, 0x0c, 0x00, 0x08, 0x04, 0x4f, 0x10}, /* COM 3 4 5 6 */
-       {0xd1, 0x21, 0x10, 0x7f, 0x40, 0x05, 0xff, 0x10},
-                                               /* AECH CLKRC COM7 COM8 */
-       {0xc1, 0x21, 0x14, 0x2c, 0x00, 0x02, 0x00, 0x10}, /* COM9 COM10 */
-       {0xd1, 0x21, 0x17, 0x10, 0x60, 0x02, 0x7b, 0x10},
-                                               /* HSTART HSTOP VSTRT VSTOP */
-       {0xa1, 0x21, 0x1b, 0x02, 0x00, 0x00, 0x00, 0x10}, /* PSHFT */
-       {0xb1, 0x21, 0x1e, 0x01, 0x0e, 0x00, 0x00, 0x10}, /* MVFP LAEC */
-       {0xd1, 0x21, 0x20, 0x07, 0x07, 0x07, 0x07, 0x10},
-                                       /* BOS GBOS GROS ROS (BGGR offset) */
-/*     {0xd1, 0x21, 0x24, 0x68, 0x58, 0xd4, 0x80, 0x10}, */
-       {0xd1, 0x21, 0x24, 0x78, 0x68, 0xd4, 0x80, 0x10},
-                                               /* AEW AEB VPT BBIAS */
-       {0xd1, 0x21, 0x28, 0x80, 0x30, 0x00, 0x00, 0x10},
-                                               /* GbBIAS RSVD EXHCH EXHCL */
-       {0xd1, 0x21, 0x2c, 0x80, 0x00, 0x00, 0x62, 0x10},
-                                               /* RBIAS ADVFL ASDVFH YAVE */
-       {0xc1, 0x21, 0x30, 0x08, 0x30, 0xb4, 0x00, 0x10},
-                                               /* HSYST HSYEN HREF */
-       {0xd1, 0x21, 0x33, 0x00, 0x07, 0x84, 0x00, 0x10}, /* reserved */
-       {0xd1, 0x21, 0x37, 0x0c, 0x02, 0x43, 0x00, 0x10},
-                                               /* ADC ACOM OFON TSLB */
-       {0xd1, 0x21, 0x3b, 0x02, 0x6c, 0x19, 0x0e, 0x10},
-                                               /* COM11 COM12 COM13 COM14 */
-       {0xd1, 0x21, 0x3f, 0x41, 0xc1, 0x22, 0x08, 0x10},
-                                               /* EDGE COM15 COM16 COM17 */
-       {0xd1, 0x21, 0x43, 0xf0, 0x10, 0x78, 0xa8, 0x10}, /* reserved */
-       {0xd1, 0x21, 0x47, 0x60, 0x80, 0x00, 0x00, 0x10}, /* reserved */
-       {0xd1, 0x21, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* reserved */
-       {0xd1, 0x21, 0x4f, 0x46, 0x36, 0x0f, 0x17, 0x10}, /* MTX 1 2 3 4 */
-       {0xd1, 0x21, 0x53, 0x7f, 0x96, 0x40, 0x40, 0x10}, /* MTX 5 6 7 8 */
-       {0xb1, 0x21, 0x57, 0x40, 0x0f, 0x00, 0x00, 0x10}, /* MTX9 MTXS */
-       {0xd1, 0x21, 0x59, 0xba, 0x9a, 0x22, 0xb9, 0x10}, /* reserved */
-       {0xd1, 0x21, 0x5d, 0x9b, 0x10, 0xf0, 0x05, 0x10}, /* reserved */
-       {0xa1, 0x21, 0x61, 0x60, 0x00, 0x00, 0x00, 0x10}, /* reserved */
-       {0xd1, 0x21, 0x62, 0x00, 0x00, 0x50, 0x30, 0x10},
-                                               /* LCC1 LCC2 LCC3 LCC4 */
-       {0xa1, 0x21, 0x66, 0x00, 0x00, 0x00, 0x00, 0x10}, /* LCC5 */
-       {0xd1, 0x21, 0x67, 0x80, 0x7a, 0x90, 0x80, 0x10}, /* MANU */
-       {0xa1, 0x21, 0x6b, 0x0a, 0x00, 0x00, 0x00, 0x10},
-                                       /* band gap reference [0:3] DBLV */
-       {0xd1, 0x21, 0x6c, 0x30, 0x48, 0x80, 0x74, 0x10}, /* gamma curve */
-       {0xd1, 0x21, 0x70, 0x64, 0x60, 0x5c, 0x58, 0x10}, /* gamma curve */
-       {0xd1, 0x21, 0x74, 0x54, 0x4c, 0x40, 0x38, 0x10}, /* gamma curve */
-       {0xd1, 0x21, 0x78, 0x34, 0x30, 0x2f, 0x2b, 0x10}, /* gamma curve */
-       {0xd1, 0x21, 0x7c, 0x03, 0x07, 0x17, 0x34, 0x10}, /* gamma curve */
-       {0xd1, 0x21, 0x80, 0x41, 0x4d, 0x58, 0x63, 0x10}, /* gamma curve */
-       {0xd1, 0x21, 0x84, 0x6e, 0x77, 0x87, 0x95, 0x10}, /* gamma curve */
-       {0xc1, 0x21, 0x88, 0xaf, 0xc7, 0xdf, 0x00, 0x10}, /* gamma curve */
-       {0xc1, 0x21, 0x8b, 0x99, 0x99, 0xcf, 0x00, 0x10}, /* reserved */
-       {0xb1, 0x21, 0x92, 0x00, 0x00, 0x00, 0x00, 0x10}, /* DM_LNL/H */
-/* not in all ms-win traces*/
-       {0xa1, 0x21, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {}
-};
-static const u8 ov7660_sensor_param1[][8] = {
-       {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10}, /* MVFP */
-                                               /* bits[3..0]reserved */
-       {0xa1, 0x21, 0x1e, 0x01, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
-                                               /* VREF vertical frame ctrl */
-       {0xa1, 0x21, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10}, /* AECH 0x20 */
-       {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFL */
-       {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, /* ADVFH */
-       {0xa1, 0x21, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x10}, /* GAIN */
-/*     {0xb1, 0x21, 0x01, 0x78, 0x78, 0x00, 0x00, 0x10}, * BLUE */
-/****** (some exchanges in the win trace) ******/
-/*fixme:param2*/
-       {0xa1, 0x21, 0x93, 0x00, 0x00, 0x00, 0x00, 0x10},/* dummy line hight */
-       {0xa1, 0x21, 0x92, 0x25, 0x00, 0x00, 0x00, 0x10}, /* dummy line low */
-       {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCH */
-       {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10}, /* EXHCL */
-/*     {0xa1, 0x21, 0x02, 0x90, 0x00, 0x00, 0x00, 0x10},  * RED */
-/****** (some exchanges in the win trace) ******/
-/******!! startsensor KO if changed !!****/
-/*fixme: param3*/
-       {0xa1, 0x21, 0x93, 0x01, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x92, 0xff, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x2b, 0xc3, 0x00, 0x00, 0x00, 0x10},
-       {}
-};
-
-static const u8 po1030_sensor_init[][8] = {
-/* the sensor registers are described in m5602/m5602_po1030.h */
-       {0xa1, 0x6e, 0x3f, 0x20, 0x00, 0x00, 0x00, 0x10}, /* sensor reset */
-       {DELAY, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 20ms */
-       {0xa1, 0x6e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x6e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x04, 0x02, 0xb1, 0x02, 0x39, 0x10},
-       {0xd1, 0x6e, 0x08, 0x00, 0x01, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x0c, 0x02, 0x7f, 0x01, 0xe0, 0x10},
-       {0xd1, 0x6e, 0x12, 0x03, 0x02, 0x00, 0x03, 0x10},
-       {0xd1, 0x6e, 0x16, 0x85, 0x40, 0x4a, 0x40, 0x10}, /* r/g1/b/g2 gains */
-       {0xc1, 0x6e, 0x1a, 0x00, 0x80, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x1d, 0x08, 0x03, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x23, 0x00, 0xb0, 0x00, 0x94, 0x10},
-       {0xd1, 0x6e, 0x27, 0x58, 0x00, 0x00, 0x00, 0x10},
-       {0xb1, 0x6e, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x2d, 0x14, 0x35, 0x61, 0x84, 0x10}, /* gamma corr */
-       {0xd1, 0x6e, 0x31, 0xa2, 0xbd, 0xd8, 0xff, 0x10},
-       {0xd1, 0x6e, 0x35, 0x06, 0x1e, 0x12, 0x02, 0x10}, /* color matrix */
-       {0xd1, 0x6e, 0x39, 0xaa, 0x53, 0x37, 0xd5, 0x10},
-       {0xa1, 0x6e, 0x3d, 0xf2, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x3e, 0x00, 0x00, 0x80, 0x03, 0x10},
-       {0xd1, 0x6e, 0x42, 0x03, 0x00, 0x00, 0x00, 0x10},
-       {0xc1, 0x6e, 0x46, 0x00, 0x80, 0x80, 0x00, 0x10},
-       {0xd1, 0x6e, 0x4b, 0x02, 0xef, 0x08, 0xcd, 0x10},
-       {0xd1, 0x6e, 0x4f, 0x00, 0xd0, 0x00, 0xa0, 0x10},
-       {0xd1, 0x6e, 0x53, 0x01, 0xaa, 0x01, 0x40, 0x10},
-       {0xd1, 0x6e, 0x5a, 0x50, 0x04, 0x30, 0x03, 0x10}, /* raw rgb bayer */
-       {0xa1, 0x6e, 0x5e, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x5f, 0x10, 0x40, 0xff, 0x00, 0x10},
-
-       {0xd1, 0x6e, 0x63, 0x40, 0x40, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xc1, 0x6e, 0x73, 0x10, 0x80, 0xeb, 0x00, 0x10},
-       {}
-};
-static const u8 po1030_sensor_param1[][8] = {
-/* from ms-win traces - these values change with auto gain/expo/wb.. */
-       {0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x6e, 0x1e, 0x03, 0x00, 0x00, 0x00, 0x10},
-/* mean values */
-       {0xc1, 0x6e, 0x1a, 0x02, 0xd4, 0xa4, 0x00, 0x10}, /* integlines */
-       {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, /* global gain */
-       {0xc1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x00, 0x10}, /* r/g1/b gains */
-
-       {0xa1, 0x6e, 0x1d, 0x08, 0x00, 0x00, 0x00, 0x10}, /* control1 */
-       {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10}, /* frameheight */
-       {0xa1, 0x6e, 0x07, 0xd5, 0x00, 0x00, 0x00, 0x10},
-/*     {0xc1, 0x6e, 0x16, 0x49, 0x40, 0x45, 0x00, 0x10}, */
-       {}
-};
-
-static const u8 po2030n_sensor_init[][8] = {
-       {0xa1, 0x6e, 0x1e, 0x1a, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x6e, 0x1f, 0x99, 0x00, 0x00, 0x00, 0x10},
-       {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */
-       {0xa1, 0x6e, 0x1e, 0x0a, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x6e, 0x1f, 0x19, 0x00, 0x00, 0x00, 0x10},
-       {DELAY, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 10ms */
-       {0xa1, 0x6e, 0x20, 0x44, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x6e, 0x05, 0x70, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x08, 0x00, 0xd0, 0x00, 0x08, 0x10},
-       {0xd1, 0x6e, 0x0c, 0x03, 0x50, 0x01, 0xe8, 0x10},
-       {0xd1, 0x6e, 0x1d, 0x20, 0x0a, 0x19, 0x44, 0x10},
-       {0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x29, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x35, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x39, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x45, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x49, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x4d, 0x00, 0x00, 0x00, 0xed, 0x10},
-       {0xd1, 0x6e, 0x51, 0x17, 0x4a, 0x2f, 0xc0, 0x10},
-       {0xd1, 0x6e, 0x55, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x59, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x61, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x69, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x79, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x81, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x85, 0x00, 0x00, 0x00, 0x08, 0x10},
-       {0xd1, 0x6e, 0x89, 0x01, 0xe8, 0x00, 0x01, 0x10},
-       {0xa1, 0x6e, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x21, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x25, 0x00, 0x00, 0x00, 0x01, 0x10},
-       {0xd1, 0x6e, 0x29, 0xe6, 0x00, 0xbd, 0x03, 0x10},
-       {0xd1, 0x6e, 0x2d, 0x41, 0x38, 0x68, 0x40, 0x10},
-       {0xd1, 0x6e, 0x31, 0x2b, 0x00, 0x36, 0x00, 0x10},
-       {0xd1, 0x6e, 0x35, 0x30, 0x30, 0x08, 0x00, 0x10},
-       {0xd1, 0x6e, 0x39, 0x00, 0x00, 0x33, 0x06, 0x10},
-       {0xb1, 0x6e, 0x3d, 0x06, 0x02, 0x00, 0x00, 0x10},
-       {}
-};
-static const u8 po2030n_sensor_param1[][8] = {
-       {0xa1, 0x6e, 0x1a, 0x01, 0x00, 0x00, 0x00, 0x10},
-       {DELAY, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */
-       {0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10},
-       {0xd1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x40, 0x10}, /* RGBG gains */
-/*param2*/
-       {0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x6e, 0x05, 0x6f, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x6e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x6e, 0x07, 0x25, 0x00, 0x00, 0x00, 0x10},
-       {}
-};
-
-static const u8 soi768_sensor_init[][8] = {
-       {0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10}, /* reset */
-       {DELAY, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 96ms */
-       {0xa1, 0x21, 0x12, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x13, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x0f, 0x03, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {}
-};
-static const u8 soi768_sensor_param1[][8] = {
-       {0xa1, 0x21, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xb1, 0x21, 0x01, 0x7f, 0x7f, 0x00, 0x00, 0x10},
-/* */
-/*     {0xa1, 0x21, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x10}, */
-/*     {0xa1, 0x21, 0x2d, 0x25, 0x00, 0x00, 0x00, 0x10}, */
-       {0xa1, 0x21, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10},
-/*     {0xb1, 0x21, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x10}, */
-       {0xa1, 0x21, 0x02, 0x8d, 0x00, 0x00, 0x00, 0x10},
-/* the next sequence should be used for auto gain */
-       {0xa1, 0x21, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10},
-                       /* global gain ? : 07 - change with 0x15 at the end */
-       {0xa1, 0x21, 0x10, 0x3f, 0x00, 0x00, 0x00, 0x10}, /* ???? : 063f */
-       {0xa1, 0x21, 0x04, 0x06, 0x00, 0x00, 0x00, 0x10},
-       {0xb1, 0x21, 0x2d, 0x63, 0x03, 0x00, 0x00, 0x10},
-                       /* exposure ? : 0200 - change with 0x1e at the end */
-       {}
-};
-
-static const u8 sp80708_sensor_init[][8] = {
-       {0xa1, 0x18, 0x06, 0xf9, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x09, 0x1f, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x0d, 0xc0, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x10, 0x40, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x11, 0x4e, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x12, 0x53, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x15, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x19, 0x18, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x1a, 0x10, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x1c, 0x28, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x1d, 0x02, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x26, 0x04, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x27, 0x1e, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x28, 0x5a, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x29, 0x28, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x2a, 0x78, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x2b, 0x01, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x2c, 0xf7, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x2d, 0x2d, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x2e, 0xd5, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x39, 0x42, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x3a, 0x67, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x3b, 0x87, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x3c, 0xa3, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x3d, 0xb0, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x3e, 0xbc, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x3f, 0xc8, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x40, 0xd4, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x41, 0xdf, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x42, 0xea, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x43, 0xf5, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x45, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x46, 0x60, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x47, 0x50, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x48, 0x30, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x49, 0x01, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x4d, 0xae, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x4e, 0x03, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x4f, 0x66, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x50, 0x1c, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x44, 0x10, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x4a, 0x30, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x51, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x52, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x53, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x54, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x55, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x56, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x57, 0xe0, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x58, 0xc0, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x59, 0xab, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x5a, 0xa0, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x5b, 0x99, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x5c, 0x90, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x5e, 0x24, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x61, 0x73, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x63, 0x42, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x64, 0x42, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x65, 0x42, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x66, 0x24, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x67, 0x24, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x68, 0x08, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x2f, 0xc9, 0x00, 0x00, 0x00, 0x10},
-       {}
-};
-static const u8 sp80708_sensor_param1[][8] = {
-       {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x03, 0x01, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x04, 0xa4, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x14, 0x3f, 0x00, 0x00, 0x00, 0x10},
-       {0xa1, 0x18, 0x5d, 0x80, 0x00, 0x00, 0x00, 0x10},
-       {0xb1, 0x18, 0x11, 0x40, 0x40, 0x00, 0x00, 0x10},
-       {}
-};
-
-static const u8 (*sensor_init[])[8] = {
-[SENSOR_ADCM1700] =    adcm1700_sensor_init,
-[SENSOR_GC0307] =      gc0307_sensor_init,
-[SENSOR_HV7131R] =     hv7131r_sensor_init,
-[SENSOR_MI0360] =      mi0360_sensor_init,
-[SENSOR_MI0360B] =     mi0360b_sensor_init,
-[SENSOR_MO4000] =      mo4000_sensor_init,
-[SENSOR_MT9V111] =     mt9v111_sensor_init,
-[SENSOR_OM6802] =      om6802_sensor_init,
-[SENSOR_OV7630] =      ov7630_sensor_init,
-[SENSOR_OV7648] =      ov7648_sensor_init,
-[SENSOR_OV7660] =      ov7660_sensor_init,
-[SENSOR_PO1030] =      po1030_sensor_init,
-[SENSOR_PO2030N] =     po2030n_sensor_init,
-[SENSOR_SOI768] =      soi768_sensor_init,
-[SENSOR_SP80708] =     sp80708_sensor_init,
-};
-
-/* read <len> bytes to gspca_dev->usb_buf */
-static void reg_r(struct gspca_dev *gspca_dev,
-                 u16 value, int len)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-#ifdef GSPCA_DEBUG
-       if (len > USB_BUF_SZ) {
-               pr_err("reg_r: buffer overflow\n");
-               return;
-       }
-#endif
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       0,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       value, 0,
-                       gspca_dev->usb_buf, len,
-                       500);
-       PDEBUG(D_USBI, "reg_r [%02x] -> %02x", value, gspca_dev->usb_buf[0]);
-       if (ret < 0) {
-               pr_err("reg_r err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void reg_w1(struct gspca_dev *gspca_dev,
-                  u16 value,
-                  u8 data)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       PDEBUG(D_USBO, "reg_w1 [%04x] = %02x", value, data);
-       gspca_dev->usb_buf[0] = data;
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0x08,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       value,
-                       0,
-                       gspca_dev->usb_buf, 1,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_w1 err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-static void reg_w(struct gspca_dev *gspca_dev,
-                         u16 value,
-                         const u8 *buffer,
-                         int len)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       PDEBUG(D_USBO, "reg_w [%04x] = %02x %02x ..",
-               value, buffer[0], buffer[1]);
-#ifdef GSPCA_DEBUG
-       if (len > USB_BUF_SZ) {
-               pr_err("reg_w: buffer overflow\n");
-               return;
-       }
-#endif
-       memcpy(gspca_dev->usb_buf, buffer, len);
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0x08,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       value, 0,
-                       gspca_dev->usb_buf, len,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_w err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-/* I2C write 1 byte */
-static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       PDEBUG(D_USBO, "i2c_w1 [%02x] = %02x", reg, val);
-       switch (sd->sensor) {
-       case SENSOR_ADCM1700:
-       case SENSOR_OM6802:
-       case SENSOR_GC0307:             /* i2c command = a0 (100 kHz) */
-               gspca_dev->usb_buf[0] = 0x80 | (2 << 4);
-               break;
-       default:                        /* i2c command = a1 (400 kHz) */
-               gspca_dev->usb_buf[0] = 0x81 | (2 << 4);
-               break;
-       }
-       gspca_dev->usb_buf[1] = sd->i2c_addr;
-       gspca_dev->usb_buf[2] = reg;
-       gspca_dev->usb_buf[3] = val;
-       gspca_dev->usb_buf[4] = 0;
-       gspca_dev->usb_buf[5] = 0;
-       gspca_dev->usb_buf[6] = 0;
-       gspca_dev->usb_buf[7] = 0x10;
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0x08,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       0x08,                   /* value = i2c */
-                       0,
-                       gspca_dev->usb_buf, 8,
-                       500);
-       if (ret < 0) {
-               pr_err("i2c_w1 err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-/* I2C write 8 bytes */
-static void i2c_w8(struct gspca_dev *gspca_dev,
-                  const u8 *buffer)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       PDEBUG(D_USBO, "i2c_w8 [%02x] = %02x ..",
-               buffer[2], buffer[3]);
-       memcpy(gspca_dev->usb_buf, buffer, 8);
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0x08,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       0x08, 0,                /* value, index */
-                       gspca_dev->usb_buf, 8,
-                       500);
-       msleep(2);
-       if (ret < 0) {
-               pr_err("i2c_w8 err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-/* sensor read 'len' (1..5) bytes in gspca_dev->usb_buf */
-static void i2c_r(struct gspca_dev *gspca_dev, u8 reg, int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 mode[8];
-
-       switch (sd->sensor) {
-       case SENSOR_ADCM1700:
-       case SENSOR_OM6802:
-       case SENSOR_GC0307:             /* i2c command = a0 (100 kHz) */
-               mode[0] = 0x80 | 0x10;
-               break;
-       default:                        /* i2c command = 91 (400 kHz) */
-               mode[0] = 0x81 | 0x10;
-               break;
-       }
-       mode[1] = sd->i2c_addr;
-       mode[2] = reg;
-       mode[3] = 0;
-       mode[4] = 0;
-       mode[5] = 0;
-       mode[6] = 0;
-       mode[7] = 0x10;
-       i2c_w8(gspca_dev, mode);
-       msleep(2);
-       mode[0] = (mode[0] & 0x81) | (len << 4) | 0x02;
-       mode[2] = 0;
-       i2c_w8(gspca_dev, mode);
-       msleep(2);
-       reg_r(gspca_dev, 0x0a, 5);
-}
-
-static void i2c_w_seq(struct gspca_dev *gspca_dev,
-                       const u8 (*data)[8])
-{
-       while ((*data)[0] != 0) {
-               if ((*data)[0] != DELAY)
-                       i2c_w8(gspca_dev, *data);
-               else
-                       msleep((*data)[1]);
-               data++;
-       }
-}
-
-/* check the ID of the hv7131 sensor */
-/* this sequence is needed because it activates the sensor */
-static void hv7131r_probe(struct gspca_dev *gspca_dev)
-{
-       i2c_w1(gspca_dev, 0x02, 0);             /* sensor wakeup */
-       msleep(10);
-       reg_w1(gspca_dev, 0x02, 0x66);          /* Gpio on */
-       msleep(10);
-       i2c_r(gspca_dev, 0, 5);                 /* read sensor id */
-       if (gspca_dev->usb_buf[0] == 0x02       /* chip ID (02 is R) */
-           && gspca_dev->usb_buf[1] == 0x09
-           && gspca_dev->usb_buf[2] == 0x01) {
-               PDEBUG(D_PROBE, "Sensor HV7131R found");
-               return;
-       }
-       pr_warn("Erroneous HV7131R ID 0x%02x 0x%02x 0x%02x\n",
-               gspca_dev->usb_buf[0], gspca_dev->usb_buf[1],
-               gspca_dev->usb_buf[2]);
-}
-
-static void mi0360_probe(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i, j;
-       u16 val = 0;
-       static const u8 probe_tb[][4][8] = {
-           {                                   /* mi0360 */
-               {0xb0, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10},
-               {0x90, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
-               {0xa2, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
-               {0xb0, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10}
-           },
-           {                                   /* mt9v111 */
-               {0xb0, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10},
-               {0x90, 0x5c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x10},
-               {0xa2, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
-               {}
-           },
-       };
-
-       for (i = 0; i < ARRAY_SIZE(probe_tb); i++) {
-               reg_w1(gspca_dev, 0x17, 0x62);
-               reg_w1(gspca_dev, 0x01, 0x08);
-               for (j = 0; j < 3; j++)
-                       i2c_w8(gspca_dev, probe_tb[i][j]);
-               msleep(2);
-               reg_r(gspca_dev, 0x0a, 5);
-               val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
-               if (probe_tb[i][3][0] != 0)
-                       i2c_w8(gspca_dev, probe_tb[i][3]);
-               reg_w1(gspca_dev, 0x01, 0x29);
-               reg_w1(gspca_dev, 0x17, 0x42);
-               if (val != 0xffff)
-                       break;
-       }
-       if (gspca_dev->usb_err < 0)
-               return;
-       switch (val) {
-       case 0x8221:
-               PDEBUG(D_PROBE, "Sensor mi0360b");
-               sd->sensor = SENSOR_MI0360B;
-               break;
-       case 0x823a:
-               PDEBUG(D_PROBE, "Sensor mt9v111");
-               sd->sensor = SENSOR_MT9V111;
-               break;
-       case 0x8243:
-               PDEBUG(D_PROBE, "Sensor mi0360");
-               break;
-       default:
-               PDEBUG(D_PROBE, "Unknown sensor %04x - forced to mi0360", val);
-               break;
-       }
-}
-
-static void ov7630_probe(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u16 val;
-
-       /* check ov76xx */
-       reg_w1(gspca_dev, 0x17, 0x62);
-       reg_w1(gspca_dev, 0x01, 0x08);
-       sd->i2c_addr = 0x21;
-       i2c_r(gspca_dev, 0x0a, 2);
-       val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
-       reg_w1(gspca_dev, 0x01, 0x29);
-       reg_w1(gspca_dev, 0x17, 0x42);
-       if (gspca_dev->usb_err < 0)
-               return;
-       if (val == 0x7628) {                    /* soi768 */
-               sd->sensor = SENSOR_SOI768;
-/*fixme: only valid for 0c45:613e?*/
-               gspca_dev->cam.input_flags =
-                               V4L2_IN_ST_VFLIP | V4L2_IN_ST_HFLIP;
-               PDEBUG(D_PROBE, "Sensor soi768");
-               return;
-       }
-       PDEBUG(D_PROBE, "Sensor ov%04x", val);
-}
-
-static void ov7648_probe(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u16 val;
-
-       /* check ov76xx */
-       reg_w1(gspca_dev, 0x17, 0x62);
-       reg_w1(gspca_dev, 0x01, 0x08);
-       sd->i2c_addr = 0x21;
-       i2c_r(gspca_dev, 0x0a, 2);
-       val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
-       reg_w1(gspca_dev, 0x01, 0x29);
-       reg_w1(gspca_dev, 0x17, 0x42);
-       if ((val & 0xff00) == 0x7600) {         /* ov76xx */
-               PDEBUG(D_PROBE, "Sensor ov%04x", val);
-               return;
-       }
-
-       /* check po1030 */
-       reg_w1(gspca_dev, 0x17, 0x62);
-       reg_w1(gspca_dev, 0x01, 0x08);
-       sd->i2c_addr = 0x6e;
-       i2c_r(gspca_dev, 0x00, 2);
-       val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
-       reg_w1(gspca_dev, 0x01, 0x29);
-       reg_w1(gspca_dev, 0x17, 0x42);
-       if (gspca_dev->usb_err < 0)
-               return;
-       if (val == 0x1030) {                    /* po1030 */
-               PDEBUG(D_PROBE, "Sensor po1030");
-               sd->sensor = SENSOR_PO1030;
-               return;
-       }
-       pr_err("Unknown sensor %04x\n", val);
-}
-
-/* 0c45:6142 sensor may be po2030n, gc0305 or gc0307 */
-static void po2030n_probe(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u16 val;
-
-       /* check gc0307 */
-       reg_w1(gspca_dev, 0x17, 0x62);
-       reg_w1(gspca_dev, 0x01, 0x08);
-       reg_w1(gspca_dev, 0x02, 0x22);
-       sd->i2c_addr = 0x21;
-       i2c_r(gspca_dev, 0x00, 1);
-       val = gspca_dev->usb_buf[4];
-       reg_w1(gspca_dev, 0x01, 0x29);          /* reset */
-       reg_w1(gspca_dev, 0x17, 0x42);
-       if (val == 0x99) {                      /* gc0307 (?) */
-               PDEBUG(D_PROBE, "Sensor gc0307");
-               sd->sensor = SENSOR_GC0307;
-               return;
-       }
-
-       /* check po2030n */
-       reg_w1(gspca_dev, 0x17, 0x62);
-       reg_w1(gspca_dev, 0x01, 0x0a);
-       sd->i2c_addr = 0x6e;
-       i2c_r(gspca_dev, 0x00, 2);
-       val = (gspca_dev->usb_buf[3] << 8) | gspca_dev->usb_buf[4];
-       reg_w1(gspca_dev, 0x01, 0x29);
-       reg_w1(gspca_dev, 0x17, 0x42);
-       if (gspca_dev->usb_err < 0)
-               return;
-       if (val == 0x2030) {
-               PDEBUG(D_PROBE, "Sensor po2030n");
-/*             sd->sensor = SENSOR_PO2030N; */
-       } else {
-               pr_err("Unknown sensor ID %04x\n", val);
-       }
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-
-       sd->bridge = id->driver_info >> 16;
-       sd->sensor = id->driver_info >> 8;
-       sd->flags = id->driver_info;
-
-       cam = &gspca_dev->cam;
-       if (sd->sensor == SENSOR_ADCM1700) {
-               cam->cam_mode = cif_mode;
-               cam->nmodes = ARRAY_SIZE(cif_mode);
-       } else {
-               cam->cam_mode = vga_mode;
-               cam->nmodes = ARRAY_SIZE(vga_mode);
-       }
-       cam->npkt = 24;                 /* 24 packets per ISOC message */
-       cam->ctrls = sd->ctrls;
-
-       sd->ag_cnt = -1;
-       sd->quality = QUALITY_DEF;
-
-       INIT_WORK(&sd->work, qual_upd);
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       const u8 *sn9c1xx;
-       u8 regGpio[] = { 0x29, 0x70 };          /* no audio */
-       u8 regF1;
-
-       /* setup a selector by bridge */
-       reg_w1(gspca_dev, 0xf1, 0x01);
-       reg_r(gspca_dev, 0x00, 1);
-       reg_w1(gspca_dev, 0xf1, 0x00);
-       reg_r(gspca_dev, 0x00, 1);              /* get sonix chip id */
-       regF1 = gspca_dev->usb_buf[0];
-       if (gspca_dev->usb_err < 0)
-               return gspca_dev->usb_err;
-       PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
-       if (gspca_dev->audio)
-               regGpio[1] |= 0x04;             /* with audio */
-       switch (sd->bridge) {
-       case BRIDGE_SN9C102P:
-       case BRIDGE_SN9C105:
-               if (regF1 != 0x11)
-                       return -ENODEV;
-               break;
-       default:
-/*     case BRIDGE_SN9C110: */
-/*     case BRIDGE_SN9C120: */
-               if (regF1 != 0x12)
-                       return -ENODEV;
-       }
-
-       switch (sd->sensor) {
-       case SENSOR_MI0360:
-               mi0360_probe(gspca_dev);
-               break;
-       case SENSOR_OV7630:
-               ov7630_probe(gspca_dev);
-               break;
-       case SENSOR_OV7648:
-               ov7648_probe(gspca_dev);
-               break;
-       case SENSOR_PO2030N:
-               po2030n_probe(gspca_dev);
-               break;
-       }
-
-       switch (sd->bridge) {
-       case BRIDGE_SN9C102P:
-               reg_w1(gspca_dev, 0x02, regGpio[1]);
-               break;
-       default:
-               reg_w(gspca_dev, 0x01, regGpio, 2);
-               break;
-       }
-
-       if (sd->sensor == SENSOR_OM6802)
-               sd->ctrls[SHARPNESS].def = 0x10;
-
-       /* Note we do not disable the sensor clock here (power saving mode),
-          as that also disables the button on the cam. */
-       reg_w1(gspca_dev, 0xf1, 0x00);
-
-       /* set the i2c address */
-       sn9c1xx = sn_tb[sd->sensor];
-       sd->i2c_addr = sn9c1xx[9];
-
-       gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
-       if (!(sd->flags & F_ILLUM))
-               gspca_dev->ctrl_dis |= (1 << ILLUM);
-
-       return gspca_dev->usb_err;
-}
-
-static u32 expo_adjust(struct gspca_dev *gspca_dev,
-                       u32 expo)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->sensor) {
-       case SENSOR_GC0307: {
-               int a, b;
-
-               /* expo = 0..255 -> a = 19..43 */
-               a = 19 + expo * 25 / 256;
-               i2c_w1(gspca_dev, 0x68, a);
-               a -= 12;
-               b = a * a * 4;                  /* heuristic */
-               i2c_w1(gspca_dev, 0x03, b >> 8);
-               i2c_w1(gspca_dev, 0x04, b);
-               break;
-           }
-       case SENSOR_HV7131R: {
-               u8 Expodoit[] =
-                       { 0xc1, 0x11, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16 };
-
-               Expodoit[3] = expo >> 16;
-               Expodoit[4] = expo >> 8;
-               Expodoit[5] = expo;
-               i2c_w8(gspca_dev, Expodoit);
-               break;
-           }
-       case SENSOR_MI0360:
-       case SENSOR_MI0360B: {
-               u8 expoMi[] =           /* exposure 0x0635 -> 4 fp/s 0x10 */
-                       { 0xb1, 0x5d, 0x09, 0x00, 0x00, 0x00, 0x00, 0x16 };
-               static const u8 doit[] =                /* update sensor */
-                       { 0xb1, 0x5d, 0x07, 0x00, 0x03, 0x00, 0x00, 0x10 };
-               static const u8 sensorgo[] =            /* sensor on */
-                       { 0xb1, 0x5d, 0x07, 0x00, 0x02, 0x00, 0x00, 0x10 };
-
-               if (expo > 0x0635)
-                       expo = 0x0635;
-               else if (expo < 0x0001)
-                       expo = 0x0001;
-               expoMi[3] = expo >> 8;
-               expoMi[4] = expo;
-               i2c_w8(gspca_dev, expoMi);
-               i2c_w8(gspca_dev, doit);
-               i2c_w8(gspca_dev, sensorgo);
-               break;
-           }
-       case SENSOR_MO4000: {
-               u8 expoMof[] =
-                       { 0xa1, 0x21, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x10 };
-               u8 expoMo10[] =
-                       { 0xa1, 0x21, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10 };
-               static const u8 gainMo[] =
-                       { 0xa1, 0x21, 0x00, 0x10, 0x00, 0x00, 0x00, 0x1d };
-
-               if (expo > 0x1fff)
-                       expo = 0x1fff;
-               else if (expo < 0x0001)
-                       expo = 0x0001;
-               expoMof[3] = (expo & 0x03fc) >> 2;
-               i2c_w8(gspca_dev, expoMof);
-               expoMo10[3] = ((expo & 0x1c00) >> 10)
-                               | ((expo & 0x0003) << 4);
-               i2c_w8(gspca_dev, expoMo10);
-               i2c_w8(gspca_dev, gainMo);
-               PDEBUG(D_FRAM, "set exposure %d",
-                       ((expoMo10[3] & 0x07) << 10)
-                       | (expoMof[3] << 2)
-                       | ((expoMo10[3] & 0x30) >> 4));
-               break;
-           }
-       case SENSOR_MT9V111: {
-               u8 expo_c1[] =
-                       { 0xb1, 0x5c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x10 };
-
-               if (expo > 0x0390)
-                       expo = 0x0390;
-               else if (expo < 0x0060)
-                       expo = 0x0060;
-               expo_c1[3] = expo >> 8;
-               expo_c1[4] = expo;
-               i2c_w8(gspca_dev, expo_c1);
-               break;
-           }
-       case SENSOR_OM6802: {
-               u8 gainOm[] =
-                       { 0xa0, 0x34, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x10 };
-                               /* preset AGC - works when AutoExpo = off */
-
-               if (expo > 0x03ff)
-                       expo = 0x03ff;
-                if (expo < 0x0001)
-                       expo = 0x0001;
-               gainOm[3] = expo >> 2;
-               i2c_w8(gspca_dev, gainOm);
-               reg_w1(gspca_dev, 0x96, expo >> 5);
-               PDEBUG(D_FRAM, "set exposure %d", gainOm[3]);
-               break;
-           }
-       }
-       return expo;
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       unsigned int expo;
-       int brightness;
-       u8 k2;
-
-       brightness = sd->ctrls[BRIGHTNESS].val;
-       k2 = (brightness - 0x80) >> 2;
-       switch (sd->sensor) {
-       case SENSOR_ADCM1700:
-               if (k2 > 0x1f)
-                       k2 = 0;         /* only positive Y offset */
-               break;
-       case SENSOR_HV7131R:
-               expo = brightness << 12;
-               if (expo > 0x002dc6c0)
-                       expo = 0x002dc6c0;
-               else if (expo < 0x02a0)
-                       expo = 0x02a0;
-               sd->exposure = expo_adjust(gspca_dev, expo);
-               break;
-       case SENSOR_MI0360:
-       case SENSOR_MO4000:
-               expo = brightness << 4;
-               sd->exposure = expo_adjust(gspca_dev, expo);
-               break;
-       case SENSOR_MI0360B:
-               expo = brightness << 2;
-               sd->exposure = expo_adjust(gspca_dev, expo);
-               break;
-       case SENSOR_GC0307:
-               expo = brightness;
-               sd->exposure = expo_adjust(gspca_dev, expo);
-               return;                 /* don't set the Y offset */
-       case SENSOR_MT9V111:
-               expo = brightness << 2;
-               sd->exposure = expo_adjust(gspca_dev, expo);
-               return;                 /* don't set the Y offset */
-       case SENSOR_OM6802:
-               expo = brightness << 2;
-               sd->exposure = expo_adjust(gspca_dev, expo);
-               return;                 /* Y offset already set */
-       }
-
-       reg_w1(gspca_dev, 0x96, k2);    /* color matrix Y offset */
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 k2;
-       u8 contrast[6];
-
-       k2 = sd->ctrls[CONTRAST].val * 37 / (CONTRAST_MAX + 1)
-                               + 37;           /* 37..73 */
-       contrast[0] = (k2 + 1) / 2;             /* red */
-       contrast[1] = 0;
-       contrast[2] = k2;                       /* green */
-       contrast[3] = 0;
-       contrast[4] = k2 / 5;                   /* blue */
-       contrast[5] = 0;
-       reg_w(gspca_dev, 0x84, contrast, sizeof contrast);
-}
-
-static void setcolors(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i, v, colors;
-       const s16 *uv;
-       u8 reg8a[12];                   /* U & V gains */
-       static const s16 uv_com[6] = {  /* same as reg84 in signed decimal */
-               -24, -38, 64,           /* UR UG UB */
-                62, -51, -9            /* VR VG VB */
-       };
-       static const s16 uv_mi0360b[6] = {
-               -20, -38, 64,           /* UR UG UB */
-                60, -51, -9            /* VR VG VB */
-       };
-
-       colors = sd->ctrls[COLORS].val;
-       if (sd->sensor == SENSOR_MI0360B)
-               uv = uv_mi0360b;
-       else
-               uv = uv_com;
-       for (i = 0; i < 6; i++) {
-               v = uv[i] * colors / COLORS_DEF;
-               reg8a[i * 2] = v;
-               reg8a[i * 2 + 1] = (v >> 8) & 0x0f;
-       }
-       reg_w(gspca_dev, 0x8a, reg8a, sizeof reg8a);
-}
-
-static void setredblue(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_PO2030N) {
-               u8 rg1b[] =             /* red  green1 blue (no g2) */
-                       {0xc1, 0x6e, 0x16, 0x00, 0x40, 0x00, 0x00, 0x10};
-
-               /* 0x40 = normal value = gain x 1 */
-               rg1b[3] = sd->ctrls[RED].val * 2;
-               rg1b[5] = sd->ctrls[BLUE].val * 2;
-               i2c_w8(gspca_dev, rg1b);
-               return;
-       }
-       reg_w1(gspca_dev, 0x05, sd->ctrls[RED].val);
-/*     reg_w1(gspca_dev, 0x07, 32); */
-       reg_w1(gspca_dev, 0x06, sd->ctrls[BLUE].val);
-}
-
-static void setgamma(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i, val;
-       u8 gamma[17];
-       const u8 *gamma_base;
-       static const u8 delta[17] = {
-               0x00, 0x14, 0x1c, 0x1c, 0x1c, 0x1c, 0x1b, 0x1a,
-               0x18, 0x13, 0x10, 0x0e, 0x08, 0x07, 0x04, 0x02, 0x00
-       };
-
-       switch (sd->sensor) {
-       case SENSOR_ADCM1700:
-               gamma_base = gamma_spec_0;
-               break;
-       case SENSOR_HV7131R:
-       case SENSOR_MI0360B:
-       case SENSOR_MT9V111:
-               gamma_base = gamma_spec_1;
-               break;
-       case SENSOR_GC0307:
-               gamma_base = gamma_spec_2;
-               break;
-       case SENSOR_SP80708:
-               gamma_base = gamma_spec_3;
-               break;
-       default:
-               gamma_base = gamma_def;
-               break;
-       }
-
-       val = sd->ctrls[GAMMA].val;
-       for (i = 0; i < sizeof gamma; i++)
-               gamma[i] = gamma_base[i]
-                       + delta[i] * (val - GAMMA_DEF) / 32;
-       reg_w(gspca_dev, 0x20, gamma, sizeof gamma);
-}
-
-static void setexposure(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_PO2030N) {
-               u8 rexpo[] =            /* 1a: expo H, 1b: expo M */
-                       {0xa1, 0x6e, 0x1a, 0x00, 0x40, 0x00, 0x00, 0x10};
-
-               rexpo[3] = sd->ctrls[EXPOSURE].val >> 8;
-               i2c_w8(gspca_dev, rexpo);
-               msleep(6);
-               rexpo[2] = 0x1b;
-               rexpo[3] = sd->ctrls[EXPOSURE].val;
-               i2c_w8(gspca_dev, rexpo);
-       }
-}
-
-static void setautogain(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
-               return;
-       switch (sd->sensor) {
-       case SENSOR_OV7630:
-       case SENSOR_OV7648: {
-               u8 comb;
-
-               if (sd->sensor == SENSOR_OV7630)
-                       comb = 0xc0;
-               else
-                       comb = 0xa0;
-               if (sd->ctrls[AUTOGAIN].val)
-                       comb |= 0x03;
-               i2c_w1(&sd->gspca_dev, 0x13, comb);
-               return;
-           }
-       }
-       if (sd->ctrls[AUTOGAIN].val)
-               sd->ag_cnt = AG_CNT_START;
-       else
-               sd->ag_cnt = -1;
-}
-
-static void setgain(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_PO2030N) {
-               u8 rgain[] =            /* 15: gain */
-                       {0xa1, 0x6e, 0x15, 0x00, 0x40, 0x00, 0x00, 0x15};
-
-               rgain[3] = sd->ctrls[GAIN].val;
-               i2c_w8(gspca_dev, rgain);
-       }
-}
-
-static void sethvflip(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 comn;
-
-       switch (sd->sensor) {
-       case SENSOR_HV7131R:
-               comn = 0x18;                    /* clkdiv = 1, ablcen = 1 */
-               if (sd->ctrls[VFLIP].val)
-                       comn |= 0x01;
-               i2c_w1(gspca_dev, 0x01, comn);  /* sctra */
-               break;
-       case SENSOR_OV7630:
-               comn = 0x02;
-               if (!sd->ctrls[VFLIP].val)
-                       comn |= 0x80;
-               i2c_w1(gspca_dev, 0x75, comn);
-               break;
-       case SENSOR_OV7648:
-               comn = 0x06;
-               if (sd->ctrls[VFLIP].val)
-                       comn |= 0x80;
-               i2c_w1(gspca_dev, 0x75, comn);
-               break;
-       case SENSOR_PO2030N:
-               /* Reg. 0x1E: Timing Generator Control Register 2 (Tgcontrol2)
-                * (reset value: 0x0A)
-                * bit7: HM: Horizontal Mirror: 0: disable, 1: enable
-                * bit6: VM: Vertical Mirror: 0: disable, 1: enable
-                * bit5: ST: Shutter Selection: 0: electrical, 1: mechanical
-                * bit4: FT: Single Frame Transfer: 0: disable, 1: enable
-                * bit3-0: X
-                */
-               comn = 0x0a;
-               if (sd->ctrls[HFLIP].val)
-                       comn |= 0x80;
-               if (sd->ctrls[VFLIP].val)
-                       comn |= 0x40;
-               i2c_w1(&sd->gspca_dev, 0x1e, comn);
-               break;
-       }
-}
-
-static void setsharpness(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       reg_w1(gspca_dev, 0x99, sd->ctrls[SHARPNESS].val);
-}
-
-static void setillum(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (gspca_dev->ctrl_dis & (1 << ILLUM))
-               return;
-       switch (sd->sensor) {
-       case SENSOR_ADCM1700:
-               reg_w1(gspca_dev, 0x02,                         /* gpio */
-                       sd->ctrls[ILLUM].val ? 0x64 : 0x60);
-               break;
-       case SENSOR_MT9V111:
-               reg_w1(gspca_dev, 0x02,
-                       sd->ctrls[ILLUM].val ? 0x77 : 0x74);
-/* should have been: */
-/*                                             0x55 : 0x54);   * 370i */
-/*                                             0x66 : 0x64);   * Clip */
-               break;
-       }
-}
-
-static void setfreq(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (gspca_dev->ctrl_dis & (1 << FREQ))
-               return;
-       if (sd->sensor == SENSOR_OV7660) {
-               u8 com8;
-
-               com8 = 0xdf;            /* auto gain/wb/expo */
-               switch (sd->ctrls[FREQ].val) {
-               case 0: /* Banding filter disabled */
-                       i2c_w1(gspca_dev, 0x13, com8 | 0x20);
-                       break;
-               case 1: /* 50 hz */
-                       i2c_w1(gspca_dev, 0x13, com8);
-                       i2c_w1(gspca_dev, 0x3b, 0x0a);
-                       break;
-               case 2: /* 60 hz */
-                       i2c_w1(gspca_dev, 0x13, com8);
-                       i2c_w1(gspca_dev, 0x3b, 0x02);
-                       break;
-               }
-       } else {
-               u8 reg2a = 0, reg2b = 0, reg2d = 0;
-
-               /* Get reg2a / reg2d base values */
-               switch (sd->sensor) {
-               case SENSOR_OV7630:
-                       reg2a = 0x08;
-                       reg2d = 0x01;
-                       break;
-               case SENSOR_OV7648:
-                       reg2a = 0x11;
-                       reg2d = 0x81;
-                       break;
-               }
-
-               switch (sd->ctrls[FREQ].val) {
-               case 0: /* Banding filter disabled */
-                       break;
-               case 1: /* 50 hz (filter on and framerate adj) */
-                       reg2a |= 0x80;
-                       reg2b = 0xac;
-                       reg2d |= 0x04;
-                       break;
-               case 2: /* 60 hz (filter on, no framerate adj) */
-                       reg2a |= 0x80;
-                       reg2d |= 0x04;
-                       break;
-               }
-               i2c_w1(gspca_dev, 0x2a, reg2a);
-               i2c_w1(gspca_dev, 0x2b, reg2b);
-               i2c_w1(gspca_dev, 0x2d, reg2d);
-       }
-}
-
-static void setjpegqual(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       jpeg_set_qual(sd->jpeg_hdr, sd->quality);
-#if USB_BUF_SZ < 64
-#error "No room enough in usb_buf for quantization table"
-#endif
-       memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
-       usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0x08,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       0x0100, 0,
-                       gspca_dev->usb_buf, 64,
-                       500);
-       memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
-       usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0x08,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                       0x0140, 0,
-                       gspca_dev->usb_buf, 64,
-                       500);
-
-       sd->reg18 ^= 0x40;
-       reg_w1(gspca_dev, 0x18, sd->reg18);
-}
-
-/* JPEG quality update */
-/* This function is executed from a work queue. */
-static void qual_upd(struct work_struct *work)
-{
-       struct sd *sd = container_of(work, struct sd, work);
-       struct gspca_dev *gspca_dev = &sd->gspca_dev;
-
-       mutex_lock(&gspca_dev->usb_lock);
-       PDEBUG(D_STREAM, "qual_upd %d%%", sd->quality);
-       setjpegqual(gspca_dev);
-       mutex_unlock(&gspca_dev->usb_lock);
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i;
-       u8 reg01, reg17;
-       u8 reg0102[2];
-       const u8 *sn9c1xx;
-       const u8 (*init)[8];
-       const u8 *reg9a;
-       int mode;
-       static const u8 reg9a_def[] =
-               {0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
-       static const u8 reg9a_spec[] =
-               {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
-       static const u8 regd4[] = {0x60, 0x00, 0x00};
-       static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
-       static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
-       static const u8 CA_adcm1700[] =
-                               { 0x14, 0xec, 0x0a, 0xf6 };
-       static const u8 CA_po2030n[] =
-                               { 0x1e, 0xe2, 0x14, 0xec };
-       static const u8 CE[] = { 0x32, 0xdd, 0x2d, 0xdd };      /* MI0360 */
-       static const u8 CE_gc0307[] =
-                               { 0x32, 0xce, 0x2d, 0xd3 };
-       static const u8 CE_ov76xx[] =
-                               { 0x32, 0xdd, 0x32, 0xdd };
-       static const u8 CE_po2030n[] =
-                               { 0x14, 0xe7, 0x1e, 0xdd };
-
-       /* create the JPEG header */
-       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
-                       0x21);          /* JPEG 422 */
-
-       /* initialize the bridge */
-       sn9c1xx = sn_tb[sd->sensor];
-
-       /* sensor clock already enabled in sd_init */
-       /* reg_w1(gspca_dev, 0xf1, 0x00); */
-       reg01 = sn9c1xx[1];
-       if (sd->flags & F_PDN_INV)
-               reg01 ^= S_PDN_INV;             /* power down inverted */
-       reg_w1(gspca_dev, 0x01, reg01);
-
-       /* configure gpio */
-       reg0102[0] = reg01;
-       reg0102[1] = sn9c1xx[2];
-       if (gspca_dev->audio)
-               reg0102[1] |= 0x04;     /* keep the audio connection */
-       reg_w(gspca_dev, 0x01, reg0102, 2);
-       reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
-       reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
-       switch (sd->sensor) {
-       case SENSOR_GC0307:
-       case SENSOR_OV7660:
-       case SENSOR_PO1030:
-       case SENSOR_PO2030N:
-       case SENSOR_SOI768:
-       case SENSOR_SP80708:
-               reg9a = reg9a_spec;
-               break;
-       default:
-               reg9a = reg9a_def;
-               break;
-       }
-       reg_w(gspca_dev, 0x9a, reg9a, 6);
-
-       reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);
-
-       reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
-
-       reg17 = sn9c1xx[0x17];
-       switch (sd->sensor) {
-       case SENSOR_GC0307:
-               msleep(50);             /*fixme: is it useful? */
-               break;
-       case SENSOR_OM6802:
-               msleep(10);
-               reg_w1(gspca_dev, 0x02, 0x73);
-               reg17 |= SEN_CLK_EN;
-               reg_w1(gspca_dev, 0x17, reg17);
-               reg_w1(gspca_dev, 0x01, 0x22);
-               msleep(100);
-               reg01 = SCL_SEL_OD | S_PDN_INV;
-               reg17 &= ~MCK_SIZE_MASK;
-               reg17 |= 0x04;          /* clock / 4 */
-               break;
-       }
-       reg01 |= SYS_SEL_48M;
-       reg_w1(gspca_dev, 0x01, reg01);
-       reg17 |= SEN_CLK_EN;
-       reg_w1(gspca_dev, 0x17, reg17);
-       reg01 &= ~S_PWR_DN;             /* sensor power on */
-       reg_w1(gspca_dev, 0x01, reg01);
-       reg01 &= ~SCL_SEL_OD;           /* remove open-drain mode */
-       reg_w1(gspca_dev, 0x01, reg01);
-
-       switch (sd->sensor) {
-       case SENSOR_HV7131R:
-               hv7131r_probe(gspca_dev);       /*fixme: is it useful? */
-               break;
-       case SENSOR_OM6802:
-               msleep(10);
-               reg_w1(gspca_dev, 0x01, reg01);
-               i2c_w8(gspca_dev, om6802_init0[0]);
-               i2c_w8(gspca_dev, om6802_init0[1]);
-               msleep(15);
-               reg_w1(gspca_dev, 0x02, 0x71);
-               msleep(150);
-               break;
-       case SENSOR_SP80708:
-               msleep(100);
-               reg_w1(gspca_dev, 0x02, 0x62);
-               break;
-       }
-
-       /* initialize the sensor */
-       i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);
-
-       reg_w1(gspca_dev, 0x15, sn9c1xx[0x15]);
-       reg_w1(gspca_dev, 0x16, sn9c1xx[0x16]);
-       reg_w1(gspca_dev, 0x12, sn9c1xx[0x12]);
-       reg_w1(gspca_dev, 0x13, sn9c1xx[0x13]);
-       reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
-       if (sd->sensor == SENSOR_ADCM1700) {
-               reg_w1(gspca_dev, 0xd2, 0x3a);  /* AE_H_SIZE = 116 */
-               reg_w1(gspca_dev, 0xd3, 0x30);  /* AE_V_SIZE = 96 */
-       } else {
-               reg_w1(gspca_dev, 0xd2, 0x6a);  /* AE_H_SIZE = 212 */
-               reg_w1(gspca_dev, 0xd3, 0x50);  /* AE_V_SIZE = 160 */
-       }
-       reg_w1(gspca_dev, 0xc6, 0x00);
-       reg_w1(gspca_dev, 0xc7, 0x00);
-       if (sd->sensor == SENSOR_ADCM1700) {
-               reg_w1(gspca_dev, 0xc8, 0x2c);  /* AW_H_STOP = 352 */
-               reg_w1(gspca_dev, 0xc9, 0x24);  /* AW_V_STOP = 288 */
-       } else {
-               reg_w1(gspca_dev, 0xc8, 0x50);  /* AW_H_STOP = 640 */
-               reg_w1(gspca_dev, 0xc9, 0x3c);  /* AW_V_STOP = 480 */
-       }
-       reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
-       switch (sd->sensor) {
-       case SENSOR_OM6802:
-/*     case SENSOR_OV7648:             * fixme: sometimes */
-               break;
-       default:
-               reg17 |= DEF_EN;
-               break;
-       }
-       reg_w1(gspca_dev, 0x17, reg17);
-
-       reg_w1(gspca_dev, 0x05, 0x00);          /* red */
-       reg_w1(gspca_dev, 0x07, 0x00);          /* green */
-       reg_w1(gspca_dev, 0x06, 0x00);          /* blue */
-       reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
-
-       setgamma(gspca_dev);
-
-/*fixme: 8 times with all zeroes and 1 or 2 times with normal values */
-       for (i = 0; i < 8; i++)
-               reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
-       switch (sd->sensor) {
-       case SENSOR_ADCM1700:
-       case SENSOR_OV7660:
-       case SENSOR_SP80708:
-               reg_w1(gspca_dev, 0x9a, 0x05);
-               break;
-       case SENSOR_GC0307:
-       case SENSOR_MT9V111:
-       case SENSOR_MI0360B:
-               reg_w1(gspca_dev, 0x9a, 0x07);
-               break;
-       case SENSOR_OV7630:
-       case SENSOR_OV7648:
-               reg_w1(gspca_dev, 0x9a, 0x0a);
-               break;
-       case SENSOR_PO2030N:
-       case SENSOR_SOI768:
-               reg_w1(gspca_dev, 0x9a, 0x06);
-               break;
-       default:
-               reg_w1(gspca_dev, 0x9a, 0x08);
-               break;
-       }
-       setsharpness(gspca_dev);
-
-       reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
-       reg_w1(gspca_dev, 0x05, 0x20);          /* red */
-       reg_w1(gspca_dev, 0x07, 0x20);          /* green */
-       reg_w1(gspca_dev, 0x06, 0x20);          /* blue */
-
-       init = NULL;
-       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-       reg01 |= SYS_SEL_48M | V_TX_EN;
-       reg17 &= ~MCK_SIZE_MASK;
-       reg17 |= 0x02;                  /* clock / 2 */
-       switch (sd->sensor) {
-       case SENSOR_ADCM1700:
-               init = adcm1700_sensor_param1;
-               break;
-       case SENSOR_GC0307:
-               init = gc0307_sensor_param1;
-               break;
-       case SENSOR_HV7131R:
-       case SENSOR_MI0360:
-               if (!mode)
-                       reg01 &= ~SYS_SEL_48M;  /* 640x480: clk 24Mhz */
-               reg17 &= ~MCK_SIZE_MASK;
-               reg17 |= 0x01;                  /* clock / 1 */
-               break;
-       case SENSOR_MI0360B:
-               init = mi0360b_sensor_param1;
-               break;
-       case SENSOR_MO4000:
-               if (mode) {                     /* if 320x240 */
-                       reg01 &= ~SYS_SEL_48M;  /* clk 24Mz */
-                       reg17 &= ~MCK_SIZE_MASK;
-                       reg17 |= 0x01;          /* clock / 1 */
-               }
-               break;
-       case SENSOR_MT9V111:
-               init = mt9v111_sensor_param1;
-               break;
-       case SENSOR_OM6802:
-               init = om6802_sensor_param1;
-               if (!mode) {                    /* if 640x480 */
-                       reg17 &= ~MCK_SIZE_MASK;
-                       reg17 |= 0x04;          /* clock / 4 */
-               } else {
-                       reg01 &= ~SYS_SEL_48M;  /* clk 24Mz */
-                       reg17 &= ~MCK_SIZE_MASK;
-                       reg17 |= 0x02;          /* clock / 2 */
-               }
-               break;
-       case SENSOR_OV7630:
-               init = ov7630_sensor_param1;
-               break;
-       case SENSOR_OV7648:
-               init = ov7648_sensor_param1;
-               reg17 &= ~MCK_SIZE_MASK;
-               reg17 |= 0x01;                  /* clock / 1 */
-               break;
-       case SENSOR_OV7660:
-               init = ov7660_sensor_param1;
-               break;
-       case SENSOR_PO1030:
-               init = po1030_sensor_param1;
-               break;
-       case SENSOR_PO2030N:
-               init = po2030n_sensor_param1;
-               break;
-       case SENSOR_SOI768:
-               init = soi768_sensor_param1;
-               break;
-       case SENSOR_SP80708:
-               init = sp80708_sensor_param1;
-               break;
-       }
-
-       /* more sensor initialization - param1 */
-       if (init != NULL) {
-               i2c_w_seq(gspca_dev, init);
-/*             init = NULL; */
-       }
-
-       reg_w(gspca_dev, 0xc0, C0, 6);
-       switch (sd->sensor) {
-       case SENSOR_ADCM1700:
-       case SENSOR_GC0307:
-       case SENSOR_SOI768:
-               reg_w(gspca_dev, 0xca, CA_adcm1700, 4);
-               break;
-       case SENSOR_PO2030N:
-               reg_w(gspca_dev, 0xca, CA_po2030n, 4);
-               break;
-       default:
-               reg_w(gspca_dev, 0xca, CA, 4);
-               break;
-       }
-       switch (sd->sensor) {
-       case SENSOR_ADCM1700:
-       case SENSOR_OV7630:
-       case SENSOR_OV7648:
-       case SENSOR_OV7660:
-       case SENSOR_SOI768:
-               reg_w(gspca_dev, 0xce, CE_ov76xx, 4);
-               break;
-       case SENSOR_GC0307:
-               reg_w(gspca_dev, 0xce, CE_gc0307, 4);
-               break;
-       case SENSOR_PO2030N:
-               reg_w(gspca_dev, 0xce, CE_po2030n, 4);
-               break;
-       default:
-               reg_w(gspca_dev, 0xce, CE, 4);
-                                       /* ?? {0x1e, 0xdd, 0x2d, 0xe7} */
-               break;
-       }
-
-       /* here change size mode 0 -> VGA; 1 -> CIF */
-       sd->reg18 = sn9c1xx[0x18] | (mode << 4) | 0x40;
-       reg_w1(gspca_dev, 0x18, sd->reg18);
-       setjpegqual(gspca_dev);
-
-       reg_w1(gspca_dev, 0x17, reg17);
-       reg_w1(gspca_dev, 0x01, reg01);
-       sd->reg01 = reg01;
-       sd->reg17 = reg17;
-
-       sethvflip(gspca_dev);
-       setbrightness(gspca_dev);
-       setcontrast(gspca_dev);
-       setcolors(gspca_dev);
-       setautogain(gspca_dev);
-       if (!(gspca_dev->ctrl_inac & ((1 << EXPOSURE) | (1 << GAIN)))) {
-               setexposure(gspca_dev);
-               setgain(gspca_dev);
-       }
-       setfreq(gspca_dev);
-
-       sd->pktsz = sd->npkt = 0;
-       sd->nchg = sd->short_mark = 0;
-       sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
-
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       static const u8 stophv7131[] =
-               { 0xa1, 0x11, 0x02, 0x09, 0x00, 0x00, 0x00, 0x10 };
-       static const u8 stopmi0360[] =
-               { 0xb1, 0x5d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x10 };
-       static const u8 stopov7648[] =
-               { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
-       static const u8 stopsoi768[] =
-               { 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };
-       u8 reg01;
-       u8 reg17;
-
-       reg01 = sd->reg01;
-       reg17 = sd->reg17 & ~SEN_CLK_EN;
-       switch (sd->sensor) {
-       case SENSOR_ADCM1700:
-       case SENSOR_GC0307:
-       case SENSOR_PO2030N:
-       case SENSOR_SP80708:
-               reg01 |= LED;
-               reg_w1(gspca_dev, 0x01, reg01);
-               reg01 &= ~(LED | V_TX_EN);
-               reg_w1(gspca_dev, 0x01, reg01);
-/*             reg_w1(gspca_dev, 0x02, 0x??);   * LED off ? */
-               break;
-       case SENSOR_HV7131R:
-               reg01 &= ~V_TX_EN;
-               reg_w1(gspca_dev, 0x01, reg01);
-               i2c_w8(gspca_dev, stophv7131);
-               break;
-       case SENSOR_MI0360:
-       case SENSOR_MI0360B:
-               reg01 &= ~V_TX_EN;
-               reg_w1(gspca_dev, 0x01, reg01);
-/*             reg_w1(gspca_dev, 0x02, 0x40);    * LED off ? */
-               i2c_w8(gspca_dev, stopmi0360);
-               break;
-       case SENSOR_MT9V111:
-       case SENSOR_OM6802:
-       case SENSOR_PO1030:
-               reg01 &= ~V_TX_EN;
-               reg_w1(gspca_dev, 0x01, reg01);
-               break;
-       case SENSOR_OV7630:
-       case SENSOR_OV7648:
-               reg01 &= ~V_TX_EN;
-               reg_w1(gspca_dev, 0x01, reg01);
-               i2c_w8(gspca_dev, stopov7648);
-               break;
-       case SENSOR_OV7660:
-               reg01 &= ~V_TX_EN;
-               reg_w1(gspca_dev, 0x01, reg01);
-               break;
-       case SENSOR_SOI768:
-               i2c_w8(gspca_dev, stopsoi768);
-               break;
-       }
-
-       reg01 |= SCL_SEL_OD;
-       reg_w1(gspca_dev, 0x01, reg01);
-       reg01 |= S_PWR_DN;              /* sensor power down */
-       reg_w1(gspca_dev, 0x01, reg01);
-       reg_w1(gspca_dev, 0x17, reg17);
-       reg01 &= ~SYS_SEL_48M;          /* clock 24MHz */
-       reg_w1(gspca_dev, 0x01, reg01);
-       reg01 |= LED;
-       reg_w1(gspca_dev, 0x01, reg01);
-       /* Don't disable sensor clock as that disables the button on the cam */
-       /* reg_w1(gspca_dev, 0xf1, 0x01); */
-}
-
-/* called on streamoff with alt==0 and on disconnect */
-/* the usb_lock is held at entry - restore on exit */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->work_thread != NULL) {
-               mutex_unlock(&gspca_dev->usb_lock);
-               destroy_workqueue(sd->work_thread);
-               mutex_lock(&gspca_dev->usb_lock);
-               sd->work_thread = NULL;
-       }
-}
-
-#define WANT_REGULAR_AUTOGAIN
-#include "autogain_functions.h"
-
-static void do_autogain(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int delta;
-       int expotimes;
-       u8 luma_mean = 130;
-       u8 luma_delta = 20;
-
-       /* Thanks S., without your advice, autobright should not work :) */
-       if (sd->ag_cnt < 0)
-               return;
-       if (--sd->ag_cnt >= 0)
-               return;
-       sd->ag_cnt = AG_CNT_START;
-
-       delta = atomic_read(&sd->avg_lum);
-       PDEBUG(D_FRAM, "mean lum %d", delta);
-
-       if (sd->sensor == SENSOR_PO2030N) {
-               auto_gain_n_exposure(gspca_dev, delta, luma_mean, luma_delta,
-                                       15, 1024);
-               return;
-       }
-
-       if (delta < luma_mean - luma_delta ||
-           delta > luma_mean + luma_delta) {
-               switch (sd->sensor) {
-               case SENSOR_GC0307:
-                       expotimes = sd->exposure;
-                       expotimes += (luma_mean - delta) >> 6;
-                       if (expotimes < 0)
-                               expotimes = 0;
-                       sd->exposure = expo_adjust(gspca_dev,
-                                                  (unsigned int) expotimes);
-                       break;
-               case SENSOR_HV7131R:
-                       expotimes = sd->exposure >> 8;
-                       expotimes += (luma_mean - delta) >> 4;
-                       if (expotimes < 0)
-                               expotimes = 0;
-                       sd->exposure = expo_adjust(gspca_dev,
-                                       (unsigned int) (expotimes << 8));
-                       break;
-               case SENSOR_OM6802:
-               case SENSOR_MT9V111:
-                       expotimes = sd->exposure;
-                       expotimes += (luma_mean - delta) >> 2;
-                       if (expotimes < 0)
-                               expotimes = 0;
-                       sd->exposure = expo_adjust(gspca_dev,
-                                                  (unsigned int) expotimes);
-                       setredblue(gspca_dev);
-                       break;
-               default:
-/*             case SENSOR_MO4000: */
-/*             case SENSOR_MI0360: */
-/*             case SENSOR_MI0360B: */
-                       expotimes = sd->exposure;
-                       expotimes += (luma_mean - delta) >> 6;
-                       if (expotimes < 0)
-                               expotimes = 0;
-                       sd->exposure = expo_adjust(gspca_dev,
-                                                  (unsigned int) expotimes);
-                       setredblue(gspca_dev);
-                       break;
-               }
-       }
-}
-
-/* set the average luminosity from an isoc marker */
-static void set_lum(struct sd *sd,
-                   u8 *data)
-{
-       int avg_lum;
-
-       /*      w0 w1 w2
-        *      w3 w4 w5
-        *      w6 w7 w8
-        */
-       avg_lum = (data[27] << 8) + data[28]            /* w3 */
-
-               + (data[31] << 8) + data[32]            /* w5 */
-
-               + (data[23] << 8) + data[24]            /* w1 */
-
-               + (data[35] << 8) + data[36]            /* w7 */
-
-               + (data[29] << 10) + (data[30] << 2);   /* w4 * 4 */
-       avg_lum >>= 10;
-       atomic_set(&sd->avg_lum, avg_lum);
-}
-
-/* scan the URB packets */
-/* This function is run at interrupt level. */
-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;
-       int i, new_qual;
-
-       /*
-        * A frame ends on the marker
-        *              ff ff 00 c4 c4 96 ..
-        * which is 62 bytes long and is followed by various information
-        * including statuses and luminosity.
-        *
-        * A marker may be splitted on two packets.
-        *
-        * The 6th byte of a marker contains the bits:
-        *      0x08: USB full
-        *      0xc0: frame sequence
-        * When the bit 'USB full' is set, the frame must be discarded;
-        * this is also the case when the 2 bytes before the marker are
-        * not the JPEG end of frame ('ff d9').
-        */
-
-       /* count the packets and their size */
-       sd->npkt++;
-       sd->pktsz += len;
-
-/*fixme: assumption about the following code:
- *     - there can be only one marker in a packet
- */
-
-       /* skip the remaining bytes of a short marker */
-       i = sd->short_mark;
-       if (i != 0) {
-               sd->short_mark = 0;
-               if (i < 0       /* if 'ff' at end of previous packet */
-                && data[0] == 0xff
-                && data[1] == 0x00)
-                       goto marker_found;
-               if (data[0] == 0xff && data[1] == 0xff) {
-                       i = 0;
-                       goto marker_found;
-               }
-               len -= i;
-               if (len <= 0)
-                       return;
-               data += i;
-       }
-
-       /* search backwards if there is a marker in the packet */
-       for (i = len - 1; --i >= 0; ) {
-               if (data[i] != 0xff) {
-                       i--;
-                       continue;
-               }
-               if (data[i + 1] == 0xff) {
-
-                       /* (there may be 'ff ff' inside a marker) */
-                       if (i + 2 >= len || data[i + 2] == 0x00)
-                               goto marker_found;
-               }
-       }
-
-       /* no marker found */
-       /* add the JPEG header if first fragment */
-       if (data[len - 1] == 0xff)
-               sd->short_mark = -1;
-       if (gspca_dev->last_packet_type == LAST_PACKET)
-               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                               sd->jpeg_hdr, JPEG_HDR_SZ);
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-       return;
-
-       /* marker found */
-       /* if some error, discard the frame and decrease the quality */
-marker_found:
-       new_qual = 0;
-       if (i > 2) {
-               if (data[i - 2] != 0xff || data[i - 1] != 0xd9) {
-                       gspca_dev->last_packet_type = DISCARD_PACKET;
-                       new_qual = -3;
-               }
-       } else if (i + 6 < len) {
-               if (data[i + 6] & 0x08) {
-                       gspca_dev->last_packet_type = DISCARD_PACKET;
-                       new_qual = -5;
-               }
-       }
-
-       gspca_frame_add(gspca_dev, LAST_PACKET, data, i);
-
-       /* compute the filling rate and a new JPEG quality */
-       if (new_qual == 0) {
-               int r;
-
-               r = (sd->pktsz * 100) /
-                       (sd->npkt *
-                               gspca_dev->urb[0]->iso_frame_desc[0].length);
-               if (r >= 85)
-                       new_qual = -3;
-               else if (r < 75)
-                       new_qual = 2;
-       }
-       if (new_qual != 0) {
-               sd->nchg += new_qual;
-               if (sd->nchg < -6 || sd->nchg >= 12) {
-                       sd->nchg = 0;
-                       new_qual += sd->quality;
-                       if (new_qual < QUALITY_MIN)
-                               new_qual = QUALITY_MIN;
-                       else if (new_qual > QUALITY_MAX)
-                               new_qual = QUALITY_MAX;
-                       if (new_qual != sd->quality) {
-                               sd->quality = new_qual;
-                               queue_work(sd->work_thread, &sd->work);
-                       }
-               }
-       } else {
-               sd->nchg = 0;
-       }
-       sd->pktsz = sd->npkt = 0;
-
-       /* if the marker is smaller than 62 bytes,
-        * memorize the number of bytes to skip in the next packet */
-       if (i + 62 > len) {                     /* no more usable data */
-               sd->short_mark = i + 62 - len;
-               return;
-       }
-       if (sd->ag_cnt >= 0)
-               set_lum(sd, data + i);
-
-       /* if more data, start a new frame */
-       i += 62;
-       if (i < len) {
-               data += i;
-               len -= i;
-               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                               sd->jpeg_hdr, JPEG_HDR_SZ);
-               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-       }
-}
-
-static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->ctrls[AUTOGAIN].val = val;
-       if (val)
-               gspca_dev->ctrl_inac |= (1 << EXPOSURE) | (1 << GAIN);
-       else
-               gspca_dev->ctrl_inac &= ~(1 << EXPOSURE) & ~(1 << GAIN);
-       if (gspca_dev->streaming)
-               setautogain(gspca_dev);
-       return gspca_dev->usb_err;
-}
-
-static int sd_querymenu(struct gspca_dev *gspca_dev,
-                       struct v4l2_querymenu *menu)
-{
-       switch (menu->id) {
-       case V4L2_CID_POWER_LINE_FREQUENCY:
-               switch (menu->index) {
-               case 0:         /* V4L2_CID_POWER_LINE_FREQUENCY_DISABLED */
-                       strcpy((char *) menu->name, "NoFliker");
-                       return 0;
-               case 1:         /* V4L2_CID_POWER_LINE_FREQUENCY_50HZ */
-                       strcpy((char *) menu->name, "50 Hz");
-                       return 0;
-               case 2:         /* V4L2_CID_POWER_LINE_FREQUENCY_60HZ */
-                       strcpy((char *) menu->name, "60 Hz");
-                       return 0;
-               }
-               break;
-       }
-       return -EINVAL;
-}
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,               /* interrupt packet data */
-                       int len)                /* interrupt packet length */
-{
-       int ret = -EINVAL;
-
-       if (len == 1 && data[0] == 1) {
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
-               input_sync(gspca_dev->input_dev);
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
-               input_sync(gspca_dev->input_dev);
-               ret = 0;
-       }
-
-       return ret;
-}
-#endif
-
-/* sub-driver description */
-static const struct sd_desc sd_desc = {
-       .name = MODULE_NAME,
-       .ctrls = sd_ctrls,
-       .nctrls = NCTRLS,
-       .config = sd_config,
-       .init = sd_init,
-       .start = sd_start,
-       .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .pkt_scan = sd_pkt_scan,
-       .dq_callback = do_autogain,
-       .querymenu = sd_querymenu,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .int_pkt_scan = sd_int_pkt_scan,
-#endif
-};
-
-/* -- module initialisation -- */
-#define BS(bridge, sensor) \
-       .driver_info = (BRIDGE_ ## bridge << 16) \
-                       | (SENSOR_ ## sensor << 8)
-#define BSF(bridge, sensor, flags) \
-       .driver_info = (BRIDGE_ ## bridge << 16) \
-                       | (SENSOR_ ## sensor << 8) \
-                       | (flags)
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x0458, 0x7025), BSF(SN9C120, MI0360B, F_PDN_INV)},
-       {USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},
-       {USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, F_PDN_INV)},
-       {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, F_PDN_INV)},
-       {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},
-       {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},
-       {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},
-       {USB_DEVICE(0x06f8, 0x3004), BS(SN9C105, OV7660)},
-       {USB_DEVICE(0x06f8, 0x3008), BS(SN9C105, OV7660)},
-/*     {USB_DEVICE(0x0c45, 0x603a), BS(SN9C102P, OV7648)}, */
-       {USB_DEVICE(0x0c45, 0x6040), BS(SN9C102P, HV7131R)},
-/*     {USB_DEVICE(0x0c45, 0x607a), BS(SN9C102P, OV7648)}, */
-/*     {USB_DEVICE(0x0c45, 0x607b), BS(SN9C102P, OV7660)}, */
-       {USB_DEVICE(0x0c45, 0x607c), BS(SN9C102P, HV7131R)},
-/*     {USB_DEVICE(0x0c45, 0x607e), BS(SN9C102P, OV7630)}, */
-       {USB_DEVICE(0x0c45, 0x60c0), BSF(SN9C105, MI0360, F_ILLUM)},
-                                               /* or MT9V111 */
-/*     {USB_DEVICE(0x0c45, 0x60c2), BS(SN9C105, P1030xC)}, */
-/*     {USB_DEVICE(0x0c45, 0x60c8), BS(SN9C105, OM6802)}, */
-/*     {USB_DEVICE(0x0c45, 0x60cc), BS(SN9C105, HV7131GP)}, */
-       {USB_DEVICE(0x0c45, 0x60ce), BS(SN9C105, SP80708)},
-       {USB_DEVICE(0x0c45, 0x60ec), BS(SN9C105, MO4000)},
-/*     {USB_DEVICE(0x0c45, 0x60ef), BS(SN9C105, ICM105C)}, */
-/*     {USB_DEVICE(0x0c45, 0x60fa), BS(SN9C105, OV7648)}, */
-/*     {USB_DEVICE(0x0c45, 0x60f2), BS(SN9C105, OV7660)}, */
-       {USB_DEVICE(0x0c45, 0x60fb), BS(SN9C105, OV7660)},
-       {USB_DEVICE(0x0c45, 0x60fc), BS(SN9C105, HV7131R)},
-       {USB_DEVICE(0x0c45, 0x60fe), BS(SN9C105, OV7630)},
-       {USB_DEVICE(0x0c45, 0x6100), BS(SN9C120, MI0360)},      /*sn9c128*/
-       {USB_DEVICE(0x0c45, 0x6102), BS(SN9C120, PO2030N)},     /* /GC0305*/
-/*     {USB_DEVICE(0x0c45, 0x6108), BS(SN9C120, OM6802)}, */
-       {USB_DEVICE(0x0c45, 0x610a), BS(SN9C120, OV7648)},      /*sn9c128*/
-       {USB_DEVICE(0x0c45, 0x610b), BS(SN9C120, OV7660)},      /*sn9c128*/
-       {USB_DEVICE(0x0c45, 0x610c), BS(SN9C120, HV7131R)},     /*sn9c128*/
-       {USB_DEVICE(0x0c45, 0x610e), BS(SN9C120, OV7630)},      /*sn9c128*/
-/*     {USB_DEVICE(0x0c45, 0x610f), BS(SN9C120, S5K53BEB)}, */
-/*     {USB_DEVICE(0x0c45, 0x6122), BS(SN9C110, ICM105C)}, */
-/*     {USB_DEVICE(0x0c45, 0x6123), BS(SN9C110, SanyoCCD)}, */
-       {USB_DEVICE(0x0c45, 0x6128), BS(SN9C120, OM6802)},      /*sn9c325?*/
-/*bw600.inf:*/
-       {USB_DEVICE(0x0c45, 0x612a), BS(SN9C120, OV7648)},      /*sn9c325?*/
-       {USB_DEVICE(0x0c45, 0x612b), BS(SN9C110, ADCM1700)},
-       {USB_DEVICE(0x0c45, 0x612c), BS(SN9C110, MO4000)},
-       {USB_DEVICE(0x0c45, 0x612e), BS(SN9C110, OV7630)},
-/*     {USB_DEVICE(0x0c45, 0x612f), BS(SN9C110, ICM105C)}, */
-       {USB_DEVICE(0x0c45, 0x6130), BS(SN9C120, MI0360)},
-                                               /* or MT9V111 / MI0360B */
-/*     {USB_DEVICE(0x0c45, 0x6132), BS(SN9C120, OV7670)}, */
-       {USB_DEVICE(0x0c45, 0x6138), BS(SN9C120, MO4000)},
-       {USB_DEVICE(0x0c45, 0x613a), BS(SN9C120, OV7648)},
-       {USB_DEVICE(0x0c45, 0x613b), BS(SN9C120, OV7660)},
-       {USB_DEVICE(0x0c45, 0x613c), BS(SN9C120, HV7131R)},
-       {USB_DEVICE(0x0c45, 0x613e), BS(SN9C120, OV7630)},
-       {USB_DEVICE(0x0c45, 0x6142), BS(SN9C120, PO2030N)},     /*sn9c120b*/
-                                               /* or GC0305 / GC0307 */
-       {USB_DEVICE(0x0c45, 0x6143), BS(SN9C120, SP80708)},     /*sn9c120b*/
-       {USB_DEVICE(0x0c45, 0x6148), BS(SN9C120, OM6802)},      /*sn9c120b*/
-       {USB_DEVICE(0x0c45, 0x614a), BSF(SN9C120, ADCM1700, F_ILLUM)},
-/*     {USB_DEVICE(0x0c45, 0x614c), BS(SN9C120, GC0306)}, */   /*sn9c120b*/
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/spca1528.c b/drivers/media/video/gspca/spca1528.c
deleted file mode 100644 (file)
index 14d6352..0000000
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * spca1528 subdriver
- *
- * Copyright (C) 2010-2011 Jean-Francois Moine (http://moinejf.free.fr)
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "spca1528"
-
-#include "gspca.h"
-#include "jpeg.h"
-
-MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
-MODULE_DESCRIPTION("SPCA1528 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       u8 pkt_seq;
-
-       u8 jpeg_hdr[JPEG_HDR_SZ];
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-/*             (does not work correctly)
-       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 5 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 3},
-*/
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 4 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 2},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-};
-
-/* read <len> bytes to gspca usb_buf */
-static void reg_r(struct gspca_dev *gspca_dev,
-                       u8 req,
-                       u16 index,
-                       int len)
-{
-#if USB_BUF_SZ < 64
-#error "USB buffer too small"
-#endif
-       struct usb_device *dev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-                       req,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0x0000,                 /* value */
-                       index,
-                       gspca_dev->usb_buf, len,
-                       500);
-       PDEBUG(D_USBI, "GET %02x 0000 %04x %02x", req, index,
-                        gspca_dev->usb_buf[0]);
-       if (ret < 0) {
-               pr_err("reg_r err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void reg_w(struct gspca_dev *gspca_dev,
-                       u8 req,
-                       u16 value,
-                       u16 index)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
-       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-                       req,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index,
-                       NULL, 0, 500);
-       if (ret < 0) {
-               pr_err("reg_w err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void reg_wb(struct gspca_dev *gspca_dev,
-                       u8 req,
-                       u16 value,
-                       u16 index,
-                       u8 byte)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       PDEBUG(D_USBO, "SET %02x %04x %04x %02x", req, value, index, byte);
-       gspca_dev->usb_buf[0] = byte;
-       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-                       req,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index,
-                       gspca_dev->usb_buf, 1, 500);
-       if (ret < 0) {
-               pr_err("reg_w err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void wait_status_0(struct gspca_dev *gspca_dev)
-{
-       int i, w;
-
-       i = 16;
-       w = 0;
-       do {
-               reg_r(gspca_dev, 0x21, 0x0000, 1);
-               if (gspca_dev->usb_buf[0] == 0)
-                       return;
-               w += 15;
-               msleep(w);
-       } while (--i > 0);
-       PDEBUG(D_ERR, "wait_status_0 timeout");
-       gspca_dev->usb_err = -ETIME;
-}
-
-static void wait_status_1(struct gspca_dev *gspca_dev)
-{
-       int i;
-
-       i = 10;
-       do {
-               reg_r(gspca_dev, 0x21, 0x0001, 1);
-               msleep(10);
-               if (gspca_dev->usb_buf[0] == 1) {
-                       reg_wb(gspca_dev, 0x21, 0x0000, 0x0001, 0x00);
-                       reg_r(gspca_dev, 0x21, 0x0001, 1);
-                       return;
-               }
-       } while (--i > 0);
-       PDEBUG(D_ERR, "wait_status_1 timeout");
-       gspca_dev->usb_err = -ETIME;
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_wb(gspca_dev, 0xc0, 0x0000, 0x00c0, val);
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_wb(gspca_dev, 0xc1, 0x0000, 0x00c1, val);
-}
-
-static void sethue(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_wb(gspca_dev, 0xc2, 0x0000, 0x0000, val);
-}
-
-static void setcolor(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_wb(gspca_dev, 0xc3, 0x0000, 0x00c3, val);
-}
-
-static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_wb(gspca_dev, 0xc4, 0x0000, 0x00c4, val);
-}
-
-/* this function is called at probe time */
-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);
-       gspca_dev->cam.npkt = 128; /* number of packets per ISOC message */
-                       /*fixme: 256 in ms-win traces*/
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       reg_w(gspca_dev, 0x00, 0x0001, 0x2067);
-       reg_w(gspca_dev, 0x00, 0x00d0, 0x206b);
-       reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
-       reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
-       msleep(8);
-       reg_w(gspca_dev, 0x00, 0x00c0, 0x206b);
-       reg_w(gspca_dev, 0x00, 0x0000, 0x206c);
-       reg_w(gspca_dev, 0x00, 0x0001, 0x2069);
-
-       reg_r(gspca_dev, 0x20, 0x0000, 1);
-       reg_r(gspca_dev, 0x20, 0x0000, 5);
-       reg_r(gspca_dev, 0x23, 0x0000, 64);
-       PDEBUG(D_PROBE, "%s%s", &gspca_dev->usb_buf[0x1c],
-                               &gspca_dev->usb_buf[0x30]);
-       reg_r(gspca_dev, 0x23, 0x0001, 64);
-       return gspca_dev->usb_err;
-}
-
-/* function called at start time before URB creation */
-static int sd_isoc_init(struct gspca_dev *gspca_dev)
-{
-       u8 mode;
-
-       reg_r(gspca_dev, 0x00, 0x2520, 1);
-       wait_status_0(gspca_dev);
-       reg_w(gspca_dev, 0xc5, 0x0003, 0x0000);
-       wait_status_1(gspca_dev);
-
-       wait_status_0(gspca_dev);
-       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-       reg_wb(gspca_dev, 0x25, 0x0000, 0x0004, mode);
-       reg_r(gspca_dev, 0x25, 0x0004, 1);
-       reg_wb(gspca_dev, 0x27, 0x0000, 0x0000, 0x06);  /* 420 */
-       reg_r(gspca_dev, 0x27, 0x0000, 1);
-
-/* not useful..
-       gspca_dev->alt = 4;             * use alternate setting 3 */
-
-       return gspca_dev->usb_err;
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* initialize the JPEG header */
-       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
-                       0x22);          /* JPEG 411 */
-
-       /* the JPEG quality shall be 85% */
-       jpeg_set_qual(sd->jpeg_hdr, 85);
-
-       reg_r(gspca_dev, 0x00, 0x2520, 1);
-       msleep(8);
-
-       /* start the capture */
-       wait_status_0(gspca_dev);
-       reg_w(gspca_dev, 0x31, 0x0000, 0x0004); /* start request */
-       wait_status_1(gspca_dev);
-       wait_status_0(gspca_dev);
-       msleep(200);
-
-       sd->pkt_seq = 0;
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       /* stop the capture */
-       wait_status_0(gspca_dev);
-       reg_w(gspca_dev, 0x31, 0x0000, 0x0000); /* stop request */
-       wait_status_1(gspca_dev);
-       wait_status_0(gspca_dev);
-}
-
-/* move a packet adding 0x00 after 0xff */
-static void add_packet(struct gspca_dev *gspca_dev,
-                       u8 *data,
-                       int len)
-{
-       int i;
-
-       i = 0;
-       do {
-               if (data[i] == 0xff) {
-                       gspca_frame_add(gspca_dev, INTER_PACKET,
-                                       data, i + 1);
-                       len -= i;
-                       data += i;
-                       *data = 0x00;
-                       i = 0;
-               }
-       } while (++i < len);
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-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;
-       static const u8 ffd9[] = {0xff, 0xd9};
-
-       /* image packets start with:
-        *      02 8n
-        * with <n> bit:
-        *      0x01: even (0) / odd (1) image
-        *      0x02: end of image when set
-        */
-       if (len < 3)
-               return;                         /* empty packet */
-       if (*data == 0x02) {
-               if (data[1] & 0x02) {
-                       sd->pkt_seq = !(data[1] & 1);
-                       add_packet(gspca_dev, data + 2, len - 2);
-                       gspca_frame_add(gspca_dev, LAST_PACKET,
-                                       ffd9, 2);
-                       return;
-               }
-               if ((data[1] & 1) != sd->pkt_seq)
-                       goto err;
-               if (gspca_dev->last_packet_type == LAST_PACKET)
-                       gspca_frame_add(gspca_dev, FIRST_PACKET,
-                                       sd->jpeg_hdr, JPEG_HDR_SZ);
-               add_packet(gspca_dev, data + 2, len - 2);
-               return;
-       }
-err:
-       gspca_dev->last_packet_type = DISCARD_PACKET;
-}
-
-static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct gspca_dev *gspca_dev =
-               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
-
-       gspca_dev->usb_err = 0;
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_HUE:
-               sethue(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               setcolor(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SHARPNESS:
-               setsharpness(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 5);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 8, 1, 1);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_HUE, 0, 255, 1, 0);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 8, 1, 1);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SHARPNESS, 0, 255, 1, 0);
-
-       if (hdl->error) {
-               pr_err("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,
-       .isoc_init = sd_isoc_init,
-       .start = sd_start,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x04fc, 0x1528)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-static int sd_probe(struct usb_interface *intf,
-                       const struct usb_device_id *id)
-{
-       /* the video interface for isochronous transfer is 1 */
-       if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
-               return -ENODEV;
-
-       return gspca_dev_probe2(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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/spca500.c b/drivers/media/video/gspca/spca500.c
deleted file mode 100644 (file)
index 25cb68d..0000000
+++ /dev/null
@@ -1,990 +0,0 @@
-/*
- * SPCA500 chip based cameras initialization data
- *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "spca500"
-
-#include "gspca.h"
-#include "jpeg.h"
-
-MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
-MODULE_DESCRIPTION("GSPCA/SPCA500 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-#define QUALITY 85
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;             /* !! must be the first item */
-
-       char subtype;
-#define AgfaCl20 0
-#define AiptekPocketDV 1
-#define BenqDC1016 2
-#define CreativePCCam300 3
-#define DLinkDSC350 4
-#define Gsmartmini 5
-#define IntelPocketPCCamera 6
-#define KodakEZ200 7
-#define LogitechClickSmart310 8
-#define LogitechClickSmart510 9
-#define LogitechTraveler 10
-#define MustekGsmart300 11
-#define Optimedia 12
-#define PalmPixDC85 13
-#define ToptroIndus 14
-
-       u8 jpeg_hdr[JPEG_HDR_SZ];
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-
-static const struct v4l2_pix_format sif_mode[] = {
-       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-
-/* Frame packet header offsets for the spca500 */
-#define SPCA500_OFFSET_PADDINGLB 2
-#define SPCA500_OFFSET_PADDINGHB 3
-#define SPCA500_OFFSET_MODE      4
-#define SPCA500_OFFSET_IMGWIDTH  5
-#define SPCA500_OFFSET_IMGHEIGHT 6
-#define SPCA500_OFFSET_IMGMODE   7
-#define SPCA500_OFFSET_QTBLINDEX 8
-#define SPCA500_OFFSET_FRAMSEQ   9
-#define SPCA500_OFFSET_CDSPINFO  10
-#define SPCA500_OFFSET_GPIO      11
-#define SPCA500_OFFSET_AUGPIO    12
-#define SPCA500_OFFSET_DATA      16
-
-
-static const __u16 spca500_visual_defaults[][3] = {
-       {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
-                                * hue (H byte) = 0,
-                                * saturation/hue enable,
-                                * brightness/contrast enable.
-                                */
-       {0x00, 0x0000, 0x8167}, /* brightness = 0 */
-       {0x00, 0x0020, 0x8168}, /* contrast = 0 */
-       {0x00, 0x0003, 0x816b}, /* SSI not active sync with vsync,
-                                * hue (H byte) = 0, saturation/hue enable,
-                                * brightness/contrast enable.
-                                * was 0x0003, now 0x0000.
-                                */
-       {0x00, 0x0000, 0x816a}, /* hue (L byte) = 0 */
-       {0x00, 0x0020, 0x8169}, /* saturation = 0x20 */
-       {0x00, 0x0050, 0x8157}, /* edge gain high threshold */
-       {0x00, 0x0030, 0x8158}, /* edge gain low threshold */
-       {0x00, 0x0028, 0x8159}, /* edge bandwidth high threshold */
-       {0x00, 0x000a, 0x815a}, /* edge bandwidth low threshold */
-       {0x00, 0x0001, 0x8202}, /* clock rate compensation = 1/25 sec/frame */
-       {0x0c, 0x0004, 0x0000},
-       /* set interface */
-       {}
-};
-static const __u16 Clicksmart510_defaults[][3] = {
-       {0x00, 0x00, 0x8211},
-       {0x00, 0x01, 0x82c0},
-       {0x00, 0x10, 0x82cb},
-       {0x00, 0x0f, 0x800d},
-       {0x00, 0x82, 0x8225},
-       {0x00, 0x21, 0x8228},
-       {0x00, 0x00, 0x8203},
-       {0x00, 0x00, 0x8204},
-       {0x00, 0x08, 0x8205},
-       {0x00, 0xf8, 0x8206},
-       {0x00, 0x28, 0x8207},
-       {0x00, 0xa0, 0x8208},
-       {0x00, 0x08, 0x824a},
-       {0x00, 0x08, 0x8214},
-       {0x00, 0x80, 0x82c1},
-       {0x00, 0x00, 0x82c2},
-       {0x00, 0x00, 0x82ca},
-       {0x00, 0x80, 0x82c1},
-       {0x00, 0x04, 0x82c2},
-       {0x00, 0x00, 0x82ca},
-       {0x00, 0xfc, 0x8100},
-       {0x00, 0xfc, 0x8105},
-       {0x00, 0x30, 0x8101},
-       {0x00, 0x00, 0x8102},
-       {0x00, 0x00, 0x8103},
-       {0x00, 0x66, 0x8107},
-       {0x00, 0x00, 0x816b},
-       {0x00, 0x00, 0x8155},
-       {0x00, 0x01, 0x8156},
-       {0x00, 0x60, 0x8157},
-       {0x00, 0x40, 0x8158},
-       {0x00, 0x0a, 0x8159},
-       {0x00, 0x06, 0x815a},
-       {0x00, 0x00, 0x813f},
-       {0x00, 0x00, 0x8200},
-       {0x00, 0x19, 0x8201},
-       {0x00, 0x00, 0x82c1},
-       {0x00, 0xa0, 0x82c2},
-       {0x00, 0x00, 0x82ca},
-       {0x00, 0x00, 0x8117},
-       {0x00, 0x00, 0x8118},
-       {0x00, 0x65, 0x8119},
-       {0x00, 0x00, 0x811a},
-       {0x00, 0x00, 0x811b},
-       {0x00, 0x55, 0x811c},
-       {0x00, 0x65, 0x811d},
-       {0x00, 0x55, 0x811e},
-       {0x00, 0x16, 0x811f},
-       {0x00, 0x19, 0x8120},
-       {0x00, 0x80, 0x8103},
-       {0x00, 0x83, 0x816b},
-       {0x00, 0x25, 0x8168},
-       {0x00, 0x01, 0x820f},
-       {0x00, 0xff, 0x8115},
-       {0x00, 0x48, 0x8116},
-       {0x00, 0x50, 0x8151},
-       {0x00, 0x40, 0x8152},
-       {0x00, 0x78, 0x8153},
-       {0x00, 0x40, 0x8154},
-       {0x00, 0x00, 0x8167},
-       {0x00, 0x20, 0x8168},
-       {0x00, 0x00, 0x816a},
-       {0x00, 0x03, 0x816b},
-       {0x00, 0x20, 0x8169},
-       {0x00, 0x60, 0x8157},
-       {0x00, 0x00, 0x8190},
-       {0x00, 0x00, 0x81a1},
-       {0x00, 0x00, 0x81b2},
-       {0x00, 0x27, 0x8191},
-       {0x00, 0x27, 0x81a2},
-       {0x00, 0x27, 0x81b3},
-       {0x00, 0x4b, 0x8192},
-       {0x00, 0x4b, 0x81a3},
-       {0x00, 0x4b, 0x81b4},
-       {0x00, 0x66, 0x8193},
-       {0x00, 0x66, 0x81a4},
-       {0x00, 0x66, 0x81b5},
-       {0x00, 0x79, 0x8194},
-       {0x00, 0x79, 0x81a5},
-       {0x00, 0x79, 0x81b6},
-       {0x00, 0x8a, 0x8195},
-       {0x00, 0x8a, 0x81a6},
-       {0x00, 0x8a, 0x81b7},
-       {0x00, 0x9b, 0x8196},
-       {0x00, 0x9b, 0x81a7},
-       {0x00, 0x9b, 0x81b8},
-       {0x00, 0xa6, 0x8197},
-       {0x00, 0xa6, 0x81a8},
-       {0x00, 0xa6, 0x81b9},
-       {0x00, 0xb2, 0x8198},
-       {0x00, 0xb2, 0x81a9},
-       {0x00, 0xb2, 0x81ba},
-       {0x00, 0xbe, 0x8199},
-       {0x00, 0xbe, 0x81aa},
-       {0x00, 0xbe, 0x81bb},
-       {0x00, 0xc8, 0x819a},
-       {0x00, 0xc8, 0x81ab},
-       {0x00, 0xc8, 0x81bc},
-       {0x00, 0xd2, 0x819b},
-       {0x00, 0xd2, 0x81ac},
-       {0x00, 0xd2, 0x81bd},
-       {0x00, 0xdb, 0x819c},
-       {0x00, 0xdb, 0x81ad},
-       {0x00, 0xdb, 0x81be},
-       {0x00, 0xe4, 0x819d},
-       {0x00, 0xe4, 0x81ae},
-       {0x00, 0xe4, 0x81bf},
-       {0x00, 0xed, 0x819e},
-       {0x00, 0xed, 0x81af},
-       {0x00, 0xed, 0x81c0},
-       {0x00, 0xf7, 0x819f},
-       {0x00, 0xf7, 0x81b0},
-       {0x00, 0xf7, 0x81c1},
-       {0x00, 0xff, 0x81a0},
-       {0x00, 0xff, 0x81b1},
-       {0x00, 0xff, 0x81c2},
-       {0x00, 0x03, 0x8156},
-       {0x00, 0x00, 0x8211},
-       {0x00, 0x20, 0x8168},
-       {0x00, 0x01, 0x8202},
-       {0x00, 0x30, 0x8101},
-       {0x00, 0x00, 0x8111},
-       {0x00, 0x00, 0x8112},
-       {0x00, 0x00, 0x8113},
-       {0x00, 0x00, 0x8114},
-       {}
-};
-
-static const __u8 qtable_creative_pccam[2][64] = {
-       {                               /* Q-table Y-components */
-        0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
-        0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
-        0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
-        0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
-        0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
-        0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
-        0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
-        0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
-       {                               /* Q-table C-components */
-        0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
-};
-
-static const __u8 qtable_kodak_ez200[2][64] = {
-       {                               /* Q-table Y-components */
-        0x02, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
-        0x01, 0x01, 0x01, 0x02, 0x03, 0x06, 0x06, 0x06,
-        0x01, 0x01, 0x02, 0x02, 0x04, 0x06, 0x07, 0x06,
-        0x01, 0x02, 0x02, 0x03, 0x05, 0x09, 0x08, 0x06,
-        0x02, 0x02, 0x04, 0x06, 0x07, 0x0b, 0x0a, 0x08,
-        0x02, 0x04, 0x06, 0x06, 0x08, 0x0a, 0x0b, 0x09,
-        0x05, 0x06, 0x08, 0x09, 0x0a, 0x0c, 0x0c, 0x0a,
-        0x07, 0x09, 0x0a, 0x0a, 0x0b, 0x0a, 0x0a, 0x0a},
-       {                               /* Q-table C-components */
-        0x02, 0x02, 0x02, 0x05, 0x0a, 0x0a, 0x0a, 0x0a,
-        0x02, 0x02, 0x03, 0x07, 0x0a, 0x0a, 0x0a, 0x0a,
-        0x02, 0x03, 0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-        0x05, 0x07, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-        0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-        0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-        0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-        0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a}
-};
-
-static const __u8 qtable_pocketdv[2][64] = {
-       {               /* Q-table Y-components start registers 0x8800 */
-        0x06, 0x04, 0x04, 0x06, 0x0a, 0x10, 0x14, 0x18,
-        0x05, 0x05, 0x06, 0x08, 0x0a, 0x17, 0x18, 0x16,
-        0x06, 0x05, 0x06, 0x0a, 0x10, 0x17, 0x1c, 0x16,
-        0x06, 0x07, 0x09, 0x0c, 0x14, 0x23, 0x20, 0x19,
-        0x07, 0x09, 0x0f, 0x16, 0x1b, 0x2c, 0x29, 0x1f,
-        0x0a, 0x0e, 0x16, 0x1a, 0x20, 0x2a, 0x2d, 0x25,
-        0x14, 0x1a, 0x1f, 0x23, 0x29, 0x30, 0x30, 0x28,
-        0x1d, 0x25, 0x26, 0x27, 0x2d, 0x28, 0x29, 0x28,
-        },
-       {               /* Q-table C-components start registers 0x8840 */
-        0x07, 0x07, 0x0a, 0x13, 0x28, 0x28, 0x28, 0x28,
-        0x07, 0x08, 0x0a, 0x1a, 0x28, 0x28, 0x28, 0x28,
-        0x0a, 0x0a, 0x16, 0x28, 0x28, 0x28, 0x28, 0x28,
-        0x13, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-        0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-        0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-        0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-        0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28}
-};
-
-/* read 'len' bytes to gspca_dev->usb_buf */
-static void reg_r(struct gspca_dev *gspca_dev,
-                 __u16 index,
-                 __u16 length)
-{
-       usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       0,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,              /* value */
-                       index, gspca_dev->usb_buf, length, 500);
-}
-
-static int reg_w(struct gspca_dev *gspca_dev,
-                    __u16 req, __u16 index, __u16 value)
-{
-       int ret;
-
-       PDEBUG(D_USBO, "reg write: [0x%02x] = 0x%02x", index, value);
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       req,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index, NULL, 0, 500);
-       if (ret < 0)
-               pr_err("reg write: error %d\n", ret);
-       return ret;
-}
-
-/* returns: negative is error, pos or zero is data */
-static int reg_r_12(struct gspca_dev *gspca_dev,
-                       __u16 req,      /* bRequest */
-                       __u16 index,    /* wIndex */
-                       __u16 length)   /* wLength (1 or 2 only) */
-{
-       int ret;
-
-       gspca_dev->usb_buf[1] = 0;
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       req,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,              /* value */
-                       index,
-                       gspca_dev->usb_buf, length,
-                       500);           /* timeout */
-       if (ret < 0) {
-               pr_err("reg_r_12 err %d\n", ret);
-               return ret;
-       }
-       return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
-}
-
-/*
- * Simple function to wait for a given 8-bit value to be returned from
- * a reg_read call.
- * Returns: negative is error or timeout, zero is success.
- */
-static int reg_r_wait(struct gspca_dev *gspca_dev,
-                       __u16 reg, __u16 index, __u16 value)
-{
-       int ret, cnt = 20;
-
-       while (--cnt > 0) {
-               ret = reg_r_12(gspca_dev, reg, index, 1);
-               if (ret == value)
-                       return 0;
-               msleep(50);
-       }
-       return -EIO;
-}
-
-static int write_vector(struct gspca_dev *gspca_dev,
-                       const __u16 data[][3])
-{
-       int ret, i = 0;
-
-       while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
-               ret = reg_w(gspca_dev, data[i][0], data[i][2], data[i][1]);
-               if (ret < 0)
-                       return ret;
-               i++;
-       }
-       return 0;
-}
-
-static int spca50x_setup_qtable(struct gspca_dev *gspca_dev,
-                               unsigned int request,
-                               unsigned int ybase,
-                               unsigned int cbase,
-                               const __u8 qtable[2][64])
-{
-       int i, err;
-
-       /* loop over y components */
-       for (i = 0; i < 64; i++) {
-               err = reg_w(gspca_dev, request, ybase + i, qtable[0][i]);
-               if (err < 0)
-                       return err;
-       }
-
-       /* loop over c components */
-       for (i = 0; i < 64; i++) {
-               err = reg_w(gspca_dev, request, cbase + i, qtable[1][i]);
-               if (err < 0)
-                       return err;
-       }
-       return 0;
-}
-
-static void spca500_ping310(struct gspca_dev *gspca_dev)
-{
-       reg_r(gspca_dev, 0x0d04, 2);
-       PDEBUG(D_STREAM, "ClickSmart310 ping 0x0d04 0x%02x 0x%02x",
-               gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
-}
-
-static void spca500_clksmart310_init(struct gspca_dev *gspca_dev)
-{
-       reg_r(gspca_dev, 0x0d05, 2);
-       PDEBUG(D_STREAM, "ClickSmart310 init 0x0d05 0x%02x 0x%02x",
-               gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
-       reg_w(gspca_dev, 0x00, 0x8167, 0x5a);
-       spca500_ping310(gspca_dev);
-
-       reg_w(gspca_dev, 0x00, 0x8168, 0x22);
-       reg_w(gspca_dev, 0x00, 0x816a, 0xc0);
-       reg_w(gspca_dev, 0x00, 0x816b, 0x0b);
-       reg_w(gspca_dev, 0x00, 0x8169, 0x25);
-       reg_w(gspca_dev, 0x00, 0x8157, 0x5b);
-       reg_w(gspca_dev, 0x00, 0x8158, 0x5b);
-       reg_w(gspca_dev, 0x00, 0x813f, 0x03);
-       reg_w(gspca_dev, 0x00, 0x8151, 0x4a);
-       reg_w(gspca_dev, 0x00, 0x8153, 0x78);
-       reg_w(gspca_dev, 0x00, 0x0d01, 0x04);
-                                               /* 00 for adjust shutter */
-       reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
-       reg_w(gspca_dev, 0x00, 0x8169, 0x25);
-       reg_w(gspca_dev, 0x00, 0x0d01, 0x02);
-}
-
-static void spca500_setmode(struct gspca_dev *gspca_dev,
-                       __u8 xmult, __u8 ymult)
-{
-       int mode;
-
-       /* set x multiplier */
-       reg_w(gspca_dev, 0, 0x8001, xmult);
-
-       /* set y multiplier */
-       reg_w(gspca_dev, 0, 0x8002, ymult);
-
-       /* use compressed mode, VGA, with mode specific subsample */
-       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
-       reg_w(gspca_dev, 0, 0x8003, mode << 4);
-}
-
-static int spca500_full_reset(struct gspca_dev *gspca_dev)
-{
-       int err;
-
-       /* send the reset command */
-       err = reg_w(gspca_dev, 0xe0, 0x0001, 0x0000);
-       if (err < 0)
-               return err;
-
-       /* wait for the reset to complete */
-       err = reg_r_wait(gspca_dev, 0x06, 0x0000, 0x0000);
-       if (err < 0)
-               return err;
-       err = reg_w(gspca_dev, 0xe0, 0x0000, 0x0000);
-       if (err < 0)
-               return err;
-       err = reg_r_wait(gspca_dev, 0x06, 0, 0);
-       if (err < 0) {
-               PDEBUG(D_ERR, "reg_r_wait() failed");
-               return err;
-       }
-       /* all ok */
-       return 0;
-}
-
-/* Synchro the Bridge with sensor */
-/* Maybe that will work on all spca500 chip */
-/* because i only own a clicksmart310 try for that chip */
-/* using spca50x_set_packet_size() cause an Ooops here */
-/* usb_set_interface from kernel 2.6.x clear all the urb stuff */
-/* up-port the same feature as in 2.4.x kernel */
-static int spca500_synch310(struct gspca_dev *gspca_dev)
-{
-       if (usb_set_interface(gspca_dev->dev, gspca_dev->iface, 0) < 0) {
-               PDEBUG(D_ERR, "Set packet size: set interface error");
-               goto error;
-       }
-       spca500_ping310(gspca_dev);
-
-       reg_r(gspca_dev, 0x0d00, 1);
-
-       /* need alt setting here */
-       PDEBUG(D_PACK, "ClickSmart310 sync alt: %d", gspca_dev->alt);
-
-       /* Windoze use pipe with altsetting 6 why 7 here */
-       if (usb_set_interface(gspca_dev->dev,
-                               gspca_dev->iface,
-                               gspca_dev->alt) < 0) {
-               PDEBUG(D_ERR, "Set packet size: set interface error");
-               goto error;
-       }
-       return 0;
-error:
-       return -EBUSY;
-}
-
-static void spca500_reinit(struct gspca_dev *gspca_dev)
-{
-       int err;
-       __u8 Data;
-
-       /* some unknown command from Aiptek pocket dv and family300 */
-
-       reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
-       reg_w(gspca_dev, 0x00, 0x0d03, 0x00);
-       reg_w(gspca_dev, 0x00, 0x0d02, 0x01);
-
-       /* enable drop packet */
-       reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
-
-       err = spca50x_setup_qtable(gspca_dev, 0x00, 0x8800, 0x8840,
-                                qtable_pocketdv);
-       if (err < 0)
-               PDEBUG(D_ERR|D_STREAM, "spca50x_setup_qtable failed on init");
-
-       /* set qtable index */
-       reg_w(gspca_dev, 0x00, 0x8880, 2);
-       /* family cam Quicksmart stuff */
-       reg_w(gspca_dev, 0x00, 0x800a, 0x00);
-       /* Set agc transfer: synced between frames */
-       reg_w(gspca_dev, 0x00, 0x820f, 0x01);
-       /* Init SDRAM - needed for SDRAM access */
-       reg_w(gspca_dev, 0x00, 0x870a, 0x04);
-       /*Start init sequence or stream */
-       reg_w(gspca_dev, 0, 0x8003, 0x00);
-       /* switch to video camera mode */
-       reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
-       msleep(2000);
-       if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0) {
-               reg_r(gspca_dev, 0x816b, 1);
-               Data = gspca_dev->usb_buf[0];
-               reg_w(gspca_dev, 0x00, 0x816b, Data);
-       }
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-
-       cam = &gspca_dev->cam;
-       sd->subtype = id->driver_info;
-       if (sd->subtype != LogitechClickSmart310) {
-               cam->cam_mode = vga_mode;
-               cam->nmodes = ARRAY_SIZE(vga_mode);
-       } else {
-               cam->cam_mode = sif_mode;
-               cam->nmodes = ARRAY_SIZE(sif_mode);
-       }
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* initialisation of spca500 based cameras is deferred */
-       PDEBUG(D_STREAM, "SPCA500 init");
-       if (sd->subtype == LogitechClickSmart310)
-               spca500_clksmart310_init(gspca_dev);
-/*     else
-               spca500_initialise(gspca_dev); */
-       PDEBUG(D_STREAM, "SPCA500 init done");
-       return 0;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int err;
-       __u8 Data;
-       __u8 xmult, ymult;
-
-       /* create the JPEG header */
-       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
-                       0x22);          /* JPEG 411 */
-       jpeg_set_qual(sd->jpeg_hdr, QUALITY);
-
-       if (sd->subtype == LogitechClickSmart310) {
-               xmult = 0x16;
-               ymult = 0x12;
-       } else {
-               xmult = 0x28;
-               ymult = 0x1e;
-       }
-
-       /* is there a sensor here ? */
-       reg_r(gspca_dev, 0x8a04, 1);
-       PDEBUG(D_STREAM, "Spca500 Sensor Address 0x%02x",
-               gspca_dev->usb_buf[0]);
-       PDEBUG(D_STREAM, "Spca500 curr_mode: %d Xmult: 0x%02x, Ymult: 0x%02x",
-               gspca_dev->curr_mode, xmult, ymult);
-
-       /* setup qtable */
-       switch (sd->subtype) {
-       case LogitechClickSmart310:
-                spca500_setmode(gspca_dev, xmult, ymult);
-
-               /* enable drop packet */
-               reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
-               reg_w(gspca_dev, 0x00, 0x8880, 3);
-               err = spca50x_setup_qtable(gspca_dev,
-                                          0x00, 0x8800, 0x8840,
-                                          qtable_creative_pccam);
-               if (err < 0)
-                       PDEBUG(D_ERR, "spca50x_setup_qtable failed");
-               /* Init SDRAM - needed for SDRAM access */
-               reg_w(gspca_dev, 0x00, 0x870a, 0x04);
-
-               /* switch to video camera mode */
-               reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
-               msleep(500);
-               if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
-                       PDEBUG(D_ERR, "reg_r_wait() failed");
-
-               reg_r(gspca_dev, 0x816b, 1);
-               Data = gspca_dev->usb_buf[0];
-               reg_w(gspca_dev, 0x00, 0x816b, Data);
-
-               spca500_synch310(gspca_dev);
-
-               write_vector(gspca_dev, spca500_visual_defaults);
-               spca500_setmode(gspca_dev, xmult, ymult);
-               /* enable drop packet */
-               err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
-               if (err < 0)
-                       PDEBUG(D_ERR, "failed to enable drop packet");
-               reg_w(gspca_dev, 0x00, 0x8880, 3);
-               err = spca50x_setup_qtable(gspca_dev,
-                                          0x00, 0x8800, 0x8840,
-                                          qtable_creative_pccam);
-               if (err < 0)
-                       PDEBUG(D_ERR, "spca50x_setup_qtable failed");
-
-               /* Init SDRAM - needed for SDRAM access */
-               reg_w(gspca_dev, 0x00, 0x870a, 0x04);
-
-               /* switch to video camera mode */
-               reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
-
-               if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
-                       PDEBUG(D_ERR, "reg_r_wait() failed");
-
-               reg_r(gspca_dev, 0x816b, 1);
-               Data = gspca_dev->usb_buf[0];
-               reg_w(gspca_dev, 0x00, 0x816b, Data);
-               break;
-       case CreativePCCam300:          /* Creative PC-CAM 300 640x480 CCD */
-       case IntelPocketPCCamera:       /* FIXME: Temporary fix for
-                                        *      Intel Pocket PC Camera
-                                        *      - NWG (Sat 29th March 2003) */
-
-               /* do a full reset */
-               err = spca500_full_reset(gspca_dev);
-               if (err < 0)
-                       PDEBUG(D_ERR, "spca500_full_reset failed");
-
-               /* enable drop packet */
-               err = reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
-               if (err < 0)
-                       PDEBUG(D_ERR, "failed to enable drop packet");
-               reg_w(gspca_dev, 0x00, 0x8880, 3);
-               err = spca50x_setup_qtable(gspca_dev,
-                                          0x00, 0x8800, 0x8840,
-                                          qtable_creative_pccam);
-               if (err < 0)
-                       PDEBUG(D_ERR, "spca50x_setup_qtable failed");
-
-               spca500_setmode(gspca_dev, xmult, ymult);
-               reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
-
-               /* switch to video camera mode */
-               reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
-
-               if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
-                       PDEBUG(D_ERR, "reg_r_wait() failed");
-
-               reg_r(gspca_dev, 0x816b, 1);
-               Data = gspca_dev->usb_buf[0];
-               reg_w(gspca_dev, 0x00, 0x816b, Data);
-
-/*             write_vector(gspca_dev, spca500_visual_defaults); */
-               break;
-       case KodakEZ200:                /* Kodak EZ200 */
-
-               /* do a full reset */
-               err = spca500_full_reset(gspca_dev);
-               if (err < 0)
-                       PDEBUG(D_ERR, "spca500_full_reset failed");
-               /* enable drop packet */
-               reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
-               reg_w(gspca_dev, 0x00, 0x8880, 0);
-               err = spca50x_setup_qtable(gspca_dev,
-                                          0x00, 0x8800, 0x8840,
-                                          qtable_kodak_ez200);
-               if (err < 0)
-                       PDEBUG(D_ERR, "spca50x_setup_qtable failed");
-               spca500_setmode(gspca_dev, xmult, ymult);
-
-               reg_w(gspca_dev, 0x20, 0x0001, 0x0004);
-
-               /* switch to video camera mode */
-               reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
-
-               if (reg_r_wait(gspca_dev, 0, 0x8000, 0x44) != 0)
-                       PDEBUG(D_ERR, "reg_r_wait() failed");
-
-               reg_r(gspca_dev, 0x816b, 1);
-               Data = gspca_dev->usb_buf[0];
-               reg_w(gspca_dev, 0x00, 0x816b, Data);
-
-/*             write_vector(gspca_dev, spca500_visual_defaults); */
-               break;
-
-       case BenqDC1016:
-       case DLinkDSC350:               /* FamilyCam 300 */
-       case AiptekPocketDV:            /* Aiptek PocketDV */
-       case Gsmartmini:                /*Mustek Gsmart Mini */
-       case MustekGsmart300:           /* Mustek Gsmart 300 */
-       case PalmPixDC85:
-       case Optimedia:
-       case ToptroIndus:
-       case AgfaCl20:
-               spca500_reinit(gspca_dev);
-               reg_w(gspca_dev, 0x00, 0x0d01, 0x01);
-               /* enable drop packet */
-               reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
-
-               err = spca50x_setup_qtable(gspca_dev,
-                                  0x00, 0x8800, 0x8840, qtable_pocketdv);
-               if (err < 0)
-                       PDEBUG(D_ERR, "spca50x_setup_qtable failed");
-               reg_w(gspca_dev, 0x00, 0x8880, 2);
-
-               /* familycam Quicksmart pocketDV stuff */
-               reg_w(gspca_dev, 0x00, 0x800a, 0x00);
-               /* Set agc transfer: synced between frames */
-               reg_w(gspca_dev, 0x00, 0x820f, 0x01);
-               /* Init SDRAM - needed for SDRAM access */
-               reg_w(gspca_dev, 0x00, 0x870a, 0x04);
-
-               spca500_setmode(gspca_dev, xmult, ymult);
-               /* switch to video camera mode */
-               reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
-
-               reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
-
-               reg_r(gspca_dev, 0x816b, 1);
-               Data = gspca_dev->usb_buf[0];
-               reg_w(gspca_dev, 0x00, 0x816b, Data);
-               break;
-       case LogitechTraveler:
-       case LogitechClickSmart510:
-               reg_w(gspca_dev, 0x02, 0x00, 0x00);
-               /* enable drop packet */
-               reg_w(gspca_dev, 0x00, 0x850a, 0x0001);
-
-               err = spca50x_setup_qtable(gspca_dev,
-                                       0x00, 0x8800,
-                                       0x8840, qtable_creative_pccam);
-               if (err < 0)
-                       PDEBUG(D_ERR, "spca50x_setup_qtable failed");
-               reg_w(gspca_dev, 0x00, 0x8880, 3);
-               reg_w(gspca_dev, 0x00, 0x800a, 0x00);
-               /* Init SDRAM - needed for SDRAM access */
-               reg_w(gspca_dev, 0x00, 0x870a, 0x04);
-
-               spca500_setmode(gspca_dev, xmult, ymult);
-
-               /* switch to video camera mode */
-               reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
-               reg_r_wait(gspca_dev, 0, 0x8000, 0x44);
-
-               reg_r(gspca_dev, 0x816b, 1);
-               Data = gspca_dev->usb_buf[0];
-               reg_w(gspca_dev, 0x00, 0x816b, Data);
-               write_vector(gspca_dev, Clicksmart510_defaults);
-               break;
-       }
-       return 0;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       reg_w(gspca_dev, 0, 0x8003, 0x00);
-
-       /* switch to video camera mode */
-       reg_w(gspca_dev, 0x00, 0x8000, 0x0004);
-       reg_r(gspca_dev, 0x8000, 1);
-       PDEBUG(D_STREAM, "stop SPCA500 done reg8000: 0x%2x",
-               gspca_dev->usb_buf[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;
-       int i;
-       static __u8 ffd9[] = {0xff, 0xd9};
-
-/* frames are jpeg 4.1.1 without 0xff escape */
-       if (data[0] == 0xff) {
-               if (data[1] != 0x01) {  /* drop packet */
-/*                     gspca_dev->last_packet_type = DISCARD_PACKET; */
-                       return;
-               }
-               gspca_frame_add(gspca_dev, LAST_PACKET,
-                                       ffd9, 2);
-
-               /* put the JPEG header in the new frame */
-               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                       sd->jpeg_hdr, JPEG_HDR_SZ);
-
-               data += SPCA500_OFFSET_DATA;
-               len -= SPCA500_OFFSET_DATA;
-       } else {
-               data += 1;
-               len -= 1;
-       }
-
-       /* add 0x00 after 0xff */
-       i = 0;
-       do {
-               if (data[i] == 0xff) {
-                       gspca_frame_add(gspca_dev, INTER_PACKET,
-                                       data, i + 1);
-                       len -= i;
-                       data += i;
-                       *data = 0x00;
-                       i = 0;
-               }
-               i++;
-       } while (i < len);
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_w(gspca_dev, 0x00, 0x8167,
-                       (__u8) (val - 128));
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_w(gspca_dev, 0x00, 0x8168, val);
-}
-
-static void setcolors(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_w(gspca_dev, 0x00, 0x8169, val);
-}
-
-static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct gspca_dev *gspca_dev =
-               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
-
-       gspca_dev->usb_err = 0;
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               setcolors(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 3);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 63, 1, 31);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 63, 1, 31);
-
-       if (hdl->error) {
-               pr_err("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,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x040a, 0x0300), .driver_info = KodakEZ200},
-       {USB_DEVICE(0x041e, 0x400a), .driver_info = CreativePCCam300},
-       {USB_DEVICE(0x046d, 0x0890), .driver_info = LogitechTraveler},
-       {USB_DEVICE(0x046d, 0x0900), .driver_info = LogitechClickSmart310},
-       {USB_DEVICE(0x046d, 0x0901), .driver_info = LogitechClickSmart510},
-       {USB_DEVICE(0x04a5, 0x300c), .driver_info = BenqDC1016},
-       {USB_DEVICE(0x04fc, 0x7333), .driver_info = PalmPixDC85},
-       {USB_DEVICE(0x055f, 0xc200), .driver_info = MustekGsmart300},
-       {USB_DEVICE(0x055f, 0xc220), .driver_info = Gsmartmini},
-       {USB_DEVICE(0x06bd, 0x0404), .driver_info = AgfaCl20},
-       {USB_DEVICE(0x06be, 0x0800), .driver_info = Optimedia},
-       {USB_DEVICE(0x084d, 0x0003), .driver_info = DLinkDSC350},
-       {USB_DEVICE(0x08ca, 0x0103), .driver_info = AiptekPocketDV},
-       {USB_DEVICE(0x2899, 0x012c), .driver_info = ToptroIndus},
-       {USB_DEVICE(0x8086, 0x0630), .driver_info = IntelPocketPCCamera},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/spca501.c b/drivers/media/video/gspca/spca501.c
deleted file mode 100644 (file)
index 3b7f777..0000000
+++ /dev/null
@@ -1,2054 +0,0 @@
-/*
- * SPCA501 chip based cameras initialization data
- *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "spca501"
-
-#include "gspca.h"
-
-MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
-MODULE_DESCRIPTION("GSPCA/SPCA501 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       unsigned short contrast;
-       __u8 brightness;
-       __u8 colors;
-       __u8 blue_balance;
-       __u8 red_balance;
-
-       char subtype;
-#define Arowana300KCMOSCamera 0
-#define IntelCreateAndShare 1
-#define KodakDVC325 2
-#define MystFromOriUnknownCamera 3
-#define SmileIntlCamera 4
-#define ThreeComHomeConnectLite 5
-#define ViewQuestM318B 6
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {160, 120, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2},
-       {320, 240, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_SPCA501, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-#define SPCA50X_REG_USB 0x2    /* spca505 501 */
-/*
- * Data to initialize a SPCA501. From a capture file provided by Bill Roehl
- * With SPCA501 chip description
- */
-#define CCDSP_SET              /* set CCDSP parameters */
-#define TG_SET                 /* set time generator set */
-#undef DSPWIN_SET              /* set DSP windows parameters */
-#undef ALTER_GAMA      /* Set alternate set to YUV transform coeffs. */
-#define SPCA501_SNAPBIT 0x80
-#define SPCA501_SNAPCTRL 0x10
-/* Frame packet header offsets for the spca501 */
-#define SPCA501_OFFSET_GPIO   1
-#define SPCA501_OFFSET_TYPE   2
-#define SPCA501_OFFSET_TURN3A 3
-#define SPCA501_OFFSET_FRAMSEQ 4
-#define SPCA501_OFFSET_COMPRESS 5
-#define SPCA501_OFFSET_QUANT 6
-#define SPCA501_OFFSET_QUANT2 7
-#define SPCA501_OFFSET_DATA 8
-
-#define SPCA501_PROP_COMP_ENABLE(d) ((d) & 1)
-#define SPCA501_PROP_SNAP(d) ((d) & 0x40)
-#define SPCA501_PROP_SNAP_CTRL(d) ((d) & 0x10)
-#define SPCA501_PROP_COMP_THRESH(d) (((d) & 0x0e) >> 1)
-#define SPCA501_PROP_COMP_QUANT(d) (((d) & 0x70) >> 4)
-
-/* SPCA501 CCDSP control */
-#define SPCA501_REG_CCDSP 0x01
-/* SPCA501 control/status registers */
-#define SPCA501_REG_CTLRL 0x02
-
-/* registers for color correction and YUV transformation */
-#define SPCA501_A11 0x08
-#define SPCA501_A12 0x09
-#define SPCA501_A13 0x0A
-#define SPCA501_A21 0x0B
-#define SPCA501_A22 0x0C
-#define SPCA501_A23 0x0D
-#define SPCA501_A31 0x0E
-#define SPCA501_A32 0x0F
-#define SPCA501_A33 0x10
-
-/* Data for video camera initialization before capturing */
-static const __u16 spca501_open_data[][3] = {
-       /* bmRequest,value,index */
-
-       {0x2, 0x50, 0x00},      /* C/S enable soft reset */
-       {0x2, 0x40, 0x00},      /* C/S disable soft reset */
-       {0x2, 0x02, 0x05},      /* C/S general purpose I/O data */
-       {0x2, 0x03, 0x05},      /* C/S general purpose I/O data */
-
-#ifdef CCDSP_SET
-       {0x1, 0x38, 0x01},      /* CCDSP options */
-       {0x1, 0x05, 0x02}, /* CCDSP Optical black level for user settings */
-       {0x1, 0xC0, 0x03},      /* CCDSP Optical black settings */
-
-       {0x1, 0x67, 0x07},
-       {0x1, 0x63, 0x3f},      /* CCDSP CCD gamma enable */
-       {0x1, 0x03, 0x56},      /* Add gamma correction */
-
-       {0x1, 0xFF, 0x15},      /* CCDSP High luminance for white balance */
-       {0x1, 0x01, 0x16},      /* CCDSP Low luminance for white balance */
-
-/* Color correction and RGB-to-YUV transformation coefficients changing */
-#ifdef ALTER_GAMA
-       {0x0, 0x00, 0x08},      /* A11 */
-       {0x0, 0x00, 0x09},      /* A12 */
-       {0x0, 0x90, 0x0A},      /* A13 */
-       {0x0, 0x12, 0x0B},      /* A21 */
-       {0x0, 0x00, 0x0C},      /* A22 */
-       {0x0, 0x00, 0x0D},      /* A23 */
-       {0x0, 0x00, 0x0E},      /* A31 */
-       {0x0, 0x02, 0x0F},      /* A32 */
-       {0x0, 0x00, 0x10},      /* A33 */
-#else
-       {0x1, 0x2a, 0x08},      /* A11 0x31 */
-       {0x1, 0xf8, 0x09},      /* A12 f8 */
-       {0x1, 0xf8, 0x0A},      /* A13 f8 */
-       {0x1, 0xf8, 0x0B},      /* A21 f8 */
-       {0x1, 0x14, 0x0C},      /* A22 0x14 */
-       {0x1, 0xf8, 0x0D},      /* A23 f8 */
-       {0x1, 0xf8, 0x0E},      /* A31 f8 */
-       {0x1, 0xf8, 0x0F},      /* A32 f8 */
-       {0x1, 0x20, 0x10},      /* A33 0x20 */
-#endif
-       {0x1, 0x00, 0x11},      /* R offset */
-       {0x1, 0x00, 0x12},      /* G offset */
-       {0x1, 0x00, 0x13},      /* B offset */
-       {0x1, 0x00, 0x14},      /* GB offset */
-
-#endif
-
-#ifdef TG_SET
-       /* Time generator manipulations */
-       {0x0, 0xfc, 0x0},       /* Set up high bits of shutter speed */
-       {0x0, 0x01, 0x1},       /* Set up low bits of shutter speed */
-
-       {0x0, 0xe4, 0x04},      /* DCLK*2 clock phase adjustment */
-       {0x0, 0x08, 0x05},      /* ADCK phase adjustment, inv. ext. VB */
-       {0x0, 0x03, 0x06},      /* FR phase adjustment */
-       {0x0, 0x01, 0x07},      /* FCDS phase adjustment */
-       {0x0, 0x39, 0x08},      /* FS phase adjustment */
-       {0x0, 0x88, 0x0a},      /* FH1 phase and delay adjustment */
-       {0x0, 0x03, 0x0f},      /* pixel identification */
-       {0x0, 0x00, 0x11},      /* clock source selection (default) */
-
-       /*VERY strange manipulations with
-        * select DMCLP or OBPX to be ADCLP output (0x0C)
-        * OPB always toggle or not (0x0D) but they allow
-        * us to set up brightness
-        */
-       {0x0, 0x01, 0x0c},
-       {0x0, 0xe0, 0x0d},
-       /* Done */
-#endif
-
-#ifdef DSPWIN_SET
-       {0x1, 0xa0, 0x01},      /* Setting image processing parameters */
-       {0x1, 0x1c, 0x17},      /* Changing Windows positions X1 */
-       {0x1, 0xe2, 0x19},      /* X2 */
-       {0x1, 0x1c, 0x1b},      /* X3 */
-       {0x1, 0xe2, 0x1d},      /* X4 */
-       {0x1, 0x5f, 0x1f},      /* X5 */
-       {0x1, 0x32, 0x20},      /* Y5 */
-       {0x1, 0x01, 0x10},      /* Changing A33 */
-#endif
-
-       {0x2, 0x204a, 0x07},/* Setting video compression & resolution 160x120 */
-       {0x2, 0x94, 0x06},      /* Setting video no compression */
-       {}
-};
-
-/*
-   The SPCAxxx docs from Sunplus document these values
-   in tables, one table per register number.  In the data
-   below, dmRequest is the register number, index is the Addr,
-   and value is a combination of Bit values.
-   Bit  Value (hex)
-   0    01
-   1    02
-   2    04
-   3    08
-   4    10
-   5    20
-   6    40
-   7    80
- */
-
-/* Data for chip initialization (set default values) */
-static const __u16 spca501_init_data[][3] = {
-       /* Set all the values to powerup defaults */
-       /* bmRequest,value,index */
-       {0x0, 0xAA, 0x00},
-       {0x0, 0x02, 0x01},
-       {0x0, 0x01, 0x02},
-       {0x0, 0x02, 0x03},
-       {0x0, 0xCE, 0x04},
-       {0x0, 0x00, 0x05},
-       {0x0, 0x00, 0x06},
-       {0x0, 0x00, 0x07},
-       {0x0, 0x00, 0x08},
-       {0x0, 0x00, 0x09},
-       {0x0, 0x90, 0x0A},
-       {0x0, 0x12, 0x0B},
-       {0x0, 0x00, 0x0C},
-       {0x0, 0x00, 0x0D},
-       {0x0, 0x00, 0x0E},
-       {0x0, 0x02, 0x0F},
-       {0x0, 0x00, 0x10},
-       {0x0, 0x00, 0x11},
-       {0x0, 0x00, 0x12},
-       {0x0, 0x00, 0x13},
-       {0x0, 0x00, 0x14},
-       {0x0, 0x00, 0x15},
-       {0x0, 0x00, 0x16},
-       {0x0, 0x00, 0x17},
-       {0x0, 0x00, 0x18},
-       {0x0, 0x00, 0x19},
-       {0x0, 0x00, 0x1A},
-       {0x0, 0x00, 0x1B},
-       {0x0, 0x00, 0x1C},
-       {0x0, 0x00, 0x1D},
-       {0x0, 0x00, 0x1E},
-       {0x0, 0x00, 0x1F},
-       {0x0, 0x00, 0x20},
-       {0x0, 0x00, 0x21},
-       {0x0, 0x00, 0x22},
-       {0x0, 0x00, 0x23},
-       {0x0, 0x00, 0x24},
-       {0x0, 0x00, 0x25},
-       {0x0, 0x00, 0x26},
-       {0x0, 0x00, 0x27},
-       {0x0, 0x00, 0x28},
-       {0x0, 0x00, 0x29},
-       {0x0, 0x00, 0x2A},
-       {0x0, 0x00, 0x2B},
-       {0x0, 0x00, 0x2C},
-       {0x0, 0x00, 0x2D},
-       {0x0, 0x00, 0x2E},
-       {0x0, 0x00, 0x2F},
-       {0x0, 0x00, 0x30},
-       {0x0, 0x00, 0x31},
-       {0x0, 0x00, 0x32},
-       {0x0, 0x00, 0x33},
-       {0x0, 0x00, 0x34},
-       {0x0, 0x00, 0x35},
-       {0x0, 0x00, 0x36},
-       {0x0, 0x00, 0x37},
-       {0x0, 0x00, 0x38},
-       {0x0, 0x00, 0x39},
-       {0x0, 0x00, 0x3A},
-       {0x0, 0x00, 0x3B},
-       {0x0, 0x00, 0x3C},
-       {0x0, 0x00, 0x3D},
-       {0x0, 0x00, 0x3E},
-       {0x0, 0x00, 0x3F},
-       {0x0, 0x00, 0x40},
-       {0x0, 0x00, 0x41},
-       {0x0, 0x00, 0x42},
-       {0x0, 0x00, 0x43},
-       {0x0, 0x00, 0x44},
-       {0x0, 0x00, 0x45},
-       {0x0, 0x00, 0x46},
-       {0x0, 0x00, 0x47},
-       {0x0, 0x00, 0x48},
-       {0x0, 0x00, 0x49},
-       {0x0, 0x00, 0x4A},
-       {0x0, 0x00, 0x4B},
-       {0x0, 0x00, 0x4C},
-       {0x0, 0x00, 0x4D},
-       {0x0, 0x00, 0x4E},
-       {0x0, 0x00, 0x4F},
-       {0x0, 0x00, 0x50},
-       {0x0, 0x00, 0x51},
-       {0x0, 0x00, 0x52},
-       {0x0, 0x00, 0x53},
-       {0x0, 0x00, 0x54},
-       {0x0, 0x00, 0x55},
-       {0x0, 0x00, 0x56},
-       {0x0, 0x00, 0x57},
-       {0x0, 0x00, 0x58},
-       {0x0, 0x00, 0x59},
-       {0x0, 0x00, 0x5A},
-       {0x0, 0x00, 0x5B},
-       {0x0, 0x00, 0x5C},
-       {0x0, 0x00, 0x5D},
-       {0x0, 0x00, 0x5E},
-       {0x0, 0x00, 0x5F},
-       {0x0, 0x00, 0x60},
-       {0x0, 0x00, 0x61},
-       {0x0, 0x00, 0x62},
-       {0x0, 0x00, 0x63},
-       {0x0, 0x00, 0x64},
-       {0x0, 0x00, 0x65},
-       {0x0, 0x00, 0x66},
-       {0x0, 0x00, 0x67},
-       {0x0, 0x00, 0x68},
-       {0x0, 0x00, 0x69},
-       {0x0, 0x00, 0x6A},
-       {0x0, 0x00, 0x6B},
-       {0x0, 0x00, 0x6C},
-       {0x0, 0x00, 0x6D},
-       {0x0, 0x00, 0x6E},
-       {0x0, 0x00, 0x6F},
-       {0x0, 0x00, 0x70},
-       {0x0, 0x00, 0x71},
-       {0x0, 0x00, 0x72},
-       {0x0, 0x00, 0x73},
-       {0x0, 0x00, 0x74},
-       {0x0, 0x00, 0x75},
-       {0x0, 0x00, 0x76},
-       {0x0, 0x00, 0x77},
-       {0x0, 0x00, 0x78},
-       {0x0, 0x00, 0x79},
-       {0x0, 0x00, 0x7A},
-       {0x0, 0x00, 0x7B},
-       {0x0, 0x00, 0x7C},
-       {0x0, 0x00, 0x7D},
-       {0x0, 0x00, 0x7E},
-       {0x0, 0x00, 0x7F},
-       {0x0, 0x00, 0x80},
-       {0x0, 0x00, 0x81},
-       {0x0, 0x00, 0x82},
-       {0x0, 0x00, 0x83},
-       {0x0, 0x00, 0x84},
-       {0x0, 0x00, 0x85},
-       {0x0, 0x00, 0x86},
-       {0x0, 0x00, 0x87},
-       {0x0, 0x00, 0x88},
-       {0x0, 0x00, 0x89},
-       {0x0, 0x00, 0x8A},
-       {0x0, 0x00, 0x8B},
-       {0x0, 0x00, 0x8C},
-       {0x0, 0x00, 0x8D},
-       {0x0, 0x00, 0x8E},
-       {0x0, 0x00, 0x8F},
-       {0x0, 0x00, 0x90},
-       {0x0, 0x00, 0x91},
-       {0x0, 0x00, 0x92},
-       {0x0, 0x00, 0x93},
-       {0x0, 0x00, 0x94},
-       {0x0, 0x00, 0x95},
-       {0x0, 0x00, 0x96},
-       {0x0, 0x00, 0x97},
-       {0x0, 0x00, 0x98},
-       {0x0, 0x00, 0x99},
-       {0x0, 0x00, 0x9A},
-       {0x0, 0x00, 0x9B},
-       {0x0, 0x00, 0x9C},
-       {0x0, 0x00, 0x9D},
-       {0x0, 0x00, 0x9E},
-       {0x0, 0x00, 0x9F},
-       {0x0, 0x00, 0xA0},
-       {0x0, 0x00, 0xA1},
-       {0x0, 0x00, 0xA2},
-       {0x0, 0x00, 0xA3},
-       {0x0, 0x00, 0xA4},
-       {0x0, 0x00, 0xA5},
-       {0x0, 0x00, 0xA6},
-       {0x0, 0x00, 0xA7},
-       {0x0, 0x00, 0xA8},
-       {0x0, 0x00, 0xA9},
-       {0x0, 0x00, 0xAA},
-       {0x0, 0x00, 0xAB},
-       {0x0, 0x00, 0xAC},
-       {0x0, 0x00, 0xAD},
-       {0x0, 0x00, 0xAE},
-       {0x0, 0x00, 0xAF},
-       {0x0, 0x00, 0xB0},
-       {0x0, 0x00, 0xB1},
-       {0x0, 0x00, 0xB2},
-       {0x0, 0x00, 0xB3},
-       {0x0, 0x00, 0xB4},
-       {0x0, 0x00, 0xB5},
-       {0x0, 0x00, 0xB6},
-       {0x0, 0x00, 0xB7},
-       {0x0, 0x00, 0xB8},
-       {0x0, 0x00, 0xB9},
-       {0x0, 0x00, 0xBA},
-       {0x0, 0x00, 0xBB},
-       {0x0, 0x00, 0xBC},
-       {0x0, 0x00, 0xBD},
-       {0x0, 0x00, 0xBE},
-       {0x0, 0x00, 0xBF},
-       {0x0, 0x00, 0xC0},
-       {0x0, 0x00, 0xC1},
-       {0x0, 0x00, 0xC2},
-       {0x0, 0x00, 0xC3},
-       {0x0, 0x00, 0xC4},
-       {0x0, 0x00, 0xC5},
-       {0x0, 0x00, 0xC6},
-       {0x0, 0x00, 0xC7},
-       {0x0, 0x00, 0xC8},
-       {0x0, 0x00, 0xC9},
-       {0x0, 0x00, 0xCA},
-       {0x0, 0x00, 0xCB},
-       {0x0, 0x00, 0xCC},
-       {0x1, 0xF4, 0x00},
-       {0x1, 0x38, 0x01},
-       {0x1, 0x40, 0x02},
-       {0x1, 0x0A, 0x03},
-       {0x1, 0x40, 0x04},
-       {0x1, 0x40, 0x05},
-       {0x1, 0x40, 0x06},
-       {0x1, 0x67, 0x07},
-       {0x1, 0x31, 0x08},
-       {0x1, 0x00, 0x09},
-       {0x1, 0x00, 0x0A},
-       {0x1, 0x00, 0x0B},
-       {0x1, 0x14, 0x0C},
-       {0x1, 0x00, 0x0D},
-       {0x1, 0x00, 0x0E},
-       {0x1, 0x00, 0x0F},
-       {0x1, 0x1E, 0x10},
-       {0x1, 0x00, 0x11},
-       {0x1, 0x00, 0x12},
-       {0x1, 0x00, 0x13},
-       {0x1, 0x00, 0x14},
-       {0x1, 0xFF, 0x15},
-       {0x1, 0x01, 0x16},
-       {0x1, 0x32, 0x17},
-       {0x1, 0x23, 0x18},
-       {0x1, 0xCE, 0x19},
-       {0x1, 0x23, 0x1A},
-       {0x1, 0x32, 0x1B},
-       {0x1, 0x8D, 0x1C},
-       {0x1, 0xCE, 0x1D},
-       {0x1, 0x8D, 0x1E},
-       {0x1, 0x00, 0x1F},
-       {0x1, 0x00, 0x20},
-       {0x1, 0xFF, 0x3E},
-       {0x1, 0x02, 0x3F},
-       {0x1, 0x00, 0x40},
-       {0x1, 0x00, 0x41},
-       {0x1, 0x00, 0x42},
-       {0x1, 0x00, 0x43},
-       {0x1, 0x00, 0x44},
-       {0x1, 0x00, 0x45},
-       {0x1, 0x00, 0x46},
-       {0x1, 0x00, 0x47},
-       {0x1, 0x00, 0x48},
-       {0x1, 0x00, 0x49},
-       {0x1, 0x00, 0x4A},
-       {0x1, 0x00, 0x4B},
-       {0x1, 0x00, 0x4C},
-       {0x1, 0x00, 0x4D},
-       {0x1, 0x00, 0x4E},
-       {0x1, 0x00, 0x4F},
-       {0x1, 0x00, 0x50},
-       {0x1, 0x00, 0x51},
-       {0x1, 0x00, 0x52},
-       {0x1, 0x00, 0x53},
-       {0x1, 0x00, 0x54},
-       {0x1, 0x00, 0x55},
-       {0x1, 0x00, 0x56},
-       {0x1, 0x00, 0x57},
-       {0x1, 0x00, 0x58},
-       {0x1, 0x00, 0x59},
-       {0x1, 0x00, 0x5A},
-       {0x2, 0x03, 0x00},
-       {0x2, 0x00, 0x01},
-       {0x2, 0x00, 0x05},
-       {0x2, 0x00, 0x06},
-       {0x2, 0x00, 0x07},
-       {0x2, 0x00, 0x10},
-       {0x2, 0x00, 0x11},
-       /* Strange - looks like the 501 driver doesn't do anything
-        * at insert time except read the EEPROM
-        */
-       {}
-};
-
-/* Data for video camera init before capture.
- * Capture and decoding by Colin Peart.
- * This is is for the 3com HomeConnect Lite which is spca501a based.
- */
-static const __u16 spca501_3com_open_data[][3] = {
-       /* bmRequest,value,index */
-       {0x2, 0x0050, 0x0000},  /* C/S Enable TG soft reset, timing mode=010 */
-       {0x2, 0x0043, 0x0000},  /* C/S Disable TG soft reset, timing mode=010 */
-       {0x2, 0x0002, 0x0005},  /* C/S GPIO */
-       {0x2, 0x0003, 0x0005},  /* C/S GPIO */
-
-#ifdef CCDSP_SET
-       {0x1, 0x0020, 0x0001},  /* CCDSP Options */
-
-       {0x1, 0x0020, 0x0002},  /* CCDSP Black Level */
-       {0x1, 0x006e, 0x0007},  /* CCDSP Gamma options */
-       {0x1, 0x0090, 0x0015},  /* CCDSP Luminance Low */
-       {0x1, 0x00ff, 0x0016},  /* CCDSP Luminance High */
-       {0x1, 0x0003, 0x003F},  /* CCDSP Gamma correction toggle */
-
-#ifdef ALTER_GAMMA
-       {0x1, 0x0010, 0x0008},  /* CCDSP YUV A11 */
-       {0x1, 0x0000, 0x0009},  /* CCDSP YUV A12 */
-       {0x1, 0x0000, 0x000a},  /* CCDSP YUV A13 */
-       {0x1, 0x0000, 0x000b},  /* CCDSP YUV A21 */
-       {0x1, 0x0010, 0x000c},  /* CCDSP YUV A22 */
-       {0x1, 0x0000, 0x000d},  /* CCDSP YUV A23 */
-       {0x1, 0x0000, 0x000e},  /* CCDSP YUV A31 */
-       {0x1, 0x0000, 0x000f},  /* CCDSP YUV A32 */
-       {0x1, 0x0010, 0x0010},  /* CCDSP YUV A33 */
-       {0x1, 0x0000, 0x0011},  /* CCDSP R Offset */
-       {0x1, 0x0000, 0x0012},  /* CCDSP G Offset */
-       {0x1, 0x0001, 0x0013},  /* CCDSP B Offset */
-       {0x1, 0x0001, 0x0014},  /* CCDSP BG Offset */
-       {0x1, 0x003f, 0x00C1},  /* CCDSP Gamma Correction Enable */
-#endif
-#endif
-
-#ifdef TG_SET
-       {0x0, 0x00fc, 0x0000},  /* TG Shutter Speed High Bits */
-       {0x0, 0x0000, 0x0001},  /* TG Shutter Speed Low Bits */
-       {0x0, 0x00e4, 0x0004},  /* TG DCLK*2 Adjust */
-       {0x0, 0x0008, 0x0005},  /* TG ADCK Adjust */
-       {0x0, 0x0003, 0x0006},  /* TG FR Phase Adjust */
-       {0x0, 0x0001, 0x0007},  /* TG FCDS Phase Adjust */
-       {0x0, 0x0039, 0x0008},  /* TG FS Phase Adjust */
-       {0x0, 0x0088, 0x000a},  /* TG MH1 */
-       {0x0, 0x0003, 0x000f},  /* TG Pixel ID */
-
-       /* Like below, unexplained toglleing */
-       {0x0, 0x0080, 0x000c},
-       {0x0, 0x0000, 0x000d},
-       {0x0, 0x0080, 0x000c},
-       {0x0, 0x0004, 0x000d},
-       {0x0, 0x0000, 0x000c},
-       {0x0, 0x0000, 0x000d},
-       {0x0, 0x0040, 0x000c},
-       {0x0, 0x0017, 0x000d},
-       {0x0, 0x00c0, 0x000c},
-       {0x0, 0x0000, 0x000d},
-       {0x0, 0x0080, 0x000c},
-       {0x0, 0x0006, 0x000d},
-       {0x0, 0x0080, 0x000c},
-       {0x0, 0x0004, 0x000d},
-       {0x0, 0x0002, 0x0003},
-#endif
-
-#ifdef DSPWIN_SET
-       {0x1, 0x001c, 0x0017},  /* CCDSP W1 Start X */
-       {0x1, 0x00e2, 0x0019},  /* CCDSP W2 Start X */
-       {0x1, 0x001c, 0x001b},  /* CCDSP W3 Start X */
-       {0x1, 0x00e2, 0x001d},  /* CCDSP W4 Start X */
-       {0x1, 0x00aa, 0x001f},  /* CCDSP W5 Start X */
-       {0x1, 0x0070, 0x0020},  /* CCDSP W5 Start Y */
-#endif
-       {0x0, 0x0001, 0x0010},  /* TG Start Clock */
-
-/*     {0x2, 0x006a, 0x0001},   * C/S Enable ISOSYNCH Packet Engine */
-       {0x2, 0x0068, 0x0001},  /* C/S Diable ISOSYNCH Packet Engine */
-       {0x2, 0x0000, 0x0005},
-       {0x2, 0x0043, 0x0000},  /* C/S Set Timing Mode, Disable TG soft reset */
-       {0x2, 0x0043, 0x0000},  /* C/S Set Timing Mode, Disable TG soft reset */
-       {0x2, 0x0002, 0x0005},  /* C/S GPIO */
-       {0x2, 0x0003, 0x0005},  /* C/S GPIO */
-
-       {0x2, 0x006a, 0x0001},  /* C/S Enable ISOSYNCH Packet Engine */
-       {}
-};
-
-/*
- * Data used to initialize a SPCA501C with HV7131B sensor.
- * From a capture file taken with USBSnoop v 1.5
- * I have a "SPCA501C pc camera chipset" manual by sunplus, but some
- * of the value meanings are obscure or simply "reserved".
- * to do list:
- * 1) Understand what every value means
- * 2) Understand why some values seem to appear more than once
- * 3) Write a small comment for each line of the following arrays.
- */
-static const __u16 spca501c_arowana_open_data[][3] = {
-       /* bmRequest,value,index */
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x01, 0x0006, 0x0011},
-       {0x01, 0x00ff, 0x0012},
-       {0x01, 0x0014, 0x0013},
-       {0x01, 0x0000, 0x0014},
-       {0x01, 0x0042, 0x0051},
-       {0x01, 0x0040, 0x0052},
-       {0x01, 0x0051, 0x0053},
-       {0x01, 0x0040, 0x0054},
-       {0x01, 0x0000, 0x0055},
-       {0x00, 0x0025, 0x0000},
-       {0x00, 0x0026, 0x0000},
-       {0x00, 0x0001, 0x0000},
-       {0x00, 0x0027, 0x0000},
-       {0x00, 0x008a, 0x0000},
-       {}
-};
-
-static const __u16 spca501c_arowana_init_data[][3] = {
-       /* bmRequest,value,index */
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x01, 0x0006, 0x0011},
-       {0x01, 0x00ff, 0x0012},
-       {0x01, 0x0014, 0x0013},
-       {0x01, 0x0000, 0x0014},
-       {0x01, 0x0042, 0x0051},
-       {0x01, 0x0040, 0x0052},
-       {0x01, 0x0051, 0x0053},
-       {0x01, 0x0040, 0x0054},
-       {0x01, 0x0000, 0x0055},
-       {0x00, 0x0025, 0x0000},
-       {0x00, 0x0026, 0x0000},
-       {0x00, 0x0001, 0x0000},
-       {0x00, 0x0027, 0x0000},
-       {0x00, 0x008a, 0x0000},
-       {0x02, 0x0000, 0x0005},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0x2000, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x05, 0x0015, 0x0001},
-       {0x05, 0x00ea, 0x0000},
-       {0x05, 0x0021, 0x0001},
-       {0x05, 0x00d2, 0x0000},
-       {0x05, 0x0023, 0x0001},
-       {0x05, 0x0003, 0x0000},
-       {0x05, 0x0030, 0x0001},
-       {0x05, 0x002b, 0x0000},
-       {0x05, 0x0031, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0032, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0033, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0034, 0x0001},
-       {0x05, 0x0002, 0x0000},
-       {0x05, 0x0050, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0051, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0052, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0054, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x00, 0x0000, 0x0001},
-       {0x00, 0x0000, 0x0002},
-       {0x00, 0x000c, 0x0003},
-       {0x00, 0x0000, 0x0004},
-       {0x00, 0x0090, 0x0005},
-       {0x00, 0x0000, 0x0006},
-       {0x00, 0x0040, 0x0007},
-       {0x00, 0x00c0, 0x0008},
-       {0x00, 0x004a, 0x0009},
-       {0x00, 0x0000, 0x000a},
-       {0x00, 0x0000, 0x000b},
-       {0x00, 0x0001, 0x000c},
-       {0x00, 0x0001, 0x000d},
-       {0x00, 0x0000, 0x000e},
-       {0x00, 0x0002, 0x000f},
-       {0x00, 0x0001, 0x0010},
-       {0x00, 0x0000, 0x0011},
-       {0x00, 0x0000, 0x0012},
-       {0x00, 0x0002, 0x0020},
-       {0x00, 0x0080, 0x0021},
-       {0x00, 0x0001, 0x0022},
-       {0x00, 0x00e0, 0x0023},
-       {0x00, 0x0000, 0x0024},
-       {0x00, 0x00d5, 0x0025},
-       {0x00, 0x0000, 0x0026},
-       {0x00, 0x000b, 0x0027},
-       {0x00, 0x0000, 0x0046},
-       {0x00, 0x0000, 0x0047},
-       {0x00, 0x0000, 0x0048},
-       {0x00, 0x0000, 0x0049},
-       {0x00, 0x0008, 0x004a},
-       {0xff, 0x0000, 0x00d0},
-       {0xff, 0x00d8, 0x00d1},
-       {0xff, 0x0000, 0x00d4},
-       {0xff, 0x0000, 0x00d5},
-       {0x01, 0x00a6, 0x0000},
-       {0x01, 0x0028, 0x0001},
-       {0x01, 0x0000, 0x0002},
-       {0x01, 0x000a, 0x0003},
-       {0x01, 0x0040, 0x0004},
-       {0x01, 0x0066, 0x0007},
-       {0x01, 0x0011, 0x0008},
-       {0x01, 0x0032, 0x0009},
-       {0x01, 0x00fd, 0x000a},
-       {0x01, 0x0038, 0x000b},
-       {0x01, 0x00d1, 0x000c},
-       {0x01, 0x00f7, 0x000d},
-       {0x01, 0x00ed, 0x000e},
-       {0x01, 0x00d8, 0x000f},
-       {0x01, 0x0038, 0x0010},
-       {0x01, 0x00ff, 0x0015},
-       {0x01, 0x0001, 0x0016},
-       {0x01, 0x0032, 0x0017},
-       {0x01, 0x0023, 0x0018},
-       {0x01, 0x00ce, 0x0019},
-       {0x01, 0x0023, 0x001a},
-       {0x01, 0x0032, 0x001b},
-       {0x01, 0x008d, 0x001c},
-       {0x01, 0x00ce, 0x001d},
-       {0x01, 0x008d, 0x001e},
-       {0x01, 0x0000, 0x001f},
-       {0x01, 0x0000, 0x0020},
-       {0x01, 0x00ff, 0x003e},
-       {0x01, 0x0003, 0x003f},
-       {0x01, 0x0000, 0x0040},
-       {0x01, 0x0035, 0x0041},
-       {0x01, 0x0053, 0x0042},
-       {0x01, 0x0069, 0x0043},
-       {0x01, 0x007c, 0x0044},
-       {0x01, 0x008c, 0x0045},
-       {0x01, 0x009a, 0x0046},
-       {0x01, 0x00a8, 0x0047},
-       {0x01, 0x00b4, 0x0048},
-       {0x01, 0x00bf, 0x0049},
-       {0x01, 0x00ca, 0x004a},
-       {0x01, 0x00d4, 0x004b},
-       {0x01, 0x00dd, 0x004c},
-       {0x01, 0x00e7, 0x004d},
-       {0x01, 0x00ef, 0x004e},
-       {0x01, 0x00f8, 0x004f},
-       {0x01, 0x00ff, 0x0050},
-       {0x01, 0x0001, 0x0056},
-       {0x01, 0x0060, 0x0057},
-       {0x01, 0x0040, 0x0058},
-       {0x01, 0x0011, 0x0059},
-       {0x01, 0x0001, 0x005a},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0x0015, 0x0006},
-       {0x02, 0x100a, 0x0007},
-       {0x02, 0xa048, 0x0000},
-       {0x02, 0xc002, 0x0001},
-       {0x02, 0x000f, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x05, 0x0025, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0026, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x05, 0x0027, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0001, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0021, 0x0001},
-       {0x05, 0x00d2, 0x0000},
-       {0x05, 0x0020, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x00, 0x0090, 0x0005},
-       {0x01, 0x00a6, 0x0000},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0x2000, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x05, 0x0015, 0x0001},
-       {0x05, 0x00ea, 0x0000},
-       {0x05, 0x0021, 0x0001},
-       {0x05, 0x00d2, 0x0000},
-       {0x05, 0x0023, 0x0001},
-       {0x05, 0x0003, 0x0000},
-       {0x05, 0x0030, 0x0001},
-       {0x05, 0x002b, 0x0000},
-       {0x05, 0x0031, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0032, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0033, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0034, 0x0001},
-       {0x05, 0x0002, 0x0000},
-       {0x05, 0x0050, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0051, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0052, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0054, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x00, 0x0000, 0x0001},
-       {0x00, 0x0000, 0x0002},
-       {0x00, 0x000c, 0x0003},
-       {0x00, 0x0000, 0x0004},
-       {0x00, 0x0090, 0x0005},
-       {0x00, 0x0000, 0x0006},
-       {0x00, 0x0040, 0x0007},
-       {0x00, 0x00c0, 0x0008},
-       {0x00, 0x004a, 0x0009},
-       {0x00, 0x0000, 0x000a},
-       {0x00, 0x0000, 0x000b},
-       {0x00, 0x0001, 0x000c},
-       {0x00, 0x0001, 0x000d},
-       {0x00, 0x0000, 0x000e},
-       {0x00, 0x0002, 0x000f},
-       {0x00, 0x0001, 0x0010},
-       {0x00, 0x0000, 0x0011},
-       {0x00, 0x0000, 0x0012},
-       {0x00, 0x0002, 0x0020},
-       {0x00, 0x0080, 0x0021},
-       {0x00, 0x0001, 0x0022},
-       {0x00, 0x00e0, 0x0023},
-       {0x00, 0x0000, 0x0024},
-       {0x00, 0x00d5, 0x0025},
-       {0x00, 0x0000, 0x0026},
-       {0x00, 0x000b, 0x0027},
-       {0x00, 0x0000, 0x0046},
-       {0x00, 0x0000, 0x0047},
-       {0x00, 0x0000, 0x0048},
-       {0x00, 0x0000, 0x0049},
-       {0x00, 0x0008, 0x004a},
-       {0xff, 0x0000, 0x00d0},
-       {0xff, 0x00d8, 0x00d1},
-       {0xff, 0x0000, 0x00d4},
-       {0xff, 0x0000, 0x00d5},
-       {0x01, 0x00a6, 0x0000},
-       {0x01, 0x0028, 0x0001},
-       {0x01, 0x0000, 0x0002},
-       {0x01, 0x000a, 0x0003},
-       {0x01, 0x0040, 0x0004},
-       {0x01, 0x0066, 0x0007},
-       {0x01, 0x0011, 0x0008},
-       {0x01, 0x0032, 0x0009},
-       {0x01, 0x00fd, 0x000a},
-       {0x01, 0x0038, 0x000b},
-       {0x01, 0x00d1, 0x000c},
-       {0x01, 0x00f7, 0x000d},
-       {0x01, 0x00ed, 0x000e},
-       {0x01, 0x00d8, 0x000f},
-       {0x01, 0x0038, 0x0010},
-       {0x01, 0x00ff, 0x0015},
-       {0x01, 0x0001, 0x0016},
-       {0x01, 0x0032, 0x0017},
-       {0x01, 0x0023, 0x0018},
-       {0x01, 0x00ce, 0x0019},
-       {0x01, 0x0023, 0x001a},
-       {0x01, 0x0032, 0x001b},
-       {0x01, 0x008d, 0x001c},
-       {0x01, 0x00ce, 0x001d},
-       {0x01, 0x008d, 0x001e},
-       {0x01, 0x0000, 0x001f},
-       {0x01, 0x0000, 0x0020},
-       {0x01, 0x00ff, 0x003e},
-       {0x01, 0x0003, 0x003f},
-       {0x01, 0x0000, 0x0040},
-       {0x01, 0x0035, 0x0041},
-       {0x01, 0x0053, 0x0042},
-       {0x01, 0x0069, 0x0043},
-       {0x01, 0x007c, 0x0044},
-       {0x01, 0x008c, 0x0045},
-       {0x01, 0x009a, 0x0046},
-       {0x01, 0x00a8, 0x0047},
-       {0x01, 0x00b4, 0x0048},
-       {0x01, 0x00bf, 0x0049},
-       {0x01, 0x00ca, 0x004a},
-       {0x01, 0x00d4, 0x004b},
-       {0x01, 0x00dd, 0x004c},
-       {0x01, 0x00e7, 0x004d},
-       {0x01, 0x00ef, 0x004e},
-       {0x01, 0x00f8, 0x004f},
-       {0x01, 0x00ff, 0x0050},
-       {0x01, 0x0001, 0x0056},
-       {0x01, 0x0060, 0x0057},
-       {0x01, 0x0040, 0x0058},
-       {0x01, 0x0011, 0x0059},
-       {0x01, 0x0001, 0x005a},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0x0015, 0x0006},
-       {0x02, 0x100a, 0x0007},
-       {0x02, 0xa048, 0x0000},
-       {0x02, 0xc002, 0x0001},
-       {0x02, 0x000f, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x05, 0x0025, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0026, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x05, 0x0027, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0001, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0021, 0x0001},
-       {0x05, 0x00d2, 0x0000},
-       {0x05, 0x0020, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x00, 0x0090, 0x0005},
-       {0x01, 0x00a6, 0x0000},
-       {0x01, 0x0003, 0x003f},
-       {0x01, 0x0001, 0x0056},
-       {0x01, 0x0011, 0x0008},
-       {0x01, 0x0032, 0x0009},
-       {0x01, 0xfffd, 0x000a},
-       {0x01, 0x0023, 0x000b},
-       {0x01, 0xffea, 0x000c},
-       {0x01, 0xfff4, 0x000d},
-       {0x01, 0xfffc, 0x000e},
-       {0x01, 0xffe3, 0x000f},
-       {0x01, 0x001f, 0x0010},
-       {0x01, 0x00a8, 0x0001},
-       {0x01, 0x0067, 0x0007},
-       {0x01, 0x0032, 0x0017},
-       {0x01, 0x0023, 0x0018},
-       {0x01, 0x00ce, 0x0019},
-       {0x01, 0x0023, 0x001a},
-       {0x01, 0x0032, 0x001b},
-       {0x01, 0x008d, 0x001c},
-       {0x01, 0x00ce, 0x001d},
-       {0x01, 0x008d, 0x001e},
-       {0x01, 0x00c8, 0x0015},
-       {0x01, 0x0032, 0x0016},
-       {0x01, 0x0000, 0x0011},
-       {0x01, 0x0000, 0x0012},
-       {0x01, 0x0000, 0x0013},
-       {0x01, 0x000a, 0x0003},
-       {0x02, 0xc002, 0x0001},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0xc000, 0x0001},
-       {0x02, 0x0000, 0x0005},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0x2000, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x05, 0x0015, 0x0001},
-       {0x05, 0x00ea, 0x0000},
-       {0x05, 0x0021, 0x0001},
-       {0x05, 0x00d2, 0x0000},
-       {0x05, 0x0023, 0x0001},
-       {0x05, 0x0003, 0x0000},
-       {0x05, 0x0030, 0x0001},
-       {0x05, 0x002b, 0x0000},
-       {0x05, 0x0031, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0032, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0033, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0034, 0x0001},
-       {0x05, 0x0002, 0x0000},
-       {0x05, 0x0050, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0051, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0052, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0054, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x00, 0x0000, 0x0001},
-       {0x00, 0x0000, 0x0002},
-       {0x00, 0x000c, 0x0003},
-       {0x00, 0x0000, 0x0004},
-       {0x00, 0x0090, 0x0005},
-       {0x00, 0x0000, 0x0006},
-       {0x00, 0x0040, 0x0007},
-       {0x00, 0x00c0, 0x0008},
-       {0x00, 0x004a, 0x0009},
-       {0x00, 0x0000, 0x000a},
-       {0x00, 0x0000, 0x000b},
-       {0x00, 0x0001, 0x000c},
-       {0x00, 0x0001, 0x000d},
-       {0x00, 0x0000, 0x000e},
-       {0x00, 0x0002, 0x000f},
-       {0x00, 0x0001, 0x0010},
-       {0x00, 0x0000, 0x0011},
-       {0x00, 0x0000, 0x0012},
-       {0x00, 0x0002, 0x0020},
-       {0x00, 0x0080, 0x0021},
-       {0x00, 0x0001, 0x0022},
-       {0x00, 0x00e0, 0x0023},
-       {0x00, 0x0000, 0x0024},
-       {0x00, 0x00d5, 0x0025},
-       {0x00, 0x0000, 0x0026},
-       {0x00, 0x000b, 0x0027},
-       {0x00, 0x0000, 0x0046},
-       {0x00, 0x0000, 0x0047},
-       {0x00, 0x0000, 0x0048},
-       {0x00, 0x0000, 0x0049},
-       {0x00, 0x0008, 0x004a},
-       {0xff, 0x0000, 0x00d0},
-       {0xff, 0x00d8, 0x00d1},
-       {0xff, 0x0000, 0x00d4},
-       {0xff, 0x0000, 0x00d5},
-       {0x01, 0x00a6, 0x0000},
-       {0x01, 0x0028, 0x0001},
-       {0x01, 0x0000, 0x0002},
-       {0x01, 0x000a, 0x0003},
-       {0x01, 0x0040, 0x0004},
-       {0x01, 0x0066, 0x0007},
-       {0x01, 0x0011, 0x0008},
-       {0x01, 0x0032, 0x0009},
-       {0x01, 0x00fd, 0x000a},
-       {0x01, 0x0038, 0x000b},
-       {0x01, 0x00d1, 0x000c},
-       {0x01, 0x00f7, 0x000d},
-       {0x01, 0x00ed, 0x000e},
-       {0x01, 0x00d8, 0x000f},
-       {0x01, 0x0038, 0x0010},
-       {0x01, 0x00ff, 0x0015},
-       {0x01, 0x0001, 0x0016},
-       {0x01, 0x0032, 0x0017},
-       {0x01, 0x0023, 0x0018},
-       {0x01, 0x00ce, 0x0019},
-       {0x01, 0x0023, 0x001a},
-       {0x01, 0x0032, 0x001b},
-       {0x01, 0x008d, 0x001c},
-       {0x01, 0x00ce, 0x001d},
-       {0x01, 0x008d, 0x001e},
-       {0x01, 0x0000, 0x001f},
-       {0x01, 0x0000, 0x0020},
-       {0x01, 0x00ff, 0x003e},
-       {0x01, 0x0003, 0x003f},
-       {0x01, 0x0000, 0x0040},
-       {0x01, 0x0035, 0x0041},
-       {0x01, 0x0053, 0x0042},
-       {0x01, 0x0069, 0x0043},
-       {0x01, 0x007c, 0x0044},
-       {0x01, 0x008c, 0x0045},
-       {0x01, 0x009a, 0x0046},
-       {0x01, 0x00a8, 0x0047},
-       {0x01, 0x00b4, 0x0048},
-       {0x01, 0x00bf, 0x0049},
-       {0x01, 0x00ca, 0x004a},
-       {0x01, 0x00d4, 0x004b},
-       {0x01, 0x00dd, 0x004c},
-       {0x01, 0x00e7, 0x004d},
-       {0x01, 0x00ef, 0x004e},
-       {0x01, 0x00f8, 0x004f},
-       {0x01, 0x00ff, 0x0050},
-       {0x01, 0x0001, 0x0056},
-       {0x01, 0x0060, 0x0057},
-       {0x01, 0x0040, 0x0058},
-       {0x01, 0x0011, 0x0059},
-       {0x01, 0x0001, 0x005a},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0x0015, 0x0006},
-       {0x02, 0x100a, 0x0007},
-       {0x02, 0xa048, 0x0000},
-       {0x02, 0xc002, 0x0001},
-       {0x02, 0x000f, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x05, 0x0025, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0026, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x05, 0x0027, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0001, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0021, 0x0001},
-       {0x05, 0x00d2, 0x0000},
-       {0x05, 0x0020, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x00, 0x0090, 0x0005},
-       {0x01, 0x00a6, 0x0000},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0x2000, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x05, 0x0015, 0x0001},
-       {0x05, 0x00ea, 0x0000},
-       {0x05, 0x0021, 0x0001},
-       {0x05, 0x00d2, 0x0000},
-       {0x05, 0x0023, 0x0001},
-       {0x05, 0x0003, 0x0000},
-       {0x05, 0x0030, 0x0001},
-       {0x05, 0x002b, 0x0000},
-       {0x05, 0x0031, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0032, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0033, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0034, 0x0001},
-       {0x05, 0x0002, 0x0000},
-       {0x05, 0x0050, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0051, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0052, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0054, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x00, 0x0000, 0x0001},
-       {0x00, 0x0000, 0x0002},
-       {0x00, 0x000c, 0x0003},
-       {0x00, 0x0000, 0x0004},
-       {0x00, 0x0090, 0x0005},
-       {0x00, 0x0000, 0x0006},
-       {0x00, 0x0040, 0x0007},
-       {0x00, 0x00c0, 0x0008},
-       {0x00, 0x004a, 0x0009},
-       {0x00, 0x0000, 0x000a},
-       {0x00, 0x0000, 0x000b},
-       {0x00, 0x0001, 0x000c},
-       {0x00, 0x0001, 0x000d},
-       {0x00, 0x0000, 0x000e},
-       {0x00, 0x0002, 0x000f},
-       {0x00, 0x0001, 0x0010},
-       {0x00, 0x0000, 0x0011},
-       {0x00, 0x0000, 0x0012},
-       {0x00, 0x0002, 0x0020},
-       {0x00, 0x0080, 0x0021},
-       {0x00, 0x0001, 0x0022},
-       {0x00, 0x00e0, 0x0023},
-       {0x00, 0x0000, 0x0024},
-       {0x00, 0x00d5, 0x0025},
-       {0x00, 0x0000, 0x0026},
-       {0x00, 0x000b, 0x0027},
-       {0x00, 0x0000, 0x0046},
-       {0x00, 0x0000, 0x0047},
-       {0x00, 0x0000, 0x0048},
-       {0x00, 0x0000, 0x0049},
-       {0x00, 0x0008, 0x004a},
-       {0xff, 0x0000, 0x00d0},
-       {0xff, 0x00d8, 0x00d1},
-       {0xff, 0x0000, 0x00d4},
-       {0xff, 0x0000, 0x00d5},
-       {0x01, 0x00a6, 0x0000},
-       {0x01, 0x0028, 0x0001},
-       {0x01, 0x0000, 0x0002},
-       {0x01, 0x000a, 0x0003},
-       {0x01, 0x0040, 0x0004},
-       {0x01, 0x0066, 0x0007},
-       {0x01, 0x0011, 0x0008},
-       {0x01, 0x0032, 0x0009},
-       {0x01, 0x00fd, 0x000a},
-       {0x01, 0x0038, 0x000b},
-       {0x01, 0x00d1, 0x000c},
-       {0x01, 0x00f7, 0x000d},
-       {0x01, 0x00ed, 0x000e},
-       {0x01, 0x00d8, 0x000f},
-       {0x01, 0x0038, 0x0010},
-       {0x01, 0x00ff, 0x0015},
-       {0x01, 0x0001, 0x0016},
-       {0x01, 0x0032, 0x0017},
-       {0x01, 0x0023, 0x0018},
-       {0x01, 0x00ce, 0x0019},
-       {0x01, 0x0023, 0x001a},
-       {0x01, 0x0032, 0x001b},
-       {0x01, 0x008d, 0x001c},
-       {0x01, 0x00ce, 0x001d},
-       {0x01, 0x008d, 0x001e},
-       {0x01, 0x0000, 0x001f},
-       {0x01, 0x0000, 0x0020},
-       {0x01, 0x00ff, 0x003e},
-       {0x01, 0x0003, 0x003f},
-       {0x01, 0x0000, 0x0040},
-       {0x01, 0x0035, 0x0041},
-       {0x01, 0x0053, 0x0042},
-       {0x01, 0x0069, 0x0043},
-       {0x01, 0x007c, 0x0044},
-       {0x01, 0x008c, 0x0045},
-       {0x01, 0x009a, 0x0046},
-       {0x01, 0x00a8, 0x0047},
-       {0x01, 0x00b4, 0x0048},
-       {0x01, 0x00bf, 0x0049},
-       {0x01, 0x00ca, 0x004a},
-       {0x01, 0x00d4, 0x004b},
-       {0x01, 0x00dd, 0x004c},
-       {0x01, 0x00e7, 0x004d},
-       {0x01, 0x00ef, 0x004e},
-       {0x01, 0x00f8, 0x004f},
-       {0x01, 0x00ff, 0x0050},
-       {0x01, 0x0001, 0x0056},
-       {0x01, 0x0060, 0x0057},
-       {0x01, 0x0040, 0x0058},
-       {0x01, 0x0011, 0x0059},
-       {0x01, 0x0001, 0x005a},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0x0015, 0x0006},
-       {0x02, 0x100a, 0x0007},
-       {0x02, 0xa048, 0x0000},
-       {0x02, 0xc002, 0x0001},
-       {0x02, 0x000f, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x05, 0x0025, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0026, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x05, 0x0027, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0001, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0021, 0x0001},
-       {0x05, 0x00d2, 0x0000},
-       {0x05, 0x0020, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x00, 0x0090, 0x0005},
-       {0x01, 0x00a6, 0x0000},
-       {0x05, 0x0026, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x05, 0x0027, 0x0001},
-       {0x05, 0x000f, 0x0000},
-       {0x01, 0x0003, 0x003f},
-       {0x01, 0x0001, 0x0056},
-       {0x01, 0x0011, 0x0008},
-       {0x01, 0x0032, 0x0009},
-       {0x01, 0xfffd, 0x000a},
-       {0x01, 0x0023, 0x000b},
-       {0x01, 0xffea, 0x000c},
-       {0x01, 0xfff4, 0x000d},
-       {0x01, 0xfffc, 0x000e},
-       {0x01, 0xffe3, 0x000f},
-       {0x01, 0x001f, 0x0010},
-       {0x01, 0x00a8, 0x0001},
-       {0x01, 0x0067, 0x0007},
-       {0x01, 0x0042, 0x0051},
-       {0x01, 0x0051, 0x0053},
-       {0x01, 0x000a, 0x0003},
-       {0x02, 0xc002, 0x0001},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0xc000, 0x0001},
-       {0x02, 0x0000, 0x0005},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0x2000, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x05, 0x0015, 0x0001},
-       {0x05, 0x00ea, 0x0000},
-       {0x05, 0x0021, 0x0001},
-       {0x05, 0x00d2, 0x0000},
-       {0x05, 0x0023, 0x0001},
-       {0x05, 0x0003, 0x0000},
-       {0x05, 0x0030, 0x0001},
-       {0x05, 0x002b, 0x0000},
-       {0x05, 0x0031, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0032, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0033, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0034, 0x0001},
-       {0x05, 0x0002, 0x0000},
-       {0x05, 0x0050, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0051, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0052, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0054, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x00, 0x0000, 0x0001},
-       {0x00, 0x0000, 0x0002},
-       {0x00, 0x000c, 0x0003},
-       {0x00, 0x0000, 0x0004},
-       {0x00, 0x0090, 0x0005},
-       {0x00, 0x0000, 0x0006},
-       {0x00, 0x0040, 0x0007},
-       {0x00, 0x00c0, 0x0008},
-       {0x00, 0x004a, 0x0009},
-       {0x00, 0x0000, 0x000a},
-       {0x00, 0x0000, 0x000b},
-       {0x00, 0x0001, 0x000c},
-       {0x00, 0x0001, 0x000d},
-       {0x00, 0x0000, 0x000e},
-       {0x00, 0x0002, 0x000f},
-       {0x00, 0x0001, 0x0010},
-       {0x00, 0x0000, 0x0011},
-       {0x00, 0x0000, 0x0012},
-       {0x00, 0x0002, 0x0020},
-       {0x00, 0x0080, 0x0021},
-       {0x00, 0x0001, 0x0022},
-       {0x00, 0x00e0, 0x0023},
-       {0x00, 0x0000, 0x0024},
-       {0x00, 0x00d5, 0x0025},
-       {0x00, 0x0000, 0x0026},
-       {0x00, 0x000b, 0x0027},
-       {0x00, 0x0000, 0x0046},
-       {0x00, 0x0000, 0x0047},
-       {0x00, 0x0000, 0x0048},
-       {0x00, 0x0000, 0x0049},
-       {0x00, 0x0008, 0x004a},
-       {0xff, 0x0000, 0x00d0},
-       {0xff, 0x00d8, 0x00d1},
-       {0xff, 0x0000, 0x00d4},
-       {0xff, 0x0000, 0x00d5},
-       {0x01, 0x00a6, 0x0000},
-       {0x01, 0x0028, 0x0001},
-       {0x01, 0x0000, 0x0002},
-       {0x01, 0x000a, 0x0003},
-       {0x01, 0x0040, 0x0004},
-       {0x01, 0x0066, 0x0007},
-       {0x01, 0x0011, 0x0008},
-       {0x01, 0x0032, 0x0009},
-       {0x01, 0x00fd, 0x000a},
-       {0x01, 0x0038, 0x000b},
-       {0x01, 0x00d1, 0x000c},
-       {0x01, 0x00f7, 0x000d},
-       {0x01, 0x00ed, 0x000e},
-       {0x01, 0x00d8, 0x000f},
-       {0x01, 0x0038, 0x0010},
-       {0x01, 0x00ff, 0x0015},
-       {0x01, 0x0001, 0x0016},
-       {0x01, 0x0032, 0x0017},
-       {0x01, 0x0023, 0x0018},
-       {0x01, 0x00ce, 0x0019},
-       {0x01, 0x0023, 0x001a},
-       {0x01, 0x0032, 0x001b},
-       {0x01, 0x008d, 0x001c},
-       {0x01, 0x00ce, 0x001d},
-       {0x01, 0x008d, 0x001e},
-       {0x01, 0x0000, 0x001f},
-       {0x01, 0x0000, 0x0020},
-       {0x01, 0x00ff, 0x003e},
-       {0x01, 0x0003, 0x003f},
-       {0x01, 0x0000, 0x0040},
-       {0x01, 0x0035, 0x0041},
-       {0x01, 0x0053, 0x0042},
-       {0x01, 0x0069, 0x0043},
-       {0x01, 0x007c, 0x0044},
-       {0x01, 0x008c, 0x0045},
-       {0x01, 0x009a, 0x0046},
-       {0x01, 0x00a8, 0x0047},
-       {0x01, 0x00b4, 0x0048},
-       {0x01, 0x00bf, 0x0049},
-       {0x01, 0x00ca, 0x004a},
-       {0x01, 0x00d4, 0x004b},
-       {0x01, 0x00dd, 0x004c},
-       {0x01, 0x00e7, 0x004d},
-       {0x01, 0x00ef, 0x004e},
-       {0x01, 0x00f8, 0x004f},
-       {0x01, 0x00ff, 0x0050},
-       {0x01, 0x0001, 0x0056},
-       {0x01, 0x0060, 0x0057},
-       {0x01, 0x0040, 0x0058},
-       {0x01, 0x0011, 0x0059},
-       {0x01, 0x0001, 0x005a},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0x0015, 0x0006},
-       {0x02, 0x100a, 0x0007},
-       {0x02, 0xa048, 0x0000},
-       {0x02, 0xc002, 0x0001},
-       {0x02, 0x000f, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x05, 0x0025, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0026, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x05, 0x0027, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0001, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0021, 0x0001},
-       {0x05, 0x00d2, 0x0000},
-       {0x05, 0x0020, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x00, 0x0090, 0x0005},
-       {0x01, 0x00a6, 0x0000},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0x2000, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x05, 0x0015, 0x0001},
-       {0x05, 0x00ea, 0x0000},
-       {0x05, 0x0021, 0x0001},
-       {0x05, 0x00d2, 0x0000},
-       {0x05, 0x0023, 0x0001},
-       {0x05, 0x0003, 0x0000},
-       {0x05, 0x0030, 0x0001},
-       {0x05, 0x002b, 0x0000},
-       {0x05, 0x0031, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0032, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0033, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0034, 0x0001},
-       {0x05, 0x0002, 0x0000},
-       {0x05, 0x0050, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0051, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0052, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0054, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x00, 0x0000, 0x0001},
-       {0x00, 0x0000, 0x0002},
-       {0x00, 0x000c, 0x0003},
-       {0x00, 0x0000, 0x0004},
-       {0x00, 0x0090, 0x0005},
-       {0x00, 0x0000, 0x0006},
-       {0x00, 0x0040, 0x0007},
-       {0x00, 0x00c0, 0x0008},
-       {0x00, 0x004a, 0x0009},
-       {0x00, 0x0000, 0x000a},
-       {0x00, 0x0000, 0x000b},
-       {0x00, 0x0001, 0x000c},
-       {0x00, 0x0001, 0x000d},
-       {0x00, 0x0000, 0x000e},
-       {0x00, 0x0002, 0x000f},
-       {0x00, 0x0001, 0x0010},
-       {0x00, 0x0000, 0x0011},
-       {0x00, 0x0000, 0x0012},
-       {0x00, 0x0002, 0x0020},
-       {0x00, 0x0080, 0x0021},
-       {0x00, 0x0001, 0x0022},
-       {0x00, 0x00e0, 0x0023},
-       {0x00, 0x0000, 0x0024},
-       {0x00, 0x00d5, 0x0025},
-       {0x00, 0x0000, 0x0026},
-       {0x00, 0x000b, 0x0027},
-       {0x00, 0x0000, 0x0046},
-       {0x00, 0x0000, 0x0047},
-       {0x00, 0x0000, 0x0048},
-       {0x00, 0x0000, 0x0049},
-       {0x00, 0x0008, 0x004a},
-       {0xff, 0x0000, 0x00d0},
-       {0xff, 0x00d8, 0x00d1},
-       {0xff, 0x0000, 0x00d4},
-       {0xff, 0x0000, 0x00d5},
-       {0x01, 0x00a6, 0x0000},
-       {0x01, 0x0028, 0x0001},
-       {0x01, 0x0000, 0x0002},
-       {0x01, 0x000a, 0x0003},
-       {0x01, 0x0040, 0x0004},
-       {0x01, 0x0066, 0x0007},
-       {0x01, 0x0011, 0x0008},
-       {0x01, 0x0032, 0x0009},
-       {0x01, 0x00fd, 0x000a},
-       {0x01, 0x0038, 0x000b},
-       {0x01, 0x00d1, 0x000c},
-       {0x01, 0x00f7, 0x000d},
-       {0x01, 0x00ed, 0x000e},
-       {0x01, 0x00d8, 0x000f},
-       {0x01, 0x0038, 0x0010},
-       {0x01, 0x00ff, 0x0015},
-       {0x01, 0x0001, 0x0016},
-       {0x01, 0x0032, 0x0017},
-       {0x01, 0x0023, 0x0018},
-       {0x01, 0x00ce, 0x0019},
-       {0x01, 0x0023, 0x001a},
-       {0x01, 0x0032, 0x001b},
-       {0x01, 0x008d, 0x001c},
-       {0x01, 0x00ce, 0x001d},
-       {0x01, 0x008d, 0x001e},
-       {0x01, 0x0000, 0x001f},
-       {0x01, 0x0000, 0x0020},
-       {0x01, 0x00ff, 0x003e},
-       {0x01, 0x0003, 0x003f},
-       {0x01, 0x0000, 0x0040},
-       {0x01, 0x0035, 0x0041},
-       {0x01, 0x0053, 0x0042},
-       {0x01, 0x0069, 0x0043},
-       {0x01, 0x007c, 0x0044},
-       {0x01, 0x008c, 0x0045},
-       {0x01, 0x009a, 0x0046},
-       {0x01, 0x00a8, 0x0047},
-       {0x01, 0x00b4, 0x0048},
-       {0x01, 0x00bf, 0x0049},
-       {0x01, 0x00ca, 0x004a},
-       {0x01, 0x00d4, 0x004b},
-       {0x01, 0x00dd, 0x004c},
-       {0x01, 0x00e7, 0x004d},
-       {0x01, 0x00ef, 0x004e},
-       {0x01, 0x00f8, 0x004f},
-       {0x01, 0x00ff, 0x0050},
-       {0x01, 0x0001, 0x0056},
-       {0x01, 0x0060, 0x0057},
-       {0x01, 0x0040, 0x0058},
-       {0x01, 0x0011, 0x0059},
-       {0x01, 0x0001, 0x005a},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0x0015, 0x0006},
-       {0x02, 0x100a, 0x0007},
-       {0x02, 0xa048, 0x0000},
-       {0x02, 0xc002, 0x0001},
-       {0x02, 0x000f, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x05, 0x0025, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0026, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x05, 0x0027, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0001, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0021, 0x0001},
-       {0x05, 0x00d2, 0x0000},
-       {0x05, 0x0020, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x00, 0x0090, 0x0005},
-       {0x01, 0x00a6, 0x0000},
-       {0x05, 0x0026, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x05, 0x0027, 0x0001},
-       {0x05, 0x001e, 0x0000},
-       {0x01, 0x0003, 0x003f},
-       {0x01, 0x0001, 0x0056},
-       {0x01, 0x0011, 0x0008},
-       {0x01, 0x0032, 0x0009},
-       {0x01, 0xfffd, 0x000a},
-       {0x01, 0x0023, 0x000b},
-       {0x01, 0xffea, 0x000c},
-       {0x01, 0xfff4, 0x000d},
-       {0x01, 0xfffc, 0x000e},
-       {0x01, 0xffe3, 0x000f},
-       {0x01, 0x001f, 0x0010},
-       {0x01, 0x00a8, 0x0001},
-       {0x01, 0x0067, 0x0007},
-       {0x01, 0x0042, 0x0051},
-       {0x01, 0x0051, 0x0053},
-       {0x01, 0x000a, 0x0003},
-       {0x02, 0xc002, 0x0001},
-       {0x02, 0x0007, 0x0005},
-       {0x01, 0x0042, 0x0051},
-       {0x01, 0x0051, 0x0053},
-       {0x05, 0x0026, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x05, 0x0027, 0x0001},
-       {0x05, 0x002d, 0x0000},
-       {0x01, 0x0003, 0x003f},
-       {0x01, 0x0001, 0x0056},
-       {0x02, 0xc000, 0x0001},
-       {0x02, 0x0000, 0x0005},
-       {}
-};
-
-/* Unknown camera from Ori Usbid 0x0000:0x0000 */
-/* Based on snoops from Ori Cohen */
-static const __u16 spca501c_mysterious_open_data[][3] = {
-       {0x02, 0x000f, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x05, 0x0022, 0x0004},
-/* DSP Registers */
-       {0x01, 0x0016, 0x0011}, /* RGB offset */
-       {0x01, 0x0000, 0x0012},
-       {0x01, 0x0006, 0x0013},
-       {0x01, 0x0078, 0x0051},
-       {0x01, 0x0040, 0x0052},
-       {0x01, 0x0046, 0x0053},
-       {0x01, 0x0040, 0x0054},
-       {0x00, 0x0025, 0x0000},
-/*     {0x00, 0x0000, 0x0000 }, */
-/* Part 2 */
-/* TG Registers */
-       {0x00, 0x0026, 0x0000},
-       {0x00, 0x0001, 0x0000},
-       {0x00, 0x0027, 0x0000},
-       {0x00, 0x008a, 0x0000},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0x2000, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x05, 0x0015, 0x0001},
-       {0x05, 0x00ea, 0x0000},
-       {0x05, 0x0021, 0x0001},
-       {0x05, 0x00d2, 0x0000},
-       {0x05, 0x0023, 0x0001},
-       {0x05, 0x0003, 0x0000},
-       {0x05, 0x0030, 0x0001},
-       {0x05, 0x002b, 0x0000},
-       {0x05, 0x0031, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0032, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0033, 0x0001},
-       {0x05, 0x0023, 0x0000},
-       {0x05, 0x0034, 0x0001},
-       {0x05, 0x0002, 0x0000},
-       {0x05, 0x0050, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0051, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0052, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0054, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {}
-};
-
-/* Based on snoops from Ori Cohen */
-static const __u16 spca501c_mysterious_init_data[][3] = {
-/* Part 3 */
-/* TG registers */
-/*     {0x00, 0x0000, 0x0000}, */
-       {0x00, 0x0000, 0x0001},
-       {0x00, 0x0000, 0x0002},
-       {0x00, 0x0006, 0x0003},
-       {0x00, 0x0000, 0x0004},
-       {0x00, 0x0090, 0x0005},
-       {0x00, 0x0000, 0x0006},
-       {0x00, 0x0040, 0x0007},
-       {0x00, 0x00c0, 0x0008},
-       {0x00, 0x004a, 0x0009},
-       {0x00, 0x0000, 0x000a},
-       {0x00, 0x0000, 0x000b},
-       {0x00, 0x0001, 0x000c},
-       {0x00, 0x0001, 0x000d},
-       {0x00, 0x0000, 0x000e},
-       {0x00, 0x0002, 0x000f},
-       {0x00, 0x0001, 0x0010},
-       {0x00, 0x0000, 0x0011},
-       {0x00, 0x0001, 0x0012},
-       {0x00, 0x0002, 0x0020},
-       {0x00, 0x0080, 0x0021}, /* 640 */
-       {0x00, 0x0001, 0x0022},
-       {0x00, 0x00e0, 0x0023}, /* 480 */
-       {0x00, 0x0000, 0x0024}, /* Offset H hight */
-       {0x00, 0x00d3, 0x0025}, /* low */
-       {0x00, 0x0000, 0x0026}, /* Offset V */
-       {0x00, 0x000d, 0x0027}, /* low */
-       {0x00, 0x0000, 0x0046},
-       {0x00, 0x0000, 0x0047},
-       {0x00, 0x0000, 0x0048},
-       {0x00, 0x0000, 0x0049},
-       {0x00, 0x0008, 0x004a},
-/* DSP Registers       */
-       {0x01, 0x00a6, 0x0000},
-       {0x01, 0x0028, 0x0001},
-       {0x01, 0x0000, 0x0002},
-       {0x01, 0x000a, 0x0003}, /* Level Calc bit7 ->1 Auto */
-       {0x01, 0x0040, 0x0004},
-       {0x01, 0x0066, 0x0007},
-       {0x01, 0x000f, 0x0008}, /* A11 Color correction coeff */
-       {0x01, 0x002d, 0x0009}, /* A12 */
-       {0x01, 0x0005, 0x000a}, /* A13 */
-       {0x01, 0x0023, 0x000b}, /* A21 */
-       {0x01, 0x00e0, 0x000c}, /* A22 */
-       {0x01, 0x00fd, 0x000d}, /* A23 */
-       {0x01, 0x00f4, 0x000e}, /* A31 */
-       {0x01, 0x00e4, 0x000f}, /* A32 */
-       {0x01, 0x0028, 0x0010}, /* A33 */
-       {0x01, 0x00ff, 0x0015}, /* Reserved */
-       {0x01, 0x0001, 0x0016}, /* Reserved */
-       {0x01, 0x0032, 0x0017}, /* Win1 Start begin */
-       {0x01, 0x0023, 0x0018},
-       {0x01, 0x00ce, 0x0019},
-       {0x01, 0x0023, 0x001a},
-       {0x01, 0x0032, 0x001b},
-       {0x01, 0x008d, 0x001c},
-       {0x01, 0x00ce, 0x001d},
-       {0x01, 0x008d, 0x001e},
-       {0x01, 0x0000, 0x001f},
-       {0x01, 0x0000, 0x0020}, /* Win1 Start end */
-       {0x01, 0x00ff, 0x003e}, /* Reserved begin */
-       {0x01, 0x0002, 0x003f},
-       {0x01, 0x0000, 0x0040},
-       {0x01, 0x0035, 0x0041},
-       {0x01, 0x0053, 0x0042},
-       {0x01, 0x0069, 0x0043},
-       {0x01, 0x007c, 0x0044},
-       {0x01, 0x008c, 0x0045},
-       {0x01, 0x009a, 0x0046},
-       {0x01, 0x00a8, 0x0047},
-       {0x01, 0x00b4, 0x0048},
-       {0x01, 0x00bf, 0x0049},
-       {0x01, 0x00ca, 0x004a},
-       {0x01, 0x00d4, 0x004b},
-       {0x01, 0x00dd, 0x004c},
-       {0x01, 0x00e7, 0x004d},
-       {0x01, 0x00ef, 0x004e},
-       {0x01, 0x00f8, 0x004f},
-       {0x01, 0x00ff, 0x0050},
-       {0x01, 0x0003, 0x0056}, /* Reserved end */
-       {0x01, 0x0060, 0x0057}, /* Edge Gain */
-       {0x01, 0x0040, 0x0058},
-       {0x01, 0x0011, 0x0059}, /* Edge Bandwidth */
-       {0x01, 0x0001, 0x005a},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x02, 0x0007, 0x0005},
-       {0x02, 0x0015, 0x0006},
-       {0x02, 0x200a, 0x0007},
-       {0x02, 0xa048, 0x0000},
-       {0x02, 0xc000, 0x0001},
-       {0x02, 0x000f, 0x0005},
-       {0x02, 0xa048, 0x0000},
-       {0x05, 0x0022, 0x0004},
-       {0x05, 0x0025, 0x0001},
-       {0x05, 0x0000, 0x0000},
-/* Part 4 */
-       {0x05, 0x0026, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x05, 0x0027, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0001, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x05, 0x0021, 0x0001},
-       {0x05, 0x00d2, 0x0000},
-       {0x05, 0x0020, 0x0001},
-       {0x05, 0x0000, 0x0000},
-       {0x00, 0x0090, 0x0005},
-       {0x01, 0x00a6, 0x0000},
-       {0x02, 0x0000, 0x0005},
-       {0x05, 0x0026, 0x0001},
-       {0x05, 0x0001, 0x0000},
-       {0x05, 0x0027, 0x0001},
-       {0x05, 0x004e, 0x0000},
-/* Part 5 */
-       {0x01, 0x0003, 0x003f},
-       {0x01, 0x0001, 0x0056},
-       {0x01, 0x000f, 0x0008},
-       {0x01, 0x002d, 0x0009},
-       {0x01, 0x0005, 0x000a},
-       {0x01, 0x0023, 0x000b},
-       {0x01, 0xffe0, 0x000c},
-       {0x01, 0xfffd, 0x000d},
-       {0x01, 0xfff4, 0x000e},
-       {0x01, 0xffe4, 0x000f},
-       {0x01, 0x0028, 0x0010},
-       {0x01, 0x00a8, 0x0001},
-       {0x01, 0x0066, 0x0007},
-       {0x01, 0x0032, 0x0017},
-       {0x01, 0x0023, 0x0018},
-       {0x01, 0x00ce, 0x0019},
-       {0x01, 0x0023, 0x001a},
-       {0x01, 0x0032, 0x001b},
-       {0x01, 0x008d, 0x001c},
-       {0x01, 0x00ce, 0x001d},
-       {0x01, 0x008d, 0x001e},
-       {0x01, 0x00c8, 0x0015}, /* c8 Poids fort Luma */
-       {0x01, 0x0032, 0x0016}, /* 32 */
-       {0x01, 0x0016, 0x0011}, /* R 00 */
-       {0x01, 0x0016, 0x0012}, /* G 00 */
-       {0x01, 0x0016, 0x0013}, /* B 00 */
-       {0x01, 0x000a, 0x0003},
-       {0x02, 0xc002, 0x0001},
-       {0x02, 0x0007, 0x0005},
-       {}
-};
-
-static int reg_write(struct usb_device *dev,
-                    __u16 req, __u16 index, __u16 value)
-{
-       int ret;
-
-       ret = usb_control_msg(dev,
-                       usb_sndctrlpipe(dev, 0),
-                       req,
-                       USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index, NULL, 0, 500);
-       PDEBUG(D_USBO, "reg write: 0x%02x 0x%02x 0x%02x",
-               req, index, value);
-       if (ret < 0)
-               pr_err("reg write: error %d\n", ret);
-       return ret;
-}
-
-
-static int write_vector(struct gspca_dev *gspca_dev,
-                       const __u16 data[][3])
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret, i = 0;
-
-       while (data[i][0] != 0 || data[i][1] != 0 || data[i][2] != 0) {
-               ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
-               if (ret < 0) {
-                       PDEBUG(D_ERR,
-                               "Reg write failed for 0x%02x,0x%02x,0x%02x",
-                               data[i][0], data[i][1], data[i][2]);
-                       return ret;
-               }
-               i++;
-       }
-       return 0;
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x12, val);
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_write(gspca_dev->dev, 0x00, 0x00,
-                                 (val >> 8) & 0xff);
-       reg_write(gspca_dev->dev, 0x00, 0x01,
-                                 val & 0xff);
-}
-
-static void setcolors(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x0c, val);
-}
-
-static void setblue_balance(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x11, val);
-}
-
-static void setred_balance(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_write(gspca_dev->dev, SPCA501_REG_CCDSP, 0x13, val);
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-
-       cam = &gspca_dev->cam;
-       cam->cam_mode = vga_mode;
-       cam->nmodes = ARRAY_SIZE(vga_mode);
-       sd->subtype = id->driver_info;
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->subtype) {
-       case Arowana300KCMOSCamera:
-       case SmileIntlCamera:
-               /* Arowana 300k CMOS Camera data */
-               if (write_vector(gspca_dev, spca501c_arowana_init_data))
-                       goto error;
-               break;
-       case MystFromOriUnknownCamera:
-               /* Unknown Ori CMOS Camera data */
-               if (write_vector(gspca_dev, spca501c_mysterious_open_data))
-                       goto error;
-               break;
-       default:
-               /* generic spca501 init data */
-               if (write_vector(gspca_dev, spca501_init_data))
-                       goto error;
-               break;
-       }
-       PDEBUG(D_STREAM, "Initializing SPCA501 finished");
-       return 0;
-error:
-       return -EINVAL;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct usb_device *dev = gspca_dev->dev;
-       int mode;
-
-       switch (sd->subtype) {
-       case ThreeComHomeConnectLite:
-               /* Special handling for 3com data */
-               write_vector(gspca_dev, spca501_3com_open_data);
-               break;
-       case Arowana300KCMOSCamera:
-       case SmileIntlCamera:
-               /* Arowana 300k CMOS Camera data */
-               write_vector(gspca_dev, spca501c_arowana_open_data);
-               break;
-       case MystFromOriUnknownCamera:
-               /* Unknown CMOS Camera data */
-               write_vector(gspca_dev, spca501c_mysterious_init_data);
-               break;
-       default:
-               /* Generic 501 open data */
-               write_vector(gspca_dev, spca501_open_data);
-       }
-
-       /* memorize the wanted pixel format */
-       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
-
-       /* Enable ISO packet machine CTRL reg=2,
-        * index=1 bitmask=0x2 (bit ordinal 1) */
-       reg_write(dev, SPCA50X_REG_USB, 0x6, 0x94);
-       switch (mode) {
-       case 0: /* 640x480 */
-               reg_write(dev, SPCA50X_REG_USB, 0x07, 0x004a);
-               break;
-       case 1: /* 320x240 */
-               reg_write(dev, SPCA50X_REG_USB, 0x07, 0x104a);
-               break;
-       default:
-/*     case 2:  * 160x120 */
-               reg_write(dev, SPCA50X_REG_USB, 0x07, 0x204a);
-               break;
-       }
-       reg_write(dev, SPCA501_REG_CTLRL, 0x01, 0x02);
-
-       return 0;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       /* Disable ISO packet
-        * machine CTRL reg=2, index=1 bitmask=0x0 (bit ordinal 1) */
-       reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x01, 0x00);
-}
-
-/* called on streamoff with alt 0 and on disconnect */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       if (!gspca_dev->present)
-               return;
-       reg_write(gspca_dev->dev, SPCA501_REG_CTLRL, 0x05, 0x00);
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,                       /* isoc packet */
-                       int len)                        /* iso packet length */
-{
-       switch (data[0]) {
-       case 0:                         /* start of frame */
-               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-               data += SPCA501_OFFSET_DATA;
-               len -= SPCA501_OFFSET_DATA;
-               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
-               return;
-       case 0xff:                      /* drop */
-/*             gspca_dev->last_packet_type = DISCARD_PACKET; */
-               return;
-       }
-       data++;
-       len--;
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct gspca_dev *gspca_dev =
-               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
-
-       gspca_dev->usb_err = 0;
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               setcolors(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               setblue_balance(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_RED_BALANCE:
-               setred_balance(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 5);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 127, 1, 0);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 64725, 1, 64725);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 63, 1, 20);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BLUE_BALANCE, 0, 127, 1, 0);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_RED_BALANCE, 0, 127, 1, 0);
-
-       if (hdl->error) {
-               pr_err("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,
-       .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x040a, 0x0002), .driver_info = KodakDVC325},
-       {USB_DEVICE(0x0497, 0xc001), .driver_info = SmileIntlCamera},
-       {USB_DEVICE(0x0506, 0x00df), .driver_info = ThreeComHomeConnectLite},
-       {USB_DEVICE(0x0733, 0x0401), .driver_info = IntelCreateAndShare},
-       {USB_DEVICE(0x0733, 0x0402), .driver_info = ViewQuestM318B},
-       {USB_DEVICE(0x1776, 0x501c), .driver_info = Arowana300KCMOSCamera},
-       {USB_DEVICE(0x0000, 0x0000), .driver_info = MystFromOriUnknownCamera},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/spca505.c b/drivers/media/video/gspca/spca505.c
deleted file mode 100644 (file)
index bc7d67c..0000000
+++ /dev/null
@@ -1,807 +0,0 @@
-/*
- * SPCA505 chip based cameras initialization data
- *
- * V4L2 by Jean-Francis Moine <http://moinejf.free.fr>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "spca505"
-
-#include "gspca.h"
-
-MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
-MODULE_DESCRIPTION("GSPCA/SPCA505 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;             /* !! must be the first item */
-
-       u8 subtype;
-#define IntelPCCameraPro 0
-#define Nxultra 1
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 4},
-       {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 3},
-       {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2},
-       {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-#define SPCA50X_OFFSET_DATA 10
-
-#define SPCA50X_REG_USB 0x02   /* spca505 501 */
-
-#define SPCA50X_USB_CTRL 0x00  /* spca505 */
-#define SPCA50X_CUSB_ENABLE 0x01 /* spca505 */
-
-#define SPCA50X_REG_GLOBAL 0x03        /* spca505 */
-#define SPCA50X_GMISC0_IDSEL 0x01 /* Global control device ID select spca505 */
-#define SPCA50X_GLOBAL_MISC0 0x00 /* Global control miscellaneous 0 spca505 */
-
-#define SPCA50X_GLOBAL_MISC1 0x01 /* 505 */
-#define SPCA50X_GLOBAL_MISC3 0x03 /* 505 */
-#define SPCA50X_GMISC3_SAA7113RST 0x20 /* Not sure about this one spca505 */
-
-/* Image format and compression control */
-#define SPCA50X_REG_COMPRESS 0x04
-
-/*
- * Data to initialize a SPCA505. Common to the CCD and external modes
- */
-static const u8 spca505_init_data[][3] = {
-       /* bmRequest,value,index */
-       {SPCA50X_REG_GLOBAL, SPCA50X_GMISC3_SAA7113RST, SPCA50X_GLOBAL_MISC3},
-       /* Sensor reset */
-       {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC3},
-       {SPCA50X_REG_GLOBAL, 0x00, SPCA50X_GLOBAL_MISC1},
-       /* Block USB reset */
-       {SPCA50X_REG_GLOBAL, SPCA50X_GMISC0_IDSEL, SPCA50X_GLOBAL_MISC0},
-
-       {0x05, 0x01, 0x10},
-                                       /* Maybe power down some stuff */
-       {0x05, 0x0f, 0x11},
-
-       /* Setup internal CCD  ? */
-       {0x06, 0x10, 0x08},
-       {0x06, 0x00, 0x09},
-       {0x06, 0x00, 0x0a},
-       {0x06, 0x00, 0x0b},
-       {0x06, 0x10, 0x0c},
-       {0x06, 0x00, 0x0d},
-       {0x06, 0x00, 0x0e},
-       {0x06, 0x00, 0x0f},
-       {0x06, 0x10, 0x10},
-       {0x06, 0x02, 0x11},
-       {0x06, 0x00, 0x12},
-       {0x06, 0x04, 0x13},
-       {0x06, 0x02, 0x14},
-       {0x06, 0x8a, 0x51},
-       {0x06, 0x40, 0x52},
-       {0x06, 0xb6, 0x53},
-       {0x06, 0x3d, 0x54},
-       {}
-};
-
-/*
- * Data to initialize the camera using the internal CCD
- */
-static const u8 spca505_open_data_ccd[][3] = {
-       /* bmRequest,value,index */
-       /* Internal CCD data set */
-       {0x03, 0x04, 0x01},
-       /* This could be a reset */
-       {0x03, 0x00, 0x01},
-
-       /* Setup compression and image registers. 0x6 and 0x7 seem to be
-          related to H&V hold, and are resolution mode specific */
-               {0x04, 0x10, 0x01},
-               /* DIFF(0x50), was (0x10) */
-       {0x04, 0x00, 0x04},
-       {0x04, 0x00, 0x05},
-       {0x04, 0x20, 0x06},
-       {0x04, 0x20, 0x07},
-
-       {0x08, 0x0a, 0x00},
-       /* DIFF (0x4a), was (0xa) */
-
-       {0x05, 0x00, 0x10},
-       {0x05, 0x00, 0x11},
-       {0x05, 0x00, 0x00},
-       /* DIFF not written */
-       {0x05, 0x00, 0x01},
-       /* DIFF not written */
-       {0x05, 0x00, 0x02},
-       /* DIFF not written */
-       {0x05, 0x00, 0x03},
-       /* DIFF not written */
-       {0x05, 0x00, 0x04},
-       /* DIFF not written */
-               {0x05, 0x80, 0x05},
-               /* DIFF not written */
-               {0x05, 0xe0, 0x06},
-               /* DIFF not written */
-               {0x05, 0x20, 0x07},
-               /* DIFF not written */
-               {0x05, 0xa0, 0x08},
-               /* DIFF not written */
-               {0x05, 0x0, 0x12},
-               /* DIFF not written */
-       {0x05, 0x02, 0x0f},
-       /* DIFF not written */
-               {0x05, 0x10, 0x46},
-               /* DIFF not written */
-               {0x05, 0x8, 0x4a},
-               /* DIFF not written */
-
-       {0x03, 0x08, 0x03},
-       /* DIFF (0x3,0x28,0x3) */
-       {0x03, 0x08, 0x01},
-       {0x03, 0x0c, 0x03},
-       /* DIFF not written */
-               {0x03, 0x21, 0x00},
-               /* DIFF (0x39) */
-
-/* Extra block copied from init to hopefully ensure CCD is in a sane state */
-       {0x06, 0x10, 0x08},
-       {0x06, 0x00, 0x09},
-       {0x06, 0x00, 0x0a},
-       {0x06, 0x00, 0x0b},
-       {0x06, 0x10, 0x0c},
-       {0x06, 0x00, 0x0d},
-       {0x06, 0x00, 0x0e},
-       {0x06, 0x00, 0x0f},
-       {0x06, 0x10, 0x10},
-       {0x06, 0x02, 0x11},
-       {0x06, 0x00, 0x12},
-       {0x06, 0x04, 0x13},
-       {0x06, 0x02, 0x14},
-       {0x06, 0x8a, 0x51},
-       {0x06, 0x40, 0x52},
-       {0x06, 0xb6, 0x53},
-       {0x06, 0x3d, 0x54},
-       /* End of extra block */
-
-               {0x06, 0x3f, 0x1},
-               /* Block skipped */
-       {0x06, 0x10, 0x02},
-       {0x06, 0x64, 0x07},
-       {0x06, 0x10, 0x08},
-       {0x06, 0x00, 0x09},
-       {0x06, 0x00, 0x0a},
-       {0x06, 0x00, 0x0b},
-       {0x06, 0x10, 0x0c},
-       {0x06, 0x00, 0x0d},
-       {0x06, 0x00, 0x0e},
-       {0x06, 0x00, 0x0f},
-       {0x06, 0x10, 0x10},
-       {0x06, 0x02, 0x11},
-       {0x06, 0x00, 0x12},
-       {0x06, 0x04, 0x13},
-       {0x06, 0x02, 0x14},
-       {0x06, 0x8a, 0x51},
-       {0x06, 0x40, 0x52},
-       {0x06, 0xb6, 0x53},
-       {0x06, 0x3d, 0x54},
-       {0x06, 0x60, 0x57},
-       {0x06, 0x20, 0x58},
-       {0x06, 0x15, 0x59},
-       {0x06, 0x05, 0x5a},
-
-       {0x05, 0x01, 0xc0},
-       {0x05, 0x10, 0xcb},
-               {0x05, 0x80, 0xc1},
-               /* */
-               {0x05, 0x0, 0xc2},
-               /* 4 was 0 */
-       {0x05, 0x00, 0xca},
-               {0x05, 0x80, 0xc1},
-               /*  */
-       {0x05, 0x04, 0xc2},
-       {0x05, 0x00, 0xca},
-               {0x05, 0x0, 0xc1},
-               /*  */
-       {0x05, 0x00, 0xc2},
-       {0x05, 0x00, 0xca},
-               {0x05, 0x40, 0xc1},
-               /* */
-       {0x05, 0x17, 0xc2},
-       {0x05, 0x00, 0xca},
-               {0x05, 0x80, 0xc1},
-               /* */
-       {0x05, 0x06, 0xc2},
-       {0x05, 0x00, 0xca},
-               {0x05, 0x80, 0xc1},
-               /* */
-       {0x05, 0x04, 0xc2},
-       {0x05, 0x00, 0xca},
-
-       {0x03, 0x4c, 0x3},
-       {0x03, 0x18, 0x1},
-
-       {0x06, 0x70, 0x51},
-       {0x06, 0xbe, 0x53},
-       {0x06, 0x71, 0x57},
-       {0x06, 0x20, 0x58},
-       {0x06, 0x05, 0x59},
-       {0x06, 0x15, 0x5a},
-
-       {0x04, 0x00, 0x08},
-       /* Compress = OFF (0x1 to turn on) */
-       {0x04, 0x12, 0x09},
-       {0x04, 0x21, 0x0a},
-       {0x04, 0x10, 0x0b},
-       {0x04, 0x21, 0x0c},
-       {0x04, 0x05, 0x00},
-       /* was 5 (Image Type ? ) */
-       {0x04, 0x00, 0x01},
-
-       {0x06, 0x3f, 0x01},
-
-       {0x04, 0x00, 0x04},
-       {0x04, 0x00, 0x05},
-       {0x04, 0x40, 0x06},
-       {0x04, 0x40, 0x07},
-
-       {0x06, 0x1c, 0x17},
-       {0x06, 0xe2, 0x19},
-       {0x06, 0x1c, 0x1b},
-       {0x06, 0xe2, 0x1d},
-       {0x06, 0xaa, 0x1f},
-       {0x06, 0x70, 0x20},
-
-       {0x05, 0x01, 0x10},
-       {0x05, 0x00, 0x11},
-       {0x05, 0x01, 0x00},
-       {0x05, 0x05, 0x01},
-               {0x05, 0x00, 0xc1},
-               /* */
-       {0x05, 0x00, 0xc2},
-       {0x05, 0x00, 0xca},
-
-       {0x06, 0x70, 0x51},
-       {0x06, 0xbe, 0x53},
-       {}
-};
-
-/*
- * Made by Tomasz Zablocki (skalamandra@poczta.onet.pl)
- * SPCA505b chip based cameras initialization data
- */
-/* jfm */
-#define initial_brightness 0x7f        /* 0x0(white)-0xff(black) */
-/* #define initial_brightness 0x0      //0x0(white)-0xff(black) */
-/*
- * Data to initialize a SPCA505. Common to the CCD and external modes
- */
-static const u8 spca505b_init_data[][3] = {
-/* start */
-       {0x02, 0x00, 0x00},             /* init */
-       {0x02, 0x00, 0x01},
-       {0x02, 0x00, 0x02},
-       {0x02, 0x00, 0x03},
-       {0x02, 0x00, 0x04},
-       {0x02, 0x00, 0x05},
-       {0x02, 0x00, 0x06},
-       {0x02, 0x00, 0x07},
-       {0x02, 0x00, 0x08},
-       {0x02, 0x00, 0x09},
-       {0x03, 0x00, 0x00},
-       {0x03, 0x00, 0x01},
-       {0x03, 0x00, 0x02},
-       {0x03, 0x00, 0x03},
-       {0x03, 0x00, 0x04},
-       {0x03, 0x00, 0x05},
-       {0x03, 0x00, 0x06},
-       {0x04, 0x00, 0x00},
-       {0x04, 0x00, 0x02},
-       {0x04, 0x00, 0x04},
-       {0x04, 0x00, 0x05},
-       {0x04, 0x00, 0x06},
-       {0x04, 0x00, 0x07},
-       {0x04, 0x00, 0x08},
-       {0x04, 0x00, 0x09},
-       {0x04, 0x00, 0x0a},
-       {0x04, 0x00, 0x0b},
-       {0x04, 0x00, 0x0c},
-       {0x07, 0x00, 0x00},
-       {0x07, 0x00, 0x03},
-       {0x08, 0x00, 0x00},
-       {0x08, 0x00, 0x01},
-       {0x08, 0x00, 0x02},
-       {0x06, 0x18, 0x08},
-       {0x06, 0xfc, 0x09},
-       {0x06, 0xfc, 0x0a},
-       {0x06, 0xfc, 0x0b},
-       {0x06, 0x18, 0x0c},
-       {0x06, 0xfc, 0x0d},
-       {0x06, 0xfc, 0x0e},
-       {0x06, 0xfc, 0x0f},
-       {0x06, 0x18, 0x10},
-       {0x06, 0xfe, 0x12},
-       {0x06, 0x00, 0x11},
-       {0x06, 0x00, 0x14},
-       {0x06, 0x00, 0x13},
-       {0x06, 0x28, 0x51},
-       {0x06, 0xff, 0x53},
-       {0x02, 0x00, 0x08},
-
-       {0x03, 0x00, 0x03},
-       {0x03, 0x10, 0x03},
-       {}
-};
-
-/*
- * Data to initialize the camera using the internal CCD
- */
-static const u8 spca505b_open_data_ccd[][3] = {
-
-/* {0x02,0x00,0x00}, */
-       {0x03, 0x04, 0x01},             /* rst */
-       {0x03, 0x00, 0x01},
-       {0x03, 0x00, 0x00},
-       {0x03, 0x21, 0x00},
-       {0x03, 0x00, 0x04},
-       {0x03, 0x00, 0x03},
-       {0x03, 0x18, 0x03},
-       {0x03, 0x08, 0x01},
-       {0x03, 0x1c, 0x03},
-       {0x03, 0x5c, 0x03},
-       {0x03, 0x5c, 0x03},
-       {0x03, 0x18, 0x01},
-
-/* same as 505 */
-       {0x04, 0x10, 0x01},
-       {0x04, 0x00, 0x04},
-       {0x04, 0x00, 0x05},
-       {0x04, 0x20, 0x06},
-       {0x04, 0x20, 0x07},
-
-       {0x08, 0x0a, 0x00},
-
-       {0x05, 0x00, 0x10},
-       {0x05, 0x00, 0x11},
-       {0x05, 0x00, 0x12},
-       {0x05, 0x6f, 0x00},
-       {0x05, initial_brightness >> 6, 0x00},
-       {0x05, (initial_brightness << 2) & 0xff, 0x01},
-       {0x05, 0x00, 0x02},
-       {0x05, 0x01, 0x03},
-       {0x05, 0x00, 0x04},
-       {0x05, 0x03, 0x05},
-       {0x05, 0xe0, 0x06},
-       {0x05, 0x20, 0x07},
-       {0x05, 0xa0, 0x08},
-       {0x05, 0x00, 0x12},
-       {0x05, 0x02, 0x0f},
-       {0x05, 0x80, 0x14},             /* max exposure off (0=on) */
-       {0x05, 0x01, 0xb0},
-       {0x05, 0x01, 0xbf},
-       {0x03, 0x02, 0x06},
-       {0x05, 0x10, 0x46},
-       {0x05, 0x08, 0x4a},
-
-       {0x06, 0x00, 0x01},
-       {0x06, 0x10, 0x02},
-       {0x06, 0x64, 0x07},
-       {0x06, 0x18, 0x08},
-       {0x06, 0xfc, 0x09},
-       {0x06, 0xfc, 0x0a},
-       {0x06, 0xfc, 0x0b},
-       {0x04, 0x00, 0x01},
-       {0x06, 0x18, 0x0c},
-       {0x06, 0xfc, 0x0d},
-       {0x06, 0xfc, 0x0e},
-       {0x06, 0xfc, 0x0f},
-       {0x06, 0x11, 0x10},             /* contrast */
-       {0x06, 0x00, 0x11},
-       {0x06, 0xfe, 0x12},
-       {0x06, 0x00, 0x13},
-       {0x06, 0x00, 0x14},
-       {0x06, 0x9d, 0x51},
-       {0x06, 0x40, 0x52},
-       {0x06, 0x7c, 0x53},
-       {0x06, 0x40, 0x54},
-       {0x06, 0x02, 0x57},
-       {0x06, 0x03, 0x58},
-       {0x06, 0x15, 0x59},
-       {0x06, 0x05, 0x5a},
-       {0x06, 0x03, 0x56},
-       {0x06, 0x02, 0x3f},
-       {0x06, 0x00, 0x40},
-       {0x06, 0x39, 0x41},
-       {0x06, 0x69, 0x42},
-       {0x06, 0x87, 0x43},
-       {0x06, 0x9e, 0x44},
-       {0x06, 0xb1, 0x45},
-       {0x06, 0xbf, 0x46},
-       {0x06, 0xcc, 0x47},
-       {0x06, 0xd5, 0x48},
-       {0x06, 0xdd, 0x49},
-       {0x06, 0xe3, 0x4a},
-       {0x06, 0xe8, 0x4b},
-       {0x06, 0xed, 0x4c},
-       {0x06, 0xf2, 0x4d},
-       {0x06, 0xf7, 0x4e},
-       {0x06, 0xfc, 0x4f},
-       {0x06, 0xff, 0x50},
-
-       {0x05, 0x01, 0xc0},
-       {0x05, 0x10, 0xcb},
-       {0x05, 0x40, 0xc1},
-       {0x05, 0x04, 0xc2},
-       {0x05, 0x00, 0xca},
-       {0x05, 0x40, 0xc1},
-       {0x05, 0x09, 0xc2},
-       {0x05, 0x00, 0xca},
-       {0x05, 0xc0, 0xc1},
-       {0x05, 0x09, 0xc2},
-       {0x05, 0x00, 0xca},
-       {0x05, 0x40, 0xc1},
-       {0x05, 0x59, 0xc2},
-       {0x05, 0x00, 0xca},
-       {0x04, 0x00, 0x01},
-       {0x05, 0x80, 0xc1},
-       {0x05, 0xec, 0xc2},
-       {0x05, 0x0, 0xca},
-
-       {0x06, 0x02, 0x57},
-       {0x06, 0x01, 0x58},
-       {0x06, 0x15, 0x59},
-       {0x06, 0x0a, 0x5a},
-       {0x06, 0x01, 0x57},
-       {0x06, 0x8a, 0x03},
-       {0x06, 0x0a, 0x6c},
-       {0x06, 0x30, 0x01},
-       {0x06, 0x20, 0x02},
-       {0x06, 0x00, 0x03},
-
-       {0x05, 0x8c, 0x25},
-
-       {0x06, 0x4d, 0x51},             /* maybe saturation (4d) */
-       {0x06, 0x84, 0x53},             /* making green (84) */
-       {0x06, 0x00, 0x57},             /* sharpness (1) */
-       {0x06, 0x18, 0x08},
-       {0x06, 0xfc, 0x09},
-       {0x06, 0xfc, 0x0a},
-       {0x06, 0xfc, 0x0b},
-       {0x06, 0x18, 0x0c},             /* maybe hue (18) */
-       {0x06, 0xfc, 0x0d},
-       {0x06, 0xfc, 0x0e},
-       {0x06, 0xfc, 0x0f},
-       {0x06, 0x18, 0x10},             /* maybe contrast (18) */
-
-       {0x05, 0x01, 0x02},
-
-       {0x04, 0x00, 0x08},             /* compression */
-       {0x04, 0x12, 0x09},
-       {0x04, 0x21, 0x0a},
-       {0x04, 0x10, 0x0b},
-       {0x04, 0x21, 0x0c},
-       {0x04, 0x1d, 0x00},             /* imagetype (1d) */
-       {0x04, 0x41, 0x01},             /* hardware snapcontrol */
-
-       {0x04, 0x00, 0x04},
-       {0x04, 0x00, 0x05},
-       {0x04, 0x10, 0x06},
-       {0x04, 0x10, 0x07},
-       {0x04, 0x40, 0x06},
-       {0x04, 0x40, 0x07},
-       {0x04, 0x00, 0x04},
-       {0x04, 0x00, 0x05},
-
-       {0x06, 0x1c, 0x17},
-       {0x06, 0xe2, 0x19},
-       {0x06, 0x1c, 0x1b},
-       {0x06, 0xe2, 0x1d},
-       {0x06, 0x5f, 0x1f},
-       {0x06, 0x32, 0x20},
-
-       {0x05, initial_brightness >> 6, 0x00},
-       {0x05, (initial_brightness << 2) & 0xff, 0x01},
-       {0x05, 0x06, 0xc1},
-       {0x05, 0x58, 0xc2},
-       {0x05, 0x00, 0xca},
-       {0x05, 0x00, 0x11},
-       {}
-};
-
-static int reg_write(struct usb_device *dev,
-                    u16 req, u16 index, u16 value)
-{
-       int ret;
-
-       ret = usb_control_msg(dev,
-                       usb_sndctrlpipe(dev, 0),
-                       req,
-                       USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index, NULL, 0, 500);
-       PDEBUG(D_USBO, "reg write: 0x%02x,0x%02x:0x%02x, %d",
-               req, index, value, ret);
-       if (ret < 0)
-               pr_err("reg write: error %d\n", ret);
-       return ret;
-}
-
-/* returns: negative is error, pos or zero is data */
-static int reg_read(struct gspca_dev *gspca_dev,
-                       u16 req,        /* bRequest */
-                       u16 index)      /* wIndex */
-{
-       int ret;
-
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       req,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,                      /* value */
-                       index,
-                       gspca_dev->usb_buf, 2,
-                       500);                   /* timeout */
-       if (ret < 0)
-               return ret;
-       return (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
-}
-
-static int write_vector(struct gspca_dev *gspca_dev,
-                       const u8 data[][3])
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret, i = 0;
-
-       while (data[i][0] != 0) {
-               ret = reg_write(dev, data[i][0], data[i][2], data[i][1]);
-               if (ret < 0)
-                       return ret;
-               i++;
-       }
-       return 0;
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-
-       cam = &gspca_dev->cam;
-       cam->cam_mode = vga_mode;
-       sd->subtype = id->driver_info;
-       if (sd->subtype != IntelPCCameraPro)
-               cam->nmodes = ARRAY_SIZE(vga_mode);
-       else                    /* no 640x480 for IntelPCCameraPro */
-               cam->nmodes = ARRAY_SIZE(vga_mode) - 1;
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (write_vector(gspca_dev,
-                        sd->subtype == Nxultra
-                               ? spca505b_init_data
-                               : spca505_init_data))
-               return -EIO;
-       return 0;
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
-{
-       reg_write(gspca_dev->dev, 0x05, 0x00, (255 - brightness) >> 6);
-       reg_write(gspca_dev->dev, 0x05, 0x01, (255 - brightness) << 2);
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct usb_device *dev = gspca_dev->dev;
-       int ret, mode;
-       static u8 mode_tb[][3] = {
-       /*        r00   r06   r07       */
-               {0x00, 0x10, 0x10},     /* 640x480 */
-               {0x01, 0x1a, 0x1a},     /* 352x288 */
-               {0x02, 0x1c, 0x1d},     /* 320x240 */
-               {0x04, 0x34, 0x34},     /* 176x144 */
-               {0x05, 0x40, 0x40}      /* 160x120 */
-       };
-
-       if (sd->subtype == Nxultra)
-               write_vector(gspca_dev, spca505b_open_data_ccd);
-       else
-               write_vector(gspca_dev, spca505_open_data_ccd);
-       ret = reg_read(gspca_dev, 0x06, 0x16);
-
-       if (ret < 0) {
-               PDEBUG(D_ERR|D_CONF,
-                      "register read failed err: %d",
-                      ret);
-               return ret;
-       }
-       if (ret != 0x0101) {
-               pr_err("After vector read returns 0x%04x should be 0x0101\n",
-                      ret);
-       }
-
-       ret = reg_write(gspca_dev->dev, 0x06, 0x16, 0x0a);
-       if (ret < 0)
-               return ret;
-       reg_write(gspca_dev->dev, 0x05, 0xc2, 0x12);
-
-       /* necessary because without it we can see stream
-        * only once after loading module */
-       /* stopping usb registers Tomasz change */
-       reg_write(dev, 0x02, 0x00, 0x00);
-
-       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
-       reg_write(dev, SPCA50X_REG_COMPRESS, 0x00, mode_tb[mode][0]);
-       reg_write(dev, SPCA50X_REG_COMPRESS, 0x06, mode_tb[mode][1]);
-       reg_write(dev, SPCA50X_REG_COMPRESS, 0x07, mode_tb[mode][2]);
-
-       return reg_write(dev, SPCA50X_REG_USB,
-                        SPCA50X_USB_CTRL,
-                        SPCA50X_CUSB_ENABLE);
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       /* Disable ISO packet machine */
-       reg_write(gspca_dev->dev, 0x02, 0x00, 0x00);
-}
-
-/* called on streamoff with alt 0 and on disconnect */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       if (!gspca_dev->present)
-               return;
-
-       /* This maybe reset or power control */
-       reg_write(gspca_dev->dev, 0x03, 0x03, 0x20);
-       reg_write(gspca_dev->dev, 0x03, 0x01, 0x00);
-       reg_write(gspca_dev->dev, 0x03, 0x00, 0x01);
-       reg_write(gspca_dev->dev, 0x05, 0x10, 0x01);
-       reg_write(gspca_dev->dev, 0x05, 0x11, 0x0f);
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,                       /* isoc packet */
-                       int len)                        /* iso packet length */
-{
-       switch (data[0]) {
-       case 0:                         /* start of frame */
-               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-               data += SPCA50X_OFFSET_DATA;
-               len -= SPCA50X_OFFSET_DATA;
-               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
-               break;
-       case 0xff:                      /* drop */
-               break;
-       default:
-               data += 1;
-               len -= 1;
-               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-               break;
-       }
-}
-
-static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct gspca_dev *gspca_dev =
-               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
-
-       gspca_dev->usb_err = 0;
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 5);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
-
-       if (hdl->error) {
-               pr_err("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_controls = sd_init_controls,
-       .init = sd_init,
-       .start = sd_start,
-       .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x041e, 0x401d), .driver_info = Nxultra},
-       {USB_DEVICE(0x0733, 0x0430), .driver_info = IntelPCCameraPro},
-/*fixme: may be UsbGrabberPV321 BRIDGE_SPCA506 SENSOR_SAA7113 */
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c
deleted file mode 100644 (file)
index 969bb5a..0000000
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * SPCA506 chip based cameras function
- * M Xhaard 15/04/2004 based on different work Mark Taylor and others
- * and my own snoopy file on a pv-321c donate by a german compagny
- *                "Firma Frank Gmbh" from  Saarbruecken
- *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define MODULE_NAME "spca506"
-
-#include "gspca.h"
-
-MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
-MODULE_DESCRIPTION("GSPCA/SPCA506 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       char norme;
-       char channel;
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {160, 120, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 5},
-       {176, 144, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 4},
-       {320, 240, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2},
-       {352, 288, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_SPCA505, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-#define SPCA50X_OFFSET_DATA 10
-
-#define SAA7113_bright 0x0a    /* defaults 0x80 */
-#define SAA7113_contrast 0x0b  /* defaults 0x47 */
-#define SAA7113_saturation 0x0c        /* defaults 0x40 */
-#define SAA7113_hue 0x0d       /* defaults 0x00 */
-#define SAA7113_I2C_BASE_WRITE 0x4a
-
-/* read 'len' bytes to gspca_dev->usb_buf */
-static void reg_r(struct gspca_dev *gspca_dev,
-                 __u16 req,
-                 __u16 index,
-                 __u16 length)
-{
-       usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       req,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,              /* value */
-                       index, gspca_dev->usb_buf, length,
-                       500);
-}
-
-static void reg_w(struct usb_device *dev,
-                 __u16 req,
-                 __u16 value,
-                 __u16 index)
-{
-       usb_control_msg(dev,
-                       usb_sndctrlpipe(dev, 0),
-                       req,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index,
-                       NULL, 0, 500);
-}
-
-static void spca506_Initi2c(struct gspca_dev *gspca_dev)
-{
-       reg_w(gspca_dev->dev, 0x07, SAA7113_I2C_BASE_WRITE, 0x0004);
-}
-
-static void spca506_WriteI2c(struct gspca_dev *gspca_dev, __u16 valeur,
-                            __u16 reg)
-{
-       int retry = 60;
-
-       reg_w(gspca_dev->dev, 0x07, reg, 0x0001);
-       reg_w(gspca_dev->dev, 0x07, valeur, 0x0000);
-       while (retry--) {
-               reg_r(gspca_dev, 0x07, 0x0003, 2);
-               if ((gspca_dev->usb_buf[0] | gspca_dev->usb_buf[1]) == 0x00)
-                       break;
-       }
-}
-
-static void spca506_SetNormeInput(struct gspca_dev *gspca_dev,
-                                __u16 norme,
-                                __u16 channel)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-/* fixme: check if channel == 0..3 and 6..9 (8 values) */
-       __u8 setbit0 = 0x00;
-       __u8 setbit1 = 0x00;
-       __u8 videomask = 0x00;
-
-       PDEBUG(D_STREAM, "** Open Set Norme **");
-       spca506_Initi2c(gspca_dev);
-       /* NTSC bit0 -> 1(525 l) PAL SECAM bit0 -> 0 (625 l) */
-       /* Composite channel bit1 -> 1 S-video bit 1 -> 0 */
-       /* and exclude SAA7113 reserved channel set default 0 otherwise */
-       if (norme & V4L2_STD_NTSC)
-               setbit0 = 0x01;
-       if (channel == 4 || channel == 5 || channel > 9)
-               channel = 0;
-       if (channel < 4)
-               setbit1 = 0x02;
-       videomask = (0x48 | setbit0 | setbit1);
-       reg_w(gspca_dev->dev, 0x08, videomask, 0x0000);
-       spca506_WriteI2c(gspca_dev, (0xc0 | (channel & 0x0F)), 0x02);
-
-       if (norme & V4L2_STD_NTSC)
-               spca506_WriteI2c(gspca_dev, 0x33, 0x0e);
-                                       /* Chrominance Control NTSC N */
-       else if (norme & V4L2_STD_SECAM)
-               spca506_WriteI2c(gspca_dev, 0x53, 0x0e);
-                                       /* Chrominance Control SECAM */
-       else
-               spca506_WriteI2c(gspca_dev, 0x03, 0x0e);
-                                       /* Chrominance Control PAL BGHIV */
-
-       sd->norme = norme;
-       sd->channel = channel;
-       PDEBUG(D_STREAM, "Set Video Byte to 0x%2x", videomask);
-       PDEBUG(D_STREAM, "Set Norme: %08x Channel %d", norme, channel);
-}
-
-static void spca506_GetNormeInput(struct gspca_dev *gspca_dev,
-                                 __u16 *norme, __u16 *channel)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* Read the register is not so good value change so
-          we use your own copy in spca50x struct */
-       *norme = sd->norme;
-       *channel = sd->channel;
-       PDEBUG(D_STREAM, "Get Norme: %d Channel %d", *norme, *channel);
-}
-
-static void spca506_Setsize(struct gspca_dev *gspca_dev, __u16 code,
-                           __u16 xmult, __u16 ymult)
-{
-       struct usb_device *dev = gspca_dev->dev;
-
-       PDEBUG(D_STREAM, "** SetSize **");
-       reg_w(dev, 0x04, (0x18 | (code & 0x07)), 0x0000);
-       /* Soft snap 0x40 Hard 0x41 */
-       reg_w(dev, 0x04, 0x41, 0x0001);
-       reg_w(dev, 0x04, 0x00, 0x0002);
-       /* reserved */
-       reg_w(dev, 0x04, 0x00, 0x0003);
-
-       /* reserved */
-       reg_w(dev, 0x04, 0x00, 0x0004);
-       /* reserved */
-       reg_w(dev, 0x04, 0x01, 0x0005);
-       /* reserced */
-       reg_w(dev, 0x04, xmult, 0x0006);
-       /* reserved */
-       reg_w(dev, 0x04, ymult, 0x0007);
-       /* compression 1 */
-       reg_w(dev, 0x04, 0x00, 0x0008);
-       /* T=64 -> 2 */
-       reg_w(dev, 0x04, 0x00, 0x0009);
-       /* threshold2D */
-       reg_w(dev, 0x04, 0x21, 0x000a);
-       /* quantization */
-       reg_w(dev, 0x04, 0x00, 0x000b);
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct cam *cam;
-
-       cam = &gspca_dev->cam;
-       cam->cam_mode = vga_mode;
-       cam->nmodes = ARRAY_SIZE(vga_mode);
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct usb_device *dev = gspca_dev->dev;
-
-       reg_w(dev, 0x03, 0x00, 0x0004);
-       reg_w(dev, 0x03, 0xFF, 0x0003);
-       reg_w(dev, 0x03, 0x00, 0x0000);
-       reg_w(dev, 0x03, 0x1c, 0x0001);
-       reg_w(dev, 0x03, 0x18, 0x0001);
-       /* Init on PAL and composite input0 */
-       spca506_SetNormeInput(gspca_dev, 0, 0);
-       reg_w(dev, 0x03, 0x1c, 0x0001);
-       reg_w(dev, 0x03, 0x18, 0x0001);
-       reg_w(dev, 0x05, 0x00, 0x0000);
-       reg_w(dev, 0x05, 0xef, 0x0001);
-       reg_w(dev, 0x05, 0x00, 0x00c1);
-       reg_w(dev, 0x05, 0x00, 0x00c2);
-       reg_w(dev, 0x06, 0x18, 0x0002);
-       reg_w(dev, 0x06, 0xf5, 0x0011);
-       reg_w(dev, 0x06, 0x02, 0x0012);
-       reg_w(dev, 0x06, 0xfb, 0x0013);
-       reg_w(dev, 0x06, 0x00, 0x0014);
-       reg_w(dev, 0x06, 0xa4, 0x0051);
-       reg_w(dev, 0x06, 0x40, 0x0052);
-       reg_w(dev, 0x06, 0x71, 0x0053);
-       reg_w(dev, 0x06, 0x40, 0x0054);
-       /************************************************/
-       reg_w(dev, 0x03, 0x00, 0x0004);
-       reg_w(dev, 0x03, 0x00, 0x0003);
-       reg_w(dev, 0x03, 0x00, 0x0004);
-       reg_w(dev, 0x03, 0xFF, 0x0003);
-       reg_w(dev, 0x02, 0x00, 0x0000);
-       reg_w(dev, 0x03, 0x60, 0x0000);
-       reg_w(dev, 0x03, 0x18, 0x0001);
-       /* for a better reading mx :)     */
-       /*sdca506_WriteI2c(value,register) */
-       spca506_Initi2c(gspca_dev);
-       spca506_WriteI2c(gspca_dev, 0x08, 0x01);
-       spca506_WriteI2c(gspca_dev, 0xc0, 0x02);
-                                               /* input composite video */
-       spca506_WriteI2c(gspca_dev, 0x33, 0x03);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x04);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x05);
-       spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
-       spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
-       spca506_WriteI2c(gspca_dev, 0x98, 0x08);
-       spca506_WriteI2c(gspca_dev, 0x03, 0x09);
-       spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
-       spca506_WriteI2c(gspca_dev, 0x47, 0x0b);
-       spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
-       spca506_WriteI2c(gspca_dev, 0x03, 0x0e);        /* Chroma Pal adjust */
-       spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x10);
-       spca506_WriteI2c(gspca_dev, 0x0c, 0x11);
-       spca506_WriteI2c(gspca_dev, 0xb8, 0x12);
-       spca506_WriteI2c(gspca_dev, 0x01, 0x13);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x14);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x15);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x16);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x17);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x18);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x19);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
-       spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
-       spca506_WriteI2c(gspca_dev, 0x02, 0x40);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x41);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x42);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x43);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x44);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x45);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x46);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x47);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x48);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x49);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x50);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x51);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x52);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x53);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x54);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x55);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x56);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x57);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x58);
-       spca506_WriteI2c(gspca_dev, 0x54, 0x59);
-       spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
-       spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x60);
-       spca506_WriteI2c(gspca_dev, 0x05, 0x61);
-       spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
-       PDEBUG(D_STREAM, "** Close Init *");
-       return 0;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       __u16 norme;
-       __u16 channel;
-
-       /**************************************/
-       reg_w(dev, 0x03, 0x00, 0x0004);
-       reg_w(dev, 0x03, 0x00, 0x0003);
-       reg_w(dev, 0x03, 0x00, 0x0004);
-       reg_w(dev, 0x03, 0xFF, 0x0003);
-       reg_w(dev, 0x02, 0x00, 0x0000);
-       reg_w(dev, 0x03, 0x60, 0x0000);
-       reg_w(dev, 0x03, 0x18, 0x0001);
-
-       /*sdca506_WriteI2c(value,register) */
-       spca506_Initi2c(gspca_dev);
-       spca506_WriteI2c(gspca_dev, 0x08, 0x01);        /* Increment Delay */
-/*     spca506_WriteI2c(gspca_dev, 0xc0, 0x02); * Analog Input Control 1 */
-       spca506_WriteI2c(gspca_dev, 0x33, 0x03);
-                                               /* Analog Input Control 2 */
-       spca506_WriteI2c(gspca_dev, 0x00, 0x04);
-                                               /* Analog Input Control 3 */
-       spca506_WriteI2c(gspca_dev, 0x00, 0x05);
-                                               /* Analog Input Control 4 */
-       spca506_WriteI2c(gspca_dev, 0x0d, 0x06);
-                                       /* Horizontal Sync Start 0xe9-0x0d */
-       spca506_WriteI2c(gspca_dev, 0xf0, 0x07);
-                                       /* Horizontal Sync Stop  0x0d-0xf0 */
-
-       spca506_WriteI2c(gspca_dev, 0x98, 0x08);        /* Sync Control */
-/*             Defaults value                  */
-       spca506_WriteI2c(gspca_dev, 0x03, 0x09);        /* Luminance Control */
-       spca506_WriteI2c(gspca_dev, 0x80, 0x0a);
-                                               /* Luminance Brightness */
-       spca506_WriteI2c(gspca_dev, 0x47, 0x0b);        /* Luminance Contrast */
-       spca506_WriteI2c(gspca_dev, 0x48, 0x0c);
-                                               /* Chrominance Saturation */
-       spca506_WriteI2c(gspca_dev, 0x00, 0x0d);
-                                               /* Chrominance Hue Control */
-       spca506_WriteI2c(gspca_dev, 0x2a, 0x0f);
-                                               /* Chrominance Gain Control */
-       /**************************************/
-       spca506_WriteI2c(gspca_dev, 0x00, 0x10);
-                                               /* Format/Delay Control */
-       spca506_WriteI2c(gspca_dev, 0x0c, 0x11);        /* Output Control 1 */
-       spca506_WriteI2c(gspca_dev, 0xb8, 0x12);        /* Output Control 2 */
-       spca506_WriteI2c(gspca_dev, 0x01, 0x13);        /* Output Control 3 */
-       spca506_WriteI2c(gspca_dev, 0x00, 0x14);        /* reserved */
-       spca506_WriteI2c(gspca_dev, 0x00, 0x15);        /* VGATE START */
-       spca506_WriteI2c(gspca_dev, 0x00, 0x16);        /* VGATE STOP */
-       spca506_WriteI2c(gspca_dev, 0x00, 0x17);    /* VGATE Control (MSB) */
-       spca506_WriteI2c(gspca_dev, 0x00, 0x18);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x19);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x1a);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x1b);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x1c);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x1d);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x1e);
-       spca506_WriteI2c(gspca_dev, 0xa1, 0x1f);
-       spca506_WriteI2c(gspca_dev, 0x02, 0x40);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x41);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x42);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x43);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x44);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x45);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x46);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x47);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x48);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x49);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x4a);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x4b);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x4c);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x4d);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x4e);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x4f);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x50);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x51);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x52);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x53);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x54);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x55);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x56);
-       spca506_WriteI2c(gspca_dev, 0xff, 0x57);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x58);
-       spca506_WriteI2c(gspca_dev, 0x54, 0x59);
-       spca506_WriteI2c(gspca_dev, 0x07, 0x5a);
-       spca506_WriteI2c(gspca_dev, 0x83, 0x5b);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x5c);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x5d);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x5e);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x5f);
-       spca506_WriteI2c(gspca_dev, 0x00, 0x60);
-       spca506_WriteI2c(gspca_dev, 0x05, 0x61);
-       spca506_WriteI2c(gspca_dev, 0x9f, 0x62);
-       /**************************************/
-       reg_w(dev, 0x05, 0x00, 0x0003);
-       reg_w(dev, 0x05, 0x00, 0x0004);
-       reg_w(dev, 0x03, 0x10, 0x0001);
-       reg_w(dev, 0x03, 0x78, 0x0000);
-       switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
-       case 0:
-               spca506_Setsize(gspca_dev, 0, 0x10, 0x10);
-               break;
-       case 1:
-               spca506_Setsize(gspca_dev, 1, 0x1a, 0x1a);
-               break;
-       case 2:
-               spca506_Setsize(gspca_dev, 2, 0x1c, 0x1c);
-               break;
-       case 4:
-               spca506_Setsize(gspca_dev, 4, 0x34, 0x34);
-               break;
-       default:
-/*     case 5: */
-               spca506_Setsize(gspca_dev, 5, 0x40, 0x40);
-               break;
-       }
-
-       /* compress setting and size */
-       /* set i2c luma */
-       reg_w(dev, 0x02, 0x01, 0x0000);
-       reg_w(dev, 0x03, 0x12, 0x0000);
-       reg_r(gspca_dev, 0x04, 0x0001, 2);
-       PDEBUG(D_STREAM, "webcam started");
-       spca506_GetNormeInput(gspca_dev, &norme, &channel);
-       spca506_SetNormeInput(gspca_dev, norme, channel);
-       return 0;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct usb_device *dev = gspca_dev->dev;
-
-       reg_w(dev, 0x02, 0x00, 0x0000);
-       reg_w(dev, 0x03, 0x00, 0x0004);
-       reg_w(dev, 0x03, 0x00, 0x0003);
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,                       /* isoc packet */
-                       int len)                        /* iso packet length */
-{
-       switch (data[0]) {
-       case 0:                         /* start of frame */
-               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-               data += SPCA50X_OFFSET_DATA;
-               len -= SPCA50X_OFFSET_DATA;
-               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
-               break;
-       case 0xff:                      /* drop */
-/*             gspca_dev->last_packet_type = DISCARD_PACKET; */
-               break;
-       default:
-               data += 1;
-               len -= 1;
-               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-               break;
-       }
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       spca506_Initi2c(gspca_dev);
-       spca506_WriteI2c(gspca_dev, val, SAA7113_bright);
-       spca506_WriteI2c(gspca_dev, 0x01, 0x09);
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
-{
-       spca506_Initi2c(gspca_dev);
-       spca506_WriteI2c(gspca_dev, val, SAA7113_contrast);
-       spca506_WriteI2c(gspca_dev, 0x01, 0x09);
-}
-
-static void setcolors(struct gspca_dev *gspca_dev, s32 val)
-{
-       spca506_Initi2c(gspca_dev);
-       spca506_WriteI2c(gspca_dev, val, SAA7113_saturation);
-       spca506_WriteI2c(gspca_dev, 0x01, 0x09);
-}
-
-static void sethue(struct gspca_dev *gspca_dev, s32 val)
-{
-       spca506_Initi2c(gspca_dev);
-       spca506_WriteI2c(gspca_dev, val, SAA7113_hue);
-       spca506_WriteI2c(gspca_dev, 0x01, 0x09);
-}
-
-static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct gspca_dev *gspca_dev =
-               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
-
-       gspca_dev->usb_err = 0;
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               setcolors(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_HUE:
-               sethue(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 4);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 255, 1, 0x47);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 255, 1, 0x40);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_HUE, 0, 255, 1, 0);
-
-       if (hdl->error) {
-               pr_err("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,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] __devinitconst = {
-       {USB_DEVICE(0x06e1, 0xa190)},
-/*fixme: may be IntelPCCameraPro BRIDGE_SPCA505
-       {USB_DEVICE(0x0733, 0x0430)}, */
-       {USB_DEVICE(0x0734, 0x043b)},
-       {USB_DEVICE(0x99fa, 0x8988)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-static int __devinit 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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c
deleted file mode 100644 (file)
index 1286b41..0000000
+++ /dev/null
@@ -1,1540 +0,0 @@
-/*
- * SPCA508 chip based cameras subdriver
- *
- * Copyright (C) 2009 Jean-Francois Moine <http://moinejf.free.fr>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "spca508"
-
-#include "gspca.h"
-
-MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
-MODULE_DESCRIPTION("GSPCA/SPCA508 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;             /* !! must be the first item */
-
-       u8 subtype;
-#define CreativeVista 0
-#define HamaUSBSightcam 1
-#define HamaUSBSightcam2 2
-#define IntelEasyPCCamera 3
-#define MicroInnovationIC200 4
-#define ViewQuestVQ110 5
-};
-
-static const struct v4l2_pix_format sif_mode[] = {
-       {160, 120, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 3},
-       {176, 144, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2},
-       {320, 240, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {352, 288, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 3 / 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-/* Frame packet header offsets for the spca508 */
-#define SPCA508_OFFSET_DATA 37
-
-/*
- * Initialization data: this is the first set-up data written to the
- * device (before the open data).
- */
-static const u16 spca508_init_data[][2] = {
-       {0x0000, 0x870b},
-
-       {0x0020, 0x8112},       /* Video drop enable, ISO streaming disable */
-       {0x0003, 0x8111},       /* Reset compression & memory */
-       {0x0000, 0x8110},       /* Disable all outputs */
-       /* READ {0x0000, 0x8114} -> 0000: 00  */
-       {0x0000, 0x8114},       /* SW GPIO data */
-       {0x0008, 0x8110},       /* Enable charge pump output */
-       {0x0002, 0x8116},       /* 200 kHz pump clock */
-       /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE:) */
-       {0x0003, 0x8111},       /* Reset compression & memory */
-       {0x0000, 0x8111},       /* Normal mode (not reset) */
-       {0x0098, 0x8110},
-               /* Enable charge pump output, sync.serial,external 2x clock */
-       {0x000d, 0x8114},       /* SW GPIO data */
-       {0x0002, 0x8116},       /* 200 kHz pump clock */
-       {0x0020, 0x8112},       /* Video drop enable, ISO streaming disable */
-/* --------------------------------------- */
-       {0x000f, 0x8402},       /* memory bank */
-       {0x0000, 0x8403},       /* ... address */
-/* --------------------------------------- */
-/* 0x88__ is Synchronous Serial Interface. */
-/* TBD: This table could be expressed more compactly */
-/* using spca508_write_i2c_vector(). */
-/* TBD: Should see if the values in spca50x_i2c_data */
-/* would work with the VQ110 instead of the values */
-/* below. */
-       {0x00c0, 0x8804},       /* SSI slave addr */
-       {0x0008, 0x8802},       /* 375 Khz SSI clock */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},       /* 375 Khz SSI clock */
-       {0x0012, 0x8801},       /* SSI reg addr */
-       {0x0080, 0x8800},       /* SSI data to write */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},       /* 375 Khz SSI clock */
-       {0x0012, 0x8801},       /* SSI reg addr */
-       {0x0000, 0x8800},       /* SSI data to write */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},       /* 375 Khz SSI clock */
-       {0x0011, 0x8801},       /* SSI reg addr */
-       {0x0040, 0x8800},       /* SSI data to write */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0013, 0x8801},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0014, 0x8801},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0015, 0x8801},
-       {0x0001, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0016, 0x8801},
-       {0x0003, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0017, 0x8801},
-       {0x0036, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0018, 0x8801},
-       {0x00ec, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x001a, 0x8801},
-       {0x0094, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x001b, 0x8801},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0027, 0x8801},
-       {0x00a2, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0028, 0x8801},
-       {0x0040, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x002a, 0x8801},
-       {0x0084, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00 */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x002b, 0x8801},
-       {0x00a8, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x002c, 0x8801},
-       {0x00fe, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x002d, 0x8801},
-       {0x0003, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0038, 0x8801},
-       {0x0083, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0033, 0x8801},
-       {0x0081, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0034, 0x8801},
-       {0x004a, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0039, 0x8801},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0010, 0x8801},
-       {0x00a8, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0006, 0x8801},
-       {0x0058, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00 */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0000, 0x8801},
-       {0x0004, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0040, 0x8801},
-       {0x0080, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0041, 0x8801},
-       {0x000c, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0042, 0x8801},
-       {0x000c, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0043, 0x8801},
-       {0x0028, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0044, 0x8801},
-       {0x0080, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0045, 0x8801},
-       {0x0020, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0046, 0x8801},
-       {0x0020, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0047, 0x8801},
-       {0x0080, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0048, 0x8801},
-       {0x004c, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x0049, 0x8801},
-       {0x0084, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x004a, 0x8801},
-       {0x0084, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x0008, 0x8802},
-       {0x004b, 0x8801},
-       {0x0084, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* --------------------------------------- */
-       {0x0012, 0x8700},       /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
-       {0x0000, 0x8701},       /* CKx1 clock delay adj */
-       {0x0000, 0x8701},       /* CKx1 clock delay adj */
-       {0x0001, 0x870c},       /* CKOx2 output */
-       /* --------------------------------------- */
-       {0x0080, 0x8600},       /* Line memory read counter (L) */
-       {0x0001, 0x8606},       /* reserved */
-       {0x0064, 0x8607},       /* Line memory read counter (H) 0x6480=25,728 */
-       {0x002a, 0x8601},       /* CDSP sharp interpolation mode,
-        *                      line sel for color sep, edge enhance enab */
-       {0x0000, 0x8602},       /* optical black level for user settng = 0 */
-       {0x0080, 0x8600},       /* Line memory read counter (L) */
-       {0x000a, 0x8603},       /* optical black level calc mode:
-                                * auto; optical black offset = 10 */
-       {0x00df, 0x865b},       /* Horiz offset for valid pixels (L)=0xdf */
-       {0x0012, 0x865c},       /* Vert offset for valid lines (L)=0x12 */
-
-/* The following two lines seem to be the "wrong" resolution. */
-/* But perhaps these indicate the actual size of the sensor */
-/* rather than the size of the current video mode. */
-       {0x0058, 0x865d},       /* Horiz valid pixels (*4) (L) = 352 */
-       {0x0048, 0x865e},       /* Vert valid lines (*4) (L) = 288 */
-
-       {0x0015, 0x8608},       /* A11 Coef ... */
-       {0x0030, 0x8609},
-       {0x00fb, 0x860a},
-       {0x003e, 0x860b},
-       {0x00ce, 0x860c},
-       {0x00f4, 0x860d},
-       {0x00eb, 0x860e},
-       {0x00dc, 0x860f},
-       {0x0039, 0x8610},
-       {0x0001, 0x8611},       /* R offset for white balance ... */
-       {0x0000, 0x8612},
-       {0x0001, 0x8613},
-       {0x0000, 0x8614},
-       {0x005b, 0x8651},       /* R gain for white balance ... */
-       {0x0040, 0x8652},
-       {0x0060, 0x8653},
-       {0x0040, 0x8654},
-       {0x0000, 0x8655},
-       {0x0001, 0x863f},       /* Fixed gamma correction enable, USB control,
-                                * lum filter disable, lum noise clip disable */
-       {0x00a1, 0x8656},       /* Window1 size 256x256, Windows2 size 64x64,
-                                * gamma look-up disable,
-                                * new edge enhancement enable */
-       {0x0018, 0x8657},       /* Edge gain high thresh */
-       {0x0020, 0x8658},       /* Edge gain low thresh */
-       {0x000a, 0x8659},       /* Edge bandwidth high threshold */
-       {0x0005, 0x865a},       /* Edge bandwidth low threshold */
-       /* -------------------------------- */
-       {0x0030, 0x8112},       /* Video drop enable, ISO streaming enable */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0xa908, 0x8802},
-       {0x0034, 0x8801},       /* SSI reg addr */
-       {0x00ca, 0x8800},
-       /* SSI data to write */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0x1f08, 0x8802},
-       {0x0006, 0x8801},
-       {0x0080, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-/* ----- Read back coefs we wrote earlier. */
-       /* READ { 0x0000, 0x8608 } -> 0000: 15  */
-       /* READ { 0x0000, 0x8609 } -> 0000: 30  */
-       /* READ { 0x0000, 0x860a } -> 0000: fb  */
-       /* READ { 0x0000, 0x860b } -> 0000: 3e  */
-       /* READ { 0x0000, 0x860c } -> 0000: ce  */
-       /* READ { 0x0000, 0x860d } -> 0000: f4  */
-       /* READ { 0x0000, 0x860e } -> 0000: eb  */
-       /* READ { 0x0000, 0x860f } -> 0000: dc  */
-       /* READ { 0x0000, 0x8610 } -> 0000: 39  */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 08  */
-       {0xb008, 0x8802},
-       {0x0006, 0x8801},
-       {0x007d, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-
-       /* This chunk is seemingly redundant with */
-       /* earlier commands (A11 Coef...), but if I disable it, */
-       /* the image appears too dark.  Maybe there was some kind of */
-       /* reset since the earlier commands, so this is necessary again. */
-       {0x0015, 0x8608},
-       {0x0030, 0x8609},
-       {0xfffb, 0x860a},
-       {0x003e, 0x860b},
-       {0xffce, 0x860c},
-       {0xfff4, 0x860d},
-       {0xffeb, 0x860e},
-       {0xffdc, 0x860f},
-       {0x0039, 0x8610},
-       {0x0018, 0x8657},
-
-       {0x0000, 0x8508},       /* Disable compression. */
-       /* Previous line was:
-       {0x0021, 0x8508},        * Enable compression. */
-       {0x0032, 0x850b},       /* compression stuff */
-       {0x0003, 0x8509},       /* compression stuff */
-       {0x0011, 0x850a},       /* compression stuff */
-       {0x0021, 0x850d},       /* compression stuff */
-       {0x0010, 0x850c},       /* compression stuff */
-       {0x0003, 0x8500},       /* *** Video mode: 160x120 */
-       {0x0001, 0x8501},       /* Hardware-dominated snap control */
-       {0x0061, 0x8656},       /* Window1 size 128x128, Windows2 size 128x128,
-                                * gamma look-up disable,
-                                * new edge enhancement enable */
-       {0x0018, 0x8617},       /* Window1 start X (*2) */
-       {0x0008, 0x8618},       /* Window1 start Y (*2) */
-       {0x0061, 0x8656},       /* Window1 size 128x128, Windows2 size 128x128,
-                                * gamma look-up disable,
-                                * new edge enhancement enable */
-       {0x0058, 0x8619},       /* Window2 start X (*2) */
-       {0x0008, 0x861a},       /* Window2 start Y (*2) */
-       {0x00ff, 0x8615},       /* High lum thresh for white balance */
-       {0x0000, 0x8616},       /* Low lum thresh for white balance */
-       {0x0012, 0x8700},       /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
-       {0x0012, 0x8700},       /* Clock speed 48Mhz/(2+2)/2= 6 Mhz */
-       /* READ { 0x0000, 0x8656 } -> 0000: 61  */
-       {0x0028, 0x8802},    /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 28  */
-       {0x1f28, 0x8802},    /* 375 Khz SSI clock, SSI r/w sync with VSYNC */
-       {0x0010, 0x8801},       /* SSI reg addr */
-       {0x003e, 0x8800},       /* SSI data to write */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       {0x0028, 0x8802},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 28  */
-       {0x1f28, 0x8802},
-       {0x0000, 0x8801},
-       {0x001f, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       {0x0001, 0x8602},    /* optical black level for user settning = 1 */
-
-       /* Original: */
-       {0x0023, 0x8700},       /* Clock speed 48Mhz/(3+2)/4= 2.4 Mhz */
-       {0x000f, 0x8602},    /* optical black level for user settning = 15 */
-
-       {0x0028, 0x8802},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 28  */
-       {0x1f28, 0x8802},
-       {0x0010, 0x8801},
-       {0x007b, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       {0x002f, 0x8651},       /* R gain for white balance ... */
-       {0x0080, 0x8653},
-       /* READ { 0x0000, 0x8655 } -> 0000: 00  */
-       {0x0000, 0x8655},
-
-       {0x0030, 0x8112},       /* Video drop enable, ISO streaming enable */
-       {0x0020, 0x8112},       /* Video drop enable, ISO streaming disable */
-       /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */
-       {}
-};
-
-/*
- * Initialization data for Intel EasyPC Camera CS110
- */
-static const u16 spca508cs110_init_data[][2] = {
-       {0x0000, 0x870b},       /* Reset CTL3 */
-       {0x0003, 0x8111},       /* Soft Reset compression, memory, TG & CDSP */
-       {0x0000, 0x8111},       /* Normal operation on reset */
-       {0x0090, 0x8110},
-                /* External Clock 2x & Synchronous Serial Interface Output */
-       {0x0020, 0x8112},       /* Video Drop packet enable */
-       {0x0000, 0x8114},       /* Software GPIO output data */
-       {0x0001, 0x8114},
-       {0x0001, 0x8114},
-       {0x0001, 0x8114},
-       {0x0003, 0x8114},
-
-       /* Initial sequence Synchronous Serial Interface */
-       {0x000f, 0x8402},       /* Memory bank Address */
-       {0x0000, 0x8403},       /* Memory bank Address */
-       {0x00ba, 0x8804},       /* SSI Slave address */
-       {0x0010, 0x8802},       /* 93.75kHz SSI Clock Two DataByte */
-       {0x0010, 0x8802},       /* 93.75kHz SSI Clock two DataByte */
-
-       {0x0001, 0x8801},
-       {0x000a, 0x8805},       /* a - NWG: Dunno what this is about */
-       {0x0000, 0x8800},
-       {0x0010, 0x8802},
-
-       {0x0002, 0x8801},
-       {0x0000, 0x8805},
-       {0x0000, 0x8800},
-       {0x0010, 0x8802},
-
-       {0x0003, 0x8801},
-       {0x0027, 0x8805},
-       {0x0001, 0x8800},
-       {0x0010, 0x8802},
-
-       {0x0004, 0x8801},
-       {0x0065, 0x8805},
-       {0x0001, 0x8800},
-       {0x0010, 0x8802},
-
-       {0x0005, 0x8801},
-       {0x0003, 0x8805},
-       {0x0000, 0x8800},
-       {0x0010, 0x8802},
-
-       {0x0006, 0x8801},
-       {0x001c, 0x8805},
-       {0x0000, 0x8800},
-       {0x0010, 0x8802},
-
-       {0x0007, 0x8801},
-       {0x002a, 0x8805},
-       {0x0000, 0x8800},
-       {0x0010, 0x8802},
-
-       {0x0002, 0x8704},       /* External input CKIx1 */
-       {0x0001, 0x8606},    /* 1 Line memory Read Counter (H) Result: (d)410 */
-       {0x009a, 0x8600},       /* Line memory Read Counter (L) */
-       {0x0001, 0x865b},       /* 1 Horizontal Offset for Valid Pixel(L) */
-       {0x0003, 0x865c},       /* 3 Vertical Offset for Valid Lines(L) */
-       {0x0058, 0x865d},       /* 58 Horizontal Valid Pixel Window(L) */
-
-       {0x0006, 0x8660},       /* Nibble data + input order */
-
-       {0x000a, 0x8602},       /* Optical black level set to 0x0a */
-       {0x0000, 0x8603},       /* Optical black level Offset */
-
-/*     {0x0000, 0x8611},        * 0 R  Offset for white Balance */
-/*     {0x0000, 0x8612},        * 1 Gr Offset for white Balance */
-/*     {0x0000, 0x8613},        * 1f B  Offset for white Balance */
-/*     {0x0000, 0x8614},        * f0 Gb Offset for white Balance */
-
-       {0x0040, 0x8651},   /* 2b BLUE gain for white balance  good at all 60 */
-       {0x0030, 0x8652},       /* 41 Gr Gain for white Balance (L) */
-       {0x0035, 0x8653},       /* 26 RED gain for white balance */
-       {0x0035, 0x8654},       /* 40Gb Gain for white Balance (L) */
-       {0x0041, 0x863f},
-             /* Fixed Gamma correction enabled (makes colours look better) */
-
-       {0x0000, 0x8655},
-               /* High bits for white balance*****brightness control*** */
-       {}
-};
-
-static const u16 spca508_sightcam_init_data[][2] = {
-/* This line seems to setup the frame/canvas */
-       {0x000f, 0x8402},
-
-/* These 6 lines are needed to startup the webcam */
-       {0x0090, 0x8110},
-       {0x0001, 0x8114},
-       {0x0001, 0x8114},
-       {0x0001, 0x8114},
-       {0x0003, 0x8114},
-       {0x0080, 0x8804},
-
-/* This part seems to make the pictures darker? (autobrightness?) */
-       {0x0001, 0x8801},
-       {0x0004, 0x8800},
-       {0x0003, 0x8801},
-       {0x00e0, 0x8800},
-       {0x0004, 0x8801},
-       {0x00b4, 0x8800},
-       {0x0005, 0x8801},
-       {0x0000, 0x8800},
-
-       {0x0006, 0x8801},
-       {0x00e0, 0x8800},
-       {0x0007, 0x8801},
-       {0x000c, 0x8800},
-
-/* This section is just needed, it probably
- * does something like the previous section,
- * but the cam won't start if it's not included.
- */
-       {0x0014, 0x8801},
-       {0x0008, 0x8800},
-       {0x0015, 0x8801},
-       {0x0067, 0x8800},
-       {0x0016, 0x8801},
-       {0x0000, 0x8800},
-       {0x0017, 0x8801},
-       {0x0020, 0x8800},
-       {0x0018, 0x8801},
-       {0x0044, 0x8800},
-
-/* Makes the picture darker - and the
- * cam won't start if not included
- */
-       {0x001e, 0x8801},
-       {0x00ea, 0x8800},
-       {0x001f, 0x8801},
-       {0x0001, 0x8800},
-       {0x0003, 0x8801},
-       {0x00e0, 0x8800},
-
-/* seems to place the colors ontop of each other #1 */
-       {0x0006, 0x8704},
-       {0x0001, 0x870c},
-       {0x0016, 0x8600},
-       {0x0002, 0x8606},
-
-/* if not included the pictures becomes _very_ dark */
-       {0x0064, 0x8607},
-       {0x003a, 0x8601},
-       {0x0000, 0x8602},
-
-/* seems to place the colors ontop of each other #2 */
-       {0x0016, 0x8600},
-       {0x0018, 0x8617},
-       {0x0008, 0x8618},
-       {0x00a1, 0x8656},
-
-/* webcam won't start if not included */
-       {0x0007, 0x865b},
-       {0x0001, 0x865c},
-       {0x0058, 0x865d},
-       {0x0048, 0x865e},
-
-/* adjusts the colors */
-       {0x0049, 0x8651},
-       {0x0040, 0x8652},
-       {0x004c, 0x8653},
-       {0x0040, 0x8654},
-       {}
-};
-
-static const u16 spca508_sightcam2_init_data[][2] = {
-       {0x0020, 0x8112},
-
-       {0x000f, 0x8402},
-       {0x0000, 0x8403},
-
-       {0x0008, 0x8201},
-       {0x0008, 0x8200},
-       {0x0001, 0x8200},
-       {0x0009, 0x8201},
-       {0x0008, 0x8200},
-       {0x0001, 0x8200},
-       {0x000a, 0x8201},
-       {0x0008, 0x8200},
-       {0x0001, 0x8200},
-       {0x000b, 0x8201},
-       {0x0008, 0x8200},
-       {0x0001, 0x8200},
-       {0x000c, 0x8201},
-       {0x0008, 0x8200},
-       {0x0001, 0x8200},
-       {0x000d, 0x8201},
-       {0x0008, 0x8200},
-       {0x0001, 0x8200},
-       {0x000e, 0x8201},
-       {0x0008, 0x8200},
-       {0x0001, 0x8200},
-       {0x0007, 0x8201},
-       {0x0008, 0x8200},
-       {0x0001, 0x8200},
-       {0x000f, 0x8201},
-       {0x0008, 0x8200},
-       {0x0001, 0x8200},
-
-       {0x0018, 0x8660},
-       {0x0010, 0x8201},
-
-       {0x0008, 0x8200},
-       {0x0001, 0x8200},
-       {0x0011, 0x8201},
-       {0x0008, 0x8200},
-       {0x0001, 0x8200},
-
-       {0x0000, 0x86b0},
-       {0x0034, 0x86b1},
-       {0x0000, 0x86b2},
-       {0x0049, 0x86b3},
-       {0x0000, 0x86b4},
-       {0x0000, 0x86b4},
-
-       {0x0012, 0x8201},
-       {0x0008, 0x8200},
-       {0x0001, 0x8200},
-       {0x0013, 0x8201},
-       {0x0008, 0x8200},
-       {0x0001, 0x8200},
-
-       {0x0001, 0x86b0},
-       {0x00aa, 0x86b1},
-       {0x0000, 0x86b2},
-       {0x00e4, 0x86b3},
-       {0x0000, 0x86b4},
-       {0x0000, 0x86b4},
-
-       {0x0018, 0x8660},
-
-       {0x0090, 0x8110},
-       {0x0001, 0x8114},
-       {0x0001, 0x8114},
-       {0x0001, 0x8114},
-       {0x0003, 0x8114},
-
-       {0x0080, 0x8804},
-       {0x0003, 0x8801},
-       {0x0012, 0x8800},
-       {0x0004, 0x8801},
-       {0x0005, 0x8800},
-       {0x0005, 0x8801},
-       {0x0000, 0x8800},
-       {0x0006, 0x8801},
-       {0x0000, 0x8800},
-       {0x0007, 0x8801},
-       {0x0000, 0x8800},
-       {0x0008, 0x8801},
-       {0x0005, 0x8800},
-       {0x000a, 0x8700},
-       {0x000e, 0x8801},
-       {0x0004, 0x8800},
-       {0x0005, 0x8801},
-       {0x0047, 0x8800},
-       {0x0006, 0x8801},
-       {0x0000, 0x8800},
-       {0x0007, 0x8801},
-       {0x00c0, 0x8800},
-       {0x0008, 0x8801},
-       {0x0003, 0x8800},
-       {0x0013, 0x8801},
-       {0x0001, 0x8800},
-       {0x0009, 0x8801},
-       {0x0000, 0x8800},
-       {0x000a, 0x8801},
-       {0x0000, 0x8800},
-       {0x000b, 0x8801},
-       {0x0000, 0x8800},
-       {0x000c, 0x8801},
-       {0x0000, 0x8800},
-       {0x000e, 0x8801},
-       {0x0004, 0x8800},
-       {0x000f, 0x8801},
-       {0x0000, 0x8800},
-       {0x0010, 0x8801},
-       {0x0006, 0x8800},
-       {0x0011, 0x8801},
-       {0x0006, 0x8800},
-       {0x0012, 0x8801},
-       {0x0000, 0x8800},
-       {0x0013, 0x8801},
-       {0x0001, 0x8800},
-
-       {0x000a, 0x8700},
-       {0x0000, 0x8702},
-       {0x0000, 0x8703},
-       {0x00c2, 0x8704},
-       {0x0001, 0x870c},
-
-       {0x0044, 0x8600},
-       {0x0002, 0x8606},
-       {0x0064, 0x8607},
-       {0x003a, 0x8601},
-       {0x0008, 0x8602},
-       {0x0044, 0x8600},
-       {0x0018, 0x8617},
-       {0x0008, 0x8618},
-       {0x00a1, 0x8656},
-       {0x0004, 0x865b},
-       {0x0002, 0x865c},
-       {0x0058, 0x865d},
-       {0x0048, 0x865e},
-       {0x0012, 0x8608},
-       {0x002c, 0x8609},
-       {0x0002, 0x860a},
-       {0x002c, 0x860b},
-       {0x00db, 0x860c},
-       {0x00f9, 0x860d},
-       {0x00f1, 0x860e},
-       {0x00e3, 0x860f},
-       {0x002c, 0x8610},
-       {0x006c, 0x8651},
-       {0x0041, 0x8652},
-       {0x0059, 0x8653},
-       {0x0040, 0x8654},
-       {0x00fa, 0x8611},
-       {0x00ff, 0x8612},
-       {0x00f8, 0x8613},
-       {0x0000, 0x8614},
-       {0x0001, 0x863f},
-       {0x0000, 0x8640},
-       {0x0026, 0x8641},
-       {0x0045, 0x8642},
-       {0x0060, 0x8643},
-       {0x0075, 0x8644},
-       {0x0088, 0x8645},
-       {0x009b, 0x8646},
-       {0x00b0, 0x8647},
-       {0x00c5, 0x8648},
-       {0x00d2, 0x8649},
-       {0x00dc, 0x864a},
-       {0x00e5, 0x864b},
-       {0x00eb, 0x864c},
-       {0x00f0, 0x864d},
-       {0x00f6, 0x864e},
-       {0x00fa, 0x864f},
-       {0x00ff, 0x8650},
-       {0x0060, 0x8657},
-       {0x0010, 0x8658},
-       {0x0018, 0x8659},
-       {0x0005, 0x865a},
-       {0x0018, 0x8660},
-       {0x0003, 0x8509},
-       {0x0011, 0x850a},
-       {0x0032, 0x850b},
-       {0x0010, 0x850c},
-       {0x0021, 0x850d},
-       {0x0001, 0x8500},
-       {0x0000, 0x8508},
-       {0x0012, 0x8608},
-       {0x002c, 0x8609},
-       {0x0002, 0x860a},
-       {0x0039, 0x860b},
-       {0x00d0, 0x860c},
-       {0x00f7, 0x860d},
-       {0x00ed, 0x860e},
-       {0x00db, 0x860f},
-       {0x0039, 0x8610},
-       {0x0012, 0x8657},
-       {0x000c, 0x8619},
-       {0x0004, 0x861a},
-       {0x00a1, 0x8656},
-       {0x00c8, 0x8615},
-       {0x0032, 0x8616},
-
-       {0x0030, 0x8112},
-       {0x0020, 0x8112},
-       {0x0020, 0x8112},
-       {0x000f, 0x8402},
-       {0x0000, 0x8403},
-
-       {0x0090, 0x8110},
-       {0x0001, 0x8114},
-       {0x0001, 0x8114},
-       {0x0001, 0x8114},
-       {0x0003, 0x8114},
-       {0x0080, 0x8804},
-
-       {0x0003, 0x8801},
-       {0x0012, 0x8800},
-       {0x0004, 0x8801},
-       {0x0005, 0x8800},
-       {0x0005, 0x8801},
-       {0x0047, 0x8800},
-       {0x0006, 0x8801},
-       {0x0000, 0x8800},
-       {0x0007, 0x8801},
-       {0x00c0, 0x8800},
-       {0x0008, 0x8801},
-       {0x0003, 0x8800},
-       {0x000a, 0x8700},
-       {0x000e, 0x8801},
-       {0x0004, 0x8800},
-       {0x0005, 0x8801},
-       {0x0047, 0x8800},
-       {0x0006, 0x8801},
-       {0x0000, 0x8800},
-       {0x0007, 0x8801},
-       {0x00c0, 0x8800},
-       {0x0008, 0x8801},
-       {0x0003, 0x8800},
-       {0x0013, 0x8801},
-       {0x0001, 0x8800},
-       {0x0009, 0x8801},
-       {0x0000, 0x8800},
-       {0x000a, 0x8801},
-       {0x0000, 0x8800},
-       {0x000b, 0x8801},
-       {0x0000, 0x8800},
-       {0x000c, 0x8801},
-       {0x0000, 0x8800},
-       {0x000e, 0x8801},
-       {0x0004, 0x8800},
-       {0x000f, 0x8801},
-       {0x0000, 0x8800},
-       {0x0010, 0x8801},
-       {0x0006, 0x8800},
-       {0x0011, 0x8801},
-       {0x0006, 0x8800},
-       {0x0012, 0x8801},
-       {0x0000, 0x8800},
-       {0x0013, 0x8801},
-       {0x0001, 0x8800},
-       {0x000a, 0x8700},
-       {0x0000, 0x8702},
-       {0x0000, 0x8703},
-       {0x00c2, 0x8704},
-       {0x0001, 0x870c},
-       {0x0044, 0x8600},
-       {0x0002, 0x8606},
-       {0x0064, 0x8607},
-       {0x003a, 0x8601},
-       {0x0008, 0x8602},
-       {0x0044, 0x8600},
-       {0x0018, 0x8617},
-       {0x0008, 0x8618},
-       {0x00a1, 0x8656},
-       {0x0004, 0x865b},
-       {0x0002, 0x865c},
-       {0x0058, 0x865d},
-       {0x0048, 0x865e},
-       {0x0012, 0x8608},
-       {0x002c, 0x8609},
-       {0x0002, 0x860a},
-       {0x002c, 0x860b},
-       {0x00db, 0x860c},
-       {0x00f9, 0x860d},
-       {0x00f1, 0x860e},
-       {0x00e3, 0x860f},
-       {0x002c, 0x8610},
-       {0x006c, 0x8651},
-       {0x0041, 0x8652},
-       {0x0059, 0x8653},
-       {0x0040, 0x8654},
-       {0x00fa, 0x8611},
-       {0x00ff, 0x8612},
-       {0x00f8, 0x8613},
-       {0x0000, 0x8614},
-       {0x0001, 0x863f},
-       {0x0000, 0x8640},
-       {0x0026, 0x8641},
-       {0x0045, 0x8642},
-       {0x0060, 0x8643},
-       {0x0075, 0x8644},
-       {0x0088, 0x8645},
-       {0x009b, 0x8646},
-       {0x00b0, 0x8647},
-       {0x00c5, 0x8648},
-       {0x00d2, 0x8649},
-       {0x00dc, 0x864a},
-       {0x00e5, 0x864b},
-       {0x00eb, 0x864c},
-       {0x00f0, 0x864d},
-       {0x00f6, 0x864e},
-       {0x00fa, 0x864f},
-       {0x00ff, 0x8650},
-       {0x0060, 0x8657},
-       {0x0010, 0x8658},
-       {0x0018, 0x8659},
-       {0x0005, 0x865a},
-       {0x0018, 0x8660},
-       {0x0003, 0x8509},
-       {0x0011, 0x850a},
-       {0x0032, 0x850b},
-       {0x0010, 0x850c},
-       {0x0021, 0x850d},
-       {0x0001, 0x8500},
-       {0x0000, 0x8508},
-
-       {0x0012, 0x8608},
-       {0x002c, 0x8609},
-       {0x0002, 0x860a},
-       {0x0039, 0x860b},
-       {0x00d0, 0x860c},
-       {0x00f7, 0x860d},
-       {0x00ed, 0x860e},
-       {0x00db, 0x860f},
-       {0x0039, 0x8610},
-       {0x0012, 0x8657},
-       {0x0064, 0x8619},
-
-/* This line starts it all, it is not needed here */
-/* since it has been build into the driver */
-/* jfm: don't start now */
-/*     {0x0030, 0x8112}, */
-       {}
-};
-
-/*
- * Initialization data for Creative Webcam Vista
- */
-static const u16 spca508_vista_init_data[][2] = {
-       {0x0008, 0x8200},       /* Clear register */
-       {0x0000, 0x870b},       /* Reset CTL3 */
-       {0x0020, 0x8112},       /* Video Drop packet enable */
-       {0x0003, 0x8111},       /* Soft Reset compression, memory, TG & CDSP */
-       {0x0000, 0x8110},       /* Disable everything */
-       {0x0000, 0x8114},       /* Software GPIO output data */
-       {0x0000, 0x8114},
-
-       {0x0003, 0x8111},
-       {0x0000, 0x8111},
-       {0x0090, 0x8110},    /* Enable: SSI output, External 2X clock output */
-       {0x0020, 0x8112},
-       {0x0000, 0x8114},
-       {0x0001, 0x8114},
-       {0x0001, 0x8114},
-       {0x0001, 0x8114},
-       {0x0003, 0x8114},
-
-       {0x000f, 0x8402},       /* Memory bank Address */
-       {0x0000, 0x8403},       /* Memory bank Address */
-       {0x00ba, 0x8804},       /* SSI Slave address */
-       {0x0010, 0x8802},       /* 93.75kHz SSI Clock Two DataByte */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},       /* Will write 2 bytes (DATA1+DATA2) */
-       {0x0020, 0x8801},       /* Register address for SSI read/write */
-       {0x0044, 0x8805},       /* DATA2 */
-       {0x0004, 0x8800},       /* DATA1 -> write triggered */
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x0009, 0x8801},
-       {0x0042, 0x8805},
-       {0x0001, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x003c, 0x8801},
-       {0x0001, 0x8805},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x0001, 0x8801},
-       {0x000a, 0x8805},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x0002, 0x8801},
-       {0x0000, 0x8805},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x0003, 0x8801},
-       {0x0027, 0x8805},
-       {0x0001, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x0004, 0x8801},
-       {0x0065, 0x8805},
-       {0x0001, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x0005, 0x8801},
-       {0x0003, 0x8805},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x0006, 0x8801},
-       {0x001c, 0x8805},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x0007, 0x8801},
-       {0x002a, 0x8805},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x000e, 0x8801},
-       {0x0000, 0x8805},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x0028, 0x8801},
-       {0x002e, 0x8805},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x0039, 0x8801},
-       {0x0013, 0x8805},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x003b, 0x8801},
-       {0x000c, 0x8805},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x0035, 0x8801},
-       {0x0028, 0x8805},
-       {0x0000, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-       /* READ { 0x0001, 0x8802 } -> 0000: 10  */
-       {0x0010, 0x8802},
-       {0x0009, 0x8801},
-       {0x0042, 0x8805},
-       {0x0001, 0x8800},
-       /* READ { 0x0001, 0x8803 } -> 0000: 00  */
-
-       {0x0050, 0x8703},
-       {0x0002, 0x8704},       /* External input CKIx1 */
-       {0x0001, 0x870c},       /* Select CKOx2 output */
-       {0x009a, 0x8600},       /* Line memory Read Counter (L) */
-       {0x0001, 0x8606},    /* 1 Line memory Read Counter (H) Result: (d)410 */
-       {0x0023, 0x8601},
-       {0x0010, 0x8602},
-       {0x000a, 0x8603},
-       {0x009a, 0x8600},
-       {0x0001, 0x865b},       /* 1 Horizontal Offset for Valid Pixel(L) */
-       {0x0003, 0x865c},       /* Vertical offset for valid lines (L) */
-       {0x0058, 0x865d},       /* Horizontal valid pixels window (L) */
-       {0x0048, 0x865e},       /* Vertical valid lines window (L) */
-       {0x0000, 0x865f},
-
-       {0x0006, 0x8660},
-                   /* Enable nibble data input, select nibble input order */
-
-       {0x0013, 0x8608},       /* A11 Coeficients for color correction */
-       {0x0028, 0x8609},
-                   /* Note: these values are confirmed at the end of array */
-       {0x0005, 0x860a},       /* ... */
-       {0x0025, 0x860b},
-       {0x00e1, 0x860c},
-       {0x00fa, 0x860d},
-       {0x00f4, 0x860e},
-       {0x00e8, 0x860f},
-       {0x0025, 0x8610},       /* A33 Coef. */
-       {0x00fc, 0x8611},       /* White balance offset: R */
-       {0x0001, 0x8612},       /* White balance offset: Gr */
-       {0x00fe, 0x8613},       /* White balance offset: B */
-       {0x0000, 0x8614},       /* White balance offset: Gb */
-
-       {0x0064, 0x8651},       /* R gain for white balance (L) */
-       {0x0040, 0x8652},       /* Gr gain for white balance (L) */
-       {0x0066, 0x8653},       /* B gain for white balance (L) */
-       {0x0040, 0x8654},       /* Gb gain for white balance (L) */
-       {0x0001, 0x863f},       /* Enable fixed gamma correction */
-
-       {0x00a1, 0x8656},       /* Size - Window1: 256x256, Window2: 128x128,
-                                * UV division: UV no change,
-                                * Enable New edge enhancement */
-       {0x0018, 0x8657},       /* Edge gain high threshold */
-       {0x0020, 0x8658},       /* Edge gain low threshold */
-       {0x000a, 0x8659},       /* Edge bandwidth high threshold */
-       {0x0005, 0x865a},       /* Edge bandwidth low threshold */
-       {0x0064, 0x8607},       /* UV filter enable */
-
-       {0x0016, 0x8660},
-       {0x0000, 0x86b0},       /* Bad pixels compensation address */
-       {0x00dc, 0x86b1},       /* X coord for bad pixels compensation (L) */
-       {0x0000, 0x86b2},
-       {0x0009, 0x86b3},       /* Y coord for bad pixels compensation (L) */
-       {0x0000, 0x86b4},
-
-       {0x0001, 0x86b0},
-       {0x00f5, 0x86b1},
-       {0x0000, 0x86b2},
-       {0x00c6, 0x86b3},
-       {0x0000, 0x86b4},
-
-       {0x0002, 0x86b0},
-       {0x001c, 0x86b1},
-       {0x0001, 0x86b2},
-       {0x00d7, 0x86b3},
-       {0x0000, 0x86b4},
-
-       {0x0003, 0x86b0},
-       {0x001c, 0x86b1},
-       {0x0001, 0x86b2},
-       {0x00d8, 0x86b3},
-       {0x0000, 0x86b4},
-
-       {0x0004, 0x86b0},
-       {0x001d, 0x86b1},
-       {0x0001, 0x86b2},
-       {0x00d8, 0x86b3},
-       {0x0000, 0x86b4},
-       {0x001e, 0x8660},
-
-       /* READ { 0x0000, 0x8608 } -> 0000: 13  */
-       /* READ { 0x0000, 0x8609 } -> 0000: 28  */
-       /* READ { 0x0000, 0x8610 } -> 0000: 05  */
-       /* READ { 0x0000, 0x8611 } -> 0000: 25  */
-       /* READ { 0x0000, 0x8612 } -> 0000: e1  */
-       /* READ { 0x0000, 0x8613 } -> 0000: fa  */
-       /* READ { 0x0000, 0x8614 } -> 0000: f4  */
-       /* READ { 0x0000, 0x8615 } -> 0000: e8  */
-       /* READ { 0x0000, 0x8616 } -> 0000: 25  */
-       {}
-};
-
-static int reg_write(struct usb_device *dev,
-                       u16 index, u16 value)
-{
-       int ret;
-
-       ret = usb_control_msg(dev,
-                       usb_sndctrlpipe(dev, 0),
-                       0,              /* request */
-                       USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index, NULL, 0, 500);
-       PDEBUG(D_USBO, "reg write i:0x%04x = 0x%02x",
-               index, value);
-       if (ret < 0)
-               pr_err("reg write: error %d\n", ret);
-       return ret;
-}
-
-/* read 1 byte */
-/* returns: negative is error, pos or zero is data */
-static int reg_read(struct gspca_dev *gspca_dev,
-                       u16 index)      /* wIndex */
-{
-       int ret;
-
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       0,                      /* register */
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,              /* value */
-                       index,
-                       gspca_dev->usb_buf, 1,
-                       500);                   /* timeout */
-       PDEBUG(D_USBI, "reg read i:%04x --> %02x",
-               index, gspca_dev->usb_buf[0]);
-       if (ret < 0) {
-               pr_err("reg_read err %d\n", ret);
-               return ret;
-       }
-       return gspca_dev->usb_buf[0];
-}
-
-/* send 1 or 2 bytes to the sensor via the Synchronous Serial Interface */
-static int ssi_w(struct gspca_dev *gspca_dev,
-               u16 reg, u16 val)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret, retry;
-
-       ret = reg_write(dev, 0x8802, reg >> 8);
-       if (ret < 0)
-               goto out;
-       ret = reg_write(dev, 0x8801, reg & 0x00ff);
-       if (ret < 0)
-               goto out;
-       if ((reg & 0xff00) == 0x1000) {         /* if 2 bytes */
-               ret = reg_write(dev, 0x8805, val & 0x00ff);
-               if (ret < 0)
-                       goto out;
-               val >>= 8;
-       }
-       ret = reg_write(dev, 0x8800, val);
-       if (ret < 0)
-               goto out;
-
-       /* poll until not busy */
-       retry = 10;
-       for (;;) {
-               ret = reg_read(gspca_dev, 0x8803);
-               if (ret < 0)
-                       break;
-               if (gspca_dev->usb_buf[0] == 0)
-                       break;
-               if (--retry <= 0) {
-                       PDEBUG(D_ERR, "ssi_w busy %02x",
-                                       gspca_dev->usb_buf[0]);
-                       ret = -1;
-                       break;
-               }
-               msleep(8);
-       }
-
-out:
-       return ret;
-}
-
-static int write_vector(struct gspca_dev *gspca_dev,
-                       const u16 (*data)[2])
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret = 0;
-
-       while ((*data)[1] != 0) {
-               if ((*data)[1] & 0x8000) {
-                       if ((*data)[1] == 0xdd00)       /* delay */
-                               msleep((*data)[0]);
-                       else
-                               ret = reg_write(dev, (*data)[1], (*data)[0]);
-               } else {
-                       ret = ssi_w(gspca_dev, (*data)[1], (*data)[0]);
-               }
-               if (ret < 0)
-                       break;
-               data++;
-       }
-       return ret;
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-       const u16 (*init_data)[2];
-       static const u16 (*(init_data_tb[]))[2] = {
-               spca508_vista_init_data,        /* CreativeVista 0 */
-               spca508_sightcam_init_data,     /* HamaUSBSightcam 1 */
-               spca508_sightcam2_init_data,    /* HamaUSBSightcam2 2 */
-               spca508cs110_init_data,         /* IntelEasyPCCamera 3 */
-               spca508cs110_init_data,         /* MicroInnovationIC200 4 */
-               spca508_init_data,              /* ViewQuestVQ110 5 */
-       };
-
-#ifdef GSPCA_DEBUG
-       int data1, data2;
-
-       /* Read from global register the USB product and vendor IDs, just to
-        * prove that we can communicate with the device.  This works, which
-        * confirms at we are communicating properly and that the device
-        * is a 508. */
-       data1 = reg_read(gspca_dev, 0x8104);
-       data2 = reg_read(gspca_dev, 0x8105);
-       PDEBUG(D_PROBE, "Webcam Vendor ID: 0x%02x%02x", data2, data1);
-
-       data1 = reg_read(gspca_dev, 0x8106);
-       data2 = reg_read(gspca_dev, 0x8107);
-       PDEBUG(D_PROBE, "Webcam Product ID: 0x%02x%02x", data2, data1);
-
-       data1 = reg_read(gspca_dev, 0x8621);
-       PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);
-#endif
-
-       cam = &gspca_dev->cam;
-       cam->cam_mode = sif_mode;
-       cam->nmodes = ARRAY_SIZE(sif_mode);
-
-       sd->subtype = id->driver_info;
-
-       init_data = init_data_tb[sd->subtype];
-       return write_vector(gspca_dev, init_data);
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       return 0;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       int mode;
-
-       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-       reg_write(gspca_dev->dev, 0x8500, mode);
-       switch (mode) {
-       case 0:
-       case 1:
-               reg_write(gspca_dev->dev, 0x8700, 0x28);        /* clock */
-               break;
-       default:
-/*     case 2: */
-/*     case 3: */
-               reg_write(gspca_dev->dev, 0x8700, 0x23);        /* clock */
-               break;
-       }
-       reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20);
-       return 0;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       /* Video ISO disable, Video Drop Packet enable: */
-       reg_write(gspca_dev->dev, 0x8112, 0x20);
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,                       /* isoc packet */
-                       int len)                        /* iso packet length */
-{
-       switch (data[0]) {
-       case 0:                         /* start of frame */
-               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-               data += SPCA508_OFFSET_DATA;
-               len -= SPCA508_OFFSET_DATA;
-               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
-               break;
-       case 0xff:                      /* drop */
-               break;
-       default:
-               data += 1;
-               len -= 1;
-               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-               break;
-       }
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
-{
-       /* MX seem contrast */
-       reg_write(gspca_dev->dev, 0x8651, brightness);
-       reg_write(gspca_dev->dev, 0x8652, brightness);
-       reg_write(gspca_dev->dev, 0x8653, brightness);
-       reg_write(gspca_dev->dev, 0x8654, brightness);
-}
-
-static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct gspca_dev *gspca_dev =
-               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
-
-       gspca_dev->usb_err = 0;
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 5);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
-
-       if (hdl->error) {
-               pr_err("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,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam},
-       {USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista},
-       {USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110},
-       {USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam},
-       {USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2},
-       {USB_DEVICE(0x8086, 0x0110), .driver_info = IntelEasyPCCamera},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c
deleted file mode 100644 (file)
index cfe71dd..0000000
+++ /dev/null
@@ -1,936 +0,0 @@
-/*
- * Sunplus spca561 subdriver
- *
- * Copyright (C) 2004 Michel Xhaard mxhaard@magic.fr
- *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "spca561"
-
-#include <linux/input.h>
-#include "gspca.h"
-
-MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
-MODULE_DESCRIPTION("GSPCA/SPCA561 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-#define EXPOSURE_MAX (2047 + 325)
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       struct { /* hue/contrast control cluster */
-               struct v4l2_ctrl *contrast;
-               struct v4l2_ctrl *hue;
-       };
-       struct v4l2_ctrl *autogain;
-
-#define EXPO12A_DEF 3
-       __u8 expo12a;           /* expo/gain? for rev 12a */
-
-       __u8 chip_revision;
-#define Rev012A 0
-#define Rev072A 1
-
-       signed char ag_cnt;
-#define AG_CNT_START 13
-};
-
-static const struct v4l2_pix_format sif_012a_mode[] = {
-       {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 3},
-       {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2},
-       {320, 240, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 4 / 8,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {352, 288, V4L2_PIX_FMT_SPCA561, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 4 / 8,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-static const struct v4l2_pix_format sif_072a_mode[] = {
-       {160, 120, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 3},
-       {176, 144, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2},
-       {320, 240, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {352, 288, V4L2_PIX_FMT_SGBRG8, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-/*
- * Initialization data
- * I'm not very sure how to split initialization from open data
- * chunks. For now, we'll consider everything as initialization
- */
-/* Frame packet header offsets for the spca561 */
-#define SPCA561_OFFSET_SNAP 1
-#define SPCA561_OFFSET_TYPE 2
-#define SPCA561_OFFSET_COMPRESS 3
-#define SPCA561_OFFSET_FRAMSEQ   4
-#define SPCA561_OFFSET_GPIO 5
-#define SPCA561_OFFSET_USBBUFF 6
-#define SPCA561_OFFSET_WIN2GRAVE 7
-#define SPCA561_OFFSET_WIN2RAVE 8
-#define SPCA561_OFFSET_WIN2BAVE 9
-#define SPCA561_OFFSET_WIN2GBAVE 10
-#define SPCA561_OFFSET_WIN1GRAVE 11
-#define SPCA561_OFFSET_WIN1RAVE 12
-#define SPCA561_OFFSET_WIN1BAVE 13
-#define SPCA561_OFFSET_WIN1GBAVE 14
-#define SPCA561_OFFSET_FREQ 15
-#define SPCA561_OFFSET_VSYNC 16
-#define SPCA561_INDEX_I2C_BASE 0x8800
-#define SPCA561_SNAPBIT 0x20
-#define SPCA561_SNAPCTRL 0x40
-
-static const u16 rev72a_reset[][2] = {
-       {0x0000, 0x8114},       /* Software GPIO output data */
-       {0x0001, 0x8114},       /* Software GPIO output data */
-       {0x0000, 0x8112},       /* Some kind of reset */
-       {}
-};
-static const __u16 rev72a_init_data1[][2] = {
-       {0x0003, 0x8701},       /* PCLK clock delay adjustment */
-       {0x0001, 0x8703},       /* HSYNC from cmos inverted */
-       {0x0011, 0x8118},       /* Enable and conf sensor */
-       {0x0001, 0x8118},       /* Conf sensor */
-       {0x0092, 0x8804},       /* I know nothing about these */
-       {0x0010, 0x8802},       /* 0x88xx registers, so I won't */
-       {}
-};
-static const u16 rev72a_init_sensor1[][2] = {
-       {0x0001, 0x000d},
-       {0x0002, 0x0018},
-       {0x0004, 0x0165},
-       {0x0005, 0x0021},
-       {0x0007, 0x00aa},
-       {0x0020, 0x1504},
-       {0x0039, 0x0002},
-       {0x0035, 0x0010},
-       {0x0009, 0x1049},
-       {0x0028, 0x000b},
-       {0x003b, 0x000f},
-       {0x003c, 0x0000},
-       {}
-};
-static const __u16 rev72a_init_data2[][2] = {
-       {0x0018, 0x8601},       /* Pixel/line selection for color separation */
-       {0x0000, 0x8602},       /* Optical black level for user setting */
-       {0x0060, 0x8604},       /* Optical black horizontal offset */
-       {0x0002, 0x8605},       /* Optical black vertical offset */
-       {0x0000, 0x8603},       /* Non-automatic optical black level */
-       {0x0002, 0x865b},       /* Horizontal offset for valid pixels */
-       {0x0000, 0x865f},       /* Vertical valid pixels window (x2) */
-       {0x00b0, 0x865d},       /* Horizontal valid pixels window (x2) */
-       {0x0090, 0x865e},       /* Vertical valid lines window (x2) */
-       {0x00e0, 0x8406},       /* Memory buffer threshold */
-       {0x0000, 0x8660},       /* Compensation memory stuff */
-       {0x0002, 0x8201},       /* Output address for r/w serial EEPROM */
-       {0x0008, 0x8200},       /* Clear valid bit for serial EEPROM */
-       {0x0001, 0x8200},       /* OprMode to be executed by hardware */
-/* from ms-win */
-       {0x0000, 0x8611},       /* R offset for white balance */
-       {0x00fd, 0x8612},       /* Gr offset for white balance */
-       {0x0003, 0x8613},       /* B offset for white balance */
-       {0x0000, 0x8614},       /* Gb offset for white balance */
-/* from ms-win */
-       {0x0035, 0x8651},       /* R gain for white balance */
-       {0x0040, 0x8652},       /* Gr gain for white balance */
-       {0x005f, 0x8653},       /* B gain for white balance */
-       {0x0040, 0x8654},       /* Gb gain for white balance */
-       {0x0002, 0x8502},       /* Maximum average bit rate stuff */
-       {0x0011, 0x8802},
-
-       {0x0087, 0x8700},       /* Set master clock (96Mhz????) */
-       {0x0081, 0x8702},       /* Master clock output enable */
-
-       {0x0000, 0x8500},       /* Set image type (352x288 no compression) */
-       /* Originally was 0x0010 (352x288 compression) */
-
-       {0x0002, 0x865b},       /* Horizontal offset for valid pixels */
-       {0x0003, 0x865c},       /* Vertical offset for valid lines */
-       {}
-};
-static const u16 rev72a_init_sensor2[][2] = {
-       {0x0003, 0x0121},
-       {0x0004, 0x0165},
-       {0x0005, 0x002f},       /* blanking control column */
-       {0x0006, 0x0000},       /* blanking mode row*/
-       {0x000a, 0x0002},
-       {0x0009, 0x1061},       /* setexposure times && pixel clock
-                                * 0001 0 | 000 0110 0001 */
-       {0x0035, 0x0014},
-       {}
-};
-
-/******************** QC Express etch2 stuff ********************/
-static const __u16 Pb100_1map8300[][2] = {
-       /* reg, value */
-       {0x8320, 0x3304},
-
-       {0x8303, 0x0125},       /* image area */
-       {0x8304, 0x0169},
-       {0x8328, 0x000b},
-       {0x833c, 0x0001},               /*fixme: win:07*/
-
-       {0x832f, 0x1904},               /*fixme: was 0419*/
-       {0x8307, 0x00aa},
-       {0x8301, 0x0003},
-       {0x8302, 0x000e},
-       {}
-};
-static const __u16 Pb100_2map8300[][2] = {
-       /* reg, value */
-       {0x8339, 0x0000},
-       {0x8307, 0x00aa},
-       {}
-};
-
-static const __u16 spca561_161rev12A_data1[][2] = {
-       {0x29, 0x8118},         /* Control register (various enable bits) */
-       {0x08, 0x8114},         /* GPIO: Led off */
-       {0x0e, 0x8112},         /* 0x0e stream off 0x3e stream on */
-       {0x00, 0x8102},         /* white balance - new */
-       {0x92, 0x8804},
-       {0x04, 0x8802},         /* windows uses 08 */
-       {}
-};
-static const __u16 spca561_161rev12A_data2[][2] = {
-       {0x21, 0x8118},
-       {0x10, 0x8500},
-       {0x07, 0x8601},
-       {0x07, 0x8602},
-       {0x04, 0x8501},
-
-       {0x07, 0x8201},         /* windows uses 02 */
-       {0x08, 0x8200},
-       {0x01, 0x8200},
-
-       {0x90, 0x8604},
-       {0x00, 0x8605},
-       {0xb0, 0x8603},
-
-       /* sensor gains */
-       {0x07, 0x8601},         /* white balance - new */
-       {0x07, 0x8602},         /* white balance - new */
-       {0x00, 0x8610},         /* *red */
-       {0x00, 0x8611},         /* 3f   *green */
-       {0x00, 0x8612},         /* green *blue */
-       {0x00, 0x8613},         /* blue *green */
-       {0x43, 0x8614},         /* green *red - white balance - was 0x35 */
-       {0x40, 0x8615},         /* 40   *green - white balance - was 0x35 */
-       {0x71, 0x8616},         /* 7a   *blue - white balance - was 0x35 */
-       {0x40, 0x8617},         /* 40   *green - white balance - was 0x35 */
-
-       {0x0c, 0x8620},         /* 0c */
-       {0xc8, 0x8631},         /* c8 */
-       {0xc8, 0x8634},         /* c8 */
-       {0x23, 0x8635},         /* 23 */
-       {0x1f, 0x8636},         /* 1f */
-       {0xdd, 0x8637},         /* dd */
-       {0xe1, 0x8638},         /* e1 */
-       {0x1d, 0x8639},         /* 1d */
-       {0x21, 0x863a},         /* 21 */
-       {0xe3, 0x863b},         /* e3 */
-       {0xdf, 0x863c},         /* df */
-       {0xf0, 0x8505},
-       {0x32, 0x850a},
-/*     {0x99, 0x8700},          * - white balance - new (removed) */
-       /* HDG we used to do this in stop0, making the init state and the state
-          after a start / stop different, so do this here instead. */
-       {0x29, 0x8118},
-       {}
-};
-
-static void reg_w_val(struct usb_device *dev, __u16 index, __u8 value)
-{
-       int ret;
-
-       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-                             0,                /* request */
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             value, index, NULL, 0, 500);
-       PDEBUG(D_USBO, "reg write: 0x%02x:0x%02x", index, value);
-       if (ret < 0)
-               pr_err("reg write: error %d\n", ret);
-}
-
-static void write_vector(struct gspca_dev *gspca_dev,
-                       const __u16 data[][2])
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int i;
-
-       i = 0;
-       while (data[i][1] != 0) {
-               reg_w_val(dev, data[i][1], data[i][0]);
-               i++;
-       }
-}
-
-/* read 'len' bytes to gspca_dev->usb_buf */
-static void reg_r(struct gspca_dev *gspca_dev,
-                 __u16 index, __u16 length)
-{
-       usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       0,                      /* request */
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,                      /* value */
-                       index, gspca_dev->usb_buf, length, 500);
-}
-
-/* write 'len' bytes from gspca_dev->usb_buf */
-static void reg_w_buf(struct gspca_dev *gspca_dev,
-                     __u16 index, __u16 len)
-{
-       usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0,                      /* request */
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,                      /* value */
-                       index, gspca_dev->usb_buf, len, 500);
-}
-
-static void i2c_write(struct gspca_dev *gspca_dev, __u16 value, __u16 reg)
-{
-       int retry = 60;
-
-       reg_w_val(gspca_dev->dev, 0x8801, reg);
-       reg_w_val(gspca_dev->dev, 0x8805, value);
-       reg_w_val(gspca_dev->dev, 0x8800, value >> 8);
-       do {
-               reg_r(gspca_dev, 0x8803, 1);
-               if (!gspca_dev->usb_buf[0])
-                       return;
-               msleep(10);
-       } while (--retry);
-}
-
-static int i2c_read(struct gspca_dev *gspca_dev, __u16 reg, __u8 mode)
-{
-       int retry = 60;
-       __u8 value;
-
-       reg_w_val(gspca_dev->dev, 0x8804, 0x92);
-       reg_w_val(gspca_dev->dev, 0x8801, reg);
-       reg_w_val(gspca_dev->dev, 0x8802, mode | 0x01);
-       do {
-               reg_r(gspca_dev, 0x8803, 1);
-               if (!gspca_dev->usb_buf[0]) {
-                       reg_r(gspca_dev, 0x8800, 1);
-                       value = gspca_dev->usb_buf[0];
-                       reg_r(gspca_dev, 0x8805, 1);
-                       return ((int) value << 8) | gspca_dev->usb_buf[0];
-               }
-               msleep(10);
-       } while (--retry);
-       return -1;
-}
-
-static void sensor_mapwrite(struct gspca_dev *gspca_dev,
-                           const __u16 (*sensormap)[2])
-{
-       while ((*sensormap)[0]) {
-               gspca_dev->usb_buf[0] = (*sensormap)[1];
-               gspca_dev->usb_buf[1] = (*sensormap)[1] >> 8;
-               reg_w_buf(gspca_dev, (*sensormap)[0], 2);
-               sensormap++;
-       }
-}
-
-static void write_sensor_72a(struct gspca_dev *gspca_dev,
-                           const __u16 (*sensor)[2])
-{
-       while ((*sensor)[0]) {
-               i2c_write(gspca_dev, (*sensor)[1], (*sensor)[0]);
-               sensor++;
-       }
-}
-
-static void init_161rev12A(struct gspca_dev *gspca_dev)
-{
-       write_vector(gspca_dev, spca561_161rev12A_data1);
-       sensor_mapwrite(gspca_dev, Pb100_1map8300);
-/*fixme: should be in sd_start*/
-       write_vector(gspca_dev, spca561_161rev12A_data2);
-       sensor_mapwrite(gspca_dev, Pb100_2map8300);
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                    const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-       __u16 vendor, product;
-       __u8 data1, data2;
-
-       /* Read frm global register the USB product and vendor IDs, just to
-        * prove that we can communicate with the device.  This works, which
-        * confirms at we are communicating properly and that the device
-        * is a 561. */
-       reg_r(gspca_dev, 0x8104, 1);
-       data1 = gspca_dev->usb_buf[0];
-       reg_r(gspca_dev, 0x8105, 1);
-       data2 = gspca_dev->usb_buf[0];
-       vendor = (data2 << 8) | data1;
-       reg_r(gspca_dev, 0x8106, 1);
-       data1 = gspca_dev->usb_buf[0];
-       reg_r(gspca_dev, 0x8107, 1);
-       data2 = gspca_dev->usb_buf[0];
-       product = (data2 << 8) | data1;
-       if (vendor != id->idVendor || product != id->idProduct) {
-               PDEBUG(D_PROBE, "Bad vendor / product from device");
-               return -EINVAL;
-       }
-
-       cam = &gspca_dev->cam;
-       cam->needs_full_bandwidth = 1;
-
-       sd->chip_revision = id->driver_info;
-       if (sd->chip_revision == Rev012A) {
-               cam->cam_mode = sif_012a_mode;
-               cam->nmodes = ARRAY_SIZE(sif_012a_mode);
-       } else {
-               cam->cam_mode = sif_072a_mode;
-               cam->nmodes = ARRAY_SIZE(sif_072a_mode);
-       }
-       sd->expo12a = EXPO12A_DEF;
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init_12a(struct gspca_dev *gspca_dev)
-{
-       PDEBUG(D_STREAM, "Chip revision: 012a");
-       init_161rev12A(gspca_dev);
-       return 0;
-}
-static int sd_init_72a(struct gspca_dev *gspca_dev)
-{
-       PDEBUG(D_STREAM, "Chip revision: 072a");
-       write_vector(gspca_dev, rev72a_reset);
-       msleep(200);
-       write_vector(gspca_dev, rev72a_init_data1);
-       write_sensor_72a(gspca_dev, rev72a_init_sensor1);
-       write_vector(gspca_dev, rev72a_init_data2);
-       write_sensor_72a(gspca_dev, rev72a_init_sensor2);
-       reg_w_val(gspca_dev->dev, 0x8112, 0x30);
-       return 0;
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct usb_device *dev = gspca_dev->dev;
-       __u16 reg;
-
-       if (sd->chip_revision == Rev012A)
-               reg = 0x8610;
-       else
-               reg = 0x8611;
-
-       reg_w_val(dev, reg + 0, val);           /* R */
-       reg_w_val(dev, reg + 1, val);           /* Gr */
-       reg_w_val(dev, reg + 2, val);           /* B */
-       reg_w_val(dev, reg + 3, val);           /* Gb */
-}
-
-static void setwhite(struct gspca_dev *gspca_dev, s32 white, s32 contrast)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct usb_device *dev = gspca_dev->dev;
-       __u8 blue, red;
-       __u16 reg;
-
-       /* try to emulate MS-win as possible */
-       red = 0x20 + white * 3 / 8;
-       blue = 0x90 - white * 5 / 8;
-       if (sd->chip_revision == Rev012A) {
-               reg = 0x8614;
-       } else {
-               reg = 0x8651;
-               red += contrast - 0x20;
-               blue += contrast - 0x20;
-               reg_w_val(dev, 0x8652, contrast + 0x20); /* Gr */
-               reg_w_val(dev, 0x8654, contrast + 0x20); /* Gb */
-       }
-       reg_w_val(dev, reg, red);
-       reg_w_val(dev, reg + 2, blue);
-}
-
-/* rev 12a only */
-static void setexposure(struct gspca_dev *gspca_dev, s32 val)
-{
-       int i, expo = 0;
-
-       /* Register 0x8309 controls exposure for the spca561,
-          the basic exposure setting goes from 1-2047, where 1 is completely
-          dark and 2047 is very bright. It not only influences exposure but
-          also the framerate (to allow for longer exposure) from 1 - 300 it
-          only raises the exposure time then from 300 - 600 it halves the
-          framerate to be able to further raise the exposure time and for every
-          300 more it halves the framerate again. This allows for a maximum
-          exposure time of circa 0.2 - 0.25 seconds (30 / (2000/3000) fps).
-          Sometimes this is not enough, the 1-2047 uses bits 0-10, bits 11-12
-          configure a divider for the base framerate which us used at the
-          exposure setting of 1-300. These bits configure the base framerate
-          according to the following formula: fps = 60 / (value + 2) */
-
-       /* We choose to use the high bits setting the fixed framerate divisor
-          asap, as setting high basic exposure setting without the fixed
-          divider in combination with high gains makes the cam stop */
-       int table[] =  { 0, 450, 550, 625, EXPOSURE_MAX };
-
-       for (i = 0; i < ARRAY_SIZE(table) - 1; i++) {
-               if (val <= table[i + 1]) {
-                       expo  = val - table[i];
-                       if (i)
-                               expo += 300;
-                       expo |= i << 11;
-                       break;
-               }
-       }
-
-       gspca_dev->usb_buf[0] = expo;
-       gspca_dev->usb_buf[1] = expo >> 8;
-       reg_w_buf(gspca_dev, 0x8309, 2);
-}
-
-/* rev 12a only */
-static void setgain(struct gspca_dev *gspca_dev, s32 val)
-{
-       /* gain reg low 6 bits  0-63 gain, bit 6 and 7, both double the
-          sensitivity when set, so 31 + one of them set == 63, and 15
-          with both of them set == 63 */
-       if (val < 64)
-               gspca_dev->usb_buf[0] = val;
-       else if (val < 128)
-               gspca_dev->usb_buf[0] = (val / 2) | 0x40;
-       else
-               gspca_dev->usb_buf[0] = (val / 4) | 0xc0;
-
-       gspca_dev->usb_buf[1] = 0;
-       reg_w_buf(gspca_dev, 0x8335, 2);
-}
-
-static void setautogain(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (val)
-               sd->ag_cnt = AG_CNT_START;
-       else
-               sd->ag_cnt = -1;
-}
-
-static int sd_start_12a(struct gspca_dev *gspca_dev)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int mode;
-       static const __u8 Reg8391[8] =
-               {0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00};
-
-       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
-       if (mode <= 1) {
-               /* Use compression on 320x240 and above */
-               reg_w_val(dev, 0x8500, 0x10 | mode);
-       } else {
-               /* I couldn't get the compression to work below 320x240
-                * Fortunately at these resolutions the bandwidth
-                * is sufficient to push raw frames at ~20fps */
-               reg_w_val(dev, 0x8500, mode);
-       }               /* -- qq@kuku.eu.org */
-
-       gspca_dev->usb_buf[0] = 0xaa;
-       gspca_dev->usb_buf[1] = 0x00;
-       reg_w_buf(gspca_dev, 0x8307, 2);
-       /* clock - lower 0x8X values lead to fps > 30 */
-       reg_w_val(gspca_dev->dev, 0x8700, 0x8a);
-                                       /* 0x8f 0x85 0x27 clock */
-       reg_w_val(gspca_dev->dev, 0x8112, 0x1e | 0x20);
-       reg_w_val(gspca_dev->dev, 0x850b, 0x03);
-       memcpy(gspca_dev->usb_buf, Reg8391, 8);
-       reg_w_buf(gspca_dev, 0x8391, 8);
-       reg_w_buf(gspca_dev, 0x8390, 8);
-
-       /* Led ON (bit 3 -> 0 */
-       reg_w_val(gspca_dev->dev, 0x8114, 0x00);
-       return 0;
-}
-static int sd_start_72a(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct usb_device *dev = gspca_dev->dev;
-       int Clck;
-       int mode;
-
-       write_vector(gspca_dev, rev72a_reset);
-       msleep(200);
-       write_vector(gspca_dev, rev72a_init_data1);
-       write_sensor_72a(gspca_dev, rev72a_init_sensor1);
-
-       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
-       switch (mode) {
-       default:
-       case 0:
-               Clck = 0x27;            /* ms-win 0x87 */
-               break;
-       case 1:
-               Clck = 0x25;
-               break;
-       case 2:
-               Clck = 0x22;
-               break;
-       case 3:
-               Clck = 0x21;
-               break;
-       }
-       reg_w_val(dev, 0x8700, Clck);   /* 0x27 clock */
-       reg_w_val(dev, 0x8702, 0x81);
-       reg_w_val(dev, 0x8500, mode);   /* mode */
-       write_sensor_72a(gspca_dev, rev72a_init_sensor2);
-       setwhite(gspca_dev, v4l2_ctrl_g_ctrl(sd->hue),
-                       v4l2_ctrl_g_ctrl(sd->contrast));
-/*     setbrightness(gspca_dev);        * fixme: bad values */
-       setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
-       reg_w_val(dev, 0x8112, 0x10 | 0x20);
-       return 0;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->chip_revision == Rev012A) {
-               reg_w_val(gspca_dev->dev, 0x8112, 0x0e);
-               /* Led Off (bit 3 -> 1 */
-               reg_w_val(gspca_dev->dev, 0x8114, 0x08);
-       } else {
-               reg_w_val(gspca_dev->dev, 0x8112, 0x20);
-/*             reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */
-       }
-}
-
-static void do_autogain(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int expotimes;
-       int pixelclk;
-       int gainG;
-       __u8 R, Gr, Gb, B;
-       int y;
-       __u8 luma_mean = 110;
-       __u8 luma_delta = 20;
-       __u8 spring = 4;
-
-       if (sd->ag_cnt < 0)
-               return;
-       if (--sd->ag_cnt >= 0)
-               return;
-       sd->ag_cnt = AG_CNT_START;
-
-       switch (sd->chip_revision) {
-       case Rev072A:
-               reg_r(gspca_dev, 0x8621, 1);
-               Gr = gspca_dev->usb_buf[0];
-               reg_r(gspca_dev, 0x8622, 1);
-               R = gspca_dev->usb_buf[0];
-               reg_r(gspca_dev, 0x8623, 1);
-               B = gspca_dev->usb_buf[0];
-               reg_r(gspca_dev, 0x8624, 1);
-               Gb = gspca_dev->usb_buf[0];
-               y = (77 * R + 75 * (Gr + Gb) + 29 * B) >> 8;
-               /* u= (128*B-(43*(Gr+Gb+R))) >> 8; */
-               /* v= (128*R-(53*(Gr+Gb))-21*B) >> 8; */
-               /* PDEBUG(D_CONF,"reading Y %d U %d V %d ",y,u,v); */
-
-               if (y < luma_mean - luma_delta ||
-                   y > luma_mean + luma_delta) {
-                       expotimes = i2c_read(gspca_dev, 0x09, 0x10);
-                       pixelclk = 0x0800;
-                       expotimes = expotimes & 0x07ff;
-                       /* PDEBUG(D_PACK,
-                               "Exposition Times 0x%03X Clock 0x%04X ",
-                               expotimes,pixelclk); */
-                       gainG = i2c_read(gspca_dev, 0x35, 0x10);
-                       /* PDEBUG(D_PACK,
-                               "reading Gain register %d", gainG); */
-
-                       expotimes += (luma_mean - y) >> spring;
-                       gainG += (luma_mean - y) / 50;
-                       /* PDEBUG(D_PACK,
-                               "compute expotimes %d gain %d",
-                               expotimes,gainG); */
-
-                       if (gainG > 0x3f)
-                               gainG = 0x3f;
-                       else if (gainG < 3)
-                               gainG = 3;
-                       i2c_write(gspca_dev, gainG, 0x35);
-
-                       if (expotimes > 0x0256)
-                               expotimes = 0x0256;
-                       else if (expotimes < 3)
-                               expotimes = 3;
-                       i2c_write(gspca_dev, expotimes | pixelclk, 0x09);
-               }
-               break;
-       }
-}
-
-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;
-
-       len--;
-       switch (*data++) {                      /* sequence number */
-       case 0:                                 /* start of frame */
-               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-
-               /* This should never happen */
-               if (len < 2) {
-                       PDEBUG(D_ERR, "Short SOF packet, ignoring");
-                       gspca_dev->last_packet_type = DISCARD_PACKET;
-                       return;
-               }
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-               if (data[0] & 0x20) {
-                       input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
-                       input_sync(gspca_dev->input_dev);
-                       input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
-                       input_sync(gspca_dev->input_dev);
-               }
-#endif
-
-               if (data[1] & 0x10) {
-                       /* compressed bayer */
-                       gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
-               } else {
-                       /* raw bayer (with a header, which we skip) */
-                       if (sd->chip_revision == Rev012A) {
-                               data += 20;
-                               len -= 20;
-                       } else {
-                               data += 16;
-                               len -= 16;
-                       }
-                       gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
-               }
-               return;
-       case 0xff:                      /* drop (empty mpackets) */
-               return;
-       }
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-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_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               /* hue/contrast control cluster for 72a */
-               setwhite(gspca_dev, sd->hue->val, ctrl->val);
-               break;
-       case V4L2_CID_HUE:
-               /* just plain hue control for 12a */
-               setwhite(gspca_dev, ctrl->val, 0);
-               break;
-       case V4L2_CID_EXPOSURE:
-               setexposure(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_GAIN:
-               setgain(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               setautogain(gspca_dev, ctrl->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_12a(struct gspca_dev *gspca_dev)
-{
-       struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 3);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_HUE, 1, 0x7f, 1, 0x40);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 1, EXPOSURE_MAX, 1, 700);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAIN, 0, 255, 1, 63);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-       return 0;
-}
-
-static int sd_init_controls_72a(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);
-       sd->contrast = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 0x3f, 1, 0x20);
-       sd->hue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_HUE, 1, 0x7f, 1, 0x40);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 0x3f, 1, 0x20);
-       sd->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-       v4l2_ctrl_cluster(2, &sd->contrast);
-       return 0;
-}
-
-/* sub-driver description */
-static const struct sd_desc sd_desc_12a = {
-       .name = MODULE_NAME,
-       .init_controls = sd_init_controls_12a,
-       .config = sd_config,
-       .init = sd_init_12a,
-       .start = sd_start_12a,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .other_input = 1,
-#endif
-};
-static const struct sd_desc sd_desc_72a = {
-       .name = MODULE_NAME,
-       .init_controls = sd_init_controls_72a,
-       .config = sd_config,
-       .init = sd_init_72a,
-       .start = sd_start_72a,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-       .dq_callback = do_autogain,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .other_input = 1,
-#endif
-};
-static const struct sd_desc *sd_desc[2] = {
-       &sd_desc_12a,
-       &sd_desc_72a
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A},
-       {USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A},
-       {USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A},
-       {USB_DEVICE(0x0461, 0x0815), .driver_info = Rev072A},
-       {USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A},
-       {USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A},
-       {USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A},
-       {USB_DEVICE(0x046d, 0x092b), .driver_info = Rev012A},
-       {USB_DEVICE(0x046d, 0x092c), .driver_info = Rev012A},
-       {USB_DEVICE(0x046d, 0x092d), .driver_info = Rev012A},
-       {USB_DEVICE(0x046d, 0x092e), .driver_info = Rev012A},
-       {USB_DEVICE(0x046d, 0x092f), .driver_info = Rev012A},
-       {USB_DEVICE(0x04fc, 0x0561), .driver_info = Rev072A},
-       {USB_DEVICE(0x060b, 0xa001), .driver_info = Rev072A},
-       {USB_DEVICE(0x10fd, 0x7e50), .driver_info = Rev072A},
-       {USB_DEVICE(0xabcd, 0xcdee), .driver_info = Rev072A},
-       {}
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-static int sd_probe(struct usb_interface *intf,
-                   const struct usb_device_id *id)
-{
-       return gspca_dev_probe(intf, id,
-                               sd_desc[id->driver_info],
-                               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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/sq905.c b/drivers/media/video/gspca/sq905.c
deleted file mode 100644 (file)
index a8ac979..0000000
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * SQ905 subdriver
- *
- * Copyright (C) 2008, 2009 Adam Baker and Theodore Kilgore
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- * History and Acknowledgments
- *
- * The original Linux driver for SQ905 based cameras was written by
- * Marcell Lengyel and furter developed by many other contributors
- * and is available from http://sourceforge.net/projects/sqcam/
- *
- * This driver takes advantage of the reverse engineering work done for
- * that driver and for libgphoto2 but shares no code with them.
- *
- * This driver has used as a base the finepix driver and other gspca
- * based drivers and may still contain code fragments taken from those
- * drivers.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "sq905"
-
-#include <linux/workqueue.h>
-#include <linux/slab.h>
-#include "gspca.h"
-
-MODULE_AUTHOR("Adam Baker <linux@baker-net.org.uk>, "
-               "Theodore Kilgore <kilgota@auburn.edu>");
-MODULE_DESCRIPTION("GSPCA/SQ905 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* Default timeouts, in ms */
-#define SQ905_CMD_TIMEOUT 500
-#define SQ905_DATA_TIMEOUT 1000
-
-/* Maximum transfer size to use. */
-#define SQ905_MAX_TRANSFER 0x8000
-#define FRAME_HEADER_LEN 64
-
-/* The known modes, or registers. These go in the "value" slot. */
-
-/* 00 is "none" obviously */
-
-#define SQ905_BULK_READ        0x03    /* precedes any bulk read */
-#define SQ905_COMMAND  0x06    /* precedes the command codes below */
-#define SQ905_PING     0x07    /* when reading an "idling" command */
-#define SQ905_READ_DONE 0xc0    /* ack bulk read completed */
-
-/* Any non-zero value in the bottom 2 bits of the 2nd byte of
- * the ID appears to indicate the camera can do 640*480. If the
- * LSB of that byte is set the image is just upside down, otherwise
- * it is rotated 180 degrees. */
-#define SQ905_HIRES_MASK       0x00000300
-#define SQ905_ORIENTATION_MASK 0x00000100
-
-/* Some command codes. These go in the "index" slot. */
-
-#define SQ905_ID      0xf0     /* asks for model string */
-#define SQ905_CONFIG  0x20     /* gets photo alloc. table, not used here */
-#define SQ905_DATA    0x30     /* accesses photo data, not used here */
-#define SQ905_CLEAR   0xa0     /* clear everything */
-#define SQ905_CAPTURE_LOW  0x60        /* Starts capture at 160x120 */
-#define SQ905_CAPTURE_MED  0x61        /* Starts capture at 320x240 */
-#define SQ905_CAPTURE_HIGH 0x62        /* Starts capture at 640x480 (some cams only) */
-/* note that the capture command also controls the output dimensions */
-
-/* Structure to hold all of our device specific stuff */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       /*
-        * Driver stuff
-        */
-       struct work_struct work_struct;
-       struct workqueue_struct *work_thread;
-};
-
-static struct v4l2_pix_format sq905_mode[] = {
-       { 160, 120, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-       { 320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-       { 640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0}
-};
-
-/*
- * Send a command to the camera.
- */
-static int sq905_command(struct gspca_dev *gspca_dev, u16 index)
-{
-       int ret;
-
-       gspca_dev->usb_buf[0] = '\0';
-       ret = usb_control_msg(gspca_dev->dev,
-                             usb_sndctrlpipe(gspca_dev->dev, 0),
-                             USB_REQ_SYNCH_FRAME,                /* request */
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             SQ905_COMMAND, index, gspca_dev->usb_buf, 1,
-                             SQ905_CMD_TIMEOUT);
-       if (ret < 0) {
-               pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
-               return ret;
-       }
-
-       ret = usb_control_msg(gspca_dev->dev,
-                             usb_sndctrlpipe(gspca_dev->dev, 0),
-                             USB_REQ_SYNCH_FRAME,                /* request */
-                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             SQ905_PING, 0, gspca_dev->usb_buf, 1,
-                             SQ905_CMD_TIMEOUT);
-       if (ret < 0) {
-               pr_err("%s: usb_control_msg failed 2 (%d)\n", __func__, ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-/*
- * Acknowledge the end of a frame - see warning on sq905_command.
- */
-static int sq905_ack_frame(struct gspca_dev *gspca_dev)
-{
-       int ret;
-
-       gspca_dev->usb_buf[0] = '\0';
-       ret = usb_control_msg(gspca_dev->dev,
-                             usb_sndctrlpipe(gspca_dev->dev, 0),
-                             USB_REQ_SYNCH_FRAME,                /* request */
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             SQ905_READ_DONE, 0, gspca_dev->usb_buf, 1,
-                             SQ905_CMD_TIMEOUT);
-       if (ret < 0) {
-               pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-/*
- *  request and read a block of data - see warning on sq905_command.
- */
-static int
-sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock)
-{
-       int ret;
-       int act_len;
-
-       gspca_dev->usb_buf[0] = '\0';
-       if (need_lock)
-               mutex_lock(&gspca_dev->usb_lock);
-       ret = usb_control_msg(gspca_dev->dev,
-                             usb_sndctrlpipe(gspca_dev->dev, 0),
-                             USB_REQ_SYNCH_FRAME,                /* request */
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             SQ905_BULK_READ, size, gspca_dev->usb_buf,
-                             1, SQ905_CMD_TIMEOUT);
-       if (need_lock)
-               mutex_unlock(&gspca_dev->usb_lock);
-       if (ret < 0) {
-               pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
-               return ret;
-       }
-       ret = usb_bulk_msg(gspca_dev->dev,
-                          usb_rcvbulkpipe(gspca_dev->dev, 0x81),
-                          data, size, &act_len, SQ905_DATA_TIMEOUT);
-
-       /* successful, it returns 0, otherwise  negative */
-       if (ret < 0 || act_len != size) {
-               pr_err("bulk read fail (%d) len %d/%d\n", ret, act_len, size);
-               return -EIO;
-       }
-       return 0;
-}
-
-/* This function is called as a workqueue function and runs whenever the camera
- * is streaming data. Because it is a workqueue function it is allowed to sleep
- * so we can use synchronous USB calls. To avoid possible collisions with other
- * threads attempting to use the camera's USB interface we take the gspca
- * usb_lock when performing USB operations. In practice the only thing we need
- * to protect against is the usb_set_interface call that gspca makes during
- * stream_off as the camera doesn't provide any controls that the user could try
- * to change.
- */
-static void sq905_dostream(struct work_struct *work)
-{
-       struct sd *dev = container_of(work, struct sd, work_struct);
-       struct gspca_dev *gspca_dev = &dev->gspca_dev;
-       int bytes_left; /* bytes remaining in current frame. */
-       int data_len;   /* size to use for the next read. */
-       int header_read; /* true if we have already read the frame header. */
-       int packet_type;
-       int frame_sz;
-       int ret;
-       u8 *data;
-       u8 *buffer;
-
-       buffer = kmalloc(SQ905_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
-       if (!buffer) {
-               pr_err("Couldn't allocate USB buffer\n");
-               goto quit_stream;
-       }
-
-       frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage
-                       + FRAME_HEADER_LEN;
-
-       while (gspca_dev->dev && gspca_dev->streaming) {
-#ifdef CONFIG_PM
-               if (gspca_dev->frozen)
-                       break;
-#endif
-               /* request some data and then read it until we have
-                * a complete frame. */
-               bytes_left = frame_sz;
-               header_read = 0;
-
-               /* Note we do not check for gspca_dev->streaming here, as
-                  we must finish reading an entire frame, otherwise the
-                  next time we stream we start reading in the middle of a
-                  frame. */
-               while (bytes_left > 0 && gspca_dev->dev) {
-                       data_len = bytes_left > SQ905_MAX_TRANSFER ?
-                               SQ905_MAX_TRANSFER : bytes_left;
-                       ret = sq905_read_data(gspca_dev, buffer, data_len, 1);
-                       if (ret < 0)
-                               goto quit_stream;
-                       PDEBUG(D_PACK,
-                               "Got %d bytes out of %d for frame",
-                               data_len, bytes_left);
-                       bytes_left -= data_len;
-                       data = buffer;
-                       if (!header_read) {
-                               packet_type = FIRST_PACKET;
-                               /* The first 64 bytes of each frame are
-                                * a header full of FF 00 bytes */
-                               data += FRAME_HEADER_LEN;
-                               data_len -= FRAME_HEADER_LEN;
-                               header_read = 1;
-                       } else if (bytes_left == 0) {
-                               packet_type = LAST_PACKET;
-                       } else {
-                               packet_type = INTER_PACKET;
-                       }
-                       gspca_frame_add(gspca_dev, packet_type,
-                                       data, data_len);
-                       /* If entire frame fits in one packet we still
-                          need to add a LAST_PACKET */
-                       if (packet_type == FIRST_PACKET &&
-                           bytes_left == 0)
-                               gspca_frame_add(gspca_dev, LAST_PACKET,
-                                               NULL, 0);
-               }
-               if (gspca_dev->dev) {
-                       /* acknowledge the frame */
-                       mutex_lock(&gspca_dev->usb_lock);
-                       ret = sq905_ack_frame(gspca_dev);
-                       mutex_unlock(&gspca_dev->usb_lock);
-                       if (ret < 0)
-                               goto quit_stream;
-               }
-       }
-quit_stream:
-       if (gspca_dev->dev) {
-               mutex_lock(&gspca_dev->usb_lock);
-               sq905_command(gspca_dev, SQ905_CLEAR);
-               mutex_unlock(&gspca_dev->usb_lock);
-       }
-       kfree(buffer);
-}
-
-/* This function is called at probe time just before sd_init */
-static int sd_config(struct gspca_dev *gspca_dev,
-               const struct usb_device_id *id)
-{
-       struct cam *cam = &gspca_dev->cam;
-       struct sd *dev = (struct sd *) gspca_dev;
-
-       /* We don't use the buffer gspca allocates so make it small. */
-       cam->bulk = 1;
-       cam->bulk_size = 64;
-
-       INIT_WORK(&dev->work_struct, sq905_dostream);
-
-       return 0;
-}
-
-/* called on streamoff with alt==0 and on disconnect */
-/* the usb_lock is held at entry - restore on exit */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       struct sd *dev = (struct sd *) gspca_dev;
-
-       /* wait for the work queue to terminate */
-       mutex_unlock(&gspca_dev->usb_lock);
-       /* This waits for sq905_dostream to finish */
-       destroy_workqueue(dev->work_thread);
-       dev->work_thread = NULL;
-       mutex_lock(&gspca_dev->usb_lock);
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       u32 ident;
-       int ret;
-
-       /* connect to the camera and read
-        * the model ID and process that and put it away.
-        */
-       ret = sq905_command(gspca_dev, SQ905_CLEAR);
-       if (ret < 0)
-               return ret;
-       ret = sq905_command(gspca_dev, SQ905_ID);
-       if (ret < 0)
-               return ret;
-       ret = sq905_read_data(gspca_dev, gspca_dev->usb_buf, 4, 0);
-       if (ret < 0)
-               return ret;
-       /* usb_buf is allocated with kmalloc so is aligned.
-        * Camera model number is the right way round if we assume this
-        * reverse engineered ID is supposed to be big endian. */
-       ident = be32_to_cpup((__be32 *)gspca_dev->usb_buf);
-       ret = sq905_command(gspca_dev, SQ905_CLEAR);
-       if (ret < 0)
-               return ret;
-       PDEBUG(D_CONF, "SQ905 camera ID %08x detected", ident);
-       gspca_dev->cam.cam_mode = sq905_mode;
-       gspca_dev->cam.nmodes = ARRAY_SIZE(sq905_mode);
-       if (!(ident & SQ905_HIRES_MASK))
-               gspca_dev->cam.nmodes--;
-
-       if (ident & SQ905_ORIENTATION_MASK)
-               gspca_dev->cam.input_flags = V4L2_IN_ST_VFLIP;
-       else
-               gspca_dev->cam.input_flags = V4L2_IN_ST_VFLIP |
-                                            V4L2_IN_ST_HFLIP;
-       return 0;
-}
-
-/* Set up for getting frames. */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *dev = (struct sd *) gspca_dev;
-       int ret;
-
-       /* "Open the shutter" and set size, to start capture */
-       switch (gspca_dev->curr_mode) {
-       default:
-/*     case 2: */
-               PDEBUG(D_STREAM, "Start streaming at high resolution");
-               ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_HIGH);
-               break;
-       case 1:
-               PDEBUG(D_STREAM, "Start streaming at medium resolution");
-               ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_MED);
-               break;
-       case 0:
-               PDEBUG(D_STREAM, "Start streaming at low resolution");
-               ret = sq905_command(&dev->gspca_dev, SQ905_CAPTURE_LOW);
-       }
-
-       if (ret < 0) {
-               PDEBUG(D_ERR, "Start streaming command failed");
-               return ret;
-       }
-       /* Start the workqueue function to do the streaming */
-       dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
-       queue_work(dev->work_thread, &dev->work_struct);
-
-       return 0;
-}
-
-/* Table of supported USB devices */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x2770, 0x9120)},
-       {}
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* sub-driver description */
-static const struct sd_desc sd_desc = {
-       .name   = MODULE_NAME,
-       .config = sd_config,
-       .init   = sd_init,
-       .start  = sd_start,
-       .stop0  = sd_stop0,
-};
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/sq905c.c b/drivers/media/video/gspca/sq905c.c
deleted file mode 100644 (file)
index 70fae69..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * SQ905C subdriver
- *
- * Copyright (C) 2009 Theodore Kilgore
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/*
- *
- * This driver uses work done in
- * libgphoto2/camlibs/digigr8, Copyright (C) Theodore Kilgore.
- *
- * This driver has also used as a base the sq905c driver
- * and may contain code fragments from it.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "sq905c"
-
-#include <linux/workqueue.h>
-#include <linux/slab.h>
-#include "gspca.h"
-
-MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>");
-MODULE_DESCRIPTION("GSPCA/SQ905C USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* Default timeouts, in ms */
-#define SQ905C_CMD_TIMEOUT 500
-#define SQ905C_DATA_TIMEOUT 1000
-
-/* Maximum transfer size to use. */
-#define SQ905C_MAX_TRANSFER 0x8000
-
-#define FRAME_HEADER_LEN 0x50
-
-/* Commands. These go in the "value" slot. */
-#define SQ905C_CLEAR   0xa0            /* clear everything */
-#define SQ905C_GET_ID  0x14f4          /* Read version number */
-#define SQ905C_CAPTURE_LOW 0xa040      /* Starts capture at 160x120 */
-#define SQ905C_CAPTURE_MED 0x1440      /* Starts capture at 320x240 */
-#define SQ905C_CAPTURE_HI 0x2840       /* Starts capture at 320x240 */
-
-/* For capture, this must go in the "index" slot. */
-#define SQ905C_CAPTURE_INDEX 0x110f
-
-/* Structure to hold all of our device specific stuff */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-       const struct v4l2_pix_format *cap_mode;
-       /* Driver stuff */
-       struct work_struct work_struct;
-       struct workqueue_struct *work_thread;
-};
-
-/*
- * Most of these cameras will do 640x480 and 320x240. 160x120 works
- * in theory but gives very poor output. Therefore, not supported.
- * The 0x2770:0x9050 cameras have max resolution of 320x240.
- */
-static struct v4l2_pix_format sq905c_mode[] = {
-       { 320, 240, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-       { 640, 480, V4L2_PIX_FMT_SQ905C, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0}
-};
-
-/* Send a command to the camera. */
-static int sq905c_command(struct gspca_dev *gspca_dev, u16 command, u16 index)
-{
-       int ret;
-
-       ret = usb_control_msg(gspca_dev->dev,
-                             usb_sndctrlpipe(gspca_dev->dev, 0),
-                             USB_REQ_SYNCH_FRAME,                /* request */
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             command, index, NULL, 0,
-                             SQ905C_CMD_TIMEOUT);
-       if (ret < 0) {
-               pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index,
-                      int size)
-{
-       int ret;
-
-       ret = usb_control_msg(gspca_dev->dev,
-                             usb_rcvctrlpipe(gspca_dev->dev, 0),
-                             USB_REQ_SYNCH_FRAME,              /* request */
-                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             command, index, gspca_dev->usb_buf, size,
-                             SQ905C_CMD_TIMEOUT);
-       if (ret < 0) {
-               pr_err("%s: usb_control_msg failed (%d)\n", __func__, ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-/* This function is called as a workqueue function and runs whenever the camera
- * is streaming data. Because it is a workqueue function it is allowed to sleep
- * so we can use synchronous USB calls. To avoid possible collisions with other
- * threads attempting to use the camera's USB interface the gspca usb_lock is
- * used when performing the one USB control operation inside the workqueue,
- * which tells the camera to close the stream. In practice the only thing
- * which needs to be protected against is the usb_set_interface call that
- * gspca makes during stream_off. Otherwise the camera doesn't provide any
- * controls that the user could try to change.
- */
-static void sq905c_dostream(struct work_struct *work)
-{
-       struct sd *dev = container_of(work, struct sd, work_struct);
-       struct gspca_dev *gspca_dev = &dev->gspca_dev;
-       int bytes_left; /* bytes remaining in current frame. */
-       int data_len;   /* size to use for the next read. */
-       int act_len;
-       int packet_type;
-       int ret;
-       u8 *buffer;
-
-       buffer = kmalloc(SQ905C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA);
-       if (!buffer) {
-               pr_err("Couldn't allocate USB buffer\n");
-               goto quit_stream;
-       }
-
-       while (gspca_dev->dev && gspca_dev->streaming) {
-#ifdef CONFIG_PM
-               if (gspca_dev->frozen)
-                       break;
-#endif
-               /* Request the header, which tells the size to download */
-               ret = usb_bulk_msg(gspca_dev->dev,
-                               usb_rcvbulkpipe(gspca_dev->dev, 0x81),
-                               buffer, FRAME_HEADER_LEN, &act_len,
-                               SQ905C_DATA_TIMEOUT);
-               PDEBUG(D_STREAM,
-                       "Got %d bytes out of %d for header",
-                       act_len, FRAME_HEADER_LEN);
-               if (ret < 0 || act_len < FRAME_HEADER_LEN)
-                       goto quit_stream;
-               /* size is read from 4 bytes starting 0x40, little endian */
-               bytes_left = buffer[0x40]|(buffer[0x41]<<8)|(buffer[0x42]<<16)
-                                       |(buffer[0x43]<<24);
-               PDEBUG(D_STREAM, "bytes_left = 0x%x", bytes_left);
-               /* We keep the header. It has other information, too. */
-               packet_type = FIRST_PACKET;
-               gspca_frame_add(gspca_dev, packet_type,
-                               buffer, FRAME_HEADER_LEN);
-               while (bytes_left > 0 && gspca_dev->dev) {
-                       data_len = bytes_left > SQ905C_MAX_TRANSFER ?
-                               SQ905C_MAX_TRANSFER : bytes_left;
-                       ret = usb_bulk_msg(gspca_dev->dev,
-                               usb_rcvbulkpipe(gspca_dev->dev, 0x81),
-                               buffer, data_len, &act_len,
-                               SQ905C_DATA_TIMEOUT);
-                       if (ret < 0 || act_len < data_len)
-                               goto quit_stream;
-                       PDEBUG(D_STREAM,
-                               "Got %d bytes out of %d for frame",
-                               data_len, bytes_left);
-                       bytes_left -= data_len;
-                       if (bytes_left == 0)
-                               packet_type = LAST_PACKET;
-                       else
-                               packet_type = INTER_PACKET;
-                       gspca_frame_add(gspca_dev, packet_type,
-                                       buffer, data_len);
-               }
-       }
-quit_stream:
-       if (gspca_dev->dev) {
-               mutex_lock(&gspca_dev->usb_lock);
-               sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
-               mutex_unlock(&gspca_dev->usb_lock);
-       }
-       kfree(buffer);
-}
-
-/* This function is called at probe time just before sd_init */
-static int sd_config(struct gspca_dev *gspca_dev,
-               const struct usb_device_id *id)
-{
-       struct cam *cam = &gspca_dev->cam;
-       struct sd *dev = (struct sd *) gspca_dev;
-       int ret;
-
-       PDEBUG(D_PROBE,
-               "SQ9050 camera detected"
-               " (vid/pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
-
-       ret = sq905c_command(gspca_dev, SQ905C_GET_ID, 0);
-       if (ret < 0) {
-               PDEBUG(D_ERR, "Get version command failed");
-               return ret;
-       }
-
-       ret = sq905c_read(gspca_dev, 0xf5, 0, 20);
-       if (ret < 0) {
-               PDEBUG(D_ERR, "Reading version command failed");
-               return ret;
-       }
-       /* Note we leave out the usb id and the manufacturing date */
-       PDEBUG(D_PROBE,
-              "SQ9050 ID string: %02x - %*ph",
-               gspca_dev->usb_buf[3], 6, gspca_dev->usb_buf + 14);
-
-       cam->cam_mode = sq905c_mode;
-       cam->nmodes = 2;
-       if (gspca_dev->usb_buf[15] == 0)
-               cam->nmodes = 1;
-       /* We don't use the buffer gspca allocates so make it small. */
-       cam->bulk_size = 32;
-       cam->bulk = 1;
-       INIT_WORK(&dev->work_struct, sq905c_dostream);
-       return 0;
-}
-
-/* called on streamoff with alt==0 and on disconnect */
-/* the usb_lock is held at entry - restore on exit */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       struct sd *dev = (struct sd *) gspca_dev;
-
-       /* wait for the work queue to terminate */
-       mutex_unlock(&gspca_dev->usb_lock);
-       /* This waits for sq905c_dostream to finish */
-       destroy_workqueue(dev->work_thread);
-       dev->work_thread = NULL;
-       mutex_lock(&gspca_dev->usb_lock);
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       int ret;
-
-       /* connect to the camera and reset it. */
-       ret = sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
-       return ret;
-}
-
-/* Set up for getting frames. */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *dev = (struct sd *) gspca_dev;
-       int ret;
-
-       dev->cap_mode = gspca_dev->cam.cam_mode;
-       /* "Open the shutter" and set size, to start capture */
-       switch (gspca_dev->width) {
-       case 640:
-               PDEBUG(D_STREAM, "Start streaming at high resolution");
-               dev->cap_mode++;
-               ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_HI,
-                                               SQ905C_CAPTURE_INDEX);
-               break;
-       default: /* 320 */
-       PDEBUG(D_STREAM, "Start streaming at medium resolution");
-               ret = sq905c_command(gspca_dev, SQ905C_CAPTURE_MED,
-                                               SQ905C_CAPTURE_INDEX);
-       }
-
-       if (ret < 0) {
-               PDEBUG(D_ERR, "Start streaming command failed");
-               return ret;
-       }
-       /* Start the workqueue function to do the streaming */
-       dev->work_thread = create_singlethread_workqueue(MODULE_NAME);
-       queue_work(dev->work_thread, &dev->work_struct);
-
-       return 0;
-}
-
-/* Table of supported USB devices */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x2770, 0x905c)},
-       {USB_DEVICE(0x2770, 0x9050)},
-       {USB_DEVICE(0x2770, 0x9051)},
-       {USB_DEVICE(0x2770, 0x9052)},
-       {USB_DEVICE(0x2770, 0x913d)},
-       {}
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* sub-driver description */
-static const struct sd_desc sd_desc = {
-       .name   = MODULE_NAME,
-       .config = sd_config,
-       .init   = sd_init,
-       .start  = sd_start,
-       .stop0  = sd_stop0,
-};
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/sq930x.c b/drivers/media/video/gspca/sq930x.c
deleted file mode 100644 (file)
index 7e8748b..0000000
+++ /dev/null
@@ -1,1164 +0,0 @@
-/*
- * SQ930x subdriver
- *
- * Copyright (C) 2010 Jean-François Moine <http://moinejf.free.fr>
- * Copyright (C) 2006 -2008 Gerard Klaver <gerard at gkall dot hobby dot nl>
- * Copyright (C) 2007 Sam Revitch <samr7@cs.washington.edu>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "sq930x"
-
-#include "gspca.h"
-
-MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>\n"
-               "Gerard Klaver <gerard at gkall dot hobby dot nl\n"
-               "Sam Revitch <samr7@cs.washington.edu>");
-MODULE_DESCRIPTION("GSPCA/SQ930x USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* Structure to hold all of our device specific stuff */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       struct { /* exposure/gain control cluster */
-               struct v4l2_ctrl *exposure;
-               struct v4l2_ctrl *gain;
-       };
-
-       u8 do_ctrl;
-       u8 gpio[2];
-       u8 sensor;
-       u8 type;
-#define Generic 0
-#define Creative_live_motion 1
-};
-enum sensors {
-       SENSOR_ICX098BQ,
-       SENSOR_LZ24BP,
-       SENSOR_MI0360,
-       SENSOR_MT9V111,         /* = MI360SOC */
-       SENSOR_OV7660,
-       SENSOR_OV9630,
-};
-
-static struct v4l2_pix_format vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_SRGGB8, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-       {640, 480, V4L2_PIX_FMT_SRGGB8, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-};
-
-/* sq930x registers */
-#define SQ930_CTRL_UCBUS_IO    0x0001
-#define SQ930_CTRL_I2C_IO      0x0002
-#define SQ930_CTRL_GPIO                0x0005
-#define SQ930_CTRL_CAP_START   0x0010
-#define SQ930_CTRL_CAP_STOP    0x0011
-#define SQ930_CTRL_SET_EXPOSURE 0x001d
-#define SQ930_CTRL_RESET       0x001e
-#define SQ930_CTRL_GET_DEV_INFO 0x001f
-
-/* gpio 1 (8..15) */
-#define SQ930_GPIO_DFL_I2C_SDA 0x0001
-#define SQ930_GPIO_DFL_I2C_SCL 0x0002
-#define SQ930_GPIO_RSTBAR      0x0004
-#define SQ930_GPIO_EXTRA1      0x0040
-#define SQ930_GPIO_EXTRA2      0x0080
-/* gpio 3 (24..31) */
-#define SQ930_GPIO_POWER       0x0200
-#define SQ930_GPIO_DFL_LED     0x1000
-
-struct ucbus_write_cmd {
-       u16     bw_addr;
-       u8      bw_data;
-};
-struct i2c_write_cmd {
-       u8      reg;
-       u16     val;
-};
-
-static const struct ucbus_write_cmd icx098bq_start_0[] = {
-       {0x0354, 0x00}, {0x03fa, 0x00}, {0xf800, 0x02}, {0xf801, 0xce},
-       {0xf802, 0xc1}, {0xf804, 0x00}, {0xf808, 0x00}, {0xf809, 0x0e},
-       {0xf80a, 0x01}, {0xf80b, 0xee}, {0xf807, 0x60}, {0xf80c, 0x02},
-       {0xf80d, 0xf0}, {0xf80e, 0x03}, {0xf80f, 0x0a}, {0xf81c, 0x02},
-       {0xf81d, 0xf0}, {0xf81e, 0x03}, {0xf81f, 0x0a}, {0xf83a, 0x00},
-       {0xf83b, 0x10}, {0xf83c, 0x00}, {0xf83d, 0x4e}, {0xf810, 0x04},
-       {0xf811, 0x00}, {0xf812, 0x02}, {0xf813, 0x10}, {0xf803, 0x00},
-       {0xf814, 0x01}, {0xf815, 0x18}, {0xf816, 0x00}, {0xf817, 0x48},
-       {0xf818, 0x00}, {0xf819, 0x25}, {0xf81a, 0x00}, {0xf81b, 0x3c},
-       {0xf82f, 0x03}, {0xf820, 0xff}, {0xf821, 0x0d}, {0xf822, 0xff},
-       {0xf823, 0x07}, {0xf824, 0xff}, {0xf825, 0x03}, {0xf826, 0xff},
-       {0xf827, 0x06}, {0xf828, 0xff}, {0xf829, 0x03}, {0xf82a, 0xff},
-       {0xf82b, 0x0c}, {0xf82c, 0xfd}, {0xf82d, 0x01}, {0xf82e, 0x00},
-       {0xf830, 0x00}, {0xf831, 0x47}, {0xf832, 0x00}, {0xf833, 0x00},
-       {0xf850, 0x00}, {0xf851, 0x00}, {0xf852, 0x00}, {0xf853, 0x24},
-       {0xf854, 0x00}, {0xf855, 0x18}, {0xf856, 0x00}, {0xf857, 0x3c},
-       {0xf858, 0x00}, {0xf859, 0x0c}, {0xf85a, 0x00}, {0xf85b, 0x30},
-       {0xf85c, 0x00}, {0xf85d, 0x0c}, {0xf85e, 0x00}, {0xf85f, 0x30},
-       {0xf860, 0x00}, {0xf861, 0x48}, {0xf862, 0x01}, {0xf863, 0xdc},
-       {0xf864, 0xff}, {0xf865, 0x98}, {0xf866, 0xff}, {0xf867, 0xc0},
-       {0xf868, 0xff}, {0xf869, 0x70}, {0xf86c, 0xff}, {0xf86d, 0x00},
-       {0xf86a, 0xff}, {0xf86b, 0x48}, {0xf86e, 0xff}, {0xf86f, 0x00},
-       {0xf870, 0x01}, {0xf871, 0xdb}, {0xf872, 0x01}, {0xf873, 0xfa},
-       {0xf874, 0x01}, {0xf875, 0xdb}, {0xf876, 0x01}, {0xf877, 0xfa},
-       {0xf878, 0x0f}, {0xf879, 0x0f}, {0xf87a, 0xff}, {0xf87b, 0xff},
-       {0xf800, 0x03}
-};
-static const struct ucbus_write_cmd icx098bq_start_1[] = {
-       {0xf5f0, 0x00}, {0xf5f1, 0xcd}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
-       {0xf5f4, 0xc0},
-       {0xf5f0, 0x49}, {0xf5f1, 0xcd}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
-       {0xf5f4, 0xc0},
-       {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
-       {0xf5f9, 0x00}
-};
-
-static const struct ucbus_write_cmd icx098bq_start_2[] = {
-       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x82}, {0xf806, 0x00},
-       {0xf807, 0x7f}, {0xf800, 0x03},
-       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x40}, {0xf806, 0x00},
-       {0xf807, 0x7f}, {0xf800, 0x03},
-       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0xcf}, {0xf806, 0xd0},
-       {0xf807, 0x7f}, {0xf800, 0x03},
-       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x00}, {0xf806, 0x00},
-       {0xf807, 0x7f}, {0xf800, 0x03}
-};
-
-static const struct ucbus_write_cmd lz24bp_start_0[] = {
-       {0x0354, 0x00}, {0x03fa, 0x00}, {0xf800, 0x02}, {0xf801, 0xbe},
-       {0xf802, 0xc6}, {0xf804, 0x00}, {0xf808, 0x00}, {0xf809, 0x06},
-       {0xf80a, 0x01}, {0xf80b, 0xfe}, {0xf807, 0x84}, {0xf80c, 0x02},
-       {0xf80d, 0xf7}, {0xf80e, 0x03}, {0xf80f, 0x0b}, {0xf81c, 0x00},
-       {0xf81d, 0x49}, {0xf81e, 0x03}, {0xf81f, 0x0b}, {0xf83a, 0x00},
-       {0xf83b, 0x01}, {0xf83c, 0x00}, {0xf83d, 0x6b}, {0xf810, 0x03},
-       {0xf811, 0x10}, {0xf812, 0x02}, {0xf813, 0x6f}, {0xf803, 0x00},
-       {0xf814, 0x00}, {0xf815, 0x44}, {0xf816, 0x00}, {0xf817, 0x48},
-       {0xf818, 0x00}, {0xf819, 0x25}, {0xf81a, 0x00}, {0xf81b, 0x3c},
-       {0xf82f, 0x03}, {0xf820, 0xff}, {0xf821, 0x0d}, {0xf822, 0xff},
-       {0xf823, 0x07}, {0xf824, 0xfd}, {0xf825, 0x07}, {0xf826, 0xf0},
-       {0xf827, 0x0c}, {0xf828, 0xff}, {0xf829, 0x03}, {0xf82a, 0xff},
-       {0xf82b, 0x0c}, {0xf82c, 0xfc}, {0xf82d, 0x01}, {0xf82e, 0x00},
-       {0xf830, 0x00}, {0xf831, 0x47}, {0xf832, 0x00}, {0xf833, 0x00},
-       {0xf850, 0x00}, {0xf851, 0x00}, {0xf852, 0x00}, {0xf853, 0x24},
-       {0xf854, 0x00}, {0xf855, 0x0c}, {0xf856, 0x00}, {0xf857, 0x30},
-       {0xf858, 0x00}, {0xf859, 0x18}, {0xf85a, 0x00}, {0xf85b, 0x3c},
-       {0xf85c, 0x00}, {0xf85d, 0x18}, {0xf85e, 0x00}, {0xf85f, 0x3c},
-       {0xf860, 0xff}, {0xf861, 0x37}, {0xf862, 0xff}, {0xf863, 0x1d},
-       {0xf864, 0xff}, {0xf865, 0x98}, {0xf866, 0xff}, {0xf867, 0xc0},
-       {0xf868, 0x00}, {0xf869, 0x37}, {0xf86c, 0x02}, {0xf86d, 0x1d},
-       {0xf86a, 0x00}, {0xf86b, 0x37}, {0xf86e, 0x02}, {0xf86f, 0x1d},
-       {0xf870, 0x01}, {0xf871, 0xc6}, {0xf872, 0x02}, {0xf873, 0x04},
-       {0xf874, 0x01}, {0xf875, 0xc6}, {0xf876, 0x02}, {0xf877, 0x04},
-       {0xf878, 0x0f}, {0xf879, 0x0f}, {0xf87a, 0xff}, {0xf87b, 0xff},
-       {0xf800, 0x03}
-};
-static const struct ucbus_write_cmd lz24bp_start_1_gen[] = {
-       {0xf5f0, 0x00}, {0xf5f1, 0xff}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
-       {0xf5f4, 0xb3},
-       {0xf5f0, 0x40}, {0xf5f1, 0xff}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
-       {0xf5f4, 0xb3},
-       {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
-       {0xf5f9, 0x00}
-};
-
-static const struct ucbus_write_cmd lz24bp_start_1_clm[] = {
-       {0xf5f0, 0x00}, {0xf5f1, 0xff}, {0xf5f2, 0x88}, {0xf5f3, 0x88},
-       {0xf5f4, 0xc0},
-       {0xf5f0, 0x40}, {0xf5f1, 0xff}, {0xf5f2, 0x88}, {0xf5f3, 0x88},
-       {0xf5f4, 0xc0},
-       {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
-       {0xf5f9, 0x00}
-};
-
-static const struct ucbus_write_cmd lz24bp_start_2[] = {
-       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x80}, {0xf806, 0x00},
-       {0xf807, 0x7f}, {0xf800, 0x03},
-       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x4e}, {0xf806, 0x00},
-       {0xf807, 0x7f}, {0xf800, 0x03},
-       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0xc0}, {0xf806, 0x48},
-       {0xf807, 0x7f}, {0xf800, 0x03},
-       {0xf800, 0x02}, {0xf807, 0xff}, {0xf805, 0x00}, {0xf806, 0x00},
-       {0xf807, 0x7f}, {0xf800, 0x03}
-};
-
-static const struct ucbus_write_cmd mi0360_start_0[] = {
-       {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0xcc}, {0xf333, 0xcc},
-       {0xf334, 0xcc}, {0xf335, 0xcc}, {0xf33f, 0x00}
-};
-static const struct i2c_write_cmd mi0360_init_23[] = {
-       {0x30, 0x0040},         /* reserved - def 0x0005 */
-       {0x31, 0x0000},         /* reserved - def 0x002a */
-       {0x34, 0x0100},         /* reserved - def 0x0100 */
-       {0x3d, 0x068f},         /* reserved - def 0x068f */
-};
-static const struct i2c_write_cmd mi0360_init_24[] = {
-       {0x03, 0x01e5},         /* window height */
-       {0x04, 0x0285},         /* window width */
-};
-static const struct i2c_write_cmd mi0360_init_25[] = {
-       {0x35, 0x0020},         /* global gain */
-       {0x2b, 0x0020},         /* green1 gain */
-       {0x2c, 0x002a},         /* blue gain */
-       {0x2d, 0x0028},         /* red gain */
-       {0x2e, 0x0020},         /* green2 gain */
-};
-static const struct ucbus_write_cmd mi0360_start_1[] = {
-       {0xf5f0, 0x11}, {0xf5f1, 0x99}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
-       {0xf5f4, 0xa6},
-       {0xf5f0, 0x51}, {0xf5f1, 0x99}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
-       {0xf5f4, 0xa6},
-       {0xf5fa, 0x00}, {0xf5f6, 0x00}, {0xf5f7, 0x00}, {0xf5f8, 0x00},
-       {0xf5f9, 0x00}
-};
-static const struct i2c_write_cmd mi0360_start_2[] = {
-       {0x62, 0x041d},         /* reserved - def 0x0418 */
-};
-static const struct i2c_write_cmd mi0360_start_3[] = {
-       {0x05, 0x007b},         /* horiz blanking */
-};
-static const struct i2c_write_cmd mi0360_start_4[] = {
-       {0x05, 0x03f5},         /* horiz blanking */
-};
-
-static const struct i2c_write_cmd mt9v111_init_0[] = {
-       {0x01, 0x0001},         /* select IFP/SOC registers */
-       {0x06, 0x300c},         /* operating mode control */
-       {0x08, 0xcc00},         /* output format control (RGB) */
-       {0x01, 0x0004},         /* select sensor core registers */
-};
-static const struct i2c_write_cmd mt9v111_init_1[] = {
-       {0x03, 0x01e5},         /* window height */
-       {0x04, 0x0285},         /* window width */
-};
-static const struct i2c_write_cmd mt9v111_init_2[] = {
-       {0x30, 0x7800},
-       {0x31, 0x0000},
-       {0x07, 0x3002},         /* output control */
-       {0x35, 0x0020},         /* global gain */
-       {0x2b, 0x0020},         /* green1 gain */
-       {0x2c, 0x0020},         /* blue gain */
-       {0x2d, 0x0020},         /* red gain */
-       {0x2e, 0x0020},         /* green2 gain */
-};
-static const struct ucbus_write_cmd mt9v111_start_1[] = {
-       {0xf5f0, 0x11}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
-       {0xf5f4, 0xaa},
-       {0xf5f0, 0x51}, {0xf5f1, 0x96}, {0xf5f2, 0x80}, {0xf5f3, 0x80},
-       {0xf5f4, 0xaa},
-       {0xf5fa, 0x00}, {0xf5f6, 0x0a}, {0xf5f7, 0x0a}, {0xf5f8, 0x0a},
-       {0xf5f9, 0x0a}
-};
-static const struct i2c_write_cmd mt9v111_init_3[] = {
-       {0x62, 0x0405},
-};
-static const struct i2c_write_cmd mt9v111_init_4[] = {
-/*     {0x05, 0x00ce}, */
-       {0x05, 0x005d},         /* horizontal blanking */
-};
-
-static const struct ucbus_write_cmd ov7660_start_0[] = {
-       {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0xc0},
-       {0xf334, 0x39}, {0xf335, 0xe7}, {0xf33f, 0x03}
-};
-
-static const struct ucbus_write_cmd ov9630_start_0[] = {
-       {0x0354, 0x00}, {0x03fa, 0x00}, {0xf332, 0x00}, {0xf333, 0x00},
-       {0xf334, 0x3e}, {0xf335, 0xf8}, {0xf33f, 0x03}
-};
-
-/* start parameters indexed by [sensor][mode] */
-static const struct cap_s {
-       u8      cc_sizeid;
-       u8      cc_bytes[32];
-} capconfig[4][2] = {
-       [SENSOR_ICX098BQ] = {
-               {2,                             /* Bayer 320x240 */
-                 {0x05, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee,
-                  0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
-               {4,                             /* Bayer 640x480 */
-                 {0x01, 0x1f, 0x20, 0x0e, 0x00, 0x9f, 0x02, 0xee,
-                  0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
-       },
-       [SENSOR_LZ24BP] = {
-               {2,                             /* Bayer 320x240 */
-                 {0x05, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee,
-                  0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
-               {4,                             /* Bayer 640x480 */
-                 {0x01, 0x22, 0x20, 0x0e, 0x00, 0xa2, 0x02, 0xee,
-                  0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
-       },
-       [SENSOR_MI0360] = {
-               {2,                             /* Bayer 320x240 */
-                 {0x05, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
-                  0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
-               {4,                             /* Bayer 640x480 */
-                 {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
-                  0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
-       },
-       [SENSOR_MT9V111] = {
-               {2,                             /* Bayer 320x240 */
-                 {0x05, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
-                  0x01, 0x01, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
-               {4,                             /* Bayer 640x480 */
-                 {0x01, 0x02, 0x20, 0x01, 0x20, 0x82, 0x02, 0xe1,
-                  0x01, 0x02, 0x00, 0x08, 0x18, 0x12, 0x78, 0xc8,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
-       },
-};
-
-struct sensor_s {
-       const char *name;
-       u8 i2c_addr;
-       u8 i2c_dum;
-       u8 gpio[5];
-       u8 cmd_len;
-       const struct ucbus_write_cmd *cmd;
-};
-
-static const struct sensor_s sensor_tb[] = {
-       [SENSOR_ICX098BQ] = {
-               "icx098bp",
-               0x00, 0x00,
-               {0,
-                SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
-                SQ930_GPIO_DFL_I2C_SDA,
-                0,
-                SQ930_GPIO_RSTBAR
-               },
-               8, icx098bq_start_0
-           },
-       [SENSOR_LZ24BP] = {
-               "lz24bp",
-               0x00, 0x00,
-               {0,
-                SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
-                SQ930_GPIO_DFL_I2C_SDA,
-                0,
-                SQ930_GPIO_RSTBAR
-               },
-               8, lz24bp_start_0
-           },
-       [SENSOR_MI0360] = {
-               "mi0360",
-               0x5d, 0x80,
-               {SQ930_GPIO_RSTBAR,
-                SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
-                SQ930_GPIO_DFL_I2C_SDA,
-                0,
-                0
-               },
-               7, mi0360_start_0
-           },
-       [SENSOR_MT9V111] = {
-               "mt9v111",
-               0x5c, 0x7f,
-               {SQ930_GPIO_RSTBAR,
-                SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
-                SQ930_GPIO_DFL_I2C_SDA,
-                0,
-                0
-               },
-               7, mi0360_start_0
-           },
-       [SENSOR_OV7660] = {
-               "ov7660",
-               0x21, 0x00,
-               {0,
-                SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
-                SQ930_GPIO_DFL_I2C_SDA,
-                0,
-                SQ930_GPIO_RSTBAR
-               },
-               7, ov7660_start_0
-           },
-       [SENSOR_OV9630] = {
-               "ov9630",
-               0x30, 0x00,
-               {0,
-                SQ930_GPIO_DFL_I2C_SDA | SQ930_GPIO_DFL_I2C_SCL,
-                SQ930_GPIO_DFL_I2C_SDA,
-                0,
-                SQ930_GPIO_RSTBAR
-               },
-               7, ov9630_start_0
-           },
-};
-
-static void reg_r(struct gspca_dev *gspca_dev,
-               u16 value, int len)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       0x0c,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, 0, gspca_dev->usb_buf, len,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_r %04x failed %d\n", value, ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void reg_w(struct gspca_dev *gspca_dev, u16 value, u16 index)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       PDEBUG(D_USBO, "reg_w v: %04x i: %04x", value, index);
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0x0c,                   /* request */
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index, NULL, 0,
-                       500);
-       msleep(30);
-       if (ret < 0) {
-               pr_err("reg_w %04x %04x failed %d\n", value, index, ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void reg_wb(struct gspca_dev *gspca_dev, u16 value, u16 index,
-               const u8 *data, int len)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       PDEBUG(D_USBO, "reg_wb v: %04x i: %04x %02x...%02x",
-                       value, index, *data, data[len - 1]);
-       memcpy(gspca_dev->usb_buf, data, len);
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0x0c,                   /* request */
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index, gspca_dev->usb_buf, len,
-                       1000);
-       msleep(30);
-       if (ret < 0) {
-               pr_err("reg_wb %04x %04x failed %d\n", value, index, ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void i2c_write(struct sd *sd,
-                       const struct i2c_write_cmd *cmd,
-                       int ncmds)
-{
-       struct gspca_dev *gspca_dev = &sd->gspca_dev;
-       const struct sensor_s *sensor;
-       u16 val, idx;
-       u8 *buf;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-
-       sensor = &sensor_tb[sd->sensor];
-
-       val = (sensor->i2c_addr << 8) | SQ930_CTRL_I2C_IO;
-       idx = (cmd->val & 0xff00) | cmd->reg;
-
-       buf = gspca_dev->usb_buf;
-       *buf++ = sensor->i2c_dum;
-       *buf++ = cmd->val;
-
-       while (--ncmds > 0) {
-               cmd++;
-               *buf++ = cmd->reg;
-               *buf++ = cmd->val >> 8;
-               *buf++ = sensor->i2c_dum;
-               *buf++ = cmd->val;
-       }
-
-       PDEBUG(D_USBO, "i2c_w v: %04x i: %04x %02x...%02x",
-                       val, idx, gspca_dev->usb_buf[0], buf[-1]);
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0x0c,                   /* request */
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       val, idx,
-                       gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
-                       500);
-       if (ret < 0) {
-               pr_err("i2c_write failed %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void ucbus_write(struct gspca_dev *gspca_dev,
-                       const struct ucbus_write_cmd *cmd,
-                       int ncmds,
-                       int batchsize)
-{
-       u8 *buf;
-       u16 val, idx;
-       int len, ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-
-#ifdef GSPCA_DEBUG
-       if ((batchsize - 1) * 3 > USB_BUF_SZ) {
-               pr_err("Bug: usb_buf overflow\n");
-               gspca_dev->usb_err = -ENOMEM;
-               return;
-       }
-#endif
-
-       for (;;) {
-               len = ncmds;
-               if (len > batchsize)
-                       len = batchsize;
-               ncmds -= len;
-
-               val = (cmd->bw_addr << 8) | SQ930_CTRL_UCBUS_IO;
-               idx = (cmd->bw_data << 8) | (cmd->bw_addr >> 8);
-
-               buf = gspca_dev->usb_buf;
-               while (--len > 0) {
-                       cmd++;
-                       *buf++ = cmd->bw_addr;
-                       *buf++ = cmd->bw_addr >> 8;
-                       *buf++ = cmd->bw_data;
-               }
-               if (buf != gspca_dev->usb_buf)
-                       PDEBUG(D_USBO, "ucbus v: %04x i: %04x %02x...%02x",
-                                       val, idx,
-                                       gspca_dev->usb_buf[0], buf[-1]);
-               else
-                       PDEBUG(D_USBO, "ucbus v: %04x i: %04x",
-                                       val, idx);
-               ret = usb_control_msg(gspca_dev->dev,
-                               usb_sndctrlpipe(gspca_dev->dev, 0),
-                               0x0c,                   /* request */
-                          USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                               val, idx,
-                               gspca_dev->usb_buf, buf - gspca_dev->usb_buf,
-                               500);
-               if (ret < 0) {
-                       pr_err("ucbus_write failed %d\n", ret);
-                       gspca_dev->usb_err = ret;
-                       return;
-               }
-               msleep(30);
-               if (ncmds <= 0)
-                       break;
-               cmd++;
-       }
-}
-
-static void gpio_set(struct sd *sd, u16 val, u16 mask)
-{
-       struct gspca_dev *gspca_dev = &sd->gspca_dev;
-
-       if (mask & 0x00ff) {
-               sd->gpio[0] &= ~mask;
-               sd->gpio[0] |= val;
-               reg_w(gspca_dev, 0x0100 | SQ930_CTRL_GPIO,
-                       ~sd->gpio[0] << 8);
-       }
-       mask >>= 8;
-       val >>= 8;
-       if (mask) {
-               sd->gpio[1] &= ~mask;
-               sd->gpio[1] |= val;
-               reg_w(gspca_dev, 0x0300 | SQ930_CTRL_GPIO,
-                       ~sd->gpio[1] << 8);
-       }
-}
-
-static void gpio_init(struct sd *sd,
-                       const u8 *gpio)
-{
-       gpio_set(sd, *gpio++, 0x000f);
-       gpio_set(sd, *gpio++, 0x000f);
-       gpio_set(sd, *gpio++, 0x000f);
-       gpio_set(sd, *gpio++, 0x000f);
-       gpio_set(sd, *gpio, 0x000f);
-}
-
-static void bridge_init(struct sd *sd)
-{
-       static const struct ucbus_write_cmd clkfreq_cmd = {
-                               0xf031, 0       /* SQ930_CLKFREQ_60MHZ */
-       };
-
-       ucbus_write(&sd->gspca_dev, &clkfreq_cmd, 1, 1);
-
-       gpio_set(sd, SQ930_GPIO_POWER, 0xff00);
-}
-
-static void cmos_probe(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i;
-       const struct sensor_s *sensor;
-       static const u8 probe_order[] = {
-/*             SENSOR_LZ24BP,          (tested as ccd) */
-               SENSOR_OV9630,
-               SENSOR_MI0360,
-               SENSOR_OV7660,
-               SENSOR_MT9V111,
-       };
-
-       for (i = 0; i < ARRAY_SIZE(probe_order); i++) {
-               sensor = &sensor_tb[probe_order[i]];
-               ucbus_write(&sd->gspca_dev, sensor->cmd, sensor->cmd_len, 8);
-               gpio_init(sd, sensor->gpio);
-               msleep(100);
-               reg_r(gspca_dev, (sensor->i2c_addr << 8) | 0x001c, 1);
-               msleep(100);
-               if (gspca_dev->usb_buf[0] != 0)
-                       break;
-       }
-       if (i >= ARRAY_SIZE(probe_order)) {
-               pr_err("Unknown sensor\n");
-               gspca_dev->usb_err = -EINVAL;
-               return;
-       }
-       sd->sensor = probe_order[i];
-       switch (sd->sensor) {
-       case SENSOR_OV7660:
-       case SENSOR_OV9630:
-               pr_err("Sensor %s not yet treated\n",
-                      sensor_tb[sd->sensor].name);
-               gspca_dev->usb_err = -EINVAL;
-               break;
-       }
-}
-
-static void mt9v111_init(struct gspca_dev *gspca_dev)
-{
-       int i, nwait;
-       static const u8 cmd_001b[] = {
-               0x00, 0x3b, 0xf6, 0x01, 0x03, 0x02, 0x00, 0x00,
-               0x00, 0x00, 0x00
-       };
-       static const u8 cmd_011b[][7] = {
-               {0x10, 0x01, 0x66, 0x08, 0x00, 0x00, 0x00},
-               {0x01, 0x00, 0x1a, 0x04, 0x00, 0x00, 0x00},
-               {0x20, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00},
-               {0x02, 0x01, 0xae, 0x01, 0x00, 0x00, 0x00},
-       };
-
-       reg_wb(gspca_dev, 0x001b, 0x0000, cmd_001b, sizeof cmd_001b);
-       for (i = 0; i < ARRAY_SIZE(cmd_011b); i++) {
-               reg_wb(gspca_dev, 0x001b, 0x0000, cmd_011b[i],
-                               ARRAY_SIZE(cmd_011b[0]));
-               msleep(400);
-               nwait = 20;
-               for (;;) {
-                       reg_r(gspca_dev, 0x031b, 1);
-                       if (gspca_dev->usb_buf[0] == 0
-                        || gspca_dev->usb_err != 0)
-                               break;
-                       if (--nwait < 0) {
-                               PDEBUG(D_PROBE, "mt9v111_init timeout");
-                               gspca_dev->usb_err = -ETIME;
-                               return;
-                       }
-                       msleep(50);
-               }
-       }
-}
-
-static void global_init(struct sd *sd, int first_time)
-{
-       switch (sd->sensor) {
-       case SENSOR_ICX098BQ:
-               if (first_time)
-                       ucbus_write(&sd->gspca_dev,
-                                       icx098bq_start_0,
-                                       8, 8);
-               gpio_init(sd, sensor_tb[sd->sensor].gpio);
-               break;
-       case SENSOR_LZ24BP:
-               if (sd->type != Creative_live_motion)
-                       gpio_set(sd, SQ930_GPIO_EXTRA1, 0x00ff);
-               else
-                       gpio_set(sd, 0, 0x00ff);
-               msleep(50);
-               if (first_time)
-                       ucbus_write(&sd->gspca_dev,
-                                       lz24bp_start_0,
-                                       8, 8);
-               gpio_init(sd, sensor_tb[sd->sensor].gpio);
-               break;
-       case SENSOR_MI0360:
-               if (first_time)
-                       ucbus_write(&sd->gspca_dev,
-                                       mi0360_start_0,
-                                       ARRAY_SIZE(mi0360_start_0),
-                                       8);
-               gpio_init(sd, sensor_tb[sd->sensor].gpio);
-               gpio_set(sd, SQ930_GPIO_EXTRA2, SQ930_GPIO_EXTRA2);
-               break;
-       default:
-/*     case SENSOR_MT9V111: */
-               if (first_time)
-                       mt9v111_init(&sd->gspca_dev);
-               else
-                       gpio_init(sd, sensor_tb[sd->sensor].gpio);
-               break;
-       }
-}
-
-static void lz24bp_ppl(struct sd *sd, u16 ppl)
-{
-       struct ucbus_write_cmd cmds[2] = {
-               {0xf810, ppl >> 8},
-               {0xf811, ppl}
-       };
-
-       ucbus_write(&sd->gspca_dev, cmds, ARRAY_SIZE(cmds), 2);
-}
-
-static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 gain)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i, integclks, intstartclk, frameclks, min_frclk;
-       const struct sensor_s *sensor;
-       u16 cmd;
-       u8 buf[15];
-
-       integclks = expo;
-       i = 0;
-       cmd = SQ930_CTRL_SET_EXPOSURE;
-
-       switch (sd->sensor) {
-       case SENSOR_ICX098BQ:                   /* ccd */
-       case SENSOR_LZ24BP:
-               min_frclk = sd->sensor == SENSOR_ICX098BQ ? 0x210 : 0x26f;
-               if (integclks >= min_frclk) {
-                       intstartclk = 0;
-                       frameclks = integclks;
-               } else {
-                       intstartclk = min_frclk - integclks;
-                       frameclks = min_frclk;
-               }
-               buf[i++] = intstartclk >> 8;
-               buf[i++] = intstartclk;
-               buf[i++] = frameclks >> 8;
-               buf[i++] = frameclks;
-               buf[i++] = gain;
-               break;
-       default:                                /* cmos */
-/*     case SENSOR_MI0360: */
-/*     case SENSOR_MT9V111: */
-               cmd |= 0x0100;
-               sensor = &sensor_tb[sd->sensor];
-               buf[i++] = sensor->i2c_addr;    /* i2c_slave_addr */
-               buf[i++] = 0x08;        /* 2 * ni2c */
-               buf[i++] = 0x09;        /* reg = shutter width */
-               buf[i++] = integclks >> 8; /* val H */
-               buf[i++] = sensor->i2c_dum;
-               buf[i++] = integclks;   /* val L */
-               buf[i++] = 0x35;        /* reg = global gain */
-               buf[i++] = 0x00;        /* val H */
-               buf[i++] = sensor->i2c_dum;
-               buf[i++] = 0x80 + gain / 2; /* val L */
-               buf[i++] = 0x00;
-               buf[i++] = 0x00;
-               buf[i++] = 0x00;
-               buf[i++] = 0x00;
-               buf[i++] = 0x83;
-               break;
-       }
-       reg_wb(gspca_dev, cmd, 0, buf, i);
-}
-
-/* This function is called at probe time just before sd_init */
-static int sd_config(struct gspca_dev *gspca_dev,
-               const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam = &gspca_dev->cam;
-
-       sd->sensor = id->driver_info >> 8;
-       sd->type = id->driver_info;
-
-       cam->cam_mode = vga_mode;
-       cam->nmodes = ARRAY_SIZE(vga_mode);
-
-       cam->bulk = 1;
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->gpio[0] = sd->gpio[1] = 0xff;       /* force gpio rewrite */
-
-/*fixme: is this needed for icx098bp and mi0360?
-       if (sd->sensor != SENSOR_LZ24BP)
-               reg_w(gspca_dev, SQ930_CTRL_RESET, 0x0000);
- */
-
-       reg_r(gspca_dev, SQ930_CTRL_GET_DEV_INFO, 8);
-       if (gspca_dev->usb_err < 0)
-               return gspca_dev->usb_err;
-
-/* it returns:
- * 03 00 12 93 0b f6 c9 00     live! ultra
- * 03 00 07 93 0b f6 ca 00     live! ultra for notebook
- * 03 00 12 93 0b fe c8 00     Trust WB-3500T
- * 02 00 06 93 0b fe c8 00     Joy-IT 318S
- * 03 00 12 93 0b f6 cf 00     icam tracer - sensor icx098bq
- * 02 00 12 93 0b fe cf 00     ProQ Motion Webcam
- *
- * byte
- * 0: 02 = usb 1.0 (12Mbit) / 03 = usb2.0 (480Mbit)
- * 1: 00
- * 2: 06 / 07 / 12 = mode webcam? firmware??
- * 3: 93 chip = 930b (930b or 930c)
- * 4: 0b
- * 5: f6 = cdd (icx098bq, lz24bp) / fe or de = cmos (i2c) (other sensors)
- * 6: c8 / c9 / ca / cf = mode webcam?, sensor? webcam?
- * 7: 00
- */
-       PDEBUG(D_PROBE, "info: %*ph", 8, gspca_dev->usb_buf);
-
-       bridge_init(sd);
-
-       if (sd->sensor == SENSOR_MI0360) {
-
-               /* no sensor probe for icam tracer */
-               if (gspca_dev->usb_buf[5] == 0xf6)      /* if ccd */
-                       sd->sensor = SENSOR_ICX098BQ;
-               else
-                       cmos_probe(gspca_dev);
-       }
-       if (gspca_dev->usb_err >= 0) {
-               PDEBUG(D_PROBE, "Sensor %s", sensor_tb[sd->sensor].name);
-               global_init(sd, 1);
-       }
-       return gspca_dev->usb_err;
-}
-
-/* send the start/stop commands to the webcam */
-static void send_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       const struct cap_s *cap;
-       int mode;
-
-       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-       cap = &capconfig[sd->sensor][mode];
-       reg_wb(gspca_dev, 0x0900 | SQ930_CTRL_CAP_START,
-                       0x0a00 | cap->cc_sizeid,
-                       cap->cc_bytes, 32);
-}
-
-static void send_stop(struct gspca_dev *gspca_dev)
-{
-       reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0);
-}
-
-/* function called at start time before URB creation */
-static int sd_isoc_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       gspca_dev->cam.bulk_nurbs = 1;  /* there must be one URB only */
-       sd->do_ctrl = 0;
-       gspca_dev->cam.bulk_size = gspca_dev->width * gspca_dev->height + 8;
-       return 0;
-}
-
-/* start the capture */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int mode;
-
-       bridge_init(sd);
-       global_init(sd, 0);
-       msleep(100);
-
-       switch (sd->sensor) {
-       case SENSOR_ICX098BQ:
-               ucbus_write(gspca_dev, icx098bq_start_0,
-                               ARRAY_SIZE(icx098bq_start_0),
-                               8);
-               ucbus_write(gspca_dev, icx098bq_start_1,
-                               ARRAY_SIZE(icx098bq_start_1),
-                               5);
-               ucbus_write(gspca_dev, icx098bq_start_2,
-                               ARRAY_SIZE(icx098bq_start_2),
-                               6);
-               msleep(50);
-
-               /* 1st start */
-               send_start(gspca_dev);
-               gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, 0x00ff);
-               msleep(70);
-               reg_w(gspca_dev, SQ930_CTRL_CAP_STOP, 0x0000);
-               gpio_set(sd, 0x7f, 0x00ff);
-
-               /* 2nd start */
-               send_start(gspca_dev);
-               gpio_set(sd, SQ930_GPIO_EXTRA2 | SQ930_GPIO_RSTBAR, 0x00ff);
-               goto out;
-       case SENSOR_LZ24BP:
-               ucbus_write(gspca_dev, lz24bp_start_0,
-                               ARRAY_SIZE(lz24bp_start_0),
-                               8);
-               if (sd->type != Creative_live_motion)
-                       ucbus_write(gspca_dev, lz24bp_start_1_gen,
-                                       ARRAY_SIZE(lz24bp_start_1_gen),
-                                       5);
-               else
-                       ucbus_write(gspca_dev, lz24bp_start_1_clm,
-                                       ARRAY_SIZE(lz24bp_start_1_clm),
-                                       5);
-               ucbus_write(gspca_dev, lz24bp_start_2,
-                               ARRAY_SIZE(lz24bp_start_2),
-                               6);
-               mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-               lz24bp_ppl(sd, mode == 1 ? 0x0564 : 0x0310);
-               msleep(10);
-               break;
-       case SENSOR_MI0360:
-               ucbus_write(gspca_dev, mi0360_start_0,
-                               ARRAY_SIZE(mi0360_start_0),
-                               8);
-               i2c_write(sd, mi0360_init_23,
-                               ARRAY_SIZE(mi0360_init_23));
-               i2c_write(sd, mi0360_init_24,
-                               ARRAY_SIZE(mi0360_init_24));
-               i2c_write(sd, mi0360_init_25,
-                               ARRAY_SIZE(mi0360_init_25));
-               ucbus_write(gspca_dev, mi0360_start_1,
-                               ARRAY_SIZE(mi0360_start_1),
-                               5);
-               i2c_write(sd, mi0360_start_2,
-                               ARRAY_SIZE(mi0360_start_2));
-               i2c_write(sd, mi0360_start_3,
-                               ARRAY_SIZE(mi0360_start_3));
-
-               /* 1st start */
-               send_start(gspca_dev);
-               msleep(60);
-               send_stop(gspca_dev);
-
-               i2c_write(sd,
-                       mi0360_start_4, ARRAY_SIZE(mi0360_start_4));
-               break;
-       default:
-/*     case SENSOR_MT9V111: */
-               ucbus_write(gspca_dev, mi0360_start_0,
-                               ARRAY_SIZE(mi0360_start_0),
-                               8);
-               i2c_write(sd, mt9v111_init_0,
-                               ARRAY_SIZE(mt9v111_init_0));
-               i2c_write(sd, mt9v111_init_1,
-                               ARRAY_SIZE(mt9v111_init_1));
-               i2c_write(sd, mt9v111_init_2,
-                               ARRAY_SIZE(mt9v111_init_2));
-               ucbus_write(gspca_dev, mt9v111_start_1,
-                               ARRAY_SIZE(mt9v111_start_1),
-                               5);
-               i2c_write(sd, mt9v111_init_3,
-                               ARRAY_SIZE(mt9v111_init_3));
-               i2c_write(sd, mt9v111_init_4,
-                               ARRAY_SIZE(mt9v111_init_4));
-               break;
-       }
-
-       send_start(gspca_dev);
-out:
-       msleep(1000);
-
-       if (sd->sensor == SENSOR_MT9V111)
-               gpio_set(sd, SQ930_GPIO_DFL_LED, SQ930_GPIO_DFL_LED);
-
-       sd->do_ctrl = 1;        /* set the exposure */
-
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_MT9V111)
-               gpio_set(sd, 0, SQ930_GPIO_DFL_LED);
-       send_stop(gspca_dev);
-}
-
-/* function called when the application gets a new frame */
-/* It sets the exposure if required and restart the bulk transfer. */
-static void sd_dq_callback(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int ret;
-
-       if (!sd->do_ctrl || gspca_dev->cam.bulk_nurbs != 0)
-               return;
-       sd->do_ctrl = 0;
-
-       setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure),
-                       v4l2_ctrl_g_ctrl(sd->gain));
-
-       gspca_dev->cam.bulk_nurbs = 1;
-       ret = usb_submit_urb(gspca_dev->urb[0], GFP_ATOMIC);
-       if (ret < 0)
-               pr_err("sd_dq_callback() err %d\n", ret);
-
-       /* wait a little time, otherwise the webcam crashes */
-       msleep(100);
-}
-
-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 (sd->do_ctrl)
-               gspca_dev->cam.bulk_nurbs = 0;
-       gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len - 8);
-       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 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, sd->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 2);
-       sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 1, 0xfff, 1, 0x356);
-       sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAIN, 1, 255, 1, 0x8d);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-       v4l2_ctrl_cluster(2, &sd->exposure);
-       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,
-       .isoc_init = sd_isoc_init,
-       .start  = sd_start,
-       .stopN  = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-       .dq_callback = sd_dq_callback,
-};
-
-/* Table of supported USB devices */
-#define ST(sensor, type) \
-       .driver_info = (SENSOR_ ## sensor << 8) \
-                       | (type)
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x041e, 0x4038), ST(MI0360, 0)},
-       {USB_DEVICE(0x041e, 0x403c), ST(LZ24BP, 0)},
-       {USB_DEVICE(0x041e, 0x403d), ST(LZ24BP, 0)},
-       {USB_DEVICE(0x041e, 0x4041), ST(LZ24BP, Creative_live_motion)},
-       {USB_DEVICE(0x2770, 0x930b), ST(MI0360, 0)},
-       {USB_DEVICE(0x2770, 0x930c), ST(MI0360, 0)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/stk014.c b/drivers/media/video/gspca/stk014.c
deleted file mode 100644 (file)
index 8c09826..0000000
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Syntek DV4000 (STK014) subdriver
- *
- * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr)
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "stk014"
-
-#include "gspca.h"
-#include "jpeg.h"
-
-MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
-MODULE_DESCRIPTION("Syntek DV4000 (STK014) USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-#define QUALITY 50
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-       u8 jpeg_hdr[JPEG_HDR_SZ];
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-
-/* -- read a register -- */
-static u8 reg_r(struct gspca_dev *gspca_dev,
-                       __u16 index)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return 0;
-       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-                       0x00,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0x00,
-                       index,
-                       gspca_dev->usb_buf, 1,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_r err %d\n", ret);
-               gspca_dev->usb_err = ret;
-               return 0;
-       }
-       return gspca_dev->usb_buf[0];
-}
-
-/* -- write a register -- */
-static void reg_w(struct gspca_dev *gspca_dev,
-                       __u16 index, __u16 value)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-                       0x01,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value,
-                       index,
-                       NULL,
-                       0,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_w err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-/* -- get a bulk value (4 bytes) -- */
-static void rcv_val(struct gspca_dev *gspca_dev,
-                       int ads)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int alen, ret;
-
-       reg_w(gspca_dev, 0x634, (ads >> 16) & 0xff);
-       reg_w(gspca_dev, 0x635, (ads >> 8) & 0xff);
-       reg_w(gspca_dev, 0x636, ads & 0xff);
-       reg_w(gspca_dev, 0x637, 0);
-       reg_w(gspca_dev, 0x638, 4);     /* len & 0xff */
-       reg_w(gspca_dev, 0x639, 0);     /* len >> 8 */
-       reg_w(gspca_dev, 0x63a, 0);
-       reg_w(gspca_dev, 0x63b, 0);
-       reg_w(gspca_dev, 0x630, 5);
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_bulk_msg(dev,
-                       usb_rcvbulkpipe(dev, 0x05),
-                       gspca_dev->usb_buf,
-                       4,              /* length */
-                       &alen,
-                       500);           /* timeout in milliseconds */
-       if (ret < 0) {
-               pr_err("rcv_val err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-/* -- send a bulk value -- */
-static void snd_val(struct gspca_dev *gspca_dev,
-                       int ads,
-                       unsigned int val)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int alen, ret;
-       __u8 seq = 0;
-
-       if (ads == 0x003f08) {
-               reg_r(gspca_dev, 0x0704);
-               seq = reg_r(gspca_dev, 0x0705);
-               reg_r(gspca_dev, 0x0650);
-               reg_w(gspca_dev, 0x654, seq);
-       } else {
-               reg_w(gspca_dev, 0x654, (ads >> 16) & 0xff);
-       }
-       reg_w(gspca_dev, 0x655, (ads >> 8) & 0xff);
-       reg_w(gspca_dev, 0x656, ads & 0xff);
-       reg_w(gspca_dev, 0x657, 0);
-       reg_w(gspca_dev, 0x658, 0x04);  /* size */
-       reg_w(gspca_dev, 0x659, 0);
-       reg_w(gspca_dev, 0x65a, 0);
-       reg_w(gspca_dev, 0x65b, 0);
-       reg_w(gspca_dev, 0x650, 5);
-       if (gspca_dev->usb_err < 0)
-               return;
-       gspca_dev->usb_buf[0] = val >> 24;
-       gspca_dev->usb_buf[1] = val >> 16;
-       gspca_dev->usb_buf[2] = val >> 8;
-       gspca_dev->usb_buf[3] = val;
-       ret = usb_bulk_msg(dev,
-                       usb_sndbulkpipe(dev, 6),
-                       gspca_dev->usb_buf,
-                       4,
-                       &alen,
-                       500);   /* timeout in milliseconds */
-       if (ret < 0) {
-               pr_err("snd_val err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       } else {
-               if (ads == 0x003f08) {
-                       seq += 4;
-                       seq &= 0x3f;
-                       reg_w(gspca_dev, 0x705, seq);
-               }
-       }
-}
-
-/* set a camera parameter */
-static void set_par(struct gspca_dev *gspca_dev,
-                  int parval)
-{
-       snd_val(gspca_dev, 0x003f08, parval);
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       int parval;
-
-       parval = 0x06000000             /* whiteness */
-               + (val << 16);
-       set_par(gspca_dev, parval);
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
-{
-       int parval;
-
-       parval = 0x07000000             /* contrast */
-               + (val << 16);
-       set_par(gspca_dev, parval);
-}
-
-static void setcolors(struct gspca_dev *gspca_dev, s32 val)
-{
-       int parval;
-
-       parval = 0x08000000             /* saturation */
-               + (val << 16);
-       set_par(gspca_dev, parval);
-}
-
-static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
-{
-       set_par(gspca_dev, val == 1
-                       ? 0x33640000            /* 50 Hz */
-                       : 0x33780000);          /* 60 Hz */
-}
-
-/* this function is called at probe time */
-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);
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       u8 ret;
-
-       /* check if the device responds */
-       usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
-       ret = reg_r(gspca_dev, 0x0740);
-       if (gspca_dev->usb_err >= 0) {
-               if (ret != 0xff) {
-                       pr_err("init reg: 0x%02x\n", ret);
-                       gspca_dev->usb_err = -EIO;
-               }
-       }
-       return gspca_dev->usb_err;
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int ret, value;
-
-       /* create the JPEG header */
-       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
-                       0x22);          /* JPEG 411 */
-       jpeg_set_qual(sd->jpeg_hdr, QUALITY);
-
-       /* work on alternate 1 */
-       usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
-
-       set_par(gspca_dev, 0x10000000);
-       set_par(gspca_dev, 0x00000000);
-       set_par(gspca_dev, 0x8002e001);
-       set_par(gspca_dev, 0x14000000);
-       if (gspca_dev->width > 320)
-               value = 0x8002e001;             /* 640x480 */
-       else
-               value = 0x4001f000;             /* 320x240 */
-       set_par(gspca_dev, value);
-       ret = usb_set_interface(gspca_dev->dev,
-                                       gspca_dev->iface,
-                                       gspca_dev->alt);
-       if (ret < 0) {
-               pr_err("set intf %d %d failed\n",
-                      gspca_dev->iface, gspca_dev->alt);
-               gspca_dev->usb_err = ret;
-               goto out;
-       }
-        reg_r(gspca_dev, 0x0630);
-       rcv_val(gspca_dev, 0x000020);   /* << (value ff ff ff ff) */
-       reg_r(gspca_dev, 0x0650);
-       snd_val(gspca_dev, 0x000020, 0xffffffff);
-       reg_w(gspca_dev, 0x0620, 0);
-       reg_w(gspca_dev, 0x0630, 0);
-       reg_w(gspca_dev, 0x0640, 0);
-       reg_w(gspca_dev, 0x0650, 0);
-       reg_w(gspca_dev, 0x0660, 0);
-       set_par(gspca_dev, 0x09800000);         /* Red ? */
-       set_par(gspca_dev, 0x0a800000);         /* Green ? */
-       set_par(gspca_dev, 0x0b800000);         /* Blue ? */
-       set_par(gspca_dev, 0x0d030000);         /* Gamma ? */
-
-       /* start the video flow */
-       set_par(gspca_dev, 0x01000000);
-       set_par(gspca_dev, 0x01000000);
-       if (gspca_dev->usb_err >= 0)
-               PDEBUG(D_STREAM, "camera started alt: 0x%02x",
-                               gspca_dev->alt);
-out:
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct usb_device *dev = gspca_dev->dev;
-
-       set_par(gspca_dev, 0x02000000);
-       set_par(gspca_dev, 0x02000000);
-       usb_set_interface(dev, gspca_dev->iface, 1);
-       reg_r(gspca_dev, 0x0630);
-       rcv_val(gspca_dev, 0x000020);   /* << (value ff ff ff ff) */
-       reg_r(gspca_dev, 0x0650);
-       snd_val(gspca_dev, 0x000020, 0xffffffff);
-       reg_w(gspca_dev, 0x0620, 0);
-       reg_w(gspca_dev, 0x0630, 0);
-       reg_w(gspca_dev, 0x0640, 0);
-       reg_w(gspca_dev, 0x0650, 0);
-       reg_w(gspca_dev, 0x0660, 0);
-       PDEBUG(D_STREAM, "camera stopped");
-}
-
-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;
-       static unsigned char ffd9[] = {0xff, 0xd9};
-
-       /* a frame starts with:
-        *      - 0xff 0xfe
-        *      - 0x08 0x00     - length (little endian ?!)
-        *      - 4 bytes = size of whole frame (BE - including header)
-        *      - 0x00 0x0c
-        *      - 0xff 0xd8
-        *      - ..    JPEG image with escape sequences (ff 00)
-        *              (without ending - ff d9)
-        */
-       if (data[0] == 0xff && data[1] == 0xfe) {
-               gspca_frame_add(gspca_dev, LAST_PACKET,
-                               ffd9, 2);
-
-               /* put the JPEG 411 header */
-               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                       sd->jpeg_hdr, JPEG_HDR_SZ);
-
-               /* beginning of the frame */
-#define STKHDRSZ 12
-               data += STKHDRSZ;
-               len -= STKHDRSZ;
-       }
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct gspca_dev *gspca_dev =
-               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
-
-       gspca_dev->usb_err = 0;
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               setcolors(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_POWER_LINE_FREQUENCY:
-               setlightfreq(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 4);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 255, 1, 127);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 255, 1, 127);
-       v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
-                       V4L2_CID_POWER_LINE_FREQUENCY,
-                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
-                       V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
-
-       if (hdl->error) {
-               pr_err("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,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x05e1, 0x0893)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/stv0680.c b/drivers/media/video/gspca/stv0680.c
deleted file mode 100644 (file)
index 6760527..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * STV0680 USB Camera Driver
- *
- * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com>
- *
- * This module is adapted from the in kernel v4l1 stv680 driver:
- *
- *  STV0680 USB Camera Driver, by Kevin Sisson (kjsisson@bellsouth.net)
- *
- * Thanks to STMicroelectronics for information on the usb commands, and
- * to Steve Miller at STM for his help and encouragement while I was
- * writing this driver.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "stv0680"
-
-#include "gspca.h"
-
-MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
-MODULE_DESCRIPTION("STV0680 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;             /* !! must be the first item */
-       struct v4l2_pix_format mode;
-       u8 orig_mode;
-       u8 video_mode;
-       u8 current_mode;
-};
-
-static int stv_sndctrl(struct gspca_dev *gspca_dev, int set, u8 req, u16 val,
-                      int size)
-{
-       int ret = -1;
-       u8 req_type = 0;
-       unsigned int pipe = 0;
-
-       switch (set) {
-       case 0: /*  0xc1  */
-               req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
-               pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
-               break;
-       case 1: /*  0x41  */
-               req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
-               pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
-               break;
-       case 2: /*  0x80  */
-               req_type = USB_DIR_IN | USB_RECIP_DEVICE;
-               pipe = usb_rcvctrlpipe(gspca_dev->dev, 0);
-               break;
-       case 3: /*  0x40  */
-               req_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-               pipe = usb_sndctrlpipe(gspca_dev->dev, 0);
-               break;
-       }
-
-       ret = usb_control_msg(gspca_dev->dev, pipe,
-                             req, req_type,
-                             val, 0, gspca_dev->usb_buf, size, 500);
-
-       if ((ret < 0) && (req != 0x0a))
-               pr_err("usb_control_msg error %i, request = 0x%x, error = %i\n",
-                      set, req, ret);
-
-       return ret;
-}
-
-static int stv0680_handle_error(struct gspca_dev *gspca_dev, int ret)
-{
-       stv_sndctrl(gspca_dev, 0, 0x80, 0, 0x02); /* Get Last Error */
-       PDEBUG(D_ERR, "last error: %i,  command = 0x%x",
-              gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
-       return ret;
-}
-
-static int stv0680_get_video_mode(struct gspca_dev *gspca_dev)
-{
-       /* Note not sure if this init of usb_buf is really necessary */
-       memset(gspca_dev->usb_buf, 0, 8);
-       gspca_dev->usb_buf[0] = 0x0f;
-
-       if (stv_sndctrl(gspca_dev, 0, 0x87, 0, 0x08) != 0x08) {
-               PDEBUG(D_ERR, "Get_Camera_Mode failed");
-               return stv0680_handle_error(gspca_dev, -EIO);
-       }
-
-       return gspca_dev->usb_buf[0]; /* 01 = VGA, 03 = QVGA, 00 = CIF */
-}
-
-static int stv0680_set_video_mode(struct gspca_dev *gspca_dev, u8 mode)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->current_mode == mode)
-               return 0;
-
-       memset(gspca_dev->usb_buf, 0, 8);
-       gspca_dev->usb_buf[0] = mode;
-
-       if (stv_sndctrl(gspca_dev, 3, 0x07, 0x0100, 0x08) != 0x08) {
-               PDEBUG(D_ERR, "Set_Camera_Mode failed");
-               return stv0680_handle_error(gspca_dev, -EIO);
-       }
-
-       /* Verify we got what we've asked for */
-       if (stv0680_get_video_mode(gspca_dev) != mode) {
-               PDEBUG(D_ERR, "Error setting camera video mode!");
-               return -EIO;
-       }
-
-       sd->current_mode = mode;
-
-       return 0;
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       int ret;
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam = &gspca_dev->cam;
-
-       /* Give the camera some time to settle, otherwise initalization will
-          fail on hotplug, and yes it really needs a full second. */
-       msleep(1000);
-
-       /* ping camera to be sure STV0680 is present */
-       if (stv_sndctrl(gspca_dev, 0, 0x88, 0x5678, 0x02) != 0x02 ||
-           gspca_dev->usb_buf[0] != 0x56 || gspca_dev->usb_buf[1] != 0x78) {
-               PDEBUG(D_ERR, "STV(e): camera ping failed!!");
-               return stv0680_handle_error(gspca_dev, -ENODEV);
-       }
-
-       /* get camera descriptor */
-       if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x09) != 0x09)
-               return stv0680_handle_error(gspca_dev, -ENODEV);
-
-       if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0200, 0x22) != 0x22 ||
-           gspca_dev->usb_buf[7] != 0xa0 || gspca_dev->usb_buf[8] != 0x23) {
-               PDEBUG(D_ERR, "Could not get descriptor 0200.");
-               return stv0680_handle_error(gspca_dev, -ENODEV);
-       }
-       if (stv_sndctrl(gspca_dev, 0, 0x8a, 0, 0x02) != 0x02)
-               return stv0680_handle_error(gspca_dev, -ENODEV);
-       if (stv_sndctrl(gspca_dev, 0, 0x8b, 0, 0x24) != 0x24)
-               return stv0680_handle_error(gspca_dev, -ENODEV);
-       if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10)
-               return stv0680_handle_error(gspca_dev, -ENODEV);
-
-       if (!(gspca_dev->usb_buf[7] & 0x09)) {
-               PDEBUG(D_ERR, "Camera supports neither CIF nor QVGA mode");
-               return -ENODEV;
-       }
-       if (gspca_dev->usb_buf[7] & 0x01)
-               PDEBUG(D_PROBE, "Camera supports CIF mode");
-       if (gspca_dev->usb_buf[7] & 0x02)
-               PDEBUG(D_PROBE, "Camera supports VGA mode");
-       if (gspca_dev->usb_buf[7] & 0x04)
-               PDEBUG(D_PROBE, "Camera supports QCIF mode");
-       if (gspca_dev->usb_buf[7] & 0x08)
-               PDEBUG(D_PROBE, "Camera supports QVGA mode");
-
-       if (gspca_dev->usb_buf[7] & 0x01)
-               sd->video_mode = 0x00; /* CIF */
-       else
-               sd->video_mode = 0x03; /* QVGA */
-
-       /* FW rev, ASIC rev, sensor ID  */
-       PDEBUG(D_PROBE, "Firmware rev is %i.%i",
-              gspca_dev->usb_buf[0], gspca_dev->usb_buf[1]);
-       PDEBUG(D_PROBE, "ASIC rev is %i.%i",
-              gspca_dev->usb_buf[2], gspca_dev->usb_buf[3]);
-       PDEBUG(D_PROBE, "Sensor ID is %i",
-              (gspca_dev->usb_buf[4]*16) + (gspca_dev->usb_buf[5]>>4));
-
-
-       ret = stv0680_get_video_mode(gspca_dev);
-       if (ret < 0)
-               return ret;
-       sd->current_mode = sd->orig_mode = ret;
-
-       ret = stv0680_set_video_mode(gspca_dev, sd->video_mode);
-       if (ret < 0)
-               return ret;
-
-       /* Get mode details */
-       if (stv_sndctrl(gspca_dev, 0, 0x8f, 0, 0x10) != 0x10)
-               return stv0680_handle_error(gspca_dev, -EIO);
-
-       cam->bulk = 1;
-       cam->bulk_nurbs = 1; /* The cam cannot handle more */
-       cam->bulk_size = (gspca_dev->usb_buf[0] << 24) |
-                        (gspca_dev->usb_buf[1] << 16) |
-                        (gspca_dev->usb_buf[2] << 8) |
-                        (gspca_dev->usb_buf[3]);
-       sd->mode.width = (gspca_dev->usb_buf[4] << 8) |
-                        (gspca_dev->usb_buf[5]);  /* 322, 356, 644 */
-       sd->mode.height = (gspca_dev->usb_buf[6] << 8) |
-                         (gspca_dev->usb_buf[7]); /* 242, 292, 484 */
-       sd->mode.pixelformat = V4L2_PIX_FMT_STV0680;
-       sd->mode.field = V4L2_FIELD_NONE;
-       sd->mode.bytesperline = sd->mode.width;
-       sd->mode.sizeimage = cam->bulk_size;
-       sd->mode.colorspace = V4L2_COLORSPACE_SRGB;
-
-       /* origGain = gspca_dev->usb_buf[12]; */
-
-       cam->cam_mode = &sd->mode;
-       cam->nmodes = 1;
-
-
-       ret = stv0680_set_video_mode(gspca_dev, sd->orig_mode);
-       if (ret < 0)
-               return ret;
-
-       if (stv_sndctrl(gspca_dev, 2, 0x06, 0x0100, 0x12) != 0x12 ||
-           gspca_dev->usb_buf[8] != 0x53 || gspca_dev->usb_buf[9] != 0x05) {
-               pr_err("Could not get descriptor 0100\n");
-               return stv0680_handle_error(gspca_dev, -EIO);
-       }
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       return 0;
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       int ret;
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       ret = stv0680_set_video_mode(gspca_dev, sd->video_mode);
-       if (ret < 0)
-               return ret;
-
-       if (stv_sndctrl(gspca_dev, 0, 0x85, 0, 0x10) != 0x10)
-               return stv0680_handle_error(gspca_dev, -EIO);
-
-       /* Start stream at:
-          0x0000 = CIF (352x288)
-          0x0100 = VGA (640x480)
-          0x0300 = QVGA (320x240) */
-       if (stv_sndctrl(gspca_dev, 1, 0x09, sd->video_mode << 8, 0x0) != 0x0)
-               return stv0680_handle_error(gspca_dev, -EIO);
-
-       return 0;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       /* This is a high priority command; it stops all lower order cmds */
-       if (stv_sndctrl(gspca_dev, 1, 0x04, 0x0000, 0x0) != 0x0)
-               stv0680_handle_error(gspca_dev, -EIO);
-}
-
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (!sd->gspca_dev.present)
-               return;
-
-       stv0680_set_video_mode(gspca_dev, sd->orig_mode);
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,
-                       int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* Every now and then the camera sends a 16 byte packet, no idea
-          what it contains, but it is not image data, when this
-          happens the frame received before this packet is corrupt,
-          so discard it. */
-       if (len != sd->mode.sizeimage) {
-               gspca_dev->last_packet_type = DISCARD_PACKET;
-               return;
-       }
-
-       /* Finish the previous frame, we do this upon reception of the next
-          packet, even though it is already complete so that the strange 16
-          byte packets send after a corrupt frame can discard it. */
-       gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-
-       /* Store the just received frame */
-       gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
-}
-
-/* sub-driver description */
-static const struct sd_desc sd_desc = {
-       .name = MODULE_NAME,
-       .config = sd_config,
-       .init = sd_init,
-       .start = sd_start,
-       .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x0553, 0x0202)},
-       {USB_DEVICE(0x041e, 0x4007)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/stv06xx/Kconfig b/drivers/media/video/gspca/stv06xx/Kconfig
deleted file mode 100644 (file)
index 634ad38..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-config USB_STV06XX
-       tristate "STV06XX USB Camera Driver"
-       depends on USB_GSPCA
-       help
-         Say Y here if you want support for cameras based on
-         the ST STV06XX chip.
-
-         To compile this driver as a module, choose M here: the
-         module will be called gspca_stv06xx.
diff --git a/drivers/media/video/gspca/stv06xx/Makefile b/drivers/media/video/gspca/stv06xx/Makefile
deleted file mode 100644 (file)
index 38bc410..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-obj-$(CONFIG_USB_STV06XX) += gspca_stv06xx.o
-
-gspca_stv06xx-objs := stv06xx.o \
-                     stv06xx_vv6410.o \
-                     stv06xx_hdcs.o \
-                     stv06xx_pb0100.o \
-                     stv06xx_st6422.o
-
-ccflags-y += -I$(srctree)/drivers/media/video/gspca
-
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c
deleted file mode 100644 (file)
index 999ec77..0000000
+++ /dev/null
@@ -1,634 +0,0 @@
-/*
- * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
- *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
- * Copyright (c) 2002, 2003 Tuukka Toivonen
- * Copyright (c) 2008 Erik Andrén
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * P/N 861037:      Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
- * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
- * P/N 861075-0040: Sensor HDCS1000        ASIC
- * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
- * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/input.h>
-#include "stv06xx_sensor.h"
-
-MODULE_AUTHOR("Erik Andrén");
-MODULE_DESCRIPTION("STV06XX USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-static bool dump_bridge;
-static bool dump_sensor;
-
-int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data)
-{
-       int err;
-       struct usb_device *udev = sd->gspca_dev.dev;
-       __u8 *buf = sd->gspca_dev.usb_buf;
-       u8 len = (i2c_data > 0xff) ? 2 : 1;
-
-       buf[0] = i2c_data & 0xff;
-       buf[1] = (i2c_data >> 8) & 0xff;
-
-       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                             0x04, 0x40, address, 0, buf, len,
-                             STV06XX_URB_MSG_TIMEOUT);
-
-       PDEBUG(D_CONF, "Written 0x%x to address 0x%x, status: %d",
-              i2c_data, address, err);
-
-       return (err < 0) ? err : 0;
-}
-
-int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data)
-{
-       int err;
-       struct usb_device *udev = sd->gspca_dev.dev;
-       __u8 *buf = sd->gspca_dev.usb_buf;
-
-       err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-                             0x04, 0xc0, address, 0, buf, 1,
-                             STV06XX_URB_MSG_TIMEOUT);
-
-       *i2c_data = buf[0];
-
-       PDEBUG(D_CONF, "Reading 0x%x from address 0x%x, status %d",
-              *i2c_data, address, err);
-
-       return (err < 0) ? err : 0;
-}
-
-/* Wraps the normal write sensor bytes / words functions for writing a
-   single value */
-int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value)
-{
-       if (sd->sensor->i2c_len == 2) {
-               u16 data[2] = { address, value };
-               return stv06xx_write_sensor_words(sd, data, 1);
-       } else {
-               u8 data[2] = { address, value };
-               return stv06xx_write_sensor_bytes(sd, data, 1);
-       }
-}
-
-static int stv06xx_write_sensor_finish(struct sd *sd)
-{
-       int err = 0;
-
-       if (sd->bridge == BRIDGE_STV610) {
-               struct usb_device *udev = sd->gspca_dev.dev;
-               __u8 *buf = sd->gspca_dev.usb_buf;
-
-               buf[0] = 0;
-               err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                     0x04, 0x40, 0x1704, 0, buf, 1,
-                                     STV06XX_URB_MSG_TIMEOUT);
-       }
-
-       return (err < 0) ? err : 0;
-}
-
-int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len)
-{
-       int err, i, j;
-       struct usb_device *udev = sd->gspca_dev.dev;
-       __u8 *buf = sd->gspca_dev.usb_buf;
-
-       PDEBUG(D_CONF, "I2C: Command buffer contains %d entries", len);
-       for (i = 0; i < len;) {
-               /* Build the command buffer */
-               memset(buf, 0, I2C_BUFFER_LENGTH);
-               for (j = 0; j < I2C_MAX_BYTES && i < len; j++, i++) {
-                       buf[j] = data[2*i];
-                       buf[0x10 + j] = data[2*i+1];
-                       PDEBUG(D_CONF, "I2C: Writing 0x%02x to reg 0x%02x",
-                       data[2*i+1], data[2*i]);
-               }
-               buf[0x20] = sd->sensor->i2c_addr;
-               buf[0x21] = j - 1; /* Number of commands to send - 1 */
-               buf[0x22] = I2C_WRITE_CMD;
-               err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                     0x04, 0x40, 0x0400, 0, buf,
-                                     I2C_BUFFER_LENGTH,
-                                     STV06XX_URB_MSG_TIMEOUT);
-               if (err < 0)
-                       return err;
-       }
-       return stv06xx_write_sensor_finish(sd);
-}
-
-int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len)
-{
-       int err, i, j;
-       struct usb_device *udev = sd->gspca_dev.dev;
-       __u8 *buf = sd->gspca_dev.usb_buf;
-
-       PDEBUG(D_CONF, "I2C: Command buffer contains %d entries", len);
-
-       for (i = 0; i < len;) {
-               /* Build the command buffer */
-               memset(buf, 0, I2C_BUFFER_LENGTH);
-               for (j = 0; j < I2C_MAX_WORDS && i < len; j++, i++) {
-                       buf[j] = data[2*i];
-                       buf[0x10 + j * 2] = data[2*i+1];
-                       buf[0x10 + j * 2 + 1] = data[2*i+1] >> 8;
-                       PDEBUG(D_CONF, "I2C: Writing 0x%04x to reg 0x%02x",
-                               data[2*i+1], data[2*i]);
-               }
-               buf[0x20] = sd->sensor->i2c_addr;
-               buf[0x21] = j - 1; /* Number of commands to send - 1 */
-               buf[0x22] = I2C_WRITE_CMD;
-               err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                               0x04, 0x40, 0x0400, 0, buf,
-                               I2C_BUFFER_LENGTH,
-                               STV06XX_URB_MSG_TIMEOUT);
-               if (err < 0)
-                       return err;
-       }
-       return stv06xx_write_sensor_finish(sd);
-}
-
-int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value)
-{
-       int err;
-       struct usb_device *udev = sd->gspca_dev.dev;
-       __u8 *buf = sd->gspca_dev.usb_buf;
-
-       err = stv06xx_write_bridge(sd, STV_I2C_FLUSH, sd->sensor->i2c_flush);
-       if (err < 0)
-               return err;
-
-       /* Clear mem */
-       memset(buf, 0, I2C_BUFFER_LENGTH);
-
-       buf[0] = address;
-       buf[0x20] = sd->sensor->i2c_addr;
-       buf[0x21] = 0;
-
-       /* Read I2C register */
-       buf[0x22] = I2C_READ_CMD;
-
-       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                             0x04, 0x40, 0x1400, 0, buf, I2C_BUFFER_LENGTH,
-                             STV06XX_URB_MSG_TIMEOUT);
-       if (err < 0) {
-               pr_err("I2C: Read error writing address: %d\n", err);
-               return err;
-       }
-
-       err = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-                             0x04, 0xc0, 0x1410, 0, buf, sd->sensor->i2c_len,
-                             STV06XX_URB_MSG_TIMEOUT);
-       if (sd->sensor->i2c_len == 2)
-               *value = buf[0] | (buf[1] << 8);
-       else
-               *value = buf[0];
-
-       PDEBUG(D_CONF, "I2C: Read 0x%x from address 0x%x, status: %d",
-              *value, address, err);
-
-       return (err < 0) ? err : 0;
-}
-
-/* Dumps all bridge registers */
-static void stv06xx_dump_bridge(struct sd *sd)
-{
-       int i;
-       u8 data, buf;
-
-       pr_info("Dumping all stv06xx bridge registers\n");
-       for (i = 0x1400; i < 0x160f; i++) {
-               stv06xx_read_bridge(sd, i, &data);
-
-               pr_info("Read 0x%x from address 0x%x\n", data, i);
-       }
-
-       pr_info("Testing stv06xx bridge registers for writability\n");
-       for (i = 0x1400; i < 0x160f; i++) {
-               stv06xx_read_bridge(sd, i, &data);
-               buf = data;
-
-               stv06xx_write_bridge(sd, i, 0xff);
-               stv06xx_read_bridge(sd, i, &data);
-               if (data == 0xff)
-                       pr_info("Register 0x%x is read/write\n", i);
-               else if (data != buf)
-                       pr_info("Register 0x%x is read/write, but only partially\n",
-                               i);
-               else
-                       pr_info("Register 0x%x is read-only\n", i);
-
-               stv06xx_write_bridge(sd, i, buf);
-       }
-}
-
-/* this function is called at probe and resume time */
-static int stv06xx_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int err;
-
-       PDEBUG(D_PROBE, "Initializing camera");
-
-       /* Let the usb init settle for a bit
-          before performing the initialization */
-       msleep(250);
-
-       err = sd->sensor->init(sd);
-
-       if (dump_sensor && sd->sensor->dump)
-               sd->sensor->dump(sd);
-
-       return (err < 0) ? err : 0;
-}
-
-/* this function is called at probe time */
-static int stv06xx_init_controls(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       PDEBUG(D_PROBE, "Initializing controls");
-
-       gspca_dev->vdev.ctrl_handler = &gspca_dev->ctrl_handler;
-       return sd->sensor->init_controls(sd);
-}
-
-/* Start the camera */
-static int stv06xx_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct usb_host_interface *alt;
-       struct usb_interface *intf;
-       int err, packet_size;
-
-       intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
-       alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
-       if (!alt) {
-               PDEBUG(D_ERR, "Couldn't get altsetting");
-               return -EIO;
-       }
-
-       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
-       err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size);
-       if (err < 0)
-               return err;
-
-       /* Prepare the sensor for start */
-       err = sd->sensor->start(sd);
-       if (err < 0)
-               goto out;
-
-       /* Start isochronous streaming */
-       err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 1);
-
-out:
-       if (err < 0)
-               PDEBUG(D_STREAM, "Starting stream failed");
-       else
-               PDEBUG(D_STREAM, "Started streaming");
-
-       return (err < 0) ? err : 0;
-}
-
-static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
-{
-       struct usb_host_interface *alt;
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
-       alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
-       alt->endpoint[0].desc.wMaxPacketSize =
-               cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
-
-       return 0;
-}
-
-static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev)
-{
-       int ret, packet_size, min_packet_size;
-       struct usb_host_interface *alt;
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
-       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
-       min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
-       if (packet_size <= min_packet_size)
-               return -EIO;
-
-       packet_size -= 100;
-       if (packet_size < min_packet_size)
-               packet_size = min_packet_size;
-       alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
-
-       ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
-       if (ret < 0)
-               PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret);
-
-       return ret;
-}
-
-static void stv06xx_stopN(struct gspca_dev *gspca_dev)
-{
-       int err;
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* stop ISO-streaming */
-       err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 0);
-       if (err < 0)
-               goto out;
-
-       err = sd->sensor->stop(sd);
-
-out:
-       if (err < 0)
-               PDEBUG(D_STREAM, "Failed to stop stream");
-       else
-               PDEBUG(D_STREAM, "Stopped streaming");
-}
-
-/*
- * Analyse an USB packet of the data stream and store it appropriately.
- * Each packet contains an integral number of chunks. Each chunk has
- * 2-bytes identification, followed by 2-bytes that describe the chunk
- * length. Known/guessed chunk identifications are:
- * 8001/8005/C001/C005 - Begin new frame
- * 8002/8006/C002/C006 - End frame
- * 0200/4200           - Contains actual image data, bayer or compressed
- * 0005                - 11 bytes of unknown data
- * 0100                - 2 bytes of unknown data
- * The 0005 and 0100 chunks seem to appear only in compressed stream.
- */
-static void stv06xx_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,                       /* isoc packet */
-                       int len)                        /* iso packet length */
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       PDEBUG(D_PACK, "Packet of length %d arrived", len);
-
-       /* A packet may contain several frames
-          loop until the whole packet is reached */
-       while (len) {
-               int id, chunk_len;
-
-               if (len < 4) {
-                       PDEBUG(D_PACK, "Packet is smaller than 4 bytes");
-                       return;
-               }
-
-               /* Capture the id */
-               id = (data[0] << 8) | data[1];
-
-               /* Capture the chunk length */
-               chunk_len = (data[2] << 8) | data[3];
-               PDEBUG(D_PACK, "Chunk id: %x, length: %d", id, chunk_len);
-
-               data += 4;
-               len -= 4;
-
-               if (len < chunk_len) {
-                       PDEBUG(D_ERR, "URB packet length is smaller"
-                               " than the specified chunk length");
-                       gspca_dev->last_packet_type = DISCARD_PACKET;
-                       return;
-               }
-
-               /* First byte seem to be 02=data 2nd byte is unknown??? */
-               if (sd->bridge == BRIDGE_ST6422 && (id & 0xff00) == 0x0200)
-                       goto frame_data;
-
-               switch (id) {
-               case 0x0200:
-               case 0x4200:
-frame_data:
-                       PDEBUG(D_PACK, "Frame data packet detected");
-
-                       if (sd->to_skip) {
-                               int skip = (sd->to_skip < chunk_len) ?
-                                           sd->to_skip : chunk_len;
-                               data += skip;
-                               len -= skip;
-                               chunk_len -= skip;
-                               sd->to_skip -= skip;
-                       }
-
-                       gspca_frame_add(gspca_dev, INTER_PACKET,
-                                       data, chunk_len);
-                       break;
-
-               case 0x8001:
-               case 0x8005:
-               case 0xc001:
-               case 0xc005:
-                       PDEBUG(D_PACK, "Starting new frame");
-
-                       /* Create a new frame, chunk length should be zero */
-                       gspca_frame_add(gspca_dev, FIRST_PACKET,
-                                       NULL, 0);
-
-                       if (sd->bridge == BRIDGE_ST6422)
-                               sd->to_skip = gspca_dev->width * 4;
-
-                       if (chunk_len)
-                               PDEBUG(D_ERR, "Chunk length is "
-                                             "non-zero on a SOF");
-                       break;
-
-               case 0x8002:
-               case 0x8006:
-               case 0xc002:
-                       PDEBUG(D_PACK, "End of frame detected");
-
-                       /* Complete the last frame (if any) */
-                       gspca_frame_add(gspca_dev, LAST_PACKET,
-                                       NULL, 0);
-
-                       if (chunk_len)
-                               PDEBUG(D_ERR, "Chunk length is "
-                                             "non-zero on a EOF");
-                       break;
-
-               case 0x0005:
-                       PDEBUG(D_PACK, "Chunk 0x005 detected");
-                       /* Unknown chunk with 11 bytes of data,
-                          occurs just before end of each frame
-                          in compressed mode */
-                       break;
-
-               case 0x0100:
-                       PDEBUG(D_PACK, "Chunk 0x0100 detected");
-                       /* Unknown chunk with 2 bytes of data,
-                          occurs 2-3 times per USB interrupt */
-                       break;
-               case 0x42ff:
-                       PDEBUG(D_PACK, "Chunk 0x42ff detected");
-                       /* Special chunk seen sometimes on the ST6422 */
-                       break;
-               default:
-                       PDEBUG(D_PACK, "Unknown chunk 0x%04x detected", id);
-                       /* Unknown chunk */
-               }
-               data    += chunk_len;
-               len     -= chunk_len;
-       }
-}
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,               /* interrupt packet data */
-                       int len)                /* interrupt packet length */
-{
-       int ret = -EINVAL;
-
-       if (len == 1 && data[0] == 0x80) {
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
-               input_sync(gspca_dev->input_dev);
-               ret = 0;
-       }
-
-       if (len == 1 && data[0] == 0x88) {
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
-               input_sync(gspca_dev->input_dev);
-               ret = 0;
-       }
-
-       return ret;
-}
-#endif
-
-static int stv06xx_config(struct gspca_dev *gspca_dev,
-                         const struct usb_device_id *id);
-
-/* sub-driver description */
-static const struct sd_desc sd_desc = {
-       .name = MODULE_NAME,
-       .config = stv06xx_config,
-       .init = stv06xx_init,
-       .init_controls = stv06xx_init_controls,
-       .start = stv06xx_start,
-       .stopN = stv06xx_stopN,
-       .pkt_scan = stv06xx_pkt_scan,
-       .isoc_init = stv06xx_isoc_init,
-       .isoc_nego = stv06xx_isoc_nego,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .int_pkt_scan = sd_int_pkt_scan,
-#endif
-};
-
-/* This function is called at probe time */
-static int stv06xx_config(struct gspca_dev *gspca_dev,
-                         const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       PDEBUG(D_PROBE, "Configuring camera");
-
-       sd->bridge = id->driver_info;
-       gspca_dev->sd_desc = &sd_desc;
-
-       if (dump_bridge)
-               stv06xx_dump_bridge(sd);
-
-       sd->sensor = &stv06xx_sensor_st6422;
-       if (!sd->sensor->probe(sd))
-               return 0;
-
-       sd->sensor = &stv06xx_sensor_vv6410;
-       if (!sd->sensor->probe(sd))
-               return 0;
-
-       sd->sensor = &stv06xx_sensor_hdcs1x00;
-       if (!sd->sensor->probe(sd))
-               return 0;
-
-       sd->sensor = &stv06xx_sensor_hdcs1020;
-       if (!sd->sensor->probe(sd))
-               return 0;
-
-       sd->sensor = &stv06xx_sensor_pb0100;
-       if (!sd->sensor->probe(sd))
-               return 0;
-
-       sd->sensor = NULL;
-       return -ENODEV;
-}
-
-
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       /* QuickCam Express */
-       {USB_DEVICE(0x046d, 0x0840), .driver_info = BRIDGE_STV600 },
-       /* LEGO cam / QuickCam Web */
-       {USB_DEVICE(0x046d, 0x0850), .driver_info = BRIDGE_STV610 },
-       /* Dexxa WebCam USB */
-       {USB_DEVICE(0x046d, 0x0870), .driver_info = BRIDGE_STV602 },
-       /* QuickCam Messenger */
-       {USB_DEVICE(0x046D, 0x08F0), .driver_info = BRIDGE_ST6422 },
-       /* QuickCam Communicate */
-       {USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 },
-       /* QuickCam Messenger (new) */
-       {USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 },
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-static int sd_probe(struct usb_interface *intf,
-                       const struct usb_device_id *id)
-{
-       PDEBUG(D_PROBE, "Probing for a stv06xx device");
-       return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
-                              THIS_MODULE);
-}
-
-static void sd_disconnect(struct usb_interface *intf)
-{
-       struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
-       struct sd *sd = (struct sd *) gspca_dev;
-       void *priv = sd->sensor_priv;
-       PDEBUG(D_PROBE, "Disconnecting the stv06xx device");
-
-       sd->sensor = NULL;
-       gspca_disconnect(intf);
-       kfree(priv);
-}
-
-static struct usb_driver sd_driver = {
-       .name = MODULE_NAME,
-       .id_table = device_table,
-       .probe = sd_probe,
-       .disconnect = sd_disconnect,
-#ifdef CONFIG_PM
-       .suspend = gspca_suspend,
-       .resume = gspca_resume,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
-
-module_param(dump_bridge, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(dump_bridge, "Dumps all usb bridge registers at startup");
-
-module_param(dump_sensor, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(dump_sensor, "Dumps all sensor registers at startup");
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.h b/drivers/media/video/gspca/stv06xx/stv06xx.h
deleted file mode 100644 (file)
index 34957a4..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
- *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
- * Copyright (c) 2002, 2003 Tuukka Toivonen
- * Copyright (c) 2008 Erik Andrén
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * P/N 861037:      Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
- * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
- * P/N 861075-0040: Sensor HDCS1000        ASIC
- * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
- * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
- */
-
-#ifndef STV06XX_H_
-#define STV06XX_H_
-
-#include <linux/slab.h>
-#include "gspca.h"
-
-#define MODULE_NAME "STV06xx"
-
-#define STV_ISOC_ENDPOINT_ADDR         0x81
-
-#define STV_R                           0x0509
-
-#define STV_REG23                      0x0423
-
-/* Control registers of the STV0600 ASIC */
-#define STV_I2C_PARTNER                        0x1420
-#define STV_I2C_VAL_REG_VAL_PAIRS_MIN1 0x1421
-#define STV_I2C_READ_WRITE_TOGGLE      0x1422
-#define STV_I2C_FLUSH                  0x1423
-#define STV_I2C_SUCC_READ_REG_VALS     0x1424
-
-#define STV_ISO_ENABLE                 0x1440
-#define STV_SCAN_RATE                  0x1443
-#define STV_LED_CTRL                   0x1445
-#define STV_STV0600_EMULATION          0x1446
-#define STV_REG00                      0x1500
-#define STV_REG01                      0x1501
-#define STV_REG02                      0x1502
-#define STV_REG03                      0x1503
-#define STV_REG04                      0x1504
-
-#define STV_ISO_SIZE_L                 0x15c1
-#define STV_ISO_SIZE_H                 0x15c2
-
-/* Refers to the CIF 352x288 and QCIF 176x144 */
-/* 1: 288 lines, 2: 144 lines */
-#define STV_Y_CTRL                     0x15c3
-
-#define STV_RESET                       0x1620
-
-/* 0xa: 352 columns, 0x6: 176 columns */
-#define STV_X_CTRL                     0x1680
-
-#define STV06XX_URB_MSG_TIMEOUT                5000
-
-#define I2C_MAX_BYTES                  16
-#define I2C_MAX_WORDS                  8
-
-#define I2C_BUFFER_LENGTH              0x23
-#define I2C_READ_CMD                   3
-#define I2C_WRITE_CMD                  1
-
-#define LED_ON                         1
-#define LED_OFF                                0
-
-/* STV06xx device descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;
-
-       /* A pointer to the currently connected sensor */
-       const struct stv06xx_sensor *sensor;
-
-       /* Sensor private data */
-       void *sensor_priv;
-
-       /* The first 4 lines produced by the stv6422 are no good, this keeps
-          track of how many bytes we still need to skip during a frame */
-       int to_skip;
-
-       /* Bridge / Camera type */
-       u8 bridge;
-       #define BRIDGE_STV600 0
-       #define BRIDGE_STV602 1
-       #define BRIDGE_STV610 2
-       #define BRIDGE_ST6422 3 /* With integrated sensor */
-};
-
-int stv06xx_write_bridge(struct sd *sd, u16 address, u16 i2c_data);
-int stv06xx_read_bridge(struct sd *sd, u16 address, u8 *i2c_data);
-
-int stv06xx_write_sensor_bytes(struct sd *sd, const u8 *data, u8 len);
-int stv06xx_write_sensor_words(struct sd *sd, const u16 *data, u8 len);
-
-int stv06xx_read_sensor(struct sd *sd, const u8 address, u16 *value);
-int stv06xx_write_sensor(struct sd *sd, u8 address, u16 value);
-
-#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
deleted file mode 100644 (file)
index 06fa54c..0000000
+++ /dev/null
@@ -1,540 +0,0 @@
-/*
- * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
- *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
- * Copyright (c) 2002, 2003 Tuukka Toivonen
- * Copyright (c) 2008 Erik Andrén
- * Copyright (c) 2008 Chia-I Wu
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * P/N 861037:      Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
- * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
- * P/N 861075-0040: Sensor HDCS1000        ASIC
- * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
- * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "stv06xx_hdcs.h"
-
-static struct v4l2_pix_format hdcs1x00_mode[] = {
-       {
-               HDCS_1X00_DEF_WIDTH,
-               HDCS_1X00_DEF_HEIGHT,
-               V4L2_PIX_FMT_SGRBG8,
-               V4L2_FIELD_NONE,
-               .sizeimage =
-                       HDCS_1X00_DEF_WIDTH * HDCS_1X00_DEF_HEIGHT,
-               .bytesperline = HDCS_1X00_DEF_WIDTH,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1
-       }
-};
-
-static struct v4l2_pix_format hdcs1020_mode[] = {
-       {
-               HDCS_1020_DEF_WIDTH,
-               HDCS_1020_DEF_HEIGHT,
-               V4L2_PIX_FMT_SGRBG8,
-               V4L2_FIELD_NONE,
-               .sizeimage =
-                       HDCS_1020_DEF_WIDTH * HDCS_1020_DEF_HEIGHT,
-               .bytesperline = HDCS_1020_DEF_WIDTH,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1
-       }
-};
-
-enum hdcs_power_state {
-       HDCS_STATE_SLEEP,
-       HDCS_STATE_IDLE,
-       HDCS_STATE_RUN
-};
-
-/* no lock? */
-struct hdcs {
-       enum hdcs_power_state state;
-       int w, h;
-
-       /* visible area of the sensor array */
-       struct {
-               int left, top;
-               int width, height;
-               int border;
-       } array;
-
-       struct {
-               /* Column timing overhead */
-               u8 cto;
-               /* Column processing overhead */
-               u8 cpo;
-               /* Row sample period constant */
-               u16 rs;
-               /* Exposure reset duration */
-               u16 er;
-       } exp;
-
-       int psmp;
-};
-
-static int hdcs_reg_write_seq(struct sd *sd, u8 reg, u8 *vals, u8 len)
-{
-       u8 regs[I2C_MAX_BYTES * 2];
-       int i;
-
-       if (unlikely((len <= 0) || (len >= I2C_MAX_BYTES) ||
-                    (reg + len > 0xff)))
-               return -EINVAL;
-
-       for (i = 0; i < len; i++) {
-               regs[2 * i] = reg;
-               regs[2 * i + 1] = vals[i];
-               /* All addresses are shifted left one bit
-                * as bit 0 toggles r/w */
-               reg += 2;
-       }
-
-       return stv06xx_write_sensor_bytes(sd, regs, len);
-}
-
-static int hdcs_set_state(struct sd *sd, enum hdcs_power_state state)
-{
-       struct hdcs *hdcs = sd->sensor_priv;
-       u8 val;
-       int ret;
-
-       if (hdcs->state == state)
-               return 0;
-
-       /* we need to go idle before running or sleeping */
-       if (hdcs->state != HDCS_STATE_IDLE) {
-               ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
-               if (ret)
-                       return ret;
-       }
-
-       hdcs->state = HDCS_STATE_IDLE;
-
-       if (state == HDCS_STATE_IDLE)
-               return 0;
-
-       switch (state) {
-       case HDCS_STATE_SLEEP:
-               val = HDCS_SLEEP_MODE;
-               break;
-
-       case HDCS_STATE_RUN:
-               val = HDCS_RUN_ENABLE;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       ret = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), val);
-
-       /* Update the state if the write succeeded */
-       if (!ret)
-               hdcs->state = state;
-
-       return ret;
-}
-
-static int hdcs_reset(struct sd *sd)
-{
-       struct hdcs *hdcs = sd->sensor_priv;
-       int err;
-
-       err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 1);
-       if (err < 0)
-               return err;
-
-       err = stv06xx_write_sensor(sd, HDCS_REG_CONTROL(sd), 0);
-       if (err < 0)
-               hdcs->state = HDCS_STATE_IDLE;
-
-       return err;
-}
-
-static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct hdcs *hdcs = sd->sensor_priv;
-       int rowexp, srowexp;
-       int max_srowexp;
-       /* Column time period */
-       int ct;
-       /* Column processing period */
-       int cp;
-       /* Row processing period */
-       int rp;
-       /* Minimum number of column timing periods
-          within the column processing period */
-       int mnct;
-       int cycles, err;
-       u8 exp[14];
-
-       cycles = val * HDCS_CLK_FREQ_MHZ * 257;
-
-       ct = hdcs->exp.cto + hdcs->psmp + (HDCS_ADC_START_SIG_DUR + 2);
-       cp = hdcs->exp.cto + (hdcs->w * ct / 2);
-
-       /* the cycles one row takes */
-       rp = hdcs->exp.rs + cp;
-
-       rowexp = cycles / rp;
-
-       /* the remaining cycles */
-       cycles -= rowexp * rp;
-
-       /* calculate sub-row exposure */
-       if (IS_1020(sd)) {
-               /* see HDCS-1020 datasheet 3.5.6.4, p. 63 */
-               srowexp = hdcs->w - (cycles + hdcs->exp.er + 13) / ct;
-
-               mnct = (hdcs->exp.er + 12 + ct - 1) / ct;
-               max_srowexp = hdcs->w - mnct;
-       } else {
-               /* see HDCS-1000 datasheet 3.4.5.5, p. 61 */
-               srowexp = cp - hdcs->exp.er - 6 - cycles;
-
-               mnct = (hdcs->exp.er + 5 + ct - 1) / ct;
-               max_srowexp = cp - mnct * ct - 1;
-       }
-
-       if (srowexp < 0)
-               srowexp = 0;
-       else if (srowexp > max_srowexp)
-               srowexp = max_srowexp;
-
-       if (IS_1020(sd)) {
-               exp[0] = HDCS20_CONTROL;
-               exp[1] = 0x00;          /* Stop streaming */
-               exp[2] = HDCS_ROWEXPL;
-               exp[3] = rowexp & 0xff;
-               exp[4] = HDCS_ROWEXPH;
-               exp[5] = rowexp >> 8;
-               exp[6] = HDCS20_SROWEXP;
-               exp[7] = (srowexp >> 2) & 0xff;
-               exp[8] = HDCS20_ERROR;
-               exp[9] = 0x10;          /* Clear exposure error flag*/
-               exp[10] = HDCS20_CONTROL;
-               exp[11] = 0x04;         /* Restart streaming */
-               err = stv06xx_write_sensor_bytes(sd, exp, 6);
-       } else {
-               exp[0] = HDCS00_CONTROL;
-               exp[1] = 0x00;         /* Stop streaming */
-               exp[2] = HDCS_ROWEXPL;
-               exp[3] = rowexp & 0xff;
-               exp[4] = HDCS_ROWEXPH;
-               exp[5] = rowexp >> 8;
-               exp[6] = HDCS00_SROWEXPL;
-               exp[7] = srowexp & 0xff;
-               exp[8] = HDCS00_SROWEXPH;
-               exp[9] = srowexp >> 8;
-               exp[10] = HDCS_STATUS;
-               exp[11] = 0x10;         /* Clear exposure error flag*/
-               exp[12] = HDCS00_CONTROL;
-               exp[13] = 0x04;         /* Restart streaming */
-               err = stv06xx_write_sensor_bytes(sd, exp, 7);
-               if (err < 0)
-                       return err;
-       }
-       PDEBUG(D_V4L2, "Writing exposure %d, rowexp %d, srowexp %d",
-              val, rowexp, srowexp);
-       return err;
-}
-
-static int hdcs_set_gains(struct sd *sd, u8 g)
-{
-       int err;
-       u8 gains[4];
-
-       /* the voltage gain Av = (1 + 19 * val / 127) * (1 + bit7) */
-       if (g > 127)
-               g = 0x80 | (g / 2);
-
-       gains[0] = g;
-       gains[1] = g;
-       gains[2] = g;
-       gains[3] = g;
-
-       err = hdcs_reg_write_seq(sd, HDCS_ERECPGA, gains, 4);
-       return err;
-}
-
-static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val)
-{
-       PDEBUG(D_V4L2, "Writing gain %d", val);
-       return hdcs_set_gains((struct sd *) gspca_dev,
-                              val & 0xff);
-}
-
-static int hdcs_set_size(struct sd *sd,
-               unsigned int width, unsigned int height)
-{
-       struct hdcs *hdcs = sd->sensor_priv;
-       u8 win[4];
-       unsigned int x, y;
-       int err;
-
-       /* must be multiple of 4 */
-       width = (width + 3) & ~0x3;
-       height = (height + 3) & ~0x3;
-
-       if (width > hdcs->array.width)
-               width = hdcs->array.width;
-
-       if (IS_1020(sd)) {
-               /* the borders are also invalid */
-               if (height + 2 * hdcs->array.border + HDCS_1020_BOTTOM_Y_SKIP
-                                 > hdcs->array.height)
-                       height = hdcs->array.height - 2 * hdcs->array.border -
-                               HDCS_1020_BOTTOM_Y_SKIP;
-
-               y = (hdcs->array.height - HDCS_1020_BOTTOM_Y_SKIP - height) / 2
-                               + hdcs->array.top;
-       } else {
-               if (height > hdcs->array.height)
-                       height = hdcs->array.height;
-
-               y = hdcs->array.top + (hdcs->array.height - height) / 2;
-       }
-
-       x = hdcs->array.left + (hdcs->array.width - width) / 2;
-
-       win[0] = y / 4;
-       win[1] = x / 4;
-       win[2] = (y + height) / 4 - 1;
-       win[3] = (x + width) / 4 - 1;
-
-       err = hdcs_reg_write_seq(sd, HDCS_FWROW, win, 4);
-       if (err < 0)
-               return err;
-
-       /* Update the current width and height */
-       hdcs->w = width;
-       hdcs->h = height;
-       return err;
-}
-
-static int hdcs_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct gspca_dev *gspca_dev =
-               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
-       int err = -EINVAL;
-
-       switch (ctrl->id) {
-       case V4L2_CID_GAIN:
-               err = hdcs_set_gain(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_EXPOSURE:
-               err = hdcs_set_exposure(gspca_dev, ctrl->val);
-               break;
-       }
-       return err;
-}
-
-static const struct v4l2_ctrl_ops hdcs_ctrl_ops = {
-       .s_ctrl = hdcs_s_ctrl,
-};
-
-static int hdcs_init_controls(struct sd *sd)
-{
-       struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
-
-       v4l2_ctrl_handler_init(hdl, 2);
-       v4l2_ctrl_new_std(hdl, &hdcs_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 0, 0xff, 1, HDCS_DEFAULT_EXPOSURE);
-       v4l2_ctrl_new_std(hdl, &hdcs_ctrl_ops,
-                       V4L2_CID_GAIN, 0, 0xff, 1, HDCS_DEFAULT_GAIN);
-       return hdl->error;
-}
-
-static int hdcs_probe_1x00(struct sd *sd)
-{
-       struct hdcs *hdcs;
-       u16 sensor;
-       int ret;
-
-       ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
-       if (ret < 0 || sensor != 0x08)
-               return -ENODEV;
-
-       pr_info("HDCS-1000/1100 sensor detected\n");
-
-       sd->gspca_dev.cam.cam_mode = hdcs1x00_mode;
-       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1x00_mode);
-
-       hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
-       if (!hdcs)
-               return -ENOMEM;
-
-       hdcs->array.left = 8;
-       hdcs->array.top = 8;
-       hdcs->array.width = HDCS_1X00_DEF_WIDTH;
-       hdcs->array.height = HDCS_1X00_DEF_HEIGHT;
-       hdcs->array.border = 4;
-
-       hdcs->exp.cto = 4;
-       hdcs->exp.cpo = 2;
-       hdcs->exp.rs = 186;
-       hdcs->exp.er = 100;
-
-       /*
-        * Frame rate on HDCS-1000 with STV600 depends on PSMP:
-        *  4 = doesn't work at all
-        *  5 = 7.8 fps,
-        *  6 = 6.9 fps,
-        *  8 = 6.3 fps,
-        * 10 = 5.5 fps,
-        * 15 = 4.4 fps,
-        * 31 = 2.8 fps
-        *
-        * Frame rate on HDCS-1000 with STV602 depends on PSMP:
-        * 15 = doesn't work at all
-        * 18 = doesn't work at all
-        * 19 = 7.3 fps
-        * 20 = 7.4 fps
-        * 21 = 7.4 fps
-        * 22 = 7.4 fps
-        * 24 = 6.3 fps
-        * 30 = 5.4 fps
-        */
-       hdcs->psmp = (sd->bridge == BRIDGE_STV602) ? 20 : 5;
-
-       sd->sensor_priv = hdcs;
-
-       return 0;
-}
-
-static int hdcs_probe_1020(struct sd *sd)
-{
-       struct hdcs *hdcs;
-       u16 sensor;
-       int ret;
-
-       ret = stv06xx_read_sensor(sd, HDCS_IDENT, &sensor);
-       if (ret < 0 || sensor != 0x10)
-               return -ENODEV;
-
-       pr_info("HDCS-1020 sensor detected\n");
-
-       sd->gspca_dev.cam.cam_mode = hdcs1020_mode;
-       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(hdcs1020_mode);
-
-       hdcs = kmalloc(sizeof(struct hdcs), GFP_KERNEL);
-       if (!hdcs)
-               return -ENOMEM;
-
-       /*
-        * From Andrey's test image: looks like HDCS-1020 upper-left
-        * visible pixel is at 24,8 (y maybe even smaller?) and lower-right
-        * visible pixel at 375,299 (x maybe even larger?)
-        */
-       hdcs->array.left = 24;
-       hdcs->array.top  = 4;
-       hdcs->array.width = HDCS_1020_DEF_WIDTH;
-       hdcs->array.height = 304;
-       hdcs->array.border = 4;
-
-       hdcs->psmp = 6;
-
-       hdcs->exp.cto = 3;
-       hdcs->exp.cpo = 3;
-       hdcs->exp.rs = 155;
-       hdcs->exp.er = 96;
-
-       sd->sensor_priv = hdcs;
-
-       return 0;
-}
-
-static int hdcs_start(struct sd *sd)
-{
-       PDEBUG(D_STREAM, "Starting stream");
-
-       return hdcs_set_state(sd, HDCS_STATE_RUN);
-}
-
-static int hdcs_stop(struct sd *sd)
-{
-       PDEBUG(D_STREAM, "Halting stream");
-
-       return hdcs_set_state(sd, HDCS_STATE_SLEEP);
-}
-
-static int hdcs_init(struct sd *sd)
-{
-       struct hdcs *hdcs = sd->sensor_priv;
-       int i, err = 0;
-
-       /* Set the STV0602AA in STV0600 emulation mode */
-       if (sd->bridge == BRIDGE_STV602)
-               stv06xx_write_bridge(sd, STV_STV0600_EMULATION, 1);
-
-       /* Execute the bridge init */
-       for (i = 0; i < ARRAY_SIZE(stv_bridge_init) && !err; i++) {
-               err = stv06xx_write_bridge(sd, stv_bridge_init[i][0],
-                                          stv_bridge_init[i][1]);
-       }
-       if (err < 0)
-               return err;
-
-       /* sensor soft reset */
-       hdcs_reset(sd);
-
-       /* Execute the sensor init */
-       for (i = 0; i < ARRAY_SIZE(stv_sensor_init) && !err; i++) {
-               err = stv06xx_write_sensor(sd, stv_sensor_init[i][0],
-                                            stv_sensor_init[i][1]);
-       }
-       if (err < 0)
-               return err;
-
-       /* Enable continuous frame capture, bit 2: stop when frame complete */
-       err = stv06xx_write_sensor(sd, HDCS_REG_CONFIG(sd), BIT(3));
-       if (err < 0)
-               return err;
-
-       /* Set PGA sample duration
-       (was 0x7E for the STV602, but caused slow framerate with HDCS-1020) */
-       if (IS_1020(sd))
-               err = stv06xx_write_sensor(sd, HDCS_TCTRL,
-                               (HDCS_ADC_START_SIG_DUR << 6) | hdcs->psmp);
-       else
-               err = stv06xx_write_sensor(sd, HDCS_TCTRL,
-                               (HDCS_ADC_START_SIG_DUR << 5) | hdcs->psmp);
-       if (err < 0)
-               return err;
-
-       return hdcs_set_size(sd, hdcs->array.width, hdcs->array.height);
-}
-
-static int hdcs_dump(struct sd *sd)
-{
-       u16 reg, val;
-
-       pr_info("Dumping sensor registers:\n");
-
-       for (reg = HDCS_IDENT; reg <= HDCS_ROWEXPH; reg++) {
-               stv06xx_read_sensor(sd, reg, &val);
-               pr_info("reg 0x%02x = 0x%02x\n", reg, val);
-       }
-       return 0;
-}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
deleted file mode 100644 (file)
index 1ba9158..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
- *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
- * Copyright (c) 2002, 2003 Tuukka Toivonen
- * Copyright (c) 2008 Erik Andrén
- * Copyright (c) 2008 Chia-I Wu
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * P/N 861037:      Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
- * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
- * P/N 861075-0040: Sensor HDCS1000        ASIC
- * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
- * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
- */
-
-#ifndef STV06XX_HDCS_H_
-#define STV06XX_HDCS_H_
-
-#include "stv06xx_sensor.h"
-
-#define HDCS_REG_CONFIG(sd)    (IS_1020(sd) ? HDCS20_CONFIG : HDCS00_CONFIG)
-#define HDCS_REG_CONTROL(sd)   (IS_1020(sd) ? HDCS20_CONTROL : HDCS00_CONTROL)
-
-#define HDCS_1X00_DEF_WIDTH    360
-#define HDCS_1X00_DEF_HEIGHT   296
-
-#define HDCS_1020_DEF_WIDTH    352
-#define HDCS_1020_DEF_HEIGHT   292
-
-#define HDCS_1020_BOTTOM_Y_SKIP        4
-
-#define HDCS_CLK_FREQ_MHZ      25
-
-#define HDCS_ADC_START_SIG_DUR 3
-
-/* LSB bit of I2C or register address signifies write (0) or read (1) */
-/* I2C Registers common for both HDCS-1000/1100 and HDCS-1020 */
-/* Identifications Register */
-#define HDCS_IDENT             (0x00 << 1)
-/* Status Register */
-#define HDCS_STATUS            (0x01 << 1)
-/* Interrupt Mask Register */
-#define HDCS_IMASK             (0x02 << 1)
-/* Pad Control Register */
-#define HDCS_PCTRL             (0x03 << 1)
-/* Pad Drive Control Register */
-#define HDCS_PDRV              (0x04 << 1)
-/* Interface Control Register */
-#define HDCS_ICTRL             (0x05 << 1)
-/* Interface Timing Register */
-#define HDCS_ITMG              (0x06 << 1)
-/* Baud Fraction Register */
-#define HDCS_BFRAC             (0x07 << 1)
-/* Baud Rate Register */
-#define HDCS_BRATE             (0x08 << 1)
-/* ADC Control Register */
-#define HDCS_ADCCTRL           (0x09 << 1)
-/* First Window Row Register */
-#define HDCS_FWROW             (0x0a << 1)
-/* First Window Column Register */
-#define HDCS_FWCOL             (0x0b << 1)
-/* Last Window Row Register */
-#define HDCS_LWROW             (0x0c << 1)
-/* Last Window Column Register */
-#define HDCS_LWCOL             (0x0d << 1)
-/* Timing Control Register */
-#define HDCS_TCTRL             (0x0e << 1)
-/* PGA Gain Register: Even Row, Even Column */
-#define HDCS_ERECPGA           (0x0f << 1)
-/* PGA Gain Register: Even Row, Odd Column */
-#define HDCS_EROCPGA           (0x10 << 1)
-/* PGA Gain Register: Odd Row, Even Column */
-#define HDCS_ORECPGA           (0x11 << 1)
-/* PGA Gain Register: Odd Row, Odd Column */
-#define HDCS_OROCPGA           (0x12 << 1)
-/* Row Exposure Low Register */
-#define HDCS_ROWEXPL           (0x13 << 1)
-/* Row Exposure High Register */
-#define HDCS_ROWEXPH           (0x14 << 1)
-
-/* I2C Registers only for HDCS-1000/1100 */
-/* Sub-Row Exposure Low Register */
-#define HDCS00_SROWEXPL                (0x15 << 1)
-/* Sub-Row Exposure High Register */
-#define HDCS00_SROWEXPH                (0x16 << 1)
-/* Configuration Register */
-#define HDCS00_CONFIG          (0x17 << 1)
-/* Control Register */
-#define HDCS00_CONTROL         (0x18 << 1)
-
-/* I2C Registers only for HDCS-1020 */
-/* Sub-Row Exposure Register */
-#define HDCS20_SROWEXP         (0x15 << 1)
-/* Error Control Register */
-#define HDCS20_ERROR           (0x16 << 1)
-/* Interface Timing 2 Register */
-#define HDCS20_ITMG2           (0x17 << 1)
-/* Interface Control 2 Register        */
-#define HDCS20_ICTRL2          (0x18 << 1)
-/* Horizontal Blank Register */
-#define HDCS20_HBLANK          (0x19 << 1)
-/* Vertical Blank Register */
-#define HDCS20_VBLANK          (0x1a << 1)
-/* Configuration Register */
-#define HDCS20_CONFIG          (0x1b << 1)
-/* Control Register */
-#define HDCS20_CONTROL         (0x1c << 1)
-
-#define HDCS_RUN_ENABLE                (1 << 2)
-#define HDCS_SLEEP_MODE                (1 << 1)
-
-#define HDCS_DEFAULT_EXPOSURE  48
-#define HDCS_DEFAULT_GAIN      50
-
-static int hdcs_probe_1x00(struct sd *sd);
-static int hdcs_probe_1020(struct sd *sd);
-static int hdcs_start(struct sd *sd);
-static int hdcs_init(struct sd *sd);
-static int hdcs_init_controls(struct sd *sd);
-static int hdcs_stop(struct sd *sd);
-static int hdcs_dump(struct sd *sd);
-
-static int hdcs_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-static int hdcs_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-
-const struct stv06xx_sensor stv06xx_sensor_hdcs1x00 = {
-       .name = "HP HDCS-1000/1100",
-       .i2c_flush = 0,
-       .i2c_addr = (0x55 << 1),
-       .i2c_len = 1,
-
-       /* FIXME (see if we can lower min_packet_size, needs testing, and also
-          adjusting framerate when the bandwidth gets lower) */
-       .min_packet_size = { 847 },
-       .max_packet_size = { 847 },
-
-       .init = hdcs_init,
-       .init_controls = hdcs_init_controls,
-       .probe = hdcs_probe_1x00,
-       .start = hdcs_start,
-       .stop = hdcs_stop,
-       .dump = hdcs_dump,
-};
-
-const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = {
-       .name = "HDCS-1020",
-       .i2c_flush = 0,
-       .i2c_addr = (0x55 << 1),
-       .i2c_len = 1,
-
-       /* FIXME (see if we can lower min_packet_size, needs testing, and also
-          adjusting framerate when the bandwidthm gets lower) */
-       .min_packet_size = { 847 },
-       .max_packet_size = { 847 },
-
-       .init = hdcs_init,
-       .init_controls = hdcs_init_controls,
-       .probe = hdcs_probe_1020,
-       .start = hdcs_start,
-       .stop = hdcs_stop,
-       .dump = hdcs_dump,
-};
-
-static const u16 stv_bridge_init[][2] = {
-       {STV_ISO_ENABLE, 0},
-       {STV_REG23, 0},
-       {STV_REG00, 0x1d},
-       {STV_REG01, 0xb5},
-       {STV_REG02, 0xa8},
-       {STV_REG03, 0x95},
-       {STV_REG04, 0x07},
-
-       {STV_SCAN_RATE, 0x20},
-       {STV_Y_CTRL, 0x01},
-       {STV_X_CTRL, 0x0a}
-};
-
-static const u8 stv_sensor_init[][2] = {
-       /* Clear status (writing 1 will clear the corresponding status bit) */
-       {HDCS_STATUS, BIT(6) | BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
-       /* Disable all interrupts */
-       {HDCS_IMASK, 0x00},
-       {HDCS_PCTRL, BIT(6) | BIT(5) | BIT(1) | BIT(0)},
-       {HDCS_PDRV,  0x00},
-       {HDCS_ICTRL, BIT(5)},
-       {HDCS_ITMG,  BIT(4) | BIT(1)},
-       /* ADC output resolution to 10 bits */
-       {HDCS_ADCCTRL, 10}
-};
-
-#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
deleted file mode 100644 (file)
index cdfc3d0..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
- *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
- * Copyright (c) 2002, 2003 Tuukka Toivonen
- * Copyright (c) 2008 Erik Andrén
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * P/N 861037:      Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
- * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
- * P/N 861075-0040: Sensor HDCS1000        ASIC
- * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
- * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
- */
-
-/*
- * The spec file for the PB-0100 suggests the following for best quality
- * images after the sensor has been reset :
- *
- * PB_ADCGAINL      = R60 = 0x03 (3 dec)      : sets low reference of ADC
-                                               to produce good black level
- * PB_PREADCTRL     = R32 = 0x1400 (5120 dec) : Enables global gain changes
-                                               through R53
- * PB_ADCMINGAIN    = R52 = 0x10 (16 dec)     : Sets the minimum gain for
-                                               auto-exposure
- * PB_ADCGLOBALGAIN = R53 = 0x10 (16 dec)     : Sets the global gain
- * PB_EXPGAIN       = R14 = 0x11 (17 dec)     : Sets the auto-exposure value
- * PB_UPDATEINT     = R23 = 0x02 (2 dec)      : Sets the speed on
-                                               auto-exposure routine
- * PB_CFILLIN       = R5  = 0x0E (14 dec)     : Sets the frame rate
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "stv06xx_pb0100.h"
-
-struct pb0100_ctrls {
-       struct { /* one big happy control cluster... */
-               struct v4l2_ctrl *autogain;
-               struct v4l2_ctrl *gain;
-               struct v4l2_ctrl *exposure;
-               struct v4l2_ctrl *red;
-               struct v4l2_ctrl *blue;
-               struct v4l2_ctrl *natural;
-       };
-       struct v4l2_ctrl *target;
-};
-
-static struct v4l2_pix_format pb0100_mode[] = {
-/* low res / subsample modes disabled as they are only half res horizontal,
-   halving the vertical resolution does not seem to work */
-       {
-               320,
-               240,
-               V4L2_PIX_FMT_SGRBG8,
-               V4L2_FIELD_NONE,
-               .sizeimage = 320 * 240,
-               .bytesperline = 320,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = PB0100_CROP_TO_VGA
-       },
-       {
-               352,
-               288,
-               V4L2_PIX_FMT_SGRBG8,
-               V4L2_FIELD_NONE,
-               .sizeimage = 352 * 288,
-               .bytesperline = 352,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0
-       }
-};
-
-static int pb0100_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;
-       struct pb0100_ctrls *ctrls = sd->sensor_priv;
-       int err = -EINVAL;
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUTOGAIN:
-               err = pb0100_set_autogain(gspca_dev, ctrl->val);
-               if (err)
-                       break;
-               if (ctrl->val)
-                       break;
-               err = pb0100_set_gain(gspca_dev, ctrls->gain->val);
-               if (err)
-                       break;
-               err = pb0100_set_exposure(gspca_dev, ctrls->exposure->val);
-               break;
-       case V4L2_CTRL_CLASS_USER + 0x1001:
-               err = pb0100_set_autogain_target(gspca_dev, ctrl->val);
-               break;
-       }
-       return err;
-}
-
-static const struct v4l2_ctrl_ops pb0100_ctrl_ops = {
-       .s_ctrl = pb0100_s_ctrl,
-};
-
-static int pb0100_init_controls(struct sd *sd)
-{
-       struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
-       struct pb0100_ctrls *ctrls;
-       static const struct v4l2_ctrl_config autogain_target = {
-               .ops = &pb0100_ctrl_ops,
-               .id = V4L2_CTRL_CLASS_USER + 0x1000,
-               .type = V4L2_CTRL_TYPE_INTEGER,
-               .name = "Automatic Gain Target",
-               .max = 255,
-               .step = 1,
-               .def = 128,
-       };
-       static const struct v4l2_ctrl_config natural_light = {
-               .ops = &pb0100_ctrl_ops,
-               .id = V4L2_CTRL_CLASS_USER + 0x1001,
-               .type = V4L2_CTRL_TYPE_BOOLEAN,
-               .name = "Natural Light Source",
-               .max = 1,
-               .step = 1,
-               .def = 1,
-       };
-
-       ctrls = kzalloc(sizeof(*ctrls), GFP_KERNEL);
-       if (!ctrls)
-               return -ENOMEM;
-
-       v4l2_ctrl_handler_init(hdl, 6);
-       ctrls->autogain = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
-                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-       ctrls->exposure = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 0, 511, 1, 12);
-       ctrls->gain = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
-                       V4L2_CID_GAIN, 0, 255, 1, 128);
-       ctrls->red = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
-                       V4L2_CID_RED_BALANCE, -255, 255, 1, 0);
-       ctrls->blue = v4l2_ctrl_new_std(hdl, &pb0100_ctrl_ops,
-                       V4L2_CID_BLUE_BALANCE, -255, 255, 1, 0);
-       ctrls->natural = v4l2_ctrl_new_custom(hdl, &natural_light, NULL);
-       ctrls->target = v4l2_ctrl_new_custom(hdl, &autogain_target, NULL);
-       if (hdl->error) {
-               kfree(ctrls);
-               return hdl->error;
-       }
-       sd->sensor_priv = ctrls;
-       v4l2_ctrl_auto_cluster(5, &ctrls->autogain, 0, false);
-       return 0;
-}
-
-static int pb0100_probe(struct sd *sd)
-{
-       u16 sensor;
-       int err;
-
-       err = stv06xx_read_sensor(sd, PB_IDENT, &sensor);
-
-       if (err < 0)
-               return -ENODEV;
-       if ((sensor >> 8) != 0x64)
-               return -ENODEV;
-
-       pr_info("Photobit pb0100 sensor detected\n");
-
-       sd->gspca_dev.cam.cam_mode = pb0100_mode;
-       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(pb0100_mode);
-
-       return 0;
-}
-
-static int pb0100_start(struct sd *sd)
-{
-       int err, packet_size, max_packet_size;
-       struct usb_host_interface *alt;
-       struct usb_interface *intf;
-       struct cam *cam = &sd->gspca_dev.cam;
-       u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
-
-       intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
-       alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
-       if (!alt)
-               return -ENODEV;
-       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
-
-       /* If we don't have enough bandwidth use a lower framerate */
-       max_packet_size = sd->sensor->max_packet_size[sd->gspca_dev.curr_mode];
-       if (packet_size < max_packet_size)
-               stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
-       else
-               stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(5)|BIT(3)|BIT(1));
-
-       /* Setup sensor window */
-       if (mode & PB0100_CROP_TO_VGA) {
-               stv06xx_write_sensor(sd, PB_RSTART, 30);
-               stv06xx_write_sensor(sd, PB_CSTART, 20);
-               stv06xx_write_sensor(sd, PB_RWSIZE, 240 - 1);
-               stv06xx_write_sensor(sd, PB_CWSIZE, 320 - 1);
-       } else {
-               stv06xx_write_sensor(sd, PB_RSTART, 8);
-               stv06xx_write_sensor(sd, PB_CSTART, 4);
-               stv06xx_write_sensor(sd, PB_RWSIZE, 288 - 1);
-               stv06xx_write_sensor(sd, PB_CWSIZE, 352 - 1);
-       }
-
-       if (mode & PB0100_SUBSAMPLE) {
-               stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02); /* Wrong, FIXME */
-               stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
-
-               stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
-       } else {
-               stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
-               stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
-               /* larger -> slower */
-               stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x20);
-       }
-
-       err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3)|BIT(1));
-       PDEBUG(D_STREAM, "Started stream, status: %d", err);
-
-       return (err < 0) ? err : 0;
-}
-
-static int pb0100_stop(struct sd *sd)
-{
-       int err;
-
-       err = stv06xx_write_sensor(sd, PB_ABORTFRAME, 1);
-
-       if (err < 0)
-               goto out;
-
-       /* Set bit 1 to zero */
-       err = stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3));
-
-       PDEBUG(D_STREAM, "Halting stream");
-out:
-       return (err < 0) ? err : 0;
-}
-
-/* FIXME: Sort the init commands out and put them into tables,
-         this is only for getting the camera to work */
-/* FIXME: No error handling for now,
-         add this once the init has been converted to proper tables */
-static int pb0100_init(struct sd *sd)
-{
-       stv06xx_write_bridge(sd, STV_REG00, 1);
-       stv06xx_write_bridge(sd, STV_SCAN_RATE, 0);
-
-       /* Reset sensor */
-       stv06xx_write_sensor(sd, PB_RESET, 1);
-       stv06xx_write_sensor(sd, PB_RESET, 0);
-
-       /* Disable chip */
-       stv06xx_write_sensor(sd, PB_CONTROL, BIT(5)|BIT(3));
-
-       /* Gain stuff...*/
-       stv06xx_write_sensor(sd, PB_PREADCTRL, BIT(12)|BIT(10)|BIT(6));
-       stv06xx_write_sensor(sd, PB_ADCGLOBALGAIN, 12);
-
-       /* Set up auto-exposure */
-       /* ADC VREF_HI new setting for a transition
-         from the Expose1 to the Expose2 setting */
-       stv06xx_write_sensor(sd, PB_R28, 12);
-       /* gain max for autoexposure */
-       stv06xx_write_sensor(sd, PB_ADCMAXGAIN, 180);
-       /* gain min for autoexposure  */
-       stv06xx_write_sensor(sd, PB_ADCMINGAIN, 12);
-       /* Maximum frame integration time (programmed into R8)
-          allowed for auto-exposure routine */
-       stv06xx_write_sensor(sd, PB_R54, 3);
-       /* Minimum frame integration time (programmed into R8)
-          allowed for auto-exposure routine */
-       stv06xx_write_sensor(sd, PB_R55, 0);
-       stv06xx_write_sensor(sd, PB_UPDATEINT, 1);
-       /* R15  Expose0 (maximum that auto-exposure may use) */
-       stv06xx_write_sensor(sd, PB_R15, 800);
-       /* R17  Expose2 (minimum that auto-exposure may use) */
-       stv06xx_write_sensor(sd, PB_R17, 10);
-
-       stv06xx_write_sensor(sd, PB_EXPGAIN, 0);
-
-       /* 0x14 */
-       stv06xx_write_sensor(sd, PB_VOFFSET, 0);
-       /* 0x0D */
-       stv06xx_write_sensor(sd, PB_ADCGAINH, 11);
-       /* Set black level (important!) */
-       stv06xx_write_sensor(sd, PB_ADCGAINL, 0);
-
-       /* ??? */
-       stv06xx_write_bridge(sd, STV_REG00, 0x11);
-       stv06xx_write_bridge(sd, STV_REG03, 0x45);
-       stv06xx_write_bridge(sd, STV_REG04, 0x07);
-
-       /* Scan/timing for the sensor */
-       stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
-       stv06xx_write_sensor(sd, PB_CFILLIN, 14);
-       stv06xx_write_sensor(sd, PB_VBL, 0);
-       stv06xx_write_sensor(sd, PB_FINTTIME, 0);
-       stv06xx_write_sensor(sd, PB_RINTTIME, 123);
-
-       stv06xx_write_bridge(sd, STV_REG01, 0xc2);
-       stv06xx_write_bridge(sd, STV_REG02, 0xb0);
-       return 0;
-}
-
-static int pb0100_dump(struct sd *sd)
-{
-       return 0;
-}
-
-static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct pb0100_ctrls *ctrls = sd->sensor_priv;
-
-       err = stv06xx_write_sensor(sd, PB_G1GAIN, val);
-       if (!err)
-               err = stv06xx_write_sensor(sd, PB_G2GAIN, val);
-       PDEBUG(D_V4L2, "Set green gain to %d, status: %d", val, err);
-
-       if (!err)
-               err = pb0100_set_red_balance(gspca_dev, ctrls->red->val);
-       if (!err)
-               err = pb0100_set_blue_balance(gspca_dev, ctrls->blue->val);
-
-       return err;
-}
-
-static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct pb0100_ctrls *ctrls = sd->sensor_priv;
-
-       val += ctrls->gain->val;
-       if (val < 0)
-               val = 0;
-       else if (val > 255)
-               val = 255;
-
-       err = stv06xx_write_sensor(sd, PB_RGAIN, val);
-       PDEBUG(D_V4L2, "Set red gain to %d, status: %d", val, err);
-
-       return err;
-}
-
-static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct pb0100_ctrls *ctrls = sd->sensor_priv;
-
-       val += ctrls->gain->val;
-       if (val < 0)
-               val = 0;
-       else if (val > 255)
-               val = 255;
-
-       err = stv06xx_write_sensor(sd, PB_BGAIN, val);
-       PDEBUG(D_V4L2, "Set blue gain to %d, status: %d", val, err);
-
-       return err;
-}
-
-static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int err;
-
-       err = stv06xx_write_sensor(sd, PB_RINTTIME, val);
-       PDEBUG(D_V4L2, "Set exposure to %d, status: %d", val, err);
-
-       return err;
-}
-
-static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct pb0100_ctrls *ctrls = sd->sensor_priv;
-
-       if (val) {
-               if (ctrls->natural->val)
-                       val = BIT(6)|BIT(4)|BIT(0);
-               else
-                       val = BIT(4)|BIT(0);
-       } else
-               val = 0;
-
-       err = stv06xx_write_sensor(sd, PB_EXPGAIN, val);
-       PDEBUG(D_V4L2, "Set autogain to %d (natural: %d), status: %d",
-              val, ctrls->natural->val, err);
-
-       return err;
-}
-
-static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err, totalpixels, brightpixels, darkpixels;
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* Number of pixels counted by the sensor when subsampling the pixels.
-        * Slightly larger than the real value to avoid oscillation */
-       totalpixels = gspca_dev->width * gspca_dev->height;
-       totalpixels = totalpixels/(8*8) + totalpixels/(64*64);
-
-       brightpixels = (totalpixels * val) >> 8;
-       darkpixels   = totalpixels - brightpixels;
-       err = stv06xx_write_sensor(sd, PB_R21, brightpixels);
-       if (!err)
-               err = stv06xx_write_sensor(sd, PB_R22, darkpixels);
-
-       PDEBUG(D_V4L2, "Set autogain target to %d, status: %d", val, err);
-
-       return err;
-}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
deleted file mode 100644 (file)
index 5071e53..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
- *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
- * Copyright (c) 2002, 2003 Tuukka Toivonen
- * Copyright (c) 2008 Erik Andrén
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * P/N 861037:      Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
- * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
- * P/N 861075-0040: Sensor HDCS1000        ASIC
- * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
- * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
- */
-
-#ifndef STV06XX_PB0100_H_
-#define STV06XX_PB0100_H_
-
-#include "stv06xx_sensor.h"
-
-/* mode priv field flags */
-#define PB0100_CROP_TO_VGA     0x01
-#define PB0100_SUBSAMPLE       0x02
-
-/* I2C Registers */
-#define PB_IDENT               0x00    /* Chip Version */
-#define PB_RSTART              0x01    /* Row Window Start */
-#define PB_CSTART              0x02    /* Column Window Start */
-#define PB_RWSIZE              0x03    /* Row Window Size */
-#define PB_CWSIZE              0x04    /* Column  Window Size */
-#define PB_CFILLIN             0x05    /* Column Fill-In */
-#define PB_VBL                 0x06    /* Vertical Blank Count */
-#define PB_CONTROL             0x07    /* Control Mode */
-#define PB_FINTTIME            0x08    /* Integration Time/Frame Unit Count */
-#define PB_RINTTIME            0x09    /* Integration Time/Row Unit Count */
-#define PB_ROWSPEED            0x0a    /* Row Speed Control */
-#define PB_ABORTFRAME          0x0b    /* Abort Frame */
-#define PB_R12                 0x0c    /* Reserved */
-#define PB_RESET               0x0d    /* Reset */
-#define PB_EXPGAIN             0x0e    /* Exposure Gain Command */
-#define PB_R15                 0x0f    /* Expose0 */
-#define PB_R16                 0x10    /* Expose1 */
-#define PB_R17                 0x11    /* Expose2 */
-#define PB_R18                 0x12    /* Low0_DAC */
-#define PB_R19                 0x13    /* Low1_DAC */
-#define PB_R20                 0x14    /* Low2_DAC */
-#define PB_R21                 0x15    /* Threshold11 */
-#define PB_R22                 0x16    /* Threshold0x */
-#define PB_UPDATEINT           0x17    /* Update Interval */
-#define PB_R24                 0x18    /* High_DAC */
-#define PB_R25                 0x19    /* Trans0H */
-#define PB_R26                 0x1a    /* Trans1L */
-#define PB_R27                 0x1b    /* Trans1H */
-#define PB_R28                 0x1c    /* Trans2L */
-#define PB_R29                 0x1d    /* Reserved */
-#define PB_R30                 0x1e    /* Reserved */
-#define PB_R31                 0x1f    /* Wait to Read */
-#define PB_PREADCTRL           0x20    /* Pixel Read Control Mode */
-#define PB_R33                 0x21    /* IREF_VLN */
-#define PB_R34                 0x22    /* IREF_VLP */
-#define PB_R35                 0x23    /* IREF_VLN_INTEG */
-#define PB_R36                 0x24    /* IREF_MASTER */
-#define PB_R37                 0x25    /* IDACP */
-#define PB_R38                 0x26    /* IDACN */
-#define PB_R39                 0x27    /* DAC_Control_Reg */
-#define PB_R40                 0x28    /* VCL */
-#define PB_R41                 0x29    /* IREF_VLN_ADCIN */
-#define PB_R42                 0x2a    /* Reserved */
-#define PB_G1GAIN              0x2b    /* Green 1 Gain */
-#define PB_BGAIN               0x2c    /* Blue Gain */
-#define PB_RGAIN               0x2d    /* Red Gain */
-#define PB_G2GAIN              0x2e    /* Green 2 Gain */
-#define PB_R47                 0x2f    /* Dark Row Address */
-#define PB_R48                 0x30    /* Dark Row Options */
-#define PB_R49                 0x31    /* Reserved */
-#define PB_R50                 0x32    /* Image Test Data */
-#define PB_ADCMAXGAIN          0x33    /* Maximum Gain */
-#define PB_ADCMINGAIN          0x34    /* Minimum Gain */
-#define PB_ADCGLOBALGAIN       0x35    /* Global Gain */
-#define PB_R54                 0x36    /* Maximum Frame */
-#define PB_R55                 0x37    /* Minimum Frame */
-#define PB_R56                 0x38    /* Reserved */
-#define PB_VOFFSET             0x39    /* VOFFSET */
-#define PB_R58                 0x3a    /* Snap-Shot Sequence Trigger */
-#define PB_ADCGAINH            0x3b    /* VREF_HI */
-#define PB_ADCGAINL            0x3c    /* VREF_LO */
-#define PB_R61                 0x3d    /* Reserved */
-#define PB_R62                 0x3e    /* Reserved */
-#define PB_R63                 0x3f    /* Reserved */
-#define PB_R64                 0x40    /* Red/Blue Gain */
-#define PB_R65                 0x41    /* Green 2/Green 1 Gain */
-#define PB_R66                 0x42    /* VREF_HI/LO */
-#define PB_R67                 0x43    /* Integration Time/Row Unit Count */
-#define PB_R240                        0xf0    /* ADC Test */
-#define PB_R241                        0xf1    /* Chip Enable */
-#define PB_R242                        0xf2    /* Reserved */
-
-static int pb0100_probe(struct sd *sd);
-static int pb0100_start(struct sd *sd);
-static int pb0100_init(struct sd *sd);
-static int pb0100_init_controls(struct sd *sd);
-static int pb0100_stop(struct sd *sd);
-static int pb0100_dump(struct sd *sd);
-
-/* V4L2 controls supported by the driver */
-static int pb0100_set_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int pb0100_set_red_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int pb0100_set_blue_balance(struct gspca_dev *gspca_dev, __s32 val);
-static int pb0100_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-static int pb0100_set_autogain(struct gspca_dev *gspca_dev, __s32 val);
-static int pb0100_set_autogain_target(struct gspca_dev *gspca_dev, __s32 val);
-
-const struct stv06xx_sensor stv06xx_sensor_pb0100 = {
-       .name = "PB-0100",
-       .i2c_flush = 1,
-       .i2c_addr = 0xba,
-       .i2c_len = 2,
-
-       .min_packet_size = { 635, 847 },
-       .max_packet_size = { 847, 923 },
-
-       .init = pb0100_init,
-       .init_controls = pb0100_init_controls,
-       .probe = pb0100_probe,
-       .start = pb0100_start,
-       .stop = pb0100_stop,
-       .dump = pb0100_dump,
-};
-
-#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
deleted file mode 100644 (file)
index 3a498c2..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
- *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
- * Copyright (c) 2002, 2003 Tuukka Toivonen
- * Copyright (c) 2008 Erik Andrén
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * P/N 861037:      Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
- * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
- * P/N 861075-0040: Sensor HDCS1000        ASIC
- * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
- * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
- */
-
-#ifndef STV06XX_SENSOR_H_
-#define STV06XX_SENSOR_H_
-
-#include "stv06xx.h"
-
-#define IS_1020(sd)    ((sd)->sensor == &stv06xx_sensor_hdcs1020)
-
-extern const struct stv06xx_sensor stv06xx_sensor_vv6410;
-extern const struct stv06xx_sensor stv06xx_sensor_hdcs1x00;
-extern const struct stv06xx_sensor stv06xx_sensor_hdcs1020;
-extern const struct stv06xx_sensor stv06xx_sensor_pb0100;
-extern const struct stv06xx_sensor stv06xx_sensor_st6422;
-
-struct stv06xx_sensor {
-       /* Defines the name of a sensor */
-       char name[32];
-
-       /* Sensor i2c address */
-       u8 i2c_addr;
-
-       /* Flush value*/
-       u8 i2c_flush;
-
-       /* length of an i2c word */
-       u8 i2c_len;
-
-       /* Isoc packet size (per mode) */
-       int min_packet_size[4];
-       int max_packet_size[4];
-
-       /* Probes if the sensor is connected */
-       int (*probe)(struct sd *sd);
-
-       /* Performs a initialization sequence */
-       int (*init)(struct sd *sd);
-
-       /* Initializes the controls */
-       int (*init_controls)(struct sd *sd);
-
-       /* Reads a sensor register */
-       int (*read_sensor)(struct sd *sd, const u8 address,
-             u8 *i2c_data, const u8 len);
-
-       /* Writes to a sensor register */
-       int (*write_sensor)(struct sd *sd, const u8 address,
-             u8 *i2c_data, const u8 len);
-
-       /* Instructs the sensor to start streaming */
-       int (*start)(struct sd *sd);
-
-       /* Instructs the sensor to stop streaming */
-       int (*stop)(struct sd *sd);
-
-       /* Instructs the sensor to dump all its contents */
-       int (*dump)(struct sd *sd);
-};
-
-#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
deleted file mode 100644 (file)
index 8a57990..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Support for the sensor part which is integrated (I think) into the
- * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
- * but instead direct bridge writes.
- *
- * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
- *
- * Strongly based on qc-usb-messenger, which is:
- * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
- *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
- * Copyright (c) 2002, 2003 Tuukka Toivonen
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "stv06xx_st6422.h"
-
-static struct v4l2_pix_format st6422_mode[] = {
-       /* Note we actually get 124 lines of data, of which we skip the 4st
-          4 as they are garbage */
-       {
-               162,
-               120,
-               V4L2_PIX_FMT_SGRBG8,
-               V4L2_FIELD_NONE,
-               .sizeimage = 162 * 120,
-               .bytesperline = 162,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1
-       },
-       /* Note we actually get 248 lines of data, of which we skip the 4st
-          4 as they are garbage, and we tell the app it only gets the
-          first 240 of the 244 lines it actually gets, so that it ignores
-          the last 4. */
-       {
-               324,
-               240,
-               V4L2_PIX_FMT_SGRBG8,
-               V4L2_FIELD_NONE,
-               .sizeimage = 324 * 244,
-               .bytesperline = 324,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0
-       },
-};
-
-/* V4L2 controls supported by the driver */
-static int setbrightness(struct sd *sd, s32 val);
-static int setcontrast(struct sd *sd, s32 val);
-static int setgain(struct sd *sd, u8 gain);
-static int setexposure(struct sd *sd, s16 expo);
-
-static int st6422_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;
-       int err = -EINVAL;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               err = setbrightness(sd, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               err = setcontrast(sd, ctrl->val);
-               break;
-       case V4L2_CID_GAIN:
-               err = setgain(sd, ctrl->val);
-               break;
-       case V4L2_CID_EXPOSURE:
-               err = setexposure(sd, ctrl->val);
-               break;
-       }
-
-       /* commit settings */
-       if (err >= 0)
-               err = stv06xx_write_bridge(sd, 0x143f, 0x01);
-       sd->gspca_dev.usb_err = err;
-       return err;
-}
-
-static const struct v4l2_ctrl_ops st6422_ctrl_ops = {
-       .s_ctrl = st6422_s_ctrl,
-};
-
-static int st6422_init_controls(struct sd *sd)
-{
-       struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
-
-       v4l2_ctrl_handler_init(hdl, 4);
-       v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 31, 1, 3);
-       v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 15, 1, 11);
-       v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 0, 1023, 1, 256);
-       v4l2_ctrl_new_std(hdl, &st6422_ctrl_ops,
-                       V4L2_CID_GAIN, 0, 255, 1, 64);
-
-       return hdl->error;
-}
-
-static int st6422_probe(struct sd *sd)
-{
-       if (sd->bridge != BRIDGE_ST6422)
-               return -ENODEV;
-
-       pr_info("st6422 sensor detected\n");
-
-       sd->gspca_dev.cam.cam_mode = st6422_mode;
-       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
-       return 0;
-}
-
-static int st6422_init(struct sd *sd)
-{
-       int err = 0, i;
-
-       const u16 st6422_bridge_init[][2] = {
-               { STV_ISO_ENABLE, 0x00 }, /* disable capture */
-               { 0x1436, 0x00 },
-               { 0x1432, 0x03 },       /* 0x00-0x1F brightness */
-               { 0x143a, 0xf9 },       /* 0x00-0x0F contrast */
-               { 0x0509, 0x38 },       /* R */
-               { 0x050a, 0x38 },       /* G */
-               { 0x050b, 0x38 },       /* B */
-               { 0x050c, 0x2a },
-               { 0x050d, 0x01 },
-
-
-               { 0x1431, 0x00 },       /* 0x00-0x07 ??? */
-               { 0x1433, 0x34 },       /* 160x120, 0x00-0x01 night filter */
-               { 0x1438, 0x18 },       /* 640x480 */
-/* 18 bayes */
-/* 10 compressed? */
-
-               { 0x1439, 0x00 },
-/* anti-noise?  0xa2 gives a perfect image */
-
-               { 0x143b, 0x05 },
-               { 0x143c, 0x00 },       /* 0x00-0x01 - ??? */
-
-
-/* shutter time 0x0000-0x03FF */
-/* low value  give good picures on moving objects (but requires much light) */
-/* high value gives good picures in darkness (but tends to be overexposed) */
-               { 0x143e, 0x01 },
-               { 0x143d, 0x00 },
-
-               { 0x1442, 0xe2 },
-/* write: 1x1x xxxx */
-/* read:  1x1x xxxx */
-/*        bit 5 == button pressed and hold if 0 */
-/* write 0xe2,0xea */
-
-/* 0x144a */
-/* 0x00 init */
-/* bit 7 == button has been pressed, but not handled */
-
-/* interrupt */
-/* if(urb->iso_frame_desc[i].status == 0x80) { */
-/* if(urb->iso_frame_desc[i].status == 0x88) { */
-
-               { 0x1500, 0xd0 },
-               { 0x1500, 0xd0 },
-               { 0x1500, 0x50 },       /* 0x00 - 0xFF  0x80 == compr ? */
-
-               { 0x1501, 0xaf },
-/* high val-> light area gets darker */
-/* low val -> light area gets lighter */
-               { 0x1502, 0xc2 },
-/* high val-> light area gets darker */
-/* low val -> light area gets lighter */
-               { 0x1503, 0x45 },
-/* high val-> light area gets darker */
-/* low val -> light area gets lighter */
-               { 0x1505, 0x02 },
-/* 2  : 324x248  80352 bytes */
-/* 7  : 248x162  40176 bytes */
-/* c+f: 162*124  20088 bytes */
-
-               { 0x150e, 0x8e },
-               { 0x150f, 0x37 },
-               { 0x15c0, 0x00 },
-               { 0x15c3, 0x08 },       /* 0x04/0x14 ... test pictures ??? */
-
-
-               { 0x143f, 0x01 },       /* commit settings */
-
-       };
-
-       for (i = 0; i < ARRAY_SIZE(st6422_bridge_init) && !err; i++) {
-               err = stv06xx_write_bridge(sd, st6422_bridge_init[i][0],
-                                              st6422_bridge_init[i][1]);
-       }
-
-       return err;
-}
-
-static int setbrightness(struct sd *sd, s32 val)
-{
-       /* val goes from 0 -> 31 */
-       return stv06xx_write_bridge(sd, 0x1432, val);
-}
-
-static int setcontrast(struct sd *sd, s32 val)
-{
-       /* Val goes from 0 -> 15 */
-       return stv06xx_write_bridge(sd, 0x143a, val | 0xf0);
-}
-
-static int setgain(struct sd *sd, u8 gain)
-{
-       int err;
-
-       /* Set red, green, blue, gain */
-       err = stv06xx_write_bridge(sd, 0x0509, gain);
-       if (err < 0)
-               return err;
-
-       err = stv06xx_write_bridge(sd, 0x050a, gain);
-       if (err < 0)
-               return err;
-
-       err = stv06xx_write_bridge(sd, 0x050b, gain);
-       if (err < 0)
-               return err;
-
-       /* 2 mystery writes */
-       err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
-       if (err < 0)
-               return err;
-
-       return stv06xx_write_bridge(sd, 0x050d, 0x01);
-}
-
-static int setexposure(struct sd *sd, s16 expo)
-{
-       int err;
-
-       err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff);
-       if (err < 0)
-               return err;
-
-       return stv06xx_write_bridge(sd, 0x143e, expo >> 8);
-}
-
-static int st6422_start(struct sd *sd)
-{
-       int err;
-       struct cam *cam = &sd->gspca_dev.cam;
-
-       if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
-               err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
-       else
-               err = stv06xx_write_bridge(sd, 0x1505, 0x02);
-       if (err < 0)
-               return err;
-
-       /* commit settings */
-       err = stv06xx_write_bridge(sd, 0x143f, 0x01);
-       return (err < 0) ? err : 0;
-}
-
-static int st6422_stop(struct sd *sd)
-{
-       PDEBUG(D_STREAM, "Halting stream");
-
-       return 0;
-}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
deleted file mode 100644 (file)
index 8f20fbf..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Support for the sensor part which is integrated (I think) into the
- * st6422 stv06xx alike bridge, as its integrated there are no i2c writes
- * but instead direct bridge writes.
- *
- * Copyright (c) 2009 Hans de Goede <hdegoede@redhat.com>
- *
- * Strongly based on qc-usb-messenger, which is:
- * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
- *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
- * Copyright (c) 2002, 2003 Tuukka Toivonen
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef STV06XX_ST6422_H_
-#define STV06XX_ST6422_H_
-
-#include "stv06xx_sensor.h"
-
-static int st6422_probe(struct sd *sd);
-static int st6422_start(struct sd *sd);
-static int st6422_init(struct sd *sd);
-static int st6422_init_controls(struct sd *sd);
-static int st6422_stop(struct sd *sd);
-
-const struct stv06xx_sensor stv06xx_sensor_st6422 = {
-       .name = "ST6422",
-       /* No known way to lower framerate in case of less bandwidth */
-       .min_packet_size = { 300, 847 },
-       .max_packet_size = { 300, 847 },
-       .init = st6422_init,
-       .init_controls = st6422_init_controls,
-       .probe = st6422_probe,
-       .start = st6422_start,
-       .stop = st6422_stop,
-};
-
-#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c
deleted file mode 100644 (file)
index 748e142..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
- *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
- * Copyright (c) 2002, 2003 Tuukka Toivonen
- * Copyright (c) 2008 Erik Andrén
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * P/N 861037:      Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
- * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
- * P/N 861075-0040: Sensor HDCS1000        ASIC
- * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
- * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "stv06xx_vv6410.h"
-
-static struct v4l2_pix_format vv6410_mode[] = {
-       {
-               356,
-               292,
-               V4L2_PIX_FMT_SGRBG8,
-               V4L2_FIELD_NONE,
-               .sizeimage = 356 * 292,
-               .bytesperline = 356,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0
-       }
-};
-
-static int vv6410_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct gspca_dev *gspca_dev =
-               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
-       int err = -EINVAL;
-
-       switch (ctrl->id) {
-       case V4L2_CID_HFLIP:
-               err = vv6410_set_hflip(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_VFLIP:
-               err = vv6410_set_vflip(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_GAIN:
-               err = vv6410_set_analog_gain(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_EXPOSURE:
-               err = vv6410_set_exposure(gspca_dev, ctrl->val);
-               break;
-       }
-       return err;
-}
-
-static const struct v4l2_ctrl_ops vv6410_ctrl_ops = {
-       .s_ctrl = vv6410_s_ctrl,
-};
-
-static int vv6410_probe(struct sd *sd)
-{
-       u16 data;
-       int err;
-
-       err = stv06xx_read_sensor(sd, VV6410_DEVICEH, &data);
-       if (err < 0)
-               return -ENODEV;
-
-       if (data != 0x19)
-               return -ENODEV;
-
-       pr_info("vv6410 sensor detected\n");
-
-       sd->gspca_dev.cam.cam_mode = vv6410_mode;
-       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(vv6410_mode);
-       return 0;
-}
-
-static int vv6410_init_controls(struct sd *sd)
-{
-       struct v4l2_ctrl_handler *hdl = &sd->gspca_dev.ctrl_handler;
-
-       v4l2_ctrl_handler_init(hdl, 4);
-       v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
-                       V4L2_CID_HFLIP, 0, 1, 1, 0);
-       v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
-                       V4L2_CID_VFLIP, 0, 1, 1, 0);
-       v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 0, 32768, 1, 20000);
-       v4l2_ctrl_new_std(hdl, &vv6410_ctrl_ops,
-                       V4L2_CID_GAIN, 0, 15, 1, 10);
-       return hdl->error;
-}
-
-static int vv6410_init(struct sd *sd)
-{
-       int err = 0, i;
-
-       for (i = 0; i < ARRAY_SIZE(stv_bridge_init); i++)
-               stv06xx_write_bridge(sd, stv_bridge_init[i].addr, stv_bridge_init[i].data);
-
-       if (err < 0)
-               return err;
-
-       err = stv06xx_write_sensor_bytes(sd, (u8 *) vv6410_sensor_init,
-                                        ARRAY_SIZE(vv6410_sensor_init));
-       return (err < 0) ? err : 0;
-}
-
-static int vv6410_start(struct sd *sd)
-{
-       int err;
-       struct cam *cam = &sd->gspca_dev.cam;
-       u32 priv = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
-
-       if (priv & VV6410_SUBSAMPLE) {
-               PDEBUG(D_CONF, "Enabling subsampling");
-               stv06xx_write_bridge(sd, STV_Y_CTRL, 0x02);
-               stv06xx_write_bridge(sd, STV_X_CTRL, 0x06);
-
-               stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x10);
-       } else {
-               stv06xx_write_bridge(sd, STV_Y_CTRL, 0x01);
-               stv06xx_write_bridge(sd, STV_X_CTRL, 0x0a);
-               stv06xx_write_bridge(sd, STV_SCAN_RATE, 0x00);
-
-       }
-
-       /* Turn on LED */
-       err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_ON);
-       if (err < 0)
-               return err;
-
-       err = stv06xx_write_sensor(sd, VV6410_SETUP0, 0);
-       if (err < 0)
-               return err;
-
-       PDEBUG(D_STREAM, "Starting stream");
-
-       return 0;
-}
-
-static int vv6410_stop(struct sd *sd)
-{
-       int err;
-
-       /* Turn off LED */
-       err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_OFF);
-       if (err < 0)
-               return err;
-
-       err = stv06xx_write_sensor(sd, VV6410_SETUP0, VV6410_LOW_POWER_MODE);
-       if (err < 0)
-               return err;
-
-       PDEBUG(D_STREAM, "Halting stream");
-
-       return (err < 0) ? err : 0;
-}
-
-static int vv6410_dump(struct sd *sd)
-{
-       u8 i;
-       int err = 0;
-
-       pr_info("Dumping all vv6410 sensor registers\n");
-       for (i = 0; i < 0xff && !err; i++) {
-               u16 data;
-               err = stv06xx_read_sensor(sd, i, &data);
-               pr_info("Register 0x%x contained 0x%x\n", i, data);
-       }
-       return (err < 0) ? err : 0;
-}
-
-static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u16 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
-       if (err < 0)
-               return err;
-
-       if (val)
-               i2c_data |= VV6410_HFLIP;
-       else
-               i2c_data &= ~VV6410_HFLIP;
-
-       PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
-       err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
-
-       return (err < 0) ? err : 0;
-}
-
-static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       u16 i2c_data;
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       err = stv06xx_read_sensor(sd, VV6410_DATAFORMAT, &i2c_data);
-       if (err < 0)
-               return err;
-
-       if (val)
-               i2c_data |= VV6410_VFLIP;
-       else
-               i2c_data &= ~VV6410_VFLIP;
-
-       PDEBUG(D_V4L2, "Set vertical flip to %d", val);
-       err = stv06xx_write_sensor(sd, VV6410_DATAFORMAT, i2c_data);
-
-       return (err < 0) ? err : 0;
-}
-
-static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       PDEBUG(D_V4L2, "Set analog gain to %d", val);
-       err = stv06xx_write_sensor(sd, VV6410_ANALOGGAIN, 0xf0 | (val & 0xf));
-
-       return (err < 0) ? err : 0;
-}
-
-static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
-{
-       int err;
-       struct sd *sd = (struct sd *) gspca_dev;
-       unsigned int fine, coarse;
-
-       val = (val * val >> 14) + val / 4;
-
-       fine = val % VV6410_CIF_LINELENGTH;
-       coarse = min(512, val / VV6410_CIF_LINELENGTH);
-
-       PDEBUG(D_V4L2, "Set coarse exposure to %d, fine expsure to %d",
-              coarse, fine);
-
-       err = stv06xx_write_sensor(sd, VV6410_FINEH, fine >> 8);
-       if (err < 0)
-               goto out;
-
-       err = stv06xx_write_sensor(sd, VV6410_FINEL, fine & 0xff);
-       if (err < 0)
-               goto out;
-
-       err = stv06xx_write_sensor(sd, VV6410_COARSEH, coarse >> 8);
-       if (err < 0)
-               goto out;
-
-       err = stv06xx_write_sensor(sd, VV6410_COARSEL, coarse & 0xff);
-
-out:
-       return err;
-}
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
deleted file mode 100644 (file)
index 53e67b4..0000000
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (c) 2001 Jean-Fredric Clere, Nikolas Zimmermann, Georg Acher
- *                   Mark Cave-Ayland, Carlo E Prelz, Dick Streefland
- * Copyright (c) 2002, 2003 Tuukka Toivonen
- * Copyright (c) 2008 Erik Andrén
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * P/N 861037:      Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0010: Sensor HDCS1000        ASIC STV0600
- * P/N 861050-0020: Sensor Photobit PB100  ASIC STV0600-1 - QuickCam Express
- * P/N 861055:      Sensor ST VV6410       ASIC STV0610   - LEGO cam
- * P/N 861075-0040: Sensor HDCS1000        ASIC
- * P/N 961179-0700: Sensor ST VV6410       ASIC STV0602   - Dexxa WebCam USB
- * P/N 861040-0000: Sensor ST VV6410       ASIC STV0610   - QuickCam Web
- */
-
-#ifndef STV06XX_VV6410_H_
-#define STV06XX_VV6410_H_
-
-#include "stv06xx_sensor.h"
-
-#define VV6410_COLS                    416
-#define VV6410_ROWS                    320
-
-/* Status registers */
-/* Chip identification number including revision indicator */
-#define VV6410_DEVICEH                 0x00
-#define VV6410_DEVICEL                 0x01
-
-/* User can determine whether timed I2C data
-   has been consumed by interrogating flag states */
-#define VV6410_STATUS0                 0x02
-
-/* Current line counter value */
-#define VV6410_LINECOUNTH              0x03
-#define VV6410_LINECOUNTL              0x04
-
-/* End x coordinate of image size */
-#define VV6410_XENDH                   0x05
-#define VV6410_XENDL                   0x06
-
-/* End y coordinate of image size */
-#define VV6410_YENDH                   0x07
-#define VV6410_YENDL                   0x08
-
-/* This is the average pixel value returned from the
-   dark line offset cancellation algorithm */
-#define VV6410_DARKAVGH                        0x09
-#define VV6410_DARKAVGL                        0x0a
-
-/* This is the average pixel value returned from the
-   black line offset cancellation algorithm  */
-#define VV6410_BLACKAVGH               0x0b
-#define VV6410_BLACKAVGL               0x0c
-
-/* Flags to indicate whether the x or y image coordinates have been clipped */
-#define VV6410_STATUS1                 0x0d
-
-/* Setup registers */
-
-/* Low-power/sleep modes & video timing */
-#define VV6410_SETUP0                  0x10
-
-/* Various parameters */
-#define VV6410_SETUP1                  0x11
-
-/* Contains pixel counter reset value used by external sync */
-#define VV6410_SYNCVALUE               0x12
-
-/* Frame grabbing modes (FST, LST and QCK) */
-#define VV6410_FGMODES                 0x14
-
-/* FST and QCK mapping modes. */
-#define VV6410_PINMAPPING              0x15
-
-/* Data resolution */
-#define VV6410_DATAFORMAT              0x16
-
-/* Output coding formats */
-#define VV6410_OPFORMAT                        0x17
-
-/* Various mode select bits */
-#define VV6410_MODESELECT              0x18
-
-/* Exposure registers */
-/* Fine exposure. */
-#define VV6410_FINEH                   0x20
-#define VV6410_FINEL                   0x21
-
-/* Coarse exposure */
-#define VV6410_COARSEH                 0x22
-#define VV6410_COARSEL                 0x23
-
-/* Analog gain setting */
-#define VV6410_ANALOGGAIN              0x24
-
-/* Clock division */
-#define VV6410_CLKDIV                  0x25
-
-/* Dark line offset cancellation value */
-#define VV6410_DARKOFFSETH             0x2c
-#define VV6410_DARKOFFSETL             0x2d
-
-/* Dark line offset cancellation enable */
-#define VV6410_DARKOFFSETSETUP         0x2e
-
-/* Video timing registers */
-/* Line Length (Pixel Clocks) */
-#define VV6410_LINELENGTHH             0x52
-#define VV6410_LINELENGTHL             0x53
-
-/* X-co-ordinate of top left corner of region of interest (x-offset) */
-#define VV6410_XOFFSETH                        0x57
-#define VV6410_XOFFSETL                        0x58
-
-/* Y-coordinate of top left corner of region of interest (y-offset) */
-#define VV6410_YOFFSETH                        0x59
-#define VV6410_YOFFSETL                        0x5a
-
-/* Field length (Lines) */
-#define VV6410_FIELDLENGTHH            0x61
-#define VV6410_FIELDLENGTHL            0x62
-
-/* System registers */
-/* Black offset cancellation default value */
-#define VV6410_BLACKOFFSETH            0x70
-#define VV6410_BLACKOFFSETL            0x71
-
-/* Black offset cancellation setup */
-#define VV6410_BLACKOFFSETSETUP                0x72
-
-/* Analog Control Register 0 */
-#define VV6410_CR0                     0x75
-
-/* Analog Control Register 1 */
-#define VV6410_CR1                     0x76
-
-/* ADC Setup Register */
-#define VV6410_AS0                     0x77
-
-/* Analog Test Register */
-#define VV6410_AT0                     0x78
-
-/* Audio Amplifier Setup Register */
-#define VV6410_AT1                     0x79
-
-#define VV6410_HFLIP                   (1 << 3)
-#define VV6410_VFLIP                   (1 << 4)
-
-#define VV6410_LOW_POWER_MODE          (1 << 0)
-#define VV6410_SOFT_RESET              (1 << 2)
-#define VV6410_PAL_25_FPS              (0 << 3)
-
-#define VV6410_CLK_DIV_2               (1 << 1)
-
-#define VV6410_FINE_EXPOSURE           320
-#define VV6410_COARSE_EXPOSURE         192
-#define VV6410_DEFAULT_GAIN            5
-
-#define VV6410_SUBSAMPLE               0x01
-#define VV6410_CROP_TO_QVGA            0x02
-
-#define VV6410_CIF_LINELENGTH          415
-
-static int vv6410_probe(struct sd *sd);
-static int vv6410_start(struct sd *sd);
-static int vv6410_init(struct sd *sd);
-static int vv6410_init_controls(struct sd *sd);
-static int vv6410_stop(struct sd *sd);
-static int vv6410_dump(struct sd *sd);
-
-/* V4L2 controls supported by the driver */
-static int vv6410_set_hflip(struct gspca_dev *gspca_dev, __s32 val);
-static int vv6410_set_vflip(struct gspca_dev *gspca_dev, __s32 val);
-static int vv6410_set_analog_gain(struct gspca_dev *gspca_dev, __s32 val);
-static int vv6410_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
-
-const struct stv06xx_sensor stv06xx_sensor_vv6410 = {
-       .name = "ST VV6410",
-       .i2c_flush = 5,
-       .i2c_addr = 0x20,
-       .i2c_len = 1,
-       /* FIXME (see if we can lower packet_size-s, needs testing, and also
-          adjusting framerate when the bandwidth gets lower) */
-       .min_packet_size = { 1023 },
-       .max_packet_size = { 1023 },
-       .init = vv6410_init,
-       .init_controls = vv6410_init_controls,
-       .probe = vv6410_probe,
-       .start = vv6410_start,
-       .stop = vv6410_stop,
-       .dump = vv6410_dump,
-};
-
-/* If NULL, only single value to write, stored in len */
-struct stv_init {
-       u16 addr;
-       u8 data;
-};
-
-static const struct stv_init stv_bridge_init[] = {
-       /* This reg is written twice. Some kind of reset? */
-       {STV_RESET, 0x80},
-       {STV_RESET, 0x00},
-       {STV_SCAN_RATE, 0x00},
-       {STV_I2C_FLUSH, 0x04},
-       {STV_REG00, 0x0b},
-       {STV_REG01, 0xa7},
-       {STV_REG02, 0xb7},
-       {STV_REG03, 0x00},
-       {STV_REG04, 0x00},
-       {0x1536, 0x02},
-       {0x1537, 0x00},
-       {0x1538, 0x60},
-       {0x1539, 0x01},
-       {0x153a, 0x20},
-       {0x153b, 0x01},
-};
-
-static const u8 vv6410_sensor_init[][2] = {
-       /* Setup registers */
-       {VV6410_SETUP0, VV6410_SOFT_RESET},
-       {VV6410_SETUP0, VV6410_LOW_POWER_MODE},
-       /* Use shuffled read-out mode */
-       {VV6410_SETUP1, BIT(6)},
-       /* All modes to 1, FST, Fast QCK, Free running QCK, Free running LST, FST will qualify visible pixels */
-       {VV6410_FGMODES, BIT(6) | BIT(4) | BIT(2) | BIT(0)},
-       {VV6410_PINMAPPING, 0x00},
-       /* Pre-clock generator divide off */
-       {VV6410_DATAFORMAT, BIT(7) | BIT(0)},
-
-       {VV6410_CLKDIV, VV6410_CLK_DIV_2},
-
-       /* System registers */
-       /* Enable voltage doubler */
-       {VV6410_AS0, BIT(6) | BIT(4) | BIT(3) | BIT(2) | BIT(1)},
-       {VV6410_AT0, 0x00},
-       /* Power up audio, differential */
-       {VV6410_AT1, BIT(4) | BIT(0)},
-};
-
-#endif
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c
deleted file mode 100644 (file)
index 9ccfcb1..0000000
+++ /dev/null
@@ -1,1085 +0,0 @@
-/*
- *             Sunplus spca504(abc) spca533 spca536 library
- *             Copyright (C) 2005 Michel Xhaard mxhaard@magic.fr
- *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "sunplus"
-
-#include "gspca.h"
-#include "jpeg.h"
-
-MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
-MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-#define QUALITY 85
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       bool autogain;
-
-       u8 bridge;
-#define BRIDGE_SPCA504 0
-#define BRIDGE_SPCA504B 1
-#define BRIDGE_SPCA504C 2
-#define BRIDGE_SPCA533 3
-#define BRIDGE_SPCA536 4
-       u8 subtype;
-#define AiptekMiniPenCam13 1
-#define LogitechClickSmart420 2
-#define LogitechClickSmart820 3
-#define MegapixV4 4
-#define MegaImageVI 5
-
-       u8 jpeg_hdr[JPEG_HDR_SZ];
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 2},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-};
-
-static const struct v4l2_pix_format custom_mode[] = {
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 2},
-       {464, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 464,
-               .sizeimage = 464 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-};
-
-static const struct v4l2_pix_format vga_mode2[] = {
-       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 4},
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 3},
-       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 2},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-};
-
-#define SPCA50X_OFFSET_DATA 10
-#define SPCA504_PCCAM600_OFFSET_SNAPSHOT 3
-#define SPCA504_PCCAM600_OFFSET_COMPRESS 4
-#define SPCA504_PCCAM600_OFFSET_MODE    5
-#define SPCA504_PCCAM600_OFFSET_DATA    14
- /* Frame packet header offsets for the spca533 */
-#define SPCA533_OFFSET_DATA    16
-#define SPCA533_OFFSET_FRAMSEQ 15
-/* Frame packet header offsets for the spca536 */
-#define SPCA536_OFFSET_DATA    4
-#define SPCA536_OFFSET_FRAMSEQ 1
-
-struct cmd {
-       u8 req;
-       u16 val;
-       u16 idx;
-};
-
-/* Initialisation data for the Creative PC-CAM 600 */
-static const struct cmd spca504_pccam600_init_data[] = {
-/*     {0xa0, 0x0000, 0x0503},  * capture mode */
-       {0x00, 0x0000, 0x2000},
-       {0x00, 0x0013, 0x2301},
-       {0x00, 0x0003, 0x2000},
-       {0x00, 0x0001, 0x21ac},
-       {0x00, 0x0001, 0x21a6},
-       {0x00, 0x0000, 0x21a7}, /* brightness */
-       {0x00, 0x0020, 0x21a8}, /* contrast */
-       {0x00, 0x0001, 0x21ac}, /* sat/hue */
-       {0x00, 0x0000, 0x21ad}, /* hue */
-       {0x00, 0x001a, 0x21ae}, /* saturation */
-       {0x00, 0x0002, 0x21a3}, /* gamma */
-       {0x30, 0x0154, 0x0008},
-       {0x30, 0x0004, 0x0006},
-       {0x30, 0x0258, 0x0009},
-       {0x30, 0x0004, 0x0000},
-       {0x30, 0x0093, 0x0004},
-       {0x30, 0x0066, 0x0005},
-       {0x00, 0x0000, 0x2000},
-       {0x00, 0x0013, 0x2301},
-       {0x00, 0x0003, 0x2000},
-       {0x00, 0x0013, 0x2301},
-       {0x00, 0x0003, 0x2000},
-};
-
-/* Creative PC-CAM 600 specific open data, sent before using the
- * generic initialisation data from spca504_open_data.
- */
-static const struct cmd spca504_pccam600_open_data[] = {
-       {0x00, 0x0001, 0x2501},
-       {0x20, 0x0500, 0x0001}, /* snapshot mode */
-       {0x00, 0x0003, 0x2880},
-       {0x00, 0x0001, 0x2881},
-};
-
-/* Initialisation data for the logitech clicksmart 420 */
-static const struct cmd spca504A_clicksmart420_init_data[] = {
-/*     {0xa0, 0x0000, 0x0503},  * capture mode */
-       {0x00, 0x0000, 0x2000},
-       {0x00, 0x0013, 0x2301},
-       {0x00, 0x0003, 0x2000},
-       {0x00, 0x0001, 0x21ac},
-       {0x00, 0x0001, 0x21a6},
-       {0x00, 0x0000, 0x21a7}, /* brightness */
-       {0x00, 0x0020, 0x21a8}, /* contrast */
-       {0x00, 0x0001, 0x21ac}, /* sat/hue */
-       {0x00, 0x0000, 0x21ad}, /* hue */
-       {0x00, 0x001a, 0x21ae}, /* saturation */
-       {0x00, 0x0002, 0x21a3}, /* gamma */
-       {0x30, 0x0004, 0x000a},
-       {0xb0, 0x0001, 0x0000},
-
-       {0xa1, 0x0080, 0x0001},
-       {0x30, 0x0049, 0x0000},
-       {0x30, 0x0060, 0x0005},
-       {0x0c, 0x0004, 0x0000},
-       {0x00, 0x0000, 0x0000},
-       {0x00, 0x0000, 0x2000},
-       {0x00, 0x0013, 0x2301},
-       {0x00, 0x0003, 0x2000},
-};
-
-/* clicksmart 420 open data ? */
-static const struct cmd spca504A_clicksmart420_open_data[] = {
-       {0x00, 0x0001, 0x2501},
-       {0x20, 0x0502, 0x0000},
-       {0x06, 0x0000, 0x0000},
-       {0x00, 0x0004, 0x2880},
-       {0x00, 0x0001, 0x2881},
-
-       {0xa0, 0x0000, 0x0503},
-};
-
-static const u8 qtable_creative_pccam[2][64] = {
-       {                               /* Q-table Y-components */
-        0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
-        0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
-        0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
-        0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
-        0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
-        0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
-        0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
-        0x16, 0x1c, 0x1d, 0x1d, 0x22, 0x1e, 0x1f, 0x1e},
-       {                               /* Q-table C-components */
-        0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
-};
-
-/* FIXME: This Q-table is identical to the Creative PC-CAM one,
- *             except for one byte. Possibly a typo?
- *             NWG: 18/05/2003.
- */
-static const u8 qtable_spca504_default[2][64] = {
-       {                               /* Q-table Y-components */
-        0x05, 0x03, 0x03, 0x05, 0x07, 0x0c, 0x0f, 0x12,
-        0x04, 0x04, 0x04, 0x06, 0x08, 0x11, 0x12, 0x11,
-        0x04, 0x04, 0x05, 0x07, 0x0c, 0x11, 0x15, 0x11,
-        0x04, 0x05, 0x07, 0x09, 0x0f, 0x1a, 0x18, 0x13,
-        0x05, 0x07, 0x0b, 0x11, 0x14, 0x21, 0x1f, 0x17,
-        0x07, 0x0b, 0x11, 0x13, 0x18, 0x1f, 0x22, 0x1c,
-        0x0f, 0x13, 0x17, 0x1a, 0x1f, 0x24, 0x24, 0x1e,
-        0x16, 0x1c, 0x1d, 0x1d, 0x1d /* 0x22 */ , 0x1e, 0x1f, 0x1e,
-        },
-       {                               /* Q-table C-components */
-        0x05, 0x05, 0x07, 0x0e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x05, 0x06, 0x08, 0x14, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x07, 0x08, 0x11, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x0e, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-        0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e}
-};
-
-/* read <len> bytes to gspca_dev->usb_buf */
-static void reg_r(struct gspca_dev *gspca_dev,
-                 u8 req,
-                 u16 index,
-                 u16 len)
-{
-       int ret;
-
-#ifdef GSPCA_DEBUG
-       if (len > USB_BUF_SZ) {
-               pr_err("reg_r: buffer overflow\n");
-               return;
-       }
-#endif
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       req,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,              /* value */
-                       index,
-                       len ? gspca_dev->usb_buf : NULL, len,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_r err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-/* write one byte */
-static void reg_w_1(struct gspca_dev *gspca_dev,
-                  u8 req,
-                  u16 value,
-                  u16 index,
-                  u16 byte)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       gspca_dev->usb_buf[0] = byte;
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       req,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index,
-                       gspca_dev->usb_buf, 1,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_w_1 err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-/* write req / index / value */
-static void reg_w_riv(struct gspca_dev *gspca_dev,
-                    u8 req, u16 index, u16 value)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_control_msg(dev,
-                       usb_sndctrlpipe(dev, 0),
-                       req,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index, NULL, 0, 500);
-       if (ret < 0) {
-               pr_err("reg_w_riv err %d\n", ret);
-               gspca_dev->usb_err = ret;
-               return;
-       }
-       PDEBUG(D_USBO, "reg_w_riv: 0x%02x,0x%04x:0x%04x",
-               req, index, value);
-}
-
-static void write_vector(struct gspca_dev *gspca_dev,
-                       const struct cmd *data, int ncmds)
-{
-       while (--ncmds >= 0) {
-               reg_w_riv(gspca_dev, data->req, data->idx, data->val);
-               data++;
-       }
-}
-
-static void setup_qtable(struct gspca_dev *gspca_dev,
-                       const u8 qtable[2][64])
-{
-       int i;
-
-       /* loop over y components */
-       for (i = 0; i < 64; i++)
-               reg_w_riv(gspca_dev, 0x00, 0x2800 + i, qtable[0][i]);
-
-       /* loop over c components */
-       for (i = 0; i < 64; i++)
-               reg_w_riv(gspca_dev, 0x00, 0x2840 + i, qtable[1][i]);
-}
-
-static void spca504_acknowledged_command(struct gspca_dev *gspca_dev,
-                            u8 req, u16 idx, u16 val)
-{
-       reg_w_riv(gspca_dev, req, idx, val);
-       reg_r(gspca_dev, 0x01, 0x0001, 1);
-       PDEBUG(D_FRAM, "before wait 0x%04x", gspca_dev->usb_buf[0]);
-       reg_w_riv(gspca_dev, req, idx, val);
-
-       msleep(200);
-       reg_r(gspca_dev, 0x01, 0x0001, 1);
-       PDEBUG(D_FRAM, "after wait 0x%04x", gspca_dev->usb_buf[0]);
-}
-
-#ifdef GSPCA_DEBUG
-static void spca504_read_info(struct gspca_dev *gspca_dev)
-{
-       int i;
-       u8 info[6];
-
-       for (i = 0; i < 6; i++) {
-               reg_r(gspca_dev, 0, i, 1);
-               info[i] = gspca_dev->usb_buf[0];
-       }
-       PDEBUG(D_STREAM,
-               "Read info: %d %d %d %d %d %d."
-               " Should be 1,0,2,2,0,0",
-               info[0], info[1], info[2],
-               info[3], info[4], info[5]);
-}
-#endif
-
-static void spca504A_acknowledged_command(struct gspca_dev *gspca_dev,
-                       u8 req,
-                       u16 idx, u16 val, u8 endcode, u8 count)
-{
-       u16 status;
-
-       reg_w_riv(gspca_dev, req, idx, val);
-       reg_r(gspca_dev, 0x01, 0x0001, 1);
-       if (gspca_dev->usb_err < 0)
-               return;
-       PDEBUG(D_FRAM, "Status 0x%02x Need 0x%02x",
-                       gspca_dev->usb_buf[0], endcode);
-       if (!count)
-               return;
-       count = 200;
-       while (--count > 0) {
-               msleep(10);
-               /* gsmart mini2 write a each wait setting 1 ms is enough */
-/*             reg_w_riv(gspca_dev, req, idx, val); */
-               reg_r(gspca_dev, 0x01, 0x0001, 1);
-               status = gspca_dev->usb_buf[0];
-               if (status == endcode) {
-                       PDEBUG(D_FRAM, "status 0x%04x after wait %d",
-                               status, 200 - count);
-                               break;
-               }
-       }
-}
-
-static void spca504B_PollingDataReady(struct gspca_dev *gspca_dev)
-{
-       int count = 10;
-
-       while (--count > 0) {
-               reg_r(gspca_dev, 0x21, 0, 1);
-               if ((gspca_dev->usb_buf[0] & 0x01) == 0)
-                       break;
-               msleep(10);
-       }
-}
-
-static void spca504B_WaitCmdStatus(struct gspca_dev *gspca_dev)
-{
-       int count = 50;
-
-       while (--count > 0) {
-               reg_r(gspca_dev, 0x21, 1, 1);
-               if (gspca_dev->usb_buf[0] != 0) {
-                       reg_w_1(gspca_dev, 0x21, 0, 1, 0);
-                       reg_r(gspca_dev, 0x21, 1, 1);
-                       spca504B_PollingDataReady(gspca_dev);
-                       break;
-               }
-               msleep(10);
-       }
-}
-
-#ifdef GSPCA_DEBUG
-static void spca50x_GetFirmware(struct gspca_dev *gspca_dev)
-{
-       u8 *data;
-
-       data = gspca_dev->usb_buf;
-       reg_r(gspca_dev, 0x20, 0, 5);
-       PDEBUG(D_STREAM, "FirmWare: %d %d %d %d %d",
-               data[0], data[1], data[2], data[3], data[4]);
-       reg_r(gspca_dev, 0x23, 0, 64);
-       reg_r(gspca_dev, 0x23, 1, 64);
-}
-#endif
-
-static void spca504B_SetSizeType(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 Size;
-
-       Size = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-       switch (sd->bridge) {
-       case BRIDGE_SPCA533:
-               reg_w_riv(gspca_dev, 0x31, 0, 0);
-               spca504B_WaitCmdStatus(gspca_dev);
-               spca504B_PollingDataReady(gspca_dev);
-#ifdef GSPCA_DEBUG
-               spca50x_GetFirmware(gspca_dev);
-#endif
-               reg_w_1(gspca_dev, 0x24, 0, 8, 2);              /* type */
-               reg_r(gspca_dev, 0x24, 8, 1);
-
-               reg_w_1(gspca_dev, 0x25, 0, 4, Size);
-               reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
-               spca504B_PollingDataReady(gspca_dev);
-
-               /* Init the cam width height with some values get on init ? */
-               reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
-               spca504B_WaitCmdStatus(gspca_dev);
-               spca504B_PollingDataReady(gspca_dev);
-               break;
-       default:
-/* case BRIDGE_SPCA504B: */
-/* case BRIDGE_SPCA536: */
-               reg_w_1(gspca_dev, 0x25, 0, 4, Size);
-               reg_r(gspca_dev, 0x25, 4, 1);                   /* size */
-               reg_w_1(gspca_dev, 0x27, 0, 0, 6);
-               reg_r(gspca_dev, 0x27, 0, 1);                   /* type */
-               spca504B_PollingDataReady(gspca_dev);
-               break;
-       case BRIDGE_SPCA504:
-               Size += 3;
-               if (sd->subtype == AiptekMiniPenCam13) {
-                       /* spca504a aiptek */
-                       spca504A_acknowledged_command(gspca_dev,
-                                               0x08, Size, 0,
-                                               0x80 | (Size & 0x0f), 1);
-                       spca504A_acknowledged_command(gspca_dev,
-                                                       1, 3, 0, 0x9f, 0);
-               } else {
-                       spca504_acknowledged_command(gspca_dev, 0x08, Size, 0);
-               }
-               break;
-       case BRIDGE_SPCA504C:
-               /* capture mode */
-               reg_w_riv(gspca_dev, 0xa0, (0x0500 | (Size & 0x0f)), 0x00);
-               reg_w_riv(gspca_dev, 0x20, 0x01, 0x0500 | (Size & 0x0f));
-               break;
-       }
-}
-
-static void spca504_wait_status(struct gspca_dev *gspca_dev)
-{
-       int cnt;
-
-       cnt = 256;
-       while (--cnt > 0) {
-               /* With this we get the status, when return 0 it's all ok */
-               reg_r(gspca_dev, 0x06, 0x00, 1);
-               if (gspca_dev->usb_buf[0] == 0)
-                       return;
-               msleep(10);
-       }
-}
-
-static void spca504B_setQtable(struct gspca_dev *gspca_dev)
-{
-       reg_w_1(gspca_dev, 0x26, 0, 0, 3);
-       reg_r(gspca_dev, 0x26, 0, 1);
-       spca504B_PollingDataReady(gspca_dev);
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u16 reg;
-
-       reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7;
-       reg_w_riv(gspca_dev, 0x00, reg, val);
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u16 reg;
-
-       reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8;
-       reg_w_riv(gspca_dev, 0x00, reg, val);
-}
-
-static void setcolors(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u16 reg;
-
-       reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae;
-       reg_w_riv(gspca_dev, 0x00, reg, val);
-}
-
-static void init_ctl_reg(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int pollreg = 1;
-
-       switch (sd->bridge) {
-       case BRIDGE_SPCA504:
-       case BRIDGE_SPCA504C:
-               pollreg = 0;
-               /* fall thru */
-       default:
-/*     case BRIDGE_SPCA533: */
-/*     case BRIDGE_SPCA504B: */
-               reg_w_riv(gspca_dev, 0, 0x21ad, 0x00);  /* hue */
-               reg_w_riv(gspca_dev, 0, 0x21ac, 0x01);  /* sat/hue */
-               reg_w_riv(gspca_dev, 0, 0x21a3, 0x00);  /* gamma */
-               break;
-       case BRIDGE_SPCA536:
-               reg_w_riv(gspca_dev, 0, 0x20f5, 0x40);
-               reg_w_riv(gspca_dev, 0, 0x20f4, 0x01);
-               reg_w_riv(gspca_dev, 0, 0x2089, 0x00);
-               break;
-       }
-       if (pollreg)
-               spca504B_PollingDataReady(gspca_dev);
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-
-       cam = &gspca_dev->cam;
-
-       sd->bridge = id->driver_info >> 8;
-       sd->subtype = id->driver_info;
-
-       if (sd->subtype == AiptekMiniPenCam13) {
-
-               /* try to get the firmware as some cam answer 2.0.1.2.2
-                * and should be a spca504b then overwrite that setting */
-               reg_r(gspca_dev, 0x20, 0, 1);
-               switch (gspca_dev->usb_buf[0]) {
-               case 1:
-                       break;          /* (right bridge/subtype) */
-               case 2:
-                       sd->bridge = BRIDGE_SPCA504B;
-                       sd->subtype = 0;
-                       break;
-               default:
-                       return -ENODEV;
-               }
-       }
-
-       switch (sd->bridge) {
-       default:
-/*     case BRIDGE_SPCA504B: */
-/*     case BRIDGE_SPCA504: */
-/*     case BRIDGE_SPCA536: */
-               cam->cam_mode = vga_mode;
-               cam->nmodes = ARRAY_SIZE(vga_mode);
-               break;
-       case BRIDGE_SPCA533:
-               cam->cam_mode = custom_mode;
-               if (sd->subtype == MegaImageVI)         /* 320x240 only */
-                       cam->nmodes = ARRAY_SIZE(custom_mode) - 1;
-               else
-                       cam->nmodes = ARRAY_SIZE(custom_mode);
-               break;
-       case BRIDGE_SPCA504C:
-               cam->cam_mode = vga_mode2;
-               cam->nmodes = ARRAY_SIZE(vga_mode2);
-               break;
-       }
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->bridge) {
-       case BRIDGE_SPCA504B:
-               reg_w_riv(gspca_dev, 0x1d, 0x00, 0);
-               reg_w_riv(gspca_dev, 0x00, 0x2306, 0x01);
-               reg_w_riv(gspca_dev, 0x00, 0x0d04, 0x00);
-               reg_w_riv(gspca_dev, 0x00, 0x2000, 0x00);
-               reg_w_riv(gspca_dev, 0x00, 0x2301, 0x13);
-               reg_w_riv(gspca_dev, 0x00, 0x2306, 0x00);
-               /* fall thru */
-       case BRIDGE_SPCA533:
-               spca504B_PollingDataReady(gspca_dev);
-#ifdef GSPCA_DEBUG
-               spca50x_GetFirmware(gspca_dev);
-#endif
-               break;
-       case BRIDGE_SPCA536:
-#ifdef GSPCA_DEBUG
-               spca50x_GetFirmware(gspca_dev);
-#endif
-               reg_r(gspca_dev, 0x00, 0x5002, 1);
-               reg_w_1(gspca_dev, 0x24, 0, 0, 0);
-               reg_r(gspca_dev, 0x24, 0, 1);
-               spca504B_PollingDataReady(gspca_dev);
-               reg_w_riv(gspca_dev, 0x34, 0, 0);
-               spca504B_WaitCmdStatus(gspca_dev);
-               break;
-       case BRIDGE_SPCA504C:   /* pccam600 */
-               PDEBUG(D_STREAM, "Opening SPCA504 (PC-CAM 600)");
-               reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0000);
-               reg_w_riv(gspca_dev, 0xe0, 0x0000, 0x0001);     /* reset */
-               spca504_wait_status(gspca_dev);
-               if (sd->subtype == LogitechClickSmart420)
-                       write_vector(gspca_dev,
-                               spca504A_clicksmart420_open_data,
-                               ARRAY_SIZE(spca504A_clicksmart420_open_data));
-               else
-                       write_vector(gspca_dev, spca504_pccam600_open_data,
-                               ARRAY_SIZE(spca504_pccam600_open_data));
-               setup_qtable(gspca_dev, qtable_creative_pccam);
-               break;
-       default:
-/*     case BRIDGE_SPCA504: */
-               PDEBUG(D_STREAM, "Opening SPCA504");
-               if (sd->subtype == AiptekMiniPenCam13) {
-#ifdef GSPCA_DEBUG
-                       spca504_read_info(gspca_dev);
-#endif
-
-                       /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
-                       spca504A_acknowledged_command(gspca_dev, 0x24,
-                                                       8, 3, 0x9e, 1);
-                       /* Twice sequential need status 0xff->0x9e->0x9d */
-                       spca504A_acknowledged_command(gspca_dev, 0x24,
-                                                       8, 3, 0x9e, 0);
-
-                       spca504A_acknowledged_command(gspca_dev, 0x24,
-                                                       0, 0, 0x9d, 1);
-                       /******************************/
-                       /* spca504a aiptek */
-                       spca504A_acknowledged_command(gspca_dev, 0x08,
-                                                       6, 0, 0x86, 1);
-/*                     reg_write (dev, 0, 0x2000, 0); */
-/*                     reg_write (dev, 0, 0x2883, 1); */
-/*                     spca504A_acknowledged_command (gspca_dev, 0x08,
-                                                       6, 0, 0x86, 1); */
-/*                     spca504A_acknowledged_command (gspca_dev, 0x24,
-                                                       0, 0, 0x9D, 1); */
-                       reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
-                                                       /* L92 sno1t.txt */
-                       reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
-                       spca504A_acknowledged_command(gspca_dev, 0x01,
-                                                       0x0f, 0, 0xff, 0);
-               }
-               /* setup qtable */
-               reg_w_riv(gspca_dev, 0, 0x2000, 0);
-               reg_w_riv(gspca_dev, 0, 0x2883, 1);
-               setup_qtable(gspca_dev, qtable_spca504_default);
-               break;
-       }
-       return gspca_dev->usb_err;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int enable;
-
-       /* create the JPEG header */
-       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
-                       0x22);          /* JPEG 411 */
-       jpeg_set_qual(sd->jpeg_hdr, QUALITY);
-
-       if (sd->bridge == BRIDGE_SPCA504B)
-               spca504B_setQtable(gspca_dev);
-       spca504B_SetSizeType(gspca_dev);
-       switch (sd->bridge) {
-       default:
-/*     case BRIDGE_SPCA504B: */
-/*     case BRIDGE_SPCA533: */
-/*     case BRIDGE_SPCA536: */
-               switch (sd->subtype) {
-               case MegapixV4:
-               case LogitechClickSmart820:
-               case MegaImageVI:
-                       reg_w_riv(gspca_dev, 0xf0, 0, 0);
-                       spca504B_WaitCmdStatus(gspca_dev);
-                       reg_r(gspca_dev, 0xf0, 4, 0);
-                       spca504B_WaitCmdStatus(gspca_dev);
-                       break;
-               default:
-                       reg_w_riv(gspca_dev, 0x31, 0x0004, 0x00);
-                       spca504B_WaitCmdStatus(gspca_dev);
-                       spca504B_PollingDataReady(gspca_dev);
-                       break;
-               }
-               break;
-       case BRIDGE_SPCA504:
-               if (sd->subtype == AiptekMiniPenCam13) {
-#ifdef GSPCA_DEBUG
-                       spca504_read_info(gspca_dev);
-#endif
-
-                       /* Set AE AWB Banding Type 3-> 50Hz 2-> 60Hz */
-                       spca504A_acknowledged_command(gspca_dev, 0x24,
-                                                       8, 3, 0x9e, 1);
-                       /* Twice sequential need status 0xff->0x9e->0x9d */
-                       spca504A_acknowledged_command(gspca_dev, 0x24,
-                                                       8, 3, 0x9e, 0);
-                       spca504A_acknowledged_command(gspca_dev, 0x24,
-                                                       0, 0, 0x9d, 1);
-               } else {
-                       spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
-#ifdef GSPCA_DEBUG
-                       spca504_read_info(gspca_dev);
-#endif
-                       spca504_acknowledged_command(gspca_dev, 0x24, 8, 3);
-                       spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
-               }
-               spca504B_SetSizeType(gspca_dev);
-               reg_w_riv(gspca_dev, 0x00, 0x270c, 0x05);
-                                                       /* L92 sno1t.txt */
-               reg_w_riv(gspca_dev, 0x00, 0x2310, 0x05);
-               break;
-       case BRIDGE_SPCA504C:
-               if (sd->subtype == LogitechClickSmart420) {
-                       write_vector(gspca_dev,
-                               spca504A_clicksmart420_init_data,
-                               ARRAY_SIZE(spca504A_clicksmart420_init_data));
-               } else {
-                       write_vector(gspca_dev, spca504_pccam600_init_data,
-                               ARRAY_SIZE(spca504_pccam600_init_data));
-               }
-               enable = (sd->autogain ? 0x04 : 0x01);
-               reg_w_riv(gspca_dev, 0x0c, 0x0000, enable);
-                                                       /* auto exposure */
-               reg_w_riv(gspca_dev, 0xb0, 0x0000, enable);
-                                                       /* auto whiteness */
-
-               /* set default exposure compensation and whiteness balance */
-               reg_w_riv(gspca_dev, 0x30, 0x0001, 800);        /* ~ 20 fps */
-               reg_w_riv(gspca_dev, 0x30, 0x0002, 1600);
-               spca504B_SetSizeType(gspca_dev);
-               break;
-       }
-       init_ctl_reg(gspca_dev);
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->bridge) {
-       default:
-/*     case BRIDGE_SPCA533: */
-/*     case BRIDGE_SPCA536: */
-/*     case BRIDGE_SPCA504B: */
-               reg_w_riv(gspca_dev, 0x31, 0, 0);
-               spca504B_WaitCmdStatus(gspca_dev);
-               spca504B_PollingDataReady(gspca_dev);
-               break;
-       case BRIDGE_SPCA504:
-       case BRIDGE_SPCA504C:
-               reg_w_riv(gspca_dev, 0x00, 0x2000, 0x0000);
-
-               if (sd->subtype == AiptekMiniPenCam13) {
-                       /* spca504a aiptek */
-/*                     spca504A_acknowledged_command(gspca_dev, 0x08,
-                                                        6, 0, 0x86, 1); */
-                       spca504A_acknowledged_command(gspca_dev, 0x24,
-                                                       0x00, 0x00, 0x9d, 1);
-                       spca504A_acknowledged_command(gspca_dev, 0x01,
-                                                       0x0f, 0x00, 0xff, 1);
-               } else {
-                       spca504_acknowledged_command(gspca_dev, 0x24, 0, 0);
-                       reg_w_riv(gspca_dev, 0x01, 0x000f, 0x0000);
-               }
-               break;
-       }
-}
-
-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;
-       int i, sof = 0;
-       static u8 ffd9[] = {0xff, 0xd9};
-
-/* frames are jpeg 4.1.1 without 0xff escape */
-       switch (sd->bridge) {
-       case BRIDGE_SPCA533:
-               if (data[0] == 0xff) {
-                       if (data[1] != 0x01) {  /* drop packet */
-/*                             gspca_dev->last_packet_type = DISCARD_PACKET; */
-                               return;
-                       }
-                       sof = 1;
-                       data += SPCA533_OFFSET_DATA;
-                       len -= SPCA533_OFFSET_DATA;
-               } else {
-                       data += 1;
-                       len -= 1;
-               }
-               break;
-       case BRIDGE_SPCA536:
-               if (data[0] == 0xff) {
-                       sof = 1;
-                       data += SPCA536_OFFSET_DATA;
-                       len -= SPCA536_OFFSET_DATA;
-               } else {
-                       data += 2;
-                       len -= 2;
-               }
-               break;
-       default:
-/*     case BRIDGE_SPCA504: */
-/*     case BRIDGE_SPCA504B: */
-               switch (data[0]) {
-               case 0xfe:                      /* start of frame */
-                       sof = 1;
-                       data += SPCA50X_OFFSET_DATA;
-                       len -= SPCA50X_OFFSET_DATA;
-                       break;
-               case 0xff:                      /* drop packet */
-/*                     gspca_dev->last_packet_type = DISCARD_PACKET; */
-                       return;
-               default:
-                       data += 1;
-                       len -= 1;
-                       break;
-               }
-               break;
-       case BRIDGE_SPCA504C:
-               switch (data[0]) {
-               case 0xfe:                      /* start of frame */
-                       sof = 1;
-                       data += SPCA504_PCCAM600_OFFSET_DATA;
-                       len -= SPCA504_PCCAM600_OFFSET_DATA;
-                       break;
-               case 0xff:                      /* drop packet */
-/*                     gspca_dev->last_packet_type = DISCARD_PACKET; */
-                       return;
-               default:
-                       data += 1;
-                       len -= 1;
-                       break;
-               }
-               break;
-       }
-       if (sof) {              /* start of frame */
-               gspca_frame_add(gspca_dev, LAST_PACKET,
-                               ffd9, 2);
-
-               /* put the JPEG header in the new frame */
-               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                       sd->jpeg_hdr, JPEG_HDR_SZ);
-       }
-
-       /* add 0x00 after 0xff */
-       i = 0;
-       do {
-               if (data[i] == 0xff) {
-                       gspca_frame_add(gspca_dev, INTER_PACKET,
-                                       data, i + 1);
-                       len -= i;
-                       data += i;
-                       *data = 0x00;
-                       i = 0;
-               }
-               i++;
-       } while (i < len);
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-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_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               setcolors(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               sd->autogain = ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 4);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 255, 1, 0x20);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 255, 1, 0x1a);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-
-       if (hdl->error) {
-               pr_err("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,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-#define BS(bridge, subtype) \
-       .driver_info = (BRIDGE_ ## bridge << 8) \
-                       | (subtype)
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x041e, 0x400b), BS(SPCA504C, 0)},
-       {USB_DEVICE(0x041e, 0x4012), BS(SPCA504C, 0)},
-       {USB_DEVICE(0x041e, 0x4013), BS(SPCA504C, 0)},
-       {USB_DEVICE(0x0458, 0x7006), BS(SPCA504B, 0)},
-       {USB_DEVICE(0x0461, 0x0821), BS(SPCA533, 0)},
-       {USB_DEVICE(0x046d, 0x0905), BS(SPCA533, LogitechClickSmart820)},
-       {USB_DEVICE(0x046d, 0x0960), BS(SPCA504C, LogitechClickSmart420)},
-       {USB_DEVICE(0x0471, 0x0322), BS(SPCA504B, 0)},
-       {USB_DEVICE(0x04a5, 0x3003), BS(SPCA504B, 0)},
-       {USB_DEVICE(0x04a5, 0x3008), BS(SPCA533, 0)},
-       {USB_DEVICE(0x04a5, 0x300a), BS(SPCA533, 0)},
-       {USB_DEVICE(0x04f1, 0x1001), BS(SPCA504B, 0)},
-       {USB_DEVICE(0x04fc, 0x500c), BS(SPCA504B, 0)},
-       {USB_DEVICE(0x04fc, 0x504a), BS(SPCA504, AiptekMiniPenCam13)},
-       {USB_DEVICE(0x04fc, 0x504b), BS(SPCA504B, 0)},
-       {USB_DEVICE(0x04fc, 0x5330), BS(SPCA533, 0)},
-       {USB_DEVICE(0x04fc, 0x5360), BS(SPCA536, 0)},
-       {USB_DEVICE(0x04fc, 0xffff), BS(SPCA504B, 0)},
-       {USB_DEVICE(0x052b, 0x1507), BS(SPCA533, MegapixV4)},
-       {USB_DEVICE(0x052b, 0x1513), BS(SPCA533, MegapixV4)},
-       {USB_DEVICE(0x052b, 0x1803), BS(SPCA533, MegaImageVI)},
-       {USB_DEVICE(0x0546, 0x3155), BS(SPCA533, 0)},
-       {USB_DEVICE(0x0546, 0x3191), BS(SPCA504B, 0)},
-       {USB_DEVICE(0x0546, 0x3273), BS(SPCA504B, 0)},
-       {USB_DEVICE(0x055f, 0xc211), BS(SPCA536, 0)},
-       {USB_DEVICE(0x055f, 0xc230), BS(SPCA533, 0)},
-       {USB_DEVICE(0x055f, 0xc232), BS(SPCA533, 0)},
-       {USB_DEVICE(0x055f, 0xc360), BS(SPCA536, 0)},
-       {USB_DEVICE(0x055f, 0xc420), BS(SPCA504, 0)},
-       {USB_DEVICE(0x055f, 0xc430), BS(SPCA533, 0)},
-       {USB_DEVICE(0x055f, 0xc440), BS(SPCA533, 0)},
-       {USB_DEVICE(0x055f, 0xc520), BS(SPCA504, 0)},
-       {USB_DEVICE(0x055f, 0xc530), BS(SPCA533, 0)},
-       {USB_DEVICE(0x055f, 0xc540), BS(SPCA533, 0)},
-       {USB_DEVICE(0x055f, 0xc630), BS(SPCA533, 0)},
-       {USB_DEVICE(0x055f, 0xc650), BS(SPCA533, 0)},
-       {USB_DEVICE(0x05da, 0x1018), BS(SPCA504B, 0)},
-       {USB_DEVICE(0x06d6, 0x0031), BS(SPCA533, 0)},
-       {USB_DEVICE(0x0733, 0x1311), BS(SPCA533, 0)},
-       {USB_DEVICE(0x0733, 0x1314), BS(SPCA533, 0)},
-       {USB_DEVICE(0x0733, 0x2211), BS(SPCA533, 0)},
-       {USB_DEVICE(0x0733, 0x2221), BS(SPCA533, 0)},
-       {USB_DEVICE(0x0733, 0x3261), BS(SPCA536, 0)},
-       {USB_DEVICE(0x0733, 0x3281), BS(SPCA536, 0)},
-       {USB_DEVICE(0x08ca, 0x0104), BS(SPCA533, 0)},
-       {USB_DEVICE(0x08ca, 0x0106), BS(SPCA533, 0)},
-       {USB_DEVICE(0x08ca, 0x2008), BS(SPCA504B, 0)},
-       {USB_DEVICE(0x08ca, 0x2010), BS(SPCA533, 0)},
-       {USB_DEVICE(0x08ca, 0x2016), BS(SPCA504B, 0)},
-       {USB_DEVICE(0x08ca, 0x2018), BS(SPCA504B, 0)},
-       {USB_DEVICE(0x08ca, 0x2020), BS(SPCA533, 0)},
-       {USB_DEVICE(0x08ca, 0x2022), BS(SPCA533, 0)},
-       {USB_DEVICE(0x08ca, 0x2024), BS(SPCA536, 0)},
-       {USB_DEVICE(0x08ca, 0x2028), BS(SPCA533, 0)},
-       {USB_DEVICE(0x08ca, 0x2040), BS(SPCA536, 0)},
-       {USB_DEVICE(0x08ca, 0x2042), BS(SPCA536, 0)},
-       {USB_DEVICE(0x08ca, 0x2050), BS(SPCA536, 0)},
-       {USB_DEVICE(0x08ca, 0x2060), BS(SPCA536, 0)},
-       {USB_DEVICE(0x0d64, 0x0303), BS(SPCA536, 0)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c
deleted file mode 100644 (file)
index 8bc6c3c..0000000
+++ /dev/null
@@ -1,1054 +0,0 @@
-/*
- * T613 subdriver
- *
- * Copyright (C) 2010 Jean-Francois Moine (http://moinejf.free.fr)
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *Notes: * t613  + tas5130A
- *     * Focus to light do not balance well as in win.
- *       Quality in win is not good, but its kinda better.
- *      * Fix some "extraneous bytes", most of apps will show the image anyway
- *      * Gamma table, is there, but its really doing something?
- *      * 7~8 Fps, its ok, max on win its 10.
- *                     Costantino Leandro
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "t613"
-
-#include <linux/input.h>
-#include <linux/slab.h>
-#include "gspca.h"
-
-MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
-MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-       struct v4l2_ctrl *freq;
-       struct { /* awb / color gains control cluster */
-               struct v4l2_ctrl *awb;
-               struct v4l2_ctrl *gain;
-               struct v4l2_ctrl *red_balance;
-               struct v4l2_ctrl *blue_balance;
-       };
-
-       u8 sensor;
-       u8 button_pressed;
-};
-enum sensors {
-       SENSOR_OM6802,
-       SENSOR_OTHER,
-       SENSOR_TAS5130A,
-       SENSOR_LT168G,          /* must verify if this is the actual model */
-};
-
-static const struct v4l2_pix_format vga_mode_t16[] = {
-       {160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 4 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 4},
-#if 0 /* HDG: broken with my test cam, so lets disable it */
-       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 3},
-#endif
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 2},
-#if 0 /* HDG: broken with my test cam, so lets disable it */
-       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-#endif
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-
-/* sensor specific data */
-struct additional_sensor_data {
-       const u8 n3[6];
-       const u8 *n4, n4sz;
-       const u8 reg80, reg8e;
-       const u8 nset8[6];
-       const u8 data1[10];
-       const u8 data2[9];
-       const u8 data3[9];
-       const u8 data5[6];
-       const u8 stream[4];
-};
-
-static const u8 n4_om6802[] = {
-       0x09, 0x01, 0x12, 0x04, 0x66, 0x8a, 0x80, 0x3c,
-       0x81, 0x22, 0x84, 0x50, 0x8a, 0x78, 0x8b, 0x68,
-       0x8c, 0x88, 0x8e, 0x33, 0x8f, 0x24, 0xaa, 0xb1,
-       0xa2, 0x60, 0xa5, 0x30, 0xa6, 0x3a, 0xa8, 0xe8,
-       0xae, 0x05, 0xb1, 0x00, 0xbb, 0x04, 0xbc, 0x48,
-       0xbe, 0x36, 0xc6, 0x88, 0xe9, 0x00, 0xc5, 0xc0,
-       0x65, 0x0a, 0xbb, 0x86, 0xaf, 0x58, 0xb0, 0x68,
-       0x87, 0x40, 0x89, 0x2b, 0x8d, 0xff, 0x83, 0x40,
-       0xac, 0x84, 0xad, 0x86, 0xaf, 0x46
-};
-static const u8 n4_other[] = {
-       0x66, 0x00, 0x7f, 0x00, 0x80, 0xac, 0x81, 0x69,
-       0x84, 0x40, 0x85, 0x70, 0x86, 0x20, 0x8a, 0x68,
-       0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xff, 0x8e, 0xb8,
-       0x8f, 0x28, 0xa2, 0x60, 0xa5, 0x40, 0xa8, 0xa8,
-       0xac, 0x84, 0xad, 0x84, 0xae, 0x24, 0xaf, 0x56,
-       0xb0, 0x68, 0xb1, 0x00, 0xb2, 0x88, 0xbb, 0xc5,
-       0xbc, 0x4a, 0xbe, 0x36, 0xc2, 0x88, 0xc5, 0xc0,
-       0xc6, 0xda, 0xe9, 0x26, 0xeb, 0x00
-};
-static const u8 n4_tas5130a[] = {
-       0x80, 0x3c, 0x81, 0x68, 0x83, 0xa0, 0x84, 0x20,
-       0x8a, 0x68, 0x8b, 0x58, 0x8c, 0x88, 0x8e, 0xb4,
-       0x8f, 0x24, 0xa1, 0xb1, 0xa2, 0x30, 0xa5, 0x10,
-       0xa6, 0x4a, 0xae, 0x03, 0xb1, 0x44, 0xb2, 0x08,
-       0xb7, 0x06, 0xb9, 0xe7, 0xbb, 0xc4, 0xbc, 0x4a,
-       0xbe, 0x36, 0xbf, 0xff, 0xc2, 0x88, 0xc5, 0xc8,
-       0xc6, 0xda
-};
-static const u8 n4_lt168g[] = {
-       0x66, 0x01, 0x7f, 0x00, 0x80, 0x7c, 0x81, 0x28,
-       0x83, 0x44, 0x84, 0x20, 0x86, 0x20, 0x8a, 0x70,
-       0x8b, 0x58, 0x8c, 0x88, 0x8d, 0xa0, 0x8e, 0xb3,
-       0x8f, 0x24, 0xa1, 0xb0, 0xa2, 0x38, 0xa5, 0x20,
-       0xa6, 0x4a, 0xa8, 0xe8, 0xaf, 0x38, 0xb0, 0x68,
-       0xb1, 0x44, 0xb2, 0x88, 0xbb, 0x86, 0xbd, 0x40,
-       0xbe, 0x26, 0xc1, 0x05, 0xc2, 0x88, 0xc5, 0xc0,
-       0xda, 0x8e, 0xdb, 0xca, 0xdc, 0xa8, 0xdd, 0x8c,
-       0xde, 0x44, 0xdf, 0x0c, 0xe9, 0x80
-};
-
-static const struct additional_sensor_data sensor_data[] = {
-[SENSOR_OM6802] = {
-       .n3 =
-               {0x61, 0x68, 0x65, 0x0a, 0x60, 0x04},
-       .n4 = n4_om6802,
-       .n4sz = sizeof n4_om6802,
-       .reg80 = 0x3c,
-       .reg8e = 0x33,
-       .nset8 = {0xa8, 0xf0, 0xc6, 0x88, 0xc0, 0x00},
-       .data1 =
-               {0xc2, 0x28, 0x0f, 0x22, 0xcd, 0x27, 0x2c, 0x06,
-                0xb3, 0xfc},
-       .data2 =
-               {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
-                0xff},
-       .data3 =
-               {0x80, 0xff, 0xff, 0x80, 0xff, 0xff, 0x80, 0xff,
-                0xff},
-       .data5 =        /* this could be removed later */
-               {0x0c, 0x03, 0xab, 0x13, 0x81, 0x23},
-       .stream =
-               {0x0b, 0x04, 0x0a, 0x78},
-    },
-[SENSOR_OTHER] = {
-       .n3 =
-               {0x61, 0xc2, 0x65, 0x88, 0x60, 0x00},
-       .n4 = n4_other,
-       .n4sz = sizeof n4_other,
-       .reg80 = 0xac,
-       .reg8e = 0xb8,
-       .nset8 = {0xa8, 0xa8, 0xc6, 0xda, 0xc0, 0x00},
-       .data1 =
-               {0xc1, 0x48, 0x04, 0x1b, 0xca, 0x2e, 0x33, 0x3a,
-                0xe8, 0xfc},
-       .data2 =
-               {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
-                0xd9},
-       .data3 =
-               {0x4e, 0x9c, 0xec, 0x40, 0x80, 0xc0, 0x48, 0x96,
-                0xd9},
-       .data5 =
-               {0x0c, 0x03, 0xab, 0x29, 0x81, 0x69},
-       .stream =
-               {0x0b, 0x04, 0x0a, 0x00},
-    },
-[SENSOR_TAS5130A] = {
-       .n3 =
-               {0x61, 0xc2, 0x65, 0x0d, 0x60, 0x08},
-       .n4 = n4_tas5130a,
-       .n4sz = sizeof n4_tas5130a,
-       .reg80 = 0x3c,
-       .reg8e = 0xb4,
-       .nset8 = {0xa8, 0xf0, 0xc6, 0xda, 0xc0, 0x00},
-       .data1 =
-               {0xbb, 0x28, 0x10, 0x10, 0xbb, 0x28, 0x1e, 0x27,
-                0xc8, 0xfc},
-       .data2 =
-               {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
-                0xe0},
-       .data3 =
-               {0x60, 0xa8, 0xe0, 0x60, 0xa8, 0xe0, 0x60, 0xa8,
-                0xe0},
-       .data5 =
-               {0x0c, 0x03, 0xab, 0x10, 0x81, 0x20},
-       .stream =
-               {0x0b, 0x04, 0x0a, 0x40},
-    },
-[SENSOR_LT168G] = {
-       .n3 = {0x61, 0xc2, 0x65, 0x68, 0x60, 0x00},
-       .n4 = n4_lt168g,
-       .n4sz = sizeof n4_lt168g,
-       .reg80 = 0x7c,
-       .reg8e = 0xb3,
-       .nset8 = {0xa8, 0xf0, 0xc6, 0xba, 0xc0, 0x00},
-       .data1 = {0xc0, 0x38, 0x08, 0x10, 0xc0, 0x30, 0x10, 0x40,
-                0xb0, 0xf4},
-       .data2 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
-                0xff},
-       .data3 = {0x40, 0x80, 0xc0, 0x50, 0xa0, 0xf0, 0x53, 0xa6,
-                0xff},
-       .data5 = {0x0c, 0x03, 0xab, 0x4b, 0x81, 0x2b},
-       .stream = {0x0b, 0x04, 0x0a, 0x28},
-    },
-};
-
-#define MAX_EFFECTS 7
-static const u8 effects_table[MAX_EFFECTS][6] = {
-       {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x00},   /* Normal */
-       {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x04},   /* Repujar */
-       {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x20},   /* Monochrome */
-       {0xa8, 0xe8, 0xc6, 0xd2, 0xc0, 0x80},   /* Sepia */
-       {0xa8, 0xc8, 0xc6, 0x52, 0xc0, 0x02},   /* Croquis */
-       {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x10},   /* Sun Effect */
-       {0xa8, 0xc8, 0xc6, 0xd2, 0xc0, 0x40},   /* Negative */
-};
-
-#define GAMMA_MAX (15)
-static const u8 gamma_table[GAMMA_MAX+1][17] = {
-/* gamma table from cam1690.ini */
-       {0x00, 0x00, 0x01, 0x04, 0x08, 0x0e, 0x16, 0x21,        /* 0 */
-        0x2e, 0x3d, 0x50, 0x65, 0x7d, 0x99, 0xb8, 0xdb,
-        0xff},
-       {0x00, 0x01, 0x03, 0x08, 0x0e, 0x16, 0x21, 0x2d,        /* 1 */
-        0x3c, 0x4d, 0x60, 0x75, 0x8d, 0xa6, 0xc2, 0xe1,
-        0xff},
-       {0x00, 0x01, 0x05, 0x0b, 0x12, 0x1c, 0x28, 0x35,        /* 2 */
-        0x45, 0x56, 0x69, 0x7e, 0x95, 0xad, 0xc7, 0xe3,
-        0xff},
-       {0x00, 0x02, 0x07, 0x0f, 0x18, 0x24, 0x30, 0x3f,        /* 3 */
-        0x4f, 0x61, 0x73, 0x88, 0x9d, 0xb4, 0xcd, 0xe6,
-        0xff},
-       {0x00, 0x04, 0x0b, 0x15, 0x20, 0x2d, 0x3b, 0x4a,        /* 4 */
-        0x5b, 0x6c, 0x7f, 0x92, 0xa7, 0xbc, 0xd2, 0xe9,
-        0xff},
-       {0x00, 0x07, 0x11, 0x15, 0x20, 0x2d, 0x48, 0x58,        /* 5 */
-        0x68, 0x79, 0x8b, 0x9d, 0xb0, 0xc4, 0xd7, 0xec,
-        0xff},
-       {0x00, 0x0c, 0x1a, 0x29, 0x38, 0x47, 0x57, 0x67,        /* 6 */
-        0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee,
-        0xff},
-       {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,        /* 7 */
-        0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
-        0xff},
-       {0x00, 0x15, 0x27, 0x38, 0x49, 0x59, 0x69, 0x79,        /* 8 */
-        0x88, 0x97, 0xa7, 0xb6, 0xc4, 0xd3, 0xe2, 0xf0,
-        0xff},
-       {0x00, 0x1c, 0x30, 0x43, 0x54, 0x65, 0x75, 0x84,        /* 9 */
-        0x93, 0xa1, 0xb0, 0xbd, 0xca, 0xd8, 0xe5, 0xf2,
-        0xff},
-       {0x00, 0x24, 0x3b, 0x4f, 0x60, 0x70, 0x80, 0x8e,        /* 10 */
-        0x9c, 0xaa, 0xb7, 0xc4, 0xd0, 0xdc, 0xe8, 0xf3,
-        0xff},
-       {0x00, 0x2a, 0x3c, 0x5d, 0x6e, 0x7e, 0x8d, 0x9b,        /* 11 */
-        0xa8, 0xb4, 0xc0, 0xcb, 0xd6, 0xe1, 0xeb, 0xf5,
-        0xff},
-       {0x00, 0x3f, 0x5a, 0x6e, 0x7f, 0x8e, 0x9c, 0xa8,        /* 12 */
-        0xb4, 0xbf, 0xc9, 0xd3, 0xdc, 0xe5, 0xee, 0xf6,
-        0xff},
-       {0x00, 0x54, 0x6f, 0x83, 0x93, 0xa0, 0xad, 0xb7,        /* 13 */
-        0xc2, 0xcb, 0xd4, 0xdc, 0xe4, 0xeb, 0xf2, 0xf9,
-        0xff},
-       {0x00, 0x6e, 0x88, 0x9a, 0xa8, 0xb3, 0xbd, 0xc6,        /* 14 */
-        0xcf, 0xd6, 0xdd, 0xe3, 0xe9, 0xef, 0xf4, 0xfa,
-        0xff},
-       {0x00, 0x93, 0xa8, 0xb7, 0xc1, 0xca, 0xd2, 0xd8,        /* 15 */
-        0xde, 0xe3, 0xe8, 0xed, 0xf1, 0xf5, 0xf8, 0xfc,
-        0xff}
-};
-
-static const u8 tas5130a_sensor_init[][8] = {
-       {0x62, 0x08, 0x63, 0x70, 0x64, 0x1d, 0x60, 0x09},
-       {0x62, 0x20, 0x63, 0x01, 0x64, 0x02, 0x60, 0x09},
-       {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09},
-};
-
-static u8 sensor_reset[] = {0x61, 0x68, 0x62, 0xff, 0x60, 0x07};
-
-/* read 1 byte */
-static u8 reg_r(struct gspca_dev *gspca_dev,
-                  u16 index)
-{
-       usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       0,              /* request */
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,              /* value */
-                       index,
-                       gspca_dev->usb_buf, 1, 500);
-       return gspca_dev->usb_buf[0];
-}
-
-static void reg_w(struct gspca_dev *gspca_dev,
-                 u16 index)
-{
-       usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0, index,
-                       NULL, 0, 500);
-}
-
-static void reg_w_buf(struct gspca_dev *gspca_dev,
-                 const u8 *buffer, u16 len)
-{
-       if (len <= USB_BUF_SZ) {
-               memcpy(gspca_dev->usb_buf, buffer, len);
-               usb_control_msg(gspca_dev->dev,
-                               usb_sndctrlpipe(gspca_dev->dev, 0),
-                               0,
-                          USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                               0x01, 0,
-                               gspca_dev->usb_buf, len, 500);
-       } else {
-               u8 *tmpbuf;
-
-               tmpbuf = kmemdup(buffer, len, GFP_KERNEL);
-               if (!tmpbuf) {
-                       pr_err("Out of memory\n");
-                       return;
-               }
-               usb_control_msg(gspca_dev->dev,
-                               usb_sndctrlpipe(gspca_dev->dev, 0),
-                               0,
-                          USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                               0x01, 0,
-                               tmpbuf, len, 500);
-               kfree(tmpbuf);
-       }
-}
-
-/* write values to consecutive registers */
-static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
-                       u8 reg,
-                       const u8 *buffer, u16 len)
-{
-       int i;
-       u8 *p, *tmpbuf;
-
-       if (len * 2 <= USB_BUF_SZ) {
-               p = tmpbuf = gspca_dev->usb_buf;
-       } else {
-               p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
-               if (!tmpbuf) {
-                       pr_err("Out of memory\n");
-                       return;
-               }
-       }
-       i = len;
-       while (--i >= 0) {
-               *p++ = reg++;
-               *p++ = *buffer++;
-       }
-       usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0x01, 0,
-                       tmpbuf, len * 2, 500);
-       if (len * 2 > USB_BUF_SZ)
-               kfree(tmpbuf);
-}
-
-static void om6802_sensor_init(struct gspca_dev *gspca_dev)
-{
-       int i;
-       const u8 *p;
-       u8 byte;
-       u8 val[6] = {0x62, 0, 0x64, 0, 0x60, 0x05};
-       static const u8 sensor_init[] = {
-               0xdf, 0x6d,
-               0xdd, 0x18,
-               0x5a, 0xe0,
-               0x5c, 0x07,
-               0x5d, 0xb0,
-               0x5e, 0x1e,
-               0x60, 0x71,
-               0xef, 0x00,
-               0xe9, 0x00,
-               0xea, 0x00,
-               0x90, 0x24,
-               0x91, 0xb2,
-               0x82, 0x32,
-               0xfd, 0x41,
-               0x00                    /* table end */
-       };
-
-       reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
-       msleep(100);
-       i = 4;
-       while (--i > 0) {
-               byte = reg_r(gspca_dev, 0x0060);
-               if (!(byte & 0x01))
-                       break;
-               msleep(100);
-       }
-       byte = reg_r(gspca_dev, 0x0063);
-       if (byte != 0x17) {
-               pr_err("Bad sensor reset %02x\n", byte);
-               /* continue? */
-       }
-
-       p = sensor_init;
-       while (*p != 0) {
-               val[1] = *p++;
-               val[3] = *p++;
-               if (*p == 0)
-                       reg_w(gspca_dev, 0x3c80);
-               reg_w_buf(gspca_dev, val, sizeof val);
-               i = 4;
-               while (--i >= 0) {
-                       msleep(15);
-                       byte = reg_r(gspca_dev, 0x60);
-                       if (!(byte & 0x01))
-                               break;
-               }
-       }
-       msleep(15);
-       reg_w(gspca_dev, 0x3c80);
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                    const struct usb_device_id *id)
-{
-       struct cam *cam  = &gspca_dev->cam;
-
-       cam->cam_mode = vga_mode_t16;
-       cam->nmodes = ARRAY_SIZE(vga_mode_t16);
-
-       return 0;
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 brightness)
-{
-       u8 set6[4] = { 0x8f, 0x24, 0xc3, 0x00 };
-
-       if (brightness < 7) {
-               set6[1] = 0x26;
-               set6[3] = 0x70 - brightness * 0x10;
-       } else {
-               set6[3] = 0x00 + ((brightness - 7) * 0x10);
-       }
-
-       reg_w_buf(gspca_dev, set6, sizeof set6);
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, s32 contrast)
-{
-       u16 reg_to_write;
-
-       if (contrast < 7)
-               reg_to_write = 0x8ea9 - contrast * 0x200;
-       else
-               reg_to_write = 0x00a9 + (contrast - 7) * 0x200;
-
-       reg_w(gspca_dev, reg_to_write);
-}
-
-static void setcolors(struct gspca_dev *gspca_dev, s32 val)
-{
-       u16 reg_to_write;
-
-       reg_to_write = 0x80bb + val * 0x100;    /* was 0xc0 */
-       reg_w(gspca_dev, reg_to_write);
-}
-
-static void setgamma(struct gspca_dev *gspca_dev, s32 val)
-{
-       PDEBUG(D_CONF, "Gamma: %d", sd->gamma);
-       reg_w_ixbuf(gspca_dev, 0x90,
-               gamma_table[val], sizeof gamma_table[0]);
-}
-
-static void setawb_n_RGB(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 all_gain_reg[8] = {
-               0x87, 0x00, 0x88, 0x00, 0x89, 0x00, 0x80, 0x00 };
-       s32 red_gain, blue_gain, green_gain;
-
-       green_gain = sd->gain->val;
-
-       red_gain = green_gain + sd->red_balance->val;
-       if (red_gain > 0x40)
-               red_gain = 0x40;
-       else if (red_gain < 0x10)
-               red_gain = 0x10;
-
-       blue_gain = green_gain + sd->blue_balance->val;
-       if (blue_gain > 0x40)
-               blue_gain = 0x40;
-       else if (blue_gain < 0x10)
-               blue_gain = 0x10;
-
-       all_gain_reg[1] = red_gain;
-       all_gain_reg[3] = blue_gain;
-       all_gain_reg[5] = green_gain;
-       all_gain_reg[7] = sensor_data[sd->sensor].reg80;
-       if (!sd->awb->val)
-               all_gain_reg[7] &= ~0x04; /* AWB off */
-
-       reg_w_buf(gspca_dev, all_gain_reg, sizeof all_gain_reg);
-}
-
-static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
-{
-       u16 reg_to_write;
-
-       reg_to_write = 0x0aa6 + 0x1000 * val;
-
-       reg_w(gspca_dev, reg_to_write);
-}
-
-static void setfreq(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 reg66;
-       u8 freq[4] = { 0x66, 0x00, 0xa8, 0xe8 };
-
-       switch (sd->sensor) {
-       case SENSOR_LT168G:
-               if (val != 0)
-                       freq[3] = 0xa8;
-               reg66 = 0x41;
-               break;
-       case SENSOR_OM6802:
-               reg66 = 0xca;
-               break;
-       default:
-               reg66 = 0x40;
-               break;
-       }
-       switch (val) {
-       case 0:                         /* no flicker */
-               freq[3] = 0xf0;
-               break;
-       case 2:                         /* 60Hz */
-               reg66 &= ~0x40;
-               break;
-       }
-       freq[1] = reg66;
-
-       reg_w_buf(gspca_dev, freq, sizeof freq);
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       /* some of this registers are not really neded, because
-        * they are overriden by setbrigthness, setcontrast, etc,
-        * but wont hurt anyway, and can help someone with similar webcam
-        * to see the initial parameters.*/
-       struct sd *sd = (struct sd *) gspca_dev;
-       const struct additional_sensor_data *sensor;
-       int i;
-       u16 sensor_id;
-       u8 test_byte = 0;
-
-       static const u8 read_indexs[] =
-               { 0x0a, 0x0b, 0x66, 0x80, 0x81, 0x8e, 0x8f, 0xa5,
-                 0xa6, 0xa8, 0xbb, 0xbc, 0xc6, 0x00 };
-       static const u8 n1[] =
-                       {0x08, 0x03, 0x09, 0x03, 0x12, 0x04};
-       static const u8 n2[] =
-                       {0x08, 0x00};
-
-       sensor_id = (reg_r(gspca_dev, 0x06) << 8)
-                       | reg_r(gspca_dev, 0x07);
-       switch (sensor_id & 0xff0f) {
-       case 0x0801:
-               PDEBUG(D_PROBE, "sensor tas5130a");
-               sd->sensor = SENSOR_TAS5130A;
-               break;
-       case 0x0802:
-               PDEBUG(D_PROBE, "sensor lt168g");
-               sd->sensor = SENSOR_LT168G;
-               break;
-       case 0x0803:
-               PDEBUG(D_PROBE, "sensor 'other'");
-               sd->sensor = SENSOR_OTHER;
-               break;
-       case 0x0807:
-               PDEBUG(D_PROBE, "sensor om6802");
-               sd->sensor = SENSOR_OM6802;
-               break;
-       default:
-               pr_err("unknown sensor %04x\n", sensor_id);
-               return -EINVAL;
-       }
-
-       if (sd->sensor == SENSOR_OM6802) {
-               reg_w_buf(gspca_dev, n1, sizeof n1);
-               i = 5;
-               while (--i >= 0) {
-                       reg_w_buf(gspca_dev, sensor_reset, sizeof sensor_reset);
-                       test_byte = reg_r(gspca_dev, 0x0063);
-                       msleep(100);
-                       if (test_byte == 0x17)
-                               break;          /* OK */
-               }
-               if (i < 0) {
-                       pr_err("Bad sensor reset %02x\n", test_byte);
-                       return -EIO;
-               }
-               reg_w_buf(gspca_dev, n2, sizeof n2);
-       }
-
-       i = 0;
-       while (read_indexs[i] != 0x00) {
-               test_byte = reg_r(gspca_dev, read_indexs[i]);
-               PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", read_indexs[i],
-                      test_byte);
-               i++;
-       }
-
-       sensor = &sensor_data[sd->sensor];
-       reg_w_buf(gspca_dev, sensor->n3, sizeof sensor->n3);
-       reg_w_buf(gspca_dev, sensor->n4, sensor->n4sz);
-
-       if (sd->sensor == SENSOR_LT168G) {
-               test_byte = reg_r(gspca_dev, 0x80);
-               PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
-                      test_byte);
-               reg_w(gspca_dev, 0x6c80);
-       }
-
-       reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
-       reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
-       reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
-
-       reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
-       reg_w(gspca_dev, (sensor->reg80 << 8) + 0x80);
-       reg_w(gspca_dev, (sensor->reg8e << 8) + 0x8e);
-       reg_w(gspca_dev, (0x20 << 8) + 0x87);
-       reg_w(gspca_dev, (0x20 << 8) + 0x88);
-       reg_w(gspca_dev, (0x20 << 8) + 0x89);
-
-       reg_w_buf(gspca_dev, sensor->data5, sizeof sensor->data5);
-       reg_w_buf(gspca_dev, sensor->nset8, sizeof sensor->nset8);
-       reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
-
-       if (sd->sensor == SENSOR_LT168G) {
-               test_byte = reg_r(gspca_dev, 0x80);
-               PDEBUG(D_STREAM, "Reg 0x%02x = 0x%02x", 0x80,
-                      test_byte);
-               reg_w(gspca_dev, 0x6c80);
-       }
-
-       reg_w_ixbuf(gspca_dev, 0xd0, sensor->data1, sizeof sensor->data1);
-       reg_w_ixbuf(gspca_dev, 0xc7, sensor->data2, sizeof sensor->data2);
-       reg_w_ixbuf(gspca_dev, 0xe0, sensor->data3, sizeof sensor->data3);
-
-       return 0;
-}
-
-static void setmirror(struct gspca_dev *gspca_dev, s32 val)
-{
-       u8 hflipcmd[8] =
-               {0x62, 0x07, 0x63, 0x03, 0x64, 0x00, 0x60, 0x09};
-
-       if (val)
-               hflipcmd[3] = 0x01;
-
-       reg_w_buf(gspca_dev, hflipcmd, sizeof hflipcmd);
-}
-
-static void seteffect(struct gspca_dev *gspca_dev, s32 val)
-{
-       int idx = 0;
-
-       switch (val) {
-       case V4L2_COLORFX_NONE:
-               break;
-       case V4L2_COLORFX_BW:
-               idx = 2;
-               break;
-       case V4L2_COLORFX_SEPIA:
-               idx = 3;
-               break;
-       case V4L2_COLORFX_SKETCH:
-               idx = 4;
-               break;
-       case V4L2_COLORFX_NEGATIVE:
-               idx = 6;
-               break;
-       default:
-               break;
-       }
-
-       reg_w_buf(gspca_dev, effects_table[idx],
-                               sizeof effects_table[0]);
-
-       if (val == V4L2_COLORFX_SKETCH)
-               reg_w(gspca_dev, 0x4aa6);
-       else
-               reg_w(gspca_dev, 0xfaa6);
-}
-
-/* Is this really needed?
- * i added some module parameters for test with some users */
-static void poll_sensor(struct gspca_dev *gspca_dev)
-{
-       static const u8 poll1[] =
-               {0x67, 0x05, 0x68, 0x81, 0x69, 0x80, 0x6a, 0x82,
-                0x6b, 0x68, 0x6c, 0x69, 0x72, 0xd9, 0x73, 0x34,
-                0x74, 0x32, 0x75, 0x92, 0x76, 0x00, 0x09, 0x01,
-                0x60, 0x14};
-       static const u8 poll2[] =
-               {0x67, 0x02, 0x68, 0x71, 0x69, 0x72, 0x72, 0xa9,
-                0x73, 0x02, 0x73, 0x02, 0x60, 0x14};
-       static const u8 noise03[] =     /* (some differences / ms-drv) */
-               {0xa6, 0x0a, 0xea, 0xcf, 0xbe, 0x26, 0xb1, 0x5f,
-                0xa1, 0xb1, 0xda, 0x6b, 0xdb, 0x98, 0xdf, 0x0c,
-                0xc2, 0x80, 0xc3, 0x10};
-
-       PDEBUG(D_STREAM, "[Sensor requires polling]");
-       reg_w_buf(gspca_dev, poll1, sizeof poll1);
-       reg_w_buf(gspca_dev, poll2, sizeof poll2);
-       reg_w_buf(gspca_dev, noise03, sizeof noise03);
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       const struct additional_sensor_data *sensor;
-       int i, mode;
-       u8 t2[] = { 0x07, 0x00, 0x0d, 0x60, 0x0e, 0x80 };
-       static const u8 t3[] =
-               { 0x07, 0x00, 0x88, 0x02, 0x06, 0x00, 0xe7, 0x01 };
-
-       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-       switch (mode) {
-       case 0:         /* 640x480 (0x00) */
-               break;
-       case 1:         /* 352x288 */
-               t2[1] = 0x40;
-               break;
-       case 2:         /* 320x240 */
-               t2[1] = 0x10;
-               break;
-       case 3:         /* 176x144 */
-               t2[1] = 0x50;
-               break;
-       default:
-/*     case 4:          * 160x120 */
-               t2[1] = 0x20;
-               break;
-       }
-
-       switch (sd->sensor) {
-       case SENSOR_OM6802:
-               om6802_sensor_init(gspca_dev);
-               break;
-       case SENSOR_TAS5130A:
-               i = 0;
-               for (;;) {
-                       reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
-                                        sizeof tas5130a_sensor_init[0]);
-                       if (i >= ARRAY_SIZE(tas5130a_sensor_init) - 1)
-                               break;
-                       i++;
-               }
-               reg_w(gspca_dev, 0x3c80);
-               /* just in case and to keep sync with logs (for mine) */
-               reg_w_buf(gspca_dev, tas5130a_sensor_init[i],
-                                sizeof tas5130a_sensor_init[0]);
-               reg_w(gspca_dev, 0x3c80);
-               break;
-       }
-       sensor = &sensor_data[sd->sensor];
-       setfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->freq));
-       reg_r(gspca_dev, 0x0012);
-       reg_w_buf(gspca_dev, t2, sizeof t2);
-       reg_w_ixbuf(gspca_dev, 0xb3, t3, sizeof t3);
-       reg_w(gspca_dev, 0x0013);
-       msleep(15);
-       reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
-       reg_w_buf(gspca_dev, sensor->stream, sizeof sensor->stream);
-
-       if (sd->sensor == SENSOR_OM6802)
-               poll_sensor(gspca_dev);
-
-       return 0;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
-                       sizeof sensor_data[sd->sensor].stream);
-       reg_w_buf(gspca_dev, sensor_data[sd->sensor].stream,
-                       sizeof sensor_data[sd->sensor].stream);
-       if (sd->sensor == SENSOR_OM6802) {
-               msleep(20);
-               reg_w(gspca_dev, 0x0309);
-       }
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       /* If the last button state is pressed, release it now! */
-       if (sd->button_pressed) {
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
-               input_sync(gspca_dev->input_dev);
-               sd->button_pressed = 0;
-       }
-#endif
-}
-
-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;
-       int pkt_type;
-
-       if (data[0] == 0x5a) {
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-               if (len > 20) {
-                       u8 state = (data[20] & 0x80) ? 1 : 0;
-                       if (sd->button_pressed != state) {
-                               input_report_key(gspca_dev->input_dev,
-                                                KEY_CAMERA, state);
-                               input_sync(gspca_dev->input_dev);
-                               sd->button_pressed = state;
-                       }
-               }
-#endif
-               /* Control Packet, after this came the header again,
-                * but extra bytes came in the packet before this,
-                * sometimes an EOF arrives, sometimes not... */
-               return;
-       }
-       data += 2;
-       len -= 2;
-       if (data[0] == 0xff && data[1] == 0xd8)
-               pkt_type = FIRST_PACKET;
-       else if (data[len - 2] == 0xff && data[len - 1] == 0xd9)
-               pkt_type = LAST_PACKET;
-       else
-               pkt_type = INTER_PACKET;
-       gspca_frame_add(gspca_dev, pkt_type, data, len);
-}
-
-static int sd_g_volatile_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;
-       s32 red_gain, blue_gain, green_gain;
-
-       gspca_dev->usb_err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUTO_WHITE_BALANCE:
-               red_gain = reg_r(gspca_dev, 0x0087);
-               if (red_gain > 0x40)
-                       red_gain = 0x40;
-               else if (red_gain < 0x10)
-                       red_gain = 0x10;
-
-               blue_gain = reg_r(gspca_dev, 0x0088);
-               if (blue_gain > 0x40)
-                       blue_gain = 0x40;
-               else if (blue_gain < 0x10)
-                       blue_gain = 0x10;
-
-               green_gain = reg_r(gspca_dev, 0x0089);
-               if (green_gain > 0x40)
-                       green_gain = 0x40;
-               else if (green_gain < 0x10)
-                       green_gain = 0x10;
-
-               sd->gain->val = green_gain;
-               sd->red_balance->val = red_gain - green_gain;
-               sd->blue_balance->val = blue_gain - green_gain;
-               break;
-       }
-       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);
-
-       gspca_dev->usb_err = 0;
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               setcolors(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_GAMMA:
-               setgamma(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_HFLIP:
-               setmirror(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SHARPNESS:
-               setsharpness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_POWER_LINE_FREQUENCY:
-               setfreq(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_BACKLIGHT_COMPENSATION:
-               reg_w(gspca_dev, ctrl->val ? 0xf48e : 0xb48e);
-               break;
-       case V4L2_CID_AUTO_WHITE_BALANCE:
-               setawb_n_RGB(gspca_dev);
-               break;
-       case V4L2_CID_COLORFX:
-               seteffect(gspca_dev, ctrl->val);
-               break;
-       }
-       return gspca_dev->usb_err;
-}
-
-static const struct v4l2_ctrl_ops sd_ctrl_ops = {
-       .g_volatile_ctrl = sd_g_volatile_ctrl,
-       .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, 12);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 14, 1, 8);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 0x0d, 1, 7);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 0, 0xf, 1, 5);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAMMA, 0, GAMMA_MAX, 1, 10);
-       /* Activate lowlight, some apps dont bring up the
-          backlight_compensation control) */
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BACKLIGHT_COMPENSATION, 0, 1, 1, 1);
-       if (sd->sensor == SENSOR_TAS5130A)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                               V4L2_CID_HFLIP, 0, 1, 1, 0);
-       sd->awb = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
-       sd->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAIN, 0x10, 0x40, 1, 0x20);
-       sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BLUE_BALANCE, -0x30, 0x30, 1, 0);
-       sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_RED_BALANCE, -0x30, 0x30, 1, 0);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SHARPNESS, 0, 15, 1, 6);
-       v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
-                       V4L2_CID_COLORFX, V4L2_COLORFX_SKETCH,
-                       ~((1 << V4L2_COLORFX_NONE) |
-                         (1 << V4L2_COLORFX_BW) |
-                         (1 << V4L2_COLORFX_SEPIA) |
-                         (1 << V4L2_COLORFX_SKETCH) |
-                         (1 << V4L2_COLORFX_NEGATIVE)),
-                       V4L2_COLORFX_NONE);
-       sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
-                       V4L2_CID_POWER_LINE_FREQUENCY,
-                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 1,
-                       V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-
-       v4l2_ctrl_auto_cluster(4, &sd->awb, 0, true);
-
-       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,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .other_input = 1,
-#endif
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x17a1, 0x0128)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/topro.c b/drivers/media/video/gspca/topro.c
deleted file mode 100644 (file)
index a605524..0000000
+++ /dev/null
@@ -1,4969 +0,0 @@
-/*
- * Topro TP6800/6810 webcam driver.
- *
- * Copyright (C) 2011 Jean-François Moine (http://moinejf.free.fr)
- * Copyright (C) 2009 Anders Blomdell (anders.blomdell@control.lth.se)
- * Copyright (C) 2008 Thomas Champagne (lafeuil@gmail.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.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include "gspca.h"
-
-MODULE_DESCRIPTION("Topro TP6800/6810 gspca webcam driver");
-MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
-               "Anders Blomdell <anders.blomdell@control.lth.se>");
-MODULE_LICENSE("GPL");
-
-static int force_sensor = -1;
-
-/* JPEG header */
-static const u8 jpeg_head[] = {
-       0xff, 0xd8,                     /* jpeg */
-
-/* quantization table quality 50% */
-       0xff, 0xdb, 0x00, 0x84,         /* DQT */
-0,
-#define JPEG_QT0_OFFSET 7
-       0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e,
-       0x0d, 0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28,
-       0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23, 0x25,
-       0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33,
-       0x38, 0x37, 0x40, 0x48, 0x5c, 0x4e, 0x40, 0x44,
-       0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51, 0x57,
-       0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71,
-       0x79, 0x70, 0x64, 0x78, 0x5c, 0x65, 0x67, 0x63,
-1,
-#define JPEG_QT1_OFFSET 72
-       0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
-       0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-       0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-
-       /* Define Huffman table (thanks to Thomas Kaiser) */
-       0xff, 0xc4, 0x01, 0x5e,
-       0x00, 0x00, 0x02, 0x03,
-       0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
-       0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
-       0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
-       0x07, 0x05, 0x04, 0x06, 0x01, 0x00, 0x00, 0x57,
-       0x01, 0x02, 0x03, 0x00, 0x11, 0x04, 0x12, 0x21,
-       0x31, 0x13, 0x41, 0x51, 0x61, 0x05, 0x22, 0x32,
-       0x14, 0x71, 0x81, 0x91, 0x15, 0x23, 0x42, 0x52,
-       0x62, 0xa1, 0xb1, 0x06, 0x33, 0x72, 0xc1, 0xd1,
-       0x24, 0x43, 0x53, 0x82, 0x16, 0x34, 0x92, 0xa2,
-       0xe1, 0xf1, 0xf0, 0x07, 0x08, 0x17, 0x18, 0x25,
-       0x26, 0x27, 0x28, 0x35, 0x36, 0x37, 0x38, 0x44,
-       0x45, 0x46, 0x47, 0x48, 0x54, 0x55, 0x56, 0x57,
-       0x58, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x73,
-       0x74, 0x75, 0x76, 0x77, 0x78, 0x83, 0x84, 0x85,
-       0x86, 0x87, 0x88, 0x93, 0x94, 0x95, 0x96, 0x97,
-       0x98, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xb2,
-       0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xc2, 0xc3,
-       0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xd2, 0xd3, 0xd4,
-       0xd5, 0xd6, 0xd7, 0xd8, 0xe2, 0xe3, 0xe4, 0xe5,
-       0xe6, 0xe7, 0xe8, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
-       0xf7, 0xf8, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-       0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
-       0x05, 0x06, 0x07, 0x08, 0x09, 0x11, 0x00, 0x02,
-       0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05,
-       0x04, 0x06, 0x01, 0x00, 0x00, 0x57, 0x00, 0x01,
-       0x11, 0x02, 0x21, 0x03, 0x12, 0x31, 0x41, 0x13,
-       0x22, 0x51, 0x61, 0x04, 0x32, 0x71, 0x05, 0x14,
-       0x23, 0x42, 0x33, 0x52, 0x81, 0x91, 0xa1, 0xb1,
-       0xf0, 0x06, 0x15, 0xc1, 0xd1, 0xe1, 0x24, 0x43,
-       0x62, 0xf1, 0x16, 0x25, 0x34, 0x53, 0x72, 0x82,
-       0x92, 0x07, 0x08, 0x17, 0x18, 0x26, 0x27, 0x28,
-       0x35, 0x36, 0x37, 0x38, 0x44, 0x45, 0x46, 0x47,
-       0x48, 0x54, 0x55, 0x56, 0x57, 0x58, 0x63, 0x64,
-       0x65, 0x66, 0x67, 0x68, 0x73, 0x74, 0x75, 0x76,
-       0x77, 0x78, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
-       0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0xa2, 0xa3,
-       0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xb2, 0xb3, 0xb4,
-       0xb5, 0xb6, 0xb7, 0xb8, 0xc2, 0xc3, 0xc4, 0xc5,
-       0xc6, 0xc7, 0xc8, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
-       0xd7, 0xd8, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
-       0xe8, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
-       0xff, 0xc0, 0x00, 0x11,         /* SOF0 (start of frame 0 */
-       0x08,                           /* data precision */
-#define JPEG_HEIGHT_OFFSET 493
-       0x01, 0xe0,                     /* height */
-       0x02, 0x80,                     /* width */
-       0x03,                           /* component number */
-               0x01,
-                       0x21,           /* samples Y = jpeg 422 */
-                       0x00,           /* quant Y */
-               0x02, 0x11, 0x01,       /* samples CbCr - quant CbCr */
-               0x03, 0x11, 0x01,
-
-       0xff, 0xda, 0x00, 0x0c,         /* SOS (start of scan) */
-       0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
-#define JPEG_HDR_SZ 521
-};
-
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-       struct v4l2_ctrl *jpegqual;
-       struct v4l2_ctrl *sharpness;
-       struct v4l2_ctrl *gamma;
-       struct v4l2_ctrl *blue;
-       struct v4l2_ctrl *red;
-
-       u8 framerate;
-       u8 quality;             /* webcam current JPEG quality (0..16) */
-       s8 ag_cnt;              /* autogain / start counter for tp6810 */
-#define AG_CNT_START 13                /* check gain every N frames */
-
-       u8 bridge;
-       u8 sensor;
-
-       u8 jpeg_hdr[JPEG_HDR_SZ];
-};
-
-enum bridges {
-       BRIDGE_TP6800,
-       BRIDGE_TP6810,
-};
-
-enum sensors {
-       SENSOR_CX0342,
-       SENSOR_SOI763A,         /* ~= ov7630 / ov7648 */
-       NSENSORS
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 4 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG}
-};
-
-/*
- * JPEG quality
- * index: webcam compression
- * value: JPEG quality in %
- */
-static const u8 jpeg_q[17] = {
-       88, 77, 67, 57, 55, 55, 45, 45, 36, 36, 30, 30, 26, 26, 22, 22, 94
-};
-
-#define BULK_OUT_SIZE          0x20
-#if BULK_OUT_SIZE > USB_BUF_SZ
-#error "USB buffer too small"
-#endif
-
-static const u8 rates[] = {30, 20, 15, 10, 7, 5};
-static const struct framerates framerates[] = {
-       {
-               .rates = rates,
-               .nrates = ARRAY_SIZE(rates)
-       },
-       {
-               .rates = rates,
-               .nrates = ARRAY_SIZE(rates)
-       }
-};
-static const u8 rates_6810[] = {30, 15, 10, 7, 5};
-static const struct framerates framerates_6810[] = {
-       {
-               .rates = rates_6810,
-               .nrates = ARRAY_SIZE(rates_6810)
-       },
-       {
-               .rates = rates_6810,
-               .nrates = ARRAY_SIZE(rates_6810)
-       }
-};
-
-/*
- * webcam quality in %
- * the last value is the ultra fine quality
- */
-
-/* TP6800 register offsets */
-#define TP6800_R10_SIF_TYPE            0x10
-#define TP6800_R11_SIF_CONTROL         0x11
-#define TP6800_R12_SIF_ADDR_S          0x12
-#define TP6800_R13_SIF_TX_DATA         0x13
-#define TP6800_R14_SIF_RX_DATA         0x14
-#define TP6800_R15_GPIO_PU             0x15
-#define TP6800_R16_GPIO_PD             0x16
-#define TP6800_R17_GPIO_IO             0x17
-#define TP6800_R18_GPIO_DATA           0x18
-#define TP6800_R19_SIF_ADDR_S2         0x19
-#define TP6800_R1A_SIF_TX_DATA2                0x1a
-#define TP6800_R1B_SIF_RX_DATA2                0x1b
-#define TP6800_R21_ENDP_1_CTL          0x21
-#define TP6800_R2F_TIMING_CFG          0x2f
-#define TP6800_R30_SENSOR_CFG          0x30
-#define TP6800_R31_PIXEL_START         0x31
-#define TP6800_R32_PIXEL_END_L         0x32
-#define TP6800_R33_PIXEL_END_H         0x33
-#define TP6800_R34_LINE_START          0x34
-#define TP6800_R35_LINE_END_L          0x35
-#define TP6800_R36_LINE_END_H          0x36
-#define TP6800_R37_FRONT_DARK_ST       0x37
-#define TP6800_R38_FRONT_DARK_END      0x38
-#define TP6800_R39_REAR_DARK_ST_L      0x39
-#define TP6800_R3A_REAR_DARK_ST_H      0x3a
-#define TP6800_R3B_REAR_DARK_END_L     0x3b
-#define TP6800_R3C_REAR_DARK_END_H     0x3c
-#define TP6800_R3D_HORIZ_DARK_LINE_L   0x3d
-#define TP6800_R3E_HORIZ_DARK_LINE_H   0x3e
-#define TP6800_R3F_FRAME_RATE          0x3f
-#define TP6800_R50                     0x50
-#define TP6800_R51                     0x51
-#define TP6800_R52                     0x52
-#define TP6800_R53                     0x53
-#define TP6800_R54_DARK_CFG            0x54
-#define TP6800_R55_GAMMA_R             0x55
-#define TP6800_R56_GAMMA_G             0x56
-#define TP6800_R57_GAMMA_B             0x57
-#define TP6800_R5C_EDGE_THRLD          0x5c
-#define TP6800_R5D_DEMOSAIC_CFG                0x5d
-#define TP6800_R78_FORMAT              0x78
-#define TP6800_R79_QUALITY             0x79
-#define TP6800_R7A_BLK_THRLD           0x7a
-
-/* CX0342 register offsets */
-
-#define CX0342_SENSOR_ID               0x00
-#define CX0342_VERSION_NO              0x01
-#define CX0342_ORG_X_L                 0x02
-#define CX0342_ORG_X_H                 0x03
-#define CX0342_ORG_Y_L                 0x04
-#define CX0342_ORG_Y_H                 0x05
-#define CX0342_STOP_X_L                        0x06
-#define CX0342_STOP_X_H                        0x07
-#define CX0342_STOP_Y_L                        0x08
-#define CX0342_STOP_Y_H                        0x09
-#define CX0342_FRAME_WIDTH_L           0x0a
-#define CX0342_FRAME_WIDTH_H           0x0b
-#define CX0342_FRAME_HEIGH_L           0x0c
-#define CX0342_FRAME_HEIGH_H           0x0d
-#define CX0342_EXPO_LINE_L             0x10
-#define CX0342_EXPO_LINE_H             0x11
-#define CX0342_EXPO_CLK_L              0x12
-#define CX0342_EXPO_CLK_H              0x13
-#define CX0342_RAW_GRGAIN_L            0x14
-#define CX0342_RAW_GRGAIN_H            0x15
-#define CX0342_RAW_GBGAIN_L            0x16
-#define CX0342_RAW_GBGAIN_H            0x17
-#define CX0342_RAW_RGAIN_L             0x18
-#define CX0342_RAW_RGAIN_H             0x19
-#define CX0342_RAW_BGAIN_L             0x1a
-#define CX0342_RAW_BGAIN_H             0x1b
-#define CX0342_GLOBAL_GAIN             0x1c
-#define CX0342_SYS_CTRL_0              0x20
-#define CX0342_SYS_CTRL_1              0x21
-#define CX0342_SYS_CTRL_2              0x22
-#define CX0342_BYPASS_MODE             0x23
-#define CX0342_SYS_CTRL_3              0x24
-#define CX0342_TIMING_EN               0x25
-#define CX0342_OUTPUT_CTRL             0x26
-#define CX0342_AUTO_ADC_CALIB          0x27
-#define CX0342_SYS_CTRL_4              0x28
-#define CX0342_ADCGN                   0x30
-#define CX0342_SLPCR                   0x31
-#define CX0342_SLPFN_LO                        0x32
-#define CX0342_ADC_CTL                 0x33
-#define CX0342_LVRST_BLBIAS            0x34
-#define CX0342_VTHSEL                  0x35
-#define CX0342_RAMP_RIV                        0x36
-#define CX0342_LDOSEL                  0x37
-#define CX0342_CLOCK_GEN               0x40
-#define CX0342_SOFT_RESET              0x41
-#define CX0342_PLL                     0x42
-#define CX0342_DR_ENH_PULSE_OFFSET_L   0x43
-#define CX0342_DR_ENH_PULSE_OFFSET_H   0x44
-#define CX0342_DR_ENH_PULSE_POS_L      0x45
-#define CX0342_DR_ENH_PULSE_POS_H      0x46
-#define CX0342_DR_ENH_PULSE_WIDTH      0x47
-#define CX0342_AS_CURRENT_CNT_L                0x48
-#define CX0342_AS_CURRENT_CNT_H                0x49
-#define CX0342_AS_PREVIOUS_CNT_L       0x4a
-#define CX0342_AS_PREVIOUS_CNT_H       0x4b
-#define CX0342_SPV_VALUE_L             0x4c
-#define CX0342_SPV_VALUE_H             0x4d
-#define CX0342_GPXLTHD_L               0x50
-#define CX0342_GPXLTHD_H               0x51
-#define CX0342_RBPXLTHD_L              0x52
-#define CX0342_RBPXLTHD_H              0x53
-#define CX0342_PLANETHD_L              0x54
-#define CX0342_PLANETHD_H              0x55
-#define CX0342_ROWDARK_TH              0x56
-#define CX0342_ROWDARK_TOL             0x57
-#define CX0342_RB_GAP_L                        0x58
-#define CX0342_RB_GAP_H                        0x59
-#define CX0342_G_GAP_L                 0x5a
-#define CX0342_G_GAP_H                 0x5b
-#define CX0342_AUTO_ROW_DARK           0x60
-#define CX0342_MANUAL_DARK_VALUE       0x61
-#define CX0342_GB_DARK_OFFSET          0x62
-#define CX0342_GR_DARK_OFFSET          0x63
-#define CX0342_RED_DARK_OFFSET         0x64
-#define CX0342_BLUE_DARK_OFFSET                0x65
-#define CX0342_DATA_SCALING_MULTI      0x66
-#define CX0342_AUTOD_Q_FRAME           0x67
-#define CX0342_AUTOD_ALLOW_VARI                0x68
-#define CX0342_AUTO_DARK_VALUE_L       0x69
-#define CX0342_AUTO_DARK_VALUE_H       0x6a
-#define CX0342_IO_CTRL_0               0x70
-#define CX0342_IO_CTRL_1               0x71
-#define CX0342_IO_CTRL_2               0x72
-#define CX0342_IDLE_CTRL               0x73
-#define CX0342_TEST_MODE               0x74
-#define CX0342_FRAME_FIX_DATA_TEST     0x75
-#define CX0342_FRAME_CNT_TEST          0x76
-#define CX0342_RST_OVERFLOW_L          0x80
-#define CX0342_RST_OVERFLOW_H          0x81
-#define CX0342_RST_UNDERFLOW_L         0x82
-#define CX0342_RST_UNDERFLOW_H         0x83
-#define CX0342_DATA_OVERFLOW_L         0x84
-#define CX0342_DATA_OVERFLOW_H         0x85
-#define CX0342_DATA_UNDERFLOW_L                0x86
-#define CX0342_DATA_UNDERFLOW_H                0x87
-#define CX0342_CHANNEL_0_0_L_irst      0x90
-#define CX0342_CHANNEL_0_0_H_irst      0x91
-#define CX0342_CHANNEL_0_1_L_irst      0x92
-#define CX0342_CHANNEL_0_1_H_irst      0x93
-#define CX0342_CHANNEL_0_2_L_irst      0x94
-#define CX0342_CHANNEL_0_2_H_irst      0x95
-#define CX0342_CHANNEL_0_3_L_irst      0x96
-#define CX0342_CHANNEL_0_3_H_irst      0x97
-#define CX0342_CHANNEL_0_4_L_irst      0x98
-#define CX0342_CHANNEL_0_4_H_irst      0x99
-#define CX0342_CHANNEL_0_5_L_irst      0x9a
-#define CX0342_CHANNEL_0_5_H_irst      0x9b
-#define CX0342_CHANNEL_0_6_L_irst      0x9c
-#define CX0342_CHANNEL_0_6_H_irst      0x9d
-#define CX0342_CHANNEL_0_7_L_irst      0x9e
-#define CX0342_CHANNEL_0_7_H_irst      0x9f
-#define CX0342_CHANNEL_1_0_L_itx       0xa0
-#define CX0342_CHANNEL_1_0_H_itx       0xa1
-#define CX0342_CHANNEL_1_1_L_itx       0xa2
-#define CX0342_CHANNEL_1_1_H_itx       0xa3
-#define CX0342_CHANNEL_1_2_L_itx       0xa4
-#define CX0342_CHANNEL_1_2_H_itx       0xa5
-#define CX0342_CHANNEL_1_3_L_itx       0xa6
-#define CX0342_CHANNEL_1_3_H_itx       0xa7
-#define CX0342_CHANNEL_1_4_L_itx       0xa8
-#define CX0342_CHANNEL_1_4_H_itx       0xa9
-#define CX0342_CHANNEL_1_5_L_itx       0xaa
-#define CX0342_CHANNEL_1_5_H_itx       0xab
-#define CX0342_CHANNEL_1_6_L_itx       0xac
-#define CX0342_CHANNEL_1_6_H_itx       0xad
-#define CX0342_CHANNEL_1_7_L_itx       0xae
-#define CX0342_CHANNEL_1_7_H_itx       0xaf
-#define CX0342_CHANNEL_2_0_L_iwl       0xb0
-#define CX0342_CHANNEL_2_0_H_iwl       0xb1
-#define CX0342_CHANNEL_2_1_L_iwl       0xb2
-#define CX0342_CHANNEL_2_1_H_iwl       0xb3
-#define CX0342_CHANNEL_2_2_L_iwl       0xb4
-#define CX0342_CHANNEL_2_2_H_iwl       0xb5
-#define CX0342_CHANNEL_2_3_L_iwl       0xb6
-#define CX0342_CHANNEL_2_3_H_iwl       0xb7
-#define CX0342_CHANNEL_2_4_L_iwl       0xb8
-#define CX0342_CHANNEL_2_4_H_iwl       0xb9
-#define CX0342_CHANNEL_2_5_L_iwl       0xba
-#define CX0342_CHANNEL_2_5_H_iwl       0xbb
-#define CX0342_CHANNEL_2_6_L_iwl       0xbc
-#define CX0342_CHANNEL_2_6_H_iwl       0xbd
-#define CX0342_CHANNEL_2_7_L_iwl       0xbe
-#define CX0342_CHANNEL_2_7_H_iwl       0xbf
-#define CX0342_CHANNEL_3_0_L_ensp      0xc0
-#define CX0342_CHANNEL_3_0_H_ensp      0xc1
-#define CX0342_CHANNEL_3_1_L_ensp      0xc2
-#define CX0342_CHANNEL_3_1_H_ensp      0xc3
-#define CX0342_CHANNEL_3_2_L_ensp      0xc4
-#define CX0342_CHANNEL_3_2_H_ensp      0xc5
-#define CX0342_CHANNEL_3_3_L_ensp      0xc6
-#define CX0342_CHANNEL_3_3_H_ensp      0xc7
-#define CX0342_CHANNEL_3_4_L_ensp      0xc8
-#define CX0342_CHANNEL_3_4_H_ensp      0xc9
-#define CX0342_CHANNEL_3_5_L_ensp      0xca
-#define CX0342_CHANNEL_3_5_H_ensp      0xcb
-#define CX0342_CHANNEL_3_6_L_ensp      0xcc
-#define CX0342_CHANNEL_3_6_H_ensp      0xcd
-#define CX0342_CHANNEL_3_7_L_ensp      0xce
-#define CX0342_CHANNEL_3_7_H_ensp      0xcf
-#define CX0342_CHANNEL_4_0_L_sela      0xd0
-#define CX0342_CHANNEL_4_0_H_sela      0xd1
-#define CX0342_CHANNEL_4_1_L_sela      0xd2
-#define CX0342_CHANNEL_4_1_H_sela      0xd3
-#define CX0342_CHANNEL_5_0_L_intla     0xe0
-#define CX0342_CHANNEL_5_0_H_intla     0xe1
-#define CX0342_CHANNEL_5_1_L_intla     0xe2
-#define CX0342_CHANNEL_5_1_H_intla     0xe3
-#define CX0342_CHANNEL_5_2_L_intla     0xe4
-#define CX0342_CHANNEL_5_2_H_intla     0xe5
-#define CX0342_CHANNEL_5_3_L_intla     0xe6
-#define CX0342_CHANNEL_5_3_H_intla     0xe7
-#define CX0342_CHANNEL_6_0_L_xa_sel_pos 0xf0
-#define CX0342_CHANNEL_6_0_H_xa_sel_pos 0xf1
-#define CX0342_CHANNEL_7_1_L_cds_pos   0xf2
-#define CX0342_CHANNEL_7_1_H_cds_pos   0xf3
-#define CX0342_SENSOR_HEIGHT_L         0xfb
-#define CX0342_SENSOR_HEIGHT_H         0xfc
-#define CX0342_SENSOR_WIDTH_L          0xfd
-#define CX0342_SENSOR_WIDTH_H          0xfe
-#define CX0342_VSYNC_HSYNC_READ                0xff
-
-struct cmd {
-       u8 reg;
-       u8 val;
-};
-
-static const u8 DQT[17][130] = {
-       /* Define quantization table (thanks to Thomas Kaiser) */
-       {                       /* Quality 0 */
-        0x00,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x01,
-        0x04, 0x04, 0x04, 0x06, 0x05, 0x06, 0x0b, 0x06,
-        0x06, 0x0b, 0x18, 0x10, 0x0e, 0x10, 0x18, 0x18,
-        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-        },
-       {                       /* Quality 1 */
-        0x00,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x09, 0x09, 0x09, 0x09, 0x09,
-        0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
-        0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
-        0x01,
-        0x08, 0x09, 0x09, 0x0c, 0x0a, 0x0c, 0x17, 0x0d,
-        0x0d, 0x17, 0x31, 0x21, 0x1c, 0x21, 0x31, 0x31,
-        0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
-        0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
-        0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
-        0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
-        0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
-        0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
-        },
-       {                       /* Quality 2 */
-        0x00,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x06, 0x06, 0x06, 0x04, 0x04, 0x04,
-        0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-        0x06, 0x06, 0x06, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
-        0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
-        0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
-        0x01,
-        0x0c, 0x0d, 0x0d, 0x12, 0x0f, 0x12, 0x23, 0x13,
-        0x13, 0x23, 0x4a, 0x31, 0x2a, 0x31, 0x4a, 0x4a,
-        0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
-        0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
-        0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
-        0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
-        0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
-        0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
-        },
-       {                       /* Quality 3 */
-        0x00,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04,
-        0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-        0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-        0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-        0x08, 0x08, 0x08, 0x13, 0x13, 0x13, 0x13, 0x13,
-        0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
-        0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
-        0x01,
-        0x11, 0x12, 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a,
-        0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42, 0x63, 0x63,
-        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-        0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-        },
-       {                       /* Quality 4 */
-        0x00,
-        0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-        0x05, 0x05, 0x0a, 0x0a, 0x0a, 0x05, 0x05, 0x05,
-        0x05, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-        0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-        0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-        0x0a, 0x0a, 0x0a, 0x17, 0x17, 0x17, 0x17, 0x17,
-        0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
-        0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
-        0x01,
-        0x11, 0x16, 0x16, 0x1e, 0x1a, 0x1e, 0x3a, 0x20,
-        0x20, 0x3a, 0x7b, 0x52, 0x46, 0x52, 0x7b, 0x7b,
-        0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
-        0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
-        0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
-        0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
-        0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
-        0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
-        },
-       {                       /* Quality 5 */
-        0x00,
-        0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-        0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x06, 0x06, 0x06,
-        0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-        0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-        0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-        0x0c, 0x0c, 0x0c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
-        0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
-        0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
-        0x01,
-        0x11, 0x1b, 0x1b, 0x24, 0x1f, 0x24, 0x46, 0x27,
-        0x27, 0x46, 0x94, 0x63, 0x54, 0x63, 0x94, 0x94,
-        0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
-        0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
-        0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
-        0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
-        0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
-        0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
-        },
-       {                       /* Quality 6 */
-        0x00,
-        0x05, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-        0x07, 0x07, 0x0e, 0x0e, 0x0e, 0x07, 0x07, 0x07,
-        0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
-        0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
-        0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
-        0x0e, 0x0e, 0x0e, 0x21, 0x21, 0x21, 0x21, 0x21,
-        0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
-        0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
-        0x01,
-        0x15, 0x1f, 0x1f, 0x2a, 0x24, 0x2a, 0x52, 0x2d,
-        0x2d, 0x52, 0xad, 0x73, 0x62, 0x73, 0xad, 0xad,
-        0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
-        0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
-        0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
-        0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
-        0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
-        0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
-        },
-       {                       /* Quality 7 */
-        0x00,
-        0x05, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-        0x08, 0x08, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08,
-        0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-        0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-        0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-        0x10, 0x10, 0x10, 0x26, 0x26, 0x26, 0x26, 0x26,
-        0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
-        0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
-        0x01,
-        0x15, 0x24, 0x24, 0x30, 0x2a, 0x30, 0x5e, 0x34,
-        0x34, 0x5e, 0xc6, 0x84, 0x70, 0x84, 0xc6, 0xc6,
-        0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-        0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-        0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-        0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-        0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-        0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-        },
-       {                       /* Quality 8 */
-        0x00,
-        0x06, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-        0x0a, 0x0a, 0x14, 0x14, 0x14, 0x0a, 0x0a, 0x0a,
-        0x0a, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
-        0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
-        0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
-        0x14, 0x14, 0x14, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
-        0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
-        0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
-        0x01,
-        0x19, 0x2d, 0x2d, 0x3c, 0x34, 0x3c, 0x75, 0x41,
-        0x41, 0x75, 0xf7, 0xa5, 0x8c, 0xa5, 0xf7, 0xf7,
-        0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
-        0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
-        0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
-        0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
-        0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
-        0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
-        },
-       {                       /* Quality 9 */
-        0x00,
-        0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-        0x0c, 0x0c, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c,
-        0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-        0x18, 0x18, 0x18, 0x39, 0x39, 0x39, 0x39, 0x39,
-        0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
-        0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
-        0x01,
-        0x19, 0x36, 0x36, 0x48, 0x3f, 0x48, 0x8d, 0x4e,
-        0x4e, 0x8d, 0xff, 0xc6, 0xa8, 0xc6, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        },
-       {                       /* Quality 10 */
-        0x00,
-        0x07, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
-        0x0e, 0x0e, 0x1c, 0x1c, 0x1c, 0x0e, 0x0e, 0x0e,
-        0x0e, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
-        0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
-        0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
-        0x1c, 0x1c, 0x1c, 0x42, 0x42, 0x42, 0x42, 0x42,
-        0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
-        0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
-        0x01,
-        0x1d, 0x3f, 0x3f, 0x54, 0x49, 0x54, 0xa4, 0x5b,
-        0x5b, 0xa4, 0xff, 0xe7, 0xc4, 0xe7, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        },
-       {                       /* Quality 11 */
-        0x00,
-        0x07, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-        0x10, 0x10, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10,
-        0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-        0x20, 0x20, 0x20, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
-        0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
-        0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
-        0x01,
-        0x1d, 0x48, 0x48, 0x60, 0x54, 0x60, 0xbc, 0x68,
-        0x68, 0xbc, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        },
-       {                       /* Quality 12 */
-        0x00,
-        0x08, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
-        0x14, 0x14, 0x28, 0x28, 0x28, 0x14, 0x14, 0x14,
-        0x14, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-        0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-        0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-        0x28, 0x28, 0x28, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
-        0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
-        0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
-        0x01,
-        0x22, 0x5a, 0x5a, 0x78, 0x69, 0x78, 0xeb, 0x82,
-        0x82, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        },
-       {                       /* Quality 13 */
-        0x00,
-        0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
-        0x18, 0x18, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18,
-        0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
-        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
-        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
-        0x30, 0x30, 0x30, 0x72, 0x72, 0x72, 0x72, 0x72,
-        0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
-        0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
-        0x01,
-        0x22, 0x6c, 0x6c, 0x90, 0x7e, 0x90, 0xff, 0x9c,
-        0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        },
-       {                       /* Quality 14 */
-        0x00,
-        0x0a, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
-        0x1c, 0x1c, 0x38, 0x38, 0x38, 0x1c, 0x1c, 0x1c,
-        0x1c, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
-        0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
-        0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
-        0x38, 0x38, 0x38, 0x85, 0x85, 0x85, 0x85, 0x85,
-        0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
-        0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
-        0x01,
-        0x2a, 0x7e, 0x7e, 0xa8, 0x93, 0xa8, 0xff, 0xb6,
-        0xb6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        },
-       {                       /* Quality 15 */
-        0x00,
-        0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-        0x20, 0x20, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20,
-        0x20, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
-        0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
-        0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
-        0x40, 0x40, 0x40, 0x98, 0x98, 0x98, 0x98, 0x98,
-        0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
-        0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
-        0x01,
-        0x2a, 0x90, 0x90, 0xc0, 0xa8, 0xc0, 0xff, 0xd0,
-        0xd0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-        },
-       {                       /* Quality 16-31 */
-        0x00,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x01,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-        }
-};
-
-static const struct cmd tp6810_cx_init_common[] = {
-       {0x1c, 0x00},
-       {TP6800_R10_SIF_TYPE, 0x00},
-       {0x4e, 0x00},
-       {0x4f, 0x00},
-       {TP6800_R50, 0xff},
-       {TP6800_R51, 0x03},
-       {0x00, 0x07},
-       {TP6800_R79_QUALITY, 0x03},
-       {TP6800_R2F_TIMING_CFG, 0x37},
-       {TP6800_R30_SENSOR_CFG, 0x10},
-       {TP6800_R21_ENDP_1_CTL, 0x00},
-       {TP6800_R52, 0x40},
-       {TP6800_R53, 0x40},
-       {TP6800_R54_DARK_CFG, 0x40},
-       {TP6800_R30_SENSOR_CFG, 0x18},
-       {0x4b, 0x00},
-       {TP6800_R3F_FRAME_RATE, 0x83},
-       {TP6800_R79_QUALITY, 0x05},
-       {TP6800_R21_ENDP_1_CTL, 0x00},
-       {0x7c, 0x04},
-       {0x25, 0x14},
-       {0x26, 0x0f},
-       {0x7b, 0x10},
-};
-
-static const struct cmd tp6810_ov_init_common[] = {
-       {0x1c, 0x00},
-       {TP6800_R10_SIF_TYPE, 0x00},
-       {0x4e, 0x00},
-       {0x4f, 0x00},
-       {TP6800_R50, 0xff},
-       {TP6800_R51, 0x03},
-       {0x00, 0x07},
-       {TP6800_R52, 0x40},
-       {TP6800_R53, 0x40},
-       {TP6800_R54_DARK_CFG, 0x40},
-       {TP6800_R79_QUALITY, 0x03},
-       {TP6800_R2F_TIMING_CFG, 0x17},
-       {TP6800_R30_SENSOR_CFG, 0x18},
-       {TP6800_R21_ENDP_1_CTL, 0x00},
-       {TP6800_R3F_FRAME_RATE, 0x86},
-       {0x25, 0x18},
-       {0x26, 0x0f},
-       {0x7b, 0x90},
-};
-
-static const struct cmd tp6810_bridge_start[] = {
-       {0x59, 0x88},
-       {0x5a, 0x0f},
-       {0x5b, 0x4e},
-       {TP6800_R5C_EDGE_THRLD, 0x63},
-       {TP6800_R5D_DEMOSAIC_CFG, 0x00},
-       {0x03, 0x7f},
-       {0x04, 0x80},
-       {0x06, 0x00},
-       {0x00, 0x00},
-};
-
-static const struct cmd tp6810_late_start[] = {
-       {0x7d, 0x01},
-       {0xb0, 0x04},
-       {0xb1, 0x04},
-       {0xb2, 0x04},
-       {0xb3, 0x04},
-       {0xb4, 0x04},
-       {0xb5, 0x04},
-       {0xb6, 0x08},
-       {0xb7, 0x08},
-       {0xb8, 0x04},
-       {0xb9, 0x04},
-       {0xba, 0x04},
-       {0xbb, 0x04},
-       {0xbc, 0x04},
-       {0xbd, 0x08},
-       {0xbe, 0x08},
-       {0xbf, 0x08},
-       {0xc0, 0x04},
-       {0xc1, 0x04},
-       {0xc2, 0x08},
-       {0xc3, 0x08},
-       {0xc4, 0x08},
-       {0xc5, 0x08},
-       {0xc6, 0x08},
-       {0xc7, 0x13},
-       {0xc8, 0x04},
-       {0xc9, 0x08},
-       {0xca, 0x08},
-       {0xcb, 0x08},
-       {0xcc, 0x08},
-       {0xcd, 0x08},
-       {0xce, 0x13},
-       {0xcf, 0x13},
-       {0xd0, 0x08},
-       {0xd1, 0x08},
-       {0xd2, 0x08},
-       {0xd3, 0x08},
-       {0xd4, 0x08},
-       {0xd5, 0x13},
-       {0xd6, 0x13},
-       {0xd7, 0x13},
-       {0xd8, 0x08},
-       {0xd9, 0x08},
-       {0xda, 0x08},
-       {0xdb, 0x08},
-       {0xdc, 0x13},
-       {0xdd, 0x13},
-       {0xde, 0x13},
-       {0xdf, 0x13},
-       {0xe0, 0x08},
-       {0xe1, 0x08},
-       {0xe2, 0x08},
-       {0xe3, 0x13},
-       {0xe4, 0x13},
-       {0xe5, 0x13},
-       {0xe6, 0x13},
-       {0xe7, 0x13},
-       {0xe8, 0x08},
-       {0xe9, 0x08},
-       {0xea, 0x13},
-       {0xeb, 0x13},
-       {0xec, 0x13},
-       {0xed, 0x13},
-       {0xee, 0x13},
-       {0xef, 0x13},
-       {0x7d, 0x02},
-
-       /* later after isoc start */
-       {0x7d, 0x08},
-       {0x7d, 0x00},
-};
-
-static const struct cmd cx0342_timing_seq[] = {
-       {CX0342_CHANNEL_0_1_L_irst, 0x20},
-       {CX0342_CHANNEL_0_2_L_irst, 0x24},
-       {CX0342_CHANNEL_0_2_H_irst, 0x00},
-       {CX0342_CHANNEL_0_3_L_irst, 0x2f},
-       {CX0342_CHANNEL_0_3_H_irst, 0x00},
-       {CX0342_CHANNEL_1_0_L_itx, 0x02},
-       {CX0342_CHANNEL_1_0_H_itx, 0x00},
-       {CX0342_CHANNEL_1_1_L_itx, 0x20},
-       {CX0342_CHANNEL_1_1_H_itx, 0x00},
-       {CX0342_CHANNEL_1_2_L_itx, 0xe4},
-       {CX0342_CHANNEL_1_2_H_itx, 0x00},
-       {CX0342_CHANNEL_1_3_L_itx, 0xee},
-       {CX0342_CHANNEL_1_3_H_itx, 0x00},
-       {CX0342_CHANNEL_2_0_L_iwl, 0x30},
-       {CX0342_CHANNEL_2_0_H_iwl, 0x00},
-       {CX0342_CHANNEL_3_0_L_ensp, 0x34},
-       {CX0342_CHANNEL_3_1_L_ensp, 0xe2},
-       {CX0342_CHANNEL_3_1_H_ensp, 0x00},
-       {CX0342_CHANNEL_3_2_L_ensp, 0xf6},
-       {CX0342_CHANNEL_3_2_H_ensp, 0x00},
-       {CX0342_CHANNEL_3_3_L_ensp, 0xf4},
-       {CX0342_CHANNEL_3_3_H_ensp, 0x02},
-       {CX0342_CHANNEL_4_0_L_sela, 0x26},
-       {CX0342_CHANNEL_4_0_H_sela, 0x00},
-       {CX0342_CHANNEL_4_1_L_sela, 0xe2},
-       {CX0342_CHANNEL_4_1_H_sela, 0x00},
-       {CX0342_CHANNEL_5_0_L_intla, 0x26},
-       {CX0342_CHANNEL_5_1_L_intla, 0x29},
-       {CX0342_CHANNEL_5_2_L_intla, 0xf0},
-       {CX0342_CHANNEL_5_2_H_intla, 0x00},
-       {CX0342_CHANNEL_5_3_L_intla, 0xf3},
-       {CX0342_CHANNEL_5_3_H_intla, 0x00},
-       {CX0342_CHANNEL_6_0_L_xa_sel_pos, 0x24},
-       {CX0342_CHANNEL_7_1_L_cds_pos, 0x02},
-       {CX0342_TIMING_EN, 0x01},
-};
-
-/* define the JPEG header */
-static void jpeg_define(u8 *jpeg_hdr,
-                       int height,
-                       int width)
-{
-       memcpy(jpeg_hdr, jpeg_head, sizeof jpeg_head);
-       jpeg_hdr[JPEG_HEIGHT_OFFSET + 0] = height >> 8;
-       jpeg_hdr[JPEG_HEIGHT_OFFSET + 1] = height;
-       jpeg_hdr[JPEG_HEIGHT_OFFSET + 2] = width >> 8;
-       jpeg_hdr[JPEG_HEIGHT_OFFSET + 3] = width;
-}
-
-/* set the JPEG quality for sensor soi763a */
-static void jpeg_set_qual(u8 *jpeg_hdr,
-                         int quality)
-{
-       int i, sc;
-
-       if (quality < 50)
-               sc = 5000 / quality;
-       else
-               sc = 200 - quality * 2;
-       for (i = 0; i < 64; i++) {
-               jpeg_hdr[JPEG_QT0_OFFSET + i] =
-                       (jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100;
-               jpeg_hdr[JPEG_QT1_OFFSET + i] =
-                       (jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100;
-       }
-}
-
-static void reg_w(struct gspca_dev *gspca_dev, u8 index, u8 value)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-                       0x0e,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index, NULL, 0, 500);
-       if (ret < 0) {
-               pr_err("reg_w err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-/* the returned value is in gspca_dev->usb_buf */
-static void reg_r(struct gspca_dev *gspca_dev, u8 index)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-                       0x0d,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0, index, gspca_dev->usb_buf, 1, 500);
-       if (ret < 0) {
-               pr_err("reg_r err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static void reg_w_buf(struct gspca_dev *gspca_dev,
-                       const struct cmd *p, int l)
-{
-       do {
-               reg_w(gspca_dev, p->reg, p->val);
-               p++;
-       } while (--l > 0);
-}
-
-static int i2c_w(struct gspca_dev *gspca_dev, u8 index, u8 value)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
-       reg_w(gspca_dev, TP6800_R19_SIF_ADDR_S2, index);
-       reg_w(gspca_dev, TP6800_R13_SIF_TX_DATA, value);
-       reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x01);
-       if (sd->bridge == BRIDGE_TP6800)
-               return 0;
-       msleep(5);
-       reg_r(gspca_dev, TP6800_R11_SIF_CONTROL);
-       if (gspca_dev->usb_buf[0] == 0)
-               return 0;
-       reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
-       return -1;                              /* error */
-}
-
-static void i2c_w_buf(struct gspca_dev *gspca_dev,
-                       const struct cmd *p, int l)
-{
-       do {
-               i2c_w(gspca_dev, p->reg, p->val);
-               p++;
-       } while (--l > 0);
-}
-
-static int i2c_r(struct gspca_dev *gspca_dev, u8 index, int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int v;
-
-       reg_w(gspca_dev, TP6800_R19_SIF_ADDR_S2, index);
-       reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x02);
-       msleep(5);
-       reg_r(gspca_dev, TP6800_R14_SIF_RX_DATA);
-       v = gspca_dev->usb_buf[0];
-       if (sd->bridge == BRIDGE_TP6800)
-               return v;
-       if (len > 1) {
-               reg_r(gspca_dev, TP6800_R1B_SIF_RX_DATA2);
-               v |= (gspca_dev->usb_buf[0] << 8);
-       }
-       reg_r(gspca_dev, TP6800_R11_SIF_CONTROL);
-       if (gspca_dev->usb_buf[0] == 0)
-               return v;
-       reg_w(gspca_dev, TP6800_R11_SIF_CONTROL, 0x00);
-       return -1;
-}
-
-static void bulk_w(struct gspca_dev *gspca_dev,
-                 u8 tag,
-                 const u8 *data,
-                 int length)
-{
-       struct usb_device *dev = gspca_dev->dev;
-       int count, actual_count, ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       for (;;) {
-               count = length > BULK_OUT_SIZE - 1
-                               ? BULK_OUT_SIZE - 1 : length;
-               gspca_dev->usb_buf[0] = tag;
-               memcpy(&gspca_dev->usb_buf[1], data, count);
-               ret = usb_bulk_msg(dev,
-                                  usb_sndbulkpipe(dev, 3),
-                                  gspca_dev->usb_buf, count + 1,
-                                  &actual_count, 500);
-               if (ret < 0) {
-                       pr_err("bulk write error %d tag=%02x\n",
-                               ret, tag);
-                       gspca_dev->usb_err = ret;
-                       return;
-               }
-               length -= count;
-               if (length <= 0)
-                       break;
-               data += count;
-       }
-}
-
-static int probe_6810(struct gspca_dev *gspca_dev)
-{
-       u8 gpio;
-       int ret;
-
-       reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
-       gpio = gspca_dev->usb_buf[0];
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
-       reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x04);    /* i2c 16 bits */
-       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x21);  /* ov??? */
-       reg_w(gspca_dev, TP6800_R1A_SIF_TX_DATA2, 0x00);
-       if (i2c_w(gspca_dev, 0x00, 0x00) >= 0)
-               return SENSOR_SOI763A;
-
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
-       reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00);    /* i2c 8 bits */
-       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x7f);  /* (unknown i2c) */
-       if (i2c_w(gspca_dev, 0x00, 0x00) >= 0)
-               return -2;
-
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
-       reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00);    /* i2c 8 bits */
-       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x11);  /* tas??? / hv??? */
-       ret = i2c_r(gspca_dev, 0x00, 1);
-       if (ret > 0)
-               return -3;
-
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
-       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x6e);  /* po??? */
-       ret = i2c_r(gspca_dev, 0x00, 1);
-       if (ret > 0)
-               return -4;
-
-       ret = i2c_r(gspca_dev, 0x01, 1);
-       if (ret > 0)
-               return -5;
-
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
-       reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x04);    /* i2c 16 bits */
-       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x5d);  /* mi/mt??? */
-       ret = i2c_r(gspca_dev, 0x00, 2);
-       if (ret > 0)
-               return -6;
-
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
-       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x5c);  /* mi/mt??? */
-       ret = i2c_r(gspca_dev, 0x36, 2);
-       if (ret > 0)
-               return -7;
-
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
-       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x61);  /* (unknown i2c) */
-       reg_w(gspca_dev, TP6800_R1A_SIF_TX_DATA2, 0x10);
-       if (i2c_w(gspca_dev, 0xff, 0x00) >= 0)
-               return -8;
-
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio);
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, gpio | 0x20);
-       reg_w(gspca_dev, TP6800_R10_SIF_TYPE, 0x00);    /* i2c 8 bits */
-       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20);  /* cx0342 */
-       ret = i2c_r(gspca_dev, 0x00, 1);
-       if (ret > 0)
-               return SENSOR_CX0342;
-       return -9;
-}
-
-static void cx0342_6810_init(struct gspca_dev *gspca_dev)
-{
-       static const struct cmd reg_init_1[] = {
-               {TP6800_R2F_TIMING_CFG, 0x2f},
-               {0x25, 0x02},
-               {TP6800_R21_ENDP_1_CTL, 0x00},
-               {TP6800_R3F_FRAME_RATE, 0x80},
-               {TP6800_R2F_TIMING_CFG, 0x2f},
-               {TP6800_R18_GPIO_DATA, 0xe1},
-               {TP6800_R18_GPIO_DATA, 0xc1},
-               {TP6800_R18_GPIO_DATA, 0xe1},
-               {TP6800_R11_SIF_CONTROL, 0x00},
-       };
-       static const struct cmd reg_init_2[] = {
-               {TP6800_R78_FORMAT, 0x48},
-               {TP6800_R11_SIF_CONTROL, 0x00},
-       };
-       static const struct cmd sensor_init[] = {
-               {CX0342_OUTPUT_CTRL, 0x07},
-               {CX0342_BYPASS_MODE, 0x58},
-               {CX0342_GPXLTHD_L, 0x28},
-               {CX0342_RBPXLTHD_L, 0x28},
-               {CX0342_PLANETHD_L, 0x50},
-               {CX0342_PLANETHD_H, 0x03},
-               {CX0342_RB_GAP_L, 0xff},
-               {CX0342_RB_GAP_H, 0x07},
-               {CX0342_G_GAP_L, 0xff},
-               {CX0342_G_GAP_H, 0x07},
-               {CX0342_RST_OVERFLOW_L, 0x5c},
-               {CX0342_RST_OVERFLOW_H, 0x01},
-               {CX0342_DATA_OVERFLOW_L, 0xfc},
-               {CX0342_DATA_OVERFLOW_H, 0x03},
-               {CX0342_DATA_UNDERFLOW_L, 0x00},
-               {CX0342_DATA_UNDERFLOW_H, 0x00},
-               {CX0342_SYS_CTRL_0, 0x40},
-               {CX0342_GLOBAL_GAIN, 0x01},
-               {CX0342_CLOCK_GEN, 0x00},
-               {CX0342_SYS_CTRL_0, 0x02},
-               {CX0342_IDLE_CTRL, 0x05},
-               {CX0342_ADCGN, 0x00},
-               {CX0342_ADC_CTL, 0x00},
-               {CX0342_LVRST_BLBIAS, 0x01},
-               {CX0342_VTHSEL, 0x0b},
-               {CX0342_RAMP_RIV, 0x0b},
-               {CX0342_LDOSEL, 0x07},
-               {CX0342_SPV_VALUE_L, 0x40},
-               {CX0342_SPV_VALUE_H, 0x02},
-
-               {CX0342_AUTO_ADC_CALIB, 0x81},
-               {CX0342_TIMING_EN, 0x01},
-       };
-
-       reg_w_buf(gspca_dev, reg_init_1, ARRAY_SIZE(reg_init_1));
-       reg_w_buf(gspca_dev, tp6810_cx_init_common,
-                       ARRAY_SIZE(tp6810_cx_init_common));
-       reg_w_buf(gspca_dev, reg_init_2, ARRAY_SIZE(reg_init_2));
-
-       reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20);  /* cx0342 I2C addr */
-       i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
-       i2c_w_buf(gspca_dev, cx0342_timing_seq, ARRAY_SIZE(cx0342_timing_seq));
-}
-
-static void soi763a_6810_init(struct gspca_dev *gspca_dev)
-{
-       static const struct cmd reg_init_1[] = {
-               {TP6800_R2F_TIMING_CFG, 0x2f},
-               {TP6800_R18_GPIO_DATA, 0xe1},
-               {0x25, 0x02},
-               {TP6800_R21_ENDP_1_CTL, 0x00},
-               {TP6800_R3F_FRAME_RATE, 0x80},
-               {TP6800_R2F_TIMING_CFG, 0x2f},
-               {TP6800_R18_GPIO_DATA, 0xc1},
-       };
-       static const struct cmd reg_init_2[] = {
-               {TP6800_R78_FORMAT, 0x54},
-       };
-       static const struct cmd sensor_init[] = {
-               {0x00, 0x00},
-               {0x01, 0x80},
-               {0x02, 0x80},
-               {0x03, 0x90},
-               {0x04, 0x20},
-               {0x05, 0x20},
-               {0x06, 0x80},
-               {0x07, 0x00},
-               {0x08, 0xff},
-               {0x09, 0xff},
-               {0x0a, 0x76},           /* 7630 = soi673a */
-               {0x0b, 0x30},
-               {0x0c, 0x20},
-               {0x0d, 0x20},
-               {0x0e, 0xff},
-               {0x0f, 0xff},
-               {0x10, 0x41},
-               {0x15, 0x14},
-               {0x11, 0x40},
-               {0x12, 0x48},
-               {0x13, 0x80},
-               {0x14, 0x80},
-               {0x16, 0x03},
-               {0x28, 0xb0},
-               {0x71, 0x20},
-               {0x75, 0x8e},
-               {0x17, 0x1b},
-               {0x18, 0xbd},
-               {0x19, 0x05},
-               {0x1a, 0xf6},
-               {0x1b, 0x04},
-               {0x1c, 0x7f},           /* omnivision */
-               {0x1d, 0xa2},
-               {0x1e, 0x00},
-               {0x1f, 0x00},
-               {0x20, 0x45},
-               {0x21, 0x80},
-               {0x22, 0x80},
-               {0x23, 0xee},
-               {0x24, 0x50},
-               {0x25, 0x7a},
-               {0x26, 0xa0},
-               {0x27, 0x9a},
-               {0x29, 0x30},
-               {0x2a, 0x80},
-               {0x2b, 0x00},
-               {0x2c, 0xac},
-               {0x2d, 0x05},
-               {0x2e, 0x80},
-               {0x2f, 0x3c},
-               {0x30, 0x22},
-               {0x31, 0x00},
-               {0x32, 0x86},
-               {0x33, 0x08},
-               {0x34, 0xff},
-               {0x35, 0xff},
-               {0x36, 0xff},
-               {0x37, 0xff},
-               {0x38, 0xff},
-               {0x39, 0xff},
-               {0x3a, 0xfe},
-               {0x3b, 0xfe},
-               {0x3c, 0xfe},
-               {0x3d, 0xfe},
-               {0x3e, 0xfe},
-               {0x3f, 0x71},
-               {0x40, 0xff},
-               {0x41, 0xff},
-               {0x42, 0xff},
-               {0x43, 0xff},
-               {0x44, 0xff},
-               {0x45, 0xff},
-               {0x46, 0xff},
-               {0x47, 0xff},
-               {0x48, 0xff},
-               {0x49, 0xff},
-               {0x4a, 0xfe},
-               {0x4b, 0xff},
-               {0x4c, 0x00},
-               {0x4d, 0x00},
-               {0x4e, 0xff},
-               {0x4f, 0xff},
-               {0x50, 0xff},
-               {0x51, 0xff},
-               {0x52, 0xff},
-               {0x53, 0xff},
-               {0x54, 0xff},
-               {0x55, 0xff},
-               {0x56, 0xff},
-               {0x57, 0xff},
-               {0x58, 0xff},
-               {0x59, 0xff},
-               {0x5a, 0xff},
-               {0x5b, 0xfe},
-               {0x5c, 0xff},
-               {0x5d, 0x8f},
-               {0x5e, 0xff},
-               {0x5f, 0x8f},
-               {0x60, 0xa2},
-               {0x61, 0x4a},
-               {0x62, 0xf3},
-               {0x63, 0x75},
-               {0x64, 0xf0},
-               {0x65, 0x00},
-               {0x66, 0x55},
-               {0x67, 0x92},
-               {0x68, 0xa0},
-               {0x69, 0x4a},
-               {0x6a, 0x22},
-               {0x6b, 0x00},
-               {0x6c, 0x33},
-               {0x6d, 0x44},
-               {0x6e, 0x22},
-               {0x6f, 0x84},
-               {0x70, 0x0b},
-               {0x72, 0x10},
-               {0x73, 0x50},
-               {0x74, 0x21},
-               {0x76, 0x00},
-               {0x77, 0xa5},
-               {0x78, 0x80},
-               {0x79, 0x80},
-               {0x7a, 0x80},
-               {0x7b, 0xe2},
-               {0x7c, 0x00},
-               {0x7d, 0xf7},
-               {0x7e, 0x00},
-               {0x7f, 0x00},
-       };
-
-       reg_w_buf(gspca_dev, reg_init_1, ARRAY_SIZE(reg_init_1));
-       reg_w_buf(gspca_dev, tp6810_ov_init_common,
-                       ARRAY_SIZE(tp6810_ov_init_common));
-       reg_w_buf(gspca_dev, reg_init_2, ARRAY_SIZE(reg_init_2));
-
-       i2c_w(gspca_dev, 0x12, 0x80);           /* sensor reset */
-       msleep(10);
-       i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
-}
-
-/* set the gain and exposure */
-static void setexposure(struct gspca_dev *gspca_dev, s32 expo, s32 gain,
-                                                       s32 blue, s32 red)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor == SENSOR_CX0342) {
-               expo = (expo << 2) - 1;
-               i2c_w(gspca_dev, CX0342_EXPO_LINE_L, expo);
-               i2c_w(gspca_dev, CX0342_EXPO_LINE_H, expo >> 8);
-               if (sd->bridge == BRIDGE_TP6800)
-                       i2c_w(gspca_dev, CX0342_RAW_GBGAIN_H,
-                                               gain >> 8);
-               i2c_w(gspca_dev, CX0342_RAW_GBGAIN_L, gain);
-               if (sd->bridge == BRIDGE_TP6800)
-                       i2c_w(gspca_dev, CX0342_RAW_GRGAIN_H,
-                                       gain >> 8);
-               i2c_w(gspca_dev, CX0342_RAW_GRGAIN_L, gain);
-               if (sd->sensor == SENSOR_CX0342) {
-                       if (sd->bridge == BRIDGE_TP6800)
-                               i2c_w(gspca_dev, CX0342_RAW_BGAIN_H,
-                                               blue >> 8);
-                       i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, blue);
-                       if (sd->bridge == BRIDGE_TP6800)
-                               i2c_w(gspca_dev, CX0342_RAW_RGAIN_H,
-                                               red >> 8);
-                       i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, red);
-               }
-               i2c_w(gspca_dev, CX0342_SYS_CTRL_0,
-                               sd->bridge == BRIDGE_TP6800 ? 0x80 : 0x81);
-               return;
-       }
-
-       /* soi763a */
-       i2c_w(gspca_dev, 0x10,          /* AEC_H (exposure time) */
-                        expo);
-/*     i2c_w(gspca_dev, 0x76, 0x02);    * AEC_L ([1:0] */
-       i2c_w(gspca_dev, 0x00,          /* gain */
-                        gain);
-}
-
-/* set the JPEG quantization tables */
-static void set_dqt(struct gspca_dev *gspca_dev, u8 q)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* update the jpeg quantization tables */
-       PDEBUG(D_STREAM, "q %d -> %d", sd->quality, q);
-       sd->quality = q;
-       if (q > 16)
-               q = 16;
-       if (sd->sensor == SENSOR_SOI763A)
-               jpeg_set_qual(sd->jpeg_hdr, jpeg_q[q]);
-       else
-               memcpy(&sd->jpeg_hdr[JPEG_QT0_OFFSET - 1],
-                       DQT[q], sizeof DQT[0]);
-}
-
-/* set the JPEG compression quality factor */
-static void setquality(struct gspca_dev *gspca_dev, s32 q)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (q != 16)
-               q = 15 - q;
-
-       reg_w(gspca_dev, TP6800_R7A_BLK_THRLD, 0x00);
-       reg_w(gspca_dev, TP6800_R79_QUALITY, 0x04);
-       reg_w(gspca_dev, TP6800_R79_QUALITY, q);
-
-       /* auto quality */
-       if (q == 15 && sd->bridge == BRIDGE_TP6810) {
-               msleep(4);
-               reg_w(gspca_dev, TP6800_R7A_BLK_THRLD, 0x19);
-       }
-}
-
-static const u8 color_null[18] = {
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-static const u8 color_gain[NSENSORS][18] = {
-[SENSOR_CX0342] =
-       {0x4c, 0x00, 0xa9, 0x00, 0x31, 0x00,    /* Y R/G/B (LE values) */
-        0xb6, 0x03, 0x6c, 0x03, 0xe0, 0x00,    /* U R/G/B */
-        0xdf, 0x00, 0x46, 0x03, 0xdc, 0x03},   /* V R/G/B */
-[SENSOR_SOI763A] =
-       {0x4c, 0x00, 0x95, 0x00, 0x1d, 0x00,    /* Y R/G/B (LE values) */
-        0xb6, 0x03, 0x6c, 0x03, 0xd7, 0x00,    /* U R/G/B */
-        0xd5, 0x00, 0x46, 0x03, 0xdc, 0x03},   /* V R/G/B */
-};
-
-static void setgamma(struct gspca_dev *gspca_dev, s32 gamma)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-#define NGAMMA 6
-       static const u8 gamma_tb[NGAMMA][3][1024] = {
-           {                           /* gamma 0 - from tp6800 + soi763a */
-               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
-                0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
-                0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
-                0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
-                0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
-                0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
-                0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
-                0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
-                0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
-                0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
-                0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
-                0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
-                0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
-                0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
-                0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
-                0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
-                0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
-                0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
-                0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
-                0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
-                0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
-                0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
-                0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
-                0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
-                0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
-                0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
-                0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
-                0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
-                0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
-                0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
-                0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
-                0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
-                0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
-                0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
-                0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
-                0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
-                0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
-                0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
-                0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
-                0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
-                0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
-                0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
-                0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
-                0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
-                0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
-                0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
-                0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
-                0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
-                0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
-                0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
-                0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
-                0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
-                0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
-                0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
-                0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
-                0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
-                0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
-                0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
-                0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
-                0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
-                0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
-                0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
-                0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
-                0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
-                0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
-                0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-                0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
-                0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
-                0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
-                0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
-                0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
-                0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
-                0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
-                0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
-                0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
-                0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
-                0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
-                0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
-                0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
-                0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
-                0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
-                0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
-                0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
-                0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
-                0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
-                0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
-                0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
-                0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
-                0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
-                0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
-                0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
-                0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
-                0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
-                0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
-               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
-                0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
-                0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
-                0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
-                0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
-                0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
-                0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
-                0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
-                0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
-                0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
-                0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
-                0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
-                0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
-                0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
-                0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
-                0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
-                0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
-                0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
-                0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
-                0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
-                0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
-                0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
-                0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
-                0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
-                0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
-                0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
-                0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
-                0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
-                0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
-                0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
-                0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
-                0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
-                0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
-                0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
-                0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
-                0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
-                0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
-                0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
-                0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
-                0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
-                0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
-                0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
-                0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
-                0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
-                0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
-                0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
-                0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
-                0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
-                0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
-                0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
-                0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
-                0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
-                0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
-                0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
-                0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
-                0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
-                0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
-                0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
-                0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
-                0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
-                0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
-                0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
-                0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
-                0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
-                0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
-                0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-                0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
-                0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
-                0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
-                0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
-                0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
-                0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
-                0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
-                0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
-                0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
-                0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
-                0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
-                0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
-                0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
-                0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
-                0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
-                0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
-                0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
-                0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
-                0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
-                0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
-                0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
-                0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
-                0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
-                0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
-                0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
-                0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
-                0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
-                0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
-               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
-                0x02, 0x03, 0x05, 0x07, 0x07, 0x08, 0x09, 0x09,
-                0x0a, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x10, 0x11,
-                0x11, 0x12, 0x14, 0x14, 0x15, 0x16, 0x16, 0x17,
-                0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
-                0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x23,
-                0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28,
-                0x29, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f,
-                0x2f, 0x30, 0x30, 0x31, 0x31, 0x33, 0x33, 0x34,
-                0x34, 0x34, 0x35, 0x35, 0x37, 0x37, 0x38, 0x38,
-                0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3c,
-                0x3c, 0x3d, 0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x40,
-                0x42, 0x42, 0x43, 0x43, 0x44, 0x44, 0x44, 0x45,
-                0x45, 0x47, 0x47, 0x47, 0x48, 0x48, 0x49, 0x49,
-                0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c,
-                0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50, 0x50,
-                0x52, 0x52, 0x52, 0x53, 0x53, 0x54, 0x54, 0x54,
-                0x55, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58, 0x58,
-                0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
-                0x5b, 0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5e, 0x5f,
-                0x5f, 0x5f, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61,
-                0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x65, 0x65,
-                0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68,
-                0x68, 0x68, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a,
-                0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
-                0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
-                0x70, 0x71, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73,
-                0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x76,
-                0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79, 0x79,
-                0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
-                0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
-                0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
-                0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
-                0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
-                0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
-                0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b,
-                0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e,
-                0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90,
-                0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
-                0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
-                0x94, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96,
-                0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
-                0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
-                0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
-                0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
-                0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0,
-                0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2,
-                0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
-                0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6,
-                0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
-                0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
-                0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
-                0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xae,
-                0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
-                0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
-                0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
-                0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
-                0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
-                0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
-                0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
-                0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
-                0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
-                0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
-                0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
-                0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
-                0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
-                0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
-                0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
-                0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc,
-                0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
-                0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
-                0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1,
-                0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
-                0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6,
-                0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
-                0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
-                0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
-                0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
-                0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
-                0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
-                0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
-                0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
-                0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
-                0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7,
-                0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
-                0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
-                0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
-                0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
-                0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
-                0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
-                0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
-                0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
-                0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
-                0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
-           },
-           {                           /* gamma 1 - from tp6810 + soi763a */
-               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x01, 0x02, 0x03, 0x05, 0x07, 0x08, 0x09, 0x0a,
-                0x0c, 0x0d, 0x0e, 0x10, 0x11, 0x12, 0x14, 0x15,
-                0x16, 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1c, 0x1e,
-                0x1f, 0x20, 0x22, 0x22, 0x23, 0x25, 0x26, 0x27,
-                0x27, 0x28, 0x29, 0x2b, 0x2b, 0x2c, 0x2d, 0x2f,
-                0x2f, 0x30, 0x31, 0x33, 0x33, 0x34, 0x35, 0x35,
-                0x37, 0x38, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c,
-                0x3c, 0x3d, 0x3f, 0x3f, 0x40, 0x42, 0x42, 0x43,
-                0x43, 0x44, 0x45, 0x45, 0x47, 0x47, 0x48, 0x49,
-                0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4d,
-                0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
-                0x54, 0x54, 0x55, 0x56, 0x56, 0x58, 0x58, 0x59,
-                0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5e,
-                0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61, 0x61,
-                0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x65, 0x66,
-                0x66, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69, 0x69,
-                0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e,
-                0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71,
-                0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75,
-                0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79,
-                0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c,
-                0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x80,
-                0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x84, 0x84,
-                0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x88,
-                0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a,
-                0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e,
-                0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91,
-                0x91, 0x91, 0x92, 0x92, 0x92, 0x92, 0x93, 0x93,
-                0x93, 0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x97,
-                0x97, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
-                0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b,
-                0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9e,
-                0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
-                0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3,
-                0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5,
-                0xa5, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
-                0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xab,
-                0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xae,
-                0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0,
-                0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
-                0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4,
-                0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
-                0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
-                0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
-                0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
-                0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
-                0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
-                0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4,
-                0xc4, 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6,
-                0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7,
-                0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
-                0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
-                0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
-                0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
-                0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
-                0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4,
-                0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
-                0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
-                0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda,
-                0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb,
-                0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
-                0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
-                0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
-                0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
-                0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
-                0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
-                0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8,
-                0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9,
-                0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec,
-                0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed,
-                0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
-                0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
-                0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3,
-                0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
-                0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
-                0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
-                0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
-                0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
-                0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe,
-                0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
-                0x05, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0c, 0x0d,
-                0x0e, 0x10, 0x10, 0x11, 0x12, 0x14, 0x15, 0x15,
-                0x16, 0x17, 0x18, 0x1a, 0x1a, 0x1b, 0x1c, 0x1e,
-                0x1e, 0x1f, 0x20, 0x20, 0x22, 0x23, 0x25, 0x25,
-                0x26, 0x27, 0x27, 0x28, 0x29, 0x29, 0x2b, 0x2c,
-                0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x30, 0x31, 0x31,
-                0x33, 0x34, 0x34, 0x35, 0x35, 0x37, 0x38, 0x38,
-                0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d,
-                0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x42, 0x43,
-                0x43, 0x44, 0x44, 0x45, 0x45, 0x47, 0x47, 0x48,
-                0x48, 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x4c,
-                0x4c, 0x4d, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x50,
-                0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x55,
-                0x55, 0x56, 0x56, 0x56, 0x58, 0x58, 0x59, 0x59,
-                0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c,
-                0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60,
-                0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x65,
-                0x65, 0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67,
-                0x68, 0x68, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a,
-                0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e,
-                0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
-                0x71, 0x71, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74,
-                0x75, 0x75, 0x75, 0x77, 0x77, 0x77, 0x78, 0x78,
-                0x78, 0x79, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a,
-                0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d,
-                0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80,
-                0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
-                0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85, 0x86,
-                0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89, 0x89,
-                0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b,
-                0x8b, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e,
-                0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
-                0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
-                0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
-                0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97,
-                0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
-                0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b,
-                0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
-                0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0,
-                0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
-                0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
-                0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
-                0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
-                0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab,
-                0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
-                0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
-                0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
-                0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
-                0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
-                0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6,
-                0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8,
-                0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
-                0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbc, 0xbc,
-                0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
-                0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf,
-                0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
-                0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
-                0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
-                0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
-                0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9,
-                0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
-                0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
-                0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd,
-                0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xcf,
-                0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
-                0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
-                0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4,
-                0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
-                0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8,
-                0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9,
-                0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb,
-                0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
-                0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf,
-                0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
-                0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2,
-                0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3,
-                0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
-                0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
-                0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
-                0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
-                0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
-                0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
-                0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
-                0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
-                0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
-                0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4,
-                0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5,
-                0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7,
-                0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8,
-                0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc,
-                0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
-                0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe,
-                0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-               {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x01, 0x02, 0x03, 0x05, 0x05, 0x07,
-                0x08, 0x09, 0x0a, 0x0a, 0x0c, 0x0d, 0x0e, 0x0e,
-                0x10, 0x11, 0x12, 0x12, 0x14, 0x15, 0x16, 0x16,
-                0x17, 0x18, 0x18, 0x1a, 0x1b, 0x1b, 0x1c, 0x1e,
-                0x1e, 0x1f, 0x1f, 0x20, 0x22, 0x22, 0x23, 0x23,
-                0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x29, 0x29,
-                0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2f, 0x30,
-                0x30, 0x31, 0x31, 0x33, 0x33, 0x34, 0x34, 0x35,
-                0x35, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x3a,
-                0x3a, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d,
-                0x3f, 0x3f, 0x40, 0x40, 0x42, 0x42, 0x42, 0x43,
-                0x43, 0x44, 0x44, 0x45, 0x45, 0x47, 0x47, 0x47,
-                0x48, 0x48, 0x49, 0x49, 0x49, 0x4a, 0x4a, 0x4b,
-                0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4f,
-                0x4f, 0x50, 0x50, 0x50, 0x52, 0x52, 0x52, 0x53,
-                0x53, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x56,
-                0x56, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x5a,
-                0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c,
-                0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x60, 0x60,
-                0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63,
-                0x63, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x66,
-                0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69,
-                0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
-                0x6c, 0x6d, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e,
-                0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
-                0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x74, 0x74,
-                0x74, 0x74, 0x75, 0x75, 0x75, 0x75, 0x77, 0x77,
-                0x77, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79,
-                0x79, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b,
-                0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d,
-                0x7d, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80,
-                0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82,
-                0x82, 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85,
-                0x85, 0x86, 0x86, 0x86, 0x86, 0x88, 0x88, 0x88,
-                0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a,
-                0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d,
-                0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
-                0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
-                0x90, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92,
-                0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94, 0x94,
-                0x94, 0x94, 0x94, 0x96, 0x96, 0x96, 0x96, 0x96,
-                0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98,
-                0x98, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
-                0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b,
-                0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
-                0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0,
-                0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1,
-                0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3,
-                0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
-                0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6,
-                0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
-                0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab,
-                0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac,
-                0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae,
-                0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
-                0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
-                0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2,
-                0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4,
-                0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6,
-                0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
-                0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
-                0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba,
-                0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
-                0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
-                0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
-                0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
-                0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3,
-                0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
-                0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
-                0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
-                0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
-                0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb,
-                0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
-                0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce,
-                0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
-                0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
-                0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
-                0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
-                0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7,
-                0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
-                0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9,
-                0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
-                0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
-                0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde,
-                0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0,
-                0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
-                0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3,
-                0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4,
-                0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
-                0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7,
-                0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
-                0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb,
-                0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
-                0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee,
-                0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, 0xef,
-                0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1,
-                0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3,
-                0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5,
-                0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
-                0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
-                0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc,
-                0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd,
-                0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
-           },
-           {                                                   /* gamma 2 */
-               {0x00, 0x01, 0x02, 0x05, 0x07, 0x08, 0x0a, 0x0c,
-                0x0d, 0x0e, 0x10, 0x12, 0x14, 0x15, 0x16, 0x17,
-                0x18, 0x1a, 0x1b, 0x1c, 0x1e, 0x1f, 0x20, 0x22,
-                0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2c,
-                0x2d, 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x34,
-                0x35, 0x37, 0x38, 0x38, 0x39, 0x3a, 0x3b, 0x3b,
-                0x3c, 0x3d, 0x3f, 0x3f, 0x40, 0x42, 0x42, 0x43,
-                0x44, 0x44, 0x45, 0x47, 0x47, 0x48, 0x49, 0x49,
-                0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4f, 0x4f,
-                0x50, 0x50, 0x52, 0x53, 0x53, 0x54, 0x54, 0x55,
-                0x55, 0x56, 0x56, 0x58, 0x58, 0x59, 0x5a, 0x5a,
-                0x5b, 0x5b, 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f,
-                0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x63, 0x63,
-                0x65, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
-                0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
-                0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x70,
-                0x70, 0x70, 0x71, 0x71, 0x73, 0x73, 0x73, 0x74,
-                0x74, 0x75, 0x75, 0x75, 0x77, 0x77, 0x78, 0x78,
-                0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b,
-                0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f,
-                0x7f, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82,
-                0x82, 0x82, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85,
-                0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x89, 0x89,
-                0x89, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8d,
-                0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f,
-                0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
-                0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94,
-                0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
-                0x97, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99,
-                0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b,
-                0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e,
-                0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1,
-                0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3,
-                0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5,
-                0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8,
-                0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
-                0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad,
-                0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
-                0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0,
-                0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2,
-                0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4,
-                0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
-                0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
-                0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba,
-                0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
-                0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
-                0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0,
-                0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3,
-                0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4,
-                0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6,
-                0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7,
-                0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
-                0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb,
-                0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
-                0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce,
-                0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0,
-                0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1,
-                0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4,
-                0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
-                0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
-                0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
-                0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda,
-                0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd,
-                0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde,
-                0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
-                0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1,
-                0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
-                0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4,
-                0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5,
-                0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
-                0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8,
-                0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9,
-                0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
-                0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed,
-                0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
-                0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
-                0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1,
-                0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
-                0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
-                0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
-                0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
-                0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9,
-                0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
-               {0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x05,
-                0x07, 0x08, 0x09, 0x0a, 0x0d, 0x0e, 0x10, 0x11,
-                0x12, 0x14, 0x15, 0x16, 0x16, 0x17, 0x18, 0x1a,
-                0x1b, 0x1c, 0x1e, 0x1f, 0x20, 0x20, 0x22, 0x23,
-                0x25, 0x26, 0x26, 0x27, 0x28, 0x29, 0x29, 0x2b,
-                0x2c, 0x2d, 0x2d, 0x2f, 0x30, 0x30, 0x31, 0x33,
-                0x33, 0x34, 0x35, 0x35, 0x37, 0x38, 0x38, 0x39,
-                0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3d, 0x3f,
-                0x3f, 0x40, 0x42, 0x42, 0x43, 0x43, 0x44, 0x44,
-                0x45, 0x45, 0x47, 0x47, 0x48, 0x48, 0x49, 0x4a,
-                0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d,
-                0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
-                0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x56, 0x58,
-                0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b,
-                0x5c, 0x5c, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f,
-                0x60, 0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x63,
-                0x63, 0x63, 0x65, 0x65, 0x65, 0x66, 0x66, 0x67,
-                0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69,
-                0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d,
-                0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70,
-                0x70, 0x71, 0x71, 0x71, 0x73, 0x73, 0x73, 0x73,
-                0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77, 0x77,
-                0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79,
-                0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7b, 0x7c,
-                0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d, 0x7f, 0x7f,
-                0x7f, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81,
-                0x82, 0x82, 0x82, 0x82, 0x84, 0x84, 0x84, 0x84,
-                0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x88,
-                0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x89, 0x8a,
-                0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8d,
-                0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f,
-                0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90, 0x91,
-                0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
-                0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
-                0x94, 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
-                0x97, 0x98, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99,
-                0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b,
-                0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9c,
-                0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e,
-                0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1,
-                0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2,
-                0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
-                0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
-                0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
-                0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
-                0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac,
-                0xac, 0xac, 0xad, 0xad, 0xad, 0xad, 0xad, 0xae,
-                0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf,
-                0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1,
-                0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2,
-                0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
-                0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6,
-                0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
-                0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9,
-                0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
-                0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
-                0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe,
-                0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf,
-                0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
-                0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
-                0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4,
-                0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
-                0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7,
-                0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9,
-                0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xca,
-                0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
-                0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
-                0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
-                0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
-                0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1,
-                0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
-                0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
-                0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
-                0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
-                0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
-                0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
-                0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
-                0xdb, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-                0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf,
-                0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0,
-                0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1,
-                0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
-                0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
-                0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
-                0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6,
-                0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
-                0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
-                0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
-                0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
-                0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
-                0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xef,
-                0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
-                0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
-                0xf1, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4,
-                0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5,
-                0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
-                0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
-                0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9,
-                0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
-               {0x00, 0x00, 0x00, 0x01, 0x02, 0x05, 0x07, 0x08,
-                0x09, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x12, 0x14,
-                0x15, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1e,
-                0x1f, 0x20, 0x20, 0x22, 0x23, 0x25, 0x26, 0x27,
-                0x28, 0x28, 0x29, 0x2b, 0x2c, 0x2d, 0x2d, 0x2f,
-                0x30, 0x31, 0x31, 0x33, 0x34, 0x35, 0x35, 0x37,
-                0x38, 0x38, 0x39, 0x3a, 0x3a, 0x3b, 0x3c, 0x3c,
-                0x3d, 0x3f, 0x3f, 0x40, 0x40, 0x42, 0x43, 0x43,
-                0x44, 0x44, 0x45, 0x47, 0x47, 0x48, 0x48, 0x49,
-                0x4a, 0x4a, 0x4b, 0x4b, 0x4c, 0x4c, 0x4d, 0x4d,
-                0x4f, 0x4f, 0x50, 0x50, 0x52, 0x52, 0x53, 0x53,
-                0x54, 0x54, 0x55, 0x55, 0x56, 0x56, 0x58, 0x58,
-                0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c,
-                0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
-                0x61, 0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65,
-                0x65, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68,
-                0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6c, 0x6c,
-                0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f,
-                0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x73, 0x73,
-                0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x77,
-                0x77, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x7a,
-                0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c,
-                0x7c, 0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80,
-                0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82,
-                0x82, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85,
-                0x86, 0x86, 0x86, 0x88, 0x88, 0x88, 0x88, 0x89,
-                0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b,
-                0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e,
-                0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90,
-                0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
-                0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
-                0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97,
-                0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
-                0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b,
-                0x9b, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d,
-                0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0xa0, 0xa0,
-                0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
-                0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
-                0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
-                0xa5, 0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8,
-                0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
-                0xab, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac, 0xac,
-                0xad, 0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
-                0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0,
-                0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1,
-                0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3,
-                0xb3, 0xb3, 0xb3, 0xb4, 0xb3, 0xb4, 0xb4, 0xb4,
-                0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
-                0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
-                0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
-                0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
-                0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe,
-                0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
-                0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2,
-                0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3,
-                0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5,
-                0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6,
-                0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
-                0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
-                0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb,
-                0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
-                0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce,
-                0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
-                0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0,
-                0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3,
-                0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
-                0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6,
-                0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8,
-                0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9,
-                0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xda,
-                0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
-                0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
-                0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
-                0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
-                0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
-                0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3,
-                0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
-                0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6,
-                0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
-                0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
-                0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9,
-                0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec,
-                0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed,
-                0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
-                0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
-                0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1,
-                0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3, 0xf3,
-                0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
-                0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
-                0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7,
-                0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
-                0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
-           },
-           {                           /* gamma 3 - from tp6810 + cx0342 */
-               {0x08, 0x09, 0x0c, 0x0d, 0x10, 0x11, 0x14, 0x15,
-                0x17, 0x18, 0x1a, 0x1c, 0x1e, 0x1f, 0x20, 0x23,
-                0x25, 0x26, 0x27, 0x28, 0x2b, 0x2c, 0x2d, 0x2f,
-                0x30, 0x31, 0x33, 0x34, 0x35, 0x37, 0x38, 0x39,
-                0x3a, 0x3b, 0x3c, 0x3d, 0x3f, 0x40, 0x42, 0x43,
-                0x44, 0x45, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b,
-                0x4c, 0x4d, 0x4d, 0x4f, 0x50, 0x52, 0x53, 0x53,
-                0x54, 0x55, 0x56, 0x56, 0x58, 0x59, 0x5a, 0x5a,
-                0x5b, 0x5c, 0x5c, 0x5e, 0x5f, 0x5f, 0x60, 0x61,
-                0x61, 0x62, 0x63, 0x63, 0x65, 0x66, 0x66, 0x67,
-                0x68, 0x68, 0x69, 0x69, 0x6a, 0x6c, 0x6c, 0x6d,
-                0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x73,
-                0x73, 0x74, 0x74, 0x75, 0x75, 0x77, 0x77, 0x78,
-                0x78, 0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c,
-                0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81,
-                0x82, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
-                0x86, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b,
-                0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x8f,
-                0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92, 0x93,
-                0x93, 0x93, 0x94, 0x94, 0x96, 0x96, 0x97, 0x97,
-                0x97, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a,
-                0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d,
-                0x9e, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
-                0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
-                0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa8, 0xa8,
-                0xa8, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac,
-                0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
-                0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
-                0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3,
-                0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
-                0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
-                0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
-                0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf,
-                0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2,
-                0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5,
-                0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
-                0xc7, 0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
-                0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
-                0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce,
-                0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
-                0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3,
-                0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6,
-                0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
-                0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda,
-                0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd,
-                0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf,
-                0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1,
-                0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
-                0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4,
-                0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
-                0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8,
-                0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb,
-                0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
-                0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
-                0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0,
-                0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
-                0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
-                0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
-                0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
-                0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
-                0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
-                0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
-                0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-               {0x03, 0x05, 0x07, 0x09, 0x0a, 0x0c, 0x0d, 0x10,
-                0x11, 0x12, 0x14, 0x15, 0x17, 0x18, 0x1a, 0x1b,
-                0x1c, 0x1e, 0x1f, 0x20, 0x22, 0x23, 0x25, 0x26,
-                0x27, 0x28, 0x29, 0x2b, 0x2c, 0x2c, 0x2d, 0x2f,
-                0x30, 0x31, 0x33, 0x33, 0x34, 0x35, 0x37, 0x38,
-                0x38, 0x39, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3f,
-                0x3f, 0x40, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45,
-                0x47, 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4b,
-                0x4c, 0x4d, 0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52,
-                0x53, 0x53, 0x54, 0x54, 0x55, 0x55, 0x56, 0x58,
-                0x58, 0x59, 0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c,
-                0x5c, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
-                0x61, 0x62, 0x62, 0x63, 0x63, 0x65, 0x65, 0x66,
-                0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69,
-                0x6a, 0x6a, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e,
-                0x6e, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71,
-                0x71, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75,
-                0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79,
-                0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c,
-                0x7d, 0x7d, 0x7d, 0x7f, 0x7f, 0x7f, 0x80, 0x80,
-                0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x84,
-                0x84, 0x84, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86,
-                0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a,
-                0x8a, 0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e,
-                0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x90, 0x90,
-                0x90, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92,
-                0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x96,
-                0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x98, 0x98,
-                0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a,
-                0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c,
-                0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e,
-                0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1,
-                0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3,
-                0xa4, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5,
-                0xa6, 0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8,
-                0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab,
-                0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad,
-                0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf,
-                0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1,
-                0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
-                0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4,
-                0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
-                0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8, 0xb9,
-                0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba,
-                0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
-                0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
-                0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0,
-                0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3,
-                0xc3, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4,
-                0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
-                0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
-                0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca,
-                0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb,
-                0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
-                0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
-                0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0,
-                0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1,
-                0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd4,
-                0xd4, 0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6,
-                0xd6, 0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7,
-                0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
-                0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
-                0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
-                0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
-                0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
-                0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1,
-                0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2,
-                0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3,
-                0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
-                0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
-                0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
-                0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
-                0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb,
-                0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec,
-                0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee,
-                0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
-                0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
-                0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
-                0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
-                0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
-                0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
-                0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8,
-                0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
-                0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc,
-                0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
-                0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe,
-                0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-               {0x07, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14,
-                0x16, 0x17, 0x18, 0x1b, 0x1c, 0x1e, 0x1f, 0x20,
-                0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2d,
-                0x2f, 0x30, 0x31, 0x33, 0x34, 0x35, 0x37, 0x38,
-                0x39, 0x3a, 0x3b, 0x3b, 0x3c, 0x3d, 0x3f, 0x40,
-                0x42, 0x43, 0x44, 0x44, 0x45, 0x47, 0x48, 0x49,
-                0x4a, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4f, 0x50,
-                0x52, 0x52, 0x53, 0x54, 0x55, 0x55, 0x56, 0x58,
-                0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e,
-                0x5f, 0x5f, 0x60, 0x61, 0x61, 0x62, 0x63, 0x63,
-                0x65, 0x65, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69,
-                0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e, 0x6e,
-                0x6f, 0x70, 0x70, 0x71, 0x71, 0x73, 0x73, 0x74,
-                0x74, 0x75, 0x75, 0x77, 0x77, 0x78, 0x78, 0x79,
-                0x79, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7d,
-                0x7d, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x81,
-                0x82, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
-                0x88, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b,
-                0x8b, 0x8b, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f,
-                0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92,
-                0x92, 0x93, 0x93, 0x94, 0x94, 0x94, 0x96, 0x96,
-                0x96, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
-                0x99, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
-                0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0xa0,
-                0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3,
-                0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5,
-                0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9,
-                0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac, 0xac, 0xac,
-                0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xaf, 0xaf,
-                0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1,
-                0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4,
-                0xb4, 0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
-                0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9,
-                0xb9, 0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc,
-                0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf,
-                0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2,
-                0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc3, 0xc4,
-                0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
-                0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9,
-                0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb,
-                0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd,
-                0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xcf,
-                0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1,
-                0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3,
-                0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
-                0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8,
-                0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda,
-                0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdd,
-                0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xde,
-                0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0,
-                0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
-                0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
-                0xe4, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5,
-                0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
-                0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9,
-                0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb, 0xeb, 0xeb,
-                0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
-                0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
-                0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
-                0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
-                0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
-                0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6,
-                0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
-                0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9,
-                0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
-                0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd,
-                0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
-           },
-           {                           /* gamma 4 - from tp6800 + soi763a */
-               {0x11, 0x14, 0x15, 0x17, 0x1a, 0x1b, 0x1e, 0x1f,
-                0x22, 0x23, 0x25, 0x27, 0x28, 0x2b, 0x2c, 0x2d,
-                0x2f, 0x31, 0x33, 0x34, 0x35, 0x38, 0x39, 0x3a,
-                0x3b, 0x3c, 0x3d, 0x40, 0x42, 0x43, 0x44, 0x45,
-                0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4f,
-                0x50, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56, 0x58,
-                0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5f, 0x60,
-                0x61, 0x61, 0x62, 0x63, 0x65, 0x65, 0x66, 0x67,
-                0x68, 0x68, 0x69, 0x6a, 0x6c, 0x6c, 0x6d, 0x6e,
-                0x6f, 0x6f, 0x70, 0x71, 0x71, 0x73, 0x74, 0x74,
-                0x75, 0x77, 0x77, 0x78, 0x79, 0x79, 0x7a, 0x7a,
-                0x7b, 0x7c, 0x7c, 0x7d, 0x7f, 0x7f, 0x80, 0x80,
-                0x81, 0x81, 0x82, 0x84, 0x84, 0x85, 0x85, 0x86,
-                0x86, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8b, 0x8b,
-                0x8d, 0x8d, 0x8e, 0x8e, 0x8f, 0x90, 0x90, 0x91,
-                0x91, 0x92, 0x92, 0x93, 0x93, 0x94, 0x94, 0x96,
-                0x96, 0x97, 0x97, 0x98, 0x98, 0x98, 0x99, 0x99,
-                0x9a, 0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d,
-                0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa2,
-                0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa5, 0xa5,
-                0xa6, 0xa6, 0xa6, 0xa8, 0xa8, 0xa9, 0xa9, 0xab,
-                0xab, 0xab, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae,
-                0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1,
-                0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4,
-                0xb4, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8,
-                0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xbc,
-                0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbf,
-                0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2,
-                0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
-                0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc9,
-                0xc9, 0xc9, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
-                0xcb, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xce,
-                0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0,
-                0xd0, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
-                0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
-                0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9,
-                0xd9, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb,
-                0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf,
-                0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1,
-                0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
-                0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5,
-                0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7,
-                0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9,
-                0xe9, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec,
-                0xec, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
-                0xee, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
-                0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3, 0xf3, 0xf3,
-                0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5,
-                0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
-                0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9,
-                0xf9, 0xf9, 0xfa, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
-               {0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x11, 0x14, 0x15,
-                0x16, 0x17, 0x1a, 0x1b, 0x1c, 0x1e, 0x1f, 0x20,
-                0x23, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2b, 0x2c,
-                0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34, 0x34, 0x35,
-                0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3c, 0x3d,
-                0x3f, 0x40, 0x42, 0x42, 0x43, 0x44, 0x45, 0x45,
-                0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b, 0x4b, 0x4c,
-                0x4d, 0x4f, 0x4f, 0x50, 0x52, 0x52, 0x53, 0x54,
-                0x54, 0x55, 0x55, 0x56, 0x58, 0x58, 0x59, 0x5a,
-                0x5a, 0x5b, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f, 0x5f,
-                0x60, 0x60, 0x61, 0x61, 0x62, 0x63, 0x63, 0x65,
-                0x65, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68, 0x69,
-                0x69, 0x6a, 0x6a, 0x6c, 0x6c, 0x6d, 0x6d, 0x6e,
-                0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71, 0x73,
-                0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x77, 0x77,
-                0x78, 0x78, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7b,
-                0x7b, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f,
-                0x7f, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82,
-                0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86, 0x86,
-                0x88, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a, 0x8a,
-                0x8b, 0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e,
-                0x8e, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x91, 0x91,
-                0x91, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x94,
-                0x94, 0x94, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
-                0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a,
-                0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c,
-                0x9c, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0xa0,
-                0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
-                0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4,
-                0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6, 0xa6,
-                0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9, 0xa9, 0xab,
-                0xaa, 0xab, 0xab, 0xac, 0xac, 0xac, 0xad, 0xad,
-                0xad, 0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf,
-                0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
-                0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3,
-                0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb6, 0xb6,
-                0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8,
-                0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
-                0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd,
-                0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
-                0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0,
-                0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
-                0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
-                0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
-                0xc7, 0xc7, 0xc7, 0xc7, 0xc9, 0xc9, 0xc9, 0xc9,
-                0xca, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
-                0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd,
-                0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
-                0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
-                0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd3,
-                0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
-                0xd4, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
-                0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
-                0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda,
-                0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb,
-                0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
-                0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf,
-                0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1,
-                0xe1, 0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2,
-                0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4, 0xe4,
-                0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
-                0xe5, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7,
-                0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8,
-                0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb,
-                0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
-                0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
-                0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
-                0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
-                0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
-                0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4,
-                0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
-                0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
-                0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
-                0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb},
-               {0x0d, 0x10, 0x11, 0x14, 0x15, 0x17, 0x18, 0x1b,
-                0x1c, 0x1e, 0x20, 0x22, 0x23, 0x26, 0x27, 0x28,
-                0x29, 0x2b, 0x2d, 0x2f, 0x30, 0x31, 0x33, 0x34,
-                0x35, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d,
-                0x3f, 0x40, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48,
-                0x49, 0x4a, 0x4b, 0x4b, 0x4c, 0x4d, 0x4f, 0x50,
-                0x52, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58,
-                0x59, 0x5a, 0x5a, 0x5b, 0x5c, 0x5e, 0x5e, 0x5f,
-                0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x65, 0x65,
-                0x66, 0x67, 0x67, 0x68, 0x69, 0x69, 0x6a, 0x6c,
-                0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
-                0x71, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x77,
-                0x78, 0x78, 0x79, 0x79, 0x7a, 0x7a, 0x7b, 0x7b,
-                0x7c, 0x7c, 0x7d, 0x7d, 0x7f, 0x7f, 0x80, 0x80,
-                0x81, 0x81, 0x82, 0x82, 0x84, 0x84, 0x85, 0x85,
-                0x86, 0x86, 0x88, 0x88, 0x89, 0x89, 0x8a, 0x8a,
-                0x8b, 0x8b, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8f,
-                0x8f, 0x90, 0x90, 0x91, 0x91, 0x91, 0x92, 0x92,
-                0x93, 0x93, 0x94, 0x94, 0x94, 0x96, 0x96, 0x97,
-                0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a,
-                0x9a, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d,
-                0x9d, 0x9e, 0x9e, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1,
-                0xa1, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
-                0xa4, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa8, 0xa8,
-                0xa8, 0xa9, 0xa9, 0xa9, 0xab, 0xab, 0xab, 0xac,
-                0xac, 0xac, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae,
-                0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1,
-                0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb4,
-                0xb4, 0xb4, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7,
-                0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba,
-                0xba, 0xba, 0xba, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
-                0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf,
-                0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0xc2, 0xc2, 0xc3,
-                0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
-                0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7,
-                0xc7, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
-                0xca, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc, 0xcc, 0xcc,
-                0xcd, 0xcd, 0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce,
-                0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0, 0xd0,
-                0xd1, 0xd1, 0xd1, 0xd1, 0xd3, 0xd3, 0xd3, 0xd3,
-                0xd4, 0xd4, 0xd4, 0xd4, 0xd6, 0xd6, 0xd6, 0xd6,
-                0xd7, 0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8,
-                0xd9, 0xd9, 0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda,
-                0xdb, 0xdb, 0xdb, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
-                0xdd, 0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf,
-                0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1,
-                0xe1, 0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
-                0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
-                0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6, 0xe6,
-                0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8,
-                0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xeb, 0xeb,
-                0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed,
-                0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee,
-                0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0,
-                0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf3,
-                0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
-                0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6,
-                0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8,
-                0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
-                0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb}
-           },
-           {                                                   /* gamma 5 */
-               {0x16, 0x18, 0x19, 0x1b, 0x1d, 0x1e, 0x20, 0x21,
-                0x23, 0x24, 0x25, 0x27, 0x28, 0x2a, 0x2b, 0x2c,
-                0x2d, 0x2f, 0x30, 0x31, 0x32, 0x34, 0x35, 0x36,
-                0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
-                0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
-                0x48, 0x49, 0x4a, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
-                0x4f, 0x50, 0x51, 0x51, 0x52, 0x53, 0x54, 0x55,
-                0x56, 0x56, 0x57, 0x58, 0x59, 0x59, 0x5a, 0x5b,
-                0x5c, 0x5c, 0x5d, 0x5e, 0x5f, 0x5f, 0x60, 0x61,
-                0x62, 0x62, 0x63, 0x64, 0x64, 0x65, 0x66, 0x66,
-                0x67, 0x68, 0x68, 0x69, 0x6a, 0x6a, 0x6b, 0x6b,
-                0x6c, 0x6d, 0x6d, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
-                0x71, 0x71, 0x72, 0x73, 0x73, 0x74, 0x74, 0x75,
-                0x75, 0x76, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79,
-                0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7d, 0x7d, 0x7e,
-                0x7e, 0x7f, 0x7f, 0x80, 0x80, 0x81, 0x81, 0x82,
-                0x82, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85,
-                0x86, 0x86, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89,
-                0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8d,
-                0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x90, 0x90,
-                0x91, 0x91, 0x91, 0x92, 0x92, 0x93, 0x93, 0x94,
-                0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x96, 0x97,
-                0x97, 0x98, 0x98, 0x98, 0x99, 0x99, 0x9a, 0x9a,
-                0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9d, 0x9d,
-                0x9d, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f, 0xa0, 0xa0,
-                0xa0, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa3,
-                0xa3, 0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa6,
-                0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8,
-                0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
-                0xab, 0xac, 0xac, 0xac, 0xad, 0xad, 0xad, 0xae,
-                0xae, 0xae, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
-                0xb0, 0xb1, 0xb1, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3,
-                0xb3, 0xb3, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5,
-                0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7,
-                0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
-                0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc,
-                0xbc, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe,
-                0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
-                0xc1, 0xc1, 0xc1, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
-                0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
-                0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7,
-                0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9, 0xc9,
-                0xc9, 0xca, 0xca, 0xca, 0xca, 0xcb, 0xcb, 0xcb,
-                0xcb, 0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd,
-                0xcd, 0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf,
-                0xcf, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
-                0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3, 0xd3, 0xd3,
-                0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd5, 0xd5, 0xd5,
-                0xd5, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
-                0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9,
-                0xd9, 0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb,
-                0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdd,
-                0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde, 0xde,
-                0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0, 0xe0, 0xe0,
-                0xe0, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
-                0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe4,
-                0xe4, 0xe4, 0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
-                0xe6, 0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7,
-                0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
-                0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea, 0xeb,
-                0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec,
-                0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee,
-                0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
-                0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
-                0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3,
-                0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5,
-                0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6,
-                0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
-                0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd,
-                0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-               {0x0f, 0x11, 0x12, 0x14, 0x15, 0x16, 0x18, 0x19,
-                0x1a, 0x1b, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
-                0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
-                0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x31, 0x32,
-                0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x38, 0x39,
-                0x3a, 0x3b, 0x3c, 0x3c, 0x3d, 0x3e, 0x3f, 0x3f,
-                0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x44, 0x45,
-                0x46, 0x47, 0x47, 0x48, 0x49, 0x49, 0x4a, 0x4b,
-                0x4b, 0x4c, 0x4c, 0x4d, 0x4e, 0x4e, 0x4f, 0x50,
-                0x50, 0x51, 0x51, 0x52, 0x53, 0x53, 0x54, 0x54,
-                0x55, 0x55, 0x56, 0x56, 0x57, 0x58, 0x58, 0x59,
-                0x59, 0x5a, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c, 0x5d,
-                0x5d, 0x5e, 0x5e, 0x5f, 0x5f, 0x60, 0x60, 0x61,
-                0x61, 0x62, 0x62, 0x63, 0x63, 0x64, 0x64, 0x65,
-                0x65, 0x66, 0x66, 0x66, 0x67, 0x67, 0x68, 0x68,
-                0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c,
-                0x6c, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f,
-                0x6f, 0x70, 0x70, 0x71, 0x71, 0x71, 0x72, 0x72,
-                0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x75,
-                0x76, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x78,
-                0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b,
-                0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e,
-                0x7e, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x81,
-                0x81, 0x81, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83,
-                0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x86,
-                0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88,
-                0x88, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8b,
-                0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d,
-                0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f,
-                0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
-                0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x94,
-                0x94, 0x94, 0x94, 0x95, 0x95, 0x95, 0x96, 0x96,
-                0x96, 0x96, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98,
-                0x98, 0x98, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a,
-                0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c,
-                0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e,
-                0x9e, 0x9e, 0x9f, 0x9f, 0x9f, 0x9f, 0xa0, 0xa0,
-                0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2,
-                0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4,
-                0xa4, 0xa4, 0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
-                0xa6, 0xa6, 0xa6, 0xa6, 0xa7, 0xa7, 0xa7, 0xa7,
-                0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa9, 0xa9, 0xa9,
-                0xa9, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
-                0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xac, 0xad,
-                0xad, 0xad, 0xad, 0xad, 0xae, 0xae, 0xae, 0xae,
-                0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xb0, 0xb0, 0xb0,
-                0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb2,
-                0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
-                0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5,
-                0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb7,
-                0xb7, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb8,
-                0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xba, 0xba,
-                0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
-                0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd,
-                0xbd, 0xbd, 0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
-                0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xc0, 0xc0, 0xc0,
-                0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
-                0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3,
-                0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4,
-                0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6,
-                0xc6, 0xc6, 0xc6, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
-                0xc7, 0xc8, 0xc8, 0xc8, 0xc8, 0xc8, 0xc9, 0xc9,
-                0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca, 0xca,
-                0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc,
-                0xcc, 0xcc, 0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd,
-                0xcd, 0xcd, 0xce, 0xce, 0xce, 0xce, 0xce, 0xce,
-                0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xd0, 0xd0, 0xd0,
-                0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1,
-                0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3,
-                0xd3, 0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4,
-                0xd4, 0xd4, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd5,
-                0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd6, 0xd7, 0xd7,
-                0xd7, 0xd7, 0xd7, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8,
-                0xd8, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xd9, 0xda,
-                0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb, 0xdb,
-                0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
-                0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde,
-                0xde, 0xde, 0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf,
-                0xdf, 0xdf, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
-                0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe1, 0xe2, 0xe2,
-                0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3, 0xe3, 0xe3,
-                0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4, 0xe5,
-                0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6, 0xe6,
-                0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
-                0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9,
-                0xe9, 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea,
-                0xea, 0xea, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
-                0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed,
-                0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
-                0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0,
-                0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
-                0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
-                0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4,
-                0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
-                0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7,
-                0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
-                0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd,
-                0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
-                0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-               {0x13, 0x15, 0x16, 0x18, 0x19, 0x1b, 0x1c, 0x1e,
-                0x1f, 0x20, 0x22, 0x23, 0x24, 0x26, 0x27, 0x28,
-                0x29, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31,
-                0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
-                0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41,
-                0x42, 0x43, 0x44, 0x44, 0x45, 0x46, 0x47, 0x48,
-                0x49, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e,
-                0x4f, 0x50, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54,
-                0x55, 0x55, 0x56, 0x57, 0x57, 0x58, 0x59, 0x59,
-                0x5a, 0x5b, 0x5b, 0x5c, 0x5d, 0x5d, 0x5e, 0x5f,
-                0x5f, 0x60, 0x60, 0x61, 0x62, 0x62, 0x63, 0x63,
-                0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
-                0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c,
-                0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70,
-                0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x74, 0x74,
-                0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x78, 0x78,
-                0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7c,
-                0x7c, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f,
-                0x80, 0x80, 0x81, 0x81, 0x81, 0x82, 0x82, 0x83,
-                0x83, 0x84, 0x84, 0x84, 0x85, 0x85, 0x86, 0x86,
-                0x86, 0x87, 0x87, 0x88, 0x88, 0x88, 0x89, 0x89,
-                0x89, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c,
-                0x8c, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f,
-                0x8f, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92,
-                0x92, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x95,
-                0x95, 0x95, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97,
-                0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x9a, 0x9a,
-                0x9a, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9d,
-                0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f,
-                0x9f, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa2,
-                0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4,
-                0xa4, 0xa5, 0xa5, 0xa5, 0xa5, 0xa6, 0xa6, 0xa6,
-                0xa7, 0xa7, 0xa7, 0xa7, 0xa8, 0xa8, 0xa8, 0xa9,
-                0xa9, 0xa9, 0xa9, 0xaa, 0xaa, 0xaa, 0xab, 0xab,
-                0xab, 0xab, 0xac, 0xac, 0xac, 0xac, 0xad, 0xad,
-                0xad, 0xae, 0xae, 0xae, 0xae, 0xaf, 0xaf, 0xaf,
-                0xaf, 0xb0, 0xb0, 0xb0, 0xb1, 0xb1, 0xb1, 0xb1,
-                0xb2, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3, 0xb3, 0xb3,
-                0xb4, 0xb4, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5,
-                0xb6, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb7,
-                0xb8, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9,
-                0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb,
-                0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
-                0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf,
-                0xbf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1,
-                0xc1, 0xc2, 0xc2, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3,
-                0xc3, 0xc3, 0xc4, 0xc4, 0xc4, 0xc4, 0xc5, 0xc5,
-                0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc6, 0xc6, 0xc7,
-                0xc7, 0xc7, 0xc7, 0xc7, 0xc8, 0xc8, 0xc8, 0xc8,
-                0xc9, 0xc9, 0xc9, 0xc9, 0xc9, 0xca, 0xca, 0xca,
-                0xca, 0xcb, 0xcb, 0xcb, 0xcb, 0xcb, 0xcc, 0xcc,
-                0xcc, 0xcc, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xce,
-                0xce, 0xce, 0xce, 0xce, 0xcf, 0xcf, 0xcf, 0xcf,
-                0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd1, 0xd1, 0xd1,
-                0xd1, 0xd1, 0xd2, 0xd2, 0xd2, 0xd2, 0xd2, 0xd3,
-                0xd3, 0xd3, 0xd3, 0xd4, 0xd4, 0xd4, 0xd4, 0xd4,
-                0xd5, 0xd5, 0xd5, 0xd5, 0xd5, 0xd6, 0xd6, 0xd6,
-                0xd6, 0xd6, 0xd7, 0xd7, 0xd7, 0xd7, 0xd7, 0xd8,
-                0xd8, 0xd8, 0xd8, 0xd8, 0xd9, 0xd9, 0xd9, 0xd9,
-                0xd9, 0xda, 0xda, 0xda, 0xda, 0xda, 0xdb, 0xdb,
-                0xdb, 0xdb, 0xdb, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
-                0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xde, 0xde, 0xde,
-                0xde, 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xe0,
-                0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe1, 0xe1, 0xe1,
-                0xe1, 0xe2, 0xe2, 0xe2, 0xe2, 0xe2, 0xe3, 0xe3,
-                0xe3, 0xe3, 0xe3, 0xe4, 0xe4, 0xe4, 0xe4, 0xe4,
-                0xe4, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe6, 0xe6,
-                0xe6, 0xe6, 0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
-                0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9,
-                0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea, 0xea, 0xea,
-                0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec,
-                0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
-                0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef,
-                0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
-                0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2,
-                0xf2, 0xf2, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
-                0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5,
-                0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
-                0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8,
-                0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
-                0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb,
-                0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
-                0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe,
-                0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-           },
-       };
-
-       reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
-       if (sd->bridge == BRIDGE_TP6810)
-               reg_w(gspca_dev, 0x02, 0x28);
-/*     msleep(50); */
-       bulk_w(gspca_dev, 0x00, gamma_tb[gamma][0], 1024);
-       bulk_w(gspca_dev, 0x01, gamma_tb[gamma][1], 1024);
-       bulk_w(gspca_dev, 0x02, gamma_tb[gamma][2], 1024);
-       if (sd->bridge == BRIDGE_TP6810) {
-               int i;
-
-               reg_w(gspca_dev, 0x02, 0x2b);
-               reg_w(gspca_dev, 0x02, 0x28);
-               for (i = 0; i < 6; i++)
-                       reg_w(gspca_dev, TP6800_R55_GAMMA_R,
-                               gamma_tb[gamma][0][i]);
-               reg_w(gspca_dev, 0x02, 0x2b);
-               reg_w(gspca_dev, 0x02, 0x28);
-               for (i = 0; i < 6; i++)
-                       reg_w(gspca_dev, TP6800_R56_GAMMA_G,
-                               gamma_tb[gamma][1][i]);
-               reg_w(gspca_dev, 0x02, 0x2b);
-               reg_w(gspca_dev, 0x02, 0x28);
-               for (i = 0; i < 6; i++)
-                       reg_w(gspca_dev, TP6800_R57_GAMMA_B,
-                               gamma_tb[gamma][2][i]);
-               reg_w(gspca_dev, 0x02, 0x28);
-       }
-       reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
-/*     msleep(50); */
-}
-
-static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->bridge == BRIDGE_TP6800) {
-               val |= 0x08;            /* grid compensation enable */
-               if (gspca_dev->width == 640)
-                       reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00); /* vga */
-               else
-                       val |= 0x04;            /* scaling down enable */
-               reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, val);
-       } else {
-               val = (val << 5) | 0x08;
-               reg_w(gspca_dev, 0x59, val);
-       }
-}
-
-static void setautogain(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->ag_cnt = val ? AG_CNT_START : -1;
-}
-
-/* set the resolution for sensor cx0342 */
-static void set_resolution(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
-       if (gspca_dev->width == 320) {
-               reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x06);
-               msleep(100);
-               i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
-               msleep(100);
-               reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
-               reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01);      /* qvga */
-               reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, 0x0d);
-               i2c_w(gspca_dev, CX0342_EXPO_LINE_L, 0x37);
-               i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x01);
-       } else {
-               reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x05);
-               msleep(100);
-               i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
-               msleep(100);
-               reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x03);
-               reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00);      /* vga */
-               reg_w(gspca_dev, TP6800_R5D_DEMOSAIC_CFG, 0x09);
-               i2c_w(gspca_dev, CX0342_EXPO_LINE_L, 0xcf);
-               i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00);
-       }
-       i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
-       bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
-                               ARRAY_SIZE(color_gain[0]));
-       setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
-       if (sd->sensor == SENSOR_SOI763A)
-               setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
-}
-
-/* convert the frame rate to a tp68x0 value */
-static int get_fr_idx(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i;
-
-       if (sd->bridge == BRIDGE_TP6800) {
-               for (i = 0; i < ARRAY_SIZE(rates) - 1; i++) {
-                       if (sd->framerate >= rates[i])
-                               break;
-               }
-               i = 6 - i;              /* 1 = 5fps .. 6 = 30fps */
-
-               /* 640x480 * 30 fps does not work */
-               if (i == 6                      /* if 30 fps */
-                && gspca_dev->width == 640)
-                       i = 0x05;               /* 15 fps */
-       } else {
-               for (i = 0; i < ARRAY_SIZE(rates_6810) - 1; i++) {
-                       if (sd->framerate >= rates_6810[i])
-                               break;
-               }
-               i = 7 - i;              /* 3 = 5fps .. 7 = 30fps */
-
-               /* 640x480 * 30 fps does not work */
-               if (i == 7                      /* if 30 fps */
-                && gspca_dev->width == 640)
-                       i = 6;                  /* 15 fps */
-               i |= 0x80;                      /* clock * 1 */
-       }
-       return i;
-}
-
-static void setframerate(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 fr_idx;
-
-       fr_idx = get_fr_idx(gspca_dev);
-
-       if (sd->bridge == BRIDGE_TP6810) {
-               reg_r(gspca_dev, 0x7b);
-               reg_w(gspca_dev, 0x7b,
-                       sd->sensor == SENSOR_CX0342 ? 0x10 : 0x90);
-               if (val >= 128)
-                       fr_idx = 0xf0;          /* lower frame rate */
-       }
-
-       reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, fr_idx);
-
-       if (sd->sensor == SENSOR_CX0342)
-               i2c_w(gspca_dev, CX0342_AUTO_ADC_CALIB, 0x01);
-}
-
-static void setrgain(struct gspca_dev *gspca_dev, s32 rgain)
-{
-       i2c_w(gspca_dev, CX0342_RAW_RGAIN_H, rgain >> 8);
-       i2c_w(gspca_dev, CX0342_RAW_RGAIN_L, rgain);
-       i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
-}
-
-static int sd_setgain(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 val = gspca_dev->gain->val;
-
-       if (sd->sensor == SENSOR_CX0342) {
-               s32 old = gspca_dev->gain->cur.val ?
-                                       gspca_dev->gain->cur.val : 1;
-
-               sd->blue->val = sd->blue->val * val / old;
-               if (sd->blue->val > 4095)
-                       sd->blue->val = 4095;
-               sd->red->val = sd->red->val * val / old;
-               if (sd->red->val > 4095)
-                       sd->red->val = 4095;
-       }
-       if (gspca_dev->streaming) {
-               if (sd->sensor == SENSOR_CX0342)
-                       setexposure(gspca_dev, gspca_dev->exposure->val,
-                                       gspca_dev->gain->val,
-                                       sd->blue->val, sd->red->val);
-               else
-                       setexposure(gspca_dev, gspca_dev->exposure->val,
-                                       gspca_dev->gain->val, 0, 0);
-       }
-       return gspca_dev->usb_err;
-}
-
-static void setbgain(struct gspca_dev *gspca_dev, s32 bgain)
-{
-       i2c_w(gspca_dev, CX0342_RAW_BGAIN_H, bgain >> 8);
-       i2c_w(gspca_dev, CX0342_RAW_BGAIN_L, bgain);
-       i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x80);
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                    const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->bridge = id->driver_info;
-
-       gspca_dev->cam.cam_mode = vga_mode;
-       gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
-       gspca_dev->cam.mode_framerates = sd->bridge == BRIDGE_TP6800 ?
-                       framerates : framerates_6810;
-
-       sd->framerate = 30;             /* default: 30 fps */
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       static const struct cmd tp6800_preinit[] = {
-               {TP6800_R10_SIF_TYPE, 0x01},    /* sif */
-               {TP6800_R11_SIF_CONTROL, 0x01},
-               {TP6800_R15_GPIO_PU, 0x9f},
-               {TP6800_R16_GPIO_PD, 0x9f},
-               {TP6800_R17_GPIO_IO, 0x80},
-               {TP6800_R18_GPIO_DATA, 0x40},   /* LED off */
-       };
-       static const struct cmd tp6810_preinit[] = {
-               {TP6800_R2F_TIMING_CFG, 0x2f},
-               {TP6800_R15_GPIO_PU, 0x6f},
-               {TP6800_R16_GPIO_PD, 0x40},
-               {TP6800_R17_GPIO_IO, 0x9f},
-               {TP6800_R18_GPIO_DATA, 0xc1},   /* LED off */
-       };
-
-       if (sd->bridge == BRIDGE_TP6800)
-               reg_w_buf(gspca_dev, tp6800_preinit,
-                               ARRAY_SIZE(tp6800_preinit));
-       else
-               reg_w_buf(gspca_dev, tp6810_preinit,
-                               ARRAY_SIZE(tp6810_preinit));
-       msleep(15);
-       reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
-       PDEBUG(D_PROBE, "gpio: %02x", gspca_dev->usb_buf[0]);
-/* values:
- *     0x80: snapshot button
- *     0x40: LED
- *     0x20: (bridge / sensor) reset for tp6810 ?
- *     0x07: sensor type ?
- */
-
-       /* guess the sensor type */
-       if (force_sensor >= 0) {
-               sd->sensor = force_sensor;
-       } else {
-               if (sd->bridge == BRIDGE_TP6800) {
-/*fixme: not sure this is working*/
-                       switch (gspca_dev->usb_buf[0] & 0x07) {
-                       case 0:
-                               sd->sensor = SENSOR_SOI763A;
-                               break;
-                       case 1:
-                               sd->sensor = SENSOR_CX0342;
-                               break;
-                       }
-               } else {
-                       int sensor;
-
-                       sensor = probe_6810(gspca_dev);
-                       if (sensor < 0) {
-                               pr_warn("Unknown sensor %d - forced to soi763a\n",
-                                       -sensor);
-                               sensor = SENSOR_SOI763A;
-                       }
-                       sd->sensor = sensor;
-               }
-       }
-       if (sd->sensor == SENSOR_SOI763A) {
-               pr_info("Sensor soi763a\n");
-               if (sd->bridge == BRIDGE_TP6810) {
-                       soi763a_6810_init(gspca_dev);
-               }
-       } else {
-               pr_info("Sensor cx0342\n");
-               if (sd->bridge == BRIDGE_TP6810) {
-                       cx0342_6810_init(gspca_dev);
-               }
-       }
-
-       set_dqt(gspca_dev, 0);
-       return 0;
-}
-
-/* This function is called before choosing the alt setting */
-static int sd_isoc_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       static const struct cmd cx_sensor_init[] = {
-               {CX0342_AUTO_ADC_CALIB, 0x81},
-               {CX0342_EXPO_LINE_L, 0x37},
-               {CX0342_EXPO_LINE_H, 0x01},
-               {CX0342_RAW_GRGAIN_L, 0x00},
-               {CX0342_RAW_GBGAIN_L, 0x00},
-               {CX0342_RAW_RGAIN_L, 0x00},
-               {CX0342_RAW_BGAIN_L, 0x00},
-               {CX0342_SYS_CTRL_0, 0x81},
-       };
-       static const struct cmd cx_bridge_init[] = {
-               {0x4d, 0x00},
-               {0x4c, 0xff},
-               {0x4e, 0xff},
-               {0x4f, 0x00},
-       };
-       static const struct cmd ov_sensor_init[] = {
-               {0x10, 0x75},           /* exposure */
-               {0x76, 0x03},
-               {0x00, 0x00},           /* gain */
-       };
-       static const struct cmd ov_bridge_init[] = {
-               {0x7b, 0x90},
-               {TP6800_R3F_FRAME_RATE, 0x87},
-       };
-
-       if (sd->bridge == BRIDGE_TP6800)
-               return 0;
-       if (sd->sensor == SENSOR_CX0342) {
-               reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x20);
-               reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87);
-               i2c_w_buf(gspca_dev, cx_sensor_init,
-                               ARRAY_SIZE(cx_sensor_init));
-               reg_w_buf(gspca_dev, cx_bridge_init,
-                               ARRAY_SIZE(cx_bridge_init));
-               bulk_w(gspca_dev, 0x03, color_null, sizeof color_null);
-               reg_w(gspca_dev, 0x59, 0x40);
-       } else {
-               reg_w(gspca_dev, TP6800_R12_SIF_ADDR_S, 0x21);
-               i2c_w_buf(gspca_dev, ov_sensor_init,
-                               ARRAY_SIZE(ov_sensor_init));
-               reg_r(gspca_dev, 0x7b);
-               reg_w_buf(gspca_dev, ov_bridge_init,
-                               ARRAY_SIZE(ov_bridge_init));
-       }
-       reg_w(gspca_dev, TP6800_R78_FORMAT,
-                       gspca_dev->curr_mode ? 0x00 : 0x01);
-       return gspca_dev->usb_err;
-}
-
-static void set_led(struct gspca_dev *gspca_dev, int on)
-{
-       u8 data;
-
-       reg_r(gspca_dev, TP6800_R18_GPIO_DATA);
-       data = gspca_dev->usb_buf[0];
-       if (on)
-               data &= ~0x40;
-       else
-               data |= 0x40;
-       reg_w(gspca_dev, TP6800_R18_GPIO_DATA, data);
-}
-
-static void cx0342_6800_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       static const struct cmd reg_init[] = {
-               /* fixme: is this useful? */
-               {TP6800_R17_GPIO_IO, 0x9f},
-               {TP6800_R16_GPIO_PD, 0x40},
-               {TP6800_R10_SIF_TYPE, 0x00},    /* i2c 8 bits */
-               {TP6800_R50, 0x00},
-               {TP6800_R51, 0x00},
-               {TP6800_R52, 0xff},
-               {TP6800_R53, 0x03},
-               {TP6800_R54_DARK_CFG, 0x07},
-               {TP6800_R5C_EDGE_THRLD, 0x40},
-               {TP6800_R7A_BLK_THRLD, 0x40},
-               {TP6800_R2F_TIMING_CFG, 0x17},
-               {TP6800_R30_SENSOR_CFG, 0x18},  /* G1B..RG0 */
-               {TP6800_R37_FRONT_DARK_ST, 0x00},
-               {TP6800_R38_FRONT_DARK_END, 0x00},
-               {TP6800_R39_REAR_DARK_ST_L, 0x00},
-               {TP6800_R3A_REAR_DARK_ST_H, 0x00},
-               {TP6800_R3B_REAR_DARK_END_L, 0x00},
-               {TP6800_R3C_REAR_DARK_END_H, 0x00},
-               {TP6800_R3D_HORIZ_DARK_LINE_L, 0x00},
-               {TP6800_R3E_HORIZ_DARK_LINE_H, 0x00},
-               {TP6800_R21_ENDP_1_CTL, 0x03},
-
-               {TP6800_R31_PIXEL_START, 0x0b},
-               {TP6800_R32_PIXEL_END_L, 0x8a},
-               {TP6800_R33_PIXEL_END_H, 0x02},
-               {TP6800_R34_LINE_START, 0x0e},
-               {TP6800_R35_LINE_END_L, 0xf4},
-               {TP6800_R36_LINE_END_H, 0x01},
-               {TP6800_R78_FORMAT, 0x00},
-               {TP6800_R12_SIF_ADDR_S, 0x20},  /* cx0342 i2c addr */
-       };
-       static const struct cmd sensor_init[] = {
-               {CX0342_OUTPUT_CTRL, 0x07},
-               {CX0342_BYPASS_MODE, 0x58},
-               {CX0342_GPXLTHD_L, 0x16},
-               {CX0342_RBPXLTHD_L, 0x16},
-               {CX0342_PLANETHD_L, 0xc0},
-               {CX0342_PLANETHD_H, 0x03},
-               {CX0342_RB_GAP_L, 0xff},
-               {CX0342_RB_GAP_H, 0x07},
-               {CX0342_G_GAP_L, 0xff},
-               {CX0342_G_GAP_H, 0x07},
-               {CX0342_RST_OVERFLOW_L, 0x5c},
-               {CX0342_RST_OVERFLOW_H, 0x01},
-               {CX0342_DATA_OVERFLOW_L, 0xfc},
-               {CX0342_DATA_OVERFLOW_H, 0x03},
-               {CX0342_DATA_UNDERFLOW_L, 0x00},
-               {CX0342_DATA_UNDERFLOW_H, 0x00},
-               {CX0342_SYS_CTRL_0, 0x40},
-               {CX0342_GLOBAL_GAIN, 0x01},
-               {CX0342_CLOCK_GEN, 0x00},
-               {CX0342_SYS_CTRL_0, 0x02},
-               {CX0342_IDLE_CTRL, 0x05},
-               {CX0342_ADCGN, 0x00},
-               {CX0342_ADC_CTL, 0x00},
-               {CX0342_LVRST_BLBIAS, 0x01},
-               {CX0342_VTHSEL, 0x0b},
-               {CX0342_RAMP_RIV, 0x0b},
-               {CX0342_LDOSEL, 0x07},
-               {CX0342_SPV_VALUE_L, 0x40},
-               {CX0342_SPV_VALUE_H, 0x02},
-       };
-
-       reg_w_buf(gspca_dev, reg_init, ARRAY_SIZE(reg_init));
-       i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
-       i2c_w_buf(gspca_dev, cx0342_timing_seq, ARRAY_SIZE(cx0342_timing_seq));
-       reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10);
-       reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
-       i2c_w(gspca_dev, CX0342_EXPO_LINE_H, 0x00);
-       i2c_w(gspca_dev, CX0342_SYS_CTRL_0, 0x01);
-       if (sd->sensor == SENSOR_CX0342)
-               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
-                       v4l2_ctrl_g_ctrl(gspca_dev->gain),
-                       v4l2_ctrl_g_ctrl(sd->blue),
-                       v4l2_ctrl_g_ctrl(sd->red));
-       else
-               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
-                       v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
-       set_led(gspca_dev, 1);
-       set_resolution(gspca_dev);
-}
-
-static void cx0342_6810_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       static const struct cmd sensor_init_2[] = {
-               {CX0342_EXPO_LINE_L, 0x6f},
-               {CX0342_EXPO_LINE_H, 0x02},
-               {CX0342_RAW_GRGAIN_L, 0x00},
-               {CX0342_RAW_GBGAIN_L, 0x00},
-               {CX0342_RAW_RGAIN_L, 0x00},
-               {CX0342_RAW_BGAIN_L, 0x00},
-               {CX0342_SYS_CTRL_0, 0x81},
-       };
-       static const struct cmd bridge_init_2[] = {
-               {0x4d, 0x00},
-               {0x4c, 0xff},
-               {0x4e, 0xff},
-               {0x4f, 0x00},
-               {TP6800_R7A_BLK_THRLD, 0x00},
-               {TP6800_R79_QUALITY, 0x04},
-               {TP6800_R79_QUALITY, 0x01},
-       };
-       static const struct cmd bridge_init_3[] = {
-               {TP6800_R31_PIXEL_START, 0x08},
-               {TP6800_R32_PIXEL_END_L, 0x87},
-               {TP6800_R33_PIXEL_END_H, 0x02},
-               {TP6800_R34_LINE_START, 0x0e},
-               {TP6800_R35_LINE_END_L, 0xf4},
-               {TP6800_R36_LINE_END_H, 0x01},
-       };
-       static const struct cmd sensor_init_3[] = {
-               {CX0342_AUTO_ADC_CALIB, 0x81},
-               {CX0342_EXPO_LINE_L, 0x6f},
-               {CX0342_EXPO_LINE_H, 0x02},
-               {CX0342_RAW_GRGAIN_L, 0x00},
-               {CX0342_RAW_GBGAIN_L, 0x00},
-               {CX0342_RAW_RGAIN_L, 0x00},
-               {CX0342_RAW_BGAIN_L, 0x00},
-               {CX0342_SYS_CTRL_0, 0x81},
-       };
-       static const struct cmd bridge_init_5[] = {
-               {0x4d, 0x00},
-               {0x4c, 0xff},
-               {0x4e, 0xff},
-               {0x4f, 0x00},
-       };
-       static const struct cmd sensor_init_4[] = {
-               {CX0342_EXPO_LINE_L, 0xd3},
-               {CX0342_EXPO_LINE_H, 0x01},
-/*fixme: gains, but 00..80 only*/
-               {CX0342_RAW_GRGAIN_L, 0x40},
-               {CX0342_RAW_GBGAIN_L, 0x40},
-               {CX0342_RAW_RGAIN_L, 0x40},
-               {CX0342_RAW_BGAIN_L, 0x40},
-               {CX0342_SYS_CTRL_0, 0x81},
-       };
-       static const struct cmd sensor_init_5[] = {
-               {CX0342_IDLE_CTRL, 0x05},
-               {CX0342_ADCGN, 0x00},
-               {CX0342_ADC_CTL, 0x00},
-               {CX0342_LVRST_BLBIAS, 0x01},
-               {CX0342_VTHSEL, 0x0b},
-               {CX0342_RAMP_RIV, 0x0b},
-               {CX0342_LDOSEL, 0x07},
-               {CX0342_SPV_VALUE_L, 0x40},
-               {CX0342_SPV_VALUE_H, 0x02},
-               {CX0342_AUTO_ADC_CALIB, 0x81},
-       };
-
-       reg_w(gspca_dev, 0x22, gspca_dev->alt);
-       i2c_w_buf(gspca_dev, sensor_init_2, ARRAY_SIZE(sensor_init_2));
-       reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2));
-       reg_w_buf(gspca_dev, tp6810_cx_init_common,
-                       ARRAY_SIZE(tp6810_cx_init_common));
-       reg_w_buf(gspca_dev, bridge_init_3, ARRAY_SIZE(bridge_init_3));
-       if (gspca_dev->curr_mode) {
-               reg_w(gspca_dev, 0x4a, 0x7f);
-               reg_w(gspca_dev, 0x07, 0x05);
-               reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00);      /* vga */
-       } else {
-               reg_w(gspca_dev, 0x4a, 0xff);
-               reg_w(gspca_dev, 0x07, 0x85);
-               reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01);      /* qvga */
-       }
-       setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
-       reg_w_buf(gspca_dev, tp6810_bridge_start,
-                       ARRAY_SIZE(tp6810_bridge_start));
-       setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
-       bulk_w(gspca_dev, 0x03, color_gain[SENSOR_CX0342],
-                               ARRAY_SIZE(color_gain[0]));
-       reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0x87);
-       i2c_w_buf(gspca_dev, sensor_init_3, ARRAY_SIZE(sensor_init_3));
-       reg_w_buf(gspca_dev, bridge_init_5, ARRAY_SIZE(bridge_init_5));
-       i2c_w_buf(gspca_dev, sensor_init_4, ARRAY_SIZE(sensor_init_4));
-       reg_w_buf(gspca_dev, bridge_init_5, ARRAY_SIZE(bridge_init_5));
-       i2c_w_buf(gspca_dev, sensor_init_5, ARRAY_SIZE(sensor_init_5));
-
-       set_led(gspca_dev, 1);
-/*     setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual)); */
-}
-
-static void soi763a_6800_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       static const struct cmd reg_init[] = {
-               {TP6800_R79_QUALITY, 0x04},
-               {TP6800_R79_QUALITY, 0x01},
-               {TP6800_R10_SIF_TYPE, 0x00},    /* i2c 8 bits */
-
-               {TP6800_R50, 0x00},
-               {TP6800_R51, 0x00},
-               {TP6800_R52, 0xff},
-               {TP6800_R53, 0x03},
-               {TP6800_R54_DARK_CFG, 0x07},
-               {TP6800_R5C_EDGE_THRLD, 0x40},
-
-               {TP6800_R79_QUALITY, 0x03},
-               {TP6800_R7A_BLK_THRLD, 0x40},
-
-               {TP6800_R2F_TIMING_CFG, 0x46},
-               {TP6800_R30_SENSOR_CFG, 0x10},  /* BG1..G0R */
-               {TP6800_R37_FRONT_DARK_ST, 0x00},
-               {TP6800_R38_FRONT_DARK_END, 0x00},
-               {TP6800_R39_REAR_DARK_ST_L, 0x00},
-               {TP6800_R3A_REAR_DARK_ST_H, 0x00},
-               {TP6800_R3B_REAR_DARK_END_L, 0x00},
-               {TP6800_R3C_REAR_DARK_END_H, 0x00},
-               {TP6800_R3D_HORIZ_DARK_LINE_L, 0x00},
-               {TP6800_R3E_HORIZ_DARK_LINE_H, 0x00},
-               {TP6800_R21_ENDP_1_CTL, 0x03},
-
-               {TP6800_R3F_FRAME_RATE, 0x04},  /* 15 fps */
-               {TP6800_R5D_DEMOSAIC_CFG, 0x0e}, /* scale down - medium edge */
-
-               {TP6800_R31_PIXEL_START, 0x1b},
-               {TP6800_R32_PIXEL_END_L, 0x9a},
-               {TP6800_R33_PIXEL_END_H, 0x02},
-               {TP6800_R34_LINE_START, 0x0f},
-               {TP6800_R35_LINE_END_L, 0xf4},
-               {TP6800_R36_LINE_END_H, 0x01},
-               {TP6800_R78_FORMAT, 0x01},      /* qvga */
-               {TP6800_R12_SIF_ADDR_S, 0x21},  /* soi763a i2c addr */
-               {TP6800_R1A_SIF_TX_DATA2, 0x00},
-       };
-       static const struct cmd sensor_init[] = {
-               {0x12, 0x48},           /* mirror - RGB */
-               {0x13, 0xa0},           /* clock - no AGC nor AEC */
-               {0x03, 0xa4},           /* saturation */
-               {0x04, 0x30},           /* hue */
-               {0x05, 0x88},           /* contrast */
-               {0x06, 0x60},           /* brightness */
-               {0x10, 0x41},           /* AEC */
-               {0x11, 0x40},           /* clock rate */
-               {0x13, 0xa0},
-               {0x14, 0x00},           /* 640x480 */
-               {0x15, 0x14},
-               {0x1f, 0x41},
-               {0x20, 0x80},
-               {0x23, 0xee},
-               {0x24, 0x50},
-               {0x25, 0x7a},
-               {0x26, 0x00},
-               {0x27, 0xe2},
-               {0x28, 0xb0},
-               {0x2a, 0x00},
-               {0x2b, 0x00},
-               {0x2d, 0x81},
-               {0x2f, 0x9d},
-               {0x60, 0x80},
-               {0x61, 0x00},
-               {0x62, 0x88},
-               {0x63, 0x11},
-               {0x64, 0x89},
-               {0x65, 0x00},
-               {0x67, 0x94},
-               {0x68, 0x7a},
-               {0x69, 0x0f},
-               {0x6c, 0x80},
-               {0x6d, 0x80},
-               {0x6e, 0x80},
-               {0x6f, 0xff},
-               {0x71, 0x20},
-               {0x74, 0x20},
-               {0x75, 0x86},
-               {0x77, 0xb5},
-               {0x17, 0x18},           /* H href start */
-               {0x18, 0xbf},           /* H href end */
-               {0x19, 0x03},           /* V start */
-               {0x1a, 0xf8},           /* V end */
-               {0x01, 0x80},           /* blue gain */
-               {0x02, 0x80},           /* red gain */
-       };
-
-       reg_w_buf(gspca_dev, reg_init, ARRAY_SIZE(reg_init));
-
-       i2c_w(gspca_dev, 0x12, 0x80);           /* sensor reset */
-       msleep(10);
-
-       i2c_w_buf(gspca_dev, sensor_init, ARRAY_SIZE(sensor_init));
-
-       reg_w(gspca_dev, TP6800_R5C_EDGE_THRLD, 0x10);
-       reg_w(gspca_dev, TP6800_R54_DARK_CFG, 0x00);
-
-       setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
-
-       bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A],
-                               ARRAY_SIZE(color_gain[0]));
-
-       set_led(gspca_dev, 1);
-       if (sd->sensor == SENSOR_CX0342)
-               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
-                       v4l2_ctrl_g_ctrl(gspca_dev->gain),
-                       v4l2_ctrl_g_ctrl(sd->blue),
-                       v4l2_ctrl_g_ctrl(sd->red));
-       else
-               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
-                       v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
-       if (sd->sensor == SENSOR_SOI763A)
-               setquality(gspca_dev, v4l2_ctrl_g_ctrl(sd->jpegqual));
-       setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
-}
-
-static void soi763a_6810_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       static const struct cmd bridge_init_2[] = {
-               {TP6800_R7A_BLK_THRLD, 0x00},
-               {TP6800_R79_QUALITY, 0x04},
-               {TP6800_R79_QUALITY, 0x01},
-       };
-       static const struct cmd bridge_init_3[] = {
-               {TP6800_R31_PIXEL_START, 0x20},
-               {TP6800_R32_PIXEL_END_L, 0x9f},
-               {TP6800_R33_PIXEL_END_H, 0x02},
-               {TP6800_R34_LINE_START, 0x13},
-               {TP6800_R35_LINE_END_L, 0xf8},
-               {TP6800_R36_LINE_END_H, 0x01},
-       };
-       static const struct cmd bridge_init_6[] = {
-               {0x08, 0xff},
-               {0x09, 0xff},
-               {0x0a, 0x5f},
-               {0x0b, 0x80},
-       };
-
-       reg_w(gspca_dev, 0x22, gspca_dev->alt);
-       bulk_w(gspca_dev, 0x03, color_null, sizeof color_null);
-       reg_w(gspca_dev, 0x59, 0x40);
-       if (sd->sensor == SENSOR_CX0342)
-               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
-                       v4l2_ctrl_g_ctrl(gspca_dev->gain),
-                       v4l2_ctrl_g_ctrl(sd->blue),
-                       v4l2_ctrl_g_ctrl(sd->red));
-       else
-               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
-                       v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
-       reg_w_buf(gspca_dev, bridge_init_2, ARRAY_SIZE(bridge_init_2));
-       reg_w_buf(gspca_dev, tp6810_ov_init_common,
-                       ARRAY_SIZE(tp6810_ov_init_common));
-       reg_w_buf(gspca_dev, bridge_init_3, ARRAY_SIZE(bridge_init_3));
-       if (gspca_dev->curr_mode) {
-               reg_w(gspca_dev, 0x4a, 0x7f);
-               reg_w(gspca_dev, 0x07, 0x05);
-               reg_w(gspca_dev, TP6800_R78_FORMAT, 0x00);      /* vga */
-       } else {
-               reg_w(gspca_dev, 0x4a, 0xff);
-               reg_w(gspca_dev, 0x07, 0x85);
-               reg_w(gspca_dev, TP6800_R78_FORMAT, 0x01);      /* qvga */
-       }
-       setgamma(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma));
-       reg_w_buf(gspca_dev, tp6810_bridge_start,
-                       ARRAY_SIZE(tp6810_bridge_start));
-
-       if (gspca_dev->curr_mode) {
-               reg_w(gspca_dev, 0x4f, 0x00);
-               reg_w(gspca_dev, 0x4e, 0x7c);
-       }
-
-       reg_w(gspca_dev, 0x00, 0x00);
-
-       setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
-       bulk_w(gspca_dev, 0x03, color_gain[SENSOR_SOI763A],
-                               ARRAY_SIZE(color_gain[0]));
-       set_led(gspca_dev, 1);
-       reg_w(gspca_dev, TP6800_R3F_FRAME_RATE, 0xf0);
-       if (sd->sensor == SENSOR_CX0342)
-               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
-                       v4l2_ctrl_g_ctrl(gspca_dev->gain),
-                       v4l2_ctrl_g_ctrl(sd->blue),
-                       v4l2_ctrl_g_ctrl(sd->red));
-       else
-               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure),
-                       v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
-       reg_w_buf(gspca_dev, bridge_init_6, ARRAY_SIZE(bridge_init_6));
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width);
-       set_dqt(gspca_dev, sd->quality);
-       if (sd->bridge == BRIDGE_TP6800) {
-               if (sd->sensor == SENSOR_CX0342)
-                       cx0342_6800_start(gspca_dev);
-               else
-                       soi763a_6800_start(gspca_dev);
-       } else {
-               if (sd->sensor == SENSOR_CX0342)
-                       cx0342_6810_start(gspca_dev);
-               else
-                       soi763a_6810_start(gspca_dev);
-               reg_w_buf(gspca_dev, tp6810_late_start,
-                               ARRAY_SIZE(tp6810_late_start));
-               reg_w(gspca_dev, 0x80, 0x03);
-               reg_w(gspca_dev, 0x82, gspca_dev->curr_mode ? 0x0a : 0x0e);
-
-               if (sd->sensor == SENSOR_CX0342)
-                       setexposure(gspca_dev,
-                               v4l2_ctrl_g_ctrl(gspca_dev->exposure),
-                               v4l2_ctrl_g_ctrl(gspca_dev->gain),
-                               v4l2_ctrl_g_ctrl(sd->blue),
-                               v4l2_ctrl_g_ctrl(sd->red));
-               else
-                       setexposure(gspca_dev,
-                               v4l2_ctrl_g_ctrl(gspca_dev->exposure),
-                               v4l2_ctrl_g_ctrl(gspca_dev->gain), 0, 0);
-               if (sd->sensor == SENSOR_SOI763A)
-                       setquality(gspca_dev,
-                                  v4l2_ctrl_g_ctrl(sd->jpegqual));
-               if (sd->bridge == BRIDGE_TP6810)
-                       setautogain(gspca_dev,
-                                   v4l2_ctrl_g_ctrl(gspca_dev->autogain));
-       }
-
-       setframerate(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
-
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->bridge == BRIDGE_TP6800)
-               reg_w(gspca_dev, TP6800_R2F_TIMING_CFG, 0x03);
-       set_led(gspca_dev, 0);
-       reg_w(gspca_dev, TP6800_R21_ENDP_1_CTL, 0x00);
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,
-                       int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* the start of frame contains:
-        *      ff d8
-        *      ff fe
-        *      width / 16
-        *      height / 8
-        *      quality
-        */
-       if (sd->bridge == BRIDGE_TP6810) {
-               if (*data != 0x5a) {
-/*fixme: don't discard the whole frame..*/
-                       if (*data == 0xaa || *data == 0x00)
-                               return;
-                       if (*data > 0xc0) {
-                               PDEBUG(D_FRAM, "bad frame");
-                               gspca_dev->last_packet_type = DISCARD_PACKET;
-                               return;
-                       }
-               }
-               data++;
-               len--;
-               if (*data == 0xff && data[1] == 0xd8) {
-/*fixme: there may be information in the 4 high bits*/
-                       if ((data[6] & 0x0f) != sd->quality)
-                               set_dqt(gspca_dev, data[6] & 0x0f);
-                       gspca_frame_add(gspca_dev, FIRST_PACKET,
-                                       sd->jpeg_hdr, JPEG_HDR_SZ);
-                       gspca_frame_add(gspca_dev, INTER_PACKET,
-                                       data + 7, len - 7);
-               } else if (data[len - 2] == 0xff && data[len - 1] == 0xd9) {
-                       gspca_frame_add(gspca_dev, LAST_PACKET,
-                                       data, len);
-               } else {
-                       gspca_frame_add(gspca_dev, INTER_PACKET,
-                                       data, len);
-               }
-               return;
-       }
-
-       switch (*data) {
-       case 0x55:
-               gspca_frame_add(gspca_dev, LAST_PACKET, data, 0);
-
-               if (len < 8
-                || data[1] != 0xff || data[2] != 0xd8
-                || data[3] != 0xff || data[4] != 0xfe) {
-
-                       /* Have only seen this with corrupt frames */
-                       gspca_dev->last_packet_type = DISCARD_PACKET;
-                       return;
-               }
-               if (data[7] != sd->quality)
-                       set_dqt(gspca_dev, data[7]);
-               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                               sd->jpeg_hdr, JPEG_HDR_SZ);
-               gspca_frame_add(gspca_dev, INTER_PACKET,
-                               data + 8, len - 8);
-               break;
-       case 0xaa:
-               gspca_dev->last_packet_type = DISCARD_PACKET;
-               break;
-       case 0xcc:
-               if (data[1] != 0xff || data[2] != 0xd8)
-                       gspca_frame_add(gspca_dev, INTER_PACKET,
-                                       data + 1, len - 1);
-               else
-                       gspca_dev->last_packet_type = DISCARD_PACKET;
-               break;
-       }
-}
-
-static void sd_dq_callback(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int ret, alen;
-       int luma, expo;
-
-       if (sd->ag_cnt < 0)
-               return;
-       if (--sd->ag_cnt > 5)
-               return;
-       switch (sd->ag_cnt) {
-/*     case 5: */
-       default:
-               reg_w(gspca_dev, 0x7d, 0x00);
-               break;
-       case 4:
-               reg_w(gspca_dev, 0x27, 0xb0);
-               break;
-       case 3:
-               reg_w(gspca_dev, 0x0c, 0x01);
-               break;
-       case 2:
-               ret = usb_bulk_msg(gspca_dev->dev,
-                               usb_rcvbulkpipe(gspca_dev->dev, 0x02),
-                               gspca_dev->usb_buf,
-                               32,
-                               &alen,
-                               500);
-               if (ret < 0) {
-                       pr_err("bulk err %d\n", ret);
-                       break;
-               }
-               /* values not used (unknown) */
-               break;
-       case 1:
-               reg_w(gspca_dev, 0x27, 0xd0);
-               break;
-       case 0:
-               ret = usb_bulk_msg(gspca_dev->dev,
-                               usb_rcvbulkpipe(gspca_dev->dev, 0x02),
-                               gspca_dev->usb_buf,
-                               32,
-                               &alen,
-                               500);
-               if (ret < 0) {
-                       pr_err("bulk err %d\n", ret);
-                       break;
-               }
-               luma = ((gspca_dev->usb_buf[8] << 8) + gspca_dev->usb_buf[7] +
-                       (gspca_dev->usb_buf[11] << 8) + gspca_dev->usb_buf[10] +
-                       (gspca_dev->usb_buf[14] << 8) + gspca_dev->usb_buf[13] +
-                       (gspca_dev->usb_buf[17] << 8) + gspca_dev->usb_buf[16] +
-                       (gspca_dev->usb_buf[20] << 8) + gspca_dev->usb_buf[19] +
-                       (gspca_dev->usb_buf[23] << 8) + gspca_dev->usb_buf[22] +
-                       (gspca_dev->usb_buf[26] << 8) + gspca_dev->usb_buf[25] +
-                       (gspca_dev->usb_buf[29] << 8) + gspca_dev->usb_buf[28])
-                               / 8;
-               if (gspca_dev->width == 640)
-                       luma /= 4;
-               reg_w(gspca_dev, 0x7d, 0x00);
-
-               expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
-               ret = gspca_expo_autogain(gspca_dev, luma,
-                               60,     /* desired luma */
-                               6,      /* dead zone */
-                               2,      /* gain knee */
-                               70);    /* expo knee */
-               sd->ag_cnt = AG_CNT_START;
-               if (sd->bridge == BRIDGE_TP6810) {
-                       int new_expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
-
-                       if ((expo >= 128 && new_expo < 128)
-                        || (expo < 128 && new_expo >= 128))
-                               setframerate(gspca_dev, new_expo);
-               }
-               break;
-       }
-}
-
-/* get stream parameters (framerate) */
-static void sd_get_streamparm(struct gspca_dev *gspca_dev,
-                            struct v4l2_streamparm *parm)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct v4l2_captureparm *cp = &parm->parm.capture;
-       struct v4l2_fract *tpf = &cp->timeperframe;
-       int fr, i;
-
-       cp->capability |= V4L2_CAP_TIMEPERFRAME;
-       tpf->numerator = 1;
-       i = get_fr_idx(gspca_dev);
-       if (i & 0x80) {
-               if (sd->bridge == BRIDGE_TP6800)
-                       fr = rates[6 - (i & 0x07)];
-               else
-                       fr = rates_6810[7 - (i & 0x07)];
-       } else {
-               fr = rates[6 - i];
-       }
-       tpf->denominator = fr;
-}
-
-/* set stream parameters (framerate) */
-static void sd_set_streamparm(struct gspca_dev *gspca_dev,
-                            struct v4l2_streamparm *parm)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct v4l2_captureparm *cp = &parm->parm.capture;
-       struct v4l2_fract *tpf = &cp->timeperframe;
-       int fr, i;
-
-       sd->framerate = tpf->denominator / tpf->numerator;
-       if (gspca_dev->streaming)
-               setframerate(gspca_dev, v4l2_ctrl_g_ctrl(gspca_dev->exposure));
-
-       /* Return the actual framerate */
-       i = get_fr_idx(gspca_dev);
-       if (i & 0x80)
-               fr = rates_6810[7 - (i & 0x07)];
-       else
-               fr = rates[6 - i];
-       tpf->numerator = 1;
-       tpf->denominator = fr;
-}
-
-static int sd_set_jcomp(struct gspca_dev *gspca_dev,
-                       struct v4l2_jpegcompression *jcomp)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor != SENSOR_SOI763A)
-               return -ENOTTY;
-       v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
-       return 0;
-}
-
-static int sd_get_jcomp(struct gspca_dev *gspca_dev,
-                       struct v4l2_jpegcompression *jcomp)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->sensor != SENSOR_SOI763A)
-               return -ENOTTY;
-       memset(jcomp, 0, sizeof *jcomp);
-       jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
-       jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
-                       | V4L2_JPEG_MARKER_DQT;
-       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_SHARPNESS:
-               setsharpness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_GAMMA:
-               setgamma(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               setbgain(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_RED_BALANCE:
-               setrgain(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_EXPOSURE:
-               sd_setgain(gspca_dev);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               if (ctrl->val)
-                       break;
-               sd_setgain(gspca_dev);
-               break;
-       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
-               jpeg_set_qual(sd->jpeg_hdr, ctrl->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,
-                       V4L2_CID_EXPOSURE, 1, 0xdc, 1, 0x4e);
-       if (sd->sensor == SENSOR_CX0342) {
-               sd->red = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_RED_BALANCE, 0, 4095, 1, 256);
-               sd->blue = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BLUE_BALANCE, 0, 4095, 1, 256);
-       }
-       if (sd->sensor == SENSOR_SOI763A)
-               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAIN, 0, 15, 1, 3);
-       else
-               gspca_dev->gain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAIN, 0, 4095, 1, 256);
-       sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SHARPNESS, 0, 3, 1, 2);
-       sd->gamma = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAMMA, 0, NGAMMA - 1, 1,
-                       (sd->sensor == SENSOR_SOI763A &&
-                        sd->bridge == BRIDGE_TP6800) ? 0 : 1);
-       if (sd->bridge == BRIDGE_TP6810)
-               gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-       if (sd->sensor == SENSOR_SOI763A)
-               sd->jpegqual = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_JPEG_COMPRESSION_QUALITY,
-                       0, 15, 1, (sd->bridge == BRIDGE_TP6810) ? 0 : 13);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-       if (gspca_dev->autogain)
-               v4l2_ctrl_auto_cluster(3, &gspca_dev->autogain, 0, false);
-       else
-               v4l2_ctrl_cluster(2, &gspca_dev->exposure);
-       return 0;
-}
-
-static const struct sd_desc sd_desc = {
-       .name = KBUILD_MODNAME,
-       .config = sd_config,
-       .init = sd_init,
-       .init_controls = sd_init_controls,
-       .isoc_init = sd_isoc_init,
-       .start = sd_start,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-       .dq_callback = sd_dq_callback,
-       .get_streamparm = sd_get_streamparm,
-       .set_streamparm = sd_set_streamparm,
-       .get_jcomp = sd_get_jcomp,
-       .set_jcomp = sd_set_jcomp,
-};
-
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x06a2, 0x0003), .driver_info = BRIDGE_TP6800},
-       {USB_DEVICE(0x06a2, 0x6810), .driver_info = BRIDGE_TP6810},
-       {}                      /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-static int sd_probe(struct usb_interface *interface,
-                   const struct usb_device_id *id)
-{
-       return gspca_dev_probe(interface, id, &sd_desc, sizeof(struct sd),
-                              THIS_MODULE);
-}
-
-static struct usb_driver sd_driver = {
-       .name = KBUILD_MODNAME,
-       .id_table = device_table,
-       .probe = sd_probe,
-       .disconnect = gspca_disconnect,
-#ifdef CONFIG_PM
-       .suspend = gspca_suspend,
-       .resume = gspca_resume,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
-
-module_param(force_sensor, int, 0644);
-MODULE_PARM_DESC(force_sensor,
-       "Force sensor. 0: cx0342, 1: soi763a");
diff --git a/drivers/media/video/gspca/tv8532.c b/drivers/media/video/gspca/tv8532.c
deleted file mode 100644 (file)
index 8591324..0000000
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Quickcam cameras initialization data
- *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-#define MODULE_NAME "tv8532"
-
-#include "gspca.h"
-
-MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
-MODULE_DESCRIPTION("TV8532 USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       __u8 packet;
-};
-
-static const struct v4l2_pix_format sif_mode[] = {
-       {176, 144, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {352, 288, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-
-/* TV-8532A (ICM532A) registers (LE) */
-#define R00_PART_CONTROL 0x00
-#define                LATENT_CHANGE   0x80
-#define                EXPO_CHANGE     0x04
-#define R01_TIMING_CONTROL_LOW 0x01
-#define                CMD_EEprom_Open 0x30
-#define                CMD_EEprom_Close 0x29
-#define R03_TABLE_ADDR 0x03
-#define R04_WTRAM_DATA_L 0x04
-#define R05_WTRAM_DATA_M 0x05
-#define R06_WTRAM_DATA_H 0x06
-#define R07_TABLE_LEN  0x07
-#define R08_RAM_WRITE_ACTION 0x08
-#define R0C_AD_WIDTHL  0x0c
-#define R0D_AD_WIDTHH  0x0d
-#define R0E_AD_HEIGHTL 0x0e
-#define R0F_AD_HEIGHTH 0x0f
-#define R10_AD_COL_BEGINL 0x10
-#define R11_AD_COL_BEGINH 0x11
-#define                MIRROR          0x04    /* [10] */
-#define R14_AD_ROW_BEGINL 0x14
-#define R15_AD_ROWBEGINH  0x15
-#define R1C_AD_EXPOSE_TIMEL 0x1c
-#define R20_GAIN_G1L   0x20
-#define R21_GAIN_G1H   0x21
-#define R22_GAIN_RL    0x22
-#define R23_GAIN_RH    0x23
-#define R24_GAIN_BL    0x24
-#define R25_GAIN_BH    0x25
-#define R26_GAIN_G2L   0x26
-#define R27_GAIN_G2H   0x27
-#define R28_QUANT      0x28
-#define R29_LINE       0x29
-#define R2C_POLARITY   0x2c
-#define R2D_POINT      0x2d
-#define R2E_POINTH     0x2e
-#define R2F_POINTB     0x2f
-#define R30_POINTBH    0x30
-#define R31_UPD                0x31
-#define R2A_HIGH_BUDGET 0x2a
-#define R2B_LOW_BUDGET 0x2b
-#define R34_VID                0x34
-#define R35_VIDH       0x35
-#define R36_PID                0x36
-#define R37_PIDH       0x37
-#define R39_Test1      0x39            /* GPIO */
-#define R3B_Test3      0x3b            /* GPIO */
-#define R83_AD_IDH     0x83
-#define R91_AD_SLOPEREG 0x91
-#define R94_AD_BITCONTROL 0x94
-
-static const u8 eeprom_data[][3] = {
-/*     dataH dataM dataL */
-       {0x01, 0x00, 0x01},
-       {0x01, 0x80, 0x11},
-       {0x05, 0x00, 0x14},
-       {0x05, 0x00, 0x1c},
-       {0x0d, 0x00, 0x1e},
-       {0x05, 0x00, 0x1f},
-       {0x05, 0x05, 0x19},
-       {0x05, 0x01, 0x1b},
-       {0x05, 0x09, 0x1e},
-       {0x0d, 0x89, 0x2e},
-       {0x05, 0x89, 0x2f},
-       {0x05, 0x0d, 0xd9},
-       {0x05, 0x09, 0xf1},
-};
-
-
-/* write 1 byte */
-static void reg_w1(struct gspca_dev *gspca_dev,
-                 __u16 index, __u8 value)
-{
-       gspca_dev->usb_buf[0] = value;
-       usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0x02,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,      /* value */
-                       index, gspca_dev->usb_buf, 1, 500);
-}
-
-/* write 2 bytes */
-static void reg_w2(struct gspca_dev *gspca_dev,
-                 u16 index, u16 value)
-{
-       gspca_dev->usb_buf[0] = value;
-       gspca_dev->usb_buf[1] = value >> 8;
-       usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0x02,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0,      /* value */
-                       index, gspca_dev->usb_buf, 2, 500);
-}
-
-static void tv_8532WriteEEprom(struct gspca_dev *gspca_dev)
-{
-       int i;
-
-       reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Open);
-       for (i = 0; i < ARRAY_SIZE(eeprom_data); i++) {
-               reg_w1(gspca_dev, R03_TABLE_ADDR, i);
-               reg_w1(gspca_dev, R04_WTRAM_DATA_L, eeprom_data[i][2]);
-               reg_w1(gspca_dev, R05_WTRAM_DATA_M, eeprom_data[i][1]);
-               reg_w1(gspca_dev, R06_WTRAM_DATA_H, eeprom_data[i][0]);
-               reg_w1(gspca_dev, R08_RAM_WRITE_ACTION, 0);
-       }
-       reg_w1(gspca_dev, R07_TABLE_LEN, i);
-       reg_w1(gspca_dev, R01_TIMING_CONTROL_LOW, CMD_EEprom_Close);
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                    const struct usb_device_id *id)
-{
-       struct cam *cam;
-
-       cam = &gspca_dev->cam;
-       cam->cam_mode = sif_mode;
-       cam->nmodes = ARRAY_SIZE(sif_mode);
-
-       return 0;
-}
-
-static void tv_8532_setReg(struct gspca_dev *gspca_dev)
-{
-       reg_w1(gspca_dev, R3B_Test3, 0x0a);     /* Test0Sel = 10 */
-       /******************************************************/
-       reg_w1(gspca_dev, R0E_AD_HEIGHTL, 0x90);
-       reg_w1(gspca_dev, R0F_AD_HEIGHTH, 0x01);
-       reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, 0x018f);
-       reg_w1(gspca_dev, R10_AD_COL_BEGINL, 0x44);
-                                               /* begin active line */
-       reg_w1(gspca_dev, R11_AD_COL_BEGINH, 0x00);
-                                               /* mirror and digital gain */
-       reg_w1(gspca_dev, R14_AD_ROW_BEGINL, 0x0a);
-
-       reg_w1(gspca_dev, R94_AD_BITCONTROL, 0x02);
-       reg_w1(gspca_dev, R91_AD_SLOPEREG, 0x00);
-       reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE);
-                                               /* = 0x84 */
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       tv_8532WriteEEprom(gspca_dev);
-
-       return 0;
-}
-
-static void setexposure(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_w2(gspca_dev, R1C_AD_EXPOSE_TIMEL, val);
-       reg_w1(gspca_dev, R00_PART_CONTROL, LATENT_CHANGE | EXPO_CHANGE);
-                                               /* 0x84 */
-}
-
-static void setgain(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_w2(gspca_dev, R20_GAIN_G1L, val);
-       reg_w2(gspca_dev, R22_GAIN_RL, val);
-       reg_w2(gspca_dev, R24_GAIN_BL, val);
-       reg_w2(gspca_dev, R26_GAIN_G2L, val);
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       reg_w1(gspca_dev, R0C_AD_WIDTHL, 0xe8);         /* 0x20; 0x0c */
-       reg_w1(gspca_dev, R0D_AD_WIDTHH, 0x03);
-
-       /************************************************/
-       reg_w1(gspca_dev, R28_QUANT, 0x90);
-                                       /* 0x72 compressed mode 0x28 */
-       if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
-               /* 176x144 */
-               reg_w1(gspca_dev, R29_LINE, 0x41);
-                                       /* CIF - 2 lines/packet */
-       } else {
-               /* 352x288 */
-               reg_w1(gspca_dev, R29_LINE, 0x81);
-                                       /* CIF - 2 lines/packet */
-       }
-       /************************************************/
-       reg_w1(gspca_dev, R2C_POLARITY, 0x10);          /* slow clock */
-       reg_w1(gspca_dev, R2D_POINT, 0x14);
-       reg_w1(gspca_dev, R2E_POINTH, 0x01);
-       reg_w1(gspca_dev, R2F_POINTB, 0x12);
-       reg_w1(gspca_dev, R30_POINTBH, 0x01);
-
-       tv_8532_setReg(gspca_dev);
-
-       /************************************************/
-       reg_w1(gspca_dev, R31_UPD, 0x01);       /* update registers */
-       msleep(200);
-       reg_w1(gspca_dev, R31_UPD, 0x00);       /* end update */
-
-       gspca_dev->empty_packet = 0;            /* check the empty packets */
-       sd->packet = 0;                         /* ignore the first packets */
-
-       return 0;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       reg_w1(gspca_dev, R3B_Test3, 0x0b);     /* Test0Sel = 11 = GPIO */
-}
-
-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;
-       int packet_type0, packet_type1;
-
-       packet_type0 = packet_type1 = INTER_PACKET;
-       if (gspca_dev->empty_packet) {
-               gspca_dev->empty_packet = 0;
-               sd->packet = gspca_dev->height / 2;
-               packet_type0 = FIRST_PACKET;
-       } else if (sd->packet == 0)
-               return;                 /* 2 more lines in 352x288 ! */
-       sd->packet--;
-       if (sd->packet == 0)
-               packet_type1 = LAST_PACKET;
-
-       /* each packet contains:
-        * - header 2 bytes
-        * - RGRG line
-        * - 4 bytes
-        * - GBGB line
-        * - 4 bytes
-        */
-       gspca_frame_add(gspca_dev, packet_type0,
-                       data + 2, gspca_dev->width);
-       gspca_frame_add(gspca_dev, packet_type1,
-                       data + gspca_dev->width + 5, gspca_dev->width);
-}
-
-static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct gspca_dev *gspca_dev =
-               container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
-
-       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:
-               setgain(gspca_dev, ctrl->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 v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 2);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 0, 0x18f, 1, 0x18f);
-       v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAIN, 0, 0x7ff, 1, 0x100);
-
-       if (hdl->error) {
-               pr_err("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,
-       .stopN = sd_stopN,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x046d, 0x0920)},
-       {USB_DEVICE(0x046d, 0x0921)},
-       {USB_DEVICE(0x0545, 0x808b)},
-       {USB_DEVICE(0x0545, 0x8333)},
-       {USB_DEVICE(0x0923, 0x010f)},
-       {}
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/vc032x.c b/drivers/media/video/gspca/vc032x.c
deleted file mode 100644 (file)
index e500795..0000000
+++ /dev/null
@@ -1,3850 +0,0 @@
-/*
- * Z-star vc0321 library
- *
- * Copyright (C) 2009-2010 Jean-François Moine <http://moinejf.free.fr>
- * Copyright (C) 2006 Koninski Artur takeshi87@o2.pl
- * Copyright (C) 2006 Michel Xhaard
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "vc032x"
-
-#include "gspca.h"
-
-MODULE_AUTHOR("Jean-François Moine <http://moinejf.free.fr>");
-MODULE_DESCRIPTION("GSPCA/VC032X USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-       struct { /* hvflip cluster */
-               struct v4l2_ctrl *hflip;
-               struct v4l2_ctrl *vflip;
-       };
-
-       u8 image_offset;
-
-       u8 bridge;
-       u8 sensor;
-       u8 flags;
-#define FL_SAMSUNG 0x01                /* SamsungQ1 (2 sensors) */
-#define FL_HFLIP 0x02          /* mirrored by default */
-#define FL_VFLIP 0x04          /* vertical flipped by default */
-};
-enum bridges {
-       BRIDGE_VC0321,
-       BRIDGE_VC0323,
-};
-enum sensors {
-       SENSOR_HV7131R,
-       SENSOR_MI0360,
-       SENSOR_MI1310_SOC,
-       SENSOR_MI1320,
-       SENSOR_MI1320_SOC,
-       SENSOR_OV7660,
-       SENSOR_OV7670,
-       SENSOR_PO1200,
-       SENSOR_PO3130NC,
-       SENSOR_POxxxx,
-       NSENSORS
-};
-
-
-static const struct v4l2_pix_format vc0321_mode[] = {
-       {320, 240, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_YVYU, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-static const struct v4l2_pix_format vc0323_mode[] = {
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-       {1280, 960, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, /* mi1310_soc only */
-               .bytesperline = 1280,
-               .sizeimage = 1280 * 960 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 2},
-};
-static const struct v4l2_pix_format bi_mode[] = {
-       {320, 240, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 2},
-       {640, 480, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 1},
-       {1280, 1024, V4L2_PIX_FMT_YUYV, V4L2_FIELD_NONE,
-               .bytesperline = 1280,
-               .sizeimage = 1280 * 1024 * 2,
-               .colorspace = V4L2_COLORSPACE_SRGB,
-               .priv = 0},
-};
-static const struct v4l2_pix_format svga_mode[] = {
-       {800, 600, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 800,
-               .sizeimage = 800 * 600 * 1 / 4 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-
-/* OV7660/7670 registers */
-#define OV7660_REG_MVFP 0x1e
-#define OV7660_MVFP_MIRROR     0x20
-#define OV7660_MVFP_VFLIP      0x10
-
-static const u8 mi0360_matrix[9] = {
-       0x50, 0xf8, 0xf8, 0xf5, 0x50, 0xfb, 0xff, 0xf1, 0x50
-};
-
-static const u8 mi0360_initVGA_JPG[][4] = {
-       {0xb0, 0x03, 0x19, 0xcc},
-       {0xb0, 0x04, 0x02, 0xcc},
-       {0xb3, 0x00, 0x24, 0xcc},
-       {0xb3, 0x00, 0x25, 0xcc},
-       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},
-       {0xb3, 0x05, 0x01, 0xcc},
-       {0xb3, 0x06, 0x03, 0xcc},
-       {0xb3, 0x03, 0x0a, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x01, 0xcc},
-       {0xb3, 0x23, 0xe0, 0xcc},
-       {0xb3, 0x04, 0x05, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},
-       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x02, 0xcc},
-       {0xb3, 0x17, 0x7f, 0xcc},
-       {0xb3, 0x35, 0xdd, 0xcc},       /* i2c add: 5d */
-       {0xb3, 0x34, 0x02, 0xcc},
-       {0xb3, 0x00, 0x25, 0xcc},
-       {0xbc, 0x00, 0x71, 0xcc},
-       {0xb8, 0x00, 0x13, 0xcc},
-       {0xb8, 0x27, 0x20, 0xcc},
-       {0xb8, 0x2c, 0x50, 0xcc},
-       {0xb8, 0x2d, 0xf8, 0xcc},
-       {0xb8, 0x2e, 0xf8, 0xcc},
-       {0xb8, 0x2f, 0xf8, 0xcc},
-       {0xb8, 0x30, 0x50, 0xcc},
-       {0xb8, 0x31, 0xf8, 0xcc},
-       {0xb8, 0x32, 0xf8, 0xcc},
-       {0xb8, 0x33, 0xf8, 0xcc},
-       {0xb8, 0x34, 0x50, 0xcc},
-       {0xb8, 0x35, 0x00, 0xcc},
-       {0xb8, 0x36, 0x00, 0xcc},
-       {0xb8, 0x37, 0x00, 0xcc},
-       {0xb8, 0x01, 0x79, 0xcc},
-       {0xb8, 0x08, 0xe0, 0xcc},
-       {0xb3, 0x01, 0x41, 0xcc},
-       {0xb8, 0x01, 0x79, 0xcc},
-       {0xb8, 0x14, 0x18, 0xcc},
-       {0xb8, 0xb2, 0x0a, 0xcc},
-       {0xb8, 0xb4, 0x0a, 0xcc},
-       {0xb8, 0xb5, 0x0a, 0xcc},
-       {0xb8, 0xfe, 0x00, 0xcc},
-       {0xb8, 0xff, 0x28, 0xcc},
-       {0xb9, 0x00, 0x28, 0xcc},
-       {0xb9, 0x01, 0x28, 0xcc},
-       {0xb9, 0x02, 0x28, 0xcc},
-       {0xb9, 0x03, 0x00, 0xcc},
-       {0xb9, 0x04, 0x00, 0xcc},
-       {0xb9, 0x05, 0x3c, 0xcc},
-       {0xb9, 0x06, 0x3c, 0xcc},
-       {0xb9, 0x07, 0x3c, 0xcc},
-       {0xb9, 0x08, 0x3c, 0xcc},
-       {0xb8, 0x8e, 0x00, 0xcc},
-       {0xb8, 0x8f, 0xff, 0xcc},
-       {0xb8, 0x81, 0x09, 0xcc},
-       {0x31, 0x00, 0x00, 0xbb},
-       {0x09, 0x01, 0xc7, 0xbb},
-       {0x34, 0x01, 0x00, 0xbb},
-       {0x2b, 0x00, 0x28, 0xbb},
-       {0x2c, 0x00, 0x30, 0xbb},
-       {0x2d, 0x00, 0x30, 0xbb},
-       {0x2e, 0x00, 0x28, 0xbb},
-       {0x62, 0x04, 0x11, 0xbb},
-       {0x03, 0x01, 0xe0, 0xbb},
-       {0x2c, 0x00, 0x2c, 0xbb},
-       {0x20, 0xd0, 0x00, 0xbb},
-       {0x01, 0x00, 0x08, 0xbb},
-       {0x06, 0x00, 0x10, 0xbb},
-       {0x05, 0x00, 0x20, 0xbb},
-       {0x20, 0x00, 0x00, 0xbb},
-       {0xb6, 0x00, 0x00, 0xcc},
-       {0xb6, 0x03, 0x02, 0xcc},
-       {0xb6, 0x02, 0x80, 0xcc},
-       {0xb6, 0x05, 0x01, 0xcc},
-       {0xb6, 0x04, 0xe0, 0xcc},
-       {0xb6, 0x12, 0x78, 0xcc},
-       {0xb6, 0x18, 0x02, 0xcc},
-       {0xb6, 0x17, 0x58, 0xcc},
-       {0xb6, 0x16, 0x00, 0xcc},
-       {0xb6, 0x22, 0x12, 0xcc},
-       {0xb6, 0x23, 0x0b, 0xcc},
-       {0xb3, 0x02, 0x02, 0xcc},
-       {0xbf, 0xc0, 0x39, 0xcc},
-       {0xbf, 0xc1, 0x04, 0xcc},
-       {0xbf, 0xcc, 0x10, 0xcc},
-       {0xb9, 0x12, 0x00, 0xcc},
-       {0xb9, 0x13, 0x0a, 0xcc},
-       {0xb9, 0x14, 0x0a, 0xcc},
-       {0xb9, 0x15, 0x0a, 0xcc},
-       {0xb9, 0x16, 0x0a, 0xcc},
-       {0xb9, 0x18, 0x00, 0xcc},
-       {0xb9, 0x19, 0x0f, 0xcc},
-       {0xb9, 0x1a, 0x0f, 0xcc},
-       {0xb9, 0x1b, 0x0f, 0xcc},
-       {0xb9, 0x1c, 0x0f, 0xcc},
-       {0xb8, 0x8e, 0x00, 0xcc},
-       {0xb8, 0x8f, 0xff, 0xcc},
-       {0xb6, 0x12, 0xf8, 0xcc},
-       {0xb8, 0x0c, 0x20, 0xcc},
-       {0xb8, 0x0d, 0x70, 0xcc},
-       {0xb6, 0x13, 0x13, 0xcc},
-       {0x35, 0x00, 0x60, 0xbb},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {}
-};
-static const u8 mi0360_initQVGA_JPG[][4] = {
-       {0xb0, 0x03, 0x19, 0xcc},
-       {0xb0, 0x04, 0x02, 0xcc},
-       {0xb3, 0x00, 0x24, 0xcc},
-       {0xb3, 0x00, 0x25, 0xcc},
-       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},
-       {0xb3, 0x05, 0x01, 0xcc},
-       {0xb3, 0x06, 0x03, 0xcc},
-       {0xb3, 0x03, 0x0a, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x01, 0xcc},
-       {0xb3, 0x23, 0xe0, 0xcc},
-       {0xb3, 0x04, 0x05, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},
-       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x02, 0xcc},
-       {0xb3, 0x17, 0x7f, 0xcc},
-       {0xb3, 0x35, 0xdd, 0xcc},
-       {0xb3, 0x34, 0x02, 0xcc},
-       {0xb3, 0x00, 0x25, 0xcc},
-       {0xbc, 0x00, 0xd1, 0xcc},
-       {0xb8, 0x00, 0x13, 0xcc},
-       {0xb8, 0x27, 0x20, 0xcc},
-       {0xb8, 0x2c, 0x50, 0xcc},
-       {0xb8, 0x2d, 0xf8, 0xcc},
-       {0xb8, 0x2e, 0xf8, 0xcc},
-       {0xb8, 0x2f, 0xf8, 0xcc},
-       {0xb8, 0x30, 0x50, 0xcc},
-       {0xb8, 0x31, 0xf8, 0xcc},
-       {0xb8, 0x32, 0xf8, 0xcc},
-       {0xb8, 0x33, 0xf8, 0xcc},
-       {0xb8, 0x34, 0x50, 0xcc},
-       {0xb8, 0x35, 0x00, 0xcc},
-       {0xb8, 0x36, 0x00, 0xcc},
-       {0xb8, 0x37, 0x00, 0xcc},
-       {0xb8, 0x01, 0x79, 0xcc},
-       {0xb8, 0x08, 0xe0, 0xcc},
-       {0xb3, 0x01, 0x41, 0xcc},
-       {0xb8, 0x01, 0x79, 0xcc},
-       {0xb8, 0x14, 0x18, 0xcc},
-       {0xb8, 0xb2, 0x0a, 0xcc},
-       {0xb8, 0xb4, 0x0a, 0xcc},
-       {0xb8, 0xb5, 0x0a, 0xcc},
-       {0xb8, 0xfe, 0x00, 0xcc},
-       {0xb8, 0xff, 0x28, 0xcc},
-       {0xb9, 0x00, 0x28, 0xcc},
-       {0xb9, 0x01, 0x28, 0xcc},
-       {0xb9, 0x02, 0x28, 0xcc},
-       {0xb9, 0x03, 0x00, 0xcc},
-       {0xb9, 0x04, 0x00, 0xcc},
-       {0xb9, 0x05, 0x3c, 0xcc},
-       {0xb9, 0x06, 0x3c, 0xcc},
-       {0xb9, 0x07, 0x3c, 0xcc},
-       {0xb9, 0x08, 0x3c, 0xcc},
-       {0xb8, 0x8e, 0x00, 0xcc},
-       {0xb8, 0x8f, 0xff, 0xcc},
-       {0xb8, 0x81, 0x09, 0xcc},
-       {0x31, 0x00, 0x00, 0xbb},
-       {0x09, 0x01, 0xc7, 0xbb},
-       {0x34, 0x01, 0x00, 0xbb},
-       {0x2b, 0x00, 0x28, 0xbb},
-       {0x2c, 0x00, 0x30, 0xbb},
-       {0x2d, 0x00, 0x30, 0xbb},
-       {0x2e, 0x00, 0x28, 0xbb},
-       {0x62, 0x04, 0x11, 0xbb},
-       {0x03, 0x01, 0xe0, 0xbb},
-       {0x2c, 0x00, 0x2c, 0xbb},
-       {0x20, 0xd0, 0x00, 0xbb},
-       {0x01, 0x00, 0x08, 0xbb},
-       {0x06, 0x00, 0x10, 0xbb},
-       {0x05, 0x00, 0x20, 0xbb},
-       {0x20, 0x00, 0x00, 0xbb},
-       {0xb6, 0x00, 0x00, 0xcc},
-       {0xb6, 0x03, 0x01, 0xcc},
-       {0xb6, 0x02, 0x40, 0xcc},
-       {0xb6, 0x05, 0x00, 0xcc},
-       {0xb6, 0x04, 0xf0, 0xcc},
-       {0xb6, 0x12, 0x78, 0xcc},
-       {0xb6, 0x18, 0x00, 0xcc},
-       {0xb6, 0x17, 0x96, 0xcc},
-       {0xb6, 0x16, 0x00, 0xcc},
-       {0xb6, 0x22, 0x12, 0xcc},
-       {0xb6, 0x23, 0x0b, 0xcc},
-       {0xb3, 0x02, 0x02, 0xcc},
-       {0xbf, 0xc0, 0x39, 0xcc},
-       {0xbf, 0xc1, 0x04, 0xcc},
-       {0xbf, 0xcc, 0x10, 0xcc},
-       {0xb9, 0x12, 0x00, 0xcc},
-       {0xb9, 0x13, 0x0a, 0xcc},
-       {0xb9, 0x14, 0x0a, 0xcc},
-       {0xb9, 0x15, 0x0a, 0xcc},
-       {0xb9, 0x16, 0x0a, 0xcc},
-       {0xb9, 0x18, 0x00, 0xcc},
-       {0xb9, 0x19, 0x0f, 0xcc},
-       {0xb9, 0x1a, 0x0f, 0xcc},
-       {0xb9, 0x1b, 0x0f, 0xcc},
-       {0xb9, 0x1c, 0x0f, 0xcc},
-       {0xb8, 0x8e, 0x00, 0xcc},
-       {0xb8, 0x8f, 0xff, 0xcc},
-       {0xb6, 0x12, 0xf8, 0xcc},
-       {0xb6, 0x13, 0x13, 0xcc},
-       {0xbc, 0x02, 0x18, 0xcc},
-       {0xbc, 0x03, 0x50, 0xcc},
-       {0xbc, 0x04, 0x18, 0xcc},
-       {0xbc, 0x05, 0x00, 0xcc},
-       {0xbc, 0x06, 0x00, 0xcc},
-       {0xbc, 0x08, 0x30, 0xcc},
-       {0xbc, 0x09, 0x40, 0xcc},
-       {0xbc, 0x0a, 0x10, 0xcc},
-       {0xb8, 0x0c, 0x20, 0xcc},
-       {0xb8, 0x0d, 0x70, 0xcc},
-       {0xbc, 0x0b, 0x00, 0xcc},
-       {0xbc, 0x0c, 0x00, 0xcc},
-       {0x35, 0x00, 0xef, 0xbb},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {}
-};
-
-static const u8 mi1310_socinitVGA_JPG[][4] = {
-       {0xb0, 0x03, 0x19, 0xcc},
-       {0xb0, 0x04, 0x02, 0xcc},
-       {0xb3, 0x00, 0x64, 0xcc},
-       {0xb3, 0x00, 0x65, 0xcc},
-       {0xb3, 0x05, 0x00, 0xcc},
-       {0xb3, 0x06, 0x00, 0xcc},
-       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},
-       {0xb3, 0x34, 0x02, 0xcc},
-       {0xb3, 0x35, 0xdd, 0xcc},       /* i2c add: 5d */
-       {0xb3, 0x02, 0x00, 0xcc},
-       {0xb3, 0x03, 0x0a, 0xcc},
-       {0xb3, 0x04, 0x05, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x03, 0xcc},
-       {0xb3, 0x23, 0xc0, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},
-       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x04, 0xcc},
-       {0xb3, 0x17, 0xff, 0xcc},
-       {0xb3, 0x00, 0x65, 0xcc},
-       {0xb8, 0x00, 0x00, 0xcc},
-       {0xbc, 0x00, 0xd0, 0xcc},
-       {0xbc, 0x01, 0x01, 0xcc},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0xc8, 0x9f, 0x0b, 0xbb},
-       {0x5b, 0x00, 0x01, 0xbb},
-       {0x2f, 0xde, 0x20, 0xbb},
-       {0xf0, 0x00, 0x00, 0xbb},
-       {0x20, 0x03, 0x02, 0xbb},       /* h/v flip */
-       {0xf0, 0x00, 0x01, 0xbb},
-       {0x05, 0x00, 0x07, 0xbb},
-       {0x34, 0x00, 0x00, 0xbb},
-       {0x35, 0xff, 0x00, 0xbb},
-       {0xdc, 0x07, 0x02, 0xbb},
-       {0xdd, 0x3c, 0x18, 0xbb},
-       {0xde, 0x92, 0x6d, 0xbb},
-       {0xdf, 0xcd, 0xb1, 0xbb},
-       {0xe0, 0xff, 0xe7, 0xbb},
-       {0x06, 0xf0, 0x0d, 0xbb},
-       {0x06, 0x70, 0x0e, 0xbb},
-       {0x4c, 0x00, 0x01, 0xbb},
-       {0x4d, 0x00, 0x01, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x2e, 0x0c, 0x55, 0xbb},
-       {0x21, 0xb6, 0x6e, 0xbb},
-       {0x36, 0x30, 0x10, 0xbb},
-       {0x37, 0x00, 0xc1, 0xbb},
-       {0xf0, 0x00, 0x00, 0xbb},
-       {0x07, 0x00, 0x84, 0xbb},
-       {0x08, 0x02, 0x4a, 0xbb},
-       {0x05, 0x01, 0x10, 0xbb},
-       {0x06, 0x00, 0x39, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x58, 0x02, 0x67, 0xbb},
-       {0x57, 0x02, 0x00, 0xbb},
-       {0x5a, 0x02, 0x67, 0xbb},
-       {0x59, 0x02, 0x00, 0xbb},
-       {0x5c, 0x12, 0x0d, 0xbb},
-       {0x5d, 0x16, 0x11, 0xbb},
-       {0x39, 0x06, 0x18, 0xbb},
-       {0x3a, 0x06, 0x18, 0xbb},
-       {0x3b, 0x06, 0x18, 0xbb},
-       {0x3c, 0x06, 0x18, 0xbb},
-       {0x64, 0x7b, 0x5b, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x36, 0x30, 0x10, 0xbb},
-       {0x37, 0x00, 0xc0, 0xbb},
-       {0xbc, 0x0e, 0x00, 0xcc},
-       {0xbc, 0x0f, 0x05, 0xcc},
-       {0xbc, 0x10, 0xc0, 0xcc},
-       {0xbc, 0x11, 0x03, 0xcc},
-       {0xb6, 0x00, 0x00, 0xcc},
-       {0xb6, 0x03, 0x02, 0xcc},
-       {0xb6, 0x02, 0x80, 0xcc},
-       {0xb6, 0x05, 0x01, 0xcc},
-       {0xb6, 0x04, 0xe0, 0xcc},
-       {0xb6, 0x12, 0xf8, 0xcc},
-       {0xb6, 0x13, 0x25, 0xcc},
-       {0xb6, 0x18, 0x02, 0xcc},
-       {0xb6, 0x17, 0x58, 0xcc},
-       {0xb6, 0x16, 0x00, 0xcc},
-       {0xb6, 0x22, 0x12, 0xcc},
-       {0xb6, 0x23, 0x0b, 0xcc},
-       {0xbf, 0xc0, 0x39, 0xcc},
-       {0xbf, 0xc1, 0x04, 0xcc},
-       {0xbf, 0xcc, 0x00, 0xcc},
-       {0xbc, 0x02, 0x18, 0xcc},
-       {0xbc, 0x03, 0x50, 0xcc},
-       {0xbc, 0x04, 0x18, 0xcc},
-       {0xbc, 0x05, 0x00, 0xcc},
-       {0xbc, 0x06, 0x00, 0xcc},
-       {0xbc, 0x08, 0x30, 0xcc},
-       {0xbc, 0x09, 0x40, 0xcc},
-       {0xbc, 0x0a, 0x10, 0xcc},
-       {0xbc, 0x0b, 0x00, 0xcc},
-       {0xbc, 0x0c, 0x00, 0xcc},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {0xf0, 0x00, 0x01, 0xbb},
-       {0x80, 0x00, 0x03, 0xbb},
-       {0x81, 0xc7, 0x14, 0xbb},
-       {0x82, 0xeb, 0xe8, 0xbb},
-       {0x83, 0xfe, 0xf4, 0xbb},
-       {0x84, 0xcd, 0x10, 0xbb},
-       {0x85, 0xf3, 0xee, 0xbb},
-       {0x86, 0xff, 0xf1, 0xbb},
-       {0x87, 0xcd, 0x10, 0xbb},
-       {0x88, 0xf3, 0xee, 0xbb},
-       {0x89, 0x01, 0xf1, 0xbb},
-       {0x8a, 0xe5, 0x17, 0xbb},
-       {0x8b, 0xe8, 0xe2, 0xbb},
-       {0x8c, 0xf7, 0xed, 0xbb},
-       {0x8d, 0x00, 0xff, 0xbb},
-       {0x8e, 0xec, 0x10, 0xbb},
-       {0x8f, 0xf0, 0xed, 0xbb},
-       {0x90, 0xf9, 0xf2, 0xbb},
-       {0x91, 0x00, 0x00, 0xbb},
-       {0x92, 0xe9, 0x0d, 0xbb},
-       {0x93, 0xf4, 0xf2, 0xbb},
-       {0x94, 0xfb, 0xf5, 0xbb},
-       {0x95, 0x00, 0xff, 0xbb},
-       {0xb6, 0x0f, 0x08, 0xbb},
-       {0xb7, 0x3d, 0x16, 0xbb},
-       {0xb8, 0x0c, 0x04, 0xbb},
-       {0xb9, 0x1c, 0x07, 0xbb},
-       {0xba, 0x0a, 0x03, 0xbb},
-       {0xbb, 0x1b, 0x09, 0xbb},
-       {0xbc, 0x17, 0x0d, 0xbb},
-       {0xbd, 0x23, 0x1d, 0xbb},
-       {0xbe, 0x00, 0x28, 0xbb},
-       {0xbf, 0x11, 0x09, 0xbb},
-       {0xc0, 0x16, 0x15, 0xbb},
-       {0xc1, 0x00, 0x1b, 0xbb},
-       {0xc2, 0x0e, 0x07, 0xbb},
-       {0xc3, 0x14, 0x10, 0xbb},
-       {0xc4, 0x00, 0x17, 0xbb},
-       {0x06, 0x74, 0x8e, 0xbb},
-       {0xf0, 0x00, 0x01, 0xbb},
-       {0x06, 0xf4, 0x8e, 0xbb},
-       {0x00, 0x00, 0x50, 0xdd},
-       {0x06, 0x74, 0x8e, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x24, 0x50, 0x20, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x34, 0x0c, 0x50, 0xbb},
-       {0xb3, 0x01, 0x41, 0xcc},
-       {0xf0, 0x00, 0x00, 0xbb},
-       {0x03, 0x03, 0xc0, 0xbb},
-       {},
-};
-static const u8 mi1310_socinitQVGA_JPG[][4] = {
-       {0xb0, 0x03, 0x19, 0xcc},       {0xb0, 0x04, 0x02, 0xcc},
-       {0xb3, 0x00, 0x64, 0xcc},       {0xb3, 0x00, 0x65, 0xcc},
-       {0xb3, 0x05, 0x00, 0xcc},       {0xb3, 0x06, 0x00, 0xcc},
-       {0xb3, 0x08, 0x01, 0xcc},       {0xb3, 0x09, 0x0c, 0xcc},
-       {0xb3, 0x34, 0x02, 0xcc},       {0xb3, 0x35, 0xdd, 0xcc},
-       {0xb3, 0x02, 0x00, 0xcc},       {0xb3, 0x03, 0x0a, 0xcc},
-       {0xb3, 0x04, 0x05, 0xcc},       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},       {0xb3, 0x22, 0x03, 0xcc},
-       {0xb3, 0x23, 0xc0, 0xcc},       {0xb3, 0x14, 0x00, 0xcc},
-       {0xb3, 0x15, 0x00, 0xcc},       {0xb3, 0x16, 0x04, 0xcc},
-       {0xb3, 0x17, 0xff, 0xcc},       {0xb3, 0x00, 0x65, 0xcc},
-       {0xb8, 0x00, 0x00, 0xcc},       {0xbc, 0x00, 0xf0, 0xcc},
-       {0xbc, 0x01, 0x01, 0xcc},       {0xf0, 0x00, 0x02, 0xbb},
-       {0xc8, 0x9f, 0x0b, 0xbb},       {0x5b, 0x00, 0x01, 0xbb},
-       {0x2f, 0xde, 0x20, 0xbb},       {0xf0, 0x00, 0x00, 0xbb},
-       {0x20, 0x03, 0x02, 0xbb},       /* h/v flip */
-       {0xf0, 0x00, 0x01, 0xbb},
-       {0x05, 0x00, 0x07, 0xbb},       {0x34, 0x00, 0x00, 0xbb},
-       {0x35, 0xff, 0x00, 0xbb},       {0xdc, 0x07, 0x02, 0xbb},
-       {0xdd, 0x3c, 0x18, 0xbb},       {0xde, 0x92, 0x6d, 0xbb},
-       {0xdf, 0xcd, 0xb1, 0xbb},       {0xe0, 0xff, 0xe7, 0xbb},
-       {0x06, 0xf0, 0x0d, 0xbb},       {0x06, 0x70, 0x0e, 0xbb},
-       {0x4c, 0x00, 0x01, 0xbb},       {0x4d, 0x00, 0x01, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},       {0x2e, 0x0c, 0x55, 0xbb},
-       {0x21, 0xb6, 0x6e, 0xbb},       {0x36, 0x30, 0x10, 0xbb},
-       {0x37, 0x00, 0xc1, 0xbb},       {0xf0, 0x00, 0x00, 0xbb},
-       {0x07, 0x00, 0x84, 0xbb},       {0x08, 0x02, 0x4a, 0xbb},
-       {0x05, 0x01, 0x10, 0xbb},       {0x06, 0x00, 0x39, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},       {0x58, 0x02, 0x67, 0xbb},
-       {0x57, 0x02, 0x00, 0xbb},       {0x5a, 0x02, 0x67, 0xbb},
-       {0x59, 0x02, 0x00, 0xbb},       {0x5c, 0x12, 0x0d, 0xbb},
-       {0x5d, 0x16, 0x11, 0xbb},       {0x39, 0x06, 0x18, 0xbb},
-       {0x3a, 0x06, 0x18, 0xbb},       {0x3b, 0x06, 0x18, 0xbb},
-       {0x3c, 0x06, 0x18, 0xbb},       {0x64, 0x7b, 0x5b, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},       {0x36, 0x30, 0x10, 0xbb},
-       {0x37, 0x00, 0xc0, 0xbb},       {0xbc, 0x0e, 0x00, 0xcc},
-       {0xbc, 0x0f, 0x05, 0xcc},       {0xbc, 0x10, 0xc0, 0xcc},
-       {0xbc, 0x11, 0x03, 0xcc},       {0xb6, 0x00, 0x00, 0xcc},
-       {0xb6, 0x03, 0x01, 0xcc},       {0xb6, 0x02, 0x40, 0xcc},
-       {0xb6, 0x05, 0x00, 0xcc},       {0xb6, 0x04, 0xf0, 0xcc},
-       {0xb6, 0x12, 0xf8, 0xcc},       {0xb6, 0x13, 0x25, 0xcc},
-       {0xb6, 0x18, 0x00, 0xcc},       {0xb6, 0x17, 0x96, 0xcc},
-       {0xb6, 0x16, 0x00, 0xcc},       {0xb6, 0x22, 0x12, 0xcc},
-       {0xb6, 0x23, 0x0b, 0xcc},       {0xbf, 0xc0, 0x39, 0xcc},
-       {0xbf, 0xc1, 0x04, 0xcc},       {0xbf, 0xcc, 0x00, 0xcc},
-       {0xb3, 0x5c, 0x01, 0xcc},       {0xf0, 0x00, 0x01, 0xbb},
-       {0x80, 0x00, 0x03, 0xbb},       {0x81, 0xc7, 0x14, 0xbb},
-       {0x82, 0xeb, 0xe8, 0xbb},       {0x83, 0xfe, 0xf4, 0xbb},
-       {0x84, 0xcd, 0x10, 0xbb},       {0x85, 0xf3, 0xee, 0xbb},
-       {0x86, 0xff, 0xf1, 0xbb},       {0x87, 0xcd, 0x10, 0xbb},
-       {0x88, 0xf3, 0xee, 0xbb},       {0x89, 0x01, 0xf1, 0xbb},
-       {0x8a, 0xe5, 0x17, 0xbb},       {0x8b, 0xe8, 0xe2, 0xbb},
-       {0x8c, 0xf7, 0xed, 0xbb},       {0x8d, 0x00, 0xff, 0xbb},
-       {0x8e, 0xec, 0x10, 0xbb},       {0x8f, 0xf0, 0xed, 0xbb},
-       {0x90, 0xf9, 0xf2, 0xbb},       {0x91, 0x00, 0x00, 0xbb},
-       {0x92, 0xe9, 0x0d, 0xbb},       {0x93, 0xf4, 0xf2, 0xbb},
-       {0x94, 0xfb, 0xf5, 0xbb},       {0x95, 0x00, 0xff, 0xbb},
-       {0xb6, 0x0f, 0x08, 0xbb},       {0xb7, 0x3d, 0x16, 0xbb},
-       {0xb8, 0x0c, 0x04, 0xbb},       {0xb9, 0x1c, 0x07, 0xbb},
-       {0xba, 0x0a, 0x03, 0xbb},       {0xbb, 0x1b, 0x09, 0xbb},
-       {0xbc, 0x17, 0x0d, 0xbb},       {0xbd, 0x23, 0x1d, 0xbb},
-       {0xbe, 0x00, 0x28, 0xbb},       {0xbf, 0x11, 0x09, 0xbb},
-       {0xc0, 0x16, 0x15, 0xbb},       {0xc1, 0x00, 0x1b, 0xbb},
-       {0xc2, 0x0e, 0x07, 0xbb},       {0xc3, 0x14, 0x10, 0xbb},
-       {0xc4, 0x00, 0x17, 0xbb},       {0x06, 0x74, 0x8e, 0xbb},
-       {0xf0, 0x00, 0x01, 0xbb},       {0x06, 0xf4, 0x8e, 0xbb},
-       {0x00, 0x00, 0x50, 0xdd},       {0x06, 0x74, 0x8e, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},       {0x24, 0x50, 0x20, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},       {0x34, 0x0c, 0x50, 0xbb},
-       {0xb3, 0x01, 0x41, 0xcc},       {0xf0, 0x00, 0x00, 0xbb},
-       {0x03, 0x03, 0xc0, 0xbb},
-       {},
-};
-static const u8 mi1310_soc_InitSXGA_JPG[][4] = {
-       {0xb0, 0x03, 0x19, 0xcc},
-       {0xb0, 0x04, 0x02, 0xcc},
-       {0xb3, 0x00, 0x64, 0xcc},
-       {0xb3, 0x00, 0x65, 0xcc},
-       {0xb3, 0x05, 0x00, 0xcc},
-       {0xb3, 0x06, 0x00, 0xcc},
-       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},
-       {0xb3, 0x34, 0x02, 0xcc},
-       {0xb3, 0x35, 0xdd, 0xcc},
-       {0xb3, 0x02, 0x00, 0xcc},
-       {0xb3, 0x03, 0x0a, 0xcc},
-       {0xb3, 0x04, 0x0d, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x03, 0xcc},
-       {0xb3, 0x23, 0xc0, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},
-       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x04, 0xcc},
-       {0xb3, 0x17, 0xff, 0xcc},
-       {0xb3, 0x00, 0x65, 0xcc},
-       {0xb8, 0x00, 0x00, 0xcc},
-       {0xbc, 0x00, 0x70, 0xcc},
-       {0xbc, 0x01, 0x01, 0xcc},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0xc8, 0x9f, 0x0b, 0xbb},
-       {0x5b, 0x00, 0x01, 0xbb},
-       {0xf0, 0x00, 0x00, 0xbb},
-       {0x20, 0x03, 0x02, 0xbb},       /* h/v flip */
-       {0xf0, 0x00, 0x01, 0xbb},
-       {0x05, 0x00, 0x07, 0xbb},
-       {0x34, 0x00, 0x00, 0xbb},
-       {0x35, 0xff, 0x00, 0xbb},
-       {0xdc, 0x07, 0x02, 0xbb},
-       {0xdd, 0x3c, 0x18, 0xbb},
-       {0xde, 0x92, 0x6d, 0xbb},
-       {0xdf, 0xcd, 0xb1, 0xbb},
-       {0xe0, 0xff, 0xe7, 0xbb},
-       {0x06, 0xf0, 0x0d, 0xbb},
-       {0x06, 0x70, 0x0e, 0xbb},
-       {0x4c, 0x00, 0x01, 0xbb},
-       {0x4d, 0x00, 0x01, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x2e, 0x0c, 0x60, 0xbb},
-       {0x21, 0xb6, 0x6e, 0xbb},
-       {0x37, 0x01, 0x40, 0xbb},
-       {0xf0, 0x00, 0x00, 0xbb},
-       {0x07, 0x00, 0x84, 0xbb},
-       {0x08, 0x02, 0x4a, 0xbb},
-       {0x05, 0x01, 0x10, 0xbb},
-       {0x06, 0x00, 0x39, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x58, 0x02, 0x67, 0xbb},
-       {0x57, 0x02, 0x00, 0xbb},
-       {0x5a, 0x02, 0x67, 0xbb},
-       {0x59, 0x02, 0x00, 0xbb},
-       {0x5c, 0x12, 0x0d, 0xbb},
-       {0x5d, 0x16, 0x11, 0xbb},
-       {0x39, 0x06, 0x18, 0xbb},
-       {0x3a, 0x06, 0x18, 0xbb},
-       {0x3b, 0x06, 0x18, 0xbb},
-       {0x3c, 0x06, 0x18, 0xbb},
-       {0x64, 0x7b, 0x5b, 0xbb},
-       {0xb6, 0x00, 0x00, 0xcc},
-       {0xb6, 0x03, 0x05, 0xcc},
-       {0xb6, 0x02, 0x00, 0xcc},
-       {0xb6, 0x05, 0x03, 0xcc},
-       {0xb6, 0x04, 0xc0, 0xcc},
-       {0xb6, 0x12, 0xf8, 0xcc},
-       {0xb6, 0x13, 0x29, 0xcc},
-       {0xb6, 0x18, 0x09, 0xcc},
-       {0xb6, 0x17, 0x60, 0xcc},
-       {0xb6, 0x16, 0x00, 0xcc},
-       {0xb6, 0x22, 0x12, 0xcc},
-       {0xb6, 0x23, 0x0b, 0xcc},
-       {0xbf, 0xc0, 0x39, 0xcc},
-       {0xbf, 0xc1, 0x04, 0xcc},
-       {0xbf, 0xcc, 0x00, 0xcc},
-       {0xb3, 0x01, 0x41, 0xcc},
-       {0x00, 0x00, 0x80, 0xdd},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x00, 0x00, 0x10, 0xdd},
-       {0x22, 0xa0, 0x78, 0xbb},
-       {0x23, 0xa0, 0x78, 0xbb},
-       {0x24, 0x7f, 0x00, 0xbb},
-       {0x28, 0xea, 0x02, 0xbb},
-       {0x29, 0x86, 0x7a, 0xbb},
-       {0x5e, 0x52, 0x4c, 0xbb},
-       {0x5f, 0x20, 0x24, 0xbb},
-       {0x60, 0x00, 0x02, 0xbb},
-       {0x02, 0x00, 0xee, 0xbb},
-       {0x03, 0x39, 0x23, 0xbb},
-       {0x04, 0x07, 0x24, 0xbb},
-       {0x09, 0x00, 0xc0, 0xbb},
-       {0x0a, 0x00, 0x79, 0xbb},
-       {0x0b, 0x00, 0x04, 0xbb},
-       {0x0c, 0x00, 0x5c, 0xbb},
-       {0x0d, 0x00, 0xd9, 0xbb},
-       {0x0e, 0x00, 0x53, 0xbb},
-       {0x0f, 0x00, 0x21, 0xbb},
-       {0x10, 0x00, 0xa4, 0xbb},
-       {0x11, 0x00, 0xe5, 0xbb},
-       {0x15, 0x00, 0x00, 0xbb},
-       {0x16, 0x00, 0x00, 0xbb},
-       {0x17, 0x00, 0x00, 0xbb},
-       {0x18, 0x00, 0x00, 0xbb},
-       {0x19, 0x00, 0x00, 0xbb},
-       {0x1a, 0x00, 0x00, 0xbb},
-       {0x1b, 0x00, 0x00, 0xbb},
-       {0x1c, 0x00, 0x00, 0xbb},
-       {0x1d, 0x00, 0x00, 0xbb},
-       {0x1e, 0x00, 0x00, 0xbb},
-       {0xf0, 0x00, 0x01, 0xbb},
-       {0x00, 0x00, 0x20, 0xdd},
-       {0x06, 0xf0, 0x8e, 0xbb},
-       {0x00, 0x00, 0x80, 0xdd},
-       {0x06, 0x70, 0x8e, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x00, 0x00, 0x20, 0xdd},
-       {0x5e, 0x6a, 0x53, 0xbb},
-       {0x5f, 0x40, 0x2c, 0xbb},
-       {0xf0, 0x00, 0x01, 0xbb},
-       {0x00, 0x00, 0x20, 0xdd},
-       {0x58, 0x00, 0x00, 0xbb},
-       {0x53, 0x09, 0x03, 0xbb},
-       {0x54, 0x31, 0x18, 0xbb},
-       {0x55, 0x8b, 0x5f, 0xbb},
-       {0x56, 0xc0, 0xa9, 0xbb},
-       {0x57, 0xe0, 0xd2, 0xbb},
-       {0xe1, 0x00, 0x00, 0xbb},
-       {0xdc, 0x09, 0x03, 0xbb},
-       {0xdd, 0x31, 0x18, 0xbb},
-       {0xde, 0x8b, 0x5f, 0xbb},
-       {0xdf, 0xc0, 0xa9, 0xbb},
-       {0xe0, 0xe0, 0xd2, 0xbb},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {0xf0, 0x00, 0x01, 0xbb},
-       {0x06, 0xf0, 0x8e, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x2f, 0xde, 0x20, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x24, 0x50, 0x20, 0xbb},
-       {0xbc, 0x0e, 0x00, 0xcc},
-       {0xbc, 0x0f, 0x05, 0xcc},
-       {0xbc, 0x10, 0xc0, 0xcc},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x34, 0x0c, 0x50, 0xbb},
-       {0xbc, 0x11, 0x03, 0xcc},
-       {0xf0, 0x00, 0x01, 0xbb},
-       {0x80, 0x00, 0x03, 0xbb},
-       {0x81, 0xc7, 0x14, 0xbb},
-       {0x82, 0xeb, 0xe8, 0xbb},
-       {0x83, 0xfe, 0xf4, 0xbb},
-       {0x84, 0xcd, 0x10, 0xbb},
-       {0x85, 0xf3, 0xee, 0xbb},
-       {0x86, 0xff, 0xf1, 0xbb},
-       {0x87, 0xcd, 0x10, 0xbb},
-       {0x88, 0xf3, 0xee, 0xbb},
-       {0x89, 0x01, 0xf1, 0xbb},
-       {0x8a, 0xe5, 0x17, 0xbb},
-       {0x8b, 0xe8, 0xe2, 0xbb},
-       {0x8c, 0xf7, 0xed, 0xbb},
-       {0x8d, 0x00, 0xff, 0xbb},
-       {0x8e, 0xec, 0x10, 0xbb},
-       {0x8f, 0xf0, 0xed, 0xbb},
-       {0x90, 0xf9, 0xf2, 0xbb},
-       {0x91, 0x00, 0x00, 0xbb},
-       {0x92, 0xe9, 0x0d, 0xbb},
-       {0x93, 0xf4, 0xf2, 0xbb},
-       {0x94, 0xfb, 0xf5, 0xbb},
-       {0x95, 0x00, 0xff, 0xbb},
-       {0xb6, 0x0f, 0x08, 0xbb},
-       {0xb7, 0x3d, 0x16, 0xbb},
-       {0xb8, 0x0c, 0x04, 0xbb},
-       {0xb9, 0x1c, 0x07, 0xbb},
-       {0xba, 0x0a, 0x03, 0xbb},
-       {0xbb, 0x1b, 0x09, 0xbb},
-       {0xbc, 0x17, 0x0d, 0xbb},
-       {0xbd, 0x23, 0x1d, 0xbb},
-       {0xbe, 0x00, 0x28, 0xbb},
-       {0xbf, 0x11, 0x09, 0xbb},
-       {0xc0, 0x16, 0x15, 0xbb},
-       {0xc1, 0x00, 0x1b, 0xbb},
-       {0xc2, 0x0e, 0x07, 0xbb},
-       {0xc3, 0x14, 0x10, 0xbb},
-       {0xc4, 0x00, 0x17, 0xbb},
-       {0x06, 0x74, 0x8e, 0xbb},
-       {0xf0, 0x00, 0x00, 0xbb},
-       {0x03, 0x03, 0xc0, 0xbb},
-       {}
-};
-
-static const u8 mi1320_gamma[17] = {
-       0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
-       0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
-};
-static const u8 mi1320_matrix[9] = {
-       0x54, 0xda, 0x06, 0xf1, 0x50, 0xf4, 0xf7, 0xea, 0x52
-};
-static const u8 mi1320_initVGA_data[][4] = {
-       {0xb3, 0x01, 0x01, 0xcc},       {0x00, 0x00, 0x33, 0xdd},
-       {0xb0, 0x03, 0x19, 0xcc},       {0x00, 0x00, 0x33, 0xdd},
-       {0xb0, 0x04, 0x02, 0xcc},       {0x00, 0x00, 0x33, 0xdd},
-       {0xb3, 0x00, 0x64, 0xcc},       {0xb3, 0x00, 0x65, 0xcc},
-       {0xb0, 0x16, 0x03, 0xcc},       {0xb3, 0x05, 0x00, 0xcc},
-       {0xb3, 0x06, 0x00, 0xcc},       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},       {0xb3, 0x34, 0x02, 0xcc},
-       {0xb3, 0x35, 0xc8, 0xcc},       /* i2c add: 48 */
-       {0xb3, 0x02, 0x00, 0xcc},
-       {0xb3, 0x03, 0x0a, 0xcc},       {0xb3, 0x04, 0x05, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x03, 0xcc},       {0xb3, 0x23, 0xc0, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x04, 0xcc},       {0xb3, 0x17, 0xff, 0xcc},
-       {0xb3, 0x00, 0x67, 0xcc},       {0xbc, 0x00, 0xd0, 0xcc},
-       {0xbc, 0x01, 0x01, 0xcc},       {0xf0, 0x00, 0x00, 0xbb},
-       {0x0d, 0x00, 0x09, 0xbb},       {0x00, 0x01, 0x00, 0xdd},
-       {0x0d, 0x00, 0x08, 0xbb},       {0xf0, 0x00, 0x01, 0xbb},
-       {0xa1, 0x05, 0x00, 0xbb},       {0xa4, 0x03, 0xc0, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},       {0x00, 0x00, 0x10, 0xdd},
-       {0xc8, 0x9f, 0x0b, 0xbb},       {0x00, 0x00, 0x10, 0xdd},
-       {0xf0, 0x00, 0x00, 0xbb},       {0x00, 0x00, 0x10, 0xdd},
-       {0x20, 0x01, 0x00, 0xbb},       {0x00, 0x00, 0x10, 0xdd},
-       {0xf0, 0x00, 0x01, 0xbb},       {0x9d, 0x3c, 0xa0, 0xbb},
-       {0x47, 0x30, 0x30, 0xbb},       {0xf0, 0x00, 0x00, 0xbb},
-       {0x0a, 0x80, 0x11, 0xbb},       {0x35, 0x00, 0x22, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},       {0x9d, 0xc5, 0x05, 0xbb},
-       {0xdc, 0x0f, 0xfc, 0xbb},       {0xf0, 0x00, 0x01, 0xbb},
-       {0x06, 0x74, 0x0e, 0xbb},       {0x80, 0x00, 0x06, 0xbb},
-       {0x81, 0x04, 0x00, 0xbb},       {0x82, 0x01, 0x02, 0xbb},
-       {0x83, 0x03, 0x02, 0xbb},       {0x84, 0x05, 0x00, 0xbb},
-       {0x85, 0x01, 0x00, 0xbb},       {0x86, 0x03, 0x02, 0xbb},
-       {0x87, 0x05, 0x00, 0xbb},       {0x88, 0x01, 0x00, 0xbb},
-       {0x89, 0x02, 0x02, 0xbb},       {0x8a, 0xfd, 0x04, 0xbb},
-       {0x8b, 0xfc, 0xfd, 0xbb},       {0x8c, 0xff, 0xfd, 0xbb},
-       {0x8d, 0x00, 0x00, 0xbb},       {0x8e, 0xfe, 0x05, 0xbb},
-       {0x8f, 0xfc, 0xfd, 0xbb},       {0x90, 0xfe, 0xfd, 0xbb},
-       {0x91, 0x00, 0x00, 0xbb},       {0x92, 0xfe, 0x03, 0xbb},
-       {0x93, 0xfd, 0xfe, 0xbb},       {0x94, 0xff, 0xfd, 0xbb},
-       {0x95, 0x00, 0x00, 0xbb},       {0xb6, 0x07, 0x05, 0xbb},
-       {0xb7, 0x13, 0x06, 0xbb},       {0xb8, 0x08, 0x06, 0xbb},
-       {0xb9, 0x14, 0x08, 0xbb},       {0xba, 0x06, 0x05, 0xbb},
-       {0xbb, 0x13, 0x06, 0xbb},       {0xbc, 0x03, 0x01, 0xbb},
-       {0xbd, 0x03, 0x04, 0xbb},       {0xbe, 0x00, 0x02, 0xbb},
-       {0xbf, 0x03, 0x01, 0xbb},       {0xc0, 0x02, 0x04, 0xbb},
-       {0xc1, 0x00, 0x04, 0xbb},       {0xc2, 0x02, 0x01, 0xbb},
-       {0xc3, 0x01, 0x03, 0xbb},       {0xc4, 0x00, 0x04, 0xbb},
-       {0xf0, 0x00, 0x00, 0xbb},       {0x05, 0x01, 0x13, 0xbb},
-       {0x06, 0x00, 0x11, 0xbb},       {0x07, 0x00, 0x85, 0xbb},
-       {0x08, 0x00, 0x27, 0xbb},
-       {0x20, 0x01, 0x00, 0xbb},       /* h/v flips - was 03 */
-       {0x21, 0x80, 0x00, 0xbb},       {0x22, 0x0d, 0x0f, 0xbb},
-       {0x24, 0x80, 0x00, 0xbb},       {0x59, 0x00, 0xff, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},       {0x39, 0x03, 0x0d, 0xbb},
-       {0x3a, 0x06, 0x1b, 0xbb},       {0x3b, 0x00, 0x95, 0xbb},
-       {0x3c, 0x04, 0xdb, 0xbb},       {0x57, 0x02, 0x00, 0xbb},
-       {0x58, 0x02, 0x66, 0xbb},       {0x59, 0x00, 0xff, 0xbb},
-       {0x5a, 0x01, 0x33, 0xbb},       {0x5c, 0x12, 0x0d, 0xbb},
-       {0x5d, 0x16, 0x11, 0xbb},       {0x64, 0x5e, 0x1c, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},       {0x2f, 0xd1, 0x00, 0xbb},
-       {0x5b, 0x00, 0x01, 0xbb},       {0xf0, 0x00, 0x02, 0xbb},
-       {0x36, 0x68, 0x10, 0xbb},       {0x00, 0x00, 0x30, 0xdd},
-       {0x37, 0x82, 0x00, 0xbb},       {0xbc, 0x0e, 0x00, 0xcc},
-       {0xbc, 0x0f, 0x05, 0xcc},       {0xbc, 0x10, 0xc0, 0xcc},
-       {0xbc, 0x11, 0x03, 0xcc},       {0xb6, 0x00, 0x00, 0xcc},
-       {0xb6, 0x03, 0x05, 0xcc},       {0xb6, 0x02, 0x00, 0xcc},
-       {0xb6, 0x05, 0x04, 0xcc},       {0xb6, 0x04, 0x00, 0xcc},
-       {0xb6, 0x12, 0xf8, 0xcc},       {0xb6, 0x13, 0x29, 0xcc},
-       {0xb6, 0x18, 0x0a, 0xcc},       {0xb6, 0x17, 0x00, 0xcc},
-       {0xb6, 0x16, 0x00, 0xcc},       {0xb6, 0x22, 0x12, 0xcc},
-       {0xb6, 0x23, 0x0b, 0xcc},       {0xbf, 0xc0, 0x26, 0xcc},
-       {0xbf, 0xc1, 0x02, 0xcc},       {0xbf, 0xcc, 0x04, 0xcc},
-       {0xbc, 0x02, 0x18, 0xcc},       {0xbc, 0x03, 0x50, 0xcc},
-       {0xbc, 0x04, 0x18, 0xcc},       {0xbc, 0x05, 0x00, 0xcc},
-       {0xbc, 0x06, 0x00, 0xcc},       {0xbc, 0x08, 0x30, 0xcc},
-       {0xbc, 0x09, 0x40, 0xcc},       {0xbc, 0x0a, 0x10, 0xcc},
-       {0xbc, 0x0b, 0x00, 0xcc},       {0xbc, 0x0c, 0x00, 0xcc},
-       {0xb3, 0x5c, 0x01, 0xcc},       {0xb3, 0x01, 0x41, 0xcc},
-       {}
-};
-static const u8 mi1320_initQVGA_data[][4] = {
-       {0xb3, 0x01, 0x01, 0xcc},       {0x00, 0x00, 0x33, 0xdd},
-       {0xb0, 0x03, 0x19, 0xcc},       {0x00, 0x00, 0x33, 0xdd},
-       {0xb0, 0x04, 0x02, 0xcc},       {0x00, 0x00, 0x33, 0xdd},
-       {0xb3, 0x00, 0x64, 0xcc},       {0xb3, 0x00, 0x65, 0xcc},
-       {0xb0, 0x16, 0x03, 0xcc},       {0xb3, 0x05, 0x01, 0xcc},
-       {0xb3, 0x06, 0x01, 0xcc},       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},       {0xb3, 0x34, 0x02, 0xcc},
-       {0xb3, 0x35, 0xc8, 0xcc},       {0xb3, 0x02, 0x00, 0xcc},
-       {0xb3, 0x03, 0x0a, 0xcc},       {0xb3, 0x04, 0x05, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x01, 0xcc},       {0xb3, 0x23, 0xe0, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x02, 0xcc},       {0xb3, 0x17, 0x7f, 0xcc},
-       {0xb3, 0x00, 0x65, 0xcc},       {0xb8, 0x00, 0x00, 0xcc},
-       {0xbc, 0x00, 0xd0, 0xcc},       {0xbc, 0x01, 0x01, 0xcc},
-       {0xf0, 0x00, 0x00, 0xbb},       {0x0d, 0x00, 0x09, 0xbb},
-       {0x00, 0x01, 0x00, 0xdd},       {0x0d, 0x00, 0x08, 0xbb},
-       {0xf0, 0x00, 0x00, 0xbb},       {0x02, 0x00, 0x64, 0xbb},
-       {0x05, 0x01, 0x78, 0xbb},       {0x06, 0x00, 0x11, 0xbb},
-       {0x07, 0x01, 0x42, 0xbb},       {0x08, 0x00, 0x11, 0xbb},
-       {0x20, 0x01, 0x00, 0xbb},       {0x21, 0x80, 0x00, 0xbb},
-       {0x22, 0x0d, 0x0f, 0xbb},       {0x24, 0x80, 0x00, 0xbb},
-       {0x59, 0x00, 0xff, 0xbb},       {0xf0, 0x00, 0x01, 0xbb},
-       {0x9d, 0x3c, 0xa0, 0xbb},       {0x47, 0x30, 0x30, 0xbb},
-       {0xf0, 0x00, 0x00, 0xbb},       {0x0a, 0x80, 0x11, 0xbb},
-       {0x35, 0x00, 0x22, 0xbb},       {0xf0, 0x00, 0x02, 0xbb},
-       {0x9d, 0xc5, 0x05, 0xbb},       {0xdc, 0x0f, 0xfc, 0xbb},
-       {0xf0, 0x00, 0x01, 0xbb},       {0x06, 0x74, 0x0e, 0xbb},
-       {0x80, 0x00, 0x06, 0xbb},       {0x81, 0x04, 0x00, 0xbb},
-       {0x82, 0x01, 0x02, 0xbb},       {0x83, 0x03, 0x02, 0xbb},
-       {0x84, 0x05, 0x00, 0xbb},       {0x85, 0x01, 0x00, 0xbb},
-       {0x86, 0x03, 0x02, 0xbb},       {0x87, 0x05, 0x00, 0xbb},
-       {0x88, 0x01, 0x00, 0xbb},       {0x89, 0x02, 0x02, 0xbb},
-       {0x8a, 0xfd, 0x04, 0xbb},       {0x8b, 0xfc, 0xfd, 0xbb},
-       {0x8c, 0xff, 0xfd, 0xbb},       {0x8d, 0x00, 0x00, 0xbb},
-       {0x8e, 0xfe, 0x05, 0xbb},       {0x8f, 0xfc, 0xfd, 0xbb},
-       {0x90, 0xfe, 0xfd, 0xbb},       {0x91, 0x00, 0x00, 0xbb},
-       {0x92, 0xfe, 0x03, 0xbb},       {0x93, 0xfd, 0xfe, 0xbb},
-       {0x94, 0xff, 0xfd, 0xbb},       {0x95, 0x00, 0x00, 0xbb},
-       {0xb6, 0x07, 0x05, 0xbb},       {0xb7, 0x13, 0x06, 0xbb},
-       {0xb8, 0x08, 0x06, 0xbb},       {0xb9, 0x14, 0x08, 0xbb},
-       {0xba, 0x06, 0x05, 0xbb},       {0xbb, 0x13, 0x06, 0xbb},
-       {0xbc, 0x03, 0x01, 0xbb},       {0xbd, 0x03, 0x04, 0xbb},
-       {0xbe, 0x00, 0x02, 0xbb},       {0xbf, 0x03, 0x01, 0xbb},
-       {0xc0, 0x02, 0x04, 0xbb},       {0xc1, 0x00, 0x04, 0xbb},
-       {0xc2, 0x02, 0x01, 0xbb},       {0xc3, 0x01, 0x03, 0xbb},
-       {0xc4, 0x00, 0x04, 0xbb},       {0xf0, 0x00, 0x02, 0xbb},
-       {0xc8, 0x00, 0x00, 0xbb},       {0x2e, 0x00, 0x00, 0xbb},
-       {0x2e, 0x0c, 0x5b, 0xbb},       {0x2f, 0xd1, 0x00, 0xbb},
-       {0x39, 0x03, 0xca, 0xbb},       {0x3a, 0x06, 0x80, 0xbb},
-       {0x3b, 0x01, 0x52, 0xbb},       {0x3c, 0x05, 0x40, 0xbb},
-       {0x57, 0x01, 0x9c, 0xbb},       {0x58, 0x01, 0xee, 0xbb},
-       {0x59, 0x00, 0xf0, 0xbb},       {0x5a, 0x01, 0x20, 0xbb},
-       {0x5c, 0x1d, 0x17, 0xbb},       {0x5d, 0x22, 0x1c, 0xbb},
-       {0x64, 0x1e, 0x1c, 0xbb},       {0x5b, 0x00, 0x01, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},       {0x36, 0x68, 0x10, 0xbb},
-       {0x00, 0x00, 0x30, 0xdd},       {0x37, 0x81, 0x00, 0xbb},
-       {0xbc, 0x02, 0x18, 0xcc},       {0xbc, 0x03, 0x50, 0xcc},
-       {0xbc, 0x04, 0x18, 0xcc},       {0xbc, 0x05, 0x00, 0xcc},
-       {0xbc, 0x06, 0x00, 0xcc},       {0xbc, 0x08, 0x30, 0xcc},
-       {0xbc, 0x09, 0x40, 0xcc},       {0xbc, 0x0a, 0x10, 0xcc},
-       {0xbc, 0x0b, 0x00, 0xcc},       {0xbc, 0x0c, 0x00, 0xcc},
-       {0xbf, 0xc0, 0x26, 0xcc},       {0xbf, 0xc1, 0x02, 0xcc},
-       {0xbf, 0xcc, 0x04, 0xcc},       {0xb3, 0x5c, 0x01, 0xcc},
-       {0xb3, 0x01, 0x41, 0xcc},
-       {}
-};
-
-static const u8 mi1320_soc_InitVGA[][4] = {
-       {0xb3, 0x01, 0x01, 0xcc},
-       {0xb0, 0x03, 0x19, 0xcc},
-       {0xb0, 0x04, 0x02, 0xcc},
-       {0x00, 0x00, 0x30, 0xdd},
-       {0xb3, 0x00, 0x64, 0xcc},
-       {0xb3, 0x00, 0x67, 0xcc},
-       {0xb3, 0x05, 0x01, 0xcc},
-       {0xb3, 0x06, 0x01, 0xcc},
-       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},
-       {0xb3, 0x34, 0x02, 0xcc},
-       {0xb3, 0x35, 0xc8, 0xcc},       /* i2c add: 48 */
-       {0xb3, 0x02, 0x00, 0xcc},
-       {0xb3, 0x03, 0x0a, 0xcc},
-       {0xb3, 0x04, 0x05, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x01, 0xcc},
-       {0xb3, 0x23, 0xe0, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},
-       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x02, 0xcc},
-       {0xb3, 0x17, 0x7f, 0xcc},
-       {0xb3, 0x00, 0x67, 0xcc},
-       {0xb8, 0x00, 0x00, 0xcc},
-       {0xbc, 0x00, 0x71, 0xcc},
-       {0xbc, 0x01, 0x01, 0xcc},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x00, 0x00, 0x10, 0xdd},
-       {0xc8, 0x00, 0x00, 0xbb},
-       {0x00, 0x00, 0x30, 0xdd},
-       {0xf0, 0x00, 0x00, 0xbb},
-       {0x00, 0x00, 0x10, 0xdd},
-       {0x07, 0x00, 0xe0, 0xbb},
-       {0x08, 0x00, 0x0b, 0xbb},
-       {0x21, 0x00, 0x0c, 0xbb},
-       {0x20, 0x01, 0x03, 0xbb},       /* h/v flip */
-       {0xbf, 0xc0, 0x26, 0xcc},
-       {0xbf, 0xc1, 0x02, 0xcc},
-       {0xbf, 0xcc, 0x04, 0xcc},
-       {0xb3, 0x01, 0x41, 0xcc},
-       {0xf0, 0x00, 0x00, 0xbb},
-       {0x05, 0x01, 0x78, 0xbb},
-       {0x06, 0x00, 0x11, 0xbb},
-       {0x07, 0x01, 0x42, 0xbb},
-       {0x08, 0x00, 0x11, 0xbb},
-       {0x20, 0x01, 0x03, 0xbb},       /* h/v flip */
-       {0x21, 0x80, 0x00, 0xbb},
-       {0x22, 0x0d, 0x0f, 0xbb},
-       {0x24, 0x80, 0x00, 0xbb},
-       {0x59, 0x00, 0xff, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x39, 0x03, 0xca, 0xbb},
-       {0x3a, 0x06, 0x80, 0xbb},
-       {0x3b, 0x01, 0x52, 0xbb},
-       {0x3c, 0x05, 0x40, 0xbb},
-       {0x57, 0x01, 0x9c, 0xbb},
-       {0x58, 0x01, 0xee, 0xbb},
-       {0x59, 0x00, 0xf0, 0xbb},
-       {0x5a, 0x01, 0x20, 0xbb},
-       {0x5c, 0x1d, 0x17, 0xbb},
-       {0x5d, 0x22, 0x1c, 0xbb},
-       {0x64, 0x1e, 0x1c, 0xbb},
-       {0x5b, 0x00, 0x00, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x22, 0xa0, 0x78, 0xbb},
-       {0x23, 0xa0, 0x78, 0xbb},
-       {0x24, 0x7f, 0x00, 0xbb},
-       {0x28, 0xea, 0x02, 0xbb},
-       {0x29, 0x86, 0x7a, 0xbb},
-       {0x5e, 0x52, 0x4c, 0xbb},
-       {0x5f, 0x20, 0x24, 0xbb},
-       {0x60, 0x00, 0x02, 0xbb},
-       {0x02, 0x00, 0xee, 0xbb},
-       {0x03, 0x39, 0x23, 0xbb},
-       {0x04, 0x07, 0x24, 0xbb},
-       {0x09, 0x00, 0xc0, 0xbb},
-       {0x0a, 0x00, 0x79, 0xbb},
-       {0x0b, 0x00, 0x04, 0xbb},
-       {0x0c, 0x00, 0x5c, 0xbb},
-       {0x0d, 0x00, 0xd9, 0xbb},
-       {0x0e, 0x00, 0x53, 0xbb},
-       {0x0f, 0x00, 0x21, 0xbb},
-       {0x10, 0x00, 0xa4, 0xbb},
-       {0x11, 0x00, 0xe5, 0xbb},
-       {0x15, 0x00, 0x00, 0xbb},
-       {0x16, 0x00, 0x00, 0xbb},
-       {0x17, 0x00, 0x00, 0xbb},
-       {0x18, 0x00, 0x00, 0xbb},
-       {0x19, 0x00, 0x00, 0xbb},
-       {0x1a, 0x00, 0x00, 0xbb},
-       {0x1b, 0x00, 0x00, 0xbb},
-       {0x1c, 0x00, 0x00, 0xbb},
-       {0x1d, 0x00, 0x00, 0xbb},
-       {0x1e, 0x00, 0x00, 0xbb},
-       {0xf0, 0x00, 0x01, 0xbb},
-       {0x06, 0xe0, 0x0e, 0xbb},
-       {0x06, 0x60, 0x0e, 0xbb},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {}
-};
-static const u8 mi1320_soc_InitQVGA[][4] = {
-       {0xb3, 0x01, 0x01, 0xcc},
-       {0xb0, 0x03, 0x19, 0xcc},
-       {0xb0, 0x04, 0x02, 0xcc},
-       {0x00, 0x00, 0x30, 0xdd},
-       {0xb3, 0x00, 0x64, 0xcc},
-       {0xb3, 0x00, 0x67, 0xcc},
-       {0xb3, 0x05, 0x01, 0xcc},
-       {0xb3, 0x06, 0x01, 0xcc},
-       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},
-       {0xb3, 0x34, 0x02, 0xcc},
-       {0xb3, 0x35, 0xc8, 0xcc},
-       {0xb3, 0x02, 0x00, 0xcc},
-       {0xb3, 0x03, 0x0a, 0xcc},
-       {0xb3, 0x04, 0x05, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x01, 0xcc},
-       {0xb3, 0x23, 0xe0, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},
-       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x02, 0xcc},
-       {0xb3, 0x17, 0x7f, 0xcc},
-       {0xb3, 0x00, 0x67, 0xcc},
-       {0xb8, 0x00, 0x00, 0xcc},
-       {0xbc, 0x00, 0xd1, 0xcc},
-       {0xbc, 0x01, 0x01, 0xcc},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x00, 0x00, 0x10, 0xdd},
-       {0xc8, 0x00, 0x00, 0xbb},
-       {0x00, 0x00, 0x30, 0xdd},
-       {0xf0, 0x00, 0x00, 0xbb},
-       {0x00, 0x00, 0x10, 0xdd},
-       {0x07, 0x00, 0xe0, 0xbb},
-       {0x08, 0x00, 0x0b, 0xbb},
-       {0x21, 0x00, 0x0c, 0xbb},
-       {0x20, 0x01, 0x03, 0xbb},       /* h/v flip */
-       {0xbf, 0xc0, 0x26, 0xcc},
-       {0xbf, 0xc1, 0x02, 0xcc},
-       {0xbf, 0xcc, 0x04, 0xcc},
-       {0xbc, 0x02, 0x18, 0xcc},
-       {0xbc, 0x03, 0x50, 0xcc},
-       {0xbc, 0x04, 0x18, 0xcc},
-       {0xbc, 0x05, 0x00, 0xcc},
-       {0xbc, 0x06, 0x00, 0xcc},
-       {0xbc, 0x08, 0x30, 0xcc},
-       {0xbc, 0x09, 0x40, 0xcc},
-       {0xbc, 0x0a, 0x10, 0xcc},
-       {0xbc, 0x0b, 0x00, 0xcc},
-       {0xbc, 0x0c, 0x00, 0xcc},
-       {0xb3, 0x01, 0x41, 0xcc},
-       {0xf0, 0x00, 0x00, 0xbb},
-       {0x05, 0x01, 0x78, 0xbb},
-       {0x06, 0x00, 0x11, 0xbb},
-       {0x07, 0x01, 0x42, 0xbb},
-       {0x08, 0x00, 0x11, 0xbb},
-       {0x20, 0x01, 0x03, 0xbb},       /* h/v flip */
-       {0x21, 0x80, 0x00, 0xbb},
-       {0x22, 0x0d, 0x0f, 0xbb},
-       {0x24, 0x80, 0x00, 0xbb},
-       {0x59, 0x00, 0xff, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x39, 0x03, 0xca, 0xbb},
-       {0x3a, 0x06, 0x80, 0xbb},
-       {0x3b, 0x01, 0x52, 0xbb},
-       {0x3c, 0x05, 0x40, 0xbb},
-       {0x57, 0x01, 0x9c, 0xbb},
-       {0x58, 0x01, 0xee, 0xbb},
-       {0x59, 0x00, 0xf0, 0xbb},
-       {0x5a, 0x01, 0x20, 0xbb},
-       {0x5c, 0x1d, 0x17, 0xbb},
-       {0x5d, 0x22, 0x1c, 0xbb},
-       {0x64, 0x1e, 0x1c, 0xbb},
-       {0x5b, 0x00, 0x00, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x22, 0xa0, 0x78, 0xbb},
-       {0x23, 0xa0, 0x78, 0xbb},
-       {0x24, 0x7f, 0x00, 0xbb},
-       {0x28, 0xea, 0x02, 0xbb},
-       {0x29, 0x86, 0x7a, 0xbb},
-       {0x5e, 0x52, 0x4c, 0xbb},
-       {0x5f, 0x20, 0x24, 0xbb},
-       {0x60, 0x00, 0x02, 0xbb},
-       {0x02, 0x00, 0xee, 0xbb},
-       {0x03, 0x39, 0x23, 0xbb},
-       {0x04, 0x07, 0x24, 0xbb},
-       {0x09, 0x00, 0xc0, 0xbb},
-       {0x0a, 0x00, 0x79, 0xbb},
-       {0x0b, 0x00, 0x04, 0xbb},
-       {0x0c, 0x00, 0x5c, 0xbb},
-       {0x0d, 0x00, 0xd9, 0xbb},
-       {0x0e, 0x00, 0x53, 0xbb},
-       {0x0f, 0x00, 0x21, 0xbb},
-       {0x10, 0x00, 0xa4, 0xbb},
-       {0x11, 0x00, 0xe5, 0xbb},
-       {0x15, 0x00, 0x00, 0xbb},
-       {0x16, 0x00, 0x00, 0xbb},
-       {0x17, 0x00, 0x00, 0xbb},
-       {0x18, 0x00, 0x00, 0xbb},
-       {0x19, 0x00, 0x00, 0xbb},
-       {0x1a, 0x00, 0x00, 0xbb},
-       {0x1b, 0x00, 0x00, 0xbb},
-       {0x1c, 0x00, 0x00, 0xbb},
-       {0x1d, 0x00, 0x00, 0xbb},
-       {0x1e, 0x00, 0x00, 0xbb},
-       {0xf0, 0x00, 0x01, 0xbb},
-       {0x06, 0xe0, 0x0e, 0xbb},
-       {0x06, 0x60, 0x0e, 0xbb},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {}
-};
-static const u8 mi1320_soc_InitSXGA[][4] = {
-       {0xb3, 0x01, 0x01, 0xcc},
-       {0xb0, 0x03, 0x19, 0xcc},
-       {0x00, 0x00, 0x30, 0xdd},
-       {0xb3, 0x00, 0x64, 0xcc},
-       {0xb3, 0x00, 0x67, 0xcc},
-       {0xb3, 0x05, 0x01, 0xcc},
-       {0xb3, 0x06, 0x01, 0xcc},
-       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},
-       {0xb3, 0x34, 0x02, 0xcc},
-       {0xb3, 0x35, 0xc8, 0xcc},
-       {0xb3, 0x02, 0x00, 0xcc},
-       {0xb3, 0x03, 0x0a, 0xcc},
-       {0xb3, 0x04, 0x05, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x04, 0xcc},
-       {0xb3, 0x23, 0x00, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},
-       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x04, 0xcc},
-       {0xb3, 0x17, 0xff, 0xcc},
-       {0xb3, 0x00, 0x67, 0xcc},
-       {0xbc, 0x00, 0x71, 0xcc},
-       {0xbc, 0x01, 0x01, 0xcc},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x00, 0x00, 0x30, 0xdd},
-       {0xc8, 0x9f, 0x0b, 0xbb},
-       {0x00, 0x00, 0x20, 0xdd},
-       {0x5b, 0x00, 0x01, 0xbb},
-       {0x00, 0x00, 0x20, 0xdd},
-       {0xf0, 0x00, 0x00, 0xbb},
-       {0x00, 0x00, 0x30, 0xdd},
-       {0x20, 0x01, 0x03, 0xbb},       /* h/v flip */
-       {0x00, 0x00, 0x20, 0xdd},
-       {0xbf, 0xc0, 0x26, 0xcc},
-       {0xbf, 0xc1, 0x02, 0xcc},
-       {0xbf, 0xcc, 0x04, 0xcc},
-       {0xb3, 0x01, 0x41, 0xcc},
-       {0xf0, 0x00, 0x00, 0xbb},
-       {0x05, 0x01, 0x78, 0xbb},
-       {0x06, 0x00, 0x11, 0xbb},
-       {0x07, 0x01, 0x42, 0xbb},
-       {0x08, 0x00, 0x11, 0xbb},
-       {0x20, 0x01, 0x03, 0xbb},       /* h/v flip */
-       {0x21, 0x80, 0x00, 0xbb},
-       {0x22, 0x0d, 0x0f, 0xbb},
-       {0x24, 0x80, 0x00, 0xbb},
-       {0x59, 0x00, 0xff, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x39, 0x03, 0xca, 0xbb},
-       {0x3a, 0x06, 0x80, 0xbb},
-       {0x3b, 0x01, 0x52, 0xbb},
-       {0x3c, 0x05, 0x40, 0xbb},
-       {0x57, 0x01, 0x9c, 0xbb},
-       {0x58, 0x01, 0xee, 0xbb},
-       {0x59, 0x00, 0xf0, 0xbb},
-       {0x5a, 0x01, 0x20, 0xbb},
-       {0x5c, 0x1d, 0x17, 0xbb},
-       {0x5d, 0x22, 0x1c, 0xbb},
-       {0x64, 0x1e, 0x1c, 0xbb},
-       {0x5b, 0x00, 0x00, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x22, 0xa0, 0x78, 0xbb},
-       {0x23, 0xa0, 0x78, 0xbb},
-       {0x24, 0x7f, 0x00, 0xbb},
-       {0x28, 0xea, 0x02, 0xbb},
-       {0x29, 0x86, 0x7a, 0xbb},
-       {0x5e, 0x52, 0x4c, 0xbb},
-       {0x5f, 0x20, 0x24, 0xbb},
-       {0x60, 0x00, 0x02, 0xbb},
-       {0x02, 0x00, 0xee, 0xbb},
-       {0x03, 0x39, 0x23, 0xbb},
-       {0x04, 0x07, 0x24, 0xbb},
-       {0x09, 0x00, 0xc0, 0xbb},
-       {0x0a, 0x00, 0x79, 0xbb},
-       {0x0b, 0x00, 0x04, 0xbb},
-       {0x0c, 0x00, 0x5c, 0xbb},
-       {0x0d, 0x00, 0xd9, 0xbb},
-       {0x0e, 0x00, 0x53, 0xbb},
-       {0x0f, 0x00, 0x21, 0xbb},
-       {0x10, 0x00, 0xa4, 0xbb},
-       {0x11, 0x00, 0xe5, 0xbb},
-       {0x15, 0x00, 0x00, 0xbb},
-       {0x16, 0x00, 0x00, 0xbb},
-       {0x17, 0x00, 0x00, 0xbb},
-       {0x18, 0x00, 0x00, 0xbb},
-       {0x19, 0x00, 0x00, 0xbb},
-       {0x1a, 0x00, 0x00, 0xbb},
-       {0x1b, 0x00, 0x00, 0xbb},
-       {0x1c, 0x00, 0x00, 0xbb},
-       {0x1d, 0x00, 0x00, 0xbb},
-       {0x1e, 0x00, 0x00, 0xbb},
-       {0xf0, 0x00, 0x01, 0xbb},
-       {0x06, 0xe0, 0x0e, 0xbb},
-       {0x06, 0x60, 0x0e, 0xbb},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {0xf0, 0x00, 0x00, 0xbb},
-       {0x05, 0x01, 0x13, 0xbb},
-       {0x06, 0x00, 0x11, 0xbb},
-       {0x07, 0x00, 0x85, 0xbb},
-       {0x08, 0x00, 0x27, 0xbb},
-       {0x20, 0x01, 0x03, 0xbb},       /* h/v flip */
-       {0x21, 0x80, 0x00, 0xbb},
-       {0x22, 0x0d, 0x0f, 0xbb},
-       {0x24, 0x80, 0x00, 0xbb},
-       {0x59, 0x00, 0xff, 0xbb},
-       {0xf0, 0x00, 0x02, 0xbb},
-       {0x39, 0x03, 0x0d, 0xbb},
-       {0x3a, 0x06, 0x1b, 0xbb},
-       {0x3b, 0x00, 0x95, 0xbb},
-       {0x3c, 0x04, 0xdb, 0xbb},
-       {0x57, 0x02, 0x00, 0xbb},
-       {0x58, 0x02, 0x66, 0xbb},
-       {0x59, 0x00, 0xff, 0xbb},
-       {0x5a, 0x01, 0x33, 0xbb},
-       {0x5c, 0x12, 0x0d, 0xbb},
-       {0x5d, 0x16, 0x11, 0xbb},
-       {0x64, 0x5e, 0x1c, 0xbb},
-       {}
-};
-static const u8 po3130_gamma[17] = {
-       0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
-       0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
-};
-static const u8 po3130_matrix[9] = {
-       0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63
-};
-
-static const u8 po3130_initVGA_data[][4] = {
-       {0xb0, 0x4d, 0x00, 0xcc},       {0xb3, 0x01, 0x01, 0xcc},
-       {0x00, 0x00, 0x50, 0xdd},       {0xb0, 0x03, 0x01, 0xcc},
-       {0xb3, 0x00, 0x04, 0xcc},       {0xb3, 0x00, 0x24, 0xcc},
-       {0xb3, 0x00, 0x25, 0xcc},       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},       {0xb3, 0x05, 0x00, 0xcc},
-       {0xb3, 0x06, 0x01, 0xcc},       {0xb3, 0x03, 0x1a, 0xcc},
-       {0xb3, 0x04, 0x15, 0xcc},       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},       {0xb3, 0x22, 0x01, 0xcc},
-       {0xb3, 0x23, 0xe8, 0xcc},       {0xb8, 0x08, 0xe8, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x02, 0xcc},       {0xb3, 0x17, 0x7f, 0xcc},
-       {0xb3, 0x34, 0x01, 0xcc},
-       {0xb3, 0x35, 0xf6, 0xcc},       /* i2c add: 76 */
-       {0xb3, 0x00, 0x27, 0xcc},       {0xbc, 0x00, 0x71, 0xcc},
-       {0xb8, 0x00, 0x21, 0xcc},       {0xb8, 0x27, 0x20, 0xcc},
-       {0xb8, 0x01, 0x79, 0xcc},       {0xb8, 0x81, 0x09, 0xcc},
-       {0xb8, 0x2c, 0x50, 0xcc},       {0xb8, 0x2d, 0xf8, 0xcc},
-       {0xb8, 0x2e, 0xf8, 0xcc},       {0xb8, 0x2f, 0xf8, 0xcc},
-       {0xb8, 0x30, 0x50, 0xcc},       {0xb8, 0x31, 0xf8, 0xcc},
-       {0xb8, 0x32, 0xf8, 0xcc},       {0xb8, 0x33, 0xf8, 0xcc},
-       {0xb8, 0x34, 0x50, 0xcc},       {0xb8, 0x35, 0x00, 0xcc},
-       {0xb8, 0x36, 0x00, 0xcc},       {0xb8, 0x37, 0x00, 0xcc},
-       {0x00, 0x1e, 0xc6, 0xaa},       {0x00, 0x20, 0x44, 0xaa},
-       {0x00, 0xad, 0x02, 0xaa},       {0x00, 0xae, 0x2c, 0xaa},
-       {0x00, 0x12, 0x08, 0xaa},       {0x00, 0x17, 0x41, 0xaa},
-       {0x00, 0x19, 0x41, 0xaa},       {0x00, 0x1e, 0x06, 0xaa},
-       {0x00, 0x21, 0x00, 0xaa},       {0x00, 0x36, 0xc0, 0xaa},
-       {0x00, 0x37, 0xc8, 0xaa},       {0x00, 0x3b, 0x36, 0xaa},
-       {0x00, 0x4b, 0xfe, 0xaa},       {0x00, 0x51, 0x1c, 0xaa},
-       {0x00, 0x52, 0x01, 0xaa},       {0x00, 0x55, 0x0a, 0xaa},
-       {0x00, 0x59, 0x02, 0xaa},       {0x00, 0x5a, 0x04, 0xaa},
-       {0x00, 0x5c, 0x10, 0xaa},       {0x00, 0x5d, 0x10, 0xaa},
-       {0x00, 0x5e, 0x10, 0xaa},       {0x00, 0x5f, 0x10, 0xaa},
-       {0x00, 0x61, 0x00, 0xaa},       {0x00, 0x62, 0x18, 0xaa},
-       {0x00, 0x63, 0x30, 0xaa},       {0x00, 0x70, 0x68, 0xaa},
-       {0x00, 0x80, 0x71, 0xaa},       {0x00, 0x81, 0x08, 0xaa},
-       {0x00, 0x82, 0x00, 0xaa},       {0x00, 0x83, 0x55, 0xaa},
-       {0x00, 0x84, 0x06, 0xaa},       {0x00, 0x85, 0x06, 0xaa},
-       {0x00, 0x86, 0x13, 0xaa},       {0x00, 0x87, 0x18, 0xaa},
-       {0x00, 0xaa, 0x3f, 0xaa},       {0x00, 0xab, 0x44, 0xaa},
-       {0x00, 0xb0, 0x68, 0xaa},       {0x00, 0xb5, 0x10, 0xaa},
-       {0x00, 0xb8, 0x20, 0xaa},       {0x00, 0xb9, 0xa0, 0xaa},
-       {0x00, 0xbc, 0x04, 0xaa},       {0x00, 0x8b, 0x40, 0xaa},
-       {0x00, 0x8c, 0x91, 0xaa},       {0x00, 0x8d, 0x8f, 0xaa},
-       {0x00, 0x8e, 0x91, 0xaa},       {0x00, 0x8f, 0x43, 0xaa},
-       {0x00, 0x90, 0x92, 0xaa},       {0x00, 0x91, 0x89, 0xaa},
-       {0x00, 0x92, 0x9d, 0xaa},       {0x00, 0x93, 0x46, 0xaa},
-       {0x00, 0xd6, 0x22, 0xaa},       {0x00, 0x73, 0x00, 0xaa},
-       {0x00, 0x74, 0x10, 0xaa},       {0x00, 0x75, 0x20, 0xaa},
-       {0x00, 0x76, 0x2b, 0xaa},       {0x00, 0x77, 0x36, 0xaa},
-       {0x00, 0x78, 0x49, 0xaa},       {0x00, 0x79, 0x5a, 0xaa},
-       {0x00, 0x7a, 0x7f, 0xaa},       {0x00, 0x7b, 0x9b, 0xaa},
-       {0x00, 0x7c, 0xba, 0xaa},       {0x00, 0x7d, 0xd4, 0xaa},
-       {0x00, 0x7e, 0xea, 0xaa},       {0x00, 0xd6, 0x62, 0xaa},
-       {0x00, 0x73, 0x00, 0xaa},       {0x00, 0x74, 0x10, 0xaa},
-       {0x00, 0x75, 0x20, 0xaa},       {0x00, 0x76, 0x2b, 0xaa},
-       {0x00, 0x77, 0x36, 0xaa},       {0x00, 0x78, 0x49, 0xaa},
-       {0x00, 0x79, 0x5a, 0xaa},       {0x00, 0x7a, 0x7f, 0xaa},
-       {0x00, 0x7b, 0x9b, 0xaa},       {0x00, 0x7c, 0xba, 0xaa},
-       {0x00, 0x7d, 0xd4, 0xaa},       {0x00, 0x7e, 0xea, 0xaa},
-       {0x00, 0xd6, 0xa2, 0xaa},       {0x00, 0x73, 0x00, 0xaa},
-       {0x00, 0x74, 0x10, 0xaa},       {0x00, 0x75, 0x20, 0xaa},
-       {0x00, 0x76, 0x2b, 0xaa},       {0x00, 0x77, 0x36, 0xaa},
-       {0x00, 0x78, 0x49, 0xaa},       {0x00, 0x79, 0x5a, 0xaa},
-       {0x00, 0x7a, 0x7f, 0xaa},       {0x00, 0x7b, 0x9b, 0xaa},
-       {0x00, 0x7c, 0xba, 0xaa},       {0x00, 0x7d, 0xd4, 0xaa},
-       {0x00, 0x7e, 0xea, 0xaa},
-       {0x00, 0x4c, 0x07, 0xaa},
-       {0x00, 0x4b, 0xe0, 0xaa},       {0x00, 0x4e, 0x77, 0xaa},
-       {0x00, 0x59, 0x02, 0xaa},       {0x00, 0x4d, 0x0a, 0xaa},
-/*     {0x00, 0xd1, 0x00, 0xaa},       {0x00, 0x20, 0xc4, 0xaa},
-       {0xb8, 0x8e, 0x00, 0xcc},       {0xb8, 0x8f, 0xff, 0xcc}, */
-       {0x00, 0xd1, 0x3c, 0xaa},       {0x00, 0x20, 0xc4, 0xaa},
-       {0xb8, 0x8e, 0x00, 0xcc},       {0xb8, 0x8f, 0xff, 0xcc},
-       {0xb8, 0xfe, 0x00, 0xcc},       {0xb8, 0xff, 0x28, 0xcc},
-       {0xb9, 0x00, 0x28, 0xcc},       {0xb9, 0x01, 0x28, 0xcc},
-       {0xb9, 0x02, 0x28, 0xcc},       {0xb9, 0x03, 0x00, 0xcc},
-       {0xb9, 0x04, 0x00, 0xcc},       {0xb9, 0x05, 0x3c, 0xcc},
-       {0xb9, 0x06, 0x3c, 0xcc},       {0xb9, 0x07, 0x3c, 0xcc},
-       {0xb9, 0x08, 0x3c, 0xcc},       {0x00, 0x05, 0x00, 0xaa},
-       {0xb3, 0x5c, 0x00, 0xcc},       {0xb3, 0x01, 0x41, 0xcc},
-       {}
-};
-static const u8 po3130_rundata[][4] = {
-       {0x00, 0x47, 0x45, 0xaa},       {0x00, 0x48, 0x9b, 0xaa},
-       {0x00, 0x49, 0x3a, 0xaa},       {0x00, 0x4a, 0x01, 0xaa},
-       {0x00, 0x44, 0x40, 0xaa},
-/*     {0x00, 0xd5, 0x7c, 0xaa}, */
-       {0x00, 0xad, 0x04, 0xaa},       {0x00, 0xae, 0x00, 0xaa},
-       {0x00, 0xb0, 0x78, 0xaa},       {0x00, 0x98, 0x02, 0xaa},
-       {0x00, 0x94, 0x25, 0xaa},       {0x00, 0x95, 0x25, 0xaa},
-       {0x00, 0x59, 0x68, 0xaa},       {0x00, 0x44, 0x20, 0xaa},
-       {0x00, 0x17, 0x50, 0xaa},       {0x00, 0x19, 0x50, 0xaa},
-       {0x00, 0xd1, 0x3c, 0xaa},       {0x00, 0xd1, 0x3c, 0xaa},
-       {0x00, 0x1e, 0x06, 0xaa},       {0x00, 0x1e, 0x06, 0xaa},
-       {}
-};
-
-static const u8 po3130_initQVGA_data[][4] = {
-       {0xb0, 0x4d, 0x00, 0xcc},       {0xb3, 0x01, 0x01, 0xcc},
-       {0x00, 0x00, 0x50, 0xdd},       {0xb0, 0x03, 0x09, 0xcc},
-       {0xb3, 0x00, 0x04, 0xcc},       {0xb3, 0x00, 0x24, 0xcc},
-       {0xb3, 0x00, 0x25, 0xcc},       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},       {0xb3, 0x05, 0x00, 0xcc},
-       {0xb3, 0x06, 0x01, 0xcc},       {0xb3, 0x03, 0x1a, 0xcc},
-       {0xb3, 0x04, 0x15, 0xcc},       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},       {0xb3, 0x22, 0x01, 0xcc},
-       {0xb3, 0x23, 0xe0, 0xcc},       {0xb8, 0x08, 0xe0, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x02, 0xcc},       {0xb3, 0x17, 0x7f, 0xcc},
-       {0xb3, 0x34, 0x01, 0xcc},       {0xb3, 0x35, 0xf6, 0xcc},
-       {0xb3, 0x00, 0x27, 0xcc},       {0xbc, 0x00, 0xd1, 0xcc},
-       {0xb8, 0x00, 0x21, 0xcc},       {0xb8, 0x27, 0x20, 0xcc},
-       {0xb8, 0x01, 0x79, 0xcc},       {0xb8, 0x81, 0x09, 0xcc},
-       {0xb8, 0x2c, 0x50, 0xcc},       {0xb8, 0x2d, 0xf8, 0xcc},
-       {0xb8, 0x2e, 0xf8, 0xcc},       {0xb8, 0x2f, 0xf8, 0xcc},
-       {0xb8, 0x30, 0x50, 0xcc},       {0xb8, 0x31, 0xf8, 0xcc},
-       {0xb8, 0x32, 0xf8, 0xcc},       {0xb8, 0x33, 0xf8, 0xcc},
-       {0xb8, 0x34, 0x50, 0xcc},       {0xb8, 0x35, 0x00, 0xcc},
-       {0xb8, 0x36, 0x00, 0xcc},       {0xb8, 0x37, 0x00, 0xcc},
-       {0x00, 0x1e, 0xc6, 0xaa},       {0x00, 0x20, 0x44, 0xaa},
-       {0x00, 0xad, 0x02, 0xaa},       {0x00, 0xae, 0x2c, 0xaa},
-       {0x00, 0x12, 0x08, 0xaa},       {0x00, 0x17, 0x41, 0xaa},
-       {0x00, 0x19, 0x41, 0xaa},       {0x00, 0x1e, 0x06, 0xaa},
-       {0x00, 0x21, 0x00, 0xaa},       {0x00, 0x36, 0xc0, 0xaa},
-       {0x00, 0x37, 0xc8, 0xaa},       {0x00, 0x3b, 0x36, 0xaa},
-       {0x00, 0x4b, 0xfe, 0xaa},       {0x00, 0x51, 0x1c, 0xaa},
-       {0x00, 0x52, 0x01, 0xaa},       {0x00, 0x55, 0x0a, 0xaa},
-       {0x00, 0x59, 0x6f, 0xaa},       {0x00, 0x5a, 0x04, 0xaa},
-       {0x00, 0x5c, 0x10, 0xaa},       {0x00, 0x5d, 0x10, 0xaa},
-       {0x00, 0x5e, 0x10, 0xaa},       {0x00, 0x5f, 0x10, 0xaa},
-       {0x00, 0x61, 0x00, 0xaa},       {0x00, 0x62, 0x18, 0xaa},
-       {0x00, 0x63, 0x30, 0xaa},       {0x00, 0x70, 0x68, 0xaa},
-       {0x00, 0x80, 0x71, 0xaa},       {0x00, 0x81, 0x08, 0xaa},
-       {0x00, 0x82, 0x00, 0xaa},       {0x00, 0x83, 0x55, 0xaa},
-       {0x00, 0x84, 0x06, 0xaa},       {0x00, 0x85, 0x06, 0xaa},
-       {0x00, 0x86, 0x13, 0xaa},       {0x00, 0x87, 0x18, 0xaa},
-       {0x00, 0xaa, 0x3f, 0xaa},       {0x00, 0xab, 0x44, 0xaa},
-       {0x00, 0xb0, 0x68, 0xaa},       {0x00, 0xb5, 0x10, 0xaa},
-       {0x00, 0xb8, 0x20, 0xaa},       {0x00, 0xb9, 0xa0, 0xaa},
-       {0x00, 0xbc, 0x04, 0xaa},       {0x00, 0x8b, 0x40, 0xaa},
-       {0x00, 0x8c, 0x91, 0xaa},       {0x00, 0x8d, 0x8f, 0xaa},
-       {0x00, 0x8e, 0x91, 0xaa},       {0x00, 0x8f, 0x43, 0xaa},
-       {0x00, 0x90, 0x92, 0xaa},       {0x00, 0x91, 0x89, 0xaa},
-       {0x00, 0x92, 0x9d, 0xaa},       {0x00, 0x93, 0x46, 0xaa},
-       {0x00, 0xd6, 0x22, 0xaa},       {0x00, 0x73, 0x00, 0xaa},
-       {0x00, 0x74, 0x10, 0xaa},       {0x00, 0x75, 0x20, 0xaa},
-       {0x00, 0x76, 0x2b, 0xaa},       {0x00, 0x77, 0x36, 0xaa},
-       {0x00, 0x78, 0x49, 0xaa},       {0x00, 0x79, 0x5a, 0xaa},
-       {0x00, 0x7a, 0x7f, 0xaa},       {0x00, 0x7b, 0x9b, 0xaa},
-       {0x00, 0x7c, 0xba, 0xaa},       {0x00, 0x7d, 0xd4, 0xaa},
-       {0x00, 0x7e, 0xea, 0xaa},       {0x00, 0xd6, 0x62, 0xaa},
-       {0x00, 0x73, 0x00, 0xaa},       {0x00, 0x74, 0x10, 0xaa},
-       {0x00, 0x75, 0x20, 0xaa},       {0x00, 0x76, 0x2b, 0xaa},
-       {0x00, 0x77, 0x36, 0xaa},       {0x00, 0x78, 0x49, 0xaa},
-       {0x00, 0x79, 0x5a, 0xaa},       {0x00, 0x7a, 0x7f, 0xaa},
-       {0x00, 0x7b, 0x9b, 0xaa},       {0x00, 0x7c, 0xba, 0xaa},
-       {0x00, 0x7d, 0xd4, 0xaa},       {0x00, 0x7e, 0xea, 0xaa},
-       {0x00, 0xd6, 0xa2, 0xaa},       {0x00, 0x73, 0x00, 0xaa},
-       {0x00, 0x74, 0x10, 0xaa},       {0x00, 0x75, 0x20, 0xaa},
-       {0x00, 0x76, 0x2b, 0xaa},       {0x00, 0x77, 0x36, 0xaa},
-       {0x00, 0x78, 0x49, 0xaa},       {0x00, 0x79, 0x5a, 0xaa},
-       {0x00, 0x7a, 0x7f, 0xaa},       {0x00, 0x7b, 0x9b, 0xaa},
-       {0x00, 0x7c, 0xba, 0xaa},       {0x00, 0x7d, 0xd4, 0xaa},
-       {0x00, 0x7e, 0xea, 0xaa},       {0x00, 0x4c, 0x07, 0xaa},
-       {0x00, 0x4b, 0xe0, 0xaa},       {0x00, 0x4e, 0x77, 0xaa},
-       {0x00, 0x59, 0x66, 0xaa},       {0x00, 0x4d, 0x0a, 0xaa},
-       {0x00, 0xd1, 0x00, 0xaa},       {0x00, 0x20, 0xc4, 0xaa},
-       {0xb8, 0x8e, 0x00, 0xcc},       {0xb8, 0x8f, 0xff, 0xcc},
-       {0xb8, 0xfe, 0x00, 0xcc},       {0xb8, 0xff, 0x28, 0xcc},
-       {0xb9, 0x00, 0x28, 0xcc},       {0xb9, 0x01, 0x28, 0xcc},
-       {0xb9, 0x02, 0x28, 0xcc},       {0xb9, 0x03, 0x00, 0xcc},
-       {0xb9, 0x04, 0x00, 0xcc},       {0xb9, 0x05, 0x3c, 0xcc},
-       {0xb9, 0x06, 0x3c, 0xcc},       {0xb9, 0x07, 0x3c, 0xcc},
-       {0xb9, 0x08, 0x3c, 0xcc},       {0xbc, 0x02, 0x18, 0xcc},
-       {0xbc, 0x03, 0x50, 0xcc},       {0xbc, 0x04, 0x18, 0xcc},
-       {0xbc, 0x05, 0x00, 0xcc},       {0xbc, 0x06, 0x00, 0xcc},
-       {0xbc, 0x08, 0x30, 0xcc},       {0xbc, 0x09, 0x40, 0xcc},
-       {0xbc, 0x0a, 0x10, 0xcc},       {0xbc, 0x0b, 0x00, 0xcc},
-       {0xbc, 0x0c, 0x00, 0xcc},       {0x00, 0x05, 0x00, 0xaa},
-       {0xb3, 0x5c, 0x00, 0xcc},       {0xb3, 0x01, 0x41, 0xcc},
-       {}
-};
-
-static const u8 hv7131r_gamma[17] = {
-       0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
-       0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
-};
-static const u8 hv7131r_matrix[9] = {
-       0x5f, 0xec, 0xf5, 0xf1, 0x5a, 0xf5, 0xf1, 0xec, 0x63
-};
-static const u8 hv7131r_initVGA_data[][4] = {
-       {0xb3, 0x01, 0x01, 0xcc},
-       {0xb0, 0x03, 0x19, 0xcc},
-       {0xb0, 0x04, 0x02, 0xcc},
-       {0x00, 0x00, 0x20, 0xdd},
-       {0xb3, 0x00, 0x24, 0xcc},
-       {0xb3, 0x00, 0x25, 0xcc},
-       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},
-       {0xb3, 0x05, 0x01, 0xcc},
-       {0xb3, 0x06, 0x03, 0xcc},
-       {0xb3, 0x01, 0x45, 0xcc},
-       {0xb3, 0x03, 0x0b, 0xcc},
-       {0xb3, 0x04, 0x05, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x01, 0xcc},
-       {0xb3, 0x23, 0xe0, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},
-       {0xb3, 0x15, 0x02, 0xcc},
-       {0xb3, 0x16, 0x02, 0xcc},
-       {0xb3, 0x17, 0x7f, 0xcc},
-       {0xb3, 0x34, 0x01, 0xcc},
-       {0xb3, 0x35, 0x91, 0xcc},       /* i2c add: 11 */
-       {0xb3, 0x00, 0x27, 0xcc},
-       {0xbc, 0x00, 0x73, 0xcc},
-       {0xb8, 0x00, 0x23, 0xcc},
-       {0xb8, 0x2c, 0x50, 0xcc},
-       {0xb8, 0x2d, 0xf8, 0xcc},
-       {0xb8, 0x2e, 0xf8, 0xcc},
-       {0xb8, 0x2f, 0xf8, 0xcc},
-       {0xb8, 0x30, 0x50, 0xcc},
-       {0xb8, 0x31, 0xf8, 0xcc},
-       {0xb8, 0x32, 0xf8, 0xcc},
-       {0xb8, 0x33, 0xf8, 0xcc},
-       {0xb8, 0x34, 0x58, 0xcc},
-       {0xb8, 0x35, 0x00, 0xcc},
-       {0xb8, 0x36, 0x00, 0xcc},
-       {0xb8, 0x37, 0x00, 0xcc},
-       {0xb8, 0x27, 0x20, 0xcc},
-       {0xb8, 0x01, 0x7d, 0xcc},
-       {0xb8, 0x81, 0x09, 0xcc},
-       {0xb3, 0x01, 0x41, 0xcc},
-       {0xb8, 0x8e, 0x00, 0xcc},
-       {0xb8, 0x8f, 0xff, 0xcc},
-       {0x00, 0x01, 0x0c, 0xaa},
-       {0x00, 0x14, 0x01, 0xaa},
-       {0x00, 0x15, 0xe6, 0xaa},
-       {0x00, 0x16, 0x02, 0xaa},
-       {0x00, 0x17, 0x86, 0xaa},
-       {0x00, 0x23, 0x00, 0xaa},
-       {0x00, 0x25, 0x03, 0xaa},
-       {0x00, 0x26, 0xa9, 0xaa},
-       {0x00, 0x27, 0x80, 0xaa},
-       {0x00, 0x30, 0x18, 0xaa},
-       {0xb6, 0x00, 0x00, 0xcc},
-       {0xb6, 0x03, 0x02, 0xcc},
-       {0xb6, 0x02, 0x80, 0xcc},
-       {0xb6, 0x05, 0x01, 0xcc},
-       {0xb6, 0x04, 0xe0, 0xcc},
-       {0xb6, 0x12, 0x78, 0xcc},
-       {0xb6, 0x18, 0x02, 0xcc},
-       {0xb6, 0x17, 0x58, 0xcc},
-       {0xb6, 0x16, 0x00, 0xcc},
-       {0xb6, 0x22, 0x12, 0xcc},
-       {0xb6, 0x23, 0x0b, 0xcc},
-       {0xb3, 0x02, 0x02, 0xcc},
-       {0xbf, 0xc0, 0x39, 0xcc},
-       {0xbf, 0xc1, 0x04, 0xcc},
-       {0xbf, 0xcc, 0x10, 0xcc},
-       {0xb6, 0x12, 0xf8, 0xcc},
-       {0xb6, 0x13, 0x13, 0xcc},
-       {0xb9, 0x12, 0x00, 0xcc},
-       {0xb9, 0x13, 0x0a, 0xcc},
-       {0xb9, 0x14, 0x0a, 0xcc},
-       {0xb9, 0x15, 0x0a, 0xcc},
-       {0xb9, 0x16, 0x0a, 0xcc},
-       {0xb8, 0x0c, 0x20, 0xcc},
-       {0xb8, 0x0d, 0x70, 0xcc},
-       {0xb9, 0x18, 0x00, 0xcc},
-       {0xb9, 0x19, 0x0f, 0xcc},
-       {0xb9, 0x1a, 0x0f, 0xcc},
-       {0xb9, 0x1b, 0x0f, 0xcc},
-       {0xb9, 0x1c, 0x0f, 0xcc},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {}
-};
-
-static const u8 hv7131r_initQVGA_data[][4] = {
-       {0xb3, 0x01, 0x01, 0xcc},
-       {0xb0, 0x03, 0x19, 0xcc},
-       {0xb0, 0x04, 0x02, 0xcc},
-       {0x00, 0x00, 0x20, 0xdd},
-       {0xb3, 0x00, 0x24, 0xcc},
-       {0xb3, 0x00, 0x25, 0xcc},
-       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},
-       {0xb3, 0x05, 0x01, 0xcc},
-       {0xb3, 0x06, 0x03, 0xcc},
-       {0xb3, 0x01, 0x45, 0xcc},
-       {0xb3, 0x03, 0x0b, 0xcc},
-       {0xb3, 0x04, 0x05, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x01, 0xcc},
-       {0xb3, 0x23, 0xe0, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},
-       {0xb3, 0x15, 0x02, 0xcc},
-       {0xb3, 0x16, 0x02, 0xcc},
-       {0xb3, 0x17, 0x7f, 0xcc},
-       {0xb3, 0x34, 0x01, 0xcc},
-       {0xb3, 0x35, 0x91, 0xcc},
-       {0xb3, 0x00, 0x27, 0xcc},
-       {0xbc, 0x00, 0xd3, 0xcc},
-       {0xb8, 0x00, 0x23, 0xcc},
-       {0xb8, 0x2c, 0x50, 0xcc},
-       {0xb8, 0x2d, 0xf8, 0xcc},
-       {0xb8, 0x2e, 0xf8, 0xcc},
-       {0xb8, 0x2f, 0xf8, 0xcc},
-       {0xb8, 0x30, 0x50, 0xcc},
-       {0xb8, 0x31, 0xf8, 0xcc},
-       {0xb8, 0x32, 0xf8, 0xcc},
-       {0xb8, 0x33, 0xf8, 0xcc},
-       {0xb8, 0x34, 0x58, 0xcc},
-       {0xb8, 0x35, 0x00, 0xcc},
-       {0xb8, 0x36, 0x00, 0xcc},
-       {0xb8, 0x37, 0x00, 0xcc},
-       {0xb8, 0x27, 0x20, 0xcc},
-       {0xb8, 0x01, 0x7d, 0xcc},
-       {0xb8, 0x81, 0x09, 0xcc},
-       {0xb3, 0x01, 0x41, 0xcc},
-       {0xb8, 0x8e, 0x00, 0xcc},
-       {0xb8, 0x8f, 0xff, 0xcc},
-       {0x00, 0x01, 0x0c, 0xaa},
-       {0x00, 0x14, 0x01, 0xaa},
-       {0x00, 0x15, 0xe6, 0xaa},
-       {0x00, 0x16, 0x02, 0xaa},
-       {0x00, 0x17, 0x86, 0xaa},
-       {0x00, 0x23, 0x00, 0xaa},
-       {0x00, 0x25, 0x03, 0xaa},
-       {0x00, 0x26, 0xa9, 0xaa},
-       {0x00, 0x27, 0x80, 0xaa},
-       {0x00, 0x30, 0x18, 0xaa},
-       {0xb6, 0x00, 0x00, 0xcc},
-       {0xb6, 0x03, 0x01, 0xcc},
-       {0xb6, 0x02, 0x40, 0xcc},
-       {0xb6, 0x05, 0x00, 0xcc},
-       {0xb6, 0x04, 0xf0, 0xcc},
-       {0xb6, 0x12, 0x78, 0xcc},
-       {0xb6, 0x18, 0x00, 0xcc},
-       {0xb6, 0x17, 0x96, 0xcc},
-       {0xb6, 0x16, 0x00, 0xcc},
-       {0xb6, 0x22, 0x12, 0xcc},
-       {0xb6, 0x23, 0x0b, 0xcc},
-       {0xb3, 0x02, 0x02, 0xcc},
-       {0xbf, 0xc0, 0x39, 0xcc},
-       {0xbf, 0xc1, 0x04, 0xcc},
-       {0xbf, 0xcc, 0x10, 0xcc},
-       {0xbc, 0x02, 0x18, 0xcc},
-       {0xbc, 0x03, 0x50, 0xcc},
-       {0xbc, 0x04, 0x18, 0xcc},
-       {0xbc, 0x05, 0x00, 0xcc},
-       {0xbc, 0x06, 0x00, 0xcc},
-       {0xbc, 0x08, 0x30, 0xcc},
-       {0xbc, 0x09, 0x40, 0xcc},
-       {0xbc, 0x0a, 0x10, 0xcc},
-       {0xbc, 0x0b, 0x00, 0xcc},
-       {0xbc, 0x0c, 0x00, 0xcc},
-       {0xb9, 0x12, 0x00, 0xcc},
-       {0xb9, 0x13, 0x0a, 0xcc},
-       {0xb9, 0x14, 0x0a, 0xcc},
-       {0xb9, 0x15, 0x0a, 0xcc},
-       {0xb9, 0x16, 0x0a, 0xcc},
-       {0xb9, 0x18, 0x00, 0xcc},
-       {0xb9, 0x19, 0x0f, 0xcc},
-       {0xb8, 0x0c, 0x20, 0xcc},
-       {0xb8, 0x0d, 0x70, 0xcc},
-       {0xb9, 0x1a, 0x0f, 0xcc},
-       {0xb9, 0x1b, 0x0f, 0xcc},
-       {0xb9, 0x1c, 0x0f, 0xcc},
-       {0xb6, 0x12, 0xf8, 0xcc},
-       {0xb6, 0x13, 0x13, 0xcc},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {}
-};
-
-static const u8 ov7660_gamma[17] = {
-       0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
-       0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
-};
-static const u8 ov7660_matrix[9] = {
-       0x5a, 0xf0, 0xf6, 0xf3, 0x57, 0xf6, 0xf3, 0xef, 0x62
-};
-static const u8 ov7660_initVGA_data[][4] = {
-       {0xb0, 0x4d, 0x00, 0xcc},       {0xb3, 0x01, 0x01, 0xcc},
-       {0x00, 0x00, 0x50, 0xdd},
-       {0xb0, 0x03, 0x01, 0xcc},
-       {0xb3, 0x00, 0x21, 0xcc},       {0xb3, 0x00, 0x26, 0xcc},
-       {0xb3, 0x05, 0x01, 0xcc},
-       {0xb3, 0x06, 0x03, 0xcc},
-       {0xb3, 0x03, 0x1f, 0xcc},       {0xb3, 0x04, 0x05, 0xcc},
-       {0xb3, 0x05, 0x00, 0xcc},
-       {0xb3, 0x06, 0x01, 0xcc},
-       {0xb3, 0x15, 0x00, 0xcc},/* 0xb315  <-0 href startl */
-       {0xb3, 0x16, 0x02, 0xcc},       {0xb3, 0x17, 0x7f, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x23, 0xe0, 0xcc},       {0xb3, 0x1d, 0x01, 0xcc},
-       {0xb3, 0x1f, 0x02, 0xcc},
-       {0xb3, 0x34, 0x01, 0xcc},
-       {0xb3, 0x35, 0xa1, 0xcc},       /* i2c add: 21 */
-       {0xb3, 0x00, 0x26, 0xcc},
-       {0xb8, 0x00, 0x33, 0xcc}, /* 13 */
-       {0xb8, 0x01, 0x7d, 0xcc},
-       {0xbc, 0x00, 0x73, 0xcc},       {0xb8, 0x81, 0x09, 0xcc},
-       {0xb8, 0x27, 0x20, 0xcc},
-       {0xb8, 0x8f, 0x50, 0xcc},
-       {0x00, 0x01, 0x80, 0xaa},       {0x00, 0x02, 0x80, 0xaa},
-       {0x00, 0x12, 0x80, 0xaa},
-       {0x00, 0x12, 0x05, 0xaa},
-       {0x00, 0x1e, 0x01, 0xaa},       /* MVFP */
-       {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */
-       {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */
-       {0x00, 0x0d, 0x48, 0xaa},       {0x00, 0x0e, 0x04, 0xaa},
-       {0x00, 0x13, 0xa7, 0xaa},
-       {0x00, 0x40, 0xc1, 0xaa},       {0x00, 0x35, 0x00, 0xaa},
-       {0x00, 0x36, 0x00, 0xaa},
-       {0x00, 0x3c, 0x68, 0xaa},       {0x00, 0x1b, 0x05, 0xaa},
-       {0x00, 0x39, 0x43, 0xaa},
-       {0x00, 0x8d, 0xcf, 0xaa},
-       {0x00, 0x8b, 0xcc, 0xaa},       {0x00, 0x8c, 0xcc, 0xaa},
-       {0x00, 0x0f, 0x62, 0xaa},
-       {0x00, 0x35, 0x84, 0xaa},
-       {0x00, 0x3b, 0x08, 0xaa}, /* 0 * Nightframe 1/4 + 50Hz -> 0xC8 */
-       {0x00, 0x3a, 0x00, 0xaa}, /* mx change yuyv format 00, 04, 01; 08, 0c*/
-       {0x00, 0x14, 0x2a, 0xaa}, /* agc ampli */
-       {0x00, 0x9e, 0x40, 0xaa},       {0xb8, 0x8f, 0x50, 0xcc},
-       {0x00, 0x01, 0x80, 0xaa},
-       {0x00, 0x02, 0x80, 0xaa},
-       {0xb8, 0xfe, 0x00, 0xcc},       {0xb8, 0xff, 0x28, 0xcc},
-       {0xb9, 0x00, 0x28, 0xcc},
-       {0xb9, 0x01, 0x28, 0xcc},       {0xb9, 0x02, 0x28, 0xcc},
-       {0xb9, 0x03, 0x00, 0xcc},
-       {0xb9, 0x04, 0x00, 0xcc},
-       {0xb9, 0x05, 0x3c, 0xcc},       {0xb9, 0x06, 0x3c, 0xcc},
-       {0xb9, 0x07, 0x3c, 0xcc},
-       {0xb9, 0x08, 0x3c, 0xcc},
-
-       {0xb8, 0x8e, 0x00, 0xcc},       {0xb8, 0x8f, 0xff, 0xcc},
-
-       {0x00, 0x29, 0x3c, 0xaa},       {0xb3, 0x01, 0x45, 0xcc},
-       {}
-};
-static const u8 ov7660_initQVGA_data[][4] = {
-       {0xb0, 0x4d, 0x00, 0xcc},       {0xb3, 0x01, 0x01, 0xcc},
-       {0x00, 0x00, 0x50, 0xdd},       {0xb0, 0x03, 0x01, 0xcc},
-       {0xb3, 0x00, 0x21, 0xcc},       {0xb3, 0x00, 0x26, 0xcc},
-       {0xb3, 0x05, 0x01, 0xcc},       {0xb3, 0x06, 0x03, 0xcc},
-       {0xb3, 0x03, 0x1f, 0xcc},       {0xb3, 0x04, 0x05, 0xcc},
-       {0xb3, 0x05, 0x00, 0xcc},       {0xb3, 0x06, 0x01, 0xcc},
-       {0xb3, 0x15, 0x00, 0xcc},/* 0xb315  <-0 href startl */
-       {0xb3, 0x16, 0x02, 0xcc},       {0xb3, 0x17, 0x7f, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x23, 0xe0, 0xcc},       {0xb3, 0x1d, 0x01, 0xcc},
-       {0xb3, 0x1f, 0x02, 0xcc},       {0xb3, 0x34, 0x01, 0xcc},
-       {0xb3, 0x35, 0xa1, 0xcc},       {0xb3, 0x00, 0x26, 0xcc},
-       {0xb8, 0x00, 0x33, 0xcc}, /* 13 */
-       {0xb8, 0x01, 0x7d, 0xcc},
-/* sizer */
-       {0xbc, 0x00, 0xd3, 0xcc},
-       {0xb8, 0x81, 0x09, 0xcc},       {0xb8, 0x81, 0x09, 0xcc},
-       {0xb8, 0x27, 0x20, 0xcc},       {0xb8, 0x8f, 0x50, 0xcc},
-       {0x00, 0x01, 0x80, 0xaa},       {0x00, 0x02, 0x80, 0xaa},
-       {0x00, 0x12, 0x80, 0xaa},       {0x00, 0x12, 0x05, 0xaa},
-       {0x00, 0x1e, 0x01, 0xaa},       /* MVFP */
-       {0x00, 0x3d, 0x40, 0xaa}, /* 0x3d <-40 gamma 01 */
-       {0x00, 0x41, 0x00, 0xaa}, /* edge 00 */
-       {0x00, 0x0d, 0x48, 0xaa},       {0x00, 0x0e, 0x04, 0xaa},
-       {0x00, 0x13, 0xa7, 0xaa},
-       {0x00, 0x40, 0xc1, 0xaa},       {0x00, 0x35, 0x00, 0xaa},
-       {0x00, 0x36, 0x00, 0xaa},
-       {0x00, 0x3c, 0x68, 0xaa},       {0x00, 0x1b, 0x05, 0xaa},
-       {0x00, 0x39, 0x43, 0xaa},       {0x00, 0x8d, 0xcf, 0xaa},
-       {0x00, 0x8b, 0xcc, 0xaa},       {0x00, 0x8c, 0xcc, 0xaa},
-       {0x00, 0x0f, 0x62, 0xaa},       {0x00, 0x35, 0x84, 0xaa},
-       {0x00, 0x3b, 0x08, 0xaa}, /* 0  * Nightframe 1/4 + 50Hz -> 0xC8 */
-       {0x00, 0x3a, 0x00, 0xaa}, /* mx change yuyv format 00, 04, 01; 08, 0c*/
-       {0x00, 0x14, 0x2a, 0xaa}, /* agc ampli */
-       {0x00, 0x9e, 0x40, 0xaa},       {0xb8, 0x8f, 0x50, 0xcc},
-       {0x00, 0x01, 0x80, 0xaa},
-       {0x00, 0x02, 0x80, 0xaa},
-/* sizer filters */
-       {0xbc, 0x02, 0x08, 0xcc},
-       {0xbc, 0x03, 0x70, 0xcc},
-       {0xb8, 0x35, 0x00, 0xcc},
-       {0xb8, 0x36, 0x00, 0xcc},
-       {0xb8, 0x37, 0x00, 0xcc},
-       {0xbc, 0x04, 0x08, 0xcc},
-       {0xbc, 0x05, 0x00, 0xcc},
-       {0xbc, 0x06, 0x00, 0xcc},
-       {0xbc, 0x08, 0x3c, 0xcc},
-       {0xbc, 0x09, 0x40, 0xcc},
-       {0xbc, 0x0a, 0x04, 0xcc},
-       {0xbc, 0x0b, 0x00, 0xcc},
-       {0xbc, 0x0c, 0x00, 0xcc},
-/* */
-       {0xb8, 0xfe, 0x00, 0xcc},
-       {0xb8, 0xff, 0x28, 0xcc},
-/* */
-       {0xb9, 0x00, 0x28, 0xcc},       {0xb9, 0x01, 0x28, 0xcc},
-       {0xb9, 0x02, 0x28, 0xcc},       {0xb9, 0x03, 0x00, 0xcc},
-       {0xb9, 0x04, 0x00, 0xcc},       {0xb9, 0x05, 0x3c, 0xcc},
-       {0xb9, 0x06, 0x3c, 0xcc},       {0xb9, 0x07, 0x3c, 0xcc},
-       {0xb9, 0x08, 0x3c, 0xcc},
-/* */
-       {0xb8, 0x8e, 0x00, 0xcc},
-       {0xb8, 0x8f, 0xff, 0xcc}, /* ff */
-       {0x00, 0x29, 0x3c, 0xaa},
-       {0xb3, 0x01, 0x45, 0xcc}, /* 45 */
-       {}
-};
-
-static const u8 ov7660_50HZ[][4] = {
-       {0x00, 0x3b, 0x08, 0xaa},
-       {0x00, 0x9d, 0x40, 0xaa},
-       {0x00, 0x13, 0xa7, 0xaa},
-       {}
-};
-
-static const u8 ov7660_60HZ[][4] = {
-       {0x00, 0x3b, 0x00, 0xaa},
-       {0x00, 0x9e, 0x40, 0xaa},
-       {0x00, 0x13, 0xa7, 0xaa},
-       {}
-};
-
-static const u8 ov7660_NoFliker[][4] = {
-       {0x00, 0x13, 0x87, 0xaa},
-       {}
-};
-
-static const u8 ov7670_InitVGA[][4] = {
-       {0xb3, 0x01, 0x05, 0xcc},
-       {0x00, 0x00, 0x30, 0xdd},
-       {0xb0, 0x03, 0x19, 0xcc},
-       {0x00, 0x00, 0x10, 0xdd},
-       {0xb0, 0x04, 0x02, 0xcc},
-       {0x00, 0x00, 0x10, 0xdd},
-       {0xb3, 0x00, 0x66, 0xcc},
-       {0xb3, 0x00, 0x67, 0xcc},
-       {0xb0, 0x16, 0x01, 0xcc},
-       {0xb3, 0x35, 0xa1, 0xcc},       /* i2c add: 21 */
-       {0xb3, 0x34, 0x01, 0xcc},
-       {0xb3, 0x05, 0x01, 0xcc},
-       {0xb3, 0x06, 0x01, 0xcc},
-       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},
-       {0xb3, 0x02, 0x02, 0xcc},
-       {0xb3, 0x03, 0x1f, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},
-       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x02, 0xcc},
-       {0xb3, 0x17, 0x7f, 0xcc},
-       {0xb3, 0x04, 0x05, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x01, 0xcc},
-       {0xb3, 0x23, 0xe0, 0xcc},
-       {0xbc, 0x00, 0x41, 0xcc},
-       {0xbc, 0x01, 0x01, 0xcc},
-       {0x00, 0x12, 0x80, 0xaa},
-       {0x00, 0x00, 0x20, 0xdd},
-       {0x00, 0x12, 0x00, 0xaa},
-       {0x00, 0x11, 0x40, 0xaa},
-       {0x00, 0x6b, 0x0a, 0xaa},
-       {0x00, 0x3a, 0x04, 0xaa},
-       {0x00, 0x40, 0xc0, 0xaa},
-       {0x00, 0x8c, 0x00, 0xaa},
-       {0x00, 0x7a, 0x29, 0xaa},
-       {0x00, 0x7b, 0x0e, 0xaa},
-       {0x00, 0x7c, 0x1a, 0xaa},
-       {0x00, 0x7d, 0x31, 0xaa},
-       {0x00, 0x7e, 0x53, 0xaa},
-       {0x00, 0x7f, 0x60, 0xaa},
-       {0x00, 0x80, 0x6b, 0xaa},
-       {0x00, 0x81, 0x73, 0xaa},
-       {0x00, 0x82, 0x7b, 0xaa},
-       {0x00, 0x83, 0x82, 0xaa},
-       {0x00, 0x84, 0x89, 0xaa},
-       {0x00, 0x85, 0x96, 0xaa},
-       {0x00, 0x86, 0xa1, 0xaa},
-       {0x00, 0x87, 0xb7, 0xaa},
-       {0x00, 0x88, 0xcc, 0xaa},
-       {0x00, 0x89, 0xe1, 0xaa},
-       {0x00, 0x13, 0xe0, 0xaa},
-       {0x00, 0x00, 0x00, 0xaa},
-       {0x00, 0x10, 0x00, 0xaa},
-       {0x00, 0x0d, 0x40, 0xaa},
-       {0x00, 0x14, 0x28, 0xaa},
-       {0x00, 0xa5, 0x05, 0xaa},
-       {0x00, 0xab, 0x07, 0xaa},
-       {0x00, 0x24, 0x95, 0xaa},
-       {0x00, 0x25, 0x33, 0xaa},
-       {0x00, 0x26, 0xe3, 0xaa},
-       {0x00, 0x9f, 0x88, 0xaa},
-       {0x00, 0xa0, 0x78, 0xaa},
-       {0x00, 0x55, 0x90, 0xaa},
-       {0x00, 0xa1, 0x03, 0xaa},
-       {0x00, 0xa6, 0xe0, 0xaa},
-       {0x00, 0xa7, 0xd8, 0xaa},
-       {0x00, 0xa8, 0xf0, 0xaa},
-       {0x00, 0xa9, 0x90, 0xaa},
-       {0x00, 0xaa, 0x14, 0xaa},
-       {0x00, 0x13, 0xe5, 0xaa},
-       {0x00, 0x0e, 0x61, 0xaa},
-       {0x00, 0x0f, 0x4b, 0xaa},
-       {0x00, 0x16, 0x02, 0xaa},
-       {0x00, 0x1e, 0x07, 0xaa},       /* MVFP */
-       {0x00, 0x21, 0x02, 0xaa},
-       {0x00, 0x22, 0x91, 0xaa},
-       {0x00, 0x29, 0x07, 0xaa},
-       {0x00, 0x33, 0x0b, 0xaa},
-       {0x00, 0x35, 0x0b, 0xaa},
-       {0x00, 0x37, 0x1d, 0xaa},
-       {0x00, 0x38, 0x71, 0xaa},
-       {0x00, 0x39, 0x2a, 0xaa},
-       {0x00, 0x3c, 0x78, 0xaa},
-       {0x00, 0x4d, 0x40, 0xaa},
-       {0x00, 0x4e, 0x20, 0xaa},
-       {0x00, 0x74, 0x19, 0xaa},
-       {0x00, 0x8d, 0x4f, 0xaa},
-       {0x00, 0x8e, 0x00, 0xaa},
-       {0x00, 0x8f, 0x00, 0xaa},
-       {0x00, 0x90, 0x00, 0xaa},
-       {0x00, 0x91, 0x00, 0xaa},
-       {0x00, 0x96, 0x00, 0xaa},
-       {0x00, 0x9a, 0x80, 0xaa},
-       {0x00, 0xb0, 0x84, 0xaa},
-       {0x00, 0xb1, 0x0c, 0xaa},
-       {0x00, 0xb2, 0x0e, 0xaa},
-       {0x00, 0xb3, 0x82, 0xaa},
-       {0x00, 0xb8, 0x0a, 0xaa},
-       {0x00, 0x43, 0x14, 0xaa},
-       {0x00, 0x44, 0xf0, 0xaa},
-       {0x00, 0x45, 0x45, 0xaa},
-       {0x00, 0x46, 0x63, 0xaa},
-       {0x00, 0x47, 0x2d, 0xaa},
-       {0x00, 0x48, 0x46, 0xaa},
-       {0x00, 0x59, 0x88, 0xaa},
-       {0x00, 0x5a, 0xa0, 0xaa},
-       {0x00, 0x5b, 0xc6, 0xaa},
-       {0x00, 0x5c, 0x7d, 0xaa},
-       {0x00, 0x5d, 0x5f, 0xaa},
-       {0x00, 0x5e, 0x19, 0xaa},
-       {0x00, 0x6c, 0x0a, 0xaa},
-       {0x00, 0x6d, 0x55, 0xaa},
-       {0x00, 0x6e, 0x11, 0xaa},
-       {0x00, 0x6f, 0x9e, 0xaa},
-       {0x00, 0x69, 0x00, 0xaa},
-       {0x00, 0x6a, 0x40, 0xaa},
-       {0x00, 0x01, 0x40, 0xaa},
-       {0x00, 0x02, 0x40, 0xaa},
-       {0x00, 0x13, 0xe7, 0xaa},
-       {0x00, 0x5f, 0xf0, 0xaa},
-       {0x00, 0x60, 0xf0, 0xaa},
-       {0x00, 0x61, 0xf0, 0xaa},
-       {0x00, 0x27, 0xa0, 0xaa},
-       {0x00, 0x28, 0x80, 0xaa},
-       {0x00, 0x2c, 0x90, 0xaa},
-       {0x00, 0x4f, 0x66, 0xaa},
-       {0x00, 0x50, 0x66, 0xaa},
-       {0x00, 0x51, 0x00, 0xaa},
-       {0x00, 0x52, 0x22, 0xaa},
-       {0x00, 0x53, 0x5e, 0xaa},
-       {0x00, 0x54, 0x80, 0xaa},
-       {0x00, 0x58, 0x9e, 0xaa},
-       {0x00, 0x41, 0x08, 0xaa},
-       {0x00, 0x3f, 0x00, 0xaa},
-       {0x00, 0x75, 0x85, 0xaa},
-       {0x00, 0x76, 0xe1, 0xaa},
-       {0x00, 0x4c, 0x00, 0xaa},
-       {0x00, 0x77, 0x0a, 0xaa},
-       {0x00, 0x3d, 0x88, 0xaa},
-       {0x00, 0x4b, 0x09, 0xaa},
-       {0x00, 0xc9, 0x60, 0xaa},
-       {0x00, 0x41, 0x38, 0xaa},
-       {0x00, 0x62, 0x30, 0xaa},
-       {0x00, 0x63, 0x30, 0xaa},
-       {0x00, 0x64, 0x08, 0xaa},
-       {0x00, 0x94, 0x07, 0xaa},
-       {0x00, 0x95, 0x0b, 0xaa},
-       {0x00, 0x65, 0x00, 0xaa},
-       {0x00, 0x66, 0x05, 0xaa},
-       {0x00, 0x56, 0x50, 0xaa},
-       {0x00, 0x34, 0x11, 0xaa},
-       {0x00, 0xa4, 0x88, 0xaa},
-       {0x00, 0x96, 0x00, 0xaa},
-       {0x00, 0x97, 0x30, 0xaa},
-       {0x00, 0x98, 0x20, 0xaa},
-       {0x00, 0x99, 0x30, 0xaa},
-       {0x00, 0x9a, 0x84, 0xaa},
-       {0x00, 0x9b, 0x29, 0xaa},
-       {0x00, 0x9c, 0x03, 0xaa},
-       {0x00, 0x78, 0x04, 0xaa},
-       {0x00, 0x79, 0x01, 0xaa},
-       {0x00, 0xc8, 0xf0, 0xaa},
-       {0x00, 0x79, 0x0f, 0xaa},
-       {0x00, 0xc8, 0x00, 0xaa},
-       {0x00, 0x79, 0x10, 0xaa},
-       {0x00, 0xc8, 0x7e, 0xaa},
-       {0x00, 0x79, 0x0a, 0xaa},
-       {0x00, 0xc8, 0x80, 0xaa},
-       {0x00, 0x79, 0x0b, 0xaa},
-       {0x00, 0xc8, 0x01, 0xaa},
-       {0x00, 0x79, 0x0c, 0xaa},
-       {0x00, 0xc8, 0x0f, 0xaa},
-       {0x00, 0x79, 0x0d, 0xaa},
-       {0x00, 0xc8, 0x20, 0xaa},
-       {0x00, 0x79, 0x09, 0xaa},
-       {0x00, 0xc8, 0x80, 0xaa},
-       {0x00, 0x79, 0x02, 0xaa},
-       {0x00, 0xc8, 0xc0, 0xaa},
-       {0x00, 0x79, 0x03, 0xaa},
-       {0x00, 0xc8, 0x40, 0xaa},
-       {0x00, 0x79, 0x05, 0xaa},
-       {0x00, 0xc8, 0x30, 0xaa},
-       {0x00, 0x79, 0x26, 0xaa},
-       {0x00, 0x11, 0x40, 0xaa},
-       {0x00, 0x3a, 0x04, 0xaa},
-       {0x00, 0x12, 0x00, 0xaa},
-       {0x00, 0x40, 0xc0, 0xaa},
-       {0x00, 0x8c, 0x00, 0xaa},
-       {0x00, 0x17, 0x14, 0xaa},
-       {0x00, 0x18, 0x02, 0xaa},
-       {0x00, 0x32, 0x92, 0xaa},
-       {0x00, 0x19, 0x02, 0xaa},
-       {0x00, 0x1a, 0x7a, 0xaa},
-       {0x00, 0x03, 0x0a, 0xaa},
-       {0x00, 0x0c, 0x00, 0xaa},
-       {0x00, 0x3e, 0x00, 0xaa},
-       {0x00, 0x70, 0x3a, 0xaa},
-       {0x00, 0x71, 0x35, 0xaa},
-       {0x00, 0x72, 0x11, 0xaa},
-       {0x00, 0x73, 0xf0, 0xaa},
-       {0x00, 0xa2, 0x02, 0xaa},
-       {0x00, 0xb1, 0x00, 0xaa},
-       {0x00, 0xb1, 0x0c, 0xaa},
-       {0x00, 0x1e, 0x37, 0xaa},       /* MVFP */
-       {0x00, 0xaa, 0x14, 0xaa},
-       {0x00, 0x24, 0x80, 0xaa},
-       {0x00, 0x25, 0x74, 0xaa},
-       {0x00, 0x26, 0xd3, 0xaa},
-       {0x00, 0x0d, 0x00, 0xaa},
-       {0x00, 0x14, 0x18, 0xaa},
-       {0x00, 0x9d, 0x99, 0xaa},
-       {0x00, 0x9e, 0x7f, 0xaa},
-       {0x00, 0x64, 0x08, 0xaa},
-       {0x00, 0x94, 0x07, 0xaa},
-       {0x00, 0x95, 0x06, 0xaa},
-       {0x00, 0x66, 0x05, 0xaa},
-       {0x00, 0x41, 0x08, 0xaa},
-       {0x00, 0x3f, 0x00, 0xaa},
-       {0x00, 0x75, 0x07, 0xaa},
-       {0x00, 0x76, 0xe1, 0xaa},
-       {0x00, 0x4c, 0x00, 0xaa},
-       {0x00, 0x77, 0x00, 0xaa},
-       {0x00, 0x3d, 0xc2, 0xaa},
-       {0x00, 0x4b, 0x09, 0xaa},
-       {0x00, 0xc9, 0x60, 0xaa},
-       {0x00, 0x41, 0x38, 0xaa},
-       {0xbf, 0xc0, 0x26, 0xcc},
-       {0xbf, 0xc1, 0x02, 0xcc},
-       {0xbf, 0xcc, 0x04, 0xcc},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {0xb3, 0x01, 0x45, 0xcc},
-       {0x00, 0x77, 0x05, 0xaa},
-       {},
-};
-
-static const u8 ov7670_InitQVGA[][4] = {
-       {0xb3, 0x01, 0x05, 0xcc},
-       {0x00, 0x00, 0x30, 0xdd},
-       {0xb0, 0x03, 0x19, 0xcc},
-       {0x00, 0x00, 0x10, 0xdd},
-       {0xb0, 0x04, 0x02, 0xcc},
-       {0x00, 0x00, 0x10, 0xdd},
-       {0xb3, 0x00, 0x66, 0xcc},
-       {0xb3, 0x00, 0x67, 0xcc},
-       {0xb0, 0x16, 0x01, 0xcc},
-       {0xb3, 0x35, 0xa1, 0xcc},       /* i2c add: 21 */
-       {0xb3, 0x34, 0x01, 0xcc},
-       {0xb3, 0x05, 0x01, 0xcc},
-       {0xb3, 0x06, 0x01, 0xcc},
-       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},
-       {0xb3, 0x02, 0x02, 0xcc},
-       {0xb3, 0x03, 0x1f, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},
-       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x02, 0xcc},
-       {0xb3, 0x17, 0x7f, 0xcc},
-       {0xb3, 0x04, 0x05, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x01, 0xcc},
-       {0xb3, 0x23, 0xe0, 0xcc},
-       {0xbc, 0x00, 0xd1, 0xcc},
-       {0xbc, 0x01, 0x01, 0xcc},
-       {0x00, 0x12, 0x80, 0xaa},
-       {0x00, 0x00, 0x20, 0xdd},
-       {0x00, 0x12, 0x00, 0xaa},
-       {0x00, 0x11, 0x40, 0xaa},
-       {0x00, 0x6b, 0x0a, 0xaa},
-       {0x00, 0x3a, 0x04, 0xaa},
-       {0x00, 0x40, 0xc0, 0xaa},
-       {0x00, 0x8c, 0x00, 0xaa},
-       {0x00, 0x7a, 0x29, 0xaa},
-       {0x00, 0x7b, 0x0e, 0xaa},
-       {0x00, 0x7c, 0x1a, 0xaa},
-       {0x00, 0x7d, 0x31, 0xaa},
-       {0x00, 0x7e, 0x53, 0xaa},
-       {0x00, 0x7f, 0x60, 0xaa},
-       {0x00, 0x80, 0x6b, 0xaa},
-       {0x00, 0x81, 0x73, 0xaa},
-       {0x00, 0x82, 0x7b, 0xaa},
-       {0x00, 0x83, 0x82, 0xaa},
-       {0x00, 0x84, 0x89, 0xaa},
-       {0x00, 0x85, 0x96, 0xaa},
-       {0x00, 0x86, 0xa1, 0xaa},
-       {0x00, 0x87, 0xb7, 0xaa},
-       {0x00, 0x88, 0xcc, 0xaa},
-       {0x00, 0x89, 0xe1, 0xaa},
-       {0x00, 0x13, 0xe0, 0xaa},
-       {0x00, 0x00, 0x00, 0xaa},
-       {0x00, 0x10, 0x00, 0xaa},
-       {0x00, 0x0d, 0x40, 0xaa},
-       {0x00, 0x14, 0x28, 0xaa},
-       {0x00, 0xa5, 0x05, 0xaa},
-       {0x00, 0xab, 0x07, 0xaa},
-       {0x00, 0x24, 0x95, 0xaa},
-       {0x00, 0x25, 0x33, 0xaa},
-       {0x00, 0x26, 0xe3, 0xaa},
-       {0x00, 0x9f, 0x88, 0xaa},
-       {0x00, 0xa0, 0x78, 0xaa},
-       {0x00, 0x55, 0x90, 0xaa},
-       {0x00, 0xa1, 0x03, 0xaa},
-       {0x00, 0xa6, 0xe0, 0xaa},
-       {0x00, 0xa7, 0xd8, 0xaa},
-       {0x00, 0xa8, 0xf0, 0xaa},
-       {0x00, 0xa9, 0x90, 0xaa},
-       {0x00, 0xaa, 0x14, 0xaa},
-       {0x00, 0x13, 0xe5, 0xaa},
-       {0x00, 0x0e, 0x61, 0xaa},
-       {0x00, 0x0f, 0x4b, 0xaa},
-       {0x00, 0x16, 0x02, 0xaa},
-       {0x00, 0x1e, 0x07, 0xaa},       /* MVFP */
-       {0x00, 0x21, 0x02, 0xaa},
-       {0x00, 0x22, 0x91, 0xaa},
-       {0x00, 0x29, 0x07, 0xaa},
-       {0x00, 0x33, 0x0b, 0xaa},
-       {0x00, 0x35, 0x0b, 0xaa},
-       {0x00, 0x37, 0x1d, 0xaa},
-       {0x00, 0x38, 0x71, 0xaa},
-       {0x00, 0x39, 0x2a, 0xaa},
-       {0x00, 0x3c, 0x78, 0xaa},
-       {0x00, 0x4d, 0x40, 0xaa},
-       {0x00, 0x4e, 0x20, 0xaa},
-       {0x00, 0x74, 0x19, 0xaa},
-       {0x00, 0x8d, 0x4f, 0xaa},
-       {0x00, 0x8e, 0x00, 0xaa},
-       {0x00, 0x8f, 0x00, 0xaa},
-       {0x00, 0x90, 0x00, 0xaa},
-       {0x00, 0x91, 0x00, 0xaa},
-       {0x00, 0x96, 0x00, 0xaa},
-       {0x00, 0x9a, 0x80, 0xaa},
-       {0x00, 0xb0, 0x84, 0xaa},
-       {0x00, 0xb1, 0x0c, 0xaa},
-       {0x00, 0xb2, 0x0e, 0xaa},
-       {0x00, 0xb3, 0x82, 0xaa},
-       {0x00, 0xb8, 0x0a, 0xaa},
-       {0x00, 0x43, 0x14, 0xaa},
-       {0x00, 0x44, 0xf0, 0xaa},
-       {0x00, 0x45, 0x45, 0xaa},
-       {0x00, 0x46, 0x63, 0xaa},
-       {0x00, 0x47, 0x2d, 0xaa},
-       {0x00, 0x48, 0x46, 0xaa},
-       {0x00, 0x59, 0x88, 0xaa},
-       {0x00, 0x5a, 0xa0, 0xaa},
-       {0x00, 0x5b, 0xc6, 0xaa},
-       {0x00, 0x5c, 0x7d, 0xaa},
-       {0x00, 0x5d, 0x5f, 0xaa},
-       {0x00, 0x5e, 0x19, 0xaa},
-       {0x00, 0x6c, 0x0a, 0xaa},
-       {0x00, 0x6d, 0x55, 0xaa},
-       {0x00, 0x6e, 0x11, 0xaa},
-       {0x00, 0x6f, 0x9e, 0xaa},
-       {0x00, 0x69, 0x00, 0xaa},
-       {0x00, 0x6a, 0x40, 0xaa},
-       {0x00, 0x01, 0x40, 0xaa},
-       {0x00, 0x02, 0x40, 0xaa},
-       {0x00, 0x13, 0xe7, 0xaa},
-       {0x00, 0x5f, 0xf0, 0xaa},
-       {0x00, 0x60, 0xf0, 0xaa},
-       {0x00, 0x61, 0xf0, 0xaa},
-       {0x00, 0x27, 0xa0, 0xaa},
-       {0x00, 0x28, 0x80, 0xaa},
-       {0x00, 0x2c, 0x90, 0xaa},
-       {0x00, 0x4f, 0x66, 0xaa},
-       {0x00, 0x50, 0x66, 0xaa},
-       {0x00, 0x51, 0x00, 0xaa},
-       {0x00, 0x52, 0x22, 0xaa},
-       {0x00, 0x53, 0x5e, 0xaa},
-       {0x00, 0x54, 0x80, 0xaa},
-       {0x00, 0x58, 0x9e, 0xaa},
-       {0x00, 0x41, 0x08, 0xaa},
-       {0x00, 0x3f, 0x00, 0xaa},
-       {0x00, 0x75, 0x85, 0xaa},
-       {0x00, 0x76, 0xe1, 0xaa},
-       {0x00, 0x4c, 0x00, 0xaa},
-       {0x00, 0x77, 0x0a, 0xaa},
-       {0x00, 0x3d, 0x88, 0xaa},
-       {0x00, 0x4b, 0x09, 0xaa},
-       {0x00, 0xc9, 0x60, 0xaa},
-       {0x00, 0x41, 0x38, 0xaa},
-       {0x00, 0x62, 0x30, 0xaa},
-       {0x00, 0x63, 0x30, 0xaa},
-       {0x00, 0x64, 0x08, 0xaa},
-       {0x00, 0x94, 0x07, 0xaa},
-       {0x00, 0x95, 0x0b, 0xaa},
-       {0x00, 0x65, 0x00, 0xaa},
-       {0x00, 0x66, 0x05, 0xaa},
-       {0x00, 0x56, 0x50, 0xaa},
-       {0x00, 0x34, 0x11, 0xaa},
-       {0x00, 0xa4, 0x88, 0xaa},
-       {0x00, 0x96, 0x00, 0xaa},
-       {0x00, 0x97, 0x30, 0xaa},
-       {0x00, 0x98, 0x20, 0xaa},
-       {0x00, 0x99, 0x30, 0xaa},
-       {0x00, 0x9a, 0x84, 0xaa},
-       {0x00, 0x9b, 0x29, 0xaa},
-       {0x00, 0x9c, 0x03, 0xaa},
-       {0x00, 0x78, 0x04, 0xaa},
-       {0x00, 0x79, 0x01, 0xaa},
-       {0x00, 0xc8, 0xf0, 0xaa},
-       {0x00, 0x79, 0x0f, 0xaa},
-       {0x00, 0xc8, 0x00, 0xaa},
-       {0x00, 0x79, 0x10, 0xaa},
-       {0x00, 0xc8, 0x7e, 0xaa},
-       {0x00, 0x79, 0x0a, 0xaa},
-       {0x00, 0xc8, 0x80, 0xaa},
-       {0x00, 0x79, 0x0b, 0xaa},
-       {0x00, 0xc8, 0x01, 0xaa},
-       {0x00, 0x79, 0x0c, 0xaa},
-       {0x00, 0xc8, 0x0f, 0xaa},
-       {0x00, 0x79, 0x0d, 0xaa},
-       {0x00, 0xc8, 0x20, 0xaa},
-       {0x00, 0x79, 0x09, 0xaa},
-       {0x00, 0xc8, 0x80, 0xaa},
-       {0x00, 0x79, 0x02, 0xaa},
-       {0x00, 0xc8, 0xc0, 0xaa},
-       {0x00, 0x79, 0x03, 0xaa},
-       {0x00, 0xc8, 0x40, 0xaa},
-       {0x00, 0x79, 0x05, 0xaa},
-       {0x00, 0xc8, 0x30, 0xaa},
-       {0x00, 0x79, 0x26, 0xaa},
-       {0x00, 0x11, 0x40, 0xaa},
-       {0x00, 0x3a, 0x04, 0xaa},
-       {0x00, 0x12, 0x00, 0xaa},
-       {0x00, 0x40, 0xc0, 0xaa},
-       {0x00, 0x8c, 0x00, 0xaa},
-       {0x00, 0x17, 0x14, 0xaa},
-       {0x00, 0x18, 0x02, 0xaa},
-       {0x00, 0x32, 0x92, 0xaa},
-       {0x00, 0x19, 0x02, 0xaa},
-       {0x00, 0x1a, 0x7a, 0xaa},
-       {0x00, 0x03, 0x0a, 0xaa},
-       {0x00, 0x0c, 0x00, 0xaa},
-       {0x00, 0x3e, 0x00, 0xaa},
-       {0x00, 0x70, 0x3a, 0xaa},
-       {0x00, 0x71, 0x35, 0xaa},
-       {0x00, 0x72, 0x11, 0xaa},
-       {0x00, 0x73, 0xf0, 0xaa},
-       {0x00, 0xa2, 0x02, 0xaa},
-       {0x00, 0xb1, 0x00, 0xaa},
-       {0x00, 0xb1, 0x0c, 0xaa},
-       {0x00, 0x1e, 0x37, 0xaa},       /* MVFP */
-       {0x00, 0xaa, 0x14, 0xaa},
-       {0x00, 0x24, 0x80, 0xaa},
-       {0x00, 0x25, 0x74, 0xaa},
-       {0x00, 0x26, 0xd3, 0xaa},
-       {0x00, 0x0d, 0x00, 0xaa},
-       {0x00, 0x14, 0x18, 0xaa},
-       {0x00, 0x9d, 0x99, 0xaa},
-       {0x00, 0x9e, 0x7f, 0xaa},
-       {0x00, 0x64, 0x08, 0xaa},
-       {0x00, 0x94, 0x07, 0xaa},
-       {0x00, 0x95, 0x06, 0xaa},
-       {0x00, 0x66, 0x05, 0xaa},
-       {0x00, 0x41, 0x08, 0xaa},
-       {0x00, 0x3f, 0x00, 0xaa},
-       {0x00, 0x75, 0x07, 0xaa},
-       {0x00, 0x76, 0xe1, 0xaa},
-       {0x00, 0x4c, 0x00, 0xaa},
-       {0x00, 0x77, 0x00, 0xaa},
-       {0x00, 0x3d, 0xc2, 0xaa},
-       {0x00, 0x4b, 0x09, 0xaa},
-       {0x00, 0xc9, 0x60, 0xaa},
-       {0x00, 0x41, 0x38, 0xaa},
-       {0xbc, 0x02, 0x18, 0xcc},
-       {0xbc, 0x03, 0x50, 0xcc},
-       {0xbc, 0x04, 0x18, 0xcc},
-       {0xbc, 0x05, 0x00, 0xcc},
-       {0xbc, 0x06, 0x00, 0xcc},
-       {0xbc, 0x08, 0x30, 0xcc},
-       {0xbc, 0x09, 0x40, 0xcc},
-       {0xbc, 0x0a, 0x10, 0xcc},
-       {0xbc, 0x0b, 0x00, 0xcc},
-       {0xbc, 0x0c, 0x00, 0xcc},
-       {0xbf, 0xc0, 0x26, 0xcc},
-       {0xbf, 0xc1, 0x02, 0xcc},
-       {0xbf, 0xcc, 0x04, 0xcc},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {0xb3, 0x01, 0x45, 0xcc},
-       {0x00, 0x77, 0x05, 0xaa},
-       {},
-};
-
-/* PO1200 - values from usbvm326.inf and ms-win trace */
-static const u8 po1200_gamma[17] = {
-       0x00, 0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
-       0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff
-};
-static const u8 po1200_matrix[9] = {
-       0x60, 0xf9, 0xe5, 0xe7, 0x50, 0x05, 0xf3, 0xe6, 0x5e
-};
-static const u8 po1200_initVGA_data[][4] = {
-       {0xb0, 0x03, 0x19, 0xcc},       /* reset? */
-       {0xb0, 0x03, 0x19, 0xcc},
-/*     {0x00, 0x00, 0x33, 0xdd}, */
-       {0xb0, 0x04, 0x02, 0xcc},
-       {0xb0, 0x02, 0x02, 0xcc},
-       {0xb3, 0x5d, 0x00, 0xcc},
-       {0xb3, 0x01, 0x01, 0xcc},
-       {0xb3, 0x00, 0x64, 0xcc},
-       {0xb3, 0x00, 0x65, 0xcc},
-       {0xb3, 0x05, 0x01, 0xcc},
-       {0xb3, 0x06, 0x01, 0xcc},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},
-       {0xb3, 0x00, 0x67, 0xcc},
-       {0xb3, 0x02, 0xb2, 0xcc},
-       {0xb3, 0x03, 0x18, 0xcc},
-       {0xb3, 0x04, 0x15, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x02, 0xcc},
-       {0xb3, 0x23, 0x58, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},
-       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x03, 0xcc},
-       {0xb3, 0x17, 0x1f, 0xcc},
-       {0xbc, 0x00, 0x71, 0xcc},
-       {0xbc, 0x01, 0x01, 0xcc},
-       {0xb0, 0x54, 0x13, 0xcc},
-       {0xb3, 0x00, 0x67, 0xcc},
-       {0xb3, 0x34, 0x01, 0xcc},
-       {0xb3, 0x35, 0xdc, 0xcc},       /* i2c add: 5c */
-       {0x00, 0x03, 0x00, 0xaa},
-       {0x00, 0x12, 0x05, 0xaa},
-       {0x00, 0x13, 0x02, 0xaa},
-       {0x00, 0x1e, 0xc6, 0xaa},       /* h/v flip */
-       {0x00, 0x21, 0x00, 0xaa},
-       {0x00, 0x25, 0x02, 0xaa},
-       {0x00, 0x3c, 0x4f, 0xaa},
-       {0x00, 0x3f, 0xe0, 0xaa},
-       {0x00, 0x42, 0xff, 0xaa},
-       {0x00, 0x45, 0x34, 0xaa},
-       {0x00, 0x55, 0xfe, 0xaa},
-       {0x00, 0x59, 0xd3, 0xaa},
-       {0x00, 0x5e, 0x04, 0xaa},
-       {0x00, 0x61, 0xb8, 0xaa},       /* sharpness */
-       {0x00, 0x62, 0x02, 0xaa},
-       {0x00, 0xa7, 0x31, 0xaa},
-       {0x00, 0xa9, 0x66, 0xaa},
-       {0x00, 0xb0, 0x00, 0xaa},
-       {0x00, 0xb1, 0x00, 0xaa},
-       {0x00, 0xb3, 0x11, 0xaa},
-       {0x00, 0xb6, 0x26, 0xaa},
-       {0x00, 0xb7, 0x20, 0xaa},
-       {0x00, 0xba, 0x04, 0xaa},
-       {0x00, 0x88, 0x42, 0xaa},
-       {0x00, 0x89, 0x9a, 0xaa},
-       {0x00, 0x8a, 0x88, 0xaa},
-       {0x00, 0x8b, 0x8e, 0xaa},
-       {0x00, 0x8c, 0x3e, 0xaa},
-       {0x00, 0x8d, 0x90, 0xaa},
-       {0x00, 0x8e, 0x87, 0xaa},
-       {0x00, 0x8f, 0x96, 0xaa},
-       {0x00, 0x90, 0x3d, 0xaa},
-       {0x00, 0x64, 0x00, 0xaa},
-       {0x00, 0x65, 0x10, 0xaa},
-       {0x00, 0x66, 0x20, 0xaa},
-       {0x00, 0x67, 0x2b, 0xaa},
-       {0x00, 0x68, 0x36, 0xaa},
-       {0x00, 0x69, 0x49, 0xaa},
-       {0x00, 0x6a, 0x5a, 0xaa},
-       {0x00, 0x6b, 0x7f, 0xaa},
-       {0x00, 0x6c, 0x9b, 0xaa},
-       {0x00, 0x6d, 0xba, 0xaa},
-       {0x00, 0x6e, 0xd4, 0xaa},
-       {0x00, 0x6f, 0xea, 0xaa},
-       {0x00, 0x70, 0x00, 0xaa},
-       {0x00, 0x71, 0x10, 0xaa},
-       {0x00, 0x72, 0x20, 0xaa},
-       {0x00, 0x73, 0x2b, 0xaa},
-       {0x00, 0x74, 0x36, 0xaa},
-       {0x00, 0x75, 0x49, 0xaa},
-       {0x00, 0x76, 0x5a, 0xaa},
-       {0x00, 0x77, 0x7f, 0xaa},
-       {0x00, 0x78, 0x9b, 0xaa},
-       {0x00, 0x79, 0xba, 0xaa},
-       {0x00, 0x7a, 0xd4, 0xaa},
-       {0x00, 0x7b, 0xea, 0xaa},
-       {0x00, 0x7c, 0x00, 0xaa},
-       {0x00, 0x7d, 0x10, 0xaa},
-       {0x00, 0x7e, 0x20, 0xaa},
-       {0x00, 0x7f, 0x2b, 0xaa},
-       {0x00, 0x80, 0x36, 0xaa},
-       {0x00, 0x81, 0x49, 0xaa},
-       {0x00, 0x82, 0x5a, 0xaa},
-       {0x00, 0x83, 0x7f, 0xaa},
-       {0x00, 0x84, 0x9b, 0xaa},
-       {0x00, 0x85, 0xba, 0xaa},
-       {0x00, 0x86, 0xd4, 0xaa},
-       {0x00, 0x87, 0xea, 0xaa},
-       {0x00, 0x57, 0x2a, 0xaa},
-       {0x00, 0x03, 0x01, 0xaa},
-       {0x00, 0x04, 0x10, 0xaa},
-       {0x00, 0x05, 0x10, 0xaa},
-       {0x00, 0x06, 0x10, 0xaa},
-       {0x00, 0x07, 0x10, 0xaa},
-       {0x00, 0x08, 0x13, 0xaa},
-       {0x00, 0x0a, 0x00, 0xaa},
-       {0x00, 0x0b, 0x10, 0xaa},
-       {0x00, 0x0c, 0x20, 0xaa},
-       {0x00, 0x0d, 0x18, 0xaa},
-       {0x00, 0x22, 0x01, 0xaa},
-       {0x00, 0x23, 0x60, 0xaa},
-       {0x00, 0x25, 0x08, 0xaa},
-       {0x00, 0x26, 0x82, 0xaa},
-       {0x00, 0x2e, 0x0f, 0xaa},
-       {0x00, 0x2f, 0x1e, 0xaa},
-       {0x00, 0x30, 0x2d, 0xaa},
-       {0x00, 0x31, 0x3c, 0xaa},
-       {0x00, 0x32, 0x4b, 0xaa},
-       {0x00, 0x33, 0x5a, 0xaa},
-       {0x00, 0x34, 0x69, 0xaa},
-       {0x00, 0x35, 0x78, 0xaa},
-       {0x00, 0x36, 0x87, 0xaa},
-       {0x00, 0x37, 0x96, 0xaa},
-       {0x00, 0x38, 0xa5, 0xaa},
-       {0x00, 0x39, 0xb4, 0xaa},
-       {0x00, 0x3a, 0xc3, 0xaa},
-       {0x00, 0x3b, 0xd2, 0xaa},
-       {0x00, 0x3c, 0xe1, 0xaa},
-       {0x00, 0x3e, 0xff, 0xaa},
-       {0x00, 0x3f, 0xff, 0xaa},
-       {0x00, 0x40, 0xff, 0xaa},
-       {0x00, 0x41, 0xff, 0xaa},
-       {0x00, 0x42, 0xff, 0xaa},
-       {0x00, 0x43, 0xff, 0xaa},
-       {0x00, 0x03, 0x00, 0xaa},
-       {0x00, 0x03, 0x00, 0xaa},
-       {0x00, 0x20, 0xc4, 0xaa},
-       {0x00, 0x13, 0x03, 0xaa},
-       {0x00, 0x3c, 0x50, 0xaa},
-       {0x00, 0x61, 0x6a, 0xaa},       /* sharpness? */
-       {0x00, 0x51, 0x5b, 0xaa},
-       {0x00, 0x52, 0x91, 0xaa},
-       {0x00, 0x53, 0x4c, 0xaa},
-       {0x00, 0x54, 0x50, 0xaa},
-       {0x00, 0x56, 0x02, 0xaa},
-       {0xb6, 0x00, 0x00, 0xcc},
-       {0xb6, 0x03, 0x03, 0xcc},
-       {0xb6, 0x02, 0x20, 0xcc},
-       {0xb6, 0x05, 0x02, 0xcc},
-       {0xb6, 0x04, 0x58, 0xcc},
-       {0xb6, 0x12, 0xf8, 0xcc},
-       {0xb6, 0x13, 0x21, 0xcc},
-       {0xb6, 0x18, 0x03, 0xcc},
-       {0xb6, 0x17, 0xa9, 0xcc},
-       {0xb6, 0x16, 0x80, 0xcc},
-       {0xb6, 0x22, 0x12, 0xcc},
-       {0xb6, 0x23, 0x0b, 0xcc},
-       {0xbf, 0xc0, 0x39, 0xcc},
-       {0xbf, 0xc1, 0x04, 0xcc},
-       {0xbf, 0xcc, 0x00, 0xcc},
-       {0xb8, 0x06, 0x20, 0xcc},
-       {0xb8, 0x07, 0x03, 0xcc},
-       {0xb8, 0x08, 0x58, 0xcc},
-       {0xb8, 0x09, 0x02, 0xcc},
-       {0xb3, 0x01, 0x41, 0xcc},
-       {0x00, 0x03, 0x00, 0xaa},
-       {0x00, 0xd9, 0x0f, 0xaa},
-       {0x00, 0xda, 0xaa, 0xaa},
-       {0x00, 0xd9, 0x10, 0xaa},
-       {0x00, 0xda, 0xaa, 0xaa},
-       {0x00, 0xd9, 0x11, 0xaa},
-       {0x00, 0xda, 0x00, 0xaa},
-       {0x00, 0xd9, 0x12, 0xaa},
-       {0x00, 0xda, 0xff, 0xaa},
-       {0x00, 0xd9, 0x13, 0xaa},
-       {0x00, 0xda, 0xff, 0xaa},
-       {0x00, 0xe8, 0x11, 0xaa},
-       {0x00, 0xe9, 0x12, 0xaa},
-       {0x00, 0xea, 0x5c, 0xaa},
-       {0x00, 0xeb, 0xff, 0xaa},
-       {0x00, 0xd8, 0x80, 0xaa},
-       {0x00, 0xe6, 0x02, 0xaa},
-       {0x00, 0xd6, 0x40, 0xaa},
-       {0x00, 0xe3, 0x05, 0xaa},
-       {0x00, 0xe0, 0x40, 0xaa},
-       {0x00, 0xde, 0x03, 0xaa},
-       {0x00, 0xdf, 0x03, 0xaa},
-       {0x00, 0xdb, 0x02, 0xaa},
-       {0x00, 0xdc, 0x00, 0xaa},
-       {0x00, 0xdd, 0x03, 0xaa},
-       {0x00, 0xe1, 0x08, 0xaa},
-       {0x00, 0xe2, 0x01, 0xaa},
-       {0x00, 0xd6, 0x40, 0xaa},
-       {0x00, 0xe4, 0x40, 0xaa},
-       {0x00, 0xa8, 0x8f, 0xaa},
-       {0x00, 0xb4, 0x16, 0xaa},
-       {0xb0, 0x02, 0x06, 0xcc},
-       {0xb0, 0x18, 0x06, 0xcc},
-       {0xb0, 0x19, 0x06, 0xcc},
-       {0xb3, 0x5d, 0x18, 0xcc},
-       {0xb3, 0x05, 0x00, 0xcc},
-       {0xb3, 0x06, 0x00, 0xcc},
-       {0x00, 0xb4, 0x0e, 0xaa},
-       {0x00, 0xb5, 0x49, 0xaa},
-       {0x00, 0xb6, 0x1c, 0xaa},
-       {0x00, 0xb7, 0x96, 0xaa},
-/* end of usbvm326.inf - start of ms-win trace */
-       {0xb6, 0x12, 0xf8, 0xcc},
-       {0xb6, 0x13, 0x3d, 0xcc},
-/*read b306*/
-       {0x00, 0x03, 0x00, 0xaa},
-       {0x00, 0x1a, 0x09, 0xaa},
-       {0x00, 0x1b, 0x8a, 0xaa},
-/*read b827*/
-       {0xb8, 0x27, 0x00, 0xcc},
-       {0xb8, 0x26, 0x60, 0xcc},
-       {0xb8, 0x26, 0x60, 0xcc},
-/*gamma - to do?*/
-       {0x00, 0x03, 0x00, 0xaa},
-       {0x00, 0xae, 0x84, 0xaa},
-/*gamma again*/
-       {0x00, 0x03, 0x00, 0xaa},
-       {0x00, 0x96, 0xa0, 0xaa},
-/*matrix*/
-       {0x00, 0x03, 0x00, 0xaa},
-       {0x00, 0x91, 0x35, 0xaa},
-       {0x00, 0x92, 0x22, 0xaa},
-/*gamma*/
-       {0x00, 0x03, 0x00, 0xaa},
-       {0x00, 0x95, 0x85, 0xaa},
-/*matrix*/
-       {0x00, 0x03, 0x00, 0xaa},
-       {0x00, 0x4d, 0x20, 0xaa},
-       {0xb8, 0x22, 0x40, 0xcc},
-       {0xb8, 0x23, 0x40, 0xcc},
-       {0xb8, 0x24, 0x40, 0xcc},
-       {0xb8, 0x81, 0x09, 0xcc},
-       {0x00, 0x00, 0x64, 0xdd},
-       {0x00, 0x03, 0x01, 0xaa},
-/*read 46*/
-       {0x00, 0x46, 0x3c, 0xaa},
-       {0x00, 0x03, 0x00, 0xaa},
-       {0x00, 0x16, 0x40, 0xaa},
-       {0x00, 0x17, 0x40, 0xaa},
-       {0x00, 0x18, 0x40, 0xaa},
-       {0x00, 0x19, 0x41, 0xaa},
-       {0x00, 0x03, 0x01, 0xaa},
-       {0x00, 0x46, 0x3c, 0xaa},
-       {0x00, 0x00, 0x18, 0xdd},
-/*read bfff*/
-       {0x00, 0x03, 0x00, 0xaa},
-       {0x00, 0xb4, 0x1c, 0xaa},
-       {0x00, 0xb5, 0x92, 0xaa},
-       {0x00, 0xb6, 0x39, 0xaa},
-       {0x00, 0xb7, 0x24, 0xaa},
-/*write 89 0400 1415*/
-       {}
-};
-
-static const u8 poxxxx_init_common[][4] = {
-       {0xb3, 0x00, 0x04, 0xcc},
-       {0x00, 0x00, 0x10, 0xdd},
-       {0xb3, 0x00, 0x64, 0xcc},
-       {0x00, 0x00, 0x10, 0xdd},
-       {0xb3, 0x00, 0x65, 0xcc},
-       {0x00, 0x00, 0x10, 0xdd},
-       {0xb3, 0x00, 0x67, 0xcc},
-       {0xb0, 0x03, 0x09, 0xcc},
-       {0xb3, 0x05, 0x00, 0xcc},
-       {0xb3, 0x06, 0x00, 0xcc},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {0xb3, 0x08, 0x01, 0xcc},
-       {0xb3, 0x09, 0x0c, 0xcc},
-       {0xb3, 0x34, 0x01, 0xcc},
-       {0xb3, 0x35, 0xf6, 0xcc},       /* i2c add: 76 */
-       {0xb3, 0x02, 0xb0, 0xcc},
-       {0xb3, 0x03, 0x18, 0xcc},
-       {0xb3, 0x04, 0x15, 0xcc},
-       {0xb3, 0x20, 0x00, 0xcc},
-       {0xb3, 0x21, 0x00, 0xcc},
-       {0xb3, 0x22, 0x04, 0xcc},       /* sensor height = 1024 */
-       {0xb3, 0x23, 0x00, 0xcc},
-       {0xb3, 0x14, 0x00, 0xcc},
-       {0xb3, 0x15, 0x00, 0xcc},
-       {0xb3, 0x16, 0x04, 0xcc},       /* sensor width = 1280 */
-       {0xb3, 0x17, 0xff, 0xcc},
-       {0xb3, 0x2c, 0x03, 0xcc},
-       {0xb3, 0x2d, 0x56, 0xcc},
-       {0xb3, 0x2e, 0x02, 0xcc},
-       {0xb3, 0x2f, 0x0a, 0xcc},
-       {0xb3, 0x40, 0x00, 0xcc},
-       {0xb3, 0x41, 0x34, 0xcc},
-       {0xb3, 0x42, 0x01, 0xcc},
-       {0xb3, 0x43, 0xe0, 0xcc},
-       {0xbc, 0x00, 0x71, 0xcc},
-       {0xbc, 0x01, 0x01, 0xcc},
-       {0xb3, 0x01, 0x41, 0xcc},
-       {0xb3, 0x4d, 0x00, 0xcc},
-       {0x00, 0x0b, 0x2a, 0xaa},
-       {0x00, 0x0e, 0x03, 0xaa},
-       {0x00, 0x0f, 0xea, 0xaa},
-       {0x00, 0x12, 0x08, 0xaa},
-       {0x00, 0x1e, 0x06, 0xaa},
-       {0x00, 0x21, 0x00, 0xaa},
-       {0x00, 0x31, 0x1f, 0xaa},
-       {0x00, 0x33, 0x38, 0xaa},
-       {0x00, 0x36, 0xc0, 0xaa},
-       {0x00, 0x37, 0xc8, 0xaa},
-       {0x00, 0x3b, 0x36, 0xaa},
-       {0x00, 0x4b, 0xfe, 0xaa},
-       {0x00, 0x4d, 0x2e, 0xaa},
-       {0x00, 0x51, 0x1c, 0xaa},
-       {0x00, 0x52, 0x01, 0xaa},
-       {0x00, 0x55, 0x0a, 0xaa},
-       {0x00, 0x56, 0x0a, 0xaa},
-       {0x00, 0x57, 0x07, 0xaa},
-       {0x00, 0x58, 0x07, 0xaa},
-       {0x00, 0x59, 0x04, 0xaa},
-       {0x00, 0x70, 0x68, 0xaa},
-       {0x00, 0x71, 0x04, 0xaa},
-       {0x00, 0x72, 0x10, 0xaa},
-       {0x00, 0x80, 0x71, 0xaa},
-       {0x00, 0x81, 0x08, 0xaa},
-       {0x00, 0x82, 0x00, 0xaa},
-       {0x00, 0x83, 0x55, 0xaa},
-       {0x00, 0x84, 0x06, 0xaa},
-       {0x00, 0x85, 0x06, 0xaa},
-       {0x00, 0x8b, 0x25, 0xaa},
-       {0x00, 0x8c, 0x00, 0xaa},
-       {0x00, 0x8d, 0x86, 0xaa},
-       {0x00, 0x8e, 0x82, 0xaa},
-       {0x00, 0x8f, 0x2d, 0xaa},
-       {0x00, 0x90, 0x8b, 0xaa},
-       {0x00, 0x91, 0x81, 0xaa},
-       {0x00, 0x92, 0x81, 0xaa},
-       {0x00, 0x93, 0x23, 0xaa},
-       {0x00, 0xa3, 0x2a, 0xaa},
-       {0x00, 0xa4, 0x03, 0xaa},
-       {0x00, 0xa5, 0xea, 0xaa},
-       {0x00, 0xb0, 0x68, 0xaa},
-       {0x00, 0xbc, 0x04, 0xaa},
-       {0x00, 0xbe, 0x3b, 0xaa},
-       {0x00, 0x4e, 0x40, 0xaa},
-       {0x00, 0x06, 0x04, 0xaa},
-       {0x00, 0x07, 0x03, 0xaa},
-       {0x00, 0xcd, 0x18, 0xaa},
-       {0x00, 0x28, 0x03, 0xaa},
-       {0x00, 0x29, 0xef, 0xaa},
-/* reinit on alt 2 (qvga) or alt7 (vga) */
-       {0xb3, 0x05, 0x00, 0xcc},
-       {0xb3, 0x06, 0x00, 0xcc},
-       {0xb8, 0x00, 0x01, 0xcc},
-
-       {0x00, 0x1d, 0x85, 0xaa},
-       {0x00, 0x1e, 0xc6, 0xaa},
-       {0x00, 0x00, 0x40, 0xdd},
-       {0x00, 0x1d, 0x05, 0xaa},
-       {}
-};
-static const u8 poxxxx_gamma[][4] = {
-       {0x00, 0xd6, 0x22, 0xaa},       /* gamma 0 */
-       {0x00, 0x73, 0x00, 0xaa},
-       {0x00, 0x74, 0x0a, 0xaa},
-       {0x00, 0x75, 0x16, 0xaa},
-       {0x00, 0x76, 0x25, 0xaa},
-       {0x00, 0x77, 0x34, 0xaa},
-       {0x00, 0x78, 0x49, 0xaa},
-       {0x00, 0x79, 0x5a, 0xaa},
-       {0x00, 0x7a, 0x7f, 0xaa},
-       {0x00, 0x7b, 0x9b, 0xaa},
-       {0x00, 0x7c, 0xba, 0xaa},
-       {0x00, 0x7d, 0xd4, 0xaa},
-       {0x00, 0x7e, 0xea, 0xaa},
-
-       {0x00, 0xd6, 0x62, 0xaa},       /* gamma 1 */
-       {0x00, 0x73, 0x00, 0xaa},
-       {0x00, 0x74, 0x0a, 0xaa},
-       {0x00, 0x75, 0x16, 0xaa},
-       {0x00, 0x76, 0x25, 0xaa},
-       {0x00, 0x77, 0x34, 0xaa},
-       {0x00, 0x78, 0x49, 0xaa},
-       {0x00, 0x79, 0x5a, 0xaa},
-       {0x00, 0x7a, 0x7f, 0xaa},
-       {0x00, 0x7b, 0x9b, 0xaa},
-       {0x00, 0x7c, 0xba, 0xaa},
-       {0x00, 0x7d, 0xd4, 0xaa},
-       {0x00, 0x7e, 0xea, 0xaa},
-
-       {0x00, 0xd6, 0xa2, 0xaa},       /* gamma 2 */
-       {0x00, 0x73, 0x00, 0xaa},
-       {0x00, 0x74, 0x0a, 0xaa},
-       {0x00, 0x75, 0x16, 0xaa},
-       {0x00, 0x76, 0x25, 0xaa},
-       {0x00, 0x77, 0x34, 0xaa},
-       {0x00, 0x78, 0x49, 0xaa},
-       {0x00, 0x79, 0x5a, 0xaa},
-       {0x00, 0x7a, 0x7f, 0xaa},
-       {0x00, 0x7b, 0x9b, 0xaa},
-       {0x00, 0x7c, 0xba, 0xaa},
-       {0x00, 0x7d, 0xd4, 0xaa},
-       {0x00, 0x7e, 0xea, 0xaa},
-       {}
-};
-static const u8 poxxxx_init_start_3[][4] = {
-       {0x00, 0xb8, 0x28, 0xaa},
-       {0x00, 0xb9, 0x1e, 0xaa},
-       {0x00, 0xb6, 0x14, 0xaa},
-       {0x00, 0xb7, 0x0f, 0xaa},
-       {0x00, 0x5c, 0x10, 0xaa},
-       {0x00, 0x5d, 0x18, 0xaa},
-       {0x00, 0x5e, 0x24, 0xaa},
-       {0x00, 0x5f, 0x24, 0xaa},
-       {0x00, 0x86, 0x1a, 0xaa},
-       {0x00, 0x60, 0x00, 0xaa},
-       {0x00, 0x61, 0x1b, 0xaa},
-       {0x00, 0x62, 0x30, 0xaa},
-       {0x00, 0x63, 0x40, 0xaa},
-       {0x00, 0x87, 0x1a, 0xaa},
-       {0x00, 0x64, 0x00, 0xaa},
-       {0x00, 0x65, 0x08, 0xaa},
-       {0x00, 0x66, 0x10, 0xaa},
-       {0x00, 0x67, 0x20, 0xaa},
-       {0x00, 0x88, 0x10, 0xaa},
-       {0x00, 0x68, 0x00, 0xaa},
-       {0x00, 0x69, 0x08, 0xaa},
-       {0x00, 0x6a, 0x0f, 0xaa},
-       {0x00, 0x6b, 0x0f, 0xaa},
-       {0x00, 0x89, 0x07, 0xaa},
-       {0x00, 0xd5, 0x4c, 0xaa},
-       {0x00, 0x0a, 0x00, 0xaa},
-       {0x00, 0x0b, 0x2a, 0xaa},
-       {0x00, 0x0e, 0x03, 0xaa},
-       {0x00, 0x0f, 0xea, 0xaa},
-       {0x00, 0xa2, 0x00, 0xaa},
-       {0x00, 0xa3, 0x2a, 0xaa},
-       {0x00, 0xa4, 0x03, 0xaa},
-       {0x00, 0xa5, 0xea, 0xaa},
-       {}
-};
-static const u8 poxxxx_initVGA[][4] = {
-       {0x00, 0x20, 0x11, 0xaa},
-       {0x00, 0x33, 0x38, 0xaa},
-       {0x00, 0xbb, 0x0d, 0xaa},
-       {0xb3, 0x22, 0x01, 0xcc},       /* change to 640x480 */
-       {0xb3, 0x23, 0xe0, 0xcc},
-       {0xb3, 0x16, 0x02, 0xcc},
-       {0xb3, 0x17, 0x7f, 0xcc},
-       {0xb3, 0x02, 0xb0, 0xcc},
-       {0xb3, 0x06, 0x00, 0xcc},
-       {0xb3, 0x5c, 0x01, 0xcc},
-       {0x00, 0x04, 0x06, 0xaa},
-       {0x00, 0x05, 0x3f, 0xaa},
-       {0x00, 0x04, 0x00, 0xdd},       /* delay 1s */
-       {}
-};
-static const u8 poxxxx_initQVGA[][4] = {
-       {0x00, 0x20, 0x33, 0xaa},
-       {0x00, 0x33, 0x38, 0xaa},
-       {0x00, 0xbb, 0x0d, 0xaa},
-       {0xb3, 0x22, 0x00, 0xcc},       /* change to 320x240 */
-       {0xb3, 0x23, 0xf0, 0xcc},
-       {0xb3, 0x16, 0x01, 0xcc},
-       {0xb3, 0x17, 0x3f, 0xcc},
-       {0xb3, 0x02, 0xb0, 0xcc},
-       {0xb3, 0x06, 0x01, 0xcc},
-       {0xb3, 0x5c, 0x00, 0xcc},
-       {0x00, 0x04, 0x06, 0xaa},
-       {0x00, 0x05, 0x3f, 0xaa},
-       {0x00, 0x04, 0x00, 0xdd},       /* delay 1s */
-       {}
-};
-static const u8 poxxxx_init_end_1[][4] = {
-       {0x00, 0x47, 0x25, 0xaa},
-       {0x00, 0x48, 0x80, 0xaa},
-       {0x00, 0x49, 0x1f, 0xaa},
-       {0x00, 0x4a, 0x40, 0xaa},
-       {0x00, 0x44, 0x40, 0xaa},
-       {0x00, 0xab, 0x4a, 0xaa},
-       {0x00, 0xb1, 0x00, 0xaa},
-       {0x00, 0xb2, 0x04, 0xaa},
-       {0x00, 0xb3, 0x08, 0xaa},
-       {0x00, 0xb4, 0x0b, 0xaa},
-       {0x00, 0xb5, 0x0d, 0xaa},
-       {}
-};
-static const u8 poxxxx_init_end_2[][4] = {
-       {0x00, 0x1d, 0x85, 0xaa},
-       {0x00, 0x1e, 0x06, 0xaa},
-       {0x00, 0x1d, 0x05, 0xaa},
-       {}
-};
-
-struct sensor_info {
-       s8 sensorId;
-       u8 I2cAdd;
-       u8 IdAdd;
-       u16 VpId;
-       u8 m1;
-       u8 m2;
-       u8 op;
-};
-
-/* probe values */
-static const struct sensor_info vc0321_probe_data[] = {
-/*      sensorId,         I2cAdd,      IdAdd,  VpId,  m1,    m2,  op */
-/* 0 OV9640 */
-       {-1,                0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
-/* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */
-       {-1,                0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01},
-/* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/
-       {-1,                0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01},
-/* 3 MI1310 */
-       {-1,                0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01},
-/* 4 MI360 - tested in vc032x_probe_sensor */
-/*     {SENSOR_MI0360,     0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */
-/* 5 7131R */
-       {SENSOR_HV7131R,    0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
-/* 6 OV7649 */
-       {-1,                0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05},
-/* 7 PAS302BCW */
-       {-1,                0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05},
-/* 8 OV7660 */
-       {SENSOR_OV7660,     0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05},
-/* 9 PO3130NC - (tested in vc032x_probe_sensor) */
-/*     {SENSOR_PO3130NC,   0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */
-/* 10 PO1030KC */
-       {-1,                0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
-/* 11 MI1310_SOC */
-       {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01},
-/* 12 OV9650 */
-       {-1,                0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
-/* 13 S5K532 */
-       {-1,                0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01},
-/* 14 MI360_SOC - ??? */
-/* 15 PO1200N */
-       {SENSOR_PO1200,     0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01},
-/* 16 PO3030K */
-       {-1,                0x80 | 0x18, 0x00, 0x0000, 0x24, 0x25, 0x01},
-/* 17 PO2030 */
-       {-1,                0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
-/* ?? */
-       {-1,                0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01},
-       {SENSOR_MI1320,     0x80 | 0x48, 0x00, 0x148c, 0x64, 0x65, 0x01},
-};
-static const struct sensor_info vc0323_probe_data[] = {
-/*      sensorId,         I2cAdd,      IdAdd,  VpId,  m1,    m2,  op */
-/* 0 OV9640 */
-       {-1,                0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
-/* 1 ICM108T (may respond on IdAdd == 0x83 - tested in vc032x_probe_sensor) */
-       {-1,                0x80 | 0x20, 0x82, 0x0000, 0x24, 0x25, 0x01},
-/* 2 PO2130 (may detect PO3130NC - tested in vc032x_probe_sensor)*/
-       {-1,                0x80 | 0x76, 0x00, 0x0000, 0x24, 0x25, 0x01},
-/* 3 MI1310 */
-       {-1,                0x80 | 0x5d, 0x00, 0x0000, 0x24, 0x25, 0x01},
-/* 4 MI360 - tested in vc032x_probe_sensor */
-/*     {SENSOR_MI0360,     0x80 | 0x5d, 0x00, 0x8243, 0x24, 0x25, 0x01}, */
-/* 5 7131R */
-       {SENSOR_HV7131R,    0x80 | 0x11, 0x00, 0x0209, 0x24, 0x25, 0x01},
-/* 6 OV7649 */
-       {-1,                0x80 | 0x21, 0x0a, 0x0000, 0x21, 0x20, 0x05},
-/* 7 PAS302BCW */
-       {-1,                0x80 | 0x40, 0x00, 0x0000, 0x20, 0x22, 0x05},
-/* 8 OV7660 */
-       {SENSOR_OV7660,     0x80 | 0x21, 0x0a, 0x7660, 0x26, 0x26, 0x05},
-/* 9 PO3130NC - (tested in vc032x_probe_sensor) */
-/*     {SENSOR_PO3130NC,   0x80 | 0x76, 0x00, 0x3130, 0x24, 0x25, 0x01}, */
-/* 10 PO1030KC */
-       {-1,                0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
-/* 11 MI1310_SOC */
-       {SENSOR_MI1310_SOC, 0x80 | 0x5d, 0x00, 0x143a, 0x24, 0x25, 0x01},
-/* 12 OV9650 */
-       {-1,                0x80 | 0x30, 0x0a, 0x0000, 0x25, 0x24, 0x05},
-/* 13 S5K532 */
-       {-1,                0x80 | 0x11, 0x39, 0x0000, 0x24, 0x25, 0x01},
-/* 14 MI360_SOC - ??? */
-/* 15 PO1200N */
-       {SENSOR_PO1200,     0x80 | 0x5c, 0x00, 0x1200, 0x67, 0x67, 0x01},
-/* 16 ?? */
-       {-1,                0x80 | 0x2d, 0x00, 0x0000, 0x65, 0x67, 0x01},
-/* 17 PO2030 */
-       {-1,                0x80 | 0x6e, 0x00, 0x0000, 0x24, 0x25, 0x01},
-/* ?? */
-       {-1,                0x80 | 0x56, 0x01, 0x0000, 0x64, 0x67, 0x01},
-       {SENSOR_MI1320_SOC, 0x80 | 0x48, 0x00, 0x148c, 0x64, 0x67, 0x01},
-/*fixme: not in the ms-win probe - may be found before? */
-       {SENSOR_OV7670,     0x80 | 0x21, 0x0a, 0x7673, 0x66, 0x67, 0x05},
-};
-
-/* read 'len' bytes in gspca_dev->usb_buf */
-static void reg_r_i(struct gspca_dev *gspca_dev,
-                 u16 req,
-                 u16 index,
-                 u16 len)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       req,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       1,                      /* value */
-                       index, gspca_dev->usb_buf, len,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_r err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-static void reg_r(struct gspca_dev *gspca_dev,
-                 u16 req,
-                 u16 index,
-                 u16 len)
-{
-       reg_r_i(gspca_dev, req, index, len);
-#ifdef GSPCA_DEBUG
-       if (gspca_dev->usb_err < 0)
-               return;
-       if (len == 1)
-               PDEBUG(D_USBI, "GET %02x 0001 %04x %02x", req, index,
-                               gspca_dev->usb_buf[0]);
-       else
-               PDEBUG(D_USBI, "GET %02x 0001 %04x %*ph",
-                               req, index, 3, gspca_dev->usb_buf);
-#endif
-}
-
-static void reg_w_i(struct gspca_dev *gspca_dev,
-                           u16 req,
-                           u16 value,
-                           u16 index)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       req,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index, NULL, 0,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_w err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-static void reg_w(struct gspca_dev *gspca_dev,
-                           u16 req,
-                           u16 value,
-                           u16 index)
-{
-#ifdef GSPCA_DEBUG
-       if (gspca_dev->usb_err < 0)
-               return;
-       PDEBUG(D_USBO, "SET %02x %04x %04x", req, value, index);
-#endif
-       reg_w_i(gspca_dev, req, value, index);
-}
-
-static u16 read_sensor_register(struct gspca_dev *gspca_dev,
-                               u16 address)
-{
-       u8 ldata, mdata, hdata;
-       int retry = 50;
-
-       reg_r(gspca_dev, 0xa1, 0xb33f, 1);
-       if (!(gspca_dev->usb_buf[0] & 0x02)) {
-               pr_err("I2c Bus Busy Wait %02x\n", gspca_dev->usb_buf[0]);
-               return 0;
-       }
-       reg_w(gspca_dev, 0xa0, address, 0xb33a);
-       reg_w(gspca_dev, 0xa0, 0x02, 0xb339);
-
-       do {
-               reg_r(gspca_dev, 0xa1, 0xb33b, 1);
-               if (gspca_dev->usb_buf[0] == 0x00)
-                       break;
-               msleep(40);
-       } while (--retry >= 0);
-
-       reg_r(gspca_dev, 0xa1, 0xb33e, 1);
-       ldata = gspca_dev->usb_buf[0];
-       reg_r(gspca_dev, 0xa1, 0xb33d, 1);
-       mdata = gspca_dev->usb_buf[0];
-       reg_r(gspca_dev, 0xa1, 0xb33c, 1);
-       hdata = gspca_dev->usb_buf[0];
-       if (hdata != 0 && mdata != 0 && ldata != 0)
-               PDEBUG(D_PROBE, "Read Sensor %02x%02x %02x",
-                       hdata, mdata, ldata);
-       reg_r(gspca_dev, 0xa1, 0xb334, 1);
-       if (gspca_dev->usb_buf[0] == 0x02)
-               return (hdata << 8) + mdata;
-       return hdata;
-}
-
-static int vc032x_probe_sensor(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i, n;
-       u16 value;
-       const struct sensor_info *ptsensor_info;
-
-/*fixme: should also check the other sensor (back mi1320_soc, front mc501cb)*/
-       if (sd->flags & FL_SAMSUNG) {
-               reg_w(gspca_dev, 0xa0, 0x01, 0xb301);
-               reg_w(gspca_dev, 0x89, 0xf0ff, 0xffff);
-                                               /* select the back sensor */
-       }
-
-       reg_r(gspca_dev, 0xa1, 0xbfcf, 1);
-       PDEBUG(D_PROBE, "vc032%d check sensor header %02x",
-               sd->bridge == BRIDGE_VC0321 ? 1 : 3, gspca_dev->usb_buf[0]);
-       if (sd->bridge == BRIDGE_VC0321) {
-               ptsensor_info = vc0321_probe_data;
-               n = ARRAY_SIZE(vc0321_probe_data);
-       } else {
-               ptsensor_info = vc0323_probe_data;
-               n = ARRAY_SIZE(vc0323_probe_data);
-       }
-       for (i = 0; i < n; i++) {
-               reg_w(gspca_dev, 0xa0, 0x02, 0xb334);
-               reg_w(gspca_dev, 0xa0, ptsensor_info->m1, 0xb300);
-               reg_w(gspca_dev, 0xa0, ptsensor_info->m2, 0xb300);
-               reg_w(gspca_dev, 0xa0, 0x01, 0xb308);
-               reg_w(gspca_dev, 0xa0, 0x0c, 0xb309);
-               reg_w(gspca_dev, 0xa0, ptsensor_info->I2cAdd, 0xb335);
-               reg_w(gspca_dev, 0xa0, ptsensor_info->op, 0xb301);
-               value = read_sensor_register(gspca_dev, ptsensor_info->IdAdd);
-               if (value == 0 && ptsensor_info->IdAdd == 0x82)
-                       value = read_sensor_register(gspca_dev, 0x83);
-               if (value != 0) {
-                       PDEBUG(D_ERR|D_PROBE, "Sensor ID %04x (%d)",
-                               value, i);
-                       if (value == ptsensor_info->VpId)
-                               return ptsensor_info->sensorId;
-
-                       switch (value) {
-                       case 0x3130:
-                               return SENSOR_PO3130NC;
-                       case 0x7673:
-                               return SENSOR_OV7670;
-                       case 0x8243:
-                               return SENSOR_MI0360;
-                       }
-               }
-               ptsensor_info++;
-       }
-       return -1;
-}
-
-static void i2c_write(struct gspca_dev *gspca_dev,
-                       u8 reg, const u8 *val,
-                       u8 size)                /* 1 or 2 */
-{
-       int retry;
-
-#ifdef GSPCA_DEBUG
-       if (gspca_dev->usb_err < 0)
-               return;
-       if (size == 1)
-               PDEBUG(D_USBO, "i2c_w %02x %02x", reg, *val);
-       else
-               PDEBUG(D_USBO, "i2c_w %02x %02x%02x", reg, *val, val[1]);
-#endif
-       reg_r_i(gspca_dev, 0xa1, 0xb33f, 1);
-/*fixme:should check if (!(gspca_dev->usb_buf[0] & 0x02)) error*/
-       reg_w_i(gspca_dev, 0xa0, size, 0xb334);
-       reg_w_i(gspca_dev, 0xa0, reg, 0xb33a);
-       reg_w_i(gspca_dev, 0xa0, val[0], 0xb336);
-       if (size > 1)
-               reg_w_i(gspca_dev, 0xa0, val[1], 0xb337);
-       reg_w_i(gspca_dev, 0xa0, 0x01, 0xb339);
-       retry = 4;
-       do {
-               reg_r_i(gspca_dev, 0xa1, 0xb33b, 1);
-               if (gspca_dev->usb_buf[0] == 0)
-                       break;
-               msleep(20);
-       } while (--retry > 0);
-       if (retry <= 0)
-               pr_err("i2c_write timeout\n");
-}
-
-static void put_tab_to_reg(struct gspca_dev *gspca_dev,
-                       const u8 *tab, u8 tabsize, u16 addr)
-{
-       int j;
-       u16 ad = addr;
-
-       for (j = 0; j < tabsize; j++)
-               reg_w(gspca_dev, 0xa0, tab[j], ad++);
-}
-
-static void usb_exchange(struct gspca_dev *gspca_dev,
-                       const u8 data[][4])
-{
-       int i = 0;
-
-       for (;;) {
-               switch (data[i][3]) {
-               default:
-                       return;
-               case 0xcc:                      /* normal write */
-                       reg_w(gspca_dev, 0xa0, data[i][2],
-                                       (data[i][0]) << 8 | data[i][1]);
-                       break;
-               case 0xaa:                      /* i2c op */
-                       i2c_write(gspca_dev, data[i][1], &data[i][2], 1);
-                       break;
-               case 0xbb:                      /* i2c op */
-                       i2c_write(gspca_dev, data[i][0], &data[i][1], 2);
-                       break;
-               case 0xdd:
-                       msleep(data[i][1] * 256 + data[i][2] + 10);
-                       break;
-               }
-               i++;
-       }
-       /*not reached*/
-}
-
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       sd->bridge = id->driver_info >> 8;
-       sd->flags = id->driver_info & 0xff;
-
-       if (id->idVendor == 0x046d &&
-           (id->idProduct == 0x0892 || id->idProduct == 0x0896))
-               sd->sensor = SENSOR_POxxxx;     /* no probe */
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-       int sensor;
-       /* number of packets per ISOC message */
-       static u8 npkt[NSENSORS] = {
-               [SENSOR_HV7131R] =      64,
-               [SENSOR_MI0360] =       32,
-               [SENSOR_MI1310_SOC] =   32,
-               [SENSOR_MI1320] =       64,
-               [SENSOR_MI1320_SOC] =   128,
-               [SENSOR_OV7660] =       32,
-               [SENSOR_OV7670] =       64,
-               [SENSOR_PO1200] =       128,
-               [SENSOR_PO3130NC] =     128,
-               [SENSOR_POxxxx] =       128,
-       };
-
-       if (sd->sensor != SENSOR_POxxxx)
-               sensor = vc032x_probe_sensor(gspca_dev);
-       else
-               sensor = sd->sensor;
-
-       switch (sensor) {
-       case -1:
-               pr_err("Unknown sensor...\n");
-               return -EINVAL;
-       case SENSOR_HV7131R:
-               PDEBUG(D_PROBE, "Find Sensor HV7131R");
-               break;
-       case SENSOR_MI0360:
-               PDEBUG(D_PROBE, "Find Sensor MI0360");
-               sd->bridge = BRIDGE_VC0323;
-               break;
-       case SENSOR_MI1310_SOC:
-               PDEBUG(D_PROBE, "Find Sensor MI1310_SOC");
-               break;
-       case SENSOR_MI1320:
-               PDEBUG(D_PROBE, "Find Sensor MI1320");
-               break;
-       case SENSOR_MI1320_SOC:
-               PDEBUG(D_PROBE, "Find Sensor MI1320_SOC");
-               break;
-       case SENSOR_OV7660:
-               PDEBUG(D_PROBE, "Find Sensor OV7660");
-               break;
-       case SENSOR_OV7670:
-               PDEBUG(D_PROBE, "Find Sensor OV7670");
-               break;
-       case SENSOR_PO1200:
-               PDEBUG(D_PROBE, "Find Sensor PO1200");
-               break;
-       case SENSOR_PO3130NC:
-               PDEBUG(D_PROBE, "Find Sensor PO3130NC");
-               break;
-       case SENSOR_POxxxx:
-               PDEBUG(D_PROBE, "Sensor POxxxx");
-               break;
-       }
-       sd->sensor = sensor;
-
-       cam = &gspca_dev->cam;
-       if (sd->bridge == BRIDGE_VC0321) {
-               cam->cam_mode = vc0321_mode;
-               cam->nmodes = ARRAY_SIZE(vc0321_mode);
-       } else {
-               switch (sensor) {
-               case SENSOR_PO1200:
-                       cam->cam_mode = svga_mode;
-                       cam->nmodes = ARRAY_SIZE(svga_mode);
-                       break;
-               case SENSOR_MI1310_SOC:
-                       cam->cam_mode = vc0323_mode;
-                       cam->nmodes = ARRAY_SIZE(vc0323_mode);
-                       break;
-               case SENSOR_MI1320_SOC:
-                       cam->cam_mode = bi_mode;
-                       cam->nmodes = ARRAY_SIZE(bi_mode);
-                       break;
-               case SENSOR_OV7670:
-                       cam->cam_mode = bi_mode;
-                       cam->nmodes = ARRAY_SIZE(bi_mode) - 1;
-                       break;
-               default:
-                       cam->cam_mode = vc0323_mode;
-                       cam->nmodes = ARRAY_SIZE(vc0323_mode) - 1;
-                       break;
-               }
-       }
-       cam->npkt = npkt[sd->sensor];
-
-       if (sd->sensor == SENSOR_OV7670)
-               sd->flags |= FL_HFLIP | FL_VFLIP;
-
-       if (sd->bridge == BRIDGE_VC0321) {
-               reg_r(gspca_dev, 0x8a, 0, 3);
-               reg_w(gspca_dev, 0x87, 0x00, 0x0f0f);
-               reg_r(gspca_dev, 0x8b, 0, 3);
-               reg_w(gspca_dev, 0x88, 0x00, 0x0202);
-               if (sd->sensor == SENSOR_POxxxx) {
-                       reg_r(gspca_dev, 0xa1, 0xb300, 1);
-                       if (gspca_dev->usb_buf[0] != 0) {
-                               reg_w(gspca_dev, 0xa0, 0x26, 0xb300);
-                               reg_w(gspca_dev, 0xa0, 0x04, 0xb300);
-                       }
-                       reg_w(gspca_dev, 0xa0, 0x00, 0xb300);
-               }
-       }
-       return gspca_dev->usb_err;
-}
-
-static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       u8 data;
-
-       data = val;
-       if (data >= 0x80)
-               data &= 0x7f;
-       else
-               data = 0xff ^ data;
-       i2c_write(gspca_dev, 0x98, &data, 1);
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev, u8 val)
-{
-       i2c_write(gspca_dev, 0x99, &val, 1);
-}
-
-static void setcolors(struct gspca_dev *gspca_dev, u8 val)
-{
-       u8 data;
-
-       data = val - (val >> 3) - 1;
-       i2c_write(gspca_dev, 0x94, &data, 1);
-       i2c_write(gspca_dev, 0x95, &val, 1);
-}
-
-static void sethvflip(struct gspca_dev *gspca_dev, bool hflip, bool vflip)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 data[2];
-
-       if (sd->flags & FL_HFLIP)
-               hflip = !hflip;
-       if (sd->flags & FL_VFLIP)
-               vflip = !vflip;
-       switch (sd->sensor) {
-       case SENSOR_MI1310_SOC:
-       case SENSOR_MI1320:
-       case SENSOR_MI1320_SOC:
-               data[0] = data[1] = 0;          /* select page 0 */
-               i2c_write(gspca_dev, 0xf0, data, 2);
-               data[0] = sd->sensor == SENSOR_MI1310_SOC ? 0x03 : 0x01;
-               data[1] = 0x02 * hflip
-                       | 0x01 * vflip;
-               i2c_write(gspca_dev, 0x20, data, 2);
-               break;
-       case SENSOR_OV7660:
-       case SENSOR_OV7670:
-               data[0] = sd->sensor == SENSOR_OV7660 ? 0x01 : 0x07;
-               data[0] |= OV7660_MVFP_MIRROR * hflip
-                       | OV7660_MVFP_VFLIP * vflip;
-               i2c_write(gspca_dev, OV7660_REG_MVFP, data, 1);
-               break;
-       case SENSOR_PO1200:
-               data[0] = 0;
-               i2c_write(gspca_dev, 0x03, data, 1);
-               data[0] = 0x80 * hflip
-                       | 0x40 * vflip
-                       | 0x06;
-               i2c_write(gspca_dev, 0x1e, data, 1);
-               break;
-       }
-}
-
-static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       static const u8 (*ov7660_freq_tb[3])[4] =
-               {ov7660_NoFliker, ov7660_50HZ, ov7660_60HZ};
-
-       if (sd->sensor != SENSOR_OV7660)
-               return;
-       usb_exchange(gspca_dev, ov7660_freq_tb[val]);
-}
-
-static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 data;
-
-       switch (sd->sensor) {
-       case SENSOR_PO1200:
-               data = 0;
-               i2c_write(gspca_dev, 0x03, &data, 1);
-               if (val < 0)
-                       data = 0x6a;
-               else
-                       data = 0xb5 + val * 3;
-               i2c_write(gspca_dev, 0x61, &data, 1);
-               break;
-       case SENSOR_POxxxx:
-               if (val < 0)
-                       data = 0x7e;    /* def = max */
-               else
-                       data = 0x60 + val * 0x0f;
-               i2c_write(gspca_dev, 0x59, &data, 1);
-               break;
-       }
-}
-static void setgain(struct gspca_dev *gspca_dev, u8 val)
-{
-       i2c_write(gspca_dev, 0x15, &val, 1);
-}
-
-static void setexposure(struct gspca_dev *gspca_dev, s32 val)
-{
-       u8 data;
-
-       data = val >> 8;
-       i2c_write(gspca_dev, 0x1a, &data, 1);
-       data = val;
-       i2c_write(gspca_dev, 0x1b, &data, 1);
-}
-
-static void setautogain(struct gspca_dev *gspca_dev, s32 val)
-{
-       static const u8 data[2] = {0x28, 0x3c};
-
-       i2c_write(gspca_dev, 0xd1, &data[val], 1);
-}
-
-static void setgamma(struct gspca_dev *gspca_dev)
-{
-/*fixme:to do */
-       usb_exchange(gspca_dev, poxxxx_gamma);
-}
-
-static void setbacklight(struct gspca_dev *gspca_dev, s32 val)
-{
-       u16 v;
-       u8 data;
-
-       data = (val << 4) | 0x0f;
-       i2c_write(gspca_dev, 0xaa, &data, 1);
-       v = 613 + 12 * val;
-       data = v >> 8;
-       i2c_write(gspca_dev, 0xc4, &data, 1);
-       data = v;
-       i2c_write(gspca_dev, 0xc5, &data, 1);
-       v = 1093 - 12 * val;
-       data = v >> 8;
-       i2c_write(gspca_dev, 0xc6, &data, 1);
-       data = v;
-       i2c_write(gspca_dev, 0xc7, &data, 1);
-       v = 342 + 9 * val;
-       data = v >> 8;
-       i2c_write(gspca_dev, 0xc8, &data, 1);
-       data = v;
-       i2c_write(gspca_dev, 0xc9, &data, 1);
-       v = 702 - 9 * val;
-       data = v >> 8;
-       i2c_write(gspca_dev, 0xca, &data, 1);
-       data = v;
-       i2c_write(gspca_dev, 0xcb, &data, 1);
-}
-
-static void setwb(struct gspca_dev *gspca_dev)
-{
-/*fixme:to do - valid when reg d1 = 0x1c - (reg16 + reg15 = 0xa3)*/
-       static const u8 data[2] = {0x00, 0x00};
-
-       i2c_write(gspca_dev, 0x16, &data[0], 1);
-       i2c_write(gspca_dev, 0x18, &data[1], 1);
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       const u8 (*init)[4];
-       const u8 *GammaT = NULL;
-       const u8 *MatrixT = NULL;
-       int mode;
-       static const u8 (*mi1320_soc_init[])[4] = {
-               mi1320_soc_InitSXGA,
-               mi1320_soc_InitVGA,
-               mi1320_soc_InitQVGA,
-       };
-
-/*fixme: back sensor only*/
-       if (sd->flags & FL_SAMSUNG) {
-               reg_w(gspca_dev, 0x89, 0xf0ff, 0xffff);
-               reg_w(gspca_dev, 0xa9, 0x8348, 0x000e);
-               reg_w(gspca_dev, 0xa9, 0x0000, 0x001a);
-       }
-
-       /* Assume start use the good resolution from gspca_dev->mode */
-       if (sd->bridge == BRIDGE_VC0321) {
-               reg_w(gspca_dev, 0xa0, 0xff, 0xbfec);
-               reg_w(gspca_dev, 0xa0, 0xff, 0xbfed);
-               reg_w(gspca_dev, 0xa0, 0xff, 0xbfee);
-               reg_w(gspca_dev, 0xa0, 0xff, 0xbfef);
-               sd->image_offset = 46;
-       } else {
-               if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].pixelformat
-                               == V4L2_PIX_FMT_JPEG)
-                       sd->image_offset = 0;
-               else
-                       sd->image_offset = 32;
-       }
-
-       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
-       switch (sd->sensor) {
-       case SENSOR_HV7131R:
-               GammaT = hv7131r_gamma;
-               MatrixT = hv7131r_matrix;
-               if (mode)
-                       init = hv7131r_initQVGA_data;   /* 320x240 */
-               else
-                       init = hv7131r_initVGA_data;    /* 640x480 */
-               break;
-       case SENSOR_OV7660:
-               GammaT = ov7660_gamma;
-               MatrixT = ov7660_matrix;
-               if (mode)
-                       init = ov7660_initQVGA_data;    /* 320x240 */
-               else
-                       init = ov7660_initVGA_data;     /* 640x480 */
-               break;
-       case SENSOR_MI0360:
-               GammaT = mi1320_gamma;
-               MatrixT = mi0360_matrix;
-               if (mode)
-                       init = mi0360_initQVGA_JPG;     /* 320x240 */
-               else
-                       init = mi0360_initVGA_JPG;      /* 640x480 */
-               break;
-       case SENSOR_MI1310_SOC:
-               GammaT = mi1320_gamma;
-               MatrixT = mi1320_matrix;
-               switch (mode) {
-               case 1:
-                       init = mi1310_socinitQVGA_JPG;  /* 320x240 */
-                       break;
-               case 0:
-                       init = mi1310_socinitVGA_JPG;   /* 640x480 */
-                       break;
-               default:
-                       init = mi1310_soc_InitSXGA_JPG; /* 1280x1024 */
-                       break;
-               }
-               break;
-       case SENSOR_MI1320:
-               GammaT = mi1320_gamma;
-               MatrixT = mi1320_matrix;
-               if (mode)
-                       init = mi1320_initQVGA_data;    /* 320x240 */
-               else
-                       init = mi1320_initVGA_data;     /* 640x480 */
-               break;
-       case SENSOR_MI1320_SOC:
-               GammaT = mi1320_gamma;
-               MatrixT = mi1320_matrix;
-               init = mi1320_soc_init[mode];
-               break;
-       case SENSOR_OV7670:
-               init = mode == 1 ? ov7670_InitVGA : ov7670_InitQVGA;
-               break;
-       case SENSOR_PO3130NC:
-               GammaT = po3130_gamma;
-               MatrixT = po3130_matrix;
-               if (mode)
-                       init = po3130_initQVGA_data;    /* 320x240 */
-               else
-                       init = po3130_initVGA_data;     /* 640x480 */
-               usb_exchange(gspca_dev, init);
-               init = po3130_rundata;
-               break;
-       case SENSOR_PO1200:
-               GammaT = po1200_gamma;
-               MatrixT = po1200_matrix;
-               init = po1200_initVGA_data;
-               break;
-       default:
-/*     case SENSOR_POxxxx: */
-               usb_exchange(gspca_dev, poxxxx_init_common);
-               setgamma(gspca_dev);
-               usb_exchange(gspca_dev, poxxxx_init_start_3);
-               if (mode)
-                       init = poxxxx_initQVGA;
-               else
-                       init = poxxxx_initVGA;
-               usb_exchange(gspca_dev, init);
-               reg_r(gspca_dev, 0x8c, 0x0000, 3);
-               reg_w(gspca_dev, 0xa0,
-                               gspca_dev->usb_buf[2] & 1 ? 0 : 1,
-                               0xb35c);
-               msleep(300);
-/*fixme: i2c read 04 and 05*/
-               init = poxxxx_init_end_1;
-               break;
-       }
-       usb_exchange(gspca_dev, init);
-       if (GammaT && MatrixT) {
-               put_tab_to_reg(gspca_dev, GammaT, 17, 0xb84a);
-               put_tab_to_reg(gspca_dev, GammaT, 17, 0xb85b);
-               put_tab_to_reg(gspca_dev, GammaT, 17, 0xb86c);
-               put_tab_to_reg(gspca_dev, MatrixT, 9, 0xb82c);
-
-               switch (sd->sensor) {
-               case SENSOR_PO1200:
-               case SENSOR_HV7131R:
-                       reg_w(gspca_dev, 0x89, 0x0400, 0x1415);
-                       break;
-               case SENSOR_MI1310_SOC:
-                       reg_w(gspca_dev, 0x89, 0x058c, 0x0000);
-                       break;
-               }
-               msleep(100);
-       }
-       switch (sd->sensor) {
-       case SENSOR_OV7670:
-               reg_w(gspca_dev, 0x87, 0xffff, 0xffff);
-               reg_w(gspca_dev, 0x88, 0xff00, 0xf0f1);
-               reg_w(gspca_dev, 0xa0, 0x0000, 0xbfff);
-               break;
-       case SENSOR_POxxxx:
-               usb_exchange(gspca_dev, poxxxx_init_end_2);
-               setwb(gspca_dev);
-               msleep(80);             /* led on */
-               reg_w(gspca_dev, 0x89, 0xffff, 0xfdff);
-               break;
-       }
-       return gspca_dev->usb_err;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->sensor) {
-       case SENSOR_MI1310_SOC:
-               reg_w(gspca_dev, 0x89, 0x058c, 0x00ff);
-               break;
-       case SENSOR_POxxxx:
-               return;
-       default:
-               if (!(sd->flags & FL_SAMSUNG))
-                       reg_w(gspca_dev, 0x89, 0xffff, 0xffff);
-               break;
-       }
-       reg_w(gspca_dev, 0xa0, 0x01, 0xb301);
-       reg_w(gspca_dev, 0xa0, 0x09, 0xb003);
-}
-
-/* called on streamoff with alt 0 and on disconnect */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (!gspca_dev->present)
-               return;
-/*fixme: is this useful?*/
-       if (sd->sensor == SENSOR_MI1310_SOC)
-               reg_w(gspca_dev, 0x89, 0x058c, 0x00ff);
-       else if (!(sd->flags & FL_SAMSUNG))
-               reg_w(gspca_dev, 0x89, 0xffff, 0xffff);
-
-       if (sd->sensor == SENSOR_POxxxx) {
-               reg_w(gspca_dev, 0xa0, 0x26, 0xb300);
-               reg_w(gspca_dev, 0xa0, 0x04, 0xb300);
-               reg_w(gspca_dev, 0xa0, 0x00, 0xb300);
-       }
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,                       /* isoc packet */
-                       int len)                        /* iso pkt length */
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (data[0] == 0xff && data[1] == 0xd8) {
-               PDEBUG(D_PACK,
-                       "vc032x header packet found len %d", len);
-               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-               data += sd->image_offset;
-               len -= sd->image_offset;
-               gspca_frame_add(gspca_dev, FIRST_PACKET, data, len);
-               return;
-       }
-
-       /* The vc0321 sends some additional data after sending the complete
-        * frame, we ignore this. */
-       if (sd->bridge == BRIDGE_VC0321) {
-               int size, l;
-
-               l = gspca_dev->image_len;
-               size = gspca_dev->frsz;
-               if (len > size - l)
-                       len = size - l;
-       }
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-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 && ctrl->id != V4L2_CID_POWER_LINE_FREQUENCY)
-               return 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               setbrightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               setcontrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               setcolors(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_HFLIP:
-               sethvflip(gspca_dev, sd->hflip->val, sd->vflip->val);
-               break;
-       case V4L2_CID_SHARPNESS:
-               setsharpness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               setautogain(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_GAIN:
-               setgain(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_EXPOSURE:
-               setexposure(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_BACKLIGHT_COMPENSATION:
-               setbacklight(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_POWER_LINE_FREQUENCY:
-               setlightfreq(gspca_dev, ctrl->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;
-       bool has_brightness = false;
-       bool has_contrast = false;
-       bool has_sat = false;
-       bool has_hvflip = false;
-       bool has_freq = false;
-       bool has_backlight = false;
-       bool has_exposure = false;
-       bool has_autogain = false;
-       bool has_gain = false;
-       bool has_sharpness = false;
-
-       switch (sd->sensor) {
-       case SENSOR_HV7131R:
-       case SENSOR_MI0360:
-       case SENSOR_PO3130NC:
-               break;
-       case SENSOR_MI1310_SOC:
-       case SENSOR_MI1320:
-       case SENSOR_MI1320_SOC:
-       case SENSOR_OV7660:
-               has_hvflip = true;
-               break;
-       case SENSOR_OV7670:
-               has_hvflip = has_freq = true;
-               break;
-       case SENSOR_PO1200:
-               has_hvflip = has_sharpness = true;
-               break;
-       case SENSOR_POxxxx:
-               has_brightness = has_contrast = has_sat = has_backlight =
-                       has_exposure = has_autogain = has_gain =
-                       has_sharpness = true;
-               break;
-       }
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 8);
-       if (has_brightness)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
-       if (has_contrast)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 255, 1, 127);
-       if (has_sat)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SATURATION, 1, 127, 1, 63);
-       if (has_hvflip) {
-               sd->hflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_HFLIP, 0, 1, 1, 0);
-               sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_VFLIP, 0, 1, 1, 0);
-       }
-       if (has_sharpness)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SHARPNESS, -1, 2, 1, -1);
-       if (has_freq)
-               v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
-                       V4L2_CID_POWER_LINE_FREQUENCY,
-                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
-                       V4L2_CID_POWER_LINE_FREQUENCY_50HZ);
-       if (has_autogain)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-       if (has_gain)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_GAIN, 0, 78, 1, 0);
-       if (has_exposure)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 0, 4095, 1, 450);
-       if (has_backlight)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BACKLIGHT_COMPENSATION, 0, 15, 1, 15);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-       if (sd->hflip)
-               v4l2_ctrl_cluster(2, &sd->hflip);
-       return 0;
-}
-
-/* sub-driver description */
-static const struct sd_desc sd_desc = {
-       .name = MODULE_NAME,
-       .init_controls = sd_init_controls,
-       .config = sd_config,
-       .init = sd_init,
-       .start = sd_start,
-       .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .pkt_scan = sd_pkt_scan,
-};
-
-/* -- module initialisation -- */
-#define BF(bridge, flags) \
-       .driver_info = (BRIDGE_ ## bridge << 8) \
-               | (flags)
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x041e, 0x405b), BF(VC0323, FL_VFLIP)},
-       {USB_DEVICE(0x046d, 0x0892), BF(VC0321, 0)},
-       {USB_DEVICE(0x046d, 0x0896), BF(VC0321, 0)},
-       {USB_DEVICE(0x046d, 0x0897), BF(VC0321, 0)},
-       {USB_DEVICE(0x0ac8, 0x0321), BF(VC0321, 0)},
-       {USB_DEVICE(0x0ac8, 0x0323), BF(VC0323, 0)},
-       {USB_DEVICE(0x0ac8, 0x0328), BF(VC0321, 0)},
-       {USB_DEVICE(0x0ac8, 0xc001), BF(VC0321, 0)},
-       {USB_DEVICE(0x0ac8, 0xc002), BF(VC0321, 0)},
-       {USB_DEVICE(0x0ac8, 0xc301), BF(VC0323, FL_SAMSUNG)},
-       {USB_DEVICE(0x15b8, 0x6001), BF(VC0323, 0)},
-       {USB_DEVICE(0x15b8, 0x6002), BF(VC0323, 0)},
-       {USB_DEVICE(0x17ef, 0x4802), BF(VC0323, 0)},
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/vicam.c b/drivers/media/video/gspca/vicam.c
deleted file mode 100644 (file)
index b1a64b9..0000000
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * gspca ViCam subdriver
- *
- * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>
- *
- * Based on the usbvideo vicam driver, which is:
- *
- * Copyright (c) 2002 Joe Burks (jburks@wavicle.org),
- *                    Christopher L Cheney (ccheney@cheney.cx),
- *                    Pavel Machek (pavel@ucw.cz),
- *                    John Tyner (jtyner@cs.ucr.edu),
- *                    Monroe Williams (monroe@pobox.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
- * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "vicam"
-#define HEADER_SIZE 64
-
-#include <linux/workqueue.h>
-#include <linux/slab.h>
-#include <linux/firmware.h>
-#include <linux/ihex.h>
-#include "gspca.h"
-
-#define VICAM_FIRMWARE "vicam/firmware.fw"
-
-MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
-MODULE_DESCRIPTION("GSPCA ViCam USB Camera Driver");
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(VICAM_FIRMWARE);
-
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-       struct work_struct work_struct;
-       struct workqueue_struct *work_thread;
-};
-
-/* The vicam sensor has a resolution of 512 x 244, with I believe square
-   pixels, but this is forced to a 4:3 ratio by optics. So it has
-   non square pixels :( */
-static struct v4l2_pix_format vicam_mode[] = {
-       { 256, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
-               .bytesperline = 256,
-               .sizeimage = 256 * 122,
-               .colorspace = V4L2_COLORSPACE_SRGB,},
-       /* 2 modes with somewhat more square pixels */
-       { 256, 200, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
-               .bytesperline = 256,
-               .sizeimage = 256 * 200,
-               .colorspace = V4L2_COLORSPACE_SRGB,},
-       { 256, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
-               .bytesperline = 256,
-               .sizeimage = 256 * 240,
-               .colorspace = V4L2_COLORSPACE_SRGB,},
-#if 0   /* This mode has extremely non square pixels, testing use only */
-       { 512, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
-               .bytesperline = 512,
-               .sizeimage = 512 * 122,
-               .colorspace = V4L2_COLORSPACE_SRGB,},
-#endif
-       { 512, 244, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
-               .bytesperline = 512,
-               .sizeimage = 512 * 244,
-               .colorspace = V4L2_COLORSPACE_SRGB,},
-};
-
-static int vicam_control_msg(struct gspca_dev *gspca_dev, u8 request,
-       u16 value, u16 index, u8 *data, u16 len)
-{
-       int ret;
-
-       ret = usb_control_msg(gspca_dev->dev,
-                             usb_sndctrlpipe(gspca_dev->dev, 0),
-                             request,
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             value, index, data, len, 1000);
-       if (ret < 0)
-               pr_err("control msg req %02X error %d\n", request, ret);
-
-       return ret;
-}
-
-static int vicam_set_camera_power(struct gspca_dev *gspca_dev, int state)
-{
-       int ret;
-
-       ret = vicam_control_msg(gspca_dev, 0x50, state, 0, NULL, 0);
-       if (ret < 0)
-               return ret;
-
-       if (state)
-               ret = vicam_control_msg(gspca_dev, 0x55, 1, 0, NULL, 0);
-
-       return ret;
-}
-
-/*
- *  request and read a block of data - see warning on vicam_command.
- */
-static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size)
-{
-       int ret, unscaled_height, act_len = 0;
-       u8 *req_data = gspca_dev->usb_buf;
-       s32 expo = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
-       s32 gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
-
-       memset(req_data, 0, 16);
-       req_data[0] = gain;
-       if (gspca_dev->width == 256)
-               req_data[1] |= 0x01; /* low nibble x-scale */
-       if (gspca_dev->height <= 122) {
-               req_data[1] |= 0x10; /* high nibble y-scale */
-               unscaled_height = gspca_dev->height * 2;
-       } else
-               unscaled_height = gspca_dev->height;
-       req_data[2] = 0x90; /* unknown, does not seem to do anything */
-       if (unscaled_height <= 200)
-               req_data[3] = 0x06; /* vend? */
-       else if (unscaled_height <= 242) /* Yes 242 not 240 */
-               req_data[3] = 0x07; /* vend? */
-       else /* Up to 244 lines with req_data[3] == 0x08 */
-               req_data[3] = 0x08; /* vend? */
-
-       if (expo < 256) {
-               /* Frame rate maxed out, use partial frame expo time */
-               req_data[4] = 255 - expo;
-               req_data[5] = 0x00;
-               req_data[6] = 0x00;
-               req_data[7] = 0x01;
-       } else {
-               /* Modify frame rate */
-               req_data[4] = 0x00;
-               req_data[5] = 0x00;
-               req_data[6] = expo & 0xFF;
-               req_data[7] = expo >> 8;
-       }
-       req_data[8] = ((244 - unscaled_height) / 2) & ~0x01; /* vstart */
-       /* bytes 9-15 do not seem to affect exposure or image quality */
-
-       mutex_lock(&gspca_dev->usb_lock);
-       ret = vicam_control_msg(gspca_dev, 0x51, 0x80, 0, req_data, 16);
-       mutex_unlock(&gspca_dev->usb_lock);
-       if (ret < 0)
-               return ret;
-
-       ret = usb_bulk_msg(gspca_dev->dev,
-                          usb_rcvbulkpipe(gspca_dev->dev, 0x81),
-                          data, size, &act_len, 10000);
-       /* successful, it returns 0, otherwise  negative */
-       if (ret < 0 || act_len != size) {
-               pr_err("bulk read fail (%d) len %d/%d\n",
-                      ret, act_len, size);
-               return -EIO;
-       }
-       return 0;
-}
-
-/* This function is called as a workqueue function and runs whenever the camera
- * is streaming data. Because it is a workqueue function it is allowed to sleep
- * so we can use synchronous USB calls. To avoid possible collisions with other
- * threads attempting to use the camera's USB interface we take the gspca
- * usb_lock when performing USB operations. In practice the only thing we need
- * to protect against is the usb_set_interface call that gspca makes during
- * stream_off as the camera doesn't provide any controls that the user could try
- * to change.
- */
-static void vicam_dostream(struct work_struct *work)
-{
-       struct sd *sd = container_of(work, struct sd, work_struct);
-       struct gspca_dev *gspca_dev = &sd->gspca_dev;
-       int ret, frame_sz;
-       u8 *buffer;
-
-       frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage +
-                  HEADER_SIZE;
-       buffer = kmalloc(frame_sz, GFP_KERNEL | GFP_DMA);
-       if (!buffer) {
-               pr_err("Couldn't allocate USB buffer\n");
-               goto exit;
-       }
-
-       while (gspca_dev->dev && gspca_dev->streaming) {
-#ifdef CONFIG_PM
-               if (gspca_dev->frozen)
-                       break;
-#endif
-               ret = vicam_read_frame(gspca_dev, buffer, frame_sz);
-               if (ret < 0)
-                       break;
-
-               /* Note the frame header contents seem to be completely
-                  constant, they do not change with either image, or
-                  settings. So we simply discard it. The frames have
-                  a very similar 64 byte footer, which we don't even
-                  bother reading from the cam */
-               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                               buffer + HEADER_SIZE,
-                               frame_sz - HEADER_SIZE);
-               gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-       }
-exit:
-       kfree(buffer);
-}
-
-/* This function is called at probe time just before sd_init */
-static int sd_config(struct gspca_dev *gspca_dev,
-               const struct usb_device_id *id)
-{
-       struct cam *cam = &gspca_dev->cam;
-       struct sd *sd = (struct sd *)gspca_dev;
-
-       /* We don't use the buffer gspca allocates so make it small. */
-       cam->bulk = 1;
-       cam->bulk_size = 64;
-       cam->cam_mode = vicam_mode;
-       cam->nmodes = ARRAY_SIZE(vicam_mode);
-
-       INIT_WORK(&sd->work_struct, vicam_dostream);
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       int ret;
-       const struct ihex_binrec *rec;
-       const struct firmware *uninitialized_var(fw);
-       u8 *firmware_buf;
-
-       ret = request_ihex_firmware(&fw, VICAM_FIRMWARE,
-                                   &gspca_dev->dev->dev);
-       if (ret) {
-               pr_err("Failed to load \"vicam/firmware.fw\": %d\n", ret);
-               return ret;
-       }
-
-       firmware_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-       if (!firmware_buf) {
-               ret = -ENOMEM;
-               goto exit;
-       }
-       for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) {
-               memcpy(firmware_buf, rec->data, be16_to_cpu(rec->len));
-               ret = vicam_control_msg(gspca_dev, 0xff, 0, 0, firmware_buf,
-                                       be16_to_cpu(rec->len));
-               if (ret < 0)
-                       break;
-       }
-
-       kfree(firmware_buf);
-exit:
-       release_firmware(fw);
-       return ret;
-}
-
-/* Set up for getting frames. */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *)gspca_dev;
-       int ret;
-
-       ret = vicam_set_camera_power(gspca_dev, 1);
-       if (ret < 0)
-               return ret;
-
-       /* Start the workqueue function to do the streaming */
-       sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
-       queue_work(sd->work_thread, &sd->work_struct);
-
-       return 0;
-}
-
-/* called on streamoff with alt==0 and on disconnect */
-/* the usb_lock is held at entry - restore on exit */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       struct sd *dev = (struct sd *)gspca_dev;
-
-       /* wait for the work queue to terminate */
-       mutex_unlock(&gspca_dev->usb_lock);
-       /* This waits for vicam_dostream to finish */
-       destroy_workqueue(dev->work_thread);
-       dev->work_thread = NULL;
-       mutex_lock(&gspca_dev->usb_lock);
-
-       if (gspca_dev->dev)
-               vicam_set_camera_power(gspca_dev, 0);
-}
-
-static int sd_init_controls(struct gspca_dev *gspca_dev)
-{
-       struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 2);
-       gspca_dev->exposure = v4l2_ctrl_new_std(hdl, NULL,
-                       V4L2_CID_EXPOSURE, 0, 2047, 1, 256);
-       gspca_dev->gain = v4l2_ctrl_new_std(hdl, NULL,
-                       V4L2_CID_GAIN, 0, 255, 1, 200);
-
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-       return 0;
-}
-
-/* Table of supported USB devices */
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x04c1, 0x009d)},
-       {USB_DEVICE(0x0602, 0x1001)},
-       {}
-};
-
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* 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,
-       .stop0  = sd_stop0,
-};
-
-/* -- device connect -- */
-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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c
deleted file mode 100644 (file)
index 9e3a909..0000000
+++ /dev/null
@@ -1,567 +0,0 @@
-/**
- *
- * GSPCA sub driver for W996[78]CF JPEG USB Dual Mode Camera Chip.
- *
- * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com>
- *
- * This module is adapted from the in kernel v4l1 w9968cf driver:
- *
- * Copyright (C) 2002-2004 by Luca Risolia <luca.risolia@studio.unibo.it>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-/* Note this is not a stand alone driver, it gets included in ov519.c, this
-   is a bit of a hack, but it needs the driver code for a lot of different
-   ov sensors which is already present in ov519.c (the old v4l1 driver used
-   the ovchipcam framework). When we have the time we really should move
-   the sensor drivers to v4l2 sub drivers, and properly split of this
-   driver from ov519.c */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define W9968CF_I2C_BUS_DELAY    4 /* delay in us for I2C bit r/w operations */
-
-#define Y_QUANTABLE (&sd->jpeg_hdr[JPEG_QT0_OFFSET])
-#define UV_QUANTABLE (&sd->jpeg_hdr[JPEG_QT1_OFFSET])
-
-static const struct v4l2_pix_format w9968cf_vga_mode[] = {
-       {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
-               .bytesperline = 160 * 2,
-               .sizeimage = 160 * 120 * 2,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-       {176, 144, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
-               .bytesperline = 176 * 2,
-               .sizeimage = 176 * 144 * 2,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320 * 2,
-               .sizeimage = 320 * 240 * 2,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 352 * 2,
-               .sizeimage = 352 * 288 * 2,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640 * 2,
-               .sizeimage = 640 * 480 * 2,
-               .colorspace = V4L2_COLORSPACE_JPEG},
-};
-
-static void reg_w(struct sd *sd, u16 index, u16 value);
-
-/*--------------------------------------------------------------------------
-  Write 64-bit data to the fast serial bus registers.
-  Return 0 on success, -1 otherwise.
-  --------------------------------------------------------------------------*/
-static void w9968cf_write_fsb(struct sd *sd, u16* data)
-{
-       struct usb_device *udev = sd->gspca_dev.dev;
-       u16 value;
-       int ret;
-
-       if (sd->gspca_dev.usb_err < 0)
-               return;
-
-       value = *data++;
-       memcpy(sd->gspca_dev.usb_buf, data, 6);
-
-       ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0,
-                             USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
-                             value, 0x06, sd->gspca_dev.usb_buf, 6, 500);
-       if (ret < 0) {
-               pr_err("Write FSB registers failed (%d)\n", ret);
-               sd->gspca_dev.usb_err = ret;
-       }
-}
-
-/*--------------------------------------------------------------------------
-  Write data to the serial bus control register.
-  Return 0 on success, a negative number otherwise.
-  --------------------------------------------------------------------------*/
-static void w9968cf_write_sb(struct sd *sd, u16 value)
-{
-       int ret;
-
-       if (sd->gspca_dev.usb_err < 0)
-               return;
-
-       /* We don't use reg_w here, as that would cause all writes when
-          bitbanging i2c to be logged, making the logs impossible to read */
-       ret = usb_control_msg(sd->gspca_dev.dev,
-               usb_sndctrlpipe(sd->gspca_dev.dev, 0),
-               0,
-               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               value, 0x01, NULL, 0, 500);
-
-       udelay(W9968CF_I2C_BUS_DELAY);
-
-       if (ret < 0) {
-               pr_err("Write SB reg [01] %04x failed\n", value);
-               sd->gspca_dev.usb_err = ret;
-       }
-}
-
-/*--------------------------------------------------------------------------
-  Read data from the serial bus control register.
-  Return 0 on success, a negative number otherwise.
-  --------------------------------------------------------------------------*/
-static int w9968cf_read_sb(struct sd *sd)
-{
-       int ret;
-
-       if (sd->gspca_dev.usb_err < 0)
-               return -1;
-
-       /* We don't use reg_r here, as the w9968cf is special and has 16
-          bit registers instead of 8 bit */
-       ret = usb_control_msg(sd->gspca_dev.dev,
-                       usb_rcvctrlpipe(sd->gspca_dev.dev, 0),
-                       1,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0, 0x01, sd->gspca_dev.usb_buf, 2, 500);
-       if (ret >= 0) {
-               ret = sd->gspca_dev.usb_buf[0] |
-                     (sd->gspca_dev.usb_buf[1] << 8);
-       } else {
-               pr_err("Read SB reg [01] failed\n");
-               sd->gspca_dev.usb_err = ret;
-       }
-
-       udelay(W9968CF_I2C_BUS_DELAY);
-
-       return ret;
-}
-
-/*--------------------------------------------------------------------------
-  Upload quantization tables for the JPEG compression.
-  This function is called by w9968cf_start_transfer().
-  Return 0 on success, a negative number otherwise.
-  --------------------------------------------------------------------------*/
-static void w9968cf_upload_quantizationtables(struct sd *sd)
-{
-       u16 a, b;
-       int i, j;
-
-       reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */
-
-       for (i = 0, j = 0; i < 32; i++, j += 2) {
-               a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j + 1]) << 8);
-               b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j + 1]) << 8);
-               reg_w(sd, 0x40 + i, a);
-               reg_w(sd, 0x60 + i, b);
-       }
-       reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */
-}
-
-/****************************************************************************
- * Low-level I2C I/O functions.                                             *
- * The adapter supports the following I2C transfer functions:               *
- * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only)           *
- * i2c_adap_read_byte_data()                                                *
- * i2c_adap_read_byte()                                                     *
- ****************************************************************************/
-
-static void w9968cf_smbus_start(struct sd *sd)
-{
-       w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
-       w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
-}
-
-static void w9968cf_smbus_stop(struct sd *sd)
-{
-       w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */
-       w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */
-       w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
-}
-
-static void w9968cf_smbus_write_byte(struct sd *sd, u8 v)
-{
-       u8 bit;
-       int sda;
-
-       for (bit = 0 ; bit < 8 ; bit++) {
-               sda = (v & 0x80) ? 2 : 0;
-               v <<= 1;
-               /* SDE=1, SDA=sda, SCL=0 */
-               w9968cf_write_sb(sd, 0x10 | sda);
-               /* SDE=1, SDA=sda, SCL=1 */
-               w9968cf_write_sb(sd, 0x11 | sda);
-               /* SDE=1, SDA=sda, SCL=0 */
-               w9968cf_write_sb(sd, 0x10 | sda);
-       }
-}
-
-static void w9968cf_smbus_read_byte(struct sd *sd, u8 *v)
-{
-       u8 bit;
-
-       /* No need to ensure SDA is high as we are always called after
-          read_ack which ends with SDA high */
-       *v = 0;
-       for (bit = 0 ; bit < 8 ; bit++) {
-               *v <<= 1;
-               /* SDE=1, SDA=1, SCL=1 */
-               w9968cf_write_sb(sd, 0x0013);
-               *v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0;
-               /* SDE=1, SDA=1, SCL=0 */
-               w9968cf_write_sb(sd, 0x0012);
-       }
-}
-
-static void w9968cf_smbus_write_nack(struct sd *sd)
-{
-       /* No need to ensure SDA is high as we are always called after
-          read_byte which ends with SDA high */
-       w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
-       w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
-}
-
-static void w9968cf_smbus_read_ack(struct sd *sd)
-{
-       int sda;
-
-       /* Ensure SDA is high before raising clock to avoid a spurious stop */
-       w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
-       w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */
-       sda = w9968cf_read_sb(sd);
-       w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
-       if (sda >= 0 && (sda & 0x08)) {
-               PDEBUG(D_USBI, "Did not receive i2c ACK");
-               sd->gspca_dev.usb_err = -EIO;
-       }
-}
-
-/* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */
-static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
-{
-       u16* data = (u16 *)sd->gspca_dev.usb_buf;
-
-       data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0);
-       data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0;
-       data[1] = 0x2082 | ((sd->sensor_addr & 0x40) ? 0x0005 : 0x0);
-       data[1] |= (sd->sensor_addr & 0x20) ? 0x0150 : 0x0;
-       data[1] |= (sd->sensor_addr & 0x10) ? 0x5400 : 0x0;
-       data[2] = 0x8208 | ((sd->sensor_addr & 0x08) ? 0x0015 : 0x0);
-       data[2] |= (sd->sensor_addr & 0x04) ? 0x0540 : 0x0;
-       data[2] |= (sd->sensor_addr & 0x02) ? 0x5000 : 0x0;
-       data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0);
-       data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0;
-
-       w9968cf_write_fsb(sd, data);
-
-       data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0);
-       data[0] |= (reg & 0x40) ? 0x0540 : 0x0;
-       data[0] |= (reg & 0x20) ? 0x5000 : 0x0;
-       data[1] = 0x0820 | ((reg & 0x20) ? 0x0001 : 0x0);
-       data[1] |= (reg & 0x10) ? 0x0054 : 0x0;
-       data[1] |= (reg & 0x08) ? 0x1500 : 0x0;
-       data[1] |= (reg & 0x04) ? 0x4000 : 0x0;
-       data[2] = 0x2082 | ((reg & 0x04) ? 0x0005 : 0x0);
-       data[2] |= (reg & 0x02) ? 0x0150 : 0x0;
-       data[2] |= (reg & 0x01) ? 0x5400 : 0x0;
-       data[3] = 0x001d;
-
-       w9968cf_write_fsb(sd, data);
-
-       data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0);
-       data[0] |= (value & 0x40) ? 0x0540 : 0x0;
-       data[0] |= (value & 0x20) ? 0x5000 : 0x0;
-       data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0);
-       data[1] |= (value & 0x10) ? 0x0054 : 0x0;
-       data[1] |= (value & 0x08) ? 0x1500 : 0x0;
-       data[1] |= (value & 0x04) ? 0x4000 : 0x0;
-       data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0);
-       data[2] |= (value & 0x02) ? 0x0150 : 0x0;
-       data[2] |= (value & 0x01) ? 0x5400 : 0x0;
-       data[3] = 0xfe1d;
-
-       w9968cf_write_fsb(sd, data);
-
-       PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
-}
-
-/* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */
-static int w9968cf_i2c_r(struct sd *sd, u8 reg)
-{
-       int ret = 0;
-       u8 value;
-
-       /* Fast serial bus data control disable */
-       w9968cf_write_sb(sd, 0x0013); /* don't change ! */
-
-       w9968cf_smbus_start(sd);
-       w9968cf_smbus_write_byte(sd, sd->sensor_addr);
-       w9968cf_smbus_read_ack(sd);
-       w9968cf_smbus_write_byte(sd, reg);
-       w9968cf_smbus_read_ack(sd);
-       w9968cf_smbus_stop(sd);
-       w9968cf_smbus_start(sd);
-       w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1);
-       w9968cf_smbus_read_ack(sd);
-       w9968cf_smbus_read_byte(sd, &value);
-       /* signal we don't want to read anymore, the v4l1 driver used to
-          send an ack here which is very wrong! (and then fixed
-          the issues this gave by retrying reads) */
-       w9968cf_smbus_write_nack(sd);
-       w9968cf_smbus_stop(sd);
-
-       /* Fast serial bus data control re-enable */
-       w9968cf_write_sb(sd, 0x0030);
-
-       if (sd->gspca_dev.usb_err >= 0) {
-               ret = value;
-               PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
-       } else
-               PDEBUG(D_ERR, "i2c read [0x%02x] failed", reg);
-
-       return ret;
-}
-
-/*--------------------------------------------------------------------------
-  Turn on the LED on some webcams. A beep should be heard too.
-  Return 0 on success, a negative number otherwise.
-  --------------------------------------------------------------------------*/
-static void w9968cf_configure(struct sd *sd)
-{
-       reg_w(sd, 0x00, 0xff00); /* power-down */
-       reg_w(sd, 0x00, 0xbf17); /* reset everything */
-       reg_w(sd, 0x00, 0xbf10); /* normal operation */
-       reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */
-       reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */
-       reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */
-       reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */
-
-       sd->stopped = 1;
-}
-
-static void w9968cf_init(struct sd *sd)
-{
-       unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2),
-                     y0 = 0x0000,
-                     u0 = y0 + hw_bufsize / 2,
-                     v0 = u0 + hw_bufsize / 4,
-                     y1 = v0 + hw_bufsize / 4,
-                     u1 = y1 + hw_bufsize / 2,
-                     v1 = u1 + hw_bufsize / 4;
-
-       reg_w(sd, 0x00, 0xff00); /* power off */
-       reg_w(sd, 0x00, 0xbf10); /* power on */
-
-       reg_w(sd, 0x03, 0x405d); /* DRAM timings */
-       reg_w(sd, 0x04, 0x0030); /* SDRAM timings */
-
-       reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */
-       reg_w(sd, 0x21, y0 >> 16);    /* Y buf.0, high */
-       reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */
-       reg_w(sd, 0x25, u0 >> 16);    /* U buf.0, high */
-       reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */
-       reg_w(sd, 0x29, v0 >> 16);    /* V buf.0, high */
-
-       reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */
-       reg_w(sd, 0x23, y1 >> 16);    /* Y buf.1, high */
-       reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */
-       reg_w(sd, 0x27, u1 >> 16);    /* U buf.1, high */
-       reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */
-       reg_w(sd, 0x2b, v1 >> 16);    /* V buf.1, high */
-
-       reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */
-       reg_w(sd, 0x33, y1 >> 16);    /* JPEG buf 0 high */
-
-       reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */
-       reg_w(sd, 0x35, y1 >> 16);    /* JPEG bug 1 high */
-
-       reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */
-       reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/
-       reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */
-       reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */
-}
-
-static void w9968cf_set_crop_window(struct sd *sd)
-{
-       int start_cropx, start_cropy,  x, y, fw, fh, cw, ch,
-           max_width, max_height;
-
-       if (sd->sif) {
-               max_width  = 352;
-               max_height = 288;
-       } else {
-               max_width  = 640;
-               max_height = 480;
-       }
-
-       if (sd->sensor == SEN_OV7620) {
-               /*
-                * Sigh, this is dependend on the clock / framerate changes
-                * made by the frequency control, sick.
-                *
-                * Note we cannot use v4l2_ctrl_g_ctrl here, as we get called
-                * from ov519.c:setfreq() with the ctrl lock held!
-                */
-               if (sd->freq->val == 1) {
-                       start_cropx = 277;
-                       start_cropy = 37;
-               } else {
-                       start_cropx = 105;
-                       start_cropy = 37;
-               }
-       } else {
-               start_cropx = 320;
-               start_cropy = 35;
-       }
-
-       /* Work around to avoid FP arithmetics */
-       #define SC(x) ((x) << 10)
-
-       /* Scaling factors */
-       fw = SC(sd->gspca_dev.width) / max_width;
-       fh = SC(sd->gspca_dev.height) / max_height;
-
-       cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width) / fh;
-       ch = (fw >= fh) ? SC(sd->gspca_dev.height) / fw : max_height;
-
-       sd->sensor_width = max_width;
-       sd->sensor_height = max_height;
-
-       x = (max_width - cw) / 2;
-       y = (max_height - ch) / 2;
-
-       reg_w(sd, 0x10, start_cropx + x);
-       reg_w(sd, 0x11, start_cropy + y);
-       reg_w(sd, 0x12, start_cropx + x + cw);
-       reg_w(sd, 0x13, start_cropy + y + ch);
-}
-
-static void w9968cf_mode_init_regs(struct sd *sd)
-{
-       int val, vs_polarity, hs_polarity;
-
-       w9968cf_set_crop_window(sd);
-
-       reg_w(sd, 0x14, sd->gspca_dev.width);
-       reg_w(sd, 0x15, sd->gspca_dev.height);
-
-       /* JPEG width & height */
-       reg_w(sd, 0x30, sd->gspca_dev.width);
-       reg_w(sd, 0x31, sd->gspca_dev.height);
-
-       /* Y & UV frame buffer strides (in WORD) */
-       if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
-           V4L2_PIX_FMT_JPEG) {
-               reg_w(sd, 0x2c, sd->gspca_dev.width / 2);
-               reg_w(sd, 0x2d, sd->gspca_dev.width / 4);
-       } else
-               reg_w(sd, 0x2c, sd->gspca_dev.width);
-
-       reg_w(sd, 0x00, 0xbf17); /* reset everything */
-       reg_w(sd, 0x00, 0xbf10); /* normal operation */
-
-       /* Transfer size in WORDS (for UYVY format only) */
-       val = sd->gspca_dev.width * sd->gspca_dev.height;
-       reg_w(sd, 0x3d, val & 0xffff); /* low bits */
-       reg_w(sd, 0x3e, val >> 16);    /* high bits */
-
-       if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
-           V4L2_PIX_FMT_JPEG) {
-               /* We may get called multiple times (usb isoc bw negotiat.) */
-               jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height,
-                           sd->gspca_dev.width, 0x22); /* JPEG 420 */
-               jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
-               w9968cf_upload_quantizationtables(sd);
-               v4l2_ctrl_grab(sd->jpegqual, true);
-       }
-
-       /* Video Capture Control Register */
-       if (sd->sensor == SEN_OV7620) {
-               /* Seems to work around a bug in the image sensor */
-               vs_polarity = 1;
-               hs_polarity = 1;
-       } else {
-               vs_polarity = 1;
-               hs_polarity = 0;
-       }
-
-       val = (vs_polarity << 12) | (hs_polarity << 11);
-
-       /* NOTE: We may not have enough memory to do double buffering while
-          doing compression (amount of memory differs per model cam).
-          So we use the second image buffer also as jpeg stream buffer
-          (see w9968cf_init), and disable double buffering. */
-       if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
-           V4L2_PIX_FMT_JPEG) {
-               /* val |= 0x0002; YUV422P */
-               val |= 0x0003; /* YUV420P */
-       } else
-               val |= 0x0080; /* Enable HW double buffering */
-
-       /* val |= 0x0020; enable clamping */
-       /* val |= 0x0008; enable (1-2-1) filter */
-       /* val |= 0x000c; enable (2-3-6-3-2) filter */
-
-       val |= 0x8000; /* capt. enable */
-
-       reg_w(sd, 0x16, val);
-
-       sd->gspca_dev.empty_packet = 0;
-}
-
-static void w9968cf_stop0(struct sd *sd)
-{
-       v4l2_ctrl_grab(sd->jpegqual, false);
-       reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */
-       reg_w(sd, 0x16, 0x0000); /* stop video capture */
-}
-
-/* The w9968cf docs say that a 0 sized packet means EOF (and also SOF
-   for the next frame). This seems to simply not be true when operating
-   in JPEG mode, in this case there may be empty packets within the
-   frame. So in JPEG mode use the JPEG SOI marker to detect SOF.
-
-   Note to make things even more interesting the w9968cf sends *PLANAR* jpeg,
-   to be precise it sends: SOI, SOF, DRI, SOS, Y-data, SOS, U-data, SOS,
-   V-data, EOI. */
-static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,                       /* isoc packet */
-                       int len)                        /* iso packet length */
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (w9968cf_vga_mode[gspca_dev->curr_mode].pixelformat ==
-           V4L2_PIX_FMT_JPEG) {
-               if (len >= 2 &&
-                   data[0] == 0xff &&
-                   data[1] == 0xd8) {
-                       gspca_frame_add(gspca_dev, LAST_PACKET,
-                                       NULL, 0);
-                       gspca_frame_add(gspca_dev, FIRST_PACKET,
-                                       sd->jpeg_hdr, JPEG_HDR_SZ);
-                       /* Strip the ff d8, our own header (which adds
-                          huffman and quantization tables) already has this */
-                       len -= 2;
-                       data += 2;
-               }
-       } else {
-               /* In UYVY mode an empty packet signals EOF */
-               if (gspca_dev->empty_packet) {
-                       gspca_frame_add(gspca_dev, LAST_PACKET,
-                                               NULL, 0);
-                       gspca_frame_add(gspca_dev, FIRST_PACKET,
-                                       NULL, 0);
-                       gspca_dev->empty_packet = 0;
-               }
-       }
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c
deleted file mode 100644 (file)
index 13b8d39..0000000
+++ /dev/null
@@ -1,3145 +0,0 @@
-/*
- * USB IBM C-It Video Camera driver
- *
- * Supports Xirlink C-It Video Camera, IBM PC Camera,
- * IBM NetCamera and Veo Stingray.
- *
- * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.com>
- *
- * This driver is based on earlier work of:
- *
- * (C) Copyright 1999 Johannes Erdfelt
- * (C) Copyright 1999 Randy Dunlap
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define MODULE_NAME "xirlink-cit"
-
-#include <linux/input.h>
-#include "gspca.h"
-
-MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
-MODULE_DESCRIPTION("Xirlink C-IT");
-MODULE_LICENSE("GPL");
-
-/* FIXME we should autodetect this */
-static int ibm_netcam_pro;
-module_param(ibm_netcam_pro, int, 0);
-MODULE_PARM_DESC(ibm_netcam_pro,
-                "Use IBM Netcamera Pro init sequences for Model 3 cams");
-
-/* FIXME this should be handled through the V4L2 input selection API */
-static int rca_input;
-module_param(rca_input, int, 0644);
-MODULE_PARM_DESC(rca_input,
-                "Use rca input instead of ccd sensor on Model 3 cams");
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;             /* !! must be the first item */
-       struct v4l2_ctrl *lighting;
-       u8 model;
-#define CIT_MODEL0 0 /* bcd version 0.01 cams ie the xvp-500 */
-#define CIT_MODEL1 1 /* The model 1 - 4 nomenclature comes from the old */
-#define CIT_MODEL2 2 /* ibmcam driver */
-#define CIT_MODEL3 3
-#define CIT_MODEL4 4
-#define CIT_IBM_NETCAM_PRO 5
-       u8 input_index;
-       u8 button_state;
-       u8 stop_on_control_change;
-       u8 sof_read;
-       u8 sof_len;
-};
-
-static void sd_stop0(struct gspca_dev *gspca_dev);
-
-static const struct v4l2_pix_format cif_yuv_mode[] = {
-       {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 3 / 2 + 4,
-               .colorspace = V4L2_COLORSPACE_SRGB},
-       {352, 288, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 3 / 2 + 4,
-               .colorspace = V4L2_COLORSPACE_SRGB},
-};
-
-static const struct v4l2_pix_format vga_yuv_mode[] = {
-       {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 3 / 2 + 4,
-               .colorspace = V4L2_COLORSPACE_SRGB},
-       {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 2 + 4,
-               .colorspace = V4L2_COLORSPACE_SRGB},
-       {640, 480, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 2 + 4,
-               .colorspace = V4L2_COLORSPACE_SRGB},
-};
-
-static const struct v4l2_pix_format model0_mode[] = {
-       {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 3 / 2 + 4,
-               .colorspace = V4L2_COLORSPACE_SRGB},
-       {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 3 / 2 + 4,
-               .colorspace = V4L2_COLORSPACE_SRGB},
-       {320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 2 + 4,
-               .colorspace = V4L2_COLORSPACE_SRGB},
-};
-
-static const struct v4l2_pix_format model2_mode[] = {
-       {160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
-               .bytesperline = 160,
-               .sizeimage = 160 * 120 * 3 / 2 + 4,
-               .colorspace = V4L2_COLORSPACE_SRGB},
-       {176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 3 / 2 + 4,
-               .colorspace = V4L2_COLORSPACE_SRGB},
-       {320, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 + 4,
-               .colorspace = V4L2_COLORSPACE_SRGB},
-       {352, 288, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 + 4,
-               .colorspace = V4L2_COLORSPACE_SRGB},
-};
-
-/*
- * 01.01.08 - Added for RCA video in support -LO
- * This struct is used to init the Model3 cam to use the RCA video in port
- * instead of the CCD sensor.
- */
-static const u16 rca_initdata[][3] = {
-       {0, 0x0000, 0x010c},
-       {0, 0x0006, 0x012c},
-       {0, 0x0078, 0x012d},
-       {0, 0x0046, 0x012f},
-       {0, 0xd141, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfea8, 0x0124},
-       {1, 0x0000, 0x0116},
-       {0, 0x0064, 0x0116},
-       {1, 0x0000, 0x0115},
-       {0, 0x0003, 0x0115},
-       {0, 0x0008, 0x0123},
-       {0, 0x0000, 0x0117},
-       {0, 0x0000, 0x0112},
-       {0, 0x0080, 0x0100},
-       {0, 0x0000, 0x0100},
-       {1, 0x0000, 0x0116},
-       {0, 0x0060, 0x0116},
-       {0, 0x0002, 0x0112},
-       {0, 0x0000, 0x0123},
-       {0, 0x0001, 0x0117},
-       {0, 0x0040, 0x0108},
-       {0, 0x0019, 0x012c},
-       {0, 0x0040, 0x0116},
-       {0, 0x000a, 0x0115},
-       {0, 0x000b, 0x0115},
-       {0, 0x0078, 0x012d},
-       {0, 0x0046, 0x012f},
-       {0, 0xd141, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfea8, 0x0124},
-       {0, 0x0064, 0x0116},
-       {0, 0x0000, 0x0115},
-       {0, 0x0001, 0x0115},
-       {0, 0xffff, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x00aa, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xffff, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x00f2, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x000f, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xffff, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x00f8, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x00fc, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xffff, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x00f9, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x003c, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xffff, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0027, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0019, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0021, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0006, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0045, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x002a, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x000e, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x002b, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x00f4, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x002c, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0004, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x002d, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0014, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x002e, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0003, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x002f, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0003, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0014, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0040, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0040, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0053, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0x0000, 0x0101},
-       {0, 0x00a0, 0x0103},
-       {0, 0x0078, 0x0105},
-       {0, 0x0000, 0x010a},
-       {0, 0x0024, 0x010b},
-       {0, 0x0028, 0x0119},
-       {0, 0x0088, 0x011b},
-       {0, 0x0002, 0x011d},
-       {0, 0x0003, 0x011e},
-       {0, 0x0000, 0x0129},
-       {0, 0x00fc, 0x012b},
-       {0, 0x0008, 0x0102},
-       {0, 0x0000, 0x0104},
-       {0, 0x0008, 0x011a},
-       {0, 0x0028, 0x011c},
-       {0, 0x0021, 0x012a},
-       {0, 0x0000, 0x0118},
-       {0, 0x0000, 0x0132},
-       {0, 0x0000, 0x0109},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0031, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0040, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0040, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x00dc, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0032, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0020, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0001, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0040, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0040, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0037, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0030, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0xfff9, 0x0124},
-       {0, 0x0086, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0038, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0008, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0x0000, 0x0127},
-       {0, 0xfff8, 0x0124},
-       {0, 0xfffd, 0x0124},
-       {0, 0xfffa, 0x0124},
-       {0, 0x0003, 0x0111},
-};
-
-/* TESTME the old ibmcam driver repeats certain commands to Model1 cameras, we
-   do the same for now (testing needed to see if this is really necessary) */
-static const int cit_model1_ntries = 5;
-static const int cit_model1_ntries2 = 2;
-
-static int cit_write_reg(struct gspca_dev *gspca_dev, u16 value, u16 index)
-{
-       struct usb_device *udev = gspca_dev->dev;
-       int err;
-
-       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x00,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
-                       value, index, NULL, 0, 1000);
-       if (err < 0)
-               pr_err("Failed to write a register (index 0x%04X, value 0x%02X, error %d)\n",
-                      index, value, err);
-
-       return 0;
-}
-
-static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index, int verbose)
-{
-       struct usb_device *udev = gspca_dev->dev;
-       __u8 *buf = gspca_dev->usb_buf;
-       int res;
-
-       res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x01,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
-                       0x00, index, buf, 8, 1000);
-       if (res < 0) {
-               pr_err("Failed to read a register (index 0x%04X, error %d)\n",
-                      index, res);
-               return res;
-       }
-
-       if (verbose)
-               PDEBUG(D_PROBE, "Register %04x value: %02x", index, buf[0]);
-
-       return 0;
-}
-
-/*
- * cit_send_FF_04_02()
- *
- * This procedure sends magic 3-command prefix to the camera.
- * The purpose of this prefix is not known.
- *
- * History:
- * 1/2/00   Created.
- */
-static void cit_send_FF_04_02(struct gspca_dev *gspca_dev)
-{
-       cit_write_reg(gspca_dev, 0x00FF, 0x0127);
-       cit_write_reg(gspca_dev, 0x0004, 0x0124);
-       cit_write_reg(gspca_dev, 0x0002, 0x0124);
-}
-
-static void cit_send_00_04_06(struct gspca_dev *gspca_dev)
-{
-       cit_write_reg(gspca_dev, 0x0000, 0x0127);
-       cit_write_reg(gspca_dev, 0x0004, 0x0124);
-       cit_write_reg(gspca_dev, 0x0006, 0x0124);
-}
-
-static void cit_send_x_00(struct gspca_dev *gspca_dev, unsigned short x)
-{
-       cit_write_reg(gspca_dev, x,      0x0127);
-       cit_write_reg(gspca_dev, 0x0000, 0x0124);
-}
-
-static void cit_send_x_00_05(struct gspca_dev *gspca_dev, unsigned short x)
-{
-       cit_send_x_00(gspca_dev, x);
-       cit_write_reg(gspca_dev, 0x0005, 0x0124);
-}
-
-static void cit_send_x_00_05_02(struct gspca_dev *gspca_dev, unsigned short x)
-{
-       cit_write_reg(gspca_dev, x,      0x0127);
-       cit_write_reg(gspca_dev, 0x0000, 0x0124);
-       cit_write_reg(gspca_dev, 0x0005, 0x0124);
-       cit_write_reg(gspca_dev, 0x0002, 0x0124);
-}
-
-static void cit_send_x_01_00_05(struct gspca_dev *gspca_dev, u16 x)
-{
-       cit_write_reg(gspca_dev, x,      0x0127);
-       cit_write_reg(gspca_dev, 0x0001, 0x0124);
-       cit_write_reg(gspca_dev, 0x0000, 0x0124);
-       cit_write_reg(gspca_dev, 0x0005, 0x0124);
-}
-
-static void cit_send_x_00_05_02_01(struct gspca_dev *gspca_dev, u16 x)
-{
-       cit_write_reg(gspca_dev, x,      0x0127);
-       cit_write_reg(gspca_dev, 0x0000, 0x0124);
-       cit_write_reg(gspca_dev, 0x0005, 0x0124);
-       cit_write_reg(gspca_dev, 0x0002, 0x0124);
-       cit_write_reg(gspca_dev, 0x0001, 0x0124);
-}
-
-static void cit_send_x_00_05_02_08_01(struct gspca_dev *gspca_dev, u16 x)
-{
-       cit_write_reg(gspca_dev, x,      0x0127);
-       cit_write_reg(gspca_dev, 0x0000, 0x0124);
-       cit_write_reg(gspca_dev, 0x0005, 0x0124);
-       cit_write_reg(gspca_dev, 0x0002, 0x0124);
-       cit_write_reg(gspca_dev, 0x0008, 0x0124);
-       cit_write_reg(gspca_dev, 0x0001, 0x0124);
-}
-
-static void cit_Packet_Format1(struct gspca_dev *gspca_dev, u16 fkey, u16 val)
-{
-       cit_send_x_01_00_05(gspca_dev, 0x0088);
-       cit_send_x_00_05(gspca_dev, fkey);
-       cit_send_x_00_05_02_08_01(gspca_dev, val);
-       cit_send_x_00_05(gspca_dev, 0x0088);
-       cit_send_x_00_05_02_01(gspca_dev, fkey);
-       cit_send_x_00_05(gspca_dev, 0x0089);
-       cit_send_x_00(gspca_dev, fkey);
-       cit_send_00_04_06(gspca_dev);
-       cit_read_reg(gspca_dev, 0x0126, 0);
-       cit_send_FF_04_02(gspca_dev);
-}
-
-static void cit_PacketFormat2(struct gspca_dev *gspca_dev, u16 fkey, u16 val)
-{
-       cit_send_x_01_00_05(gspca_dev, 0x0088);
-       cit_send_x_00_05(gspca_dev, fkey);
-       cit_send_x_00_05_02(gspca_dev, val);
-}
-
-static void cit_model2_Packet2(struct gspca_dev *gspca_dev)
-{
-       cit_write_reg(gspca_dev, 0x00ff, 0x012d);
-       cit_write_reg(gspca_dev, 0xfea3, 0x0124);
-}
-
-static void cit_model2_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
-{
-       cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-       cit_write_reg(gspca_dev, 0x00ff, 0x012e);
-       cit_write_reg(gspca_dev, v1,     0x012f);
-       cit_write_reg(gspca_dev, 0x00ff, 0x0130);
-       cit_write_reg(gspca_dev, 0xc719, 0x0124);
-       cit_write_reg(gspca_dev, v2,     0x0127);
-
-       cit_model2_Packet2(gspca_dev);
-}
-
-/*
- * cit_model3_Packet1()
- *
- * 00_0078_012d
- * 00_0097_012f
- * 00_d141_0124
- * 00_0096_0127
- * 00_fea8_0124
-*/
-static void cit_model3_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
-{
-       cit_write_reg(gspca_dev, 0x0078, 0x012d);
-       cit_write_reg(gspca_dev, v1,     0x012f);
-       cit_write_reg(gspca_dev, 0xd141, 0x0124);
-       cit_write_reg(gspca_dev, v2,     0x0127);
-       cit_write_reg(gspca_dev, 0xfea8, 0x0124);
-}
-
-static void cit_model4_Packet1(struct gspca_dev *gspca_dev, u16 v1, u16 v2)
-{
-       cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-       cit_write_reg(gspca_dev, v1,     0x012f);
-       cit_write_reg(gspca_dev, 0xd141, 0x0124);
-       cit_write_reg(gspca_dev, v2,     0x0127);
-       cit_write_reg(gspca_dev, 0xfea8, 0x0124);
-}
-
-static void cit_model4_BrightnessPacket(struct gspca_dev *gspca_dev, u16 val)
-{
-       cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-       cit_write_reg(gspca_dev, 0x0026, 0x012f);
-       cit_write_reg(gspca_dev, 0xd141, 0x0124);
-       cit_write_reg(gspca_dev, val,    0x0127);
-       cit_write_reg(gspca_dev, 0x00aa, 0x0130);
-       cit_write_reg(gspca_dev, 0x82a8, 0x0124);
-       cit_write_reg(gspca_dev, 0x0038, 0x012d);
-       cit_write_reg(gspca_dev, 0x0004, 0x012f);
-       cit_write_reg(gspca_dev, 0xd145, 0x0124);
-       cit_write_reg(gspca_dev, 0xfffa, 0x0124);
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                    const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-
-       sd->model = id->driver_info;
-       if (sd->model == CIT_MODEL3 && ibm_netcam_pro)
-               sd->model = CIT_IBM_NETCAM_PRO;
-
-       cam = &gspca_dev->cam;
-       switch (sd->model) {
-       case CIT_MODEL0:
-               cam->cam_mode = model0_mode;
-               cam->nmodes = ARRAY_SIZE(model0_mode);
-               sd->sof_len = 4;
-               break;
-       case CIT_MODEL1:
-               cam->cam_mode = cif_yuv_mode;
-               cam->nmodes = ARRAY_SIZE(cif_yuv_mode);
-               sd->sof_len = 4;
-               break;
-       case CIT_MODEL2:
-               cam->cam_mode = model2_mode + 1; /* no 160x120 */
-               cam->nmodes = 3;
-               break;
-       case CIT_MODEL3:
-               cam->cam_mode = vga_yuv_mode;
-               cam->nmodes = ARRAY_SIZE(vga_yuv_mode);
-               sd->stop_on_control_change = 1;
-               sd->sof_len = 4;
-               break;
-       case CIT_MODEL4:
-               cam->cam_mode = model2_mode;
-               cam->nmodes = ARRAY_SIZE(model2_mode);
-               break;
-       case CIT_IBM_NETCAM_PRO:
-               cam->cam_mode = vga_yuv_mode;
-               cam->nmodes = 2; /* no 640 x 480 */
-               cam->input_flags = V4L2_IN_ST_VFLIP;
-               sd->stop_on_control_change = 1;
-               sd->sof_len = 4;
-               break;
-       }
-
-       return 0;
-}
-
-static int cit_init_model0(struct gspca_dev *gspca_dev)
-{
-       cit_write_reg(gspca_dev, 0x0000, 0x0100); /* turn on led */
-       cit_write_reg(gspca_dev, 0x0001, 0x0112); /* turn on autogain ? */
-       cit_write_reg(gspca_dev, 0x0000, 0x0400);
-       cit_write_reg(gspca_dev, 0x0001, 0x0400);
-       cit_write_reg(gspca_dev, 0x0000, 0x0420);
-       cit_write_reg(gspca_dev, 0x0001, 0x0420);
-       cit_write_reg(gspca_dev, 0x000d, 0x0409);
-       cit_write_reg(gspca_dev, 0x0002, 0x040a);
-       cit_write_reg(gspca_dev, 0x0018, 0x0405);
-       cit_write_reg(gspca_dev, 0x0008, 0x0435);
-       cit_write_reg(gspca_dev, 0x0026, 0x040b);
-       cit_write_reg(gspca_dev, 0x0007, 0x0437);
-       cit_write_reg(gspca_dev, 0x0015, 0x042f);
-       cit_write_reg(gspca_dev, 0x002b, 0x0439);
-       cit_write_reg(gspca_dev, 0x0026, 0x043a);
-       cit_write_reg(gspca_dev, 0x0008, 0x0438);
-       cit_write_reg(gspca_dev, 0x001e, 0x042b);
-       cit_write_reg(gspca_dev, 0x0041, 0x042c);
-
-       return 0;
-}
-
-static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev)
-{
-       cit_read_reg(gspca_dev, 0x128, 1);
-       cit_write_reg(gspca_dev, 0x0003, 0x0133);
-       cit_write_reg(gspca_dev, 0x0000, 0x0117);
-       cit_write_reg(gspca_dev, 0x0008, 0x0123);
-       cit_write_reg(gspca_dev, 0x0000, 0x0100);
-       cit_read_reg(gspca_dev, 0x0116, 0);
-       cit_write_reg(gspca_dev, 0x0060, 0x0116);
-       cit_write_reg(gspca_dev, 0x0002, 0x0112);
-       cit_write_reg(gspca_dev, 0x0000, 0x0133);
-       cit_write_reg(gspca_dev, 0x0000, 0x0123);
-       cit_write_reg(gspca_dev, 0x0001, 0x0117);
-       cit_write_reg(gspca_dev, 0x0040, 0x0108);
-       cit_write_reg(gspca_dev, 0x0019, 0x012c);
-       cit_write_reg(gspca_dev, 0x0060, 0x0116);
-       cit_write_reg(gspca_dev, 0x0002, 0x0115);
-       cit_write_reg(gspca_dev, 0x000b, 0x0115);
-
-       cit_write_reg(gspca_dev, 0x0078, 0x012d);
-       cit_write_reg(gspca_dev, 0x0001, 0x012f);
-       cit_write_reg(gspca_dev, 0xd141, 0x0124);
-       cit_write_reg(gspca_dev, 0x0079, 0x012d);
-       cit_write_reg(gspca_dev, 0x00ff, 0x0130);
-       cit_write_reg(gspca_dev, 0xcd41, 0x0124);
-       cit_write_reg(gspca_dev, 0xfffa, 0x0124);
-       cit_read_reg(gspca_dev, 0x0126, 1);
-
-       cit_model3_Packet1(gspca_dev, 0x0000, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0000, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x000b, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x000c, 0x0008);
-       cit_model3_Packet1(gspca_dev, 0x000d, 0x003a);
-       cit_model3_Packet1(gspca_dev, 0x000e, 0x0060);
-       cit_model3_Packet1(gspca_dev, 0x000f, 0x0060);
-       cit_model3_Packet1(gspca_dev, 0x0010, 0x0008);
-       cit_model3_Packet1(gspca_dev, 0x0011, 0x0004);
-       cit_model3_Packet1(gspca_dev, 0x0012, 0x0028);
-       cit_model3_Packet1(gspca_dev, 0x0013, 0x0002);
-       cit_model3_Packet1(gspca_dev, 0x0014, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0015, 0x00fb);
-       cit_model3_Packet1(gspca_dev, 0x0016, 0x0002);
-       cit_model3_Packet1(gspca_dev, 0x0017, 0x0037);
-       cit_model3_Packet1(gspca_dev, 0x0018, 0x0036);
-       cit_model3_Packet1(gspca_dev, 0x001e, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x001f, 0x0008);
-       cit_model3_Packet1(gspca_dev, 0x0020, 0x00c1);
-       cit_model3_Packet1(gspca_dev, 0x0021, 0x0034);
-       cit_model3_Packet1(gspca_dev, 0x0022, 0x0034);
-       cit_model3_Packet1(gspca_dev, 0x0025, 0x0002);
-       cit_model3_Packet1(gspca_dev, 0x0028, 0x0022);
-       cit_model3_Packet1(gspca_dev, 0x0029, 0x000a);
-       cit_model3_Packet1(gspca_dev, 0x002b, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x002c, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x002d, 0x00ff);
-       cit_model3_Packet1(gspca_dev, 0x002e, 0x00ff);
-       cit_model3_Packet1(gspca_dev, 0x002f, 0x00ff);
-       cit_model3_Packet1(gspca_dev, 0x0030, 0x00ff);
-       cit_model3_Packet1(gspca_dev, 0x0031, 0x00ff);
-       cit_model3_Packet1(gspca_dev, 0x0032, 0x0007);
-       cit_model3_Packet1(gspca_dev, 0x0033, 0x0005);
-       cit_model3_Packet1(gspca_dev, 0x0037, 0x0040);
-       cit_model3_Packet1(gspca_dev, 0x0039, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x003a, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x003b, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x003c, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0040, 0x000c);
-       cit_model3_Packet1(gspca_dev, 0x0041, 0x00fb);
-       cit_model3_Packet1(gspca_dev, 0x0042, 0x0002);
-       cit_model3_Packet1(gspca_dev, 0x0043, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0045, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0046, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0047, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0048, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0049, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x004a, 0x00ff);
-       cit_model3_Packet1(gspca_dev, 0x004b, 0x00ff);
-       cit_model3_Packet1(gspca_dev, 0x004c, 0x00ff);
-       cit_model3_Packet1(gspca_dev, 0x004f, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0050, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0051, 0x0002);
-       cit_model3_Packet1(gspca_dev, 0x0055, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0056, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0057, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0058, 0x0002);
-       cit_model3_Packet1(gspca_dev, 0x0059, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x005c, 0x0016);
-       cit_model3_Packet1(gspca_dev, 0x005d, 0x0022);
-       cit_model3_Packet1(gspca_dev, 0x005e, 0x003c);
-       cit_model3_Packet1(gspca_dev, 0x005f, 0x0050);
-       cit_model3_Packet1(gspca_dev, 0x0060, 0x0044);
-       cit_model3_Packet1(gspca_dev, 0x0061, 0x0005);
-       cit_model3_Packet1(gspca_dev, 0x006a, 0x007e);
-       cit_model3_Packet1(gspca_dev, 0x006f, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0072, 0x001b);
-       cit_model3_Packet1(gspca_dev, 0x0073, 0x0005);
-       cit_model3_Packet1(gspca_dev, 0x0074, 0x000a);
-       cit_model3_Packet1(gspca_dev, 0x0075, 0x001b);
-       cit_model3_Packet1(gspca_dev, 0x0076, 0x002a);
-       cit_model3_Packet1(gspca_dev, 0x0077, 0x003c);
-       cit_model3_Packet1(gspca_dev, 0x0078, 0x0050);
-       cit_model3_Packet1(gspca_dev, 0x007b, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x007c, 0x0011);
-       cit_model3_Packet1(gspca_dev, 0x007d, 0x0024);
-       cit_model3_Packet1(gspca_dev, 0x007e, 0x0043);
-       cit_model3_Packet1(gspca_dev, 0x007f, 0x005a);
-       cit_model3_Packet1(gspca_dev, 0x0084, 0x0020);
-       cit_model3_Packet1(gspca_dev, 0x0085, 0x0033);
-       cit_model3_Packet1(gspca_dev, 0x0086, 0x000a);
-       cit_model3_Packet1(gspca_dev, 0x0087, 0x0030);
-       cit_model3_Packet1(gspca_dev, 0x0088, 0x0070);
-       cit_model3_Packet1(gspca_dev, 0x008b, 0x0008);
-       cit_model3_Packet1(gspca_dev, 0x008f, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0090, 0x0006);
-       cit_model3_Packet1(gspca_dev, 0x0091, 0x0028);
-       cit_model3_Packet1(gspca_dev, 0x0092, 0x005a);
-       cit_model3_Packet1(gspca_dev, 0x0093, 0x0082);
-       cit_model3_Packet1(gspca_dev, 0x0096, 0x0014);
-       cit_model3_Packet1(gspca_dev, 0x0097, 0x0020);
-       cit_model3_Packet1(gspca_dev, 0x0098, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00b0, 0x0046);
-       cit_model3_Packet1(gspca_dev, 0x00b1, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00b2, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00b3, 0x0004);
-       cit_model3_Packet1(gspca_dev, 0x00b4, 0x0007);
-       cit_model3_Packet1(gspca_dev, 0x00b6, 0x0002);
-       cit_model3_Packet1(gspca_dev, 0x00b7, 0x0004);
-       cit_model3_Packet1(gspca_dev, 0x00bb, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00bc, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x00bd, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00bf, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00c0, 0x00c8);
-       cit_model3_Packet1(gspca_dev, 0x00c1, 0x0014);
-       cit_model3_Packet1(gspca_dev, 0x00c2, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x00c3, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00c4, 0x0004);
-       cit_model3_Packet1(gspca_dev, 0x00cb, 0x00bf);
-       cit_model3_Packet1(gspca_dev, 0x00cc, 0x00bf);
-       cit_model3_Packet1(gspca_dev, 0x00cd, 0x00bf);
-       cit_model3_Packet1(gspca_dev, 0x00ce, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00cf, 0x0020);
-       cit_model3_Packet1(gspca_dev, 0x00d0, 0x0040);
-       cit_model3_Packet1(gspca_dev, 0x00d1, 0x00bf);
-       cit_model3_Packet1(gspca_dev, 0x00d1, 0x00bf);
-       cit_model3_Packet1(gspca_dev, 0x00d2, 0x00bf);
-       cit_model3_Packet1(gspca_dev, 0x00d3, 0x00bf);
-       cit_model3_Packet1(gspca_dev, 0x00ea, 0x0008);
-       cit_model3_Packet1(gspca_dev, 0x00eb, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00ec, 0x00e8);
-       cit_model3_Packet1(gspca_dev, 0x00ed, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x00ef, 0x0022);
-       cit_model3_Packet1(gspca_dev, 0x00f0, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00f2, 0x0028);
-       cit_model3_Packet1(gspca_dev, 0x00f4, 0x0002);
-       cit_model3_Packet1(gspca_dev, 0x00f5, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00fa, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00fb, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x00fc, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00fd, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00fe, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00ff, 0x0000);
-
-       cit_model3_Packet1(gspca_dev, 0x00be, 0x0003);
-       cit_model3_Packet1(gspca_dev, 0x00c8, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00c9, 0x0020);
-       cit_model3_Packet1(gspca_dev, 0x00ca, 0x0040);
-       cit_model3_Packet1(gspca_dev, 0x0053, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x0082, 0x000e);
-       cit_model3_Packet1(gspca_dev, 0x0083, 0x0020);
-       cit_model3_Packet1(gspca_dev, 0x0034, 0x003c);
-       cit_model3_Packet1(gspca_dev, 0x006e, 0x0055);
-       cit_model3_Packet1(gspca_dev, 0x0062, 0x0005);
-       cit_model3_Packet1(gspca_dev, 0x0063, 0x0008);
-       cit_model3_Packet1(gspca_dev, 0x0066, 0x000a);
-       cit_model3_Packet1(gspca_dev, 0x0067, 0x0006);
-       cit_model3_Packet1(gspca_dev, 0x006b, 0x0010);
-       cit_model3_Packet1(gspca_dev, 0x005a, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x005b, 0x000a);
-       cit_model3_Packet1(gspca_dev, 0x0023, 0x0006);
-       cit_model3_Packet1(gspca_dev, 0x0026, 0x0004);
-       cit_model3_Packet1(gspca_dev, 0x0036, 0x0069);
-       cit_model3_Packet1(gspca_dev, 0x0038, 0x0064);
-       cit_model3_Packet1(gspca_dev, 0x003d, 0x0003);
-       cit_model3_Packet1(gspca_dev, 0x003e, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x00b8, 0x0014);
-       cit_model3_Packet1(gspca_dev, 0x00b9, 0x0014);
-       cit_model3_Packet1(gspca_dev, 0x00e6, 0x0004);
-       cit_model3_Packet1(gspca_dev, 0x00e8, 0x0001);
-
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->model) {
-       case CIT_MODEL0:
-               cit_init_model0(gspca_dev);
-               sd_stop0(gspca_dev);
-               break;
-       case CIT_MODEL1:
-       case CIT_MODEL2:
-       case CIT_MODEL3:
-       case CIT_MODEL4:
-               break; /* All is done in sd_start */
-       case CIT_IBM_NETCAM_PRO:
-               cit_init_ibm_netcam_pro(gspca_dev);
-               sd_stop0(gspca_dev);
-               break;
-       }
-       return 0;
-}
-
-static int cit_set_brightness(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i;
-
-       switch (sd->model) {
-       case CIT_MODEL0:
-       case CIT_IBM_NETCAM_PRO:
-               /* No (known) brightness control for these */
-               break;
-       case CIT_MODEL1:
-               /* Model 1: Brightness range 0 - 63 */
-               cit_Packet_Format1(gspca_dev, 0x0031, val);
-               cit_Packet_Format1(gspca_dev, 0x0032, val);
-               cit_Packet_Format1(gspca_dev, 0x0033, val);
-               break;
-       case CIT_MODEL2:
-               /* Model 2: Brightness range 0x60 - 0xee */
-               /* Scale 0 - 63 to 0x60 - 0xee */
-               i = 0x60 + val * 2254 / 1000;
-               cit_model2_Packet1(gspca_dev, 0x001a, i);
-               break;
-       case CIT_MODEL3:
-               /* Model 3: Brightness range 'i' in [0x0C..0x3F] */
-               i = val;
-               if (i < 0x0c)
-                       i = 0x0c;
-               cit_model3_Packet1(gspca_dev, 0x0036, i);
-               break;
-       case CIT_MODEL4:
-               /* Model 4: Brightness range 'i' in [0x04..0xb4] */
-               /* Scale 0 - 63 to 0x04 - 0xb4 */
-               i = 0x04 + val * 2794 / 1000;
-               cit_model4_BrightnessPacket(gspca_dev, i);
-               break;
-       }
-
-       return 0;
-}
-
-static int cit_set_contrast(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->model) {
-       case CIT_MODEL0: {
-               int i;
-               /* gain 0-15, 0-20 -> 0-15 */
-               i = val * 1000 / 1333;
-               cit_write_reg(gspca_dev, i, 0x0422);
-               /* gain 0-31, may not be lower then 0x0422, 0-20 -> 0-31 */
-               i = val * 2000 / 1333;
-               cit_write_reg(gspca_dev, i, 0x0423);
-               /* gain 0-127, may not be lower then 0x0423, 0-20 -> 0-63  */
-               i = val * 4000 / 1333;
-               cit_write_reg(gspca_dev, i, 0x0424);
-               /* gain 0-127, may not be lower then 0x0424, , 0-20 -> 0-127 */
-               i = val * 8000 / 1333;
-               cit_write_reg(gspca_dev, i, 0x0425);
-               break;
-       }
-       case CIT_MODEL2:
-       case CIT_MODEL4:
-               /* These models do not have this control. */
-               break;
-       case CIT_MODEL1:
-       {
-               /* Scale 0 - 20 to 15 - 0 */
-               int i, new_contrast = (20 - val) * 1000 / 1333;
-               for (i = 0; i < cit_model1_ntries; i++) {
-                       cit_Packet_Format1(gspca_dev, 0x0014, new_contrast);
-                       cit_send_FF_04_02(gspca_dev);
-               }
-               break;
-       }
-       case CIT_MODEL3:
-       {       /* Preset hardware values */
-               static const struct {
-                       unsigned short cv1;
-                       unsigned short cv2;
-                       unsigned short cv3;
-               } cv[7] = {
-                       { 0x05, 0x05, 0x0f },   /* Minimum */
-                       { 0x04, 0x04, 0x16 },
-                       { 0x02, 0x03, 0x16 },
-                       { 0x02, 0x08, 0x16 },
-                       { 0x01, 0x0c, 0x16 },
-                       { 0x01, 0x0e, 0x16 },
-                       { 0x01, 0x10, 0x16 }    /* Maximum */
-               };
-               int i = val / 3;
-               cit_model3_Packet1(gspca_dev, 0x0067, cv[i].cv1);
-               cit_model3_Packet1(gspca_dev, 0x005b, cv[i].cv2);
-               cit_model3_Packet1(gspca_dev, 0x005c, cv[i].cv3);
-               break;
-       }
-       case CIT_IBM_NETCAM_PRO:
-               cit_model3_Packet1(gspca_dev, 0x005b, val + 1);
-               break;
-       }
-       return 0;
-}
-
-static int cit_set_hue(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->model) {
-       case CIT_MODEL0:
-       case CIT_MODEL1:
-       case CIT_IBM_NETCAM_PRO:
-               /* No hue control for these models */
-               break;
-       case CIT_MODEL2:
-               cit_model2_Packet1(gspca_dev, 0x0024, val);
-               /* cit_model2_Packet1(gspca_dev, 0x0020, sat); */
-               break;
-       case CIT_MODEL3: {
-               /* Model 3: Brightness range 'i' in [0x05..0x37] */
-               /* TESTME according to the ibmcam driver this does not work */
-               if (0) {
-                       /* Scale 0 - 127 to 0x05 - 0x37 */
-                       int i = 0x05 + val * 1000 / 2540;
-                       cit_model3_Packet1(gspca_dev, 0x007e, i);
-               }
-               break;
-       }
-       case CIT_MODEL4:
-               /* HDG: taken from ibmcam, setting the color gains does not
-                * really belong here.
-                *
-                * I am not sure r/g/b_gain variables exactly control gain
-                * of those channels. Most likely they subtly change some
-                * very internal image processing settings in the camera.
-                * In any case, here is what they do, and feel free to tweak:
-                *
-                * r_gain: seriously affects red gain
-                * g_gain: seriously affects green gain
-                * b_gain: seriously affects blue gain
-                * hue: changes average color from violet (0) to red (0xFF)
-                */
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x001e, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev,    160, 0x0127);  /* Green gain */
-               cit_write_reg(gspca_dev,    160, 0x012e);  /* Red gain */
-               cit_write_reg(gspca_dev,    160, 0x0130);  /* Blue gain */
-               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
-               cit_write_reg(gspca_dev, val, 0x012d); /* Hue */
-               cit_write_reg(gspca_dev, 0xf545, 0x0124);
-               break;
-       }
-       return 0;
-}
-
-static int cit_set_sharpness(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->model) {
-       case CIT_MODEL0:
-       case CIT_MODEL2:
-       case CIT_MODEL4:
-       case CIT_IBM_NETCAM_PRO:
-               /* These models do not have this control */
-               break;
-       case CIT_MODEL1: {
-               int i;
-               const unsigned short sa[] = {
-                       0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a };
-
-               for (i = 0; i < cit_model1_ntries; i++)
-                       cit_PacketFormat2(gspca_dev, 0x0013, sa[val]);
-               break;
-       }
-       case CIT_MODEL3:
-       {       /*
-                * "Use a table of magic numbers.
-                *  This setting doesn't really change much.
-                *  But that's how Windows does it."
-                */
-               static const struct {
-                       unsigned short sv1;
-                       unsigned short sv2;
-                       unsigned short sv3;
-                       unsigned short sv4;
-               } sv[7] = {
-                       { 0x00, 0x00, 0x05, 0x14 },     /* Smoothest */
-                       { 0x01, 0x04, 0x05, 0x14 },
-                       { 0x02, 0x04, 0x05, 0x14 },
-                       { 0x03, 0x04, 0x05, 0x14 },
-                       { 0x03, 0x05, 0x05, 0x14 },
-                       { 0x03, 0x06, 0x05, 0x14 },
-                       { 0x03, 0x07, 0x05, 0x14 }      /* Sharpest */
-               };
-               cit_model3_Packet1(gspca_dev, 0x0060, sv[val].sv1);
-               cit_model3_Packet1(gspca_dev, 0x0061, sv[val].sv2);
-               cit_model3_Packet1(gspca_dev, 0x0062, sv[val].sv3);
-               cit_model3_Packet1(gspca_dev, 0x0063, sv[val].sv4);
-               break;
-       }
-       }
-       return 0;
-}
-
-/*
- * cit_set_lighting()
- *
- * Camera model 1:
- * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low.
- *
- * Camera model 2:
- * We have 16 levels of lighting, 0 for bright light and up to 15 for
- * low light. But values above 5 or so are useless because camera is
- * not really capable to produce anything worth viewing at such light.
- * This setting may be altered only in certain camera state.
- *
- * Low lighting forces slower FPS.
- *
- * History:
- * 1/5/00   Created.
- * 2/20/00  Added support for Model 2 cameras.
- */
-static void cit_set_lighting(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->model) {
-       case CIT_MODEL0:
-       case CIT_MODEL2:
-       case CIT_MODEL3:
-       case CIT_MODEL4:
-       case CIT_IBM_NETCAM_PRO:
-               break;
-       case CIT_MODEL1: {
-               int i;
-               for (i = 0; i < cit_model1_ntries; i++)
-                       cit_Packet_Format1(gspca_dev, 0x0027, val);
-               break;
-       }
-       }
-}
-
-static void cit_set_hflip(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->model) {
-       case CIT_MODEL0:
-               if (val)
-                       cit_write_reg(gspca_dev, 0x0020, 0x0115);
-               else
-                       cit_write_reg(gspca_dev, 0x0040, 0x0115);
-               break;
-       case CIT_MODEL1:
-       case CIT_MODEL2:
-       case CIT_MODEL3:
-       case CIT_MODEL4:
-       case CIT_IBM_NETCAM_PRO:
-               break;
-       }
-}
-
-static int cit_restart_stream(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       switch (sd->model) {
-       case CIT_MODEL0:
-       case CIT_MODEL1:
-               cit_write_reg(gspca_dev, 0x0001, 0x0114);
-               /* Fall through */
-       case CIT_MODEL2:
-       case CIT_MODEL4:
-               cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */
-               usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
-               break;
-       case CIT_MODEL3:
-       case CIT_IBM_NETCAM_PRO:
-               cit_write_reg(gspca_dev, 0x0001, 0x0114);
-               cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */
-               usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
-               /* Clear button events from while we were not streaming */
-               cit_write_reg(gspca_dev, 0x0001, 0x0113);
-               break;
-       }
-
-       sd->sof_read = 0;
-
-       return 0;
-}
-
-static int cit_get_packet_size(struct gspca_dev *gspca_dev)
-{
-       struct usb_host_interface *alt;
-       struct usb_interface *intf;
-
-       intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface);
-       alt = usb_altnum_to_altsetting(intf, gspca_dev->alt);
-       if (!alt) {
-               pr_err("Couldn't get altsetting\n");
-               return -EIO;
-       }
-
-       return le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
-}
-
-/* Calculate the clockdiv giving us max fps given the available bandwidth */
-static int cit_get_clock_div(struct gspca_dev *gspca_dev)
-{
-       int clock_div = 7; /* 0=30 1=25 2=20 3=15 4=12 5=7.5 6=6 7=3fps ?? */
-       int fps[8] = { 30, 25, 20, 15, 12, 8, 6, 3 };
-       int packet_size;
-
-       packet_size = cit_get_packet_size(gspca_dev);
-       if (packet_size < 0)
-               return packet_size;
-
-       while (clock_div > 3 &&
-                       1000 * packet_size >
-                       gspca_dev->width * gspca_dev->height *
-                       fps[clock_div - 1] * 3 / 2)
-               clock_div--;
-
-       PDEBUG(D_PROBE,
-              "PacketSize: %d, res: %dx%d -> using clockdiv: %d (%d fps)",
-              packet_size, gspca_dev->width, gspca_dev->height, clock_div,
-              fps[clock_div]);
-
-       return clock_div;
-}
-
-static int cit_start_model0(struct gspca_dev *gspca_dev)
-{
-       const unsigned short compression = 0; /* 0=none, 7=best frame rate */
-       int clock_div;
-
-       clock_div = cit_get_clock_div(gspca_dev);
-       if (clock_div < 0)
-               return clock_div;
-
-       cit_write_reg(gspca_dev, 0x0000, 0x0100); /* turn on led */
-       cit_write_reg(gspca_dev, 0x0003, 0x0438);
-       cit_write_reg(gspca_dev, 0x001e, 0x042b);
-       cit_write_reg(gspca_dev, 0x0041, 0x042c);
-       cit_write_reg(gspca_dev, 0x0008, 0x0436);
-       cit_write_reg(gspca_dev, 0x0024, 0x0403);
-       cit_write_reg(gspca_dev, 0x002c, 0x0404);
-       cit_write_reg(gspca_dev, 0x0002, 0x0426);
-       cit_write_reg(gspca_dev, 0x0014, 0x0427);
-
-       switch (gspca_dev->width) {
-       case 160: /* 160x120 */
-               cit_write_reg(gspca_dev, 0x0004, 0x010b);
-               cit_write_reg(gspca_dev, 0x0001, 0x010a);
-               cit_write_reg(gspca_dev, 0x0010, 0x0102);
-               cit_write_reg(gspca_dev, 0x00a0, 0x0103);
-               cit_write_reg(gspca_dev, 0x0000, 0x0104);
-               cit_write_reg(gspca_dev, 0x0078, 0x0105);
-               break;
-
-       case 176: /* 176x144 */
-               cit_write_reg(gspca_dev, 0x0006, 0x010b);
-               cit_write_reg(gspca_dev, 0x0000, 0x010a);
-               cit_write_reg(gspca_dev, 0x0005, 0x0102);
-               cit_write_reg(gspca_dev, 0x00b0, 0x0103);
-               cit_write_reg(gspca_dev, 0x0000, 0x0104);
-               cit_write_reg(gspca_dev, 0x0090, 0x0105);
-               break;
-
-       case 320: /* 320x240 */
-               cit_write_reg(gspca_dev, 0x0008, 0x010b);
-               cit_write_reg(gspca_dev, 0x0004, 0x010a);
-               cit_write_reg(gspca_dev, 0x0005, 0x0102);
-               cit_write_reg(gspca_dev, 0x00a0, 0x0103);
-               cit_write_reg(gspca_dev, 0x0010, 0x0104);
-               cit_write_reg(gspca_dev, 0x0078, 0x0105);
-               break;
-       }
-
-       cit_write_reg(gspca_dev, compression, 0x0109);
-       cit_write_reg(gspca_dev, clock_div, 0x0111);
-
-       return 0;
-}
-
-static int cit_start_model1(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i, clock_div;
-
-       clock_div = cit_get_clock_div(gspca_dev);
-       if (clock_div < 0)
-               return clock_div;
-
-       cit_read_reg(gspca_dev, 0x0128, 1);
-       cit_read_reg(gspca_dev, 0x0100, 0);
-       cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On  */
-       cit_read_reg(gspca_dev, 0x0100, 0);
-       cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */
-       cit_read_reg(gspca_dev, 0x0100, 0);
-       cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On  */
-       cit_write_reg(gspca_dev, 0x01, 0x0108);
-
-       cit_write_reg(gspca_dev, 0x03, 0x0112);
-       cit_read_reg(gspca_dev, 0x0115, 0);
-       cit_write_reg(gspca_dev, 0x06, 0x0115);
-       cit_read_reg(gspca_dev, 0x0116, 0);
-       cit_write_reg(gspca_dev, 0x44, 0x0116);
-       cit_read_reg(gspca_dev, 0x0116, 0);
-       cit_write_reg(gspca_dev, 0x40, 0x0116);
-       cit_read_reg(gspca_dev, 0x0115, 0);
-       cit_write_reg(gspca_dev, 0x0e, 0x0115);
-       cit_write_reg(gspca_dev, 0x19, 0x012c);
-
-       cit_Packet_Format1(gspca_dev, 0x00, 0x1e);
-       cit_Packet_Format1(gspca_dev, 0x39, 0x0d);
-       cit_Packet_Format1(gspca_dev, 0x39, 0x09);
-       cit_Packet_Format1(gspca_dev, 0x3b, 0x00);
-       cit_Packet_Format1(gspca_dev, 0x28, 0x22);
-       cit_Packet_Format1(gspca_dev, 0x27, 0x00);
-       cit_Packet_Format1(gspca_dev, 0x2b, 0x1f);
-       cit_Packet_Format1(gspca_dev, 0x39, 0x08);
-
-       for (i = 0; i < cit_model1_ntries; i++)
-               cit_Packet_Format1(gspca_dev, 0x2c, 0x00);
-
-       for (i = 0; i < cit_model1_ntries; i++)
-               cit_Packet_Format1(gspca_dev, 0x30, 0x14);
-
-       cit_PacketFormat2(gspca_dev, 0x39, 0x02);
-       cit_PacketFormat2(gspca_dev, 0x01, 0xe1);
-       cit_PacketFormat2(gspca_dev, 0x02, 0xcd);
-       cit_PacketFormat2(gspca_dev, 0x03, 0xcd);
-       cit_PacketFormat2(gspca_dev, 0x04, 0xfa);
-       cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
-       cit_PacketFormat2(gspca_dev, 0x39, 0x00);
-
-       cit_PacketFormat2(gspca_dev, 0x39, 0x02);
-       cit_PacketFormat2(gspca_dev, 0x0a, 0x37);
-       cit_PacketFormat2(gspca_dev, 0x0b, 0xb8);
-       cit_PacketFormat2(gspca_dev, 0x0c, 0xf3);
-       cit_PacketFormat2(gspca_dev, 0x0d, 0xe3);
-       cit_PacketFormat2(gspca_dev, 0x0e, 0x0d);
-       cit_PacketFormat2(gspca_dev, 0x0f, 0xf2);
-       cit_PacketFormat2(gspca_dev, 0x10, 0xd5);
-       cit_PacketFormat2(gspca_dev, 0x11, 0xba);
-       cit_PacketFormat2(gspca_dev, 0x12, 0x53);
-       cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
-       cit_PacketFormat2(gspca_dev, 0x39, 0x00);
-
-       cit_PacketFormat2(gspca_dev, 0x39, 0x02);
-       cit_PacketFormat2(gspca_dev, 0x16, 0x00);
-       cit_PacketFormat2(gspca_dev, 0x17, 0x28);
-       cit_PacketFormat2(gspca_dev, 0x18, 0x7d);
-       cit_PacketFormat2(gspca_dev, 0x19, 0xbe);
-       cit_PacketFormat2(gspca_dev, 0x3f, 0xff);
-       cit_PacketFormat2(gspca_dev, 0x39, 0x00);
-
-       for (i = 0; i < cit_model1_ntries; i++)
-               cit_Packet_Format1(gspca_dev, 0x00, 0x18);
-       for (i = 0; i < cit_model1_ntries; i++)
-               cit_Packet_Format1(gspca_dev, 0x13, 0x18);
-       for (i = 0; i < cit_model1_ntries; i++)
-               cit_Packet_Format1(gspca_dev, 0x14, 0x06);
-
-       /* TESTME These are handled through controls
-          KEEP until someone can test leaving this out is ok */
-       if (0) {
-               /* This is default brightness */
-               for (i = 0; i < cit_model1_ntries; i++)
-                       cit_Packet_Format1(gspca_dev, 0x31, 0x37);
-               for (i = 0; i < cit_model1_ntries; i++)
-                       cit_Packet_Format1(gspca_dev, 0x32, 0x46);
-               for (i = 0; i < cit_model1_ntries; i++)
-                       cit_Packet_Format1(gspca_dev, 0x33, 0x55);
-       }
-
-       cit_Packet_Format1(gspca_dev, 0x2e, 0x04);
-       for (i = 0; i < cit_model1_ntries; i++)
-               cit_Packet_Format1(gspca_dev, 0x2d, 0x04);
-       for (i = 0; i < cit_model1_ntries; i++)
-               cit_Packet_Format1(gspca_dev, 0x29, 0x80);
-       cit_Packet_Format1(gspca_dev, 0x2c, 0x01);
-       cit_Packet_Format1(gspca_dev, 0x30, 0x17);
-       cit_Packet_Format1(gspca_dev, 0x39, 0x08);
-       for (i = 0; i < cit_model1_ntries; i++)
-               cit_Packet_Format1(gspca_dev, 0x34, 0x00);
-
-       cit_write_reg(gspca_dev, 0x00, 0x0101);
-       cit_write_reg(gspca_dev, 0x00, 0x010a);
-
-       switch (gspca_dev->width) {
-       case 128: /* 128x96 */
-               cit_write_reg(gspca_dev, 0x80, 0x0103);
-               cit_write_reg(gspca_dev, 0x60, 0x0105);
-               cit_write_reg(gspca_dev, 0x0c, 0x010b);
-               cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x0b, 0x011d);
-               cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x00, 0x0129);
-               break;
-       case 176: /* 176x144 */
-               cit_write_reg(gspca_dev, 0xb0, 0x0103);
-               cit_write_reg(gspca_dev, 0x8f, 0x0105);
-               cit_write_reg(gspca_dev, 0x06, 0x010b);
-               cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x0d, 0x011d);
-               cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x03, 0x0129);
-               break;
-       case 352: /* 352x288 */
-               cit_write_reg(gspca_dev, 0xb0, 0x0103);
-               cit_write_reg(gspca_dev, 0x90, 0x0105);
-               cit_write_reg(gspca_dev, 0x02, 0x010b);
-               cit_write_reg(gspca_dev, 0x04, 0x011b); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x05, 0x011d);
-               cit_write_reg(gspca_dev, 0x00, 0x011e); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x00, 0x0129);
-               break;
-       }
-
-       cit_write_reg(gspca_dev, 0xff, 0x012b);
-
-       /* TESTME These are handled through controls
-          KEEP until someone can test leaving this out is ok */
-       if (0) {
-               /* This is another brightness - don't know why */
-               for (i = 0; i < cit_model1_ntries; i++)
-                       cit_Packet_Format1(gspca_dev, 0x31, 0xc3);
-               for (i = 0; i < cit_model1_ntries; i++)
-                       cit_Packet_Format1(gspca_dev, 0x32, 0xd2);
-               for (i = 0; i < cit_model1_ntries; i++)
-                       cit_Packet_Format1(gspca_dev, 0x33, 0xe1);
-
-               /* Default contrast */
-               for (i = 0; i < cit_model1_ntries; i++)
-                       cit_Packet_Format1(gspca_dev, 0x14, 0x0a);
-
-               /* Default sharpness */
-               for (i = 0; i < cit_model1_ntries2; i++)
-                       cit_PacketFormat2(gspca_dev, 0x13, 0x1a);
-
-               /* Default lighting conditions */
-               cit_Packet_Format1(gspca_dev, 0x0027,
-                                  v4l2_ctrl_g_ctrl(sd->lighting));
-       }
-
-       /* Assorted init */
-       switch (gspca_dev->width) {
-       case 128: /* 128x96 */
-               cit_Packet_Format1(gspca_dev, 0x2b, 0x1e);
-               cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x36, 0x0102);
-               cit_write_reg(gspca_dev, 0x1a, 0x0104);
-               cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x2b, 0x011c);
-               cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
-               break;
-       case 176: /* 176x144 */
-               cit_Packet_Format1(gspca_dev, 0x2b, 0x1e);
-               cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x04, 0x0102);
-               cit_write_reg(gspca_dev, 0x02, 0x0104);
-               cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x2b, 0x011c);
-               cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
-               break;
-       case 352: /* 352x288 */
-               cit_Packet_Format1(gspca_dev, 0x2b, 0x1f);
-               cit_write_reg(gspca_dev, 0xc9, 0x0119); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x80, 0x0109); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x08, 0x0102);
-               cit_write_reg(gspca_dev, 0x01, 0x0104);
-               cit_write_reg(gspca_dev, 0x04, 0x011a); /* Same everywhere */
-               cit_write_reg(gspca_dev, 0x2f, 0x011c);
-               cit_write_reg(gspca_dev, 0x23, 0x012a); /* Same everywhere */
-               break;
-       }
-
-       cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On  */
-       cit_write_reg(gspca_dev, clock_div, 0x0111);
-
-       return 0;
-}
-
-static int cit_start_model2(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int clock_div = 0;
-
-       cit_write_reg(gspca_dev, 0x0000, 0x0100);       /* LED on */
-       cit_read_reg(gspca_dev, 0x0116, 0);
-       cit_write_reg(gspca_dev, 0x0060, 0x0116);
-       cit_write_reg(gspca_dev, 0x0002, 0x0112);
-       cit_write_reg(gspca_dev, 0x00bc, 0x012c);
-       cit_write_reg(gspca_dev, 0x0008, 0x012b);
-       cit_write_reg(gspca_dev, 0x0000, 0x0108);
-       cit_write_reg(gspca_dev, 0x0001, 0x0133);
-       cit_write_reg(gspca_dev, 0x0001, 0x0102);
-       switch (gspca_dev->width) {
-       case 176: /* 176x144 */
-               cit_write_reg(gspca_dev, 0x002c, 0x0103);       /* All except 320x240 */
-               cit_write_reg(gspca_dev, 0x0000, 0x0104);       /* Same */
-               cit_write_reg(gspca_dev, 0x0024, 0x0105);       /* 176x144, 352x288 */
-               cit_write_reg(gspca_dev, 0x00b9, 0x010a);       /* Unique to this mode */
-               cit_write_reg(gspca_dev, 0x0038, 0x0119);       /* Unique to this mode */
-               /* TESTME HDG: this does not seem right
-                  (it is 2 for all other resolutions) */
-               sd->sof_len = 10;
-               break;
-       case 320: /* 320x240 */
-               cit_write_reg(gspca_dev, 0x0028, 0x0103);       /* Unique to this mode */
-               cit_write_reg(gspca_dev, 0x0000, 0x0104);       /* Same */
-               cit_write_reg(gspca_dev, 0x001e, 0x0105);       /* 320x240, 352x240 */
-               cit_write_reg(gspca_dev, 0x0039, 0x010a);       /* All except 176x144 */
-               cit_write_reg(gspca_dev, 0x0070, 0x0119);       /* All except 176x144 */
-               sd->sof_len = 2;
-               break;
-       /* case VIDEOSIZE_352x240: */
-               cit_write_reg(gspca_dev, 0x002c, 0x0103);       /* All except 320x240 */
-               cit_write_reg(gspca_dev, 0x0000, 0x0104);       /* Same */
-               cit_write_reg(gspca_dev, 0x001e, 0x0105);       /* 320x240, 352x240 */
-               cit_write_reg(gspca_dev, 0x0039, 0x010a);       /* All except 176x144 */
-               cit_write_reg(gspca_dev, 0x0070, 0x0119);       /* All except 176x144 */
-               sd->sof_len = 2;
-               break;
-       case 352: /* 352x288 */
-               cit_write_reg(gspca_dev, 0x002c, 0x0103);       /* All except 320x240 */
-               cit_write_reg(gspca_dev, 0x0000, 0x0104);       /* Same */
-               cit_write_reg(gspca_dev, 0x0024, 0x0105);       /* 176x144, 352x288 */
-               cit_write_reg(gspca_dev, 0x0039, 0x010a);       /* All except 176x144 */
-               cit_write_reg(gspca_dev, 0x0070, 0x0119);       /* All except 176x144 */
-               sd->sof_len = 2;
-               break;
-       }
-
-       cit_write_reg(gspca_dev, 0x0000, 0x0100);       /* LED on */
-
-       switch (gspca_dev->width) {
-       case 176: /* 176x144 */
-               cit_write_reg(gspca_dev, 0x0050, 0x0111);
-               cit_write_reg(gspca_dev, 0x00d0, 0x0111);
-               break;
-       case 320: /* 320x240 */
-       case 352: /* 352x288 */
-               cit_write_reg(gspca_dev, 0x0040, 0x0111);
-               cit_write_reg(gspca_dev, 0x00c0, 0x0111);
-               break;
-       }
-       cit_write_reg(gspca_dev, 0x009b, 0x010f);
-       cit_write_reg(gspca_dev, 0x00bb, 0x010f);
-
-       /*
-        * Hardware settings, may affect CMOS sensor; not user controls!
-        * -------------------------------------------------------------
-        * 0x0004: no effect
-        * 0x0006: hardware effect
-        * 0x0008: no effect
-        * 0x000a: stops video stream, probably important h/w setting
-        * 0x000c: changes color in hardware manner (not user setting)
-        * 0x0012: changes number of colors (does not affect speed)
-        * 0x002a: no effect
-        * 0x002c: hardware setting (related to scan lines)
-        * 0x002e: stops video stream, probably important h/w setting
-        */
-       cit_model2_Packet1(gspca_dev, 0x000a, 0x005c);
-       cit_model2_Packet1(gspca_dev, 0x0004, 0x0000);
-       cit_model2_Packet1(gspca_dev, 0x0006, 0x00fb);
-       cit_model2_Packet1(gspca_dev, 0x0008, 0x0000);
-       cit_model2_Packet1(gspca_dev, 0x000c, 0x0009);
-       cit_model2_Packet1(gspca_dev, 0x0012, 0x000a);
-       cit_model2_Packet1(gspca_dev, 0x002a, 0x0000);
-       cit_model2_Packet1(gspca_dev, 0x002c, 0x0000);
-       cit_model2_Packet1(gspca_dev, 0x002e, 0x0008);
-
-       /*
-        * Function 0x0030 pops up all over the place. Apparently
-        * it is a hardware control register, with every bit assigned to
-        * do something.
-        */
-       cit_model2_Packet1(gspca_dev, 0x0030, 0x0000);
-
-       /*
-        * Magic control of CMOS sensor. Only lower values like
-        * 0-3 work, and picture shifts left or right. Don't change.
-        */
-       switch (gspca_dev->width) {
-       case 176: /* 176x144 */
-               cit_model2_Packet1(gspca_dev, 0x0014, 0x0002);
-               cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */
-               cit_model2_Packet1(gspca_dev, 0x0018, 0x004a); /* Another hardware setting */
-               clock_div = 6;
-               break;
-       case 320: /* 320x240 */
-               cit_model2_Packet1(gspca_dev, 0x0014, 0x0009);
-               cit_model2_Packet1(gspca_dev, 0x0016, 0x0005); /* Horizontal shift */
-               cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Another hardware setting */
-               clock_div = 8;
-               break;
-       /* case VIDEOSIZE_352x240: */
-               /* This mode doesn't work as Windows programs it; changed to work */
-               cit_model2_Packet1(gspca_dev, 0x0014, 0x0009); /* Windows sets this to 8 */
-               cit_model2_Packet1(gspca_dev, 0x0016, 0x0003); /* Horizontal shift */
-               cit_model2_Packet1(gspca_dev, 0x0018, 0x0044); /* Windows sets this to 0x0045 */
-               clock_div = 10;
-               break;
-       case 352: /* 352x288 */
-               cit_model2_Packet1(gspca_dev, 0x0014, 0x0003);
-               cit_model2_Packet1(gspca_dev, 0x0016, 0x0002); /* Horizontal shift */
-               cit_model2_Packet1(gspca_dev, 0x0018, 0x004a); /* Another hardware setting */
-               clock_div = 16;
-               break;
-       }
-
-       /* TESTME These are handled through controls
-          KEEP until someone can test leaving this out is ok */
-       if (0)
-               cit_model2_Packet1(gspca_dev, 0x001a, 0x005a);
-
-       /*
-        * We have our own frame rate setting varying from 0 (slowest) to 6
-        * (fastest). The camera model 2 allows frame rate in range [0..0x1F]
-        # where 0 is also the slowest setting. However for all practical
-        # reasons high settings make no sense because USB is not fast enough
-        # to support high FPS. Be aware that the picture datastream will be
-        # severely disrupted if you ask for frame rate faster than allowed
-        # for the video size - see below:
-        *
-        * Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz):
-        * -----------------------------------------------------------------
-        * 176x144: [6..31]
-        * 320x240: [8..31]
-        * 352x240: [10..31]
-        * 352x288: [16..31] I have to raise lower threshold for stability...
-        *
-        * As usual, slower FPS provides better sensitivity.
-        */
-       cit_model2_Packet1(gspca_dev, 0x001c, clock_div);
-
-       /*
-        * This setting does not visibly affect pictures; left it here
-        * because it was present in Windows USB data stream. This function
-        * does not allow arbitrary values and apparently is a bit mask, to
-        * be activated only at appropriate time. Don't change it randomly!
-        */
-       switch (gspca_dev->width) {
-       case 176: /* 176x144 */
-               cit_model2_Packet1(gspca_dev, 0x0026, 0x00c2);
-               break;
-       case 320: /* 320x240 */
-               cit_model2_Packet1(gspca_dev, 0x0026, 0x0044);
-               break;
-       /* case VIDEOSIZE_352x240: */
-               cit_model2_Packet1(gspca_dev, 0x0026, 0x0046);
-               break;
-       case 352: /* 352x288 */
-               cit_model2_Packet1(gspca_dev, 0x0026, 0x0048);
-               break;
-       }
-
-       cit_model2_Packet1(gspca_dev, 0x0028, v4l2_ctrl_g_ctrl(sd->lighting));
-       /* model2 cannot change the backlight compensation while streaming */
-       v4l2_ctrl_grab(sd->lighting, true);
-
-       /* color balance rg2 */
-       cit_model2_Packet1(gspca_dev, 0x001e, 0x002f);
-       /* saturation */
-       cit_model2_Packet1(gspca_dev, 0x0020, 0x0034);
-       /* color balance yb */
-       cit_model2_Packet1(gspca_dev, 0x0022, 0x00a0);
-
-       /* Hardware control command */
-       cit_model2_Packet1(gspca_dev, 0x0030, 0x0004);
-
-       return 0;
-}
-
-static int cit_start_model3(struct gspca_dev *gspca_dev)
-{
-       const unsigned short compression = 0; /* 0=none, 7=best frame rate */
-       int i, clock_div = 0;
-
-       /* HDG not in ibmcam driver, added to see if it helps with
-          auto-detecting between model3 and ibm netcamera pro */
-       cit_read_reg(gspca_dev, 0x128, 1);
-
-       cit_write_reg(gspca_dev, 0x0000, 0x0100);
-       cit_read_reg(gspca_dev, 0x0116, 0);
-       cit_write_reg(gspca_dev, 0x0060, 0x0116);
-       cit_write_reg(gspca_dev, 0x0002, 0x0112);
-       cit_write_reg(gspca_dev, 0x0000, 0x0123);
-       cit_write_reg(gspca_dev, 0x0001, 0x0117);
-       cit_write_reg(gspca_dev, 0x0040, 0x0108);
-       cit_write_reg(gspca_dev, 0x0019, 0x012c);
-       cit_write_reg(gspca_dev, 0x0060, 0x0116);
-       cit_write_reg(gspca_dev, 0x0002, 0x0115);
-       cit_write_reg(gspca_dev, 0x0003, 0x0115);
-       cit_read_reg(gspca_dev, 0x0115, 0);
-       cit_write_reg(gspca_dev, 0x000b, 0x0115);
-
-       /* TESTME HDG not in ibmcam driver, added to see if it helps with
-          auto-detecting between model3 and ibm netcamera pro */
-       if (0) {
-               cit_write_reg(gspca_dev, 0x0078, 0x012d);
-               cit_write_reg(gspca_dev, 0x0001, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x0079, 0x012d);
-               cit_write_reg(gspca_dev, 0x00ff, 0x0130);
-               cit_write_reg(gspca_dev, 0xcd41, 0x0124);
-               cit_write_reg(gspca_dev, 0xfffa, 0x0124);
-               cit_read_reg(gspca_dev, 0x0126, 1);
-       }
-
-       cit_model3_Packet1(gspca_dev, 0x000a, 0x0040);
-       cit_model3_Packet1(gspca_dev, 0x000b, 0x00f6);
-       cit_model3_Packet1(gspca_dev, 0x000c, 0x0002);
-       cit_model3_Packet1(gspca_dev, 0x000d, 0x0020);
-       cit_model3_Packet1(gspca_dev, 0x000e, 0x0033);
-       cit_model3_Packet1(gspca_dev, 0x000f, 0x0007);
-       cit_model3_Packet1(gspca_dev, 0x0010, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0011, 0x0070);
-       cit_model3_Packet1(gspca_dev, 0x0012, 0x0030);
-       cit_model3_Packet1(gspca_dev, 0x0013, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0014, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x0015, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x0016, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x0017, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x0018, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x001e, 0x00c3);
-       cit_model3_Packet1(gspca_dev, 0x0020, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0028, 0x0010);
-       cit_model3_Packet1(gspca_dev, 0x0029, 0x0054);
-       cit_model3_Packet1(gspca_dev, 0x002a, 0x0013);
-       cit_model3_Packet1(gspca_dev, 0x002b, 0x0007);
-       cit_model3_Packet1(gspca_dev, 0x002d, 0x0028);
-       cit_model3_Packet1(gspca_dev, 0x002e, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0031, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0032, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0033, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0034, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0035, 0x0038);
-       cit_model3_Packet1(gspca_dev, 0x003a, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x003c, 0x001e);
-       cit_model3_Packet1(gspca_dev, 0x003f, 0x000a);
-       cit_model3_Packet1(gspca_dev, 0x0041, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0046, 0x003f);
-       cit_model3_Packet1(gspca_dev, 0x0047, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0050, 0x0005);
-       cit_model3_Packet1(gspca_dev, 0x0052, 0x001a);
-       cit_model3_Packet1(gspca_dev, 0x0053, 0x0003);
-       cit_model3_Packet1(gspca_dev, 0x005a, 0x006b);
-       cit_model3_Packet1(gspca_dev, 0x005d, 0x001e);
-       cit_model3_Packet1(gspca_dev, 0x005e, 0x0030);
-       cit_model3_Packet1(gspca_dev, 0x005f, 0x0041);
-       cit_model3_Packet1(gspca_dev, 0x0064, 0x0008);
-       cit_model3_Packet1(gspca_dev, 0x0065, 0x0015);
-       cit_model3_Packet1(gspca_dev, 0x0068, 0x000f);
-       cit_model3_Packet1(gspca_dev, 0x0079, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x007a, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x007c, 0x003f);
-       cit_model3_Packet1(gspca_dev, 0x0082, 0x000f);
-       cit_model3_Packet1(gspca_dev, 0x0085, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0099, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x009b, 0x0023);
-       cit_model3_Packet1(gspca_dev, 0x009c, 0x0022);
-       cit_model3_Packet1(gspca_dev, 0x009d, 0x0096);
-       cit_model3_Packet1(gspca_dev, 0x009e, 0x0096);
-       cit_model3_Packet1(gspca_dev, 0x009f, 0x000a);
-
-       switch (gspca_dev->width) {
-       case 160:
-               cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
-               cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
-               cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
-               cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
-               cit_write_reg(gspca_dev, 0x0024, 0x010b); /* Differs everywhere */
-               cit_write_reg(gspca_dev, 0x00a9, 0x0119);
-               cit_write_reg(gspca_dev, 0x0016, 0x011b);
-               cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same on 160x120, 320x240 */
-               cit_write_reg(gspca_dev, 0x0003, 0x011e); /* Same on 160x120, 640x480 */
-               cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
-               cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
-               cit_write_reg(gspca_dev, 0x0018, 0x0102);
-               cit_write_reg(gspca_dev, 0x0004, 0x0104);
-               cit_write_reg(gspca_dev, 0x0004, 0x011a);
-               cit_write_reg(gspca_dev, 0x0028, 0x011c);
-               cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
-               cit_write_reg(gspca_dev, 0x0000, 0x0118);
-               cit_write_reg(gspca_dev, 0x0000, 0x0132);
-               cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
-               cit_write_reg(gspca_dev, compression, 0x0109);
-               clock_div = 3;
-               break;
-       case 320:
-               cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
-               cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
-               cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
-               cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
-               cit_write_reg(gspca_dev, 0x0028, 0x010b); /* Differs everywhere */
-               cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same */
-               cit_write_reg(gspca_dev, 0x0000, 0x011e);
-               cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
-               cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
-               /* 4 commands from 160x120 skipped */
-               cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
-               cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
-               cit_write_reg(gspca_dev, compression, 0x0109);
-               cit_write_reg(gspca_dev, 0x00d9, 0x0119);
-               cit_write_reg(gspca_dev, 0x0006, 0x011b);
-               cit_write_reg(gspca_dev, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
-               cit_write_reg(gspca_dev, 0x0010, 0x0104);
-               cit_write_reg(gspca_dev, 0x0004, 0x011a);
-               cit_write_reg(gspca_dev, 0x003f, 0x011c);
-               cit_write_reg(gspca_dev, 0x001c, 0x0118);
-               cit_write_reg(gspca_dev, 0x0000, 0x0132);
-               clock_div = 5;
-               break;
-       case 640:
-               cit_write_reg(gspca_dev, 0x00f0, 0x0105);
-               cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
-               cit_write_reg(gspca_dev, 0x0038, 0x010b); /* Differs everywhere */
-               cit_write_reg(gspca_dev, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */
-               cit_write_reg(gspca_dev, 0x0006, 0x011b); /* Same on 320x240, 640x480 */
-               cit_write_reg(gspca_dev, 0x0004, 0x011d); /* NC */
-               cit_write_reg(gspca_dev, 0x0003, 0x011e); /* Same on 160x120, 640x480 */
-               cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
-               cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
-               cit_write_reg(gspca_dev, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
-               cit_write_reg(gspca_dev, 0x0016, 0x0104); /* NC */
-               cit_write_reg(gspca_dev, 0x0004, 0x011a); /* Same on 320x240, 640x480 */
-               cit_write_reg(gspca_dev, 0x003f, 0x011c); /* Same on 320x240, 640x480 */
-               cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
-               cit_write_reg(gspca_dev, 0x001c, 0x0118); /* Same on 320x240, 640x480 */
-               cit_model3_Packet1(gspca_dev, 0x0021, 0x0001); /* Same */
-               cit_write_reg(gspca_dev, compression, 0x0109);
-               cit_write_reg(gspca_dev, 0x0040, 0x0101);
-               cit_write_reg(gspca_dev, 0x0040, 0x0103);
-               cit_write_reg(gspca_dev, 0x0000, 0x0132); /* Same on 320x240, 640x480 */
-               clock_div = 7;
-               break;
-       }
-
-       cit_model3_Packet1(gspca_dev, 0x007e, 0x000e);  /* Hue */
-       cit_model3_Packet1(gspca_dev, 0x0036, 0x0011);  /* Brightness */
-       cit_model3_Packet1(gspca_dev, 0x0060, 0x0002);  /* Sharpness */
-       cit_model3_Packet1(gspca_dev, 0x0061, 0x0004);  /* Sharpness */
-       cit_model3_Packet1(gspca_dev, 0x0062, 0x0005);  /* Sharpness */
-       cit_model3_Packet1(gspca_dev, 0x0063, 0x0014);  /* Sharpness */
-       cit_model3_Packet1(gspca_dev, 0x0096, 0x00a0);  /* Red sharpness */
-       cit_model3_Packet1(gspca_dev, 0x0097, 0x0096);  /* Blue sharpness */
-       cit_model3_Packet1(gspca_dev, 0x0067, 0x0001);  /* Contrast */
-       cit_model3_Packet1(gspca_dev, 0x005b, 0x000c);  /* Contrast */
-       cit_model3_Packet1(gspca_dev, 0x005c, 0x0016);  /* Contrast */
-       cit_model3_Packet1(gspca_dev, 0x0098, 0x000b);
-       cit_model3_Packet1(gspca_dev, 0x002c, 0x0003);  /* Was 1, broke 640x480 */
-       cit_model3_Packet1(gspca_dev, 0x002f, 0x002a);
-       cit_model3_Packet1(gspca_dev, 0x0030, 0x0029);
-       cit_model3_Packet1(gspca_dev, 0x0037, 0x0002);
-       cit_model3_Packet1(gspca_dev, 0x0038, 0x0059);
-       cit_model3_Packet1(gspca_dev, 0x003d, 0x002e);
-       cit_model3_Packet1(gspca_dev, 0x003e, 0x0028);
-       cit_model3_Packet1(gspca_dev, 0x0078, 0x0005);
-       cit_model3_Packet1(gspca_dev, 0x007b, 0x0011);
-       cit_model3_Packet1(gspca_dev, 0x007d, 0x004b);
-       cit_model3_Packet1(gspca_dev, 0x007f, 0x0022);
-       cit_model3_Packet1(gspca_dev, 0x0080, 0x000c);
-       cit_model3_Packet1(gspca_dev, 0x0081, 0x000b);
-       cit_model3_Packet1(gspca_dev, 0x0083, 0x00fd);
-       cit_model3_Packet1(gspca_dev, 0x0086, 0x000b);
-       cit_model3_Packet1(gspca_dev, 0x0087, 0x000b);
-       cit_model3_Packet1(gspca_dev, 0x007e, 0x000e);
-       cit_model3_Packet1(gspca_dev, 0x0096, 0x00a0);  /* Red sharpness */
-       cit_model3_Packet1(gspca_dev, 0x0097, 0x0096);  /* Blue sharpness */
-       cit_model3_Packet1(gspca_dev, 0x0098, 0x000b);
-
-       /* FIXME we should probably use cit_get_clock_div() here (in
-          combination with isoc negotiation using the programmable isoc size)
-          like with the IBM netcam pro). */
-       cit_write_reg(gspca_dev, clock_div, 0x0111); /* Clock Divider */
-
-       switch (gspca_dev->width) {
-       case 160:
-               cit_model3_Packet1(gspca_dev, 0x001f, 0x0000); /* Same */
-               cit_model3_Packet1(gspca_dev, 0x0039, 0x001f); /* Same */
-               cit_model3_Packet1(gspca_dev, 0x003b, 0x003c); /* Same */
-               cit_model3_Packet1(gspca_dev, 0x0040, 0x000a);
-               cit_model3_Packet1(gspca_dev, 0x0051, 0x000a);
-               break;
-       case 320:
-               cit_model3_Packet1(gspca_dev, 0x001f, 0x0000); /* Same */
-               cit_model3_Packet1(gspca_dev, 0x0039, 0x001f); /* Same */
-               cit_model3_Packet1(gspca_dev, 0x003b, 0x003c); /* Same */
-               cit_model3_Packet1(gspca_dev, 0x0040, 0x0008);
-               cit_model3_Packet1(gspca_dev, 0x0051, 0x000b);
-               break;
-       case 640:
-               cit_model3_Packet1(gspca_dev, 0x001f, 0x0002);  /* !Same */
-               cit_model3_Packet1(gspca_dev, 0x0039, 0x003e);  /* !Same */
-               cit_model3_Packet1(gspca_dev, 0x0040, 0x0008);
-               cit_model3_Packet1(gspca_dev, 0x0051, 0x000a);
-               break;
-       }
-
-/*     if (sd->input_index) { */
-       if (rca_input) {
-               for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) {
-                       if (rca_initdata[i][0])
-                               cit_read_reg(gspca_dev, rca_initdata[i][2], 0);
-                       else
-                               cit_write_reg(gspca_dev, rca_initdata[i][1],
-                                             rca_initdata[i][2]);
-               }
-       }
-
-       return 0;
-}
-
-static int cit_start_model4(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       cit_write_reg(gspca_dev, 0x0000, 0x0100);
-       cit_write_reg(gspca_dev, 0x00c0, 0x0111);
-       cit_write_reg(gspca_dev, 0x00bc, 0x012c);
-       cit_write_reg(gspca_dev, 0x0080, 0x012b);
-       cit_write_reg(gspca_dev, 0x0000, 0x0108);
-       cit_write_reg(gspca_dev, 0x0001, 0x0133);
-       cit_write_reg(gspca_dev, 0x009b, 0x010f);
-       cit_write_reg(gspca_dev, 0x00bb, 0x010f);
-       cit_model4_Packet1(gspca_dev, 0x0038, 0x0000);
-       cit_model4_Packet1(gspca_dev, 0x000a, 0x005c);
-
-       cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-       cit_write_reg(gspca_dev, 0x0004, 0x012f);
-       cit_write_reg(gspca_dev, 0xd141, 0x0124);
-       cit_write_reg(gspca_dev, 0x0000, 0x0127);
-       cit_write_reg(gspca_dev, 0x00fb, 0x012e);
-       cit_write_reg(gspca_dev, 0x0000, 0x0130);
-       cit_write_reg(gspca_dev, 0x8a28, 0x0124);
-       cit_write_reg(gspca_dev, 0x00aa, 0x012f);
-       cit_write_reg(gspca_dev, 0xd055, 0x0124);
-       cit_write_reg(gspca_dev, 0x000c, 0x0127);
-       cit_write_reg(gspca_dev, 0x0009, 0x012e);
-       cit_write_reg(gspca_dev, 0xaa28, 0x0124);
-
-       cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-       cit_write_reg(gspca_dev, 0x0012, 0x012f);
-       cit_write_reg(gspca_dev, 0xd141, 0x0124);
-       cit_write_reg(gspca_dev, 0x0008, 0x0127);
-       cit_write_reg(gspca_dev, 0x00aa, 0x0130);
-       cit_write_reg(gspca_dev, 0x82a8, 0x0124);
-       cit_write_reg(gspca_dev, 0x002a, 0x012d);
-       cit_write_reg(gspca_dev, 0x0000, 0x012f);
-       cit_write_reg(gspca_dev, 0xd145, 0x0124);
-       cit_write_reg(gspca_dev, 0xfffa, 0x0124);
-       cit_model4_Packet1(gspca_dev, 0x0034, 0x0000);
-
-       switch (gspca_dev->width) {
-       case 128: /* 128x96 */
-               cit_write_reg(gspca_dev, 0x0070, 0x0119);
-               cit_write_reg(gspca_dev, 0x00d0, 0x0111);
-               cit_write_reg(gspca_dev, 0x0039, 0x010a);
-               cit_write_reg(gspca_dev, 0x0001, 0x0102);
-               cit_write_reg(gspca_dev, 0x0028, 0x0103);
-               cit_write_reg(gspca_dev, 0x0000, 0x0104);
-               cit_write_reg(gspca_dev, 0x001e, 0x0105);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x0016, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x000a, 0x0127);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
-               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
-               cit_write_reg(gspca_dev, 0x0014, 0x012d);
-               cit_write_reg(gspca_dev, 0x0008, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012e);
-               cit_write_reg(gspca_dev, 0x001a, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
-               cit_write_reg(gspca_dev, 0x005a, 0x012d);
-               cit_write_reg(gspca_dev, 0x9545, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0127);
-               cit_write_reg(gspca_dev, 0x0018, 0x012e);
-               cit_write_reg(gspca_dev, 0x0043, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012f);
-               cit_write_reg(gspca_dev, 0xd055, 0x0124);
-               cit_write_reg(gspca_dev, 0x001c, 0x0127);
-               cit_write_reg(gspca_dev, 0x00eb, 0x012e);
-               cit_write_reg(gspca_dev, 0xaa28, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x0032, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x0000, 0x0127);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
-               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
-               cit_write_reg(gspca_dev, 0x0036, 0x012d);
-               cit_write_reg(gspca_dev, 0x0008, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0xfffa, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x001e, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x0017, 0x0127);
-               cit_write_reg(gspca_dev, 0x0013, 0x012e);
-               cit_write_reg(gspca_dev, 0x0031, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
-               cit_write_reg(gspca_dev, 0x0017, 0x012d);
-               cit_write_reg(gspca_dev, 0x0078, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0x0000, 0x0127);
-               cit_write_reg(gspca_dev, 0xfea8, 0x0124);
-               sd->sof_len = 2;
-               break;
-       case 160: /* 160x120 */
-               cit_write_reg(gspca_dev, 0x0038, 0x0119);
-               cit_write_reg(gspca_dev, 0x00d0, 0x0111);
-               cit_write_reg(gspca_dev, 0x00b9, 0x010a);
-               cit_write_reg(gspca_dev, 0x0001, 0x0102);
-               cit_write_reg(gspca_dev, 0x0028, 0x0103);
-               cit_write_reg(gspca_dev, 0x0000, 0x0104);
-               cit_write_reg(gspca_dev, 0x001e, 0x0105);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x0016, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x000b, 0x0127);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
-               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
-               cit_write_reg(gspca_dev, 0x0014, 0x012d);
-               cit_write_reg(gspca_dev, 0x0008, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012e);
-               cit_write_reg(gspca_dev, 0x001a, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
-               cit_write_reg(gspca_dev, 0x005a, 0x012d);
-               cit_write_reg(gspca_dev, 0x9545, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0127);
-               cit_write_reg(gspca_dev, 0x0018, 0x012e);
-               cit_write_reg(gspca_dev, 0x0043, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012f);
-               cit_write_reg(gspca_dev, 0xd055, 0x0124);
-               cit_write_reg(gspca_dev, 0x001c, 0x0127);
-               cit_write_reg(gspca_dev, 0x00c7, 0x012e);
-               cit_write_reg(gspca_dev, 0xaa28, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x0032, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x0025, 0x0127);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
-               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
-               cit_write_reg(gspca_dev, 0x0036, 0x012d);
-               cit_write_reg(gspca_dev, 0x0008, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0xfffa, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x001e, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x0048, 0x0127);
-               cit_write_reg(gspca_dev, 0x0035, 0x012e);
-               cit_write_reg(gspca_dev, 0x00d0, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
-               cit_write_reg(gspca_dev, 0x0048, 0x012d);
-               cit_write_reg(gspca_dev, 0x0090, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0x0001, 0x0127);
-               cit_write_reg(gspca_dev, 0xfea8, 0x0124);
-               sd->sof_len = 2;
-               break;
-       case 176: /* 176x144 */
-               cit_write_reg(gspca_dev, 0x0038, 0x0119);
-               cit_write_reg(gspca_dev, 0x00d0, 0x0111);
-               cit_write_reg(gspca_dev, 0x00b9, 0x010a);
-               cit_write_reg(gspca_dev, 0x0001, 0x0102);
-               cit_write_reg(gspca_dev, 0x002c, 0x0103);
-               cit_write_reg(gspca_dev, 0x0000, 0x0104);
-               cit_write_reg(gspca_dev, 0x0024, 0x0105);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x0016, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x0007, 0x0127);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
-               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
-               cit_write_reg(gspca_dev, 0x0014, 0x012d);
-               cit_write_reg(gspca_dev, 0x0001, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012e);
-               cit_write_reg(gspca_dev, 0x001a, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
-               cit_write_reg(gspca_dev, 0x005e, 0x012d);
-               cit_write_reg(gspca_dev, 0x9545, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0127);
-               cit_write_reg(gspca_dev, 0x0018, 0x012e);
-               cit_write_reg(gspca_dev, 0x0049, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012f);
-               cit_write_reg(gspca_dev, 0xd055, 0x0124);
-               cit_write_reg(gspca_dev, 0x001c, 0x0127);
-               cit_write_reg(gspca_dev, 0x00c7, 0x012e);
-               cit_write_reg(gspca_dev, 0xaa28, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x0032, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x0028, 0x0127);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
-               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
-               cit_write_reg(gspca_dev, 0x0036, 0x012d);
-               cit_write_reg(gspca_dev, 0x0008, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0xfffa, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x001e, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x0010, 0x0127);
-               cit_write_reg(gspca_dev, 0x0013, 0x012e);
-               cit_write_reg(gspca_dev, 0x002a, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
-               cit_write_reg(gspca_dev, 0x0010, 0x012d);
-               cit_write_reg(gspca_dev, 0x006d, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0x0001, 0x0127);
-               cit_write_reg(gspca_dev, 0xfea8, 0x0124);
-               /* TESTME HDG: this does not seem right
-                  (it is 2 for all other resolutions) */
-               sd->sof_len = 10;
-               break;
-       case 320: /* 320x240 */
-               cit_write_reg(gspca_dev, 0x0070, 0x0119);
-               cit_write_reg(gspca_dev, 0x00d0, 0x0111);
-               cit_write_reg(gspca_dev, 0x0039, 0x010a);
-               cit_write_reg(gspca_dev, 0x0001, 0x0102);
-               cit_write_reg(gspca_dev, 0x0028, 0x0103);
-               cit_write_reg(gspca_dev, 0x0000, 0x0104);
-               cit_write_reg(gspca_dev, 0x001e, 0x0105);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x0016, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x000a, 0x0127);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
-               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
-               cit_write_reg(gspca_dev, 0x0014, 0x012d);
-               cit_write_reg(gspca_dev, 0x0008, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012e);
-               cit_write_reg(gspca_dev, 0x001a, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
-               cit_write_reg(gspca_dev, 0x005a, 0x012d);
-               cit_write_reg(gspca_dev, 0x9545, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0127);
-               cit_write_reg(gspca_dev, 0x0018, 0x012e);
-               cit_write_reg(gspca_dev, 0x0043, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012f);
-               cit_write_reg(gspca_dev, 0xd055, 0x0124);
-               cit_write_reg(gspca_dev, 0x001c, 0x0127);
-               cit_write_reg(gspca_dev, 0x00eb, 0x012e);
-               cit_write_reg(gspca_dev, 0xaa28, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x0032, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x0000, 0x0127);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
-               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
-               cit_write_reg(gspca_dev, 0x0036, 0x012d);
-               cit_write_reg(gspca_dev, 0x0008, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0xfffa, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x001e, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x0017, 0x0127);
-               cit_write_reg(gspca_dev, 0x0013, 0x012e);
-               cit_write_reg(gspca_dev, 0x0031, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
-               cit_write_reg(gspca_dev, 0x0017, 0x012d);
-               cit_write_reg(gspca_dev, 0x0078, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0x0000, 0x0127);
-               cit_write_reg(gspca_dev, 0xfea8, 0x0124);
-               sd->sof_len = 2;
-               break;
-       case 352: /* 352x288 */
-               cit_write_reg(gspca_dev, 0x0070, 0x0119);
-               cit_write_reg(gspca_dev, 0x00c0, 0x0111);
-               cit_write_reg(gspca_dev, 0x0039, 0x010a);
-               cit_write_reg(gspca_dev, 0x0001, 0x0102);
-               cit_write_reg(gspca_dev, 0x002c, 0x0103);
-               cit_write_reg(gspca_dev, 0x0000, 0x0104);
-               cit_write_reg(gspca_dev, 0x0024, 0x0105);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x0016, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x0006, 0x0127);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
-               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
-               cit_write_reg(gspca_dev, 0x0014, 0x012d);
-               cit_write_reg(gspca_dev, 0x0002, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012e);
-               cit_write_reg(gspca_dev, 0x001a, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a0a, 0x0124);
-               cit_write_reg(gspca_dev, 0x005e, 0x012d);
-               cit_write_reg(gspca_dev, 0x9545, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0127);
-               cit_write_reg(gspca_dev, 0x0018, 0x012e);
-               cit_write_reg(gspca_dev, 0x0049, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012f);
-               cit_write_reg(gspca_dev, 0xd055, 0x0124);
-               cit_write_reg(gspca_dev, 0x001c, 0x0127);
-               cit_write_reg(gspca_dev, 0x00cf, 0x012e);
-               cit_write_reg(gspca_dev, 0xaa28, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x0032, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x0000, 0x0127);
-               cit_write_reg(gspca_dev, 0x00aa, 0x0130);
-               cit_write_reg(gspca_dev, 0x82a8, 0x0124);
-               cit_write_reg(gspca_dev, 0x0036, 0x012d);
-               cit_write_reg(gspca_dev, 0x0008, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0xfffa, 0x0124);
-               cit_write_reg(gspca_dev, 0x00aa, 0x012d);
-               cit_write_reg(gspca_dev, 0x001e, 0x012f);
-               cit_write_reg(gspca_dev, 0xd141, 0x0124);
-               cit_write_reg(gspca_dev, 0x0010, 0x0127);
-               cit_write_reg(gspca_dev, 0x0013, 0x012e);
-               cit_write_reg(gspca_dev, 0x0025, 0x0130);
-               cit_write_reg(gspca_dev, 0x8a28, 0x0124);
-               cit_write_reg(gspca_dev, 0x0010, 0x012d);
-               cit_write_reg(gspca_dev, 0x0048, 0x012f);
-               cit_write_reg(gspca_dev, 0xd145, 0x0124);
-               cit_write_reg(gspca_dev, 0x0000, 0x0127);
-               cit_write_reg(gspca_dev, 0xfea8, 0x0124);
-               sd->sof_len = 2;
-               break;
-       }
-
-       cit_model4_Packet1(gspca_dev, 0x0038, 0x0004);
-
-       return 0;
-}
-
-static int cit_start_ibm_netcam_pro(struct gspca_dev *gspca_dev)
-{
-       const unsigned short compression = 0; /* 0=none, 7=best frame rate */
-       int i, clock_div;
-
-       clock_div = cit_get_clock_div(gspca_dev);
-       if (clock_div < 0)
-               return clock_div;
-
-       cit_write_reg(gspca_dev, 0x0003, 0x0133);
-       cit_write_reg(gspca_dev, 0x0000, 0x0117);
-       cit_write_reg(gspca_dev, 0x0008, 0x0123);
-       cit_write_reg(gspca_dev, 0x0000, 0x0100);
-       cit_write_reg(gspca_dev, 0x0060, 0x0116);
-       /* cit_write_reg(gspca_dev, 0x0002, 0x0112); see sd_stop0 */
-       cit_write_reg(gspca_dev, 0x0000, 0x0133);
-       cit_write_reg(gspca_dev, 0x0000, 0x0123);
-       cit_write_reg(gspca_dev, 0x0001, 0x0117);
-       cit_write_reg(gspca_dev, 0x0040, 0x0108);
-       cit_write_reg(gspca_dev, 0x0019, 0x012c);
-       cit_write_reg(gspca_dev, 0x0060, 0x0116);
-       /* cit_write_reg(gspca_dev, 0x000b, 0x0115); see sd_stop0 */
-
-       cit_model3_Packet1(gspca_dev, 0x0049, 0x0000);
-
-       cit_write_reg(gspca_dev, 0x0000, 0x0101); /* Same on 160x120, 320x240 */
-       cit_write_reg(gspca_dev, 0x003a, 0x0102); /* Hstart */
-       cit_write_reg(gspca_dev, 0x00a0, 0x0103); /* Same on 160x120, 320x240 */
-       cit_write_reg(gspca_dev, 0x0078, 0x0105); /* Same on 160x120, 320x240 */
-       cit_write_reg(gspca_dev, 0x0000, 0x010a); /* Same */
-       cit_write_reg(gspca_dev, 0x0002, 0x011d); /* Same on 160x120, 320x240 */
-       cit_write_reg(gspca_dev, 0x0000, 0x0129); /* Same */
-       cit_write_reg(gspca_dev, 0x00fc, 0x012b); /* Same */
-       cit_write_reg(gspca_dev, 0x0022, 0x012a); /* Same */
-
-       switch (gspca_dev->width) {
-       case 160: /* 160x120 */
-               cit_write_reg(gspca_dev, 0x0024, 0x010b);
-               cit_write_reg(gspca_dev, 0x0089, 0x0119);
-               cit_write_reg(gspca_dev, 0x000a, 0x011b);
-               cit_write_reg(gspca_dev, 0x0003, 0x011e);
-               cit_write_reg(gspca_dev, 0x0007, 0x0104);
-               cit_write_reg(gspca_dev, 0x0009, 0x011a);
-               cit_write_reg(gspca_dev, 0x008b, 0x011c);
-               cit_write_reg(gspca_dev, 0x0008, 0x0118);
-               cit_write_reg(gspca_dev, 0x0000, 0x0132);
-               break;
-       case 320: /* 320x240 */
-               cit_write_reg(gspca_dev, 0x0028, 0x010b);
-               cit_write_reg(gspca_dev, 0x00d9, 0x0119);
-               cit_write_reg(gspca_dev, 0x0006, 0x011b);
-               cit_write_reg(gspca_dev, 0x0000, 0x011e);
-               cit_write_reg(gspca_dev, 0x000e, 0x0104);
-               cit_write_reg(gspca_dev, 0x0004, 0x011a);
-               cit_write_reg(gspca_dev, 0x003f, 0x011c);
-               cit_write_reg(gspca_dev, 0x000c, 0x0118);
-               cit_write_reg(gspca_dev, 0x0000, 0x0132);
-               break;
-       }
-
-       cit_model3_Packet1(gspca_dev, 0x0019, 0x0031);
-       cit_model3_Packet1(gspca_dev, 0x001a, 0x0003);
-       cit_model3_Packet1(gspca_dev, 0x001b, 0x0038);
-       cit_model3_Packet1(gspca_dev, 0x001c, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0024, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x0027, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x002a, 0x0004);
-       cit_model3_Packet1(gspca_dev, 0x0035, 0x000b);
-       cit_model3_Packet1(gspca_dev, 0x003f, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x0044, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x0054, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00c4, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00e7, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x00e9, 0x0001);
-       cit_model3_Packet1(gspca_dev, 0x00ee, 0x0000);
-       cit_model3_Packet1(gspca_dev, 0x00f3, 0x00c0);
-
-       cit_write_reg(gspca_dev, compression, 0x0109);
-       cit_write_reg(gspca_dev, clock_div, 0x0111);
-
-/*     if (sd->input_index) { */
-       if (rca_input) {
-               for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) {
-                       if (rca_initdata[i][0])
-                               cit_read_reg(gspca_dev, rca_initdata[i][2], 0);
-                       else
-                               cit_write_reg(gspca_dev, rca_initdata[i][1],
-                                             rca_initdata[i][2]);
-               }
-       }
-
-       return 0;
-}
-
-/* -- start the camera -- */
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int packet_size;
-
-       packet_size = cit_get_packet_size(gspca_dev);
-       if (packet_size < 0)
-               return packet_size;
-
-       switch (sd->model) {
-       case CIT_MODEL0:
-               cit_start_model0(gspca_dev);
-               break;
-       case CIT_MODEL1:
-               cit_start_model1(gspca_dev);
-               break;
-       case CIT_MODEL2:
-               cit_start_model2(gspca_dev);
-               break;
-       case CIT_MODEL3:
-               cit_start_model3(gspca_dev);
-               break;
-       case CIT_MODEL4:
-               cit_start_model4(gspca_dev);
-               break;
-       case CIT_IBM_NETCAM_PRO:
-               cit_start_ibm_netcam_pro(gspca_dev);
-               break;
-       }
-
-       /* Program max isoc packet size */
-       cit_write_reg(gspca_dev, packet_size >> 8, 0x0106);
-       cit_write_reg(gspca_dev, packet_size & 0xff, 0x0107);
-
-       cit_restart_stream(gspca_dev);
-
-       return 0;
-}
-
-static int sd_isoc_init(struct gspca_dev *gspca_dev)
-{
-       struct usb_host_interface *alt;
-       int max_packet_size;
-
-       switch (gspca_dev->width) {
-       case 160:
-               max_packet_size = 450;
-               break;
-       case 176:
-               max_packet_size = 600;
-               break;
-       default:
-               max_packet_size = 1022;
-               break;
-       }
-
-       /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
-       alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
-       alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size);
-
-       return 0;
-}
-
-static int sd_isoc_nego(struct gspca_dev *gspca_dev)
-{
-       int ret, packet_size, min_packet_size;
-       struct usb_host_interface *alt;
-
-       switch (gspca_dev->width) {
-       case 160:
-               min_packet_size = 200;
-               break;
-       case 176:
-               min_packet_size = 266;
-               break;
-       default:
-               min_packet_size = 400;
-               break;
-       }
-
-       alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
-       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
-       if (packet_size <= min_packet_size)
-               return -EIO;
-
-       packet_size -= 100;
-       if (packet_size < min_packet_size)
-               packet_size = min_packet_size;
-       alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
-
-       ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
-       if (ret < 0)
-               pr_err("set alt 1 err %d\n", ret);
-
-       return ret;
-}
-
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-       cit_write_reg(gspca_dev, 0x0000, 0x010c);
-}
-
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* We cannot use gspca_dev->present here as that is not set when
-          sd_init gets called and we get called from sd_init */
-       if (!gspca_dev->dev)
-               return;
-
-       switch (sd->model) {
-       case CIT_MODEL0:
-               /* HDG windows does this, but it causes the cams autogain to
-                  restart from a gain of 0, which does not look good when
-                  changing resolutions. */
-               /* cit_write_reg(gspca_dev, 0x0000, 0x0112); */
-               cit_write_reg(gspca_dev, 0x00c0, 0x0100); /* LED Off */
-               break;
-       case CIT_MODEL1:
-               cit_send_FF_04_02(gspca_dev);
-               cit_read_reg(gspca_dev, 0x0100, 0);
-               cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */
-               break;
-       case CIT_MODEL2:
-               v4l2_ctrl_grab(sd->lighting, false);
-               /* Fall through! */
-       case CIT_MODEL4:
-               cit_model2_Packet1(gspca_dev, 0x0030, 0x0004);
-
-               cit_write_reg(gspca_dev, 0x0080, 0x0100);       /* LED Off */
-               cit_write_reg(gspca_dev, 0x0020, 0x0111);
-               cit_write_reg(gspca_dev, 0x00a0, 0x0111);
-
-               cit_model2_Packet1(gspca_dev, 0x0030, 0x0002);
-
-               cit_write_reg(gspca_dev, 0x0020, 0x0111);
-               cit_write_reg(gspca_dev, 0x0000, 0x0112);
-               break;
-       case CIT_MODEL3:
-               cit_write_reg(gspca_dev, 0x0006, 0x012c);
-               cit_model3_Packet1(gspca_dev, 0x0046, 0x0000);
-               cit_read_reg(gspca_dev, 0x0116, 0);
-               cit_write_reg(gspca_dev, 0x0064, 0x0116);
-               cit_read_reg(gspca_dev, 0x0115, 0);
-               cit_write_reg(gspca_dev, 0x0003, 0x0115);
-               cit_write_reg(gspca_dev, 0x0008, 0x0123);
-               cit_write_reg(gspca_dev, 0x0000, 0x0117);
-               cit_write_reg(gspca_dev, 0x0000, 0x0112);
-               cit_write_reg(gspca_dev, 0x0080, 0x0100);
-               break;
-       case CIT_IBM_NETCAM_PRO:
-               cit_model3_Packet1(gspca_dev, 0x0049, 0x00ff);
-               cit_write_reg(gspca_dev, 0x0006, 0x012c);
-               cit_write_reg(gspca_dev, 0x0000, 0x0116);
-               /* HDG windows does this, but I cannot get the camera
-                  to restart with this without redoing the entire init
-                  sequence which makes switching modes really slow */
-               /* cit_write_reg(gspca_dev, 0x0006, 0x0115); */
-               cit_write_reg(gspca_dev, 0x0008, 0x0123);
-               cit_write_reg(gspca_dev, 0x0000, 0x0117);
-               cit_write_reg(gspca_dev, 0x0003, 0x0133);
-               cit_write_reg(gspca_dev, 0x0000, 0x0111);
-               /* HDG windows does this, but I get a green picture when
-                  restarting the stream after this */
-               /* cit_write_reg(gspca_dev, 0x0000, 0x0112); */
-               cit_write_reg(gspca_dev, 0x00c0, 0x0100);
-               break;
-       }
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       /* If the last button state is pressed, release it now! */
-       if (sd->button_state) {
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
-               input_sync(gspca_dev->input_dev);
-               sd->button_state = 0;
-       }
-#endif
-}
-
-static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 byte3 = 0, byte4 = 0;
-       int i;
-
-       switch (sd->model) {
-       case CIT_MODEL0:
-       case CIT_MODEL1:
-       case CIT_MODEL3:
-       case CIT_IBM_NETCAM_PRO:
-               switch (gspca_dev->width) {
-               case 160: /* 160x120 */
-                       byte3 = 0x02;
-                       byte4 = 0x0a;
-                       break;
-               case 176: /* 176x144 */
-                       byte3 = 0x02;
-                       byte4 = 0x0e;
-                       break;
-               case 320: /* 320x240 */
-                       byte3 = 0x02;
-                       byte4 = 0x08;
-                       break;
-               case 352: /* 352x288 */
-                       byte3 = 0x02;
-                       byte4 = 0x00;
-                       break;
-               case 640:
-                       byte3 = 0x03;
-                       byte4 = 0x08;
-                       break;
-               }
-
-               /* These have a different byte3 */
-               if (sd->model <= CIT_MODEL1)
-                       byte3 = 0x00;
-
-               for (i = 0; i < len; i++) {
-                       /* For this model the SOF always starts at offset 0
-                          so no need to search the entire frame */
-                       if (sd->model == CIT_MODEL0 && sd->sof_read != i)
-                               break;
-
-                       switch (sd->sof_read) {
-                       case 0:
-                               if (data[i] == 0x00)
-                                       sd->sof_read++;
-                               break;
-                       case 1:
-                               if (data[i] == 0xff)
-                                       sd->sof_read++;
-                               else if (data[i] == 0x00)
-                                       sd->sof_read = 1;
-                               else
-                                       sd->sof_read = 0;
-                               break;
-                       case 2:
-                               if (data[i] == byte3)
-                                       sd->sof_read++;
-                               else if (data[i] == 0x00)
-                                       sd->sof_read = 1;
-                               else
-                                       sd->sof_read = 0;
-                               break;
-                       case 3:
-                               if (data[i] == byte4) {
-                                       sd->sof_read = 0;
-                                       return data + i + (sd->sof_len - 3);
-                               }
-                               if (byte3 == 0x00 && data[i] == 0xff)
-                                       sd->sof_read = 2;
-                               else if (data[i] == 0x00)
-                                       sd->sof_read = 1;
-                               else
-                                       sd->sof_read = 0;
-                               break;
-                       }
-               }
-               break;
-       case CIT_MODEL2:
-       case CIT_MODEL4:
-               /* TESTME we need to find a longer sof signature to avoid
-                  false positives */
-               for (i = 0; i < len; i++) {
-                       switch (sd->sof_read) {
-                       case 0:
-                               if (data[i] == 0x00)
-                                       sd->sof_read++;
-                               break;
-                       case 1:
-                               sd->sof_read = 0;
-                               if (data[i] == 0xff) {
-                                       if (i >= 4)
-                                               PDEBUG(D_FRAM,
-                                                      "header found at offset: %d: %02x %02x 00 %02x %02x %02x\n",
-                                                      i - 1,
-                                                      data[i - 4],
-                                                      data[i - 3],
-                                                      data[i],
-                                                      data[i + 1],
-                                                      data[i + 2]);
-                                       else
-                                               PDEBUG(D_FRAM,
-                                                      "header found at offset: %d: 00 %02x %02x %02x\n",
-                                                      i - 1,
-                                                      data[i],
-                                                      data[i + 1],
-                                                      data[i + 2]);
-                                       return data + i + (sd->sof_len - 1);
-                               }
-                               break;
-                       }
-               }
-               break;
-       }
-       return NULL;
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data, int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       unsigned char *sof;
-
-       sof = cit_find_sof(gspca_dev, data, len);
-       if (sof) {
-               int n;
-
-               /* finish decoding current frame */
-               n = sof - data;
-               if (n > sd->sof_len)
-                       n -= sd->sof_len;
-               else
-                       n = 0;
-               gspca_frame_add(gspca_dev, LAST_PACKET,
-                               data, n);
-               gspca_frame_add(gspca_dev, FIRST_PACKET, NULL, 0);
-               len -= sof - data;
-               data = sof;
-       }
-
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-static void cit_check_button(struct gspca_dev *gspca_dev)
-{
-       int new_button_state;
-       struct sd *sd = (struct sd *)gspca_dev;
-
-       switch (sd->model) {
-       case CIT_MODEL3:
-       case CIT_IBM_NETCAM_PRO:
-               break;
-       default: /* TEST ME unknown if this works on other models too */
-               return;
-       }
-
-       /* Read the button state */
-       cit_read_reg(gspca_dev, 0x0113, 0);
-       new_button_state = !gspca_dev->usb_buf[0];
-
-       /* Tell the cam we've seen the button press, notice that this
-          is a nop (iow the cam keeps reporting pressed) until the
-          button is actually released. */
-       if (new_button_state)
-               cit_write_reg(gspca_dev, 0x01, 0x0113);
-
-       if (sd->button_state != new_button_state) {
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA,
-                                new_button_state);
-               input_sync(gspca_dev->input_dev);
-               sd->button_state = new_button_state;
-       }
-}
-#endif
-
-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;
-
-       if (sd->stop_on_control_change)
-               sd_stopN(gspca_dev);
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               cit_set_brightness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               cit_set_contrast(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_HUE:
-               cit_set_hue(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_HFLIP:
-               cit_set_hflip(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SHARPNESS:
-               cit_set_sharpness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_BACKLIGHT_COMPENSATION:
-               cit_set_lighting(gspca_dev, ctrl->val);
-               break;
-       }
-       if (sd->stop_on_control_change)
-               cit_restart_stream(gspca_dev);
-       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;
-       bool has_brightness;
-       bool has_contrast;
-       bool has_hue;
-       bool has_sharpness;
-       bool has_lighting;
-       bool has_hflip;
-
-       has_brightness = has_contrast = has_hue =
-               has_sharpness = has_hflip = has_lighting = false;
-       switch (sd->model) {
-       case CIT_MODEL0:
-               has_contrast = has_hflip = true;
-               break;
-       case CIT_MODEL1:
-               has_brightness = has_contrast =
-                       has_sharpness = has_lighting = true;
-               break;
-       case CIT_MODEL2:
-               has_brightness = has_hue = has_lighting = true;
-               break;
-       case CIT_MODEL3:
-               has_brightness = has_contrast = has_sharpness = true;
-               break;
-       case CIT_MODEL4:
-               has_brightness = has_hue = true;
-               break;
-       case CIT_IBM_NETCAM_PRO:
-               has_brightness = has_hue =
-                       has_sharpness = has_hflip = has_lighting = true;
-               break;
-       }
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 5);
-       if (has_brightness)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 63, 1, 32);
-       if (has_contrast)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 20, 1, 10);
-       if (has_hue)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_HUE, 0, 127, 1, 63);
-       if (has_sharpness)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_SHARPNESS, 0, 6, 1, 3);
-       if (has_lighting)
-               sd->lighting = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_BACKLIGHT_COMPENSATION, 0, 2, 1, 1);
-       if (has_hflip)
-               v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                       V4L2_CID_HFLIP, 0, 1, 1, 0);
-
-       if (hdl->error) {
-               pr_err("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,
-       .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .pkt_scan = sd_pkt_scan,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .dq_callback = cit_check_button,
-       .other_input = 1,
-#endif
-};
-
-static const struct sd_desc sd_desc_isoc_nego = {
-       .name = MODULE_NAME,
-       .config = sd_config,
-       .init = sd_init,
-       .init_controls = sd_init_controls,
-       .start = sd_start,
-       .isoc_init = sd_isoc_init,
-       .isoc_nego = sd_isoc_nego,
-       .stopN = sd_stopN,
-       .stop0 = sd_stop0,
-       .pkt_scan = sd_pkt_scan,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .dq_callback = cit_check_button,
-       .other_input = 1,
-#endif
-};
-
-/* -- module initialisation -- */
-static const struct usb_device_id device_table[] = {
-       { USB_DEVICE_VER(0x0545, 0x8080, 0x0001, 0x0001), .driver_info = CIT_MODEL0 },
-       { USB_DEVICE_VER(0x0545, 0x8080, 0x0002, 0x0002), .driver_info = CIT_MODEL1 },
-       { USB_DEVICE_VER(0x0545, 0x8080, 0x030a, 0x030a), .driver_info = CIT_MODEL2 },
-       { USB_DEVICE_VER(0x0545, 0x8080, 0x0301, 0x0301), .driver_info = CIT_MODEL3 },
-       { USB_DEVICE_VER(0x0545, 0x8002, 0x030a, 0x030a), .driver_info = CIT_MODEL4 },
-       { USB_DEVICE_VER(0x0545, 0x800c, 0x030a, 0x030a), .driver_info = CIT_MODEL2 },
-       { USB_DEVICE_VER(0x0545, 0x800d, 0x030a, 0x030a), .driver_info = CIT_MODEL4 },
-       {}
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-static int sd_probe(struct usb_interface *intf,
-                       const struct usb_device_id *id)
-{
-       const struct sd_desc *desc = &sd_desc;
-
-       switch (id->driver_info) {
-       case CIT_MODEL0:
-       case CIT_MODEL1:
-               if (intf->cur_altsetting->desc.bInterfaceNumber != 2)
-                       return -ENODEV;
-               break;
-       case CIT_MODEL2:
-       case CIT_MODEL4:
-               if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
-                       return -ENODEV;
-               break;
-       case CIT_MODEL3:
-               if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
-                       return -ENODEV;
-               /* FIXME this likely applies to all model3 cams and probably
-                  to other models too. */
-               if (ibm_netcam_pro)
-                       desc = &sd_desc_isoc_nego;
-               break;
-       }
-
-       return gspca_dev_probe2(intf, id, 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,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
diff --git a/drivers/media/video/gspca/zc3xx-reg.h b/drivers/media/video/gspca/zc3xx-reg.h
deleted file mode 100644 (file)
index a1bd94e..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * zc030x registers
- *
- * Copyright (c) 2008 Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- * The register aliases used here came from this driver:
- *     http://zc0302.sourceforge.net/zc0302.php
- *
- * This code is placed under the terms of the GNU General Public License v2
- */
-
-/* Define the register map */
-#define ZC3XX_R000_SYSTEMCONTROL       0x0000
-#define ZC3XX_R001_SYSTEMOPERATING     0x0001
-
-/* Picture size */
-#define ZC3XX_R002_CLOCKSELECT         0x0002
-#define ZC3XX_R003_FRAMEWIDTHHIGH      0x0003
-#define ZC3XX_R004_FRAMEWIDTHLOW       0x0004
-#define ZC3XX_R005_FRAMEHEIGHTHIGH     0x0005
-#define ZC3XX_R006_FRAMEHEIGHTLOW      0x0006
-
-/* JPEG control */
-#define ZC3XX_R008_CLOCKSETTING        0x0008
-
-/* Test mode */
-#define ZC3XX_R00B_TESTMODECONTROL     0x000b
-
-/* Frame retreiving */
-#define ZC3XX_R00C_LASTACQTIME         0x000c
-#define ZC3XX_R00D_MONITORRES          0x000d
-#define ZC3XX_R00E_TIMESTAMPHIGH       0x000e
-#define ZC3XX_R00F_TIMESTAMPLOW        0x000f
-#define ZC3XX_R018_FRAMELOST           0x0018
-#define ZC3XX_R019_AUTOADJUSTFPS       0x0019
-#define ZC3XX_R01A_LASTFRAMESTATE      0x001a
-#define ZC3XX_R025_DATACOUNTER         0x0025
-
-/* Stream and sensor specific */
-#define ZC3XX_R010_CMOSSENSORSELECT    0x0010
-#define ZC3XX_R011_VIDEOSTATUS         0x0011
-#define ZC3XX_R012_VIDEOCONTROLFUNC    0x0012
-
-/* Horizontal and vertical synchros */
-#define ZC3XX_R01D_HSYNC_0             0x001d
-#define ZC3XX_R01E_HSYNC_1             0x001e
-#define ZC3XX_R01F_HSYNC_2             0x001f
-#define ZC3XX_R020_HSYNC_3             0x0020
-
-/* Target picture size in byte */
-#define ZC3XX_R022_TARGETPICTSIZE_0    0x0022
-#define ZC3XX_R023_TARGETPICTSIZE_1    0x0023
-#define ZC3XX_R024_TARGETPICTSIZE_2    0x0024
-
-/* Audio registers */
-#define ZC3XX_R030_AUDIOADC            0x0030
-#define ZC3XX_R031_AUDIOSTREAMSTATUS   0x0031
-#define ZC3XX_R032_AUDIOSTATUS         0x0032
-
-/* Sensor interface */
-#define ZC3XX_R080_HBLANKHIGH          0x0080
-#define ZC3XX_R081_HBLANKLOW           0x0081
-#define ZC3XX_R082_RESETLEVELADDR      0x0082
-#define ZC3XX_R083_RGAINADDR           0x0083
-#define ZC3XX_R084_GGAINADDR           0x0084
-#define ZC3XX_R085_BGAINADDR           0x0085
-#define ZC3XX_R086_EXPTIMEHIGH         0x0086
-#define ZC3XX_R087_EXPTIMEMID          0x0087
-#define ZC3XX_R088_EXPTIMELOW          0x0088
-#define ZC3XX_R089_RESETBLACKHIGH      0x0089
-#define ZC3XX_R08A_RESETWHITEHIGH      0x008a
-#define ZC3XX_R08B_I2CDEVICEADDR       0x008b
-#define ZC3XX_R08C_I2CIDLEANDNACK      0x008c
-#define ZC3XX_R08D_COMPABILITYMODE     0x008d
-#define ZC3XX_R08E_COMPABILITYMODE2    0x008e
-
-/* I2C control */
-#define ZC3XX_R090_I2CCOMMAND          0x0090
-#define ZC3XX_R091_I2CSTATUS           0x0091
-#define ZC3XX_R092_I2CADDRESSSELECT    0x0092
-#define ZC3XX_R093_I2CSETVALUE         0x0093
-#define ZC3XX_R094_I2CWRITEACK         0x0094
-#define ZC3XX_R095_I2CREAD             0x0095
-#define ZC3XX_R096_I2CREADACK          0x0096
-
-/* Window inside the sensor array */
-#define ZC3XX_R097_WINYSTARTHIGH       0x0097
-#define ZC3XX_R098_WINYSTARTLOW        0x0098
-#define ZC3XX_R099_WINXSTARTHIGH       0x0099
-#define ZC3XX_R09A_WINXSTARTLOW        0x009a
-#define ZC3XX_R09B_WINHEIGHTHIGH       0x009b
-#define ZC3XX_R09C_WINHEIGHTLOW        0x009c
-#define ZC3XX_R09D_WINWIDTHHIGH        0x009d
-#define ZC3XX_R09E_WINWIDTHLOW         0x009e
-#define ZC3XX_R119_FIRSTYHIGH          0x0119
-#define ZC3XX_R11A_FIRSTYLOW           0x011a
-#define ZC3XX_R11B_FIRSTXHIGH          0x011b
-#define ZC3XX_R11C_FIRSTXLOW           0x011c
-
-/* Max sensor array size */
-#define ZC3XX_R09F_MAXXHIGH            0x009f
-#define ZC3XX_R0A0_MAXXLOW             0x00a0
-#define ZC3XX_R0A1_MAXYHIGH            0x00a1
-#define ZC3XX_R0A2_MAXYLOW             0x00a2
-#define ZC3XX_R0A3_EXPOSURETIMEHIGH    0x00a3
-#define ZC3XX_R0A4_EXPOSURETIMELOW     0x00a4
-#define ZC3XX_R0A5_EXPOSUREGAIN        0x00a5
-#define ZC3XX_R0A6_EXPOSUREBLACKLVL    0x00a6
-
-/* Other registers */
-#define ZC3XX_R100_OPERATIONMODE       0x0100
-#define ZC3XX_R101_SENSORCORRECTION    0x0101
-
-/* Gains */
-#define ZC3XX_R116_RGAIN               0x0116
-#define ZC3XX_R117_GGAIN               0x0117
-#define ZC3XX_R118_BGAIN               0x0118
-#define ZC3XX_R11D_GLOBALGAIN          0x011d
-#define ZC3XX_R1A8_DIGITALGAIN         0x01a8
-#define ZC3XX_R1A9_DIGITALLIMITDIFF    0x01a9
-#define ZC3XX_R1AA_DIGITALGAINSTEP     0x01aa
-
-/* Auto correction */
-#define ZC3XX_R180_AUTOCORRECTENABLE   0x0180
-#define ZC3XX_R181_WINXSTART           0x0181
-#define ZC3XX_R182_WINXWIDTH           0x0182
-#define ZC3XX_R183_WINXCENTER          0x0183
-#define ZC3XX_R184_WINYSTART           0x0184
-#define ZC3XX_R185_WINYWIDTH           0x0185
-#define ZC3XX_R186_WINYCENTER          0x0186
-
-/* Gain range */
-#define ZC3XX_R187_MAXGAIN             0x0187
-#define ZC3XX_R188_MINGAIN             0x0188
-
-/* Auto exposure and white balance */
-#define ZC3XX_R189_AWBSTATUS           0x0189
-#define ZC3XX_R18A_AWBFREEZE           0x018a
-#define ZC3XX_R18B_AESTATUS            0x018b
-#define ZC3XX_R18C_AEFREEZE            0x018c
-#define ZC3XX_R18F_AEUNFREEZE          0x018f
-#define ZC3XX_R190_EXPOSURELIMITHIGH   0x0190
-#define ZC3XX_R191_EXPOSURELIMITMID    0x0191
-#define ZC3XX_R192_EXPOSURELIMITLOW    0x0192
-#define ZC3XX_R195_ANTIFLICKERHIGH     0x0195
-#define ZC3XX_R196_ANTIFLICKERMID      0x0196
-#define ZC3XX_R197_ANTIFLICKERLOW      0x0197
-
-/* What is this ? */
-#define ZC3XX_R18D_YTARGET             0x018d
-#define ZC3XX_R18E_RESETLVL            0x018e
-
-/* Color */
-#define ZC3XX_R1A0_REDMEANAFTERAGC     0x01a0
-#define ZC3XX_R1A1_GREENMEANAFTERAGC   0x01a1
-#define ZC3XX_R1A2_BLUEMEANAFTERAGC    0x01a2
-#define ZC3XX_R1A3_REDMEANAFTERAWB     0x01a3
-#define ZC3XX_R1A4_GREENMEANAFTERAWB   0x01a4
-#define ZC3XX_R1A5_BLUEMEANAFTERAWB    0x01a5
-#define ZC3XX_R1A6_YMEANAFTERAE        0x01a6
-#define ZC3XX_R1A7_CALCGLOBALMEAN      0x01a7
-
-/* Matrixes */
-
-/* Color matrix is like :
-   R' = R * RGB00 + G * RGB01 + B * RGB02 + RGB03
-   G' = R * RGB10 + G * RGB11 + B * RGB22 + RGB13
-   B' = R * RGB20 + G * RGB21 + B * RGB12 + RGB23
- */
-#define ZC3XX_R10A_RGB00               0x010a
-#define ZC3XX_R10B_RGB01               0x010b
-#define ZC3XX_R10C_RGB02               0x010c
-#define ZC3XX_R113_RGB03               0x0113
-#define ZC3XX_R10D_RGB10               0x010d
-#define ZC3XX_R10E_RGB11               0x010e
-#define ZC3XX_R10F_RGB12               0x010f
-#define ZC3XX_R114_RGB13               0x0114
-#define ZC3XX_R110_RGB20               0x0110
-#define ZC3XX_R111_RGB21               0x0111
-#define ZC3XX_R112_RGB22               0x0112
-#define ZC3XX_R115_RGB23               0x0115
-
-/* Gamma matrix */
-#define ZC3XX_R120_GAMMA00             0x0120
-#define ZC3XX_R121_GAMMA01             0x0121
-#define ZC3XX_R122_GAMMA02             0x0122
-#define ZC3XX_R123_GAMMA03             0x0123
-#define ZC3XX_R124_GAMMA04             0x0124
-#define ZC3XX_R125_GAMMA05             0x0125
-#define ZC3XX_R126_GAMMA06             0x0126
-#define ZC3XX_R127_GAMMA07             0x0127
-#define ZC3XX_R128_GAMMA08             0x0128
-#define ZC3XX_R129_GAMMA09             0x0129
-#define ZC3XX_R12A_GAMMA0A             0x012a
-#define ZC3XX_R12B_GAMMA0B             0x012b
-#define ZC3XX_R12C_GAMMA0C             0x012c
-#define ZC3XX_R12D_GAMMA0D             0x012d
-#define ZC3XX_R12E_GAMMA0E             0x012e
-#define ZC3XX_R12F_GAMMA0F             0x012f
-#define ZC3XX_R130_GAMMA10             0x0130
-#define ZC3XX_R131_GAMMA11             0x0131
-#define ZC3XX_R132_GAMMA12             0x0132
-#define ZC3XX_R133_GAMMA13             0x0133
-#define ZC3XX_R134_GAMMA14             0x0134
-#define ZC3XX_R135_GAMMA15             0x0135
-#define ZC3XX_R136_GAMMA16             0x0136
-#define ZC3XX_R137_GAMMA17             0x0137
-#define ZC3XX_R138_GAMMA18             0x0138
-#define ZC3XX_R139_GAMMA19             0x0139
-#define ZC3XX_R13A_GAMMA1A             0x013a
-#define ZC3XX_R13B_GAMMA1B             0x013b
-#define ZC3XX_R13C_GAMMA1C             0x013c
-#define ZC3XX_R13D_GAMMA1D             0x013d
-#define ZC3XX_R13E_GAMMA1E             0x013e
-#define ZC3XX_R13F_GAMMA1F             0x013f
-
-/* Luminance gamma */
-#define ZC3XX_R140_YGAMMA00            0x0140
-#define ZC3XX_R141_YGAMMA01            0x0141
-#define ZC3XX_R142_YGAMMA02            0x0142
-#define ZC3XX_R143_YGAMMA03            0x0143
-#define ZC3XX_R144_YGAMMA04            0x0144
-#define ZC3XX_R145_YGAMMA05            0x0145
-#define ZC3XX_R146_YGAMMA06            0x0146
-#define ZC3XX_R147_YGAMMA07            0x0147
-#define ZC3XX_R148_YGAMMA08            0x0148
-#define ZC3XX_R149_YGAMMA09            0x0149
-#define ZC3XX_R14A_YGAMMA0A            0x014a
-#define ZC3XX_R14B_YGAMMA0B            0x014b
-#define ZC3XX_R14C_YGAMMA0C            0x014c
-#define ZC3XX_R14D_YGAMMA0D            0x014d
-#define ZC3XX_R14E_YGAMMA0E            0x014e
-#define ZC3XX_R14F_YGAMMA0F            0x014f
-#define ZC3XX_R150_YGAMMA10            0x0150
-#define ZC3XX_R151_YGAMMA11            0x0151
-
-#define ZC3XX_R1C5_SHARPNESSMODE       0x01c5
-#define ZC3XX_R1C6_SHARPNESS00         0x01c6
-#define ZC3XX_R1C7_SHARPNESS01         0x01c7
-#define ZC3XX_R1C8_SHARPNESS02         0x01c8
-#define ZC3XX_R1C9_SHARPNESS03         0x01c9
-#define ZC3XX_R1CA_SHARPNESS04         0x01ca
-#define ZC3XX_R1CB_SHARPNESS05         0x01cb
-
-/* Dead pixels */
-#define ZC3XX_R250_DEADPIXELSMODE      0x0250
-
-/* EEPROM */
-#define ZC3XX_R300_EEPROMCONFIG        0x0300
-#define ZC3XX_R301_EEPROMACCESS        0x0301
-#define ZC3XX_R302_EEPROMSTATUS        0x0302
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
deleted file mode 100644 (file)
index f0bacee..0000000
+++ /dev/null
@@ -1,7024 +0,0 @@
-/*
- * Z-Star/Vimicro zc301/zc302p/vc30x driver
- *
- * Copyright (C) 2009-2012 Jean-Francois Moine <http://moinejf.free.fr>
- * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr
- *
- * 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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/input.h>
-#include "gspca.h"
-#include "jpeg.h"
-
-MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>, "
-               "Serge A. Suchkov <Serge.A.S@tochka.ru>");
-MODULE_DESCRIPTION("GSPCA ZC03xx/VC3xx USB Camera Driver");
-MODULE_LICENSE("GPL");
-
-static int force_sensor = -1;
-
-#define REG08_DEF 3            /* default JPEG compression (75%) */
-#include "zc3xx-reg.h"
-
-/* specific webcam descriptor */
-struct sd {
-       struct gspca_dev gspca_dev;     /* !! must be the first item */
-
-       struct { /* gamma/brightness/contrast control cluster */
-               struct v4l2_ctrl *gamma;
-               struct v4l2_ctrl *brightness;
-               struct v4l2_ctrl *contrast;
-       };
-       struct { /* autogain/exposure control cluster */
-               struct v4l2_ctrl *autogain;
-               struct v4l2_ctrl *exposure;
-       };
-       struct v4l2_ctrl *plfreq;
-       struct v4l2_ctrl *sharpness;
-       struct v4l2_ctrl *jpegqual;
-
-       struct work_struct work;
-       struct workqueue_struct *work_thread;
-
-       u8 reg08;               /* webcam compression quality */
-
-       u8 bridge;
-       u8 sensor;              /* Type of image sensor chip */
-       u16 chip_revision;
-
-       u8 jpeg_hdr[JPEG_HDR_SZ];
-};
-enum bridges {
-       BRIDGE_ZC301,
-       BRIDGE_ZC303,
-};
-enum sensors {
-       SENSOR_ADCM2700,
-       SENSOR_CS2102,
-       SENSOR_CS2102K,
-       SENSOR_GC0303,
-       SENSOR_GC0305,
-       SENSOR_HDCS2020,
-       SENSOR_HV7131B,
-       SENSOR_HV7131R,
-       SENSOR_ICM105A,
-       SENSOR_MC501CB,
-       SENSOR_MT9V111_1,       /* (mi360soc) zc301 */
-       SENSOR_MT9V111_3,       /* (mi360soc) zc303 */
-       SENSOR_OV7620,          /* OV7648 - same values */
-       SENSOR_OV7630C,
-       SENSOR_PAS106,
-       SENSOR_PAS202B,
-       SENSOR_PB0330,
-       SENSOR_PO2030,
-       SENSOR_TAS5130C,
-       SENSOR_MAX
-};
-
-static const struct v4l2_pix_format vga_mode[] = {
-       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 240 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 480 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-
-static const struct v4l2_pix_format broken_vga_mode[] = {
-       {320, 232, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 320,
-               .sizeimage = 320 * 232 * 4 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {640, 472, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 640,
-               .sizeimage = 640 * 472 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-
-static const struct v4l2_pix_format sif_mode[] = {
-       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 176,
-               .sizeimage = 176 * 144 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 1},
-       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
-               .bytesperline = 352,
-               .sizeimage = 352 * 288 * 3 / 8 + 590,
-               .colorspace = V4L2_COLORSPACE_JPEG,
-               .priv = 0},
-};
-
-/*
- * Bridge reg08 bits 1-2 -> JPEG quality conversion table. Note the highest
- * quality setting is not usable as USB 1 does not have enough bandwidth.
- */
-static u8 jpeg_qual[] = {50, 75, 87, /* 94 */};
-
-/* usb exchanges */
-struct usb_action {
-       u8      req;
-       u8      val;
-       u16     idx;
-};
-
-static const struct usb_action adcm2700_Initial[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},         /* 00,00,01,cc */
-       {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT},           /* 00,02,04,cc */
-       {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING},          /* 00,08,03,cc */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,d3,cc */
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc */
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},         /* 00,04,80,cc */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc */
-       {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW},        /* 00,06,d8,cc */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc */
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,05,cc */
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},          /* 00,98,00,cc */
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},          /* 00,9a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},             /* 01,1a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},             /* 01,1c,00,cc */
-       {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW},          /* 00,9c,de,cc */
-       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},           /* 00,9e,86,cc */
-       {0xbb, 0x00, 0x0400},                           /* 04,00,00,bb */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xbb, 0x0f, 0x140f},                           /* 14,0f,0f,bb */
-       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,37,cc */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0d,cc */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},             /* 01,89,06,cc */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},         /* 01,c5,03,cc */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},           /* 01,cb,13,cc */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},          /* 03,01,08,cc */
-       {0xa0, 0x58, ZC3XX_R116_RGAIN},                 /* 01,16,58,cc */
-       {0xa0, 0x5a, ZC3XX_R118_BGAIN},                 /* 01,18,5a,cc */
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,02,cc */
-       {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,d3,cc */
-       {0xbb, 0x00, 0x0408},                           /* 04,00,08,bb */
-       {0xdd, 0x00, 0x0200},                           /* 00,02,00,dd */
-       {0xbb, 0x00, 0x0400},                           /* 04,00,00,bb */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xbb, 0x0f, 0x140f},                           /* 14,0f,0f,bb */
-       {0xbb, 0xe0, 0x0c2e},                           /* 0c,e0,2e,bb */
-       {0xbb, 0x01, 0x2000},                           /* 20,01,00,bb */
-       {0xbb, 0x96, 0x2400},                           /* 24,96,00,bb */
-       {0xbb, 0x06, 0x1006},                           /* 10,06,06,bb */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xaa, 0xfe, 0x0002},                           /* 00,fe,02,aa */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xbb, 0x5f, 0x2090},                           /* 20,5f,90,bb */
-       {0xbb, 0x01, 0x8000},                           /* 80,01,00,bb */
-       {0xbb, 0x09, 0x8400},                           /* 84,09,00,bb */
-       {0xbb, 0x86, 0x0002},                           /* 00,86,02,bb */
-       {0xbb, 0xe6, 0x0401},                           /* 04,e6,01,bb */
-       {0xbb, 0x86, 0x0802},                           /* 08,86,02,bb */
-       {0xbb, 0xe6, 0x0c01},                           /* 0c,e6,01,bb */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xaa, 0xfe, 0x0000},                           /* 00,fe,00,aa */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xaa, 0xfe, 0x0020},                           /* 00,fe,20,aa */
-/*mswin+*/
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xaa, 0xfe, 0x0002},
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xaa, 0xb4, 0xcd37},
-       {0xaa, 0xa4, 0x0004},
-       {0xaa, 0xa8, 0x0007},
-       {0xaa, 0xac, 0x0004},
-/*mswin-*/
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xaa, 0xfe, 0x0000},                           /* 00,fe,00,aa */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xbb, 0x04, 0x0400},                           /* 04,04,00,bb */
-       {0xdd, 0x00, 0x0100},                           /* 00,01,00,dd */
-       {0xbb, 0x01, 0x0400},                           /* 04,01,00,bb */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xaa, 0xfe, 0x0002},                           /* 00,fe,02,aa */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xbb, 0x41, 0x2803},                           /* 28,41,03,bb */
-       {0xbb, 0x40, 0x2c03},                           /* 2c,40,03,bb */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xaa, 0xfe, 0x0010},                           /* 00,fe,10,aa */
-       {}
-};
-static const struct usb_action adcm2700_InitialScale[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},         /* 00,00,01,cc */
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},           /* 00,02,10,cc */
-       {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING},          /* 00,08,03,cc */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,d3,cc */
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc */
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},         /* 00,04,80,cc */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc */
-       {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW},        /* 00,06,d0,cc */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc */
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,05,cc */
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},          /* 00,98,00,cc */
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},          /* 00,9a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},             /* 01,1a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},             /* 01,1c,00,cc */
-       {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW},          /* 00,9c,d8,cc */
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},           /* 00,9e,88,cc */
-       {0xbb, 0x00, 0x0400},                           /* 04,00,00,bb */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xbb, 0x0f, 0x140f},                           /* 14,0f,0f,bb */
-       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,37,cc */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0d,cc */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},             /* 01,89,06,cc */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},         /* 01,c5,03,cc */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},           /* 01,cb,13,cc */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},          /* 03,01,08,cc */
-       {0xa0, 0x58, ZC3XX_R116_RGAIN},                 /* 01,16,58,cc */
-       {0xa0, 0x5a, ZC3XX_R118_BGAIN},                 /* 01,18,5a,cc */
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,02,cc */
-       {0xa0, 0xd3, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,d3,cc */
-       {0xbb, 0x00, 0x0408},                           /* 04,00,08,bb */
-       {0xdd, 0x00, 0x0200},                           /* 00,02,00,dd */
-       {0xbb, 0x00, 0x0400},                           /* 04,00,00,bb */
-       {0xdd, 0x00, 0x0050},                           /* 00,00,50,dd */
-       {0xbb, 0x0f, 0x140f},                           /* 14,0f,0f,bb */
-       {0xbb, 0xe0, 0x0c2e},                           /* 0c,e0,2e,bb */
-       {0xbb, 0x01, 0x2000},                           /* 20,01,00,bb */
-       {0xbb, 0x96, 0x2400},                           /* 24,96,00,bb */
-       {0xbb, 0x06, 0x1006},                           /* 10,06,06,bb */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xaa, 0xfe, 0x0002},                           /* 00,fe,02,aa */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xbb, 0x5f, 0x2090},                           /* 20,5f,90,bb */
-       {0xbb, 0x01, 0x8000},                           /* 80,01,00,bb */
-       {0xbb, 0x09, 0x8400},                           /* 84,09,00,bb */
-       {0xbb, 0x86, 0x0002},                           /* 00,88,02,bb */
-       {0xbb, 0xe6, 0x0401},                           /* 04,e6,01,bb */
-       {0xbb, 0x86, 0x0802},                           /* 08,88,02,bb */
-       {0xbb, 0xe6, 0x0c01},                           /* 0c,e6,01,bb */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xaa, 0xfe, 0x0000},                           /* 00,fe,00,aa */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xaa, 0xfe, 0x0020},                           /* 00,fe,20,aa */
-       /*******/
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xaa, 0xfe, 0x0000},                           /* 00,fe,00,aa */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xdd, 0x00, 0x0010},                           /* 00,00,10,dd */
-       {0xbb, 0x04, 0x0400},                           /* 04,04,00,bb */
-       {0xdd, 0x00, 0x0100},                           /* 00,01,00,dd */
-       {0xbb, 0x01, 0x0400},                           /* 04,01,00,bb */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xaa, 0xfe, 0x0002},                           /* 00,fe,02,aa */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xbb, 0x41, 0x2803},                           /* 28,41,03,bb */
-       {0xbb, 0x40, 0x2c03},                           /* 2c,40,03,bb */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xaa, 0xfe, 0x0010},                           /* 00,fe,10,aa */
-       {}
-};
-static const struct usb_action adcm2700_50HZ[] = {
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xaa, 0xfe, 0x0002},                           /* 00,fe,02,aa */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xbb, 0x05, 0x8400},                           /* 84,05,00,bb */
-       {0xbb, 0xd0, 0xb007},                           /* b0,d0,07,bb */
-       {0xbb, 0xa0, 0xb80f},                           /* b8,a0,0f,bb */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xaa, 0xfe, 0x0010},                           /* 00,fe,10,aa */
-       {0xaa, 0x26, 0x00d0},                           /* 00,26,d0,aa */
-       {0xaa, 0x28, 0x0002},                           /* 00,28,02,aa */
-       {}
-};
-static const struct usb_action adcm2700_60HZ[] = {
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xaa, 0xfe, 0x0002},                           /* 00,fe,02,aa */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xbb, 0x07, 0x8400},                           /* 84,07,00,bb */
-       {0xbb, 0x82, 0xb006},                           /* b0,82,06,bb */
-       {0xbb, 0x04, 0xb80d},                           /* b8,04,0d,bb */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xaa, 0xfe, 0x0010},                           /* 00,fe,10,aa */
-       {0xaa, 0x26, 0x0057},                           /* 00,26,57,aa */
-       {0xaa, 0x28, 0x0002},                           /* 00,28,02,aa */
-       {}
-};
-static const struct usb_action adcm2700_NoFliker[] = {
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xaa, 0xfe, 0x0002},                           /* 00,fe,02,aa */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0a,cc */
-       {0xbb, 0x07, 0x8400},                           /* 84,07,00,bb */
-       {0xbb, 0x05, 0xb000},                           /* b0,05,00,bb */
-       {0xbb, 0xa0, 0xb801},                           /* b8,a0,01,bb */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xaa, 0xfe, 0x0010},                           /* 00,fe,10,aa */
-       {}
-};
-static const struct usb_action cs2102_InitialScale[] = {       /* 320x240 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x20, ZC3XX_R080_HBLANKHIGH},
-       {0xa0, 0x21, ZC3XX_R081_HBLANKLOW},
-       {0xa0, 0x30, ZC3XX_R083_RGAINADDR},
-       {0xa0, 0x31, ZC3XX_R084_GGAINADDR},
-       {0xa0, 0x32, ZC3XX_R085_BGAINADDR},
-       {0xa0, 0x23, ZC3XX_R086_EXPTIMEHIGH},
-       {0xa0, 0x24, ZC3XX_R087_EXPTIMEMID},
-       {0xa0, 0x25, ZC3XX_R088_EXPTIMELOW},
-       {0xa0, 0xb3, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00 */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xaa, 0x02, 0x0008},
-       {0xaa, 0x03, 0x0000},
-       {0xaa, 0x11, 0x0000},
-       {0xaa, 0x12, 0x0089},
-       {0xaa, 0x13, 0x0000},
-       {0xaa, 0x14, 0x00e9},
-       {0xaa, 0x20, 0x0000},
-       {0xaa, 0x22, 0x0000},
-       {0xaa, 0x0b, 0x0004},
-       {0xaa, 0x30, 0x0030},
-       {0xaa, 0x31, 0x0030},
-       {0xaa, 0x32, 0x0030},
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x10, 0x01ae},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa0, 0x68, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x00, 0x01ad},
-       {}
-};
-
-static const struct usb_action cs2102_Initial[] = {    /* 640x480 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x20, ZC3XX_R080_HBLANKHIGH},
-       {0xa0, 0x21, ZC3XX_R081_HBLANKLOW},
-       {0xa0, 0x30, ZC3XX_R083_RGAINADDR},
-       {0xa0, 0x31, ZC3XX_R084_GGAINADDR},
-       {0xa0, 0x32, ZC3XX_R085_BGAINADDR},
-       {0xa0, 0x23, ZC3XX_R086_EXPTIMEHIGH},
-       {0xa0, 0x24, ZC3XX_R087_EXPTIMEMID},
-       {0xa0, 0x25, ZC3XX_R088_EXPTIMELOW},
-       {0xa0, 0xb3, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00 */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xaa, 0x02, 0x0008},
-       {0xaa, 0x03, 0x0000},
-       {0xaa, 0x11, 0x0001},
-       {0xaa, 0x12, 0x0087},
-       {0xaa, 0x13, 0x0001},
-       {0xaa, 0x14, 0x00e7},
-       {0xaa, 0x20, 0x0000},
-       {0xaa, 0x22, 0x0000},
-       {0xaa, 0x0b, 0x0004},
-       {0xaa, 0x30, 0x0030},
-       {0xaa, 0x31, 0x0030},
-       {0xaa, 0x32, 0x0030},
-       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x15, 0x01ae},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa0, 0x68, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x00, 0x01ad},
-       {}
-};
-static const struct usb_action cs2102_50HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x23, 0x0001},
-       {0xaa, 0x24, 0x005f},
-       {0xaa, 0x25, 0x0090},
-       {0xaa, 0x21, 0x00dd},
-       {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0xbf, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x3a, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x98, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xdd, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xe4, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action cs2102_50HZ[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x23, 0x0000},
-       {0xaa, 0x24, 0x00af},
-       {0xaa, 0x25, 0x00c8},
-       {0xaa, 0x21, 0x0068},
-       {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x5f, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x90, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x1d, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x4c, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x68, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xe3, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action cs2102_60HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x23, 0x0001},
-       {0xaa, 0x24, 0x0055},
-       {0xaa, 0x25, 0x00cc},
-       {0xaa, 0x21, 0x003f},
-       {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0xab, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x98, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x30, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0xd4, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x39, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x70, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xb0, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action cs2102_60HZ[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x23, 0x0000},
-       {0xaa, 0x24, 0x00aa},
-       {0xaa, 0x25, 0x00e6},
-       {0xaa, 0x21, 0x003f},
-       {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x55, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xcc, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x18, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x6a, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x3f, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xa5, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xf0, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action cs2102_NoFlikerScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x23, 0x0001},
-       {0xaa, 0x24, 0x005f},
-       {0xaa, 0x25, 0x0000},
-       {0xaa, 0x21, 0x0001},
-       {0xa0, 0x02, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0xbf, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x80, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x01, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xa0, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action cs2102_NoFliker[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x23, 0x0000},
-       {0xaa, 0x24, 0x00af},
-       {0xaa, 0x25, 0x0080},
-       {0xaa, 0x21, 0x0001},
-       {0xa0, 0x01, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x5f, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x80, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x01, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xa0, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {}
-};
-
-/* CS2102_KOCOM */
-static const struct usb_action cs2102K_InitialScale[] = {
-       {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
-       {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x0a, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x0b, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x0c, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x7c, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x0d, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0xa3, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x0e, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x78, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
-       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa0, 0x00, 0x01ad},
-       {0xa0, 0x01, 0x01b1},
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x60, ZC3XX_R116_RGAIN},
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},
-       {0xa0, 0x4c, ZC3XX_R118_BGAIN},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
-       {0xa0, 0x13, ZC3XX_R120_GAMMA00},       /* gamma 4 */
-       {0xa0, 0x38, ZC3XX_R121_GAMMA01},
-       {0xa0, 0x59, ZC3XX_R122_GAMMA02},
-       {0xa0, 0x79, ZC3XX_R123_GAMMA03},
-       {0xa0, 0x92, ZC3XX_R124_GAMMA04},
-       {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
-       {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
-       {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
-       {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
-       {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
-       {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
-       {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
-       {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
-       {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
-       {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
-       {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
-       {0xa0, 0x26, ZC3XX_R130_GAMMA10},
-       {0xa0, 0x22, ZC3XX_R131_GAMMA11},
-       {0xa0, 0x20, ZC3XX_R132_GAMMA12},
-       {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
-       {0xa0, 0x16, ZC3XX_R134_GAMMA14},
-       {0xa0, 0x13, ZC3XX_R135_GAMMA15},
-       {0xa0, 0x10, ZC3XX_R136_GAMMA16},
-       {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
-       {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
-       {0xa0, 0x09, ZC3XX_R139_GAMMA19},
-       {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
-       {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
-       {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
-       {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
-       {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
-       {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
-       {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
-       {0xa0, 0xf4, ZC3XX_R10B_RGB01},
-       {0xa0, 0xf4, ZC3XX_R10C_RGB02},
-       {0xa0, 0xf4, ZC3XX_R10D_RGB10},
-       {0xa0, 0x58, ZC3XX_R10E_RGB11},
-       {0xa0, 0xf4, ZC3XX_R10F_RGB12},
-       {0xa0, 0xf4, ZC3XX_R110_RGB20},
-       {0xa0, 0xf4, ZC3XX_R111_RGB21},
-       {0xa0, 0x58, ZC3XX_R112_RGB22},
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
-       {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x60, ZC3XX_R116_RGAIN},
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},
-       {0xa0, 0x4c, ZC3XX_R118_BGAIN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {}
-};
-
-static const struct usb_action cs2102K_Initial[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
-/*fixme: next sequence = i2c exchanges*/
-       {0xa0, 0x55, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x0a, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x0b, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x0c, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x7b, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x0d, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0xa3, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x03, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0xfb, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x05, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x06, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x03, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x09, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x08, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x0e, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x0f, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x10, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x11, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x12, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x18, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x15, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x16, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x17, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x0c, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x78, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},
-       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa0, 0x00, 0x01ad},
-       {0xa0, 0x01, 0x01b1},
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x60, ZC3XX_R116_RGAIN},
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},
-       {0xa0, 0x4c, ZC3XX_R118_BGAIN},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
-       {0xa0, 0x13, ZC3XX_R120_GAMMA00},       /* gamma 4 */
-       {0xa0, 0x38, ZC3XX_R121_GAMMA01},
-       {0xa0, 0x59, ZC3XX_R122_GAMMA02},
-       {0xa0, 0x79, ZC3XX_R123_GAMMA03},
-       {0xa0, 0x92, ZC3XX_R124_GAMMA04},
-       {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
-       {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
-       {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
-       {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
-       {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
-       {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
-       {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
-       {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
-       {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
-       {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
-       {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
-       {0xa0, 0x26, ZC3XX_R130_GAMMA10},
-       {0xa0, 0x22, ZC3XX_R131_GAMMA11},
-       {0xa0, 0x20, ZC3XX_R132_GAMMA12},
-       {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
-       {0xa0, 0x16, ZC3XX_R134_GAMMA14},
-       {0xa0, 0x13, ZC3XX_R135_GAMMA15},
-       {0xa0, 0x10, ZC3XX_R136_GAMMA16},
-       {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
-       {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
-       {0xa0, 0x09, ZC3XX_R139_GAMMA19},
-       {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
-       {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
-       {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
-       {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
-       {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
-       {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
-       {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
-       {0xa0, 0xf4, ZC3XX_R10B_RGB01},
-       {0xa0, 0xf4, ZC3XX_R10C_RGB02},
-       {0xa0, 0xf4, ZC3XX_R10D_RGB10},
-       {0xa0, 0x58, ZC3XX_R10E_RGB11},
-       {0xa0, 0xf4, ZC3XX_R10F_RGB12},
-       {0xa0, 0xf4, ZC3XX_R110_RGB20},
-       {0xa0, 0xf4, ZC3XX_R111_RGB21},
-       {0xa0, 0x58, ZC3XX_R112_RGB22},
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x22, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH},
-       {0xa0, 0x22, ZC3XX_R0A4_EXPOSURETIMELOW},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xee, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x3a, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x0f, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x19, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0x1f, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x60, ZC3XX_R116_RGAIN},
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},
-       {0xa0, 0x4c, ZC3XX_R118_BGAIN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x5c, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x96, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-/*fixme:what does the next sequence?*/
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0xd0, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0xd0, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x01, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x0a, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x0a, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x44, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x44, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x20, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x21, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x7e, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x00, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x13, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x7e, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x14, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x02, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x18, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x04, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x00, ZC3XX_R094_I2CWRITEACK},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {}
-};
-
-static const struct usb_action gc0305_Initial[] = {    /* 640x480 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00,08,03,cc */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT},   /* 00,02,04,cc */
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc */
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc */
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},        /* 00,06,e0,cc */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc */
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},  /* 00,98,00,cc */
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},  /* 00,9a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},     /* 01,1a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},     /* 01,1c,00,cc */
-       {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},  /* 00,9c,e6,cc */
-       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},   /* 00,9e,86,cc */
-       {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc */
-       {0xaa, 0x13, 0x0002},   /* 00,13,02,aa */
-       {0xaa, 0x15, 0x0003},   /* 00,15,03,aa */
-       {0xaa, 0x01, 0x0000},   /* 00,01,00,aa */
-       {0xaa, 0x02, 0x0000},   /* 00,02,00,aa */
-       {0xaa, 0x1a, 0x0000},   /* 00,1a,00,aa */
-       {0xaa, 0x1c, 0x0017},   /* 00,1c,17,aa */
-       {0xaa, 0x1d, 0x0080},   /* 00,1d,80,aa */
-       {0xaa, 0x1f, 0x0008},   /* 00,1f,08,aa */
-       {0xaa, 0x21, 0x0012},   /* 00,21,12,aa */
-       {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH},   /* 00,86,82,cc */
-       {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID},    /* 00,87,83,cc */
-       {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW},    /* 00,88,84,cc */
-       {0xaa, 0x05, 0x0000},   /* 00,05,00,aa */
-       {0xaa, 0x0a, 0x0000},   /* 00,0a,00,aa */
-       {0xaa, 0x0b, 0x00b0},   /* 00,0b,b0,aa */
-       {0xaa, 0x0c, 0x0000},   /* 00,0c,00,aa */
-       {0xaa, 0x0d, 0x00b0},   /* 00,0d,b0,aa */
-       {0xaa, 0x0e, 0x0000},   /* 00,0e,00,aa */
-       {0xaa, 0x0f, 0x00b0},   /* 00,0f,b0,aa */
-       {0xaa, 0x10, 0x0000},   /* 00,10,00,aa */
-       {0xaa, 0x11, 0x00b0},   /* 00,11,b0,aa */
-       {0xaa, 0x16, 0x0001},   /* 00,16,01,aa */
-       {0xaa, 0x17, 0x00e6},   /* 00,17,e6,aa */
-       {0xaa, 0x18, 0x0002},   /* 00,18,02,aa */
-       {0xaa, 0x19, 0x0086},   /* 00,19,86,aa */
-       {0xaa, 0x20, 0x0000},   /* 00,20,00,aa */
-       {0xaa, 0x1b, 0x0020},   /* 00,1b,20,aa */
-       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,b7,cc */
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,05,cc */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
-       {0xa0, 0x76, ZC3XX_R189_AWBSTATUS},     /* 01,89,76,cc */
-       {0xa0, 0x09, 0x01ad},   /* 01,ad,09,cc */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},   /* 01,cb,13,cc */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},  /* 03,01,08,cc */
-       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},   /* 01,a8,60,cc */
-       {0xa0, 0x85, ZC3XX_R18D_YTARGET},       /* 01,8d,85,cc */
-       {0xa0, 0x00, 0x011e},   /* 01,1e,00,cc */
-       {0xa0, 0x52, ZC3XX_R116_RGAIN}, /* 01,16,52,cc */
-       {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* 01,17,40,cc */
-       {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
-       {0xa0, 0x03, ZC3XX_R113_RGB03}, /* 01,13,03,cc */
-       {}
-};
-static const struct usb_action gc0305_InitialScale[] = { /* 320x240 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00,08,03,cc */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc */
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},   /* 00,02,10,cc */
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc */
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc */
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},        /* 00,06,e0,cc */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc */
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},  /* 00,98,00,cc */
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},  /* 00,9a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},     /* 01,1a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},     /* 01,1c,00,cc */
-       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},  /* 00,9c,e8,cc */
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},   /* 00,9e,88,cc */
-       {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc */
-       {0xaa, 0x13, 0x0000},   /* 00,13,00,aa */
-       {0xaa, 0x15, 0x0001},   /* 00,15,01,aa */
-       {0xaa, 0x01, 0x0000},   /* 00,01,00,aa */
-       {0xaa, 0x02, 0x0000},   /* 00,02,00,aa */
-       {0xaa, 0x1a, 0x0000},   /* 00,1a,00,aa */
-       {0xaa, 0x1c, 0x0017},   /* 00,1c,17,aa */
-       {0xaa, 0x1d, 0x0080},   /* 00,1d,80,aa */
-       {0xaa, 0x1f, 0x0008},   /* 00,1f,08,aa */
-       {0xaa, 0x21, 0x0012},   /* 00,21,12,aa */
-       {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH},   /* 00,86,82,cc */
-       {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID},    /* 00,87,83,cc */
-       {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW},    /* 00,88,84,cc */
-       {0xaa, 0x05, 0x0000},   /* 00,05,00,aa */
-       {0xaa, 0x0a, 0x0000},   /* 00,0a,00,aa */
-       {0xaa, 0x0b, 0x00b0},   /* 00,0b,b0,aa */
-       {0xaa, 0x0c, 0x0000},   /* 00,0c,00,aa */
-       {0xaa, 0x0d, 0x00b0},   /* 00,0d,b0,aa */
-       {0xaa, 0x0e, 0x0000},   /* 00,0e,00,aa */
-       {0xaa, 0x0f, 0x00b0},   /* 00,0f,b0,aa */
-       {0xaa, 0x10, 0x0000},   /* 00,10,00,aa */
-       {0xaa, 0x11, 0x00b0},   /* 00,11,b0,aa */
-       {0xaa, 0x16, 0x0001},   /* 00,16,01,aa */
-       {0xaa, 0x17, 0x00e8},   /* 00,17,e8,aa */
-       {0xaa, 0x18, 0x0002},   /* 00,18,02,aa */
-       {0xaa, 0x19, 0x0088},   /* 00,19,88,aa */
-       {0xaa, 0x20, 0x0000},   /* 00,20,00,aa */
-       {0xaa, 0x1b, 0x0020},   /* 00,1b,20,aa */
-       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,b7,cc */
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,05,cc */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
-       {0xa0, 0x76, ZC3XX_R189_AWBSTATUS},     /* 01,89,76,cc */
-       {0xa0, 0x09, 0x01ad},   /* 01,ad,09,cc */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},   /* 01,cb,13,cc */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},  /* 03,01,08,cc */
-       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},   /* 01,a8,60,cc */
-       {0xa0, 0x00, 0x011e},   /* 01,1e,00,cc */
-       {0xa0, 0x52, ZC3XX_R116_RGAIN}, /* 01,16,52,cc */
-       {0xa0, 0x40, ZC3XX_R117_GGAIN}, /* 01,17,40,cc */
-       {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
-       {0xa0, 0x03, ZC3XX_R113_RGB03}, /* 01,13,03,cc */
-       {}
-};
-static const struct usb_action gc0305_50HZ[] = {
-       {0xaa, 0x82, 0x0000},   /* 00,82,00,aa */
-       {0xaa, 0x83, 0x0002},   /* 00,83,02,aa */
-       {0xaa, 0x84, 0x0038},   /* 00,84,38,aa */       /* win: 00,84,ec */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
-       {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,0b,cc */
-       {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,18,cc */
-                                                       /* win: 01,92,10 */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
-       {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,8e,cc */
-                                                       /* win: 01,97,ec */
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},      /* 01,8c,0e,cc */
-       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,15,cc */
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,10,cc */
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
-       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},       /* 00,1d,62,cc */
-       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},       /* 00,1e,90,cc */
-       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},       /* 00,1f,c8,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},       /* 00,20,ff,cc */
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},    /* 01,1d,60,cc */
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc */
-/*     {0xa0, 0x85, ZC3XX_R18D_YTARGET},        * 01,8d,85,cc *
-                                                * if 640x480 */
-       {}
-};
-static const struct usb_action gc0305_60HZ[] = {
-       {0xaa, 0x82, 0x0000},   /* 00,82,00,aa */
-       {0xaa, 0x83, 0x0000},   /* 00,83,00,aa */
-       {0xaa, 0x84, 0x00ec},   /* 00,84,ec,aa */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
-       {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,0b,cc */
-       {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,10,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
-       {0xa0, 0xec, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,ec,cc */
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},      /* 01,8c,0e,cc */
-       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,15,cc */
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,10,cc */
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
-       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},       /* 00,1d,62,cc */
-       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},       /* 00,1e,90,cc */
-       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},       /* 00,1f,c8,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},       /* 00,20,ff,cc */
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},    /* 01,1d,60,cc */
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc */
-       {0xa0, 0x80, ZC3XX_R18D_YTARGET},       /* 01,8d,80,cc */
-       {}
-};
-
-static const struct usb_action gc0305_NoFliker[] = {
-       {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc */
-       {0xaa, 0x82, 0x0000},   /* 00,82,00,aa */
-       {0xaa, 0x83, 0x0000},   /* 00,83,00,aa */
-       {0xaa, 0x84, 0x0020},   /* 00,84,20,aa */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
-       {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,00,cc */
-       {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,48,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
-       {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,10,cc */
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},      /* 01,8c,0e,cc */
-       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,15,cc */
-       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},       /* 00,1d,62,cc */
-       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},       /* 00,1e,90,cc */
-       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},       /* 00,1f,c8,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},       /* 00,20,ff,cc */
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},    /* 01,1d,60,cc */
-       {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,03,cc */
-       {0xa0, 0x80, ZC3XX_R18D_YTARGET},       /* 01,8d,80,cc */
-       {}
-};
-
-static const struct usb_action hdcs2020_InitialScale[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* qtable 0x05 */
-       {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
-       {0xaa, 0x1c, 0x0000},
-       {0xaa, 0x0a, 0x0001},
-       {0xaa, 0x0b, 0x0006},
-       {0xaa, 0x0c, 0x007b},
-       {0xaa, 0x0d, 0x00a7},
-       {0xaa, 0x03, 0x00fb},
-       {0xaa, 0x05, 0x0000},
-       {0xaa, 0x06, 0x0003},
-       {0xaa, 0x09, 0x0008},
-
-       {0xaa, 0x0f, 0x0018},   /* set sensor gain */
-       {0xaa, 0x10, 0x0018},
-       {0xaa, 0x11, 0x0018},
-       {0xaa, 0x12, 0x0018},
-
-       {0xaa, 0x15, 0x004e},
-       {0xaa, 0x1c, 0x0004},
-       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x70, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa1, 0x01, 0x0002},
-       {0xa1, 0x01, 0x0008},
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x40, ZC3XX_R116_RGAIN},
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},
-       {0xa0, 0x40, ZC3XX_R118_BGAIN},
-       {0xa1, 0x01, 0x0008},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
-       {0xa1, 0x01, 0x01c8},
-       {0xa1, 0x01, 0x01c9},
-       {0xa1, 0x01, 0x01ca},
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
-       {0xa0, 0x13, ZC3XX_R120_GAMMA00},       /* gamma 4 */
-       {0xa0, 0x38, ZC3XX_R121_GAMMA01},
-       {0xa0, 0x59, ZC3XX_R122_GAMMA02},
-       {0xa0, 0x79, ZC3XX_R123_GAMMA03},
-       {0xa0, 0x92, ZC3XX_R124_GAMMA04},
-       {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
-       {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
-       {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
-       {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
-       {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
-       {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
-       {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
-       {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
-       {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
-       {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
-       {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
-       {0xa0, 0x26, ZC3XX_R130_GAMMA10},
-       {0xa0, 0x22, ZC3XX_R131_GAMMA11},
-       {0xa0, 0x20, ZC3XX_R132_GAMMA12},
-       {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
-       {0xa0, 0x16, ZC3XX_R134_GAMMA14},
-       {0xa0, 0x13, ZC3XX_R135_GAMMA15},
-       {0xa0, 0x10, ZC3XX_R136_GAMMA16},
-       {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
-       {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
-       {0xa0, 0x09, ZC3XX_R139_GAMMA19},
-       {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
-       {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
-       {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
-       {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
-       {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
-       {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
-
-       {0xa0, 0x66, ZC3XX_R10A_RGB00}, /* matrix */
-       {0xa0, 0xed, ZC3XX_R10B_RGB01},
-       {0xa0, 0xed, ZC3XX_R10C_RGB02},
-       {0xa0, 0xed, ZC3XX_R10D_RGB10},
-       {0xa0, 0x66, ZC3XX_R10E_RGB11},
-       {0xa0, 0xed, ZC3XX_R10F_RGB12},
-       {0xa0, 0xed, ZC3XX_R110_RGB20},
-       {0xa0, 0xed, ZC3XX_R111_RGB21},
-       {0xa0, 0x66, ZC3XX_R112_RGB22},
-
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x13, 0x0031},
-       {0xaa, 0x14, 0x0001},
-       {0xaa, 0x0e, 0x0004},
-       {0xaa, 0x19, 0x00cd},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-
-       {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 0x14 */
-       {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x18, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0x41, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x40, ZC3XX_R116_RGAIN},
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},
-       {0xa0, 0x40, ZC3XX_R118_BGAIN},
-       {}
-};
-static const struct usb_action hdcs2020_Initial[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x08, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
-       {0xaa, 0x1c, 0x0000},
-       {0xaa, 0x0a, 0x0001},
-       {0xaa, 0x0b, 0x0006},
-       {0xaa, 0x0c, 0x007a},
-       {0xaa, 0x0d, 0x00a7},
-       {0xaa, 0x03, 0x00fb},
-       {0xaa, 0x05, 0x0000},
-       {0xaa, 0x06, 0x0003},
-       {0xaa, 0x09, 0x0008},
-       {0xaa, 0x0f, 0x0018},   /* original setting */
-       {0xaa, 0x10, 0x0018},
-       {0xaa, 0x11, 0x0018},
-       {0xaa, 0x12, 0x0018},
-       {0xaa, 0x15, 0x004e},
-       {0xaa, 0x1c, 0x0004},
-       {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x70, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa1, 0x01, 0x0002},
-       {0xa1, 0x01, 0x0008},
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x40, ZC3XX_R116_RGAIN},
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},
-       {0xa0, 0x40, ZC3XX_R118_BGAIN},
-       {0xa1, 0x01, 0x0008},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
-       {0xa1, 0x01, 0x01c8},
-       {0xa1, 0x01, 0x01c9},
-       {0xa1, 0x01, 0x01ca},
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
-       {0xa0, 0x13, ZC3XX_R120_GAMMA00},       /* gamma 4 */
-       {0xa0, 0x38, ZC3XX_R121_GAMMA01},
-       {0xa0, 0x59, ZC3XX_R122_GAMMA02},
-       {0xa0, 0x79, ZC3XX_R123_GAMMA03},
-       {0xa0, 0x92, ZC3XX_R124_GAMMA04},
-       {0xa0, 0xa7, ZC3XX_R125_GAMMA05},
-       {0xa0, 0xb9, ZC3XX_R126_GAMMA06},
-       {0xa0, 0xc8, ZC3XX_R127_GAMMA07},
-       {0xa0, 0xd4, ZC3XX_R128_GAMMA08},
-       {0xa0, 0xdf, ZC3XX_R129_GAMMA09},
-       {0xa0, 0xe7, ZC3XX_R12A_GAMMA0A},
-       {0xa0, 0xee, ZC3XX_R12B_GAMMA0B},
-       {0xa0, 0xf4, ZC3XX_R12C_GAMMA0C},
-       {0xa0, 0xf9, ZC3XX_R12D_GAMMA0D},
-       {0xa0, 0xfc, ZC3XX_R12E_GAMMA0E},
-       {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
-       {0xa0, 0x26, ZC3XX_R130_GAMMA10},
-       {0xa0, 0x22, ZC3XX_R131_GAMMA11},
-       {0xa0, 0x20, ZC3XX_R132_GAMMA12},
-       {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
-       {0xa0, 0x16, ZC3XX_R134_GAMMA14},
-       {0xa0, 0x13, ZC3XX_R135_GAMMA15},
-       {0xa0, 0x10, ZC3XX_R136_GAMMA16},
-       {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
-       {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
-       {0xa0, 0x09, ZC3XX_R139_GAMMA19},
-       {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
-       {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
-       {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
-       {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
-       {0xa0, 0x03, ZC3XX_R13E_GAMMA1E},
-       {0xa0, 0x02, ZC3XX_R13F_GAMMA1F},
-       {0xa0, 0x66, ZC3XX_R10A_RGB00}, /* matrix */
-       {0xa0, 0xed, ZC3XX_R10B_RGB01},
-       {0xa0, 0xed, ZC3XX_R10C_RGB02},
-       {0xa0, 0xed, ZC3XX_R10D_RGB10},
-       {0xa0, 0x66, ZC3XX_R10E_RGB11},
-       {0xa0, 0xed, ZC3XX_R10F_RGB12},
-       {0xa0, 0xed, ZC3XX_R110_RGB20},
-       {0xa0, 0xed, ZC3XX_R111_RGB21},
-       {0xa0, 0x66, ZC3XX_R112_RGB22},
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
- /**** set exposure ***/
-       {0xaa, 0x13, 0x0031},
-       {0xaa, 0x14, 0x0001},
-       {0xaa, 0x0e, 0x0004},
-       {0xaa, 0x19, 0x00cd},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x04, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x18, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0x41, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x40, ZC3XX_R116_RGAIN},
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},
-       {0xa0, 0x40, ZC3XX_R118_BGAIN},
-       {}
-};
-static const struct usb_action hdcs2020_50HZ[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x13, 0x0018},                   /* 00,13,18,aa */
-       {0xaa, 0x14, 0x0001},                   /* 00,14,01,aa */
-       {0xaa, 0x0e, 0x0005},                   /* 00,0e,05,aa */
-       {0xaa, 0x19, 0x001f},                   /* 00,19,1f,aa */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
-       {0xa0, 0x76, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,76,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x46, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,46,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
-       {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
-       {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,28,cc */
-       {0xa0, 0x05, ZC3XX_R01D_HSYNC_0}, /* 00,1d,05,cc */
-       {0xa0, 0x1a, ZC3XX_R01E_HSYNC_1}, /* 00,1e,1a,cc */
-       {0xa0, 0x2f, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2f,cc */
-       {}
-};
-static const struct usb_action hdcs2020_60HZ[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x13, 0x0031},                   /* 00,13,31,aa */
-       {0xaa, 0x14, 0x0001},                   /* 00,14,01,aa */
-       {0xaa, 0x0e, 0x0004},                   /* 00,0e,04,aa */
-       {0xaa, 0x19, 0x00cd},                   /* 00,19,cd,aa */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
-       {0xa0, 0x62, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,62,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3d,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
-       {0xa0, 0x0c, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,0c,cc */
-       {0xa0, 0x28, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,28,cc */
-       {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, /* 00,1d,04,cc */
-       {0xa0, 0x18, ZC3XX_R01E_HSYNC_1}, /* 00,1e,18,cc */
-       {0xa0, 0x2c, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2c,cc */
-       {}
-};
-static const struct usb_action hdcs2020_NoFliker[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x13, 0x0010},                   /* 00,13,10,aa */
-       {0xaa, 0x14, 0x0001},                   /* 00,14,01,aa */
-       {0xaa, 0x0e, 0x0004},                   /* 00,0e,04,aa */
-       {0xaa, 0x19, 0x0000},                   /* 00,19,00,aa */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,02,cc */
-       {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
-       {0xa0, 0x04, ZC3XX_R01D_HSYNC_0}, /* 00,1d,04,cc */
-       {0xa0, 0x17, ZC3XX_R01E_HSYNC_1}, /* 00,1e,17,cc */
-       {0xa0, 0x2a, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2a,cc */
-       {}
-};
-
-static const struct usb_action hv7131b_InitialScale[] = {      /* 320x240 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00 */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xaa, 0x30, 0x002d},
-       {0xaa, 0x01, 0x0005},
-       {0xaa, 0x11, 0x0000},
-       {0xaa, 0x13, 0x0001},   /* {0xaa, 0x13, 0x0000}, */
-       {0xaa, 0x14, 0x0001},
-       {0xaa, 0x15, 0x00e8},
-       {0xaa, 0x16, 0x0002},
-       {0xaa, 0x17, 0x0086},           /* 00,17,88,aa */
-       {0xaa, 0x31, 0x0038},
-       {0xaa, 0x32, 0x0038},
-       {0xaa, 0x33, 0x0038},
-       {0xaa, 0x5b, 0x0001},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x68, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0x00, 0x01ad},
-       {0xa0, 0xc0, 0x019b},
-       {0xa0, 0xa0, 0x019c},
-       {0xa0, 0x02, ZC3XX_R188_MINGAIN},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xaa, 0x02, 0x0090},                   /* 00,02,80,aa */
-       {}
-};
-
-static const struct usb_action hv7131b_Initial[] = {   /* 640x480*/
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x00, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00 */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xaa, 0x30, 0x002d},
-       {0xaa, 0x01, 0x0005},
-       {0xaa, 0x11, 0x0001},
-       {0xaa, 0x13, 0x0000},   /* {0xaa, 0x13, 0x0001}; */
-       {0xaa, 0x14, 0x0001},
-       {0xaa, 0x15, 0x00e6},
-       {0xaa, 0x16, 0x0002},
-       {0xaa, 0x17, 0x0086},
-       {0xaa, 0x31, 0x0038},
-       {0xaa, 0x32, 0x0038},
-       {0xaa, 0x33, 0x0038},
-       {0xaa, 0x5b, 0x0001},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x70, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0x00, 0x01ad},
-       {0xa0, 0xc0, 0x019b},
-       {0xa0, 0xa0, 0x019c},
-       {0xa0, 0x02, ZC3XX_R188_MINGAIN},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xaa, 0x02, 0x0090},   /* {0xaa, 0x02, 0x0080}, */
-       {}
-};
-static const struct usb_action hv7131b_50HZ[] = {      /* 640x480*/
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x25, 0x0007},                   /* 00,25,07,aa */
-       {0xaa, 0x26, 0x0053},                   /* 00,26,53,aa */
-       {0xaa, 0x27, 0x0000},                   /* 00,27,00,aa */
-       {0xaa, 0x20, 0x0000},                   /* 00,20,00,aa */
-       {0xaa, 0x21, 0x0050},                   /* 00,21,50,aa */
-       {0xaa, 0x22, 0x001b},                   /* 00,22,1b,aa */
-       {0xaa, 0x23, 0x00fc},                   /* 00,23,fc,aa */
-       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,2f,cc */
-       {0xa0, 0x9b, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,9b,cc */
-       {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,80,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
-       {0xa0, 0xea, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,ea,cc */
-       {0xa0, 0x60, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,60,cc */
-       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},      /* 01,8c,0c,cc */
-       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,18,cc */
-       {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,18,cc */
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
-       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},       /* 00,1d,00,cc */
-       {0xa0, 0x50, ZC3XX_R01E_HSYNC_1},       /* 00,1e,50,cc */
-       {0xa0, 0x1b, ZC3XX_R01F_HSYNC_2},       /* 00,1f,1b,cc */
-       {0xa0, 0xfc, ZC3XX_R020_HSYNC_3},       /* 00,20,fc,cc */
-       {}
-};
-static const struct usb_action hv7131b_50HZScale[] = { /* 320x240 */
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x25, 0x0007},                   /* 00,25,07,aa */
-       {0xaa, 0x26, 0x0053},                   /* 00,26,53,aa */
-       {0xaa, 0x27, 0x0000},                   /* 00,27,00,aa */
-       {0xaa, 0x20, 0x0000},                   /* 00,20,00,aa */
-       {0xaa, 0x21, 0x0050},                   /* 00,21,50,aa */
-       {0xaa, 0x22, 0x0012},                   /* 00,22,12,aa */
-       {0xaa, 0x23, 0x0080},                   /* 00,23,80,aa */
-       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,2f,cc */
-       {0xa0, 0x9b, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,9b,cc */
-       {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,80,cc */
-       {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,01,cc */
-       {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,d4,cc */
-       {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,c0,cc */
-       {0xa0, 0x07, ZC3XX_R18C_AEFREEZE},      /* 01,8c,07,cc */
-       {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,0f,cc */
-       {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,18,cc */
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
-       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},       /* 00,1d,00,cc */
-       {0xa0, 0x50, ZC3XX_R01E_HSYNC_1},       /* 00,1e,50,cc */
-       {0xa0, 0x12, ZC3XX_R01F_HSYNC_2},       /* 00,1f,12,cc */
-       {0xa0, 0x80, ZC3XX_R020_HSYNC_3},       /* 00,20,80,cc */
-       {}
-};
-static const struct usb_action hv7131b_60HZ[] = {      /* 640x480*/
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x25, 0x0007},                   /* 00,25,07,aa */
-       {0xaa, 0x26, 0x00a1},                   /* 00,26,a1,aa */
-       {0xaa, 0x27, 0x0020},                   /* 00,27,20,aa */
-       {0xaa, 0x20, 0x0000},                   /* 00,20,00,aa */
-       {0xaa, 0x21, 0x0040},                   /* 00,21,40,aa */
-       {0xaa, 0x22, 0x0013},                   /* 00,22,13,aa */
-       {0xaa, 0x23, 0x004c},                   /* 00,23,4c,aa */
-       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,2f,cc */
-       {0xa0, 0x4d, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,4d,cc */
-       {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,60,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
-       {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,c3,cc */
-       {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,50,cc */
-       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},      /* 01,8c,0c,cc */
-       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,18,cc */
-       {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,18,cc */
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
-       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},       /* 00,1d,00,cc */
-       {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},       /* 00,1e,40,cc */
-       {0xa0, 0x13, ZC3XX_R01F_HSYNC_2},       /* 00,1f,13,cc */
-       {0xa0, 0x4c, ZC3XX_R020_HSYNC_3},       /* 00,20,4c,cc */
-       {}
-};
-static const struct usb_action hv7131b_60HZScale[] = { /* 320x240 */
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x25, 0x0007},                   /* 00,25,07,aa */
-       {0xaa, 0x26, 0x00a1},                   /* 00,26,a1,aa */
-       {0xaa, 0x27, 0x0020},                   /* 00,27,20,aa */
-       {0xaa, 0x20, 0x0000},                   /* 00,20,00,aa */
-       {0xaa, 0x21, 0x00a0},                   /* 00,21,a0,aa */
-       {0xaa, 0x22, 0x0016},                   /* 00,22,16,aa */
-       {0xaa, 0x23, 0x0040},                   /* 00,23,40,aa */
-       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,2f,cc */
-       {0xa0, 0x4d, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,4d,cc */
-       {0xa0, 0x60, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,60,cc */
-       {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,01,cc */
-       {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,86,cc */
-       {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,a0,cc */
-       {0xa0, 0x07, ZC3XX_R18C_AEFREEZE},      /* 01,8c,07,cc */
-       {0xa0, 0x0f, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,0f,cc */
-       {0xa0, 0x18, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,18,cc */
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
-       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},       /* 00,1d,00,cc */
-       {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1},       /* 00,1e,a0,cc */
-       {0xa0, 0x16, ZC3XX_R01F_HSYNC_2},       /* 00,1f,16,cc */
-       {0xa0, 0x40, ZC3XX_R020_HSYNC_3},       /* 00,20,40,cc */
-       {}
-};
-static const struct usb_action hv7131b_NoFliker[] = {  /* 640x480*/
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x25, 0x0003},                   /* 00,25,03,aa */
-       {0xaa, 0x26, 0x0000},                   /* 00,26,00,aa */
-       {0xaa, 0x27, 0x0000},                   /* 00,27,00,aa */
-       {0xaa, 0x20, 0x0000},                   /* 00,20,00,aa */
-       {0xaa, 0x21, 0x0010},                   /* 00,21,10,aa */
-       {0xaa, 0x22, 0x0000},                   /* 00,22,00,aa */
-       {0xaa, 0x23, 0x0003},                   /* 00,23,03,aa */
-       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,2f,cc */
-       {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,f8,cc */
-       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,00,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
-       {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,02,cc */
-       {0xa0, 0x00, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,00,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},      /* 01,8c,10,cc */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,20,cc */
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,00,cc */
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,00,cc */
-       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},       /* 00,1d,00,cc */
-       {0xa0, 0x10, ZC3XX_R01E_HSYNC_1},       /* 00,1e,10,cc */
-       {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},       /* 00,1f,00,cc */
-       {0xa0, 0x03, ZC3XX_R020_HSYNC_3},       /* 00,20,03,cc */
-       {}
-};
-static const struct usb_action hv7131b_NoFlikerScale[] = { /* 320x240 */
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x25, 0x0003},                   /* 00,25,03,aa */
-       {0xaa, 0x26, 0x0000},                   /* 00,26,00,aa */
-       {0xaa, 0x27, 0x0000},                   /* 00,27,00,aa */
-       {0xaa, 0x20, 0x0000},                   /* 00,20,00,aa */
-       {0xaa, 0x21, 0x00a0},                   /* 00,21,a0,aa */
-       {0xaa, 0x22, 0x0016},                   /* 00,22,16,aa */
-       {0xaa, 0x23, 0x0040},                   /* 00,23,40,aa */
-       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,2f,cc */
-       {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,f8,cc */
-       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,00,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
-       {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,02,cc */
-       {0xa0, 0x00, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,00,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},      /* 01,8c,10,cc */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,20,cc */
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,00,cc */
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,00,cc */
-       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},       /* 00,1d,00,cc */
-       {0xa0, 0xa0, ZC3XX_R01E_HSYNC_1},       /* 00,1e,a0,cc */
-       {0xa0, 0x16, ZC3XX_R01F_HSYNC_2},       /* 00,1f,16,cc */
-       {0xa0, 0x40, ZC3XX_R020_HSYNC_3},       /* 00,20,40,cc */
-       {}
-};
-
-/* from lPEPI264v.inf (hv7131b!) */
-static const struct usb_action hv7131r_InitialScale[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
-       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xdd, 0x00, 0x0200},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xaa, 0x01, 0x000c},
-       {0xaa, 0x11, 0x0000},
-       {0xaa, 0x13, 0x0000},
-       {0xaa, 0x14, 0x0001},
-       {0xaa, 0x15, 0x00e8},
-       {0xaa, 0x16, 0x0002},
-       {0xaa, 0x17, 0x0088},
-       {0xaa, 0x30, 0x000b},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x78, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0x00, 0x01ad},
-       {0xa0, 0xc0, 0x019b},
-       {0xa0, 0xa0, 0x019c},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {}
-};
-static const struct usb_action hv7131r_Initial[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
-       {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
-       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xdd, 0x00, 0x0200},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xaa, 0x01, 0x000c},
-       {0xaa, 0x11, 0x0000},
-       {0xaa, 0x13, 0x0000},
-       {0xaa, 0x14, 0x0001},
-       {0xaa, 0x15, 0x00e6},
-       {0xaa, 0x16, 0x0002},
-       {0xaa, 0x17, 0x0086},
-       {0xaa, 0x30, 0x000b},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x78, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0x00, 0x01ad},
-       {0xa0, 0xc0, 0x019b},
-       {0xa0, 0xa0, 0x019c},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {}
-};
-static const struct usb_action hv7131r_50HZ[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xa0, 0x06, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x68, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0xea, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x60, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action hv7131r_50HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xa0, 0x0c, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0xd1, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x40, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0xd4, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0xc0, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action hv7131r_60HZ[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xa0, 0x06, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x1a, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0xc3, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x50, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action hv7131r_60HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xa0, 0x0c, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x35, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x01, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x86, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0xa0, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x18, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action hv7131r_NoFliker[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x02, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x58, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action hv7131r_NoFlikerScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xa0, 0x2f, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0xf8, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x04, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0xb0, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x00, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x00, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0x08, ZC3XX_R020_HSYNC_3},
-       {}
-};
-
-static const struct usb_action icm105a_InitialScale[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x0c, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xa0, 0x00, ZC3XX_R097_WINYSTARTHIGH},
-       {0xa0, 0x01, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R099_WINXSTARTHIGH},
-       {0xa0, 0x01, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x01, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x01, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
-       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xaa, 0x01, 0x0010},
-       {0xaa, 0x03, 0x0000},
-       {0xaa, 0x04, 0x0001},
-       {0xaa, 0x05, 0x0020},
-       {0xaa, 0x06, 0x0001},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0001},
-       {0xaa, 0x04, 0x0011},
-       {0xaa, 0x05, 0x00a0},
-       {0xaa, 0x06, 0x0001},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0002},
-       {0xaa, 0x04, 0x0013},
-       {0xaa, 0x05, 0x0020},
-       {0xaa, 0x06, 0x0001},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0003},
-       {0xaa, 0x04, 0x0015},
-       {0xaa, 0x05, 0x0020},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0004},
-       {0xaa, 0x04, 0x0017},
-       {0xaa, 0x05, 0x0020},
-       {0xaa, 0x06, 0x000d},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0005},
-       {0xaa, 0x04, 0x0019},
-       {0xaa, 0x05, 0x0020},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0006},
-       {0xaa, 0x04, 0x0017},
-       {0xaa, 0x05, 0x0026},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0007},
-       {0xaa, 0x04, 0x0019},
-       {0xaa, 0x05, 0x0022},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0008},
-       {0xaa, 0x04, 0x0021},
-       {0xaa, 0x05, 0x00aa},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0009},
-       {0xaa, 0x04, 0x0023},
-       {0xaa, 0x05, 0x00aa},
-       {0xaa, 0x06, 0x000d},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x000a},
-       {0xaa, 0x04, 0x0025},
-       {0xaa, 0x05, 0x00aa},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x000b},
-       {0xaa, 0x04, 0x00ec},
-       {0xaa, 0x05, 0x002e},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x000c},
-       {0xaa, 0x04, 0x00fa},
-       {0xaa, 0x05, 0x002a},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x07, 0x000d},
-       {0xaa, 0x01, 0x0005},
-       {0xaa, 0x94, 0x0002},
-       {0xaa, 0x90, 0x0000},
-       {0xaa, 0x91, 0x001f},
-       {0xaa, 0x10, 0x0064},
-       {0xaa, 0x9b, 0x00f0},
-       {0xaa, 0x9c, 0x0002},
-       {0xaa, 0x14, 0x001a},
-       {0xaa, 0x20, 0x0080},
-       {0xaa, 0x22, 0x0080},
-       {0xaa, 0x24, 0x0080},
-       {0xaa, 0x26, 0x0080},
-       {0xaa, 0x00, 0x0084},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xaa, 0xa8, 0x00c0},
-       {0xa1, 0x01, 0x0002},
-       {0xa1, 0x01, 0x0008},
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x40, ZC3XX_R116_RGAIN},
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},
-       {0xa0, 0x40, ZC3XX_R118_BGAIN},
-       {0xa1, 0x01, 0x0008},
-
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
-       {0xa1, 0x01, 0x01c8},
-       {0xa1, 0x01, 0x01c9},
-       {0xa1, 0x01, 0x01ca},
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
-       {0xa0, 0x52, ZC3XX_R10A_RGB00}, /* matrix */
-       {0xa0, 0xf7, ZC3XX_R10B_RGB01},
-       {0xa0, 0xf7, ZC3XX_R10C_RGB02},
-       {0xa0, 0xf7, ZC3XX_R10D_RGB10},
-       {0xa0, 0x52, ZC3XX_R10E_RGB11},
-       {0xa0, 0xf7, ZC3XX_R10F_RGB12},
-       {0xa0, 0xf7, ZC3XX_R110_RGB20},
-       {0xa0, 0xf7, ZC3XX_R111_RGB21},
-       {0xa0, 0x52, ZC3XX_R112_RGB22},
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x0d, 0x0003},
-       {0xaa, 0x0c, 0x008c},
-       {0xaa, 0x0e, 0x0095},
-       {0xaa, 0x0f, 0x0002},
-       {0xaa, 0x1c, 0x0094},
-       {0xaa, 0x1d, 0x0002},
-       {0xaa, 0x20, 0x0080},
-       {0xaa, 0x22, 0x0080},
-       {0xaa, 0x24, 0x0080},
-       {0xaa, 0x26, 0x0080},
-       {0xaa, 0x00, 0x0084},
-       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH},
-       {0xa0, 0x94, ZC3XX_R0A4_EXPOSURETIMELOW},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x84, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xe3, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xec, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xf5, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0xc0, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x40, ZC3XX_R116_RGAIN},
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},
-       {0xa0, 0x40, ZC3XX_R118_BGAIN},
-       {}
-};
-
-static const struct usb_action icm105a_Initial[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x0c, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xa0, 0x00, ZC3XX_R097_WINYSTARTHIGH},
-       {0xa0, 0x02, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R099_WINXSTARTHIGH},
-       {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x02, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
-       {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
-       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
-       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xaa, 0x01, 0x0010},
-       {0xaa, 0x03, 0x0000},
-       {0xaa, 0x04, 0x0001},
-       {0xaa, 0x05, 0x0020},
-       {0xaa, 0x06, 0x0001},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0001},
-       {0xaa, 0x04, 0x0011},
-       {0xaa, 0x05, 0x00a0},
-       {0xaa, 0x06, 0x0001},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0002},
-       {0xaa, 0x04, 0x0013},
-       {0xaa, 0x05, 0x0020},
-       {0xaa, 0x06, 0x0001},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0003},
-       {0xaa, 0x04, 0x0015},
-       {0xaa, 0x05, 0x0020},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0004},
-       {0xaa, 0x04, 0x0017},
-       {0xaa, 0x05, 0x0020},
-       {0xaa, 0x06, 0x000d},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0005},
-       {0xa0, 0x04, ZC3XX_R092_I2CADDRESSSELECT},
-       {0xa0, 0x19, ZC3XX_R093_I2CSETVALUE},
-       {0xa0, 0x01, ZC3XX_R090_I2CCOMMAND},
-       {0xa1, 0x01, 0x0091},
-       {0xaa, 0x05, 0x0020},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0006},
-       {0xaa, 0x04, 0x0017},
-       {0xaa, 0x05, 0x0026},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0007},
-       {0xaa, 0x04, 0x0019},
-       {0xaa, 0x05, 0x0022},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0008},
-       {0xaa, 0x04, 0x0021},
-       {0xaa, 0x05, 0x00aa},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x0009},
-       {0xaa, 0x04, 0x0023},
-       {0xaa, 0x05, 0x00aa},
-       {0xaa, 0x06, 0x000d},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x000a},
-       {0xaa, 0x04, 0x0025},
-       {0xaa, 0x05, 0x00aa},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x000b},
-       {0xaa, 0x04, 0x00ec},
-       {0xaa, 0x05, 0x002e},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x03, 0x000c},
-       {0xaa, 0x04, 0x00fa},
-       {0xaa, 0x05, 0x002a},
-       {0xaa, 0x06, 0x0005},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x07, 0x000d},
-       {0xaa, 0x01, 0x0005},
-       {0xaa, 0x94, 0x0002},
-       {0xaa, 0x90, 0x0000},
-       {0xaa, 0x91, 0x0010},
-       {0xaa, 0x10, 0x0064},
-       {0xaa, 0x9b, 0x00f0},
-       {0xaa, 0x9c, 0x0002},
-       {0xaa, 0x14, 0x001a},
-       {0xaa, 0x20, 0x0080},
-       {0xaa, 0x22, 0x0080},
-       {0xaa, 0x24, 0x0080},
-       {0xaa, 0x26, 0x0080},
-       {0xaa, 0x00, 0x0084},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xaa, 0xa8, 0x0080},
-       {0xa0, 0x78, ZC3XX_R18D_YTARGET},
-       {0xa1, 0x01, 0x0002},
-       {0xa1, 0x01, 0x0008},
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x40, ZC3XX_R116_RGAIN},
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},
-       {0xa0, 0x40, ZC3XX_R118_BGAIN},
-       {0xa1, 0x01, 0x0008},
-
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
-       {0xa1, 0x01, 0x01c8},
-       {0xa1, 0x01, 0x01c9},
-       {0xa1, 0x01, 0x01ca},
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
-
-       {0xa0, 0x52, ZC3XX_R10A_RGB00}, /* matrix */
-       {0xa0, 0xf7, ZC3XX_R10B_RGB01},
-       {0xa0, 0xf7, ZC3XX_R10C_RGB02},
-       {0xa0, 0xf7, ZC3XX_R10D_RGB10},
-       {0xa0, 0x52, ZC3XX_R10E_RGB11},
-       {0xa0, 0xf7, ZC3XX_R10F_RGB12},
-       {0xa0, 0xf7, ZC3XX_R110_RGB20},
-       {0xa0, 0xf7, ZC3XX_R111_RGB21},
-       {0xa0, 0x52, ZC3XX_R112_RGB22},
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x0d, 0x0003},
-       {0xaa, 0x0c, 0x0020},
-       {0xaa, 0x0e, 0x000e},
-       {0xaa, 0x0f, 0x0002},
-       {0xaa, 0x1c, 0x000d},
-       {0xaa, 0x1d, 0x0002},
-       {0xaa, 0x20, 0x0080},
-       {0xaa, 0x22, 0x0080},
-       {0xaa, 0x24, 0x0080},
-       {0xaa, 0x26, 0x0080},
-       {0xaa, 0x00, 0x0084},
-       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH},
-       {0xa0, 0x0d, ZC3XX_R0A4_EXPOSURETIMELOW},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x1a, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x4b, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xd8, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xea, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x40, ZC3XX_R116_RGAIN},
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},
-       {0xa0, 0x40, ZC3XX_R118_BGAIN},
-       {}
-};
-static const struct usb_action icm105a_50HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
-       {0xaa, 0x0c, 0x0020}, /* 00,0c,20,aa */
-       {0xaa, 0x0e, 0x000e}, /* 00,0e,0e,aa */
-       {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
-       {0xaa, 0x1c, 0x000d}, /* 00,1c,0d,aa */
-       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
-       {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
-       {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
-       {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
-       {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
-       {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
-       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
-       {0xa0, 0x0d, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,0d,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
-       {0xa0, 0x1a, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,1a,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x4b, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,4b,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
-       {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
-       {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */
-       {0xa0, 0xd8, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d8,cc */
-       {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
-       {}
-};
-static const struct usb_action icm105a_50HZ[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
-       {0xaa, 0x0c, 0x008c}, /* 00,0c,8c,aa */
-       {0xaa, 0x0e, 0x0095}, /* 00,0e,95,aa */
-       {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
-       {0xaa, 0x1c, 0x0094}, /* 00,1c,94,aa */
-       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
-       {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
-       {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
-       {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
-       {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
-       {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
-       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
-       {0xa0, 0x94, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,94,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
-       {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x84, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,84,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
-       {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
-       {0xa0, 0xe3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,e3,cc */
-       {0xa0, 0xec, ZC3XX_R01E_HSYNC_1}, /* 00,1e,ec,cc */
-       {0xa0, 0xf5, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f5,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
-       {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
-       {}
-};
-static const struct usb_action icm105a_60HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
-       {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
-       {0xaa, 0x0e, 0x000d}, /* 00,0e,0d,aa */
-       {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
-       {0xaa, 0x1c, 0x0008}, /* 00,1c,08,aa */
-       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
-       {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
-       {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
-       {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
-       {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
-       {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
-       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
-       {0xa0, 0x08, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,08,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
-       {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x41, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,41,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
-       {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
-       {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
-       {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
-       {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
-       {}
-};
-static const struct usb_action icm105a_60HZ[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
-       {0xaa, 0x0c, 0x0008}, /* 00,0c,08,aa */
-       {0xaa, 0x0e, 0x0086}, /* 00,0e,86,aa */
-       {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
-       {0xaa, 0x1c, 0x0085}, /* 00,1c,85,aa */
-       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
-       {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
-       {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
-       {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
-       {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
-       {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
-       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
-       {0xa0, 0x85, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,85,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
-       {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,08,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,81,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
-       {0xa0, 0x12, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,12,cc */
-       {0xa0, 0xc2, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c2,cc */
-       {0xa0, 0xd6, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d6,cc */
-       {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
-       {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
-       {}
-};
-static const struct usb_action icm105a_NoFlikerScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
-       {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
-       {0xaa, 0x0e, 0x000d}, /* 00,0e,0d,aa */
-       {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
-       {0xaa, 0x1c, 0x0000}, /* 00,1c,00,aa */
-       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
-       {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
-       {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
-       {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
-       {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
-       {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
-       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
-       {0xa0, 0x00, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,00,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
-       {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
-       {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
-       {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
-       {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
-       {}
-};
-static const struct usb_action icm105a_NoFliker[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0x0d, 0x0003}, /* 00,0d,03,aa */
-       {0xaa, 0x0c, 0x0004}, /* 00,0c,04,aa */
-       {0xaa, 0x0e, 0x0081}, /* 00,0e,81,aa */
-       {0xaa, 0x0f, 0x0002}, /* 00,0f,02,aa */
-       {0xaa, 0x1c, 0x0080}, /* 00,1c,80,aa */
-       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
-       {0xaa, 0x20, 0x0080}, /* 00,20,80,aa */
-       {0xaa, 0x22, 0x0080}, /* 00,22,80,aa */
-       {0xaa, 0x24, 0x0080}, /* 00,24,80,aa */
-       {0xaa, 0x26, 0x0080}, /* 00,26,80,aa */
-       {0xaa, 0x00, 0x0084}, /* 00,00,84,aa */
-       {0xa0, 0x02, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,02,cc */
-       {0xa0, 0x80, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,80,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
-       {0xa0, 0x20, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,20,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE}, /* 01,8c,10,cc */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,20,cc */
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
-       {0xa0, 0xc1, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c1,cc */
-       {0xa0, 0xd4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d4,cc */
-       {0xa0, 0xe8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e8,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
-       {0xa0, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN}, /* 01,a7,00,cc */
-       {0xa0, 0xc0, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,c0,cc */
-       {}
-};
-
-static const struct usb_action mc501cb_Initial[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
-       {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
-       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
-       {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */
-       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
-       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
-       {0xa0, 0x33, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,33,cc */
-       {0xa0, 0x34, ZC3XX_R087_EXPTIMEMID}, /* 00,87,34,cc */
-       {0xa0, 0x35, ZC3XX_R088_EXPTIMELOW}, /* 00,88,35,cc */
-       {0xa0, 0xb0, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,b0,cc */
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
-       {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
-       {0xaa, 0x01, 0x0003}, /* 00,01,03,aa */
-       {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
-       {0xaa, 0x03, 0x0000}, /* 00,03,00,aa */
-       {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
-       {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
-       {0xaa, 0x12, 0x0000}, /* 00,12,00,aa */
-       {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
-       {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
-       {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
-       {0xaa, 0x16, 0x0000}, /* 00,16,00,aa */
-       {0xaa, 0x17, 0x0001}, /* 00,17,01,aa */
-       {0xaa, 0x18, 0x00de}, /* 00,18,de,aa */
-       {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
-       {0xaa, 0x1a, 0x0086}, /* 00,1a,86,aa */
-       {0xaa, 0x20, 0x00a8}, /* 00,20,a8,aa */
-       {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
-       {0xaa, 0x23, 0x0000}, /* 00,23,00,aa */
-       {0xaa, 0x24, 0x0000}, /* 00,24,00,aa */
-       {0xaa, 0x40, 0x0033}, /* 00,40,33,aa */
-       {0xaa, 0x41, 0x0077}, /* 00,41,77,aa */
-       {0xaa, 0x42, 0x0053}, /* 00,42,53,aa */
-       {0xaa, 0x43, 0x00b0}, /* 00,43,b0,aa */
-       {0xaa, 0x4b, 0x0001}, /* 00,4b,01,aa */
-       {0xaa, 0x72, 0x0020}, /* 00,72,20,aa */
-       {0xaa, 0x73, 0x0000}, /* 00,73,00,aa */
-       {0xaa, 0x80, 0x0000}, /* 00,80,00,aa */
-       {0xaa, 0x85, 0x0050}, /* 00,85,50,aa */
-       {0xaa, 0x91, 0x0070}, /* 00,91,70,aa */
-       {0xaa, 0x92, 0x0072}, /* 00,92,72,aa */
-       {0xaa, 0x03, 0x0001}, /* 00,03,01,aa */
-       {0xaa, 0x10, 0x00a0}, /* 00,10,a0,aa */
-       {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */
-       {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */
-       {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */
-       {0xaa, 0xa0, 0x001a}, /* 00,a0,1a,aa */
-       {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */
-       {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */
-       {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */
-       {0xaa, 0xa4, 0x0010}, /* 00,a4,10,aa */
-       {0xaa, 0xa5, 0x0020}, /* 00,a5,20,aa */
-       {0xaa, 0xb1, 0x0044}, /* 00,b1,44,aa */
-       {0xaa, 0xd0, 0x0001}, /* 00,d0,01,aa */
-       {0xaa, 0xd1, 0x0085}, /* 00,d1,85,aa */
-       {0xaa, 0xd2, 0x0080}, /* 00,d2,80,aa */
-       {0xaa, 0xd3, 0x0080}, /* 00,d3,80,aa */
-       {0xaa, 0xd4, 0x0080}, /* 00,d4,80,aa */
-       {0xaa, 0xd5, 0x0080}, /* 00,d5,80,aa */
-       {0xaa, 0xc0, 0x00c3}, /* 00,c0,c3,aa */
-       {0xaa, 0xc2, 0x0044}, /* 00,c2,44,aa */
-       {0xaa, 0xc4, 0x0040}, /* 00,c4,40,aa */
-       {0xaa, 0xc5, 0x0020}, /* 00,c5,20,aa */
-       {0xaa, 0xc6, 0x0008}, /* 00,c6,08,aa */
-       {0xaa, 0x03, 0x0004}, /* 00,03,04,aa */
-       {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
-       {0xaa, 0x40, 0x0030}, /* 00,40,30,aa */
-       {0xaa, 0x41, 0x0020}, /* 00,41,20,aa */
-       {0xaa, 0x42, 0x002d}, /* 00,42,2d,aa */
-       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
-       {0xaa, 0x1c, 0x0050}, /* 00,1C,50,aa */
-       {0xaa, 0x11, 0x0081}, /* 00,11,81,aa */
-       {0xaa, 0x3b, 0x001d}, /* 00,3b,1D,aa */
-       {0xaa, 0x3c, 0x004c}, /* 00,3c,4C,aa */
-       {0xaa, 0x3d, 0x0018}, /* 00,3d,18,aa */
-       {0xaa, 0x3e, 0x006a}, /* 00,3e,6A,aa */
-       {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
-       {0xaa, 0x52, 0x00ff}, /* 00,52,FF,aa */
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
-       {0xaa, 0x03, 0x0002}, /* 00,03,02,aa */
-       {0xaa, 0x51, 0x0027}, /* 00,51,27,aa */
-       {0xaa, 0x52, 0x0020}, /* 00,52,20,aa */
-       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
-       {0xaa, 0x50, 0x0010}, /* 00,50,10,aa */
-       {0xaa, 0x51, 0x0010}, /* 00,51,10,aa */
-       {0xaa, 0x54, 0x0010}, /* 00,54,10,aa */
-       {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */
-       {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */
-       {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */
-
-       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
-       {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
-       {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
-       {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */
-       {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */
-       {}
-};
-
-static const struct usb_action mc501cb_InitialScale[] = {      /* 320x240 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
-       {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
-       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH}, /* 00,9b,01,cc */
-       {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,d8,cc */
-       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH}, /* 00,9d,02,cc */
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
-       {0xa0, 0x33, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,33,cc */
-       {0xa0, 0x34, ZC3XX_R087_EXPTIMEMID}, /* 00,87,34,cc */
-       {0xa0, 0x35, ZC3XX_R088_EXPTIMELOW}, /* 00,88,35,cc */
-       {0xa0, 0xb0, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,b0,cc */
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
-       {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
-       {0xaa, 0x01, 0x0003}, /* 00,01,03,aa */
-       {0xaa, 0x01, 0x0001}, /* 00,01,01,aa */
-       {0xaa, 0x03, 0x0000}, /* 00,03,00,aa */
-       {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
-       {0xaa, 0x11, 0x0080}, /* 00,11,80,aa */
-       {0xaa, 0x12, 0x0000}, /* 00,12,00,aa */
-       {0xaa, 0x13, 0x0000}, /* 00,13,00,aa */
-       {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
-       {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
-       {0xaa, 0x16, 0x0000}, /* 00,16,00,aa */
-       {0xaa, 0x17, 0x0001}, /* 00,17,01,aa */
-       {0xaa, 0x18, 0x00d8}, /* 00,18,d8,aa */
-       {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
-       {0xaa, 0x1a, 0x0088}, /* 00,1a,88,aa */
-       {0xaa, 0x20, 0x00a8}, /* 00,20,a8,aa */
-       {0xaa, 0x22, 0x0000}, /* 00,22,00,aa */
-       {0xaa, 0x23, 0x0000}, /* 00,23,00,aa */
-       {0xaa, 0x24, 0x0000}, /* 00,24,00,aa */
-       {0xaa, 0x40, 0x0033}, /* 00,40,33,aa */
-       {0xaa, 0x41, 0x0077}, /* 00,41,77,aa */
-       {0xaa, 0x42, 0x0053}, /* 00,42,53,aa */
-       {0xaa, 0x43, 0x00b0}, /* 00,43,b0,aa */
-       {0xaa, 0x4b, 0x0001}, /* 00,4b,01,aa */
-       {0xaa, 0x72, 0x0020}, /* 00,72,20,aa */
-       {0xaa, 0x73, 0x0000}, /* 00,73,00,aa */
-       {0xaa, 0x80, 0x0000}, /* 00,80,00,aa */
-       {0xaa, 0x85, 0x0050}, /* 00,85,50,aa */
-       {0xaa, 0x91, 0x0070}, /* 00,91,70,aa */
-       {0xaa, 0x92, 0x0072}, /* 00,92,72,aa */
-       {0xaa, 0x03, 0x0001}, /* 00,03,01,aa */
-       {0xaa, 0x10, 0x00a0}, /* 00,10,a0,aa */
-       {0xaa, 0x11, 0x0001}, /* 00,11,01,aa */
-       {0xaa, 0x30, 0x0000}, /* 00,30,00,aa */
-       {0xaa, 0x60, 0x0000}, /* 00,60,00,aa */
-       {0xaa, 0xa0, 0x001a}, /* 00,a0,1a,aa */
-       {0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */
-       {0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */
-       {0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */
-       {0xaa, 0xa4, 0x0010}, /* 00,a4,10,aa */
-       {0xaa, 0xa5, 0x0020}, /* 00,a5,20,aa */
-       {0xaa, 0xb1, 0x0044}, /* 00,b1,44,aa */
-       {0xaa, 0xd0, 0x0001}, /* 00,d0,01,aa */
-       {0xaa, 0xd1, 0x0085}, /* 00,d1,85,aa */
-       {0xaa, 0xd2, 0x0080}, /* 00,d2,80,aa */
-       {0xaa, 0xd3, 0x0080}, /* 00,d3,80,aa */
-       {0xaa, 0xd4, 0x0080}, /* 00,d4,80,aa */
-       {0xaa, 0xd5, 0x0080}, /* 00,d5,80,aa */
-       {0xaa, 0xc0, 0x00c3}, /* 00,c0,c3,aa */
-       {0xaa, 0xc2, 0x0044}, /* 00,c2,44,aa */
-       {0xaa, 0xc4, 0x0040}, /* 00,c4,40,aa */
-       {0xaa, 0xc5, 0x0020}, /* 00,c5,20,aa */
-       {0xaa, 0xc6, 0x0008}, /* 00,c6,08,aa */
-       {0xaa, 0x03, 0x0004}, /* 00,03,04,aa */
-       {0xaa, 0x10, 0x0000}, /* 00,10,00,aa */
-       {0xaa, 0x40, 0x0030}, /* 00,40,30,aa */
-       {0xaa, 0x41, 0x0020}, /* 00,41,20,aa */
-       {0xaa, 0x42, 0x002d}, /* 00,42,2d,aa */
-       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
-       {0xaa, 0x1c, 0x0050}, /* 00,1c,50,aa */
-       {0xaa, 0x11, 0x0081}, /* 00,11,81,aa */
-       {0xaa, 0x3b, 0x003a}, /* 00,3b,3A,aa */
-       {0xaa, 0x3c, 0x0098}, /* 00,3c,98,aa */
-       {0xaa, 0x3d, 0x0030}, /* 00,3d,30,aa */
-       {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
-       {0xaa, 0x01, 0x0000}, /* 00,01,00,aa */
-       {0xaa, 0x52, 0x00ff}, /* 00,52,FF,aa */
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,37,cc */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
-       {0xaa, 0x03, 0x0002}, /* 00,03,02,aa */
-       {0xaa, 0x51, 0x004e}, /* 00,51,4E,aa */
-       {0xaa, 0x52, 0x0041}, /* 00,52,41,aa */
-       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
-       {0xaa, 0x50, 0x0010}, /* 00,50,10,aa */
-       {0xaa, 0x51, 0x0010}, /* 00,51,10,aa */
-       {0xaa, 0x54, 0x0010}, /* 00,54,10,aa */
-       {0xaa, 0x55, 0x0010}, /* 00,55,10,aa */
-       {0xa0, 0xf0, 0x0199}, /* 01,99,F0,cc */
-       {0xa0, 0x80, 0x019a}, /* 01,9A,80,cc */
-       {}
-};
-
-static const struct usb_action mc501cb_50HZ[] = {
-       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
-       {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
-       {0xaa, 0x36, 0x001d}, /* 00,36,1D,aa */
-       {0xaa, 0x37, 0x004c}, /* 00,37,4C,aa */
-       {0xaa, 0x3b, 0x001d}, /* 00,3B,1D,aa */
-       {0xaa, 0x3c, 0x004c}, /* 00,3C,4C,aa */
-       {0xaa, 0x3d, 0x001d}, /* 00,3D,1D,aa */
-       {0xaa, 0x3e, 0x004c}, /* 00,3E,4C,aa */
-       {}
-};
-
-static const struct usb_action mc501cb_50HZScale[] = {
-       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
-       {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
-       {0xaa, 0x36, 0x003a}, /* 00,36,3A,aa */
-       {0xaa, 0x37, 0x0098}, /* 00,37,98,aa */
-       {0xaa, 0x3b, 0x003a}, /* 00,3B,3A,aa */
-       {0xaa, 0x3c, 0x0098}, /* 00,3C,98,aa */
-       {0xaa, 0x3d, 0x003a}, /* 00,3D,3A,aa */
-       {0xaa, 0x3e, 0x0098}, /* 00,3E,98,aa */
-       {}
-};
-
-static const struct usb_action mc501cb_60HZ[] = {
-       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
-       {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
-       {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
-       {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
-       {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
-       {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */
-       {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */
-       {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */
-       {}
-};
-
-static const struct usb_action mc501cb_60HZScale[] = {
-       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
-       {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
-       {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
-       {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
-       {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
-       {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
-       {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */
-       {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */
-       {}
-};
-
-static const struct usb_action mc501cb_NoFliker[] = {
-       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
-       {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
-       {0xaa, 0x36, 0x0018}, /* 00,36,18,aa */
-       {0xaa, 0x37, 0x006a}, /* 00,37,6A,aa */
-       {0xaa, 0x3d, 0x0018}, /* 00,3D,18,aa */
-       {0xaa, 0x3e, 0x006a}, /* 00,3E,6A,aa */
-       {0xaa, 0x3b, 0x0018}, /* 00,3B,18,aa */
-       {0xaa, 0x3c, 0x006a}, /* 00,3C,6A,aa */
-       {}
-};
-
-static const struct usb_action mc501cb_NoFlikerScale[] = {
-       {0xaa, 0x03, 0x0003}, /* 00,03,03,aa */
-       {0xaa, 0x10, 0x00fc}, /* 00,10,fc,aa */
-       {0xaa, 0x36, 0x0030}, /* 00,36,30,aa */
-       {0xaa, 0x37, 0x00d4}, /* 00,37,D4,aa */
-       {0xaa, 0x3d, 0x0030}, /* 00,3D,30,aa */
-       {0xaa, 0x3e, 0x00d4}, /* 00,3E,D4,aa */
-       {0xaa, 0x3b, 0x0030}, /* 00,3B,30,aa */
-       {0xaa, 0x3c, 0x00d4}, /* 00,3C,D4,aa */
-       {}
-};
-
-/* from zs211.inf */
-static const struct usb_action ov7620_Initial[] = {    /* 640x480 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
-       {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT}, /* 00,02,40,cc */
-       {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING}, /* 00,08,00,cc */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
-       {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */
-       {0xa0, 0x02, ZC3XX_R083_RGAINADDR}, /* 00,83,02,cc */
-       {0xa0, 0x01, ZC3XX_R085_BGAINADDR}, /* 00,85,01,cc */
-       {0xa0, 0x80, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,80,cc */
-       {0xa0, 0x81, ZC3XX_R087_EXPTIMEMID}, /* 00,87,81,cc */
-       {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW}, /* 00,88,10,cc */
-       {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,a1,cc */
-       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
-       {0xa0, 0xd8, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d8,cc */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
-       {0xa0, 0xde, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,de,cc */
-       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,86,cc */
-       {0xaa, 0x12, 0x0088}, /* 00,12,88,aa */
-       {0xaa, 0x12, 0x0048}, /* 00,12,48,aa */
-       {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
-       {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
-       {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
-       {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
-       {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
-       {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
-       {0xaa, 0x17, 0x0018}, /* 00,17,18,aa */
-       {0xaa, 0x18, 0x00ba}, /* 00,18,ba,aa */
-       {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
-       {0xaa, 0x1a, 0x00f1}, /* 00,1a,f1,aa */
-       {0xaa, 0x20, 0x0040}, /* 00,20,40,aa */
-       {0xaa, 0x24, 0x0088}, /* 00,24,88,aa */
-       {0xaa, 0x25, 0x0078}, /* 00,25,78,aa */
-       {0xaa, 0x27, 0x00f6}, /* 00,27,f6,aa */
-       {0xaa, 0x28, 0x00a0}, /* 00,28,a0,aa */
-       {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
-       {0xaa, 0x2a, 0x0083}, /* 00,2a,83,aa */
-       {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
-       {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
-       {0xaa, 0x74, 0x0020}, /* 00,74,20,aa */
-       {0xaa, 0x61, 0x0068}, /* 00,61,68,aa */
-       {0xaa, 0x64, 0x0088}, /* 00,64,88,aa */
-       {0xaa, 0x00, 0x0000}, /* 00,00,00,aa */
-       {0xaa, 0x06, 0x0080}, /* 00,06,80,aa */
-       {0xaa, 0x01, 0x0090}, /* 00,01,90,aa */
-       {0xaa, 0x02, 0x0030}, /* 00,02,30,aa */
-       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,77,cc */
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
-       {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
-       {0xa0, 0x68, ZC3XX_R116_RGAIN}, /* 01,16,68,cc */
-       {0xa0, 0x52, ZC3XX_R118_BGAIN}, /* 01,18,52,cc */
-       {0xa0, 0x40, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,40,cc */
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
-       {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,50,cc */
-       {}
-};
-static const struct usb_action ov7620_InitialScale[] = {       /* 320x240 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
-       {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT},   /* 00,02,50,cc */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00,08,00,cc */
-                                               /* mx change? */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
-       {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,06,cc */
-       {0xa0, 0x02, ZC3XX_R083_RGAINADDR},     /* 00,83,02,cc */
-       {0xa0, 0x01, ZC3XX_R085_BGAINADDR},     /* 00,85,01,cc */
-       {0xa0, 0x80, ZC3XX_R086_EXPTIMEHIGH},   /* 00,86,80,cc */
-       {0xa0, 0x81, ZC3XX_R087_EXPTIMEMID},    /* 00,87,81,cc */
-       {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW},    /* 00,88,10,cc */
-       {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,a1,cc */
-       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE}, /* 00,8d,08,cc */
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
-       {0xa0, 0xd0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,d0,cc */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},  /* 00,98,00,cc */
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},  /* 00,9a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},     /* 01,1a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},     /* 01,1c,00,cc */
-       {0xa0, 0xd6, ZC3XX_R09C_WINHEIGHTLOW},  /* 00,9c,d6,cc */
-                                               /* OV7648 00,9c,d8,cc */
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},   /* 00,9e,88,cc */
-       {0xaa, 0x12, 0x0088}, /* 00,12,88,aa */
-       {0xaa, 0x12, 0x0048}, /* 00,12,48,aa */
-       {0xaa, 0x75, 0x008a}, /* 00,75,8a,aa */
-       {0xaa, 0x13, 0x00a3}, /* 00,13,a3,aa */
-       {0xaa, 0x04, 0x0000}, /* 00,04,00,aa */
-       {0xaa, 0x05, 0x0000}, /* 00,05,00,aa */
-       {0xaa, 0x14, 0x0000}, /* 00,14,00,aa */
-       {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */
-       {0xaa, 0x24, 0x0088}, /* 00,24,88,aa */
-       {0xaa, 0x25, 0x0078}, /* 00,25,78,aa */
-       {0xaa, 0x17, 0x0018}, /* 00,17,18,aa */
-       {0xaa, 0x18, 0x00ba}, /* 00,18,ba,aa */
-       {0xaa, 0x19, 0x0002}, /* 00,19,02,aa */
-       {0xaa, 0x1a, 0x00f2}, /* 00,1a,f2,aa */
-       {0xaa, 0x20, 0x0040}, /* 00,20,40,aa */
-       {0xaa, 0x27, 0x00f6}, /* 00,27,f6,aa */
-       {0xaa, 0x28, 0x00a0}, /* 00,28,a0,aa */
-       {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
-       {0xaa, 0x2a, 0x0083}, /* 00,2a,83,aa */
-       {0xaa, 0x2b, 0x0096}, /* 00,2b,96,aa */
-       {0xaa, 0x2d, 0x0005}, /* 00,2d,05,aa */
-       {0xaa, 0x74, 0x0020}, /* 00,74,20,aa */
-       {0xaa, 0x61, 0x0068}, /* 00,61,68,aa */
-       {0xaa, 0x64, 0x0088}, /* 00,64,88,aa */
-       {0xaa, 0x00, 0x0000}, /* 00,00,00,aa */
-       {0xaa, 0x06, 0x0080}, /* 00,06,80,aa */
-       {0xaa, 0x01, 0x0090}, /* 00,01,90,aa */
-       {0xaa, 0x02, 0x0030}, /* 00,02,30,aa */
-       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,77,cc */
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},     /* 01,89,06,cc */
-       {0xa0, 0x00, 0x01ad},                   /* 01,ad,00,cc */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},   /* 01,cb,13,cc */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},  /* 03,01,08,cc */
-       {0xa0, 0x68, ZC3XX_R116_RGAIN},         /* 01,16,68,cc */
-       {0xa0, 0x52, ZC3XX_R118_BGAIN},         /* 01,18,52,cc */
-       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},    /* 01,1d,50,cc */
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
-       {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},   /* 01,a8,50,cc */
-       {}
-};
-static const struct usb_action ov7620_50HZ[] = {
-       {0xaa, 0x13, 0x00a3},   /* 00,13,a3,aa */
-       {0xdd, 0x00, 0x0100},   /* 00,01,00,dd */
-       {0xaa, 0x2b, 0x0096},   /* 00,2b,96,aa */
-       {0xaa, 0x75, 0x008a},   /* 00,75,8a,aa */
-       {0xaa, 0x2d, 0x0005},   /* 00,2d,05,aa */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,04,cc */
-       {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,18,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
-       {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,83,cc */
-       {0xaa, 0x10, 0x0082},                           /* 00,10,82,aa */
-       {0xaa, 0x76, 0x0003},                           /* 00,76,03,aa */
-/*     {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT},            * 00,02,40,cc
-                                                        * if mode0 (640x480) */
-       {}
-};
-static const struct usb_action ov7620_60HZ[] = {
-       {0xaa, 0x13, 0x00a3},                   /* 00,13,a3,aa */
-                                               /* (bug in zs211.inf) */
-       {0xdd, 0x00, 0x0100},                   /* 00,01,00,dd */
-       {0xaa, 0x2b, 0x0000},                   /* 00,2b,00,aa */
-       {0xaa, 0x75, 0x008a},                   /* 00,75,8a,aa */
-       {0xaa, 0x2d, 0x0005},                   /* 00,2d,05,aa */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
-       {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x83, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,83,cc */
-       {0xaa, 0x10, 0x0020},                   /* 00,10,20,aa */
-       {0xaa, 0x76, 0x0003},                   /* 00,76,03,aa */
-/*     {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT},    * 00,02,40,cc
-                                                * if mode0 (640x480) */
-/* ?? in gspca v1, it was
-       {0xa0, 0x00, 0x0039},  * 00,00,00,dd *
-       {0xa1, 0x01, 0x0037},           */
-       {}
-};
-static const struct usb_action ov7620_NoFliker[] = {
-       {0xaa, 0x13, 0x00a3},                   /* 00,13,a3,aa */
-                                               /* (bug in zs211.inf) */
-       {0xdd, 0x00, 0x0100},                   /* 00,01,00,dd */
-       {0xaa, 0x2b, 0x0000},                   /* 00,2b,00,aa */
-       {0xaa, 0x75, 0x008e},                   /* 00,75,8e,aa */
-       {0xaa, 0x2d, 0x0001},                   /* 00,2d,01,aa */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,04,cc */
-       {0xa0, 0x18, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,18,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,01,cc */
-/*     {0xa0, 0x44, ZC3XX_R002_CLOCKSELECT},    * 00,02,44,cc
-                                                * if mode1 (320x240) */
-/* ?? was
-       {0xa0, 0x00, 0x0039},  * 00,00,00,dd *
-       {0xa1, 0x01, 0x0037},           */
-       {}
-};
-
-static const struct usb_action ov7630c_InitialScale[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xaa, 0x12, 0x0080},
-       {0xa0, 0x02, ZC3XX_R083_RGAINADDR},
-       {0xa0, 0x01, ZC3XX_R085_BGAINADDR},
-       {0xa0, 0x90, ZC3XX_R086_EXPTIMEHIGH},
-       {0xa0, 0x91, ZC3XX_R087_EXPTIMEMID},
-       {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0xd8, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
-       {0xaa, 0x12, 0x0069},
-       {0xaa, 0x04, 0x0020},
-       {0xaa, 0x06, 0x0050},
-       {0xaa, 0x13, 0x0083},
-       {0xaa, 0x14, 0x0000},
-       {0xaa, 0x15, 0x0024},
-       {0xaa, 0x17, 0x0018},
-       {0xaa, 0x18, 0x00ba},
-       {0xaa, 0x19, 0x0002},
-       {0xaa, 0x1a, 0x00f6},
-       {0xaa, 0x1b, 0x0002},
-       {0xaa, 0x20, 0x00c2},
-       {0xaa, 0x24, 0x0060},
-       {0xaa, 0x25, 0x0040},
-       {0xaa, 0x26, 0x0030},
-       {0xaa, 0x27, 0x00ea},
-       {0xaa, 0x28, 0x00a0},
-       {0xaa, 0x21, 0x0000},
-       {0xaa, 0x2a, 0x0081},
-       {0xaa, 0x2b, 0x0096},
-       {0xaa, 0x2d, 0x0094},
-       {0xaa, 0x2f, 0x003d},
-       {0xaa, 0x30, 0x0024},
-       {0xaa, 0x60, 0x0000},
-       {0xaa, 0x61, 0x0040},
-       {0xaa, 0x68, 0x007c},
-       {0xaa, 0x6f, 0x0015},
-       {0xaa, 0x75, 0x0088},
-       {0xaa, 0x77, 0x00b5},
-       {0xaa, 0x01, 0x0060},
-       {0xaa, 0x02, 0x0060},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x00, 0x01ad},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa0, 0x60, ZC3XX_R116_RGAIN},
-       {0xa0, 0x46, ZC3XX_R118_BGAIN},
-       {0xa0, 0x04, ZC3XX_R113_RGB03},
-/* 0x10, */
-       {0xa1, 0x01, 0x0002},
-       {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
-       {0xa0, 0xf8, ZC3XX_R10B_RGB01},
-       {0xa0, 0xf8, ZC3XX_R10C_RGB02},
-       {0xa0, 0xf8, ZC3XX_R10D_RGB10},
-       {0xa0, 0x50, ZC3XX_R10E_RGB11},
-       {0xa0, 0xf8, ZC3XX_R10F_RGB12},
-       {0xa0, 0xf8, ZC3XX_R110_RGB20},
-       {0xa0, 0xf8, ZC3XX_R111_RGB21},
-       {0xa0, 0x50, ZC3XX_R112_RGB22},
-       {0xa1, 0x01, 0x0008},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
-       {0xa1, 0x01, 0x01c8},
-       {0xa1, 0x01, 0x01c9},
-       {0xa1, 0x01, 0x01ca},
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
-       {0xa0, 0x01, ZC3XX_R120_GAMMA00},       /* gamma 2 ?*/
-       {0xa0, 0x0c, ZC3XX_R121_GAMMA01},
-       {0xa0, 0x1f, ZC3XX_R122_GAMMA02},
-       {0xa0, 0x3a, ZC3XX_R123_GAMMA03},
-       {0xa0, 0x53, ZC3XX_R124_GAMMA04},
-       {0xa0, 0x6d, ZC3XX_R125_GAMMA05},
-       {0xa0, 0x85, ZC3XX_R126_GAMMA06},
-       {0xa0, 0x9c, ZC3XX_R127_GAMMA07},
-       {0xa0, 0xb0, ZC3XX_R128_GAMMA08},
-       {0xa0, 0xc2, ZC3XX_R129_GAMMA09},
-       {0xa0, 0xd1, ZC3XX_R12A_GAMMA0A},
-       {0xa0, 0xde, ZC3XX_R12B_GAMMA0B},
-       {0xa0, 0xe9, ZC3XX_R12C_GAMMA0C},
-       {0xa0, 0xf2, ZC3XX_R12D_GAMMA0D},
-       {0xa0, 0xf9, ZC3XX_R12E_GAMMA0E},
-       {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
-       {0xa0, 0x05, ZC3XX_R130_GAMMA10},
-       {0xa0, 0x0f, ZC3XX_R131_GAMMA11},
-       {0xa0, 0x16, ZC3XX_R132_GAMMA12},
-       {0xa0, 0x1a, ZC3XX_R133_GAMMA13},
-       {0xa0, 0x19, ZC3XX_R134_GAMMA14},
-       {0xa0, 0x19, ZC3XX_R135_GAMMA15},
-       {0xa0, 0x17, ZC3XX_R136_GAMMA16},
-       {0xa0, 0x15, ZC3XX_R137_GAMMA17},
-       {0xa0, 0x12, ZC3XX_R138_GAMMA18},
-       {0xa0, 0x10, ZC3XX_R139_GAMMA19},
-       {0xa0, 0x0e, ZC3XX_R13A_GAMMA1A},
-       {0xa0, 0x0b, ZC3XX_R13B_GAMMA1B},
-       {0xa0, 0x09, ZC3XX_R13C_GAMMA1C},
-       {0xa0, 0x08, ZC3XX_R13D_GAMMA1D},
-       {0xa0, 0x06, ZC3XX_R13E_GAMMA1E},
-       {0xa0, 0x03, ZC3XX_R13F_GAMMA1F},
-       {0xa0, 0x50, ZC3XX_R10A_RGB00}, /* matrix */
-       {0xa0, 0xf8, ZC3XX_R10B_RGB01},
-       {0xa0, 0xf8, ZC3XX_R10C_RGB02},
-       {0xa0, 0xf8, ZC3XX_R10D_RGB10},
-       {0xa0, 0x50, ZC3XX_R10E_RGB11},
-       {0xa0, 0xf8, ZC3XX_R10F_RGB12},
-       {0xa0, 0xf8, ZC3XX_R110_RGB20},
-       {0xa0, 0xf8, ZC3XX_R111_RGB21},
-       {0xa0, 0x50, ZC3XX_R112_RGB22},
-
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xaa, 0x10, 0x001b},
-       {0xaa, 0x76, 0x0002},
-       {0xaa, 0x2a, 0x0081},
-       {0xaa, 0x2b, 0x0000},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x01, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xb8, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x37, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xaa, 0x13, 0x0083},   /* 40 */
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {}
-};
-
-static const struct usb_action ov7630c_Initial[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x06, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0xa1, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-
-       {0xaa, 0x12, 0x0080},
-       {0xa0, 0x02, ZC3XX_R083_RGAINADDR},
-       {0xa0, 0x01, ZC3XX_R085_BGAINADDR},
-       {0xa0, 0x90, ZC3XX_R086_EXPTIMEHIGH},
-       {0xa0, 0x91, ZC3XX_R087_EXPTIMEMID},
-       {0xa0, 0x10, ZC3XX_R088_EXPTIMELOW},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
-       {0xaa, 0x12, 0x0069},   /* i2c */
-       {0xaa, 0x04, 0x0020},
-       {0xaa, 0x06, 0x0050},
-       {0xaa, 0x13, 0x00c3},
-       {0xaa, 0x14, 0x0000},
-       {0xaa, 0x15, 0x0024},
-       {0xaa, 0x19, 0x0003},
-       {0xaa, 0x1a, 0x00f6},
-       {0xaa, 0x1b, 0x0002},
-       {0xaa, 0x20, 0x00c2},
-       {0xaa, 0x24, 0x0060},
-       {0xaa, 0x25, 0x0040},
-       {0xaa, 0x26, 0x0030},
-       {0xaa, 0x27, 0x00ea},
-       {0xaa, 0x28, 0x00a0},
-       {0xaa, 0x21, 0x0000},
-       {0xaa, 0x2a, 0x0081},
-       {0xaa, 0x2b, 0x0096},
-       {0xaa, 0x2d, 0x0084},
-       {0xaa, 0x2f, 0x003d},
-       {0xaa, 0x30, 0x0024},
-       {0xaa, 0x60, 0x0000},
-       {0xaa, 0x61, 0x0040},
-       {0xaa, 0x68, 0x007c},
-       {0xaa, 0x6f, 0x0015},
-       {0xaa, 0x75, 0x0088},
-       {0xaa, 0x77, 0x00b5},
-       {0xaa, 0x01, 0x0060},
-       {0xaa, 0x02, 0x0060},
-       {0xaa, 0x17, 0x0018},
-       {0xaa, 0x18, 0x00ba},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x77, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x04, ZC3XX_R1A7_CALCGLOBALMEAN},
-       {0xa0, 0x00, 0x01ad},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa0, 0x60, ZC3XX_R116_RGAIN},
-       {0xa0, 0x46, ZC3XX_R118_BGAIN},
-       {0xa0, 0x04, ZC3XX_R113_RGB03},
-
-       {0xa1, 0x01, 0x0002},
-       {0xa0, 0x4e, ZC3XX_R10A_RGB00}, /* matrix */
-       {0xa0, 0xfe, ZC3XX_R10B_RGB01},
-       {0xa0, 0xf4, ZC3XX_R10C_RGB02},
-       {0xa0, 0xf7, ZC3XX_R10D_RGB10},
-       {0xa0, 0x4d, ZC3XX_R10E_RGB11},
-       {0xa0, 0xfc, ZC3XX_R10F_RGB12},
-       {0xa0, 0x00, ZC3XX_R110_RGB20},
-       {0xa0, 0xf6, ZC3XX_R111_RGB21},
-       {0xa0, 0x4a, ZC3XX_R112_RGB22},
-
-       {0xa1, 0x01, 0x0008},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* clock ? */
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},   /* sharpness+ */
-       {0xa1, 0x01, 0x01c8},
-       {0xa1, 0x01, 0x01c9},
-       {0xa1, 0x01, 0x01ca},
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},   /* sharpness- */
-       {0xa0, 0x16, ZC3XX_R120_GAMMA00},       /* gamma ~4 */
-       {0xa0, 0x3a, ZC3XX_R121_GAMMA01},
-       {0xa0, 0x5b, ZC3XX_R122_GAMMA02},
-       {0xa0, 0x7c, ZC3XX_R123_GAMMA03},
-       {0xa0, 0x94, ZC3XX_R124_GAMMA04},
-       {0xa0, 0xa9, ZC3XX_R125_GAMMA05},
-       {0xa0, 0xbb, ZC3XX_R126_GAMMA06},
-       {0xa0, 0xca, ZC3XX_R127_GAMMA07},
-       {0xa0, 0xd7, ZC3XX_R128_GAMMA08},
-       {0xa0, 0xe1, ZC3XX_R129_GAMMA09},
-       {0xa0, 0xea, ZC3XX_R12A_GAMMA0A},
-       {0xa0, 0xf1, ZC3XX_R12B_GAMMA0B},
-       {0xa0, 0xf7, ZC3XX_R12C_GAMMA0C},
-       {0xa0, 0xfc, ZC3XX_R12D_GAMMA0D},
-       {0xa0, 0xff, ZC3XX_R12E_GAMMA0E},
-       {0xa0, 0xff, ZC3XX_R12F_GAMMA0F},
-       {0xa0, 0x20, ZC3XX_R130_GAMMA10},
-       {0xa0, 0x22, ZC3XX_R131_GAMMA11},
-       {0xa0, 0x20, ZC3XX_R132_GAMMA12},
-       {0xa0, 0x1c, ZC3XX_R133_GAMMA13},
-       {0xa0, 0x16, ZC3XX_R134_GAMMA14},
-       {0xa0, 0x13, ZC3XX_R135_GAMMA15},
-       {0xa0, 0x10, ZC3XX_R136_GAMMA16},
-       {0xa0, 0x0d, ZC3XX_R137_GAMMA17},
-       {0xa0, 0x0b, ZC3XX_R138_GAMMA18},
-       {0xa0, 0x09, ZC3XX_R139_GAMMA19},
-       {0xa0, 0x07, ZC3XX_R13A_GAMMA1A},
-       {0xa0, 0x06, ZC3XX_R13B_GAMMA1B},
-       {0xa0, 0x05, ZC3XX_R13C_GAMMA1C},
-       {0xa0, 0x04, ZC3XX_R13D_GAMMA1D},
-       {0xa0, 0x00, ZC3XX_R13E_GAMMA1E},
-       {0xa0, 0x01, ZC3XX_R13F_GAMMA1F},
-       {0xa0, 0x4e, ZC3XX_R10A_RGB00}, /* matrix */
-       {0xa0, 0xfe, ZC3XX_R10B_RGB01},
-       {0xa0, 0xf4, ZC3XX_R10C_RGB02},
-       {0xa0, 0xf7, ZC3XX_R10D_RGB10},
-       {0xa0, 0x4d, ZC3XX_R10E_RGB11},
-       {0xa0, 0xfc, ZC3XX_R10F_RGB12},
-       {0xa0, 0x00, ZC3XX_R110_RGB20},
-       {0xa0, 0xf6, ZC3XX_R111_RGB21},
-       {0xa0, 0x4a, ZC3XX_R112_RGB22},
-
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xaa, 0x10, 0x000d},
-       {0xaa, 0x76, 0x0002},
-       {0xaa, 0x2a, 0x0081},
-       {0xaa, 0x2b, 0x0000},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xd8, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x1b, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xaa, 0x13, 0x00c3},
-
-       {0xa1, 0x01, 0x0180},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {}
-};
-
-static const struct usb_action pas106b_Initial_com[] = {
-/* Sream and Sensor specific */
-       {0xa1, 0x01, 0x0010},   /* CMOSSensorSelect */
-/* System */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* SystemControl */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* SystemControl */
-/* Picture size */
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},   /* ClockSelect */
-       {0xa0, 0x03, 0x003a},
-       {0xa0, 0x0c, 0x003b},
-       {0xa0, 0x04, 0x0038},
-       {}
-};
-
-static const struct usb_action pas106b_InitialScale[] = {      /* 176x144 */
-/* JPEG control */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-/* Sream and Sensor specific */
-       {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT},
-/* Picture size */
-       {0xa0, 0x00, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0xb0, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x00, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0x90, ZC3XX_R006_FRAMEHEIGHTLOW},
-/* System */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-/* Sream and Sensor specific */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-/* Sensor Interface */
-       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
-/* Window inside sensor array */
-       {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW},
-/* Init the sensor */
-       {0xaa, 0x02, 0x0004},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x09, 0x0005},
-       {0xaa, 0x0a, 0x0002},
-       {0xaa, 0x0b, 0x0002},
-       {0xaa, 0x0c, 0x0005},
-       {0xaa, 0x0d, 0x0000},
-       {0xaa, 0x0e, 0x0002},
-       {0xaa, 0x14, 0x0081},
-/* Other registers */
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
-/* Frame retreiving */
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-/* Gains */
-       {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN},
-/* Unknown */
-       {0xa0, 0x00, 0x01ad},
-/* Sharpness */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-/* Other registers */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-/* Auto exposure and white balance */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-/*Dead pixels */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-/* EEPROM */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-/* JPEG control */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
-/* Other registers */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-/* Auto exposure and white balance */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-/*Dead pixels */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-/* EEPROM */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-/* JPEG control */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
-
-       {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
-       {0xa0, 0xf4, ZC3XX_R10B_RGB01},
-       {0xa0, 0xf4, ZC3XX_R10C_RGB02},
-       {0xa0, 0xf4, ZC3XX_R10D_RGB10},
-       {0xa0, 0x58, ZC3XX_R10E_RGB11},
-       {0xa0, 0xf4, ZC3XX_R10F_RGB12},
-       {0xa0, 0xf4, ZC3XX_R110_RGB20},
-       {0xa0, 0xf4, ZC3XX_R111_RGB21},
-       {0xa0, 0x58, ZC3XX_R112_RGB22},
-/* Auto correction */
-       {0xa0, 0x03, ZC3XX_R181_WINXSTART},
-       {0xa0, 0x08, ZC3XX_R182_WINXWIDTH},
-       {0xa0, 0x16, ZC3XX_R183_WINXCENTER},
-       {0xa0, 0x03, ZC3XX_R184_WINYSTART},
-       {0xa0, 0x05, ZC3XX_R185_WINYWIDTH},
-       {0xa0, 0x14, ZC3XX_R186_WINYCENTER},
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-/* Auto exposure and white balance */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
-/* sensor on */
-       {0xaa, 0x07, 0x00b1},
-       {0xaa, 0x05, 0x0003},
-       {0xaa, 0x04, 0x0001},
-       {0xaa, 0x03, 0x003b},
-/* Gains */
-       {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xa0, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-/* Auto correction */
-       {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa1, 0x01, 0x0180},                           /* AutoCorrectEnable */
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-/* Gains */
-       {0xa0, 0x40, ZC3XX_R116_RGAIN},
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},
-       {0xa0, 0x40, ZC3XX_R118_BGAIN},
-       {}
-};
-
-static const struct usb_action pas106b_Initial[] = {   /* 352x288 */
-/* JPEG control */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-/* Sream and Sensor specific */
-       {0xa0, 0x0f, ZC3XX_R010_CMOSSENSORSELECT},
-/* Picture size */
-       {0xa0, 0x01, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x60, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0x20, ZC3XX_R006_FRAMEHEIGHTLOW},
-/* System */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-/* Sream and Sensor specific */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-/* Sensor Interface */
-       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},
-/* Window inside sensor array */
-       {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0x28, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x68, ZC3XX_R09E_WINWIDTHLOW},
-/* Init the sensor */
-       {0xaa, 0x02, 0x0004},
-       {0xaa, 0x08, 0x0000},
-       {0xaa, 0x09, 0x0005},
-       {0xaa, 0x0a, 0x0002},
-       {0xaa, 0x0b, 0x0002},
-       {0xaa, 0x0c, 0x0005},
-       {0xaa, 0x0d, 0x0000},
-       {0xaa, 0x0e, 0x0002},
-       {0xaa, 0x14, 0x0081},
-/* Other registers */
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
-/* Frame retreiving */
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-/* Gains */
-       {0xa0, 0xa0, ZC3XX_R1A8_DIGITALGAIN},
-/* Unknown */
-       {0xa0, 0x00, 0x01ad},
-/* Sharpness */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-/* Other registers */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-/* Auto exposure and white balance */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x80, ZC3XX_R18D_YTARGET},
-/*Dead pixels */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-/* EEPROM */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-/* JPEG control */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
-/* Other registers */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-/* Auto exposure and white balance */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-/*Dead pixels */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-/* EEPROM */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-/* JPEG control */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x08, ZC3XX_R1C6_SHARPNESS00},
-       {0xa0, 0x0f, ZC3XX_R1CB_SHARPNESS05},
-
-       {0xa0, 0x58, ZC3XX_R10A_RGB00}, /* matrix */
-       {0xa0, 0xf4, ZC3XX_R10B_RGB01},
-       {0xa0, 0xf4, ZC3XX_R10C_RGB02},
-       {0xa0, 0xf4, ZC3XX_R10D_RGB10},
-       {0xa0, 0x58, ZC3XX_R10E_RGB11},
-       {0xa0, 0xf4, ZC3XX_R10F_RGB12},
-       {0xa0, 0xf4, ZC3XX_R110_RGB20},
-       {0xa0, 0xf4, ZC3XX_R111_RGB21},
-       {0xa0, 0x58, ZC3XX_R112_RGB22},
-/* Auto correction */
-       {0xa0, 0x03, ZC3XX_R181_WINXSTART},
-       {0xa0, 0x08, ZC3XX_R182_WINXWIDTH},
-       {0xa0, 0x16, ZC3XX_R183_WINXCENTER},
-       {0xa0, 0x03, ZC3XX_R184_WINYSTART},
-       {0xa0, 0x05, ZC3XX_R185_WINYWIDTH},
-       {0xa0, 0x14, ZC3XX_R186_WINYCENTER},
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-
-/* Auto exposure and white balance */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xb1, ZC3XX_R192_EXPOSURELIMITLOW},
-
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW},
-
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-/* sensor on */
-       {0xaa, 0x07, 0x00b1},
-       {0xaa, 0x05, 0x0003},
-       {0xaa, 0x04, 0x0001},
-       {0xaa, 0x03, 0x003b},
-/* Gains */
-       {0xa0, 0x20, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x26, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-/* Auto correction */
-       {0xa0, 0x40, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa1, 0x01, 0x0180},                           /* AutoCorrectEnable */
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-/* Gains */
-       {0xa0, 0x40, ZC3XX_R116_RGAIN},
-       {0xa0, 0x40, ZC3XX_R117_GGAIN},
-       {0xa0, 0x40, ZC3XX_R118_BGAIN},
-
-       {0xa0, 0x00, 0x0007},                   /* AutoCorrectEnable */
-       {0xa0, 0xff, ZC3XX_R018_FRAMELOST},     /* Frame adjust */
-       {}
-};
-static const struct usb_action pas106b_50HZ[] = {
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
-       {0xa0, 0x54, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,54,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x87, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,87,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},      /* 01,8c,10,cc */
-       {0xa0, 0x30, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,30,cc */
-       {0xaa, 0x03, 0x0021},                   /* 00,03,21,aa */
-       {0xaa, 0x04, 0x000c},                   /* 00,04,0c,aa */
-       {0xaa, 0x05, 0x0002},                   /* 00,05,02,aa */
-       {0xaa, 0x07, 0x001c},                   /* 00,07,1c,aa */
-       {0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
-       {}
-};
-static const struct usb_action pas106b_60HZ[] = {
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
-       {0xa0, 0x2e, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,2e,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x71, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,71,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},      /* 01,8c,10,cc */
-       {0xa0, 0x30, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,30,cc */
-       {0xaa, 0x03, 0x001c},                   /* 00,03,1c,aa */
-       {0xaa, 0x04, 0x0004},                   /* 00,04,04,aa */
-       {0xaa, 0x05, 0x0001},                   /* 00,05,01,aa */
-       {0xaa, 0x07, 0x00c4},                   /* 00,07,c4,aa */
-       {0xa0, 0x04, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,04,cc */
-       {}
-};
-static const struct usb_action pas106b_NoFliker[] = {
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,06,cc */
-       {0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},      /* 01,8c,10,cc */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},    /* 01,8f,20,cc */
-       {0xaa, 0x03, 0x0013},                   /* 00,03,13,aa */
-       {0xaa, 0x04, 0x0000},                   /* 00,04,00,aa */
-       {0xaa, 0x05, 0x0001},                   /* 00,05,01,aa */
-       {0xaa, 0x07, 0x0030},                   /* 00,07,30,aa */
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
-       {}
-};
-
-/* from lvWIMv.inf 046d:08a2/:08aa 2007/06/03 */
-static const struct usb_action pas202b_Initial[] = {   /* 640x480 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},         /* 00,00,01,cc */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0e,cc */
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},           /* 00,02,00,cc */
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc */
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},         /* 00,04,80,cc */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc */
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},        /* 00,06,e0,cc */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc */
-       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},       /* 00,8d,08,cc */
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},          /* 00,98,00,cc */
-       {0xa0, 0x03, ZC3XX_R09A_WINXSTARTLOW},          /* 00,9a,03,cc */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},             /* 01,1a,00,cc */
-       {0xa0, 0x03, ZC3XX_R11C_FIRSTXLOW},             /* 01,1c,03,cc */
-       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},         /* 00,9b,01,cc */
-       {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},          /* 00,9c,e6,cc */
-       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},          /* 00,9d,02,cc */
-       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},           /* 00,9e,86,cc */
-       {0xaa, 0x02, 0x0002},                   /* 00,02,04,aa --> 02 */
-       {0xaa, 0x07, 0x0006},                           /* 00,07,06,aa */
-       {0xaa, 0x08, 0x0002},                           /* 00,08,02,aa */
-       {0xaa, 0x09, 0x0006},                           /* 00,09,06,aa */
-       {0xaa, 0x0a, 0x0001},                           /* 00,0a,01,aa */
-       {0xaa, 0x0b, 0x0001},                           /* 00,0b,01,aa */
-       {0xaa, 0x0c, 0x0006},
-       {0xaa, 0x0d, 0x0000},                           /* 00,0d,00,aa */
-       {0xaa, 0x10, 0x0000},                           /* 00,10,00,aa */
-       {0xaa, 0x12, 0x0005},                           /* 00,12,05,aa */
-       {0xaa, 0x13, 0x0063},                           /* 00,13,63,aa */
-       {0xaa, 0x15, 0x0070},                           /* 00,15,70,aa */
-       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,b7,cc */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0d,cc */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},             /* 01,89,06,cc */
-       {0xa0, 0x00, 0x01ad},                           /* 01,ad,00,cc */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},         /* 01,c5,03,cc */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},           /* 01,cb,13,cc */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},          /* 03,01,08,cc */
-       {0xa0, 0x70, ZC3XX_R18D_YTARGET},               /* 01,8d,70,cc */
-       {}
-};
-static const struct usb_action pas202b_InitialScale[] = {      /* 320x240 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},         /* 00,00,01,cc */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x0e, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,0e,cc */
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},           /* 00,02,10,cc */
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc */
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},         /* 00,04,80,cc */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc */
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc */
-       {0xa0, 0x08, ZC3XX_R08D_COMPABILITYMODE},       /* 00,8d,08,cc */
-       {0xa0, 0x08, ZC3XX_R098_WINYSTARTLOW},          /* 00,98,08,cc */
-       {0xa0, 0x02, ZC3XX_R09A_WINXSTARTLOW},          /* 00,9a,02,cc */
-       {0xa0, 0x08, ZC3XX_R11A_FIRSTYLOW},             /* 01,1a,08,cc */
-       {0xa0, 0x02, ZC3XX_R11C_FIRSTXLOW},             /* 01,1c,02,cc */
-       {0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},         /* 00,9b,01,cc */
-       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},          /* 00,9d,02,cc */
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},           /* 00,9e,88,cc */
-       {0xaa, 0x02, 0x0002},                           /* 00,02,02,aa */
-       {0xaa, 0x07, 0x0006},                           /* 00,07,06,aa */
-       {0xaa, 0x08, 0x0002},                           /* 00,08,02,aa */
-       {0xaa, 0x09, 0x0006},                           /* 00,09,06,aa */
-       {0xaa, 0x0a, 0x0001},                           /* 00,0a,01,aa */
-       {0xaa, 0x0b, 0x0001},                           /* 00,0b,01,aa */
-       {0xaa, 0x0c, 0x0006},
-       {0xaa, 0x0d, 0x0000},                           /* 00,0d,00,aa */
-       {0xaa, 0x10, 0x0000},                           /* 00,10,00,aa */
-       {0xaa, 0x12, 0x0005},                           /* 00,12,05,aa */
-       {0xaa, 0x13, 0x0063},                           /* 00,13,63,aa */
-       {0xaa, 0x15, 0x0070},                           /* 00,15,70,aa */
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,37,cc */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0d,cc */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},             /* 01,89,06,cc */
-       {0xa0, 0x00, 0x01ad},                           /* 01,ad,00,cc */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},         /* 01,c5,03,cc */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},           /* 01,cb,13,cc */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},          /* 03,01,08,cc */
-       {0xa0, 0x70, ZC3XX_R18D_YTARGET},               /* 01,8d,70,cc */
-       {0xa0, 0xff, ZC3XX_R097_WINYSTARTHIGH},
-       {0xa0, 0xfe, ZC3XX_R098_WINYSTARTLOW},
-       {}
-};
-static const struct usb_action pas202b_50HZ[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},         /* 00,19,00,cc */
-       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},            /* 00,87,20,cc */
-       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},            /* 00,88,21,cc */
-       {0xaa, 0x20, 0x0002},                           /* 00,20,02,aa */
-       {0xaa, 0x21, 0x001b},
-       {0xaa, 0x03, 0x0044},                           /* 00,03,44,aa */
-       {0xaa, 0x04, 0x0008},
-       {0xaa, 0x05, 0x001b},
-       {0xaa, 0x0e, 0x0001},                           /* 00,0e,01,aa */
-       {0xaa, 0x0f, 0x0000},                           /* 00,0f,00,aa */
-       {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
-       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x1b, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
-       {0xa0, 0x4d, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,4d,cc */
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x44, ZC3XX_R01D_HSYNC_0},               /* 00,1d,44,cc */
-       {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1},               /* 00,1e,6f,cc */
-       {0xa0, 0xad, ZC3XX_R01F_HSYNC_2},               /* 00,1f,ad,cc */
-       {0xa0, 0xeb, ZC3XX_R020_HSYNC_3},               /* 00,20,eb,cc */
-       {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},            /* 00,87,0f,cc */
-       {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},            /* 00,88,0e,cc */
-       {}
-};
-static const struct usb_action pas202b_50HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},         /* 00,19,00,cc */
-       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},            /* 00,87,20,cc */
-       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},            /* 00,88,21,cc */
-       {0xaa, 0x20, 0x0004},
-       {0xaa, 0x21, 0x003d},
-       {0xaa, 0x03, 0x0041},                           /* 00,03,41,aa */
-       {0xaa, 0x04, 0x0010},
-       {0xaa, 0x05, 0x003d},
-       {0xaa, 0x0e, 0x0001},                           /* 00,0e,01,aa */
-       {0xaa, 0x0f, 0x0000},                           /* 00,0f,00,aa */
-       {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x3d, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
-       {0xa0, 0x9b, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,9b,cc */
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x41, ZC3XX_R01D_HSYNC_0},               /* 00,1d,41,cc */
-       {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1},               /* 00,1e,6f,cc */
-       {0xa0, 0xad, ZC3XX_R01F_HSYNC_2},               /* 00,1f,ad,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc */
-       {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},            /* 00,87,0f,cc */
-       {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},            /* 00,88,0e,cc */
-       {}
-};
-static const struct usb_action pas202b_60HZ[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},         /* 00,19,00,cc */
-       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},            /* 00,87,20,cc */
-       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},            /* 00,88,21,cc */
-       {0xaa, 0x20, 0x0002},                           /* 00,20,02,aa */
-       {0xaa, 0x21, 0x0000},                           /* 00,21,00,aa */
-       {0xaa, 0x03, 0x0045},                           /* 00,03,45,aa */
-       {0xaa, 0x04, 0x0008},                           /* 00,04,08,aa */
-       {0xaa, 0x05, 0x0000},                           /* 00,05,00,aa */
-       {0xaa, 0x0e, 0x0001},                           /* 00,0e,01,aa */
-       {0xaa, 0x0f, 0x0000},                           /* 00,0f,00,aa */
-       {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
-       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
-       {0xa0, 0x40, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,40,cc */
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x45, ZC3XX_R01D_HSYNC_0},               /* 00,1d,45,cc */
-       {0xa0, 0x8e, ZC3XX_R01E_HSYNC_1},               /* 00,1e,8e,cc */
-       {0xa0, 0xc1, ZC3XX_R01F_HSYNC_2},               /* 00,1f,c1,cc */
-       {0xa0, 0xf5, ZC3XX_R020_HSYNC_3},               /* 00,20,f5,cc */
-       {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},            /* 00,87,0f,cc */
-       {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},            /* 00,88,0e,cc */
-       {}
-};
-static const struct usb_action pas202b_60HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},         /* 00,19,00,cc */
-       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},            /* 00,87,20,cc */
-       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},            /* 00,88,21,cc */
-       {0xaa, 0x20, 0x0004},
-       {0xaa, 0x21, 0x0008},
-       {0xaa, 0x03, 0x0042},                           /* 00,03,42,aa */
-       {0xaa, 0x04, 0x0010},
-       {0xaa, 0x05, 0x0008},
-       {0xaa, 0x0e, 0x0001},                           /* 00,0e,01,aa */
-       {0xaa, 0x0f, 0x0000},                           /* 00,0f,00,aa */
-       {0xa0, 0x1c, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x08, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
-       {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,81,cc */
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1b, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x42, ZC3XX_R01D_HSYNC_0},               /* 00,1d,42,cc */
-       {0xa0, 0x6f, ZC3XX_R01E_HSYNC_1},               /* 00,1e,6f,cc */
-       {0xa0, 0xaf, ZC3XX_R01F_HSYNC_2},               /* 00,1f,af,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc */
-       {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},            /* 00,87,0f,cc */
-       {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},            /* 00,88,0e,cc */
-       {}
-};
-static const struct usb_action pas202b_NoFliker[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},         /* 00,19,00,cc */
-       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},            /* 00,87,20,cc */
-       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},            /* 00,88,21,cc */
-       {0xaa, 0x20, 0x0002},                           /* 00,20,02,aa */
-       {0xaa, 0x21, 0x0006},
-       {0xaa, 0x03, 0x0040},                           /* 00,03,40,aa */
-       {0xaa, 0x04, 0x0008},                           /* 00,04,08,aa */
-       {0xaa, 0x05, 0x0006},
-       {0xaa, 0x0e, 0x0001},                           /* 00,0e,01,aa */
-       {0xaa, 0x0f, 0x0000},                           /* 00,0f,00,aa */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
-       {0xa0, 0x02, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x06, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
-       {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},              /* 01,8c,10,cc */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,20,cc */
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,00,cc */
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x40, ZC3XX_R01D_HSYNC_0},               /* 00,1d,40,cc */
-       {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},               /* 00,1e,60,cc */
-       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},               /* 00,1f,90,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc */
-       {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},            /* 00,87,0f,cc */
-       {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},            /* 00,88,0e,cc */
-       {}
-};
-static const struct usb_action pas202b_NoFlikerScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},         /* 00,19,00,cc */
-       {0xa0, 0x20, ZC3XX_R087_EXPTIMEMID},            /* 00,87,20,cc */
-       {0xa0, 0x21, ZC3XX_R088_EXPTIMELOW},            /* 00,88,21,cc */
-       {0xaa, 0x20, 0x0004},
-       {0xaa, 0x21, 0x000c},
-       {0xaa, 0x03, 0x0040},                           /* 00,03,40,aa */
-       {0xaa, 0x04, 0x0010},
-       {0xaa, 0x05, 0x000c},
-       {0xaa, 0x0e, 0x0001},                           /* 00,0e,01,aa */
-       {0xaa, 0x0f, 0x0000},                           /* 00,0f,00,aa */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc */
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x0c, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc */
-       {0xa0, 0x02, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,02,cc */
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},              /* 01,8c,10,cc */
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,20,cc */
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,00,cc */
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x40, ZC3XX_R01D_HSYNC_0},               /* 00,1d,40,cc */
-       {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},               /* 00,1e,60,cc */
-       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},               /* 00,1f,90,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc */
-       {0xa0, 0x0f, ZC3XX_R087_EXPTIMEMID},            /* 00,87,0f,cc */
-       {0xa0, 0x0e, ZC3XX_R088_EXPTIMELOW},            /* 00,88,0e,cc */
-       {}
-};
-
-/* mt9v111 (mi0360soc) and pb0330 from vm30x.inf 0ac8:301b 07/02/13 */
-static const struct usb_action mt9v111_1_Initial[] = { /* 640x480 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xdd, 0x00, 0x0200},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xaa, 0x01, 0x0001},
-       {0xaa, 0x06, 0x0000},
-       {0xaa, 0x08, 0x0483},
-       {0xaa, 0x01, 0x0004},
-       {0xaa, 0x08, 0x0006},
-       {0xaa, 0x02, 0x0011},
-       {0xaa, 0x03, 0x01e5},                   /*jfm: was 01e7*/
-       {0xaa, 0x04, 0x0285},                   /*jfm: was 0287*/
-       {0xaa, 0x07, 0x3002},
-       {0xaa, 0x20, 0x5100},
-       {0xaa, 0x35, 0x507f},
-       {0xaa, 0x30, 0x0005},
-       {0xaa, 0x31, 0x0000},
-       {0xaa, 0x58, 0x0078},
-       {0xaa, 0x62, 0x0411},
-       {0xaa, 0x2b, 0x007f},
-       {0xaa, 0x2c, 0x007f},                   /*jfm: was 0030*/
-       {0xaa, 0x2d, 0x007f},                   /*jfm: was 0030*/
-       {0xaa, 0x2e, 0x007f},                   /*jfm: was 0030*/
-       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
-       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x09, 0x01ad},                   /*jfm: was 00*/
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x61, ZC3XX_R116_RGAIN},
-       {0xa0, 0x65, ZC3XX_R118_BGAIN},
-       {}
-};
-static const struct usb_action mt9v111_1_InitialScale[] = {    /* 320x240 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xdd, 0x00, 0x0200},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xaa, 0x01, 0x0001},
-       {0xaa, 0x06, 0x0000},
-       {0xaa, 0x08, 0x0483},
-       {0xaa, 0x01, 0x0004},
-       {0xaa, 0x08, 0x0006},
-       {0xaa, 0x02, 0x0011},
-       {0xaa, 0x03, 0x01e7},
-       {0xaa, 0x04, 0x0287},
-       {0xaa, 0x07, 0x3002},
-       {0xaa, 0x20, 0x5100},
-       {0xaa, 0x35, 0x007f},                   /*jfm: was 0050*/
-       {0xaa, 0x30, 0x0005},
-       {0xaa, 0x31, 0x0000},
-       {0xaa, 0x58, 0x0078},
-       {0xaa, 0x62, 0x0411},
-       {0xaa, 0x2b, 0x007f},                   /*jfm: was 28*/
-       {0xaa, 0x2c, 0x007f},                   /*jfm: was 30*/
-       {0xaa, 0x2d, 0x007f},                   /*jfm: was 30*/
-       {0xaa, 0x2e, 0x007f},                   /*jfm: was 28*/
-       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
-       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x09, 0x01ad},                   /*jfm: was 00*/
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0x6c, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x61, ZC3XX_R116_RGAIN},
-       {0xa0, 0x65, ZC3XX_R118_BGAIN},
-       {}
-};
-static const struct usb_action mt9v111_1_AE50HZ[] = {
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xbb, 0x00, 0x0562},
-       {0xbb, 0x01, 0x09aa},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x03, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x9b, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {}
-};
-static const struct usb_action mt9v111_1_AE50HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xbb, 0x00, 0x0509},
-       {0xbb, 0x01, 0x0934},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {}
-};
-static const struct usb_action mt9v111_1_AE60HZ[] = {
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x05, 0x003d},
-       {0xaa, 0x09, 0x016e},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xdd, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x3d, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {}
-};
-static const struct usb_action mt9v111_1_AE60HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xbb, 0x00, 0x0509},
-       {0xbb, 0x01, 0x0983},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {}
-};
-static const struct usb_action mt9v111_1_AENoFliker[] = {
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xbb, 0x00, 0x0509},
-       {0xbb, 0x01, 0x0960},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x09, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {}
-};
-static const struct usb_action mt9v111_1_AENoFlikerScale[] = {
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xbb, 0x00, 0x0534},
-       {0xbb, 0x02, 0x0960},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x34, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {}
-};
-/* from usbvm303.inf 0ac8:303b 07/03/25 (3 - tas5130c) */
-static const struct usb_action mt9v111_3_Initial[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xdd, 0x00, 0x0200},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xaa, 0x01, 0x0001},           /* select IFP/SOC registers */
-       {0xaa, 0x06, 0x0000},           /* operating mode control */
-       {0xaa, 0x08, 0x0483},           /* output format control */
-                                       /* H red first, V red or blue first,
-                                        * raw Bayer, auto flicker */
-       {0xaa, 0x01, 0x0004},           /* select sensor core registers */
-       {0xaa, 0x08, 0x0006},           /* row start */
-       {0xaa, 0x02, 0x0011},           /* column start */
-       {0xaa, 0x03, 0x01e5},           /* window height - 1 */
-       {0xaa, 0x04, 0x0285},           /* window width - 1 */
-       {0xaa, 0x07, 0x3002},           /* output control */
-       {0xaa, 0x20, 0x1100},           /* read mode: bits 8 & 12 (?) */
-       {0xaa, 0x35, 0x007f},           /* global gain */
-       {0xaa, 0x30, 0x0005},
-       {0xaa, 0x31, 0x0000},
-       {0xaa, 0x58, 0x0078},
-       {0xaa, 0x62, 0x0411},
-       {0xaa, 0x2b, 0x007f},           /* green1 gain */
-       {0xaa, 0x2c, 0x007f},           /* blue gain */
-       {0xaa, 0x2d, 0x007f},           /* red gain */
-       {0xaa, 0x2e, 0x007f},           /* green2 gain */
-       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x00, 0x01ad},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0x80, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x61, ZC3XX_R116_RGAIN},
-       {0xa0, 0x65, ZC3XX_R118_BGAIN},
-       {}
-};
-static const struct usb_action mt9v111_3_InitialScale[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0xdc, ZC3XX_R08B_I2CDEVICEADDR},
-       {0xdd, 0x00, 0x0200},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xaa, 0x01, 0x0001},
-       {0xaa, 0x06, 0x0000},
-       {0xaa, 0x08, 0x0483},
-       {0xaa, 0x01, 0x0004},
-       {0xaa, 0x08, 0x0006},
-       {0xaa, 0x02, 0x0011},
-       {0xaa, 0x03, 0x01e7},
-       {0xaa, 0x04, 0x0287},
-       {0xaa, 0x07, 0x3002},
-       {0xaa, 0x20, 0x1100},
-       {0xaa, 0x35, 0x007f},
-       {0xaa, 0x30, 0x0005},
-       {0xaa, 0x31, 0x0000},
-       {0xaa, 0x58, 0x0078},
-       {0xaa, 0x62, 0x0411},
-       {0xaa, 0x2b, 0x007f},
-       {0xaa, 0x2c, 0x007f},
-       {0xaa, 0x2d, 0x007f},
-       {0xaa, 0x2e, 0x007f},
-       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x00, 0x01ad},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0x80, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x61, ZC3XX_R116_RGAIN},
-       {0xa0, 0x65, ZC3XX_R118_BGAIN},
-       {}
-};
-static const struct usb_action mt9v111_3_AE50HZ[] = {
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x05, 0x0009},           /* horizontal blanking */
-       {0xaa, 0x09, 0x01ce},           /* shutter width */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {}
-};
-static const struct usb_action mt9v111_3_AE50HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x05, 0x0009},
-       {0xaa, 0x09, 0x01ce},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xd2, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x9a, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {}
-};
-static const struct usb_action mt9v111_3_AE60HZ[] = {
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x05, 0x0009},
-       {0xaa, 0x09, 0x0083},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {}
-};
-static const struct usb_action mt9v111_3_AE60HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x05, 0x0009},
-       {0xaa, 0x09, 0x0083},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x8f, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x81, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xf9, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {}
-};
-static const struct usb_action mt9v111_3_AENoFliker[] = {
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x05, 0x0034},
-       {0xaa, 0x09, 0x0260},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x34, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {}
-};
-static const struct usb_action mt9v111_3_AENoFlikerScale[] = {
-       {0xa0, 0x00, ZC3XX_R180_AUTOCORRECTENABLE},
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xaa, 0x05, 0x0034},
-       {0xaa, 0x09, 0x0260},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1c, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x34, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},
-       {}
-};
-
-static const struct usb_action pb0330_Initial[] = {    /* 640x480 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00 */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xdd, 0x00, 0x0200},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xaa, 0x01, 0x0006},
-       {0xaa, 0x02, 0x0011},
-       {0xaa, 0x03, 0x01e5},                   /*jfm: was 1e7*/
-       {0xaa, 0x04, 0x0285},                   /*jfm: was 0287*/
-       {0xaa, 0x06, 0x0003},
-       {0xaa, 0x07, 0x3002},
-       {0xaa, 0x20, 0x1100},
-       {0xaa, 0x2f, 0xf7b0},
-       {0xaa, 0x30, 0x0005},
-       {0xaa, 0x31, 0x0000},
-       {0xaa, 0x34, 0x0100},
-       {0xaa, 0x35, 0x0060},
-       {0xaa, 0x3d, 0x068f},
-       {0xaa, 0x40, 0x01e0},
-       {0xaa, 0x58, 0x0078},
-       {0xaa, 0x62, 0x0411},
-       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x09, 0x01ad},                   /*jfm: was 00 */
-       {0xa0, 0x15, 0x01ae},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0x78, ZC3XX_R18D_YTARGET},       /*jfm: was 6c*/
-       {}
-};
-static const struct usb_action pb0330_InitialScale[] = {       /* 320x240 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},  /* 00 */
-       {0xa0, 0x0a, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x07, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},
-       {0xdd, 0x00, 0x0200},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xaa, 0x01, 0x0006},
-       {0xaa, 0x02, 0x0011},
-       {0xaa, 0x03, 0x01e7},
-       {0xaa, 0x04, 0x0287},
-       {0xaa, 0x06, 0x0003},
-       {0xaa, 0x07, 0x3002},
-       {0xaa, 0x20, 0x1100},
-       {0xaa, 0x2f, 0xf7b0},
-       {0xaa, 0x30, 0x0005},
-       {0xaa, 0x31, 0x0000},
-       {0xaa, 0x34, 0x0100},
-       {0xaa, 0x35, 0x0060},
-       {0xaa, 0x3d, 0x068f},
-       {0xaa, 0x40, 0x01e0},
-       {0xaa, 0x58, 0x0078},
-       {0xaa, 0x62, 0x0411},
-       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x09, 0x01ad},
-       {0xa0, 0x15, 0x01ae},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0x78, ZC3XX_R18D_YTARGET},       /*jfm: was 6c*/
-       {}
-};
-static const struct usb_action pb0330_50HZ[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xbb, 0x00, 0x055c},
-       {0xbb, 0x01, 0x09aa},
-       {0xbb, 0x00, 0x1001},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xc4, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x5c, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action pb0330_50HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xbb, 0x00, 0x0566},
-       {0xbb, 0x02, 0x09b2},
-       {0xbb, 0x00, 0x1002},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x8c, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x8a, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xd7, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0xf0, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action pb0330_60HZ[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xbb, 0x00, 0x0535},
-       {0xbb, 0x01, 0x0974},
-       {0xbb, 0x00, 0x1001},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xfe, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x35, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x50, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xd0, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action pb0330_60HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xbb, 0x00, 0x0535},
-       {0xbb, 0x02, 0x096c},
-       {0xbb, 0x00, 0x1002},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xc0, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x7c, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x1a, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x14, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x66, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x35, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x50, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xd0, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action pb0330_NoFliker[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xbb, 0x00, 0x0509},
-       {0xbb, 0x02, 0x0940},
-       {0xbb, 0x00, 0x1002},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x09, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x40, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
-       {}
-};
-static const struct usb_action pb0330_NoFlikerScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS},
-       {0xbb, 0x00, 0x0535},
-       {0xbb, 0x01, 0x0980},
-       {0xbb, 0x00, 0x1001},
-       {0xa0, 0x60, ZC3XX_R11D_GLOBALGAIN},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xf0, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x01, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x10, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x20, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x35, ZC3XX_R01D_HSYNC_0},
-       {0xa0, 0x60, ZC3XX_R01E_HSYNC_1},
-       {0xa0, 0x90, ZC3XX_R01F_HSYNC_2},
-       {0xa0, 0xe0, ZC3XX_R020_HSYNC_3},
-       {}
-};
-
-/* from oem9.inf */
-static const struct usb_action po2030_Initial[] = {    /* 640x480 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
-       {0xa0, 0x04, ZC3XX_R002_CLOCKSELECT},   /* 00,02,04,cc */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
-       {0xa0, 0x04, ZC3XX_R080_HBLANKHIGH}, /* 00,80,04,cc */
-       {0xa0, 0x05, ZC3XX_R081_HBLANKLOW}, /* 00,81,05,cc */
-       {0xa0, 0x16, ZC3XX_R083_RGAINADDR}, /* 00,83,16,cc */
-       {0xa0, 0x18, ZC3XX_R085_BGAINADDR}, /* 00,85,18,cc */
-       {0xa0, 0x1a, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,1a,cc */
-       {0xa0, 0x1b, ZC3XX_R087_EXPTIMEMID}, /* 00,87,1b,cc */
-       {0xa0, 0x1c, ZC3XX_R088_EXPTIMELOW}, /* 00,88,1c,cc */
-       {0xa0, 0xee, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,ee,cc */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
-       {0xaa, 0x8d, 0x0008},                   /* 00,8d,08,aa */
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},  /* 00,98,00,cc */
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},  /* 00,9a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},     /* 01,1a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},     /* 01,1c,00,cc */
-       {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},  /* 00,9c,e6,cc */
-       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},   /* 00,9e,86,cc */
-       {0xaa, 0x09, 0x00ce}, /* 00,09,ce,aa */
-       {0xaa, 0x0b, 0x0005}, /* 00,0b,05,aa */
-       {0xaa, 0x0d, 0x0054}, /* 00,0d,54,aa */
-       {0xaa, 0x0f, 0x00eb}, /* 00,0f,eb,aa */
-       {0xaa, 0x87, 0x0000}, /* 00,87,00,aa */
-       {0xaa, 0x88, 0x0004}, /* 00,88,04,aa */
-       {0xaa, 0x89, 0x0000}, /* 00,89,00,aa */
-       {0xaa, 0x8a, 0x0005}, /* 00,8a,05,aa */
-       {0xaa, 0x13, 0x0003}, /* 00,13,03,aa */
-       {0xaa, 0x16, 0x0040}, /* 00,16,40,aa */
-       {0xaa, 0x18, 0x0040}, /* 00,18,40,aa */
-       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
-       {0xaa, 0x29, 0x00e8}, /* 00,29,e8,aa */
-       {0xaa, 0x45, 0x0045}, /* 00,45,45,aa */
-       {0xaa, 0x50, 0x00ed}, /* 00,50,ed,aa */
-       {0xaa, 0x51, 0x0025}, /* 00,51,25,aa */
-       {0xaa, 0x52, 0x0042}, /* 00,52,42,aa */
-       {0xaa, 0x53, 0x002f}, /* 00,53,2f,aa */
-       {0xaa, 0x79, 0x0025}, /* 00,79,25,aa */
-       {0xaa, 0x7b, 0x0000}, /* 00,7b,00,aa */
-       {0xaa, 0x7e, 0x0025}, /* 00,7e,25,aa */
-       {0xaa, 0x7f, 0x0025}, /* 00,7f,25,aa */
-       {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
-       {0xaa, 0x33, 0x0036}, /* 00,33,36,aa */
-       {0xaa, 0x36, 0x0060}, /* 00,36,60,aa */
-       {0xaa, 0x37, 0x0008}, /* 00,37,08,aa */
-       {0xaa, 0x3b, 0x0031}, /* 00,3b,31,aa */
-       {0xaa, 0x44, 0x000f}, /* 00,44,0f,aa */
-       {0xaa, 0x58, 0x0002}, /* 00,58,02,aa */
-       {0xaa, 0x66, 0x00c0}, /* 00,66,c0,aa */
-       {0xaa, 0x67, 0x0044}, /* 00,67,44,aa */
-       {0xaa, 0x6b, 0x00a0}, /* 00,6b,a0,aa */
-       {0xaa, 0x6c, 0x0054}, /* 00,6c,54,aa */
-       {0xaa, 0xd6, 0x0007}, /* 00,d6,07,aa */
-       {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,f7,cc */
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
-       {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
-       {0xa0, 0x7a, ZC3XX_R116_RGAIN}, /* 01,16,7a,cc */
-       {0xa0, 0x4a, ZC3XX_R118_BGAIN}, /* 01,18,4a,cc */
-       {}
-};
-
-/* from oem9.inf */
-static const struct usb_action po2030_InitialScale[] = {       /* 320x240 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc */
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING}, /* 00,01,01,cc */
-       {0xa0, 0x04, ZC3XX_R080_HBLANKHIGH}, /* 00,80,04,cc */
-       {0xa0, 0x05, ZC3XX_R081_HBLANKLOW}, /* 00,81,05,cc */
-       {0xa0, 0x16, ZC3XX_R083_RGAINADDR}, /* 00,83,16,cc */
-       {0xa0, 0x18, ZC3XX_R085_BGAINADDR}, /* 00,85,18,cc */
-       {0xa0, 0x1a, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,1a,cc */
-       {0xa0, 0x1b, ZC3XX_R087_EXPTIMEMID}, /* 00,87,1b,cc */
-       {0xa0, 0x1c, ZC3XX_R088_EXPTIMELOW}, /* 00,88,1c,cc */
-       {0xa0, 0xee, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,ee,cc */
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING}, /* 00,08,03,cc */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,03,cc */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,01,cc */
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc */
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc */
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW}, /* 00,06,e0,cc */
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
-       {0xaa, 0x8d, 0x0008},                   /* 00,8d,08,aa */
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW}, /* 00,98,00,cc */
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW}, /* 00,9a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW}, /* 01,1a,00,cc */
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW}, /* 01,1c,00,cc */
-       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW}, /* 00,9c,e8,cc */
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW}, /* 00,9e,88,cc */
-       {0xaa, 0x09, 0x00cc}, /* 00,09,cc,aa */
-       {0xaa, 0x0b, 0x0005}, /* 00,0b,05,aa */
-       {0xaa, 0x0d, 0x0058}, /* 00,0d,58,aa */
-       {0xaa, 0x0f, 0x00ed}, /* 00,0f,ed,aa */
-       {0xaa, 0x87, 0x0000}, /* 00,87,00,aa */
-       {0xaa, 0x88, 0x0004}, /* 00,88,04,aa */
-       {0xaa, 0x89, 0x0000}, /* 00,89,00,aa */
-       {0xaa, 0x8a, 0x0005}, /* 00,8a,05,aa */
-       {0xaa, 0x13, 0x0003}, /* 00,13,03,aa */
-       {0xaa, 0x16, 0x0040}, /* 00,16,40,aa */
-       {0xaa, 0x18, 0x0040}, /* 00,18,40,aa */
-       {0xaa, 0x1d, 0x0002}, /* 00,1d,02,aa */
-       {0xaa, 0x29, 0x00e8}, /* 00,29,e8,aa */
-       {0xaa, 0x45, 0x0045}, /* 00,45,45,aa */
-       {0xaa, 0x50, 0x00ed}, /* 00,50,ed,aa */
-       {0xaa, 0x51, 0x0025}, /* 00,51,25,aa */
-       {0xaa, 0x52, 0x0042}, /* 00,52,42,aa */
-       {0xaa, 0x53, 0x002f}, /* 00,53,2f,aa */
-       {0xaa, 0x79, 0x0025}, /* 00,79,25,aa */
-       {0xaa, 0x7b, 0x0000}, /* 00,7b,00,aa */
-       {0xaa, 0x7e, 0x0025}, /* 00,7e,25,aa */
-       {0xaa, 0x7f, 0x0025}, /* 00,7f,25,aa */
-       {0xaa, 0x21, 0x0000}, /* 00,21,00,aa */
-       {0xaa, 0x33, 0x0036}, /* 00,33,36,aa */
-       {0xaa, 0x36, 0x0060}, /* 00,36,60,aa */
-       {0xaa, 0x37, 0x0008}, /* 00,37,08,aa */
-       {0xaa, 0x3b, 0x0031}, /* 00,3b,31,aa */
-       {0xaa, 0x44, 0x000f}, /* 00,44,0f,aa */
-       {0xaa, 0x58, 0x0002}, /* 00,58,02,aa */
-       {0xaa, 0x66, 0x00c0}, /* 00,66,c0,aa */
-       {0xaa, 0x67, 0x0044}, /* 00,67,44,aa */
-       {0xaa, 0x6b, 0x00a0}, /* 00,6b,a0,aa */
-       {0xaa, 0x6c, 0x0054}, /* 00,6c,54,aa */
-       {0xaa, 0xd6, 0x0007}, /* 00,d6,07,aa */
-       {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,f7,cc */
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc */
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS}, /* 01,89,06,cc */
-       {0xa0, 0x00, 0x01ad}, /* 01,ad,00,cc */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE}, /* 01,c5,03,cc */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc */
-       {0xa0, 0x7a, ZC3XX_R116_RGAIN}, /* 01,16,7a,cc */
-       {0xa0, 0x4a, ZC3XX_R118_BGAIN}, /* 01,18,4a,cc */
-       {}
-};
-
-static const struct usb_action po2030_50HZ[] = {
-       {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
-       {0xaa, 0x1a, 0x0001}, /* 00,1a,01,aa */
-       {0xaa, 0x1b, 0x000a}, /* 00,1b,0a,aa */
-       {0xaa, 0x1c, 0x00b0}, /* 00,1c,b0,aa */
-       {0xa0, 0x05, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,05,cc */
-       {0xa0, 0x35, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,35,cc */
-       {0xa0, 0x70, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,70,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x85, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,85,cc */
-       {0xa0, 0x58, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,58,cc */
-       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
-       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
-       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
-       {0xa0, 0x22, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,22,cc */
-       {0xa0, 0x88, ZC3XX_R18D_YTARGET}, /* 01,8d,88,cc */
-       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc */
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc */
-       {}
-};
-
-static const struct usb_action po2030_60HZ[] = {
-       {0xaa, 0x8d, 0x0008}, /* 00,8d,08,aa */
-       {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
-       {0xaa, 0x1b, 0x00de}, /* 00,1b,de,aa */
-       {0xaa, 0x1c, 0x0040}, /* 00,1c,40,aa */
-       {0xa0, 0x08, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,08,cc */
-       {0xa0, 0xae, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,ae,cc */
-       {0xa0, 0x80, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,80,cc */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x6f, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,6f,cc */
-       {0xa0, 0x20, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,20,cc */
-       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0c,cc */
-       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,18,cc */
-       {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc */
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc */
-       {0xa0, 0x22, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,22,cc */
-       {0xa0, 0x88, ZC3XX_R18D_YTARGET},               /* 01,8d,88,cc */
-                                                       /* win: 01,8d,80 */
-       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc */
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc */
-       {}
-};
-
-static const struct usb_action po2030_NoFliker[] = {
-       {0xa0, 0x02, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,02,cc */
-       {0xaa, 0x8d, 0x000d}, /* 00,8d,0d,aa */
-       {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa */
-       {0xaa, 0x1b, 0x0002}, /* 00,1b,02,aa */
-       {0xaa, 0x1c, 0x0078}, /* 00,1c,78,aa */
-       {0xaa, 0x46, 0x0000}, /* 00,46,00,aa */
-       {0xaa, 0x15, 0x0000}, /* 00,15,00,aa */
-       {}
-};
-
-static const struct usb_action tas5130c_InitialScale[] = {     /* 320x240 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x50, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-
-       {0xa0, 0x04, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x0f, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x04, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x0f, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},
-       {0xa0, 0x06, ZC3XX_R08D_COMPABILITYMODE},
-       {0xa0, 0xf7, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x70, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0x00, 0x01ad},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
-       {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
-       {}
-};
-static const struct usb_action tas5130c_Initial[] = {  /* 640x480 */
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
-       {0xa0, 0x40, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x00, ZC3XX_R008_CLOCKSETTING},
-       {0xa0, 0x02, ZC3XX_R010_CMOSSENSORSELECT},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x00, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-       {0xa0, 0x05, ZC3XX_R098_WINYSTARTLOW},
-       {0xa0, 0x0f, ZC3XX_R09A_WINXSTARTLOW},
-       {0xa0, 0x05, ZC3XX_R11A_FIRSTYLOW},
-       {0xa0, 0x0f, ZC3XX_R11C_FIRSTXLOW},
-       {0xa0, 0xe6, ZC3XX_R09C_WINHEIGHTLOW},
-       {0xa0, 0x02, ZC3XX_R09D_WINWIDTHHIGH},
-       {0xa0, 0x86, ZC3XX_R09E_WINWIDTHLOW},
-       {0xa0, 0x06, ZC3XX_R08D_COMPABILITYMODE},
-       {0xa0, 0x37, ZC3XX_R101_SENSORCORRECTION},
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},
-       {0xa0, 0x06, ZC3XX_R189_AWBSTATUS},
-       {0xa0, 0x70, ZC3XX_R18D_YTARGET},
-       {0xa0, 0x50, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0x00, 0x01ad},
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},
-       {0xa0, 0x07, ZC3XX_R0A5_EXPOSUREGAIN},
-       {0xa0, 0x02, ZC3XX_R0A6_EXPOSUREBLACKLVL},
-       {}
-};
-static const struct usb_action tas5130c_50HZ[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
-       {0xaa, 0xa4, 0x0063}, /* 00,a4,63,aa */
-       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
-       {0xa0, 0x63, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,63,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x04, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xfe, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc */
-       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xd3, ZC3XX_R01D_HSYNC_0}, /* 00,1d,d3,cc */
-       {0xa0, 0xda, ZC3XX_R01E_HSYNC_1}, /* 00,1e,da,cc */
-       {0xa0, 0xea, ZC3XX_R01F_HSYNC_2}, /* 00,1f,ea,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
-       {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
-       {0xa0, 0x4c, ZC3XX_R0A0_MAXXLOW},
-       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
-       {}
-};
-static const struct usb_action tas5130c_50HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
-       {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */
-       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
-       {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x07, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xd0, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */
-       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xf0, ZC3XX_R01D_HSYNC_0}, /* 00,1d,f0,cc */
-       {0xa0, 0xf4, ZC3XX_R01E_HSYNC_1}, /* 00,1e,f4,cc */
-       {0xa0, 0xf8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,f8,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
-       {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
-       {0xa0, 0xc0, ZC3XX_R0A0_MAXXLOW},
-       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
-       {}
-};
-static const struct usb_action tas5130c_60HZ[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
-       {0xaa, 0xa4, 0x0036}, /* 00,a4,36,aa */
-       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
-       {0xa0, 0x36, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,36,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x54, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x3e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,3e,cc */
-       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xca, ZC3XX_R01D_HSYNC_0}, /* 00,1d,ca,cc */
-       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
-       {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
-       {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
-       {0xa0, 0x28, ZC3XX_R0A0_MAXXLOW},
-       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
-       {}
-};
-static const struct usb_action tas5130c_60HZScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
-       {0xaa, 0xa4, 0x0077}, /* 00,a4,77,aa */
-       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
-       {0xa0, 0x77, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,77,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x09, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x47, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc */
-       {0xa0, 0x7d, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,7d,cc */
-       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x08, ZC3XX_R1A9_DIGITALLIMITDIFF},
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0xc8, ZC3XX_R01D_HSYNC_0}, /* 00,1d,c8,cc */
-       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
-       {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
-       {0xa0, 0x03, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,03,cc */
-       {0xa0, 0x20, ZC3XX_R0A0_MAXXLOW},
-       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
-       {}
-};
-static const struct usb_action tas5130c_NoFliker[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
-       {0xaa, 0xa4, 0x0040}, /* 00,a4,40,aa */
-       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
-       {0xa0, 0x40, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,40,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0xa0, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
-       {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */
-       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
-       {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
-       {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */
-       {0xa0, 0xf0, ZC3XX_R0A0_MAXXLOW},
-       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
-       {}
-};
-
-static const struct usb_action tas5130c_NoFlikerScale[] = {
-       {0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
-       {0xaa, 0xa3, 0x0001}, /* 00,a3,01,aa */
-       {0xaa, 0xa4, 0x0090}, /* 00,a4,90,aa */
-       {0xa0, 0x01, ZC3XX_R0A3_EXPOSURETIMEHIGH}, /* 00,a3,01,cc */
-       {0xa0, 0x90, ZC3XX_R0A4_EXPOSURETIMELOW}, /* 00,a4,90,cc */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc */
-       {0xa0, 0x0a, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x00, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},
-       {0xa0, 0x04, ZC3XX_R197_ANTIFLICKERLOW},
-       {0xa0, 0x0c, ZC3XX_R18C_AEFREEZE},
-       {0xa0, 0x18, ZC3XX_R18F_AEUNFREEZE},
-       {0xa0, 0x00, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,00,cc */
-       {0xa0, 0x00, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,00,cc */
-       {0xa0, 0xbc, ZC3XX_R01D_HSYNC_0}, /* 00,1d,bc,cc */
-       {0xa0, 0xd0, ZC3XX_R01E_HSYNC_1}, /* 00,1e,d0,cc */
-       {0xa0, 0xe0, ZC3XX_R01F_HSYNC_2}, /* 00,1f,e0,cc */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc */
-       {0xa0, 0x02, ZC3XX_R09F_MAXXHIGH}, /* 00,9f,02,cc */
-       {0xa0, 0xf0, ZC3XX_R0A0_MAXXLOW},
-       {0xa0, 0x50, ZC3XX_R11D_GLOBALGAIN},
-       {}
-};
-
-/* from usbvm305.inf 0ac8:305b 07/06/15 (3 - tas5130c) */
-static const struct usb_action gc0303_Initial[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},         /* 00,00,01,cc, */
-       {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},          /* 00,08,02,cc, */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc, */
-       {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc, */
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},         /* 00,04,80,cc, */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc, */
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},        /* 00,06,e0,cc, */
-       {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,98,cc, */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc, */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc, */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc, */
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},          /* 00,98,00,cc, */
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},          /* 00,9a,00,cc, */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},             /* 01,1a,00,cc, */
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},             /* 01,1c,00,cc, */
-       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},          /* 00,9c,e6,cc,
-                                                        * 6<->8 */
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},           /* 00,9e,86,cc,
-                                                        * 6<->8 */
-       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},            /* 00,87,10,cc, */
-       {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,98,cc, */
-       {0xaa, 0x01, 0x0000},
-       {0xaa, 0x1a, 0x0000},           /* 00,1a,00,aa, */
-       {0xaa, 0x1c, 0x0017},           /* 00,1c,17,aa, */
-       {0xaa, 0x1b, 0x0000},
-       {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH},           /* 00,86,82,cc, */
-       {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID},            /* 00,87,83,cc, */
-       {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW},            /* 00,88,84,cc, */
-       {0xaa, 0x05, 0x0010},           /* 00,05,10,aa, */
-       {0xaa, 0x0a, 0x0002},
-       {0xaa, 0x0b, 0x0000},
-       {0xaa, 0x0c, 0x0002},
-       {0xaa, 0x0d, 0x0000},
-       {0xaa, 0x0e, 0x0002},
-       {0xaa, 0x0f, 0x0000},
-       {0xaa, 0x10, 0x0002},
-       {0xaa, 0x11, 0x0000},
-       {0xaa, 0x16, 0x0001},           /* 00,16,01,aa, */
-       {0xaa, 0x17, 0x00e8},           /* 00,17,e6,aa, (e6 -> e8) */
-       {0xaa, 0x18, 0x0002},           /* 00,18,02,aa, */
-       {0xaa, 0x19, 0x0088},           /* 00,19,86,aa, */
-       {0xaa, 0x20, 0x0020},           /* 00,20,20,aa, */
-       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,b7,cc, */
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,05,cc, */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0d,cc, */
-       {0xa0, 0x76, ZC3XX_R189_AWBSTATUS},             /* 01,89,76,cc, */
-       {0xa0, 0x09, 0x01ad},                           /* 01,ad,09,cc, */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},         /* 01,c5,03,cc, */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},           /* 01,cb,13,cc, */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc, */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},          /* 03,01,08,cc, */
-       {0xa0, 0x58, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0x61, ZC3XX_R116_RGAIN},                 /* 01,16,61,cc, */
-       {0xa0, 0x65, ZC3XX_R118_BGAIN},                 /* 01,18,65,cc */
-       {0xaa, 0x1b, 0x0000},
-       {}
-};
-
-static const struct usb_action gc0303_InitialScale[] = {
-       {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},         /* 00,00,01,cc, */
-       {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING},          /* 00,08,02,cc, */
-       {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT},      /* 00,10,01,cc, */
-       {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT},
-       {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH},        /* 00,03,02,cc, */
-       {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},         /* 00,04,80,cc, */
-       {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},       /* 00,05,01,cc, */
-       {0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},        /* 00,06,e0,cc, */
-       {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,98,cc, */
-       {0xa0, 0x01, ZC3XX_R001_SYSTEMOPERATING},       /* 00,01,01,cc, */
-       {0xa0, 0x03, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,03,cc, */
-       {0xa0, 0x01, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,01,cc, */
-       {0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},          /* 00,98,00,cc, */
-       {0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},          /* 00,9a,00,cc, */
-       {0xa0, 0x00, ZC3XX_R11A_FIRSTYLOW},             /* 01,1a,00,cc, */
-       {0xa0, 0x00, ZC3XX_R11C_FIRSTXLOW},             /* 01,1c,00,cc, */
-       {0xa0, 0xe8, ZC3XX_R09C_WINHEIGHTLOW},          /* 00,9c,e8,cc,
-                                                        * 8<->6 */
-       {0xa0, 0x88, ZC3XX_R09E_WINWIDTHLOW},           /* 00,9e,88,cc,
-                                                        * 8<->6 */
-       {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID},            /* 00,87,10,cc, */
-       {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR},         /* 00,8b,98,cc, */
-       {0xaa, 0x01, 0x0000},
-       {0xaa, 0x1a, 0x0000},           /* 00,1a,00,aa, */
-       {0xaa, 0x1c, 0x0017},           /* 00,1c,17,aa, */
-       {0xaa, 0x1b, 0x0000},
-       {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH},   /* 00,86,82,cc, */
-       {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID},    /* 00,87,83,cc, */
-       {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW},    /* 00,88,84,cc, */
-       {0xaa, 0x05, 0x0010},           /* 00,05,10,aa, */
-       {0xaa, 0x0a, 0x0001},
-       {0xaa, 0x0b, 0x0000},
-       {0xaa, 0x0c, 0x0001},
-       {0xaa, 0x0d, 0x0000},
-       {0xaa, 0x0e, 0x0001},
-       {0xaa, 0x0f, 0x0000},
-       {0xaa, 0x10, 0x0001},
-       {0xaa, 0x11, 0x0000},
-       {0xaa, 0x16, 0x0001},           /* 00,16,01,aa, */
-       {0xaa, 0x17, 0x00e8},           /* 00,17,e6,aa (e6 -> e8) */
-       {0xaa, 0x18, 0x0002},           /* 00,18,02,aa, */
-       {0xaa, 0x19, 0x0088},           /* 00,19,88,aa, */
-       {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION},      /* 01,01,b7,cc, */
-       {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC},      /* 00,12,05,cc, */
-       {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0d,cc, */
-       {0xa0, 0x76, ZC3XX_R189_AWBSTATUS},             /* 01,89,76,cc, */
-       {0xa0, 0x09, 0x01ad},                           /* 01,ad,09,cc, */
-       {0xa0, 0x03, ZC3XX_R1C5_SHARPNESSMODE},         /* 01,c5,03,cc, */
-       {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05},           /* 01,cb,13,cc, */
-       {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE},        /* 02,50,08,cc, */
-       {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS},          /* 03,01,08,cc, */
-       {0xa0, 0x58, ZC3XX_R1A8_DIGITALGAIN},
-       {0xa0, 0x61, ZC3XX_R116_RGAIN},         /* 01,16,61,cc, */
-       {0xa0, 0x65, ZC3XX_R118_BGAIN},         /* 01,18,65,cc */
-       {0xaa, 0x1b, 0x0000},
-       {}
-};
-static const struct usb_action gc0303_50HZ[] = {
-       {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
-       {0xaa, 0x83, 0x0001},           /* 00,83,01,aa */
-       {0xaa, 0x84, 0x0063},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc, */
-       {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,0d,cc, */
-       {0xa0, 0xa8, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,50,cc, */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc, */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc, */
-       {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,47,cc, */
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},              /* 01,8c,0e,cc, */
-       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,15,cc, */
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,10,cc, */
-       {0xa0, 0x48, ZC3XX_R1AA_DIGITALGAINSTEP},
-       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},               /* 00,1d,62,cc, */
-       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},               /* 00,1e,90,cc, */
-       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},               /* 00,1f,c8,cc, */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc, */
-       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc, */
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc, */
-       {0xa0, 0x7f, ZC3XX_R18D_YTARGET},
-       {}
-};
-
-static const struct usb_action gc0303_50HZScale[] = {
-       {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
-       {0xaa, 0x83, 0x0003},           /* 00,83,03,aa */
-       {0xaa, 0x84, 0x0054},           /* 00,84,54,aa */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc, */
-       {0xa0, 0x0d, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,0d,cc, */
-       {0xa0, 0x50, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,50,cc, */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc, */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc, */
-       {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,8e,cc, */
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},              /* 01,8c,0e,cc, */
-       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,15,cc, */
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,10,cc, */
-       {0xa0, 0x48, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc, */
-       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},               /* 00,1d,62,cc, */
-       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},               /* 00,1e,90,cc, */
-       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},               /* 00,1f,c8,cc, */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc, */
-       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc, */
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc, */
-       {0xa0, 0x7f, ZC3XX_R18D_YTARGET},
-       {}
-};
-
-static const struct usb_action gc0303_60HZ[] = {
-       {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
-       {0xaa, 0x83, 0x0000},
-       {0xaa, 0x84, 0x003b},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc, */
-       {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,91,05,cc, */
-       {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,92,88,cc, */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc, */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc, */
-       {0xa0, 0x3b, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,3b,cc, */
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},              /* 01,8c,0e,cc, */
-       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,15,cc, */
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,a9,10,cc, */
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,aa,24,cc, */
-       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},               /* 00,1d,62,cc, */
-       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},               /* 00,1e,90,cc, */
-       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},               /* 00,1f,c8,cc, */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc, */
-       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc, */
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc, */
-       {0xa0, 0x80, ZC3XX_R18D_YTARGET},
-       {}
-};
-
-static const struct usb_action gc0303_60HZScale[] = {
-       {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
-       {0xaa, 0x83, 0x0000},
-       {0xaa, 0x84, 0x0076},
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc, */
-       {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID},      /* 01,1,0b,cc, */
-       {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW},      /* 01,2,10,cc, */
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,5,00,cc, */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,6,00,cc, */
-       {0xa0, 0x76, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,7,76,cc, */
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},              /* 01,c,0e,cc, */
-       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},            /* 01,f,15,cc, */
-       {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF},      /* 01,9,10,cc, */
-       {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP},       /* 01,a,24,cc, */
-       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},               /* 00,d,62,cc, */
-       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},               /* 00,e,90,cc, */
-       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},               /* 00,f,c8,cc, */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,0,ff,cc, */
-       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,d,58,cc, */
-       {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,42,cc, */
-       {0xa0, 0x80, ZC3XX_R18D_YTARGET},
-       {}
-};
-
-static const struct usb_action gc0303_NoFliker[] = {
-       {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0c,cc, */
-       {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
-       {0xaa, 0x83, 0x0000},           /* 00,83,00,aa */
-       {0xaa, 0x84, 0x0020},           /* 00,84,20,aa */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,0,00,cc, */
-       {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc, */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc, */
-       {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,10,cc, */
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},              /* 01,8c,0e,cc, */
-       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,15,cc, */
-       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},               /* 00,1d,62,cc, */
-       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},               /* 00,1e,90,cc, */
-       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},               /* 00,1f,c8,cc, */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc, */
-       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc, */
-       {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,03,cc */
-       {}
-};
-
-static const struct usb_action gc0303_NoFlikerScale[] = {
-       {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE},         /* 01,00,0c,cc, */
-       {0xaa, 0x82, 0x0000},           /* 00,82,00,aa */
-       {0xaa, 0x83, 0x0000},           /* 00,83,00,aa */
-       {0xaa, 0x84, 0x0020},           /* 00,84,20,aa */
-       {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH},     /* 01,90,00,cc, */
-       {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID},
-       {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW},
-       {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH},       /* 01,95,00,cc, */
-       {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID},        /* 01,96,00,cc, */
-       {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW},        /* 01,97,10,cc, */
-       {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE},              /* 01,8c,0e,cc, */
-       {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE},            /* 01,8f,15,cc, */
-       {0xa0, 0x62, ZC3XX_R01D_HSYNC_0},               /* 00,1d,62,cc, */
-       {0xa0, 0x90, ZC3XX_R01E_HSYNC_1},               /* 00,1e,90,cc, */
-       {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2},               /* 00,1f,c8,cc, */
-       {0xa0, 0xff, ZC3XX_R020_HSYNC_3},               /* 00,20,ff,cc, */
-       {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN},            /* 01,1d,58,cc, */
-       {0xa0, 0x03, ZC3XX_R180_AUTOCORRECTENABLE},     /* 01,80,03,cc */
-       {}
-};
-
-static u8 reg_r(struct gspca_dev *gspca_dev,
-               u16 index)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return 0;
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_rcvctrlpipe(gspca_dev->dev, 0),
-                       0xa1,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0x01,                   /* value */
-                       index, gspca_dev->usb_buf, 1,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_r err %d\n", ret);
-               gspca_dev->usb_err = ret;
-               return 0;
-       }
-       return gspca_dev->usb_buf[0];
-}
-
-static void reg_w(struct gspca_dev *gspca_dev,
-                       u8 value,
-                       u16 index)
-{
-       int ret;
-
-       if (gspca_dev->usb_err < 0)
-               return;
-       ret = usb_control_msg(gspca_dev->dev,
-                       usb_sndctrlpipe(gspca_dev->dev, 0),
-                       0xa0,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index, NULL, 0,
-                       500);
-       if (ret < 0) {
-               pr_err("reg_w_i err %d\n", ret);
-               gspca_dev->usb_err = ret;
-       }
-}
-
-static u16 i2c_read(struct gspca_dev *gspca_dev,
-                       u8 reg)
-{
-       u8 retbyte;
-       u16 retval;
-
-       if (gspca_dev->usb_err < 0)
-               return 0;
-       reg_w(gspca_dev, reg, 0x0092);
-       reg_w(gspca_dev, 0x02, 0x0090);                 /* <- read command */
-       msleep(20);
-       retbyte = reg_r(gspca_dev, 0x0091);             /* read status */
-       if (retbyte != 0x00)
-               pr_err("i2c_r status error %02x\n", retbyte);
-       retval = reg_r(gspca_dev, 0x0095);              /* read Lowbyte */
-       retval |= reg_r(gspca_dev, 0x0096) << 8;        /* read Hightbyte */
-       return retval;
-}
-
-static u8 i2c_write(struct gspca_dev *gspca_dev,
-                       u8 reg,
-                       u8 valL,
-                       u8 valH)
-{
-       u8 retbyte;
-
-       if (gspca_dev->usb_err < 0)
-               return 0;
-       reg_w(gspca_dev, reg, 0x92);
-       reg_w(gspca_dev, valL, 0x93);
-       reg_w(gspca_dev, valH, 0x94);
-       reg_w(gspca_dev, 0x01, 0x90);           /* <- write command */
-       msleep(1);
-       retbyte = reg_r(gspca_dev, 0x0091);             /* read status */
-       if (retbyte != 0x00)
-               pr_err("i2c_w status error %02x\n", retbyte);
-       return retbyte;
-}
-
-static void usb_exchange(struct gspca_dev *gspca_dev,
-                       const struct usb_action *action)
-{
-       while (action->req) {
-               switch (action->req) {
-               case 0xa0:      /* write register */
-                       reg_w(gspca_dev, action->val, action->idx);
-                       break;
-               case 0xa1:      /* read status */
-                       reg_r(gspca_dev, action->idx);
-                       break;
-               case 0xaa:
-                       i2c_write(gspca_dev,
-                                 action->val,                  /* reg */
-                                 action->idx & 0xff,           /* valL */
-                                 action->idx >> 8);            /* valH */
-                       break;
-               case 0xbb:
-                       i2c_write(gspca_dev,
-                                 action->idx >> 8,             /* reg */
-                                 action->idx & 0xff,           /* valL */
-                                 action->val);                 /* valH */
-                       break;
-               default:
-/*             case 0xdd:       * delay */
-                       msleep(action->idx);
-                       break;
-               }
-               action++;
-               msleep(1);
-       }
-}
-
-static void setmatrix(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i;
-       const u8 *matrix;
-       static const u8 adcm2700_matrix[9] =
-/*             {0x66, 0xed, 0xed, 0xed, 0x66, 0xed, 0xed, 0xed, 0x66}; */
-/*ms-win*/
-               {0x74, 0xed, 0xed, 0xed, 0x74, 0xed, 0xed, 0xed, 0x74};
-       static const u8 gc0305_matrix[9] =
-               {0x50, 0xf8, 0xf8, 0xf8, 0x50, 0xf8, 0xf8, 0xf8, 0x50};
-       static const u8 ov7620_matrix[9] =
-               {0x58, 0xf4, 0xf4, 0xf4, 0x58, 0xf4, 0xf4, 0xf4, 0x58};
-       static const u8 pas202b_matrix[9] =
-               {0x4c, 0xf5, 0xff, 0xf9, 0x51, 0xf5, 0xfb, 0xed, 0x5f};
-       static const u8 po2030_matrix[9] =
-               {0x60, 0xf0, 0xf0, 0xf0, 0x60, 0xf0, 0xf0, 0xf0, 0x60};
-       static const u8 tas5130c_matrix[9] =
-               {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68};
-       static const u8 gc0303_matrix[9] =
-               {0x6c, 0xea, 0xea, 0xea, 0x6c, 0xea, 0xea, 0xea, 0x6c};
-       static const u8 *matrix_tb[SENSOR_MAX] = {
-               [SENSOR_ADCM2700] =     adcm2700_matrix,
-               [SENSOR_CS2102] =       ov7620_matrix,
-               [SENSOR_CS2102K] =      NULL,
-               [SENSOR_GC0303] =       gc0303_matrix,
-               [SENSOR_GC0305] =       gc0305_matrix,
-               [SENSOR_HDCS2020] =     NULL,
-               [SENSOR_HV7131B] =      NULL,
-               [SENSOR_HV7131R] =      po2030_matrix,
-               [SENSOR_ICM105A] =      po2030_matrix,
-               [SENSOR_MC501CB] =      NULL,
-               [SENSOR_MT9V111_1] =    gc0305_matrix,
-               [SENSOR_MT9V111_3] =    gc0305_matrix,
-               [SENSOR_OV7620] =       ov7620_matrix,
-               [SENSOR_OV7630C] =      NULL,
-               [SENSOR_PAS106] =       NULL,
-               [SENSOR_PAS202B] =      pas202b_matrix,
-               [SENSOR_PB0330] =       gc0305_matrix,
-               [SENSOR_PO2030] =       po2030_matrix,
-               [SENSOR_TAS5130C] =     tas5130c_matrix,
-       };
-
-       matrix = matrix_tb[sd->sensor];
-       if (matrix == NULL)
-               return;         /* matrix already loaded */
-       for (i = 0; i < ARRAY_SIZE(ov7620_matrix); i++)
-               reg_w(gspca_dev, matrix[i], 0x010a + i);
-}
-
-static void setsharpness(struct gspca_dev *gspca_dev, s32 val)
-{
-       static const u8 sharpness_tb[][2] = {
-               {0x02, 0x03},
-               {0x04, 0x07},
-               {0x08, 0x0f},
-               {0x10, 0x1e}
-       };
-
-       reg_w(gspca_dev, sharpness_tb[val][0], 0x01c6);
-       reg_r(gspca_dev, 0x01c8);
-       reg_r(gspca_dev, 0x01c9);
-       reg_r(gspca_dev, 0x01ca);
-       reg_w(gspca_dev, sharpness_tb[val][1], 0x01cb);
-}
-
-static void setcontrast(struct gspca_dev *gspca_dev,
-               s32 gamma, s32 brightness, s32 contrast)
-{
-       const u8 *Tgamma;
-       int g, i, adj, gp1, gp2;
-       u8 gr[16];
-       static const u8 delta_b[16] =           /* delta for brightness */
-               {0x50, 0x38, 0x2d, 0x28, 0x24, 0x21, 0x1e, 0x1d,
-                0x1d, 0x1b, 0x1b, 0x1b, 0x19, 0x18, 0x18, 0x18};
-       static const u8 delta_c[16] =           /* delta for contrast */
-               {0x2c, 0x1a, 0x12, 0x0c, 0x0a, 0x06, 0x06, 0x06,
-                0x04, 0x06, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02};
-       static const u8 gamma_tb[6][16] = {
-               {0x00, 0x00, 0x03, 0x0d, 0x1b, 0x2e, 0x45, 0x5f,
-                0x79, 0x93, 0xab, 0xc1, 0xd4, 0xe5, 0xf3, 0xff},
-               {0x01, 0x0c, 0x1f, 0x3a, 0x53, 0x6d, 0x85, 0x9c,
-                0xb0, 0xc2, 0xd1, 0xde, 0xe9, 0xf2, 0xf9, 0xff},
-               {0x04, 0x16, 0x30, 0x4e, 0x68, 0x81, 0x98, 0xac,
-                0xbe, 0xcd, 0xda, 0xe4, 0xed, 0xf5, 0xfb, 0xff},
-               {0x13, 0x38, 0x59, 0x79, 0x92, 0xa7, 0xb9, 0xc8,
-                0xd4, 0xdf, 0xe7, 0xee, 0xf4, 0xf9, 0xfc, 0xff},
-               {0x20, 0x4b, 0x6e, 0x8d, 0xa3, 0xb5, 0xc5, 0xd2,
-                0xdc, 0xe5, 0xec, 0xf2, 0xf6, 0xfa, 0xfd, 0xff},
-               {0x24, 0x44, 0x64, 0x84, 0x9d, 0xb2, 0xc4, 0xd3,
-                0xe0, 0xeb, 0xf4, 0xff, 0xff, 0xff, 0xff, 0xff},
-       };
-
-       Tgamma = gamma_tb[gamma - 1];
-
-       contrast -= 128; /* -128 / 127 */
-       brightness -= 128; /* -128 / 92 */
-       adj = 0;
-       gp1 = gp2 = 0;
-       for (i = 0; i < 16; i++) {
-               g = Tgamma[i] + delta_b[i] * brightness / 256
-                               - delta_c[i] * contrast / 256 - adj / 2;
-               if (g > 0xff)
-                       g = 0xff;
-               else if (g < 0)
-                       g = 0;
-               reg_w(gspca_dev, g, 0x0120 + i);        /* gamma */
-               if (contrast > 0)
-                       adj--;
-               else if (contrast < 0)
-                       adj++;
-               if (i > 1)
-                       gr[i - 1] = (g - gp2) / 2;
-               else if (i != 0)
-                       gr[0] = gp1 == 0 ? 0 : (g - gp1);
-               gp2 = gp1;
-               gp1 = g;
-       }
-       gr[15] = (0xff - gp2) / 2;
-       for (i = 0; i < 16; i++)
-               reg_w(gspca_dev, gr[i], 0x0130 + i);    /* gradient */
-}
-
-static s32 getexposure(struct gspca_dev *gspca_dev)
-{
-       return (i2c_read(gspca_dev, 0x25) << 9)
-               | (i2c_read(gspca_dev, 0x26) << 1)
-               | (i2c_read(gspca_dev, 0x27) >> 7);
-}
-
-static void setexposure(struct gspca_dev *gspca_dev, s32 val)
-{
-       i2c_write(gspca_dev, 0x25, val >> 9, 0x00);
-       i2c_write(gspca_dev, 0x26, val >> 1, 0x00);
-       i2c_write(gspca_dev, 0x27, val << 7, 0x00);
-}
-
-static void setquality(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       jpeg_set_qual(sd->jpeg_hdr, jpeg_qual[sd->reg08 >> 1]);
-       reg_w(gspca_dev, sd->reg08, ZC3XX_R008_CLOCKSETTING);
-}
-
-/* Matches the sensor's internal frame rate to the lighting frequency.
- * Valid frequencies are:
- *     50Hz, for European and Asian lighting (default)
- *     60Hz, for American lighting
- *     0 = No Fliker (for outdoore usage)
- */
-static void setlightfreq(struct gspca_dev *gspca_dev, s32 val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i, mode;
-       const struct usb_action *zc3_freq;
-       static const struct usb_action *freq_tb[SENSOR_MAX][6] = {
-       [SENSOR_ADCM2700] =
-               {adcm2700_NoFliker, adcm2700_NoFliker,
-                adcm2700_50HZ, adcm2700_50HZ,
-                adcm2700_60HZ, adcm2700_60HZ},
-       [SENSOR_CS2102] =
-               {cs2102_NoFliker, cs2102_NoFlikerScale,
-                cs2102_50HZ, cs2102_50HZScale,
-                cs2102_60HZ, cs2102_60HZScale},
-       [SENSOR_CS2102K] =
-               {cs2102_NoFliker, cs2102_NoFlikerScale,
-                NULL, NULL, /* currently disabled */
-                NULL, NULL},
-       [SENSOR_GC0303] =
-               {gc0303_NoFliker, gc0303_NoFlikerScale,
-                gc0303_50HZ, gc0303_50HZScale,
-                gc0303_60HZ, gc0303_60HZScale},
-       [SENSOR_GC0305] =
-               {gc0305_NoFliker, gc0305_NoFliker,
-                gc0305_50HZ, gc0305_50HZ,
-                gc0305_60HZ, gc0305_60HZ},
-       [SENSOR_HDCS2020] =
-               {hdcs2020_NoFliker, hdcs2020_NoFliker,
-                hdcs2020_50HZ, hdcs2020_50HZ,
-                hdcs2020_60HZ, hdcs2020_60HZ},
-       [SENSOR_HV7131B] =
-               {hv7131b_NoFliker, hv7131b_NoFlikerScale,
-                hv7131b_50HZ, hv7131b_50HZScale,
-                hv7131b_60HZ, hv7131b_60HZScale},
-       [SENSOR_HV7131R] =
-               {hv7131r_NoFliker, hv7131r_NoFlikerScale,
-                hv7131r_50HZ, hv7131r_50HZScale,
-                hv7131r_60HZ, hv7131r_60HZScale},
-       [SENSOR_ICM105A] =
-               {icm105a_NoFliker, icm105a_NoFlikerScale,
-                icm105a_50HZ, icm105a_50HZScale,
-                icm105a_60HZ, icm105a_60HZScale},
-       [SENSOR_MC501CB] =
-               {mc501cb_NoFliker, mc501cb_NoFlikerScale,
-                mc501cb_50HZ, mc501cb_50HZScale,
-                mc501cb_60HZ, mc501cb_60HZScale},
-       [SENSOR_MT9V111_1] =
-               {mt9v111_1_AENoFliker, mt9v111_1_AENoFlikerScale,
-                mt9v111_1_AE50HZ, mt9v111_1_AE50HZScale,
-                mt9v111_1_AE60HZ, mt9v111_1_AE60HZScale},
-       [SENSOR_MT9V111_3] =
-               {mt9v111_3_AENoFliker, mt9v111_3_AENoFlikerScale,
-                mt9v111_3_AE50HZ, mt9v111_3_AE50HZScale,
-                mt9v111_3_AE60HZ, mt9v111_3_AE60HZScale},
-       [SENSOR_OV7620] =
-               {ov7620_NoFliker, ov7620_NoFliker,
-                ov7620_50HZ, ov7620_50HZ,
-                ov7620_60HZ, ov7620_60HZ},
-       [SENSOR_OV7630C] =
-               {NULL, NULL,
-                NULL, NULL,
-                NULL, NULL},
-       [SENSOR_PAS106] =
-               {pas106b_NoFliker, pas106b_NoFliker,
-                pas106b_50HZ, pas106b_50HZ,
-                pas106b_60HZ, pas106b_60HZ},
-       [SENSOR_PAS202B] =
-               {pas202b_NoFliker, pas202b_NoFlikerScale,
-                pas202b_50HZ, pas202b_50HZScale,
-                pas202b_60HZ, pas202b_60HZScale},
-       [SENSOR_PB0330] =
-               {pb0330_NoFliker, pb0330_NoFlikerScale,
-                pb0330_50HZ, pb0330_50HZScale,
-                pb0330_60HZ, pb0330_60HZScale},
-       [SENSOR_PO2030] =
-               {po2030_NoFliker, po2030_NoFliker,
-                po2030_50HZ, po2030_50HZ,
-                po2030_60HZ, po2030_60HZ},
-       [SENSOR_TAS5130C] =
-               {tas5130c_NoFliker, tas5130c_NoFlikerScale,
-                tas5130c_50HZ, tas5130c_50HZScale,
-                tas5130c_60HZ, tas5130c_60HZScale},
-       };
-
-       i = val * 2;
-       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-       if (mode)
-               i++;                    /* 320x240 */
-       zc3_freq = freq_tb[sd->sensor][i];
-       if (zc3_freq == NULL)
-               return;
-       usb_exchange(gspca_dev, zc3_freq);
-       switch (sd->sensor) {
-       case SENSOR_GC0305:
-               if (mode                /* if 320x240 */
-                   && val == 1)        /* and 50Hz */
-                       reg_w(gspca_dev, 0x85, 0x018d);
-                                       /* win: 0x80, 0x018d */
-               break;
-       case SENSOR_OV7620:
-               if (!mode) {            /* if 640x480 */
-                       if (val != 0)   /* and filter */
-                               reg_w(gspca_dev, 0x40, 0x0002);
-                       else
-                               reg_w(gspca_dev, 0x44, 0x0002);
-               }
-               break;
-       case SENSOR_PAS202B:
-               reg_w(gspca_dev, 0x00, 0x01a7);
-               break;
-       }
-}
-
-static void setautogain(struct gspca_dev *gspca_dev, s32 val)
-{
-       reg_w(gspca_dev, val ? 0x42 : 0x02, 0x0180);
-}
-
-/*
- * Update the transfer parameters.
- * This function is executed from a work queue.
- */
-static void transfer_update(struct work_struct *work)
-{
-       struct sd *sd = container_of(work, struct sd, work);
-       struct gspca_dev *gspca_dev = &sd->gspca_dev;
-       int change, good;
-       u8 reg07, reg11;
-
-       /* reg07 gets set to 0 by sd_start before starting us */
-       reg07 = 0;
-
-       good = 0;
-       for (;;) {
-               msleep(100);
-
-               mutex_lock(&gspca_dev->usb_lock);
-#ifdef CONFIG_PM
-               if (gspca_dev->frozen)
-                       goto err;
-#endif
-               if (!gspca_dev->dev || !gspca_dev->streaming)
-                       goto err;
-
-               /* Bit 0 of register 11 indicates FIFO overflow */
-               gspca_dev->usb_err = 0;
-               reg11 = reg_r(gspca_dev, 0x0011);
-               if (gspca_dev->usb_err)
-                       goto err;
-
-               change = reg11 & 0x01;
-               if (change) {                           /* overflow */
-                       good = 0;
-
-                       if (reg07 == 0) /* Bit Rate Control not enabled? */
-                               reg07 = 0x32; /* Allow 98 bytes / unit */
-                       else if (reg07 > 2)
-                               reg07 -= 2; /* Decrease allowed bytes / unit */
-                       else
-                               change = 0;
-               } else {                                /* no overflow */
-                       good++;
-                       if (good >= 10) {
-                               good = 0;
-                               if (reg07) { /* BRC enabled? */
-                                       change = 1;
-                                       if (reg07 < 0x32)
-                                               reg07 += 2;
-                                       else
-                                               reg07 = 0;
-                               }
-                       }
-               }
-               if (change) {
-                       gspca_dev->usb_err = 0;
-                       reg_w(gspca_dev, reg07, 0x0007);
-                       if (gspca_dev->usb_err)
-                               goto err;
-               }
-               mutex_unlock(&gspca_dev->usb_lock);
-       }
-       return;
-err:
-       mutex_unlock(&gspca_dev->usb_lock);
-}
-
-static void send_unknown(struct gspca_dev *gspca_dev, int sensor)
-{
-       reg_w(gspca_dev, 0x01, 0x0000);         /* bridge reset */
-       switch (sensor) {
-       case SENSOR_PAS106:
-               reg_w(gspca_dev, 0x03, 0x003a);
-               reg_w(gspca_dev, 0x0c, 0x003b);
-               reg_w(gspca_dev, 0x08, 0x0038);
-               break;
-       case SENSOR_ADCM2700:
-       case SENSOR_GC0305:
-       case SENSOR_OV7620:
-       case SENSOR_MT9V111_1:
-       case SENSOR_MT9V111_3:
-       case SENSOR_PB0330:
-       case SENSOR_PO2030:
-               reg_w(gspca_dev, 0x0d, 0x003a);
-               reg_w(gspca_dev, 0x02, 0x003b);
-               reg_w(gspca_dev, 0x00, 0x0038);
-               break;
-       case SENSOR_HV7131R:
-       case SENSOR_PAS202B:
-               reg_w(gspca_dev, 0x03, 0x003b);
-               reg_w(gspca_dev, 0x0c, 0x003a);
-               reg_w(gspca_dev, 0x0b, 0x0039);
-               if (sensor == SENSOR_PAS202B)
-                       reg_w(gspca_dev, 0x0b, 0x0038);
-               break;
-       }
-}
-
-/* start probe 2 wires */
-static void start_2wr_probe(struct gspca_dev *gspca_dev, int sensor)
-{
-       reg_w(gspca_dev, 0x01, 0x0000);
-       reg_w(gspca_dev, sensor, 0x0010);
-       reg_w(gspca_dev, 0x01, 0x0001);
-       reg_w(gspca_dev, 0x03, 0x0012);
-       reg_w(gspca_dev, 0x01, 0x0012);
-/*     msleep(2); */
-}
-
-static int sif_probe(struct gspca_dev *gspca_dev)
-{
-       u16 checkword;
-
-       start_2wr_probe(gspca_dev, 0x0f);               /* PAS106 */
-       reg_w(gspca_dev, 0x08, 0x008d);
-       msleep(150);
-       checkword = ((i2c_read(gspca_dev, 0x00) & 0x0f) << 4)
-                       | ((i2c_read(gspca_dev, 0x01) & 0xf0) >> 4);
-       PDEBUG(D_PROBE, "probe sif 0x%04x", checkword);
-       if (checkword == 0x0007) {
-               send_unknown(gspca_dev, SENSOR_PAS106);
-               return 0x0f;                    /* PAS106 */
-       }
-       return -1;
-}
-
-static int vga_2wr_probe(struct gspca_dev *gspca_dev)
-{
-       u16 retword;
-
-       start_2wr_probe(gspca_dev, 0x00);       /* HV7131B */
-       i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
-       retword = i2c_read(gspca_dev, 0x01);
-       if (retword != 0)
-               return 0x00;                    /* HV7131B */
-
-       start_2wr_probe(gspca_dev, 0x04);       /* CS2102 */
-       i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
-       retword = i2c_read(gspca_dev, 0x01);
-       if (retword != 0)
-               return 0x04;                    /* CS2102 */
-
-       start_2wr_probe(gspca_dev, 0x06);       /* OmniVision */
-       reg_w(gspca_dev, 0x08, 0x008d);
-       i2c_write(gspca_dev, 0x11, 0xaa, 0x00);
-       retword = i2c_read(gspca_dev, 0x11);
-       if (retword != 0) {
-               /* (should have returned 0xaa) --> Omnivision? */
-               /* reg_r 0x10 -> 0x06 -->  */
-               goto ov_check;
-       }
-
-       start_2wr_probe(gspca_dev, 0x08);       /* HDCS2020 */
-       i2c_write(gspca_dev, 0x1c, 0x00, 0x00);
-       i2c_write(gspca_dev, 0x15, 0xaa, 0x00);
-       retword = i2c_read(gspca_dev, 0x15);
-       if (retword != 0)
-               return 0x08;                    /* HDCS2020 */
-
-       start_2wr_probe(gspca_dev, 0x0a);       /* PB0330 */
-       i2c_write(gspca_dev, 0x07, 0xaa, 0xaa);
-       retword = i2c_read(gspca_dev, 0x07);
-       if (retword != 0)
-               return 0x0a;                    /* PB0330 */
-       retword = i2c_read(gspca_dev, 0x03);
-       if (retword != 0)
-               return 0x0a;                    /* PB0330 ?? */
-       retword = i2c_read(gspca_dev, 0x04);
-       if (retword != 0)
-               return 0x0a;                    /* PB0330 ?? */
-
-       start_2wr_probe(gspca_dev, 0x0c);       /* ICM105A */
-       i2c_write(gspca_dev, 0x01, 0x11, 0x00);
-       retword = i2c_read(gspca_dev, 0x01);
-       if (retword != 0)
-               return 0x0c;                    /* ICM105A */
-
-       start_2wr_probe(gspca_dev, 0x0e);       /* PAS202BCB */
-       reg_w(gspca_dev, 0x08, 0x008d);
-       i2c_write(gspca_dev, 0x03, 0xaa, 0x00);
-       msleep(50);
-       retword = i2c_read(gspca_dev, 0x03);
-       if (retword != 0) {
-               send_unknown(gspca_dev, SENSOR_PAS202B);
-               return 0x0e;                    /* PAS202BCB */
-       }
-
-       start_2wr_probe(gspca_dev, 0x02);       /* TAS5130C */
-       i2c_write(gspca_dev, 0x01, 0xaa, 0x00);
-       retword = i2c_read(gspca_dev, 0x01);
-       if (retword != 0)
-               return 0x02;                    /* TAS5130C */
-ov_check:
-       reg_r(gspca_dev, 0x0010);               /* ?? */
-       reg_r(gspca_dev, 0x0010);
-
-       reg_w(gspca_dev, 0x01, 0x0000);
-       reg_w(gspca_dev, 0x01, 0x0001);
-       reg_w(gspca_dev, 0x06, 0x0010);         /* OmniVision */
-       reg_w(gspca_dev, 0xa1, 0x008b);
-       reg_w(gspca_dev, 0x08, 0x008d);
-       msleep(500);
-       reg_w(gspca_dev, 0x01, 0x0012);
-       i2c_write(gspca_dev, 0x12, 0x80, 0x00); /* sensor reset */
-       retword = i2c_read(gspca_dev, 0x0a) << 8;
-       retword |= i2c_read(gspca_dev, 0x0b);
-       PDEBUG(D_PROBE, "probe 2wr ov vga 0x%04x", retword);
-       switch (retword) {
-       case 0x7631:                            /* OV7630C */
-               reg_w(gspca_dev, 0x06, 0x0010);
-               break;
-       case 0x7620:                            /* OV7620 */
-       case 0x7648:                            /* OV7648 */
-               break;
-       default:
-               return -1;                      /* not OmniVision */
-       }
-       return retword;
-}
-
-struct sensor_by_chipset_revision {
-       u16 revision;
-       u8 internal_sensor_id;
-};
-static const struct sensor_by_chipset_revision chipset_revision_sensor[] = {
-       {0xc000, 0x12},         /* TAS5130C */
-       {0xc001, 0x13},         /* MT9V111 */
-       {0xe001, 0x13},
-       {0x8001, 0x13},
-       {0x8000, 0x14},         /* CS2102K */
-       {0x8400, 0x15},         /* MT9V111 */
-       {0xe400, 0x15},
-};
-
-static int vga_3wr_probe(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int i;
-       u16 retword;
-
-/*fixme: lack of 8b=b3 (11,12)-> 10, 8b=e0 (14,15,16)-> 12 found in gspcav1*/
-       reg_w(gspca_dev, 0x02, 0x0010);
-       reg_r(gspca_dev, 0x0010);
-       reg_w(gspca_dev, 0x01, 0x0000);
-       reg_w(gspca_dev, 0x00, 0x0010);
-       reg_w(gspca_dev, 0x01, 0x0001);
-       reg_w(gspca_dev, 0x91, 0x008b);
-       reg_w(gspca_dev, 0x03, 0x0012);
-       reg_w(gspca_dev, 0x01, 0x0012);
-       reg_w(gspca_dev, 0x05, 0x0012);
-       retword = i2c_read(gspca_dev, 0x14);
-       if (retword != 0)
-               return 0x11;                    /* HV7131R */
-       retword = i2c_read(gspca_dev, 0x15);
-       if (retword != 0)
-               return 0x11;                    /* HV7131R */
-       retword = i2c_read(gspca_dev, 0x16);
-       if (retword != 0)
-               return 0x11;                    /* HV7131R */
-
-       reg_w(gspca_dev, 0x02, 0x0010);
-       retword = reg_r(gspca_dev, 0x000b) << 8;
-       retword |= reg_r(gspca_dev, 0x000a);
-       PDEBUG(D_PROBE, "probe 3wr vga 1 0x%04x", retword);
-       reg_r(gspca_dev, 0x0010);
-       if ((retword & 0xff00) == 0x6400)
-               return 0x02;            /* TAS5130C */
-       for (i = 0; i < ARRAY_SIZE(chipset_revision_sensor); i++) {
-               if (chipset_revision_sensor[i].revision == retword) {
-                       sd->chip_revision = retword;
-                       send_unknown(gspca_dev, SENSOR_PB0330);
-                       return chipset_revision_sensor[i].internal_sensor_id;
-               }
-       }
-
-       reg_w(gspca_dev, 0x01, 0x0000); /* check PB0330 */
-       reg_w(gspca_dev, 0x01, 0x0001);
-       reg_w(gspca_dev, 0xdd, 0x008b);
-       reg_w(gspca_dev, 0x0a, 0x0010);
-       reg_w(gspca_dev, 0x03, 0x0012);
-       reg_w(gspca_dev, 0x01, 0x0012);
-       retword = i2c_read(gspca_dev, 0x00);
-       if (retword != 0) {
-               PDEBUG(D_PROBE, "probe 3wr vga type 0a");
-               return 0x0a;                    /* PB0330 */
-       }
-
-       /* probe gc0303 / gc0305 */
-       reg_w(gspca_dev, 0x01, 0x0000);
-       reg_w(gspca_dev, 0x01, 0x0001);
-       reg_w(gspca_dev, 0x98, 0x008b);
-       reg_w(gspca_dev, 0x01, 0x0010);
-       reg_w(gspca_dev, 0x03, 0x0012);
-       msleep(2);
-       reg_w(gspca_dev, 0x01, 0x0012);
-       retword = i2c_read(gspca_dev, 0x00);
-       if (retword != 0) {
-               PDEBUG(D_PROBE, "probe 3wr vga type %02x", retword);
-               if (retword == 0x0011)                  /* gc0303 */
-                       return 0x0303;
-               if (retword == 0x0029)                  /* gc0305 */
-                       send_unknown(gspca_dev, SENSOR_GC0305);
-               return retword;
-       }
-
-       reg_w(gspca_dev, 0x01, 0x0000); /* check OmniVision */
-       reg_w(gspca_dev, 0x01, 0x0001);
-       reg_w(gspca_dev, 0xa1, 0x008b);
-       reg_w(gspca_dev, 0x08, 0x008d);
-       reg_w(gspca_dev, 0x06, 0x0010);
-       reg_w(gspca_dev, 0x01, 0x0012);
-       reg_w(gspca_dev, 0x05, 0x0012);
-       if (i2c_read(gspca_dev, 0x1c) == 0x007f /* OV7610 - manufacturer ID */
-           && i2c_read(gspca_dev, 0x1d) == 0x00a2) {
-               send_unknown(gspca_dev, SENSOR_OV7620);
-               return 0x06;            /* OmniVision confirm ? */
-       }
-
-       reg_w(gspca_dev, 0x01, 0x0000);
-       reg_w(gspca_dev, 0x00, 0x0002);
-       reg_w(gspca_dev, 0x01, 0x0010);
-       reg_w(gspca_dev, 0x01, 0x0001);
-       reg_w(gspca_dev, 0xee, 0x008b);
-       reg_w(gspca_dev, 0x03, 0x0012);
-       reg_w(gspca_dev, 0x01, 0x0012);
-       reg_w(gspca_dev, 0x05, 0x0012);
-       retword = i2c_read(gspca_dev, 0x00) << 8;       /* ID 0 */
-       retword |= i2c_read(gspca_dev, 0x01);           /* ID 1 */
-       PDEBUG(D_PROBE, "probe 3wr vga 2 0x%04x", retword);
-       if (retword == 0x2030) {
-#ifdef GSPCA_DEBUG
-               u8 retbyte;
-
-               retbyte = i2c_read(gspca_dev, 0x02);    /* revision number */
-               PDEBUG(D_PROBE, "sensor PO2030 rev 0x%02x", retbyte);
-#endif
-               send_unknown(gspca_dev, SENSOR_PO2030);
-               return retword;
-       }
-
-       reg_w(gspca_dev, 0x01, 0x0000);
-       reg_w(gspca_dev, 0x0a, 0x0010);
-       reg_w(gspca_dev, 0xd3, 0x008b);
-       reg_w(gspca_dev, 0x01, 0x0001);
-       reg_w(gspca_dev, 0x03, 0x0012);
-       reg_w(gspca_dev, 0x01, 0x0012);
-       reg_w(gspca_dev, 0x05, 0x0012);
-       reg_w(gspca_dev, 0xd3, 0x008b);
-       retword = i2c_read(gspca_dev, 0x01);
-       if (retword != 0) {
-               PDEBUG(D_PROBE, "probe 3wr vga type 0a ? ret: %04x", retword);
-               return 0x16;                    /* adcm2700 (6100/6200) */
-       }
-       return -1;
-}
-
-static int zcxx_probeSensor(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int sensor;
-
-       switch (sd->sensor) {
-       case SENSOR_MC501CB:
-               return -1;              /* don't probe */
-       case SENSOR_GC0303:
-                       /* may probe but with no write in reg 0x0010 */
-               return -1;              /* don't probe */
-       case SENSOR_PAS106:
-               sensor =  sif_probe(gspca_dev);
-               if (sensor >= 0)
-                       return sensor;
-               break;
-       }
-       sensor = vga_2wr_probe(gspca_dev);
-       if (sensor >= 0)
-               return sensor;
-       return vga_3wr_probe(gspca_dev);
-}
-
-/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
-                       const struct usb_device_id *id)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (id->idProduct == 0x301b)
-               sd->bridge = BRIDGE_ZC301;
-       else
-               sd->bridge = BRIDGE_ZC303;
-
-       /* define some sensors from the vendor/product */
-       sd->sensor = id->driver_info;
-
-       sd->reg08 = REG08_DEF;
-
-       INIT_WORK(&sd->work, transfer_update);
-
-       return 0;
-}
-
-static int zcxx_g_volatile_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;
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUTOGAIN:
-               gspca_dev->usb_err = 0;
-               if (ctrl->val && sd->exposure && gspca_dev->streaming)
-                       sd->exposure->val = getexposure(gspca_dev);
-               return gspca_dev->usb_err;
-       }
-       return -EINVAL;
-}
-
-static int zcxx_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;
-       int i, qual;
-
-       gspca_dev->usb_err = 0;
-
-       if (ctrl->id == V4L2_CID_JPEG_COMPRESSION_QUALITY) {
-               qual = sd->reg08 >> 1;
-
-               for (i = 0; i < ARRAY_SIZE(jpeg_qual); i++) {
-                       if (ctrl->val <= jpeg_qual[i])
-                               break;
-               }
-               if (i > 0 && i == qual && ctrl->val < jpeg_qual[i])
-                       i--;
-
-               /* With high quality settings we need max bandwidth */
-               if (i >= 2 && gspca_dev->streaming &&
-                   !gspca_dev->cam.needs_full_bandwidth)
-                       return -EBUSY;
-
-               sd->reg08 = (i << 1) | 1;
-               ctrl->val = jpeg_qual[i];
-       }
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       switch (ctrl->id) {
-       /* gamma/brightness/contrast cluster */
-       case V4L2_CID_GAMMA:
-               setcontrast(gspca_dev, sd->gamma->val,
-                               sd->brightness->val, sd->contrast->val);
-               break;
-       /* autogain/exposure cluster */
-       case V4L2_CID_AUTOGAIN:
-               setautogain(gspca_dev, ctrl->val);
-               if (!gspca_dev->usb_err && !ctrl->val && sd->exposure)
-                       setexposure(gspca_dev, sd->exposure->val);
-               break;
-       case V4L2_CID_POWER_LINE_FREQUENCY:
-               setlightfreq(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_SHARPNESS:
-               setsharpness(gspca_dev, ctrl->val);
-               break;
-       case V4L2_CID_JPEG_COMPRESSION_QUALITY:
-               setquality(gspca_dev);
-               break;
-       }
-       return gspca_dev->usb_err;
-}
-
-static const struct v4l2_ctrl_ops zcxx_ctrl_ops = {
-       .g_volatile_ctrl = zcxx_g_volatile_ctrl,
-       .s_ctrl = zcxx_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;
-       static const u8 gamma[SENSOR_MAX] = {
-               [SENSOR_ADCM2700] =     4,
-               [SENSOR_CS2102] =       4,
-               [SENSOR_CS2102K] =      5,
-               [SENSOR_GC0303] =       3,
-               [SENSOR_GC0305] =       4,
-               [SENSOR_HDCS2020] =     4,
-               [SENSOR_HV7131B] =      4,
-               [SENSOR_HV7131R] =      4,
-               [SENSOR_ICM105A] =      4,
-               [SENSOR_MC501CB] =      4,
-               [SENSOR_MT9V111_1] =    4,
-               [SENSOR_MT9V111_3] =    4,
-               [SENSOR_OV7620] =       3,
-               [SENSOR_OV7630C] =      4,
-               [SENSOR_PAS106] =       4,
-               [SENSOR_PAS202B] =      4,
-               [SENSOR_PB0330] =       4,
-               [SENSOR_PO2030] =       4,
-               [SENSOR_TAS5130C] =     3,
-       };
-
-       gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 8);
-       sd->brightness = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
-                       V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
-       sd->contrast = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
-                       V4L2_CID_CONTRAST, 0, 255, 1, 128);
-       sd->gamma = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
-                       V4L2_CID_GAMMA, 1, 6, 1, gamma[sd->sensor]);
-       if (sd->sensor == SENSOR_HV7131R)
-               sd->exposure = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
-                       V4L2_CID_EXPOSURE, 0x30d, 0x493e, 1, 0x927);
-       sd->autogain = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
-                       V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
-       if (sd->sensor != SENSOR_OV7630C)
-               sd->plfreq = v4l2_ctrl_new_std_menu(hdl, &zcxx_ctrl_ops,
-                       V4L2_CID_POWER_LINE_FREQUENCY,
-                       V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0,
-                       V4L2_CID_POWER_LINE_FREQUENCY_DISABLED);
-       sd->sharpness = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
-                       V4L2_CID_SHARPNESS, 0, 3, 1,
-                       sd->sensor == SENSOR_PO2030 ? 0 : 2);
-       sd->jpegqual = v4l2_ctrl_new_std(hdl, &zcxx_ctrl_ops,
-                       V4L2_CID_JPEG_COMPRESSION_QUALITY,
-                       jpeg_qual[0], jpeg_qual[ARRAY_SIZE(jpeg_qual) - 1], 1,
-                       jpeg_qual[REG08_DEF >> 1]);
-       if (hdl->error) {
-               pr_err("Could not initialize controls\n");
-               return hdl->error;
-       }
-       v4l2_ctrl_cluster(3, &sd->gamma);
-       if (sd->sensor == SENSOR_HV7131R)
-               v4l2_ctrl_auto_cluster(2, &sd->autogain, 0, true);
-       return 0;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       struct cam *cam;
-       int sensor;
-       static const u8 mode_tb[SENSOR_MAX] = {
-               [SENSOR_ADCM2700] =     2,
-               [SENSOR_CS2102] =       1,
-               [SENSOR_CS2102K] =      1,
-               [SENSOR_GC0303] =       1,
-               [SENSOR_GC0305] =       1,
-               [SENSOR_HDCS2020] =     1,
-               [SENSOR_HV7131B] =      1,
-               [SENSOR_HV7131R] =      1,
-               [SENSOR_ICM105A] =      1,
-               [SENSOR_MC501CB] =      2,
-               [SENSOR_MT9V111_1] =    1,
-               [SENSOR_MT9V111_3] =    1,
-               [SENSOR_OV7620] =       2,
-               [SENSOR_OV7630C] =      1,
-               [SENSOR_PAS106] =       0,
-               [SENSOR_PAS202B] =      1,
-               [SENSOR_PB0330] =       1,
-               [SENSOR_PO2030] =       1,
-               [SENSOR_TAS5130C] =     1,
-       };
-
-       sensor = zcxx_probeSensor(gspca_dev);
-       if (sensor >= 0)
-               PDEBUG(D_PROBE, "probe sensor -> %04x", sensor);
-       if ((unsigned) force_sensor < SENSOR_MAX) {
-               sd->sensor = force_sensor;
-               PDEBUG(D_PROBE, "sensor forced to %d", force_sensor);
-       } else {
-               switch (sensor) {
-               case -1:
-                       switch (sd->sensor) {
-                       case SENSOR_MC501CB:
-                               PDEBUG(D_PROBE, "Sensor MC501CB");
-                               break;
-                       case SENSOR_GC0303:
-                               PDEBUG(D_PROBE, "Sensor GC0303");
-                               break;
-                       default:
-                               pr_warn("Unknown sensor - set to TAS5130C\n");
-                               sd->sensor = SENSOR_TAS5130C;
-                       }
-                       break;
-               case 0:
-                       /* check the sensor type */
-                       sensor = i2c_read(gspca_dev, 0x00);
-                       PDEBUG(D_PROBE, "Sensor hv7131 type %d", sensor);
-                       switch (sensor) {
-                       case 0:                 /* hv7131b */
-                       case 1:                 /* hv7131e */
-                               PDEBUG(D_PROBE, "Find Sensor HV7131B");
-                               sd->sensor = SENSOR_HV7131B;
-                               break;
-                       default:
-/*                     case 2:                  * hv7131r */
-                               PDEBUG(D_PROBE, "Find Sensor HV7131R");
-                               sd->sensor = SENSOR_HV7131R;
-                               break;
-                       }
-                       break;
-               case 0x02:
-                       PDEBUG(D_PROBE, "Sensor TAS5130C");
-                       sd->sensor = SENSOR_TAS5130C;
-                       break;
-               case 0x04:
-                       PDEBUG(D_PROBE, "Find Sensor CS2102");
-                       sd->sensor = SENSOR_CS2102;
-                       break;
-               case 0x08:
-                       PDEBUG(D_PROBE, "Find Sensor HDCS2020");
-                       sd->sensor = SENSOR_HDCS2020;
-                       break;
-               case 0x0a:
-                       PDEBUG(D_PROBE,
-                               "Find Sensor PB0330. Chip revision %x",
-                               sd->chip_revision);
-                       sd->sensor = SENSOR_PB0330;
-                       break;
-               case 0x0c:
-                       PDEBUG(D_PROBE, "Find Sensor ICM105A");
-                       sd->sensor = SENSOR_ICM105A;
-                       break;
-               case 0x0e:
-                       PDEBUG(D_PROBE, "Find Sensor PAS202B");
-                       sd->sensor = SENSOR_PAS202B;
-                       break;
-               case 0x0f:
-                       PDEBUG(D_PROBE, "Find Sensor PAS106");
-                       sd->sensor = SENSOR_PAS106;
-                       break;
-               case 0x10:
-               case 0x12:
-                       PDEBUG(D_PROBE, "Find Sensor TAS5130C");
-                       sd->sensor = SENSOR_TAS5130C;
-                       break;
-               case 0x11:
-                       PDEBUG(D_PROBE, "Find Sensor HV7131R");
-                       sd->sensor = SENSOR_HV7131R;
-                       break;
-               case 0x13:
-               case 0x15:
-                       PDEBUG(D_PROBE,
-                               "Sensor MT9V111. Chip revision %04x",
-                               sd->chip_revision);
-                       sd->sensor = sd->bridge == BRIDGE_ZC301
-                                       ? SENSOR_MT9V111_1
-                                       : SENSOR_MT9V111_3;
-                       break;
-               case 0x14:
-                       PDEBUG(D_PROBE,
-                               "Find Sensor CS2102K?. Chip revision %x",
-                               sd->chip_revision);
-                       sd->sensor = SENSOR_CS2102K;
-                       break;
-               case 0x16:
-                       PDEBUG(D_PROBE, "Find Sensor ADCM2700");
-                       sd->sensor = SENSOR_ADCM2700;
-                       break;
-               case 0x29:
-                       PDEBUG(D_PROBE, "Find Sensor GC0305");
-                       sd->sensor = SENSOR_GC0305;
-                       break;
-               case 0x0303:
-                       PDEBUG(D_PROBE, "Sensor GC0303");
-                       sd->sensor =  SENSOR_GC0303;
-                       break;
-               case 0x2030:
-                       PDEBUG(D_PROBE, "Find Sensor PO2030");
-                       sd->sensor = SENSOR_PO2030;
-                       break;
-               case 0x7620:
-                       PDEBUG(D_PROBE, "Find Sensor OV7620");
-                       sd->sensor = SENSOR_OV7620;
-                       break;
-               case 0x7631:
-                       PDEBUG(D_PROBE, "Find Sensor OV7630C");
-                       sd->sensor = SENSOR_OV7630C;
-                       break;
-               case 0x7648:
-                       PDEBUG(D_PROBE, "Find Sensor OV7648");
-                       sd->sensor = SENSOR_OV7620;     /* same sensor (?) */
-                       break;
-               default:
-                       pr_err("Unknown sensor %04x\n", sensor);
-                       return -EINVAL;
-               }
-       }
-       if (sensor < 0x20) {
-               if (sensor == -1 || sensor == 0x10 || sensor == 0x12)
-                       reg_w(gspca_dev, 0x02, 0x0010);
-               reg_r(gspca_dev, 0x0010);
-       }
-
-       cam = &gspca_dev->cam;
-       switch (mode_tb[sd->sensor]) {
-       case 0:
-               cam->cam_mode = sif_mode;
-               cam->nmodes = ARRAY_SIZE(sif_mode);
-               break;
-       case 1:
-               cam->cam_mode = vga_mode;
-               cam->nmodes = ARRAY_SIZE(vga_mode);
-               break;
-       default:
-/*     case 2: */
-               cam->cam_mode = broken_vga_mode;
-               cam->nmodes = ARRAY_SIZE(broken_vga_mode);
-               break;
-       }
-
-       /* switch off the led */
-       reg_w(gspca_dev, 0x01, 0x0000);
-       return gspca_dev->usb_err;
-}
-
-static int sd_pre_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       gspca_dev->cam.needs_full_bandwidth = (sd->reg08 >= 4) ? 1 : 0;
-       return 0;
-}
-
-static int sd_start(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int mode;
-       static const struct usb_action *init_tb[SENSOR_MAX][2] = {
-       [SENSOR_ADCM2700] =
-                       {adcm2700_Initial, adcm2700_InitialScale},
-       [SENSOR_CS2102] =
-                       {cs2102_Initial, cs2102_InitialScale},
-       [SENSOR_CS2102K] =
-                       {cs2102K_Initial, cs2102K_InitialScale},
-       [SENSOR_GC0303] =
-               {gc0303_Initial, gc0303_InitialScale},
-       [SENSOR_GC0305] =
-                       {gc0305_Initial, gc0305_InitialScale},
-       [SENSOR_HDCS2020] =
-                       {hdcs2020_Initial, hdcs2020_InitialScale},
-       [SENSOR_HV7131B] =
-                       {hv7131b_Initial, hv7131b_InitialScale},
-       [SENSOR_HV7131R] =
-                       {hv7131r_Initial, hv7131r_InitialScale},
-       [SENSOR_ICM105A] =
-                       {icm105a_Initial, icm105a_InitialScale},
-       [SENSOR_MC501CB] =
-                       {mc501cb_Initial, mc501cb_InitialScale},
-       [SENSOR_MT9V111_1] =
-                       {mt9v111_1_Initial, mt9v111_1_InitialScale},
-       [SENSOR_MT9V111_3] =
-                       {mt9v111_3_Initial, mt9v111_3_InitialScale},
-       [SENSOR_OV7620] =
-                       {ov7620_Initial, ov7620_InitialScale},
-       [SENSOR_OV7630C] =
-                       {ov7630c_Initial, ov7630c_InitialScale},
-       [SENSOR_PAS106] =
-                       {pas106b_Initial, pas106b_InitialScale},
-       [SENSOR_PAS202B] =
-                       {pas202b_Initial, pas202b_InitialScale},
-       [SENSOR_PB0330] =
-                       {pb0330_Initial, pb0330_InitialScale},
-       [SENSOR_PO2030] =
-                       {po2030_Initial, po2030_InitialScale},
-       [SENSOR_TAS5130C] =
-                       {tas5130c_Initial, tas5130c_InitialScale},
-       };
-
-       /* create the JPEG header */
-       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
-                       0x21);          /* JPEG 422 */
-
-       mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-       switch (sd->sensor) {
-       case SENSOR_HV7131R:
-               zcxx_probeSensor(gspca_dev);
-               break;
-       case SENSOR_PAS106:
-               usb_exchange(gspca_dev, pas106b_Initial_com);
-               break;
-       }
-       usb_exchange(gspca_dev, init_tb[sd->sensor][mode]);
-
-       switch (sd->sensor) {
-       case SENSOR_ADCM2700:
-       case SENSOR_GC0305:
-       case SENSOR_OV7620:
-       case SENSOR_PO2030:
-       case SENSOR_TAS5130C:
-       case SENSOR_GC0303:
-/*             msleep(100);                     * ?? */
-               reg_r(gspca_dev, 0x0002);       /* --> 0x40 */
-               reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
-               reg_w(gspca_dev, 0x15, 0x01ae);
-               if (sd->sensor == SENSOR_TAS5130C)
-                       break;
-               reg_w(gspca_dev, 0x0d, 0x003a);
-               reg_w(gspca_dev, 0x02, 0x003b);
-               reg_w(gspca_dev, 0x00, 0x0038);
-               break;
-       case SENSOR_HV7131R:
-       case SENSOR_PAS202B:
-               reg_w(gspca_dev, 0x03, 0x003b);
-               reg_w(gspca_dev, 0x0c, 0x003a);
-               reg_w(gspca_dev, 0x0b, 0x0039);
-               if (sd->sensor == SENSOR_HV7131R)
-                       reg_w(gspca_dev, 0x50, ZC3XX_R11D_GLOBALGAIN);
-               break;
-       }
-
-       setmatrix(gspca_dev);
-       switch (sd->sensor) {
-       case SENSOR_ADCM2700:
-       case SENSOR_OV7620:
-               reg_r(gspca_dev, 0x0008);
-               reg_w(gspca_dev, 0x00, 0x0008);
-               break;
-       case SENSOR_PAS202B:
-       case SENSOR_GC0305:
-       case SENSOR_HV7131R:
-       case SENSOR_TAS5130C:
-               reg_r(gspca_dev, 0x0008);
-               /* fall thru */
-       case SENSOR_PO2030:
-               reg_w(gspca_dev, 0x03, 0x0008);
-               break;
-       }
-       setsharpness(gspca_dev, v4l2_ctrl_g_ctrl(sd->sharpness));
-
-       /* set the gamma tables when not set */
-       switch (sd->sensor) {
-       case SENSOR_CS2102K:            /* gamma set in xxx_Initial */
-       case SENSOR_HDCS2020:
-       case SENSOR_OV7630C:
-               break;
-       default:
-               setcontrast(gspca_dev, v4l2_ctrl_g_ctrl(sd->gamma),
-                               v4l2_ctrl_g_ctrl(sd->brightness),
-                               v4l2_ctrl_g_ctrl(sd->contrast));
-               break;
-       }
-       setmatrix(gspca_dev);                   /* one more time? */
-       switch (sd->sensor) {
-       case SENSOR_OV7620:
-       case SENSOR_PAS202B:
-               reg_r(gspca_dev, 0x0180);       /* from win */
-               reg_w(gspca_dev, 0x00, 0x0180);
-               break;
-       }
-       setquality(gspca_dev);
-       /* Start with BRC disabled, transfer_update will enable it if needed */
-       reg_w(gspca_dev, 0x00, 0x0007);
-       if (sd->plfreq)
-               setlightfreq(gspca_dev, v4l2_ctrl_g_ctrl(sd->plfreq));
-
-       switch (sd->sensor) {
-       case SENSOR_ADCM2700:
-               reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
-               reg_w(gspca_dev, 0x15, 0x01ae);
-               reg_w(gspca_dev, 0x02, 0x0180);
-                                               /* ms-win + */
-               reg_w(gspca_dev, 0x40, 0x0117);
-               break;
-       case SENSOR_HV7131R:
-               setexposure(gspca_dev, v4l2_ctrl_g_ctrl(sd->exposure));
-               reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN);
-               break;
-       case SENSOR_GC0305:
-       case SENSOR_TAS5130C:
-               reg_w(gspca_dev, 0x09, 0x01ad); /* (from win traces) */
-               reg_w(gspca_dev, 0x15, 0x01ae);
-               /* fall thru */
-       case SENSOR_PAS202B:
-       case SENSOR_PO2030:
-/*             reg_w(gspca_dev, 0x40, ZC3XX_R117_GGAIN); in win traces */
-               reg_r(gspca_dev, 0x0180);
-               break;
-       case SENSOR_OV7620:
-               reg_w(gspca_dev, 0x09, 0x01ad);
-               reg_w(gspca_dev, 0x15, 0x01ae);
-               i2c_read(gspca_dev, 0x13);      /*fixme: returns 0xa3 */
-               i2c_write(gspca_dev, 0x13, 0xa3, 0x00);
-                                       /*fixme: returned value to send? */
-               reg_w(gspca_dev, 0x40, 0x0117);
-               reg_r(gspca_dev, 0x0180);
-               break;
-       }
-
-       setautogain(gspca_dev, v4l2_ctrl_g_ctrl(sd->autogain));
-
-       if (gspca_dev->usb_err < 0)
-               return gspca_dev->usb_err;
-
-       /* Start the transfer parameters update thread */
-       sd->work_thread = create_singlethread_workqueue(KBUILD_MODNAME);
-       queue_work(sd->work_thread, &sd->work);
-
-       return 0;
-}
-
-/* called on streamoff with alt 0 and on disconnect */
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       if (sd->work_thread != NULL) {
-               mutex_unlock(&gspca_dev->usb_lock);
-               destroy_workqueue(sd->work_thread);
-               mutex_lock(&gspca_dev->usb_lock);
-               sd->work_thread = NULL;
-       }
-       if (!gspca_dev->dev)
-               return;
-       send_unknown(gspca_dev, sd->sensor);
-}
-
-static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,
-                       int len)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       /* check the JPEG end of frame */
-       if (len >= 3
-        && data[len - 3] == 0xff && data[len - 2] == 0xd9) {
-/*fixme: what does the last byte mean?*/
-               gspca_frame_add(gspca_dev, LAST_PACKET,
-                                       data, len - 1);
-               return;
-       }
-
-       /* check the JPEG start of a frame */
-       if (data[0] == 0xff && data[1] == 0xd8) {
-               /* put the JPEG header in the new frame */
-               gspca_frame_add(gspca_dev, FIRST_PACKET,
-                       sd->jpeg_hdr, JPEG_HDR_SZ);
-
-               /* remove the webcam's header:
-                * ff d8 ff fe 00 0e 00 00 ss ss 00 01 ww ww hh hh pp pp
-                *      - 'ss ss' is the frame sequence number (BE)
-                *      - 'ww ww' and 'hh hh' are the window dimensions (BE)
-                *      - 'pp pp' is the packet sequence number (BE)
-                */
-               data += 18;
-               len -= 18;
-       }
-       gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
-}
-
-static int sd_set_jcomp(struct gspca_dev *gspca_dev,
-                       struct v4l2_jpegcompression *jcomp)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       int ret;
-
-       ret = v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
-       if (ret)
-               return ret;
-       jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
-       return 0;
-}
-
-static int sd_get_jcomp(struct gspca_dev *gspca_dev,
-                       struct v4l2_jpegcompression *jcomp)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
-       memset(jcomp, 0, sizeof *jcomp);
-       jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
-       jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
-                       | V4L2_JPEG_MARKER_DQT;
-       return 0;
-}
-
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-static int sd_int_pkt_scan(struct gspca_dev *gspca_dev,
-                       u8 *data,               /* interrupt packet data */
-                       int len)                /* interrput packet length */
-{
-       if (len == 8 && data[4] == 1) {
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 1);
-               input_sync(gspca_dev->input_dev);
-               input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
-               input_sync(gspca_dev->input_dev);
-       }
-
-       return 0;
-}
-#endif
-
-static const struct sd_desc sd_desc = {
-       .name = KBUILD_MODNAME,
-       .config = sd_config,
-       .init = sd_init,
-       .init_controls = sd_init_controls,
-       .isoc_init = sd_pre_start,
-       .start = sd_start,
-       .stop0 = sd_stop0,
-       .pkt_scan = sd_pkt_scan,
-       .get_jcomp = sd_get_jcomp,
-       .set_jcomp = sd_set_jcomp,
-#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
-       .int_pkt_scan = sd_int_pkt_scan,
-#endif
-};
-
-static const struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x03f0, 0x1b07)},
-       {USB_DEVICE(0x041e, 0x041e)},
-       {USB_DEVICE(0x041e, 0x4017)},
-       {USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106},
-       {USB_DEVICE(0x041e, 0x401e)},
-       {USB_DEVICE(0x041e, 0x401f)},
-       {USB_DEVICE(0x041e, 0x4022)},
-       {USB_DEVICE(0x041e, 0x4029)},
-       {USB_DEVICE(0x041e, 0x4034), .driver_info = SENSOR_PAS106},
-       {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106},
-       {USB_DEVICE(0x041e, 0x4036)},
-       {USB_DEVICE(0x041e, 0x403a)},
-       {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_GC0303},
-       {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_GC0303},
-       {USB_DEVICE(0x0458, 0x7007)},
-       {USB_DEVICE(0x0458, 0x700c)},
-       {USB_DEVICE(0x0458, 0x700f)},
-       {USB_DEVICE(0x0461, 0x0a00)},
-       {USB_DEVICE(0x046d, 0x089d), .driver_info = SENSOR_MC501CB},
-       {USB_DEVICE(0x046d, 0x08a0)},
-       {USB_DEVICE(0x046d, 0x08a1)},
-       {USB_DEVICE(0x046d, 0x08a2)},
-       {USB_DEVICE(0x046d, 0x08a3)},
-       {USB_DEVICE(0x046d, 0x08a6)},
-       {USB_DEVICE(0x046d, 0x08a7)},
-       {USB_DEVICE(0x046d, 0x08a9)},
-       {USB_DEVICE(0x046d, 0x08aa)},
-       {USB_DEVICE(0x046d, 0x08ac)},
-       {USB_DEVICE(0x046d, 0x08ad)},
-       {USB_DEVICE(0x046d, 0x08ae)},
-       {USB_DEVICE(0x046d, 0x08af)},
-       {USB_DEVICE(0x046d, 0x08b9)},
-       {USB_DEVICE(0x046d, 0x08d7)},
-       {USB_DEVICE(0x046d, 0x08d8)},
-       {USB_DEVICE(0x046d, 0x08d9)},
-       {USB_DEVICE(0x046d, 0x08da)},
-       {USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB},
-       {USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106},
-       {USB_DEVICE(0x0471, 0x0326), .driver_info = SENSOR_PAS106},
-       {USB_DEVICE(0x0471, 0x032d), .driver_info = SENSOR_PAS106},
-       {USB_DEVICE(0x0471, 0x032e), .driver_info = SENSOR_PAS106},
-       {USB_DEVICE(0x055f, 0xc005)},
-       {USB_DEVICE(0x055f, 0xd003)},
-       {USB_DEVICE(0x055f, 0xd004)},
-       {USB_DEVICE(0x0698, 0x2003)},
-       {USB_DEVICE(0x0ac8, 0x0301), .driver_info = SENSOR_PAS106},
-       {USB_DEVICE(0x0ac8, 0x0302), .driver_info = SENSOR_PAS106},
-       {USB_DEVICE(0x0ac8, 0x301b)},
-       {USB_DEVICE(0x0ac8, 0x303b)},
-       {USB_DEVICE(0x0ac8, 0x305b)},
-       {USB_DEVICE(0x0ac8, 0x307b)},
-       {USB_DEVICE(0x10fd, 0x0128)},
-       {USB_DEVICE(0x10fd, 0x804d)},
-       {USB_DEVICE(0x10fd, 0x8050)},
-       {}                      /* end of entry */
-};
-MODULE_DEVICE_TABLE(usb, device_table);
-
-/* -- device connect -- */
-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);
-}
-
-/* USB driver */
-static struct usb_driver sd_driver = {
-       .name = KBUILD_MODNAME,
-       .id_table = device_table,
-       .probe = sd_probe,
-       .disconnect = gspca_disconnect,
-#ifdef CONFIG_PM
-       .suspend = gspca_suspend,
-       .resume = gspca_resume,
-       .reset_resume = gspca_resume,
-#endif
-};
-
-module_usb_driver(sd_driver);
-
-module_param(force_sensor, int, 0644);
-MODULE_PARM_DESC(force_sensor,
-       "Force sensor. Only for experts!!!");
diff --git a/drivers/media/video/hdpvr/Kconfig b/drivers/media/video/hdpvr/Kconfig
deleted file mode 100644 (file)
index de247f3..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-
-config VIDEO_HDPVR
-       tristate "Hauppauge HD PVR support"
-       depends on VIDEO_DEV
-       ---help---
-         This is a video4linux driver for Hauppauge's HD PVR USB device.
-
-         To compile this driver as a module, choose M here: the
-         module will be called hdpvr
-
diff --git a/drivers/media/video/hdpvr/Makefile b/drivers/media/video/hdpvr/Makefile
deleted file mode 100644 (file)
index 52f057f..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-hdpvr-objs     := hdpvr-control.o hdpvr-core.o hdpvr-video.o hdpvr-i2c.o
-
-obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o
-
-ccflags-y += -Idrivers/media/video
-
-ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
diff --git a/drivers/media/video/hdpvr/hdpvr-control.c b/drivers/media/video/hdpvr/hdpvr-control.c
deleted file mode 100644 (file)
index ae8f229..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Hauppauge HD PVR USB driver - video 4 linux 2 interface
- *
- * Copyright (C) 2008      Janne Grunau (j@jannau.net)
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation, version 2.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/mutex.h>
-
-#include <linux/videodev2.h>
-
-#include <media/v4l2-common.h>
-
-#include "hdpvr.h"
-
-
-int hdpvr_config_call(struct hdpvr_device *dev, uint value, u8 valbuf)
-{
-       int ret;
-       char request_type = 0x38, snd_request = 0x01;
-
-       mutex_lock(&dev->usbc_mutex);
-       dev->usbc_buf[0] = valbuf;
-       ret = usb_control_msg(dev->udev,
-                             usb_sndctrlpipe(dev->udev, 0),
-                             snd_request, 0x00 | request_type,
-                             value, CTRL_DEFAULT_INDEX,
-                             dev->usbc_buf, 1, 10000);
-
-       mutex_unlock(&dev->usbc_mutex);
-       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                "config call request for value 0x%x returned %d\n", value,
-                ret);
-
-       return ret < 0 ? ret : 0;
-}
-
-struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev)
-{
-       struct hdpvr_video_info *vidinf = NULL;
-#ifdef HDPVR_DEBUG
-       char print_buf[15];
-#endif
-       int ret;
-
-       vidinf = kzalloc(sizeof(struct hdpvr_video_info), GFP_KERNEL);
-       if (!vidinf) {
-               v4l2_err(&dev->v4l2_dev, "out of memory\n");
-               goto err;
-       }
-
-       mutex_lock(&dev->usbc_mutex);
-       ret = usb_control_msg(dev->udev,
-                             usb_rcvctrlpipe(dev->udev, 0),
-                             0x81, 0x80 | 0x38,
-                             0x1400, 0x0003,
-                             dev->usbc_buf, 5,
-                             1000);
-       if (ret == 5) {
-               vidinf->width   = dev->usbc_buf[1] << 8 | dev->usbc_buf[0];
-               vidinf->height  = dev->usbc_buf[3] << 8 | dev->usbc_buf[2];
-               vidinf->fps     = dev->usbc_buf[4];
-       }
-
-#ifdef HDPVR_DEBUG
-       if (hdpvr_debug & MSG_INFO) {
-               hex_dump_to_buffer(dev->usbc_buf, 5, 16, 1, print_buf,
-                                  sizeof(print_buf), 0);
-               v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                        "get video info returned: %d, %s\n", ret, print_buf);
-       }
-#endif
-       mutex_unlock(&dev->usbc_mutex);
-
-       if (!vidinf->width || !vidinf->height || !vidinf->fps) {
-               kfree(vidinf);
-               vidinf = NULL;
-       }
-err:
-       return vidinf;
-}
-
-int get_input_lines_info(struct hdpvr_device *dev)
-{
-#ifdef HDPVR_DEBUG
-       char print_buf[9];
-#endif
-       int ret, lines;
-
-       mutex_lock(&dev->usbc_mutex);
-       ret = usb_control_msg(dev->udev,
-                             usb_rcvctrlpipe(dev->udev, 0),
-                             0x81, 0x80 | 0x38,
-                             0x1800, 0x0003,
-                             dev->usbc_buf, 3,
-                             1000);
-
-#ifdef HDPVR_DEBUG
-       if (hdpvr_debug & MSG_INFO) {
-               hex_dump_to_buffer(dev->usbc_buf, 3, 16, 1, print_buf,
-                                  sizeof(print_buf), 0);
-               v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                        "get input lines info returned: %d, %s\n", ret,
-                        print_buf);
-       }
-#else
-       (void)ret;      /* suppress compiler warning */
-#endif
-       lines = dev->usbc_buf[1] << 8 | dev->usbc_buf[0];
-       mutex_unlock(&dev->usbc_mutex);
-       return lines;
-}
-
-
-int hdpvr_set_bitrate(struct hdpvr_device *dev)
-{
-       int ret;
-
-       mutex_lock(&dev->usbc_mutex);
-       memset(dev->usbc_buf, 0, 4);
-       dev->usbc_buf[0] = dev->options.bitrate;
-       dev->usbc_buf[2] = dev->options.peak_bitrate;
-
-       ret = usb_control_msg(dev->udev,
-                             usb_sndctrlpipe(dev->udev, 0),
-                             0x01, 0x38, CTRL_BITRATE_VALUE,
-                             CTRL_DEFAULT_INDEX, dev->usbc_buf, 4, 1000);
-       mutex_unlock(&dev->usbc_mutex);
-
-       return ret;
-}
-
-int hdpvr_set_audio(struct hdpvr_device *dev, u8 input,
-                   enum v4l2_mpeg_audio_encoding codec)
-{
-       int ret = 0;
-
-       if (dev->flags & HDPVR_FLAG_AC3_CAP) {
-               mutex_lock(&dev->usbc_mutex);
-               memset(dev->usbc_buf, 0, 2);
-               dev->usbc_buf[0] = input;
-               if (codec == V4L2_MPEG_AUDIO_ENCODING_AAC)
-                       dev->usbc_buf[1] = 0;
-               else if (codec == V4L2_MPEG_AUDIO_ENCODING_AC3)
-                       dev->usbc_buf[1] = 1;
-               else {
-                       mutex_unlock(&dev->usbc_mutex);
-                       v4l2_err(&dev->v4l2_dev, "invalid audio codec %d\n",
-                                codec);
-                       ret = -EINVAL;
-                       goto error;
-               }
-
-               ret = usb_control_msg(dev->udev,
-                                     usb_sndctrlpipe(dev->udev, 0),
-                                     0x01, 0x38, CTRL_AUDIO_INPUT_VALUE,
-                                     CTRL_DEFAULT_INDEX, dev->usbc_buf, 2,
-                                     1000);
-               mutex_unlock(&dev->usbc_mutex);
-               if (ret == 2)
-                       ret = 0;
-       } else
-               ret = hdpvr_config_call(dev, CTRL_AUDIO_INPUT_VALUE, input);
-error:
-       return ret;
-}
-
-int hdpvr_set_options(struct hdpvr_device *dev)
-{
-       hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, dev->options.video_std);
-
-       hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE,
-                        dev->options.video_input+1);
-
-       hdpvr_set_audio(dev, dev->options.audio_input+1,
-                      dev->options.audio_codec);
-
-       hdpvr_set_bitrate(dev);
-       hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE,
-                        dev->options.bitrate_mode);
-       hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, dev->options.gop_mode);
-
-       hdpvr_config_call(dev, CTRL_BRIGHTNESS, dev->options.brightness);
-       hdpvr_config_call(dev, CTRL_CONTRAST,   dev->options.contrast);
-       hdpvr_config_call(dev, CTRL_HUE,        dev->options.hue);
-       hdpvr_config_call(dev, CTRL_SATURATION, dev->options.saturation);
-       hdpvr_config_call(dev, CTRL_SHARPNESS,  dev->options.sharpness);
-
-       return 0;
-}
diff --git a/drivers/media/video/hdpvr/hdpvr-core.c b/drivers/media/video/hdpvr/hdpvr-core.c
deleted file mode 100644 (file)
index 304f43e..0000000
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * Hauppauge HD PVR USB driver
- *
- * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2008      Janne Grunau (j@jannau.net)
- * Copyright (C) 2008      John Poet
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation, version 2.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/uaccess.h>
-#include <linux/atomic.h>
-#include <linux/usb.h>
-#include <linux/mutex.h>
-#include <linux/i2c.h>
-
-#include <linux/videodev2.h>
-#include <media/v4l2-dev.h>
-#include <media/v4l2-common.h>
-
-#include "hdpvr.h"
-
-static int video_nr[HDPVR_MAX] = {[0 ... (HDPVR_MAX - 1)] = UNSET};
-module_param_array(video_nr, int, NULL, 0);
-MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)");
-
-/* holds the number of currently registered devices */
-static atomic_t dev_nr = ATOMIC_INIT(-1);
-
-int hdpvr_debug;
-module_param(hdpvr_debug, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(hdpvr_debug, "enable debugging output");
-
-static uint default_video_input = HDPVR_VIDEO_INPUTS;
-module_param(default_video_input, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(default_video_input, "default video input: 0=Component / "
-                "1=S-Video / 2=Composite");
-
-static uint default_audio_input = HDPVR_AUDIO_INPUTS;
-module_param(default_audio_input, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(default_audio_input, "default audio input: 0=RCA back / "
-                "1=RCA front / 2=S/PDIF");
-
-static bool boost_audio;
-module_param(boost_audio, bool, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(boost_audio, "boost the audio signal");
-
-
-/* table of devices that work with this driver */
-static struct usb_device_id hdpvr_table[] = {
-       { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID) },
-       { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID1) },
-       { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID2) },
-       { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID3) },
-       { USB_DEVICE(HD_PVR_VENDOR_ID, HD_PVR_PRODUCT_ID4) },
-       { }                                     /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, hdpvr_table);
-
-
-void hdpvr_delete(struct hdpvr_device *dev)
-{
-       hdpvr_free_buffers(dev);
-
-       if (dev->video_dev)
-               video_device_release(dev->video_dev);
-
-       usb_put_dev(dev->udev);
-}
-
-static void challenge(u8 *bytes)
-{
-       u64 *i64P, tmp64;
-       uint i, idx;
-
-       for (idx = 0; idx < 32; ++idx) {
-
-               if (idx & 0x3)
-                       bytes[(idx >> 3) + 3] = bytes[(idx >> 2) & 0x3];
-
-               switch (idx & 0x3) {
-               case 0x3:
-                       bytes[2] += bytes[3] * 4 + bytes[4] + bytes[5];
-                       bytes[4] += bytes[(idx & 0x1) * 2] * 9 + 9;
-                       break;
-               case 0x1:
-                       bytes[0] *= 8;
-                       bytes[0] += 7*idx + 4;
-                       bytes[6] += bytes[3] * 3;
-                       break;
-               case 0x0:
-                       bytes[3 - (idx >> 3)] = bytes[idx >> 2];
-                       bytes[5] += bytes[6] * 3;
-                       for (i = 0; i < 3; i++)
-                               bytes[3] *= bytes[3] + 1;
-                       break;
-               case 0x2:
-                       for (i = 0; i < 3; i++)
-                               bytes[1] *= bytes[6] + 1;
-                       for (i = 0; i < 3; i++) {
-                               i64P = (u64 *)bytes;
-                               tmp64 = le64_to_cpup(i64P);
-                               tmp64 <<= bytes[7] & 0x0f;
-                               *i64P += cpu_to_le64(tmp64);
-                       }
-                       break;
-               }
-       }
-}
-
-/* try to init the device like the windows driver */
-static int device_authorization(struct hdpvr_device *dev)
-{
-
-       int ret, retval = -ENOMEM;
-       char request_type = 0x38, rcv_request = 0x81;
-       char *response;
-#ifdef HDPVR_DEBUG
-       size_t buf_size = 46;
-       char *print_buf = kzalloc(5*buf_size+1, GFP_KERNEL);
-       if (!print_buf) {
-               v4l2_err(&dev->v4l2_dev, "Out of memory\n");
-               return retval;
-       }
-#endif
-
-       mutex_lock(&dev->usbc_mutex);
-       ret = usb_control_msg(dev->udev,
-                             usb_rcvctrlpipe(dev->udev, 0),
-                             rcv_request, 0x80 | request_type,
-                             0x0400, 0x0003,
-                             dev->usbc_buf, 46,
-                             10000);
-       if (ret != 46) {
-               v4l2_err(&dev->v4l2_dev,
-                        "unexpected answer of status request, len %d\n", ret);
-               goto unlock;
-       }
-#ifdef HDPVR_DEBUG
-       else {
-               hex_dump_to_buffer(dev->usbc_buf, 46, 16, 1, print_buf,
-                                  5*buf_size+1, 0);
-               v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                        "Status request returned, len %d: %s\n",
-                        ret, print_buf);
-       }
-#endif
-
-       dev->fw_ver = dev->usbc_buf[1];
-
-       v4l2_info(&dev->v4l2_dev, "firmware version 0x%x dated %s\n",
-                         dev->fw_ver, &dev->usbc_buf[2]);
-
-       if (dev->fw_ver > 0x15) {
-               dev->options.brightness = 0x80;
-               dev->options.contrast   = 0x40;
-               dev->options.hue        = 0xf;
-               dev->options.saturation = 0x40;
-               dev->options.sharpness  = 0x80;
-       }
-
-       switch (dev->fw_ver) {
-       case HDPVR_FIRMWARE_VERSION:
-               dev->flags &= ~HDPVR_FLAG_AC3_CAP;
-               break;
-       case HDPVR_FIRMWARE_VERSION_AC3:
-       case HDPVR_FIRMWARE_VERSION_0X12:
-       case HDPVR_FIRMWARE_VERSION_0X15:
-               dev->flags |= HDPVR_FLAG_AC3_CAP;
-               break;
-       default:
-               v4l2_info(&dev->v4l2_dev, "untested firmware, the driver might"
-                         " not work.\n");
-               if (dev->fw_ver >= HDPVR_FIRMWARE_VERSION_AC3)
-                       dev->flags |= HDPVR_FLAG_AC3_CAP;
-               else
-                       dev->flags &= ~HDPVR_FLAG_AC3_CAP;
-       }
-
-       response = dev->usbc_buf+38;
-#ifdef HDPVR_DEBUG
-       hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0);
-       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, "challenge: %s\n",
-                print_buf);
-#endif
-       challenge(response);
-#ifdef HDPVR_DEBUG
-       hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0);
-       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %s\n",
-                print_buf);
-#endif
-
-       msleep(100);
-       ret = usb_control_msg(dev->udev,
-                             usb_sndctrlpipe(dev->udev, 0),
-                             0xd1, 0x00 | request_type,
-                             0x0000, 0x0000,
-                             response, 8,
-                             10000);
-       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                "magic request returned %d\n", ret);
-
-       retval = ret != 8;
-unlock:
-       mutex_unlock(&dev->usbc_mutex);
-       return retval;
-}
-
-static int hdpvr_device_init(struct hdpvr_device *dev)
-{
-       int ret;
-       u8 *buf;
-       struct hdpvr_video_info *vidinf;
-
-       if (device_authorization(dev))
-               return -EACCES;
-
-       /* default options for init */
-       hdpvr_set_options(dev);
-
-       /* set filter options */
-       mutex_lock(&dev->usbc_mutex);
-       buf = dev->usbc_buf;
-       buf[0] = 0x03; buf[1] = 0x03; buf[2] = 0x00; buf[3] = 0x00;
-       ret = usb_control_msg(dev->udev,
-                             usb_sndctrlpipe(dev->udev, 0),
-                             0x01, 0x38,
-                             CTRL_LOW_PASS_FILTER_VALUE, CTRL_DEFAULT_INDEX,
-                             buf, 4,
-                             1000);
-       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                "control request returned %d\n", ret);
-       mutex_unlock(&dev->usbc_mutex);
-
-       vidinf = get_video_info(dev);
-       if (!vidinf)
-               v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                       "no valid video signal or device init failed\n");
-       else
-               kfree(vidinf);
-
-       /* enable fan and bling leds */
-       mutex_lock(&dev->usbc_mutex);
-       buf[0] = 0x1;
-       ret = usb_control_msg(dev->udev,
-                             usb_sndctrlpipe(dev->udev, 0),
-                             0xd4, 0x38, 0, 0, buf, 1,
-                             1000);
-       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                "control request returned %d\n", ret);
-
-       /* boost analog audio */
-       buf[0] = boost_audio;
-       ret = usb_control_msg(dev->udev,
-                             usb_sndctrlpipe(dev->udev, 0),
-                             0xd5, 0x38, 0, 0, buf, 1,
-                             1000);
-       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                "control request returned %d\n", ret);
-       mutex_unlock(&dev->usbc_mutex);
-
-       dev->status = STATUS_IDLE;
-       return 0;
-}
-
-static const struct hdpvr_options hdpvr_default_options = {
-       .video_std      = HDPVR_60HZ,
-       .video_input    = HDPVR_COMPONENT,
-       .audio_input    = HDPVR_RCA_BACK,
-       .bitrate        = 65, /* 6 mbps */
-       .peak_bitrate   = 90, /* 9 mbps */
-       .bitrate_mode   = HDPVR_CONSTANT,
-       .gop_mode       = HDPVR_SIMPLE_IDR_GOP,
-       .audio_codec    = V4L2_MPEG_AUDIO_ENCODING_AAC,
-       /* original picture controls for firmware version <= 0x15 */
-       /* updated in device_authorization() for newer firmware */
-       .brightness     = 0x86,
-       .contrast       = 0x80,
-       .hue            = 0x80,
-       .saturation     = 0x80,
-       .sharpness      = 0x80,
-};
-
-static int hdpvr_probe(struct usb_interface *interface,
-                      const struct usb_device_id *id)
-{
-       struct hdpvr_device *dev;
-       struct usb_host_interface *iface_desc;
-       struct usb_endpoint_descriptor *endpoint;
-       struct i2c_client *client;
-       size_t buffer_size;
-       int i;
-       int retval = -ENOMEM;
-
-       /* allocate memory for our device state and initialize it */
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (!dev) {
-               dev_err(&interface->dev, "Out of memory\n");
-               goto error;
-       }
-
-       dev->workqueue = 0;
-
-       /* register v4l2_device early so it can be used for printks */
-       if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) {
-               dev_err(&interface->dev, "v4l2_device_register failed\n");
-               goto error;
-       }
-
-       mutex_init(&dev->io_mutex);
-       mutex_init(&dev->i2c_mutex);
-       mutex_init(&dev->usbc_mutex);
-       dev->usbc_buf = kmalloc(64, GFP_KERNEL);
-       if (!dev->usbc_buf) {
-               v4l2_err(&dev->v4l2_dev, "Out of memory\n");
-               goto error;
-       }
-
-       init_waitqueue_head(&dev->wait_buffer);
-       init_waitqueue_head(&dev->wait_data);
-
-       dev->workqueue = create_singlethread_workqueue("hdpvr_buffer");
-       if (!dev->workqueue)
-               goto error;
-
-       /* init video transfer queues */
-       INIT_LIST_HEAD(&dev->free_buff_list);
-       INIT_LIST_HEAD(&dev->rec_buff_list);
-
-       dev->options = hdpvr_default_options;
-
-       if (default_video_input < HDPVR_VIDEO_INPUTS)
-               dev->options.video_input = default_video_input;
-
-       if (default_audio_input < HDPVR_AUDIO_INPUTS) {
-               dev->options.audio_input = default_audio_input;
-               if (default_audio_input == HDPVR_SPDIF)
-                       dev->options.audio_codec =
-                               V4L2_MPEG_AUDIO_ENCODING_AC3;
-       }
-
-       dev->udev = usb_get_dev(interface_to_usbdev(interface));
-
-       /* set up the endpoint information */
-       /* use only the first bulk-in and bulk-out endpoints */
-       iface_desc = interface->cur_altsetting;
-       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-               endpoint = &iface_desc->endpoint[i].desc;
-
-               if (!dev->bulk_in_endpointAddr &&
-                   usb_endpoint_is_bulk_in(endpoint)) {
-                       /* USB interface description is buggy, reported max
-                        * packet size is 512 bytes, windows driver uses 8192 */
-                       buffer_size = 8192;
-                       dev->bulk_in_size = buffer_size;
-                       dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
-               }
-
-       }
-       if (!dev->bulk_in_endpointAddr) {
-               v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n");
-               goto error;
-       }
-
-       /* init the device */
-       if (hdpvr_device_init(dev)) {
-               v4l2_err(&dev->v4l2_dev, "device init failed\n");
-               goto error;
-       }
-
-       mutex_lock(&dev->io_mutex);
-       if (hdpvr_alloc_buffers(dev, NUM_BUFFERS)) {
-               mutex_unlock(&dev->io_mutex);
-               v4l2_err(&dev->v4l2_dev,
-                        "allocating transfer buffers failed\n");
-               goto error;
-       }
-       mutex_unlock(&dev->io_mutex);
-
-       if (hdpvr_register_videodev(dev, &interface->dev,
-                                   video_nr[atomic_inc_return(&dev_nr)])) {
-               v4l2_err(&dev->v4l2_dev, "registering videodev failed\n");
-               goto error;
-       }
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       retval = hdpvr_register_i2c_adapter(dev);
-       if (retval < 0) {
-               v4l2_err(&dev->v4l2_dev, "i2c adapter register failed\n");
-               goto error;
-       }
-
-       client = hdpvr_register_ir_rx_i2c(dev);
-       if (!client) {
-               v4l2_err(&dev->v4l2_dev, "i2c IR RX device register failed\n");
-               goto reg_fail;
-       }
-
-       client = hdpvr_register_ir_tx_i2c(dev);
-       if (!client) {
-               v4l2_err(&dev->v4l2_dev, "i2c IR TX device register failed\n");
-               goto reg_fail;
-       }
-#endif
-
-       /* let the user know what node this device is now attached to */
-       v4l2_info(&dev->v4l2_dev, "device now attached to %s\n",
-                 video_device_node_name(dev->video_dev));
-       return 0;
-
-reg_fail:
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       i2c_del_adapter(&dev->i2c_adapter);
-#endif
-error:
-       if (dev) {
-               /* Destroy single thread */
-               if (dev->workqueue)
-                       destroy_workqueue(dev->workqueue);
-               /* this frees allocated memory */
-               hdpvr_delete(dev);
-       }
-       return retval;
-}
-
-static void hdpvr_disconnect(struct usb_interface *interface)
-{
-       struct hdpvr_device *dev = to_hdpvr_dev(usb_get_intfdata(interface));
-
-       v4l2_info(&dev->v4l2_dev, "device %s disconnected\n",
-                 video_device_node_name(dev->video_dev));
-       /* prevent more I/O from starting and stop any ongoing */
-       mutex_lock(&dev->io_mutex);
-       dev->status = STATUS_DISCONNECTED;
-       wake_up_interruptible(&dev->wait_data);
-       wake_up_interruptible(&dev->wait_buffer);
-       mutex_unlock(&dev->io_mutex);
-       v4l2_device_disconnect(&dev->v4l2_dev);
-       msleep(100);
-       flush_workqueue(dev->workqueue);
-       mutex_lock(&dev->io_mutex);
-       hdpvr_cancel_queue(dev);
-       mutex_unlock(&dev->io_mutex);
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-       i2c_del_adapter(&dev->i2c_adapter);
-#endif
-       video_unregister_device(dev->video_dev);
-       atomic_dec(&dev_nr);
-}
-
-
-static struct usb_driver hdpvr_usb_driver = {
-       .name =         "hdpvr",
-       .probe =        hdpvr_probe,
-       .disconnect =   hdpvr_disconnect,
-       .id_table =     hdpvr_table,
-};
-
-module_usb_driver(hdpvr_usb_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_VERSION("0.2.1");
-MODULE_AUTHOR("Janne Grunau");
-MODULE_DESCRIPTION("Hauppauge HD PVR driver");
diff --git a/drivers/media/video/hdpvr/hdpvr-i2c.c b/drivers/media/video/hdpvr/hdpvr-i2c.c
deleted file mode 100644 (file)
index 82e819f..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-
-/*
- * Hauppauge HD PVR USB driver
- *
- * Copyright (C) 2008      Janne Grunau (j@jannau.net)
- *
- * IR device registration code is
- * Copyright (C) 2010  Andy Walls <awalls@md.metrocast.net>
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation, version 2.
- *
- */
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-
-#include "hdpvr.h"
-
-#define CTRL_READ_REQUEST      0xb8
-#define CTRL_WRITE_REQUEST     0x38
-
-#define REQTYPE_I2C_READ       0xb1
-#define REQTYPE_I2C_WRITE      0xb0
-#define REQTYPE_I2C_WRITE_STATT        0xd0
-
-#define Z8F0811_IR_TX_I2C_ADDR 0x70
-#define Z8F0811_IR_RX_I2C_ADDR 0x71
-
-
-struct i2c_client *hdpvr_register_ir_tx_i2c(struct hdpvr_device *dev)
-{
-       struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data;
-       struct i2c_board_info hdpvr_ir_tx_i2c_board_info = {
-               I2C_BOARD_INFO("ir_tx_z8f0811_hdpvr", Z8F0811_IR_TX_I2C_ADDR),
-       };
-
-       init_data->name = "HD-PVR";
-       hdpvr_ir_tx_i2c_board_info.platform_data = init_data;
-
-       return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_tx_i2c_board_info);
-}
-
-struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev)
-{
-       struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data;
-       struct i2c_board_info hdpvr_ir_rx_i2c_board_info = {
-               I2C_BOARD_INFO("ir_rx_z8f0811_hdpvr", Z8F0811_IR_RX_I2C_ADDR),
-       };
-
-       /* Our default information for ir-kbd-i2c.c to use */
-       init_data->ir_codes = RC_MAP_HAUPPAUGE;
-       init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-       init_data->type = RC_TYPE_RC5;
-       init_data->name = "HD-PVR";
-       init_data->polling_interval = 405; /* ms, duplicated from Windows */
-       hdpvr_ir_rx_i2c_board_info.platform_data = init_data;
-
-       return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_rx_i2c_board_info);
-}
-
-static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus,
-                         unsigned char addr, char *wdata, int wlen,
-                         char *data, int len)
-{
-       int ret;
-
-       if ((len > sizeof(dev->i2c_buf)) || (wlen > sizeof(dev->i2c_buf)))
-               return -EINVAL;
-
-       if (wlen) {
-               memcpy(&dev->i2c_buf, wdata, wlen);
-               ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-                                     REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
-                                     (bus << 8) | addr, 0, &dev->i2c_buf,
-                                     wlen, 1000);
-               if (ret < 0)
-                       return ret;
-       }
-
-       ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-                             REQTYPE_I2C_READ, CTRL_READ_REQUEST,
-                             (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
-
-       if (ret == len) {
-               memcpy(data, &dev->i2c_buf, len);
-               ret = 0;
-       } else if (ret >= 0)
-               ret = -EIO;
-
-       return ret;
-}
-
-static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus,
-                          unsigned char addr, char *data, int len)
-{
-       int ret;
-
-       if (len > sizeof(dev->i2c_buf))
-               return -EINVAL;
-
-       memcpy(&dev->i2c_buf, data, len);
-       ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-                             REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
-                             (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
-
-       if (ret < 0)
-               return ret;
-
-       ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-                             REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST,
-                             0, 0, &dev->i2c_buf, 2, 1000);
-
-       if ((ret == 2) && (dev->i2c_buf[1] == (len - 1)))
-               ret = 0;
-       else if (ret >= 0)
-               ret = -EIO;
-
-       return ret;
-}
-
-static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs,
-                         int num)
-{
-       struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter);
-       int retval = 0, addr;
-
-       if (num <= 0)
-               return 0;
-
-       mutex_lock(&dev->i2c_mutex);
-
-       addr = msgs[0].addr << 1;
-
-       if (num == 1) {
-               if (msgs[0].flags & I2C_M_RD)
-                       retval = hdpvr_i2c_read(dev, 1, addr, NULL, 0,
-                                               msgs[0].buf, msgs[0].len);
-               else
-                       retval = hdpvr_i2c_write(dev, 1, addr, msgs[0].buf,
-                                                msgs[0].len);
-       } else if (num == 2) {
-               if (msgs[0].addr != msgs[1].addr) {
-                       v4l2_warn(&dev->v4l2_dev, "refusing 2-phase i2c xfer "
-                                 "with conflicting target addresses\n");
-                       retval = -EINVAL;
-                       goto out;
-               }
-
-               if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD)) {
-                       v4l2_warn(&dev->v4l2_dev, "refusing complex xfer with "
-                                 "r0=%d, r1=%d\n", msgs[0].flags & I2C_M_RD,
-                                 msgs[1].flags & I2C_M_RD);
-                       retval = -EINVAL;
-                       goto out;
-               }
-
-               /*
-                * Write followed by atomic read is the only complex xfer that
-                * we actually support here.
-                */
-               retval = hdpvr_i2c_read(dev, 1, addr, msgs[0].buf, msgs[0].len,
-                                       msgs[1].buf, msgs[1].len);
-       } else {
-               v4l2_warn(&dev->v4l2_dev, "refusing %d-phase i2c xfer\n", num);
-       }
-
-out:
-       mutex_unlock(&dev->i2c_mutex);
-
-       return retval ? retval : num;
-}
-
-static u32 hdpvr_functionality(struct i2c_adapter *adapter)
-{
-       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-static struct i2c_algorithm hdpvr_algo = {
-       .master_xfer   = hdpvr_transfer,
-       .functionality = hdpvr_functionality,
-};
-
-static struct i2c_adapter hdpvr_i2c_adapter_template = {
-       .name   = "Hauppage HD PVR I2C",
-       .owner  = THIS_MODULE,
-       .algo   = &hdpvr_algo,
-};
-
-static int hdpvr_activate_ir(struct hdpvr_device *dev)
-{
-       char buffer[2];
-
-       mutex_lock(&dev->i2c_mutex);
-
-       hdpvr_i2c_read(dev, 0, 0x54, NULL, 0, buffer, 1);
-
-       buffer[0] = 0;
-       buffer[1] = 0x8;
-       hdpvr_i2c_write(dev, 1, 0x54, buffer, 2);
-
-       buffer[1] = 0x18;
-       hdpvr_i2c_write(dev, 1, 0x54, buffer, 2);
-
-       mutex_unlock(&dev->i2c_mutex);
-
-       return 0;
-}
-
-int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
-{
-       int retval = -ENOMEM;
-
-       hdpvr_activate_ir(dev);
-
-       memcpy(&dev->i2c_adapter, &hdpvr_i2c_adapter_template,
-              sizeof(struct i2c_adapter));
-       dev->i2c_adapter.dev.parent = &dev->udev->dev;
-
-       i2c_set_adapdata(&dev->i2c_adapter, dev);
-
-       retval = i2c_add_adapter(&dev->i2c_adapter);
-
-       return retval;
-}
-
-#endif
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c
deleted file mode 100644 (file)
index 0e9e156..0000000
+++ /dev/null
@@ -1,1289 +0,0 @@
-/*
- * Hauppauge HD PVR USB driver - video 4 linux 2 interface
- *
- * Copyright (C) 2008      Janne Grunau (j@jannau.net)
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation, version 2.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/uaccess.h>
-#include <linux/usb.h>
-#include <linux/mutex.h>
-#include <linux/workqueue.h>
-
-#include <linux/videodev2.h>
-#include <media/v4l2-dev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include "hdpvr.h"
-
-#define BULK_URB_TIMEOUT   90 /* 0.09 seconds */
-
-#define print_buffer_status() { \
-               v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,       \
-                        "%s:%d buffer stat: %d free, %d proc\n",       \
-                        __func__, __LINE__,                            \
-                        list_size(&dev->free_buff_list),               \
-                        list_size(&dev->rec_buff_list)); }
-
-struct hdpvr_fh {
-       struct hdpvr_device     *dev;
-};
-
-static uint list_size(struct list_head *list)
-{
-       struct list_head *tmp;
-       uint count = 0;
-
-       list_for_each(tmp, list) {
-               count++;
-       }
-
-       return count;
-}
-
-/*=========================================================================*/
-/* urb callback */
-static void hdpvr_read_bulk_callback(struct urb *urb)
-{
-       struct hdpvr_buffer *buf = (struct hdpvr_buffer *)urb->context;
-       struct hdpvr_device *dev = buf->dev;
-
-       /* marking buffer as received and wake waiting */
-       buf->status = BUFSTAT_READY;
-       wake_up_interruptible(&dev->wait_data);
-}
-
-/*=========================================================================*/
-/* bufffer bits */
-
-/* function expects dev->io_mutex to be hold by caller */
-int hdpvr_cancel_queue(struct hdpvr_device *dev)
-{
-       struct hdpvr_buffer *buf;
-
-       list_for_each_entry(buf, &dev->rec_buff_list, buff_list) {
-               usb_kill_urb(buf->urb);
-               buf->status = BUFSTAT_AVAILABLE;
-       }
-
-       list_splice_init(&dev->rec_buff_list, dev->free_buff_list.prev);
-
-       return 0;
-}
-
-static int hdpvr_free_queue(struct list_head *q)
-{
-       struct list_head *tmp;
-       struct list_head *p;
-       struct hdpvr_buffer *buf;
-       struct urb *urb;
-
-       for (p = q->next; p != q;) {
-               buf = list_entry(p, struct hdpvr_buffer, buff_list);
-
-               urb = buf->urb;
-               usb_free_coherent(urb->dev, urb->transfer_buffer_length,
-                                 urb->transfer_buffer, urb->transfer_dma);
-               usb_free_urb(urb);
-               tmp = p->next;
-               list_del(p);
-               kfree(buf);
-               p = tmp;
-       }
-
-       return 0;
-}
-
-/* function expects dev->io_mutex to be hold by caller */
-int hdpvr_free_buffers(struct hdpvr_device *dev)
-{
-       hdpvr_cancel_queue(dev);
-
-       hdpvr_free_queue(&dev->free_buff_list);
-       hdpvr_free_queue(&dev->rec_buff_list);
-
-       return 0;
-}
-
-/* function expects dev->io_mutex to be hold by caller */
-int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count)
-{
-       uint i;
-       int retval = -ENOMEM;
-       u8 *mem;
-       struct hdpvr_buffer *buf;
-       struct urb *urb;
-
-       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                "allocating %u buffers\n", count);
-
-       for (i = 0; i < count; i++) {
-
-               buf = kzalloc(sizeof(struct hdpvr_buffer), GFP_KERNEL);
-               if (!buf) {
-                       v4l2_err(&dev->v4l2_dev, "cannot allocate buffer\n");
-                       goto exit;
-               }
-               buf->dev = dev;
-
-               urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (!urb) {
-                       v4l2_err(&dev->v4l2_dev, "cannot allocate urb\n");
-                       goto exit_urb;
-               }
-               buf->urb = urb;
-
-               mem = usb_alloc_coherent(dev->udev, dev->bulk_in_size, GFP_KERNEL,
-                                        &urb->transfer_dma);
-               if (!mem) {
-                       v4l2_err(&dev->v4l2_dev,
-                                "cannot allocate usb transfer buffer\n");
-                       goto exit_urb_buffer;
-               }
-
-               usb_fill_bulk_urb(buf->urb, dev->udev,
-                                 usb_rcvbulkpipe(dev->udev,
-                                                 dev->bulk_in_endpointAddr),
-                                 mem, dev->bulk_in_size,
-                                 hdpvr_read_bulk_callback, buf);
-
-               buf->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-               buf->status = BUFSTAT_AVAILABLE;
-               list_add_tail(&buf->buff_list, &dev->free_buff_list);
-       }
-       return 0;
-exit_urb_buffer:
-       usb_free_urb(urb);
-exit_urb:
-       kfree(buf);
-exit:
-       hdpvr_free_buffers(dev);
-       return retval;
-}
-
-static int hdpvr_submit_buffers(struct hdpvr_device *dev)
-{
-       struct hdpvr_buffer *buf;
-       struct urb *urb;
-       int ret = 0, err_count = 0;
-
-       mutex_lock(&dev->io_mutex);
-
-       while (dev->status == STATUS_STREAMING &&
-              !list_empty(&dev->free_buff_list)) {
-
-               buf = list_entry(dev->free_buff_list.next, struct hdpvr_buffer,
-                                buff_list);
-               if (buf->status != BUFSTAT_AVAILABLE) {
-                       v4l2_err(&dev->v4l2_dev,
-                                "buffer not marked as available\n");
-                       ret = -EFAULT;
-                       goto err;
-               }
-
-               urb = buf->urb;
-               urb->status = 0;
-               urb->actual_length = 0;
-               ret = usb_submit_urb(urb, GFP_KERNEL);
-               if (ret) {
-                       v4l2_err(&dev->v4l2_dev,
-                                "usb_submit_urb in %s returned %d\n",
-                                __func__, ret);
-                       if (++err_count > 2)
-                               break;
-                       continue;
-               }
-               buf->status = BUFSTAT_INPROGRESS;
-               list_move_tail(&buf->buff_list, &dev->rec_buff_list);
-       }
-err:
-       print_buffer_status();
-       mutex_unlock(&dev->io_mutex);
-       return ret;
-}
-
-static struct hdpvr_buffer *hdpvr_get_next_buffer(struct hdpvr_device *dev)
-{
-       struct hdpvr_buffer *buf;
-
-       mutex_lock(&dev->io_mutex);
-
-       if (list_empty(&dev->rec_buff_list)) {
-               mutex_unlock(&dev->io_mutex);
-               return NULL;
-       }
-
-       buf = list_entry(dev->rec_buff_list.next, struct hdpvr_buffer,
-                        buff_list);
-       mutex_unlock(&dev->io_mutex);
-
-       return buf;
-}
-
-static void hdpvr_transmit_buffers(struct work_struct *work)
-{
-       struct hdpvr_device *dev = container_of(work, struct hdpvr_device,
-                                               worker);
-
-       while (dev->status == STATUS_STREAMING) {
-
-               if (hdpvr_submit_buffers(dev)) {
-                       v4l2_err(&dev->v4l2_dev, "couldn't submit buffers\n");
-                       goto error;
-               }
-               if (wait_event_interruptible(dev->wait_buffer,
-                               !list_empty(&dev->free_buff_list) ||
-                                            dev->status != STATUS_STREAMING))
-                       goto error;
-       }
-
-       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                "transmit worker exited\n");
-       return;
-error:
-       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                "transmit buffers errored\n");
-       dev->status = STATUS_ERROR;
-}
-
-/* function expects dev->io_mutex to be hold by caller */
-static int hdpvr_start_streaming(struct hdpvr_device *dev)
-{
-       int ret;
-       struct hdpvr_video_info *vidinf;
-
-       if (dev->status == STATUS_STREAMING)
-               return 0;
-       else if (dev->status != STATUS_IDLE)
-               return -EAGAIN;
-
-       vidinf = get_video_info(dev);
-
-       if (vidinf) {
-               v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
-                        "video signal: %dx%d@%dhz\n", vidinf->width,
-                        vidinf->height, vidinf->fps);
-               kfree(vidinf);
-
-               /* start streaming 2 request */
-               ret = usb_control_msg(dev->udev,
-                                     usb_sndctrlpipe(dev->udev, 0),
-                                     0xb8, 0x38, 0x1, 0, NULL, 0, 8000);
-               v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
-                        "encoder start control request returned %d\n", ret);
-
-               hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00);
-
-               dev->status = STATUS_STREAMING;
-
-               INIT_WORK(&dev->worker, hdpvr_transmit_buffers);
-               queue_work(dev->workqueue, &dev->worker);
-
-               v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
-                        "streaming started\n");
-
-               return 0;
-       }
-       msleep(250);
-       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                "no video signal at input %d\n", dev->options.video_input);
-       return -EAGAIN;
-}
-
-
-/* function expects dev->io_mutex to be hold by caller */
-static int hdpvr_stop_streaming(struct hdpvr_device *dev)
-{
-       int actual_length;
-       uint c = 0;
-       u8 *buf;
-
-       if (dev->status == STATUS_IDLE)
-               return 0;
-       else if (dev->status != STATUS_STREAMING)
-               return -EAGAIN;
-
-       buf = kmalloc(dev->bulk_in_size, GFP_KERNEL);
-       if (!buf)
-               v4l2_err(&dev->v4l2_dev, "failed to allocate temporary buffer "
-                        "for emptying the internal device buffer. "
-                        "Next capture start will be slow\n");
-
-       dev->status = STATUS_SHUTTING_DOWN;
-       hdpvr_config_call(dev, CTRL_STOP_STREAMING_VALUE, 0x00);
-       mutex_unlock(&dev->io_mutex);
-
-       wake_up_interruptible(&dev->wait_buffer);
-       msleep(50);
-
-       flush_workqueue(dev->workqueue);
-
-       mutex_lock(&dev->io_mutex);
-       /* kill the still outstanding urbs */
-       hdpvr_cancel_queue(dev);
-
-       /* emptying the device buffer beforeshutting it down */
-       while (buf && ++c < 500 &&
-              !usb_bulk_msg(dev->udev,
-                            usb_rcvbulkpipe(dev->udev,
-                                            dev->bulk_in_endpointAddr),
-                            buf, dev->bulk_in_size, &actual_length,
-                            BULK_URB_TIMEOUT)) {
-               v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
-                        "%2d: got %d bytes\n", c, actual_length);
-       }
-       kfree(buf);
-       v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
-                "used %d urbs to empty device buffers\n", c-1);
-       msleep(10);
-
-       dev->status = STATUS_IDLE;
-
-       return 0;
-}
-
-
-/*=======================================================================*/
-/*
- * video 4 linux 2 file operations
- */
-
-static int hdpvr_open(struct file *file)
-{
-       struct hdpvr_device *dev;
-       struct hdpvr_fh *fh;
-       int retval = -ENOMEM;
-
-       dev = (struct hdpvr_device *)video_get_drvdata(video_devdata(file));
-       if (!dev) {
-               pr_err("open failing with with ENODEV\n");
-               retval = -ENODEV;
-               goto err;
-       }
-
-       fh = kzalloc(sizeof(struct hdpvr_fh), GFP_KERNEL);
-       if (!fh) {
-               v4l2_err(&dev->v4l2_dev, "Out of memory\n");
-               goto err;
-       }
-       /* lock the device to allow correctly handling errors
-        * in resumption */
-       mutex_lock(&dev->io_mutex);
-       dev->open_count++;
-       mutex_unlock(&dev->io_mutex);
-
-       fh->dev = dev;
-
-       /* save our object in the file's private structure */
-       file->private_data = fh;
-
-       retval = 0;
-err:
-       return retval;
-}
-
-static int hdpvr_release(struct file *file)
-{
-       struct hdpvr_fh         *fh  = file->private_data;
-       struct hdpvr_device     *dev = fh->dev;
-
-       if (!dev)
-               return -ENODEV;
-
-       mutex_lock(&dev->io_mutex);
-       if (!(--dev->open_count) && dev->status == STATUS_STREAMING)
-               hdpvr_stop_streaming(dev);
-
-       mutex_unlock(&dev->io_mutex);
-
-       return 0;
-}
-
-/*
- * hdpvr_v4l2_read()
- * will allocate buffers when called for the first time
- */
-static ssize_t hdpvr_read(struct file *file, char __user *buffer, size_t count,
-                         loff_t *pos)
-{
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
-       struct hdpvr_buffer *buf = NULL;
-       struct urb *urb;
-       unsigned int ret = 0;
-       int rem, cnt;
-
-       if (*pos)
-               return -ESPIPE;
-
-       if (!dev)
-               return -ENODEV;
-
-       mutex_lock(&dev->io_mutex);
-       if (dev->status == STATUS_IDLE) {
-               if (hdpvr_start_streaming(dev)) {
-                       v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                                "start_streaming failed\n");
-                       ret = -EIO;
-                       msleep(200);
-                       dev->status = STATUS_IDLE;
-                       mutex_unlock(&dev->io_mutex);
-                       goto err;
-               }
-               print_buffer_status();
-       }
-       mutex_unlock(&dev->io_mutex);
-
-       /* wait for the first buffer */
-       if (!(file->f_flags & O_NONBLOCK)) {
-               if (wait_event_interruptible(dev->wait_data,
-                                            hdpvr_get_next_buffer(dev)))
-                       return -ERESTARTSYS;
-       }
-
-       buf = hdpvr_get_next_buffer(dev);
-
-       while (count > 0 && buf) {
-
-               if (buf->status != BUFSTAT_READY &&
-                   dev->status != STATUS_DISCONNECTED) {
-                       /* return nonblocking */
-                       if (file->f_flags & O_NONBLOCK) {
-                               if (!ret)
-                                       ret = -EAGAIN;
-                               goto err;
-                       }
-
-                       if (wait_event_interruptible(dev->wait_data,
-                                             buf->status == BUFSTAT_READY)) {
-                               ret = -ERESTARTSYS;
-                               goto err;
-                       }
-               }
-
-               if (buf->status != BUFSTAT_READY)
-                       break;
-
-               /* set remaining bytes to copy */
-               urb = buf->urb;
-               rem = urb->actual_length - buf->pos;
-               cnt = rem > count ? count : rem;
-
-               if (copy_to_user(buffer, urb->transfer_buffer + buf->pos,
-                                cnt)) {
-                       v4l2_err(&dev->v4l2_dev, "read: copy_to_user failed\n");
-                       if (!ret)
-                               ret = -EFAULT;
-                       goto err;
-               }
-
-               buf->pos += cnt;
-               count -= cnt;
-               buffer += cnt;
-               ret += cnt;
-
-               /* finished, take next buffer */
-               if (buf->pos == urb->actual_length) {
-                       mutex_lock(&dev->io_mutex);
-                       buf->pos = 0;
-                       buf->status = BUFSTAT_AVAILABLE;
-
-                       list_move_tail(&buf->buff_list, &dev->free_buff_list);
-
-                       print_buffer_status();
-
-                       mutex_unlock(&dev->io_mutex);
-
-                       wake_up_interruptible(&dev->wait_buffer);
-
-                       buf = hdpvr_get_next_buffer(dev);
-               }
-       }
-err:
-       if (!ret && !buf)
-               ret = -EAGAIN;
-       return ret;
-}
-
-static unsigned int hdpvr_poll(struct file *filp, poll_table *wait)
-{
-       struct hdpvr_buffer *buf = NULL;
-       struct hdpvr_fh *fh = filp->private_data;
-       struct hdpvr_device *dev = fh->dev;
-       unsigned int mask = 0;
-
-       mutex_lock(&dev->io_mutex);
-
-       if (!video_is_registered(dev->video_dev)) {
-               mutex_unlock(&dev->io_mutex);
-               return -EIO;
-       }
-
-       if (dev->status == STATUS_IDLE) {
-               if (hdpvr_start_streaming(dev)) {
-                       v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
-                                "start_streaming failed\n");
-                       dev->status = STATUS_IDLE;
-               }
-
-               print_buffer_status();
-       }
-       mutex_unlock(&dev->io_mutex);
-
-       buf = hdpvr_get_next_buffer(dev);
-       /* only wait if no data is available */
-       if (!buf || buf->status != BUFSTAT_READY) {
-               poll_wait(filp, &dev->wait_data, wait);
-               buf = hdpvr_get_next_buffer(dev);
-       }
-       if (buf && buf->status == BUFSTAT_READY)
-               mask |= POLLIN | POLLRDNORM;
-
-       return mask;
-}
-
-
-static const struct v4l2_file_operations hdpvr_fops = {
-       .owner          = THIS_MODULE,
-       .open           = hdpvr_open,
-       .release        = hdpvr_release,
-       .read           = hdpvr_read,
-       .poll           = hdpvr_poll,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-/*=======================================================================*/
-/*
- * V4L2 ioctl handling
- */
-
-static int vidioc_querycap(struct file *file, void  *priv,
-                          struct v4l2_capability *cap)
-{
-       struct hdpvr_device *dev = video_drvdata(file);
-
-       strcpy(cap->driver, "hdpvr");
-       strcpy(cap->card, "Hauppauge HD PVR");
-       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
-       cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
-                               V4L2_CAP_AUDIO         |
-                               V4L2_CAP_READWRITE;
-       return 0;
-}
-
-static int vidioc_s_std(struct file *file, void *private_data,
-                       v4l2_std_id *std)
-{
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
-       u8 std_type = 1;
-
-       if (*std & (V4L2_STD_NTSC | V4L2_STD_PAL_60))
-               std_type = 0;
-
-       return hdpvr_config_call(dev, CTRL_VIDEO_STD_TYPE, std_type);
-}
-
-static const char *iname[] = {
-       [HDPVR_COMPONENT] = "Component",
-       [HDPVR_SVIDEO]    = "S-Video",
-       [HDPVR_COMPOSITE] = "Composite",
-};
-
-static int vidioc_enum_input(struct file *file, void *priv,
-                               struct v4l2_input *i)
-{
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
-       unsigned int n;
-
-       n = i->index;
-       if (n >= HDPVR_VIDEO_INPUTS)
-               return -EINVAL;
-
-       i->type = V4L2_INPUT_TYPE_CAMERA;
-
-       strncpy(i->name, iname[n], sizeof(i->name) - 1);
-       i->name[sizeof(i->name) - 1] = '\0';
-
-       i->audioset = 1<<HDPVR_RCA_FRONT | 1<<HDPVR_RCA_BACK | 1<<HDPVR_SPDIF;
-
-       i->std = dev->video_dev->tvnorms;
-
-       return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *private_data,
-                         unsigned int index)
-{
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
-       int retval;
-
-       if (index >= HDPVR_VIDEO_INPUTS)
-               return -EINVAL;
-
-       if (dev->status != STATUS_IDLE)
-               return -EAGAIN;
-
-       retval = hdpvr_config_call(dev, CTRL_VIDEO_INPUT_VALUE, index+1);
-       if (!retval)
-               dev->options.video_input = index;
-
-       return retval;
-}
-
-static int vidioc_g_input(struct file *file, void *private_data,
-                         unsigned int *index)
-{
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
-
-       *index = dev->options.video_input;
-       return 0;
-}
-
-
-static const char *audio_iname[] = {
-       [HDPVR_RCA_FRONT] = "RCA front",
-       [HDPVR_RCA_BACK]  = "RCA back",
-       [HDPVR_SPDIF]     = "SPDIF",
-};
-
-static int vidioc_enumaudio(struct file *file, void *priv,
-                               struct v4l2_audio *audio)
-{
-       unsigned int n;
-
-       n = audio->index;
-       if (n >= HDPVR_AUDIO_INPUTS)
-               return -EINVAL;
-
-       audio->capability = V4L2_AUDCAP_STEREO;
-
-       strncpy(audio->name, audio_iname[n], sizeof(audio->name) - 1);
-       audio->name[sizeof(audio->name) - 1] = '\0';
-
-       return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *private_data,
-                         struct v4l2_audio *audio)
-{
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
-       int retval;
-
-       if (audio->index >= HDPVR_AUDIO_INPUTS)
-               return -EINVAL;
-
-       if (dev->status != STATUS_IDLE)
-               return -EAGAIN;
-
-       retval = hdpvr_set_audio(dev, audio->index+1, dev->options.audio_codec);
-       if (!retval)
-               dev->options.audio_input = audio->index;
-
-       return retval;
-}
-
-static int vidioc_g_audio(struct file *file, void *private_data,
-                         struct v4l2_audio *audio)
-{
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
-
-       audio->index = dev->options.audio_input;
-       audio->capability = V4L2_AUDCAP_STEREO;
-       strncpy(audio->name, audio_iname[audio->index], sizeof(audio->name));
-       audio->name[sizeof(audio->name) - 1] = '\0';
-       return 0;
-}
-
-static const s32 supported_v4l2_ctrls[] = {
-       V4L2_CID_BRIGHTNESS,
-       V4L2_CID_CONTRAST,
-       V4L2_CID_SATURATION,
-       V4L2_CID_HUE,
-       V4L2_CID_SHARPNESS,
-       V4L2_CID_MPEG_AUDIO_ENCODING,
-       V4L2_CID_MPEG_VIDEO_ENCODING,
-       V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
-       V4L2_CID_MPEG_VIDEO_BITRATE,
-       V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
-};
-
-static int fill_queryctrl(struct hdpvr_options *opt, struct v4l2_queryctrl *qc,
-                         int ac3, int fw_ver)
-{
-       int err;
-
-       if (fw_ver > 0x15) {
-               switch (qc->id) {
-               case V4L2_CID_BRIGHTNESS:
-                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
-               case V4L2_CID_CONTRAST:
-                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x40);
-               case V4L2_CID_SATURATION:
-                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x40);
-               case V4L2_CID_HUE:
-                       return v4l2_ctrl_query_fill(qc, 0x0, 0x1e, 1, 0xf);
-               case V4L2_CID_SHARPNESS:
-                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
-               }
-       } else {
-               switch (qc->id) {
-               case V4L2_CID_BRIGHTNESS:
-                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x86);
-               case V4L2_CID_CONTRAST:
-                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
-               case V4L2_CID_SATURATION:
-                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
-               case V4L2_CID_HUE:
-                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
-               case V4L2_CID_SHARPNESS:
-                       return v4l2_ctrl_query_fill(qc, 0x0, 0xff, 1, 0x80);
-               }
-       }
-
-       switch (qc->id) {
-       case V4L2_CID_MPEG_AUDIO_ENCODING:
-               return v4l2_ctrl_query_fill(
-                       qc, V4L2_MPEG_AUDIO_ENCODING_AAC,
-                       ac3 ? V4L2_MPEG_AUDIO_ENCODING_AC3
-                       : V4L2_MPEG_AUDIO_ENCODING_AAC,
-                       1, V4L2_MPEG_AUDIO_ENCODING_AAC);
-       case V4L2_CID_MPEG_VIDEO_ENCODING:
-               return v4l2_ctrl_query_fill(
-                       qc, V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC,
-                       V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC, 1,
-                       V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC);
-
-/*     case V4L2_CID_MPEG_VIDEO_? maybe keyframe interval: */
-/*             return v4l2_ctrl_query_fill(qc, 0, 128, 128, 0); */
-       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-               return v4l2_ctrl_query_fill(
-                       qc, V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
-                       V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
-                       V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);
-
-       case V4L2_CID_MPEG_VIDEO_BITRATE:
-               return v4l2_ctrl_query_fill(qc, 1000000, 13500000, 100000,
-                                           6500000);
-       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
-               err = v4l2_ctrl_query_fill(qc, 1100000, 20200000, 100000,
-                                          9000000);
-               if (!err && opt->bitrate_mode == HDPVR_CONSTANT)
-                       qc->flags |= V4L2_CTRL_FLAG_INACTIVE;
-               return err;
-       default:
-               return -EINVAL;
-       }
-}
-
-static int vidioc_queryctrl(struct file *file, void *private_data,
-                           struct v4l2_queryctrl *qc)
-{
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
-       int i, next;
-       u32 id = qc->id;
-
-       memset(qc, 0, sizeof(*qc));
-
-       next = !!(id &  V4L2_CTRL_FLAG_NEXT_CTRL);
-       qc->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
-
-       for (i = 0; i < ARRAY_SIZE(supported_v4l2_ctrls); i++) {
-               if (next) {
-                       if (qc->id < supported_v4l2_ctrls[i])
-                               qc->id = supported_v4l2_ctrls[i];
-                       else
-                               continue;
-               }
-
-               if (qc->id == supported_v4l2_ctrls[i])
-                       return fill_queryctrl(&dev->options, qc,
-                                             dev->flags & HDPVR_FLAG_AC3_CAP,
-                                             dev->fw_ver);
-
-               if (qc->id < supported_v4l2_ctrls[i])
-                       break;
-       }
-
-       return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *private_data,
-                        struct v4l2_control *ctrl)
-{
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               ctrl->value = dev->options.brightness;
-               break;
-       case V4L2_CID_CONTRAST:
-               ctrl->value = dev->options.contrast;
-               break;
-       case V4L2_CID_SATURATION:
-               ctrl->value = dev->options.saturation;
-               break;
-       case V4L2_CID_HUE:
-               ctrl->value = dev->options.hue;
-               break;
-       case V4L2_CID_SHARPNESS:
-               ctrl->value = dev->options.sharpness;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *private_data,
-                        struct v4l2_control *ctrl)
-{
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
-       int retval;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               retval = hdpvr_config_call(dev, CTRL_BRIGHTNESS, ctrl->value);
-               if (!retval)
-                       dev->options.brightness = ctrl->value;
-               break;
-       case V4L2_CID_CONTRAST:
-               retval = hdpvr_config_call(dev, CTRL_CONTRAST, ctrl->value);
-               if (!retval)
-                       dev->options.contrast = ctrl->value;
-               break;
-       case V4L2_CID_SATURATION:
-               retval = hdpvr_config_call(dev, CTRL_SATURATION, ctrl->value);
-               if (!retval)
-                       dev->options.saturation = ctrl->value;
-               break;
-       case V4L2_CID_HUE:
-               retval = hdpvr_config_call(dev, CTRL_HUE, ctrl->value);
-               if (!retval)
-                       dev->options.hue = ctrl->value;
-               break;
-       case V4L2_CID_SHARPNESS:
-               retval = hdpvr_config_call(dev, CTRL_SHARPNESS, ctrl->value);
-               if (!retval)
-                       dev->options.sharpness = ctrl->value;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return retval;
-}
-
-
-static int hdpvr_get_ctrl(struct hdpvr_options *opt,
-                         struct v4l2_ext_control *ctrl)
-{
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_AUDIO_ENCODING:
-               ctrl->value = opt->audio_codec;
-               break;
-       case V4L2_CID_MPEG_VIDEO_ENCODING:
-               ctrl->value = V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC;
-               break;
-/*     case V4L2_CID_MPEG_VIDEO_B_FRAMES: */
-/*             ctrl->value = (opt->gop_mode & 0x2) ? 0 : 128; */
-/*             break; */
-       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-               ctrl->value = opt->bitrate_mode == HDPVR_CONSTANT
-                       ? V4L2_MPEG_VIDEO_BITRATE_MODE_CBR
-                       : V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE:
-               ctrl->value = opt->bitrate * 100000;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
-               ctrl->value = opt->peak_bitrate * 100000;
-               break;
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               ctrl->value = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int vidioc_g_ext_ctrls(struct file *file, void *priv,
-                             struct v4l2_ext_controls *ctrls)
-{
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
-       int i, err = 0;
-
-       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
-               for (i = 0; i < ctrls->count; i++) {
-                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
-                       err = hdpvr_get_ctrl(&dev->options, ctrl);
-                       if (err) {
-                               ctrls->error_idx = i;
-                               break;
-                       }
-               }
-               return err;
-
-       }
-
-       return -EINVAL;
-}
-
-
-static int hdpvr_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
-{
-       int ret = -EINVAL;
-
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_AUDIO_ENCODING:
-               if (ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AAC ||
-                   (ac3 && ctrl->value == V4L2_MPEG_AUDIO_ENCODING_AC3))
-                       ret = 0;
-               break;
-       case V4L2_CID_MPEG_VIDEO_ENCODING:
-               if (ctrl->value == V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC)
-                       ret = 0;
-               break;
-/*     case V4L2_CID_MPEG_VIDEO_B_FRAMES: */
-/*             if (ctrl->value == 0 || ctrl->value == 128) */
-/*                     ret = 0; */
-/*             break; */
-       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-               if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR ||
-                   ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR)
-                       ret = 0;
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE:
-       {
-               uint bitrate = ctrl->value / 100000;
-               if (bitrate >= 10 && bitrate <= 135)
-                       ret = 0;
-               break;
-       }
-       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
-       {
-               uint peak_bitrate = ctrl->value / 100000;
-               if (peak_bitrate >= 10 && peak_bitrate <= 202)
-                       ret = 0;
-               break;
-       }
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               if (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS)
-                       ret = 0;
-               break;
-       default:
-               return -EINVAL;
-       }
-       return ret;
-}
-
-static int vidioc_try_ext_ctrls(struct file *file, void *priv,
-                               struct v4l2_ext_controls *ctrls)
-{
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
-       int i, err = 0;
-
-       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
-               for (i = 0; i < ctrls->count; i++) {
-                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
-                       err = hdpvr_try_ctrl(ctrl,
-                                            dev->flags & HDPVR_FLAG_AC3_CAP);
-                       if (err) {
-                               ctrls->error_idx = i;
-                               break;
-                       }
-               }
-               return err;
-       }
-
-       return -EINVAL;
-}
-
-
-static int hdpvr_set_ctrl(struct hdpvr_device *dev,
-                         struct v4l2_ext_control *ctrl)
-{
-       struct hdpvr_options *opt = &dev->options;
-       int ret = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_MPEG_AUDIO_ENCODING:
-               if (dev->flags & HDPVR_FLAG_AC3_CAP) {
-                       opt->audio_codec = ctrl->value;
-                       ret = hdpvr_set_audio(dev, opt->audio_input,
-                                             opt->audio_codec);
-               }
-               break;
-       case V4L2_CID_MPEG_VIDEO_ENCODING:
-               break;
-/*     case V4L2_CID_MPEG_VIDEO_B_FRAMES: */
-/*             if (ctrl->value == 0 && !(opt->gop_mode & 0x2)) { */
-/*                     opt->gop_mode |= 0x2; */
-/*                     hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */
-/*                                       opt->gop_mode); */
-/*             } */
-/*             if (ctrl->value == 128 && opt->gop_mode & 0x2) { */
-/*                     opt->gop_mode &= ~0x2; */
-/*                     hdpvr_config_call(dev, CTRL_GOP_MODE_VALUE, */
-/*                                       opt->gop_mode); */
-/*             } */
-/*             break; */
-       case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
-               if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR &&
-                   opt->bitrate_mode != HDPVR_CONSTANT) {
-                       opt->bitrate_mode = HDPVR_CONSTANT;
-                       hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE,
-                                         opt->bitrate_mode);
-               }
-               if (ctrl->value == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
-                   opt->bitrate_mode == HDPVR_CONSTANT) {
-                       opt->bitrate_mode = HDPVR_VARIABLE_AVERAGE;
-                       hdpvr_config_call(dev, CTRL_BITRATE_MODE_VALUE,
-                                         opt->bitrate_mode);
-               }
-               break;
-       case V4L2_CID_MPEG_VIDEO_BITRATE: {
-               uint bitrate = ctrl->value / 100000;
-
-               opt->bitrate = bitrate;
-               if (bitrate >= opt->peak_bitrate)
-                       opt->peak_bitrate = bitrate+1;
-
-               hdpvr_set_bitrate(dev);
-               break;
-       }
-       case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: {
-               uint peak_bitrate = ctrl->value / 100000;
-
-               if (opt->bitrate_mode == HDPVR_CONSTANT)
-                       break;
-
-               if (opt->bitrate < peak_bitrate) {
-                       opt->peak_bitrate = peak_bitrate;
-                       hdpvr_set_bitrate(dev);
-               } else
-                       ret = -EINVAL;
-               break;
-       }
-       case V4L2_CID_MPEG_STREAM_TYPE:
-               break;
-       default:
-               return -EINVAL;
-       }
-       return ret;
-}
-
-static int vidioc_s_ext_ctrls(struct file *file, void *priv,
-                             struct v4l2_ext_controls *ctrls)
-{
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
-       int i, err = 0;
-
-       if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
-               for (i = 0; i < ctrls->count; i++) {
-                       struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
-                       err = hdpvr_try_ctrl(ctrl,
-                                            dev->flags & HDPVR_FLAG_AC3_CAP);
-                       if (err) {
-                               ctrls->error_idx = i;
-                               break;
-                       }
-                       err = hdpvr_set_ctrl(dev, ctrl);
-                       if (err) {
-                               ctrls->error_idx = i;
-                               break;
-                       }
-               }
-               return err;
-
-       }
-
-       return -EINVAL;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void *private_data,
-                                   struct v4l2_fmtdesc *f)
-{
-
-       if (f->index != 0 || f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       f->flags = V4L2_FMT_FLAG_COMPRESSED;
-       strncpy(f->description, "MPEG2-TS with AVC/AAC streams", 32);
-       f->pixelformat = V4L2_PIX_FMT_MPEG;
-
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *private_data,
-                               struct v4l2_format *f)
-{
-       struct hdpvr_fh *fh = file->private_data;
-       struct hdpvr_device *dev = fh->dev;
-       struct hdpvr_video_info *vid_info;
-
-       if (!dev)
-               return -ENODEV;
-
-       vid_info = get_video_info(dev);
-       if (!vid_info)
-               return -EFAULT;
-
-       f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
-       f->fmt.pix.width        = vid_info->width;
-       f->fmt.pix.height       = vid_info->height;
-       f->fmt.pix.sizeimage    = dev->bulk_in_size;
-       f->fmt.pix.colorspace   = 0;
-       f->fmt.pix.bytesperline = 0;
-       f->fmt.pix.field        = V4L2_FIELD_ANY;
-
-       kfree(vid_info);
-       return 0;
-}
-
-static int vidioc_encoder_cmd(struct file *filp, void *priv,
-                              struct v4l2_encoder_cmd *a)
-{
-       struct hdpvr_fh *fh = filp->private_data;
-       struct hdpvr_device *dev = fh->dev;
-       int res;
-
-       mutex_lock(&dev->io_mutex);
-
-       memset(&a->raw, 0, sizeof(a->raw));
-       switch (a->cmd) {
-       case V4L2_ENC_CMD_START:
-               a->flags = 0;
-               res = hdpvr_start_streaming(dev);
-               break;
-       case V4L2_ENC_CMD_STOP:
-               res = hdpvr_stop_streaming(dev);
-               break;
-       default:
-               v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev,
-                        "Unsupported encoder cmd %d\n", a->cmd);
-               res = -EINVAL;
-       }
-       mutex_unlock(&dev->io_mutex);
-       return res;
-}
-
-static int vidioc_try_encoder_cmd(struct file *filp, void *priv,
-                                       struct v4l2_encoder_cmd *a)
-{
-       switch (a->cmd) {
-       case V4L2_ENC_CMD_START:
-       case V4L2_ENC_CMD_STOP:
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-static const struct v4l2_ioctl_ops hdpvr_ioctl_ops = {
-       .vidioc_querycap        = vidioc_querycap,
-       .vidioc_s_std           = vidioc_s_std,
-       .vidioc_enum_input      = vidioc_enum_input,
-       .vidioc_g_input         = vidioc_g_input,
-       .vidioc_s_input         = vidioc_s_input,
-       .vidioc_enumaudio       = vidioc_enumaudio,
-       .vidioc_g_audio         = vidioc_g_audio,
-       .vidioc_s_audio         = vidioc_s_audio,
-       .vidioc_queryctrl       = vidioc_queryctrl,
-       .vidioc_g_ctrl          = vidioc_g_ctrl,
-       .vidioc_s_ctrl          = vidioc_s_ctrl,
-       .vidioc_g_ext_ctrls     = vidioc_g_ext_ctrls,
-       .vidioc_s_ext_ctrls     = vidioc_s_ext_ctrls,
-       .vidioc_try_ext_ctrls   = vidioc_try_ext_ctrls,
-       .vidioc_enum_fmt_vid_cap        = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap           = vidioc_g_fmt_vid_cap,
-       .vidioc_encoder_cmd     = vidioc_encoder_cmd,
-       .vidioc_try_encoder_cmd = vidioc_try_encoder_cmd,
-};
-
-static void hdpvr_device_release(struct video_device *vdev)
-{
-       struct hdpvr_device *dev = video_get_drvdata(vdev);
-
-       hdpvr_delete(dev);
-       mutex_lock(&dev->io_mutex);
-       destroy_workqueue(dev->workqueue);
-       mutex_unlock(&dev->io_mutex);
-
-       v4l2_device_unregister(&dev->v4l2_dev);
-
-       /* deregister I2C adapter */
-#if defined(CONFIG_I2C) || (CONFIG_I2C_MODULE)
-       mutex_lock(&dev->i2c_mutex);
-       i2c_del_adapter(&dev->i2c_adapter);
-       mutex_unlock(&dev->i2c_mutex);
-#endif /* CONFIG_I2C */
-
-       kfree(dev->usbc_buf);
-       kfree(dev);
-}
-
-static const struct video_device hdpvr_video_template = {
-/*     .type                   = VFL_TYPE_GRABBER, */
-/*     .type2                  = VID_TYPE_CAPTURE | VID_TYPE_MPEG_ENCODER, */
-       .fops                   = &hdpvr_fops,
-       .release                = hdpvr_device_release,
-       .ioctl_ops              = &hdpvr_ioctl_ops,
-       .tvnorms                =
-               V4L2_STD_NTSC  | V4L2_STD_SECAM | V4L2_STD_PAL_B |
-               V4L2_STD_PAL_G | V4L2_STD_PAL_H | V4L2_STD_PAL_I |
-               V4L2_STD_PAL_D | V4L2_STD_PAL_M | V4L2_STD_PAL_N |
-               V4L2_STD_PAL_60,
-       .current_norm           = V4L2_STD_NTSC | V4L2_STD_PAL_M |
-               V4L2_STD_PAL_60,
-};
-
-int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
-                           int devnum)
-{
-       /* setup and register video device */
-       dev->video_dev = video_device_alloc();
-       if (!dev->video_dev) {
-               v4l2_err(&dev->v4l2_dev, "video_device_alloc() failed\n");
-               goto error;
-       }
-
-       *(dev->video_dev) = hdpvr_video_template;
-       strcpy(dev->video_dev->name, "Hauppauge HD PVR");
-       dev->video_dev->parent = parent;
-       video_set_drvdata(dev->video_dev, dev);
-
-       if (video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum)) {
-               v4l2_err(&dev->v4l2_dev, "video_device registration failed\n");
-               goto error;
-       }
-
-       return 0;
-error:
-       return -ENOMEM;
-}
diff --git a/drivers/media/video/hdpvr/hdpvr.h b/drivers/media/video/hdpvr/hdpvr.h
deleted file mode 100644 (file)
index fea3c69..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Hauppauge HD PVR USB driver
- *
- * Copyright (C) 2008      Janne Grunau (j@jannau.net)
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation, version 2.
- *
- */
-
-#include <linux/usb.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <linux/workqueue.h>
-#include <linux/videodev2.h>
-
-#include <media/v4l2-device.h>
-#include <media/ir-kbd-i2c.h>
-
-#define HDPVR_MAX 8
-#define HDPVR_I2C_MAX_SIZE 128
-
-/* Define these values to match your devices */
-#define HD_PVR_VENDOR_ID       0x2040
-#define HD_PVR_PRODUCT_ID      0x4900
-#define HD_PVR_PRODUCT_ID1     0x4901
-#define HD_PVR_PRODUCT_ID2     0x4902
-#define HD_PVR_PRODUCT_ID4     0x4903
-#define HD_PVR_PRODUCT_ID3     0x4982
-
-#define UNSET    (-1U)
-
-#define NUM_BUFFERS 64
-
-#define HDPVR_FIRMWARE_VERSION         0x08
-#define HDPVR_FIRMWARE_VERSION_AC3     0x0d
-#define HDPVR_FIRMWARE_VERSION_0X12    0x12
-#define HDPVR_FIRMWARE_VERSION_0X15    0x15
-
-/* #define HDPVR_DEBUG */
-
-extern int hdpvr_debug;
-
-#define MSG_INFO       1
-#define MSG_BUFFER     2
-
-struct hdpvr_options {
-       u8      video_std;
-       u8      video_input;
-       u8      audio_input;
-       u8      bitrate;        /* in 100kbps */
-       u8      peak_bitrate;   /* in 100kbps */
-       u8      bitrate_mode;
-       u8      gop_mode;
-       enum v4l2_mpeg_audio_encoding   audio_codec;
-       u8      brightness;
-       u8      contrast;
-       u8      hue;
-       u8      saturation;
-       u8      sharpness;
-};
-
-/* Structure to hold all of our device specific stuff */
-struct hdpvr_device {
-       /* the v4l device for this device */
-       struct video_device     *video_dev;
-       /* the usb device for this device */
-       struct usb_device       *udev;
-       /* v4l2-device unused */
-       struct v4l2_device      v4l2_dev;
-
-       /* the max packet size of the bulk endpoint */
-       size_t                  bulk_in_size;
-       /* the address of the bulk in endpoint */
-       __u8                    bulk_in_endpointAddr;
-
-       /* holds the current device status */
-       __u8                    status;
-       /* count the number of openers */
-       uint                    open_count;
-
-       /* holds the cureent set options */
-       struct hdpvr_options    options;
-
-       uint                    flags;
-
-       /* synchronize I/O */
-       struct mutex            io_mutex;
-       /* available buffers */
-       struct list_head        free_buff_list;
-       /* in progress buffers */
-       struct list_head        rec_buff_list;
-       /* waitqueue for buffers */
-       wait_queue_head_t       wait_buffer;
-       /* waitqueue for data */
-       wait_queue_head_t       wait_data;
-       /**/
-       struct workqueue_struct *workqueue;
-       /**/
-       struct work_struct      worker;
-
-       /* I2C adapter */
-       struct i2c_adapter      i2c_adapter;
-       /* I2C lock */
-       struct mutex            i2c_mutex;
-       /* I2C message buffer space */
-       char                    i2c_buf[HDPVR_I2C_MAX_SIZE];
-
-       /* For passing data to ir-kbd-i2c */
-       struct IR_i2c_init_data ir_i2c_init_data;
-
-       /* usb control transfer buffer and lock */
-       struct mutex            usbc_mutex;
-       u8                      *usbc_buf;
-       u8                      fw_ver;
-};
-
-static inline struct hdpvr_device *to_hdpvr_dev(struct v4l2_device *v4l2_dev)
-{
-       return container_of(v4l2_dev, struct hdpvr_device, v4l2_dev);
-}
-
-
-/* buffer one bulk urb of data */
-struct hdpvr_buffer {
-       struct list_head        buff_list;
-
-       struct urb              *urb;
-
-       struct hdpvr_device     *dev;
-
-       uint                    pos;
-
-       __u8                    status;
-};
-
-/* */
-
-struct hdpvr_video_info {
-       u16     width;
-       u16     height;
-       u8      fps;
-};
-
-enum {
-       STATUS_UNINITIALIZED    = 0,
-       STATUS_IDLE,
-       STATUS_STARTING,
-       STATUS_SHUTTING_DOWN,
-       STATUS_STREAMING,
-       STATUS_ERROR,
-       STATUS_DISCONNECTED,
-};
-
-enum {
-       HDPVR_FLAG_AC3_CAP = 1,
-};
-
-enum {
-       BUFSTAT_UNINITIALIZED = 0,
-       BUFSTAT_AVAILABLE,
-       BUFSTAT_INPROGRESS,
-       BUFSTAT_READY,
-};
-
-#define CTRL_START_STREAMING_VALUE     0x0700
-#define CTRL_STOP_STREAMING_VALUE      0x0800
-#define CTRL_BITRATE_VALUE             0x1000
-#define CTRL_BITRATE_MODE_VALUE                0x1200
-#define CTRL_GOP_MODE_VALUE            0x1300
-#define CTRL_VIDEO_INPUT_VALUE         0x1500
-#define CTRL_VIDEO_STD_TYPE            0x1700
-#define CTRL_AUDIO_INPUT_VALUE         0x2500
-#define CTRL_BRIGHTNESS                        0x2900
-#define CTRL_CONTRAST                  0x2a00
-#define CTRL_HUE                       0x2b00
-#define CTRL_SATURATION                        0x2c00
-#define CTRL_SHARPNESS                 0x2d00
-#define CTRL_LOW_PASS_FILTER_VALUE     0x3100
-
-#define CTRL_DEFAULT_INDEX             0x0003
-
-
-       /* :0 s 38 01 1000 0003 0004 4 = 0a00ca00
-        * BITRATE SETTING
-        *   1st and 2nd byte (little endian): average bitrate in 100 000 bit/s
-        *                                     min: 1 mbit/s, max: 13.5 mbit/s
-        *   3rd and 4th byte (little endian): peak bitrate in 100 000 bit/s
-        *                                     min: average + 100kbit/s,
-        *                                      max: 20.2 mbit/s
-        */
-
-       /* :0 s 38 01 1200 0003 0001 1 = 02
-        * BIT RATE MODE
-        *  constant = 1, variable (peak) = 2, variable (average) = 3
-        */
-
-       /* :0 s 38 01 1300 0003 0001 1 = 03
-        * GOP MODE (2 bit)
-        *    low bit 0/1: advanced/simple GOP
-        *   high bit 0/1: IDR(4/32/128) / no IDR (4/32/0)
-        */
-
-       /* :0 s 38 01 1700 0003 0001 1 = 00
-        * VIDEO STANDARD or FREQUNCY 0 = 60hz, 1 = 50hz
-        */
-
-       /* :0 s 38 01 3100 0003 0004 4 = 03030000
-        * FILTER CONTROL
-        *   1st byte luma low pass filter strength,
-        *   2nd byte chroma low pass filter strength,
-        *   3rd byte MF enable chroma, min=0, max=1
-        *   4th byte n
-        */
-
-
-       /* :0 s 38 b9 0001 0000 0000 0 */
-
-
-
-/* :0 s 38 d3 0000 0000 0001 1 = 00 */
-/*             ret = usb_control_msg(dev->udev, */
-/*                                   usb_sndctrlpipe(dev->udev, 0), */
-/*                                   0xd3, 0x38, */
-/*                                   0, 0, */
-/*                                   "\0", 1, */
-/*                                   1000); */
-
-/*             info("control request returned %d", ret); */
-/*             msleep(5000); */
-
-
-       /* :0 s b8 81 1400 0003 0005 5 <
-        * :0 0 5 = d0024002 19
-        * QUERY FRAME SIZE AND RATE
-        *   1st and 2nd byte (little endian): horizontal resolution
-        *   3rd and 4th byte (little endian): vertical resolution
-        *   5th byte: frame rate
-        */
-
-       /* :0 s b8 81 1800 0003 0003 3 <
-        * :0 0 3 = 030104
-        * QUERY SIGNAL AND DETECTED LINES, maybe INPUT
-        */
-
-enum hdpvr_video_std {
-       HDPVR_60HZ = 0,
-       HDPVR_50HZ,
-};
-
-enum hdpvr_video_input {
-       HDPVR_COMPONENT = 0,
-       HDPVR_SVIDEO,
-       HDPVR_COMPOSITE,
-       HDPVR_VIDEO_INPUTS
-};
-
-enum hdpvr_audio_inputs {
-       HDPVR_RCA_BACK = 0,
-       HDPVR_RCA_FRONT,
-       HDPVR_SPDIF,
-       HDPVR_AUDIO_INPUTS
-};
-
-enum hdpvr_bitrate_mode {
-       HDPVR_CONSTANT = 1,
-       HDPVR_VARIABLE_PEAK,
-       HDPVR_VARIABLE_AVERAGE,
-};
-
-enum hdpvr_gop_mode {
-       HDPVR_ADVANCED_IDR_GOP = 0,
-       HDPVR_SIMPLE_IDR_GOP,
-       HDPVR_ADVANCED_NOIDR_GOP,
-       HDPVR_SIMPLE_NOIDR_GOP,
-};
-
-void hdpvr_delete(struct hdpvr_device *dev);
-
-/*========================================================================*/
-/* hardware control functions */
-int hdpvr_set_options(struct hdpvr_device *dev);
-
-int hdpvr_set_bitrate(struct hdpvr_device *dev);
-
-int hdpvr_set_audio(struct hdpvr_device *dev, u8 input,
-                   enum v4l2_mpeg_audio_encoding codec);
-
-int hdpvr_config_call(struct hdpvr_device *dev, uint value,
-                     unsigned char valbuf);
-
-struct hdpvr_video_info *get_video_info(struct hdpvr_device *dev);
-
-/* :0 s b8 81 1800 0003 0003 3 < */
-/* :0 0 3 = 0301ff */
-int get_input_lines_info(struct hdpvr_device *dev);
-
-
-/*========================================================================*/
-/* v4l2 registration */
-int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
-                           int devnumber);
-
-int hdpvr_cancel_queue(struct hdpvr_device *dev);
-
-/*========================================================================*/
-/* i2c adapter registration */
-int hdpvr_register_i2c_adapter(struct hdpvr_device *dev);
-
-struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev);
-struct i2c_client *hdpvr_register_ir_tx_i2c(struct hdpvr_device *dev);
-
-/*========================================================================*/
-/* buffer management */
-int hdpvr_free_buffers(struct hdpvr_device *dev);
-int hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count);
diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig
deleted file mode 100644 (file)
index 25e412e..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-config VIDEO_PVRUSB2
-       tristate "Hauppauge WinTV-PVR USB2 support"
-       depends on VIDEO_V4L2 && I2C
-       select VIDEO_TUNER
-       select VIDEO_TVEEPROM
-       select VIDEO_CX2341X
-       select VIDEO_SAA711X
-       select VIDEO_CX25840
-       select VIDEO_MSP3400
-       select VIDEO_WM8775
-       select VIDEO_CS53L32A
-       ---help---
-         This is a video4linux driver for Conexant 23416 based
-         usb2 personal video recorder devices.
-
-         To compile this driver as a module, choose M here: the
-         module will be called pvrusb2
-
-config VIDEO_PVRUSB2_SYSFS
-       bool "pvrusb2 sysfs support (EXPERIMENTAL)"
-       default y
-       depends on VIDEO_PVRUSB2 && SYSFS && EXPERIMENTAL
-       ---help---
-         This option enables the operation of a sysfs based
-         interface for query and control of the pvrusb2 driver.
-
-         This is not generally needed for v4l applications,
-         although certain applications are optimized to take
-         advantage of this feature.
-
-         If you are in doubt, say Y.
-
-         Note: This feature is experimental and subject to change.
-
-config VIDEO_PVRUSB2_DVB
-       bool "pvrusb2 ATSC/DVB support (EXPERIMENTAL)"
-       default y
-       depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL
-       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select DVB_S5H1409 if !DVB_FE_CUSTOMISE
-       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10048 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
-       ---help---
-
-         This option enables a DVB interface for the pvrusb2 driver.
-         If your device does not support digital television, this
-         feature will have no affect on the driver's operation.
-
-         If you are in doubt, say Y.
-
-config VIDEO_PVRUSB2_DEBUGIFC
-       bool "pvrusb2 debug interface"
-       depends on VIDEO_PVRUSB2_SYSFS
-       ---help---
-         This option enables the inclusion of a debug interface
-         in the pvrusb2 driver, hosted through sysfs.
-
-         You do not need to select this option unless you plan
-         on debugging the driver or performing a manual firmware
-         extraction.
-
-         If you are in doubt, say N.
diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile
deleted file mode 100644 (file)
index bc716db..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o
-obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
-obj-pvrusb2-dvb-$(CONFIG_VIDEO_PVRUSB2_DVB) := pvrusb2-dvb.o
-
-pvrusb2-objs   := pvrusb2-i2c-core.o \
-                  pvrusb2-audio.o \
-                  pvrusb2-encoder.o pvrusb2-video-v4l.o \
-                  pvrusb2-eeprom.o \
-                  pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \
-                  pvrusb2-ctrl.o pvrusb2-std.o pvrusb2-devattr.o \
-                  pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
-                  pvrusb2-cx2584x-v4l.o pvrusb2-wm8775.o \
-                  pvrusb2-cs53l32a.o \
-                  $(obj-pvrusb2-dvb-y) \
-                  $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
-
-obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
-
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/tuners
-ccflags-y += -Idrivers/media/dvb-core
-ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c
deleted file mode 100644 (file)
index cc06d5e..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include "pvrusb2-audio.h"
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-#include <linux/videodev2.h>
-#include <media/msp3400.h>
-#include <media/v4l2-common.h>
-
-
-struct routing_scheme {
-       const int *def;
-       unsigned int cnt;
-};
-
-static const int routing_scheme0[] = {
-       [PVR2_CVAL_INPUT_TV]        = MSP_INPUT_DEFAULT,
-       [PVR2_CVAL_INPUT_RADIO]     = MSP_INPUT(MSP_IN_SCART2,
-                                               MSP_IN_TUNER1,
-                                               MSP_DSP_IN_SCART,
-                                               MSP_DSP_IN_SCART),
-       [PVR2_CVAL_INPUT_COMPOSITE] = MSP_INPUT(MSP_IN_SCART1,
-                                               MSP_IN_TUNER1,
-                                               MSP_DSP_IN_SCART,
-                                               MSP_DSP_IN_SCART),
-       [PVR2_CVAL_INPUT_SVIDEO]    = MSP_INPUT(MSP_IN_SCART1,
-                                               MSP_IN_TUNER1,
-                                               MSP_DSP_IN_SCART,
-                                               MSP_DSP_IN_SCART),
-};
-
-static const struct routing_scheme routing_def0 = {
-       .def = routing_scheme0,
-       .cnt = ARRAY_SIZE(routing_scheme0),
-};
-
-static const struct routing_scheme *routing_schemes[] = {
-       [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
-};
-
-void pvr2_msp3400_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
-{
-       if (hdw->input_dirty || hdw->force_dirty) {
-               const struct routing_scheme *sp;
-               unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
-               u32 input;
-
-               pvr2_trace(PVR2_TRACE_CHIPS, "subdev msp3400 v4l2 set_stereo");
-               sp = (sid < ARRAY_SIZE(routing_schemes)) ?
-                       routing_schemes[sid] : NULL;
-
-               if ((sp != NULL) &&
-                   (hdw->input_val >= 0) &&
-                   (hdw->input_val < sp->cnt)) {
-                       input = sp->def[hdw->input_val];
-               } else {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "*** WARNING *** subdev msp3400 set_input:"
-                                  " Invalid routing scheme (%u)"
-                                  " and/or input (%d)",
-                                  sid, hdw->input_val);
-                       return;
-               }
-               sd->ops->audio->s_routing(sd, input,
-                       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/video/pvrusb2/pvrusb2-audio.h b/drivers/media/video/pvrusb2/pvrusb2-audio.h
deleted file mode 100644 (file)
index e3e63d7..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef __PVRUSB2_AUDIO_H
-#define __PVRUSB2_AUDIO_H
-
-#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/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c
deleted file mode 100644 (file)
index 7c19ff7..0000000
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include "pvrusb2-context.h"
-#include "pvrusb2-io.h"
-#include "pvrusb2-ioread.h"
-#include "pvrusb2-hdw.h"
-#include "pvrusb2-debug.h"
-#include <linux/wait.h>
-#include <linux/kthread.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-
-static struct pvr2_context *pvr2_context_exist_first;
-static struct pvr2_context *pvr2_context_exist_last;
-static struct pvr2_context *pvr2_context_notify_first;
-static struct pvr2_context *pvr2_context_notify_last;
-static DEFINE_MUTEX(pvr2_context_mutex);
-static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_sync_data);
-static DECLARE_WAIT_QUEUE_HEAD(pvr2_context_cleanup_data);
-static int pvr2_context_cleanup_flag;
-static int pvr2_context_cleaned_flag;
-static struct task_struct *pvr2_context_thread_ptr;
-
-
-static void pvr2_context_set_notify(struct pvr2_context *mp, int fl)
-{
-       int signal_flag = 0;
-       mutex_lock(&pvr2_context_mutex);
-       if (fl) {
-               if (!mp->notify_flag) {
-                       signal_flag = (pvr2_context_notify_first == NULL);
-                       mp->notify_prev = pvr2_context_notify_last;
-                       mp->notify_next = NULL;
-                       pvr2_context_notify_last = mp;
-                       if (mp->notify_prev) {
-                               mp->notify_prev->notify_next = mp;
-                       } else {
-                               pvr2_context_notify_first = mp;
-                       }
-                       mp->notify_flag = !0;
-               }
-       } else {
-               if (mp->notify_flag) {
-                       mp->notify_flag = 0;
-                       if (mp->notify_next) {
-                               mp->notify_next->notify_prev = mp->notify_prev;
-                       } else {
-                               pvr2_context_notify_last = mp->notify_prev;
-                       }
-                       if (mp->notify_prev) {
-                               mp->notify_prev->notify_next = mp->notify_next;
-                       } else {
-                               pvr2_context_notify_first = mp->notify_next;
-                       }
-               }
-       }
-       mutex_unlock(&pvr2_context_mutex);
-       if (signal_flag) wake_up(&pvr2_context_sync_data);
-}
-
-
-static void pvr2_context_destroy(struct pvr2_context *mp)
-{
-       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp);
-       if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
-       pvr2_context_set_notify(mp, 0);
-       mutex_lock(&pvr2_context_mutex);
-       if (mp->exist_next) {
-               mp->exist_next->exist_prev = mp->exist_prev;
-       } else {
-               pvr2_context_exist_last = mp->exist_prev;
-       }
-       if (mp->exist_prev) {
-               mp->exist_prev->exist_next = mp->exist_next;
-       } else {
-               pvr2_context_exist_first = mp->exist_next;
-       }
-       if (!pvr2_context_exist_first) {
-               /* Trigger wakeup on control thread in case it is waiting
-                  for an exit condition. */
-               wake_up(&pvr2_context_sync_data);
-       }
-       mutex_unlock(&pvr2_context_mutex);
-       kfree(mp);
-}
-
-
-static void pvr2_context_notify(struct pvr2_context *mp)
-{
-       pvr2_context_set_notify(mp,!0);
-}
-
-
-static void pvr2_context_check(struct pvr2_context *mp)
-{
-       struct pvr2_channel *ch1, *ch2;
-       pvr2_trace(PVR2_TRACE_CTXT,
-                  "pvr2_context %p (notify)", mp);
-       if (!mp->initialized_flag && !mp->disconnect_flag) {
-               mp->initialized_flag = !0;
-               pvr2_trace(PVR2_TRACE_CTXT,
-                          "pvr2_context %p (initialize)", mp);
-               /* Finish hardware initialization */
-               if (pvr2_hdw_initialize(mp->hdw,
-                                       (void (*)(void *))pvr2_context_notify,
-                                       mp)) {
-                       mp->video_stream.stream =
-                               pvr2_hdw_get_video_stream(mp->hdw);
-                       /* Trigger interface initialization.  By doing this
-                          here initialization runs in our own safe and
-                          cozy thread context. */
-                       if (mp->setup_func) mp->setup_func(mp);
-               } else {
-                       pvr2_trace(PVR2_TRACE_CTXT,
-                                  "pvr2_context %p (thread skipping setup)",
-                                  mp);
-                       /* Even though initialization did not succeed,
-                          we're still going to continue anyway.  We need
-                          to do this in order to await the expected
-                          disconnect (which we will detect in the normal
-                          course of operation). */
-               }
-       }
-
-       for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
-               ch2 = ch1->mc_next;
-               if (ch1->check_func) ch1->check_func(ch1);
-       }
-
-       if (mp->disconnect_flag && !mp->mc_first) {
-               /* Go away... */
-               pvr2_context_destroy(mp);
-               return;
-       }
-}
-
-
-static int pvr2_context_shutok(void)
-{
-       return pvr2_context_cleanup_flag && (pvr2_context_exist_first == NULL);
-}
-
-
-static int pvr2_context_thread_func(void *foo)
-{
-       struct pvr2_context *mp;
-
-       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread start");
-
-       do {
-               while ((mp = pvr2_context_notify_first) != NULL) {
-                       pvr2_context_set_notify(mp, 0);
-                       pvr2_context_check(mp);
-               }
-               wait_event_interruptible(
-                       pvr2_context_sync_data,
-                       ((pvr2_context_notify_first != NULL) ||
-                        pvr2_context_shutok()));
-       } while (!pvr2_context_shutok());
-
-       pvr2_context_cleaned_flag = !0;
-       wake_up(&pvr2_context_cleanup_data);
-
-       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread cleaned up");
-
-       wait_event_interruptible(
-               pvr2_context_sync_data,
-               kthread_should_stop());
-
-       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context thread end");
-
-       return 0;
-}
-
-
-int pvr2_context_global_init(void)
-{
-       pvr2_context_thread_ptr = kthread_run(pvr2_context_thread_func,
-                                             NULL,
-                                             "pvrusb2-context");
-       return (pvr2_context_thread_ptr ? 0 : -ENOMEM);
-}
-
-
-void pvr2_context_global_done(void)
-{
-       pvr2_context_cleanup_flag = !0;
-       wake_up(&pvr2_context_sync_data);
-       wait_event_interruptible(
-               pvr2_context_cleanup_data,
-               pvr2_context_cleaned_flag);
-       kthread_stop(pvr2_context_thread_ptr);
-}
-
-
-struct pvr2_context *pvr2_context_create(
-       struct usb_interface *intf,
-       const struct usb_device_id *devid,
-       void (*setup_func)(struct pvr2_context *))
-{
-       struct pvr2_context *mp = NULL;
-       mp = kzalloc(sizeof(*mp),GFP_KERNEL);
-       if (!mp) goto done;
-       pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp);
-       mp->setup_func = setup_func;
-       mutex_init(&mp->mutex);
-       mutex_lock(&pvr2_context_mutex);
-       mp->exist_prev = pvr2_context_exist_last;
-       mp->exist_next = NULL;
-       pvr2_context_exist_last = mp;
-       if (mp->exist_prev) {
-               mp->exist_prev->exist_next = mp;
-       } else {
-               pvr2_context_exist_first = mp;
-       }
-       mutex_unlock(&pvr2_context_mutex);
-       mp->hdw = pvr2_hdw_create(intf,devid);
-       if (!mp->hdw) {
-               pvr2_context_destroy(mp);
-               mp = NULL;
-               goto done;
-       }
-       pvr2_context_set_notify(mp, !0);
- done:
-       return mp;
-}
-
-
-static void pvr2_context_reset_input_limits(struct pvr2_context *mp)
-{
-       unsigned int tmsk,mmsk;
-       struct pvr2_channel *cp;
-       struct pvr2_hdw *hdw = mp->hdw;
-       mmsk = pvr2_hdw_get_input_available(hdw);
-       tmsk = mmsk;
-       for (cp = mp->mc_first; cp; cp = cp->mc_next) {
-               if (!cp->input_mask) continue;
-               tmsk &= cp->input_mask;
-       }
-       pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk);
-       pvr2_hdw_commit_ctl(hdw);
-}
-
-
-static void pvr2_context_enter(struct pvr2_context *mp)
-{
-       mutex_lock(&mp->mutex);
-}
-
-
-static void pvr2_context_exit(struct pvr2_context *mp)
-{
-       int destroy_flag = 0;
-       if (!(mp->mc_first || !mp->disconnect_flag)) {
-               destroy_flag = !0;
-       }
-       mutex_unlock(&mp->mutex);
-       if (destroy_flag) pvr2_context_notify(mp);
-}
-
-
-void pvr2_context_disconnect(struct pvr2_context *mp)
-{
-       pvr2_hdw_disconnect(mp->hdw);
-       mp->disconnect_flag = !0;
-       pvr2_context_notify(mp);
-}
-
-
-void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
-{
-       pvr2_context_enter(mp);
-       cp->hdw = mp->hdw;
-       cp->mc_head = mp;
-       cp->mc_next = NULL;
-       cp->mc_prev = mp->mc_last;
-       if (mp->mc_last) {
-               mp->mc_last->mc_next = cp;
-       } else {
-               mp->mc_first = cp;
-       }
-       mp->mc_last = cp;
-       pvr2_context_exit(mp);
-}
-
-
-static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
-{
-       if (!cp->stream) return;
-       pvr2_stream_kill(cp->stream->stream);
-       cp->stream->user = NULL;
-       cp->stream = NULL;
-}
-
-
-void pvr2_channel_done(struct pvr2_channel *cp)
-{
-       struct pvr2_context *mp = cp->mc_head;
-       pvr2_context_enter(mp);
-       cp->input_mask = 0;
-       pvr2_channel_disclaim_stream(cp);
-       pvr2_context_reset_input_limits(mp);
-       if (cp->mc_next) {
-               cp->mc_next->mc_prev = cp->mc_prev;
-       } else {
-               mp->mc_last = cp->mc_prev;
-       }
-       if (cp->mc_prev) {
-               cp->mc_prev->mc_next = cp->mc_next;
-       } else {
-               mp->mc_first = cp->mc_next;
-       }
-       cp->hdw = NULL;
-       pvr2_context_exit(mp);
-}
-
-
-int pvr2_channel_limit_inputs(struct pvr2_channel *cp,unsigned int cmsk)
-{
-       unsigned int tmsk,mmsk;
-       int ret = 0;
-       struct pvr2_channel *p2;
-       struct pvr2_hdw *hdw = cp->hdw;
-
-       mmsk = pvr2_hdw_get_input_available(hdw);
-       cmsk &= mmsk;
-       if (cmsk == cp->input_mask) {
-               /* No change; nothing to do */
-               return 0;
-       }
-
-       pvr2_context_enter(cp->mc_head);
-       do {
-               if (!cmsk) {
-                       cp->input_mask = 0;
-                       pvr2_context_reset_input_limits(cp->mc_head);
-                       break;
-               }
-               tmsk = mmsk;
-               for (p2 = cp->mc_head->mc_first; p2; p2 = p2->mc_next) {
-                       if (p2 == cp) continue;
-                       if (!p2->input_mask) continue;
-                       tmsk &= p2->input_mask;
-               }
-               if (!(tmsk & cmsk)) {
-                       ret = -EPERM;
-                       break;
-               }
-               tmsk &= cmsk;
-               if ((ret = pvr2_hdw_set_input_allowed(hdw,mmsk,tmsk)) != 0) {
-                       /* Internal failure changing allowed list; probably
-                          should not happen, but react if it does. */
-                       break;
-               }
-               cp->input_mask = cmsk;
-               pvr2_hdw_commit_ctl(hdw);
-       } while (0);
-       pvr2_context_exit(cp->mc_head);
-       return ret;
-}
-
-
-unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *cp)
-{
-       return cp->input_mask;
-}
-
-
-int pvr2_channel_claim_stream(struct pvr2_channel *cp,
-                             struct pvr2_context_stream *sp)
-{
-       int code = 0;
-       pvr2_context_enter(cp->mc_head); do {
-               if (sp == cp->stream) break;
-               if (sp && sp->user) {
-                       code = -EBUSY;
-                       break;
-               }
-               pvr2_channel_disclaim_stream(cp);
-               if (!sp) break;
-               sp->user = cp;
-               cp->stream = sp;
-       } while (0); pvr2_context_exit(cp->mc_head);
-       return code;
-}
-
-
-// This is the marker for the real beginning of a legitimate mpeg2 stream.
-static char stream_sync_key[] = {
-       0x00, 0x00, 0x01, 0xba,
-};
-
-struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
-       struct pvr2_context_stream *sp)
-{
-       struct pvr2_ioread *cp;
-       cp = pvr2_ioread_create();
-       if (!cp) return NULL;
-       pvr2_ioread_setup(cp,sp->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/video/pvrusb2/pvrusb2-context.h b/drivers/media/video/pvrusb2/pvrusb2-context.h
deleted file mode 100644 (file)
index d657e53..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifndef __PVRUSB2_CONTEXT_H
-#define __PVRUSB2_CONTEXT_H
-
-#include <linux/mutex.h>
-#include <linux/usb.h>
-#include <linux/workqueue.h>
-
-struct pvr2_hdw;     /* hardware interface - defined elsewhere */
-struct pvr2_stream;  /* stream interface - defined elsewhere */
-
-struct pvr2_context;        /* All central state */
-struct pvr2_channel;        /* One I/O pathway to a user */
-struct pvr2_context_stream; /* Wrapper for a stream */
-struct pvr2_ioread;         /* Low level stream structure */
-
-struct pvr2_context_stream {
-       struct pvr2_channel *user;
-       struct pvr2_stream *stream;
-};
-
-struct pvr2_context {
-       struct pvr2_channel *mc_first;
-       struct pvr2_channel *mc_last;
-       struct pvr2_context *exist_next;
-       struct pvr2_context *exist_prev;
-       struct pvr2_context *notify_next;
-       struct pvr2_context *notify_prev;
-       struct pvr2_hdw *hdw;
-       struct pvr2_context_stream video_stream;
-       struct mutex mutex;
-       int notify_flag;
-       int initialized_flag;
-       int disconnect_flag;
-
-       /* Called after pvr2_context initialization is complete */
-       void (*setup_func)(struct pvr2_context *);
-
-};
-
-struct pvr2_channel {
-       struct pvr2_context *mc_head;
-       struct pvr2_channel *mc_next;
-       struct pvr2_channel *mc_prev;
-       struct pvr2_context_stream *stream;
-       struct pvr2_hdw *hdw;
-       unsigned int input_mask;
-       void (*check_func)(struct pvr2_channel *);
-};
-
-struct pvr2_context *pvr2_context_create(struct usb_interface *intf,
-                                        const struct usb_device_id *devid,
-                                        void (*setup_func)(struct pvr2_context *));
-void pvr2_context_disconnect(struct pvr2_context *);
-
-void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *);
-void pvr2_channel_done(struct pvr2_channel *);
-int pvr2_channel_limit_inputs(struct pvr2_channel *,unsigned int);
-unsigned int pvr2_channel_get_limited_inputs(struct pvr2_channel *);
-int pvr2_channel_claim_stream(struct pvr2_channel *,
-                             struct pvr2_context_stream *);
-struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
-       struct pvr2_context_stream *);
-
-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/video/pvrusb2/pvrusb2-cs53l32a.c b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c
deleted file mode 100644 (file)
index 8832090..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-/*
-
-   This source file is specifically designed to interface with the
-   v4l-dvb cs53l32a module.
-
-*/
-
-#include "pvrusb2-cs53l32a.h"
-
-
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <linux/errno.h>
-
-struct routing_scheme {
-       const int *def;
-       unsigned int cnt;
-};
-
-
-static const int routing_scheme1[] = {
-       [PVR2_CVAL_INPUT_TV] = 2,  /* 1 or 2 seems to work here */
-       [PVR2_CVAL_INPUT_RADIO] = 2,
-       [PVR2_CVAL_INPUT_COMPOSITE] = 0,
-       [PVR2_CVAL_INPUT_SVIDEO] =  0,
-};
-
-static const struct routing_scheme routing_def1 = {
-       .def = routing_scheme1,
-       .cnt = ARRAY_SIZE(routing_scheme1),
-};
-
-static const struct routing_scheme *routing_schemes[] = {
-       [PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1,
-};
-
-
-void pvr2_cs53l32a_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
-{
-       if (hdw->input_dirty || hdw->force_dirty) {
-               const struct routing_scheme *sp;
-               unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
-               u32 input;
-               pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)",
-                          hdw->input_val);
-               sp = (sid < ARRAY_SIZE(routing_schemes)) ?
-                       routing_schemes[sid] : NULL;
-               if ((sp == NULL) ||
-                   (hdw->input_val < 0) ||
-                   (hdw->input_val >= sp->cnt)) {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "*** WARNING *** subdev v4l2 set_input:"
-                                  " Invalid routing scheme (%u)"
-                                  " and/or input (%d)",
-                                  sid, hdw->input_val);
-                       return;
-               }
-               input = sp->def[hdw->input_val];
-               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/video/pvrusb2/pvrusb2-cs53l32a.h b/drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h
deleted file mode 100644 (file)
index 53ba548..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef __PVRUSB2_CS53L32A_H
-#define __PVRUSB2_CS53L32A_H
-
-/*
-
-   This module connects the pvrusb2 driver to the I2C chip level
-   driver which handles device video processing.  This interface is
-   used internally by the driver; higher level code should only
-   interact through the interface provided by pvrusb2-hdw.h.
-
-*/
-
-
-#include "pvrusb2-hdw-internal.h"
-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/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
deleted file mode 100644 (file)
index 7d5a713..0000000
+++ /dev/null
@@ -1,609 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include "pvrusb2-ctrl.h"
-#include "pvrusb2-hdw-internal.h"
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mutex.h>
-
-
-static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
-{
-       if (cptr->info->check_value) {
-               if (!cptr->info->check_value(cptr,val)) return -ERANGE;
-       } else if (cptr->info->type == pvr2_ctl_enum) {
-               if (val < 0) return -ERANGE;
-               if (val >= cptr->info->def.type_enum.count) return -ERANGE;
-       } else {
-               int lim;
-               lim = cptr->info->def.type_int.min_value;
-               if (cptr->info->get_min_value) {
-                       cptr->info->get_min_value(cptr,&lim);
-               }
-               if (val < lim) return -ERANGE;
-               lim = cptr->info->def.type_int.max_value;
-               if (cptr->info->get_max_value) {
-                       cptr->info->get_max_value(cptr,&lim);
-               }
-               if (val > lim) return -ERANGE;
-       }
-       return 0;
-}
-
-
-/* Set the given control. */
-int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
-{
-       return pvr2_ctrl_set_mask_value(cptr,~0,val);
-}
-
-
-/* Set/clear specific bits of the given control. */
-int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
-{
-       int ret = 0;
-       if (!cptr) return -EINVAL;
-       LOCK_TAKE(cptr->hdw->big_lock); do {
-               if (cptr->info->set_value) {
-                       if (cptr->info->type == pvr2_ctl_bitmask) {
-                               mask &= cptr->info->def.type_bitmask.valid_bits;
-                       } else if ((cptr->info->type == pvr2_ctl_int)||
-                                  (cptr->info->type == pvr2_ctl_enum)) {
-                               ret = pvr2_ctrl_range_check(cptr,val);
-                               if (ret < 0) break;
-                       } else if (cptr->info->type != pvr2_ctl_bool) {
-                               break;
-                       }
-                       ret = cptr->info->set_value(cptr,mask,val);
-               } else {
-                       ret = -EPERM;
-               }
-       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
-       return ret;
-}
-
-
-/* Get the current value of the given control. */
-int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
-{
-       int ret = 0;
-       if (!cptr) return -EINVAL;
-       LOCK_TAKE(cptr->hdw->big_lock); do {
-               ret = cptr->info->get_value(cptr,valptr);
-       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
-       return ret;
-}
-
-
-/* Retrieve control's type */
-enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
-{
-       if (!cptr) return pvr2_ctl_int;
-       return cptr->info->type;
-}
-
-
-/* Retrieve control's maximum value (int type) */
-int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
-{
-       int ret = 0;
-       if (!cptr) return 0;
-       LOCK_TAKE(cptr->hdw->big_lock); do {
-               if (cptr->info->get_max_value) {
-                       cptr->info->get_max_value(cptr,&ret);
-               } else if (cptr->info->type == pvr2_ctl_int) {
-                       ret = cptr->info->def.type_int.max_value;
-               }
-       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
-       return ret;
-}
-
-
-/* Retrieve control's minimum value (int type) */
-int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
-{
-       int ret = 0;
-       if (!cptr) return 0;
-       LOCK_TAKE(cptr->hdw->big_lock); do {
-               if (cptr->info->get_min_value) {
-                       cptr->info->get_min_value(cptr,&ret);
-               } else if (cptr->info->type == pvr2_ctl_int) {
-                       ret = cptr->info->def.type_int.min_value;
-               }
-       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
-       return ret;
-}
-
-
-/* Retrieve control's default value (any type) */
-int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr)
-{
-       int ret = 0;
-       if (!cptr) return -EINVAL;
-       LOCK_TAKE(cptr->hdw->big_lock); do {
-               if (cptr->info->get_def_value) {
-                       ret = cptr->info->get_def_value(cptr, valptr);
-               } else {
-                       *valptr = cptr->info->default_value;
-               }
-       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
-       return ret;
-}
-
-
-/* Retrieve control's enumeration count (enum only) */
-int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
-{
-       int ret = 0;
-       if (!cptr) return 0;
-       LOCK_TAKE(cptr->hdw->big_lock); do {
-               if (cptr->info->type == pvr2_ctl_enum) {
-                       ret = cptr->info->def.type_enum.count;
-               }
-       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
-       return ret;
-}
-
-
-/* Retrieve control's valid mask bits (bit mask only) */
-int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
-{
-       int ret = 0;
-       if (!cptr) return 0;
-       LOCK_TAKE(cptr->hdw->big_lock); do {
-               if (cptr->info->type == pvr2_ctl_bitmask) {
-                       ret = cptr->info->def.type_bitmask.valid_bits;
-               }
-       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
-       return ret;
-}
-
-
-/* Retrieve the control's name */
-const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
-{
-       if (!cptr) return NULL;
-       return cptr->info->name;
-}
-
-
-/* Retrieve the control's desc */
-const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
-{
-       if (!cptr) return NULL;
-       return cptr->info->desc;
-}
-
-
-/* Retrieve a control enumeration or bit mask value */
-int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
-                         char *bptr,unsigned int bmax,
-                         unsigned int *blen)
-{
-       int ret = -EINVAL;
-       if (!cptr) return 0;
-       *blen = 0;
-       LOCK_TAKE(cptr->hdw->big_lock); do {
-               if (cptr->info->type == pvr2_ctl_enum) {
-                       const char * const *names;
-                       names = cptr->info->def.type_enum.value_names;
-                       if (pvr2_ctrl_range_check(cptr,val) == 0) {
-                               if (names[val]) {
-                                       *blen = scnprintf(
-                                               bptr,bmax,"%s",
-                                               names[val]);
-                               } else {
-                                       *blen = 0;
-                               }
-                               ret = 0;
-                       }
-               } else if (cptr->info->type == pvr2_ctl_bitmask) {
-                       const char **names;
-                       unsigned int idx;
-                       int msk;
-                       names = cptr->info->def.type_bitmask.bit_names;
-                       val &= cptr->info->def.type_bitmask.valid_bits;
-                       for (idx = 0, msk = 1; val; idx++, msk <<= 1) {
-                               if (val & msk) {
-                                       *blen = scnprintf(bptr,bmax,"%s",
-                                                         names[idx]);
-                                       ret = 0;
-                                       break;
-                               }
-                       }
-               }
-       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
-       return ret;
-}
-
-
-/* Return V4L ID for this control or zero if none */
-int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
-{
-       if (!cptr) return 0;
-       return cptr->info->v4l_id;
-}
-
-
-unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
-{
-       unsigned int flags = 0;
-
-       if (cptr->info->get_v4lflags) {
-               flags = cptr->info->get_v4lflags(cptr);
-       }
-
-       if (cptr->info->set_value) {
-               flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
-       } else {
-               flags |= V4L2_CTRL_FLAG_READ_ONLY;
-       }
-
-       return flags;
-}
-
-
-/* Return true if control is writable */
-int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
-{
-       if (!cptr) return 0;
-       return cptr->info->set_value != NULL;
-}
-
-
-/* Return true if control has custom symbolic representation */
-int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
-{
-       if (!cptr) return 0;
-       if (!cptr->info->val_to_sym) return 0;
-       if (!cptr->info->sym_to_val) return 0;
-       return !0;
-}
-
-
-/* Convert a given mask/val to a custom symbolic value */
-int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
-                                 int mask,int val,
-                                 char *buf,unsigned int maxlen,
-                                 unsigned int *len)
-{
-       if (!cptr) return -EINVAL;
-       if (!cptr->info->val_to_sym) return -EINVAL;
-       return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len);
-}
-
-
-/* Convert a symbolic value to a mask/value pair */
-int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr,
-                                 const char *buf,unsigned int len,
-                                 int *maskptr,int *valptr)
-{
-       if (!cptr) return -EINVAL;
-       if (!cptr->info->sym_to_val) return -EINVAL;
-       return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr);
-}
-
-
-static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
-                                      const char **names,
-                                      char *ptr,unsigned int len)
-{
-       unsigned int idx;
-       long sm,um;
-       int spcFl;
-       unsigned int uc,cnt;
-       const char *idStr;
-
-       spcFl = 0;
-       uc = 0;
-       um = 0;
-       for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
-               if (sm & msk) {
-                       msk &= ~sm;
-                       idStr = names[idx];
-                       if (idStr) {
-                               cnt = scnprintf(ptr,len,"%s%s%s",
-                                               (spcFl ? " " : ""),
-                                               (msk_only ? "" :
-                                                ((val & sm) ? "+" : "-")),
-                                               idStr);
-                               ptr += cnt; len -= cnt; uc += cnt;
-                               spcFl = !0;
-                       } else {
-                               um |= sm;
-                       }
-               }
-       }
-       if (um) {
-               if (msk_only) {
-                       cnt = scnprintf(ptr,len,"%s0x%lx",
-                                       (spcFl ? " " : ""),
-                                       um);
-                       ptr += cnt; len -= cnt; uc += cnt;
-                       spcFl = !0;
-               } else if (um & val) {
-                       cnt = scnprintf(ptr,len,"%s+0x%lx",
-                                       (spcFl ? " " : ""),
-                                       um & val);
-                       ptr += cnt; len -= cnt; uc += cnt;
-                       spcFl = !0;
-               } else if (um & ~val) {
-                       cnt = scnprintf(ptr,len,"%s+0x%lx",
-                                       (spcFl ? " " : ""),
-                                       um & ~val);
-                       ptr += cnt; len -= cnt; uc += cnt;
-                       spcFl = !0;
-               }
-       }
-       return uc;
-}
-
-
-static const char *boolNames[] = {
-       "false",
-       "true",
-       "no",
-       "yes",
-};
-
-
-static int parse_token(const char *ptr,unsigned int len,
-                      int *valptr,
-                      const char * const *names, unsigned int namecnt)
-{
-       char buf[33];
-       unsigned int slen;
-       unsigned int idx;
-       int negfl;
-       char *p2;
-       *valptr = 0;
-       if (!names) namecnt = 0;
-       for (idx = 0; idx < namecnt; idx++) {
-               if (!names[idx]) continue;
-               slen = strlen(names[idx]);
-               if (slen != len) continue;
-               if (memcmp(names[idx],ptr,slen)) continue;
-               *valptr = idx;
-               return 0;
-       }
-       negfl = 0;
-       if ((*ptr == '-') || (*ptr == '+')) {
-               negfl = (*ptr == '-');
-               ptr++; len--;
-       }
-       if (len >= sizeof(buf)) return -EINVAL;
-       memcpy(buf,ptr,len);
-       buf[len] = 0;
-       *valptr = simple_strtol(buf,&p2,0);
-       if (negfl) *valptr = -(*valptr);
-       if (*p2) return -EINVAL;
-       return 1;
-}
-
-
-static int parse_mtoken(const char *ptr,unsigned int len,
-                       int *valptr,
-                       const char **names,int valid_bits)
-{
-       char buf[33];
-       unsigned int slen;
-       unsigned int idx;
-       char *p2;
-       int msk;
-       *valptr = 0;
-       for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
-               if (!(msk & valid_bits)) continue;
-               valid_bits &= ~msk;
-               if (!names[idx]) continue;
-               slen = strlen(names[idx]);
-               if (slen != len) continue;
-               if (memcmp(names[idx],ptr,slen)) continue;
-               *valptr = msk;
-               return 0;
-       }
-       if (len >= sizeof(buf)) return -EINVAL;
-       memcpy(buf,ptr,len);
-       buf[len] = 0;
-       *valptr = simple_strtol(buf,&p2,0);
-       if (*p2) return -EINVAL;
-       return 0;
-}
-
-
-static int parse_tlist(const char *ptr,unsigned int len,
-                      int *maskptr,int *valptr,
-                      const char **names,int valid_bits)
-{
-       unsigned int cnt;
-       int mask,val,kv,mode,ret;
-       mask = 0;
-       val = 0;
-       ret = 0;
-       while (len) {
-               cnt = 0;
-               while ((cnt < len) &&
-                      ((ptr[cnt] <= 32) ||
-                       (ptr[cnt] >= 127))) cnt++;
-               ptr += cnt;
-               len -= cnt;
-               mode = 0;
-               if ((*ptr == '-') || (*ptr == '+')) {
-                       mode = (*ptr == '-') ? -1 : 1;
-                       ptr++;
-                       len--;
-               }
-               cnt = 0;
-               while (cnt < len) {
-                       if (ptr[cnt] <= 32) break;
-                       if (ptr[cnt] >= 127) break;
-                       cnt++;
-               }
-               if (!cnt) break;
-               if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
-                       ret = -EINVAL;
-                       break;
-               }
-               ptr += cnt;
-               len -= cnt;
-               switch (mode) {
-               case 0:
-                       mask = valid_bits;
-                       val |= kv;
-                       break;
-               case -1:
-                       mask |= kv;
-                       val &= ~kv;
-                       break;
-               case 1:
-                       mask |= kv;
-                       val |= kv;
-                       break;
-               default:
-                       break;
-               }
-       }
-       *maskptr = mask;
-       *valptr = val;
-       return ret;
-}
-
-
-/* Convert a symbolic value to a mask/value pair */
-int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
-                          const char *ptr,unsigned int len,
-                          int *maskptr,int *valptr)
-{
-       int ret = -EINVAL;
-       unsigned int cnt;
-
-       *maskptr = 0;
-       *valptr = 0;
-
-       cnt = 0;
-       while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
-       len -= cnt; ptr += cnt;
-       cnt = 0;
-       while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
-                              (ptr[len-(cnt+1)] >= 127))) cnt++;
-       len -= cnt;
-
-       if (!len) return -EINVAL;
-
-       LOCK_TAKE(cptr->hdw->big_lock); do {
-               if (cptr->info->type == pvr2_ctl_int) {
-                       ret = parse_token(ptr,len,valptr,NULL,0);
-                       if (ret >= 0) {
-                               ret = pvr2_ctrl_range_check(cptr,*valptr);
-                       }
-                       *maskptr = ~0;
-               } else if (cptr->info->type == pvr2_ctl_bool) {
-                       ret = parse_token(ptr,len,valptr,boolNames,
-                                         ARRAY_SIZE(boolNames));
-                       if (ret == 1) {
-                               *valptr = *valptr ? !0 : 0;
-                       } else if (ret == 0) {
-                               *valptr = (*valptr & 1) ? !0 : 0;
-                       }
-                       *maskptr = 1;
-               } else if (cptr->info->type == pvr2_ctl_enum) {
-                       ret = parse_token(
-                               ptr,len,valptr,
-                               cptr->info->def.type_enum.value_names,
-                               cptr->info->def.type_enum.count);
-                       if (ret >= 0) {
-                               ret = pvr2_ctrl_range_check(cptr,*valptr);
-                       }
-                       *maskptr = ~0;
-               } else if (cptr->info->type == pvr2_ctl_bitmask) {
-                       ret = parse_tlist(
-                               ptr,len,maskptr,valptr,
-                               cptr->info->def.type_bitmask.bit_names,
-                               cptr->info->def.type_bitmask.valid_bits);
-               }
-       } while(0); LOCK_GIVE(cptr->hdw->big_lock);
-       return ret;
-}
-
-
-/* Convert a given mask/val to a symbolic value */
-int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
-                                   int mask,int val,
-                                   char *buf,unsigned int maxlen,
-                                   unsigned int *len)
-{
-       int ret = -EINVAL;
-
-       *len = 0;
-       if (cptr->info->type == pvr2_ctl_int) {
-               *len = scnprintf(buf,maxlen,"%d",val);
-               ret = 0;
-       } else if (cptr->info->type == pvr2_ctl_bool) {
-               *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
-               ret = 0;
-       } else if (cptr->info->type == pvr2_ctl_enum) {
-               const char * const *names;
-               names = cptr->info->def.type_enum.value_names;
-               if ((val >= 0) &&
-                   (val < cptr->info->def.type_enum.count)) {
-                       if (names[val]) {
-                               *len = scnprintf(
-                                       buf,maxlen,"%s",
-                                       names[val]);
-                       } else {
-                               *len = 0;
-                       }
-                       ret = 0;
-               }
-       } else if (cptr->info->type == pvr2_ctl_bitmask) {
-               *len = gen_bitmask_string(
-                       val & mask & cptr->info->def.type_bitmask.valid_bits,
-                       ~0,!0,
-                       cptr->info->def.type_bitmask.bit_names,
-                       buf,maxlen);
-       }
-       return ret;
-}
-
-
-/* Convert a given mask/val to a symbolic value */
-int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
-                          int mask,int val,
-                          char *buf,unsigned int maxlen,
-                          unsigned int *len)
-{
-       int ret;
-       LOCK_TAKE(cptr->hdw->big_lock); do {
-               ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
-                                                     buf,maxlen,len);
-       } 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/video/pvrusb2/pvrusb2-ctrl.h b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
deleted file mode 100644 (file)
index 794ff90..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifndef __PVRUSB2_CTRL_H
-#define __PVRUSB2_CTRL_H
-
-struct pvr2_ctrl;
-
-enum pvr2_ctl_type {
-       pvr2_ctl_int = 0,
-       pvr2_ctl_enum = 1,
-       pvr2_ctl_bitmask = 2,
-       pvr2_ctl_bool = 3,
-};
-
-
-/* Set the given control. */
-int pvr2_ctrl_set_value(struct pvr2_ctrl *,int val);
-
-/* Set/clear specific bits of the given control. */
-int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *,int mask,int val);
-
-/* Get the current value of the given control. */
-int pvr2_ctrl_get_value(struct pvr2_ctrl *,int *valptr);
-
-/* Retrieve control's type */
-enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *);
-
-/* Retrieve control's maximum value (int type) */
-int pvr2_ctrl_get_max(struct pvr2_ctrl *);
-
-/* Retrieve control's minimum value (int type) */
-int pvr2_ctrl_get_min(struct pvr2_ctrl *);
-
-/* Retrieve control's default value (any type) */
-int pvr2_ctrl_get_def(struct pvr2_ctrl *, int *valptr);
-
-/* Retrieve control's enumeration count (enum only) */
-int pvr2_ctrl_get_cnt(struct pvr2_ctrl *);
-
-/* Retrieve control's valid mask bits (bit mask only) */
-int pvr2_ctrl_get_mask(struct pvr2_ctrl *);
-
-/* Retrieve the control's name */
-const char *pvr2_ctrl_get_name(struct pvr2_ctrl *);
-
-/* Retrieve the control's desc */
-const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *);
-
-/* Retrieve a control enumeration or bit mask value */
-int pvr2_ctrl_get_valname(struct pvr2_ctrl *,int,char *,unsigned int,
-                         unsigned int *);
-
-/* Return true if control is writable */
-int pvr2_ctrl_is_writable(struct pvr2_ctrl *);
-
-/* Return V4L flags value for control (or zero if there is no v4l control
-   actually under this control) */
-unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *);
-
-/* Return V4L ID for this control or zero if none */
-int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *);
-
-/* Return true if control has custom symbolic representation */
-int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *);
-
-/* Convert a given mask/val to a custom symbolic value */
-int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *,
-                                 int mask,int val,
-                                 char *buf,unsigned int maxlen,
-                                 unsigned int *len);
-
-/* Convert a symbolic value to a mask/value pair */
-int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *,
-                                 const char *buf,unsigned int len,
-                                 int *maskptr,int *valptr);
-
-/* Convert a given mask/val to a symbolic value */
-int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *,
-                          int mask,int val,
-                          char *buf,unsigned int maxlen,
-                          unsigned int *len);
-
-/* Convert a symbolic value to a mask/value pair */
-int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *,
-                          const char *buf,unsigned int len,
-                          int *maskptr,int *valptr);
-
-/* Convert a given mask/val to a symbolic value - must already be
-   inside of critical region. */
-int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *,
-                          int mask,int val,
-                          char *buf,unsigned int maxlen,
-                          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/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
deleted file mode 100644 (file)
index c514d0b..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-/*
-
-   This source file is specifically designed to interface with the
-   cx2584x, in kernels 2.6.16 or newer.
-
-*/
-
-#include "pvrusb2-cx2584x-v4l.h"
-#include "pvrusb2-video-v4l.h"
-
-
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-#include <media/cx25840.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <linux/errno.h>
-
-
-struct routing_scheme_item {
-       int vid;
-       int aud;
-};
-
-struct routing_scheme {
-       const struct routing_scheme_item *def;
-       unsigned int cnt;
-};
-
-static const struct routing_scheme_item routing_scheme0[] = {
-       [PVR2_CVAL_INPUT_TV] = {
-               .vid = CX25840_COMPOSITE7,
-               .aud = CX25840_AUDIO8,
-       },
-       [PVR2_CVAL_INPUT_RADIO] = { /* Treat the same as composite */
-               .vid = CX25840_COMPOSITE3,
-               .aud = CX25840_AUDIO_SERIAL,
-       },
-       [PVR2_CVAL_INPUT_COMPOSITE] = {
-               .vid = CX25840_COMPOSITE3,
-               .aud = CX25840_AUDIO_SERIAL,
-       },
-       [PVR2_CVAL_INPUT_SVIDEO] = {
-               .vid = CX25840_SVIDEO1,
-               .aud = CX25840_AUDIO_SERIAL,
-       },
-};
-
-static const struct routing_scheme routing_def0 = {
-       .def = routing_scheme0,
-       .cnt = ARRAY_SIZE(routing_scheme0),
-};
-
-/* Specific to gotview device */
-static const struct routing_scheme_item routing_schemegv[] = {
-       [PVR2_CVAL_INPUT_TV] = {
-               .vid = CX25840_COMPOSITE2,
-               .aud = CX25840_AUDIO5,
-       },
-       [PVR2_CVAL_INPUT_RADIO] = {
-               /* line-in is used for radio and composite.  A GPIO is
-                  used to switch between the two choices. */
-               .vid = CX25840_COMPOSITE1,
-               .aud = CX25840_AUDIO_SERIAL,
-       },
-       [PVR2_CVAL_INPUT_COMPOSITE] = {
-               .vid = CX25840_COMPOSITE1,
-               .aud = CX25840_AUDIO_SERIAL,
-       },
-       [PVR2_CVAL_INPUT_SVIDEO] = {
-               .vid = (CX25840_SVIDEO_LUMA3|CX25840_SVIDEO_CHROMA4),
-               .aud = CX25840_AUDIO_SERIAL,
-       },
-};
-
-static const struct routing_scheme routing_defgv = {
-       .def = routing_schemegv,
-       .cnt = ARRAY_SIZE(routing_schemegv),
-};
-
-/* Specific to grabster av400 device */
-static const struct routing_scheme_item routing_schemeav400[] = {
-       [PVR2_CVAL_INPUT_COMPOSITE] = {
-               .vid = CX25840_COMPOSITE1,
-               .aud = CX25840_AUDIO_SERIAL,
-       },
-       [PVR2_CVAL_INPUT_SVIDEO] = {
-               .vid = (CX25840_SVIDEO_LUMA2|CX25840_SVIDEO_CHROMA4),
-               .aud = CX25840_AUDIO_SERIAL,
-       },
-};
-
-static const struct routing_scheme routing_defav400 = {
-       .def = routing_schemeav400,
-       .cnt = ARRAY_SIZE(routing_schemeav400),
-};
-
-static const struct routing_scheme *routing_schemes[] = {
-       [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
-       [PVR2_ROUTING_SCHEME_GOTVIEW] = &routing_defgv,
-       [PVR2_ROUTING_SCHEME_AV400] = &routing_defav400,
-};
-
-void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
-{
-       pvr2_trace(PVR2_TRACE_CHIPS, "subdev cx2584x update...");
-       if (hdw->input_dirty || hdw->force_dirty) {
-               enum cx25840_video_input vid_input;
-               enum cx25840_audio_input aud_input;
-               const struct routing_scheme *sp;
-               unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
-
-               sp = (sid < ARRAY_SIZE(routing_schemes)) ?
-                       routing_schemes[sid] : NULL;
-               if ((sp == NULL) ||
-                   (hdw->input_val < 0) ||
-                   (hdw->input_val >= sp->cnt)) {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "*** WARNING *** subdev cx2584x set_input:"
-                                  " Invalid routing scheme (%u)"
-                                  " and/or input (%d)",
-                                  sid, hdw->input_val);
-                       return;
-               }
-               vid_input = sp->def[hdw->input_val].vid;
-               aud_input = sp->def[hdw->input_val].aud;
-               pvr2_trace(PVR2_TRACE_CHIPS,
-                          "subdev cx2584x set_input vid=0x%x aud=0x%x",
-                          vid_input, aud_input);
-               sd->ops->video->s_routing(sd, (u32)vid_input, 0, 0);
-               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/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
deleted file mode 100644 (file)
index e35c232..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef __PVRUSB2_CX2584X_V4L_H
-#define __PVRUSB2_CX2584X_V4L_H
-
-/*
-
-   This module connects the pvrusb2 driver to the I2C chip level
-   driver which handles combined device audio & video processing.
-   This interface is used internally by the driver; higher level code
-   should only interact through the interface provided by
-   pvrusb2-hdw.h.
-
-*/
-
-
-
-#include "pvrusb2-hdw-internal.h"
-
-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/video/pvrusb2/pvrusb2-debug.h b/drivers/media/video/pvrusb2/pvrusb2-debug.h
deleted file mode 100644 (file)
index be79249..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifndef __PVRUSB2_DEBUG_H
-#define __PVRUSB2_DEBUG_H
-
-extern int pvrusb2_debug;
-
-#define pvr2_trace(msk, fmt, arg...) do {if(msk & pvrusb2_debug) printk(KERN_INFO "pvrusb2: " fmt "\n", ##arg); } while (0)
-
-/* These are listed in *rough* order of decreasing usefulness and
-   increasing noise level. */
-#define PVR2_TRACE_INFO       (1 <<  0) /* Normal messages */
-#define PVR2_TRACE_ERROR_LEGS (1 <<  1) /* error messages */
-#define PVR2_TRACE_TOLERANCE  (1 <<  2) /* track tolerance-affected errors */
-#define PVR2_TRACE_TRAP       (1 <<  3) /* Trap & report app misbehavior */
-#define PVR2_TRACE_STD        (1 <<  4) /* Log video standard stuff */
-#define PVR2_TRACE_INIT       (1 <<  5) /* misc initialization steps */
-#define PVR2_TRACE_START_STOP (1 <<  6) /* Streaming start / stop */
-#define PVR2_TRACE_CTL        (1 <<  7) /* commit of control changes */
-#define PVR2_TRACE_STATE      (1 <<  8) /* Device state changes */
-#define PVR2_TRACE_STBITS     (1 <<  9) /* Individual bit state changes */
-#define PVR2_TRACE_EEPROM     (1 << 10) /* eeprom parsing / report */
-#define PVR2_TRACE_STRUCT     (1 << 11) /* internal struct creation */
-#define PVR2_TRACE_OPEN_CLOSE (1 << 12) /* application open / close */
-#define PVR2_TRACE_CTXT       (1 << 13) /* Main context tracking */
-#define PVR2_TRACE_SYSFS      (1 << 14) /* Sysfs driven I/O */
-#define PVR2_TRACE_FIRMWARE   (1 << 15) /* firmware upload actions */
-#define PVR2_TRACE_CHIPS      (1 << 16) /* chip broadcast operation */
-#define PVR2_TRACE_I2C        (1 << 17) /* I2C related stuff */
-#define PVR2_TRACE_I2C_CMD    (1 << 18) /* Software commands to I2C modules */
-#define PVR2_TRACE_I2C_CORE   (1 << 19) /* I2C core debugging */
-#define PVR2_TRACE_I2C_TRAF   (1 << 20) /* I2C traffic through the adapter */
-#define PVR2_TRACE_V4LIOCTL   (1 << 21) /* v4l ioctl details */
-#define PVR2_TRACE_ENCODER    (1 << 22) /* mpeg2 encoder operation */
-#define PVR2_TRACE_BUF_POOL   (1 << 23) /* Track buffer pool management */
-#define PVR2_TRACE_BUF_FLOW   (1 << 24) /* Track buffer flow in system */
-#define PVR2_TRACE_DATA_FLOW  (1 << 25) /* Track data flow */
-#define PVR2_TRACE_DEBUGIFC   (1 << 26) /* Debug interface actions */
-#define PVR2_TRACE_GPIO       (1 << 27) /* GPIO state bit changes */
-#define PVR2_TRACE_DVB_FEED   (1 << 28) /* DVB transport feed 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/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
deleted file mode 100644 (file)
index 4279ebb..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/string.h>
-#include "pvrusb2-debugifc.h"
-#include "pvrusb2-hdw.h"
-#include "pvrusb2-debug.h"
-
-struct debugifc_mask_item {
-       const char *name;
-       unsigned long msk;
-};
-
-
-static unsigned int debugifc_count_whitespace(const char *buf,
-                                             unsigned int count)
-{
-       unsigned int scnt;
-       char ch;
-
-       for (scnt = 0; scnt < count; scnt++) {
-               ch = buf[scnt];
-               if (ch == ' ') continue;
-               if (ch == '\t') continue;
-               if (ch == '\n') continue;
-               break;
-       }
-       return scnt;
-}
-
-
-static unsigned int debugifc_count_nonwhitespace(const char *buf,
-                                                unsigned int count)
-{
-       unsigned int scnt;
-       char ch;
-
-       for (scnt = 0; scnt < count; scnt++) {
-               ch = buf[scnt];
-               if (ch == ' ') break;
-               if (ch == '\t') break;
-               if (ch == '\n') break;
-       }
-       return scnt;
-}
-
-
-static unsigned int debugifc_isolate_word(const char *buf,unsigned int count,
-                                         const char **wstrPtr,
-                                         unsigned int *wlenPtr)
-{
-       const char *wptr;
-       unsigned int consume_cnt = 0;
-       unsigned int wlen;
-       unsigned int scnt;
-
-       wptr = NULL;
-       wlen = 0;
-       scnt = debugifc_count_whitespace(buf,count);
-       consume_cnt += scnt; count -= scnt; buf += scnt;
-       if (!count) goto done;
-
-       scnt = debugifc_count_nonwhitespace(buf,count);
-       if (!scnt) goto done;
-       wptr = buf;
-       wlen = scnt;
-       consume_cnt += scnt; count -= scnt; buf += scnt;
-
- done:
-       *wstrPtr = wptr;
-       *wlenPtr = wlen;
-       return consume_cnt;
-}
-
-
-static int debugifc_parse_unsigned_number(const char *buf,unsigned int count,
-                                         u32 *num_ptr)
-{
-       u32 result = 0;
-       int radix = 10;
-       if ((count >= 2) && (buf[0] == '0') &&
-           ((buf[1] == 'x') || (buf[1] == 'X'))) {
-               radix = 16;
-               count -= 2;
-               buf += 2;
-       } else if ((count >= 1) && (buf[0] == '0')) {
-               radix = 8;
-       }
-
-       while (count--) {
-               int val = hex_to_bin(*buf++);
-               if (val < 0 || val >= radix)
-                       return -EINVAL;
-               result *= radix;
-               result += val;
-       }
-       *num_ptr = result;
-       return 0;
-}
-
-
-static int debugifc_match_keyword(const char *buf,unsigned int count,
-                                 const char *keyword)
-{
-       unsigned int kl;
-       if (!keyword) return 0;
-       kl = strlen(keyword);
-       if (kl != count) return 0;
-       return !memcmp(buf,keyword,kl);
-}
-
-
-int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt)
-{
-       int bcnt = 0;
-       int ccnt;
-       ccnt = scnprintf(buf, acnt, "Driver hardware description: %s\n",
-                        pvr2_hdw_get_desc(hdw));
-       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
-       ccnt = scnprintf(buf,acnt,"Driver state info:\n");
-       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
-       ccnt = pvr2_hdw_state_report(hdw,buf,acnt);
-       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
-
-       return bcnt;
-}
-
-
-int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
-                              char *buf,unsigned int acnt)
-{
-       int bcnt = 0;
-       int ccnt;
-       int ret;
-       u32 gpio_dir,gpio_in,gpio_out;
-       struct pvr2_stream_stats stats;
-       struct pvr2_stream *sp;
-
-       ret = pvr2_hdw_is_hsm(hdw);
-       ccnt = scnprintf(buf,acnt,"USB link speed: %s\n",
-                        (ret < 0 ? "FAIL" : (ret ? "high" : "full")));
-       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
-
-       gpio_dir = 0; gpio_in = 0; gpio_out = 0;
-       pvr2_hdw_gpio_get_dir(hdw,&gpio_dir);
-       pvr2_hdw_gpio_get_out(hdw,&gpio_out);
-       pvr2_hdw_gpio_get_in(hdw,&gpio_in);
-       ccnt = scnprintf(buf,acnt,"GPIO state: dir=0x%x in=0x%x out=0x%x\n",
-                        gpio_dir,gpio_in,gpio_out);
-       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
-
-       ccnt = scnprintf(buf,acnt,"Streaming is %s\n",
-                        pvr2_hdw_get_streaming(hdw) ? "on" : "off");
-       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
-
-
-       sp = pvr2_hdw_get_video_stream(hdw);
-       if (sp) {
-               pvr2_stream_get_stats(sp, &stats, 0);
-               ccnt = scnprintf(
-                       buf,acnt,
-                       "Bytes streamed=%u"
-                       " URBs: queued=%u idle=%u ready=%u"
-                       " processed=%u failed=%u\n",
-                       stats.bytes_processed,
-                       stats.buffers_in_queue,
-                       stats.buffers_in_idle,
-                       stats.buffers_in_ready,
-                       stats.buffers_processed,
-                       stats.buffers_failed);
-               bcnt += ccnt; acnt -= ccnt; buf += ccnt;
-       }
-
-       return bcnt;
-}
-
-
-static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
-                               unsigned int count)
-{
-       const char *wptr;
-       unsigned int wlen;
-       unsigned int scnt;
-
-       scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
-       if (!scnt) return 0;
-       count -= scnt; buf += scnt;
-       if (!wptr) return 0;
-
-       pvr2_trace(PVR2_TRACE_DEBUGIFC,"debugifc cmd: \"%.*s\"",wlen,wptr);
-       if (debugifc_match_keyword(wptr,wlen,"reset")) {
-               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
-               if (!scnt) return -EINVAL;
-               count -= scnt; buf += scnt;
-               if (!wptr) return -EINVAL;
-               if (debugifc_match_keyword(wptr,wlen,"cpu")) {
-                       pvr2_hdw_cpureset_assert(hdw,!0);
-                       pvr2_hdw_cpureset_assert(hdw,0);
-                       return 0;
-               } else if (debugifc_match_keyword(wptr,wlen,"bus")) {
-                       pvr2_hdw_device_reset(hdw);
-               } else if (debugifc_match_keyword(wptr,wlen,"soft")) {
-                       return pvr2_hdw_cmd_powerup(hdw);
-               } else if (debugifc_match_keyword(wptr,wlen,"deep")) {
-                       return pvr2_hdw_cmd_deep_reset(hdw);
-               } else if (debugifc_match_keyword(wptr,wlen,"firmware")) {
-                       return pvr2_upload_firmware2(hdw);
-               } else if (debugifc_match_keyword(wptr,wlen,"decoder")) {
-                       return pvr2_hdw_cmd_decoder_reset(hdw);
-               } else if (debugifc_match_keyword(wptr,wlen,"worker")) {
-                       return pvr2_hdw_untrip(hdw);
-               } else if (debugifc_match_keyword(wptr,wlen,"usbstats")) {
-                       pvr2_stream_get_stats(pvr2_hdw_get_video_stream(hdw),
-                                             NULL, !0);
-                       return 0;
-               }
-               return -EINVAL;
-       } else if (debugifc_match_keyword(wptr,wlen,"cpufw")) {
-               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
-               if (!scnt) return -EINVAL;
-               count -= scnt; buf += scnt;
-               if (!wptr) return -EINVAL;
-               if (debugifc_match_keyword(wptr,wlen,"fetch")) {
-                       scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
-                       if (scnt && wptr) {
-                               count -= scnt; buf += scnt;
-                               if (debugifc_match_keyword(wptr, wlen,
-                                                          "prom")) {
-                                       pvr2_hdw_cpufw_set_enabled(hdw, 2, !0);
-                               } else if (debugifc_match_keyword(wptr, wlen,
-                                                                 "ram8k")) {
-                                       pvr2_hdw_cpufw_set_enabled(hdw, 0, !0);
-                               } else if (debugifc_match_keyword(wptr, wlen,
-                                                                 "ram16k")) {
-                                       pvr2_hdw_cpufw_set_enabled(hdw, 1, !0);
-                               } else {
-                                       return -EINVAL;
-                               }
-                       }
-                       pvr2_hdw_cpufw_set_enabled(hdw,0,!0);
-                       return 0;
-               } else if (debugifc_match_keyword(wptr,wlen,"done")) {
-                       pvr2_hdw_cpufw_set_enabled(hdw,0,0);
-                       return 0;
-               } else {
-                       return -EINVAL;
-               }
-       } else if (debugifc_match_keyword(wptr,wlen,"gpio")) {
-               int dir_fl = 0;
-               int ret;
-               u32 msk,val;
-               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
-               if (!scnt) return -EINVAL;
-               count -= scnt; buf += scnt;
-               if (!wptr) return -EINVAL;
-               if (debugifc_match_keyword(wptr,wlen,"dir")) {
-                       dir_fl = !0;
-               } else if (!debugifc_match_keyword(wptr,wlen,"out")) {
-                       return -EINVAL;
-               }
-               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
-               if (!scnt) return -EINVAL;
-               count -= scnt; buf += scnt;
-               if (!wptr) return -EINVAL;
-               ret = debugifc_parse_unsigned_number(wptr,wlen,&msk);
-               if (ret) return ret;
-               scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
-               if (wptr) {
-                       ret = debugifc_parse_unsigned_number(wptr,wlen,&val);
-                       if (ret) return ret;
-               } else {
-                       val = msk;
-                       msk = 0xffffffff;
-               }
-               if (dir_fl) {
-                       ret = pvr2_hdw_gpio_chg_dir(hdw,msk,val);
-               } else {
-                       ret = pvr2_hdw_gpio_chg_out(hdw,msk,val);
-               }
-               return ret;
-       }
-       pvr2_trace(PVR2_TRACE_DEBUGIFC,
-                  "debugifc failed to recognize cmd: \"%.*s\"",wlen,wptr);
-       return -EINVAL;
-}
-
-
-int pvr2_debugifc_docmd(struct pvr2_hdw *hdw,const char *buf,
-                       unsigned int count)
-{
-       unsigned int bcnt = 0;
-       int ret;
-
-       while (count) {
-               for (bcnt = 0; bcnt < count; bcnt++) {
-                       if (buf[bcnt] == '\n') break;
-               }
-
-               ret = pvr2_debugifc_do1cmd(hdw,buf,bcnt);
-               if (ret < 0) return ret;
-               if (bcnt < count) bcnt++;
-               buf += bcnt;
-               count -= bcnt;
-       }
-
-       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/video/pvrusb2/pvrusb2-debugifc.h b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
deleted file mode 100644 (file)
index 2f8d467..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifndef __PVRUSB2_DEBUGIFC_H
-#define __PVRUSB2_DEBUGIFC_H
-
-struct pvr2_hdw;
-
-/* Print general status of driver.  This will also trigger a probe of
-   the USB link.  Unlike print_info(), this one synchronizes with the
-   driver so the information should be self-consistent (but it will
-   hang if the driver is wedged). */
-int pvr2_debugifc_print_info(struct pvr2_hdw *,
-                            char *buf_ptr, unsigned int buf_size);
-
-/* Non-intrusively print some useful debugging info from inside the
-   driver.  This should work even if the driver appears to be
-   wedged. */
-int pvr2_debugifc_print_status(struct pvr2_hdw *,
-                              char *buf_ptr,unsigned int buf_size);
-
-/* Parse a string command into a driver action. */
-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/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
deleted file mode 100644 (file)
index adc501d..0000000
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2007 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-/*
-
-This source file should encompass ALL per-device type information for the
-driver.  To define a new device, add elements to the pvr2_device_table and
-pvr2_device_desc structures.
-
-*/
-
-#include "pvrusb2-devattr.h"
-#include <linux/usb.h>
-#include <linux/module.h>
-/* This is needed in order to pull in tuner type ids... */
-#include <linux/i2c.h>
-#include <media/tuner.h>
-#ifdef CONFIG_VIDEO_PVRUSB2_DVB
-#include "pvrusb2-hdw-internal.h"
-#include "lgdt330x.h"
-#include "s5h1409.h"
-#include "s5h1411.h"
-#include "tda10048.h"
-#include "tda18271.h"
-#include "tda8290.h"
-#include "tuner-simple.h"
-#endif
-
-
-/*------------------------------------------------------------------------*/
-/* Hauppauge PVR-USB2 Model 29xxx */
-
-static const struct pvr2_device_client_desc pvr2_cli_29xxx[] = {
-       { .module_id = PVR2_CLIENT_ID_SAA7115 },
-       { .module_id = PVR2_CLIENT_ID_MSP3400 },
-       { .module_id = PVR2_CLIENT_ID_TUNER },
-       { .module_id = PVR2_CLIENT_ID_DEMOD },
-};
-
-#define PVR2_FIRMWARE_29xxx "v4l-pvrusb2-29xxx-01.fw"
-static const char *pvr2_fw1_names_29xxx[] = {
-               PVR2_FIRMWARE_29xxx,
-};
-
-static const struct pvr2_device_desc pvr2_device_29xxx = {
-               .description = "WinTV PVR USB2 Model 29xxx",
-               .shortname = "29xxx",
-               .client_table.lst = pvr2_cli_29xxx,
-               .client_table.cnt = ARRAY_SIZE(pvr2_cli_29xxx),
-               .fx2_firmware.lst = pvr2_fw1_names_29xxx,
-               .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_29xxx),
-               .flag_has_hauppauge_rom = !0,
-               .flag_has_analogtuner = !0,
-               .flag_has_fmradio = !0,
-               .flag_has_composite = !0,
-               .flag_has_svideo = !0,
-               .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
-               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
-               .ir_scheme = PVR2_IR_SCHEME_29XXX,
-};
-
-
-
-/*------------------------------------------------------------------------*/
-/* Hauppauge PVR-USB2 Model 24xxx */
-
-static const struct pvr2_device_client_desc pvr2_cli_24xxx[] = {
-       { .module_id = PVR2_CLIENT_ID_CX25840 },
-       { .module_id = PVR2_CLIENT_ID_TUNER },
-       { .module_id = PVR2_CLIENT_ID_WM8775 },
-       { .module_id = PVR2_CLIENT_ID_DEMOD },
-};
-
-#define PVR2_FIRMWARE_24xxx "v4l-pvrusb2-24xxx-01.fw"
-static const char *pvr2_fw1_names_24xxx[] = {
-               PVR2_FIRMWARE_24xxx,
-};
-
-static const struct pvr2_device_desc pvr2_device_24xxx = {
-               .description = "WinTV PVR USB2 Model 24xxx",
-               .shortname = "24xxx",
-               .client_table.lst = pvr2_cli_24xxx,
-               .client_table.cnt = ARRAY_SIZE(pvr2_cli_24xxx),
-               .fx2_firmware.lst = pvr2_fw1_names_24xxx,
-               .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_24xxx),
-               .flag_has_cx25840 = !0,
-               .flag_has_wm8775 = !0,
-               .flag_has_hauppauge_rom = !0,
-               .flag_has_analogtuner = !0,
-               .flag_has_fmradio = !0,
-               .flag_has_composite = !0,
-               .flag_has_svideo = !0,
-               .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
-               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
-               .ir_scheme = PVR2_IR_SCHEME_24XXX,
-};
-
-
-
-/*------------------------------------------------------------------------*/
-/* GOTVIEW USB2.0 DVD2 */
-
-static const struct pvr2_device_client_desc pvr2_cli_gotview_2[] = {
-       { .module_id = PVR2_CLIENT_ID_CX25840 },
-       { .module_id = PVR2_CLIENT_ID_TUNER },
-       { .module_id = PVR2_CLIENT_ID_DEMOD },
-};
-
-static const struct pvr2_device_desc pvr2_device_gotview_2 = {
-               .description = "Gotview USB 2.0 DVD 2",
-               .shortname = "gv2",
-               .client_table.lst = pvr2_cli_gotview_2,
-               .client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2),
-               .flag_has_cx25840 = !0,
-               .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
-               .flag_has_analogtuner = !0,
-               .flag_has_fmradio = !0,
-               .flag_has_composite = !0,
-               .flag_has_svideo = !0,
-               .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW,
-};
-
-
-
-/*------------------------------------------------------------------------*/
-/* GOTVIEW USB2.0 DVD Deluxe */
-
-/* (same module list as gotview_2) */
-
-static const struct pvr2_device_desc pvr2_device_gotview_2d = {
-               .description = "Gotview USB 2.0 DVD Deluxe",
-               .shortname = "gv2d",
-               .client_table.lst = pvr2_cli_gotview_2,
-               .client_table.cnt = ARRAY_SIZE(pvr2_cli_gotview_2),
-               .flag_has_cx25840 = !0,
-               .default_tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
-               .flag_has_analogtuner = !0,
-               .flag_has_composite = !0,
-               .flag_has_svideo = !0,
-               .signal_routing_scheme = PVR2_ROUTING_SCHEME_GOTVIEW,
-};
-
-
-
-/*------------------------------------------------------------------------*/
-/* Terratec Grabster AV400 */
-
-static const struct pvr2_device_client_desc pvr2_cli_av400[] = {
-       { .module_id = PVR2_CLIENT_ID_CX25840 },
-};
-
-static const struct pvr2_device_desc pvr2_device_av400 = {
-               .description = "Terratec Grabster AV400",
-               .shortname = "av400",
-               .flag_is_experimental = 1,
-               .client_table.lst = pvr2_cli_av400,
-               .client_table.cnt = ARRAY_SIZE(pvr2_cli_av400),
-               .flag_has_cx25840 = !0,
-               .flag_has_analogtuner = 0,
-               .flag_has_composite = !0,
-               .flag_has_svideo = !0,
-               .signal_routing_scheme = PVR2_ROUTING_SCHEME_AV400,
-};
-
-
-
-/*------------------------------------------------------------------------*/
-/* OnAir Creator */
-
-#ifdef CONFIG_VIDEO_PVRUSB2_DVB
-static struct lgdt330x_config pvr2_lgdt3303_config = {
-       .demod_address       = 0x0e,
-       .demod_chip          = LGDT3303,
-       .clock_polarity_flip = 1,
-};
-
-static int pvr2_lgdt3303_attach(struct pvr2_dvb_adapter *adap)
-{
-       adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3303_config,
-                             &adap->channel.hdw->i2c_adap);
-       if (adap->fe)
-               return 0;
-
-       return -EIO;
-}
-
-static int pvr2_lgh06xf_attach(struct pvr2_dvb_adapter *adap)
-{
-       dvb_attach(simple_tuner_attach, adap->fe,
-                  &adap->channel.hdw->i2c_adap, 0x61,
-                  TUNER_LG_TDVS_H06XF);
-
-       return 0;
-}
-
-static const struct pvr2_dvb_props pvr2_onair_creator_fe_props = {
-       .frontend_attach = pvr2_lgdt3303_attach,
-       .tuner_attach    = pvr2_lgh06xf_attach,
-};
-#endif
-
-static const struct pvr2_device_client_desc pvr2_cli_onair_creator[] = {
-       { .module_id = PVR2_CLIENT_ID_SAA7115 },
-       { .module_id = PVR2_CLIENT_ID_CS53L32A },
-       { .module_id = PVR2_CLIENT_ID_TUNER },
-};
-
-static const struct pvr2_device_desc pvr2_device_onair_creator = {
-               .description = "OnAir Creator Hybrid USB tuner",
-               .shortname = "oac",
-               .client_table.lst = pvr2_cli_onair_creator,
-               .client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_creator),
-               .default_tuner_type = TUNER_LG_TDVS_H06XF,
-               .flag_has_analogtuner = !0,
-               .flag_has_composite = !0,
-               .flag_has_svideo = !0,
-               .flag_digital_requires_cx23416 = !0,
-               .signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR,
-               .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
-               .default_std_mask = V4L2_STD_NTSC_M,
-#ifdef CONFIG_VIDEO_PVRUSB2_DVB
-               .dvb_props = &pvr2_onair_creator_fe_props,
-#endif
-};
-
-
-
-/*------------------------------------------------------------------------*/
-/* OnAir USB 2.0 */
-
-#ifdef CONFIG_VIDEO_PVRUSB2_DVB
-static struct lgdt330x_config pvr2_lgdt3302_config = {
-       .demod_address       = 0x0e,
-       .demod_chip          = LGDT3302,
-};
-
-static int pvr2_lgdt3302_attach(struct pvr2_dvb_adapter *adap)
-{
-       adap->fe = dvb_attach(lgdt330x_attach, &pvr2_lgdt3302_config,
-                             &adap->channel.hdw->i2c_adap);
-       if (adap->fe)
-               return 0;
-
-       return -EIO;
-}
-
-static int pvr2_fcv1236d_attach(struct pvr2_dvb_adapter *adap)
-{
-       dvb_attach(simple_tuner_attach, adap->fe,
-                  &adap->channel.hdw->i2c_adap, 0x61,
-                  TUNER_PHILIPS_FCV1236D);
-
-       return 0;
-}
-
-static const struct pvr2_dvb_props pvr2_onair_usb2_fe_props = {
-       .frontend_attach = pvr2_lgdt3302_attach,
-       .tuner_attach    = pvr2_fcv1236d_attach,
-};
-#endif
-
-static const struct pvr2_device_client_desc pvr2_cli_onair_usb2[] = {
-       { .module_id = PVR2_CLIENT_ID_SAA7115 },
-       { .module_id = PVR2_CLIENT_ID_CS53L32A },
-       { .module_id = PVR2_CLIENT_ID_TUNER },
-};
-
-static const struct pvr2_device_desc pvr2_device_onair_usb2 = {
-               .description = "OnAir USB2 Hybrid USB tuner",
-               .shortname = "oa2",
-               .client_table.lst = pvr2_cli_onair_usb2,
-               .client_table.cnt = ARRAY_SIZE(pvr2_cli_onair_usb2),
-               .default_tuner_type = TUNER_PHILIPS_FCV1236D,
-               .flag_has_analogtuner = !0,
-               .flag_has_composite = !0,
-               .flag_has_svideo = !0,
-               .flag_digital_requires_cx23416 = !0,
-               .signal_routing_scheme = PVR2_ROUTING_SCHEME_ONAIR,
-               .digital_control_scheme = PVR2_DIGITAL_SCHEME_ONAIR,
-               .default_std_mask = V4L2_STD_NTSC_M,
-#ifdef CONFIG_VIDEO_PVRUSB2_DVB
-               .dvb_props = &pvr2_onair_usb2_fe_props,
-#endif
-};
-
-
-
-/*------------------------------------------------------------------------*/
-/* Hauppauge PVR-USB2 Model 73xxx */
-
-#ifdef CONFIG_VIDEO_PVRUSB2_DVB
-static struct tda10048_config hauppauge_tda10048_config = {
-       .demod_address  = 0x10 >> 1,
-       .output_mode    = TDA10048_PARALLEL_OUTPUT,
-       .fwbulkwritelen = TDA10048_BULKWRITE_50,
-       .inversion      = TDA10048_INVERSION_ON,
-       .dtv6_if_freq_khz = TDA10048_IF_3300,
-       .dtv7_if_freq_khz = TDA10048_IF_3800,
-       .dtv8_if_freq_khz = TDA10048_IF_4300,
-       .clk_freq_khz   = TDA10048_CLK_16000,
-       .disable_gate_access = 1,
-};
-
-static struct tda829x_config tda829x_no_probe = {
-       .probe_tuner = TDA829X_DONT_PROBE,
-};
-
-static struct tda18271_std_map hauppauge_tda18271_dvbt_std_map = {
-        .dvbt_6   = { .if_freq = 3300, .agc_mode = 3, .std = 4,
-                      .if_lvl = 1, .rfagc_top = 0x37, },
-        .dvbt_7   = { .if_freq = 3800, .agc_mode = 3, .std = 5,
-                      .if_lvl = 1, .rfagc_top = 0x37, },
-        .dvbt_8   = { .if_freq = 4300, .agc_mode = 3, .std = 6,
-                      .if_lvl = 1, .rfagc_top = 0x37, },
-};
-
-static struct tda18271_config hauppauge_tda18271_dvb_config = {
-       .std_map = &hauppauge_tda18271_dvbt_std_map,
-       .gate    = TDA18271_GATE_ANALOG,
-       .output_opt = TDA18271_OUTPUT_LT_OFF,
-};
-
-static int pvr2_tda10048_attach(struct pvr2_dvb_adapter *adap)
-{
-       adap->fe = dvb_attach(tda10048_attach, &hauppauge_tda10048_config,
-                             &adap->channel.hdw->i2c_adap);
-       if (adap->fe)
-               return 0;
-
-       return -EIO;
-}
-
-static int pvr2_73xxx_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
-{
-       dvb_attach(tda829x_attach, adap->fe,
-                  &adap->channel.hdw->i2c_adap, 0x42,
-                  &tda829x_no_probe);
-       dvb_attach(tda18271_attach, adap->fe, 0x60,
-                  &adap->channel.hdw->i2c_adap,
-                  &hauppauge_tda18271_dvb_config);
-
-       return 0;
-}
-
-static const struct pvr2_dvb_props pvr2_73xxx_dvb_props = {
-       .frontend_attach = pvr2_tda10048_attach,
-       .tuner_attach    = pvr2_73xxx_tda18271_8295_attach,
-};
-#endif
-
-static const struct pvr2_device_client_desc pvr2_cli_73xxx[] = {
-       { .module_id = PVR2_CLIENT_ID_CX25840 },
-       { .module_id = PVR2_CLIENT_ID_TUNER,
-         .i2c_address_list = "\x42"},
-};
-
-#define PVR2_FIRMWARE_73xxx "v4l-pvrusb2-73xxx-01.fw"
-static const char *pvr2_fw1_names_73xxx[] = {
-               PVR2_FIRMWARE_73xxx,
-};
-
-static const struct pvr2_device_desc pvr2_device_73xxx = {
-               .description = "WinTV HVR-1900 Model 73xxx",
-               .shortname = "73xxx",
-               .client_table.lst = pvr2_cli_73xxx,
-               .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx),
-               .fx2_firmware.lst = pvr2_fw1_names_73xxx,
-               .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_73xxx),
-               .flag_has_cx25840 = !0,
-               .flag_has_hauppauge_rom = !0,
-               .flag_has_analogtuner = !0,
-               .flag_has_composite = !0,
-               .flag_has_svideo = !0,
-               .flag_fx2_16kb = !0,
-               .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
-               .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
-               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
-               .ir_scheme = PVR2_IR_SCHEME_ZILOG,
-#ifdef CONFIG_VIDEO_PVRUSB2_DVB
-               .dvb_props = &pvr2_73xxx_dvb_props,
-#endif
-};
-
-
-
-/*------------------------------------------------------------------------*/
-/* Hauppauge PVR-USB2 Model 75xxx */
-
-#ifdef CONFIG_VIDEO_PVRUSB2_DVB
-static struct s5h1409_config pvr2_s5h1409_config = {
-       .demod_address = 0x32 >> 1,
-       .output_mode   = S5H1409_PARALLEL_OUTPUT,
-       .gpio          = S5H1409_GPIO_OFF,
-       .qam_if        = 4000,
-       .inversion     = S5H1409_INVERSION_ON,
-       .status_mode   = S5H1409_DEMODLOCKING,
-};
-
-static struct s5h1411_config pvr2_s5h1411_config = {
-       .output_mode   = S5H1411_PARALLEL_OUTPUT,
-       .gpio          = S5H1411_GPIO_OFF,
-       .vsb_if        = S5H1411_IF_44000,
-       .qam_if        = S5H1411_IF_4000,
-       .inversion     = S5H1411_INVERSION_ON,
-       .status_mode   = S5H1411_DEMODLOCKING,
-};
-
-static struct tda18271_std_map hauppauge_tda18271_std_map = {
-       .atsc_6   = { .if_freq = 5380, .agc_mode = 3, .std = 3,
-                     .if_lvl = 6, .rfagc_top = 0x37, },
-       .qam_6    = { .if_freq = 4000, .agc_mode = 3, .std = 0,
-                     .if_lvl = 6, .rfagc_top = 0x37, },
-};
-
-static struct tda18271_config hauppauge_tda18271_config = {
-       .std_map = &hauppauge_tda18271_std_map,
-       .gate    = TDA18271_GATE_ANALOG,
-       .output_opt = TDA18271_OUTPUT_LT_OFF,
-};
-
-static int pvr2_s5h1409_attach(struct pvr2_dvb_adapter *adap)
-{
-       adap->fe = dvb_attach(s5h1409_attach, &pvr2_s5h1409_config,
-                             &adap->channel.hdw->i2c_adap);
-       if (adap->fe)
-               return 0;
-
-       return -EIO;
-}
-
-static int pvr2_s5h1411_attach(struct pvr2_dvb_adapter *adap)
-{
-       adap->fe = dvb_attach(s5h1411_attach, &pvr2_s5h1411_config,
-                             &adap->channel.hdw->i2c_adap);
-       if (adap->fe)
-               return 0;
-
-       return -EIO;
-}
-
-static int pvr2_tda18271_8295_attach(struct pvr2_dvb_adapter *adap)
-{
-       dvb_attach(tda829x_attach, adap->fe,
-                  &adap->channel.hdw->i2c_adap, 0x42,
-                  &tda829x_no_probe);
-       dvb_attach(tda18271_attach, adap->fe, 0x60,
-                  &adap->channel.hdw->i2c_adap,
-                  &hauppauge_tda18271_config);
-
-       return 0;
-}
-
-static const struct pvr2_dvb_props pvr2_750xx_dvb_props = {
-       .frontend_attach = pvr2_s5h1409_attach,
-       .tuner_attach    = pvr2_tda18271_8295_attach,
-};
-
-static const struct pvr2_dvb_props pvr2_751xx_dvb_props = {
-       .frontend_attach = pvr2_s5h1411_attach,
-       .tuner_attach    = pvr2_tda18271_8295_attach,
-};
-#endif
-
-#define PVR2_FIRMWARE_75xxx "v4l-pvrusb2-73xxx-01.fw"
-static const char *pvr2_fw1_names_75xxx[] = {
-               PVR2_FIRMWARE_75xxx,
-};
-
-static const struct pvr2_device_desc pvr2_device_750xx = {
-               .description = "WinTV HVR-1950 Model 750xx",
-               .shortname = "750xx",
-               .client_table.lst = pvr2_cli_73xxx,
-               .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx),
-               .fx2_firmware.lst = pvr2_fw1_names_75xxx,
-               .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
-               .flag_has_cx25840 = !0,
-               .flag_has_hauppauge_rom = !0,
-               .flag_has_analogtuner = !0,
-               .flag_has_composite = !0,
-               .flag_has_svideo = !0,
-               .flag_fx2_16kb = !0,
-               .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
-               .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
-               .default_std_mask = V4L2_STD_NTSC_M,
-               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
-               .ir_scheme = PVR2_IR_SCHEME_ZILOG,
-#ifdef CONFIG_VIDEO_PVRUSB2_DVB
-               .dvb_props = &pvr2_750xx_dvb_props,
-#endif
-};
-
-static const struct pvr2_device_desc pvr2_device_751xx = {
-               .description = "WinTV HVR-1950 Model 751xx",
-               .shortname = "751xx",
-               .client_table.lst = pvr2_cli_73xxx,
-               .client_table.cnt = ARRAY_SIZE(pvr2_cli_73xxx),
-               .fx2_firmware.lst = pvr2_fw1_names_75xxx,
-               .fx2_firmware.cnt = ARRAY_SIZE(pvr2_fw1_names_75xxx),
-               .flag_has_cx25840 = !0,
-               .flag_has_hauppauge_rom = !0,
-               .flag_has_analogtuner = !0,
-               .flag_has_composite = !0,
-               .flag_has_svideo = !0,
-               .flag_fx2_16kb = !0,
-               .signal_routing_scheme = PVR2_ROUTING_SCHEME_HAUPPAUGE,
-               .digital_control_scheme = PVR2_DIGITAL_SCHEME_HAUPPAUGE,
-               .default_std_mask = V4L2_STD_NTSC_M,
-               .led_scheme = PVR2_LED_SCHEME_HAUPPAUGE,
-               .ir_scheme = PVR2_IR_SCHEME_ZILOG,
-#ifdef CONFIG_VIDEO_PVRUSB2_DVB
-               .dvb_props = &pvr2_751xx_dvb_props,
-#endif
-};
-
-
-
-/*------------------------------------------------------------------------*/
-
-struct usb_device_id pvr2_device_table[] = {
-       { USB_DEVICE(0x2040, 0x2900),
-         .driver_info = (kernel_ulong_t)&pvr2_device_29xxx},
-       { USB_DEVICE(0x2040, 0x2950), /* Logically identical to 2900 */
-         .driver_info = (kernel_ulong_t)&pvr2_device_29xxx},
-       { USB_DEVICE(0x2040, 0x2400),
-         .driver_info = (kernel_ulong_t)&pvr2_device_24xxx},
-       { USB_DEVICE(0x1164, 0x0622),
-         .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2},
-       { USB_DEVICE(0x1164, 0x0602),
-         .driver_info = (kernel_ulong_t)&pvr2_device_gotview_2d},
-       { USB_DEVICE(0x11ba, 0x1003),
-         .driver_info = (kernel_ulong_t)&pvr2_device_onair_creator},
-       { USB_DEVICE(0x11ba, 0x1001),
-         .driver_info = (kernel_ulong_t)&pvr2_device_onair_usb2},
-       { USB_DEVICE(0x2040, 0x7300),
-         .driver_info = (kernel_ulong_t)&pvr2_device_73xxx},
-       { USB_DEVICE(0x2040, 0x7500),
-         .driver_info = (kernel_ulong_t)&pvr2_device_750xx},
-       { USB_DEVICE(0x2040, 0x7501),
-         .driver_info = (kernel_ulong_t)&pvr2_device_751xx},
-       { USB_DEVICE(0x0ccd, 0x0039),
-         .driver_info = (kernel_ulong_t)&pvr2_device_av400},
-       { }
-};
-
-MODULE_DEVICE_TABLE(usb, pvr2_device_table);
-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/video/pvrusb2/pvrusb2-devattr.h b/drivers/media/video/pvrusb2/pvrusb2-devattr.h
deleted file mode 100644 (file)
index 273c8d4..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifndef __PVRUSB2_DEVATTR_H
-#define __PVRUSB2_DEVATTR_H
-
-#include <linux/mod_devicetable.h>
-#include <linux/videodev2.h>
-#ifdef CONFIG_VIDEO_PVRUSB2_DVB
-#include "pvrusb2-dvb.h"
-#endif
-
-/*
-
-  This header defines structures used to describe attributes of a device.
-
-*/
-
-
-#define PVR2_CLIENT_ID_NULL 0
-#define PVR2_CLIENT_ID_MSP3400 1
-#define PVR2_CLIENT_ID_CX25840 2
-#define PVR2_CLIENT_ID_SAA7115 3
-#define PVR2_CLIENT_ID_TUNER 4
-#define PVR2_CLIENT_ID_CS53L32A 5
-#define PVR2_CLIENT_ID_WM8775 6
-#define PVR2_CLIENT_ID_DEMOD 7
-
-struct pvr2_device_client_desc {
-       /* One ovr PVR2_CLIENT_ID_xxxx */
-       unsigned char module_id;
-
-       /* Null-terminated array of I2C addresses to try in order
-          initialize the module.  It's safe to make this null terminated
-          since we're never going to encounter an i2c device with an
-          address of zero.  If this is a null pointer or zero-length,
-          then no I2C addresses have been specified, in which case we'll
-          try some compiled in defaults for now. */
-       unsigned char *i2c_address_list;
-};
-
-struct pvr2_device_client_table {
-       const struct pvr2_device_client_desc *lst;
-       unsigned char cnt;
-};
-
-
-struct pvr2_string_table {
-       const char **lst;
-       unsigned int cnt;
-};
-
-#define PVR2_ROUTING_SCHEME_HAUPPAUGE 0
-#define PVR2_ROUTING_SCHEME_GOTVIEW 1
-#define PVR2_ROUTING_SCHEME_ONAIR 2
-#define PVR2_ROUTING_SCHEME_AV400 3
-
-#define PVR2_DIGITAL_SCHEME_NONE 0
-#define PVR2_DIGITAL_SCHEME_HAUPPAUGE 1
-#define PVR2_DIGITAL_SCHEME_ONAIR 2
-
-#define PVR2_LED_SCHEME_NONE 0
-#define PVR2_LED_SCHEME_HAUPPAUGE 1
-
-#define PVR2_IR_SCHEME_NONE 0
-#define PVR2_IR_SCHEME_24XXX 1 /* FX2-controlled IR */
-#define PVR2_IR_SCHEME_ZILOG 2 /* HVR-1950 style (must be taken out of reset) */
-#define PVR2_IR_SCHEME_24XXX_MCE 3 /* 24xxx MCE device */
-#define PVR2_IR_SCHEME_29XXX 4 /* Original 29xxx device */
-
-/* This describes a particular hardware type (except for the USB device ID
-   which must live in a separate structure due to environmental
-   constraints).  See the top of pvrusb2-hdw.c for where this is
-   instantiated. */
-struct pvr2_device_desc {
-       /* Single line text description of hardware */
-       const char *description;
-
-       /* Single token identifier for hardware */
-       const char *shortname;
-
-       /* List of additional client modules we need to load */
-       struct pvr2_string_table client_modules;
-
-       /* List of defined client modules we need to load */
-       struct pvr2_device_client_table client_table;
-
-       /* List of FX2 firmware file names we should search; if empty then
-          FX2 firmware check / load is skipped and we assume the device
-          was initialized from internal ROM. */
-       struct pvr2_string_table fx2_firmware;
-
-#ifdef CONFIG_VIDEO_PVRUSB2_DVB
-       /* callback functions to handle attachment of digital tuner & demod */
-       const struct pvr2_dvb_props *dvb_props;
-
-#endif
-       /* Initial standard bits to use for this device, if not zero.
-          Anything set here is also implied as an available standard.
-          Note: This is ignored if overridden on the module load line via
-          the video_std module option. */
-       v4l2_std_id default_std_mask;
-
-       /* V4L tuner type ID to use with this device (only used if the
-          driver could not discover the type any other way). */
-       int default_tuner_type;
-
-       /* Signal routing scheme used by device, contains one of
-          PVR2_ROUTING_SCHEME_XXX.  Schemes have to be defined as we
-          encounter them.  This is an arbitrary integer scheme id; its
-          meaning is contained entirely within the driver and is
-          interpreted by logic which must send commands to the chip-level
-          drivers (search for things which touch this field). */
-       unsigned char signal_routing_scheme;
-
-       /* Indicates scheme for controlling device's LED (if any).  The
-          driver will turn on the LED when streaming is underway.  This
-          contains one of PVR2_LED_SCHEME_XXX. */
-       unsigned char led_scheme;
-
-       /* Control scheme to use if there is a digital tuner.  This
-          contains one of PVR2_DIGITAL_SCHEME_XXX.  This is an arbitrary
-          integer scheme id; its meaning is contained entirely within the
-          driver and is interpreted by logic which must control the
-          streaming pathway (search for things which touch this field). */
-       unsigned char digital_control_scheme;
-
-       /* If set, we don't bother trying to load cx23416 firmware. */
-       unsigned int flag_skip_cx23416_firmware:1;
-
-       /* If set, the encoder must be healthy in order for digital mode to
-          work (otherwise we assume that digital streaming will work even
-          if we fail to locate firmware for the encoder).  If the device
-          doesn't support digital streaming then this flag has no
-          effect. */
-       unsigned int flag_digital_requires_cx23416:1;
-
-       /* Device has a hauppauge eeprom which we can interrogate. */
-       unsigned int flag_has_hauppauge_rom:1;
-
-       /* Device does not require a powerup command to be issued. */
-       unsigned int flag_no_powerup:1;
-
-       /* Device has a cx25840 - this enables special additional logic to
-          handle it. */
-       unsigned int flag_has_cx25840:1;
-
-       /* Device has a wm8775 - this enables special additional logic to
-          ensure that it is found. */
-       unsigned int flag_has_wm8775:1;
-
-       /* Indicate IR scheme of hardware.  If not set, then it is assumed
-          that IR can work without any help from the driver. */
-       unsigned int ir_scheme:3;
-
-       /* These bits define which kinds of sources the device can handle.
-          Note: Digital tuner presence is inferred by the
-          digital_control_scheme enumeration. */
-       unsigned int flag_has_fmradio:1;       /* Has FM radio receiver */
-       unsigned int flag_has_analogtuner:1;   /* Has analog tuner */
-       unsigned int flag_has_composite:1;     /* Has composite input */
-       unsigned int flag_has_svideo:1;        /* Has s-video input */
-       unsigned int flag_fx2_16kb:1;          /* 16KB FX2 firmware OK here */
-
-       /* If this driver is considered experimental, i.e. not all aspects
-          are working correctly and/or it is untested, mark that fact
-          with this flag. */
-       unsigned int flag_is_experimental:1;
-};
-
-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/video/pvrusb2/pvrusb2-dvb.c b/drivers/media/video/pvrusb2/pvrusb2-dvb.c
deleted file mode 100644 (file)
index 8c95793..0000000
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- *  pvrusb2-dvb.c - linux-dvb api interface to the pvrusb2 driver.
- *
- *  Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/kthread.h>
-#include <linux/freezer.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include "dvbdev.h"
-#include "pvrusb2-debug.h"
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-hdw.h"
-#include "pvrusb2-io.h"
-#include "pvrusb2-dvb.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int pvr2_dvb_feed_func(struct pvr2_dvb_adapter *adap)
-{
-       int ret;
-       unsigned int count;
-       struct pvr2_buffer *bp;
-       struct pvr2_stream *stream;
-
-       pvr2_trace(PVR2_TRACE_DVB_FEED, "dvb feed thread started");
-       set_freezable();
-
-       stream = adap->channel.stream->stream;
-
-       for (;;) {
-               if (kthread_should_stop()) break;
-
-               /* Not sure about this... */
-               try_to_freeze();
-
-               bp = pvr2_stream_get_ready_buffer(stream);
-               if (bp != NULL) {
-                       count = pvr2_buffer_get_count(bp);
-                       if (count) {
-                               dvb_dmx_swfilter(
-                                       &adap->demux,
-                                       adap->buffer_storage[
-                                           pvr2_buffer_get_id(bp)],
-                                       count);
-                       } else {
-                               ret = pvr2_buffer_get_status(bp);
-                               if (ret < 0) break;
-                       }
-                       ret = pvr2_buffer_queue(bp);
-                       if (ret < 0) break;
-
-                       /* Since we know we did something to a buffer,
-                          just go back and try again.  No point in
-                          blocking unless we really ran out of
-                          buffers to process. */
-                       continue;
-               }
-
-
-               /* Wait until more buffers become available or we're
-                  told not to wait any longer. */
-               ret = wait_event_interruptible(
-                   adap->buffer_wait_data,
-                   (pvr2_stream_get_ready_count(stream) > 0) ||
-                   kthread_should_stop());
-               if (ret < 0) break;
-       }
-
-       /* If we get here and ret is < 0, then an error has occurred.
-          Probably would be a good idea to communicate that to DVB core... */
-
-       pvr2_trace(PVR2_TRACE_DVB_FEED, "dvb feed thread stopped");
-
-       return 0;
-}
-
-static int pvr2_dvb_feed_thread(void *data)
-{
-       int stat = pvr2_dvb_feed_func(data);
-       /* from videobuf-dvb.c: */
-       while (!kthread_should_stop()) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule();
-       }
-       return stat;
-}
-
-static void pvr2_dvb_notify(struct pvr2_dvb_adapter *adap)
-{
-       wake_up(&adap->buffer_wait_data);
-}
-
-static void pvr2_dvb_stream_end(struct pvr2_dvb_adapter *adap)
-{
-       unsigned int idx;
-       struct pvr2_stream *stream;
-
-       if (adap->thread) {
-               kthread_stop(adap->thread);
-               adap->thread = NULL;
-       }
-
-       if (adap->channel.stream) {
-               stream = adap->channel.stream->stream;
-       } else {
-               stream = NULL;
-       }
-       if (stream) {
-               pvr2_hdw_set_streaming(adap->channel.hdw, 0);
-               pvr2_stream_set_callback(stream, NULL, NULL);
-               pvr2_stream_kill(stream);
-               pvr2_stream_set_buffer_count(stream, 0);
-               pvr2_channel_claim_stream(&adap->channel, NULL);
-       }
-
-       if (adap->stream_run) {
-               for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
-                       if (!(adap->buffer_storage[idx])) continue;
-                       kfree(adap->buffer_storage[idx]);
-                       adap->buffer_storage[idx] = NULL;
-               }
-               adap->stream_run = 0;
-       }
-}
-
-static int pvr2_dvb_stream_do_start(struct pvr2_dvb_adapter *adap)
-{
-       struct pvr2_context *pvr = adap->channel.mc_head;
-       unsigned int idx;
-       int ret;
-       struct pvr2_buffer *bp;
-       struct pvr2_stream *stream = NULL;
-
-       if (adap->stream_run) return -EIO;
-
-       ret = pvr2_channel_claim_stream(&adap->channel, &pvr->video_stream);
-       /* somebody else already has the stream */
-       if (ret < 0) return ret;
-
-       stream = adap->channel.stream->stream;
-
-       for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
-               adap->buffer_storage[idx] = kmalloc(PVR2_DVB_BUFFER_SIZE,
-                                                   GFP_KERNEL);
-               if (!(adap->buffer_storage[idx])) return -ENOMEM;
-       }
-
-       pvr2_stream_set_callback(pvr->video_stream.stream,
-                                (pvr2_stream_callback) pvr2_dvb_notify, adap);
-
-       ret = pvr2_stream_set_buffer_count(stream, PVR2_DVB_BUFFER_COUNT);
-       if (ret < 0) return ret;
-
-       for (idx = 0; idx < PVR2_DVB_BUFFER_COUNT; idx++) {
-               bp = pvr2_stream_get_buffer(stream, idx);
-               pvr2_buffer_set_buffer(bp,
-                                      adap->buffer_storage[idx],
-                                      PVR2_DVB_BUFFER_SIZE);
-       }
-
-       ret = pvr2_hdw_set_streaming(adap->channel.hdw, 1);
-       if (ret < 0) return ret;
-
-       while ((bp = pvr2_stream_get_idle_buffer(stream)) != NULL) {
-               ret = pvr2_buffer_queue(bp);
-               if (ret < 0) return ret;
-       }
-
-       adap->thread = kthread_run(pvr2_dvb_feed_thread, adap, "pvrusb2-dvb");
-
-       if (IS_ERR(adap->thread)) {
-               ret = PTR_ERR(adap->thread);
-               adap->thread = NULL;
-               return ret;
-       }
-
-       adap->stream_run = !0;
-
-       return 0;
-}
-
-static int pvr2_dvb_stream_start(struct pvr2_dvb_adapter *adap)
-{
-       int ret = pvr2_dvb_stream_do_start(adap);
-       if (ret < 0) pvr2_dvb_stream_end(adap);
-       return ret;
-}
-
-static int pvr2_dvb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
-{
-       struct pvr2_dvb_adapter *adap = dvbdmxfeed->demux->priv;
-       int ret = 0;
-
-       if (adap == NULL) return -ENODEV;
-
-       mutex_lock(&adap->lock);
-       do {
-               if (onoff) {
-                       if (!adap->feedcount) {
-                               pvr2_trace(PVR2_TRACE_DVB_FEED,
-                                          "start feeding demux");
-                               ret = pvr2_dvb_stream_start(adap);
-                               if (ret < 0) break;
-                       }
-                       (adap->feedcount)++;
-               } else if (adap->feedcount > 0) {
-                       (adap->feedcount)--;
-                       if (!adap->feedcount) {
-                               pvr2_trace(PVR2_TRACE_DVB_FEED,
-                                          "stop feeding demux");
-                               pvr2_dvb_stream_end(adap);
-                       }
-               }
-       } while (0);
-       mutex_unlock(&adap->lock);
-
-       return ret;
-}
-
-static int pvr2_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-       pvr2_trace(PVR2_TRACE_DVB_FEED, "start pid: 0x%04x", dvbdmxfeed->pid);
-       return pvr2_dvb_ctrl_feed(dvbdmxfeed, 1);
-}
-
-static int pvr2_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-       pvr2_trace(PVR2_TRACE_DVB_FEED, "stop pid: 0x%04x", dvbdmxfeed->pid);
-       return pvr2_dvb_ctrl_feed(dvbdmxfeed, 0);
-}
-
-static int pvr2_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
-{
-       struct pvr2_dvb_adapter *adap = fe->dvb->priv;
-       return pvr2_channel_limit_inputs(
-           &adap->channel,
-           (acquire ? (1 << PVR2_CVAL_INPUT_DTV) : 0));
-}
-
-static int pvr2_dvb_adapter_init(struct pvr2_dvb_adapter *adap)
-{
-       int ret;
-
-       ret = dvb_register_adapter(&adap->dvb_adap, "pvrusb2-dvb",
-                                  THIS_MODULE/*&hdw->usb_dev->owner*/,
-                                  &adap->channel.hdw->usb_dev->dev,
-                                  adapter_nr);
-       if (ret < 0) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "dvb_register_adapter failed: error %d", ret);
-               goto err;
-       }
-       adap->dvb_adap.priv = adap;
-
-       adap->demux.dmx.capabilities = DMX_TS_FILTERING |
-                                      DMX_SECTION_FILTERING |
-                                      DMX_MEMORY_BASED_FILTERING;
-       adap->demux.priv             = adap;
-       adap->demux.filternum        = 256;
-       adap->demux.feednum          = 256;
-       adap->demux.start_feed       = pvr2_dvb_start_feed;
-       adap->demux.stop_feed        = pvr2_dvb_stop_feed;
-       adap->demux.write_to_decoder = NULL;
-
-       ret = dvb_dmx_init(&adap->demux);
-       if (ret < 0) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "dvb_dmx_init failed: error %d", ret);
-               goto err_dmx;
-       }
-
-       adap->dmxdev.filternum       = adap->demux.filternum;
-       adap->dmxdev.demux           = &adap->demux.dmx;
-       adap->dmxdev.capabilities    = 0;
-
-       ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
-       if (ret < 0) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "dvb_dmxdev_init failed: error %d", ret);
-               goto err_dmx_dev;
-       }
-
-       dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
-
-       return 0;
-
-err_dmx_dev:
-       dvb_dmx_release(&adap->demux);
-err_dmx:
-       dvb_unregister_adapter(&adap->dvb_adap);
-err:
-       return ret;
-}
-
-static int pvr2_dvb_adapter_exit(struct pvr2_dvb_adapter *adap)
-{
-       pvr2_trace(PVR2_TRACE_INFO, "unregistering DVB devices");
-       dvb_net_release(&adap->dvb_net);
-       adap->demux.dmx.close(&adap->demux.dmx);
-       dvb_dmxdev_release(&adap->dmxdev);
-       dvb_dmx_release(&adap->demux);
-       dvb_unregister_adapter(&adap->dvb_adap);
-       return 0;
-}
-
-static int pvr2_dvb_frontend_init(struct pvr2_dvb_adapter *adap)
-{
-       struct pvr2_hdw *hdw = adap->channel.hdw;
-       const struct pvr2_dvb_props *dvb_props = hdw->hdw_desc->dvb_props;
-       int ret = 0;
-
-       if (dvb_props == NULL) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS, "fe_props not defined!");
-               return -EINVAL;
-       }
-
-       ret = pvr2_channel_limit_inputs(
-           &adap->channel,
-           (1 << PVR2_CVAL_INPUT_DTV));
-       if (ret) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "failed to grab control of dtv input (code=%d)",
-                   ret);
-               return ret;
-       }
-
-       if (dvb_props->frontend_attach == NULL) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "frontend_attach not defined!");
-               ret = -EINVAL;
-               goto done;
-       }
-
-       if ((dvb_props->frontend_attach(adap) == 0) && (adap->fe)) {
-
-               if (dvb_register_frontend(&adap->dvb_adap, adap->fe)) {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "frontend registration failed!");
-                       dvb_frontend_detach(adap->fe);
-                       adap->fe = NULL;
-                       ret = -ENODEV;
-                       goto done;
-               }
-
-               if (dvb_props->tuner_attach)
-                       dvb_props->tuner_attach(adap);
-
-               if (adap->fe->ops.analog_ops.standby)
-                       adap->fe->ops.analog_ops.standby(adap->fe);
-
-               /* Ensure all frontends negotiate bus access */
-               adap->fe->ops.ts_bus_ctrl = pvr2_dvb_bus_ctrl;
-
-       } else {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "no frontend was attached!");
-               ret = -ENODEV;
-               return ret;
-       }
-
- done:
-       pvr2_channel_limit_inputs(&adap->channel, 0);
-       return ret;
-}
-
-static int pvr2_dvb_frontend_exit(struct pvr2_dvb_adapter *adap)
-{
-       if (adap->fe != NULL) {
-               dvb_unregister_frontend(adap->fe);
-               dvb_frontend_detach(adap->fe);
-       }
-       return 0;
-}
-
-static void pvr2_dvb_destroy(struct pvr2_dvb_adapter *adap)
-{
-       pvr2_dvb_stream_end(adap);
-       pvr2_dvb_frontend_exit(adap);
-       pvr2_dvb_adapter_exit(adap);
-       pvr2_channel_done(&adap->channel);
-       kfree(adap);
-}
-
-static void pvr2_dvb_internal_check(struct pvr2_channel *chp)
-{
-       struct pvr2_dvb_adapter *adap;
-       adap = container_of(chp, struct pvr2_dvb_adapter, channel);
-       if (!adap->channel.mc_head->disconnect_flag) return;
-       pvr2_dvb_destroy(adap);
-}
-
-struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr)
-{
-       int ret = 0;
-       struct pvr2_dvb_adapter *adap;
-       if (!pvr->hdw->hdw_desc->dvb_props) {
-               /* Device lacks a digital interface so don't set up
-                  the DVB side of the driver either.  For now. */
-               return NULL;
-       }
-       adap = kzalloc(sizeof(*adap), GFP_KERNEL);
-       if (!adap) return adap;
-       pvr2_channel_init(&adap->channel, pvr);
-       adap->channel.check_func = pvr2_dvb_internal_check;
-       init_waitqueue_head(&adap->buffer_wait_data);
-       mutex_init(&adap->lock);
-       ret = pvr2_dvb_adapter_init(adap);
-       if (ret < 0) goto fail1;
-       ret = pvr2_dvb_frontend_init(adap);
-       if (ret < 0) goto fail2;
-       return adap;
-
-fail2:
-       pvr2_dvb_adapter_exit(adap);
-fail1:
-       pvr2_channel_done(&adap->channel);
-       return NULL;
-}
-
diff --git a/drivers/media/video/pvrusb2/pvrusb2-dvb.h b/drivers/media/video/pvrusb2/pvrusb2-dvb.h
deleted file mode 100644 (file)
index 884ff91..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef __PVRUSB2_DVB_H__
-#define __PVRUSB2_DVB_H__
-
-#include "dvb_frontend.h"
-#include "dvb_demux.h"
-#include "dvb_net.h"
-#include "dmxdev.h"
-#include "pvrusb2-context.h"
-
-#define PVR2_DVB_BUFFER_COUNT 32
-#define PVR2_DVB_BUFFER_SIZE PAGE_ALIGN(0x4000)
-
-struct pvr2_dvb_adapter {
-       struct pvr2_channel     channel;
-
-       struct dvb_adapter      dvb_adap;
-       struct dmxdev           dmxdev;
-       struct dvb_demux        demux;
-       struct dvb_net          dvb_net;
-       struct dvb_frontend     *fe;
-
-       int                     feedcount;
-       int                     max_feed_count;
-
-       struct task_struct      *thread;
-       struct mutex            lock;
-
-       unsigned int            stream_run:1;
-
-       wait_queue_head_t       buffer_wait_data;
-       char                    *buffer_storage[PVR2_DVB_BUFFER_COUNT];
-};
-
-struct pvr2_dvb_props {
-       int (*frontend_attach) (struct pvr2_dvb_adapter *);
-       int (*tuner_attach) (struct pvr2_dvb_adapter *);
-};
-
-struct pvr2_dvb_adapter *pvr2_dvb_create(struct pvr2_context *pvr);
-
-#endif /* __PVRUSB2_DVB_H__ */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
deleted file mode 100644 (file)
index 9515f3a..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/slab.h>
-#include "pvrusb2-eeprom.h"
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-
-#define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__)
-
-
-
-/*
-
-   Read and analyze data in the eeprom.  Use tveeprom to figure out
-   the packet structure, since this is another Hauppauge device and
-   internally it has a family resemblance to ivtv-type devices
-
-*/
-
-#include <media/tveeprom.h>
-
-/* We seem to only be interested in the last 128 bytes of the EEPROM */
-#define EEPROM_SIZE 128
-
-/* Grab EEPROM contents, needed for direct method. */
-static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw)
-{
-       struct i2c_msg msg[2];
-       u8 *eeprom;
-       u8 iadd[2];
-       u8 addr;
-       u16 eepromSize;
-       unsigned int offs;
-       int ret;
-       int mode16 = 0;
-       unsigned pcnt,tcnt;
-       eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL);
-       if (!eeprom) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Failed to allocate memory"
-                          " required to read eeprom");
-               return NULL;
-       }
-
-       trace_eeprom("Value for eeprom addr from controller was 0x%x",
-                    hdw->eeprom_addr);
-       addr = hdw->eeprom_addr;
-       /* Seems that if the high bit is set, then the *real* eeprom
-          address is shifted right now bit position (noticed this in
-          newer PVR USB2 hardware) */
-       if (addr & 0x80) addr >>= 1;
-
-       /* FX2 documentation states that a 16bit-addressed eeprom is
-          expected if the I2C address is an odd number (yeah, this is
-          strange but it's what they do) */
-       mode16 = (addr & 1);
-       eepromSize = (mode16 ? 4096 : 256);
-       trace_eeprom("Examining %d byte eeprom at location 0x%x"
-                    " using %d bit addressing",eepromSize,addr,
-                    mode16 ? 16 : 8);
-
-       msg[0].addr = addr;
-       msg[0].flags = 0;
-       msg[0].len = mode16 ? 2 : 1;
-       msg[0].buf = iadd;
-       msg[1].addr = addr;
-       msg[1].flags = I2C_M_RD;
-
-       /* We have to do the actual eeprom data fetch ourselves, because
-          (1) we're only fetching part of the eeprom, and (2) if we were
-          getting the whole thing our I2C driver can't grab it in one
-          pass - which is what tveeprom is otherwise going to attempt */
-       memset(eeprom,0,EEPROM_SIZE);
-       for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) {
-               pcnt = 16;
-               if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt;
-               offs = tcnt + (eepromSize - EEPROM_SIZE);
-               if (mode16) {
-                       iadd[0] = offs >> 8;
-                       iadd[1] = offs;
-               } else {
-                       iadd[0] = offs;
-               }
-               msg[1].len = pcnt;
-               msg[1].buf = eeprom+tcnt;
-               if ((ret = i2c_transfer(&hdw->i2c_adap,
-                                       msg,ARRAY_SIZE(msg))) != 2) {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "eeprom fetch set offs err=%d",ret);
-                       kfree(eeprom);
-                       return NULL;
-               }
-       }
-       return eeprom;
-}
-
-
-/* Directly call eeprom analysis function within tveeprom. */
-int pvr2_eeprom_analyze(struct pvr2_hdw *hdw)
-{
-       u8 *eeprom;
-       struct tveeprom tvdata;
-
-       memset(&tvdata,0,sizeof(tvdata));
-
-       eeprom = pvr2_eeprom_fetch(hdw);
-       if (!eeprom) return -EINVAL;
-
-       {
-               struct i2c_client fake_client;
-               /* Newer version expects a useless client interface */
-               fake_client.addr = hdw->eeprom_addr;
-               fake_client.adapter = &hdw->i2c_adap;
-               tveeprom_hauppauge_analog(&fake_client,&tvdata,eeprom);
-       }
-
-       trace_eeprom("eeprom assumed v4l tveeprom module");
-       trace_eeprom("eeprom direct call results:");
-       trace_eeprom("has_radio=%d",tvdata.has_radio);
-       trace_eeprom("tuner_type=%d",tvdata.tuner_type);
-       trace_eeprom("tuner_formats=0x%x",tvdata.tuner_formats);
-       trace_eeprom("audio_processor=%d",tvdata.audio_processor);
-       trace_eeprom("model=%d",tvdata.model);
-       trace_eeprom("revision=%d",tvdata.revision);
-       trace_eeprom("serial_number=%d",tvdata.serial_number);
-       trace_eeprom("rev_str=%s",tvdata.rev_str);
-       hdw->tuner_type = tvdata.tuner_type;
-       hdw->tuner_updated = !0;
-       hdw->serial_number = tvdata.serial_number;
-       hdw->std_mask_eeprom = tvdata.tuner_formats;
-
-       kfree(eeprom);
-
-       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/video/pvrusb2/pvrusb2-eeprom.h b/drivers/media/video/pvrusb2/pvrusb2-eeprom.h
deleted file mode 100644 (file)
index cca3216..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef __PVRUSB2_EEPROM_H
-#define __PVRUSB2_EEPROM_H
-
-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/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
deleted file mode 100644 (file)
index e046fda..0000000
+++ /dev/null
@@ -1,552 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/device.h>   // for linux/firmware.h
-#include <linux/firmware.h>
-#include "pvrusb2-util.h"
-#include "pvrusb2-encoder.h"
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-#include "pvrusb2-fx2-cmd.h"
-
-
-
-/* Firmware mailbox flags - definitions found from ivtv */
-#define IVTV_MBOX_FIRMWARE_DONE 0x00000004
-#define IVTV_MBOX_DRIVER_DONE 0x00000002
-#define IVTV_MBOX_DRIVER_BUSY 0x00000001
-
-#define MBOX_BASE 0x44
-
-
-static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
-                                   unsigned int offs,
-                                   const u32 *data, unsigned int dlen)
-{
-       unsigned int idx,addr;
-       unsigned int bAddr;
-       int ret;
-       unsigned int chunkCnt;
-
-       /*
-
-       Format: First byte must be 0x01.  Remaining 32 bit words are
-       spread out into chunks of 7 bytes each, with the first 4 bytes
-       being the data word (little endian), and the next 3 bytes
-       being the address where that data word is to be written (big
-       endian).  Repeat request for additional words, with offset
-       adjusted accordingly.
-
-       */
-       while (dlen) {
-               chunkCnt = 8;
-               if (chunkCnt > dlen) chunkCnt = dlen;
-               memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
-               bAddr = 0;
-               hdw->cmd_buffer[bAddr++] = FX2CMD_MEM_WRITE_DWORD;
-               for (idx = 0; idx < chunkCnt; idx++) {
-                       addr = idx + offs;
-                       hdw->cmd_buffer[bAddr+6] = (addr & 0xffu);
-                       hdw->cmd_buffer[bAddr+5] = ((addr>>8) & 0xffu);
-                       hdw->cmd_buffer[bAddr+4] = ((addr>>16) & 0xffu);
-                       PVR2_DECOMPOSE_LE(hdw->cmd_buffer, bAddr,data[idx]);
-                       bAddr += 7;
-               }
-               ret = pvr2_send_request(hdw,
-                                       hdw->cmd_buffer,1+(chunkCnt*7),
-                                       NULL,0);
-               if (ret) return ret;
-               data += chunkCnt;
-               dlen -= chunkCnt;
-               offs += chunkCnt;
-       }
-
-       return 0;
-}
-
-
-static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,
-                                  unsigned int offs,
-                                  u32 *data, unsigned int dlen)
-{
-       unsigned int idx;
-       int ret;
-       unsigned int chunkCnt;
-
-       /*
-
-       Format: First byte must be 0x02 (status check) or 0x28 (read
-       back block of 32 bit words).  Next 6 bytes must be zero,
-       followed by a single byte of MBOX_BASE+offset for portion to
-       be read.  Returned data is packed set of 32 bits words that
-       were read.
-
-       */
-
-       while (dlen) {
-               chunkCnt = 16;
-               if (chunkCnt > dlen) chunkCnt = dlen;
-               if (chunkCnt < 16) chunkCnt = 1;
-               hdw->cmd_buffer[0] =
-                       ((chunkCnt == 1) ?
-                        FX2CMD_MEM_READ_DWORD : FX2CMD_MEM_READ_64BYTES);
-               hdw->cmd_buffer[1] = 0;
-               hdw->cmd_buffer[2] = 0;
-               hdw->cmd_buffer[3] = 0;
-               hdw->cmd_buffer[4] = 0;
-               hdw->cmd_buffer[5] = ((offs>>16) & 0xffu);
-               hdw->cmd_buffer[6] = ((offs>>8) & 0xffu);
-               hdw->cmd_buffer[7] = (offs & 0xffu);
-               ret = pvr2_send_request(hdw,
-                                       hdw->cmd_buffer,8,
-                                       hdw->cmd_buffer,
-                                       (chunkCnt == 1 ? 4 : 16 * 4));
-               if (ret) return ret;
-
-               for (idx = 0; idx < chunkCnt; idx++) {
-                       data[idx] = PVR2_COMPOSE_LE(hdw->cmd_buffer,idx*4);
-               }
-               data += chunkCnt;
-               dlen -= chunkCnt;
-               offs += chunkCnt;
-       }
-
-       return 0;
-}
-
-
-/* This prototype is set up to be compatible with the
-   cx2341x_mbox_func prototype in cx2341x.h, which should be in
-   kernels 2.6.18 or later.  We do this so that we can enable
-   cx2341x.ko to write to our encoder (by handing it a pointer to this
-   function).  For earlier kernels this doesn't really matter. */
-static int pvr2_encoder_cmd(void *ctxt,
-                           u32 cmd,
-                           int arg_cnt_send,
-                           int arg_cnt_recv,
-                           u32 *argp)
-{
-       unsigned int poll_count;
-       unsigned int try_count = 0;
-       int retry_flag;
-       int ret = 0;
-       unsigned int idx;
-       /* These sizes look to be limited by the FX2 firmware implementation */
-       u32 wrData[16];
-       u32 rdData[16];
-       struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt;
-
-
-       /*
-
-       The encoder seems to speak entirely using blocks 32 bit words.
-       In ivtv driver terms, this is a mailbox at MBOX_BASE which we
-       populate with data and watch what the hardware does with it.
-       The first word is a set of flags used to control the
-       transaction, the second word is the command to execute, the
-       third byte is zero (ivtv driver suggests that this is some
-       kind of return value), and the fourth byte is a specified
-       timeout (windows driver always uses 0x00060000 except for one
-       case when it is zero).  All successive words are the argument
-       words for the command.
-
-       First, write out the entire set of words, with the first word
-       being zero.
-
-       Next, write out just the first word again, but set it to
-       IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which
-       probably means "go").
-
-       Next, read back the return count words.  Check the first word,
-       which should have IVTV_MBOX_FIRMWARE_DONE set.  If however
-       that bit is not set, then the command isn't done so repeat the
-       read until it is set.
-
-       Finally, write out just the first word again, but set it to
-       0x0 this time (which probably means "idle").
-
-       */
-
-       if (arg_cnt_send > (ARRAY_SIZE(wrData) - 4)) {
-               pvr2_trace(
-                       PVR2_TRACE_ERROR_LEGS,
-                       "Failed to write cx23416 command"
-                       " - too many input arguments"
-                       " (was given %u limit %lu)",
-                       arg_cnt_send, (long unsigned) ARRAY_SIZE(wrData) - 4);
-               return -EINVAL;
-       }
-
-       if (arg_cnt_recv > (ARRAY_SIZE(rdData) - 4)) {
-               pvr2_trace(
-                       PVR2_TRACE_ERROR_LEGS,
-                       "Failed to write cx23416 command"
-                       " - too many return arguments"
-                       " (was given %u limit %lu)",
-                       arg_cnt_recv, (long unsigned) ARRAY_SIZE(rdData) - 4);
-               return -EINVAL;
-       }
-
-
-       LOCK_TAKE(hdw->ctl_lock); do {
-
-               if (!hdw->state_encoder_ok) {
-                       ret = -EIO;
-                       break;
-               }
-
-               retry_flag = 0;
-               try_count++;
-               ret = 0;
-               wrData[0] = 0;
-               wrData[1] = cmd;
-               wrData[2] = 0;
-               wrData[3] = 0x00060000;
-               for (idx = 0; idx < arg_cnt_send; idx++) {
-                       wrData[idx+4] = argp[idx];
-               }
-               for (; idx < ARRAY_SIZE(wrData) - 4; idx++) {
-                       wrData[idx+4] = 0;
-               }
-
-               ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,idx);
-               if (ret) break;
-               wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
-               ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
-               if (ret) break;
-               poll_count = 0;
-               while (1) {
-                       poll_count++;
-                       ret = pvr2_encoder_read_words(hdw,MBOX_BASE,rdData,
-                                                     arg_cnt_recv+4);
-                       if (ret) {
-                               break;
-                       }
-                       if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
-                               break;
-                       }
-                       if (rdData[0] && (poll_count < 1000)) continue;
-                       if (!rdData[0]) {
-                               retry_flag = !0;
-                               pvr2_trace(
-                                       PVR2_TRACE_ERROR_LEGS,
-                                       "Encoder timed out waiting for us"
-                                       "; arranging to retry");
-                       } else {
-                               pvr2_trace(
-                                       PVR2_TRACE_ERROR_LEGS,
-                                       "***WARNING*** device's encoder"
-                                       " appears to be stuck"
-                                       " (status=0x%08x)",rdData[0]);
-                       }
-                       pvr2_trace(
-                               PVR2_TRACE_ERROR_LEGS,
-                               "Encoder command: 0x%02x",cmd);
-                       for (idx = 4; idx < arg_cnt_send; idx++) {
-                               pvr2_trace(
-                                       PVR2_TRACE_ERROR_LEGS,
-                                       "Encoder arg%d: 0x%08x",
-                                       idx-3,wrData[idx]);
-                       }
-                       ret = -EBUSY;
-                       break;
-               }
-               if (retry_flag) {
-                       if (try_count < 20) continue;
-                       pvr2_trace(
-                               PVR2_TRACE_ERROR_LEGS,
-                               "Too many retries...");
-                       ret = -EBUSY;
-               }
-               if (ret) {
-                       del_timer_sync(&hdw->encoder_run_timer);
-                       hdw->state_encoder_ok = 0;
-                       pvr2_trace(PVR2_TRACE_STBITS,
-                                  "State bit %s <-- %s",
-                                  "state_encoder_ok",
-                                  (hdw->state_encoder_ok ? "true" : "false"));
-                       if (hdw->state_encoder_runok) {
-                               hdw->state_encoder_runok = 0;
-                               pvr2_trace(PVR2_TRACE_STBITS,
-                                  "State bit %s <-- %s",
-                                          "state_encoder_runok",
-                                          (hdw->state_encoder_runok ?
-                                           "true" : "false"));
-                       }
-                       pvr2_trace(
-                               PVR2_TRACE_ERROR_LEGS,
-                               "Giving up on command."
-                               "  This is normally recovered via a firmware"
-                               " reload and re-initialization; concern"
-                               " is only warranted if this happens repeatedly"
-                               " and rapidly.");
-                       break;
-               }
-               wrData[0] = 0x7;
-               for (idx = 0; idx < arg_cnt_recv; idx++) {
-                       argp[idx] = rdData[idx+4];
-               }
-
-               wrData[0] = 0x0;
-               ret = pvr2_encoder_write_words(hdw,MBOX_BASE,wrData,1);
-               if (ret) break;
-
-       } while(0); LOCK_GIVE(hdw->ctl_lock);
-
-       return ret;
-}
-
-
-static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd,
-                            int args, ...)
-{
-       va_list vl;
-       unsigned int idx;
-       u32 data[12];
-
-       if (args > ARRAY_SIZE(data)) {
-               pvr2_trace(
-                       PVR2_TRACE_ERROR_LEGS,
-                       "Failed to write cx23416 command"
-                       " - too many arguments"
-                       " (was given %u limit %lu)",
-                       args, (long unsigned) ARRAY_SIZE(data));
-               return -EINVAL;
-       }
-
-       va_start(vl, args);
-       for (idx = 0; idx < args; idx++) {
-               data[idx] = va_arg(vl, u32);
-       }
-       va_end(vl);
-
-       return pvr2_encoder_cmd(hdw,cmd,args,0,data);
-}
-
-
-/* This implements some extra setup for the encoder that seems to be
-   specific to the PVR USB2 hardware. */
-static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw)
-{
-       int ret = 0;
-       int encMisc3Arg = 0;
-
-#if 0
-       /* This inexplicable bit happens in the Hauppauge windows
-          driver (for both 24xxx and 29xxx devices).  However I
-          currently see no difference in behavior with or without
-          this stuff.  Leave this here as a note of its existence,
-          but don't use it. */
-       LOCK_TAKE(hdw->ctl_lock); do {
-               u32 dat[1];
-               dat[0] = 0x80000640;
-               pvr2_encoder_write_words(hdw,0x01fe,dat,1);
-               pvr2_encoder_write_words(hdw,0x023e,dat,1);
-       } while(0); LOCK_GIVE(hdw->ctl_lock);
-#endif
-
-       /* Mike Isely <isely@pobox.com> 26-Jan-2006 The windows driver
-          sends the following list of ENC_MISC commands (for both
-          24xxx and 29xxx devices).  Meanings are not entirely clear,
-          however without the ENC_MISC(3,1) command then we risk
-          random perpetual video corruption whenever the video input
-          breaks up for a moment (like when switching channels). */
-
-
-#if 0
-       /* This ENC_MISC(5,0) command seems to hurt 29xxx sync
-          performance on channel changes, but is not a problem on
-          24xxx devices. */
-       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 5,0,0,0);
-#endif
-
-       /* This ENC_MISC(3,encMisc3Arg) command is critical - without
-          it there will eventually be video corruption.  Also, the
-          saa7115 case is strange - the Windows driver is passing 1
-          regardless of device type but if we have 1 for saa7115
-          devices the video turns sluggish.  */
-       if (hdw->hdw_desc->flag_has_cx25840) {
-               encMisc3Arg = 1;
-       } else {
-               encMisc3Arg = 0;
-       }
-       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 3,
-                                encMisc3Arg,0,0);
-
-       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 8,0,0,0);
-
-#if 0
-       /* This ENC_MISC(4,1) command is poisonous, so it is commented
-          out.  But I'm leaving it here anyway to document its
-          existence in the Windows driver.  The effect of this
-          command is that apps displaying the stream become sluggish
-          with stuttering video. */
-       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 4,1,0,0);
-#endif
-
-       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0);
-       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0);
-
-       /* prevent the PTSs from slowly drifting away in the generated
-          MPEG stream */
-       ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC, 2, 4, 1);
-
-       return ret;
-}
-
-int pvr2_encoder_adjust(struct pvr2_hdw *hdw)
-{
-       int ret;
-       ret = cx2341x_update(hdw,pvr2_encoder_cmd,
-                            (hdw->enc_cur_valid ? &hdw->enc_cur_state : NULL),
-                            &hdw->enc_ctl_state);
-       if (ret) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Error from cx2341x module code=%d",ret);
-       } else {
-               memcpy(&hdw->enc_cur_state,&hdw->enc_ctl_state,
-                      sizeof(struct cx2341x_mpeg_params));
-               hdw->enc_cur_valid = !0;
-       }
-       return ret;
-}
-
-
-int pvr2_encoder_configure(struct pvr2_hdw *hdw)
-{
-       int ret;
-       int val;
-       pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure"
-                  " (cx2341x module)");
-       hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING;
-       hdw->enc_ctl_state.width = hdw->res_hor_val;
-       hdw->enc_ctl_state.height = hdw->res_ver_val;
-       hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & V4L2_STD_525_60) ?
-                                     0 : 1);
-
-       ret = 0;
-
-       ret |= pvr2_encoder_prep_config(hdw);
-
-       /* saa7115: 0xf0 */
-       val = 0xf0;
-       if (hdw->hdw_desc->flag_has_cx25840) {
-               /* ivtv cx25840: 0x140 */
-               val = 0x140;
-       }
-
-       if (!ret) ret = pvr2_encoder_vcmd(
-               hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
-               val, val);
-
-       /* setup firmware to notify us about some events (don't know why...) */
-       if (!ret) ret = pvr2_encoder_vcmd(
-               hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4,
-               0, 0, 0x10000000, 0xffffffff);
-
-       if (!ret) ret = pvr2_encoder_vcmd(
-               hdw,CX2341X_ENC_SET_VBI_LINE, 5,
-               0xffffffff,0,0,0,0);
-
-       if (ret) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Failed to configure cx23416");
-               return ret;
-       }
-
-       ret = pvr2_encoder_adjust(hdw);
-       if (ret) return ret;
-
-       ret = pvr2_encoder_vcmd(
-               hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
-
-       if (ret) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Failed to initialize cx23416 video input");
-               return ret;
-       }
-
-       return 0;
-}
-
-
-int pvr2_encoder_start(struct pvr2_hdw *hdw)
-{
-       int status;
-
-       /* unmask some interrupts */
-       pvr2_write_register(hdw, 0x0048, 0xbfffffff);
-
-       pvr2_encoder_vcmd(hdw,CX2341X_ENC_MUTE_VIDEO,1,
-                         hdw->input_val == PVR2_CVAL_INPUT_RADIO ? 1 : 0);
-
-       switch (hdw->active_stream_type) {
-       case pvr2_config_vbi:
-               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
-                                          0x01,0x14);
-               break;
-       case pvr2_config_mpeg:
-               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
-                                          0,0x13);
-               break;
-       default: /* Unhandled cases for now */
-               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
-                                          0,0x13);
-               break;
-       }
-       return status;
-}
-
-int pvr2_encoder_stop(struct pvr2_hdw *hdw)
-{
-       int status;
-
-       /* mask all interrupts */
-       pvr2_write_register(hdw, 0x0048, 0xffffffff);
-
-       switch (hdw->active_stream_type) {
-       case pvr2_config_vbi:
-               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
-                                          0x01,0x01,0x14);
-               break;
-       case pvr2_config_mpeg:
-               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
-                                          0x01,0,0x13);
-               break;
-       default: /* Unhandled cases for now */
-               status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
-                                          0x01,0,0x13);
-               break;
-       }
-
-       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/video/pvrusb2/pvrusb2-encoder.h b/drivers/media/video/pvrusb2/pvrusb2-encoder.h
deleted file mode 100644 (file)
index 232fefb..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef __PVRUSB2_ENCODER_H
-#define __PVRUSB2_ENCODER_H
-
-struct pvr2_hdw;
-
-int pvr2_encoder_adjust(struct pvr2_hdw *);
-int pvr2_encoder_configure(struct pvr2_hdw *);
-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/video/pvrusb2/pvrusb2-fx2-cmd.h b/drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h
deleted file mode 100644 (file)
index 614755e..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2007 Michael Krufky <mkrufky@linuxtv.org>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef _PVRUSB2_FX2_CMD_H_
-#define _PVRUSB2_FX2_CMD_H_
-
-#define FX2CMD_MEM_WRITE_DWORD  0x01u
-#define FX2CMD_MEM_READ_DWORD   0x02u
-
-#define FX2CMD_HCW_ZILOG_RESET  0x10u /* 1=reset 0=release */
-
-#define FX2CMD_MEM_READ_64BYTES 0x28u
-
-#define FX2CMD_REG_WRITE        0x04u
-#define FX2CMD_REG_READ         0x05u
-#define FX2CMD_MEMSEL           0x06u
-
-#define FX2CMD_I2C_WRITE        0x08u
-#define FX2CMD_I2C_READ         0x09u
-
-#define FX2CMD_GET_USB_SPEED    0x0bu
-
-#define FX2CMD_STREAMING_ON     0x36u
-#define FX2CMD_STREAMING_OFF    0x37u
-
-#define FX2CMD_FWPOST1          0x52u
-
-#define FX2CMD_POWER_OFF        0xdcu
-#define FX2CMD_POWER_ON         0xdeu
-
-#define FX2CMD_DEEP_RESET       0xddu
-
-#define FX2CMD_GET_EEPROM_ADDR  0xebu
-#define FX2CMD_GET_IR_CODE      0xecu
-
-#define FX2CMD_HCW_DEMOD_RESETIN       0xf0u
-#define FX2CMD_HCW_DTV_STREAMING_ON    0xf1u
-#define FX2CMD_HCW_DTV_STREAMING_OFF   0xf2u
-
-#define FX2CMD_ONAIR_DTV_STREAMING_ON  0xa0u
-#define FX2CMD_ONAIR_DTV_STREAMING_OFF 0xa1u
-#define FX2CMD_ONAIR_DTV_POWER_ON      0xa2u
-#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/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
deleted file mode 100644 (file)
index 036952f..0000000
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifndef __PVRUSB2_HDW_INTERNAL_H
-#define __PVRUSB2_HDW_INTERNAL_H
-
-/*
-
-  This header sets up all the internal structures and definitions needed to
-  track and coordinate the driver's interaction with the hardware.  ONLY
-  source files which actually implement part of that whole circus should be
-  including this header.  Higher levels, like the external layers to the
-  various public APIs (V4L, sysfs, etc) should NOT ever include this
-  private, internal header.  This means that pvrusb2-hdw, pvrusb2-encoder,
-  etc will include this, but pvrusb2-v4l should not.
-
-*/
-
-#include <linux/videodev2.h>
-#include <linux/i2c.h>
-#include <linux/workqueue.h>
-#include <linux/mutex.h>
-#include "pvrusb2-hdw.h"
-#include "pvrusb2-io.h"
-#include <media/v4l2-device.h>
-#include <media/cx2341x.h>
-#include <media/ir-kbd-i2c.h>
-#include "pvrusb2-devattr.h"
-
-/* Legal values for PVR2_CID_HSM */
-#define PVR2_CVAL_HSM_FAIL 0
-#define PVR2_CVAL_HSM_FULL 1
-#define PVR2_CVAL_HSM_HIGH 2
-
-#define PVR2_VID_ENDPOINT        0x84
-#define PVR2_UNK_ENDPOINT        0x86    /* maybe raw yuv ? */
-#define PVR2_VBI_ENDPOINT        0x88
-
-#define PVR2_CTL_BUFFSIZE        64
-
-#define FREQTABLE_SIZE 500
-
-#define LOCK_TAKE(x) do { mutex_lock(&x##_mutex); x##_held = !0; } while (0)
-#define LOCK_GIVE(x) do { x##_held = 0; mutex_unlock(&x##_mutex); } while (0)
-
-typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *);
-typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *);
-typedef int (*pvr2_ctlf_check_value)(struct pvr2_ctrl *,int);
-typedef int (*pvr2_ctlf_get_value)(struct pvr2_ctrl *,int *);
-typedef int (*pvr2_ctlf_set_value)(struct pvr2_ctrl *,int msk,int val);
-typedef int (*pvr2_ctlf_val_to_sym)(struct pvr2_ctrl *,int msk,int val,
-                                   char *,unsigned int,unsigned int *);
-typedef int (*pvr2_ctlf_sym_to_val)(struct pvr2_ctrl *,
-                                   const char *,unsigned int,
-                                   int *mskp,int *valp);
-typedef unsigned int (*pvr2_ctlf_get_v4lflags)(struct pvr2_ctrl *);
-
-/* This structure describes a specific control.  A table of these is set up
-   in pvrusb2-hdw.c. */
-struct pvr2_ctl_info {
-       /* Control's name suitable for use as an identifier */
-       const char *name;
-
-       /* Short description of control */
-       const char *desc;
-
-       /* Control's implementation */
-       pvr2_ctlf_get_value get_value;      /* Get its value */
-       pvr2_ctlf_get_value get_def_value;  /* Get its default value */
-       pvr2_ctlf_get_value get_min_value;  /* Get minimum allowed value */
-       pvr2_ctlf_get_value get_max_value;  /* Get maximum allowed value */
-       pvr2_ctlf_set_value set_value;      /* Set its value */
-       pvr2_ctlf_check_value check_value;  /* Check that value is valid */
-       pvr2_ctlf_val_to_sym val_to_sym;    /* Custom convert value->symbol */
-       pvr2_ctlf_sym_to_val sym_to_val;    /* Custom convert symbol->value */
-       pvr2_ctlf_is_dirty is_dirty;        /* Return true if dirty */
-       pvr2_ctlf_clear_dirty clear_dirty;  /* Clear dirty state */
-       pvr2_ctlf_get_v4lflags get_v4lflags;/* Retrieve v4l flags */
-
-       /* Control's type (int, enum, bitmask) */
-       enum pvr2_ctl_type type;
-
-       /* Associated V4L control ID, if any */
-       int v4l_id;
-
-       /* Associated driver internal ID, if any */
-       int internal_id;
-
-       /* Don't implicitly initialize this control's value */
-       int skip_init;
-
-       /* Starting value for this control */
-       int default_value;
-
-       /* Type-specific control information */
-       union {
-               struct { /* Integer control */
-                       long min_value; /* lower limit */
-                       long max_value; /* upper limit */
-               } type_int;
-               struct { /* enumerated control */
-                       unsigned int count;       /* enum value count */
-                       const char * const *value_names; /* symbol names */
-               } type_enum;
-               struct { /* bitmask control */
-                       unsigned int valid_bits; /* bits in use */
-                       const char **bit_names;  /* symbol name/bit */
-               } type_bitmask;
-       } def;
-};
-
-
-/* Same as pvr2_ctl_info, but includes storage for the control description */
-#define PVR2_CTLD_INFO_DESC_SIZE 32
-struct pvr2_ctld_info {
-       struct pvr2_ctl_info info;
-       char desc[PVR2_CTLD_INFO_DESC_SIZE];
-};
-
-struct pvr2_ctrl {
-       const struct pvr2_ctl_info *info;
-       struct pvr2_hdw *hdw;
-};
-
-
-
-/* Disposition of firmware1 loading situation */
-#define FW1_STATE_UNKNOWN 0
-#define FW1_STATE_MISSING 1
-#define FW1_STATE_FAILED 2
-#define FW1_STATE_RELOAD 3
-#define FW1_STATE_OK 4
-
-/* What state the device is in if it is a hybrid */
-#define PVR2_PATHWAY_UNKNOWN 0
-#define PVR2_PATHWAY_ANALOG 1
-#define PVR2_PATHWAY_DIGITAL 2
-
-typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16);
-#define PVR2_I2C_FUNC_CNT 128
-
-/* This structure contains all state data directly needed to
-   manipulate the hardware (as opposed to complying with a kernel
-   interface) */
-struct pvr2_hdw {
-       /* Underlying USB device handle */
-       struct usb_device *usb_dev;
-       struct usb_interface *usb_intf;
-
-       /* Our handle into the v4l2 sub-device architecture */
-       struct v4l2_device v4l2_dev;
-       /* Device description, anything that must adjust behavior based on
-          device specific info will use information held here. */
-       const struct pvr2_device_desc *hdw_desc;
-
-       /* Kernel worker thread handling */
-       struct workqueue_struct *workqueue;
-       struct work_struct workpoll;     /* Update driver state */
-
-       /* Video spigot */
-       struct pvr2_stream *vid_stream;
-
-       /* Mutex for all hardware state control */
-       struct mutex big_lock_mutex;
-       int big_lock_held;  /* For debugging */
-
-       /* This is a simple string which identifies the instance of this
-          driver.  It is unique within the set of existing devices, but
-          there is no attempt to keep the name consistent with the same
-          physical device each time. */
-       char name[32];
-
-       /* This is a simple string which identifies the physical device
-          instance itself - if possible.  (If not possible, then it is
-          based on the specific driver instance, similar to name above.)
-          The idea here is that userspace might hopefully be able to use
-          this recognize specific tuners.  It will encode a serial number,
-          if available. */
-       char identifier[32];
-
-       /* I2C stuff */
-       struct i2c_adapter i2c_adap;
-       struct i2c_algorithm i2c_algo;
-       pvr2_i2c_func i2c_func[PVR2_I2C_FUNC_CNT];
-       int i2c_cx25840_hack_state;
-       int i2c_linked;
-
-       /* IR related */
-       unsigned int ir_scheme_active; /* IR scheme as seen from the outside */
-       struct IR_i2c_init_data ir_init_data; /* params passed to IR modules */
-
-       /* Frequency table */
-       unsigned int freqTable[FREQTABLE_SIZE];
-       unsigned int freqProgSlot;
-
-       /* Stuff for handling low level control interaction with device */
-       struct mutex ctl_lock_mutex;
-       int ctl_lock_held;  /* For debugging */
-       struct urb *ctl_write_urb;
-       struct urb *ctl_read_urb;
-       unsigned char *ctl_write_buffer;
-       unsigned char *ctl_read_buffer;
-       int ctl_write_pend_flag;
-       int ctl_read_pend_flag;
-       int ctl_timeout_flag;
-       struct completion ctl_done;
-       unsigned char cmd_buffer[PVR2_CTL_BUFFSIZE];
-       int cmd_debug_state;               // Low level command debugging info
-       unsigned char cmd_debug_code;      //
-       unsigned int cmd_debug_write_len;  //
-       unsigned int cmd_debug_read_len;   //
-
-       /* Bits of state that describe what is going on with various parts
-          of the driver. */
-       int state_pathway_ok;         /* Pathway config is ok */
-       int state_encoder_ok;         /* Encoder is operational */
-       int state_encoder_run;        /* Encoder is running */
-       int state_encoder_config;     /* Encoder is configured */
-       int state_encoder_waitok;     /* Encoder pre-wait done */
-       int state_encoder_runok;      /* Encoder has run for >= .25 sec */
-       int state_decoder_run;        /* Decoder is running */
-       int state_decoder_ready;      /* Decoder is stabilized & streamable */
-       int state_usbstream_run;      /* FX2 is streaming */
-       int state_decoder_quiescent;  /* Decoder idle for minimal interval */
-       int state_pipeline_config;    /* Pipeline is configured */
-       int state_pipeline_req;       /* Somebody wants to stream */
-       int state_pipeline_pause;     /* Pipeline must be paused */
-       int state_pipeline_idle;      /* Pipeline not running */
-
-       /* This is the master state of the driver.  It is the combined
-          result of other bits of state.  Examining this will indicate the
-          overall state of the driver.  Values here are one of
-          PVR2_STATE_xxxx */
-       unsigned int master_state;
-
-       /* True if device led is currently on */
-       int led_on;
-
-       /* True if states must be re-evaluated */
-       int state_stale;
-
-       void (*state_func)(void *);
-       void *state_data;
-
-       /* Timer for measuring required decoder settling time before we're
-          allowed to fire it up again. */
-       struct timer_list quiescent_timer;
-
-       /* Timer for measuring decoder stabilization time, which is the
-          amount of time we need to let the decoder run before we can
-          trust its output (otherwise the encoder might see garbage and
-          then fail to start correctly). */
-       struct timer_list decoder_stabilization_timer;
-
-       /* Timer for measuring encoder pre-wait time */
-       struct timer_list encoder_wait_timer;
-
-       /* Timer for measuring encoder minimum run time */
-       struct timer_list encoder_run_timer;
-
-       /* Place to block while waiting for state changes */
-       wait_queue_head_t state_wait_data;
-
-
-       int force_dirty;        /* consider all controls dirty if true */
-       int flag_ok;            /* device in known good state */
-       int flag_modulefail;    /* true if at least one module failed to load */
-       int flag_disconnected;  /* flag_ok == 0 due to disconnect */
-       int flag_init_ok;       /* true if structure is fully initialized */
-       int fw1_state;          /* current situation with fw1 */
-       int pathway_state;      /* one of PVR2_PATHWAY_xxx */
-       int flag_decoder_missed;/* We've noticed missing decoder */
-       int flag_tripped;       /* Indicates overall failure to start */
-
-       unsigned int decoder_client_id;
-
-       // CPU firmware info (used to help find / save firmware data)
-       char *fw_buffer;
-       unsigned int fw_size;
-       int fw_cpu_flag; /* True if we are dealing with the CPU */
-
-       /* Tuner / frequency control stuff */
-       unsigned int tuner_type;
-       int tuner_updated;
-       unsigned int freqValTelevision;  /* Current freq for tv mode */
-       unsigned int freqValRadio;       /* Current freq for radio mode */
-       unsigned int freqSlotTelevision; /* Current slot for tv mode */
-       unsigned int freqSlotRadio;      /* Current slot for radio mode */
-       unsigned int freqSelector;       /* 0=radio 1=television */
-       int freqDirty;
-
-       /* Current tuner info - this information is polled from the I2C bus */
-       struct v4l2_tuner tuner_signal_info;
-       int tuner_signal_stale;
-
-       /* Cropping capability info */
-       struct v4l2_cropcap cropcap_info;
-       int cropcap_stale;
-
-       /* Video standard handling */
-       v4l2_std_id std_mask_eeprom; // Hardware supported selections
-       v4l2_std_id std_mask_avail;  // Which standards we may select from
-       v4l2_std_id std_mask_cur;    // Currently selected standard(s)
-       int std_enum_cur;            // selected standard enumeration value
-       int std_dirty;               // True if std_mask_cur has changed
-       struct pvr2_ctl_info std_info_enum;
-       struct pvr2_ctl_info std_info_avail;
-       struct pvr2_ctl_info std_info_cur;
-       struct pvr2_ctl_info std_info_detect;
-
-       // Generated string names, one per actual V4L2 standard
-       const char *std_mask_ptrs[32];
-       char std_mask_names[32][16];
-
-       int unit_number;             /* ID for driver instance */
-       unsigned long serial_number; /* ID for hardware itself */
-
-       char bus_info[32]; /* Bus location info */
-
-       /* Minor numbers used by v4l logic (yes, this is a hack, as there
-          should be no v4l junk here).  Probably a better way to do this. */
-       int v4l_minor_number_video;
-       int v4l_minor_number_vbi;
-       int v4l_minor_number_radio;
-
-       /* Bit mask of PVR2_CVAL_INPUT choices which are valid for the hardware */
-       unsigned int input_avail_mask;
-       /* Bit mask of PVR2_CVAL_INPUT choices which are currently allowed */
-       unsigned int input_allowed_mask;
-
-       /* Location of eeprom or a negative number if none */
-       int eeprom_addr;
-
-       enum pvr2_config active_stream_type;
-       enum pvr2_config desired_stream_type;
-
-       /* Control state needed for cx2341x module */
-       struct cx2341x_mpeg_params enc_cur_state;
-       struct cx2341x_mpeg_params enc_ctl_state;
-       /* True if an encoder attribute has changed */
-       int enc_stale;
-       /* True if an unsafe encoder attribute has changed */
-       int enc_unsafe_stale;
-       /* True if enc_cur_state is valid */
-       int enc_cur_valid;
-
-       /* Control state */
-#define VCREATE_DATA(lab) int lab##_val; int lab##_dirty
-       VCREATE_DATA(brightness);
-       VCREATE_DATA(contrast);
-       VCREATE_DATA(saturation);
-       VCREATE_DATA(hue);
-       VCREATE_DATA(volume);
-       VCREATE_DATA(balance);
-       VCREATE_DATA(bass);
-       VCREATE_DATA(treble);
-       VCREATE_DATA(mute);
-       VCREATE_DATA(cropl);
-       VCREATE_DATA(cropt);
-       VCREATE_DATA(cropw);
-       VCREATE_DATA(croph);
-       VCREATE_DATA(input);
-       VCREATE_DATA(audiomode);
-       VCREATE_DATA(res_hor);
-       VCREATE_DATA(res_ver);
-       VCREATE_DATA(srate);
-#undef VCREATE_DATA
-
-       struct pvr2_ctld_info *mpeg_ctrl_info;
-
-       struct pvr2_ctrl *controls;
-       unsigned int control_cnt;
-};
-
-/* This function gets the current frequency */
-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/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
deleted file mode 100644 (file)
index fb828ba..0000000
+++ /dev/null
@@ -1,5202 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/firmware.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/tuner.h>
-#include "pvrusb2.h"
-#include "pvrusb2-std.h"
-#include "pvrusb2-util.h"
-#include "pvrusb2-hdw.h"
-#include "pvrusb2-i2c-core.h"
-#include "pvrusb2-eeprom.h"
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-encoder.h"
-#include "pvrusb2-debug.h"
-#include "pvrusb2-fx2-cmd.h"
-#include "pvrusb2-wm8775.h"
-#include "pvrusb2-video-v4l.h"
-#include "pvrusb2-cx2584x-v4l.h"
-#include "pvrusb2-cs53l32a.h"
-#include "pvrusb2-audio.h"
-
-#define TV_MIN_FREQ     55250000L
-#define TV_MAX_FREQ    850000000L
-
-/* This defines a minimum interval that the decoder must remain quiet
-   before we are allowed to start it running. */
-#define TIME_MSEC_DECODER_WAIT 50
-
-/* This defines a minimum interval that the decoder must be allowed to run
-   before we can safely begin using its streaming output. */
-#define TIME_MSEC_DECODER_STABILIZATION_WAIT 300
-
-/* This defines a minimum interval that the encoder must remain quiet
-   before we are allowed to configure it. */
-#define TIME_MSEC_ENCODER_WAIT 50
-
-/* This defines the minimum interval that the encoder must successfully run
-   before we consider that the encoder has run at least once since its
-   firmware has been loaded.  This measurement is in important for cases
-   where we can't do something until we know that the encoder has been run
-   at least once. */
-#define TIME_MSEC_ENCODER_OK 250
-
-static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL};
-static DEFINE_MUTEX(pvr2_unit_mtx);
-
-static int ctlchg;
-static int procreload;
-static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };
-static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
-static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
-static int init_pause_msec;
-
-module_param(ctlchg, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value");
-module_param(init_pause_msec, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(init_pause_msec, "hardware initialization settling delay");
-module_param(procreload, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(procreload,
-                "Attempt init failure recovery with firmware reload");
-module_param_array(tuner,    int, NULL, 0444);
-MODULE_PARM_DESC(tuner,"specify installed tuner type");
-module_param_array(video_std,    int, NULL, 0444);
-MODULE_PARM_DESC(video_std,"specify initial video standard");
-module_param_array(tolerance,    int, NULL, 0444);
-MODULE_PARM_DESC(tolerance,"specify stream error tolerance");
-
-/* US Broadcast channel 3 (61.25 MHz), to help with testing */
-static int default_tv_freq    = 61250000L;
-/* 104.3 MHz, a usable FM station for my area */
-static int default_radio_freq = 104300000L;
-
-module_param_named(tv_freq, default_tv_freq, int, 0444);
-MODULE_PARM_DESC(tv_freq, "specify initial television frequency");
-module_param_named(radio_freq, default_radio_freq, int, 0444);
-MODULE_PARM_DESC(radio_freq, "specify initial radio frequency");
-
-#define PVR2_CTL_WRITE_ENDPOINT  0x01
-#define PVR2_CTL_READ_ENDPOINT   0x81
-
-#define PVR2_GPIO_IN 0x9008
-#define PVR2_GPIO_OUT 0x900c
-#define PVR2_GPIO_DIR 0x9020
-
-#define trace_firmware(...) pvr2_trace(PVR2_TRACE_FIRMWARE,__VA_ARGS__)
-
-#define PVR2_FIRMWARE_ENDPOINT   0x02
-
-/* size of a firmware chunk */
-#define FIRMWARE_CHUNK_SIZE 0x2000
-
-typedef void (*pvr2_subdev_update_func)(struct pvr2_hdw *,
-                                       struct v4l2_subdev *);
-
-static const pvr2_subdev_update_func pvr2_module_update_functions[] = {
-       [PVR2_CLIENT_ID_WM8775] = pvr2_wm8775_subdev_update,
-       [PVR2_CLIENT_ID_SAA7115] = pvr2_saa7115_subdev_update,
-       [PVR2_CLIENT_ID_MSP3400] = pvr2_msp3400_subdev_update,
-       [PVR2_CLIENT_ID_CX25840] = pvr2_cx25840_subdev_update,
-       [PVR2_CLIENT_ID_CS53L32A] = pvr2_cs53l32a_subdev_update,
-};
-
-static const char *module_names[] = {
-       [PVR2_CLIENT_ID_MSP3400] = "msp3400",
-       [PVR2_CLIENT_ID_CX25840] = "cx25840",
-       [PVR2_CLIENT_ID_SAA7115] = "saa7115",
-       [PVR2_CLIENT_ID_TUNER] = "tuner",
-       [PVR2_CLIENT_ID_DEMOD] = "tuner",
-       [PVR2_CLIENT_ID_CS53L32A] = "cs53l32a",
-       [PVR2_CLIENT_ID_WM8775] = "wm8775",
-};
-
-
-static const unsigned char *module_i2c_addresses[] = {
-       [PVR2_CLIENT_ID_TUNER] = "\x60\x61\x62\x63",
-       [PVR2_CLIENT_ID_DEMOD] = "\x43",
-       [PVR2_CLIENT_ID_MSP3400] = "\x40",
-       [PVR2_CLIENT_ID_SAA7115] = "\x21",
-       [PVR2_CLIENT_ID_WM8775] = "\x1b",
-       [PVR2_CLIENT_ID_CX25840] = "\x44",
-       [PVR2_CLIENT_ID_CS53L32A] = "\x11",
-};
-
-
-static const char *ir_scheme_names[] = {
-       [PVR2_IR_SCHEME_NONE] = "none",
-       [PVR2_IR_SCHEME_29XXX] = "29xxx",
-       [PVR2_IR_SCHEME_24XXX] = "24xxx (29xxx emulation)",
-       [PVR2_IR_SCHEME_24XXX_MCE] = "24xxx (MCE device)",
-       [PVR2_IR_SCHEME_ZILOG] = "Zilog",
-};
-
-
-/* Define the list of additional controls we'll dynamically construct based
-   on query of the cx2341x module. */
-struct pvr2_mpeg_ids {
-       const char *strid;
-       int id;
-};
-static const struct pvr2_mpeg_ids mpeg_ids[] = {
-       {
-               .strid = "audio_layer",
-               .id = V4L2_CID_MPEG_AUDIO_ENCODING,
-       },{
-               .strid = "audio_bitrate",
-               .id = V4L2_CID_MPEG_AUDIO_L2_BITRATE,
-       },{
-               /* Already using audio_mode elsewhere :-( */
-               .strid = "mpeg_audio_mode",
-               .id = V4L2_CID_MPEG_AUDIO_MODE,
-       },{
-               .strid = "mpeg_audio_mode_extension",
-               .id = V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
-       },{
-               .strid = "audio_emphasis",
-               .id = V4L2_CID_MPEG_AUDIO_EMPHASIS,
-       },{
-               .strid = "audio_crc",
-               .id = V4L2_CID_MPEG_AUDIO_CRC,
-       },{
-               .strid = "video_aspect",
-               .id = V4L2_CID_MPEG_VIDEO_ASPECT,
-       },{
-               .strid = "video_b_frames",
-               .id = V4L2_CID_MPEG_VIDEO_B_FRAMES,
-       },{
-               .strid = "video_gop_size",
-               .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE,
-       },{
-               .strid = "video_gop_closure",
-               .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
-       },{
-               .strid = "video_bitrate_mode",
-               .id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
-       },{
-               .strid = "video_bitrate",
-               .id = V4L2_CID_MPEG_VIDEO_BITRATE,
-       },{
-               .strid = "video_bitrate_peak",
-               .id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
-       },{
-               .strid = "video_temporal_decimation",
-               .id = V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
-       },{
-               .strid = "stream_type",
-               .id = V4L2_CID_MPEG_STREAM_TYPE,
-       },{
-               .strid = "video_spatial_filter_mode",
-               .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
-       },{
-               .strid = "video_spatial_filter",
-               .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
-       },{
-               .strid = "video_luma_spatial_filter_type",
-               .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
-       },{
-               .strid = "video_chroma_spatial_filter_type",
-               .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
-       },{
-               .strid = "video_temporal_filter_mode",
-               .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
-       },{
-               .strid = "video_temporal_filter",
-               .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
-       },{
-               .strid = "video_median_filter_type",
-               .id = V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
-       },{
-               .strid = "video_luma_median_filter_top",
-               .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
-       },{
-               .strid = "video_luma_median_filter_bottom",
-               .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
-       },{
-               .strid = "video_chroma_median_filter_top",
-               .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
-       },{
-               .strid = "video_chroma_median_filter_bottom",
-               .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
-       }
-};
-#define MPEGDEF_COUNT ARRAY_SIZE(mpeg_ids)
-
-
-static const char *control_values_srate[] = {
-       [V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100]   = "44.1 kHz",
-       [V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000]   = "48 kHz",
-       [V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000]   = "32 kHz",
-};
-
-
-
-static const char *control_values_input[] = {
-       [PVR2_CVAL_INPUT_TV]        = "television",  /*xawtv needs this name*/
-       [PVR2_CVAL_INPUT_DTV]       = "dtv",
-       [PVR2_CVAL_INPUT_RADIO]     = "radio",
-       [PVR2_CVAL_INPUT_SVIDEO]    = "s-video",
-       [PVR2_CVAL_INPUT_COMPOSITE] = "composite",
-};
-
-
-static const char *control_values_audiomode[] = {
-       [V4L2_TUNER_MODE_MONO]   = "Mono",
-       [V4L2_TUNER_MODE_STEREO] = "Stereo",
-       [V4L2_TUNER_MODE_LANG1]  = "Lang1",
-       [V4L2_TUNER_MODE_LANG2]  = "Lang2",
-       [V4L2_TUNER_MODE_LANG1_LANG2] = "Lang1+Lang2",
-};
-
-
-static const char *control_values_hsm[] = {
-       [PVR2_CVAL_HSM_FAIL] = "Fail",
-       [PVR2_CVAL_HSM_HIGH] = "High",
-       [PVR2_CVAL_HSM_FULL] = "Full",
-};
-
-
-static const char *pvr2_state_names[] = {
-       [PVR2_STATE_NONE] =    "none",
-       [PVR2_STATE_DEAD] =    "dead",
-       [PVR2_STATE_COLD] =    "cold",
-       [PVR2_STATE_WARM] =    "warm",
-       [PVR2_STATE_ERROR] =   "error",
-       [PVR2_STATE_READY] =   "ready",
-       [PVR2_STATE_RUN] =     "run",
-};
-
-
-struct pvr2_fx2cmd_descdef {
-       unsigned char id;
-       unsigned char *desc;
-};
-
-static const struct pvr2_fx2cmd_descdef pvr2_fx2cmd_desc[] = {
-       {FX2CMD_MEM_WRITE_DWORD, "write encoder dword"},
-       {FX2CMD_MEM_READ_DWORD, "read encoder dword"},
-       {FX2CMD_HCW_ZILOG_RESET, "zilog IR reset control"},
-       {FX2CMD_MEM_READ_64BYTES, "read encoder 64bytes"},
-       {FX2CMD_REG_WRITE, "write encoder register"},
-       {FX2CMD_REG_READ, "read encoder register"},
-       {FX2CMD_MEMSEL, "encoder memsel"},
-       {FX2CMD_I2C_WRITE, "i2c write"},
-       {FX2CMD_I2C_READ, "i2c read"},
-       {FX2CMD_GET_USB_SPEED, "get USB speed"},
-       {FX2CMD_STREAMING_ON, "stream on"},
-       {FX2CMD_STREAMING_OFF, "stream off"},
-       {FX2CMD_FWPOST1, "fwpost1"},
-       {FX2CMD_POWER_OFF, "power off"},
-       {FX2CMD_POWER_ON, "power on"},
-       {FX2CMD_DEEP_RESET, "deep reset"},
-       {FX2CMD_GET_EEPROM_ADDR, "get rom addr"},
-       {FX2CMD_GET_IR_CODE, "get IR code"},
-       {FX2CMD_HCW_DEMOD_RESETIN, "hcw demod resetin"},
-       {FX2CMD_HCW_DTV_STREAMING_ON, "hcw dtv stream on"},
-       {FX2CMD_HCW_DTV_STREAMING_OFF, "hcw dtv stream off"},
-       {FX2CMD_ONAIR_DTV_STREAMING_ON, "onair dtv stream on"},
-       {FX2CMD_ONAIR_DTV_STREAMING_OFF, "onair dtv stream off"},
-       {FX2CMD_ONAIR_DTV_POWER_ON, "onair dtv power on"},
-       {FX2CMD_ONAIR_DTV_POWER_OFF, "onair dtv power off"},
-};
-
-
-static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v);
-static void pvr2_hdw_state_sched(struct pvr2_hdw *);
-static int pvr2_hdw_state_eval(struct pvr2_hdw *);
-static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long);
-static void pvr2_hdw_worker_poll(struct work_struct *work);
-static int pvr2_hdw_wait(struct pvr2_hdw *,int state);
-static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *);
-static void pvr2_hdw_state_log_state(struct pvr2_hdw *);
-static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl);
-static int pvr2_hdw_commit_setup(struct pvr2_hdw *hdw);
-static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw);
-static void pvr2_hdw_quiescent_timeout(unsigned long);
-static void pvr2_hdw_decoder_stabilization_timeout(unsigned long);
-static void pvr2_hdw_encoder_wait_timeout(unsigned long);
-static void pvr2_hdw_encoder_run_timeout(unsigned long);
-static int pvr2_issue_simple_cmd(struct pvr2_hdw *,u32);
-static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
-                               unsigned int timeout,int probe_fl,
-                               void *write_data,unsigned int write_len,
-                               void *read_data,unsigned int read_len);
-static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw);
-static v4l2_std_id pvr2_hdw_get_detected_std(struct pvr2_hdw *hdw);
-
-static void trace_stbit(const char *name,int val)
-{
-       pvr2_trace(PVR2_TRACE_STBITS,
-                  "State bit %s <-- %s",
-                  name,(val ? "true" : "false"));
-}
-
-static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       struct pvr2_hdw *hdw = cptr->hdw;
-       if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) {
-               *vp = hdw->freqTable[hdw->freqProgSlot-1];
-       } else {
-               *vp = 0;
-       }
-       return 0;
-}
-
-static int ctrl_channelfreq_set(struct pvr2_ctrl *cptr,int m,int v)
-{
-       struct pvr2_hdw *hdw = cptr->hdw;
-       unsigned int slotId = hdw->freqProgSlot;
-       if ((slotId > 0) && (slotId <= FREQTABLE_SIZE)) {
-               hdw->freqTable[slotId-1] = v;
-               /* Handle side effects correctly - if we're tuned to this
-                  slot, then forgot the slot id relation since the stored
-                  frequency has been changed. */
-               if (hdw->freqSelector) {
-                       if (hdw->freqSlotRadio == slotId) {
-                               hdw->freqSlotRadio = 0;
-                       }
-               } else {
-                       if (hdw->freqSlotTelevision == slotId) {
-                               hdw->freqSlotTelevision = 0;
-                       }
-               }
-       }
-       return 0;
-}
-
-static int ctrl_channelprog_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       *vp = cptr->hdw->freqProgSlot;
-       return 0;
-}
-
-static int ctrl_channelprog_set(struct pvr2_ctrl *cptr,int m,int v)
-{
-       struct pvr2_hdw *hdw = cptr->hdw;
-       if ((v >= 0) && (v <= FREQTABLE_SIZE)) {
-               hdw->freqProgSlot = v;
-       }
-       return 0;
-}
-
-static int ctrl_channel_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       struct pvr2_hdw *hdw = cptr->hdw;
-       *vp = hdw->freqSelector ? hdw->freqSlotRadio : hdw->freqSlotTelevision;
-       return 0;
-}
-
-static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int slotId)
-{
-       unsigned freq = 0;
-       struct pvr2_hdw *hdw = cptr->hdw;
-       if ((slotId < 0) || (slotId > FREQTABLE_SIZE)) return 0;
-       if (slotId > 0) {
-               freq = hdw->freqTable[slotId-1];
-               if (!freq) return 0;
-               pvr2_hdw_set_cur_freq(hdw,freq);
-       }
-       if (hdw->freqSelector) {
-               hdw->freqSlotRadio = slotId;
-       } else {
-               hdw->freqSlotTelevision = slotId;
-       }
-       return 0;
-}
-
-static int ctrl_freq_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       *vp = pvr2_hdw_get_cur_freq(cptr->hdw);
-       return 0;
-}
-
-static int ctrl_freq_is_dirty(struct pvr2_ctrl *cptr)
-{
-       return cptr->hdw->freqDirty != 0;
-}
-
-static void ctrl_freq_clear_dirty(struct pvr2_ctrl *cptr)
-{
-       cptr->hdw->freqDirty = 0;
-}
-
-static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
-{
-       pvr2_hdw_set_cur_freq(cptr->hdw,v);
-       return 0;
-}
-
-static int ctrl_cropl_min_get(struct pvr2_ctrl *cptr, int *left)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       *left = cap->bounds.left;
-       return 0;
-}
-
-static int ctrl_cropl_max_get(struct pvr2_ctrl *cptr, int *left)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       *left = cap->bounds.left;
-       if (cap->bounds.width > cptr->hdw->cropw_val) {
-               *left += cap->bounds.width - cptr->hdw->cropw_val;
-       }
-       return 0;
-}
-
-static int ctrl_cropt_min_get(struct pvr2_ctrl *cptr, int *top)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       *top = cap->bounds.top;
-       return 0;
-}
-
-static int ctrl_cropt_max_get(struct pvr2_ctrl *cptr, int *top)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       *top = cap->bounds.top;
-       if (cap->bounds.height > cptr->hdw->croph_val) {
-               *top += cap->bounds.height - cptr->hdw->croph_val;
-       }
-       return 0;
-}
-
-static int ctrl_cropw_max_get(struct pvr2_ctrl *cptr, int *width)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat, bleftend, cleft;
-
-       stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       bleftend = cap->bounds.left+cap->bounds.width;
-       cleft = cptr->hdw->cropl_val;
-
-       *width = cleft < bleftend ? bleftend-cleft : 0;
-       return 0;
-}
-
-static int ctrl_croph_max_get(struct pvr2_ctrl *cptr, int *height)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat, btopend, ctop;
-
-       stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       btopend = cap->bounds.top+cap->bounds.height;
-       ctop = cptr->hdw->cropt_val;
-
-       *height = ctop < btopend ? btopend-ctop : 0;
-       return 0;
-}
-
-static int ctrl_get_cropcapbl(struct pvr2_ctrl *cptr, int *val)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       *val = cap->bounds.left;
-       return 0;
-}
-
-static int ctrl_get_cropcapbt(struct pvr2_ctrl *cptr, int *val)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       *val = cap->bounds.top;
-       return 0;
-}
-
-static int ctrl_get_cropcapbw(struct pvr2_ctrl *cptr, int *val)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       *val = cap->bounds.width;
-       return 0;
-}
-
-static int ctrl_get_cropcapbh(struct pvr2_ctrl *cptr, int *val)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       *val = cap->bounds.height;
-       return 0;
-}
-
-static int ctrl_get_cropcapdl(struct pvr2_ctrl *cptr, int *val)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       *val = cap->defrect.left;
-       return 0;
-}
-
-static int ctrl_get_cropcapdt(struct pvr2_ctrl *cptr, int *val)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       *val = cap->defrect.top;
-       return 0;
-}
-
-static int ctrl_get_cropcapdw(struct pvr2_ctrl *cptr, int *val)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       *val = cap->defrect.width;
-       return 0;
-}
-
-static int ctrl_get_cropcapdh(struct pvr2_ctrl *cptr, int *val)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       *val = cap->defrect.height;
-       return 0;
-}
-
-static int ctrl_get_cropcappan(struct pvr2_ctrl *cptr, int *val)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       *val = cap->pixelaspect.numerator;
-       return 0;
-}
-
-static int ctrl_get_cropcappad(struct pvr2_ctrl *cptr, int *val)
-{
-       struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-       int stat = pvr2_hdw_check_cropcap(cptr->hdw);
-       if (stat != 0) {
-               return stat;
-       }
-       *val = cap->pixelaspect.denominator;
-       return 0;
-}
-
-static int ctrl_vres_max_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       /* Actual maximum depends on the video standard in effect. */
-       if (cptr->hdw->std_mask_cur & V4L2_STD_525_60) {
-               *vp = 480;
-       } else {
-               *vp = 576;
-       }
-       return 0;
-}
-
-static int ctrl_vres_min_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       /* Actual minimum depends on device digitizer type. */
-       if (cptr->hdw->hdw_desc->flag_has_cx25840) {
-               *vp = 75;
-       } else {
-               *vp = 17;
-       }
-       return 0;
-}
-
-static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp)
-{
-       *vp = cptr->hdw->input_val;
-       return 0;
-}
-
-static int ctrl_check_input(struct pvr2_ctrl *cptr,int v)
-{
-       return ((1 << v) & cptr->hdw->input_allowed_mask) != 0;
-}
-
-static int ctrl_set_input(struct pvr2_ctrl *cptr,int m,int v)
-{
-       return pvr2_hdw_set_input(cptr->hdw,v);
-}
-
-static int ctrl_isdirty_input(struct pvr2_ctrl *cptr)
-{
-       return cptr->hdw->input_dirty != 0;
-}
-
-static void ctrl_cleardirty_input(struct pvr2_ctrl *cptr)
-{
-       cptr->hdw->input_dirty = 0;
-}
-
-
-static int ctrl_freq_max_get(struct pvr2_ctrl *cptr, int *vp)
-{
-       unsigned long fv;
-       struct pvr2_hdw *hdw = cptr->hdw;
-       if (hdw->tuner_signal_stale) {
-               pvr2_hdw_status_poll(hdw);
-       }
-       fv = hdw->tuner_signal_info.rangehigh;
-       if (!fv) {
-               /* Safety fallback */
-               *vp = TV_MAX_FREQ;
-               return 0;
-       }
-       if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
-               fv = (fv * 125) / 2;
-       } else {
-               fv = fv * 62500;
-       }
-       *vp = fv;
-       return 0;
-}
-
-static int ctrl_freq_min_get(struct pvr2_ctrl *cptr, int *vp)
-{
-       unsigned long fv;
-       struct pvr2_hdw *hdw = cptr->hdw;
-       if (hdw->tuner_signal_stale) {
-               pvr2_hdw_status_poll(hdw);
-       }
-       fv = hdw->tuner_signal_info.rangelow;
-       if (!fv) {
-               /* Safety fallback */
-               *vp = TV_MIN_FREQ;
-               return 0;
-       }
-       if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
-               fv = (fv * 125) / 2;
-       } else {
-               fv = fv * 62500;
-       }
-       *vp = fv;
-       return 0;
-}
-
-static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr)
-{
-       return cptr->hdw->enc_stale != 0;
-}
-
-static void ctrl_cx2341x_clear_dirty(struct pvr2_ctrl *cptr)
-{
-       cptr->hdw->enc_stale = 0;
-       cptr->hdw->enc_unsafe_stale = 0;
-}
-
-static int ctrl_cx2341x_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       int ret;
-       struct v4l2_ext_controls cs;
-       struct v4l2_ext_control c1;
-       memset(&cs,0,sizeof(cs));
-       memset(&c1,0,sizeof(c1));
-       cs.controls = &c1;
-       cs.count = 1;
-       c1.id = cptr->info->v4l_id;
-       ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state, 0, &cs,
-                               VIDIOC_G_EXT_CTRLS);
-       if (ret) return ret;
-       *vp = c1.value;
-       return 0;
-}
-
-static int ctrl_cx2341x_set(struct pvr2_ctrl *cptr,int m,int v)
-{
-       int ret;
-       struct pvr2_hdw *hdw = cptr->hdw;
-       struct v4l2_ext_controls cs;
-       struct v4l2_ext_control c1;
-       memset(&cs,0,sizeof(cs));
-       memset(&c1,0,sizeof(c1));
-       cs.controls = &c1;
-       cs.count = 1;
-       c1.id = cptr->info->v4l_id;
-       c1.value = v;
-       ret = cx2341x_ext_ctrls(&hdw->enc_ctl_state,
-                               hdw->state_encoder_run, &cs,
-                               VIDIOC_S_EXT_CTRLS);
-       if (ret == -EBUSY) {
-               /* Oops.  cx2341x is telling us it's not safe to change
-                  this control while we're capturing.  Make a note of this
-                  fact so that the pipeline will be stopped the next time
-                  controls are committed.  Then go on ahead and store this
-                  change anyway. */
-               ret = cx2341x_ext_ctrls(&hdw->enc_ctl_state,
-                                       0, &cs,
-                                       VIDIOC_S_EXT_CTRLS);
-               if (!ret) hdw->enc_unsafe_stale = !0;
-       }
-       if (ret) return ret;
-       hdw->enc_stale = !0;
-       return 0;
-}
-
-static unsigned int ctrl_cx2341x_getv4lflags(struct pvr2_ctrl *cptr)
-{
-       struct v4l2_queryctrl qctrl;
-       struct pvr2_ctl_info *info;
-       qctrl.id = cptr->info->v4l_id;
-       cx2341x_ctrl_query(&cptr->hdw->enc_ctl_state,&qctrl);
-       /* Strip out the const so we can adjust a function pointer.  It's
-          OK to do this here because we know this is a dynamically created
-          control, so the underlying storage for the info pointer is (a)
-          private to us, and (b) not in read-only storage.  Either we do
-          this or we significantly complicate the underlying control
-          implementation. */
-       info = (struct pvr2_ctl_info *)(cptr->info);
-       if (qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
-               if (info->set_value) {
-                       info->set_value = NULL;
-               }
-       } else {
-               if (!(info->set_value)) {
-                       info->set_value = ctrl_cx2341x_set;
-               }
-       }
-       return qctrl.flags;
-}
-
-static int ctrl_streamingenabled_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       *vp = cptr->hdw->state_pipeline_req;
-       return 0;
-}
-
-static int ctrl_masterstate_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       *vp = cptr->hdw->master_state;
-       return 0;
-}
-
-static int ctrl_hsm_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       int result = pvr2_hdw_is_hsm(cptr->hdw);
-       *vp = PVR2_CVAL_HSM_FULL;
-       if (result < 0) *vp = PVR2_CVAL_HSM_FAIL;
-       if (result) *vp = PVR2_CVAL_HSM_HIGH;
-       return 0;
-}
-
-static int ctrl_stddetect_get(struct pvr2_ctrl *cptr, int *vp)
-{
-       *vp = pvr2_hdw_get_detected_std(cptr->hdw);
-       return 0;
-}
-
-static int ctrl_stdavail_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       *vp = cptr->hdw->std_mask_avail;
-       return 0;
-}
-
-static int ctrl_stdavail_set(struct pvr2_ctrl *cptr,int m,int v)
-{
-       struct pvr2_hdw *hdw = cptr->hdw;
-       v4l2_std_id ns;
-       ns = hdw->std_mask_avail;
-       ns = (ns & ~m) | (v & m);
-       if (ns == hdw->std_mask_avail) return 0;
-       hdw->std_mask_avail = ns;
-       hdw->std_info_cur.def.type_bitmask.valid_bits = hdw->std_mask_avail;
-       return 0;
-}
-
-static int ctrl_std_val_to_sym(struct pvr2_ctrl *cptr,int msk,int val,
-                              char *bufPtr,unsigned int bufSize,
-                              unsigned int *len)
-{
-       *len = pvr2_std_id_to_str(bufPtr,bufSize,msk & val);
-       return 0;
-}
-
-static int ctrl_std_sym_to_val(struct pvr2_ctrl *cptr,
-                              const char *bufPtr,unsigned int bufSize,
-                              int *mskp,int *valp)
-{
-       int ret;
-       v4l2_std_id id;
-       ret = pvr2_std_str_to_id(&id,bufPtr,bufSize);
-       if (ret < 0) return ret;
-       if (mskp) *mskp = id;
-       if (valp) *valp = id;
-       return 0;
-}
-
-static int ctrl_stdcur_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       *vp = cptr->hdw->std_mask_cur;
-       return 0;
-}
-
-static int ctrl_stdcur_set(struct pvr2_ctrl *cptr,int m,int v)
-{
-       struct pvr2_hdw *hdw = cptr->hdw;
-       v4l2_std_id ns;
-       ns = hdw->std_mask_cur;
-       ns = (ns & ~m) | (v & m);
-       if (ns == hdw->std_mask_cur) return 0;
-       hdw->std_mask_cur = ns;
-       hdw->std_dirty = !0;
-       return 0;
-}
-
-static int ctrl_stdcur_is_dirty(struct pvr2_ctrl *cptr)
-{
-       return cptr->hdw->std_dirty != 0;
-}
-
-static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr)
-{
-       cptr->hdw->std_dirty = 0;
-}
-
-static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       struct pvr2_hdw *hdw = cptr->hdw;
-       pvr2_hdw_status_poll(hdw);
-       *vp = hdw->tuner_signal_info.signal;
-       return 0;
-}
-
-static int ctrl_audio_modes_present_get(struct pvr2_ctrl *cptr,int *vp)
-{
-       int val = 0;
-       unsigned int subchan;
-       struct pvr2_hdw *hdw = cptr->hdw;
-       pvr2_hdw_status_poll(hdw);
-       subchan = hdw->tuner_signal_info.rxsubchans;
-       if (subchan & V4L2_TUNER_SUB_MONO) {
-               val |= (1 << V4L2_TUNER_MODE_MONO);
-       }
-       if (subchan & V4L2_TUNER_SUB_STEREO) {
-               val |= (1 << V4L2_TUNER_MODE_STEREO);
-       }
-       if (subchan & V4L2_TUNER_SUB_LANG1) {
-               val |= (1 << V4L2_TUNER_MODE_LANG1);
-       }
-       if (subchan & V4L2_TUNER_SUB_LANG2) {
-               val |= (1 << V4L2_TUNER_MODE_LANG2);
-       }
-       *vp = val;
-       return 0;
-}
-
-
-#define DEFINT(vmin,vmax) \
-       .type = pvr2_ctl_int, \
-       .def.type_int.min_value = vmin, \
-       .def.type_int.max_value = vmax
-
-#define DEFENUM(tab) \
-       .type = pvr2_ctl_enum, \
-       .def.type_enum.count = ARRAY_SIZE(tab), \
-       .def.type_enum.value_names = tab
-
-#define DEFBOOL \
-       .type = pvr2_ctl_bool
-
-#define DEFMASK(msk,tab) \
-       .type = pvr2_ctl_bitmask, \
-       .def.type_bitmask.valid_bits = msk, \
-       .def.type_bitmask.bit_names = tab
-
-#define DEFREF(vname) \
-       .set_value = ctrl_set_##vname, \
-       .get_value = ctrl_get_##vname, \
-       .is_dirty = ctrl_isdirty_##vname, \
-       .clear_dirty = ctrl_cleardirty_##vname
-
-
-#define VCREATE_FUNCS(vname) \
-static int ctrl_get_##vname(struct pvr2_ctrl *cptr,int *vp) \
-{*vp = cptr->hdw->vname##_val; return 0;} \
-static int ctrl_set_##vname(struct pvr2_ctrl *cptr,int m,int v) \
-{cptr->hdw->vname##_val = v; cptr->hdw->vname##_dirty = !0; return 0;} \
-static int ctrl_isdirty_##vname(struct pvr2_ctrl *cptr) \
-{return cptr->hdw->vname##_dirty != 0;} \
-static void ctrl_cleardirty_##vname(struct pvr2_ctrl *cptr) \
-{cptr->hdw->vname##_dirty = 0;}
-
-VCREATE_FUNCS(brightness)
-VCREATE_FUNCS(contrast)
-VCREATE_FUNCS(saturation)
-VCREATE_FUNCS(hue)
-VCREATE_FUNCS(volume)
-VCREATE_FUNCS(balance)
-VCREATE_FUNCS(bass)
-VCREATE_FUNCS(treble)
-VCREATE_FUNCS(mute)
-VCREATE_FUNCS(cropl)
-VCREATE_FUNCS(cropt)
-VCREATE_FUNCS(cropw)
-VCREATE_FUNCS(croph)
-VCREATE_FUNCS(audiomode)
-VCREATE_FUNCS(res_hor)
-VCREATE_FUNCS(res_ver)
-VCREATE_FUNCS(srate)
-
-/* Table definition of all controls which can be manipulated */
-static const struct pvr2_ctl_info control_defs[] = {
-       {
-               .v4l_id = V4L2_CID_BRIGHTNESS,
-               .desc = "Brightness",
-               .name = "brightness",
-               .default_value = 128,
-               DEFREF(brightness),
-               DEFINT(0,255),
-       },{
-               .v4l_id = V4L2_CID_CONTRAST,
-               .desc = "Contrast",
-               .name = "contrast",
-               .default_value = 68,
-               DEFREF(contrast),
-               DEFINT(0,127),
-       },{
-               .v4l_id = V4L2_CID_SATURATION,
-               .desc = "Saturation",
-               .name = "saturation",
-               .default_value = 64,
-               DEFREF(saturation),
-               DEFINT(0,127),
-       },{
-               .v4l_id = V4L2_CID_HUE,
-               .desc = "Hue",
-               .name = "hue",
-               .default_value = 0,
-               DEFREF(hue),
-               DEFINT(-128,127),
-       },{
-               .v4l_id = V4L2_CID_AUDIO_VOLUME,
-               .desc = "Volume",
-               .name = "volume",
-               .default_value = 62000,
-               DEFREF(volume),
-               DEFINT(0,65535),
-       },{
-               .v4l_id = V4L2_CID_AUDIO_BALANCE,
-               .desc = "Balance",
-               .name = "balance",
-               .default_value = 0,
-               DEFREF(balance),
-               DEFINT(-32768,32767),
-       },{
-               .v4l_id = V4L2_CID_AUDIO_BASS,
-               .desc = "Bass",
-               .name = "bass",
-               .default_value = 0,
-               DEFREF(bass),
-               DEFINT(-32768,32767),
-       },{
-               .v4l_id = V4L2_CID_AUDIO_TREBLE,
-               .desc = "Treble",
-               .name = "treble",
-               .default_value = 0,
-               DEFREF(treble),
-               DEFINT(-32768,32767),
-       },{
-               .v4l_id = V4L2_CID_AUDIO_MUTE,
-               .desc = "Mute",
-               .name = "mute",
-               .default_value = 0,
-               DEFREF(mute),
-               DEFBOOL,
-       }, {
-               .desc = "Capture crop left margin",
-               .name = "crop_left",
-               .internal_id = PVR2_CID_CROPL,
-               .default_value = 0,
-               DEFREF(cropl),
-               DEFINT(-129, 340),
-               .get_min_value = ctrl_cropl_min_get,
-               .get_max_value = ctrl_cropl_max_get,
-               .get_def_value = ctrl_get_cropcapdl,
-       }, {
-               .desc = "Capture crop top margin",
-               .name = "crop_top",
-               .internal_id = PVR2_CID_CROPT,
-               .default_value = 0,
-               DEFREF(cropt),
-               DEFINT(-35, 544),
-               .get_min_value = ctrl_cropt_min_get,
-               .get_max_value = ctrl_cropt_max_get,
-               .get_def_value = ctrl_get_cropcapdt,
-       }, {
-               .desc = "Capture crop width",
-               .name = "crop_width",
-               .internal_id = PVR2_CID_CROPW,
-               .default_value = 720,
-               DEFREF(cropw),
-               DEFINT(0, 864),
-               .get_max_value = ctrl_cropw_max_get,
-               .get_def_value = ctrl_get_cropcapdw,
-       }, {
-               .desc = "Capture crop height",
-               .name = "crop_height",
-               .internal_id = PVR2_CID_CROPH,
-               .default_value = 480,
-               DEFREF(croph),
-               DEFINT(0, 576),
-               .get_max_value = ctrl_croph_max_get,
-               .get_def_value = ctrl_get_cropcapdh,
-       }, {
-               .desc = "Capture capability pixel aspect numerator",
-               .name = "cropcap_pixel_numerator",
-               .internal_id = PVR2_CID_CROPCAPPAN,
-               .get_value = ctrl_get_cropcappan,
-       }, {
-               .desc = "Capture capability pixel aspect denominator",
-               .name = "cropcap_pixel_denominator",
-               .internal_id = PVR2_CID_CROPCAPPAD,
-               .get_value = ctrl_get_cropcappad,
-       }, {
-               .desc = "Capture capability bounds top",
-               .name = "cropcap_bounds_top",
-               .internal_id = PVR2_CID_CROPCAPBT,
-               .get_value = ctrl_get_cropcapbt,
-       }, {
-               .desc = "Capture capability bounds left",
-               .name = "cropcap_bounds_left",
-               .internal_id = PVR2_CID_CROPCAPBL,
-               .get_value = ctrl_get_cropcapbl,
-       }, {
-               .desc = "Capture capability bounds width",
-               .name = "cropcap_bounds_width",
-               .internal_id = PVR2_CID_CROPCAPBW,
-               .get_value = ctrl_get_cropcapbw,
-       }, {
-               .desc = "Capture capability bounds height",
-               .name = "cropcap_bounds_height",
-               .internal_id = PVR2_CID_CROPCAPBH,
-               .get_value = ctrl_get_cropcapbh,
-       },{
-               .desc = "Video Source",
-               .name = "input",
-               .internal_id = PVR2_CID_INPUT,
-               .default_value = PVR2_CVAL_INPUT_TV,
-               .check_value = ctrl_check_input,
-               DEFREF(input),
-               DEFENUM(control_values_input),
-       },{
-               .desc = "Audio Mode",
-               .name = "audio_mode",
-               .internal_id = PVR2_CID_AUDIOMODE,
-               .default_value = V4L2_TUNER_MODE_STEREO,
-               DEFREF(audiomode),
-               DEFENUM(control_values_audiomode),
-       },{
-               .desc = "Horizontal capture resolution",
-               .name = "resolution_hor",
-               .internal_id = PVR2_CID_HRES,
-               .default_value = 720,
-               DEFREF(res_hor),
-               DEFINT(19,720),
-       },{
-               .desc = "Vertical capture resolution",
-               .name = "resolution_ver",
-               .internal_id = PVR2_CID_VRES,
-               .default_value = 480,
-               DEFREF(res_ver),
-               DEFINT(17,576),
-               /* Hook in check for video standard and adjust maximum
-                  depending on the standard. */
-               .get_max_value = ctrl_vres_max_get,
-               .get_min_value = ctrl_vres_min_get,
-       },{
-               .v4l_id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
-               .default_value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
-               .desc = "Audio Sampling Frequency",
-               .name = "srate",
-               DEFREF(srate),
-               DEFENUM(control_values_srate),
-       },{
-               .desc = "Tuner Frequency (Hz)",
-               .name = "frequency",
-               .internal_id = PVR2_CID_FREQUENCY,
-               .default_value = 0,
-               .set_value = ctrl_freq_set,
-               .get_value = ctrl_freq_get,
-               .is_dirty = ctrl_freq_is_dirty,
-               .clear_dirty = ctrl_freq_clear_dirty,
-               DEFINT(0,0),
-               /* Hook in check for input value (tv/radio) and adjust
-                  max/min values accordingly */
-               .get_max_value = ctrl_freq_max_get,
-               .get_min_value = ctrl_freq_min_get,
-       },{
-               .desc = "Channel",
-               .name = "channel",
-               .set_value = ctrl_channel_set,
-               .get_value = ctrl_channel_get,
-               DEFINT(0,FREQTABLE_SIZE),
-       },{
-               .desc = "Channel Program Frequency",
-               .name = "freq_table_value",
-               .set_value = ctrl_channelfreq_set,
-               .get_value = ctrl_channelfreq_get,
-               DEFINT(0,0),
-               /* Hook in check for input value (tv/radio) and adjust
-                  max/min values accordingly */
-               .get_max_value = ctrl_freq_max_get,
-               .get_min_value = ctrl_freq_min_get,
-       },{
-               .desc = "Channel Program ID",
-               .name = "freq_table_channel",
-               .set_value = ctrl_channelprog_set,
-               .get_value = ctrl_channelprog_get,
-               DEFINT(0,FREQTABLE_SIZE),
-       },{
-               .desc = "Streaming Enabled",
-               .name = "streaming_enabled",
-               .get_value = ctrl_streamingenabled_get,
-               DEFBOOL,
-       },{
-               .desc = "USB Speed",
-               .name = "usb_speed",
-               .get_value = ctrl_hsm_get,
-               DEFENUM(control_values_hsm),
-       },{
-               .desc = "Master State",
-               .name = "master_state",
-               .get_value = ctrl_masterstate_get,
-               DEFENUM(pvr2_state_names),
-       },{
-               .desc = "Signal Present",
-               .name = "signal_present",
-               .get_value = ctrl_signal_get,
-               DEFINT(0,65535),
-       },{
-               .desc = "Audio Modes Present",
-               .name = "audio_modes_present",
-               .get_value = ctrl_audio_modes_present_get,
-               /* For this type we "borrow" the V4L2_TUNER_MODE enum from
-                  v4l.  Nothing outside of this module cares about this,
-                  but I reuse it in order to also reuse the
-                  control_values_audiomode string table. */
-               DEFMASK(((1 << V4L2_TUNER_MODE_MONO)|
-                        (1 << V4L2_TUNER_MODE_STEREO)|
-                        (1 << V4L2_TUNER_MODE_LANG1)|
-                        (1 << V4L2_TUNER_MODE_LANG2)),
-                       control_values_audiomode),
-       },{
-               .desc = "Video Standards Available Mask",
-               .name = "video_standard_mask_available",
-               .internal_id = PVR2_CID_STDAVAIL,
-               .skip_init = !0,
-               .get_value = ctrl_stdavail_get,
-               .set_value = ctrl_stdavail_set,
-               .val_to_sym = ctrl_std_val_to_sym,
-               .sym_to_val = ctrl_std_sym_to_val,
-               .type = pvr2_ctl_bitmask,
-       },{
-               .desc = "Video Standards In Use Mask",
-               .name = "video_standard_mask_active",
-               .internal_id = PVR2_CID_STDCUR,
-               .skip_init = !0,
-               .get_value = ctrl_stdcur_get,
-               .set_value = ctrl_stdcur_set,
-               .is_dirty = ctrl_stdcur_is_dirty,
-               .clear_dirty = ctrl_stdcur_clear_dirty,
-               .val_to_sym = ctrl_std_val_to_sym,
-               .sym_to_val = ctrl_std_sym_to_val,
-               .type = pvr2_ctl_bitmask,
-       },{
-               .desc = "Video Standards Detected Mask",
-               .name = "video_standard_mask_detected",
-               .internal_id = PVR2_CID_STDDETECT,
-               .skip_init = !0,
-               .get_value = ctrl_stddetect_get,
-               .val_to_sym = ctrl_std_val_to_sym,
-               .sym_to_val = ctrl_std_sym_to_val,
-               .type = pvr2_ctl_bitmask,
-       }
-};
-
-#define CTRLDEF_COUNT ARRAY_SIZE(control_defs)
-
-
-const char *pvr2_config_get_name(enum pvr2_config cfg)
-{
-       switch (cfg) {
-       case pvr2_config_empty: return "empty";
-       case pvr2_config_mpeg: return "mpeg";
-       case pvr2_config_vbi: return "vbi";
-       case pvr2_config_pcm: return "pcm";
-       case pvr2_config_rawvideo: return "raw video";
-       }
-       return "<unknown>";
-}
-
-
-struct usb_device *pvr2_hdw_get_dev(struct pvr2_hdw *hdw)
-{
-       return hdw->usb_dev;
-}
-
-
-unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *hdw)
-{
-       return hdw->serial_number;
-}
-
-
-const char *pvr2_hdw_get_bus_info(struct pvr2_hdw *hdw)
-{
-       return hdw->bus_info;
-}
-
-
-const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *hdw)
-{
-       return hdw->identifier;
-}
-
-
-unsigned long pvr2_hdw_get_cur_freq(struct pvr2_hdw *hdw)
-{
-       return hdw->freqSelector ? hdw->freqValTelevision : hdw->freqValRadio;
-}
-
-/* Set the currently tuned frequency and account for all possible
-   driver-core side effects of this action. */
-static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *hdw,unsigned long val)
-{
-       if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
-               if (hdw->freqSelector) {
-                       /* Swing over to radio frequency selection */
-                       hdw->freqSelector = 0;
-                       hdw->freqDirty = !0;
-               }
-               if (hdw->freqValRadio != val) {
-                       hdw->freqValRadio = val;
-                       hdw->freqSlotRadio = 0;
-                       hdw->freqDirty = !0;
-               }
-       } else {
-               if (!(hdw->freqSelector)) {
-                       /* Swing over to television frequency selection */
-                       hdw->freqSelector = 1;
-                       hdw->freqDirty = !0;
-               }
-               if (hdw->freqValTelevision != val) {
-                       hdw->freqValTelevision = val;
-                       hdw->freqSlotTelevision = 0;
-                       hdw->freqDirty = !0;
-               }
-       }
-}
-
-int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw)
-{
-       return hdw->unit_number;
-}
-
-
-/* Attempt to locate one of the given set of files.  Messages are logged
-   appropriate to what has been found.  The return value will be 0 or
-   greater on success (it will be the index of the file name found) and
-   fw_entry will be filled in.  Otherwise a negative error is returned on
-   failure.  If the return value is -ENOENT then no viable firmware file
-   could be located. */
-static int pvr2_locate_firmware(struct pvr2_hdw *hdw,
-                               const struct firmware **fw_entry,
-                               const char *fwtypename,
-                               unsigned int fwcount,
-                               const char *fwnames[])
-{
-       unsigned int idx;
-       int ret = -EINVAL;
-       for (idx = 0; idx < fwcount; idx++) {
-               ret = request_firmware(fw_entry,
-                                      fwnames[idx],
-                                      &hdw->usb_dev->dev);
-               if (!ret) {
-                       trace_firmware("Located %s firmware: %s;"
-                                      " uploading...",
-                                      fwtypename,
-                                      fwnames[idx]);
-                       return idx;
-               }
-               if (ret == -ENOENT) continue;
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "request_firmware fatal error with code=%d",ret);
-               return ret;
-       }
-       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                  "***WARNING***"
-                  " Device %s firmware"
-                  " seems to be missing.",
-                  fwtypename);
-       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                  "Did you install the pvrusb2 firmware files"
-                  " in their proper location?");
-       if (fwcount == 1) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "request_firmware unable to locate %s file %s",
-                          fwtypename,fwnames[0]);
-       } else {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "request_firmware unable to locate"
-                          " one of the following %s files:",
-                          fwtypename);
-               for (idx = 0; idx < fwcount; idx++) {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "request_firmware: Failed to find %s",
-                                  fwnames[idx]);
-               }
-       }
-       return ret;
-}
-
-
-/*
- * pvr2_upload_firmware1().
- *
- * Send the 8051 firmware to the device.  After the upload, arrange for
- * device to re-enumerate.
- *
- * NOTE : the pointer to the firmware data given by request_firmware()
- * is not suitable for an usb transaction.
- *
- */
-static int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
-{
-       const struct firmware *fw_entry = NULL;
-       void  *fw_ptr;
-       unsigned int pipe;
-       unsigned int fwsize;
-       int ret;
-       u16 address;
-
-       if (!hdw->hdw_desc->fx2_firmware.cnt) {
-               hdw->fw1_state = FW1_STATE_OK;
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Connected device type defines"
-                          " no firmware to upload; ignoring firmware");
-               return -ENOTTY;
-       }
-
-       hdw->fw1_state = FW1_STATE_FAILED; // default result
-
-       trace_firmware("pvr2_upload_firmware1");
-
-       ret = pvr2_locate_firmware(hdw,&fw_entry,"fx2 controller",
-                                  hdw->hdw_desc->fx2_firmware.cnt,
-                                  hdw->hdw_desc->fx2_firmware.lst);
-       if (ret < 0) {
-               if (ret == -ENOENT) hdw->fw1_state = FW1_STATE_MISSING;
-               return ret;
-       }
-
-       usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f));
-
-       pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
-       fwsize = fw_entry->size;
-
-       if ((fwsize != 0x2000) &&
-           (!(hdw->hdw_desc->flag_fx2_16kb && (fwsize == 0x4000)))) {
-               if (hdw->hdw_desc->flag_fx2_16kb) {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "Wrong fx2 firmware size"
-                                  " (expected 8192 or 16384, got %u)",
-                                  fwsize);
-               } else {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "Wrong fx2 firmware size"
-                                  " (expected 8192, got %u)",
-                                  fwsize);
-               }
-               release_firmware(fw_entry);
-               return -ENOMEM;
-       }
-
-       fw_ptr = kmalloc(0x800, GFP_KERNEL);
-       if (fw_ptr == NULL){
-               release_firmware(fw_entry);
-               return -ENOMEM;
-       }
-
-       /* We have to hold the CPU during firmware upload. */
-       pvr2_hdw_cpureset_assert(hdw,1);
-
-       /* upload the firmware to address 0000-1fff in 2048 (=0x800) bytes
-          chunk. */
-
-       ret = 0;
-       for (address = 0; address < fwsize; address += 0x800) {
-               memcpy(fw_ptr, fw_entry->data + address, 0x800);
-               ret += usb_control_msg(hdw->usb_dev, pipe, 0xa0, 0x40, address,
-                                      0, fw_ptr, 0x800, HZ);
-       }
-
-       trace_firmware("Upload done, releasing device's CPU");
-
-       /* Now release the CPU.  It will disconnect and reconnect later. */
-       pvr2_hdw_cpureset_assert(hdw,0);
-
-       kfree(fw_ptr);
-       release_firmware(fw_entry);
-
-       trace_firmware("Upload done (%d bytes sent)",ret);
-
-       /* We should have written fwsize bytes */
-       if (ret == fwsize) {
-               hdw->fw1_state = FW1_STATE_RELOAD;
-               return 0;
-       }
-
-       return -EIO;
-}
-
-
-/*
- * pvr2_upload_firmware2()
- *
- * This uploads encoder firmware on endpoint 2.
- *
- */
-
-int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
-{
-       const struct firmware *fw_entry = NULL;
-       void  *fw_ptr;
-       unsigned int pipe, fw_len, fw_done, bcnt, icnt;
-       int actual_length;
-       int ret = 0;
-       int fwidx;
-       static const char *fw_files[] = {
-               CX2341X_FIRM_ENC_FILENAME,
-       };
-
-       if (hdw->hdw_desc->flag_skip_cx23416_firmware) {
-               return 0;
-       }
-
-       trace_firmware("pvr2_upload_firmware2");
-
-       ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder",
-                                  ARRAY_SIZE(fw_files), fw_files);
-       if (ret < 0) return ret;
-       fwidx = ret;
-       ret = 0;
-       /* Since we're about to completely reinitialize the encoder,
-          invalidate our cached copy of its configuration state.  Next
-          time we configure the encoder, then we'll fully configure it. */
-       hdw->enc_cur_valid = 0;
-
-       /* Encoder is about to be reset so note that as far as we're
-          concerned now, the encoder has never been run. */
-       del_timer_sync(&hdw->encoder_run_timer);
-       if (hdw->state_encoder_runok) {
-               hdw->state_encoder_runok = 0;
-               trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
-       }
-
-       /* First prepare firmware loading */
-       ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/
-       ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/
-       ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/
-       ret |= pvr2_hdw_cmd_deep_reset(hdw);
-       ret |= pvr2_write_register(hdw, 0xa064, 0x00000000); /*APU command*/
-       ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000408); /*gpio dir*/
-       ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/
-       ret |= pvr2_write_register(hdw, 0x9058, 0xffffffed); /*VPU ctrl*/
-       ret |= pvr2_write_register(hdw, 0x9054, 0xfffffffd); /*reset hw blocks*/
-       ret |= pvr2_write_register(hdw, 0x07f8, 0x80000800); /*encoder SDRAM refresh*/
-       ret |= pvr2_write_register(hdw, 0x07fc, 0x0000001a); /*encoder SDRAM pre-charge*/
-       ret |= pvr2_write_register(hdw, 0x0700, 0x00000000); /*I2C clock*/
-       ret |= pvr2_write_register(hdw, 0xaa00, 0x00000000); /*unknown*/
-       ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/
-       ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/
-       ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/
-       ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_FWPOST1);
-       ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
-
-       if (ret) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "firmware2 upload prep failed, ret=%d",ret);
-               release_firmware(fw_entry);
-               goto done;
-       }
-
-       /* Now send firmware */
-
-       fw_len = fw_entry->size;
-
-       if (fw_len % sizeof(u32)) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "size of %s firmware"
-                          " must be a multiple of %zu bytes",
-                          fw_files[fwidx],sizeof(u32));
-               release_firmware(fw_entry);
-               ret = -EINVAL;
-               goto done;
-       }
-
-       fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
-       if (fw_ptr == NULL){
-               release_firmware(fw_entry);
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "failed to allocate memory for firmware2 upload");
-               ret = -ENOMEM;
-               goto done;
-       }
-
-       pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT);
-
-       fw_done = 0;
-       for (fw_done = 0; fw_done < fw_len;) {
-               bcnt = fw_len - fw_done;
-               if (bcnt > FIRMWARE_CHUNK_SIZE) bcnt = FIRMWARE_CHUNK_SIZE;
-               memcpy(fw_ptr, fw_entry->data + fw_done, bcnt);
-               /* Usbsnoop log shows that we must swap bytes... */
-               /* Some background info: The data being swapped here is a
-                  firmware image destined for the mpeg encoder chip that
-                  lives at the other end of a USB endpoint.  The encoder
-                  chip always talks in 32 bit chunks and its storage is
-                  organized into 32 bit words.  However from the file
-                  system to the encoder chip everything is purely a byte
-                  stream.  The firmware file's contents are always 32 bit
-                  swapped from what the encoder expects.  Thus the need
-                  always exists to swap the bytes regardless of the endian
-                  type of the host processor and therefore swab32() makes
-                  the most sense. */
-               for (icnt = 0; icnt < bcnt/4 ; icnt++)
-                       ((u32 *)fw_ptr)[icnt] = swab32(((u32 *)fw_ptr)[icnt]);
-
-               ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt,
-                                   &actual_length, HZ);
-               ret |= (actual_length != bcnt);
-               if (ret) break;
-               fw_done += bcnt;
-       }
-
-       trace_firmware("upload of %s : %i / %i ",
-                      fw_files[fwidx],fw_done,fw_len);
-
-       kfree(fw_ptr);
-       release_firmware(fw_entry);
-
-       if (ret) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "firmware2 upload transfer failure");
-               goto done;
-       }
-
-       /* Finish upload */
-
-       ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/
-       ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/
-       ret |= pvr2_issue_simple_cmd(hdw,FX2CMD_MEMSEL | (1 << 8) | (0 << 16));
-
-       if (ret) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "firmware2 upload post-proc failure");
-       }
-
- done:
-       if (hdw->hdw_desc->signal_routing_scheme ==
-           PVR2_ROUTING_SCHEME_GOTVIEW) {
-               /* Ensure that GPIO 11 is set to output for GOTVIEW
-                  hardware. */
-               pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
-       }
-       return ret;
-}
-
-
-static const char *pvr2_get_state_name(unsigned int st)
-{
-       if (st < ARRAY_SIZE(pvr2_state_names)) {
-               return pvr2_state_names[st];
-       }
-       return "???";
-}
-
-static int pvr2_decoder_enable(struct pvr2_hdw *hdw,int enablefl)
-{
-       /* Even though we really only care about the video decoder chip at
-          this point, we'll broadcast stream on/off to all sub-devices
-          anyway, just in case somebody else wants to hear the
-          command... */
-       pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 stream=%s",
-                  (enablefl ? "on" : "off"));
-       v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_stream, enablefl);
-       v4l2_device_call_all(&hdw->v4l2_dev, 0, audio, s_stream, enablefl);
-       if (hdw->decoder_client_id) {
-               /* We get here if the encoder has been noticed.  Otherwise
-                  we'll issue a warning to the user (which should
-                  normally never happen). */
-               return 0;
-       }
-       if (!hdw->flag_decoder_missed) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "WARNING: No decoder present");
-               hdw->flag_decoder_missed = !0;
-               trace_stbit("flag_decoder_missed",
-                           hdw->flag_decoder_missed);
-       }
-       return -EIO;
-}
-
-
-int pvr2_hdw_get_state(struct pvr2_hdw *hdw)
-{
-       return hdw->master_state;
-}
-
-
-static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *hdw)
-{
-       if (!hdw->flag_tripped) return 0;
-       hdw->flag_tripped = 0;
-       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                  "Clearing driver error statuss");
-       return !0;
-}
-
-
-int pvr2_hdw_untrip(struct pvr2_hdw *hdw)
-{
-       int fl;
-       LOCK_TAKE(hdw->big_lock); do {
-               fl = pvr2_hdw_untrip_unlocked(hdw);
-       } while (0); LOCK_GIVE(hdw->big_lock);
-       if (fl) pvr2_hdw_state_sched(hdw);
-       return 0;
-}
-
-
-
-
-int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw)
-{
-       return hdw->state_pipeline_req != 0;
-}
-
-
-int pvr2_hdw_set_streaming(struct pvr2_hdw *hdw,int enable_flag)
-{
-       int ret,st;
-       LOCK_TAKE(hdw->big_lock); do {
-               pvr2_hdw_untrip_unlocked(hdw);
-               if ((!enable_flag) != !(hdw->state_pipeline_req)) {
-                       hdw->state_pipeline_req = enable_flag != 0;
-                       pvr2_trace(PVR2_TRACE_START_STOP,
-                                  "/*--TRACE_STREAM--*/ %s",
-                                  enable_flag ? "enable" : "disable");
-               }
-               pvr2_hdw_state_sched(hdw);
-       } while (0); LOCK_GIVE(hdw->big_lock);
-       if ((ret = pvr2_hdw_wait(hdw,0)) < 0) return ret;
-       if (enable_flag) {
-               while ((st = hdw->master_state) != PVR2_STATE_RUN) {
-                       if (st != PVR2_STATE_READY) return -EIO;
-                       if ((ret = pvr2_hdw_wait(hdw,st)) < 0) return ret;
-               }
-       }
-       return 0;
-}
-
-
-int pvr2_hdw_set_stream_type(struct pvr2_hdw *hdw,enum pvr2_config config)
-{
-       int fl;
-       LOCK_TAKE(hdw->big_lock);
-       if ((fl = (hdw->desired_stream_type != config)) != 0) {
-               hdw->desired_stream_type = config;
-               hdw->state_pipeline_config = 0;
-               trace_stbit("state_pipeline_config",
-                           hdw->state_pipeline_config);
-               pvr2_hdw_state_sched(hdw);
-       }
-       LOCK_GIVE(hdw->big_lock);
-       if (fl) return 0;
-       return pvr2_hdw_wait(hdw,0);
-}
-
-
-static int get_default_tuner_type(struct pvr2_hdw *hdw)
-{
-       int unit_number = hdw->unit_number;
-       int tp = -1;
-       if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
-               tp = tuner[unit_number];
-       }
-       if (tp < 0) return -EINVAL;
-       hdw->tuner_type = tp;
-       hdw->tuner_updated = !0;
-       return 0;
-}
-
-
-static v4l2_std_id get_default_standard(struct pvr2_hdw *hdw)
-{
-       int unit_number = hdw->unit_number;
-       int tp = 0;
-       if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
-               tp = video_std[unit_number];
-               if (tp) return tp;
-       }
-       return 0;
-}
-
-
-static unsigned int get_default_error_tolerance(struct pvr2_hdw *hdw)
-{
-       int unit_number = hdw->unit_number;
-       int tp = 0;
-       if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
-               tp = tolerance[unit_number];
-       }
-       return tp;
-}
-
-
-static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw)
-{
-       /* Try a harmless request to fetch the eeprom's address over
-          endpoint 1.  See what happens.  Only the full FX2 image can
-          respond to this.  If this probe fails then likely the FX2
-          firmware needs be loaded. */
-       int result;
-       LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] = FX2CMD_GET_EEPROM_ADDR;
-               result = pvr2_send_request_ex(hdw,HZ*1,!0,
-                                          hdw->cmd_buffer,1,
-                                          hdw->cmd_buffer,1);
-               if (result < 0) break;
-       } while(0); LOCK_GIVE(hdw->ctl_lock);
-       if (result) {
-               pvr2_trace(PVR2_TRACE_INIT,
-                          "Probe of device endpoint 1 result status %d",
-                          result);
-       } else {
-               pvr2_trace(PVR2_TRACE_INIT,
-                          "Probe of device endpoint 1 succeeded");
-       }
-       return result == 0;
-}
-
-struct pvr2_std_hack {
-       v4l2_std_id pat;  /* Pattern to match */
-       v4l2_std_id msk;  /* Which bits we care about */
-       v4l2_std_id std;  /* What additional standards or default to set */
-};
-
-/* This data structure labels specific combinations of standards from
-   tveeprom that we'll try to recognize.  If we recognize one, then assume
-   a specified default standard to use.  This is here because tveeprom only
-   tells us about available standards not the intended default standard (if
-   any) for the device in question.  We guess the default based on what has
-   been reported as available.  Note that this is only for guessing a
-   default - which can always be overridden explicitly - and if the user
-   has otherwise named a default then that default will always be used in
-   place of this table. */
-static const struct pvr2_std_hack std_eeprom_maps[] = {
-       {       /* PAL(B/G) */
-               .pat = V4L2_STD_B|V4L2_STD_GH,
-               .std = V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_PAL_G,
-       },
-       {       /* NTSC(M) */
-               .pat = V4L2_STD_MN,
-               .std = V4L2_STD_NTSC_M,
-       },
-       {       /* PAL(I) */
-               .pat = V4L2_STD_PAL_I,
-               .std = V4L2_STD_PAL_I,
-       },
-       {       /* SECAM(L/L') */
-               .pat = V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC,
-               .std = V4L2_STD_SECAM_L|V4L2_STD_SECAM_LC,
-       },
-       {       /* PAL(D/D1/K) */
-               .pat = V4L2_STD_DK,
-               .std = V4L2_STD_PAL_D|V4L2_STD_PAL_D1|V4L2_STD_PAL_K,
-       },
-};
-
-static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
-{
-       char buf[40];
-       unsigned int bcnt;
-       v4l2_std_id std1,std2,std3;
-
-       std1 = get_default_standard(hdw);
-       std3 = std1 ? 0 : hdw->hdw_desc->default_std_mask;
-
-       bcnt = pvr2_std_id_to_str(buf,sizeof(buf),hdw->std_mask_eeprom);
-       pvr2_trace(PVR2_TRACE_STD,
-                  "Supported video standard(s) reported available"
-                  " in hardware: %.*s",
-                  bcnt,buf);
-
-       hdw->std_mask_avail = hdw->std_mask_eeprom;
-
-       std2 = (std1|std3) & ~hdw->std_mask_avail;
-       if (std2) {
-               bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std2);
-               pvr2_trace(PVR2_TRACE_STD,
-                          "Expanding supported video standards"
-                          " to include: %.*s",
-                          bcnt,buf);
-               hdw->std_mask_avail |= std2;
-       }
-
-       hdw->std_info_cur.def.type_bitmask.valid_bits = hdw->std_mask_avail;
-
-       if (std1) {
-               bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std1);
-               pvr2_trace(PVR2_TRACE_STD,
-                          "Initial video standard forced to %.*s",
-                          bcnt,buf);
-               hdw->std_mask_cur = std1;
-               hdw->std_dirty = !0;
-               return;
-       }
-       if (std3) {
-               bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std3);
-               pvr2_trace(PVR2_TRACE_STD,
-                          "Initial video standard"
-                          " (determined by device type): %.*s",bcnt,buf);
-               hdw->std_mask_cur = std3;
-               hdw->std_dirty = !0;
-               return;
-       }
-
-       {
-               unsigned int idx;
-               for (idx = 0; idx < ARRAY_SIZE(std_eeprom_maps); idx++) {
-                       if (std_eeprom_maps[idx].msk ?
-                           ((std_eeprom_maps[idx].pat ^
-                            hdw->std_mask_eeprom) &
-                            std_eeprom_maps[idx].msk) :
-                           (std_eeprom_maps[idx].pat !=
-                            hdw->std_mask_eeprom)) continue;
-                       bcnt = pvr2_std_id_to_str(buf,sizeof(buf),
-                                                 std_eeprom_maps[idx].std);
-                       pvr2_trace(PVR2_TRACE_STD,
-                                  "Initial video standard guessed as %.*s",
-                                  bcnt,buf);
-                       hdw->std_mask_cur = std_eeprom_maps[idx].std;
-                       hdw->std_dirty = !0;
-                       return;
-               }
-       }
-
-}
-
-
-static unsigned int pvr2_copy_i2c_addr_list(
-       unsigned short *dst, const unsigned char *src,
-       unsigned int dst_max)
-{
-       unsigned int cnt = 0;
-       if (!src) return 0;
-       while (src[cnt] && (cnt + 1) < dst_max) {
-               dst[cnt] = src[cnt];
-               cnt++;
-       }
-       dst[cnt] = I2C_CLIENT_END;
-       return cnt;
-}
-
-
-static void pvr2_hdw_cx25840_vbi_hack(struct pvr2_hdw *hdw)
-{
-       /*
-         Mike Isely <isely@pobox.com> 19-Nov-2006 - This bit of nuttiness
-         for cx25840 causes that module to correctly set up its video
-         scaling.  This is really a problem in the cx25840 module itself,
-         but we work around it here.  The problem has not been seen in
-         ivtv because there VBI is supported and set up.  We don't do VBI
-         here (at least not yet) and thus we never attempted to even set
-         it up.
-       */
-       struct v4l2_format fmt;
-       if (hdw->decoder_client_id != PVR2_CLIENT_ID_CX25840) {
-               /* We're not using a cx25840 so don't enable the hack */
-               return;
-       }
-
-       pvr2_trace(PVR2_TRACE_INIT,
-                  "Module ID %u:"
-                  " Executing cx25840 VBI hack",
-                  hdw->decoder_client_id);
-       memset(&fmt, 0, sizeof(fmt));
-       fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
-       fmt.fmt.sliced.service_lines[0][21] = V4L2_SLICED_CAPTION_525;
-       fmt.fmt.sliced.service_lines[1][21] = V4L2_SLICED_CAPTION_525;
-       v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id,
-                            vbi, s_sliced_fmt, &fmt.fmt.sliced);
-}
-
-
-static int pvr2_hdw_load_subdev(struct pvr2_hdw *hdw,
-                               const struct pvr2_device_client_desc *cd)
-{
-       const char *fname;
-       unsigned char mid;
-       struct v4l2_subdev *sd;
-       unsigned int i2ccnt;
-       const unsigned char *p;
-       /* Arbitrary count - max # i2c addresses we will probe */
-       unsigned short i2caddr[25];
-
-       mid = cd->module_id;
-       fname = (mid < ARRAY_SIZE(module_names)) ? module_names[mid] : NULL;
-       if (!fname) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Module ID %u for device %s has no name?"
-                          "  The driver might have a configuration problem.",
-                          mid,
-                          hdw->hdw_desc->description);
-               return -EINVAL;
-       }
-       pvr2_trace(PVR2_TRACE_INIT,
-                  "Module ID %u (%s) for device %s being loaded...",
-                  mid, fname,
-                  hdw->hdw_desc->description);
-
-       i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, cd->i2c_address_list,
-                                        ARRAY_SIZE(i2caddr));
-       if (!i2ccnt && ((p = (mid < ARRAY_SIZE(module_i2c_addresses)) ?
-                        module_i2c_addresses[mid] : NULL) != NULL)) {
-               /* Second chance: Try default i2c address list */
-               i2ccnt = pvr2_copy_i2c_addr_list(i2caddr, p,
-                                                ARRAY_SIZE(i2caddr));
-               if (i2ccnt) {
-                       pvr2_trace(PVR2_TRACE_INIT,
-                                  "Module ID %u:"
-                                  " Using default i2c address list",
-                                  mid);
-               }
-       }
-
-       if (!i2ccnt) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Module ID %u (%s) for device %s:"
-                          " No i2c addresses."
-                          "  The driver might have a configuration problem.",
-                          mid, fname, hdw->hdw_desc->description);
-               return -EINVAL;
-       }
-
-       if (i2ccnt == 1) {
-               pvr2_trace(PVR2_TRACE_INIT,
-                          "Module ID %u:"
-                          " Setting up with specified i2c address 0x%x",
-                          mid, i2caddr[0]);
-               sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap,
-                                        fname, i2caddr[0], NULL);
-       } else {
-               pvr2_trace(PVR2_TRACE_INIT,
-                          "Module ID %u:"
-                          " Setting up with address probe list",
-                          mid);
-               sd = v4l2_i2c_new_subdev(&hdw->v4l2_dev, &hdw->i2c_adap,
-                                        fname, 0, i2caddr);
-       }
-
-       if (!sd) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Module ID %u (%s) for device %s failed to load."
-                          "  Possible missing sub-device kernel module or"
-                          " initialization failure within module.",
-                          mid, fname, hdw->hdw_desc->description);
-               return -EIO;
-       }
-
-       /* Tag this sub-device instance with the module ID we know about.
-          In other places we'll use that tag to determine if the instance
-          requires special handling. */
-       sd->grp_id = mid;
-
-       pvr2_trace(PVR2_TRACE_INFO, "Attached sub-driver %s", fname);
-
-
-       /* client-specific setup... */
-       switch (mid) {
-       case PVR2_CLIENT_ID_CX25840:
-       case PVR2_CLIENT_ID_SAA7115:
-               hdw->decoder_client_id = mid;
-               break;
-       default: break;
-       }
-
-       return 0;
-}
-
-
-static void pvr2_hdw_load_modules(struct pvr2_hdw *hdw)
-{
-       unsigned int idx;
-       const struct pvr2_string_table *cm;
-       const struct pvr2_device_client_table *ct;
-       int okFl = !0;
-
-       cm = &hdw->hdw_desc->client_modules;
-       for (idx = 0; idx < cm->cnt; idx++) {
-               request_module(cm->lst[idx]);
-       }
-
-       ct = &hdw->hdw_desc->client_table;
-       for (idx = 0; idx < ct->cnt; idx++) {
-               if (pvr2_hdw_load_subdev(hdw, &ct->lst[idx]) < 0) okFl = 0;
-       }
-       if (!okFl) {
-               hdw->flag_modulefail = !0;
-               pvr2_hdw_render_useless(hdw);
-       }
-}
-
-
-static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
-{
-       int ret;
-       unsigned int idx;
-       struct pvr2_ctrl *cptr;
-       int reloadFl = 0;
-       if (hdw->hdw_desc->fx2_firmware.cnt) {
-               if (!reloadFl) {
-                       reloadFl =
-                               (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints
-                                == 0);
-                       if (reloadFl) {
-                               pvr2_trace(PVR2_TRACE_INIT,
-                                          "USB endpoint config looks strange"
-                                          "; possibly firmware needs to be"
-                                          " loaded");
-                       }
-               }
-               if (!reloadFl) {
-                       reloadFl = !pvr2_hdw_check_firmware(hdw);
-                       if (reloadFl) {
-                               pvr2_trace(PVR2_TRACE_INIT,
-                                          "Check for FX2 firmware failed"
-                                          "; possibly firmware needs to be"
-                                          " loaded");
-                       }
-               }
-               if (reloadFl) {
-                       if (pvr2_upload_firmware1(hdw) != 0) {
-                               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                          "Failure uploading firmware1");
-                       }
-                       return;
-               }
-       }
-       hdw->fw1_state = FW1_STATE_OK;
-
-       if (!pvr2_hdw_dev_ok(hdw)) return;
-
-       hdw->force_dirty = !0;
-
-       if (!hdw->hdw_desc->flag_no_powerup) {
-               pvr2_hdw_cmd_powerup(hdw);
-               if (!pvr2_hdw_dev_ok(hdw)) return;
-       }
-
-       /* Take the IR chip out of reset, if appropriate */
-       if (hdw->ir_scheme_active == PVR2_IR_SCHEME_ZILOG) {
-               pvr2_issue_simple_cmd(hdw,
-                                     FX2CMD_HCW_ZILOG_RESET |
-                                     (1 << 8) |
-                                     ((0) << 16));
-       }
-
-       // This step MUST happen after the earlier powerup step.
-       pvr2_i2c_core_init(hdw);
-       if (!pvr2_hdw_dev_ok(hdw)) return;
-
-       pvr2_hdw_load_modules(hdw);
-       if (!pvr2_hdw_dev_ok(hdw)) return;
-
-       v4l2_device_call_all(&hdw->v4l2_dev, 0, core, load_fw);
-
-       for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
-               cptr = hdw->controls + idx;
-               if (cptr->info->skip_init) continue;
-               if (!cptr->info->set_value) continue;
-               cptr->info->set_value(cptr,~0,cptr->info->default_value);
-       }
-
-       pvr2_hdw_cx25840_vbi_hack(hdw);
-
-       /* Set up special default values for the television and radio
-          frequencies here.  It's not really important what these defaults
-          are, but I set them to something usable in the Chicago area just
-          to make driver testing a little easier. */
-
-       hdw->freqValTelevision = default_tv_freq;
-       hdw->freqValRadio = default_radio_freq;
-
-       // Do not use pvr2_reset_ctl_endpoints() here.  It is not
-       // thread-safe against the normal pvr2_send_request() mechanism.
-       // (We should make it thread safe).
-
-       if (hdw->hdw_desc->flag_has_hauppauge_rom) {
-               ret = pvr2_hdw_get_eeprom_addr(hdw);
-               if (!pvr2_hdw_dev_ok(hdw)) return;
-               if (ret < 0) {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "Unable to determine location of eeprom,"
-                                  " skipping");
-               } else {
-                       hdw->eeprom_addr = ret;
-                       pvr2_eeprom_analyze(hdw);
-                       if (!pvr2_hdw_dev_ok(hdw)) return;
-               }
-       } else {
-               hdw->tuner_type = hdw->hdw_desc->default_tuner_type;
-               hdw->tuner_updated = !0;
-               hdw->std_mask_eeprom = V4L2_STD_ALL;
-       }
-
-       if (hdw->serial_number) {
-               idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1,
-                               "sn-%lu", hdw->serial_number);
-       } else if (hdw->unit_number >= 0) {
-               idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1,
-                               "unit-%c",
-                               hdw->unit_number + 'a');
-       } else {
-               idx = scnprintf(hdw->identifier, sizeof(hdw->identifier) - 1,
-                               "unit-??");
-       }
-       hdw->identifier[idx] = 0;
-
-       pvr2_hdw_setup_std(hdw);
-
-       if (!get_default_tuner_type(hdw)) {
-               pvr2_trace(PVR2_TRACE_INIT,
-                          "pvr2_hdw_setup: Tuner type overridden to %d",
-                          hdw->tuner_type);
-       }
-
-
-       if (!pvr2_hdw_dev_ok(hdw)) return;
-
-       if (hdw->hdw_desc->signal_routing_scheme ==
-           PVR2_ROUTING_SCHEME_GOTVIEW) {
-               /* Ensure that GPIO 11 is set to output for GOTVIEW
-                  hardware. */
-               pvr2_hdw_gpio_chg_dir(hdw,(1 << 11),~0);
-       }
-
-       pvr2_hdw_commit_setup(hdw);
-
-       hdw->vid_stream = pvr2_stream_create();
-       if (!pvr2_hdw_dev_ok(hdw)) return;
-       pvr2_trace(PVR2_TRACE_INIT,
-                  "pvr2_hdw_setup: video stream is %p",hdw->vid_stream);
-       if (hdw->vid_stream) {
-               idx = get_default_error_tolerance(hdw);
-               if (idx) {
-                       pvr2_trace(PVR2_TRACE_INIT,
-                                  "pvr2_hdw_setup: video stream %p"
-                                  " setting tolerance %u",
-                                  hdw->vid_stream,idx);
-               }
-               pvr2_stream_setup(hdw->vid_stream,hdw->usb_dev,
-                                 PVR2_VID_ENDPOINT,idx);
-       }
-
-       if (!pvr2_hdw_dev_ok(hdw)) return;
-
-       hdw->flag_init_ok = !0;
-
-       pvr2_hdw_state_sched(hdw);
-}
-
-
-/* Set up the structure and attempt to put the device into a usable state.
-   This can be a time-consuming operation, which is why it is not done
-   internally as part of the create() step. */
-static void pvr2_hdw_setup(struct pvr2_hdw *hdw)
-{
-       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) begin",hdw);
-       do {
-               pvr2_hdw_setup_low(hdw);
-               pvr2_trace(PVR2_TRACE_INIT,
-                          "pvr2_hdw_setup(hdw=%p) done, ok=%d init_ok=%d",
-                          hdw,pvr2_hdw_dev_ok(hdw),hdw->flag_init_ok);
-               if (pvr2_hdw_dev_ok(hdw)) {
-                       if (hdw->flag_init_ok) {
-                               pvr2_trace(
-                                       PVR2_TRACE_INFO,
-                                       "Device initialization"
-                                       " completed successfully.");
-                               break;
-                       }
-                       if (hdw->fw1_state == FW1_STATE_RELOAD) {
-                               pvr2_trace(
-                                       PVR2_TRACE_INFO,
-                                       "Device microcontroller firmware"
-                                       " (re)loaded; it should now reset"
-                                       " and reconnect.");
-                               break;
-                       }
-                       pvr2_trace(
-                               PVR2_TRACE_ERROR_LEGS,
-                               "Device initialization was not successful.");
-                       if (hdw->fw1_state == FW1_STATE_MISSING) {
-                               pvr2_trace(
-                                       PVR2_TRACE_ERROR_LEGS,
-                                       "Giving up since device"
-                                       " microcontroller firmware"
-                                       " appears to be missing.");
-                               break;
-                       }
-               }
-               if (hdw->flag_modulefail) {
-                       pvr2_trace(
-                               PVR2_TRACE_ERROR_LEGS,
-                               "***WARNING*** pvrusb2 driver initialization"
-                               " failed due to the failure of one or more"
-                               " sub-device kernel modules.");
-                       pvr2_trace(
-                               PVR2_TRACE_ERROR_LEGS,
-                               "You need to resolve the failing condition"
-                               " before this driver can function.  There"
-                               " should be some earlier messages giving more"
-                               " information about the problem.");
-                       break;
-               }
-               if (procreload) {
-                       pvr2_trace(
-                               PVR2_TRACE_ERROR_LEGS,
-                               "Attempting pvrusb2 recovery by reloading"
-                               " primary firmware.");
-                       pvr2_trace(
-                               PVR2_TRACE_ERROR_LEGS,
-                               "If this works, device should disconnect"
-                               " and reconnect in a sane state.");
-                       hdw->fw1_state = FW1_STATE_UNKNOWN;
-                       pvr2_upload_firmware1(hdw);
-               } else {
-                       pvr2_trace(
-                               PVR2_TRACE_ERROR_LEGS,
-                               "***WARNING*** pvrusb2 device hardware"
-                               " appears to be jammed"
-                               " and I can't clear it.");
-                       pvr2_trace(
-                               PVR2_TRACE_ERROR_LEGS,
-                               "You might need to power cycle"
-                               " the pvrusb2 device"
-                               " in order to recover.");
-               }
-       } while (0);
-       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) end",hdw);
-}
-
-
-/* Perform second stage initialization.  Set callback pointer first so that
-   we can avoid a possible initialization race (if the kernel thread runs
-   before the callback has been set). */
-int pvr2_hdw_initialize(struct pvr2_hdw *hdw,
-                       void (*callback_func)(void *),
-                       void *callback_data)
-{
-       LOCK_TAKE(hdw->big_lock); do {
-               if (hdw->flag_disconnected) {
-                       /* Handle a race here: If we're already
-                          disconnected by this point, then give up.  If we
-                          get past this then we'll remain connected for
-                          the duration of initialization since the entire
-                          initialization sequence is now protected by the
-                          big_lock. */
-                       break;
-               }
-               hdw->state_data = callback_data;
-               hdw->state_func = callback_func;
-               pvr2_hdw_setup(hdw);
-       } while (0); LOCK_GIVE(hdw->big_lock);
-       return hdw->flag_init_ok;
-}
-
-
-/* Create, set up, and return a structure for interacting with the
-   underlying hardware.  */
-struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
-                                const struct usb_device_id *devid)
-{
-       unsigned int idx,cnt1,cnt2,m;
-       struct pvr2_hdw *hdw = NULL;
-       int valid_std_mask;
-       struct pvr2_ctrl *cptr;
-       struct usb_device *usb_dev;
-       const struct pvr2_device_desc *hdw_desc;
-       __u8 ifnum;
-       struct v4l2_queryctrl qctrl;
-       struct pvr2_ctl_info *ciptr;
-
-       usb_dev = interface_to_usbdev(intf);
-
-       hdw_desc = (const struct pvr2_device_desc *)(devid->driver_info);
-
-       if (hdw_desc == NULL) {
-               pvr2_trace(PVR2_TRACE_INIT, "pvr2_hdw_create:"
-                          " No device description pointer,"
-                          " unable to continue.");
-               pvr2_trace(PVR2_TRACE_INIT, "If you have a new device type,"
-                          " please contact Mike Isely <isely@pobox.com>"
-                          " to get it included in the driver\n");
-               goto fail;
-       }
-
-       hdw = kzalloc(sizeof(*hdw),GFP_KERNEL);
-       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"",
-                  hdw,hdw_desc->description);
-       pvr2_trace(PVR2_TRACE_INFO, "Hardware description: %s",
-               hdw_desc->description);
-       if (hdw_desc->flag_is_experimental) {
-               pvr2_trace(PVR2_TRACE_INFO, "**********");
-               pvr2_trace(PVR2_TRACE_INFO,
-                          "WARNING: Support for this device (%s) is"
-                          " experimental.", hdw_desc->description);
-               pvr2_trace(PVR2_TRACE_INFO,
-                          "Important functionality might not be"
-                          " entirely working.");
-               pvr2_trace(PVR2_TRACE_INFO,
-                          "Please consider contacting the driver author to"
-                          " help with further stabilization of the driver.");
-               pvr2_trace(PVR2_TRACE_INFO, "**********");
-       }
-       if (!hdw) goto fail;
-
-       init_timer(&hdw->quiescent_timer);
-       hdw->quiescent_timer.data = (unsigned long)hdw;
-       hdw->quiescent_timer.function = pvr2_hdw_quiescent_timeout;
-
-       init_timer(&hdw->decoder_stabilization_timer);
-       hdw->decoder_stabilization_timer.data = (unsigned long)hdw;
-       hdw->decoder_stabilization_timer.function =
-               pvr2_hdw_decoder_stabilization_timeout;
-
-       init_timer(&hdw->encoder_wait_timer);
-       hdw->encoder_wait_timer.data = (unsigned long)hdw;
-       hdw->encoder_wait_timer.function = pvr2_hdw_encoder_wait_timeout;
-
-       init_timer(&hdw->encoder_run_timer);
-       hdw->encoder_run_timer.data = (unsigned long)hdw;
-       hdw->encoder_run_timer.function = pvr2_hdw_encoder_run_timeout;
-
-       hdw->master_state = PVR2_STATE_DEAD;
-
-       init_waitqueue_head(&hdw->state_wait_data);
-
-       hdw->tuner_signal_stale = !0;
-       cx2341x_fill_defaults(&hdw->enc_ctl_state);
-
-       /* Calculate which inputs are OK */
-       m = 0;
-       if (hdw_desc->flag_has_analogtuner) m |= 1 << PVR2_CVAL_INPUT_TV;
-       if (hdw_desc->digital_control_scheme != PVR2_DIGITAL_SCHEME_NONE) {
-               m |= 1 << PVR2_CVAL_INPUT_DTV;
-       }
-       if (hdw_desc->flag_has_svideo) m |= 1 << PVR2_CVAL_INPUT_SVIDEO;
-       if (hdw_desc->flag_has_composite) m |= 1 << PVR2_CVAL_INPUT_COMPOSITE;
-       if (hdw_desc->flag_has_fmradio) m |= 1 << PVR2_CVAL_INPUT_RADIO;
-       hdw->input_avail_mask = m;
-       hdw->input_allowed_mask = hdw->input_avail_mask;
-
-       /* If not a hybrid device, pathway_state never changes.  So
-          initialize it here to what it should forever be. */
-       if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_DTV))) {
-               hdw->pathway_state = PVR2_PATHWAY_ANALOG;
-       } else if (!(hdw->input_avail_mask & (1 << PVR2_CVAL_INPUT_TV))) {
-               hdw->pathway_state = PVR2_PATHWAY_DIGITAL;
-       }
-
-       hdw->control_cnt = CTRLDEF_COUNT;
-       hdw->control_cnt += MPEGDEF_COUNT;
-       hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
-                               GFP_KERNEL);
-       if (!hdw->controls) goto fail;
-       hdw->hdw_desc = hdw_desc;
-       hdw->ir_scheme_active = hdw->hdw_desc->ir_scheme;
-       for (idx = 0; idx < hdw->control_cnt; idx++) {
-               cptr = hdw->controls + idx;
-               cptr->hdw = hdw;
-       }
-       for (idx = 0; idx < 32; idx++) {
-               hdw->std_mask_ptrs[idx] = hdw->std_mask_names[idx];
-       }
-       for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
-               cptr = hdw->controls + idx;
-               cptr->info = control_defs+idx;
-       }
-
-       /* Ensure that default input choice is a valid one. */
-       m = hdw->input_avail_mask;
-       if (m) for (idx = 0; idx < (sizeof(m) << 3); idx++) {
-               if (!((1 << idx) & m)) continue;
-               hdw->input_val = idx;
-               break;
-       }
-
-       /* Define and configure additional controls from cx2341x module. */
-       hdw->mpeg_ctrl_info = kcalloc(MPEGDEF_COUNT,
-                                     sizeof(*(hdw->mpeg_ctrl_info)),
-                                     GFP_KERNEL);
-       if (!hdw->mpeg_ctrl_info) goto fail;
-       for (idx = 0; idx < MPEGDEF_COUNT; idx++) {
-               cptr = hdw->controls + idx + CTRLDEF_COUNT;
-               ciptr = &(hdw->mpeg_ctrl_info[idx].info);
-               ciptr->desc = hdw->mpeg_ctrl_info[idx].desc;
-               ciptr->name = mpeg_ids[idx].strid;
-               ciptr->v4l_id = mpeg_ids[idx].id;
-               ciptr->skip_init = !0;
-               ciptr->get_value = ctrl_cx2341x_get;
-               ciptr->get_v4lflags = ctrl_cx2341x_getv4lflags;
-               ciptr->is_dirty = ctrl_cx2341x_is_dirty;
-               if (!idx) ciptr->clear_dirty = ctrl_cx2341x_clear_dirty;
-               qctrl.id = ciptr->v4l_id;
-               cx2341x_ctrl_query(&hdw->enc_ctl_state,&qctrl);
-               if (!(qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY)) {
-                       ciptr->set_value = ctrl_cx2341x_set;
-               }
-               strncpy(hdw->mpeg_ctrl_info[idx].desc,qctrl.name,
-                       PVR2_CTLD_INFO_DESC_SIZE);
-               hdw->mpeg_ctrl_info[idx].desc[PVR2_CTLD_INFO_DESC_SIZE-1] = 0;
-               ciptr->default_value = qctrl.default_value;
-               switch (qctrl.type) {
-               default:
-               case V4L2_CTRL_TYPE_INTEGER:
-                       ciptr->type = pvr2_ctl_int;
-                       ciptr->def.type_int.min_value = qctrl.minimum;
-                       ciptr->def.type_int.max_value = qctrl.maximum;
-                       break;
-               case V4L2_CTRL_TYPE_BOOLEAN:
-                       ciptr->type = pvr2_ctl_bool;
-                       break;
-               case V4L2_CTRL_TYPE_MENU:
-                       ciptr->type = pvr2_ctl_enum;
-                       ciptr->def.type_enum.value_names =
-                               cx2341x_ctrl_get_menu(&hdw->enc_ctl_state,
-                                                               ciptr->v4l_id);
-                       for (cnt1 = 0;
-                            ciptr->def.type_enum.value_names[cnt1] != NULL;
-                            cnt1++) { }
-                       ciptr->def.type_enum.count = cnt1;
-                       break;
-               }
-               cptr->info = ciptr;
-       }
-
-       // Initialize control data regarding video standard masks
-       valid_std_mask = pvr2_std_get_usable();
-       for (idx = 0; idx < 32; idx++) {
-               if (!(valid_std_mask & (1 << idx))) continue;
-               cnt1 = pvr2_std_id_to_str(
-                       hdw->std_mask_names[idx],
-                       sizeof(hdw->std_mask_names[idx])-1,
-                       1 << idx);
-               hdw->std_mask_names[idx][cnt1] = 0;
-       }
-       cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDAVAIL);
-       if (cptr) {
-               memcpy(&hdw->std_info_avail,cptr->info,
-                      sizeof(hdw->std_info_avail));
-               cptr->info = &hdw->std_info_avail;
-               hdw->std_info_avail.def.type_bitmask.bit_names =
-                       hdw->std_mask_ptrs;
-               hdw->std_info_avail.def.type_bitmask.valid_bits =
-                       valid_std_mask;
-       }
-       cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR);
-       if (cptr) {
-               memcpy(&hdw->std_info_cur,cptr->info,
-                      sizeof(hdw->std_info_cur));
-               cptr->info = &hdw->std_info_cur;
-               hdw->std_info_cur.def.type_bitmask.bit_names =
-                       hdw->std_mask_ptrs;
-               hdw->std_info_cur.def.type_bitmask.valid_bits =
-                       valid_std_mask;
-       }
-       cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDDETECT);
-       if (cptr) {
-               memcpy(&hdw->std_info_detect,cptr->info,
-                      sizeof(hdw->std_info_detect));
-               cptr->info = &hdw->std_info_detect;
-               hdw->std_info_detect.def.type_bitmask.bit_names =
-                       hdw->std_mask_ptrs;
-               hdw->std_info_detect.def.type_bitmask.valid_bits =
-                       valid_std_mask;
-       }
-
-       hdw->cropcap_stale = !0;
-       hdw->eeprom_addr = -1;
-       hdw->unit_number = -1;
-       hdw->v4l_minor_number_video = -1;
-       hdw->v4l_minor_number_vbi = -1;
-       hdw->v4l_minor_number_radio = -1;
-       hdw->ctl_write_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
-       if (!hdw->ctl_write_buffer) goto fail;
-       hdw->ctl_read_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
-       if (!hdw->ctl_read_buffer) goto fail;
-       hdw->ctl_write_urb = usb_alloc_urb(0,GFP_KERNEL);
-       if (!hdw->ctl_write_urb) goto fail;
-       hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL);
-       if (!hdw->ctl_read_urb) goto fail;
-
-       if (v4l2_device_register(&intf->dev, &hdw->v4l2_dev) != 0) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Error registering with v4l core, giving up");
-               goto fail;
-       }
-       mutex_lock(&pvr2_unit_mtx); do {
-               for (idx = 0; idx < PVR_NUM; idx++) {
-                       if (unit_pointers[idx]) continue;
-                       hdw->unit_number = idx;
-                       unit_pointers[idx] = hdw;
-                       break;
-               }
-       } while (0); mutex_unlock(&pvr2_unit_mtx);
-
-       cnt1 = 0;
-       cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2");
-       cnt1 += cnt2;
-       if (hdw->unit_number >= 0) {
-               cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"_%c",
-                                ('a' + hdw->unit_number));
-               cnt1 += cnt2;
-       }
-       if (cnt1 >= sizeof(hdw->name)) cnt1 = sizeof(hdw->name)-1;
-       hdw->name[cnt1] = 0;
-
-       hdw->workqueue = create_singlethread_workqueue(hdw->name);
-       INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll);
-
-       pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",
-                  hdw->unit_number,hdw->name);
-
-       hdw->tuner_type = -1;
-       hdw->flag_ok = !0;
-
-       hdw->usb_intf = intf;
-       hdw->usb_dev = usb_dev;
-
-       usb_make_path(hdw->usb_dev, hdw->bus_info, sizeof(hdw->bus_info));
-
-       ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber;
-       usb_set_interface(hdw->usb_dev,ifnum,0);
-
-       mutex_init(&hdw->ctl_lock_mutex);
-       mutex_init(&hdw->big_lock_mutex);
-
-       return hdw;
- fail:
-       if (hdw) {
-               del_timer_sync(&hdw->quiescent_timer);
-               del_timer_sync(&hdw->decoder_stabilization_timer);
-               del_timer_sync(&hdw->encoder_run_timer);
-               del_timer_sync(&hdw->encoder_wait_timer);
-               if (hdw->workqueue) {
-                       flush_workqueue(hdw->workqueue);
-                       destroy_workqueue(hdw->workqueue);
-                       hdw->workqueue = NULL;
-               }
-               usb_free_urb(hdw->ctl_read_urb);
-               usb_free_urb(hdw->ctl_write_urb);
-               kfree(hdw->ctl_read_buffer);
-               kfree(hdw->ctl_write_buffer);
-               kfree(hdw->controls);
-               kfree(hdw->mpeg_ctrl_info);
-               kfree(hdw);
-       }
-       return NULL;
-}
-
-
-/* Remove _all_ associations between this driver and the underlying USB
-   layer. */
-static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw)
-{
-       if (hdw->flag_disconnected) return;
-       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_remove_usb_stuff: hdw=%p",hdw);
-       if (hdw->ctl_read_urb) {
-               usb_kill_urb(hdw->ctl_read_urb);
-               usb_free_urb(hdw->ctl_read_urb);
-               hdw->ctl_read_urb = NULL;
-       }
-       if (hdw->ctl_write_urb) {
-               usb_kill_urb(hdw->ctl_write_urb);
-               usb_free_urb(hdw->ctl_write_urb);
-               hdw->ctl_write_urb = NULL;
-       }
-       if (hdw->ctl_read_buffer) {
-               kfree(hdw->ctl_read_buffer);
-               hdw->ctl_read_buffer = NULL;
-       }
-       if (hdw->ctl_write_buffer) {
-               kfree(hdw->ctl_write_buffer);
-               hdw->ctl_write_buffer = NULL;
-       }
-       hdw->flag_disconnected = !0;
-       /* If we don't do this, then there will be a dangling struct device
-          reference to our disappearing device persisting inside the V4L
-          core... */
-       v4l2_device_disconnect(&hdw->v4l2_dev);
-       hdw->usb_dev = NULL;
-       hdw->usb_intf = NULL;
-       pvr2_hdw_render_useless(hdw);
-}
-
-
-/* Destroy hardware interaction structure */
-void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
-{
-       if (!hdw) return;
-       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw);
-       if (hdw->workqueue) {
-               flush_workqueue(hdw->workqueue);
-               destroy_workqueue(hdw->workqueue);
-               hdw->workqueue = NULL;
-       }
-       del_timer_sync(&hdw->quiescent_timer);
-       del_timer_sync(&hdw->decoder_stabilization_timer);
-       del_timer_sync(&hdw->encoder_run_timer);
-       del_timer_sync(&hdw->encoder_wait_timer);
-       if (hdw->fw_buffer) {
-               kfree(hdw->fw_buffer);
-               hdw->fw_buffer = NULL;
-       }
-       if (hdw->vid_stream) {
-               pvr2_stream_destroy(hdw->vid_stream);
-               hdw->vid_stream = NULL;
-       }
-       pvr2_i2c_core_done(hdw);
-       v4l2_device_unregister(&hdw->v4l2_dev);
-       pvr2_hdw_remove_usb_stuff(hdw);
-       mutex_lock(&pvr2_unit_mtx); do {
-               if ((hdw->unit_number >= 0) &&
-                   (hdw->unit_number < PVR_NUM) &&
-                   (unit_pointers[hdw->unit_number] == hdw)) {
-                       unit_pointers[hdw->unit_number] = NULL;
-               }
-       } while (0); mutex_unlock(&pvr2_unit_mtx);
-       kfree(hdw->controls);
-       kfree(hdw->mpeg_ctrl_info);
-       kfree(hdw);
-}
-
-
-int pvr2_hdw_dev_ok(struct pvr2_hdw *hdw)
-{
-       return (hdw && hdw->flag_ok);
-}
-
-
-/* Called when hardware has been unplugged */
-void pvr2_hdw_disconnect(struct pvr2_hdw *hdw)
-{
-       pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_disconnect(hdw=%p)",hdw);
-       LOCK_TAKE(hdw->big_lock);
-       LOCK_TAKE(hdw->ctl_lock);
-       pvr2_hdw_remove_usb_stuff(hdw);
-       LOCK_GIVE(hdw->ctl_lock);
-       LOCK_GIVE(hdw->big_lock);
-}
-
-
-/* Get the number of defined controls */
-unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw)
-{
-       return hdw->control_cnt;
-}
-
-
-/* Retrieve a control handle given its index (0..count-1) */
-struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *hdw,
-                                            unsigned int idx)
-{
-       if (idx >= hdw->control_cnt) return NULL;
-       return hdw->controls + idx;
-}
-
-
-/* Retrieve a control handle given its index (0..count-1) */
-struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *hdw,
-                                         unsigned int ctl_id)
-{
-       struct pvr2_ctrl *cptr;
-       unsigned int idx;
-       int i;
-
-       /* This could be made a lot more efficient, but for now... */
-       for (idx = 0; idx < hdw->control_cnt; idx++) {
-               cptr = hdw->controls + idx;
-               i = cptr->info->internal_id;
-               if (i && (i == ctl_id)) return cptr;
-       }
-       return NULL;
-}
-
-
-/* Given a V4L ID, retrieve the control structure associated with it. */
-struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *hdw,unsigned int ctl_id)
-{
-       struct pvr2_ctrl *cptr;
-       unsigned int idx;
-       int i;
-
-       /* This could be made a lot more efficient, but for now... */
-       for (idx = 0; idx < hdw->control_cnt; idx++) {
-               cptr = hdw->controls + idx;
-               i = cptr->info->v4l_id;
-               if (i && (i == ctl_id)) return cptr;
-       }
-       return NULL;
-}
-
-
-/* Given a V4L ID for its immediate predecessor, retrieve the control
-   structure associated with it. */
-struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *hdw,
-                                           unsigned int ctl_id)
-{
-       struct pvr2_ctrl *cptr,*cp2;
-       unsigned int idx;
-       int i;
-
-       /* This could be made a lot more efficient, but for now... */
-       cp2 = NULL;
-       for (idx = 0; idx < hdw->control_cnt; idx++) {
-               cptr = hdw->controls + idx;
-               i = cptr->info->v4l_id;
-               if (!i) continue;
-               if (i <= ctl_id) continue;
-               if (cp2 && (cp2->info->v4l_id < i)) continue;
-               cp2 = cptr;
-       }
-       return cp2;
-       return NULL;
-}
-
-
-static const char *get_ctrl_typename(enum pvr2_ctl_type tp)
-{
-       switch (tp) {
-       case pvr2_ctl_int: return "integer";
-       case pvr2_ctl_enum: return "enum";
-       case pvr2_ctl_bool: return "boolean";
-       case pvr2_ctl_bitmask: return "bitmask";
-       }
-       return "";
-}
-
-
-static void pvr2_subdev_set_control(struct pvr2_hdw *hdw, int id,
-                                   const char *name, int val)
-{
-       struct v4l2_control ctrl;
-       pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 %s=%d", name, val);
-       memset(&ctrl, 0, sizeof(ctrl));
-       ctrl.id = id;
-       ctrl.value = val;
-       v4l2_device_call_all(&hdw->v4l2_dev, 0, core, s_ctrl, &ctrl);
-}
-
-#define PVR2_SUBDEV_SET_CONTROL(hdw, id, lab) \
-       if ((hdw)->lab##_dirty || (hdw)->force_dirty) {         \
-               pvr2_subdev_set_control(hdw, id, #lab, (hdw)->lab##_val); \
-       }
-
-v4l2_std_id pvr2_hdw_get_detected_std(struct pvr2_hdw *hdw)
-{
-       v4l2_std_id std;
-       std = (v4l2_std_id)hdw->std_mask_avail;
-       v4l2_device_call_all(&hdw->v4l2_dev, 0,
-                            video, querystd, &std);
-       return std;
-}
-
-/* Execute whatever commands are required to update the state of all the
-   sub-devices so that they match our current control values. */
-static void pvr2_subdev_update(struct pvr2_hdw *hdw)
-{
-       struct v4l2_subdev *sd;
-       unsigned int id;
-       pvr2_subdev_update_func fp;
-
-       pvr2_trace(PVR2_TRACE_CHIPS, "subdev update...");
-
-       if (hdw->tuner_updated || hdw->force_dirty) {
-               struct tuner_setup setup;
-               pvr2_trace(PVR2_TRACE_CHIPS, "subdev tuner set_type(%d)",
-                          hdw->tuner_type);
-               if (((int)(hdw->tuner_type)) >= 0) {
-                       memset(&setup, 0, sizeof(setup));
-                       setup.addr = ADDR_UNSET;
-                       setup.type = hdw->tuner_type;
-                       setup.mode_mask = T_RADIO | T_ANALOG_TV;
-                       v4l2_device_call_all(&hdw->v4l2_dev, 0,
-                                            tuner, s_type_addr, &setup);
-               }
-       }
-
-       if (hdw->input_dirty || hdw->std_dirty || hdw->force_dirty) {
-               pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_standard");
-               if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
-                       v4l2_device_call_all(&hdw->v4l2_dev, 0,
-                                            tuner, s_radio);
-               } else {
-                       v4l2_std_id vs;
-                       vs = hdw->std_mask_cur;
-                       v4l2_device_call_all(&hdw->v4l2_dev, 0,
-                                            core, s_std, vs);
-                       pvr2_hdw_cx25840_vbi_hack(hdw);
-               }
-               hdw->tuner_signal_stale = !0;
-               hdw->cropcap_stale = !0;
-       }
-
-       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_BRIGHTNESS, brightness);
-       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_CONTRAST, contrast);
-       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_SATURATION, saturation);
-       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_HUE, hue);
-       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_MUTE, mute);
-       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_VOLUME, volume);
-       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BALANCE, balance);
-       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_BASS, bass);
-       PVR2_SUBDEV_SET_CONTROL(hdw, V4L2_CID_AUDIO_TREBLE, treble);
-
-       if (hdw->input_dirty || hdw->audiomode_dirty || hdw->force_dirty) {
-               struct v4l2_tuner vt;
-               memset(&vt, 0, sizeof(vt));
-               vt.type = (hdw->input_val == PVR2_CVAL_INPUT_RADIO) ?
-                       V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-               vt.audmode = hdw->audiomode_val;
-               v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_tuner, &vt);
-       }
-
-       if (hdw->freqDirty || hdw->force_dirty) {
-               unsigned long fv;
-               struct v4l2_frequency freq;
-               fv = pvr2_hdw_get_cur_freq(hdw);
-               pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_freq(%lu)", fv);
-               if (hdw->tuner_signal_stale) pvr2_hdw_status_poll(hdw);
-               memset(&freq, 0, sizeof(freq));
-               if (hdw->tuner_signal_info.capability & V4L2_TUNER_CAP_LOW) {
-                       /* ((fv * 1000) / 62500) */
-                       freq.frequency = (fv * 2) / 125;
-               } else {
-                       freq.frequency = fv / 62500;
-               }
-               /* tuner-core currently doesn't seem to care about this, but
-                  let's set it anyway for completeness. */
-               if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
-                       freq.type = V4L2_TUNER_RADIO;
-               } else {
-                       freq.type = V4L2_TUNER_ANALOG_TV;
-               }
-               freq.tuner = 0;
-               v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner,
-                                    s_frequency, &freq);
-       }
-
-       if (hdw->res_hor_dirty || hdw->res_ver_dirty || hdw->force_dirty) {
-               struct v4l2_mbus_framefmt fmt;
-               memset(&fmt, 0, sizeof(fmt));
-               fmt.width = hdw->res_hor_val;
-               fmt.height = hdw->res_ver_val;
-               fmt.code = V4L2_MBUS_FMT_FIXED;
-               pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)",
-                          fmt.width, fmt.height);
-               v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_mbus_fmt, &fmt);
-       }
-
-       if (hdw->srate_dirty || hdw->force_dirty) {
-               u32 val;
-               pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_audio %d",
-                          hdw->srate_val);
-               switch (hdw->srate_val) {
-               default:
-               case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
-                       val = 48000;
-                       break;
-               case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
-                       val = 44100;
-                       break;
-               case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
-                       val = 32000;
-                       break;
-               }
-               v4l2_device_call_all(&hdw->v4l2_dev, 0,
-                                    audio, s_clock_freq, val);
-       }
-
-       /* Unable to set crop parameters; there is apparently no equivalent
-          for VIDIOC_S_CROP */
-
-       v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
-               id = sd->grp_id;
-               if (id >= ARRAY_SIZE(pvr2_module_update_functions)) continue;
-               fp = pvr2_module_update_functions[id];
-               if (!fp) continue;
-               (*fp)(hdw, sd);
-       }
-
-       if (hdw->tuner_signal_stale || hdw->cropcap_stale) {
-               pvr2_hdw_status_poll(hdw);
-       }
-}
-
-
-/* Figure out if we need to commit control changes.  If so, mark internal
-   state flags to indicate this fact and return true.  Otherwise do nothing
-   else and return false. */
-static int pvr2_hdw_commit_setup(struct pvr2_hdw *hdw)
-{
-       unsigned int idx;
-       struct pvr2_ctrl *cptr;
-       int value;
-       int commit_flag = hdw->force_dirty;
-       char buf[100];
-       unsigned int bcnt,ccnt;
-
-       for (idx = 0; idx < hdw->control_cnt; idx++) {
-               cptr = hdw->controls + idx;
-               if (!cptr->info->is_dirty) continue;
-               if (!cptr->info->is_dirty(cptr)) continue;
-               commit_flag = !0;
-
-               if (!(pvrusb2_debug & PVR2_TRACE_CTL)) continue;
-               bcnt = scnprintf(buf,sizeof(buf),"\"%s\" <-- ",
-                                cptr->info->name);
-               value = 0;
-               cptr->info->get_value(cptr,&value);
-               pvr2_ctrl_value_to_sym_internal(cptr,~0,value,
-                                               buf+bcnt,
-                                               sizeof(buf)-bcnt,&ccnt);
-               bcnt += ccnt;
-               bcnt += scnprintf(buf+bcnt,sizeof(buf)-bcnt," <%s>",
-                                 get_ctrl_typename(cptr->info->type));
-               pvr2_trace(PVR2_TRACE_CTL,
-                          "/*--TRACE_COMMIT--*/ %.*s",
-                          bcnt,buf);
-       }
-
-       if (!commit_flag) {
-               /* Nothing has changed */
-               return 0;
-       }
-
-       hdw->state_pipeline_config = 0;
-       trace_stbit("state_pipeline_config",hdw->state_pipeline_config);
-       pvr2_hdw_state_sched(hdw);
-
-       return !0;
-}
-
-
-/* Perform all operations needed to commit all control changes.  This must
-   be performed in synchronization with the pipeline state and is thus
-   expected to be called as part of the driver's worker thread.  Return
-   true if commit successful, otherwise return false to indicate that
-   commit isn't possible at this time. */
-static int pvr2_hdw_commit_execute(struct pvr2_hdw *hdw)
-{
-       unsigned int idx;
-       struct pvr2_ctrl *cptr;
-       int disruptive_change;
-
-       if (hdw->input_dirty && hdw->state_pathway_ok &&
-           (((hdw->input_val == PVR2_CVAL_INPUT_DTV) ?
-             PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG) !=
-            hdw->pathway_state)) {
-               /* Change of mode being asked for... */
-               hdw->state_pathway_ok = 0;
-               trace_stbit("state_pathway_ok", hdw->state_pathway_ok);
-       }
-       if (!hdw->state_pathway_ok) {
-               /* Can't commit anything until pathway is ok. */
-               return 0;
-       }
-
-       /* Handle some required side effects when the video standard is
-          changed.... */
-       if (hdw->std_dirty) {
-               int nvres;
-               int gop_size;
-               if (hdw->std_mask_cur & V4L2_STD_525_60) {
-                       nvres = 480;
-                       gop_size = 15;
-               } else {
-                       nvres = 576;
-                       gop_size = 12;
-               }
-               /* Rewrite the vertical resolution to be appropriate to the
-                  video standard that has been selected. */
-               if (nvres != hdw->res_ver_val) {
-                       hdw->res_ver_val = nvres;
-                       hdw->res_ver_dirty = !0;
-               }
-               /* Rewrite the GOP size to be appropriate to the video
-                  standard that has been selected. */
-               if (gop_size != hdw->enc_ctl_state.video_gop_size) {
-                       struct v4l2_ext_controls cs;
-                       struct v4l2_ext_control c1;
-                       memset(&cs, 0, sizeof(cs));
-                       memset(&c1, 0, sizeof(c1));
-                       cs.controls = &c1;
-                       cs.count = 1;
-                       c1.id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
-                       c1.value = gop_size;
-                       cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,
-                                         VIDIOC_S_EXT_CTRLS);
-               }
-       }
-
-       /* The broadcast decoder can only scale down, so if
-        * res_*_dirty && crop window < output format ==> enlarge crop.
-        *
-        * The mpeg encoder receives fields of res_hor_val dots and
-        * res_ver_val halflines.  Limits: hor<=720, ver<=576.
-        */
-       if (hdw->res_hor_dirty && hdw->cropw_val < hdw->res_hor_val) {
-               hdw->cropw_val = hdw->res_hor_val;
-               hdw->cropw_dirty = !0;
-       } else if (hdw->cropw_dirty) {
-               hdw->res_hor_dirty = !0;           /* must rescale */
-               hdw->res_hor_val = min(720, hdw->cropw_val);
-       }
-       if (hdw->res_ver_dirty && hdw->croph_val < hdw->res_ver_val) {
-               hdw->croph_val = hdw->res_ver_val;
-               hdw->croph_dirty = !0;
-       } else if (hdw->croph_dirty) {
-               int nvres = hdw->std_mask_cur & V4L2_STD_525_60 ? 480 : 576;
-               hdw->res_ver_dirty = !0;
-               hdw->res_ver_val = min(nvres, hdw->croph_val);
-       }
-
-       /* If any of the below has changed, then we can't do the update
-          while the pipeline is running.  Pipeline must be paused first
-          and decoder -> encoder connection be made quiescent before we
-          can proceed. */
-       disruptive_change =
-               (hdw->std_dirty ||
-                hdw->enc_unsafe_stale ||
-                hdw->srate_dirty ||
-                hdw->res_ver_dirty ||
-                hdw->res_hor_dirty ||
-                hdw->cropw_dirty ||
-                hdw->croph_dirty ||
-                hdw->input_dirty ||
-                (hdw->active_stream_type != hdw->desired_stream_type));
-       if (disruptive_change && !hdw->state_pipeline_idle) {
-               /* Pipeline is not idle; we can't proceed.  Arrange to
-                  cause pipeline to stop so that we can try this again
-                  later.... */
-               hdw->state_pipeline_pause = !0;
-               return 0;
-       }
-
-       if (hdw->srate_dirty) {
-               /* Write new sample rate into control structure since
-                * the master copy is stale.  We must track srate
-                * separate from the mpeg control structure because
-                * other logic also uses this value. */
-               struct v4l2_ext_controls cs;
-               struct v4l2_ext_control c1;
-               memset(&cs,0,sizeof(cs));
-               memset(&c1,0,sizeof(c1));
-               cs.controls = &c1;
-               cs.count = 1;
-               c1.id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ;
-               c1.value = hdw->srate_val;
-               cx2341x_ext_ctrls(&hdw->enc_ctl_state, 0, &cs,VIDIOC_S_EXT_CTRLS);
-       }
-
-       if (hdw->active_stream_type != hdw->desired_stream_type) {
-               /* Handle any side effects of stream config here */
-               hdw->active_stream_type = hdw->desired_stream_type;
-       }
-
-       if (hdw->hdw_desc->signal_routing_scheme ==
-           PVR2_ROUTING_SCHEME_GOTVIEW) {
-               u32 b;
-               /* Handle GOTVIEW audio switching */
-               pvr2_hdw_gpio_get_out(hdw,&b);
-               if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
-                       /* Set GPIO 11 */
-                       pvr2_hdw_gpio_chg_out(hdw,(1 << 11),~0);
-               } else {
-                       /* Clear GPIO 11 */
-                       pvr2_hdw_gpio_chg_out(hdw,(1 << 11),0);
-               }
-       }
-
-       /* Check and update state for all sub-devices. */
-       pvr2_subdev_update(hdw);
-
-       hdw->tuner_updated = 0;
-       hdw->force_dirty = 0;
-       for (idx = 0; idx < hdw->control_cnt; idx++) {
-               cptr = hdw->controls + idx;
-               if (!cptr->info->clear_dirty) continue;
-               cptr->info->clear_dirty(cptr);
-       }
-
-       if ((hdw->pathway_state == PVR2_PATHWAY_ANALOG) &&
-           hdw->state_encoder_run) {
-               /* If encoder isn't running or it can't be touched, then
-                  this will get worked out later when we start the
-                  encoder. */
-               if (pvr2_encoder_adjust(hdw) < 0) return !0;
-       }
-
-       hdw->state_pipeline_config = !0;
-       /* Hardware state may have changed in a way to cause the cropping
-          capabilities to have changed.  So mark it stale, which will
-          cause a later re-fetch. */
-       trace_stbit("state_pipeline_config",hdw->state_pipeline_config);
-       return !0;
-}
-
-
-int pvr2_hdw_commit_ctl(struct pvr2_hdw *hdw)
-{
-       int fl;
-       LOCK_TAKE(hdw->big_lock);
-       fl = pvr2_hdw_commit_setup(hdw);
-       LOCK_GIVE(hdw->big_lock);
-       if (!fl) return 0;
-       return pvr2_hdw_wait(hdw,0);
-}
-
-
-static void pvr2_hdw_worker_poll(struct work_struct *work)
-{
-       int fl = 0;
-       struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,workpoll);
-       LOCK_TAKE(hdw->big_lock); do {
-               fl = pvr2_hdw_state_eval(hdw);
-       } while (0); LOCK_GIVE(hdw->big_lock);
-       if (fl && hdw->state_func) {
-               hdw->state_func(hdw->state_data);
-       }
-}
-
-
-static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state)
-{
-       return wait_event_interruptible(
-               hdw->state_wait_data,
-               (hdw->state_stale == 0) &&
-               (!state || (hdw->master_state != state)));
-}
-
-
-/* Return name for this driver instance */
-const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
-{
-       return hdw->name;
-}
-
-
-const char *pvr2_hdw_get_desc(struct pvr2_hdw *hdw)
-{
-       return hdw->hdw_desc->description;
-}
-
-
-const char *pvr2_hdw_get_type(struct pvr2_hdw *hdw)
-{
-       return hdw->hdw_desc->shortname;
-}
-
-
-int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
-{
-       int result;
-       LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] = FX2CMD_GET_USB_SPEED;
-               result = pvr2_send_request(hdw,
-                                          hdw->cmd_buffer,1,
-                                          hdw->cmd_buffer,1);
-               if (result < 0) break;
-               result = (hdw->cmd_buffer[0] != 0);
-       } while(0); LOCK_GIVE(hdw->ctl_lock);
-       return result;
-}
-
-
-/* Execute poll of tuner status */
-void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *hdw)
-{
-       LOCK_TAKE(hdw->big_lock); do {
-               pvr2_hdw_status_poll(hdw);
-       } while (0); LOCK_GIVE(hdw->big_lock);
-}
-
-
-static int pvr2_hdw_check_cropcap(struct pvr2_hdw *hdw)
-{
-       if (!hdw->cropcap_stale) {
-               return 0;
-       }
-       pvr2_hdw_status_poll(hdw);
-       if (hdw->cropcap_stale) {
-               return -EIO;
-       }
-       return 0;
-}
-
-
-/* Return information about cropping capabilities */
-int pvr2_hdw_get_cropcap(struct pvr2_hdw *hdw, struct v4l2_cropcap *pp)
-{
-       int stat = 0;
-       LOCK_TAKE(hdw->big_lock);
-       stat = pvr2_hdw_check_cropcap(hdw);
-       if (!stat) {
-               memcpy(pp, &hdw->cropcap_info, sizeof(hdw->cropcap_info));
-       }
-       LOCK_GIVE(hdw->big_lock);
-       return stat;
-}
-
-
-/* Return information about the tuner */
-int pvr2_hdw_get_tuner_status(struct pvr2_hdw *hdw,struct v4l2_tuner *vtp)
-{
-       LOCK_TAKE(hdw->big_lock); do {
-               if (hdw->tuner_signal_stale) {
-                       pvr2_hdw_status_poll(hdw);
-               }
-               memcpy(vtp,&hdw->tuner_signal_info,sizeof(struct v4l2_tuner));
-       } while (0); LOCK_GIVE(hdw->big_lock);
-       return 0;
-}
-
-
-/* Get handle to video output stream */
-struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *hp)
-{
-       return hp->vid_stream;
-}
-
-
-void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw)
-{
-       int nr = pvr2_hdw_get_unit_number(hdw);
-       LOCK_TAKE(hdw->big_lock); do {
-               printk(KERN_INFO "pvrusb2: =================  START STATUS CARD #%d  =================\n", nr);
-               v4l2_device_call_all(&hdw->v4l2_dev, 0, core, log_status);
-               pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:");
-               cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2");
-               pvr2_hdw_state_log_state(hdw);
-               printk(KERN_INFO "pvrusb2: ==================  END STATUS CARD #%d  ==================\n", nr);
-       } while (0); LOCK_GIVE(hdw->big_lock);
-}
-
-
-/* Grab EEPROM contents, needed for direct method. */
-#define EEPROM_SIZE 8192
-#define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__)
-static u8 *pvr2_full_eeprom_fetch(struct pvr2_hdw *hdw)
-{
-       struct i2c_msg msg[2];
-       u8 *eeprom;
-       u8 iadd[2];
-       u8 addr;
-       u16 eepromSize;
-       unsigned int offs;
-       int ret;
-       int mode16 = 0;
-       unsigned pcnt,tcnt;
-       eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL);
-       if (!eeprom) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Failed to allocate memory"
-                          " required to read eeprom");
-               return NULL;
-       }
-
-       trace_eeprom("Value for eeprom addr from controller was 0x%x",
-                    hdw->eeprom_addr);
-       addr = hdw->eeprom_addr;
-       /* Seems that if the high bit is set, then the *real* eeprom
-          address is shifted right now bit position (noticed this in
-          newer PVR USB2 hardware) */
-       if (addr & 0x80) addr >>= 1;
-
-       /* FX2 documentation states that a 16bit-addressed eeprom is
-          expected if the I2C address is an odd number (yeah, this is
-          strange but it's what they do) */
-       mode16 = (addr & 1);
-       eepromSize = (mode16 ? EEPROM_SIZE : 256);
-       trace_eeprom("Examining %d byte eeprom at location 0x%x"
-                    " using %d bit addressing",eepromSize,addr,
-                    mode16 ? 16 : 8);
-
-       msg[0].addr = addr;
-       msg[0].flags = 0;
-       msg[0].len = mode16 ? 2 : 1;
-       msg[0].buf = iadd;
-       msg[1].addr = addr;
-       msg[1].flags = I2C_M_RD;
-
-       /* We have to do the actual eeprom data fetch ourselves, because
-          (1) we're only fetching part of the eeprom, and (2) if we were
-          getting the whole thing our I2C driver can't grab it in one
-          pass - which is what tveeprom is otherwise going to attempt */
-       memset(eeprom,0,EEPROM_SIZE);
-       for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) {
-               pcnt = 16;
-               if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt;
-               offs = tcnt + (eepromSize - EEPROM_SIZE);
-               if (mode16) {
-                       iadd[0] = offs >> 8;
-                       iadd[1] = offs;
-               } else {
-                       iadd[0] = offs;
-               }
-               msg[1].len = pcnt;
-               msg[1].buf = eeprom+tcnt;
-               if ((ret = i2c_transfer(&hdw->i2c_adap,
-                                       msg,ARRAY_SIZE(msg))) != 2) {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "eeprom fetch set offs err=%d",ret);
-                       kfree(eeprom);
-                       return NULL;
-               }
-       }
-       return eeprom;
-}
-
-
-void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw,
-                               int mode,
-                               int enable_flag)
-{
-       int ret;
-       u16 address;
-       unsigned int pipe;
-       LOCK_TAKE(hdw->big_lock); do {
-               if ((hdw->fw_buffer == NULL) == !enable_flag) break;
-
-               if (!enable_flag) {
-                       pvr2_trace(PVR2_TRACE_FIRMWARE,
-                                  "Cleaning up after CPU firmware fetch");
-                       kfree(hdw->fw_buffer);
-                       hdw->fw_buffer = NULL;
-                       hdw->fw_size = 0;
-                       if (hdw->fw_cpu_flag) {
-                               /* Now release the CPU.  It will disconnect
-                                  and reconnect later. */
-                               pvr2_hdw_cpureset_assert(hdw,0);
-                       }
-                       break;
-               }
-
-               hdw->fw_cpu_flag = (mode != 2);
-               if (hdw->fw_cpu_flag) {
-                       hdw->fw_size = (mode == 1) ? 0x4000 : 0x2000;
-                       pvr2_trace(PVR2_TRACE_FIRMWARE,
-                                  "Preparing to suck out CPU firmware"
-                                  " (size=%u)", hdw->fw_size);
-                       hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL);
-                       if (!hdw->fw_buffer) {
-                               hdw->fw_size = 0;
-                               break;
-                       }
-
-                       /* We have to hold the CPU during firmware upload. */
-                       pvr2_hdw_cpureset_assert(hdw,1);
-
-                       /* download the firmware from address 0000-1fff in 2048
-                          (=0x800) bytes chunk. */
-
-                       pvr2_trace(PVR2_TRACE_FIRMWARE,
-                                  "Grabbing CPU firmware");
-                       pipe = usb_rcvctrlpipe(hdw->usb_dev, 0);
-                       for(address = 0; address < hdw->fw_size;
-                           address += 0x800) {
-                               ret = usb_control_msg(hdw->usb_dev,pipe,
-                                                     0xa0,0xc0,
-                                                     address,0,
-                                                     hdw->fw_buffer+address,
-                                                     0x800,HZ);
-                               if (ret < 0) break;
-                       }
-
-                       pvr2_trace(PVR2_TRACE_FIRMWARE,
-                                  "Done grabbing CPU firmware");
-               } else {
-                       pvr2_trace(PVR2_TRACE_FIRMWARE,
-                                  "Sucking down EEPROM contents");
-                       hdw->fw_buffer = pvr2_full_eeprom_fetch(hdw);
-                       if (!hdw->fw_buffer) {
-                               pvr2_trace(PVR2_TRACE_FIRMWARE,
-                                          "EEPROM content suck failed.");
-                               break;
-                       }
-                       hdw->fw_size = EEPROM_SIZE;
-                       pvr2_trace(PVR2_TRACE_FIRMWARE,
-                                  "Done sucking down EEPROM contents");
-               }
-
-       } while (0); LOCK_GIVE(hdw->big_lock);
-}
-
-
-/* Return true if we're in a mode for retrieval CPU firmware */
-int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *hdw)
-{
-       return hdw->fw_buffer != NULL;
-}
-
-
-int pvr2_hdw_cpufw_get(struct pvr2_hdw *hdw,unsigned int offs,
-                      char *buf,unsigned int cnt)
-{
-       int ret = -EINVAL;
-       LOCK_TAKE(hdw->big_lock); do {
-               if (!buf) break;
-               if (!cnt) break;
-
-               if (!hdw->fw_buffer) {
-                       ret = -EIO;
-                       break;
-               }
-
-               if (offs >= hdw->fw_size) {
-                       pvr2_trace(PVR2_TRACE_FIRMWARE,
-                                  "Read firmware data offs=%d EOF",
-                                  offs);
-                       ret = 0;
-                       break;
-               }
-
-               if (offs + cnt > hdw->fw_size) cnt = hdw->fw_size - offs;
-
-               memcpy(buf,hdw->fw_buffer+offs,cnt);
-
-               pvr2_trace(PVR2_TRACE_FIRMWARE,
-                          "Read firmware data offs=%d cnt=%d",
-                          offs,cnt);
-               ret = cnt;
-       } while (0); LOCK_GIVE(hdw->big_lock);
-
-       return ret;
-}
-
-
-int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *hdw,
-                                 enum pvr2_v4l_type index)
-{
-       switch (index) {
-       case pvr2_v4l_type_video: return hdw->v4l_minor_number_video;
-       case pvr2_v4l_type_vbi: return hdw->v4l_minor_number_vbi;
-       case pvr2_v4l_type_radio: return hdw->v4l_minor_number_radio;
-       default: return -1;
-       }
-}
-
-
-/* Store a v4l minor device number */
-void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,
-                                    enum pvr2_v4l_type index,int v)
-{
-       switch (index) {
-       case pvr2_v4l_type_video: hdw->v4l_minor_number_video = v;
-       case pvr2_v4l_type_vbi: hdw->v4l_minor_number_vbi = v;
-       case pvr2_v4l_type_radio: hdw->v4l_minor_number_radio = v;
-       default: break;
-       }
-}
-
-
-static void pvr2_ctl_write_complete(struct urb *urb)
-{
-       struct pvr2_hdw *hdw = urb->context;
-       hdw->ctl_write_pend_flag = 0;
-       if (hdw->ctl_read_pend_flag) return;
-       complete(&hdw->ctl_done);
-}
-
-
-static void pvr2_ctl_read_complete(struct urb *urb)
-{
-       struct pvr2_hdw *hdw = urb->context;
-       hdw->ctl_read_pend_flag = 0;
-       if (hdw->ctl_write_pend_flag) return;
-       complete(&hdw->ctl_done);
-}
-
-
-static void pvr2_ctl_timeout(unsigned long data)
-{
-       struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
-       if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
-               hdw->ctl_timeout_flag = !0;
-               if (hdw->ctl_write_pend_flag)
-                       usb_unlink_urb(hdw->ctl_write_urb);
-               if (hdw->ctl_read_pend_flag)
-                       usb_unlink_urb(hdw->ctl_read_urb);
-       }
-}
-
-
-/* Issue a command and get a response from the device.  This extended
-   version includes a probe flag (which if set means that device errors
-   should not be logged or treated as fatal) and a timeout in jiffies.
-   This can be used to non-lethally probe the health of endpoint 1. */
-static int pvr2_send_request_ex(struct pvr2_hdw *hdw,
-                               unsigned int timeout,int probe_fl,
-                               void *write_data,unsigned int write_len,
-                               void *read_data,unsigned int read_len)
-{
-       unsigned int idx;
-       int status = 0;
-       struct timer_list timer;
-       if (!hdw->ctl_lock_held) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Attempted to execute control transfer"
-                          " without lock!!");
-               return -EDEADLK;
-       }
-       if (!hdw->flag_ok && !probe_fl) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Attempted to execute control transfer"
-                          " when device not ok");
-               return -EIO;
-       }
-       if (!(hdw->ctl_read_urb && hdw->ctl_write_urb)) {
-               if (!probe_fl) {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "Attempted to execute control transfer"
-                                  " when USB is disconnected");
-               }
-               return -ENOTTY;
-       }
-
-       /* Ensure that we have sane parameters */
-       if (!write_data) write_len = 0;
-       if (!read_data) read_len = 0;
-       if (write_len > PVR2_CTL_BUFFSIZE) {
-               pvr2_trace(
-                       PVR2_TRACE_ERROR_LEGS,
-                       "Attempted to execute %d byte"
-                       " control-write transfer (limit=%d)",
-                       write_len,PVR2_CTL_BUFFSIZE);
-               return -EINVAL;
-       }
-       if (read_len > PVR2_CTL_BUFFSIZE) {
-               pvr2_trace(
-                       PVR2_TRACE_ERROR_LEGS,
-                       "Attempted to execute %d byte"
-                       " control-read transfer (limit=%d)",
-                       write_len,PVR2_CTL_BUFFSIZE);
-               return -EINVAL;
-       }
-       if ((!write_len) && (!read_len)) {
-               pvr2_trace(
-                       PVR2_TRACE_ERROR_LEGS,
-                       "Attempted to execute null control transfer?");
-               return -EINVAL;
-       }
-
-
-       hdw->cmd_debug_state = 1;
-       if (write_len) {
-               hdw->cmd_debug_code = ((unsigned char *)write_data)[0];
-       } else {
-               hdw->cmd_debug_code = 0;
-       }
-       hdw->cmd_debug_write_len = write_len;
-       hdw->cmd_debug_read_len = read_len;
-
-       /* Initialize common stuff */
-       init_completion(&hdw->ctl_done);
-       hdw->ctl_timeout_flag = 0;
-       hdw->ctl_write_pend_flag = 0;
-       hdw->ctl_read_pend_flag = 0;
-       init_timer(&timer);
-       timer.expires = jiffies + timeout;
-       timer.data = (unsigned long)hdw;
-       timer.function = pvr2_ctl_timeout;
-
-       if (write_len) {
-               hdw->cmd_debug_state = 2;
-               /* Transfer write data to internal buffer */
-               for (idx = 0; idx < write_len; idx++) {
-                       hdw->ctl_write_buffer[idx] =
-                               ((unsigned char *)write_data)[idx];
-               }
-               /* Initiate a write request */
-               usb_fill_bulk_urb(hdw->ctl_write_urb,
-                                 hdw->usb_dev,
-                                 usb_sndbulkpipe(hdw->usb_dev,
-                                                 PVR2_CTL_WRITE_ENDPOINT),
-                                 hdw->ctl_write_buffer,
-                                 write_len,
-                                 pvr2_ctl_write_complete,
-                                 hdw);
-               hdw->ctl_write_urb->actual_length = 0;
-               hdw->ctl_write_pend_flag = !0;
-               status = usb_submit_urb(hdw->ctl_write_urb,GFP_KERNEL);
-               if (status < 0) {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "Failed to submit write-control"
-                                  " URB status=%d",status);
-                       hdw->ctl_write_pend_flag = 0;
-                       goto done;
-               }
-       }
-
-       if (read_len) {
-               hdw->cmd_debug_state = 3;
-               memset(hdw->ctl_read_buffer,0x43,read_len);
-               /* Initiate a read request */
-               usb_fill_bulk_urb(hdw->ctl_read_urb,
-                                 hdw->usb_dev,
-                                 usb_rcvbulkpipe(hdw->usb_dev,
-                                                 PVR2_CTL_READ_ENDPOINT),
-                                 hdw->ctl_read_buffer,
-                                 read_len,
-                                 pvr2_ctl_read_complete,
-                                 hdw);
-               hdw->ctl_read_urb->actual_length = 0;
-               hdw->ctl_read_pend_flag = !0;
-               status = usb_submit_urb(hdw->ctl_read_urb,GFP_KERNEL);
-               if (status < 0) {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "Failed to submit read-control"
-                                  " URB status=%d",status);
-                       hdw->ctl_read_pend_flag = 0;
-                       goto done;
-               }
-       }
-
-       /* Start timer */
-       add_timer(&timer);
-
-       /* Now wait for all I/O to complete */
-       hdw->cmd_debug_state = 4;
-       while (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
-               wait_for_completion(&hdw->ctl_done);
-       }
-       hdw->cmd_debug_state = 5;
-
-       /* Stop timer */
-       del_timer_sync(&timer);
-
-       hdw->cmd_debug_state = 6;
-       status = 0;
-
-       if (hdw->ctl_timeout_flag) {
-               status = -ETIMEDOUT;
-               if (!probe_fl) {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "Timed out control-write");
-               }
-               goto done;
-       }
-
-       if (write_len) {
-               /* Validate results of write request */
-               if ((hdw->ctl_write_urb->status != 0) &&
-                   (hdw->ctl_write_urb->status != -ENOENT) &&
-                   (hdw->ctl_write_urb->status != -ESHUTDOWN) &&
-                   (hdw->ctl_write_urb->status != -ECONNRESET)) {
-                       /* USB subsystem is reporting some kind of failure
-                          on the write */
-                       status = hdw->ctl_write_urb->status;
-                       if (!probe_fl) {
-                               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                          "control-write URB failure,"
-                                          " status=%d",
-                                          status);
-                       }
-                       goto done;
-               }
-               if (hdw->ctl_write_urb->actual_length < write_len) {
-                       /* Failed to write enough data */
-                       status = -EIO;
-                       if (!probe_fl) {
-                               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                          "control-write URB short,"
-                                          " expected=%d got=%d",
-                                          write_len,
-                                          hdw->ctl_write_urb->actual_length);
-                       }
-                       goto done;
-               }
-       }
-       if (read_len) {
-               /* Validate results of read request */
-               if ((hdw->ctl_read_urb->status != 0) &&
-                   (hdw->ctl_read_urb->status != -ENOENT) &&
-                   (hdw->ctl_read_urb->status != -ESHUTDOWN) &&
-                   (hdw->ctl_read_urb->status != -ECONNRESET)) {
-                       /* USB subsystem is reporting some kind of failure
-                          on the read */
-                       status = hdw->ctl_read_urb->status;
-                       if (!probe_fl) {
-                               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                          "control-read URB failure,"
-                                          " status=%d",
-                                          status);
-                       }
-                       goto done;
-               }
-               if (hdw->ctl_read_urb->actual_length < read_len) {
-                       /* Failed to read enough data */
-                       status = -EIO;
-                       if (!probe_fl) {
-                               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                          "control-read URB short,"
-                                          " expected=%d got=%d",
-                                          read_len,
-                                          hdw->ctl_read_urb->actual_length);
-                       }
-                       goto done;
-               }
-               /* Transfer retrieved data out from internal buffer */
-               for (idx = 0; idx < read_len; idx++) {
-                       ((unsigned char *)read_data)[idx] =
-                               hdw->ctl_read_buffer[idx];
-               }
-       }
-
- done:
-
-       hdw->cmd_debug_state = 0;
-       if ((status < 0) && (!probe_fl)) {
-               pvr2_hdw_render_useless(hdw);
-       }
-       return status;
-}
-
-
-int pvr2_send_request(struct pvr2_hdw *hdw,
-                     void *write_data,unsigned int write_len,
-                     void *read_data,unsigned int read_len)
-{
-       return pvr2_send_request_ex(hdw,HZ*4,0,
-                                   write_data,write_len,
-                                   read_data,read_len);
-}
-
-
-static int pvr2_issue_simple_cmd(struct pvr2_hdw *hdw,u32 cmdcode)
-{
-       int ret;
-       unsigned int cnt = 1;
-       unsigned int args = 0;
-       LOCK_TAKE(hdw->ctl_lock);
-       hdw->cmd_buffer[0] = cmdcode & 0xffu;
-       args = (cmdcode >> 8) & 0xffu;
-       args = (args > 2) ? 2 : args;
-       if (args) {
-               cnt += args;
-               hdw->cmd_buffer[1] = (cmdcode >> 16) & 0xffu;
-               if (args > 1) {
-                       hdw->cmd_buffer[2] = (cmdcode >> 24) & 0xffu;
-               }
-       }
-       if (pvrusb2_debug & PVR2_TRACE_INIT) {
-               unsigned int idx;
-               unsigned int ccnt,bcnt;
-               char tbuf[50];
-               cmdcode &= 0xffu;
-               bcnt = 0;
-               ccnt = scnprintf(tbuf+bcnt,
-                                sizeof(tbuf)-bcnt,
-                                "Sending FX2 command 0x%x",cmdcode);
-               bcnt += ccnt;
-               for (idx = 0; idx < ARRAY_SIZE(pvr2_fx2cmd_desc); idx++) {
-                       if (pvr2_fx2cmd_desc[idx].id == cmdcode) {
-                               ccnt = scnprintf(tbuf+bcnt,
-                                                sizeof(tbuf)-bcnt,
-                                                " \"%s\"",
-                                                pvr2_fx2cmd_desc[idx].desc);
-                               bcnt += ccnt;
-                               break;
-                       }
-               }
-               if (args) {
-                       ccnt = scnprintf(tbuf+bcnt,
-                                        sizeof(tbuf)-bcnt,
-                                        " (%u",hdw->cmd_buffer[1]);
-                       bcnt += ccnt;
-                       if (args > 1) {
-                               ccnt = scnprintf(tbuf+bcnt,
-                                                sizeof(tbuf)-bcnt,
-                                                ",%u",hdw->cmd_buffer[2]);
-                               bcnt += ccnt;
-                       }
-                       ccnt = scnprintf(tbuf+bcnt,
-                                        sizeof(tbuf)-bcnt,
-                                        ")");
-                       bcnt += ccnt;
-               }
-               pvr2_trace(PVR2_TRACE_INIT,"%.*s",bcnt,tbuf);
-       }
-       ret = pvr2_send_request(hdw,hdw->cmd_buffer,cnt,NULL,0);
-       LOCK_GIVE(hdw->ctl_lock);
-       return ret;
-}
-
-
-int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data)
-{
-       int ret;
-
-       LOCK_TAKE(hdw->ctl_lock);
-
-       hdw->cmd_buffer[0] = FX2CMD_REG_WRITE;  /* write register prefix */
-       PVR2_DECOMPOSE_LE(hdw->cmd_buffer,1,data);
-       hdw->cmd_buffer[5] = 0;
-       hdw->cmd_buffer[6] = (reg >> 8) & 0xff;
-       hdw->cmd_buffer[7] = reg & 0xff;
-
-
-       ret = pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 0);
-
-       LOCK_GIVE(hdw->ctl_lock);
-
-       return ret;
-}
-
-
-static int pvr2_read_register(struct pvr2_hdw *hdw, u16 reg, u32 *data)
-{
-       int ret = 0;
-
-       LOCK_TAKE(hdw->ctl_lock);
-
-       hdw->cmd_buffer[0] = FX2CMD_REG_READ;  /* read register prefix */
-       hdw->cmd_buffer[1] = 0;
-       hdw->cmd_buffer[2] = 0;
-       hdw->cmd_buffer[3] = 0;
-       hdw->cmd_buffer[4] = 0;
-       hdw->cmd_buffer[5] = 0;
-       hdw->cmd_buffer[6] = (reg >> 8) & 0xff;
-       hdw->cmd_buffer[7] = reg & 0xff;
-
-       ret |= pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 4);
-       *data = PVR2_COMPOSE_LE(hdw->cmd_buffer,0);
-
-       LOCK_GIVE(hdw->ctl_lock);
-
-       return ret;
-}
-
-
-void pvr2_hdw_render_useless(struct pvr2_hdw *hdw)
-{
-       if (!hdw->flag_ok) return;
-       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                  "Device being rendered inoperable");
-       if (hdw->vid_stream) {
-               pvr2_stream_setup(hdw->vid_stream,NULL,0,0);
-       }
-       hdw->flag_ok = 0;
-       trace_stbit("flag_ok",hdw->flag_ok);
-       pvr2_hdw_state_sched(hdw);
-}
-
-
-void pvr2_hdw_device_reset(struct pvr2_hdw *hdw)
-{
-       int ret;
-       pvr2_trace(PVR2_TRACE_INIT,"Performing a device reset...");
-       ret = usb_lock_device_for_reset(hdw->usb_dev,NULL);
-       if (ret == 0) {
-               ret = usb_reset_device(hdw->usb_dev);
-               usb_unlock_device(hdw->usb_dev);
-       } else {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Failed to lock USB device ret=%d",ret);
-       }
-       if (init_pause_msec) {
-               pvr2_trace(PVR2_TRACE_INFO,
-                          "Waiting %u msec for hardware to settle",
-                          init_pause_msec);
-               msleep(init_pause_msec);
-       }
-
-}
-
-
-void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
-{
-       char *da;
-       unsigned int pipe;
-       int ret;
-
-       if (!hdw->usb_dev) return;
-
-       da = kmalloc(16, GFP_KERNEL);
-
-       if (da == NULL) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Unable to allocate memory to control CPU reset");
-               return;
-       }
-
-       pvr2_trace(PVR2_TRACE_INIT,"cpureset_assert(%d)",val);
-
-       da[0] = val ? 0x01 : 0x00;
-
-       /* Write the CPUCS register on the 8051.  The lsb of the register
-          is the reset bit; a 1 asserts reset while a 0 clears it. */
-       pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
-       ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0x40,0xe600,0,da,1,HZ);
-       if (ret < 0) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "cpureset_assert(%d) error=%d",val,ret);
-               pvr2_hdw_render_useless(hdw);
-       }
-
-       kfree(da);
-}
-
-
-int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw)
-{
-       return pvr2_issue_simple_cmd(hdw,FX2CMD_DEEP_RESET);
-}
-
-
-int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw)
-{
-       return pvr2_issue_simple_cmd(hdw,FX2CMD_POWER_ON);
-}
-
-
-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)
-{
-       pvr2_trace(PVR2_TRACE_INIT,
-                  "Requesting decoder reset");
-       if (hdw->decoder_client_id) {
-               v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id,
-                                    core, reset, 0);
-               pvr2_hdw_cx25840_vbi_hack(hdw);
-               return 0;
-       }
-       pvr2_trace(PVR2_TRACE_INIT,
-                  "Unable to reset decoder: nothing attached");
-       return -ENOTTY;
-}
-
-
-static int pvr2_hdw_cmd_hcw_demod_reset(struct pvr2_hdw *hdw, int onoff)
-{
-       hdw->flag_ok = !0;
-       return pvr2_issue_simple_cmd(hdw,
-                                    FX2CMD_HCW_DEMOD_RESETIN |
-                                    (1 << 8) |
-                                    ((onoff ? 1 : 0) << 16));
-}
-
-
-static int pvr2_hdw_cmd_onair_fe_power_ctrl(struct pvr2_hdw *hdw, int onoff)
-{
-       hdw->flag_ok = !0;
-       return pvr2_issue_simple_cmd(hdw,(onoff ?
-                                         FX2CMD_ONAIR_DTV_POWER_ON :
-                                         FX2CMD_ONAIR_DTV_POWER_OFF));
-}
-
-
-static int pvr2_hdw_cmd_onair_digital_path_ctrl(struct pvr2_hdw *hdw,
-                                               int onoff)
-{
-       return pvr2_issue_simple_cmd(hdw,(onoff ?
-                                         FX2CMD_ONAIR_DTV_STREAMING_ON :
-                                         FX2CMD_ONAIR_DTV_STREAMING_OFF));
-}
-
-
-static void pvr2_hdw_cmd_modeswitch(struct pvr2_hdw *hdw,int digitalFl)
-{
-       int cmode;
-       /* Compare digital/analog desired setting with current setting.  If
-          they don't match, fix it... */
-       cmode = (digitalFl ? PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG);
-       if (cmode == hdw->pathway_state) {
-               /* They match; nothing to do */
-               return;
-       }
-
-       switch (hdw->hdw_desc->digital_control_scheme) {
-       case PVR2_DIGITAL_SCHEME_HAUPPAUGE:
-               pvr2_hdw_cmd_hcw_demod_reset(hdw,digitalFl);
-               if (cmode == PVR2_PATHWAY_ANALOG) {
-                       /* If moving to analog mode, also force the decoder
-                          to reset.  If no decoder is attached, then it's
-                          ok to ignore this because if/when the decoder
-                          attaches, it will reset itself at that time. */
-                       pvr2_hdw_cmd_decoder_reset(hdw);
-               }
-               break;
-       case PVR2_DIGITAL_SCHEME_ONAIR:
-               /* Supposedly we should always have the power on whether in
-                  digital or analog mode.  But for now do what appears to
-                  work... */
-               pvr2_hdw_cmd_onair_fe_power_ctrl(hdw,digitalFl);
-               break;
-       default: break;
-       }
-
-       pvr2_hdw_untrip_unlocked(hdw);
-       hdw->pathway_state = cmode;
-}
-
-
-static void pvr2_led_ctrl_hauppauge(struct pvr2_hdw *hdw, int onoff)
-{
-       /* change some GPIO data
-        *
-        * note: bit d7 of dir appears to control the LED,
-        * so we shut it off here.
-        *
-        */
-       if (onoff) {
-               pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000481);
-       } else {
-               pvr2_hdw_gpio_chg_dir(hdw, 0xffffffff, 0x00000401);
-       }
-       pvr2_hdw_gpio_chg_out(hdw, 0xffffffff, 0x00000000);
-}
-
-
-typedef void (*led_method_func)(struct pvr2_hdw *,int);
-
-static led_method_func led_methods[] = {
-       [PVR2_LED_SCHEME_HAUPPAUGE] = pvr2_led_ctrl_hauppauge,
-};
-
-
-/* Toggle LED */
-static void pvr2_led_ctrl(struct pvr2_hdw *hdw,int onoff)
-{
-       unsigned int scheme_id;
-       led_method_func fp;
-
-       if ((!onoff) == (!hdw->led_on)) return;
-
-       hdw->led_on = onoff != 0;
-
-       scheme_id = hdw->hdw_desc->led_scheme;
-       if (scheme_id < ARRAY_SIZE(led_methods)) {
-               fp = led_methods[scheme_id];
-       } else {
-               fp = NULL;
-       }
-
-       if (fp) (*fp)(hdw,onoff);
-}
-
-
-/* Stop / start video stream transport */
-static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
-{
-       int ret;
-
-       /* If we're in analog mode, then just issue the usual analog
-          command. */
-       if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
-               return pvr2_issue_simple_cmd(hdw,
-                                            (runFl ?
-                                             FX2CMD_STREAMING_ON :
-                                             FX2CMD_STREAMING_OFF));
-               /*Note: Not reached */
-       }
-
-       if (hdw->pathway_state != PVR2_PATHWAY_DIGITAL) {
-               /* Whoops, we don't know what mode we're in... */
-               return -EINVAL;
-       }
-
-       /* To get here we have to be in digital mode.  The mechanism here
-          is unfortunately different for different vendors.  So we switch
-          on the device's digital scheme attribute in order to figure out
-          what to do. */
-       switch (hdw->hdw_desc->digital_control_scheme) {
-       case PVR2_DIGITAL_SCHEME_HAUPPAUGE:
-               return pvr2_issue_simple_cmd(hdw,
-                                            (runFl ?
-                                             FX2CMD_HCW_DTV_STREAMING_ON :
-                                             FX2CMD_HCW_DTV_STREAMING_OFF));
-       case PVR2_DIGITAL_SCHEME_ONAIR:
-               ret = pvr2_issue_simple_cmd(hdw,
-                                           (runFl ?
-                                            FX2CMD_STREAMING_ON :
-                                            FX2CMD_STREAMING_OFF));
-               if (ret) return ret;
-               return pvr2_hdw_cmd_onair_digital_path_ctrl(hdw,runFl);
-       default:
-               return -EINVAL;
-       }
-}
-
-
-/* Evaluate whether or not state_pathway_ok can change */
-static int state_eval_pathway_ok(struct pvr2_hdw *hdw)
-{
-       if (hdw->state_pathway_ok) {
-               /* Nothing to do if pathway is already ok */
-               return 0;
-       }
-       if (!hdw->state_pipeline_idle) {
-               /* Not allowed to change anything if pipeline is not idle */
-               return 0;
-       }
-       pvr2_hdw_cmd_modeswitch(hdw,hdw->input_val == PVR2_CVAL_INPUT_DTV);
-       hdw->state_pathway_ok = !0;
-       trace_stbit("state_pathway_ok",hdw->state_pathway_ok);
-       return !0;
-}
-
-
-/* Evaluate whether or not state_encoder_ok can change */
-static int state_eval_encoder_ok(struct pvr2_hdw *hdw)
-{
-       if (hdw->state_encoder_ok) return 0;
-       if (hdw->flag_tripped) return 0;
-       if (hdw->state_encoder_run) return 0;
-       if (hdw->state_encoder_config) return 0;
-       if (hdw->state_decoder_run) return 0;
-       if (hdw->state_usbstream_run) return 0;
-       if (hdw->pathway_state == PVR2_PATHWAY_DIGITAL) {
-               if (!hdw->hdw_desc->flag_digital_requires_cx23416) return 0;
-       } else if (hdw->pathway_state != PVR2_PATHWAY_ANALOG) {
-               return 0;
-       }
-
-       if (pvr2_upload_firmware2(hdw) < 0) {
-               hdw->flag_tripped = !0;
-               trace_stbit("flag_tripped",hdw->flag_tripped);
-               return !0;
-       }
-       hdw->state_encoder_ok = !0;
-       trace_stbit("state_encoder_ok",hdw->state_encoder_ok);
-       return !0;
-}
-
-
-/* Evaluate whether or not state_encoder_config can change */
-static int state_eval_encoder_config(struct pvr2_hdw *hdw)
-{
-       if (hdw->state_encoder_config) {
-               if (hdw->state_encoder_ok) {
-                       if (hdw->state_pipeline_req &&
-                           !hdw->state_pipeline_pause) return 0;
-               }
-               hdw->state_encoder_config = 0;
-               hdw->state_encoder_waitok = 0;
-               trace_stbit("state_encoder_waitok",hdw->state_encoder_waitok);
-               /* paranoia - solve race if timer just completed */
-               del_timer_sync(&hdw->encoder_wait_timer);
-       } else {
-               if (!hdw->state_pathway_ok ||
-                   (hdw->pathway_state != PVR2_PATHWAY_ANALOG) ||
-                   !hdw->state_encoder_ok ||
-                   !hdw->state_pipeline_idle ||
-                   hdw->state_pipeline_pause ||
-                   !hdw->state_pipeline_req ||
-                   !hdw->state_pipeline_config) {
-                       /* We must reset the enforced wait interval if
-                          anything has happened that might have disturbed
-                          the encoder.  This should be a rare case. */
-                       if (timer_pending(&hdw->encoder_wait_timer)) {
-                               del_timer_sync(&hdw->encoder_wait_timer);
-                       }
-                       if (hdw->state_encoder_waitok) {
-                               /* Must clear the state - therefore we did
-                                  something to a state bit and must also
-                                  return true. */
-                               hdw->state_encoder_waitok = 0;
-                               trace_stbit("state_encoder_waitok",
-                                           hdw->state_encoder_waitok);
-                               return !0;
-                       }
-                       return 0;
-               }
-               if (!hdw->state_encoder_waitok) {
-                       if (!timer_pending(&hdw->encoder_wait_timer)) {
-                               /* waitok flag wasn't set and timer isn't
-                                  running.  Check flag once more to avoid
-                                  a race then start the timer.  This is
-                                  the point when we measure out a minimal
-                                  quiet interval before doing something to
-                                  the encoder. */
-                               if (!hdw->state_encoder_waitok) {
-                                       hdw->encoder_wait_timer.expires =
-                                               jiffies +
-                                               (HZ * TIME_MSEC_ENCODER_WAIT
-                                                / 1000);
-                                       add_timer(&hdw->encoder_wait_timer);
-                               }
-                       }
-                       /* We can't continue until we know we have been
-                          quiet for the interval measured by this
-                          timer. */
-                       return 0;
-               }
-               pvr2_encoder_configure(hdw);
-               if (hdw->state_encoder_ok) hdw->state_encoder_config = !0;
-       }
-       trace_stbit("state_encoder_config",hdw->state_encoder_config);
-       return !0;
-}
-
-
-/* Return true if the encoder should not be running. */
-static int state_check_disable_encoder_run(struct pvr2_hdw *hdw)
-{
-       if (!hdw->state_encoder_ok) {
-               /* Encoder isn't healthy at the moment, so stop it. */
-               return !0;
-       }
-       if (!hdw->state_pathway_ok) {
-               /* Mode is not understood at the moment (i.e. it wants to
-                  change), so encoder must be stopped. */
-               return !0;
-       }
-
-       switch (hdw->pathway_state) {
-       case PVR2_PATHWAY_ANALOG:
-               if (!hdw->state_decoder_run) {
-                       /* We're in analog mode and the decoder is not
-                          running; thus the encoder should be stopped as
-                          well. */
-                       return !0;
-               }
-               break;
-       case PVR2_PATHWAY_DIGITAL:
-               if (hdw->state_encoder_runok) {
-                       /* This is a funny case.  We're in digital mode so
-                          really the encoder should be stopped.  However
-                          if it really is running, only kill it after
-                          runok has been set.  This gives a chance for the
-                          onair quirk to function (encoder must run
-                          briefly first, at least once, before onair
-                          digital streaming can work). */
-                       return !0;
-               }
-               break;
-       default:
-               /* Unknown mode; so encoder should be stopped. */
-               return !0;
-       }
-
-       /* If we get here, we haven't found a reason to stop the
-          encoder. */
-       return 0;
-}
-
-
-/* Return true if the encoder should be running. */
-static int state_check_enable_encoder_run(struct pvr2_hdw *hdw)
-{
-       if (!hdw->state_encoder_ok) {
-               /* Don't run the encoder if it isn't healthy... */
-               return 0;
-       }
-       if (!hdw->state_pathway_ok) {
-               /* Don't run the encoder if we don't (yet) know what mode
-                  we need to be in... */
-               return 0;
-       }
-
-       switch (hdw->pathway_state) {
-       case PVR2_PATHWAY_ANALOG:
-               if (hdw->state_decoder_run && hdw->state_decoder_ready) {
-                       /* In analog mode, if the decoder is running, then
-                          run the encoder. */
-                       return !0;
-               }
-               break;
-       case PVR2_PATHWAY_DIGITAL:
-               if ((hdw->hdw_desc->digital_control_scheme ==
-                    PVR2_DIGITAL_SCHEME_ONAIR) &&
-                   !hdw->state_encoder_runok) {
-                       /* This is a quirk.  OnAir hardware won't stream
-                          digital until the encoder has been run at least
-                          once, for a minimal period of time (empiricially
-                          measured to be 1/4 second).  So if we're on
-                          OnAir hardware and the encoder has never been
-                          run at all, then start the encoder.  Normal
-                          state machine logic in the driver will
-                          automatically handle the remaining bits. */
-                       return !0;
-               }
-               break;
-       default:
-               /* For completeness (unknown mode; encoder won't run ever) */
-               break;
-       }
-       /* If we get here, then we haven't found any reason to run the
-          encoder, so don't run it. */
-       return 0;
-}
-
-
-/* Evaluate whether or not state_encoder_run can change */
-static int state_eval_encoder_run(struct pvr2_hdw *hdw)
-{
-       if (hdw->state_encoder_run) {
-               if (!state_check_disable_encoder_run(hdw)) return 0;
-               if (hdw->state_encoder_ok) {
-                       del_timer_sync(&hdw->encoder_run_timer);
-                       if (pvr2_encoder_stop(hdw) < 0) return !0;
-               }
-               hdw->state_encoder_run = 0;
-       } else {
-               if (!state_check_enable_encoder_run(hdw)) return 0;
-               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);
-                       add_timer(&hdw->encoder_run_timer);
-               }
-       }
-       trace_stbit("state_encoder_run",hdw->state_encoder_run);
-       return !0;
-}
-
-
-/* Timeout function for quiescent timer. */
-static void pvr2_hdw_quiescent_timeout(unsigned long data)
-{
-       struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
-       hdw->state_decoder_quiescent = !0;
-       trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent);
-       hdw->state_stale = !0;
-       queue_work(hdw->workqueue,&hdw->workpoll);
-}
-
-
-/* Timeout function for decoder stabilization timer. */
-static void pvr2_hdw_decoder_stabilization_timeout(unsigned long data)
-{
-       struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
-       hdw->state_decoder_ready = !0;
-       trace_stbit("state_decoder_ready", hdw->state_decoder_ready);
-       hdw->state_stale = !0;
-       queue_work(hdw->workqueue, &hdw->workpoll);
-}
-
-
-/* Timeout function for encoder wait timer. */
-static void pvr2_hdw_encoder_wait_timeout(unsigned long data)
-{
-       struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
-       hdw->state_encoder_waitok = !0;
-       trace_stbit("state_encoder_waitok",hdw->state_encoder_waitok);
-       hdw->state_stale = !0;
-       queue_work(hdw->workqueue,&hdw->workpoll);
-}
-
-
-/* Timeout function for encoder run timer. */
-static void pvr2_hdw_encoder_run_timeout(unsigned long data)
-{
-       struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
-       if (!hdw->state_encoder_runok) {
-               hdw->state_encoder_runok = !0;
-               trace_stbit("state_encoder_runok",hdw->state_encoder_runok);
-               hdw->state_stale = !0;
-               queue_work(hdw->workqueue,&hdw->workpoll);
-       }
-}
-
-
-/* Evaluate whether or not state_decoder_run can change */
-static int state_eval_decoder_run(struct pvr2_hdw *hdw)
-{
-       if (hdw->state_decoder_run) {
-               if (hdw->state_encoder_ok) {
-                       if (hdw->state_pipeline_req &&
-                           !hdw->state_pipeline_pause &&
-                           hdw->state_pathway_ok) return 0;
-               }
-               if (!hdw->flag_decoder_missed) {
-                       pvr2_decoder_enable(hdw,0);
-               }
-               hdw->state_decoder_quiescent = 0;
-               hdw->state_decoder_run = 0;
-               /* paranoia - solve race if timer(s) just completed */
-               del_timer_sync(&hdw->quiescent_timer);
-               /* Kill the stabilization timer, in case we're killing the
-                  encoder before the previous stabilization interval has
-                  been properly timed. */
-               del_timer_sync(&hdw->decoder_stabilization_timer);
-               hdw->state_decoder_ready = 0;
-       } else {
-               if (!hdw->state_decoder_quiescent) {
-                       if (!timer_pending(&hdw->quiescent_timer)) {
-                               /* We don't do something about the
-                                  quiescent timer until right here because
-                                  we also want to catch cases where the
-                                  decoder was already not running (like
-                                  after initialization) as opposed to
-                                  knowing that we had just stopped it.
-                                  The second flag check is here to cover a
-                                  race - the timer could have run and set
-                                  this flag just after the previous check
-                                  but before we did the pending check. */
-                               if (!hdw->state_decoder_quiescent) {
-                                       hdw->quiescent_timer.expires =
-                                               jiffies +
-                                               (HZ * TIME_MSEC_DECODER_WAIT
-                                                / 1000);
-                                       add_timer(&hdw->quiescent_timer);
-                               }
-                       }
-                       /* Don't allow decoder to start again until it has
-                          been quiesced first.  This little detail should
-                          hopefully further stabilize the encoder. */
-                       return 0;
-               }
-               if (!hdw->state_pathway_ok ||
-                   (hdw->pathway_state != PVR2_PATHWAY_ANALOG) ||
-                   !hdw->state_pipeline_req ||
-                   hdw->state_pipeline_pause ||
-                   !hdw->state_pipeline_config ||
-                   !hdw->state_encoder_config ||
-                   !hdw->state_encoder_ok) return 0;
-               del_timer_sync(&hdw->quiescent_timer);
-               if (hdw->flag_decoder_missed) return 0;
-               if (pvr2_decoder_enable(hdw,!0) < 0) return 0;
-               hdw->state_decoder_quiescent = 0;
-               hdw->state_decoder_ready = 0;
-               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);
-                       add_timer(&hdw->decoder_stabilization_timer);
-               } else {
-                       hdw->state_decoder_ready = !0;
-               }
-       }
-       trace_stbit("state_decoder_quiescent",hdw->state_decoder_quiescent);
-       trace_stbit("state_decoder_run",hdw->state_decoder_run);
-       trace_stbit("state_decoder_ready", hdw->state_decoder_ready);
-       return !0;
-}
-
-
-/* Evaluate whether or not state_usbstream_run can change */
-static int state_eval_usbstream_run(struct pvr2_hdw *hdw)
-{
-       if (hdw->state_usbstream_run) {
-               int fl = !0;
-               if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
-                       fl = (hdw->state_encoder_ok &&
-                             hdw->state_encoder_run);
-               } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
-                          (hdw->hdw_desc->flag_digital_requires_cx23416)) {
-                       fl = hdw->state_encoder_ok;
-               }
-               if (fl &&
-                   hdw->state_pipeline_req &&
-                   !hdw->state_pipeline_pause &&
-                   hdw->state_pathway_ok) {
-                       return 0;
-               }
-               pvr2_hdw_cmd_usbstream(hdw,0);
-               hdw->state_usbstream_run = 0;
-       } else {
-               if (!hdw->state_pipeline_req ||
-                   hdw->state_pipeline_pause ||
-                   !hdw->state_pathway_ok) return 0;
-               if (hdw->pathway_state == PVR2_PATHWAY_ANALOG) {
-                       if (!hdw->state_encoder_ok ||
-                           !hdw->state_encoder_run) return 0;
-               } else if ((hdw->pathway_state == PVR2_PATHWAY_DIGITAL) &&
-                          (hdw->hdw_desc->flag_digital_requires_cx23416)) {
-                       if (!hdw->state_encoder_ok) return 0;
-                       if (hdw->state_encoder_run) return 0;
-                       if (hdw->hdw_desc->digital_control_scheme ==
-                           PVR2_DIGITAL_SCHEME_ONAIR) {
-                               /* OnAir digital receivers won't stream
-                                  unless the analog encoder has run first.
-                                  Why?  I have no idea.  But don't even
-                                  try until we know the analog side is
-                                  known to have run. */
-                               if (!hdw->state_encoder_runok) return 0;
-                       }
-               }
-               if (pvr2_hdw_cmd_usbstream(hdw,!0) < 0) return 0;
-               hdw->state_usbstream_run = !0;
-       }
-       trace_stbit("state_usbstream_run",hdw->state_usbstream_run);
-       return !0;
-}
-
-
-/* Attempt to configure pipeline, if needed */
-static int state_eval_pipeline_config(struct pvr2_hdw *hdw)
-{
-       if (hdw->state_pipeline_config ||
-           hdw->state_pipeline_pause) return 0;
-       pvr2_hdw_commit_execute(hdw);
-       return !0;
-}
-
-
-/* Update pipeline idle and pipeline pause tracking states based on other
-   inputs.  This must be called whenever the other relevant inputs have
-   changed. */
-static int state_update_pipeline_state(struct pvr2_hdw *hdw)
-{
-       unsigned int st;
-       int updatedFl = 0;
-       /* Update pipeline state */
-       st = !(hdw->state_encoder_run ||
-              hdw->state_decoder_run ||
-              hdw->state_usbstream_run ||
-              (!hdw->state_decoder_quiescent));
-       if (!st != !hdw->state_pipeline_idle) {
-               hdw->state_pipeline_idle = st;
-               updatedFl = !0;
-       }
-       if (hdw->state_pipeline_idle && hdw->state_pipeline_pause) {
-               hdw->state_pipeline_pause = 0;
-               updatedFl = !0;
-       }
-       return updatedFl;
-}
-
-
-typedef int (*state_eval_func)(struct pvr2_hdw *);
-
-/* Set of functions to be run to evaluate various states in the driver. */
-static const state_eval_func eval_funcs[] = {
-       state_eval_pathway_ok,
-       state_eval_pipeline_config,
-       state_eval_encoder_ok,
-       state_eval_encoder_config,
-       state_eval_decoder_run,
-       state_eval_encoder_run,
-       state_eval_usbstream_run,
-};
-
-
-/* Process various states and return true if we did anything interesting. */
-static int pvr2_hdw_state_update(struct pvr2_hdw *hdw)
-{
-       unsigned int i;
-       int state_updated = 0;
-       int check_flag;
-
-       if (!hdw->state_stale) return 0;
-       if ((hdw->fw1_state != FW1_STATE_OK) ||
-           !hdw->flag_ok) {
-               hdw->state_stale = 0;
-               return !0;
-       }
-       /* This loop is the heart of the entire driver.  It keeps trying to
-          evaluate various bits of driver state until nothing changes for
-          one full iteration.  Each "bit of state" tracks some global
-          aspect of the driver, e.g. whether decoder should run, if
-          pipeline is configured, usb streaming is on, etc.  We separately
-          evaluate each of those questions based on other driver state to
-          arrive at the correct running configuration. */
-       do {
-               check_flag = 0;
-               state_update_pipeline_state(hdw);
-               /* Iterate over each bit of state */
-               for (i = 0; (i<ARRAY_SIZE(eval_funcs)) && hdw->flag_ok; i++) {
-                       if ((*eval_funcs[i])(hdw)) {
-                               check_flag = !0;
-                               state_updated = !0;
-                               state_update_pipeline_state(hdw);
-                       }
-               }
-       } while (check_flag && hdw->flag_ok);
-       hdw->state_stale = 0;
-       trace_stbit("state_stale",hdw->state_stale);
-       return state_updated;
-}
-
-
-static unsigned int print_input_mask(unsigned int msk,
-                                    char *buf,unsigned int acnt)
-{
-       unsigned int idx,ccnt;
-       unsigned int tcnt = 0;
-       for (idx = 0; idx < ARRAY_SIZE(control_values_input); idx++) {
-               if (!((1 << idx) & msk)) continue;
-               ccnt = scnprintf(buf+tcnt,
-                                acnt-tcnt,
-                                "%s%s",
-                                (tcnt ? ", " : ""),
-                                control_values_input[idx]);
-               tcnt += ccnt;
-       }
-       return tcnt;
-}
-
-
-static const char *pvr2_pathway_state_name(int id)
-{
-       switch (id) {
-       case PVR2_PATHWAY_ANALOG: return "analog";
-       case PVR2_PATHWAY_DIGITAL: return "digital";
-       default: return "unknown";
-       }
-}
-
-
-static unsigned int pvr2_hdw_report_unlocked(struct pvr2_hdw *hdw,int which,
-                                            char *buf,unsigned int acnt)
-{
-       switch (which) {
-       case 0:
-               return scnprintf(
-                       buf,acnt,
-                       "driver:%s%s%s%s%s <mode=%s>",
-                       (hdw->flag_ok ? " <ok>" : " <fail>"),
-                       (hdw->flag_init_ok ? " <init>" : " <uninitialized>"),
-                       (hdw->flag_disconnected ? " <disconnected>" :
-                        " <connected>"),
-                       (hdw->flag_tripped ? " <tripped>" : ""),
-                       (hdw->flag_decoder_missed ? " <no decoder>" : ""),
-                       pvr2_pathway_state_name(hdw->pathway_state));
-
-       case 1:
-               return scnprintf(
-                       buf,acnt,
-                       "pipeline:%s%s%s%s",
-                       (hdw->state_pipeline_idle ? " <idle>" : ""),
-                       (hdw->state_pipeline_config ?
-                        " <configok>" : " <stale>"),
-                       (hdw->state_pipeline_req ? " <req>" : ""),
-                       (hdw->state_pipeline_pause ? " <pause>" : ""));
-       case 2:
-               return scnprintf(
-                       buf,acnt,
-                       "worker:%s%s%s%s%s%s%s",
-                       (hdw->state_decoder_run ?
-                        (hdw->state_decoder_ready ?
-                         "<decode:run>" : " <decode:start>") :
-                        (hdw->state_decoder_quiescent ?
-                         "" : " <decode:stop>")),
-                       (hdw->state_decoder_quiescent ?
-                        " <decode:quiescent>" : ""),
-                       (hdw->state_encoder_ok ?
-                        "" : " <encode:init>"),
-                       (hdw->state_encoder_run ?
-                        (hdw->state_encoder_runok ?
-                         " <encode:run>" :
-                         " <encode:firstrun>") :
-                        (hdw->state_encoder_runok ?
-                         " <encode:stop>" :
-                         " <encode:virgin>")),
-                       (hdw->state_encoder_config ?
-                        " <encode:configok>" :
-                        (hdw->state_encoder_waitok ?
-                         "" : " <encode:waitok>")),
-                       (hdw->state_usbstream_run ?
-                        " <usb:run>" : " <usb:stop>"),
-                       (hdw->state_pathway_ok ?
-                        " <pathway:ok>" : ""));
-       case 3:
-               return scnprintf(
-                       buf,acnt,
-                       "state: %s",
-                       pvr2_get_state_name(hdw->master_state));
-       case 4: {
-               unsigned int tcnt = 0;
-               unsigned int ccnt;
-
-               ccnt = scnprintf(buf,
-                                acnt,
-                                "Hardware supported inputs: ");
-               tcnt += ccnt;
-               tcnt += print_input_mask(hdw->input_avail_mask,
-                                        buf+tcnt,
-                                        acnt-tcnt);
-               if (hdw->input_avail_mask != hdw->input_allowed_mask) {
-                       ccnt = scnprintf(buf+tcnt,
-                                        acnt-tcnt,
-                                        "; allowed inputs: ");
-                       tcnt += ccnt;
-                       tcnt += print_input_mask(hdw->input_allowed_mask,
-                                                buf+tcnt,
-                                                acnt-tcnt);
-               }
-               return tcnt;
-       }
-       case 5: {
-               struct pvr2_stream_stats stats;
-               if (!hdw->vid_stream) break;
-               pvr2_stream_get_stats(hdw->vid_stream,
-                                     &stats,
-                                     0);
-               return scnprintf(
-                       buf,acnt,
-                       "Bytes streamed=%u"
-                       " URBs: queued=%u idle=%u ready=%u"
-                       " processed=%u failed=%u",
-                       stats.bytes_processed,
-                       stats.buffers_in_queue,
-                       stats.buffers_in_idle,
-                       stats.buffers_in_ready,
-                       stats.buffers_processed,
-                       stats.buffers_failed);
-       }
-       case 6: {
-               unsigned int id = hdw->ir_scheme_active;
-               return scnprintf(buf, acnt, "ir scheme: id=%d %s", id,
-                                (id >= ARRAY_SIZE(ir_scheme_names) ?
-                                 "?" : ir_scheme_names[id]));
-       }
-       default: break;
-       }
-       return 0;
-}
-
-
-/* Generate report containing info about attached sub-devices and attached
-   i2c clients, including an indication of which attached i2c clients are
-   actually sub-devices. */
-static unsigned int pvr2_hdw_report_clients(struct pvr2_hdw *hdw,
-                                           char *buf, unsigned int acnt)
-{
-       struct v4l2_subdev *sd;
-       unsigned int tcnt = 0;
-       unsigned int ccnt;
-       struct i2c_client *client;
-       const char *p;
-       unsigned int id;
-
-       ccnt = scnprintf(buf, acnt, "Associated v4l2-subdev drivers and I2C clients:\n");
-       tcnt += ccnt;
-       v4l2_device_for_each_subdev(sd, &hdw->v4l2_dev) {
-               id = sd->grp_id;
-               p = NULL;
-               if (id < ARRAY_SIZE(module_names)) p = module_names[id];
-               if (p) {
-                       ccnt = scnprintf(buf + tcnt, acnt - tcnt, "  %s:", p);
-                       tcnt += ccnt;
-               } else {
-                       ccnt = scnprintf(buf + tcnt, acnt - tcnt,
-                                        "  (unknown id=%u):", id);
-                       tcnt += ccnt;
-               }
-               client = v4l2_get_subdevdata(sd);
-               if (client) {
-                       ccnt = scnprintf(buf + tcnt, acnt - tcnt,
-                                        " %s @ %02x\n", client->name,
-                                        client->addr);
-                       tcnt += ccnt;
-               } else {
-                       ccnt = scnprintf(buf + tcnt, acnt - tcnt,
-                                        " no i2c client\n");
-                       tcnt += ccnt;
-               }
-       }
-       return tcnt;
-}
-
-
-unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw,
-                                  char *buf,unsigned int acnt)
-{
-       unsigned int bcnt,ccnt,idx;
-       bcnt = 0;
-       LOCK_TAKE(hdw->big_lock);
-       for (idx = 0; ; idx++) {
-               ccnt = pvr2_hdw_report_unlocked(hdw,idx,buf,acnt);
-               if (!ccnt) break;
-               bcnt += ccnt; acnt -= ccnt; buf += ccnt;
-               if (!acnt) break;
-               buf[0] = '\n'; ccnt = 1;
-               bcnt += ccnt; acnt -= ccnt; buf += ccnt;
-       }
-       ccnt = pvr2_hdw_report_clients(hdw, buf, acnt);
-       bcnt += ccnt; acnt -= ccnt; buf += ccnt;
-       LOCK_GIVE(hdw->big_lock);
-       return bcnt;
-}
-
-
-static void pvr2_hdw_state_log_state(struct pvr2_hdw *hdw)
-{
-       char buf[256];
-       unsigned int idx, ccnt;
-       unsigned int lcnt, ucnt;
-
-       for (idx = 0; ; idx++) {
-               ccnt = pvr2_hdw_report_unlocked(hdw,idx,buf,sizeof(buf));
-               if (!ccnt) break;
-               printk(KERN_INFO "%s %.*s\n",hdw->name,ccnt,buf);
-       }
-       ccnt = pvr2_hdw_report_clients(hdw, buf, sizeof(buf));
-       ucnt = 0;
-       while (ucnt < ccnt) {
-               lcnt = 0;
-               while ((lcnt + ucnt < ccnt) && (buf[lcnt + ucnt] != '\n')) {
-                       lcnt++;
-               }
-               printk(KERN_INFO "%s %.*s\n", hdw->name, lcnt, buf + ucnt);
-               ucnt += lcnt + 1;
-       }
-}
-
-
-/* Evaluate and update the driver's current state, taking various actions
-   as appropriate for the update. */
-static int pvr2_hdw_state_eval(struct pvr2_hdw *hdw)
-{
-       unsigned int st;
-       int state_updated = 0;
-       int callback_flag = 0;
-       int analog_mode;
-
-       pvr2_trace(PVR2_TRACE_STBITS,
-                  "Drive state check START");
-       if (pvrusb2_debug & PVR2_TRACE_STBITS) {
-               pvr2_hdw_state_log_state(hdw);
-       }
-
-       /* Process all state and get back over disposition */
-       state_updated = pvr2_hdw_state_update(hdw);
-
-       analog_mode = (hdw->pathway_state != PVR2_PATHWAY_DIGITAL);
-
-       /* Update master state based upon all other states. */
-       if (!hdw->flag_ok) {
-               st = PVR2_STATE_DEAD;
-       } else if (hdw->fw1_state != FW1_STATE_OK) {
-               st = PVR2_STATE_COLD;
-       } else if ((analog_mode ||
-                   hdw->hdw_desc->flag_digital_requires_cx23416) &&
-                  !hdw->state_encoder_ok) {
-               st = PVR2_STATE_WARM;
-       } else if (hdw->flag_tripped ||
-                  (analog_mode && hdw->flag_decoder_missed)) {
-               st = PVR2_STATE_ERROR;
-       } else if (hdw->state_usbstream_run &&
-                  (!analog_mode ||
-                   (hdw->state_encoder_run && hdw->state_decoder_run))) {
-               st = PVR2_STATE_RUN;
-       } else {
-               st = PVR2_STATE_READY;
-       }
-       if (hdw->master_state != st) {
-               pvr2_trace(PVR2_TRACE_STATE,
-                          "Device state change from %s to %s",
-                          pvr2_get_state_name(hdw->master_state),
-                          pvr2_get_state_name(st));
-               pvr2_led_ctrl(hdw,st == PVR2_STATE_RUN);
-               hdw->master_state = st;
-               state_updated = !0;
-               callback_flag = !0;
-       }
-       if (state_updated) {
-               /* Trigger anyone waiting on any state changes here. */
-               wake_up(&hdw->state_wait_data);
-       }
-
-       if (pvrusb2_debug & PVR2_TRACE_STBITS) {
-               pvr2_hdw_state_log_state(hdw);
-       }
-       pvr2_trace(PVR2_TRACE_STBITS,
-                  "Drive state check DONE callback=%d",callback_flag);
-
-       return callback_flag;
-}
-
-
-/* Cause kernel thread to check / update driver state */
-static void pvr2_hdw_state_sched(struct pvr2_hdw *hdw)
-{
-       if (hdw->state_stale) return;
-       hdw->state_stale = !0;
-       trace_stbit("state_stale",hdw->state_stale);
-       queue_work(hdw->workqueue,&hdw->workpoll);
-}
-
-
-int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *dp)
-{
-       return pvr2_read_register(hdw,PVR2_GPIO_DIR,dp);
-}
-
-
-int pvr2_hdw_gpio_get_out(struct pvr2_hdw *hdw,u32 *dp)
-{
-       return pvr2_read_register(hdw,PVR2_GPIO_OUT,dp);
-}
-
-
-int pvr2_hdw_gpio_get_in(struct pvr2_hdw *hdw,u32 *dp)
-{
-       return pvr2_read_register(hdw,PVR2_GPIO_IN,dp);
-}
-
-
-int pvr2_hdw_gpio_chg_dir(struct pvr2_hdw *hdw,u32 msk,u32 val)
-{
-       u32 cval,nval;
-       int ret;
-       if (~msk) {
-               ret = pvr2_read_register(hdw,PVR2_GPIO_DIR,&cval);
-               if (ret) return ret;
-               nval = (cval & ~msk) | (val & msk);
-               pvr2_trace(PVR2_TRACE_GPIO,
-                          "GPIO direction changing 0x%x:0x%x"
-                          " from 0x%x to 0x%x",
-                          msk,val,cval,nval);
-       } else {
-               nval = val;
-               pvr2_trace(PVR2_TRACE_GPIO,
-                          "GPIO direction changing to 0x%x",nval);
-       }
-       return pvr2_write_register(hdw,PVR2_GPIO_DIR,nval);
-}
-
-
-int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val)
-{
-       u32 cval,nval;
-       int ret;
-       if (~msk) {
-               ret = pvr2_read_register(hdw,PVR2_GPIO_OUT,&cval);
-               if (ret) return ret;
-               nval = (cval & ~msk) | (val & msk);
-               pvr2_trace(PVR2_TRACE_GPIO,
-                          "GPIO output changing 0x%x:0x%x from 0x%x to 0x%x",
-                          msk,val,cval,nval);
-       } else {
-               nval = val;
-               pvr2_trace(PVR2_TRACE_GPIO,
-                          "GPIO output changing to 0x%x",nval);
-       }
-       return pvr2_write_register(hdw,PVR2_GPIO_OUT,nval);
-}
-
-
-void pvr2_hdw_status_poll(struct pvr2_hdw *hdw)
-{
-       struct v4l2_tuner *vtp = &hdw->tuner_signal_info;
-       memset(vtp, 0, sizeof(*vtp));
-       vtp->type = (hdw->input_val == PVR2_CVAL_INPUT_RADIO) ?
-               V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-       hdw->tuner_signal_stale = 0;
-       /* Note: There apparently is no replacement for VIDIOC_CROPCAP
-          using v4l2-subdev - therefore we can't support that AT ALL right
-          now.  (Of course, no sub-drivers seem to implement it either.
-          But now it's a a chicken and egg problem...) */
-       v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, g_tuner, vtp);
-       pvr2_trace(PVR2_TRACE_CHIPS, "subdev status poll"
-                  " type=%u strength=%u audio=0x%x cap=0x%x"
-                  " low=%u hi=%u",
-                  vtp->type,
-                  vtp->signal, vtp->rxsubchans, vtp->capability,
-                  vtp->rangelow, vtp->rangehigh);
-
-       /* We have to do this to avoid getting into constant polling if
-          there's nobody to answer a poll of cropcap info. */
-       hdw->cropcap_stale = 0;
-}
-
-
-unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *hdw)
-{
-       return hdw->input_avail_mask;
-}
-
-
-unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *hdw)
-{
-       return hdw->input_allowed_mask;
-}
-
-
-static int pvr2_hdw_set_input(struct pvr2_hdw *hdw,int v)
-{
-       if (hdw->input_val != v) {
-               hdw->input_val = v;
-               hdw->input_dirty = !0;
-       }
-
-       /* Handle side effects - if we switch to a mode that needs the RF
-          tuner, then select the right frequency choice as well and mark
-          it dirty. */
-       if (hdw->input_val == PVR2_CVAL_INPUT_RADIO) {
-               hdw->freqSelector = 0;
-               hdw->freqDirty = !0;
-       } else if ((hdw->input_val == PVR2_CVAL_INPUT_TV) ||
-                  (hdw->input_val == PVR2_CVAL_INPUT_DTV)) {
-               hdw->freqSelector = 1;
-               hdw->freqDirty = !0;
-       }
-       return 0;
-}
-
-
-int pvr2_hdw_set_input_allowed(struct pvr2_hdw *hdw,
-                              unsigned int change_mask,
-                              unsigned int change_val)
-{
-       int ret = 0;
-       unsigned int nv,m,idx;
-       LOCK_TAKE(hdw->big_lock);
-       do {
-               nv = hdw->input_allowed_mask & ~change_mask;
-               nv |= (change_val & change_mask);
-               nv &= hdw->input_avail_mask;
-               if (!nv) {
-                       /* No legal modes left; return error instead. */
-                       ret = -EPERM;
-                       break;
-               }
-               hdw->input_allowed_mask = nv;
-               if ((1 << hdw->input_val) & hdw->input_allowed_mask) {
-                       /* Current mode is still in the allowed mask, so
-                          we're done. */
-                       break;
-               }
-               /* Select and switch to a mode that is still in the allowed
-                  mask */
-               if (!hdw->input_allowed_mask) {
-                       /* Nothing legal; give up */
-                       break;
-               }
-               m = hdw->input_allowed_mask;
-               for (idx = 0; idx < (sizeof(m) << 3); idx++) {
-                       if (!((1 << idx) & m)) continue;
-                       pvr2_hdw_set_input(hdw,idx);
-                       break;
-               }
-       } while (0);
-       LOCK_GIVE(hdw->big_lock);
-       return ret;
-}
-
-
-/* Find I2C address of eeprom */
-static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
-{
-       int result;
-       LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] = FX2CMD_GET_EEPROM_ADDR;
-               result = pvr2_send_request(hdw,
-                                          hdw->cmd_buffer,1,
-                                          hdw->cmd_buffer,1);
-               if (result < 0) break;
-               result = hdw->cmd_buffer[0];
-       } while(0); LOCK_GIVE(hdw->ctl_lock);
-       return result;
-}
-
-
-int pvr2_hdw_register_access(struct pvr2_hdw *hdw,
-                            struct v4l2_dbg_match *match, u64 reg_id,
-                            int setFl, u64 *val_ptr)
-{
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       struct v4l2_dbg_register req;
-       int stat = 0;
-       int okFl = 0;
-
-       if (!capable(CAP_SYS_ADMIN)) return -EPERM;
-
-       req.match = *match;
-       req.reg = reg_id;
-       if (setFl) req.val = *val_ptr;
-       /* It would be nice to know if a sub-device answered the request */
-       v4l2_device_call_all(&hdw->v4l2_dev, 0, core, g_register, &req);
-       if (!setFl) *val_ptr = req.val;
-       if (okFl) {
-               return stat;
-       }
-       return -EINVAL;
-#else
-       return -ENOSYS;
-#endif
-}
-
-
-/*
-  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/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
deleted file mode 100644 (file)
index 8060fc6..0000000
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifndef __PVRUSB2_HDW_H
-#define __PVRUSB2_HDW_H
-
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include "pvrusb2-io.h"
-#include "pvrusb2-ctrl.h"
-
-
-/* Private internal control ids, look these up with
-   pvr2_hdw_get_ctrl_by_id() - these are NOT visible in V4L */
-#define PVR2_CID_STDCUR 2
-#define PVR2_CID_STDAVAIL 3
-#define PVR2_CID_INPUT 4
-#define PVR2_CID_AUDIOMODE 5
-#define PVR2_CID_FREQUENCY 6
-#define PVR2_CID_HRES 7
-#define PVR2_CID_VRES 8
-#define PVR2_CID_CROPL 9
-#define PVR2_CID_CROPT 10
-#define PVR2_CID_CROPW 11
-#define PVR2_CID_CROPH 12
-#define PVR2_CID_CROPCAPPAN 13
-#define PVR2_CID_CROPCAPPAD 14
-#define PVR2_CID_CROPCAPBL 15
-#define PVR2_CID_CROPCAPBT 16
-#define PVR2_CID_CROPCAPBW 17
-#define PVR2_CID_CROPCAPBH 18
-#define PVR2_CID_STDDETECT 19
-
-/* Legal values for the INPUT state variable */
-#define PVR2_CVAL_INPUT_TV 0
-#define PVR2_CVAL_INPUT_DTV 1
-#define PVR2_CVAL_INPUT_COMPOSITE 2
-#define PVR2_CVAL_INPUT_SVIDEO 3
-#define PVR2_CVAL_INPUT_RADIO 4
-
-enum pvr2_config {
-       pvr2_config_empty,    /* No configuration */
-       pvr2_config_mpeg,     /* Encoded / compressed video */
-       pvr2_config_vbi,      /* Standard vbi info */
-       pvr2_config_pcm,      /* Audio raw pcm stream */
-       pvr2_config_rawvideo, /* Video raw frames */
-};
-
-enum pvr2_v4l_type {
-       pvr2_v4l_type_video,
-       pvr2_v4l_type_vbi,
-       pvr2_v4l_type_radio,
-};
-
-/* Major states that we can be in:
- *
- *  DEAD - Device is in an unusable state and cannot be recovered.  This
- *  can happen if we completely lose the ability to communicate with it
- *  (but it might still on the bus).  In this state there's nothing we can
- *  do; it must be replugged in order to recover.
- *
- *  COLD - Device is in an unusable state, needs microcontroller firmware.
- *
- *  WARM - We can communicate with the device and the proper
- *  microcontroller firmware is running, but other device initialization is
- *  still needed (e.g. encoder firmware).
- *
- *  ERROR - A problem prevents capture operation (e.g. encoder firmware
- *  missing).
- *
- *  READY - Device is operational, but not streaming.
- *
- *  RUN - Device is streaming.
- *
- */
-#define PVR2_STATE_NONE 0
-#define PVR2_STATE_DEAD 1
-#define PVR2_STATE_COLD 2
-#define PVR2_STATE_WARM 3
-#define PVR2_STATE_ERROR 4
-#define PVR2_STATE_READY 5
-#define PVR2_STATE_RUN 6
-
-/* Translate configuration enum to a string label */
-const char *pvr2_config_get_name(enum pvr2_config);
-
-struct pvr2_hdw;
-
-/* Create and return a structure for interacting with the underlying
-   hardware */
-struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
-                                const struct usb_device_id *devid);
-
-/* Perform second stage initialization, passing in a notification callback
-   for when the master state changes. */
-int pvr2_hdw_initialize(struct pvr2_hdw *,
-                       void (*callback_func)(void *),
-                       void *callback_data);
-
-/* Destroy hardware interaction structure */
-void pvr2_hdw_destroy(struct pvr2_hdw *);
-
-/* Return true if in the ready (normal) state */
-int pvr2_hdw_dev_ok(struct pvr2_hdw *);
-
-/* Return small integer number [1..N] for logical instance number of this
-   device.  This is useful for indexing array-valued module parameters. */
-int pvr2_hdw_get_unit_number(struct pvr2_hdw *);
-
-/* Get pointer to underlying USB device */
-struct usb_device *pvr2_hdw_get_dev(struct pvr2_hdw *);
-
-/* Retrieve serial number of device */
-unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *);
-
-/* Retrieve bus location info of device */
-const char *pvr2_hdw_get_bus_info(struct pvr2_hdw *);
-
-/* Retrieve per-instance string identifier for this specific device */
-const char *pvr2_hdw_get_device_identifier(struct pvr2_hdw *);
-
-/* Called when hardware has been unplugged */
-void pvr2_hdw_disconnect(struct pvr2_hdw *);
-
-/* Get the number of defined controls */
-unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *);
-
-/* Retrieve a control handle given its index (0..count-1) */
-struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *,unsigned int);
-
-/* Retrieve a control handle given its internal ID (if any) */
-struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *,unsigned int);
-
-/* Retrieve a control handle given its V4L ID (if any) */
-struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *,unsigned int ctl_id);
-
-/* Retrieve a control handle given its immediate predecessor V4L ID (if any) */
-struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *,
-                                           unsigned int ctl_id);
-
-/* Commit all control changes made up to this point */
-int pvr2_hdw_commit_ctl(struct pvr2_hdw *);
-
-/* Return a bit mask of valid input selections for this device.  Mask bits
- * will be according to PVR_CVAL_INPUT_xxxx definitions. */
-unsigned int pvr2_hdw_get_input_available(struct pvr2_hdw *);
-
-/* Return a bit mask of allowed input selections for this device.  Mask bits
- * will be according to PVR_CVAL_INPUT_xxxx definitions. */
-unsigned int pvr2_hdw_get_input_allowed(struct pvr2_hdw *);
-
-/* Change the set of allowed input selections for this device.  Both
-   change_mask and change_valu are mask bits according to
-   PVR_CVAL_INPUT_xxxx definitions.  The change_mask parameter indicate
-   which settings are being changed and the change_val parameter indicates
-   whether corresponding settings are being set or cleared. */
-int pvr2_hdw_set_input_allowed(struct pvr2_hdw *,
-                              unsigned int change_mask,
-                              unsigned int change_val);
-
-/* Return name for this driver instance */
-const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *);
-
-/* Mark tuner status stale so that it will be re-fetched */
-void pvr2_hdw_execute_tuner_poll(struct pvr2_hdw *);
-
-/* Return information about the tuner */
-int pvr2_hdw_get_tuner_status(struct pvr2_hdw *,struct v4l2_tuner *);
-
-/* Return information about cropping capabilities */
-int pvr2_hdw_get_cropcap(struct pvr2_hdw *, struct v4l2_cropcap *);
-
-/* Query device and see if it thinks it is on a high-speed USB link */
-int pvr2_hdw_is_hsm(struct pvr2_hdw *);
-
-/* Return a string token representative of the hardware type */
-const char *pvr2_hdw_get_type(struct pvr2_hdw *);
-
-/* Return a single line description of the hardware type */
-const char *pvr2_hdw_get_desc(struct pvr2_hdw *);
-
-/* Turn streaming on/off */
-int pvr2_hdw_set_streaming(struct pvr2_hdw *,int);
-
-/* Find out if streaming is on */
-int pvr2_hdw_get_streaming(struct pvr2_hdw *);
-
-/* Retrieve driver overall state */
-int pvr2_hdw_get_state(struct pvr2_hdw *);
-
-/* Configure the type of stream to generate */
-int pvr2_hdw_set_stream_type(struct pvr2_hdw *, enum pvr2_config);
-
-/* Get handle to video output stream */
-struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *);
-
-/* Enable / disable retrieval of CPU firmware or prom contents.  This must
-   be enabled before pvr2_hdw_cpufw_get() will function.  Note that doing
-   this may prevent the device from running (and leaving this mode may
-   imply a device reset). */
-void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *,
-                               int mode, /* 0=8KB FX2, 1=16KB FX2, 2=PROM */
-                               int enable_flag);
-
-/* Return true if we're in a mode for retrieval CPU firmware */
-int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *);
-
-/* Retrieve a piece of the CPU's firmware at the given offset.  Return
-   value is the number of bytes retrieved or zero if we're past the end or
-   an error otherwise (e.g. if firmware retrieval is not enabled). */
-int pvr2_hdw_cpufw_get(struct pvr2_hdw *,unsigned int offs,
-                      char *buf,unsigned int cnt);
-
-/* Retrieve a previously stored v4l minor device number */
-int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *,enum pvr2_v4l_type index);
-
-/* Store a v4l minor device number */
-void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,
-                                    enum pvr2_v4l_type index,int);
-
-/* Direct read/write access to chip's registers:
-   match - specify criteria to identify target chip (this is a v4l dbg struct)
-   reg_id  - register number to access
-   setFl   - true to set the register, false to read it
-   val_ptr - storage location for source / result. */
-int pvr2_hdw_register_access(struct pvr2_hdw *,
-                            struct v4l2_dbg_match *match, u64 reg_id,
-                            int setFl, u64 *val_ptr);
-
-/* The following entry points are all lower level things you normally don't
-   want to worry about. */
-
-/* Issue a command and get a response from the device.  LOTS of higher
-   level stuff is built on this. */
-int pvr2_send_request(struct pvr2_hdw *,
-                     void *write_ptr,unsigned int write_len,
-                     void *read_ptr,unsigned int read_len);
-
-/* Slightly higher level device communication functions. */
-int pvr2_write_register(struct pvr2_hdw *, u16, u32);
-
-/* Call if for any reason we can't talk to the hardware anymore - this will
-   cause the driver to stop flailing on the device. */
-void pvr2_hdw_render_useless(struct pvr2_hdw *);
-
-/* Set / clear 8051's reset bit */
-void pvr2_hdw_cpureset_assert(struct pvr2_hdw *,int);
-
-/* Execute a USB-commanded device reset */
-void pvr2_hdw_device_reset(struct pvr2_hdw *);
-
-/* Reset worker's error trapping circuit breaker */
-int pvr2_hdw_untrip(struct pvr2_hdw *);
-
-/* Execute hard reset command (after this point it's likely that the
-   encoder will have to be reconfigured).  This also clears the "useless"
-   state. */
-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 *);
-
-/* Direct manipulation of GPIO bits */
-int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *);
-int pvr2_hdw_gpio_get_out(struct pvr2_hdw *hdw,u32 *);
-int pvr2_hdw_gpio_get_in(struct pvr2_hdw *hdw,u32 *);
-int pvr2_hdw_gpio_chg_dir(struct pvr2_hdw *hdw,u32 msk,u32 val);
-int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val);
-
-/* This data structure is specifically for the next function... */
-struct pvr2_hdw_debug_info {
-       int big_lock_held;
-       int ctl_lock_held;
-       int flag_disconnected;
-       int flag_init_ok;
-       int flag_ok;
-       int fw1_state;
-       int flag_decoder_missed;
-       int flag_tripped;
-       int state_encoder_ok;
-       int state_encoder_run;
-       int state_decoder_run;
-       int state_decoder_ready;
-       int state_usbstream_run;
-       int state_decoder_quiescent;
-       int state_pipeline_config;
-       int state_pipeline_req;
-       int state_pipeline_pause;
-       int state_pipeline_idle;
-       int cmd_debug_state;
-       int cmd_debug_write_len;
-       int cmd_debug_read_len;
-       int cmd_debug_write_pend;
-       int cmd_debug_read_pend;
-       int cmd_debug_timeout;
-       int cmd_debug_rstatus;
-       int cmd_debug_wstatus;
-       unsigned char cmd_code;
-};
-
-/* Non-intrusively retrieve internal state info - this is useful for
-   diagnosing lockups.  Note that this operation is completed without any
-   kind of locking and so it is not atomic and may yield inconsistent
-   results.  This is *purely* a debugging aid. */
-void pvr2_hdw_get_debug_info_unlocked(const struct pvr2_hdw *hdw,
-                                     struct pvr2_hdw_debug_info *);
-
-/* Intrusively retrieve internal state info - this is useful for
-   diagnosing overall driver state.  This operation synchronizes against
-   the overall driver mutex - so if there are locking problems this will
-   likely hang!  This is *purely* a debugging aid. */
-void pvr2_hdw_get_debug_info_locked(struct pvr2_hdw *hdw,
-                                   struct pvr2_hdw_debug_info *);
-
-/* Report out several lines of text that describes driver internal state.
-   Results are written into the passed-in buffer. */
-unsigned int pvr2_hdw_state_report(struct pvr2_hdw *hdw,
-                                  char *buf_ptr,unsigned int buf_size);
-
-/* Cause modules to log their state once */
-void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw);
-
-/* Cause encoder firmware to be uploaded into the device.  This is normally
-   done autonomously, but the interface is exported here because it is also
-   a debugging aid. */
-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/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
deleted file mode 100644 (file)
index 885ce11..0000000
+++ /dev/null
@@ -1,698 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <media/ir-kbd-i2c.h>
-#include "pvrusb2-i2c-core.h"
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-#include "pvrusb2-fx2-cmd.h"
-#include "pvrusb2.h"
-
-#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
-
-/*
-
-  This module attempts to implement a compliant I2C adapter for the pvrusb2
-  device.
-
-*/
-
-static unsigned int i2c_scan;
-module_param(i2c_scan, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
-
-static int ir_mode[PVR_NUM] = { [0 ... PVR_NUM-1] = 1 };
-module_param_array(ir_mode, int, NULL, 0444);
-MODULE_PARM_DESC(ir_mode,"specify: 0=disable IR reception, 1=normal IR");
-
-static int pvr2_disable_ir_video;
-module_param_named(disable_autoload_ir_video, pvr2_disable_ir_video,
-                  int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(disable_autoload_ir_video,
-                "1=do not try to autoload ir_video IR receiver");
-
-static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */
-                         u8 i2c_addr,      /* I2C address we're talking to */
-                         u8 *data,         /* Data to write */
-                         u16 length)       /* Size of data to write */
-{
-       /* Return value - default 0 means success */
-       int ret;
-
-
-       if (!data) length = 0;
-       if (length > (sizeof(hdw->cmd_buffer) - 3)) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Killing an I2C write to %u that is too large"
-                          " (desired=%u limit=%u)",
-                          i2c_addr,
-                          length,(unsigned int)(sizeof(hdw->cmd_buffer) - 3));
-               return -ENOTSUPP;
-       }
-
-       LOCK_TAKE(hdw->ctl_lock);
-
-       /* Clear the command buffer (likely to be paranoia) */
-       memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer));
-
-       /* Set up command buffer for an I2C write */
-       hdw->cmd_buffer[0] = FX2CMD_I2C_WRITE;      /* write prefix */
-       hdw->cmd_buffer[1] = i2c_addr;  /* i2c addr of chip */
-       hdw->cmd_buffer[2] = length;    /* length of what follows */
-       if (length) memcpy(hdw->cmd_buffer + 3, data, length);
-
-       /* Do the operation */
-       ret = pvr2_send_request(hdw,
-                               hdw->cmd_buffer,
-                               length + 3,
-                               hdw->cmd_buffer,
-                               1);
-       if (!ret) {
-               if (hdw->cmd_buffer[0] != 8) {
-                       ret = -EIO;
-                       if (hdw->cmd_buffer[0] != 7) {
-                               trace_i2c("unexpected status"
-                                         " from i2_write[%d]: %d",
-                                         i2c_addr,hdw->cmd_buffer[0]);
-                       }
-               }
-       }
-
-       LOCK_GIVE(hdw->ctl_lock);
-
-       return ret;
-}
-
-static int pvr2_i2c_read(struct pvr2_hdw *hdw, /* Context */
-                        u8 i2c_addr,       /* I2C address we're talking to */
-                        u8 *data,          /* Data to write */
-                        u16 dlen,          /* Size of data to write */
-                        u8 *res,           /* Where to put data we read */
-                        u16 rlen)          /* Amount of data to read */
-{
-       /* Return value - default 0 means success */
-       int ret;
-
-
-       if (!data) dlen = 0;
-       if (dlen > (sizeof(hdw->cmd_buffer) - 4)) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Killing an I2C read to %u that has wlen too large"
-                          " (desired=%u limit=%u)",
-                          i2c_addr,
-                          dlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 4));
-               return -ENOTSUPP;
-       }
-       if (res && (rlen > (sizeof(hdw->cmd_buffer) - 1))) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Killing an I2C read to %u that has rlen too large"
-                          " (desired=%u limit=%u)",
-                          i2c_addr,
-                          rlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 1));
-               return -ENOTSUPP;
-       }
-
-       LOCK_TAKE(hdw->ctl_lock);
-
-       /* Clear the command buffer (likely to be paranoia) */
-       memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer));
-
-       /* Set up command buffer for an I2C write followed by a read */
-       hdw->cmd_buffer[0] = FX2CMD_I2C_READ;  /* read prefix */
-       hdw->cmd_buffer[1] = dlen;  /* arg length */
-       hdw->cmd_buffer[2] = rlen;  /* answer length. Device will send one
-                                      more byte (status). */
-       hdw->cmd_buffer[3] = i2c_addr;  /* i2c addr of chip */
-       if (dlen) memcpy(hdw->cmd_buffer + 4, data, dlen);
-
-       /* Do the operation */
-       ret = pvr2_send_request(hdw,
-                               hdw->cmd_buffer,
-                               4 + dlen,
-                               hdw->cmd_buffer,
-                               rlen + 1);
-       if (!ret) {
-               if (hdw->cmd_buffer[0] != 8) {
-                       ret = -EIO;
-                       if (hdw->cmd_buffer[0] != 7) {
-                               trace_i2c("unexpected status"
-                                         " from i2_read[%d]: %d",
-                                         i2c_addr,hdw->cmd_buffer[0]);
-                       }
-               }
-       }
-
-       /* Copy back the result */
-       if (res && rlen) {
-               if (ret) {
-                       /* Error, just blank out the return buffer */
-                       memset(res, 0, rlen);
-               } else {
-                       memcpy(res, hdw->cmd_buffer + 1, rlen);
-               }
-       }
-
-       LOCK_GIVE(hdw->ctl_lock);
-
-       return ret;
-}
-
-/* This is the common low level entry point for doing I2C operations to the
-   hardware. */
-static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw,
-                            u8 i2c_addr,
-                            u8 *wdata,
-                            u16 wlen,
-                            u8 *rdata,
-                            u16 rlen)
-{
-       if (!rdata) rlen = 0;
-       if (!wdata) wlen = 0;
-       if (rlen || !wlen) {
-               return pvr2_i2c_read(hdw,i2c_addr,wdata,wlen,rdata,rlen);
-       } else {
-               return pvr2_i2c_write(hdw,i2c_addr,wdata,wlen);
-       }
-}
-
-
-/* This is a special entry point for cases of I2C transaction attempts to
-   the IR receiver.  The implementation here simulates the IR receiver by
-   issuing a command to the FX2 firmware and using that response to return
-   what the real I2C receiver would have returned.  We use this for 24xxx
-   devices, where the IR receiver chip has been removed and replaced with
-   FX2 related logic. */
-static int i2c_24xxx_ir(struct pvr2_hdw *hdw,
-                       u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
-{
-       u8 dat[4];
-       unsigned int stat;
-
-       if (!(rlen || wlen)) {
-               /* This is a probe attempt.  Just let it succeed. */
-               return 0;
-       }
-
-       /* We don't understand this kind of transaction */
-       if ((wlen != 0) || (rlen == 0)) return -EIO;
-
-       if (rlen < 3) {
-               /* Mike Isely <isely@pobox.com> Appears to be a probe
-                  attempt from lirc.  Just fill in zeroes and return.  If
-                  we try instead to do the full transaction here, then bad
-                  things seem to happen within the lirc driver module
-                  (version 0.8.0-7 sources from Debian, when run under
-                  vanilla 2.6.17.6 kernel) - and I don't have the patience
-                  to chase it down. */
-               if (rlen > 0) rdata[0] = 0;
-               if (rlen > 1) rdata[1] = 0;
-               return 0;
-       }
-
-       /* Issue a command to the FX2 to read the IR receiver. */
-       LOCK_TAKE(hdw->ctl_lock); do {
-               hdw->cmd_buffer[0] = FX2CMD_GET_IR_CODE;
-               stat = pvr2_send_request(hdw,
-                                        hdw->cmd_buffer,1,
-                                        hdw->cmd_buffer,4);
-               dat[0] = hdw->cmd_buffer[0];
-               dat[1] = hdw->cmd_buffer[1];
-               dat[2] = hdw->cmd_buffer[2];
-               dat[3] = hdw->cmd_buffer[3];
-       } while (0); LOCK_GIVE(hdw->ctl_lock);
-
-       /* Give up if that operation failed. */
-       if (stat != 0) return stat;
-
-       /* Mangle the results into something that looks like the real IR
-          receiver. */
-       rdata[2] = 0xc1;
-       if (dat[0] != 1) {
-               /* No code received. */
-               rdata[0] = 0;
-               rdata[1] = 0;
-       } else {
-               u16 val;
-               /* Mash the FX2 firmware-provided IR code into something
-                  that the normal i2c chip-level driver expects. */
-               val = dat[1];
-               val <<= 8;
-               val |= dat[2];
-               val >>= 1;
-               val &= ~0x0003;
-               val |= 0x8000;
-               rdata[0] = (val >> 8) & 0xffu;
-               rdata[1] = val & 0xffu;
-       }
-
-       return 0;
-}
-
-/* This is a special entry point that is entered if an I2C operation is
-   attempted to a wm8775 chip on model 24xxx hardware.  Autodetect of this
-   part doesn't work, but we know it is really there.  So let's look for
-   the autodetect attempt and just return success if we see that. */
-static int i2c_hack_wm8775(struct pvr2_hdw *hdw,
-                          u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
-{
-       if (!(rlen || wlen)) {
-               // This is a probe attempt.  Just let it succeed.
-               return 0;
-       }
-       return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen);
-}
-
-/* This is an entry point designed to always fail any attempt to perform a
-   transfer.  We use this to cause certain I2C addresses to not be
-   probed. */
-static int i2c_black_hole(struct pvr2_hdw *hdw,
-                          u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
-{
-       return -EIO;
-}
-
-/* This is a special entry point that is entered if an I2C operation is
-   attempted to a cx25840 chip on model 24xxx hardware.  This chip can
-   sometimes wedge itself.  Worse still, when this happens msp3400 can
-   falsely detect this part and then the system gets hosed up after msp3400
-   gets confused and dies.  What we want to do here is try to keep msp3400
-   away and also try to notice if the chip is wedged and send a warning to
-   the system log. */
-static int i2c_hack_cx25840(struct pvr2_hdw *hdw,
-                           u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
-{
-       int ret;
-       unsigned int subaddr;
-       u8 wbuf[2];
-       int state = hdw->i2c_cx25840_hack_state;
-
-       if (!(rlen || wlen)) {
-               // Probe attempt - always just succeed and don't bother the
-               // hardware (this helps to make the state machine further
-               // down somewhat easier).
-               return 0;
-       }
-
-       if (state == 3) {
-               return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen);
-       }
-
-       /* We're looking for the exact pattern where the revision register
-          is being read.  The cx25840 module will always look at the
-          revision register first.  Any other pattern of access therefore
-          has to be a probe attempt from somebody else so we'll reject it.
-          Normally we could just let each client just probe the part
-          anyway, but when the cx25840 is wedged, msp3400 will get a false
-          positive and that just screws things up... */
-
-       if (wlen == 0) {
-               switch (state) {
-               case 1: subaddr = 0x0100; break;
-               case 2: subaddr = 0x0101; break;
-               default: goto fail;
-               }
-       } else if (wlen == 2) {
-               subaddr = (wdata[0] << 8) | wdata[1];
-               switch (subaddr) {
-               case 0x0100: state = 1; break;
-               case 0x0101: state = 2; break;
-               default: goto fail;
-               }
-       } else {
-               goto fail;
-       }
-       if (!rlen) goto success;
-       state = 0;
-       if (rlen != 1) goto fail;
-
-       /* If we get to here then we have a legitimate read for one of the
-          two revision bytes, so pass it through. */
-       wbuf[0] = subaddr >> 8;
-       wbuf[1] = subaddr;
-       ret = pvr2_i2c_basic_op(hdw,i2c_addr,wbuf,2,rdata,rlen);
-
-       if ((ret != 0) || (*rdata == 0x04) || (*rdata == 0x0a)) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "WARNING: Detected a wedged cx25840 chip;"
-                          " the device will not work.");
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "WARNING: Try power cycling the pvrusb2 device.");
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "WARNING: Disabling further access to the device"
-                          " to prevent other foul-ups.");
-               // This blocks all further communication with the part.
-               hdw->i2c_func[0x44] = NULL;
-               pvr2_hdw_render_useless(hdw);
-               goto fail;
-       }
-
-       /* Success! */
-       pvr2_trace(PVR2_TRACE_CHIPS,"cx25840 appears to be OK.");
-       state = 3;
-
- success:
-       hdw->i2c_cx25840_hack_state = state;
-       return 0;
-
- fail:
-       hdw->i2c_cx25840_hack_state = state;
-       return -EIO;
-}
-
-/* This is a very, very limited I2C adapter implementation.  We can only
-   support what we actually know will work on the device... */
-static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
-                        struct i2c_msg msgs[],
-                        int num)
-{
-       int ret = -ENOTSUPP;
-       pvr2_i2c_func funcp = NULL;
-       struct pvr2_hdw *hdw = (struct pvr2_hdw *)(i2c_adap->algo_data);
-
-       if (!num) {
-               ret = -EINVAL;
-               goto done;
-       }
-       if (msgs[0].addr < PVR2_I2C_FUNC_CNT) {
-               funcp = hdw->i2c_func[msgs[0].addr];
-       }
-       if (!funcp) {
-               ret = -EIO;
-               goto done;
-       }
-
-       if (num == 1) {
-               if (msgs[0].flags & I2C_M_RD) {
-                       /* Simple read */
-                       u16 tcnt,bcnt,offs;
-                       if (!msgs[0].len) {
-                               /* Length == 0 read.  This is a probe. */
-                               if (funcp(hdw,msgs[0].addr,NULL,0,NULL,0)) {
-                                       ret = -EIO;
-                                       goto done;
-                               }
-                               ret = 1;
-                               goto done;
-                       }
-                       /* If the read is short enough we'll do the whole
-                          thing atomically.  Otherwise we have no choice
-                          but to break apart the reads. */
-                       tcnt = msgs[0].len;
-                       offs = 0;
-                       while (tcnt) {
-                               bcnt = tcnt;
-                               if (bcnt > sizeof(hdw->cmd_buffer)-1) {
-                                       bcnt = sizeof(hdw->cmd_buffer)-1;
-                               }
-                               if (funcp(hdw,msgs[0].addr,NULL,0,
-                                         msgs[0].buf+offs,bcnt)) {
-                                       ret = -EIO;
-                                       goto done;
-                               }
-                               offs += bcnt;
-                               tcnt -= bcnt;
-                       }
-                       ret = 1;
-                       goto done;
-               } else {
-                       /* Simple write */
-                       ret = 1;
-                       if (funcp(hdw,msgs[0].addr,
-                                 msgs[0].buf,msgs[0].len,NULL,0)) {
-                               ret = -EIO;
-                       }
-                       goto done;
-               }
-       } else if (num == 2) {
-               if (msgs[0].addr != msgs[1].addr) {
-                       trace_i2c("i2c refusing 2 phase transfer with"
-                                 " conflicting target addresses");
-                       ret = -ENOTSUPP;
-                       goto done;
-               }
-               if ((!((msgs[0].flags & I2C_M_RD))) &&
-                   (msgs[1].flags & I2C_M_RD)) {
-                       u16 tcnt,bcnt,wcnt,offs;
-                       /* Write followed by atomic read.  If the read
-                          portion is short enough we'll do the whole thing
-                          atomically.  Otherwise we have no choice but to
-                          break apart the reads. */
-                       tcnt = msgs[1].len;
-                       wcnt = msgs[0].len;
-                       offs = 0;
-                       while (tcnt || wcnt) {
-                               bcnt = tcnt;
-                               if (bcnt > sizeof(hdw->cmd_buffer)-1) {
-                                       bcnt = sizeof(hdw->cmd_buffer)-1;
-                               }
-                               if (funcp(hdw,msgs[0].addr,
-                                         msgs[0].buf,wcnt,
-                                         msgs[1].buf+offs,bcnt)) {
-                                       ret = -EIO;
-                                       goto done;
-                               }
-                               offs += bcnt;
-                               tcnt -= bcnt;
-                               wcnt = 0;
-                       }
-                       ret = 2;
-                       goto done;
-               } else {
-                       trace_i2c("i2c refusing complex transfer"
-                                 " read0=%d read1=%d",
-                                 (msgs[0].flags & I2C_M_RD),
-                                 (msgs[1].flags & I2C_M_RD));
-               }
-       } else {
-               trace_i2c("i2c refusing %d phase transfer",num);
-       }
-
- done:
-       if (pvrusb2_debug & PVR2_TRACE_I2C_TRAF) {
-               unsigned int idx,offs,cnt;
-               for (idx = 0; idx < num; idx++) {
-                       cnt = msgs[idx].len;
-                       printk(KERN_INFO
-                              "pvrusb2 i2c xfer %u/%u:"
-                              " addr=0x%x len=%d %s",
-                              idx+1,num,
-                              msgs[idx].addr,
-                              cnt,
-                              (msgs[idx].flags & I2C_M_RD ?
-                               "read" : "write"));
-                       if ((ret > 0) || !(msgs[idx].flags & I2C_M_RD)) {
-                               if (cnt > 8) cnt = 8;
-                               printk(" [");
-                               for (offs = 0; offs < (cnt>8?8:cnt); offs++) {
-                                       if (offs) printk(" ");
-                                       printk("%02x",msgs[idx].buf[offs]);
-                               }
-                               if (offs < cnt) printk(" ...");
-                               printk("]");
-                       }
-                       if (idx+1 == num) {
-                               printk(" result=%d",ret);
-                       }
-                       printk("\n");
-               }
-               if (!num) {
-                       printk(KERN_INFO
-                              "pvrusb2 i2c xfer null transfer result=%d\n",
-                              ret);
-               }
-       }
-       return ret;
-}
-
-static u32 pvr2_i2c_functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm pvr2_i2c_algo_template = {
-       .master_xfer   = pvr2_i2c_xfer,
-       .functionality = pvr2_i2c_functionality,
-};
-
-static struct i2c_adapter pvr2_i2c_adap_template = {
-       .owner         = THIS_MODULE,
-       .class         = 0,
-};
-
-
-/* Return true if device exists at given address */
-static int do_i2c_probe(struct pvr2_hdw *hdw, int addr)
-{
-       struct i2c_msg msg[1];
-       int rc;
-       msg[0].addr = 0;
-       msg[0].flags = I2C_M_RD;
-       msg[0].len = 0;
-       msg[0].buf = NULL;
-       msg[0].addr = addr;
-       rc = i2c_transfer(&hdw->i2c_adap, msg, ARRAY_SIZE(msg));
-       return rc == 1;
-}
-
-static void do_i2c_scan(struct pvr2_hdw *hdw)
-{
-       int i;
-       printk(KERN_INFO "%s: i2c scan beginning\n", hdw->name);
-       for (i = 0; i < 128; i++) {
-               if (do_i2c_probe(hdw, i)) {
-                       printk(KERN_INFO "%s: i2c scan: found device @ 0x%x\n",
-                              hdw->name, i);
-               }
-       }
-       printk(KERN_INFO "%s: i2c scan done.\n", hdw->name);
-}
-
-static void pvr2_i2c_register_ir(struct pvr2_hdw *hdw)
-{
-       struct i2c_board_info info;
-       struct IR_i2c_init_data *init_data = &hdw->ir_init_data;
-       if (pvr2_disable_ir_video) {
-               pvr2_trace(PVR2_TRACE_INFO,
-                          "Automatic binding of ir_video has been disabled.");
-               return;
-       }
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       switch (hdw->ir_scheme_active) {
-       case PVR2_IR_SCHEME_24XXX: /* FX2-controlled IR */
-       case PVR2_IR_SCHEME_29XXX: /* Original 29xxx device */
-               init_data->ir_codes              = RC_MAP_HAUPPAUGE;
-               init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
-               init_data->type                  = RC_TYPE_RC5;
-               init_data->name                  = hdw->hdw_desc->description;
-               init_data->polling_interval      = 100; /* ms From ir-kbd-i2c */
-               /* IR Receiver */
-               info.addr          = 0x18;
-               info.platform_data = init_data;
-               strlcpy(info.type, "ir_video", I2C_NAME_SIZE);
-               pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.",
-                          info.type, info.addr);
-               i2c_new_device(&hdw->i2c_adap, &info);
-               break;
-       case PVR2_IR_SCHEME_ZILOG:     /* HVR-1950 style */
-       case PVR2_IR_SCHEME_24XXX_MCE: /* 24xxx MCE device */
-               init_data->ir_codes              = RC_MAP_HAUPPAUGE;
-               init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
-               init_data->type                  = RC_TYPE_RC5;
-               init_data->name                  = hdw->hdw_desc->description;
-               /* IR Receiver */
-               info.addr          = 0x71;
-               info.platform_data = init_data;
-               strlcpy(info.type, "ir_rx_z8f0811_haup", I2C_NAME_SIZE);
-               pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.",
-                          info.type, info.addr);
-               i2c_new_device(&hdw->i2c_adap, &info);
-               /* IR Trasmitter */
-               info.addr          = 0x70;
-               info.platform_data = init_data;
-               strlcpy(info.type, "ir_tx_z8f0811_haup", I2C_NAME_SIZE);
-               pvr2_trace(PVR2_TRACE_INFO, "Binding %s to i2c address 0x%02x.",
-                          info.type, info.addr);
-               i2c_new_device(&hdw->i2c_adap, &info);
-               break;
-       default:
-               /* The device either doesn't support I2C-based IR or we
-                  don't know (yet) how to operate IR on the device. */
-               break;
-       }
-}
-
-void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
-{
-       unsigned int idx;
-
-       /* The default action for all possible I2C addresses is just to do
-          the transfer normally. */
-       for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) {
-               hdw->i2c_func[idx] = pvr2_i2c_basic_op;
-       }
-
-       /* However, deal with various special cases for 24xxx hardware. */
-       if (ir_mode[hdw->unit_number] == 0) {
-               printk(KERN_INFO "%s: IR disabled\n",hdw->name);
-               hdw->i2c_func[0x18] = i2c_black_hole;
-       } else if (ir_mode[hdw->unit_number] == 1) {
-               if (hdw->ir_scheme_active == PVR2_IR_SCHEME_24XXX) {
-                       /* Set up translation so that our IR looks like a
-                          29xxx device */
-                       hdw->i2c_func[0x18] = i2c_24xxx_ir;
-               }
-       }
-       if (hdw->hdw_desc->flag_has_cx25840) {
-               hdw->i2c_func[0x44] = i2c_hack_cx25840;
-       }
-       if (hdw->hdw_desc->flag_has_wm8775) {
-               hdw->i2c_func[0x1b] = i2c_hack_wm8775;
-       }
-
-       // Configure the adapter and set up everything else related to it.
-       memcpy(&hdw->i2c_adap,&pvr2_i2c_adap_template,sizeof(hdw->i2c_adap));
-       memcpy(&hdw->i2c_algo,&pvr2_i2c_algo_template,sizeof(hdw->i2c_algo));
-       strlcpy(hdw->i2c_adap.name,hdw->name,sizeof(hdw->i2c_adap.name));
-       hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev;
-       hdw->i2c_adap.algo = &hdw->i2c_algo;
-       hdw->i2c_adap.algo_data = hdw;
-       hdw->i2c_linked = !0;
-       i2c_set_adapdata(&hdw->i2c_adap, &hdw->v4l2_dev);
-       i2c_add_adapter(&hdw->i2c_adap);
-       if (hdw->i2c_func[0x18] == i2c_24xxx_ir) {
-               /* Probe for a different type of IR receiver on this
-                  device.  This is really the only way to differentiate
-                  older 24xxx devices from 24xxx variants that include an
-                  IR blaster.  If the IR blaster is present, the IR
-                  receiver is part of that chip and thus we must disable
-                  the emulated IR receiver. */
-               if (do_i2c_probe(hdw, 0x71)) {
-                       pvr2_trace(PVR2_TRACE_INFO,
-                                  "Device has newer IR hardware;"
-                                  " disabling unneeded virtual IR device");
-                       hdw->i2c_func[0x18] = NULL;
-                       /* Remember that this is a different device... */
-                       hdw->ir_scheme_active = PVR2_IR_SCHEME_24XXX_MCE;
-               }
-       }
-       if (i2c_scan) do_i2c_scan(hdw);
-
-       pvr2_i2c_register_ir(hdw);
-}
-
-void pvr2_i2c_core_done(struct pvr2_hdw *hdw)
-{
-       if (hdw->i2c_linked) {
-               i2c_del_adapter(&hdw->i2c_adap);
-               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/video/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
deleted file mode 100644 (file)
index 6a75769..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifndef __PVRUSB2_I2C_CORE_H
-#define __PVRUSB2_I2C_CORE_H
-
-struct pvr2_hdw;
-
-void pvr2_i2c_core_init(struct pvr2_hdw *);
-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/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c
deleted file mode 100644 (file)
index 20b6ae0..0000000
+++ /dev/null
@@ -1,695 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include "pvrusb2-io.h"
-#include "pvrusb2-debug.h"
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-
-static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state);
-
-#define BUFFER_SIG 0x47653271
-
-// #define SANITY_CHECK_BUFFERS
-
-
-#ifdef SANITY_CHECK_BUFFERS
-#define BUFFER_CHECK(bp) do { \
-       if ((bp)->signature != BUFFER_SIG) { \
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS, \
-               "Buffer %p is bad at %s:%d", \
-               (bp),__FILE__,__LINE__); \
-               pvr2_buffer_describe(bp,"BadSig"); \
-               BUG(); \
-       } \
-} while (0)
-#else
-#define BUFFER_CHECK(bp) do {} while(0)
-#endif
-
-struct pvr2_stream {
-       /* Buffers queued for reading */
-       struct list_head queued_list;
-       unsigned int q_count;
-       unsigned int q_bcount;
-       /* Buffers with retrieved data */
-       struct list_head ready_list;
-       unsigned int r_count;
-       unsigned int r_bcount;
-       /* Buffers available for use */
-       struct list_head idle_list;
-       unsigned int i_count;
-       unsigned int i_bcount;
-       /* Pointers to all buffers */
-       struct pvr2_buffer **buffers;
-       /* Array size of buffers */
-       unsigned int buffer_slot_count;
-       /* Total buffers actually in circulation */
-       unsigned int buffer_total_count;
-       /* Designed number of buffers to be in circulation */
-       unsigned int buffer_target_count;
-       /* Executed when ready list become non-empty */
-       pvr2_stream_callback callback_func;
-       void *callback_data;
-       /* Context for transfer endpoint */
-       struct usb_device *dev;
-       int endpoint;
-       /* Overhead for mutex enforcement */
-       spinlock_t list_lock;
-       struct mutex mutex;
-       /* Tracking state for tolerating errors */
-       unsigned int fail_count;
-       unsigned int fail_tolerance;
-
-       unsigned int buffers_processed;
-       unsigned int buffers_failed;
-       unsigned int bytes_processed;
-};
-
-struct pvr2_buffer {
-       int id;
-       int signature;
-       enum pvr2_buffer_state state;
-       void *ptr;               /* Pointer to storage area */
-       unsigned int max_count;  /* Size of storage area */
-       unsigned int used_count; /* Amount of valid data in storage area */
-       int status;              /* Transfer result status */
-       struct pvr2_stream *stream;
-       struct list_head list_overhead;
-       struct urb *purb;
-};
-
-static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state st)
-{
-       switch (st) {
-       case pvr2_buffer_state_none: return "none";
-       case pvr2_buffer_state_idle: return "idle";
-       case pvr2_buffer_state_queued: return "queued";
-       case pvr2_buffer_state_ready: return "ready";
-       }
-       return "unknown";
-}
-
-#ifdef SANITY_CHECK_BUFFERS
-static void pvr2_buffer_describe(struct pvr2_buffer *bp,const char *msg)
-{
-       pvr2_trace(PVR2_TRACE_INFO,
-                  "buffer%s%s %p state=%s id=%d status=%d"
-                  " stream=%p purb=%p sig=0x%x",
-                  (msg ? " " : ""),
-                  (msg ? msg : ""),
-                  bp,
-                  (bp ? pvr2_buffer_state_decode(bp->state) : "(invalid)"),
-                  (bp ? bp->id : 0),
-                  (bp ? bp->status : 0),
-                  (bp ? bp->stream : NULL),
-                  (bp ? bp->purb : NULL),
-                  (bp ? bp->signature : 0));
-}
-#endif  /*  SANITY_CHECK_BUFFERS  */
-
-static void pvr2_buffer_remove(struct pvr2_buffer *bp)
-{
-       unsigned int *cnt;
-       unsigned int *bcnt;
-       unsigned int ccnt;
-       struct pvr2_stream *sp = bp->stream;
-       switch (bp->state) {
-       case pvr2_buffer_state_idle:
-               cnt = &sp->i_count;
-               bcnt = &sp->i_bcount;
-               ccnt = bp->max_count;
-               break;
-       case pvr2_buffer_state_queued:
-               cnt = &sp->q_count;
-               bcnt = &sp->q_bcount;
-               ccnt = bp->max_count;
-               break;
-       case pvr2_buffer_state_ready:
-               cnt = &sp->r_count;
-               bcnt = &sp->r_bcount;
-               ccnt = bp->used_count;
-               break;
-       default:
-               return;
-       }
-       list_del_init(&bp->list_overhead);
-       (*cnt)--;
-       (*bcnt) -= ccnt;
-       pvr2_trace(PVR2_TRACE_BUF_FLOW,
-                  "/*---TRACE_FLOW---*/"
-                  " bufferPool     %8s dec cap=%07d cnt=%02d",
-                  pvr2_buffer_state_decode(bp->state),*bcnt,*cnt);
-       bp->state = pvr2_buffer_state_none;
-}
-
-static void pvr2_buffer_set_none(struct pvr2_buffer *bp)
-{
-       unsigned long irq_flags;
-       struct pvr2_stream *sp;
-       BUFFER_CHECK(bp);
-       sp = bp->stream;
-       pvr2_trace(PVR2_TRACE_BUF_FLOW,
-                  "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
-                  bp,
-                  pvr2_buffer_state_decode(bp->state),
-                  pvr2_buffer_state_decode(pvr2_buffer_state_none));
-       spin_lock_irqsave(&sp->list_lock,irq_flags);
-       pvr2_buffer_remove(bp);
-       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
-}
-
-static int pvr2_buffer_set_ready(struct pvr2_buffer *bp)
-{
-       int fl;
-       unsigned long irq_flags;
-       struct pvr2_stream *sp;
-       BUFFER_CHECK(bp);
-       sp = bp->stream;
-       pvr2_trace(PVR2_TRACE_BUF_FLOW,
-                  "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
-                  bp,
-                  pvr2_buffer_state_decode(bp->state),
-                  pvr2_buffer_state_decode(pvr2_buffer_state_ready));
-       spin_lock_irqsave(&sp->list_lock,irq_flags);
-       fl = (sp->r_count == 0);
-       pvr2_buffer_remove(bp);
-       list_add_tail(&bp->list_overhead,&sp->ready_list);
-       bp->state = pvr2_buffer_state_ready;
-       (sp->r_count)++;
-       sp->r_bcount += bp->used_count;
-       pvr2_trace(PVR2_TRACE_BUF_FLOW,
-                  "/*---TRACE_FLOW---*/"
-                  " bufferPool     %8s inc cap=%07d cnt=%02d",
-                  pvr2_buffer_state_decode(bp->state),
-                  sp->r_bcount,sp->r_count);
-       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
-       return fl;
-}
-
-static void pvr2_buffer_set_idle(struct pvr2_buffer *bp)
-{
-       unsigned long irq_flags;
-       struct pvr2_stream *sp;
-       BUFFER_CHECK(bp);
-       sp = bp->stream;
-       pvr2_trace(PVR2_TRACE_BUF_FLOW,
-                  "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
-                  bp,
-                  pvr2_buffer_state_decode(bp->state),
-                  pvr2_buffer_state_decode(pvr2_buffer_state_idle));
-       spin_lock_irqsave(&sp->list_lock,irq_flags);
-       pvr2_buffer_remove(bp);
-       list_add_tail(&bp->list_overhead,&sp->idle_list);
-       bp->state = pvr2_buffer_state_idle;
-       (sp->i_count)++;
-       sp->i_bcount += bp->max_count;
-       pvr2_trace(PVR2_TRACE_BUF_FLOW,
-                  "/*---TRACE_FLOW---*/"
-                  " bufferPool     %8s inc cap=%07d cnt=%02d",
-                  pvr2_buffer_state_decode(bp->state),
-                  sp->i_bcount,sp->i_count);
-       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
-}
-
-static void pvr2_buffer_set_queued(struct pvr2_buffer *bp)
-{
-       unsigned long irq_flags;
-       struct pvr2_stream *sp;
-       BUFFER_CHECK(bp);
-       sp = bp->stream;
-       pvr2_trace(PVR2_TRACE_BUF_FLOW,
-                  "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
-                  bp,
-                  pvr2_buffer_state_decode(bp->state),
-                  pvr2_buffer_state_decode(pvr2_buffer_state_queued));
-       spin_lock_irqsave(&sp->list_lock,irq_flags);
-       pvr2_buffer_remove(bp);
-       list_add_tail(&bp->list_overhead,&sp->queued_list);
-       bp->state = pvr2_buffer_state_queued;
-       (sp->q_count)++;
-       sp->q_bcount += bp->max_count;
-       pvr2_trace(PVR2_TRACE_BUF_FLOW,
-                  "/*---TRACE_FLOW---*/"
-                  " bufferPool     %8s inc cap=%07d cnt=%02d",
-                  pvr2_buffer_state_decode(bp->state),
-                  sp->q_bcount,sp->q_count);
-       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
-}
-
-static void pvr2_buffer_wipe(struct pvr2_buffer *bp)
-{
-       if (bp->state == pvr2_buffer_state_queued) {
-               usb_kill_urb(bp->purb);
-       }
-}
-
-static int pvr2_buffer_init(struct pvr2_buffer *bp,
-                           struct pvr2_stream *sp,
-                           unsigned int id)
-{
-       memset(bp,0,sizeof(*bp));
-       bp->signature = BUFFER_SIG;
-       bp->id = id;
-       pvr2_trace(PVR2_TRACE_BUF_POOL,
-                  "/*---TRACE_FLOW---*/ bufferInit     %p stream=%p",bp,sp);
-       bp->stream = sp;
-       bp->state = pvr2_buffer_state_none;
-       INIT_LIST_HEAD(&bp->list_overhead);
-       bp->purb = usb_alloc_urb(0,GFP_KERNEL);
-       if (! bp->purb) return -ENOMEM;
-#ifdef SANITY_CHECK_BUFFERS
-       pvr2_buffer_describe(bp,"create");
-#endif
-       return 0;
-}
-
-static void pvr2_buffer_done(struct pvr2_buffer *bp)
-{
-#ifdef SANITY_CHECK_BUFFERS
-       pvr2_buffer_describe(bp,"delete");
-#endif
-       pvr2_buffer_wipe(bp);
-       pvr2_buffer_set_none(bp);
-       bp->signature = 0;
-       bp->stream = NULL;
-       usb_free_urb(bp->purb);
-       pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/"
-                  " bufferDone     %p",bp);
-}
-
-static int pvr2_stream_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
-{
-       int ret;
-       unsigned int scnt;
-
-       /* Allocate buffers pointer array in multiples of 32 entries */
-       if (cnt == sp->buffer_total_count) return 0;
-
-       pvr2_trace(PVR2_TRACE_BUF_POOL,
-                  "/*---TRACE_FLOW---*/ poolResize    "
-                  " stream=%p cur=%d adj=%+d",
-                  sp,
-                  sp->buffer_total_count,
-                  cnt-sp->buffer_total_count);
-
-       scnt = cnt & ~0x1f;
-       if (cnt > scnt) scnt += 0x20;
-
-       if (cnt > sp->buffer_total_count) {
-               if (scnt > sp->buffer_slot_count) {
-                       struct pvr2_buffer **nb;
-                       nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL);
-                       if (!nb) return -ENOMEM;
-                       if (sp->buffer_slot_count) {
-                               memcpy(nb,sp->buffers,
-                                      sp->buffer_slot_count * sizeof(*nb));
-                               kfree(sp->buffers);
-                       }
-                       sp->buffers = nb;
-                       sp->buffer_slot_count = scnt;
-               }
-               while (sp->buffer_total_count < cnt) {
-                       struct pvr2_buffer *bp;
-                       bp = kmalloc(sizeof(*bp),GFP_KERNEL);
-                       if (!bp) return -ENOMEM;
-                       ret = pvr2_buffer_init(bp,sp,sp->buffer_total_count);
-                       if (ret) {
-                               kfree(bp);
-                               return -ENOMEM;
-                       }
-                       sp->buffers[sp->buffer_total_count] = bp;
-                       (sp->buffer_total_count)++;
-                       pvr2_buffer_set_idle(bp);
-               }
-       } else {
-               while (sp->buffer_total_count > cnt) {
-                       struct pvr2_buffer *bp;
-                       bp = sp->buffers[sp->buffer_total_count - 1];
-                       /* Paranoia */
-                       sp->buffers[sp->buffer_total_count - 1] = NULL;
-                       (sp->buffer_total_count)--;
-                       pvr2_buffer_done(bp);
-                       kfree(bp);
-               }
-               if (scnt < sp->buffer_slot_count) {
-                       struct pvr2_buffer **nb = NULL;
-                       if (scnt) {
-                               nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL);
-                               if (!nb) return -ENOMEM;
-                               memcpy(nb,sp->buffers,scnt * sizeof(*nb));
-                       }
-                       kfree(sp->buffers);
-                       sp->buffers = nb;
-                       sp->buffer_slot_count = scnt;
-               }
-       }
-       return 0;
-}
-
-static int pvr2_stream_achieve_buffer_count(struct pvr2_stream *sp)
-{
-       struct pvr2_buffer *bp;
-       unsigned int cnt;
-
-       if (sp->buffer_total_count == sp->buffer_target_count) return 0;
-
-       pvr2_trace(PVR2_TRACE_BUF_POOL,
-                  "/*---TRACE_FLOW---*/"
-                  " poolCheck      stream=%p cur=%d tgt=%d",
-                  sp,sp->buffer_total_count,sp->buffer_target_count);
-
-       if (sp->buffer_total_count < sp->buffer_target_count) {
-               return pvr2_stream_buffer_count(sp,sp->buffer_target_count);
-       }
-
-       cnt = 0;
-       while ((sp->buffer_total_count - cnt) > sp->buffer_target_count) {
-               bp = sp->buffers[sp->buffer_total_count - (cnt + 1)];
-               if (bp->state != pvr2_buffer_state_idle) break;
-               cnt++;
-       }
-       if (cnt) {
-               pvr2_stream_buffer_count(sp,sp->buffer_total_count - cnt);
-       }
-
-       return 0;
-}
-
-static void pvr2_stream_internal_flush(struct pvr2_stream *sp)
-{
-       struct list_head *lp;
-       struct pvr2_buffer *bp1;
-       while ((lp = sp->queued_list.next) != &sp->queued_list) {
-               bp1 = list_entry(lp,struct pvr2_buffer,list_overhead);
-               pvr2_buffer_wipe(bp1);
-               /* At this point, we should be guaranteed that no
-                  completion callback may happen on this buffer.  But it's
-                  possible that it might have completed after we noticed
-                  it but before we wiped it.  So double check its status
-                  here first. */
-               if (bp1->state != pvr2_buffer_state_queued) continue;
-               pvr2_buffer_set_idle(bp1);
-       }
-       if (sp->buffer_total_count != sp->buffer_target_count) {
-               pvr2_stream_achieve_buffer_count(sp);
-       }
-}
-
-static void pvr2_stream_init(struct pvr2_stream *sp)
-{
-       spin_lock_init(&sp->list_lock);
-       mutex_init(&sp->mutex);
-       INIT_LIST_HEAD(&sp->queued_list);
-       INIT_LIST_HEAD(&sp->ready_list);
-       INIT_LIST_HEAD(&sp->idle_list);
-}
-
-static void pvr2_stream_done(struct pvr2_stream *sp)
-{
-       mutex_lock(&sp->mutex); do {
-               pvr2_stream_internal_flush(sp);
-               pvr2_stream_buffer_count(sp,0);
-       } while (0); mutex_unlock(&sp->mutex);
-}
-
-static void buffer_complete(struct urb *urb)
-{
-       struct pvr2_buffer *bp = urb->context;
-       struct pvr2_stream *sp;
-       unsigned long irq_flags;
-       BUFFER_CHECK(bp);
-       sp = bp->stream;
-       bp->used_count = 0;
-       bp->status = 0;
-       pvr2_trace(PVR2_TRACE_BUF_FLOW,
-                  "/*---TRACE_FLOW---*/ bufferComplete %p stat=%d cnt=%d",
-                  bp,urb->status,urb->actual_length);
-       spin_lock_irqsave(&sp->list_lock,irq_flags);
-       if ((!(urb->status)) ||
-           (urb->status == -ENOENT) ||
-           (urb->status == -ECONNRESET) ||
-           (urb->status == -ESHUTDOWN)) {
-               (sp->buffers_processed)++;
-               sp->bytes_processed += urb->actual_length;
-               bp->used_count = urb->actual_length;
-               if (sp->fail_count) {
-                       pvr2_trace(PVR2_TRACE_TOLERANCE,
-                                  "stream %p transfer ok"
-                                  " - fail count reset",sp);
-                       sp->fail_count = 0;
-               }
-       } else if (sp->fail_count < sp->fail_tolerance) {
-               // We can tolerate this error, because we're below the
-               // threshold...
-               (sp->fail_count)++;
-               (sp->buffers_failed)++;
-               pvr2_trace(PVR2_TRACE_TOLERANCE,
-                          "stream %p ignoring error %d"
-                          " - fail count increased to %u",
-                          sp,urb->status,sp->fail_count);
-       } else {
-               (sp->buffers_failed)++;
-               bp->status = urb->status;
-       }
-       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
-       pvr2_buffer_set_ready(bp);
-       if (sp && sp->callback_func) {
-               sp->callback_func(sp->callback_data);
-       }
-}
-
-struct pvr2_stream *pvr2_stream_create(void)
-{
-       struct pvr2_stream *sp;
-       sp = kzalloc(sizeof(*sp),GFP_KERNEL);
-       if (!sp) return sp;
-       pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_create: sp=%p",sp);
-       pvr2_stream_init(sp);
-       return sp;
-}
-
-void pvr2_stream_destroy(struct pvr2_stream *sp)
-{
-       if (!sp) return;
-       pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_destroy: sp=%p",sp);
-       pvr2_stream_done(sp);
-       kfree(sp);
-}
-
-void pvr2_stream_setup(struct pvr2_stream *sp,
-                      struct usb_device *dev,
-                      int endpoint,
-                      unsigned int tolerance)
-{
-       mutex_lock(&sp->mutex); do {
-               pvr2_stream_internal_flush(sp);
-               sp->dev = dev;
-               sp->endpoint = endpoint;
-               sp->fail_tolerance = tolerance;
-       } while(0); mutex_unlock(&sp->mutex);
-}
-
-void pvr2_stream_set_callback(struct pvr2_stream *sp,
-                             pvr2_stream_callback func,
-                             void *data)
-{
-       unsigned long irq_flags;
-       mutex_lock(&sp->mutex); do {
-               spin_lock_irqsave(&sp->list_lock,irq_flags);
-               sp->callback_data = data;
-               sp->callback_func = func;
-               spin_unlock_irqrestore(&sp->list_lock,irq_flags);
-       } while(0); mutex_unlock(&sp->mutex);
-}
-
-void pvr2_stream_get_stats(struct pvr2_stream *sp,
-                          struct pvr2_stream_stats *stats,
-                          int zero_counts)
-{
-       unsigned long irq_flags;
-       spin_lock_irqsave(&sp->list_lock,irq_flags);
-       if (stats) {
-               stats->buffers_in_queue = sp->q_count;
-               stats->buffers_in_idle = sp->i_count;
-               stats->buffers_in_ready = sp->r_count;
-               stats->buffers_processed = sp->buffers_processed;
-               stats->buffers_failed = sp->buffers_failed;
-               stats->bytes_processed = sp->bytes_processed;
-       }
-       if (zero_counts) {
-               sp->buffers_processed = 0;
-               sp->buffers_failed = 0;
-               sp->bytes_processed = 0;
-       }
-       spin_unlock_irqrestore(&sp->list_lock,irq_flags);
-}
-
-/* Query / set the nominal buffer count */
-int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
-{
-       return sp->buffer_target_count;
-}
-
-int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
-{
-       int ret;
-       if (sp->buffer_target_count == cnt) return 0;
-       mutex_lock(&sp->mutex); do {
-               sp->buffer_target_count = cnt;
-               ret = pvr2_stream_achieve_buffer_count(sp);
-       } while(0); mutex_unlock(&sp->mutex);
-       return ret;
-}
-
-struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *sp)
-{
-       struct list_head *lp = sp->idle_list.next;
-       if (lp == &sp->idle_list) return NULL;
-       return list_entry(lp,struct pvr2_buffer,list_overhead);
-}
-
-struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *sp)
-{
-       struct list_head *lp = sp->ready_list.next;
-       if (lp == &sp->ready_list) return NULL;
-       return list_entry(lp,struct pvr2_buffer,list_overhead);
-}
-
-struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id)
-{
-       if (id < 0) return NULL;
-       if (id >= sp->buffer_total_count) return NULL;
-       return sp->buffers[id];
-}
-
-int pvr2_stream_get_ready_count(struct pvr2_stream *sp)
-{
-       return sp->r_count;
-}
-
-void pvr2_stream_kill(struct pvr2_stream *sp)
-{
-       struct pvr2_buffer *bp;
-       mutex_lock(&sp->mutex); do {
-               pvr2_stream_internal_flush(sp);
-               while ((bp = pvr2_stream_get_ready_buffer(sp)) != NULL) {
-                       pvr2_buffer_set_idle(bp);
-               }
-               if (sp->buffer_total_count != sp->buffer_target_count) {
-                       pvr2_stream_achieve_buffer_count(sp);
-               }
-       } while(0); mutex_unlock(&sp->mutex);
-}
-
-int pvr2_buffer_queue(struct pvr2_buffer *bp)
-{
-#undef SEED_BUFFER
-#ifdef SEED_BUFFER
-       unsigned int idx;
-       unsigned int val;
-#endif
-       int ret = 0;
-       struct pvr2_stream *sp;
-       if (!bp) return -EINVAL;
-       sp = bp->stream;
-       mutex_lock(&sp->mutex); do {
-               pvr2_buffer_wipe(bp);
-               if (!sp->dev) {
-                       ret = -EIO;
-                       break;
-               }
-               pvr2_buffer_set_queued(bp);
-#ifdef SEED_BUFFER
-               for (idx = 0; idx < (bp->max_count) / 4; idx++) {
-                       val = bp->id << 24;
-                       val |= idx;
-                       ((unsigned int *)(bp->ptr))[idx] = val;
-               }
-#endif
-               bp->status = -EINPROGRESS;
-               usb_fill_bulk_urb(bp->purb,      // struct urb *urb
-                                 sp->dev,       // struct usb_device *dev
-                                 // endpoint (below)
-                                 usb_rcvbulkpipe(sp->dev,sp->endpoint),
-                                 bp->ptr,       // void *transfer_buffer
-                                 bp->max_count, // int buffer_length
-                                 buffer_complete,
-                                 bp);
-               usb_submit_urb(bp->purb,GFP_KERNEL);
-       } while(0); mutex_unlock(&sp->mutex);
-       return ret;
-}
-
-int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt)
-{
-       int ret = 0;
-       unsigned long irq_flags;
-       struct pvr2_stream *sp;
-       if (!bp) return -EINVAL;
-       sp = bp->stream;
-       mutex_lock(&sp->mutex); do {
-               spin_lock_irqsave(&sp->list_lock,irq_flags);
-               if (bp->state != pvr2_buffer_state_idle) {
-                       ret = -EPERM;
-               } else {
-                       bp->ptr = ptr;
-                       bp->stream->i_bcount -= bp->max_count;
-                       bp->max_count = cnt;
-                       bp->stream->i_bcount += bp->max_count;
-                       pvr2_trace(PVR2_TRACE_BUF_FLOW,
-                                  "/*---TRACE_FLOW---*/ bufferPool    "
-                                  " %8s cap cap=%07d cnt=%02d",
-                                  pvr2_buffer_state_decode(
-                                          pvr2_buffer_state_idle),
-                                  bp->stream->i_bcount,bp->stream->i_count);
-               }
-               spin_unlock_irqrestore(&sp->list_lock,irq_flags);
-       } while(0); mutex_unlock(&sp->mutex);
-       return ret;
-}
-
-unsigned int pvr2_buffer_get_count(struct pvr2_buffer *bp)
-{
-       return bp->used_count;
-}
-
-int pvr2_buffer_get_status(struct pvr2_buffer *bp)
-{
-       return bp->status;
-}
-
-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/video/pvrusb2/pvrusb2-io.h b/drivers/media/video/pvrusb2/pvrusb2-io.h
deleted file mode 100644 (file)
index afb7e87..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifndef __PVRUSB2_IO_H
-#define __PVRUSB2_IO_H
-
-#include <linux/usb.h>
-#include <linux/list.h>
-
-typedef void (*pvr2_stream_callback)(void *);
-
-enum pvr2_buffer_state {
-       pvr2_buffer_state_none = 0,   // Not on any list
-       pvr2_buffer_state_idle = 1,   // Buffer is ready to be used again
-       pvr2_buffer_state_queued = 2, // Buffer has been queued for filling
-       pvr2_buffer_state_ready = 3,  // Buffer has data available
-};
-
-struct pvr2_stream;
-struct pvr2_buffer;
-
-struct pvr2_stream_stats {
-       unsigned int buffers_in_queue;
-       unsigned int buffers_in_idle;
-       unsigned int buffers_in_ready;
-       unsigned int buffers_processed;
-       unsigned int buffers_failed;
-       unsigned int bytes_processed;
-};
-
-/* Initialize / tear down stream structure */
-struct pvr2_stream *pvr2_stream_create(void);
-void pvr2_stream_destroy(struct pvr2_stream *);
-void pvr2_stream_setup(struct pvr2_stream *,
-                      struct usb_device *dev,int endpoint,
-                      unsigned int tolerance);
-void pvr2_stream_set_callback(struct pvr2_stream *,
-                             pvr2_stream_callback func,
-                             void *data);
-void pvr2_stream_get_stats(struct pvr2_stream *,
-                          struct pvr2_stream_stats *,
-                          int zero_counts);
-
-/* Query / set the nominal buffer count */
-int pvr2_stream_get_buffer_count(struct pvr2_stream *);
-int pvr2_stream_set_buffer_count(struct pvr2_stream *,unsigned int);
-
-/* Get a pointer to a buffer that is either idle, ready, or is specified
-   named. */
-struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *);
-struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *);
-struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id);
-
-/* Find out how many buffers are idle or ready */
-int pvr2_stream_get_ready_count(struct pvr2_stream *);
-
-
-/* Kill all pending buffers and throw away any ready buffers as well */
-void pvr2_stream_kill(struct pvr2_stream *);
-
-/* Set up the actual storage for a buffer */
-int pvr2_buffer_set_buffer(struct pvr2_buffer *,void *ptr,unsigned int cnt);
-
-/* Find out size of data in the given ready buffer */
-unsigned int pvr2_buffer_get_count(struct pvr2_buffer *);
-
-/* Retrieve completion code for given ready buffer */
-int pvr2_buffer_get_status(struct pvr2_buffer *);
-
-/* Retrieve ID of given buffer */
-int pvr2_buffer_get_id(struct pvr2_buffer *);
-
-/* Start reading into given buffer (kill it if needed) */
-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/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
deleted file mode 100644 (file)
index bba6115..0000000
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include "pvrusb2-ioread.h"
-#include "pvrusb2-debug.h"
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <asm/uaccess.h>
-
-#define BUFFER_COUNT 32
-#define BUFFER_SIZE PAGE_ALIGN(0x4000)
-
-struct pvr2_ioread {
-       struct pvr2_stream *stream;
-       char *buffer_storage[BUFFER_COUNT];
-       char *sync_key_ptr;
-       unsigned int sync_key_len;
-       unsigned int sync_buf_offs;
-       unsigned int sync_state;
-       unsigned int sync_trashed_count;
-       int enabled;         // Streaming is on
-       int spigot_open;     // OK to pass data to client
-       int stream_running;  // Passing data to client now
-
-       /* State relevant to current buffer being read */
-       struct pvr2_buffer *c_buf;
-       char *c_data_ptr;
-       unsigned int c_data_len;
-       unsigned int c_data_offs;
-       struct mutex mutex;
-};
-
-static int pvr2_ioread_init(struct pvr2_ioread *cp)
-{
-       unsigned int idx;
-
-       cp->stream = NULL;
-       mutex_init(&cp->mutex);
-
-       for (idx = 0; idx < BUFFER_COUNT; idx++) {
-               cp->buffer_storage[idx] = kmalloc(BUFFER_SIZE,GFP_KERNEL);
-               if (!(cp->buffer_storage[idx])) break;
-       }
-
-       if (idx < BUFFER_COUNT) {
-               // An allocation appears to have failed
-               for (idx = 0; idx < BUFFER_COUNT; idx++) {
-                       if (!(cp->buffer_storage[idx])) continue;
-                       kfree(cp->buffer_storage[idx]);
-               }
-               return -ENOMEM;
-       }
-       return 0;
-}
-
-static void pvr2_ioread_done(struct pvr2_ioread *cp)
-{
-       unsigned int idx;
-
-       pvr2_ioread_setup(cp,NULL);
-       for (idx = 0; idx < BUFFER_COUNT; idx++) {
-               if (!(cp->buffer_storage[idx])) continue;
-               kfree(cp->buffer_storage[idx]);
-       }
-}
-
-struct pvr2_ioread *pvr2_ioread_create(void)
-{
-       struct pvr2_ioread *cp;
-       cp = kzalloc(sizeof(*cp),GFP_KERNEL);
-       if (!cp) return NULL;
-       pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_create id=%p",cp);
-       if (pvr2_ioread_init(cp) < 0) {
-               kfree(cp);
-               return NULL;
-       }
-       return cp;
-}
-
-void pvr2_ioread_destroy(struct pvr2_ioread *cp)
-{
-       if (!cp) return;
-       pvr2_ioread_done(cp);
-       pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_destroy id=%p",cp);
-       if (cp->sync_key_ptr) {
-               kfree(cp->sync_key_ptr);
-               cp->sync_key_ptr = NULL;
-       }
-       kfree(cp);
-}
-
-void pvr2_ioread_set_sync_key(struct pvr2_ioread *cp,
-                             const char *sync_key_ptr,
-                             unsigned int sync_key_len)
-{
-       if (!cp) return;
-
-       if (!sync_key_ptr) sync_key_len = 0;
-       if ((sync_key_len == cp->sync_key_len) &&
-           ((!sync_key_len) ||
-            (!memcmp(sync_key_ptr,cp->sync_key_ptr,sync_key_len)))) return;
-
-       if (sync_key_len != cp->sync_key_len) {
-               if (cp->sync_key_ptr) {
-                       kfree(cp->sync_key_ptr);
-                       cp->sync_key_ptr = NULL;
-               }
-               cp->sync_key_len = 0;
-               if (sync_key_len) {
-                       cp->sync_key_ptr = kmalloc(sync_key_len,GFP_KERNEL);
-                       if (cp->sync_key_ptr) {
-                               cp->sync_key_len = sync_key_len;
-                       }
-               }
-       }
-       if (!cp->sync_key_len) return;
-       memcpy(cp->sync_key_ptr,sync_key_ptr,cp->sync_key_len);
-}
-
-static void pvr2_ioread_stop(struct pvr2_ioread *cp)
-{
-       if (!(cp->enabled)) return;
-       pvr2_trace(PVR2_TRACE_START_STOP,
-                  "/*---TRACE_READ---*/ pvr2_ioread_stop id=%p",cp);
-       pvr2_stream_kill(cp->stream);
-       cp->c_buf = NULL;
-       cp->c_data_ptr = NULL;
-       cp->c_data_len = 0;
-       cp->c_data_offs = 0;
-       cp->enabled = 0;
-       cp->stream_running = 0;
-       cp->spigot_open = 0;
-       if (cp->sync_state) {
-               pvr2_trace(PVR2_TRACE_DATA_FLOW,
-                          "/*---TRACE_READ---*/ sync_state <== 0");
-               cp->sync_state = 0;
-       }
-}
-
-static int pvr2_ioread_start(struct pvr2_ioread *cp)
-{
-       int stat;
-       struct pvr2_buffer *bp;
-       if (cp->enabled) return 0;
-       if (!(cp->stream)) return 0;
-       pvr2_trace(PVR2_TRACE_START_STOP,
-                  "/*---TRACE_READ---*/ pvr2_ioread_start id=%p",cp);
-       while ((bp = pvr2_stream_get_idle_buffer(cp->stream)) != NULL) {
-               stat = pvr2_buffer_queue(bp);
-               if (stat < 0) {
-                       pvr2_trace(PVR2_TRACE_DATA_FLOW,
-                                  "/*---TRACE_READ---*/"
-                                  " pvr2_ioread_start id=%p"
-                                  " error=%d",
-                                  cp,stat);
-                       pvr2_ioread_stop(cp);
-                       return stat;
-               }
-       }
-       cp->enabled = !0;
-       cp->c_buf = NULL;
-       cp->c_data_ptr = NULL;
-       cp->c_data_len = 0;
-       cp->c_data_offs = 0;
-       cp->stream_running = 0;
-       if (cp->sync_key_len) {
-               pvr2_trace(PVR2_TRACE_DATA_FLOW,
-                          "/*---TRACE_READ---*/ sync_state <== 1");
-               cp->sync_state = 1;
-               cp->sync_trashed_count = 0;
-               cp->sync_buf_offs = 0;
-       }
-       cp->spigot_open = 0;
-       return 0;
-}
-
-struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *cp)
-{
-       return cp->stream;
-}
-
-int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp)
-{
-       int ret;
-       unsigned int idx;
-       struct pvr2_buffer *bp;
-
-       mutex_lock(&cp->mutex); do {
-               if (cp->stream) {
-                       pvr2_trace(PVR2_TRACE_START_STOP,
-                                  "/*---TRACE_READ---*/"
-                                  " pvr2_ioread_setup (tear-down) id=%p",cp);
-                       pvr2_ioread_stop(cp);
-                       pvr2_stream_kill(cp->stream);
-                       if (pvr2_stream_get_buffer_count(cp->stream)) {
-                               pvr2_stream_set_buffer_count(cp->stream,0);
-                       }
-                       cp->stream = NULL;
-               }
-               if (sp) {
-                       pvr2_trace(PVR2_TRACE_START_STOP,
-                                  "/*---TRACE_READ---*/"
-                                  " pvr2_ioread_setup (setup) id=%p",cp);
-                       pvr2_stream_kill(sp);
-                       ret = pvr2_stream_set_buffer_count(sp,BUFFER_COUNT);
-                       if (ret < 0) {
-                               mutex_unlock(&cp->mutex);
-                               return ret;
-                       }
-                       for (idx = 0; idx < BUFFER_COUNT; idx++) {
-                               bp = pvr2_stream_get_buffer(sp,idx);
-                               pvr2_buffer_set_buffer(bp,
-                                                      cp->buffer_storage[idx],
-                                                      BUFFER_SIZE);
-                       }
-                       cp->stream = sp;
-               }
-       } while (0); mutex_unlock(&cp->mutex);
-
-       return 0;
-}
-
-int pvr2_ioread_set_enabled(struct pvr2_ioread *cp,int fl)
-{
-       int ret = 0;
-       if ((!fl) == (!(cp->enabled))) return ret;
-
-       mutex_lock(&cp->mutex); do {
-               if (fl) {
-                       ret = pvr2_ioread_start(cp);
-               } else {
-                       pvr2_ioread_stop(cp);
-               }
-       } while (0); mutex_unlock(&cp->mutex);
-       return ret;
-}
-
-static int pvr2_ioread_get_buffer(struct pvr2_ioread *cp)
-{
-       int stat;
-
-       while (cp->c_data_len <= cp->c_data_offs) {
-               if (cp->c_buf) {
-                       // Flush out current buffer first.
-                       stat = pvr2_buffer_queue(cp->c_buf);
-                       if (stat < 0) {
-                               // Streaming error...
-                               pvr2_trace(PVR2_TRACE_DATA_FLOW,
-                                          "/*---TRACE_READ---*/"
-                                          " pvr2_ioread_read id=%p"
-                                          " queue_error=%d",
-                                          cp,stat);
-                               pvr2_ioread_stop(cp);
-                               return 0;
-                       }
-                       cp->c_buf = NULL;
-                       cp->c_data_ptr = NULL;
-                       cp->c_data_len = 0;
-                       cp->c_data_offs = 0;
-               }
-               // Now get a freshly filled buffer.
-               cp->c_buf = pvr2_stream_get_ready_buffer(cp->stream);
-               if (!cp->c_buf) break; // Nothing ready; done.
-               cp->c_data_len = pvr2_buffer_get_count(cp->c_buf);
-               if (!cp->c_data_len) {
-                       // Nothing transferred.  Was there an error?
-                       stat = pvr2_buffer_get_status(cp->c_buf);
-                       if (stat < 0) {
-                               // Streaming error...
-                               pvr2_trace(PVR2_TRACE_DATA_FLOW,
-                                          "/*---TRACE_READ---*/"
-                                          " pvr2_ioread_read id=%p"
-                                          " buffer_error=%d",
-                                          cp,stat);
-                               pvr2_ioread_stop(cp);
-                               // Give up.
-                               return 0;
-                       }
-                       // Start over...
-                       continue;
-               }
-               cp->c_data_offs = 0;
-               cp->c_data_ptr = cp->buffer_storage[
-                       pvr2_buffer_get_id(cp->c_buf)];
-       }
-       return !0;
-}
-
-static void pvr2_ioread_filter(struct pvr2_ioread *cp)
-{
-       unsigned int idx;
-       if (!cp->enabled) return;
-       if (cp->sync_state != 1) return;
-
-       // Search the stream for our synchronization key.  This is made
-       // complicated by the fact that in order to be honest with
-       // ourselves here we must search across buffer boundaries...
-       mutex_lock(&cp->mutex); while (1) {
-               // Ensure we have a buffer
-               if (!pvr2_ioread_get_buffer(cp)) break;
-               if (!cp->c_data_len) break;
-
-               // Now walk the buffer contents until we match the key or
-               // run out of buffer data.
-               for (idx = cp->c_data_offs; idx < cp->c_data_len; idx++) {
-                       if (cp->sync_buf_offs >= cp->sync_key_len) break;
-                       if (cp->c_data_ptr[idx] ==
-                           cp->sync_key_ptr[cp->sync_buf_offs]) {
-                               // Found the next key byte
-                               (cp->sync_buf_offs)++;
-                       } else {
-                               // Whoops, mismatched.  Start key over...
-                               cp->sync_buf_offs = 0;
-                       }
-               }
-
-               // Consume what we've walked through
-               cp->c_data_offs += idx;
-               cp->sync_trashed_count += idx;
-
-               // If we've found the key, then update state and get out.
-               if (cp->sync_buf_offs >= cp->sync_key_len) {
-                       cp->sync_trashed_count -= cp->sync_key_len;
-                       pvr2_trace(PVR2_TRACE_DATA_FLOW,
-                                  "/*---TRACE_READ---*/"
-                                  " sync_state <== 2 (skipped %u bytes)",
-                                  cp->sync_trashed_count);
-                       cp->sync_state = 2;
-                       cp->sync_buf_offs = 0;
-                       break;
-               }
-
-               if (cp->c_data_offs < cp->c_data_len) {
-                       // Sanity check - should NEVER get here
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "ERROR: pvr2_ioread filter sync problem"
-                                  " len=%u offs=%u",
-                                  cp->c_data_len,cp->c_data_offs);
-                       // Get out so we don't get stuck in an infinite
-                       // loop.
-                       break;
-               }
-
-               continue; // (for clarity)
-       } mutex_unlock(&cp->mutex);
-}
-
-int pvr2_ioread_avail(struct pvr2_ioread *cp)
-{
-       int ret;
-       if (!(cp->enabled)) {
-               // Stream is not enabled; so this is an I/O error
-               return -EIO;
-       }
-
-       if (cp->sync_state == 1) {
-               pvr2_ioread_filter(cp);
-               if (cp->sync_state == 1) return -EAGAIN;
-       }
-
-       ret = 0;
-       if (cp->stream_running) {
-               if (!pvr2_stream_get_ready_count(cp->stream)) {
-                       // No data available at all right now.
-                       ret = -EAGAIN;
-               }
-       } else {
-               if (pvr2_stream_get_ready_count(cp->stream) < BUFFER_COUNT/2) {
-                       // Haven't buffered up enough yet; try again later
-                       ret = -EAGAIN;
-               }
-       }
-
-       if ((!(cp->spigot_open)) != (!(ret == 0))) {
-               cp->spigot_open = (ret == 0);
-               pvr2_trace(PVR2_TRACE_DATA_FLOW,
-                          "/*---TRACE_READ---*/ data is %s",
-                          cp->spigot_open ? "available" : "pending");
-       }
-
-       return ret;
-}
-
-int pvr2_ioread_read(struct pvr2_ioread *cp,void __user *buf,unsigned int cnt)
-{
-       unsigned int copied_cnt;
-       unsigned int bcnt;
-       const char *src;
-       int stat;
-       int ret = 0;
-       unsigned int req_cnt = cnt;
-
-       if (!cnt) {
-               pvr2_trace(PVR2_TRACE_TRAP,
-                          "/*---TRACE_READ---*/ pvr2_ioread_read id=%p"
-                          " ZERO Request? Returning zero.",cp);
-               return 0;
-       }
-
-       stat = pvr2_ioread_avail(cp);
-       if (stat < 0) return stat;
-
-       cp->stream_running = !0;
-
-       mutex_lock(&cp->mutex); do {
-
-               // Suck data out of the buffers and copy to the user
-               copied_cnt = 0;
-               if (!buf) cnt = 0;
-               while (1) {
-                       if (!pvr2_ioread_get_buffer(cp)) {
-                               ret = -EIO;
-                               break;
-                       }
-
-                       if (!cnt) break;
-
-                       if (cp->sync_state == 2) {
-                               // We're repeating the sync key data into
-                               // the stream.
-                               src = cp->sync_key_ptr + cp->sync_buf_offs;
-                               bcnt = cp->sync_key_len - cp->sync_buf_offs;
-                       } else {
-                               // Normal buffer copy
-                               src = cp->c_data_ptr + cp->c_data_offs;
-                               bcnt = cp->c_data_len - cp->c_data_offs;
-                       }
-
-                       if (!bcnt) break;
-
-                       // Don't run past user's buffer
-                       if (bcnt > cnt) bcnt = cnt;
-
-                       if (copy_to_user(buf,src,bcnt)) {
-                               // User supplied a bad pointer?
-                               // Give up - this *will* cause data
-                               // to be lost.
-                               ret = -EFAULT;
-                               break;
-                       }
-                       cnt -= bcnt;
-                       buf += bcnt;
-                       copied_cnt += bcnt;
-
-                       if (cp->sync_state == 2) {
-                               // Update offset inside sync key that we're
-                               // repeating back out.
-                               cp->sync_buf_offs += bcnt;
-                               if (cp->sync_buf_offs >= cp->sync_key_len) {
-                                       // Consumed entire key; switch mode
-                                       // to normal.
-                                       pvr2_trace(PVR2_TRACE_DATA_FLOW,
-                                                  "/*---TRACE_READ---*/"
-                                                  " sync_state <== 0");
-                                       cp->sync_state = 0;
-                               }
-                       } else {
-                               // Update buffer offset.
-                               cp->c_data_offs += bcnt;
-                       }
-               }
-
-       } while (0); mutex_unlock(&cp->mutex);
-
-       if (!ret) {
-               if (copied_cnt) {
-                       // If anything was copied, return that count
-                       ret = copied_cnt;
-               } else {
-                       // Nothing copied; suggest to caller that another
-                       // attempt should be tried again later
-                       ret = -EAGAIN;
-               }
-       }
-
-       pvr2_trace(PVR2_TRACE_DATA_FLOW,
-                  "/*---TRACE_READ---*/ pvr2_ioread_read"
-                  " id=%p request=%d result=%d",
-                  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/video/pvrusb2/pvrusb2-ioread.h b/drivers/media/video/pvrusb2/pvrusb2-ioread.h
deleted file mode 100644 (file)
index 100e078..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifndef __PVRUSB2_IOREAD_H
-#define __PVRUSB2_IOREAD_H
-
-#include "pvrusb2-io.h"
-
-struct pvr2_ioread;
-
-struct pvr2_ioread *pvr2_ioread_create(void);
-void pvr2_ioread_destroy(struct pvr2_ioread *);
-int pvr2_ioread_setup(struct pvr2_ioread *,struct pvr2_stream *);
-struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *);
-void pvr2_ioread_set_sync_key(struct pvr2_ioread *,
-                             const char *sync_key_ptr,
-                             unsigned int sync_key_len);
-int pvr2_ioread_set_enabled(struct pvr2_ioread *,int fl);
-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/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c
deleted file mode 100644 (file)
index c1d9bb6..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-
-#include "pvrusb2-hdw.h"
-#include "pvrusb2-devattr.h"
-#include "pvrusb2-context.h"
-#include "pvrusb2-debug.h"
-#include "pvrusb2-v4l2.h"
-#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
-#include "pvrusb2-sysfs.h"
-#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
-
-#define DRIVER_AUTHOR "Mike Isely <isely@pobox.com>"
-#define DRIVER_DESC "Hauppauge WinTV-PVR-USB2 MPEG2 Encoder/Tuner"
-#define DRIVER_VERSION "V4L in-tree version"
-
-#define DEFAULT_DEBUG_MASK (PVR2_TRACE_ERROR_LEGS| \
-                           PVR2_TRACE_INFO| \
-                           PVR2_TRACE_STD| \
-                           PVR2_TRACE_TOLERANCE| \
-                           PVR2_TRACE_TRAP| \
-                           0)
-
-int pvrusb2_debug = DEFAULT_DEBUG_MASK;
-
-module_param_named(debug,pvrusb2_debug,int,S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug trace mask");
-
-#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
-static struct pvr2_sysfs_class *class_ptr = NULL;
-#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
-
-static void pvr_setup_attach(struct pvr2_context *pvr)
-{
-       /* Create association with v4l layer */
-       pvr2_v4l2_create(pvr);
-#ifdef CONFIG_VIDEO_PVRUSB2_DVB
-       /* Create association with dvb layer */
-       pvr2_dvb_create(pvr);
-#endif
-#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
-       pvr2_sysfs_create(pvr,class_ptr);
-#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
-}
-
-static int pvr_probe(struct usb_interface *intf,
-                    const struct usb_device_id *devid)
-{
-       struct pvr2_context *pvr;
-
-       /* Create underlying hardware interface */
-       pvr = pvr2_context_create(intf,devid,pvr_setup_attach);
-       if (!pvr) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "Failed to create hdw handler");
-               return -ENOMEM;
-       }
-
-       pvr2_trace(PVR2_TRACE_INIT,"pvr_probe(pvr=%p)",pvr);
-
-       usb_set_intfdata(intf, pvr);
-
-       return 0;
-}
-
-/*
- * pvr_disconnect()
- *
- */
-static void pvr_disconnect(struct usb_interface *intf)
-{
-       struct pvr2_context *pvr = usb_get_intfdata(intf);
-
-       pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) BEGIN",pvr);
-
-       usb_set_intfdata (intf, NULL);
-       pvr2_context_disconnect(pvr);
-
-       pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) DONE",pvr);
-
-}
-
-static struct usb_driver pvr_driver = {
-       .name =         "pvrusb2",
-       .id_table =     pvr2_device_table,
-       .probe =        pvr_probe,
-       .disconnect =   pvr_disconnect
-};
-
-/*
- * pvr_init() / pvr_exit()
- *
- * This code is run to initialize/exit the driver.
- *
- */
-static int __init pvr_init(void)
-{
-       int ret;
-
-       pvr2_trace(PVR2_TRACE_INIT,"pvr_init");
-
-       ret = pvr2_context_global_init();
-       if (ret != 0) {
-               pvr2_trace(PVR2_TRACE_INIT,"pvr_init failure code=%d",ret);
-               return ret;
-       }
-
-#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
-       class_ptr = pvr2_sysfs_class_create();
-#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
-
-       ret = usb_register(&pvr_driver);
-
-       if (ret == 0)
-               printk(KERN_INFO "pvrusb2: " DRIVER_VERSION ":"
-                      DRIVER_DESC "\n");
-       if (pvrusb2_debug)
-               printk(KERN_INFO "pvrusb2: Debug mask is %d (0x%x)\n",
-                      pvrusb2_debug,pvrusb2_debug);
-
-       pvr2_trace(PVR2_TRACE_INIT,"pvr_init complete");
-
-       return ret;
-}
-
-static void __exit pvr_exit(void)
-{
-       pvr2_trace(PVR2_TRACE_INIT,"pvr_exit");
-
-       usb_deregister(&pvr_driver);
-
-       pvr2_context_global_done();
-
-#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
-       pvr2_sysfs_class_destroy(class_ptr);
-#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
-
-       pvr2_trace(PVR2_TRACE_INIT,"pvr_exit complete");
-}
-
-module_init(pvr_init);
-module_exit(pvr_exit);
-
-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/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c
deleted file mode 100644 (file)
index 453627b..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include "pvrusb2-std.h"
-#include "pvrusb2-debug.h"
-#include <asm/string.h>
-#include <linux/slab.h>
-
-struct std_name {
-       const char *name;
-       v4l2_std_id id;
-};
-
-
-#define CSTD_PAL \
-       (V4L2_STD_PAL_B| \
-        V4L2_STD_PAL_B1| \
-        V4L2_STD_PAL_G| \
-        V4L2_STD_PAL_H| \
-        V4L2_STD_PAL_I| \
-        V4L2_STD_PAL_D| \
-        V4L2_STD_PAL_D1| \
-        V4L2_STD_PAL_K| \
-        V4L2_STD_PAL_M| \
-        V4L2_STD_PAL_N| \
-        V4L2_STD_PAL_Nc| \
-        V4L2_STD_PAL_60)
-
-#define CSTD_NTSC \
-       (V4L2_STD_NTSC_M| \
-        V4L2_STD_NTSC_M_JP| \
-        V4L2_STD_NTSC_M_KR| \
-        V4L2_STD_NTSC_443)
-
-#define CSTD_ATSC \
-       (V4L2_STD_ATSC_8_VSB| \
-        V4L2_STD_ATSC_16_VSB)
-
-#define CSTD_SECAM \
-       (V4L2_STD_SECAM_B| \
-        V4L2_STD_SECAM_D| \
-        V4L2_STD_SECAM_G| \
-        V4L2_STD_SECAM_H| \
-        V4L2_STD_SECAM_K| \
-        V4L2_STD_SECAM_K1| \
-        V4L2_STD_SECAM_L| \
-        V4L2_STD_SECAM_LC)
-
-#define TSTD_B   (V4L2_STD_PAL_B|V4L2_STD_SECAM_B)
-#define TSTD_B1  (V4L2_STD_PAL_B1)
-#define TSTD_D   (V4L2_STD_PAL_D|V4L2_STD_SECAM_D)
-#define TSTD_D1  (V4L2_STD_PAL_D1)
-#define TSTD_G   (V4L2_STD_PAL_G|V4L2_STD_SECAM_G)
-#define TSTD_H   (V4L2_STD_PAL_H|V4L2_STD_SECAM_H)
-#define TSTD_I   (V4L2_STD_PAL_I)
-#define TSTD_K   (V4L2_STD_PAL_K|V4L2_STD_SECAM_K)
-#define TSTD_K1  (V4L2_STD_SECAM_K1)
-#define TSTD_L   (V4L2_STD_SECAM_L)
-#define TSTD_M   (V4L2_STD_PAL_M|V4L2_STD_NTSC_M)
-#define TSTD_N   (V4L2_STD_PAL_N)
-#define TSTD_Nc  (V4L2_STD_PAL_Nc)
-#define TSTD_60  (V4L2_STD_PAL_60)
-
-#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_ATSC|CSTD_SECAM)
-
-/* Mapping of standard bits to color system */
-static const struct std_name std_groups[] = {
-       {"PAL",CSTD_PAL},
-       {"NTSC",CSTD_NTSC},
-       {"SECAM",CSTD_SECAM},
-       {"ATSC",CSTD_ATSC},
-};
-
-/* Mapping of standard bits to modulation system */
-static const struct std_name std_items[] = {
-       {"B",TSTD_B},
-       {"B1",TSTD_B1},
-       {"D",TSTD_D},
-       {"D1",TSTD_D1},
-       {"G",TSTD_G},
-       {"H",TSTD_H},
-       {"I",TSTD_I},
-       {"K",TSTD_K},
-       {"K1",TSTD_K1},
-       {"L",TSTD_L},
-       {"LC",V4L2_STD_SECAM_LC},
-       {"M",TSTD_M},
-       {"Mj",V4L2_STD_NTSC_M_JP},
-       {"443",V4L2_STD_NTSC_443},
-       {"Mk",V4L2_STD_NTSC_M_KR},
-       {"N",TSTD_N},
-       {"Nc",TSTD_Nc},
-       {"60",TSTD_60},
-       {"8VSB",V4L2_STD_ATSC_8_VSB},
-       {"16VSB",V4L2_STD_ATSC_16_VSB},
-};
-
-
-// Search an array of std_name structures and return a pointer to the
-// element with the matching name.
-static const struct std_name *find_std_name(const struct std_name *arrPtr,
-                                           unsigned int arrSize,
-                                           const char *bufPtr,
-                                           unsigned int bufSize)
-{
-       unsigned int idx;
-       const struct std_name *p;
-       for (idx = 0; idx < arrSize; idx++) {
-               p = arrPtr + idx;
-               if (strlen(p->name) != bufSize) continue;
-               if (!memcmp(bufPtr,p->name,bufSize)) return p;
-       }
-       return NULL;
-}
-
-
-int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
-                      unsigned int bufSize)
-{
-       v4l2_std_id id = 0;
-       v4l2_std_id cmsk = 0;
-       v4l2_std_id t;
-       int mMode = 0;
-       unsigned int cnt;
-       char ch;
-       const struct std_name *sp;
-
-       while (bufSize) {
-               if (!mMode) {
-                       cnt = 0;
-                       while ((cnt < bufSize) && (bufPtr[cnt] != '-')) cnt++;
-                       if (cnt >= bufSize) return 0; // No more characters
-                       sp = find_std_name(std_groups, ARRAY_SIZE(std_groups),
-                                          bufPtr,cnt);
-                       if (!sp) return 0; // Illegal color system name
-                       cnt++;
-                       bufPtr += cnt;
-                       bufSize -= cnt;
-                       mMode = !0;
-                       cmsk = sp->id;
-                       continue;
-               }
-               cnt = 0;
-               while (cnt < bufSize) {
-                       ch = bufPtr[cnt];
-                       if (ch == ';') {
-                               mMode = 0;
-                               break;
-                       }
-                       if (ch == '/') break;
-                       cnt++;
-               }
-               sp = find_std_name(std_items, ARRAY_SIZE(std_items),
-                                  bufPtr,cnt);
-               if (!sp) return 0; // Illegal modulation system ID
-               t = sp->id & cmsk;
-               if (!t) return 0; // Specific color + modulation system illegal
-               id |= t;
-               if (cnt < bufSize) cnt++;
-               bufPtr += cnt;
-               bufSize -= cnt;
-       }
-
-       if (idPtr) *idPtr = id;
-       return !0;
-}
-
-
-unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize,
-                               v4l2_std_id id)
-{
-       unsigned int idx1,idx2;
-       const struct std_name *ip,*gp;
-       int gfl,cfl;
-       unsigned int c1,c2;
-       cfl = 0;
-       c1 = 0;
-       for (idx1 = 0; idx1 < ARRAY_SIZE(std_groups); idx1++) {
-               gp = std_groups + idx1;
-               gfl = 0;
-               for (idx2 = 0; idx2 < ARRAY_SIZE(std_items); idx2++) {
-                       ip = std_items + idx2;
-                       if (!(gp->id & ip->id & id)) continue;
-                       if (!gfl) {
-                               if (cfl) {
-                                       c2 = scnprintf(bufPtr,bufSize,";");
-                                       c1 += c2;
-                                       bufSize -= c2;
-                                       bufPtr += c2;
-                               }
-                               cfl = !0;
-                               c2 = scnprintf(bufPtr,bufSize,
-                                              "%s-",gp->name);
-                               gfl = !0;
-                       } else {
-                               c2 = scnprintf(bufPtr,bufSize,"/");
-                       }
-                       c1 += c2;
-                       bufSize -= c2;
-                       bufPtr += c2;
-                       c2 = scnprintf(bufPtr,bufSize,
-                                      ip->name);
-                       c1 += c2;
-                       bufSize -= c2;
-                       bufPtr += c2;
-               }
-       }
-       return c1;
-}
-
-
-// Template data for possible enumerated video standards.  Here we group
-// standards which share common frame rates and resolution.
-static struct v4l2_standard generic_standards[] = {
-       {
-               .id             = (TSTD_B|TSTD_B1|
-                                  TSTD_D|TSTD_D1|
-                                  TSTD_G|
-                                  TSTD_H|
-                                  TSTD_I|
-                                  TSTD_K|TSTD_K1|
-                                  TSTD_L|
-                                  V4L2_STD_SECAM_LC |
-                                  TSTD_N|TSTD_Nc),
-               .frameperiod    =
-               {
-                       .numerator  = 1,
-                       .denominator= 25
-               },
-               .framelines     = 625,
-               .reserved       = {0,0,0,0}
-       }, {
-               .id             = (TSTD_M|
-                                  V4L2_STD_NTSC_M_JP|
-                                  V4L2_STD_NTSC_M_KR),
-               .frameperiod    =
-               {
-                       .numerator  = 1001,
-                       .denominator= 30000
-               },
-               .framelines     = 525,
-               .reserved       = {0,0,0,0}
-       }, { // This is a total wild guess
-               .id             = (TSTD_60),
-               .frameperiod    =
-               {
-                       .numerator  = 1001,
-                       .denominator= 30000
-               },
-               .framelines     = 525,
-               .reserved       = {0,0,0,0}
-       }, { // This is total wild guess
-               .id             = V4L2_STD_NTSC_443,
-               .frameperiod    =
-               {
-                       .numerator  = 1001,
-                       .denominator= 30000
-               },
-               .framelines     = 525,
-               .reserved       = {0,0,0,0}
-       }
-};
-
-static struct v4l2_standard *match_std(v4l2_std_id id)
-{
-       unsigned int idx;
-       for (idx = 0; idx < ARRAY_SIZE(generic_standards); idx++) {
-               if (generic_standards[idx].id & id) {
-                       return generic_standards + idx;
-               }
-       }
-       return NULL;
-}
-
-static int pvr2_std_fill(struct v4l2_standard *std,v4l2_std_id id)
-{
-       struct v4l2_standard *template;
-       int idx;
-       unsigned int bcnt;
-       template = match_std(id);
-       if (!template) return 0;
-       idx = std->index;
-       memcpy(std,template,sizeof(*template));
-       std->index = idx;
-       std->id = id;
-       bcnt = pvr2_std_id_to_str(std->name,sizeof(std->name)-1,id);
-       std->name[bcnt] = 0;
-       pvr2_trace(PVR2_TRACE_STD,"Set up standard idx=%u name=%s",
-                  std->index,std->name);
-       return !0;
-}
-
-/* These are special cases of combined standards that we should enumerate
-   separately if the component pieces are present. */
-static v4l2_std_id std_mixes[] = {
-       V4L2_STD_PAL_B | V4L2_STD_PAL_G,
-       V4L2_STD_PAL_D | V4L2_STD_PAL_K,
-       V4L2_STD_SECAM_B | V4L2_STD_SECAM_G,
-       V4L2_STD_SECAM_D | V4L2_STD_SECAM_K,
-};
-
-struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
-                                          v4l2_std_id id)
-{
-       unsigned int std_cnt = 0;
-       unsigned int idx,bcnt,idx2;
-       v4l2_std_id idmsk,cmsk,fmsk;
-       struct v4l2_standard *stddefs;
-
-       if (pvrusb2_debug & PVR2_TRACE_STD) {
-               char buf[100];
-               bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id);
-               pvr2_trace(
-                       PVR2_TRACE_STD,"Mapping standards mask=0x%x (%.*s)",
-                       (int)id,bcnt,buf);
-       }
-
-       *countptr = 0;
-       std_cnt = 0;
-       fmsk = 0;
-       for (idmsk = 1, cmsk = id; cmsk; idmsk <<= 1) {
-               if (!(idmsk & cmsk)) continue;
-               cmsk &= ~idmsk;
-               if (match_std(idmsk)) {
-                       std_cnt++;
-                       continue;
-               }
-               fmsk |= idmsk;
-       }
-
-       for (idx2 = 0; idx2 < ARRAY_SIZE(std_mixes); idx2++) {
-               if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++;
-       }
-
-       /* Don't complain about ATSC standard values */
-       fmsk &= ~CSTD_ATSC;
-
-       if (fmsk) {
-               char buf[100];
-               bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk);
-               pvr2_trace(
-                       PVR2_TRACE_ERROR_LEGS,
-                       "WARNING:"
-                       " Failed to classify the following standard(s): %.*s",
-                       bcnt,buf);
-       }
-
-       pvr2_trace(PVR2_TRACE_STD,"Setting up %u unique standard(s)",
-                  std_cnt);
-       if (!std_cnt) return NULL; // paranoia
-
-       stddefs = kzalloc(sizeof(struct v4l2_standard) * std_cnt,
-                         GFP_KERNEL);
-       if (!stddefs)
-               return NULL;
-
-       for (idx = 0; idx < std_cnt; idx++)
-               stddefs[idx].index = idx;
-
-       idx = 0;
-
-       /* Enumerate potential special cases */
-       for (idx2 = 0; (idx2 < ARRAY_SIZE(std_mixes)) && (idx < std_cnt);
-            idx2++) {
-               if (!(id & std_mixes[idx2])) continue;
-               if (pvr2_std_fill(stddefs+idx,std_mixes[idx2])) idx++;
-       }
-       /* Now enumerate individual pieces */
-       for (idmsk = 1, cmsk = id; cmsk && (idx < std_cnt); idmsk <<= 1) {
-               if (!(idmsk & cmsk)) continue;
-               cmsk &= ~idmsk;
-               if (!pvr2_std_fill(stddefs+idx,idmsk)) continue;
-               idx++;
-       }
-
-       *countptr = std_cnt;
-       return stddefs;
-}
-
-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/video/pvrusb2/pvrusb2-std.h b/drivers/media/video/pvrusb2/pvrusb2-std.h
deleted file mode 100644 (file)
index a35c53d..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifndef __PVRUSB2_STD_H
-#define __PVRUSB2_STD_H
-
-#include <linux/videodev2.h>
-
-// Convert string describing one or more video standards into a mask of V4L
-// standard bits.  Return true if conversion succeeds otherwise return
-// false.  String is expected to be of the form: C1-x/y;C2-a/b where C1 and
-// C2 are color system names (e.g. "PAL", "NTSC") and x, y, a, and b are
-// modulation schemes (e.g. "M", "B", "G", etc).
-int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
-                      unsigned int bufSize);
-
-// Convert any arbitrary set of video standard bits into an unambiguous
-// readable string.  Return value is the number of bytes consumed in the
-// buffer.  The formatted string is of a form that can be parsed by our
-// sibling std_std_to_id() function.
-unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize,
-                               v4l2_std_id id);
-
-// Create an array of suitable v4l2_standard structures given a bit mask of
-// video standards to support.  The array is allocated from the heap, and
-// the number of elements is returned in the first argument.
-struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
-                                          v4l2_std_id id);
-
-// Return mask of which video standard bits are valid
-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/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
deleted file mode 100644 (file)
index 6ef1335..0000000
+++ /dev/null
@@ -1,861 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/string.h>
-#include <linux/slab.h>
-#include "pvrusb2-sysfs.h"
-#include "pvrusb2-hdw.h"
-#include "pvrusb2-debug.h"
-#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
-#include "pvrusb2-debugifc.h"
-#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
-
-#define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__)
-
-struct pvr2_sysfs {
-       struct pvr2_channel channel;
-       struct device *class_dev;
-#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
-       struct pvr2_sysfs_debugifc *debugifc;
-#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
-       struct pvr2_sysfs_ctl_item *item_first;
-       struct pvr2_sysfs_ctl_item *item_last;
-       struct device_attribute attr_v4l_minor_number;
-       struct device_attribute attr_v4l_radio_minor_number;
-       struct device_attribute attr_unit_number;
-       struct device_attribute attr_bus_info;
-       struct device_attribute attr_hdw_name;
-       struct device_attribute attr_hdw_desc;
-       int v4l_minor_number_created_ok;
-       int v4l_radio_minor_number_created_ok;
-       int unit_number_created_ok;
-       int bus_info_created_ok;
-       int hdw_name_created_ok;
-       int hdw_desc_created_ok;
-};
-
-#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
-struct pvr2_sysfs_debugifc {
-       struct device_attribute attr_debugcmd;
-       struct device_attribute attr_debuginfo;
-       int debugcmd_created_ok;
-       int debuginfo_created_ok;
-};
-#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
-
-struct pvr2_sysfs_ctl_item {
-       struct device_attribute attr_name;
-       struct device_attribute attr_type;
-       struct device_attribute attr_min;
-       struct device_attribute attr_max;
-       struct device_attribute attr_def;
-       struct device_attribute attr_enum;
-       struct device_attribute attr_bits;
-       struct device_attribute attr_val;
-       struct device_attribute attr_custom;
-       struct pvr2_ctrl *cptr;
-       int ctl_id;
-       struct pvr2_sysfs *chptr;
-       struct pvr2_sysfs_ctl_item *item_next;
-       struct attribute *attr_gen[8];
-       struct attribute_group grp;
-       int created_ok;
-       char name[80];
-};
-
-struct pvr2_sysfs_class {
-       struct class class;
-};
-
-static ssize_t show_name(struct device *class_dev,
-                        struct device_attribute *attr,
-                        char *buf)
-{
-       struct pvr2_sysfs_ctl_item *cip;
-       const char *name;
-       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_name);
-       name = pvr2_ctrl_get_desc(cip->cptr);
-       pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",
-                        cip->chptr, cip->ctl_id, name);
-       if (!name) return -EINVAL;
-       return scnprintf(buf, PAGE_SIZE, "%s\n", name);
-}
-
-static ssize_t show_type(struct device *class_dev,
-                        struct device_attribute *attr,
-                        char *buf)
-{
-       struct pvr2_sysfs_ctl_item *cip;
-       const char *name;
-       enum pvr2_ctl_type tp;
-       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_type);
-       tp = pvr2_ctrl_get_type(cip->cptr);
-       switch (tp) {
-       case pvr2_ctl_int: name = "integer"; break;
-       case pvr2_ctl_enum: name = "enum"; break;
-       case pvr2_ctl_bitmask: name = "bitmask"; break;
-       case pvr2_ctl_bool: name = "boolean"; break;
-       default: name = "?"; break;
-       }
-       pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",
-                        cip->chptr, cip->ctl_id, name);
-       if (!name) return -EINVAL;
-       return scnprintf(buf, PAGE_SIZE, "%s\n", name);
-}
-
-static ssize_t show_min(struct device *class_dev,
-                       struct device_attribute *attr,
-                       char *buf)
-{
-       struct pvr2_sysfs_ctl_item *cip;
-       long val;
-       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_min);
-       val = pvr2_ctrl_get_min(cip->cptr);
-       pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",
-                        cip->chptr, cip->ctl_id, val);
-       return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
-}
-
-static ssize_t show_max(struct device *class_dev,
-                       struct device_attribute *attr,
-                       char *buf)
-{
-       struct pvr2_sysfs_ctl_item *cip;
-       long val;
-       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_max);
-       val = pvr2_ctrl_get_max(cip->cptr);
-       pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",
-                        cip->chptr, cip->ctl_id, val);
-       return scnprintf(buf, PAGE_SIZE, "%ld\n", val);
-}
-
-static ssize_t show_def(struct device *class_dev,
-                       struct device_attribute *attr,
-                       char *buf)
-{
-       struct pvr2_sysfs_ctl_item *cip;
-       int val;
-       int ret;
-       unsigned int cnt = 0;
-       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_def);
-       ret = pvr2_ctrl_get_def(cip->cptr, &val);
-       if (ret < 0) return ret;
-       ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
-                                    buf, PAGE_SIZE - 1, &cnt);
-       pvr2_sysfs_trace("pvr2_sysfs(%p) show_def(cid=%d) is %.*s (%d)",
-                        cip->chptr, cip->ctl_id, cnt, buf, val);
-       buf[cnt] = '\n';
-       return cnt + 1;
-}
-
-static ssize_t show_val_norm(struct device *class_dev,
-                            struct device_attribute *attr,
-                            char *buf)
-{
-       struct pvr2_sysfs_ctl_item *cip;
-       int val;
-       int ret;
-       unsigned int cnt = 0;
-       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
-       ret = pvr2_ctrl_get_value(cip->cptr, &val);
-       if (ret < 0) return ret;
-       ret = pvr2_ctrl_value_to_sym(cip->cptr, ~0, val,
-                                    buf, PAGE_SIZE - 1, &cnt);
-       pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
-                        cip->chptr, cip->ctl_id, cnt, buf, val);
-       buf[cnt] = '\n';
-       return cnt+1;
-}
-
-static ssize_t show_val_custom(struct device *class_dev,
-                              struct device_attribute *attr,
-                              char *buf)
-{
-       struct pvr2_sysfs_ctl_item *cip;
-       int val;
-       int ret;
-       unsigned int cnt = 0;
-       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
-       ret = pvr2_ctrl_get_value(cip->cptr, &val);
-       if (ret < 0) return ret;
-       ret = pvr2_ctrl_custom_value_to_sym(cip->cptr, ~0, val,
-                                           buf, PAGE_SIZE - 1, &cnt);
-       pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
-                        cip->chptr, cip->ctl_id, cnt, buf, val);
-       buf[cnt] = '\n';
-       return cnt+1;
-}
-
-static ssize_t show_enum(struct device *class_dev,
-                        struct device_attribute *attr,
-                        char *buf)
-{
-       struct pvr2_sysfs_ctl_item *cip;
-       long val;
-       unsigned int bcnt, ccnt, ecnt;
-       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_enum);
-       ecnt = pvr2_ctrl_get_cnt(cip->cptr);
-       bcnt = 0;
-       for (val = 0; val < ecnt; val++) {
-               pvr2_ctrl_get_valname(cip->cptr, val, buf + bcnt,
-                                     PAGE_SIZE - bcnt, &ccnt);
-               if (!ccnt) continue;
-               bcnt += ccnt;
-               if (bcnt >= PAGE_SIZE) break;
-               buf[bcnt] = '\n';
-               bcnt++;
-       }
-       pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",
-                        cip->chptr, cip->ctl_id);
-       return bcnt;
-}
-
-static ssize_t show_bits(struct device *class_dev,
-                        struct device_attribute *attr,
-                        char *buf)
-{
-       struct pvr2_sysfs_ctl_item *cip;
-       int valid_bits, msk;
-       unsigned int bcnt, ccnt;
-       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_bits);
-       valid_bits = pvr2_ctrl_get_mask(cip->cptr);
-       bcnt = 0;
-       for (msk = 1; valid_bits; msk <<= 1) {
-               if (!(msk & valid_bits)) continue;
-               valid_bits &= ~msk;
-               pvr2_ctrl_get_valname(cip->cptr, msk, buf + bcnt,
-                                     PAGE_SIZE - bcnt, &ccnt);
-               bcnt += ccnt;
-               if (bcnt >= PAGE_SIZE) break;
-               buf[bcnt] = '\n';
-               bcnt++;
-       }
-       pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",
-                        cip->chptr, cip->ctl_id);
-       return bcnt;
-}
-
-static int store_val_any(struct pvr2_sysfs_ctl_item *cip, int customfl,
-                        const char *buf,unsigned int count)
-{
-       int ret;
-       int mask,val;
-       if (customfl) {
-               ret = pvr2_ctrl_custom_sym_to_value(cip->cptr, buf, count,
-                                                   &mask, &val);
-       } else {
-               ret = pvr2_ctrl_sym_to_value(cip->cptr, buf, count,
-                                            &mask, &val);
-       }
-       if (ret < 0) return ret;
-       ret = pvr2_ctrl_set_mask_value(cip->cptr, mask, val);
-       pvr2_hdw_commit_ctl(cip->chptr->channel.hdw);
-       return ret;
-}
-
-static ssize_t store_val_norm(struct device *class_dev,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       struct pvr2_sysfs_ctl_item *cip;
-       int ret;
-       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_val);
-       pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_norm(cid=%d) \"%.*s\"",
-                        cip->chptr, cip->ctl_id, (int)count, buf);
-       ret = store_val_any(cip, 0, buf, count);
-       if (!ret) ret = count;
-       return ret;
-}
-
-static ssize_t store_val_custom(struct device *class_dev,
-                               struct device_attribute *attr,
-                               const char *buf, size_t count)
-{
-       struct pvr2_sysfs_ctl_item *cip;
-       int ret;
-       cip = container_of(attr, struct pvr2_sysfs_ctl_item, attr_custom);
-       pvr2_sysfs_trace("pvr2_sysfs(%p) store_val_custom(cid=%d) \"%.*s\"",
-                        cip->chptr, cip->ctl_id, (int)count, buf);
-       ret = store_val_any(cip, 1, buf, count);
-       if (!ret) ret = count;
-       return ret;
-}
-
-static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
-{
-       struct pvr2_sysfs_ctl_item *cip;
-       struct pvr2_ctrl *cptr;
-       unsigned int cnt,acnt;
-       int ret;
-
-       cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id);
-       if (!cptr) return;
-
-       cip = kzalloc(sizeof(*cip),GFP_KERNEL);
-       if (!cip) return;
-       pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip);
-
-       cip->cptr = cptr;
-       cip->ctl_id = ctl_id;
-
-       cip->chptr = sfp;
-       cip->item_next = NULL;
-       if (sfp->item_last) {
-               sfp->item_last->item_next = cip;
-       } else {
-               sfp->item_first = cip;
-       }
-       sfp->item_last = cip;
-
-       sysfs_attr_init(&cip->attr_name.attr);
-       cip->attr_name.attr.name = "name";
-       cip->attr_name.attr.mode = S_IRUGO;
-       cip->attr_name.show = show_name;
-
-       sysfs_attr_init(&cip->attr_type.attr);
-       cip->attr_type.attr.name = "type";
-       cip->attr_type.attr.mode = S_IRUGO;
-       cip->attr_type.show = show_type;
-
-       sysfs_attr_init(&cip->attr_min.attr);
-       cip->attr_min.attr.name = "min_val";
-       cip->attr_min.attr.mode = S_IRUGO;
-       cip->attr_min.show = show_min;
-
-       sysfs_attr_init(&cip->attr_max.attr);
-       cip->attr_max.attr.name = "max_val";
-       cip->attr_max.attr.mode = S_IRUGO;
-       cip->attr_max.show = show_max;
-
-       sysfs_attr_init(&cip->attr_def.attr);
-       cip->attr_def.attr.name = "def_val";
-       cip->attr_def.attr.mode = S_IRUGO;
-       cip->attr_def.show = show_def;
-
-       sysfs_attr_init(&cip->attr_val.attr);
-       cip->attr_val.attr.name = "cur_val";
-       cip->attr_val.attr.mode = S_IRUGO;
-
-       sysfs_attr_init(&cip->attr_custom.attr);
-       cip->attr_custom.attr.name = "custom_val";
-       cip->attr_custom.attr.mode = S_IRUGO;
-
-       sysfs_attr_init(&cip->attr_enum.attr);
-       cip->attr_enum.attr.name = "enum_val";
-       cip->attr_enum.attr.mode = S_IRUGO;
-       cip->attr_enum.show = show_enum;
-
-       sysfs_attr_init(&cip->attr_bits.attr);
-       cip->attr_bits.attr.name = "bit_val";
-       cip->attr_bits.attr.mode = S_IRUGO;
-       cip->attr_bits.show = show_bits;
-
-       if (pvr2_ctrl_is_writable(cptr)) {
-               cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP;
-               cip->attr_custom.attr.mode |= S_IWUSR|S_IWGRP;
-       }
-
-       acnt = 0;
-       cip->attr_gen[acnt++] = &cip->attr_name.attr;
-       cip->attr_gen[acnt++] = &cip->attr_type.attr;
-       cip->attr_gen[acnt++] = &cip->attr_val.attr;
-       cip->attr_gen[acnt++] = &cip->attr_def.attr;
-       cip->attr_val.show = show_val_norm;
-       cip->attr_val.store = store_val_norm;
-       if (pvr2_ctrl_has_custom_symbols(cptr)) {
-               cip->attr_gen[acnt++] = &cip->attr_custom.attr;
-               cip->attr_custom.show = show_val_custom;
-               cip->attr_custom.store = store_val_custom;
-       }
-       switch (pvr2_ctrl_get_type(cptr)) {
-       case pvr2_ctl_enum:
-               // Control is an enumeration
-               cip->attr_gen[acnt++] = &cip->attr_enum.attr;
-               break;
-       case pvr2_ctl_int:
-               // Control is an integer
-               cip->attr_gen[acnt++] = &cip->attr_min.attr;
-               cip->attr_gen[acnt++] = &cip->attr_max.attr;
-               break;
-       case pvr2_ctl_bitmask:
-               // Control is an bitmask
-               cip->attr_gen[acnt++] = &cip->attr_bits.attr;
-               break;
-       default: break;
-       }
-
-       cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s",
-                       pvr2_ctrl_get_name(cptr));
-       cip->name[cnt] = 0;
-       cip->grp.name = cip->name;
-       cip->grp.attrs = cip->attr_gen;
-
-       ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
-       if (ret) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "sysfs_create_group error: %d",
-                          ret);
-               return;
-       }
-       cip->created_ok = !0;
-}
-
-#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
-static ssize_t debuginfo_show(struct device *, struct device_attribute *,
-                             char *);
-static ssize_t debugcmd_show(struct device *, struct device_attribute *,
-                            char *);
-static ssize_t debugcmd_store(struct device *, struct device_attribute *,
-                             const char *, size_t count);
-
-static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
-{
-       struct pvr2_sysfs_debugifc *dip;
-       int ret;
-
-       dip = kzalloc(sizeof(*dip),GFP_KERNEL);
-       if (!dip) return;
-       sysfs_attr_init(&dip->attr_debugcmd.attr);
-       dip->attr_debugcmd.attr.name = "debugcmd";
-       dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP;
-       dip->attr_debugcmd.show = debugcmd_show;
-       dip->attr_debugcmd.store = debugcmd_store;
-       sysfs_attr_init(&dip->attr_debuginfo.attr);
-       dip->attr_debuginfo.attr.name = "debuginfo";
-       dip->attr_debuginfo.attr.mode = S_IRUGO;
-       dip->attr_debuginfo.show = debuginfo_show;
-       sfp->debugifc = dip;
-       ret = device_create_file(sfp->class_dev,&dip->attr_debugcmd);
-       if (ret < 0) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "device_create_file error: %d",
-                          ret);
-       } else {
-               dip->debugcmd_created_ok = !0;
-       }
-       ret = device_create_file(sfp->class_dev,&dip->attr_debuginfo);
-       if (ret < 0) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "device_create_file error: %d",
-                          ret);
-       } else {
-               dip->debuginfo_created_ok = !0;
-       }
-}
-
-
-static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
-{
-       if (!sfp->debugifc) return;
-       if (sfp->debugifc->debuginfo_created_ok) {
-               device_remove_file(sfp->class_dev,
-                                        &sfp->debugifc->attr_debuginfo);
-       }
-       if (sfp->debugifc->debugcmd_created_ok) {
-               device_remove_file(sfp->class_dev,
-                                        &sfp->debugifc->attr_debugcmd);
-       }
-       kfree(sfp->debugifc);
-       sfp->debugifc = NULL;
-}
-#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
-
-
-static void pvr2_sysfs_add_controls(struct pvr2_sysfs *sfp)
-{
-       unsigned int idx,cnt;
-       cnt = pvr2_hdw_get_ctrl_count(sfp->channel.hdw);
-       for (idx = 0; idx < cnt; idx++) {
-               pvr2_sysfs_add_control(sfp,idx);
-       }
-}
-
-
-static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp)
-{
-       struct pvr2_sysfs_ctl_item *cip1,*cip2;
-       for (cip1 = sfp->item_first; cip1; cip1 = cip2) {
-               cip2 = cip1->item_next;
-               if (cip1->created_ok) {
-                       sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
-               }
-               pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1);
-               kfree(cip1);
-       }
-}
-
-
-static void pvr2_sysfs_class_release(struct class *class)
-{
-       struct pvr2_sysfs_class *clp;
-       clp = container_of(class,struct pvr2_sysfs_class,class);
-       pvr2_sysfs_trace("Destroying pvr2_sysfs_class id=%p",clp);
-       kfree(clp);
-}
-
-
-static void pvr2_sysfs_release(struct device *class_dev)
-{
-       pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev);
-       kfree(class_dev);
-}
-
-
-static void class_dev_destroy(struct pvr2_sysfs *sfp)
-{
-       struct device *dev;
-       if (!sfp->class_dev) return;
-#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
-       pvr2_sysfs_tear_down_debugifc(sfp);
-#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
-       pvr2_sysfs_tear_down_controls(sfp);
-       if (sfp->hdw_desc_created_ok) {
-               device_remove_file(sfp->class_dev,
-                                  &sfp->attr_hdw_desc);
-       }
-       if (sfp->hdw_name_created_ok) {
-               device_remove_file(sfp->class_dev,
-                                  &sfp->attr_hdw_name);
-       }
-       if (sfp->bus_info_created_ok) {
-               device_remove_file(sfp->class_dev,
-                                        &sfp->attr_bus_info);
-       }
-       if (sfp->v4l_minor_number_created_ok) {
-               device_remove_file(sfp->class_dev,
-                                        &sfp->attr_v4l_minor_number);
-       }
-       if (sfp->v4l_radio_minor_number_created_ok) {
-               device_remove_file(sfp->class_dev,
-                                        &sfp->attr_v4l_radio_minor_number);
-       }
-       if (sfp->unit_number_created_ok) {
-               device_remove_file(sfp->class_dev,
-                                        &sfp->attr_unit_number);
-       }
-       pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
-       dev_set_drvdata(sfp->class_dev, NULL);
-       dev = sfp->class_dev->parent;
-       sfp->class_dev->parent = NULL;
-       put_device(dev);
-       device_unregister(sfp->class_dev);
-       sfp->class_dev = NULL;
-}
-
-
-static ssize_t v4l_minor_number_show(struct device *class_dev,
-                                    struct device_attribute *attr, char *buf)
-{
-       struct pvr2_sysfs *sfp;
-       sfp = dev_get_drvdata(class_dev);
-       if (!sfp) return -EINVAL;
-       return scnprintf(buf,PAGE_SIZE,"%d\n",
-                        pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
-                                                      pvr2_v4l_type_video));
-}
-
-
-static ssize_t bus_info_show(struct device *class_dev,
-                            struct device_attribute *attr, char *buf)
-{
-       struct pvr2_sysfs *sfp;
-       sfp = dev_get_drvdata(class_dev);
-       if (!sfp) return -EINVAL;
-       return scnprintf(buf,PAGE_SIZE,"%s\n",
-                        pvr2_hdw_get_bus_info(sfp->channel.hdw));
-}
-
-
-static ssize_t hdw_name_show(struct device *class_dev,
-                            struct device_attribute *attr, char *buf)
-{
-       struct pvr2_sysfs *sfp;
-       sfp = dev_get_drvdata(class_dev);
-       if (!sfp) return -EINVAL;
-       return scnprintf(buf,PAGE_SIZE,"%s\n",
-                        pvr2_hdw_get_type(sfp->channel.hdw));
-}
-
-
-static ssize_t hdw_desc_show(struct device *class_dev,
-                            struct device_attribute *attr, char *buf)
-{
-       struct pvr2_sysfs *sfp;
-       sfp = dev_get_drvdata(class_dev);
-       if (!sfp) return -EINVAL;
-       return scnprintf(buf,PAGE_SIZE,"%s\n",
-                        pvr2_hdw_get_desc(sfp->channel.hdw));
-}
-
-
-static ssize_t v4l_radio_minor_number_show(struct device *class_dev,
-                                          struct device_attribute *attr,
-                                          char *buf)
-{
-       struct pvr2_sysfs *sfp;
-       sfp = dev_get_drvdata(class_dev);
-       if (!sfp) return -EINVAL;
-       return scnprintf(buf,PAGE_SIZE,"%d\n",
-                        pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw,
-                                                      pvr2_v4l_type_radio));
-}
-
-
-static ssize_t unit_number_show(struct device *class_dev,
-                               struct device_attribute *attr, char *buf)
-{
-       struct pvr2_sysfs *sfp;
-       sfp = dev_get_drvdata(class_dev);
-       if (!sfp) return -EINVAL;
-       return scnprintf(buf,PAGE_SIZE,"%d\n",
-                        pvr2_hdw_get_unit_number(sfp->channel.hdw));
-}
-
-
-static void class_dev_create(struct pvr2_sysfs *sfp,
-                            struct pvr2_sysfs_class *class_ptr)
-{
-       struct usb_device *usb_dev;
-       struct device *class_dev;
-       int ret;
-
-       usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
-       if (!usb_dev) return;
-       class_dev = kzalloc(sizeof(*class_dev),GFP_KERNEL);
-       if (!class_dev) return;
-
-       pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
-
-       class_dev->class = &class_ptr->class;
-
-       dev_set_name(class_dev, "%s",
-                    pvr2_hdw_get_device_identifier(sfp->channel.hdw));
-
-       class_dev->parent = get_device(&usb_dev->dev);
-
-       sfp->class_dev = class_dev;
-       dev_set_drvdata(class_dev, sfp);
-       ret = device_register(class_dev);
-       if (ret) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "device_register failed");
-               put_device(class_dev);
-               return;
-       }
-
-       sysfs_attr_init(&sfp->attr_v4l_minor_number.attr);
-       sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
-       sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
-       sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
-       sfp->attr_v4l_minor_number.store = NULL;
-       ret = device_create_file(sfp->class_dev,
-                                      &sfp->attr_v4l_minor_number);
-       if (ret < 0) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "device_create_file error: %d",
-                          ret);
-       } else {
-               sfp->v4l_minor_number_created_ok = !0;
-       }
-
-       sysfs_attr_init(&sfp->attr_v4l_radio_minor_number.attr);
-       sfp->attr_v4l_radio_minor_number.attr.name = "v4l_radio_minor_number";
-       sfp->attr_v4l_radio_minor_number.attr.mode = S_IRUGO;
-       sfp->attr_v4l_radio_minor_number.show = v4l_radio_minor_number_show;
-       sfp->attr_v4l_radio_minor_number.store = NULL;
-       ret = device_create_file(sfp->class_dev,
-                                      &sfp->attr_v4l_radio_minor_number);
-       if (ret < 0) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "device_create_file error: %d",
-                          ret);
-       } else {
-               sfp->v4l_radio_minor_number_created_ok = !0;
-       }
-
-       sysfs_attr_init(&sfp->attr_unit_number.attr);
-       sfp->attr_unit_number.attr.name = "unit_number";
-       sfp->attr_unit_number.attr.mode = S_IRUGO;
-       sfp->attr_unit_number.show = unit_number_show;
-       sfp->attr_unit_number.store = NULL;
-       ret = device_create_file(sfp->class_dev,&sfp->attr_unit_number);
-       if (ret < 0) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "device_create_file error: %d",
-                          ret);
-       } else {
-               sfp->unit_number_created_ok = !0;
-       }
-
-       sysfs_attr_init(&sfp->attr_bus_info.attr);
-       sfp->attr_bus_info.attr.name = "bus_info_str";
-       sfp->attr_bus_info.attr.mode = S_IRUGO;
-       sfp->attr_bus_info.show = bus_info_show;
-       sfp->attr_bus_info.store = NULL;
-       ret = device_create_file(sfp->class_dev,
-                                      &sfp->attr_bus_info);
-       if (ret < 0) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "device_create_file error: %d",
-                          ret);
-       } else {
-               sfp->bus_info_created_ok = !0;
-       }
-
-       sysfs_attr_init(&sfp->attr_hdw_name.attr);
-       sfp->attr_hdw_name.attr.name = "device_hardware_type";
-       sfp->attr_hdw_name.attr.mode = S_IRUGO;
-       sfp->attr_hdw_name.show = hdw_name_show;
-       sfp->attr_hdw_name.store = NULL;
-       ret = device_create_file(sfp->class_dev,
-                                &sfp->attr_hdw_name);
-       if (ret < 0) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "device_create_file error: %d",
-                          ret);
-       } else {
-               sfp->hdw_name_created_ok = !0;
-       }
-
-       sysfs_attr_init(&sfp->attr_hdw_desc.attr);
-       sfp->attr_hdw_desc.attr.name = "device_hardware_description";
-       sfp->attr_hdw_desc.attr.mode = S_IRUGO;
-       sfp->attr_hdw_desc.show = hdw_desc_show;
-       sfp->attr_hdw_desc.store = NULL;
-       ret = device_create_file(sfp->class_dev,
-                                &sfp->attr_hdw_desc);
-       if (ret < 0) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "device_create_file error: %d",
-                          ret);
-       } else {
-               sfp->hdw_desc_created_ok = !0;
-       }
-
-       pvr2_sysfs_add_controls(sfp);
-#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
-       pvr2_sysfs_add_debugifc(sfp);
-#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
-}
-
-
-static void pvr2_sysfs_internal_check(struct pvr2_channel *chp)
-{
-       struct pvr2_sysfs *sfp;
-       sfp = container_of(chp,struct pvr2_sysfs,channel);
-       if (!sfp->channel.mc_head->disconnect_flag) return;
-       pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_sysfs id=%p",sfp);
-       class_dev_destroy(sfp);
-       pvr2_channel_done(&sfp->channel);
-       kfree(sfp);
-}
-
-
-struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp,
-                                    struct pvr2_sysfs_class *class_ptr)
-{
-       struct pvr2_sysfs *sfp;
-       sfp = kzalloc(sizeof(*sfp),GFP_KERNEL);
-       if (!sfp) return sfp;
-       pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp);
-       pvr2_channel_init(&sfp->channel,mp);
-       sfp->channel.check_func = pvr2_sysfs_internal_check;
-
-       class_dev_create(sfp,class_ptr);
-       return sfp;
-}
-
-
-
-struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
-{
-       struct pvr2_sysfs_class *clp;
-       clp = kzalloc(sizeof(*clp),GFP_KERNEL);
-       if (!clp) return clp;
-       pvr2_sysfs_trace("Creating and registering pvr2_sysfs_class id=%p",
-                        clp);
-       clp->class.name = "pvrusb2";
-       clp->class.class_release = pvr2_sysfs_class_release;
-       clp->class.dev_release = pvr2_sysfs_release;
-       if (class_register(&clp->class)) {
-               pvr2_sysfs_trace(
-                       "Registration failed for pvr2_sysfs_class id=%p",clp);
-               kfree(clp);
-               clp = NULL;
-       }
-       return clp;
-}
-
-
-void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp)
-{
-       pvr2_sysfs_trace("Unregistering pvr2_sysfs_class id=%p", clp);
-       class_unregister(&clp->class);
-}
-
-
-#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
-static ssize_t debuginfo_show(struct device *class_dev,
-                             struct device_attribute *attr, char *buf)
-{
-       struct pvr2_sysfs *sfp;
-       sfp = dev_get_drvdata(class_dev);
-       if (!sfp) return -EINVAL;
-       pvr2_hdw_trigger_module_log(sfp->channel.hdw);
-       return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE);
-}
-
-
-static ssize_t debugcmd_show(struct device *class_dev,
-                            struct device_attribute *attr, char *buf)
-{
-       struct pvr2_sysfs *sfp;
-       sfp = dev_get_drvdata(class_dev);
-       if (!sfp) return -EINVAL;
-       return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE);
-}
-
-
-static ssize_t debugcmd_store(struct device *class_dev,
-                             struct device_attribute *attr,
-                             const char *buf, size_t count)
-{
-       struct pvr2_sysfs *sfp;
-       int ret;
-
-       sfp = dev_get_drvdata(class_dev);
-       if (!sfp) return -EINVAL;
-
-       ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count);
-       if (ret < 0) return ret;
-       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/video/pvrusb2/pvrusb2-sysfs.h b/drivers/media/video/pvrusb2/pvrusb2-sysfs.h
deleted file mode 100644 (file)
index 6d875bf..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifndef __PVRUSB2_SYSFS_H
-#define __PVRUSB2_SYSFS_H
-
-#include <linux/list.h>
-#include <linux/sysfs.h>
-#include "pvrusb2-context.h"
-
-struct pvr2_sysfs;
-struct pvr2_sysfs_class;
-
-struct pvr2_sysfs_class *pvr2_sysfs_class_create(void);
-void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *);
-
-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/video/pvrusb2/pvrusb2-util.h b/drivers/media/video/pvrusb2/pvrusb2-util.h
deleted file mode 100644 (file)
index 92b7554..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifndef __PVRUSB2_UTIL_H
-#define __PVRUSB2_UTIL_H
-
-#define PVR2_DECOMPOSE_LE(t,i,d) \
-    do {    \
-       (t)[i] = (d) & 0xff;\
-       (t)[i+1] = ((d) >> 8) & 0xff;\
-       (t)[i+2] = ((d) >> 16) & 0xff;\
-       (t)[i+3] = ((d) >> 24) & 0xff;\
-    } while(0)
-
-#define PVR2_DECOMPOSE_BE(t,i,d) \
-    do {    \
-       (t)[i+3] = (d) & 0xff;\
-       (t)[i+2] = ((d) >> 8) & 0xff;\
-       (t)[i+1] = ((d) >> 16) & 0xff;\
-       (t)[i] = ((d) >> 24) & 0xff;\
-    } while(0)
-
-#define PVR2_COMPOSE_LE(t,i) \
-    ((((u32)((t)[i+3])) << 24) | \
-     (((u32)((t)[i+2])) << 16) | \
-     (((u32)((t)[i+1])) << 8) | \
-     ((u32)((t)[i])))
-
-#define PVR2_COMPOSE_BE(t,i) \
-    ((((u32)((t)[i])) << 24) | \
-     (((u32)((t)[i+1])) << 16) | \
-     (((u32)((t)[i+2])) << 8) | \
-     ((u32)((t)[i+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/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
deleted file mode 100644 (file)
index f344aed..0000000
+++ /dev/null
@@ -1,1413 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/version.h>
-#include "pvrusb2-context.h"
-#include "pvrusb2-hdw.h"
-#include "pvrusb2.h"
-#include "pvrusb2-debug.h"
-#include "pvrusb2-v4l2.h"
-#include "pvrusb2-ioread.h"
-#include <linux/videodev2.h>
-#include <linux/module.h>
-#include <media/v4l2-dev.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-
-struct pvr2_v4l2_dev;
-struct pvr2_v4l2_fh;
-struct pvr2_v4l2;
-
-struct pvr2_v4l2_dev {
-       struct video_device devbase; /* MUST be first! */
-       struct pvr2_v4l2 *v4lp;
-       struct pvr2_context_stream *stream;
-       /* Information about this device: */
-       enum pvr2_config config; /* Expected stream format */
-       int v4l_type; /* V4L defined type for this device node */
-       enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
-};
-
-struct pvr2_v4l2_fh {
-       struct pvr2_channel channel;
-       struct pvr2_v4l2_dev *pdi;
-       enum v4l2_priority prio;
-       struct pvr2_ioread *rhp;
-       struct file *file;
-       struct pvr2_v4l2 *vhead;
-       struct pvr2_v4l2_fh *vnext;
-       struct pvr2_v4l2_fh *vprev;
-       wait_queue_head_t wait_data;
-       int fw_mode_flag;
-       /* Map contiguous ordinal value to input id */
-       unsigned char *input_map;
-       unsigned int input_cnt;
-};
-
-struct pvr2_v4l2 {
-       struct pvr2_channel channel;
-       struct pvr2_v4l2_fh *vfirst;
-       struct pvr2_v4l2_fh *vlast;
-
-       struct v4l2_prio_state prio;
-
-       /* streams - Note that these must be separately, individually,
-        * allocated pointers.  This is because the v4l core is going to
-        * manage their deletion - separately, individually...  */
-       struct pvr2_v4l2_dev *dev_video;
-       struct pvr2_v4l2_dev *dev_radio;
-};
-
-static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
-module_param_array(video_nr, int, NULL, 0444);
-MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
-static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
-module_param_array(radio_nr, int, NULL, 0444);
-MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
-static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
-module_param_array(vbi_nr, int, NULL, 0444);
-MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
-
-static struct v4l2_capability pvr_capability ={
-       .driver         = "pvrusb2",
-       .card           = "Hauppauge WinTV pvr-usb2",
-       .bus_info       = "usb",
-       .version        = LINUX_VERSION_CODE,
-       .capabilities   = (V4L2_CAP_VIDEO_CAPTURE |
-                          V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
-                          V4L2_CAP_READWRITE),
-};
-
-static struct v4l2_fmtdesc pvr_fmtdesc [] = {
-       {
-               .index          = 0,
-               .type           = V4L2_BUF_TYPE_VIDEO_CAPTURE,
-               .flags          = V4L2_FMT_FLAG_COMPRESSED,
-               .description    = "MPEG1/2",
-               // This should really be V4L2_PIX_FMT_MPEG, but xawtv
-               // breaks when I do that.
-               .pixelformat    = 0, // V4L2_PIX_FMT_MPEG,
-       }
-};
-
-#define PVR_FORMAT_PIX  0
-#define PVR_FORMAT_VBI  1
-
-static struct v4l2_format pvr_format [] = {
-       [PVR_FORMAT_PIX] = {
-               .type   = V4L2_BUF_TYPE_VIDEO_CAPTURE,
-               .fmt    = {
-                       .pix        = {
-                               .width          = 720,
-                               .height             = 576,
-                               // This should really be V4L2_PIX_FMT_MPEG,
-                               // but xawtv breaks when I do that.
-                               .pixelformat    = 0, // V4L2_PIX_FMT_MPEG,
-                               .field          = V4L2_FIELD_INTERLACED,
-                               .bytesperline   = 0,  // doesn't make sense
-                                                     // here
-                               //FIXME : Don't know what to put here...
-                               .sizeimage          = (32*1024),
-                               .colorspace     = 0, // doesn't make sense here
-                               .priv           = 0
-                       }
-               }
-       },
-       [PVR_FORMAT_VBI] = {
-               .type   = V4L2_BUF_TYPE_VBI_CAPTURE,
-               .fmt    = {
-                       .vbi        = {
-                               .sampling_rate = 27000000,
-                               .offset = 248,
-                               .samples_per_line = 1443,
-                               .sample_format = V4L2_PIX_FMT_GREY,
-                               .start = { 0, 0 },
-                               .count = { 0, 0 },
-                               .flags = 0,
-                       }
-               }
-       }
-};
-
-
-
-/*
- * This is part of Video 4 Linux API. These procedures handle ioctl() calls.
- */
-static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-
-       memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
-       strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
-                       sizeof(cap->bus_info));
-       strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
-       return 0;
-}
-
-static int pvr2_g_priority(struct file *file, void *priv, enum v4l2_priority *p)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_v4l2 *vp = fh->vhead;
-
-       *p = v4l2_prio_max(&vp->prio);
-       return 0;
-}
-
-static int pvr2_s_priority(struct file *file, void *priv, enum v4l2_priority prio)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_v4l2 *vp = fh->vhead;
-
-       return v4l2_prio_change(&vp->prio, &fh->prio, prio);
-}
-
-static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       int val = 0;
-       int ret;
-
-       ret = pvr2_ctrl_get_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), &val);
-       *std = val;
-       return ret;
-}
-
-int pvr2_s_std(struct file *file, void *priv, v4l2_std_id *std)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-
-       return pvr2_ctrl_set_value(
-               pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), *std);
-}
-
-static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       int val = 0;
-       int ret;
-
-       ret = pvr2_ctrl_get_value(
-               pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDDETECT), &val);
-       *std = val;
-       return ret;
-}
-
-static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       struct pvr2_ctrl *cptr;
-       struct v4l2_input tmp;
-       unsigned int cnt;
-       int val;
-
-       cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
-
-       memset(&tmp, 0, sizeof(tmp));
-       tmp.index = vi->index;
-       if (vi->index >= fh->input_cnt)
-               return -EINVAL;
-       val = fh->input_map[vi->index];
-       switch (val) {
-       case PVR2_CVAL_INPUT_TV:
-       case PVR2_CVAL_INPUT_DTV:
-       case PVR2_CVAL_INPUT_RADIO:
-               tmp.type = V4L2_INPUT_TYPE_TUNER;
-               break;
-       case PVR2_CVAL_INPUT_SVIDEO:
-       case PVR2_CVAL_INPUT_COMPOSITE:
-               tmp.type = V4L2_INPUT_TYPE_CAMERA;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       cnt = 0;
-       pvr2_ctrl_get_valname(cptr, val,
-                       tmp.name, sizeof(tmp.name) - 1, &cnt);
-       tmp.name[cnt] = 0;
-
-       /* Don't bother with audioset, since this driver currently
-          always switches the audio whenever the video is
-          switched. */
-
-       /* Handling std is a tougher problem.  It doesn't make
-          sense in cases where a device might be multi-standard.
-          We could just copy out the current value for the
-          standard, but it can change over time.  For now just
-          leave it zero. */
-       *vi = tmp;
-       return 0;
-}
-
-static int pvr2_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       unsigned int idx;
-       struct pvr2_ctrl *cptr;
-       int val;
-       int ret;
-
-       cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
-       val = 0;
-       ret = pvr2_ctrl_get_value(cptr, &val);
-       *i = 0;
-       for (idx = 0; idx < fh->input_cnt; idx++) {
-               if (fh->input_map[idx] == val) {
-                       *i = idx;
-                       break;
-               }
-       }
-       return ret;
-}
-
-static int pvr2_s_input(struct file *file, void *priv, unsigned int inp)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-
-       if (inp >= fh->input_cnt)
-               return -EINVAL;
-       return pvr2_ctrl_set_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
-                       fh->input_map[inp]);
-}
-
-static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin)
-{
-       /* pkt: FIXME: We are returning one "fake" input here
-          which could very well be called "whatever_we_like".
-          This is for apps that want to see an audio input
-          just to feel comfortable, as well as to test if
-          it can do stereo or sth. There is actually no guarantee
-          that the actual audio input cannot change behind the app's
-          back, but most applications should not mind that either.
-
-          Hopefully, mplayer people will work with us on this (this
-          whole mess is to support mplayer pvr://), or Hans will come
-          up with a more standard way to say "we have inputs but we
-          don 't want you to change them independent of video" which
-          will sort this mess.
-        */
-
-       if (vin->index > 0)
-               return -EINVAL;
-       strncpy(vin->name, "PVRUSB2 Audio", 14);
-       vin->capability = V4L2_AUDCAP_STEREO;
-       return 0;
-}
-
-static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin)
-{
-       /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
-       vin->index = 0;
-       strncpy(vin->name, "PVRUSB2 Audio", 14);
-       vin->capability = V4L2_AUDCAP_STEREO;
-       return 0;
-}
-
-static int pvr2_s_audio(struct file *file, void *priv, struct v4l2_audio *vout)
-{
-       if (vout->index)
-               return -EINVAL;
-       return 0;
-}
-
-static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-
-       if (vt->index != 0)
-               return -EINVAL; /* Only answer for the 1st tuner */
-
-       pvr2_hdw_execute_tuner_poll(hdw);
-       return pvr2_hdw_get_tuner_status(hdw, vt);
-}
-
-static int pvr2_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-
-       if (vt->index != 0)
-               return -EINVAL;
-
-       return pvr2_ctrl_set_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE),
-                       vt->audmode);
-}
-
-int pvr2_s_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       unsigned long fv;
-       struct v4l2_tuner vt;
-       int cur_input;
-       struct pvr2_ctrl *ctrlp;
-       int ret;
-
-       ret = pvr2_hdw_get_tuner_status(hdw, &vt);
-       if (ret != 0)
-               return ret;
-       ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
-       ret = pvr2_ctrl_get_value(ctrlp, &cur_input);
-       if (ret != 0)
-               return ret;
-       if (vf->type == V4L2_TUNER_RADIO) {
-               if (cur_input != PVR2_CVAL_INPUT_RADIO)
-                       pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO);
-       } else {
-               if (cur_input == PVR2_CVAL_INPUT_RADIO)
-                       pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_TV);
-       }
-       fv = vf->frequency;
-       if (vt.capability & V4L2_TUNER_CAP_LOW)
-               fv = (fv * 125) / 2;
-       else
-               fv = fv * 62500;
-       return pvr2_ctrl_set_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
-}
-
-static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       int val = 0;
-       int cur_input;
-       struct v4l2_tuner vt;
-       int ret;
-
-       ret = pvr2_hdw_get_tuner_status(hdw, &vt);
-       if (ret != 0)
-               return ret;
-       ret = pvr2_ctrl_get_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY),
-                       &val);
-       if (ret != 0)
-               return ret;
-       pvr2_ctrl_get_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
-                       &cur_input);
-       if (cur_input == PVR2_CVAL_INPUT_RADIO)
-               vf->type = V4L2_TUNER_RADIO;
-       else
-               vf->type = V4L2_TUNER_ANALOG_TV;
-       if (vt.capability & V4L2_TUNER_CAP_LOW)
-               val = (val * 2) / 125;
-       else
-               val /= 62500;
-       vf->frequency = val;
-       return 0;
-}
-
-static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd)
-{
-       /* Only one format is supported : mpeg.*/
-       if (fd->index != 0)
-               return -EINVAL;
-
-       memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
-       return 0;
-}
-
-static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       int val;
-
-       memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format));
-       val = 0;
-       pvr2_ctrl_get_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES),
-                       &val);
-       vf->fmt.pix.width = val;
-       val = 0;
-       pvr2_ctrl_get_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES),
-                       &val);
-       vf->fmt.pix.height = val;
-       return 0;
-}
-
-static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       int lmin, lmax, ldef;
-       struct pvr2_ctrl *hcp, *vcp;
-       int h = vf->fmt.pix.height;
-       int w = vf->fmt.pix.width;
-
-       hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
-       vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
-
-       lmin = pvr2_ctrl_get_min(hcp);
-       lmax = pvr2_ctrl_get_max(hcp);
-       pvr2_ctrl_get_def(hcp, &ldef);
-       if (w == -1)
-               w = ldef;
-       else if (w < lmin)
-               w = lmin;
-       else if (w > lmax)
-               w = lmax;
-       lmin = pvr2_ctrl_get_min(vcp);
-       lmax = pvr2_ctrl_get_max(vcp);
-       pvr2_ctrl_get_def(vcp, &ldef);
-       if (h == -1)
-               h = ldef;
-       else if (h < lmin)
-               h = lmin;
-       else if (h > lmax)
-               h = lmax;
-
-       memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
-                       sizeof(struct v4l2_format));
-       vf->fmt.pix.width = w;
-       vf->fmt.pix.height = h;
-       return 0;
-}
-
-static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       struct pvr2_ctrl *hcp, *vcp;
-       int ret = pvr2_try_fmt_vid_cap(file, fh, vf);
-
-       if (ret)
-               return ret;
-       hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
-       vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
-       pvr2_ctrl_set_value(hcp, vf->fmt.pix.width);
-       pvr2_ctrl_set_value(vcp, vf->fmt.pix.height);
-       return 0;
-}
-
-static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       struct pvr2_v4l2_dev *pdi = fh->pdi;
-       int ret;
-
-       if (!fh->pdi->stream) {
-               /* No stream defined for this node.  This means
-                  that we're not currently allowed to stream from
-                  this node. */
-               return -EPERM;
-       }
-       ret = pvr2_hdw_set_stream_type(hdw, pdi->config);
-       if (ret < 0)
-               return ret;
-       return pvr2_hdw_set_streaming(hdw, !0);
-}
-
-static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-
-       if (!fh->pdi->stream) {
-               /* No stream defined for this node.  This means
-                  that we're not currently allowed to stream from
-                  this node. */
-               return -EPERM;
-       }
-       return pvr2_hdw_set_streaming(hdw, 0);
-}
-
-static int pvr2_queryctrl(struct file *file, void *priv,
-               struct v4l2_queryctrl *vc)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       struct pvr2_ctrl *cptr;
-       int val;
-
-       if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
-               cptr = pvr2_hdw_get_ctrl_nextv4l(
-                               hdw, (vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
-               if (cptr)
-                       vc->id = pvr2_ctrl_get_v4lid(cptr);
-       } else {
-               cptr = pvr2_hdw_get_ctrl_v4l(hdw, vc->id);
-       }
-       if (!cptr) {
-               pvr2_trace(PVR2_TRACE_V4LIOCTL,
-                               "QUERYCTRL id=0x%x not implemented here",
-                               vc->id);
-               return -EINVAL;
-       }
-
-       pvr2_trace(PVR2_TRACE_V4LIOCTL,
-                       "QUERYCTRL id=0x%x mapping name=%s (%s)",
-                       vc->id, pvr2_ctrl_get_name(cptr),
-                       pvr2_ctrl_get_desc(cptr));
-       strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
-       vc->flags = pvr2_ctrl_get_v4lflags(cptr);
-       pvr2_ctrl_get_def(cptr, &val);
-       vc->default_value = val;
-       switch (pvr2_ctrl_get_type(cptr)) {
-       case pvr2_ctl_enum:
-               vc->type = V4L2_CTRL_TYPE_MENU;
-               vc->minimum = 0;
-               vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
-               vc->step = 1;
-               break;
-       case pvr2_ctl_bool:
-               vc->type = V4L2_CTRL_TYPE_BOOLEAN;
-               vc->minimum = 0;
-               vc->maximum = 1;
-               vc->step = 1;
-               break;
-       case pvr2_ctl_int:
-               vc->type = V4L2_CTRL_TYPE_INTEGER;
-               vc->minimum = pvr2_ctrl_get_min(cptr);
-               vc->maximum = pvr2_ctrl_get_max(cptr);
-               vc->step = 1;
-               break;
-       default:
-               pvr2_trace(PVR2_TRACE_V4LIOCTL,
-                               "QUERYCTRL id=0x%x name=%s not mappable",
-                               vc->id, pvr2_ctrl_get_name(cptr));
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       unsigned int cnt = 0;
-       int ret;
-
-       ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw, vm->id),
-                       vm->index,
-                       vm->name, sizeof(vm->name) - 1,
-                       &cnt);
-       vm->name[cnt] = 0;
-       return ret;
-}
-
-static int pvr2_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       int val = 0;
-       int ret;
-
-       ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
-                       &val);
-       vc->value = val;
-       return ret;
-}
-
-static int pvr2_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-
-       return pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
-                       vc->value);
-}
-
-static int pvr2_g_ext_ctrls(struct file *file, void *priv,
-                                       struct v4l2_ext_controls *ctls)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       struct v4l2_ext_control *ctrl;
-       unsigned int idx;
-       int val;
-       int ret;
-
-       ret = 0;
-       for (idx = 0; idx < ctls->count; idx++) {
-               ctrl = ctls->controls + idx;
-               ret = pvr2_ctrl_get_value(
-                               pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id), &val);
-               if (ret) {
-                       ctls->error_idx = idx;
-                       return ret;
-               }
-               /* Ensure that if read as a 64 bit value, the user
-                  will still get a hopefully sane value */
-               ctrl->value64 = 0;
-               ctrl->value = val;
-       }
-       return 0;
-}
-
-static int pvr2_s_ext_ctrls(struct file *file, void *priv,
-               struct v4l2_ext_controls *ctls)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       struct v4l2_ext_control *ctrl;
-       unsigned int idx;
-       int ret;
-
-       ret = 0;
-       for (idx = 0; idx < ctls->count; idx++) {
-               ctrl = ctls->controls + idx;
-               ret = pvr2_ctrl_set_value(
-                               pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id),
-                               ctrl->value);
-               if (ret) {
-                       ctls->error_idx = idx;
-                       return ret;
-               }
-       }
-       return 0;
-}
-
-static int pvr2_try_ext_ctrls(struct file *file, void *priv,
-               struct v4l2_ext_controls *ctls)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       struct v4l2_ext_control *ctrl;
-       struct pvr2_ctrl *pctl;
-       unsigned int idx;
-
-       /* For the moment just validate that the requested control
-          actually exists. */
-       for (idx = 0; idx < ctls->count; idx++) {
-               ctrl = ctls->controls + idx;
-               pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
-               if (!pctl) {
-                       ctls->error_idx = idx;
-                       return -EINVAL;
-               }
-       }
-       return 0;
-}
-
-static int pvr2_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       int ret;
-
-       if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       ret = pvr2_hdw_get_cropcap(hdw, cap);
-       cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
-       return ret;
-}
-
-static int pvr2_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       int val = 0;
-       int ret;
-
-       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       ret = pvr2_ctrl_get_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
-       if (ret != 0)
-               return -EINVAL;
-       crop->c.left = val;
-       ret = pvr2_ctrl_get_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
-       if (ret != 0)
-               return -EINVAL;
-       crop->c.top = val;
-       ret = pvr2_ctrl_get_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
-       if (ret != 0)
-               return -EINVAL;
-       crop->c.width = val;
-       ret = pvr2_ctrl_get_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
-       if (ret != 0)
-               return -EINVAL;
-       crop->c.height = val;
-       return 0;
-}
-
-static int pvr2_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       int ret;
-
-       if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       ret = pvr2_ctrl_set_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
-                       crop->c.left);
-       if (ret != 0)
-               return -EINVAL;
-       ret = pvr2_ctrl_set_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
-                       crop->c.top);
-       if (ret != 0)
-               return -EINVAL;
-       ret = pvr2_ctrl_set_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
-                       crop->c.width);
-       if (ret != 0)
-               return -EINVAL;
-       ret = pvr2_ctrl_set_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
-                       crop->c.height);
-       if (ret != 0)
-               return -EINVAL;
-       return 0;
-}
-
-static int pvr2_log_status(struct file *file, void *priv)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-
-       pvr2_hdw_trigger_module_log(hdw);
-       return 0;
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int pvr2_g_register(struct file *file, void *priv, struct v4l2_dbg_register *req)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       u64 val;
-       int ret;
-
-       ret = pvr2_hdw_register_access(
-                       hdw, &req->match, req->reg,
-                       0, &val);
-       req->val = val;
-       return ret;
-}
-
-static int pvr2_s_register(struct file *file, void *priv, struct v4l2_dbg_register *req)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       u64 val;
-       int ret;
-
-       val = req->val;
-       ret = pvr2_hdw_register_access(
-                       hdw, &req->match, req->reg,
-                       1, &val);
-       return ret;
-}
-#endif
-
-static const struct v4l2_ioctl_ops pvr2_ioctl_ops = {
-       .vidioc_querycap                    = pvr2_querycap,
-       .vidioc_g_priority                  = pvr2_g_priority,
-       .vidioc_s_priority                  = pvr2_s_priority,
-       .vidioc_s_audio                     = pvr2_s_audio,
-       .vidioc_g_audio                     = pvr2_g_audio,
-       .vidioc_enumaudio                   = pvr2_enumaudio,
-       .vidioc_enum_input                  = pvr2_enum_input,
-       .vidioc_cropcap                     = pvr2_cropcap,
-       .vidioc_s_crop                      = pvr2_s_crop,
-       .vidioc_g_crop                      = pvr2_g_crop,
-       .vidioc_g_input                     = pvr2_g_input,
-       .vidioc_s_input                     = pvr2_s_input,
-       .vidioc_g_frequency                 = pvr2_g_frequency,
-       .vidioc_s_frequency                 = pvr2_s_frequency,
-       .vidioc_s_tuner                     = pvr2_s_tuner,
-       .vidioc_g_tuner                     = pvr2_g_tuner,
-       .vidioc_g_std                       = pvr2_g_std,
-       .vidioc_s_std                       = pvr2_s_std,
-       .vidioc_querystd                    = pvr2_querystd,
-       .vidioc_log_status                  = pvr2_log_status,
-       .vidioc_enum_fmt_vid_cap            = pvr2_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap               = pvr2_g_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap               = pvr2_s_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap             = pvr2_try_fmt_vid_cap,
-       .vidioc_streamon                    = pvr2_streamon,
-       .vidioc_streamoff                   = pvr2_streamoff,
-       .vidioc_queryctrl                   = pvr2_queryctrl,
-       .vidioc_querymenu                   = pvr2_querymenu,
-       .vidioc_g_ctrl                      = pvr2_g_ctrl,
-       .vidioc_s_ctrl                      = pvr2_s_ctrl,
-       .vidioc_g_ext_ctrls                 = pvr2_g_ext_ctrls,
-       .vidioc_s_ext_ctrls                 = pvr2_s_ext_ctrls,
-       .vidioc_try_ext_ctrls               = pvr2_try_ext_ctrls,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register                  = pvr2_g_register,
-       .vidioc_s_register                  = pvr2_s_register,
-#endif
-};
-
-static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
-{
-       struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
-       enum pvr2_config cfg = dip->config;
-       char msg[80];
-       unsigned int mcnt;
-
-       /* Construct the unregistration message *before* we actually
-          perform the unregistration step.  By doing it this way we don't
-          have to worry about potentially touching deleted resources. */
-       mcnt = scnprintf(msg, sizeof(msg) - 1,
-                        "pvrusb2: unregistered device %s [%s]",
-                        video_device_node_name(&dip->devbase),
-                        pvr2_config_get_name(cfg));
-       msg[mcnt] = 0;
-
-       pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
-
-       /* Paranoia */
-       dip->v4lp = NULL;
-       dip->stream = NULL;
-
-       /* Actual deallocation happens later when all internal references
-          are gone. */
-       video_unregister_device(&dip->devbase);
-
-       printk(KERN_INFO "%s\n", msg);
-
-}
-
-
-static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
-{
-       if (!dip) return;
-       if (!dip->devbase.parent) return;
-       dip->devbase.parent = NULL;
-       device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
-}
-
-
-static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
-{
-       if (vp->dev_video) {
-               pvr2_v4l2_dev_destroy(vp->dev_video);
-               vp->dev_video = NULL;
-       }
-       if (vp->dev_radio) {
-               pvr2_v4l2_dev_destroy(vp->dev_radio);
-               vp->dev_radio = NULL;
-       }
-
-       pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
-       pvr2_channel_done(&vp->channel);
-       kfree(vp);
-}
-
-
-static void pvr2_video_device_release(struct video_device *vdev)
-{
-       struct pvr2_v4l2_dev *dev;
-       dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
-       kfree(dev);
-}
-
-
-static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
-{
-       struct pvr2_v4l2 *vp;
-       vp = container_of(chp,struct pvr2_v4l2,channel);
-       if (!vp->channel.mc_head->disconnect_flag) return;
-       pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
-       pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
-       if (vp->vfirst) return;
-       pvr2_v4l2_destroy_no_lock(vp);
-}
-
-
-static long pvr2_v4l2_ioctl(struct file *file,
-                          unsigned int cmd, unsigned long arg)
-{
-
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       struct pvr2_v4l2 *vp = fh->vhead;
-       struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-       long ret = -EINVAL;
-
-       if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL)
-               v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
-
-       if (!pvr2_hdw_dev_ok(hdw)) {
-               pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                          "ioctl failed - bad or no context");
-               return -EFAULT;
-       }
-
-       /* check priority */
-       switch (cmd) {
-       case VIDIOC_S_CTRL:
-       case VIDIOC_S_STD:
-       case VIDIOC_S_INPUT:
-       case VIDIOC_S_TUNER:
-       case VIDIOC_S_FREQUENCY:
-               ret = v4l2_prio_check(&vp->prio, fh->prio);
-               if (ret)
-                       return ret;
-       }
-
-       ret = video_ioctl2(file, cmd, arg);
-
-       pvr2_hdw_commit_ctl(hdw);
-
-       if (ret < 0) {
-               if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
-                       pvr2_trace(PVR2_TRACE_V4LIOCTL,
-                                  "pvr2_v4l2_do_ioctl failure, ret=%ld", ret);
-               } else {
-                       if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
-                               pvr2_trace(PVR2_TRACE_V4LIOCTL,
-                                          "pvr2_v4l2_do_ioctl failure, ret=%ld"
-                                          " command was:", ret);
-                               v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw),
-                                               cmd);
-                       }
-               }
-       } else {
-               pvr2_trace(PVR2_TRACE_V4LIOCTL,
-                          "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
-                          ret, ret);
-       }
-       return ret;
-
-}
-
-
-static int pvr2_v4l2_release(struct file *file)
-{
-       struct pvr2_v4l2_fh *fhp = file->private_data;
-       struct pvr2_v4l2 *vp = fhp->vhead;
-       struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
-
-       pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
-
-       if (fhp->rhp) {
-               struct pvr2_stream *sp;
-               pvr2_hdw_set_streaming(hdw,0);
-               sp = pvr2_ioread_get_stream(fhp->rhp);
-               if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
-               pvr2_ioread_destroy(fhp->rhp);
-               fhp->rhp = NULL;
-       }
-
-       v4l2_prio_close(&vp->prio, fhp->prio);
-       file->private_data = NULL;
-
-       if (fhp->vnext) {
-               fhp->vnext->vprev = fhp->vprev;
-       } else {
-               vp->vlast = fhp->vprev;
-       }
-       if (fhp->vprev) {
-               fhp->vprev->vnext = fhp->vnext;
-       } else {
-               vp->vfirst = fhp->vnext;
-       }
-       fhp->vnext = NULL;
-       fhp->vprev = NULL;
-       fhp->vhead = NULL;
-       pvr2_channel_done(&fhp->channel);
-       pvr2_trace(PVR2_TRACE_STRUCT,
-                  "Destroying pvr_v4l2_fh id=%p",fhp);
-       if (fhp->input_map) {
-               kfree(fhp->input_map);
-               fhp->input_map = NULL;
-       }
-       kfree(fhp);
-       if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
-               pvr2_v4l2_destroy_no_lock(vp);
-       }
-       return 0;
-}
-
-
-static int pvr2_v4l2_open(struct file *file)
-{
-       struct pvr2_v4l2_dev *dip; /* Our own context pointer */
-       struct pvr2_v4l2_fh *fhp;
-       struct pvr2_v4l2 *vp;
-       struct pvr2_hdw *hdw;
-       unsigned int input_mask = 0;
-       unsigned int input_cnt,idx;
-       int ret = 0;
-
-       dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
-
-       vp = dip->v4lp;
-       hdw = vp->channel.hdw;
-
-       pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
-
-       if (!pvr2_hdw_dev_ok(hdw)) {
-               pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
-                          "pvr2_v4l2_open: hardware not ready");
-               return -EIO;
-       }
-
-       fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
-       if (!fhp) {
-               return -ENOMEM;
-       }
-
-       init_waitqueue_head(&fhp->wait_data);
-       fhp->pdi = dip;
-
-       pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
-       pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
-
-       if (dip->v4l_type == VFL_TYPE_RADIO) {
-               /* Opening device as a radio, legal input selection subset
-                  is just the radio. */
-               input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
-       } else {
-               /* Opening the main V4L device, legal input selection
-                  subset includes all analog inputs. */
-               input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
-                             (1 << PVR2_CVAL_INPUT_TV) |
-                             (1 << PVR2_CVAL_INPUT_COMPOSITE) |
-                             (1 << PVR2_CVAL_INPUT_SVIDEO));
-       }
-       ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
-       if (ret) {
-               pvr2_channel_done(&fhp->channel);
-               pvr2_trace(PVR2_TRACE_STRUCT,
-                          "Destroying pvr_v4l2_fh id=%p (input mask error)",
-                          fhp);
-
-               kfree(fhp);
-               return ret;
-       }
-
-       input_mask &= pvr2_hdw_get_input_available(hdw);
-       input_cnt = 0;
-       for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
-               if (input_mask & (1 << idx)) input_cnt++;
-       }
-       fhp->input_cnt = input_cnt;
-       fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
-       if (!fhp->input_map) {
-               pvr2_channel_done(&fhp->channel);
-               pvr2_trace(PVR2_TRACE_STRUCT,
-                          "Destroying pvr_v4l2_fh id=%p (input map failure)",
-                          fhp);
-               kfree(fhp);
-               return -ENOMEM;
-       }
-       input_cnt = 0;
-       for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
-               if (!(input_mask & (1 << idx))) continue;
-               fhp->input_map[input_cnt++] = idx;
-       }
-
-       fhp->vnext = NULL;
-       fhp->vprev = vp->vlast;
-       if (vp->vlast) {
-               vp->vlast->vnext = fhp;
-       } else {
-               vp->vfirst = fhp;
-       }
-       vp->vlast = fhp;
-       fhp->vhead = vp;
-
-       fhp->file = file;
-       file->private_data = fhp;
-       v4l2_prio_open(&vp->prio, &fhp->prio);
-
-       fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
-
-       return 0;
-}
-
-
-static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
-{
-       wake_up(&fhp->wait_data);
-}
-
-static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
-{
-       int ret;
-       struct pvr2_stream *sp;
-       struct pvr2_hdw *hdw;
-       if (fh->rhp) return 0;
-
-       if (!fh->pdi->stream) {
-               /* No stream defined for this node.  This means that we're
-                  not currently allowed to stream from this node. */
-               return -EPERM;
-       }
-
-       /* First read() attempt.  Try to claim the stream and start
-          it... */
-       if ((ret = pvr2_channel_claim_stream(&fh->channel,
-                                            fh->pdi->stream)) != 0) {
-               /* Someone else must already have it */
-               return ret;
-       }
-
-       fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
-       if (!fh->rhp) {
-               pvr2_channel_claim_stream(&fh->channel,NULL);
-               return -ENOMEM;
-       }
-
-       hdw = fh->channel.mc_head->hdw;
-       sp = fh->pdi->stream->stream;
-       pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
-       pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
-       if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
-       return pvr2_ioread_set_enabled(fh->rhp,!0);
-}
-
-
-static ssize_t pvr2_v4l2_read(struct file *file,
-                             char __user *buff, size_t count, loff_t *ppos)
-{
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       int ret;
-
-       if (fh->fw_mode_flag) {
-               struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
-               char *tbuf;
-               int c1,c2;
-               int tcnt = 0;
-               unsigned int offs = *ppos;
-
-               tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
-               if (!tbuf) return -ENOMEM;
-
-               while (count) {
-                       c1 = count;
-                       if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
-                       c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
-                       if (c2 < 0) {
-                               tcnt = c2;
-                               break;
-                       }
-                       if (!c2) break;
-                       if (copy_to_user(buff,tbuf,c2)) {
-                               tcnt = -EFAULT;
-                               break;
-                       }
-                       offs += c2;
-                       tcnt += c2;
-                       buff += c2;
-                       count -= c2;
-                       *ppos += c2;
-               }
-               kfree(tbuf);
-               return tcnt;
-       }
-
-       if (!fh->rhp) {
-               ret = pvr2_v4l2_iosetup(fh);
-               if (ret) {
-                       return ret;
-               }
-       }
-
-       for (;;) {
-               ret = pvr2_ioread_read(fh->rhp,buff,count);
-               if (ret >= 0) break;
-               if (ret != -EAGAIN) break;
-               if (file->f_flags & O_NONBLOCK) break;
-               /* Doing blocking I/O.  Wait here. */
-               ret = wait_event_interruptible(
-                       fh->wait_data,
-                       pvr2_ioread_avail(fh->rhp) >= 0);
-               if (ret < 0) break;
-       }
-
-       return ret;
-}
-
-
-static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
-{
-       unsigned int mask = 0;
-       struct pvr2_v4l2_fh *fh = file->private_data;
-       int ret;
-
-       if (fh->fw_mode_flag) {
-               mask |= POLLIN | POLLRDNORM;
-               return mask;
-       }
-
-       if (!fh->rhp) {
-               ret = pvr2_v4l2_iosetup(fh);
-               if (ret) return POLLERR;
-       }
-
-       poll_wait(file,&fh->wait_data,wait);
-
-       if (pvr2_ioread_avail(fh->rhp) >= 0) {
-               mask |= POLLIN | POLLRDNORM;
-       }
-
-       return mask;
-}
-
-
-static const struct v4l2_file_operations vdev_fops = {
-       .owner      = THIS_MODULE,
-       .open       = pvr2_v4l2_open,
-       .release    = pvr2_v4l2_release,
-       .read       = pvr2_v4l2_read,
-       .ioctl      = pvr2_v4l2_ioctl,
-       .poll       = pvr2_v4l2_poll,
-};
-
-
-static struct video_device vdev_template = {
-       .fops       = &vdev_fops,
-};
-
-
-static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
-                              struct pvr2_v4l2 *vp,
-                              int v4l_type)
-{
-       struct usb_device *usbdev;
-       int mindevnum;
-       int unit_number;
-       struct pvr2_hdw *hdw;
-       int *nr_ptr = NULL;
-       dip->v4lp = vp;
-
-       hdw = vp->channel.mc_head->hdw;
-       usbdev = pvr2_hdw_get_dev(hdw);
-       dip->v4l_type = v4l_type;
-       switch (v4l_type) {
-       case VFL_TYPE_GRABBER:
-               dip->stream = &vp->channel.mc_head->video_stream;
-               dip->config = pvr2_config_mpeg;
-               dip->minor_type = pvr2_v4l_type_video;
-               nr_ptr = video_nr;
-               if (!dip->stream) {
-                       pr_err(KBUILD_MODNAME
-                               ": Failed to set up pvrusb2 v4l video dev"
-                               " due to missing stream instance\n");
-                       return;
-               }
-               break;
-       case VFL_TYPE_VBI:
-               dip->config = pvr2_config_vbi;
-               dip->minor_type = pvr2_v4l_type_vbi;
-               nr_ptr = vbi_nr;
-               break;
-       case VFL_TYPE_RADIO:
-               dip->stream = &vp->channel.mc_head->video_stream;
-               dip->config = pvr2_config_mpeg;
-               dip->minor_type = pvr2_v4l_type_radio;
-               nr_ptr = radio_nr;
-               break;
-       default:
-               /* Bail out (this should be impossible) */
-               pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
-                   " due to unrecognized config\n");
-               return;
-       }
-
-       memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
-       dip->devbase.release = pvr2_video_device_release;
-       dip->devbase.ioctl_ops = &pvr2_ioctl_ops;
-       {
-               int val;
-               pvr2_ctrl_get_value(
-                       pvr2_hdw_get_ctrl_by_id(hdw,
-                                               PVR2_CID_STDAVAIL), &val);
-               dip->devbase.tvnorms = (v4l2_std_id)val;
-       }
-
-       mindevnum = -1;
-       unit_number = pvr2_hdw_get_unit_number(hdw);
-       if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
-               mindevnum = nr_ptr[unit_number];
-       }
-       dip->devbase.parent = &usbdev->dev;
-       if ((video_register_device(&dip->devbase,
-                                  dip->v4l_type, mindevnum) < 0) &&
-           (video_register_device(&dip->devbase,
-                                  dip->v4l_type, -1) < 0)) {
-               pr_err(KBUILD_MODNAME
-                       ": Failed to register pvrusb2 v4l device\n");
-       }
-
-       printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
-              video_device_node_name(&dip->devbase),
-              pvr2_config_get_name(dip->config));
-
-       pvr2_hdw_v4l_store_minor_number(hdw,
-                                       dip->minor_type,dip->devbase.minor);
-}
-
-
-struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
-{
-       struct pvr2_v4l2 *vp;
-
-       vp = kzalloc(sizeof(*vp),GFP_KERNEL);
-       if (!vp) return vp;
-       pvr2_channel_init(&vp->channel,mnp);
-       pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
-
-       vp->channel.check_func = pvr2_v4l2_internal_check;
-
-       /* register streams */
-       vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
-       if (!vp->dev_video) goto fail;
-       pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
-       if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
-           (1 << PVR2_CVAL_INPUT_RADIO)) {
-               vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
-               if (!vp->dev_radio) goto fail;
-               pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
-       }
-
-       return vp;
- fail:
-       pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
-       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/video/pvrusb2/pvrusb2-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-v4l2.h
deleted file mode 100644 (file)
index 34c011a..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifndef __PVRUSB2_V4L2_H
-#define __PVRUSB2_V4L2_H
-
-#include "pvrusb2-context.h"
-
-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/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
deleted file mode 100644 (file)
index 2e205c9..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-/*
-
-   This source file is specifically designed to interface with the
-   saa711x support that is available in the v4l available starting
-   with linux 2.6.15.
-
-*/
-
-#include "pvrusb2-video-v4l.h"
-
-
-
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/saa7115.h>
-#include <linux/errno.h>
-
-struct routing_scheme {
-       const int *def;
-       unsigned int cnt;
-};
-
-
-static const int routing_scheme0[] = {
-       [PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4,
-       /* In radio mode, we mute the video, but point at one
-          spot just to stay consistent */
-       [PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5,
-       [PVR2_CVAL_INPUT_COMPOSITE] = SAA7115_COMPOSITE5,
-       [PVR2_CVAL_INPUT_SVIDEO] =  SAA7115_SVIDEO2,
-};
-
-static const struct routing_scheme routing_def0 = {
-       .def = routing_scheme0,
-       .cnt = ARRAY_SIZE(routing_scheme0),
-};
-
-static const int routing_scheme1[] = {
-       [PVR2_CVAL_INPUT_TV] = SAA7115_COMPOSITE4,
-       [PVR2_CVAL_INPUT_RADIO] = SAA7115_COMPOSITE5,
-       [PVR2_CVAL_INPUT_COMPOSITE] = SAA7115_COMPOSITE3,
-       [PVR2_CVAL_INPUT_SVIDEO] =  SAA7115_SVIDEO2, /* or SVIDEO0, it seems */
-};
-
-static const struct routing_scheme routing_def1 = {
-       .def = routing_scheme1,
-       .cnt = ARRAY_SIZE(routing_scheme1),
-};
-
-static const struct routing_scheme *routing_schemes[] = {
-       [PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
-       [PVR2_ROUTING_SCHEME_ONAIR] = &routing_def1,
-};
-
-void pvr2_saa7115_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
-{
-       if (hdw->input_dirty || hdw->force_dirty) {
-               const struct routing_scheme *sp;
-               unsigned int sid = hdw->hdw_desc->signal_routing_scheme;
-               u32 input;
-
-               pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_input(%d)",
-                          hdw->input_val);
-
-               sp = (sid < ARRAY_SIZE(routing_schemes)) ?
-                       routing_schemes[sid] : NULL;
-               if ((sp == NULL) ||
-                   (hdw->input_val < 0) ||
-                   (hdw->input_val >= sp->cnt)) {
-                       pvr2_trace(PVR2_TRACE_ERROR_LEGS,
-                                  "*** WARNING *** subdev v4l2 set_input:"
-                                  " Invalid routing scheme (%u)"
-                                  " and/or input (%d)",
-                                  sid, hdw->input_val);
-                       return;
-               }
-               input = sp->def[hdw->input_val];
-               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/video/pvrusb2/pvrusb2-video-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
deleted file mode 100644 (file)
index 3b0bd5d..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef __PVRUSB2_VIDEO_V4L_H
-#define __PVRUSB2_VIDEO_V4L_H
-
-/*
-
-   This module connects the pvrusb2 driver to the I2C chip level
-   driver which handles device video processing.  This interface is
-   used internally by the driver; higher level code should only
-   interact through the interface provided by pvrusb2-hdw.h.
-
-*/
-
-
-#include "pvrusb2-hdw-internal.h"
-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/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
deleted file mode 100644 (file)
index 3ac8d75..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-/*
-
-   This source file is specifically designed to interface with the
-   wm8775.
-
-*/
-
-#include "pvrusb2-wm8775.h"
-
-
-#include "pvrusb2-hdw-internal.h"
-#include "pvrusb2-debug.h"
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <linux/errno.h>
-
-void pvr2_wm8775_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
-{
-       if (hdw->input_dirty || hdw->force_dirty) {
-               u32 input;
-
-               switch (hdw->input_val) {
-               case PVR2_CVAL_INPUT_RADIO:
-                       input = 1;
-                       break;
-               default:
-                       /* All other cases just use the second input */
-                       input = 2;
-                       break;
-               }
-               pvr2_trace(PVR2_TRACE_CHIPS, "subdev wm8775"
-                          " set_input(val=%d route=0x%x)",
-                          hdw->input_val, input);
-
-               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/video/pvrusb2/pvrusb2-wm8775.h b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
deleted file mode 100644 (file)
index 0577bc7..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef __PVRUSB2_WM8775_H
-#define __PVRUSB2_WM8775_H
-
-/*
-
-   This module connects the pvrusb2 driver to the I2C chip level
-   driver which performs analog -> digital audio conversion for
-   external audio inputs.  This interface is used internally by the
-   driver; higher level code should only interact through the
-   interface provided by pvrusb2-hdw.h.
-
-*/
-
-
-
-#include "pvrusb2-hdw-internal.h"
-
-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/video/pvrusb2/pvrusb2.h b/drivers/media/video/pvrusb2/pvrusb2.h
deleted file mode 100644 (file)
index 240de9b..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- *
- *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
- *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
- *
- *  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
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-
-#ifndef __PVRUSB2_H
-#define __PVRUSB2_H
-
-/* Maximum number of pvrusb2 instances we can track at once.  You
-   might want to increase this - however the driver operation will not
-   be impaired if it is too small.  Instead additional units just
-   won't have an ID assigned and it might not be possible to specify
-   module parameters for those extra units. */
-#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/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig
deleted file mode 100644 (file)
index d63d0a8..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-config USB_PWC
-       tristate "USB Philips Cameras"
-       depends on VIDEO_V4L2
-       select VIDEOBUF2_VMALLOC
-       ---help---
-         Say Y or M here if you want to use one of these Philips & OEM
-         webcams:
-          * Philips PCA645, PCA646
-          * Philips PCVC675, PCVC680, PCVC690
-          * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
-          * Philips SPC900NC
-          * Askey VC010
-          * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
-            and 'Orbit'/'Sphere'
-          * Samsung MPC-C10, MPC-C30
-          * Creative Webcam 5, Pro Ex
-          * SOTEC Afina Eye
-          * Visionite VCS-UC300, VCS-UM100
-
-         The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
-         and never will be, but the 665 and 720/20 are supported by other
-         drivers.
-
-         Some newer logitech webcams are not handled by this driver but by the
-         Usb Video Class driver (linux-uvc).
-
-         The built-in microphone is enabled by selecting USB Audio support.
-
-         To compile this driver as a module, choose M here: the
-         module will be called pwc.
-
-config USB_PWC_DEBUG
-       bool "USB Philips Cameras verbose debug"
-       depends on USB_PWC
-       help
-         Say Y here in order to have the pwc driver generate verbose debugging
-         messages.
-         A special module options 'trace' is used to control the verbosity.
-
-config USB_PWC_INPUT_EVDEV
-       bool "USB Philips Cameras input events device support"
-       default y
-       depends on USB_PWC && (USB_PWC=INPUT || INPUT=y)
-       ---help---
-         This option makes USB Philips cameras register the snapshot button as
-         an input device to report button events.
-
-         If you are in doubt, say Y.
diff --git a/drivers/media/video/pwc/Makefile b/drivers/media/video/pwc/Makefile
deleted file mode 100644 (file)
index f5c8ec2..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-pwc-objs       := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o
-pwc-objs       += pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o
-
-obj-$(CONFIG_USB_PWC) += pwc.o
diff --git a/drivers/media/video/pwc/philips.txt b/drivers/media/video/pwc/philips.txt
deleted file mode 100644 (file)
index d38dd79..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-This file contains some additional information for the Philips and OEM webcams.
-E-mail: webcam@smcc.demon.nl                        Last updated: 2004-01-19
-Site: http://www.smcc.demon.nl/webcam/
-
-As of this moment, the following cameras are supported:
- * Philips PCA645
- * Philips PCA646
- * Philips PCVC675
- * Philips PCVC680
- * Philips PCVC690
- * Philips PCVC720/40
- * Philips PCVC730
- * Philips PCVC740
- * Philips PCVC750
- * Askey VC010
- * Creative Labs Webcam 5
- * Creative Labs Webcam Pro Ex
- * Logitech QuickCam 3000 Pro
- * Logitech QuickCam 4000 Pro
- * Logitech QuickCam Notebook Pro
- * Logitech QuickCam Zoom
- * Logitech QuickCam Orbit
- * Logitech QuickCam Sphere
- * Samsung MPC-C10
- * Samsung MPC-C30
- * Sotec Afina Eye
- * AME CU-001
- * Visionite VCS-UM100
- * Visionite VCS-UC300
-
-The main webpage for the Philips driver is at the address above. It contains
-a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin
-contains decompression routines that allow you to use higher image sizes and
-framerates; in addition the webcam uses less bandwidth on the USB bus (handy
-if you want to run more than 1 camera simultaneously). These routines fall
-under a NDA, and may therefore not be distributed as source; however, its use
-is completely optional.
-
-You can build this code either into your kernel, or as a module. I recommend
-the latter, since it makes troubleshooting a lot easier. The built-in
-microphone is supported through the USB Audio class.
-
-When you load the module you can set some default settings for the
-camera; some programs depend on a particular image-size or -format and
-don't know how to set it properly in the driver. The options are:
-
-size
-   Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
-   'vga', for an image size of resp. 128x96, 160x120, 176x144,
-   320x240, 352x288 and 640x480 (of course, only for those cameras that
-   support these resolutions).
-
-fps
-   Specifies the desired framerate. Is an integer in the range of 4-30.
-
-fbufs
-   This parameter specifies the number of internal buffers to use for storing
-   frames from the cam. This will help if the process that reads images from
-   the cam is a bit slow or momentarily busy. However, on slow machines it
-   only introduces lag, so choose carefully. The default is 3, which is
-   reasonable. You can set it between 2 and 5.
-
-mbufs
-   This is an integer between 1 and 10. It will tell the module the number of
-   buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
-   The default is 2, which is adequate for most applications (double
-   buffering).
-
-   Should you experience a lot of 'Dumping frame...' messages during
-   grabbing with a tool that uses mmap(), you might want to increase if.
-   However, it doesn't really buffer images, it just gives you a bit more
-   slack when your program is behind. But you need a multi-threaded or
-   forked program to really take advantage of these buffers.
-
-   The absolute maximum is 10, but don't set it too high!  Every buffer takes
-   up 460 KB of RAM, so unless you have a lot of memory setting this to
-   something more than 4 is an absolute waste.  This memory is only
-   allocated during open(), so nothing is wasted when the camera is not in
-   use.
-
-power_save
-   When power_save is enabled (set to 1), the module will try to shut down
-   the cam on close() and re-activate on open(). This will save power and
-   turn off the LED. Not all cameras support this though (the 645 and 646
-   don't have power saving at all), and some models don't work either (they
-   will shut down, but never wake up). Consider this experimental. By
-   default this option is disabled.
-
-compression (only useful with the plugin)
-   With this option you can control the compression factor that the camera
-   uses to squeeze the image through the USB bus. You can set the
-   parameter between 0 and 3:
-     0 = prefer uncompressed images; if the requested mode is not available
-        in an uncompressed format, the driver will silently switch to low
-        compression.
-     1 = low compression.
-     2 = medium compression.
-     3 = high compression.
-
-   High compression takes less bandwidth of course, but it could also
-   introduce some unwanted artefacts. The default is 2, medium compression.
-   See the FAQ on the website for an overview of which modes require
-   compression.
-
-   The compression parameter does not apply to the 645 and 646 cameras
-   and OEM models derived from those (only a few). Most cams honour this
-   parameter.
-
-leds
-   This settings takes 2 integers, that define the on/off time for the LED
-   (in milliseconds). One of the interesting things that you can do with
-   this is let the LED blink while the camera is in use. This:
-
-     leds=500,500
-
-   will blink the LED once every second. But with:
-
-     leds=0,0
-
-   the LED never goes on, making it suitable for silent surveillance.
-
-   By default the camera's LED is on solid while in use, and turned off
-   when the camera is not used anymore.
-
-   This parameter works only with the ToUCam range of cameras (720, 730, 740,
-   750) and OEMs. For other cameras this command is silently ignored, and
-   the LED cannot be controlled.
-
-   Finally: this parameters does not take effect UNTIL the first time you
-   open the camera device. Until then, the LED remains on.
-
-dev_hint
-   A long standing problem with USB devices is their dynamic nature: you
-   never know what device a camera gets assigned; it depends on module load
-   order, the hub configuration, the order in which devices are plugged in,
-   and the phase of the moon (i.e. it can be random). With this option you
-   can give the driver a hint as to what video device node (/dev/videoX) it
-   should use with a specific camera. This is also handy if you have two
-   cameras of the same model.
-
-   A camera is specified by its type (the number from the camera model,
-   like PCA645, PCVC750VC, etc) and optionally the serial number (visible
-   in /proc/bus/usb/devices). A hint consists of a string with the following
-   format:
-
-      [type[.serialnumber]:]node
-
-   The square brackets mean that both the type and the serialnumber are
-   optional, but a serialnumber cannot be specified without a type (which
-   would be rather pointless). The serialnumber is separated from the type
-   by a '.'; the node number by a ':'.
-
-   This somewhat cryptic syntax is best explained by a few examples:
-
-     dev_hint=3,5              The first detected cam gets assigned
-                              /dev/video3, the second /dev/video5. Any
-                              other cameras will get the first free
-                              available slot (see below).
-
-     dev_hint=645:1,680:2      The PCA645 camera will get /dev/video1,
-                              and a PCVC680 /dev/video2.
-
-     dev_hint=645.0123:3,645.4567:0    The PCA645 camera with serialnumber
-                                       0123 goes to /dev/video3, the same
-                                       camera model with the 4567 serial
-                                       gets /dev/video0.
-
-     dev_hint=750:1,4,5,6       The PCVC750 camera will get /dev/video1, the
-                               next 3 Philips cams will use /dev/video4
-                               through /dev/video6.
-
-   Some points worth knowing:
-   - Serialnumbers are case sensitive and must be written full, including
-     leading zeroes (it's treated as a string).
-   - If a device node is already occupied, registration will fail and
-     the webcam is not available.
-   - You can have up to 64 video devices; be sure to make enough device
-     nodes in /dev if you want to spread the numbers.
-     After /dev/video9 comes /dev/video10 (not /dev/videoA).
-   - If a camera does not match any dev_hint, it will simply get assigned
-     the first available device node, just as it used to be.
-
-trace
-   In order to better detect problems, it is now possible to turn on a
-   'trace' of some of the calls the module makes; it logs all items in your
-   kernel log at debug level.
-
-   The trace variable is a bitmask; each bit represents a certain feature.
-   If you want to trace something, look up the bit value(s) in the table
-   below, add the values together and supply that to the trace variable.
-
-   Value  Value   Description                                     Default
-   (dec)  (hex)
-       1    0x1   Module initialization; this will log messages       On
-                 while loading and unloading the module
-
-       2    0x2   probe() and disconnect() traces                     On
-
-       4    0x4   Trace open() and close() calls                      Off
-
-       8    0x8   read(), mmap() and associated ioctl() calls         Off
-
-      16   0x10   Memory allocation of buffers, etc.                  Off
-
-      32   0x20   Showing underflow, overflow and Dumping frame       On
-                 messages
-
-      64   0x40   Show viewport and image sizes                       Off
-
-     128   0x80   PWCX debugging                                      Off
-
-   For example, to trace the open() & read() functions, sum 8 + 4 = 12,
-   so you would supply trace=12 during insmod or modprobe. If
-   you want to turn the initialization and probing tracing off, set trace=0.
-   The default value for trace is 35 (0x23).
-
-
-
-Example:
-
-     # modprobe pwc size=cif fps=15 power_save=1
-
-The fbufs, mbufs and trace parameters are global and apply to all connected
-cameras. Each camera has its own set of buffers.
-
-size and fps only specify defaults when you open() the device; this is to
-accommodate some tools that don't set the size. You can change these
-settings after open() with the Video4Linux ioctl() calls. The default of
-defaults is QCIF size at 10 fps.
-
-The compression parameter is semiglobal; it sets the initial compression
-preference for all camera's, but this parameter can be set per camera with
-the VIDIOCPWCSCQUAL ioctl() call.
-
-All parameters are optional.
-
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
deleted file mode 100644 (file)
index 1f506fd..0000000
+++ /dev/null
@@ -1,553 +0,0 @@
-/* Driver for Philips webcam
-   Functions that send various control messages to the webcam, including
-   video modes.
-   (C) 1999-2003 Nemosoft Unv.
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-   (C) 2011 Hans de Goede <hdegoede@redhat.com>
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-/*
-   Changes
-   2001/08/03  Alvarado   Added methods for changing white balance and
-                         red/green gains
- */
-
-/* Control functions for the cam; brightness, contrast, video mode, etc. */
-
-#ifdef __KERNEL__
-#include <asm/uaccess.h>
-#endif
-#include <asm/errno.h>
-
-#include "pwc.h"
-#include "pwc-kiara.h"
-#include "pwc-timon.h"
-#include "pwc-dec1.h"
-#include "pwc-dec23.h"
-
-/* Selectors for status controls used only in this file */
-#define GET_STATUS_B00                         0x0B00
-#define SENSOR_TYPE_FORMATTER1                 0x0C00
-#define GET_STATUS_3000                                0x3000
-#define READ_RAW_Y_MEAN_FORMATTER              0x3100
-#define SET_POWER_SAVE_MODE_FORMATTER          0x3200
-#define MIRROR_IMAGE_FORMATTER                 0x3300
-#define LED_FORMATTER                          0x3400
-#define LOWLIGHT                               0x3500
-#define GET_STATUS_3600                                0x3600
-#define SENSOR_TYPE_FORMATTER2                 0x3700
-#define GET_STATUS_3800                                0x3800
-#define GET_STATUS_4000                                0x4000
-#define GET_STATUS_4100                                0x4100  /* Get */
-#define CTL_STATUS_4200                                0x4200  /* [GS] 1 */
-
-/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
-#define VIDEO_OUTPUT_CONTROL_FORMATTER         0x0100
-
-static const char *size2name[PSZ_MAX] =
-{
-       "subQCIF",
-       "QSIF",
-       "QCIF",
-       "SIF",
-       "CIF",
-       "VGA",
-};
-
-/********/
-
-/* Entries for the Nala (645/646) camera; the Nala doesn't have compression
-   preferences, so you either get compressed or non-compressed streams.
-
-   An alternate value of 0 means this mode is not available at all.
- */
-
-#define PWC_FPS_MAX_NALA 8
-
-struct Nala_table_entry {
-       char alternate;                 /* USB alternate setting */
-       int compressed;                 /* Compressed yes/no */
-
-       unsigned char mode[3];          /* precomputed mode table */
-};
-
-static unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15, 20, 24 };
-
-static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
-{
-#include "pwc-nala.h"
-};
-
-/****************************************************************************/
-
-static int recv_control_msg(struct pwc_device *pdev,
-       u8 request, u16 value, int recv_count)
-{
-       int rc;
-
-       rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
-               request,
-               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               value, pdev->vcinterface,
-               pdev->ctrl_buf, recv_count, USB_CTRL_GET_TIMEOUT);
-       if (rc < 0)
-               PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
-                         rc, request, value);
-       return rc;
-}
-
-static inline int send_video_command(struct pwc_device *pdev,
-       int index, const unsigned char *buf, int buflen)
-{
-       int rc;
-
-       memcpy(pdev->ctrl_buf, buf, buflen);
-
-       rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-                       SET_EP_STREAM_CTL,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       VIDEO_OUTPUT_CONTROL_FORMATTER, index,
-                       pdev->ctrl_buf, buflen, USB_CTRL_SET_TIMEOUT);
-       if (rc >= 0)
-               memcpy(pdev->cmd_buf, buf, buflen);
-       else
-               PWC_ERROR("send_video_command error %d\n", rc);
-
-       return rc;
-}
-
-int send_control_msg(struct pwc_device *pdev,
-       u8 request, u16 value, void *buf, int buflen)
-{
-       return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
-                       request,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, pdev->vcinterface,
-                       buf, buflen, USB_CTRL_SET_TIMEOUT);
-}
-
-static int set_video_mode_Nala(struct pwc_device *pdev, int size, int pixfmt,
-                              int frames, int *compression, int send_to_cam)
-{
-       int fps, ret = 0;
-       struct Nala_table_entry *pEntry;
-       int frames2frames[31] =
-       { /* closest match of framerate */
-          0,  0,  0,  0,  4,  /*  0-4  */
-          5,  5,  7,  7, 10,  /*  5-9  */
-         10, 10, 12, 12, 15,  /* 10-14 */
-         15, 15, 15, 20, 20,  /* 15-19 */
-         20, 20, 20, 24, 24,  /* 20-24 */
-         24, 24, 24, 24, 24,  /* 25-29 */
-         24                   /* 30    */
-       };
-       int frames2table[31] =
-       { 0, 0, 0, 0, 0, /*  0-4  */
-         1, 1, 1, 2, 2, /*  5-9  */
-         3, 3, 4, 4, 4, /* 10-14 */
-         5, 5, 5, 5, 5, /* 15-19 */
-         6, 6, 6, 6, 7, /* 20-24 */
-         7, 7, 7, 7, 7, /* 25-29 */
-         7              /* 30    */
-       };
-
-       if (size < 0 || size > PSZ_CIF)
-               return -EINVAL;
-       if (frames < 4)
-               frames = 4;
-       else if (frames > 25)
-               frames = 25;
-       frames = frames2frames[frames];
-       fps = frames2table[frames];
-       pEntry = &Nala_table[size][fps];
-       if (pEntry->alternate == 0)
-               return -EINVAL;
-
-       if (send_to_cam)
-               ret = send_video_command(pdev, pdev->vendpoint,
-                                        pEntry->mode, 3);
-       if (ret < 0)
-               return ret;
-
-       if (pEntry->compressed && pixfmt == V4L2_PIX_FMT_YUV420)
-               pwc_dec1_init(pdev, pEntry->mode);
-
-       /* Set various parameters */
-       pdev->pixfmt = pixfmt;
-       pdev->vframes = frames;
-       pdev->valternate = pEntry->alternate;
-       pdev->width  = pwc_image_sizes[size][0];
-       pdev->height = pwc_image_sizes[size][1];
-       pdev->frame_size = (pdev->width * pdev->height * 3) / 2;
-       if (pEntry->compressed) {
-               if (pdev->release < 5) { /* 4 fold compression */
-                       pdev->vbandlength = 528;
-                       pdev->frame_size /= 4;
-               }
-               else {
-                       pdev->vbandlength = 704;
-                       pdev->frame_size /= 3;
-               }
-       }
-       else
-               pdev->vbandlength = 0;
-
-       /* Let pwc-if.c:isoc_init know we don't support higher compression */
-       *compression = 3;
-
-       return 0;
-}
-
-
-static int set_video_mode_Timon(struct pwc_device *pdev, int size, int pixfmt,
-                               int frames, int *compression, int send_to_cam)
-{
-       const struct Timon_table_entry *pChoose;
-       int fps, ret = 0;
-
-       if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
-               return -EINVAL;
-       if (frames < 5)
-               frames = 5;
-       else if (size == PSZ_VGA && frames > 15)
-               frames = 15;
-       else if (frames > 30)
-               frames = 30;
-       fps = (frames / 5) - 1;
-
-       /* Find a supported framerate with progressively higher compression */
-       pChoose = NULL;
-       while (*compression <= 3) {
-               pChoose = &Timon_table[size][fps][*compression];
-               if (pChoose->alternate != 0)
-                       break;
-               (*compression)++;
-       }
-       if (pChoose == NULL || pChoose->alternate == 0)
-               return -ENOENT; /* Not supported. */
-
-       if (send_to_cam)
-               ret = send_video_command(pdev, pdev->vendpoint,
-                                        pChoose->mode, 13);
-       if (ret < 0)
-               return ret;
-
-       if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
-               pwc_dec23_init(pdev, pChoose->mode);
-
-       /* Set various parameters */
-       pdev->pixfmt = pixfmt;
-       pdev->vframes = (fps + 1) * 5;
-       pdev->valternate = pChoose->alternate;
-       pdev->width  = pwc_image_sizes[size][0];
-       pdev->height = pwc_image_sizes[size][1];
-       pdev->vbandlength = pChoose->bandlength;
-       if (pChoose->bandlength > 0)
-               pdev->frame_size = (pChoose->bandlength * pdev->height) / 4;
-       else
-               pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
-       return 0;
-}
-
-
-static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int pixfmt,
-                               int frames, int *compression, int send_to_cam)
-{
-       const struct Kiara_table_entry *pChoose = NULL;
-       int fps, ret = 0;
-
-       if (size >= PSZ_MAX || *compression < 0 || *compression > 3)
-               return -EINVAL;
-       if (frames < 5)
-               frames = 5;
-       else if (size == PSZ_VGA && frames > 15)
-               frames = 15;
-       else if (frames > 30)
-               frames = 30;
-       fps = (frames / 5) - 1;
-
-       /* Find a supported framerate with progressively higher compression */
-       while (*compression <= 3) {
-               pChoose = &Kiara_table[size][fps][*compression];
-               if (pChoose->alternate != 0)
-                       break;
-               (*compression)++;
-       }
-       if (pChoose == NULL || pChoose->alternate == 0)
-               return -ENOENT; /* Not supported. */
-
-       /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
-       if (send_to_cam)
-               ret = send_video_command(pdev, 4, pChoose->mode, 12);
-       if (ret < 0)
-               return ret;
-
-       if (pChoose->bandlength > 0 && pixfmt == V4L2_PIX_FMT_YUV420)
-               pwc_dec23_init(pdev, pChoose->mode);
-
-       /* All set and go */
-       pdev->pixfmt = pixfmt;
-       pdev->vframes = (fps + 1) * 5;
-       pdev->valternate = pChoose->alternate;
-       pdev->width  = pwc_image_sizes[size][0];
-       pdev->height = pwc_image_sizes[size][1];
-       pdev->vbandlength = pChoose->bandlength;
-       if (pdev->vbandlength > 0)
-               pdev->frame_size = (pdev->vbandlength * pdev->height) / 4;
-       else
-               pdev->frame_size = (pdev->width * pdev->height * 12) / 8;
-       PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n",
-           pdev->frame_size, pdev->vframes, size, pdev->vbandlength);
-       return 0;
-}
-
-int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
-       int pixfmt, int frames, int *compression, int send_to_cam)
-{
-       int ret, size;
-
-       PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n",
-                      width, height, frames, pixfmt);
-       size = pwc_get_size(pdev, width, height);
-       PWC_TRACE("decode_size = %d.\n", size);
-
-       if (DEVICE_USE_CODEC1(pdev->type)) {
-               ret = set_video_mode_Nala(pdev, size, pixfmt, frames,
-                                         compression, send_to_cam);
-       } else if (DEVICE_USE_CODEC3(pdev->type)) {
-               ret = set_video_mode_Kiara(pdev, size, pixfmt, frames,
-                                          compression, send_to_cam);
-       } else {
-               ret = set_video_mode_Timon(pdev, size, pixfmt, frames,
-                                          compression, send_to_cam);
-       }
-       if (ret < 0) {
-               PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
-               return ret;
-       }
-       pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
-       PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height);
-       return 0;
-}
-
-static unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int index, unsigned int size)
-{
-       unsigned int i;
-
-       for (i = 0; i < PWC_FPS_MAX_NALA; i++) {
-               if (Nala_table[size][i].alternate) {
-                       if (index--==0) return Nala_fps_vector[i];
-               }
-       }
-       return 0;
-}
-
-static unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int index, unsigned int size)
-{
-       unsigned int i;
-
-       for (i = 0; i < PWC_FPS_MAX_KIARA; i++) {
-               if (Kiara_table[size][i][3].alternate) {
-                       if (index--==0) return Kiara_fps_vector[i];
-               }
-       }
-       return 0;
-}
-
-static unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int index, unsigned int size)
-{
-       unsigned int i;
-
-       for (i=0; i < PWC_FPS_MAX_TIMON; i++) {
-               if (Timon_table[size][i][3].alternate) {
-                       if (index--==0) return Timon_fps_vector[i];
-               }
-       }
-       return 0;
-}
-
-unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size)
-{
-       unsigned int ret;
-
-       if (DEVICE_USE_CODEC1(pdev->type)) {
-               ret = pwc_get_fps_Nala(pdev, index, size);
-
-       } else if (DEVICE_USE_CODEC3(pdev->type)) {
-               ret = pwc_get_fps_Kiara(pdev, index, size);
-
-       } else {
-               ret = pwc_get_fps_Timon(pdev, index, size);
-       }
-
-       return ret;
-}
-
-int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
-{
-       int ret;
-
-       ret = recv_control_msg(pdev, request, value, 1);
-       if (ret < 0)
-               return ret;
-
-       *data = pdev->ctrl_buf[0];
-       return 0;
-}
-
-int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
-{
-       int ret;
-
-       pdev->ctrl_buf[0] = data;
-       ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 1);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
-{
-       int ret;
-
-       ret = recv_control_msg(pdev, request, value, 1);
-       if (ret < 0)
-               return ret;
-
-       *data = ((s8 *)pdev->ctrl_buf)[0];
-       return 0;
-}
-
-int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
-{
-       int ret;
-
-       ret = recv_control_msg(pdev, request, value, 2);
-       if (ret < 0)
-               return ret;
-
-       *data = (pdev->ctrl_buf[1] << 8) | pdev->ctrl_buf[0];
-       return 0;
-}
-
-int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
-{
-       int ret;
-
-       pdev->ctrl_buf[0] = data & 0xff;
-       pdev->ctrl_buf[1] = data >> 8;
-       ret = send_control_msg(pdev, request, value, pdev->ctrl_buf, 2);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
-{
-       int ret;
-
-       ret = send_control_msg(pdev, SET_STATUS_CTL, value, NULL, 0);
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-
-/* POWER */
-void pwc_camera_power(struct pwc_device *pdev, int power)
-{
-       int r;
-
-       if (!pdev->power_save)
-               return;
-
-       if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
-               return; /* Not supported by Nala or Timon < release 6 */
-
-       if (power)
-               pdev->ctrl_buf[0] = 0x00; /* active */
-       else
-               pdev->ctrl_buf[0] = 0xFF; /* power save */
-       r = send_control_msg(pdev, SET_STATUS_CTL,
-               SET_POWER_SAVE_MODE_FORMATTER, pdev->ctrl_buf, 1);
-       if (r < 0)
-               PWC_ERROR("Failed to power %s camera (%d)\n",
-                         power ? "on" : "off", r);
-}
-
-int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
-{
-       int r;
-
-       if (pdev->type < 730)
-               return 0;
-       on_value /= 100;
-       off_value /= 100;
-       if (on_value < 0)
-               on_value = 0;
-       if (on_value > 0xff)
-               on_value = 0xff;
-       if (off_value < 0)
-               off_value = 0;
-       if (off_value > 0xff)
-               off_value = 0xff;
-
-       pdev->ctrl_buf[0] = on_value;
-       pdev->ctrl_buf[1] = off_value;
-
-       r = send_control_msg(pdev,
-               SET_STATUS_CTL, LED_FORMATTER, pdev->ctrl_buf, 2);
-       if (r < 0)
-               PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
-
-       return r;
-}
-
-#ifdef CONFIG_USB_PWC_DEBUG
-int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
-{
-       int ret = -1, request;
-
-       if (pdev->type < 675)
-               request = SENSOR_TYPE_FORMATTER1;
-       else if (pdev->type < 730)
-               return -1; /* The Vesta series doesn't have this call */
-       else
-               request = SENSOR_TYPE_FORMATTER2;
-
-       ret = recv_control_msg(pdev, GET_STATUS_CTL, request, 1);
-       if (ret < 0)
-               return ret;
-       if (pdev->type < 675)
-               *sensor = pdev->ctrl_buf[0] | 0x100;
-       else
-               *sensor = pdev->ctrl_buf[0];
-       return 0;
-}
-#endif
diff --git a/drivers/media/video/pwc/pwc-dec1.c b/drivers/media/video/pwc/pwc-dec1.c
deleted file mode 100644 (file)
index e899036..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Linux driver for Philips webcam
-   Decompression for chipset version 1
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-#include "pwc.h"
-
-void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd)
-{
-       struct pwc_dec1_private *pdec = &pdev->dec1;
-
-       pdec->version = pdev->release;
-}
diff --git a/drivers/media/video/pwc/pwc-dec1.h b/drivers/media/video/pwc/pwc-dec1.h
deleted file mode 100644 (file)
index c565ef8..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Linux driver for Philips webcam
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef PWC_DEC1_H
-#define PWC_DEC1_H
-
-#include <linux/mutex.h>
-
-struct pwc_device;
-
-struct pwc_dec1_private
-{
-       int version;
-};
-
-void pwc_dec1_init(struct pwc_device *pdev, const unsigned char *cmd);
-
-#endif
diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/video/pwc/pwc-dec23.c
deleted file mode 100644 (file)
index 3792fed..0000000
+++ /dev/null
@@ -1,691 +0,0 @@
-/* Linux driver for Philips webcam
-   Decompression for chipset version 2 et 3
-   (C) 2004-2006  Luc Saillard (luc@saillard.org)
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-*/
-
-#include "pwc-timon.h"
-#include "pwc-kiara.h"
-#include "pwc-dec23.h"
-
-#include <linux/string.h>
-#include <linux/slab.h>
-
-/*
- * USE_LOOKUP_TABLE_TO_CLAMP
- *   0: use a C version of this tests:  {  a<0?0:(a>255?255:a) }
- *   1: use a faster lookup table for cpu with a big cache (intel)
- */
-#define USE_LOOKUP_TABLE_TO_CLAMP      1
-/*
- * UNROLL_LOOP_FOR_COPYING_BLOCK
- *   0: use a loop for a smaller code (but little slower)
- *   1: when unrolling the loop, gcc produces some faster code (perhaps only
- *   valid for intel processor class). Activating this option, automaticaly
- *   activate USE_LOOKUP_TABLE_TO_CLAMP
- */
-#define UNROLL_LOOP_FOR_COPY           1
-#if UNROLL_LOOP_FOR_COPY
-# undef USE_LOOKUP_TABLE_TO_CLAMP
-# define USE_LOOKUP_TABLE_TO_CLAMP 1
-#endif
-
-static void build_subblock_pattern(struct pwc_dec23_private *pdec)
-{
-       static const unsigned int initial_values[12] = {
-               -0x526500, -0x221200, 0x221200, 0x526500,
-                          -0x3de200, 0x3de200,
-               -0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480,
-                          -0x12c200, 0x12c200
-
-       };
-       static const unsigned int values_derivated[12] = {
-               0xa4ca, 0x4424, -0x4424, -0xa4ca,
-                       0x7bc4, -0x7bc4,
-               0xdb69, 0x5aba, -0x5aba, -0xdb69,
-                       0x2584, -0x2584
-       };
-       unsigned int temp_values[12];
-       int i, j;
-
-       memcpy(temp_values, initial_values, sizeof(initial_values));
-       for (i = 0; i < 256; i++) {
-               for (j = 0; j < 12; j++) {
-                       pdec->table_subblock[i][j] = temp_values[j];
-                       temp_values[j] += values_derivated[j];
-               }
-       }
-}
-
-static void build_bit_powermask_table(struct pwc_dec23_private *pdec)
-{
-       unsigned char *p;
-       unsigned int bit, byte, mask, val;
-       unsigned int bitpower = 1;
-
-       for (bit = 0; bit < 8; bit++) {
-               mask = bitpower - 1;
-               p = pdec->table_bitpowermask[bit];
-               for (byte = 0; byte < 256; byte++) {
-                       val = (byte & mask);
-                       if (byte & bitpower)
-                               val = -val;
-                       *p++ = val;
-               }
-               bitpower<<=1;
-       }
-}
-
-
-static void build_table_color(const unsigned int romtable[16][8],
-                             unsigned char p0004[16][1024],
-                             unsigned char p8004[16][256])
-{
-       int compression_mode, j, k, bit, pw;
-       unsigned char *p0, *p8;
-       const unsigned int *r;
-
-       /* We have 16 compressions tables */
-       for (compression_mode = 0; compression_mode < 16; compression_mode++) {
-               p0 = p0004[compression_mode];
-               p8 = p8004[compression_mode];
-               r  = romtable[compression_mode];
-
-               for (j = 0; j < 8; j++, r++, p0 += 128) {
-
-                       for (k = 0; k < 16; k++) {
-                               if (k == 0)
-                                       bit = 1;
-                               else if (k >= 1 && k < 3)
-                                       bit = (r[0] >> 15) & 7;
-                               else if (k >= 3 && k < 6)
-                                       bit = (r[0] >> 12) & 7;
-                               else if (k >= 6 && k < 10)
-                                       bit = (r[0] >> 9) & 7;
-                               else if (k >= 10 && k < 13)
-                                       bit = (r[0] >> 6) & 7;
-                               else if (k >= 13 && k < 15)
-                                       bit = (r[0] >> 3) & 7;
-                               else
-                                       bit = (r[0]) & 7;
-                               if (k == 0)
-                                       *p8++ = 8;
-                               else
-                                       *p8++ = j - bit;
-                               *p8++ = bit;
-
-                               pw = 1 << bit;
-                               p0[k + 0x00] = (1 * pw) + 0x80;
-                               p0[k + 0x10] = (2 * pw) + 0x80;
-                               p0[k + 0x20] = (3 * pw) + 0x80;
-                               p0[k + 0x30] = (4 * pw) + 0x80;
-                               p0[k + 0x40] = (-1 * pw) + 0x80;
-                               p0[k + 0x50] = (-2 * pw) + 0x80;
-                               p0[k + 0x60] = (-3 * pw) + 0x80;
-                               p0[k + 0x70] = (-4 * pw) + 0x80;
-                       }       /* end of for (k=0; k<16; k++, p8++) */
-               }       /* end of for (j=0; j<8; j++ , table++) */
-       } /* end of foreach compression_mode */
-}
-
-/*
- *
- */
-static void fill_table_dc00_d800(struct pwc_dec23_private *pdec)
-{
-#define SCALEBITS 15
-#define ONE_HALF  (1UL << (SCALEBITS - 1))
-       int i;
-       unsigned int offset1 = ONE_HALF;
-       unsigned int offset2 = 0x0000;
-
-       for (i=0; i<256; i++) {
-               pdec->table_dc00[i] = offset1 & ~(ONE_HALF);
-               pdec->table_d800[i] = offset2;
-
-               offset1 += 0x7bc4;
-               offset2 += 0x7bc4;
-       }
-}
-
-/*
- * To decode the stream:
- *   if look_bits(2) == 0:     # op == 2 in the lookup table
- *      skip_bits(2)
- *      end of the stream
- *   elif look_bits(3) == 7:   # op == 1 in the lookup table
- *      skip_bits(3)
- *      yyyy = get_bits(4)
- *      xxxx = get_bits(8)
- *   else:                     # op == 0 in the lookup table
- *      skip_bits(x)
- *
- * For speedup processing, we build a lookup table and we takes the first 6 bits.
- *
- * struct {
- *   unsigned char op;     // operation to execute
- *   unsigned char bits;    // bits use to perform operation
- *   unsigned char offset1; // offset to add to access in the table_0004 % 16
- *   unsigned char offset2; // offset to add to access in the table_0004
- * }
- *
- * How to build this table ?
- *   op == 2 when (i%4)==0
- *   op == 1 when (i%8)==7
- *   op == 0 otherwise
- *
- */
-static const unsigned char hash_table_ops[64*4] = {
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x00,
-       0x00, 0x04, 0x01, 0x10,
-       0x00, 0x06, 0x01, 0x30,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x40,
-       0x00, 0x05, 0x01, 0x20,
-       0x01, 0x00, 0x00, 0x00,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x00,
-       0x00, 0x04, 0x01, 0x50,
-       0x00, 0x05, 0x02, 0x00,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x40,
-       0x00, 0x05, 0x03, 0x00,
-       0x01, 0x00, 0x00, 0x00,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x00,
-       0x00, 0x04, 0x01, 0x10,
-       0x00, 0x06, 0x02, 0x10,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x40,
-       0x00, 0x05, 0x01, 0x60,
-       0x01, 0x00, 0x00, 0x00,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x00,
-       0x00, 0x04, 0x01, 0x50,
-       0x00, 0x05, 0x02, 0x40,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x40,
-       0x00, 0x05, 0x03, 0x40,
-       0x01, 0x00, 0x00, 0x00,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x00,
-       0x00, 0x04, 0x01, 0x10,
-       0x00, 0x06, 0x01, 0x70,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x40,
-       0x00, 0x05, 0x01, 0x20,
-       0x01, 0x00, 0x00, 0x00,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x00,
-       0x00, 0x04, 0x01, 0x50,
-       0x00, 0x05, 0x02, 0x00,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x40,
-       0x00, 0x05, 0x03, 0x00,
-       0x01, 0x00, 0x00, 0x00,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x00,
-       0x00, 0x04, 0x01, 0x10,
-       0x00, 0x06, 0x02, 0x50,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x40,
-       0x00, 0x05, 0x01, 0x60,
-       0x01, 0x00, 0x00, 0x00,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x00,
-       0x00, 0x04, 0x01, 0x50,
-       0x00, 0x05, 0x02, 0x40,
-       0x02, 0x00, 0x00, 0x00,
-       0x00, 0x03, 0x01, 0x40,
-       0x00, 0x05, 0x03, 0x40,
-       0x01, 0x00, 0x00, 0x00
-};
-
-/*
- *
- */
-static const unsigned int MulIdx[16][16] = {
-       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
-       {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,},
-       {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,},
-       {4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,},
-       {6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,},
-       {4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,},
-       {1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,},
-       {0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,},
-       {0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,},
-       {1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,},
-       {7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,},
-       {4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,},
-       {7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,},
-       {1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,},
-       {1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,},
-       {10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10}
-};
-
-#if USE_LOOKUP_TABLE_TO_CLAMP
-#define MAX_OUTER_CROP_VALUE   (512)
-static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];
-#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)])
-#else
-#define CLAMP(x) ((x)>255?255:((x)<0?0:x))
-#endif
-
-
-/* If the type or the command change, we rebuild the lookup table */
-void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd)
-{
-       int flags, version, shift, i;
-       struct pwc_dec23_private *pdec = &pdev->dec23;
-
-       mutex_init(&pdec->lock);
-
-       if (pdec->last_cmd_valid && pdec->last_cmd == cmd[2])
-               return;
-
-       if (DEVICE_USE_CODEC3(pdev->type)) {
-               flags = cmd[2] & 0x18;
-               if (flags == 8)
-                       pdec->nbits = 7;        /* More bits, mean more bits to encode the stream, but better quality */
-               else if (flags == 0x10)
-                       pdec->nbits = 8;
-               else
-                       pdec->nbits = 6;
-
-               version = cmd[2] >> 5;
-               build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
-               build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
-
-       } else {
-
-               flags = cmd[2] & 6;
-               if (flags == 2)
-                       pdec->nbits = 7;
-               else if (flags == 4)
-                       pdec->nbits = 8;
-               else
-                       pdec->nbits = 6;
-
-               version = cmd[2] >> 3;
-               build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
-               build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
-       }
-
-       /* Informations can be coded on a variable number of bits but never less than 8 */
-       shift = 8 - pdec->nbits;
-       pdec->scalebits = SCALEBITS - shift;
-       pdec->nbitsmask = 0xFF >> shift;
-
-       fill_table_dc00_d800(pdec);
-       build_subblock_pattern(pdec);
-       build_bit_powermask_table(pdec);
-
-#if USE_LOOKUP_TABLE_TO_CLAMP
-       /* Build the static table to clamp value [0-255] */
-       for (i=0;i<MAX_OUTER_CROP_VALUE;i++)
-               pwc_crop_table[i] = 0;
-       for (i=0; i<256; i++)
-               pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i;
-       for (i=0; i<MAX_OUTER_CROP_VALUE; i++)
-               pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255;
-#endif
-
-       pdec->last_cmd = cmd[2];
-       pdec->last_cmd_valid = 1;
-}
-
-/*
- * Copy the 4x4 image block to Y plane buffer
- */
-static void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
-{
-#if UNROLL_LOOP_FOR_COPY
-       const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
-       const int *c = src;
-       unsigned char *d = dst;
-
-       *d++ = cm[c[0] >> scalebits];
-       *d++ = cm[c[1] >> scalebits];
-       *d++ = cm[c[2] >> scalebits];
-       *d++ = cm[c[3] >> scalebits];
-
-       d = dst + bytes_per_line;
-       *d++ = cm[c[4] >> scalebits];
-       *d++ = cm[c[5] >> scalebits];
-       *d++ = cm[c[6] >> scalebits];
-       *d++ = cm[c[7] >> scalebits];
-
-       d = dst + bytes_per_line*2;
-       *d++ = cm[c[8] >> scalebits];
-       *d++ = cm[c[9] >> scalebits];
-       *d++ = cm[c[10] >> scalebits];
-       *d++ = cm[c[11] >> scalebits];
-
-       d = dst + bytes_per_line*3;
-       *d++ = cm[c[12] >> scalebits];
-       *d++ = cm[c[13] >> scalebits];
-       *d++ = cm[c[14] >> scalebits];
-       *d++ = cm[c[15] >> scalebits];
-#else
-       int i;
-       const int *c = src;
-       unsigned char *d = dst;
-       for (i = 0; i < 4; i++, c++)
-               *d++ = CLAMP((*c) >> scalebits);
-
-       d = dst + bytes_per_line;
-       for (i = 0; i < 4; i++, c++)
-               *d++ = CLAMP((*c) >> scalebits);
-
-       d = dst + bytes_per_line*2;
-       for (i = 0; i < 4; i++, c++)
-               *d++ = CLAMP((*c) >> scalebits);
-
-       d = dst + bytes_per_line*3;
-       for (i = 0; i < 4; i++, c++)
-               *d++ = CLAMP((*c) >> scalebits);
-#endif
-}
-
-/*
- * Copy the 4x4 image block to a CrCb plane buffer
- *
- */
-static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
-{
-#if UNROLL_LOOP_FOR_COPY
-       /* Unroll all loops */
-       const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
-       const int *c = src;
-       unsigned char *d = dst;
-
-       *d++ = cm[c[0] >> scalebits];
-       *d++ = cm[c[4] >> scalebits];
-       *d++ = cm[c[1] >> scalebits];
-       *d++ = cm[c[5] >> scalebits];
-       *d++ = cm[c[2] >> scalebits];
-       *d++ = cm[c[6] >> scalebits];
-       *d++ = cm[c[3] >> scalebits];
-       *d++ = cm[c[7] >> scalebits];
-
-       d = dst + bytes_per_line;
-       *d++ = cm[c[12] >> scalebits];
-       *d++ = cm[c[8] >> scalebits];
-       *d++ = cm[c[13] >> scalebits];
-       *d++ = cm[c[9] >> scalebits];
-       *d++ = cm[c[14] >> scalebits];
-       *d++ = cm[c[10] >> scalebits];
-       *d++ = cm[c[15] >> scalebits];
-       *d++ = cm[c[11] >> scalebits];
-#else
-       int i;
-       const int *c1 = src;
-       const int *c2 = src + 4;
-       unsigned char *d = dst;
-
-       for (i = 0; i < 4; i++, c1++, c2++) {
-               *d++ = CLAMP((*c1) >> scalebits);
-               *d++ = CLAMP((*c2) >> scalebits);
-       }
-       c1 = src + 12;
-       d = dst + bytes_per_line;
-       for (i = 0; i < 4; i++, c1++, c2++) {
-               *d++ = CLAMP((*c1) >> scalebits);
-               *d++ = CLAMP((*c2) >> scalebits);
-       }
-#endif
-}
-
-/*
- * To manage the stream, we keep bits in a 32 bits register.
- * fill_nbits(n): fill the reservoir with at least n bits
- * skip_bits(n): discard n bits from the reservoir
- * get_bits(n): fill the reservoir, returns the first n bits and discard the
- *              bits from the reservoir.
- * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir
- *                 contains at least n bits. bits returned is discarded.
- */
-#define fill_nbits(pdec, nbits_wanted) do { \
-   while (pdec->nbits_in_reservoir<(nbits_wanted)) \
-    { \
-      pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \
-      pdec->nbits_in_reservoir += 8; \
-    } \
-}  while(0);
-
-#define skip_nbits(pdec, nbits_to_skip) do { \
-   pdec->reservoir >>= (nbits_to_skip); \
-   pdec->nbits_in_reservoir -= (nbits_to_skip); \
-}  while(0);
-
-#define get_nbits(pdec, nbits_wanted, result) do { \
-   fill_nbits(pdec, nbits_wanted); \
-   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
-   skip_nbits(pdec, nbits_wanted); \
-}  while(0);
-
-#define __get_nbits(pdec, nbits_wanted, result) do { \
-   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
-   skip_nbits(pdec, nbits_wanted); \
-}  while(0);
-
-#define look_nbits(pdec, nbits_wanted) \
-   ((pdec->reservoir) & ((1U<<(nbits_wanted))-1))
-
-/*
- * Decode a 4x4 pixel block
- */
-static void decode_block(struct pwc_dec23_private *pdec,
-                        const unsigned char *ptable0004,
-                        const unsigned char *ptable8004)
-{
-       unsigned int primary_color;
-       unsigned int channel_v, offset1, op;
-       int i;
-
-       fill_nbits(pdec, 16);
-       __get_nbits(pdec, pdec->nbits, primary_color);
-
-       if (look_nbits(pdec,2) == 0) {
-               skip_nbits(pdec, 2);
-               /* Very simple, the color is the same for all pixels of the square */
-               for (i = 0; i < 16; i++)
-                       pdec->temp_colors[i] = pdec->table_dc00[primary_color];
-
-               return;
-       }
-
-       /* This block is encoded with small pattern */
-       for (i = 0; i < 16; i++)
-               pdec->temp_colors[i] = pdec->table_d800[primary_color];
-
-       __get_nbits(pdec, 3, channel_v);
-       channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2);
-
-       ptable0004 += (channel_v * 128);
-       ptable8004 += (channel_v * 32);
-
-       offset1 = 0;
-       do
-       {
-               unsigned int htable_idx, rows = 0;
-               const unsigned int *block;
-
-               /* [  zzzz y x x ]
-                *     xx == 00 :=> end of the block def, remove the two bits from the stream
-                *    yxx == 111
-                *    yxx == any other value
-                *
-                */
-               fill_nbits(pdec, 16);
-               htable_idx = look_nbits(pdec, 6);
-               op = hash_table_ops[htable_idx * 4];
-
-               if (op == 2) {
-                       skip_nbits(pdec, 2);
-
-               } else if (op == 1) {
-                       /* 15bits [ xxxx xxxx yyyy 111 ]
-                        * yyy => offset in the table8004
-                        * xxx => offset in the tabled004 (tree)
-                        */
-                       unsigned int mask, shift;
-                       unsigned int nbits, col1;
-                       unsigned int yyyy;
-
-                       skip_nbits(pdec, 3);
-                       /* offset1 += yyyy */
-                       __get_nbits(pdec, 4, yyyy);
-                       offset1 += 1 + yyyy;
-                       offset1 &= 0x0F;
-                       nbits = ptable8004[offset1 * 2];
-
-                       /* col1 = xxxx xxxx */
-                       __get_nbits(pdec, nbits+1, col1);
-
-                       /* Bit mask table */
-                       mask = pdec->table_bitpowermask[nbits][col1];
-                       shift = ptable8004[offset1 * 2 + 1];
-                       rows = ((mask << shift) + 0x80) & 0xFF;
-
-                       block = pdec->table_subblock[rows];
-                       for (i = 0; i < 16; i++)
-                               pdec->temp_colors[i] += block[MulIdx[offset1][i]];
-
-               } else {
-                       /* op == 0
-                        * offset1 is coded on 3 bits
-                        */
-                       unsigned int shift;
-
-                       offset1 += hash_table_ops [htable_idx * 4 + 2];
-                       offset1 &= 0x0F;
-
-                       rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3]];
-                       block = pdec->table_subblock[rows];
-                       for (i = 0; i < 16; i++)
-                               pdec->temp_colors[i] += block[MulIdx[offset1][i]];
-
-                       shift = hash_table_ops[htable_idx * 4 + 1];
-                       skip_nbits(pdec, shift);
-               }
-
-       } while (op != 2);
-
-}
-
-static void DecompressBand23(struct pwc_dec23_private *pdec,
-                            const unsigned char *rawyuv,
-                            unsigned char *planar_y,
-                            unsigned char *planar_u,
-                            unsigned char *planar_v,
-                            unsigned int   compressed_image_width,
-                            unsigned int   real_image_width)
-{
-       int compression_index, nblocks;
-       const unsigned char *ptable0004;
-       const unsigned char *ptable8004;
-
-       pdec->reservoir = 0;
-       pdec->nbits_in_reservoir = 0;
-       pdec->stream = rawyuv + 1;      /* The first byte of the stream is skipped */
-
-       get_nbits(pdec, 4, compression_index);
-
-       /* pass 1: uncompress Y component */
-       nblocks = compressed_image_width / 4;
-
-       ptable0004 = pdec->table_0004_pass1[compression_index];
-       ptable8004 = pdec->table_8004_pass1[compression_index];
-
-       /* Each block decode a square of 4x4 */
-       while (nblocks) {
-               decode_block(pdec, ptable0004, ptable8004);
-               copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits);
-               planar_y += 4;
-               nblocks--;
-       }
-
-       /* pass 2: uncompress UV component */
-       nblocks = compressed_image_width / 8;
-
-       ptable0004 = pdec->table_0004_pass2[compression_index];
-       ptable8004 = pdec->table_8004_pass2[compression_index];
-
-       /* Each block decode a square of 4x4 */
-       while (nblocks) {
-               decode_block(pdec, ptable0004, ptable8004);
-               copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits);
-
-               decode_block(pdec, ptable0004, ptable8004);
-               copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits);
-
-               planar_v += 8;
-               planar_u += 8;
-               nblocks -= 2;
-       }
-
-}
-
-/**
- *
- * Uncompress a pwc23 buffer.
- *
- * src: raw data
- * dst: image output
- */
-void pwc_dec23_decompress(struct pwc_device *pdev,
-                         const void *src,
-                         void *dst)
-{
-       int bandlines_left, bytes_per_block;
-       struct pwc_dec23_private *pdec = &pdev->dec23;
-
-       /* YUV420P image format */
-       unsigned char *pout_planar_y;
-       unsigned char *pout_planar_u;
-       unsigned char *pout_planar_v;
-       unsigned int   plane_size;
-
-       mutex_lock(&pdec->lock);
-
-       bandlines_left = pdev->height / 4;
-       bytes_per_block = pdev->width * 4;
-       plane_size = pdev->height * pdev->width;
-
-       pout_planar_y = dst;
-       pout_planar_u = dst + plane_size;
-       pout_planar_v = dst + plane_size + plane_size / 4;
-
-       while (bandlines_left--) {
-               DecompressBand23(pdec, src,
-                                pout_planar_y, pout_planar_u, pout_planar_v,
-                                pdev->width, pdev->width);
-               src += pdev->vbandlength;
-               pout_planar_y += bytes_per_block;
-               pout_planar_u += pdev->width;
-               pout_planar_v += pdev->width;
-       }
-       mutex_unlock(&pdec->lock);
-}
diff --git a/drivers/media/video/pwc/pwc-dec23.h b/drivers/media/video/pwc/pwc-dec23.h
deleted file mode 100644 (file)
index c655b1c..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Linux driver for Philips webcam
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef PWC_DEC23_H
-#define PWC_DEC23_H
-
-struct pwc_device;
-
-struct pwc_dec23_private
-{
-       struct mutex lock;
-
-       unsigned char last_cmd, last_cmd_valid;
-
-  unsigned int scalebits;
-  unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */
-
-  unsigned int reservoir;
-  unsigned int nbits_in_reservoir;
-
-  const unsigned char *stream;
-  int temp_colors[16];
-
-  unsigned char table_0004_pass1[16][1024];
-  unsigned char table_0004_pass2[16][1024];
-  unsigned char table_8004_pass1[16][256];
-  unsigned char table_8004_pass2[16][256];
-  unsigned int  table_subblock[256][12];
-
-  unsigned char table_bitpowermask[8][256];
-  unsigned int  table_d800[256];
-  unsigned int  table_dc00[256];
-
-};
-
-void pwc_dec23_init(struct pwc_device *pdev, const unsigned char *cmd);
-void pwc_dec23_decompress(struct pwc_device *pdev,
-                         const void *src,
-                         void *dst);
-#endif
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
deleted file mode 100644 (file)
index de7c7ba..0000000
+++ /dev/null
@@ -1,1165 +0,0 @@
-/* Linux driver for Philips webcam
-   USB and Video4Linux interface part.
-   (C) 1999-2004 Nemosoft Unv.
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-   (C) 2011 Hans de Goede <hdegoede@redhat.com>
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-*/
-
-/*
-   This code forms the interface between the USB layers and the Philips
-   specific stuff. Some adanved stuff of the driver falls under an
-   NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
-   is thus not distributed in source form. The binary pwcx.o module
-   contains the code that falls under the NDA.
-
-   In case you're wondering: 'pwc' stands for "Philips WebCam", but
-   I really didn't want to type 'philips_web_cam' every time (I'm lazy as
-   any Linux kernel hacker, but I don't like uncomprehensible abbreviations
-   without explanation).
-
-   Oh yes, convention: to disctinguish between all the various pointers to
-   device-structures, I use these names for the pointer variables:
-   udev: struct usb_device *
-   vdev: struct video_device (member of pwc_dev)
-   pdev: struct pwc_devive *
-*/
-
-/* Contributors:
-   - Alvarado: adding whitebalance code
-   - Alistar Moire: QuickCam 3000 Pro device/product ID
-   - Tony Hoyle: Creative Labs Webcam 5 device/product ID
-   - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
-   - Jk Fang: Sotec Afina Eye ID
-   - Xavier Roche: QuickCam Pro 4000 ID
-   - Jens Knudsen: QuickCam Zoom ID
-   - J. Debert: QuickCam for Notebooks ID
-   - Pham Thanh Nam: webcam snapshot button as an event input device
-*/
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#ifdef CONFIG_USB_PWC_INPUT_EVDEV
-#include <linux/usb/input.h>
-#endif
-#include <linux/vmalloc.h>
-#include <asm/io.h>
-#include <linux/kernel.h>              /* simple_strtol() */
-
-#include "pwc.h"
-#include "pwc-kiara.h"
-#include "pwc-timon.h"
-#include "pwc-dec23.h"
-#include "pwc-dec1.h"
-
-/* Function prototypes and driver templates */
-
-/* hotplug device table support */
-static const struct usb_device_id pwc_device_table [] = {
-       { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */
-       { USB_DEVICE(0x0471, 0x0303) },
-       { USB_DEVICE(0x0471, 0x0304) },
-       { USB_DEVICE(0x0471, 0x0307) },
-       { USB_DEVICE(0x0471, 0x0308) },
-       { USB_DEVICE(0x0471, 0x030C) },
-       { USB_DEVICE(0x0471, 0x0310) },
-       { USB_DEVICE(0x0471, 0x0311) }, /* Philips ToUcam PRO II */
-       { USB_DEVICE(0x0471, 0x0312) },
-       { USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */
-       { USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */
-       { USB_DEVICE(0x069A, 0x0001) }, /* Askey */
-       { USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */
-       { USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */
-       { USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */
-       { USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom (old model) */
-       { USB_DEVICE(0x046D, 0x08B4) }, /* Logitech QuickCam Zoom (new model) */
-       { USB_DEVICE(0x046D, 0x08B5) }, /* Logitech QuickCam Orbit/Sphere */
-       { USB_DEVICE(0x046D, 0x08B6) }, /* Cisco VT Camera */
-       { USB_DEVICE(0x046D, 0x08B7) }, /* Logitech ViewPort AV 100 */
-       { USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */
-       { USB_DEVICE(0x055D, 0x9000) }, /* Samsung MPC-C10 */
-       { USB_DEVICE(0x055D, 0x9001) }, /* Samsung MPC-C30 */
-       { USB_DEVICE(0x055D, 0x9002) }, /* Samsung SNC-35E (Ver3.0) */
-       { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */
-       { USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */
-       { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */
-       { USB_DEVICE(0x06BE, 0x8116) }, /* new Afina Eye */
-       { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */
-       { USB_DEVICE(0x0d81, 0x1900) },
-       { }
-};
-MODULE_DEVICE_TABLE(usb, pwc_device_table);
-
-static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id);
-static void usb_pwc_disconnect(struct usb_interface *intf);
-static void pwc_isoc_cleanup(struct pwc_device *pdev);
-
-static struct usb_driver pwc_driver = {
-       .name =                 "Philips webcam",       /* name */
-       .id_table =             pwc_device_table,
-       .probe =                usb_pwc_probe,          /* probe() */
-       .disconnect =           usb_pwc_disconnect,     /* disconnect() */
-};
-
-#define MAX_DEV_HINTS  20
-#define MAX_ISOC_ERRORS        20
-
-#ifdef CONFIG_USB_PWC_DEBUG
-       int pwc_trace = PWC_DEBUG_LEVEL;
-#endif
-static int power_save = -1;
-static int leds[2] = { 100, 0 };
-
-/***/
-
-static const struct v4l2_file_operations pwc_fops = {
-       .owner =        THIS_MODULE,
-       .open =         v4l2_fh_open,
-       .release =      vb2_fop_release,
-       .read =         vb2_fop_read,
-       .poll =         vb2_fop_poll,
-       .mmap =         vb2_fop_mmap,
-       .unlocked_ioctl = video_ioctl2,
-};
-static struct video_device pwc_template = {
-       .name =         "Philips Webcam",       /* Filled in later */
-       .release =      video_device_release_empty,
-       .fops =         &pwc_fops,
-       .ioctl_ops =    &pwc_ioctl_ops,
-};
-
-/***************************************************************************/
-/* Private functions */
-
-struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev)
-{
-       unsigned long flags = 0;
-       struct pwc_frame_buf *buf = NULL;
-
-       spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
-       if (list_empty(&pdev->queued_bufs))
-               goto leave;
-
-       buf = list_entry(pdev->queued_bufs.next, struct pwc_frame_buf, list);
-       list_del(&buf->list);
-leave:
-       spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
-       return buf;
-}
-
-static void pwc_snapshot_button(struct pwc_device *pdev, int down)
-{
-       if (down) {
-               PWC_TRACE("Snapshot button pressed.\n");
-       } else {
-               PWC_TRACE("Snapshot button released.\n");
-       }
-
-#ifdef CONFIG_USB_PWC_INPUT_EVDEV
-       if (pdev->button_dev) {
-               input_report_key(pdev->button_dev, KEY_CAMERA, down);
-               input_sync(pdev->button_dev);
-       }
-#endif
-}
-
-static void pwc_frame_complete(struct pwc_device *pdev)
-{
-       struct pwc_frame_buf *fbuf = pdev->fill_buf;
-
-       /* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
-          frames on the USB wire after an exposure change. This conditition is
-          however detected  in the cam and a bit is set in the header.
-          */
-       if (pdev->type == 730) {
-               unsigned char *ptr = (unsigned char *)fbuf->data;
-
-               if (ptr[1] == 1 && ptr[0] & 0x10) {
-                       PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n");
-                       pdev->drop_frames += 2;
-               }
-               if ((ptr[0] ^ pdev->vmirror) & 0x01) {
-                       pwc_snapshot_button(pdev, ptr[0] & 0x01);
-               }
-               if ((ptr[0] ^ pdev->vmirror) & 0x02) {
-                       if (ptr[0] & 0x02)
-                               PWC_TRACE("Image is mirrored.\n");
-                       else
-                               PWC_TRACE("Image is normal.\n");
-               }
-               pdev->vmirror = ptr[0] & 0x03;
-               /* Sometimes the trailer of the 730 is still sent as a 4 byte packet
-                  after a short frame; this condition is filtered out specifically. A 4 byte
-                  frame doesn't make sense anyway.
-                  So we get either this sequence:
-                  drop_bit set -> 4 byte frame -> short frame -> good frame
-                  Or this one:
-                  drop_bit set -> short frame -> good frame
-                  So we drop either 3 or 2 frames in all!
-                  */
-               if (fbuf->filled == 4)
-                       pdev->drop_frames++;
-       } else if (pdev->type == 740 || pdev->type == 720) {
-               unsigned char *ptr = (unsigned char *)fbuf->data;
-               if ((ptr[0] ^ pdev->vmirror) & 0x01) {
-                       pwc_snapshot_button(pdev, ptr[0] & 0x01);
-               }
-               pdev->vmirror = ptr[0] & 0x03;
-       }
-
-       /* In case we were instructed to drop the frame, do so silently. */
-       if (pdev->drop_frames > 0) {
-               pdev->drop_frames--;
-       } else {
-               /* Check for underflow first */
-               if (fbuf->filled < pdev->frame_total_size) {
-                       PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
-                                      " discarded.\n", fbuf->filled);
-               } else {
-                       fbuf->vb.v4l2_buf.field = V4L2_FIELD_NONE;
-                       fbuf->vb.v4l2_buf.sequence = pdev->vframe_count;
-                       vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
-                       pdev->fill_buf = NULL;
-                       pdev->vsync = 0;
-               }
-       } /* !drop_frames */
-       pdev->vframe_count++;
-}
-
-/* This gets called for the Isochronous pipe (video). This is done in
- * interrupt time, so it has to be fast, not crash, and not stall. Neat.
- */
-static void pwc_isoc_handler(struct urb *urb)
-{
-       struct pwc_device *pdev = (struct pwc_device *)urb->context;
-       int i, fst, flen;
-       unsigned char *iso_buf = NULL;
-
-       if (urb->status == -ENOENT || urb->status == -ECONNRESET ||
-           urb->status == -ESHUTDOWN) {
-               PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
-               return;
-       }
-
-       if (pdev->fill_buf == NULL)
-               pdev->fill_buf = pwc_get_next_fill_buf(pdev);
-
-       if (urb->status != 0) {
-               const char *errmsg;
-
-               errmsg = "Unknown";
-               switch(urb->status) {
-                       case -ENOSR:            errmsg = "Buffer error (overrun)"; break;
-                       case -EPIPE:            errmsg = "Stalled (device not responding)"; break;
-                       case -EOVERFLOW:        errmsg = "Babble (bad cable?)"; break;
-                       case -EPROTO:           errmsg = "Bit-stuff error (bad cable?)"; break;
-                       case -EILSEQ:           errmsg = "CRC/Timeout (could be anything)"; break;
-                       case -ETIME:            errmsg = "Device does not respond"; break;
-               }
-               PWC_ERROR("pwc_isoc_handler() called with status %d [%s].\n",
-                         urb->status, errmsg);
-               /* Give up after a number of contiguous errors */
-               if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
-               {
-                       PWC_ERROR("Too many ISOC errors, bailing out.\n");
-                       if (pdev->fill_buf) {
-                               vb2_buffer_done(&pdev->fill_buf->vb,
-                                               VB2_BUF_STATE_ERROR);
-                               pdev->fill_buf = NULL;
-                       }
-               }
-               pdev->vsync = 0; /* Drop the current frame */
-               goto handler_end;
-       }
-
-       /* Reset ISOC error counter. We did get here, after all. */
-       pdev->visoc_errors = 0;
-
-       /* vsync: 0 = don't copy data
-                 1 = sync-hunt
-                 2 = synched
-        */
-       /* Compact data */
-       for (i = 0; i < urb->number_of_packets; i++) {
-               fst  = urb->iso_frame_desc[i].status;
-               flen = urb->iso_frame_desc[i].actual_length;
-               iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-               if (fst != 0) {
-                       PWC_ERROR("Iso frame %d has error %d\n", i, fst);
-                       continue;
-               }
-               if (flen > 0 && pdev->vsync) {
-                       struct pwc_frame_buf *fbuf = pdev->fill_buf;
-
-                       if (pdev->vsync == 1) {
-                               do_gettimeofday(&fbuf->vb.v4l2_buf.timestamp);
-                               pdev->vsync = 2;
-                       }
-
-                       if (flen + fbuf->filled > pdev->frame_total_size) {
-                               PWC_ERROR("Frame overflow (%d > %d)\n",
-                                         flen + fbuf->filled,
-                                         pdev->frame_total_size);
-                               pdev->vsync = 0; /* Let's wait for an EOF */
-                       } else {
-                               memcpy(fbuf->data + fbuf->filled, iso_buf,
-                                      flen);
-                               fbuf->filled += flen;
-                       }
-               }
-               if (flen < pdev->vlast_packet_size) {
-                       /* Shorter packet... end of frame */
-                       if (pdev->vsync == 2)
-                               pwc_frame_complete(pdev);
-                       if (pdev->fill_buf == NULL)
-                               pdev->fill_buf = pwc_get_next_fill_buf(pdev);
-                       if (pdev->fill_buf) {
-                               pdev->fill_buf->filled = 0;
-                               pdev->vsync = 1;
-                       }
-               }
-               pdev->vlast_packet_size = flen;
-       }
-
-handler_end:
-       i = usb_submit_urb(urb, GFP_ATOMIC);
-       if (i != 0)
-               PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
-}
-
-/* Both v4l2_lock and vb_queue_lock should be locked when calling this */
-static int pwc_isoc_init(struct pwc_device *pdev)
-{
-       struct usb_device *udev;
-       struct urb *urb;
-       int i, j, ret;
-       struct usb_interface *intf;
-       struct usb_host_interface *idesc = NULL;
-       int compression = 0; /* 0..3 = uncompressed..high */
-
-       pdev->vsync = 0;
-       pdev->vlast_packet_size = 0;
-       pdev->fill_buf = NULL;
-       pdev->vframe_count = 0;
-       pdev->visoc_errors = 0;
-       udev = pdev->udev;
-
-retry:
-       /* We first try with low compression and then retry with a higher
-          compression setting if there is not enough bandwidth. */
-       ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
-                                pdev->vframes, &compression, 1);
-
-       /* Get the current alternate interface, adjust packet size */
-       intf = usb_ifnum_to_if(udev, 0);
-       if (intf)
-               idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
-       if (!idesc)
-               return -EIO;
-
-       /* Search video endpoint */
-       pdev->vmax_packet_size = -1;
-       for (i = 0; i < idesc->desc.bNumEndpoints; i++) {
-               if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
-                       pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
-                       break;
-               }
-       }
-
-       if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
-               PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n");
-               return -ENFILE; /* Odd error, that should be noticeable */
-       }
-
-       /* Set alternate interface */
-       PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
-       ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
-       if (ret == -ENOSPC && compression < 3) {
-               compression++;
-               goto retry;
-       }
-       if (ret < 0)
-               return ret;
-
-       /* Allocate and init Isochronuous urbs */
-       for (i = 0; i < MAX_ISO_BUFS; i++) {
-               urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
-               if (urb == NULL) {
-                       PWC_ERROR("Failed to allocate urb %d\n", i);
-                       pwc_isoc_cleanup(pdev);
-                       return -ENOMEM;
-               }
-               pdev->urbs[i] = urb;
-               PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
-
-               urb->interval = 1; // devik
-               urb->dev = udev;
-               urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
-               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-               urb->transfer_buffer = usb_alloc_coherent(udev,
-                                                         ISO_BUFFER_SIZE,
-                                                         GFP_KERNEL,
-                                                         &urb->transfer_dma);
-               if (urb->transfer_buffer == NULL) {
-                       PWC_ERROR("Failed to allocate urb buffer %d\n", i);
-                       pwc_isoc_cleanup(pdev);
-                       return -ENOMEM;
-               }
-               urb->transfer_buffer_length = ISO_BUFFER_SIZE;
-               urb->complete = pwc_isoc_handler;
-               urb->context = pdev;
-               urb->start_frame = 0;
-               urb->number_of_packets = ISO_FRAMES_PER_DESC;
-               for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
-                       urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
-                       urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
-               }
-       }
-
-       /* link */
-       for (i = 0; i < MAX_ISO_BUFS; i++) {
-               ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL);
-               if (ret == -ENOSPC && compression < 3) {
-                       compression++;
-                       pwc_isoc_cleanup(pdev);
-                       goto retry;
-               }
-               if (ret) {
-                       PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
-                       pwc_isoc_cleanup(pdev);
-                       return ret;
-               }
-               PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->urbs[i]);
-       }
-
-       /* All is done... */
-       PWC_DEBUG_OPEN("<< pwc_isoc_init()\n");
-       return 0;
-}
-
-static void pwc_iso_stop(struct pwc_device *pdev)
-{
-       int i;
-
-       /* Unlinking ISOC buffers one by one */
-       for (i = 0; i < MAX_ISO_BUFS; i++) {
-               if (pdev->urbs[i]) {
-                       PWC_DEBUG_MEMORY("Unlinking URB %p\n", pdev->urbs[i]);
-                       usb_kill_urb(pdev->urbs[i]);
-               }
-       }
-}
-
-static void pwc_iso_free(struct pwc_device *pdev)
-{
-       int i;
-
-       /* Freeing ISOC buffers one by one */
-       for (i = 0; i < MAX_ISO_BUFS; i++) {
-               if (pdev->urbs[i]) {
-                       PWC_DEBUG_MEMORY("Freeing URB\n");
-                       if (pdev->urbs[i]->transfer_buffer) {
-                               usb_free_coherent(pdev->udev,
-                                       pdev->urbs[i]->transfer_buffer_length,
-                                       pdev->urbs[i]->transfer_buffer,
-                                       pdev->urbs[i]->transfer_dma);
-                       }
-                       usb_free_urb(pdev->urbs[i]);
-                       pdev->urbs[i] = NULL;
-               }
-       }
-}
-
-/* Both v4l2_lock and vb_queue_lock should be locked when calling this */
-static void pwc_isoc_cleanup(struct pwc_device *pdev)
-{
-       PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
-
-       pwc_iso_stop(pdev);
-       pwc_iso_free(pdev);
-       usb_set_interface(pdev->udev, 0, 0);
-
-       PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
-}
-
-/* Must be called with vb_queue_lock hold */
-static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
-{
-       unsigned long flags = 0;
-
-       spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
-       while (!list_empty(&pdev->queued_bufs)) {
-               struct pwc_frame_buf *buf;
-
-               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);
-       }
-       spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
-}
-
-#ifdef CONFIG_USB_PWC_DEBUG
-static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
-{
-       switch(sensor_type) {
-               case 0x00:
-                       return "Hyundai CMOS sensor";
-               case 0x20:
-                       return "Sony CCD sensor + TDA8787";
-               case 0x2E:
-                       return "Sony CCD sensor + Exas 98L59";
-               case 0x2F:
-                       return "Sony CCD sensor + ADI 9804";
-               case 0x30:
-                       return "Sharp CCD sensor + TDA8787";
-               case 0x3E:
-                       return "Sharp CCD sensor + Exas 98L59";
-               case 0x3F:
-                       return "Sharp CCD sensor + ADI 9804";
-               case 0x40:
-                       return "UPA 1021 sensor";
-               case 0x100:
-                       return "VGA sensor";
-               case 0x101:
-                       return "PAL MR sensor";
-               default:
-                       return "unknown type of sensor";
-       }
-}
-#endif
-
-/***************************************************************************/
-/* Video4Linux functions */
-
-static void pwc_video_release(struct v4l2_device *v)
-{
-       struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
-
-       v4l2_ctrl_handler_free(&pdev->ctrl_handler);
-       v4l2_device_unregister(&pdev->v4l2_dev);
-       kfree(pdev->ctrl_buf);
-       kfree(pdev);
-}
-
-/***************************************************************************/
-/* Videobuf2 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 pwc_device *pdev = vb2_get_drv_priv(vq);
-       int size;
-
-       if (*nbuffers < MIN_FRAMES)
-               *nbuffers = MIN_FRAMES;
-       else if (*nbuffers > MAX_FRAMES)
-               *nbuffers = MAX_FRAMES;
-
-       *nplanes = 1;
-
-       size = pwc_get_size(pdev, MAX_WIDTH, MAX_HEIGHT);
-       sizes[0] = PAGE_ALIGN(pwc_image_sizes[size][0] *
-                             pwc_image_sizes[size][1] * 3 / 2);
-
-       return 0;
-}
-
-static int buffer_init(struct vb2_buffer *vb)
-{
-       struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
-
-       /* need vmalloc since frame buffer > 128K */
-       buf->data = vzalloc(PWC_FRAME_SIZE);
-       if (buf->data == NULL)
-               return -ENOMEM;
-
-       return 0;
-}
-
-static int buffer_prepare(struct vb2_buffer *vb)
-{
-       struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
-
-       /* Don't allow queing new buffers after device disconnection */
-       if (!pdev->udev)
-               return -ENODEV;
-
-       return 0;
-}
-
-static int buffer_finish(struct vb2_buffer *vb)
-{
-       struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
-       struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
-
-       /*
-        * Application has called dqbuf and is getting back a buffer we've
-        * filled, take the pwc data we've stored in buf->data and decompress
-        * it into a usable format, storing the result in the vb2_buffer
-        */
-       return pwc_decompress(pdev, buf);
-}
-
-static void buffer_cleanup(struct vb2_buffer *vb)
-{
-       struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
-
-       vfree(buf->data);
-}
-
-static void buffer_queue(struct vb2_buffer *vb)
-{
-       struct pwc_device *pdev = vb2_get_drv_priv(vb->vb2_queue);
-       struct pwc_frame_buf *buf = container_of(vb, struct pwc_frame_buf, vb);
-       unsigned long flags = 0;
-
-       /* Check the device has not disconnected between prep and queuing */
-       if (!pdev->udev) {
-               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-               return;
-       }
-
-       spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
-       list_add_tail(&buf->list, &pdev->queued_bufs);
-       spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
-}
-
-static int start_streaming(struct vb2_queue *vq, unsigned int count)
-{
-       struct pwc_device *pdev = vb2_get_drv_priv(vq);
-       int r;
-
-       if (!pdev->udev)
-               return -ENODEV;
-
-       if (mutex_lock_interruptible(&pdev->v4l2_lock))
-               return -ERESTARTSYS;
-       /* Turn on camera and set LEDS on */
-       pwc_camera_power(pdev, 1);
-       pwc_set_leds(pdev, leds[0], leds[1]);
-
-       r = pwc_isoc_init(pdev);
-       if (r) {
-               /* If we failed turn camera and LEDS back off */
-               pwc_set_leds(pdev, 0, 0);
-               pwc_camera_power(pdev, 0);
-               /* And cleanup any queued bufs!! */
-               pwc_cleanup_queued_bufs(pdev);
-       }
-       mutex_unlock(&pdev->v4l2_lock);
-
-       return r;
-}
-
-static int stop_streaming(struct vb2_queue *vq)
-{
-       struct pwc_device *pdev = vb2_get_drv_priv(vq);
-
-       if (mutex_lock_interruptible(&pdev->v4l2_lock))
-               return -ERESTARTSYS;
-       if (pdev->udev) {
-               pwc_set_leds(pdev, 0, 0);
-               pwc_camera_power(pdev, 0);
-               pwc_isoc_cleanup(pdev);
-       }
-
-       pwc_cleanup_queued_bufs(pdev);
-       mutex_unlock(&pdev->v4l2_lock);
-
-       return 0;
-}
-
-static struct vb2_ops pwc_vb_queue_ops = {
-       .queue_setup            = queue_setup,
-       .buf_init               = buffer_init,
-       .buf_prepare            = buffer_prepare,
-       .buf_finish             = buffer_finish,
-       .buf_cleanup            = buffer_cleanup,
-       .buf_queue              = buffer_queue,
-       .start_streaming        = start_streaming,
-       .stop_streaming         = stop_streaming,
-       .wait_prepare           = vb2_ops_wait_prepare,
-       .wait_finish            = vb2_ops_wait_finish,
-};
-
-/***************************************************************************/
-/* USB functions */
-
-/* This function gets called when a new device is plugged in or the usb core
- * is loaded.
- */
-
-static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-       struct usb_device *udev = interface_to_usbdev(intf);
-       struct pwc_device *pdev = NULL;
-       int vendor_id, product_id, type_id;
-       int rc;
-       int features = 0;
-       int compression = 0;
-       int my_power_save = power_save;
-       char serial_number[30], *name;
-
-       vendor_id = le16_to_cpu(udev->descriptor.idVendor);
-       product_id = le16_to_cpu(udev->descriptor.idProduct);
-
-       /* Check if we can handle this device */
-       PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n",
-               vendor_id, product_id,
-               intf->altsetting->desc.bInterfaceNumber);
-
-       /* the interfaces are probed one by one. We are only interested in the
-          video interface (0) now.
-          Interface 1 is the Audio Control, and interface 2 Audio itself.
-        */
-       if (intf->altsetting->desc.bInterfaceNumber > 0)
-               return -ENODEV;
-
-       if (vendor_id == 0x0471) {
-               switch (product_id) {
-               case 0x0302:
-                       PWC_INFO("Philips PCA645VC USB webcam detected.\n");
-                       name = "Philips 645 webcam";
-                       type_id = 645;
-                       break;
-               case 0x0303:
-                       PWC_INFO("Philips PCA646VC USB webcam detected.\n");
-                       name = "Philips 646 webcam";
-                       type_id = 646;
-                       break;
-               case 0x0304:
-                       PWC_INFO("Askey VC010 type 2 USB webcam detected.\n");
-                       name = "Askey VC010 webcam";
-                       type_id = 646;
-                       break;
-               case 0x0307:
-                       PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n");
-                       name = "Philips 675 webcam";
-                       type_id = 675;
-                       break;
-               case 0x0308:
-                       PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
-                       name = "Philips 680 webcam";
-                       type_id = 680;
-                       break;
-               case 0x030C:
-                       PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
-                       name = "Philips 690 webcam";
-                       type_id = 690;
-                       break;
-               case 0x0310:
-                       PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
-                       name = "Philips 730 webcam";
-                       type_id = 730;
-                       break;
-               case 0x0311:
-                       PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
-                       name = "Philips 740 webcam";
-                       type_id = 740;
-                       break;
-               case 0x0312:
-                       PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
-                       name = "Philips 750 webcam";
-                       type_id = 750;
-                       break;
-               case 0x0313:
-                       PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
-                       name = "Philips 720K/40 webcam";
-                       type_id = 720;
-                       break;
-               case 0x0329:
-                       PWC_INFO("Philips SPC 900NC USB webcam detected.\n");
-                       name = "Philips SPC 900NC webcam";
-                       type_id = 740;
-                       break;
-               default:
-                       return -ENODEV;
-                       break;
-               }
-       }
-       else if (vendor_id == 0x069A) {
-               switch(product_id) {
-               case 0x0001:
-                       PWC_INFO("Askey VC010 type 1 USB webcam detected.\n");
-                       name = "Askey VC010 webcam";
-                       type_id = 645;
-                       break;
-               default:
-                       return -ENODEV;
-                       break;
-               }
-       }
-       else if (vendor_id == 0x046d) {
-               switch(product_id) {
-               case 0x08b0:
-                       PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n");
-                       name = "Logitech QuickCam Pro 3000";
-                       type_id = 740; /* CCD sensor */
-                       break;
-               case 0x08b1:
-                       PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n");
-                       name = "Logitech QuickCam Notebook Pro";
-                       type_id = 740; /* CCD sensor */
-                       break;
-               case 0x08b2:
-                       PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n");
-                       name = "Logitech QuickCam Pro 4000";
-                       type_id = 740; /* CCD sensor */
-                       if (my_power_save == -1)
-                               my_power_save = 1;
-                       break;
-               case 0x08b3:
-                       PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n");
-                       name = "Logitech QuickCam Zoom";
-                       type_id = 740; /* CCD sensor */
-                       break;
-               case 0x08B4:
-                       PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
-                       name = "Logitech QuickCam Zoom";
-                       type_id = 740; /* CCD sensor */
-                       if (my_power_save == -1)
-                               my_power_save = 1;
-                       break;
-               case 0x08b5:
-                       PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
-                       name = "Logitech QuickCam Orbit";
-                       type_id = 740; /* CCD sensor */
-                       if (my_power_save == -1)
-                               my_power_save = 1;
-                       features |= FEATURE_MOTOR_PANTILT;
-                       break;
-               case 0x08b6:
-                       PWC_INFO("Logitech/Cisco VT Camera webcam detected.\n");
-                       name = "Cisco VT Camera";
-                       type_id = 740; /* CCD sensor */
-                       break;
-               case 0x08b7:
-                       PWC_INFO("Logitech ViewPort AV 100 webcam detected.\n");
-                       name = "Logitech ViewPort AV 100";
-                       type_id = 740; /* CCD sensor */
-                       break;
-               case 0x08b8: /* Where this released? */
-                       PWC_INFO("Logitech QuickCam detected (reserved ID).\n");
-                       name = "Logitech QuickCam (res.)";
-                       type_id = 730; /* Assuming CMOS */
-                       break;
-               default:
-                       return -ENODEV;
-                       break;
-               }
-       }
-       else if (vendor_id == 0x055d) {
-               /* I don't know the difference between the C10 and the C30;
-                  I suppose the difference is the sensor, but both cameras
-                  work equally well with a type_id of 675
-                */
-               switch(product_id) {
-               case 0x9000:
-                       PWC_INFO("Samsung MPC-C10 USB webcam detected.\n");
-                       name = "Samsung MPC-C10";
-                       type_id = 675;
-                       break;
-               case 0x9001:
-                       PWC_INFO("Samsung MPC-C30 USB webcam detected.\n");
-                       name = "Samsung MPC-C30";
-                       type_id = 675;
-                       break;
-               case 0x9002:
-                       PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n");
-                       name = "Samsung MPC-C30";
-                       type_id = 740;
-                       break;
-               default:
-                       return -ENODEV;
-                       break;
-               }
-       }
-       else if (vendor_id == 0x041e) {
-               switch(product_id) {
-               case 0x400c:
-                       PWC_INFO("Creative Labs Webcam 5 detected.\n");
-                       name = "Creative Labs Webcam 5";
-                       type_id = 730;
-                       if (my_power_save == -1)
-                               my_power_save = 1;
-                       break;
-               case 0x4011:
-                       PWC_INFO("Creative Labs Webcam Pro Ex detected.\n");
-                       name = "Creative Labs Webcam Pro Ex";
-                       type_id = 740;
-                       break;
-               default:
-                       return -ENODEV;
-                       break;
-               }
-       }
-       else if (vendor_id == 0x04cc) {
-               switch(product_id) {
-               case 0x8116:
-                       PWC_INFO("Sotec Afina Eye USB webcam detected.\n");
-                       name = "Sotec Afina Eye";
-                       type_id = 730;
-                       break;
-               default:
-                       return -ENODEV;
-                       break;
-               }
-       }
-       else if (vendor_id == 0x06be) {
-               switch(product_id) {
-               case 0x8116:
-                       /* This is essentially the same cam as the Sotec Afina Eye */
-                       PWC_INFO("AME Co. Afina Eye USB webcam detected.\n");
-                       name = "AME Co. Afina Eye";
-                       type_id = 750;
-                       break;
-               default:
-                       return -ENODEV;
-                       break;
-               }
-
-       }
-       else if (vendor_id == 0x0d81) {
-               switch(product_id) {
-               case 0x1900:
-                       PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n");
-                       name = "Visionite VCS-UC300";
-                       type_id = 740; /* CCD sensor */
-                       break;
-               case 0x1910:
-                       PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n");
-                       name = "Visionite VCS-UM100";
-                       type_id = 730; /* CMOS sensor */
-                       break;
-               default:
-                       return -ENODEV;
-                       break;
-               }
-       }
-       else
-               return -ENODEV; /* Not any of the know types; but the list keeps growing. */
-
-       if (my_power_save == -1)
-               my_power_save = 0;
-
-       memset(serial_number, 0, 30);
-       usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
-       PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
-
-       if (udev->descriptor.bNumConfigurations > 1)
-               PWC_WARNING("Warning: more than 1 configuration available.\n");
-
-       /* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
-       pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL);
-       if (pdev == NULL) {
-               PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
-               return -ENOMEM;
-       }
-       pdev->type = type_id;
-       pdev->features = features;
-       pwc_construct(pdev); /* set min/max sizes correct */
-
-       mutex_init(&pdev->v4l2_lock);
-       mutex_init(&pdev->vb_queue_lock);
-       spin_lock_init(&pdev->queued_bufs_lock);
-       INIT_LIST_HEAD(&pdev->queued_bufs);
-
-       pdev->udev = udev;
-       pdev->power_save = my_power_save;
-
-       /* Init videobuf2 queue structure */
-       memset(&pdev->vb_queue, 0, sizeof(pdev->vb_queue));
-       pdev->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       pdev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
-       pdev->vb_queue.drv_priv = pdev;
-       pdev->vb_queue.buf_struct_size = sizeof(struct pwc_frame_buf);
-       pdev->vb_queue.ops = &pwc_vb_queue_ops;
-       pdev->vb_queue.mem_ops = &vb2_vmalloc_memops;
-       vb2_queue_init(&pdev->vb_queue);
-
-       /* Init video_device structure */
-       memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
-       strcpy(pdev->vdev.name, name);
-       pdev->vdev.queue = &pdev->vb_queue;
-       pdev->vdev.queue->lock = &pdev->vb_queue_lock;
-       set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags);
-       video_set_drvdata(&pdev->vdev, pdev);
-
-       pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
-       PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
-
-       /* Allocate USB command buffers */
-       pdev->ctrl_buf = kmalloc(sizeof(pdev->cmd_buf), GFP_KERNEL);
-       if (!pdev->ctrl_buf) {
-               PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
-               rc = -ENOMEM;
-               goto err_free_mem;
-       }
-
-#ifdef CONFIG_USB_PWC_DEBUG
-       /* Query sensor type */
-       if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
-               PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
-                               pdev->vdev.name,
-                               pwc_sensor_type_to_string(rc), rc);
-       }
-#endif
-
-       /* Set the leds off */
-       pwc_set_leds(pdev, 0, 0);
-
-       /* Setup intial videomode */
-       rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT,
-                               V4L2_PIX_FMT_YUV420, 30, &compression, 1);
-       if (rc)
-               goto err_free_mem;
-
-       /* Register controls (and read default values from camera */
-       rc = pwc_init_controls(pdev);
-       if (rc) {
-               PWC_ERROR("Failed to register v4l2 controls (%d).\n", rc);
-               goto err_free_mem;
-       }
-
-       /* And powerdown the camera until streaming starts */
-       pwc_camera_power(pdev, 0);
-
-       /* Register the v4l2_device structure */
-       pdev->v4l2_dev.release = pwc_video_release;
-       rc = v4l2_device_register(&intf->dev, &pdev->v4l2_dev);
-       if (rc) {
-               PWC_ERROR("Failed to register v4l2-device (%d).\n", rc);
-               goto err_free_controls;
-       }
-
-       pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
-       pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
-       pdev->vdev.lock = &pdev->v4l2_lock;
-
-       rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, -1);
-       if (rc < 0) {
-               PWC_ERROR("Failed to register as video device (%d).\n", rc);
-               goto err_unregister_v4l2_dev;
-       }
-       PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
-
-#ifdef CONFIG_USB_PWC_INPUT_EVDEV
-       /* register webcam snapshot button input device */
-       pdev->button_dev = input_allocate_device();
-       if (!pdev->button_dev) {
-               PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
-               rc = -ENOMEM;
-               goto err_video_unreg;
-       }
-
-       usb_make_path(udev, pdev->button_phys, sizeof(pdev->button_phys));
-       strlcat(pdev->button_phys, "/input0", sizeof(pdev->button_phys));
-
-       pdev->button_dev->name = "PWC snapshot button";
-       pdev->button_dev->phys = pdev->button_phys;
-       usb_to_input_id(pdev->udev, &pdev->button_dev->id);
-       pdev->button_dev->dev.parent = &pdev->udev->dev;
-       pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY);
-       pdev->button_dev->keybit[BIT_WORD(KEY_CAMERA)] = BIT_MASK(KEY_CAMERA);
-
-       rc = input_register_device(pdev->button_dev);
-       if (rc) {
-               input_free_device(pdev->button_dev);
-               pdev->button_dev = NULL;
-               goto err_video_unreg;
-       }
-#endif
-
-       return 0;
-
-err_video_unreg:
-       video_unregister_device(&pdev->vdev);
-err_unregister_v4l2_dev:
-       v4l2_device_unregister(&pdev->v4l2_dev);
-err_free_controls:
-       v4l2_ctrl_handler_free(&pdev->ctrl_handler);
-err_free_mem:
-       kfree(pdev->ctrl_buf);
-       kfree(pdev);
-       return rc;
-}
-
-/* The user yanked out the cable... */
-static void usb_pwc_disconnect(struct usb_interface *intf)
-{
-       struct v4l2_device *v = usb_get_intfdata(intf);
-       struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
-
-       mutex_lock(&pdev->vb_queue_lock);
-       mutex_lock(&pdev->v4l2_lock);
-       /* No need to keep the urbs around after disconnection */
-       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);
-       mutex_unlock(&pdev->v4l2_lock);
-       mutex_unlock(pdev->vb_queue.lock);
-
-#ifdef CONFIG_USB_PWC_INPUT_EVDEV
-       if (pdev->button_dev)
-               input_unregister_device(pdev->button_dev);
-#endif
-
-       v4l2_device_put(&pdev->v4l2_dev);
-}
-
-
-/*
- * Initialization code & module stuff
- */
-
-static unsigned int leds_nargs;
-
-#ifdef CONFIG_USB_PWC_DEBUG
-module_param_named(trace, pwc_trace, int, 0644);
-#endif
-module_param(power_save, int, 0644);
-module_param_array(leds, int, &leds_nargs, 0444);
-
-#ifdef CONFIG_USB_PWC_DEBUG
-MODULE_PARM_DESC(trace, "For debugging purposes");
-#endif
-MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
-MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
-
-MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
-MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("pwcx");
-MODULE_VERSION( PWC_VERSION );
-
-module_usb_driver(pwc_driver);
diff --git a/drivers/media/video/pwc/pwc-kiara.c b/drivers/media/video/pwc/pwc-kiara.c
deleted file mode 100644 (file)
index e5f4fd8..0000000
+++ /dev/null
@@ -1,892 +0,0 @@
-/* Linux driver for Philips webcam
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-
-/* This tables contains entries for the 730/740/750 (Kiara) camera, with
-   4 different qualities (no compression, low, medium, high).
-   It lists the bandwidth requirements for said mode by its alternate interface
-   number. An alternate of 0 means that the mode is unavailable.
-
-   There are 6 * 4 * 4 entries:
-     6 different resolutions subqcif, qsif, qcif, sif, cif, vga
-     6 framerates: 5, 10, 15, 20, 25, 30
-     4 compression modi: none, low, medium, high
-
-   When an uncompressed mode is not available, the next available compressed mode
-   will be chosen (unless the decompressor is absent). Sometimes there are only
-   1 or 2 compressed modes available; in that case entries are duplicated.
-*/
-
-
-#include "pwc-kiara.h"
-
-const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA] = { 5, 10, 15, 20, 25, 30 };
-
-const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
-{
-   /* SQCIF */
-   {
-      /* 5 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 10 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 15 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 20 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 25 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 30 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-   },
-   /* QSIF */
-   {
-      /* 5 fps */
-      {
-        {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
-        {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
-        {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
-        {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
-      },
-      /* 10 fps */
-      {
-        {2, 291,    0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}},
-        {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
-        {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
-        {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
-      },
-      /* 15 fps */
-      {
-        {3, 437,    0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}},
-        {2, 292,  640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
-        {2, 292,  640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
-        {1, 192,  420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
-      },
-      /* 20 fps */
-      {
-        {4, 589,    0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}},
-        {3, 448,  730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}},
-        {2, 292,  476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}},
-        {1, 192,  312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
-      },
-      /* 25 fps */
-      {
-        {5, 703,    0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}},
-        {3, 447,  610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}},
-        {2, 292,  398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}},
-        {1, 193,  262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}},
-      },
-      /* 30 fps */
-      {
-        {8, 874,    0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}},
-        {5, 704,  730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}},
-        {3, 448,  492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}},
-        {2, 292,  320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}},
-      },
-   },
-   /* QCIF */
-   {
-      /* 5 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 10 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 15 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 20 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 25 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 30 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-   },
-   /* SIF */
-   {
-      /* 5 fps */
-      {
-        {4, 582,    0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}},
-        {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}},
-        {2, 291,  960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}},
-        {1, 191,  630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}},
-      },
-      /* 10 fps */
-      {
-        {0, },
-        {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}},
-        {3, 447,  736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}},
-        {2, 292,  480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}},
-      },
-      /* 15 fps */
-      {
-        {0, },
-        {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}},
-        {4, 592,  650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}},
-        {3, 448,  492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}},
-      },
-      /* 20 fps */
-      {
-        {0, },
-        {9, 958,  782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}},
-        {5, 703,  574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}},
-        {3, 446,  364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}},
-      },
-      /* 25 fps */
-      {
-        {0, },
-        {9, 958,  654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}},
-        {6, 776,  530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}},
-        {4, 592,  404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}},
-      },
-      /* 30 fps */
-      {
-        {0, },
-        {9, 957,  526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}},
-        {6, 775,  426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}},
-        {4, 590,  324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}},
-      },
-   },
-   /* CIF */
-   {
-      /* 5 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 10 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 15 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 20 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 25 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 30 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-   },
-   /* VGA */
-   {
-      /* 5 fps */
-      {
-        {0, },
-        {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}},
-        {4, 592,  976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}},
-        {3, 448,  738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}},
-      },
-      /* 10 fps */
-      {
-        {0, },
-        {9, 956,  788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}},
-        {6, 776,  640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}},
-        {4, 592,  488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}},
-      },
-      /* 15 fps */
-      {
-        {0, },
-        {9, 957,  526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
-        {9, 957,  526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
-        {8, 895,  492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}},
-      },
-      /* 20 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 25 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 30 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-   },
-};
-
-
-/*
- * Rom table for kiara chips
- *
- * 32 roms tables (one for each resolution ?)
- *  2 tables per roms (one for each passes) (Y, and U&V)
- * 128 bytes per passes
- */
-
-const unsigned int KiaraRomTable [8][2][16][8] =
-{
- { /* version 0 */
-  { /* version 0, passes 0 */
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000001,0x00000001},
-   {0x00000000,0x00000000,0x00000009,0x00000009,
-    0x00000009,0x00000009,0x00000009,0x00000009},
-   {0x00000000,0x00000000,0x00000009,0x00000049,
-    0x00000049,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000249,0x0000024a,0x00000049},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000249,0x00000249,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00000049,0x00000249,
-    0x00000249,0x0000124a,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00000049,0x00000249,
-    0x0000124a,0x00009252,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00009252,0x00009292,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x00009292,0x00009292,0x00009493,0x000124db},
-   {0x00000000,0x00000000,0x00000249,0x0000924a,
-    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
-   {0x00000000,0x00000000,0x00001249,0x00009252,
-    0x0000a493,0x000124db,0x000124db,0x000126dc},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x000124db,0x000126dc,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000124db,0x000136e4,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 0, passes 1 */
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000},
-   {0x00000000,0x00000000,0x00000001,0x00000009,
-    0x00000009,0x00000009,0x00000009,0x00000001},
-   {0x00000000,0x00000000,0x00000009,0x00000009,
-    0x00000049,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000249,0x00000249,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00000049,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x00001252},
-   {0x00000000,0x00000000,0x00000049,0x00001249,
-    0x0000124a,0x0000124a,0x00001252,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x00009252,0x00009252,0x00009292,0x00009493},
-   {0x00000000,0x00000000,0x00000249,0x0000924a,
-    0x00009292,0x00009292,0x00009292,0x00009493},
-   {0x00000000,0x00000000,0x00000249,0x00009292,
-    0x00009492,0x00009493,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x0000a493,0x000124db,0x000126dc,0x000126dc},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x00009252,0x00009493,
-    0x000126dc,0x000126dc,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000136e4,0x000136e4,0x0001b725,0x0001b724},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 1 */
-  { /* version 1, passes 0 */
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000001},
-   {0x00000000,0x00000000,0x00000009,0x00000009,
-    0x00000009,0x00000009,0x00000009,0x00000009},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000249,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00000049,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x00001252},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x0000124a,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x0000124a,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x0000124a,0x00009252,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x00009252,0x00009292,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x00009252,0x00009292,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00000249,0x0000924a,
-    0x00009252,0x00009493,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00000249,0x0000924a,
-    0x00009292,0x00009493,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00000249,0x00009252,
-    0x00009492,0x00009493,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x000124db,0x000124db,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000126dc,0x000126dc,0x000126dc},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 1, passes 1 */
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000},
-   {0x00000000,0x00000000,0x00000049,0x00000009,
-    0x00000049,0x00000009,0x00000001,0x00000000},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000049,0x00000000},
-   {0x00000000,0x00000000,0x00000249,0x00000049,
-    0x00000249,0x00000049,0x0000024a,0x00000001},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x00000001},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x00000001},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x00000009},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x0000124a,0x0000024a,0x00000009},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x0000124a,0x0000024a,0x00000009},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x00009252,0x00001252,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x00009292,0x00001252,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x00009292,0x00001252,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00001252,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009292,0x00009292,0x00001252,0x0000024a},
-   {0x00000000,0x00000000,0x0000924a,0x0000924a,
-    0x00009492,0x00009493,0x00009292,0x00001252},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 2 */
-  { /* version 2, passes 0 */
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x0000124a,0x00001252,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x00009252,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x0000124a,0x00009292,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x00009252,0x00009493,0x00009493,0x0000a49b},
-   {0x00000000,0x00000000,0x00000249,0x0000924a,
-    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009292,0x00009493,0x0000a49b,0x000124db},
-   {0x00000000,0x00000000,0x00001249,0x00009252,
-    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x000124db,0x000124db,0x000126dc},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x0000a493,0x000124db,0x000126dc,0x000126dc},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x000136e4},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000136e4,0x000136e4,0x0001b724},
-   {0x00000000,0x00000000,0x00009252,0x000124db,
-    0x000126dc,0x0001b724,0x0001b725,0x0001b925},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 2, passes 1 */
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00000249,
-    0x0000124a,0x0000124a,0x00001252,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x0000124a,0x00009292,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00009292,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x0000a49b,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009292,0x00009493,0x0000a49b,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009292,0x00009493,0x0000a49b,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009492,0x0000a49b,0x0000a49b,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00009252,
-    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x00009252,0x0000a49b,
-    0x0001249b,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 3 */
-  { /* version 3, passes 0 */
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x0000124a,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x000124db,0x000126dc,0x000126dc},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x000126dc},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000126dc,0x000136e4,0x0001b724},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000136e4,0x0001b725,0x0001b724},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000136e4,0x0001b725,0x0001b925},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 3, passes 1 */
-   {0x00000000,0x00000000,0x00001249,0x00000249,
-    0x0000124a,0x0000124a,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00009292,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009492,0x00009493,0x0000a49b,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00009252,
-    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x0000a49b,0x000126dc,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00009492,0x0000a49b,
-    0x000136e4,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x0001b724,0x0001b724,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 4 */
-  { /* version 4, passes 0 */
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00000249,0x00000049,
-    0x00000249,0x00000249,0x0000024a,0x00000049},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x00009252,0x00001252,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00009493,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009292,0x00009493,0x00009493,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000124db,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0001249b,0x000126dc,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00009252,0x00009493,
-    0x000124db,0x000136e4,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00009252,0x0000a49b,
-    0x000124db,0x000136e4,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x00009492,0x0000a49b,
-    0x000126dc,0x0001b724,0x0001b725,0x0001b724},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 4, passes 1 */
-   {0x00000000,0x00000000,0x00000249,0x00000049,
-    0x00000009,0x00000009,0x00000009,0x00000009},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000049,0x00000049,0x00000009,0x00000009},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x00000249,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x0000124a,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x0000124a,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009252,0x0000124a,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x00009252,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x00009292,0x00009292,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x00009292,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x00009493,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00009252,0x000124db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 5 */
-  { /* version 5, passes 0 */
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x00000249,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00009292,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x0000a49b,0x000124db,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x0001b724,0x0001b725,0x000136e4},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
-   {0x00000000,0x00000000,0x00009492,0x0000a49b,
-    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 5, passes 1 */
-   {0x00000000,0x00000000,0x00001249,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x0000124a,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009252,0x00009252,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x0000a49b,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x0000a49b,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x0000a49b,0x00009292,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000124db,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000124db,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000126dc,0x000126dc,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00009292,0x000124db,
-    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00009492,0x000126db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 6 */
-  { /* version 6, passes 0 */
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
-   {0x00000000,0x00000000,0x00009492,0x0000a49b,
-    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
-   {0x00000000,0x00000000,0x00012492,0x000126db,
-    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 6, passes 1 */
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x0000124a,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x00009252,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x00009292,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x0000a49b,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000124db,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000126dc,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00009492,0x000126db,
-    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00009492,0x000126db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00009492,0x000126db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 7 */
-  { /* version 7, passes 0 */
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x0000a49b,
-    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x000136e4,0x0001b725,0x000124db},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
-   {0x00000000,0x00000000,0x00009292,0x000124db,
-    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
-   {0x00000000,0x00000000,0x00012492,0x000136db,
-    0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 7, passes 1 */
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x0000124a,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x00009492,0x00009292,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x0000a49b,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000126dc,0x000124db,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000136e4,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000136db,
-    0x0001b724,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000136db,
-    0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00009292,0x000136db,
-    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00009492,0x000136db,
-    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00012492,0x0001b6db,
-    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- }
-};
-
diff --git a/drivers/media/video/pwc/pwc-kiara.h b/drivers/media/video/pwc/pwc-kiara.h
deleted file mode 100644 (file)
index 8e02b7a..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Linux driver for Philips webcam
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-/* Entries for the Kiara (730/740/750) camera */
-
-#ifndef PWC_KIARA_H
-#define PWC_KIARA_H
-
-#include "pwc.h"
-
-#define PWC_FPS_MAX_KIARA 6
-
-struct Kiara_table_entry
-{
-       char alternate;                 /* USB alternate interface */
-       unsigned short packetsize;      /* Normal packet size */
-       unsigned short bandlength;      /* Bandlength when decompressing */
-       unsigned char mode[12];         /* precomputed mode settings for cam */
-};
-
-extern const struct Kiara_table_entry Kiara_table[PSZ_MAX][PWC_FPS_MAX_KIARA][4];
-extern const unsigned int KiaraRomTable[8][2][16][8];
-extern const unsigned int Kiara_fps_vector[PWC_FPS_MAX_KIARA];
-
-#endif
-
-
diff --git a/drivers/media/video/pwc/pwc-misc.c b/drivers/media/video/pwc/pwc-misc.c
deleted file mode 100644 (file)
index 9be5adf..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/* Linux driver for Philips webcam
-   Various miscellaneous functions and tables.
-   (C) 1999-2003 Nemosoft Unv.
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-
-#include "pwc.h"
-
-const int pwc_image_sizes[PSZ_MAX][2] =
-{
-       { 128,  96 }, /* sqcif */
-       { 160, 120 }, /* qsif */
-       { 176, 144 }, /* qcif */
-       { 320, 240 }, /* sif */
-       { 352, 288 }, /* cif */
-       { 640, 480 }, /* vga */
-};
-
-/* x,y -> PSZ_ */
-int pwc_get_size(struct pwc_device *pdev, int width, int height)
-{
-       int i;
-
-       /* Find the largest size supported by the camera that fits into the
-          requested size. */
-       for (i = PSZ_MAX - 1; i >= 0; i--) {
-               if (!(pdev->image_mask & (1 << i)))
-                       continue;
-
-               if (pwc_image_sizes[i][0] <= width &&
-                   pwc_image_sizes[i][1] <= height)
-                       return i;
-       }
-
-       /* No mode found, return the smallest mode we have */
-       for (i = 0; i < PSZ_MAX; i++) {
-               if (pdev->image_mask & (1 << i))
-                       return i;
-       }
-
-       /* Never reached there always is atleast one supported mode */
-       return 0;
-}
-
-/* initialize variables depending on type and decompressor */
-void pwc_construct(struct pwc_device *pdev)
-{
-       if (DEVICE_USE_CODEC1(pdev->type)) {
-
-               pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
-               pdev->vcinterface = 2;
-               pdev->vendpoint = 4;
-               pdev->frame_header_size = 0;
-               pdev->frame_trailer_size = 0;
-
-       } else if (DEVICE_USE_CODEC3(pdev->type)) {
-
-               pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
-               pdev->vcinterface = 3;
-               pdev->vendpoint = 5;
-               pdev->frame_header_size = TOUCAM_HEADER_SIZE;
-               pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
-
-       } else /* if (DEVICE_USE_CODEC2(pdev->type)) */ {
-
-               pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
-               pdev->vcinterface = 3;
-               pdev->vendpoint = 4;
-               pdev->frame_header_size = 0;
-               pdev->frame_trailer_size = 0;
-       }
-}
diff --git a/drivers/media/video/pwc/pwc-nala.h b/drivers/media/video/pwc/pwc-nala.h
deleted file mode 100644 (file)
index 168c73e..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-   /* SQCIF */
-   {
-      {0, 0, {0x04, 0x01, 0x03}},
-      {8, 0, {0x05, 0x01, 0x03}},
-      {7, 0, {0x08, 0x01, 0x03}},
-      {7, 0, {0x0A, 0x01, 0x03}},
-      {6, 0, {0x0C, 0x01, 0x03}},
-      {5, 0, {0x0F, 0x01, 0x03}},
-      {4, 0, {0x14, 0x01, 0x03}},
-      {3, 0, {0x18, 0x01, 0x03}},
-   },
-   /* QSIF */
-   {
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-   },
-   /* QCIF */
-   {
-      {0, 0, {0x04, 0x01, 0x02}},
-      {8, 0, {0x05, 0x01, 0x02}},
-      {7, 0, {0x08, 0x01, 0x02}},
-      {6, 0, {0x0A, 0x01, 0x02}},
-      {5, 0, {0x0C, 0x01, 0x02}},
-      {4, 0, {0x0F, 0x01, 0x02}},
-      {1, 0, {0x14, 0x01, 0x02}},
-      {1, 0, {0x18, 0x01, 0x02}},
-   },
-   /* SIF */
-   {
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-   },
-   /* CIF */
-   {
-      {4, 0, {0x04, 0x01, 0x01}},
-      {7, 1, {0x05, 0x03, 0x01}},
-      {6, 1, {0x08, 0x03, 0x01}},
-      {4, 1, {0x0A, 0x03, 0x01}},
-      {3, 1, {0x0C, 0x03, 0x01}},
-      {2, 1, {0x0F, 0x03, 0x01}},
-      {0},
-      {0},
-   },
-   /* VGA */
-   {
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-      {0},
-   },
diff --git a/drivers/media/video/pwc/pwc-timon.c b/drivers/media/video/pwc/pwc-timon.c
deleted file mode 100644 (file)
index c56c174..0000000
+++ /dev/null
@@ -1,1448 +0,0 @@
-/* Linux driver for Philips webcam
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-
-/* This tables contains entries for the 675/680/690 (Timon) camera, with
-   4 different qualities (no compression, low, medium, high).
-   It lists the bandwidth requirements for said mode by its alternate interface
-   number. An alternate of 0 means that the mode is unavailable.
-
-   There are 6 * 4 * 4 entries:
-     6 different resolutions subqcif, qsif, qcif, sif, cif, vga
-     6 framerates: 5, 10, 15, 20, 25, 30
-     4 compression modi: none, low, medium, high
-
-   When an uncompressed mode is not available, the next available compressed mode
-   will be chosen (unless the decompressor is absent). Sometimes there are only
-   1 or 2 compressed modes available; in that case entries are duplicated.
-*/
-
-#include "pwc-timon.h"
-
-const unsigned int Timon_fps_vector[PWC_FPS_MAX_TIMON] = { 5, 10, 15, 20, 25, 30 };
-
-const struct Timon_table_entry Timon_table[PSZ_MAX][PWC_FPS_MAX_TIMON][4] =
-{
-   /* SQCIF */
-   {
-      /* 5 fps */
-      {
-        {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
-        {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
-        {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
-        {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
-      },
-      /* 10 fps */
-      {
-        {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
-        {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
-        {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
-        {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
-      },
-      /* 15 fps */
-      {
-        {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
-        {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
-        {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
-        {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
-      },
-      /* 20 fps */
-      {
-        {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
-        {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
-        {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
-        {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
-      },
-      /* 25 fps */
-      {
-        {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
-        {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
-        {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
-        {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
-      },
-      /* 30 fps */
-      {
-        {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
-        {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
-        {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
-        {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
-      },
-   },
-   /* QSIF */
-   {
-      /* 5 fps */
-      {
-        {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
-        {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
-        {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
-        {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
-      },
-      /* 10 fps */
-      {
-        {2, 291,    0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}},
-        {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
-        {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
-        {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
-      },
-      /* 15 fps */
-      {
-        {3, 437,    0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}},
-        {2, 291,  640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
-        {2, 291,  640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
-        {1, 191,  420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
-      },
-      /* 20 fps */
-      {
-        {4, 588,    0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}},
-        {3, 447,  730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
-        {2, 292,  476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
-        {1, 192,  312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
-      },
-      /* 25 fps */
-      {
-        {5, 703,    0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}},
-        {3, 447,  610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
-        {2, 292,  398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
-        {1, 192,  262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
-      },
-      /* 30 fps */
-      {
-        {8, 873,    0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}},
-        {5, 704,  774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}},
-        {3, 448,  492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}},
-        {2, 291,  320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
-      },
-   },
-   /* QCIF */
-   {
-      /* 5 fps */
-      {
-        {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
-        {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
-        {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
-        {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
-      },
-      /* 10 fps */
-      {
-        {3, 385,    0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}},
-        {2, 291,  800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
-        {2, 291,  800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
-        {1, 194,  532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}},
-      },
-      /* 15 fps */
-      {
-        {4, 577,    0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}},
-        {3, 447,  818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}},
-        {2, 292,  534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}},
-        {1, 195,  356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}},
-      },
-      /* 20 fps */
-      {
-        {6, 776,    0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}},
-        {4, 591,  804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}},
-        {3, 447,  608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
-        {2, 291,  396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
-      },
-      /* 25 fps */
-      {
-        {9, 928,    0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}},
-        {5, 703,  800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}},
-        {3, 447,  508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
-        {2, 292,  332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
-      },
-      /* 30 fps */
-      {
-        {0, },
-        {9, 956,  876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}},
-        {4, 592,  542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}},
-        {2, 291,  266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}},
-      },
-   },
-   /* SIF */
-   {
-      /* 5 fps */
-      {
-        {4, 582,    0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}},
-        {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}},
-        {2, 291,  960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}},
-        {1, 191,  630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}},
-      },
-      /* 10 fps */
-      {
-        {0, },
-        {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}},
-        {3, 447,  736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}},
-        {2, 291,  480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}},
-      },
-      /* 15 fps */
-      {
-        {0, },
-        {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}},
-        {4, 591,  650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}},
-        {3, 448,  492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}},
-      },
-      /* 20 fps */
-      {
-        {0, },
-        {9, 958,  782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}},
-        {5, 703,  574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}},
-        {3, 446,  364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}},
-      },
-      /* 25 fps */
-      {
-        {0, },
-        {9, 958,  654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}},
-        {6, 776,  530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}},
-        {4, 592,  404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}},
-      },
-      /* 30 fps */
-      {
-        {0, },
-        {9, 957,  526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}},
-        {6, 775,  426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}},
-        {4, 590,  324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}},
-      },
-   },
-   /* CIF */
-   {
-      /* 5 fps */
-      {
-        {6, 771,    0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}},
-        {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}},
-        {2, 291,  800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}},
-        {1, 193,  528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}},
-      },
-      /* 10 fps */
-      {
-        {0, },
-        {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}},
-        {4, 591,  812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}},
-        {2, 291,  400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}},
-      },
-      /* 15 fps */
-      {
-        {0, },
-        {9, 956,  876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}},
-        {5, 703,  644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}},
-        {3, 448,  410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}},
-      },
-      /* 20 fps */
-      {
-        {0, },
-        {9, 956,  650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}},
-        {6, 776,  528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}},
-        {4, 591,  402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}},
-      },
-      /* 25 fps */
-      {
-        {0, },
-        {9, 956,  544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}},
-        {7, 840,  478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}},
-        {5, 703,  400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}},
-      },
-      /* 30 fps */
-      {
-        {0, },
-        {9, 956,  438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}},
-        {7, 838,  384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}},
-        {6, 773,  354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}},
-      },
-   },
-   /* VGA */
-   {
-      /* 5 fps */
-      {
-        {0, },
-        {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}},
-        {4, 592,  976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}},
-        {3, 448,  738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}},
-      },
-      /* 10 fps */
-      {
-        {0, },
-        {9, 956,  788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}},
-        {6, 776,  640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}},
-        {4, 592,  488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}},
-      },
-      /* 15 fps */
-      {
-        {0, },
-        {9, 957,  526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
-        {9, 957,  526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
-        {8, 895,  492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}},
-      },
-      /* 20 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 25 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-      /* 30 fps */
-      {
-        {0, },
-        {0, },
-        {0, },
-        {0, },
-      },
-   },
-};
-
-/*
- * 16 versions:
- *   2 tables  (one for Y, and one for U&V)
- *   16 levels of details per tables
- *   8 blocs
- */
-
-const unsigned int TimonRomTable [16][2][16][8] =
-{
- { /* version 0 */
-  { /* version 0, passes 0 */
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000001},
-   {0x00000000,0x00000000,0x00000001,0x00000001,
-    0x00000001,0x00000001,0x00000001,0x00000001},
-   {0x00000000,0x00000000,0x00000001,0x00000001,
-    0x00000001,0x00000009,0x00000009,0x00000009},
-   {0x00000000,0x00000000,0x00000009,0x00000001,
-    0x00000009,0x00000009,0x00000009,0x00000009},
-   {0x00000000,0x00000000,0x00000009,0x00000009,
-    0x00000009,0x00000009,0x00000049,0x00000009},
-   {0x00000000,0x00000000,0x00000009,0x00000009,
-    0x00000009,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00000009,0x00000009,
-    0x00000049,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00000009,0x00000049,
-    0x00000049,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000249,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000249,0x00000249,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000249,0x00000249,0x00001252,0x0000024a},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000249,0x0000124a,0x00001252,0x0000024a},
-   {0x00000000,0x00000000,0x00000049,0x00000249,
-    0x00000249,0x0000124a,0x00001252,0x0000024a},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x0000124a,0x00009252,0x00009292,0x00001252},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 0, passes 1 */
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000},
-   {0x00000000,0x00000000,0x00000001,0x00000001,
-    0x00000001,0x00000001,0x00000000,0x00000000},
-   {0x00000000,0x00000000,0x00000009,0x00000001,
-    0x00000001,0x00000009,0x00000000,0x00000000},
-   {0x00000000,0x00000000,0x00000009,0x00000009,
-    0x00000009,0x00000009,0x00000000,0x00000000},
-   {0x00000000,0x00000000,0x00000009,0x00000009,
-    0x00000009,0x00000009,0x00000001,0x00000000},
-   {0x00000000,0x00000000,0x00000049,0x00000009,
-    0x00000009,0x00000049,0x00000001,0x00000001},
-   {0x00000000,0x00000000,0x00000049,0x00000009,
-    0x00000009,0x00000049,0x00000001,0x00000001},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000009,0x00000001},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000009,0x00000001},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000009,0x00000001},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000009,0x00000009},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000249,0x00000049,0x00000009},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000249,0x00000049,0x00000009},
-   {0x00000000,0x00000000,0x00000249,0x00000049,
-    0x00000249,0x00000249,0x00000049,0x00000009},
-   {0x00000000,0x00000000,0x00001249,0x00000249,
-    0x0000124a,0x0000124a,0x0000024a,0x00000049},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 1 */
-  { /* version 1, passes 0 */
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000001},
-   {0x00000000,0x00000000,0x00000001,0x00000001,
-    0x00000001,0x00000009,0x00000009,0x00000009},
-   {0x00000000,0x00000000,0x00000009,0x00000009,
-    0x00000009,0x00000009,0x00000009,0x00000009},
-   {0x00000000,0x00000000,0x00000009,0x00000009,
-    0x00000009,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00000009,0x00000049,
-    0x00000049,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000249,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000249,0x00000249,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00000049,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x00001252},
-   {0x00000000,0x00000000,0x00000049,0x00000249,
-    0x00000249,0x0000124a,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x00000049,0x00000249,
-    0x0000124a,0x0000124a,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x0000124a,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x0000124a,0x00009252,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x00009252,0x00009252,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x0000924a,
-    0x00009292,0x00009493,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x00009252,
-    0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 1, passes 1 */
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000},
-   {0x00000000,0x00000000,0x00000009,0x00000009,
-    0x00000009,0x00000001,0x00000001,0x00000000},
-   {0x00000000,0x00000000,0x00000009,0x00000009,
-    0x00000009,0x00000009,0x00000001,0x00000000},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000009,0x00000001,0x00000000},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000001,0x00000001},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000009,0x00000001},
-   {0x00000000,0x00000000,0x00000249,0x00000049,
-    0x00000049,0x00000249,0x00000009,0x00000001},
-   {0x00000000,0x00000000,0x00000249,0x00000049,
-    0x00000249,0x00000249,0x00000009,0x00000009},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x00000249,0x00000049,0x00000009},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x0000124a,0x00000049,0x00000009},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x0000124a,0x00000049,0x00000009},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x0000124a,0x0000024a,0x00000049},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x0000124a,0x0000024a,0x00000049},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x0000124a,0x0000024a,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009252,0x00001252,0x0000024a},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 2 */
-  { /* version 2, passes 0 */
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000001},
-   {0x00000000,0x00000000,0x00000009,0x00000009,
-    0x00000009,0x00000009,0x00000009,0x00000009},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000249,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00000049,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x00001252},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x0000124a,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x0000124a,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x0000124a,0x00009252,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x00009252,0x00009292,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x00009252,0x00009292,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00000249,0x0000924a,
-    0x00009252,0x00009493,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00000249,0x0000924a,
-    0x00009292,0x00009493,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00000249,0x00009252,
-    0x00009492,0x00009493,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x000124db,0x000124db,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000126dc,0x000126dc,0x000126dc},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 2, passes 1 */
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000},
-   {0x00000000,0x00000000,0x00000049,0x00000009,
-    0x00000049,0x00000009,0x00000001,0x00000000},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000049,0x00000000},
-   {0x00000000,0x00000000,0x00000249,0x00000049,
-    0x00000249,0x00000049,0x0000024a,0x00000001},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x00000001},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x00000001},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x00000009},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x0000124a,0x0000024a,0x00000009},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x0000124a,0x0000024a,0x00000009},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x00009252,0x00001252,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x00009292,0x00001252,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x00009292,0x00001252,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00001252,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009292,0x00009292,0x00001252,0x0000024a},
-   {0x00000000,0x00000000,0x0000924a,0x0000924a,
-    0x00009492,0x00009493,0x00009292,0x00001252},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 3 */
-  { /* version 3, passes 0 */
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000001},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00000049,0x00000249,
-    0x00000249,0x00000249,0x00001252,0x0000024a},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x0000124a,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x00009252,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x0000124a,0x00009292,0x00009292,0x00009493},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x00009252,0x00009292,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x00009292,0x00009493,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00000249,0x00009252,
-    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00001249,0x00009252,
-    0x00009292,0x0000a49b,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00001249,0x00009252,
-    0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x0000a49b,0x000124db,0x000124db},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x0000a493,0x0000a49b,0x000124db,0x000124db},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0001249b,0x000126dc,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000136e4,0x0001b725,0x000136e4},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 3, passes 1 */
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000},
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000001,0x00000000},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x00000249,0x00000049,0x00000001},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x0000124a,0x00001252,0x00000001},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x0000124a,0x00001252,0x00000009},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x0000124a,0x00009252,0x00009292,0x00000009},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x00009252,0x00009292,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009252,0x00009292,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009493,0x00009292,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009493,0x00009292,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009493,0x00009493,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009292,0x00009493,0x00009493,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009492,0x00009493,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009252,
-    0x00009492,0x0000a49b,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x00009292,
-    0x0000a493,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 4 */
-  { /* version 4, passes 0 */
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x0000124a,0x00001252,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x00009252,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x0000124a,0x00009292,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x00009252,0x00009493,0x00009493,0x0000a49b},
-   {0x00000000,0x00000000,0x00000249,0x0000924a,
-    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009292,0x00009493,0x0000a49b,0x000124db},
-   {0x00000000,0x00000000,0x00001249,0x00009252,
-    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x000124db,0x000124db,0x000126dc},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x0000a493,0x000124db,0x000126dc,0x000126dc},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x000136e4},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000136e4,0x000136e4,0x0001b724},
-   {0x00000000,0x00000000,0x00009252,0x000124db,
-    0x000126dc,0x0001b724,0x0001b725,0x0001b925},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 4, passes 1 */
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00000249,
-    0x0000124a,0x0000124a,0x00001252,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x0000124a,0x00009292,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00009292,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x0000a49b,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009292,0x00009493,0x0000a49b,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009292,0x00009493,0x0000a49b,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009492,0x0000a49b,0x0000a49b,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00009252,
-    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x00009252,0x0000a49b,
-    0x0001249b,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 5 */
-  { /* version 5, passes 0 */
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x0000124a,0x00001252,0x00009292},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x0000124a,0x00009292,0x00009292,0x00009493},
-   {0x00000000,0x00000000,0x00000249,0x0000924a,
-    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x0000a49b,0x000124db,0x000124db},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x0000a493,0x000124db,0x000124db,0x000126dc},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x000126dc},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0001249b,0x000126dc,0x0001b725,0x0001b724},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000126dc,0x0001b725,0x0001b724},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b724,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 5, passes 1 */
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x00000249,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x0000124a,0x00001252,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009292,0x00009493,0x00009493,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009292,0x00009493,0x00009493,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009292,0x00009493,0x0000a49b,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009492,0x00009493,0x000124db,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x00009493,0x000124db,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x0000a49b,0x000124db,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x0000a49b,0x000124db,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000124db,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x000124db,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x000124db,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00009252,0x000124db,
-    0x000126dc,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 6 */
-  { /* version 6, passes 0 */
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x0000124a,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x000124db,0x000126dc,0x000126dc},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x000126dc},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000126dc,0x000136e4,0x0001b724},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000136e4,0x0001b725,0x0001b724},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000136e4,0x0001b725,0x0001b925},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 6, passes 1 */
-   {0x00000000,0x00000000,0x00001249,0x00000249,
-    0x0000124a,0x0000124a,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00009292,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009492,0x00009493,0x0000a49b,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00009252,
-    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x0000a49b,0x000126dc,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00009492,0x0000a49b,
-    0x000136e4,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x0001b724,0x0001b724,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 7 */
-  { /* version 7, passes 0 */
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009292,0x00009493,0x0000a49b,0x000124db},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x0000a493,0x0000a49b,0x000124db,0x000126dc},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x000136e4},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x00001249,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000136e4,0x0001b725,0x0001b724},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x000136e4,0x0001b725,0x0001b925},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x00009292,0x000124db,
-    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b724,0x0001c96e,0x0002496e},
-   {0x00000000,0x00000000,0x00009492,0x000126db,
-    0x000136e4,0x0001b925,0x0001c96e,0x0002496e},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b724,0x0002496d,0x00025bb6,0x00025bbf},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 7, passes 1 */
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009492,0x00009493,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x0000a49b,0x000124db,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x000124db,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x000124db,0x000136e4,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x000124db,0x000136e4,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000124db,0x000136e4,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x000136e4,0x000136e4,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x000136e4,0x000136e4,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000136e4,0x000136e4,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x000136e4,0x0001b724,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00012492,0x000126db,
-    0x0001b724,0x0001b925,0x0001b725,0x000136e4},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 8 */
-  { /* version 8, passes 0 */
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009292,0x00009493,0x0000a49b,0x000124db},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x0000a493,0x000124db,0x000126dc,0x000126dc},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x000136e4},
-   {0x00000000,0x00000000,0x00001249,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000136e4,0x0001b725,0x0001b724},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x000136e4,0x0001b725,0x0001b925},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
-   {0x00000000,0x00000000,0x00009252,0x000124db,
-    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
-   {0x00000000,0x00000000,0x00009292,0x000124db,
-    0x000126dc,0x0001b925,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b925,0x00024b76,0x00024b77},
-   {0x00000000,0x00000000,0x00009492,0x000126db,
-    0x000136e4,0x0001b925,0x00024b76,0x00025bbf},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x000136e4,0x0001c92d,0x00024b76,0x00025bbf},
-   {0x00000000,0x00000000,0x00012492,0x000136db,
-    0x0001b724,0x00024b6d,0x0002ddb6,0x0002efff},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 8, passes 1 */
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009493,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x0000a49b,0x000124db,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x000124db,0x000136e4,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x000126dc,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x00009292,0x000124db,
-    0x000136e4,0x0001b724,0x0001b725,0x000136e4},
-   {0x00000000,0x00000000,0x00009492,0x000126db,
-    0x000136e4,0x0001b925,0x0001b725,0x0001b724},
-   {0x00000000,0x00000000,0x00009492,0x000126db,
-    0x000136e4,0x0001b925,0x0001b725,0x0001b724},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b724,0x0002496d,0x0001b92d,0x0001b925},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 9 */
-  { /* version 9, passes 0 */
-   {0x00000000,0x00000000,0x00000049,0x00000049,
-    0x00000049,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00000249,0x00000049,
-    0x00000249,0x00000249,0x0000024a,0x00000049},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x0000124a,0x00009252,0x00001252,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00009493,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009292,0x00009493,0x00009493,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000124db,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0001249b,0x000126dc,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00009252,0x00009493,
-    0x000124db,0x000136e4,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00009252,0x0000a49b,
-    0x000124db,0x000136e4,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x00009492,0x0000a49b,
-    0x000126dc,0x0001b724,0x0001b725,0x0001b724},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 9, passes 1 */
-   {0x00000000,0x00000000,0x00000249,0x00000049,
-    0x00000009,0x00000009,0x00000009,0x00000009},
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000049,0x00000049,0x00000009,0x00000009},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x00000249,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x0000124a,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x0000124a,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009252,0x0000124a,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x00009252,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x00009292,0x00009292,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x00009292,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x00009493,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00009252,0x000124db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 10 */
-  { /* version 10, passes 0 */
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00000249,0x00001249,
-    0x00009252,0x00009292,0x00009292,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00009292,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009492,0x00009493,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x000124db,0x000124db,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000124db,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0001249b,0x000126dc,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000126dc,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00009252,0x0000a49b,
-    0x000124db,0x000136e4,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x00009492,0x0000a49b,
-    0x000126dc,0x0001b724,0x0001b92d,0x0001b724},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000126dc,0x0001b925,0x0001b92d,0x0001b925},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x000136e4,0x0002496d,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 10, passes 1 */
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000049,0x00000049,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x00000249,0x00000049,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x00009252,0x0000024a,0x00000049},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009493,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00009252,
-    0x00009492,0x00009493,0x00001252,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x00009493,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x00009492,0x00009493,0x00009292,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x00009493,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x0000a49b,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x0000a49b,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00009252,0x000126db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 11 */
-  { /* version 11, passes 0 */
-   {0x00000000,0x00000000,0x00000249,0x00000249,
-    0x00000249,0x00000249,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00009292,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x0000a49b,0x000124db,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x0001b724,0x0001b725,0x000136e4},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
-   {0x00000000,0x00000000,0x00009492,0x0000a49b,
-    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 11, passes 1 */
-   {0x00000000,0x00000000,0x00001249,0x00000249,
-    0x00000249,0x00000249,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x0000124a,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009252,0x00009252,0x0000024a,0x0000024a},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x0000a49b,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x0000a49b,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x0000a49b,0x00009292,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000124db,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000124db,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000126dc,0x000126dc,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00009292,0x000124db,
-    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00009492,0x000126db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 12 */
-  { /* version 12, passes 0 */
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
-   {0x00000000,0x00000000,0x00009492,0x0000a49b,
-    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
-   {0x00000000,0x00000000,0x00012492,0x000126db,
-    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 12, passes 1 */
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x0000124a,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x00001249,0x00009292,
-    0x00009492,0x00009252,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x00009292,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x0000a49b,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000124db,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000124db,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000126dc,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00009492,0x000126db,
-    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00009492,0x000126db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00009492,0x000126db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 13 */
-  { /* version 13, passes 0 */
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x00009252,0x00009292,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x000124db,0x000126dc,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x0000a49b,
-    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x000136e4,0x0001b725,0x000124db},
-   {0x00000000,0x00000000,0x00009292,0x0000a49b,
-    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
-   {0x00000000,0x00000000,0x00009292,0x000124db,
-    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
-   {0x00000000,0x00000000,0x00012492,0x000136db,
-    0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 13, passes 1 */
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x0000124a,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x00009492,0x00009292,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x0000a49b,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000126dc,0x000124db,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000136e4,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000136db,
-    0x0001b724,0x000124db,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000136db,
-    0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00009292,0x000136db,
-    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x00009492,0x000136db,
-    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00012492,0x0001b6db,
-    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 14 */
-  { /* version 14, passes 0 */
-   {0x00000000,0x00000000,0x00001249,0x0000924a,
-    0x00009292,0x00009493,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00001249,0x0000a49b,
-    0x0000a493,0x000124db,0x000126dc,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000126dc,0x000136e4,0x0001b725,0x000124db},
-   {0x00000000,0x00000000,0x00009292,0x000124db,
-    0x000126dc,0x0001b724,0x0001b92d,0x000126dc},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001c92d,0x0001c96e,0x000136e4},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x0001b724,0x0001c92d,0x00024b76,0x0001b925},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b924,0x0002496d,0x00024b76,0x00024b77},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b924,0x00024b6d,0x0002ddb6,0x00025bbf},
-   {0x00000000,0x00000000,0x00012492,0x0001b6db,
-    0x00024924,0x0002db6d,0x00036db6,0x0002efff},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 14, passes 1 */
-   {0x00000000,0x00000000,0x00001249,0x00001249,
-    0x0000124a,0x0000124a,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x00009493,
-    0x0000a493,0x00009292,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x0000a49b,0x00001252,0x00001252},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000136e4,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000136e4,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000136e4,0x000136e4,0x00009493,0x00009292},
-   {0x00000000,0x00000000,0x00009492,0x000136db,
-    0x0001b724,0x000136e4,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x00009492,0x000136db,
-    0x0001b724,0x000136e4,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x00009492,0x000136db,
-    0x0001b724,0x000136e4,0x0000a49b,0x00009493},
-   {0x00000000,0x00000000,0x00009492,0x000136db,
-    0x0001b724,0x000136e4,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b724,0x000136e4,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b724,0x000136e4,0x000124db,0x0000a49b},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b724,0x000136e4,0x000126dc,0x000124db},
-   {0x00000000,0x00000000,0x00012492,0x0001b6db,
-    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- },
- { /* version 15 */
-  { /* version 15, passes 0 */
-   {0x00000000,0x00000000,0x00001249,0x00009493,
-    0x0000a493,0x0000a49b,0x000124db,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0001249b,0x000126dc,0x000136e4,0x000124db},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x000136e4,0x0001b925,0x0001c96e,0x000136e4},
-   {0x00000000,0x00000000,0x00009492,0x000124db,
-    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
-   {0x00000000,0x00000000,0x0000a492,0x000124db,
-    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
-   {0x00000000,0x00000000,0x0000a492,0x000126db,
-    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001b924,0x0002496d,0x00024b76,0x0002496e},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001c924,0x00024b6d,0x00025bb6,0x00024b77},
-   {0x00000000,0x00000000,0x00012492,0x000136db,
-    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
-   {0x00000000,0x00000000,0x00012492,0x0001b6db,
-    0x00024924,0x0002db6d,0x00036db6,0x0002efff},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  },
-  { /* version 15, passes 1 */
-   {0x00000000,0x00000000,0x0000924a,0x0000924a,
-    0x00009292,0x00009292,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
-    0x0000a493,0x000124db,0x00009292,0x00009292},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000124db,0x0001b724,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000126dc,0x0001b724,0x00009493,0x00009493},
-   {0x00000000,0x00000000,0x0000924a,0x000124db,
-    0x000136e4,0x0001b724,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00009292,0x000136db,
-    0x0001b724,0x0001b724,0x0000a49b,0x0000a49b},
-   {0x00000000,0x00000000,0x00009492,0x000136db,
-    0x0001c924,0x0001b724,0x000124db,0x000124db},
-   {0x00000000,0x00000000,0x00009492,0x000136db,
-    0x0001c924,0x0001b724,0x000124db,0x000124db},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001c924,0x0001b724,0x000126dc,0x000126dc},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001c924,0x0001b925,0x000126dc,0x000126dc},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001c924,0x0001b925,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001c924,0x0001b925,0x000136e4,0x000136e4},
-   {0x00000000,0x00000000,0x0000a492,0x000136db,
-    0x0001c924,0x0001b925,0x0001b725,0x0001b724},
-   {0x00000000,0x00000000,0x00012492,0x000136db,
-    0x0001c924,0x0001b925,0x0001b725,0x0001b724},
-   {0x00000000,0x00000000,0x00012492,0x0001b6db,
-    0x00024924,0x0002496d,0x0001b92d,0x0001b925},
-   {0x00000000,0x00000000,0x00000000,0x00000000,
-    0x00000000,0x00000000,0x00000000,0x00000000}
-  }
- }
-};
diff --git a/drivers/media/video/pwc/pwc-timon.h b/drivers/media/video/pwc/pwc-timon.h
deleted file mode 100644 (file)
index 270c5b9..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Linux driver for Philips webcam
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-
-
-/* This tables contains entries for the 675/680/690 (Timon) camera, with
-   4 different qualities (no compression, low, medium, high).
-   It lists the bandwidth requirements for said mode by its alternate interface
-   number. An alternate of 0 means that the mode is unavailable.
-
-   There are 6 * 4 * 4 entries:
-     6 different resolutions subqcif, qsif, qcif, sif, cif, vga
-     6 framerates: 5, 10, 15, 20, 25, 30
-     4 compression modi: none, low, medium, high
-
-   When an uncompressed mode is not available, the next available compressed mode
-   will be chosen (unless the decompressor is absent). Sometimes there are only
-   1 or 2 compressed modes available; in that case entries are duplicated.
-*/
-
-#ifndef PWC_TIMON_H
-#define PWC_TIMON_H
-
-#include "pwc.h"
-
-#define PWC_FPS_MAX_TIMON 6
-
-struct Timon_table_entry
-{
-       char alternate;                 /* USB alternate interface */
-       unsigned short packetsize;      /* Normal packet size */
-       unsigned short bandlength;      /* Bandlength when decompressing */
-       unsigned char mode[13];         /* precomputed mode settings for cam */
-};
-
-extern const struct Timon_table_entry Timon_table[PSZ_MAX][PWC_FPS_MAX_TIMON][4];
-extern const unsigned int TimonRomTable [16][2][16][8];
-extern const unsigned int Timon_fps_vector[PWC_FPS_MAX_TIMON];
-
-#endif
-
-
diff --git a/drivers/media/video/pwc/pwc-uncompress.c b/drivers/media/video/pwc/pwc-uncompress.c
deleted file mode 100644 (file)
index b65903f..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/* Linux driver for Philips webcam
-   Decompression frontend.
-   (C) 1999-2003 Nemosoft Unv.
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-   vim: set ts=8:
-*/
-
-#include <asm/current.h>
-#include <asm/types.h>
-
-#include "pwc.h"
-#include "pwc-dec1.h"
-#include "pwc-dec23.h"
-
-int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf)
-{
-       int n, line, col;
-       void *yuv, *image;
-       u16 *src;
-       u16 *dsty, *dstu, *dstv;
-
-       image = vb2_plane_vaddr(&fbuf->vb, 0);
-
-       yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
-
-       /* Raw format; that's easy... */
-       if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
-       {
-               struct pwc_raw_frame *raw_frame = image;
-               raw_frame->type = cpu_to_le16(pdev->type);
-               raw_frame->vbandlength = cpu_to_le16(pdev->vbandlength);
-                       /* cmd_buf is always 4 bytes, but sometimes, only the
-                        * first 3 bytes is filled (Nala case). We can
-                        * determine this using the type of the webcam */
-               memcpy(raw_frame->cmd, pdev->cmd_buf, 4);
-               memcpy(raw_frame+1, yuv, pdev->frame_size);
-               vb2_set_plane_payload(&fbuf->vb, 0,
-                       pdev->frame_size + sizeof(struct pwc_raw_frame));
-               return 0;
-       }
-
-       vb2_set_plane_payload(&fbuf->vb, 0,
-                             pdev->width * pdev->height * 3 / 2);
-
-       if (pdev->vbandlength == 0) {
-               /* Uncompressed mode.
-                *
-                * We do some byte shuffling here to go from the
-                * native format to YUV420P.
-                */
-               src = (u16 *)yuv;
-               n = pdev->width * pdev->height;
-               dsty = (u16 *)(image);
-               dstu = (u16 *)(image + n);
-               dstv = (u16 *)(image + n + n / 4);
-
-               for (line = 0; line < pdev->height; line++) {
-                       for (col = 0; col < pdev->width; col += 4) {
-                               *dsty++ = *src++;
-                               *dsty++ = *src++;
-                               if (line & 1)
-                                       *dstv++ = *src++;
-                               else
-                                       *dstu++ = *src++;
-                       }
-               }
-
-               return 0;
-       }
-
-       /*
-        * Compressed;
-        * the decompressor routines will write the data in planar format
-        * immediately.
-        */
-       if (DEVICE_USE_CODEC1(pdev->type)) {
-
-               /* TODO & FIXME */
-               PWC_ERROR("This chipset is not supported for now\n");
-               return -ENXIO; /* No such device or address: missing decompressor */
-
-       } else {
-               pwc_dec23_decompress(pdev, yuv, image);
-       }
-       return 0;
-}
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
deleted file mode 100644 (file)
index 545e9bb..0000000
+++ /dev/null
@@ -1,1053 +0,0 @@
-/* Linux driver for Philips webcam
-   USB and Video4Linux interface part.
-   (C) 1999-2004 Nemosoft Unv.
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-   (C) 2011 Hans de Goede <hdegoede@redhat.com>
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-*/
-
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/vmalloc.h>
-#include <linux/jiffies.h>
-#include <asm/io.h>
-
-#include "pwc.h"
-
-#define PWC_CID_CUSTOM(ctrl) ((V4L2_CID_USER_BASE | 0xf000) + custom_ ## ctrl)
-
-static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl);
-static int pwc_s_ctrl(struct v4l2_ctrl *ctrl);
-
-static const struct v4l2_ctrl_ops pwc_ctrl_ops = {
-       .g_volatile_ctrl = pwc_g_volatile_ctrl,
-       .s_ctrl = pwc_s_ctrl,
-};
-
-enum { awb_indoor, awb_outdoor, awb_fl, awb_manual, awb_auto };
-enum { custom_autocontour, custom_contour, custom_noise_reduction,
-       custom_awb_speed, custom_awb_delay,
-       custom_save_user, custom_restore_user, custom_restore_factory };
-
-const char * const pwc_auto_whitebal_qmenu[] = {
-       "Indoor (Incandescant Lighting) Mode",
-       "Outdoor (Sunlight) Mode",
-       "Indoor (Fluorescent Lighting) Mode",
-       "Manual Mode",
-       "Auto Mode",
-       NULL
-};
-
-static const struct v4l2_ctrl_config pwc_auto_white_balance_cfg = {
-       .ops    = &pwc_ctrl_ops,
-       .id     = V4L2_CID_AUTO_WHITE_BALANCE,
-       .type   = V4L2_CTRL_TYPE_MENU,
-       .max    = awb_auto,
-       .qmenu  = pwc_auto_whitebal_qmenu,
-};
-
-static const struct v4l2_ctrl_config pwc_autocontour_cfg = {
-       .ops    = &pwc_ctrl_ops,
-       .id     = PWC_CID_CUSTOM(autocontour),
-       .type   = V4L2_CTRL_TYPE_BOOLEAN,
-       .name   = "Auto contour",
-       .min    = 0,
-       .max    = 1,
-       .step   = 1,
-};
-
-static const struct v4l2_ctrl_config pwc_contour_cfg = {
-       .ops    = &pwc_ctrl_ops,
-       .id     = PWC_CID_CUSTOM(contour),
-       .type   = V4L2_CTRL_TYPE_INTEGER,
-       .name   = "Contour",
-       .flags  = V4L2_CTRL_FLAG_SLIDER,
-       .min    = 0,
-       .max    = 63,
-       .step   = 1,
-};
-
-static const struct v4l2_ctrl_config pwc_backlight_cfg = {
-       .ops    = &pwc_ctrl_ops,
-       .id     = V4L2_CID_BACKLIGHT_COMPENSATION,
-       .type   = V4L2_CTRL_TYPE_BOOLEAN,
-       .min    = 0,
-       .max    = 1,
-       .step   = 1,
-};
-
-static const struct v4l2_ctrl_config pwc_flicker_cfg = {
-       .ops    = &pwc_ctrl_ops,
-       .id     = V4L2_CID_BAND_STOP_FILTER,
-       .type   = V4L2_CTRL_TYPE_BOOLEAN,
-       .min    = 0,
-       .max    = 1,
-       .step   = 1,
-};
-
-static const struct v4l2_ctrl_config pwc_noise_reduction_cfg = {
-       .ops    = &pwc_ctrl_ops,
-       .id     = PWC_CID_CUSTOM(noise_reduction),
-       .type   = V4L2_CTRL_TYPE_INTEGER,
-       .name   = "Dynamic Noise Reduction",
-       .min    = 0,
-       .max    = 3,
-       .step   = 1,
-};
-
-static const struct v4l2_ctrl_config pwc_save_user_cfg = {
-       .ops    = &pwc_ctrl_ops,
-       .id     = PWC_CID_CUSTOM(save_user),
-       .type   = V4L2_CTRL_TYPE_BUTTON,
-       .name    = "Save User Settings",
-};
-
-static const struct v4l2_ctrl_config pwc_restore_user_cfg = {
-       .ops    = &pwc_ctrl_ops,
-       .id     = PWC_CID_CUSTOM(restore_user),
-       .type   = V4L2_CTRL_TYPE_BUTTON,
-       .name    = "Restore User Settings",
-};
-
-static const struct v4l2_ctrl_config pwc_restore_factory_cfg = {
-       .ops    = &pwc_ctrl_ops,
-       .id     = PWC_CID_CUSTOM(restore_factory),
-       .type   = V4L2_CTRL_TYPE_BUTTON,
-       .name    = "Restore Factory Settings",
-};
-
-static const struct v4l2_ctrl_config pwc_awb_speed_cfg = {
-       .ops    = &pwc_ctrl_ops,
-       .id     = PWC_CID_CUSTOM(awb_speed),
-       .type   = V4L2_CTRL_TYPE_INTEGER,
-       .name   = "Auto White Balance Speed",
-       .min    = 1,
-       .max    = 32,
-       .step   = 1,
-};
-
-static const struct v4l2_ctrl_config pwc_awb_delay_cfg = {
-       .ops    = &pwc_ctrl_ops,
-       .id     = PWC_CID_CUSTOM(awb_delay),
-       .type   = V4L2_CTRL_TYPE_INTEGER,
-       .name   = "Auto White Balance Delay",
-       .min    = 0,
-       .max    = 63,
-       .step   = 1,
-};
-
-int pwc_init_controls(struct pwc_device *pdev)
-{
-       struct v4l2_ctrl_handler *hdl;
-       struct v4l2_ctrl_config cfg;
-       int r, def;
-
-       hdl = &pdev->ctrl_handler;
-       r = v4l2_ctrl_handler_init(hdl, 20);
-       if (r)
-               return r;
-
-       /* Brightness, contrast, saturation, gamma */
-       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, BRIGHTNESS_FORMATTER, &def);
-       if (r || def > 127)
-               def = 63;
-       pdev->brightness = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
-                               V4L2_CID_BRIGHTNESS, 0, 127, 1, def);
-
-       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, CONTRAST_FORMATTER, &def);
-       if (r || def > 63)
-               def = 31;
-       pdev->contrast = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
-                               V4L2_CID_CONTRAST, 0, 63, 1, def);
-
-       if (pdev->type >= 675) {
-               if (pdev->type < 730)
-                       pdev->saturation_fmt = SATURATION_MODE_FORMATTER2;
-               else
-                       pdev->saturation_fmt = SATURATION_MODE_FORMATTER1;
-               r = pwc_get_s8_ctrl(pdev, GET_CHROM_CTL, pdev->saturation_fmt,
-                                   &def);
-               if (r || def < -100 || def > 100)
-                       def = 0;
-               pdev->saturation = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
-                                     V4L2_CID_SATURATION, -100, 100, 1, def);
-       }
-
-       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, GAMMA_FORMATTER, &def);
-       if (r || def > 31)
-               def = 15;
-       pdev->gamma = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
-                               V4L2_CID_GAMMA, 0, 31, 1, def);
-
-       /* auto white balance, red gain, blue gain */
-       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, WB_MODE_FORMATTER, &def);
-       if (r || def > awb_auto)
-               def = awb_auto;
-       cfg = pwc_auto_white_balance_cfg;
-       cfg.name = v4l2_ctrl_get_name(cfg.id);
-       cfg.def = def;
-       pdev->auto_white_balance = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
-       /* check auto controls to avoid NULL deref in v4l2_ctrl_auto_cluster */
-       if (!pdev->auto_white_balance)
-               return hdl->error;
-
-       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
-                           PRESET_MANUAL_RED_GAIN_FORMATTER, &def);
-       if (r)
-               def = 127;
-       pdev->red_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
-                               V4L2_CID_RED_BALANCE, 0, 255, 1, def);
-
-       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
-                           PRESET_MANUAL_BLUE_GAIN_FORMATTER, &def);
-       if (r)
-               def = 127;
-       pdev->blue_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
-                               V4L2_CID_BLUE_BALANCE, 0, 255, 1, def);
-
-       v4l2_ctrl_auto_cluster(3, &pdev->auto_white_balance, awb_manual, true);
-
-       /* autogain, gain */
-       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AGC_MODE_FORMATTER, &def);
-       if (r || (def != 0 && def != 0xff))
-               def = 0;
-       /* Note a register value if 0 means auto gain is on */
-       pdev->autogain = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
-                               V4L2_CID_AUTOGAIN, 0, 1, 1, def == 0);
-       if (!pdev->autogain)
-               return hdl->error;
-
-       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, PRESET_AGC_FORMATTER, &def);
-       if (r || def > 63)
-               def = 31;
-       pdev->gain = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
-                               V4L2_CID_GAIN, 0, 63, 1, def);
-
-       /* auto exposure, exposure */
-       if (DEVICE_USE_CODEC2(pdev->type)) {
-               r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, SHUTTER_MODE_FORMATTER,
-                                   &def);
-               if (r || (def != 0 && def != 0xff))
-                       def = 0;
-               /*
-                * def = 0 auto, def = ff manual
-                * menu idx 0 = auto, idx 1 = manual
-                */
-               pdev->exposure_auto = v4l2_ctrl_new_std_menu(hdl,
-                                       &pwc_ctrl_ops,
-                                       V4L2_CID_EXPOSURE_AUTO,
-                                       1, 0, def != 0);
-               if (!pdev->exposure_auto)
-                       return hdl->error;
-
-               /* GET_LUM_CTL, PRESET_SHUTTER_FORMATTER is unreliable */
-               r = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
-                                    READ_SHUTTER_FORMATTER, &def);
-               if (r || def > 655)
-                       def = 655;
-               pdev->exposure = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
-                                       V4L2_CID_EXPOSURE, 0, 655, 1, def);
-               /* CODEC2: separate auto gain & auto exposure */
-               v4l2_ctrl_auto_cluster(2, &pdev->autogain, 0, true);
-               v4l2_ctrl_auto_cluster(2, &pdev->exposure_auto,
-                                      V4L2_EXPOSURE_MANUAL, true);
-       } else if (DEVICE_USE_CODEC3(pdev->type)) {
-               /* GET_LUM_CTL, PRESET_SHUTTER_FORMATTER is unreliable */
-               r = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
-                                    READ_SHUTTER_FORMATTER, &def);
-               if (r || def > 255)
-                       def = 255;
-               pdev->exposure = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
-                                       V4L2_CID_EXPOSURE, 0, 255, 1, def);
-               /* CODEC3: both gain and exposure controlled by autogain */
-               pdev->autogain_expo_cluster[0] = pdev->autogain;
-               pdev->autogain_expo_cluster[1] = pdev->gain;
-               pdev->autogain_expo_cluster[2] = pdev->exposure;
-               v4l2_ctrl_auto_cluster(3, pdev->autogain_expo_cluster,
-                                      0, true);
-       }
-
-       /* color / bw setting */
-       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, COLOUR_MODE_FORMATTER,
-                        &def);
-       if (r || (def != 0 && def != 0xff))
-               def = 0xff;
-       /* def = 0 bw, def = ff color, menu idx 0 = color, idx 1 = bw */
-       pdev->colorfx = v4l2_ctrl_new_std_menu(hdl, &pwc_ctrl_ops,
-                               V4L2_CID_COLORFX, 1, 0, def == 0);
-
-       /* autocontour, contour */
-       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &def);
-       if (r || (def != 0 && def != 0xff))
-               def = 0;
-       cfg = pwc_autocontour_cfg;
-       cfg.def = def == 0;
-       pdev->autocontour = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
-       if (!pdev->autocontour)
-               return hdl->error;
-
-       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, &def);
-       if (r || def > 63)
-               def = 31;
-       cfg = pwc_contour_cfg;
-       cfg.def = def;
-       pdev->contour = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
-
-       v4l2_ctrl_auto_cluster(2, &pdev->autocontour, 0, false);
-
-       /* backlight */
-       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
-                           BACK_LIGHT_COMPENSATION_FORMATTER, &def);
-       if (r || (def != 0 && def != 0xff))
-               def = 0;
-       cfg = pwc_backlight_cfg;
-       cfg.name = v4l2_ctrl_get_name(cfg.id);
-       cfg.def = def == 0;
-       pdev->backlight = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
-
-       /* flikker rediction */
-       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
-                           FLICKERLESS_MODE_FORMATTER, &def);
-       if (r || (def != 0 && def != 0xff))
-               def = 0;
-       cfg = pwc_flicker_cfg;
-       cfg.name = v4l2_ctrl_get_name(cfg.id);
-       cfg.def = def == 0;
-       pdev->flicker = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
-
-       /* Dynamic noise reduction */
-       r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL,
-                           DYNAMIC_NOISE_CONTROL_FORMATTER, &def);
-       if (r || def > 3)
-               def = 2;
-       cfg = pwc_noise_reduction_cfg;
-       cfg.def = def;
-       pdev->noise_reduction = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
-
-       /* Save / Restore User / Factory Settings */
-       pdev->save_user = v4l2_ctrl_new_custom(hdl, &pwc_save_user_cfg, NULL);
-       pdev->restore_user = v4l2_ctrl_new_custom(hdl, &pwc_restore_user_cfg,
-                                                 NULL);
-       if (pdev->restore_user)
-               pdev->restore_user->flags |= V4L2_CTRL_FLAG_UPDATE;
-       pdev->restore_factory = v4l2_ctrl_new_custom(hdl,
-                                                    &pwc_restore_factory_cfg,
-                                                    NULL);
-       if (pdev->restore_factory)
-               pdev->restore_factory->flags |= V4L2_CTRL_FLAG_UPDATE;
-
-       /* Auto White Balance speed & delay */
-       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
-                           AWB_CONTROL_SPEED_FORMATTER, &def);
-       if (r || def < 1 || def > 32)
-               def = 1;
-       cfg = pwc_awb_speed_cfg;
-       cfg.def = def;
-       pdev->awb_speed = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
-
-       r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL,
-                           AWB_CONTROL_DELAY_FORMATTER, &def);
-       if (r || def > 63)
-               def = 0;
-       cfg = pwc_awb_delay_cfg;
-       cfg.def = def;
-       pdev->awb_delay = v4l2_ctrl_new_custom(hdl, &cfg, NULL);
-
-       if (!(pdev->features & FEATURE_MOTOR_PANTILT))
-               return hdl->error;
-
-       /* Motor pan / tilt / reset */
-       pdev->motor_pan = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
-                               V4L2_CID_PAN_RELATIVE, -4480, 4480, 64, 0);
-       if (!pdev->motor_pan)
-               return hdl->error;
-       pdev->motor_tilt = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
-                               V4L2_CID_TILT_RELATIVE, -1920, 1920, 64, 0);
-       pdev->motor_pan_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
-                               V4L2_CID_PAN_RESET, 0, 0, 0, 0);
-       pdev->motor_tilt_reset = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
-                               V4L2_CID_TILT_RESET, 0, 0, 0, 0);
-       v4l2_ctrl_cluster(4, &pdev->motor_pan);
-
-       return hdl->error;
-}
-
-static void pwc_vidioc_fill_fmt(struct v4l2_format *f,
-       int width, int height, u32 pixfmt)
-{
-       memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
-       f->fmt.pix.width        = width;
-       f->fmt.pix.height       = height;
-       f->fmt.pix.field        = V4L2_FIELD_NONE;
-       f->fmt.pix.pixelformat  = pixfmt;
-       f->fmt.pix.bytesperline = f->fmt.pix.width;
-       f->fmt.pix.sizeimage    = f->fmt.pix.height * f->fmt.pix.width * 3 / 2;
-       f->fmt.pix.colorspace   = V4L2_COLORSPACE_SRGB;
-       PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() "
-                       "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n",
-                       f->fmt.pix.width,
-                       f->fmt.pix.height,
-                       f->fmt.pix.bytesperline,
-                       f->fmt.pix.sizeimage,
-                       (f->fmt.pix.pixelformat)&255,
-                       (f->fmt.pix.pixelformat>>8)&255,
-                       (f->fmt.pix.pixelformat>>16)&255,
-                       (f->fmt.pix.pixelformat>>24)&255);
-}
-
-/* ioctl(VIDIOC_TRY_FMT) */
-static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
-{
-       int size;
-
-       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
-               return -EINVAL;
-       }
-
-       switch (f->fmt.pix.pixelformat) {
-               case V4L2_PIX_FMT_YUV420:
-                       break;
-               case V4L2_PIX_FMT_PWC1:
-                       if (DEVICE_USE_CODEC23(pdev->type)) {
-                               PWC_DEBUG_IOCTL("codec1 is only supported for old pwc webcam\n");
-                               return -EINVAL;
-                       }
-                       break;
-               case V4L2_PIX_FMT_PWC2:
-                       if (DEVICE_USE_CODEC1(pdev->type)) {
-                               PWC_DEBUG_IOCTL("codec23 is only supported for new pwc webcam\n");
-                               return -EINVAL;
-                       }
-                       break;
-               default:
-                       PWC_DEBUG_IOCTL("Unsupported pixel format\n");
-                       return -EINVAL;
-
-       }
-
-       size = pwc_get_size(pdev, f->fmt.pix.width, f->fmt.pix.height);
-       pwc_vidioc_fill_fmt(f,
-                           pwc_image_sizes[size][0],
-                           pwc_image_sizes[size][1],
-                           f->fmt.pix.pixelformat);
-
-       return 0;
-}
-
-/* ioctl(VIDIOC_SET_FMT) */
-
-static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
-{
-       struct pwc_device *pdev = video_drvdata(file);
-       int ret, pixelformat, compression = 0;
-
-       ret = pwc_vidioc_try_fmt(pdev, f);
-       if (ret < 0)
-               return ret;
-
-       if (vb2_is_busy(&pdev->vb_queue))
-               return -EBUSY;
-
-       pixelformat = f->fmt.pix.pixelformat;
-
-       PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d "
-                       "format=%c%c%c%c\n",
-                       f->fmt.pix.width, f->fmt.pix.height, pdev->vframes,
-                       (pixelformat)&255,
-                       (pixelformat>>8)&255,
-                       (pixelformat>>16)&255,
-                       (pixelformat>>24)&255);
-
-       ret = pwc_set_video_mode(pdev, f->fmt.pix.width, f->fmt.pix.height,
-                                pixelformat, 30, &compression, 0);
-
-       PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret);
-
-       pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
-       return ret;
-}
-
-static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
-{
-       struct pwc_device *pdev = video_drvdata(file);
-
-       strcpy(cap->driver, PWC_NAME);
-       strlcpy(cap->card, pdev->vdev.name, sizeof(cap->card));
-       usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info));
-       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
-                                       V4L2_CAP_READWRITE;
-       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-       return 0;
-}
-
-static int pwc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
-{
-       if (i->index)   /* Only one INPUT is supported */
-               return -EINVAL;
-
-       strlcpy(i->name, "Camera", sizeof(i->name));
-       i->type = V4L2_INPUT_TYPE_CAMERA;
-       return 0;
-}
-
-static int pwc_g_input(struct file *file, void *fh, unsigned int *i)
-{
-       *i = 0;
-       return 0;
-}
-
-static int pwc_s_input(struct file *file, void *fh, unsigned int i)
-{
-       return i ? -EINVAL : 0;
-}
-
-static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct pwc_device *pdev =
-               container_of(ctrl->handler, struct pwc_device, ctrl_handler);
-       int ret = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_AUTO_WHITE_BALANCE:
-               if (pdev->color_bal_valid &&
-                       (pdev->auto_white_balance->val != awb_auto ||
-                        time_before(jiffies,
-                               pdev->last_color_bal_update + HZ / 4))) {
-                       pdev->red_balance->val  = pdev->last_red_balance;
-                       pdev->blue_balance->val = pdev->last_blue_balance;
-                       break;
-               }
-               ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
-                                     READ_RED_GAIN_FORMATTER,
-                                     &pdev->red_balance->val);
-               if (ret)
-                       break;
-               ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
-                                     READ_BLUE_GAIN_FORMATTER,
-                                     &pdev->blue_balance->val);
-               if (ret)
-                       break;
-               pdev->last_red_balance  = pdev->red_balance->val;
-               pdev->last_blue_balance = pdev->blue_balance->val;
-               pdev->last_color_bal_update = jiffies;
-               pdev->color_bal_valid = true;
-               break;
-       case V4L2_CID_AUTOGAIN:
-               if (pdev->gain_valid && time_before(jiffies,
-                               pdev->last_gain_update + HZ / 4)) {
-                       pdev->gain->val = pdev->last_gain;
-                       break;
-               }
-               ret = pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
-                                     READ_AGC_FORMATTER, &pdev->gain->val);
-               if (ret)
-                       break;
-               pdev->last_gain = pdev->gain->val;
-               pdev->last_gain_update = jiffies;
-               pdev->gain_valid = true;
-               if (!DEVICE_USE_CODEC3(pdev->type))
-                       break;
-               /* Fall through for CODEC3 where autogain also controls expo */
-       case V4L2_CID_EXPOSURE_AUTO:
-               if (pdev->exposure_valid && time_before(jiffies,
-                               pdev->last_exposure_update + HZ / 4)) {
-                       pdev->exposure->val = pdev->last_exposure;
-                       break;
-               }
-               ret = pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
-                                      READ_SHUTTER_FORMATTER,
-                                      &pdev->exposure->val);
-               if (ret)
-                       break;
-               pdev->last_exposure = pdev->exposure->val;
-               pdev->last_exposure_update = jiffies;
-               pdev->exposure_valid = true;
-               break;
-       default:
-               ret = -EINVAL;
-       }
-
-       if (ret)
-               PWC_ERROR("g_ctrl %s error %d\n", ctrl->name, ret);
-
-       return ret;
-}
-
-static int pwc_set_awb(struct pwc_device *pdev)
-{
-       int ret;
-
-       if (pdev->auto_white_balance->is_new) {
-               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
-                                     WB_MODE_FORMATTER,
-                                     pdev->auto_white_balance->val);
-               if (ret)
-                       return ret;
-
-               if (pdev->auto_white_balance->val != awb_manual)
-                       pdev->color_bal_valid = false; /* Force cache update */
-
-               /*
-                * If this is a preset, update our red / blue balance values
-                * so that events get generated for the new preset values
-                */
-               if (pdev->auto_white_balance->val == awb_indoor ||
-                   pdev->auto_white_balance->val == awb_outdoor ||
-                   pdev->auto_white_balance->val == awb_fl)
-                       pwc_g_volatile_ctrl(pdev->auto_white_balance);
-       }
-       if (pdev->auto_white_balance->val != awb_manual)
-               return 0;
-
-       if (pdev->red_balance->is_new) {
-               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
-                                     PRESET_MANUAL_RED_GAIN_FORMATTER,
-                                     pdev->red_balance->val);
-               if (ret)
-                       return ret;
-       }
-
-       if (pdev->blue_balance->is_new) {
-               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
-                                     PRESET_MANUAL_BLUE_GAIN_FORMATTER,
-                                     pdev->blue_balance->val);
-               if (ret)
-                       return ret;
-       }
-       return 0;
-}
-
-/* For CODEC2 models which have separate autogain and auto exposure */
-static int pwc_set_autogain(struct pwc_device *pdev)
-{
-       int ret;
-
-       if (pdev->autogain->is_new) {
-               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
-                                     AGC_MODE_FORMATTER,
-                                     pdev->autogain->val ? 0 : 0xff);
-               if (ret)
-                       return ret;
-
-               if (pdev->autogain->val)
-                       pdev->gain_valid = false; /* Force cache update */
-       }
-
-       if (pdev->autogain->val)
-               return 0;
-
-       if (pdev->gain->is_new) {
-               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
-                                     PRESET_AGC_FORMATTER,
-                                     pdev->gain->val);
-               if (ret)
-                       return ret;
-       }
-       return 0;
-}
-
-/* For CODEC2 models which have separate autogain and auto exposure */
-static int pwc_set_exposure_auto(struct pwc_device *pdev)
-{
-       int ret;
-       int is_auto = pdev->exposure_auto->val == V4L2_EXPOSURE_AUTO;
-
-       if (pdev->exposure_auto->is_new) {
-               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
-                                     SHUTTER_MODE_FORMATTER,
-                                     is_auto ? 0 : 0xff);
-               if (ret)
-                       return ret;
-
-               if (is_auto)
-                       pdev->exposure_valid = false; /* Force cache update */
-       }
-
-       if (is_auto)
-               return 0;
-
-       if (pdev->exposure->is_new) {
-               ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
-                                      PRESET_SHUTTER_FORMATTER,
-                                      pdev->exposure->val);
-               if (ret)
-                       return ret;
-       }
-       return 0;
-}
-
-/* For CODEC3 models which have autogain controlling both gain and exposure */
-static int pwc_set_autogain_expo(struct pwc_device *pdev)
-{
-       int ret;
-
-       if (pdev->autogain->is_new) {
-               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
-                                     AGC_MODE_FORMATTER,
-                                     pdev->autogain->val ? 0 : 0xff);
-               if (ret)
-                       return ret;
-
-               if (pdev->autogain->val) {
-                       pdev->gain_valid     = false; /* Force cache update */
-                       pdev->exposure_valid = false; /* Force cache update */
-               }
-       }
-
-       if (pdev->autogain->val)
-               return 0;
-
-       if (pdev->gain->is_new) {
-               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
-                                     PRESET_AGC_FORMATTER,
-                                     pdev->gain->val);
-               if (ret)
-                       return ret;
-       }
-
-       if (pdev->exposure->is_new) {
-               ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
-                                      PRESET_SHUTTER_FORMATTER,
-                                      pdev->exposure->val);
-               if (ret)
-                       return ret;
-       }
-       return 0;
-}
-
-static int pwc_set_motor(struct pwc_device *pdev)
-{
-       int ret;
-
-       pdev->ctrl_buf[0] = 0;
-       if (pdev->motor_pan_reset->is_new)
-               pdev->ctrl_buf[0] |= 0x01;
-       if (pdev->motor_tilt_reset->is_new)
-               pdev->ctrl_buf[0] |= 0x02;
-       if (pdev->motor_pan_reset->is_new || pdev->motor_tilt_reset->is_new) {
-               ret = send_control_msg(pdev, SET_MPT_CTL,
-                                      PT_RESET_CONTROL_FORMATTER,
-                                      pdev->ctrl_buf, 1);
-               if (ret < 0)
-                       return ret;
-       }
-
-       memset(pdev->ctrl_buf, 0, 4);
-       if (pdev->motor_pan->is_new) {
-               pdev->ctrl_buf[0] = pdev->motor_pan->val & 0xFF;
-               pdev->ctrl_buf[1] = (pdev->motor_pan->val >> 8);
-       }
-       if (pdev->motor_tilt->is_new) {
-               pdev->ctrl_buf[2] = pdev->motor_tilt->val & 0xFF;
-               pdev->ctrl_buf[3] = (pdev->motor_tilt->val >> 8);
-       }
-       if (pdev->motor_pan->is_new || pdev->motor_tilt->is_new) {
-               ret = send_control_msg(pdev, SET_MPT_CTL,
-                                      PT_RELATIVE_CONTROL_FORMATTER,
-                                      pdev->ctrl_buf, 4);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-       struct pwc_device *pdev =
-               container_of(ctrl->handler, struct pwc_device, ctrl_handler);
-       int ret = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_BRIGHTNESS:
-               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
-                                     BRIGHTNESS_FORMATTER, ctrl->val);
-               break;
-       case V4L2_CID_CONTRAST:
-               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
-                                     CONTRAST_FORMATTER, ctrl->val);
-               break;
-       case V4L2_CID_SATURATION:
-               ret = pwc_set_s8_ctrl(pdev, SET_CHROM_CTL,
-                                     pdev->saturation_fmt, ctrl->val);
-               break;
-       case V4L2_CID_GAMMA:
-               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
-                                     GAMMA_FORMATTER, ctrl->val);
-               break;
-       case V4L2_CID_AUTO_WHITE_BALANCE:
-               ret = pwc_set_awb(pdev);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               if (DEVICE_USE_CODEC2(pdev->type))
-                       ret = pwc_set_autogain(pdev);
-               else if (DEVICE_USE_CODEC3(pdev->type))
-                       ret = pwc_set_autogain_expo(pdev);
-               else
-                       ret = -EINVAL;
-               break;
-       case V4L2_CID_EXPOSURE_AUTO:
-               if (DEVICE_USE_CODEC2(pdev->type))
-                       ret = pwc_set_exposure_auto(pdev);
-               else
-                       ret = -EINVAL;
-               break;
-       case V4L2_CID_COLORFX:
-               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
-                                     COLOUR_MODE_FORMATTER,
-                                     ctrl->val ? 0 : 0xff);
-               break;
-       case PWC_CID_CUSTOM(autocontour):
-               if (pdev->autocontour->is_new) {
-                       ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
-                                       AUTO_CONTOUR_FORMATTER,
-                                       pdev->autocontour->val ? 0 : 0xff);
-               }
-               if (ret == 0 && pdev->contour->is_new) {
-                       ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
-                                             PRESET_CONTOUR_FORMATTER,
-                                             pdev->contour->val);
-               }
-               break;
-       case V4L2_CID_BACKLIGHT_COMPENSATION:
-               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
-                                     BACK_LIGHT_COMPENSATION_FORMATTER,
-                                     ctrl->val ? 0 : 0xff);
-               break;
-       case V4L2_CID_BAND_STOP_FILTER:
-               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
-                                     FLICKERLESS_MODE_FORMATTER,
-                                     ctrl->val ? 0 : 0xff);
-               break;
-       case PWC_CID_CUSTOM(noise_reduction):
-               ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
-                                     DYNAMIC_NOISE_CONTROL_FORMATTER,
-                                     ctrl->val);
-               break;
-       case PWC_CID_CUSTOM(save_user):
-               ret = pwc_button_ctrl(pdev, SAVE_USER_DEFAULTS_FORMATTER);
-               break;
-       case PWC_CID_CUSTOM(restore_user):
-               ret = pwc_button_ctrl(pdev, RESTORE_USER_DEFAULTS_FORMATTER);
-               break;
-       case PWC_CID_CUSTOM(restore_factory):
-               ret = pwc_button_ctrl(pdev,
-                                     RESTORE_FACTORY_DEFAULTS_FORMATTER);
-               break;
-       case PWC_CID_CUSTOM(awb_speed):
-               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
-                                     AWB_CONTROL_SPEED_FORMATTER,
-                                     ctrl->val);
-               break;
-       case PWC_CID_CUSTOM(awb_delay):
-               ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
-                                     AWB_CONTROL_DELAY_FORMATTER,
-                                     ctrl->val);
-               break;
-       case V4L2_CID_PAN_RELATIVE:
-               ret = pwc_set_motor(pdev);
-               break;
-       default:
-               ret = -EINVAL;
-       }
-
-       if (ret)
-               PWC_ERROR("s_ctrl %s error %d\n", ctrl->name, ret);
-
-       return ret;
-}
-
-static int pwc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
-{
-       struct pwc_device *pdev = video_drvdata(file);
-
-       /* We only support two format: the raw format, and YUV */
-       switch (f->index) {
-       case 0:
-               /* RAW format */
-               f->pixelformat = pdev->type <= 646 ? V4L2_PIX_FMT_PWC1 : V4L2_PIX_FMT_PWC2;
-               f->flags = V4L2_FMT_FLAG_COMPRESSED;
-               strlcpy(f->description, "Raw Philips Webcam", sizeof(f->description));
-               break;
-       case 1:
-               f->pixelformat = V4L2_PIX_FMT_YUV420;
-               strlcpy(f->description, "4:2:0, planar, Y-Cb-Cr", sizeof(f->description));
-               break;
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
-{
-       struct pwc_device *pdev = video_drvdata(file);
-
-       if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",
-                       pdev->width, pdev->height);
-       pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt);
-       return 0;
-}
-
-static int pwc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
-{
-       struct pwc_device *pdev = video_drvdata(file);
-
-       return pwc_vidioc_try_fmt(pdev, f);
-}
-
-static int pwc_enum_framesizes(struct file *file, void *fh,
-                                        struct v4l2_frmsizeenum *fsize)
-{
-       struct pwc_device *pdev = video_drvdata(file);
-       unsigned int i = 0, index = fsize->index;
-
-       if (fsize->pixel_format == V4L2_PIX_FMT_YUV420 ||
-           (fsize->pixel_format == V4L2_PIX_FMT_PWC1 &&
-                       DEVICE_USE_CODEC1(pdev->type)) ||
-           (fsize->pixel_format == V4L2_PIX_FMT_PWC2 &&
-                       DEVICE_USE_CODEC23(pdev->type))) {
-               for (i = 0; i < PSZ_MAX; i++) {
-                       if (!(pdev->image_mask & (1UL << i)))
-                               continue;
-                       if (!index--) {
-                               fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-                               fsize->discrete.width = pwc_image_sizes[i][0];
-                               fsize->discrete.height = pwc_image_sizes[i][1];
-                               return 0;
-                       }
-               }
-       }
-       return -EINVAL;
-}
-
-static int pwc_enum_frameintervals(struct file *file, void *fh,
-                                          struct v4l2_frmivalenum *fival)
-{
-       struct pwc_device *pdev = video_drvdata(file);
-       int size = -1;
-       unsigned int i;
-
-       for (i = 0; i < PSZ_MAX; i++) {
-               if (pwc_image_sizes[i][0] == fival->width &&
-                               pwc_image_sizes[i][1] == fival->height) {
-                       size = i;
-                       break;
-               }
-       }
-
-       /* TODO: Support raw format */
-       if (size < 0 || fival->pixel_format != V4L2_PIX_FMT_YUV420)
-               return -EINVAL;
-
-       i = pwc_get_fps(pdev, fival->index, size);
-       if (!i)
-               return -EINVAL;
-
-       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-       fival->discrete.numerator = 1;
-       fival->discrete.denominator = i;
-
-       return 0;
-}
-
-static int pwc_g_parm(struct file *file, void *fh,
-                     struct v4l2_streamparm *parm)
-{
-       struct pwc_device *pdev = video_drvdata(file);
-
-       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       memset(parm, 0, sizeof(*parm));
-
-       parm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       parm->parm.capture.readbuffers = MIN_FRAMES;
-       parm->parm.capture.capability |= V4L2_CAP_TIMEPERFRAME;
-       parm->parm.capture.timeperframe.denominator = pdev->vframes;
-       parm->parm.capture.timeperframe.numerator = 1;
-
-       return 0;
-}
-
-static int pwc_s_parm(struct file *file, void *fh,
-                     struct v4l2_streamparm *parm)
-{
-       struct pwc_device *pdev = video_drvdata(file);
-       int compression = 0;
-       int ret, fps;
-
-       if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       /* If timeperframe == 0, then reset the framerate to the nominal value.
-          We pick a high framerate here, and let pwc_set_video_mode() figure
-          out the best match. */
-       if (parm->parm.capture.timeperframe.numerator == 0 ||
-           parm->parm.capture.timeperframe.denominator == 0)
-               fps = 30;
-       else
-               fps = parm->parm.capture.timeperframe.denominator /
-                     parm->parm.capture.timeperframe.numerator;
-
-       if (vb2_is_busy(&pdev->vb_queue))
-               return -EBUSY;
-
-       ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
-                                fps, &compression, 0);
-
-       pwc_g_parm(file, fh, parm);
-
-       return ret;
-}
-
-const struct v4l2_ioctl_ops pwc_ioctl_ops = {
-       .vidioc_querycap                    = pwc_querycap,
-       .vidioc_enum_input                  = pwc_enum_input,
-       .vidioc_g_input                     = pwc_g_input,
-       .vidioc_s_input                     = pwc_s_input,
-       .vidioc_enum_fmt_vid_cap            = pwc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap               = pwc_g_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap               = pwc_s_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap             = pwc_try_fmt_vid_cap,
-       .vidioc_reqbufs                     = vb2_ioctl_reqbufs,
-       .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_enum_framesizes             = pwc_enum_framesizes,
-       .vidioc_enum_frameintervals         = pwc_enum_frameintervals,
-       .vidioc_g_parm                      = pwc_g_parm,
-       .vidioc_s_parm                      = pwc_s_parm,
-       .vidioc_subscribe_event             = v4l2_ctrl_subscribe_event,
-       .vidioc_unsubscribe_event           = v4l2_event_unsubscribe,
-};
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
deleted file mode 100644 (file)
index 7a6a0d3..0000000
+++ /dev/null
@@ -1,393 +0,0 @@
-/* (C) 1999-2003 Nemosoft Unv.
-   (C) 2004-2006 Luc Saillard (luc@saillard.org)
-
-   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
-   driver and thus may have bugs that are not present in the original version.
-   Please send bug reports and support requests to <luc@saillard.org>.
-   The decompression routines have been implemented by reverse-engineering the
-   Nemosoft binary pwcx module. Caveat emptor.
-
-   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef PWC_H
-#define PWC_H
-
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-#include <linux/mutex.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <asm/errno.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-event.h>
-#include <media/videobuf2-vmalloc.h>
-#ifdef CONFIG_USB_PWC_INPUT_EVDEV
-#include <linux/input.h>
-#endif
-#include "pwc-dec1.h"
-#include "pwc-dec23.h"
-
-/* Version block */
-#define PWC_VERSION    "10.0.15"
-#define PWC_NAME       "pwc"
-#define PFX            PWC_NAME ": "
-
-
-/* Trace certain actions in the driver */
-#define PWC_DEBUG_LEVEL_MODULE (1<<0)
-#define PWC_DEBUG_LEVEL_PROBE  (1<<1)
-#define PWC_DEBUG_LEVEL_OPEN   (1<<2)
-#define PWC_DEBUG_LEVEL_READ   (1<<3)
-#define PWC_DEBUG_LEVEL_MEMORY (1<<4)
-#define PWC_DEBUG_LEVEL_FLOW   (1<<5)
-#define PWC_DEBUG_LEVEL_SIZE   (1<<6)
-#define PWC_DEBUG_LEVEL_IOCTL  (1<<7)
-#define PWC_DEBUG_LEVEL_TRACE  (1<<8)
-
-#define PWC_DEBUG_MODULE(fmt, args...) PWC_DEBUG(MODULE, fmt, ##args)
-#define PWC_DEBUG_PROBE(fmt, args...) PWC_DEBUG(PROBE, fmt, ##args)
-#define PWC_DEBUG_OPEN(fmt, args...) PWC_DEBUG(OPEN, fmt, ##args)
-#define PWC_DEBUG_READ(fmt, args...) PWC_DEBUG(READ, fmt, ##args)
-#define PWC_DEBUG_MEMORY(fmt, args...) PWC_DEBUG(MEMORY, fmt, ##args)
-#define PWC_DEBUG_FLOW(fmt, args...) PWC_DEBUG(FLOW, fmt, ##args)
-#define PWC_DEBUG_SIZE(fmt, args...) PWC_DEBUG(SIZE, fmt, ##args)
-#define PWC_DEBUG_IOCTL(fmt, args...) PWC_DEBUG(IOCTL, fmt, ##args)
-#define PWC_DEBUG_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
-
-
-#ifdef CONFIG_USB_PWC_DEBUG
-
-#define PWC_DEBUG_LEVEL        (PWC_DEBUG_LEVEL_MODULE)
-
-#define PWC_DEBUG(level, fmt, args...) do {\
-       if ((PWC_DEBUG_LEVEL_ ##level) & pwc_trace) \
-               printk(KERN_DEBUG PFX fmt, ##args); \
-       } while (0)
-
-#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
-#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
-#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
-#define PWC_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
-
-#else /* if ! CONFIG_USB_PWC_DEBUG */
-
-#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
-#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
-#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
-#define PWC_TRACE(fmt, args...) do { } while(0)
-#define PWC_DEBUG(level, fmt, args...) do { } while(0)
-
-#define pwc_trace 0
-
-#endif
-
-/* Defines for ToUCam cameras */
-#define TOUCAM_HEADER_SIZE             8
-#define TOUCAM_TRAILER_SIZE            4
-
-#define FEATURE_MOTOR_PANTILT          0x0001
-#define FEATURE_CODEC1                 0x0002
-#define FEATURE_CODEC2                 0x0004
-
-#define MAX_WIDTH              640
-#define MAX_HEIGHT             480
-
-/* Ignore errors in the first N frames, to allow for startup delays */
-#define FRAME_LOWMARK 5
-
-/* Size and number of buffers for the ISO pipe. */
-#define MAX_ISO_BUFS           3
-#define ISO_FRAMES_PER_DESC    10
-#define ISO_MAX_FRAME_SIZE     960
-#define ISO_BUFFER_SIZE        (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
-
-/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */
-#define PWC_FRAME_SIZE                 (460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE)
-
-/* Absolute minimum and maximum number of buffers available for mmap() */
-#define MIN_FRAMES             2
-#define MAX_FRAMES             16
-
-/* Some macros to quickly find the type of a webcam */
-#define DEVICE_USE_CODEC1(x) ((x)<675)
-#define DEVICE_USE_CODEC2(x) ((x)>=675 && (x)<700)
-#define DEVICE_USE_CODEC3(x) ((x)>=700)
-#define DEVICE_USE_CODEC23(x) ((x)>=675)
-
-/* Request types: video */
-#define SET_LUM_CTL                    0x01
-#define GET_LUM_CTL                    0x02
-#define SET_CHROM_CTL                  0x03
-#define GET_CHROM_CTL                  0x04
-#define SET_STATUS_CTL                 0x05
-#define GET_STATUS_CTL                 0x06
-#define SET_EP_STREAM_CTL              0x07
-#define GET_EP_STREAM_CTL              0x08
-#define GET_XX_CTL                     0x09
-#define SET_XX_CTL                     0x0A
-#define GET_XY_CTL                     0x0B
-#define SET_XY_CTL                     0x0C
-#define SET_MPT_CTL                    0x0D
-#define GET_MPT_CTL                    0x0E
-
-/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
-#define AGC_MODE_FORMATTER                     0x2000
-#define PRESET_AGC_FORMATTER                   0x2100
-#define SHUTTER_MODE_FORMATTER                 0x2200
-#define PRESET_SHUTTER_FORMATTER               0x2300
-#define PRESET_CONTOUR_FORMATTER               0x2400
-#define AUTO_CONTOUR_FORMATTER                 0x2500
-#define BACK_LIGHT_COMPENSATION_FORMATTER      0x2600
-#define CONTRAST_FORMATTER                     0x2700
-#define DYNAMIC_NOISE_CONTROL_FORMATTER                0x2800
-#define FLICKERLESS_MODE_FORMATTER             0x2900
-#define AE_CONTROL_SPEED                       0x2A00
-#define BRIGHTNESS_FORMATTER                   0x2B00
-#define GAMMA_FORMATTER                                0x2C00
-
-/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
-#define WB_MODE_FORMATTER                      0x1000
-#define AWB_CONTROL_SPEED_FORMATTER            0x1100
-#define AWB_CONTROL_DELAY_FORMATTER            0x1200
-#define PRESET_MANUAL_RED_GAIN_FORMATTER       0x1300
-#define PRESET_MANUAL_BLUE_GAIN_FORMATTER      0x1400
-#define COLOUR_MODE_FORMATTER                  0x1500
-#define SATURATION_MODE_FORMATTER1             0x1600
-#define SATURATION_MODE_FORMATTER2             0x1700
-
-/* Selectors for the Status controls [GS]ET_STATUS_CTL */
-#define SAVE_USER_DEFAULTS_FORMATTER           0x0200
-#define RESTORE_USER_DEFAULTS_FORMATTER                0x0300
-#define RESTORE_FACTORY_DEFAULTS_FORMATTER     0x0400
-#define READ_AGC_FORMATTER                     0x0500
-#define READ_SHUTTER_FORMATTER                 0x0600
-#define READ_RED_GAIN_FORMATTER                        0x0700
-#define READ_BLUE_GAIN_FORMATTER               0x0800
-
-/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */
-#define PT_RELATIVE_CONTROL_FORMATTER          0x01
-#define PT_RESET_CONTROL_FORMATTER             0x02
-#define PT_STATUS_FORMATTER                    0x03
-
-/* Enumeration of image sizes */
-#define PSZ_SQCIF      0x00
-#define PSZ_QSIF       0x01
-#define PSZ_QCIF       0x02
-#define PSZ_SIF                0x03
-#define PSZ_CIF                0x04
-#define PSZ_VGA                0x05
-#define PSZ_MAX                6
-
-struct pwc_raw_frame {
-       __le16 type;            /* type of the webcam */
-       __le16 vbandlength;     /* Size of 4 lines compressed (used by the
-                                  decompressor) */
-       __u8   cmd[4];          /* the four byte of the command (in case of
-                                  nala, only the first 3 bytes is filled) */
-       __u8   rawframe[0];     /* frame_size = H / 4 * vbandlength */
-} __packed;
-
-/* intermediate buffers with raw data from the USB cam */
-struct pwc_frame_buf
-{
-       struct vb2_buffer vb;   /* common v4l buffer stuff -- must be first */
-       struct list_head list;
-       void *data;
-       int filled;             /* number of bytes filled */
-};
-
-struct pwc_device
-{
-       struct video_device vdev;
-       struct v4l2_device v4l2_dev;
-
-       /* videobuf2 queue and queued buffers list */
-       struct vb2_queue vb_queue;
-       struct list_head queued_bufs;
-       spinlock_t queued_bufs_lock; /* Protects queued_bufs */
-
-       /* Note if taking both locks v4l2_lock must always be locked first! */
-       struct mutex v4l2_lock;      /* Protects everything else */
-       struct mutex vb_queue_lock;  /* Protects vb_queue and capt_file */
-
-       /* Pointer to our usb_device, will be NULL after unplug */
-       struct usb_device *udev; /* Both mutexes most be hold when setting! */
-
-       /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
-       int type;
-       int release;            /* release number */
-       int features;           /* feature bits */
-
-       /*** Video data ***/
-       int vendpoint;          /* video isoc endpoint */
-       int vcinterface;        /* video control interface */
-       int valternate;         /* alternate interface needed */
-       int vframes;            /* frames-per-second */
-       int pixfmt;             /* pixelformat: V4L2_PIX_FMT_YUV420 or _PWCX */
-       int vframe_count;       /* received frames */
-       int vmax_packet_size;   /* USB maxpacket size */
-       int vlast_packet_size;  /* for frame synchronisation */
-       int visoc_errors;       /* number of contiguous ISOC errors */
-       int vbandlength;        /* compressed band length; 0 is uncompressed */
-       char vsync;             /* used by isoc handler */
-       char vmirror;           /* for ToUCaM series */
-       char power_save;        /* Do powersaving for this cam */
-
-       unsigned char cmd_buf[13];
-       unsigned char *ctrl_buf;
-
-       struct urb *urbs[MAX_ISO_BUFS];
-
-       /*
-        * Frame currently being filled, this only gets touched by the
-        * isoc urb complete handler, and by stream start / stop since
-        * start / stop touch it before / after starting / killing the urbs
-        * no locking is needed around this
-        */
-       struct pwc_frame_buf *fill_buf;
-
-       int frame_header_size, frame_trailer_size;
-       int frame_size;
-       int frame_total_size;   /* including header & trailer */
-       int drop_frames;
-
-       union { /* private data for decompression engine */
-               struct pwc_dec1_private dec1;
-               struct pwc_dec23_private dec23;
-       };
-
-       /*
-        * We have an 'image' and a 'view', where 'image' is the fixed-size img
-        * as delivered by the camera, and 'view' is the size requested by the
-        * program. The camera image is centered in this viewport, laced with
-        * a gray or black border. view_min <= image <= view <= view_max;
-        */
-       int image_mask;                         /* supported sizes */
-       int width, height;                      /* current resolution */
-
-#ifdef CONFIG_USB_PWC_INPUT_EVDEV
-       struct input_dev *button_dev;   /* webcam snapshot button input */
-       char button_phys[64];
-#endif
-
-       /* controls */
-       struct v4l2_ctrl_handler        ctrl_handler;
-       u16                             saturation_fmt;
-       struct v4l2_ctrl                *brightness;
-       struct v4l2_ctrl                *contrast;
-       struct v4l2_ctrl                *saturation;
-       struct v4l2_ctrl                *gamma;
-       struct {
-               /* awb / red-blue balance cluster */
-               struct v4l2_ctrl        *auto_white_balance;
-               struct v4l2_ctrl        *red_balance;
-               struct v4l2_ctrl        *blue_balance;
-               /* usb ctrl transfers are slow, so we cache things */
-               int                     color_bal_valid;
-               unsigned long           last_color_bal_update; /* In jiffies */
-               s32                     last_red_balance;
-               s32                     last_blue_balance;
-       };
-       struct {
-               /* autogain / gain cluster */
-               struct v4l2_ctrl        *autogain;
-               struct v4l2_ctrl        *gain;
-               int                     gain_valid;
-               unsigned long           last_gain_update; /* In jiffies */
-               s32                     last_gain;
-       };
-       struct {
-               /* exposure_auto / exposure cluster */
-               struct v4l2_ctrl        *exposure_auto;
-               struct v4l2_ctrl        *exposure;
-               int                     exposure_valid;
-               unsigned long           last_exposure_update; /* In jiffies */
-               s32                     last_exposure;
-       };
-       struct v4l2_ctrl                *colorfx;
-       struct {
-               /* autocontour/contour cluster */
-               struct v4l2_ctrl        *autocontour;
-               struct v4l2_ctrl        *contour;
-       };
-       struct v4l2_ctrl                *backlight;
-       struct v4l2_ctrl                *flicker;
-       struct v4l2_ctrl                *noise_reduction;
-       struct v4l2_ctrl                *save_user;
-       struct v4l2_ctrl                *restore_user;
-       struct v4l2_ctrl                *restore_factory;
-       struct v4l2_ctrl                *awb_speed;
-       struct v4l2_ctrl                *awb_delay;
-       struct {
-               /* motor control cluster */
-               struct v4l2_ctrl        *motor_pan;
-               struct v4l2_ctrl        *motor_tilt;
-               struct v4l2_ctrl        *motor_pan_reset;
-               struct v4l2_ctrl        *motor_tilt_reset;
-       };
-       /* CODEC3 models have both gain and exposure controlled by autogain */
-       struct v4l2_ctrl                *autogain_expo_cluster[3];
-};
-
-/* Global variables */
-#ifdef CONFIG_USB_PWC_DEBUG
-extern int pwc_trace;
-#endif
-
-/** Functions in pwc-misc.c */
-/* sizes in pixels */
-extern const int pwc_image_sizes[PSZ_MAX][2];
-
-int pwc_get_size(struct pwc_device *pdev, int width, int height);
-void pwc_construct(struct pwc_device *pdev);
-
-/** Functions in pwc-ctrl.c */
-/* Request a certain video mode. Returns < 0 if not possible */
-extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height,
-       int pixfmt, int frames, int *compression, int send_to_cam);
-extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size);
-extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
-extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
-extern int send_control_msg(struct pwc_device *pdev,
-                           u8 request, u16 value, void *buf, int buflen);
-
-/* Control get / set helpers */
-int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data);
-int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data);
-int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data);
-#define pwc_set_s8_ctrl pwc_set_u8_ctrl
-int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *dat);
-int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data);
-int pwc_button_ctrl(struct pwc_device *pdev, u16 value);
-int pwc_init_controls(struct pwc_device *pdev);
-
-/* Power down or up the camera; not supported by all models */
-extern void pwc_camera_power(struct pwc_device *pdev, int power);
-
-extern const struct v4l2_ioctl_ops pwc_ioctl_ops;
-
-/** pwc-uncompress.c */
-/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
-int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf);
-
-#endif
diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig
deleted file mode 100644 (file)
index 6ebaf29..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-config USB_SN9C102
-       tristate "USB SN9C1xx PC Camera Controller support (DEPRECATED)"
-       depends on VIDEO_V4L2
-       ---help---
-         This driver is DEPRECATED please use the gspca sonixb and
-         sonixj modules instead.
-
-         Say Y here if you want support for cameras based on SONiX SN9C101,
-         SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers.
-
-         See <file:Documentation/video4linux/sn9c102.txt> for more info.
-
-         To compile this driver as a module, choose M here: the
-         module will be called sn9c102.
diff --git a/drivers/media/video/sn9c102/Makefile b/drivers/media/video/sn9c102/Makefile
deleted file mode 100644 (file)
index 7ecd5a9..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-sn9c102-objs := sn9c102_core.o \
-               sn9c102_hv7131d.o \
-               sn9c102_hv7131r.o \
-               sn9c102_mi0343.o \
-               sn9c102_mi0360.o \
-               sn9c102_mt9v111.o \
-               sn9c102_ov7630.o \
-               sn9c102_ov7660.o \
-               sn9c102_pas106b.o \
-               sn9c102_pas202bcb.o \
-               sn9c102_tas5110c1b.o \
-               sn9c102_tas5110d.o \
-               sn9c102_tas5130d1b.o
-
-obj-$(CONFIG_USB_SN9C102)       += sn9c102.o
diff --git a/drivers/media/video/sn9c102/sn9c102.h b/drivers/media/video/sn9c102/sn9c102.h
deleted file mode 100644 (file)
index 2bc153e..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/***************************************************************************
- * V4L2 driver for SN9C1xx PC Camera Controllers                           *
- *                                                                         *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * 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.               *
- ***************************************************************************/
-
-#ifndef _SN9C102_H_
-#define _SN9C102_H_
-
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/time.h>
-#include <linux/wait.h>
-#include <linux/types.h>
-#include <linux/param.h>
-#include <linux/rwsem.h>
-#include <linux/mutex.h>
-#include <linux/string.h>
-#include <linux/stddef.h>
-#include <linux/kref.h>
-
-#include "sn9c102_config.h"
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-enum sn9c102_frame_state {
-       F_UNUSED,
-       F_QUEUED,
-       F_GRABBING,
-       F_DONE,
-       F_ERROR,
-};
-
-struct sn9c102_frame_t {
-       void* bufmem;
-       struct v4l2_buffer buf;
-       enum sn9c102_frame_state state;
-       struct list_head frame;
-       unsigned long vma_use_count;
-};
-
-enum sn9c102_dev_state {
-       DEV_INITIALIZED = 0x01,
-       DEV_DISCONNECTED = 0x02,
-       DEV_MISCONFIGURED = 0x04,
-};
-
-enum sn9c102_io_method {
-       IO_NONE,
-       IO_READ,
-       IO_MMAP,
-};
-
-enum sn9c102_stream_state {
-       STREAM_OFF,
-       STREAM_INTERRUPT,
-       STREAM_ON,
-};
-
-typedef char sn9c102_sof_header_t[62];
-
-struct sn9c102_sof_t {
-       sn9c102_sof_header_t header;
-       u16 bytesread;
-};
-
-struct sn9c102_sysfs_attr {
-       u16 reg, i2c_reg;
-       sn9c102_sof_header_t frame_header;
-};
-
-struct sn9c102_module_param {
-       u8 force_munmap;
-       u16 frame_timeout;
-};
-
-static DEFINE_MUTEX(sn9c102_sysfs_lock);
-static DECLARE_RWSEM(sn9c102_dev_lock);
-
-struct sn9c102_device {
-       struct video_device* v4ldev;
-
-       enum sn9c102_bridge bridge;
-       struct sn9c102_sensor sensor;
-
-       struct usb_device* usbdev;
-       struct urb* urb[SN9C102_URBS];
-       void* transfer_buffer[SN9C102_URBS];
-       u8* control_buffer;
-
-       struct sn9c102_frame_t *frame_current, frame[SN9C102_MAX_FRAMES];
-       struct list_head inqueue, outqueue;
-       u32 frame_count, nbuffers, nreadbuffers;
-
-       enum sn9c102_io_method io;
-       enum sn9c102_stream_state stream;
-
-       struct v4l2_jpegcompression compression;
-
-       struct sn9c102_sysfs_attr sysfs;
-       struct sn9c102_sof_t sof;
-       u16 reg[384];
-
-       struct sn9c102_module_param module_param;
-
-       struct kref kref;
-       enum sn9c102_dev_state state;
-       u8 users;
-
-       struct completion probe;
-       struct mutex open_mutex, fileop_mutex;
-       spinlock_t queue_lock;
-       wait_queue_head_t wait_open, wait_frame, wait_stream;
-};
-
-/*****************************************************************************/
-
-struct sn9c102_device*
-sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id)
-{
-       return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL;
-}
-
-
-void
-sn9c102_attach_sensor(struct sn9c102_device* cam,
-                     const struct sn9c102_sensor* sensor)
-{
-       memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
-}
-
-
-enum sn9c102_bridge
-sn9c102_get_bridge(struct sn9c102_device* cam)
-{
-       return cam->bridge;
-}
-
-
-struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam)
-{
-       return &cam->sensor;
-}
-
-/*****************************************************************************/
-
-#undef DBG
-#undef KDBG
-#ifdef SN9C102_DEBUG
-#      define DBG(level, fmt, args...)                                       \
-do {                                                                          \
-       if (debug >= (level)) {                                               \
-               if ((level) == 1)                                             \
-                       dev_err(&cam->usbdev->dev, fmt "\n", ## args);        \
-               else if ((level) == 2)                                        \
-                       dev_info(&cam->usbdev->dev, fmt "\n", ## args);       \
-               else if ((level) >= 3)                                        \
-                       dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n",      \
-                                __func__, __LINE__ , ## args);           \
-       }                                                                     \
-} while (0)
-#      define V4LDBG(level, name, cmd)                                       \
-do {                                                                          \
-       if (debug >= (level))                                                 \
-               v4l_printk_ioctl(name, cmd);                                  \
-} while (0)
-#      define KDBG(level, fmt, args...)                                      \
-do {                                                                          \
-       if (debug >= (level)) {                                               \
-               if ((level) == 1 || (level) == 2)                             \
-                       pr_info("sn9c102: " fmt "\n", ## args);               \
-               else if ((level) == 3)                                        \
-                       pr_debug("sn9c102: [%s:%d] " fmt "\n",                \
-                                __func__, __LINE__ , ## args);           \
-       }                                                                     \
-} while (0)
-#else
-#      define DBG(level, fmt, args...) do {;} while(0)
-#      define V4LDBG(level, name, cmd) do {;} while(0)
-#      define KDBG(level, fmt, args...) do {;} while(0)
-#endif
-
-#undef PDBG
-#define PDBG(fmt, args...)                                                    \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__,   \
-        __LINE__ , ## args)
-
-#undef PDBGG
-#define PDBGG(fmt, args...) do {;} while(0) /* placeholder */
-
-#endif /* _SN9C102_H_ */
diff --git a/drivers/media/video/sn9c102/sn9c102_config.h b/drivers/media/video/sn9c102/sn9c102_config.h
deleted file mode 100644 (file)
index 0f4e037..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/***************************************************************************
- * Global parameters for the V4L2 driver for SN9C1xx PC Camera Controllers *
- *                                                                         *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * 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.               *
- ***************************************************************************/
-
-#ifndef _SN9C102_CONFIG_H_
-#define _SN9C102_CONFIG_H_
-
-#include <linux/types.h>
-#include <linux/jiffies.h>
-
-#define SN9C102_DEBUG
-#define SN9C102_DEBUG_LEVEL       2
-#define SN9C102_MAX_DEVICES       64
-#define SN9C102_PRESERVE_IMGSCALE 0
-#define SN9C102_FORCE_MUNMAP      0
-#define SN9C102_MAX_FRAMES        32
-#define SN9C102_URBS              2
-#define SN9C102_ISO_PACKETS       7
-#define SN9C102_ALTERNATE_SETTING 8
-#define SN9C102_URB_TIMEOUT       msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
-#define SN9C102_CTRL_TIMEOUT      300
-#define SN9C102_FRAME_TIMEOUT     0
-
-/*****************************************************************************/
-
-static const u8 SN9C102_Y_QTABLE0[64] = {
-        8,   5,   5,   8,  12,  20,  25,  30,
-        6,   6,   7,   9,  13,  29,  30,  27,
-        7,   6,   8,  12,  20,  28,  34,  28,
-        7,   8,  11,  14,  25,  43,  40,  31,
-        9,  11,  18,  28,  34,  54,  51,  38,
-       12,  17,  27,  32,  40,  52,  56,  46,
-       24,  32,  39,  43,  51,  60,  60,  50,
-       36,  46,  47,  49,  56,  50,  51,  49
-};
-
-static const u8 SN9C102_UV_QTABLE0[64] = {
-        8,   9,  12,  23,  49,  49,  49,  49,
-        9,  10,  13,  33,  49,  49,  49,  49,
-       12,  13,  28,  49,  49,  49,  49,  49,
-       23,  33,  49,  49,  49,  49,  49,  49,
-       49,  49,  49,  49,  49,  49,  49,  49,
-       49,  49,  49,  49,  49,  49,  49,  49,
-       49,  49,  49,  49,  49,  49,  49,  49,
-       49,  49,  49,  49,  49,  49,  49,  49
-};
-
-static const u8 SN9C102_Y_QTABLE1[64] = {
-       16,  11,  10,  16,  24,  40,  51,  61,
-       12,  12,  14,  19,  26,  58,  60,  55,
-       14,  13,  16,  24,  40,  57,  69,  56,
-       14,  17,  22,  29,  51,  87,  80,  62,
-       18,  22,  37,  56,  68, 109, 103,  77,
-       24,  35,  55,  64,  81, 104, 113,  92,
-       49,  64,  78,  87, 103, 121, 120, 101,
-       72,  92,  95,  98, 112, 100, 103,  99
-};
-
-static const u8 SN9C102_UV_QTABLE1[64] = {
-       17,  18,  24,  47,  99,  99,  99,  99,
-       18,  21,  26,  66,  99,  99,  99,  99,
-       24,  26,  56,  99,  99,  99,  99,  99,
-       47,  66,  99,  99,  99,  99,  99,  99,
-       99,  99,  99,  99,  99,  99,  99,  99,
-       99,  99,  99,  99,  99,  99,  99,  99,
-       99,  99,  99,  99,  99,  99,  99,  99,
-       99,  99,  99,  99,  99,  99,  99,  99
-};
-
-#endif /* _SN9C102_CONFIG_H_ */
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
deleted file mode 100644 (file)
index 19ea780..0000000
+++ /dev/null
@@ -1,3421 +0,0 @@
-/***************************************************************************
- * V4L2 driver for SN9C1xx PC Camera Controllers                           *
- *                                                                         *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * 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/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include <linux/compiler.h>
-#include <linux/ioctl.h>
-#include <linux/poll.h>
-#include <linux/stat.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/version.h>
-#include <linux/page-flags.h>
-#include <asm/byteorder.h>
-#include <asm/page.h>
-#include <asm/uaccess.h>
-
-#include "sn9c102.h"
-
-/*****************************************************************************/
-
-#define SN9C102_MODULE_NAME     "V4L2 driver for SN9C1xx PC Camera Controllers"
-#define SN9C102_MODULE_ALIAS    "sn9c1xx"
-#define SN9C102_MODULE_AUTHOR   "(C) 2004-2007 Luca Risolia"
-#define SN9C102_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
-#define SN9C102_MODULE_LICENSE  "GPL"
-#define SN9C102_MODULE_VERSION  "1:1.48"
-
-/*****************************************************************************/
-
-MODULE_DEVICE_TABLE(usb, sn9c102_id_table);
-
-MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);
-MODULE_DESCRIPTION(SN9C102_MODULE_NAME);
-MODULE_ALIAS(SN9C102_MODULE_ALIAS);
-MODULE_VERSION(SN9C102_MODULE_VERSION);
-MODULE_LICENSE(SN9C102_MODULE_LICENSE);
-
-static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1};
-module_param_array(video_nr, short, NULL, 0444);
-MODULE_PARM_DESC(video_nr,
-                " <-1|n[,...]>"
-                "\nSpecify V4L2 minor mode number."
-                "\n-1 = use next available (default)"
-                "\n n = use minor number n (integer >= 0)"
-                "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES)
-                " cameras this way."
-                "\nFor example:"
-                "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
-                "\nthe second camera and use auto for the first"
-                "\none and for every other camera."
-                "\n");
-
-static bool force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
-                             SN9C102_FORCE_MUNMAP};
-module_param_array(force_munmap, bool, NULL, 0444);
-MODULE_PARM_DESC(force_munmap,
-                " <0|1[,...]>"
-                "\nForce the application to unmap previously"
-                "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
-                "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
-                "\nthis feature. This parameter is specific for each"
-                "\ndetected camera."
-                "\n0 = do not force memory unmapping"
-                "\n1 = force memory unmapping (save memory)"
-                "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
-                "\n");
-
-static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] =
-                                      SN9C102_FRAME_TIMEOUT};
-module_param_array(frame_timeout, uint, NULL, 0644);
-MODULE_PARM_DESC(frame_timeout,
-                " <0|n[,...]>"
-                "\nTimeout for a video frame in seconds before"
-                "\nreturning an I/O error; 0 for infinity."
-                "\nThis parameter is specific for each detected camera."
-                "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
-                "\n");
-
-#ifdef SN9C102_DEBUG
-static unsigned short debug = SN9C102_DEBUG_LEVEL;
-module_param(debug, ushort, 0644);
-MODULE_PARM_DESC(debug,
-                " <n>"
-                "\nDebugging information level, from 0 to 3:"
-                "\n0 = none (use carefully)"
-                "\n1 = critical errors"
-                "\n2 = significant informations"
-                "\n3 = more verbose messages"
-                "\nLevel 3 is useful for testing only."
-                "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
-                "\n");
-#endif
-
-/*
-   Add the probe entries to this table. Be sure to add the entry in the right
-   place, since, on failure, the next probing routine is called according to
-   the order of the list below, from top to bottom.
-*/
-static int (*sn9c102_sensor_table[])(struct sn9c102_device *) = {
-       &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
-       &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
-       &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
-       &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
-};
-
-/*****************************************************************************/
-
-static u32
-sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
-                       enum sn9c102_io_method io)
-{
-       struct v4l2_pix_format* p = &(cam->sensor.pix_format);
-       struct v4l2_rect* r = &(cam->sensor.cropcap.bounds);
-       size_t imagesize = cam->module_param.force_munmap || io == IO_READ ?
-                          (p->width * p->height * p->priv) / 8 :
-                          (r->width * r->height * p->priv) / 8;
-       void* buff = NULL;
-       u32 i;
-
-       if (count > SN9C102_MAX_FRAMES)
-               count = SN9C102_MAX_FRAMES;
-
-       if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120)
-               imagesize += 589 + 2; /* length of JPEG header + EOI marker */
-
-       cam->nbuffers = count;
-       while (cam->nbuffers > 0) {
-               if ((buff = vmalloc_32_user(cam->nbuffers *
-                                           PAGE_ALIGN(imagesize))))
-                       break;
-               cam->nbuffers--;
-       }
-
-       for (i = 0; i < cam->nbuffers; i++) {
-               cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize);
-               cam->frame[i].buf.index = i;
-               cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize);
-               cam->frame[i].buf.length = imagesize;
-               cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               cam->frame[i].buf.sequence = 0;
-               cam->frame[i].buf.field = V4L2_FIELD_NONE;
-               cam->frame[i].buf.memory = V4L2_MEMORY_MMAP;
-               cam->frame[i].buf.flags = 0;
-       }
-
-       return cam->nbuffers;
-}
-
-
-static void sn9c102_release_buffers(struct sn9c102_device* cam)
-{
-       if (cam->nbuffers) {
-               vfree(cam->frame[0].bufmem);
-               cam->nbuffers = 0;
-       }
-       cam->frame_current = NULL;
-}
-
-
-static void sn9c102_empty_framequeues(struct sn9c102_device* cam)
-{
-       u32 i;
-
-       INIT_LIST_HEAD(&cam->inqueue);
-       INIT_LIST_HEAD(&cam->outqueue);
-
-       for (i = 0; i < SN9C102_MAX_FRAMES; i++) {
-               cam->frame[i].state = F_UNUSED;
-               cam->frame[i].buf.bytesused = 0;
-       }
-}
-
-
-static void sn9c102_requeue_outqueue(struct sn9c102_device* cam)
-{
-       struct sn9c102_frame_t *i;
-
-       list_for_each_entry(i, &cam->outqueue, frame) {
-               i->state = F_QUEUED;
-               list_add(&i->frame, &cam->inqueue);
-       }
-
-       INIT_LIST_HEAD(&cam->outqueue);
-}
-
-
-static void sn9c102_queue_unusedframes(struct sn9c102_device* cam)
-{
-       unsigned long lock_flags;
-       u32 i;
-
-       for (i = 0; i < cam->nbuffers; i++)
-               if (cam->frame[i].state == F_UNUSED) {
-                       cam->frame[i].state = F_QUEUED;
-                       spin_lock_irqsave(&cam->queue_lock, lock_flags);
-                       list_add_tail(&cam->frame[i].frame, &cam->inqueue);
-                       spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-               }
-}
-
-/*****************************************************************************/
-
-/*
-   Write a sequence of count value/register pairs. Returns -1 after the first
-   failed write, or 0 for no errors.
-*/
-int sn9c102_write_regs(struct sn9c102_device* cam, const u8 valreg[][2],
-                      int count)
-{
-       struct usb_device* udev = cam->usbdev;
-       u8* buff = cam->control_buffer;
-       int i, res;
-
-       for (i = 0; i < count; i++) {
-               u8 index = valreg[i][1];
-
-               /*
-                  index is a u8, so it must be <256 and can't be out of range.
-                  If we put in a check anyway, gcc annoys us with a warning
-                  hat our check is useless. People get all uppity when they
-                  see warnings in the kernel compile.
-               */
-
-               *buff = valreg[i][0];
-
-               res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08,
-                                     0x41, index, 0, buff, 1,
-                                     SN9C102_CTRL_TIMEOUT);
-
-               if (res < 0) {
-                       DBG(3, "Failed to write a register (value 0x%02X, "
-                              "index 0x%02X, error %d)", *buff, index, res);
-                       return -1;
-               }
-
-               cam->reg[index] = *buff;
-       }
-
-       return 0;
-}
-
-
-int sn9c102_write_reg(struct sn9c102_device* cam, u8 value, u16 index)
-{
-       struct usb_device* udev = cam->usbdev;
-       u8* buff = cam->control_buffer;
-       int res;
-
-       if (index >= ARRAY_SIZE(cam->reg))
-               return -1;
-
-       *buff = value;
-
-       res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
-                             index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
-       if (res < 0) {
-               DBG(3, "Failed to write a register (value 0x%02X, index "
-                      "0x%02X, error %d)", value, index, res);
-               return -1;
-       }
-
-       cam->reg[index] = value;
-
-       return 0;
-}
-
-
-/* NOTE: with the SN9C10[123] reading some registers always returns 0 */
-int sn9c102_read_reg(struct sn9c102_device* cam, u16 index)
-{
-       struct usb_device* udev = cam->usbdev;
-       u8* buff = cam->control_buffer;
-       int res;
-
-       res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
-                             index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
-       if (res < 0)
-               DBG(3, "Failed to read a register (index 0x%02X, error %d)",
-                   index, res);
-
-       return (res >= 0) ? (int)(*buff) : -1;
-}
-
-
-int sn9c102_pread_reg(struct sn9c102_device* cam, u16 index)
-{
-       if (index >= ARRAY_SIZE(cam->reg))
-               return -1;
-
-       return cam->reg[index];
-}
-
-
-static int
-sn9c102_i2c_wait(struct sn9c102_device* cam,
-                const struct sn9c102_sensor* sensor)
-{
-       int i, r;
-
-       for (i = 1; i <= 5; i++) {
-               r = sn9c102_read_reg(cam, 0x08);
-               if (r < 0)
-                       return -EIO;
-               if (r & 0x04)
-                       return 0;
-               if (sensor->frequency & SN9C102_I2C_400KHZ)
-                       udelay(5*16);
-               else
-                       udelay(16*16);
-       }
-       return -EBUSY;
-}
-
-
-static int
-sn9c102_i2c_detect_read_error(struct sn9c102_device* cam,
-                             const struct sn9c102_sensor* sensor)
-{
-       int r , err = 0;
-
-       r = sn9c102_read_reg(cam, 0x08);
-       if (r < 0)
-               err += r;
-
-       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
-               if (!(r & 0x08))
-                       err += -1;
-       } else {
-               if (r & 0x08)
-                       err += -1;
-       }
-
-       return err ? -EIO : 0;
-}
-
-
-static int
-sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
-                              const struct sn9c102_sensor* sensor)
-{
-       int r;
-       r = sn9c102_read_reg(cam, 0x08);
-       return (r < 0 || (r >= 0 && (r & 0x08))) ? -EIO : 0;
-}
-
-
-int
-sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
-                        const struct sn9c102_sensor* sensor, u8 data0,
-                        u8 data1, u8 n, u8 buffer[])
-{
-       struct usb_device* udev = cam->usbdev;
-       u8* data = cam->control_buffer;
-       int i = 0, err = 0, res;
-
-       /* Write cycle */
-       data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
-                 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10;
-       data[1] = data0; /* I2C slave id */
-       data[2] = data1; /* address */
-       data[7] = 0x10;
-       res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
-                             0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
-       if (res < 0)
-               err += res;
-
-       err += sn9c102_i2c_wait(cam, sensor);
-
-       /* Read cycle - n bytes */
-       data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
-                 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) |
-                 (n << 4) | 0x02;
-       data[1] = data0;
-       data[7] = 0x10;
-       res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
-                             0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
-       if (res < 0)
-               err += res;
-
-       err += sn9c102_i2c_wait(cam, sensor);
-
-       /* The first read byte will be placed in data[4] */
-       res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
-                             0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT);
-       if (res < 0)
-               err += res;
-
-       err += sn9c102_i2c_detect_read_error(cam, sensor);
-
-       PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1,
-             data[4]);
-
-       if (err) {
-               DBG(3, "I2C read failed for %s image sensor", sensor->name);
-               return -1;
-       }
-
-       if (buffer)
-               for (i = 0; i < n && i < 5; i++)
-                       buffer[n-i-1] = data[4-i];
-
-       return (int)data[4];
-}
-
-
-int
-sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
-                         const struct sn9c102_sensor* sensor, u8 n, u8 data0,
-                         u8 data1, u8 data2, u8 data3, u8 data4, u8 data5)
-{
-       struct usb_device* udev = cam->usbdev;
-       u8* data = cam->control_buffer;
-       int err = 0, res;
-
-       /* Write cycle. It usually is address + value */
-       data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
-                 ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0)
-                 | ((n - 1) << 4);
-       data[1] = data0;
-       data[2] = data1;
-       data[3] = data2;
-       data[4] = data3;
-       data[5] = data4;
-       data[6] = data5;
-       data[7] = 0x17;
-       res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
-                             0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
-       if (res < 0)
-               err += res;
-
-       err += sn9c102_i2c_wait(cam, sensor);
-       err += sn9c102_i2c_detect_write_error(cam, sensor);
-
-       if (err)
-               DBG(3, "I2C write failed for %s image sensor", sensor->name);
-
-       PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, "
-             "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X",
-             n, data0, data1, data2, data3, data4, data5);
-
-       return err ? -1 : 0;
-}
-
-
-int
-sn9c102_i2c_try_read(struct sn9c102_device* cam,
-                    const struct sn9c102_sensor* sensor, u8 address)
-{
-       return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id,
-                                       address, 1, NULL);
-}
-
-
-static int sn9c102_i2c_try_write(struct sn9c102_device* cam,
-                                const struct sn9c102_sensor* sensor,
-                                u8 address, u8 value)
-{
-       return sn9c102_i2c_try_raw_write(cam, sensor, 3,
-                                        sensor->i2c_slave_id, address,
-                                        value, 0, 0, 0);
-}
-
-
-int sn9c102_i2c_read(struct sn9c102_device* cam, u8 address)
-{
-       return sn9c102_i2c_try_read(cam, &cam->sensor, address);
-}
-
-
-int sn9c102_i2c_write(struct sn9c102_device* cam, u8 address, u8 value)
-{
-       return sn9c102_i2c_try_write(cam, &cam->sensor, address, value);
-}
-
-/*****************************************************************************/
-
-static size_t sn9c102_sof_length(struct sn9c102_device* cam)
-{
-       switch (cam->bridge) {
-       case BRIDGE_SN9C101:
-       case BRIDGE_SN9C102:
-               return 12;
-       case BRIDGE_SN9C103:
-               return 18;
-       case BRIDGE_SN9C105:
-       case BRIDGE_SN9C120:
-               return 62;
-       }
-
-       return 0;
-}
-
-
-static void*
-sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
-{
-       static const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
-       const char *m = mem;
-       size_t soflen = 0, i, j;
-
-       soflen = sn9c102_sof_length(cam);
-
-       for (i = 0; i < len; i++) {
-               size_t b;
-
-               /* Read the variable part of the header */
-               if (unlikely(cam->sof.bytesread >= sizeof(marker))) {
-                       cam->sof.header[cam->sof.bytesread] = *(m+i);
-                       if (++cam->sof.bytesread == soflen) {
-                               cam->sof.bytesread = 0;
-                               return mem + i;
-                       }
-                       continue;
-               }
-
-               /* Search for the SOF marker (fixed part) in the header */
-               for (j = 0, b=cam->sof.bytesread; j+b < sizeof(marker); j++) {
-                       if (unlikely(i+j == len))
-                               return NULL;
-                       if (*(m+i+j) == marker[cam->sof.bytesread]) {
-                               cam->sof.header[cam->sof.bytesread] = *(m+i+j);
-                               if (++cam->sof.bytesread == sizeof(marker)) {
-                                       PDBGG("Bytes to analyze: %zd. SOF "
-                                             "starts at byte #%zd", len, i);
-                                       i += j+1;
-                                       break;
-                               }
-                       } else {
-                               cam->sof.bytesread = 0;
-                               break;
-                       }
-               }
-       }
-
-       return NULL;
-}
-
-
-static void*
-sn9c102_find_eof_header(struct sn9c102_device* cam, void* mem, size_t len)
-{
-       static const u8 eof_header[4][4] = {
-               {0x00, 0x00, 0x00, 0x00},
-               {0x40, 0x00, 0x00, 0x00},
-               {0x80, 0x00, 0x00, 0x00},
-               {0xc0, 0x00, 0x00, 0x00},
-       };
-       size_t i, j;
-
-       /* The EOF header does not exist in compressed data */
-       if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
-           cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
-               return NULL;
-
-       /*
-          The EOF header might cross the packet boundary, but this is not a
-          problem, since the end of a frame is determined by checking its size
-          in the first place.
-       */
-       for (i = 0; (len >= 4) && (i <= len - 4); i++)
-               for (j = 0; j < ARRAY_SIZE(eof_header); j++)
-                       if (!memcmp(mem + i, eof_header[j], 4))
-                               return mem + i;
-
-       return NULL;
-}
-
-
-static void
-sn9c102_write_jpegheader(struct sn9c102_device* cam, struct sn9c102_frame_t* f)
-{
-       static const u8 jpeg_header[589] = {
-               0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05,
-               0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06,
-               0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e,
-               0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16,
-               0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16,
-               0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29,
-               0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29,
-               0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a,
-               0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28,
-               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
-               0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2,
-               0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
-               0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01,
-               0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-               0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
-               0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00,
-               0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
-               0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
-               0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
-               0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,
-               0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
-               0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
-               0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38,
-               0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
-               0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
-               0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
-               0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
-               0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
-               0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
-               0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
-               0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3,
-               0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3,
-               0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
-               0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
-               0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
-               0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
-               0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
-               0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
-               0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1,
-               0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19,
-               0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
-               0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
-               0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
-               0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
-               0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-               0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
-               0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
-               0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
-               0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
-               0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
-               0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
-               0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11,
-               0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02,
-               0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03,
-               0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
-       };
-       u8 *pos = f->bufmem;
-
-       memcpy(pos, jpeg_header, sizeof(jpeg_header));
-       *(pos + 6) = 0x00;
-       *(pos + 7 + 64) = 0x01;
-       if (cam->compression.quality == 0) {
-               memcpy(pos + 7, SN9C102_Y_QTABLE0, 64);
-               memcpy(pos + 8 + 64, SN9C102_UV_QTABLE0, 64);
-       } else if (cam->compression.quality == 1) {
-               memcpy(pos + 7, SN9C102_Y_QTABLE1, 64);
-               memcpy(pos + 8 + 64, SN9C102_UV_QTABLE1, 64);
-       }
-       *(pos + 564) = cam->sensor.pix_format.width & 0xFF;
-       *(pos + 563) = (cam->sensor.pix_format.width >> 8) & 0xFF;
-       *(pos + 562) = cam->sensor.pix_format.height & 0xFF;
-       *(pos + 561) = (cam->sensor.pix_format.height >> 8) & 0xFF;
-       *(pos + 567) = 0x21;
-
-       f->buf.bytesused += sizeof(jpeg_header);
-}
-
-
-static void sn9c102_urb_complete(struct urb *urb)
-{
-       struct sn9c102_device* cam = urb->context;
-       struct sn9c102_frame_t** f;
-       size_t imagesize, soflen;
-       u8 i;
-       int err = 0;
-
-       if (urb->status == -ENOENT)
-               return;
-
-       f = &cam->frame_current;
-
-       if (cam->stream == STREAM_INTERRUPT) {
-               cam->stream = STREAM_OFF;
-               if ((*f))
-                       (*f)->state = F_QUEUED;
-               cam->sof.bytesread = 0;
-               DBG(3, "Stream interrupted by application");
-               wake_up(&cam->wait_stream);
-       }
-
-       if (cam->state & DEV_DISCONNECTED)
-               return;
-
-       if (cam->state & DEV_MISCONFIGURED) {
-               wake_up_interruptible(&cam->wait_frame);
-               return;
-       }
-
-       if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue))
-               goto resubmit_urb;
-
-       if (!(*f))
-               (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t,
-                                 frame);
-
-       imagesize = (cam->sensor.pix_format.width *
-                    cam->sensor.pix_format.height *
-                    cam->sensor.pix_format.priv) / 8;
-       if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
-               imagesize += 589; /* length of jpeg header */
-       soflen = sn9c102_sof_length(cam);
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               unsigned int img, len, status;
-               void *pos, *sof, *eof;
-
-               len = urb->iso_frame_desc[i].actual_length;
-               status = urb->iso_frame_desc[i].status;
-               pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer;
-
-               if (status) {
-                       DBG(3, "Error in isochronous frame");
-                       (*f)->state = F_ERROR;
-                       cam->sof.bytesread = 0;
-                       continue;
-               }
-
-               PDBGG("Isochrnous frame: length %u, #%u i", len, i);
-
-redo:
-               sof = sn9c102_find_sof_header(cam, pos, len);
-               if (likely(!sof)) {
-                       eof = sn9c102_find_eof_header(cam, pos, len);
-                       if ((*f)->state == F_GRABBING) {
-end_of_frame:
-                               img = len;
-
-                               if (eof)
-                                       img = (eof > pos) ? eof - pos - 1 : 0;
-
-                               if ((*f)->buf.bytesused + img > imagesize) {
-                                       u32 b;
-                                       b = (*f)->buf.bytesused + img -
-                                           imagesize;
-                                       img = imagesize - (*f)->buf.bytesused;
-                                       PDBGG("Expected EOF not found: video "
-                                             "frame cut");
-                                       if (eof)
-                                               DBG(3, "Exceeded limit: +%u "
-                                                      "bytes", (unsigned)(b));
-                               }
-
-                               memcpy((*f)->bufmem + (*f)->buf.bytesused, pos,
-                                      img);
-
-                               if ((*f)->buf.bytesused == 0)
-                                       do_gettimeofday(&(*f)->buf.timestamp);
-
-                               (*f)->buf.bytesused += img;
-
-                               if ((*f)->buf.bytesused == imagesize ||
-                                   ((cam->sensor.pix_format.pixelformat ==
-                                     V4L2_PIX_FMT_SN9C10X ||
-                                     cam->sensor.pix_format.pixelformat ==
-                                     V4L2_PIX_FMT_JPEG) && eof)) {
-                                       u32 b;
-
-                                       b = (*f)->buf.bytesused;
-                                       (*f)->state = F_DONE;
-                                       (*f)->buf.sequence= ++cam->frame_count;
-
-                                       spin_lock(&cam->queue_lock);
-                                       list_move_tail(&(*f)->frame,
-                                                      &cam->outqueue);
-                                       if (!list_empty(&cam->inqueue))
-                                               (*f) = list_entry(
-                                                       cam->inqueue.next,
-                                                       struct sn9c102_frame_t,
-                                                       frame );
-                                       else
-                                               (*f) = NULL;
-                                       spin_unlock(&cam->queue_lock);
-
-                                       memcpy(cam->sysfs.frame_header,
-                                              cam->sof.header, soflen);
-
-                                       DBG(3, "Video frame captured: %lu "
-                                              "bytes", (unsigned long)(b));
-
-                                       if (!(*f))
-                                               goto resubmit_urb;
-
-                               } else if (eof) {
-                                       (*f)->state = F_ERROR;
-                                       DBG(3, "Not expected EOF after %lu "
-                                              "bytes of image data",
-                                           (unsigned long)
-                                           ((*f)->buf.bytesused));
-                               }
-
-                               if (sof) /* (1) */
-                                       goto start_of_frame;
-
-                       } else if (eof) {
-                               DBG(3, "EOF without SOF");
-                               continue;
-
-                       } else {
-                               PDBGG("Ignoring pointless isochronous frame");
-                               continue;
-                       }
-
-               } else if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) {
-start_of_frame:
-                       (*f)->state = F_GRABBING;
-                       (*f)->buf.bytesused = 0;
-                       len -= (sof - pos);
-                       pos = sof;
-                       if (cam->sensor.pix_format.pixelformat ==
-                           V4L2_PIX_FMT_JPEG)
-                               sn9c102_write_jpegheader(cam, (*f));
-                       DBG(3, "SOF detected: new video frame");
-                       if (len)
-                               goto redo;
-
-               } else if ((*f)->state == F_GRABBING) {
-                       eof = sn9c102_find_eof_header(cam, pos, len);
-                       if (eof && eof < sof)
-                               goto end_of_frame; /* (1) */
-                       else {
-                               if (cam->sensor.pix_format.pixelformat ==
-                                   V4L2_PIX_FMT_SN9C10X ||
-                                   cam->sensor.pix_format.pixelformat ==
-                                   V4L2_PIX_FMT_JPEG) {
-                                       if (sof - pos >= soflen) {
-                                               eof = sof - soflen;
-                                       } else { /* remove header */
-                                               eof = pos;
-                                               (*f)->buf.bytesused -=
-                                                       (soflen - (sof - pos));
-                                       }
-                                       goto end_of_frame;
-                               } else {
-                                       DBG(3, "SOF before expected EOF after "
-                                              "%lu bytes of image data",
-                                           (unsigned long)
-                                           ((*f)->buf.bytesused));
-                                       goto start_of_frame;
-                               }
-                       }
-               }
-       }
-
-resubmit_urb:
-       urb->dev = cam->usbdev;
-       err = usb_submit_urb(urb, GFP_ATOMIC);
-       if (err < 0 && err != -EPERM) {
-               cam->state |= DEV_MISCONFIGURED;
-               DBG(1, "usb_submit_urb() failed");
-       }
-
-       wake_up_interruptible(&cam->wait_frame);
-}
-
-
-static int sn9c102_start_transfer(struct sn9c102_device* cam)
-{
-       struct usb_device *udev = cam->usbdev;
-       struct urb* urb;
-       struct usb_host_interface* altsetting = usb_altnum_to_altsetting(
-                                                   usb_ifnum_to_if(udev, 0),
-                                                   SN9C102_ALTERNATE_SETTING);
-       const unsigned int psz = le16_to_cpu(altsetting->
-                                            endpoint[0].desc.wMaxPacketSize);
-       s8 i, j;
-       int err = 0;
-
-       for (i = 0; i < SN9C102_URBS; i++) {
-               cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz,
-                                                 GFP_KERNEL);
-               if (!cam->transfer_buffer[i]) {
-                       err = -ENOMEM;
-                       DBG(1, "Not enough memory");
-                       goto free_buffers;
-               }
-       }
-
-       for (i = 0; i < SN9C102_URBS; i++) {
-               urb = usb_alloc_urb(SN9C102_ISO_PACKETS, GFP_KERNEL);
-               cam->urb[i] = urb;
-               if (!urb) {
-                       err = -ENOMEM;
-                       DBG(1, "usb_alloc_urb() failed");
-                       goto free_urbs;
-               }
-               urb->dev = udev;
-               urb->context = cam;
-               urb->pipe = usb_rcvisocpipe(udev, 1);
-               urb->transfer_flags = URB_ISO_ASAP;
-               urb->number_of_packets = SN9C102_ISO_PACKETS;
-               urb->complete = sn9c102_urb_complete;
-               urb->transfer_buffer = cam->transfer_buffer[i];
-               urb->transfer_buffer_length = psz * SN9C102_ISO_PACKETS;
-               urb->interval = 1;
-               for (j = 0; j < SN9C102_ISO_PACKETS; j++) {
-                       urb->iso_frame_desc[j].offset = psz * j;
-                       urb->iso_frame_desc[j].length = psz;
-               }
-       }
-
-       /* Enable video */
-       if (!(cam->reg[0x01] & 0x04)) {
-               err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01);
-               if (err) {
-                       err = -EIO;
-                       DBG(1, "I/O hardware error");
-                       goto free_urbs;
-               }
-       }
-
-       err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING);
-       if (err) {
-               DBG(1, "usb_set_interface() failed");
-               goto free_urbs;
-       }
-
-       cam->frame_current = NULL;
-       cam->sof.bytesread = 0;
-
-       for (i = 0; i < SN9C102_URBS; i++) {
-               err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
-               if (err) {
-                       for (j = i-1; j >= 0; j--)
-                               usb_kill_urb(cam->urb[j]);
-                       DBG(1, "usb_submit_urb() failed, error %d", err);
-                       goto free_urbs;
-               }
-       }
-
-       return 0;
-
-free_urbs:
-       for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++)
-               usb_free_urb(cam->urb[i]);
-
-free_buffers:
-       for (i = 0; (i < SN9C102_URBS) && cam->transfer_buffer[i]; i++)
-               kfree(cam->transfer_buffer[i]);
-
-       return err;
-}
-
-
-static int sn9c102_stop_transfer(struct sn9c102_device* cam)
-{
-       struct usb_device *udev = cam->usbdev;
-       s8 i;
-       int err = 0;
-
-       if (cam->state & DEV_DISCONNECTED)
-               return 0;
-
-       for (i = SN9C102_URBS-1; i >= 0; i--) {
-               usb_kill_urb(cam->urb[i]);
-               usb_free_urb(cam->urb[i]);
-               kfree(cam->transfer_buffer[i]);
-       }
-
-       err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */
-       if (err)
-               DBG(3, "usb_set_interface() failed");
-
-       return err;
-}
-
-
-static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
-{
-       cam->stream = STREAM_INTERRUPT;
-       wait_event_timeout(cam->wait_stream,
-                                    (cam->stream == STREAM_OFF) ||
-                                    (cam->state & DEV_DISCONNECTED),
-                                    SN9C102_URB_TIMEOUT);
-       if (cam->state & DEV_DISCONNECTED)
-               return -ENODEV;
-       else if (cam->stream != STREAM_OFF) {
-               cam->state |= DEV_MISCONFIGURED;
-               DBG(1, "URB timeout reached. The camera is misconfigured. "
-                      "To use it, close and open %s again.",
-                   video_device_node_name(cam->v4ldev));
-               return -EIO;
-       }
-
-       return 0;
-}
-
-/*****************************************************************************/
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count)
-{
-       char str[7];
-       char* endp;
-       unsigned long val;
-
-       if (len < 6) {
-               strncpy(str, buff, len);
-               str[len] = '\0';
-       } else {
-               strncpy(str, buff, 6);
-               str[6] = '\0';
-       }
-
-       val = simple_strtoul(str, &endp, 0);
-
-       *count = 0;
-       if (val <= 0xffff)
-               *count = (ssize_t)(endp - str);
-       if ((*count) && (len == *count+1) && (buff[*count] == '\n'))
-               *count += 1;
-
-       return (u16)val;
-}
-
-/*
-   NOTE 1: being inside one of the following methods implies that the v4l
-          device exists for sure (see kobjects and reference counters)
-   NOTE 2: buffers are PAGE_SIZE long
-*/
-
-static ssize_t sn9c102_show_reg(struct device* cd,
-                               struct device_attribute *attr, char* buf)
-{
-       struct sn9c102_device* cam;
-       ssize_t count;
-
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-               return -ERESTARTSYS;
-
-       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-       if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -ENODEV;
-       }
-
-       count = sprintf(buf, "%u\n", cam->sysfs.reg);
-
-       mutex_unlock(&sn9c102_sysfs_lock);
-
-       return count;
-}
-
-
-static ssize_t
-sn9c102_store_reg(struct device* cd, struct device_attribute *attr,
-                 const char* buf, size_t len)
-{
-       struct sn9c102_device* cam;
-       u16 index;
-       ssize_t count;
-
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-               return -ERESTARTSYS;
-
-       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-       if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -ENODEV;
-       }
-
-       index = sn9c102_strtou16(buf, len, &count);
-       if (index >= ARRAY_SIZE(cam->reg) || !count) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -EINVAL;
-       }
-
-       cam->sysfs.reg = index;
-
-       DBG(2, "Moved SN9C1XX register index to 0x%02X", cam->sysfs.reg);
-       DBG(3, "Written bytes: %zd", count);
-
-       mutex_unlock(&sn9c102_sysfs_lock);
-
-       return count;
-}
-
-
-static ssize_t sn9c102_show_val(struct device* cd,
-                               struct device_attribute *attr, char* buf)
-{
-       struct sn9c102_device* cam;
-       ssize_t count;
-       int val;
-
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-               return -ERESTARTSYS;
-
-       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-       if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -ENODEV;
-       }
-
-       if ((val = sn9c102_read_reg(cam, cam->sysfs.reg)) < 0) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -EIO;
-       }
-
-       count = sprintf(buf, "%d\n", val);
-
-       DBG(3, "Read bytes: %zd, value: %d", count, val);
-
-       mutex_unlock(&sn9c102_sysfs_lock);
-
-       return count;
-}
-
-
-static ssize_t
-sn9c102_store_val(struct device* cd, struct device_attribute *attr,
-                 const char* buf, size_t len)
-{
-       struct sn9c102_device* cam;
-       u16 value;
-       ssize_t count;
-       int err;
-
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-               return -ERESTARTSYS;
-
-       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-       if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -ENODEV;
-       }
-
-       value = sn9c102_strtou16(buf, len, &count);
-       if (!count) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -EINVAL;
-       }
-
-       err = sn9c102_write_reg(cam, value, cam->sysfs.reg);
-       if (err) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -EIO;
-       }
-
-       DBG(2, "Written SN9C1XX reg. 0x%02X, val. 0x%02X",
-           cam->sysfs.reg, value);
-       DBG(3, "Written bytes: %zd", count);
-
-       mutex_unlock(&sn9c102_sysfs_lock);
-
-       return count;
-}
-
-
-static ssize_t sn9c102_show_i2c_reg(struct device* cd,
-                                   struct device_attribute *attr, char* buf)
-{
-       struct sn9c102_device* cam;
-       ssize_t count;
-
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-               return -ERESTARTSYS;
-
-       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-       if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -ENODEV;
-       }
-
-       count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg);
-
-       DBG(3, "Read bytes: %zd", count);
-
-       mutex_unlock(&sn9c102_sysfs_lock);
-
-       return count;
-}
-
-
-static ssize_t
-sn9c102_store_i2c_reg(struct device* cd, struct device_attribute *attr,
-                     const char* buf, size_t len)
-{
-       struct sn9c102_device* cam;
-       u16 index;
-       ssize_t count;
-
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-               return -ERESTARTSYS;
-
-       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-       if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -ENODEV;
-       }
-
-       index = sn9c102_strtou16(buf, len, &count);
-       if (!count) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -EINVAL;
-       }
-
-       cam->sysfs.i2c_reg = index;
-
-       DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg);
-       DBG(3, "Written bytes: %zd", count);
-
-       mutex_unlock(&sn9c102_sysfs_lock);
-
-       return count;
-}
-
-
-static ssize_t sn9c102_show_i2c_val(struct device* cd,
-                                   struct device_attribute *attr, char* buf)
-{
-       struct sn9c102_device* cam;
-       ssize_t count;
-       int val;
-
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-               return -ERESTARTSYS;
-
-       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-       if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -ENODEV;
-       }
-
-       if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -ENOSYS;
-       }
-
-       if ((val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -EIO;
-       }
-
-       count = sprintf(buf, "%d\n", val);
-
-       DBG(3, "Read bytes: %zd, value: %d", count, val);
-
-       mutex_unlock(&sn9c102_sysfs_lock);
-
-       return count;
-}
-
-
-static ssize_t
-sn9c102_store_i2c_val(struct device* cd, struct device_attribute *attr,
-                     const char* buf, size_t len)
-{
-       struct sn9c102_device* cam;
-       u16 value;
-       ssize_t count;
-       int err;
-
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-               return -ERESTARTSYS;
-
-       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-       if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -ENODEV;
-       }
-
-       if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -ENOSYS;
-       }
-
-       value = sn9c102_strtou16(buf, len, &count);
-       if (!count) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -EINVAL;
-       }
-
-       err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value);
-       if (err) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -EIO;
-       }
-
-       DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X",
-           cam->sysfs.i2c_reg, value);
-       DBG(3, "Written bytes: %zd", count);
-
-       mutex_unlock(&sn9c102_sysfs_lock);
-
-       return count;
-}
-
-
-static ssize_t
-sn9c102_store_green(struct device* cd, struct device_attribute *attr,
-                   const char* buf, size_t len)
-{
-       struct sn9c102_device* cam;
-       enum sn9c102_bridge bridge;
-       ssize_t res = 0;
-       u16 value;
-       ssize_t count;
-
-       if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
-               return -ERESTARTSYS;
-
-       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-       if (!cam) {
-               mutex_unlock(&sn9c102_sysfs_lock);
-               return -ENODEV;
-       }
-
-       bridge = cam->bridge;
-
-       mutex_unlock(&sn9c102_sysfs_lock);
-
-       value = sn9c102_strtou16(buf, len, &count);
-       if (!count)
-               return -EINVAL;
-
-       switch (bridge) {
-       case BRIDGE_SN9C101:
-       case BRIDGE_SN9C102:
-               if (value > 0x0f)
-                       return -EINVAL;
-               if ((res = sn9c102_store_reg(cd, attr, "0x11", 4)) >= 0)
-                       res = sn9c102_store_val(cd, attr, buf, len);
-               break;
-       case BRIDGE_SN9C103:
-       case BRIDGE_SN9C105:
-       case BRIDGE_SN9C120:
-               if (value > 0x7f)
-                       return -EINVAL;
-               if ((res = sn9c102_store_reg(cd, attr, "0x07", 4)) >= 0)
-                       res = sn9c102_store_val(cd, attr, buf, len);
-               break;
-       }
-
-       return res;
-}
-
-
-static ssize_t
-sn9c102_store_blue(struct device* cd, struct device_attribute *attr,
-                  const char* buf, size_t len)
-{
-       ssize_t res = 0;
-       u16 value;
-       ssize_t count;
-
-       value = sn9c102_strtou16(buf, len, &count);
-       if (!count || value > 0x7f)
-               return -EINVAL;
-
-       if ((res = sn9c102_store_reg(cd, attr, "0x06", 4)) >= 0)
-               res = sn9c102_store_val(cd, attr, buf, len);
-
-       return res;
-}
-
-
-static ssize_t
-sn9c102_store_red(struct device* cd, struct device_attribute *attr,
-                 const char* buf, size_t len)
-{
-       ssize_t res = 0;
-       u16 value;
-       ssize_t count;
-
-       value = sn9c102_strtou16(buf, len, &count);
-       if (!count || value > 0x7f)
-               return -EINVAL;
-
-       if ((res = sn9c102_store_reg(cd, attr, "0x05", 4)) >= 0)
-               res = sn9c102_store_val(cd, attr, buf, len);
-
-       return res;
-}
-
-
-static ssize_t sn9c102_show_frame_header(struct device* cd,
-                                        struct device_attribute *attr,
-                                        char* buf)
-{
-       struct sn9c102_device* cam;
-       ssize_t count;
-
-       cam = video_get_drvdata(container_of(cd, struct video_device, dev));
-       if (!cam)
-               return -ENODEV;
-
-       count = sizeof(cam->sysfs.frame_header);
-       memcpy(buf, cam->sysfs.frame_header, count);
-
-       DBG(3, "Frame header, read bytes: %zd", count);
-
-       return count;
-}
-
-
-static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, sn9c102_show_reg, sn9c102_store_reg);
-static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, sn9c102_show_val, sn9c102_store_val);
-static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
-                  sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
-static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
-                  sn9c102_show_i2c_val, sn9c102_store_i2c_val);
-static DEVICE_ATTR(green, S_IWUSR, NULL, sn9c102_store_green);
-static DEVICE_ATTR(blue, S_IWUSR, NULL, sn9c102_store_blue);
-static DEVICE_ATTR(red, S_IWUSR, NULL, sn9c102_store_red);
-static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL);
-
-
-static int sn9c102_create_sysfs(struct sn9c102_device* cam)
-{
-       struct device *dev = &(cam->v4ldev->dev);
-       int err = 0;
-
-       if ((err = device_create_file(dev, &dev_attr_reg)))
-               goto err_out;
-       if ((err = device_create_file(dev, &dev_attr_val)))
-               goto err_reg;
-       if ((err = device_create_file(dev, &dev_attr_frame_header)))
-               goto err_val;
-
-       if (cam->sensor.sysfs_ops) {
-               if ((err = device_create_file(dev, &dev_attr_i2c_reg)))
-                       goto err_frame_header;
-               if ((err = device_create_file(dev, &dev_attr_i2c_val)))
-                       goto err_i2c_reg;
-       }
-
-       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
-               if ((err = device_create_file(dev, &dev_attr_green)))
-                       goto err_i2c_val;
-       } else {
-               if ((err = device_create_file(dev, &dev_attr_blue)))
-                       goto err_i2c_val;
-               if ((err = device_create_file(dev, &dev_attr_red)))
-                       goto err_blue;
-       }
-
-       return 0;
-
-err_blue:
-       device_remove_file(dev, &dev_attr_blue);
-err_i2c_val:
-       if (cam->sensor.sysfs_ops)
-               device_remove_file(dev, &dev_attr_i2c_val);
-err_i2c_reg:
-       if (cam->sensor.sysfs_ops)
-               device_remove_file(dev, &dev_attr_i2c_reg);
-err_frame_header:
-       device_remove_file(dev, &dev_attr_frame_header);
-err_val:
-       device_remove_file(dev, &dev_attr_val);
-err_reg:
-       device_remove_file(dev, &dev_attr_reg);
-err_out:
-       return err;
-}
-#endif /* CONFIG_VIDEO_ADV_DEBUG */
-
-/*****************************************************************************/
-
-static int
-sn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix)
-{
-       int err = 0;
-
-       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
-           pix->pixelformat == V4L2_PIX_FMT_JPEG) {
-               switch (cam->bridge) {
-               case BRIDGE_SN9C101:
-               case BRIDGE_SN9C102:
-               case BRIDGE_SN9C103:
-                       err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
-                                                0x18);
-                       break;
-               case BRIDGE_SN9C105:
-               case BRIDGE_SN9C120:
-                       err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
-                                                0x18);
-                       break;
-               }
-       } else {
-               switch (cam->bridge) {
-               case BRIDGE_SN9C101:
-               case BRIDGE_SN9C102:
-               case BRIDGE_SN9C103:
-                       err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
-                                                0x18);
-                       break;
-               case BRIDGE_SN9C105:
-               case BRIDGE_SN9C120:
-                       err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
-                                                0x18);
-                       break;
-               }
-       }
-
-       return err ? -EIO : 0;
-}
-
-
-static int
-sn9c102_set_compression(struct sn9c102_device* cam,
-                       struct v4l2_jpegcompression* compression)
-{
-       int i, err = 0;
-
-       switch (cam->bridge) {
-       case BRIDGE_SN9C101:
-       case BRIDGE_SN9C102:
-       case BRIDGE_SN9C103:
-               if (compression->quality == 0)
-                       err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01,
-                                                0x17);
-               else if (compression->quality == 1)
-                       err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe,
-                                                0x17);
-               break;
-       case BRIDGE_SN9C105:
-       case BRIDGE_SN9C120:
-               if (compression->quality == 0) {
-                       for (i = 0; i <= 63; i++) {
-                               err += sn9c102_write_reg(cam,
-                                                        SN9C102_Y_QTABLE1[i],
-                                                        0x100 + i);
-                               err += sn9c102_write_reg(cam,
-                                                        SN9C102_UV_QTABLE1[i],
-                                                        0x140 + i);
-                       }
-                       err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf,
-                                                0x18);
-               } else if (compression->quality == 1) {
-                       for (i = 0; i <= 63; i++) {
-                               err += sn9c102_write_reg(cam,
-                                                        SN9C102_Y_QTABLE1[i],
-                                                        0x100 + i);
-                               err += sn9c102_write_reg(cam,
-                                                        SN9C102_UV_QTABLE1[i],
-                                                        0x140 + i);
-                       }
-                       err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x40,
-                                                0x18);
-               }
-               break;
-       }
-
-       return err ? -EIO : 0;
-}
-
-
-static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale)
-{
-       u8 r = 0;
-       int err = 0;
-
-       if (scale == 1)
-               r = cam->reg[0x18] & 0xcf;
-       else if (scale == 2) {
-               r = cam->reg[0x18] & 0xcf;
-               r |= 0x10;
-       } else if (scale == 4)
-               r = cam->reg[0x18] | 0x20;
-
-       err += sn9c102_write_reg(cam, r, 0x18);
-       if (err)
-               return -EIO;
-
-       PDBGG("Scaling factor: %u", scale);
-
-       return 0;
-}
-
-
-static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect)
-{
-       struct sn9c102_sensor* s = &cam->sensor;
-       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left),
-          v_start = (u8)(rect->top - s->cropcap.bounds.top),
-          h_size = (u8)(rect->width / 16),
-          v_size = (u8)(rect->height / 16);
-       int err = 0;
-
-       err += sn9c102_write_reg(cam, h_start, 0x12);
-       err += sn9c102_write_reg(cam, v_start, 0x13);
-       err += sn9c102_write_reg(cam, h_size, 0x15);
-       err += sn9c102_write_reg(cam, v_size, 0x16);
-       if (err)
-               return -EIO;
-
-       PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size "
-             "%u %u %u %u", h_start, v_start, h_size, v_size);
-
-       return 0;
-}
-
-
-static int sn9c102_init(struct sn9c102_device* cam)
-{
-       struct sn9c102_sensor* s = &cam->sensor;
-       struct v4l2_control ctrl;
-       struct v4l2_queryctrl *qctrl;
-       struct v4l2_rect* rect;
-       u8 i = 0;
-       int err = 0;
-
-       if (!(cam->state & DEV_INITIALIZED)) {
-               mutex_init(&cam->open_mutex);
-               init_waitqueue_head(&cam->wait_open);
-               qctrl = s->qctrl;
-               rect = &(s->cropcap.defrect);
-       } else { /* use current values */
-               qctrl = s->_qctrl;
-               rect = &(s->_rect);
-       }
-
-       err += sn9c102_set_scale(cam, rect->width / s->pix_format.width);
-       err += sn9c102_set_crop(cam, rect);
-       if (err)
-               return err;
-
-       if (s->init) {
-               err = s->init(cam);
-               if (err) {
-                       DBG(3, "Sensor initialization failed");
-                       return err;
-               }
-       }
-
-       if (!(cam->state & DEV_INITIALIZED))
-               if (cam->bridge == BRIDGE_SN9C101 ||
-                   cam->bridge == BRIDGE_SN9C102 ||
-                   cam->bridge == BRIDGE_SN9C103) {
-                       if (s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
-                               s->pix_format.pixelformat= V4L2_PIX_FMT_SBGGR8;
-                       cam->compression.quality =  cam->reg[0x17] & 0x01 ?
-                                                   0 : 1;
-               } else {
-                       if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
-                               s->pix_format.pixelformat = V4L2_PIX_FMT_JPEG;
-                       cam->compression.quality =  cam->reg[0x18] & 0x40 ?
-                                                   0 : 1;
-                       err += sn9c102_set_compression(cam, &cam->compression);
-               }
-       else
-               err += sn9c102_set_compression(cam, &cam->compression);
-       err += sn9c102_set_pix_format(cam, &s->pix_format);
-       if (s->set_pix_format)
-               err += s->set_pix_format(cam, &s->pix_format);
-       if (err)
-               return err;
-
-       if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
-           s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
-               DBG(3, "Compressed video format is active, quality %d",
-                   cam->compression.quality);
-       else
-               DBG(3, "Uncompressed video format is active");
-
-       if (s->set_crop)
-               if ((err = s->set_crop(cam, rect))) {
-                       DBG(3, "set_crop() failed");
-                       return err;
-               }
-
-       if (s->set_ctrl) {
-               for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
-                       if (s->qctrl[i].id != 0 &&
-                           !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) {
-                               ctrl.id = s->qctrl[i].id;
-                               ctrl.value = qctrl[i].default_value;
-                               err = s->set_ctrl(cam, &ctrl);
-                               if (err) {
-                                       DBG(3, "Set %s control failed",
-                                           s->qctrl[i].name);
-                                       return err;
-                               }
-                               DBG(3, "Image sensor supports '%s' control",
-                                   s->qctrl[i].name);
-                       }
-       }
-
-       if (!(cam->state & DEV_INITIALIZED)) {
-               mutex_init(&cam->fileop_mutex);
-               spin_lock_init(&cam->queue_lock);
-               init_waitqueue_head(&cam->wait_frame);
-               init_waitqueue_head(&cam->wait_stream);
-               cam->nreadbuffers = 2;
-               memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl));
-               memcpy(&(s->_rect), &(s->cropcap.defrect),
-                      sizeof(struct v4l2_rect));
-               cam->state |= DEV_INITIALIZED;
-       }
-
-       DBG(2, "Initialization succeeded");
-       return 0;
-}
-
-/*****************************************************************************/
-
-static void sn9c102_release_resources(struct kref *kref)
-{
-       struct sn9c102_device *cam;
-
-       mutex_lock(&sn9c102_sysfs_lock);
-
-       cam = container_of(kref, struct sn9c102_device, kref);
-
-       DBG(2, "V4L2 device %s deregistered",
-           video_device_node_name(cam->v4ldev));
-       video_set_drvdata(cam->v4ldev, NULL);
-       video_unregister_device(cam->v4ldev);
-       usb_put_dev(cam->usbdev);
-       kfree(cam->control_buffer);
-       kfree(cam);
-
-       mutex_unlock(&sn9c102_sysfs_lock);
-
-}
-
-
-static int sn9c102_open(struct file *filp)
-{
-       struct sn9c102_device* cam;
-       int err = 0;
-
-       /*
-          A read_trylock() in open() is the only safe way to prevent race
-          conditions with disconnect(), one close() and multiple (not
-          necessarily simultaneous) attempts to open(). For example, it
-          prevents from waiting for a second access, while the device
-          structure is being deallocated, after a possible disconnect() and
-          during a following close() holding the write lock: given that, after
-          this deallocation, no access will be possible anymore, using the
-          non-trylock version would have let open() gain the access to the
-          device structure improperly.
-          For this reason the lock must also not be per-device.
-       */
-       if (!down_read_trylock(&sn9c102_dev_lock))
-               return -ERESTARTSYS;
-
-       cam = video_drvdata(filp);
-
-       if (wait_for_completion_interruptible(&cam->probe)) {
-               up_read(&sn9c102_dev_lock);
-               return -ERESTARTSYS;
-       }
-
-       kref_get(&cam->kref);
-
-       /*
-           Make sure to isolate all the simultaneous opens.
-       */
-       if (mutex_lock_interruptible(&cam->open_mutex)) {
-               kref_put(&cam->kref, sn9c102_release_resources);
-               up_read(&sn9c102_dev_lock);
-               return -ERESTARTSYS;
-       }
-
-       if (cam->state & DEV_DISCONNECTED) {
-               DBG(1, "Device not present");
-               err = -ENODEV;
-               goto out;
-       }
-
-       if (cam->users) {
-               DBG(2, "Device %s is already in use",
-                   video_device_node_name(cam->v4ldev));
-               DBG(3, "Simultaneous opens are not supported");
-               /*
-                  open() must follow the open flags and should block
-                  eventually while the device is in use.
-               */
-               if ((filp->f_flags & O_NONBLOCK) ||
-                   (filp->f_flags & O_NDELAY)) {
-                       err = -EWOULDBLOCK;
-                       goto out;
-               }
-               DBG(2, "A blocking open() has been requested. Wait for the "
-                      "device to be released...");
-               up_read(&sn9c102_dev_lock);
-               /*
-                  We will not release the "open_mutex" lock, so that only one
-                  process can be in the wait queue below. This way the process
-                  will be sleeping while holding the lock, without losing its
-                  priority after any wake_up().
-               */
-               err = wait_event_interruptible_exclusive(cam->wait_open,
-                                               (cam->state & DEV_DISCONNECTED)
-                                                        || !cam->users);
-               down_read(&sn9c102_dev_lock);
-               if (err)
-                       goto out;
-               if (cam->state & DEV_DISCONNECTED) {
-                       err = -ENODEV;
-                       goto out;
-               }
-       }
-
-       if (cam->state & DEV_MISCONFIGURED) {
-               err = sn9c102_init(cam);
-               if (err) {
-                       DBG(1, "Initialization failed again. "
-                              "I will retry on next open().");
-                       goto out;
-               }
-               cam->state &= ~DEV_MISCONFIGURED;
-       }
-
-       if ((err = sn9c102_start_transfer(cam)))
-               goto out;
-
-       filp->private_data = cam;
-       cam->users++;
-       cam->io = IO_NONE;
-       cam->stream = STREAM_OFF;
-       cam->nbuffers = 0;
-       cam->frame_count = 0;
-       sn9c102_empty_framequeues(cam);
-
-       DBG(3, "Video device %s is open", video_device_node_name(cam->v4ldev));
-
-out:
-       mutex_unlock(&cam->open_mutex);
-       if (err)
-               kref_put(&cam->kref, sn9c102_release_resources);
-
-       up_read(&sn9c102_dev_lock);
-       return err;
-}
-
-
-static int sn9c102_release(struct file *filp)
-{
-       struct sn9c102_device* cam;
-
-       down_write(&sn9c102_dev_lock);
-
-       cam = video_drvdata(filp);
-
-       sn9c102_stop_transfer(cam);
-       sn9c102_release_buffers(cam);
-       cam->users--;
-       wake_up_interruptible_nr(&cam->wait_open, 1);
-
-       DBG(3, "Video device %s closed", video_device_node_name(cam->v4ldev));
-
-       kref_put(&cam->kref, sn9c102_release_resources);
-
-       up_write(&sn9c102_dev_lock);
-
-       return 0;
-}
-
-
-static ssize_t
-sn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos)
-{
-       struct sn9c102_device *cam = video_drvdata(filp);
-       struct sn9c102_frame_t* f, * i;
-       unsigned long lock_flags;
-       long timeout;
-       int err = 0;
-
-       if (mutex_lock_interruptible(&cam->fileop_mutex))
-               return -ERESTARTSYS;
-
-       if (cam->state & DEV_DISCONNECTED) {
-               DBG(1, "Device not present");
-               mutex_unlock(&cam->fileop_mutex);
-               return -ENODEV;
-       }
-
-       if (cam->state & DEV_MISCONFIGURED) {
-               DBG(1, "The camera is misconfigured. Close and open it "
-                      "again.");
-               mutex_unlock(&cam->fileop_mutex);
-               return -EIO;
-       }
-
-       if (cam->io == IO_MMAP) {
-               DBG(3, "Close and open the device again to choose "
-                      "the read method");
-               mutex_unlock(&cam->fileop_mutex);
-               return -EBUSY;
-       }
-
-       if (cam->io == IO_NONE) {
-               if (!sn9c102_request_buffers(cam,cam->nreadbuffers, IO_READ)) {
-                       DBG(1, "read() failed, not enough memory");
-                       mutex_unlock(&cam->fileop_mutex);
-                       return -ENOMEM;
-               }
-               cam->io = IO_READ;
-               cam->stream = STREAM_ON;
-       }
-
-       if (list_empty(&cam->inqueue)) {
-               if (!list_empty(&cam->outqueue))
-                       sn9c102_empty_framequeues(cam);
-               sn9c102_queue_unusedframes(cam);
-       }
-
-       if (!count) {
-               mutex_unlock(&cam->fileop_mutex);
-               return 0;
-       }
-
-       if (list_empty(&cam->outqueue)) {
-               if (filp->f_flags & O_NONBLOCK) {
-                       mutex_unlock(&cam->fileop_mutex);
-                       return -EAGAIN;
-               }
-               if (!cam->module_param.frame_timeout) {
-                       err = wait_event_interruptible
-                             ( cam->wait_frame,
-                               (!list_empty(&cam->outqueue)) ||
-                               (cam->state & DEV_DISCONNECTED) ||
-                               (cam->state & DEV_MISCONFIGURED) );
-                       if (err) {
-                               mutex_unlock(&cam->fileop_mutex);
-                               return err;
-                       }
-               } else {
-                       timeout = wait_event_interruptible_timeout
-                                 ( cam->wait_frame,
-                                   (!list_empty(&cam->outqueue)) ||
-                                   (cam->state & DEV_DISCONNECTED) ||
-                                   (cam->state & DEV_MISCONFIGURED),
-                                   msecs_to_jiffies(
-                                       cam->module_param.frame_timeout * 1000
-                                   )
-                                 );
-                       if (timeout < 0) {
-                               mutex_unlock(&cam->fileop_mutex);
-                               return timeout;
-                       } else if (timeout == 0 &&
-                                  !(cam->state & DEV_DISCONNECTED)) {
-                               DBG(1, "Video frame timeout elapsed");
-                               mutex_unlock(&cam->fileop_mutex);
-                               return -EIO;
-                       }
-               }
-               if (cam->state & DEV_DISCONNECTED) {
-                       mutex_unlock(&cam->fileop_mutex);
-                       return -ENODEV;
-               }
-               if (cam->state & DEV_MISCONFIGURED) {
-                       mutex_unlock(&cam->fileop_mutex);
-                       return -EIO;
-               }
-       }
-
-       f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame);
-
-       if (count > f->buf.bytesused)
-               count = f->buf.bytesused;
-
-       if (copy_to_user(buf, f->bufmem, count)) {
-               err = -EFAULT;
-               goto exit;
-       }
-       *f_pos += count;
-
-exit:
-       spin_lock_irqsave(&cam->queue_lock, lock_flags);
-       list_for_each_entry(i, &cam->outqueue, frame)
-               i->state = F_UNUSED;
-       INIT_LIST_HEAD(&cam->outqueue);
-       spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-
-       sn9c102_queue_unusedframes(cam);
-
-       PDBGG("Frame #%lu, bytes read: %zu",
-             (unsigned long)f->buf.index, count);
-
-       mutex_unlock(&cam->fileop_mutex);
-
-       return count;
-}
-
-
-static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
-{
-       struct sn9c102_device *cam = video_drvdata(filp);
-       struct sn9c102_frame_t* f;
-       unsigned long lock_flags;
-       unsigned int mask = 0;
-
-       if (mutex_lock_interruptible(&cam->fileop_mutex))
-               return POLLERR;
-
-       if (cam->state & DEV_DISCONNECTED) {
-               DBG(1, "Device not present");
-               goto error;
-       }
-
-       if (cam->state & DEV_MISCONFIGURED) {
-               DBG(1, "The camera is misconfigured. Close and open it "
-                      "again.");
-               goto error;
-       }
-
-       if (cam->io == IO_NONE) {
-               if (!sn9c102_request_buffers(cam, cam->nreadbuffers,
-                                            IO_READ)) {
-                       DBG(1, "poll() failed, not enough memory");
-                       goto error;
-               }
-               cam->io = IO_READ;
-               cam->stream = STREAM_ON;
-       }
-
-       if (cam->io == IO_READ) {
-               spin_lock_irqsave(&cam->queue_lock, lock_flags);
-               list_for_each_entry(f, &cam->outqueue, frame)
-                       f->state = F_UNUSED;
-               INIT_LIST_HEAD(&cam->outqueue);
-               spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-               sn9c102_queue_unusedframes(cam);
-       }
-
-       poll_wait(filp, &cam->wait_frame, wait);
-
-       if (!list_empty(&cam->outqueue))
-               mask |= POLLIN | POLLRDNORM;
-
-       mutex_unlock(&cam->fileop_mutex);
-
-       return mask;
-
-error:
-       mutex_unlock(&cam->fileop_mutex);
-       return POLLERR;
-}
-
-
-static void sn9c102_vm_open(struct vm_area_struct* vma)
-{
-       struct sn9c102_frame_t* f = vma->vm_private_data;
-       f->vma_use_count++;
-}
-
-
-static void sn9c102_vm_close(struct vm_area_struct* vma)
-{
-       /* NOTE: buffers are not freed here */
-       struct sn9c102_frame_t* f = vma->vm_private_data;
-       f->vma_use_count--;
-}
-
-
-static const struct vm_operations_struct sn9c102_vm_ops = {
-       .open = sn9c102_vm_open,
-       .close = sn9c102_vm_close,
-};
-
-
-static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
-{
-       struct sn9c102_device *cam = video_drvdata(filp);
-       unsigned long size = vma->vm_end - vma->vm_start,
-                     start = vma->vm_start;
-       void *pos;
-       u32 i;
-
-       if (mutex_lock_interruptible(&cam->fileop_mutex))
-               return -ERESTARTSYS;
-
-       if (cam->state & DEV_DISCONNECTED) {
-               DBG(1, "Device not present");
-               mutex_unlock(&cam->fileop_mutex);
-               return -ENODEV;
-       }
-
-       if (cam->state & DEV_MISCONFIGURED) {
-               DBG(1, "The camera is misconfigured. Close and open it "
-                      "again.");
-               mutex_unlock(&cam->fileop_mutex);
-               return -EIO;
-       }
-
-       if (!(vma->vm_flags & (VM_WRITE | VM_READ))) {
-               mutex_unlock(&cam->fileop_mutex);
-               return -EACCES;
-       }
-
-       if (cam->io != IO_MMAP ||
-           size != PAGE_ALIGN(cam->frame[0].buf.length)) {
-               mutex_unlock(&cam->fileop_mutex);
-               return -EINVAL;
-       }
-
-       for (i = 0; i < cam->nbuffers; i++) {
-               if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff)
-                       break;
-       }
-       if (i == cam->nbuffers) {
-               mutex_unlock(&cam->fileop_mutex);
-               return -EINVAL;
-       }
-
-       vma->vm_flags |= VM_IO;
-       vma->vm_flags |= VM_RESERVED;
-
-       pos = cam->frame[i].bufmem;
-       while (size > 0) { /* size is page-aligned */
-               if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
-                       mutex_unlock(&cam->fileop_mutex);
-                       return -EAGAIN;
-               }
-               start += PAGE_SIZE;
-               pos += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-
-       vma->vm_ops = &sn9c102_vm_ops;
-       vma->vm_private_data = &cam->frame[i];
-       sn9c102_vm_open(vma);
-
-       mutex_unlock(&cam->fileop_mutex);
-
-       return 0;
-}
-
-/*****************************************************************************/
-
-static int
-sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_capability cap = {
-               .driver = "sn9c102",
-               .version = LINUX_VERSION_CODE,
-               .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
-                               V4L2_CAP_STREAMING,
-       };
-
-       strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
-       if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
-               strlcpy(cap.bus_info, dev_name(&cam->usbdev->dev),
-                       sizeof(cap.bus_info));
-
-       if (copy_to_user(arg, &cap, sizeof(cap)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_input i;
-
-       if (copy_from_user(&i, arg, sizeof(i)))
-               return -EFAULT;
-
-       if (i.index)
-               return -EINVAL;
-
-       memset(&i, 0, sizeof(i));
-       strcpy(i.name, "Camera");
-       i.type = V4L2_INPUT_TYPE_CAMERA;
-       i.capabilities = V4L2_IN_CAP_STD;
-
-       if (copy_to_user(arg, &i, sizeof(i)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_input(struct sn9c102_device* cam, void __user * arg)
-{
-       int index = 0;
-
-       if (copy_to_user(arg, &index, sizeof(index)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_input(struct sn9c102_device* cam, void __user * arg)
-{
-       int index;
-
-       if (copy_from_user(&index, arg, sizeof(index)))
-               return -EFAULT;
-
-       if (index != 0)
-               return -EINVAL;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_query_ctrl(struct sn9c102_device* cam, void __user * arg)
-{
-       struct sn9c102_sensor* s = &cam->sensor;
-       struct v4l2_queryctrl qc;
-       u8 i;
-
-       if (copy_from_user(&qc, arg, sizeof(qc)))
-               return -EFAULT;
-
-       for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
-               if (qc.id && qc.id == s->qctrl[i].id) {
-                       memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
-                       if (copy_to_user(arg, &qc, sizeof(qc)))
-                               return -EFAULT;
-                       return 0;
-               }
-
-       return -EINVAL;
-}
-
-
-static int
-sn9c102_vidioc_g_ctrl(struct sn9c102_device* cam, void __user * arg)
-{
-       struct sn9c102_sensor* s = &cam->sensor;
-       struct v4l2_control ctrl;
-       int err = 0;
-       u8 i;
-
-       if (!s->get_ctrl && !s->set_ctrl)
-               return -EINVAL;
-
-       if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
-               return -EFAULT;
-
-       if (!s->get_ctrl) {
-               for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
-                       if (ctrl.id && ctrl.id == s->qctrl[i].id) {
-                               ctrl.value = s->_qctrl[i].default_value;
-                               goto exit;
-                       }
-               return -EINVAL;
-       } else
-               err = s->get_ctrl(cam, &ctrl);
-
-exit:
-       if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
-               return -EFAULT;
-
-       PDBGG("VIDIOC_G_CTRL: id %lu, value %lu",
-             (unsigned long)ctrl.id, (unsigned long)ctrl.value);
-
-       return err;
-}
-
-
-static int
-sn9c102_vidioc_s_ctrl(struct sn9c102_device* cam, void __user * arg)
-{
-       struct sn9c102_sensor* s = &cam->sensor;
-       struct v4l2_control ctrl;
-       u8 i;
-       int err = 0;
-
-       if (!s->set_ctrl)
-               return -EINVAL;
-
-       if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
-               return -EFAULT;
-
-       for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) {
-               if (ctrl.id == s->qctrl[i].id) {
-                       if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)
-                               return -EINVAL;
-                       if (ctrl.value < s->qctrl[i].minimum ||
-                           ctrl.value > s->qctrl[i].maximum)
-                               return -ERANGE;
-                       ctrl.value -= ctrl.value % s->qctrl[i].step;
-                       break;
-               }
-       }
-       if (i == ARRAY_SIZE(s->qctrl))
-               return -EINVAL;
-       if ((err = s->set_ctrl(cam, &ctrl)))
-               return err;
-
-       s->_qctrl[i].default_value = ctrl.value;
-
-       PDBGG("VIDIOC_S_CTRL: id %lu, value %lu",
-             (unsigned long)ctrl.id, (unsigned long)ctrl.value);
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_cropcap(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_cropcap* cc = &(cam->sensor.cropcap);
-
-       cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       cc->pixelaspect.numerator = 1;
-       cc->pixelaspect.denominator = 1;
-
-       if (copy_to_user(arg, cc, sizeof(*cc)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_crop(struct sn9c102_device* cam, void __user * arg)
-{
-       struct sn9c102_sensor* s = &cam->sensor;
-       struct v4l2_crop crop = {
-               .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
-       };
-
-       memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
-
-       if (copy_to_user(arg, &crop, sizeof(crop)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_crop(struct sn9c102_device* cam, void __user * arg)
-{
-       struct sn9c102_sensor* s = &cam->sensor;
-       struct v4l2_crop crop;
-       struct v4l2_rect* rect;
-       struct v4l2_rect* bounds = &(s->cropcap.bounds);
-       struct v4l2_pix_format* pix_format = &(s->pix_format);
-       u8 scale;
-       const enum sn9c102_stream_state stream = cam->stream;
-       const u32 nbuffers = cam->nbuffers;
-       u32 i;
-       int err = 0;
-
-       if (copy_from_user(&crop, arg, sizeof(crop)))
-               return -EFAULT;
-
-       rect = &(crop.c);
-
-       if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       if (cam->module_param.force_munmap)
-               for (i = 0; i < cam->nbuffers; i++)
-                       if (cam->frame[i].vma_use_count) {
-                               DBG(3, "VIDIOC_S_CROP failed. "
-                                      "Unmap the buffers first.");
-                               return -EBUSY;
-                       }
-
-       /* Preserve R,G or B origin */
-       rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;
-       rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;
-
-       if (rect->width < 16)
-               rect->width = 16;
-       if (rect->height < 16)
-               rect->height = 16;
-       if (rect->width > bounds->width)
-               rect->width = bounds->width;
-       if (rect->height > bounds->height)
-               rect->height = bounds->height;
-       if (rect->left < bounds->left)
-               rect->left = bounds->left;
-       if (rect->top < bounds->top)
-               rect->top = bounds->top;
-       if (rect->left + rect->width > bounds->left + bounds->width)
-               rect->left = bounds->left+bounds->width - rect->width;
-       if (rect->top + rect->height > bounds->top + bounds->height)
-               rect->top = bounds->top+bounds->height - rect->height;
-
-       rect->width &= ~15L;
-       rect->height &= ~15L;
-
-       if (SN9C102_PRESERVE_IMGSCALE) {
-               /* Calculate the actual scaling factor */
-               u32 a, b;
-               a = rect->width * rect->height;
-               b = pix_format->width * pix_format->height;
-               scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
-       } else
-               scale = 1;
-
-       if (cam->stream == STREAM_ON)
-               if ((err = sn9c102_stream_interrupt(cam)))
-                       return err;
-
-       if (copy_to_user(arg, &crop, sizeof(crop))) {
-               cam->stream = stream;
-               return -EFAULT;
-       }
-
-       if (cam->module_param.force_munmap || cam->io == IO_READ)
-               sn9c102_release_buffers(cam);
-
-       err = sn9c102_set_crop(cam, rect);
-       if (s->set_crop)
-               err += s->set_crop(cam, rect);
-       err += sn9c102_set_scale(cam, scale);
-
-       if (err) { /* atomic, no rollback in ioctl() */
-               cam->state |= DEV_MISCONFIGURED;
-               DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
-                      "use the camera, close and open %s again.",
-                   video_device_node_name(cam->v4ldev));
-               return -EIO;
-       }
-
-       s->pix_format.width = rect->width/scale;
-       s->pix_format.height = rect->height/scale;
-       memcpy(&(s->_rect), rect, sizeof(*rect));
-
-       if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
-           nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
-               cam->state |= DEV_MISCONFIGURED;
-               DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
-                      "use the camera, close and open %s again.",
-                   video_device_node_name(cam->v4ldev));
-               return -ENOMEM;
-       }
-
-       if (cam->io == IO_READ)
-               sn9c102_empty_framequeues(cam);
-       else if (cam->module_param.force_munmap)
-               sn9c102_requeue_outqueue(cam);
-
-       cam->stream = stream;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_enum_framesizes(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_frmsizeenum frmsize;
-
-       if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
-               return -EFAULT;
-
-       if (frmsize.index != 0)
-               return -EINVAL;
-
-       switch (cam->bridge) {
-       case BRIDGE_SN9C101:
-       case BRIDGE_SN9C102:
-       case BRIDGE_SN9C103:
-               if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X &&
-                   frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
-                       return -EINVAL;
-       case BRIDGE_SN9C105:
-       case BRIDGE_SN9C120:
-               if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG &&
-                   frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
-                       return -EINVAL;
-       }
-
-       frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE;
-       frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16;
-       frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16;
-       frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width;
-       frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height;
-       memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
-
-       if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_enum_fmt(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_fmtdesc fmtd;
-
-       if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
-               return -EFAULT;
-
-       if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       if (fmtd.index == 0) {
-               strcpy(fmtd.description, "bayer rgb");
-               fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
-       } else if (fmtd.index == 1) {
-               switch (cam->bridge) {
-               case BRIDGE_SN9C101:
-               case BRIDGE_SN9C102:
-               case BRIDGE_SN9C103:
-                       strcpy(fmtd.description, "compressed");
-                       fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
-                       break;
-               case BRIDGE_SN9C105:
-               case BRIDGE_SN9C120:
-                       strcpy(fmtd.description, "JPEG");
-                       fmtd.pixelformat = V4L2_PIX_FMT_JPEG;
-                       break;
-               }
-               fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
-       } else
-               return -EINVAL;
-
-       fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
-
-       if (copy_to_user(arg, &fmtd, sizeof(fmtd)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_fmt(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_format format;
-       struct v4l2_pix_format* pfmt = &(cam->sensor.pix_format);
-
-       if (copy_from_user(&format, arg, sizeof(format)))
-               return -EFAULT;
-
-       if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ?
-                          V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
-       pfmt->bytesperline = (pfmt->pixelformat == V4L2_PIX_FMT_SN9C10X ||
-                             pfmt->pixelformat == V4L2_PIX_FMT_JPEG)
-                            ? 0 : (pfmt->width * pfmt->priv) / 8;
-       pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
-       pfmt->field = V4L2_FIELD_NONE;
-       memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
-
-       if (copy_to_user(arg, &format, sizeof(format)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_try_s_fmt(struct sn9c102_device* cam, unsigned int cmd,
-                        void __user * arg)
-{
-       struct sn9c102_sensor* s = &cam->sensor;
-       struct v4l2_format format;
-       struct v4l2_pix_format* pix;
-       struct v4l2_pix_format* pfmt = &(s->pix_format);
-       struct v4l2_rect* bounds = &(s->cropcap.bounds);
-       struct v4l2_rect rect;
-       u8 scale;
-       const enum sn9c102_stream_state stream = cam->stream;
-       const u32 nbuffers = cam->nbuffers;
-       u32 i;
-       int err = 0;
-
-       if (copy_from_user(&format, arg, sizeof(format)))
-               return -EFAULT;
-
-       pix = &(format.fmt.pix);
-
-       if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       memcpy(&rect, &(s->_rect), sizeof(rect));
-
-       { /* calculate the actual scaling factor */
-               u32 a, b;
-               a = rect.width * rect.height;
-               b = pix->width * pix->height;
-               scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
-       }
-
-       rect.width = scale * pix->width;
-       rect.height = scale * pix->height;
-
-       if (rect.width < 16)
-               rect.width = 16;
-       if (rect.height < 16)
-               rect.height = 16;
-       if (rect.width > bounds->left + bounds->width - rect.left)
-               rect.width = bounds->left + bounds->width - rect.left;
-       if (rect.height > bounds->top + bounds->height - rect.top)
-               rect.height = bounds->top + bounds->height - rect.top;
-
-       rect.width &= ~15L;
-       rect.height &= ~15L;
-
-       { /* adjust the scaling factor */
-               u32 a, b;
-               a = rect.width * rect.height;
-               b = pix->width * pix->height;
-               scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
-       }
-
-       pix->width = rect.width / scale;
-       pix->height = rect.height / scale;
-
-       switch (cam->bridge) {
-       case BRIDGE_SN9C101:
-       case BRIDGE_SN9C102:
-       case BRIDGE_SN9C103:
-               if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
-                   pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
-                       pix->pixelformat = pfmt->pixelformat;
-               break;
-       case BRIDGE_SN9C105:
-       case BRIDGE_SN9C120:
-               if (pix->pixelformat != V4L2_PIX_FMT_JPEG &&
-                   pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
-                       pix->pixelformat = pfmt->pixelformat;
-               break;
-       }
-       pix->priv = pfmt->priv; /* bpp */
-       pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_JPEG) ?
-                         V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
-       pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
-                            pix->pixelformat == V4L2_PIX_FMT_JPEG)
-                           ? 0 : (pix->width * pix->priv) / 8;
-       pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
-       pix->field = V4L2_FIELD_NONE;
-
-       if (cmd == VIDIOC_TRY_FMT) {
-               if (copy_to_user(arg, &format, sizeof(format)))
-                       return -EFAULT;
-               return 0;
-       }
-
-       if (cam->module_param.force_munmap)
-               for (i = 0; i < cam->nbuffers; i++)
-                       if (cam->frame[i].vma_use_count) {
-                               DBG(3, "VIDIOC_S_FMT failed. Unmap the "
-                                      "buffers first.");
-                               return -EBUSY;
-                       }
-
-       if (cam->stream == STREAM_ON)
-               if ((err = sn9c102_stream_interrupt(cam)))
-                       return err;
-
-       if (copy_to_user(arg, &format, sizeof(format))) {
-               cam->stream = stream;
-               return -EFAULT;
-       }
-
-       if (cam->module_param.force_munmap  || cam->io == IO_READ)
-               sn9c102_release_buffers(cam);
-
-       err += sn9c102_set_pix_format(cam, pix);
-       err += sn9c102_set_crop(cam, &rect);
-       if (s->set_pix_format)
-               err += s->set_pix_format(cam, pix);
-       if (s->set_crop)
-               err += s->set_crop(cam, &rect);
-       err += sn9c102_set_scale(cam, scale);
-
-       if (err) { /* atomic, no rollback in ioctl() */
-               cam->state |= DEV_MISCONFIGURED;
-               DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
-                      "use the camera, close and open %s again.",
-                   video_device_node_name(cam->v4ldev));
-               return -EIO;
-       }
-
-       memcpy(pfmt, pix, sizeof(*pix));
-       memcpy(&(s->_rect), &rect, sizeof(rect));
-
-       if ((cam->module_param.force_munmap  || cam->io == IO_READ) &&
-           nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
-               cam->state |= DEV_MISCONFIGURED;
-               DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
-                      "use the camera, close and open %s again.",
-                   video_device_node_name(cam->v4ldev));
-               return -ENOMEM;
-       }
-
-       if (cam->io == IO_READ)
-               sn9c102_empty_framequeues(cam);
-       else if (cam->module_param.force_munmap)
-               sn9c102_requeue_outqueue(cam);
-
-       cam->stream = stream;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_jpegcomp(struct sn9c102_device* cam, void __user * arg)
-{
-       if (copy_to_user(arg, &cam->compression, sizeof(cam->compression)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_jpegcomp(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_jpegcompression jc;
-       const enum sn9c102_stream_state stream = cam->stream;
-       int err = 0;
-
-       if (copy_from_user(&jc, arg, sizeof(jc)))
-               return -EFAULT;
-
-       if (jc.quality != 0 && jc.quality != 1)
-               return -EINVAL;
-
-       if (cam->stream == STREAM_ON)
-               if ((err = sn9c102_stream_interrupt(cam)))
-                       return err;
-
-       err += sn9c102_set_compression(cam, &jc);
-       if (err) { /* atomic, no rollback in ioctl() */
-               cam->state |= DEV_MISCONFIGURED;
-               DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware problems. "
-                      "To use the camera, close and open %s again.",
-                   video_device_node_name(cam->v4ldev));
-               return -EIO;
-       }
-
-       cam->compression.quality = jc.quality;
-
-       cam->stream = stream;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_reqbufs(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_requestbuffers rb;
-       u32 i;
-       int err;
-
-       if (copy_from_user(&rb, arg, sizeof(rb)))
-               return -EFAULT;
-
-       if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-           rb.memory != V4L2_MEMORY_MMAP)
-               return -EINVAL;
-
-       if (cam->io == IO_READ) {
-               DBG(3, "Close and open the device again to choose the mmap "
-                      "I/O method");
-               return -EBUSY;
-       }
-
-       for (i = 0; i < cam->nbuffers; i++)
-               if (cam->frame[i].vma_use_count) {
-                       DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are "
-                              "still mapped.");
-                       return -EBUSY;
-               }
-
-       if (cam->stream == STREAM_ON)
-               if ((err = sn9c102_stream_interrupt(cam)))
-                       return err;
-
-       sn9c102_empty_framequeues(cam);
-
-       sn9c102_release_buffers(cam);
-       if (rb.count)
-               rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP);
-
-       if (copy_to_user(arg, &rb, sizeof(rb))) {
-               sn9c102_release_buffers(cam);
-               cam->io = IO_NONE;
-               return -EFAULT;
-       }
-
-       cam->io = rb.count ? IO_MMAP : IO_NONE;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_querybuf(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_buffer b;
-
-       if (copy_from_user(&b, arg, sizeof(b)))
-               return -EFAULT;
-
-       if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-           b.index >= cam->nbuffers || cam->io != IO_MMAP)
-               return -EINVAL;
-
-       memcpy(&b, &cam->frame[b.index].buf, sizeof(b));
-
-       if (cam->frame[b.index].vma_use_count)
-               b.flags |= V4L2_BUF_FLAG_MAPPED;
-
-       if (cam->frame[b.index].state == F_DONE)
-               b.flags |= V4L2_BUF_FLAG_DONE;
-       else if (cam->frame[b.index].state != F_UNUSED)
-               b.flags |= V4L2_BUF_FLAG_QUEUED;
-
-       if (copy_to_user(arg, &b, sizeof(b)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_qbuf(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_buffer b;
-       unsigned long lock_flags;
-
-       if (copy_from_user(&b, arg, sizeof(b)))
-               return -EFAULT;
-
-       if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-           b.index >= cam->nbuffers || cam->io != IO_MMAP)
-               return -EINVAL;
-
-       if (cam->frame[b.index].state != F_UNUSED)
-               return -EINVAL;
-
-       cam->frame[b.index].state = F_QUEUED;
-
-       spin_lock_irqsave(&cam->queue_lock, lock_flags);
-       list_add_tail(&cam->frame[b.index].frame, &cam->inqueue);
-       spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-
-       PDBGG("Frame #%lu queued", (unsigned long)b.index);
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_dqbuf(struct sn9c102_device* cam, struct file* filp,
-                    void __user * arg)
-{
-       struct v4l2_buffer b;
-       struct sn9c102_frame_t *f;
-       unsigned long lock_flags;
-       long timeout;
-       int err = 0;
-
-       if (copy_from_user(&b, arg, sizeof(b)))
-               return -EFAULT;
-
-       if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
-               return -EINVAL;
-
-       if (list_empty(&cam->outqueue)) {
-               if (cam->stream == STREAM_OFF)
-                       return -EINVAL;
-               if (filp->f_flags & O_NONBLOCK)
-                       return -EAGAIN;
-               if (!cam->module_param.frame_timeout) {
-                       err = wait_event_interruptible
-                             ( cam->wait_frame,
-                               (!list_empty(&cam->outqueue)) ||
-                               (cam->state & DEV_DISCONNECTED) ||
-                               (cam->state & DEV_MISCONFIGURED) );
-                       if (err)
-                               return err;
-               } else {
-                       timeout = wait_event_interruptible_timeout
-                                 ( cam->wait_frame,
-                                   (!list_empty(&cam->outqueue)) ||
-                                   (cam->state & DEV_DISCONNECTED) ||
-                                   (cam->state & DEV_MISCONFIGURED),
-                                   cam->module_param.frame_timeout *
-                                   1000 * msecs_to_jiffies(1) );
-                       if (timeout < 0)
-                               return timeout;
-                       else if (timeout == 0 &&
-                                !(cam->state & DEV_DISCONNECTED)) {
-                               DBG(1, "Video frame timeout elapsed");
-                               return -EIO;
-                       }
-               }
-               if (cam->state & DEV_DISCONNECTED)
-                       return -ENODEV;
-               if (cam->state & DEV_MISCONFIGURED)
-                       return -EIO;
-       }
-
-       spin_lock_irqsave(&cam->queue_lock, lock_flags);
-       f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame);
-       list_del(cam->outqueue.next);
-       spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-
-       f->state = F_UNUSED;
-
-       memcpy(&b, &f->buf, sizeof(b));
-       if (f->vma_use_count)
-               b.flags |= V4L2_BUF_FLAG_MAPPED;
-
-       if (copy_to_user(arg, &b, sizeof(b)))
-               return -EFAULT;
-
-       PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index);
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_streamon(struct sn9c102_device* cam, void __user * arg)
-{
-       int type;
-
-       if (copy_from_user(&type, arg, sizeof(type)))
-               return -EFAULT;
-
-       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
-               return -EINVAL;
-
-       cam->stream = STREAM_ON;
-
-       DBG(3, "Stream on");
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_streamoff(struct sn9c102_device* cam, void __user * arg)
-{
-       int type, err;
-
-       if (copy_from_user(&type, arg, sizeof(type)))
-               return -EFAULT;
-
-       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
-               return -EINVAL;
-
-       if (cam->stream == STREAM_ON)
-               if ((err = sn9c102_stream_interrupt(cam)))
-                       return err;
-
-       sn9c102_empty_framequeues(cam);
-
-       DBG(3, "Stream off");
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_parm(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_streamparm sp;
-
-       if (copy_from_user(&sp, arg, sizeof(sp)))
-               return -EFAULT;
-
-       if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       sp.parm.capture.extendedmode = 0;
-       sp.parm.capture.readbuffers = cam->nreadbuffers;
-
-       if (copy_to_user(arg, &sp, sizeof(sp)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_parm(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_streamparm sp;
-
-       if (copy_from_user(&sp, arg, sizeof(sp)))
-               return -EFAULT;
-
-       if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       sp.parm.capture.extendedmode = 0;
-
-       if (sp.parm.capture.readbuffers == 0)
-               sp.parm.capture.readbuffers = cam->nreadbuffers;
-
-       if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES)
-               sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES;
-
-       if (copy_to_user(arg, &sp, sizeof(sp)))
-               return -EFAULT;
-
-       cam->nreadbuffers = sp.parm.capture.readbuffers;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_enumaudio(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_audio audio;
-
-       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
-               return -EINVAL;
-
-       if (copy_from_user(&audio, arg, sizeof(audio)))
-               return -EFAULT;
-
-       if (audio.index != 0)
-               return -EINVAL;
-
-       strcpy(audio.name, "Microphone");
-       audio.capability = 0;
-       audio.mode = 0;
-
-       if (copy_to_user(arg, &audio, sizeof(audio)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_audio(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_audio audio;
-
-       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
-               return -EINVAL;
-
-       if (copy_from_user(&audio, arg, sizeof(audio)))
-               return -EFAULT;
-
-       memset(&audio, 0, sizeof(audio));
-       strcpy(audio.name, "Microphone");
-
-       if (copy_to_user(arg, &audio, sizeof(audio)))
-               return -EFAULT;
-
-       return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_audio(struct sn9c102_device* cam, void __user * arg)
-{
-       struct v4l2_audio audio;
-
-       if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
-               return -EINVAL;
-
-       if (copy_from_user(&audio, arg, sizeof(audio)))
-               return -EFAULT;
-
-       if (audio.index != 0)
-               return -EINVAL;
-
-       return 0;
-}
-
-
-static long sn9c102_ioctl_v4l2(struct file *filp,
-                             unsigned int cmd, void __user *arg)
-{
-       struct sn9c102_device *cam = video_drvdata(filp);
-
-       switch (cmd) {
-
-       case VIDIOC_QUERYCAP:
-               return sn9c102_vidioc_querycap(cam, arg);
-
-       case VIDIOC_ENUMINPUT:
-               return sn9c102_vidioc_enuminput(cam, arg);
-
-       case VIDIOC_G_INPUT:
-               return sn9c102_vidioc_g_input(cam, arg);
-
-       case VIDIOC_S_INPUT:
-               return sn9c102_vidioc_s_input(cam, arg);
-
-       case VIDIOC_QUERYCTRL:
-               return sn9c102_vidioc_query_ctrl(cam, arg);
-
-       case VIDIOC_G_CTRL:
-               return sn9c102_vidioc_g_ctrl(cam, arg);
-
-       case VIDIOC_S_CTRL:
-               return sn9c102_vidioc_s_ctrl(cam, arg);
-
-       case VIDIOC_CROPCAP:
-               return sn9c102_vidioc_cropcap(cam, arg);
-
-       case VIDIOC_G_CROP:
-               return sn9c102_vidioc_g_crop(cam, arg);
-
-       case VIDIOC_S_CROP:
-               return sn9c102_vidioc_s_crop(cam, arg);
-
-       case VIDIOC_ENUM_FRAMESIZES:
-               return sn9c102_vidioc_enum_framesizes(cam, arg);
-
-       case VIDIOC_ENUM_FMT:
-               return sn9c102_vidioc_enum_fmt(cam, arg);
-
-       case VIDIOC_G_FMT:
-               return sn9c102_vidioc_g_fmt(cam, arg);
-
-       case VIDIOC_TRY_FMT:
-       case VIDIOC_S_FMT:
-               return sn9c102_vidioc_try_s_fmt(cam, cmd, arg);
-
-       case VIDIOC_G_JPEGCOMP:
-               return sn9c102_vidioc_g_jpegcomp(cam, arg);
-
-       case VIDIOC_S_JPEGCOMP:
-               return sn9c102_vidioc_s_jpegcomp(cam, arg);
-
-       case VIDIOC_REQBUFS:
-               return sn9c102_vidioc_reqbufs(cam, arg);
-
-       case VIDIOC_QUERYBUF:
-               return sn9c102_vidioc_querybuf(cam, arg);
-
-       case VIDIOC_QBUF:
-               return sn9c102_vidioc_qbuf(cam, arg);
-
-       case VIDIOC_DQBUF:
-               return sn9c102_vidioc_dqbuf(cam, filp, arg);
-
-       case VIDIOC_STREAMON:
-               return sn9c102_vidioc_streamon(cam, arg);
-
-       case VIDIOC_STREAMOFF:
-               return sn9c102_vidioc_streamoff(cam, arg);
-
-       case VIDIOC_G_PARM:
-               return sn9c102_vidioc_g_parm(cam, arg);
-
-       case VIDIOC_S_PARM:
-               return sn9c102_vidioc_s_parm(cam, arg);
-
-       case VIDIOC_ENUMAUDIO:
-               return sn9c102_vidioc_enumaudio(cam, arg);
-
-       case VIDIOC_G_AUDIO:
-               return sn9c102_vidioc_g_audio(cam, arg);
-
-       case VIDIOC_S_AUDIO:
-               return sn9c102_vidioc_s_audio(cam, arg);
-
-       default:
-               return -ENOTTY;
-
-       }
-}
-
-
-static long sn9c102_ioctl(struct file *filp,
-                        unsigned int cmd, unsigned long arg)
-{
-       struct sn9c102_device *cam = video_drvdata(filp);
-       int err = 0;
-
-       if (mutex_lock_interruptible(&cam->fileop_mutex))
-               return -ERESTARTSYS;
-
-       if (cam->state & DEV_DISCONNECTED) {
-               DBG(1, "Device not present");
-               mutex_unlock(&cam->fileop_mutex);
-               return -ENODEV;
-       }
-
-       if (cam->state & DEV_MISCONFIGURED) {
-               DBG(1, "The camera is misconfigured. Close and open it "
-                      "again.");
-               mutex_unlock(&cam->fileop_mutex);
-               return -EIO;
-       }
-
-       V4LDBG(3, "sn9c102", cmd);
-
-       err = sn9c102_ioctl_v4l2(filp, cmd, (void __user *)arg);
-
-       mutex_unlock(&cam->fileop_mutex);
-
-       return err;
-}
-
-/*****************************************************************************/
-
-static const struct v4l2_file_operations sn9c102_fops = {
-       .owner = THIS_MODULE,
-       .open = sn9c102_open,
-       .release = sn9c102_release,
-       .unlocked_ioctl = sn9c102_ioctl,
-       .read = sn9c102_read,
-       .poll = sn9c102_poll,
-       .mmap = sn9c102_mmap,
-};
-
-/*****************************************************************************/
-
-/* It exists a single interface only. We do not need to validate anything. */
-static int
-sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
-{
-       struct usb_device *udev = interface_to_usbdev(intf);
-       struct sn9c102_device* cam;
-       static unsigned int dev_nr;
-       unsigned int i;
-       int err = 0, r;
-
-       if (!(cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL)))
-               return -ENOMEM;
-
-       cam->usbdev = udev;
-
-       if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) {
-               DBG(1, "kzalloc() failed");
-               err = -ENOMEM;
-               goto fail;
-       }
-
-       if (!(cam->v4ldev = video_device_alloc())) {
-               DBG(1, "video_device_alloc() failed");
-               err = -ENOMEM;
-               goto fail;
-       }
-
-       r = sn9c102_read_reg(cam, 0x00);
-       if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
-               DBG(1, "Sorry, this is not a SN9C1xx-based camera "
-                      "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
-               err = -ENODEV;
-               goto fail;
-       }
-
-       cam->bridge = id->driver_info;
-       switch (cam->bridge) {
-       case BRIDGE_SN9C101:
-       case BRIDGE_SN9C102:
-               DBG(2, "SN9C10[12] PC Camera Controller detected "
-                      "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
-               break;
-       case BRIDGE_SN9C103:
-               DBG(2, "SN9C103 PC Camera Controller detected "
-                      "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
-               break;
-       case BRIDGE_SN9C105:
-               DBG(2, "SN9C105 PC Camera Controller detected "
-                      "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
-               break;
-       case BRIDGE_SN9C120:
-               DBG(2, "SN9C120 PC Camera Controller detected "
-                      "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
-               break;
-       }
-
-       for  (i = 0; i < ARRAY_SIZE(sn9c102_sensor_table); i++) {
-               err = sn9c102_sensor_table[i](cam);
-               if (!err)
-                       break;
-       }
-
-       if (!err) {
-               DBG(2, "%s image sensor detected", cam->sensor.name);
-               DBG(3, "Support for %s maintained by %s",
-                   cam->sensor.name, cam->sensor.maintainer);
-       } else {
-               DBG(1, "No supported image sensor detected for this bridge");
-               err = -ENODEV;
-               goto fail;
-       }
-
-       if (!(cam->bridge & cam->sensor.supported_bridge)) {
-               DBG(1, "Bridge not supported");
-               err = -ENODEV;
-               goto fail;
-       }
-
-       if (sn9c102_init(cam)) {
-               DBG(1, "Initialization failed. I will retry on open().");
-               cam->state |= DEV_MISCONFIGURED;
-       }
-
-       strcpy(cam->v4ldev->name, "SN9C1xx PC Camera");
-       cam->v4ldev->fops = &sn9c102_fops;
-       cam->v4ldev->release = video_device_release;
-       cam->v4ldev->parent = &udev->dev;
-
-       init_completion(&cam->probe);
-
-       err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
-                                   video_nr[dev_nr]);
-       if (err) {
-               DBG(1, "V4L2 device registration failed");
-               if (err == -ENFILE && video_nr[dev_nr] == -1)
-                       DBG(1, "Free /dev/videoX node not found");
-               video_nr[dev_nr] = -1;
-               dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
-               complete_all(&cam->probe);
-               goto fail;
-       }
-
-       DBG(2, "V4L2 device registered as %s",
-           video_device_node_name(cam->v4ldev));
-
-       video_set_drvdata(cam->v4ldev, cam);
-       cam->module_param.force_munmap = force_munmap[dev_nr];
-       cam->module_param.frame_timeout = frame_timeout[dev_nr];
-
-       dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       err = sn9c102_create_sysfs(cam);
-       if (!err)
-               DBG(2, "Optional device control through 'sysfs' "
-                      "interface ready");
-       else
-               DBG(2, "Failed to create optional 'sysfs' interface for "
-                      "device controlling. Error #%d", err);
-#else
-       DBG(2, "Optional device control through 'sysfs' interface disabled");
-       DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' "
-              "configuration option to enable it.");
-#endif
-
-       usb_set_intfdata(intf, cam);
-       kref_init(&cam->kref);
-       usb_get_dev(cam->usbdev);
-
-       complete_all(&cam->probe);
-
-       return 0;
-
-fail:
-       if (cam) {
-               kfree(cam->control_buffer);
-               if (cam->v4ldev)
-                       video_device_release(cam->v4ldev);
-               kfree(cam);
-       }
-       return err;
-}
-
-
-static void sn9c102_usb_disconnect(struct usb_interface* intf)
-{
-       struct sn9c102_device* cam;
-
-       down_write(&sn9c102_dev_lock);
-
-       cam = usb_get_intfdata(intf);
-
-       DBG(2, "Disconnecting %s...", cam->v4ldev->name);
-
-       if (cam->users) {
-               DBG(2, "Device %s is open! Deregistration and memory "
-                      "deallocation are deferred.",
-                   video_device_node_name(cam->v4ldev));
-               cam->state |= DEV_MISCONFIGURED;
-               sn9c102_stop_transfer(cam);
-               cam->state |= DEV_DISCONNECTED;
-               wake_up_interruptible(&cam->wait_frame);
-               wake_up(&cam->wait_stream);
-       } else
-               cam->state |= DEV_DISCONNECTED;
-
-       wake_up_interruptible_all(&cam->wait_open);
-
-       kref_put(&cam->kref, sn9c102_release_resources);
-
-       up_write(&sn9c102_dev_lock);
-}
-
-
-static struct usb_driver sn9c102_usb_driver = {
-       .name =       "sn9c102",
-       .id_table =   sn9c102_id_table,
-       .probe =      sn9c102_usb_probe,
-       .disconnect = sn9c102_usb_disconnect,
-};
-
-module_usb_driver(sn9c102_usb_driver);
diff --git a/drivers/media/video/sn9c102/sn9c102_devtable.h b/drivers/media/video/sn9c102/sn9c102_devtable.h
deleted file mode 100644 (file)
index b3d2cc7..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/***************************************************************************
- * Table of device identifiers of the SN9C1xx PC Camera Controllers        *
- *                                                                         *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * 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.               *
- ***************************************************************************/
-
-#ifndef _SN9C102_DEVTABLE_H_
-#define _SN9C102_DEVTABLE_H_
-
-#include <linux/usb.h>
-
-struct sn9c102_device;
-
-/*
-   Each SN9C1xx camera has proper PID/VID identifiers.
-   SN9C103, SN9C105, SN9C120 support multiple interfaces, but we only have to
-   handle the video class interface.
-*/
-#define SN9C102_USB_DEVICE(vend, prod, bridge)                                \
-       .match_flags = USB_DEVICE_ID_MATCH_DEVICE |                           \
-                      USB_DEVICE_ID_MATCH_INT_CLASS,                         \
-       .idVendor = (vend),                                                   \
-       .idProduct = (prod),                                                  \
-       .bInterfaceClass = 0xff,                                              \
-       .driver_info = (bridge)
-
-static const struct usb_device_id sn9c102_id_table[] = {
-       /* SN9C101 and SN9C102 */
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
-       { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), },
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */
-       { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), },
-#endif
-       { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), },
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
-       { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), },
-#endif
-       { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, /* not in sonixb */
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
-       { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */
-       { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
-#endif
-       { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, /* not in sonixb */
-       /* SN9C103 */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, non existent ? */
-       { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), }, /* not in sonixb */
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, HY7131D/E */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), }, non existent ? */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), }, non existent ? */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, non existent ? */
-       { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), },
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */
-       { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), },
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, non existent ? */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), }, non existent ? */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, non existent ? */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, PAS106 */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, TAS5130 */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, TAS5110, non existent */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, non existent ? */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, non existent ? */
-       { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), },
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, non existent ? */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), }, non existent ? */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), }, non existent ? */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), }, non existent ? */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), }, non existent ? */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, non existent ? */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, non existent ? */
-#endif
-       /* SN9C105 */
-#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE
-       { SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), },
-       { SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), },
-       { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
-       { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), }, PO1030 */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, OM6801 */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, HV7131GP */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, non existent ? */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, MO4000 */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), }, ICM105C */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, OV7648 */
-       { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
-       /* SN9C120 */
-       { SN9C102_USB_DEVICE(0x0458, 0x7025, BRIDGE_SN9C120), },
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), }, po2030 */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, om6801 */
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, S5K53BEB */
-       { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
-/*     { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */
-       { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
-       { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), },
-#endif
-       { }
-};
-
-/*
-   Probing functions: on success, you must attach the sensor to the camera
-   by calling sn9c102_attach_sensor().
-   To enable the I2C communication, you might need to perform a really basic
-   initialization of the SN9C1XX chip.
-   Functions must return 0 on success, the appropriate error otherwise.
-*/
-extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
-extern int sn9c102_probe_hv7131r(struct sn9c102_device* cam);
-extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
-extern int sn9c102_probe_mi0360(struct sn9c102_device* cam);
-extern int sn9c102_probe_mt9v111(struct sn9c102_device *cam);
-extern int sn9c102_probe_ov7630(struct sn9c102_device* cam);
-extern int sn9c102_probe_ov7660(struct sn9c102_device* cam);
-extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
-extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
-extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
-extern int sn9c102_probe_tas5110d(struct sn9c102_device* cam);
-extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
-
-#endif /* _SN9C102_DEVTABLE_H_ */
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131d.c b/drivers/media/video/sn9c102/sn9c102_hv7131d.c
deleted file mode 100644 (file)
index 2dce5c9..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-/***************************************************************************
- * Plug-in for HV7131D image sensor connected to the SN9C1xx PC Camera     *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int hv7131d_init(struct sn9c102_device* cam)
-{
-       int err;
-
-       err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
-                                      {0x00, 0x14}, {0x60, 0x17},
-                                      {0x0e, 0x18}, {0xf2, 0x19});
-
-       err += sn9c102_i2c_write(cam, 0x01, 0x04);
-       err += sn9c102_i2c_write(cam, 0x02, 0x00);
-       err += sn9c102_i2c_write(cam, 0x28, 0x00);
-
-       return err;
-}
-
-
-static int hv7131d_get_ctrl(struct sn9c102_device* cam,
-                           struct v4l2_control* ctrl)
-{
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               {
-                       int r1 = sn9c102_i2c_read(cam, 0x26),
-                           r2 = sn9c102_i2c_read(cam, 0x27);
-                       if (r1 < 0 || r2 < 0)
-                               return -EIO;
-                       ctrl->value = (r1 << 8) | (r2 & 0xff);
-               }
-               return 0;
-       case V4L2_CID_RED_BALANCE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0)
-                       return -EIO;
-               ctrl->value = 0x3f - (ctrl->value & 0x3f);
-               return 0;
-       case V4L2_CID_BLUE_BALANCE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0)
-                       return -EIO;
-               ctrl->value = 0x3f - (ctrl->value & 0x3f);
-               return 0;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0)
-                       return -EIO;
-               ctrl->value = 0x3f - (ctrl->value & 0x3f);
-               return 0;
-       case SN9C102_V4L2_CID_RESET_LEVEL:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x3f;
-               return 0;
-       case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x34)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x07;
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-
-static int hv7131d_set_ctrl(struct sn9c102_device* cam,
-                           const struct v4l2_control* ctrl)
-{
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               err += sn9c102_i2c_write(cam, 0x26, ctrl->value >> 8);
-               err += sn9c102_i2c_write(cam, 0x27, ctrl->value & 0xff);
-               break;
-       case V4L2_CID_RED_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x31, 0x3f - ctrl->value);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x33, 0x3f - ctrl->value);
-               break;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x32, 0x3f - ctrl->value);
-               break;
-       case SN9C102_V4L2_CID_RESET_LEVEL:
-               err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
-               break;
-       case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE:
-               err += sn9c102_i2c_write(cam, 0x34, ctrl->value);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return err ? -EIO : 0;
-}
-
-
-static int hv7131d_set_crop(struct sn9c102_device* cam,
-                           const struct v4l2_rect* rect)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2,
-          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
-
-       err += sn9c102_write_reg(cam, h_start, 0x12);
-       err += sn9c102_write_reg(cam, v_start, 0x13);
-
-       return err;
-}
-
-
-static int hv7131d_set_pix_format(struct sn9c102_device* cam,
-                                 const struct v4l2_pix_format* pix)
-{
-       int err = 0;
-
-       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-               err += sn9c102_write_reg(cam, 0x42, 0x19);
-       else
-               err += sn9c102_write_reg(cam, 0xf2, 0x19);
-
-       return err;
-}
-
-
-static const struct sn9c102_sensor hv7131d = {
-       .name = "HV7131D",
-       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
-       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
-       .frequency = SN9C102_I2C_100KHZ,
-       .interface = SN9C102_I2C_2WIRES,
-       .i2c_slave_id = 0x11,
-       .init = &hv7131d_init,
-       .qctrl = {
-               {
-                       .id = V4L2_CID_EXPOSURE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "exposure",
-                       .minimum = 0x0250,
-                       .maximum = 0xffff,
-                       .step = 0x0001,
-                       .default_value = 0x0250,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_RED_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "red balance",
-                       .minimum = 0x00,
-                       .maximum = 0x3f,
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_BLUE_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "blue balance",
-                       .minimum = 0x00,
-                       .maximum = 0x3f,
-                       .step = 0x01,
-                       .default_value = 0x20,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "green balance",
-                       .minimum = 0x00,
-                       .maximum = 0x3f,
-                       .step = 0x01,
-                       .default_value = 0x1e,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_RESET_LEVEL,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "reset level",
-                       .minimum = 0x19,
-                       .maximum = 0x3f,
-                       .step = 0x01,
-                       .default_value = 0x30,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "pixel bias voltage",
-                       .minimum = 0x00,
-                       .maximum = 0x07,
-                       .step = 0x01,
-                       .default_value = 0x02,
-                       .flags = 0,
-               },
-       },
-       .get_ctrl = &hv7131d_get_ctrl,
-       .set_ctrl = &hv7131d_set_ctrl,
-       .cropcap = {
-               .bounds = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-               .defrect = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-       },
-       .set_crop = &hv7131d_set_crop,
-       .pix_format = {
-               .width = 640,
-               .height = 480,
-               .pixelformat = V4L2_PIX_FMT_SBGGR8,
-               .priv = 8,
-       },
-       .set_pix_format = &hv7131d_set_pix_format
-};
-
-
-int sn9c102_probe_hv7131d(struct sn9c102_device* cam)
-{
-       int r0 = 0, r1 = 0, err;
-
-       err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
-                                      {0x28, 0x17});
-
-       r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00);
-       r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01);
-       if (err || r0 < 0 || r1 < 0)
-               return -EIO;
-
-       if ((r0 != 0x00 && r0 != 0x01) || r1 != 0x04)
-               return -ENODEV;
-
-       sn9c102_attach_sensor(cam, &hv7131d);
-
-       return 0;
-}
diff --git a/drivers/media/video/sn9c102/sn9c102_hv7131r.c b/drivers/media/video/sn9c102/sn9c102_hv7131r.c
deleted file mode 100644 (file)
index 4295887..0000000
+++ /dev/null
@@ -1,363 +0,0 @@
-/***************************************************************************
- * Plug-in for HV7131R image sensor connected to the SN9C1xx PC Camera     *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int hv7131r_init(struct sn9c102_device* cam)
-{
-       int err = 0;
-
-       switch (sn9c102_get_bridge(cam)) {
-       case BRIDGE_SN9C103:
-               err = sn9c102_write_const_regs(cam, {0x00, 0x03}, {0x1a, 0x04},
-                                              {0x20, 0x05}, {0x20, 0x06},
-                                              {0x03, 0x10}, {0x00, 0x14},
-                                              {0x60, 0x17}, {0x0a, 0x18},
-                                              {0xf0, 0x19}, {0x1d, 0x1a},
-                                              {0x10, 0x1b}, {0x02, 0x1c},
-                                              {0x03, 0x1d}, {0x0f, 0x1e},
-                                              {0x0c, 0x1f}, {0x00, 0x20},
-                                              {0x10, 0x21}, {0x20, 0x22},
-                                              {0x30, 0x23}, {0x40, 0x24},
-                                              {0x50, 0x25}, {0x60, 0x26},
-                                              {0x70, 0x27}, {0x80, 0x28},
-                                              {0x90, 0x29}, {0xa0, 0x2a},
-                                              {0xb0, 0x2b}, {0xc0, 0x2c},
-                                              {0xd0, 0x2d}, {0xe0, 0x2e},
-                                              {0xf0, 0x2f}, {0xff, 0x30});
-               break;
-       case BRIDGE_SN9C105:
-       case BRIDGE_SN9C120:
-               err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
-                                              {0x00, 0x03}, {0x1a, 0x04},
-                                              {0x44, 0x05}, {0x3e, 0x06},
-                                              {0x1a, 0x07}, {0x03, 0x10},
-                                              {0x08, 0x14}, {0xa3, 0x17},
-                                              {0x4b, 0x18}, {0x00, 0x19},
-                                              {0x1d, 0x1a}, {0x10, 0x1b},
-                                              {0x02, 0x1c}, {0x03, 0x1d},
-                                              {0x0f, 0x1e}, {0x0c, 0x1f},
-                                              {0x00, 0x20}, {0x29, 0x21},
-                                              {0x40, 0x22}, {0x54, 0x23},
-                                              {0x66, 0x24}, {0x76, 0x25},
-                                              {0x85, 0x26}, {0x94, 0x27},
-                                              {0xa1, 0x28}, {0xae, 0x29},
-                                              {0xbb, 0x2a}, {0xc7, 0x2b},
-                                              {0xd3, 0x2c}, {0xde, 0x2d},
-                                              {0xea, 0x2e}, {0xf4, 0x2f},
-                                              {0xff, 0x30}, {0x00, 0x3F},
-                                              {0xC7, 0x40}, {0x01, 0x41},
-                                              {0x44, 0x42}, {0x00, 0x43},
-                                              {0x44, 0x44}, {0x00, 0x45},
-                                              {0x44, 0x46}, {0x00, 0x47},
-                                              {0xC7, 0x48}, {0x01, 0x49},
-                                              {0xC7, 0x4A}, {0x01, 0x4B},
-                                              {0xC7, 0x4C}, {0x01, 0x4D},
-                                              {0x44, 0x4E}, {0x00, 0x4F},
-                                              {0x44, 0x50}, {0x00, 0x51},
-                                              {0x44, 0x52}, {0x00, 0x53},
-                                              {0xC7, 0x54}, {0x01, 0x55},
-                                              {0xC7, 0x56}, {0x01, 0x57},
-                                              {0xC7, 0x58}, {0x01, 0x59},
-                                              {0x44, 0x5A}, {0x00, 0x5B},
-                                              {0x44, 0x5C}, {0x00, 0x5D},
-                                              {0x44, 0x5E}, {0x00, 0x5F},
-                                              {0xC7, 0x60}, {0x01, 0x61},
-                                              {0xC7, 0x62}, {0x01, 0x63},
-                                              {0xC7, 0x64}, {0x01, 0x65},
-                                              {0x44, 0x66}, {0x00, 0x67},
-                                              {0x44, 0x68}, {0x00, 0x69},
-                                              {0x44, 0x6A}, {0x00, 0x6B},
-                                              {0xC7, 0x6C}, {0x01, 0x6D},
-                                              {0xC7, 0x6E}, {0x01, 0x6F},
-                                              {0xC7, 0x70}, {0x01, 0x71},
-                                              {0x44, 0x72}, {0x00, 0x73},
-                                              {0x44, 0x74}, {0x00, 0x75},
-                                              {0x44, 0x76}, {0x00, 0x77},
-                                              {0xC7, 0x78}, {0x01, 0x79},
-                                              {0xC7, 0x7A}, {0x01, 0x7B},
-                                              {0xC7, 0x7C}, {0x01, 0x7D},
-                                              {0x44, 0x7E}, {0x00, 0x7F},
-                                              {0x14, 0x84}, {0x00, 0x85},
-                                              {0x27, 0x86}, {0x00, 0x87},
-                                              {0x07, 0x88}, {0x00, 0x89},
-                                              {0xEC, 0x8A}, {0x0f, 0x8B},
-                                              {0xD8, 0x8C}, {0x0f, 0x8D},
-                                              {0x3D, 0x8E}, {0x00, 0x8F},
-                                              {0x3D, 0x90}, {0x00, 0x91},
-                                              {0xCD, 0x92}, {0x0f, 0x93},
-                                              {0xf7, 0x94}, {0x0f, 0x95},
-                                              {0x0C, 0x96}, {0x00, 0x97},
-                                              {0x00, 0x98}, {0x66, 0x99},
-                                              {0x05, 0x9A}, {0x00, 0x9B},
-                                              {0x04, 0x9C}, {0x00, 0x9D},
-                                              {0x08, 0x9E}, {0x00, 0x9F},
-                                              {0x2D, 0xC0}, {0x2D, 0xC1},
-                                              {0x3A, 0xC2}, {0x05, 0xC3},
-                                              {0x04, 0xC4}, {0x3F, 0xC5},
-                                              {0x00, 0xC6}, {0x00, 0xC7},
-                                              {0x50, 0xC8}, {0x3C, 0xC9},
-                                              {0x28, 0xCA}, {0xD8, 0xCB},
-                                              {0x14, 0xCC}, {0xEC, 0xCD},
-                                              {0x32, 0xCE}, {0xDD, 0xCF},
-                                              {0x32, 0xD0}, {0xDD, 0xD1},
-                                              {0x6A, 0xD2}, {0x50, 0xD3},
-                                              {0x00, 0xD4}, {0x00, 0xD5},
-                                              {0x00, 0xD6});
-               break;
-       default:
-               break;
-       }
-
-       err += sn9c102_i2c_write(cam, 0x20, 0x00);
-       err += sn9c102_i2c_write(cam, 0x21, 0xd6);
-       err += sn9c102_i2c_write(cam, 0x25, 0x06);
-
-       return err;
-}
-
-
-static int hv7131r_get_ctrl(struct sn9c102_device* cam,
-                           struct v4l2_control* ctrl)
-{
-       switch (ctrl->id) {
-       case V4L2_CID_GAIN:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0)
-                       return -EIO;
-               return 0;
-       case V4L2_CID_RED_BALANCE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0)
-                       return -EIO;
-               ctrl->value = ctrl->value & 0x3f;
-               return 0;
-       case V4L2_CID_BLUE_BALANCE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0)
-                       return -EIO;
-               ctrl->value = ctrl->value & 0x3f;
-               return 0;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0)
-                       return -EIO;
-               ctrl->value = ctrl->value & 0x3f;
-               return 0;
-       case V4L2_CID_BLACK_LEVEL:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x01)) < 0)
-                       return -EIO;
-               ctrl->value = (ctrl->value & 0x08) ? 1 : 0;
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-
-static int hv7131r_set_ctrl(struct sn9c102_device* cam,
-                           const struct v4l2_control* ctrl)
-{
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_GAIN:
-               err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
-               break;
-       case V4L2_CID_RED_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x31, ctrl->value);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x33, ctrl->value);
-               break;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x32, ctrl->value);
-               break;
-       case V4L2_CID_BLACK_LEVEL:
-               {
-                       int r = sn9c102_i2c_read(cam, 0x01);
-                       if (r < 0)
-                               return -EIO;
-                       err += sn9c102_i2c_write(cam, 0x01,
-                                                (ctrl->value<<3) | (r&0xf7));
-               }
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return err ? -EIO : 0;
-}
-
-
-static int hv7131r_set_crop(struct sn9c102_device* cam,
-                           const struct v4l2_rect* rect)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
-          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
-
-       err += sn9c102_write_reg(cam, h_start, 0x12);
-       err += sn9c102_write_reg(cam, v_start, 0x13);
-
-       return err;
-}
-
-
-static int hv7131r_set_pix_format(struct sn9c102_device* cam,
-                                 const struct v4l2_pix_format* pix)
-{
-       int err = 0;
-
-       switch (sn9c102_get_bridge(cam)) {
-       case BRIDGE_SN9C103:
-               if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
-                       err += sn9c102_write_reg(cam, 0xa0, 0x19);
-                       err += sn9c102_i2c_write(cam, 0x01, 0x04);
-               } else {
-                       err += sn9c102_write_reg(cam, 0x30, 0x19);
-                       err += sn9c102_i2c_write(cam, 0x01, 0x04);
-               }
-               break;
-       case BRIDGE_SN9C105:
-       case BRIDGE_SN9C120:
-               if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
-                       err += sn9c102_write_reg(cam, 0xa5, 0x17);
-                       err += sn9c102_i2c_write(cam, 0x01, 0x24);
-               } else {
-                       err += sn9c102_write_reg(cam, 0xa3, 0x17);
-                       err += sn9c102_i2c_write(cam, 0x01, 0x04);
-               }
-               break;
-       default:
-               break;
-       }
-
-       return err;
-}
-
-
-static const struct sn9c102_sensor hv7131r = {
-       .name = "HV7131R",
-       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-       .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
-       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
-       .frequency = SN9C102_I2C_100KHZ,
-       .interface = SN9C102_I2C_2WIRES,
-       .i2c_slave_id = 0x11,
-       .init = &hv7131r_init,
-       .qctrl = {
-               {
-                       .id = V4L2_CID_GAIN,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "global gain",
-                       .minimum = 0x00,
-                       .maximum = 0xff,
-                       .step = 0x01,
-                       .default_value = 0x40,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_RED_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "red balance",
-                       .minimum = 0x00,
-                       .maximum = 0x3f,
-                       .step = 0x01,
-                       .default_value = 0x08,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_BLUE_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "blue balance",
-                       .minimum = 0x00,
-                       .maximum = 0x3f,
-                       .step = 0x01,
-                       .default_value = 0x1a,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "green balance",
-                       .minimum = 0x00,
-                       .maximum = 0x3f,
-                       .step = 0x01,
-                       .default_value = 0x2f,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_BLACK_LEVEL,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "auto black level compensation",
-                       .minimum = 0x00,
-                       .maximum = 0x01,
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-       },
-       .get_ctrl = &hv7131r_get_ctrl,
-       .set_ctrl = &hv7131r_set_ctrl,
-       .cropcap = {
-               .bounds = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-               .defrect = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-       },
-       .set_crop = &hv7131r_set_crop,
-       .pix_format = {
-               .width = 640,
-               .height = 480,
-               .pixelformat = V4L2_PIX_FMT_SBGGR8,
-               .priv = 8,
-       },
-       .set_pix_format = &hv7131r_set_pix_format
-};
-
-
-int sn9c102_probe_hv7131r(struct sn9c102_device* cam)
-{
-       int devid, err;
-
-       err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x02},
-                                      {0x34, 0x01}, {0x20, 0x17},
-                                      {0x34, 0x01}, {0x46, 0x01});
-
-       devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00);
-       if (err || devid < 0)
-               return -EIO;
-
-       if (devid != 0x02)
-               return -ENODEV;
-
-       sn9c102_attach_sensor(cam, &hv7131r);
-
-       return 0;
-}
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0343.c b/drivers/media/video/sn9c102/sn9c102_mi0343.c
deleted file mode 100644 (file)
index 1f5b09b..0000000
+++ /dev/null
@@ -1,352 +0,0 @@
-/***************************************************************************
- * Plug-in for MI-0343 image sensor connected to the SN9C1xx PC Camera     *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int mi0343_init(struct sn9c102_device* cam)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-
-       err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
-                                      {0x0a, 0x14}, {0x40, 0x01},
-                                      {0x20, 0x17}, {0x07, 0x18},
-                                      {0xa0, 0x19});
-
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
-                                        0x00, 0x01, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
-                                        0x00, 0x00, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
-                                        0x01, 0xe1, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
-                                        0x02, 0x81, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
-                                        0x00, 0x17, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
-                                        0x00, 0x11, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
-                                        0x04, 0x9a, 0, 0);
-
-       return err;
-}
-
-
-static int mi0343_get_ctrl(struct sn9c102_device* cam,
-                          struct v4l2_control* ctrl)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       u8 data[2];
-
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
-                                            data) < 0)
-                       return -EIO;
-               ctrl->value = data[0];
-               return 0;
-       case V4L2_CID_GAIN:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
-                                            data) < 0)
-                       return -EIO;
-               break;
-       case V4L2_CID_HFLIP:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
-                                            data) < 0)
-                       return -EIO;
-               ctrl->value = data[1] & 0x20 ? 1 : 0;
-               return 0;
-       case V4L2_CID_VFLIP:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
-                                            data) < 0)
-                       return -EIO;
-               ctrl->value = data[1] & 0x80 ? 1 : 0;
-               return 0;
-       case V4L2_CID_RED_BALANCE:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
-                                            data) < 0)
-                       return -EIO;
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
-                                            data) < 0)
-                       return -EIO;
-               break;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
-                                            data) < 0)
-                       return -EIO;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       switch (ctrl->id) {
-       case V4L2_CID_GAIN:
-       case V4L2_CID_RED_BALANCE:
-       case V4L2_CID_BLUE_BALANCE:
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               ctrl->value = data[1] | (data[0] << 8);
-               if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
-                       ctrl->value -= 0x10;
-               else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
-                       ctrl->value -= 0x60;
-               else if (ctrl->value >= 0xe0 && ctrl->value <= 0xff)
-                       ctrl->value -= 0xe0;
-       }
-
-       return 0;
-}
-
-
-static int mi0343_set_ctrl(struct sn9c102_device* cam,
-                          const struct v4l2_control* ctrl)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       u16 reg = 0;
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_GAIN:
-       case V4L2_CID_RED_BALANCE:
-       case V4L2_CID_BLUE_BALANCE:
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               if (ctrl->value <= (0x3f-0x10))
-                       reg = 0x10 + ctrl->value;
-               else if (ctrl->value <= ((0x3f-0x10) + (0x7f-0x60)))
-                       reg = 0x60 + (ctrl->value - (0x3f-0x10));
-               else
-                       reg = 0xe0 + (ctrl->value - (0x3f-0x10) - (0x7f-0x60));
-               break;
-       }
-
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x09, ctrl->value, 0x00,
-                                                0, 0);
-               break;
-       case V4L2_CID_GAIN:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x35, reg >> 8, reg & 0xff,
-                                                0, 0);
-               break;
-       case V4L2_CID_HFLIP:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x20, ctrl->value ? 0x40:0x00,
-                                                ctrl->value ? 0x20:0x00,
-                                                0, 0);
-               break;
-       case V4L2_CID_VFLIP:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x20, ctrl->value ? 0x80:0x00,
-                                                ctrl->value ? 0x80:0x00,
-                                                0, 0);
-               break;
-       case V4L2_CID_RED_BALANCE:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x2d, reg >> 8, reg & 0xff,
-                                                0, 0);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x2c, reg >> 8, reg & 0xff,
-                                                0, 0);
-               break;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x2b, reg >> 8, reg & 0xff,
-                                                0, 0);
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x2e, reg >> 8, reg & 0xff,
-                                                0, 0);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return err ? -EIO : 0;
-}
-
-
-static int mi0343_set_crop(struct sn9c102_device* cam,
-                           const struct v4l2_rect* rect)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
-          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
-
-       err += sn9c102_write_reg(cam, h_start, 0x12);
-       err += sn9c102_write_reg(cam, v_start, 0x13);
-
-       return err;
-}
-
-
-static int mi0343_set_pix_format(struct sn9c102_device* cam,
-                                const struct v4l2_pix_format* pix)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-
-       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x0a, 0x00, 0x03, 0, 0);
-               err += sn9c102_write_reg(cam, 0x20, 0x19);
-       } else {
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x0a, 0x00, 0x05, 0, 0);
-               err += sn9c102_write_reg(cam, 0xa0, 0x19);
-       }
-
-       return err;
-}
-
-
-static const struct sn9c102_sensor mi0343 = {
-       .name = "MI-0343",
-       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
-       .frequency = SN9C102_I2C_100KHZ,
-       .interface = SN9C102_I2C_2WIRES,
-       .i2c_slave_id = 0x5d,
-       .init = &mi0343_init,
-       .qctrl = {
-               {
-                       .id = V4L2_CID_EXPOSURE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "exposure",
-                       .minimum = 0x00,
-                       .maximum = 0x0f,
-                       .step = 0x01,
-                       .default_value = 0x06,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_GAIN,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "global gain",
-                       .minimum = 0x00,
-                       .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),/*0x6d*/
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_HFLIP,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "horizontal mirror",
-                       .minimum = 0,
-                       .maximum = 1,
-                       .step = 1,
-                       .default_value = 0,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_VFLIP,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "vertical mirror",
-                       .minimum = 0,
-                       .maximum = 1,
-                       .step = 1,
-                       .default_value = 0,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_RED_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "red balance",
-                       .minimum = 0x00,
-                       .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_BLUE_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "blue balance",
-                       .minimum = 0x00,
-                       .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "green balance",
-                       .minimum = 0x00,
-                       .maximum = ((0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0)),
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-       },
-       .get_ctrl = &mi0343_get_ctrl,
-       .set_ctrl = &mi0343_set_ctrl,
-       .cropcap = {
-               .bounds = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-               .defrect = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-       },
-       .set_crop = &mi0343_set_crop,
-       .pix_format = {
-               .width = 640,
-               .height = 480,
-               .pixelformat = V4L2_PIX_FMT_SBGGR8,
-               .priv = 8,
-       },
-       .set_pix_format = &mi0343_set_pix_format
-};
-
-
-int sn9c102_probe_mi0343(struct sn9c102_device* cam)
-{
-       u8 data[2];
-
-       if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
-                                    {0x28, 0x17}))
-               return -EIO;
-
-       if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
-                                    2, data) < 0)
-               return -EIO;
-
-       if (data[1] != 0x42 || data[0] != 0xe3)
-               return -ENODEV;
-
-       sn9c102_attach_sensor(cam, &mi0343);
-
-       return 0;
-}
diff --git a/drivers/media/video/sn9c102/sn9c102_mi0360.c b/drivers/media/video/sn9c102/sn9c102_mi0360.c
deleted file mode 100644 (file)
index d973fc1..0000000
+++ /dev/null
@@ -1,453 +0,0 @@
-/***************************************************************************
- * Plug-in for MI-0360 image sensor connected to the SN9C1xx PC Camera     *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int mi0360_init(struct sn9c102_device* cam)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-
-       switch (sn9c102_get_bridge(cam)) {
-       case BRIDGE_SN9C103:
-               err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
-                                              {0x0a, 0x14}, {0x40, 0x01},
-                                              {0x20, 0x17}, {0x07, 0x18},
-                                              {0xa0, 0x19}, {0x02, 0x1c},
-                                              {0x03, 0x1d}, {0x0f, 0x1e},
-                                              {0x0c, 0x1f}, {0x00, 0x20},
-                                              {0x10, 0x21}, {0x20, 0x22},
-                                              {0x30, 0x23}, {0x40, 0x24},
-                                              {0x50, 0x25}, {0x60, 0x26},
-                                              {0x70, 0x27}, {0x80, 0x28},
-                                              {0x90, 0x29}, {0xa0, 0x2a},
-                                              {0xb0, 0x2b}, {0xc0, 0x2c},
-                                              {0xd0, 0x2d}, {0xe0, 0x2e},
-                                              {0xf0, 0x2f}, {0xff, 0x30});
-               break;
-       case BRIDGE_SN9C105:
-       case BRIDGE_SN9C120:
-               err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
-                                              {0x00, 0x03}, {0x1a, 0x04},
-                                              {0x50, 0x05}, {0x20, 0x06},
-                                              {0x10, 0x07}, {0x03, 0x10},
-                                              {0x08, 0x14}, {0xa2, 0x17},
-                                              {0x47, 0x18}, {0x00, 0x19},
-                                              {0x1d, 0x1a}, {0x10, 0x1b},
-                                              {0x02, 0x1c}, {0x03, 0x1d},
-                                              {0x0f, 0x1e}, {0x0c, 0x1f},
-                                              {0x00, 0x20}, {0x29, 0x21},
-                                              {0x40, 0x22}, {0x54, 0x23},
-                                              {0x66, 0x24}, {0x76, 0x25},
-                                              {0x85, 0x26}, {0x94, 0x27},
-                                              {0xa1, 0x28}, {0xae, 0x29},
-                                              {0xbb, 0x2a}, {0xc7, 0x2b},
-                                              {0xd3, 0x2c}, {0xde, 0x2d},
-                                              {0xea, 0x2e}, {0xf4, 0x2f},
-                                              {0xff, 0x30}, {0x00, 0x3F},
-                                              {0xC7, 0x40}, {0x01, 0x41},
-                                              {0x44, 0x42}, {0x00, 0x43},
-                                              {0x44, 0x44}, {0x00, 0x45},
-                                              {0x44, 0x46}, {0x00, 0x47},
-                                              {0xC7, 0x48}, {0x01, 0x49},
-                                              {0xC7, 0x4A}, {0x01, 0x4B},
-                                              {0xC7, 0x4C}, {0x01, 0x4D},
-                                              {0x44, 0x4E}, {0x00, 0x4F},
-                                              {0x44, 0x50}, {0x00, 0x51},
-                                              {0x44, 0x52}, {0x00, 0x53},
-                                              {0xC7, 0x54}, {0x01, 0x55},
-                                              {0xC7, 0x56}, {0x01, 0x57},
-                                              {0xC7, 0x58}, {0x01, 0x59},
-                                              {0x44, 0x5A}, {0x00, 0x5B},
-                                              {0x44, 0x5C}, {0x00, 0x5D},
-                                              {0x44, 0x5E}, {0x00, 0x5F},
-                                              {0xC7, 0x60}, {0x01, 0x61},
-                                              {0xC7, 0x62}, {0x01, 0x63},
-                                              {0xC7, 0x64}, {0x01, 0x65},
-                                              {0x44, 0x66}, {0x00, 0x67},
-                                              {0x44, 0x68}, {0x00, 0x69},
-                                              {0x44, 0x6A}, {0x00, 0x6B},
-                                              {0xC7, 0x6C}, {0x01, 0x6D},
-                                              {0xC7, 0x6E}, {0x01, 0x6F},
-                                              {0xC7, 0x70}, {0x01, 0x71},
-                                              {0x44, 0x72}, {0x00, 0x73},
-                                              {0x44, 0x74}, {0x00, 0x75},
-                                              {0x44, 0x76}, {0x00, 0x77},
-                                              {0xC7, 0x78}, {0x01, 0x79},
-                                              {0xC7, 0x7A}, {0x01, 0x7B},
-                                              {0xC7, 0x7C}, {0x01, 0x7D},
-                                              {0x44, 0x7E}, {0x00, 0x7F},
-                                              {0x14, 0x84}, {0x00, 0x85},
-                                              {0x27, 0x86}, {0x00, 0x87},
-                                              {0x07, 0x88}, {0x00, 0x89},
-                                              {0xEC, 0x8A}, {0x0f, 0x8B},
-                                              {0xD8, 0x8C}, {0x0f, 0x8D},
-                                              {0x3D, 0x8E}, {0x00, 0x8F},
-                                              {0x3D, 0x90}, {0x00, 0x91},
-                                              {0xCD, 0x92}, {0x0f, 0x93},
-                                              {0xf7, 0x94}, {0x0f, 0x95},
-                                              {0x0C, 0x96}, {0x00, 0x97},
-                                              {0x00, 0x98}, {0x66, 0x99},
-                                              {0x05, 0x9A}, {0x00, 0x9B},
-                                              {0x04, 0x9C}, {0x00, 0x9D},
-                                              {0x08, 0x9E}, {0x00, 0x9F},
-                                              {0x2D, 0xC0}, {0x2D, 0xC1},
-                                              {0x3A, 0xC2}, {0x05, 0xC3},
-                                              {0x04, 0xC4}, {0x3F, 0xC5},
-                                              {0x00, 0xC6}, {0x00, 0xC7},
-                                              {0x50, 0xC8}, {0x3C, 0xC9},
-                                              {0x28, 0xCA}, {0xD8, 0xCB},
-                                              {0x14, 0xCC}, {0xEC, 0xCD},
-                                              {0x32, 0xCE}, {0xDD, 0xCF},
-                                              {0x32, 0xD0}, {0xDD, 0xD1},
-                                              {0x6A, 0xD2}, {0x50, 0xD3},
-                                              {0x00, 0xD4}, {0x00, 0xD5},
-                                              {0x00, 0xD6});
-               break;
-       default:
-               break;
-       }
-
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
-                                        0x00, 0x01, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
-                                        0x00, 0x00, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
-                                        0x01, 0xe1, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
-                                        0x02, 0x81, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
-                                        0x00, 0x17, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
-                                        0x00, 0x11, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
-                                        0x04, 0x9a, 0, 0);
-
-       return err;
-}
-
-
-static int mi0360_get_ctrl(struct sn9c102_device* cam,
-                          struct v4l2_control* ctrl)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       u8 data[2];
-
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
-                                            data) < 0)
-                       return -EIO;
-               ctrl->value = data[0];
-               return 0;
-       case V4L2_CID_GAIN:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
-                                            data) < 0)
-                       return -EIO;
-               ctrl->value = data[1];
-               return 0;
-       case V4L2_CID_RED_BALANCE:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
-                                            data) < 0)
-                       return -EIO;
-               ctrl->value = data[1];
-               return 0;
-       case V4L2_CID_BLUE_BALANCE:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
-                                            data) < 0)
-                       return -EIO;
-               ctrl->value = data[1];
-               return 0;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
-                                            data) < 0)
-                       return -EIO;
-               ctrl->value = data[1];
-               return 0;
-       case V4L2_CID_HFLIP:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
-                                            data) < 0)
-                       return -EIO;
-               ctrl->value = data[1] & 0x20 ? 1 : 0;
-               return 0;
-       case V4L2_CID_VFLIP:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
-                                            data) < 0)
-                       return -EIO;
-               ctrl->value = data[1] & 0x80 ? 1 : 0;
-               return 0;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-
-static int mi0360_set_ctrl(struct sn9c102_device* cam,
-                          const struct v4l2_control* ctrl)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x09, ctrl->value, 0x00,
-                                                0, 0);
-               break;
-       case V4L2_CID_GAIN:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x35, 0x03, ctrl->value,
-                                                0, 0);
-               break;
-       case V4L2_CID_RED_BALANCE:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x2c, 0x03, ctrl->value,
-                                                0, 0);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x2d, 0x03, ctrl->value,
-                                                0, 0);
-               break;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x2b, 0x03, ctrl->value,
-                                                0, 0);
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x2e, 0x03, ctrl->value,
-                                                0, 0);
-               break;
-       case V4L2_CID_HFLIP:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x20, ctrl->value ? 0x40:0x00,
-                                                ctrl->value ? 0x20:0x00,
-                                                0, 0);
-               break;
-       case V4L2_CID_VFLIP:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x20, ctrl->value ? 0x80:0x00,
-                                                ctrl->value ? 0x80:0x00,
-                                                0, 0);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return err ? -EIO : 0;
-}
-
-
-static int mi0360_set_crop(struct sn9c102_device* cam,
-                           const struct v4l2_rect* rect)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-       u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
-
-       switch (sn9c102_get_bridge(cam)) {
-       case BRIDGE_SN9C103:
-               h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0;
-               break;
-       case BRIDGE_SN9C105:
-       case BRIDGE_SN9C120:
-               h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
-               break;
-       default:
-               break;
-       }
-
-       err += sn9c102_write_reg(cam, h_start, 0x12);
-       err += sn9c102_write_reg(cam, v_start, 0x13);
-
-       return err;
-}
-
-
-static int mi0360_set_pix_format(struct sn9c102_device* cam,
-                                const struct v4l2_pix_format* pix)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-
-       if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x0a, 0x00, 0x05, 0, 0);
-               err += sn9c102_write_reg(cam, 0x60, 0x19);
-               if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
-                   sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
-                       err += sn9c102_write_reg(cam, 0xa6, 0x17);
-       } else {
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x0a, 0x00, 0x02, 0, 0);
-               err += sn9c102_write_reg(cam, 0x20, 0x19);
-               if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
-                   sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
-                       err += sn9c102_write_reg(cam, 0xa2, 0x17);
-       }
-
-       return err;
-}
-
-
-static const struct sn9c102_sensor mi0360 = {
-       .name = "MI-0360",
-       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-       .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
-       .frequency = SN9C102_I2C_100KHZ,
-       .interface = SN9C102_I2C_2WIRES,
-       .i2c_slave_id = 0x5d,
-       .init = &mi0360_init,
-       .qctrl = {
-               {
-                       .id = V4L2_CID_EXPOSURE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "exposure",
-                       .minimum = 0x00,
-                       .maximum = 0x0f,
-                       .step = 0x01,
-                       .default_value = 0x05,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_GAIN,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "global gain",
-                       .minimum = 0x00,
-                       .maximum = 0x7f,
-                       .step = 0x01,
-                       .default_value = 0x25,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_HFLIP,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "horizontal mirror",
-                       .minimum = 0,
-                       .maximum = 1,
-                       .step = 1,
-                       .default_value = 0,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_VFLIP,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "vertical mirror",
-                       .minimum = 0,
-                       .maximum = 1,
-                       .step = 1,
-                       .default_value = 0,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_BLUE_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "blue balance",
-                       .minimum = 0x00,
-                       .maximum = 0x7f,
-                       .step = 0x01,
-                       .default_value = 0x0f,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_RED_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "red balance",
-                       .minimum = 0x00,
-                       .maximum = 0x7f,
-                       .step = 0x01,
-                       .default_value = 0x32,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "green balance",
-                       .minimum = 0x00,
-                       .maximum = 0x7f,
-                       .step = 0x01,
-                       .default_value = 0x25,
-                       .flags = 0,
-               },
-       },
-       .get_ctrl = &mi0360_get_ctrl,
-       .set_ctrl = &mi0360_set_ctrl,
-       .cropcap = {
-               .bounds = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-               .defrect = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-       },
-       .set_crop = &mi0360_set_crop,
-       .pix_format = {
-               .width = 640,
-               .height = 480,
-               .pixelformat = V4L2_PIX_FMT_SBGGR8,
-               .priv = 8,
-       },
-       .set_pix_format = &mi0360_set_pix_format
-};
-
-
-int sn9c102_probe_mi0360(struct sn9c102_device* cam)
-{
-
-       u8 data[2];
-
-       switch (sn9c102_get_bridge(cam)) {
-       case BRIDGE_SN9C103:
-               if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
-                                            {0x28, 0x17}))
-                       return -EIO;
-               break;
-       case BRIDGE_SN9C105:
-       case BRIDGE_SN9C120:
-               if (sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
-                                            {0x01, 0x01}, {0x00, 0x01},
-                                            {0x28, 0x17}))
-                       return -EIO;
-               break;
-       default:
-               break;
-       }
-
-       if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00,
-                                    2, data) < 0)
-               return -EIO;
-
-       if (data[0] != 0x82 || data[1] != 0x43)
-               return -ENODEV;
-
-       sn9c102_attach_sensor(cam, &mi0360);
-
-       return 0;
-}
diff --git a/drivers/media/video/sn9c102/sn9c102_mt9v111.c b/drivers/media/video/sn9c102/sn9c102_mt9v111.c
deleted file mode 100644 (file)
index 95986eb..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/***************************************************************************
- * Plug-in for MT9V111 image sensor connected to the SN9C1xx PC Camera     *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int mt9v111_init(struct sn9c102_device *cam)
-{
-       struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-       int err = 0;
-
-       err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
-                                      {0x00, 0x03}, {0x1a, 0x04},
-                                      {0x1f, 0x05}, {0x20, 0x06},
-                                      {0x1f, 0x07}, {0x81, 0x08},
-                                      {0x5c, 0x09}, {0x00, 0x0a},
-                                      {0x00, 0x0b}, {0x00, 0x0c},
-                                      {0x00, 0x0d}, {0x00, 0x0e},
-                                      {0x00, 0x0f}, {0x03, 0x10},
-                                      {0x00, 0x11}, {0x00, 0x12},
-                                      {0x02, 0x13}, {0x14, 0x14},
-                                      {0x28, 0x15}, {0x1e, 0x16},
-                                      {0xe2, 0x17}, {0x06, 0x18},
-                                      {0x00, 0x19}, {0x00, 0x1a},
-                                      {0x00, 0x1b}, {0x08, 0x20},
-                                      {0x39, 0x21}, {0x51, 0x22},
-                                      {0x63, 0x23}, {0x73, 0x24},
-                                      {0x82, 0x25}, {0x8f, 0x26},
-                                      {0x9b, 0x27}, {0xa7, 0x28},
-                                      {0xb1, 0x29}, {0xbc, 0x2a},
-                                      {0xc6, 0x2b}, {0xcf, 0x2c},
-                                      {0xd8, 0x2d}, {0xe1, 0x2e},
-                                      {0xea, 0x2f}, {0xf2, 0x30},
-                                      {0x13, 0x84}, {0x00, 0x85},
-                                      {0x25, 0x86}, {0x00, 0x87},
-                                      {0x07, 0x88}, {0x00, 0x89},
-                                      {0xee, 0x8a}, {0x0f, 0x8b},
-                                      {0xe5, 0x8c}, {0x0f, 0x8d},
-                                      {0x2e, 0x8e}, {0x00, 0x8f},
-                                      {0x30, 0x90}, {0x00, 0x91},
-                                      {0xd4, 0x92}, {0x0f, 0x93},
-                                      {0xfc, 0x94}, {0x0f, 0x95},
-                                      {0x14, 0x96}, {0x00, 0x97},
-                                      {0x00, 0x98}, {0x60, 0x99},
-                                      {0x07, 0x9a}, {0x40, 0x9b},
-                                      {0x20, 0x9c}, {0x00, 0x9d},
-                                      {0x00, 0x9e}, {0x00, 0x9f},
-                                      {0x2d, 0xc0}, {0x2d, 0xc1},
-                                      {0x3a, 0xc2}, {0x05, 0xc3},
-                                      {0x04, 0xc4}, {0x3f, 0xc5},
-                                      {0x00, 0xc6}, {0x00, 0xc7},
-                                      {0x50, 0xc8}, {0x3c, 0xc9},
-                                      {0x28, 0xca}, {0xd8, 0xcb},
-                                      {0x14, 0xcc}, {0xec, 0xcd},
-                                      {0x32, 0xce}, {0xdd, 0xcf},
-                                      {0x2d, 0xd0}, {0xdd, 0xd1},
-                                      {0x6a, 0xd2}, {0x50, 0xd3},
-                                      {0x60, 0xd4}, {0x00, 0xd5},
-                                      {0x00, 0xd6});
-
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
-                                        0x00, 0x01, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
-                                        0x00, 0x01, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
-                                        0x00, 0x00, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08,
-                                        0x04, 0x80, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
-                                        0x00, 0x04, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08,
-                                        0x00, 0x08, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x02,
-                                        0x00, 0x16, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
-                                        0x01, 0xe7, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
-                                        0x02, 0x87, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
-                                        0x00, 0x40, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
-                                        0x00, 0x09, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x07,
-                                        0x30, 0x02, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0c,
-                                        0x00, 0x00, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x12,
-                                        0x00, 0xb0, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x13,
-                                        0x00, 0x7c, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x1e,
-                                        0x00, 0x00, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20,
-                                        0x00, 0x00, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20,
-                                        0x00, 0x00, 0, 0);
-       err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
-                                        0x00, 0x04, 0, 0);
-
-       return err;
-}
-
-static int mt9v111_get_ctrl(struct sn9c102_device *cam,
-                           struct v4l2_control *ctrl)
-{
-       struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-       u8 data[2];
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_VFLIP:
-               if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
-                                            data) < 0)
-                       return -EIO;
-               ctrl->value = data[1] & 0x80 ? 1 : 0;
-               return 0;
-       default:
-               return -EINVAL;
-       }
-
-       return err ? -EIO : 0;
-}
-
-static int mt9v111_set_ctrl(struct sn9c102_device *cam,
-                           const struct v4l2_control *ctrl)
-{
-       struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_VFLIP:
-               err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
-                                                0x20,
-                                                ctrl->value ? 0x80 : 0x00,
-                                                ctrl->value ? 0x80 : 0x00, 0,
-                                                0);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return err ? -EIO : 0;
-}
-
-static int mt9v111_set_crop(struct sn9c102_device *cam,
-                           const struct v4l2_rect *rect)
-{
-       struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
-       int err = 0;
-       u8 v_start = (u8) (rect->top - s->cropcap.bounds.top) + 2;
-
-       err += sn9c102_write_reg(cam, v_start, 0x13);
-
-       return err;
-}
-
-static int mt9v111_set_pix_format(struct sn9c102_device *cam,
-                                 const struct v4l2_pix_format *pix)
-{
-       int err = 0;
-
-       if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
-               err += sn9c102_write_reg(cam, 0xb4, 0x17);
-       } else {
-               err += sn9c102_write_reg(cam, 0xe2, 0x17);
-       }
-
-       return err;
-}
-
-
-static const struct sn9c102_sensor mt9v111 = {
-       .name = "MT9V111",
-       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-       .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
-       .frequency = SN9C102_I2C_100KHZ,
-       .interface = SN9C102_I2C_2WIRES,
-       .i2c_slave_id = 0x5c,
-       .init = &mt9v111_init,
-       .qctrl = {
-               {
-                       .id = V4L2_CID_VFLIP,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "vertical mirror",
-                       .minimum = 0,
-                       .maximum = 1,
-                       .step = 1,
-                       .default_value = 0,
-                       .flags = 0,
-               },
-       },
-       .get_ctrl = &mt9v111_get_ctrl,
-       .set_ctrl = &mt9v111_set_ctrl,
-       .cropcap = {
-               .bounds = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-               .defrect = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-       },
-       .set_crop = &mt9v111_set_crop,
-       .pix_format = {
-               .width = 640,
-               .height = 480,
-               .pixelformat = V4L2_PIX_FMT_SBGGR8,
-               .priv = 8,
-       },
-       .set_pix_format = &mt9v111_set_pix_format
-};
-
-
-int sn9c102_probe_mt9v111(struct sn9c102_device *cam)
-{
-       u8 data[2];
-       int err = 0;
-
-       err += sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
-                                       {0x29, 0x01}, {0x42, 0x17},
-                                       {0x62, 0x17}, {0x08, 0x01});
-       err += sn9c102_i2c_try_raw_write(cam, &mt9v111, 4,
-                                        mt9v111.i2c_slave_id, 0x01, 0x00,
-                                        0x04, 0, 0);
-       if (err || sn9c102_i2c_try_raw_read(cam, &mt9v111,
-                                           mt9v111.i2c_slave_id, 0x36, 2,
-                                           data) < 0)
-               return -EIO;
-
-       if (data[0] != 0x82 || data[1] != 0x3a)
-               return -ENODEV;
-
-       sn9c102_attach_sensor(cam, &mt9v111);
-
-       return 0;
-}
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7630.c b/drivers/media/video/sn9c102/sn9c102_ov7630.c
deleted file mode 100644 (file)
index 803712c..0000000
+++ /dev/null
@@ -1,626 +0,0 @@
-/***************************************************************************
- * Plug-in for OV7630 image sensor connected to the SN9C1xx PC Camera      *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int ov7630_init(struct sn9c102_device* cam)
-{
-       int err = 0;
-
-       switch (sn9c102_get_bridge(cam)) {
-       case BRIDGE_SN9C101:
-       case BRIDGE_SN9C102:
-               err = sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17},
-                                              {0x0f, 0x18}, {0x50, 0x19});
-
-               err += sn9c102_i2c_write(cam, 0x12, 0x8d);
-               err += sn9c102_i2c_write(cam, 0x12, 0x0d);
-               err += sn9c102_i2c_write(cam, 0x11, 0x00);
-               err += sn9c102_i2c_write(cam, 0x15, 0x35);
-               err += sn9c102_i2c_write(cam, 0x16, 0x03);
-               err += sn9c102_i2c_write(cam, 0x17, 0x1c);
-               err += sn9c102_i2c_write(cam, 0x18, 0xbd);
-               err += sn9c102_i2c_write(cam, 0x19, 0x06);
-               err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
-               err += sn9c102_i2c_write(cam, 0x1b, 0x04);
-               err += sn9c102_i2c_write(cam, 0x20, 0x44);
-               err += sn9c102_i2c_write(cam, 0x23, 0xee);
-               err += sn9c102_i2c_write(cam, 0x26, 0xa0);
-               err += sn9c102_i2c_write(cam, 0x27, 0x9a);
-               err += sn9c102_i2c_write(cam, 0x28, 0x20);
-               err += sn9c102_i2c_write(cam, 0x29, 0x30);
-               err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
-               err += sn9c102_i2c_write(cam, 0x30, 0x24);
-               err += sn9c102_i2c_write(cam, 0x32, 0x86);
-               err += sn9c102_i2c_write(cam, 0x60, 0xa9);
-               err += sn9c102_i2c_write(cam, 0x61, 0x42);
-               err += sn9c102_i2c_write(cam, 0x65, 0x00);
-               err += sn9c102_i2c_write(cam, 0x69, 0x38);
-               err += sn9c102_i2c_write(cam, 0x6f, 0x88);
-               err += sn9c102_i2c_write(cam, 0x70, 0x0b);
-               err += sn9c102_i2c_write(cam, 0x71, 0x00);
-               err += sn9c102_i2c_write(cam, 0x74, 0x21);
-               err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
-               break;
-       case BRIDGE_SN9C103:
-               err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
-                                              {0x1a, 0x04}, {0x20, 0x05},
-                                              {0x20, 0x06}, {0x20, 0x07},
-                                              {0x03, 0x10}, {0x0a, 0x14},
-                                              {0x60, 0x17}, {0x0f, 0x18},
-                                              {0x50, 0x19}, {0x1d, 0x1a},
-                                              {0x10, 0x1b}, {0x02, 0x1c},
-                                              {0x03, 0x1d}, {0x0f, 0x1e},
-                                              {0x0c, 0x1f}, {0x00, 0x20},
-                                              {0x10, 0x21}, {0x20, 0x22},
-                                              {0x30, 0x23}, {0x40, 0x24},
-                                              {0x50, 0x25}, {0x60, 0x26},
-                                              {0x70, 0x27}, {0x80, 0x28},
-                                              {0x90, 0x29}, {0xa0, 0x2a},
-                                              {0xb0, 0x2b}, {0xc0, 0x2c},
-                                              {0xd0, 0x2d}, {0xe0, 0x2e},
-                                              {0xf0, 0x2f}, {0xff, 0x30});
-
-               err += sn9c102_i2c_write(cam, 0x12, 0x8d);
-               err += sn9c102_i2c_write(cam, 0x12, 0x0d);
-               err += sn9c102_i2c_write(cam, 0x15, 0x34);
-               err += sn9c102_i2c_write(cam, 0x11, 0x01);
-               err += sn9c102_i2c_write(cam, 0x1b, 0x04);
-               err += sn9c102_i2c_write(cam, 0x20, 0x44);
-               err += sn9c102_i2c_write(cam, 0x23, 0xee);
-               err += sn9c102_i2c_write(cam, 0x26, 0xa0);
-               err += sn9c102_i2c_write(cam, 0x27, 0x9a);
-               err += sn9c102_i2c_write(cam, 0x28, 0x20);
-               err += sn9c102_i2c_write(cam, 0x29, 0x30);
-               err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
-               err += sn9c102_i2c_write(cam, 0x30, 0x24);
-               err += sn9c102_i2c_write(cam, 0x32, 0x86);
-               err += sn9c102_i2c_write(cam, 0x60, 0xa9);
-               err += sn9c102_i2c_write(cam, 0x61, 0x42);
-               err += sn9c102_i2c_write(cam, 0x65, 0x00);
-               err += sn9c102_i2c_write(cam, 0x69, 0x38);
-               err += sn9c102_i2c_write(cam, 0x6f, 0x88);
-               err += sn9c102_i2c_write(cam, 0x70, 0x0b);
-               err += sn9c102_i2c_write(cam, 0x71, 0x00);
-               err += sn9c102_i2c_write(cam, 0x74, 0x21);
-               err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
-               break;
-       case BRIDGE_SN9C105:
-       case BRIDGE_SN9C120:
-       err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
-                                      {0x1a, 0x04}, {0x03, 0x10},
-                                      {0x0a, 0x14}, {0xe2, 0x17},
-                                      {0x0b, 0x18}, {0x00, 0x19},
-                                      {0x1d, 0x1a}, {0x10, 0x1b},
-                                      {0x02, 0x1c}, {0x03, 0x1d},
-                                      {0x0f, 0x1e}, {0x0c, 0x1f},
-                                      {0x00, 0x20}, {0x24, 0x21},
-                                      {0x3b, 0x22}, {0x47, 0x23},
-                                      {0x60, 0x24}, {0x71, 0x25},
-                                      {0x80, 0x26}, {0x8f, 0x27},
-                                      {0x9d, 0x28}, {0xaa, 0x29},
-                                      {0xb8, 0x2a}, {0xc4, 0x2b},
-                                      {0xd1, 0x2c}, {0xdd, 0x2d},
-                                      {0xe8, 0x2e}, {0xf4, 0x2f},
-                                      {0xff, 0x30}, {0x00, 0x3f},
-                                      {0xc7, 0x40}, {0x01, 0x41},
-                                      {0x44, 0x42}, {0x00, 0x43},
-                                      {0x44, 0x44}, {0x00, 0x45},
-                                      {0x44, 0x46}, {0x00, 0x47},
-                                      {0xc7, 0x48}, {0x01, 0x49},
-                                      {0xc7, 0x4a}, {0x01, 0x4b},
-                                      {0xc7, 0x4c}, {0x01, 0x4d},
-                                      {0x44, 0x4e}, {0x00, 0x4f},
-                                      {0x44, 0x50}, {0x00, 0x51},
-                                      {0x44, 0x52}, {0x00, 0x53},
-                                      {0xc7, 0x54}, {0x01, 0x55},
-                                      {0xc7, 0x56}, {0x01, 0x57},
-                                      {0xc7, 0x58}, {0x01, 0x59},
-                                      {0x44, 0x5a}, {0x00, 0x5b},
-                                      {0x44, 0x5c}, {0x00, 0x5d},
-                                      {0x44, 0x5e}, {0x00, 0x5f},
-                                      {0xc7, 0x60}, {0x01, 0x61},
-                                      {0xc7, 0x62}, {0x01, 0x63},
-                                      {0xc7, 0x64}, {0x01, 0x65},
-                                      {0x44, 0x66}, {0x00, 0x67},
-                                      {0x44, 0x68}, {0x00, 0x69},
-                                      {0x44, 0x6a}, {0x00, 0x6b},
-                                      {0xc7, 0x6c}, {0x01, 0x6d},
-                                      {0xc7, 0x6e}, {0x01, 0x6f},
-                                      {0xc7, 0x70}, {0x01, 0x71},
-                                      {0x44, 0x72}, {0x00, 0x73},
-                                      {0x44, 0x74}, {0x00, 0x75},
-                                      {0x44, 0x76}, {0x00, 0x77},
-                                      {0xc7, 0x78}, {0x01, 0x79},
-                                      {0xc7, 0x7a}, {0x01, 0x7b},
-                                      {0xc7, 0x7c}, {0x01, 0x7d},
-                                      {0x44, 0x7e}, {0x00, 0x7f},
-                                      {0x17, 0x84}, {0x00, 0x85},
-                                      {0x2e, 0x86}, {0x00, 0x87},
-                                      {0x09, 0x88}, {0x00, 0x89},
-                                      {0xe8, 0x8a}, {0x0f, 0x8b},
-                                      {0xda, 0x8c}, {0x0f, 0x8d},
-                                      {0x40, 0x8e}, {0x00, 0x8f},
-                                      {0x37, 0x90}, {0x00, 0x91},
-                                      {0xcf, 0x92}, {0x0f, 0x93},
-                                      {0xfa, 0x94}, {0x0f, 0x95},
-                                      {0x00, 0x96}, {0x00, 0x97},
-                                      {0x00, 0x98}, {0x66, 0x99},
-                                      {0x00, 0x9a}, {0x40, 0x9b},
-                                      {0x20, 0x9c}, {0x00, 0x9d},
-                                      {0x00, 0x9e}, {0x00, 0x9f},
-                                      {0x2d, 0xc0}, {0x2d, 0xc1},
-                                      {0x3a, 0xc2}, {0x00, 0xc3},
-                                      {0x04, 0xc4}, {0x3f, 0xc5},
-                                      {0x00, 0xc6}, {0x00, 0xc7},
-                                      {0x50, 0xc8}, {0x3c, 0xc9},
-                                      {0x28, 0xca}, {0xd8, 0xcb},
-                                      {0x14, 0xcc}, {0xec, 0xcd},
-                                      {0x32, 0xce}, {0xdd, 0xcf},
-                                      {0x32, 0xd0}, {0xdd, 0xd1},
-                                      {0x6a, 0xd2}, {0x50, 0xd3},
-                                      {0x60, 0xd4}, {0x00, 0xd5},
-                                      {0x00, 0xd6});
-
-               err += sn9c102_i2c_write(cam, 0x12, 0x80);
-               err += sn9c102_i2c_write(cam, 0x12, 0x48);
-               err += sn9c102_i2c_write(cam, 0x01, 0x80);
-               err += sn9c102_i2c_write(cam, 0x02, 0x80);
-               err += sn9c102_i2c_write(cam, 0x03, 0x80);
-               err += sn9c102_i2c_write(cam, 0x04, 0x10);
-               err += sn9c102_i2c_write(cam, 0x05, 0x20);
-               err += sn9c102_i2c_write(cam, 0x06, 0x80);
-               err += sn9c102_i2c_write(cam, 0x11, 0x00);
-               err += sn9c102_i2c_write(cam, 0x0c, 0x20);
-               err += sn9c102_i2c_write(cam, 0x0d, 0x20);
-               err += sn9c102_i2c_write(cam, 0x15, 0x80);
-               err += sn9c102_i2c_write(cam, 0x16, 0x03);
-               err += sn9c102_i2c_write(cam, 0x17, 0x1b);
-               err += sn9c102_i2c_write(cam, 0x18, 0xbd);
-               err += sn9c102_i2c_write(cam, 0x19, 0x05);
-               err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
-               err += sn9c102_i2c_write(cam, 0x1b, 0x04);
-               err += sn9c102_i2c_write(cam, 0x21, 0x1b);
-               err += sn9c102_i2c_write(cam, 0x22, 0x00);
-               err += sn9c102_i2c_write(cam, 0x23, 0xde);
-               err += sn9c102_i2c_write(cam, 0x24, 0x10);
-               err += sn9c102_i2c_write(cam, 0x25, 0x8a);
-               err += sn9c102_i2c_write(cam, 0x26, 0xa0);
-               err += sn9c102_i2c_write(cam, 0x27, 0xca);
-               err += sn9c102_i2c_write(cam, 0x28, 0xa2);
-               err += sn9c102_i2c_write(cam, 0x29, 0x74);
-               err += sn9c102_i2c_write(cam, 0x2a, 0x88);
-               err += sn9c102_i2c_write(cam, 0x2b, 0x34);
-               err += sn9c102_i2c_write(cam, 0x2c, 0x88);
-               err += sn9c102_i2c_write(cam, 0x2e, 0x00);
-               err += sn9c102_i2c_write(cam, 0x2f, 0x00);
-               err += sn9c102_i2c_write(cam, 0x30, 0x00);
-               err += sn9c102_i2c_write(cam, 0x32, 0xc2);
-               err += sn9c102_i2c_write(cam, 0x33, 0x08);
-               err += sn9c102_i2c_write(cam, 0x4c, 0x40);
-               err += sn9c102_i2c_write(cam, 0x4d, 0xf3);
-               err += sn9c102_i2c_write(cam, 0x60, 0x05);
-               err += sn9c102_i2c_write(cam, 0x61, 0x40);
-               err += sn9c102_i2c_write(cam, 0x62, 0x12);
-               err += sn9c102_i2c_write(cam, 0x63, 0x57);
-               err += sn9c102_i2c_write(cam, 0x64, 0x73);
-               err += sn9c102_i2c_write(cam, 0x65, 0x00);
-               err += sn9c102_i2c_write(cam, 0x66, 0x55);
-               err += sn9c102_i2c_write(cam, 0x67, 0x01);
-               err += sn9c102_i2c_write(cam, 0x68, 0xac);
-               err += sn9c102_i2c_write(cam, 0x69, 0x38);
-               err += sn9c102_i2c_write(cam, 0x6f, 0x1f);
-               err += sn9c102_i2c_write(cam, 0x70, 0x01);
-               err += sn9c102_i2c_write(cam, 0x71, 0x00);
-               err += sn9c102_i2c_write(cam, 0x72, 0x10);
-               err += sn9c102_i2c_write(cam, 0x73, 0x50);
-               err += sn9c102_i2c_write(cam, 0x74, 0x20);
-               err += sn9c102_i2c_write(cam, 0x76, 0x01);
-               err += sn9c102_i2c_write(cam, 0x77, 0xf3);
-               err += sn9c102_i2c_write(cam, 0x78, 0x90);
-               err += sn9c102_i2c_write(cam, 0x79, 0x98);
-               err += sn9c102_i2c_write(cam, 0x7a, 0x98);
-               err += sn9c102_i2c_write(cam, 0x7b, 0x00);
-               err += sn9c102_i2c_write(cam, 0x7c, 0x38);
-               err += sn9c102_i2c_write(cam, 0x7d, 0xff);
-               break;
-       default:
-               break;
-       }
-
-       return err;
-}
-
-
-static int ov7630_get_ctrl(struct sn9c102_device* cam,
-                          struct v4l2_control* ctrl)
-{
-       enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
-                       return -EIO;
-               break;
-       case V4L2_CID_RED_BALANCE:
-               if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
-                       ctrl->value = sn9c102_pread_reg(cam, 0x05);
-               else
-                       ctrl->value = sn9c102_pread_reg(cam, 0x07);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               ctrl->value = sn9c102_pread_reg(cam, 0x06);
-               break;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
-                       ctrl->value = sn9c102_pread_reg(cam, 0x07);
-               else
-                       ctrl->value = sn9c102_pread_reg(cam, 0x05);
-               break;
-               break;
-       case V4L2_CID_GAIN:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x3f;
-               break;
-       case V4L2_CID_DO_WHITE_BALANCE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x3f;
-               break;
-       case V4L2_CID_WHITENESS:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0d)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x3f;
-               break;
-       case V4L2_CID_AUTOGAIN:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x01;
-               break;
-       case V4L2_CID_VFLIP:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x75)) < 0)
-                       return -EIO;
-               ctrl->value = (ctrl->value & 0x80) ? 1 : 0;
-               break;
-       case SN9C102_V4L2_CID_GAMMA:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x14)) < 0)
-                       return -EIO;
-               ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
-               break;
-       case SN9C102_V4L2_CID_BAND_FILTER:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x2d)) < 0)
-                       return -EIO;
-               ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return err ? -EIO : 0;
-}
-
-
-static int ov7630_set_ctrl(struct sn9c102_device* cam,
-                          const struct v4l2_control* ctrl)
-{
-       enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
-               break;
-       case V4L2_CID_RED_BALANCE:
-               if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
-                       err += sn9c102_write_reg(cam, ctrl->value, 0x05);
-               else
-                       err += sn9c102_write_reg(cam, ctrl->value, 0x07);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               err += sn9c102_write_reg(cam, ctrl->value, 0x06);
-               break;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
-                       err += sn9c102_write_reg(cam, ctrl->value, 0x07);
-               else
-                       err += sn9c102_write_reg(cam, ctrl->value, 0x05);
-               break;
-       case V4L2_CID_GAIN:
-               err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
-               break;
-       case V4L2_CID_DO_WHITE_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
-               break;
-       case V4L2_CID_WHITENESS:
-               err += sn9c102_i2c_write(cam, 0x0d, ctrl->value);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               err += sn9c102_i2c_write(cam, 0x13, ctrl->value |
-                                                   (ctrl->value << 1));
-               break;
-       case V4L2_CID_VFLIP:
-               err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7));
-               break;
-       case SN9C102_V4L2_CID_GAMMA:
-               err += sn9c102_i2c_write(cam, 0x14, ctrl->value << 2);
-               break;
-       case SN9C102_V4L2_CID_BAND_FILTER:
-               err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return err ? -EIO : 0;
-}
-
-
-static int ov7630_set_crop(struct sn9c102_device* cam,
-                          const struct v4l2_rect* rect)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-       u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
-
-       switch (sn9c102_get_bridge(cam)) {
-       case BRIDGE_SN9C101:
-       case BRIDGE_SN9C102:
-       case BRIDGE_SN9C103:
-               h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
-               break;
-       case BRIDGE_SN9C105:
-       case BRIDGE_SN9C120:
-               h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
-               break;
-       default:
-               break;
-       }
-
-       err += sn9c102_write_reg(cam, h_start, 0x12);
-       err += sn9c102_write_reg(cam, v_start, 0x13);
-
-       return err;
-}
-
-
-static int ov7630_set_pix_format(struct sn9c102_device* cam,
-                                const struct v4l2_pix_format* pix)
-{
-       int err = 0;
-
-       switch (sn9c102_get_bridge(cam)) {
-       case BRIDGE_SN9C101:
-       case BRIDGE_SN9C102:
-       case BRIDGE_SN9C103:
-               if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8)
-                       err += sn9c102_write_reg(cam, 0x50, 0x19);
-               else
-                       err += sn9c102_write_reg(cam, 0x20, 0x19);
-               break;
-       case BRIDGE_SN9C105:
-       case BRIDGE_SN9C120:
-               if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
-                       err += sn9c102_write_reg(cam, 0xe5, 0x17);
-                       err += sn9c102_i2c_write(cam, 0x11, 0x04);
-               } else {
-                       err += sn9c102_write_reg(cam, 0xe2, 0x17);
-                       err += sn9c102_i2c_write(cam, 0x11, 0x02);
-               }
-               break;
-       default:
-               break;
-       }
-
-       return err;
-}
-
-
-static const struct sn9c102_sensor ov7630 = {
-       .name = "OV7630",
-       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103 |
-                           BRIDGE_SN9C105 | BRIDGE_SN9C120,
-       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
-       .frequency = SN9C102_I2C_100KHZ,
-       .interface = SN9C102_I2C_2WIRES,
-       .i2c_slave_id = 0x21,
-       .init = &ov7630_init,
-       .qctrl = {
-               {
-                       .id = V4L2_CID_GAIN,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "global gain",
-                       .minimum = 0x00,
-                       .maximum = 0x3f,
-                       .step = 0x01,
-                       .default_value = 0x14,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_EXPOSURE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "exposure",
-                       .minimum = 0x00,
-                       .maximum = 0xff,
-                       .step = 0x01,
-                       .default_value = 0x60,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_WHITENESS,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "white balance background: red",
-                       .minimum = 0x00,
-                       .maximum = 0x3f,
-                       .step = 0x01,
-                       .default_value = 0x20,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_DO_WHITE_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "white balance background: blue",
-                       .minimum = 0x00,
-                       .maximum = 0x3f,
-                       .step = 0x01,
-                       .default_value = 0x20,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_RED_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "red balance",
-                       .minimum = 0x00,
-                       .maximum = 0x7f,
-                       .step = 0x01,
-                       .default_value = 0x20,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_BLUE_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "blue balance",
-                       .minimum = 0x00,
-                       .maximum = 0x7f,
-                       .step = 0x01,
-                       .default_value = 0x20,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_AUTOGAIN,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "auto adjust",
-                       .minimum = 0x00,
-                       .maximum = 0x01,
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_VFLIP,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "vertical flip",
-                       .minimum = 0x00,
-                       .maximum = 0x01,
-                       .step = 0x01,
-                       .default_value = 0x01,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "green balance",
-                       .minimum = 0x00,
-                       .maximum = 0x7f,
-                       .step = 0x01,
-                       .default_value = 0x20,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_BAND_FILTER,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "band filter",
-                       .minimum = 0x00,
-                       .maximum = 0x01,
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_GAMMA,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "rgb gamma",
-                       .minimum = 0x00,
-                       .maximum = 0x01,
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-       },
-       .get_ctrl = &ov7630_get_ctrl,
-       .set_ctrl = &ov7630_set_ctrl,
-       .cropcap = {
-               .bounds = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-               .defrect = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-       },
-       .set_crop = &ov7630_set_crop,
-       .pix_format = {
-               .width = 640,
-               .height = 480,
-               .pixelformat = V4L2_PIX_FMT_SN9C10X,
-               .priv = 8,
-       },
-       .set_pix_format = &ov7630_set_pix_format
-};
-
-
-int sn9c102_probe_ov7630(struct sn9c102_device* cam)
-{
-       int pid, ver, err = 0;
-
-       switch (sn9c102_get_bridge(cam)) {
-       case BRIDGE_SN9C101:
-       case BRIDGE_SN9C102:
-               err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
-                                              {0x28, 0x17});
-               break;
-       case BRIDGE_SN9C103: /* do _not_ change anything! */
-               err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x42, 0x01},
-                                              {0x28, 0x17}, {0x44, 0x02});
-               pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
-               if (err || pid < 0) /* try a different initialization */
-                       err += sn9c102_write_const_regs(cam, {0x01, 0x01},
-                                                       {0x00, 0x01});
-               break;
-       case BRIDGE_SN9C105:
-       case BRIDGE_SN9C120:
-               err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
-                                              {0x29, 0x01}, {0x74, 0x02},
-                                              {0x0e, 0x01}, {0x44, 0x01});
-               break;
-       default:
-               break;
-       }
-
-       pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
-       ver = sn9c102_i2c_try_read(cam, &ov7630, 0x0b);
-       if (err || pid < 0 || ver < 0)
-               return -EIO;
-       if (pid != 0x76 || ver != 0x31)
-               return -ENODEV;
-       sn9c102_attach_sensor(cam, &ov7630);
-
-       return 0;
-}
diff --git a/drivers/media/video/sn9c102/sn9c102_ov7660.c b/drivers/media/video/sn9c102/sn9c102_ov7660.c
deleted file mode 100644 (file)
index 7977795..0000000
+++ /dev/null
@@ -1,538 +0,0 @@
-/***************************************************************************
- * Plug-in for OV7660 image sensor connected to the SN9C1xx PC Camera      *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int ov7660_init(struct sn9c102_device* cam)
-{
-       int err = 0;
-
-       err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
-                                      {0x1a, 0x04}, {0x03, 0x10},
-                                      {0x08, 0x14}, {0x20, 0x17},
-                                      {0x8b, 0x18}, {0x00, 0x19},
-                                      {0x1d, 0x1a}, {0x10, 0x1b},
-                                      {0x02, 0x1c}, {0x03, 0x1d},
-                                      {0x0f, 0x1e}, {0x0c, 0x1f},
-                                      {0x00, 0x20}, {0x29, 0x21},
-                                      {0x40, 0x22}, {0x54, 0x23},
-                                      {0x66, 0x24}, {0x76, 0x25},
-                                      {0x85, 0x26}, {0x94, 0x27},
-                                      {0xa1, 0x28}, {0xae, 0x29},
-                                      {0xbb, 0x2a}, {0xc7, 0x2b},
-                                      {0xd3, 0x2c}, {0xde, 0x2d},
-                                      {0xea, 0x2e}, {0xf4, 0x2f},
-                                      {0xff, 0x30}, {0x00, 0x3f},
-                                      {0xc7, 0x40}, {0x01, 0x41},
-                                      {0x44, 0x42}, {0x00, 0x43},
-                                      {0x44, 0x44}, {0x00, 0x45},
-                                      {0x44, 0x46}, {0x00, 0x47},
-                                      {0xc7, 0x48}, {0x01, 0x49},
-                                      {0xc7, 0x4a}, {0x01, 0x4b},
-                                      {0xc7, 0x4c}, {0x01, 0x4d},
-                                      {0x44, 0x4e}, {0x00, 0x4f},
-                                      {0x44, 0x50}, {0x00, 0x51},
-                                      {0x44, 0x52}, {0x00, 0x53},
-                                      {0xc7, 0x54}, {0x01, 0x55},
-                                      {0xc7, 0x56}, {0x01, 0x57},
-                                      {0xc7, 0x58}, {0x01, 0x59},
-                                      {0x44, 0x5a}, {0x00, 0x5b},
-                                      {0x44, 0x5c}, {0x00, 0x5d},
-                                      {0x44, 0x5e}, {0x00, 0x5f},
-                                      {0xc7, 0x60}, {0x01, 0x61},
-                                      {0xc7, 0x62}, {0x01, 0x63},
-                                      {0xc7, 0x64}, {0x01, 0x65},
-                                      {0x44, 0x66}, {0x00, 0x67},
-                                      {0x44, 0x68}, {0x00, 0x69},
-                                      {0x44, 0x6a}, {0x00, 0x6b},
-                                      {0xc7, 0x6c}, {0x01, 0x6d},
-                                      {0xc7, 0x6e}, {0x01, 0x6f},
-                                      {0xc7, 0x70}, {0x01, 0x71},
-                                      {0x44, 0x72}, {0x00, 0x73},
-                                      {0x44, 0x74}, {0x00, 0x75},
-                                      {0x44, 0x76}, {0x00, 0x77},
-                                      {0xc7, 0x78}, {0x01, 0x79},
-                                      {0xc7, 0x7a}, {0x01, 0x7b},
-                                      {0xc7, 0x7c}, {0x01, 0x7d},
-                                      {0x44, 0x7e}, {0x00, 0x7f},
-                                      {0x14, 0x84}, {0x00, 0x85},
-                                      {0x27, 0x86}, {0x00, 0x87},
-                                      {0x07, 0x88}, {0x00, 0x89},
-                                      {0xec, 0x8a}, {0x0f, 0x8b},
-                                      {0xd8, 0x8c}, {0x0f, 0x8d},
-                                      {0x3d, 0x8e}, {0x00, 0x8f},
-                                      {0x3d, 0x90}, {0x00, 0x91},
-                                      {0xcd, 0x92}, {0x0f, 0x93},
-                                      {0xf7, 0x94}, {0x0f, 0x95},
-                                      {0x0c, 0x96}, {0x00, 0x97},
-                                      {0x00, 0x98}, {0x66, 0x99},
-                                      {0x05, 0x9a}, {0x00, 0x9b},
-                                      {0x04, 0x9c}, {0x00, 0x9d},
-                                      {0x08, 0x9e}, {0x00, 0x9f},
-                                      {0x2d, 0xc0}, {0x2d, 0xc1},
-                                      {0x3a, 0xc2}, {0x05, 0xc3},
-                                      {0x04, 0xc4}, {0x3f, 0xc5},
-                                      {0x00, 0xc6}, {0x00, 0xc7},
-                                      {0x50, 0xc8}, {0x3C, 0xc9},
-                                      {0x28, 0xca}, {0xd8, 0xcb},
-                                      {0x14, 0xcc}, {0xec, 0xcd},
-                                      {0x32, 0xce}, {0xdd, 0xcf},
-                                      {0x32, 0xd0}, {0xdd, 0xd1},
-                                      {0x6a, 0xd2}, {0x50, 0xd3},
-                                      {0x00, 0xd4}, {0x00, 0xd5},
-                                      {0x00, 0xd6});
-
-       err += sn9c102_i2c_write(cam, 0x12, 0x80);
-       err += sn9c102_i2c_write(cam, 0x11, 0x09);
-       err += sn9c102_i2c_write(cam, 0x00, 0x0A);
-       err += sn9c102_i2c_write(cam, 0x01, 0x80);
-       err += sn9c102_i2c_write(cam, 0x02, 0x80);
-       err += sn9c102_i2c_write(cam, 0x03, 0x00);
-       err += sn9c102_i2c_write(cam, 0x04, 0x00);
-       err += sn9c102_i2c_write(cam, 0x05, 0x08);
-       err += sn9c102_i2c_write(cam, 0x06, 0x0B);
-       err += sn9c102_i2c_write(cam, 0x07, 0x00);
-       err += sn9c102_i2c_write(cam, 0x08, 0x1C);
-       err += sn9c102_i2c_write(cam, 0x09, 0x01);
-       err += sn9c102_i2c_write(cam, 0x0A, 0x76);
-       err += sn9c102_i2c_write(cam, 0x0B, 0x60);
-       err += sn9c102_i2c_write(cam, 0x0C, 0x00);
-       err += sn9c102_i2c_write(cam, 0x0D, 0x08);
-       err += sn9c102_i2c_write(cam, 0x0E, 0x04);
-       err += sn9c102_i2c_write(cam, 0x0F, 0x6F);
-       err += sn9c102_i2c_write(cam, 0x10, 0x20);
-       err += sn9c102_i2c_write(cam, 0x11, 0x03);
-       err += sn9c102_i2c_write(cam, 0x12, 0x05);
-       err += sn9c102_i2c_write(cam, 0x13, 0xC7);
-       err += sn9c102_i2c_write(cam, 0x14, 0x2C);
-       err += sn9c102_i2c_write(cam, 0x15, 0x00);
-       err += sn9c102_i2c_write(cam, 0x16, 0x02);
-       err += sn9c102_i2c_write(cam, 0x17, 0x10);
-       err += sn9c102_i2c_write(cam, 0x18, 0x60);
-       err += sn9c102_i2c_write(cam, 0x19, 0x02);
-       err += sn9c102_i2c_write(cam, 0x1A, 0x7B);
-       err += sn9c102_i2c_write(cam, 0x1B, 0x02);
-       err += sn9c102_i2c_write(cam, 0x1C, 0x7F);
-       err += sn9c102_i2c_write(cam, 0x1D, 0xA2);
-       err += sn9c102_i2c_write(cam, 0x1E, 0x01);
-       err += sn9c102_i2c_write(cam, 0x1F, 0x0E);
-       err += sn9c102_i2c_write(cam, 0x20, 0x05);
-       err += sn9c102_i2c_write(cam, 0x21, 0x05);
-       err += sn9c102_i2c_write(cam, 0x22, 0x05);
-       err += sn9c102_i2c_write(cam, 0x23, 0x05);
-       err += sn9c102_i2c_write(cam, 0x24, 0x68);
-       err += sn9c102_i2c_write(cam, 0x25, 0x58);
-       err += sn9c102_i2c_write(cam, 0x26, 0xD4);
-       err += sn9c102_i2c_write(cam, 0x27, 0x80);
-       err += sn9c102_i2c_write(cam, 0x28, 0x80);
-       err += sn9c102_i2c_write(cam, 0x29, 0x30);
-       err += sn9c102_i2c_write(cam, 0x2A, 0x00);
-       err += sn9c102_i2c_write(cam, 0x2B, 0x00);
-       err += sn9c102_i2c_write(cam, 0x2C, 0x80);
-       err += sn9c102_i2c_write(cam, 0x2D, 0x00);
-       err += sn9c102_i2c_write(cam, 0x2E, 0x00);
-       err += sn9c102_i2c_write(cam, 0x2F, 0x0E);
-       err += sn9c102_i2c_write(cam, 0x30, 0x08);
-       err += sn9c102_i2c_write(cam, 0x31, 0x30);
-       err += sn9c102_i2c_write(cam, 0x32, 0xB4);
-       err += sn9c102_i2c_write(cam, 0x33, 0x00);
-       err += sn9c102_i2c_write(cam, 0x34, 0x07);
-       err += sn9c102_i2c_write(cam, 0x35, 0x84);
-       err += sn9c102_i2c_write(cam, 0x36, 0x00);
-       err += sn9c102_i2c_write(cam, 0x37, 0x0C);
-       err += sn9c102_i2c_write(cam, 0x38, 0x02);
-       err += sn9c102_i2c_write(cam, 0x39, 0x43);
-       err += sn9c102_i2c_write(cam, 0x3A, 0x00);
-       err += sn9c102_i2c_write(cam, 0x3B, 0x0A);
-       err += sn9c102_i2c_write(cam, 0x3C, 0x6C);
-       err += sn9c102_i2c_write(cam, 0x3D, 0x99);
-       err += sn9c102_i2c_write(cam, 0x3E, 0x0E);
-       err += sn9c102_i2c_write(cam, 0x3F, 0x41);
-       err += sn9c102_i2c_write(cam, 0x40, 0xC1);
-       err += sn9c102_i2c_write(cam, 0x41, 0x22);
-       err += sn9c102_i2c_write(cam, 0x42, 0x08);
-       err += sn9c102_i2c_write(cam, 0x43, 0xF0);
-       err += sn9c102_i2c_write(cam, 0x44, 0x10);
-       err += sn9c102_i2c_write(cam, 0x45, 0x78);
-       err += sn9c102_i2c_write(cam, 0x46, 0xA8);
-       err += sn9c102_i2c_write(cam, 0x47, 0x60);
-       err += sn9c102_i2c_write(cam, 0x48, 0x80);
-       err += sn9c102_i2c_write(cam, 0x49, 0x00);
-       err += sn9c102_i2c_write(cam, 0x4A, 0x00);
-       err += sn9c102_i2c_write(cam, 0x4B, 0x00);
-       err += sn9c102_i2c_write(cam, 0x4C, 0x00);
-       err += sn9c102_i2c_write(cam, 0x4D, 0x00);
-       err += sn9c102_i2c_write(cam, 0x4E, 0x00);
-       err += sn9c102_i2c_write(cam, 0x4F, 0x46);
-       err += sn9c102_i2c_write(cam, 0x50, 0x36);
-       err += sn9c102_i2c_write(cam, 0x51, 0x0F);
-       err += sn9c102_i2c_write(cam, 0x52, 0x17);
-       err += sn9c102_i2c_write(cam, 0x53, 0x7F);
-       err += sn9c102_i2c_write(cam, 0x54, 0x96);
-       err += sn9c102_i2c_write(cam, 0x55, 0x40);
-       err += sn9c102_i2c_write(cam, 0x56, 0x40);
-       err += sn9c102_i2c_write(cam, 0x57, 0x40);
-       err += sn9c102_i2c_write(cam, 0x58, 0x0F);
-       err += sn9c102_i2c_write(cam, 0x59, 0xBA);
-       err += sn9c102_i2c_write(cam, 0x5A, 0x9A);
-       err += sn9c102_i2c_write(cam, 0x5B, 0x22);
-       err += sn9c102_i2c_write(cam, 0x5C, 0xB9);
-       err += sn9c102_i2c_write(cam, 0x5D, 0x9B);
-       err += sn9c102_i2c_write(cam, 0x5E, 0x10);
-       err += sn9c102_i2c_write(cam, 0x5F, 0xF0);
-       err += sn9c102_i2c_write(cam, 0x60, 0x05);
-       err += sn9c102_i2c_write(cam, 0x61, 0x60);
-       err += sn9c102_i2c_write(cam, 0x62, 0x00);
-       err += sn9c102_i2c_write(cam, 0x63, 0x00);
-       err += sn9c102_i2c_write(cam, 0x64, 0x50);
-       err += sn9c102_i2c_write(cam, 0x65, 0x30);
-       err += sn9c102_i2c_write(cam, 0x66, 0x00);
-       err += sn9c102_i2c_write(cam, 0x67, 0x80);
-       err += sn9c102_i2c_write(cam, 0x68, 0x7A);
-       err += sn9c102_i2c_write(cam, 0x69, 0x90);
-       err += sn9c102_i2c_write(cam, 0x6A, 0x80);
-       err += sn9c102_i2c_write(cam, 0x6B, 0x0A);
-       err += sn9c102_i2c_write(cam, 0x6C, 0x30);
-       err += sn9c102_i2c_write(cam, 0x6D, 0x48);
-       err += sn9c102_i2c_write(cam, 0x6E, 0x80);
-       err += sn9c102_i2c_write(cam, 0x6F, 0x74);
-       err += sn9c102_i2c_write(cam, 0x70, 0x64);
-       err += sn9c102_i2c_write(cam, 0x71, 0x60);
-       err += sn9c102_i2c_write(cam, 0x72, 0x5C);
-       err += sn9c102_i2c_write(cam, 0x73, 0x58);
-       err += sn9c102_i2c_write(cam, 0x74, 0x54);
-       err += sn9c102_i2c_write(cam, 0x75, 0x4C);
-       err += sn9c102_i2c_write(cam, 0x76, 0x40);
-       err += sn9c102_i2c_write(cam, 0x77, 0x38);
-       err += sn9c102_i2c_write(cam, 0x78, 0x34);
-       err += sn9c102_i2c_write(cam, 0x79, 0x30);
-       err += sn9c102_i2c_write(cam, 0x7A, 0x2F);
-       err += sn9c102_i2c_write(cam, 0x7B, 0x2B);
-       err += sn9c102_i2c_write(cam, 0x7C, 0x03);
-       err += sn9c102_i2c_write(cam, 0x7D, 0x07);
-       err += sn9c102_i2c_write(cam, 0x7E, 0x17);
-       err += sn9c102_i2c_write(cam, 0x7F, 0x34);
-       err += sn9c102_i2c_write(cam, 0x80, 0x41);
-       err += sn9c102_i2c_write(cam, 0x81, 0x4D);
-       err += sn9c102_i2c_write(cam, 0x82, 0x58);
-       err += sn9c102_i2c_write(cam, 0x83, 0x63);
-       err += sn9c102_i2c_write(cam, 0x84, 0x6E);
-       err += sn9c102_i2c_write(cam, 0x85, 0x77);
-       err += sn9c102_i2c_write(cam, 0x86, 0x87);
-       err += sn9c102_i2c_write(cam, 0x87, 0x95);
-       err += sn9c102_i2c_write(cam, 0x88, 0xAF);
-       err += sn9c102_i2c_write(cam, 0x89, 0xC7);
-       err += sn9c102_i2c_write(cam, 0x8A, 0xDF);
-       err += sn9c102_i2c_write(cam, 0x8B, 0x99);
-       err += sn9c102_i2c_write(cam, 0x8C, 0x99);
-       err += sn9c102_i2c_write(cam, 0x8D, 0xCF);
-       err += sn9c102_i2c_write(cam, 0x8E, 0x20);
-       err += sn9c102_i2c_write(cam, 0x8F, 0x26);
-       err += sn9c102_i2c_write(cam, 0x90, 0x10);
-       err += sn9c102_i2c_write(cam, 0x91, 0x0C);
-       err += sn9c102_i2c_write(cam, 0x92, 0x25);
-       err += sn9c102_i2c_write(cam, 0x93, 0x00);
-       err += sn9c102_i2c_write(cam, 0x94, 0x50);
-       err += sn9c102_i2c_write(cam, 0x95, 0x50);
-       err += sn9c102_i2c_write(cam, 0x96, 0x00);
-       err += sn9c102_i2c_write(cam, 0x97, 0x01);
-       err += sn9c102_i2c_write(cam, 0x98, 0x10);
-       err += sn9c102_i2c_write(cam, 0x99, 0x40);
-       err += sn9c102_i2c_write(cam, 0x9A, 0x40);
-       err += sn9c102_i2c_write(cam, 0x9B, 0x20);
-       err += sn9c102_i2c_write(cam, 0x9C, 0x00);
-       err += sn9c102_i2c_write(cam, 0x9D, 0x99);
-       err += sn9c102_i2c_write(cam, 0x9E, 0x7F);
-       err += sn9c102_i2c_write(cam, 0x9F, 0x00);
-       err += sn9c102_i2c_write(cam, 0xA0, 0x00);
-       err += sn9c102_i2c_write(cam, 0xA1, 0x00);
-
-       return err;
-}
-
-
-static int ov7660_get_ctrl(struct sn9c102_device* cam,
-                          struct v4l2_control* ctrl)
-{
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
-                       return -EIO;
-               break;
-       case V4L2_CID_DO_WHITE_BALANCE:
-               if ((ctrl->value = sn9c102_read_reg(cam, 0x02)) < 0)
-                       return -EIO;
-               ctrl->value = (ctrl->value & 0x04) ? 1 : 0;
-               break;
-       case V4L2_CID_RED_BALANCE:
-               if ((ctrl->value = sn9c102_read_reg(cam, 0x05)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x7f;
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               if ((ctrl->value = sn9c102_read_reg(cam, 0x06)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x7f;
-               break;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               if ((ctrl->value = sn9c102_read_reg(cam, 0x07)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x7f;
-               break;
-       case SN9C102_V4L2_CID_BAND_FILTER:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x3b)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x08;
-               break;
-       case V4L2_CID_GAIN:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x00)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x1f;
-               break;
-       case V4L2_CID_AUTOGAIN:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x13)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x01;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return err ? -EIO : 0;
-}
-
-
-static int ov7660_set_ctrl(struct sn9c102_device* cam,
-                          const struct v4l2_control* ctrl)
-{
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
-               break;
-       case V4L2_CID_DO_WHITE_BALANCE:
-               err += sn9c102_write_reg(cam, 0x43 | (ctrl->value << 2), 0x02);
-               break;
-       case V4L2_CID_RED_BALANCE:
-               err += sn9c102_write_reg(cam, ctrl->value, 0x05);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               err += sn9c102_write_reg(cam, ctrl->value, 0x06);
-               break;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               err += sn9c102_write_reg(cam, ctrl->value, 0x07);
-               break;
-       case SN9C102_V4L2_CID_BAND_FILTER:
-               err += sn9c102_i2c_write(cam, ctrl->value << 3, 0x3b);
-               break;
-       case V4L2_CID_GAIN:
-               err += sn9c102_i2c_write(cam, 0x00, 0x60 + ctrl->value);
-               break;
-       case V4L2_CID_AUTOGAIN:
-               err += sn9c102_i2c_write(cam, 0x13, 0xc0 |
-                                                   (ctrl->value * 0x07));
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return err ? -EIO : 0;
-}
-
-
-static int ov7660_set_crop(struct sn9c102_device* cam,
-                          const struct v4l2_rect* rect)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
-          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
-
-       err += sn9c102_write_reg(cam, h_start, 0x12);
-       err += sn9c102_write_reg(cam, v_start, 0x13);
-
-       return err;
-}
-
-
-static int ov7660_set_pix_format(struct sn9c102_device* cam,
-                                const struct v4l2_pix_format* pix)
-{
-       int r0, err = 0;
-
-       r0 = sn9c102_pread_reg(cam, 0x01);
-
-       if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
-               err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
-               err += sn9c102_write_reg(cam, 0xa2, 0x17);
-               err += sn9c102_i2c_write(cam, 0x11, 0x00);
-       } else {
-               err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
-               err += sn9c102_write_reg(cam, 0xa2, 0x17);
-               err += sn9c102_i2c_write(cam, 0x11, 0x0d);
-       }
-
-       return err;
-}
-
-
-static const struct sn9c102_sensor ov7660 = {
-       .name = "OV7660",
-       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-       .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
-       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
-       .frequency = SN9C102_I2C_100KHZ,
-       .interface = SN9C102_I2C_2WIRES,
-       .i2c_slave_id = 0x21,
-       .init = &ov7660_init,
-       .qctrl = {
-               {
-                       .id = V4L2_CID_GAIN,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "global gain",
-                       .minimum = 0x00,
-                       .maximum = 0x1f,
-                       .step = 0x01,
-                       .default_value = 0x09,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_EXPOSURE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "exposure",
-                       .minimum = 0x00,
-                       .maximum = 0xff,
-                       .step = 0x01,
-                       .default_value = 0x27,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_DO_WHITE_BALANCE,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "night mode",
-                       .minimum = 0x00,
-                       .maximum = 0x01,
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_RED_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "red balance",
-                       .minimum = 0x00,
-                       .maximum = 0x7f,
-                       .step = 0x01,
-                       .default_value = 0x14,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_BLUE_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "blue balance",
-                       .minimum = 0x00,
-                       .maximum = 0x7f,
-                       .step = 0x01,
-                       .default_value = 0x14,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_AUTOGAIN,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "auto adjust",
-                       .minimum = 0x00,
-                       .maximum = 0x01,
-                       .step = 0x01,
-                       .default_value = 0x01,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "green balance",
-                       .minimum = 0x00,
-                       .maximum = 0x7f,
-                       .step = 0x01,
-                       .default_value = 0x14,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_BAND_FILTER,
-                       .type = V4L2_CTRL_TYPE_BOOLEAN,
-                       .name = "band filter",
-                       .minimum = 0x00,
-                       .maximum = 0x01,
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-       },
-       .get_ctrl = &ov7660_get_ctrl,
-       .set_ctrl = &ov7660_set_ctrl,
-       .cropcap = {
-               .bounds = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-               .defrect = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-       },
-       .set_crop = &ov7660_set_crop,
-       .pix_format = {
-               .width = 640,
-               .height = 480,
-               .pixelformat = V4L2_PIX_FMT_JPEG,
-               .priv = 8,
-       },
-       .set_pix_format = &ov7660_set_pix_format
-};
-
-
-int sn9c102_probe_ov7660(struct sn9c102_device* cam)
-{
-       int pid, ver, err;
-
-       err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
-                                      {0x01, 0x01}, {0x00, 0x01},
-                                      {0x28, 0x17});
-
-       pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a);
-       ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b);
-       if (err || pid < 0 || ver < 0)
-               return -EIO;
-       if (pid != 0x76 || ver != 0x60)
-               return -ENODEV;
-
-       sn9c102_attach_sensor(cam, &ov7660);
-
-       return 0;
-}
diff --git a/drivers/media/video/sn9c102/sn9c102_pas106b.c b/drivers/media/video/sn9c102/sn9c102_pas106b.c
deleted file mode 100644 (file)
index 81cd969..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-/***************************************************************************
- * Plug-in for PAS106B image sensor connected to the SN9C1xx PC Camera     *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * 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/delay.h>
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int pas106b_init(struct sn9c102_device* cam)
-{
-       int err = 0;
-
-       err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
-                                      {0x00, 0x14}, {0x20, 0x17},
-                                      {0x20, 0x19}, {0x09, 0x18});
-
-       err += sn9c102_i2c_write(cam, 0x02, 0x0c);
-       err += sn9c102_i2c_write(cam, 0x05, 0x5a);
-       err += sn9c102_i2c_write(cam, 0x06, 0x88);
-       err += sn9c102_i2c_write(cam, 0x07, 0x80);
-       err += sn9c102_i2c_write(cam, 0x10, 0x06);
-       err += sn9c102_i2c_write(cam, 0x11, 0x06);
-       err += sn9c102_i2c_write(cam, 0x12, 0x00);
-       err += sn9c102_i2c_write(cam, 0x14, 0x02);
-       err += sn9c102_i2c_write(cam, 0x13, 0x01);
-
-       msleep(400);
-
-       return err;
-}
-
-
-static int pas106b_get_ctrl(struct sn9c102_device* cam,
-                           struct v4l2_control* ctrl)
-{
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               {
-                       int r1 = sn9c102_i2c_read(cam, 0x03),
-                           r2 = sn9c102_i2c_read(cam, 0x04);
-                       if (r1 < 0 || r2 < 0)
-                               return -EIO;
-                       ctrl->value = (r1 << 4) | (r2 & 0x0f);
-               }
-               return 0;
-       case V4L2_CID_RED_BALANCE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x1f;
-               return 0;
-       case V4L2_CID_BLUE_BALANCE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x1f;
-               return 0;
-       case V4L2_CID_GAIN:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0e)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x1f;
-               return 0;
-       case V4L2_CID_CONTRAST:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0f)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x07;
-               return 0;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0a)) < 0)
-                       return -EIO;
-               ctrl->value = (ctrl->value & 0x1f) << 1;
-               return 0;
-       case SN9C102_V4L2_CID_DAC_MAGNITUDE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0)
-                       return -EIO;
-               ctrl->value &= 0xf8;
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-
-static int pas106b_set_ctrl(struct sn9c102_device* cam,
-                           const struct v4l2_control* ctrl)
-{
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               err += sn9c102_i2c_write(cam, 0x03, ctrl->value >> 4);
-               err += sn9c102_i2c_write(cam, 0x04, ctrl->value & 0x0f);
-               break;
-       case V4L2_CID_RED_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
-               break;
-       case V4L2_CID_GAIN:
-               err += sn9c102_i2c_write(cam, 0x0e, ctrl->value);
-               break;
-       case V4L2_CID_CONTRAST:
-               err += sn9c102_i2c_write(cam, 0x0f, ctrl->value);
-               break;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x0a, ctrl->value >> 1);
-               err += sn9c102_i2c_write(cam, 0x0b, ctrl->value >> 1);
-               break;
-       case SN9C102_V4L2_CID_DAC_MAGNITUDE:
-               err += sn9c102_i2c_write(cam, 0x08, ctrl->value << 3);
-               break;
-       default:
-               return -EINVAL;
-       }
-       err += sn9c102_i2c_write(cam, 0x13, 0x01);
-
-       return err ? -EIO : 0;
-}
-
-
-static int pas106b_set_crop(struct sn9c102_device* cam,
-                           const struct v4l2_rect* rect)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
-          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
-
-       err += sn9c102_write_reg(cam, h_start, 0x12);
-       err += sn9c102_write_reg(cam, v_start, 0x13);
-
-       return err;
-}
-
-
-static int pas106b_set_pix_format(struct sn9c102_device* cam,
-                                 const struct v4l2_pix_format* pix)
-{
-       int err = 0;
-
-       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-               err += sn9c102_write_reg(cam, 0x2c, 0x17);
-       else
-               err += sn9c102_write_reg(cam, 0x20, 0x17);
-
-       return err;
-}
-
-
-static const struct sn9c102_sensor pas106b = {
-       .name = "PAS106B",
-       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
-       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
-       .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
-       .interface = SN9C102_I2C_2WIRES,
-       .i2c_slave_id = 0x40,
-       .init = &pas106b_init,
-       .qctrl = {
-               {
-                       .id = V4L2_CID_EXPOSURE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "exposure",
-                       .minimum = 0x125,
-                       .maximum = 0xfff,
-                       .step = 0x001,
-                       .default_value = 0x140,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_GAIN,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "global gain",
-                       .minimum = 0x00,
-                       .maximum = 0x1f,
-                       .step = 0x01,
-                       .default_value = 0x0d,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_CONTRAST,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "contrast",
-                       .minimum = 0x00,
-                       .maximum = 0x07,
-                       .step = 0x01,
-                       .default_value = 0x00, /* 0x00~0x03 have same effect */
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_RED_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "red balance",
-                       .minimum = 0x00,
-                       .maximum = 0x1f,
-                       .step = 0x01,
-                       .default_value = 0x04,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_BLUE_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "blue balance",
-                       .minimum = 0x00,
-                       .maximum = 0x1f,
-                       .step = 0x01,
-                       .default_value = 0x06,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "green balance",
-                       .minimum = 0x00,
-                       .maximum = 0x3e,
-                       .step = 0x02,
-                       .default_value = 0x02,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "DAC magnitude",
-                       .minimum = 0x00,
-                       .maximum = 0x1f,
-                       .step = 0x01,
-                       .default_value = 0x01,
-                       .flags = 0,
-               },
-       },
-       .get_ctrl = &pas106b_get_ctrl,
-       .set_ctrl = &pas106b_set_ctrl,
-       .cropcap = {
-               .bounds = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 352,
-                       .height = 288,
-               },
-               .defrect = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 352,
-                       .height = 288,
-               },
-       },
-       .set_crop = &pas106b_set_crop,
-       .pix_format = {
-               .width = 352,
-               .height = 288,
-               .pixelformat = V4L2_PIX_FMT_SBGGR8,
-               .priv = 8, /* we use this field as 'bits per pixel' */
-       },
-       .set_pix_format = &pas106b_set_pix_format
-};
-
-
-int sn9c102_probe_pas106b(struct sn9c102_device* cam)
-{
-       int r0 = 0, r1 = 0;
-       unsigned int pid = 0;
-
-       /*
-          Minimal initialization to enable the I2C communication
-          NOTE: do NOT change the values!
-       */
-       if (sn9c102_write_const_regs(cam,
-                                    {0x01, 0x01}, /* sensor power down */
-                                    {0x00, 0x01}, /* sensor power on */
-                                   {0x28, 0x17})) /* sensor clock at 24 MHz */
-               return -EIO;
-
-       r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00);
-       r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01);
-       if (r0 < 0 || r1 < 0)
-               return -EIO;
-
-       pid = (r0 << 11) | ((r1 & 0xf0) >> 4);
-       if (pid != 0x007)
-               return -ENODEV;
-
-       sn9c102_attach_sensor(cam, &pas106b);
-
-       return 0;
-}
diff --git a/drivers/media/video/sn9c102/sn9c102_pas202bcb.c b/drivers/media/video/sn9c102/sn9c102_pas202bcb.c
deleted file mode 100644 (file)
index 2e86fdc..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-/***************************************************************************
- * Plug-in for PAS202BCB image sensor connected to the SN9C1xx PC Camera   *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio                  *
- *                       <medaglia@undl.org.br>                            *
- *                                                                         *
- * Support for SN9C103, DAC Magnitude, exposure and green gain controls    *
- * added by Luca Risolia <luca.risolia@studio.unibo.it>                    *
- *                                                                         *
- * 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/delay.h>
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int pas202bcb_init(struct sn9c102_device* cam)
-{
-       int err = 0;
-
-       switch (sn9c102_get_bridge(cam)) {
-       case BRIDGE_SN9C101:
-       case BRIDGE_SN9C102:
-               err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
-                                              {0x00, 0x14}, {0x20, 0x17},
-                                              {0x30, 0x19}, {0x09, 0x18});
-               break;
-       case BRIDGE_SN9C103:
-               err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
-                                              {0x1a, 0x04}, {0x20, 0x05},
-                                              {0x20, 0x06}, {0x20, 0x07},
-                                              {0x00, 0x10}, {0x00, 0x11},
-                                              {0x00, 0x14}, {0x20, 0x17},
-                                              {0x30, 0x19}, {0x09, 0x18},
-                                              {0x02, 0x1c}, {0x03, 0x1d},
-                                              {0x0f, 0x1e}, {0x0c, 0x1f},
-                                              {0x00, 0x20}, {0x10, 0x21},
-                                              {0x20, 0x22}, {0x30, 0x23},
-                                              {0x40, 0x24}, {0x50, 0x25},
-                                              {0x60, 0x26}, {0x70, 0x27},
-                                              {0x80, 0x28}, {0x90, 0x29},
-                                              {0xa0, 0x2a}, {0xb0, 0x2b},
-                                              {0xc0, 0x2c}, {0xd0, 0x2d},
-                                              {0xe0, 0x2e}, {0xf0, 0x2f},
-                                              {0xff, 0x30});
-               break;
-       default:
-               break;
-       }
-
-       err += sn9c102_i2c_write(cam, 0x02, 0x14);
-       err += sn9c102_i2c_write(cam, 0x03, 0x40);
-       err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
-       err += sn9c102_i2c_write(cam, 0x0e, 0x01);
-       err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
-       err += sn9c102_i2c_write(cam, 0x10, 0x08);
-       err += sn9c102_i2c_write(cam, 0x13, 0x63);
-       err += sn9c102_i2c_write(cam, 0x15, 0x70);
-       err += sn9c102_i2c_write(cam, 0x11, 0x01);
-
-       msleep(400);
-
-       return err;
-}
-
-
-static int pas202bcb_get_ctrl(struct sn9c102_device* cam,
-                             struct v4l2_control* ctrl)
-{
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               {
-                       int r1 = sn9c102_i2c_read(cam, 0x04),
-                           r2 = sn9c102_i2c_read(cam, 0x05);
-                       if (r1 < 0 || r2 < 0)
-                               return -EIO;
-                       ctrl->value = (r1 << 6) | (r2 & 0x3f);
-               }
-               return 0;
-       case V4L2_CID_RED_BALANCE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x09)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x0f;
-               return 0;
-       case V4L2_CID_BLUE_BALANCE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x0f;
-               return 0;
-       case V4L2_CID_GAIN:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x10)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x1f;
-               return 0;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x08)) < 0)
-                       return -EIO;
-               ctrl->value &= 0x0f;
-               return 0;
-       case SN9C102_V4L2_CID_DAC_MAGNITUDE:
-               if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
-                       return -EIO;
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-
-static int pas202bcb_set_pix_format(struct sn9c102_device* cam,
-                                   const struct v4l2_pix_format* pix)
-{
-       int err = 0;
-
-       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-               err += sn9c102_write_reg(cam, 0x28, 0x17);
-       else
-               err += sn9c102_write_reg(cam, 0x20, 0x17);
-
-       return err;
-}
-
-
-static int pas202bcb_set_ctrl(struct sn9c102_device* cam,
-                             const struct v4l2_control* ctrl)
-{
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_EXPOSURE:
-               err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6);
-               err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f);
-               break;
-       case V4L2_CID_RED_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
-               break;
-       case V4L2_CID_BLUE_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x07, ctrl->value);
-               break;
-       case V4L2_CID_GAIN:
-               err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
-               break;
-       case SN9C102_V4L2_CID_GREEN_BALANCE:
-               err += sn9c102_i2c_write(cam, 0x08, ctrl->value);
-               break;
-       case SN9C102_V4L2_CID_DAC_MAGNITUDE:
-               err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
-               break;
-       default:
-               return -EINVAL;
-       }
-       err += sn9c102_i2c_write(cam, 0x11, 0x01);
-
-       return err ? -EIO : 0;
-}
-
-
-static int pas202bcb_set_crop(struct sn9c102_device* cam,
-                             const struct v4l2_rect* rect)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-       u8 h_start = 0,
-          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
-
-       switch (sn9c102_get_bridge(cam)) {
-       case BRIDGE_SN9C101:
-       case BRIDGE_SN9C102:
-               h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
-               break;
-       case BRIDGE_SN9C103:
-               h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3;
-               break;
-       default:
-               break;
-       }
-
-       err += sn9c102_write_reg(cam, h_start, 0x12);
-       err += sn9c102_write_reg(cam, v_start, 0x13);
-
-       return err;
-}
-
-
-static const struct sn9c102_sensor pas202bcb = {
-       .name = "PAS202BCB",
-       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
-       .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
-       .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
-       .interface = SN9C102_I2C_2WIRES,
-       .i2c_slave_id = 0x40,
-       .init = &pas202bcb_init,
-       .qctrl = {
-               {
-                       .id = V4L2_CID_EXPOSURE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "exposure",
-                       .minimum = 0x01e5,
-                       .maximum = 0x3fff,
-                       .step = 0x0001,
-                       .default_value = 0x01e5,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_GAIN,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "global gain",
-                       .minimum = 0x00,
-                       .maximum = 0x1f,
-                       .step = 0x01,
-                       .default_value = 0x0b,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_RED_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "red balance",
-                       .minimum = 0x00,
-                       .maximum = 0x0f,
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_BLUE_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "blue balance",
-                       .minimum = 0x00,
-                       .maximum = 0x0f,
-                       .step = 0x01,
-                       .default_value = 0x05,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_GREEN_BALANCE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "green balance",
-                       .minimum = 0x00,
-                       .maximum = 0x0f,
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-               {
-                       .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "DAC magnitude",
-                       .minimum = 0x00,
-                       .maximum = 0xff,
-                       .step = 0x01,
-                       .default_value = 0x04,
-                       .flags = 0,
-               },
-       },
-       .get_ctrl = &pas202bcb_get_ctrl,
-       .set_ctrl = &pas202bcb_set_ctrl,
-       .cropcap = {
-               .bounds = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-               .defrect = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-       },
-       .set_crop = &pas202bcb_set_crop,
-       .pix_format = {
-               .width = 640,
-               .height = 480,
-               .pixelformat = V4L2_PIX_FMT_SBGGR8,
-               .priv = 8,
-       },
-       .set_pix_format = &pas202bcb_set_pix_format
-};
-
-
-int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
-{
-       int r0 = 0, r1 = 0, err = 0;
-       unsigned int pid = 0;
-
-       /*
-        *  Minimal initialization to enable the I2C communication
-        *  NOTE: do NOT change the values!
-        */
-       switch (sn9c102_get_bridge(cam)) {
-       case BRIDGE_SN9C101:
-       case BRIDGE_SN9C102:
-               err = sn9c102_write_const_regs(cam,
-                                              {0x01, 0x01}, /* power down */
-                                              {0x40, 0x01}, /* power on */
-                                              {0x28, 0x17});/* clock 24 MHz */
-               break;
-       case BRIDGE_SN9C103: /* do _not_ change anything! */
-               err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x01},
-                                              {0x44, 0x02}, {0x29, 0x17});
-               break;
-       default:
-               break;
-       }
-
-       r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00);
-       r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01);
-
-       if (err || r0 < 0 || r1 < 0)
-               return -EIO;
-
-       pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
-       if (pid != 0x017)
-               return -ENODEV;
-
-       sn9c102_attach_sensor(cam, &pas202bcb);
-
-       return 0;
-}
diff --git a/drivers/media/video/sn9c102/sn9c102_sensor.h b/drivers/media/video/sn9c102/sn9c102_sensor.h
deleted file mode 100644 (file)
index 3679970..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/***************************************************************************
- * API for image sensors connected to the SN9C1xx PC Camera Controllers    *
- *                                                                         *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * 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.               *
- ***************************************************************************/
-
-#ifndef _SN9C102_SENSOR_H_
-#define _SN9C102_SENSOR_H_
-
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include <linux/device.h>
-#include <linux/stddef.h>
-#include <linux/errno.h>
-#include <asm/types.h>
-
-struct sn9c102_device;
-struct sn9c102_sensor;
-
-/*****************************************************************************/
-
-/*
-   OVERVIEW.
-   This is a small interface that allows you to add support for any CCD/CMOS
-   image sensors connected to the SN9C1XX bridges. The entire API is documented
-   below. In the most general case, to support a sensor there are three steps
-   you have to follow:
-   1) define the main "sn9c102_sensor" structure by setting the basic fields;
-   2) write a probing function to be called by the core module when the USB
-      camera is recognized, then add both the USB ids and the name of that
-      function to the two corresponding tables in sn9c102_devtable.h;
-   3) implement the methods that you want/need (and fill the rest of the main
-      structure accordingly).
-   "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do
-   NOT need to touch the source code of the core module for the things to work
-   properly, unless you find bugs or flaws in it. Finally, do not forget to
-   read the V4L2 API for completeness.
-*/
-
-/*****************************************************************************/
-
-enum sn9c102_bridge {
-       BRIDGE_SN9C101 = 0x01,
-       BRIDGE_SN9C102 = 0x02,
-       BRIDGE_SN9C103 = 0x04,
-       BRIDGE_SN9C105 = 0x08,
-       BRIDGE_SN9C120 = 0x10,
-};
-
-/* Return the bridge name */
-enum sn9c102_bridge sn9c102_get_bridge(struct sn9c102_device* cam);
-
-/* Return a pointer the sensor struct attached to the camera */
-struct sn9c102_sensor* sn9c102_get_sensor(struct sn9c102_device* cam);
-
-/* Identify a device */
-extern struct sn9c102_device*
-sn9c102_match_id(struct sn9c102_device* cam, const struct usb_device_id *id);
-
-/* Attach a probed sensor to the camera. */
-extern void
-sn9c102_attach_sensor(struct sn9c102_device* cam,
-                     const struct sn9c102_sensor* sensor);
-
-/*
-   Read/write routines: they always return -1 on error, 0 or the read value
-   otherwise. NOTE that a real read operation is not supported by the SN9C1XX
-   chip for some of its registers. To work around this problem, a pseudo-read
-   call is provided instead: it returns the last successfully written value
-   on the register (0 if it has never been written), the usual -1 on error.
-*/
-
-/* The "try" I2C I/O versions are used when probing the sensor */
-extern int sn9c102_i2c_try_read(struct sn9c102_device*,
-                               const struct sn9c102_sensor*, u8 address);
-
-/*
-   These must be used if and only if the sensor doesn't implement the standard
-   I2C protocol. There are a number of good reasons why you must use the
-   single-byte versions of these functions: do not abuse. The first function
-   writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C1XX
-   chip. The second one programs the registers 0x09 and 0x10 with data0 and
-   data1, and places the n bytes read from the sensor register table in the
-   buffer pointed by 'buffer'. Both the functions return -1 on error; the write
-   version returns 0 on success, while the read version returns the first read
-   byte.
-*/
-extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
-                                    const struct sn9c102_sensor* sensor, u8 n,
-                                    u8 data0, u8 data1, u8 data2, u8 data3,
-                                    u8 data4, u8 data5);
-extern int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
-                                   const struct sn9c102_sensor* sensor,
-                                   u8 data0, u8 data1, u8 n, u8 buffer[]);
-
-/* To be used after the sensor struct has been attached to the camera struct */
-extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value);
-extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address);
-
-/* I/O on registers in the bridge. Could be used by the sensor methods too */
-extern int sn9c102_read_reg(struct sn9c102_device*, u16 index);
-extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
-extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
-extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2],
-                             int count);
-/*
-   Write multiple registers with constant values. For example:
-   sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18});
-   Register addresses must be < 256.
-*/
-#define sn9c102_write_const_regs(sn9c102_device, data...)                     \
-       ({ static const u8 _valreg[][2] = {data};                             \
-       sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); })
-
-/*****************************************************************************/
-
-enum sn9c102_i2c_sysfs_ops {
-       SN9C102_I2C_READ = 0x01,
-       SN9C102_I2C_WRITE = 0x02,
-};
-
-enum sn9c102_i2c_frequency { /* sensors may support both the frequencies */
-       SN9C102_I2C_100KHZ = 0x01,
-       SN9C102_I2C_400KHZ = 0x02,
-};
-
-enum sn9c102_i2c_interface {
-       SN9C102_I2C_2WIRES,
-       SN9C102_I2C_3WIRES,
-};
-
-#define SN9C102_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10)
-
-struct sn9c102_sensor {
-       char name[32], /* sensor name */
-            maintainer[64]; /* name of the maintainer <email> */
-
-       enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */
-
-       /* Supported operations through the 'sysfs' interface */
-       enum sn9c102_i2c_sysfs_ops sysfs_ops;
-
-       /*
-          These sensor capabilities must be provided if the SN9C1XX controller
-          needs to communicate through the sensor serial interface by using
-          at least one of the i2c functions available.
-       */
-       enum sn9c102_i2c_frequency frequency;
-       enum sn9c102_i2c_interface interface;
-
-       /*
-          This identifier must be provided if the image sensor implements
-          the standard I2C protocol.
-       */
-       u8 i2c_slave_id; /* reg. 0x09 */
-
-       /*
-          NOTE: Where not noted,most of the functions below are not mandatory.
-                Set to null if you do not implement them. If implemented,
-                they must return 0 on success, the proper error otherwise.
-       */
-
-       int (*init)(struct sn9c102_device* cam);
-       /*
-          This function will be called after the sensor has been attached.
-          It should be used to initialize the sensor only, but may also
-          configure part of the SN9C1XX chip if necessary. You don't need to
-          setup picture settings like brightness, contrast, etc.. here, if
-          the corresponding controls are implemented (see below), since
-          they are adjusted in the core driver by calling the set_ctrl()
-          method after init(), where the arguments are the default values
-          specified in the v4l2_queryctrl list of supported controls;
-          Same suggestions apply for other settings, _if_ the corresponding
-          methods are present; if not, the initialization must configure the
-          sensor according to the default configuration structures below.
-       */
-
-       struct v4l2_queryctrl qctrl[SN9C102_MAX_CTRLS];
-       /*
-          Optional list of default controls, defined as indicated in the
-          V4L2 API. Menu type controls are not handled by this interface.
-       */
-
-       int (*get_ctrl)(struct sn9c102_device* cam, struct v4l2_control* ctrl);
-       int (*set_ctrl)(struct sn9c102_device* cam,
-                       const struct v4l2_control* ctrl);
-       /*
-          You must implement at least the set_ctrl method if you have defined
-          the list above. The returned value must follow the V4L2
-          specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER
-          are not supported by this driver, so do not implement them. Also,
-          you don't have to check whether the passed values are out of bounds,
-          given that this is done by the core module.
-       */
-
-       struct v4l2_cropcap cropcap;
-       /*
-          Think the image sensor as a grid of R,G,B monochromatic pixels
-          disposed according to a particular Bayer pattern, which describes
-          the complete array of pixels, from (0,0) to (xmax, ymax). We will
-          use this coordinate system from now on. It is assumed the sensor
-          chip can be programmed to capture/transmit a subsection of that
-          array of pixels: we will call this subsection "active window".
-          It is not always true that the largest achievable active window can
-          cover the whole array of pixels. The V4L2 API defines another
-          area called "source rectangle", which, in turn, is a subrectangle of
-          the active window. The SN9C1XX chip is always programmed to read the
-          source rectangle.
-          The bounds of both the active window and the source rectangle are
-          specified in the cropcap substructures 'bounds' and 'defrect'.
-          By default, the source rectangle should cover the largest possible
-          area. Again, it is not always true that the largest source rectangle
-          can cover the entire active window, although it is a rare case for
-          the hardware we have. The bounds of the source rectangle _must_ be
-          multiple of 16 and must use the same coordinate system as indicated
-          before; their centers shall align initially.
-          If necessary, the sensor chip must be initialized during init() to
-          set the bounds of the active sensor window; however, by default, it
-          usually covers the largest achievable area (maxwidth x maxheight)
-          of pixels, so no particular initialization is needed, if you have
-          defined the correct default bounds in the structures.
-          See the V4L2 API for further details.
-          NOTE: once you have defined the bounds of the active window
-                (struct cropcap.bounds) you must not change them.anymore.
-          Only 'bounds' and 'defrect' fields are mandatory, other fields
-          will be ignored.
-       */
-
-       int (*set_crop)(struct sn9c102_device* cam,
-                       const struct v4l2_rect* rect);
-       /*
-          To be called on VIDIOC_C_SETCROP. The core module always calls a
-          default routine which configures the appropriate SN9C1XX regs (also
-          scaling), but you may need to override/adjust specific stuff.
-          'rect' contains width and height values that are multiple of 16: in
-          case you override the default function, you always have to program
-          the chip to match those values; on error return the corresponding
-          error code without rolling back.
-          NOTE: in case, you must program the SN9C1XX chip to get rid of
-                blank pixels or blank lines at the _start_ of each line or
-                frame after each HSYNC or VSYNC, so that the image starts with
-                real RGB data (see regs 0x12, 0x13) (having set H_SIZE and,
-                V_SIZE you don't have to care about blank pixels or blank
-                lines at the end of each line or frame).
-       */
-
-       struct v4l2_pix_format pix_format;
-       /*
-          What you have to define here are: 1) initial 'width' and 'height' of
-          the target rectangle 2) the initial 'pixelformat', which can be
-          either V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_JPEG (for ompressed video)
-          or V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate
-          the number of bits per pixel for uncompressed video, 8 or 9 (despite
-          the current value of 'pixelformat').
-          NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4
-                  of cropcap.defrect.width and cropcap.defrect.height. I
-                  suggest 1/1.
-          NOTE 2: The initial compression quality is defined by the first bit
-                  of reg 0x17 during the initialization of the image sensor.
-          NOTE 3: as said above, you have to program the SN9C1XX chip to get
-                  rid of any blank pixels, so that the output of the sensor
-                  matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
-       */
-
-       int (*set_pix_format)(struct sn9c102_device* cam,
-                             const struct v4l2_pix_format* pix);
-       /*
-          To be called on VIDIOC_S_FMT, when switching from the SBGGR8 to
-          SN9C10X pixel format or viceversa. On error return the corresponding
-          error code without rolling back.
-       */
-
-       /*
-          Do NOT write to the data below, it's READ ONLY. It is used by the
-          core module to store successfully updated values of the above
-          settings, for rollbacks..etc..in case of errors during atomic I/O
-       */
-       struct v4l2_queryctrl _qctrl[SN9C102_MAX_CTRLS];
-       struct v4l2_rect _rect;
-};
-
-/*****************************************************************************/
-
-/* Private ioctl's for control settings supported by some image sensors */
-#define SN9C102_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0)
-#define SN9C102_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1)
-#define SN9C102_V4L2_CID_RESET_LEVEL (V4L2_CID_PRIVATE_BASE + 2)
-#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE (V4L2_CID_PRIVATE_BASE + 3)
-#define SN9C102_V4L2_CID_GAMMA (V4L2_CID_PRIVATE_BASE + 4)
-#define SN9C102_V4L2_CID_BAND_FILTER (V4L2_CID_PRIVATE_BASE + 5)
-#define SN9C102_V4L2_CID_BRIGHT_LEVEL (V4L2_CID_PRIVATE_BASE + 6)
-
-#endif /* _SN9C102_SENSOR_H_ */
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c b/drivers/media/video/sn9c102/sn9c102_tas5110c1b.c
deleted file mode 100644 (file)
index 04cdfdd..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/***************************************************************************
- * Plug-in for TAS5110C1B image sensor connected to the SN9C1xx PC Camera  *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int tas5110c1b_init(struct sn9c102_device* cam)
-{
-       int err = 0;
-
-       err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x44, 0x01},
-                                      {0x00, 0x10}, {0x00, 0x11},
-                                      {0x0a, 0x14}, {0x60, 0x17},
-                                      {0x06, 0x18}, {0xfb, 0x19});
-
-       err += sn9c102_i2c_write(cam, 0xc0, 0x80);
-
-       return err;
-}
-
-
-static int tas5110c1b_set_ctrl(struct sn9c102_device* cam,
-                              const struct v4l2_control* ctrl)
-{
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_GAIN:
-               err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return err ? -EIO : 0;
-}
-
-
-static int tas5110c1b_set_crop(struct sn9c102_device* cam,
-                              const struct v4l2_rect* rect)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
-          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
-
-       err += sn9c102_write_reg(cam, h_start, 0x12);
-       err += sn9c102_write_reg(cam, v_start, 0x13);
-
-       /* Don't change ! */
-       err += sn9c102_write_reg(cam, 0x14, 0x1a);
-       err += sn9c102_write_reg(cam, 0x0a, 0x1b);
-       err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19);
-
-       return err;
-}
-
-
-static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
-                                    const struct v4l2_pix_format* pix)
-{
-       int err = 0;
-
-       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-               err += sn9c102_write_reg(cam, 0x2b, 0x19);
-       else
-               err += sn9c102_write_reg(cam, 0xfb, 0x19);
-
-       return err;
-}
-
-
-static const struct sn9c102_sensor tas5110c1b = {
-       .name = "TAS5110C1B",
-       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
-       .sysfs_ops = SN9C102_I2C_WRITE,
-       .frequency = SN9C102_I2C_100KHZ,
-       .interface = SN9C102_I2C_3WIRES,
-       .init = &tas5110c1b_init,
-       .qctrl = {
-               {
-                       .id = V4L2_CID_GAIN,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "global gain",
-                       .minimum = 0x00,
-                       .maximum = 0xf6,
-                       .step = 0x01,
-                       .default_value = 0x40,
-                       .flags = 0,
-               },
-       },
-       .set_ctrl = &tas5110c1b_set_ctrl,
-       .cropcap = {
-               .bounds = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 352,
-                       .height = 288,
-               },
-               .defrect = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 352,
-                       .height = 288,
-               },
-       },
-       .set_crop = &tas5110c1b_set_crop,
-       .pix_format = {
-               .width = 352,
-               .height = 288,
-               .pixelformat = V4L2_PIX_FMT_SBGGR8,
-               .priv = 8,
-       },
-       .set_pix_format = &tas5110c1b_set_pix_format
-};
-
-
-int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
-{
-       const struct usb_device_id tas5110c1b_id_table[] = {
-               { USB_DEVICE(0x0c45, 0x6001), },
-               { USB_DEVICE(0x0c45, 0x6005), },
-               { USB_DEVICE(0x0c45, 0x60ab), },
-               { }
-       };
-
-       /* Sensor detection is based on USB pid/vid */
-       if (!sn9c102_match_id(cam, tas5110c1b_id_table))
-               return -ENODEV;
-
-       sn9c102_attach_sensor(cam, &tas5110c1b);
-
-       return 0;
-}
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5110d.c b/drivers/media/video/sn9c102/sn9c102_tas5110d.c
deleted file mode 100644 (file)
index 9372e6f..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/***************************************************************************
- * Plug-in for TAS5110D image sensor connected to the SN9C1xx PC Camera    *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it>       *
- *                                                                         *
- * 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int tas5110d_init(struct sn9c102_device* cam)
-{
-       int err;
-
-       err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x04, 0x01},
-                                      {0x0a, 0x14}, {0x60, 0x17},
-                                      {0x06, 0x18}, {0xfb, 0x19});
-
-       err += sn9c102_i2c_write(cam, 0x9a, 0xca);
-
-       return err;
-}
-
-
-static int tas5110d_set_crop(struct sn9c102_device* cam,
-                            const struct v4l2_rect* rect)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       int err = 0;
-       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
-          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
-
-       err += sn9c102_write_reg(cam, h_start, 0x12);
-       err += sn9c102_write_reg(cam, v_start, 0x13);
-
-       err += sn9c102_write_reg(cam, 0x14, 0x1a);
-       err += sn9c102_write_reg(cam, 0x0a, 0x1b);
-
-       return err;
-}
-
-
-static int tas5110d_set_pix_format(struct sn9c102_device* cam,
-                                    const struct v4l2_pix_format* pix)
-{
-       int err = 0;
-
-       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-               err += sn9c102_write_reg(cam, 0x3b, 0x19);
-       else
-               err += sn9c102_write_reg(cam, 0xfb, 0x19);
-
-       return err;
-}
-
-
-static const struct sn9c102_sensor tas5110d = {
-       .name = "TAS5110D",
-       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
-       .sysfs_ops = SN9C102_I2C_WRITE,
-       .frequency = SN9C102_I2C_100KHZ,
-       .interface = SN9C102_I2C_2WIRES,
-       .i2c_slave_id = 0x61,
-       .init = &tas5110d_init,
-       .cropcap = {
-               .bounds = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 352,
-                       .height = 288,
-               },
-               .defrect = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 352,
-                       .height = 288,
-               },
-       },
-       .set_crop = &tas5110d_set_crop,
-       .pix_format = {
-               .width = 352,
-               .height = 288,
-               .pixelformat = V4L2_PIX_FMT_SBGGR8,
-               .priv = 8,
-       },
-       .set_pix_format = &tas5110d_set_pix_format
-};
-
-
-int sn9c102_probe_tas5110d(struct sn9c102_device* cam)
-{
-       const struct usb_device_id tas5110d_id_table[] = {
-               { USB_DEVICE(0x0c45, 0x6007), },
-               { }
-       };
-
-       if (!sn9c102_match_id(cam, tas5110d_id_table))
-               return -ENODEV;
-
-       sn9c102_attach_sensor(cam, &tas5110d);
-
-       return 0;
-}
diff --git a/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c b/drivers/media/video/sn9c102/sn9c102_tas5130d1b.c
deleted file mode 100644 (file)
index a30bbc4..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/***************************************************************************
- * Plug-in for TAS5130D1B image sensor connected to the SN9C1xx PC Camera  *
- * Controllers                                                             *
- *                                                                         *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>  *
- *                                                                         *
- * 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 "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int tas5130d1b_init(struct sn9c102_device* cam)
-{
-       int err;
-
-       err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x20, 0x17},
-                                      {0x04, 0x01}, {0x01, 0x10},
-                                      {0x00, 0x11}, {0x00, 0x14},
-                                      {0x60, 0x17}, {0x07, 0x18});
-
-       return err;
-}
-
-
-static int tas5130d1b_set_ctrl(struct sn9c102_device* cam,
-                              const struct v4l2_control* ctrl)
-{
-       int err = 0;
-
-       switch (ctrl->id) {
-       case V4L2_CID_GAIN:
-               err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
-               break;
-       case V4L2_CID_EXPOSURE:
-               err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return err ? -EIO : 0;
-}
-
-
-static int tas5130d1b_set_crop(struct sn9c102_device* cam,
-                              const struct v4l2_rect* rect)
-{
-       struct sn9c102_sensor* s = sn9c102_get_sensor(cam);
-       u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104,
-          v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12;
-       int err = 0;
-
-       err += sn9c102_write_reg(cam, h_start, 0x12);
-       err += sn9c102_write_reg(cam, v_start, 0x13);
-
-       /* Do NOT change! */
-       err += sn9c102_write_reg(cam, 0x1f, 0x1a);
-       err += sn9c102_write_reg(cam, 0x1a, 0x1b);
-       err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19);
-
-       return err;
-}
-
-
-static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
-                                    const struct v4l2_pix_format* pix)
-{
-       int err = 0;
-
-       if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
-               err += sn9c102_write_reg(cam, 0x63, 0x19);
-       else
-               err += sn9c102_write_reg(cam, 0xf3, 0x19);
-
-       return err;
-}
-
-
-static const struct sn9c102_sensor tas5130d1b = {
-       .name = "TAS5130D1B",
-       .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
-       .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
-       .sysfs_ops = SN9C102_I2C_WRITE,
-       .frequency = SN9C102_I2C_100KHZ,
-       .interface = SN9C102_I2C_3WIRES,
-       .init = &tas5130d1b_init,
-       .qctrl = {
-               {
-                       .id = V4L2_CID_GAIN,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "global gain",
-                       .minimum = 0x00,
-                       .maximum = 0xf6,
-                       .step = 0x02,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-               {
-                       .id = V4L2_CID_EXPOSURE,
-                       .type = V4L2_CTRL_TYPE_INTEGER,
-                       .name = "exposure",
-                       .minimum = 0x00,
-                       .maximum = 0x47,
-                       .step = 0x01,
-                       .default_value = 0x00,
-                       .flags = 0,
-               },
-       },
-       .set_ctrl = &tas5130d1b_set_ctrl,
-       .cropcap = {
-               .bounds = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-               .defrect = {
-                       .left = 0,
-                       .top = 0,
-                       .width = 640,
-                       .height = 480,
-               },
-       },
-       .set_crop = &tas5130d1b_set_crop,
-       .pix_format = {
-               .width = 640,
-               .height = 480,
-               .pixelformat = V4L2_PIX_FMT_SBGGR8,
-               .priv = 8,
-       },
-       .set_pix_format = &tas5130d1b_set_pix_format
-};
-
-
-int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam)
-{
-       const struct usb_device_id tas5130d1b_id_table[] = {
-               { USB_DEVICE(0x0c45, 0x6024), },
-               { USB_DEVICE(0x0c45, 0x6025), },
-               { USB_DEVICE(0x0c45, 0x60aa), },
-               { }
-       };
-
-       /* Sensor detection is based on USB pid/vid */
-       if (!sn9c102_match_id(cam, tas5130d1b_id_table))
-               return -ENODEV;
-
-       sn9c102_attach_sensor(cam, &tas5130d1b);
-
-       return 0;
-}
diff --git a/drivers/media/video/stk1160/Kconfig b/drivers/media/video/stk1160/Kconfig
deleted file mode 100644 (file)
index 1c3a1ec..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-config VIDEO_STK1160
-       tristate "STK1160 USB video capture support"
-       depends on VIDEO_DEV && I2C
-       select VIDEOBUF2_VMALLOC
-       select VIDEO_SAA711X
-
-       ---help---
-         This is a video4linux driver for STK1160 based video capture devices.
-
-         To compile this driver as a module, choose M here: the
-         module will be called stk1160
-
-config VIDEO_STK1160_AC97
-       bool "STK1160 AC97 codec support"
-       depends on VIDEO_STK1160 && SND
-       select SND_AC97_CODEC
-
-       ---help---
-         Enables AC97 codec support for stk1160 driver.
-.
diff --git a/drivers/media/video/stk1160/Makefile b/drivers/media/video/stk1160/Makefile
deleted file mode 100644 (file)
index 8a3c784..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-obj-stk1160-ac97-$(CONFIG_VIDEO_STK1160_AC97) := stk1160-ac97.o
-
-stk1160-y :=   stk1160-core.o \
-               stk1160-v4l.o \
-               stk1160-video.o \
-               stk1160-i2c.o \
-               $(obj-stk1160-ac97-y)
-
-obj-$(CONFIG_VIDEO_STK1160) += stk1160.o
-
-ccflags-y += -Idrivers/media/video
diff --git a/drivers/media/video/stk1160/stk1160-ac97.c b/drivers/media/video/stk1160/stk1160-ac97.c
deleted file mode 100644 (file)
index 8d325f5..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * STK1160 driver
- *
- * Copyright (C) 2012 Ezequiel Garcia
- * <elezegarcia--a.t--gmail.com>
- *
- * Based on Easycap driver by R.M. Thomas
- *     Copyright (C) 2010 R.M. Thomas
- *     <rmthomas--a.t--sciolus.org>
- *
- * 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.
- *
- */
-
-#include <linux/module.h>
-#include <sound/core.h>
-#include <sound/initval.h>
-#include <sound/ac97_codec.h>
-
-#include "stk1160.h"
-#include "stk1160-reg.h"
-
-static struct snd_ac97 *stk1160_ac97;
-
-static void stk1160_write_ac97(struct snd_ac97 *ac97, u16 reg, u16 value)
-{
-       struct stk1160 *dev = ac97->private_data;
-
-       /* Set codec register address */
-       stk1160_write_reg(dev, STK1160_AC97_ADDR, reg);
-
-       /* Set codec command */
-       stk1160_write_reg(dev, STK1160_AC97_CMD, value & 0xff);
-       stk1160_write_reg(dev, STK1160_AC97_CMD + 1, (value & 0xff00) >> 8);
-
-       /*
-        * Set command write bit to initiate write operation.
-        * The bit will be cleared when transfer is done.
-        */
-       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8c);
-}
-
-static u16 stk1160_read_ac97(struct snd_ac97 *ac97, u16 reg)
-{
-       struct stk1160 *dev = ac97->private_data;
-       u8 vall = 0;
-       u8 valh = 0;
-
-       /* Set codec register address */
-       stk1160_write_reg(dev, STK1160_AC97_ADDR, reg);
-
-       /*
-        * Set command read bit to initiate read operation.
-        * The bit will be cleared when transfer is done.
-        */
-       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8b);
-
-       /* Retrieve register value */
-       stk1160_read_reg(dev, STK1160_AC97_CMD, &vall);
-       stk1160_read_reg(dev, STK1160_AC97_CMD + 1, &valh);
-
-       return (valh << 8) | vall;
-}
-
-static void stk1160_reset_ac97(struct snd_ac97 *ac97)
-{
-       struct stk1160 *dev = ac97->private_data;
-       /* Two-step reset AC97 interface and hardware codec */
-       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x94);
-       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x88);
-
-       /* Set 16-bit audio data and choose L&R channel*/
-       stk1160_write_reg(dev, STK1160_AC97CTL_1 + 2, 0x01);
-}
-
-static struct snd_ac97_bus_ops stk1160_ac97_ops = {
-       .read   = stk1160_read_ac97,
-       .write  = stk1160_write_ac97,
-       .reset  = stk1160_reset_ac97,
-};
-
-int stk1160_ac97_register(struct stk1160 *dev)
-{
-       struct snd_card *card = NULL;
-       struct snd_ac97_bus *ac97_bus;
-       struct snd_ac97_template ac97_template;
-       int rc;
-
-       /*
-        * Just want a card to access ac96 controls,
-        * the actual capture interface will be handled by snd-usb-audio
-        */
-       rc = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
-                             THIS_MODULE, 0, &card);
-       if (rc < 0)
-               return rc;
-
-       snd_card_set_dev(card, dev->dev);
-
-       /* TODO: I'm not sure where should I get these names :-( */
-       snprintf(card->shortname, sizeof(card->shortname),
-                "stk1160-mixer");
-       snprintf(card->longname, sizeof(card->longname),
-                "stk1160 ac97 codec mixer control");
-       strncpy(card->driver, dev->dev->driver->name, sizeof(card->driver));
-
-       rc = snd_ac97_bus(card, 0, &stk1160_ac97_ops, NULL, &ac97_bus);
-       if (rc)
-               goto err;
-
-       /* We must set private_data before calling snd_ac97_mixer */
-       memset(&ac97_template, 0, sizeof(ac97_template));
-       ac97_template.private_data = dev;
-       ac97_template.scaps = AC97_SCAP_SKIP_MODEM;
-       rc = snd_ac97_mixer(ac97_bus, &ac97_template, &stk1160_ac97);
-       if (rc)
-               goto err;
-
-       dev->snd_card = card;
-       rc = snd_card_register(card);
-       if (rc)
-               goto err;
-
-       return 0;
-
-err:
-       dev->snd_card = NULL;
-       if (card)
-               snd_card_free(card);
-       return rc;
-}
-
-int stk1160_ac97_unregister(struct stk1160 *dev)
-{
-       struct snd_card *card = dev->snd_card;
-
-       /*
-        * We need to check usb_device,
-        * because ac97 release attempts to communicate with codec
-        */
-       if (card && dev->udev)
-               snd_card_free(card);
-
-       return 0;
-}
diff --git a/drivers/media/video/stk1160/stk1160-core.c b/drivers/media/video/stk1160/stk1160-core.c
deleted file mode 100644 (file)
index 74236fd..0000000
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * STK1160 driver
- *
- * Copyright (C) 2012 Ezequiel Garcia
- * <elezegarcia--a.t--gmail.com>
- *
- * Based on Easycap driver by R.M. Thomas
- *     Copyright (C) 2010 R.M. Thomas
- *     <rmthomas--a.t--sciolus.org>
- *
- * 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.
- *
- * TODO:
- *
- * 1. (Try to) detect if we must register ac97 mixer
- * 2. Support stream at lower speed: lower frame rate or lower frame size.
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-#include <linux/usb.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <media/saa7115.h>
-
-#include "stk1160.h"
-#include "stk1160-reg.h"
-
-static unsigned int input;
-module_param(input, int, 0644);
-MODULE_PARM_DESC(input, "Set default input");
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Ezequiel Garcia");
-MODULE_DESCRIPTION("STK1160 driver");
-
-/* Devices supported by this driver */
-static struct usb_device_id stk1160_id_table[] = {
-       { USB_DEVICE(0x05e1, 0x0408) },
-       { }
-};
-MODULE_DEVICE_TABLE(usb, stk1160_id_table);
-
-/* saa7113 I2C address */
-static unsigned short saa7113_addrs[] = {
-       0x4a >> 1,
-       I2C_CLIENT_END
-};
-
-/*
- * Read/Write stk registers
- */
-int stk1160_read_reg(struct stk1160 *dev, u16 reg, u8 *value)
-{
-       int ret;
-       int pipe = usb_rcvctrlpipe(dev->udev, 0);
-
-       *value = 0;
-       ret = usb_control_msg(dev->udev, pipe, 0x00,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       0x00, reg, value, sizeof(u8), HZ);
-       if (ret < 0) {
-               stk1160_err("read failed on reg 0x%x (%d)\n",
-                       reg, ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value)
-{
-       int ret;
-       int pipe = usb_sndctrlpipe(dev->udev, 0);
-
-       ret =  usb_control_msg(dev->udev, pipe, 0x01,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, reg, NULL, 0, HZ);
-       if (ret < 0) {
-               stk1160_err("write failed on reg 0x%x (%d)\n",
-                       reg, ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-void stk1160_select_input(struct stk1160 *dev)
-{
-       static const u8 gctrl[] = {
-               0x98, 0x90, 0x88, 0x80
-       };
-
-       if (dev->ctl_input < ARRAY_SIZE(gctrl))
-               stk1160_write_reg(dev, STK1160_GCTRL, gctrl[dev->ctl_input]);
-}
-
-/* TODO: We should break this into pieces */
-static void stk1160_reg_reset(struct stk1160 *dev)
-{
-       int i;
-
-       static const struct regval ctl[] = {
-               {STK1160_GCTRL+2, 0x0078},
-
-               {STK1160_RMCTL+1, 0x0000},
-               {STK1160_RMCTL+3, 0x0002},
-
-               {STK1160_PLLSO,   0x0010},
-               {STK1160_PLLSO+1, 0x0000},
-               {STK1160_PLLSO+2, 0x0014},
-               {STK1160_PLLSO+3, 0x000E},
-
-               {STK1160_PLLFD,   0x0046},
-
-               /* Timing generator setup */
-               {STK1160_TIGEN,   0x0012},
-               {STK1160_TICTL,   0x002D},
-               {STK1160_TICTL+1, 0x0001},
-               {STK1160_TICTL+2, 0x0000},
-               {STK1160_TICTL+3, 0x0000},
-               {STK1160_TIGEN,   0x0080},
-
-               {0xffff, 0xffff}
-       };
-
-       for (i = 0; ctl[i].reg != 0xffff; i++)
-               stk1160_write_reg(dev, ctl[i].reg, ctl[i].val);
-}
-
-static void stk1160_release(struct v4l2_device *v4l2_dev)
-{
-       struct stk1160 *dev = container_of(v4l2_dev, struct stk1160, v4l2_dev);
-
-       stk1160_info("releasing all resources\n");
-
-       stk1160_i2c_unregister(dev);
-
-       v4l2_ctrl_handler_free(&dev->ctrl_handler);
-       v4l2_device_unregister(&dev->v4l2_dev);
-       kfree(dev->alt_max_pkt_size);
-       kfree(dev);
-}
-
-/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
-#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
-
-/*
- * Scan usb interface and populate max_pkt_size array
- * with information on each alternate setting.
- * The array should be allocated by the caller.
- */
-static int stk1160_scan_usb(struct usb_interface *intf, struct usb_device *udev,
-               unsigned int *max_pkt_size)
-{
-       int i, e, sizedescr, size, ifnum;
-       const struct usb_endpoint_descriptor *desc;
-
-       bool has_video = false, has_audio = false;
-       const char *speed;
-
-       ifnum = intf->altsetting[0].desc.bInterfaceNumber;
-
-       /* Get endpoints */
-       for (i = 0; i < intf->num_altsetting; i++) {
-
-               for (e = 0; e < intf->altsetting[i].desc.bNumEndpoints; e++) {
-
-                       /* This isn't clear enough, at least to me */
-                       desc = &intf->altsetting[i].endpoint[e].desc;
-                       sizedescr = le16_to_cpu(desc->wMaxPacketSize);
-                       size = sizedescr & 0x7ff;
-
-                       if (udev->speed == USB_SPEED_HIGH)
-                               size = size * hb_mult(sizedescr);
-
-                       if (usb_endpoint_xfer_isoc(desc) &&
-                           usb_endpoint_dir_in(desc)) {
-                               switch (desc->bEndpointAddress) {
-                               case STK1160_EP_AUDIO:
-                                       has_audio = true;
-                                       break;
-                               case STK1160_EP_VIDEO:
-                                       has_video = true;
-                                       max_pkt_size[i] = size;
-                                       break;
-                               }
-                       }
-               }
-       }
-
-       /* Is this even possible? */
-       if (!(has_audio || has_video)) {
-               dev_err(&udev->dev, "no audio or video endpoints found\n");
-               return -ENODEV;
-       }
-
-       switch (udev->speed) {
-       case USB_SPEED_LOW:
-               speed = "1.5";
-               break;
-       case USB_SPEED_FULL:
-               speed = "12";
-               break;
-       case USB_SPEED_HIGH:
-               speed = "480";
-               break;
-       default:
-               speed = "unknown";
-       }
-
-       dev_info(&udev->dev, "New device %s %s @ %s Mbps (%04x:%04x, interface %d, class %d)\n",
-               udev->manufacturer ? udev->manufacturer : "",
-               udev->product ? udev->product : "",
-               speed,
-               le16_to_cpu(udev->descriptor.idVendor),
-               le16_to_cpu(udev->descriptor.idProduct),
-               ifnum,
-               intf->altsetting->desc.bInterfaceNumber);
-
-       /* This should never happen, since we rejected audio interfaces */
-       if (has_audio)
-               dev_warn(&udev->dev, "audio interface %d found.\n\
-                               This is not implemented by this driver,\
-                               you should use snd-usb-audio instead\n", ifnum);
-
-       if (has_video)
-               dev_info(&udev->dev, "video interface %d found\n",
-                               ifnum);
-
-       /*
-        * Make sure we have 480 Mbps of bandwidth, otherwise things like
-        * video stream wouldn't likely work, since 12 Mbps is generally
-        * not enough even for most streams.
-        */
-       if (udev->speed != USB_SPEED_HIGH)
-               dev_warn(&udev->dev, "must be connected to a high-speed USB 2.0 port\n\
-                               You may not be able to stream video smoothly\n");
-
-       return 0;
-}
-
-static int stk1160_probe(struct usb_interface *interface,
-               const struct usb_device_id *id)
-{
-       int ifnum;
-       int rc = 0;
-
-       unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
-       struct usb_device *udev;
-       struct stk1160 *dev;
-
-       ifnum = interface->altsetting[0].desc.bInterfaceNumber;
-       udev = interface_to_usbdev(interface);
-
-       /*
-        * Since usb audio class is supported by snd-usb-audio,
-        * we reject audio interface.
-        */
-       if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO)
-               return -ENODEV;
-
-       /* Alloc an array for all possible max_pkt_size */
-       alt_max_pkt_size = kmalloc(sizeof(alt_max_pkt_size[0]) *
-                       interface->num_altsetting, GFP_KERNEL);
-       if (alt_max_pkt_size == NULL)
-               return -ENOMEM;
-
-       /*
-        * Scan usb posibilities and populate alt_max_pkt_size array.
-        * Also, check if device speed is fast enough.
-        */
-       rc = stk1160_scan_usb(interface, udev, alt_max_pkt_size);
-       if (rc < 0) {
-               kfree(alt_max_pkt_size);
-               return rc;
-       }
-
-       dev = kzalloc(sizeof(struct stk1160), GFP_KERNEL);
-       if (dev == NULL) {
-               kfree(alt_max_pkt_size);
-               return -ENOMEM;
-       }
-
-       dev->alt_max_pkt_size = alt_max_pkt_size;
-       dev->udev = udev;
-       dev->num_alt = interface->num_altsetting;
-       dev->ctl_input = input;
-
-       /* We save struct device for debug purposes only */
-       dev->dev = &interface->dev;
-
-       usb_set_intfdata(interface, dev);
-
-       /* initialize videobuf2 stuff */
-       rc = stk1160_vb2_setup(dev);
-       if (rc < 0)
-               goto free_err;
-
-       /*
-        * There is no need to take any locks here in probe
-        * because we register the device node as the *last* thing.
-        */
-       spin_lock_init(&dev->buf_lock);
-       mutex_init(&dev->v4l_lock);
-       mutex_init(&dev->vb_queue_lock);
-
-       rc = v4l2_ctrl_handler_init(&dev->ctrl_handler, 0);
-       if (rc) {
-               stk1160_err("v4l2_ctrl_handler_init failed (%d)\n", rc);
-               goto free_err;
-       }
-
-       /*
-        * We obtain a v4l2_dev but defer
-        * registration of video device node as the last thing.
-        * There is no need to set the name if we give a device struct
-        */
-       dev->v4l2_dev.release = stk1160_release;
-       dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler;
-       rc = v4l2_device_register(dev->dev, &dev->v4l2_dev);
-       if (rc) {
-               stk1160_err("v4l2_device_register failed (%d)\n", rc);
-               goto free_ctrl;
-       }
-
-       rc = stk1160_i2c_register(dev);
-       if (rc < 0)
-               goto unreg_v4l2;
-
-       /*
-        * To the best of my knowledge stk1160 boards only have
-        * saa7113, but it doesn't hurt to support them all.
-        */
-       dev->sd_saa7115 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-               "saa7115_auto", 0, saa7113_addrs);
-
-       stk1160_info("driver ver %s successfully loaded\n",
-               STK1160_VERSION);
-
-       /* i2c reset saa711x */
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0);
-       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
-                               0, 0, 0);
-       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
-
-       /* reset stk1160 to default values */
-       stk1160_reg_reset(dev);
-
-       /* select default input */
-       stk1160_select_input(dev);
-
-       stk1160_ac97_register(dev);
-
-       rc = stk1160_video_register(dev);
-       if (rc < 0)
-               goto unreg_i2c;
-
-       return 0;
-
-unreg_i2c:
-       stk1160_i2c_unregister(dev);
-unreg_v4l2:
-       v4l2_device_unregister(&dev->v4l2_dev);
-free_ctrl:
-       v4l2_ctrl_handler_free(&dev->ctrl_handler);
-free_err:
-       kfree(alt_max_pkt_size);
-       kfree(dev);
-
-       return rc;
-}
-
-static void stk1160_disconnect(struct usb_interface *interface)
-{
-       struct stk1160 *dev;
-
-       dev = usb_get_intfdata(interface);
-       usb_set_intfdata(interface, NULL);
-
-       /*
-        * Wait until all current v4l2 operation are finished
-        * then deallocate resources
-        */
-       mutex_lock(&dev->vb_queue_lock);
-       mutex_lock(&dev->v4l_lock);
-
-       /* Here is the only place where isoc get released */
-       stk1160_uninit_isoc(dev);
-
-       /* ac97 unregister needs to be done before usb_device is cleared */
-       stk1160_ac97_unregister(dev);
-
-       stk1160_clear_queue(dev);
-
-       video_unregister_device(&dev->vdev);
-       v4l2_device_disconnect(&dev->v4l2_dev);
-
-       /* This way current users can detect device is gone */
-       dev->udev = NULL;
-
-       mutex_unlock(&dev->v4l_lock);
-       mutex_unlock(&dev->vb_queue_lock);
-
-       /*
-        * This calls stk1160_release if it's the last reference.
-        * therwise, release is posponed until there are no users left.
-        */
-       v4l2_device_put(&dev->v4l2_dev);
-}
-
-static struct usb_driver stk1160_usb_driver = {
-       .name = "stk1160",
-       .id_table = stk1160_id_table,
-       .probe = stk1160_probe,
-       .disconnect = stk1160_disconnect,
-};
-
-module_usb_driver(stk1160_usb_driver);
diff --git a/drivers/media/video/stk1160/stk1160-i2c.c b/drivers/media/video/stk1160/stk1160-i2c.c
deleted file mode 100644 (file)
index 176ac93..0000000
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * STK1160 driver
- *
- * Copyright (C) 2012 Ezequiel Garcia
- * <elezegarcia--a.t--gmail.com>
- *
- * Based on Easycap driver by R.M. Thomas
- *     Copyright (C) 2010 R.M. Thomas
- *     <rmthomas--a.t--sciolus.org>
- *
- * 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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/i2c.h>
-
-#include "stk1160.h"
-#include "stk1160-reg.h"
-
-static unsigned int i2c_debug;
-module_param(i2c_debug, int, 0644);
-MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
-
-#define dprintk_i2c(fmt, args...)                              \
-do {                                                           \
-       if (i2c_debug)                                          \
-               printk(KERN_DEBUG fmt, ##args);                 \
-} while (0)
-
-static int stk1160_i2c_busy_wait(struct stk1160 *dev, u8 wait_bit_mask)
-{
-       unsigned long end;
-       u8 flag;
-
-       /* Wait until read/write finish bit is set */
-       end = jiffies + msecs_to_jiffies(STK1160_I2C_TIMEOUT);
-       while (time_is_after_jiffies(end)) {
-
-               stk1160_read_reg(dev, STK1160_SICTL+1, &flag);
-               /* read/write done? */
-               if (flag & wait_bit_mask)
-                       goto done;
-
-               usleep_range(10 * USEC_PER_MSEC, 20 * USEC_PER_MSEC);
-       }
-
-       return -ETIMEDOUT;
-
-done:
-       return 0;
-}
-
-static int stk1160_i2c_write_reg(struct stk1160 *dev, u8 addr,
-               u8 reg, u8 value)
-{
-       int rc;
-
-       /* Set serial device address */
-       rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
-       if (rc < 0)
-               return rc;
-
-       /* Set i2c device register sub-address */
-       rc = stk1160_write_reg(dev, STK1160_SBUSW_WA, reg);
-       if (rc < 0)
-               return rc;
-
-       /* Set i2c device register value */
-       rc = stk1160_write_reg(dev, STK1160_SBUSW_WD, value);
-       if (rc < 0)
-               return rc;
-
-       /* Start write now */
-       rc = stk1160_write_reg(dev, STK1160_SICTL, 0x01);
-       if (rc < 0)
-               return rc;
-
-       rc = stk1160_i2c_busy_wait(dev, 0x04);
-       if (rc < 0)
-               return rc;
-
-       return 0;
-}
-
-static int stk1160_i2c_read_reg(struct stk1160 *dev, u8 addr,
-               u8 reg, u8 *value)
-{
-       int rc;
-
-       /* Set serial device address */
-       rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
-       if (rc < 0)
-               return rc;
-
-       /* Set i2c device register sub-address */
-       rc = stk1160_write_reg(dev, STK1160_SBUSR_RA, reg);
-       if (rc < 0)
-               return rc;
-
-       /* Start read now */
-       rc = stk1160_write_reg(dev, STK1160_SICTL, 0x20);
-       if (rc < 0)
-               return rc;
-
-       rc = stk1160_i2c_busy_wait(dev, 0x01);
-       if (rc < 0)
-               return rc;
-
-       stk1160_read_reg(dev, STK1160_SBUSR_RD, value);
-       if (rc < 0)
-               return rc;
-
-       return 0;
-}
-
-/*
- * stk1160_i2c_check_for_device()
- * check if there is a i2c_device at the supplied address
- */
-static int stk1160_i2c_check_for_device(struct stk1160 *dev,
-               unsigned char addr)
-{
-       int rc;
-
-       /* Set serial device address */
-       rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
-       if (rc < 0)
-               return rc;
-
-       /* Set device sub-address, we'll chip version reg */
-       rc = stk1160_write_reg(dev, STK1160_SBUSR_RA, 0x00);
-       if (rc < 0)
-               return rc;
-
-       /* Start read now */
-       rc = stk1160_write_reg(dev, STK1160_SICTL, 0x20);
-       if (rc < 0)
-               return rc;
-
-       rc = stk1160_i2c_busy_wait(dev, 0x01);
-       if (rc < 0)
-               return -ENODEV;
-
-       return 0;
-}
-
-/*
- * stk1160_i2c_xfer()
- * the main i2c transfer function
- */
-static int stk1160_i2c_xfer(struct i2c_adapter *i2c_adap,
-                          struct i2c_msg msgs[], int num)
-{
-       struct stk1160 *dev = i2c_adap->algo_data;
-       int addr, rc, i;
-
-       for (i = 0; i < num; i++) {
-               addr = msgs[i].addr << 1;
-               dprintk_i2c("%s: addr=%x", __func__, addr);
-
-               if (!msgs[i].len) {
-                       /* no len: check only for device presence */
-                       rc = stk1160_i2c_check_for_device(dev, addr);
-                       if (rc < 0) {
-                               dprintk_i2c(" no device\n");
-                               return rc;
-                       }
-
-               } else if (msgs[i].flags & I2C_M_RD) {
-                       /* read request without preceding register selection */
-                       dprintk_i2c(" subaddr not selected");
-                       rc = -EOPNOTSUPP;
-                       goto err;
-
-               } else if (i + 1 < num && msgs[i].len <= 2 &&
-                          (msgs[i + 1].flags & I2C_M_RD) &&
-                          msgs[i].addr == msgs[i + 1].addr) {
-
-                       if (msgs[i].len != 1 || msgs[i + 1].len != 1) {
-                               dprintk_i2c(" len not supported");
-                               rc = -EOPNOTSUPP;
-                               goto err;
-                       }
-
-                       dprintk_i2c(" subaddr=%x", msgs[i].buf[0]);
-
-                       rc = stk1160_i2c_read_reg(dev, addr, msgs[i].buf[0],
-                               msgs[i + 1].buf);
-
-                       dprintk_i2c(" read=%x", *msgs[i + 1].buf);
-
-                       /* consumed two msgs, so we skip one of them */
-                       i++;
-
-               } else {
-                       if (msgs[i].len != 2) {
-                               dprintk_i2c(" len not supported");
-                               rc = -EOPNOTSUPP;
-                               goto err;
-                       }
-
-                       dprintk_i2c(" subaddr=%x write=%x",
-                               msgs[i].buf[0],  msgs[i].buf[1]);
-
-                       rc = stk1160_i2c_write_reg(dev, addr, msgs[i].buf[0],
-                               msgs[i].buf[1]);
-               }
-
-               if (rc < 0)
-                       goto err;
-               dprintk_i2c(" OK\n");
-       }
-
-       return num;
-err:
-       dprintk_i2c(" ERROR: %d\n", rc);
-       return num;
-}
-
-/*
- * functionality(), what da heck is this?
- */
-static u32 functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_SMBUS_EMUL;
-}
-
-static struct i2c_algorithm algo = {
-       .master_xfer   = stk1160_i2c_xfer,
-       .functionality = functionality,
-};
-
-static struct i2c_adapter adap_template = {
-       .owner = THIS_MODULE,
-       .name = "stk1160",
-       .algo = &algo,
-};
-
-static struct i2c_client client_template = {
-       .name = "stk1160 internal",
-};
-
-/*
- * stk1160_i2c_register()
- * register i2c bus
- */
-int stk1160_i2c_register(struct stk1160 *dev)
-{
-       int rc;
-
-       dev->i2c_adap = adap_template;
-       dev->i2c_adap.dev.parent = dev->dev;
-       strcpy(dev->i2c_adap.name, "stk1160");
-       dev->i2c_adap.algo_data = dev;
-
-       i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
-
-       rc = i2c_add_adapter(&dev->i2c_adap);
-       if (rc < 0) {
-               stk1160_err("cannot add i2c adapter (%d)\n", rc);
-               return rc;
-       }
-
-       dev->i2c_client = client_template;
-       dev->i2c_client.adapter = &dev->i2c_adap;
-
-       /* Set i2c clock divider device address */
-       stk1160_write_reg(dev, STK1160_SICTL_CD,  0x0f);
-
-       /* ??? */
-       stk1160_write_reg(dev, STK1160_ASIC + 3,  0x00);
-
-       return 0;
-}
-
-/*
- * stk1160_i2c_unregister()
- * unregister i2c_bus
- */
-int stk1160_i2c_unregister(struct stk1160 *dev)
-{
-       i2c_del_adapter(&dev->i2c_adap);
-       return 0;
-}
diff --git a/drivers/media/video/stk1160/stk1160-reg.h b/drivers/media/video/stk1160/stk1160-reg.h
deleted file mode 100644 (file)
index 3e49da6..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * STK1160 driver
- *
- * Copyright (C) 2012 Ezequiel Garcia
- * <elezegarcia--a.t--gmail.com>
- *
- * Based on Easycap driver by R.M. Thomas
- *     Copyright (C) 2010 R.M. Thomas
- *     <rmthomas--a.t--sciolus.org>
- *
- * 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.
- *
- */
-
-/* GPIO Control */
-#define STK1160_GCTRL                  0x000
-
-/* Remote Wakup Control */
-#define STK1160_RMCTL                  0x00c
-
-/*
- * Decoder Control Register:
- * This byte controls capture start/stop
- * with bit #7 (0x?? OR 0x80 to activate).
- */
-#define STK1160_DCTRL                  0x100
-
-/* Capture Frame Start Position */
-#define STK116_CFSPO                   0x110
-#define STK116_CFSPO_STX_L             0x110
-#define STK116_CFSPO_STX_H             0x111
-#define STK116_CFSPO_STY_L             0x112
-#define STK116_CFSPO_STY_H             0x113
-
-/* Capture Frame End Position */
-#define STK116_CFEPO                   0x114
-#define STK116_CFEPO_ENX_L             0x114
-#define STK116_CFEPO_ENX_H             0x115
-#define STK116_CFEPO_ENY_L             0x116
-#define STK116_CFEPO_ENY_H             0x117
-
-/* Serial Interface Control  */
-#define STK1160_SICTL                  0x200
-#define STK1160_SICTL_CD               0x202
-#define STK1160_SICTL_SDA              0x203
-
-/* Serial Bus Write */
-#define STK1160_SBUSW                  0x204
-#define STK1160_SBUSW_WA               0x204
-#define STK1160_SBUSW_WD               0x205
-
-/* Serial Bus Read */
-#define STK1160_SBUSR                  0x208
-#define STK1160_SBUSR_RA               0x208
-#define STK1160_SBUSR_RD               0x209
-
-/* Alternate Serial Inteface Control */
-#define STK1160_ASIC                   0x2fc
-
-/* PLL Select Options */
-#define STK1160_PLLSO                  0x018
-
-/* PLL Frequency Divider */
-#define STK1160_PLLFD                  0x01c
-
-/* Timing Generator */
-#define STK1160_TIGEN                  0x300
-
-/* Timing Control Parameter */
-#define STK1160_TICTL                  0x350
-
-/* AC97 Audio Control */
-#define STK1160_AC97CTL_0              0x500
-#define STK1160_AC97CTL_1              0x504
-
-/* Use [0:6] bits of register 0x504 to set codec command address */
-#define STK1160_AC97_ADDR              0x504
-/* Use [16:31] bits of register 0x500 to set codec command data */
-#define STK1160_AC97_CMD               0x502
-
-/* Audio I2S Interface */
-#define STK1160_I2SCTL                 0x50c
-
-/* EEPROM Interface */
-#define STK1160_EEPROM_SZ              0x5f0
diff --git a/drivers/media/video/stk1160/stk1160-v4l.c b/drivers/media/video/stk1160/stk1160-v4l.c
deleted file mode 100644 (file)
index 360bdbe..0000000
+++ /dev/null
@@ -1,738 +0,0 @@
-/*
- * STK1160 driver
- *
- * Copyright (C) 2012 Ezequiel Garcia
- * <elezegarcia--a.t--gmail.com>
- *
- * Based on Easycap driver by R.M. Thomas
- *     Copyright (C) 2010 R.M. Thomas
- *     <rmthomas--a.t--sciolus.org>
- *
- * 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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-
-#include <linux/videodev2.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-chip-ident.h>
-#include <media/videobuf2-vmalloc.h>
-
-#include <media/saa7115.h>
-
-#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");
-
-/* supported video standards */
-static struct stk1160_fmt format[] = {
-       {
-               .name     = "16 bpp YUY2, 4:2:2, packed",
-               .fourcc   = V4L2_PIX_FMT_UYVY,
-               .depth    = 16,
-       }
-};
-
-static void stk1160_set_std(struct stk1160 *dev)
-{
-       int i;
-
-       static struct regval std525[] = {
-
-               /* 720x480 */
-
-               /* Frame start */
-               {STK116_CFSPO_STX_L, 0x0000},
-               {STK116_CFSPO_STX_H, 0x0000},
-               {STK116_CFSPO_STY_L, 0x0003},
-               {STK116_CFSPO_STY_H, 0x0000},
-
-               /* Frame end */
-               {STK116_CFEPO_ENX_L, 0x05a0},
-               {STK116_CFEPO_ENX_H, 0x0005},
-               {STK116_CFEPO_ENY_L, 0x00f3},
-               {STK116_CFEPO_ENY_H, 0x0000},
-
-               {0xffff, 0xffff}
-       };
-
-       static struct regval std625[] = {
-
-               /* 720x576 */
-
-               /* TODO: Each line of frame has some junk at the end */
-               /* Frame start */
-               {STK116_CFSPO,   0x0000},
-               {STK116_CFSPO+1, 0x0000},
-               {STK116_CFSPO+2, 0x0001},
-               {STK116_CFSPO+3, 0x0000},
-
-               /* Frame end */
-               {STK116_CFEPO,   0x05a0},
-               {STK116_CFEPO+1, 0x0005},
-               {STK116_CFEPO+2, 0x0121},
-               {STK116_CFEPO+3, 0x0001},
-
-               {0xffff, 0xffff}
-       };
-
-       if (dev->norm & V4L2_STD_525_60) {
-               stk1160_dbg("registers to NTSC like standard\n");
-               for (i = 0; std525[i].reg != 0xffff; i++)
-                       stk1160_write_reg(dev, std525[i].reg, std525[i].val);
-       } else {
-               stk1160_dbg("registers to PAL like standard\n");
-               for (i = 0; std625[i].reg != 0xffff; i++)
-                       stk1160_write_reg(dev, std625[i].reg, std625[i].val);
-       }
-
-}
-
-/*
- * Set a new alternate setting.
- * Returns true is dev->max_pkt_size has changed, false otherwise.
- */
-static bool stk1160_set_alternate(struct stk1160 *dev)
-{
-       int i, prev_alt = dev->alt;
-       unsigned int min_pkt_size;
-       bool new_pkt_size;
-
-       /*
-        * If we don't set right alternate,
-        * then we will get a green screen with junk.
-        */
-       min_pkt_size = STK1160_MIN_PKT_SIZE;
-
-       for (i = 0; i < dev->num_alt; i++) {
-               /* stop when the selected alt setting offers enough bandwidth */
-               if (dev->alt_max_pkt_size[i] >= min_pkt_size) {
-                       dev->alt = i;
-                       break;
-               /*
-                * otherwise make sure that we end up with the maximum bandwidth
-                * because the min_pkt_size equation might be wrong...
-                */
-               } else if (dev->alt_max_pkt_size[i] >
-                          dev->alt_max_pkt_size[dev->alt])
-                       dev->alt = i;
-       }
-
-       stk1160_info("setting alternate %d\n", dev->alt);
-
-       if (dev->alt != prev_alt) {
-               stk1160_dbg("minimum isoc packet size: %u (alt=%d)\n",
-                               min_pkt_size, dev->alt);
-               stk1160_dbg("setting alt %d with wMaxPacketSize=%u\n",
-                              dev->alt, dev->alt_max_pkt_size[dev->alt]);
-               usb_set_interface(dev->udev, 0, dev->alt);
-       }
-
-       new_pkt_size = dev->max_pkt_size != dev->alt_max_pkt_size[dev->alt];
-       dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
-
-       return new_pkt_size;
-}
-
-static int stk1160_start_streaming(struct stk1160 *dev)
-{
-       int i, rc;
-       bool new_pkt_size;
-
-       /* Check device presence */
-       if (!dev->udev)
-               return -ENODEV;
-
-       if (mutex_lock_interruptible(&dev->v4l_lock))
-               return -ERESTARTSYS;
-       /*
-        * For some reason it is mandatory to set alternate *first*
-        * and only *then* initialize isoc urbs.
-        * Someone please explain me why ;)
-        */
-       new_pkt_size = stk1160_set_alternate(dev);
-
-       /*
-        * We (re)allocate isoc urbs if:
-        * there is no allocated isoc urbs, OR
-        * a new dev->max_pkt_size is detected
-        */
-       if (!dev->isoc_ctl.num_bufs || new_pkt_size) {
-               rc = stk1160_alloc_isoc(dev);
-               if (rc < 0)
-                       return rc;
-       }
-
-       /* 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_KERNEL);
-               if (rc) {
-                       stk1160_err("cannot submit urb[%d] (%d)\n", i, rc);
-                       stk1160_uninit_isoc(dev);
-                       return rc;
-               }
-       }
-
-       /* Start saa711x */
-       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
-
-       /* Start stk1160 */
-       stk1160_write_reg(dev, STK1160_DCTRL, 0xb3);
-       stk1160_write_reg(dev, STK1160_DCTRL+3, 0x00);
-
-       stk1160_dbg("streaming started\n");
-
-       mutex_unlock(&dev->v4l_lock);
-
-       return 0;
-}
-
-/* Must be called with v4l_lock hold */
-static void stk1160_stop_hw(struct stk1160 *dev)
-{
-       /* If the device is not physically present, there is nothing to do */
-       if (!dev->udev)
-               return;
-
-       /* set alternate 0 */
-       dev->alt = 0;
-       stk1160_info("setting alternate %d\n", dev->alt);
-       usb_set_interface(dev->udev, 0, 0);
-
-       /* Stop stk1160 */
-       stk1160_write_reg(dev, STK1160_DCTRL, 0x00);
-       stk1160_write_reg(dev, STK1160_DCTRL+3, 0x00);
-
-       /* Stop saa711x */
-       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
-}
-
-static int stk1160_stop_streaming(struct stk1160 *dev)
-{
-       if (mutex_lock_interruptible(&dev->v4l_lock))
-               return -ERESTARTSYS;
-
-       stk1160_cancel_isoc(dev);
-
-       /*
-        * It is possible to keep buffers around using a module parameter.
-        * This is intended to avoid memory fragmentation.
-        */
-       if (!keep_buffers)
-               stk1160_free_isoc(dev);
-
-       stk1160_stop_hw(dev);
-
-       stk1160_clear_queue(dev);
-
-       stk1160_dbg("streaming stopped\n");
-
-       mutex_unlock(&dev->v4l_lock);
-
-       return 0;
-}
-
-static struct v4l2_file_operations stk1160_fops = {
-       .owner = THIS_MODULE,
-       .open = v4l2_fh_open,
-       .release = vb2_fop_release,
-       .read = vb2_fop_read,
-       .poll = vb2_fop_poll,
-       .mmap = vb2_fop_mmap,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-/*
- * vidioc ioctls
- */
-static int vidioc_querycap(struct file *file,
-               void *priv, struct v4l2_capability *cap)
-{
-       struct stk1160 *dev = video_drvdata(file);
-
-       strcpy(cap->driver, "stk1160");
-       strcpy(cap->card, "stk1160");
-       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
-       cap->device_caps =
-               V4L2_CAP_VIDEO_CAPTURE |
-               V4L2_CAP_STREAMING |
-               V4L2_CAP_READWRITE;
-       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-               struct v4l2_fmtdesc *f)
-{
-       if (f->index != 0)
-               return -EINVAL;
-
-       strlcpy(f->description, format[f->index].name, sizeof(f->description));
-       f->pixelformat = format[f->index].fourcc;
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct stk1160 *dev = video_drvdata(file);
-
-       f->fmt.pix.width = dev->width;
-       f->fmt.pix.height = dev->height;
-       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       f->fmt.pix.pixelformat = dev->fmt->fourcc;
-       f->fmt.pix.bytesperline = dev->width * 2;
-       f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-
-       return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                       struct v4l2_format *f)
-{
-       struct stk1160 *dev = video_drvdata(file);
-
-       if (f->fmt.pix.pixelformat != format[0].fourcc) {
-               stk1160_err("fourcc format 0x%08x invalid\n",
-                       f->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       /*
-        * User can't choose size at his own will,
-        * so we just return him the current size chosen
-        * at standard selection.
-        * TODO: Implement frame scaling?
-        */
-
-       f->fmt.pix.width = dev->width;
-       f->fmt.pix.height = dev->height;
-       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
-       f->fmt.pix.bytesperline = dev->width * 2;
-       f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline;
-       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct stk1160 *dev = video_drvdata(file);
-       struct vb2_queue *q = &dev->vb_vidq;
-       int rc;
-
-       if (vb2_is_busy(q))
-               return -EBUSY;
-
-       rc = vidioc_try_fmt_vid_cap(file, priv, f);
-       if (rc < 0)
-               return rc;
-
-       /* We don't support any format changes */
-
-       return 0;
-}
-
-static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
-{
-       struct stk1160 *dev = video_drvdata(file);
-       v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm);
-       return 0;
-}
-
-static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
-{
-       struct stk1160 *dev = video_drvdata(file);
-
-       *norm = dev->norm;
-       return 0;
-}
-
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
-{
-       struct stk1160 *dev = video_drvdata(file);
-       struct vb2_queue *q = &dev->vb_vidq;
-
-       if (vb2_is_busy(q))
-               return -EBUSY;
-
-       /* Check device presence */
-       if (!dev->udev)
-               return -ENODEV;
-
-       /* We need to set this now, before we call stk1160_set_std */
-       dev->norm = *norm;
-
-       /* This is taken from saa7115 video decoder */
-       if (dev->norm & V4L2_STD_525_60) {
-               dev->width = 720;
-               dev->height = 480;
-       } else if (dev->norm & V4L2_STD_625_50) {
-               dev->width = 720;
-               dev->height = 576;
-       } else {
-               stk1160_err("invalid standard\n");
-               return -EINVAL;
-       }
-
-       stk1160_set_std(dev);
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std,
-                       dev->norm);
-
-       return 0;
-}
-
-
-static int vidioc_enum_input(struct file *file, void *priv,
-                               struct v4l2_input *i)
-{
-       struct stk1160 *dev = video_drvdata(file);
-
-       if (i->index > STK1160_MAX_INPUT)
-               return -EINVAL;
-
-       sprintf(i->name, "Composite%d", i->index);
-       i->type = V4L2_INPUT_TYPE_CAMERA;
-       i->std = dev->vdev.tvnorms;
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       struct stk1160 *dev = video_drvdata(file);
-       *i = dev->ctl_input;
-       return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       struct stk1160 *dev = video_drvdata(file);
-
-       if (vb2_is_busy(&dev->vb_vidq))
-               return -EBUSY;
-
-       if (i > STK1160_MAX_INPUT)
-               return -EINVAL;
-
-       dev->ctl_input = i;
-
-       stk1160_select_input(dev);
-
-       return 0;
-}
-
-static int vidioc_g_chip_ident(struct file *file, void *priv,
-              struct v4l2_dbg_chip_ident *chip)
-{
-       switch (chip->match.type) {
-       case V4L2_CHIP_MATCH_HOST:
-               chip->ident = V4L2_IDENT_NONE;
-               chip->revision = 0;
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int vidioc_g_register(struct file *file, void *priv,
-                            struct v4l2_dbg_register *reg)
-{
-       struct stk1160 *dev = video_drvdata(file);
-       int rc;
-       u8 val;
-
-       switch (reg->match.type) {
-       case V4L2_CHIP_MATCH_AC97:
-               /* TODO: Support me please :-( */
-               return -EINVAL;
-       case V4L2_CHIP_MATCH_I2C_DRIVER:
-               v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
-               return 0;
-       case V4L2_CHIP_MATCH_I2C_ADDR:
-               /* TODO: is this correct? */
-               v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
-               return 0;
-       default:
-               if (!v4l2_chip_match_host(&reg->match))
-                       return -EINVAL;
-       }
-
-       /* Match host */
-       rc = stk1160_read_reg(dev, reg->reg, &val);
-       reg->val = val;
-       reg->size = 1;
-
-       return rc;
-}
-
-static int vidioc_s_register(struct file *file, void *priv,
-                            struct v4l2_dbg_register *reg)
-{
-       struct stk1160 *dev = video_drvdata(file);
-
-       switch (reg->match.type) {
-       case V4L2_CHIP_MATCH_AC97:
-               return -EINVAL;
-       case V4L2_CHIP_MATCH_I2C_DRIVER:
-               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
-               return 0;
-       case V4L2_CHIP_MATCH_I2C_ADDR:
-               /* TODO: is this correct? */
-               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
-               return 0;
-       default:
-               if (!v4l2_chip_match_host(&reg->match))
-                       return -EINVAL;
-       }
-
-       /* Match host */
-       return stk1160_write_reg(dev, reg->reg, cpu_to_le16(reg->val));
-}
-#endif
-
-static const struct v4l2_ioctl_ops stk1160_ioctl_ops = {
-       .vidioc_querycap      = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
-       .vidioc_querystd      = vidioc_querystd,
-       .vidioc_g_std         = vidioc_g_std,
-       .vidioc_s_std         = vidioc_s_std,
-       .vidioc_enum_input    = vidioc_enum_input,
-       .vidioc_g_input       = vidioc_g_input,
-       .vidioc_s_input       = vidioc_s_input,
-
-       /* vb2 takes care of these */
-       .vidioc_reqbufs       = vb2_ioctl_reqbufs,
-       .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,
-       .vidioc_g_chip_ident = vidioc_g_chip_ident,
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register = vidioc_g_register,
-       .vidioc_s_register = vidioc_s_register,
-#endif
-};
-
-/********************************************************************/
-
-/*
- * Videobuf2 operations
- */
-static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *v4l_fmt,
-                               unsigned int *nbuffers, unsigned int *nplanes,
-                               unsigned int sizes[], void *alloc_ctxs[])
-{
-       struct stk1160 *dev = vb2_get_drv_priv(vq);
-       unsigned long size;
-
-       size = dev->width * dev->height * 2;
-
-       /*
-        * Here we can change the number of buffers being requested.
-        * So, we set a minimum and a maximum like this:
-        */
-       *nbuffers = clamp_t(unsigned int, *nbuffers,
-                       STK1160_MIN_VIDEO_BUFFERS, STK1160_MAX_VIDEO_BUFFERS);
-
-       /* This means a packed colorformat */
-       *nplanes = 1;
-
-       sizes[0] = size;
-
-       stk1160_info("%s: buffer count %d, each %ld bytes\n",
-                       __func__, *nbuffers, size);
-
-       return 0;
-}
-
-static void buffer_queue(struct vb2_buffer *vb)
-{
-       unsigned long flags;
-       struct stk1160 *dev = vb2_get_drv_priv(vb->vb2_queue);
-       struct stk1160_buffer *buf =
-               container_of(vb, struct stk1160_buffer, vb);
-
-       spin_lock_irqsave(&dev->buf_lock, flags);
-       if (!dev->udev) {
-               /*
-                * If the device is disconnected return the buffer to userspace
-                * directly. The next QBUF call will fail with -ENODEV.
-                */
-               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-       } else {
-
-               buf->mem = vb2_plane_vaddr(vb, 0);
-               buf->length = vb2_plane_size(vb, 0);
-               buf->bytesused = 0;
-               buf->pos = 0;
-
-               /*
-                * If buffer length is less from expected then we return
-                * the buffer to userspace directly.
-                */
-               if (buf->length < dev->width * dev->height * 2)
-                       vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-               else
-                       list_add_tail(&buf->list, &dev->avail_bufs);
-
-       }
-       spin_unlock_irqrestore(&dev->buf_lock, flags);
-}
-
-static int start_streaming(struct vb2_queue *vq, unsigned int count)
-{
-       struct stk1160 *dev = vb2_get_drv_priv(vq);
-       return stk1160_start_streaming(dev);
-}
-
-/* abort streaming and wait for last buffer */
-static int stop_streaming(struct vb2_queue *vq)
-{
-       struct stk1160 *dev = vb2_get_drv_priv(vq);
-       return stk1160_stop_streaming(dev);
-}
-
-static struct vb2_ops stk1160_video_qops = {
-       .queue_setup            = queue_setup,
-       .buf_queue              = buffer_queue,
-       .start_streaming        = start_streaming,
-       .stop_streaming         = stop_streaming,
-       .wait_prepare           = vb2_ops_wait_prepare,
-       .wait_finish            = vb2_ops_wait_finish,
-};
-
-static struct video_device v4l_template = {
-       .name = "stk1160",
-       .tvnorms = V4L2_STD_525_60 | V4L2_STD_625_50,
-       .fops = &stk1160_fops,
-       .ioctl_ops = &stk1160_ioctl_ops,
-       .release = video_device_release_empty,
-};
-
-/********************************************************************/
-
-/* Must be called with both v4l_lock and vb_queue_lock hold */
-void stk1160_clear_queue(struct stk1160 *dev)
-{
-       struct stk1160_buffer *buf;
-       unsigned long flags;
-
-       /* Release all active buffers */
-       spin_lock_irqsave(&dev->buf_lock, flags);
-       while (!list_empty(&dev->avail_bufs)) {
-               buf = list_first_entry(&dev->avail_bufs,
-                       struct stk1160_buffer, list);
-               list_del(&buf->list);
-               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
-               stk1160_info("buffer [%p/%d] aborted\n",
-                               buf, buf->vb.v4l2_buf.index);
-       }
-       /* It's important to clear current buffer */
-       dev->isoc_ctl.buf = NULL;
-       spin_unlock_irqrestore(&dev->buf_lock, flags);
-}
-
-int stk1160_vb2_setup(struct stk1160 *dev)
-{
-       int rc;
-       struct vb2_queue *q;
-
-       q = &dev->vb_vidq;
-       memset(q, 0, sizeof(dev->vb_vidq));
-       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
-       q->drv_priv = dev;
-       q->buf_struct_size = sizeof(struct stk1160_buffer);
-       q->ops = &stk1160_video_qops;
-       q->mem_ops = &vb2_vmalloc_memops;
-
-       rc = vb2_queue_init(q);
-       if (rc < 0)
-               return rc;
-
-       /* initialize video dma queue */
-       INIT_LIST_HEAD(&dev->avail_bufs);
-
-       return 0;
-}
-
-int stk1160_video_register(struct stk1160 *dev)
-{
-       int rc;
-
-       /* Initialize video_device with a template structure */
-       dev->vdev = v4l_template;
-       dev->vdev.debug = vidioc_debug;
-       dev->vdev.queue = &dev->vb_vidq;
-
-       /*
-        * Provide mutexes for v4l2 core and for videobuf2 queue.
-        * It will be used to protect *only* v4l2 ioctls.
-        */
-       dev->vdev.lock = &dev->v4l_lock;
-       dev->vdev.queue->lock = &dev->vb_queue_lock;
-
-       /* This will be used to set video_device parent */
-       dev->vdev.v4l2_dev = &dev->v4l2_dev;
-       set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
-
-       /* NTSC is default */
-       dev->norm = V4L2_STD_NTSC_M;
-       dev->width = 720;
-       dev->height = 480;
-
-       /* set default format */
-       dev->fmt = &format[0];
-       stk1160_set_std(dev);
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std,
-                       dev->norm);
-
-       video_set_drvdata(&dev->vdev, dev);
-       rc = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
-       if (rc < 0) {
-               stk1160_err("video_register_device failed (%d)\n", rc);
-               return rc;
-       }
-
-       v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
-                 video_device_node_name(&dev->vdev));
-
-       return 0;
-}
diff --git a/drivers/media/video/stk1160/stk1160-video.c b/drivers/media/video/stk1160/stk1160-video.c
deleted file mode 100644 (file)
index 3785269..0000000
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
- * STK1160 driver
- *
- * Copyright (C) 2012 Ezequiel Garcia
- * <elezegarcia--a.t--gmail.com>
- *
- * Based on Easycap driver by R.M. Thomas
- *     Copyright (C) 2010 R.M. Thomas
- *     <rmthomas--a.t--sciolus.org>
- *
- * 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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/slab.h>
-#include <linux/ratelimit.h>
-
-#include "stk1160.h"
-
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug messages");
-
-static inline void print_err_status(struct stk1160 *dev,
-                                    int packet, int status)
-{
-       char *errmsg = "Unknown";
-
-       switch (status) {
-       case -ENOENT:
-               errmsg = "unlinked synchronuously";
-               break;
-       case -ECONNRESET:
-               errmsg = "unlinked asynchronuously";
-               break;
-       case -ENOSR:
-               errmsg = "Buffer error (overrun)";
-               break;
-       case -EPIPE:
-               errmsg = "Stalled (device not responding)";
-               break;
-       case -EOVERFLOW:
-               errmsg = "Babble (bad cable?)";
-               break;
-       case -EPROTO:
-               errmsg = "Bit-stuff error (bad cable?)";
-               break;
-       case -EILSEQ:
-               errmsg = "CRC/Timeout (could be anything)";
-               break;
-       case -ETIME:
-               errmsg = "Device does not respond";
-               break;
-       }
-
-       if (packet < 0)
-               printk_ratelimited(KERN_WARNING "URB status %d [%s].\n",
-                               status, errmsg);
-       else
-               printk_ratelimited(KERN_INFO "URB packet %d, status %d [%s].\n",
-                              packet, status, errmsg);
-}
-
-static inline
-struct stk1160_buffer *stk1160_next_buffer(struct stk1160 *dev)
-{
-       struct stk1160_buffer *buf = NULL;
-       unsigned long flags = 0;
-
-       /* Current buffer must be NULL when this functions gets called */
-       BUG_ON(dev->isoc_ctl.buf);
-
-       spin_lock_irqsave(&dev->buf_lock, flags);
-       if (!list_empty(&dev->avail_bufs)) {
-               buf = list_first_entry(&dev->avail_bufs,
-                               struct stk1160_buffer, list);
-               list_del(&buf->list);
-       }
-       spin_unlock_irqrestore(&dev->buf_lock, flags);
-
-       return buf;
-}
-
-static inline
-void stk1160_buffer_done(struct stk1160 *dev)
-{
-       struct stk1160_buffer *buf = dev->isoc_ctl.buf;
-
-       dev->field_count++;
-
-       buf->vb.v4l2_buf.sequence = dev->field_count >> 1;
-       buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
-       buf->vb.v4l2_buf.bytesused = buf->bytesused;
-       do_gettimeofday(&buf->vb.v4l2_buf.timestamp);
-
-       vb2_set_plane_payload(&buf->vb, 0, buf->bytesused);
-       vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
-
-       dev->isoc_ctl.buf = NULL;
-}
-
-static inline
-void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len)
-{
-       int linesdone, lineoff, lencopy;
-       int bytesperline = dev->width * 2;
-       struct stk1160_buffer *buf = dev->isoc_ctl.buf;
-       u8 *dst = buf->mem;
-       int remain;
-
-       /*
-        * TODO: These stk1160_dbg are very spammy!
-        * We should 1) check why we are getting them
-        * and 2) add ratelimit.
-        *
-        * UPDATE: One of the reasons (the only one?) for getting these
-        * is incorrect standard (mismatch between expected and configured).
-        * So perhaps, we could add a counter for errors. When the counter
-        * reaches some value, we simply stop streaming.
-        */
-
-       len -= 4;
-       src += 4;
-
-       remain = len;
-
-       linesdone = buf->pos / bytesperline;
-       lineoff = buf->pos % bytesperline; /* offset in current line */
-
-       if (!buf->odd)
-               dst += bytesperline;
-
-       /* Multiply linesdone by two, to take account of the other field */
-       dst += linesdone * bytesperline * 2 + lineoff;
-
-       /* Copy the remaining of current line */
-       if (remain < (bytesperline - lineoff))
-               lencopy = remain;
-       else
-               lencopy = bytesperline - lineoff;
-
-       /*
-        * Check if we have enough space left in the buffer.
-        * In that case, we force loop exit after copy.
-        */
-       if (lencopy > buf->bytesused - buf->length) {
-               lencopy = buf->bytesused - buf->length;
-               remain = lencopy;
-       }
-
-       /* Check if the copy is done */
-       if (lencopy == 0 || remain == 0)
-               return;
-
-       /* Let the bug hunt begin! sanity checks! */
-       if (lencopy < 0) {
-               stk1160_dbg("copy skipped: negative lencopy\n");
-               return;
-       }
-
-       if ((unsigned long)dst + lencopy >
-               (unsigned long)buf->mem + buf->length) {
-               printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n");
-               return;
-       }
-
-       memcpy(dst, src, lencopy);
-
-       buf->bytesused += lencopy;
-       buf->pos += lencopy;
-       remain -= lencopy;
-
-       /* Copy current field line by line, interlacing with the other field */
-       while (remain > 0) {
-
-               dst += lencopy + bytesperline;
-               src += lencopy;
-
-               /* Copy one line at a time */
-               if (remain < bytesperline)
-                       lencopy = remain;
-               else
-                       lencopy = bytesperline;
-
-               /*
-                * Check if we have enough space left in the buffer.
-                * In that case, we force loop exit after copy.
-                */
-               if (lencopy > buf->bytesused - buf->length) {
-                       lencopy = buf->bytesused - buf->length;
-                       remain = lencopy;
-               }
-
-               /* Check if the copy is done */
-               if (lencopy == 0 || remain == 0)
-                       return;
-
-               if (lencopy < 0) {
-                       printk_ratelimited(KERN_WARNING "stk1160: negative lencopy detected\n");
-                       return;
-               }
-
-               if ((unsigned long)dst + lencopy >
-                       (unsigned long)buf->mem + buf->length) {
-                       printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n");
-                       return;
-               }
-
-               memcpy(dst, src, lencopy);
-               remain -= lencopy;
-
-               buf->bytesused += lencopy;
-               buf->pos += lencopy;
-       }
-}
-
-/*
- * Controls the isoc copy of each urb packet
- */
-static void stk1160_process_isoc(struct stk1160 *dev, struct urb *urb)
-{
-       int i, len, status;
-       u8 *p;
-
-       if (!dev) {
-               stk1160_warn("%s called with null device\n", __func__);
-               return;
-       }
-
-       if (urb->status < 0) {
-               /* Print status and drop current packet (or field?) */
-               print_err_status(dev, -1, urb->status);
-               return;
-       }
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               status = urb->iso_frame_desc[i].status;
-               if (status < 0) {
-                       print_err_status(dev, i, status);
-                       continue;
-               }
-
-               /* Get packet actual length and pointer to data */
-               p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-               len = urb->iso_frame_desc[i].actual_length;
-
-               /* Empty packet */
-               if (len <= 4)
-                       continue;
-
-               /*
-                * An 8-byte packet sequence means end of field.
-                * So if we don't have any packet, we start receiving one now
-                * and if we do have a packet, then we are done with it.
-                *
-                * These end of field packets are always 0xc0 or 0x80,
-                * but not always 8-byte long so we don't check packet length.
-                */
-               if (p[0] == 0xc0) {
-
-                       /*
-                        * If first byte is 0xc0 then we received
-                        * second field, and frame has ended.
-                        */
-                       if (dev->isoc_ctl.buf != NULL)
-                               stk1160_buffer_done(dev);
-
-                       dev->isoc_ctl.buf = stk1160_next_buffer(dev);
-                       if (dev->isoc_ctl.buf == NULL)
-                               return;
-               }
-
-               /*
-                * If we don't have a buffer here, then it means we
-                * haven't found the start mark sequence.
-                */
-               if (dev->isoc_ctl.buf == NULL)
-                       continue;
-
-               if (p[0] == 0xc0 || p[0] == 0x80) {
-
-                       /* We set next packet parity and
-                        * continue to get next one
-                        */
-                       dev->isoc_ctl.buf->odd = *p & 0x40;
-                       dev->isoc_ctl.buf->pos = 0;
-                       continue;
-               }
-
-               stk1160_copy_video(dev, p, len);
-       }
-}
-
-
-/*
- * IRQ callback, called by URB callback
- */
-static void stk1160_isoc_irq(struct urb *urb)
-{
-       int i, rc;
-       struct stk1160 *dev = urb->context;
-
-       switch (urb->status) {
-       case 0:
-               break;
-       case -ECONNRESET:   /* kill */
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* TODO: check uvc driver: he frees the queue here */
-               return;
-       default:
-               stk1160_err("urb error! status %d\n", urb->status);
-               return;
-       }
-
-       stk1160_process_isoc(dev, urb);
-
-       /* Reset urb buffers */
-       for (i = 0; i < urb->number_of_packets; i++) {
-               urb->iso_frame_desc[i].status = 0;
-               urb->iso_frame_desc[i].actual_length = 0;
-       }
-
-       rc = usb_submit_urb(urb, GFP_ATOMIC);
-       if (rc)
-               stk1160_err("urb re-submit failed (%d)\n", rc);
-}
-
-/*
- * Cancel urbs
- * This function can't be called in atomic context
- */
-void stk1160_cancel_isoc(struct stk1160 *dev)
-{
-       int i;
-
-       /*
-        * This check is not necessary, but we add it
-        * to avoid a spurious debug message
-        */
-       if (!dev->isoc_ctl.num_bufs)
-               return;
-
-       stk1160_dbg("killing urbs...\n");
-
-       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
-
-               /*
-                * To kill urbs we can't be in atomic context.
-                * We don't care for NULL pointer since
-                * usb_kill_urb allows it.
-                */
-               usb_kill_urb(dev->isoc_ctl.urb[i]);
-       }
-
-       stk1160_dbg("all urbs killed\n");
-}
-
-/*
- * Releases urb and transfer buffers
- * Obviusly, associated urb must be killed before releasing it.
- */
-void stk1160_free_isoc(struct stk1160 *dev)
-{
-       struct urb *urb;
-       int i;
-
-       stk1160_dbg("freeing urb buffers...\n");
-
-       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
-
-               urb = dev->isoc_ctl.urb[i];
-               if (urb) {
-
-                       if (dev->isoc_ctl.transfer_buffer[i]) {
-#ifndef CONFIG_DMA_NONCOHERENT
-                               usb_free_coherent(dev->udev,
-                                       urb->transfer_buffer_length,
-                                       dev->isoc_ctl.transfer_buffer[i],
-                                       urb->transfer_dma);
-#else
-                               kfree(dev->isoc_ctl.transfer_buffer[i]);
-#endif
-                       }
-                       usb_free_urb(urb);
-                       dev->isoc_ctl.urb[i] = NULL;
-               }
-               dev->isoc_ctl.transfer_buffer[i] = NULL;
-       }
-
-       kfree(dev->isoc_ctl.urb);
-       kfree(dev->isoc_ctl.transfer_buffer);
-
-       dev->isoc_ctl.urb = NULL;
-       dev->isoc_ctl.transfer_buffer = NULL;
-       dev->isoc_ctl.num_bufs = 0;
-
-       stk1160_dbg("all urb buffers freed\n");
-}
-
-/*
- * Helper for cancelling and freeing urbs
- * This function can't be called in atomic context
- */
-void stk1160_uninit_isoc(struct stk1160 *dev)
-{
-       stk1160_cancel_isoc(dev);
-       stk1160_free_isoc(dev);
-}
-
-/*
- * Allocate URBs
- */
-int stk1160_alloc_isoc(struct stk1160 *dev)
-{
-       struct urb *urb;
-       int i, j, k, sb_size, max_packets, num_bufs;
-
-       /*
-        * It may be necessary to release isoc here,
-        * since isoc are only released on disconnection.
-        * (see new_pkt_size flag)
-        */
-       if (dev->isoc_ctl.num_bufs)
-               stk1160_uninit_isoc(dev);
-
-       stk1160_dbg("allocating urbs...\n");
-
-       num_bufs = STK1160_NUM_BUFS;
-       max_packets = STK1160_NUM_PACKETS;
-       sb_size = max_packets * dev->max_pkt_size;
-
-       dev->isoc_ctl.buf = NULL;
-       dev->isoc_ctl.max_pkt_size = dev->max_pkt_size;
-       dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
-       if (!dev->isoc_ctl.urb) {
-               stk1160_err("out of memory for urb array\n");
-               return -ENOMEM;
-       }
-
-       dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
-                                             GFP_KERNEL);
-       if (!dev->isoc_ctl.transfer_buffer) {
-               stk1160_err("out of memory for usb transfers\n");
-               kfree(dev->isoc_ctl.urb);
-               return -ENOMEM;
-       }
-
-       /* allocate urbs and transfer buffers */
-       for (i = 0; i < num_bufs; i++) {
-
-               urb = usb_alloc_urb(max_packets, GFP_KERNEL);
-               if (!urb) {
-                       stk1160_err("cannot alloc urb[%d]\n", i);
-                       stk1160_uninit_isoc(dev);
-                       return -ENOMEM;
-               }
-               dev->isoc_ctl.urb[i] = urb;
-
-#ifndef CONFIG_DMA_NONCOHERENT
-               dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev,
-                       sb_size, GFP_KERNEL, &urb->transfer_dma);
-#else
-               dev->isoc_ctl.transfer_buffer[i] = kmalloc(sb_size, GFP_KERNEL);
-#endif
-               if (!dev->isoc_ctl.transfer_buffer[i]) {
-                       stk1160_err("cannot alloc %d bytes for tx buffer\n",
-                               sb_size);
-                       stk1160_uninit_isoc(dev);
-                       return -ENOMEM;
-               }
-               memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
-
-               /*
-                * FIXME: Where can I get the endpoint?
-                */
-               urb->dev = dev->udev;
-               urb->pipe = usb_rcvisocpipe(dev->udev, STK1160_EP_VIDEO);
-               urb->transfer_buffer = dev->isoc_ctl.transfer_buffer[i];
-               urb->transfer_buffer_length = sb_size;
-               urb->complete = stk1160_isoc_irq;
-               urb->context = dev;
-               urb->interval = 1;
-               urb->start_frame = 0;
-               urb->number_of_packets = max_packets;
-#ifndef CONFIG_DMA_NONCOHERENT
-               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-#else
-               urb->transfer_flags = URB_ISO_ASAP;
-#endif
-
-               k = 0;
-               for (j = 0; j < max_packets; j++) {
-                       urb->iso_frame_desc[j].offset = k;
-                       urb->iso_frame_desc[j].length =
-                                       dev->isoc_ctl.max_pkt_size;
-                       k += dev->isoc_ctl.max_pkt_size;
-               }
-       }
-
-       stk1160_dbg("urbs allocated\n");
-
-       /* At last we can say we have some buffers */
-       dev->isoc_ctl.num_bufs = num_bufs;
-
-       return 0;
-}
-
diff --git a/drivers/media/video/stk1160/stk1160.h b/drivers/media/video/stk1160/stk1160.h
deleted file mode 100644 (file)
index 3feba00..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * STK1160 driver
- *
- * Copyright (C) 2012 Ezequiel Garcia
- * <elezegarcia--a.t--gmail.com>
- *
- * Based on Easycap driver by R.M. Thomas
- *     Copyright (C) 2010 R.M. Thomas
- *     <rmthomas--a.t--sciolus.org>
- *
- * 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.
- *
- */
-
-#include <linux/i2c.h>
-#include <sound/core.h>
-#include <sound/ac97_codec.h>
-#include <media/videobuf2-core.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-ctrls.h>
-
-#define STK1160_VERSION                "0.9.5"
-#define STK1160_VERSION_NUM    0x000905
-
-/* TODO: Decide on number of packets for each buffer */
-#define STK1160_NUM_PACKETS 64
-
-/* Number of buffers for isoc transfers */
-#define STK1160_NUM_BUFS 16 /* TODO */
-
-/* TODO: This endpoint address should be retrieved */
-#define STK1160_EP_VIDEO 0x82
-#define STK1160_EP_AUDIO 0x81
-
-/* Max and min video buffers */
-#define STK1160_MIN_VIDEO_BUFFERS 8
-#define STK1160_MAX_VIDEO_BUFFERS 32
-
-#define STK1160_MIN_PKT_SIZE 3072
-
-#define STK1160_MAX_INPUT 3
-
-#define STK1160_I2C_TIMEOUT 100
-
-/* TODO: Print helpers
- * I could use dev_xxx, pr_xxx, v4l2_xxx or printk.
- * However, there isn't a solid consensus on which
- * new drivers should use.
- *
- */
-#define DEBUG
-#ifdef DEBUG
-#define stk1160_dbg(fmt, args...) \
-       printk(KERN_DEBUG "stk1160: " fmt,  ## args)
-#else
-#define stk1160_dbg(fmt, args...)
-#endif
-
-#define stk1160_info(fmt, args...) \
-       pr_info("stk1160: " fmt, ## args)
-
-#define stk1160_warn(fmt, args...) \
-       pr_warn("stk1160: " fmt, ## args)
-
-#define stk1160_err(fmt, args...) \
-       pr_err("stk1160: " fmt, ## args)
-
-/* Buffer for one video frame */
-struct stk1160_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct vb2_buffer vb;
-       struct list_head list;
-
-       void *mem;
-       unsigned int length;            /* buffer length */
-       unsigned int bytesused;         /* bytes written */
-       int odd;                        /* current oddity */
-
-       /*
-        * Since we interlace two fields per frame,
-        * this is different from bytesused.
-        */
-       unsigned int pos;               /* current pos inside buffer */
-};
-
-struct stk1160_isoc_ctl {
-       /* max packet size of isoc transaction */
-       int max_pkt_size;
-
-       /* number of allocated urbs */
-       int num_bufs;
-
-       /* urb for isoc transfers */
-       struct urb **urb;
-
-       /* transfer buffers for isoc transfer */
-       char **transfer_buffer;
-
-       /* current buffer */
-       struct stk1160_buffer *buf;
-};
-
-struct stk1160_fmt {
-       char  *name;
-       u32   fourcc;          /* v4l2 format id */
-       int   depth;
-};
-
-struct stk1160 {
-       struct v4l2_device v4l2_dev;
-       struct video_device vdev;
-       struct v4l2_ctrl_handler ctrl_handler;
-
-       struct device *dev;
-       struct usb_device *udev;
-
-       /* saa7115 subdev */
-       struct v4l2_subdev *sd_saa7115;
-
-       /* isoc control struct */
-       struct list_head avail_bufs;
-
-       /* video capture */
-       struct vb2_queue vb_vidq;
-
-       /* max packet size of isoc transaction */
-       int max_pkt_size;
-       /* array of wMaxPacketSize */
-       unsigned int *alt_max_pkt_size;
-       /* alternate */
-       int alt;
-       /* Number of alternative settings */
-       int num_alt;
-
-       struct stk1160_isoc_ctl isoc_ctl;
-       char urb_buf[255];       /* urb control msg buffer */
-
-       /* frame properties */
-       int width;                /* current frame width */
-       int height;               /* current frame height */
-       unsigned int ctl_input;   /* selected input */
-       v4l2_std_id norm;         /* current norm */
-       struct stk1160_fmt *fmt;  /* selected format */
-
-       unsigned int field_count; /* not sure ??? */
-       enum v4l2_field field;    /* also not sure :/ */
-
-       /* i2c i/o */
-       struct i2c_adapter i2c_adap;
-       struct i2c_client i2c_client;
-
-       struct mutex v4l_lock;
-       struct mutex vb_queue_lock;
-       spinlock_t buf_lock;
-
-       struct file *fh_owner;  /* filehandle ownership */
-
-       /* EXPERIMENTAL */
-       struct snd_card *snd_card;
-};
-
-struct regval {
-       u16 reg;
-       u16 val;
-};
-
-/* Provided by stk1160-v4l.c */
-int stk1160_vb2_setup(struct stk1160 *dev);
-int stk1160_video_register(struct stk1160 *dev);
-void stk1160_video_unregister(struct stk1160 *dev);
-void stk1160_clear_queue(struct stk1160 *dev);
-
-/* Provided by stk1160-video.c */
-int stk1160_alloc_isoc(struct stk1160 *dev);
-void stk1160_free_isoc(struct stk1160 *dev);
-void stk1160_cancel_isoc(struct stk1160 *dev);
-void stk1160_uninit_isoc(struct stk1160 *dev);
-
-/* Provided by stk1160-i2c.c */
-int stk1160_i2c_register(struct stk1160 *dev);
-int stk1160_i2c_unregister(struct stk1160 *dev);
-
-/* Provided by stk1160-core.c */
-int stk1160_read_reg(struct stk1160 *dev, u16 reg, u8 *value);
-int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value);
-int stk1160_write_regs_req(struct stk1160 *dev, u8 req, u16 reg,
-               char *buf, int len);
-int stk1160_read_reg_req_len(struct stk1160 *dev, u8 req, u16 reg,
-               char *buf, int len);
-void stk1160_select_input(struct stk1160 *dev);
-
-/* Provided by stk1160-ac97.c */
-#ifdef CONFIG_VIDEO_STK1160_AC97
-int stk1160_ac97_register(struct stk1160 *dev);
-int stk1160_ac97_unregister(struct stk1160 *dev);
-#else
-static inline int stk1160_ac97_register(struct stk1160 *dev) { return 0; }
-static inline int stk1160_ac97_unregister(struct stk1160 *dev) { return 0; }
-#endif
-
diff --git a/drivers/media/video/tlg2300/Kconfig b/drivers/media/video/tlg2300/Kconfig
deleted file mode 100644 (file)
index 645d915..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-config VIDEO_TLG2300
-       tristate "Telegent TLG2300 USB video capture support"
-       depends on VIDEO_DEV && I2C && SND && DVB_CORE
-       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.
-
-         To compile this driver as a module, choose M here: the
-         module will be called poseidon
diff --git a/drivers/media/video/tlg2300/Makefile b/drivers/media/video/tlg2300/Makefile
deleted file mode 100644 (file)
index 4d66087..0000000
+++ /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/video
-ccflags-y += -Idrivers/media/tuners
-ccflags-y += -Idrivers/media/dvb-core
-ccflags-y += -Idrivers/media/dvb-frontends
-
diff --git a/drivers/media/video/tlg2300/pd-alsa.c b/drivers/media/video/tlg2300/pd-alsa.c
deleted file mode 100644 (file)
index 9f8b7da..0000000
+++ /dev/null
@@ -1,332 +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_create(-1, "Telegent", THIS_MODULE, 0, &card);
-       if (ret != 0)
-               return ret;
-
-       ret = snd_pcm_new(card, "poseidon audio", 0, 0, 1, &pcm);
-       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/media/video/tlg2300/pd-common.h b/drivers/media/video/tlg2300/pd-common.h
deleted file mode 100644 (file)
index 5dd73b7..0000000
+++ /dev/null
@@ -1,281 +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 "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_VBI             (0x0008)
-#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         (45000000)
-#define TUNER_FREQ_MAX         (862000000)
-
-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;
-
-       /* 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;
-       int             users;
-       unsigned int    is_radio_streaming;
-       int             pre_emphasis;
-       struct video_device *fm_dev;
-};
-
-#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 *);
-struct video_device *vdev_init(struct poseidon *, struct video_device *);
-
-/* 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);
-void destroy_video_device(struct video_device **v_dev);
-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)
-
-#define logs(f) do { \
-                       if ((debug_mode & 0x4) && \
-                               (f)->type == V4L2_BUF_TYPE_VBI_CAPTURE) \
-                                       log("type : VBI");\
-                                                               \
-                       if ((debug_mode & 0x8) && \
-                               (f)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) \
-                                       log("type : VIDEO");\
-               } while (0)
-#endif
diff --git a/drivers/media/video/tlg2300/pd-dvb.c b/drivers/media/video/tlg2300/pd-dvb.c
deleted file mode 100644 (file)
index 30fcb11..0000000
+++ /dev/null
@@ -1,596 +0,0 @@
-#include "pd-common.h"
-#include <linux/kernel.h>
-#include <linux/usb.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/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c
deleted file mode 100644 (file)
index 7b1f6eb..0000000
+++ /dev/null
@@ -1,536 +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 struct usb_driver poseidon_driver;
-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 = 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) + pd->radio_data.users;
-}
-
-/* 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 "\n\t+ TLG2300 auto suspend +\n\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 "\n\t ++ TLG2300 resume ++\n\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, int *down_firmware)
-{
-       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) {
-               *down_firmware = 1;
-               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 */
-       check_firmware(udev, &ret);
-       if (ret)
-               return 0;
-
-       /* 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) {
-               struct device *dev = &interface->dev;
-
-               logpm(pd);
-               mutex_init(&pd->lock);
-
-               /* register v4l2 device */
-               snprintf(pd->v4l2_dev.name, sizeof(pd->v4l2_dev.name), "%s %s",
-                       dev->driver->name, dev_name(dev));
-               ret = v4l2_device_register(NULL, &pd->v4l2_dev);
-
-               /* register devices in directory /dev */
-               ret = pd_video_init(pd);
-               poseidon_audio_init(pd);
-               poseidon_fm_init(pd);
-               pd_dvb_usb_device_init(pd);
-
-               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;
-}
-
-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/media/video/tlg2300/pd-radio.c b/drivers/media/video/tlg2300/pd-radio.c
deleted file mode 100644 (file)
index 4fad1df..0000000
+++ /dev/null
@@ -1,421 +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 <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 76000000
-#define TUNER_FREQ_MAX_FM 108000000
-
-#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 video_device *vfd = video_devdata(filp);
-       struct poseidon *p = video_get_drvdata(vfd);
-       int ret = 0;
-
-       if (!p)
-               return -1;
-
-       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;
-       }
-
-       usb_autopm_get_interface(p->interface);
-       if (0 == p->state) {
-               /* 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;
-       }
-       p->radio_data.users++;
-       kref_get(&p->kref);
-       filp->private_data = p;
-out:
-       mutex_unlock(&p->lock);
-       return ret;
-}
-
-static int poseidon_fm_close(struct file *filp)
-{
-       struct poseidon *p = filp->private_data;
-       struct radio_data *fm = &p->radio_data;
-       uint32_t status;
-
-       mutex_lock(&p->lock);
-       fm->users--;
-       if (0 == fm->users)
-               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);
-       filp->private_data = NULL;
-       return 0;
-}
-
-static int vidioc_querycap(struct file *file, void *priv,
-                       struct v4l2_capability *v)
-{
-       struct poseidon *p = file->private_data;
-
-       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->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
-       return 0;
-}
-
-static const struct v4l2_file_operations poseidon_fm_fops = {
-       .owner         = THIS_MODULE,
-       .open          = poseidon_fm_open,
-       .release       = poseidon_fm_close,
-       .ioctl         = video_ioctl2,
-};
-
-static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv,
-                                struct v4l2_tuner *vt)
-{
-       struct tuner_fm_sig_stat_s fm_stat = {};
-       int ret, status, count = 5;
-       struct poseidon *p = file->private_data;
-
-       if (vt->index != 0)
-               return -EINVAL;
-
-       vt->type        = V4L2_TUNER_RADIO;
-       vt->capability  = V4L2_TUNER_CAP_STEREO;
-       vt->rangelow    = TUNER_FREQ_MIN_FM / 62500;
-       vt->rangehigh   = TUNER_FREQ_MAX_FM / 62500;
-       vt->rxsubchans  = V4L2_TUNER_SUB_STEREO;
-       vt->audmode     = V4L2_TUNER_MODE_STEREO;
-       vt->signal      = 0;
-       vt->afc         = 0;
-
-       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 = file->private_data;
-
-       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) * 500 / 1000;/* kHZ */
-       if (freq < TUNER_FREQ_MIN_FM/1000 || freq > TUNER_FREQ_MAX_FM/1000) {
-               ret = -EINVAL;
-               goto error;
-       }
-
-       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 = frequency;
-error:
-       mutex_unlock(&p->lock);
-       return ret;
-}
-
-static int fm_set_freq(struct file *file, void *priv,
-                      struct v4l2_frequency *argp)
-{
-       struct poseidon *p = file->private_data;
-
-       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_vidioc_g_ctrl(struct file *file, void *priv,
-               struct v4l2_control *arg)
-{
-       return 0;
-}
-
-static int tlg_fm_vidioc_g_exts_ctrl(struct file *file, void *fh,
-                               struct v4l2_ext_controls *ctrls)
-{
-       struct poseidon *p = file->private_data;
-       int i;
-
-       if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX)
-               return -EINVAL;
-
-       for (i = 0; i < ctrls->count; i++) {
-               struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
-               if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS)
-                       continue;
-
-               if (i < MAX_PREEMPHASIS)
-                       ctrl->value = p->radio_data.pre_emphasis;
-       }
-       return 0;
-}
-
-static int tlg_fm_vidioc_s_exts_ctrl(struct file *file, void *fh,
-                       struct v4l2_ext_controls *ctrls)
-{
-       int i;
-
-       if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX)
-               return -EINVAL;
-
-       for (i = 0; i < ctrls->count; i++) {
-               struct v4l2_ext_control *ctrl = ctrls->controls + i;
-
-               if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS)
-                       continue;
-
-               if (ctrl->value >= 0 && ctrl->value < MAX_PREEMPHASIS) {
-                       struct poseidon *p = file->private_data;
-                       int pre_emphasis = preemphasis[ctrl->value];
-                       u32 status;
-
-                       send_set_req(p, TUNER_AUD_ANA_STD,
-                                               pre_emphasis, &status);
-                       p->radio_data.pre_emphasis = pre_emphasis;
-               }
-       }
-       return 0;
-}
-
-static int tlg_fm_vidioc_s_ctrl(struct file *file, void *priv,
-               struct v4l2_control *ctrl)
-{
-       return 0;
-}
-
-static int tlg_fm_vidioc_queryctrl(struct file *file, void *priv,
-               struct v4l2_queryctrl *ctrl)
-{
-       if (!(ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL))
-               return -EINVAL;
-
-       ctrl->id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
-       if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS) {
-               /* return the next supported control */
-               ctrl->id = V4L2_CID_TUNE_PREEMPHASIS;
-               v4l2_ctrl_query_fill(ctrl, V4L2_PREEMPHASIS_DISABLED,
-                                       V4L2_PREEMPHASIS_75_uS, 1,
-                                       V4L2_PREEMPHASIS_50_uS);
-               ctrl->flags = V4L2_CTRL_FLAG_UPDATE;
-               return 0;
-       }
-       return -EINVAL;
-}
-
-static int tlg_fm_vidioc_querymenu(struct file *file, void *fh,
-                               struct v4l2_querymenu *qmenu)
-{
-       return v4l2_ctrl_query_menu(qmenu, NULL, NULL);
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
-{
-       return vt->index > 0 ? -EINVAL : 0;
-}
-static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *va)
-{
-       return (va->index != 0) ? -EINVAL : 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-       a->index    = 0;
-       a->mode    = 0;
-       a->capability = V4L2_AUDCAP_STEREO;
-       strcpy(a->name, "Radio");
-       return 0;
-}
-
-static int vidioc_s_input(struct file *filp, void *priv, u32 i)
-{
-       return (i != 0) ? -EINVAL : 0;
-}
-
-static int vidioc_g_input(struct file *filp, void *priv, u32 *i)
-{
-       return (*i != 0) ? -EINVAL : 0;
-}
-
-static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = {
-       .vidioc_querycap    = vidioc_querycap,
-       .vidioc_g_audio     = vidioc_g_audio,
-       .vidioc_s_audio     = vidioc_s_audio,
-       .vidioc_g_input     = vidioc_g_input,
-       .vidioc_s_input     = vidioc_s_input,
-       .vidioc_queryctrl   = tlg_fm_vidioc_queryctrl,
-       .vidioc_querymenu   = tlg_fm_vidioc_querymenu,
-       .vidioc_g_ctrl      = tlg_fm_vidioc_g_ctrl,
-       .vidioc_s_ctrl      = tlg_fm_vidioc_s_ctrl,
-       .vidioc_s_ext_ctrls = tlg_fm_vidioc_s_exts_ctrl,
-       .vidioc_g_ext_ctrls = tlg_fm_vidioc_g_exts_ctrl,
-       .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,
-};
-
-static struct video_device poseidon_fm_template = {
-       .name       = "Telegent-Radio",
-       .fops       = &poseidon_fm_fops,
-       .minor      = -1,
-       .release    = video_device_release,
-       .ioctl_ops  = &poseidon_fm_ioctl_ops,
-};
-
-int poseidon_fm_init(struct poseidon *p)
-{
-       struct video_device *fm_dev;
-
-       fm_dev = vdev_init(p, &poseidon_fm_template);
-       if (fm_dev == NULL)
-               return -1;
-
-       if (video_register_device(fm_dev, VFL_TYPE_RADIO, -1) < 0) {
-               video_device_release(fm_dev);
-               return -1;
-       }
-       p->radio_data.fm_dev = fm_dev;
-       return 0;
-}
-
-int poseidon_fm_exit(struct poseidon *p)
-{
-       destroy_video_device(&p->radio_data.fm_dev);
-       return 0;
-}
diff --git a/drivers/media/video/tlg2300/pd-video.c b/drivers/media/video/tlg2300/pd-video.c
deleted file mode 100644 (file)
index bfbf9e5..0000000
+++ /dev/null
@@ -1,1668 +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 "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 poseidon_control {
-       struct v4l2_queryctrl v4l2_ctrl;
-       enum cmd_custom_param_id vc_id;
-};
-
-static struct poseidon_control controls[] = {
-       {
-               { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER,
-                       "brightness", 0, 10000, 1, 100, 0, },
-               CUST_PARM_ID_BRIGHTNESS_CTRL
-       }, {
-               { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER,
-                       "contrast", 0, 10000, 1, 100, 0, },
-               CUST_PARM_ID_CONTRAST_CTRL,
-       }, {
-               { V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER,
-                       "hue", 0, 10000, 1, 100, 0, },
-               CUST_PARM_ID_HUE_CTRL,
-       }, {
-               { V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER,
-                       "saturation", 0, 10000, 1, 100, 0, },
-               CUST_PARM_ID_SATURATION_CTRL,
-       },
-};
-
-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 front_face *front = fh;
-       struct poseidon *p = front->pd;
-
-       logs(front);
-
-       strcpy(cap->driver, "tele-video");
-       strcpy(cap->card, "Telegent Poseidon");
-       usb_make_path(p->udev, cap->bus_info, sizeof(cap->bus_info));
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
-                               V4L2_CAP_AUDIO | V4L2_CAP_STREAMING |
-                               V4L2_CAP_READWRITE | V4L2_CAP_VBI_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++;
-       do_gettimeofday(&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)
-{
-       /* logs(video->front); */
-       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;
-
-       logs(front);
-       f->fmt.pix = pd->video_data.context.pix;
-       return 0;
-}
-
-static int vidioc_try_fmt(struct file *file, void *fh,
-               struct v4l2_format *f)
-{
-       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;
-
-       logs(front);
-       /* 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;
-       logs(front);
-       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;
-       logs(front);
-       return set_std(front->pd, norm);
-}
-
-static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in)
-{
-       struct front_face *front = fh;
-
-       if (in->index < 0 || 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    = 0;
-       in->tuner       = 0;
-       in->std         = V4L2_STD_ALL;
-       in->status      = 0;
-       logs(front);
-       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;
-
-       logs(front);
-       *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 < 0 || 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 struct poseidon_control *check_control_id(__u32 id)
-{
-       struct poseidon_control *control = &controls[0];
-       int array_size = ARRAY_SIZE(controls);
-
-       for (; control < &controls[array_size]; control++)
-               if (control->v4l2_ctrl.id  == id)
-                       return control;
-       return NULL;
-}
-
-static int vidioc_queryctrl(struct file *file, void *fh,
-                       struct v4l2_queryctrl *a)
-{
-       struct poseidon_control *control = NULL;
-
-       control = check_control_id(a->id);
-       if (!control)
-               return -EINVAL;
-
-       *a = control->v4l2_ctrl;
-       return 0;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *fh, struct v4l2_control *ctrl)
-{
-       struct front_face *front = fh;
-       struct poseidon *pd = front->pd;
-       struct poseidon_control *control = NULL;
-       struct tuner_custom_parameter_s tuner_param;
-       s32 ret = 0, cmd_status;
-
-       control = check_control_id(ctrl->id);
-       if (!control)
-               return -EINVAL;
-
-       mutex_lock(&pd->lock);
-       ret = send_get_req(pd, TUNER_CUSTOM_PARAMETER, control->vc_id,
-                       &tuner_param, &cmd_status, sizeof(tuner_param));
-       mutex_unlock(&pd->lock);
-
-       if (ret || cmd_status)
-               return -1;
-
-       ctrl->value = tuner_param.param_value;
-       return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *fh, struct v4l2_control *a)
-{
-       struct tuner_custom_parameter_s param = {0};
-       struct poseidon_control *control = NULL;
-       struct front_face *front        = fh;
-       struct poseidon *pd             = front->pd;
-       s32 ret = 0, cmd_status, params;
-
-       control = check_control_id(a->id);
-       if (!control)
-               return -EINVAL;
-
-       param.param_value = a->value;
-       param.param_id  = control->vc_id;
-       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, 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;
-       logs(front);
-       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, struct v4l2_tuner *a)
-{
-       struct front_face *front        = fh;
-       struct poseidon *pd             = front->pd;
-       int index;
-
-       if (0 != a->index)
-               return -EINVAL;
-       logs(front);
-       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;
-
-       param = frequency * 62500 / 1000;
-       if (param < TUNER_FREQ_MIN/1000 || param > TUNER_FREQ_MAX / 1000)
-               return -EINVAL;
-
-       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,
-                               struct v4l2_frequency *freq)
-{
-       struct front_face *front = fh;
-       struct poseidon *pd = front->pd;
-
-       logs(front);
-#ifdef CONFIG_PM
-       pd->pm_suspend = pm_video_suspend;
-       pd->pm_resume = pm_video_resume;
-#endif
-       return set_frequency(pd, freq->frequency);
-}
-
-static int vidioc_reqbufs(struct file *file, void *fh,
-                               struct v4l2_requestbuffers *b)
-{
-       struct front_face *front = file->private_data;
-       logs(front);
-       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;
-       logs(front);
-       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;
-
-       logs(front);
-       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;
-
-       logs(front);
-       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,
-                               .priv           = 0
-                       };
-}
-
-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 (vfd->vfl_type == VFL_TYPE_GRABBER
-               && !(pd->state & POSEIDON_STATE_ANALOG)) {
-               front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
-               if (!front)
-                       goto out;
-
-               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;
-               }
-
-               pd->state               |= POSEIDON_STATE_ANALOG;
-               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 if (vfd->vfl_type == VFL_TYPE_VBI
-               && !(pd->state & POSEIDON_STATE_VBI)) {
-               front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
-               if (!front)
-                       goto out;
-
-               pd->state       |= POSEIDON_STATE_VBI;
-               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);
-       } else {
-               /* maybe add FM support here */
-               log("other ");
-               ret = -EINVAL;
-               goto out;
-       }
-
-       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;
-
-       logs(front);
-       mutex_lock(&pd->lock);
-
-       if (front->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               pd->state &= ~POSEIDON_STATE_ANALOG;
-
-               /* 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->state &= ~POSEIDON_STATE_VBI;
-               pd->vbi_data.front = NULL;
-               pd->vbi_data.users--;
-       }
-       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 */
-       .vidioc_try_fmt_vid_cap = vidioc_try_fmt,
-
-       /* 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_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,
-
-       /* Control handling */
-       .vidioc_queryctrl       = vidioc_queryctrl,
-       .vidioc_g_ctrl          = vidioc_g_ctrl,
-       .vidioc_s_ctrl          = vidioc_s_ctrl,
-};
-
-static struct video_device pd_video_template = {
-       .name = "Telegent-Video",
-       .fops = &pd_video_fops,
-       .minor = -1,
-       .release = video_device_release,
-       .tvnorms = V4L2_STD_ALL,
-       .ioctl_ops = &pd_video_ioctl_ops,
-};
-
-struct video_device *vdev_init(struct poseidon *pd, struct video_device *tmp)
-{
-       struct video_device *vfd;
-
-       vfd = video_device_alloc();
-       if (vfd == NULL)
-               return NULL;
-       *vfd            = *tmp;
-       vfd->minor      = -1;
-       vfd->v4l2_dev   = &pd->v4l2_dev;
-       /*vfd->parent   = &(pd->udev->dev); */
-       vfd->release    = video_device_release;
-       video_set_drvdata(vfd, pd);
-       return vfd;
-}
-
-void destroy_video_device(struct video_device **v_dev)
-{
-       struct video_device *dev = *v_dev;
-
-       if (dev == NULL)
-               return;
-
-       if (video_is_registered(dev))
-               video_unregister_device(dev);
-       else
-               video_device_release(dev);
-       *v_dev = NULL;
-}
-
-void pd_video_exit(struct poseidon *pd)
-{
-       struct video_data *video = &pd->video_data;
-       struct vbi_data *vbi = &pd->vbi_data;
-
-       destroy_video_device(&video->v_dev);
-       destroy_video_device(&vbi->v_dev);
-       log();
-}
-
-int pd_video_init(struct poseidon *pd)
-{
-       struct video_data *video = &pd->video_data;
-       struct vbi_data *vbi    = &pd->vbi_data;
-       int ret = -ENOMEM;
-
-       video->v_dev = vdev_init(pd, &pd_video_template);
-       if (video->v_dev == NULL)
-               goto out;
-
-       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 = vdev_init(pd, &pd_video_template);
-       if (vbi->v_dev == NULL) {
-               ret = -ENOMEM;
-               goto out;
-       }
-       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/media/video/tlg2300/vendorcmds.h b/drivers/media/video/tlg2300/vendorcmds.h
deleted file mode 100644 (file)
index ba6f4ae..0000000
+++ /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/media/video/tm6000/Kconfig b/drivers/media/video/tm6000/Kconfig
deleted file mode 100644 (file)
index a43b77a..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-config VIDEO_TM6000
-       tristate "TV Master TM5600/6000/6010 driver"
-       depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB
-       select VIDEO_TUNER
-       select MEDIA_TUNER_XC2028
-       select MEDIA_TUNER_XC5000
-       select VIDEOBUF_VMALLOC
-       help
-         Support for TM5600/TM6000/TM6010 USB Device
-
-         Since these cards have no MPEG decoder onboard, they transmit
-         only compressed MPEG data over the usb bus, so you need
-         an external software decoder to watch TV on your computer.
-
-         Say Y if you own such a device and want to use it.
-
-config VIDEO_TM6000_ALSA
-       tristate "TV Master TM5600/6000/6010 audio support"
-       depends on VIDEO_TM6000 && SND
-       select SND_PCM
-       ---help---
-         This is a video4linux driver for direct (DMA) audio for
-         TM5600/TM6000/TM6010 USB Devices.
-
-         To compile this driver as a module, choose M here: the
-         module will be called tm6000-alsa.
-
-config VIDEO_TM6000_DVB
-       tristate "DVB Support for tm6000 based TV cards"
-       depends on VIDEO_TM6000 && DVB_CORE && USB
-       select DVB_ZL10353
-       ---help---
-         This adds support for DVB cards based on the tm5600/tm6000 chip.
diff --git a/drivers/media/video/tm6000/Makefile b/drivers/media/video/tm6000/Makefile
deleted file mode 100644 (file)
index 1feb8c9..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-tm6000-y := tm6000-cards.o \
-                  tm6000-core.o  \
-                  tm6000-i2c.o   \
-                  tm6000-video.o \
-                  tm6000-stds.o \
-                  tm6000-input.o
-
-obj-$(CONFIG_VIDEO_TM6000) += tm6000.o
-obj-$(CONFIG_VIDEO_TM6000_ALSA) += tm6000-alsa.o
-obj-$(CONFIG_VIDEO_TM6000_DVB) += tm6000-dvb.o
-
-ccflags-y := -Idrivers/media/video
-ccflags-y += -Idrivers/media/tuners
-ccflags-y += -Idrivers/media/dvb-core
-ccflags-y += -Idrivers/media/dvb-frontends
diff --git a/drivers/media/video/tm6000/tm6000-alsa.c b/drivers/media/video/tm6000/tm6000-alsa.c
deleted file mode 100644 (file)
index bd07ec7..0000000
+++ /dev/null
@@ -1,528 +0,0 @@
-/*
- *
- *  Support for audio capture for tm5600/6000/6010
- *    (c) 2007-2008 Mauro Carvalho Chehab <mchehab@redhat.com>
- *
- *  Based on cx88-alsa.c
- *
- *  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/module.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/usb.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-#include <linux/delay.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/control.h>
-#include <sound/initval.h>
-
-
-#include "tm6000.h"
-#include "tm6000-regs.h"
-
-#undef dprintk
-
-#define dprintk(level, fmt, arg...) do {                                  \
-       if (debug >= level)                                                \
-               printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg); \
-       } while (0)
-
-/****************************************************************************
-                       Module global static vars
- ****************************************************************************/
-
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
-
-static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
-
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable tm6000x soundcard. default enabled.");
-
-module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for tm6000x capture interface(s).");
-
-
-/****************************************************************************
-                               Module macros
- ****************************************************************************/
-
-MODULE_DESCRIPTION("ALSA driver module for tm5600/tm6000/tm6010 based TV cards");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("{{Trident,tm5600},"
-                       "{{Trident,tm6000},"
-                       "{{Trident,tm6010}");
-static unsigned int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug messages");
-
-/****************************************************************************
-                       Module specific funtions
- ****************************************************************************/
-
-/*
- * BOARD Specific: Sets audio DMA
- */
-
-static int _tm6000_start_audio_dma(struct snd_tm6000_card *chip)
-{
-       struct tm6000_core *core = chip->core;
-
-       dprintk(1, "Starting audio DMA\n");
-
-       /* Enables audio */
-       tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x40, 0x40);
-
-       tm6000_set_audio_bitrate(core, 48000);
-
-       return 0;
-}
-
-/*
- * BOARD Specific: Resets audio DMA
- */
-static int _tm6000_stop_audio_dma(struct snd_tm6000_card *chip)
-{
-       struct tm6000_core *core = chip->core;
-
-       dprintk(1, "Stopping audio DMA\n");
-
-       /* Disables audio */
-       tm6000_set_reg_mask(core, TM6010_REQ07_RCC_ACTIVE_IF, 0x00, 0x40);
-
-       return 0;
-}
-
-static void dsp_buffer_free(struct snd_pcm_substream *substream)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-
-       dprintk(2, "Freeing buffer\n");
-
-       vfree(substream->runtime->dma_area);
-       substream->runtime->dma_area = NULL;
-       substream->runtime->dma_bytes = 0;
-}
-
-static int dsp_buffer_alloc(struct snd_pcm_substream *substream, int size)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-
-       dprintk(2, "Allocating buffer\n");
-
-       if (substream->runtime->dma_area) {
-               if (substream->runtime->dma_bytes > size)
-                       return 0;
-
-               dsp_buffer_free(substream);
-       }
-
-       substream->runtime->dma_area = vmalloc(size);
-       if (!substream->runtime->dma_area)
-               return -ENOMEM;
-
-       substream->runtime->dma_bytes = size;
-
-       return 0;
-}
-
-
-/****************************************************************************
-                               ALSA PCM Interface
- ****************************************************************************/
-
-/*
- * Digital hardware definition
- */
-#define DEFAULT_FIFO_SIZE      4096
-
-static struct snd_pcm_hardware snd_tm6000_digital_hw = {
-       .info = SNDRV_PCM_INFO_BATCH |
-               SNDRV_PCM_INFO_MMAP |
-               SNDRV_PCM_INFO_INTERLEAVED |
-               SNDRV_PCM_INFO_BLOCK_TRANSFER |
-               SNDRV_PCM_INFO_MMAP_VALID,
-       .formats = SNDRV_PCM_FMTBIT_S16_LE,
-
-       .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT,
-       .rate_min = 48000,
-       .rate_max = 48000,
-       .channels_min = 2,
-       .channels_max = 2,
-       .period_bytes_min = 64,
-       .period_bytes_max = 12544,
-       .periods_min = 2,
-       .periods_max = 98,
-       .buffer_bytes_max = 62720 * 8,
-};
-
-/*
- * audio pcm capture open callback
- */
-static int snd_tm6000_pcm_open(struct snd_pcm_substream *substream)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
-       int err;
-
-       err = snd_pcm_hw_constraint_pow2(runtime, 0,
-                                        SNDRV_PCM_HW_PARAM_PERIODS);
-       if (err < 0)
-               goto _error;
-
-       chip->substream = substream;
-
-       runtime->hw = snd_tm6000_digital_hw;
-       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
-
-       return 0;
-_error:
-       dprintk(1, "Error opening PCM!\n");
-       return err;
-}
-
-/*
- * audio close callback
- */
-static int snd_tm6000_close(struct snd_pcm_substream *substream)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-       struct tm6000_core *core = chip->core;
-
-       if (atomic_read(&core->stream_started) > 0) {
-               atomic_set(&core->stream_started, 0);
-               schedule_work(&core->wq_trigger);
-       }
-
-       return 0;
-}
-
-static int tm6000_fillbuf(struct tm6000_core *core, char *buf, int size)
-{
-       struct snd_tm6000_card *chip = core->adev;
-       struct snd_pcm_substream *substream = chip->substream;
-       struct snd_pcm_runtime *runtime;
-       int period_elapsed = 0;
-       unsigned int stride, buf_pos;
-       int length;
-
-       if (atomic_read(&core->stream_started) == 0)
-               return 0;
-
-       if (!size || !substream) {
-               dprintk(1, "substream was NULL\n");
-               return -EINVAL;
-       }
-
-       runtime = substream->runtime;
-       if (!runtime || !runtime->dma_area) {
-               dprintk(1, "runtime was NULL\n");
-               return -EINVAL;
-       }
-
-       buf_pos = chip->buf_pos;
-       stride = runtime->frame_bits >> 3;
-
-       if (stride == 0) {
-               dprintk(1, "stride is zero\n");
-               return -EINVAL;
-       }
-
-       length = size / stride;
-       if (length == 0) {
-               dprintk(1, "%s: length was zero\n", __func__);
-               return -EINVAL;
-       }
-
-       dprintk(1, "Copying %d bytes at %p[%d] - buf size=%d x %d\n", size,
-               runtime->dma_area, buf_pos,
-               (unsigned int)runtime->buffer_size, stride);
-
-       if (buf_pos + length >= runtime->buffer_size) {
-               unsigned int cnt = runtime->buffer_size - buf_pos;
-               memcpy(runtime->dma_area + buf_pos * stride, buf, cnt * stride);
-               memcpy(runtime->dma_area, buf + cnt * stride,
-                       length * stride - cnt * stride);
-       } else
-               memcpy(runtime->dma_area + buf_pos * stride, buf,
-                       length * stride);
-
-       snd_pcm_stream_lock(substream);
-
-       chip->buf_pos += length;
-       if (chip->buf_pos >= runtime->buffer_size)
-               chip->buf_pos -= runtime->buffer_size;
-
-       chip->period_pos += length;
-       if (chip->period_pos >= runtime->period_size) {
-               chip->period_pos -= runtime->period_size;
-               period_elapsed = 1;
-       }
-
-       snd_pcm_stream_unlock(substream);
-
-       if (period_elapsed)
-               snd_pcm_period_elapsed(substream);
-
-       return 0;
-}
-
-/*
- * hw_params callback
- */
-static int snd_tm6000_hw_params(struct snd_pcm_substream *substream,
-                             struct snd_pcm_hw_params *hw_params)
-{
-       int size, rc;
-
-       size = params_period_bytes(hw_params) * params_periods(hw_params);
-
-       rc = dsp_buffer_alloc(substream, size);
-       if (rc < 0)
-               return rc;
-
-       return 0;
-}
-
-/*
- * hw free callback
- */
-static int snd_tm6000_hw_free(struct snd_pcm_substream *substream)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-       struct tm6000_core *core = chip->core;
-
-       if (atomic_read(&core->stream_started) > 0) {
-               atomic_set(&core->stream_started, 0);
-               schedule_work(&core->wq_trigger);
-       }
-
-       dsp_buffer_free(substream);
-       return 0;
-}
-
-/*
- * prepare callback
- */
-static int snd_tm6000_prepare(struct snd_pcm_substream *substream)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-
-       chip->buf_pos = 0;
-       chip->period_pos = 0;
-
-       return 0;
-}
-
-
-/*
- * trigger callback
- */
-static void audio_trigger(struct work_struct *work)
-{
-       struct tm6000_core *core = container_of(work, struct tm6000_core,
-                                               wq_trigger);
-       struct snd_tm6000_card *chip = core->adev;
-
-       if (atomic_read(&core->stream_started)) {
-               dprintk(1, "starting capture");
-               _tm6000_start_audio_dma(chip);
-       } else {
-               dprintk(1, "stopping capture");
-               _tm6000_stop_audio_dma(chip);
-       }
-}
-
-static int snd_tm6000_card_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-       struct tm6000_core *core = chip->core;
-       int err = 0;
-
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
-       case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
-       case SNDRV_PCM_TRIGGER_START:
-               atomic_set(&core->stream_started, 1);
-               break;
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
-       case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
-       case SNDRV_PCM_TRIGGER_STOP:
-               atomic_set(&core->stream_started, 0);
-               break;
-       default:
-               err = -EINVAL;
-               break;
-       }
-       schedule_work(&core->wq_trigger);
-
-       return err;
-}
-/*
- * pointer callback
- */
-static snd_pcm_uframes_t snd_tm6000_pointer(struct snd_pcm_substream *substream)
-{
-       struct snd_tm6000_card *chip = snd_pcm_substream_chip(substream);
-
-       return chip->buf_pos;
-}
-
-static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
-                                            unsigned long offset)
-{
-       void *pageptr = subs->runtime->dma_area + offset;
-
-       return vmalloc_to_page(pageptr);
-}
-
-/*
- * operators
- */
-static struct snd_pcm_ops snd_tm6000_pcm_ops = {
-       .open = snd_tm6000_pcm_open,
-       .close = snd_tm6000_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_tm6000_hw_params,
-       .hw_free = snd_tm6000_hw_free,
-       .prepare = snd_tm6000_prepare,
-       .trigger = snd_tm6000_card_trigger,
-       .pointer = snd_tm6000_pointer,
-       .page = snd_pcm_get_vmalloc_page,
-};
-
-/*
- * create a PCM device
- */
-
-/* FIXME: Control interface - How to control volume/mute? */
-
-/****************************************************************************
-                       Basic Flow for Sound Devices
- ****************************************************************************/
-
-/*
- * Alsa Constructor - Component probe
- */
-static int tm6000_audio_init(struct tm6000_core *dev)
-{
-       struct snd_card         *card;
-       struct snd_tm6000_card  *chip;
-       int                     rc;
-       static int              devnr;
-       char                    component[14];
-       struct snd_pcm          *pcm;
-
-       if (!dev)
-               return 0;
-
-       if (devnr >= SNDRV_CARDS)
-               return -ENODEV;
-
-       if (!enable[devnr])
-               return -ENOENT;
-
-       rc = snd_card_create(index[devnr], "tm6000", THIS_MODULE, 0, &card);
-       if (rc < 0) {
-               snd_printk(KERN_ERR "cannot create card instance %d\n", devnr);
-               return rc;
-       }
-       strcpy(card->driver, "tm6000-alsa");
-       strcpy(card->shortname, "TM5600/60x0");
-       sprintf(card->longname, "TM5600/60x0 Audio at bus %d device %d",
-               dev->udev->bus->busnum, dev->udev->devnum);
-
-       sprintf(component, "USB%04x:%04x",
-               le16_to_cpu(dev->udev->descriptor.idVendor),
-               le16_to_cpu(dev->udev->descriptor.idProduct));
-       snd_component_add(card, component);
-       snd_card_set_dev(card, &dev->udev->dev);
-
-       chip = kzalloc(sizeof(struct snd_tm6000_card), GFP_KERNEL);
-       if (!chip) {
-               rc = -ENOMEM;
-               goto error;
-       }
-
-       chip->core = dev;
-       chip->card = card;
-       dev->adev = chip;
-       spin_lock_init(&chip->reg_lock);
-
-       rc = snd_pcm_new(card, "TM6000 Audio", 0, 0, 1, &pcm);
-       if (rc < 0)
-               goto error_chip;
-
-       pcm->info_flags = 0;
-       pcm->private_data = chip;
-       strcpy(pcm->name, "Trident TM5600/60x0");
-
-       snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_tm6000_pcm_ops);
-
-       INIT_WORK(&dev->wq_trigger, audio_trigger);
-       rc = snd_card_register(card);
-       if (rc < 0)
-               goto error_chip;
-
-       dprintk(1, "Registered audio driver for %s\n", card->longname);
-
-       return 0;
-
-error_chip:
-       kfree(chip);
-       dev->adev = NULL;
-error:
-       snd_card_free(card);
-       return rc;
-}
-
-static int tm6000_audio_fini(struct tm6000_core *dev)
-{
-       struct snd_tm6000_card  *chip = dev->adev;
-
-       if (!dev)
-               return 0;
-
-       if (!chip)
-               return 0;
-
-       if (!chip->card)
-               return 0;
-
-       snd_card_free(chip->card);
-       chip->card = NULL;
-       kfree(chip);
-       dev->adev = NULL;
-
-       return 0;
-}
-
-static struct tm6000_ops audio_ops = {
-       .type   = TM6000_AUDIO,
-       .name   = "TM6000 Audio Extension",
-       .init   = tm6000_audio_init,
-       .fini   = tm6000_audio_fini,
-       .fillbuf = tm6000_fillbuf,
-};
-
-static int __init tm6000_alsa_register(void)
-{
-       return tm6000_register_extension(&audio_ops);
-}
-
-static void __exit tm6000_alsa_unregister(void)
-{
-       tm6000_unregister_extension(&audio_ops);
-}
-
-module_init(tm6000_alsa_register);
-module_exit(tm6000_alsa_unregister);
diff --git a/drivers/media/video/tm6000/tm6000-cards.c b/drivers/media/video/tm6000/tm6000-cards.c
deleted file mode 100644 (file)
index 034659b..0000000
+++ /dev/null
@@ -1,1413 +0,0 @@
-/*
- *  tm6000-cards.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation version 2
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/usb.h>
-#include <linux/slab.h>
-#include <media/v4l2-common.h>
-#include <media/tuner.h>
-#include <media/tvaudio.h>
-#include <media/i2c-addr.h>
-#include <media/rc-map.h>
-
-#include "tm6000.h"
-#include "tm6000-regs.h"
-#include "tuner-xc2028.h"
-#include "xc5000.h"
-
-#define TM6000_BOARD_UNKNOWN                   0
-#define TM5600_BOARD_GENERIC                   1
-#define TM6000_BOARD_GENERIC                   2
-#define TM6010_BOARD_GENERIC                   3
-#define TM5600_BOARD_10MOONS_UT821             4
-#define TM5600_BOARD_10MOONS_UT330             5
-#define TM6000_BOARD_ADSTECH_DUAL_TV           6
-#define TM6000_BOARD_FREECOM_AND_SIMILAR       7
-#define TM6000_BOARD_ADSTECH_MINI_DUAL_TV      8
-#define TM6010_BOARD_HAUPPAUGE_900H            9
-#define TM6010_BOARD_BEHOLD_WANDER             10
-#define TM6010_BOARD_BEHOLD_VOYAGER            11
-#define TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE        12
-#define TM6010_BOARD_TWINHAN_TU501             13
-#define TM6010_BOARD_BEHOLD_WANDER_LITE                14
-#define TM6010_BOARD_BEHOLD_VOYAGER_LITE       15
-#define TM5600_BOARD_TERRATEC_GRABSTER         16
-
-#define is_generic(model) ((model == TM6000_BOARD_UNKNOWN) || \
-                          (model == TM5600_BOARD_GENERIC) || \
-                          (model == TM6000_BOARD_GENERIC) || \
-                          (model == TM6010_BOARD_GENERIC))
-
-#define TM6000_MAXBOARDS        16
-static unsigned int card[]     = {[0 ... (TM6000_MAXBOARDS - 1)] = UNSET };
-
-module_param_array(card,  int, NULL, 0444);
-
-static unsigned long tm6000_devused;
-
-
-struct tm6000_board {
-       char            *name;
-       char            eename[16];             /* EEPROM name */
-       unsigned        eename_size;            /* size of EEPROM name */
-       unsigned        eename_pos;             /* Position where it appears at ROM */
-
-       struct tm6000_capabilities caps;
-
-       enum            tm6000_devtype type;    /* variant of the chipset */
-       int             tuner_type;     /* type of the tuner */
-       int             tuner_addr;     /* tuner address */
-       int             demod_addr;     /* demodulator address */
-
-       struct tm6000_gpio gpio;
-
-       struct tm6000_input     vinput[3];
-       struct tm6000_input     rinput;
-
-       char            *ir_codes;
-};
-
-static struct tm6000_board tm6000_boards[] = {
-       [TM6000_BOARD_UNKNOWN] = {
-               .name         = "Unknown tm6000 video grabber",
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_eeprom     = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6000_GPIO_1,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM5600_BOARD_GENERIC] = {
-               .name         = "Generic tm5600 board",
-               .type         = TM5600,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_addr   = 0xc2 >> 1,
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_eeprom     = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6000_GPIO_1,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6000_BOARD_GENERIC] = {
-               .name         = "Generic tm6000 board",
-               .tuner_type   = TUNER_XC2028,
-               .tuner_addr   = 0xc2 >> 1,
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_eeprom     = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6000_GPIO_1,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6010_BOARD_GENERIC] = {
-               .name         = "Generic tm6010 board",
-               .type         = TM6010,
-               .tuner_type   = TUNER_XC2028,
-               .tuner_addr   = 0xc2 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_dvb        = 1,
-                       .has_zl10353    = 1,
-                       .has_eeprom     = 1,
-                       .has_remote     = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_2,
-                       .tuner_on       = TM6010_GPIO_3,
-                       .demod_reset    = TM6010_GPIO_1,
-                       .demod_on       = TM6010_GPIO_4,
-                       .power_led      = TM6010_GPIO_7,
-                       .dvb_led        = TM6010_GPIO_5,
-                       .ir             = TM6010_GPIO_0,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM5600_BOARD_10MOONS_UT821] = {
-               .name         = "10Moons UT 821",
-               .tuner_type   = TUNER_XC2028,
-               .eename       = { '1', '0', 'M', 'O', 'O', 'N', 'S', '5', '6', '0', '0', 0xff, 0x45, 0x5b},
-               .eename_size  = 14,
-               .eename_pos   = 0x14,
-               .type         = TM5600,
-               .tuner_addr   = 0xc2 >> 1,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_eeprom   = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6000_GPIO_1,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM5600_BOARD_10MOONS_UT330] = {
-               .name         = "10Moons UT 330",
-               .tuner_type   = TUNER_PHILIPS_FQ1216AME_MK4,
-               .tuner_addr   = 0xc8 >> 1,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_dvb      = 0,
-                       .has_zl10353  = 0,
-                       .has_eeprom   = 1,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6000_BOARD_ADSTECH_DUAL_TV] = {
-               .name         = "ADSTECH Dual TV USB",
-               .tuner_type   = TUNER_XC2028,
-               .tuner_addr   = 0xc8 >> 1,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_tda9874  = 1,
-                       .has_dvb      = 1,
-                       .has_zl10353  = 1,
-                       .has_eeprom   = 1,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6000_BOARD_FREECOM_AND_SIMILAR] = {
-               .name         = "Freecom Hybrid Stick / Moka DVB-T Receiver Dual",
-               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
-               .tuner_addr   = 0xc2 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_dvb      = 1,
-                       .has_zl10353  = 1,
-                       .has_eeprom   = 0,
-                       .has_remote   = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6000_GPIO_4,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6000_BOARD_ADSTECH_MINI_DUAL_TV] = {
-               .name         = "ADSTECH Mini Dual TV USB",
-               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
-               .tuner_addr   = 0xc8 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_dvb      = 1,
-                       .has_zl10353  = 1,
-                       .has_eeprom   = 0,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6000_GPIO_4,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6010_BOARD_HAUPPAUGE_900H] = {
-               .name         = "Hauppauge WinTV HVR-900H / WinTV USB2-Stick",
-               .eename       = { 'H', 0, 'V', 0, 'R', 0, '9', 0, '0', 0, '0', 0, 'H', 0 },
-               .eename_size  = 14,
-               .eename_pos   = 0x42,
-               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
-               .tuner_addr   = 0xc2 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .type         = TM6010,
-               .ir_codes = RC_MAP_HAUPPAUGE,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_dvb      = 1,
-                       .has_zl10353  = 1,
-                       .has_eeprom   = 1,
-                       .has_remote   = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_2,
-                       .tuner_on       = TM6010_GPIO_3,
-                       .demod_reset    = TM6010_GPIO_1,
-                       .demod_on       = TM6010_GPIO_4,
-                       .power_led      = TM6010_GPIO_7,
-                       .dvb_led        = TM6010_GPIO_5,
-                       .ir             = TM6010_GPIO_0,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6010_BOARD_BEHOLD_WANDER] = {
-               .name         = "Beholder Wander DVB-T/TV/FM USB2.0",
-               .tuner_type   = TUNER_XC5000,
-               .tuner_addr   = 0xc2 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .type         = TM6010,
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_dvb        = 1,
-                       .has_zl10353    = 1,
-                       .has_eeprom     = 1,
-                       .has_remote     = 1,
-                       .has_radio      = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_0,
-                       .demod_reset    = TM6010_GPIO_1,
-                       .power_led      = TM6010_GPIO_6,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-               .rinput = {
-                       .type   = TM6000_INPUT_RADIO,
-                       .amux   = TM6000_AMUX_ADC1,
-               },
-       },
-       [TM6010_BOARD_BEHOLD_VOYAGER] = {
-               .name         = "Beholder Voyager TV/FM USB2.0",
-               .tuner_type   = TUNER_XC5000,
-               .tuner_addr   = 0xc2 >> 1,
-               .type         = TM6010,
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_dvb        = 0,
-                       .has_zl10353    = 0,
-                       .has_eeprom     = 1,
-                       .has_remote     = 1,
-                       .has_radio      = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_0,
-                       .power_led      = TM6010_GPIO_6,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-               .rinput = {
-                       .type   = TM6000_INPUT_RADIO,
-                       .amux   = TM6000_AMUX_ADC1,
-               },
-       },
-       [TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE] = {
-               .name         = "Terratec Cinergy Hybrid XE / Cinergy Hybrid-Stick",
-               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
-               .tuner_addr   = 0xc2 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .type         = TM6010,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_dvb      = 1,
-                       .has_zl10353  = 1,
-                       .has_eeprom   = 1,
-                       .has_remote   = 1,
-                       .has_radio    = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_2,
-                       .tuner_on       = TM6010_GPIO_3,
-                       .demod_reset    = TM6010_GPIO_1,
-                       .demod_on       = TM6010_GPIO_4,
-                       .power_led      = TM6010_GPIO_7,
-                       .dvb_led        = TM6010_GPIO_5,
-                       .ir             = TM6010_GPIO_0,
-               },
-               .ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS,
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-               .rinput = {
-                       .type = TM6000_INPUT_RADIO,
-                       .amux = TM6000_AMUX_SIF1,
-               },
-       },
-       [TM5600_BOARD_TERRATEC_GRABSTER] = {
-               .name         = "Terratec Grabster AV 150/250 MX",
-               .type         = TM5600,
-               .tuner_type   = TUNER_ABSENT,
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_ADC1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6010_BOARD_TWINHAN_TU501] = {
-               .name         = "Twinhan TU501(704D1)",
-               .tuner_type   = TUNER_XC2028, /* has a XC3028 */
-               .tuner_addr   = 0xc2 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .type         = TM6010,
-               .caps = {
-                       .has_tuner    = 1,
-                       .has_dvb      = 1,
-                       .has_zl10353  = 1,
-                       .has_eeprom   = 1,
-                       .has_remote   = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_2,
-                       .tuner_on       = TM6010_GPIO_3,
-                       .demod_reset    = TM6010_GPIO_1,
-                       .demod_on       = TM6010_GPIO_4,
-                       .power_led      = TM6010_GPIO_7,
-                       .dvb_led        = TM6010_GPIO_5,
-                       .ir             = TM6010_GPIO_0,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       }, {
-                       .type   = TM6000_INPUT_COMPOSITE1,
-                       .vmux   = TM6000_VMUX_VIDEO_A,
-                       .amux   = TM6000_AMUX_ADC2,
-                       }, {
-                       .type   = TM6000_INPUT_SVIDEO,
-                       .vmux   = TM6000_VMUX_VIDEO_AB,
-                       .amux   = TM6000_AMUX_ADC2,
-                       },
-               },
-       },
-       [TM6010_BOARD_BEHOLD_WANDER_LITE] = {
-               .name         = "Beholder Wander Lite DVB-T/TV/FM USB2.0",
-               .tuner_type   = TUNER_XC5000,
-               .tuner_addr   = 0xc2 >> 1,
-               .demod_addr   = 0x1e >> 1,
-               .type         = TM6010,
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_dvb        = 1,
-                       .has_zl10353    = 1,
-                       .has_eeprom     = 1,
-                       .has_remote     = 0,
-                       .has_radio      = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_0,
-                       .demod_reset    = TM6010_GPIO_1,
-                       .power_led      = TM6010_GPIO_6,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       },
-               },
-               .rinput = {
-                       .type   = TM6000_INPUT_RADIO,
-                       .amux   = TM6000_AMUX_ADC1,
-               },
-       },
-       [TM6010_BOARD_BEHOLD_VOYAGER_LITE] = {
-               .name         = "Beholder Voyager Lite TV/FM USB2.0",
-               .tuner_type   = TUNER_XC5000,
-               .tuner_addr   = 0xc2 >> 1,
-               .type         = TM6010,
-               .caps = {
-                       .has_tuner      = 1,
-                       .has_dvb        = 0,
-                       .has_zl10353    = 0,
-                       .has_eeprom     = 1,
-                       .has_remote     = 0,
-                       .has_radio      = 1,
-               },
-               .gpio = {
-                       .tuner_reset    = TM6010_GPIO_0,
-                       .power_led      = TM6010_GPIO_6,
-               },
-               .vinput = { {
-                       .type   = TM6000_INPUT_TV,
-                       .vmux   = TM6000_VMUX_VIDEO_B,
-                       .amux   = TM6000_AMUX_SIF1,
-                       },
-               },
-               .rinput = {
-                       .type   = TM6000_INPUT_RADIO,
-                       .amux   = TM6000_AMUX_ADC1,
-               },
-       },
-};
-
-/* table of devices that work with this driver */
-static struct usb_device_id tm6000_id_table[] = {
-       { USB_DEVICE(0x6000, 0x0001), .driver_info = TM5600_BOARD_GENERIC },
-       { USB_DEVICE(0x6000, 0x0002), .driver_info = TM6010_BOARD_GENERIC },
-       { USB_DEVICE(0x06e1, 0xf332), .driver_info = TM6000_BOARD_ADSTECH_DUAL_TV },
-       { USB_DEVICE(0x14aa, 0x0620), .driver_info = TM6000_BOARD_FREECOM_AND_SIMILAR },
-       { USB_DEVICE(0x06e1, 0xb339), .driver_info = TM6000_BOARD_ADSTECH_MINI_DUAL_TV },
-       { USB_DEVICE(0x2040, 0x6600), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
-       { USB_DEVICE(0x2040, 0x6601), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
-       { USB_DEVICE(0x2040, 0x6610), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
-       { USB_DEVICE(0x2040, 0x6611), .driver_info = TM6010_BOARD_HAUPPAUGE_900H },
-       { USB_DEVICE(0x6000, 0xdec0), .driver_info = TM6010_BOARD_BEHOLD_WANDER },
-       { USB_DEVICE(0x6000, 0xdec1), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER },
-       { USB_DEVICE(0x0ccd, 0x0086), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE },
-       { USB_DEVICE(0x0ccd, 0x00A5), .driver_info = TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE },
-       { USB_DEVICE(0x0ccd, 0x0079), .driver_info = TM5600_BOARD_TERRATEC_GRABSTER },
-       { USB_DEVICE(0x13d3, 0x3240), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
-       { USB_DEVICE(0x13d3, 0x3241), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
-       { USB_DEVICE(0x13d3, 0x3243), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
-       { USB_DEVICE(0x13d3, 0x3264), .driver_info = TM6010_BOARD_TWINHAN_TU501 },
-       { USB_DEVICE(0x6000, 0xdec2), .driver_info = TM6010_BOARD_BEHOLD_WANDER_LITE },
-       { USB_DEVICE(0x6000, 0xdec3), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER_LITE },
-       { }
-};
-MODULE_DEVICE_TABLE(usb, tm6000_id_table);
-
-/* Control power led for show some activity */
-void tm6000_flash_led(struct tm6000_core *dev, u8 state)
-{
-       /* Power LED unconfigured */
-       if (!dev->gpio.power_led)
-               return;
-
-       /* ON Power LED */
-       if (state) {
-               switch (dev->model) {
-               case TM6010_BOARD_HAUPPAUGE_900H:
-               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
-               case TM6010_BOARD_TWINHAN_TU501:
-                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                               dev->gpio.power_led, 0x00);
-                       break;
-               case TM6010_BOARD_BEHOLD_WANDER:
-               case TM6010_BOARD_BEHOLD_VOYAGER:
-               case TM6010_BOARD_BEHOLD_WANDER_LITE:
-               case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
-                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                               dev->gpio.power_led, 0x01);
-                       break;
-               }
-       }
-       /* OFF Power LED */
-       else {
-               switch (dev->model) {
-               case TM6010_BOARD_HAUPPAUGE_900H:
-               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
-               case TM6010_BOARD_TWINHAN_TU501:
-                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                               dev->gpio.power_led, 0x01);
-                       break;
-               case TM6010_BOARD_BEHOLD_WANDER:
-               case TM6010_BOARD_BEHOLD_VOYAGER:
-               case TM6010_BOARD_BEHOLD_WANDER_LITE:
-               case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
-                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                               dev->gpio.power_led, 0x00);
-                       break;
-               }
-       }
-}
-
-/* Tuner callback to provide the proper gpio changes needed for xc5000 */
-int tm6000_xc5000_callback(void *ptr, int component, int command, int arg)
-{
-       int rc = 0;
-       struct tm6000_core *dev = ptr;
-
-       if (dev->tuner_type != TUNER_XC5000)
-               return 0;
-
-       switch (command) {
-       case XC5000_TUNER_RESET:
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                              dev->gpio.tuner_reset, 0x01);
-               msleep(15);
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                              dev->gpio.tuner_reset, 0x00);
-               msleep(15);
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                              dev->gpio.tuner_reset, 0x01);
-               break;
-       }
-       return rc;
-}
-EXPORT_SYMBOL_GPL(tm6000_xc5000_callback);
-
-/* Tuner callback to provide the proper gpio changes needed for xc2028 */
-
-int tm6000_tuner_callback(void *ptr, int component, int command, int arg)
-{
-       int rc = 0;
-       struct tm6000_core *dev = ptr;
-
-       if (dev->tuner_type != TUNER_XC2028)
-               return 0;
-
-       switch (command) {
-       case XC2028_RESET_CLK:
-               tm6000_ir_wait(dev, 0);
-
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT,
-                                       0x02, arg);
-               msleep(10);
-               rc = tm6000_i2c_reset(dev, 10);
-               break;
-       case XC2028_TUNER_RESET:
-               /* Reset codes during load firmware */
-               switch (arg) {
-               case 0:
-                       /* newer tuner can faster reset */
-                       switch (dev->model) {
-                       case TM5600_BOARD_10MOONS_UT821:
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x01);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              0x300, 0x01);
-                               msleep(10);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x00);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              0x300, 0x00);
-                               msleep(10);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x01);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              0x300, 0x01);
-                               break;
-                       case TM6010_BOARD_HAUPPAUGE_900H:
-                       case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
-                       case TM6010_BOARD_TWINHAN_TU501:
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x01);
-                               msleep(60);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x00);
-                               msleep(75);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x01);
-                               msleep(60);
-                               break;
-                       default:
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x00);
-                               msleep(130);
-                               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                              dev->gpio.tuner_reset, 0x01);
-                               msleep(130);
-                               break;
-                       }
-
-                       tm6000_ir_wait(dev, 1);
-                       break;
-               case 1:
-                       tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT,
-                                               0x02, 0x01);
-                       msleep(10);
-                       break;
-               case 2:
-                       rc = tm6000_i2c_reset(dev, 100);
-                       break;
-               }
-               break;
-       case XC2028_I2C_FLUSH:
-               tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
-               tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
-               break;
-       }
-       return rc;
-}
-EXPORT_SYMBOL_GPL(tm6000_tuner_callback);
-
-int tm6000_cards_setup(struct tm6000_core *dev)
-{
-       /*
-        * Board-specific initialization sequence. Handles all GPIO
-        * initialization sequences that are board-specific.
-        * Up to now, all found devices use GPIO1 and GPIO4 at the same way.
-        * Probably, they're all based on some reference device. Due to that,
-        * there's a common routine at the end to handle those GPIO's. Devices
-        * that use different pinups or init sequences can just return at
-        * the board-specific session.
-        */
-       switch (dev->model) {
-       case TM6010_BOARD_HAUPPAUGE_900H:
-       case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
-       case TM6010_BOARD_TWINHAN_TU501:
-       case TM6010_BOARD_GENERIC:
-               /* Turn xceive 3028 on */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.tuner_on, 0x01);
-               msleep(15);
-               /* Turn zarlink zl10353 on */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00);
-               msleep(15);
-               /* Reset zarlink zl10353 */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00);
-               msleep(50);
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01);
-               msleep(15);
-               /* Turn zarlink zl10353 off */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x01);
-               msleep(15);
-               /* ir ? */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.ir, 0x01);
-               msleep(15);
-               /* Power led on (blue) */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x00);
-               msleep(15);
-               /* DVB led off (orange) */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.dvb_led, 0x01);
-               msleep(15);
-               /* Turn zarlink zl10353 on */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_on, 0x00);
-               msleep(15);
-               break;
-       case TM6010_BOARD_BEHOLD_WANDER:
-       case TM6010_BOARD_BEHOLD_WANDER_LITE:
-               /* Power led on (blue) */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01);
-               msleep(15);
-               /* Reset zarlink zl10353 */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x00);
-               msleep(50);
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.demod_reset, 0x01);
-               msleep(15);
-               break;
-       case TM6010_BOARD_BEHOLD_VOYAGER:
-       case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
-               /* Power led on (blue) */
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, dev->gpio.power_led, 0x01);
-               msleep(15);
-               break;
-       default:
-               break;
-       }
-
-       /*
-        * Default initialization. Most of the devices seem to use GPIO1
-        * and GPIO4.on the same way, so, this handles the common sequence
-        * used by most devices.
-        * If a device uses a different sequence or different GPIO pins for
-        * reset, just add the code at the board-specific part
-        */
-
-       if (dev->gpio.tuner_reset) {
-               int rc;
-               int i;
-
-               for (i = 0; i < 2; i++) {
-                       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                               dev->gpio.tuner_reset, 0x00);
-                       if (rc < 0) {
-                               printk(KERN_ERR "Error %i doing tuner reset\n", rc);
-                               return rc;
-                       }
-
-                       msleep(10); /* Just to be conservative */
-                       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                                               dev->gpio.tuner_reset, 0x01);
-                       if (rc < 0) {
-                               printk(KERN_ERR "Error %i doing tuner reset\n", rc);
-                               return rc;
-                       }
-               }
-       } else {
-               printk(KERN_ERR "Tuner reset is not configured\n");
-               return -1;
-       }
-
-       msleep(50);
-
-       return 0;
-};
-
-static void tm6000_config_tuner(struct tm6000_core *dev)
-{
-       struct tuner_setup tun_setup;
-
-       /* Load tuner module */
-       v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-               "tuner", dev->tuner_addr, NULL);
-
-       memset(&tun_setup, 0, sizeof(tun_setup));
-       tun_setup.type = dev->tuner_type;
-       tun_setup.addr = dev->tuner_addr;
-
-       tun_setup.mode_mask = 0;
-       if (dev->caps.has_tuner)
-               tun_setup.mode_mask |= (T_ANALOG_TV | T_RADIO);
-
-       switch (dev->tuner_type) {
-       case TUNER_XC2028:
-               tun_setup.tuner_callback = tm6000_tuner_callback;
-               break;
-       case TUNER_XC5000:
-               tun_setup.tuner_callback = tm6000_xc5000_callback;
-               break;
-       }
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_type_addr, &tun_setup);
-
-       switch (dev->tuner_type) {
-       case TUNER_XC2028: {
-               struct v4l2_priv_tun_config xc2028_cfg;
-               struct xc2028_ctrl ctl;
-
-               memset(&xc2028_cfg, 0, sizeof(xc2028_cfg));
-               memset(&ctl, 0, sizeof(ctl));
-
-               ctl.demod = XC3028_FE_ZARLINK456;
-
-               xc2028_cfg.tuner = TUNER_XC2028;
-               xc2028_cfg.priv  = &ctl;
-
-               switch (dev->model) {
-               case TM6010_BOARD_HAUPPAUGE_900H:
-               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
-               case TM6010_BOARD_TWINHAN_TU501:
-                       ctl.max_len = 80;
-                       ctl.fname = "xc3028L-v36.fw";
-                       break;
-               default:
-                       if (dev->dev_type == TM6010)
-                               ctl.fname = "xc3028-v27.fw";
-                       else
-                               ctl.fname = "xc3028-v24.fw";
-               }
-
-               printk(KERN_INFO "Setting firmware parameters for xc2028\n");
-               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config,
-                                    &xc2028_cfg);
-
-               }
-               break;
-       case TUNER_XC5000:
-               {
-               struct v4l2_priv_tun_config  xc5000_cfg;
-               struct xc5000_config ctl = {
-                       .i2c_address = dev->tuner_addr,
-                       .if_khz      = 4570,
-                       .radio_input = XC5000_RADIO_FM1_MONO,
-                       };
-
-               xc5000_cfg.tuner = TUNER_XC5000;
-               xc5000_cfg.priv  = &ctl;
-
-               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_config,
-                                    &xc5000_cfg);
-               }
-               break;
-       default:
-               printk(KERN_INFO "Unknown tuner type. Tuner is not configured.\n");
-               break;
-       }
-}
-
-static int fill_board_specific_data(struct tm6000_core *dev)
-{
-       int rc;
-
-       dev->dev_type   = tm6000_boards[dev->model].type;
-       dev->tuner_type = tm6000_boards[dev->model].tuner_type;
-       dev->tuner_addr = tm6000_boards[dev->model].tuner_addr;
-
-       dev->gpio = tm6000_boards[dev->model].gpio;
-
-       dev->ir_codes = tm6000_boards[dev->model].ir_codes;
-
-       dev->demod_addr = tm6000_boards[dev->model].demod_addr;
-
-       dev->caps = tm6000_boards[dev->model].caps;
-
-       dev->vinput[0] = tm6000_boards[dev->model].vinput[0];
-       dev->vinput[1] = tm6000_boards[dev->model].vinput[1];
-       dev->vinput[2] = tm6000_boards[dev->model].vinput[2];
-       dev->rinput = tm6000_boards[dev->model].rinput;
-
-       /* setup per-model quirks */
-       switch (dev->model) {
-       case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
-       case TM6010_BOARD_HAUPPAUGE_900H:
-               dev->quirks |= TM6000_QUIRK_NO_USB_DELAY;
-               break;
-
-       default:
-               break;
-       }
-
-       /* initialize hardware */
-       rc = tm6000_init(dev);
-       if (rc < 0)
-               return rc;
-
-       return v4l2_device_register(&dev->udev->dev, &dev->v4l2_dev);
-}
-
-
-static void use_alternative_detection_method(struct tm6000_core *dev)
-{
-       int i, model = -1;
-
-       if (!dev->eedata_size)
-               return;
-
-       for (i = 0; i < ARRAY_SIZE(tm6000_boards); i++) {
-               if (!tm6000_boards[i].eename_size)
-                       continue;
-               if (dev->eedata_size < tm6000_boards[i].eename_pos +
-                                      tm6000_boards[i].eename_size)
-                       continue;
-
-               if (!memcmp(&dev->eedata[tm6000_boards[i].eename_pos],
-                           tm6000_boards[i].eename,
-                           tm6000_boards[i].eename_size)) {
-                       model = i;
-                       break;
-               }
-       }
-       if (model < 0) {
-               printk(KERN_INFO "Device has eeprom but is currently unknown\n");
-               return;
-       }
-
-       dev->model = model;
-
-       printk(KERN_INFO "Device identified via eeprom as %s (type = %d)\n",
-              tm6000_boards[model].name, model);
-}
-
-#if defined(CONFIG_MODULES) && defined(MODULE)
-static void request_module_async(struct work_struct *work)
-{
-       struct tm6000_core *dev = container_of(work, struct tm6000_core,
-                                              request_module_wk);
-
-       request_module("tm6000-alsa");
-
-       if (dev->caps.has_dvb)
-               request_module("tm6000-dvb");
-}
-
-static void request_modules(struct tm6000_core *dev)
-{
-       INIT_WORK(&dev->request_module_wk, request_module_async);
-       schedule_work(&dev->request_module_wk);
-}
-
-static void flush_request_modules(struct tm6000_core *dev)
-{
-       flush_work_sync(&dev->request_module_wk);
-}
-#else
-#define request_modules(dev)
-#define flush_request_modules(dev)
-#endif /* CONFIG_MODULES */
-
-static int tm6000_init_dev(struct tm6000_core *dev)
-{
-       struct v4l2_frequency f;
-       int rc = 0;
-
-       mutex_init(&dev->lock);
-       mutex_lock(&dev->lock);
-
-       if (!is_generic(dev->model)) {
-               rc = fill_board_specific_data(dev);
-               if (rc < 0)
-                       goto err;
-
-               /* register i2c bus */
-               rc = tm6000_i2c_register(dev);
-               if (rc < 0)
-                       goto err;
-       } else {
-               /* register i2c bus */
-               rc = tm6000_i2c_register(dev);
-               if (rc < 0)
-                       goto err;
-
-               use_alternative_detection_method(dev);
-
-               rc = fill_board_specific_data(dev);
-               if (rc < 0)
-                       goto err;
-       }
-
-       /* Default values for STD and resolutions */
-       dev->width = 720;
-       dev->height = 480;
-       dev->norm = V4L2_STD_PAL_M;
-
-       /* Configure tuner */
-       tm6000_config_tuner(dev);
-
-       /* Set video standard */
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
-
-       /* Set tuner frequency - also loads firmware on xc2028/xc3028 */
-       f.tuner = 0;
-       f.type = V4L2_TUNER_ANALOG_TV;
-       f.frequency = 3092;     /* 193.25 MHz */
-       dev->freq = f.frequency;
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
-
-       if (dev->caps.has_tda9874)
-               v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
-                       "tvaudio", I2C_ADDR_TDA9874, NULL);
-
-       /* register and initialize V4L2 */
-       rc = tm6000_v4l2_register(dev);
-       if (rc < 0)
-               goto err;
-
-       tm6000_add_into_devlist(dev);
-       tm6000_init_extension(dev);
-
-       tm6000_ir_init(dev);
-
-       request_modules(dev);
-
-       mutex_unlock(&dev->lock);
-       return 0;
-
-err:
-       mutex_unlock(&dev->lock);
-       return rc;
-}
-
-/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
-#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
-
-static void get_max_endpoint(struct usb_device *udev,
-                            struct usb_host_interface *alt,
-                            char *msgtype,
-                            struct usb_host_endpoint *curr_e,
-                            struct tm6000_endpoint *tm_ep)
-{
-       u16 tmp = le16_to_cpu(curr_e->desc.wMaxPacketSize);
-       unsigned int size = tmp & 0x7ff;
-
-       if (udev->speed == USB_SPEED_HIGH)
-               size = size * hb_mult(tmp);
-
-       if (size > tm_ep->maxsize) {
-               tm_ep->endp = curr_e;
-               tm_ep->maxsize = size;
-               tm_ep->bInterfaceNumber = alt->desc.bInterfaceNumber;
-               tm_ep->bAlternateSetting = alt->desc.bAlternateSetting;
-
-               printk(KERN_INFO "tm6000: %s endpoint: 0x%02x (max size=%u bytes)\n",
-                                       msgtype, curr_e->desc.bEndpointAddress,
-                                       size);
-       }
-}
-
-/*
- * tm6000_usb_probe()
- * checks for supported devices
- */
-static int tm6000_usb_probe(struct usb_interface *interface,
-                           const struct usb_device_id *id)
-{
-       struct usb_device *usbdev;
-       struct tm6000_core *dev = NULL;
-       int i, rc = 0;
-       int nr = 0;
-       char *speed;
-
-       usbdev = usb_get_dev(interface_to_usbdev(interface));
-
-       /* Selects the proper interface */
-       rc = usb_set_interface(usbdev, 0, 1);
-       if (rc < 0)
-               goto err;
-
-       /* Check to see next free device and mark as used */
-       nr = find_first_zero_bit(&tm6000_devused, TM6000_MAXBOARDS);
-       if (nr >= TM6000_MAXBOARDS) {
-               printk(KERN_ERR "tm6000: Supports only %i tm60xx boards.\n", TM6000_MAXBOARDS);
-               usb_put_dev(usbdev);
-               return -ENOMEM;
-       }
-
-       /* Create and initialize dev struct */
-       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL) {
-               printk(KERN_ERR "tm6000" ": out of memory!\n");
-               usb_put_dev(usbdev);
-               return -ENOMEM;
-       }
-       spin_lock_init(&dev->slock);
-       mutex_init(&dev->usb_lock);
-
-       /* Increment usage count */
-       set_bit(nr, &tm6000_devused);
-       snprintf(dev->name, 29, "tm6000 #%d", nr);
-
-       dev->model = id->driver_info;
-       if (card[nr] < ARRAY_SIZE(tm6000_boards))
-               dev->model = card[nr];
-
-       dev->udev = usbdev;
-       dev->devno = nr;
-
-       switch (usbdev->speed) {
-       case USB_SPEED_LOW:
-               speed = "1.5";
-               break;
-       case USB_SPEED_UNKNOWN:
-       case USB_SPEED_FULL:
-               speed = "12";
-               break;
-       case USB_SPEED_HIGH:
-               speed = "480";
-               break;
-       default:
-               speed = "unknown";
-       }
-
-       /* Get endpoints */
-       for (i = 0; i < interface->num_altsetting; i++) {
-               int ep;
-
-               for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) {
-                       struct usb_host_endpoint        *e;
-                       int dir_out;
-
-                       e = &interface->altsetting[i].endpoint[ep];
-
-                       dir_out = ((e->desc.bEndpointAddress &
-                                       USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
-
-                       printk(KERN_INFO "tm6000: alt %d, interface %i, class %i\n",
-                              i,
-                              interface->altsetting[i].desc.bInterfaceNumber,
-                              interface->altsetting[i].desc.bInterfaceClass);
-
-                       switch (e->desc.bmAttributes) {
-                       case USB_ENDPOINT_XFER_BULK:
-                               if (!dir_out) {
-                                       get_max_endpoint(usbdev,
-                                                        &interface->altsetting[i],
-                                                        "Bulk IN", e,
-                                                        &dev->bulk_in);
-                               } else {
-                                       get_max_endpoint(usbdev,
-                                                        &interface->altsetting[i],
-                                                        "Bulk OUT", e,
-                                                        &dev->bulk_out);
-                               }
-                               break;
-                       case USB_ENDPOINT_XFER_ISOC:
-                               if (!dir_out) {
-                                       get_max_endpoint(usbdev,
-                                                        &interface->altsetting[i],
-                                                        "ISOC IN", e,
-                                                        &dev->isoc_in);
-                               } else {
-                                       get_max_endpoint(usbdev,
-                                                        &interface->altsetting[i],
-                                                        "ISOC OUT", e,
-                                                        &dev->isoc_out);
-                               }
-                               break;
-                       case USB_ENDPOINT_XFER_INT:
-                               if (!dir_out) {
-                                       get_max_endpoint(usbdev,
-                                                       &interface->altsetting[i],
-                                                       "INT IN", e,
-                                                       &dev->int_in);
-                               } else {
-                                       get_max_endpoint(usbdev,
-                                                       &interface->altsetting[i],
-                                                       "INT OUT", e,
-                                                       &dev->int_out);
-                               }
-                               break;
-                       }
-               }
-       }
-
-
-       printk(KERN_INFO "tm6000: New video device @ %s Mbps (%04x:%04x, ifnum %d)\n",
-               speed,
-               le16_to_cpu(dev->udev->descriptor.idVendor),
-               le16_to_cpu(dev->udev->descriptor.idProduct),
-               interface->altsetting->desc.bInterfaceNumber);
-
-/* check if the the device has the iso in endpoint at the correct place */
-       if (!dev->isoc_in.endp) {
-               printk(KERN_ERR "tm6000: probing error: no IN ISOC endpoint!\n");
-               rc = -ENODEV;
-
-               goto err;
-       }
-
-       /* save our data pointer in this interface device */
-       usb_set_intfdata(interface, dev);
-
-       printk(KERN_INFO "tm6000: Found %s\n", tm6000_boards[dev->model].name);
-
-       rc = tm6000_init_dev(dev);
-       if (rc < 0)
-               goto err;
-
-       return 0;
-
-err:
-       printk(KERN_ERR "tm6000: Error %d while registering\n", rc);
-
-       clear_bit(nr, &tm6000_devused);
-       usb_put_dev(usbdev);
-
-       kfree(dev);
-       return rc;
-}
-
-/*
- * tm6000_usb_disconnect()
- * called when the device gets diconencted
- * video device will be unregistered on v4l2_close in case it is still open
- */
-static void tm6000_usb_disconnect(struct usb_interface *interface)
-{
-       struct tm6000_core *dev = usb_get_intfdata(interface);
-       usb_set_intfdata(interface, NULL);
-
-       if (!dev)
-               return;
-
-       printk(KERN_INFO "tm6000: disconnecting %s\n", dev->name);
-
-       flush_request_modules(dev);
-
-       tm6000_ir_fini(dev);
-
-       if (dev->gpio.power_led) {
-               switch (dev->model) {
-               case TM6010_BOARD_HAUPPAUGE_900H:
-               case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE:
-               case TM6010_BOARD_TWINHAN_TU501:
-                       /* Power led off */
-                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                               dev->gpio.power_led, 0x01);
-                       msleep(15);
-                       break;
-               case TM6010_BOARD_BEHOLD_WANDER:
-               case TM6010_BOARD_BEHOLD_VOYAGER:
-               case TM6010_BOARD_BEHOLD_WANDER_LITE:
-               case TM6010_BOARD_BEHOLD_VOYAGER_LITE:
-                       /* Power led off */
-                       tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                               dev->gpio.power_led, 0x00);
-                       msleep(15);
-                       break;
-               }
-       }
-       tm6000_v4l2_unregister(dev);
-
-       tm6000_i2c_unregister(dev);
-
-       v4l2_device_unregister(&dev->v4l2_dev);
-
-       dev->state |= DEV_DISCONNECTED;
-
-       usb_put_dev(dev->udev);
-
-       tm6000_close_extension(dev);
-       tm6000_remove_from_devlist(dev);
-
-       clear_bit(dev->devno, &tm6000_devused);
-       kfree(dev);
-}
-
-static struct usb_driver tm6000_usb_driver = {
-               .name = "tm6000",
-               .probe = tm6000_usb_probe,
-               .disconnect = tm6000_usb_disconnect,
-               .id_table = tm6000_id_table,
-};
-
-module_usb_driver(tm6000_usb_driver);
-
-MODULE_DESCRIPTION("Trident TVMaster TM5600/TM6000/TM6010 USB2 adapter");
-MODULE_AUTHOR("Mauro Carvalho Chehab");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/tm6000/tm6000-core.c b/drivers/media/video/tm6000/tm6000-core.c
deleted file mode 100644 (file)
index 22cc011..0000000
+++ /dev/null
@@ -1,935 +0,0 @@
-/*
- *  tm6000-core.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
- *      - DVB-T support
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation version 2
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/i2c.h>
-#include "tm6000.h"
-#include "tm6000-regs.h"
-#include <media/v4l2-common.h>
-#include <media/tuner.h>
-
-#define USB_TIMEOUT    (5 * HZ) /* ms */
-
-int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req,
-                         u16 value, u16 index, u8 *buf, u16 len)
-{
-       int          ret, i;
-       unsigned int pipe;
-       u8           *data = NULL;
-       int delay = 5000;
-
-       mutex_lock(&dev->usb_lock);
-
-       if (len)
-               data = kzalloc(len, GFP_KERNEL);
-
-       if (req_type & USB_DIR_IN)
-               pipe = usb_rcvctrlpipe(dev->udev, 0);
-       else {
-               pipe = usb_sndctrlpipe(dev->udev, 0);
-               memcpy(data, buf, len);
-       }
-
-       if (tm6000_debug & V4L2_DEBUG_I2C) {
-               printk(KERN_DEBUG "(dev %p, pipe %08x): ", dev->udev, pipe);
-
-               printk(KERN_CONT "%s: %02x %02x %02x %02x %02x %02x %02x %02x ",
-                       (req_type & USB_DIR_IN) ? " IN" : "OUT",
-                       req_type, req, value&0xff, value>>8, index&0xff,
-                       index>>8, len&0xff, len>>8);
-
-               if (!(req_type & USB_DIR_IN)) {
-                       printk(KERN_CONT ">>> ");
-                       for (i = 0; i < len; i++)
-                               printk(KERN_CONT " %02x", buf[i]);
-                       printk(KERN_CONT "\n");
-               }
-       }
-
-       ret = usb_control_msg(dev->udev, pipe, req, req_type, value, index,
-                             data, len, USB_TIMEOUT);
-
-       if (req_type &  USB_DIR_IN)
-               memcpy(buf, data, len);
-
-       if (tm6000_debug & V4L2_DEBUG_I2C) {
-               if (ret < 0) {
-                       if (req_type &  USB_DIR_IN)
-                               printk(KERN_DEBUG "<<< (len=%d)\n", len);
-
-                       printk(KERN_CONT "%s: Error #%d\n", __func__, ret);
-               } else if (req_type &  USB_DIR_IN) {
-                       printk(KERN_CONT "<<< ");
-                       for (i = 0; i < len; i++)
-                               printk(KERN_CONT " %02x", buf[i]);
-                       printk(KERN_CONT "\n");
-               }
-       }
-
-       kfree(data);
-
-       if (dev->quirks & TM6000_QUIRK_NO_USB_DELAY)
-               delay = 0;
-
-       if (req == REQ_16_SET_GET_I2C_WR1_RDN && !(req_type & USB_DIR_IN)) {
-               unsigned int tsleep;
-               /* Calculate delay time, 14000us for 64 bytes */
-               tsleep = (len * 200) + 200;
-               if (tsleep < delay)
-                       tsleep = delay;
-               usleep_range(tsleep, tsleep + 1000);
-       }
-       else if (delay)
-               usleep_range(delay, delay + 1000);
-
-       mutex_unlock(&dev->usb_lock);
-       return ret;
-}
-
-int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index)
-{
-       return
-               tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
-                                     req, value, index, NULL, 0);
-}
-EXPORT_SYMBOL_GPL(tm6000_set_reg);
-
-int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index)
-{
-       int rc;
-       u8 buf[1];
-
-       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
-                                       value, index, buf, 1);
-
-       if (rc < 0)
-               return rc;
-
-       return *buf;
-}
-EXPORT_SYMBOL_GPL(tm6000_get_reg);
-
-int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
-                                               u16 index, u16 mask)
-{
-       int rc;
-       u8 buf[1];
-       u8 new_index;
-
-       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
-                                       value, 0, buf, 1);
-
-       if (rc < 0)
-               return rc;
-
-       new_index = (buf[0] & ~mask) | (index & mask);
-
-       if (new_index == buf[0])
-               return 0;
-
-       return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR,
-                                     req, value, new_index, NULL, 0);
-}
-EXPORT_SYMBOL_GPL(tm6000_set_reg_mask);
-
-int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index)
-{
-       int rc;
-       u8 buf[2];
-
-       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
-                                       value, index, buf, 2);
-
-       if (rc < 0)
-               return rc;
-
-       return buf[1]|buf[0]<<8;
-}
-
-int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index)
-{
-       int rc;
-       u8 buf[4];
-
-       rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req,
-                                       value, index, buf, 4);
-
-       if (rc < 0)
-               return rc;
-
-       return buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24;
-}
-
-int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep)
-{
-       int rc;
-
-       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 0);
-       if (rc < 0)
-               return rc;
-
-       msleep(tsleep);
-
-       rc = tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN, TM6000_GPIO_CLK, 1);
-       msleep(tsleep);
-
-       return rc;
-}
-
-void tm6000_set_fourcc_format(struct tm6000_core *dev)
-{
-       if (dev->dev_type == TM6010) {
-               int val;
-
-               val = tm6000_get_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, 0) & 0xfc;
-               if (dev->fourcc == V4L2_PIX_FMT_UYVY)
-                       tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val);
-               else
-                       tm6000_set_reg(dev, TM6010_REQ07_RCC_ACTIVE_IF, val | 1);
-       } else {
-               if (dev->fourcc == V4L2_PIX_FMT_UYVY)
-                       tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
-               else
-                       tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0x90);
-       }
-}
-
-static void tm6000_set_vbi(struct tm6000_core *dev)
-{
-       /*
-        * FIXME:
-        * VBI lines and start/end are different between 60Hz and 50Hz
-        * So, it is very likely that we need to change the config to
-        * something that takes it into account, doing something different
-        * if (dev->norm & V4L2_STD_525_60)
-        */
-
-       if (dev->dev_type == TM6010) {
-               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
-               tm6000_set_reg(dev, TM6010_REQ07_R41_TELETEXT_VBI_CODE1, 0x27);
-               tm6000_set_reg(dev, TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55);
-               tm6000_set_reg(dev, TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7, 0x66);
-               tm6000_set_reg(dev, TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8, 0x66);
-               tm6000_set_reg(dev, TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22, 0x66);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23, 0x00);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES, 0x00);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN, 0x00);
-               tm6000_set_reg(dev,
-                       TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02);
-               tm6000_set_reg(dev, TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35);
-               tm6000_set_reg(dev, TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0);
-               tm6000_set_reg(dev, TM6010_REQ07_R5A_VBI_TELETEXT_DTO1, 0x11);
-               tm6000_set_reg(dev, TM6010_REQ07_R5B_VBI_TELETEXT_DTO0, 0x4c);
-               tm6000_set_reg(dev, TM6010_REQ07_R40_TELETEXT_VBI_CODE0, 0x01);
-               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00);
-       }
-}
-
-int tm6000_init_analog_mode(struct tm6000_core *dev)
-{
-       struct v4l2_frequency f;
-
-       if (dev->dev_type == TM6010) {
-               u8 active = TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE;
-
-               if (!dev->radio)
-                       active |= TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE;
-
-               /* Enable video and audio */
-               tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
-                                                       active, 0x60);
-               /* Disable TS input */
-               tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
-                                                       0x00, 0x40);
-       } else {
-               /* Enables soft reset */
-               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
-
-               if (dev->scaler)
-                       /* Disable Hfilter and Enable TS Drop err */
-                       tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x20);
-               else    /* Enable Hfilter and disable TS Drop err */
-                       tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x80);
-
-               tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x88);
-               tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x23);
-               tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xc0);
-               tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xd8);
-               tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x06);
-               tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f);
-
-               /* AP Software reset */
-               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08);
-               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00);
-
-               tm6000_set_fourcc_format(dev);
-
-               /* Disables soft reset */
-               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x00);
-       }
-       msleep(20);
-
-       /* Tuner firmware can now be loaded */
-
-       /*
-        * FIXME: This is a hack! xc3028 "sleeps" when no channel is detected
-        * for more than a few seconds. Not sure why, as this behavior does
-        * not happen on other devices with xc3028. So, I suspect that it
-        * is yet another bug at tm6000. After start sleeping, decoding
-        * doesn't start automatically. Instead, it requires some
-        * I2C commands to wake it up. As we want to have image at the
-        * beginning, we needed to add this hack. The better would be to
-        * discover some way to make tm6000 to wake up without this hack.
-        */
-       f.frequency = dev->freq;
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, &f);
-
-       msleep(100);
-       tm6000_set_standard(dev);
-       tm6000_set_vbi(dev);
-       tm6000_set_audio_bitrate(dev, 48000);
-
-       /* switch dvb led off */
-       if (dev->gpio.dvb_led) {
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                       dev->gpio.dvb_led, 0x01);
-       }
-
-       return 0;
-}
-
-int tm6000_init_digital_mode(struct tm6000_core *dev)
-{
-       if (dev->dev_type == TM6010) {
-               /* Disable video and audio */
-               tm6000_set_reg_mask(dev, TM6010_REQ07_RCC_ACTIVE_IF,
-                               0x00, 0x60);
-               /* Enable TS input */
-               tm6000_set_reg_mask(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE,
-                               0x40, 0x40);
-               /* all power down, but not the digital data port */
-               tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0x28);
-               tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xfc);
-               tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0xff);
-       } else  {
-               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x08);
-               tm6000_set_reg(dev, TM6010_REQ07_RFF_SOFT_RESET, 0x00);
-               tm6000_set_reg(dev, TM6010_REQ07_R3F_RESET, 0x01);
-               tm6000_set_reg(dev, TM6000_REQ07_RDF_PWDOWN_ACLK, 0x08);
-               tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c);
-               tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff);
-               tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0xd8);
-               tm6000_set_reg(dev, TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x40);
-               tm6000_set_reg(dev, TM6010_REQ07_RC1_TRESHOLD, 0xd0);
-               tm6000_set_reg(dev, TM6010_REQ07_RC3_HSTART1, 0x09);
-               tm6000_set_reg(dev, TM6000_REQ07_RDA_CLK_SEL, 0x37);
-               tm6000_set_reg(dev, TM6010_REQ07_RD1_ADDR_FOR_REQ1, 0xd8);
-               tm6000_set_reg(dev, TM6010_REQ07_RD2_ADDR_FOR_REQ2, 0xc0);
-               tm6000_set_reg(dev, TM6010_REQ07_RD6_ENDP_REQ1_REQ2, 0x60);
-
-               tm6000_set_reg(dev, TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x0c);
-               tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0xff);
-               tm6000_set_reg(dev, TM6000_REQ07_REB_VADC_AADC_MODE, 0x08);
-               msleep(50);
-
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
-               msleep(50);
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x01);
-               msleep(50);
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 0x0020, 0x00);
-               msleep(100);
-       }
-
-       /* switch dvb led on */
-       if (dev->gpio.dvb_led) {
-               tm6000_set_reg(dev, REQ_03_SET_GET_MCU_PIN,
-                       dev->gpio.dvb_led, 0x00);
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(tm6000_init_digital_mode);
-
-struct reg_init {
-       u8 req;
-       u8 reg;
-       u8 val;
-};
-
-/* The meaning of those initializations are unknown */
-static struct reg_init tm6000_init_tab[] = {
-       /* REG  VALUE */
-       { TM6000_REQ07_RDF_PWDOWN_ACLK, 0x1f },
-       { TM6010_REQ07_RFF_SOFT_RESET, 0x08 },
-       { TM6010_REQ07_RFF_SOFT_RESET, 0x00 },
-       { TM6010_REQ07_RD5_POWERSAVE, 0x4f },
-       { TM6000_REQ07_RDA_CLK_SEL, 0x23 },
-       { TM6000_REQ07_RDB_OUT_SEL, 0x08 },
-       { TM6000_REQ07_RE2_VADC_STATUS_CTL, 0x00 },
-       { TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10 },
-       { TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00 },
-       { TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00 },
-       { TM6000_REQ07_REB_VADC_AADC_MODE, 0x64 },      /* 48000 bits/sample, external input */
-       { TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL, 0xc2 },
-
-       { TM6010_REQ07_R3F_RESET, 0x01 },               /* Start of soft reset */
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
-       { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 },
-       { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 },
-       { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 },
-       { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 },
-       { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a },
-       { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 },
-       { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 },
-       { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b },
-       { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 },
-       { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f },
-       { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c },
-       { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c },
-       { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
-       { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
-       { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a },
-       { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 },
-       { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 },
-       { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a },
-       { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 },
-       { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 },
-       { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 },
-       { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 },
-       { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 },
-       { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 },
-       { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
-       { TM6010_REQ07_RC1_TRESHOLD, 0xd0 },
-       { TM6010_REQ07_RC3_HSTART1, 0x88 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },               /* End of the soft reset */
-       { TM6010_REQ05_R18_IMASK7, 0x00 },
-};
-
-static struct reg_init tm6010_init_tab[] = {
-       { TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE, 0x00 },
-       { TM6010_REQ07_RC4_HSTART0, 0xa0 },
-       { TM6010_REQ07_RC6_HEND0, 0x40 },
-       { TM6010_REQ07_RCA_VEND0, 0x31 },
-       { TM6010_REQ07_RCC_ACTIVE_IF, 0xe1 },
-       { TM6010_REQ07_RE0_DVIDEO_SOURCE, 0x03 },
-       { TM6010_REQ07_RFE_POWER_DOWN, 0x7f },
-
-       { TM6010_REQ08_RE2_POWER_DOWN_CTRL1, 0xf0 },
-       { TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4 },
-       { TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8 },
-       { TM6010_REQ08_RE6_POWER_DOWN_CTRL2, 0x00 },
-       { TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2 },
-       { TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0 },
-       { TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2 },
-       { TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, 0x60 },
-       { TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfc },
-
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x07 },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
-       { TM6010_REQ07_R05_NOISE_THRESHOLD, 0x64 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x01 },
-       { TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0x82 },
-       { TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0x36 },
-       { TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0x50 },
-       { TM6010_REQ07_R0C_CHROMA_AGC_CONTROL, 0x6a },
-       { TM6010_REQ07_R11_AGC_PEAK_CONTROL, 0xc9 },
-       { TM6010_REQ07_R12_AGC_GATE_STARTH, 0x07 },
-       { TM6010_REQ07_R13_AGC_GATE_STARTL, 0x3b },
-       { TM6010_REQ07_R14_AGC_GATE_WIDTH, 0x47 },
-       { TM6010_REQ07_R15_AGC_BP_DELAY, 0x6f },
-       { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0xcd },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME, 0x3c },
-       { TM6010_REQ07_R21_HSYNC_PHASE_OFFSET, 0x3c },
-       { TM6010_REQ07_R2D_CHROMA_BURST_END, 0x48 },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
-       { TM6010_REQ07_R32_VSYNC_HLOCK_MIN, 0x74 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
-       { TM6010_REQ07_R34_VSYNC_AGC_MIN, 0x74 },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R36_VSYNC_VBI_MIN, 0x7a },
-       { TM6010_REQ07_R37_VSYNC_VBI_MAX, 0x26 },
-       { TM6010_REQ07_R38_VSYNC_THRESHOLD, 0x40 },
-       { TM6010_REQ07_R39_VSYNC_TIME_CONSTANT, 0x0a },
-       { TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL, 0x55 },
-       { TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21, 0x11 },
-       { TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN, 0x01 },
-       { TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN, 0x02 },
-       { TM6010_REQ07_R58_VBI_CAPTION_DTO1, 0x35 },
-       { TM6010_REQ07_R59_VBI_CAPTION_DTO0, 0xa0 },
-       { TM6010_REQ07_R80_COMB_FILTER_TRESHOLD, 0x15 },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
-       { TM6010_REQ07_RC1_TRESHOLD, 0xd0 },
-       { TM6010_REQ07_RC3_HSTART1, 0x88 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-
-       { TM6010_REQ05_R18_IMASK7, 0x00 },
-
-       { TM6010_REQ07_RDC_IR_LEADER1, 0xaa },
-       { TM6010_REQ07_RDD_IR_LEADER0, 0x30 },
-       { TM6010_REQ07_RDE_IR_PULSE_CNT1, 0x20 },
-       { TM6010_REQ07_RDF_IR_PULSE_CNT0, 0xd0 },
-       { REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 },
-       { TM6010_REQ07_RD8_IR, 0x0f },
-
-       /* set remote wakeup key:any key wakeup */
-       { TM6010_REQ07_RE5_REMOTE_WAKEUP,  0xfe },
-       { TM6010_REQ07_RDA_IR_WAKEUP_SEL,  0xff },
-};
-
-int tm6000_init(struct tm6000_core *dev)
-{
-       int board, rc = 0, i, size;
-       struct reg_init *tab;
-
-       /* Check board revision */
-       board = tm6000_get_reg32(dev, REQ_40_GET_VERSION, 0, 0);
-       if (board >= 0) {
-               switch (board & 0xff) {
-               case 0xf3:
-                       printk(KERN_INFO "Found tm6000\n");
-                       if (dev->dev_type != TM6000)
-                               dev->dev_type = TM6000;
-                       break;
-               case 0xf4:
-                       printk(KERN_INFO "Found tm6010\n");
-                       if (dev->dev_type != TM6010)
-                               dev->dev_type = TM6010;
-                       break;
-               default:
-                       printk(KERN_INFO "Unknown board version = 0x%08x\n", board);
-               }
-       } else
-               printk(KERN_ERR "Error %i while retrieving board version\n", board);
-
-       if (dev->dev_type == TM6010) {
-               tab = tm6010_init_tab;
-               size = ARRAY_SIZE(tm6010_init_tab);
-       } else {
-               tab = tm6000_init_tab;
-               size = ARRAY_SIZE(tm6000_init_tab);
-       }
-
-       /* Load board's initialization table */
-       for (i = 0; i < size; i++) {
-               rc = tm6000_set_reg(dev, tab[i].req, tab[i].reg, tab[i].val);
-               if (rc < 0) {
-                       printk(KERN_ERR "Error %i while setting req %d, "
-                                       "reg %d to value %d\n", rc,
-                                       tab[i].req, tab[i].reg, tab[i].val);
-                       return rc;
-               }
-       }
-
-       msleep(5); /* Just to be conservative */
-
-       rc = tm6000_cards_setup(dev);
-
-       return rc;
-}
-
-
-int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate)
-{
-       int val = 0;
-       u8 areg_f0 = 0x60; /* ADC MCLK = 250 Fs */
-       u8 areg_0a = 0x91; /* SIF 48KHz */
-
-       switch (bitrate) {
-       case 48000:
-               areg_f0 = 0x60; /* ADC MCLK = 250 Fs */
-               areg_0a = 0x91; /* SIF 48KHz */
-               dev->audio_bitrate = bitrate;
-               break;
-       case 32000:
-               areg_f0 = 0x00; /* ADC MCLK = 375 Fs */
-               areg_0a = 0x90; /* SIF 32KHz */
-               dev->audio_bitrate = bitrate;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-
-       /* enable I2S, if we use sif or external I2S device */
-       if (dev->dev_type == TM6010) {
-               val = tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, areg_0a);
-               if (val < 0)
-                       return val;
-
-               val = tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
-                                                       areg_f0, 0xf0);
-               if (val < 0)
-                       return val;
-       } else {
-               val = tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
-                                                       areg_f0, 0xf0);
-               if (val < 0)
-                       return val;
-       }
-       return 0;
-}
-EXPORT_SYMBOL_GPL(tm6000_set_audio_bitrate);
-
-int tm6000_set_audio_rinput(struct tm6000_core *dev)
-{
-       if (dev->dev_type == TM6010) {
-               /* Audio crossbar setting, default SIF1 */
-               u8 areg_f0;
-               u8 areg_07 = 0x10;
-
-               switch (dev->rinput.amux) {
-               case TM6000_AMUX_SIF1:
-               case TM6000_AMUX_SIF2:
-                       areg_f0 = 0x03;
-                       areg_07 = 0x30;
-                       break;
-               case TM6000_AMUX_ADC1:
-                       areg_f0 = 0x00;
-                       break;
-               case TM6000_AMUX_ADC2:
-                       areg_f0 = 0x08;
-                       break;
-               case TM6000_AMUX_I2S:
-                       areg_f0 = 0x04;
-                       break;
-               default:
-                       printk(KERN_INFO "%s: audio input dosn't support\n",
-                               dev->name);
-                       return 0;
-                       break;
-               }
-               /* Set audio input crossbar */
-               tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
-                                                       areg_f0, 0x0f);
-               /* Mux overflow workaround */
-               tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
-                       areg_07, 0xf0);
-       } else {
-               u8 areg_eb;
-               /* Audio setting, default LINE1 */
-               switch (dev->rinput.amux) {
-               case TM6000_AMUX_ADC1:
-                       areg_eb = 0x00;
-                       break;
-               case TM6000_AMUX_ADC2:
-                       areg_eb = 0x04;
-                       break;
-               default:
-                       printk(KERN_INFO "%s: audio input dosn't support\n",
-                               dev->name);
-                       return 0;
-                       break;
-               }
-               /* Set audio input */
-               tm6000_set_reg_mask(dev, TM6000_REQ07_REB_VADC_AADC_MODE,
-                                                       areg_eb, 0x0f);
-       }
-       return 0;
-}
-
-static void tm6010_set_mute_sif(struct tm6000_core *dev, u8 mute)
-{
-       u8 mute_reg = 0;
-
-       if (mute)
-               mute_reg = 0x08;
-
-       tm6000_set_reg_mask(dev, TM6010_REQ08_R0A_A_I2S_MOD, mute_reg, 0x08);
-}
-
-static void tm6010_set_mute_adc(struct tm6000_core *dev, u8 mute)
-{
-       u8 mute_reg = 0;
-
-       if (mute)
-               mute_reg = 0x20;
-
-       if (dev->dev_type == TM6010) {
-               tm6000_set_reg_mask(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL,
-                                                       mute_reg, 0x20);
-               tm6000_set_reg_mask(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL,
-                                                       mute_reg, 0x20);
-       } else {
-               tm6000_set_reg_mask(dev, TM6000_REQ07_REC_VADC_AADC_LVOL,
-                                                       mute_reg, 0x20);
-               tm6000_set_reg_mask(dev, TM6000_REQ07_RED_VADC_AADC_RVOL,
-                                                       mute_reg, 0x20);
-       }
-}
-
-int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute)
-{
-       enum tm6000_mux mux;
-
-       if (dev->radio)
-               mux = dev->rinput.amux;
-       else
-               mux = dev->vinput[dev->input].amux;
-
-       switch (mux) {
-       case TM6000_AMUX_SIF1:
-       case TM6000_AMUX_SIF2:
-               if (dev->dev_type == TM6010)
-                       tm6010_set_mute_sif(dev, mute);
-               else {
-                       printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has"
-                                       " SIF audio inputs. Please check the %s"
-                                       " configuration.\n", dev->name);
-                       return -EINVAL;
-               }
-               break;
-       case TM6000_AMUX_ADC1:
-       case TM6000_AMUX_ADC2:
-               tm6010_set_mute_adc(dev, mute);
-               break;
-       default:
-               return -EINVAL;
-               break;
-       }
-       return 0;
-}
-
-static void tm6010_set_volume_sif(struct tm6000_core *dev, int vol)
-{
-       u8 vol_reg;
-
-       vol_reg = vol & 0x0F;
-
-       if (vol < 0)
-               vol_reg |= 0x40;
-
-       tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, vol_reg);
-       tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, vol_reg);
-}
-
-static void tm6010_set_volume_adc(struct tm6000_core *dev, int vol)
-{
-       u8 vol_reg;
-
-       vol_reg = (vol + 0x10) & 0x1f;
-
-       if (dev->dev_type == TM6010) {
-               tm6000_set_reg(dev, TM6010_REQ08_RF2_LEFT_CHANNEL_VOL, vol_reg);
-               tm6000_set_reg(dev, TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL, vol_reg);
-       } else {
-               tm6000_set_reg(dev, TM6000_REQ07_REC_VADC_AADC_LVOL, vol_reg);
-               tm6000_set_reg(dev, TM6000_REQ07_RED_VADC_AADC_RVOL, vol_reg);
-       }
-}
-
-void tm6000_set_volume(struct tm6000_core *dev, int vol)
-{
-       enum tm6000_mux mux;
-
-       if (dev->radio) {
-               mux = dev->rinput.amux;
-               vol += 8; /* Offset to 0 dB */
-       } else
-               mux = dev->vinput[dev->input].amux;
-
-       switch (mux) {
-       case TM6000_AMUX_SIF1:
-       case TM6000_AMUX_SIF2:
-               if (dev->dev_type == TM6010)
-                       tm6010_set_volume_sif(dev, vol);
-               else
-                       printk(KERN_INFO "ERROR: TM5600 and TM6000 don't has"
-                                       " SIF audio inputs. Please check the %s"
-                                       " configuration.\n", dev->name);
-               break;
-       case TM6000_AMUX_ADC1:
-       case TM6000_AMUX_ADC2:
-               tm6010_set_volume_adc(dev, vol);
-               break;
-       default:
-               break;
-       }
-}
-
-static LIST_HEAD(tm6000_devlist);
-static DEFINE_MUTEX(tm6000_devlist_mutex);
-
-/*
- * tm6000_realease_resource()
- */
-
-void tm6000_remove_from_devlist(struct tm6000_core *dev)
-{
-       mutex_lock(&tm6000_devlist_mutex);
-       list_del(&dev->devlist);
-       mutex_unlock(&tm6000_devlist_mutex);
-};
-
-void tm6000_add_into_devlist(struct tm6000_core *dev)
-{
-       mutex_lock(&tm6000_devlist_mutex);
-       list_add_tail(&dev->devlist, &tm6000_devlist);
-       mutex_unlock(&tm6000_devlist_mutex);
-};
-
-/*
- * Extension interface
- */
-
-static LIST_HEAD(tm6000_extension_devlist);
-
-int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
-                       char *buf, int size)
-{
-       struct tm6000_ops *ops = NULL;
-
-       /* FIXME: tm6000_extension_devlist_lock should be a spinlock */
-
-       if (!list_empty(&tm6000_extension_devlist)) {
-               list_for_each_entry(ops, &tm6000_extension_devlist, next) {
-                       if (ops->fillbuf && ops->type == type)
-                               ops->fillbuf(dev, buf, size);
-               }
-       }
-
-       return 0;
-}
-
-int tm6000_register_extension(struct tm6000_ops *ops)
-{
-       struct tm6000_core *dev = NULL;
-
-       mutex_lock(&tm6000_devlist_mutex);
-       list_add_tail(&ops->next, &tm6000_extension_devlist);
-       list_for_each_entry(dev, &tm6000_devlist, devlist) {
-               ops->init(dev);
-               printk(KERN_INFO "%s: Initialized (%s) extension\n",
-                      dev->name, ops->name);
-       }
-       mutex_unlock(&tm6000_devlist_mutex);
-       return 0;
-}
-EXPORT_SYMBOL(tm6000_register_extension);
-
-void tm6000_unregister_extension(struct tm6000_ops *ops)
-{
-       struct tm6000_core *dev = NULL;
-
-       mutex_lock(&tm6000_devlist_mutex);
-       list_for_each_entry(dev, &tm6000_devlist, devlist)
-               ops->fini(dev);
-
-       printk(KERN_INFO "tm6000: Remove (%s) extension\n", ops->name);
-       list_del(&ops->next);
-       mutex_unlock(&tm6000_devlist_mutex);
-}
-EXPORT_SYMBOL(tm6000_unregister_extension);
-
-void tm6000_init_extension(struct tm6000_core *dev)
-{
-       struct tm6000_ops *ops = NULL;
-
-       mutex_lock(&tm6000_devlist_mutex);
-       if (!list_empty(&tm6000_extension_devlist)) {
-               list_for_each_entry(ops, &tm6000_extension_devlist, next) {
-                       if (ops->init)
-                               ops->init(dev);
-               }
-       }
-       mutex_unlock(&tm6000_devlist_mutex);
-}
-
-void tm6000_close_extension(struct tm6000_core *dev)
-{
-       struct tm6000_ops *ops = NULL;
-
-       mutex_lock(&tm6000_devlist_mutex);
-       if (!list_empty(&tm6000_extension_devlist)) {
-               list_for_each_entry(ops, &tm6000_extension_devlist, next) {
-                       if (ops->fini)
-                               ops->fini(dev);
-               }
-       }
-       mutex_unlock(&tm6000_devlist_mutex);
-}
diff --git a/drivers/media/video/tm6000/tm6000-dvb.c b/drivers/media/video/tm6000/tm6000-dvb.c
deleted file mode 100644 (file)
index e1f3f66..0000000
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- *  tm6000-dvb.c - dvb-t support for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.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 version 2
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-
-#include "tm6000.h"
-#include "tm6000-regs.h"
-
-#include "zl10353.h"
-
-#include <media/tuner.h>
-
-#include "tuner-xc2028.h"
-#include "xc5000.h"
-
-MODULE_DESCRIPTION("DVB driver extension module for tm5600/6000/6010 based TV cards");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
-MODULE_LICENSE("GPL");
-
-MODULE_SUPPORTED_DEVICE("{{Trident, tm5600},"
-                       "{{Trident, tm6000},"
-                       "{{Trident, tm6010}");
-
-static int debug;
-
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "enable debug message");
-
-static inline void print_err_status(struct tm6000_core *dev,
-                                   int packet, int status)
-{
-       char *errmsg = "Unknown";
-
-       switch (status) {
-       case -ENOENT:
-               errmsg = "unlinked synchronuously";
-               break;
-       case -ECONNRESET:
-               errmsg = "unlinked asynchronuously";
-               break;
-       case -ENOSR:
-               errmsg = "Buffer error (overrun)";
-               break;
-       case -EPIPE:
-               errmsg = "Stalled (device not responding)";
-               break;
-       case -EOVERFLOW:
-               errmsg = "Babble (bad cable?)";
-               break;
-       case -EPROTO:
-               errmsg = "Bit-stuff error (bad cable?)";
-               break;
-       case -EILSEQ:
-               errmsg = "CRC/Timeout (could be anything)";
-               break;
-       case -ETIME:
-               errmsg = "Device does not respond";
-               break;
-       }
-       if (packet < 0) {
-               dprintk(dev, 1, "URB status %d [%s].\n",
-                       status, errmsg);
-       } else {
-               dprintk(dev, 1, "URB packet %d, status %d [%s].\n",
-                       packet, status, errmsg);
-       }
-}
-
-static void tm6000_urb_received(struct urb *urb)
-{
-       int ret;
-       struct tm6000_core *dev = urb->context;
-
-       switch (urb->status) {
-       case 0:
-       case -ETIMEDOUT:
-               break;
-       case -ENOENT:
-       case -ECONNRESET:
-       case -ESHUTDOWN:
-               return;
-       default:
-               print_err_status(dev, 0, urb->status);
-       }
-
-       if (urb->actual_length > 0)
-               dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
-                                                  urb->actual_length);
-
-       if (dev->dvb->streams > 0) {
-               ret = usb_submit_urb(urb, GFP_ATOMIC);
-               if (ret < 0) {
-                       printk(KERN_ERR "tm6000:  error %s\n", __func__);
-                       kfree(urb->transfer_buffer);
-                       usb_free_urb(urb);
-               }
-       }
-}
-
-static int tm6000_start_stream(struct tm6000_core *dev)
-{
-       int ret;
-       unsigned int pipe, size;
-       struct tm6000_dvb *dvb = dev->dvb;
-
-       printk(KERN_INFO "tm6000: got start stream request %s\n", __func__);
-
-       if (dev->mode != TM6000_MODE_DIGITAL) {
-               tm6000_init_digital_mode(dev);
-               dev->mode = TM6000_MODE_DIGITAL;
-       }
-
-       dvb->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (dvb->bulk_urb == NULL) {
-               printk(KERN_ERR "tm6000: couldn't allocate urb\n");
-               return -ENOMEM;
-       }
-
-       pipe = usb_rcvbulkpipe(dev->udev, dev->bulk_in.endp->desc.bEndpointAddress
-                                                         & USB_ENDPOINT_NUMBER_MASK);
-
-       size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
-       size = size * 15; /* 512 x 8 or 12 or 15 */
-
-       dvb->bulk_urb->transfer_buffer = kzalloc(size, GFP_KERNEL);
-       if (dvb->bulk_urb->transfer_buffer == NULL) {
-               usb_free_urb(dvb->bulk_urb);
-               printk(KERN_ERR "tm6000: couldn't allocate transfer buffer!\n");
-               return -ENOMEM;
-       }
-
-       usb_fill_bulk_urb(dvb->bulk_urb, dev->udev, pipe,
-                                                dvb->bulk_urb->transfer_buffer,
-                                                size,
-                                                tm6000_urb_received, dev);
-
-       ret = usb_clear_halt(dev->udev, pipe);
-       if (ret < 0) {
-               printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",
-                                                       ret, __func__);
-               return ret;
-       } else
-               printk(KERN_ERR "tm6000: pipe resetted\n");
-
-/*     mutex_lock(&tm6000_driver.open_close_mutex); */
-       ret = usb_submit_urb(dvb->bulk_urb, GFP_ATOMIC);
-
-/*     mutex_unlock(&tm6000_driver.open_close_mutex); */
-       if (ret) {
-               printk(KERN_ERR "tm6000: submit of urb failed (error=%i)\n",
-                                                                       ret);
-
-               kfree(dvb->bulk_urb->transfer_buffer);
-               usb_free_urb(dvb->bulk_urb);
-               return ret;
-       }
-
-       return 0;
-}
-
-static void tm6000_stop_stream(struct tm6000_core *dev)
-{
-       struct tm6000_dvb *dvb = dev->dvb;
-
-       if (dvb->bulk_urb) {
-               printk(KERN_INFO "urb killing\n");
-               usb_kill_urb(dvb->bulk_urb);
-               printk(KERN_INFO "urb buffer free\n");
-               kfree(dvb->bulk_urb->transfer_buffer);
-               usb_free_urb(dvb->bulk_urb);
-               dvb->bulk_urb = NULL;
-       }
-}
-
-static int tm6000_start_feed(struct dvb_demux_feed *feed)
-{
-       struct dvb_demux *demux = feed->demux;
-       struct tm6000_core *dev = demux->priv;
-       struct tm6000_dvb *dvb = dev->dvb;
-       printk(KERN_INFO "tm6000: got start feed request %s\n", __func__);
-
-       mutex_lock(&dvb->mutex);
-       if (dvb->streams == 0) {
-               dvb->streams = 1;
-/*             mutex_init(&tm6000_dev->streming_mutex); */
-               tm6000_start_stream(dev);
-       } else
-               ++(dvb->streams);
-       mutex_unlock(&dvb->mutex);
-
-       return 0;
-}
-
-static int tm6000_stop_feed(struct dvb_demux_feed *feed)
-{
-       struct dvb_demux *demux = feed->demux;
-       struct tm6000_core *dev = demux->priv;
-       struct tm6000_dvb *dvb = dev->dvb;
-
-       printk(KERN_INFO "tm6000: got stop feed request %s\n", __func__);
-
-       mutex_lock(&dvb->mutex);
-
-       printk(KERN_INFO "stream %#x\n", dvb->streams);
-       --(dvb->streams);
-       if (dvb->streams == 0) {
-               printk(KERN_INFO "stop stream\n");
-               tm6000_stop_stream(dev);
-/*             mutex_destroy(&tm6000_dev->streaming_mutex); */
-       }
-       mutex_unlock(&dvb->mutex);
-/*     mutex_destroy(&tm6000_dev->streaming_mutex); */
-
-       return 0;
-}
-
-static int tm6000_dvb_attach_frontend(struct tm6000_core *dev)
-{
-       struct tm6000_dvb *dvb = dev->dvb;
-
-       if (dev->caps.has_zl10353) {
-               struct zl10353_config config = {
-                                    .demod_address = dev->demod_addr,
-                                    .no_tuner = 1,
-                                    .parallel_ts = 1,
-                                    .if2 = 45700,
-                                    .disable_i2c_gate_ctrl = 1,
-                                   };
-
-               dvb->frontend = dvb_attach(zl10353_attach, &config,
-                                                          &dev->i2c_adap);
-       } else {
-               printk(KERN_ERR "tm6000: no frontend defined for the device!\n");
-               return -1;
-       }
-
-       return (!dvb->frontend) ? -1 : 0;
-}
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int register_dvb(struct tm6000_core *dev)
-{
-       int ret = -1;
-       struct tm6000_dvb *dvb = dev->dvb;
-
-       mutex_init(&dvb->mutex);
-
-       dvb->streams = 0;
-
-       /* attach the frontend */
-       ret = tm6000_dvb_attach_frontend(dev);
-       if (ret < 0) {
-               printk(KERN_ERR "tm6000: couldn't attach the frontend!\n");
-               goto err;
-       }
-
-       ret = dvb_register_adapter(&dvb->adapter, "Trident TVMaster 6000 DVB-T",
-                                       THIS_MODULE, &dev->udev->dev, adapter_nr);
-       dvb->adapter.priv = dev;
-
-       if (dvb->frontend) {
-               switch (dev->tuner_type) {
-               case TUNER_XC2028: {
-                       struct xc2028_config cfg = {
-                               .i2c_adap = &dev->i2c_adap,
-                               .i2c_addr = dev->tuner_addr,
-                       };
-
-                       dvb->frontend->callback = tm6000_tuner_callback;
-                       ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
-                       if (ret < 0) {
-                               printk(KERN_ERR
-                                       "tm6000: couldn't register frontend\n");
-                               goto adapter_err;
-                       }
-
-                       if (!dvb_attach(xc2028_attach, dvb->frontend, &cfg)) {
-                               printk(KERN_ERR "tm6000: couldn't register "
-                                               "frontend (xc3028)\n");
-                               ret = -EINVAL;
-                               goto frontend_err;
-                       }
-                       printk(KERN_INFO "tm6000: XC2028/3028 asked to be "
-                                        "attached to frontend!\n");
-                       break;
-                       }
-               case TUNER_XC5000: {
-                       struct xc5000_config cfg = {
-                               .i2c_address = dev->tuner_addr,
-                       };
-
-                       dvb->frontend->callback = tm6000_xc5000_callback;
-                       ret = dvb_register_frontend(&dvb->adapter, dvb->frontend);
-                       if (ret < 0) {
-                               printk(KERN_ERR
-                                       "tm6000: couldn't register frontend\n");
-                               goto adapter_err;
-                       }
-
-                       if (!dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, &cfg)) {
-                               printk(KERN_ERR "tm6000: couldn't register "
-                                               "frontend (xc5000)\n");
-                               ret = -EINVAL;
-                               goto frontend_err;
-                       }
-                       printk(KERN_INFO "tm6000: XC5000 asked to be "
-                                        "attached to frontend!\n");
-                       break;
-                       }
-               }
-       } else
-               printk(KERN_ERR "tm6000: no frontend found\n");
-
-       dvb->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING
-                                                           | DMX_MEMORY_BASED_FILTERING;
-       dvb->demux.priv = dev;
-       dvb->demux.filternum = 8;
-       dvb->demux.feednum = 8;
-       dvb->demux.start_feed = tm6000_start_feed;
-       dvb->demux.stop_feed = tm6000_stop_feed;
-       dvb->demux.write_to_decoder = NULL;
-       ret = dvb_dmx_init(&dvb->demux);
-       if (ret < 0) {
-               printk(KERN_ERR "tm6000: dvb_dmx_init failed (errno = %d)\n", ret);
-               goto frontend_err;
-       }
-
-       dvb->dmxdev.filternum = dev->dvb->demux.filternum;
-       dvb->dmxdev.demux = &dev->dvb->demux.dmx;
-       dvb->dmxdev.capabilities = 0;
-
-       ret =  dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
-       if (ret < 0) {
-               printk(KERN_ERR "tm6000: dvb_dmxdev_init failed (errno = %d)\n", ret);
-               goto dvb_dmx_err;
-       }
-
-       return 0;
-
-dvb_dmx_err:
-       dvb_dmx_release(&dvb->demux);
-frontend_err:
-       if (dvb->frontend) {
-               dvb_frontend_detach(dvb->frontend);
-               dvb_unregister_frontend(dvb->frontend);
-       }
-adapter_err:
-       dvb_unregister_adapter(&dvb->adapter);
-err:
-       return ret;
-}
-
-static void unregister_dvb(struct tm6000_core *dev)
-{
-       struct tm6000_dvb *dvb = dev->dvb;
-
-       if (dvb->bulk_urb != NULL) {
-               struct urb *bulk_urb = dvb->bulk_urb;
-
-               kfree(bulk_urb->transfer_buffer);
-               bulk_urb->transfer_buffer = NULL;
-               usb_unlink_urb(bulk_urb);
-               usb_free_urb(bulk_urb);
-       }
-
-/*     mutex_lock(&tm6000_driver.open_close_mutex); */
-       if (dvb->frontend) {
-               dvb_frontend_detach(dvb->frontend);
-               dvb_unregister_frontend(dvb->frontend);
-       }
-
-       dvb_dmxdev_release(&dvb->dmxdev);
-       dvb_dmx_release(&dvb->demux);
-       dvb_unregister_adapter(&dvb->adapter);
-       mutex_destroy(&dvb->mutex);
-/*     mutex_unlock(&tm6000_driver.open_close_mutex); */
-}
-
-static int dvb_init(struct tm6000_core *dev)
-{
-       struct tm6000_dvb *dvb;
-       int rc;
-
-       if (!dev)
-               return 0;
-
-       if (!dev->caps.has_dvb)
-               return 0;
-
-       if (dev->udev->speed == USB_SPEED_FULL) {
-               printk(KERN_INFO "This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)\n");
-               return 0;
-       }
-
-       dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL);
-       if (!dvb) {
-               printk(KERN_INFO "Cannot allocate memory\n");
-               return -ENOMEM;
-       }
-
-       dev->dvb = dvb;
-
-       rc = register_dvb(dev);
-       if (rc < 0) {
-               kfree(dvb);
-               dev->dvb = NULL;
-               return 0;
-       }
-
-       return 0;
-}
-
-static int dvb_fini(struct tm6000_core *dev)
-{
-       if (!dev)
-               return 0;
-
-       if (!dev->caps.has_dvb)
-               return 0;
-
-       if (dev->dvb) {
-               unregister_dvb(dev);
-               kfree(dev->dvb);
-               dev->dvb = NULL;
-       }
-
-       return 0;
-}
-
-static struct tm6000_ops dvb_ops = {
-       .type   = TM6000_DVB,
-       .name   = "TM6000 dvb Extension",
-       .init   = dvb_init,
-       .fini   = dvb_fini,
-};
-
-static int __init tm6000_dvb_register(void)
-{
-       return tm6000_register_extension(&dvb_ops);
-}
-
-static void __exit tm6000_dvb_unregister(void)
-{
-       tm6000_unregister_extension(&dvb_ops);
-}
-
-module_init(tm6000_dvb_register);
-module_exit(tm6000_dvb_unregister);
diff --git a/drivers/media/video/tm6000/tm6000-i2c.c b/drivers/media/video/tm6000/tm6000-i2c.c
deleted file mode 100644 (file)
index c7e23e3..0000000
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- *  tm6000-i2c.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
- *     - Fix SMBus Read Byte command
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation version 2
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/i2c.h>
-
-#include "tm6000.h"
-#include "tm6000-regs.h"
-#include <media/v4l2-common.h>
-#include <media/tuner.h>
-#include "tuner-xc2028.h"
-
-
-/* ----------------------------------------------------------- */
-
-static unsigned int i2c_debug;
-module_param(i2c_debug, int, 0644);
-MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
-
-#define i2c_dprintk(lvl, fmt, args...) if (i2c_debug >= lvl) do { \
-                       printk(KERN_DEBUG "%s at %s: " fmt, \
-                       dev->name, __func__, ##args); } while (0)
-
-static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr,
-                               __u8 reg, char *buf, int len)
-{
-       int rc;
-       unsigned int i2c_packet_limit = 16;
-
-       if (dev->dev_type == TM6010)
-               i2c_packet_limit = 80;
-
-       if (!buf)
-               return -1;
-
-       if (len < 1 || len > i2c_packet_limit) {
-               printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
-                       len, i2c_packet_limit);
-               return -1;
-       }
-
-       /* capture mutex */
-       rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
-               USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
-               addr | reg << 8, 0, buf, len);
-
-       if (rc < 0) {
-               /* release mutex */
-               return rc;
-       }
-
-       /* release mutex */
-       return rc;
-}
-
-/* Generic read - doesn't work fine with 16bit registers */
-static int tm6000_i2c_recv_regs(struct tm6000_core *dev, unsigned char addr,
-                               __u8 reg, char *buf, int len)
-{
-       int rc;
-       u8 b[2];
-       unsigned int i2c_packet_limit = 16;
-
-       if (dev->dev_type == TM6010)
-               i2c_packet_limit = 64;
-
-       if (!buf)
-               return -1;
-
-       if (len < 1 || len > i2c_packet_limit) {
-               printk(KERN_ERR "Incorrect length of i2c packet = %d, limit set to %d\n",
-                       len, i2c_packet_limit);
-               return -1;
-       }
-
-       /* capture mutex */
-       if ((dev->caps.has_zl10353) && (dev->demod_addr << 1 == addr) && (reg % 2 == 0)) {
-               /*
-                * Workaround an I2C bug when reading from zl10353
-                */
-               reg -= 1;
-               len += 1;
-
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, b, len);
-
-               *buf = b[1];
-       } else {
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       REQ_16_SET_GET_I2C_WR1_RDN, addr | reg << 8, 0, buf, len);
-       }
-
-       /* release mutex */
-       return rc;
-}
-
-/*
- * read from a 16bit register
- * for example xc2028, xc3028 or xc3028L
- */
-static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr,
-                                 __u16 reg, char *buf, int len)
-{
-       int rc;
-       unsigned char ureg;
-
-       if (!buf || len != 2)
-               return -1;
-
-       /* capture mutex */
-       if (dev->dev_type == TM6010) {
-               ureg = reg & 0xFF;
-               rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR |
-                       USB_RECIP_DEVICE, REQ_16_SET_GET_I2C_WR1_RDN,
-                       addr | (reg & 0xFF00), 0, &ureg, 1);
-
-               if (rc < 0) {
-                       /* release mutex */
-                       return rc;
-               }
-
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
-                       USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ,
-                       reg, 0, buf, len);
-       } else {
-               rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR |
-                       USB_RECIP_DEVICE, REQ_14_SET_GET_I2C_WR2_RDN,
-                       addr, reg, buf, len);
-       }
-
-       /* release mutex */
-       return rc;
-}
-
-static int tm6000_i2c_xfer(struct i2c_adapter *i2c_adap,
-                          struct i2c_msg msgs[], int num)
-{
-       struct tm6000_core *dev = i2c_adap->algo_data;
-       int addr, rc, i, byte;
-
-       if (num <= 0)
-               return 0;
-       for (i = 0; i < num; i++) {
-               addr = (msgs[i].addr << 1) & 0xff;
-               i2c_dprintk(2, "%s %s addr=0x%x len=%d:",
-                        (msgs[i].flags & I2C_M_RD) ? "read" : "write",
-                        i == num - 1 ? "stop" : "nonstop", addr, msgs[i].len);
-               if (msgs[i].flags & I2C_M_RD) {
-                       /* read request without preceding register selection */
-                       /*
-                        * The TM6000 only supports a read transaction
-                        * immediately after a 1 or 2 byte write to select
-                        * a register.  We cannot fulfil this request.
-                        */
-                       i2c_dprintk(2, " read without preceding write not"
-                                      " supported");
-                       rc = -EOPNOTSUPP;
-                       goto err;
-               } else if (i + 1 < num && msgs[i].len <= 2 &&
-                          (msgs[i + 1].flags & I2C_M_RD) &&
-                          msgs[i].addr == msgs[i + 1].addr) {
-                       /* 1 or 2 byte write followed by a read */
-                       if (i2c_debug >= 2)
-                               for (byte = 0; byte < msgs[i].len; byte++)
-                                       printk(KERN_CONT " %02x", msgs[i].buf[byte]);
-                       i2c_dprintk(2, "; joined to read %s len=%d:",
-                                   i == num - 2 ? "stop" : "nonstop",
-                                   msgs[i + 1].len);
-
-                       if (msgs[i].len == 2) {
-                               rc = tm6000_i2c_recv_regs16(dev, addr,
-                                       msgs[i].buf[0] << 8 | msgs[i].buf[1],
-                                       msgs[i + 1].buf, msgs[i + 1].len);
-                       } else {
-                               rc = tm6000_i2c_recv_regs(dev, addr, msgs[i].buf[0],
-                                       msgs[i + 1].buf, msgs[i + 1].len);
-                       }
-
-                       i++;
-
-                       if (addr == dev->tuner_addr << 1) {
-                               tm6000_set_reg(dev, REQ_50_SET_START, 0, 0);
-                               tm6000_set_reg(dev, REQ_51_SET_STOP, 0, 0);
-                       }
-                       if (i2c_debug >= 2)
-                               for (byte = 0; byte < msgs[i].len; byte++)
-                                       printk(KERN_CONT " %02x", msgs[i].buf[byte]);
-               } else {
-                       /* write bytes */
-                       if (i2c_debug >= 2)
-                               for (byte = 0; byte < msgs[i].len; byte++)
-                                       printk(KERN_CONT " %02x", msgs[i].buf[byte]);
-                       rc = tm6000_i2c_send_regs(dev, addr, msgs[i].buf[0],
-                               msgs[i].buf + 1, msgs[i].len - 1);
-               }
-               if (i2c_debug >= 2)
-                       printk(KERN_CONT "\n");
-               if (rc < 0)
-                       goto err;
-       }
-
-       return num;
-err:
-       i2c_dprintk(2, " ERROR: %i\n", rc);
-       return rc;
-}
-
-static int tm6000_i2c_eeprom(struct tm6000_core *dev)
-{
-       int i, rc;
-       unsigned char *p = dev->eedata;
-       unsigned char bytes[17];
-
-       dev->i2c_client.addr = 0xa0 >> 1;
-       dev->eedata_size = 0;
-
-       bytes[16] = '\0';
-       for (i = 0; i < sizeof(dev->eedata); ) {
-               *p = i;
-               rc = tm6000_i2c_recv_regs(dev, 0xa0, i, p, 1);
-               if (rc < 1) {
-                       if (p == dev->eedata)
-                               goto noeeprom;
-                       else {
-                               printk(KERN_WARNING
-                               "%s: i2c eeprom read error (err=%d)\n",
-                               dev->name, rc);
-                       }
-                       return -EINVAL;
-               }
-               dev->eedata_size++;
-               p++;
-               if (0 == (i % 16))
-                       printk(KERN_INFO "%s: i2c eeprom %02x:", dev->name, i);
-               printk(KERN_CONT " %02x", dev->eedata[i]);
-               if ((dev->eedata[i] >= ' ') && (dev->eedata[i] <= 'z'))
-                       bytes[i%16] = dev->eedata[i];
-               else
-                       bytes[i%16] = '.';
-
-               i++;
-
-               if (0 == (i % 16)) {
-                       bytes[16] = '\0';
-                       printk(KERN_CONT "  %s\n", bytes);
-               }
-       }
-       if (0 != (i%16)) {
-               bytes[i%16] = '\0';
-               for (i %= 16; i < 16; i++)
-                       printk(KERN_CONT "   ");
-               printk(KERN_CONT "  %s\n", bytes);
-       }
-
-       return 0;
-
-noeeprom:
-       printk(KERN_INFO "%s: Huh, no eeprom present (err=%d)?\n",
-              dev->name, rc);
-       return -EINVAL;
-}
-
-/* ----------------------------------------------------------- */
-
-/*
- * functionality()
- */
-static u32 functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_SMBUS_EMUL;
-}
-
-static const struct i2c_algorithm tm6000_algo = {
-       .master_xfer   = tm6000_i2c_xfer,
-       .functionality = functionality,
-};
-
-/* ----------------------------------------------------------- */
-
-/*
- * tm6000_i2c_register()
- * register i2c bus
- */
-int tm6000_i2c_register(struct tm6000_core *dev)
-{
-       int rc;
-
-       dev->i2c_adap.owner = THIS_MODULE;
-       dev->i2c_adap.algo = &tm6000_algo;
-       dev->i2c_adap.dev.parent = &dev->udev->dev;
-       strlcpy(dev->i2c_adap.name, dev->name, sizeof(dev->i2c_adap.name));
-       dev->i2c_adap.algo_data = dev;
-       i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
-       rc = i2c_add_adapter(&dev->i2c_adap);
-       if (rc)
-               return rc;
-
-       dev->i2c_client.adapter = &dev->i2c_adap;
-       strlcpy(dev->i2c_client.name, "tm6000 internal", I2C_NAME_SIZE);
-       tm6000_i2c_eeprom(dev);
-
-       return 0;
-}
-
-/*
- * tm6000_i2c_unregister()
- * unregister i2c_bus
- */
-int tm6000_i2c_unregister(struct tm6000_core *dev)
-{
-       i2c_del_adapter(&dev->i2c_adap);
-       return 0;
-}
diff --git a/drivers/media/video/tm6000/tm6000-input.c b/drivers/media/video/tm6000/tm6000-input.c
deleted file mode 100644 (file)
index e80b7e1..0000000
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- *  tm6000-input.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2010 Stefan Ringel <stefan.ringel@arcor.de>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation version 2
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-
-#include <linux/input.h>
-#include <linux/usb.h>
-
-#include <media/rc-core.h>
-
-#include "tm6000.h"
-#include "tm6000-regs.h"
-
-static unsigned int ir_debug;
-module_param(ir_debug, int, 0644);
-MODULE_PARM_DESC(ir_debug, "debug message level");
-
-static unsigned int enable_ir = 1;
-module_param(enable_ir, int, 0644);
-MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)");
-
-static unsigned int ir_clock_mhz = 12;
-module_param(ir_clock_mhz, int, 0644);
-MODULE_PARM_DESC(enable_ir, "ir clock, in MHz");
-
-#define URB_SUBMIT_DELAY       100     /* ms - Delay to submit an URB request on retrial and init */
-#define URB_INT_LED_DELAY      100     /* ms - Delay to turn led on again on int mode */
-
-#undef dprintk
-
-#define dprintk(level, fmt, arg...) do {\
-       if (ir_debug >= level) \
-               printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \
-       } while (0)
-
-struct tm6000_ir_poll_result {
-       u16 rc_data;
-};
-
-struct tm6000_IR {
-       struct tm6000_core      *dev;
-       struct rc_dev           *rc;
-       char                    name[32];
-       char                    phys[32];
-
-       /* poll expernal decoder */
-       int                     polling;
-       struct delayed_work     work;
-       u8                      wait:1;
-       u8                      pwled:2;
-       u8                      submit_urb:1;
-       u16                     key_addr;
-       struct urb              *int_urb;
-
-       /* IR device properties */
-       u64                     rc_type;
-};
-
-void tm6000_ir_wait(struct tm6000_core *dev, u8 state)
-{
-       struct tm6000_IR *ir = dev->ir;
-
-       if (!dev->ir)
-               return;
-
-       dprintk(2, "%s: %i\n",__func__, ir->wait);
-
-       if (state)
-               ir->wait = 1;
-       else
-               ir->wait = 0;
-}
-
-static int tm6000_ir_config(struct tm6000_IR *ir)
-{
-       struct tm6000_core *dev = ir->dev;
-       u32 pulse = 0, leader = 0;
-
-       dprintk(2, "%s\n",__func__);
-
-       /*
-        * The IR decoder supports RC-5 or NEC, with a configurable timing.
-        * The timing configuration there is not that accurate, as it uses
-        * approximate values. The NEC spec mentions a 562.5 unit period,
-        * and RC-5 uses a 888.8 period.
-        * Currently, driver assumes a clock provided by a 12 MHz XTAL, but
-        * a modprobe parameter can adjust it.
-        * Adjustments are required for other timings.
-        * It seems that the 900ms timing for NEC is used to detect a RC-5
-        * IR, in order to discard such decoding
-        */
-
-       switch (ir->rc_type) {
-       case RC_TYPE_NEC:
-               leader = 900;   /* ms */
-               pulse  = 700;   /* ms - the actual value would be 562 */
-               break;
-       default:
-       case RC_TYPE_RC5:
-               leader = 900;   /* ms - from the NEC decoding */
-               pulse  = 1780;  /* ms - The actual value would be 1776 */
-               break;
-       }
-
-       pulse = ir_clock_mhz * pulse;
-       leader = ir_clock_mhz * leader;
-       if (ir->rc_type == RC_TYPE_NEC)
-               leader = leader | 0x8000;
-
-       dprintk(2, "%s: %s, %d MHz, leader = 0x%04x, pulse = 0x%06x \n",
-               __func__,
-               (ir->rc_type == RC_TYPE_NEC) ? "NEC" : "RC-5",
-               ir_clock_mhz, leader, pulse);
-
-       /* Remote WAKEUP = enable, normal mode, from IR decoder output */
-       tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe);
-
-       /* Enable IR reception on non-busrt mode */
-       tm6000_set_reg(dev, TM6010_REQ07_RD8_IR, 0x2f);
-
-       /* IR_WKUP_SEL = Low byte in decoded IR data */
-       tm6000_set_reg(dev, TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff);
-       /* IR_WKU_ADD code */
-       tm6000_set_reg(dev, TM6010_REQ07_RDB_IR_WAKEUP_ADD, 0xff);
-
-       tm6000_set_reg(dev, TM6010_REQ07_RDC_IR_LEADER1, leader >> 8);
-       tm6000_set_reg(dev, TM6010_REQ07_RDD_IR_LEADER0, leader);
-
-       tm6000_set_reg(dev, TM6010_REQ07_RDE_IR_PULSE_CNT1, pulse >> 8);
-       tm6000_set_reg(dev, TM6010_REQ07_RDF_IR_PULSE_CNT0, pulse);
-
-       if (!ir->polling)
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
-       else
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1);
-       msleep(10);
-
-       /* Shows that IR is working via the LED */
-       tm6000_flash_led(dev, 0);
-       msleep(100);
-       tm6000_flash_led(dev, 1);
-       ir->pwled = 1;
-
-       return 0;
-}
-
-static void tm6000_ir_urb_received(struct urb *urb)
-{
-       struct tm6000_core *dev = urb->context;
-       struct tm6000_IR *ir = dev->ir;
-       struct tm6000_ir_poll_result poll_result;
-       char *buf;
-
-       dprintk(2, "%s\n",__func__);
-       if (urb->status < 0 || urb->actual_length <= 0) {
-               printk(KERN_INFO "tm6000: IR URB failure: status: %i, length %i\n",
-                      urb->status, urb->actual_length);
-               ir->submit_urb = 1;
-               schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
-               return;
-       }
-       buf = urb->transfer_buffer;
-
-       if (ir_debug)
-               print_hex_dump(KERN_DEBUG, "tm6000: IR data: ",
-                              DUMP_PREFIX_OFFSET,16, 1,
-                              buf, urb->actual_length, false);
-
-       poll_result.rc_data = buf[0];
-       if (urb->actual_length > 1)
-               poll_result.rc_data |= buf[1] << 8;
-
-       dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
-       rc_keydown(ir->rc, poll_result.rc_data, 0);
-
-       usb_submit_urb(urb, GFP_ATOMIC);
-       /*
-        * Flash the led. We can't do it here, as it is running on IRQ context.
-        * So, use the scheduler to do it, in a few ms.
-        */
-       ir->pwled = 2;
-       schedule_delayed_work(&ir->work, msecs_to_jiffies(10));
-}
-
-static void tm6000_ir_handle_key(struct work_struct *work)
-{
-       struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
-       struct tm6000_core *dev = ir->dev;
-       struct tm6000_ir_poll_result poll_result;
-       int rc;
-       u8 buf[2];
-
-       if (ir->wait)
-               return;
-
-       dprintk(3, "%s\n",__func__);
-
-       rc = tm6000_read_write_usb(dev, USB_DIR_IN |
-               USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               REQ_02_GET_IR_CODE, 0, 0, buf, 2);
-       if (rc < 0)
-               return;
-
-       if (rc > 1)
-               poll_result.rc_data = buf[0] | buf[1] << 8;
-       else
-               poll_result.rc_data = buf[0];
-
-       /* Check if something was read */
-       if ((poll_result.rc_data & 0xff) == 0xff) {
-               if (!ir->pwled) {
-                       tm6000_flash_led(dev, 1);
-                       ir->pwled = 1;
-               }
-               return;
-       }
-
-       dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data);
-       rc_keydown(ir->rc, poll_result.rc_data, 0);
-       tm6000_flash_led(dev, 0);
-       ir->pwled = 0;
-
-       /* Re-schedule polling */
-       schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
-}
-
-static void tm6000_ir_int_work(struct work_struct *work)
-{
-       struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work);
-       struct tm6000_core *dev = ir->dev;
-       int rc;
-
-       dprintk(3, "%s, submit_urb = %d, pwled = %d\n",__func__, ir->submit_urb,
-               ir->pwled);
-
-       if (ir->submit_urb) {
-               dprintk(3, "Resubmit urb\n");
-               tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0);
-
-               rc = usb_submit_urb(ir->int_urb, GFP_ATOMIC);
-               if (rc < 0) {
-                       printk(KERN_ERR "tm6000: Can't submit an IR interrupt. Error %i\n",
-                              rc);
-                       /* Retry in 100 ms */
-                       schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
-                       return;
-               }
-               ir->submit_urb = 0;
-       }
-
-       /* Led is enabled only if USB submit doesn't fail */
-       if (ir->pwled == 2) {
-               tm6000_flash_led(dev, 0);
-               ir->pwled = 0;
-               schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_INT_LED_DELAY));
-       } else if (!ir->pwled) {
-               tm6000_flash_led(dev, 1);
-               ir->pwled = 1;
-       }
-}
-
-static int tm6000_ir_start(struct rc_dev *rc)
-{
-       struct tm6000_IR *ir = rc->priv;
-
-       dprintk(2, "%s\n",__func__);
-
-       schedule_delayed_work(&ir->work, 0);
-
-       return 0;
-}
-
-static void tm6000_ir_stop(struct rc_dev *rc)
-{
-       struct tm6000_IR *ir = rc->priv;
-
-       dprintk(2, "%s\n",__func__);
-
-       cancel_delayed_work_sync(&ir->work);
-}
-
-static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
-{
-       struct tm6000_IR *ir = rc->priv;
-
-       if (!ir)
-               return 0;
-
-       dprintk(2, "%s\n",__func__);
-
-       if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC))
-               ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff);
-
-       ir->rc_type = rc_type;
-
-       tm6000_ir_config(ir);
-       /* TODO */
-       return 0;
-}
-
-static int __tm6000_ir_int_start(struct rc_dev *rc)
-{
-       struct tm6000_IR *ir = rc->priv;
-       struct tm6000_core *dev = ir->dev;
-       int pipe, size;
-       int err = -ENOMEM;
-
-       if (!ir)
-               return -ENODEV;
-
-       dprintk(2, "%s\n",__func__);
-
-       ir->int_urb = usb_alloc_urb(0, GFP_ATOMIC);
-       if (!ir->int_urb)
-               return -ENOMEM;
-
-       pipe = usb_rcvintpipe(dev->udev,
-               dev->int_in.endp->desc.bEndpointAddress
-               & USB_ENDPOINT_NUMBER_MASK);
-
-       size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
-       dprintk(1, "IR max size: %d\n", size);
-
-       ir->int_urb->transfer_buffer = kzalloc(size, GFP_ATOMIC);
-       if (ir->int_urb->transfer_buffer == NULL) {
-               usb_free_urb(ir->int_urb);
-               return err;
-       }
-       dprintk(1, "int interval: %d\n", dev->int_in.endp->desc.bInterval);
-
-       usb_fill_int_urb(ir->int_urb, dev->udev, pipe,
-               ir->int_urb->transfer_buffer, size,
-               tm6000_ir_urb_received, dev,
-               dev->int_in.endp->desc.bInterval);
-
-       ir->submit_urb = 1;
-       schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY));
-
-       return 0;
-}
-
-static void __tm6000_ir_int_stop(struct rc_dev *rc)
-{
-       struct tm6000_IR *ir = rc->priv;
-
-       if (!ir || !ir->int_urb)
-               return;
-
-       dprintk(2, "%s\n",__func__);
-
-       usb_kill_urb(ir->int_urb);
-       kfree(ir->int_urb->transfer_buffer);
-       usb_free_urb(ir->int_urb);
-       ir->int_urb = NULL;
-}
-
-int tm6000_ir_int_start(struct tm6000_core *dev)
-{
-       struct tm6000_IR *ir = dev->ir;
-
-       if (!ir)
-               return 0;
-
-       return __tm6000_ir_int_start(ir->rc);
-}
-
-void tm6000_ir_int_stop(struct tm6000_core *dev)
-{
-       struct tm6000_IR *ir = dev->ir;
-
-       if (!ir || !ir->rc)
-               return;
-
-       __tm6000_ir_int_stop(ir->rc);
-}
-
-int tm6000_ir_init(struct tm6000_core *dev)
-{
-       struct tm6000_IR *ir;
-       struct rc_dev *rc;
-       int err = -ENOMEM;
-
-       if (!enable_ir)
-               return -ENODEV;
-
-       if (!dev->caps.has_remote)
-               return 0;
-
-       if (!dev->ir_codes)
-               return 0;
-
-       ir = kzalloc(sizeof(*ir), GFP_ATOMIC);
-       rc = rc_allocate_device();
-       if (!ir || !rc)
-               goto out;
-
-       dprintk(2, "%s\n", __func__);
-
-       /* record handles to ourself */
-       ir->dev = dev;
-       dev->ir = ir;
-       ir->rc = rc;
-
-       /* input setup */
-       rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC;
-       /* Neded, in order to support NEC remotes with 24 or 32 bits */
-       rc->scanmask = 0xffff;
-       rc->priv = ir;
-       rc->change_protocol = tm6000_ir_change_protocol;
-       if (dev->int_in.endp) {
-               rc->open    = __tm6000_ir_int_start;
-               rc->close   = __tm6000_ir_int_stop;
-               INIT_DELAYED_WORK(&ir->work, tm6000_ir_int_work);
-       } else {
-               rc->open  = tm6000_ir_start;
-               rc->close = tm6000_ir_stop;
-               ir->polling = 50;
-               INIT_DELAYED_WORK(&ir->work, tm6000_ir_handle_key);
-       }
-       rc->driver_type = RC_DRIVER_SCANCODE;
-
-       snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)",
-                                               dev->name);
-
-       usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
-       strlcat(ir->phys, "/input0", sizeof(ir->phys));
-
-       tm6000_ir_change_protocol(rc, RC_TYPE_UNKNOWN);
-
-       rc->input_name = ir->name;
-       rc->input_phys = ir->phys;
-       rc->input_id.bustype = BUS_USB;
-       rc->input_id.version = 1;
-       rc->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
-       rc->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
-       rc->map_name = dev->ir_codes;
-       rc->driver_name = "tm6000";
-       rc->dev.parent = &dev->udev->dev;
-
-       /* ir register */
-       err = rc_register_device(rc);
-       if (err)
-               goto out;
-
-       return 0;
-
-out:
-       dev->ir = NULL;
-       rc_free_device(rc);
-       kfree(ir);
-       return err;
-}
-
-int tm6000_ir_fini(struct tm6000_core *dev)
-{
-       struct tm6000_IR *ir = dev->ir;
-
-       /* skip detach on non attached board */
-
-       if (!ir)
-               return 0;
-
-       dprintk(2, "%s\n",__func__);
-
-       if (!ir->polling)
-               __tm6000_ir_int_stop(ir->rc);
-
-       tm6000_ir_stop(ir->rc);
-
-       /* Turn off the led */
-       tm6000_flash_led(dev, 0);
-       ir->pwled = 0;
-
-       rc_unregister_device(ir->rc);
-
-       kfree(ir);
-       dev->ir = NULL;
-
-       return 0;
-}
diff --git a/drivers/media/video/tm6000/tm6000-regs.h b/drivers/media/video/tm6000/tm6000-regs.h
deleted file mode 100644 (file)
index a38c251..0000000
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- *  tm6000-regs.h - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation version 2
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * Define TV Master TM5600/TM6000/TM6010 Request codes
- */
-#define REQ_00_SET_IR_VALUE            0
-#define REQ_01_SET_WAKEUP_IRCODE       1
-#define REQ_02_GET_IR_CODE             2
-#define REQ_03_SET_GET_MCU_PIN         3
-#define REQ_04_EN_DISABLE_MCU_INT      4
-#define REQ_05_SET_GET_USBREG          5
-       /* Write: RegNum, Value, 0 */
-       /* Read : RegNum, Value, 1, RegStatus */
-#define REQ_06_SET_GET_USBREG_BIT      6
-#define REQ_07_SET_GET_AVREG           7
-       /* Write: RegNum, Value, 0 */
-       /* Read : RegNum, Value, 1, RegStatus */
-#define REQ_08_SET_GET_AVREG_BIT       8
-#define REQ_09_SET_GET_TUNER_FQ                9
-#define REQ_10_SET_TUNER_SYSTEM                10
-#define REQ_11_SET_EEPROM_ADDR         11
-#define REQ_12_SET_GET_EEPROMBYTE      12
-#define REQ_13_GET_EEPROM_SEQREAD      13
-#define REQ_14_SET_GET_I2C_WR2_RDN     14
-#define REQ_15_SET_GET_I2CBYTE         15
-       /* Write: Subaddr, Slave Addr, value, 0 */
-       /* Read : Subaddr, Slave Addr, value, 1 */
-#define REQ_16_SET_GET_I2C_WR1_RDN     16
-       /* Subaddr, Slave Addr, 0, length */
-#define REQ_17_SET_GET_I2CFP           17
-       /* Write: Slave Addr, register, value */
-       /* Read : Slave Addr, register, 2, data */
-#define REQ_20_DATA_TRANSFER           20
-#define REQ_30_I2C_WRITE               30
-#define REQ_31_I2C_READ                        31
-#define REQ_35_AFTEK_TUNER_READ                35
-#define REQ_40_GET_VERSION             40
-#define REQ_50_SET_START               50
-#define REQ_51_SET_STOP                        51
-#define REQ_52_TRANSMIT_DATA           52
-#define REQ_53_SPI_INITIAL             53
-#define REQ_54_SPI_SETSTART            54
-#define REQ_55_SPI_INOUTDATA           55
-#define REQ_56_SPI_SETSTOP             56
-
-/*
- * Define TV Master TM5600/TM6000/TM6010 GPIO lines
- */
-
-#define TM6000_GPIO_CLK                0x101
-#define TM6000_GPIO_DATA       0x100
-
-#define TM6000_GPIO_1          0x102
-#define TM6000_GPIO_2          0x103
-#define TM6000_GPIO_3          0x104
-#define TM6000_GPIO_4          0x300
-#define TM6000_GPIO_5          0x301
-#define TM6000_GPIO_6          0x304
-#define TM6000_GPIO_7          0x305
-
-/* tm6010 defines GPIO with different values */
-#define TM6010_GPIO_0      0x0102
-#define TM6010_GPIO_1      0x0103
-#define TM6010_GPIO_2      0x0104
-#define TM6010_GPIO_3      0x0105
-#define TM6010_GPIO_4      0x0106
-#define TM6010_GPIO_5      0x0107
-#define TM6010_GPIO_6      0x0300
-#define TM6010_GPIO_7      0x0301
-#define TM6010_GPIO_9      0x0305
-/*
- * Define TV Master TM5600/TM6000/TM6010 URB message codes and length
- */
-
-enum {
-       TM6000_URB_MSG_VIDEO = 1,
-       TM6000_URB_MSG_AUDIO,
-       TM6000_URB_MSG_VBI,
-       TM6000_URB_MSG_PTS,
-       TM6000_URB_MSG_ERR,
-};
-
-/* Define specific TM6000 Video decoder registers */
-#define TM6000_REQ07_RD8_TEST_SEL                      0x07, 0xd8
-#define TM6000_REQ07_RD9_A_SIM_SEL                     0x07, 0xd9
-#define TM6000_REQ07_RDA_CLK_SEL                       0x07, 0xda
-#define TM6000_REQ07_RDB_OUT_SEL                       0x07, 0xdb
-#define TM6000_REQ07_RDC_NSEL_I2S                      0x07, 0xdc
-#define TM6000_REQ07_RDD_GPIO2_MDRV                    0x07, 0xdd
-#define TM6000_REQ07_RDE_GPIO1_MDRV                    0x07, 0xde
-#define TM6000_REQ07_RDF_PWDOWN_ACLK                   0x07, 0xdf
-#define TM6000_REQ07_RE0_VADC_REF_CTL                  0x07, 0xe0
-#define TM6000_REQ07_RE1_VADC_DACLIMP                  0x07, 0xe1
-#define TM6000_REQ07_RE2_VADC_STATUS_CTL               0x07, 0xe2
-#define TM6000_REQ07_RE3_VADC_INP_LPF_SEL1             0x07, 0xe3
-#define TM6000_REQ07_RE4_VADC_TARGET1                  0x07, 0xe4
-#define TM6000_REQ07_RE5_VADC_INP_LPF_SEL2             0x07, 0xe5
-#define TM6000_REQ07_RE6_VADC_TARGET2                  0x07, 0xe6
-#define TM6000_REQ07_RE7_VADC_AGAIN_CTL                        0x07, 0xe7
-#define TM6000_REQ07_RE8_VADC_PWDOWN_CTL               0x07, 0xe8
-#define TM6000_REQ07_RE9_VADC_INPUT_CTL1               0x07, 0xe9
-#define TM6000_REQ07_REA_VADC_INPUT_CTL2               0x07, 0xea
-#define TM6000_REQ07_REB_VADC_AADC_MODE                        0x07, 0xeb
-#define TM6000_REQ07_REC_VADC_AADC_LVOL                        0x07, 0xec
-#define TM6000_REQ07_RED_VADC_AADC_RVOL                        0x07, 0xed
-#define TM6000_REQ07_REE_VADC_CTRL_SEL_CONTROL         0x07, 0xee
-#define TM6000_REQ07_REF_VADC_GAIN_MAP_CTL             0x07, 0xef
-#define TM6000_REQ07_RFD_BIST_ERR_VST_LOW              0x07, 0xfd
-#define TM6000_REQ07_RFE_BIST_ERR_VST_HIGH             0x07, 0xfe
-
-/* Define TM6000/TM6010 Video decoder registers */
-#define TM6010_REQ07_R00_VIDEO_CONTROL0                        0x07, 0x00
-#define TM6010_REQ07_R01_VIDEO_CONTROL1                        0x07, 0x01
-#define TM6010_REQ07_R02_VIDEO_CONTROL2                        0x07, 0x02
-#define TM6010_REQ07_R03_YC_SEP_CONTROL                        0x07, 0x03
-#define TM6010_REQ07_R04_LUMA_HAGC_CONTROL             0x07, 0x04
-#define TM6010_REQ07_R05_NOISE_THRESHOLD               0x07, 0x05
-#define TM6010_REQ07_R06_AGC_GATE_THRESHOLD            0x07, 0x06
-#define TM6010_REQ07_R07_OUTPUT_CONTROL                        0x07, 0x07
-#define TM6010_REQ07_R08_LUMA_CONTRAST_ADJ             0x07, 0x08
-#define TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ           0x07, 0x09
-#define TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ         0x07, 0x0a
-#define TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ          0x07, 0x0b
-#define TM6010_REQ07_R0C_CHROMA_AGC_CONTROL            0x07, 0x0c
-#define TM6010_REQ07_R0D_CHROMA_KILL_LEVEL             0x07, 0x0d
-#define TM6010_REQ07_R0F_CHROMA_AUTO_POSITION          0x07, 0x0f
-#define TM6010_REQ07_R10_AGC_PEAK_NOMINAL              0x07, 0x10
-#define TM6010_REQ07_R11_AGC_PEAK_CONTROL              0x07, 0x11
-#define TM6010_REQ07_R12_AGC_GATE_STARTH               0x07, 0x12
-#define TM6010_REQ07_R13_AGC_GATE_STARTL               0x07, 0x13
-#define TM6010_REQ07_R14_AGC_GATE_WIDTH                        0x07, 0x14
-#define TM6010_REQ07_R15_AGC_BP_DELAY                  0x07, 0x15
-#define TM6010_REQ07_R16_LOCK_COUNT                    0x07, 0x16
-#define TM6010_REQ07_R17_HLOOP_MAXSTATE                        0x07, 0x17
-#define TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3         0x07, 0x18
-#define TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2         0x07, 0x19
-#define TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1         0x07, 0x1a
-#define TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0         0x07, 0x1b
-#define TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3          0x07, 0x1c
-#define TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2          0x07, 0x1d
-#define TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1          0x07, 0x1e
-#define TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0          0x07, 0x1f
-#define TM6010_REQ07_R20_HSYNC_RISING_EDGE_TIME                0x07, 0x20
-#define TM6010_REQ07_R21_HSYNC_PHASE_OFFSET            0x07, 0x21
-#define TM6010_REQ07_R22_HSYNC_PLL_START_TIME          0x07, 0x22
-#define TM6010_REQ07_R23_HSYNC_PLL_END_TIME            0x07, 0x23
-#define TM6010_REQ07_R24_HSYNC_TIP_START_TIME          0x07, 0x24
-#define TM6010_REQ07_R25_HSYNC_TIP_END_TIME            0x07, 0x25
-#define TM6010_REQ07_R26_HSYNC_RISING_EDGE_START       0x07, 0x26
-#define TM6010_REQ07_R27_HSYNC_RISING_EDGE_END         0x07, 0x27
-#define TM6010_REQ07_R28_BACKPORCH_START               0x07, 0x28
-#define TM6010_REQ07_R29_BACKPORCH_END                 0x07, 0x29
-#define TM6010_REQ07_R2A_HSYNC_FILTER_START            0x07, 0x2a
-#define TM6010_REQ07_R2B_HSYNC_FILTER_END              0x07, 0x2b
-#define TM6010_REQ07_R2C_CHROMA_BURST_START            0x07, 0x2c
-#define TM6010_REQ07_R2D_CHROMA_BURST_END              0x07, 0x2d
-#define TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART           0x07, 0x2e
-#define TM6010_REQ07_R2F_ACTIVE_VIDEO_HWIDTH           0x07, 0x2f
-#define TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART           0x07, 0x30
-#define TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT           0x07, 0x31
-#define TM6010_REQ07_R32_VSYNC_HLOCK_MIN               0x07, 0x32
-#define TM6010_REQ07_R33_VSYNC_HLOCK_MAX               0x07, 0x33
-#define TM6010_REQ07_R34_VSYNC_AGC_MIN                 0x07, 0x34
-#define TM6010_REQ07_R35_VSYNC_AGC_MAX                 0x07, 0x35
-#define TM6010_REQ07_R36_VSYNC_VBI_MIN                 0x07, 0x36
-#define TM6010_REQ07_R37_VSYNC_VBI_MAX                 0x07, 0x37
-#define TM6010_REQ07_R38_VSYNC_THRESHOLD               0x07, 0x38
-#define TM6010_REQ07_R39_VSYNC_TIME_CONSTANT           0x07, 0x39
-#define TM6010_REQ07_R3A_STATUS1                       0x07, 0x3a
-#define TM6010_REQ07_R3B_STATUS2                       0x07, 0x3b
-#define TM6010_REQ07_R3C_STATUS3                       0x07, 0x3c
-#define TM6010_REQ07_R3F_RESET                         0x07, 0x3f
-#define TM6010_REQ07_R40_TELETEXT_VBI_CODE0            0x07, 0x40
-#define TM6010_REQ07_R41_TELETEXT_VBI_CODE1            0x07, 0x41
-#define TM6010_REQ07_R42_VBI_DATA_HIGH_LEVEL           0x07, 0x42
-#define TM6010_REQ07_R43_VBI_DATA_TYPE_LINE7           0x07, 0x43
-#define TM6010_REQ07_R44_VBI_DATA_TYPE_LINE8           0x07, 0x44
-#define TM6010_REQ07_R45_VBI_DATA_TYPE_LINE9           0x07, 0x45
-#define TM6010_REQ07_R46_VBI_DATA_TYPE_LINE10          0x07, 0x46
-#define TM6010_REQ07_R47_VBI_DATA_TYPE_LINE11          0x07, 0x47
-#define TM6010_REQ07_R48_VBI_DATA_TYPE_LINE12          0x07, 0x48
-#define TM6010_REQ07_R49_VBI_DATA_TYPE_LINE13          0x07, 0x49
-#define TM6010_REQ07_R4A_VBI_DATA_TYPE_LINE14          0x07, 0x4a
-#define TM6010_REQ07_R4B_VBI_DATA_TYPE_LINE15          0x07, 0x4b
-#define TM6010_REQ07_R4C_VBI_DATA_TYPE_LINE16          0x07, 0x4c
-#define TM6010_REQ07_R4D_VBI_DATA_TYPE_LINE17          0x07, 0x4d
-#define TM6010_REQ07_R4E_VBI_DATA_TYPE_LINE18          0x07, 0x4e
-#define TM6010_REQ07_R4F_VBI_DATA_TYPE_LINE19          0x07, 0x4f
-#define TM6010_REQ07_R50_VBI_DATA_TYPE_LINE20          0x07, 0x50
-#define TM6010_REQ07_R51_VBI_DATA_TYPE_LINE21          0x07, 0x51
-#define TM6010_REQ07_R52_VBI_DATA_TYPE_LINE22          0x07, 0x52
-#define TM6010_REQ07_R53_VBI_DATA_TYPE_LINE23          0x07, 0x53
-#define TM6010_REQ07_R54_VBI_DATA_TYPE_RLINES          0x07, 0x54
-#define TM6010_REQ07_R55_VBI_LOOP_FILTER_GAIN          0x07, 0x55
-#define TM6010_REQ07_R56_VBI_LOOP_FILTER_I_GAIN                0x07, 0x56
-#define TM6010_REQ07_R57_VBI_LOOP_FILTER_P_GAIN                0x07, 0x57
-#define TM6010_REQ07_R58_VBI_CAPTION_DTO1              0x07, 0x58
-#define TM6010_REQ07_R59_VBI_CAPTION_DTO0              0x07, 0x59
-#define TM6010_REQ07_R5A_VBI_TELETEXT_DTO1             0x07, 0x5a
-#define TM6010_REQ07_R5B_VBI_TELETEXT_DTO0             0x07, 0x5b
-#define TM6010_REQ07_R5C_VBI_WSS625_DTO1               0x07, 0x5c
-#define TM6010_REQ07_R5D_VBI_WSS625_DTO0               0x07, 0x5d
-#define TM6010_REQ07_R5E_VBI_CAPTION_FRAME_START       0x07, 0x5e
-#define TM6010_REQ07_R5F_VBI_WSS625_FRAME_START                0x07, 0x5f
-#define TM6010_REQ07_R60_TELETEXT_FRAME_START          0x07, 0x60
-#define TM6010_REQ07_R61_VBI_CCDATA1                   0x07, 0x61
-#define TM6010_REQ07_R62_VBI_CCDATA2                   0x07, 0x62
-#define TM6010_REQ07_R63_VBI_WSS625_DATA1              0x07, 0x63
-#define TM6010_REQ07_R64_VBI_WSS625_DATA2              0x07, 0x64
-#define TM6010_REQ07_R65_VBI_DATA_STATUS               0x07, 0x65
-#define TM6010_REQ07_R66_VBI_CAPTION_START             0x07, 0x66
-#define TM6010_REQ07_R67_VBI_WSS625_START              0x07, 0x67
-#define TM6010_REQ07_R68_VBI_TELETEXT_START            0x07, 0x68
-#define TM6010_REQ07_R70_HSYNC_DTO_INC_STATUS3         0x07, 0x70
-#define TM6010_REQ07_R71_HSYNC_DTO_INC_STATUS2         0x07, 0x71
-#define TM6010_REQ07_R72_HSYNC_DTO_INC_STATUS1         0x07, 0x72
-#define TM6010_REQ07_R73_HSYNC_DTO_INC_STATUS0         0x07, 0x73
-#define TM6010_REQ07_R74_CHROMA_DTO_INC_STATUS3                0x07, 0x74
-#define TM6010_REQ07_R75_CHROMA_DTO_INC_STATUS2                0x07, 0x75
-#define TM6010_REQ07_R76_CHROMA_DTO_INC_STATUS1                0x07, 0x76
-#define TM6010_REQ07_R77_CHROMA_DTO_INC_STATUS0                0x07, 0x77
-#define TM6010_REQ07_R78_AGC_AGAIN_STATUS              0x07, 0x78
-#define TM6010_REQ07_R79_AGC_DGAIN_STATUS              0x07, 0x79
-#define TM6010_REQ07_R7A_CHROMA_MAG_STATUS             0x07, 0x7a
-#define TM6010_REQ07_R7B_CHROMA_GAIN_STATUS1           0x07, 0x7b
-#define TM6010_REQ07_R7C_CHROMA_GAIN_STATUS0           0x07, 0x7c
-#define TM6010_REQ07_R7D_CORDIC_FREQ_STATUS            0x07, 0x7d
-#define TM6010_REQ07_R7F_STATUS_NOISE                  0x07, 0x7f
-#define TM6010_REQ07_R80_COMB_FILTER_TRESHOLD          0x07, 0x80
-#define TM6010_REQ07_R82_COMB_FILTER_CONFIG            0x07, 0x82
-#define TM6010_REQ07_R83_CHROMA_LOCK_CONFIG            0x07, 0x83
-#define TM6010_REQ07_R84_NOISE_NTSC_C                  0x07, 0x84
-#define TM6010_REQ07_R85_NOISE_PAL_C                   0x07, 0x85
-#define TM6010_REQ07_R86_NOISE_PHASE_C                 0x07, 0x86
-#define TM6010_REQ07_R87_NOISE_PHASE_Y                 0x07, 0x87
-#define TM6010_REQ07_R8A_CHROMA_LOOPFILTER_STATE       0x07, 0x8a
-#define TM6010_REQ07_R8B_CHROMA_HRESAMPLER             0x07, 0x8b
-#define TM6010_REQ07_R8D_CPUMP_DELAY_ADJ               0x07, 0x8d
-#define TM6010_REQ07_R8E_CPUMP_ADJ                     0x07, 0x8e
-#define TM6010_REQ07_R8F_CPUMP_DELAY                   0x07, 0x8f
-
-/* Define TM6000/TM6010 Miscellaneous registers */
-#define TM6010_REQ07_RC0_ACTIVE_VIDEO_SOURCE           0x07, 0xc0
-#define TM6010_REQ07_RC1_TRESHOLD                      0x07, 0xc1
-#define TM6010_REQ07_RC2_HSYNC_WIDTH                   0x07, 0xc2
-#define TM6010_REQ07_RC3_HSTART1                       0x07, 0xc3
-#define TM6010_REQ07_RC4_HSTART0                       0x07, 0xc4
-#define TM6010_REQ07_RC5_HEND1                         0x07, 0xc5
-#define TM6010_REQ07_RC6_HEND0                         0x07, 0xc6
-#define TM6010_REQ07_RC7_VSTART1                       0x07, 0xc7
-#define TM6010_REQ07_RC8_VSTART0                       0x07, 0xc8
-#define TM6010_REQ07_RC9_VEND1                         0x07, 0xc9
-#define TM6010_REQ07_RCA_VEND0                         0x07, 0xca
-#define TM6010_REQ07_RCB_DELAY                         0x07, 0xcb
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RCC_ACTIVE_IF                     0x07, 0xcc
-#define TM6010_REQ07_RCC_ACTIVE_IF_VIDEO_ENABLE (1 << 5)
-#define TM6010_REQ07_RCC_ACTIVE_IF_AUDIO_ENABLE (1 << 6)
-#define TM6010_REQ07_RD0_USB_PERIPHERY_CONTROL         0x07, 0xd0
-#define TM6010_REQ07_RD1_ADDR_FOR_REQ1                 0x07, 0xd1
-#define TM6010_REQ07_RD2_ADDR_FOR_REQ2                 0x07, 0xd2
-#define TM6010_REQ07_RD3_ADDR_FOR_REQ3                 0x07, 0xd3
-#define TM6010_REQ07_RD4_ADDR_FOR_REQ4                 0x07, 0xd4
-#define TM6010_REQ07_RD5_POWERSAVE                     0x07, 0xd5
-#define TM6010_REQ07_RD6_ENDP_REQ1_REQ2                        0x07, 0xd6
-#define TM6010_REQ07_RD7_ENDP_REQ3_REQ4                        0x07, 0xd7
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RD8_IR                            0x07, 0xd8
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RD9_IR_BSIZE                      0x07, 0xd9
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RDA_IR_WAKEUP_SEL                 0x07, 0xda
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RDB_IR_WAKEUP_ADD                 0x07, 0xdb
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RDC_IR_LEADER1                    0x07, 0xdc
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RDD_IR_LEADER0                    0x07, 0xdd
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RDE_IR_PULSE_CNT1                 0x07, 0xde
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RDF_IR_PULSE_CNT0                 0x07, 0xdf
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE0_DVIDEO_SOURCE                 0x07, 0xe0
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE0_DVIDEO_SOURCE_IF              0x07, 0xe1
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE2_OUT_SEL2                      0x07, 0xe2
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE3_OUT_SEL1                      0x07, 0xe3
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE4_OUT_SEL0                      0x07, 0xe4
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE5_REMOTE_WAKEUP                 0x07, 0xe5
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE7_PUB_GPIO                      0x07, 0xe7
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE8_TYPESEL_MOS_I2S               0x07, 0xe8
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RE9_TYPESEL_MOS_TS                        0x07, 0xe9
-/* ONLY for TM6010 */
-#define TM6010_REQ07_REA_TYPESEL_MOS_CCIR              0x07, 0xea
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF0_BIST_CRC_RESULT0              0x07, 0xf0
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF1_BIST_CRC_RESULT1              0x07, 0xf1
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF2_BIST_CRC_RESULT2              0x07, 0xf2
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF3_BIST_CRC_RESULT3              0x07, 0xf3
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF4_BIST_ERR_VST2                 0x07, 0xf4
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF5_BIST_ERR_VST1                 0x07, 0xf5
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF6_BIST_ERR_VST0                 0x07, 0xf6
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RF7_BIST                          0x07, 0xf7
-/* ONLY for TM6010 */
-#define TM6010_REQ07_RFE_POWER_DOWN                    0x07, 0xfe
-#define TM6010_REQ07_RFF_SOFT_RESET                    0x07, 0xff
-
-/* Define TM6000/TM6010 USB registers */
-#define TM6010_REQ05_R00_MAIN_CTRL             0x05, 0x00
-#define TM6010_REQ05_R01_DEVADDR               0x05, 0x01
-#define TM6010_REQ05_R02_TEST                  0x05, 0x02
-#define TM6010_REQ05_R04_SOFN0                 0x05, 0x04
-#define TM6010_REQ05_R05_SOFN1                 0x05, 0x05
-#define TM6010_REQ05_R06_SOFTM0                        0x05, 0x06
-#define TM6010_REQ05_R07_SOFTM1                        0x05, 0x07
-#define TM6010_REQ05_R08_PHY_TEST              0x05, 0x08
-#define TM6010_REQ05_R09_VCTL                  0x05, 0x09
-#define TM6010_REQ05_R0A_VSTA                  0x05, 0x0a
-#define TM6010_REQ05_R0B_CX_CFG                        0x05, 0x0b
-#define TM6010_REQ05_R0C_ENDP0_REG0            0x05, 0x0c
-#define TM6010_REQ05_R10_GMASK                 0x05, 0x10
-#define TM6010_REQ05_R11_IMASK0                        0x05, 0x11
-#define TM6010_REQ05_R12_IMASK1                        0x05, 0x12
-#define TM6010_REQ05_R13_IMASK2                        0x05, 0x13
-#define TM6010_REQ05_R14_IMASK3                        0x05, 0x14
-#define TM6010_REQ05_R15_IMASK4                        0x05, 0x15
-#define TM6010_REQ05_R16_IMASK5                        0x05, 0x16
-#define TM6010_REQ05_R17_IMASK6                        0x05, 0x17
-#define TM6010_REQ05_R18_IMASK7                        0x05, 0x18
-#define TM6010_REQ05_R19_ZEROP0                        0x05, 0x19
-#define TM6010_REQ05_R1A_ZEROP1                        0x05, 0x1a
-#define TM6010_REQ05_R1C_FIFO_EMP0             0x05, 0x1c
-#define TM6010_REQ05_R1D_FIFO_EMP1             0x05, 0x1d
-#define TM6010_REQ05_R20_IRQ_GROUP             0x05, 0x20
-#define TM6010_REQ05_R21_IRQ_SOURCE0           0x05, 0x21
-#define TM6010_REQ05_R22_IRQ_SOURCE1           0x05, 0x22
-#define TM6010_REQ05_R23_IRQ_SOURCE2           0x05, 0x23
-#define TM6010_REQ05_R24_IRQ_SOURCE3           0x05, 0x24
-#define TM6010_REQ05_R25_IRQ_SOURCE4           0x05, 0x25
-#define TM6010_REQ05_R26_IRQ_SOURCE5           0x05, 0x26
-#define TM6010_REQ05_R27_IRQ_SOURCE6           0x05, 0x27
-#define TM6010_REQ05_R28_IRQ_SOURCE7           0x05, 0x28
-#define TM6010_REQ05_R29_SEQ_ERR0              0x05, 0x29
-#define TM6010_REQ05_R2A_SEQ_ERR1              0x05, 0x2a
-#define TM6010_REQ05_R2B_SEQ_ABORT0            0x05, 0x2b
-#define TM6010_REQ05_R2C_SEQ_ABORT1            0x05, 0x2c
-#define TM6010_REQ05_R2D_TX_ZERO0              0x05, 0x2d
-#define TM6010_REQ05_R2E_TX_ZERO1              0x05, 0x2e
-#define TM6010_REQ05_R2F_IDLE_CNT              0x05, 0x2f
-#define TM6010_REQ05_R30_FNO_P1                        0x05, 0x30
-#define TM6010_REQ05_R31_FNO_P2                        0x05, 0x31
-#define TM6010_REQ05_R32_FNO_P3                        0x05, 0x32
-#define TM6010_REQ05_R33_FNO_P4                        0x05, 0x33
-#define TM6010_REQ05_R34_FNO_P5                        0x05, 0x34
-#define TM6010_REQ05_R35_FNO_P6                        0x05, 0x35
-#define TM6010_REQ05_R36_FNO_P7                        0x05, 0x36
-#define TM6010_REQ05_R37_FNO_P8                        0x05, 0x37
-#define TM6010_REQ05_R38_FNO_P9                        0x05, 0x38
-#define TM6010_REQ05_R30_FNO_P10               0x05, 0x39
-#define TM6010_REQ05_R30_FNO_P11               0x05, 0x3a
-#define TM6010_REQ05_R30_FNO_P12               0x05, 0x3b
-#define TM6010_REQ05_R30_FNO_P13               0x05, 0x3c
-#define TM6010_REQ05_R30_FNO_P14               0x05, 0x3d
-#define TM6010_REQ05_R30_FNO_P15               0x05, 0x3e
-#define TM6010_REQ05_R40_IN_MAXPS_LOW1         0x05, 0x40
-#define TM6010_REQ05_R41_IN_MAXPS_HIGH1                0x05, 0x41
-#define TM6010_REQ05_R42_IN_MAXPS_LOW2         0x05, 0x42
-#define TM6010_REQ05_R43_IN_MAXPS_HIGH2                0x05, 0x43
-#define TM6010_REQ05_R44_IN_MAXPS_LOW3         0x05, 0x44
-#define TM6010_REQ05_R45_IN_MAXPS_HIGH3                0x05, 0x45
-#define TM6010_REQ05_R46_IN_MAXPS_LOW4         0x05, 0x46
-#define TM6010_REQ05_R47_IN_MAXPS_HIGH4                0x05, 0x47
-#define TM6010_REQ05_R48_IN_MAXPS_LOW5         0x05, 0x48
-#define TM6010_REQ05_R49_IN_MAXPS_HIGH5                0x05, 0x49
-#define TM6010_REQ05_R4A_IN_MAXPS_LOW6         0x05, 0x4a
-#define TM6010_REQ05_R4B_IN_MAXPS_HIGH6                0x05, 0x4b
-#define TM6010_REQ05_R4C_IN_MAXPS_LOW7         0x05, 0x4c
-#define TM6010_REQ05_R4D_IN_MAXPS_HIGH7                0x05, 0x4d
-#define TM6010_REQ05_R4E_IN_MAXPS_LOW8         0x05, 0x4e
-#define TM6010_REQ05_R4F_IN_MAXPS_HIGH8                0x05, 0x4f
-#define TM6010_REQ05_R50_IN_MAXPS_LOW9         0x05, 0x50
-#define TM6010_REQ05_R51_IN_MAXPS_HIGH9                0x05, 0x51
-#define TM6010_REQ05_R40_IN_MAXPS_LOW10                0x05, 0x52
-#define TM6010_REQ05_R41_IN_MAXPS_HIGH10       0x05, 0x53
-#define TM6010_REQ05_R40_IN_MAXPS_LOW11                0x05, 0x54
-#define TM6010_REQ05_R41_IN_MAXPS_HIGH11       0x05, 0x55
-#define TM6010_REQ05_R40_IN_MAXPS_LOW12                0x05, 0x56
-#define TM6010_REQ05_R41_IN_MAXPS_HIGH12       0x05, 0x57
-#define TM6010_REQ05_R40_IN_MAXPS_LOW13                0x05, 0x58
-#define TM6010_REQ05_R41_IN_MAXPS_HIGH13       0x05, 0x59
-#define TM6010_REQ05_R40_IN_MAXPS_LOW14                0x05, 0x5a
-#define TM6010_REQ05_R41_IN_MAXPS_HIGH14       0x05, 0x5b
-#define TM6010_REQ05_R40_IN_MAXPS_LOW15                0x05, 0x5c
-#define TM6010_REQ05_R41_IN_MAXPS_HIGH15       0x05, 0x5d
-#define TM6010_REQ05_R60_OUT_MAXPS_LOW1                0x05, 0x60
-#define TM6010_REQ05_R61_OUT_MAXPS_HIGH1       0x05, 0x61
-#define TM6010_REQ05_R62_OUT_MAXPS_LOW2                0x05, 0x62
-#define TM6010_REQ05_R63_OUT_MAXPS_HIGH2       0x05, 0x63
-#define TM6010_REQ05_R64_OUT_MAXPS_LOW3                0x05, 0x64
-#define TM6010_REQ05_R65_OUT_MAXPS_HIGH3       0x05, 0x65
-#define TM6010_REQ05_R66_OUT_MAXPS_LOW4                0x05, 0x66
-#define TM6010_REQ05_R67_OUT_MAXPS_HIGH4       0x05, 0x67
-#define TM6010_REQ05_R68_OUT_MAXPS_LOW5                0x05, 0x68
-#define TM6010_REQ05_R69_OUT_MAXPS_HIGH5       0x05, 0x69
-#define TM6010_REQ05_R6A_OUT_MAXPS_LOW6                0x05, 0x6a
-#define TM6010_REQ05_R6B_OUT_MAXPS_HIGH6       0x05, 0x6b
-#define TM6010_REQ05_R6C_OUT_MAXPS_LOW7                0x05, 0x6c
-#define TM6010_REQ05_R6D_OUT_MAXPS_HIGH7       0x05, 0x6d
-#define TM6010_REQ05_R6E_OUT_MAXPS_LOW8                0x05, 0x6e
-#define TM6010_REQ05_R6F_OUT_MAXPS_HIGH8       0x05, 0x6f
-#define TM6010_REQ05_R70_OUT_MAXPS_LOW9                0x05, 0x70
-#define TM6010_REQ05_R71_OUT_MAXPS_HIGH9       0x05, 0x71
-#define TM6010_REQ05_R60_OUT_MAXPS_LOW10       0x05, 0x72
-#define TM6010_REQ05_R61_OUT_MAXPS_HIGH10      0x05, 0x73
-#define TM6010_REQ05_R60_OUT_MAXPS_LOW11       0x05, 0x74
-#define TM6010_REQ05_R61_OUT_MAXPS_HIGH11      0x05, 0x75
-#define TM6010_REQ05_R60_OUT_MAXPS_LOW12       0x05, 0x76
-#define TM6010_REQ05_R61_OUT_MAXPS_HIGH12      0x05, 0x77
-#define TM6010_REQ05_R60_OUT_MAXPS_LOW13       0x05, 0x78
-#define TM6010_REQ05_R61_OUT_MAXPS_HIGH13      0x05, 0x79
-#define TM6010_REQ05_R60_OUT_MAXPS_LOW14       0x05, 0x7a
-#define TM6010_REQ05_R61_OUT_MAXPS_HIGH14      0x05, 0x7b
-#define TM6010_REQ05_R60_OUT_MAXPS_LOW15       0x05, 0x7c
-#define TM6010_REQ05_R61_OUT_MAXPS_HIGH15      0x05, 0x7d
-#define TM6010_REQ05_R80_FIFO0                 0x05, 0x80
-#define TM6010_REQ05_R81_FIFO1                 0x05, 0x81
-#define TM6010_REQ05_R82_FIFO2                 0x05, 0x82
-#define TM6010_REQ05_R83_FIFO3                 0x05, 0x83
-#define TM6010_REQ05_R84_FIFO4                 0x05, 0x84
-#define TM6010_REQ05_R85_FIFO5                 0x05, 0x85
-#define TM6010_REQ05_R86_FIFO6                 0x05, 0x86
-#define TM6010_REQ05_R87_FIFO7                 0x05, 0x87
-#define TM6010_REQ05_R88_FIFO8                 0x05, 0x88
-#define TM6010_REQ05_R89_FIFO9                 0x05, 0x89
-#define TM6010_REQ05_R81_FIFO10                        0x05, 0x8a
-#define TM6010_REQ05_R81_FIFO11                        0x05, 0x8b
-#define TM6010_REQ05_R81_FIFO12                        0x05, 0x8c
-#define TM6010_REQ05_R81_FIFO13                        0x05, 0x8d
-#define TM6010_REQ05_R81_FIFO14                        0x05, 0x8e
-#define TM6010_REQ05_R81_FIFO15                        0x05, 0x8f
-#define TM6010_REQ05_R90_CFG_FIFO0             0x05, 0x90
-#define TM6010_REQ05_R91_CFG_FIFO1             0x05, 0x91
-#define TM6010_REQ05_R92_CFG_FIFO2             0x05, 0x92
-#define TM6010_REQ05_R93_CFG_FIFO3             0x05, 0x93
-#define TM6010_REQ05_R94_CFG_FIFO4             0x05, 0x94
-#define TM6010_REQ05_R95_CFG_FIFO5             0x05, 0x95
-#define TM6010_REQ05_R96_CFG_FIFO6             0x05, 0x96
-#define TM6010_REQ05_R97_CFG_FIFO7             0x05, 0x97
-#define TM6010_REQ05_R98_CFG_FIFO8             0x05, 0x98
-#define TM6010_REQ05_R99_CFG_FIFO9             0x05, 0x99
-#define TM6010_REQ05_R91_CFG_FIFO10            0x05, 0x9a
-#define TM6010_REQ05_R91_CFG_FIFO11            0x05, 0x9b
-#define TM6010_REQ05_R91_CFG_FIFO12            0x05, 0x9c
-#define TM6010_REQ05_R91_CFG_FIFO13            0x05, 0x9d
-#define TM6010_REQ05_R91_CFG_FIFO14            0x05, 0x9e
-#define TM6010_REQ05_R91_CFG_FIFO15            0x05, 0x9f
-#define TM6010_REQ05_RA0_CTL_FIFO0             0x05, 0xa0
-#define TM6010_REQ05_RA1_CTL_FIFO1             0x05, 0xa1
-#define TM6010_REQ05_RA2_CTL_FIFO2             0x05, 0xa2
-#define TM6010_REQ05_RA3_CTL_FIFO3             0x05, 0xa3
-#define TM6010_REQ05_RA4_CTL_FIFO4             0x05, 0xa4
-#define TM6010_REQ05_RA5_CTL_FIFO5             0x05, 0xa5
-#define TM6010_REQ05_RA6_CTL_FIFO6             0x05, 0xa6
-#define TM6010_REQ05_RA7_CTL_FIFO7             0x05, 0xa7
-#define TM6010_REQ05_RA8_CTL_FIFO8             0x05, 0xa8
-#define TM6010_REQ05_RA9_CTL_FIFO9             0x05, 0xa9
-#define TM6010_REQ05_RA1_CTL_FIFO10            0x05, 0xaa
-#define TM6010_REQ05_RA1_CTL_FIFO11            0x05, 0xab
-#define TM6010_REQ05_RA1_CTL_FIFO12            0x05, 0xac
-#define TM6010_REQ05_RA1_CTL_FIFO13            0x05, 0xad
-#define TM6010_REQ05_RA1_CTL_FIFO14            0x05, 0xae
-#define TM6010_REQ05_RA1_CTL_FIFO15            0x05, 0xaf
-#define TM6010_REQ05_RB0_BC_LOW_FIFO0          0x05, 0xb0
-#define TM6010_REQ05_RB1_BC_LOW_FIFO1          0x05, 0xb1
-#define TM6010_REQ05_RB2_BC_LOW_FIFO2          0x05, 0xb2
-#define TM6010_REQ05_RB3_BC_LOW_FIFO3          0x05, 0xb3
-#define TM6010_REQ05_RB4_BC_LOW_FIFO4          0x05, 0xb4
-#define TM6010_REQ05_RB5_BC_LOW_FIFO5          0x05, 0xb5
-#define TM6010_REQ05_RB6_BC_LOW_FIFO6          0x05, 0xb6
-#define TM6010_REQ05_RB7_BC_LOW_FIFO7          0x05, 0xb7
-#define TM6010_REQ05_RB8_BC_LOW_FIFO8          0x05, 0xb8
-#define TM6010_REQ05_RB9_BC_LOW_FIFO9          0x05, 0xb9
-#define TM6010_REQ05_RB1_BC_LOW_FIFO10         0x05, 0xba
-#define TM6010_REQ05_RB1_BC_LOW_FIFO11         0x05, 0xbb
-#define TM6010_REQ05_RB1_BC_LOW_FIFO12         0x05, 0xbc
-#define TM6010_REQ05_RB1_BC_LOW_FIFO13         0x05, 0xbd
-#define TM6010_REQ05_RB1_BC_LOW_FIFO14         0x05, 0xbe
-#define TM6010_REQ05_RB1_BC_LOW_FIFO15         0x05, 0xbf
-#define TM6010_REQ05_RC0_DATA_FIFO0            0x05, 0xc0
-#define TM6010_REQ05_RC4_DATA_FIFO1            0x05, 0xc4
-#define TM6010_REQ05_RC8_DATA_FIFO2            0x05, 0xc8
-#define TM6010_REQ05_RCC_DATA_FIFO3            0x05, 0xcc
-#define TM6010_REQ05_RD0_DATA_FIFO4            0x05, 0xd0
-#define TM6010_REQ05_RD4_DATA_FIFO5            0x05, 0xd4
-#define TM6010_REQ05_RD8_DATA_FIFO6            0x05, 0xd8
-#define TM6010_REQ05_RDC_DATA_FIFO7            0x05, 0xdc
-#define TM6010_REQ05_RE0_DATA_FIFO8            0x05, 0xe0
-#define TM6010_REQ05_RE4_DATA_FIFO9            0x05, 0xe4
-#define TM6010_REQ05_RC4_DATA_FIFO10           0x05, 0xe8
-#define TM6010_REQ05_RC4_DATA_FIFO11           0x05, 0xec
-#define TM6010_REQ05_RC4_DATA_FIFO12           0x05, 0xf0
-#define TM6010_REQ05_RC4_DATA_FIFO13           0x05, 0xf4
-#define TM6010_REQ05_RC4_DATA_FIFO14           0x05, 0xf8
-#define TM6010_REQ05_RC4_DATA_FIFO15           0x05, 0xfc
-
-/* Define TM6010 Audio decoder registers */
-/* This core available only in TM6010 */
-#define TM6010_REQ08_R00_A_VERSION             0x08, 0x00
-#define TM6010_REQ08_R01_A_INIT                        0x08, 0x01
-#define TM6010_REQ08_R02_A_FIX_GAIN_CTRL       0x08, 0x02
-#define TM6010_REQ08_R03_A_AUTO_GAIN_CTRL      0x08, 0x03
-#define TM6010_REQ08_R04_A_SIF_AMP_CTRL                0x08, 0x04
-#define TM6010_REQ08_R05_A_STANDARD_MOD                0x08, 0x05
-#define TM6010_REQ08_R06_A_SOUND_MOD           0x08, 0x06
-#define TM6010_REQ08_R07_A_LEFT_VOL            0x08, 0x07
-#define TM6010_REQ08_R08_A_RIGHT_VOL           0x08, 0x08
-#define TM6010_REQ08_R09_A_MAIN_VOL            0x08, 0x09
-#define TM6010_REQ08_R0A_A_I2S_MOD             0x08, 0x0a
-#define TM6010_REQ08_R0B_A_ASD_THRES1          0x08, 0x0b
-#define TM6010_REQ08_R0C_A_ASD_THRES2          0x08, 0x0c
-#define TM6010_REQ08_R0D_A_AMD_THRES           0x08, 0x0d
-#define TM6010_REQ08_R0E_A_MONO_THRES1         0x08, 0x0e
-#define TM6010_REQ08_R0F_A_MONO_THRES2         0x08, 0x0f
-#define TM6010_REQ08_R10_A_MUTE_THRES1         0x08, 0x10
-#define TM6010_REQ08_R11_A_MUTE_THRES2         0x08, 0x11
-#define TM6010_REQ08_R12_A_AGC_U               0x08, 0x12
-#define TM6010_REQ08_R13_A_AGC_ERR_T           0x08, 0x13
-#define TM6010_REQ08_R14_A_AGC_GAIN_INIT       0x08, 0x14
-#define TM6010_REQ08_R15_A_AGC_STEP_THR                0x08, 0x15
-#define TM6010_REQ08_R16_A_AGC_GAIN_MAX                0x08, 0x16
-#define TM6010_REQ08_R17_A_AGC_GAIN_MIN                0x08, 0x17
-#define TM6010_REQ08_R18_A_TR_CTRL             0x08, 0x18
-#define TM6010_REQ08_R19_A_FH_2FH_GAIN         0x08, 0x19
-#define TM6010_REQ08_R1A_A_NICAM_SER_MAX       0x08, 0x1a
-#define TM6010_REQ08_R1B_A_NICAM_SER_MIN       0x08, 0x1b
-#define TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT     0x08, 0x1e
-#define TM6010_REQ08_R1F_A_TEST_INTF_SEL       0x08, 0x1f
-#define TM6010_REQ08_R20_A_TEST_PIN_SEL                0x08, 0x20
-#define TM6010_REQ08_R21_A_AGC_ERR             0x08, 0x21
-#define TM6010_REQ08_R22_A_AGC_GAIN            0x08, 0x22
-#define TM6010_REQ08_R23_A_NICAM_INFO          0x08, 0x23
-#define TM6010_REQ08_R24_A_SER                 0x08, 0x24
-#define TM6010_REQ08_R25_A_C1_AMP              0x08, 0x25
-#define TM6010_REQ08_R26_A_C2_AMP              0x08, 0x26
-#define TM6010_REQ08_R27_A_NOISE_AMP           0x08, 0x27
-#define TM6010_REQ08_R28_A_AUDIO_MODE_RES      0x08, 0x28
-
-/* Define TM6010 Video ADC registers */
-#define TM6010_REQ08_RE0_ADC_REF               0x08, 0xe0
-#define TM6010_REQ08_RE1_DAC_CLMP              0x08, 0xe1
-#define TM6010_REQ08_RE2_POWER_DOWN_CTRL1      0x08, 0xe2
-#define TM6010_REQ08_RE3_ADC_IN1_SEL           0x08, 0xe3
-#define TM6010_REQ08_RE4_ADC_IN2_SEL           0x08, 0xe4
-#define TM6010_REQ08_RE5_GAIN_PARAM            0x08, 0xe5
-#define TM6010_REQ08_RE6_POWER_DOWN_CTRL2      0x08, 0xe6
-#define TM6010_REQ08_RE7_REG_GAIN_Y            0x08, 0xe7
-#define TM6010_REQ08_RE8_REG_GAIN_C            0x08, 0xe8
-#define TM6010_REQ08_RE9_BIAS_CTRL             0x08, 0xe9
-#define TM6010_REQ08_REA_BUFF_DRV_CTRL         0x08, 0xea
-#define TM6010_REQ08_REB_SIF_GAIN_CTRL         0x08, 0xeb
-#define TM6010_REQ08_REC_REVERSE_YC_CTRL       0x08, 0xec
-#define TM6010_REQ08_RED_GAIN_SEL              0x08, 0xed
-
-/* Define TM6010 Audio ADC registers */
-#define TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG   0x08, 0xf0
-#define TM6010_REQ08_RF1_AADC_POWER_DOWN       0x08, 0xf1
-#define TM6010_REQ08_RF2_LEFT_CHANNEL_VOL      0x08, 0xf2
-#define TM6010_REQ08_RF3_RIGHT_CHANNEL_VOL     0x08, 0xf3
diff --git a/drivers/media/video/tm6000/tm6000-stds.c b/drivers/media/video/tm6000/tm6000-stds.c
deleted file mode 100644 (file)
index 5e28d6a..0000000
+++ /dev/null
@@ -1,638 +0,0 @@
-/*
- *  tm6000-stds.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2007 Mauro Carvalho Chehab <mchehab@redhat.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 version 2
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include "tm6000.h"
-#include "tm6000-regs.h"
-
-static unsigned int tm6010_a_mode;
-module_param(tm6010_a_mode, int, 0644);
-MODULE_PARM_DESC(tm6010_a_mode, "set tm6010 sif audio mode");
-
-struct tm6000_reg_settings {
-       unsigned char req;
-       unsigned char reg;
-       unsigned char value;
-};
-
-
-struct tm6000_std_settings {
-       v4l2_std_id id;
-       struct tm6000_reg_settings *common;
-};
-
-static struct tm6000_reg_settings composite_pal_m[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x04 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x20 },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings composite_pal_nc[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x36 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings composite_pal[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x32 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings composite_secam[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x38 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x02 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2c },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings composite_ntsc[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x00 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x00 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_std_settings composite_stds[] = {
-       { .id = V4L2_STD_PAL_M, .common = composite_pal_m, },
-       { .id = V4L2_STD_PAL_Nc, .common = composite_pal_nc, },
-       { .id = V4L2_STD_PAL, .common = composite_pal, },
-       { .id = V4L2_STD_SECAM, .common = composite_secam, },
-       { .id = V4L2_STD_NTSC, .common = composite_ntsc, },
-};
-
-static struct tm6000_reg_settings svideo_pal_m[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x05 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x83 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x0a },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe0 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings svideo_pal_nc[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x37 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x91 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x1f },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x0c },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings svideo_pal[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x33 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x04 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x25 },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0xd5 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0x63 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0x50 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x0c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x52 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdc },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings svideo_secam[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x39 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0e },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x31 },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x24 },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x92 },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xe8 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xed },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x8c },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x2a },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0xc1 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x2c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x18 },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0xff },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_reg_settings svideo_ntsc[] = {
-       { TM6010_REQ07_R3F_RESET, 0x01 },
-       { TM6010_REQ07_R00_VIDEO_CONTROL0, 0x01 },
-       { TM6010_REQ07_R01_VIDEO_CONTROL1, 0x0f },
-       { TM6010_REQ07_R02_VIDEO_CONTROL2, 0x5f },
-       { TM6010_REQ07_R03_YC_SEP_CONTROL, 0x03 },
-       { TM6010_REQ07_R07_OUTPUT_CONTROL, 0x30 },
-       { TM6010_REQ07_R17_HLOOP_MAXSTATE, 0x8b },
-       { TM6010_REQ07_R18_CHROMA_DTO_INCREMENT3, 0x1e },
-       { TM6010_REQ07_R19_CHROMA_DTO_INCREMENT2, 0x8b },
-       { TM6010_REQ07_R1A_CHROMA_DTO_INCREMENT1, 0xa2 },
-       { TM6010_REQ07_R1B_CHROMA_DTO_INCREMENT0, 0xe9 },
-       { TM6010_REQ07_R1C_HSYNC_DTO_INCREMENT3, 0x1c },
-       { TM6010_REQ07_R1D_HSYNC_DTO_INCREMENT2, 0xcc },
-       { TM6010_REQ07_R1E_HSYNC_DTO_INCREMENT1, 0xcc },
-       { TM6010_REQ07_R1F_HSYNC_DTO_INCREMENT0, 0xcd },
-       { TM6010_REQ07_R2E_ACTIVE_VIDEO_HSTART, 0x88 },
-       { TM6010_REQ07_R30_ACTIVE_VIDEO_VSTART, 0x22 },
-       { TM6010_REQ07_R31_ACTIVE_VIDEO_VHIGHT, 0x61 },
-       { TM6010_REQ07_R33_VSYNC_HLOCK_MAX, 0x1c },
-       { TM6010_REQ07_R35_VSYNC_AGC_MAX, 0x1c },
-       { TM6010_REQ07_R82_COMB_FILTER_CONFIG, 0x42 },
-       { TM6010_REQ07_R83_CHROMA_LOCK_CONFIG, 0x6f },
-       { TM6010_REQ07_R04_LUMA_HAGC_CONTROL, 0xdd },
-       { TM6010_REQ07_R0D_CHROMA_KILL_LEVEL, 0x07 },
-       { TM6010_REQ07_R3F_RESET, 0x00 },
-       { 0, 0, 0 }
-};
-
-static struct tm6000_std_settings svideo_stds[] = {
-       { .id = V4L2_STD_PAL_M, .common = svideo_pal_m, },
-       { .id = V4L2_STD_PAL_Nc, .common = svideo_pal_nc, },
-       { .id = V4L2_STD_PAL, .common = svideo_pal, },
-       { .id = V4L2_STD_SECAM, .common = svideo_secam, },
-       { .id = V4L2_STD_NTSC, .common = svideo_ntsc, },
-};
-
-static int tm6000_set_audio_std(struct tm6000_core *dev)
-{
-       uint8_t areg_02 = 0x04; /* GC1 Fixed gain 0dB */
-       uint8_t areg_05 = 0x01; /* Auto 4.5 = M Japan, Auto 6.5 = DK */
-       uint8_t areg_06 = 0x02; /* Auto de-emphasis, mannual channel mode */
-
-       if (dev->radio) {
-               tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00);
-               tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, 0x04);
-               tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00);
-               tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0x80);
-               tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, 0x0c);
-               /* set mono or stereo */
-               if (dev->amode == V4L2_TUNER_MODE_MONO)
-                       tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x00);
-               else if (dev->amode == V4L2_TUNER_MODE_STEREO)
-                       tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, 0x02);
-               tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x18);
-               tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x0a);
-               tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x40);
-               tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, 0xfe);
-               tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13);
-               tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80);
-               tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, 0xff);
-               return 0;
-       }
-
-       /*
-        * STD/MN shouldn't be affected by tm6010_a_mode, as there's just one
-        * audio standard for each V4L2_STD type.
-        */
-       if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_KR) {
-               areg_05 |= 0x04;
-       } else if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_JP) {
-               areg_05 |= 0x43;
-       } else if (dev->norm & V4L2_STD_MN) {
-               areg_05 |= 0x22;
-       } else switch (tm6010_a_mode) {
-       /* auto */
-       case 0:
-               if ((dev->norm & V4L2_STD_SECAM) == V4L2_STD_SECAM_L)
-                       areg_05 |= 0x00;
-               else    /* Other PAL/SECAM standards */
-                       areg_05 |= 0x10;
-               break;
-       /* A2 */
-       case 1:
-               if (dev->norm & V4L2_STD_DK)
-                       areg_05 = 0x09;
-               else
-                       areg_05 = 0x05;
-               break;
-       /* NICAM */
-       case 2:
-               if (dev->norm & V4L2_STD_DK) {
-                       areg_05 = 0x06;
-               } else if (dev->norm & V4L2_STD_PAL_I) {
-                       areg_05 = 0x08;
-               } else if (dev->norm & V4L2_STD_SECAM_L) {
-                       areg_05 = 0x0a;
-                       areg_02 = 0x02;
-               } else {
-                       areg_05 = 0x07;
-               }
-               break;
-       /* other */
-       case 3:
-               if (dev->norm & V4L2_STD_DK) {
-                       areg_05 = 0x0b;
-               } else {
-                       areg_05 = 0x02;
-               }
-               break;
-       }
-
-       tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x00);
-       tm6000_set_reg(dev, TM6010_REQ08_R02_A_FIX_GAIN_CTRL, areg_02);
-       tm6000_set_reg(dev, TM6010_REQ08_R03_A_AUTO_GAIN_CTRL, 0x00);
-       tm6000_set_reg(dev, TM6010_REQ08_R04_A_SIF_AMP_CTRL, 0xa0);
-       tm6000_set_reg(dev, TM6010_REQ08_R05_A_STANDARD_MOD, areg_05);
-       tm6000_set_reg(dev, TM6010_REQ08_R06_A_SOUND_MOD, areg_06);
-       tm6000_set_reg(dev, TM6010_REQ08_R07_A_LEFT_VOL, 0x00);
-       tm6000_set_reg(dev, TM6010_REQ08_R08_A_RIGHT_VOL, 0x00);
-       tm6000_set_reg(dev, TM6010_REQ08_R09_A_MAIN_VOL, 0x08);
-       tm6000_set_reg(dev, TM6010_REQ08_R0A_A_I2S_MOD, 0x91);
-       tm6000_set_reg(dev, TM6010_REQ08_R0B_A_ASD_THRES1, 0x20);
-       tm6000_set_reg(dev, TM6010_REQ08_R0C_A_ASD_THRES2, 0x12);
-       tm6000_set_reg(dev, TM6010_REQ08_R0D_A_AMD_THRES, 0x20);
-       tm6000_set_reg(dev, TM6010_REQ08_R0E_A_MONO_THRES1, 0xf0);
-       tm6000_set_reg(dev, TM6010_REQ08_R0F_A_MONO_THRES2, 0x80);
-       tm6000_set_reg(dev, TM6010_REQ08_R10_A_MUTE_THRES1, 0xc0);
-       tm6000_set_reg(dev, TM6010_REQ08_R11_A_MUTE_THRES2, 0x80);
-       tm6000_set_reg(dev, TM6010_REQ08_R12_A_AGC_U, 0x12);
-       tm6000_set_reg(dev, TM6010_REQ08_R13_A_AGC_ERR_T, 0xfe);
-       tm6000_set_reg(dev, TM6010_REQ08_R14_A_AGC_GAIN_INIT, 0x20);
-       tm6000_set_reg(dev, TM6010_REQ08_R15_A_AGC_STEP_THR, 0x14);
-       tm6000_set_reg(dev, TM6010_REQ08_R16_A_AGC_GAIN_MAX, 0xfe);
-       tm6000_set_reg(dev, TM6010_REQ08_R17_A_AGC_GAIN_MIN, 0x01);
-       tm6000_set_reg(dev, TM6010_REQ08_R18_A_TR_CTRL, 0xa0);
-       tm6000_set_reg(dev, TM6010_REQ08_R19_A_FH_2FH_GAIN, 0x32);
-       tm6000_set_reg(dev, TM6010_REQ08_R1A_A_NICAM_SER_MAX, 0x64);
-       tm6000_set_reg(dev, TM6010_REQ08_R1B_A_NICAM_SER_MIN, 0x20);
-       tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1c, 0x00);
-       tm6000_set_reg(dev, REQ_08_SET_GET_AVREG_BIT, 0x1d, 0x00);
-       tm6000_set_reg(dev, TM6010_REQ08_R1E_A_GAIN_DEEMPH_OUT, 0x13);
-       tm6000_set_reg(dev, TM6010_REQ08_R1F_A_TEST_INTF_SEL, 0x00);
-       tm6000_set_reg(dev, TM6010_REQ08_R20_A_TEST_PIN_SEL, 0x00);
-       tm6000_set_reg(dev, TM6010_REQ08_R01_A_INIT, 0x80);
-
-       return 0;
-}
-
-void tm6000_get_std_res(struct tm6000_core *dev)
-{
-       /* Currently, those are the only supported resoltions */
-       if (dev->norm & V4L2_STD_525_60)
-               dev->height = 480;
-       else
-               dev->height = 576;
-
-       dev->width = 720;
-}
-
-static int tm6000_load_std(struct tm6000_core *dev, struct tm6000_reg_settings *set)
-{
-       int i, rc;
-
-       /* Load board's initialization table */
-       for (i = 0; set[i].req; i++) {
-               rc = tm6000_set_reg(dev, set[i].req, set[i].reg, set[i].value);
-               if (rc < 0) {
-                       printk(KERN_ERR "Error %i while setting "
-                              "req %d, reg %d to value %d\n",
-                              rc, set[i].req, set[i].reg, set[i].value);
-                       return rc;
-               }
-       }
-
-       return 0;
-}
-
-int tm6000_set_standard(struct tm6000_core *dev)
-{
-       struct tm6000_input *input;
-       int i, rc = 0;
-       u8 reg_07_fe = 0x8a;
-       u8 reg_08_f1 = 0xfc;
-       u8 reg_08_e2 = 0xf0;
-       u8 reg_08_e6 = 0x0f;
-
-       tm6000_get_std_res(dev);
-
-       if (!dev->radio)
-               input = &dev->vinput[dev->input];
-       else
-               input = &dev->rinput;
-
-       if (dev->dev_type == TM6010) {
-               switch (input->vmux) {
-               case TM6000_VMUX_VIDEO_A:
-                       tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf4);
-                       tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1);
-                       tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0);
-                       tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
-                       tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8);
-                       reg_07_fe |= 0x01;
-                       break;
-               case TM6000_VMUX_VIDEO_B:
-                       tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xf8);
-                       tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf1);
-                       tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xe0);
-                       tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
-                       tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe8);
-                       reg_07_fe |= 0x01;
-                       break;
-               case TM6000_VMUX_VIDEO_AB:
-                       tm6000_set_reg(dev, TM6010_REQ08_RE3_ADC_IN1_SEL, 0xfc);
-                       tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf8);
-                       reg_08_e6 = 0x00;
-                       tm6000_set_reg(dev, TM6010_REQ08_REA_BUFF_DRV_CTRL, 0xf2);
-                       tm6000_set_reg(dev, TM6010_REQ08_REB_SIF_GAIN_CTRL, 0xf0);
-                       tm6000_set_reg(dev, TM6010_REQ08_REC_REVERSE_YC_CTRL, 0xc2);
-                       tm6000_set_reg(dev, TM6010_REQ08_RED_GAIN_SEL, 0xe0);
-                       break;
-               default:
-                       break;
-               }
-               switch (input->amux) {
-               case TM6000_AMUX_ADC1:
-                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
-                               0x00, 0x0f);
-                       /* Mux overflow workaround */
-                       tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
-                               0x10, 0xf0);
-                       break;
-               case TM6000_AMUX_ADC2:
-                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
-                               0x08, 0x0f);
-                       /* Mux overflow workaround */
-                       tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
-                               0x10, 0xf0);
-                       break;
-               case TM6000_AMUX_SIF1:
-                       reg_08_e2 |= 0x02;
-                       reg_08_e6 = 0x08;
-                       reg_07_fe |= 0x40;
-                       reg_08_f1 |= 0x02;
-                       tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3);
-                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
-                               0x02, 0x0f);
-                       /* Mux overflow workaround */
-                       tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
-                               0x30, 0xf0);
-                       break;
-               case TM6000_AMUX_SIF2:
-                       reg_08_e2 |= 0x02;
-                       reg_08_e6 = 0x08;
-                       reg_07_fe |= 0x40;
-                       reg_08_f1 |= 0x02;
-                       tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf7);
-                       tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG,
-                               0x02, 0x0f);
-                       /* Mux overflow workaround */
-                       tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL,
-                               0x30, 0xf0);
-                       break;
-               default:
-                       break;
-               }
-               tm6000_set_reg(dev, TM6010_REQ08_RE2_POWER_DOWN_CTRL1, reg_08_e2);
-               tm6000_set_reg(dev, TM6010_REQ08_RE6_POWER_DOWN_CTRL2, reg_08_e6);
-               tm6000_set_reg(dev, TM6010_REQ08_RF1_AADC_POWER_DOWN, reg_08_f1);
-               tm6000_set_reg(dev, TM6010_REQ07_RFE_POWER_DOWN, reg_07_fe);
-       } else {
-               switch (input->vmux) {
-               case TM6000_VMUX_VIDEO_A:
-                       tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10);
-                       tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00);
-                       tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f);
-                       tm6000_set_reg(dev,
-                           REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0);
-                       break;
-               case TM6000_VMUX_VIDEO_B:
-                       tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x00);
-                       tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x00);
-                       tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x0f);
-                       tm6000_set_reg(dev,
-                           REQ_03_SET_GET_MCU_PIN, input->v_gpio, 0);
-                       break;
-               case TM6000_VMUX_VIDEO_AB:
-                       tm6000_set_reg(dev, TM6000_REQ07_RE3_VADC_INP_LPF_SEL1, 0x10);
-                       tm6000_set_reg(dev, TM6000_REQ07_RE5_VADC_INP_LPF_SEL2, 0x10);
-                       tm6000_set_reg(dev, TM6000_REQ07_RE8_VADC_PWDOWN_CTL, 0x00);
-                       tm6000_set_reg(dev,
-                           REQ_03_SET_GET_MCU_PIN, input->v_gpio, 1);
-                       break;
-               default:
-                       break;
-               }
-               switch (input->amux) {
-               case TM6000_AMUX_ADC1:
-                       tm6000_set_reg_mask(dev,
-                               TM6000_REQ07_REB_VADC_AADC_MODE, 0x00, 0x0f);
-                       break;
-               case TM6000_AMUX_ADC2:
-                       tm6000_set_reg_mask(dev,
-                               TM6000_REQ07_REB_VADC_AADC_MODE, 0x04, 0x0f);
-                       break;
-               default:
-                       break;
-               }
-       }
-       if (input->type == TM6000_INPUT_SVIDEO) {
-               for (i = 0; i < ARRAY_SIZE(svideo_stds); i++) {
-                       if (dev->norm & svideo_stds[i].id) {
-                               rc = tm6000_load_std(dev, svideo_stds[i].common);
-                               goto ret;
-                       }
-               }
-               return -EINVAL;
-       } else {
-               for (i = 0; i < ARRAY_SIZE(composite_stds); i++) {
-                       if (dev->norm & composite_stds[i].id) {
-                               rc = tm6000_load_std(dev, composite_stds[i].common);
-                               goto ret;
-                       }
-               }
-               return -EINVAL;
-       }
-
-ret:
-       if (rc < 0)
-               return rc;
-
-       if ((dev->dev_type == TM6010) &&
-           ((input->amux == TM6000_AMUX_SIF1) ||
-           (input->amux == TM6000_AMUX_SIF2)))
-               tm6000_set_audio_std(dev);
-
-       msleep(40);
-
-       return 0;
-}
diff --git a/drivers/media/video/tm6000/tm6000-usb-isoc.h b/drivers/media/video/tm6000/tm6000-usb-isoc.h
deleted file mode 100644 (file)
index 99d15a5..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  tm6000-buf.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation version 2
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/videodev2.h>
-
-#define TM6000_URB_MSG_LEN 180
-
-struct usb_isoc_ctl {
-               /* max packet size of isoc transaction */
-       int                             max_pkt_size;
-
-               /* number of allocated urbs */
-       int                             num_bufs;
-
-               /* urb for isoc transfers */
-       struct urb                      **urb;
-
-               /* transfer buffers for isoc transfer */
-       char                            **transfer_buffer;
-
-               /* Last buffer command and region */
-       u8                              cmd;
-       int                             pos, size, pktsize;
-
-               /* Last field: ODD or EVEN? */
-       int                             vfield, field;
-
-               /* Stores incomplete commands */
-       u32                             tmp_buf;
-       int                             tmp_buf_len;
-
-               /* Stores already requested buffers */
-       struct tm6000_buffer            *buf;
-};
diff --git a/drivers/media/video/tm6000/tm6000-video.c b/drivers/media/video/tm6000/tm6000-video.c
deleted file mode 100644 (file)
index 45ed59c..0000000
+++ /dev/null
@@ -1,1852 +0,0 @@
-/*
- *   tm6000-video.c - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
- *     - Fixed module load/unload
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation version 2
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#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/ioport.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/random.h>
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-ioctl.h>
-#include <media/tuner.h>
-#include <linux/interrupt.h>
-#include <linux/kthread.h>
-#include <linux/highmem.h>
-#include <linux/freezer.h>
-
-#include "tm6000-regs.h"
-#include "tm6000.h"
-
-#define BUFFER_TIMEOUT     msecs_to_jiffies(2000)  /* 2 seconds */
-
-/* Limits minimum and default number of buffers */
-#define TM6000_MIN_BUF 4
-#define TM6000_DEF_BUF 8
-
-#define TM6000_MAX_ISO_PACKETS 46      /* Max number of ISO packets */
-
-/* Declare static vars that will be used as parameters */
-static unsigned int vid_limit = 16;    /* Video memory limit, in Mb */
-static int video_nr = -1;              /* /dev/videoN, -1 for autodetect */
-static int radio_nr = -1;              /* /dev/radioN, -1 for autodetect */
-
-/* Debug level */
-int tm6000_debug;
-EXPORT_SYMBOL_GPL(tm6000_debug);
-
-static const struct v4l2_queryctrl no_ctrl = {
-       .name  = "42",
-       .flags = V4L2_CTRL_FLAG_DISABLED,
-};
-
-/* supported controls */
-static struct v4l2_queryctrl tm6000_qctrl[] = {
-       {
-               .id            = V4L2_CID_BRIGHTNESS,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Brightness",
-               .minimum       = 0,
-               .maximum       = 255,
-               .step          = 1,
-               .default_value = 54,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_CONTRAST,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Contrast",
-               .minimum       = 0,
-               .maximum       = 255,
-               .step          = 0x1,
-               .default_value = 119,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_SATURATION,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Saturation",
-               .minimum       = 0,
-               .maximum       = 255,
-               .step          = 0x1,
-               .default_value = 112,
-               .flags         = 0,
-       }, {
-               .id            = V4L2_CID_HUE,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-               .name          = "Hue",
-               .minimum       = -128,
-               .maximum       = 127,
-               .step          = 0x1,
-               .default_value = 0,
-               .flags         = 0,
-       },
-               /* --- audio --- */
-       {
-               .id            = V4L2_CID_AUDIO_MUTE,
-               .name          = "Mute",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
-       }, {
-               .id            = V4L2_CID_AUDIO_VOLUME,
-               .name          = "Volume",
-               .minimum       = -15,
-               .maximum       = 15,
-               .step          = 1,
-               .default_value = 0,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
-       }
-};
-
-static const unsigned int CTRLS = ARRAY_SIZE(tm6000_qctrl);
-static int qctl_regs[ARRAY_SIZE(tm6000_qctrl)];
-
-static struct tm6000_fmt format[] = {
-       {
-               .name     = "4:2:2, packed, YVY2",
-               .fourcc   = V4L2_PIX_FMT_YUYV,
-               .depth    = 16,
-       }, {
-               .name     = "4:2:2, packed, UYVY",
-               .fourcc   = V4L2_PIX_FMT_UYVY,
-               .depth    = 16,
-       }, {
-               .name     = "A/V + VBI mux packet",
-               .fourcc   = V4L2_PIX_FMT_TM6000,
-               .depth    = 16,
-       }
-};
-
-static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id)
-{
-       unsigned int i;
-
-       for (i = 0; i < CTRLS; i++)
-               if (tm6000_qctrl[i].id == id)
-                       return tm6000_qctrl+i;
-       return NULL;
-}
-
-/* ------------------------------------------------------------------
- *     DMA and thread functions
- * ------------------------------------------------------------------
- */
-
-#define norm_maxw(a) 720
-#define norm_maxh(a) 576
-
-#define norm_minw(a) norm_maxw(a)
-#define norm_minh(a) norm_maxh(a)
-
-/*
- * video-buf generic routine to get the next available buffer
- */
-static inline void get_next_buf(struct tm6000_dmaqueue *dma_q,
-                              struct tm6000_buffer   **buf)
-{
-       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
-
-       if (list_empty(&dma_q->active)) {
-               dprintk(dev, V4L2_DEBUG_QUEUE, "No active queue to serve\n");
-               *buf = NULL;
-               return;
-       }
-
-       *buf = list_entry(dma_q->active.next,
-                       struct tm6000_buffer, vb.queue);
-}
-
-/*
- * Announces that a buffer were filled and request the next
- */
-static inline void buffer_filled(struct tm6000_core *dev,
-                                struct tm6000_dmaqueue *dma_q,
-                                struct tm6000_buffer *buf)
-{
-       /* Advice that buffer was filled */
-       dprintk(dev, V4L2_DEBUG_ISOC, "[%p/%d] wakeup\n", buf, buf->vb.i);
-       buf->vb.state = VIDEOBUF_DONE;
-       buf->vb.field_count++;
-       do_gettimeofday(&buf->vb.ts);
-
-       list_del(&buf->vb.queue);
-       wake_up(&buf->vb.done);
-}
-
-/*
- * Identify the tm5600/6000 buffer header type and properly handles
- */
-static int copy_streams(u8 *data, unsigned long len,
-                       struct urb *urb)
-{
-       struct tm6000_dmaqueue  *dma_q = urb->context;
-       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
-       u8 *ptr = data, *endp = data+len;
-       unsigned long header = 0;
-       int rc = 0;
-       unsigned int cmd, cpysize, pktsize, size, field, block, line, pos = 0;
-       struct tm6000_buffer *vbuf = NULL;
-       char *voutp = NULL;
-       unsigned int linewidth;
-
-       if (!dev->radio) {
-               /* get video buffer */
-               get_next_buf(dma_q, &vbuf);
-
-               if (!vbuf)
-                       return rc;
-               voutp = videobuf_to_vmalloc(&vbuf->vb);
-
-               if (!voutp)
-                       return 0;
-       }
-
-       for (ptr = data; ptr < endp;) {
-               if (!dev->isoc_ctl.cmd) {
-                       /* Header */
-                       if (dev->isoc_ctl.tmp_buf_len > 0) {
-                               /* from last urb or packet */
-                               header = dev->isoc_ctl.tmp_buf;
-                               if (4 - dev->isoc_ctl.tmp_buf_len > 0) {
-                                       memcpy((u8 *)&header +
-                                               dev->isoc_ctl.tmp_buf_len,
-                                               ptr,
-                                               4 - dev->isoc_ctl.tmp_buf_len);
-                                       ptr += 4 - dev->isoc_ctl.tmp_buf_len;
-                               }
-                               dev->isoc_ctl.tmp_buf_len = 0;
-                       } else {
-                               if (ptr + 3 >= endp) {
-                                       /* have incomplete header */
-                                       dev->isoc_ctl.tmp_buf_len = endp - ptr;
-                                       memcpy(&dev->isoc_ctl.tmp_buf, ptr,
-                                               dev->isoc_ctl.tmp_buf_len);
-                                       return rc;
-                               }
-                               /* Seek for sync */
-                               for (; ptr < endp - 3; ptr++) {
-                                       if (*(ptr + 3) == 0x47)
-                                               break;
-                               }
-                               /* Get message header */
-                               header = *(unsigned long *)ptr;
-                               ptr += 4;
-                       }
-
-                       /* split the header fields */
-                       size = ((header & 0x7e) << 1);
-                       if (size > 0)
-                               size -= 4;
-                       block = (header >> 7) & 0xf;
-                       field = (header >> 11) & 0x1;
-                       line  = (header >> 12) & 0x1ff;
-                       cmd   = (header >> 21) & 0x7;
-                       /* Validates haeder fields */
-                       if (size > TM6000_URB_MSG_LEN)
-                               size = TM6000_URB_MSG_LEN;
-                       pktsize = TM6000_URB_MSG_LEN;
-                       /*
-                        * calculate position in buffer and change the buffer
-                        */
-                       switch (cmd) {
-                       case TM6000_URB_MSG_VIDEO:
-                               if (!dev->radio) {
-                                       if ((dev->isoc_ctl.vfield != field) &&
-                                               (field == 1)) {
-                                               /*
-                                                * Announces that a new buffer
-                                                * were filled
-                                                */
-                                               buffer_filled(dev, dma_q, vbuf);
-                                               dprintk(dev, V4L2_DEBUG_ISOC,
-                                                       "new buffer filled\n");
-                                               get_next_buf(dma_q, &vbuf);
-                                               if (!vbuf)
-                                                       return rc;
-                                               voutp = videobuf_to_vmalloc(&vbuf->vb);
-                                               if (!voutp)
-                                                       return rc;
-                                               memset(voutp, 0, vbuf->vb.size);
-                                       }
-                                       linewidth = vbuf->vb.width << 1;
-                                       pos = ((line << 1) - field - 1) *
-                                       linewidth + block * TM6000_URB_MSG_LEN;
-                                       /* Don't allow to write out of the buffer */
-                                       if (pos + size > vbuf->vb.size)
-                                               cmd = TM6000_URB_MSG_ERR;
-                                       dev->isoc_ctl.vfield = field;
-                               }
-                               break;
-                       case TM6000_URB_MSG_VBI:
-                               break;
-                       case TM6000_URB_MSG_AUDIO:
-                       case TM6000_URB_MSG_PTS:
-                               size = pktsize; /* Size is always 180 bytes */
-                               break;
-                       }
-               } else {
-                       /* Continue the last copy */
-                       cmd = dev->isoc_ctl.cmd;
-                       size = dev->isoc_ctl.size;
-                       pos = dev->isoc_ctl.pos;
-                       pktsize = dev->isoc_ctl.pktsize;
-                       field = dev->isoc_ctl.field;
-               }
-               cpysize = (endp - ptr > size) ? size : endp - ptr;
-               if (cpysize) {
-                       /* copy data in different buffers */
-                       switch (cmd) {
-                       case TM6000_URB_MSG_VIDEO:
-                               /* Fills video buffer */
-                               if (vbuf)
-                                       memcpy(&voutp[pos], ptr, cpysize);
-                               break;
-                       case TM6000_URB_MSG_AUDIO: {
-                               int i;
-                               for (i = 0; i < cpysize; i += 2)
-                                       swab16s((u16 *)(ptr + i));
-
-                               tm6000_call_fillbuf(dev, TM6000_AUDIO, ptr, cpysize);
-                               break;
-                       }
-                       case TM6000_URB_MSG_VBI:
-                               /* Need some code to copy vbi buffer */
-                               break;
-                       case TM6000_URB_MSG_PTS: {
-                               /* Need some code to copy pts */
-                               u32 pts;
-                               pts = *(u32 *)ptr;
-                               dprintk(dev, V4L2_DEBUG_ISOC, "field %d, PTS %x",
-                                       field, pts);
-                               break;
-                       }
-                       }
-               }
-               if (ptr + pktsize > endp) {
-                       /*
-                        * End of URB packet, but cmd processing is not
-                        * complete. Preserve the state for a next packet
-                        */
-                       dev->isoc_ctl.pos = pos + cpysize;
-                       dev->isoc_ctl.size = size - cpysize;
-                       dev->isoc_ctl.cmd = cmd;
-                       dev->isoc_ctl.field = field;
-                       dev->isoc_ctl.pktsize = pktsize - (endp - ptr);
-                       ptr += endp - ptr;
-               } else {
-                       dev->isoc_ctl.cmd = 0;
-                       ptr += pktsize;
-               }
-       }
-       return 0;
-}
-
-/*
- * Identify the tm5600/6000 buffer header type and properly handles
- */
-static int copy_multiplexed(u8 *ptr, unsigned long len,
-                       struct urb *urb)
-{
-       struct tm6000_dmaqueue  *dma_q = urb->context;
-       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
-       unsigned int pos = dev->isoc_ctl.pos, cpysize;
-       int rc = 1;
-       struct tm6000_buffer *buf;
-       char *outp = NULL;
-
-       get_next_buf(dma_q, &buf);
-       if (buf)
-               outp = videobuf_to_vmalloc(&buf->vb);
-
-       if (!outp)
-               return 0;
-
-       while (len > 0) {
-               cpysize = min(len, buf->vb.size-pos);
-               memcpy(&outp[pos], ptr, cpysize);
-               pos += cpysize;
-               ptr += cpysize;
-               len -= cpysize;
-               if (pos >= buf->vb.size) {
-                       pos = 0;
-                       /* Announces that a new buffer were filled */
-                       buffer_filled(dev, dma_q, buf);
-                       dprintk(dev, V4L2_DEBUG_ISOC, "new buffer filled\n");
-                       get_next_buf(dma_q, &buf);
-                       if (!buf)
-                               break;
-                       outp = videobuf_to_vmalloc(&(buf->vb));
-                       if (!outp)
-                               return rc;
-                       pos = 0;
-               }
-       }
-
-       dev->isoc_ctl.pos = pos;
-       return rc;
-}
-
-static inline void print_err_status(struct tm6000_core *dev,
-                                    int packet, int status)
-{
-       char *errmsg = "Unknown";
-
-       switch (status) {
-       case -ENOENT:
-               errmsg = "unlinked synchronuously";
-               break;
-       case -ECONNRESET:
-               errmsg = "unlinked asynchronuously";
-               break;
-       case -ENOSR:
-               errmsg = "Buffer error (overrun)";
-               break;
-       case -EPIPE:
-               errmsg = "Stalled (device not responding)";
-               break;
-       case -EOVERFLOW:
-               errmsg = "Babble (bad cable?)";
-               break;
-       case -EPROTO:
-               errmsg = "Bit-stuff error (bad cable?)";
-               break;
-       case -EILSEQ:
-               errmsg = "CRC/Timeout (could be anything)";
-               break;
-       case -ETIME:
-               errmsg = "Device does not respond";
-               break;
-       }
-       if (packet < 0) {
-               dprintk(dev, V4L2_DEBUG_QUEUE, "URB status %d [%s].\n",
-                       status, errmsg);
-       } else {
-               dprintk(dev, V4L2_DEBUG_QUEUE, "URB packet %d, status %d [%s].\n",
-                       packet, status, errmsg);
-       }
-}
-
-
-/*
- * Controls the isoc copy of each urb packet
- */
-static inline int tm6000_isoc_copy(struct urb *urb)
-{
-       struct tm6000_dmaqueue  *dma_q = urb->context;
-       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
-       int i, len = 0, rc = 1, status;
-       char *p;
-
-       if (urb->status < 0) {
-               print_err_status(dev, -1, urb->status);
-               return 0;
-       }
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               status = urb->iso_frame_desc[i].status;
-
-               if (status < 0) {
-                       print_err_status(dev, i, status);
-                       continue;
-               }
-
-               len = urb->iso_frame_desc[i].actual_length;
-
-               if (len > 0) {
-                       p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-                       if (!urb->iso_frame_desc[i].status) {
-                               if ((dev->fourcc) == V4L2_PIX_FMT_TM6000) {
-                                       rc = copy_multiplexed(p, len, urb);
-                                       if (rc <= 0)
-                                               return rc;
-                               } else {
-                                       copy_streams(p, len, urb);
-                               }
-                       }
-               }
-       }
-       return rc;
-}
-
-/* ------------------------------------------------------------------
- *     URB control
- * ------------------------------------------------------------------
- */
-
-/*
- * IRQ callback, called by URB callback
- */
-static void tm6000_irq_callback(struct urb *urb)
-{
-       struct tm6000_dmaqueue  *dma_q = urb->context;
-       struct tm6000_core *dev = container_of(dma_q, struct tm6000_core, vidq);
-       int i;
-
-       switch (urb->status) {
-       case 0:
-       case -ETIMEDOUT:
-               break;
-
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               return;
-
-       default:
-               tm6000_err("urb completion error %d.\n", urb->status);
-               break;
-       }
-
-       spin_lock(&dev->slock);
-       tm6000_isoc_copy(urb);
-       spin_unlock(&dev->slock);
-
-       /* Reset urb buffers */
-       for (i = 0; i < urb->number_of_packets; i++) {
-               urb->iso_frame_desc[i].status = 0;
-               urb->iso_frame_desc[i].actual_length = 0;
-       }
-
-       urb->status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (urb->status)
-               tm6000_err("urb resubmit failed (error=%i)\n",
-                       urb->status);
-}
-
-/*
- * Stop and Deallocate URBs
- */
-static void tm6000_uninit_isoc(struct tm6000_core *dev)
-{
-       struct urb *urb;
-       int i;
-
-       dev->isoc_ctl.buf = NULL;
-       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
-               urb = dev->isoc_ctl.urb[i];
-               if (urb) {
-                       usb_kill_urb(urb);
-                       usb_unlink_urb(urb);
-                       if (dev->isoc_ctl.transfer_buffer[i]) {
-                               usb_free_coherent(dev->udev,
-                                               urb->transfer_buffer_length,
-                                               dev->isoc_ctl.transfer_buffer[i],
-                                               urb->transfer_dma);
-                       }
-                       usb_free_urb(urb);
-                       dev->isoc_ctl.urb[i] = NULL;
-               }
-               dev->isoc_ctl.transfer_buffer[i] = NULL;
-       }
-
-       kfree(dev->isoc_ctl.urb);
-       kfree(dev->isoc_ctl.transfer_buffer);
-
-       dev->isoc_ctl.urb = NULL;
-       dev->isoc_ctl.transfer_buffer = NULL;
-       dev->isoc_ctl.num_bufs = 0;
-}
-
-/*
- * Allocate URBs and start IRQ
- */
-static int tm6000_prepare_isoc(struct tm6000_core *dev)
-{
-       struct tm6000_dmaqueue *dma_q = &dev->vidq;
-       int i, j, sb_size, pipe, size, max_packets, num_bufs = 8;
-       struct urb *urb;
-
-       /* De-allocates all pending stuff */
-       tm6000_uninit_isoc(dev);
-       /* Stop interrupt USB pipe */
-       tm6000_ir_int_stop(dev);
-
-       usb_set_interface(dev->udev,
-                         dev->isoc_in.bInterfaceNumber,
-                         dev->isoc_in.bAlternateSetting);
-
-       /* Start interrupt USB pipe */
-       tm6000_ir_int_start(dev);
-
-       pipe = usb_rcvisocpipe(dev->udev,
-                              dev->isoc_in.endp->desc.bEndpointAddress &
-                              USB_ENDPOINT_NUMBER_MASK);
-
-       size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe));
-
-       if (size > dev->isoc_in.maxsize)
-               size = dev->isoc_in.maxsize;
-
-       dev->isoc_ctl.max_pkt_size = size;
-
-       max_packets = TM6000_MAX_ISO_PACKETS;
-       sb_size = max_packets * size;
-
-       dev->isoc_ctl.num_bufs = num_bufs;
-
-       dev->isoc_ctl.urb = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
-       if (!dev->isoc_ctl.urb) {
-               tm6000_err("cannot alloc memory for usb buffers\n");
-               return -ENOMEM;
-       }
-
-       dev->isoc_ctl.transfer_buffer = kmalloc(sizeof(void *)*num_bufs,
-                                  GFP_KERNEL);
-       if (!dev->isoc_ctl.transfer_buffer) {
-               tm6000_err("cannot allocate memory for usbtransfer\n");
-               kfree(dev->isoc_ctl.urb);
-               return -ENOMEM;
-       }
-
-       dprintk(dev, V4L2_DEBUG_QUEUE, "Allocating %d x %d packets"
-                   " (%d bytes) of %d bytes each to handle %u size\n",
-                   max_packets, num_bufs, sb_size,
-                   dev->isoc_in.maxsize, size);
-
-       /* allocate urbs and transfer buffers */
-       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
-               urb = usb_alloc_urb(max_packets, GFP_KERNEL);
-               if (!urb) {
-                       tm6000_err("cannot alloc isoc_ctl.urb %i\n", i);
-                       tm6000_uninit_isoc(dev);
-                       usb_free_urb(urb);
-                       return -ENOMEM;
-               }
-               dev->isoc_ctl.urb[i] = urb;
-
-               dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev,
-                       sb_size, GFP_KERNEL, &urb->transfer_dma);
-               if (!dev->isoc_ctl.transfer_buffer[i]) {
-                       tm6000_err("unable to allocate %i bytes for transfer"
-                                       " buffer %i%s\n",
-                                       sb_size, i,
-                                       in_interrupt() ? " while in int" : "");
-                       tm6000_uninit_isoc(dev);
-                       return -ENOMEM;
-               }
-               memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
-
-               usb_fill_bulk_urb(urb, dev->udev, pipe,
-                                 dev->isoc_ctl.transfer_buffer[i], sb_size,
-                                 tm6000_irq_callback, dma_q);
-               urb->interval = dev->isoc_in.endp->desc.bInterval;
-               urb->number_of_packets = max_packets;
-               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-
-               for (j = 0; j < max_packets; j++) {
-                       urb->iso_frame_desc[j].offset = size * j;
-                       urb->iso_frame_desc[j].length = size;
-               }
-       }
-
-       return 0;
-}
-
-static int tm6000_start_thread(struct tm6000_core *dev)
-{
-       struct tm6000_dmaqueue *dma_q = &dev->vidq;
-       int i;
-
-       dma_q->frame = 0;
-       dma_q->ini_jiffies = jiffies;
-
-       init_waitqueue_head(&dma_q->wq);
-
-       /* submit urbs and enables IRQ */
-       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
-               int rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_ATOMIC);
-               if (rc) {
-                       tm6000_err("submit of urb %i failed (error=%i)\n", i,
-                                  rc);
-                       tm6000_uninit_isoc(dev);
-                       return rc;
-               }
-       }
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------
- *     Videobuf operations
- * ------------------------------------------------------------------
- */
-
-static int
-buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
-{
-       struct tm6000_fh *fh = vq->priv_data;
-
-       *size = fh->fmt->depth * fh->width * fh->height >> 3;
-       if (0 == *count)
-               *count = TM6000_DEF_BUF;
-
-       if (*count < TM6000_MIN_BUF)
-               *count = TM6000_MIN_BUF;
-
-       while (*size * *count > vid_limit * 1024 * 1024)
-               (*count)--;
-
-       return 0;
-}
-
-static void free_buffer(struct videobuf_queue *vq, struct tm6000_buffer *buf)
-{
-       struct tm6000_fh *fh = vq->priv_data;
-       struct tm6000_core   *dev = fh->dev;
-       unsigned long flags;
-
-       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;
-}
-
-static int
-buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
-                                               enum v4l2_field field)
-{
-       struct tm6000_fh     *fh  = vq->priv_data;
-       struct tm6000_buffer *buf = container_of(vb, struct tm6000_buffer, vb);
-       struct tm6000_core   *dev = fh->dev;
-       int rc = 0;
-
-       BUG_ON(NULL == fh->fmt);
-
-
-       /* FIXME: It assumes depth=2 */
-       /* The only currently supported format is 16 bits/pixel */
-       buf->vb.size = fh->fmt->depth*fh->width*fh->height >> 3;
-       if (0 != buf->vb.baddr  &&  buf->vb.bsize < buf->vb.size)
-               return -EINVAL;
-
-       if (buf->fmt       != fh->fmt    ||
-           buf->vb.width  != fh->width  ||
-           buf->vb.height != fh->height ||
-           buf->vb.field  != field) {
-               buf->fmt       = fh->fmt;
-               buf->vb.width  = fh->width;
-               buf->vb.height = fh->height;
-               buf->vb.field  = field;
-               buf->vb.state = VIDEOBUF_NEEDS_INIT;
-       }
-
-       if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-               rc = videobuf_iolock(vq, &buf->vb, NULL);
-               if (rc != 0)
-                       goto fail;
-       }
-
-       if (!dev->isoc_ctl.num_bufs) {
-               rc = tm6000_prepare_isoc(dev);
-               if (rc < 0)
-                       goto fail;
-
-               rc = tm6000_start_thread(dev);
-               if (rc < 0)
-                       goto fail;
-
-       }
-
-       buf->vb.state = VIDEOBUF_PREPARED;
-       return 0;
-
-fail:
-       free_buffer(vq, buf);
-       return rc;
-}
-
-static void
-buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
-{
-       struct tm6000_buffer    *buf     = container_of(vb, struct tm6000_buffer, vb);
-       struct tm6000_fh        *fh      = vq->priv_data;
-       struct tm6000_core      *dev     = fh->dev;
-       struct tm6000_dmaqueue  *vidq    = &dev->vidq;
-
-       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 tm6000_buffer   *buf  = container_of(vb, struct tm6000_buffer, vb);
-
-       free_buffer(vq, buf);
-}
-
-static struct videobuf_queue_ops tm6000_video_qops = {
-       .buf_setup      = buffer_setup,
-       .buf_prepare    = buffer_prepare,
-       .buf_queue      = buffer_queue,
-       .buf_release    = buffer_release,
-};
-
-/* ------------------------------------------------------------------
- *     IOCTL handling
- * ------------------------------------------------------------------
- */
-
-static bool is_res_read(struct tm6000_core *dev, struct tm6000_fh *fh)
-{
-       /* Is the current fh handling it? if so, that's OK */
-       if (dev->resources == fh && dev->is_res_read)
-               return true;
-
-       return false;
-}
-
-static bool is_res_streaming(struct tm6000_core *dev, struct tm6000_fh *fh)
-{
-       /* Is the current fh handling it? if so, that's OK */
-       if (dev->resources == fh)
-               return true;
-
-       return false;
-}
-
-static bool res_get(struct tm6000_core *dev, struct tm6000_fh *fh,
-                  bool is_res_read)
-{
-       /* Is the current fh handling it? if so, that's OK */
-       if (dev->resources == fh && dev->is_res_read == is_res_read)
-               return true;
-
-       /* is it free? */
-       if (dev->resources)
-               return false;
-
-       /* grab it */
-       dev->resources = fh;
-       dev->is_res_read = is_res_read;
-       dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: get\n");
-       return true;
-}
-
-static void res_free(struct tm6000_core *dev, struct tm6000_fh *fh)
-{
-       /* Is the current fh handling it? if so, that's OK */
-       if (dev->resources != fh)
-               return;
-
-       dev->resources = NULL;
-       dprintk(dev, V4L2_DEBUG_RES_LOCK, "res: put\n");
-}
-
-/* ------------------------------------------------------------------
- *     IOCTL vidioc handling
- * ------------------------------------------------------------------
- */
-static int vidioc_querycap(struct file *file, void  *priv,
-                                       struct v4l2_capability *cap)
-{
-       struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
-
-       strlcpy(cap->driver, "tm6000", sizeof(cap->driver));
-       strlcpy(cap->card, "Trident TVMaster TM5600/6000/6010", sizeof(cap->card));
-       cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
-                               V4L2_CAP_STREAMING     |
-                               V4L2_CAP_AUDIO         |
-                               V4L2_CAP_READWRITE;
-
-       if (dev->tuner_type != TUNER_ABSENT)
-               cap->capabilities |= V4L2_CAP_TUNER;
-
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *f)
-{
-       if (unlikely(f->index >= ARRAY_SIZE(format)))
-               return -EINVAL;
-
-       strlcpy(f->description, format[f->index].name, sizeof(f->description));
-       f->pixelformat = format[f->index].fourcc;
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct tm6000_fh  *fh = priv;
-
-       f->fmt.pix.width        = fh->width;
-       f->fmt.pix.height       = fh->height;
-       f->fmt.pix.field        = fh->vb_vidq.field;
-       f->fmt.pix.pixelformat  = fh->fmt->fourcc;
-       f->fmt.pix.bytesperline =
-               (f->fmt.pix.width * fh->fmt->depth) >> 3;
-       f->fmt.pix.sizeimage =
-               f->fmt.pix.height * f->fmt.pix.bytesperline;
-
-       return 0;
-}
-
-static struct tm6000_fmt *format_by_fourcc(unsigned int fourcc)
-{
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(format); i++)
-               if (format[i].fourcc == fourcc)
-                       return format+i;
-       return NULL;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                       struct v4l2_format *f)
-{
-       struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
-       struct tm6000_fmt *fmt;
-       enum v4l2_field field;
-
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
-       if (NULL == fmt) {
-               dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Fourcc format (0x%08x)"
-                               " invalid.\n", f->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       field = f->fmt.pix.field;
-
-       if (field == V4L2_FIELD_ANY)
-               field = V4L2_FIELD_SEQ_TB;
-       else if (V4L2_FIELD_INTERLACED != field) {
-               dprintk(dev, V4L2_DEBUG_IOCTL_ARG, "Field type invalid.\n");
-               return -EINVAL;
-       }
-
-       tm6000_get_std_res(dev);
-
-       f->fmt.pix.width  = dev->width;
-       f->fmt.pix.height = dev->height;
-
-       f->fmt.pix.width &= ~0x01;
-
-       f->fmt.pix.field = field;
-
-       f->fmt.pix.bytesperline =
-               (f->fmt.pix.width * fmt->depth) >> 3;
-       f->fmt.pix.sizeimage =
-               f->fmt.pix.height * f->fmt.pix.bytesperline;
-
-       return 0;
-}
-
-/*FIXME: This seems to be generic enough to be at videodev2 */
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                                       struct v4l2_format *f)
-{
-       struct tm6000_fh  *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-       int ret = vidioc_try_fmt_vid_cap(file, fh, f);
-       if (ret < 0)
-               return ret;
-
-       fh->fmt           = format_by_fourcc(f->fmt.pix.pixelformat);
-       fh->width         = f->fmt.pix.width;
-       fh->height        = f->fmt.pix.height;
-       fh->vb_vidq.field = f->fmt.pix.field;
-       fh->type          = f->type;
-
-       dev->fourcc       = f->fmt.pix.pixelformat;
-
-       tm6000_set_fourcc_format(dev);
-
-       return 0;
-}
-
-static int vidioc_reqbufs(struct file *file, void *priv,
-                          struct v4l2_requestbuffers *p)
-{
-       struct tm6000_fh  *fh = priv;
-
-       return videobuf_reqbufs(&fh->vb_vidq, p);
-}
-
-static int vidioc_querybuf(struct file *file, void *priv,
-                           struct v4l2_buffer *p)
-{
-       struct tm6000_fh  *fh = priv;
-
-       return videobuf_querybuf(&fh->vb_vidq, p);
-}
-
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       struct tm6000_fh  *fh = priv;
-
-       return videobuf_qbuf(&fh->vb_vidq, p);
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
-{
-       struct tm6000_fh  *fh = priv;
-
-       return videobuf_dqbuf(&fh->vb_vidq, p,
-                               file->f_flags & O_NONBLOCK);
-}
-
-static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct tm6000_fh *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-       if (i != fh->type)
-               return -EINVAL;
-
-       if (!res_get(dev, fh, false))
-               return -EBUSY;
-       return videobuf_streamon(&fh->vb_vidq);
-}
-
-static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct tm6000_fh *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       if (i != fh->type)
-               return -EINVAL;
-
-       videobuf_streamoff(&fh->vb_vidq);
-       res_free(dev, fh);
-
-       return 0;
-}
-
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
-{
-       int rc = 0;
-       struct tm6000_fh *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       dev->norm = *norm;
-       rc = tm6000_init_analog_mode(dev);
-
-       fh->width  = dev->width;
-       fh->height = dev->height;
-
-       if (rc < 0)
-               return rc;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, dev->norm);
-
-       return 0;
-}
-
-static const char *iname[] = {
-       [TM6000_INPUT_TV] = "Television",
-       [TM6000_INPUT_COMPOSITE1] = "Composite 1",
-       [TM6000_INPUT_COMPOSITE2] = "Composite 2",
-       [TM6000_INPUT_SVIDEO] = "S-Video",
-};
-
-static int vidioc_enum_input(struct file *file, void *priv,
-                               struct v4l2_input *i)
-{
-       struct tm6000_fh   *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-       unsigned int n;
-
-       n = i->index;
-       if (n >= 3)
-               return -EINVAL;
-
-       if (!dev->vinput[n].type)
-               return -EINVAL;
-
-       i->index = n;
-
-       if (dev->vinput[n].type == TM6000_INPUT_TV)
-               i->type = V4L2_INPUT_TYPE_TUNER;
-       else
-               i->type = V4L2_INPUT_TYPE_CAMERA;
-
-       strcpy(i->name, iname[dev->vinput[n].type]);
-
-       i->std = TM6000_STD;
-
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
-{
-       struct tm6000_fh   *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       *i = dev->input;
-
-       return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
-{
-       struct tm6000_fh   *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-       int rc = 0;
-
-       if (i >= 3)
-               return -EINVAL;
-       if (!dev->vinput[i].type)
-               return -EINVAL;
-
-       dev->input = i;
-
-       rc = vidioc_s_std(file, priv, &dev->vfd->current_norm);
-
-       return rc;
-}
-
-/* --- controls ---------------------------------------------- */
-static int vidioc_queryctrl(struct file *file, void *priv,
-                               struct v4l2_queryctrl *qc)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)
-               if (qc->id && qc->id == tm6000_qctrl[i].id) {
-                       memcpy(qc, &(tm6000_qctrl[i]),
-                               sizeof(*qc));
-                       return 0;
-               }
-
-       return -EINVAL;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctrl)
-{
-       struct tm6000_fh  *fh = priv;
-       struct tm6000_core *dev    = fh->dev;
-       int  val;
-
-       /* FIXME: Probably, those won't work! Maybe we need shadow regs */
-       switch (ctrl->id) {
-       case V4L2_CID_CONTRAST:
-               val = tm6000_get_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, 0);
-               break;
-       case V4L2_CID_BRIGHTNESS:
-               val = tm6000_get_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, 0);
-               return 0;
-       case V4L2_CID_SATURATION:
-               val = tm6000_get_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, 0);
-               return 0;
-       case V4L2_CID_HUE:
-               val = tm6000_get_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, 0);
-               return 0;
-       case V4L2_CID_AUDIO_MUTE:
-               val = dev->ctl_mute;
-               return 0;
-       case V4L2_CID_AUDIO_VOLUME:
-               val = dev->ctl_volume;
-               return 0;
-       default:
-               return -EINVAL;
-       }
-
-       if (val < 0)
-               return val;
-
-       ctrl->value = val;
-
-       return 0;
-}
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctrl)
-{
-       struct tm6000_fh   *fh  = priv;
-       struct tm6000_core *dev = fh->dev;
-       u8  val = ctrl->value;
-
-       switch (ctrl->id) {
-       case V4L2_CID_CONTRAST:
-               tm6000_set_reg(dev, TM6010_REQ07_R08_LUMA_CONTRAST_ADJ, val);
-               return 0;
-       case V4L2_CID_BRIGHTNESS:
-               tm6000_set_reg(dev, TM6010_REQ07_R09_LUMA_BRIGHTNESS_ADJ, val);
-               return 0;
-       case V4L2_CID_SATURATION:
-               tm6000_set_reg(dev, TM6010_REQ07_R0A_CHROMA_SATURATION_ADJ, val);
-               return 0;
-       case V4L2_CID_HUE:
-               tm6000_set_reg(dev, TM6010_REQ07_R0B_CHROMA_HUE_PHASE_ADJ, val);
-               return 0;
-       case V4L2_CID_AUDIO_MUTE:
-               dev->ctl_mute = val;
-               tm6000_tvaudio_set_mute(dev, val);
-               return 0;
-       case V4L2_CID_AUDIO_VOLUME:
-               dev->ctl_volume = val;
-               tm6000_set_volume(dev, val);
-               return 0;
-       }
-       return -EINVAL;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct tm6000_fh   *fh  = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (unlikely(UNSET == dev->tuner_type))
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-
-       strcpy(t->name, "Television");
-       t->type       = V4L2_TUNER_ANALOG_TV;
-       t->capability = V4L2_TUNER_CAP_NORM;
-       t->rangehigh  = 0xffffffffUL;
-       t->rxsubchans = V4L2_TUNER_SUB_STEREO;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
-
-       t->audmode = dev->amode;
-
-       return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *t)
-{
-       struct tm6000_fh   *fh  = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (UNSET == dev->tuner_type)
-               return -EINVAL;
-       if (0 != t->index)
-               return -EINVAL;
-
-       dev->amode = t->audmode;
-       dprintk(dev, 3, "audio mode: %x\n", t->audmode);
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
-
-       return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *f)
-{
-       struct tm6000_fh   *fh  = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (unlikely(UNSET == dev->tuner_type))
-               return -EINVAL;
-
-       f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
-       f->frequency = dev->freq;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_frequency, f);
-
-       return 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *f)
-{
-       struct tm6000_fh   *fh  = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (unlikely(UNSET == dev->tuner_type))
-               return -EINVAL;
-       if (unlikely(f->tuner != 0))
-               return -EINVAL;
-       if (0 == fh->radio && V4L2_TUNER_ANALOG_TV != f->type)
-               return -EINVAL;
-       if (1 == fh->radio && V4L2_TUNER_RADIO != f->type)
-               return -EINVAL;
-
-       dev->freq = f->frequency;
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, f);
-
-       return 0;
-}
-
-static int radio_querycap(struct file *file, void *priv,
-                                       struct v4l2_capability *cap)
-{
-       struct tm6000_fh *fh = file->private_data;
-       struct tm6000_core *dev = fh->dev;
-
-       strcpy(cap->driver, "tm6000");
-       strlcpy(cap->card, dev->name, sizeof(dev->name));
-       sprintf(cap->bus_info, "USB%04x:%04x",
-               le16_to_cpu(dev->udev->descriptor.idVendor),
-               le16_to_cpu(dev->udev->descriptor.idProduct));
-       cap->version = dev->dev_type;
-       cap->capabilities = V4L2_CAP_TUNER |
-                       V4L2_CAP_AUDIO     |
-                       V4L2_CAP_RADIO     |
-                       V4L2_CAP_READWRITE |
-                       V4L2_CAP_STREAMING;
-
-       return 0;
-}
-
-static int radio_g_tuner(struct file *file, void *priv,
-                                       struct v4l2_tuner *t)
-{
-       struct tm6000_fh *fh = file->private_data;
-       struct tm6000_core *dev = fh->dev;
-
-       if (0 != t->index)
-               return -EINVAL;
-
-       memset(t, 0, sizeof(*t));
-       strcpy(t->name, "Radio");
-       t->type = V4L2_TUNER_RADIO;
-       t->rxsubchans = V4L2_TUNER_SUB_STEREO;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, g_tuner, t);
-
-       return 0;
-}
-
-static int radio_s_tuner(struct file *file, void *priv,
-                                       struct v4l2_tuner *t)
-{
-       struct tm6000_fh *fh = file->private_data;
-       struct tm6000_core *dev = fh->dev;
-
-       if (0 != t->index)
-               return -EINVAL;
-
-       v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
-
-       return 0;
-}
-
-static int radio_enum_input(struct file *file, void *priv,
-                                       struct v4l2_input *i)
-{
-       struct tm6000_fh *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (i->index != 0)
-               return -EINVAL;
-
-       if (!dev->rinput.type)
-               return -EINVAL;
-
-       strcpy(i->name, "Radio");
-       i->type = V4L2_INPUT_TYPE_TUNER;
-
-       return 0;
-}
-
-static int radio_g_input(struct file *filp, void *priv, unsigned int *i)
-{
-       struct tm6000_fh *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (dev->input != 5)
-               return -EINVAL;
-
-       *i = dev->input - 5;
-
-       return 0;
-}
-
-static int radio_g_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *a)
-{
-       memset(a, 0, sizeof(*a));
-       strcpy(a->name, "Radio");
-       return 0;
-}
-
-static int radio_s_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *a)
-{
-       return 0;
-}
-
-static int radio_s_input(struct file *filp, void *priv, unsigned int i)
-{
-       struct tm6000_fh *fh = priv;
-       struct tm6000_core *dev = fh->dev;
-
-       if (i)
-               return -EINVAL;
-
-       if (!dev->rinput.type)
-               return -EINVAL;
-
-       dev->input = i + 5;
-
-       return 0;
-}
-
-static int radio_s_std(struct file *file, void *fh, v4l2_std_id *norm)
-{
-       return 0;
-}
-
-static int radio_queryctrl(struct file *file, void *priv,
-                                       struct v4l2_queryctrl *c)
-{
-       const struct v4l2_queryctrl *ctrl;
-
-       if (c->id <  V4L2_CID_BASE ||
-           c->id >= V4L2_CID_LASTP1)
-               return -EINVAL;
-       if (c->id == V4L2_CID_AUDIO_MUTE) {
-               ctrl = ctrl_by_id(c->id);
-               *c = *ctrl;
-       } else
-               *c = no_ctrl;
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------
-       File operations for the device
-   ------------------------------------------------------------------*/
-
-static int __tm6000_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct tm6000_core *dev = video_drvdata(file);
-       struct tm6000_fh *fh;
-       enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-       int i, rc;
-       int radio = 0;
-
-       dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: open called (dev=%s)\n",
-               video_device_node_name(vdev));
-
-       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;
-       case VFL_TYPE_RADIO:
-               radio = 1;
-               break;
-       }
-
-       /* If more than one user, mutex should be added */
-       dev->users++;
-
-       dprintk(dev, V4L2_DEBUG_OPEN, "open dev=%s type=%s users=%d\n",
-               video_device_node_name(vdev), v4l2_type_names[type],
-               dev->users);
-
-       /* allocate + initialize per filehandle data */
-       fh = kzalloc(sizeof(*fh), GFP_KERNEL);
-       if (NULL == fh) {
-               dev->users--;
-               return -ENOMEM;
-       }
-
-       file->private_data = fh;
-       fh->dev      = dev;
-       fh->radio    = radio;
-       dev->radio   = radio;
-       fh->type     = type;
-       dev->fourcc  = format[0].fourcc;
-
-       fh->fmt      = format_by_fourcc(dev->fourcc);
-
-       tm6000_get_std_res(dev);
-
-       fh->width = dev->width;
-       fh->height = dev->height;
-
-       dprintk(dev, V4L2_DEBUG_OPEN, "Open: fh=0x%08lx, dev=0x%08lx, "
-                                               "dev->vidq=0x%08lx\n",
-                       (unsigned long)fh, (unsigned long)dev,
-                       (unsigned long)&dev->vidq);
-       dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "
-                               "queued=%d\n", list_empty(&dev->vidq.queued));
-       dprintk(dev, V4L2_DEBUG_OPEN, "Open: list_empty "
-                               "active=%d\n", list_empty(&dev->vidq.active));
-
-       /* initialize hardware on analog mode */
-       rc = tm6000_init_analog_mode(dev);
-       if (rc < 0)
-               return rc;
-
-       if (dev->mode != TM6000_MODE_ANALOG) {
-               /* Put all controls at a sane state */
-               for (i = 0; i < ARRAY_SIZE(tm6000_qctrl); i++)
-                       qctl_regs[i] = tm6000_qctrl[i].default_value;
-
-               dev->mode = TM6000_MODE_ANALOG;
-       }
-
-       if (!fh->radio) {
-               videobuf_queue_vmalloc_init(&fh->vb_vidq, &tm6000_video_qops,
-                               NULL, &dev->slock,
-                               fh->type,
-                               V4L2_FIELD_INTERLACED,
-                               sizeof(struct tm6000_buffer), fh, &dev->lock);
-       } else {
-               dprintk(dev, V4L2_DEBUG_OPEN, "video_open: setting radio device\n");
-               dev->input = 5;
-               tm6000_set_audio_rinput(dev);
-               v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_radio);
-               tm6000_prepare_isoc(dev);
-               tm6000_start_thread(dev);
-       }
-
-       return 0;
-}
-
-static int tm6000_open(struct file *file)
-{
-       struct video_device *vdev = video_devdata(file);
-       int res;
-
-       mutex_lock(vdev->lock);
-       res = __tm6000_open(file);
-       mutex_unlock(vdev->lock);
-       return res;
-}
-
-static ssize_t
-tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos)
-{
-       struct tm6000_fh *fh = file->private_data;
-       struct tm6000_core *dev = fh->dev;
-
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               int res;
-
-               if (!res_get(fh->dev, fh, true))
-                       return -EBUSY;
-
-               if (mutex_lock_interruptible(&dev->lock))
-                       return -ERESTARTSYS;
-               res = videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0,
-                                       file->f_flags & O_NONBLOCK);
-               mutex_unlock(&dev->lock);
-               return res;
-       }
-       return 0;
-}
-
-static unsigned int
-__tm6000_poll(struct file *file, struct poll_table_struct *wait)
-{
-       struct tm6000_fh        *fh = file->private_data;
-       struct tm6000_buffer    *buf;
-
-       if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
-               return POLLERR;
-
-       if (!!is_res_streaming(fh->dev, fh))
-               return POLLERR;
-
-       if (!is_res_read(fh->dev, fh)) {
-               /* streaming capture */
-               if (list_empty(&fh->vb_vidq.stream))
-                       return POLLERR;
-               buf = list_entry(fh->vb_vidq.stream.next, struct tm6000_buffer, vb.stream);
-       } else {
-               /* read() capture */
-               return videobuf_poll_stream(file, &fh->vb_vidq, wait);
-       }
-       poll_wait(file, &buf->vb.done, wait);
-       if (buf->vb.state == VIDEOBUF_DONE ||
-           buf->vb.state == VIDEOBUF_ERROR)
-               return POLLIN | POLLRDNORM;
-       return 0;
-}
-
-static unsigned int tm6000_poll(struct file *file, struct poll_table_struct *wait)
-{
-       struct tm6000_fh *fh = file->private_data;
-       struct tm6000_core *dev = fh->dev;
-       unsigned int res;
-
-       mutex_lock(&dev->lock);
-       res = __tm6000_poll(file, wait);
-       mutex_unlock(&dev->lock);
-       return res;
-}
-
-static int tm6000_release(struct file *file)
-{
-       struct tm6000_fh         *fh = file->private_data;
-       struct tm6000_core      *dev = fh->dev;
-       struct video_device    *vdev = video_devdata(file);
-
-       dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: close called (dev=%s, users=%d)\n",
-               video_device_node_name(vdev), dev->users);
-
-       mutex_lock(&dev->lock);
-       dev->users--;
-
-       res_free(dev, fh);
-
-       if (!dev->users) {
-               tm6000_uninit_isoc(dev);
-
-               /* Stop interrupt USB pipe */
-               tm6000_ir_int_stop(dev);
-
-               usb_reset_configuration(dev->udev);
-
-               if (dev->int_in.endp)
-                       usb_set_interface(dev->udev,
-                                       dev->isoc_in.bInterfaceNumber, 2);
-               else
-                       usb_set_interface(dev->udev,
-                                       dev->isoc_in.bInterfaceNumber, 0);
-
-               /* Start interrupt USB pipe */
-               tm6000_ir_int_start(dev);
-
-               if (!fh->radio)
-                       videobuf_mmap_free(&fh->vb_vidq);
-       }
-
-       kfree(fh);
-       mutex_unlock(&dev->lock);
-
-       return 0;
-}
-
-static int tm6000_mmap(struct file *file, struct vm_area_struct * vma)
-{
-       struct tm6000_fh *fh = file->private_data;
-       struct tm6000_core *dev = fh->dev;
-       int res;
-
-       if (mutex_lock_interruptible(&dev->lock))
-               return -ERESTARTSYS;
-       res = videobuf_mmap_mapper(&fh->vb_vidq, vma);
-       mutex_unlock(&dev->lock);
-       return res;
-}
-
-static struct v4l2_file_operations tm6000_fops = {
-       .owner = THIS_MODULE,
-       .open = tm6000_open,
-       .release = tm6000_release,
-       .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
-       .read = tm6000_read,
-       .poll = tm6000_poll,
-       .mmap = tm6000_mmap,
-};
-
-static const struct v4l2_ioctl_ops video_ioctl_ops = {
-       .vidioc_querycap          = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
-       .vidioc_s_std             = vidioc_s_std,
-       .vidioc_enum_input        = vidioc_enum_input,
-       .vidioc_g_input           = vidioc_g_input,
-       .vidioc_s_input           = vidioc_s_input,
-       .vidioc_queryctrl         = vidioc_queryctrl,
-       .vidioc_g_ctrl            = vidioc_g_ctrl,
-       .vidioc_s_ctrl            = vidioc_s_ctrl,
-       .vidioc_g_tuner           = vidioc_g_tuner,
-       .vidioc_s_tuner           = vidioc_s_tuner,
-       .vidioc_g_frequency       = vidioc_g_frequency,
-       .vidioc_s_frequency       = vidioc_s_frequency,
-       .vidioc_streamon          = vidioc_streamon,
-       .vidioc_streamoff         = vidioc_streamoff,
-       .vidioc_reqbufs           = vidioc_reqbufs,
-       .vidioc_querybuf          = vidioc_querybuf,
-       .vidioc_qbuf              = vidioc_qbuf,
-       .vidioc_dqbuf             = vidioc_dqbuf,
-};
-
-static struct video_device tm6000_template = {
-       .name           = "tm6000",
-       .fops           = &tm6000_fops,
-       .ioctl_ops      = &video_ioctl_ops,
-       .release        = video_device_release,
-       .tvnorms        = TM6000_STD,
-       .current_norm   = V4L2_STD_NTSC_M,
-};
-
-static const struct v4l2_file_operations radio_fops = {
-       .owner          = THIS_MODULE,
-       .open           = tm6000_open,
-       .release        = tm6000_release,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops radio_ioctl_ops = {
-       .vidioc_querycap        = radio_querycap,
-       .vidioc_g_tuner         = radio_g_tuner,
-       .vidioc_enum_input      = radio_enum_input,
-       .vidioc_g_audio         = radio_g_audio,
-       .vidioc_s_tuner         = radio_s_tuner,
-       .vidioc_s_audio         = radio_s_audio,
-       .vidioc_s_input         = radio_s_input,
-       .vidioc_s_std           = radio_s_std,
-       .vidioc_queryctrl       = radio_queryctrl,
-       .vidioc_g_input         = radio_g_input,
-       .vidioc_g_ctrl          = vidioc_g_ctrl,
-       .vidioc_s_ctrl          = vidioc_s_ctrl,
-       .vidioc_g_frequency     = vidioc_g_frequency,
-       .vidioc_s_frequency     = vidioc_s_frequency,
-};
-
-static struct video_device tm6000_radio_template = {
-       .name                   = "tm6000",
-       .fops                   = &radio_fops,
-       .ioctl_ops              = &radio_ioctl_ops,
-};
-
-/* -----------------------------------------------------------------
- *     Initialization and module stuff
- * ------------------------------------------------------------------
- */
-
-static struct video_device *vdev_init(struct tm6000_core *dev,
-               const struct video_device
-               *template, const char *type_name)
-{
-       struct video_device *vfd;
-
-       vfd = video_device_alloc();
-       if (NULL == vfd)
-               return NULL;
-
-       *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);
-
-       video_set_drvdata(vfd, dev);
-       return vfd;
-}
-
-int tm6000_v4l2_register(struct tm6000_core *dev)
-{
-       int ret = -1;
-
-       dev->vfd = vdev_init(dev, &tm6000_template, "video");
-
-       if (!dev->vfd) {
-               printk(KERN_INFO "%s: can't register video device\n",
-                      dev->name);
-               return -ENOMEM;
-       }
-
-       /* init video dma queues */
-       INIT_LIST_HEAD(&dev->vidq.active);
-       INIT_LIST_HEAD(&dev->vidq.queued);
-
-       ret = video_register_device(dev->vfd, VFL_TYPE_GRABBER, video_nr);
-
-       if (ret < 0) {
-               printk(KERN_INFO "%s: can't register video device\n",
-                      dev->name);
-               return ret;
-       }
-
-       printk(KERN_INFO "%s: registered device %s\n",
-              dev->name, video_device_node_name(dev->vfd));
-
-       if (dev->caps.has_radio) {
-               dev->radio_dev = vdev_init(dev, &tm6000_radio_template,
-                                                          "radio");
-               if (!dev->radio_dev) {
-                       printk(KERN_INFO "%s: can't register radio device\n",
-                              dev->name);
-                       return ret; /* FIXME release resource */
-               }
-
-               ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
-                                           radio_nr);
-               if (ret < 0) {
-                       printk(KERN_INFO "%s: can't register radio device\n",
-                              dev->name);
-                       return ret; /* FIXME release resource */
-               }
-
-               printk(KERN_INFO "%s: registered device %s\n",
-                      dev->name, video_device_node_name(dev->radio_dev));
-       }
-
-       printk(KERN_INFO "Trident TVMaster TM5600/TM6000/TM6010 USB2 board (Load status: %d)\n", ret);
-       return ret;
-}
-
-int tm6000_v4l2_unregister(struct tm6000_core *dev)
-{
-       video_unregister_device(dev->vfd);
-
-       if (dev->radio_dev) {
-               if (video_is_registered(dev->radio_dev))
-                       video_unregister_device(dev->radio_dev);
-               else
-                       video_device_release(dev->radio_dev);
-               dev->radio_dev = NULL;
-       }
-
-       return 0;
-}
-
-int tm6000_v4l2_exit(void)
-{
-       return 0;
-}
-
-module_param(video_nr, int, 0);
-MODULE_PARM_DESC(video_nr, "Allow changing video device number");
-
-module_param_named(debug, tm6000_debug, int, 0444);
-MODULE_PARM_DESC(debug, "activates debug info");
-
-module_param(vid_limit, int, 0644);
-MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes");
-
diff --git a/drivers/media/video/tm6000/tm6000.h b/drivers/media/video/tm6000/tm6000.h
deleted file mode 100644 (file)
index 6df4186..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- *  tm6000.h - driver for TM5600/TM6000/TM6010 USB video capture devices
- *
- *  Copyright (C) 2006-2007 Mauro Carvalho Chehab <mchehab@infradead.org>
- *
- *  Copyright (C) 2007 Michel Ludwig <michel.ludwig@gmail.com>
- *     - DVB-T support
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation version 2
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/videobuf-vmalloc.h>
-#include "tm6000-usb-isoc.h"
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <media/v4l2-device.h>
-
-#include <linux/dvb/frontend.h>
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dmxdev.h"
-
-/* Inputs */
-enum tm6000_itype {
-       TM6000_INPUT_TV = 1,
-       TM6000_INPUT_COMPOSITE1,
-       TM6000_INPUT_COMPOSITE2,
-       TM6000_INPUT_SVIDEO,
-       TM6000_INPUT_DVB,
-       TM6000_INPUT_RADIO,
-};
-
-enum tm6000_mux {
-       TM6000_VMUX_VIDEO_A = 1,
-       TM6000_VMUX_VIDEO_B,
-       TM6000_VMUX_VIDEO_AB,
-       TM6000_AMUX_ADC1,
-       TM6000_AMUX_ADC2,
-       TM6000_AMUX_SIF1,
-       TM6000_AMUX_SIF2,
-       TM6000_AMUX_I2S,
-};
-
-enum tm6000_devtype {
-       TM6000 = 0,
-       TM5600,
-       TM6010,
-};
-
-struct tm6000_input {
-       enum tm6000_itype       type;
-       enum tm6000_mux         vmux;
-       enum tm6000_mux         amux;
-       unsigned int            v_gpio;
-       unsigned int            a_gpio;
-};
-
-/* ------------------------------------------------------------------
- *     Basic structures
- * ------------------------------------------------------------------
- */
-
-struct tm6000_fmt {
-       char  *name;
-       u32   fourcc;          /* v4l2 format id */
-       int   depth;
-};
-
-/* buffer for one video frame */
-struct tm6000_buffer {
-       /* common v4l buffer stuff -- must be first */
-       struct videobuf_buffer vb;
-
-       struct tm6000_fmt      *fmt;
-};
-
-struct tm6000_dmaqueue {
-       struct list_head       active;
-       struct list_head       queued;
-
-       /* thread for generating video stream*/
-       struct task_struct         *kthread;
-       wait_queue_head_t          wq;
-       /* Counters to control fps rate */
-       int                        frame;
-       int                        ini_jiffies;
-};
-
-/* device states */
-enum tm6000_core_state {
-       DEV_INITIALIZED   = 0x01,
-       DEV_DISCONNECTED  = 0x02,
-       DEV_MISCONFIGURED = 0x04,
-};
-
-/* io methods */
-enum tm6000_io_method {
-       IO_NONE,
-       IO_READ,
-       IO_MMAP,
-};
-
-enum tm6000_mode {
-       TM6000_MODE_UNKNOWN = 0,
-       TM6000_MODE_ANALOG,
-       TM6000_MODE_DIGITAL,
-};
-
-struct tm6000_gpio {
-       int             tuner_reset;
-       int             tuner_on;
-       int             demod_reset;
-       int             demod_on;
-       int             power_led;
-       int             dvb_led;
-       int             ir;
-};
-
-struct tm6000_capabilities {
-       unsigned int    has_tuner:1;
-       unsigned int    has_tda9874:1;
-       unsigned int    has_dvb:1;
-       unsigned int    has_zl10353:1;
-       unsigned int    has_eeprom:1;
-       unsigned int    has_remote:1;
-       unsigned int    has_radio:1;
-};
-
-struct tm6000_dvb {
-       struct dvb_adapter      adapter;
-       struct dvb_demux        demux;
-       struct dvb_frontend     *frontend;
-       struct dmxdev           dmxdev;
-       unsigned int            streams;
-       struct urb              *bulk_urb;
-       struct mutex            mutex;
-};
-
-struct snd_tm6000_card {
-       struct snd_card                 *card;
-       spinlock_t                      reg_lock;
-       struct tm6000_core              *core;
-       struct snd_pcm_substream        *substream;
-
-       /* temporary data for buffer fill processing */
-       unsigned                        buf_pos;
-       unsigned                        period_pos;
-};
-
-struct tm6000_endpoint {
-       struct usb_host_endpoint        *endp;
-       __u8                            bInterfaceNumber;
-       __u8                            bAlternateSetting;
-       unsigned                        maxsize;
-};
-
-#define TM6000_QUIRK_NO_USB_DELAY (1 << 0)
-
-struct tm6000_core {
-       /* generic device properties */
-       char                            name[30];       /* name (including minor) of the device */
-       int                             model;          /* index in the device_data struct */
-       int                             devno;          /* marks the number of this device */
-       enum tm6000_devtype             dev_type;       /* type of device */
-       unsigned char                   eedata[256];    /* Eeprom data */
-       unsigned                        eedata_size;    /* Size of the eeprom info */
-
-       v4l2_std_id                     norm;           /* Current norm */
-       int                             width, height;  /* Selected resolution */
-
-       enum tm6000_core_state          state;
-
-       /* Device Capabilities*/
-       struct tm6000_capabilities      caps;
-
-       /* Used to load alsa/dvb */
-        struct work_struct             request_module_wk;
-
-       /* Tuner configuration */
-       int                             tuner_type;             /* type of the tuner */
-       int                             tuner_addr;             /* tuner address */
-
-       struct tm6000_gpio              gpio;
-
-       char                            *ir_codes;
-
-       __u8                            radio;
-
-       /* Demodulator configuration */
-       int                             demod_addr;     /* demodulator address */
-
-       int                             audio_bitrate;
-       /* i2c i/o */
-       struct i2c_adapter              i2c_adap;
-       struct i2c_client               i2c_client;
-
-
-       /* extension */
-       struct list_head                devlist;
-
-       /* video for linux */
-       int                             users;
-
-       /* various device info */
-       struct tm6000_fh                *resources;     /* Points to fh that is streaming */
-       bool                            is_res_read;
-
-       struct video_device             *vfd;
-       struct video_device             *radio_dev;
-       struct tm6000_dmaqueue          vidq;
-       struct v4l2_device              v4l2_dev;
-
-       int                             input;
-       struct tm6000_input             vinput[3];      /* video input */
-       struct tm6000_input             rinput;         /* radio input */
-
-       int                             freq;
-       unsigned int                    fourcc;
-
-       enum tm6000_mode                mode;
-
-       int                             ctl_mute;             /* audio */
-       int                             ctl_volume;
-       int                             amode;
-
-       /* DVB-T support */
-       struct tm6000_dvb               *dvb;
-
-       /* audio support */
-       struct snd_tm6000_card          *adev;
-       struct work_struct              wq_trigger;   /* Trigger to start/stop audio for alsa module */
-       atomic_t                        stream_started;  /* stream should be running if true */
-
-       struct tm6000_IR                *ir;
-
-       /* locks */
-       struct mutex                    lock;
-       struct mutex                    usb_lock;
-
-       /* usb transfer */
-       struct usb_device               *udev;          /* the usb device */
-
-       struct tm6000_endpoint          bulk_in, bulk_out, isoc_in, isoc_out;
-       struct tm6000_endpoint          int_in, int_out;
-
-       /* scaler!=0 if scaler is active*/
-       int                             scaler;
-
-               /* Isoc control struct */
-       struct usb_isoc_ctl          isoc_ctl;
-
-       spinlock_t                   slock;
-
-       unsigned long quirks;
-};
-
-enum tm6000_ops_type {
-       TM6000_AUDIO = 0x10,
-       TM6000_DVB = 0x20,
-};
-
-struct tm6000_ops {
-       struct list_head        next;
-       char                    *name;
-       enum tm6000_ops_type    type;
-       int (*init)(struct tm6000_core *);
-       int (*fini)(struct tm6000_core *);
-       int (*fillbuf)(struct tm6000_core *, char *buf, int size);
-};
-
-struct tm6000_fh {
-       struct tm6000_core           *dev;
-       unsigned int                 radio;
-
-       /* video capture */
-       struct tm6000_fmt            *fmt;
-       unsigned int                 width, height;
-       struct videobuf_queue        vb_vidq;
-
-       enum v4l2_buf_type           type;
-};
-
-#define TM6000_STD     (V4L2_STD_PAL|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|    \
-                       V4L2_STD_PAL_M|V4L2_STD_PAL_60|V4L2_STD_NTSC_M| \
-                       V4L2_STD_NTSC_M_JP|V4L2_STD_SECAM)
-
-/* In tm6000-cards.c */
-
-int tm6000_tuner_callback(void *ptr, int component, int command, int arg);
-int tm6000_xc5000_callback(void *ptr, int component, int command, int arg);
-int tm6000_cards_setup(struct tm6000_core *dev);
-void tm6000_flash_led(struct tm6000_core *dev, u8 state);
-
-/* In tm6000-core.c */
-
-int tm6000_read_write_usb(struct tm6000_core *dev, u8 reqtype, u8 req,
-                          u16 value, u16 index, u8 *buf, u16 len);
-int tm6000_get_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index);
-int tm6000_get_reg16(struct tm6000_core *dev, u8 req, u16 value, u16 index);
-int tm6000_get_reg32(struct tm6000_core *dev, u8 req, u16 value, u16 index);
-int tm6000_set_reg(struct tm6000_core *dev, u8 req, u16 value, u16 index);
-int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value,
-                                               u16 index, u16 mask);
-int tm6000_i2c_reset(struct tm6000_core *dev, u16 tsleep);
-int tm6000_init(struct tm6000_core *dev);
-int tm6000_reset(struct tm6000_core *dev);
-
-int tm6000_init_analog_mode(struct tm6000_core *dev);
-int tm6000_init_digital_mode(struct tm6000_core *dev);
-int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate);
-int tm6000_set_audio_rinput(struct tm6000_core *dev);
-int tm6000_tvaudio_set_mute(struct tm6000_core *dev, u8 mute);
-void tm6000_set_volume(struct tm6000_core *dev, int vol);
-
-int tm6000_v4l2_register(struct tm6000_core *dev);
-int tm6000_v4l2_unregister(struct tm6000_core *dev);
-int tm6000_v4l2_exit(void);
-void tm6000_set_fourcc_format(struct tm6000_core *dev);
-
-void tm6000_remove_from_devlist(struct tm6000_core *dev);
-void tm6000_add_into_devlist(struct tm6000_core *dev);
-int tm6000_register_extension(struct tm6000_ops *ops);
-void tm6000_unregister_extension(struct tm6000_ops *ops);
-void tm6000_init_extension(struct tm6000_core *dev);
-void tm6000_close_extension(struct tm6000_core *dev);
-int tm6000_call_fillbuf(struct tm6000_core *dev, enum tm6000_ops_type type,
-                       char *buf, int size);
-
-
-/* In tm6000-stds.c */
-void tm6000_get_std_res(struct tm6000_core *dev);
-int tm6000_set_standard(struct tm6000_core *dev);
-
-/* In tm6000-i2c.c */
-int tm6000_i2c_register(struct tm6000_core *dev);
-int tm6000_i2c_unregister(struct tm6000_core *dev);
-
-/* In tm6000-queue.c */
-
-int tm6000_v4l2_mmap(struct file *filp, struct vm_area_struct *vma);
-
-int tm6000_vidioc_streamon(struct file *file, void *priv,
-                          enum v4l2_buf_type i);
-int tm6000_vidioc_streamoff(struct file *file, void *priv,
-                           enum v4l2_buf_type i);
-int tm6000_vidioc_reqbufs(struct file *file, void *priv,
-                         struct v4l2_requestbuffers *rb);
-int tm6000_vidioc_querybuf(struct file *file, void *priv,
-                          struct v4l2_buffer *b);
-int tm6000_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *b);
-int tm6000_vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b);
-ssize_t tm6000_v4l2_read(struct file *filp, char __user * buf, size_t count,
-                        loff_t *f_pos);
-unsigned int tm6000_v4l2_poll(struct file *file,
-                             struct poll_table_struct *wait);
-int tm6000_queue_init(struct tm6000_core *dev);
-
-/* In tm6000-alsa.c */
-/*int tm6000_audio_init(struct tm6000_core *dev, int idx);*/
-
-/* In tm6000-input.c */
-int tm6000_ir_init(struct tm6000_core *dev);
-int tm6000_ir_fini(struct tm6000_core *dev);
-void tm6000_ir_wait(struct tm6000_core *dev, u8 state);
-int tm6000_ir_int_start(struct tm6000_core *dev);
-void tm6000_ir_int_stop(struct tm6000_core *dev);
-
-/* Debug stuff */
-
-extern int tm6000_debug;
-
-#define dprintk(dev, level, fmt, arg...) do {\
-       if (tm6000_debug & level) \
-               printk(KERN_INFO "(%lu) %s %s :"fmt, jiffies, \
-                        dev->name, __func__ , ##arg); } while (0)
-
-#define V4L2_DEBUG_REG         0x0004
-#define V4L2_DEBUG_I2C         0x0008
-#define V4L2_DEBUG_QUEUE       0x0010
-#define V4L2_DEBUG_ISOC                0x0020
-#define V4L2_DEBUG_RES_LOCK    0x0040  /* Resource locking */
-#define V4L2_DEBUG_OPEN                0x0080  /* video open/close debug */
-
-#define tm6000_err(fmt, arg...) do {\
-       printk(KERN_ERR "tm6000 %s :"fmt, \
-               __func__ , ##arg); } while (0)
diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/video/usbvision/Kconfig
deleted file mode 100644 (file)
index fc24ef0..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-config VIDEO_USBVISION
-       tristate "USB video devices based on Nogatech NT1003/1004/1005"
-       depends on I2C && VIDEO_V4L2
-       select VIDEO_TUNER
-       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
-       ---help---
-         There are more than 50 different USB video devices based on
-         NT1003/1004/1005 USB Bridges. This driver enables using those
-         devices.
-
-         To compile this driver as a module, choose M here: the
-         module will be called usbvision.
diff --git a/drivers/media/video/usbvision/Makefile b/drivers/media/video/usbvision/Makefile
deleted file mode 100644 (file)
index d55c6bd..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-usbvision-objs  := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-cards.o
-
-obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o
-
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/tuners
diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c
deleted file mode 100644 (file)
index 3103d0d..0000000
+++ /dev/null
@@ -1,1133 +0,0 @@
-/*
- *  usbvision-cards.c
- *  usbvision cards definition file
- *
- * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
- *
- * This module is part of usbvision driver project.
- * Updates to driver completed by Dwaine P. Garden
- *
- * 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/list.h>
-#include <linux/module.h>
-#include <media/v4l2-dev.h>
-#include <media/tuner.h>
-#include "usbvision.h"
-#include "usbvision-cards.h"
-
-/* Supported Devices: A table for usbvision.c*/
-struct usbvision_device_data_st  usbvision_device_data[] = {
-       [XANBOO] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 4,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Xanboo",
-       },
-       [BELKIN_VIDEOBUS_II] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Belkin USB VideoBus II Adapter",
-       },
-       [BELKIN_VIDEOBUS] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Belkin Components USB VideoBus",
-       },
-       [BELKIN_USB_VIDEOBUS_II] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Belkin USB VideoBus II",
-       },
-       [ECHOFX_INTERVIEW_LITE] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 0,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "echoFX InterView Lite",
-       },
-       [USBGEAR_USBG_V1] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "USBGear USBG-V1 resp. HAMA USB",
-       },
-       [D_LINK_V100] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 4,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 0,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "D-Link V100",
-       },
-       [X10_USB_CAMERA] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "X10 USB Camera",
-       },
-       [HPG_WINTV_LIVE_PAL_BG] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = -1,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Live (PAL B/G)",
-       },
-       [HPG_WINTV_LIVE_PRO_NTSC_MN] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 0,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Live Pro (NTSC M/N)",
-       },
-       [ZORAN_PMD_NOGATECH] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 2,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Zoran Co. PMD (Nogatech) AV-grabber Manhattan",
-       },
-       [NOGATECH_USB_TV_NTSC_FM] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .x_offset       = -1,
-               .y_offset       = 20,
-               .model_string   = "Nogatech USB-TV (NTSC) FM",
-       },
-       [PNY_USB_TV_NTSC_FM] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .x_offset       = -1,
-               .y_offset       = 20,
-               .model_string   = "PNY USB-TV (NTSC) FM",
-       },
-       [PV_PLAYTV_USB_PRO_PAL_FM] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "PixelView PlayTv-USB PRO (PAL) FM",
-       },
-       [ZT_721] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "ZTV ZT-721 2.4GHz USB A/V Receiver",
-       },
-       [HPG_WINTV_NTSC_MN] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .x_offset       = -1,
-               .y_offset       = 20,
-               .model_string   = "Hauppauge WinTV USB (NTSC M/N)",
-       },
-       [HPG_WINTV_PAL_BG] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Hauppauge WinTV USB (PAL B/G)",
-       },
-       [HPG_WINTV_PAL_I] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Hauppauge WinTV USB (PAL I)",
-       },
-       [HPG_WINTV_PAL_SECAM_L] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_SECAM,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_SECAM,
-               .x_offset       = 0x80,
-               .y_offset       = 0x16,
-               .model_string   = "Hauppauge WinTV USB (PAL/SECAM L)",
-       },
-       [HPG_WINTV_PAL_D_K] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Hauppauge WinTV USB (PAL D/K)",
-       },
-       [HPG_WINTV_NTSC_FM] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Hauppauge WinTV USB (NTSC FM)",
-       },
-       [HPG_WINTV_PAL_BG_FM] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Hauppauge WinTV USB (PAL B/G FM)",
-       },
-       [HPG_WINTV_PAL_I_FM] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Hauppauge WinTV USB (PAL I FM)",
-       },
-       [HPG_WINTV_PAL_D_K_FM] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Hauppauge WinTV USB (PAL D/K FM)",
-       },
-       [HPG_WINTV_PRO_NTSC_MN] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_MICROTUNE_4049FM5,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (NTSC M/N)",
-       },
-       [HPG_WINTV_PRO_NTSC_MN_V2] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_MICROTUNE_4049FM5,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (NTSC M/N) V2",
-       },
-       [HPG_WINTV_PRO_PAL] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L)",
-       },
-       [HPG_WINTV_PRO_NTSC_MN_V3] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (NTSC M/N) V3",
-       },
-       [HPG_WINTV_PRO_PAL_BG] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (PAL B/G)",
-       },
-       [HPG_WINTV_PRO_PAL_I] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (PAL I)",
-       },
-       [HPG_WINTV_PRO_PAL_SECAM_L] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_SECAM,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_SECAM,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM L)",
-       },
-       [HPG_WINTV_PRO_PAL_D_K] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (PAL D/K)",
-       },
-       [HPG_WINTV_PRO_PAL_SECAM] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_SECAM,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_SECAM,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L)",
-       },
-       [HPG_WINTV_PRO_PAL_SECAM_V2] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_SECAM,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_SECAM,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM BGDK/I/L) V2",
-       },
-       [HPG_WINTV_PRO_PAL_BG_V2] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_ALPS_TSBE1_PAL,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (PAL B/G) V2",
-       },
-       [HPG_WINTV_PRO_PAL_BG_D_K] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_ALPS_TSBE1_PAL,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (PAL B/G,D/K)",
-       },
-       [HPG_WINTV_PRO_PAL_I_D_K] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_LG_PAL_NEW_TAPC,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (PAL I,D/K)",
-       },
-       [HPG_WINTV_PRO_NTSC_MN_FM] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (NTSC M/N FM)",
-       },
-       [HPG_WINTV_PRO_PAL_BG_FM] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (PAL B/G FM)",
-       },
-       [HPG_WINTV_PRO_PAL_I_FM] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (PAL I FM)",
-       },
-       [HPG_WINTV_PRO_PAL_D_K_FM] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (PAL D/K FM)",
-       },
-       [HPG_WINTV_PRO_TEMIC_PAL_FM] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_MICROTUNE_4049FM5,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (Temic PAL/SECAM B/G/I/D/K/L FM)",
-       },
-       [HPG_WINTV_PRO_TEMIC_PAL_BG_FM] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_MICROTUNE_4049FM5,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (Temic PAL B/G FM)",
-       },
-       [HPG_WINTV_PRO_PAL_FM] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (PAL/SECAM B/G/I/D/K/L FM)",
-       },
-       [HPG_WINTV_PRO_NTSC_MN_FM_V2] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Hauppauge WinTV USB Pro (NTSC M/N FM) V2",
-       },
-       [CAMTEL_TVB330] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .x_offset       = 5,
-               .y_offset       = 5,
-               .model_string   = "Camtel Technology USB TV Genie Pro FM Model TVB330",
-       },
-       [DIGITAL_VIDEO_CREATOR_I] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 0,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Digital Video Creator I",
-       },
-       [GLOBAL_VILLAGE_GV_007_NTSC] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 0,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = 82,
-               .y_offset       = 20,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Global Village GV-007 (NTSC)",
-       },
-       [DAZZLE_DVC_50_REV_1_NTSC] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 0,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Dazzle Fusion Model DVC-50 Rev 1 (NTSC)",
-       },
-       [DAZZLE_DVC_80_REV_1_PAL] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 0,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Dazzle Fusion Model DVC-80 Rev 1 (PAL)",
-       },
-       [DAZZLE_DVC_90_REV_1_SECAM] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_SECAM,
-               .audio_channels = 0,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Dazzle Fusion Model DVC-90 Rev 1 (SECAM)",
-       },
-       [ESKAPE_LABS_MYTV2GO] = {
-               .interface      = 0,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Eskape Labs MyTV2Go",
-       },
-       [PINNA_PCTV_USB_PAL] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 0,
-               .tuner          = 1,
-               .tuner_type     = TUNER_TEMIC_4066FY5_PAL_I,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Pinnacle Studio PCTV USB (PAL)",
-       },
-       [PINNA_PCTV_USB_SECAM] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_SECAM,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_SECAM,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Pinnacle Studio PCTV USB (SECAM)",
-       },
-       [PINNA_PCTV_USB_PAL_FM] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = 128,
-               .y_offset       = 23,
-               .model_string   = "Pinnacle Studio PCTV USB (PAL) FM",
-       },
-       [MIRO_PCTV_USB] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_PAL,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Miro PCTV USB",
-       },
-       [PINNA_PCTV_USB_NTSC_FM] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Pinnacle Studio PCTV USB (NTSC) FM",
-       },
-       [PINNA_PCTV_USB_NTSC_FM_V3] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Pinnacle Studio PCTV USB (NTSC) FM V3",
-       },
-       [PINNA_PCTV_USB_PAL_FM_V2] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_TEMIC_4009FR5_PAL,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Pinnacle Studio PCTV USB (PAL) FM V2",
-       },
-       [PINNA_PCTV_USB_NTSC_FM_V2] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_TEMIC_4039FR5_NTSC,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Pinnacle Studio PCTV USB (NTSC) FM V2",
-       },
-       [PINNA_PCTV_USB_PAL_FM_V3] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_TEMIC_4009FR5_PAL,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Pinnacle Studio PCTV USB (PAL) FM V3",
-       },
-       [PINNA_LINX_VD_IN_CAB_NTSC] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Pinnacle Studio Linx Video input cable (NTSC)",
-       },
-       [PINNA_LINX_VD_IN_CAB_PAL] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 2,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Pinnacle Studio Linx Video input cable (PAL)",
-       },
-       [PINNA_PCTV_BUNGEE_PAL_FM] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7113,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 1,
-               .radio          = 1,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_TEMIC_4009FR5_PAL,
-               .x_offset       = 0,
-               .y_offset       = 3,
-               .dvi_yuv_override = 1,
-               .dvi_yuv        = 7,
-               .model_string   = "Pinnacle PCTV Bungee USB (PAL) FM",
-       },
-       [HPG_WINTV] = {
-               .interface      = -1,
-               .codec          = CODEC_SAA7111,
-               .video_channels = 3,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 1,
-               .radio          = 0,
-               .vbi            = 1,
-               .tuner          = 1,
-               .tuner_type     = TUNER_PHILIPS_NTSC_M,
-               .x_offset       = -1,
-               .y_offset       = -1,
-               .model_string   = "Hauppauge WinTv-USB",
-       },
-       [MICROCAM_NTSC] = {
-               .interface      = -1,
-               .codec          = CODEC_WEBCAM,
-               .video_channels = 1,
-               .video_norm     = V4L2_STD_NTSC,
-               .audio_channels = 0,
-               .radio          = 0,
-               .vbi            = 0,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = 71,
-               .y_offset       = 15,
-               .model_string   = "Nogatech USB MicroCam NTSC (NV3000N)",
-       },
-       [MICROCAM_PAL] = {
-               .interface      = -1,
-               .codec          = CODEC_WEBCAM,
-               .video_channels = 1,
-               .video_norm     = V4L2_STD_PAL,
-               .audio_channels = 0,
-               .radio          = 0,
-               .vbi            = 0,
-               .tuner          = 0,
-               .tuner_type     = 0,
-               .x_offset       = 71,
-               .y_offset       = 18,
-               .model_string   = "Nogatech USB MicroCam PAL (NV3001P)",
-       },
-};
-const int usbvision_device_data_size = ARRAY_SIZE(usbvision_device_data);
-
-/* Supported Devices */
-
-struct usb_device_id usbvision_table[] = {
-       { USB_DEVICE(0x0a6f, 0x0400), .driver_info = XANBOO },
-       { USB_DEVICE(0x050d, 0x0106), .driver_info = BELKIN_VIDEOBUS_II },
-       { USB_DEVICE(0x050d, 0x0207), .driver_info = BELKIN_VIDEOBUS },
-       { USB_DEVICE(0x050d, 0x0208), .driver_info = BELKIN_USB_VIDEOBUS_II },
-       { USB_DEVICE(0x0571, 0x0002), .driver_info = ECHOFX_INTERVIEW_LITE },
-       { USB_DEVICE(0x0573, 0x0003), .driver_info = USBGEAR_USBG_V1 },
-       { USB_DEVICE(0x0573, 0x0400), .driver_info = D_LINK_V100 },
-       { USB_DEVICE(0x0573, 0x2000), .driver_info = X10_USB_CAMERA },
-       { USB_DEVICE(0x0573, 0x2d00), .driver_info = HPG_WINTV_LIVE_PAL_BG },
-       { USB_DEVICE(0x0573, 0x2d01), .driver_info = HPG_WINTV_LIVE_PRO_NTSC_MN },
-       { USB_DEVICE(0x0573, 0x2101), .driver_info = ZORAN_PMD_NOGATECH },
-       { USB_DEVICE(0x0573, 0x3000), .driver_info = MICROCAM_NTSC },
-       { USB_DEVICE(0x0573, 0x3001), .driver_info = MICROCAM_PAL },
-       { USB_DEVICE(0x0573, 0x4100), .driver_info = NOGATECH_USB_TV_NTSC_FM },
-       { USB_DEVICE(0x0573, 0x4110), .driver_info = PNY_USB_TV_NTSC_FM },
-       { USB_DEVICE(0x0573, 0x4450), .driver_info = PV_PLAYTV_USB_PRO_PAL_FM },
-       { USB_DEVICE(0x0573, 0x4550), .driver_info = ZT_721 },
-       { USB_DEVICE(0x0573, 0x4d00), .driver_info = HPG_WINTV_NTSC_MN },
-       { USB_DEVICE(0x0573, 0x4d01), .driver_info = HPG_WINTV_PAL_BG },
-       { USB_DEVICE(0x0573, 0x4d02), .driver_info = HPG_WINTV_PAL_I },
-       { USB_DEVICE(0x0573, 0x4d03), .driver_info = HPG_WINTV_PAL_SECAM_L },
-       { USB_DEVICE(0x0573, 0x4d04), .driver_info = HPG_WINTV_PAL_D_K },
-       { USB_DEVICE(0x0573, 0x4d10), .driver_info = HPG_WINTV_NTSC_FM },
-       { USB_DEVICE(0x0573, 0x4d11), .driver_info = HPG_WINTV_PAL_BG_FM },
-       { USB_DEVICE(0x0573, 0x4d12), .driver_info = HPG_WINTV_PAL_I_FM },
-       { USB_DEVICE(0x0573, 0x4d14), .driver_info = HPG_WINTV_PAL_D_K_FM },
-       { USB_DEVICE(0x0573, 0x4d2a), .driver_info = HPG_WINTV_PRO_NTSC_MN },
-       { USB_DEVICE(0x0573, 0x4d2b), .driver_info = HPG_WINTV_PRO_NTSC_MN_V2 },
-       { USB_DEVICE(0x0573, 0x4d2c), .driver_info = HPG_WINTV_PRO_PAL },
-       { USB_DEVICE(0x0573, 0x4d20), .driver_info = HPG_WINTV_PRO_NTSC_MN_V3 },
-       { USB_DEVICE(0x0573, 0x4d21), .driver_info = HPG_WINTV_PRO_PAL_BG },
-       { USB_DEVICE(0x0573, 0x4d22), .driver_info = HPG_WINTV_PRO_PAL_I },
-       { USB_DEVICE(0x0573, 0x4d23), .driver_info = HPG_WINTV_PRO_PAL_SECAM_L },
-       { USB_DEVICE(0x0573, 0x4d24), .driver_info = HPG_WINTV_PRO_PAL_D_K },
-       { USB_DEVICE(0x0573, 0x4d25), .driver_info = HPG_WINTV_PRO_PAL_SECAM },
-       { USB_DEVICE(0x0573, 0x4d26), .driver_info = HPG_WINTV_PRO_PAL_SECAM_V2 },
-       { USB_DEVICE(0x0573, 0x4d27), .driver_info = HPG_WINTV_PRO_PAL_BG_V2 },
-       { USB_DEVICE(0x0573, 0x4d28), .driver_info = HPG_WINTV_PRO_PAL_BG_D_K },
-       { USB_DEVICE(0x0573, 0x4d29), .driver_info = HPG_WINTV_PRO_PAL_I_D_K },
-       { USB_DEVICE(0x0573, 0x4d30), .driver_info = HPG_WINTV_PRO_NTSC_MN_FM },
-       { USB_DEVICE(0x0573, 0x4d31), .driver_info = HPG_WINTV_PRO_PAL_BG_FM },
-       { USB_DEVICE(0x0573, 0x4d32), .driver_info = HPG_WINTV_PRO_PAL_I_FM },
-       { USB_DEVICE(0x0573, 0x4d34), .driver_info = HPG_WINTV_PRO_PAL_D_K_FM },
-       { USB_DEVICE(0x0573, 0x4d35), .driver_info = HPG_WINTV_PRO_TEMIC_PAL_FM },
-       { USB_DEVICE(0x0573, 0x4d36), .driver_info = HPG_WINTV_PRO_TEMIC_PAL_BG_FM },
-       { USB_DEVICE(0x0573, 0x4d37), .driver_info = HPG_WINTV_PRO_PAL_FM },
-       { USB_DEVICE(0x0573, 0x4d38), .driver_info = HPG_WINTV_PRO_NTSC_MN_FM_V2 },
-       { USB_DEVICE(0x0768, 0x0006), .driver_info = CAMTEL_TVB330 },
-       { USB_DEVICE(0x07d0, 0x0001), .driver_info = DIGITAL_VIDEO_CREATOR_I },
-       { USB_DEVICE(0x07d0, 0x0002), .driver_info = GLOBAL_VILLAGE_GV_007_NTSC },
-       { USB_DEVICE(0x07d0, 0x0003), .driver_info = DAZZLE_DVC_50_REV_1_NTSC },
-       { USB_DEVICE(0x07d0, 0x0004), .driver_info = DAZZLE_DVC_80_REV_1_PAL },
-       { USB_DEVICE(0x07d0, 0x0005), .driver_info = DAZZLE_DVC_90_REV_1_SECAM },
-       { USB_DEVICE(0x07f8, 0x9104), .driver_info = ESKAPE_LABS_MYTV2GO },
-       { USB_DEVICE(0x2304, 0x010d), .driver_info = PINNA_PCTV_USB_PAL },
-       { USB_DEVICE(0x2304, 0x0109), .driver_info = PINNA_PCTV_USB_SECAM },
-       { USB_DEVICE(0x2304, 0x0110), .driver_info = PINNA_PCTV_USB_PAL_FM },
-       { USB_DEVICE(0x2304, 0x0111), .driver_info = MIRO_PCTV_USB },
-       { USB_DEVICE(0x2304, 0x0112), .driver_info = PINNA_PCTV_USB_NTSC_FM },
-       { USB_DEVICE(0x2304, 0x0113), .driver_info = PINNA_PCTV_USB_NTSC_FM_V3 },
-       { USB_DEVICE(0x2304, 0x0210), .driver_info = PINNA_PCTV_USB_PAL_FM_V2 },
-       { USB_DEVICE(0x2304, 0x0212), .driver_info = PINNA_PCTV_USB_NTSC_FM_V2 },
-       { USB_DEVICE(0x2304, 0x0214), .driver_info = PINNA_PCTV_USB_PAL_FM_V3 },
-       { USB_DEVICE(0x2304, 0x0300), .driver_info = PINNA_LINX_VD_IN_CAB_NTSC },
-       { USB_DEVICE(0x2304, 0x0301), .driver_info = PINNA_LINX_VD_IN_CAB_PAL },
-       { USB_DEVICE(0x2304, 0x0419), .driver_info = PINNA_PCTV_BUNGEE_PAL_FM },
-       { USB_DEVICE(0x2400, 0x4200), .driver_info = HPG_WINTV },
-       { },    /* terminate list */
-};
-
-MODULE_DEVICE_TABLE(usb, usbvision_table);
diff --git a/drivers/media/video/usbvision/usbvision-cards.h b/drivers/media/video/usbvision/usbvision-cards.h
deleted file mode 100644 (file)
index a51cc11..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#define XANBOO                                   0
-#define BELKIN_VIDEOBUS_II                       1
-#define BELKIN_VIDEOBUS                          2
-#define BELKIN_USB_VIDEOBUS_II                   3
-#define ECHOFX_INTERVIEW_LITE                    4
-#define USBGEAR_USBG_V1                          5
-#define D_LINK_V100                              6
-#define X10_USB_CAMERA                           7
-#define HPG_WINTV_LIVE_PAL_BG                    8
-#define HPG_WINTV_LIVE_PRO_NTSC_MN               9
-#define ZORAN_PMD_NOGATECH                       10
-#define NOGATECH_USB_TV_NTSC_FM                  11
-#define PNY_USB_TV_NTSC_FM                       12
-#define PV_PLAYTV_USB_PRO_PAL_FM                 13
-#define ZT_721                                   14
-#define HPG_WINTV_NTSC_MN                        15
-#define HPG_WINTV_PAL_BG                         16
-#define HPG_WINTV_PAL_I                          17
-#define HPG_WINTV_PAL_SECAM_L                    18
-#define HPG_WINTV_PAL_D_K                        19
-#define HPG_WINTV_NTSC_FM                        20
-#define HPG_WINTV_PAL_BG_FM                      21
-#define HPG_WINTV_PAL_I_FM                       22
-#define HPG_WINTV_PAL_D_K_FM                     23
-#define HPG_WINTV_PRO_NTSC_MN                    24
-#define HPG_WINTV_PRO_NTSC_MN_V2                 25
-#define HPG_WINTV_PRO_PAL                        26
-#define HPG_WINTV_PRO_NTSC_MN_V3                 27
-#define HPG_WINTV_PRO_PAL_BG                     28
-#define HPG_WINTV_PRO_PAL_I                      29
-#define HPG_WINTV_PRO_PAL_SECAM_L                30
-#define HPG_WINTV_PRO_PAL_D_K                    31
-#define HPG_WINTV_PRO_PAL_SECAM                  32
-#define HPG_WINTV_PRO_PAL_SECAM_V2               33
-#define HPG_WINTV_PRO_PAL_BG_V2                  34
-#define HPG_WINTV_PRO_PAL_BG_D_K                 35
-#define HPG_WINTV_PRO_PAL_I_D_K                  36
-#define HPG_WINTV_PRO_NTSC_MN_FM                 37
-#define HPG_WINTV_PRO_PAL_BG_FM                  38
-#define HPG_WINTV_PRO_PAL_I_FM                   39
-#define HPG_WINTV_PRO_PAL_D_K_FM                 40
-#define HPG_WINTV_PRO_TEMIC_PAL_FM               41
-#define HPG_WINTV_PRO_TEMIC_PAL_BG_FM            42
-#define HPG_WINTV_PRO_PAL_FM                     43
-#define HPG_WINTV_PRO_NTSC_MN_FM_V2              44
-#define CAMTEL_TVB330                            45
-#define DIGITAL_VIDEO_CREATOR_I                  46
-#define GLOBAL_VILLAGE_GV_007_NTSC               47
-#define DAZZLE_DVC_50_REV_1_NTSC                 48
-#define DAZZLE_DVC_80_REV_1_PAL                  49
-#define DAZZLE_DVC_90_REV_1_SECAM                50
-#define ESKAPE_LABS_MYTV2GO                      51
-#define PINNA_PCTV_USB_PAL                       52
-#define PINNA_PCTV_USB_SECAM                     53
-#define PINNA_PCTV_USB_PAL_FM                    54
-#define MIRO_PCTV_USB                            55
-#define PINNA_PCTV_USB_NTSC_FM                   56
-#define PINNA_PCTV_USB_PAL_FM_V2                 57
-#define PINNA_PCTV_USB_NTSC_FM_V2                58
-#define PINNA_PCTV_USB_PAL_FM_V3                 59
-#define PINNA_LINX_VD_IN_CAB_NTSC                60
-#define PINNA_LINX_VD_IN_CAB_PAL                 61
-#define PINNA_PCTV_BUNGEE_PAL_FM                 62
-#define HPG_WINTV                                63
-#define PINNA_PCTV_USB_NTSC_FM_V3                64
-#define MICROCAM_NTSC                            65
-#define MICROCAM_PAL                             66
-
-extern const int usbvision_device_data_size;
diff --git a/drivers/media/video/usbvision/usbvision-core.c b/drivers/media/video/usbvision/usbvision-core.c
deleted file mode 100644 (file)
index c9b2042..0000000
+++ /dev/null
@@ -1,2518 +0,0 @@
-/*
- * usbvision-core.c - driver for NT100x USB video capture devices
- *
- *
- * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
- *                         Dwaine Garden <dwainegarden@rogers.com>
- *
- * This module is part of usbvision driver project.
- * Updates to driver completed by Dwaine P. Garden
- *
- * 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/list.h>
-#include <linux/timer.h>
-#include <linux/gfp.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/videodev2.h>
-#include <linux/i2c.h>
-
-#include <media/saa7115.h>
-#include <media/v4l2-common.h>
-#include <media/tuner.h>
-
-#include <linux/workqueue.h>
-
-#include "usbvision.h"
-
-static unsigned int core_debug;
-module_param(core_debug, int, 0644);
-MODULE_PARM_DESC(core_debug, "enable debug messages [core]");
-
-static int adjust_compression = 1;     /* Set the compression to be adaptive */
-module_param(adjust_compression, int, 0444);
-MODULE_PARM_DESC(adjust_compression, " Set the ADPCM compression for the device.  Default: 1 (On)");
-
-/* To help people with Black and White output with using s-video input.
- * Some cables and input device are wired differently. */
-static int switch_svideo_input;
-module_param(switch_svideo_input, int, 0444);
-MODULE_PARM_DESC(switch_svideo_input, " Set the S-Video input.  Some cables and input device are wired differently. Default: 0 (Off)");
-
-static unsigned int adjust_x_offset = -1;
-module_param(adjust_x_offset, int, 0644);
-MODULE_PARM_DESC(adjust_x_offset, "adjust X offset display [core]");
-
-static unsigned int adjust_y_offset = -1;
-module_param(adjust_y_offset, int, 0644);
-MODULE_PARM_DESC(adjust_y_offset, "adjust Y offset display [core]");
-
-
-#define        ENABLE_HEXDUMP  0       /* Enable if you need it */
-
-
-#ifdef USBVISION_DEBUG
-       #define PDEBUG(level, fmt, args...) { \
-               if (core_debug & (level)) \
-                       printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \
-                               __func__, __LINE__ , ## args); \
-       }
-#else
-       #define PDEBUG(level, fmt, args...) do {} while (0)
-#endif
-
-#define DBG_HEADER     (1 << 0)
-#define DBG_IRQ                (1 << 1)
-#define DBG_ISOC       (1 << 2)
-#define DBG_PARSE      (1 << 3)
-#define DBG_SCRATCH    (1 << 4)
-#define DBG_FUNC       (1 << 5)
-
-static const int max_imgwidth = MAX_FRAME_WIDTH;
-static const int max_imgheight = MAX_FRAME_HEIGHT;
-static const int min_imgwidth = MIN_FRAME_WIDTH;
-static const int min_imgheight = MIN_FRAME_HEIGHT;
-
-/* The value of 'scratch_buf_size' affects quality of the picture
- * in many ways. Shorter buffers may cause loss of data when client
- * is too slow. Larger buffers are memory-consuming and take longer
- * to work with. This setting can be adjusted, but the default value
- * should be OK for most desktop users.
- */
-#define DEFAULT_SCRATCH_BUF_SIZE       (0x20000)               /* 128kB memory scratch buffer */
-static const int scratch_buf_size = DEFAULT_SCRATCH_BUF_SIZE;
-
-/* Function prototypes */
-static int usbvision_request_intra(struct usb_usbvision *usbvision);
-static int usbvision_unrequest_intra(struct usb_usbvision *usbvision);
-static int usbvision_adjust_compression(struct usb_usbvision *usbvision);
-static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision);
-
-/*******************************/
-/* Memory management functions */
-/*******************************/
-
-/*
- * Here we want the physical address of the memory.
- * This is used when initializing the contents of the area.
- */
-
-static void *usbvision_rvmalloc(unsigned long size)
-{
-       void *mem;
-       unsigned long adr;
-
-       size = PAGE_ALIGN(size);
-       mem = vmalloc_32(size);
-       if (!mem)
-               return NULL;
-
-       memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-       adr = (unsigned long) mem;
-       while (size > 0) {
-               SetPageReserved(vmalloc_to_page((void *)adr));
-               adr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-
-       return mem;
-}
-
-static void usbvision_rvfree(void *mem, unsigned long size)
-{
-       unsigned long adr;
-
-       if (!mem)
-               return;
-
-       size = PAGE_ALIGN(size);
-
-       adr = (unsigned long) mem;
-       while ((long) size > 0) {
-               ClearPageReserved(vmalloc_to_page((void *)adr));
-               adr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-
-       vfree(mem);
-}
-
-
-#if ENABLE_HEXDUMP
-static void usbvision_hexdump(const unsigned char *data, int len)
-{
-       char tmp[80];
-       int i, k;
-
-       for (i = k = 0; len > 0; i++, len--) {
-               if (i > 0 && (i % 16 == 0)) {
-                       printk("%s\n", tmp);
-                       k = 0;
-               }
-               k += sprintf(&tmp[k], "%02x ", data[i]);
-       }
-       if (k > 0)
-               printk(KERN_CONT "%s\n", tmp);
-}
-#endif
-
-/********************************
- * scratch ring buffer handling
- ********************************/
-static int scratch_len(struct usb_usbvision *usbvision)    /* This returns the amount of data actually in the buffer */
-{
-       int len = usbvision->scratch_write_ptr - usbvision->scratch_read_ptr;
-
-       if (len < 0)
-               len += scratch_buf_size;
-       PDEBUG(DBG_SCRATCH, "scratch_len() = %d\n", len);
-
-       return len;
-}
-
-
-/* This returns the free space left in the buffer */
-static int scratch_free(struct usb_usbvision *usbvision)
-{
-       int free = usbvision->scratch_read_ptr - usbvision->scratch_write_ptr;
-       if (free <= 0)
-               free += scratch_buf_size;
-       if (free) {
-               free -= 1;                                                      /* at least one byte in the buffer must */
-                                                                               /* left blank, otherwise there is no chance to differ between full and empty */
-       }
-       PDEBUG(DBG_SCRATCH, "return %d\n", free);
-
-       return free;
-}
-
-
-/* This puts data into the buffer */
-static int scratch_put(struct usb_usbvision *usbvision, unsigned char *data,
-                      int len)
-{
-       int len_part;
-
-       if (usbvision->scratch_write_ptr + len < scratch_buf_size) {
-               memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len);
-               usbvision->scratch_write_ptr += len;
-       } else {
-               len_part = scratch_buf_size - usbvision->scratch_write_ptr;
-               memcpy(usbvision->scratch + usbvision->scratch_write_ptr, data, len_part);
-               if (len == len_part) {
-                       usbvision->scratch_write_ptr = 0;                       /* just set write_ptr to zero */
-               } else {
-                       memcpy(usbvision->scratch, data + len_part, len - len_part);
-                       usbvision->scratch_write_ptr = len - len_part;
-               }
-       }
-
-       PDEBUG(DBG_SCRATCH, "len=%d, new write_ptr=%d\n", len, usbvision->scratch_write_ptr);
-
-       return len;
-}
-
-/* This marks the write_ptr as position of new frame header */
-static void scratch_mark_header(struct usb_usbvision *usbvision)
-{
-       PDEBUG(DBG_SCRATCH, "header at write_ptr=%d\n", usbvision->scratch_headermarker_write_ptr);
-
-       usbvision->scratch_headermarker[usbvision->scratch_headermarker_write_ptr] =
-                               usbvision->scratch_write_ptr;
-       usbvision->scratch_headermarker_write_ptr += 1;
-       usbvision->scratch_headermarker_write_ptr %= USBVISION_NUM_HEADERMARKER;
-}
-
-/* This gets data from the buffer at the given "ptr" position */
-static int scratch_get_extra(struct usb_usbvision *usbvision,
-                            unsigned char *data, int *ptr, int len)
-{
-       int len_part;
-
-       if (*ptr + len < scratch_buf_size) {
-               memcpy(data, usbvision->scratch + *ptr, len);
-               *ptr += len;
-       } else {
-               len_part = scratch_buf_size - *ptr;
-               memcpy(data, usbvision->scratch + *ptr, len_part);
-               if (len == len_part) {
-                       *ptr = 0;                                                       /* just set the y_ptr to zero */
-               } else {
-                       memcpy(data + len_part, usbvision->scratch, len - len_part);
-                       *ptr = len - len_part;
-               }
-       }
-
-       PDEBUG(DBG_SCRATCH, "len=%d, new ptr=%d\n", len, *ptr);
-
-       return len;
-}
-
-
-/* This sets the scratch extra read pointer */
-static void scratch_set_extra_ptr(struct usb_usbvision *usbvision, int *ptr,
-                                 int len)
-{
-       *ptr = (usbvision->scratch_read_ptr + len) % scratch_buf_size;
-
-       PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr);
-}
-
-
-/* This increments the scratch extra read pointer */
-static void scratch_inc_extra_ptr(int *ptr, int len)
-{
-       *ptr = (*ptr + len) % scratch_buf_size;
-
-       PDEBUG(DBG_SCRATCH, "ptr=%d\n", *ptr);
-}
-
-
-/* This gets data from the buffer */
-static int scratch_get(struct usb_usbvision *usbvision, unsigned char *data,
-                      int len)
-{
-       int len_part;
-
-       if (usbvision->scratch_read_ptr + len < scratch_buf_size) {
-               memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len);
-               usbvision->scratch_read_ptr += len;
-       } else {
-               len_part = scratch_buf_size - usbvision->scratch_read_ptr;
-               memcpy(data, usbvision->scratch + usbvision->scratch_read_ptr, len_part);
-               if (len == len_part) {
-                       usbvision->scratch_read_ptr = 0;                                /* just set the read_ptr to zero */
-               } else {
-                       memcpy(data + len_part, usbvision->scratch, len - len_part);
-                       usbvision->scratch_read_ptr = len - len_part;
-               }
-       }
-
-       PDEBUG(DBG_SCRATCH, "len=%d, new read_ptr=%d\n", len, usbvision->scratch_read_ptr);
-
-       return len;
-}
-
-
-/* This sets read pointer to next header and returns it */
-static int scratch_get_header(struct usb_usbvision *usbvision,
-                             struct usbvision_frame_header *header)
-{
-       int err_code = 0;
-
-       PDEBUG(DBG_SCRATCH, "from read_ptr=%d", usbvision->scratch_headermarker_read_ptr);
-
-       while (usbvision->scratch_headermarker_write_ptr -
-               usbvision->scratch_headermarker_read_ptr != 0) {
-               usbvision->scratch_read_ptr =
-                       usbvision->scratch_headermarker[usbvision->scratch_headermarker_read_ptr];
-               usbvision->scratch_headermarker_read_ptr += 1;
-               usbvision->scratch_headermarker_read_ptr %= USBVISION_NUM_HEADERMARKER;
-               scratch_get(usbvision, (unsigned char *)header, USBVISION_HEADER_LENGTH);
-               if ((header->magic_1 == USBVISION_MAGIC_1)
-                        && (header->magic_2 == USBVISION_MAGIC_2)
-                        && (header->header_length == USBVISION_HEADER_LENGTH)) {
-                       err_code = USBVISION_HEADER_LENGTH;
-                       header->frame_width  = header->frame_width_lo  + (header->frame_width_hi << 8);
-                       header->frame_height = header->frame_height_lo + (header->frame_height_hi << 8);
-                       break;
-               }
-       }
-
-       return err_code;
-}
-
-
-/* This removes len bytes of old data from the buffer */
-static void scratch_rm_old(struct usb_usbvision *usbvision, int len)
-{
-       usbvision->scratch_read_ptr += len;
-       usbvision->scratch_read_ptr %= scratch_buf_size;
-       PDEBUG(DBG_SCRATCH, "read_ptr is now %d\n", usbvision->scratch_read_ptr);
-}
-
-
-/* This resets the buffer - kills all data in it too */
-static void scratch_reset(struct usb_usbvision *usbvision)
-{
-       PDEBUG(DBG_SCRATCH, "\n");
-
-       usbvision->scratch_read_ptr = 0;
-       usbvision->scratch_write_ptr = 0;
-       usbvision->scratch_headermarker_read_ptr = 0;
-       usbvision->scratch_headermarker_write_ptr = 0;
-       usbvision->isocstate = isoc_state_no_frame;
-}
-
-int usbvision_scratch_alloc(struct usb_usbvision *usbvision)
-{
-       usbvision->scratch = vmalloc_32(scratch_buf_size);
-       scratch_reset(usbvision);
-       if (usbvision->scratch == NULL) {
-               dev_err(&usbvision->dev->dev,
-                       "%s: unable to allocate %d bytes for scratch\n",
-                               __func__, scratch_buf_size);
-               return -ENOMEM;
-       }
-       return 0;
-}
-
-void usbvision_scratch_free(struct usb_usbvision *usbvision)
-{
-       vfree(usbvision->scratch);
-       usbvision->scratch = NULL;
-}
-
-/*
- * usbvision_decompress_alloc()
- *
- * allocates intermediate buffer for decompression
- */
-int usbvision_decompress_alloc(struct usb_usbvision *usbvision)
-{
-       int IFB_size = MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * 3 / 2;
-
-       usbvision->intra_frame_buffer = vmalloc_32(IFB_size);
-       if (usbvision->intra_frame_buffer == NULL) {
-               dev_err(&usbvision->dev->dev,
-                       "%s: unable to allocate %d for compr. frame buffer\n",
-                               __func__, IFB_size);
-               return -ENOMEM;
-       }
-       return 0;
-}
-
-/*
- * usbvision_decompress_free()
- *
- * frees intermediate buffer for decompression
- */
-void usbvision_decompress_free(struct usb_usbvision *usbvision)
-{
-       vfree(usbvision->intra_frame_buffer);
-       usbvision->intra_frame_buffer = NULL;
-
-}
-
-/************************************************************
- * Here comes the data parsing stuff that is run as interrupt
- ************************************************************/
-/*
- * usbvision_find_header()
- *
- * Locate one of supported header markers in the scratch buffer.
- */
-static enum parse_state usbvision_find_header(struct usb_usbvision *usbvision)
-{
-       struct usbvision_frame *frame;
-       int found_header = 0;
-
-       frame = usbvision->cur_frame;
-
-       while (scratch_get_header(usbvision, &frame->isoc_header) == USBVISION_HEADER_LENGTH) {
-               /* found header in scratch */
-               PDEBUG(DBG_HEADER, "found header: 0x%02x%02x %d %d %d %d %#x 0x%02x %u %u",
-                               frame->isoc_header.magic_2,
-                               frame->isoc_header.magic_1,
-                               frame->isoc_header.header_length,
-                               frame->isoc_header.frame_num,
-                               frame->isoc_header.frame_phase,
-                               frame->isoc_header.frame_latency,
-                               frame->isoc_header.data_format,
-                               frame->isoc_header.format_param,
-                               frame->isoc_header.frame_width,
-                               frame->isoc_header.frame_height);
-
-               if (usbvision->request_intra) {
-                       if (frame->isoc_header.format_param & 0x80) {
-                               found_header = 1;
-                               usbvision->last_isoc_frame_num = -1; /* do not check for lost frames this time */
-                               usbvision_unrequest_intra(usbvision);
-                               break;
-                       }
-               } else {
-                       found_header = 1;
-                       break;
-               }
-       }
-
-       if (found_header) {
-               frame->frmwidth = frame->isoc_header.frame_width * usbvision->stretch_width;
-               frame->frmheight = frame->isoc_header.frame_height * usbvision->stretch_height;
-               frame->v4l2_linesize = (frame->frmwidth * frame->v4l2_format.depth) >> 3;
-       } else { /* no header found */
-               PDEBUG(DBG_HEADER, "skipping scratch data, no header");
-               scratch_reset(usbvision);
-               return parse_state_end_parse;
-       }
-
-       /* found header */
-       if (frame->isoc_header.data_format == ISOC_MODE_COMPRESS) {
-               /* check isoc_header.frame_num for lost frames */
-               if (usbvision->last_isoc_frame_num >= 0) {
-                       if (((usbvision->last_isoc_frame_num + 1) % 32) != frame->isoc_header.frame_num) {
-                               /* unexpected frame drop: need to request new intra frame */
-                               PDEBUG(DBG_HEADER, "Lost frame before %d on USB", frame->isoc_header.frame_num);
-                               usbvision_request_intra(usbvision);
-                               return parse_state_next_frame;
-                       }
-               }
-               usbvision->last_isoc_frame_num = frame->isoc_header.frame_num;
-       }
-       usbvision->header_count++;
-       frame->scanstate = scan_state_lines;
-       frame->curline = 0;
-
-       return parse_state_continue;
-}
-
-static enum parse_state usbvision_parse_lines_422(struct usb_usbvision *usbvision,
-                                          long *pcopylen)
-{
-       volatile struct usbvision_frame *frame;
-       unsigned char *f;
-       int len;
-       int i;
-       unsigned char yuyv[4] = { 180, 128, 10, 128 }; /* YUV components */
-       unsigned char rv, gv, bv;       /* RGB components */
-       int clipmask_index, bytes_per_pixel;
-       int stretch_bytes, clipmask_add;
-
-       frame  = usbvision->cur_frame;
-       f = frame->data + (frame->v4l2_linesize * frame->curline);
-
-       /* Make sure there's enough data for the entire line */
-       len = (frame->isoc_header.frame_width * 2) + 5;
-       if (scratch_len(usbvision) < len) {
-               PDEBUG(DBG_PARSE, "out of data in line %d, need %u.\n", frame->curline, len);
-               return parse_state_out;
-       }
-
-       if ((frame->curline + 1) >= frame->frmheight)
-               return parse_state_next_frame;
-
-       bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
-       stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel;
-       clipmask_index = frame->curline * MAX_FRAME_WIDTH;
-       clipmask_add = usbvision->stretch_width;
-
-       for (i = 0; i < frame->frmwidth; i += (2 * usbvision->stretch_width)) {
-               scratch_get(usbvision, &yuyv[0], 4);
-
-               if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
-                       *f++ = yuyv[0]; /* Y */
-                       *f++ = yuyv[3]; /* U */
-               } else {
-                       YUV_TO_RGB_BY_THE_BOOK(yuyv[0], yuyv[1], yuyv[3], rv, gv, bv);
-                       switch (frame->v4l2_format.format) {
-                       case V4L2_PIX_FMT_RGB565:
-                               *f++ = (0x1F & rv) |
-                                       (0xE0 & (gv << 5));
-                               *f++ = (0x07 & (gv >> 3)) |
-                                       (0xF8 &  bv);
-                               break;
-                       case V4L2_PIX_FMT_RGB24:
-                               *f++ = rv;
-                               *f++ = gv;
-                               *f++ = bv;
-                               break;
-                       case V4L2_PIX_FMT_RGB32:
-                               *f++ = rv;
-                               *f++ = gv;
-                               *f++ = bv;
-                               f++;
-                               break;
-                       case V4L2_PIX_FMT_RGB555:
-                               *f++ = (0x1F & rv) |
-                                       (0xE0 & (gv << 5));
-                               *f++ = (0x03 & (gv >> 3)) |
-                                       (0x7C & (bv << 2));
-                               break;
-                       }
-               }
-               clipmask_index += clipmask_add;
-               f += stretch_bytes;
-
-               if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
-                       *f++ = yuyv[2]; /* Y */
-                       *f++ = yuyv[1]; /* V */
-               } else {
-                       YUV_TO_RGB_BY_THE_BOOK(yuyv[2], yuyv[1], yuyv[3], rv, gv, bv);
-                       switch (frame->v4l2_format.format) {
-                       case V4L2_PIX_FMT_RGB565:
-                               *f++ = (0x1F & rv) |
-                                       (0xE0 & (gv << 5));
-                               *f++ = (0x07 & (gv >> 3)) |
-                                       (0xF8 &  bv);
-                               break;
-                       case V4L2_PIX_FMT_RGB24:
-                               *f++ = rv;
-                               *f++ = gv;
-                               *f++ = bv;
-                               break;
-                       case V4L2_PIX_FMT_RGB32:
-                               *f++ = rv;
-                               *f++ = gv;
-                               *f++ = bv;
-                               f++;
-                               break;
-                       case V4L2_PIX_FMT_RGB555:
-                               *f++ = (0x1F & rv) |
-                                       (0xE0 & (gv << 5));
-                               *f++ = (0x03 & (gv >> 3)) |
-                                       (0x7C & (bv << 2));
-                               break;
-                       }
-               }
-               clipmask_index += clipmask_add;
-               f += stretch_bytes;
-       }
-
-       frame->curline += usbvision->stretch_height;
-       *pcopylen += frame->v4l2_linesize * usbvision->stretch_height;
-
-       if (frame->curline >= frame->frmheight)
-               return parse_state_next_frame;
-       return parse_state_continue;
-}
-
-/* The decompression routine  */
-static int usbvision_decompress(struct usb_usbvision *usbvision, unsigned char *compressed,
-                                                               unsigned char *decompressed, int *start_pos,
-                                                               int *block_typestart_pos, int len)
-{
-       int rest_pixel, idx, pos, extra_pos, block_len, block_type_pos, block_type_len;
-       unsigned char block_byte, block_code, block_type, block_type_byte, integrator;
-
-       integrator = 0;
-       pos = *start_pos;
-       block_type_pos = *block_typestart_pos;
-       extra_pos = pos;
-       block_len = 0;
-       block_byte = 0;
-       block_code = 0;
-       block_type = 0;
-       block_type_byte = 0;
-       block_type_len = 0;
-       rest_pixel = len;
-
-       for (idx = 0; idx < len; idx++) {
-               if (block_len == 0) {
-                       if (block_type_len == 0) {
-                               block_type_byte = compressed[block_type_pos];
-                               block_type_pos++;
-                               block_type_len = 4;
-                       }
-                       block_type = (block_type_byte & 0xC0) >> 6;
-
-                       /* statistic: */
-                       usbvision->compr_block_types[block_type]++;
-
-                       pos = extra_pos;
-                       if (block_type == 0) {
-                               if (rest_pixel >= 24) {
-                                       idx += 23;
-                                       rest_pixel -= 24;
-                                       integrator = decompressed[idx];
-                               } else {
-                                       idx += rest_pixel - 1;
-                                       rest_pixel = 0;
-                               }
-                       } else {
-                               block_code = compressed[pos];
-                               pos++;
-                               if (rest_pixel >= 24)
-                                       block_len  = 24;
-                               else
-                                       block_len = rest_pixel;
-                               rest_pixel -= block_len;
-                               extra_pos = pos + (block_len / 4);
-                       }
-                       block_type_byte <<= 2;
-                       block_type_len -= 1;
-               }
-               if (block_len > 0) {
-                       if ((block_len % 4) == 0) {
-                               block_byte = compressed[pos];
-                               pos++;
-                       }
-                       if (block_type == 1) /* inter Block */
-                               integrator = decompressed[idx];
-                       switch (block_byte & 0xC0) {
-                       case 0x03 << 6:
-                               integrator += compressed[extra_pos];
-                               extra_pos++;
-                               break;
-                       case 0x02 << 6:
-                               integrator += block_code;
-                               break;
-                       case 0x00:
-                               integrator -= block_code;
-                               break;
-                       }
-                       decompressed[idx] = integrator;
-                       block_byte <<= 2;
-                       block_len -= 1;
-               }
-       }
-       *start_pos = extra_pos;
-       *block_typestart_pos = block_type_pos;
-       return idx;
-}
-
-
-/*
- * usbvision_parse_compress()
- *
- * Parse compressed frame from the scratch buffer, put
- * decoded RGB value into the current frame buffer and add the written
- * number of bytes (RGB) to the *pcopylen.
- *
- */
-static enum parse_state usbvision_parse_compress(struct usb_usbvision *usbvision,
-                                          long *pcopylen)
-{
-#define USBVISION_STRIP_MAGIC          0x5A
-#define USBVISION_STRIP_LEN_MAX                400
-#define USBVISION_STRIP_HEADER_LEN     3
-
-       struct usbvision_frame *frame;
-       unsigned char *f, *u = NULL, *v = NULL;
-       unsigned char strip_data[USBVISION_STRIP_LEN_MAX];
-       unsigned char strip_header[USBVISION_STRIP_HEADER_LEN];
-       int idx, idx_end, strip_len, strip_ptr, startblock_pos, block_pos, block_type_pos;
-       int clipmask_index;
-       int image_size;
-       unsigned char rv, gv, bv;
-       static unsigned char *Y, *U, *V;
-
-       frame = usbvision->cur_frame;
-       image_size = frame->frmwidth * frame->frmheight;
-       if ((frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) ||
-           (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420)) {       /* this is a planar format */
-               /* ... v4l2_linesize not used here. */
-               f = frame->data + (frame->width * frame->curline);
-       } else
-               f = frame->data + (frame->v4l2_linesize * frame->curline);
-
-       if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) { /* initialise u and v pointers */
-               /* get base of u and b planes add halfoffset */
-               u = frame->data
-                       + image_size
-                       + (frame->frmwidth >> 1) * frame->curline;
-               v = u + (image_size >> 1);
-       } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) {
-               v = frame->data + image_size + ((frame->curline * (frame->width)) >> 2);
-               u = v + (image_size >> 2);
-       }
-
-       if (frame->curline == 0)
-               usbvision_adjust_compression(usbvision);
-
-       if (scratch_len(usbvision) < USBVISION_STRIP_HEADER_LEN)
-               return parse_state_out;
-
-       /* get strip header without changing the scratch_read_ptr */
-       scratch_set_extra_ptr(usbvision, &strip_ptr, 0);
-       scratch_get_extra(usbvision, &strip_header[0], &strip_ptr,
-                               USBVISION_STRIP_HEADER_LEN);
-
-       if (strip_header[0] != USBVISION_STRIP_MAGIC) {
-               /* wrong strip magic */
-               usbvision->strip_magic_errors++;
-               return parse_state_next_frame;
-       }
-
-       if (frame->curline != (int)strip_header[2]) {
-               /* line number mismatch error */
-               usbvision->strip_line_number_errors++;
-       }
-
-       strip_len = 2 * (unsigned int)strip_header[1];
-       if (strip_len > USBVISION_STRIP_LEN_MAX) {
-               /* strip overrun */
-               /* I think this never happens */
-               usbvision_request_intra(usbvision);
-       }
-
-       if (scratch_len(usbvision) < strip_len) {
-               /* there is not enough data for the strip */
-               return parse_state_out;
-       }
-
-       if (usbvision->intra_frame_buffer) {
-               Y = usbvision->intra_frame_buffer + frame->frmwidth * frame->curline;
-               U = usbvision->intra_frame_buffer + image_size + (frame->frmwidth / 2) * (frame->curline / 2);
-               V = usbvision->intra_frame_buffer + image_size / 4 * 5 + (frame->frmwidth / 2) * (frame->curline / 2);
-       } else {
-               return parse_state_next_frame;
-       }
-
-       clipmask_index = frame->curline * MAX_FRAME_WIDTH;
-
-       scratch_get(usbvision, strip_data, strip_len);
-
-       idx_end = frame->frmwidth;
-       block_type_pos = USBVISION_STRIP_HEADER_LEN;
-       startblock_pos = block_type_pos + (idx_end - 1) / 96 + (idx_end / 2 - 1) / 96 + 2;
-       block_pos = startblock_pos;
-
-       usbvision->block_pos = block_pos;
-
-       usbvision_decompress(usbvision, strip_data, Y, &block_pos, &block_type_pos, idx_end);
-       if (strip_len > usbvision->max_strip_len)
-               usbvision->max_strip_len = strip_len;
-
-       if (frame->curline % 2)
-               usbvision_decompress(usbvision, strip_data, V, &block_pos, &block_type_pos, idx_end / 2);
-       else
-               usbvision_decompress(usbvision, strip_data, U, &block_pos, &block_type_pos, idx_end / 2);
-
-       if (block_pos > usbvision->comprblock_pos)
-               usbvision->comprblock_pos = block_pos;
-       if (block_pos > strip_len)
-               usbvision->strip_len_errors++;
-
-       for (idx = 0; idx < idx_end; idx++) {
-               if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
-                       *f++ = Y[idx];
-                       *f++ = idx & 0x01 ? U[idx / 2] : V[idx / 2];
-               } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YUV422P) {
-                       *f++ = Y[idx];
-                       if (idx & 0x01)
-                               *u++ = U[idx >> 1];
-                       else
-                               *v++ = V[idx >> 1];
-               } else if (frame->v4l2_format.format == V4L2_PIX_FMT_YVU420) {
-                       *f++ = Y[idx];
-                       if (!((idx & 0x01) | (frame->curline & 0x01))) {
-                               /* only need do this for 1 in 4 pixels */
-                               /* intraframe buffer is YUV420 format */
-                               *u++ = U[idx >> 1];
-                               *v++ = V[idx >> 1];
-                       }
-               } else {
-                       YUV_TO_RGB_BY_THE_BOOK(Y[idx], U[idx / 2], V[idx / 2], rv, gv, bv);
-                       switch (frame->v4l2_format.format) {
-                       case V4L2_PIX_FMT_GREY:
-                               *f++ = Y[idx];
-                               break;
-                       case V4L2_PIX_FMT_RGB555:
-                               *f++ = (0x1F & rv) |
-                                       (0xE0 & (gv << 5));
-                               *f++ = (0x03 & (gv >> 3)) |
-                                       (0x7C & (bv << 2));
-                               break;
-                       case V4L2_PIX_FMT_RGB565:
-                               *f++ = (0x1F & rv) |
-                                       (0xE0 & (gv << 5));
-                               *f++ = (0x07 & (gv >> 3)) |
-                                       (0xF8 & bv);
-                               break;
-                       case V4L2_PIX_FMT_RGB24:
-                               *f++ = rv;
-                               *f++ = gv;
-                               *f++ = bv;
-                               break;
-                       case V4L2_PIX_FMT_RGB32:
-                               *f++ = rv;
-                               *f++ = gv;
-                               *f++ = bv;
-                               f++;
-                               break;
-                       }
-               }
-               clipmask_index++;
-       }
-       /* Deal with non-integer no. of bytes for YUV420P */
-       if (frame->v4l2_format.format != V4L2_PIX_FMT_YVU420)
-               *pcopylen += frame->v4l2_linesize;
-       else
-               *pcopylen += frame->curline & 0x01 ? frame->v4l2_linesize : frame->v4l2_linesize << 1;
-
-       frame->curline += 1;
-
-       if (frame->curline >= frame->frmheight)
-               return parse_state_next_frame;
-       return parse_state_continue;
-
-}
-
-
-/*
- * usbvision_parse_lines_420()
- *
- * Parse two lines from the scratch buffer, put
- * decoded RGB value into the current frame buffer and add the written
- * number of bytes (RGB) to the *pcopylen.
- *
- */
-static enum parse_state usbvision_parse_lines_420(struct usb_usbvision *usbvision,
-                                          long *pcopylen)
-{
-       struct usbvision_frame *frame;
-       unsigned char *f_even = NULL, *f_odd = NULL;
-       unsigned int pixel_per_line, block;
-       int pixel, block_split;
-       int y_ptr, u_ptr, v_ptr, y_odd_offset;
-       const int y_block_size = 128;
-       const int uv_block_size = 64;
-       const int sub_block_size = 32;
-       const int y_step[] = { 0, 0, 0, 2 }, y_step_size = 4;
-       const int uv_step[] = { 0, 0, 0, 4 }, uv_step_size = 4;
-       unsigned char y[2], u, v;       /* YUV components */
-       int y_, u_, v_, vb, uvg, ur;
-       int r_, g_, b_;                 /* RGB components */
-       unsigned char g;
-       int clipmask_even_index, clipmask_odd_index, bytes_per_pixel;
-       int clipmask_add, stretch_bytes;
-
-       frame  = usbvision->cur_frame;
-       f_even = frame->data + (frame->v4l2_linesize * frame->curline);
-       f_odd  = f_even + frame->v4l2_linesize * usbvision->stretch_height;
-
-       /* Make sure there's enough data for the entire line */
-       /* In this mode usbvision transfer 3 bytes for every 2 pixels */
-       /* I need two lines to decode the color */
-       bytes_per_pixel = frame->v4l2_format.bytes_per_pixel;
-       stretch_bytes = (usbvision->stretch_width - 1) * bytes_per_pixel;
-       clipmask_even_index = frame->curline * MAX_FRAME_WIDTH;
-       clipmask_odd_index  = clipmask_even_index + MAX_FRAME_WIDTH;
-       clipmask_add = usbvision->stretch_width;
-       pixel_per_line = frame->isoc_header.frame_width;
-
-       if (scratch_len(usbvision) < (int)pixel_per_line * 3) {
-               /* printk(KERN_DEBUG "out of data, need %d\n", len); */
-               return parse_state_out;
-       }
-
-       if ((frame->curline + 1) >= frame->frmheight)
-               return parse_state_next_frame;
-
-       block_split = (pixel_per_line%y_block_size) ? 1 : 0;    /* are some blocks splitted into different lines? */
-
-       y_odd_offset = (pixel_per_line / y_block_size) * (y_block_size + uv_block_size)
-                       + block_split * uv_block_size;
-
-       scratch_set_extra_ptr(usbvision, &y_ptr, y_odd_offset);
-       scratch_set_extra_ptr(usbvision, &u_ptr, y_block_size);
-       scratch_set_extra_ptr(usbvision, &v_ptr, y_odd_offset
-                       + (4 - block_split) * sub_block_size);
-
-       for (block = 0; block < (pixel_per_line / sub_block_size); block++) {
-               for (pixel = 0; pixel < sub_block_size; pixel += 2) {
-                       scratch_get(usbvision, &y[0], 2);
-                       scratch_get_extra(usbvision, &u, &u_ptr, 1);
-                       scratch_get_extra(usbvision, &v, &v_ptr, 1);
-
-                       /* I don't use the YUV_TO_RGB macro for better performance */
-                       v_ = v - 128;
-                       u_ = u - 128;
-                       vb = 132252 * v_;
-                       uvg = -53281 * u_ - 25625 * v_;
-                       ur = 104595 * u_;
-
-                       if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
-                               *f_even++ = y[0];
-                               *f_even++ = v;
-                       } else {
-                               y_ = 76284 * (y[0] - 16);
-
-                               b_ = (y_ + vb) >> 16;
-                               g_ = (y_ + uvg) >> 16;
-                               r_ = (y_ + ur) >> 16;
-
-                               switch (frame->v4l2_format.format) {
-                               case V4L2_PIX_FMT_RGB565:
-                                       g = LIMIT_RGB(g_);
-                                       *f_even++ =
-                                               (0x1F & LIMIT_RGB(r_)) |
-                                               (0xE0 & (g << 5));
-                                       *f_even++ =
-                                               (0x07 & (g >> 3)) |
-                                               (0xF8 &  LIMIT_RGB(b_));
-                                       break;
-                               case V4L2_PIX_FMT_RGB24:
-                                       *f_even++ = LIMIT_RGB(r_);
-                                       *f_even++ = LIMIT_RGB(g_);
-                                       *f_even++ = LIMIT_RGB(b_);
-                                       break;
-                               case V4L2_PIX_FMT_RGB32:
-                                       *f_even++ = LIMIT_RGB(r_);
-                                       *f_even++ = LIMIT_RGB(g_);
-                                       *f_even++ = LIMIT_RGB(b_);
-                                       f_even++;
-                                       break;
-                               case V4L2_PIX_FMT_RGB555:
-                                       g = LIMIT_RGB(g_);
-                                       *f_even++ = (0x1F & LIMIT_RGB(r_)) |
-                                               (0xE0 & (g << 5));
-                                       *f_even++ = (0x03 & (g >> 3)) |
-                                               (0x7C & (LIMIT_RGB(b_) << 2));
-                                       break;
-                               }
-                       }
-                       clipmask_even_index += clipmask_add;
-                       f_even += stretch_bytes;
-
-                       if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
-                               *f_even++ = y[1];
-                               *f_even++ = u;
-                       } else {
-                               y_ = 76284 * (y[1] - 16);
-
-                               b_ = (y_ + vb) >> 16;
-                               g_ = (y_ + uvg) >> 16;
-                               r_ = (y_ + ur) >> 16;
-
-                               switch (frame->v4l2_format.format) {
-                               case V4L2_PIX_FMT_RGB565:
-                                       g = LIMIT_RGB(g_);
-                                       *f_even++ =
-                                               (0x1F & LIMIT_RGB(r_)) |
-                                               (0xE0 & (g << 5));
-                                       *f_even++ =
-                                               (0x07 & (g >> 3)) |
-                                               (0xF8 &  LIMIT_RGB(b_));
-                                       break;
-                               case V4L2_PIX_FMT_RGB24:
-                                       *f_even++ = LIMIT_RGB(r_);
-                                       *f_even++ = LIMIT_RGB(g_);
-                                       *f_even++ = LIMIT_RGB(b_);
-                                       break;
-                               case V4L2_PIX_FMT_RGB32:
-                                       *f_even++ = LIMIT_RGB(r_);
-                                       *f_even++ = LIMIT_RGB(g_);
-                                       *f_even++ = LIMIT_RGB(b_);
-                                       f_even++;
-                                       break;
-                               case V4L2_PIX_FMT_RGB555:
-                                       g = LIMIT_RGB(g_);
-                                       *f_even++ = (0x1F & LIMIT_RGB(r_)) |
-                                               (0xE0 & (g << 5));
-                                       *f_even++ = (0x03 & (g >> 3)) |
-                                               (0x7C & (LIMIT_RGB(b_) << 2));
-                                       break;
-                               }
-                       }
-                       clipmask_even_index += clipmask_add;
-                       f_even += stretch_bytes;
-
-                       scratch_get_extra(usbvision, &y[0], &y_ptr, 2);
-
-                       if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
-                               *f_odd++ = y[0];
-                               *f_odd++ = v;
-                       } else {
-                               y_ = 76284 * (y[0] - 16);
-
-                               b_ = (y_ + vb) >> 16;
-                               g_ = (y_ + uvg) >> 16;
-                               r_ = (y_ + ur) >> 16;
-
-                               switch (frame->v4l2_format.format) {
-                               case V4L2_PIX_FMT_RGB565:
-                                       g = LIMIT_RGB(g_);
-                                       *f_odd++ =
-                                               (0x1F & LIMIT_RGB(r_)) |
-                                               (0xE0 & (g << 5));
-                                       *f_odd++ =
-                                               (0x07 & (g >> 3)) |
-                                               (0xF8 &  LIMIT_RGB(b_));
-                                       break;
-                               case V4L2_PIX_FMT_RGB24:
-                                       *f_odd++ = LIMIT_RGB(r_);
-                                       *f_odd++ = LIMIT_RGB(g_);
-                                       *f_odd++ = LIMIT_RGB(b_);
-                                       break;
-                               case V4L2_PIX_FMT_RGB32:
-                                       *f_odd++ = LIMIT_RGB(r_);
-                                       *f_odd++ = LIMIT_RGB(g_);
-                                       *f_odd++ = LIMIT_RGB(b_);
-                                       f_odd++;
-                                       break;
-                               case V4L2_PIX_FMT_RGB555:
-                                       g = LIMIT_RGB(g_);
-                                       *f_odd++ = (0x1F & LIMIT_RGB(r_)) |
-                                               (0xE0 & (g << 5));
-                                       *f_odd++ = (0x03 & (g >> 3)) |
-                                               (0x7C & (LIMIT_RGB(b_) << 2));
-                                       break;
-                               }
-                       }
-                       clipmask_odd_index += clipmask_add;
-                       f_odd += stretch_bytes;
-
-                       if (frame->v4l2_format.format == V4L2_PIX_FMT_YUYV) {
-                               *f_odd++ = y[1];
-                               *f_odd++ = u;
-                       } else {
-                               y_ = 76284 * (y[1] - 16);
-
-                               b_ = (y_ + vb) >> 16;
-                               g_ = (y_ + uvg) >> 16;
-                               r_ = (y_ + ur) >> 16;
-
-                               switch (frame->v4l2_format.format) {
-                               case V4L2_PIX_FMT_RGB565:
-                                       g = LIMIT_RGB(g_);
-                                       *f_odd++ =
-                                               (0x1F & LIMIT_RGB(r_)) |
-                                               (0xE0 & (g << 5));
-                                       *f_odd++ =
-                                               (0x07 & (g >> 3)) |
-                                               (0xF8 &  LIMIT_RGB(b_));
-                                       break;
-                               case V4L2_PIX_FMT_RGB24:
-                                       *f_odd++ = LIMIT_RGB(r_);
-                                       *f_odd++ = LIMIT_RGB(g_);
-                                       *f_odd++ = LIMIT_RGB(b_);
-                                       break;
-                               case V4L2_PIX_FMT_RGB32:
-                                       *f_odd++ = LIMIT_RGB(r_);
-                                       *f_odd++ = LIMIT_RGB(g_);
-                                       *f_odd++ = LIMIT_RGB(b_);
-                                       f_odd++;
-                                       break;
-                               case V4L2_PIX_FMT_RGB555:
-                                       g = LIMIT_RGB(g_);
-                                       *f_odd++ = (0x1F & LIMIT_RGB(r_)) |
-                                               (0xE0 & (g << 5));
-                                       *f_odd++ = (0x03 & (g >> 3)) |
-                                               (0x7C & (LIMIT_RGB(b_) << 2));
-                                       break;
-                               }
-                       }
-                       clipmask_odd_index += clipmask_add;
-                       f_odd += stretch_bytes;
-               }
-
-               scratch_rm_old(usbvision, y_step[block % y_step_size] * sub_block_size);
-               scratch_inc_extra_ptr(&y_ptr, y_step[(block + 2 * block_split) % y_step_size]
-                               * sub_block_size);
-               scratch_inc_extra_ptr(&u_ptr, uv_step[block % uv_step_size]
-                               * sub_block_size);
-               scratch_inc_extra_ptr(&v_ptr, uv_step[(block + 2 * block_split) % uv_step_size]
-                               * sub_block_size);
-       }
-
-       scratch_rm_old(usbvision, pixel_per_line * 3 / 2
-                       + block_split * sub_block_size);
-
-       frame->curline += 2 * usbvision->stretch_height;
-       *pcopylen += frame->v4l2_linesize * 2 * usbvision->stretch_height;
-
-       if (frame->curline >= frame->frmheight)
-               return parse_state_next_frame;
-       return parse_state_continue;
-}
-
-/*
- * usbvision_parse_data()
- *
- * Generic routine to parse the scratch buffer. It employs either
- * usbvision_find_header() or usbvision_parse_lines() to do most
- * of work.
- *
- */
-static void usbvision_parse_data(struct usb_usbvision *usbvision)
-{
-       struct usbvision_frame *frame;
-       enum parse_state newstate;
-       long copylen = 0;
-       unsigned long lock_flags;
-
-       frame = usbvision->cur_frame;
-
-       PDEBUG(DBG_PARSE, "parsing len=%d\n", scratch_len(usbvision));
-
-       while (1) {
-               newstate = parse_state_out;
-               if (scratch_len(usbvision)) {
-                       if (frame->scanstate == scan_state_scanning) {
-                               newstate = usbvision_find_header(usbvision);
-                       } else if (frame->scanstate == scan_state_lines) {
-                               if (usbvision->isoc_mode == ISOC_MODE_YUV420)
-                                       newstate = usbvision_parse_lines_420(usbvision, &copylen);
-                               else if (usbvision->isoc_mode == ISOC_MODE_YUV422)
-                                       newstate = usbvision_parse_lines_422(usbvision, &copylen);
-                               else if (usbvision->isoc_mode == ISOC_MODE_COMPRESS)
-                                       newstate = usbvision_parse_compress(usbvision, &copylen);
-                       }
-               }
-               if (newstate == parse_state_continue)
-                       continue;
-               if ((newstate == parse_state_next_frame) || (newstate == parse_state_out))
-                       break;
-               return; /* parse_state_end_parse */
-       }
-
-       if (newstate == parse_state_next_frame) {
-               frame->grabstate = frame_state_done;
-               do_gettimeofday(&(frame->timestamp));
-               frame->sequence = usbvision->frame_num;
-
-               spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
-               list_move_tail(&(frame->frame), &usbvision->outqueue);
-               usbvision->cur_frame = NULL;
-               spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
-
-               usbvision->frame_num++;
-
-               /* This will cause the process to request another frame. */
-               if (waitqueue_active(&usbvision->wait_frame)) {
-                       PDEBUG(DBG_PARSE, "Wake up !");
-                       wake_up_interruptible(&usbvision->wait_frame);
-               }
-       } else {
-               frame->grabstate = frame_state_grabbing;
-       }
-
-       /* Update the frame's uncompressed length. */
-       frame->scanlength += copylen;
-}
-
-
-/*
- * Make all of the blocks of data contiguous
- */
-static int usbvision_compress_isochronous(struct usb_usbvision *usbvision,
-                                         struct urb *urb)
-{
-       unsigned char *packet_data;
-       int i, totlen = 0;
-
-       for (i = 0; i < urb->number_of_packets; i++) {
-               int packet_len = urb->iso_frame_desc[i].actual_length;
-               int packet_stat = urb->iso_frame_desc[i].status;
-
-               packet_data = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-
-               /* Detect and ignore errored packets */
-               if (packet_stat) {      /* packet_stat != 0 ????????????? */
-                       PDEBUG(DBG_ISOC, "data error: [%d] len=%d, status=%X", i, packet_len, packet_stat);
-                       usbvision->isoc_err_count++;
-                       continue;
-               }
-
-               /* Detect and ignore empty packets */
-               if (packet_len < 0) {
-                       PDEBUG(DBG_ISOC, "error packet [%d]", i);
-                       usbvision->isoc_skip_count++;
-                       continue;
-               } else if (packet_len == 0) {   /* Frame end ????? */
-                       PDEBUG(DBG_ISOC, "null packet [%d]", i);
-                       usbvision->isocstate = isoc_state_no_frame;
-                       usbvision->isoc_skip_count++;
-                       continue;
-               } else if (packet_len > usbvision->isoc_packet_size) {
-                       PDEBUG(DBG_ISOC, "packet[%d] > isoc_packet_size", i);
-                       usbvision->isoc_skip_count++;
-                       continue;
-               }
-
-               PDEBUG(DBG_ISOC, "packet ok [%d] len=%d", i, packet_len);
-
-               if (usbvision->isocstate == isoc_state_no_frame) { /* new frame begins */
-                       usbvision->isocstate = isoc_state_in_frame;
-                       scratch_mark_header(usbvision);
-                       usbvision_measure_bandwidth(usbvision);
-                       PDEBUG(DBG_ISOC, "packet with header");
-               }
-
-               /*
-                * If usbvision continues to feed us with data but there is no
-                * consumption (if, for example, V4L client fell asleep) we
-                * may overflow the buffer. We have to move old data over to
-                * free room for new data. This is bad for old data. If we
-                * just drop new data then it's bad for new data... choose
-                * your favorite evil here.
-                */
-               if (scratch_free(usbvision) < packet_len) {
-                       usbvision->scratch_ovf_count++;
-                       PDEBUG(DBG_ISOC, "scratch buf overflow! scr_len: %d, n: %d",
-                              scratch_len(usbvision), packet_len);
-                       scratch_rm_old(usbvision, packet_len - scratch_free(usbvision));
-               }
-
-               /* Now we know that there is enough room in scratch buffer */
-               scratch_put(usbvision, packet_data, packet_len);
-               totlen += packet_len;
-               usbvision->isoc_data_count += packet_len;
-               usbvision->isoc_packet_count++;
-       }
-#if ENABLE_HEXDUMP
-       if (totlen > 0) {
-               static int foo;
-
-               if (foo < 1) {
-                       printk(KERN_DEBUG "+%d.\n", usbvision->scratchlen);
-                       usbvision_hexdump(data0, (totlen > 64) ? 64 : totlen);
-                       ++foo;
-               }
-       }
-#endif
-       return totlen;
-}
-
-static void usbvision_isoc_irq(struct urb *urb)
-{
-       int err_code = 0;
-       int len;
-       struct usb_usbvision *usbvision = urb->context;
-       int i;
-       unsigned long start_time = jiffies;
-       struct usbvision_frame **f;
-
-       /* We don't want to do anything if we are about to be removed! */
-       if (!USBVISION_IS_OPERATIONAL(usbvision))
-               return;
-
-       /* any urb with wrong status is ignored without acknowledgement */
-       if (urb->status == -ENOENT)
-               return;
-
-       f = &usbvision->cur_frame;
-
-       /* Manage streaming interruption */
-       if (usbvision->streaming == stream_interrupt) {
-               usbvision->streaming = stream_idle;
-               if ((*f)) {
-                       (*f)->grabstate = frame_state_ready;
-                       (*f)->scanstate = scan_state_scanning;
-               }
-               PDEBUG(DBG_IRQ, "stream interrupted");
-               wake_up_interruptible(&usbvision->wait_stream);
-       }
-
-       /* Copy the data received into our scratch buffer */
-       len = usbvision_compress_isochronous(usbvision, urb);
-
-       usbvision->isoc_urb_count++;
-       usbvision->urb_length = len;
-
-       if (usbvision->streaming == stream_on) {
-               /* If we collected enough data let's parse! */
-               if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH &&
-                   !list_empty(&(usbvision->inqueue))) {
-                       if (!(*f)) {
-                               (*f) = list_entry(usbvision->inqueue.next,
-                                                 struct usbvision_frame,
-                                                 frame);
-                       }
-                       usbvision_parse_data(usbvision);
-               } else {
-                       /* If we don't have a frame
-                         we're current working on, complain */
-                       PDEBUG(DBG_IRQ,
-                              "received data, but no one needs it");
-                       scratch_reset(usbvision);
-               }
-       } else {
-               PDEBUG(DBG_IRQ, "received data, but no one needs it");
-               scratch_reset(usbvision);
-       }
-
-       usbvision->time_in_irq += jiffies - start_time;
-
-       for (i = 0; i < USBVISION_URB_FRAMES; i++) {
-               urb->iso_frame_desc[i].status = 0;
-               urb->iso_frame_desc[i].actual_length = 0;
-       }
-
-       urb->status = 0;
-       urb->dev = usbvision->dev;
-       err_code = usb_submit_urb(urb, GFP_ATOMIC);
-
-       if (err_code) {
-               dev_err(&usbvision->dev->dev,
-                       "%s: usb_submit_urb failed: error %d\n",
-                               __func__, err_code);
-       }
-
-       return;
-}
-
-/*************************************/
-/* Low level usbvision access functions */
-/*************************************/
-
-/*
- * usbvision_read_reg()
- *
- * return  < 0 -> Error
- *        >= 0 -> Data
- */
-
-int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg)
-{
-       int err_code = 0;
-       unsigned char buffer[1];
-
-       if (!USBVISION_IS_OPERATIONAL(usbvision))
-               return -1;
-
-       err_code = usb_control_msg(usbvision->dev, usb_rcvctrlpipe(usbvision->dev, 1),
-                               USBVISION_OP_CODE,
-                               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
-                               0, (__u16) reg, buffer, 1, HZ);
-
-       if (err_code < 0) {
-               dev_err(&usbvision->dev->dev,
-                       "%s: failed: error %d\n", __func__, err_code);
-               return err_code;
-       }
-       return buffer[0];
-}
-
-/*
- * usbvision_write_reg()
- *
- * return 1 -> Reg written
- *        0 -> usbvision is not yet ready
- *       -1 -> Something went wrong
- */
-
-int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
-                           unsigned char value)
-{
-       int err_code = 0;
-
-       if (!USBVISION_IS_OPERATIONAL(usbvision))
-               return 0;
-
-       err_code = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
-                               USBVISION_OP_CODE,
-                               USB_DIR_OUT | USB_TYPE_VENDOR |
-                               USB_RECIP_ENDPOINT, 0, (__u16) reg, &value, 1, HZ);
-
-       if (err_code < 0) {
-               dev_err(&usbvision->dev->dev,
-                       "%s: failed: error %d\n", __func__, err_code);
-       }
-       return err_code;
-}
-
-
-static void usbvision_ctrl_urb_complete(struct urb *urb)
-{
-       struct usb_usbvision *usbvision = (struct usb_usbvision *)urb->context;
-
-       PDEBUG(DBG_IRQ, "");
-       usbvision->ctrl_urb_busy = 0;
-       if (waitqueue_active(&usbvision->ctrl_urb_wq))
-               wake_up_interruptible(&usbvision->ctrl_urb_wq);
-}
-
-
-static int usbvision_write_reg_irq(struct usb_usbvision *usbvision, int address,
-                               unsigned char *data, int len)
-{
-       int err_code = 0;
-
-       PDEBUG(DBG_IRQ, "");
-       if (len > 8)
-               return -EFAULT;
-       if (usbvision->ctrl_urb_busy)
-               return -EBUSY;
-       usbvision->ctrl_urb_busy = 1;
-
-       usbvision->ctrl_urb_setup.bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
-       usbvision->ctrl_urb_setup.bRequest     = USBVISION_OP_CODE;
-       usbvision->ctrl_urb_setup.wValue       = 0;
-       usbvision->ctrl_urb_setup.wIndex       = cpu_to_le16(address);
-       usbvision->ctrl_urb_setup.wLength      = cpu_to_le16(len);
-       usb_fill_control_urb(usbvision->ctrl_urb, usbvision->dev,
-                                                       usb_sndctrlpipe(usbvision->dev, 1),
-                                                       (unsigned char *)&usbvision->ctrl_urb_setup,
-                                                       (void *)usbvision->ctrl_urb_buffer, len,
-                                                       usbvision_ctrl_urb_complete,
-                                                       (void *)usbvision);
-
-       memcpy(usbvision->ctrl_urb_buffer, data, len);
-
-       err_code = usb_submit_urb(usbvision->ctrl_urb, GFP_ATOMIC);
-       if (err_code < 0) {
-               /* error in usb_submit_urb() */
-               usbvision->ctrl_urb_busy = 0;
-       }
-       PDEBUG(DBG_IRQ, "submit %d byte: error %d", len, err_code);
-       return err_code;
-}
-
-
-static int usbvision_init_compression(struct usb_usbvision *usbvision)
-{
-       int err_code = 0;
-
-       usbvision->last_isoc_frame_num = -1;
-       usbvision->isoc_data_count = 0;
-       usbvision->isoc_packet_count = 0;
-       usbvision->isoc_skip_count = 0;
-       usbvision->compr_level = 50;
-       usbvision->last_compr_level = -1;
-       usbvision->isoc_urb_count = 0;
-       usbvision->request_intra = 1;
-       usbvision->isoc_measure_bandwidth_count = 0;
-
-       return err_code;
-}
-
-/* this function measures the used bandwidth since last call
- * return:    0 : no error
- * sets used_bandwidth to 1-100 : 1-100% of full bandwidth resp. to isoc_packet_size
- */
-static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision)
-{
-       int err_code = 0;
-
-       if (usbvision->isoc_measure_bandwidth_count < 2) { /* this gives an average bandwidth of 3 frames */
-               usbvision->isoc_measure_bandwidth_count++;
-               return err_code;
-       }
-       if ((usbvision->isoc_packet_size > 0) && (usbvision->isoc_packet_count > 0)) {
-               usbvision->used_bandwidth = usbvision->isoc_data_count /
-                                       (usbvision->isoc_packet_count + usbvision->isoc_skip_count) *
-                                       100 / usbvision->isoc_packet_size;
-       }
-       usbvision->isoc_measure_bandwidth_count = 0;
-       usbvision->isoc_data_count = 0;
-       usbvision->isoc_packet_count = 0;
-       usbvision->isoc_skip_count = 0;
-       return err_code;
-}
-
-static int usbvision_adjust_compression(struct usb_usbvision *usbvision)
-{
-       int err_code = 0;
-       unsigned char buffer[6];
-
-       PDEBUG(DBG_IRQ, "");
-       if ((adjust_compression) && (usbvision->used_bandwidth > 0)) {
-               usbvision->compr_level += (usbvision->used_bandwidth - 90) / 2;
-               RESTRICT_TO_RANGE(usbvision->compr_level, 0, 100);
-               if (usbvision->compr_level != usbvision->last_compr_level) {
-                       int distortion;
-
-                       if (usbvision->bridge_type == BRIDGE_NT1004 || usbvision->bridge_type == BRIDGE_NT1005) {
-                               buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100);     /* PCM Threshold 1 */
-                               buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100);      /* PCM Threshold 2 */
-                               distortion = 7 + 248 * usbvision->compr_level / 100;
-                               buffer[2] = (unsigned char)(distortion & 0xFF);                         /* Average distortion Threshold (inter) */
-                               buffer[3] = (unsigned char)(distortion & 0xFF);                         /* Average distortion Threshold (intra) */
-                               distortion = 1 + 42 * usbvision->compr_level / 100;
-                               buffer[4] = (unsigned char)(distortion & 0xFF);                         /* Maximum distortion Threshold (inter) */
-                               buffer[5] = (unsigned char)(distortion & 0xFF);                         /* Maximum distortion Threshold (intra) */
-                       } else { /* BRIDGE_NT1003 */
-                               buffer[0] = (unsigned char)(4 + 16 * usbvision->compr_level / 100);     /* PCM threshold 1 */
-                               buffer[1] = (unsigned char)(4 + 8 * usbvision->compr_level / 100);      /* PCM threshold 2 */
-                               distortion = 2 + 253 * usbvision->compr_level / 100;
-                               buffer[2] = (unsigned char)(distortion & 0xFF);                         /* distortion threshold bit0-7 */
-                               buffer[3] = 0;  /* (unsigned char)((distortion >> 8) & 0x0F);           distortion threshold bit 8-11 */
-                               distortion = 0 + 43 * usbvision->compr_level / 100;
-                               buffer[4] = (unsigned char)(distortion & 0xFF);                         /* maximum distortion bit0-7 */
-                               buffer[5] = 0; /* (unsigned char)((distortion >> 8) & 0x01);            maximum distortion bit 8 */
-                       }
-                       err_code = usbvision_write_reg_irq(usbvision, USBVISION_PCM_THR1, buffer, 6);
-                       if (err_code == 0) {
-                               PDEBUG(DBG_IRQ, "new compr params %#02x %#02x %#02x %#02x %#02x %#02x", buffer[0],
-                                                               buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
-                               usbvision->last_compr_level = usbvision->compr_level;
-                       }
-               }
-       }
-       return err_code;
-}
-
-static int usbvision_request_intra(struct usb_usbvision *usbvision)
-{
-       int err_code = 0;
-       unsigned char buffer[1];
-
-       PDEBUG(DBG_IRQ, "");
-       usbvision->request_intra = 1;
-       buffer[0] = 1;
-       usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
-       return err_code;
-}
-
-static int usbvision_unrequest_intra(struct usb_usbvision *usbvision)
-{
-       int err_code = 0;
-       unsigned char buffer[1];
-
-       PDEBUG(DBG_IRQ, "");
-       usbvision->request_intra = 0;
-       buffer[0] = 0;
-       usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
-       return err_code;
-}
-
-/*******************************
- * usbvision utility functions
- *******************************/
-
-int usbvision_power_off(struct usb_usbvision *usbvision)
-{
-       int err_code = 0;
-
-       PDEBUG(DBG_FUNC, "");
-
-       err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN);
-       if (err_code == 1)
-               usbvision->power = 0;
-       PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code != 1) ? "ERROR" : "power is off", err_code);
-       return err_code;
-}
-
-/* configure webcam image sensor using the serial port */
-static int usbvision_init_webcam(struct usb_usbvision *usbvision)
-{
-       int rc;
-       int i;
-       static char init_values[38][3] = {
-               { 0x04, 0x12, 0x08 }, { 0x05, 0xff, 0xc8 }, { 0x06, 0x18, 0x07 }, { 0x07, 0x90, 0x00 },
-               { 0x09, 0x00, 0x00 }, { 0x0a, 0x00, 0x00 }, { 0x0b, 0x08, 0x00 }, { 0x0d, 0xcc, 0xcc },
-               { 0x0e, 0x13, 0x14 }, { 0x10, 0x9b, 0x83 }, { 0x11, 0x5a, 0x3f }, { 0x12, 0xe4, 0x73 },
-               { 0x13, 0x88, 0x84 }, { 0x14, 0x89, 0x80 }, { 0x15, 0x00, 0x20 }, { 0x16, 0x00, 0x00 },
-               { 0x17, 0xff, 0xa0 }, { 0x18, 0x6b, 0x20 }, { 0x19, 0x22, 0x40 }, { 0x1a, 0x10, 0x07 },
-               { 0x1b, 0x00, 0x47 }, { 0x1c, 0x03, 0xe0 }, { 0x1d, 0x00, 0x00 }, { 0x1e, 0x00, 0x00 },
-               { 0x1f, 0x00, 0x00 }, { 0x20, 0x00, 0x00 }, { 0x21, 0x00, 0x00 }, { 0x22, 0x00, 0x00 },
-               { 0x23, 0x00, 0x00 }, { 0x24, 0x00, 0x00 }, { 0x25, 0x00, 0x00 }, { 0x26, 0x00, 0x00 },
-               { 0x27, 0x00, 0x00 }, { 0x28, 0x00, 0x00 }, { 0x29, 0x00, 0x00 }, { 0x08, 0x80, 0x60 },
-               { 0x0f, 0x2d, 0x24 }, { 0x0c, 0x80, 0x80 }
-       };
-       char value[3];
-
-       /* the only difference between PAL and NTSC init_values */
-       if (usbvision_device_data[usbvision->dev_model].video_norm == V4L2_STD_NTSC)
-               init_values[4][1] = 0x34;
-
-       for (i = 0; i < sizeof(init_values) / 3; i++) {
-               usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT);
-               memcpy(value, init_values[i], 3);
-               rc = usb_control_msg(usbvision->dev,
-                                    usb_sndctrlpipe(usbvision->dev, 1),
-                                    USBVISION_OP_CODE,
-                                    USB_DIR_OUT | USB_TYPE_VENDOR |
-                                    USB_RECIP_ENDPOINT, 0,
-                                    (__u16) USBVISION_SER_DAT1, value,
-                                    3, HZ);
-               if (rc < 0)
-                       return rc;
-               usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SIO);
-               /* write 3 bytes to the serial port using SIO mode */
-               usbvision_write_reg(usbvision, USBVISION_SER_CONT, 3 | 0x10);
-               usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, 0);
-               usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT);
-               usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_IO_2);
-               usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_CLK_OUT);
-               usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_DAT_IO);
-               usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_SER_MODE_SOFT | USBVISION_CLK_OUT | USBVISION_DAT_IO);
-       }
-
-       return 0;
-}
-
-/*
- * usbvision_set_video_format()
- *
- */
-static int usbvision_set_video_format(struct usb_usbvision *usbvision, int format)
-{
-       static const char proc[] = "usbvision_set_video_format";
-       int rc;
-       unsigned char value[2];
-
-       if (!USBVISION_IS_OPERATIONAL(usbvision))
-               return 0;
-
-       PDEBUG(DBG_FUNC, "isoc_mode %#02x", format);
-
-       if ((format != ISOC_MODE_YUV422)
-           && (format != ISOC_MODE_YUV420)
-           && (format != ISOC_MODE_COMPRESS)) {
-               printk(KERN_ERR "usbvision: unknown video format %02x, using default YUV420",
-                      format);
-               format = ISOC_MODE_YUV420;
-       }
-       value[0] = 0x0A;  /* TODO: See the effect of the filter */
-       value[1] = format; /* Sets the VO_MODE register which follows FILT_CONT */
-       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
-                            USBVISION_OP_CODE,
-                            USB_DIR_OUT | USB_TYPE_VENDOR |
-                            USB_RECIP_ENDPOINT, 0,
-                            (__u16) USBVISION_FILT_CONT, value, 2, HZ);
-
-       if (rc < 0) {
-               printk(KERN_ERR "%s: ERROR=%d. USBVISION stopped - "
-                      "reconnect or reload driver.\n", proc, rc);
-       }
-       usbvision->isoc_mode = format;
-       return rc;
-}
-
-/*
- * usbvision_set_output()
- *
- */
-
-int usbvision_set_output(struct usb_usbvision *usbvision, int width,
-                        int height)
-{
-       int err_code = 0;
-       int usb_width, usb_height;
-       unsigned int frame_rate = 0, frame_drop = 0;
-       unsigned char value[4];
-
-       if (!USBVISION_IS_OPERATIONAL(usbvision))
-               return 0;
-
-       if (width > MAX_USB_WIDTH) {
-               usb_width = width / 2;
-               usbvision->stretch_width = 2;
-       } else {
-               usb_width = width;
-               usbvision->stretch_width = 1;
-       }
-
-       if (height > MAX_USB_HEIGHT) {
-               usb_height = height / 2;
-               usbvision->stretch_height = 2;
-       } else {
-               usb_height = height;
-               usbvision->stretch_height = 1;
-       }
-
-       RESTRICT_TO_RANGE(usb_width, MIN_FRAME_WIDTH, MAX_USB_WIDTH);
-       usb_width &= ~(MIN_FRAME_WIDTH-1);
-       RESTRICT_TO_RANGE(usb_height, MIN_FRAME_HEIGHT, MAX_USB_HEIGHT);
-       usb_height &= ~(1);
-
-       PDEBUG(DBG_FUNC, "usb %dx%d; screen %dx%d; stretch %dx%d",
-                                               usb_width, usb_height, width, height,
-                                               usbvision->stretch_width, usbvision->stretch_height);
-
-       /* I'll not rewrite the same values */
-       if ((usb_width != usbvision->curwidth) || (usb_height != usbvision->curheight)) {
-               value[0] = usb_width & 0xff;            /* LSB */
-               value[1] = (usb_width >> 8) & 0x03;     /* MSB */
-               value[2] = usb_height & 0xff;           /* LSB */
-               value[3] = (usb_height >> 8) & 0x03;    /* MSB */
-
-               err_code = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
-                            USBVISION_OP_CODE,
-                            USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
-                                0, (__u16) USBVISION_LXSIZE_O, value, 4, HZ);
-
-               if (err_code < 0) {
-                       dev_err(&usbvision->dev->dev,
-                               "%s failed: error %d\n", __func__, err_code);
-                       return err_code;
-               }
-               usbvision->curwidth = usbvision->stretch_width * usb_width;
-               usbvision->curheight = usbvision->stretch_height * usb_height;
-       }
-
-       if (usbvision->isoc_mode == ISOC_MODE_YUV422)
-               frame_rate = (usbvision->isoc_packet_size * 1000) / (usb_width * usb_height * 2);
-       else if (usbvision->isoc_mode == ISOC_MODE_YUV420)
-               frame_rate = (usbvision->isoc_packet_size * 1000) / ((usb_width * usb_height * 12) / 8);
-       else
-               frame_rate = FRAMERATE_MAX;
-
-       if (usbvision->tvnorm_id & V4L2_STD_625_50)
-               frame_drop = frame_rate * 32 / 25 - 1;
-       else if (usbvision->tvnorm_id & V4L2_STD_525_60)
-               frame_drop = frame_rate * 32 / 30 - 1;
-
-       RESTRICT_TO_RANGE(frame_drop, FRAMERATE_MIN, FRAMERATE_MAX);
-
-       PDEBUG(DBG_FUNC, "frame_rate %d fps, frame_drop %d", frame_rate, frame_drop);
-
-       frame_drop = FRAMERATE_MAX;     /* We can allow the maximum here, because dropping is controlled */
-
-       if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) {
-               if (usbvision_device_data[usbvision->dev_model].video_norm == V4L2_STD_PAL)
-                       frame_drop = 25;
-               else
-                       frame_drop = 30;
-       }
-
-       /* frame_drop = 7; => frame_phase = 1, 5, 9, 13, 17, 21, 25, 0, 4, 8, ...
-               => frame_skip = 4;
-               => frame_rate = (7 + 1) * 25 / 32 = 200 / 32 = 6.25;
-
-          frame_drop = 9; => frame_phase = 1, 5, 8, 11, 14, 17, 21, 24, 27, 1, 4, 8, ...
-           => frame_skip = 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 4, ...
-               => frame_rate = (9 + 1) * 25 / 32 = 250 / 32 = 7.8125;
-       */
-       err_code = usbvision_write_reg(usbvision, USBVISION_FRM_RATE, frame_drop);
-       return err_code;
-}
-
-
-/*
- * usbvision_frames_alloc
- * allocate the required frames
- */
-int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames)
-{
-       int i;
-
-       /* needs to be page aligned cause the buffers can be mapped individually! */
-       usbvision->max_frame_size = PAGE_ALIGN(usbvision->curwidth *
-                                               usbvision->curheight *
-                                               usbvision->palette.bytes_per_pixel);
-
-       /* Try to do my best to allocate the frames the user want in the remaining memory */
-       usbvision->num_frames = number_of_frames;
-       while (usbvision->num_frames > 0) {
-               usbvision->fbuf_size = usbvision->num_frames * usbvision->max_frame_size;
-               usbvision->fbuf = usbvision_rvmalloc(usbvision->fbuf_size);
-               if (usbvision->fbuf)
-                       break;
-               usbvision->num_frames--;
-       }
-
-       spin_lock_init(&usbvision->queue_lock);
-       init_waitqueue_head(&usbvision->wait_frame);
-       init_waitqueue_head(&usbvision->wait_stream);
-
-       /* Allocate all buffers */
-       for (i = 0; i < usbvision->num_frames; i++) {
-               usbvision->frame[i].index = i;
-               usbvision->frame[i].grabstate = frame_state_unused;
-               usbvision->frame[i].data = usbvision->fbuf +
-                       i * usbvision->max_frame_size;
-               /*
-                * Set default sizes for read operation.
-                */
-               usbvision->stretch_width = 1;
-               usbvision->stretch_height = 1;
-               usbvision->frame[i].width = usbvision->curwidth;
-               usbvision->frame[i].height = usbvision->curheight;
-               usbvision->frame[i].bytes_read = 0;
-       }
-       PDEBUG(DBG_FUNC, "allocated %d frames (%d bytes per frame)",
-                       usbvision->num_frames, usbvision->max_frame_size);
-       return usbvision->num_frames;
-}
-
-/*
- * usbvision_frames_free
- * frees memory allocated for the frames
- */
-void usbvision_frames_free(struct usb_usbvision *usbvision)
-{
-       /* Have to free all that memory */
-       PDEBUG(DBG_FUNC, "free %d frames", usbvision->num_frames);
-
-       if (usbvision->fbuf != NULL) {
-               usbvision_rvfree(usbvision->fbuf, usbvision->fbuf_size);
-               usbvision->fbuf = NULL;
-
-               usbvision->num_frames = 0;
-       }
-}
-/*
- * usbvision_empty_framequeues()
- * prepare queues for incoming and outgoing frames
- */
-void usbvision_empty_framequeues(struct usb_usbvision *usbvision)
-{
-       u32 i;
-
-       INIT_LIST_HEAD(&(usbvision->inqueue));
-       INIT_LIST_HEAD(&(usbvision->outqueue));
-
-       for (i = 0; i < USBVISION_NUMFRAMES; i++) {
-               usbvision->frame[i].grabstate = frame_state_unused;
-               usbvision->frame[i].bytes_read = 0;
-       }
-}
-
-/*
- * usbvision_stream_interrupt()
- * stops streaming
- */
-int usbvision_stream_interrupt(struct usb_usbvision *usbvision)
-{
-       int ret = 0;
-
-       /* stop reading from the device */
-
-       usbvision->streaming = stream_interrupt;
-       ret = wait_event_timeout(usbvision->wait_stream,
-                                (usbvision->streaming == stream_idle),
-                                msecs_to_jiffies(USBVISION_NUMSBUF*USBVISION_URB_FRAMES));
-       return ret;
-}
-
-/*
- * usbvision_set_compress_params()
- *
- */
-
-static int usbvision_set_compress_params(struct usb_usbvision *usbvision)
-{
-       static const char proc[] = "usbvision_set_compresion_params: ";
-       int rc;
-       unsigned char value[6];
-
-       value[0] = 0x0F;    /* Intra-Compression cycle */
-       value[1] = 0x01;    /* Reg.45 one line per strip */
-       value[2] = 0x00;    /* Reg.46 Force intra mode on all new frames */
-       value[3] = 0x00;    /* Reg.47 FORCE_UP <- 0 normal operation (not force) */
-       value[4] = 0xA2;    /* Reg.48 BUF_THR I'm not sure if this does something in not compressed mode. */
-       value[5] = 0x00;    /* Reg.49 DVI_YUV This has nothing to do with compression */
-
-       /* catched values for NT1004 */
-       /* value[0] = 0xFF; Never apply intra mode automatically */
-       /* value[1] = 0xF1; Use full frame height for virtual strip width; One line per strip */
-       /* value[2] = 0x01; Force intra mode on all new frames */
-       /* value[3] = 0x00; Strip size 400 Bytes; do not force up */
-       /* value[4] = 0xA2; */
-       if (!USBVISION_IS_OPERATIONAL(usbvision))
-               return 0;
-
-       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
-                            USBVISION_OP_CODE,
-                            USB_DIR_OUT | USB_TYPE_VENDOR |
-                            USB_RECIP_ENDPOINT, 0,
-                            (__u16) USBVISION_INTRA_CYC, value, 5, HZ);
-
-       if (rc < 0) {
-               printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
-                      "reconnect or reload driver.\n", proc, rc);
-               return rc;
-       }
-
-       if (usbvision->bridge_type == BRIDGE_NT1004) {
-               value[0] =  20; /* PCM Threshold 1 */
-               value[1] =  12; /* PCM Threshold 2 */
-               value[2] = 255; /* Distortion Threshold inter */
-               value[3] = 255; /* Distortion Threshold intra */
-               value[4] =  43; /* Max Distortion inter */
-               value[5] =  43; /* Max Distortion intra */
-       } else {
-               value[0] =  20; /* PCM Threshold 1 */
-               value[1] =  12; /* PCM Threshold 2 */
-               value[2] = 255; /* Distortion Threshold d7-d0 */
-               value[3] =   0; /* Distortion Threshold d11-d8 */
-               value[4] =  43; /* Max Distortion d7-d0 */
-               value[5] =   0; /* Max Distortion d8 */
-       }
-
-       if (!USBVISION_IS_OPERATIONAL(usbvision))
-               return 0;
-
-       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
-                            USBVISION_OP_CODE,
-                            USB_DIR_OUT | USB_TYPE_VENDOR |
-                            USB_RECIP_ENDPOINT, 0,
-                            (__u16) USBVISION_PCM_THR1, value, 6, HZ);
-
-       if (rc < 0) {
-               printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
-                      "reconnect or reload driver.\n", proc, rc);
-       }
-       return rc;
-}
-
-
-/*
- * usbvision_set_input()
- *
- * Set the input (saa711x, ...) size x y and other misc input params
- * I've no idea if this parameters are right
- *
- */
-int usbvision_set_input(struct usb_usbvision *usbvision)
-{
-       static const char proc[] = "usbvision_set_input: ";
-       int rc;
-       unsigned char value[8];
-       unsigned char dvi_yuv_value;
-
-       if (!USBVISION_IS_OPERATIONAL(usbvision))
-               return 0;
-
-       /* Set input format expected from decoder*/
-       if (usbvision_device_data[usbvision->dev_model].vin_reg1_override) {
-               value[0] = usbvision_device_data[usbvision->dev_model].vin_reg1;
-       } else if (usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) {
-               /* SAA7113 uses 8 bit output */
-               value[0] = USBVISION_8_422_SYNC;
-       } else {
-               /* I'm sure only about d2-d0 [010] 16 bit 4:2:2 usin sync pulses
-                * as that is how saa7111 is configured */
-               value[0] = USBVISION_16_422_SYNC;
-               /* | USBVISION_VSNC_POL | USBVISION_VCLK_POL);*/
-       }
-
-       rc = usbvision_write_reg(usbvision, USBVISION_VIN_REG1, value[0]);
-       if (rc < 0) {
-               printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
-                      "reconnect or reload driver.\n", proc, rc);
-               return rc;
-       }
-
-
-       if (usbvision->tvnorm_id & V4L2_STD_PAL) {
-               value[0] = 0xC0;
-               value[1] = 0x02;        /* 0x02C0 -> 704 Input video line length */
-               value[2] = 0x20;
-               value[3] = 0x01;        /* 0x0120 -> 288 Input video n. of lines */
-               value[4] = 0x60;
-               value[5] = 0x00;        /* 0x0060 -> 96 Input video h offset */
-               value[6] = 0x16;
-               value[7] = 0x00;        /* 0x0016 -> 22 Input video v offset */
-       } else if (usbvision->tvnorm_id & V4L2_STD_SECAM) {
-               value[0] = 0xC0;
-               value[1] = 0x02;        /* 0x02C0 -> 704 Input video line length */
-               value[2] = 0x20;
-               value[3] = 0x01;        /* 0x0120 -> 288 Input video n. of lines */
-               value[4] = 0x01;
-               value[5] = 0x00;        /* 0x0001 -> 01 Input video h offset */
-               value[6] = 0x01;
-               value[7] = 0x00;        /* 0x0001 -> 01 Input video v offset */
-       } else {        /* V4L2_STD_NTSC */
-               value[0] = 0xD0;
-               value[1] = 0x02;        /* 0x02D0 -> 720 Input video line length */
-               value[2] = 0xF0;
-               value[3] = 0x00;        /* 0x00F0 -> 240 Input video number of lines */
-               value[4] = 0x50;
-               value[5] = 0x00;        /* 0x0050 -> 80 Input video h offset */
-               value[6] = 0x10;
-               value[7] = 0x00;        /* 0x0010 -> 16 Input video v offset */
-       }
-
-       /* webcam is only 480 pixels wide, both PAL and NTSC version */
-       if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) {
-               value[0] = 0xe0;
-               value[1] = 0x01;        /* 0x01E0 -> 480 Input video line length */
-       }
-
-       if (usbvision_device_data[usbvision->dev_model].x_offset >= 0) {
-               value[4] = usbvision_device_data[usbvision->dev_model].x_offset & 0xff;
-               value[5] = (usbvision_device_data[usbvision->dev_model].x_offset & 0x0300) >> 8;
-       }
-
-       if (adjust_x_offset != -1) {
-               value[4] = adjust_x_offset & 0xff;
-               value[5] = (adjust_x_offset & 0x0300) >> 8;
-       }
-
-       if (usbvision_device_data[usbvision->dev_model].y_offset >= 0) {
-               value[6] = usbvision_device_data[usbvision->dev_model].y_offset & 0xff;
-               value[7] = (usbvision_device_data[usbvision->dev_model].y_offset & 0x0300) >> 8;
-       }
-
-       if (adjust_y_offset != -1) {
-               value[6] = adjust_y_offset & 0xff;
-               value[7] = (adjust_y_offset & 0x0300) >> 8;
-       }
-
-       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
-                            USBVISION_OP_CODE, /* USBVISION specific code */
-                            USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0,
-                            (__u16) USBVISION_LXSIZE_I, value, 8, HZ);
-       if (rc < 0) {
-               printk(KERN_ERR "%sERROR=%d. USBVISION stopped - "
-                      "reconnect or reload driver.\n", proc, rc);
-               return rc;
-       }
-
-
-       dvi_yuv_value = 0x00;   /* U comes after V, Ya comes after U/V, Yb comes after Yb */
-
-       if (usbvision_device_data[usbvision->dev_model].dvi_yuv_override) {
-               dvi_yuv_value = usbvision_device_data[usbvision->dev_model].dvi_yuv;
-       } else if (usbvision_device_data[usbvision->dev_model].codec == CODEC_SAA7113) {
-               /* This changes as the fine sync control changes. Further investigation necessary */
-               dvi_yuv_value = 0x06;
-       }
-
-       return usbvision_write_reg(usbvision, USBVISION_DVI_YUV, dvi_yuv_value);
-}
-
-
-/*
- * usbvision_set_dram_settings()
- *
- * Set the buffer address needed by the usbvision dram to operate
- * This values has been taken with usbsnoop.
- *
- */
-
-static int usbvision_set_dram_settings(struct usb_usbvision *usbvision)
-{
-       int rc;
-       unsigned char value[8];
-
-       if (usbvision->isoc_mode == ISOC_MODE_COMPRESS) {
-               value[0] = 0x42;
-               value[1] = 0x71;
-               value[2] = 0xff;
-               value[3] = 0x00;
-               value[4] = 0x98;
-               value[5] = 0xe0;
-               value[6] = 0x71;
-               value[7] = 0xff;
-               /* UR:  0x0E200-0x3FFFF = 204288 Words (1 Word = 2 Byte) */
-               /* FDL: 0x00000-0x0E099 =  57498 Words */
-               /* VDW: 0x0E3FF-0x3FFFF */
-       } else {
-               value[0] = 0x42;
-               value[1] = 0x00;
-               value[2] = 0xff;
-               value[3] = 0x00;
-               value[4] = 0x00;
-               value[5] = 0x00;
-               value[6] = 0x00;
-               value[7] = 0xff;
-       }
-       /* These are the values of the address of the video buffer,
-        * they have to be loaded into the USBVISION_DRM_PRM1-8
-        *
-        * Start address of video output buffer for read:       drm_prm1-2 -> 0x00000
-        * End address of video output buffer for read:         drm_prm1-3 -> 0x1ffff
-        * Start address of video frame delay buffer:           drm_prm1-4 -> 0x20000
-        *    Only used in compressed mode
-        * End address of video frame delay buffer:             drm_prm1-5-6 -> 0x3ffff
-        *    Only used in compressed mode
-        * Start address of video output buffer for write:      drm_prm1-7 -> 0x00000
-        * End address of video output buffer for write:        drm_prm1-8 -> 0x1ffff
-        */
-
-       if (!USBVISION_IS_OPERATIONAL(usbvision))
-               return 0;
-
-       rc = usb_control_msg(usbvision->dev, usb_sndctrlpipe(usbvision->dev, 1),
-                            USBVISION_OP_CODE, /* USBVISION specific code */
-                            USB_DIR_OUT | USB_TYPE_VENDOR |
-                            USB_RECIP_ENDPOINT, 0,
-                            (__u16) USBVISION_DRM_PRM1, value, 8, HZ);
-
-       if (rc < 0) {
-               dev_err(&usbvision->dev->dev, "%s: ERROR=%d\n", __func__, rc);
-               return rc;
-       }
-
-       /* Restart the video buffer logic */
-       rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, USBVISION_RES_UR |
-                                  USBVISION_RES_FDL | USBVISION_RES_VDW);
-       if (rc < 0)
-               return rc;
-       rc = usbvision_write_reg(usbvision, USBVISION_DRM_CONT, 0x00);
-
-       return rc;
-}
-
-/*
- * ()
- *
- * Power on the device, enables suspend-resume logic
- * &  reset the isoc End-Point
- *
- */
-
-int usbvision_power_on(struct usb_usbvision *usbvision)
-{
-       int err_code = 0;
-
-       PDEBUG(DBG_FUNC, "");
-
-       usbvision_write_reg(usbvision, USBVISION_PWR_REG, USBVISION_SSPND_EN);
-       usbvision_write_reg(usbvision, USBVISION_PWR_REG,
-                       USBVISION_SSPND_EN | USBVISION_RES2);
-
-       if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM) {
-               usbvision_write_reg(usbvision, USBVISION_VIN_REG1,
-                               USBVISION_16_422_SYNC | USBVISION_HVALID_PO);
-               usbvision_write_reg(usbvision, USBVISION_VIN_REG2,
-                               USBVISION_NOHVALID | USBVISION_KEEP_BLANK);
-       }
-       usbvision_write_reg(usbvision, USBVISION_PWR_REG,
-                       USBVISION_SSPND_EN | USBVISION_PWR_VID);
-       mdelay(10);
-       err_code = usbvision_write_reg(usbvision, USBVISION_PWR_REG,
-                       USBVISION_SSPND_EN | USBVISION_PWR_VID | USBVISION_RES2);
-       if (err_code == 1)
-               usbvision->power = 1;
-       PDEBUG(DBG_FUNC, "%s: err_code %d", (err_code < 0) ? "ERROR" : "power is on", err_code);
-       return err_code;
-}
-
-
-/*
- * usbvision timer stuff
- */
-
-/* to call usbvision_power_off from task queue */
-static void call_usbvision_power_off(struct work_struct *work)
-{
-       struct usb_usbvision *usbvision = container_of(work, struct usb_usbvision, power_off_work);
-
-       PDEBUG(DBG_FUNC, "");
-       if (mutex_lock_interruptible(&usbvision->v4l2_lock))
-               return;
-
-       if (usbvision->user == 0) {
-               usbvision_i2c_unregister(usbvision);
-
-               usbvision_power_off(usbvision);
-               usbvision->initialized = 0;
-       }
-       mutex_unlock(&usbvision->v4l2_lock);
-}
-
-static void usbvision_power_off_timer(unsigned long data)
-{
-       struct usb_usbvision *usbvision = (void *)data;
-
-       PDEBUG(DBG_FUNC, "");
-       del_timer(&usbvision->power_off_timer);
-       INIT_WORK(&usbvision->power_off_work, call_usbvision_power_off);
-       (void) schedule_work(&usbvision->power_off_work);
-}
-
-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;
-}
-
-void usbvision_set_power_off_timer(struct usb_usbvision *usbvision)
-{
-       mod_timer(&usbvision->power_off_timer, jiffies + USBVISION_POWEROFF_TIME);
-}
-
-void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision)
-{
-       if (timer_pending(&usbvision->power_off_timer))
-               del_timer(&usbvision->power_off_timer);
-}
-
-/*
- * usbvision_begin_streaming()
- * Sure you have to put bit 7 to 0, if not incoming frames are droped, but no
- * idea about the rest
- */
-int usbvision_begin_streaming(struct usb_usbvision *usbvision)
-{
-       if (usbvision->isoc_mode == ISOC_MODE_COMPRESS)
-               usbvision_init_compression(usbvision);
-       return usbvision_write_reg(usbvision, USBVISION_VIN_REG2,
-               USBVISION_NOHVALID | usbvision->vin_reg2_preset);
-}
-
-/*
- * usbvision_restart_isoc()
- * Not sure yet if touching here PWR_REG make loose the config
- */
-
-int usbvision_restart_isoc(struct usb_usbvision *usbvision)
-{
-       int ret;
-
-       ret = usbvision_write_reg(usbvision, USBVISION_PWR_REG,
-                             USBVISION_SSPND_EN | USBVISION_PWR_VID);
-       if (ret < 0)
-               return ret;
-       ret = usbvision_write_reg(usbvision, USBVISION_PWR_REG,
-                             USBVISION_SSPND_EN | USBVISION_PWR_VID |
-                             USBVISION_RES2);
-       if (ret < 0)
-               return ret;
-       ret = usbvision_write_reg(usbvision, USBVISION_VIN_REG2,
-                             USBVISION_KEEP_BLANK | USBVISION_NOHVALID |
-                                 usbvision->vin_reg2_preset);
-       if (ret < 0)
-               return ret;
-
-       /* TODO: schedule timeout */
-       while ((usbvision_read_reg(usbvision, USBVISION_STATUS_REG) & 0x01) != 1)
-               ;
-
-       return 0;
-}
-
-int usbvision_audio_off(struct usb_usbvision *usbvision)
-{
-       if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, USBVISION_AUDIO_MUTE) < 0) {
-               printk(KERN_ERR "usbvision_audio_off: can't write reg\n");
-               return -1;
-       }
-       usbvision->audio_mute = 0;
-       usbvision->audio_channel = USBVISION_AUDIO_MUTE;
-       return 0;
-}
-
-int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel)
-{
-       if (!usbvision->audio_mute) {
-               if (usbvision_write_reg(usbvision, USBVISION_IOPIN_REG, audio_channel) < 0) {
-                       printk(KERN_ERR "usbvision_set_audio: can't write iopin register for audio switching\n");
-                       return -1;
-               }
-       }
-       usbvision->audio_channel = audio_channel;
-       return 0;
-}
-
-int usbvision_setup(struct usb_usbvision *usbvision, int format)
-{
-       if (usbvision_device_data[usbvision->dev_model].codec == CODEC_WEBCAM)
-               usbvision_init_webcam(usbvision);
-       usbvision_set_video_format(usbvision, format);
-       usbvision_set_dram_settings(usbvision);
-       usbvision_set_compress_params(usbvision);
-       usbvision_set_input(usbvision);
-       usbvision_set_output(usbvision, MAX_USB_WIDTH, MAX_USB_HEIGHT);
-       usbvision_restart_isoc(usbvision);
-
-       /* cosas del PCM */
-       return USBVISION_IS_OPERATIONAL(usbvision);
-}
-
-int usbvision_set_alternate(struct usb_usbvision *dev)
-{
-       int err_code, prev_alt = dev->iface_alt;
-       int i;
-
-       dev->iface_alt = 0;
-       for (i = 0; i < dev->num_alt; i++)
-               if (dev->alt_max_pkt_size[i] > dev->alt_max_pkt_size[dev->iface_alt])
-                       dev->iface_alt = i;
-
-       if (dev->iface_alt != prev_alt) {
-               dev->isoc_packet_size = dev->alt_max_pkt_size[dev->iface_alt];
-               PDEBUG(DBG_FUNC, "setting alternate %d with max_packet_size=%u",
-                               dev->iface_alt, dev->isoc_packet_size);
-               err_code = usb_set_interface(dev->dev, dev->iface, dev->iface_alt);
-               if (err_code < 0) {
-                       dev_err(&dev->dev->dev,
-                               "cannot change alternate number to %d (error=%i)\n",
-                                       dev->iface_alt, err_code);
-                       return err_code;
-               }
-       }
-
-       PDEBUG(DBG_ISOC, "ISO Packet Length:%d", dev->isoc_packet_size);
-
-       return 0;
-}
-
-/*
- * usbvision_init_isoc()
- *
- */
-int usbvision_init_isoc(struct usb_usbvision *usbvision)
-{
-       struct usb_device *dev = usbvision->dev;
-       int buf_idx, err_code, reg_value;
-       int sb_size;
-
-       if (!USBVISION_IS_OPERATIONAL(usbvision))
-               return -EFAULT;
-
-       usbvision->cur_frame = NULL;
-       scratch_reset(usbvision);
-
-       /* Alternate interface 1 is is the biggest frame size */
-       err_code = usbvision_set_alternate(usbvision);
-       if (err_code < 0) {
-               usbvision->last_error = err_code;
-               return -EBUSY;
-       }
-       sb_size = USBVISION_URB_FRAMES * usbvision->isoc_packet_size;
-
-       reg_value = (16 - usbvision_read_reg(usbvision,
-                                           USBVISION_ALTER_REG)) & 0x0F;
-
-       usbvision->usb_bandwidth = reg_value >> 1;
-       PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
-              usbvision->usb_bandwidth);
-
-
-
-       /* We double buffer the Iso lists */
-
-       for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) {
-               int j, k;
-               struct urb *urb;
-
-               urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
-               if (urb == NULL) {
-                       dev_err(&usbvision->dev->dev,
-                               "%s: usb_alloc_urb() failed\n", __func__);
-                       return -ENOMEM;
-               }
-               usbvision->sbuf[buf_idx].urb = urb;
-               usbvision->sbuf[buf_idx].data =
-                       usb_alloc_coherent(usbvision->dev,
-                                          sb_size,
-                                          GFP_KERNEL,
-                                          &urb->transfer_dma);
-               urb->dev = dev;
-               urb->context = usbvision;
-               urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp);
-               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-               urb->interval = 1;
-               urb->transfer_buffer = usbvision->sbuf[buf_idx].data;
-               urb->complete = usbvision_isoc_irq;
-               urb->number_of_packets = USBVISION_URB_FRAMES;
-               urb->transfer_buffer_length =
-                   usbvision->isoc_packet_size * USBVISION_URB_FRAMES;
-               for (j = k = 0; j < USBVISION_URB_FRAMES; j++,
-                    k += usbvision->isoc_packet_size) {
-                       urb->iso_frame_desc[j].offset = k;
-                       urb->iso_frame_desc[j].length =
-                               usbvision->isoc_packet_size;
-               }
-       }
-
-       /* Submit all URBs */
-       for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) {
-                       err_code = usb_submit_urb(usbvision->sbuf[buf_idx].urb,
-                                                GFP_KERNEL);
-               if (err_code) {
-                       dev_err(&usbvision->dev->dev,
-                               "%s: usb_submit_urb(%d) failed: error %d\n",
-                                       __func__, buf_idx, err_code);
-               }
-       }
-
-       usbvision->streaming = stream_idle;
-       PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x",
-              __func__,
-              usbvision->video_endp);
-       return 0;
-}
-
-/*
- * usbvision_stop_isoc()
- *
- * This procedure stops streaming and deallocates URBs. Then it
- * activates zero-bandwidth alt. setting of the video interface.
- *
- */
-void usbvision_stop_isoc(struct usb_usbvision *usbvision)
-{
-       int buf_idx, err_code, reg_value;
-       int sb_size = USBVISION_URB_FRAMES * usbvision->isoc_packet_size;
-
-       if ((usbvision->streaming == stream_off) || (usbvision->dev == NULL))
-               return;
-
-       /* Unschedule all of the iso td's */
-       for (buf_idx = 0; buf_idx < USBVISION_NUMSBUF; buf_idx++) {
-               usb_kill_urb(usbvision->sbuf[buf_idx].urb);
-               if (usbvision->sbuf[buf_idx].data) {
-                       usb_free_coherent(usbvision->dev,
-                                         sb_size,
-                                         usbvision->sbuf[buf_idx].data,
-                                         usbvision->sbuf[buf_idx].urb->transfer_dma);
-               }
-               usb_free_urb(usbvision->sbuf[buf_idx].urb);
-               usbvision->sbuf[buf_idx].urb = NULL;
-       }
-
-       PDEBUG(DBG_ISOC, "%s: streaming=stream_off\n", __func__);
-       usbvision->streaming = stream_off;
-
-       if (!usbvision->remove_pending) {
-               /* Set packet size to 0 */
-               usbvision->iface_alt = 0;
-               err_code = usb_set_interface(usbvision->dev, usbvision->iface,
-                                           usbvision->iface_alt);
-               if (err_code < 0) {
-                       dev_err(&usbvision->dev->dev,
-                               "%s: usb_set_interface() failed: error %d\n",
-                                       __func__, err_code);
-                       usbvision->last_error = err_code;
-               }
-               reg_value = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
-               usbvision->isoc_packet_size =
-                       (reg_value == 0) ? 0 : (reg_value * 64) - 1;
-               PDEBUG(DBG_ISOC, "ISO Packet Length:%d",
-                      usbvision->isoc_packet_size);
-
-               usbvision->usb_bandwidth = reg_value >> 1;
-               PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
-                      usbvision->usb_bandwidth);
-       }
-}
-
-int usbvision_muxsel(struct usb_usbvision *usbvision, int channel)
-{
-       /* inputs #0 and #3 are constant for every SAA711x. */
-       /* inputs #1 and #2 are variable for SAA7111 and SAA7113 */
-       int mode[4] = { SAA7115_COMPOSITE0, 0, 0, SAA7115_COMPOSITE3 };
-       int audio[] = { 1, 0, 0, 0 };
-       /* channel 0 is TV with audiochannel 1 (tuner mono) */
-       /* channel 1 is Composite with audio channel 0 (line in) */
-       /* channel 2 is S-Video with audio channel 0 (line in) */
-       /* channel 3 is additional video inputs to the device with audio channel 0 (line in) */
-
-       RESTRICT_TO_RANGE(channel, 0, usbvision->video_inputs);
-       usbvision->ctl_input = channel;
-
-       /* set the new channel */
-       /* Regular USB TV Tuners -> channel: 0 = Television, 1 = Composite, 2 = S-Video */
-       /* Four video input devices -> channel: 0 = Chan White, 1 = Chan Green, 2 = Chan Yellow, 3 = Chan Red */
-
-       switch (usbvision_device_data[usbvision->dev_model].codec) {
-       case CODEC_SAA7113:
-               mode[1] = SAA7115_COMPOSITE2;
-               if (switch_svideo_input) {
-                       /* To handle problems with S-Video Input for
-                        * some devices.  Use switch_svideo_input
-                        * parameter when loading the module.*/
-                       mode[2] = SAA7115_COMPOSITE1;
-               } else {
-                       mode[2] = SAA7115_SVIDEO1;
-               }
-               break;
-       case CODEC_SAA7111:
-       default:
-               /* modes for saa7111 */
-               mode[1] = SAA7115_COMPOSITE1;
-               mode[2] = SAA7115_SVIDEO1;
-               break;
-       }
-       call_all(usbvision, video, s_routing, mode[channel], 0, 0);
-       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/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c
deleted file mode 100644 (file)
index 89fec02..0000000
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * usbvision_i2c.c
- *  i2c algorithm for USB-I2C Bridges
- *
- * Copyright (c) 1999-2007 Joerg Heckenbach <joerg@heckenbach-aw.de>
- *                         Dwaine Garden <dwainegarden@rogers.com>
- *
- * This module is part of usbvision driver project.
- * Updates to driver completed by Dwaine P. Garden
- *
- * 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/module.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/uaccess.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <linux/usb.h>
-#include <linux/i2c.h>
-#include "usbvision.h"
-
-#define DBG_I2C                (1 << 0)
-
-static int i2c_debug;
-
-module_param(i2c_debug, int, 0644);                    /* debug_i2c_usb mode of the device driver */
-MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
-
-#define PDEBUG(level, fmt, args...) { \
-               if (i2c_debug & (level)) \
-                       printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \
-                               __func__, __LINE__ , ## args); \
-       }
-
-static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
-                           short len);
-static int usbvision_i2c_read(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
-                          short len);
-
-static inline int try_write_address(struct i2c_adapter *i2c_adap,
-                                   unsigned char addr, int retries)
-{
-       struct usb_usbvision *usbvision;
-       int i, ret = -1;
-       char buf[4];
-
-       usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap);
-       buf[0] = 0x00;
-       for (i = 0; i <= retries; i++) {
-               ret = (usbvision_i2c_write(usbvision, addr, buf, 1));
-               if (ret == 1)
-                       break;  /* success! */
-               udelay(5);
-               if (i == retries)       /* no success */
-                       break;
-               udelay(10);
-       }
-       if (i) {
-               PDEBUG(DBG_I2C, "Needed %d retries for address %#2x", i, addr);
-               PDEBUG(DBG_I2C, "Maybe there's no device at this address");
-       }
-       return ret;
-}
-
-static inline int try_read_address(struct i2c_adapter *i2c_adap,
-                                  unsigned char addr, int retries)
-{
-       struct usb_usbvision *usbvision;
-       int i, ret = -1;
-       char buf[4];
-
-       usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap);
-       for (i = 0; i <= retries; i++) {
-               ret = (usbvision_i2c_read(usbvision, addr, buf, 1));
-               if (ret == 1)
-                       break;  /* success! */
-               udelay(5);
-               if (i == retries)       /* no success */
-                       break;
-               udelay(10);
-       }
-       if (i) {
-               PDEBUG(DBG_I2C, "Needed %d retries for address %#2x", i, addr);
-               PDEBUG(DBG_I2C, "Maybe there's no device at this address");
-       }
-       return ret;
-}
-
-static inline int usb_find_address(struct i2c_adapter *i2c_adap,
-                                  struct i2c_msg *msg, int retries,
-                                  unsigned char *add)
-{
-       unsigned short flags = msg->flags;
-
-       unsigned char addr;
-       int ret;
-
-       addr = (msg->addr << 1);
-       if (flags & I2C_M_RD)
-               addr |= 1;
-
-       add[0] = addr;
-       if (flags & I2C_M_RD)
-               ret = try_read_address(i2c_adap, addr, retries);
-       else
-               ret = try_write_address(i2c_adap, addr, retries);
-
-       if (ret != 1)
-               return -EREMOTEIO;
-
-       return 0;
-}
-
-static int
-usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
-{
-       struct i2c_msg *pmsg;
-       struct usb_usbvision *usbvision;
-       int i, ret;
-       unsigned char addr = 0;
-
-       usbvision = (struct usb_usbvision *)i2c_get_adapdata(i2c_adap);
-
-       for (i = 0; i < num; i++) {
-               pmsg = &msgs[i];
-               ret = usb_find_address(i2c_adap, pmsg, i2c_adap->retries, &addr);
-               if (ret != 0) {
-                       PDEBUG(DBG_I2C, "got NAK from device, message #%d", i);
-                       return (ret < 0) ? ret : -EREMOTEIO;
-               }
-
-               if (pmsg->flags & I2C_M_RD) {
-                       /* read bytes into buffer */
-                       ret = (usbvision_i2c_read(usbvision, addr, pmsg->buf, pmsg->len));
-                       if (ret < pmsg->len)
-                               return (ret < 0) ? ret : -EREMOTEIO;
-               } else {
-                       /* write bytes from buffer */
-                       ret = (usbvision_i2c_write(usbvision, addr, pmsg->buf, pmsg->len));
-                       if (ret < pmsg->len)
-                               return (ret < 0) ? ret : -EREMOTEIO;
-               }
-       }
-       return num;
-}
-
-static u32 functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-/* -----exported algorithm data: ------------------------------------- */
-
-static struct i2c_algorithm usbvision_algo = {
-       .master_xfer   = usbvision_i2c_xfer,
-       .smbus_xfer    = NULL,
-       .functionality = functionality,
-};
-
-
-/* ----------------------------------------------------------------------- */
-/* usbvision specific I2C functions                                        */
-/* ----------------------------------------------------------------------- */
-static struct i2c_adapter i2c_adap_template;
-
-int usbvision_i2c_register(struct usb_usbvision *usbvision)
-{
-       static unsigned short saa711x_addrs[] = {
-               0x4a >> 1, 0x48 >> 1,   /* SAA7111, SAA7111A and SAA7113 */
-               0x42 >> 1, 0x40 >> 1,   /* SAA7114, SAA7115 and SAA7118 */
-               I2C_CLIENT_END };
-
-       if (usbvision->registered_i2c)
-               return 0;
-
-       memcpy(&usbvision->i2c_adap, &i2c_adap_template,
-              sizeof(struct i2c_adapter));
-
-       sprintf(usbvision->i2c_adap.name, "%s-%d-%s", i2c_adap_template.name,
-               usbvision->dev->bus->busnum, usbvision->dev->devpath);
-       PDEBUG(DBG_I2C, "Adaptername: %s", usbvision->i2c_adap.name);
-       usbvision->i2c_adap.dev.parent = &usbvision->dev->dev;
-
-       i2c_set_adapdata(&usbvision->i2c_adap, &usbvision->v4l2_dev);
-
-       if (usbvision_write_reg(usbvision, USBVISION_SER_MODE, USBVISION_IIC_LRNACK) < 0) {
-               printk(KERN_ERR "usbvision_i2c_register: can't write reg\n");
-               return -EBUSY;
-       }
-
-       PDEBUG(DBG_I2C, "I2C   debugging is enabled [i2c]");
-       PDEBUG(DBG_I2C, "ALGO   debugging is enabled [i2c]");
-
-       /* register new adapter to i2c module... */
-
-       usbvision->i2c_adap.algo = &usbvision_algo;
-
-       usbvision->i2c_adap.timeout = 100;      /* default values, should       */
-       usbvision->i2c_adap.retries = 3;        /* be replaced by defines       */
-
-       i2c_add_adapter(&usbvision->i2c_adap);
-
-       PDEBUG(DBG_I2C, "i2c bus for %s registered", usbvision->i2c_adap.name);
-
-       /* Request the load of the i2c modules we need */
-       switch (usbvision_device_data[usbvision->dev_model].codec) {
-       case CODEC_SAA7113:
-       case CODEC_SAA7111:
-               /* Without this delay the detection of the saa711x is
-                  hit-and-miss. */
-               mdelay(10);
-               v4l2_i2c_new_subdev(&usbvision->v4l2_dev,
-                               &usbvision->i2c_adap,
-                               "saa7115_auto", 0, saa711x_addrs);
-               break;
-       }
-       if (usbvision_device_data[usbvision->dev_model].tuner == 1) {
-               struct v4l2_subdev *sd;
-               enum v4l2_i2c_tuner_type type;
-               struct tuner_setup tun_setup;
-
-               sd = v4l2_i2c_new_subdev(&usbvision->v4l2_dev,
-                               &usbvision->i2c_adap,
-                               "tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
-               /* depending on whether we found a demod or not, select
-                  the tuner type. */
-               type = sd ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
-
-               sd = v4l2_i2c_new_subdev(&usbvision->v4l2_dev,
-                               &usbvision->i2c_adap,
-                               "tuner", 0, v4l2_i2c_tuner_addrs(type));
-
-               if (sd == NULL)
-                       return -ENODEV;
-               if (usbvision->tuner_type != -1) {
-                       tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
-                       tun_setup.type = usbvision->tuner_type;
-                       tun_setup.addr = v4l2_i2c_subdev_addr(sd);
-                       call_all(usbvision, tuner, s_type_addr, &tun_setup);
-               }
-       }
-       usbvision->registered_i2c = 1;
-
-       return 0;
-}
-
-int usbvision_i2c_unregister(struct usb_usbvision *usbvision)
-{
-       if (!usbvision->registered_i2c)
-               return 0;
-
-       i2c_del_adapter(&(usbvision->i2c_adap));
-       usbvision->registered_i2c = 0;
-
-       PDEBUG(DBG_I2C, "i2c bus for %s unregistered", usbvision->i2c_adap.name);
-
-       return 0;
-}
-
-static int
-usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr,
-                    char *buf, short len)
-{
-       int rc, retries;
-
-       for (retries = 5;;) {
-               rc = usbvision_write_reg(usbvision, USBVISION_SER_ADRS, addr);
-               if (rc < 0)
-                       return rc;
-
-               /* Initiate byte read cycle                    */
-               /* USBVISION_SER_CONT <- d0-d2 n. of bytes to r/w */
-               /*                    d3 0=Wr 1=Rd             */
-               rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT,
-                                     (len & 0x07) | 0x18);
-               if (rc < 0)
-                       return rc;
-
-               /* Test for Busy and ACK */
-               do {
-                       /* USBVISION_SER_CONT -> d4 == 0 busy */
-                       rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT);
-               } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */
-               if (rc < 0)
-                       return rc;
-
-               /* USBVISION_SER_CONT -> d5 == 1 Not ack */
-               if ((rc & 0x20) == 0)   /* Ack? */
-                       break;
-
-               /* I2C abort */
-               rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00);
-               if (rc < 0)
-                       return rc;
-
-               if (--retries < 0)
-                       return -1;
-       }
-
-       switch (len) {
-       case 4:
-               buf[3] = usbvision_read_reg(usbvision, USBVISION_SER_DAT4);
-       case 3:
-               buf[2] = usbvision_read_reg(usbvision, USBVISION_SER_DAT3);
-       case 2:
-               buf[1] = usbvision_read_reg(usbvision, USBVISION_SER_DAT2);
-       case 1:
-               buf[0] = usbvision_read_reg(usbvision, USBVISION_SER_DAT1);
-               break;
-       default:
-               printk(KERN_ERR
-                      "usbvision_i2c_read_max4: buffer length > 4\n");
-       }
-
-       if (i2c_debug & DBG_I2C) {
-               int idx;
-
-               for (idx = 0; idx < len; idx++)
-                       PDEBUG(DBG_I2C, "read %x from address %x", (unsigned char)buf[idx], addr);
-       }
-       return len;
-}
-
-
-static int usbvision_i2c_write_max4(struct usb_usbvision *usbvision,
-                                unsigned char addr, const char *buf,
-                                short len)
-{
-       int rc, retries;
-       int i;
-       unsigned char value[6];
-       unsigned char ser_cont;
-
-       ser_cont = (len & 0x07) | 0x10;
-
-       value[0] = addr;
-       value[1] = ser_cont;
-       for (i = 0; i < len; i++)
-               value[i + 2] = buf[i];
-
-       for (retries = 5;;) {
-               rc = usb_control_msg(usbvision->dev,
-                                    usb_sndctrlpipe(usbvision->dev, 1),
-                                    USBVISION_OP_CODE,
-                                    USB_DIR_OUT | USB_TYPE_VENDOR |
-                                    USB_RECIP_ENDPOINT, 0,
-                                    (__u16) USBVISION_SER_ADRS, value,
-                                    len + 2, HZ);
-
-               if (rc < 0)
-                       return rc;
-
-               rc = usbvision_write_reg(usbvision, USBVISION_SER_CONT,
-                                     (len & 0x07) | 0x10);
-               if (rc < 0)
-                       return rc;
-
-               /* Test for Busy and ACK */
-               do {
-                       rc = usbvision_read_reg(usbvision, USBVISION_SER_CONT);
-               } while (rc > 0 && ((rc & 0x10) != 0)); /* Retry while busy */
-               if (rc < 0)
-                       return rc;
-
-               if ((rc & 0x20) == 0)   /* Ack? */
-                       break;
-
-               /* I2C abort */
-               usbvision_write_reg(usbvision, USBVISION_SER_CONT, 0x00);
-
-               if (--retries < 0)
-                       return -1;
-
-       }
-
-       if (i2c_debug & DBG_I2C) {
-               int idx;
-
-               for (idx = 0; idx < len; idx++)
-                       PDEBUG(DBG_I2C, "wrote %x at address %x", (unsigned char)buf[idx], addr);
-       }
-       return len;
-}
-
-static int usbvision_i2c_write(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
-                           short len)
-{
-       char *buf_ptr = buf;
-       int retval;
-       int wrcount = 0;
-       int count;
-       int max_len = 4;
-
-       while (len > 0) {
-               count = (len > max_len) ? max_len : len;
-               retval = usbvision_i2c_write_max4(usbvision, addr, buf_ptr, count);
-               if (retval > 0) {
-                       len -= count;
-                       buf_ptr += count;
-                       wrcount += count;
-               } else
-                       return (retval < 0) ? retval : -EFAULT;
-       }
-       return wrcount;
-}
-
-static int usbvision_i2c_read(struct usb_usbvision *usbvision, unsigned char addr, char *buf,
-                          short len)
-{
-       char temp[4];
-       int retval, i;
-       int rdcount = 0;
-       int count;
-
-       while (len > 0) {
-               count = (len > 3) ? 4 : len;
-               retval = usbvision_i2c_read_max4(usbvision, addr, temp, count);
-               if (retval > 0) {
-                       for (i = 0; i < len; i++)
-                               buf[rdcount + i] = temp[i];
-                       len -= count;
-                       rdcount += count;
-               } else
-                       return (retval < 0) ? retval : -EFAULT;
-       }
-       return rdcount;
-}
-
-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/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
deleted file mode 100644 (file)
index 8a43179..0000000
+++ /dev/null
@@ -1,1720 +0,0 @@
-/*
- * USB USBVISION Video device driver 0.9.10
- *
- *
- *
- * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
- *
- * This module is part of usbvision driver project.
- *
- * 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.
- *
- * Let's call the version 0.... until compression decoding is completely
- * implemented.
- *
- * This driver is written by Jose Ignacio Gijon and Joerg Heckenbach.
- * It was based on USB CPiA driver written by Peter Pregler,
- * Scott J. Bertin and Johannes Erdfelt
- * Ideas are taken from bttv driver by Ralph Metzler, Marcus Metzler &
- * Gerd Knorr and zoran 36120/36125 driver by Pauline Middelink
- * Updates to driver completed by Dwaine P. Garden
- *
- *
- * TODO:
- *     - use submit_urb for all setup packets
- *     - Fix memory settings for nt1004. It is 4 times as big as the
- *       nt1003 memory.
- *     - Add audio on endpoint 3 for nt1004 chip.
- *         Seems impossible, needs a codec interface.  Which one?
- *     - Clean up the driver.
- *     - optimization for performance.
- *     - Add Videotext capability (VBI).  Working on it.....
- *     - Check audio for other devices
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/vmalloc.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <linux/videodev2.h>
-#include <linux/i2c.h>
-
-#include <media/saa7115.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/tuner.h>
-
-#include <linux/workqueue.h>
-
-#include "usbvision.h"
-#include "usbvision-cards.h"
-
-#define DRIVER_AUTHOR                                  \
-       "Joerg Heckenbach <joerg@heckenbach-aw.de>, "   \
-       "Dwaine Garden <DwaineGarden@rogers.com>"
-#define DRIVER_NAME "usbvision"
-#define DRIVER_ALIAS "USBVision"
-#define DRIVER_DESC "USBVision USB Video Device Driver for Linux"
-#define DRIVER_LICENSE "GPL"
-#define USBVISION_VERSION_STRING "0.9.11"
-
-#define        ENABLE_HEXDUMP  0       /* Enable if you need it */
-
-
-#ifdef USBVISION_DEBUG
-       #define PDEBUG(level, fmt, args...) { \
-               if (video_debug & (level)) \
-                       printk(KERN_INFO KBUILD_MODNAME ":[%s:%d] " fmt, \
-                               __func__, __LINE__ , ## args); \
-       }
-#else
-       #define PDEBUG(level, fmt, args...) do {} while (0)
-#endif
-
-#define DBG_IO         (1 << 1)
-#define DBG_PROBE      (1 << 2)
-#define DBG_MMAP       (1 << 3)
-
-/* String operations */
-#define rmspace(str)   while (*str == ' ') str++;
-#define goto2next(str) while (*str != ' ') str++; while (*str == ' ') str++;
-
-
-/* sequential number of usbvision device */
-static int usbvision_nr;
-
-static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = {
-       { 1, 1,  8, V4L2_PIX_FMT_GREY    , "GREY" },
-       { 1, 2, 16, V4L2_PIX_FMT_RGB565  , "RGB565" },
-       { 1, 3, 24, V4L2_PIX_FMT_RGB24   , "RGB24" },
-       { 1, 4, 32, V4L2_PIX_FMT_RGB32   , "RGB32" },
-       { 1, 2, 16, V4L2_PIX_FMT_RGB555  , "RGB555" },
-       { 1, 2, 16, V4L2_PIX_FMT_YUYV    , "YUV422" },
-       { 1, 2, 12, V4L2_PIX_FMT_YVU420  , "YUV420P" }, /* 1.5 ! */
-       { 1, 2, 16, V4L2_PIX_FMT_YUV422P , "YUV422P" }
-};
-
-/* Function prototypes */
-static void usbvision_release(struct usb_usbvision *usbvision);
-
-/* Default initialization of device driver parameters */
-/* Set the default format for ISOC endpoint */
-static int isoc_mode = ISOC_MODE_COMPRESS;
-/* Set the default Debug Mode of the device driver */
-static int video_debug;
-/* Set the default device to power on at startup */
-static int power_on_at_open = 1;
-/* Sequential Number of Video Device */
-static int video_nr = -1;
-/* Sequential Number of Radio Device */
-static int radio_nr = -1;
-
-/* Grab parameters for the device driver */
-
-/* Showing parameters under SYSFS */
-module_param(isoc_mode, int, 0444);
-module_param(video_debug, int, 0444);
-module_param(power_on_at_open, int, 0444);
-module_param(video_nr, int, 0444);
-module_param(radio_nr, int, 0444);
-
-MODULE_PARM_DESC(isoc_mode, " Set the default format for ISOC endpoint.  Default: 0x60 (Compression On)");
-MODULE_PARM_DESC(video_debug, " Set the default Debug Mode of the device driver.  Default: 0 (Off)");
-MODULE_PARM_DESC(power_on_at_open, " Set the default device to power on when device is opened.  Default: 1 (On)");
-MODULE_PARM_DESC(video_nr, "Set video device number (/dev/videoX).  Default: -1 (autodetect)");
-MODULE_PARM_DESC(radio_nr, "Set radio device number (/dev/radioX).  Default: -1 (autodetect)");
-
-
-/* Misc stuff */
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-MODULE_VERSION(USBVISION_VERSION_STRING);
-MODULE_ALIAS(DRIVER_ALIAS);
-
-
-/*****************************************************************************/
-/* SYSFS Code - Copied from the stv680.c usb module.                        */
-/* Device information is located at /sys/class/video4linux/video0            */
-/* Device parameters information is located at /sys/module/usbvision         */
-/* Device USB Information is located at                                      */
-/*   /sys/bus/usb/drivers/USBVision Video Grabber                            */
-/*****************************************************************************/
-
-#define YES_NO(x) ((x) ? "Yes" : "No")
-
-static inline struct usb_usbvision *cd_to_usbvision(struct device *cd)
-{
-       struct video_device *vdev =
-               container_of(cd, struct video_device, dev);
-       return video_get_drvdata(vdev);
-}
-
-static ssize_t show_version(struct device *cd,
-                           struct device_attribute *attr, char *buf)
-{
-       return sprintf(buf, "%s\n", USBVISION_VERSION_STRING);
-}
-static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
-
-static ssize_t show_model(struct device *cd,
-                         struct device_attribute *attr, char *buf)
-{
-       struct video_device *vdev =
-               container_of(cd, struct video_device, dev);
-       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
-       return sprintf(buf, "%s\n",
-                      usbvision_device_data[usbvision->dev_model].model_string);
-}
-static DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
-
-static ssize_t show_hue(struct device *cd,
-                       struct device_attribute *attr, char *buf)
-{
-       struct video_device *vdev =
-               container_of(cd, struct video_device, dev);
-       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
-       struct v4l2_control ctrl;
-       ctrl.id = V4L2_CID_HUE;
-       ctrl.value = 0;
-       if (usbvision->user)
-               call_all(usbvision, core, g_ctrl, &ctrl);
-       return sprintf(buf, "%d\n", ctrl.value);
-}
-static DEVICE_ATTR(hue, S_IRUGO, show_hue, NULL);
-
-static ssize_t show_contrast(struct device *cd,
-                            struct device_attribute *attr, char *buf)
-{
-       struct video_device *vdev =
-               container_of(cd, struct video_device, dev);
-       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
-       struct v4l2_control ctrl;
-       ctrl.id = V4L2_CID_CONTRAST;
-       ctrl.value = 0;
-       if (usbvision->user)
-               call_all(usbvision, core, g_ctrl, &ctrl);
-       return sprintf(buf, "%d\n", ctrl.value);
-}
-static DEVICE_ATTR(contrast, S_IRUGO, show_contrast, NULL);
-
-static ssize_t show_brightness(struct device *cd,
-                              struct device_attribute *attr, char *buf)
-{
-       struct video_device *vdev =
-               container_of(cd, struct video_device, dev);
-       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
-       struct v4l2_control ctrl;
-       ctrl.id = V4L2_CID_BRIGHTNESS;
-       ctrl.value = 0;
-       if (usbvision->user)
-               call_all(usbvision, core, g_ctrl, &ctrl);
-       return sprintf(buf, "%d\n", ctrl.value);
-}
-static DEVICE_ATTR(brightness, S_IRUGO, show_brightness, NULL);
-
-static ssize_t show_saturation(struct device *cd,
-                              struct device_attribute *attr, char *buf)
-{
-       struct video_device *vdev =
-               container_of(cd, struct video_device, dev);
-       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
-       struct v4l2_control ctrl;
-       ctrl.id = V4L2_CID_SATURATION;
-       ctrl.value = 0;
-       if (usbvision->user)
-               call_all(usbvision, core, g_ctrl, &ctrl);
-       return sprintf(buf, "%d\n", ctrl.value);
-}
-static DEVICE_ATTR(saturation, S_IRUGO, show_saturation, NULL);
-
-static ssize_t show_streaming(struct device *cd,
-                             struct device_attribute *attr, char *buf)
-{
-       struct video_device *vdev =
-               container_of(cd, struct video_device, dev);
-       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
-       return sprintf(buf, "%s\n",
-                      YES_NO(usbvision->streaming == stream_on ? 1 : 0));
-}
-static DEVICE_ATTR(streaming, S_IRUGO, show_streaming, NULL);
-
-static ssize_t show_compression(struct device *cd,
-                               struct device_attribute *attr, char *buf)
-{
-       struct video_device *vdev =
-               container_of(cd, struct video_device, dev);
-       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
-       return sprintf(buf, "%s\n",
-                      YES_NO(usbvision->isoc_mode == ISOC_MODE_COMPRESS));
-}
-static DEVICE_ATTR(compression, S_IRUGO, show_compression, NULL);
-
-static ssize_t show_device_bridge(struct device *cd,
-                                 struct device_attribute *attr, char *buf)
-{
-       struct video_device *vdev =
-               container_of(cd, struct video_device, dev);
-       struct usb_usbvision *usbvision = video_get_drvdata(vdev);
-       return sprintf(buf, "%d\n", usbvision->bridge_type);
-}
-static DEVICE_ATTR(bridge, S_IRUGO, show_device_bridge, NULL);
-
-static void usbvision_create_sysfs(struct video_device *vdev)
-{
-       int res;
-
-       if (!vdev)
-               return;
-       do {
-               res = device_create_file(&vdev->dev, &dev_attr_version);
-               if (res < 0)
-                       break;
-               res = device_create_file(&vdev->dev, &dev_attr_model);
-               if (res < 0)
-                       break;
-               res = device_create_file(&vdev->dev, &dev_attr_hue);
-               if (res < 0)
-                       break;
-               res = device_create_file(&vdev->dev, &dev_attr_contrast);
-               if (res < 0)
-                       break;
-               res = device_create_file(&vdev->dev, &dev_attr_brightness);
-               if (res < 0)
-                       break;
-               res = device_create_file(&vdev->dev, &dev_attr_saturation);
-               if (res < 0)
-                       break;
-               res = device_create_file(&vdev->dev, &dev_attr_streaming);
-               if (res < 0)
-                       break;
-               res = device_create_file(&vdev->dev, &dev_attr_compression);
-               if (res < 0)
-                       break;
-               res = device_create_file(&vdev->dev, &dev_attr_bridge);
-               if (res >= 0)
-                       return;
-       } while (0);
-
-       dev_err(&vdev->dev, "%s error: %d\n", __func__, res);
-}
-
-static void usbvision_remove_sysfs(struct video_device *vdev)
-{
-       if (vdev) {
-               device_remove_file(&vdev->dev, &dev_attr_version);
-               device_remove_file(&vdev->dev, &dev_attr_model);
-               device_remove_file(&vdev->dev, &dev_attr_hue);
-               device_remove_file(&vdev->dev, &dev_attr_contrast);
-               device_remove_file(&vdev->dev, &dev_attr_brightness);
-               device_remove_file(&vdev->dev, &dev_attr_saturation);
-               device_remove_file(&vdev->dev, &dev_attr_streaming);
-               device_remove_file(&vdev->dev, &dev_attr_compression);
-               device_remove_file(&vdev->dev, &dev_attr_bridge);
-       }
-}
-
-/*
- * usbvision_open()
- *
- * This is part of Video 4 Linux API. The driver can be opened by one
- * client only (checks internal counter 'usbvision->user'). The procedure
- * then allocates buffers needed for video processing.
- *
- */
-static int usbvision_v4l2_open(struct file *file)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       int err_code = 0;
-
-       PDEBUG(DBG_IO, "open");
-
-       if (mutex_lock_interruptible(&usbvision->v4l2_lock))
-               return -ERESTARTSYS;
-       usbvision_reset_power_off_timer(usbvision);
-
-       if (usbvision->user)
-               err_code = -EBUSY;
-       else {
-               /* Allocate memory for the scratch ring buffer */
-               err_code = usbvision_scratch_alloc(usbvision);
-               if (isoc_mode == ISOC_MODE_COMPRESS) {
-                       /* Allocate intermediate decompression buffers
-                          only if needed */
-                       err_code = usbvision_decompress_alloc(usbvision);
-               }
-               if (err_code) {
-                       /* Deallocate all buffers if trouble */
-                       usbvision_scratch_free(usbvision);
-                       usbvision_decompress_free(usbvision);
-               }
-       }
-
-       /* If so far no errors then we shall start the camera */
-       if (!err_code) {
-               if (usbvision->power == 0) {
-                       usbvision_power_on(usbvision);
-                       usbvision_i2c_register(usbvision);
-               }
-
-               /* Send init sequence only once, it's large! */
-               if (!usbvision->initialized) {
-                       int setup_ok = 0;
-                       setup_ok = usbvision_setup(usbvision, isoc_mode);
-                       if (setup_ok)
-                               usbvision->initialized = 1;
-                       else
-                               err_code = -EBUSY;
-               }
-
-               if (!err_code) {
-                       usbvision_begin_streaming(usbvision);
-                       err_code = usbvision_init_isoc(usbvision);
-                       /* device must be initialized before isoc transfer */
-                       usbvision_muxsel(usbvision, 0);
-                       usbvision->user++;
-               } else {
-                       if (power_on_at_open) {
-                               usbvision_i2c_unregister(usbvision);
-                               usbvision_power_off(usbvision);
-                               usbvision->initialized = 0;
-                       }
-               }
-       }
-
-       /* prepare queues */
-       usbvision_empty_framequeues(usbvision);
-       mutex_unlock(&usbvision->v4l2_lock);
-
-       PDEBUG(DBG_IO, "success");
-       return err_code;
-}
-
-/*
- * usbvision_v4l2_close()
- *
- * This is part of Video 4 Linux API. The procedure
- * stops streaming and deallocates all buffers that were earlier
- * allocated in usbvision_v4l2_open().
- *
- */
-static int usbvision_v4l2_close(struct file *file)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       PDEBUG(DBG_IO, "close");
-
-       mutex_lock(&usbvision->v4l2_lock);
-       usbvision_audio_off(usbvision);
-       usbvision_restart_isoc(usbvision);
-       usbvision_stop_isoc(usbvision);
-
-       usbvision_decompress_free(usbvision);
-       usbvision_frames_free(usbvision);
-       usbvision_empty_framequeues(usbvision);
-       usbvision_scratch_free(usbvision);
-
-       usbvision->user--;
-
-       if (power_on_at_open) {
-               /* power off in a little while
-                  to avoid off/on every close/open short sequences */
-               usbvision_set_power_off_timer(usbvision);
-               usbvision->initialized = 0;
-       }
-
-       if (usbvision->remove_pending) {
-               printk(KERN_INFO "%s: Final disconnect\n", __func__);
-               usbvision_release(usbvision);
-       }
-       mutex_unlock(&usbvision->v4l2_lock);
-
-       PDEBUG(DBG_IO, "success");
-       return 0;
-}
-
-
-/*
- * usbvision_ioctl()
- *
- * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
- *
- */
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static int vidioc_g_register(struct file *file, void *priv,
-                               struct v4l2_dbg_register *reg)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       int err_code;
-
-       if (!v4l2_chip_match_host(&reg->match))
-               return -EINVAL;
-       /* NT100x has a 8-bit register space */
-       err_code = usbvision_read_reg(usbvision, reg->reg&0xff);
-       if (err_code < 0) {
-               dev_err(&usbvision->vdev->dev,
-                       "%s: VIDIOC_DBG_G_REGISTER failed: error %d\n",
-                               __func__, err_code);
-               return err_code;
-       }
-       reg->val = err_code;
-       reg->size = 1;
-       return 0;
-}
-
-static int vidioc_s_register(struct file *file, void *priv,
-                               struct v4l2_dbg_register *reg)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       int err_code;
-
-       if (!v4l2_chip_match_host(&reg->match))
-               return -EINVAL;
-       /* NT100x has a 8-bit register space */
-       err_code = usbvision_write_reg(usbvision, reg->reg & 0xff, reg->val);
-       if (err_code < 0) {
-               dev_err(&usbvision->vdev->dev,
-                       "%s: VIDIOC_DBG_S_REGISTER failed: error %d\n",
-                               __func__, err_code);
-               return err_code;
-       }
-       return 0;
-}
-#endif
-
-static int vidioc_querycap(struct file *file, void  *priv,
-                                       struct v4l2_capability *vc)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       strlcpy(vc->driver, "USBVision", sizeof(vc->driver));
-       strlcpy(vc->card,
-               usbvision_device_data[usbvision->dev_model].model_string,
-               sizeof(vc->card));
-       usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info));
-       vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
-               V4L2_CAP_AUDIO |
-               V4L2_CAP_READWRITE |
-               V4L2_CAP_STREAMING |
-               (usbvision->have_tuner ? V4L2_CAP_TUNER : 0);
-       return 0;
-}
-
-static int vidioc_enum_input(struct file *file, void *priv,
-                               struct v4l2_input *vi)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       int chan;
-
-       if (vi->index >= usbvision->video_inputs)
-               return -EINVAL;
-       if (usbvision->have_tuner)
-               chan = vi->index;
-       else
-               chan = vi->index + 1; /* skip Television string*/
-
-       /* Determine the requested input characteristics
-          specific for each usbvision card model */
-       switch (chan) {
-       case 0:
-               if (usbvision_device_data[usbvision->dev_model].video_channels == 4) {
-                       strcpy(vi->name, "White Video Input");
-               } else {
-                       strcpy(vi->name, "Television");
-                       vi->type = V4L2_INPUT_TYPE_TUNER;
-                       vi->audioset = 1;
-                       vi->tuner = chan;
-                       vi->std = USBVISION_NORMS;
-               }
-               break;
-       case 1:
-               vi->type = V4L2_INPUT_TYPE_CAMERA;
-               if (usbvision_device_data[usbvision->dev_model].video_channels == 4)
-                       strcpy(vi->name, "Green Video Input");
-               else
-                       strcpy(vi->name, "Composite Video Input");
-               vi->std = V4L2_STD_PAL;
-               break;
-       case 2:
-               vi->type = V4L2_INPUT_TYPE_CAMERA;
-               if (usbvision_device_data[usbvision->dev_model].video_channels == 4)
-                       strcpy(vi->name, "Yellow Video Input");
-               else
-                       strcpy(vi->name, "S-Video Input");
-               vi->std = V4L2_STD_PAL;
-               break;
-       case 3:
-               vi->type = V4L2_INPUT_TYPE_CAMERA;
-               strcpy(vi->name, "Red Video Input");
-               vi->std = V4L2_STD_PAL;
-               break;
-       }
-       return 0;
-}
-
-static int vidioc_g_input(struct file *file, void *priv, unsigned int *input)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       *input = usbvision->ctl_input;
-       return 0;
-}
-
-static int vidioc_s_input(struct file *file, void *priv, unsigned int input)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       if (input >= usbvision->video_inputs)
-               return -EINVAL;
-
-       usbvision_muxsel(usbvision, input);
-       usbvision_set_input(usbvision);
-       usbvision_set_output(usbvision,
-                            usbvision->curwidth,
-                            usbvision->curheight);
-       return 0;
-}
-
-static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       usbvision->tvnorm_id = *id;
-
-       call_all(usbvision, core, s_std, usbvision->tvnorm_id);
-       /* propagate the change to the decoder */
-       usbvision_muxsel(usbvision, usbvision->ctl_input);
-
-       return 0;
-}
-
-static int vidioc_g_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *vt)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       if (!usbvision->have_tuner || vt->index)        /* Only tuner 0 */
-               return -EINVAL;
-       if (usbvision->radio) {
-               strcpy(vt->name, "Radio");
-               vt->type = V4L2_TUNER_RADIO;
-       } else {
-               strcpy(vt->name, "Television");
-       }
-       /* Let clients fill in the remainder of this struct */
-       call_all(usbvision, tuner, g_tuner, vt);
-
-       return 0;
-}
-
-static int vidioc_s_tuner(struct file *file, void *priv,
-                               struct v4l2_tuner *vt)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       /* Only no or one tuner for now */
-       if (!usbvision->have_tuner || vt->index)
-               return -EINVAL;
-       /* let clients handle this */
-       call_all(usbvision, tuner, s_tuner, vt);
-
-       return 0;
-}
-
-static int vidioc_g_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *freq)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       freq->tuner = 0; /* Only one tuner */
-       if (usbvision->radio)
-               freq->type = V4L2_TUNER_RADIO;
-       else
-               freq->type = V4L2_TUNER_ANALOG_TV;
-       freq->frequency = usbvision->freq;
-
-       return 0;
-}
-
-static int vidioc_s_frequency(struct file *file, void *priv,
-                               struct v4l2_frequency *freq)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       /* Only no or one tuner for now */
-       if (!usbvision->have_tuner || freq->tuner)
-               return -EINVAL;
-
-       usbvision->freq = freq->frequency;
-       call_all(usbvision, tuner, s_frequency, freq);
-
-       return 0;
-}
-
-static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       if (usbvision->radio)
-               strcpy(a->name, "Radio");
-       else
-               strcpy(a->name, "TV");
-
-       return 0;
-}
-
-static int vidioc_s_audio(struct file *file, void *fh,
-                         struct v4l2_audio *a)
-{
-       if (a->index)
-               return -EINVAL;
-       return 0;
-}
-
-static int vidioc_queryctrl(struct file *file, void *priv,
-                           struct v4l2_queryctrl *ctrl)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       call_all(usbvision, core, queryctrl, ctrl);
-
-       if (!ctrl->type)
-               return -EINVAL;
-
-       return 0;
-}
-
-static int vidioc_g_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctrl)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       call_all(usbvision, core, g_ctrl, ctrl);
-       return 0;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-                               struct v4l2_control *ctrl)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       call_all(usbvision, core, s_ctrl, ctrl);
-       return 0;
-}
-
-static int vidioc_reqbufs(struct file *file,
-                          void *priv, struct v4l2_requestbuffers *vr)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       int ret;
-
-       RESTRICT_TO_RANGE(vr->count, 1, USBVISION_NUMFRAMES);
-
-       /* Check input validity:
-          the user must do a VIDEO CAPTURE and MMAP method. */
-       if (vr->memory != V4L2_MEMORY_MMAP)
-               return -EINVAL;
-
-       if (usbvision->streaming == stream_on) {
-               ret = usbvision_stream_interrupt(usbvision);
-               if (ret)
-                       return ret;
-       }
-
-       usbvision_frames_free(usbvision);
-       usbvision_empty_framequeues(usbvision);
-       vr->count = usbvision_frames_alloc(usbvision, vr->count);
-
-       usbvision->cur_frame = NULL;
-
-       return 0;
-}
-
-static int vidioc_querybuf(struct file *file,
-                           void *priv, struct v4l2_buffer *vb)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       struct usbvision_frame *frame;
-
-       /* FIXME : must control
-          that buffers are mapped (VIDIOC_REQBUFS has been called) */
-       if (vb->index >= usbvision->num_frames)
-               return -EINVAL;
-       /* Updating the corresponding frame state */
-       vb->flags = 0;
-       frame = &usbvision->frame[vb->index];
-       if (frame->grabstate >= frame_state_ready)
-               vb->flags |= V4L2_BUF_FLAG_QUEUED;
-       if (frame->grabstate >= frame_state_done)
-               vb->flags |= V4L2_BUF_FLAG_DONE;
-       if (frame->grabstate == frame_state_unused)
-               vb->flags |= V4L2_BUF_FLAG_MAPPED;
-       vb->memory = V4L2_MEMORY_MMAP;
-
-       vb->m.offset = vb->index * PAGE_ALIGN(usbvision->max_frame_size);
-
-       vb->memory = V4L2_MEMORY_MMAP;
-       vb->field = V4L2_FIELD_NONE;
-       vb->length = usbvision->curwidth *
-               usbvision->curheight *
-               usbvision->palette.bytes_per_pixel;
-       vb->timestamp = usbvision->frame[vb->index].timestamp;
-       vb->sequence = usbvision->frame[vb->index].sequence;
-       return 0;
-}
-
-static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *vb)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       struct usbvision_frame *frame;
-       unsigned long lock_flags;
-
-       /* FIXME : works only on VIDEO_CAPTURE MODE, MMAP. */
-       if (vb->index >= usbvision->num_frames)
-               return -EINVAL;
-
-       frame = &usbvision->frame[vb->index];
-
-       if (frame->grabstate != frame_state_unused)
-               return -EAGAIN;
-
-       /* Mark it as ready and enqueue frame */
-       frame->grabstate = frame_state_ready;
-       frame->scanstate = scan_state_scanning;
-       frame->scanlength = 0;  /* Accumulated in usbvision_parse_data() */
-
-       vb->flags &= ~V4L2_BUF_FLAG_DONE;
-
-       /* set v4l2_format index */
-       frame->v4l2_format = usbvision->palette;
-
-       spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
-       list_add_tail(&usbvision->frame[vb->index].frame, &usbvision->inqueue);
-       spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
-
-       return 0;
-}
-
-static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *vb)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       int ret;
-       struct usbvision_frame *f;
-       unsigned long lock_flags;
-
-       if (list_empty(&(usbvision->outqueue))) {
-               if (usbvision->streaming == stream_idle)
-                       return -EINVAL;
-               ret = wait_event_interruptible
-                       (usbvision->wait_frame,
-                        !list_empty(&(usbvision->outqueue)));
-               if (ret)
-                       return ret;
-       }
-
-       spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
-       f = list_entry(usbvision->outqueue.next,
-                      struct usbvision_frame, frame);
-       list_del(usbvision->outqueue.next);
-       spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
-
-       f->grabstate = frame_state_unused;
-
-       vb->memory = V4L2_MEMORY_MMAP;
-       vb->flags = V4L2_BUF_FLAG_MAPPED |
-               V4L2_BUF_FLAG_QUEUED |
-               V4L2_BUF_FLAG_DONE;
-       vb->index = f->index;
-       vb->sequence = f->sequence;
-       vb->timestamp = f->timestamp;
-       vb->field = V4L2_FIELD_NONE;
-       vb->bytesused = f->scanlength;
-
-       return 0;
-}
-
-static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       usbvision->streaming = stream_on;
-       call_all(usbvision, video, s_stream, 1);
-
-       return 0;
-}
-
-static int vidioc_streamoff(struct file *file,
-                           void *priv, enum v4l2_buf_type type)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               return -EINVAL;
-
-       if (usbvision->streaming == stream_on) {
-               usbvision_stream_interrupt(usbvision);
-               /* Stop all video streamings */
-               call_all(usbvision, video, s_stream, 0);
-       }
-       usbvision_empty_framequeues(usbvision);
-
-       return 0;
-}
-
-static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
-                                       struct v4l2_fmtdesc *vfd)
-{
-       if (vfd->index >= USBVISION_SUPPORTED_PALETTES - 1)
-               return -EINVAL;
-       strcpy(vfd->description, usbvision_v4l2_format[vfd->index].desc);
-       vfd->pixelformat = usbvision_v4l2_format[vfd->index].format;
-       return 0;
-}
-
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
-                                       struct v4l2_format *vf)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       vf->fmt.pix.width = usbvision->curwidth;
-       vf->fmt.pix.height = usbvision->curheight;
-       vf->fmt.pix.pixelformat = usbvision->palette.format;
-       vf->fmt.pix.bytesperline =
-               usbvision->curwidth * usbvision->palette.bytes_per_pixel;
-       vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline * usbvision->curheight;
-       vf->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-       vf->fmt.pix.field = V4L2_FIELD_NONE; /* Always progressive image */
-
-       return 0;
-}
-
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
-                              struct v4l2_format *vf)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       int format_idx;
-
-       /* Find requested format in available ones */
-       for (format_idx = 0; format_idx < USBVISION_SUPPORTED_PALETTES; format_idx++) {
-               if (vf->fmt.pix.pixelformat ==
-                  usbvision_v4l2_format[format_idx].format) {
-                       usbvision->palette = usbvision_v4l2_format[format_idx];
-                       break;
-               }
-       }
-       /* robustness */
-       if (format_idx == USBVISION_SUPPORTED_PALETTES)
-               return -EINVAL;
-       RESTRICT_TO_RANGE(vf->fmt.pix.width, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
-       RESTRICT_TO_RANGE(vf->fmt.pix.height, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT);
-
-       vf->fmt.pix.bytesperline = vf->fmt.pix.width*
-               usbvision->palette.bytes_per_pixel;
-       vf->fmt.pix.sizeimage = vf->fmt.pix.bytesperline*vf->fmt.pix.height;
-
-       return 0;
-}
-
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
-                              struct v4l2_format *vf)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       int ret;
-
-       ret = vidioc_try_fmt_vid_cap(file, priv, vf);
-       if (ret)
-               return ret;
-
-       /* stop io in case it is already in progress */
-       if (usbvision->streaming == stream_on) {
-               ret = usbvision_stream_interrupt(usbvision);
-               if (ret)
-                       return ret;
-       }
-       usbvision_frames_free(usbvision);
-       usbvision_empty_framequeues(usbvision);
-
-       usbvision->cur_frame = NULL;
-
-       /* by now we are committed to the new data... */
-       usbvision_set_output(usbvision, vf->fmt.pix.width, vf->fmt.pix.height);
-
-       return 0;
-}
-
-static ssize_t usbvision_read(struct file *file, char __user *buf,
-                     size_t count, loff_t *ppos)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       int noblock = file->f_flags & O_NONBLOCK;
-       unsigned long lock_flags;
-       int ret, i;
-       struct usbvision_frame *frame;
-
-       PDEBUG(DBG_IO, "%s: %ld bytes, noblock=%d", __func__,
-              (unsigned long)count, noblock);
-
-       if (!USBVISION_IS_OPERATIONAL(usbvision) || (buf == NULL))
-               return -EFAULT;
-
-       /* This entry point is compatible with the mmap routines
-          so that a user can do either VIDIOC_QBUF/VIDIOC_DQBUF
-          to get frames or call read on the device. */
-       if (!usbvision->num_frames) {
-               /* First, allocate some frames to work with
-                  if this has not been done with VIDIOC_REQBUF */
-               usbvision_frames_free(usbvision);
-               usbvision_empty_framequeues(usbvision);
-               usbvision_frames_alloc(usbvision, USBVISION_NUMFRAMES);
-       }
-
-       if (usbvision->streaming != stream_on) {
-               /* no stream is running, make it running ! */
-               usbvision->streaming = stream_on;
-               call_all(usbvision, video, s_stream, 1);
-       }
-
-       /* Then, enqueue as many frames as possible
-          (like a user of VIDIOC_QBUF would do) */
-       for (i = 0; i < usbvision->num_frames; i++) {
-               frame = &usbvision->frame[i];
-               if (frame->grabstate == frame_state_unused) {
-                       /* Mark it as ready and enqueue frame */
-                       frame->grabstate = frame_state_ready;
-                       frame->scanstate = scan_state_scanning;
-                       /* Accumulated in usbvision_parse_data() */
-                       frame->scanlength = 0;
-
-                       /* set v4l2_format index */
-                       frame->v4l2_format = usbvision->palette;
-
-                       spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
-                       list_add_tail(&frame->frame, &usbvision->inqueue);
-                       spin_unlock_irqrestore(&usbvision->queue_lock,
-                                              lock_flags);
-               }
-       }
-
-       /* Then try to steal a frame (like a VIDIOC_DQBUF would do) */
-       if (list_empty(&(usbvision->outqueue))) {
-               if (noblock)
-                       return -EAGAIN;
-
-               ret = wait_event_interruptible
-                       (usbvision->wait_frame,
-                        !list_empty(&(usbvision->outqueue)));
-               if (ret)
-                       return ret;
-       }
-
-       spin_lock_irqsave(&usbvision->queue_lock, lock_flags);
-       frame = list_entry(usbvision->outqueue.next,
-                          struct usbvision_frame, frame);
-       list_del(usbvision->outqueue.next);
-       spin_unlock_irqrestore(&usbvision->queue_lock, lock_flags);
-
-       /* An error returns an empty frame */
-       if (frame->grabstate == frame_state_error) {
-               frame->bytes_read = 0;
-               return 0;
-       }
-
-       PDEBUG(DBG_IO, "%s: frmx=%d, bytes_read=%ld, scanlength=%ld",
-              __func__,
-              frame->index, frame->bytes_read, frame->scanlength);
-
-       /* copy bytes to user space; we allow for partials reads */
-       if ((count + frame->bytes_read) > (unsigned long)frame->scanlength)
-               count = frame->scanlength - frame->bytes_read;
-
-       if (copy_to_user(buf, frame->data + frame->bytes_read, count))
-               return -EFAULT;
-
-       frame->bytes_read += count;
-       PDEBUG(DBG_IO, "%s: {copy} count used=%ld, new bytes_read=%ld",
-              __func__,
-              (unsigned long)count, frame->bytes_read);
-
-       /* For now, forget the frame if it has not been read in one shot. */
-/*     if (frame->bytes_read >= frame->scanlength) {*/ /* All data has been read */
-               frame->bytes_read = 0;
-
-               /* Mark it as available to be used again. */
-               frame->grabstate = frame_state_unused;
-/*     } */
-
-       return count;
-}
-
-static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
-                     size_t count, loff_t *ppos)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       int res;
-
-       if (mutex_lock_interruptible(&usbvision->v4l2_lock))
-               return -ERESTARTSYS;
-       res = usbvision_read(file, buf, count, ppos);
-       mutex_unlock(&usbvision->v4l2_lock);
-       return res;
-}
-
-static int usbvision_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       unsigned long size = vma->vm_end - vma->vm_start,
-               start = vma->vm_start;
-       void *pos;
-       u32 i;
-       struct usb_usbvision *usbvision = video_drvdata(file);
-
-       PDEBUG(DBG_MMAP, "mmap");
-
-       if (!USBVISION_IS_OPERATIONAL(usbvision))
-               return -EFAULT;
-
-       if (!(vma->vm_flags & VM_WRITE) ||
-           size != PAGE_ALIGN(usbvision->max_frame_size)) {
-               return -EINVAL;
-       }
-
-       for (i = 0; i < usbvision->num_frames; i++) {
-               if (((PAGE_ALIGN(usbvision->max_frame_size)*i) >> PAGE_SHIFT) ==
-                   vma->vm_pgoff)
-                       break;
-       }
-       if (i == usbvision->num_frames) {
-               PDEBUG(DBG_MMAP,
-                      "mmap: user supplied mapping address is out of range");
-               return -EINVAL;
-       }
-
-       /* VM_IO is eventually going to replace PageReserved altogether */
-       vma->vm_flags |= VM_IO;
-       vma->vm_flags |= VM_RESERVED;   /* avoid to swap out this VMA */
-
-       pos = usbvision->frame[i].data;
-       while (size > 0) {
-               if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
-                       PDEBUG(DBG_MMAP, "mmap: vm_insert_page failed");
-                       return -EAGAIN;
-               }
-               start += PAGE_SIZE;
-               pos += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-
-       return 0;
-}
-
-static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       int res;
-
-       if (mutex_lock_interruptible(&usbvision->v4l2_lock))
-               return -ERESTARTSYS;
-       res = usbvision_mmap(file, vma);
-       mutex_unlock(&usbvision->v4l2_lock);
-       return res;
-}
-
-/*
- * Here comes the stuff for radio on usbvision based devices
- *
- */
-static int usbvision_radio_open(struct file *file)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       int err_code = 0;
-
-       PDEBUG(DBG_IO, "%s:", __func__);
-
-       if (mutex_lock_interruptible(&usbvision->v4l2_lock))
-               return -ERESTARTSYS;
-       if (usbvision->user) {
-               dev_err(&usbvision->rdev->dev,
-                       "%s: Someone tried to open an already opened USBVision Radio!\n",
-                               __func__);
-               err_code = -EBUSY;
-       } else {
-               if (power_on_at_open) {
-                       usbvision_reset_power_off_timer(usbvision);
-                       if (usbvision->power == 0) {
-                               usbvision_power_on(usbvision);
-                               usbvision_i2c_register(usbvision);
-                       }
-               }
-
-               /* Alternate interface 1 is is the biggest frame size */
-               err_code = usbvision_set_alternate(usbvision);
-               if (err_code < 0) {
-                       usbvision->last_error = err_code;
-                       err_code = -EBUSY;
-                       goto out;
-               }
-
-               /* If so far no errors then we shall start the radio */
-               usbvision->radio = 1;
-               call_all(usbvision, tuner, s_radio);
-               usbvision_set_audio(usbvision, USBVISION_AUDIO_RADIO);
-               usbvision->user++;
-       }
-
-       if (err_code) {
-               if (power_on_at_open) {
-                       usbvision_i2c_unregister(usbvision);
-                       usbvision_power_off(usbvision);
-                       usbvision->initialized = 0;
-               }
-       }
-out:
-       mutex_unlock(&usbvision->v4l2_lock);
-       return err_code;
-}
-
-
-static int usbvision_radio_close(struct file *file)
-{
-       struct usb_usbvision *usbvision = video_drvdata(file);
-       int err_code = 0;
-
-       PDEBUG(DBG_IO, "");
-
-       mutex_lock(&usbvision->v4l2_lock);
-       /* Set packet size to 0 */
-       usbvision->iface_alt = 0;
-       err_code = usb_set_interface(usbvision->dev, usbvision->iface,
-                                   usbvision->iface_alt);
-
-       usbvision_audio_off(usbvision);
-       usbvision->radio = 0;
-       usbvision->user--;
-
-       if (power_on_at_open) {
-               usbvision_set_power_off_timer(usbvision);
-               usbvision->initialized = 0;
-       }
-
-       if (usbvision->remove_pending) {
-               printk(KERN_INFO "%s: Final disconnect\n", __func__);
-               usbvision_release(usbvision);
-       }
-
-       mutex_unlock(&usbvision->v4l2_lock);
-       PDEBUG(DBG_IO, "success");
-       return err_code;
-}
-
-/* Video registration stuff */
-
-/* Video template */
-static const struct v4l2_file_operations usbvision_fops = {
-       .owner             = THIS_MODULE,
-       .open           = usbvision_v4l2_open,
-       .release        = usbvision_v4l2_close,
-       .read           = usbvision_v4l2_read,
-       .mmap           = usbvision_v4l2_mmap,
-       .unlocked_ioctl = video_ioctl2,
-/*     .poll           = video_poll, */
-};
-
-static const struct v4l2_ioctl_ops usbvision_ioctl_ops = {
-       .vidioc_querycap      = vidioc_querycap,
-       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
-       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
-       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
-       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
-       .vidioc_reqbufs       = vidioc_reqbufs,
-       .vidioc_querybuf      = vidioc_querybuf,
-       .vidioc_qbuf          = vidioc_qbuf,
-       .vidioc_dqbuf         = vidioc_dqbuf,
-       .vidioc_s_std         = vidioc_s_std,
-       .vidioc_enum_input    = vidioc_enum_input,
-       .vidioc_g_input       = vidioc_g_input,
-       .vidioc_s_input       = vidioc_s_input,
-       .vidioc_queryctrl     = vidioc_queryctrl,
-       .vidioc_g_audio       = vidioc_g_audio,
-       .vidioc_s_audio       = vidioc_s_audio,
-       .vidioc_g_ctrl        = vidioc_g_ctrl,
-       .vidioc_s_ctrl        = vidioc_s_ctrl,
-       .vidioc_streamon      = vidioc_streamon,
-       .vidioc_streamoff     = vidioc_streamoff,
-       .vidioc_g_tuner       = vidioc_g_tuner,
-       .vidioc_s_tuner       = vidioc_s_tuner,
-       .vidioc_g_frequency   = vidioc_g_frequency,
-       .vidioc_s_frequency   = vidioc_s_frequency,
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-       .vidioc_g_register    = vidioc_g_register,
-       .vidioc_s_register    = vidioc_s_register,
-#endif
-};
-
-static struct video_device usbvision_video_template = {
-       .fops           = &usbvision_fops,
-       .ioctl_ops      = &usbvision_ioctl_ops,
-       .name           = "usbvision-video",
-       .release        = video_device_release,
-       .tvnorms        = USBVISION_NORMS,
-       .current_norm   = V4L2_STD_PAL
-};
-
-
-/* Radio template */
-static const struct v4l2_file_operations usbvision_radio_fops = {
-       .owner             = THIS_MODULE,
-       .open           = usbvision_radio_open,
-       .release        = usbvision_radio_close,
-       .unlocked_ioctl = video_ioctl2,
-};
-
-static const struct v4l2_ioctl_ops usbvision_radio_ioctl_ops = {
-       .vidioc_querycap      = vidioc_querycap,
-       .vidioc_enum_input    = vidioc_enum_input,
-       .vidioc_g_input       = vidioc_g_input,
-       .vidioc_s_input       = vidioc_s_input,
-       .vidioc_queryctrl     = vidioc_queryctrl,
-       .vidioc_g_audio       = vidioc_g_audio,
-       .vidioc_s_audio       = vidioc_s_audio,
-       .vidioc_g_ctrl        = vidioc_g_ctrl,
-       .vidioc_s_ctrl        = vidioc_s_ctrl,
-       .vidioc_g_tuner       = vidioc_g_tuner,
-       .vidioc_s_tuner       = vidioc_s_tuner,
-       .vidioc_g_frequency   = vidioc_g_frequency,
-       .vidioc_s_frequency   = vidioc_s_frequency,
-};
-
-static struct video_device usbvision_radio_template = {
-       .fops           = &usbvision_radio_fops,
-       .name           = "usbvision-radio",
-       .release        = video_device_release,
-       .ioctl_ops      = &usbvision_radio_ioctl_ops,
-
-       .tvnorms              = USBVISION_NORMS,
-       .current_norm         = V4L2_STD_PAL
-};
-
-
-static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision,
-                                       struct video_device *vdev_template,
-                                       char *name)
-{
-       struct usb_device *usb_dev = usbvision->dev;
-       struct video_device *vdev;
-
-       if (usb_dev == NULL) {
-               dev_err(&usbvision->dev->dev,
-                       "%s: usbvision->dev is not set\n", __func__);
-               return NULL;
-       }
-
-       vdev = video_device_alloc();
-       if (NULL == vdev)
-               return NULL;
-       *vdev = *vdev_template;
-       vdev->lock = &usbvision->v4l2_lock;
-       vdev->v4l2_dev = &usbvision->v4l2_dev;
-       snprintf(vdev->name, sizeof(vdev->name), "%s", name);
-       video_set_drvdata(vdev, usbvision);
-       return vdev;
-}
-
-/* unregister video4linux devices */
-static void usbvision_unregister_video(struct usb_usbvision *usbvision)
-{
-       /* Radio Device: */
-       if (usbvision->rdev) {
-               PDEBUG(DBG_PROBE, "unregister %s [v4l2]",
-                      video_device_node_name(usbvision->rdev));
-               if (video_is_registered(usbvision->rdev))
-                       video_unregister_device(usbvision->rdev);
-               else
-                       video_device_release(usbvision->rdev);
-               usbvision->rdev = NULL;
-       }
-
-       /* Video Device: */
-       if (usbvision->vdev) {
-               PDEBUG(DBG_PROBE, "unregister %s [v4l2]",
-                      video_device_node_name(usbvision->vdev));
-               if (video_is_registered(usbvision->vdev))
-                       video_unregister_device(usbvision->vdev);
-               else
-                       video_device_release(usbvision->vdev);
-               usbvision->vdev = NULL;
-       }
-}
-
-/* register video4linux devices */
-static int __devinit usbvision_register_video(struct usb_usbvision *usbvision)
-{
-       /* Video Device: */
-       usbvision->vdev = usbvision_vdev_init(usbvision,
-                                             &usbvision_video_template,
-                                             "USBVision Video");
-       if (usbvision->vdev == NULL)
-               goto err_exit;
-       if (video_register_device(usbvision->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
-               goto err_exit;
-       printk(KERN_INFO "USBVision[%d]: registered USBVision Video device %s [v4l2]\n",
-              usbvision->nr, video_device_node_name(usbvision->vdev));
-
-       /* Radio Device: */
-       if (usbvision_device_data[usbvision->dev_model].radio) {
-               /* usbvision has radio */
-               usbvision->rdev = usbvision_vdev_init(usbvision,
-                                                     &usbvision_radio_template,
-                                                     "USBVision Radio");
-               if (usbvision->rdev == NULL)
-                       goto err_exit;
-               if (video_register_device(usbvision->rdev, VFL_TYPE_RADIO, radio_nr) < 0)
-                       goto err_exit;
-               printk(KERN_INFO "USBVision[%d]: registered USBVision Radio device %s [v4l2]\n",
-                      usbvision->nr, video_device_node_name(usbvision->rdev));
-       }
-       /* all done */
-       return 0;
-
- err_exit:
-       dev_err(&usbvision->dev->dev,
-               "USBVision[%d]: video_register_device() failed\n",
-                       usbvision->nr);
-       usbvision_unregister_video(usbvision);
-       return -1;
-}
-
-/*
- * usbvision_alloc()
- *
- * This code allocates the struct usb_usbvision.
- * It is filled with default values.
- *
- * Returns NULL on error, a pointer to usb_usbvision else.
- *
- */
-static struct usb_usbvision *usbvision_alloc(struct usb_device *dev,
-                                            struct usb_interface *intf)
-{
-       struct usb_usbvision *usbvision;
-
-       usbvision = kzalloc(sizeof(struct usb_usbvision), GFP_KERNEL);
-       if (usbvision == NULL)
-               return NULL;
-
-       usbvision->dev = dev;
-       if (v4l2_device_register(&intf->dev, &usbvision->v4l2_dev))
-               goto err_free;
-
-       mutex_init(&usbvision->v4l2_lock);
-
-       /* prepare control urb for control messages during interrupts */
-       usbvision->ctrl_urb = usb_alloc_urb(USBVISION_URB_FRAMES, GFP_KERNEL);
-       if (usbvision->ctrl_urb == NULL)
-               goto err_unreg;
-       init_waitqueue_head(&usbvision->ctrl_urb_wq);
-
-       usbvision_init_power_off_timer(usbvision);
-
-       return usbvision;
-
-err_unreg:
-       v4l2_device_unregister(&usbvision->v4l2_dev);
-err_free:
-       kfree(usbvision);
-       return NULL;
-}
-
-/*
- * usbvision_release()
- *
- * This code does final release of struct usb_usbvision. This happens
- * after the device is disconnected -and- all clients closed their files.
- *
- */
-static void usbvision_release(struct usb_usbvision *usbvision)
-{
-       PDEBUG(DBG_PROBE, "");
-
-       usbvision_reset_power_off_timer(usbvision);
-
-       usbvision->initialized = 0;
-
-       usbvision_remove_sysfs(usbvision->vdev);
-       usbvision_unregister_video(usbvision);
-
-       usb_free_urb(usbvision->ctrl_urb);
-
-       v4l2_device_unregister(&usbvision->v4l2_dev);
-       kfree(usbvision);
-
-       PDEBUG(DBG_PROBE, "success");
-}
-
-
-/*********************** usb interface **********************************/
-
-static void usbvision_configure_video(struct usb_usbvision *usbvision)
-{
-       int model;
-
-       if (usbvision == NULL)
-               return;
-
-       model = usbvision->dev_model;
-       usbvision->palette = usbvision_v4l2_format[2]; /* V4L2_PIX_FMT_RGB24; */
-
-       if (usbvision_device_data[usbvision->dev_model].vin_reg2_override) {
-               usbvision->vin_reg2_preset =
-                       usbvision_device_data[usbvision->dev_model].vin_reg2;
-       } else {
-               usbvision->vin_reg2_preset = 0;
-       }
-
-       usbvision->tvnorm_id = usbvision_device_data[model].video_norm;
-
-       usbvision->video_inputs = usbvision_device_data[model].video_channels;
-       usbvision->ctl_input = 0;
-
-       /* This should be here to make i2c clients to be able to register */
-       /* first switch off audio */
-       if (usbvision_device_data[model].audio_channels > 0)
-               usbvision_audio_off(usbvision);
-       if (!power_on_at_open) {
-               /* and then power up the noisy tuner */
-               usbvision_power_on(usbvision);
-               usbvision_i2c_register(usbvision);
-       }
-}
-
-/*
- * usbvision_probe()
- *
- * This procedure queries device descriptor and accepts the interface
- * if it looks like USBVISION video device
- *
- */
-static int __devinit usbvision_probe(struct usb_interface *intf,
-                                    const struct usb_device_id *devid)
-{
-       struct usb_device *dev = usb_get_dev(interface_to_usbdev(intf));
-       struct usb_interface *uif;
-       __u8 ifnum = intf->altsetting->desc.bInterfaceNumber;
-       const struct usb_host_interface *interface;
-       struct usb_usbvision *usbvision = NULL;
-       const struct usb_endpoint_descriptor *endpoint;
-       int model, i;
-
-       PDEBUG(DBG_PROBE, "VID=%#04x, PID=%#04x, ifnum=%u",
-                               dev->descriptor.idVendor,
-                               dev->descriptor.idProduct, ifnum);
-
-       model = devid->driver_info;
-       if (model < 0 || model >= usbvision_device_data_size) {
-               PDEBUG(DBG_PROBE, "model out of bounds %d", model);
-               return -ENODEV;
-       }
-       printk(KERN_INFO "%s: %s found\n", __func__,
-                               usbvision_device_data[model].model_string);
-
-       if (usbvision_device_data[model].interface >= 0)
-               interface = &dev->actconfig->interface[usbvision_device_data[model].interface]->altsetting[0];
-       else
-               interface = &dev->actconfig->interface[ifnum]->altsetting[0];
-       endpoint = &interface->endpoint[1].desc;
-       if (!usb_endpoint_xfer_isoc(endpoint)) {
-               dev_err(&intf->dev, "%s: interface %d. has non-ISO endpoint!\n",
-                   __func__, ifnum);
-               dev_err(&intf->dev, "%s: Endpoint attributes %d",
-                   __func__, endpoint->bmAttributes);
-               return -ENODEV;
-       }
-       if (usb_endpoint_dir_out(endpoint)) {
-               dev_err(&intf->dev, "%s: interface %d. has ISO OUT endpoint!\n",
-                   __func__, ifnum);
-               return -ENODEV;
-       }
-
-       usbvision = usbvision_alloc(dev, intf);
-       if (usbvision == NULL) {
-               dev_err(&intf->dev, "%s: couldn't allocate USBVision struct\n", __func__);
-               return -ENOMEM;
-       }
-
-       if (dev->descriptor.bNumConfigurations > 1)
-               usbvision->bridge_type = BRIDGE_NT1004;
-       else if (model == DAZZLE_DVC_90_REV_1_SECAM)
-               usbvision->bridge_type = BRIDGE_NT1005;
-       else
-               usbvision->bridge_type = BRIDGE_NT1003;
-       PDEBUG(DBG_PROBE, "bridge_type %d", usbvision->bridge_type);
-
-       /* compute alternate max packet sizes */
-       uif = dev->actconfig->interface[0];
-
-       usbvision->num_alt = uif->num_altsetting;
-       PDEBUG(DBG_PROBE, "Alternate settings: %i", usbvision->num_alt);
-       usbvision->alt_max_pkt_size = kmalloc(32 * usbvision->num_alt, GFP_KERNEL);
-       if (usbvision->alt_max_pkt_size == NULL) {
-               dev_err(&intf->dev, "usbvision: out of memory!\n");
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < usbvision->num_alt; i++) {
-               u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[1].desc.
-                                     wMaxPacketSize);
-               usbvision->alt_max_pkt_size[i] =
-                       (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
-               PDEBUG(DBG_PROBE, "Alternate setting %i, max size= %i", i,
-                      usbvision->alt_max_pkt_size[i]);
-       }
-
-
-       usbvision->nr = usbvision_nr++;
-
-       usbvision->have_tuner = usbvision_device_data[model].tuner;
-       if (usbvision->have_tuner)
-               usbvision->tuner_type = usbvision_device_data[model].tuner_type;
-
-       usbvision->dev_model = model;
-       usbvision->remove_pending = 0;
-       usbvision->iface = ifnum;
-       usbvision->iface_alt = 0;
-       usbvision->video_endp = endpoint->bEndpointAddress;
-       usbvision->isoc_packet_size = 0;
-       usbvision->usb_bandwidth = 0;
-       usbvision->user = 0;
-       usbvision->streaming = stream_off;
-       usbvision_configure_video(usbvision);
-       usbvision_register_video(usbvision);
-
-       usbvision_create_sysfs(usbvision->vdev);
-
-       PDEBUG(DBG_PROBE, "success");
-       return 0;
-}
-
-
-/*
- * usbvision_disconnect()
- *
- * This procedure stops all driver activity, deallocates interface-private
- * structure (pointed by 'ptr') and after that driver should be removable
- * with no ill consequences.
- *
- */
-static void __devexit usbvision_disconnect(struct usb_interface *intf)
-{
-       struct usb_usbvision *usbvision = to_usbvision(usb_get_intfdata(intf));
-
-       PDEBUG(DBG_PROBE, "");
-
-       if (usbvision == NULL) {
-               pr_err("%s: usb_get_intfdata() failed\n", __func__);
-               return;
-       }
-
-       mutex_lock(&usbvision->v4l2_lock);
-
-       /* At this time we ask to cancel outstanding URBs */
-       usbvision_stop_isoc(usbvision);
-
-       v4l2_device_disconnect(&usbvision->v4l2_dev);
-
-       if (usbvision->power) {
-               usbvision_i2c_unregister(usbvision);
-               usbvision_power_off(usbvision);
-       }
-       usbvision->remove_pending = 1;  /* Now all ISO data will be ignored */
-
-       usb_put_dev(usbvision->dev);
-       usbvision->dev = NULL;  /* USB device is no more */
-
-       mutex_unlock(&usbvision->v4l2_lock);
-
-       if (usbvision->user) {
-               printk(KERN_INFO "%s: In use, disconnect pending\n",
-                      __func__);
-               wake_up_interruptible(&usbvision->wait_frame);
-               wake_up_interruptible(&usbvision->wait_stream);
-       } else {
-               usbvision_release(usbvision);
-       }
-
-       PDEBUG(DBG_PROBE, "success");
-}
-
-static struct usb_driver usbvision_driver = {
-       .name           = "usbvision",
-       .id_table       = usbvision_table,
-       .probe          = usbvision_probe,
-       .disconnect     = __devexit_p(usbvision_disconnect),
-};
-
-/*
- * usbvision_init()
- *
- * This code is run to initialize the driver.
- *
- */
-static int __init usbvision_init(void)
-{
-       int err_code;
-
-       PDEBUG(DBG_PROBE, "");
-
-       PDEBUG(DBG_IO,  "IO      debugging is enabled [video]");
-       PDEBUG(DBG_PROBE, "PROBE   debugging is enabled [video]");
-       PDEBUG(DBG_MMAP, "MMAP    debugging is enabled [video]");
-
-       /* disable planar mode support unless compression enabled */
-       if (isoc_mode != ISOC_MODE_COMPRESS) {
-               /* FIXME : not the right way to set supported flag */
-               usbvision_v4l2_format[6].supported = 0; /* V4L2_PIX_FMT_YVU420 */
-               usbvision_v4l2_format[7].supported = 0; /* V4L2_PIX_FMT_YUV422P */
-       }
-
-       err_code = usb_register(&usbvision_driver);
-
-       if (err_code == 0) {
-               printk(KERN_INFO DRIVER_DESC " : " USBVISION_VERSION_STRING "\n");
-               PDEBUG(DBG_PROBE, "success");
-       }
-       return err_code;
-}
-
-static void __exit usbvision_exit(void)
-{
-       PDEBUG(DBG_PROBE, "");
-
-       usb_deregister(&usbvision_driver);
-       PDEBUG(DBG_PROBE, "success");
-}
-
-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/video/usbvision/usbvision.h b/drivers/media/video/usbvision/usbvision.h
deleted file mode 100644 (file)
index 43cf61f..0000000
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * USBVISION.H
- *  usbvision header file
- *
- * Copyright (c) 1999-2005 Joerg Heckenbach <joerg@heckenbach-aw.de>
- *                         Dwaine Garden <dwainegarden@rogers.com>
- *
- *
- * Report problems to v4l MailingList: linux-media@vger.kernel.org
- *
- * This module is part of usbvision driver project.
- * Updates to driver completed by Dwaine P. Garden
- * v4l2 conversion by Thierry Merle <thierry.merle@free.fr>
- *
- * 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.
- */
-
-
-#ifndef __LINUX_USBVISION_H
-#define __LINUX_USBVISION_H
-
-#include <linux/list.h>
-#include <linux/usb.h>
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <media/v4l2-device.h>
-#include <media/tuner.h>
-#include <linux/videodev2.h>
-
-#define USBVISION_DEBUG                /* Turn on debug messages */
-
-#define USBVISION_PWR_REG              0x00
-       #define USBVISION_SSPND_EN              (1 << 1)
-       #define USBVISION_RES2                  (1 << 2)
-       #define USBVISION_PWR_VID               (1 << 5)
-       #define USBVISION_E2_EN                 (1 << 7)
-#define USBVISION_CONFIG_REG           0x01
-#define USBVISION_ADRS_REG             0x02
-#define USBVISION_ALTER_REG            0x03
-#define USBVISION_FORCE_ALTER_REG      0x04
-#define USBVISION_STATUS_REG           0x05
-#define USBVISION_IOPIN_REG            0x06
-       #define USBVISION_IO_1                  (1 << 0)
-       #define USBVISION_IO_2                  (1 << 1)
-       #define USBVISION_AUDIO_IN              0
-       #define USBVISION_AUDIO_TV              1
-       #define USBVISION_AUDIO_RADIO           2
-       #define USBVISION_AUDIO_MUTE            3
-#define USBVISION_SER_MODE             0x07
-       #define USBVISION_CLK_OUT               (1 << 0)
-       #define USBVISION_DAT_IO                (1 << 1)
-       #define USBVISION_SENS_OUT              (1 << 2)
-       #define USBVISION_SER_MODE_SOFT         (0 << 4)
-       #define USBVISION_SER_MODE_SIO          (1 << 4)
-#define USBVISION_SER_ADRS             0x08
-#define USBVISION_SER_CONT             0x09
-#define USBVISION_SER_DAT1             0x0A
-#define USBVISION_SER_DAT2             0x0B
-#define USBVISION_SER_DAT3             0x0C
-#define USBVISION_SER_DAT4             0x0D
-#define USBVISION_EE_DATA              0x0E
-#define USBVISION_EE_LSBAD             0x0F
-#define USBVISION_EE_CONT              0x10
-#define USBVISION_DRM_CONT                     0x12
-       #define USBVISION_REF                   (1 << 0)
-       #define USBVISION_RES_UR                (1 << 2)
-       #define USBVISION_RES_FDL               (1 << 3)
-       #define USBVISION_RES_VDW               (1 << 4)
-#define USBVISION_DRM_PRM1             0x13
-#define USBVISION_DRM_PRM2             0x14
-#define USBVISION_DRM_PRM3             0x15
-#define USBVISION_DRM_PRM4             0x16
-#define USBVISION_DRM_PRM5             0x17
-#define USBVISION_DRM_PRM6             0x18
-#define USBVISION_DRM_PRM7             0x19
-#define USBVISION_DRM_PRM8             0x1A
-#define USBVISION_VIN_REG1             0x1B
-       #define USBVISION_8_422_SYNC            0x01
-       #define USBVISION_16_422_SYNC           0x02
-       #define USBVISION_VSNC_POL              (1 << 3)
-       #define USBVISION_HSNC_POL              (1 << 4)
-       #define USBVISION_FID_POL               (1 << 5)
-       #define USBVISION_HVALID_PO             (1 << 6)
-       #define USBVISION_VCLK_POL              (1 << 7)
-#define USBVISION_VIN_REG2             0x1C
-       #define USBVISION_AUTO_FID              (1 << 0)
-       #define USBVISION_NONE_INTER            (1 << 1)
-       #define USBVISION_NOHVALID              (1 << 2)
-       #define USBVISION_UV_ID                 (1 << 3)
-       #define USBVISION_FIX_2C                (1 << 4)
-       #define USBVISION_SEND_FID              (1 << 5)
-       #define USBVISION_KEEP_BLANK            (1 << 7)
-#define USBVISION_LXSIZE_I             0x1D
-#define USBVISION_MXSIZE_I             0x1E
-#define USBVISION_LYSIZE_I             0x1F
-#define USBVISION_MYSIZE_I             0x20
-#define USBVISION_LX_OFFST             0x21
-#define USBVISION_MX_OFFST             0x22
-#define USBVISION_LY_OFFST             0x23
-#define USBVISION_MY_OFFST             0x24
-#define USBVISION_FRM_RATE             0x25
-#define USBVISION_LXSIZE_O             0x26
-#define USBVISION_MXSIZE_O             0x27
-#define USBVISION_LYSIZE_O             0x28
-#define USBVISION_MYSIZE_O             0x29
-#define USBVISION_FILT_CONT            0x2A
-#define USBVISION_VO_MODE              0x2B
-#define USBVISION_INTRA_CYC            0x2C
-#define USBVISION_STRIP_SZ             0x2D
-#define USBVISION_FORCE_INTRA          0x2E
-#define USBVISION_FORCE_UP             0x2F
-#define USBVISION_BUF_THR              0x30
-#define USBVISION_DVI_YUV              0x31
-#define USBVISION_AUDIO_CONT           0x32
-#define USBVISION_AUD_PK_LEN           0x33
-#define USBVISION_BLK_PK_LEN           0x34
-#define USBVISION_PCM_THR1             0x38
-#define USBVISION_PCM_THR2             0x39
-#define USBVISION_DIST_THR_L           0x3A
-#define USBVISION_DIST_THR_H           0x3B
-#define USBVISION_MAX_DIST_L           0x3C
-#define USBVISION_MAX_DIST_H           0x3D
-#define USBVISION_OP_CODE              0x33
-
-#define MAX_BYTES_PER_PIXEL            4
-
-#define MIN_FRAME_WIDTH                        64
-#define MAX_USB_WIDTH                  320  /* 384 */
-#define MAX_FRAME_WIDTH                        320  /* 384 */                  /* streching sometimes causes crashes*/
-
-#define MIN_FRAME_HEIGHT               48
-#define MAX_USB_HEIGHT                 240  /* 288 */
-#define MAX_FRAME_HEIGHT               240  /* 288 */                  /* Streching sometimes causes crashes*/
-
-#define MAX_FRAME_SIZE                 (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT * MAX_BYTES_PER_PIXEL)
-#define USBVISION_CLIPMASK_SIZE                (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) /* bytesize of clipmask */
-
-#define USBVISION_URB_FRAMES           32
-
-#define USBVISION_NUM_HEADERMARKER     20
-#define USBVISION_NUMFRAMES            3  /* Maximum number of frames an application can get */
-#define USBVISION_NUMSBUF              2 /* Dimensioning the USB S buffering */
-
-#define USBVISION_POWEROFF_TIME                (3 * HZ)                /* 3 seconds */
-
-
-#define FRAMERATE_MIN  0
-#define FRAMERATE_MAX  31
-
-enum {
-       ISOC_MODE_YUV422 = 0x03,
-       ISOC_MODE_YUV420 = 0x14,
-       ISOC_MODE_COMPRESS = 0x60,
-};
-
-/* This macro restricts an int variable to an inclusive range */
-#define RESTRICT_TO_RANGE(v, mi, ma) \
-       { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
-
-/*
- * We use macros to do YUV -> RGB conversion because this is
- * very important for speed and totally unimportant for size.
- *
- * YUV -> RGB Conversion
- * ---------------------
- *
- * B = 1.164*(Y-16)                + 2.018*(V-128)
- * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128)
- * R = 1.164*(Y-16) + 1.596*(U-128)
- *
- * If you fancy integer arithmetics (as you should), hear this:
- *
- * 65536*B = 76284*(Y-16)                + 132252*(V-128)
- * 65536*G = 76284*(Y-16) -  53281*(U-128) -  25625*(V-128)
- * 65536*R = 76284*(Y-16) + 104595*(U-128)
- *
- * Make sure the output values are within [0..255] range.
- */
-#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x)))
-#define YUV_TO_RGB_BY_THE_BOOK(my, mu, mv, mr, mg, mb) { \
-       int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \
-       mm_y = (my) - 16; \
-       mm_u = (mu) - 128; \
-       mm_v = (mv) - 128; \
-       mm_yc = mm_y * 76284; \
-       mm_b = (mm_yc + 132252 * mm_v) >> 16; \
-       mm_g = (mm_yc - 53281 * mm_u - 25625 * mm_v) >> 16; \
-       mm_r = (mm_yc + 104595 * mm_u) >> 16; \
-       mb = LIMIT_RGB(mm_b); \
-       mg = LIMIT_RGB(mm_g); \
-       mr = LIMIT_RGB(mm_r); \
-}
-
-/* Debugging aid */
-#define USBVISION_SAY_AND_WAIT(what) { \
-       wait_queue_head_t wq; \
-       init_waitqueue_head(&wq); \
-       printk(KERN_INFO "Say: %s\n", what); \
-       interruptible_sleep_on_timeout(&wq, HZ * 3); \
-}
-
-/*
- * This macro checks if usbvision is still operational. The 'usbvision'
- * pointer must be valid, usbvision->dev must be valid, we are not
- * removing the device and the device has not erred on us.
- */
-#define USBVISION_IS_OPERATIONAL(udevice) (\
-       (udevice != NULL) && \
-       ((udevice)->dev != NULL) && \
-       ((udevice)->last_error == 0) && \
-       (!(udevice)->remove_pending))
-
-#define I2C_USB_ADAP_MAX       16
-
-#define USBVISION_NORMS (V4L2_STD_PAL | V4L2_STD_NTSC | V4L2_STD_SECAM | V4L2_STD_PAL_M)
-
-/* ----------------------------------------------------------------- */
-/* usbvision video structures                                        */
-/* ----------------------------------------------------------------- */
-enum scan_state {
-       scan_state_scanning,    /* Scanning for header */
-       scan_state_lines        /* Parsing lines */
-};
-
-/* Completion states of the data parser */
-enum parse_state {
-       parse_state_continue,   /* Just parse next item */
-       parse_state_next_frame, /* Frame done, send it to V4L */
-       parse_state_out,        /* Not enough data for frame */
-       parse_state_end_parse   /* End parsing */
-};
-
-enum frame_state {
-       frame_state_unused,     /* Unused (no MCAPTURE) */
-       frame_state_ready,      /* Ready to start grabbing */
-       frame_state_grabbing,   /* In the process of being grabbed into */
-       frame_state_done,       /* Finished grabbing, but not been synced yet */
-       frame_state_done_hold,  /* Are syncing or reading */
-       frame_state_error,      /* Something bad happened while processing */
-};
-
-/* stream states */
-enum stream_state {
-       stream_off,             /* Driver streaming is completely OFF */
-       stream_idle,            /* Driver streaming is ready to be put ON by the application */
-       stream_interrupt,       /* Driver streaming must be interrupted */
-       stream_on,              /* Driver streaming is put ON by the application */
-};
-
-enum isoc_state {
-       isoc_state_in_frame,    /* Isoc packet is member of frame */
-       isoc_state_no_frame,    /* Isoc packet is not member of any frame */
-};
-
-struct usb_device;
-
-struct usbvision_sbuf {
-       char *data;
-       struct urb *urb;
-};
-
-#define USBVISION_MAGIC_1                      0x55
-#define USBVISION_MAGIC_2                      0xAA
-#define USBVISION_HEADER_LENGTH                        0x0c
-#define USBVISION_SAA7111_ADDR                 0x48
-#define USBVISION_SAA7113_ADDR                 0x4a
-#define USBVISION_IIC_LRACK                    0x20
-#define USBVISION_IIC_LRNACK                   0x30
-#define USBVISION_FRAME_FORMAT_PARAM_INTRA     (1<<7)
-
-struct usbvision_v4l2_format_st {
-       int             supported;
-       int             bytes_per_pixel;
-       int             depth;
-       int             format;
-       char            *desc;
-};
-#define USBVISION_SUPPORTED_PALETTES ARRAY_SIZE(usbvision_v4l2_format)
-
-struct usbvision_frame_header {
-       unsigned char magic_1;                          /* 0 magic */
-       unsigned char magic_2;                          /* 1  magic */
-       unsigned char header_length;                    /* 2 */
-       unsigned char frame_num;                        /* 3 */
-       unsigned char frame_phase;                      /* 4 */
-       unsigned char frame_latency;                    /* 5 */
-       unsigned char data_format;                      /* 6 */
-       unsigned char format_param;                     /* 7 */
-       unsigned char frame_width_lo;                   /* 8 */
-       unsigned char frame_width_hi;                   /* 9 */
-       unsigned char frame_height_lo;                  /* 10 */
-       unsigned char frame_height_hi;                  /* 11 */
-       __u16 frame_width;                              /* 8 - 9 after endian correction*/
-       __u16 frame_height;                             /* 10 - 11 after endian correction*/
-};
-
-struct usbvision_frame {
-       char *data;                                     /* Frame buffer */
-       struct usbvision_frame_header isoc_header;      /* Header from stream */
-
-       int width;                                      /* Width application is expecting */
-       int height;                                     /* Height */
-       int index;                                      /* Frame index */
-       int frmwidth;                                   /* Width the frame actually is */
-       int frmheight;                                  /* Height */
-
-       volatile int grabstate;                         /* State of grabbing */
-       int scanstate;                                  /* State of scanning */
-
-       struct list_head frame;
-
-       int curline;                                    /* Line of frame we're working on */
-
-       long scanlength;                                /* uncompressed, raw data length of frame */
-       long bytes_read;                                /* amount of scanlength that has been read from data */
-       struct usbvision_v4l2_format_st v4l2_format;    /* format the user needs*/
-       int v4l2_linesize;                              /* bytes for one videoline*/
-       struct timeval timestamp;
-       int sequence;                                   /* How many video frames we send to user */
-};
-
-#define CODEC_SAA7113  7113
-#define CODEC_SAA7111  7111
-#define CODEC_WEBCAM   3000
-#define BRIDGE_NT1003  1003
-#define BRIDGE_NT1004  1004
-#define BRIDGE_NT1005   1005
-
-struct usbvision_device_data_st {
-       __u64 video_norm;
-       const char *model_string;
-       int interface; /* to handle special interface number like BELKIN and Hauppauge WinTV-USB II */
-       __u16 codec;
-       unsigned video_channels:3;
-       unsigned audio_channels:2;
-       unsigned radio:1;
-       unsigned vbi:1;
-       unsigned tuner:1;
-       unsigned vin_reg1_override:1;   /* Override default value with */
-       unsigned vin_reg2_override:1;   /* vin_reg1, vin_reg2, etc. */
-       unsigned dvi_yuv_override:1;
-       __u8 vin_reg1;
-       __u8 vin_reg2;
-       __u8 dvi_yuv;
-       __u8 tuner_type;
-       __s16 x_offset;
-       __s16 y_offset;
-};
-
-/* Declared on usbvision-cards.c */
-extern struct usbvision_device_data_st usbvision_device_data[];
-extern struct usb_device_id usbvision_table[];
-
-struct usb_usbvision {
-       struct v4l2_device v4l2_dev;
-       struct video_device *vdev;                                      /* Video Device */
-       struct video_device *rdev;                                      /* Radio Device */
-
-       /* i2c Declaration Section*/
-       struct i2c_adapter i2c_adap;
-       int registered_i2c;
-
-       struct urb *ctrl_urb;
-       unsigned char ctrl_urb_buffer[8];
-       int ctrl_urb_busy;
-       struct usb_ctrlrequest ctrl_urb_setup;
-       wait_queue_head_t ctrl_urb_wq;                                  /* Processes waiting */
-
-       /* configuration part */
-       int have_tuner;
-       int tuner_type;
-       int bridge_type;                                                /* NT1003, NT1004, NT1005 */
-       int radio;
-       int video_inputs;                                               /* # of inputs */
-       unsigned long freq;
-       int audio_mute;
-       int audio_channel;
-       int isoc_mode;                                                  /* format of video data for the usb isoc-transfer */
-       unsigned int nr;                                                /* Number of the device */
-
-       /* Device structure */
-       struct usb_device *dev;
-       /* usb transfer */
-       int num_alt;            /* Number of alternative settings */
-       unsigned int *alt_max_pkt_size; /* array of max_packet_size */
-       unsigned char iface;                                            /* Video interface number */
-       unsigned char iface_alt;                                        /* Alt settings */
-       unsigned char vin_reg2_preset;
-       struct mutex v4l2_lock;
-       struct timer_list power_off_timer;
-       struct work_struct power_off_work;
-       int power;                                                      /* is the device powered on? */
-       int user;                                                       /* user count for exclusive use */
-       int initialized;                                                /* Had we already sent init sequence? */
-       int dev_model;                                                  /* What type of USBVISION device we got? */
-       enum stream_state streaming;                                    /* Are we streaming Isochronous? */
-       int last_error;                                                 /* What calamity struck us? */
-       int curwidth;                                                   /* width of the frame the device is currently set to*/
-       int curheight;                                                  /* height of the frame the device is currently set to*/
-       int stretch_width;                                              /* stretch-factor for frame width (from usb to screen)*/
-       int stretch_height;                                             /* stretch-factor for frame height (from usb to screen)*/
-       char *fbuf;                                                     /* Videodev buffer area for mmap*/
-       int max_frame_size;                                             /* Bytes in one video frame */
-       int fbuf_size;                                                  /* Videodev buffer size */
-       spinlock_t queue_lock;                                          /* spinlock for protecting mods on inqueue and outqueue */
-       struct list_head inqueue, outqueue;                             /* queued frame list and ready to dequeue frame list */
-       wait_queue_head_t wait_frame;                                   /* Processes waiting */
-       wait_queue_head_t wait_stream;                                  /* Processes waiting */
-       struct usbvision_frame *cur_frame;                              /* pointer to current frame, set by usbvision_find_header */
-       struct usbvision_frame frame[USBVISION_NUMFRAMES];              /* frame buffer */
-       int num_frames;                                                 /* number of frames allocated */
-       struct usbvision_sbuf sbuf[USBVISION_NUMSBUF];                  /* S buffering */
-       volatile int remove_pending;                                    /* If set then about to exit */
-
-       /* Scratch space from the Isochronous Pipe.*/
-       unsigned char *scratch;
-       int scratch_read_ptr;
-       int scratch_write_ptr;
-       int scratch_headermarker[USBVISION_NUM_HEADERMARKER];
-       int scratch_headermarker_read_ptr;
-       int scratch_headermarker_write_ptr;
-       enum isoc_state isocstate;
-       struct usbvision_v4l2_format_st palette;
-
-       struct v4l2_capability vcap;                                    /* Video capabilities */
-       unsigned int ctl_input;                                         /* selected input */
-       v4l2_std_id tvnorm_id;                                          /* selected tv norm */
-       unsigned char video_endp;                                       /* 0x82 for USBVISION devices based */
-
-       /* Decompression stuff: */
-       unsigned char *intra_frame_buffer;                              /* Buffer for reference frame */
-       int block_pos;                                                  /* for test only */
-       int request_intra;                                              /* 0 = normal; 1 = intra frame is requested; */
-       int last_isoc_frame_num;                                        /* check for lost isoc frames */
-       int isoc_packet_size;                                           /* need to calculate used_bandwidth */
-       int used_bandwidth;                                             /* used bandwidth 0-100%, need to set compr_level */
-       int compr_level;                                                /* How strong (100) or weak (0) is compression */
-       int last_compr_level;                                           /* How strong (100) or weak (0) was compression */
-       int usb_bandwidth;                                              /* Mbit/s */
-
-       /* Statistics that can be overlayed on the screen */
-       unsigned long isoc_urb_count;                   /* How many URBs we received so far */
-       unsigned long urb_length;                       /* Length of last URB */
-       unsigned long isoc_data_count;                  /* How many bytes we received */
-       unsigned long header_count;                     /* How many frame headers we found */
-       unsigned long scratch_ovf_count;                /* How many times we overflowed scratch */
-       unsigned long isoc_skip_count;                  /* How many empty ISO packets received */
-       unsigned long isoc_err_count;                   /* How many bad ISO packets received */
-       unsigned long isoc_packet_count;                /* How many packets we totally got */
-       unsigned long time_in_irq;                      /* How long do we need for interrupt */
-       int isoc_measure_bandwidth_count;
-       int frame_num;                                  /* How many video frames we send to user */
-       int max_strip_len;                              /* How big is the biggest strip */
-       int comprblock_pos;
-       int strip_len_errors;                           /* How many times was block_pos greater than strip_len */
-       int strip_magic_errors;
-       int strip_line_number_errors;
-       int compr_block_types[4];
-};
-
-static inline struct usb_usbvision *to_usbvision(struct v4l2_device *v4l2_dev)
-{
-       return container_of(v4l2_dev, struct usb_usbvision, v4l2_dev);
-}
-
-#define call_all(usbvision, o, f, args...) \
-       v4l2_device_call_all(&usbvision->v4l2_dev, 0, o, f, ##args)
-
-/* --------------------------------------------------------------- */
-/* defined in usbvision-i2c.c                                      */
-/* i2c-algo-usb declaration                                        */
-/* --------------------------------------------------------------- */
-
-/* ----------------------------------------------------------------------- */
-/* usbvision specific I2C functions                                        */
-/* ----------------------------------------------------------------------- */
-int usbvision_i2c_register(struct usb_usbvision *usbvision);
-int usbvision_i2c_unregister(struct usb_usbvision *usbvision);
-
-/* defined in usbvision-core.c                                      */
-int usbvision_read_reg(struct usb_usbvision *usbvision, unsigned char reg);
-int usbvision_write_reg(struct usb_usbvision *usbvision, unsigned char reg,
-                       unsigned char value);
-
-int usbvision_frames_alloc(struct usb_usbvision *usbvision, int number_of_frames);
-void usbvision_frames_free(struct usb_usbvision *usbvision);
-int usbvision_scratch_alloc(struct usb_usbvision *usbvision);
-void usbvision_scratch_free(struct usb_usbvision *usbvision);
-int usbvision_decompress_alloc(struct usb_usbvision *usbvision);
-void usbvision_decompress_free(struct usb_usbvision *usbvision);
-
-int usbvision_setup(struct usb_usbvision *usbvision, int format);
-int usbvision_init_isoc(struct usb_usbvision *usbvision);
-int usbvision_restart_isoc(struct usb_usbvision *usbvision);
-void usbvision_stop_isoc(struct usb_usbvision *usbvision);
-int usbvision_set_alternate(struct usb_usbvision *dev);
-
-int usbvision_set_audio(struct usb_usbvision *usbvision, int audio_channel);
-int usbvision_audio_off(struct usb_usbvision *usbvision);
-
-int usbvision_begin_streaming(struct usb_usbvision *usbvision);
-void usbvision_empty_framequeues(struct usb_usbvision *dev);
-int usbvision_stream_interrupt(struct usb_usbvision *dev);
-
-int usbvision_muxsel(struct usb_usbvision *usbvision, int channel);
-int usbvision_set_input(struct usb_usbvision *usbvision);
-int usbvision_set_output(struct usb_usbvision *usbvision, int width, int height);
-
-void usbvision_init_power_off_timer(struct usb_usbvision *usbvision);
-void usbvision_set_power_off_timer(struct usb_usbvision *usbvision);
-void usbvision_reset_power_off_timer(struct usb_usbvision *usbvision);
-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/video/uvc/Kconfig b/drivers/media/video/uvc/Kconfig
deleted file mode 100644 (file)
index 541c9f1..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-config USB_VIDEO_CLASS
-       tristate "USB Video Class (UVC)"
-       select VIDEOBUF2_VMALLOC
-       ---help---
-         Support for the USB Video Class (UVC).  Currently only video
-         input devices, such as webcams, are supported.
-
-         For more information see: <http://linux-uvc.berlios.de/>
-
-config USB_VIDEO_CLASS_INPUT_EVDEV
-       bool "UVC input events device support"
-       default y
-       depends on USB_VIDEO_CLASS
-       depends on USB_VIDEO_CLASS=INPUT || INPUT=y
-       ---help---
-         This option makes USB Video Class devices register an input device
-         to report button events.
-
-         If you are in doubt, say Y.
diff --git a/drivers/media/video/uvc/Makefile b/drivers/media/video/uvc/Makefile
deleted file mode 100644 (file)
index c26d12f..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-uvcvideo-objs  := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \
-                 uvc_status.o uvc_isight.o uvc_debugfs.o
-ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
-uvcvideo-objs  += uvc_entity.o
-endif
-obj-$(CONFIG_USB_VIDEO_CLASS) += uvcvideo.o
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c
deleted file mode 100644 (file)
index f7061a5..0000000
+++ /dev/null
@@ -1,2165 +0,0 @@
-/*
- *      uvc_ctrl.c  --  USB Video Class driver - Controls
- *
- *      Copyright (C) 2005-2010
- *          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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include <linux/vmalloc.h>
-#include <linux/wait.h>
-#include <linux/atomic.h>
-#include <media/v4l2-ctrls.h>
-
-#include "uvcvideo.h"
-
-#define UVC_CTRL_DATA_CURRENT  0
-#define UVC_CTRL_DATA_BACKUP   1
-#define UVC_CTRL_DATA_MIN      2
-#define UVC_CTRL_DATA_MAX      3
-#define UVC_CTRL_DATA_RES      4
-#define UVC_CTRL_DATA_DEF      5
-#define UVC_CTRL_DATA_LAST     6
-
-/* ------------------------------------------------------------------------
- * Controls
- */
-
-static struct uvc_control_info uvc_ctrls[] = {
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_BRIGHTNESS_CONTROL,
-               .index          = 0,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_CONTRAST_CONTROL,
-               .index          = 1,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_HUE_CONTROL,
-               .index          = 2,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE
-                               | UVC_CTRL_FLAG_AUTO_UPDATE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_SATURATION_CONTROL,
-               .index          = 3,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_SHARPNESS_CONTROL,
-               .index          = 4,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_GAMMA_CONTROL,
-               .index          = 5,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
-               .index          = 6,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE
-                               | UVC_CTRL_FLAG_AUTO_UPDATE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
-               .index          = 7,
-               .size           = 4,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE
-                               | UVC_CTRL_FLAG_AUTO_UPDATE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL,
-               .index          = 8,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_GAIN_CONTROL,
-               .index          = 9,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
-               .index          = 10,
-               .size           = 1,
-               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
-                               | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_HUE_AUTO_CONTROL,
-               .index          = 11,
-               .size           = 1,
-               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
-                               | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
-               .index          = 12,
-               .size           = 1,
-               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
-                               | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
-               .index          = 13,
-               .size           = 1,
-               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
-                               | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_DIGITAL_MULTIPLIER_CONTROL,
-               .index          = 14,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL,
-               .index          = 15,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL,
-               .index          = 16,
-               .size           = 1,
-               .flags          = UVC_CTRL_FLAG_GET_CUR,
-       },
-       {
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_ANALOG_LOCK_STATUS_CONTROL,
-               .index          = 17,
-               .size           = 1,
-               .flags          = UVC_CTRL_FLAG_GET_CUR,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_SCANNING_MODE_CONTROL,
-               .index          = 0,
-               .size           = 1,
-               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
-                               | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_AE_MODE_CONTROL,
-               .index          = 1,
-               .size           = 1,
-               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
-                               | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_GET_RES
-                               | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_AE_PRIORITY_CONTROL,
-               .index          = 2,
-               .size           = 1,
-               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
-                               | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
-               .index          = 3,
-               .size           = 4,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL,
-               .index          = 4,
-               .size           = 1,
-               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_FOCUS_ABSOLUTE_CONTROL,
-               .index          = 5,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE
-                               | UVC_CTRL_FLAG_AUTO_UPDATE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_FOCUS_RELATIVE_CONTROL,
-               .index          = 6,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN
-                               | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES
-                               | UVC_CTRL_FLAG_GET_DEF
-                               | UVC_CTRL_FLAG_AUTO_UPDATE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_IRIS_ABSOLUTE_CONTROL,
-               .index          = 7,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE
-                               | UVC_CTRL_FLAG_AUTO_UPDATE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_IRIS_RELATIVE_CONTROL,
-               .index          = 8,
-               .size           = 1,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_AUTO_UPDATE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_ZOOM_ABSOLUTE_CONTROL,
-               .index          = 9,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE
-                               | UVC_CTRL_FLAG_AUTO_UPDATE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_ZOOM_RELATIVE_CONTROL,
-               .index          = 10,
-               .size           = 3,
-               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN
-                               | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES
-                               | UVC_CTRL_FLAG_GET_DEF
-                               | UVC_CTRL_FLAG_AUTO_UPDATE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_PANTILT_ABSOLUTE_CONTROL,
-               .index          = 11,
-               .size           = 8,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE
-                               | UVC_CTRL_FLAG_AUTO_UPDATE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_PANTILT_RELATIVE_CONTROL,
-               .index          = 12,
-               .size           = 4,
-               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN
-                               | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES
-                               | UVC_CTRL_FLAG_GET_DEF
-                               | UVC_CTRL_FLAG_AUTO_UPDATE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_ROLL_ABSOLUTE_CONTROL,
-               .index          = 13,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR
-                               | UVC_CTRL_FLAG_GET_RANGE
-                               | UVC_CTRL_FLAG_RESTORE
-                               | UVC_CTRL_FLAG_AUTO_UPDATE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_ROLL_RELATIVE_CONTROL,
-               .index          = 14,
-               .size           = 2,
-               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_MIN
-                               | UVC_CTRL_FLAG_GET_MAX | UVC_CTRL_FLAG_GET_RES
-                               | UVC_CTRL_FLAG_GET_DEF
-                               | UVC_CTRL_FLAG_AUTO_UPDATE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_FOCUS_AUTO_CONTROL,
-               .index          = 17,
-               .size           = 1,
-               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
-                               | UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_RESTORE,
-       },
-       {
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_PRIVACY_CONTROL,
-               .index          = 18,
-               .size           = 1,
-               .flags          = UVC_CTRL_FLAG_SET_CUR | UVC_CTRL_FLAG_GET_CUR
-                               | UVC_CTRL_FLAG_RESTORE
-                               | UVC_CTRL_FLAG_AUTO_UPDATE,
-       },
-};
-
-static struct uvc_menu_info power_line_frequency_controls[] = {
-       { 0, "Disabled" },
-       { 1, "50 Hz" },
-       { 2, "60 Hz" },
-};
-
-static struct uvc_menu_info exposure_auto_controls[] = {
-       { 2, "Auto Mode" },
-       { 1, "Manual Mode" },
-       { 4, "Shutter Priority Mode" },
-       { 8, "Aperture Priority Mode" },
-};
-
-static __s32 uvc_ctrl_get_zoom(struct uvc_control_mapping *mapping,
-       __u8 query, const __u8 *data)
-{
-       __s8 zoom = (__s8)data[0];
-
-       switch (query) {
-       case UVC_GET_CUR:
-               return (zoom == 0) ? 0 : (zoom > 0 ? data[2] : -data[2]);
-
-       case UVC_GET_MIN:
-       case UVC_GET_MAX:
-       case UVC_GET_RES:
-       case UVC_GET_DEF:
-       default:
-               return data[2];
-       }
-}
-
-static void uvc_ctrl_set_zoom(struct uvc_control_mapping *mapping,
-       __s32 value, __u8 *data)
-{
-       data[0] = value == 0 ? 0 : (value > 0) ? 1 : 0xff;
-       data[2] = min((int)abs(value), 0xff);
-}
-
-static struct uvc_control_mapping uvc_ctrl_mappings[] = {
-       {
-               .id             = V4L2_CID_BRIGHTNESS,
-               .name           = "Brightness",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_BRIGHTNESS_CONTROL,
-               .size           = 16,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
-       },
-       {
-               .id             = V4L2_CID_CONTRAST,
-               .name           = "Contrast",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_CONTRAST_CONTROL,
-               .size           = 16,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
-       },
-       {
-               .id             = V4L2_CID_HUE,
-               .name           = "Hue",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_HUE_CONTROL,
-               .size           = 16,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
-               .master_id      = V4L2_CID_HUE_AUTO,
-               .master_manual  = 0,
-       },
-       {
-               .id             = V4L2_CID_SATURATION,
-               .name           = "Saturation",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_SATURATION_CONTROL,
-               .size           = 16,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
-       },
-       {
-               .id             = V4L2_CID_SHARPNESS,
-               .name           = "Sharpness",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_SHARPNESS_CONTROL,
-               .size           = 16,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
-       },
-       {
-               .id             = V4L2_CID_GAMMA,
-               .name           = "Gamma",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_GAMMA_CONTROL,
-               .size           = 16,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
-       },
-       {
-               .id             = V4L2_CID_BACKLIGHT_COMPENSATION,
-               .name           = "Backlight Compensation",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL,
-               .size           = 16,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
-       },
-       {
-               .id             = V4L2_CID_GAIN,
-               .name           = "Gain",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_GAIN_CONTROL,
-               .size           = 16,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
-       },
-       {
-               .id             = V4L2_CID_POWER_LINE_FREQUENCY,
-               .name           = "Power Line Frequency",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_POWER_LINE_FREQUENCY_CONTROL,
-               .size           = 2,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_MENU,
-               .data_type      = UVC_CTRL_DATA_TYPE_ENUM,
-               .menu_info      = power_line_frequency_controls,
-               .menu_count     = ARRAY_SIZE(power_line_frequency_controls),
-       },
-       {
-               .id             = V4L2_CID_HUE_AUTO,
-               .name           = "Hue, Auto",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_HUE_AUTO_CONTROL,
-               .size           = 1,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
-               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
-               .slave_ids      = { V4L2_CID_HUE, },
-       },
-       {
-               .id             = V4L2_CID_EXPOSURE_AUTO,
-               .name           = "Exposure, Auto",
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_AE_MODE_CONTROL,
-               .size           = 4,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_MENU,
-               .data_type      = UVC_CTRL_DATA_TYPE_BITMASK,
-               .menu_info      = exposure_auto_controls,
-               .menu_count     = ARRAY_SIZE(exposure_auto_controls),
-               .slave_ids      = { V4L2_CID_EXPOSURE_ABSOLUTE, },
-       },
-       {
-               .id             = V4L2_CID_EXPOSURE_AUTO_PRIORITY,
-               .name           = "Exposure, Auto Priority",
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_AE_PRIORITY_CONTROL,
-               .size           = 1,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
-               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
-       },
-       {
-               .id             = V4L2_CID_EXPOSURE_ABSOLUTE,
-               .name           = "Exposure (Absolute)",
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL,
-               .size           = 32,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
-               .master_id      = V4L2_CID_EXPOSURE_AUTO,
-               .master_manual  = V4L2_EXPOSURE_MANUAL,
-       },
-       {
-               .id             = V4L2_CID_AUTO_WHITE_BALANCE,
-               .name           = "White Balance Temperature, Auto",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
-               .size           = 1,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
-               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
-               .slave_ids      = { V4L2_CID_WHITE_BALANCE_TEMPERATURE, },
-       },
-       {
-               .id             = V4L2_CID_WHITE_BALANCE_TEMPERATURE,
-               .name           = "White Balance Temperature",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
-               .size           = 16,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
-               .master_id      = V4L2_CID_AUTO_WHITE_BALANCE,
-               .master_manual  = 0,
-       },
-       {
-               .id             = V4L2_CID_AUTO_WHITE_BALANCE,
-               .name           = "White Balance Component, Auto",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
-               .size           = 1,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
-               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
-               .slave_ids      = { V4L2_CID_BLUE_BALANCE,
-                                   V4L2_CID_RED_BALANCE },
-       },
-       {
-               .id             = V4L2_CID_BLUE_BALANCE,
-               .name           = "White Balance Blue Component",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
-               .size           = 16,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
-               .master_id      = V4L2_CID_AUTO_WHITE_BALANCE,
-               .master_manual  = 0,
-       },
-       {
-               .id             = V4L2_CID_RED_BALANCE,
-               .name           = "White Balance Red Component",
-               .entity         = UVC_GUID_UVC_PROCESSING,
-               .selector       = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL,
-               .size           = 16,
-               .offset         = 16,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
-               .master_id      = V4L2_CID_AUTO_WHITE_BALANCE,
-               .master_manual  = 0,
-       },
-       {
-               .id             = V4L2_CID_FOCUS_ABSOLUTE,
-               .name           = "Focus (absolute)",
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_FOCUS_ABSOLUTE_CONTROL,
-               .size           = 16,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
-               .master_id      = V4L2_CID_FOCUS_AUTO,
-               .master_manual  = 0,
-       },
-       {
-               .id             = V4L2_CID_FOCUS_AUTO,
-               .name           = "Focus, Auto",
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_FOCUS_AUTO_CONTROL,
-               .size           = 1,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
-               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
-               .slave_ids      = { V4L2_CID_FOCUS_ABSOLUTE, },
-       },
-       {
-               .id             = V4L2_CID_IRIS_ABSOLUTE,
-               .name           = "Iris, Absolute",
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_IRIS_ABSOLUTE_CONTROL,
-               .size           = 16,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
-       },
-       {
-               .id             = V4L2_CID_IRIS_RELATIVE,
-               .name           = "Iris, Relative",
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_IRIS_RELATIVE_CONTROL,
-               .size           = 8,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
-       },
-       {
-               .id             = V4L2_CID_ZOOM_ABSOLUTE,
-               .name           = "Zoom, Absolute",
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_ZOOM_ABSOLUTE_CONTROL,
-               .size           = 16,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
-       },
-       {
-               .id             = V4L2_CID_ZOOM_CONTINUOUS,
-               .name           = "Zoom, Continuous",
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_ZOOM_RELATIVE_CONTROL,
-               .size           = 0,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_SIGNED,
-               .get            = uvc_ctrl_get_zoom,
-               .set            = uvc_ctrl_set_zoom,
-       },
-       {
-               .id             = V4L2_CID_PAN_ABSOLUTE,
-               .name           = "Pan (Absolute)",
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_PANTILT_ABSOLUTE_CONTROL,
-               .size           = 32,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
-       },
-       {
-               .id             = V4L2_CID_TILT_ABSOLUTE,
-               .name           = "Tilt (Absolute)",
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_PANTILT_ABSOLUTE_CONTROL,
-               .size           = 32,
-               .offset         = 32,
-               .v4l2_type      = V4L2_CTRL_TYPE_INTEGER,
-               .data_type      = UVC_CTRL_DATA_TYPE_UNSIGNED,
-       },
-       {
-               .id             = V4L2_CID_PRIVACY,
-               .name           = "Privacy",
-               .entity         = UVC_GUID_UVC_CAMERA,
-               .selector       = UVC_CT_PRIVACY_CONTROL,
-               .size           = 1,
-               .offset         = 0,
-               .v4l2_type      = V4L2_CTRL_TYPE_BOOLEAN,
-               .data_type      = UVC_CTRL_DATA_TYPE_BOOLEAN,
-       },
-};
-
-/* ------------------------------------------------------------------------
- * Utility functions
- */
-
-static inline __u8 *uvc_ctrl_data(struct uvc_control *ctrl, int id)
-{
-       return ctrl->uvc_data + id * ctrl->info.size;
-}
-
-static inline int uvc_test_bit(const __u8 *data, int bit)
-{
-       return (data[bit >> 3] >> (bit & 7)) & 1;
-}
-
-static inline void uvc_clear_bit(__u8 *data, int bit)
-{
-       data[bit >> 3] &= ~(1 << (bit & 7));
-}
-
-/* Extract the bit string specified by mapping->offset and mapping->size
- * from the little-endian data stored at 'data' and return the result as
- * a signed 32bit integer. Sign extension will be performed if the mapping
- * references a signed data type.
- */
-static __s32 uvc_get_le_value(struct uvc_control_mapping *mapping,
-       __u8 query, const __u8 *data)
-{
-       int bits = mapping->size;
-       int offset = mapping->offset;
-       __s32 value = 0;
-       __u8 mask;
-
-       data += offset / 8;
-       offset &= 7;
-       mask = ((1LL << bits) - 1) << offset;
-
-       for (; bits > 0; data++) {
-               __u8 byte = *data & mask;
-               value |= offset > 0 ? (byte >> offset) : (byte << (-offset));
-               bits -= 8 - (offset > 0 ? offset : 0);
-               offset -= 8;
-               mask = (1 << bits) - 1;
-       }
-
-       /* Sign-extend the value if needed. */
-       if (mapping->data_type == UVC_CTRL_DATA_TYPE_SIGNED)
-               value |= -(value & (1 << (mapping->size - 1)));
-
-       return value;
-}
-
-/* Set the bit string specified by mapping->offset and mapping->size
- * in the little-endian data stored at 'data' to the value 'value'.
- */
-static void uvc_set_le_value(struct uvc_control_mapping *mapping,
-       __s32 value, __u8 *data)
-{
-       int bits = mapping->size;
-       int offset = mapping->offset;
-       __u8 mask;
-
-       /* According to the v4l2 spec, writing any value to a button control
-        * should result in the action belonging to the button control being
-        * triggered. UVC devices however want to see a 1 written -> override
-        * value.
-        */
-       if (mapping->v4l2_type == V4L2_CTRL_TYPE_BUTTON)
-               value = -1;
-
-       data += offset / 8;
-       offset &= 7;
-
-       for (; bits > 0; data++) {
-               mask = ((1LL << bits) - 1) << offset;
-               *data = (*data & ~mask) | ((value << offset) & mask);
-               value >>= offset ? offset : 8;
-               bits -= 8 - offset;
-               offset = 0;
-       }
-}
-
-/* ------------------------------------------------------------------------
- * Terminal and unit management
- */
-
-static const __u8 uvc_processing_guid[16] = UVC_GUID_UVC_PROCESSING;
-static const __u8 uvc_camera_guid[16] = UVC_GUID_UVC_CAMERA;
-static const __u8 uvc_media_transport_input_guid[16] =
-       UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT;
-
-static int uvc_entity_match_guid(const struct uvc_entity *entity,
-       const __u8 guid[16])
-{
-       switch (UVC_ENTITY_TYPE(entity)) {
-       case UVC_ITT_CAMERA:
-               return memcmp(uvc_camera_guid, guid, 16) == 0;
-
-       case UVC_ITT_MEDIA_TRANSPORT_INPUT:
-               return memcmp(uvc_media_transport_input_guid, guid, 16) == 0;
-
-       case UVC_VC_PROCESSING_UNIT:
-               return memcmp(uvc_processing_guid, guid, 16) == 0;
-
-       case UVC_VC_EXTENSION_UNIT:
-               return memcmp(entity->extension.guidExtensionCode,
-                             guid, 16) == 0;
-
-       default:
-               return 0;
-       }
-}
-
-/* ------------------------------------------------------------------------
- * UVC Controls
- */
-
-static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id,
-       struct uvc_control_mapping **mapping, struct uvc_control **control,
-       int next)
-{
-       struct uvc_control *ctrl;
-       struct uvc_control_mapping *map;
-       unsigned int i;
-
-       if (entity == NULL)
-               return;
-
-       for (i = 0; i < entity->ncontrols; ++i) {
-               ctrl = &entity->controls[i];
-               if (!ctrl->initialized)
-                       continue;
-
-               list_for_each_entry(map, &ctrl->info.mappings, list) {
-                       if ((map->id == v4l2_id) && !next) {
-                               *control = ctrl;
-                               *mapping = map;
-                               return;
-                       }
-
-                       if ((*mapping == NULL || (*mapping)->id > map->id) &&
-                           (map->id > v4l2_id) && next) {
-                               *control = ctrl;
-                               *mapping = map;
-                       }
-               }
-       }
-}
-
-static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
-       __u32 v4l2_id, struct uvc_control_mapping **mapping)
-{
-       struct uvc_control *ctrl = NULL;
-       struct uvc_entity *entity;
-       int next = v4l2_id & V4L2_CTRL_FLAG_NEXT_CTRL;
-
-       *mapping = NULL;
-
-       /* Mask the query flags. */
-       v4l2_id &= V4L2_CTRL_ID_MASK;
-
-       /* Find the control. */
-       list_for_each_entry(entity, &chain->entities, chain) {
-               __uvc_find_control(entity, v4l2_id, mapping, &ctrl, next);
-               if (ctrl && !next)
-                       return ctrl;
-       }
-
-       if (ctrl == NULL && !next)
-               uvc_trace(UVC_TRACE_CONTROL, "Control 0x%08x not found.\n",
-                               v4l2_id);
-
-       return ctrl;
-}
-
-static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain,
-       struct uvc_control *ctrl)
-{
-       int ret;
-
-       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) {
-               ret = uvc_query_ctrl(chain->dev, UVC_GET_DEF, ctrl->entity->id,
-                                    chain->dev->intfnum, ctrl->info.selector,
-                                    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF),
-                                    ctrl->info.size);
-               if (ret < 0)
-                       return ret;
-       }
-
-       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN) {
-               ret = uvc_query_ctrl(chain->dev, UVC_GET_MIN, ctrl->entity->id,
-                                    chain->dev->intfnum, ctrl->info.selector,
-                                    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN),
-                                    ctrl->info.size);
-               if (ret < 0)
-                       return ret;
-       }
-       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX) {
-               ret = uvc_query_ctrl(chain->dev, UVC_GET_MAX, ctrl->entity->id,
-                                    chain->dev->intfnum, ctrl->info.selector,
-                                    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX),
-                                    ctrl->info.size);
-               if (ret < 0)
-                       return ret;
-       }
-       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) {
-               ret = uvc_query_ctrl(chain->dev, UVC_GET_RES, ctrl->entity->id,
-                                    chain->dev->intfnum, ctrl->info.selector,
-                                    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES),
-                                    ctrl->info.size);
-               if (ret < 0) {
-                       if (UVC_ENTITY_TYPE(ctrl->entity) !=
-                           UVC_VC_EXTENSION_UNIT)
-                               return ret;
-
-                       /* GET_RES is mandatory for XU controls, but some
-                        * cameras still choke on it. Ignore errors and set the
-                        * resolution value to zero.
-                        */
-                       uvc_warn_once(chain->dev, UVC_WARN_XU_GET_RES,
-                                     "UVC non compliance - GET_RES failed on "
-                                     "an XU control. Enabling workaround.\n");
-                       memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), 0,
-                              ctrl->info.size);
-               }
-       }
-
-       ctrl->cached = 1;
-       return 0;
-}
-
-static int __uvc_ctrl_get(struct uvc_video_chain *chain,
-       struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
-       s32 *value)
-{
-       struct uvc_menu_info *menu;
-       unsigned int i;
-       int ret;
-
-       if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
-               return -EINVAL;
-
-       if (!ctrl->loaded) {
-               ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id,
-                               chain->dev->intfnum, ctrl->info.selector,
-                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
-                               ctrl->info.size);
-               if (ret < 0)
-                       return ret;
-
-               ctrl->loaded = 1;
-       }
-
-       *value = mapping->get(mapping, UVC_GET_CUR,
-               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
-
-       if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
-               menu = mapping->menu_info;
-               for (i = 0; i < mapping->menu_count; ++i, ++menu) {
-                       if (menu->value == *value) {
-                               *value = i;
-                               break;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static int __uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
-       struct uvc_control *ctrl,
-       struct uvc_control_mapping *mapping,
-       struct v4l2_queryctrl *v4l2_ctrl)
-{
-       struct uvc_control_mapping *master_map = NULL;
-       struct uvc_control *master_ctrl = NULL;
-       struct uvc_menu_info *menu;
-       unsigned int i;
-
-       memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl);
-       v4l2_ctrl->id = mapping->id;
-       v4l2_ctrl->type = mapping->v4l2_type;
-       strlcpy(v4l2_ctrl->name, mapping->name, sizeof v4l2_ctrl->name);
-       v4l2_ctrl->flags = 0;
-
-       if (!(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR))
-               v4l2_ctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
-       if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR))
-               v4l2_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-
-       if (mapping->master_id)
-               __uvc_find_control(ctrl->entity, mapping->master_id,
-                                  &master_map, &master_ctrl, 0);
-       if (master_ctrl && (master_ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR)) {
-               s32 val;
-               int ret = __uvc_ctrl_get(chain, master_ctrl, master_map, &val);
-               if (ret < 0)
-                       return ret;
-
-               if (val != mapping->master_manual)
-                               v4l2_ctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
-       }
-
-       if (!ctrl->cached) {
-               int ret = uvc_ctrl_populate_cache(chain, ctrl);
-               if (ret < 0)
-                       return ret;
-       }
-
-       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_DEF) {
-               v4l2_ctrl->default_value = mapping->get(mapping, UVC_GET_DEF,
-                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_DEF));
-       }
-
-       switch (mapping->v4l2_type) {
-       case V4L2_CTRL_TYPE_MENU:
-               v4l2_ctrl->minimum = 0;
-               v4l2_ctrl->maximum = mapping->menu_count - 1;
-               v4l2_ctrl->step = 1;
-
-               menu = mapping->menu_info;
-               for (i = 0; i < mapping->menu_count; ++i, ++menu) {
-                       if (menu->value == v4l2_ctrl->default_value) {
-                               v4l2_ctrl->default_value = i;
-                               break;
-                       }
-               }
-
-               return 0;
-
-       case V4L2_CTRL_TYPE_BOOLEAN:
-               v4l2_ctrl->minimum = 0;
-               v4l2_ctrl->maximum = 1;
-               v4l2_ctrl->step = 1;
-               return 0;
-
-       case V4L2_CTRL_TYPE_BUTTON:
-               v4l2_ctrl->minimum = 0;
-               v4l2_ctrl->maximum = 0;
-               v4l2_ctrl->step = 0;
-               return 0;
-
-       default:
-               break;
-       }
-
-       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MIN)
-               v4l2_ctrl->minimum = mapping->get(mapping, UVC_GET_MIN,
-                                    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
-
-       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_MAX)
-               v4l2_ctrl->maximum = mapping->get(mapping, UVC_GET_MAX,
-                                    uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
-
-       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)
-               v4l2_ctrl->step = mapping->get(mapping, UVC_GET_RES,
-                                 uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
-
-       return 0;
-}
-
-int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
-       struct v4l2_queryctrl *v4l2_ctrl)
-{
-       struct uvc_control *ctrl;
-       struct uvc_control_mapping *mapping;
-       int ret;
-
-       ret = mutex_lock_interruptible(&chain->ctrl_mutex);
-       if (ret < 0)
-               return -ERESTARTSYS;
-
-       ctrl = uvc_find_control(chain, v4l2_ctrl->id, &mapping);
-       if (ctrl == NULL) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       ret = __uvc_query_v4l2_ctrl(chain, ctrl, mapping, v4l2_ctrl);
-done:
-       mutex_unlock(&chain->ctrl_mutex);
-       return ret;
-}
-
-/*
- * Mapping V4L2 controls to UVC controls can be straighforward if done well.
- * Most of the UVC controls exist in V4L2, and can be mapped directly. Some
- * must be grouped (for instance the Red Balance, Blue Balance and Do White
- * Balance V4L2 controls use the White Balance Component UVC control) or
- * otherwise translated. The approach we take here is to use a translation
- * table for the controls that can be mapped directly, and handle the others
- * manually.
- */
-int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
-       struct v4l2_querymenu *query_menu)
-{
-       struct uvc_menu_info *menu_info;
-       struct uvc_control_mapping *mapping;
-       struct uvc_control *ctrl;
-       u32 index = query_menu->index;
-       u32 id = query_menu->id;
-       int ret;
-
-       memset(query_menu, 0, sizeof(*query_menu));
-       query_menu->id = id;
-       query_menu->index = index;
-
-       ret = mutex_lock_interruptible(&chain->ctrl_mutex);
-       if (ret < 0)
-               return -ERESTARTSYS;
-
-       ctrl = uvc_find_control(chain, query_menu->id, &mapping);
-       if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       if (query_menu->index >= mapping->menu_count) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       menu_info = &mapping->menu_info[query_menu->index];
-
-       if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK &&
-           (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) {
-               s32 bitmap;
-
-               if (!ctrl->cached) {
-                       ret = uvc_ctrl_populate_cache(chain, ctrl);
-                       if (ret < 0)
-                               goto done;
-               }
-
-               bitmap = mapping->get(mapping, UVC_GET_RES,
-                                     uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
-               if (!(bitmap & menu_info->value)) {
-                       ret = -EINVAL;
-                       goto done;
-               }
-       }
-
-       strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
-
-done:
-       mutex_unlock(&chain->ctrl_mutex);
-       return ret;
-}
-
-/* --------------------------------------------------------------------------
- * Ctrl event handling
- */
-
-static void uvc_ctrl_fill_event(struct uvc_video_chain *chain,
-       struct v4l2_event *ev,
-       struct uvc_control *ctrl,
-       struct uvc_control_mapping *mapping,
-       s32 value, u32 changes)
-{
-       struct v4l2_queryctrl v4l2_ctrl;
-
-       __uvc_query_v4l2_ctrl(chain, ctrl, mapping, &v4l2_ctrl);
-
-       memset(ev->reserved, 0, sizeof(ev->reserved));
-       ev->type = V4L2_EVENT_CTRL;
-       ev->id = v4l2_ctrl.id;
-       ev->u.ctrl.value = value;
-       ev->u.ctrl.changes = changes;
-       ev->u.ctrl.type = v4l2_ctrl.type;
-       ev->u.ctrl.flags = v4l2_ctrl.flags;
-       ev->u.ctrl.minimum = v4l2_ctrl.minimum;
-       ev->u.ctrl.maximum = v4l2_ctrl.maximum;
-       ev->u.ctrl.step = v4l2_ctrl.step;
-       ev->u.ctrl.default_value = v4l2_ctrl.default_value;
-}
-
-static void uvc_ctrl_send_event(struct uvc_fh *handle,
-       struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
-       s32 value, u32 changes)
-{
-       struct v4l2_subscribed_event *sev;
-       struct v4l2_event ev;
-
-       if (list_empty(&mapping->ev_subs))
-               return;
-
-       uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, value, changes);
-
-       list_for_each_entry(sev, &mapping->ev_subs, node) {
-               if (sev->fh && (sev->fh != &handle->vfh ||
-                   (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK) ||
-                   (changes & V4L2_EVENT_CTRL_CH_FLAGS)))
-                       v4l2_event_queue_fh(sev->fh, &ev);
-       }
-}
-
-static void uvc_ctrl_send_slave_event(struct uvc_fh *handle,
-       struct uvc_control *master, u32 slave_id,
-       const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
-{
-       struct uvc_control_mapping *mapping = NULL;
-       struct uvc_control *ctrl = NULL;
-       u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
-       unsigned int i;
-       s32 val = 0;
-
-       /*
-        * We can skip sending an event for the slave if the slave
-        * is being modified in the same transaction.
-        */
-       for (i = 0; i < xctrls_count; i++) {
-               if (xctrls[i].id == slave_id)
-                       return;
-       }
-
-       __uvc_find_control(master->entity, slave_id, &mapping, &ctrl, 0);
-       if (ctrl == NULL)
-               return;
-
-       if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0)
-               changes |= V4L2_EVENT_CTRL_CH_VALUE;
-
-       uvc_ctrl_send_event(handle, ctrl, mapping, val, changes);
-}
-
-static void uvc_ctrl_send_events(struct uvc_fh *handle,
-       const struct v4l2_ext_control *xctrls, unsigned int xctrls_count)
-{
-       struct uvc_control_mapping *mapping;
-       struct uvc_control *ctrl;
-       u32 changes = V4L2_EVENT_CTRL_CH_VALUE;
-       unsigned int i;
-       unsigned int j;
-
-       for (i = 0; i < xctrls_count; ++i) {
-               ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping);
-
-               for (j = 0; j < ARRAY_SIZE(mapping->slave_ids); ++j) {
-                       if (!mapping->slave_ids[j])
-                               break;
-                       uvc_ctrl_send_slave_event(handle, ctrl,
-                                                 mapping->slave_ids[j],
-                                                 xctrls, xctrls_count);
-               }
-
-               /*
-                * If the master is being modified in the same transaction
-                * flags may change too.
-                */
-               if (mapping->master_id) {
-                       for (j = 0; j < xctrls_count; j++) {
-                               if (xctrls[j].id == mapping->master_id) {
-                                       changes |= V4L2_EVENT_CTRL_CH_FLAGS;
-                                       break;
-                               }
-                       }
-               }
-
-               uvc_ctrl_send_event(handle, ctrl, mapping, xctrls[i].value,
-                                   changes);
-       }
-}
-
-static int uvc_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
-{
-       struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh);
-       struct uvc_control_mapping *mapping;
-       struct uvc_control *ctrl;
-       int ret;
-
-       ret = mutex_lock_interruptible(&handle->chain->ctrl_mutex);
-       if (ret < 0)
-               return -ERESTARTSYS;
-
-       ctrl = uvc_find_control(handle->chain, sev->id, &mapping);
-       if (ctrl == NULL) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       list_add_tail(&sev->node, &mapping->ev_subs);
-       if (sev->flags & V4L2_EVENT_SUB_FL_SEND_INITIAL) {
-               struct v4l2_event ev;
-               u32 changes = V4L2_EVENT_CTRL_CH_FLAGS;
-               s32 val = 0;
-
-               if (__uvc_ctrl_get(handle->chain, ctrl, mapping, &val) == 0)
-                       changes |= V4L2_EVENT_CTRL_CH_VALUE;
-
-               uvc_ctrl_fill_event(handle->chain, &ev, ctrl, mapping, val,
-                                   changes);
-               /* Mark the queue as active, allowing this initial
-                  event to be accepted. */
-               sev->elems = elems;
-               v4l2_event_queue_fh(sev->fh, &ev);
-       }
-
-done:
-       mutex_unlock(&handle->chain->ctrl_mutex);
-       return ret;
-}
-
-static void uvc_ctrl_del_event(struct v4l2_subscribed_event *sev)
-{
-       struct uvc_fh *handle = container_of(sev->fh, struct uvc_fh, vfh);
-
-       mutex_lock(&handle->chain->ctrl_mutex);
-       list_del(&sev->node);
-       mutex_unlock(&handle->chain->ctrl_mutex);
-}
-
-const struct v4l2_subscribed_event_ops uvc_ctrl_sub_ev_ops = {
-       .add = uvc_ctrl_add_event,
-       .del = uvc_ctrl_del_event,
-       .replace = v4l2_ctrl_replace,
-       .merge = v4l2_ctrl_merge,
-};
-
-/* --------------------------------------------------------------------------
- * Control transactions
- *
- * To make extended set operations as atomic as the hardware allows, controls
- * are handled using begin/commit/rollback operations.
- *
- * At the beginning of a set request, uvc_ctrl_begin should be called to
- * initialize the request. This function acquires the control lock.
- *
- * When setting a control, the new value is stored in the control data field
- * at position UVC_CTRL_DATA_CURRENT. The control is then marked as dirty for
- * later processing. If the UVC and V4L2 control sizes differ, the current
- * value is loaded from the hardware before storing the new value in the data
- * field.
- *
- * After processing all controls in the transaction, uvc_ctrl_commit or
- * uvc_ctrl_rollback must be called to apply the pending changes to the
- * hardware or revert them. When applying changes, all controls marked as
- * dirty will be modified in the UVC device, and the dirty flag will be
- * cleared. When reverting controls, the control data field
- * UVC_CTRL_DATA_CURRENT is reverted to its previous value
- * (UVC_CTRL_DATA_BACKUP) for all dirty controls. Both functions release the
- * control lock.
- */
-int uvc_ctrl_begin(struct uvc_video_chain *chain)
-{
-       return mutex_lock_interruptible(&chain->ctrl_mutex) ? -ERESTARTSYS : 0;
-}
-
-static int uvc_ctrl_commit_entity(struct uvc_device *dev,
-       struct uvc_entity *entity, int rollback)
-{
-       struct uvc_control *ctrl;
-       unsigned int i;
-       int ret;
-
-       if (entity == NULL)
-               return 0;
-
-       for (i = 0; i < entity->ncontrols; ++i) {
-               ctrl = &entity->controls[i];
-               if (!ctrl->initialized)
-                       continue;
-
-               /* Reset the loaded flag for auto-update controls that were
-                * marked as loaded in uvc_ctrl_get/uvc_ctrl_set to prevent
-                * uvc_ctrl_get from using the cached value, and for write-only
-                * controls to prevent uvc_ctrl_set from setting bits not
-                * explicitly set by the user.
-                */
-               if (ctrl->info.flags & UVC_CTRL_FLAG_AUTO_UPDATE ||
-                   !(ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR))
-                       ctrl->loaded = 0;
-
-               if (!ctrl->dirty)
-                       continue;
-
-               if (!rollback)
-                       ret = uvc_query_ctrl(dev, UVC_SET_CUR, ctrl->entity->id,
-                               dev->intfnum, ctrl->info.selector,
-                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
-                               ctrl->info.size);
-               else
-                       ret = 0;
-
-               if (rollback || ret < 0)
-                       memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
-                              uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
-                              ctrl->info.size);
-
-               ctrl->dirty = 0;
-
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
-}
-
-int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback,
-                     const struct v4l2_ext_control *xctrls,
-                     unsigned int xctrls_count)
-{
-       struct uvc_video_chain *chain = handle->chain;
-       struct uvc_entity *entity;
-       int ret = 0;
-
-       /* Find the control. */
-       list_for_each_entry(entity, &chain->entities, chain) {
-               ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback);
-               if (ret < 0)
-                       goto done;
-       }
-
-       if (!rollback)
-               uvc_ctrl_send_events(handle, xctrls, xctrls_count);
-done:
-       mutex_unlock(&chain->ctrl_mutex);
-       return ret;
-}
-
-int uvc_ctrl_get(struct uvc_video_chain *chain,
-       struct v4l2_ext_control *xctrl)
-{
-       struct uvc_control *ctrl;
-       struct uvc_control_mapping *mapping;
-
-       ctrl = uvc_find_control(chain, xctrl->id, &mapping);
-       if (ctrl == NULL)
-               return -EINVAL;
-
-       return __uvc_ctrl_get(chain, ctrl, mapping, &xctrl->value);
-}
-
-int uvc_ctrl_set(struct uvc_video_chain *chain,
-       struct v4l2_ext_control *xctrl)
-{
-       struct uvc_control *ctrl;
-       struct uvc_control_mapping *mapping;
-       s32 value;
-       u32 step;
-       s32 min;
-       s32 max;
-       int ret;
-
-       ctrl = uvc_find_control(chain, xctrl->id, &mapping);
-       if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) == 0)
-               return -EINVAL;
-
-       /* Clamp out of range values. */
-       switch (mapping->v4l2_type) {
-       case V4L2_CTRL_TYPE_INTEGER:
-               if (!ctrl->cached) {
-                       ret = uvc_ctrl_populate_cache(chain, ctrl);
-                       if (ret < 0)
-                               return ret;
-               }
-
-               min = mapping->get(mapping, UVC_GET_MIN,
-                                  uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MIN));
-               max = mapping->get(mapping, UVC_GET_MAX,
-                                  uvc_ctrl_data(ctrl, UVC_CTRL_DATA_MAX));
-               step = mapping->get(mapping, UVC_GET_RES,
-                                   uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
-               if (step == 0)
-                       step = 1;
-
-               xctrl->value = min + (xctrl->value - min + step/2) / step * step;
-               xctrl->value = clamp(xctrl->value, min, max);
-               value = xctrl->value;
-               break;
-
-       case V4L2_CTRL_TYPE_BOOLEAN:
-               xctrl->value = clamp(xctrl->value, 0, 1);
-               value = xctrl->value;
-               break;
-
-       case V4L2_CTRL_TYPE_MENU:
-               if (xctrl->value < 0 || xctrl->value >= mapping->menu_count)
-                       return -ERANGE;
-               value = mapping->menu_info[xctrl->value].value;
-
-               /* Valid menu indices are reported by the GET_RES request for
-                * UVC controls that support it.
-                */
-               if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK &&
-                   (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) {
-                       if (!ctrl->cached) {
-                               ret = uvc_ctrl_populate_cache(chain, ctrl);
-                               if (ret < 0)
-                                       return ret;
-                       }
-
-                       step = mapping->get(mapping, UVC_GET_RES,
-                                       uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES));
-                       if (!(step & value))
-                               return -ERANGE;
-               }
-
-               break;
-
-       default:
-               value = xctrl->value;
-               break;
-       }
-
-       /* If the mapping doesn't span the whole UVC control, the current value
-        * needs to be loaded from the device to perform the read-modify-write
-        * operation.
-        */
-       if (!ctrl->loaded && (ctrl->info.size * 8) != mapping->size) {
-               if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) {
-                       memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
-                               0, ctrl->info.size);
-               } else {
-                       ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
-                               ctrl->entity->id, chain->dev->intfnum,
-                               ctrl->info.selector,
-                               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
-                               ctrl->info.size);
-                       if (ret < 0)
-                               return ret;
-               }
-
-               ctrl->loaded = 1;
-       }
-
-       /* Backup the current value in case we need to rollback later. */
-       if (!ctrl->dirty) {
-               memcpy(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_BACKUP),
-                      uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
-                      ctrl->info.size);
-       }
-
-       mapping->set(mapping, value,
-               uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
-
-       ctrl->dirty = 1;
-       ctrl->modified = 1;
-       return 0;
-}
-
-/* --------------------------------------------------------------------------
- * Dynamic controls
- */
-
-static void uvc_ctrl_fixup_xu_info(struct uvc_device *dev,
-       const struct uvc_control *ctrl, struct uvc_control_info *info)
-{
-       struct uvc_ctrl_fixup {
-               struct usb_device_id id;
-               u8 entity;
-               u8 selector;
-               u8 flags;
-       };
-
-       static const struct uvc_ctrl_fixup fixups[] = {
-               { { USB_DEVICE(0x046d, 0x08c2) }, 9, 1,
-                       UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
-                       UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
-                       UVC_CTRL_FLAG_AUTO_UPDATE },
-               { { USB_DEVICE(0x046d, 0x08cc) }, 9, 1,
-                       UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
-                       UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
-                       UVC_CTRL_FLAG_AUTO_UPDATE },
-               { { USB_DEVICE(0x046d, 0x0994) }, 9, 1,
-                       UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX |
-                       UVC_CTRL_FLAG_GET_DEF | UVC_CTRL_FLAG_SET_CUR |
-                       UVC_CTRL_FLAG_AUTO_UPDATE },
-       };
-
-       unsigned int i;
-
-       for (i = 0; i < ARRAY_SIZE(fixups); ++i) {
-               if (!usb_match_one_id(dev->intf, &fixups[i].id))
-                       continue;
-
-               if (fixups[i].entity == ctrl->entity->id &&
-                   fixups[i].selector == info->selector) {
-                       info->flags = fixups[i].flags;
-                       return;
-               }
-       }
-}
-
-/*
- * Query control information (size and flags) for XU controls.
- */
-static int uvc_ctrl_fill_xu_info(struct uvc_device *dev,
-       const struct uvc_control *ctrl, struct uvc_control_info *info)
-{
-       u8 *data;
-       int ret;
-
-       data = kmalloc(2, GFP_KERNEL);
-       if (data == NULL)
-               return -ENOMEM;
-
-       memcpy(info->entity, ctrl->entity->extension.guidExtensionCode,
-              sizeof(info->entity));
-       info->index = ctrl->index;
-       info->selector = ctrl->index + 1;
-
-       /* Query and verify the control length (GET_LEN) */
-       ret = uvc_query_ctrl(dev, UVC_GET_LEN, ctrl->entity->id, dev->intfnum,
-                            info->selector, data, 2);
-       if (ret < 0) {
-               uvc_trace(UVC_TRACE_CONTROL,
-                         "GET_LEN failed on control %pUl/%u (%d).\n",
-                          info->entity, info->selector, ret);
-               goto done;
-       }
-
-       info->size = le16_to_cpup((__le16 *)data);
-
-       /* Query the control information (GET_INFO) */
-       ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, dev->intfnum,
-                            info->selector, data, 1);
-       if (ret < 0) {
-               uvc_trace(UVC_TRACE_CONTROL,
-                         "GET_INFO failed on control %pUl/%u (%d).\n",
-                         info->entity, info->selector, ret);
-               goto done;
-       }
-
-       info->flags = UVC_CTRL_FLAG_GET_MIN | UVC_CTRL_FLAG_GET_MAX
-                   | UVC_CTRL_FLAG_GET_RES | UVC_CTRL_FLAG_GET_DEF
-                   | (data[0] & UVC_CONTROL_CAP_GET ?
-                      UVC_CTRL_FLAG_GET_CUR : 0)
-                   | (data[0] & UVC_CONTROL_CAP_SET ?
-                      UVC_CTRL_FLAG_SET_CUR : 0)
-                   | (data[0] & UVC_CONTROL_CAP_AUTOUPDATE ?
-                      UVC_CTRL_FLAG_AUTO_UPDATE : 0);
-
-       uvc_ctrl_fixup_xu_info(dev, ctrl, info);
-
-       uvc_trace(UVC_TRACE_CONTROL, "XU control %pUl/%u queried: len %u, "
-                 "flags { get %u set %u auto %u }.\n",
-                 info->entity, info->selector, info->size,
-                 (info->flags & UVC_CTRL_FLAG_GET_CUR) ? 1 : 0,
-                 (info->flags & UVC_CTRL_FLAG_SET_CUR) ? 1 : 0,
-                 (info->flags & UVC_CTRL_FLAG_AUTO_UPDATE) ? 1 : 0);
-
-done:
-       kfree(data);
-       return ret;
-}
-
-static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl,
-       const struct uvc_control_info *info);
-
-static int uvc_ctrl_init_xu_ctrl(struct uvc_device *dev,
-       struct uvc_control *ctrl)
-{
-       struct uvc_control_info info;
-       int ret;
-
-       if (ctrl->initialized)
-               return 0;
-
-       ret = uvc_ctrl_fill_xu_info(dev, ctrl, &info);
-       if (ret < 0)
-               return ret;
-
-       ret = uvc_ctrl_add_info(dev, ctrl, &info);
-       if (ret < 0)
-               uvc_trace(UVC_TRACE_CONTROL, "Failed to initialize control "
-                         "%pUl/%u on device %s entity %u\n", info.entity,
-                         info.selector, dev->udev->devpath, ctrl->entity->id);
-
-       return ret;
-}
-
-int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
-       struct uvc_xu_control_query *xqry)
-{
-       struct uvc_entity *entity;
-       struct uvc_control *ctrl;
-       unsigned int i, found = 0;
-       __u32 reqflags;
-       __u16 size;
-       __u8 *data = NULL;
-       int ret;
-
-       /* Find the extension unit. */
-       list_for_each_entry(entity, &chain->entities, chain) {
-               if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT &&
-                   entity->id == xqry->unit)
-                       break;
-       }
-
-       if (entity->id != xqry->unit) {
-               uvc_trace(UVC_TRACE_CONTROL, "Extension unit %u not found.\n",
-                       xqry->unit);
-               return -ENOENT;
-       }
-
-       /* Find the control and perform delayed initialization if needed. */
-       for (i = 0; i < entity->ncontrols; ++i) {
-               ctrl = &entity->controls[i];
-               if (ctrl->index == xqry->selector - 1) {
-                       found = 1;
-                       break;
-               }
-       }
-
-       if (!found) {
-               uvc_trace(UVC_TRACE_CONTROL, "Control %pUl/%u not found.\n",
-                       entity->extension.guidExtensionCode, xqry->selector);
-               return -ENOENT;
-       }
-
-       if (mutex_lock_interruptible(&chain->ctrl_mutex))
-               return -ERESTARTSYS;
-
-       ret = uvc_ctrl_init_xu_ctrl(chain->dev, ctrl);
-       if (ret < 0) {
-               ret = -ENOENT;
-               goto done;
-       }
-
-       /* Validate the required buffer size and flags for the request */
-       reqflags = 0;
-       size = ctrl->info.size;
-
-       switch (xqry->query) {
-       case UVC_GET_CUR:
-               reqflags = UVC_CTRL_FLAG_GET_CUR;
-               break;
-       case UVC_GET_MIN:
-               reqflags = UVC_CTRL_FLAG_GET_MIN;
-               break;
-       case UVC_GET_MAX:
-               reqflags = UVC_CTRL_FLAG_GET_MAX;
-               break;
-       case UVC_GET_DEF:
-               reqflags = UVC_CTRL_FLAG_GET_DEF;
-               break;
-       case UVC_GET_RES:
-               reqflags = UVC_CTRL_FLAG_GET_RES;
-               break;
-       case UVC_SET_CUR:
-               reqflags = UVC_CTRL_FLAG_SET_CUR;
-               break;
-       case UVC_GET_LEN:
-               size = 2;
-               break;
-       case UVC_GET_INFO:
-               size = 1;
-               break;
-       default:
-               ret = -EINVAL;
-               goto done;
-       }
-
-       if (size != xqry->size) {
-               ret = -ENOBUFS;
-               goto done;
-       }
-
-       if (reqflags && !(ctrl->info.flags & reqflags)) {
-               ret = -EBADRQC;
-               goto done;
-       }
-
-       data = kmalloc(size, GFP_KERNEL);
-       if (data == NULL) {
-               ret = -ENOMEM;
-               goto done;
-       }
-
-       if (xqry->query == UVC_SET_CUR &&
-           copy_from_user(data, xqry->data, size)) {
-               ret = -EFAULT;
-               goto done;
-       }
-
-       ret = uvc_query_ctrl(chain->dev, xqry->query, xqry->unit,
-                            chain->dev->intfnum, xqry->selector, data, size);
-       if (ret < 0)
-               goto done;
-
-       if (xqry->query != UVC_SET_CUR &&
-           copy_to_user(xqry->data, data, size))
-               ret = -EFAULT;
-done:
-       kfree(data);
-       mutex_unlock(&chain->ctrl_mutex);
-       return ret;
-}
-
-/* --------------------------------------------------------------------------
- * Suspend/resume
- */
-
-/*
- * Restore control values after resume, skipping controls that haven't been
- * changed.
- *
- * TODO
- * - Don't restore modified controls that are back to their default value.
- * - Handle restore order (Auto-Exposure Mode should be restored before
- *   Exposure Time).
- */
-int uvc_ctrl_resume_device(struct uvc_device *dev)
-{
-       struct uvc_control *ctrl;
-       struct uvc_entity *entity;
-       unsigned int i;
-       int ret;
-
-       /* Walk the entities list and restore controls when possible. */
-       list_for_each_entry(entity, &dev->entities, list) {
-
-               for (i = 0; i < entity->ncontrols; ++i) {
-                       ctrl = &entity->controls[i];
-
-                       if (!ctrl->initialized || !ctrl->modified ||
-                           (ctrl->info.flags & UVC_CTRL_FLAG_RESTORE) == 0)
-                               continue;
-
-                       printk(KERN_INFO "restoring control %pUl/%u/%u\n",
-                               ctrl->info.entity, ctrl->info.index,
-                               ctrl->info.selector);
-                       ctrl->dirty = 1;
-               }
-
-               ret = uvc_ctrl_commit_entity(dev, entity, 0);
-               if (ret < 0)
-                       return ret;
-       }
-
-       return 0;
-}
-
-/* --------------------------------------------------------------------------
- * Control and mapping handling
- */
-
-/*
- * Add control information to a given control.
- */
-static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl,
-       const struct uvc_control_info *info)
-{
-       int ret = 0;
-
-       memcpy(&ctrl->info, info, sizeof(*info));
-       INIT_LIST_HEAD(&ctrl->info.mappings);
-
-       /* Allocate an array to save control values (cur, def, max, etc.) */
-       ctrl->uvc_data = kzalloc(ctrl->info.size * UVC_CTRL_DATA_LAST + 1,
-                                GFP_KERNEL);
-       if (ctrl->uvc_data == NULL) {
-               ret = -ENOMEM;
-               goto done;
-       }
-
-       ctrl->initialized = 1;
-
-       uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s "
-               "entity %u\n", ctrl->info.entity, ctrl->info.selector,
-               dev->udev->devpath, ctrl->entity->id);
-
-done:
-       if (ret < 0)
-               kfree(ctrl->uvc_data);
-       return ret;
-}
-
-/*
- * Add a control mapping to a given control.
- */
-static int __uvc_ctrl_add_mapping(struct uvc_device *dev,
-       struct uvc_control *ctrl, const struct uvc_control_mapping *mapping)
-{
-       struct uvc_control_mapping *map;
-       unsigned int size;
-
-       /* Most mappings come from static kernel data and need to be duplicated.
-        * Mappings that come from userspace will be unnecessarily duplicated,
-        * this could be optimized.
-        */
-       map = kmemdup(mapping, sizeof(*mapping), GFP_KERNEL);
-       if (map == NULL)
-               return -ENOMEM;
-
-       INIT_LIST_HEAD(&map->ev_subs);
-
-       size = sizeof(*mapping->menu_info) * mapping->menu_count;
-       map->menu_info = kmemdup(mapping->menu_info, size, GFP_KERNEL);
-       if (map->menu_info == NULL) {
-               kfree(map);
-               return -ENOMEM;
-       }
-
-       if (map->get == NULL)
-               map->get = uvc_get_le_value;
-       if (map->set == NULL)
-               map->set = uvc_set_le_value;
-
-       list_add_tail(&map->list, &ctrl->info.mappings);
-       uvc_trace(UVC_TRACE_CONTROL,
-               "Adding mapping '%s' to control %pUl/%u.\n",
-               map->name, ctrl->info.entity, ctrl->info.selector);
-
-       return 0;
-}
-
-int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
-       const struct uvc_control_mapping *mapping)
-{
-       struct uvc_device *dev = chain->dev;
-       struct uvc_control_mapping *map;
-       struct uvc_entity *entity;
-       struct uvc_control *ctrl;
-       int found = 0;
-       int ret;
-
-       if (mapping->id & ~V4L2_CTRL_ID_MASK) {
-               uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', control "
-                       "id 0x%08x is invalid.\n", mapping->name,
-                       mapping->id);
-               return -EINVAL;
-       }
-
-       /* Search for the matching (GUID/CS) control on the current chain */
-       list_for_each_entry(entity, &chain->entities, chain) {
-               unsigned int i;
-
-               if (UVC_ENTITY_TYPE(entity) != UVC_VC_EXTENSION_UNIT ||
-                   !uvc_entity_match_guid(entity, mapping->entity))
-                       continue;
-
-               for (i = 0; i < entity->ncontrols; ++i) {
-                       ctrl = &entity->controls[i];
-                       if (ctrl->index == mapping->selector - 1) {
-                               found = 1;
-                               break;
-                       }
-               }
-
-               if (found)
-                       break;
-       }
-       if (!found)
-               return -ENOENT;
-
-       if (mutex_lock_interruptible(&chain->ctrl_mutex))
-               return -ERESTARTSYS;
-
-       /* Perform delayed initialization of XU controls */
-       ret = uvc_ctrl_init_xu_ctrl(dev, ctrl);
-       if (ret < 0) {
-               ret = -ENOENT;
-               goto done;
-       }
-
-       list_for_each_entry(map, &ctrl->info.mappings, list) {
-               if (mapping->id == map->id) {
-                       uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', "
-                               "control id 0x%08x already exists.\n",
-                               mapping->name, mapping->id);
-                       ret = -EEXIST;
-                       goto done;
-               }
-       }
-
-       /* Prevent excess memory consumption */
-       if (atomic_inc_return(&dev->nmappings) > UVC_MAX_CONTROL_MAPPINGS) {
-               atomic_dec(&dev->nmappings);
-               uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', maximum "
-                       "mappings count (%u) exceeded.\n", mapping->name,
-                       UVC_MAX_CONTROL_MAPPINGS);
-               ret = -ENOMEM;
-               goto done;
-       }
-
-       ret = __uvc_ctrl_add_mapping(dev, ctrl, mapping);
-       if (ret < 0)
-               atomic_dec(&dev->nmappings);
-
-done:
-       mutex_unlock(&chain->ctrl_mutex);
-       return ret;
-}
-
-/*
- * Prune an entity of its bogus controls using a blacklist. Bogus controls
- * are currently the ones that crash the camera or unconditionally return an
- * error when queried.
- */
-static void uvc_ctrl_prune_entity(struct uvc_device *dev,
-       struct uvc_entity *entity)
-{
-       struct uvc_ctrl_blacklist {
-               struct usb_device_id id;
-               u8 index;
-       };
-
-       static const struct uvc_ctrl_blacklist processing_blacklist[] = {
-               { { USB_DEVICE(0x13d3, 0x509b) }, 9 }, /* Gain */
-               { { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */
-               { { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */
-       };
-       static const struct uvc_ctrl_blacklist camera_blacklist[] = {
-               { { USB_DEVICE(0x06f8, 0x3005) }, 9 }, /* Zoom, Absolute */
-       };
-
-       const struct uvc_ctrl_blacklist *blacklist;
-       unsigned int size;
-       unsigned int count;
-       unsigned int i;
-       u8 *controls;
-
-       switch (UVC_ENTITY_TYPE(entity)) {
-       case UVC_VC_PROCESSING_UNIT:
-               blacklist = processing_blacklist;
-               count = ARRAY_SIZE(processing_blacklist);
-               controls = entity->processing.bmControls;
-               size = entity->processing.bControlSize;
-               break;
-
-       case UVC_ITT_CAMERA:
-               blacklist = camera_blacklist;
-               count = ARRAY_SIZE(camera_blacklist);
-               controls = entity->camera.bmControls;
-               size = entity->camera.bControlSize;
-               break;
-
-       default:
-               return;
-       }
-
-       for (i = 0; i < count; ++i) {
-               if (!usb_match_one_id(dev->intf, &blacklist[i].id))
-                       continue;
-
-               if (blacklist[i].index >= 8 * size ||
-                   !uvc_test_bit(controls, blacklist[i].index))
-                       continue;
-
-               uvc_trace(UVC_TRACE_CONTROL, "%u/%u control is black listed, "
-                       "removing it.\n", entity->id, blacklist[i].index);
-
-               uvc_clear_bit(controls, blacklist[i].index);
-       }
-}
-
-/*
- * Add control information and hardcoded stock control mappings to the given
- * device.
- */
-static void uvc_ctrl_init_ctrl(struct uvc_device *dev, struct uvc_control *ctrl)
-{
-       const struct uvc_control_info *info = uvc_ctrls;
-       const struct uvc_control_info *iend = info + ARRAY_SIZE(uvc_ctrls);
-       const struct uvc_control_mapping *mapping = uvc_ctrl_mappings;
-       const struct uvc_control_mapping *mend =
-               mapping + ARRAY_SIZE(uvc_ctrl_mappings);
-
-       /* XU controls initialization requires querying the device for control
-        * information. As some buggy UVC devices will crash when queried
-        * repeatedly in a tight loop, delay XU controls initialization until
-        * first use.
-        */
-       if (UVC_ENTITY_TYPE(ctrl->entity) == UVC_VC_EXTENSION_UNIT)
-               return;
-
-       for (; info < iend; ++info) {
-               if (uvc_entity_match_guid(ctrl->entity, info->entity) &&
-                   ctrl->index == info->index) {
-                       uvc_ctrl_add_info(dev, ctrl, info);
-                       break;
-                }
-       }
-
-       if (!ctrl->initialized)
-               return;
-
-       for (; mapping < mend; ++mapping) {
-               if (uvc_entity_match_guid(ctrl->entity, mapping->entity) &&
-                   ctrl->info.selector == mapping->selector)
-                       __uvc_ctrl_add_mapping(dev, ctrl, mapping);
-       }
-}
-
-/*
- * Initialize device controls.
- */
-int uvc_ctrl_init_device(struct uvc_device *dev)
-{
-       struct uvc_entity *entity;
-       unsigned int i;
-
-       /* Walk the entities list and instantiate controls */
-       list_for_each_entry(entity, &dev->entities, list) {
-               struct uvc_control *ctrl;
-               unsigned int bControlSize = 0, ncontrols;
-               __u8 *bmControls = NULL;
-
-               if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) {
-                       bmControls = entity->extension.bmControls;
-                       bControlSize = entity->extension.bControlSize;
-               } else if (UVC_ENTITY_TYPE(entity) == UVC_VC_PROCESSING_UNIT) {
-                       bmControls = entity->processing.bmControls;
-                       bControlSize = entity->processing.bControlSize;
-               } else if (UVC_ENTITY_TYPE(entity) == UVC_ITT_CAMERA) {
-                       bmControls = entity->camera.bmControls;
-                       bControlSize = entity->camera.bControlSize;
-               }
-
-               /* Remove bogus/blacklisted controls */
-               uvc_ctrl_prune_entity(dev, entity);
-
-               /* Count supported controls and allocate the controls array */
-               ncontrols = memweight(bmControls, bControlSize);
-               if (ncontrols == 0)
-                       continue;
-
-               entity->controls = kcalloc(ncontrols, sizeof(*ctrl),
-                                          GFP_KERNEL);
-               if (entity->controls == NULL)
-                       return -ENOMEM;
-               entity->ncontrols = ncontrols;
-
-               /* Initialize all supported controls */
-               ctrl = entity->controls;
-               for (i = 0; i < bControlSize * 8; ++i) {
-                       if (uvc_test_bit(bmControls, i) == 0)
-                               continue;
-
-                       ctrl->entity = entity;
-                       ctrl->index = i;
-
-                       uvc_ctrl_init_ctrl(dev, ctrl);
-                       ctrl++;
-               }
-       }
-
-       return 0;
-}
-
-/*
- * Cleanup device controls.
- */
-static void uvc_ctrl_cleanup_mappings(struct uvc_device *dev,
-       struct uvc_control *ctrl)
-{
-       struct uvc_control_mapping *mapping, *nm;
-
-       list_for_each_entry_safe(mapping, nm, &ctrl->info.mappings, list) {
-               list_del(&mapping->list);
-               kfree(mapping->menu_info);
-               kfree(mapping);
-       }
-}
-
-void uvc_ctrl_cleanup_device(struct uvc_device *dev)
-{
-       struct uvc_entity *entity;
-       unsigned int i;
-
-       /* Free controls and control mappings for all entities. */
-       list_for_each_entry(entity, &dev->entities, list) {
-               for (i = 0; i < entity->ncontrols; ++i) {
-                       struct uvc_control *ctrl = &entity->controls[i];
-
-                       if (!ctrl->initialized)
-                               continue;
-
-                       uvc_ctrl_cleanup_mappings(dev, ctrl);
-                       kfree(ctrl->uvc_data);
-               }
-
-               kfree(entity->controls);
-       }
-}
diff --git a/drivers/media/video/uvc/uvc_debugfs.c b/drivers/media/video/uvc/uvc_debugfs.c
deleted file mode 100644 (file)
index 14561a5..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- *      uvc_debugfs.c --  USB Video Class driver - Debugging support
- *
- *      Copyright (C) 2011
- *          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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-
-#include "uvcvideo.h"
-
-/* -----------------------------------------------------------------------------
- * Statistics
- */
-
-#define UVC_DEBUGFS_BUF_SIZE   1024
-
-struct uvc_debugfs_buffer {
-       size_t count;
-       char data[UVC_DEBUGFS_BUF_SIZE];
-};
-
-static int uvc_debugfs_stats_open(struct inode *inode, struct file *file)
-{
-       struct uvc_streaming *stream = inode->i_private;
-       struct uvc_debugfs_buffer *buf;
-
-       buf = kmalloc(sizeof(*buf), GFP_KERNEL);
-       if (buf == NULL)
-               return -ENOMEM;
-
-       buf->count = uvc_video_stats_dump(stream, buf->data, sizeof(buf->data));
-
-       file->private_data = buf;
-       return 0;
-}
-
-static ssize_t uvc_debugfs_stats_read(struct file *file, char __user *user_buf,
-                                     size_t nbytes, loff_t *ppos)
-{
-       struct uvc_debugfs_buffer *buf = file->private_data;
-
-       return simple_read_from_buffer(user_buf, nbytes, ppos, buf->data,
-                                      buf->count);
-}
-
-static int uvc_debugfs_stats_release(struct inode *inode, struct file *file)
-{
-       kfree(file->private_data);
-       file->private_data = NULL;
-
-       return 0;
-}
-
-static const struct file_operations uvc_debugfs_stats_fops = {
-       .owner = THIS_MODULE,
-       .open = uvc_debugfs_stats_open,
-       .llseek = no_llseek,
-       .read = uvc_debugfs_stats_read,
-       .release = uvc_debugfs_stats_release,
-};
-
-/* -----------------------------------------------------------------------------
- * Global and stream initialization/cleanup
- */
-
-static struct dentry *uvc_debugfs_root_dir;
-
-int uvc_debugfs_init_stream(struct uvc_streaming *stream)
-{
-       struct usb_device *udev = stream->dev->udev;
-       struct dentry *dent;
-       char dir_name[32];
-
-       if (uvc_debugfs_root_dir == NULL)
-               return -ENODEV;
-
-       sprintf(dir_name, "%u-%u", udev->bus->busnum, udev->devnum);
-
-       dent = debugfs_create_dir(dir_name, uvc_debugfs_root_dir);
-       if (IS_ERR_OR_NULL(dent)) {
-               uvc_printk(KERN_INFO, "Unable to create debugfs %s "
-                          "directory.\n", dir_name);
-               return -ENODEV;
-       }
-
-       stream->debugfs_dir = dent;
-
-       dent = debugfs_create_file("stats", 0444, stream->debugfs_dir,
-                                  stream, &uvc_debugfs_stats_fops);
-       if (IS_ERR_OR_NULL(dent)) {
-               uvc_printk(KERN_INFO, "Unable to create debugfs stats file.\n");
-               uvc_debugfs_cleanup_stream(stream);
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream)
-{
-       if (stream->debugfs_dir == NULL)
-               return;
-
-       debugfs_remove_recursive(stream->debugfs_dir);
-       stream->debugfs_dir = NULL;
-}
-
-int uvc_debugfs_init(void)
-{
-       struct dentry *dir;
-
-       dir = debugfs_create_dir("uvcvideo", usb_debug_root);
-       if (IS_ERR_OR_NULL(dir)) {
-               uvc_printk(KERN_INFO, "Unable to create debugfs directory\n");
-               return -ENODATA;
-       }
-
-       uvc_debugfs_root_dir = dir;
-       return 0;
-}
-
-void uvc_debugfs_cleanup(void)
-{
-       if (uvc_debugfs_root_dir != NULL)
-               debugfs_remove_recursive(uvc_debugfs_root_dir);
-}
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
deleted file mode 100644 (file)
index 45d7aa1..0000000
+++ /dev/null
@@ -1,2472 +0,0 @@
-/*
- *      uvc_driver.c  --  USB Video Class driver
- *
- *      Copyright (C) 2005-2010
- *          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.
- *
- */
-
-/*
- * This driver aims to support video input and ouput devices compliant with the
- * 'USB Video Class' specification.
- *
- * The driver doesn't support the deprecated v4l1 interface. It implements the
- * mmap capture method only, and doesn't do any image format conversion in
- * software. If your user-space application doesn't support YUYV or MJPEG, fix
- * it :-). Please note that the MJPEG data have been stripped from their
- * Huffman tables (DHT marker), you will need to add it back if your JPEG
- * codec can't handle MJPEG data.
- */
-
-#include <linux/atomic.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include <linux/vmalloc.h>
-#include <linux/wait.h>
-#include <linux/version.h>
-#include <asm/unaligned.h>
-
-#include <media/v4l2-common.h>
-
-#include "uvcvideo.h"
-
-#define DRIVER_AUTHOR          "Laurent Pinchart " \
-                               "<laurent.pinchart@ideasonboard.com>"
-#define DRIVER_DESC            "USB Video Class driver"
-
-unsigned int uvc_clock_param = CLOCK_MONOTONIC;
-unsigned int uvc_no_drop_param;
-static unsigned int uvc_quirks_param = -1;
-unsigned int uvc_trace_param;
-unsigned int uvc_timeout_param = UVC_CTRL_STREAMING_TIMEOUT;
-
-/* ------------------------------------------------------------------------
- * Video formats
- */
-
-static struct uvc_format_desc uvc_fmts[] = {
-       {
-               .name           = "YUV 4:2:2 (YUYV)",
-               .guid           = UVC_GUID_FORMAT_YUY2,
-               .fcc            = V4L2_PIX_FMT_YUYV,
-       },
-       {
-               .name           = "YUV 4:2:2 (YUYV)",
-               .guid           = UVC_GUID_FORMAT_YUY2_ISIGHT,
-               .fcc            = V4L2_PIX_FMT_YUYV,
-       },
-       {
-               .name           = "YUV 4:2:0 (NV12)",
-               .guid           = UVC_GUID_FORMAT_NV12,
-               .fcc            = V4L2_PIX_FMT_NV12,
-       },
-       {
-               .name           = "MJPEG",
-               .guid           = UVC_GUID_FORMAT_MJPEG,
-               .fcc            = V4L2_PIX_FMT_MJPEG,
-       },
-       {
-               .name           = "YVU 4:2:0 (YV12)",
-               .guid           = UVC_GUID_FORMAT_YV12,
-               .fcc            = V4L2_PIX_FMT_YVU420,
-       },
-       {
-               .name           = "YUV 4:2:0 (I420)",
-               .guid           = UVC_GUID_FORMAT_I420,
-               .fcc            = V4L2_PIX_FMT_YUV420,
-       },
-       {
-               .name           = "YUV 4:2:0 (M420)",
-               .guid           = UVC_GUID_FORMAT_M420,
-               .fcc            = V4L2_PIX_FMT_M420,
-       },
-       {
-               .name           = "YUV 4:2:2 (UYVY)",
-               .guid           = UVC_GUID_FORMAT_UYVY,
-               .fcc            = V4L2_PIX_FMT_UYVY,
-       },
-       {
-               .name           = "Greyscale 8-bit (Y800)",
-               .guid           = UVC_GUID_FORMAT_Y800,
-               .fcc            = V4L2_PIX_FMT_GREY,
-       },
-       {
-               .name           = "Greyscale 8-bit (Y8  )",
-               .guid           = UVC_GUID_FORMAT_Y8,
-               .fcc            = V4L2_PIX_FMT_GREY,
-       },
-       {
-               .name           = "Greyscale 10-bit (Y10 )",
-               .guid           = UVC_GUID_FORMAT_Y10,
-               .fcc            = V4L2_PIX_FMT_Y10,
-       },
-       {
-               .name           = "Greyscale 12-bit (Y12 )",
-               .guid           = UVC_GUID_FORMAT_Y12,
-               .fcc            = V4L2_PIX_FMT_Y12,
-       },
-       {
-               .name           = "Greyscale 16-bit (Y16 )",
-               .guid           = UVC_GUID_FORMAT_Y16,
-               .fcc            = V4L2_PIX_FMT_Y16,
-       },
-       {
-               .name           = "RGB Bayer",
-               .guid           = UVC_GUID_FORMAT_BY8,
-               .fcc            = V4L2_PIX_FMT_SBGGR8,
-       },
-       {
-               .name           = "RGB565",
-               .guid           = UVC_GUID_FORMAT_RGBP,
-               .fcc            = V4L2_PIX_FMT_RGB565,
-       },
-       {
-               .name           = "H.264",
-               .guid           = UVC_GUID_FORMAT_H264,
-               .fcc            = V4L2_PIX_FMT_H264,
-       },
-};
-
-/* ------------------------------------------------------------------------
- * Utility functions
- */
-
-struct usb_host_endpoint *uvc_find_endpoint(struct usb_host_interface *alts,
-               __u8 epaddr)
-{
-       struct usb_host_endpoint *ep;
-       unsigned int i;
-
-       for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
-               ep = &alts->endpoint[i];
-               if (ep->desc.bEndpointAddress == epaddr)
-                       return ep;
-       }
-
-       return NULL;
-}
-
-static struct uvc_format_desc *uvc_format_by_guid(const __u8 guid[16])
-{
-       unsigned int len = ARRAY_SIZE(uvc_fmts);
-       unsigned int i;
-
-       for (i = 0; i < len; ++i) {
-               if (memcmp(guid, uvc_fmts[i].guid, 16) == 0)
-                       return &uvc_fmts[i];
-       }
-
-       return NULL;
-}
-
-static __u32 uvc_colorspace(const __u8 primaries)
-{
-       static const __u8 colorprimaries[] = {
-               0,
-               V4L2_COLORSPACE_SRGB,
-               V4L2_COLORSPACE_470_SYSTEM_M,
-               V4L2_COLORSPACE_470_SYSTEM_BG,
-               V4L2_COLORSPACE_SMPTE170M,
-               V4L2_COLORSPACE_SMPTE240M,
-       };
-
-       if (primaries < ARRAY_SIZE(colorprimaries))
-               return colorprimaries[primaries];
-
-       return 0;
-}
-
-/* Simplify a fraction using a simple continued fraction decomposition. The
- * idea here is to convert fractions such as 333333/10000000 to 1/30 using
- * 32 bit arithmetic only. The algorithm is not perfect and relies upon two
- * arbitrary parameters to remove non-significative terms from the simple
- * continued fraction decomposition. Using 8 and 333 for n_terms and threshold
- * respectively seems to give nice results.
- */
-void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator,
-               unsigned int n_terms, unsigned int threshold)
-{
-       uint32_t *an;
-       uint32_t x, y, r;
-       unsigned int i, n;
-
-       an = kmalloc(n_terms * sizeof *an, GFP_KERNEL);
-       if (an == NULL)
-               return;
-
-       /* Convert the fraction to a simple continued fraction. See
-        * http://mathforum.org/dr.math/faq/faq.fractions.html
-        * Stop if the current term is bigger than or equal to the given
-        * threshold.
-        */
-       x = *numerator;
-       y = *denominator;
-
-       for (n = 0; n < n_terms && y != 0; ++n) {
-               an[n] = x / y;
-               if (an[n] >= threshold) {
-                       if (n < 2)
-                               n++;
-                       break;
-               }
-
-               r = x - an[n] * y;
-               x = y;
-               y = r;
-       }
-
-       /* Expand the simple continued fraction back to an integer fraction. */
-       x = 0;
-       y = 1;
-
-       for (i = n; i > 0; --i) {
-               r = y;
-               y = an[i-1] * y + x;
-               x = r;
-       }
-
-       *numerator = y;
-       *denominator = x;
-       kfree(an);
-}
-
-/* Convert a fraction to a frame interval in 100ns multiples. The idea here is
- * to compute numerator / denominator * 10000000 using 32 bit fixed point
- * arithmetic only.
- */
-uint32_t uvc_fraction_to_interval(uint32_t numerator, uint32_t denominator)
-{
-       uint32_t multiplier;
-
-       /* Saturate the result if the operation would overflow. */
-       if (denominator == 0 ||
-           numerator/denominator >= ((uint32_t)-1)/10000000)
-               return (uint32_t)-1;
-
-       /* Divide both the denominator and the multiplier by two until
-        * numerator * multiplier doesn't overflow. If anyone knows a better
-        * algorithm please let me know.
-        */
-       multiplier = 10000000;
-       while (numerator > ((uint32_t)-1)/multiplier) {
-               multiplier /= 2;
-               denominator /= 2;
-       }
-
-       return denominator ? numerator * multiplier / denominator : 0;
-}
-
-/* ------------------------------------------------------------------------
- * Terminal and unit management
- */
-
-struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id)
-{
-       struct uvc_entity *entity;
-
-       list_for_each_entry(entity, &dev->entities, list) {
-               if (entity->id == id)
-                       return entity;
-       }
-
-       return NULL;
-}
-
-static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev,
-       int id, struct uvc_entity *entity)
-{
-       unsigned int i;
-
-       if (entity == NULL)
-               entity = list_entry(&dev->entities, struct uvc_entity, list);
-
-       list_for_each_entry_continue(entity, &dev->entities, list) {
-               for (i = 0; i < entity->bNrInPins; ++i)
-                       if (entity->baSourceID[i] == id)
-                               return entity;
-       }
-
-       return NULL;
-}
-
-static struct uvc_streaming *uvc_stream_by_id(struct uvc_device *dev, int id)
-{
-       struct uvc_streaming *stream;
-
-       list_for_each_entry(stream, &dev->streams, list) {
-               if (stream->header.bTerminalLink == id)
-                       return stream;
-       }
-
-       return NULL;
-}
-
-/* ------------------------------------------------------------------------
- * Descriptors parsing
- */
-
-static int uvc_parse_format(struct uvc_device *dev,
-       struct uvc_streaming *streaming, struct uvc_format *format,
-       __u32 **intervals, unsigned char *buffer, int buflen)
-{
-       struct usb_interface *intf = streaming->intf;
-       struct usb_host_interface *alts = intf->cur_altsetting;
-       struct uvc_format_desc *fmtdesc;
-       struct uvc_frame *frame;
-       const unsigned char *start = buffer;
-       unsigned int interval;
-       unsigned int i, n;
-       __u8 ftype;
-
-       format->type = buffer[2];
-       format->index = buffer[3];
-
-       switch (buffer[2]) {
-       case UVC_VS_FORMAT_UNCOMPRESSED:
-       case UVC_VS_FORMAT_FRAME_BASED:
-               n = buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED ? 27 : 28;
-               if (buflen < n) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
-                              "interface %d FORMAT error\n",
-                              dev->udev->devnum,
-                              alts->desc.bInterfaceNumber);
-                       return -EINVAL;
-               }
-
-               /* Find the format descriptor from its GUID. */
-               fmtdesc = uvc_format_by_guid(&buffer[5]);
-
-               if (fmtdesc != NULL) {
-                       strlcpy(format->name, fmtdesc->name,
-                               sizeof format->name);
-                       format->fcc = fmtdesc->fcc;
-               } else {
-                       uvc_printk(KERN_INFO, "Unknown video format %pUl\n",
-                               &buffer[5]);
-                       snprintf(format->name, sizeof(format->name), "%pUl\n",
-                               &buffer[5]);
-                       format->fcc = 0;
-               }
-
-               format->bpp = buffer[21];
-               if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) {
-                       ftype = UVC_VS_FRAME_UNCOMPRESSED;
-               } else {
-                       ftype = UVC_VS_FRAME_FRAME_BASED;
-                       if (buffer[27])
-                               format->flags = UVC_FMT_FLAG_COMPRESSED;
-               }
-               break;
-
-       case UVC_VS_FORMAT_MJPEG:
-               if (buflen < 11) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
-                              "interface %d FORMAT error\n",
-                              dev->udev->devnum,
-                              alts->desc.bInterfaceNumber);
-                       return -EINVAL;
-               }
-
-               strlcpy(format->name, "MJPEG", sizeof format->name);
-               format->fcc = V4L2_PIX_FMT_MJPEG;
-               format->flags = UVC_FMT_FLAG_COMPRESSED;
-               format->bpp = 0;
-               ftype = UVC_VS_FRAME_MJPEG;
-               break;
-
-       case UVC_VS_FORMAT_DV:
-               if (buflen < 9) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
-                              "interface %d FORMAT error\n",
-                              dev->udev->devnum,
-                              alts->desc.bInterfaceNumber);
-                       return -EINVAL;
-               }
-
-               switch (buffer[8] & 0x7f) {
-               case 0:
-                       strlcpy(format->name, "SD-DV", sizeof format->name);
-                       break;
-               case 1:
-                       strlcpy(format->name, "SDL-DV", sizeof format->name);
-                       break;
-               case 2:
-                       strlcpy(format->name, "HD-DV", sizeof format->name);
-                       break;
-               default:
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
-                              "interface %d: unknown DV format %u\n",
-                              dev->udev->devnum,
-                              alts->desc.bInterfaceNumber, buffer[8]);
-                       return -EINVAL;
-               }
-
-               strlcat(format->name, buffer[8] & (1 << 7) ? " 60Hz" : " 50Hz",
-                       sizeof format->name);
-
-               format->fcc = V4L2_PIX_FMT_DV;
-               format->flags = UVC_FMT_FLAG_COMPRESSED | UVC_FMT_FLAG_STREAM;
-               format->bpp = 0;
-               ftype = 0;
-
-               /* Create a dummy frame descriptor. */
-               frame = &format->frame[0];
-               memset(&format->frame[0], 0, sizeof format->frame[0]);
-               frame->bFrameIntervalType = 1;
-               frame->dwDefaultFrameInterval = 1;
-               frame->dwFrameInterval = *intervals;
-               *(*intervals)++ = 1;
-               format->nframes = 1;
-               break;
-
-       case UVC_VS_FORMAT_MPEG2TS:
-       case UVC_VS_FORMAT_STREAM_BASED:
-               /* Not supported yet. */
-       default:
-               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
-                      "interface %d unsupported format %u\n",
-                      dev->udev->devnum, alts->desc.bInterfaceNumber,
-                      buffer[2]);
-               return -EINVAL;
-       }
-
-       uvc_trace(UVC_TRACE_DESCR, "Found format %s.\n", format->name);
-
-       buflen -= buffer[0];
-       buffer += buffer[0];
-
-       /* Parse the frame descriptors. Only uncompressed, MJPEG and frame
-        * based formats have frame descriptors.
-        */
-       while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
-              buffer[2] == ftype) {
-               frame = &format->frame[format->nframes];
-               if (ftype != UVC_VS_FRAME_FRAME_BASED)
-                       n = buflen > 25 ? buffer[25] : 0;
-               else
-                       n = buflen > 21 ? buffer[21] : 0;
-
-               n = n ? n : 3;
-
-               if (buflen < 26 + 4*n) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
-                              "interface %d FRAME error\n", dev->udev->devnum,
-                              alts->desc.bInterfaceNumber);
-                       return -EINVAL;
-               }
-
-               frame->bFrameIndex = buffer[3];
-               frame->bmCapabilities = buffer[4];
-               frame->wWidth = get_unaligned_le16(&buffer[5]);
-               frame->wHeight = get_unaligned_le16(&buffer[7]);
-               frame->dwMinBitRate = get_unaligned_le32(&buffer[9]);
-               frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]);
-               if (ftype != UVC_VS_FRAME_FRAME_BASED) {
-                       frame->dwMaxVideoFrameBufferSize =
-                               get_unaligned_le32(&buffer[17]);
-                       frame->dwDefaultFrameInterval =
-                               get_unaligned_le32(&buffer[21]);
-                       frame->bFrameIntervalType = buffer[25];
-               } else {
-                       frame->dwMaxVideoFrameBufferSize = 0;
-                       frame->dwDefaultFrameInterval =
-                               get_unaligned_le32(&buffer[17]);
-                       frame->bFrameIntervalType = buffer[21];
-               }
-               frame->dwFrameInterval = *intervals;
-
-               /* Several UVC chipsets screw up dwMaxVideoFrameBufferSize
-                * completely. Observed behaviours range from setting the
-                * value to 1.1x the actual frame size to hardwiring the
-                * 16 low bits to 0. This results in a higher than necessary
-                * memory usage as well as a wrong image size information. For
-                * uncompressed formats this can be fixed by computing the
-                * value from the frame size.
-                */
-               if (!(format->flags & UVC_FMT_FLAG_COMPRESSED))
-                       frame->dwMaxVideoFrameBufferSize = format->bpp
-                               * frame->wWidth * frame->wHeight / 8;
-
-               /* Some bogus devices report dwMinFrameInterval equal to
-                * dwMaxFrameInterval and have dwFrameIntervalStep set to
-                * zero. Setting all null intervals to 1 fixes the problem and
-                * some other divisions by zero that could happen.
-                */
-               for (i = 0; i < n; ++i) {
-                       interval = get_unaligned_le32(&buffer[26+4*i]);
-                       *(*intervals)++ = interval ? interval : 1;
-               }
-
-               /* Make sure that the default frame interval stays between
-                * the boundaries.
-                */
-               n -= frame->bFrameIntervalType ? 1 : 2;
-               frame->dwDefaultFrameInterval =
-                       min(frame->dwFrameInterval[n],
-                           max(frame->dwFrameInterval[0],
-                               frame->dwDefaultFrameInterval));
-
-               if (dev->quirks & UVC_QUIRK_RESTRICT_FRAME_RATE) {
-                       frame->bFrameIntervalType = 1;
-                       frame->dwFrameInterval[0] =
-                               frame->dwDefaultFrameInterval;
-               }
-
-               uvc_trace(UVC_TRACE_DESCR, "- %ux%u (%u.%u fps)\n",
-                       frame->wWidth, frame->wHeight,
-                       10000000/frame->dwDefaultFrameInterval,
-                       (100000000/frame->dwDefaultFrameInterval)%10);
-
-               format->nframes++;
-               buflen -= buffer[0];
-               buffer += buffer[0];
-       }
-
-       if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
-           buffer[2] == UVC_VS_STILL_IMAGE_FRAME) {
-               buflen -= buffer[0];
-               buffer += buffer[0];
-       }
-
-       if (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
-           buffer[2] == UVC_VS_COLORFORMAT) {
-               if (buflen < 6) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
-                              "interface %d COLORFORMAT error\n",
-                              dev->udev->devnum,
-                              alts->desc.bInterfaceNumber);
-                       return -EINVAL;
-               }
-
-               format->colorspace = uvc_colorspace(buffer[3]);
-
-               buflen -= buffer[0];
-               buffer += buffer[0];
-       }
-
-       return buffer - start;
-}
-
-static int uvc_parse_streaming(struct uvc_device *dev,
-       struct usb_interface *intf)
-{
-       struct uvc_streaming *streaming = NULL;
-       struct uvc_format *format;
-       struct uvc_frame *frame;
-       struct usb_host_interface *alts = &intf->altsetting[0];
-       unsigned char *_buffer, *buffer = alts->extra;
-       int _buflen, buflen = alts->extralen;
-       unsigned int nformats = 0, nframes = 0, nintervals = 0;
-       unsigned int size, i, n, p;
-       __u32 *interval;
-       __u16 psize;
-       int ret = -EINVAL;
-
-       if (intf->cur_altsetting->desc.bInterfaceSubClass
-               != UVC_SC_VIDEOSTREAMING) {
-               uvc_trace(UVC_TRACE_DESCR, "device %d interface %d isn't a "
-                       "video streaming interface\n", dev->udev->devnum,
-                       intf->altsetting[0].desc.bInterfaceNumber);
-               return -EINVAL;
-       }
-
-       if (usb_driver_claim_interface(&uvc_driver.driver, intf, dev)) {
-               uvc_trace(UVC_TRACE_DESCR, "device %d interface %d is already "
-                       "claimed\n", dev->udev->devnum,
-                       intf->altsetting[0].desc.bInterfaceNumber);
-               return -EINVAL;
-       }
-
-       streaming = kzalloc(sizeof *streaming, GFP_KERNEL);
-       if (streaming == NULL) {
-               usb_driver_release_interface(&uvc_driver.driver, intf);
-               return -EINVAL;
-       }
-
-       mutex_init(&streaming->mutex);
-       streaming->dev = dev;
-       streaming->intf = usb_get_intf(intf);
-       streaming->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
-
-       /* The Pico iMage webcam has its class-specific interface descriptors
-        * after the endpoint descriptors.
-        */
-       if (buflen == 0) {
-               for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
-                       struct usb_host_endpoint *ep = &alts->endpoint[i];
-
-                       if (ep->extralen == 0)
-                               continue;
-
-                       if (ep->extralen > 2 &&
-                           ep->extra[1] == USB_DT_CS_INTERFACE) {
-                               uvc_trace(UVC_TRACE_DESCR, "trying extra data "
-                                       "from endpoint %u.\n", i);
-                               buffer = alts->endpoint[i].extra;
-                               buflen = alts->endpoint[i].extralen;
-                               break;
-                       }
-               }
-       }
-
-       /* Skip the standard interface descriptors. */
-       while (buflen > 2 && buffer[1] != USB_DT_CS_INTERFACE) {
-               buflen -= buffer[0];
-               buffer += buffer[0];
-       }
-
-       if (buflen <= 2) {
-               uvc_trace(UVC_TRACE_DESCR, "no class-specific streaming "
-                       "interface descriptors found.\n");
-               goto error;
-       }
-
-       /* Parse the header descriptor. */
-       switch (buffer[2]) {
-       case UVC_VS_OUTPUT_HEADER:
-               streaming->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-               size = 9;
-               break;
-
-       case UVC_VS_INPUT_HEADER:
-               streaming->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               size = 13;
-               break;
-
-       default:
-               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
-                       "%d HEADER descriptor not found.\n", dev->udev->devnum,
-                       alts->desc.bInterfaceNumber);
-               goto error;
-       }
-
-       p = buflen >= 4 ? buffer[3] : 0;
-       n = buflen >= size ? buffer[size-1] : 0;
-
-       if (buflen < size + p*n) {
-               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
-                       "interface %d HEADER descriptor is invalid.\n",
-                       dev->udev->devnum, alts->desc.bInterfaceNumber);
-               goto error;
-       }
-
-       streaming->header.bNumFormats = p;
-       streaming->header.bEndpointAddress = buffer[6];
-       if (buffer[2] == UVC_VS_INPUT_HEADER) {
-               streaming->header.bmInfo = buffer[7];
-               streaming->header.bTerminalLink = buffer[8];
-               streaming->header.bStillCaptureMethod = buffer[9];
-               streaming->header.bTriggerSupport = buffer[10];
-               streaming->header.bTriggerUsage = buffer[11];
-       } else {
-               streaming->header.bTerminalLink = buffer[7];
-       }
-       streaming->header.bControlSize = n;
-
-       streaming->header.bmaControls = kmemdup(&buffer[size], p * n,
-                                               GFP_KERNEL);
-       if (streaming->header.bmaControls == NULL) {
-               ret = -ENOMEM;
-               goto error;
-       }
-
-       buflen -= buffer[0];
-       buffer += buffer[0];
-
-       _buffer = buffer;
-       _buflen = buflen;
-
-       /* Count the format and frame descriptors. */
-       while (_buflen > 2 && _buffer[1] == USB_DT_CS_INTERFACE) {
-               switch (_buffer[2]) {
-               case UVC_VS_FORMAT_UNCOMPRESSED:
-               case UVC_VS_FORMAT_MJPEG:
-               case UVC_VS_FORMAT_FRAME_BASED:
-                       nformats++;
-                       break;
-
-               case UVC_VS_FORMAT_DV:
-                       /* DV format has no frame descriptor. We will create a
-                        * dummy frame descriptor with a dummy frame interval.
-                        */
-                       nformats++;
-                       nframes++;
-                       nintervals++;
-                       break;
-
-               case UVC_VS_FORMAT_MPEG2TS:
-               case UVC_VS_FORMAT_STREAM_BASED:
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming "
-                               "interface %d FORMAT %u is not supported.\n",
-                               dev->udev->devnum,
-                               alts->desc.bInterfaceNumber, _buffer[2]);
-                       break;
-
-               case UVC_VS_FRAME_UNCOMPRESSED:
-               case UVC_VS_FRAME_MJPEG:
-                       nframes++;
-                       if (_buflen > 25)
-                               nintervals += _buffer[25] ? _buffer[25] : 3;
-                       break;
-
-               case UVC_VS_FRAME_FRAME_BASED:
-                       nframes++;
-                       if (_buflen > 21)
-                               nintervals += _buffer[21] ? _buffer[21] : 3;
-                       break;
-               }
-
-               _buflen -= _buffer[0];
-               _buffer += _buffer[0];
-       }
-
-       if (nformats == 0) {
-               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
-                       "%d has no supported formats defined.\n",
-                       dev->udev->devnum, alts->desc.bInterfaceNumber);
-               goto error;
-       }
-
-       size = nformats * sizeof *format + nframes * sizeof *frame
-            + nintervals * sizeof *interval;
-       format = kzalloc(size, GFP_KERNEL);
-       if (format == NULL) {
-               ret = -ENOMEM;
-               goto error;
-       }
-
-       frame = (struct uvc_frame *)&format[nformats];
-       interval = (__u32 *)&frame[nframes];
-
-       streaming->format = format;
-       streaming->nformats = nformats;
-
-       /* Parse the format descriptors. */
-       while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) {
-               switch (buffer[2]) {
-               case UVC_VS_FORMAT_UNCOMPRESSED:
-               case UVC_VS_FORMAT_MJPEG:
-               case UVC_VS_FORMAT_DV:
-               case UVC_VS_FORMAT_FRAME_BASED:
-                       format->frame = frame;
-                       ret = uvc_parse_format(dev, streaming, format,
-                               &interval, buffer, buflen);
-                       if (ret < 0)
-                               goto error;
-
-                       frame += format->nframes;
-                       format++;
-
-                       buflen -= ret;
-                       buffer += ret;
-                       continue;
-
-               default:
-                       break;
-               }
-
-               buflen -= buffer[0];
-               buffer += buffer[0];
-       }
-
-       if (buflen)
-               uvc_trace(UVC_TRACE_DESCR, "device %d videostreaming interface "
-                       "%d has %u bytes of trailing descriptor garbage.\n",
-                       dev->udev->devnum, alts->desc.bInterfaceNumber, buflen);
-
-       /* Parse the alternate settings to find the maximum bandwidth. */
-       for (i = 0; i < intf->num_altsetting; ++i) {
-               struct usb_host_endpoint *ep;
-               alts = &intf->altsetting[i];
-               ep = uvc_find_endpoint(alts,
-                               streaming->header.bEndpointAddress);
-               if (ep == NULL)
-                       continue;
-
-               psize = le16_to_cpu(ep->desc.wMaxPacketSize);
-               psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
-               if (psize > streaming->maxpsize)
-                       streaming->maxpsize = psize;
-       }
-
-       list_add_tail(&streaming->list, &dev->streams);
-       return 0;
-
-error:
-       usb_driver_release_interface(&uvc_driver.driver, intf);
-       usb_put_intf(intf);
-       kfree(streaming->format);
-       kfree(streaming->header.bmaControls);
-       kfree(streaming);
-       return ret;
-}
-
-static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,
-               unsigned int num_pads, unsigned int extra_size)
-{
-       struct uvc_entity *entity;
-       unsigned int num_inputs;
-       unsigned int size;
-       unsigned int i;
-
-       extra_size = ALIGN(extra_size, sizeof(*entity->pads));
-       num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1;
-       size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads
-            + num_inputs;
-       entity = kzalloc(size, GFP_KERNEL);
-       if (entity == NULL)
-               return NULL;
-
-       entity->id = id;
-       entity->type = type;
-
-       entity->num_links = 0;
-       entity->num_pads = num_pads;
-       entity->pads = ((void *)(entity + 1)) + extra_size;
-
-       for (i = 0; i < num_inputs; ++i)
-               entity->pads[i].flags = MEDIA_PAD_FL_SINK;
-       if (!UVC_ENTITY_IS_OTERM(entity))
-               entity->pads[num_pads-1].flags = MEDIA_PAD_FL_SOURCE;
-
-       entity->bNrInPins = num_inputs;
-       entity->baSourceID = (__u8 *)(&entity->pads[num_pads]);
-
-       return entity;
-}
-
-/* Parse vendor-specific extensions. */
-static int uvc_parse_vendor_control(struct uvc_device *dev,
-       const unsigned char *buffer, int buflen)
-{
-       struct usb_device *udev = dev->udev;
-       struct usb_host_interface *alts = dev->intf->cur_altsetting;
-       struct uvc_entity *unit;
-       unsigned int n, p;
-       int handled = 0;
-
-       switch (le16_to_cpu(dev->udev->descriptor.idVendor)) {
-       case 0x046d:            /* Logitech */
-               if (buffer[1] != 0x41 || buffer[2] != 0x01)
-                       break;
-
-               /* Logitech implements several vendor specific functions
-                * through vendor specific extension units (LXU).
-                *
-                * The LXU descriptors are similar to XU descriptors
-                * (see "USB Device Video Class for Video Devices", section
-                * 3.7.2.6 "Extension Unit Descriptor") with the following
-                * differences:
-                *
-                * ----------------------------------------------------------
-                * 0            bLength         1        Number
-                *      Size of this descriptor, in bytes: 24+p+n*2
-                * ----------------------------------------------------------
-                * 23+p+n       bmControlsType  N       Bitmap
-                *      Individual bits in the set are defined:
-                *      0: Absolute
-                *      1: Relative
-                *
-                *      This bitset is mapped exactly the same as bmControls.
-                * ----------------------------------------------------------
-                * 23+p+n*2     bReserved       1       Boolean
-                * ----------------------------------------------------------
-                * 24+p+n*2     iExtension      1       Index
-                *      Index of a string descriptor that describes this
-                *      extension unit.
-                * ----------------------------------------------------------
-                */
-               p = buflen >= 22 ? buffer[21] : 0;
-               n = buflen >= 25 + p ? buffer[22+p] : 0;
-
-               if (buflen < 25 + p + 2*n) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
-                               "interface %d EXTENSION_UNIT error\n",
-                               udev->devnum, alts->desc.bInterfaceNumber);
-                       break;
-               }
-
-               unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3],
-                                       p + 1, 2*n);
-               if (unit == NULL)
-                       return -ENOMEM;
-
-               memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
-               unit->extension.bNumControls = buffer[20];
-               memcpy(unit->baSourceID, &buffer[22], p);
-               unit->extension.bControlSize = buffer[22+p];
-               unit->extension.bmControls = (__u8 *)unit + sizeof(*unit);
-               unit->extension.bmControlsType = (__u8 *)unit + sizeof(*unit)
-                                              + n;
-               memcpy(unit->extension.bmControls, &buffer[23+p], 2*n);
-
-               if (buffer[24+p+2*n] != 0)
-                       usb_string(udev, buffer[24+p+2*n], unit->name,
-                                  sizeof unit->name);
-               else
-                       sprintf(unit->name, "Extension %u", buffer[3]);
-
-               list_add_tail(&unit->list, &dev->entities);
-               handled = 1;
-               break;
-       }
-
-       return handled;
-}
-
-static int uvc_parse_standard_control(struct uvc_device *dev,
-       const unsigned char *buffer, int buflen)
-{
-       struct usb_device *udev = dev->udev;
-       struct uvc_entity *unit, *term;
-       struct usb_interface *intf;
-       struct usb_host_interface *alts = dev->intf->cur_altsetting;
-       unsigned int i, n, p, len;
-       __u16 type;
-
-       switch (buffer[2]) {
-       case UVC_VC_HEADER:
-               n = buflen >= 12 ? buffer[11] : 0;
-
-               if (buflen < 12 || buflen < 12 + n) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
-                               "interface %d HEADER error\n", udev->devnum,
-                               alts->desc.bInterfaceNumber);
-                       return -EINVAL;
-               }
-
-               dev->uvc_version = get_unaligned_le16(&buffer[3]);
-               dev->clock_frequency = get_unaligned_le32(&buffer[7]);
-
-               /* Parse all USB Video Streaming interfaces. */
-               for (i = 0; i < n; ++i) {
-                       intf = usb_ifnum_to_if(udev, buffer[12+i]);
-                       if (intf == NULL) {
-                               uvc_trace(UVC_TRACE_DESCR, "device %d "
-                                       "interface %d doesn't exists\n",
-                                       udev->devnum, i);
-                               continue;
-                       }
-
-                       uvc_parse_streaming(dev, intf);
-               }
-               break;
-
-       case UVC_VC_INPUT_TERMINAL:
-               if (buflen < 8) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
-                               "interface %d INPUT_TERMINAL error\n",
-                               udev->devnum, alts->desc.bInterfaceNumber);
-                       return -EINVAL;
-               }
-
-               /* Make sure the terminal type MSB is not null, otherwise it
-                * could be confused with a unit.
-                */
-               type = get_unaligned_le16(&buffer[4]);
-               if ((type & 0xff00) == 0) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
-                               "interface %d INPUT_TERMINAL %d has invalid "
-                               "type 0x%04x, skipping\n", udev->devnum,
-                               alts->desc.bInterfaceNumber,
-                               buffer[3], type);
-                       return 0;
-               }
-
-               n = 0;
-               p = 0;
-               len = 8;
-
-               if (type == UVC_ITT_CAMERA) {
-                       n = buflen >= 15 ? buffer[14] : 0;
-                       len = 15;
-
-               } else if (type == UVC_ITT_MEDIA_TRANSPORT_INPUT) {
-                       n = buflen >= 9 ? buffer[8] : 0;
-                       p = buflen >= 10 + n ? buffer[9+n] : 0;
-                       len = 10;
-               }
-
-               if (buflen < len + n + p) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
-                               "interface %d INPUT_TERMINAL error\n",
-                               udev->devnum, alts->desc.bInterfaceNumber);
-                       return -EINVAL;
-               }
-
-               term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3],
-                                       1, n + p);
-               if (term == NULL)
-                       return -ENOMEM;
-
-               if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) {
-                       term->camera.bControlSize = n;
-                       term->camera.bmControls = (__u8 *)term + sizeof *term;
-                       term->camera.wObjectiveFocalLengthMin =
-                               get_unaligned_le16(&buffer[8]);
-                       term->camera.wObjectiveFocalLengthMax =
-                               get_unaligned_le16(&buffer[10]);
-                       term->camera.wOcularFocalLength =
-                               get_unaligned_le16(&buffer[12]);
-                       memcpy(term->camera.bmControls, &buffer[15], n);
-               } else if (UVC_ENTITY_TYPE(term) ==
-                          UVC_ITT_MEDIA_TRANSPORT_INPUT) {
-                       term->media.bControlSize = n;
-                       term->media.bmControls = (__u8 *)term + sizeof *term;
-                       term->media.bTransportModeSize = p;
-                       term->media.bmTransportModes = (__u8 *)term
-                                                    + sizeof *term + n;
-                       memcpy(term->media.bmControls, &buffer[9], n);
-                       memcpy(term->media.bmTransportModes, &buffer[10+n], p);
-               }
-
-               if (buffer[7] != 0)
-                       usb_string(udev, buffer[7], term->name,
-                                  sizeof term->name);
-               else if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA)
-                       sprintf(term->name, "Camera %u", buffer[3]);
-               else if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT)
-                       sprintf(term->name, "Media %u", buffer[3]);
-               else
-                       sprintf(term->name, "Input %u", buffer[3]);
-
-               list_add_tail(&term->list, &dev->entities);
-               break;
-
-       case UVC_VC_OUTPUT_TERMINAL:
-               if (buflen < 9) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
-                               "interface %d OUTPUT_TERMINAL error\n",
-                               udev->devnum, alts->desc.bInterfaceNumber);
-                       return -EINVAL;
-               }
-
-               /* Make sure the terminal type MSB is not null, otherwise it
-                * could be confused with a unit.
-                */
-               type = get_unaligned_le16(&buffer[4]);
-               if ((type & 0xff00) == 0) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
-                               "interface %d OUTPUT_TERMINAL %d has invalid "
-                               "type 0x%04x, skipping\n", udev->devnum,
-                               alts->desc.bInterfaceNumber, buffer[3], type);
-                       return 0;
-               }
-
-               term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3],
-                                       1, 0);
-               if (term == NULL)
-                       return -ENOMEM;
-
-               memcpy(term->baSourceID, &buffer[7], 1);
-
-               if (buffer[8] != 0)
-                       usb_string(udev, buffer[8], term->name,
-                                  sizeof term->name);
-               else
-                       sprintf(term->name, "Output %u", buffer[3]);
-
-               list_add_tail(&term->list, &dev->entities);
-               break;
-
-       case UVC_VC_SELECTOR_UNIT:
-               p = buflen >= 5 ? buffer[4] : 0;
-
-               if (buflen < 5 || buflen < 6 + p) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
-                               "interface %d SELECTOR_UNIT error\n",
-                               udev->devnum, alts->desc.bInterfaceNumber);
-                       return -EINVAL;
-               }
-
-               unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0);
-               if (unit == NULL)
-                       return -ENOMEM;
-
-               memcpy(unit->baSourceID, &buffer[5], p);
-
-               if (buffer[5+p] != 0)
-                       usb_string(udev, buffer[5+p], unit->name,
-                                  sizeof unit->name);
-               else
-                       sprintf(unit->name, "Selector %u", buffer[3]);
-
-               list_add_tail(&unit->list, &dev->entities);
-               break;
-
-       case UVC_VC_PROCESSING_UNIT:
-               n = buflen >= 8 ? buffer[7] : 0;
-               p = dev->uvc_version >= 0x0110 ? 10 : 9;
-
-               if (buflen < p + n) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
-                               "interface %d PROCESSING_UNIT error\n",
-                               udev->devnum, alts->desc.bInterfaceNumber);
-                       return -EINVAL;
-               }
-
-               unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n);
-               if (unit == NULL)
-                       return -ENOMEM;
-
-               memcpy(unit->baSourceID, &buffer[4], 1);
-               unit->processing.wMaxMultiplier =
-                       get_unaligned_le16(&buffer[5]);
-               unit->processing.bControlSize = buffer[7];
-               unit->processing.bmControls = (__u8 *)unit + sizeof *unit;
-               memcpy(unit->processing.bmControls, &buffer[8], n);
-               if (dev->uvc_version >= 0x0110)
-                       unit->processing.bmVideoStandards = buffer[9+n];
-
-               if (buffer[8+n] != 0)
-                       usb_string(udev, buffer[8+n], unit->name,
-                                  sizeof unit->name);
-               else
-                       sprintf(unit->name, "Processing %u", buffer[3]);
-
-               list_add_tail(&unit->list, &dev->entities);
-               break;
-
-       case UVC_VC_EXTENSION_UNIT:
-               p = buflen >= 22 ? buffer[21] : 0;
-               n = buflen >= 24 + p ? buffer[22+p] : 0;
-
-               if (buflen < 24 + p + n) {
-                       uvc_trace(UVC_TRACE_DESCR, "device %d videocontrol "
-                               "interface %d EXTENSION_UNIT error\n",
-                               udev->devnum, alts->desc.bInterfaceNumber);
-                       return -EINVAL;
-               }
-
-               unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n);
-               if (unit == NULL)
-                       return -ENOMEM;
-
-               memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
-               unit->extension.bNumControls = buffer[20];
-               memcpy(unit->baSourceID, &buffer[22], p);
-               unit->extension.bControlSize = buffer[22+p];
-               unit->extension.bmControls = (__u8 *)unit + sizeof *unit;
-               memcpy(unit->extension.bmControls, &buffer[23+p], n);
-
-               if (buffer[23+p+n] != 0)
-                       usb_string(udev, buffer[23+p+n], unit->name,
-                                  sizeof unit->name);
-               else
-                       sprintf(unit->name, "Extension %u", buffer[3]);
-
-               list_add_tail(&unit->list, &dev->entities);
-               break;
-
-       default:
-               uvc_trace(UVC_TRACE_DESCR, "Found an unknown CS_INTERFACE "
-                       "descriptor (%u)\n", buffer[2]);
-               break;
-       }
-
-       return 0;
-}
-
-static int uvc_parse_control(struct uvc_device *dev)
-{
-       struct usb_host_interface *alts = dev->intf->cur_altsetting;
-       unsigned char *buffer = alts->extra;
-       int buflen = alts->extralen;
-       int ret;
-
-       /* Parse the default alternate setting only, as the UVC specification
-        * defines a single alternate setting, the default alternate setting
-        * zero.
-        */
-
-       while (buflen > 2) {
-               if (uvc_parse_vendor_control(dev, buffer, buflen) ||
-                   buffer[1] != USB_DT_CS_INTERFACE)
-                       goto next_descriptor;
-
-               if ((ret = uvc_parse_standard_control(dev, buffer, buflen)) < 0)
-                       return ret;
-
-next_descriptor:
-               buflen -= buffer[0];
-               buffer += buffer[0];
-       }
-
-       /* Check if the optional status endpoint is present. Built-in iSight
-        * webcams have an interrupt endpoint but spit proprietary data that
-        * don't conform to the UVC status endpoint messages. Don't try to
-        * handle the interrupt endpoint for those cameras.
-        */
-       if (alts->desc.bNumEndpoints == 1 &&
-           !(dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)) {
-               struct usb_host_endpoint *ep = &alts->endpoint[0];
-               struct usb_endpoint_descriptor *desc = &ep->desc;
-
-               if (usb_endpoint_is_int_in(desc) &&
-                   le16_to_cpu(desc->wMaxPacketSize) >= 8 &&
-                   desc->bInterval != 0) {
-                       uvc_trace(UVC_TRACE_DESCR, "Found a Status endpoint "
-                               "(addr %02x).\n", desc->bEndpointAddress);
-                       dev->int_ep = ep;
-               }
-       }
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------------
- * UVC device scan
- */
-
-/*
- * Scan the UVC descriptors to locate a chain starting at an Output Terminal
- * and containing the following units:
- *
- * - one or more Output Terminals (USB Streaming or Display)
- * - zero or one Processing Unit
- * - zero, one or more single-input Selector Units
- * - zero or one multiple-input Selector Units, provided all inputs are
- *   connected to input terminals
- * - zero, one or mode single-input Extension Units
- * - one or more Input Terminals (Camera, External or USB Streaming)
- *
- * The terminal and units must match on of the following structures:
- *
- * ITT_*(0) -> +---------+    +---------+    +---------+ -> TT_STREAMING(0)
- * ...         | SU{0,1} | -> | PU{0,1} | -> | XU{0,n} |    ...
- * ITT_*(n) -> +---------+    +---------+    +---------+ -> TT_STREAMING(n)
- *
- *                 +---------+    +---------+ -> OTT_*(0)
- * TT_STREAMING -> | PU{0,1} | -> | XU{0,n} |    ...
- *                 +---------+    +---------+ -> OTT_*(n)
- *
- * The Processing Unit and Extension Units can be in any order. Additional
- * Extension Units connected to the main chain as single-unit branches are
- * also supported. Single-input Selector Units are ignored.
- */
-static int uvc_scan_chain_entity(struct uvc_video_chain *chain,
-       struct uvc_entity *entity)
-{
-       switch (UVC_ENTITY_TYPE(entity)) {
-       case UVC_VC_EXTENSION_UNIT:
-               if (uvc_trace_param & UVC_TRACE_PROBE)
-                       printk(" <- XU %d", entity->id);
-
-               if (entity->bNrInPins != 1) {
-                       uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more "
-                               "than 1 input pin.\n", entity->id);
-                       return -1;
-               }
-
-               break;
-
-       case UVC_VC_PROCESSING_UNIT:
-               if (uvc_trace_param & UVC_TRACE_PROBE)
-                       printk(" <- PU %d", entity->id);
-
-               if (chain->processing != NULL) {
-                       uvc_trace(UVC_TRACE_DESCR, "Found multiple "
-                               "Processing Units in chain.\n");
-                       return -1;
-               }
-
-               chain->processing = entity;
-               break;
-
-       case UVC_VC_SELECTOR_UNIT:
-               if (uvc_trace_param & UVC_TRACE_PROBE)
-                       printk(" <- SU %d", entity->id);
-
-               /* Single-input selector units are ignored. */
-               if (entity->bNrInPins == 1)
-                       break;
-
-               if (chain->selector != NULL) {
-                       uvc_trace(UVC_TRACE_DESCR, "Found multiple Selector "
-                               "Units in chain.\n");
-                       return -1;
-               }
-
-               chain->selector = entity;
-               break;
-
-       case UVC_ITT_VENDOR_SPECIFIC:
-       case UVC_ITT_CAMERA:
-       case UVC_ITT_MEDIA_TRANSPORT_INPUT:
-               if (uvc_trace_param & UVC_TRACE_PROBE)
-                       printk(" <- IT %d\n", entity->id);
-
-               break;
-
-       case UVC_OTT_VENDOR_SPECIFIC:
-       case UVC_OTT_DISPLAY:
-       case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
-               if (uvc_trace_param & UVC_TRACE_PROBE)
-                       printk(" OT %d", entity->id);
-
-               break;
-
-       case UVC_TT_STREAMING:
-               if (UVC_ENTITY_IS_ITERM(entity)) {
-                       if (uvc_trace_param & UVC_TRACE_PROBE)
-                               printk(" <- IT %d\n", entity->id);
-               } else {
-                       if (uvc_trace_param & UVC_TRACE_PROBE)
-                               printk(" OT %d", entity->id);
-               }
-
-               break;
-
-       default:
-               uvc_trace(UVC_TRACE_DESCR, "Unsupported entity type "
-                       "0x%04x found in chain.\n", UVC_ENTITY_TYPE(entity));
-               return -1;
-       }
-
-       list_add_tail(&entity->chain, &chain->entities);
-       return 0;
-}
-
-static int uvc_scan_chain_forward(struct uvc_video_chain *chain,
-       struct uvc_entity *entity, struct uvc_entity *prev)
-{
-       struct uvc_entity *forward;
-       int found;
-
-       /* Forward scan */
-       forward = NULL;
-       found = 0;
-
-       while (1) {
-               forward = uvc_entity_by_reference(chain->dev, entity->id,
-                       forward);
-               if (forward == NULL)
-                       break;
-               if (forward == prev)
-                       continue;
-
-               switch (UVC_ENTITY_TYPE(forward)) {
-               case UVC_VC_EXTENSION_UNIT:
-                       if (forward->bNrInPins != 1) {
-                               uvc_trace(UVC_TRACE_DESCR, "Extension unit %d "
-                                         "has more than 1 input pin.\n",
-                                         entity->id);
-                               return -EINVAL;
-                       }
-
-                       list_add_tail(&forward->chain, &chain->entities);
-                       if (uvc_trace_param & UVC_TRACE_PROBE) {
-                               if (!found)
-                                       printk(" (->");
-
-                               printk(" XU %d", forward->id);
-                               found = 1;
-                       }
-                       break;
-
-               case UVC_OTT_VENDOR_SPECIFIC:
-               case UVC_OTT_DISPLAY:
-               case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
-               case UVC_TT_STREAMING:
-                       if (UVC_ENTITY_IS_ITERM(forward)) {
-                               uvc_trace(UVC_TRACE_DESCR, "Unsupported input "
-                                       "terminal %u.\n", forward->id);
-                               return -EINVAL;
-                       }
-
-                       list_add_tail(&forward->chain, &chain->entities);
-                       if (uvc_trace_param & UVC_TRACE_PROBE) {
-                               if (!found)
-                                       printk(" (->");
-
-                               printk(" OT %d", forward->id);
-                               found = 1;
-                       }
-                       break;
-               }
-       }
-       if (found)
-               printk(")");
-
-       return 0;
-}
-
-static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
-       struct uvc_entity **_entity)
-{
-       struct uvc_entity *entity = *_entity;
-       struct uvc_entity *term;
-       int id = -EINVAL, i;
-
-       switch (UVC_ENTITY_TYPE(entity)) {
-       case UVC_VC_EXTENSION_UNIT:
-       case UVC_VC_PROCESSING_UNIT:
-               id = entity->baSourceID[0];
-               break;
-
-       case UVC_VC_SELECTOR_UNIT:
-               /* Single-input selector units are ignored. */
-               if (entity->bNrInPins == 1) {
-                       id = entity->baSourceID[0];
-                       break;
-               }
-
-               if (uvc_trace_param & UVC_TRACE_PROBE)
-                       printk(" <- IT");
-
-               chain->selector = entity;
-               for (i = 0; i < entity->bNrInPins; ++i) {
-                       id = entity->baSourceID[i];
-                       term = uvc_entity_by_id(chain->dev, id);
-                       if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) {
-                               uvc_trace(UVC_TRACE_DESCR, "Selector unit %d "
-                                       "input %d isn't connected to an "
-                                       "input terminal\n", entity->id, i);
-                               return -1;
-                       }
-
-                       if (uvc_trace_param & UVC_TRACE_PROBE)
-                               printk(" %d", term->id);
-
-                       list_add_tail(&term->chain, &chain->entities);
-                       uvc_scan_chain_forward(chain, term, entity);
-               }
-
-               if (uvc_trace_param & UVC_TRACE_PROBE)
-                       printk("\n");
-
-               id = 0;
-               break;
-
-       case UVC_ITT_VENDOR_SPECIFIC:
-       case UVC_ITT_CAMERA:
-       case UVC_ITT_MEDIA_TRANSPORT_INPUT:
-       case UVC_OTT_VENDOR_SPECIFIC:
-       case UVC_OTT_DISPLAY:
-       case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
-       case UVC_TT_STREAMING:
-               id = UVC_ENTITY_IS_OTERM(entity) ? entity->baSourceID[0] : 0;
-               break;
-       }
-
-       if (id <= 0) {
-               *_entity = NULL;
-               return id;
-       }
-
-       entity = uvc_entity_by_id(chain->dev, id);
-       if (entity == NULL) {
-               uvc_trace(UVC_TRACE_DESCR, "Found reference to "
-                       "unknown entity %d.\n", id);
-               return -EINVAL;
-       }
-
-       *_entity = entity;
-       return 0;
-}
-
-static int uvc_scan_chain(struct uvc_video_chain *chain,
-                         struct uvc_entity *term)
-{
-       struct uvc_entity *entity, *prev;
-
-       uvc_trace(UVC_TRACE_PROBE, "Scanning UVC chain:");
-
-       entity = term;
-       prev = NULL;
-
-       while (entity != NULL) {
-               /* Entity must not be part of an existing chain */
-               if (entity->chain.next || entity->chain.prev) {
-                       uvc_trace(UVC_TRACE_DESCR, "Found reference to "
-                               "entity %d already in chain.\n", entity->id);
-                       return -EINVAL;
-               }
-
-               /* Process entity */
-               if (uvc_scan_chain_entity(chain, entity) < 0)
-                       return -EINVAL;
-
-               /* Forward scan */
-               if (uvc_scan_chain_forward(chain, entity, prev) < 0)
-                       return -EINVAL;
-
-               /* Backward scan */
-               prev = entity;
-               if (uvc_scan_chain_backward(chain, &entity) < 0)
-                       return -EINVAL;
-       }
-
-       return 0;
-}
-
-static unsigned int uvc_print_terms(struct list_head *terms, u16 dir,
-               char *buffer)
-{
-       struct uvc_entity *term;
-       unsigned int nterms = 0;
-       char *p = buffer;
-
-       list_for_each_entry(term, terms, chain) {
-               if (!UVC_ENTITY_IS_TERM(term) ||
-                   UVC_TERM_DIRECTION(term) != dir)
-                       continue;
-
-               if (nterms)
-                       p += sprintf(p, ",");
-               if (++nterms >= 4) {
-                       p += sprintf(p, "...");
-                       break;
-               }
-               p += sprintf(p, "%u", term->id);
-       }
-
-       return p - buffer;
-}
-
-static const char *uvc_print_chain(struct uvc_video_chain *chain)
-{
-       static char buffer[43];
-       char *p = buffer;
-
-       p += uvc_print_terms(&chain->entities, UVC_TERM_INPUT, p);
-       p += sprintf(p, " -> ");
-       uvc_print_terms(&chain->entities, UVC_TERM_OUTPUT, p);
-
-       return buffer;
-}
-
-/*
- * Scan the device for video chains and register video devices.
- *
- * Chains are scanned starting at their output terminals and walked backwards.
- */
-static int uvc_scan_device(struct uvc_device *dev)
-{
-       struct uvc_video_chain *chain;
-       struct uvc_entity *term;
-
-       list_for_each_entry(term, &dev->entities, list) {
-               if (!UVC_ENTITY_IS_OTERM(term))
-                       continue;
-
-               /* If the terminal is already included in a chain, skip it.
-                * This can happen for chains that have multiple output
-                * terminals, where all output terminals beside the first one
-                * will be inserted in the chain in forward scans.
-                */
-               if (term->chain.next || term->chain.prev)
-                       continue;
-
-               chain = kzalloc(sizeof(*chain), GFP_KERNEL);
-               if (chain == NULL)
-                       return -ENOMEM;
-
-               INIT_LIST_HEAD(&chain->entities);
-               mutex_init(&chain->ctrl_mutex);
-               chain->dev = dev;
-
-               if (uvc_scan_chain(chain, term) < 0) {
-                       kfree(chain);
-                       continue;
-               }
-
-               uvc_trace(UVC_TRACE_PROBE, "Found a valid video chain (%s).\n",
-                         uvc_print_chain(chain));
-
-               list_add_tail(&chain->list, &dev->chains);
-       }
-
-       if (list_empty(&dev->chains)) {
-               uvc_printk(KERN_INFO, "No valid video chain found.\n");
-               return -1;
-       }
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------------
- * Video device registration and unregistration
- */
-
-/*
- * Delete the UVC device.
- *
- * Called by the kernel when the last reference to the uvc_device structure
- * is released.
- *
- * As this function is called after or during disconnect(), all URBs have
- * already been canceled by the USB core. There is no need to kill the
- * interrupt URB manually.
- */
-static void uvc_delete(struct uvc_device *dev)
-{
-       struct list_head *p, *n;
-
-       usb_put_intf(dev->intf);
-       usb_put_dev(dev->udev);
-
-       uvc_status_cleanup(dev);
-       uvc_ctrl_cleanup_device(dev);
-
-       if (dev->vdev.dev)
-               v4l2_device_unregister(&dev->vdev);
-#ifdef CONFIG_MEDIA_CONTROLLER
-       if (media_devnode_is_registered(&dev->mdev.devnode))
-               media_device_unregister(&dev->mdev);
-#endif
-
-       list_for_each_safe(p, n, &dev->chains) {
-               struct uvc_video_chain *chain;
-               chain = list_entry(p, struct uvc_video_chain, list);
-               kfree(chain);
-       }
-
-       list_for_each_safe(p, n, &dev->entities) {
-               struct uvc_entity *entity;
-               entity = list_entry(p, struct uvc_entity, list);
-#ifdef CONFIG_MEDIA_CONTROLLER
-               uvc_mc_cleanup_entity(entity);
-#endif
-               if (entity->vdev) {
-                       video_device_release(entity->vdev);
-                       entity->vdev = NULL;
-               }
-               kfree(entity);
-       }
-
-       list_for_each_safe(p, n, &dev->streams) {
-               struct uvc_streaming *streaming;
-               streaming = list_entry(p, struct uvc_streaming, list);
-               usb_driver_release_interface(&uvc_driver.driver,
-                       streaming->intf);
-               usb_put_intf(streaming->intf);
-               kfree(streaming->format);
-               kfree(streaming->header.bmaControls);
-               kfree(streaming);
-       }
-
-       kfree(dev);
-}
-
-static void uvc_release(struct video_device *vdev)
-{
-       struct uvc_streaming *stream = video_get_drvdata(vdev);
-       struct uvc_device *dev = stream->dev;
-
-       /* Decrement the registered streams count and delete the device when it
-        * reaches zero.
-        */
-       if (atomic_dec_and_test(&dev->nstreams))
-               uvc_delete(dev);
-}
-
-/*
- * Unregister the video devices.
- */
-static void uvc_unregister_video(struct uvc_device *dev)
-{
-       struct uvc_streaming *stream;
-
-       /* Unregistering all video devices might result in uvc_delete() being
-        * called from inside the loop if there's no open file handle. To avoid
-        * that, increment the stream count before iterating over the streams
-        * and decrement it when done.
-        */
-       atomic_inc(&dev->nstreams);
-
-       list_for_each_entry(stream, &dev->streams, list) {
-               if (stream->vdev == NULL)
-                       continue;
-
-               video_unregister_device(stream->vdev);
-               stream->vdev = NULL;
-
-               uvc_debugfs_cleanup_stream(stream);
-       }
-
-       /* Decrement the stream count and call uvc_delete explicitly if there
-        * are no stream left.
-        */
-       if (atomic_dec_and_test(&dev->nstreams))
-               uvc_delete(dev);
-}
-
-static int uvc_register_video(struct uvc_device *dev,
-               struct uvc_streaming *stream)
-{
-       struct video_device *vdev;
-       int ret;
-
-       /* Initialize the streaming interface with default streaming
-        * parameters.
-        */
-       ret = uvc_video_init(stream);
-       if (ret < 0) {
-               uvc_printk(KERN_ERR, "Failed to initialize the device "
-                       "(%d).\n", ret);
-               return ret;
-       }
-
-       uvc_debugfs_init_stream(stream);
-
-       /* Register the device with V4L. */
-       vdev = video_device_alloc();
-       if (vdev == NULL) {
-               uvc_printk(KERN_ERR, "Failed to allocate video device (%d).\n",
-                          ret);
-               return -ENOMEM;
-       }
-
-       /* We already hold a reference to dev->udev. The video device will be
-        * unregistered before the reference is released, so we don't need to
-        * get another one.
-        */
-       vdev->v4l2_dev = &dev->vdev;
-       vdev->fops = &uvc_fops;
-       vdev->release = uvc_release;
-       strlcpy(vdev->name, dev->name, sizeof vdev->name);
-
-       /* Set the driver data before calling video_register_device, otherwise
-        * uvc_v4l2_open might race us.
-        */
-       stream->vdev = vdev;
-       video_set_drvdata(vdev, stream);
-
-       ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
-       if (ret < 0) {
-               uvc_printk(KERN_ERR, "Failed to register video device (%d).\n",
-                          ret);
-               stream->vdev = NULL;
-               video_device_release(vdev);
-               return ret;
-       }
-
-       atomic_inc(&dev->nstreams);
-       return 0;
-}
-
-/*
- * Register all video devices in all chains.
- */
-static int uvc_register_terms(struct uvc_device *dev,
-       struct uvc_video_chain *chain)
-{
-       struct uvc_streaming *stream;
-       struct uvc_entity *term;
-       int ret;
-
-       list_for_each_entry(term, &chain->entities, chain) {
-               if (UVC_ENTITY_TYPE(term) != UVC_TT_STREAMING)
-                       continue;
-
-               stream = uvc_stream_by_id(dev, term->id);
-               if (stream == NULL) {
-                       uvc_printk(KERN_INFO, "No streaming interface found "
-                                  "for terminal %u.", term->id);
-                       continue;
-               }
-
-               stream->chain = chain;
-               ret = uvc_register_video(dev, stream);
-               if (ret < 0)
-                       return ret;
-
-               term->vdev = stream->vdev;
-       }
-
-       return 0;
-}
-
-static int uvc_register_chains(struct uvc_device *dev)
-{
-       struct uvc_video_chain *chain;
-       int ret;
-
-       list_for_each_entry(chain, &dev->chains, list) {
-               ret = uvc_register_terms(dev, chain);
-               if (ret < 0)
-                       return ret;
-
-#ifdef CONFIG_MEDIA_CONTROLLER
-               ret = uvc_mc_register_entities(chain);
-               if (ret < 0) {
-                       uvc_printk(KERN_INFO, "Failed to register entites "
-                               "(%d).\n", ret);
-               }
-#endif
-       }
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------------
- * USB probe, disconnect, suspend and resume
- */
-
-static int uvc_probe(struct usb_interface *intf,
-                    const struct usb_device_id *id)
-{
-       struct usb_device *udev = interface_to_usbdev(intf);
-       struct uvc_device *dev;
-       int ret;
-
-       if (id->idVendor && id->idProduct)
-               uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s "
-                               "(%04x:%04x)\n", udev->devpath, id->idVendor,
-                               id->idProduct);
-       else
-               uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",
-                               udev->devpath);
-
-       /* Allocate memory for the device and initialize it. */
-       if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)
-               return -ENOMEM;
-
-       INIT_LIST_HEAD(&dev->entities);
-       INIT_LIST_HEAD(&dev->chains);
-       INIT_LIST_HEAD(&dev->streams);
-       atomic_set(&dev->nstreams, 0);
-       atomic_set(&dev->users, 0);
-       atomic_set(&dev->nmappings, 0);
-
-       dev->udev = usb_get_dev(udev);
-       dev->intf = usb_get_intf(intf);
-       dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
-       dev->quirks = (uvc_quirks_param == -1)
-                   ? id->driver_info : uvc_quirks_param;
-
-       if (udev->product != NULL)
-               strlcpy(dev->name, udev->product, sizeof dev->name);
-       else
-               snprintf(dev->name, sizeof dev->name,
-                       "UVC Camera (%04x:%04x)",
-                       le16_to_cpu(udev->descriptor.idVendor),
-                       le16_to_cpu(udev->descriptor.idProduct));
-
-       /* Parse the Video Class control descriptor. */
-       if (uvc_parse_control(dev) < 0) {
-               uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
-                       "descriptors.\n");
-               goto error;
-       }
-
-       uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",
-               dev->uvc_version >> 8, dev->uvc_version & 0xff,
-               udev->product ? udev->product : "<unnamed>",
-               le16_to_cpu(udev->descriptor.idVendor),
-               le16_to_cpu(udev->descriptor.idProduct));
-
-       if (dev->quirks != id->driver_info) {
-               uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module "
-                       "parameter for testing purpose.\n", dev->quirks);
-               uvc_printk(KERN_INFO, "Please report required quirks to the "
-                       "linux-uvc-devel mailing list.\n");
-       }
-
-       /* Register the media and V4L2 devices. */
-#ifdef CONFIG_MEDIA_CONTROLLER
-       dev->mdev.dev = &intf->dev;
-       strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
-       if (udev->serial)
-               strlcpy(dev->mdev.serial, udev->serial,
-                       sizeof(dev->mdev.serial));
-       strcpy(dev->mdev.bus_info, udev->devpath);
-       dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
-       dev->mdev.driver_version = LINUX_VERSION_CODE;
-       if (media_device_register(&dev->mdev) < 0)
-               goto error;
-
-       dev->vdev.mdev = &dev->mdev;
-#endif
-       if (v4l2_device_register(&intf->dev, &dev->vdev) < 0)
-               goto error;
-
-       /* Initialize controls. */
-       if (uvc_ctrl_init_device(dev) < 0)
-               goto error;
-
-       /* Scan the device for video chains. */
-       if (uvc_scan_device(dev) < 0)
-               goto error;
-
-       /* Register video device nodes. */
-       if (uvc_register_chains(dev) < 0)
-               goto error;
-
-       /* Save our data pointer in the interface data. */
-       usb_set_intfdata(intf, dev);
-
-       /* Initialize the interrupt URB. */
-       if ((ret = uvc_status_init(dev)) < 0) {
-               uvc_printk(KERN_INFO, "Unable to initialize the status "
-                       "endpoint (%d), status interrupt will not be "
-                       "supported.\n", ret);
-       }
-
-       uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n");
-       usb_enable_autosuspend(udev);
-       return 0;
-
-error:
-       uvc_unregister_video(dev);
-       return -ENODEV;
-}
-
-static void uvc_disconnect(struct usb_interface *intf)
-{
-       struct uvc_device *dev = usb_get_intfdata(intf);
-
-       /* Set the USB interface data to NULL. This can be done outside the
-        * lock, as there's no other reader.
-        */
-       usb_set_intfdata(intf, NULL);
-
-       if (intf->cur_altsetting->desc.bInterfaceSubClass ==
-           UVC_SC_VIDEOSTREAMING)
-               return;
-
-       dev->state |= UVC_DEV_DISCONNECTED;
-
-       uvc_unregister_video(dev);
-}
-
-static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
-{
-       struct uvc_device *dev = usb_get_intfdata(intf);
-       struct uvc_streaming *stream;
-
-       uvc_trace(UVC_TRACE_SUSPEND, "Suspending interface %u\n",
-               intf->cur_altsetting->desc.bInterfaceNumber);
-
-       /* Controls are cached on the fly so they don't need to be saved. */
-       if (intf->cur_altsetting->desc.bInterfaceSubClass ==
-           UVC_SC_VIDEOCONTROL)
-               return uvc_status_suspend(dev);
-
-       list_for_each_entry(stream, &dev->streams, list) {
-               if (stream->intf == intf)
-                       return uvc_video_suspend(stream);
-       }
-
-       uvc_trace(UVC_TRACE_SUSPEND, "Suspend: video streaming USB interface "
-                       "mismatch.\n");
-       return -EINVAL;
-}
-
-static int __uvc_resume(struct usb_interface *intf, int reset)
-{
-       struct uvc_device *dev = usb_get_intfdata(intf);
-       struct uvc_streaming *stream;
-
-       uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
-               intf->cur_altsetting->desc.bInterfaceNumber);
-
-       if (intf->cur_altsetting->desc.bInterfaceSubClass ==
-           UVC_SC_VIDEOCONTROL) {
-               if (reset) {
-                       int ret = uvc_ctrl_resume_device(dev);
-
-                       if (ret < 0)
-                               return ret;
-               }
-
-               return uvc_status_resume(dev);
-       }
-
-       list_for_each_entry(stream, &dev->streams, list) {
-               if (stream->intf == intf)
-                       return uvc_video_resume(stream, reset);
-       }
-
-       uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface "
-                       "mismatch.\n");
-       return -EINVAL;
-}
-
-static int uvc_resume(struct usb_interface *intf)
-{
-       return __uvc_resume(intf, 0);
-}
-
-static int uvc_reset_resume(struct usb_interface *intf)
-{
-       return __uvc_resume(intf, 1);
-}
-
-/* ------------------------------------------------------------------------
- * Module parameters
- */
-
-static int uvc_clock_param_get(char *buffer, struct kernel_param *kp)
-{
-       if (uvc_clock_param == CLOCK_MONOTONIC)
-               return sprintf(buffer, "CLOCK_MONOTONIC");
-       else
-               return sprintf(buffer, "CLOCK_REALTIME");
-}
-
-static int uvc_clock_param_set(const char *val, struct kernel_param *kp)
-{
-       if (strncasecmp(val, "clock_", strlen("clock_")) == 0)
-               val += strlen("clock_");
-
-       if (strcasecmp(val, "monotonic") == 0)
-               uvc_clock_param = CLOCK_MONOTONIC;
-       else if (strcasecmp(val, "realtime") == 0)
-               uvc_clock_param = CLOCK_REALTIME;
-       else
-               return -EINVAL;
-
-       return 0;
-}
-
-module_param_call(clock, uvc_clock_param_set, uvc_clock_param_get,
-                 &uvc_clock_param, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(clock, "Video buffers timestamp clock");
-module_param_named(nodrop, uvc_no_drop_param, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(nodrop, "Don't drop incomplete frames");
-module_param_named(quirks, uvc_quirks_param, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(quirks, "Forced device quirks");
-module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(trace, "Trace level bitmask");
-module_param_named(timeout, uvc_timeout_param, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(timeout, "Streaming control requests timeout");
-
-/* ------------------------------------------------------------------------
- * Driver initialization and cleanup
- */
-
-/*
- * The Logitech cameras listed below have their interface class set to
- * VENDOR_SPEC because they don't announce themselves as UVC devices, even
- * though they are compliant.
- */
-static struct usb_device_id uvc_ids[] = {
-       /* LogiLink Wireless Webcam */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x0416,
-         .idProduct            = 0xa91a,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
-       /* Genius eFace 2025 */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x0458,
-         .idProduct            = 0x706e,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
-       /* Microsoft Lifecam NX-6000 */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x045e,
-         .idProduct            = 0x00f8,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
-       /* Microsoft Lifecam VX-7000 */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x045e,
-         .idProduct            = 0x0723,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
-       /* Logitech Quickcam Fusion */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x046d,
-         .idProduct            = 0x08c1,
-         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0 },
-       /* Logitech Quickcam Orbit MP */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x046d,
-         .idProduct            = 0x08c2,
-         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0 },
-       /* Logitech Quickcam Pro for Notebook */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x046d,
-         .idProduct            = 0x08c3,
-         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0 },
-       /* Logitech Quickcam Pro 5000 */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x046d,
-         .idProduct            = 0x08c5,
-         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0 },
-       /* Logitech Quickcam OEM Dell Notebook */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x046d,
-         .idProduct            = 0x08c6,
-         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0 },
-       /* Logitech Quickcam OEM Cisco VT Camera II */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x046d,
-         .idProduct            = 0x08c7,
-         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0 },
-       /* Chicony CNF7129 (Asus EEE 100HE) */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x04f2,
-         .idProduct            = 0xb071,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_RESTRICT_FRAME_RATE },
-       /* Alcor Micro AU3820 (Future Boy PC USB Webcam) */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x058f,
-         .idProduct            = 0x3820,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
-       /* Dell XPS m1530 */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x05a9,
-         .idProduct            = 0x2640,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_DEF },
-       /* Apple Built-In iSight */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x05ac,
-         .idProduct            = 0x8501,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_MINMAX
-                               | UVC_QUIRK_BUILTIN_ISIGHT },
-       /* Foxlink ("HP Webcam" on HP Mini 5103) */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x05c8,
-         .idProduct            = 0x0403,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_FIX_BANDWIDTH },
-       /* Genesys Logic USB 2.0 PC Camera */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x05e3,
-         .idProduct            = 0x0505,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
-       /* Hercules Classic Silver */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x06f8,
-         .idProduct            = 0x300c,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_FIX_BANDWIDTH },
-       /* ViMicro Vega */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x0ac8,
-         .idProduct            = 0x332d,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_FIX_BANDWIDTH },
-       /* ViMicro - Minoru3D */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x0ac8,
-         .idProduct            = 0x3410,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_FIX_BANDWIDTH },
-       /* ViMicro Venus - Minoru3D */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x0ac8,
-         .idProduct            = 0x3420,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_FIX_BANDWIDTH },
-       /* Ophir Optronics - SPCAM 620U */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x0bd3,
-         .idProduct            = 0x0555,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
-       /* MT6227 */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x0e8d,
-         .idProduct            = 0x0004,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_MINMAX
-                               | UVC_QUIRK_PROBE_DEF },
-       /* IMC Networks (Medion Akoya) */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x13d3,
-         .idProduct            = 0x5103,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
-       /* JMicron USB2.0 XGA WebCam */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x152d,
-         .idProduct            = 0x0310,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
-       /* Syntek (HP Spartan) */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x174f,
-         .idProduct            = 0x5212,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
-       /* Syntek (Samsung Q310) */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x174f,
-         .idProduct            = 0x5931,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
-       /* Syntek (Packard Bell EasyNote MX52 */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x174f,
-         .idProduct            = 0x8a12,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
-       /* Syntek (Asus F9SG) */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x174f,
-         .idProduct            = 0x8a31,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
-       /* Syntek (Asus U3S) */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x174f,
-         .idProduct            = 0x8a33,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
-       /* Syntek (JAOtech Smart Terminal) */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x174f,
-         .idProduct            = 0x8a34,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
-       /* Miricle 307K */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x17dc,
-         .idProduct            = 0x0202,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
-       /* Lenovo Thinkpad SL400/SL500 */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x17ef,
-         .idProduct            = 0x480b,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_STREAM_NO_FID },
-       /* Aveo Technology USB 2.0 Camera */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x1871,
-         .idProduct            = 0x0306,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_MINMAX
-                               | UVC_QUIRK_PROBE_EXTRAFIELDS },
-       /* Ecamm Pico iMage */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x18cd,
-         .idProduct            = 0xcafe,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_EXTRAFIELDS },
-       /* Manta MM-353 Plako */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x18ec,
-         .idProduct            = 0x3188,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
-       /* FSC WebCam V30S */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x18ec,
-         .idProduct            = 0x3288,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
-       /* Arkmicro unbranded */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x18ec,
-         .idProduct            = 0x3290,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_DEF },
-       /* The Imaging Source USB CCD cameras */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x199e,
-         .idProduct            = 0x8102,
-         .bInterfaceClass      = USB_CLASS_VENDOR_SPEC,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0 },
-       /* Bodelin ProScopeHR */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_DEV_HI
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x19ab,
-         .idProduct            = 0x1000,
-         .bcdDevice_hi         = 0x0126,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_STATUS_INTERVAL },
-       /* MSI StarCam 370i */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x1b3b,
-         .idProduct            = 0x2951,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
-       /* SiGma Micro USB Web Camera */
-       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-                               | USB_DEVICE_ID_MATCH_INT_INFO,
-         .idVendor             = 0x1c4f,
-         .idProduct            = 0x3000,
-         .bInterfaceClass      = USB_CLASS_VIDEO,
-         .bInterfaceSubClass   = 1,
-         .bInterfaceProtocol   = 0,
-         .driver_info          = UVC_QUIRK_PROBE_MINMAX
-                               | UVC_QUIRK_IGNORE_SELECTOR_UNIT },
-       /* Generic USB Video Class */
-       { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
-       {}
-};
-
-MODULE_DEVICE_TABLE(usb, uvc_ids);
-
-struct uvc_driver uvc_driver = {
-       .driver = {
-               .name           = "uvcvideo",
-               .probe          = uvc_probe,
-               .disconnect     = uvc_disconnect,
-               .suspend        = uvc_suspend,
-               .resume         = uvc_resume,
-               .reset_resume   = uvc_reset_resume,
-               .id_table       = uvc_ids,
-               .supports_autosuspend = 1,
-       },
-};
-
-static int __init uvc_init(void)
-{
-       int ret;
-
-       uvc_debugfs_init();
-
-       ret = usb_register(&uvc_driver.driver);
-       if (ret < 0) {
-               uvc_debugfs_cleanup();
-               return ret;
-       }
-
-       printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n");
-       return 0;
-}
-
-static void __exit uvc_cleanup(void)
-{
-       usb_deregister(&uvc_driver.driver);
-       uvc_debugfs_cleanup();
-}
-
-module_init(uvc_init);
-module_exit(uvc_cleanup);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRIVER_VERSION);
-
diff --git a/drivers/media/video/uvc/uvc_entity.c b/drivers/media/video/uvc/uvc_entity.c
deleted file mode 100644 (file)
index 29e2399..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- *      uvc_entity.c  --  USB Video Class driver
- *
- *      Copyright (C) 2005-2011
- *          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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/videodev2.h>
-
-#include <media/v4l2-common.h>
-
-#include "uvcvideo.h"
-
-/* ------------------------------------------------------------------------
- * Video subdevices registration and unregistration
- */
-
-static int uvc_mc_register_entity(struct uvc_video_chain *chain,
-       struct uvc_entity *entity)
-{
-       const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE;
-       struct media_entity *sink;
-       unsigned int i;
-       int ret;
-
-       sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING)
-            ? (entity->vdev ? &entity->vdev->entity : NULL)
-            : &entity->subdev.entity;
-       if (sink == NULL)
-               return 0;
-
-       for (i = 0; i < entity->num_pads; ++i) {
-               struct media_entity *source;
-               struct uvc_entity *remote;
-               u8 remote_pad;
-
-               if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK))
-                       continue;
-
-               remote = uvc_entity_by_id(chain->dev, entity->baSourceID[i]);
-               if (remote == NULL)
-                       return -EINVAL;
-
-               source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING)
-                      ? (remote->vdev ? &remote->vdev->entity : NULL)
-                      : &remote->subdev.entity;
-               if (source == NULL)
-                       continue;
-
-               remote_pad = remote->num_pads - 1;
-               ret = media_entity_create_link(source, remote_pad,
-                                              sink, i, flags);
-               if (ret < 0)
-                       return ret;
-       }
-
-       if (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING)
-               return 0;
-
-       return v4l2_device_register_subdev(&chain->dev->vdev, &entity->subdev);
-}
-
-static struct v4l2_subdev_ops uvc_subdev_ops = {
-};
-
-void uvc_mc_cleanup_entity(struct uvc_entity *entity)
-{
-       if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING)
-               media_entity_cleanup(&entity->subdev.entity);
-       else if (entity->vdev != NULL)
-               media_entity_cleanup(&entity->vdev->entity);
-}
-
-static int uvc_mc_init_entity(struct uvc_entity *entity)
-{
-       int ret;
-
-       if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) {
-               v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops);
-               strlcpy(entity->subdev.name, entity->name,
-                       sizeof(entity->subdev.name));
-
-               ret = media_entity_init(&entity->subdev.entity,
-                                       entity->num_pads, entity->pads, 0);
-       } else if (entity->vdev != NULL) {
-               ret = media_entity_init(&entity->vdev->entity,
-                                       entity->num_pads, entity->pads, 0);
-       } else
-               ret = 0;
-
-       return ret;
-}
-
-int uvc_mc_register_entities(struct uvc_video_chain *chain)
-{
-       struct uvc_entity *entity;
-       int ret;
-
-       list_for_each_entry(entity, &chain->entities, chain) {
-               ret = uvc_mc_init_entity(entity);
-               if (ret < 0) {
-                       uvc_printk(KERN_INFO, "Failed to initialize entity for "
-                                  "entity %u\n", entity->id);
-                       return ret;
-               }
-       }
-
-       list_for_each_entry(entity, &chain->entities, chain) {
-               ret = uvc_mc_register_entity(chain, entity);
-               if (ret < 0) {
-                       uvc_printk(KERN_INFO, "Failed to register entity for "
-                                  "entity %u\n", entity->id);
-                       return ret;
-               }
-       }
-
-       return 0;
-}
diff --git a/drivers/media/video/uvc/uvc_isight.c b/drivers/media/video/uvc/uvc_isight.c
deleted file mode 100644 (file)
index 8510e72..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- *      uvc_isight.c  --  USB Video Class driver - iSight support
- *
- *     Copyright (C) 2006-2007
- *             Ivan N. Zlatev <contact@i-nz.net>
- *     Copyright (C) 2008-2009
- *             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.
- *
- */
-
-#include <linux/usb.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-
-#include "uvcvideo.h"
-
-/* Built-in iSight webcams implements most of UVC 1.0 except a
- * different packet format. Instead of sending a header at the
- * beginning of each isochronous transfer payload, the webcam sends a
- * single header per image (on its own in a packet), followed by
- * packets containing data only.
- *
- * Offset   Size (bytes)       Description
- * ------------------------------------------------------------------
- * 0x00        1       Header length
- * 0x01        1       Flags (UVC-compliant)
- * 0x02        4       Always equal to '11223344'
- * 0x06        8       Always equal to 'deadbeefdeadface'
- * 0x0e        16      Unknown
- *
- * The header can be prefixed by an optional, unknown-purpose byte.
- */
-
-static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf,
-               const __u8 *data, unsigned int len)
-{
-       static const __u8 hdr[] = {
-               0x11, 0x22, 0x33, 0x44,
-               0xde, 0xad, 0xbe, 0xef,
-               0xde, 0xad, 0xfa, 0xce
-       };
-
-       unsigned int maxlen, nbytes;
-       __u8 *mem;
-       int is_header = 0;
-
-       if (buf == NULL)
-               return 0;
-
-       if ((len >= 14 && memcmp(&data[2], hdr, 12) == 0) ||
-           (len >= 15 && memcmp(&data[3], hdr, 12) == 0)) {
-               uvc_trace(UVC_TRACE_FRAME, "iSight header found\n");
-               is_header = 1;
-       }
-
-       /* Synchronize to the input stream by waiting for a header packet. */
-       if (buf->state != UVC_BUF_STATE_ACTIVE) {
-               if (!is_header) {
-                       uvc_trace(UVC_TRACE_FRAME, "Dropping packet (out of "
-                                 "sync).\n");
-                       return 0;
-               }
-
-               buf->state = UVC_BUF_STATE_ACTIVE;
-       }
-
-       /* Mark the buffer as done if we're at the beginning of a new frame.
-        *
-        * Empty buffers (bytesused == 0) don't trigger end of frame detection
-        * as it doesn't make sense to return an empty buffer.
-        */
-       if (is_header && buf->bytesused != 0) {
-               buf->state = UVC_BUF_STATE_DONE;
-               return -EAGAIN;
-       }
-
-       /* Copy the video data to the buffer. Skip header packets, as they
-        * contain no data.
-        */
-       if (!is_header) {
-               maxlen = buf->length - buf->bytesused;
-               mem = buf->mem + buf->bytesused;
-               nbytes = min(len, maxlen);
-               memcpy(mem, data, nbytes);
-               buf->bytesused += nbytes;
-
-               if (len > maxlen || buf->bytesused == buf->length) {
-                       uvc_trace(UVC_TRACE_FRAME, "Frame complete "
-                                 "(overflow).\n");
-                       buf->state = UVC_BUF_STATE_DONE;
-               }
-       }
-
-       return 0;
-}
-
-void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream,
-               struct uvc_buffer *buf)
-{
-       int ret, i;
-
-       for (i = 0; i < urb->number_of_packets; ++i) {
-               if (urb->iso_frame_desc[i].status < 0) {
-                       uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame "
-                                 "lost (%d).\n",
-                                 urb->iso_frame_desc[i].status);
-               }
-
-               /* Decode the payload packet.
-                * uvc_video_decode is entered twice when a frame transition
-                * has been detected because the end of frame can only be
-                * reliably detected when the first packet of the new frame
-                * is processed. The first pass detects the transition and
-                * closes the previous frame's buffer, the second pass
-                * processes the data of the first payload of the new frame.
-                */
-               do {
-                       ret = isight_decode(&stream->queue, buf,
-                                       urb->transfer_buffer +
-                                       urb->iso_frame_desc[i].offset,
-                                       urb->iso_frame_desc[i].actual_length);
-
-                       if (buf == NULL)
-                               break;
-
-                       if (buf->state == UVC_BUF_STATE_DONE ||
-                           buf->state == UVC_BUF_STATE_ERROR)
-                               buf = uvc_queue_next_buffer(&stream->queue,
-                                                       buf);
-               } while (ret == -EAGAIN);
-       }
-}
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
deleted file mode 100644 (file)
index 9288fbd..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- *      uvc_queue.c  --  USB Video Class driver - Buffers management
- *
- *      Copyright (C) 2005-2010
- *          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.
- *
- */
-
-#include <linux/atomic.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include <linux/vmalloc.h>
-#include <linux/wait.h>
-#include <media/videobuf2-vmalloc.h>
-
-#include "uvcvideo.h"
-
-/* ------------------------------------------------------------------------
- * Video buffers queue management.
- *
- * Video queues is initialized by uvc_queue_init(). The function performs
- * basic initialization of the uvc_video_queue struct and never fails.
- *
- * Video buffers are managed by videobuf2. The driver uses a mutex to protect
- * the videobuf2 queue operations by serializing calls to videobuf2 and a
- * spinlock to protect the IRQ queue that holds the buffers to be processed by
- * the driver.
- */
-
-/* -----------------------------------------------------------------------------
- * videobuf2 queue operations
- */
-
-static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
-                          unsigned int *nbuffers, unsigned int *nplanes,
-                          unsigned int sizes[], void *alloc_ctxs[])
-{
-       struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
-       struct uvc_streaming *stream =
-                       container_of(queue, struct uvc_streaming, queue);
-
-       if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
-               *nbuffers = UVC_MAX_VIDEO_BUFFERS;
-
-       *nplanes = 1;
-
-       sizes[0] = stream->ctrl.dwMaxVideoFrameSize;
-
-       return 0;
-}
-
-static int uvc_buffer_prepare(struct vb2_buffer *vb)
-{
-       struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
-       struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
-
-       if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-           vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
-               return -EINVAL;
-       }
-
-       if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED))
-               return -ENODEV;
-
-       buf->state = UVC_BUF_STATE_QUEUED;
-       buf->error = 0;
-       buf->mem = vb2_plane_vaddr(vb, 0);
-       buf->length = vb2_plane_size(vb, 0);
-       if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               buf->bytesused = 0;
-       else
-               buf->bytesused = vb2_get_plane_payload(vb, 0);
-
-       return 0;
-}
-
-static void uvc_buffer_queue(struct vb2_buffer *vb)
-{
-       struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
-       struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
-       unsigned long flags;
-
-       spin_lock_irqsave(&queue->irqlock, flags);
-       if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
-               list_add_tail(&buf->queue, &queue->irqqueue);
-       } else {
-               /* If the device is disconnected return the buffer to userspace
-                * directly. The next QBUF call will fail with -ENODEV.
-                */
-               buf->state = UVC_BUF_STATE_ERROR;
-               vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
-       }
-
-       spin_unlock_irqrestore(&queue->irqlock, flags);
-}
-
-static int uvc_buffer_finish(struct vb2_buffer *vb)
-{
-       struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
-       struct uvc_streaming *stream =
-                       container_of(queue, struct uvc_streaming, queue);
-       struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
-
-       uvc_video_clock_update(stream, &vb->v4l2_buf, buf);
-       return 0;
-}
-
-static struct vb2_ops uvc_queue_qops = {
-       .queue_setup = uvc_queue_setup,
-       .buf_prepare = uvc_buffer_prepare,
-       .buf_queue = uvc_buffer_queue,
-       .buf_finish = uvc_buffer_finish,
-};
-
-void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
-                   int drop_corrupted)
-{
-       queue->queue.type = type;
-       queue->queue.io_modes = VB2_MMAP | VB2_USERPTR;
-       queue->queue.drv_priv = queue;
-       queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
-       queue->queue.ops = &uvc_queue_qops;
-       queue->queue.mem_ops = &vb2_vmalloc_memops;
-       vb2_queue_init(&queue->queue);
-
-       mutex_init(&queue->mutex);
-       spin_lock_init(&queue->irqlock);
-       INIT_LIST_HEAD(&queue->irqqueue);
-       queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0;
-}
-
-/* -----------------------------------------------------------------------------
- * V4L2 queue operations
- */
-
-int uvc_alloc_buffers(struct uvc_video_queue *queue,
-                     struct v4l2_requestbuffers *rb)
-{
-       int ret;
-
-       mutex_lock(&queue->mutex);
-       ret = vb2_reqbufs(&queue->queue, rb);
-       mutex_unlock(&queue->mutex);
-
-       return ret ? ret : rb->count;
-}
-
-void uvc_free_buffers(struct uvc_video_queue *queue)
-{
-       mutex_lock(&queue->mutex);
-       vb2_queue_release(&queue->queue);
-       mutex_unlock(&queue->mutex);
-}
-
-int uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
-{
-       int ret;
-
-       mutex_lock(&queue->mutex);
-       ret = vb2_querybuf(&queue->queue, buf);
-       mutex_unlock(&queue->mutex);
-
-       return ret;
-}
-
-int uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
-{
-       int ret;
-
-       mutex_lock(&queue->mutex);
-       ret = vb2_qbuf(&queue->queue, buf);
-       mutex_unlock(&queue->mutex);
-
-       return ret;
-}
-
-int uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf,
-                      int nonblocking)
-{
-       int ret;
-
-       mutex_lock(&queue->mutex);
-       ret = vb2_dqbuf(&queue->queue, buf, nonblocking);
-       mutex_unlock(&queue->mutex);
-
-       return ret;
-}
-
-int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
-{
-       int ret;
-
-       mutex_lock(&queue->mutex);
-       ret = vb2_mmap(&queue->queue, vma);
-       mutex_unlock(&queue->mutex);
-
-       return ret;
-}
-
-#ifndef CONFIG_MMU
-unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
-               unsigned long pgoff)
-{
-       unsigned long ret;
-
-       mutex_lock(&queue->mutex);
-       ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0);
-       mutex_unlock(&queue->mutex);
-       return ret;
-}
-#endif
-
-unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
-                           poll_table *wait)
-{
-       unsigned int ret;
-
-       mutex_lock(&queue->mutex);
-       ret = vb2_poll(&queue->queue, file, wait);
-       mutex_unlock(&queue->mutex);
-
-       return ret;
-}
-
-/* -----------------------------------------------------------------------------
- *
- */
-
-/*
- * Check if buffers have been allocated.
- */
-int uvc_queue_allocated(struct uvc_video_queue *queue)
-{
-       int allocated;
-
-       mutex_lock(&queue->mutex);
-       allocated = vb2_is_busy(&queue->queue);
-       mutex_unlock(&queue->mutex);
-
-       return allocated;
-}
-
-/*
- * Enable or disable the video buffers queue.
- *
- * The queue must be enabled before starting video acquisition and must be
- * disabled after stopping it. This ensures that the video buffers queue
- * state can be properly initialized before buffers are accessed from the
- * interrupt handler.
- *
- * Enabling the video queue returns -EBUSY if the queue is already enabled.
- *
- * Disabling the video queue cancels the queue and removes all buffers from
- * the main queue.
- *
- * This function can't be called from interrupt context. Use
- * uvc_queue_cancel() instead.
- */
-int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
-{
-       unsigned long flags;
-       int ret;
-
-       mutex_lock(&queue->mutex);
-       if (enable) {
-               ret = vb2_streamon(&queue->queue, queue->queue.type);
-               if (ret < 0)
-                       goto done;
-
-               queue->buf_used = 0;
-       } else {
-               ret = vb2_streamoff(&queue->queue, queue->queue.type);
-               if (ret < 0)
-                       goto done;
-
-               spin_lock_irqsave(&queue->irqlock, flags);
-               INIT_LIST_HEAD(&queue->irqqueue);
-               spin_unlock_irqrestore(&queue->irqlock, flags);
-       }
-
-done:
-       mutex_unlock(&queue->mutex);
-       return ret;
-}
-
-/*
- * Cancel the video buffers queue.
- *
- * Cancelling the queue marks all buffers on the irq queue as erroneous,
- * wakes them up and removes them from the queue.
- *
- * If the disconnect parameter is set, further calls to uvc_queue_buffer will
- * fail with -ENODEV.
- *
- * This function acquires the irq spinlock and can be called from interrupt
- * context.
- */
-void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
-{
-       struct uvc_buffer *buf;
-       unsigned long flags;
-
-       spin_lock_irqsave(&queue->irqlock, flags);
-       while (!list_empty(&queue->irqqueue)) {
-               buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
-                                      queue);
-               list_del(&buf->queue);
-               buf->state = UVC_BUF_STATE_ERROR;
-               vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
-       }
-       /* This must be protected by the irqlock spinlock to avoid race
-        * conditions between uvc_buffer_queue and the disconnection event that
-        * could result in an interruptible wait in uvc_dequeue_buffer. Do not
-        * blindly replace this logic by checking for the UVC_QUEUE_DISCONNECTED
-        * state outside the queue code.
-        */
-       if (disconnect)
-               queue->flags |= UVC_QUEUE_DISCONNECTED;
-       spin_unlock_irqrestore(&queue->irqlock, flags);
-}
-
-struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
-               struct uvc_buffer *buf)
-{
-       struct uvc_buffer *nextbuf;
-       unsigned long flags;
-
-       if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) {
-               buf->error = 0;
-               buf->state = UVC_BUF_STATE_QUEUED;
-               vb2_set_plane_payload(&buf->buf, 0, 0);
-               return buf;
-       }
-
-       spin_lock_irqsave(&queue->irqlock, flags);
-       list_del(&buf->queue);
-       if (!list_empty(&queue->irqqueue))
-               nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
-                                          queue);
-       else
-               nextbuf = NULL;
-       spin_unlock_irqrestore(&queue->irqlock, flags);
-
-       buf->state = buf->error ? VB2_BUF_STATE_ERROR : UVC_BUF_STATE_DONE;
-       vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
-       vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
-
-       return nextbuf;
-}
diff --git a/drivers/media/video/uvc/uvc_status.c b/drivers/media/video/uvc/uvc_status.c
deleted file mode 100644 (file)
index b749277..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- *      uvc_status.c  --  USB Video Class driver - Status endpoint
- *
- *      Copyright (C) 2005-2009
- *          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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/usb/input.h>
-
-#include "uvcvideo.h"
-
-/* --------------------------------------------------------------------------
- * Input device
- */
-#ifdef CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV
-static int uvc_input_init(struct uvc_device *dev)
-{
-       struct input_dev *input;
-       int ret;
-
-       input = input_allocate_device();
-       if (input == NULL)
-               return -ENOMEM;
-
-       usb_make_path(dev->udev, dev->input_phys, sizeof(dev->input_phys));
-       strlcat(dev->input_phys, "/button", sizeof(dev->input_phys));
-
-       input->name = dev->name;
-       input->phys = dev->input_phys;
-       usb_to_input_id(dev->udev, &input->id);
-       input->dev.parent = &dev->intf->dev;
-
-       __set_bit(EV_KEY, input->evbit);
-       __set_bit(KEY_CAMERA, input->keybit);
-
-       if ((ret = input_register_device(input)) < 0)
-               goto error;
-
-       dev->input = input;
-       return 0;
-
-error:
-       input_free_device(input);
-       return ret;
-}
-
-static void uvc_input_cleanup(struct uvc_device *dev)
-{
-       if (dev->input)
-               input_unregister_device(dev->input);
-}
-
-static void uvc_input_report_key(struct uvc_device *dev, unsigned int code,
-       int value)
-{
-       if (dev->input) {
-               input_report_key(dev->input, code, value);
-               input_sync(dev->input);
-       }
-}
-
-#else
-#define uvc_input_init(dev)
-#define uvc_input_cleanup(dev)
-#define uvc_input_report_key(dev, code, value)
-#endif /* CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV */
-
-/* --------------------------------------------------------------------------
- * Status interrupt endpoint
- */
-static void uvc_event_streaming(struct uvc_device *dev, __u8 *data, int len)
-{
-       if (len < 3) {
-               uvc_trace(UVC_TRACE_STATUS, "Invalid streaming status event "
-                               "received.\n");
-               return;
-       }
-
-       if (data[2] == 0) {
-               if (len < 4)
-                       return;
-               uvc_trace(UVC_TRACE_STATUS, "Button (intf %u) %s len %d\n",
-                       data[1], data[3] ? "pressed" : "released", len);
-               uvc_input_report_key(dev, KEY_CAMERA, data[3]);
-       } else {
-               uvc_trace(UVC_TRACE_STATUS, "Stream %u error event %02x %02x "
-                       "len %d.\n", data[1], data[2], data[3], len);
-       }
-}
-
-static void uvc_event_control(struct uvc_device *dev, __u8 *data, int len)
-{
-       char *attrs[3] = { "value", "info", "failure" };
-
-       if (len < 6 || data[2] != 0 || data[4] > 2) {
-               uvc_trace(UVC_TRACE_STATUS, "Invalid control status event "
-                               "received.\n");
-               return;
-       }
-
-       uvc_trace(UVC_TRACE_STATUS, "Control %u/%u %s change len %d.\n",
-               data[1], data[3], attrs[data[4]], len);
-}
-
-static void uvc_status_complete(struct urb *urb)
-{
-       struct uvc_device *dev = urb->context;
-       int len, ret;
-
-       switch (urb->status) {
-       case 0:
-               break;
-
-       case -ENOENT:           /* usb_kill_urb() called. */
-       case -ECONNRESET:       /* usb_unlink_urb() called. */
-       case -ESHUTDOWN:        /* The endpoint is being disabled. */
-       case -EPROTO:           /* Device is disconnected (reported by some
-                                * host controller). */
-               return;
-
-       default:
-               uvc_printk(KERN_WARNING, "Non-zero status (%d) in status "
-                       "completion handler.\n", urb->status);
-               return;
-       }
-
-       len = urb->actual_length;
-       if (len > 0) {
-               switch (dev->status[0] & 0x0f) {
-               case UVC_STATUS_TYPE_CONTROL:
-                       uvc_event_control(dev, dev->status, len);
-                       break;
-
-               case UVC_STATUS_TYPE_STREAMING:
-                       uvc_event_streaming(dev, dev->status, len);
-                       break;
-
-               default:
-                       uvc_trace(UVC_TRACE_STATUS, "Unknown status event "
-                               "type %u.\n", dev->status[0]);
-                       break;
-               }
-       }
-
-       /* Resubmit the URB. */
-       urb->interval = dev->int_ep->desc.bInterval;
-       if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
-               uvc_printk(KERN_ERR, "Failed to resubmit status URB (%d).\n",
-                       ret);
-       }
-}
-
-int uvc_status_init(struct uvc_device *dev)
-{
-       struct usb_host_endpoint *ep = dev->int_ep;
-       unsigned int pipe;
-       int interval;
-
-       if (ep == NULL)
-               return 0;
-
-       uvc_input_init(dev);
-
-       dev->status = kzalloc(UVC_MAX_STATUS_SIZE, GFP_KERNEL);
-       if (dev->status == NULL)
-               return -ENOMEM;
-
-       dev->int_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (dev->int_urb == NULL) {
-               kfree(dev->status);
-               return -ENOMEM;
-       }
-
-       pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress);
-
-       /* For high-speed interrupt endpoints, the bInterval value is used as
-        * an exponent of two. Some developers forgot about it.
-        */
-       interval = ep->desc.bInterval;
-       if (interval > 16 && dev->udev->speed == USB_SPEED_HIGH &&
-           (dev->quirks & UVC_QUIRK_STATUS_INTERVAL))
-               interval = fls(interval) - 1;
-
-       usb_fill_int_urb(dev->int_urb, dev->udev, pipe,
-               dev->status, UVC_MAX_STATUS_SIZE, uvc_status_complete,
-               dev, interval);
-
-       return 0;
-}
-
-void uvc_status_cleanup(struct uvc_device *dev)
-{
-       usb_kill_urb(dev->int_urb);
-       usb_free_urb(dev->int_urb);
-       kfree(dev->status);
-       uvc_input_cleanup(dev);
-}
-
-int uvc_status_start(struct uvc_device *dev)
-{
-       if (dev->int_urb == NULL)
-               return 0;
-
-       return usb_submit_urb(dev->int_urb, GFP_KERNEL);
-}
-
-void uvc_status_stop(struct uvc_device *dev)
-{
-       usb_kill_urb(dev->int_urb);
-}
-
-int uvc_status_suspend(struct uvc_device *dev)
-{
-       if (atomic_read(&dev->users))
-               usb_kill_urb(dev->int_urb);
-
-       return 0;
-}
-
-int uvc_status_resume(struct uvc_device *dev)
-{
-       if (dev->int_urb == NULL || atomic_read(&dev->users) == 0)
-               return 0;
-
-       return usb_submit_urb(dev->int_urb, GFP_NOIO);
-}
-
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
deleted file mode 100644 (file)
index f00db30..0000000
+++ /dev/null
@@ -1,1317 +0,0 @@
-/*
- *      uvc_v4l2.c  --  USB Video Class driver - V4L2 API
- *
- *      Copyright (C) 2005-2010
- *          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.
- *
- */
-
-#include <linux/compat.h>
-#include <linux/kernel.h>
-#include <linux/version.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include <linux/vmalloc.h>
-#include <linux/mm.h>
-#include <linux/wait.h>
-#include <linux/atomic.h>
-
-#include <media/v4l2-common.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-ioctl.h>
-
-#include "uvcvideo.h"
-
-/* ------------------------------------------------------------------------
- * UVC ioctls
- */
-static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
-       struct uvc_xu_control_mapping *xmap)
-{
-       struct uvc_control_mapping *map;
-       unsigned int size;
-       int ret;
-
-       map = kzalloc(sizeof *map, GFP_KERNEL);
-       if (map == NULL)
-               return -ENOMEM;
-
-       map->id = xmap->id;
-       memcpy(map->name, xmap->name, sizeof map->name);
-       memcpy(map->entity, xmap->entity, sizeof map->entity);
-       map->selector = xmap->selector;
-       map->size = xmap->size;
-       map->offset = xmap->offset;
-       map->v4l2_type = xmap->v4l2_type;
-       map->data_type = xmap->data_type;
-
-       switch (xmap->v4l2_type) {
-       case V4L2_CTRL_TYPE_INTEGER:
-       case V4L2_CTRL_TYPE_BOOLEAN:
-       case V4L2_CTRL_TYPE_BUTTON:
-               break;
-
-       case V4L2_CTRL_TYPE_MENU:
-               /* Prevent excessive memory consumption, as well as integer
-                * overflows.
-                */
-               if (xmap->menu_count == 0 ||
-                   xmap->menu_count > UVC_MAX_CONTROL_MENU_ENTRIES) {
-                       ret = -EINVAL;
-                       goto done;
-               }
-
-               size = xmap->menu_count * sizeof(*map->menu_info);
-               map->menu_info = kmalloc(size, GFP_KERNEL);
-               if (map->menu_info == NULL) {
-                       ret = -ENOMEM;
-                       goto done;
-               }
-
-               if (copy_from_user(map->menu_info, xmap->menu_info, size)) {
-                       ret = -EFAULT;
-                       goto done;
-               }
-
-               map->menu_count = xmap->menu_count;
-               break;
-
-       default:
-               uvc_trace(UVC_TRACE_CONTROL, "Unsupported V4L2 control type "
-                         "%u.\n", xmap->v4l2_type);
-               ret = -ENOTTY;
-               goto done;
-       }
-
-       ret = uvc_ctrl_add_mapping(chain, map);
-
-done:
-       kfree(map->menu_info);
-       kfree(map);
-
-       return ret;
-}
-
-/* ------------------------------------------------------------------------
- * V4L2 interface
- */
-
-/*
- * Find the frame interval closest to the requested frame interval for the
- * given frame format and size. This should be done by the device as part of
- * the Video Probe and Commit negotiation, but some hardware don't implement
- * that feature.
- */
-static __u32 uvc_try_frame_interval(struct uvc_frame *frame, __u32 interval)
-{
-       unsigned int i;
-
-       if (frame->bFrameIntervalType) {
-               __u32 best = -1, dist;
-
-               for (i = 0; i < frame->bFrameIntervalType; ++i) {
-                       dist = interval > frame->dwFrameInterval[i]
-                            ? interval - frame->dwFrameInterval[i]
-                            : frame->dwFrameInterval[i] - interval;
-
-                       if (dist > best)
-                               break;
-
-                       best = dist;
-               }
-
-               interval = frame->dwFrameInterval[i-1];
-       } else {
-               const __u32 min = frame->dwFrameInterval[0];
-               const __u32 max = frame->dwFrameInterval[1];
-               const __u32 step = frame->dwFrameInterval[2];
-
-               interval = min + (interval - min + step/2) / step * step;
-               if (interval > max)
-                       interval = max;
-       }
-
-       return interval;
-}
-
-static int uvc_v4l2_try_format(struct uvc_streaming *stream,
-       struct v4l2_format *fmt, struct uvc_streaming_control *probe,
-       struct uvc_format **uvc_format, struct uvc_frame **uvc_frame)
-{
-       struct uvc_format *format = NULL;
-       struct uvc_frame *frame = NULL;
-       __u16 rw, rh;
-       unsigned int d, maxd;
-       unsigned int i;
-       __u32 interval;
-       int ret = 0;
-       __u8 *fcc;
-
-       if (fmt->type != stream->type)
-               return -EINVAL;
-
-       fcc = (__u8 *)&fmt->fmt.pix.pixelformat;
-       uvc_trace(UVC_TRACE_FORMAT, "Trying format 0x%08x (%c%c%c%c): %ux%u.\n",
-                       fmt->fmt.pix.pixelformat,
-                       fcc[0], fcc[1], fcc[2], fcc[3],
-                       fmt->fmt.pix.width, fmt->fmt.pix.height);
-
-       /* Check if the hardware supports the requested format. */
-       for (i = 0; i < stream->nformats; ++i) {
-               format = &stream->format[i];
-               if (format->fcc == fmt->fmt.pix.pixelformat)
-                       break;
-       }
-
-       if (format == NULL || format->fcc != fmt->fmt.pix.pixelformat) {
-               uvc_trace(UVC_TRACE_FORMAT, "Unsupported format 0x%08x.\n",
-                               fmt->fmt.pix.pixelformat);
-               return -EINVAL;
-       }
-
-       /* Find the closest image size. The distance between image sizes is
-        * the size in pixels of the non-overlapping regions between the
-        * requested size and the frame-specified size.
-        */
-       rw = fmt->fmt.pix.width;
-       rh = fmt->fmt.pix.height;
-       maxd = (unsigned int)-1;
-
-       for (i = 0; i < format->nframes; ++i) {
-               __u16 w = format->frame[i].wWidth;
-               __u16 h = format->frame[i].wHeight;
-
-               d = min(w, rw) * min(h, rh);
-               d = w*h + rw*rh - 2*d;
-               if (d < maxd) {
-                       maxd = d;
-                       frame = &format->frame[i];
-               }
-
-               if (maxd == 0)
-                       break;
-       }
-
-       if (frame == NULL) {
-               uvc_trace(UVC_TRACE_FORMAT, "Unsupported size %ux%u.\n",
-                               fmt->fmt.pix.width, fmt->fmt.pix.height);
-               return -EINVAL;
-       }
-
-       /* Use the default frame interval. */
-       interval = frame->dwDefaultFrameInterval;
-       uvc_trace(UVC_TRACE_FORMAT, "Using default frame interval %u.%u us "
-               "(%u.%u fps).\n", interval/10, interval%10, 10000000/interval,
-               (100000000/interval)%10);
-
-       /* Set the format index, frame index and frame interval. */
-       memset(probe, 0, sizeof *probe);
-       probe->bmHint = 1;      /* dwFrameInterval */
-       probe->bFormatIndex = format->index;
-       probe->bFrameIndex = frame->bFrameIndex;
-       probe->dwFrameInterval = uvc_try_frame_interval(frame, interval);
-       /* Some webcams stall the probe control set request when the
-        * dwMaxVideoFrameSize field is set to zero. The UVC specification
-        * clearly states that the field is read-only from the host, so this
-        * is a webcam bug. Set dwMaxVideoFrameSize to the value reported by
-        * the webcam to work around the problem.
-        *
-        * The workaround could probably be enabled for all webcams, so the
-        * quirk can be removed if needed. It's currently useful to detect
-        * webcam bugs and fix them before they hit the market (providing
-        * developers test their webcams with the Linux driver as well as with
-        * the Windows driver).
-        */
-       mutex_lock(&stream->mutex);
-       if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)
-               probe->dwMaxVideoFrameSize =
-                       stream->ctrl.dwMaxVideoFrameSize;
-
-       /* Probe the device. */
-       ret = uvc_probe_video(stream, probe);
-       mutex_unlock(&stream->mutex);
-       if (ret < 0)
-               goto done;
-
-       fmt->fmt.pix.width = frame->wWidth;
-       fmt->fmt.pix.height = frame->wHeight;
-       fmt->fmt.pix.field = V4L2_FIELD_NONE;
-       fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8;
-       fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize;
-       fmt->fmt.pix.colorspace = format->colorspace;
-       fmt->fmt.pix.priv = 0;
-
-       if (uvc_format != NULL)
-               *uvc_format = format;
-       if (uvc_frame != NULL)
-               *uvc_frame = frame;
-
-done:
-       return ret;
-}
-
-static int uvc_v4l2_get_format(struct uvc_streaming *stream,
-       struct v4l2_format *fmt)
-{
-       struct uvc_format *format;
-       struct uvc_frame *frame;
-       int ret = 0;
-
-       if (fmt->type != stream->type)
-               return -EINVAL;
-
-       mutex_lock(&stream->mutex);
-       format = stream->cur_format;
-       frame = stream->cur_frame;
-
-       if (format == NULL || frame == NULL) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       fmt->fmt.pix.pixelformat = format->fcc;
-       fmt->fmt.pix.width = frame->wWidth;
-       fmt->fmt.pix.height = frame->wHeight;
-       fmt->fmt.pix.field = V4L2_FIELD_NONE;
-       fmt->fmt.pix.bytesperline = format->bpp * frame->wWidth / 8;
-       fmt->fmt.pix.sizeimage = stream->ctrl.dwMaxVideoFrameSize;
-       fmt->fmt.pix.colorspace = format->colorspace;
-       fmt->fmt.pix.priv = 0;
-
-done:
-       mutex_unlock(&stream->mutex);
-       return ret;
-}
-
-static int uvc_v4l2_set_format(struct uvc_streaming *stream,
-       struct v4l2_format *fmt)
-{
-       struct uvc_streaming_control probe;
-       struct uvc_format *format;
-       struct uvc_frame *frame;
-       int ret;
-
-       if (fmt->type != stream->type)
-               return -EINVAL;
-
-       ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);
-       if (ret < 0)
-               return ret;
-
-       mutex_lock(&stream->mutex);
-
-       if (uvc_queue_allocated(&stream->queue)) {
-               ret = -EBUSY;
-               goto done;
-       }
-
-       memcpy(&stream->ctrl, &probe, sizeof probe);
-       stream->cur_format = format;
-       stream->cur_frame = frame;
-
-done:
-       mutex_unlock(&stream->mutex);
-       return ret;
-}
-
-static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
-               struct v4l2_streamparm *parm)
-{
-       uint32_t numerator, denominator;
-
-       if (parm->type != stream->type)
-               return -EINVAL;
-
-       mutex_lock(&stream->mutex);
-       numerator = stream->ctrl.dwFrameInterval;
-       mutex_unlock(&stream->mutex);
-
-       denominator = 10000000;
-       uvc_simplify_fraction(&numerator, &denominator, 8, 333);
-
-       memset(parm, 0, sizeof *parm);
-       parm->type = stream->type;
-
-       if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
-               parm->parm.capture.capturemode = 0;
-               parm->parm.capture.timeperframe.numerator = numerator;
-               parm->parm.capture.timeperframe.denominator = denominator;
-               parm->parm.capture.extendedmode = 0;
-               parm->parm.capture.readbuffers = 0;
-       } else {
-               parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
-               parm->parm.output.outputmode = 0;
-               parm->parm.output.timeperframe.numerator = numerator;
-               parm->parm.output.timeperframe.denominator = denominator;
-       }
-
-       return 0;
-}
-
-static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
-               struct v4l2_streamparm *parm)
-{
-       struct uvc_streaming_control probe;
-       struct v4l2_fract timeperframe;
-       uint32_t interval;
-       int ret;
-
-       if (parm->type != stream->type)
-               return -EINVAL;
-
-       if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               timeperframe = parm->parm.capture.timeperframe;
-       else
-               timeperframe = parm->parm.output.timeperframe;
-
-       interval = uvc_fraction_to_interval(timeperframe.numerator,
-               timeperframe.denominator);
-       uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n",
-               timeperframe.numerator, timeperframe.denominator, interval);
-
-       mutex_lock(&stream->mutex);
-
-       if (uvc_queue_streaming(&stream->queue)) {
-               mutex_unlock(&stream->mutex);
-               return -EBUSY;
-       }
-
-       memcpy(&probe, &stream->ctrl, sizeof probe);
-       probe.dwFrameInterval =
-               uvc_try_frame_interval(stream->cur_frame, interval);
-
-       /* Probe the device with the new settings. */
-       ret = uvc_probe_video(stream, &probe);
-       if (ret < 0) {
-               mutex_unlock(&stream->mutex);
-               return ret;
-       }
-
-       memcpy(&stream->ctrl, &probe, sizeof probe);
-       mutex_unlock(&stream->mutex);
-
-       /* Return the actual frame period. */
-       timeperframe.numerator = probe.dwFrameInterval;
-       timeperframe.denominator = 10000000;
-       uvc_simplify_fraction(&timeperframe.numerator,
-               &timeperframe.denominator, 8, 333);
-
-       if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               parm->parm.capture.timeperframe = timeperframe;
-       else
-               parm->parm.output.timeperframe = timeperframe;
-
-       return 0;
-}
-
-/* ------------------------------------------------------------------------
- * Privilege management
- */
-
-/*
- * Privilege management is the multiple-open implementation basis. The current
- * implementation is completely transparent for the end-user and doesn't
- * require explicit use of the VIDIOC_G_PRIORITY and VIDIOC_S_PRIORITY ioctls.
- * Those ioctls enable finer control on the device (by making possible for a
- * user to request exclusive access to a device), but are not mature yet.
- * Switching to the V4L2 priority mechanism might be considered in the future
- * if this situation changes.
- *
- * Each open instance of a UVC device can either be in a privileged or
- * unprivileged state. Only a single instance can be in a privileged state at
- * a given time. Trying to perform an operation that requires privileges will
- * automatically acquire the required privileges if possible, or return -EBUSY
- * otherwise. Privileges are dismissed when closing the instance or when
- * freeing the video buffers using VIDIOC_REQBUFS.
- *
- * Operations that require privileges are:
- *
- * - VIDIOC_S_INPUT
- * - VIDIOC_S_PARM
- * - VIDIOC_S_FMT
- * - VIDIOC_REQBUFS
- */
-static int uvc_acquire_privileges(struct uvc_fh *handle)
-{
-       /* Always succeed if the handle is already privileged. */
-       if (handle->state == UVC_HANDLE_ACTIVE)
-               return 0;
-
-       /* Check if the device already has a privileged handle. */
-       if (atomic_inc_return(&handle->stream->active) != 1) {
-               atomic_dec(&handle->stream->active);
-               return -EBUSY;
-       }
-
-       handle->state = UVC_HANDLE_ACTIVE;
-       return 0;
-}
-
-static void uvc_dismiss_privileges(struct uvc_fh *handle)
-{
-       if (handle->state == UVC_HANDLE_ACTIVE)
-               atomic_dec(&handle->stream->active);
-
-       handle->state = UVC_HANDLE_PASSIVE;
-}
-
-static int uvc_has_privileges(struct uvc_fh *handle)
-{
-       return handle->state == UVC_HANDLE_ACTIVE;
-}
-
-/* ------------------------------------------------------------------------
- * V4L2 file operations
- */
-
-static int uvc_v4l2_open(struct file *file)
-{
-       struct uvc_streaming *stream;
-       struct uvc_fh *handle;
-       int ret = 0;
-
-       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_open\n");
-       stream = video_drvdata(file);
-
-       if (stream->dev->state & UVC_DEV_DISCONNECTED)
-               return -ENODEV;
-
-       ret = usb_autopm_get_interface(stream->dev->intf);
-       if (ret < 0)
-               return ret;
-
-       /* Create the device handle. */
-       handle = kzalloc(sizeof *handle, GFP_KERNEL);
-       if (handle == NULL) {
-               usb_autopm_put_interface(stream->dev->intf);
-               return -ENOMEM;
-       }
-
-       if (atomic_inc_return(&stream->dev->users) == 1) {
-               ret = uvc_status_start(stream->dev);
-               if (ret < 0) {
-                       usb_autopm_put_interface(stream->dev->intf);
-                       atomic_dec(&stream->dev->users);
-                       kfree(handle);
-                       return ret;
-               }
-       }
-
-       v4l2_fh_init(&handle->vfh, stream->vdev);
-       v4l2_fh_add(&handle->vfh);
-       handle->chain = stream->chain;
-       handle->stream = stream;
-       handle->state = UVC_HANDLE_PASSIVE;
-       file->private_data = handle;
-
-       return 0;
-}
-
-static int uvc_v4l2_release(struct file *file)
-{
-       struct uvc_fh *handle = file->private_data;
-       struct uvc_streaming *stream = handle->stream;
-
-       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n");
-
-       /* Only free resources if this is a privileged handle. */
-       if (uvc_has_privileges(handle)) {
-               uvc_video_enable(stream, 0);
-               uvc_free_buffers(&stream->queue);
-       }
-
-       /* Release the file handle. */
-       uvc_dismiss_privileges(handle);
-       v4l2_fh_del(&handle->vfh);
-       v4l2_fh_exit(&handle->vfh);
-       kfree(handle);
-       file->private_data = NULL;
-
-       if (atomic_dec_return(&stream->dev->users) == 0)
-               uvc_status_stop(stream->dev);
-
-       usb_autopm_put_interface(stream->dev->intf);
-       return 0;
-}
-
-static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
-{
-       struct video_device *vdev = video_devdata(file);
-       struct uvc_fh *handle = file->private_data;
-       struct uvc_video_chain *chain = handle->chain;
-       struct uvc_streaming *stream = handle->stream;
-       long ret = 0;
-
-       switch (cmd) {
-       /* Query capabilities */
-       case VIDIOC_QUERYCAP:
-       {
-               struct v4l2_capability *cap = arg;
-
-               memset(cap, 0, sizeof *cap);
-               strlcpy(cap->driver, "uvcvideo", sizeof cap->driver);
-               strlcpy(cap->card, vdev->name, sizeof cap->card);
-               usb_make_path(stream->dev->udev,
-                             cap->bus_info, sizeof(cap->bus_info));
-               cap->version = LINUX_VERSION_CODE;
-               if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
-                                         | V4L2_CAP_STREAMING;
-               else
-                       cap->capabilities = V4L2_CAP_VIDEO_OUTPUT
-                                         | V4L2_CAP_STREAMING;
-               break;
-       }
-
-       /* Get, Set & Query control */
-       case VIDIOC_QUERYCTRL:
-               return uvc_query_v4l2_ctrl(chain, arg);
-
-       case VIDIOC_G_CTRL:
-       {
-               struct v4l2_control *ctrl = arg;
-               struct v4l2_ext_control xctrl;
-
-               memset(&xctrl, 0, sizeof xctrl);
-               xctrl.id = ctrl->id;
-
-               ret = uvc_ctrl_begin(chain);
-               if (ret < 0)
-                       return ret;
-
-               ret = uvc_ctrl_get(chain, &xctrl);
-               uvc_ctrl_rollback(handle);
-               if (ret >= 0)
-                       ctrl->value = xctrl.value;
-               break;
-       }
-
-       case VIDIOC_S_CTRL:
-       {
-               struct v4l2_control *ctrl = arg;
-               struct v4l2_ext_control xctrl;
-
-               memset(&xctrl, 0, sizeof xctrl);
-               xctrl.id = ctrl->id;
-               xctrl.value = ctrl->value;
-
-               ret = uvc_ctrl_begin(chain);
-               if (ret < 0)
-                       return ret;
-
-               ret = uvc_ctrl_set(chain, &xctrl);
-               if (ret < 0) {
-                       uvc_ctrl_rollback(handle);
-                       return ret;
-               }
-               ret = uvc_ctrl_commit(handle, &xctrl, 1);
-               if (ret == 0)
-                       ctrl->value = xctrl.value;
-               break;
-       }
-
-       case VIDIOC_QUERYMENU:
-               return uvc_query_v4l2_menu(chain, arg);
-
-       case VIDIOC_G_EXT_CTRLS:
-       {
-               struct v4l2_ext_controls *ctrls = arg;
-               struct v4l2_ext_control *ctrl = ctrls->controls;
-               unsigned int i;
-
-               ret = uvc_ctrl_begin(chain);
-               if (ret < 0)
-                       return ret;
-
-               for (i = 0; i < ctrls->count; ++ctrl, ++i) {
-                       ret = uvc_ctrl_get(chain, ctrl);
-                       if (ret < 0) {
-                               uvc_ctrl_rollback(handle);
-                               ctrls->error_idx = i;
-                               return ret;
-                       }
-               }
-               ctrls->error_idx = 0;
-               ret = uvc_ctrl_rollback(handle);
-               break;
-       }
-
-       case VIDIOC_S_EXT_CTRLS:
-       case VIDIOC_TRY_EXT_CTRLS:
-       {
-               struct v4l2_ext_controls *ctrls = arg;
-               struct v4l2_ext_control *ctrl = ctrls->controls;
-               unsigned int i;
-
-               ret = uvc_ctrl_begin(chain);
-               if (ret < 0)
-                       return ret;
-
-               for (i = 0; i < ctrls->count; ++ctrl, ++i) {
-                       ret = uvc_ctrl_set(chain, ctrl);
-                       if (ret < 0) {
-                               uvc_ctrl_rollback(handle);
-                               ctrls->error_idx = i;
-                               return ret;
-                       }
-               }
-
-               ctrls->error_idx = 0;
-
-               if (cmd == VIDIOC_S_EXT_CTRLS)
-                       ret = uvc_ctrl_commit(handle,
-                                             ctrls->controls, ctrls->count);
-               else
-                       ret = uvc_ctrl_rollback(handle);
-               break;
-       }
-
-       /* Get, Set & Enum input */
-       case VIDIOC_ENUMINPUT:
-       {
-               const struct uvc_entity *selector = chain->selector;
-               struct v4l2_input *input = arg;
-               struct uvc_entity *iterm = NULL;
-               u32 index = input->index;
-               int pin = 0;
-
-               if (selector == NULL ||
-                   (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
-                       if (index != 0)
-                               return -EINVAL;
-                       list_for_each_entry(iterm, &chain->entities, chain) {
-                               if (UVC_ENTITY_IS_ITERM(iterm))
-                                       break;
-                       }
-                       pin = iterm->id;
-               } else if (index < selector->bNrInPins) {
-                       pin = selector->baSourceID[index];
-                       list_for_each_entry(iterm, &chain->entities, chain) {
-                               if (!UVC_ENTITY_IS_ITERM(iterm))
-                                       continue;
-                               if (iterm->id == pin)
-                                       break;
-                       }
-               }
-
-               if (iterm == NULL || iterm->id != pin)
-                       return -EINVAL;
-
-               memset(input, 0, sizeof *input);
-               input->index = index;
-               strlcpy(input->name, iterm->name, sizeof input->name);
-               if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA)
-                       input->type = V4L2_INPUT_TYPE_CAMERA;
-               break;
-       }
-
-       case VIDIOC_G_INPUT:
-       {
-               u8 input;
-
-               if (chain->selector == NULL ||
-                   (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
-                       *(int *)arg = 0;
-                       break;
-               }
-
-               ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
-                       chain->selector->id, chain->dev->intfnum,
-                       UVC_SU_INPUT_SELECT_CONTROL, &input, 1);
-               if (ret < 0)
-                       return ret;
-
-               *(int *)arg = input - 1;
-               break;
-       }
-
-       case VIDIOC_S_INPUT:
-       {
-               u32 input = *(u32 *)arg + 1;
-
-               if ((ret = uvc_acquire_privileges(handle)) < 0)
-                       return ret;
-
-               if (chain->selector == NULL ||
-                   (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
-                       if (input != 1)
-                               return -EINVAL;
-                       break;
-               }
-
-               if (input == 0 || input > chain->selector->bNrInPins)
-                       return -EINVAL;
-
-               return uvc_query_ctrl(chain->dev, UVC_SET_CUR,
-                       chain->selector->id, chain->dev->intfnum,
-                       UVC_SU_INPUT_SELECT_CONTROL, &input, 1);
-       }
-
-       /* Try, Get, Set & Enum format */
-       case VIDIOC_ENUM_FMT:
-       {
-               struct v4l2_fmtdesc *fmt = arg;
-               struct uvc_format *format;
-               enum v4l2_buf_type type = fmt->type;
-               __u32 index = fmt->index;
-
-               if (fmt->type != stream->type ||
-                   fmt->index >= stream->nformats)
-                       return -EINVAL;
-
-               memset(fmt, 0, sizeof(*fmt));
-               fmt->index = index;
-               fmt->type = type;
-
-               format = &stream->format[fmt->index];
-               fmt->flags = 0;
-               if (format->flags & UVC_FMT_FLAG_COMPRESSED)
-                       fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
-               strlcpy(fmt->description, format->name,
-                       sizeof fmt->description);
-               fmt->description[sizeof fmt->description - 1] = 0;
-               fmt->pixelformat = format->fcc;
-               break;
-       }
-
-       case VIDIOC_TRY_FMT:
-       {
-               struct uvc_streaming_control probe;
-
-               return uvc_v4l2_try_format(stream, arg, &probe, NULL, NULL);
-       }
-
-       case VIDIOC_S_FMT:
-               if ((ret = uvc_acquire_privileges(handle)) < 0)
-                       return ret;
-
-               return uvc_v4l2_set_format(stream, arg);
-
-       case VIDIOC_G_FMT:
-               return uvc_v4l2_get_format(stream, arg);
-
-       /* Frame size enumeration */
-       case VIDIOC_ENUM_FRAMESIZES:
-       {
-               struct v4l2_frmsizeenum *fsize = arg;
-               struct uvc_format *format = NULL;
-               struct uvc_frame *frame;
-               int i;
-
-               /* Look for the given pixel format */
-               for (i = 0; i < stream->nformats; i++) {
-                       if (stream->format[i].fcc ==
-                                       fsize->pixel_format) {
-                               format = &stream->format[i];
-                               break;
-                       }
-               }
-               if (format == NULL)
-                       return -EINVAL;
-
-               if (fsize->index >= format->nframes)
-                       return -EINVAL;
-
-               frame = &format->frame[fsize->index];
-               fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-               fsize->discrete.width = frame->wWidth;
-               fsize->discrete.height = frame->wHeight;
-               break;
-       }
-
-       /* Frame interval enumeration */
-       case VIDIOC_ENUM_FRAMEINTERVALS:
-       {
-               struct v4l2_frmivalenum *fival = arg;
-               struct uvc_format *format = NULL;
-               struct uvc_frame *frame = NULL;
-               int i;
-
-               /* Look for the given pixel format and frame size */
-               for (i = 0; i < stream->nformats; i++) {
-                       if (stream->format[i].fcc ==
-                                       fival->pixel_format) {
-                               format = &stream->format[i];
-                               break;
-                       }
-               }
-               if (format == NULL)
-                       return -EINVAL;
-
-               for (i = 0; i < format->nframes; i++) {
-                       if (format->frame[i].wWidth == fival->width &&
-                           format->frame[i].wHeight == fival->height) {
-                               frame = &format->frame[i];
-                               break;
-                       }
-               }
-               if (frame == NULL)
-                       return -EINVAL;
-
-               if (frame->bFrameIntervalType) {
-                       if (fival->index >= frame->bFrameIntervalType)
-                               return -EINVAL;
-
-                       fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-                       fival->discrete.numerator =
-                               frame->dwFrameInterval[fival->index];
-                       fival->discrete.denominator = 10000000;
-                       uvc_simplify_fraction(&fival->discrete.numerator,
-                               &fival->discrete.denominator, 8, 333);
-               } else {
-                       fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
-                       fival->stepwise.min.numerator =
-                               frame->dwFrameInterval[0];
-                       fival->stepwise.min.denominator = 10000000;
-                       fival->stepwise.max.numerator =
-                               frame->dwFrameInterval[1];
-                       fival->stepwise.max.denominator = 10000000;
-                       fival->stepwise.step.numerator =
-                               frame->dwFrameInterval[2];
-                       fival->stepwise.step.denominator = 10000000;
-                       uvc_simplify_fraction(&fival->stepwise.min.numerator,
-                               &fival->stepwise.min.denominator, 8, 333);
-                       uvc_simplify_fraction(&fival->stepwise.max.numerator,
-                               &fival->stepwise.max.denominator, 8, 333);
-                       uvc_simplify_fraction(&fival->stepwise.step.numerator,
-                               &fival->stepwise.step.denominator, 8, 333);
-               }
-               break;
-       }
-
-       /* Get & Set streaming parameters */
-       case VIDIOC_G_PARM:
-               return uvc_v4l2_get_streamparm(stream, arg);
-
-       case VIDIOC_S_PARM:
-               if ((ret = uvc_acquire_privileges(handle)) < 0)
-                       return ret;
-
-               return uvc_v4l2_set_streamparm(stream, arg);
-
-       /* Cropping and scaling */
-       case VIDIOC_CROPCAP:
-       {
-               struct v4l2_cropcap *ccap = arg;
-
-               if (ccap->type != stream->type)
-                       return -EINVAL;
-
-               ccap->bounds.left = 0;
-               ccap->bounds.top = 0;
-
-               mutex_lock(&stream->mutex);
-               ccap->bounds.width = stream->cur_frame->wWidth;
-               ccap->bounds.height = stream->cur_frame->wHeight;
-               mutex_unlock(&stream->mutex);
-
-               ccap->defrect = ccap->bounds;
-
-               ccap->pixelaspect.numerator = 1;
-               ccap->pixelaspect.denominator = 1;
-               break;
-       }
-
-       case VIDIOC_G_CROP:
-       case VIDIOC_S_CROP:
-               return -EINVAL;
-
-       /* Buffers & streaming */
-       case VIDIOC_REQBUFS:
-               if ((ret = uvc_acquire_privileges(handle)) < 0)
-                       return ret;
-
-               mutex_lock(&stream->mutex);
-               ret = uvc_alloc_buffers(&stream->queue, arg);
-               mutex_unlock(&stream->mutex);
-               if (ret < 0)
-                       return ret;
-
-               if (ret == 0)
-                       uvc_dismiss_privileges(handle);
-
-               ret = 0;
-               break;
-
-       case VIDIOC_QUERYBUF:
-       {
-               struct v4l2_buffer *buf = arg;
-
-               if (!uvc_has_privileges(handle))
-                       return -EBUSY;
-
-               return uvc_query_buffer(&stream->queue, buf);
-       }
-
-       case VIDIOC_QBUF:
-               if (!uvc_has_privileges(handle))
-                       return -EBUSY;
-
-               return uvc_queue_buffer(&stream->queue, arg);
-
-       case VIDIOC_DQBUF:
-               if (!uvc_has_privileges(handle))
-                       return -EBUSY;
-
-               return uvc_dequeue_buffer(&stream->queue, arg,
-                       file->f_flags & O_NONBLOCK);
-
-       case VIDIOC_STREAMON:
-       {
-               int *type = arg;
-
-               if (*type != stream->type)
-                       return -EINVAL;
-
-               if (!uvc_has_privileges(handle))
-                       return -EBUSY;
-
-               mutex_lock(&stream->mutex);
-               ret = uvc_video_enable(stream, 1);
-               mutex_unlock(&stream->mutex);
-               if (ret < 0)
-                       return ret;
-               break;
-       }
-
-       case VIDIOC_STREAMOFF:
-       {
-               int *type = arg;
-
-               if (*type != stream->type)
-                       return -EINVAL;
-
-               if (!uvc_has_privileges(handle))
-                       return -EBUSY;
-
-               return uvc_video_enable(stream, 0);
-       }
-
-       case VIDIOC_SUBSCRIBE_EVENT:
-       {
-               struct v4l2_event_subscription *sub = arg;
-
-               switch (sub->type) {
-               case V4L2_EVENT_CTRL:
-                       return v4l2_event_subscribe(&handle->vfh, sub, 0,
-                                                   &uvc_ctrl_sub_ev_ops);
-               default:
-                       return -EINVAL;
-               }
-       }
-
-       case VIDIOC_UNSUBSCRIBE_EVENT:
-               return v4l2_event_unsubscribe(&handle->vfh, arg);
-
-       case VIDIOC_DQEVENT:
-               return v4l2_event_dequeue(&handle->vfh, arg,
-                                         file->f_flags & O_NONBLOCK);
-
-       /* Analog video standards make no sense for digital cameras. */
-       case VIDIOC_ENUMSTD:
-       case VIDIOC_QUERYSTD:
-       case VIDIOC_G_STD:
-       case VIDIOC_S_STD:
-
-       case VIDIOC_OVERLAY:
-
-       case VIDIOC_ENUMAUDIO:
-       case VIDIOC_ENUMAUDOUT:
-
-       case VIDIOC_ENUMOUTPUT:
-               uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd);
-               return -EINVAL;
-
-       case UVCIOC_CTRL_MAP:
-               return uvc_ioctl_ctrl_map(chain, arg);
-
-       case UVCIOC_CTRL_QUERY:
-               return uvc_xu_ctrl_query(chain, arg);
-
-       default:
-               uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd);
-               return -ENOTTY;
-       }
-
-       return ret;
-}
-
-static long uvc_v4l2_ioctl(struct file *file,
-                    unsigned int cmd, unsigned long arg)
-{
-       if (uvc_trace_param & UVC_TRACE_IOCTL) {
-               uvc_printk(KERN_DEBUG, "uvc_v4l2_ioctl(");
-               v4l_printk_ioctl(NULL, cmd);
-               printk(")\n");
-       }
-
-       return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl);
-}
-
-#ifdef CONFIG_COMPAT
-struct uvc_xu_control_mapping32 {
-       __u32 id;
-       __u8 name[32];
-       __u8 entity[16];
-       __u8 selector;
-
-       __u8 size;
-       __u8 offset;
-       __u32 v4l2_type;
-       __u32 data_type;
-
-       compat_caddr_t menu_info;
-       __u32 menu_count;
-
-       __u32 reserved[4];
-};
-
-static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp,
-                       const struct uvc_xu_control_mapping32 __user *up)
-{
-       struct uvc_menu_info __user *umenus;
-       struct uvc_menu_info __user *kmenus;
-       compat_caddr_t p;
-
-       if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
-           __copy_from_user(kp, up, offsetof(typeof(*up), menu_info)) ||
-           __get_user(kp->menu_count, &up->menu_count))
-               return -EFAULT;
-
-       memset(kp->reserved, 0, sizeof(kp->reserved));
-
-       if (kp->menu_count == 0) {
-               kp->menu_info = NULL;
-               return 0;
-       }
-
-       if (__get_user(p, &up->menu_info))
-               return -EFAULT;
-       umenus = compat_ptr(p);
-       if (!access_ok(VERIFY_READ, umenus, kp->menu_count * sizeof(*umenus)))
-               return -EFAULT;
-
-       kmenus = compat_alloc_user_space(kp->menu_count * sizeof(*kmenus));
-       if (kmenus == NULL)
-               return -EFAULT;
-       kp->menu_info = kmenus;
-
-       if (copy_in_user(kmenus, umenus, kp->menu_count * sizeof(*umenus)))
-               return -EFAULT;
-
-       return 0;
-}
-
-static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp,
-                       struct uvc_xu_control_mapping32 __user *up)
-{
-       struct uvc_menu_info __user *umenus;
-       struct uvc_menu_info __user *kmenus = kp->menu_info;
-       compat_caddr_t p;
-
-       if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
-           __copy_to_user(up, kp, offsetof(typeof(*up), menu_info)) ||
-           __put_user(kp->menu_count, &up->menu_count))
-               return -EFAULT;
-
-       if (__clear_user(up->reserved, sizeof(up->reserved)))
-               return -EFAULT;
-
-       if (kp->menu_count == 0)
-               return 0;
-
-       if (get_user(p, &up->menu_info))
-               return -EFAULT;
-       umenus = compat_ptr(p);
-
-       if (copy_in_user(umenus, kmenus, kp->menu_count * sizeof(*umenus)))
-               return -EFAULT;
-
-       return 0;
-}
-
-struct uvc_xu_control_query32 {
-       __u8 unit;
-       __u8 selector;
-       __u8 query;
-       __u16 size;
-       compat_caddr_t data;
-};
-
-static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp,
-                       const struct uvc_xu_control_query32 __user *up)
-{
-       u8 __user *udata;
-       u8 __user *kdata;
-       compat_caddr_t p;
-
-       if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
-           __copy_from_user(kp, up, offsetof(typeof(*up), data)))
-               return -EFAULT;
-
-       if (kp->size == 0) {
-               kp->data = NULL;
-               return 0;
-       }
-
-       if (__get_user(p, &up->data))
-               return -EFAULT;
-       udata = compat_ptr(p);
-       if (!access_ok(VERIFY_READ, udata, kp->size))
-               return -EFAULT;
-
-       kdata = compat_alloc_user_space(kp->size);
-       if (kdata == NULL)
-               return -EFAULT;
-       kp->data = kdata;
-
-       if (copy_in_user(kdata, udata, kp->size))
-               return -EFAULT;
-
-       return 0;
-}
-
-static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp,
-                       struct uvc_xu_control_query32 __user *up)
-{
-       u8 __user *udata;
-       u8 __user *kdata = kp->data;
-       compat_caddr_t p;
-
-       if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
-           __copy_to_user(up, kp, offsetof(typeof(*up), data)))
-               return -EFAULT;
-
-       if (kp->size == 0)
-               return 0;
-
-       if (get_user(p, &up->data))
-               return -EFAULT;
-       udata = compat_ptr(p);
-       if (!access_ok(VERIFY_READ, udata, kp->size))
-               return -EFAULT;
-
-       if (copy_in_user(udata, kdata, kp->size))
-               return -EFAULT;
-
-       return 0;
-}
-
-#define UVCIOC_CTRL_MAP32      _IOWR('u', 0x20, struct uvc_xu_control_mapping32)
-#define UVCIOC_CTRL_QUERY32    _IOWR('u', 0x21, struct uvc_xu_control_query32)
-
-static long uvc_v4l2_compat_ioctl32(struct file *file,
-                    unsigned int cmd, unsigned long arg)
-{
-       union {
-               struct uvc_xu_control_mapping xmap;
-               struct uvc_xu_control_query xqry;
-       } karg;
-       void __user *up = compat_ptr(arg);
-       mm_segment_t old_fs;
-       long ret;
-
-       switch (cmd) {
-       case UVCIOC_CTRL_MAP32:
-               cmd = UVCIOC_CTRL_MAP;
-               ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up);
-               break;
-
-       case UVCIOC_CTRL_QUERY32:
-               cmd = UVCIOC_CTRL_QUERY;
-               ret = uvc_v4l2_get_xu_query(&karg.xqry, up);
-               break;
-
-       default:
-               return -ENOIOCTLCMD;
-       }
-
-       old_fs = get_fs();
-       set_fs(KERNEL_DS);
-       ret = uvc_v4l2_ioctl(file, cmd, (unsigned long)&karg);
-       set_fs(old_fs);
-
-       if (ret < 0)
-               return ret;
-
-       switch (cmd) {
-       case UVCIOC_CTRL_MAP:
-               ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up);
-               break;
-
-       case UVCIOC_CTRL_QUERY:
-               ret = uvc_v4l2_put_xu_query(&karg.xqry, up);
-               break;
-       }
-
-       return ret;
-}
-#endif
-
-static ssize_t uvc_v4l2_read(struct file *file, char __user *data,
-                   size_t count, loff_t *ppos)
-{
-       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_read: not implemented.\n");
-       return -EINVAL;
-}
-
-static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct uvc_fh *handle = file->private_data;
-       struct uvc_streaming *stream = handle->stream;
-
-       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n");
-
-       return uvc_queue_mmap(&stream->queue, vma);
-}
-
-static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
-{
-       struct uvc_fh *handle = file->private_data;
-       struct uvc_streaming *stream = handle->stream;
-
-       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n");
-
-       return uvc_queue_poll(&stream->queue, file, wait);
-}
-
-#ifndef CONFIG_MMU
-static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
-               unsigned long addr, unsigned long len, unsigned long pgoff,
-               unsigned long flags)
-{
-       struct uvc_fh *handle = file->private_data;
-       struct uvc_streaming *stream = handle->stream;
-
-       uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n");
-
-       return uvc_queue_get_unmapped_area(&stream->queue, pgoff);
-}
-#endif
-
-const struct v4l2_file_operations uvc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = uvc_v4l2_open,
-       .release        = uvc_v4l2_release,
-       .unlocked_ioctl = uvc_v4l2_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl32 = uvc_v4l2_compat_ioctl32,
-#endif
-       .read           = uvc_v4l2_read,
-       .mmap           = uvc_v4l2_mmap,
-       .poll           = uvc_v4l2_poll,
-#ifndef CONFIG_MMU
-       .get_unmapped_area = uvc_v4l2_get_unmapped_area,
-#endif
-};
-
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
deleted file mode 100644 (file)
index 1c15b42..0000000
+++ /dev/null
@@ -1,1879 +0,0 @@
-/*
- *      uvc_video.c  --  USB Video Class driver - Video handling
- *
- *      Copyright (C) 2005-2010
- *          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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include <linux/vmalloc.h>
-#include <linux/wait.h>
-#include <linux/atomic.h>
-#include <asm/unaligned.h>
-
-#include <media/v4l2-common.h>
-
-#include "uvcvideo.h"
-
-/* ------------------------------------------------------------------------
- * UVC Controls
- */
-
-static int __uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
-                       __u8 intfnum, __u8 cs, void *data, __u16 size,
-                       int timeout)
-{
-       __u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-       unsigned int pipe;
-
-       pipe = (query & 0x80) ? usb_rcvctrlpipe(dev->udev, 0)
-                             : usb_sndctrlpipe(dev->udev, 0);
-       type |= (query & 0x80) ? USB_DIR_IN : USB_DIR_OUT;
-
-       return usb_control_msg(dev->udev, pipe, query, type, cs << 8,
-                       unit << 8 | intfnum, data, size, timeout);
-}
-
-static const char *uvc_query_name(__u8 query)
-{
-       switch (query) {
-       case UVC_SET_CUR:
-               return "SET_CUR";
-       case UVC_GET_CUR:
-               return "GET_CUR";
-       case UVC_GET_MIN:
-               return "GET_MIN";
-       case UVC_GET_MAX:
-               return "GET_MAX";
-       case UVC_GET_RES:
-               return "GET_RES";
-       case UVC_GET_LEN:
-               return "GET_LEN";
-       case UVC_GET_INFO:
-               return "GET_INFO";
-       case UVC_GET_DEF:
-               return "GET_DEF";
-       default:
-               return "<invalid>";
-       }
-}
-
-int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
-                       __u8 intfnum, __u8 cs, void *data, __u16 size)
-{
-       int ret;
-
-       ret = __uvc_query_ctrl(dev, query, unit, intfnum, cs, data, size,
-                               UVC_CTRL_CONTROL_TIMEOUT);
-       if (ret != size) {
-               uvc_printk(KERN_ERR, "Failed to query (%s) UVC control %u on "
-                       "unit %u: %d (exp. %u).\n", uvc_query_name(query), cs,
-                       unit, ret, size);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
-       struct uvc_streaming_control *ctrl)
-{
-       struct uvc_format *format = NULL;
-       struct uvc_frame *frame = NULL;
-       unsigned int i;
-
-       for (i = 0; i < stream->nformats; ++i) {
-               if (stream->format[i].index == ctrl->bFormatIndex) {
-                       format = &stream->format[i];
-                       break;
-               }
-       }
-
-       if (format == NULL)
-               return;
-
-       for (i = 0; i < format->nframes; ++i) {
-               if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) {
-                       frame = &format->frame[i];
-                       break;
-               }
-       }
-
-       if (frame == NULL)
-               return;
-
-       if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) ||
-            (ctrl->dwMaxVideoFrameSize == 0 &&
-             stream->dev->uvc_version < 0x0110))
-               ctrl->dwMaxVideoFrameSize =
-                       frame->dwMaxVideoFrameBufferSize;
-
-       if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) &&
-           stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH &&
-           stream->intf->num_altsetting > 1) {
-               u32 interval;
-               u32 bandwidth;
-
-               interval = (ctrl->dwFrameInterval > 100000)
-                        ? ctrl->dwFrameInterval
-                        : frame->dwFrameInterval[0];
-
-               /* Compute a bandwidth estimation by multiplying the frame
-                * size by the number of video frames per second, divide the
-                * result by the number of USB frames (or micro-frames for
-                * high-speed devices) per second and add the UVC header size
-                * (assumed to be 12 bytes long).
-                */
-               bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp;
-               bandwidth *= 10000000 / interval + 1;
-               bandwidth /= 1000;
-               if (stream->dev->udev->speed == USB_SPEED_HIGH)
-                       bandwidth /= 8;
-               bandwidth += 12;
-
-               /* The bandwidth estimate is too low for many cameras. Don't use
-                * maximum packet sizes lower than 1024 bytes to try and work
-                * around the problem. According to measurements done on two
-                * different camera models, the value is high enough to get most
-                * resolutions working while not preventing two simultaneous
-                * VGA streams at 15 fps.
-                */
-               bandwidth = max_t(u32, bandwidth, 1024);
-
-               ctrl->dwMaxPayloadTransferSize = bandwidth;
-       }
-}
-
-static int uvc_get_video_ctrl(struct uvc_streaming *stream,
-       struct uvc_streaming_control *ctrl, int probe, __u8 query)
-{
-       __u8 *data;
-       __u16 size;
-       int ret;
-
-       size = stream->dev->uvc_version >= 0x0110 ? 34 : 26;
-       if ((stream->dev->quirks & UVC_QUIRK_PROBE_DEF) &&
-                       query == UVC_GET_DEF)
-               return -EIO;
-
-       data = kmalloc(size, GFP_KERNEL);
-       if (data == NULL)
-               return -ENOMEM;
-
-       ret = __uvc_query_ctrl(stream->dev, query, 0, stream->intfnum,
-               probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data,
-               size, uvc_timeout_param);
-
-       if ((query == UVC_GET_MIN || query == UVC_GET_MAX) && ret == 2) {
-               /* Some cameras, mostly based on Bison Electronics chipsets,
-                * answer a GET_MIN or GET_MAX request with the wCompQuality
-                * field only.
-                */
-               uvc_warn_once(stream->dev, UVC_WARN_MINMAX, "UVC non "
-                       "compliance - GET_MIN/MAX(PROBE) incorrectly "
-                       "supported. Enabling workaround.\n");
-               memset(ctrl, 0, sizeof *ctrl);
-               ctrl->wCompQuality = le16_to_cpup((__le16 *)data);
-               ret = 0;
-               goto out;
-       } else if (query == UVC_GET_DEF && probe == 1 && ret != size) {
-               /* Many cameras don't support the GET_DEF request on their
-                * video probe control. Warn once and return, the caller will
-                * fall back to GET_CUR.
-                */
-               uvc_warn_once(stream->dev, UVC_WARN_PROBE_DEF, "UVC non "
-                       "compliance - GET_DEF(PROBE) not supported. "
-                       "Enabling workaround.\n");
-               ret = -EIO;
-               goto out;
-       } else if (ret != size) {
-               uvc_printk(KERN_ERR, "Failed to query (%u) UVC %s control : "
-                       "%d (exp. %u).\n", query, probe ? "probe" : "commit",
-                       ret, size);
-               ret = -EIO;
-               goto out;
-       }
-
-       ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]);
-       ctrl->bFormatIndex = data[2];
-       ctrl->bFrameIndex = data[3];
-       ctrl->dwFrameInterval = le32_to_cpup((__le32 *)&data[4]);
-       ctrl->wKeyFrameRate = le16_to_cpup((__le16 *)&data[8]);
-       ctrl->wPFrameRate = le16_to_cpup((__le16 *)&data[10]);
-       ctrl->wCompQuality = le16_to_cpup((__le16 *)&data[12]);
-       ctrl->wCompWindowSize = le16_to_cpup((__le16 *)&data[14]);
-       ctrl->wDelay = le16_to_cpup((__le16 *)&data[16]);
-       ctrl->dwMaxVideoFrameSize = get_unaligned_le32(&data[18]);
-       ctrl->dwMaxPayloadTransferSize = get_unaligned_le32(&data[22]);
-
-       if (size == 34) {
-               ctrl->dwClockFrequency = get_unaligned_le32(&data[26]);
-               ctrl->bmFramingInfo = data[30];
-               ctrl->bPreferedVersion = data[31];
-               ctrl->bMinVersion = data[32];
-               ctrl->bMaxVersion = data[33];
-       } else {
-               ctrl->dwClockFrequency = stream->dev->clock_frequency;
-               ctrl->bmFramingInfo = 0;
-               ctrl->bPreferedVersion = 0;
-               ctrl->bMinVersion = 0;
-               ctrl->bMaxVersion = 0;
-       }
-
-       /* Some broken devices return null or wrong dwMaxVideoFrameSize and
-        * dwMaxPayloadTransferSize fields. Try to get the value from the
-        * format and frame descriptors.
-        */
-       uvc_fixup_video_ctrl(stream, ctrl);
-       ret = 0;
-
-out:
-       kfree(data);
-       return ret;
-}
-
-static int uvc_set_video_ctrl(struct uvc_streaming *stream,
-       struct uvc_streaming_control *ctrl, int probe)
-{
-       __u8 *data;
-       __u16 size;
-       int ret;
-
-       size = stream->dev->uvc_version >= 0x0110 ? 34 : 26;
-       data = kzalloc(size, GFP_KERNEL);
-       if (data == NULL)
-               return -ENOMEM;
-
-       *(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint);
-       data[2] = ctrl->bFormatIndex;
-       data[3] = ctrl->bFrameIndex;
-       *(__le32 *)&data[4] = cpu_to_le32(ctrl->dwFrameInterval);
-       *(__le16 *)&data[8] = cpu_to_le16(ctrl->wKeyFrameRate);
-       *(__le16 *)&data[10] = cpu_to_le16(ctrl->wPFrameRate);
-       *(__le16 *)&data[12] = cpu_to_le16(ctrl->wCompQuality);
-       *(__le16 *)&data[14] = cpu_to_le16(ctrl->wCompWindowSize);
-       *(__le16 *)&data[16] = cpu_to_le16(ctrl->wDelay);
-       put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]);
-       put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]);
-
-       if (size == 34) {
-               put_unaligned_le32(ctrl->dwClockFrequency, &data[26]);
-               data[30] = ctrl->bmFramingInfo;
-               data[31] = ctrl->bPreferedVersion;
-               data[32] = ctrl->bMinVersion;
-               data[33] = ctrl->bMaxVersion;
-       }
-
-       ret = __uvc_query_ctrl(stream->dev, UVC_SET_CUR, 0, stream->intfnum,
-               probe ? UVC_VS_PROBE_CONTROL : UVC_VS_COMMIT_CONTROL, data,
-               size, uvc_timeout_param);
-       if (ret != size) {
-               uvc_printk(KERN_ERR, "Failed to set UVC %s control : "
-                       "%d (exp. %u).\n", probe ? "probe" : "commit",
-                       ret, size);
-               ret = -EIO;
-       }
-
-       kfree(data);
-       return ret;
-}
-
-int uvc_probe_video(struct uvc_streaming *stream,
-       struct uvc_streaming_control *probe)
-{
-       struct uvc_streaming_control probe_min, probe_max;
-       __u16 bandwidth;
-       unsigned int i;
-       int ret;
-
-       /* Perform probing. The device should adjust the requested values
-        * according to its capabilities. However, some devices, namely the
-        * first generation UVC Logitech webcams, don't implement the Video
-        * Probe control properly, and just return the needed bandwidth. For
-        * that reason, if the needed bandwidth exceeds the maximum available
-        * bandwidth, try to lower the quality.
-        */
-       ret = uvc_set_video_ctrl(stream, probe, 1);
-       if (ret < 0)
-               goto done;
-
-       /* Get the minimum and maximum values for compression settings. */
-       if (!(stream->dev->quirks & UVC_QUIRK_PROBE_MINMAX)) {
-               ret = uvc_get_video_ctrl(stream, &probe_min, 1, UVC_GET_MIN);
-               if (ret < 0)
-                       goto done;
-               ret = uvc_get_video_ctrl(stream, &probe_max, 1, UVC_GET_MAX);
-               if (ret < 0)
-                       goto done;
-
-               probe->wCompQuality = probe_max.wCompQuality;
-       }
-
-       for (i = 0; i < 2; ++i) {
-               ret = uvc_set_video_ctrl(stream, probe, 1);
-               if (ret < 0)
-                       goto done;
-               ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR);
-               if (ret < 0)
-                       goto done;
-
-               if (stream->intf->num_altsetting == 1)
-                       break;
-
-               bandwidth = probe->dwMaxPayloadTransferSize;
-               if (bandwidth <= stream->maxpsize)
-                       break;
-
-               if (stream->dev->quirks & UVC_QUIRK_PROBE_MINMAX) {
-                       ret = -ENOSPC;
-                       goto done;
-               }
-
-               /* TODO: negotiate compression parameters */
-               probe->wKeyFrameRate = probe_min.wKeyFrameRate;
-               probe->wPFrameRate = probe_min.wPFrameRate;
-               probe->wCompQuality = probe_max.wCompQuality;
-               probe->wCompWindowSize = probe_min.wCompWindowSize;
-       }
-
-done:
-       return ret;
-}
-
-static int uvc_commit_video(struct uvc_streaming *stream,
-                           struct uvc_streaming_control *probe)
-{
-       return uvc_set_video_ctrl(stream, probe, 0);
-}
-
-/* -----------------------------------------------------------------------------
- * Clocks and timestamps
- */
-
-static void
-uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
-                      const __u8 *data, int len)
-{
-       struct uvc_clock_sample *sample;
-       unsigned int header_size;
-       bool has_pts = false;
-       bool has_scr = false;
-       unsigned long flags;
-       struct timespec ts;
-       u16 host_sof;
-       u16 dev_sof;
-
-       switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
-       case UVC_STREAM_PTS | UVC_STREAM_SCR:
-               header_size = 12;
-               has_pts = true;
-               has_scr = true;
-               break;
-       case UVC_STREAM_PTS:
-               header_size = 6;
-               has_pts = true;
-               break;
-       case UVC_STREAM_SCR:
-               header_size = 8;
-               has_scr = true;
-               break;
-       default:
-               header_size = 2;
-               break;
-       }
-
-       /* Check for invalid headers. */
-       if (len < header_size)
-               return;
-
-       /* Extract the timestamps:
-        *
-        * - store the frame PTS in the buffer structure
-        * - if the SCR field is present, retrieve the host SOF counter and
-        *   kernel timestamps and store them with the SCR STC and SOF fields
-        *   in the ring buffer
-        */
-       if (has_pts && buf != NULL)
-               buf->pts = get_unaligned_le32(&data[2]);
-
-       if (!has_scr)
-               return;
-
-       /* To limit the amount of data, drop SCRs with an SOF identical to the
-        * previous one.
-        */
-       dev_sof = get_unaligned_le16(&data[header_size - 2]);
-       if (dev_sof == stream->clock.last_sof)
-               return;
-
-       stream->clock.last_sof = dev_sof;
-
-       host_sof = usb_get_current_frame_number(stream->dev->udev);
-       ktime_get_ts(&ts);
-
-       /* The UVC specification allows device implementations that can't obtain
-        * the USB frame number to keep their own frame counters as long as they
-        * match the size and frequency of the frame number associated with USB
-        * SOF tokens. The SOF values sent by such devices differ from the USB
-        * SOF tokens by a fixed offset that needs to be estimated and accounted
-        * for to make timestamp recovery as accurate as possible.
-        *
-        * The offset is estimated the first time a device SOF value is received
-        * as the difference between the host and device SOF values. As the two
-        * SOF values can differ slightly due to transmission delays, consider
-        * that the offset is null if the difference is not higher than 10 ms
-        * (negative differences can not happen and are thus considered as an
-        * offset). The video commit control wDelay field should be used to
-        * compute a dynamic threshold instead of using a fixed 10 ms value, but
-        * devices don't report reliable wDelay values.
-        *
-        * See uvc_video_clock_host_sof() for an explanation regarding why only
-        * the 8 LSBs of the delta are kept.
-        */
-       if (stream->clock.sof_offset == (u16)-1) {
-               u16 delta_sof = (host_sof - dev_sof) & 255;
-               if (delta_sof >= 10)
-                       stream->clock.sof_offset = delta_sof;
-               else
-                       stream->clock.sof_offset = 0;
-       }
-
-       dev_sof = (dev_sof + stream->clock.sof_offset) & 2047;
-
-       spin_lock_irqsave(&stream->clock.lock, flags);
-
-       sample = &stream->clock.samples[stream->clock.head];
-       sample->dev_stc = get_unaligned_le32(&data[header_size - 6]);
-       sample->dev_sof = dev_sof;
-       sample->host_sof = host_sof;
-       sample->host_ts = ts;
-
-       /* Update the sliding window head and count. */
-       stream->clock.head = (stream->clock.head + 1) % stream->clock.size;
-
-       if (stream->clock.count < stream->clock.size)
-               stream->clock.count++;
-
-       spin_unlock_irqrestore(&stream->clock.lock, flags);
-}
-
-static void uvc_video_clock_reset(struct uvc_streaming *stream)
-{
-       struct uvc_clock *clock = &stream->clock;
-
-       clock->head = 0;
-       clock->count = 0;
-       clock->last_sof = -1;
-       clock->sof_offset = -1;
-}
-
-static int uvc_video_clock_init(struct uvc_streaming *stream)
-{
-       struct uvc_clock *clock = &stream->clock;
-
-       spin_lock_init(&clock->lock);
-       clock->size = 32;
-
-       clock->samples = kmalloc(clock->size * sizeof(*clock->samples),
-                                GFP_KERNEL);
-       if (clock->samples == NULL)
-               return -ENOMEM;
-
-       uvc_video_clock_reset(stream);
-
-       return 0;
-}
-
-static void uvc_video_clock_cleanup(struct uvc_streaming *stream)
-{
-       kfree(stream->clock.samples);
-       stream->clock.samples = NULL;
-}
-
-/*
- * uvc_video_clock_host_sof - Return the host SOF value for a clock sample
- *
- * Host SOF counters reported by usb_get_current_frame_number() usually don't
- * cover the whole 11-bits SOF range (0-2047) but are limited to the HCI frame
- * schedule window. They can be limited to 8, 9 or 10 bits depending on the host
- * controller and its configuration.
- *
- * We thus need to recover the SOF value corresponding to the host frame number.
- * As the device and host frame numbers are sampled in a short interval, the
- * difference between their values should be equal to a small delta plus an
- * integer multiple of 256 caused by the host frame number limited precision.
- *
- * To obtain the recovered host SOF value, compute the small delta by masking
- * the high bits of the host frame counter and device SOF difference and add it
- * to the device SOF value.
- */
-static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample)
-{
-       /* The delta value can be negative. */
-       s8 delta_sof;
-
-       delta_sof = (sample->host_sof - sample->dev_sof) & 255;
-
-       return (sample->dev_sof + delta_sof) & 2047;
-}
-
-/*
- * uvc_video_clock_update - Update the buffer timestamp
- *
- * This function converts the buffer PTS timestamp to the host clock domain by
- * going through the USB SOF clock domain and stores the result in the V4L2
- * buffer timestamp field.
- *
- * The relationship between the device clock and the host clock isn't known.
- * However, the device and the host share the common USB SOF clock which can be
- * used to recover that relationship.
- *
- * The relationship between the device clock and the USB SOF clock is considered
- * to be linear over the clock samples sliding window and is given by
- *
- * SOF = m * PTS + p
- *
- * Several methods to compute the slope (m) and intercept (p) can be used. As
- * the clock drift should be small compared to the sliding window size, we
- * assume that the line that goes through the points at both ends of the window
- * is a good approximation. Naming those points P1 and P2, we get
- *
- * SOF = (SOF2 - SOF1) / (STC2 - STC1) * PTS
- *     + (SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1)
- *
- * or
- *
- * SOF = ((SOF2 - SOF1) * PTS + SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1)   (1)
- *
- * to avoid loosing precision in the division. Similarly, the host timestamp is
- * computed with
- *
- * TS = ((TS2 - TS1) * PTS + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1)       (2)
- *
- * SOF values are coded on 11 bits by USB. We extend their precision with 16
- * decimal bits, leading to a 11.16 coding.
- *
- * TODO: To avoid surprises with device clock values, PTS/STC timestamps should
- * be normalized using the nominal device clock frequency reported through the
- * UVC descriptors.
- *
- * Both the PTS/STC and SOF counters roll over, after a fixed but device
- * specific amount of time for PTS/STC and after 2048ms for SOF. As long as the
- * sliding window size is smaller than the rollover period, differences computed
- * on unsigned integers will produce the correct result. However, the p term in
- * the linear relations will be miscomputed.
- *
- * To fix the issue, we subtract a constant from the PTS and STC values to bring
- * PTS to half the 32 bit STC range. The sliding window STC values then fit into
- * the 32 bit range without any rollover.
- *
- * Similarly, we add 2048 to the device SOF values to make sure that the SOF
- * computed by (1) will never be smaller than 0. This offset is then compensated
- * by adding 2048 to the SOF values used in (2). However, this doesn't prevent
- * rollovers between (1) and (2): the SOF value computed by (1) can be slightly
- * lower than 4096, and the host SOF counters can have rolled over to 2048. This
- * case is handled by subtracting 2048 from the SOF value if it exceeds the host
- * SOF value at the end of the sliding window.
- *
- * Finally we subtract a constant from the host timestamps to bring the first
- * timestamp of the sliding window to 1s.
- */
-void uvc_video_clock_update(struct uvc_streaming *stream,
-                           struct v4l2_buffer *v4l2_buf,
-                           struct uvc_buffer *buf)
-{
-       struct uvc_clock *clock = &stream->clock;
-       struct uvc_clock_sample *first;
-       struct uvc_clock_sample *last;
-       unsigned long flags;
-       struct timespec ts;
-       u32 delta_stc;
-       u32 y1, y2;
-       u32 x1, x2;
-       u32 mean;
-       u32 sof;
-       u32 div;
-       u32 rem;
-       u64 y;
-
-       spin_lock_irqsave(&clock->lock, flags);
-
-       if (clock->count < clock->size)
-               goto done;
-
-       first = &clock->samples[clock->head];
-       last = &clock->samples[(clock->head - 1) % clock->size];
-
-       /* First step, PTS to SOF conversion. */
-       delta_stc = buf->pts - (1UL << 31);
-       x1 = first->dev_stc - delta_stc;
-       x2 = last->dev_stc - delta_stc;
-       if (x1 == x2)
-               goto done;
-
-       y1 = (first->dev_sof + 2048) << 16;
-       y2 = (last->dev_sof + 2048) << 16;
-       if (y2 < y1)
-               y2 += 2048 << 16;
-
-       y = (u64)(y2 - y1) * (1ULL << 31) + (u64)y1 * (u64)x2
-         - (u64)y2 * (u64)x1;
-       y = div_u64(y, x2 - x1);
-
-       sof = y;
-
-       uvc_trace(UVC_TRACE_CLOCK, "%s: PTS %u y %llu.%06llu SOF %u.%06llu "
-                 "(x1 %u x2 %u y1 %u y2 %u SOF offset %u)\n",
-                 stream->dev->name, buf->pts,
-                 y >> 16, div_u64((y & 0xffff) * 1000000, 65536),
-                 sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
-                 x1, x2, y1, y2, clock->sof_offset);
-
-       /* Second step, SOF to host clock conversion. */
-       x1 = (uvc_video_clock_host_sof(first) + 2048) << 16;
-       x2 = (uvc_video_clock_host_sof(last) + 2048) << 16;
-       if (x2 < x1)
-               x2 += 2048 << 16;
-       if (x1 == x2)
-               goto done;
-
-       ts = timespec_sub(last->host_ts, first->host_ts);
-       y1 = NSEC_PER_SEC;
-       y2 = (ts.tv_sec + 1) * NSEC_PER_SEC + ts.tv_nsec;
-
-       /* Interpolated and host SOF timestamps can wrap around at slightly
-        * different times. Handle this by adding or removing 2048 to or from
-        * the computed SOF value to keep it close to the SOF samples mean
-        * value.
-        */
-       mean = (x1 + x2) / 2;
-       if (mean - (1024 << 16) > sof)
-               sof += 2048 << 16;
-       else if (sof > mean + (1024 << 16))
-               sof -= 2048 << 16;
-
-       y = (u64)(y2 - y1) * (u64)sof + (u64)y1 * (u64)x2
-         - (u64)y2 * (u64)x1;
-       y = div_u64(y, x2 - x1);
-
-       div = div_u64_rem(y, NSEC_PER_SEC, &rem);
-       ts.tv_sec = first->host_ts.tv_sec - 1 + div;
-       ts.tv_nsec = first->host_ts.tv_nsec + rem;
-       if (ts.tv_nsec >= NSEC_PER_SEC) {
-               ts.tv_sec++;
-               ts.tv_nsec -= NSEC_PER_SEC;
-       }
-
-       uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %lu.%06lu "
-                 "buf ts %lu.%06lu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n",
-                 stream->dev->name,
-                 sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
-                 y, ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC,
-                 v4l2_buf->timestamp.tv_sec, v4l2_buf->timestamp.tv_usec,
-                 x1, first->host_sof, first->dev_sof,
-                 x2, last->host_sof, last->dev_sof, y1, y2);
-
-       /* Update the V4L2 buffer. */
-       v4l2_buf->timestamp.tv_sec = ts.tv_sec;
-       v4l2_buf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
-
-done:
-       spin_unlock_irqrestore(&stream->clock.lock, flags);
-}
-
-/* ------------------------------------------------------------------------
- * Stream statistics
- */
-
-static void uvc_video_stats_decode(struct uvc_streaming *stream,
-               const __u8 *data, int len)
-{
-       unsigned int header_size;
-       bool has_pts = false;
-       bool has_scr = false;
-       u16 uninitialized_var(scr_sof);
-       u32 uninitialized_var(scr_stc);
-       u32 uninitialized_var(pts);
-
-       if (stream->stats.stream.nb_frames == 0 &&
-           stream->stats.frame.nb_packets == 0)
-               ktime_get_ts(&stream->stats.stream.start_ts);
-
-       switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
-       case UVC_STREAM_PTS | UVC_STREAM_SCR:
-               header_size = 12;
-               has_pts = true;
-               has_scr = true;
-               break;
-       case UVC_STREAM_PTS:
-               header_size = 6;
-               has_pts = true;
-               break;
-       case UVC_STREAM_SCR:
-               header_size = 8;
-               has_scr = true;
-               break;
-       default:
-               header_size = 2;
-               break;
-       }
-
-       /* Check for invalid headers. */
-       if (len < header_size || data[0] < header_size) {
-               stream->stats.frame.nb_invalid++;
-               return;
-       }
-
-       /* Extract the timestamps. */
-       if (has_pts)
-               pts = get_unaligned_le32(&data[2]);
-
-       if (has_scr) {
-               scr_stc = get_unaligned_le32(&data[header_size - 6]);
-               scr_sof = get_unaligned_le16(&data[header_size - 2]);
-       }
-
-       /* Is PTS constant through the whole frame ? */
-       if (has_pts && stream->stats.frame.nb_pts) {
-               if (stream->stats.frame.pts != pts) {
-                       stream->stats.frame.nb_pts_diffs++;
-                       stream->stats.frame.last_pts_diff =
-                               stream->stats.frame.nb_packets;
-               }
-       }
-
-       if (has_pts) {
-               stream->stats.frame.nb_pts++;
-               stream->stats.frame.pts = pts;
-       }
-
-       /* Do all frames have a PTS in their first non-empty packet, or before
-        * their first empty packet ?
-        */
-       if (stream->stats.frame.size == 0) {
-               if (len > header_size)
-                       stream->stats.frame.has_initial_pts = has_pts;
-               if (len == header_size && has_pts)
-                       stream->stats.frame.has_early_pts = true;
-       }
-
-       /* Do the SCR.STC and SCR.SOF fields vary through the frame ? */
-       if (has_scr && stream->stats.frame.nb_scr) {
-               if (stream->stats.frame.scr_stc != scr_stc)
-                       stream->stats.frame.nb_scr_diffs++;
-       }
-
-       if (has_scr) {
-               /* Expand the SOF counter to 32 bits and store its value. */
-               if (stream->stats.stream.nb_frames > 0 ||
-                   stream->stats.frame.nb_scr > 0)
-                       stream->stats.stream.scr_sof_count +=
-                               (scr_sof - stream->stats.stream.scr_sof) % 2048;
-               stream->stats.stream.scr_sof = scr_sof;
-
-               stream->stats.frame.nb_scr++;
-               stream->stats.frame.scr_stc = scr_stc;
-               stream->stats.frame.scr_sof = scr_sof;
-
-               if (scr_sof < stream->stats.stream.min_sof)
-                       stream->stats.stream.min_sof = scr_sof;
-               if (scr_sof > stream->stats.stream.max_sof)
-                       stream->stats.stream.max_sof = scr_sof;
-       }
-
-       /* Record the first non-empty packet number. */
-       if (stream->stats.frame.size == 0 && len > header_size)
-               stream->stats.frame.first_data = stream->stats.frame.nb_packets;
-
-       /* Update the frame size. */
-       stream->stats.frame.size += len - header_size;
-
-       /* Update the packets counters. */
-       stream->stats.frame.nb_packets++;
-       if (len > header_size)
-               stream->stats.frame.nb_empty++;
-
-       if (data[1] & UVC_STREAM_ERR)
-               stream->stats.frame.nb_errors++;
-}
-
-static void uvc_video_stats_update(struct uvc_streaming *stream)
-{
-       struct uvc_stats_frame *frame = &stream->stats.frame;
-
-       uvc_trace(UVC_TRACE_STATS, "frame %u stats: %u/%u/%u packets, "
-                 "%u/%u/%u pts (%searly %sinitial), %u/%u scr, "
-                 "last pts/stc/sof %u/%u/%u\n",
-                 stream->sequence, frame->first_data,
-                 frame->nb_packets - frame->nb_empty, frame->nb_packets,
-                 frame->nb_pts_diffs, frame->last_pts_diff, frame->nb_pts,
-                 frame->has_early_pts ? "" : "!",
-                 frame->has_initial_pts ? "" : "!",
-                 frame->nb_scr_diffs, frame->nb_scr,
-                 frame->pts, frame->scr_stc, frame->scr_sof);
-
-       stream->stats.stream.nb_frames++;
-       stream->stats.stream.nb_packets += stream->stats.frame.nb_packets;
-       stream->stats.stream.nb_empty += stream->stats.frame.nb_empty;
-       stream->stats.stream.nb_errors += stream->stats.frame.nb_errors;
-       stream->stats.stream.nb_invalid += stream->stats.frame.nb_invalid;
-
-       if (frame->has_early_pts)
-               stream->stats.stream.nb_pts_early++;
-       if (frame->has_initial_pts)
-               stream->stats.stream.nb_pts_initial++;
-       if (frame->last_pts_diff <= frame->first_data)
-               stream->stats.stream.nb_pts_constant++;
-       if (frame->nb_scr >= frame->nb_packets - frame->nb_empty)
-               stream->stats.stream.nb_scr_count_ok++;
-       if (frame->nb_scr_diffs + 1 == frame->nb_scr)
-               stream->stats.stream.nb_scr_diffs_ok++;
-
-       memset(&stream->stats.frame, 0, sizeof(stream->stats.frame));
-}
-
-size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf,
-                           size_t size)
-{
-       unsigned int scr_sof_freq;
-       unsigned int duration;
-       struct timespec ts;
-       size_t count = 0;
-
-       ts.tv_sec = stream->stats.stream.stop_ts.tv_sec
-                 - stream->stats.stream.start_ts.tv_sec;
-       ts.tv_nsec = stream->stats.stream.stop_ts.tv_nsec
-                  - stream->stats.stream.start_ts.tv_nsec;
-       if (ts.tv_nsec < 0) {
-               ts.tv_sec--;
-               ts.tv_nsec += 1000000000;
-       }
-
-       /* Compute the SCR.SOF frequency estimate. At the nominal 1kHz SOF
-        * frequency this will not overflow before more than 1h.
-        */
-       duration = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
-       if (duration != 0)
-               scr_sof_freq = stream->stats.stream.scr_sof_count * 1000
-                            / duration;
-       else
-               scr_sof_freq = 0;
-
-       count += scnprintf(buf + count, size - count,
-                          "frames:  %u\npackets: %u\nempty:   %u\n"
-                          "errors:  %u\ninvalid: %u\n",
-                          stream->stats.stream.nb_frames,
-                          stream->stats.stream.nb_packets,
-                          stream->stats.stream.nb_empty,
-                          stream->stats.stream.nb_errors,
-                          stream->stats.stream.nb_invalid);
-       count += scnprintf(buf + count, size - count,
-                          "pts: %u early, %u initial, %u ok\n",
-                          stream->stats.stream.nb_pts_early,
-                          stream->stats.stream.nb_pts_initial,
-                          stream->stats.stream.nb_pts_constant);
-       count += scnprintf(buf + count, size - count,
-                          "scr: %u count ok, %u diff ok\n",
-                          stream->stats.stream.nb_scr_count_ok,
-                          stream->stats.stream.nb_scr_diffs_ok);
-       count += scnprintf(buf + count, size - count,
-                          "sof: %u <= sof <= %u, freq %u.%03u kHz\n",
-                          stream->stats.stream.min_sof,
-                          stream->stats.stream.max_sof,
-                          scr_sof_freq / 1000, scr_sof_freq % 1000);
-
-       return count;
-}
-
-static void uvc_video_stats_start(struct uvc_streaming *stream)
-{
-       memset(&stream->stats, 0, sizeof(stream->stats));
-       stream->stats.stream.min_sof = 2048;
-}
-
-static void uvc_video_stats_stop(struct uvc_streaming *stream)
-{
-       ktime_get_ts(&stream->stats.stream.stop_ts);
-}
-
-/* ------------------------------------------------------------------------
- * Video codecs
- */
-
-/* Video payload decoding is handled by uvc_video_decode_start(),
- * uvc_video_decode_data() and uvc_video_decode_end().
- *
- * uvc_video_decode_start is called with URB data at the start of a bulk or
- * isochronous payload. It processes header data and returns the header size
- * in bytes if successful. If an error occurs, it returns a negative error
- * code. The following error codes have special meanings.
- *
- * - EAGAIN informs the caller that the current video buffer should be marked
- *   as done, and that the function should be called again with the same data
- *   and a new video buffer. This is used when end of frame conditions can be
- *   reliably detected at the beginning of the next frame only.
- *
- * If an error other than -EAGAIN is returned, the caller will drop the current
- * payload. No call to uvc_video_decode_data and uvc_video_decode_end will be
- * made until the next payload. -ENODATA can be used to drop the current
- * payload if no other error code is appropriate.
- *
- * uvc_video_decode_data is called for every URB with URB data. It copies the
- * data to the video buffer.
- *
- * uvc_video_decode_end is called with header data at the end of a bulk or
- * isochronous payload. It performs any additional header data processing and
- * returns 0 or a negative error code if an error occurred. As header data have
- * already been processed by uvc_video_decode_start, this functions isn't
- * required to perform sanity checks a second time.
- *
- * For isochronous transfers where a payload is always transferred in a single
- * URB, the three functions will be called in a row.
- *
- * To let the decoder process header data and update its internal state even
- * when no video buffer is available, uvc_video_decode_start must be prepared
- * to be called with a NULL buf parameter. uvc_video_decode_data and
- * uvc_video_decode_end will never be called with a NULL buffer.
- */
-static int uvc_video_decode_start(struct uvc_streaming *stream,
-               struct uvc_buffer *buf, const __u8 *data, int len)
-{
-       __u8 fid;
-
-       /* Sanity checks:
-        * - packet must be at least 2 bytes long
-        * - bHeaderLength value must be at least 2 bytes (see above)
-        * - bHeaderLength value can't be larger than the packet size.
-        */
-       if (len < 2 || data[0] < 2 || data[0] > len) {
-               stream->stats.frame.nb_invalid++;
-               return -EINVAL;
-       }
-
-       fid = data[1] & UVC_STREAM_FID;
-
-       /* Increase the sequence number regardless of any buffer states, so
-        * that discontinuous sequence numbers always indicate lost frames.
-        */
-       if (stream->last_fid != fid) {
-               stream->sequence++;
-               if (stream->sequence)
-                       uvc_video_stats_update(stream);
-       }
-
-       uvc_video_clock_decode(stream, buf, data, len);
-       uvc_video_stats_decode(stream, data, len);
-
-       /* Store the payload FID bit and return immediately when the buffer is
-        * NULL.
-        */
-       if (buf == NULL) {
-               stream->last_fid = fid;
-               return -ENODATA;
-       }
-
-       /* Mark the buffer as bad if the error bit is set. */
-       if (data[1] & UVC_STREAM_ERR) {
-               uvc_trace(UVC_TRACE_FRAME, "Marking buffer as bad (error bit "
-                         "set).\n");
-               buf->error = 1;
-       }
-
-       /* Synchronize to the input stream by waiting for the FID bit to be
-        * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE.
-        * stream->last_fid is initialized to -1, so the first isochronous
-        * frame will always be in sync.
-        *
-        * If the device doesn't toggle the FID bit, invert stream->last_fid
-        * when the EOF bit is set to force synchronisation on the next packet.
-        */
-       if (buf->state != UVC_BUF_STATE_ACTIVE) {
-               struct timespec ts;
-
-               if (fid == stream->last_fid) {
-                       uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of "
-                               "sync).\n");
-                       if ((stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) &&
-                           (data[1] & UVC_STREAM_EOF))
-                               stream->last_fid ^= UVC_STREAM_FID;
-                       return -ENODATA;
-               }
-
-               if (uvc_clock_param == CLOCK_MONOTONIC)
-                       ktime_get_ts(&ts);
-               else
-                       ktime_get_real_ts(&ts);
-
-               buf->buf.v4l2_buf.sequence = stream->sequence;
-               buf->buf.v4l2_buf.timestamp.tv_sec = ts.tv_sec;
-               buf->buf.v4l2_buf.timestamp.tv_usec =
-                       ts.tv_nsec / NSEC_PER_USEC;
-
-               /* TODO: Handle PTS and SCR. */
-               buf->state = UVC_BUF_STATE_ACTIVE;
-       }
-
-       /* Mark the buffer as done if we're at the beginning of a new frame.
-        * End of frame detection is better implemented by checking the EOF
-        * bit (FID bit toggling is delayed by one frame compared to the EOF
-        * bit), but some devices don't set the bit at end of frame (and the
-        * last payload can be lost anyway). We thus must check if the FID has
-        * been toggled.
-        *
-        * stream->last_fid is initialized to -1, so the first isochronous
-        * frame will never trigger an end of frame detection.
-        *
-        * Empty buffers (bytesused == 0) don't trigger end of frame detection
-        * as it doesn't make sense to return an empty buffer. This also
-        * avoids detecting end of frame conditions at FID toggling if the
-        * previous payload had the EOF bit set.
-        */
-       if (fid != stream->last_fid && buf->bytesused != 0) {
-               uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit "
-                               "toggled).\n");
-               buf->state = UVC_BUF_STATE_READY;
-               return -EAGAIN;
-       }
-
-       stream->last_fid = fid;
-
-       return data[0];
-}
-
-static void uvc_video_decode_data(struct uvc_streaming *stream,
-               struct uvc_buffer *buf, const __u8 *data, int len)
-{
-       unsigned int maxlen, nbytes;
-       void *mem;
-
-       if (len <= 0)
-               return;
-
-       /* Copy the video data to the buffer. */
-       maxlen = buf->length - buf->bytesused;
-       mem = buf->mem + buf->bytesused;
-       nbytes = min((unsigned int)len, maxlen);
-       memcpy(mem, data, nbytes);
-       buf->bytesused += nbytes;
-
-       /* Complete the current frame if the buffer size was exceeded. */
-       if (len > maxlen) {
-               uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n");
-               buf->state = UVC_BUF_STATE_READY;
-       }
-}
-
-static void uvc_video_decode_end(struct uvc_streaming *stream,
-               struct uvc_buffer *buf, const __u8 *data, int len)
-{
-       /* Mark the buffer as done if the EOF marker is set. */
-       if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) {
-               uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n");
-               if (data[0] == len)
-                       uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n");
-               buf->state = UVC_BUF_STATE_READY;
-               if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID)
-                       stream->last_fid ^= UVC_STREAM_FID;
-       }
-}
-
-/* Video payload encoding is handled by uvc_video_encode_header() and
- * uvc_video_encode_data(). Only bulk transfers are currently supported.
- *
- * uvc_video_encode_header is called at the start of a payload. It adds header
- * data to the transfer buffer and returns the header size. As the only known
- * UVC output device transfers a whole frame in a single payload, the EOF bit
- * is always set in the header.
- *
- * uvc_video_encode_data is called for every URB and copies the data from the
- * video buffer to the transfer buffer.
- */
-static int uvc_video_encode_header(struct uvc_streaming *stream,
-               struct uvc_buffer *buf, __u8 *data, int len)
-{
-       data[0] = 2;    /* Header length */
-       data[1] = UVC_STREAM_EOH | UVC_STREAM_EOF
-               | (stream->last_fid & UVC_STREAM_FID);
-       return 2;
-}
-
-static int uvc_video_encode_data(struct uvc_streaming *stream,
-               struct uvc_buffer *buf, __u8 *data, int len)
-{
-       struct uvc_video_queue *queue = &stream->queue;
-       unsigned int nbytes;
-       void *mem;
-
-       /* Copy video data to the URB buffer. */
-       mem = buf->mem + queue->buf_used;
-       nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
-       nbytes = min(stream->bulk.max_payload_size - stream->bulk.payload_size,
-                       nbytes);
-       memcpy(data, mem, nbytes);
-
-       queue->buf_used += nbytes;
-
-       return nbytes;
-}
-
-/* ------------------------------------------------------------------------
- * URB handling
- */
-
-/*
- * Completion handler for video URBs.
- */
-static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream,
-       struct uvc_buffer *buf)
-{
-       u8 *mem;
-       int ret, i;
-
-       for (i = 0; i < urb->number_of_packets; ++i) {
-               if (urb->iso_frame_desc[i].status < 0) {
-                       uvc_trace(UVC_TRACE_FRAME, "USB isochronous frame "
-                               "lost (%d).\n", urb->iso_frame_desc[i].status);
-                       /* Mark the buffer as faulty. */
-                       if (buf != NULL)
-                               buf->error = 1;
-                       continue;
-               }
-
-               /* Decode the payload header. */
-               mem = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
-               do {
-                       ret = uvc_video_decode_start(stream, buf, mem,
-                               urb->iso_frame_desc[i].actual_length);
-                       if (ret == -EAGAIN)
-                               buf = uvc_queue_next_buffer(&stream->queue,
-                                                           buf);
-               } while (ret == -EAGAIN);
-
-               if (ret < 0)
-                       continue;
-
-               /* Decode the payload data. */
-               uvc_video_decode_data(stream, buf, mem + ret,
-                       urb->iso_frame_desc[i].actual_length - ret);
-
-               /* Process the header again. */
-               uvc_video_decode_end(stream, buf, mem,
-                       urb->iso_frame_desc[i].actual_length);
-
-               if (buf->state == UVC_BUF_STATE_READY) {
-                       if (buf->length != buf->bytesused &&
-                           !(stream->cur_format->flags &
-                             UVC_FMT_FLAG_COMPRESSED))
-                               buf->error = 1;
-
-                       buf = uvc_queue_next_buffer(&stream->queue, buf);
-               }
-       }
-}
-
-static void uvc_video_decode_bulk(struct urb *urb, struct uvc_streaming *stream,
-       struct uvc_buffer *buf)
-{
-       u8 *mem;
-       int len, ret;
-
-       /*
-        * Ignore ZLPs if they're not part of a frame, otherwise process them
-        * to trigger the end of payload detection.
-        */
-       if (urb->actual_length == 0 && stream->bulk.header_size == 0)
-               return;
-
-       mem = urb->transfer_buffer;
-       len = urb->actual_length;
-       stream->bulk.payload_size += len;
-
-       /* If the URB is the first of its payload, decode and save the
-        * header.
-        */
-       if (stream->bulk.header_size == 0 && !stream->bulk.skip_payload) {
-               do {
-                       ret = uvc_video_decode_start(stream, buf, mem, len);
-                       if (ret == -EAGAIN)
-                               buf = uvc_queue_next_buffer(&stream->queue,
-                                                           buf);
-               } while (ret == -EAGAIN);
-
-               /* If an error occurred skip the rest of the payload. */
-               if (ret < 0 || buf == NULL) {
-                       stream->bulk.skip_payload = 1;
-               } else {
-                       memcpy(stream->bulk.header, mem, ret);
-                       stream->bulk.header_size = ret;
-
-                       mem += ret;
-                       len -= ret;
-               }
-       }
-
-       /* The buffer queue might have been cancelled while a bulk transfer
-        * was in progress, so we can reach here with buf equal to NULL. Make
-        * sure buf is never dereferenced if NULL.
-        */
-
-       /* Process video data. */
-       if (!stream->bulk.skip_payload && buf != NULL)
-               uvc_video_decode_data(stream, buf, mem, len);
-
-       /* Detect the payload end by a URB smaller than the maximum size (or
-        * a payload size equal to the maximum) and process the header again.
-        */
-       if (urb->actual_length < urb->transfer_buffer_length ||
-           stream->bulk.payload_size >= stream->bulk.max_payload_size) {
-               if (!stream->bulk.skip_payload && buf != NULL) {
-                       uvc_video_decode_end(stream, buf, stream->bulk.header,
-                               stream->bulk.payload_size);
-                       if (buf->state == UVC_BUF_STATE_READY)
-                               buf = uvc_queue_next_buffer(&stream->queue,
-                                                           buf);
-               }
-
-               stream->bulk.header_size = 0;
-               stream->bulk.skip_payload = 0;
-               stream->bulk.payload_size = 0;
-       }
-}
-
-static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream,
-       struct uvc_buffer *buf)
-{
-       u8 *mem = urb->transfer_buffer;
-       int len = stream->urb_size, ret;
-
-       if (buf == NULL) {
-               urb->transfer_buffer_length = 0;
-               return;
-       }
-
-       /* If the URB is the first of its payload, add the header. */
-       if (stream->bulk.header_size == 0) {
-               ret = uvc_video_encode_header(stream, buf, mem, len);
-               stream->bulk.header_size = ret;
-               stream->bulk.payload_size += ret;
-               mem += ret;
-               len -= ret;
-       }
-
-       /* Process video data. */
-       ret = uvc_video_encode_data(stream, buf, mem, len);
-
-       stream->bulk.payload_size += ret;
-       len -= ret;
-
-       if (buf->bytesused == stream->queue.buf_used ||
-           stream->bulk.payload_size == stream->bulk.max_payload_size) {
-               if (buf->bytesused == stream->queue.buf_used) {
-                       stream->queue.buf_used = 0;
-                       buf->state = UVC_BUF_STATE_READY;
-                       buf->buf.v4l2_buf.sequence = ++stream->sequence;
-                       uvc_queue_next_buffer(&stream->queue, buf);
-                       stream->last_fid ^= UVC_STREAM_FID;
-               }
-
-               stream->bulk.header_size = 0;
-               stream->bulk.payload_size = 0;
-       }
-
-       urb->transfer_buffer_length = stream->urb_size - len;
-}
-
-static void uvc_video_complete(struct urb *urb)
-{
-       struct uvc_streaming *stream = urb->context;
-       struct uvc_video_queue *queue = &stream->queue;
-       struct uvc_buffer *buf = NULL;
-       unsigned long flags;
-       int ret;
-
-       switch (urb->status) {
-       case 0:
-               break;
-
-       default:
-               uvc_printk(KERN_WARNING, "Non-zero status (%d) in video "
-                       "completion handler.\n", urb->status);
-
-       case -ENOENT:           /* usb_kill_urb() called. */
-               if (stream->frozen)
-                       return;
-
-       case -ECONNRESET:       /* usb_unlink_urb() called. */
-       case -ESHUTDOWN:        /* The endpoint is being disabled. */
-               uvc_queue_cancel(queue, urb->status == -ESHUTDOWN);
-               return;
-       }
-
-       spin_lock_irqsave(&queue->irqlock, flags);
-       if (!list_empty(&queue->irqqueue))
-               buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
-                                      queue);
-       spin_unlock_irqrestore(&queue->irqlock, flags);
-
-       stream->decode(urb, stream, buf);
-
-       if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
-               uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n",
-                       ret);
-       }
-}
-
-/*
- * Free transfer buffers.
- */
-static void uvc_free_urb_buffers(struct uvc_streaming *stream)
-{
-       unsigned int i;
-
-       for (i = 0; i < UVC_URBS; ++i) {
-               if (stream->urb_buffer[i]) {
-#ifndef CONFIG_DMA_NONCOHERENT
-                       usb_free_coherent(stream->dev->udev, stream->urb_size,
-                               stream->urb_buffer[i], stream->urb_dma[i]);
-#else
-                       kfree(stream->urb_buffer[i]);
-#endif
-                       stream->urb_buffer[i] = NULL;
-               }
-       }
-
-       stream->urb_size = 0;
-}
-
-/*
- * Allocate transfer buffers. This function can be called with buffers
- * already allocated when resuming from suspend, in which case it will
- * return without touching the buffers.
- *
- * Limit the buffer size to UVC_MAX_PACKETS bulk/isochronous packets. If the
- * system is too low on memory try successively smaller numbers of packets
- * until allocation succeeds.
- *
- * Return the number of allocated packets on success or 0 when out of memory.
- */
-static int uvc_alloc_urb_buffers(struct uvc_streaming *stream,
-       unsigned int size, unsigned int psize, gfp_t gfp_flags)
-{
-       unsigned int npackets;
-       unsigned int i;
-
-       /* Buffers are already allocated, bail out. */
-       if (stream->urb_size)
-               return stream->urb_size / psize;
-
-       /* Compute the number of packets. Bulk endpoints might transfer UVC
-        * payloads across multiple URBs.
-        */
-       npackets = DIV_ROUND_UP(size, psize);
-       if (npackets > UVC_MAX_PACKETS)
-               npackets = UVC_MAX_PACKETS;
-
-       /* Retry allocations until one succeed. */
-       for (; npackets > 1; npackets /= 2) {
-               for (i = 0; i < UVC_URBS; ++i) {
-                       stream->urb_size = psize * npackets;
-#ifndef CONFIG_DMA_NONCOHERENT
-                       stream->urb_buffer[i] = usb_alloc_coherent(
-                               stream->dev->udev, stream->urb_size,
-                               gfp_flags | __GFP_NOWARN, &stream->urb_dma[i]);
-#else
-                       stream->urb_buffer[i] =
-                           kmalloc(stream->urb_size, gfp_flags | __GFP_NOWARN);
-#endif
-                       if (!stream->urb_buffer[i]) {
-                               uvc_free_urb_buffers(stream);
-                               break;
-                       }
-               }
-
-               if (i == UVC_URBS) {
-                       uvc_trace(UVC_TRACE_VIDEO, "Allocated %u URB buffers "
-                               "of %ux%u bytes each.\n", UVC_URBS, npackets,
-                               psize);
-                       return npackets;
-               }
-       }
-
-       uvc_trace(UVC_TRACE_VIDEO, "Failed to allocate URB buffers (%u bytes "
-               "per packet).\n", psize);
-       return 0;
-}
-
-/*
- * Uninitialize isochronous/bulk URBs and free transfer buffers.
- */
-static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
-{
-       struct urb *urb;
-       unsigned int i;
-
-       uvc_video_stats_stop(stream);
-
-       for (i = 0; i < UVC_URBS; ++i) {
-               urb = stream->urb[i];
-               if (urb == NULL)
-                       continue;
-
-               usb_kill_urb(urb);
-               usb_free_urb(urb);
-               stream->urb[i] = NULL;
-       }
-
-       if (free_buffers)
-               uvc_free_urb_buffers(stream);
-}
-
-/*
- * Compute the maximum number of bytes per interval for an endpoint.
- */
-static unsigned int uvc_endpoint_max_bpi(struct usb_device *dev,
-                                        struct usb_host_endpoint *ep)
-{
-       u16 psize;
-
-       switch (dev->speed) {
-       case USB_SPEED_SUPER:
-               return ep->ss_ep_comp.wBytesPerInterval;
-       case USB_SPEED_HIGH:
-               psize = usb_endpoint_maxp(&ep->desc);
-               return (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
-       default:
-               psize = usb_endpoint_maxp(&ep->desc);
-               return psize & 0x07ff;
-       }
-}
-
-/*
- * Initialize isochronous URBs and allocate transfer buffers. The packet size
- * is given by the endpoint.
- */
-static int uvc_init_video_isoc(struct uvc_streaming *stream,
-       struct usb_host_endpoint *ep, gfp_t gfp_flags)
-{
-       struct urb *urb;
-       unsigned int npackets, i, j;
-       u16 psize;
-       u32 size;
-
-       psize = uvc_endpoint_max_bpi(stream->dev->udev, ep);
-       size = stream->ctrl.dwMaxVideoFrameSize;
-
-       npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags);
-       if (npackets == 0)
-               return -ENOMEM;
-
-       size = npackets * psize;
-
-       for (i = 0; i < UVC_URBS; ++i) {
-               urb = usb_alloc_urb(npackets, gfp_flags);
-               if (urb == NULL) {
-                       uvc_uninit_video(stream, 1);
-                       return -ENOMEM;
-               }
-
-               urb->dev = stream->dev->udev;
-               urb->context = stream;
-               urb->pipe = usb_rcvisocpipe(stream->dev->udev,
-                               ep->desc.bEndpointAddress);
-#ifndef CONFIG_DMA_NONCOHERENT
-               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
-               urb->transfer_dma = stream->urb_dma[i];
-#else
-               urb->transfer_flags = URB_ISO_ASAP;
-#endif
-               urb->interval = ep->desc.bInterval;
-               urb->transfer_buffer = stream->urb_buffer[i];
-               urb->complete = uvc_video_complete;
-               urb->number_of_packets = npackets;
-               urb->transfer_buffer_length = size;
-
-               for (j = 0; j < npackets; ++j) {
-                       urb->iso_frame_desc[j].offset = j * psize;
-                       urb->iso_frame_desc[j].length = psize;
-               }
-
-               stream->urb[i] = urb;
-       }
-
-       return 0;
-}
-
-/*
- * Initialize bulk URBs and allocate transfer buffers. The packet size is
- * given by the endpoint.
- */
-static int uvc_init_video_bulk(struct uvc_streaming *stream,
-       struct usb_host_endpoint *ep, gfp_t gfp_flags)
-{
-       struct urb *urb;
-       unsigned int npackets, pipe, i;
-       u16 psize;
-       u32 size;
-
-       psize = usb_endpoint_maxp(&ep->desc) & 0x7ff;
-       size = stream->ctrl.dwMaxPayloadTransferSize;
-       stream->bulk.max_payload_size = size;
-
-       npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags);
-       if (npackets == 0)
-               return -ENOMEM;
-
-       size = npackets * psize;
-
-       if (usb_endpoint_dir_in(&ep->desc))
-               pipe = usb_rcvbulkpipe(stream->dev->udev,
-                                      ep->desc.bEndpointAddress);
-       else
-               pipe = usb_sndbulkpipe(stream->dev->udev,
-                                      ep->desc.bEndpointAddress);
-
-       if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-               size = 0;
-
-       for (i = 0; i < UVC_URBS; ++i) {
-               urb = usb_alloc_urb(0, gfp_flags);
-               if (urb == NULL) {
-                       uvc_uninit_video(stream, 1);
-                       return -ENOMEM;
-               }
-
-               usb_fill_bulk_urb(urb, stream->dev->udev, pipe,
-                       stream->urb_buffer[i], size, uvc_video_complete,
-                       stream);
-#ifndef CONFIG_DMA_NONCOHERENT
-               urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
-               urb->transfer_dma = stream->urb_dma[i];
-#endif
-
-               stream->urb[i] = urb;
-       }
-
-       return 0;
-}
-
-/*
- * Initialize isochronous/bulk URBs and allocate transfer buffers.
- */
-static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
-{
-       struct usb_interface *intf = stream->intf;
-       struct usb_host_endpoint *ep;
-       unsigned int i;
-       int ret;
-
-       stream->sequence = -1;
-       stream->last_fid = -1;
-       stream->bulk.header_size = 0;
-       stream->bulk.skip_payload = 0;
-       stream->bulk.payload_size = 0;
-
-       uvc_video_stats_start(stream);
-
-       if (intf->num_altsetting > 1) {
-               struct usb_host_endpoint *best_ep = NULL;
-               unsigned int best_psize = UINT_MAX;
-               unsigned int bandwidth;
-               unsigned int uninitialized_var(altsetting);
-               int intfnum = stream->intfnum;
-
-               /* Isochronous endpoint, select the alternate setting. */
-               bandwidth = stream->ctrl.dwMaxPayloadTransferSize;
-
-               if (bandwidth == 0) {
-                       uvc_trace(UVC_TRACE_VIDEO, "Device requested null "
-                               "bandwidth, defaulting to lowest.\n");
-                       bandwidth = 1;
-               } else {
-                       uvc_trace(UVC_TRACE_VIDEO, "Device requested %u "
-                               "B/frame bandwidth.\n", bandwidth);
-               }
-
-               for (i = 0; i < intf->num_altsetting; ++i) {
-                       struct usb_host_interface *alts;
-                       unsigned int psize;
-
-                       alts = &intf->altsetting[i];
-                       ep = uvc_find_endpoint(alts,
-                               stream->header.bEndpointAddress);
-                       if (ep == NULL)
-                               continue;
-
-                       /* Check if the bandwidth is high enough. */
-                       psize = uvc_endpoint_max_bpi(stream->dev->udev, ep);
-                       if (psize >= bandwidth && psize <= best_psize) {
-                               altsetting = alts->desc.bAlternateSetting;
-                               best_psize = psize;
-                               best_ep = ep;
-                       }
-               }
-
-               if (best_ep == NULL) {
-                       uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting "
-                               "for requested bandwidth.\n");
-                       return -EIO;
-               }
-
-               uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u "
-                       "(%u B/frame bandwidth).\n", altsetting, best_psize);
-
-               ret = usb_set_interface(stream->dev->udev, intfnum, altsetting);
-               if (ret < 0)
-                       return ret;
-
-               ret = uvc_init_video_isoc(stream, best_ep, gfp_flags);
-       } else {
-               /* Bulk endpoint, proceed to URB initialization. */
-               ep = uvc_find_endpoint(&intf->altsetting[0],
-                               stream->header.bEndpointAddress);
-               if (ep == NULL)
-                       return -EIO;
-
-               ret = uvc_init_video_bulk(stream, ep, gfp_flags);
-       }
-
-       if (ret < 0)
-               return ret;
-
-       /* Submit the URBs. */
-       for (i = 0; i < UVC_URBS; ++i) {
-               ret = usb_submit_urb(stream->urb[i], gfp_flags);
-               if (ret < 0) {
-                       uvc_printk(KERN_ERR, "Failed to submit URB %u "
-                                       "(%d).\n", i, ret);
-                       uvc_uninit_video(stream, 1);
-                       return ret;
-               }
-       }
-
-       return 0;
-}
-
-/* --------------------------------------------------------------------------
- * Suspend/resume
- */
-
-/*
- * Stop streaming without disabling the video queue.
- *
- * To let userspace applications resume without trouble, we must not touch the
- * video buffers in any way. We mark the device as frozen to make sure the URB
- * completion handler won't try to cancel the queue when we kill the URBs.
- */
-int uvc_video_suspend(struct uvc_streaming *stream)
-{
-       if (!uvc_queue_streaming(&stream->queue))
-               return 0;
-
-       stream->frozen = 1;
-       uvc_uninit_video(stream, 0);
-       usb_set_interface(stream->dev->udev, stream->intfnum, 0);
-       return 0;
-}
-
-/*
- * Reconfigure the video interface and restart streaming if it was enabled
- * before suspend.
- *
- * If an error occurs, disable the video queue. This will wake all pending
- * buffers, making sure userspace applications are notified of the problem
- * instead of waiting forever.
- */
-int uvc_video_resume(struct uvc_streaming *stream, int reset)
-{
-       int ret;
-
-       /* If the bus has been reset on resume, set the alternate setting to 0.
-        * This should be the default value, but some devices crash or otherwise
-        * misbehave if they don't receive a SET_INTERFACE request before any
-        * other video control request.
-        */
-       if (reset)
-               usb_set_interface(stream->dev->udev, stream->intfnum, 0);
-
-       stream->frozen = 0;
-
-       uvc_video_clock_reset(stream);
-
-       ret = uvc_commit_video(stream, &stream->ctrl);
-       if (ret < 0) {
-               uvc_queue_enable(&stream->queue, 0);
-               return ret;
-       }
-
-       if (!uvc_queue_streaming(&stream->queue))
-               return 0;
-
-       ret = uvc_init_video(stream, GFP_NOIO);
-       if (ret < 0)
-               uvc_queue_enable(&stream->queue, 0);
-
-       return ret;
-}
-
-/* ------------------------------------------------------------------------
- * Video device
- */
-
-/*
- * Initialize the UVC video device by switching to alternate setting 0 and
- * retrieve the default format.
- *
- * Some cameras (namely the Fuji Finepix) set the format and frame
- * indexes to zero. The UVC standard doesn't clearly make this a spec
- * violation, so try to silently fix the values if possible.
- *
- * This function is called before registering the device with V4L.
- */
-int uvc_video_init(struct uvc_streaming *stream)
-{
-       struct uvc_streaming_control *probe = &stream->ctrl;
-       struct uvc_format *format = NULL;
-       struct uvc_frame *frame = NULL;
-       unsigned int i;
-       int ret;
-
-       if (stream->nformats == 0) {
-               uvc_printk(KERN_INFO, "No supported video formats found.\n");
-               return -EINVAL;
-       }
-
-       atomic_set(&stream->active, 0);
-
-       /* Initialize the video buffers queue. */
-       uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
-
-       /* Alternate setting 0 should be the default, yet the XBox Live Vision
-        * Cam (and possibly other devices) crash or otherwise misbehave if
-        * they don't receive a SET_INTERFACE request before any other video
-        * control request.
-        */
-       usb_set_interface(stream->dev->udev, stream->intfnum, 0);
-
-       /* Set the streaming probe control with default streaming parameters
-        * retrieved from the device. Webcams that don't suport GET_DEF
-        * requests on the probe control will just keep their current streaming
-        * parameters.
-        */
-       if (uvc_get_video_ctrl(stream, probe, 1, UVC_GET_DEF) == 0)
-               uvc_set_video_ctrl(stream, probe, 1);
-
-       /* Initialize the streaming parameters with the probe control current
-        * value. This makes sure SET_CUR requests on the streaming commit
-        * control will always use values retrieved from a successful GET_CUR
-        * request on the probe control, as required by the UVC specification.
-        */
-       ret = uvc_get_video_ctrl(stream, probe, 1, UVC_GET_CUR);
-       if (ret < 0)
-               return ret;
-
-       /* Check if the default format descriptor exists. Use the first
-        * available format otherwise.
-        */
-       for (i = stream->nformats; i > 0; --i) {
-               format = &stream->format[i-1];
-               if (format->index == probe->bFormatIndex)
-                       break;
-       }
-
-       if (format->nframes == 0) {
-               uvc_printk(KERN_INFO, "No frame descriptor found for the "
-                       "default format.\n");
-               return -EINVAL;
-       }
-
-       /* Zero bFrameIndex might be correct. Stream-based formats (including
-        * MPEG-2 TS and DV) do not support frames but have a dummy frame
-        * descriptor with bFrameIndex set to zero. If the default frame
-        * descriptor is not found, use the first available frame.
-        */
-       for (i = format->nframes; i > 0; --i) {
-               frame = &format->frame[i-1];
-               if (frame->bFrameIndex == probe->bFrameIndex)
-                       break;
-       }
-
-       probe->bFormatIndex = format->index;
-       probe->bFrameIndex = frame->bFrameIndex;
-
-       stream->cur_format = format;
-       stream->cur_frame = frame;
-
-       /* Select the video decoding function */
-       if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               if (stream->dev->quirks & UVC_QUIRK_BUILTIN_ISIGHT)
-                       stream->decode = uvc_video_decode_isight;
-               else if (stream->intf->num_altsetting > 1)
-                       stream->decode = uvc_video_decode_isoc;
-               else
-                       stream->decode = uvc_video_decode_bulk;
-       } else {
-               if (stream->intf->num_altsetting == 1)
-                       stream->decode = uvc_video_encode_bulk;
-               else {
-                       uvc_printk(KERN_INFO, "Isochronous endpoints are not "
-                               "supported for video output devices.\n");
-                       return -EINVAL;
-               }
-       }
-
-       return 0;
-}
-
-/*
- * Enable or disable the video stream.
- */
-int uvc_video_enable(struct uvc_streaming *stream, int enable)
-{
-       int ret;
-
-       if (!enable) {
-               uvc_uninit_video(stream, 1);
-               usb_set_interface(stream->dev->udev, stream->intfnum, 0);
-               uvc_queue_enable(&stream->queue, 0);
-               uvc_video_clock_cleanup(stream);
-               return 0;
-       }
-
-       ret = uvc_video_clock_init(stream);
-       if (ret < 0)
-               return ret;
-
-       ret = uvc_queue_enable(&stream->queue, 1);
-       if (ret < 0)
-               goto error_queue;
-
-       /* Commit the streaming parameters. */
-       ret = uvc_commit_video(stream, &stream->ctrl);
-       if (ret < 0)
-               goto error_commit;
-
-       ret = uvc_init_video(stream, GFP_KERNEL);
-       if (ret < 0)
-               goto error_video;
-
-       return 0;
-
-error_video:
-       usb_set_interface(stream->dev->udev, stream->intfnum, 0);
-error_commit:
-       uvc_queue_enable(&stream->queue, 0);
-error_queue:
-       uvc_video_clock_cleanup(stream);
-
-       return ret;
-}
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
deleted file mode 100644 (file)
index 3764040..0000000
+++ /dev/null
@@ -1,718 +0,0 @@
-#ifndef _USB_VIDEO_H_
-#define _USB_VIDEO_H_
-
-#ifndef __KERNEL__
-#error "The uvcvideo.h header is deprecated, use linux/uvcvideo.h instead."
-#endif /* __KERNEL__ */
-
-#include <linux/kernel.h>
-#include <linux/poll.h>
-#include <linux/usb.h>
-#include <linux/usb/video.h>
-#include <linux/uvcvideo.h>
-#include <linux/videodev2.h>
-#include <media/media-device.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-fh.h>
-#include <media/videobuf2-core.h>
-
-/* --------------------------------------------------------------------------
- * UVC constants
- */
-
-#define UVC_TERM_INPUT                 0x0000
-#define UVC_TERM_OUTPUT                        0x8000
-#define UVC_TERM_DIRECTION(term)       ((term)->type & 0x8000)
-
-#define UVC_ENTITY_TYPE(entity)                ((entity)->type & 0x7fff)
-#define UVC_ENTITY_IS_UNIT(entity)     (((entity)->type & 0xff00) == 0)
-#define UVC_ENTITY_IS_TERM(entity)     (((entity)->type & 0xff00) != 0)
-#define UVC_ENTITY_IS_ITERM(entity) \
-       (UVC_ENTITY_IS_TERM(entity) && \
-       ((entity)->type & 0x8000) == UVC_TERM_INPUT)
-#define UVC_ENTITY_IS_OTERM(entity) \
-       (UVC_ENTITY_IS_TERM(entity) && \
-       ((entity)->type & 0x8000) == UVC_TERM_OUTPUT)
-
-
-/* ------------------------------------------------------------------------
- * GUIDs
- */
-#define UVC_GUID_UVC_CAMERA \
-       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}
-#define UVC_GUID_UVC_OUTPUT \
-       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}
-#define UVC_GUID_UVC_MEDIA_TRANSPORT_INPUT \
-       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
-#define UVC_GUID_UVC_PROCESSING \
-       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}
-#define UVC_GUID_UVC_SELECTOR \
-       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02}
-
-#define UVC_GUID_FORMAT_MJPEG \
-       { 'M',  'J',  'P',  'G', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
-#define UVC_GUID_FORMAT_YUY2 \
-       { 'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
-#define UVC_GUID_FORMAT_YUY2_ISIGHT \
-       { 'Y',  'U',  'Y',  '2', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0x9b, 0x71}
-#define UVC_GUID_FORMAT_NV12 \
-       { 'N',  'V',  '1',  '2', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
-#define UVC_GUID_FORMAT_YV12 \
-       { 'Y',  'V',  '1',  '2', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
-#define UVC_GUID_FORMAT_I420 \
-       { 'I',  '4',  '2',  '0', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
-#define UVC_GUID_FORMAT_UYVY \
-       { 'U',  'Y',  'V',  'Y', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
-#define UVC_GUID_FORMAT_Y800 \
-       { 'Y',  '8',  '0',  '0', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
-#define UVC_GUID_FORMAT_Y8 \
-       { 'Y',  '8',  ' ',  ' ', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
-#define UVC_GUID_FORMAT_Y10 \
-       { 'Y',  '1',  '0',  ' ', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
-#define UVC_GUID_FORMAT_Y12 \
-       { 'Y',  '1',  '2',  ' ', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
-#define UVC_GUID_FORMAT_Y16 \
-       { 'Y',  '1',  '6',  ' ', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
-#define UVC_GUID_FORMAT_BY8 \
-       { 'B',  'Y',  '8',  ' ', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
-#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_M420 \
-       { 'M',  '4',  '2',  '0', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
-
-#define UVC_GUID_FORMAT_H264 \
-       { 'H',  '2',  '6',  '4', 0x00, 0x00, 0x10, 0x00, \
-        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
-
-/* ------------------------------------------------------------------------
- * Driver specific constants.
- */
-
-#define DRIVER_VERSION         "1.1.1"
-
-/* Number of isochronous URBs. */
-#define UVC_URBS               5
-/* Maximum number of packets per URB. */
-#define UVC_MAX_PACKETS                32
-/* Maximum number of video buffers. */
-#define UVC_MAX_VIDEO_BUFFERS  32
-/* Maximum status buffer size in bytes of interrupt URB. */
-#define UVC_MAX_STATUS_SIZE    16
-
-#define UVC_CTRL_CONTROL_TIMEOUT       300
-#define UVC_CTRL_STREAMING_TIMEOUT     5000
-
-/* Maximum allowed number of control mappings per device */
-#define UVC_MAX_CONTROL_MAPPINGS       1024
-#define UVC_MAX_CONTROL_MENU_ENTRIES   32
-
-/* Devices quirks */
-#define UVC_QUIRK_STATUS_INTERVAL      0x00000001
-#define UVC_QUIRK_PROBE_MINMAX         0x00000002
-#define UVC_QUIRK_PROBE_EXTRAFIELDS    0x00000004
-#define UVC_QUIRK_BUILTIN_ISIGHT       0x00000008
-#define UVC_QUIRK_STREAM_NO_FID                0x00000010
-#define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020
-#define UVC_QUIRK_FIX_BANDWIDTH                0x00000080
-#define UVC_QUIRK_PROBE_DEF            0x00000100
-#define UVC_QUIRK_RESTRICT_FRAME_RATE  0x00000200
-
-/* Format flags */
-#define UVC_FMT_FLAG_COMPRESSED                0x00000001
-#define UVC_FMT_FLAG_STREAM            0x00000002
-
-/* ------------------------------------------------------------------------
- * Structures.
- */
-
-struct uvc_device;
-
-/* TODO: Put the most frequently accessed fields at the beginning of
- * structures to maximize cache efficiency.
- */
-struct uvc_control_info {
-       struct list_head mappings;
-
-       __u8 entity[16];
-       __u8 index;     /* Bit index in bmControls */
-       __u8 selector;
-
-       __u16 size;
-       __u32 flags;
-};
-
-struct uvc_control_mapping {
-       struct list_head list;
-       struct list_head ev_subs;
-
-       __u32 id;
-       __u8 name[32];
-       __u8 entity[16];
-       __u8 selector;
-
-       __u8 size;
-       __u8 offset;
-       enum v4l2_ctrl_type v4l2_type;
-       __u32 data_type;
-
-       struct uvc_menu_info *menu_info;
-       __u32 menu_count;
-
-       __u32 master_id;
-       __s32 master_manual;
-       __u32 slave_ids[2];
-
-       __s32 (*get) (struct uvc_control_mapping *mapping, __u8 query,
-                     const __u8 *data);
-       void (*set) (struct uvc_control_mapping *mapping, __s32 value,
-                    __u8 *data);
-};
-
-struct uvc_control {
-       struct uvc_entity *entity;
-       struct uvc_control_info info;
-
-       __u8 index;     /* Used to match the uvc_control entry with a
-                          uvc_control_info. */
-       __u8 dirty:1,
-            loaded:1,
-            modified:1,
-            cached:1,
-            initialized:1;
-
-       __u8 *uvc_data;
-};
-
-struct uvc_format_desc {
-       char *name;
-       __u8 guid[16];
-       __u32 fcc;
-};
-
-/* The term 'entity' refers to both UVC units and UVC terminals.
- *
- * The type field is either the terminal type (wTerminalType in the terminal
- * descriptor), or the unit type (bDescriptorSubtype in the unit descriptor).
- * As the bDescriptorSubtype field is one byte long, the type value will
- * always have a null MSB for units. All terminal types defined by the UVC
- * specification have a non-null MSB, so it is safe to use the MSB to
- * differentiate between units and terminals as long as the descriptor parsing
- * code makes sure terminal types have a non-null MSB.
- *
- * For terminals, the type's most significant bit stores the terminal
- * direction (either UVC_TERM_INPUT or UVC_TERM_OUTPUT). The type field should
- * always be accessed with the UVC_ENTITY_* macros and never directly.
- */
-
-struct uvc_entity {
-       struct list_head list;          /* Entity as part of a UVC device. */
-       struct list_head chain;         /* Entity as part of a video device
-                                        * chain. */
-       __u8 id;
-       __u16 type;
-       char name[64];
-
-       /* Media controller-related fields. */
-       struct video_device *vdev;
-       struct v4l2_subdev subdev;
-       unsigned int num_pads;
-       unsigned int num_links;
-       struct media_pad *pads;
-
-       union {
-               struct {
-                       __u16 wObjectiveFocalLengthMin;
-                       __u16 wObjectiveFocalLengthMax;
-                       __u16 wOcularFocalLength;
-                       __u8  bControlSize;
-                       __u8  *bmControls;
-               } camera;
-
-               struct {
-                       __u8  bControlSize;
-                       __u8  *bmControls;
-                       __u8  bTransportModeSize;
-                       __u8  *bmTransportModes;
-               } media;
-
-               struct {
-               } output;
-
-               struct {
-                       __u16 wMaxMultiplier;
-                       __u8  bControlSize;
-                       __u8  *bmControls;
-                       __u8  bmVideoStandards;
-               } processing;
-
-               struct {
-               } selector;
-
-               struct {
-                       __u8  guidExtensionCode[16];
-                       __u8  bNumControls;
-                       __u8  bControlSize;
-                       __u8  *bmControls;
-                       __u8  *bmControlsType;
-               } extension;
-       };
-
-       __u8 bNrInPins;
-       __u8 *baSourceID;
-
-       unsigned int ncontrols;
-       struct uvc_control *controls;
-};
-
-struct uvc_frame {
-       __u8  bFrameIndex;
-       __u8  bmCapabilities;
-       __u16 wWidth;
-       __u16 wHeight;
-       __u32 dwMinBitRate;
-       __u32 dwMaxBitRate;
-       __u32 dwMaxVideoFrameBufferSize;
-       __u8  bFrameIntervalType;
-       __u32 dwDefaultFrameInterval;
-       __u32 *dwFrameInterval;
-};
-
-struct uvc_format {
-       __u8 type;
-       __u8 index;
-       __u8 bpp;
-       __u8 colorspace;
-       __u32 fcc;
-       __u32 flags;
-
-       char name[32];
-
-       unsigned int nframes;
-       struct uvc_frame *frame;
-};
-
-struct uvc_streaming_header {
-       __u8 bNumFormats;
-       __u8 bEndpointAddress;
-       __u8 bTerminalLink;
-       __u8 bControlSize;
-       __u8 *bmaControls;
-       /* The following fields are used by input headers only. */
-       __u8 bmInfo;
-       __u8 bStillCaptureMethod;
-       __u8 bTriggerSupport;
-       __u8 bTriggerUsage;
-};
-
-enum uvc_buffer_state {
-       UVC_BUF_STATE_IDLE      = 0,
-       UVC_BUF_STATE_QUEUED    = 1,
-       UVC_BUF_STATE_ACTIVE    = 2,
-       UVC_BUF_STATE_READY     = 3,
-       UVC_BUF_STATE_DONE      = 4,
-       UVC_BUF_STATE_ERROR     = 5,
-};
-
-struct uvc_buffer {
-       struct vb2_buffer buf;
-       struct list_head queue;
-
-       enum uvc_buffer_state state;
-       unsigned int error;
-
-       void *mem;
-       unsigned int length;
-       unsigned int bytesused;
-
-       u32 pts;
-};
-
-#define UVC_QUEUE_DISCONNECTED         (1 << 0)
-#define UVC_QUEUE_DROP_CORRUPTED       (1 << 1)
-
-struct uvc_video_queue {
-       struct vb2_queue queue;
-       struct mutex mutex;                     /* Protects queue */
-
-       unsigned int flags;
-       unsigned int buf_used;
-
-       spinlock_t irqlock;                     /* Protects irqqueue */
-       struct list_head irqqueue;
-};
-
-struct uvc_video_chain {
-       struct uvc_device *dev;
-       struct list_head list;
-
-       struct list_head entities;              /* All entities */
-       struct uvc_entity *processing;          /* Processing unit */
-       struct uvc_entity *selector;            /* Selector unit */
-
-       struct mutex ctrl_mutex;                /* Protects ctrl.info */
-};
-
-struct uvc_stats_frame {
-       unsigned int size;              /* Number of bytes captured */
-       unsigned int first_data;        /* Index of the first non-empty packet */
-
-       unsigned int nb_packets;        /* Number of packets */
-       unsigned int nb_empty;          /* Number of empty packets */
-       unsigned int nb_invalid;        /* Number of packets with an invalid header */
-       unsigned int nb_errors;         /* Number of packets with the error bit set */
-
-       unsigned int nb_pts;            /* Number of packets with a PTS timestamp */
-       unsigned int nb_pts_diffs;      /* Number of PTS differences inside a frame */
-       unsigned int last_pts_diff;     /* Index of the last PTS difference */
-       bool has_initial_pts;           /* Whether the first non-empty packet has a PTS */
-       bool has_early_pts;             /* Whether a PTS is present before the first non-empty packet */
-       u32 pts;                        /* PTS of the last packet */
-
-       unsigned int nb_scr;            /* Number of packets with a SCR timestamp */
-       unsigned int nb_scr_diffs;      /* Number of SCR.STC differences inside a frame */
-       u16 scr_sof;                    /* SCR.SOF of the last packet */
-       u32 scr_stc;                    /* SCR.STC of the last packet */
-};
-
-struct uvc_stats_stream {
-       struct timespec start_ts;       /* Stream start timestamp */
-       struct timespec stop_ts;        /* Stream stop timestamp */
-
-       unsigned int nb_frames;         /* Number of frames */
-
-       unsigned int nb_packets;        /* Number of packets */
-       unsigned int nb_empty;          /* Number of empty packets */
-       unsigned int nb_invalid;        /* Number of packets with an invalid header */
-       unsigned int nb_errors;         /* Number of packets with the error bit set */
-
-       unsigned int nb_pts_constant;   /* Number of frames with constant PTS */
-       unsigned int nb_pts_early;      /* Number of frames with early PTS */
-       unsigned int nb_pts_initial;    /* Number of frames with initial PTS */
-
-       unsigned int nb_scr_count_ok;   /* Number of frames with at least one SCR per non empty packet */
-       unsigned int nb_scr_diffs_ok;   /* Number of frames with varying SCR.STC */
-       unsigned int scr_sof_count;     /* STC.SOF counter accumulated since stream start */
-       unsigned int scr_sof;           /* STC.SOF of the last packet */
-       unsigned int min_sof;           /* Minimum STC.SOF value */
-       unsigned int max_sof;           /* Maximum STC.SOF value */
-};
-
-struct uvc_streaming {
-       struct list_head list;
-       struct uvc_device *dev;
-       struct video_device *vdev;
-       struct uvc_video_chain *chain;
-       atomic_t active;
-
-       struct usb_interface *intf;
-       int intfnum;
-       __u16 maxpsize;
-
-       struct uvc_streaming_header header;
-       enum v4l2_buf_type type;
-
-       unsigned int nformats;
-       struct uvc_format *format;
-
-       struct uvc_streaming_control ctrl;
-       struct uvc_format *cur_format;
-       struct uvc_frame *cur_frame;
-       /* Protect access to ctrl, cur_format, cur_frame and hardware video
-        * probe control.
-        */
-       struct mutex mutex;
-
-       /* Buffers queue. */
-       unsigned int frozen : 1;
-       struct uvc_video_queue queue;
-       void (*decode) (struct urb *urb, struct uvc_streaming *video,
-                       struct uvc_buffer *buf);
-
-       /* Context data used by the bulk completion handler. */
-       struct {
-               __u8 header[256];
-               unsigned int header_size;
-               int skip_payload;
-               __u32 payload_size;
-               __u32 max_payload_size;
-       } bulk;
-
-       struct urb *urb[UVC_URBS];
-       char *urb_buffer[UVC_URBS];
-       dma_addr_t urb_dma[UVC_URBS];
-       unsigned int urb_size;
-
-       __u32 sequence;
-       __u8 last_fid;
-
-       /* debugfs */
-       struct dentry *debugfs_dir;
-       struct {
-               struct uvc_stats_frame frame;
-               struct uvc_stats_stream stream;
-       } stats;
-
-       /* Timestamps support. */
-       struct uvc_clock {
-               struct uvc_clock_sample {
-                       u32 dev_stc;
-                       u16 dev_sof;
-                       struct timespec host_ts;
-                       u16 host_sof;
-               } *samples;
-
-               unsigned int head;
-               unsigned int count;
-               unsigned int size;
-
-               u16 last_sof;
-               u16 sof_offset;
-
-               spinlock_t lock;
-       } clock;
-};
-
-enum uvc_device_state {
-       UVC_DEV_DISCONNECTED = 1,
-};
-
-struct uvc_device {
-       struct usb_device *udev;
-       struct usb_interface *intf;
-       unsigned long warnings;
-       __u32 quirks;
-       int intfnum;
-       char name[32];
-
-       enum uvc_device_state state;
-       atomic_t users;
-       atomic_t nmappings;
-
-       /* Video control interface */
-#ifdef CONFIG_MEDIA_CONTROLLER
-       struct media_device mdev;
-#endif
-       struct v4l2_device vdev;
-       __u16 uvc_version;
-       __u32 clock_frequency;
-
-       struct list_head entities;
-       struct list_head chains;
-
-       /* Video Streaming interfaces */
-       struct list_head streams;
-       atomic_t nstreams;
-
-       /* Status Interrupt Endpoint */
-       struct usb_host_endpoint *int_ep;
-       struct urb *int_urb;
-       __u8 *status;
-       struct input_dev *input;
-       char input_phys[64];
-};
-
-enum uvc_handle_state {
-       UVC_HANDLE_PASSIVE      = 0,
-       UVC_HANDLE_ACTIVE       = 1,
-};
-
-struct uvc_fh {
-       struct v4l2_fh vfh;
-       struct uvc_video_chain *chain;
-       struct uvc_streaming *stream;
-       enum uvc_handle_state state;
-};
-
-struct uvc_driver {
-       struct usb_driver driver;
-};
-
-/* ------------------------------------------------------------------------
- * Debugging, printing and logging
- */
-
-#define UVC_TRACE_PROBE                (1 << 0)
-#define UVC_TRACE_DESCR                (1 << 1)
-#define UVC_TRACE_CONTROL      (1 << 2)
-#define UVC_TRACE_FORMAT       (1 << 3)
-#define UVC_TRACE_CAPTURE      (1 << 4)
-#define UVC_TRACE_CALLS                (1 << 5)
-#define UVC_TRACE_IOCTL                (1 << 6)
-#define UVC_TRACE_FRAME                (1 << 7)
-#define UVC_TRACE_SUSPEND      (1 << 8)
-#define UVC_TRACE_STATUS       (1 << 9)
-#define UVC_TRACE_VIDEO                (1 << 10)
-#define UVC_TRACE_STATS                (1 << 11)
-#define UVC_TRACE_CLOCK                (1 << 12)
-
-#define UVC_WARN_MINMAX                0
-#define UVC_WARN_PROBE_DEF     1
-#define UVC_WARN_XU_GET_RES    2
-
-extern unsigned int uvc_clock_param;
-extern unsigned int uvc_no_drop_param;
-extern unsigned int uvc_trace_param;
-extern unsigned int uvc_timeout_param;
-
-#define uvc_trace(flag, msg...) \
-       do { \
-               if (uvc_trace_param & flag) \
-                       printk(KERN_DEBUG "uvcvideo: " msg); \
-       } while (0)
-
-#define uvc_warn_once(dev, warn, msg...) \
-       do { \
-               if (!test_and_set_bit(warn, &dev->warnings)) \
-                       printk(KERN_INFO "uvcvideo: " msg); \
-       } while (0)
-
-#define uvc_printk(level, msg...) \
-       printk(level "uvcvideo: " msg)
-
-/* --------------------------------------------------------------------------
- * Internal functions.
- */
-
-/* Core driver */
-extern struct uvc_driver uvc_driver;
-
-extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id);
-
-/* Video buffers queue management. */
-extern void uvc_queue_init(struct uvc_video_queue *queue,
-               enum v4l2_buf_type type, int drop_corrupted);
-extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
-               struct v4l2_requestbuffers *rb);
-extern void uvc_free_buffers(struct uvc_video_queue *queue);
-extern int uvc_query_buffer(struct uvc_video_queue *queue,
-               struct v4l2_buffer *v4l2_buf);
-extern int uvc_queue_buffer(struct uvc_video_queue *queue,
-               struct v4l2_buffer *v4l2_buf);
-extern int uvc_dequeue_buffer(struct uvc_video_queue *queue,
-               struct v4l2_buffer *v4l2_buf, int nonblocking);
-extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
-extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
-extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
-               struct uvc_buffer *buf);
-extern int uvc_queue_mmap(struct uvc_video_queue *queue,
-               struct vm_area_struct *vma);
-extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
-               struct file *file, poll_table *wait);
-#ifndef CONFIG_MMU
-extern unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
-               unsigned long pgoff);
-#endif
-extern int uvc_queue_allocated(struct uvc_video_queue *queue);
-static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
-{
-       return vb2_is_streaming(&queue->queue);
-}
-
-/* V4L2 interface */
-extern const struct v4l2_file_operations uvc_fops;
-
-/* Media controller */
-extern int uvc_mc_register_entities(struct uvc_video_chain *chain);
-extern void uvc_mc_cleanup_entity(struct uvc_entity *entity);
-
-/* Video */
-extern int uvc_video_init(struct uvc_streaming *stream);
-extern int uvc_video_suspend(struct uvc_streaming *stream);
-extern int uvc_video_resume(struct uvc_streaming *stream, int reset);
-extern int uvc_video_enable(struct uvc_streaming *stream, int enable);
-extern int uvc_probe_video(struct uvc_streaming *stream,
-               struct uvc_streaming_control *probe);
-extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
-               __u8 intfnum, __u8 cs, void *data, __u16 size);
-void uvc_video_clock_update(struct uvc_streaming *stream,
-                           struct v4l2_buffer *v4l2_buf,
-                           struct uvc_buffer *buf);
-
-/* Status */
-extern int uvc_status_init(struct uvc_device *dev);
-extern void uvc_status_cleanup(struct uvc_device *dev);
-extern int uvc_status_start(struct uvc_device *dev);
-extern void uvc_status_stop(struct uvc_device *dev);
-extern int uvc_status_suspend(struct uvc_device *dev);
-extern int uvc_status_resume(struct uvc_device *dev);
-
-/* Controls */
-extern const struct v4l2_subscribed_event_ops uvc_ctrl_sub_ev_ops;
-
-extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
-               struct v4l2_queryctrl *v4l2_ctrl);
-extern int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
-               struct v4l2_querymenu *query_menu);
-
-extern int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
-               const struct uvc_control_mapping *mapping);
-extern int uvc_ctrl_init_device(struct uvc_device *dev);
-extern void uvc_ctrl_cleanup_device(struct uvc_device *dev);
-extern int uvc_ctrl_resume_device(struct uvc_device *dev);
-
-extern int uvc_ctrl_begin(struct uvc_video_chain *chain);
-extern int __uvc_ctrl_commit(struct uvc_fh *handle, int rollback,
-                       const struct v4l2_ext_control *xctrls,
-                       unsigned int xctrls_count);
-static inline int uvc_ctrl_commit(struct uvc_fh *handle,
-                       const struct v4l2_ext_control *xctrls,
-                       unsigned int xctrls_count)
-{
-       return __uvc_ctrl_commit(handle, 0, xctrls, xctrls_count);
-}
-static inline int uvc_ctrl_rollback(struct uvc_fh *handle)
-{
-       return __uvc_ctrl_commit(handle, 1, NULL, 0);
-}
-
-extern int uvc_ctrl_get(struct uvc_video_chain *chain,
-               struct v4l2_ext_control *xctrl);
-extern int uvc_ctrl_set(struct uvc_video_chain *chain,
-               struct v4l2_ext_control *xctrl);
-
-extern int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
-               struct uvc_xu_control_query *xqry);
-
-/* Utility functions */
-extern void uvc_simplify_fraction(uint32_t *numerator, uint32_t *denominator,
-               unsigned int n_terms, unsigned int threshold);
-extern uint32_t uvc_fraction_to_interval(uint32_t numerator,
-               uint32_t denominator);
-extern struct usb_host_endpoint *uvc_find_endpoint(
-               struct usb_host_interface *alts, __u8 epaddr);
-
-/* Quirks support */
-void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream,
-               struct uvc_buffer *buf);
-
-/* debugfs and statistics */
-int uvc_debugfs_init(void);
-void uvc_debugfs_cleanup(void);
-int uvc_debugfs_init_stream(struct uvc_streaming *stream);
-void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream);
-
-size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf,
-                           size_t size);
-
-#endif